From d5c9f1c70dc5c4ebbfb4459f2bf6ef4aa3578c1c Mon Sep 17 00:00:00 2001 From: Prakash Dhavali Date: Sun, 8 Nov 2015 19:04:44 -0800 Subject: qcacld-3.0: Initial snapshot of ihelium wlan driver qcacld-3.0: Initial snapshot of ihelium wlan driver This is SU Release 5.0.0.139. Change-Id: Icf598ca97da74f84bea607e4e902d1889806f507 --- Android.mk | 106 + Kbuild | 1331 ++ Kconfig | 110 + Makefile | 20 + README.txt | 1 + config/WCNSS_qcom_cfg.ini | 591 + core/bmi/inc/bmi.h | 60 + core/bmi/inc/ol_fw.h | 64 + core/bmi/inc/ol_if_athvar.h | 87 + core/bmi/src/bmi.c | 470 + core/bmi/src/bmi_1.c | 321 + core/bmi/src/bmi_2.c | 452 + core/bmi/src/i_ar6320v2_regtable.h | 607 + core/bmi/src/i_bmi.h | 149 + core/bmi/src/ol_fw.c | 1637 ++ core/cdf/inc/cdf_atomic.h | 140 + core/cdf/inc/cdf_defer.h | 138 + core/cdf/inc/cdf_event.h | 154 + core/cdf/inc/cdf_list.h | 110 + core/cdf/inc/cdf_lock.h | 296 + core/cdf/inc/cdf_mc_timer.h | 253 + core/cdf/inc/cdf_memory.h | 225 + core/cdf/inc/cdf_nbuf.h | 1053 + core/cdf/inc/cdf_net_types.h | 117 + core/cdf/inc/cdf_softirq_timer.h | 118 + core/cdf/inc/cdf_status.h | 111 + core/cdf/inc/cdf_threads.h | 83 + core/cdf/inc/cdf_time.h | 184 + core/cdf/inc/cdf_trace.h | 283 + core/cdf/inc/cdf_types.h | 492 + core/cdf/inc/cdf_util.h | 325 + core/cdf/inc/osdep.h | 300 + core/cdf/src/cdf_defer.c | 50 + core/cdf/src/cdf_event.c | 270 + core/cdf/src/cdf_list.c | 225 + core/cdf/src/cdf_lock.c | 491 + core/cdf/src/cdf_mc_timer.c | 800 + core/cdf/src/cdf_memory.c | 631 + core/cdf/src/cdf_nbuf.c | 1017 + core/cdf/src/cdf_threads.c | 107 + core/cdf/src/cdf_trace.c | 1018 + core/cdf/src/i_cdf_atomic.h | 78 + core/cdf/src/i_cdf_defer.h | 106 + core/cdf/src/i_cdf_event.h | 62 + core/cdf/src/i_cdf_lock.h | 255 + core/cdf/src/i_cdf_mc_timer.h | 61 + core/cdf/src/i_cdf_nbuf.h | 1092 + core/cdf/src/i_cdf_softirq_timer.h | 152 + core/cdf/src/i_cdf_time.h | 217 + core/cdf/src/i_cdf_trace.h | 145 + core/cdf/src/i_cdf_types.h | 234 + core/cdf/src/i_cdf_util.h | 107 + core/cds/inc/cds_api.h | 124 + core/cds/inc/cds_concurrency.h | 732 + core/cds/inc/cds_crypto.h | 183 + core/cds/inc/cds_get_bin.h | 75 + core/cds/inc/cds_ieee80211_common.h | 2105 ++ core/cds/inc/cds_ieee80211_defines.h | 1374 ++ core/cds/inc/cds_if_upperproto.h | 238 + core/cds/inc/cds_mq.h | 165 + core/cds/inc/cds_pack_align.h | 111 + core/cds/inc/cds_packet.h | 185 + core/cds/inc/cds_queue.h | 33 + core/cds/inc/cds_reg_service.h | 310 + core/cds/inc/cds_regdomain.h | 1098 + core/cds/inc/cds_regdomain_common.h | 2218 ++ core/cds/inc/cds_sched.h | 451 + core/cds/inc/cds_utils.h | 189 + core/cds/src/cds_api.c | 2085 ++ core/cds/src/cds_concurrency.c | 6823 ++++++ core/cds/src/cds_get_bin.c | 166 + core/cds/src/cds_ieee80211_common_i.h | 545 + core/cds/src/cds_mq.c | 215 + core/cds/src/cds_packet.c | 348 + core/cds/src/cds_reg_service.c | 1439 ++ core/cds/src/cds_regdomain.c | 699 + core/cds/src/cds_sched.c | 1270 ++ core/cds/src/cds_utils.c | 1135 + core/cds/src/i_cds_packet.h | 76 + core/cds/src/queue.h | 571 + core/dp/htt/htt.c | 562 + core/dp/htt/htt_fw_stats.c | 1155 + core/dp/htt/htt_h2t.c | 904 + core/dp/htt/htt_internal.h | 500 + core/dp/htt/htt_rx.c | 2444 +++ core/dp/htt/htt_t2h.c | 935 + core/dp/htt/htt_tx.c | 864 + core/dp/htt/htt_types.h | 373 + core/dp/htt/rx_desc.h | 533 + core/dp/ol/inc/ol_cfg.h | 543 + core/dp/ol/inc/ol_ctrl_addba_api.h | 43 + core/dp/ol/inc/ol_ctrl_api.h | 44 + core/dp/ol/inc/ol_defines.h | 47 + core/dp/ol/inc/ol_htt_api.h | 353 + core/dp/ol/inc/ol_htt_rx_api.h | 863 + core/dp/ol/inc/ol_htt_tx_api.h | 969 + core/dp/ol/inc/ol_osif_api.h | 42 + core/dp/ol/inc/ol_params.h | 103 + core/dp/ol/inc/ol_txrx_api.h | 113 + core/dp/ol/inc/ol_txrx_ctrl_api.h | 1312 ++ core/dp/ol/inc/ol_txrx_dbg.h | 203 + core/dp/ol/inc/ol_txrx_htt_api.h | 579 + core/dp/ol/inc/ol_txrx_osif_api.h | 283 + core/dp/ol/inc/ol_txrx_stats.h | 133 + core/dp/ol/inc/ol_vowext_dbg_defs.h | 66 + core/dp/txrx/ipv6_defs.h | 107 + core/dp/txrx/ol_cfg.c | 323 + core/dp/txrx/ol_ctrl_txrx_api.h | 190 + core/dp/txrx/ol_osif_txrx_api.h | 51 + core/dp/txrx/ol_rx.c | 1493 ++ core/dp/txrx/ol_rx.h | 67 + core/dp/txrx/ol_rx_defrag.c | 1059 + core/dp/txrx/ol_rx_defrag.h | 197 + core/dp/txrx/ol_rx_fwd.c | 232 + core/dp/txrx/ol_rx_fwd.h | 75 + core/dp/txrx/ol_rx_pn.c | 348 + core/dp/txrx/ol_rx_pn.h | 105 + core/dp/txrx/ol_rx_reorder.c | 827 + core/dp/txrx/ol_rx_reorder.h | 93 + core/dp/txrx/ol_rx_reorder_timeout.c | 219 + core/dp/txrx/ol_rx_reorder_timeout.h | 66 + core/dp/txrx/ol_tx.c | 1364 ++ core/dp/txrx/ol_tx.h | 82 + core/dp/txrx/ol_tx_desc.c | 621 + core/dp/txrx/ol_tx_desc.h | 171 + core/dp/txrx/ol_tx_queue.c | 428 + core/dp/txrx/ol_tx_queue.h | 92 + core/dp/txrx/ol_tx_send.c | 969 + core/dp/txrx/ol_tx_send.h | 86 + core/dp/txrx/ol_txrx.c | 3173 +++ core/dp/txrx/ol_txrx.h | 70 + core/dp/txrx/ol_txrx_encap.c | 593 + core/dp/txrx/ol_txrx_encap.h | 120 + core/dp/txrx/ol_txrx_event.c | 228 + core/dp/txrx/ol_txrx_flow_control.c | 707 + core/dp/txrx/ol_txrx_internal.h | 737 + core/dp/txrx/ol_txrx_peer_find.c | 494 + core/dp/txrx/ol_txrx_peer_find.h | 116 + core/dp/txrx/ol_txrx_types.h | 1018 + core/dp/txrx/txrx.h | 235 + core/dp/txrx/wdi_event.h | 92 + core/dp/txrx/wdi_event_api.h | 95 + core/hdd/inc/qc_sap_ioctl.h | 248 + core/hdd/inc/wlan_hdd_assoc.h | 251 + core/hdd/inc/wlan_hdd_cfg.h | 3351 +++ core/hdd/inc/wlan_hdd_conc_ut.h | 79 + core/hdd/inc/wlan_hdd_debugfs.h | 44 + core/hdd/inc/wlan_hdd_driver_ops.h | 39 + core/hdd/inc/wlan_hdd_ether.h | 89 + core/hdd/inc/wlan_hdd_ftm.h | 68 + core/hdd/inc/wlan_hdd_host_offload.h | 60 + core/hdd/inc/wlan_hdd_includes.h | 69 + core/hdd/inc/wlan_hdd_ipa.h | 151 + core/hdd/inc/wlan_hdd_lro.h | 145 + core/hdd/inc/wlan_hdd_main.h | 1529 ++ core/hdd/inc/wlan_hdd_memdump.h | 92 + core/hdd/inc/wlan_hdd_mib.h | 190 + core/hdd/inc/wlan_hdd_misc.h | 39 + core/hdd/inc/wlan_hdd_nan.h | 59 + core/hdd/inc/wlan_hdd_napi.h | 82 + core/hdd/inc/wlan_hdd_oemdata.h | 172 + core/hdd/inc/wlan_hdd_p2p.h | 202 + core/hdd/inc/wlan_hdd_power.h | 190 + core/hdd/inc/wlan_hdd_softap_tx_rx.h | 94 + core/hdd/inc/wlan_hdd_tdls.h | 633 + core/hdd/inc/wlan_hdd_trace.h | 138 + core/hdd/inc/wlan_hdd_tx_rx.h | 154 + core/hdd/inc/wlan_hdd_wext.h | 385 + core/hdd/inc/wlan_hdd_wmm.h | 404 + core/hdd/inc/wlan_hdd_wowl.h | 183 + core/hdd/src/wlan_hdd_assoc.c | 5426 +++++ core/hdd/src/wlan_hdd_cfg.c | 6612 ++++++ core/hdd/src/wlan_hdd_cfg80211.c | 10706 +++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 2279 ++ core/hdd/src/wlan_hdd_conc_ut.c | 865 + core/hdd/src/wlan_hdd_debugfs.c | 648 + core/hdd/src/wlan_hdd_driver_ops.c | 642 + core/hdd/src/wlan_hdd_ext_scan.c | 4605 ++++ core/hdd/src/wlan_hdd_ext_scan.h | 127 + core/hdd/src/wlan_hdd_ftm.c | 1061 + core/hdd/src/wlan_hdd_green_ap.c | 449 + core/hdd/src/wlan_hdd_green_ap.h | 54 + core/hdd/src/wlan_hdd_hostapd.c | 8421 +++++++ core/hdd/src/wlan_hdd_hostapd.h | 128 + core/hdd/src/wlan_hdd_ioctl.c | 6314 ++++++ core/hdd/src/wlan_hdd_ioctl.h | 39 + core/hdd/src/wlan_hdd_ipa.c | 3935 ++++ core/hdd/src/wlan_hdd_lro.c | 663 + core/hdd/src/wlan_hdd_main.c | 6731 ++++++ core/hdd/src/wlan_hdd_memdump.c | 647 + core/hdd/src/wlan_hdd_nan.c | 194 + core/hdd/src/wlan_hdd_napi.c | 262 + core/hdd/src/wlan_hdd_ocb.c | 2112 ++ core/hdd/src/wlan_hdd_ocb.h | 292 + core/hdd/src/wlan_hdd_oemdata.c | 847 + core/hdd/src/wlan_hdd_p2p.c | 2626 +++ core/hdd/src/wlan_hdd_power.c | 2346 ++ core/hdd/src/wlan_hdd_scan.c | 2429 +++ core/hdd/src/wlan_hdd_scan.h | 75 + core/hdd/src/wlan_hdd_softap_tx_rx.c | 943 + core/hdd/src/wlan_hdd_stats.c | 2511 +++ core/hdd/src/wlan_hdd_stats.h | 186 + core/hdd/src/wlan_hdd_tdls.c | 4705 ++++ core/hdd/src/wlan_hdd_trace.c | 71 + core/hdd/src/wlan_hdd_tx_rx.c | 1065 + core/hdd/src/wlan_hdd_wext.c | 10708 +++++++++ core/hdd/src/wlan_hdd_wmm.c | 2590 +++ core/hdd/src/wlan_hdd_wowl.c | 600 + core/hif/inc/hif.h | 650 + core/hif/inc/hif_napi.h | 153 + core/hif/inc/regtable.h | 33 + core/hif/inc/regtable_ce.h | 259 + core/hif/inc/regtable_pcie.h | 1030 + core/hif/src/adrastea_reg_def.h | 2352 ++ core/hif/src/ar6320def.h | 796 + core/hif/src/ar6320v2def.h | 815 + core/hif/src/ar9888def.h | 590 + core/hif/src/ath_procfs.c | 201 + core/hif/src/ce/ce_api.h | 471 + core/hif/src/ce/ce_assignment.h | 291 + core/hif/src/ce/ce_bmi.c | 293 + core/hif/src/ce/ce_bmi.h | 45 + core/hif/src/ce/ce_diag.c | 456 + core/hif/src/ce/ce_internal.h | 314 + core/hif/src/ce/ce_main.c | 2593 +++ core/hif/src/ce/ce_main.h | 168 + core/hif/src/ce/ce_reg.h | 478 + core/hif/src/ce/ce_service.c | 1678 ++ core/hif/src/ce/ce_tasklet.c | 404 + core/hif/src/ce/ce_tasklet.h | 35 + core/hif/src/hif_debug.h | 42 + core/hif/src/hif_hw_version.h | 93 + core/hif/src/hif_io32.h | 39 + core/hif/src/hif_main.c | 894 + core/hif/src/hif_main.h | 142 + core/hif/src/hif_napi.c | 444 + core/hif/src/icnss_stub/icnss_stub.c | 342 + core/hif/src/icnss_stub/icnss_stub.h | 134 + core/hif/src/mp_dev.c | 310 + core/hif/src/mp_dev.h | 36 + core/hif/src/pcie/cnss_stub.h | 40 + core/hif/src/pcie/hif_io32_pci.h | 306 + core/hif/src/pcie/if_pci.c | 2239 ++ core/hif/src/pcie/if_pci.h | 115 + core/hif/src/pcie/if_pci_internal.h | 110 + core/hif/src/qca6180def.h | 1008 + core/hif/src/regtable.c | 91 + core/hif/src/snoc/hif_io32_snoc.h | 236 + core/hif/src/snoc/if_snoc.c | 294 + core/htc/dl_list.h | 208 + core/htc/htc.c | 816 + core/htc/htc_api.h | 712 + core/htc/htc_debug.h | 50 + core/htc/htc_internal.h | 310 + core/htc/htc_packet.h | 266 + core/htc/htc_recv.c | 743 + core/htc/htc_send.c | 1850 ++ core/htc/htc_services.c | 368 + core/mac/inc/ani_global.h | 1064 + core/mac/inc/ani_system_defs.h | 216 + core/mac/inc/mac_init_api.h | 50 + core/mac/inc/mac_trace.h | 72 + core/mac/inc/qwlan_version.h | 49 + core/mac/inc/sir_api.h | 5350 +++++ core/mac/inc/sir_mac_prop_exts.h | 119 + core/mac/inc/sir_mac_prot_def.h | 2192 ++ core/mac/inc/sir_types.h | 236 + core/mac/inc/wni_api.h | 539 + core/mac/inc/wni_cfg.h | 1572 ++ core/mac/src/cfg/cfgUtil/cfg.txt | 4474 ++++ core/mac/src/cfg/cfgUtil/dot11f.frms | 3611 +++ core/mac/src/cfg/cfg_api.c | 948 + core/mac/src/cfg/cfg_debug.c | 57 + core/mac/src/cfg/cfg_debug.h | 51 + core/mac/src/cfg/cfg_def.h | 72 + core/mac/src/cfg/cfg_param_name.c | 326 + core/mac/src/cfg/cfg_priv.h | 90 + core/mac/src/cfg/cfg_proc_msg.c | 2607 +++ core/mac/src/cfg/cfg_send_msg.c | 140 + core/mac/src/dph/dph_hash_table.c | 459 + core/mac/src/dph/dph_hash_table.h | 102 + core/mac/src/include/cfg_api.h | 131 + core/mac/src/include/cfg_global.h | 95 + core/mac/src/include/dot11f.h | 8920 ++++++++ core/mac/src/include/dph_global.h | 258 + core/mac/src/include/parser_api.h | 965 + core/mac/src/include/sir_common.h | 55 + core/mac/src/include/sir_debug.h | 109 + core/mac/src/include/sir_params.h | 758 + core/mac/src/include/sys_global.h | 52 + core/mac/src/include/utils_api.h | 669 + core/mac/src/include/utils_global.h | 56 + core/mac/src/pe/include/lim_admit_control.h | 106 + core/mac/src/pe/include/lim_api.h | 251 + core/mac/src/pe/include/lim_ft.h | 80 + core/mac/src/pe/include/lim_ft_defs.h | 131 + core/mac/src/pe/include/lim_global.h | 670 + core/mac/src/pe/include/lim_session.h | 612 + core/mac/src/pe/include/lim_trace.h | 99 + core/mac/src/pe/include/rrm_api.h | 104 + core/mac/src/pe/include/rrm_global.h | 228 + core/mac/src/pe/include/sch_api.h | 112 + core/mac/src/pe/include/sch_global.h | 176 + core/mac/src/pe/include/wmm_apsd.h | 50 + core/mac/src/pe/lim/lim_admit_control.c | 1140 + core/mac/src/pe/lim/lim_aid_mgmt.c | 194 + core/mac/src/pe/lim/lim_api.c | 2202 ++ core/mac/src/pe/lim/lim_assoc_utils.c | 5132 +++++ core/mac/src/pe/lim/lim_assoc_utils.h | 212 + core/mac/src/pe/lim/lim_debug.c | 57 + core/mac/src/pe/lim/lim_debug.h | 61 + core/mac/src/pe/lim/lim_ft.c | 2027 ++ core/mac/src/pe/lim/lim_ibss_peer_mgmt.c | 1833 ++ core/mac/src/pe/lim/lim_ibss_peer_mgmt.h | 60 + core/mac/src/pe/lim/lim_link_monitoring_algo.c | 561 + core/mac/src/pe/lim/lim_p2p.c | 794 + core/mac/src/pe/lim/lim_process_action_frame.c | 2093 ++ core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 1921 ++ core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 1109 + core/mac/src/pe/lim/lim_process_auth_frame.c | 1929 ++ core/mac/src/pe/lim/lim_process_beacon_frame.c | 250 + core/mac/src/pe/lim/lim_process_cfg_updates.c | 648 + core/mac/src/pe/lim/lim_process_deauth_frame.c | 596 + core/mac/src/pe/lim/lim_process_disassoc_frame.c | 390 + core/mac/src/pe/lim/lim_process_message_queue.c | 2098 ++ core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 2868 +++ core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 4200 ++++ core/mac/src/pe/lim/lim_process_probe_req_frame.c | 693 + core/mac/src/pe/lim/lim_process_probe_rsp_frame.c | 362 + core/mac/src/pe/lim/lim_process_sme_req_messages.c | 5690 +++++ core/mac/src/pe/lim/lim_process_tdls.c | 3267 +++ core/mac/src/pe/lim/lim_prop_exts_utils.c | 296 + core/mac/src/pe/lim/lim_prop_exts_utils.h | 64 + core/mac/src/pe/lim/lim_scan_result_utils.c | 421 + core/mac/src/pe/lim/lim_scan_result_utils.h | 59 + core/mac/src/pe/lim/lim_security_utils.c | 1075 + core/mac/src/pe/lim/lim_security_utils.h | 95 + core/mac/src/pe/lim/lim_send_management_frames.c | 5130 +++++ core/mac/src/pe/lim/lim_send_messages.c | 854 + core/mac/src/pe/lim/lim_send_messages.h | 126 + core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 2370 ++ core/mac/src/pe/lim/lim_send_sme_rsp_messages.h | 134 + core/mac/src/pe/lim/lim_ser_des_utils.c | 78 + core/mac/src/pe/lim/lim_ser_des_utils.h | 98 + core/mac/src/pe/lim/lim_session.c | 767 + core/mac/src/pe/lim/lim_session_utils.c | 145 + core/mac/src/pe/lim/lim_session_utils.h | 36 + core/mac/src/pe/lim/lim_sme_req_utils.c | 925 + core/mac/src/pe/lim/lim_sme_req_utils.h | 59 + core/mac/src/pe/lim/lim_sta_hash_api.c | 76 + core/mac/src/pe/lim/lim_sta_hash_api.h | 50 + core/mac/src/pe/lim/lim_timer_utils.c | 1357 ++ core/mac/src/pe/lim/lim_timer_utils.h | 102 + core/mac/src/pe/lim/lim_trace.c | 483 + core/mac/src/pe/lim/lim_types.h | 867 + core/mac/src/pe/lim/lim_utils.c | 7145 ++++++ core/mac/src/pe/lim/lim_utils.h | 591 + core/mac/src/pe/rrm/rrm_api.c | 1495 ++ core/mac/src/pe/sch/sch_api.c | 625 + core/mac/src/pe/sch/sch_beacon_gen.c | 930 + core/mac/src/pe/sch/sch_beacon_process.c | 1011 + core/mac/src/pe/sch/sch_debug.c | 61 + core/mac/src/pe/sch/sch_debug.h | 53 + core/mac/src/pe/sch/sch_message.c | 574 + core/mac/src/pe/sch/sch_sys_params.h | 107 + core/mac/src/sys/common/inc/wlan_qct_sys.h | 194 + core/mac/src/sys/common/src/wlan_qct_sys.c | 371 + .../src/sys/legacy/src/platform/inc/sys_wrapper.h | 149 + .../src/sys/legacy/src/platform/src/sys_wrapper.c | 502 + core/mac/src/sys/legacy/src/system/inc/sys_debug.h | 47 + core/mac/src/sys/legacy/src/system/inc/sys_def.h | 168 + .../src/sys/legacy/src/system/inc/sys_entry_func.h | 53 + .../src/sys/legacy/src/system/inc/sys_startup.h | 53 + .../src/sys/legacy/src/system/src/mac_init_api.c | 194 + .../src/sys/legacy/src/system/src/sys_entry_func.c | 247 + core/mac/src/sys/legacy/src/utils/inc/dot11fdefs.h | 99 + .../src/sys/legacy/src/utils/inc/utils_parser.h | 98 + core/mac/src/sys/legacy/src/utils/src/dot11f.c | 21682 +++++++++++++++++++ core/mac/src/sys/legacy/src/utils/src/log_api.c | 200 + core/mac/src/sys/legacy/src/utils/src/mac_trace.c | 759 + core/mac/src/sys/legacy/src/utils/src/parser_api.c | 5654 +++++ core/mac/src/sys/legacy/src/utils/src/utils_api.c | 91 + .../src/sys/legacy/src/utils/src/utils_parser.c | 827 + core/sap/dfs/inc/ath_dfs_structs.h | 257 + core/sap/dfs/inc/dfs.h | 824 + core/sap/dfs/inc/dfs_interface.h | 171 + core/sap/dfs/inc/radar_filters.h | 142 + core/sap/dfs/sources | 62 + core/sap/dfs/src/dfs.c | 993 + core/sap/dfs/src/dfs_bindetects.c | 485 + core/sap/dfs/src/dfs_debug.c | 160 + core/sap/dfs/src/dfs_fcc_bin5.c | 874 + core/sap/dfs/src/dfs_init.c | 403 + core/sap/dfs/src/dfs_ioctl.h | 117 + core/sap/dfs/src/dfs_ioctl_private.h | 100 + core/sap/dfs/src/dfs_misc.c | 276 + core/sap/dfs/src/dfs_nol.c | 405 + core/sap/dfs/src/dfs_phyerr.h | 50 + core/sap/dfs/src/dfs_phyerr_tlv.c | 726 + core/sap/dfs/src/dfs_phyerr_tlv.h | 206 + core/sap/dfs/src/dfs_process_phyerr.c | 855 + core/sap/dfs/src/dfs_process_radarevent.c | 799 + core/sap/dfs/src/dfs_staggered.c | 308 + core/sap/inc/sap_api.h | 920 + core/sap/src/sap_api_link_cntl.c | 1209 ++ core/sap/src/sap_ch_select.c | 2030 ++ core/sap/src/sap_ch_select.h | 187 + core/sap/src/sap_fsm.c | 4754 ++++ core/sap/src/sap_fsm_ext.h | 61 + core/sap/src/sap_internal.h | 430 + core/sap/src/sap_module.c | 3272 +++ core/sme/inc/csr_api.h | 1644 ++ core/sme/inc/csr_internal.h | 1403 ++ core/sme/inc/csr_link_list.h | 110 + core/sme/inc/csr_neighbor_roam.h | 311 + core/sme/inc/csr_support.h | 378 + core/sme/inc/nan_api.h | 51 + core/sme/inc/oem_data_api.h | 87 + core/sme/inc/oem_data_internal.h | 68 + core/sme/inc/p2p_api.h | 113 + core/sme/inc/sme_api.h | 1027 + core/sme/inc/sme_ft_api.h | 107 + core/sme/inc/sme_inside.h | 287 + core/sme/inc/sme_internal.h | 223 + core/sme/inc/sme_power_save.h | 152 + core/sme/inc/sme_power_save_api.h | 97 + core/sme/inc/sme_qos_api.h | 257 + core/sme/inc/sme_qos_internal.h | 138 + core/sme/inc/sme_rrm_api.h | 67 + core/sme/inc/sme_rrm_internal.h | 108 + core/sme/inc/sme_trace.h | 137 + core/sme/inc/sms_debug.h | 48 + core/sme/inc/wlan_ps_wow_diag.h | 136 + core/sme/src/common/sme_api.c | 14610 +++++++++++++ core/sme/src/common/sme_ft_api.c | 634 + core/sme/src/common/sme_power_save.c | 1214 ++ core/sme/src/common/sme_trace.c | 209 + core/sme/src/csr/csr_api_roam.c | 18860 ++++++++++++++++ core/sme/src/csr/csr_api_scan.c | 6941 ++++++ core/sme/src/csr/csr_cmd_process.c | 189 + core/sme/src/csr/csr_inside_api.h | 1070 + core/sme/src/csr/csr_link_list.c | 571 + core/sme/src/csr/csr_neighbor_roam.c | 3541 +++ core/sme/src/csr/csr_tdls_process.c | 820 + core/sme/src/csr/csr_util.c | 5626 +++++ core/sme/src/nan/nan_api.c | 145 + core/sme/src/oem_data/oem_data_api.c | 391 + core/sme/src/p2p/p2p_api.c | 419 + core/sme/src/qos/sme_qos.c | 7834 +++++++ core/sme/src/rrm/sme_rrm.c | 1566 ++ core/utils/epping/inc/epping_internal.h | 197 + core/utils/epping/inc/epping_main.h | 55 + core/utils/epping/src/epping_helper.c | 213 + core/utils/epping/src/epping_main.c | 303 + core/utils/epping/src/epping_rx.c | 161 + core/utils/epping/src/epping_tx.c | 385 + core/utils/epping/src/epping_txrx.c | 457 + core/utils/fwlog/dbglog_host.c | 4464 ++++ core/utils/fwlog/dbglog_host.h | 127 + .../utils/host_diag_log/inc/host_diag_core_event.h | 362 + core/utils/host_diag_log/inc/host_diag_core_log.h | 380 + .../utils/host_diag_log/inc/host_diag_event_defs.h | 61 + core/utils/host_diag_log/inc/log_codes.h | 2078 ++ core/utils/host_diag_log/src/host_diag_log.c | 264 + .../host_diag_log/src/i_host_diag_core_event.h | 102 + .../utils/host_diag_log/src/i_host_diag_core_log.h | 132 + core/utils/logging/inc/wlan_logging_sock_svc.h | 61 + core/utils/logging/src/wlan_logging_sock_svc.c | 817 + core/utils/nlink/inc/wlan_nlink_common.h | 139 + core/utils/nlink/inc/wlan_nlink_srv.h | 60 + core/utils/nlink/src/wlan_nlink_srv.c | 309 + core/utils/pktlog/include/pktlog.h | 39 + core/utils/pktlog/include/pktlog_ac.h | 163 + core/utils/pktlog/include/pktlog_ac_api.h | 115 + core/utils/pktlog/include/pktlog_ac_i.h | 67 + core/utils/pktlog/linux_ac.c | 1183 + core/utils/pktlog/pktlog_ac.c | 449 + core/utils/pktlog/pktlog_internal.c | 680 + core/utils/ptt/inc/wlan_ptt_sock_svc.h | 118 + core/utils/ptt/src/wlan_ptt_sock_svc.c | 229 + core/wma/inc/wma.h | 1981 ++ core/wma/inc/wma_api.h | 220 + core/wma/inc/wma_dfs_interface.h | 252 + core/wma/inc/wma_if.h | 1429 ++ core/wma/inc/wma_internal.h | 1097 + core/wma/inc/wma_tgt_cfg.h | 167 + core/wma/inc/wma_types.h | 679 + core/wma/src/wlan_qct_wma_legacy.c | 157 + core/wma/src/wma_data.c | 3084 +++ core/wma/src/wma_dev_if.c | 4470 ++++ core/wma/src/wma_dfs_interface.c | 245 + core/wma/src/wma_features.c | 7171 ++++++ core/wma/src/wma_main.c | 5382 +++++ core/wma/src/wma_mgmt.c | 3208 +++ core/wma/src/wma_ocb.c | 1119 + core/wma/src/wma_ocb.h | 68 + core/wma/src/wma_power.c | 2250 ++ core/wma/src/wma_scan_roam.c | 6886 ++++++ core/wma/src/wma_utils.c | 3526 +++ core/wma/src/wma_utils_ut.c | 82 + core/wmi/wmi_tlv_helper.c | 1190 + core/wmi/wmi_tlv_platform.c | 58 + core/wmi/wmi_unified.c | 1222 ++ core/wmi/wmi_unified_api.h | 160 + core/wmi/wmi_unified_priv.h | 95 + core/wmi/wmi_version_whitelist.c | 38 + target/inc/a_osapi.h | 71 + target/inc/a_usb_defs.h | 97 + target/inc/apb_athr_wlan_map.h | 59 + target/inc/athdefs.h | 83 + target/inc/athendpack.h | 35 + target/inc/bin_sig.h | 45 + target/inc/bmi_msg.h | 364 + target/inc/cepci.h | 125 + target/inc/dbglog.h | 168 + target/inc/dbglog_id.h | 1586 ++ target/inc/efuse_reg.h | 154 + target/inc/enet.h | 148 + target/inc/epping_test.h | 124 + target/inc/htc.h | 405 + target/inc/htc_services.h | 95 + target/inc/htt.h | 7034 ++++++ target/inc/htt_common.h | 120 + target/inc/htt_isoc.h | 1058 + target/inc/ip_prot.h | 58 + target/inc/ipv4.h | 55 + target/inc/ol_fw_tx_dbg.h | 184 + target/inc/rtc_soc_reg.h | 1966 ++ target/inc/targaddrs.h | 673 + target/inc/targcfg.h | 53 + target/inc/wal_rx_desc.h | 127 + target/inc/wlan_defs.h | 800 + target/inc/wlan_module_ids.h | 103 + target/inc/wlan_tgt_def_config.h | 259 + target/inc/wmi.h | 188 + target/inc/wmi_services.h | 162 + target/inc/wmi_tlv_defs.h | 2996 +++ target/inc/wmi_tlv_helper.h | 160 + target/inc/wmi_unified.h | 12299 +++++++++++ target/inc/wmi_version.h | 80 + target/inc/wmix.h | 182 + uapi/linux/a_debug.h | 202 + uapi/linux/a_types.h | 52 + uapi/linux/athstartpack.h | 48 + uapi/linux/dbglog_common.h | 142 + uapi/linux/debug_linux.h | 50 + uapi/linux/osapi_linux.h | 293 + uapi/linux/pktlog_ac_fmt.h | 267 + 548 files changed, 531133 insertions(+) create mode 100644 Android.mk create mode 100644 Kbuild create mode 100644 Kconfig create mode 100644 Makefile create mode 100644 README.txt create mode 100644 config/WCNSS_qcom_cfg.ini create mode 100644 core/bmi/inc/bmi.h create mode 100644 core/bmi/inc/ol_fw.h create mode 100644 core/bmi/inc/ol_if_athvar.h create mode 100644 core/bmi/src/bmi.c create mode 100644 core/bmi/src/bmi_1.c create mode 100644 core/bmi/src/bmi_2.c create mode 100644 core/bmi/src/i_ar6320v2_regtable.h create mode 100644 core/bmi/src/i_bmi.h create mode 100644 core/bmi/src/ol_fw.c create mode 100644 core/cdf/inc/cdf_atomic.h create mode 100644 core/cdf/inc/cdf_defer.h create mode 100644 core/cdf/inc/cdf_event.h create mode 100644 core/cdf/inc/cdf_list.h create mode 100644 core/cdf/inc/cdf_lock.h create mode 100644 core/cdf/inc/cdf_mc_timer.h create mode 100644 core/cdf/inc/cdf_memory.h create mode 100644 core/cdf/inc/cdf_nbuf.h create mode 100644 core/cdf/inc/cdf_net_types.h create mode 100644 core/cdf/inc/cdf_softirq_timer.h create mode 100644 core/cdf/inc/cdf_status.h create mode 100644 core/cdf/inc/cdf_threads.h create mode 100644 core/cdf/inc/cdf_time.h create mode 100644 core/cdf/inc/cdf_trace.h create mode 100644 core/cdf/inc/cdf_types.h create mode 100644 core/cdf/inc/cdf_util.h create mode 100644 core/cdf/inc/osdep.h create mode 100644 core/cdf/src/cdf_defer.c create mode 100644 core/cdf/src/cdf_event.c create mode 100644 core/cdf/src/cdf_list.c create mode 100644 core/cdf/src/cdf_lock.c create mode 100644 core/cdf/src/cdf_mc_timer.c create mode 100644 core/cdf/src/cdf_memory.c create mode 100644 core/cdf/src/cdf_nbuf.c create mode 100644 core/cdf/src/cdf_threads.c create mode 100644 core/cdf/src/cdf_trace.c create mode 100644 core/cdf/src/i_cdf_atomic.h create mode 100644 core/cdf/src/i_cdf_defer.h create mode 100644 core/cdf/src/i_cdf_event.h create mode 100644 core/cdf/src/i_cdf_lock.h create mode 100644 core/cdf/src/i_cdf_mc_timer.h create mode 100644 core/cdf/src/i_cdf_nbuf.h create mode 100644 core/cdf/src/i_cdf_softirq_timer.h create mode 100644 core/cdf/src/i_cdf_time.h create mode 100644 core/cdf/src/i_cdf_trace.h create mode 100644 core/cdf/src/i_cdf_types.h create mode 100644 core/cdf/src/i_cdf_util.h create mode 100644 core/cds/inc/cds_api.h create mode 100644 core/cds/inc/cds_concurrency.h create mode 100644 core/cds/inc/cds_crypto.h create mode 100644 core/cds/inc/cds_get_bin.h create mode 100644 core/cds/inc/cds_ieee80211_common.h create mode 100644 core/cds/inc/cds_ieee80211_defines.h create mode 100644 core/cds/inc/cds_if_upperproto.h create mode 100644 core/cds/inc/cds_mq.h create mode 100644 core/cds/inc/cds_pack_align.h create mode 100644 core/cds/inc/cds_packet.h create mode 100644 core/cds/inc/cds_queue.h create mode 100644 core/cds/inc/cds_reg_service.h create mode 100644 core/cds/inc/cds_regdomain.h create mode 100644 core/cds/inc/cds_regdomain_common.h create mode 100644 core/cds/inc/cds_sched.h create mode 100644 core/cds/inc/cds_utils.h create mode 100644 core/cds/src/cds_api.c create mode 100644 core/cds/src/cds_concurrency.c create mode 100644 core/cds/src/cds_get_bin.c create mode 100644 core/cds/src/cds_ieee80211_common_i.h create mode 100644 core/cds/src/cds_mq.c create mode 100644 core/cds/src/cds_packet.c create mode 100644 core/cds/src/cds_reg_service.c create mode 100644 core/cds/src/cds_regdomain.c create mode 100644 core/cds/src/cds_sched.c create mode 100644 core/cds/src/cds_utils.c create mode 100644 core/cds/src/i_cds_packet.h create mode 100644 core/cds/src/queue.h create mode 100644 core/dp/htt/htt.c create mode 100644 core/dp/htt/htt_fw_stats.c create mode 100644 core/dp/htt/htt_h2t.c create mode 100644 core/dp/htt/htt_internal.h create mode 100644 core/dp/htt/htt_rx.c create mode 100644 core/dp/htt/htt_t2h.c create mode 100644 core/dp/htt/htt_tx.c create mode 100644 core/dp/htt/htt_types.h create mode 100644 core/dp/htt/rx_desc.h create mode 100644 core/dp/ol/inc/ol_cfg.h create mode 100644 core/dp/ol/inc/ol_ctrl_addba_api.h create mode 100644 core/dp/ol/inc/ol_ctrl_api.h create mode 100644 core/dp/ol/inc/ol_defines.h create mode 100644 core/dp/ol/inc/ol_htt_api.h create mode 100644 core/dp/ol/inc/ol_htt_rx_api.h create mode 100644 core/dp/ol/inc/ol_htt_tx_api.h create mode 100644 core/dp/ol/inc/ol_osif_api.h create mode 100644 core/dp/ol/inc/ol_params.h create mode 100644 core/dp/ol/inc/ol_txrx_api.h create mode 100644 core/dp/ol/inc/ol_txrx_ctrl_api.h create mode 100644 core/dp/ol/inc/ol_txrx_dbg.h create mode 100644 core/dp/ol/inc/ol_txrx_htt_api.h create mode 100644 core/dp/ol/inc/ol_txrx_osif_api.h create mode 100644 core/dp/ol/inc/ol_txrx_stats.h create mode 100644 core/dp/ol/inc/ol_vowext_dbg_defs.h create mode 100644 core/dp/txrx/ipv6_defs.h create mode 100644 core/dp/txrx/ol_cfg.c create mode 100644 core/dp/txrx/ol_ctrl_txrx_api.h create mode 100644 core/dp/txrx/ol_osif_txrx_api.h create mode 100644 core/dp/txrx/ol_rx.c create mode 100644 core/dp/txrx/ol_rx.h create mode 100644 core/dp/txrx/ol_rx_defrag.c create mode 100644 core/dp/txrx/ol_rx_defrag.h create mode 100644 core/dp/txrx/ol_rx_fwd.c create mode 100644 core/dp/txrx/ol_rx_fwd.h create mode 100644 core/dp/txrx/ol_rx_pn.c create mode 100644 core/dp/txrx/ol_rx_pn.h create mode 100644 core/dp/txrx/ol_rx_reorder.c create mode 100644 core/dp/txrx/ol_rx_reorder.h create mode 100644 core/dp/txrx/ol_rx_reorder_timeout.c create mode 100644 core/dp/txrx/ol_rx_reorder_timeout.h create mode 100644 core/dp/txrx/ol_tx.c create mode 100644 core/dp/txrx/ol_tx.h create mode 100644 core/dp/txrx/ol_tx_desc.c create mode 100644 core/dp/txrx/ol_tx_desc.h create mode 100644 core/dp/txrx/ol_tx_queue.c create mode 100644 core/dp/txrx/ol_tx_queue.h create mode 100644 core/dp/txrx/ol_tx_send.c create mode 100644 core/dp/txrx/ol_tx_send.h create mode 100644 core/dp/txrx/ol_txrx.c create mode 100644 core/dp/txrx/ol_txrx.h create mode 100644 core/dp/txrx/ol_txrx_encap.c create mode 100644 core/dp/txrx/ol_txrx_encap.h create mode 100644 core/dp/txrx/ol_txrx_event.c create mode 100644 core/dp/txrx/ol_txrx_flow_control.c create mode 100644 core/dp/txrx/ol_txrx_internal.h create mode 100644 core/dp/txrx/ol_txrx_peer_find.c create mode 100644 core/dp/txrx/ol_txrx_peer_find.h create mode 100644 core/dp/txrx/ol_txrx_types.h create mode 100644 core/dp/txrx/txrx.h create mode 100644 core/dp/txrx/wdi_event.h create mode 100644 core/dp/txrx/wdi_event_api.h create mode 100644 core/hdd/inc/qc_sap_ioctl.h create mode 100644 core/hdd/inc/wlan_hdd_assoc.h create mode 100644 core/hdd/inc/wlan_hdd_cfg.h create mode 100644 core/hdd/inc/wlan_hdd_conc_ut.h create mode 100644 core/hdd/inc/wlan_hdd_debugfs.h create mode 100644 core/hdd/inc/wlan_hdd_driver_ops.h create mode 100644 core/hdd/inc/wlan_hdd_ether.h create mode 100644 core/hdd/inc/wlan_hdd_ftm.h create mode 100644 core/hdd/inc/wlan_hdd_host_offload.h create mode 100644 core/hdd/inc/wlan_hdd_includes.h create mode 100644 core/hdd/inc/wlan_hdd_ipa.h create mode 100644 core/hdd/inc/wlan_hdd_lro.h create mode 100644 core/hdd/inc/wlan_hdd_main.h create mode 100644 core/hdd/inc/wlan_hdd_memdump.h create mode 100644 core/hdd/inc/wlan_hdd_mib.h create mode 100644 core/hdd/inc/wlan_hdd_misc.h create mode 100644 core/hdd/inc/wlan_hdd_nan.h create mode 100644 core/hdd/inc/wlan_hdd_napi.h create mode 100644 core/hdd/inc/wlan_hdd_oemdata.h create mode 100644 core/hdd/inc/wlan_hdd_p2p.h create mode 100644 core/hdd/inc/wlan_hdd_power.h create mode 100644 core/hdd/inc/wlan_hdd_softap_tx_rx.h create mode 100644 core/hdd/inc/wlan_hdd_tdls.h create mode 100644 core/hdd/inc/wlan_hdd_trace.h create mode 100644 core/hdd/inc/wlan_hdd_tx_rx.h create mode 100644 core/hdd/inc/wlan_hdd_wext.h create mode 100644 core/hdd/inc/wlan_hdd_wmm.h create mode 100644 core/hdd/inc/wlan_hdd_wowl.h create mode 100644 core/hdd/src/wlan_hdd_assoc.c create mode 100644 core/hdd/src/wlan_hdd_cfg.c create mode 100644 core/hdd/src/wlan_hdd_cfg80211.c create mode 100644 core/hdd/src/wlan_hdd_cfg80211.h create mode 100644 core/hdd/src/wlan_hdd_conc_ut.c create mode 100644 core/hdd/src/wlan_hdd_debugfs.c create mode 100644 core/hdd/src/wlan_hdd_driver_ops.c create mode 100644 core/hdd/src/wlan_hdd_ext_scan.c create mode 100644 core/hdd/src/wlan_hdd_ext_scan.h create mode 100644 core/hdd/src/wlan_hdd_ftm.c create mode 100644 core/hdd/src/wlan_hdd_green_ap.c create mode 100644 core/hdd/src/wlan_hdd_green_ap.h create mode 100644 core/hdd/src/wlan_hdd_hostapd.c create mode 100644 core/hdd/src/wlan_hdd_hostapd.h create mode 100644 core/hdd/src/wlan_hdd_ioctl.c create mode 100644 core/hdd/src/wlan_hdd_ioctl.h create mode 100644 core/hdd/src/wlan_hdd_ipa.c create mode 100644 core/hdd/src/wlan_hdd_lro.c create mode 100644 core/hdd/src/wlan_hdd_main.c create mode 100644 core/hdd/src/wlan_hdd_memdump.c create mode 100644 core/hdd/src/wlan_hdd_nan.c create mode 100644 core/hdd/src/wlan_hdd_napi.c create mode 100644 core/hdd/src/wlan_hdd_ocb.c create mode 100644 core/hdd/src/wlan_hdd_ocb.h create mode 100644 core/hdd/src/wlan_hdd_oemdata.c create mode 100644 core/hdd/src/wlan_hdd_p2p.c create mode 100644 core/hdd/src/wlan_hdd_power.c create mode 100644 core/hdd/src/wlan_hdd_scan.c create mode 100644 core/hdd/src/wlan_hdd_scan.h create mode 100644 core/hdd/src/wlan_hdd_softap_tx_rx.c create mode 100644 core/hdd/src/wlan_hdd_stats.c create mode 100644 core/hdd/src/wlan_hdd_stats.h create mode 100644 core/hdd/src/wlan_hdd_tdls.c create mode 100644 core/hdd/src/wlan_hdd_trace.c create mode 100644 core/hdd/src/wlan_hdd_tx_rx.c create mode 100644 core/hdd/src/wlan_hdd_wext.c create mode 100644 core/hdd/src/wlan_hdd_wmm.c create mode 100644 core/hdd/src/wlan_hdd_wowl.c create mode 100644 core/hif/inc/hif.h create mode 100644 core/hif/inc/hif_napi.h create mode 100644 core/hif/inc/regtable.h create mode 100644 core/hif/inc/regtable_ce.h create mode 100644 core/hif/inc/regtable_pcie.h create mode 100644 core/hif/src/adrastea_reg_def.h create mode 100644 core/hif/src/ar6320def.h create mode 100644 core/hif/src/ar6320v2def.h create mode 100644 core/hif/src/ar9888def.h create mode 100644 core/hif/src/ath_procfs.c create mode 100644 core/hif/src/ce/ce_api.h create mode 100644 core/hif/src/ce/ce_assignment.h create mode 100644 core/hif/src/ce/ce_bmi.c create mode 100644 core/hif/src/ce/ce_bmi.h create mode 100644 core/hif/src/ce/ce_diag.c create mode 100644 core/hif/src/ce/ce_internal.h create mode 100644 core/hif/src/ce/ce_main.c create mode 100644 core/hif/src/ce/ce_main.h create mode 100644 core/hif/src/ce/ce_reg.h create mode 100644 core/hif/src/ce/ce_service.c create mode 100644 core/hif/src/ce/ce_tasklet.c create mode 100644 core/hif/src/ce/ce_tasklet.h create mode 100644 core/hif/src/hif_debug.h create mode 100644 core/hif/src/hif_hw_version.h create mode 100644 core/hif/src/hif_io32.h create mode 100644 core/hif/src/hif_main.c create mode 100644 core/hif/src/hif_main.h create mode 100644 core/hif/src/hif_napi.c create mode 100644 core/hif/src/icnss_stub/icnss_stub.c create mode 100644 core/hif/src/icnss_stub/icnss_stub.h create mode 100644 core/hif/src/mp_dev.c create mode 100644 core/hif/src/mp_dev.h create mode 100644 core/hif/src/pcie/cnss_stub.h create mode 100644 core/hif/src/pcie/hif_io32_pci.h create mode 100644 core/hif/src/pcie/if_pci.c create mode 100644 core/hif/src/pcie/if_pci.h create mode 100644 core/hif/src/pcie/if_pci_internal.h create mode 100644 core/hif/src/qca6180def.h create mode 100644 core/hif/src/regtable.c create mode 100644 core/hif/src/snoc/hif_io32_snoc.h create mode 100644 core/hif/src/snoc/if_snoc.c create mode 100644 core/htc/dl_list.h create mode 100644 core/htc/htc.c create mode 100644 core/htc/htc_api.h create mode 100644 core/htc/htc_debug.h create mode 100644 core/htc/htc_internal.h create mode 100644 core/htc/htc_packet.h create mode 100644 core/htc/htc_recv.c create mode 100644 core/htc/htc_send.c create mode 100644 core/htc/htc_services.c create mode 100644 core/mac/inc/ani_global.h create mode 100644 core/mac/inc/ani_system_defs.h create mode 100644 core/mac/inc/mac_init_api.h create mode 100644 core/mac/inc/mac_trace.h create mode 100644 core/mac/inc/qwlan_version.h create mode 100644 core/mac/inc/sir_api.h create mode 100644 core/mac/inc/sir_mac_prop_exts.h create mode 100644 core/mac/inc/sir_mac_prot_def.h create mode 100644 core/mac/inc/sir_types.h create mode 100644 core/mac/inc/wni_api.h create mode 100644 core/mac/inc/wni_cfg.h create mode 100644 core/mac/src/cfg/cfgUtil/cfg.txt create mode 100644 core/mac/src/cfg/cfgUtil/dot11f.frms create mode 100644 core/mac/src/cfg/cfg_api.c create mode 100644 core/mac/src/cfg/cfg_debug.c create mode 100644 core/mac/src/cfg/cfg_debug.h create mode 100644 core/mac/src/cfg/cfg_def.h create mode 100644 core/mac/src/cfg/cfg_param_name.c create mode 100644 core/mac/src/cfg/cfg_priv.h create mode 100644 core/mac/src/cfg/cfg_proc_msg.c create mode 100644 core/mac/src/cfg/cfg_send_msg.c create mode 100644 core/mac/src/dph/dph_hash_table.c create mode 100644 core/mac/src/dph/dph_hash_table.h create mode 100644 core/mac/src/include/cfg_api.h create mode 100644 core/mac/src/include/cfg_global.h create mode 100644 core/mac/src/include/dot11f.h create mode 100644 core/mac/src/include/dph_global.h create mode 100644 core/mac/src/include/parser_api.h create mode 100644 core/mac/src/include/sir_common.h create mode 100644 core/mac/src/include/sir_debug.h create mode 100644 core/mac/src/include/sir_params.h create mode 100644 core/mac/src/include/sys_global.h create mode 100644 core/mac/src/include/utils_api.h create mode 100644 core/mac/src/include/utils_global.h create mode 100644 core/mac/src/pe/include/lim_admit_control.h create mode 100644 core/mac/src/pe/include/lim_api.h create mode 100644 core/mac/src/pe/include/lim_ft.h create mode 100644 core/mac/src/pe/include/lim_ft_defs.h create mode 100644 core/mac/src/pe/include/lim_global.h create mode 100644 core/mac/src/pe/include/lim_session.h create mode 100644 core/mac/src/pe/include/lim_trace.h create mode 100644 core/mac/src/pe/include/rrm_api.h create mode 100644 core/mac/src/pe/include/rrm_global.h create mode 100644 core/mac/src/pe/include/sch_api.h create mode 100644 core/mac/src/pe/include/sch_global.h create mode 100644 core/mac/src/pe/include/wmm_apsd.h create mode 100644 core/mac/src/pe/lim/lim_admit_control.c create mode 100644 core/mac/src/pe/lim/lim_aid_mgmt.c create mode 100644 core/mac/src/pe/lim/lim_api.c create mode 100644 core/mac/src/pe/lim/lim_assoc_utils.c create mode 100644 core/mac/src/pe/lim/lim_assoc_utils.h create mode 100644 core/mac/src/pe/lim/lim_debug.c create mode 100644 core/mac/src/pe/lim/lim_debug.h create mode 100644 core/mac/src/pe/lim/lim_ft.c create mode 100644 core/mac/src/pe/lim/lim_ibss_peer_mgmt.c create mode 100644 core/mac/src/pe/lim/lim_ibss_peer_mgmt.h create mode 100644 core/mac/src/pe/lim/lim_link_monitoring_algo.c create mode 100644 core/mac/src/pe/lim/lim_p2p.c create mode 100644 core/mac/src/pe/lim/lim_process_action_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_assoc_req_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_auth_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_beacon_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_cfg_updates.c create mode 100644 core/mac/src/pe/lim/lim_process_deauth_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_disassoc_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_message_queue.c create mode 100644 core/mac/src/pe/lim/lim_process_mlm_req_messages.c create mode 100644 core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c create mode 100644 core/mac/src/pe/lim/lim_process_probe_req_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_probe_rsp_frame.c create mode 100644 core/mac/src/pe/lim/lim_process_sme_req_messages.c create mode 100644 core/mac/src/pe/lim/lim_process_tdls.c create mode 100644 core/mac/src/pe/lim/lim_prop_exts_utils.c create mode 100644 core/mac/src/pe/lim/lim_prop_exts_utils.h create mode 100644 core/mac/src/pe/lim/lim_scan_result_utils.c create mode 100644 core/mac/src/pe/lim/lim_scan_result_utils.h create mode 100644 core/mac/src/pe/lim/lim_security_utils.c create mode 100644 core/mac/src/pe/lim/lim_security_utils.h create mode 100644 core/mac/src/pe/lim/lim_send_management_frames.c create mode 100644 core/mac/src/pe/lim/lim_send_messages.c create mode 100644 core/mac/src/pe/lim/lim_send_messages.h create mode 100644 core/mac/src/pe/lim/lim_send_sme_rsp_messages.c create mode 100644 core/mac/src/pe/lim/lim_send_sme_rsp_messages.h create mode 100644 core/mac/src/pe/lim/lim_ser_des_utils.c create mode 100644 core/mac/src/pe/lim/lim_ser_des_utils.h create mode 100644 core/mac/src/pe/lim/lim_session.c create mode 100644 core/mac/src/pe/lim/lim_session_utils.c create mode 100644 core/mac/src/pe/lim/lim_session_utils.h create mode 100644 core/mac/src/pe/lim/lim_sme_req_utils.c create mode 100644 core/mac/src/pe/lim/lim_sme_req_utils.h create mode 100644 core/mac/src/pe/lim/lim_sta_hash_api.c create mode 100644 core/mac/src/pe/lim/lim_sta_hash_api.h create mode 100644 core/mac/src/pe/lim/lim_timer_utils.c create mode 100644 core/mac/src/pe/lim/lim_timer_utils.h create mode 100644 core/mac/src/pe/lim/lim_trace.c create mode 100644 core/mac/src/pe/lim/lim_types.h create mode 100644 core/mac/src/pe/lim/lim_utils.c create mode 100644 core/mac/src/pe/lim/lim_utils.h create mode 100644 core/mac/src/pe/rrm/rrm_api.c create mode 100644 core/mac/src/pe/sch/sch_api.c create mode 100644 core/mac/src/pe/sch/sch_beacon_gen.c create mode 100644 core/mac/src/pe/sch/sch_beacon_process.c create mode 100644 core/mac/src/pe/sch/sch_debug.c create mode 100644 core/mac/src/pe/sch/sch_debug.h create mode 100644 core/mac/src/pe/sch/sch_message.c create mode 100644 core/mac/src/pe/sch/sch_sys_params.h create mode 100644 core/mac/src/sys/common/inc/wlan_qct_sys.h create mode 100644 core/mac/src/sys/common/src/wlan_qct_sys.c create mode 100644 core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h create mode 100644 core/mac/src/sys/legacy/src/platform/src/sys_wrapper.c create mode 100644 core/mac/src/sys/legacy/src/system/inc/sys_debug.h create mode 100644 core/mac/src/sys/legacy/src/system/inc/sys_def.h create mode 100644 core/mac/src/sys/legacy/src/system/inc/sys_entry_func.h create mode 100644 core/mac/src/sys/legacy/src/system/inc/sys_startup.h create mode 100644 core/mac/src/sys/legacy/src/system/src/mac_init_api.c create mode 100644 core/mac/src/sys/legacy/src/system/src/sys_entry_func.c create mode 100644 core/mac/src/sys/legacy/src/utils/inc/dot11fdefs.h create mode 100644 core/mac/src/sys/legacy/src/utils/inc/utils_parser.h create mode 100644 core/mac/src/sys/legacy/src/utils/src/dot11f.c create mode 100644 core/mac/src/sys/legacy/src/utils/src/log_api.c create mode 100644 core/mac/src/sys/legacy/src/utils/src/mac_trace.c create mode 100644 core/mac/src/sys/legacy/src/utils/src/parser_api.c create mode 100644 core/mac/src/sys/legacy/src/utils/src/utils_api.c create mode 100644 core/mac/src/sys/legacy/src/utils/src/utils_parser.c create mode 100644 core/sap/dfs/inc/ath_dfs_structs.h create mode 100644 core/sap/dfs/inc/dfs.h create mode 100644 core/sap/dfs/inc/dfs_interface.h create mode 100644 core/sap/dfs/inc/radar_filters.h create mode 100644 core/sap/dfs/sources create mode 100644 core/sap/dfs/src/dfs.c create mode 100644 core/sap/dfs/src/dfs_bindetects.c create mode 100644 core/sap/dfs/src/dfs_debug.c create mode 100644 core/sap/dfs/src/dfs_fcc_bin5.c create mode 100644 core/sap/dfs/src/dfs_init.c create mode 100644 core/sap/dfs/src/dfs_ioctl.h create mode 100644 core/sap/dfs/src/dfs_ioctl_private.h create mode 100644 core/sap/dfs/src/dfs_misc.c create mode 100644 core/sap/dfs/src/dfs_nol.c create mode 100644 core/sap/dfs/src/dfs_phyerr.h create mode 100644 core/sap/dfs/src/dfs_phyerr_tlv.c create mode 100644 core/sap/dfs/src/dfs_phyerr_tlv.h create mode 100644 core/sap/dfs/src/dfs_process_phyerr.c create mode 100644 core/sap/dfs/src/dfs_process_radarevent.c create mode 100644 core/sap/dfs/src/dfs_staggered.c create mode 100644 core/sap/inc/sap_api.h create mode 100644 core/sap/src/sap_api_link_cntl.c create mode 100644 core/sap/src/sap_ch_select.c create mode 100644 core/sap/src/sap_ch_select.h create mode 100644 core/sap/src/sap_fsm.c create mode 100644 core/sap/src/sap_fsm_ext.h create mode 100644 core/sap/src/sap_internal.h create mode 100644 core/sap/src/sap_module.c create mode 100644 core/sme/inc/csr_api.h create mode 100644 core/sme/inc/csr_internal.h create mode 100644 core/sme/inc/csr_link_list.h create mode 100644 core/sme/inc/csr_neighbor_roam.h create mode 100644 core/sme/inc/csr_support.h create mode 100644 core/sme/inc/nan_api.h create mode 100644 core/sme/inc/oem_data_api.h create mode 100644 core/sme/inc/oem_data_internal.h create mode 100644 core/sme/inc/p2p_api.h create mode 100644 core/sme/inc/sme_api.h create mode 100644 core/sme/inc/sme_ft_api.h create mode 100644 core/sme/inc/sme_inside.h create mode 100644 core/sme/inc/sme_internal.h create mode 100644 core/sme/inc/sme_power_save.h create mode 100644 core/sme/inc/sme_power_save_api.h create mode 100644 core/sme/inc/sme_qos_api.h create mode 100644 core/sme/inc/sme_qos_internal.h create mode 100644 core/sme/inc/sme_rrm_api.h create mode 100644 core/sme/inc/sme_rrm_internal.h create mode 100644 core/sme/inc/sme_trace.h create mode 100644 core/sme/inc/sms_debug.h create mode 100644 core/sme/inc/wlan_ps_wow_diag.h create mode 100644 core/sme/src/common/sme_api.c create mode 100644 core/sme/src/common/sme_ft_api.c create mode 100644 core/sme/src/common/sme_power_save.c create mode 100644 core/sme/src/common/sme_trace.c create mode 100644 core/sme/src/csr/csr_api_roam.c create mode 100644 core/sme/src/csr/csr_api_scan.c create mode 100644 core/sme/src/csr/csr_cmd_process.c create mode 100644 core/sme/src/csr/csr_inside_api.h create mode 100644 core/sme/src/csr/csr_link_list.c create mode 100644 core/sme/src/csr/csr_neighbor_roam.c create mode 100644 core/sme/src/csr/csr_tdls_process.c create mode 100644 core/sme/src/csr/csr_util.c create mode 100644 core/sme/src/nan/nan_api.c create mode 100644 core/sme/src/oem_data/oem_data_api.c create mode 100644 core/sme/src/p2p/p2p_api.c create mode 100644 core/sme/src/qos/sme_qos.c create mode 100644 core/sme/src/rrm/sme_rrm.c create mode 100644 core/utils/epping/inc/epping_internal.h create mode 100644 core/utils/epping/inc/epping_main.h create mode 100644 core/utils/epping/src/epping_helper.c create mode 100644 core/utils/epping/src/epping_main.c create mode 100644 core/utils/epping/src/epping_rx.c create mode 100644 core/utils/epping/src/epping_tx.c create mode 100644 core/utils/epping/src/epping_txrx.c create mode 100644 core/utils/fwlog/dbglog_host.c create mode 100644 core/utils/fwlog/dbglog_host.h create mode 100644 core/utils/host_diag_log/inc/host_diag_core_event.h create mode 100644 core/utils/host_diag_log/inc/host_diag_core_log.h create mode 100644 core/utils/host_diag_log/inc/host_diag_event_defs.h create mode 100644 core/utils/host_diag_log/inc/log_codes.h create mode 100644 core/utils/host_diag_log/src/host_diag_log.c create mode 100644 core/utils/host_diag_log/src/i_host_diag_core_event.h create mode 100644 core/utils/host_diag_log/src/i_host_diag_core_log.h create mode 100644 core/utils/logging/inc/wlan_logging_sock_svc.h create mode 100644 core/utils/logging/src/wlan_logging_sock_svc.c create mode 100644 core/utils/nlink/inc/wlan_nlink_common.h create mode 100644 core/utils/nlink/inc/wlan_nlink_srv.h create mode 100644 core/utils/nlink/src/wlan_nlink_srv.c create mode 100644 core/utils/pktlog/include/pktlog.h create mode 100644 core/utils/pktlog/include/pktlog_ac.h create mode 100644 core/utils/pktlog/include/pktlog_ac_api.h create mode 100644 core/utils/pktlog/include/pktlog_ac_i.h create mode 100644 core/utils/pktlog/linux_ac.c create mode 100644 core/utils/pktlog/pktlog_ac.c create mode 100644 core/utils/pktlog/pktlog_internal.c create mode 100644 core/utils/ptt/inc/wlan_ptt_sock_svc.h create mode 100644 core/utils/ptt/src/wlan_ptt_sock_svc.c create mode 100644 core/wma/inc/wma.h create mode 100644 core/wma/inc/wma_api.h create mode 100644 core/wma/inc/wma_dfs_interface.h create mode 100644 core/wma/inc/wma_if.h create mode 100644 core/wma/inc/wma_internal.h create mode 100644 core/wma/inc/wma_tgt_cfg.h create mode 100644 core/wma/inc/wma_types.h create mode 100644 core/wma/src/wlan_qct_wma_legacy.c create mode 100644 core/wma/src/wma_data.c create mode 100644 core/wma/src/wma_dev_if.c create mode 100644 core/wma/src/wma_dfs_interface.c create mode 100644 core/wma/src/wma_features.c create mode 100644 core/wma/src/wma_main.c create mode 100644 core/wma/src/wma_mgmt.c create mode 100644 core/wma/src/wma_ocb.c create mode 100644 core/wma/src/wma_ocb.h create mode 100644 core/wma/src/wma_power.c create mode 100644 core/wma/src/wma_scan_roam.c create mode 100644 core/wma/src/wma_utils.c create mode 100644 core/wma/src/wma_utils_ut.c create mode 100644 core/wmi/wmi_tlv_helper.c create mode 100644 core/wmi/wmi_tlv_platform.c create mode 100644 core/wmi/wmi_unified.c create mode 100644 core/wmi/wmi_unified_api.h create mode 100644 core/wmi/wmi_unified_priv.h create mode 100644 core/wmi/wmi_version_whitelist.c create mode 100644 target/inc/a_osapi.h create mode 100644 target/inc/a_usb_defs.h create mode 100644 target/inc/apb_athr_wlan_map.h create mode 100644 target/inc/athdefs.h create mode 100644 target/inc/athendpack.h create mode 100644 target/inc/bin_sig.h create mode 100644 target/inc/bmi_msg.h create mode 100644 target/inc/cepci.h create mode 100644 target/inc/dbglog.h create mode 100644 target/inc/dbglog_id.h create mode 100644 target/inc/efuse_reg.h create mode 100644 target/inc/enet.h create mode 100644 target/inc/epping_test.h create mode 100644 target/inc/htc.h create mode 100644 target/inc/htc_services.h create mode 100644 target/inc/htt.h create mode 100644 target/inc/htt_common.h create mode 100644 target/inc/htt_isoc.h create mode 100644 target/inc/ip_prot.h create mode 100644 target/inc/ipv4.h create mode 100644 target/inc/ol_fw_tx_dbg.h create mode 100644 target/inc/rtc_soc_reg.h create mode 100644 target/inc/targaddrs.h create mode 100644 target/inc/targcfg.h create mode 100644 target/inc/wal_rx_desc.h create mode 100644 target/inc/wlan_defs.h create mode 100644 target/inc/wlan_module_ids.h create mode 100644 target/inc/wlan_tgt_def_config.h create mode 100644 target/inc/wmi.h create mode 100644 target/inc/wmi_services.h create mode 100644 target/inc/wmi_tlv_defs.h create mode 100644 target/inc/wmi_tlv_helper.h create mode 100644 target/inc/wmi_unified.h create mode 100644 target/inc/wmi_version.h create mode 100644 target/inc/wmix.h create mode 100644 uapi/linux/a_debug.h create mode 100644 uapi/linux/a_types.h create mode 100644 uapi/linux/athstartpack.h create mode 100644 uapi/linux/dbglog_common.h create mode 100644 uapi/linux/debug_linux.h create mode 100644 uapi/linux/osapi_linux.h create mode 100644 uapi/linux/pktlog_ac_fmt.h diff --git a/Android.mk b/Android.mk new file mode 100644 index 000000000000..3bbcfe93ea9e --- /dev/null +++ b/Android.mk @@ -0,0 +1,106 @@ +# Android makefile for the WLAN Module + +# Assume no targets will be supported +WLAN_CHIPSET := + +ifeq ($(BOARD_HAS_QCOM_WLAN), true) + +# Build/Package options for 8084/8092/8960/8992/8994 target +ifeq ($(call is-board-platform-in-list, apq8084 mpq8092 msm8960 msm8992 msm8994 msm8996 msm8998),true) + WLAN_CHIPSET := qca_cld + WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m +endif # platform + +# Build/Package only in case of supported target +ifneq ($(WLAN_CHIPSET),) + +LOCAL_PATH := $(call my-dir) + +# This makefile is only for DLKM +ifneq ($(findstring vendor,$(LOCAL_PATH)),) + +ifneq ($(findstring opensource,$(LOCAL_PATH)),) + WLAN_PROPRIETARY := 0 + WLAN_BLD_DIR := vendor/qcom/opensource/wlan +else + WLAN_PROPRIETARY := 1 + WLAN_BLD_DIR := vendor/qcom/proprietary/wlan-noship +endif # opensource + +# DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) +ifeq ($(call is-platform-sdk-version-at-least,16),true) + DLKM_DIR := $(TOP)/device/qcom/common/dlkm +else + DLKM_DIR := build/dlkm +endif # platform-sdk-version + +# Copy WCNSS_cfg.dat and WCNSS_qcom_cfg.ini file from firmware_bin/ folder to target out directory. +ifeq ($(call is-board-platform-in-list, msm8960),true) +$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_cfg.dat) +$(shell rm -f $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_qcom_cfg.ini $(TARGET_OUT_ETC)/firmware/wlan/qca_cld) +endif + +# Build wlan.ko as $(WLAN_CHIPSET)_wlan.ko +########################################################### +# This is set once per LOCAL_PATH, not per (kernel) module +KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-new +# We are actually building wlan.ko here, as per the +# requirement we are specifying _wlan.ko as LOCAL_MODULE. +# This means we need to rename the module to _wlan.ko +# after wlan.ko is built. +KBUILD_OPTIONS += MODNAME=wlan +KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) +KBUILD_OPTIONS += $(WLAN_SELECT) + +include $(CLEAR_VARS) +LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko +LOCAL_MODULE_KBUILD_NAME := wlan.ko +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_DEBUG_ENABLE := true +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) +include $(DLKM_DIR)/AndroidKernelModule.mk +########################################################### + +# Create Symbolic link +ifeq ($(WLAN_PROPRIETARY),1) +$(shell mkdir -p $(TARGET_OUT)/lib/modules; \ + ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(LOCAL_MODULE) \ + $(TARGET_OUT)/lib/modules/wlan.ko) +endif +$(shell ln -sf /persist/wlan_mac.bin $(TARGET_OUT_ETC)/firmware/wlan/qca_cld/wlan_mac.bin) + +ifeq ($(call is-board-platform-in-list, msm8960),true) +$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/fakeboar.bin) +$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp.bin) +$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf.bin) +$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/athwlan.bin) + +$(shell ln -sf /firmware/image/bdwlan20.bin $(TARGET_OUT_ETC)/firmware/bdwlan20.bin) +$(shell ln -sf /firmware/image/otp20.bin $(TARGET_OUT_ETC)/firmware/otp20.bin) +$(shell ln -sf /firmware/image/utf20.bin $(TARGET_OUT_ETC)/firmware/utf20.bin) +$(shell ln -sf /firmware/image/qwlan20.bin $(TARGET_OUT_ETC)/firmware/qwlan20.bin) + +$(shell ln -sf /firmware/image/bdwlan30.bin $(TARGET_OUT_ETC)/firmware/bdwlan30.bin) +$(shell ln -sf /firmware/image/otp30.bin $(TARGET_OUT_ETC)/firmware/otp30.bin) +$(shell ln -sf /firmware/image/utf30.bin $(TARGET_OUT_ETC)/firmware/utf30.bin) +$(shell ln -sf /firmware/image/qwlan30.bin $(TARGET_OUT_ETC)/firmware/qwlan30.bin) +endif + +# Copy config ini files to target +#ifeq ($(call is-board-platform-in-list, msm8992 msm8994),false) +ifeq ($(WLAN_PROPRIETARY),1) +$(shell mkdir -p $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) +$(shell mkdir -p $(TARGET_OUT)/etc/wifi) +$(shell rm -f $(TARGET_OUT)/etc/wifi/WCNSS_qcom_cfg.ini) +$(shell rm -f $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_SHIPSET)/WCNSS_cfg.dat) +$(shell cp $(LOCAL_PATH)/config/WCNSS_qcom_cfg.ini $(TARGET_OUT)/etc/wifi) +$(shell cp $(LOCAL_PATH)/firmware_bin/WCNSS_cfg.dat $(TARGET_OUT)/etc/firmware/wlan/$(WLAN_CHIPSET)) +endif +#endif + +endif # DLKM check + +endif # supported target check +endif # WLAN enabled check diff --git a/Kbuild b/Kbuild new file mode 100644 index 000000000000..0ad05d87faa4 --- /dev/null +++ b/Kbuild @@ -0,0 +1,1331 @@ +# 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_CNSS), y) +ifndef CONFIG_ROME_IF + #use pci as default interface + CONFIG_ROME_IF = pci +endif +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-3.0 +endif + +# Make WLAN as open-source driver by default +WLAN_OPEN_SOURCE := 1 + +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 + + #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 + + ifeq ($(CONFIG_MOBILE_ROUTER), y) + CONFIG_QCACLD_FEATURE_GREEN_AP := 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_QCACLD_FEATURE_NAN := y + endif + + #Flag to enable Linux QCMBR feature as default feature + ifeq ($(CONFIG_ROME_IF),usb) + CONFIG_LINUX_QCMBR :=y + endif + + ifeq ($(CONFIG_CNSS_EOS),y) + CONFIG_FEATURE_BMI_2 :=y + endif + + CONFIG_MPC_UT_FRAMEWORK := y + + #Flag to enable offload packets feature + CONFIG_WLAN_OFFLOAD_PACKETS := y + + #Flag to enable memdump feature + CONFIG_WLAN_FEATURE_MEMDUMP := y + + #Flag to enable Fast Path feature + CONFIG_WLAN_FASTPATH := y + + # Flag to enable NAPI + CONFIG_WLAN_NAPI := y + CONFIG_WLAN_NAPI_DEBUG := n + + # Flag to enable FW based TX Flow control + CONFIG_WLAN_TX_FLOW_CONTROL_V2 := n + + # Flag to enable LRO (Large Receive Offload) + ifeq ($(CONFIG_CNSS_EOS), y) + ifeq ($(CONFIG_INET_LRO), y) + CONFIG_WLAN_LRO := y + else + CONFIG_WLAN_LRO := n + endif + endif +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 + +#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 + +#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 + + +#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 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 power management suspend/resume functionality to PCI +CONFIG_ATH_BUS_PM := 1 + +#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 +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/disable secure firmware feature +CONFIG_FEATURE_SECURE_FIRMWARE := 0 + +#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 + +############ UAPI ############ +UAPI_DIR := uapi +UAPI_INC := -I$(WLAN_ROOT)/$(UAPI_DIR)/linux + +############ COMMON ############ +COMMON_DIR := core/common +COMMON_INC := -I$(WLAN_ROOT)/$(COMMON_DIR) + +############ 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_driver_ops.o \ + $(HDD_SRC_DIR)/wlan_hdd_ftm.o \ + $(HDD_SRC_DIR)/wlan_hdd_hostapd.o \ + $(HDD_SRC_DIR)/wlan_hdd_ioctl.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_power.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_WLAN_LRO), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_lro.o +endif + +ifeq ($(CONFIG_WLAN_NAPI), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_napi.o +endif + +ifeq ($(CONFIG_IPA_OFFLOAD), 1) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_ipa.o +endif + +ifeq ($(HAVE_CFG80211),1) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_cfg80211.o \ + $(HDD_SRC_DIR)/wlan_hdd_ext_scan.o \ + $(HDD_SRC_DIR)/wlan_hdd_stats.o \ + $(HDD_SRC_DIR)/wlan_hdd_p2p.o +endif + +ifeq ($(CONFIG_QCACLD_FEATURE_GREEN_AP),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_green_ap.o +endif + +ifeq ($(CONFIG_QCACLD_FEATURE_NAN),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_nan.o +endif + +ifeq ($(CONFIG_QCOM_TDLS),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o +endif + +ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_conc_ut.o +endif + +ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_memdump.o +endif + +########### HOST DIAG LOG ########### +HOST_DIAG_LOG_DIR := core/utils/host_diag_log + +HOST_DIAG_LOG_INC_DIR := $(HOST_DIAG_LOG_DIR)/inc +HOST_DIAG_LOG_SRC_DIR := $(HOST_DIAG_LOG_DIR)/src + +HOST_DIAG_LOG_INC := -I$(WLAN_ROOT)/$(HOST_DIAG_LOG_INC_DIR) \ + -I$(WLAN_ROOT)/$(HOST_DIAG_LOG_SRC_DIR) + +HOST_DIAG_LOG_OBJS += $(HOST_DIAG_LOG_SRC_DIR)/host_diag_log.o + +############ EPPING ############ +EPPING_DIR := core/utils/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/cfg_api.o \ + $(MAC_SRC_DIR)/cfg/cfg_debug.o \ + $(MAC_SRC_DIR)/cfg/cfg_param_name.o \ + $(MAC_SRC_DIR)/cfg/cfg_proc_msg.o \ + $(MAC_SRC_DIR)/cfg/cfg_send_msg.o + +MAC_DPH_OBJS := $(MAC_SRC_DIR)/dph/dph_hash_table.o + +MAC_LIM_OBJS := $(MAC_SRC_DIR)/pe/lim/lim_aid_mgmt.o \ + $(MAC_SRC_DIR)/pe/lim/lim_admit_control.o \ + $(MAC_SRC_DIR)/pe/lim/lim_api.o \ + $(MAC_SRC_DIR)/pe/lim/lim_assoc_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_debug.o \ + $(MAC_SRC_DIR)/pe/lim/lim_ft.o \ + $(MAC_SRC_DIR)/pe/lim/lim_ibss_peer_mgmt.o \ + $(MAC_SRC_DIR)/pe/lim/lim_link_monitoring_algo.o \ + $(MAC_SRC_DIR)/pe/lim/lim_p2p.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_action_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_assoc_req_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_assoc_rsp_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_auth_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_beacon_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_cfg_updates.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_deauth_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_disassoc_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_message_queue.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_mlm_req_messages.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_mlm_rsp_messages.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_probe_req_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_probe_rsp_frame.o \ + $(MAC_SRC_DIR)/pe/lim/lim_process_sme_req_messages.o \ + $(MAC_SRC_DIR)/pe/lim/lim_prop_exts_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_scan_result_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_security_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_send_management_frames.o \ + $(MAC_SRC_DIR)/pe/lim/lim_send_messages.o \ + $(MAC_SRC_DIR)/pe/lim/lim_send_sme_rsp_messages.o \ + $(MAC_SRC_DIR)/pe/lim/lim_ser_des_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_session.o \ + $(MAC_SRC_DIR)/pe/lim/lim_session_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_sme_req_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_sta_hash_api.o \ + $(MAC_SRC_DIR)/pe/lim/lim_timer_utils.o \ + $(MAC_SRC_DIR)/pe/lim/lim_trace.o \ + $(MAC_SRC_DIR)/pe/lim/lim_utils.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/lim_process_tdls.o +endif + +MAC_SCH_OBJS := $(MAC_SRC_DIR)/pe/sch/sch_api.o \ + $(MAC_SRC_DIR)/pe/sch/sch_beacon_gen.o \ + $(MAC_SRC_DIR)/pe/sch/sch_beacon_process.o \ + $(MAC_SRC_DIR)/pe/sch/sch_debug.o \ + $(MAC_SRC_DIR)/pe/sch/sch_message.o + +MAC_RRM_OBJS := $(MAC_SRC_DIR)/pe/rrm/rrm_api.o + +MAC_OBJS := $(MAC_CFG_OBJS) \ + $(MAC_DPH_OBJS) \ + $(MAC_LIM_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)/sap_api_link_cntl.o \ + $(SAP_SRC_DIR)/sap_ch_select.o \ + $(SAP_SRC_DIR)/sap_fsm.o \ + $(SAP_SRC_DIR)/sap_module.o + +############ DFS ############ 350 +DFS_DIR := $(SAP_DIR)/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_CSR_OBJS := $(SME_SRC_DIR)/csr/csr_api_roam.o \ + $(SME_SRC_DIR)/csr/csr_api_scan.o \ + $(SME_SRC_DIR)/csr/csr_cmd_process.o \ + $(SME_SRC_DIR)/csr/csr_link_list.o \ + $(SME_SRC_DIR)/csr/csr_neighbor_roam.o \ + $(SME_SRC_DIR)/csr/csr_util.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/csr_tdls_process.o +endif + +SME_QOS_OBJS := $(SME_SRC_DIR)/qos/sme_qos.o + +SME_CMN_OBJS := $(SME_SRC_DIR)/common/sme_api.o \ + $(SME_SRC_DIR)/common/sme_ft_api.o \ + $(SME_SRC_DIR)/common/sme_power_save.o \ + $(SME_SRC_DIR)/common/sme_trace.o + +SME_OEM_DATA_OBJS := $(SME_SRC_DIR)/oem_data/oem_data_api.o + +SME_P2P_OBJS = $(SME_SRC_DIR)/p2p/p2p_api.o + +SME_RRM_OBJS := $(SME_SRC_DIR)/rrm/sme_rrm.o + +ifeq ($(CONFIG_QCACLD_FEATURE_NAN),y) +SME_NAN_OBJS = $(SME_SRC_DIR)/nan/nan_api.o +endif + +SME_OBJS := $(SME_CMN_OBJS) \ + $(SME_CSR_OBJS) \ + $(SME_OEM_DATA_OBJS) \ + $(SME_P2P_OBJS) \ + $(SME_QOS_OBJS) \ + $(SME_RRM_OBJS) \ + $(SME_NAN_OBJS) + +############ NLINK ############ +NLINK_DIR := core/utils/nlink +NLINK_INC_DIR := $(NLINK_DIR)/inc +NLINK_SRC_DIR := $(NLINK_DIR)/src + +NLINK_INC := -I$(WLAN_ROOT)/$(NLINK_INC_DIR) +NLINK_OBJS := $(NLINK_SRC_DIR)/wlan_nlink_srv.o + +############ PTT ############ +PTT_DIR := core/utils/ptt +PTT_INC_DIR := $(PTT_DIR)/inc +PTT_SRC_DIR := $(PTT_DIR)/src + +PTT_INC := -I$(WLAN_ROOT)/$(PTT_INC_DIR) +PTT_OBJS := $(PTT_SRC_DIR)/wlan_ptt_sock_svc.o + +############ WLAN_LOGGING ############ +WLAN_LOGGING_DIR := core/utils/logging +WLAN_LOGGING_INC_DIR := $(WLAN_LOGGING_DIR)/inc +WLAN_LOGGING_SRC_DIR := $(WLAN_LOGGING_DIR)/src + +WLAN_LOGGING_INC := -I$(WLAN_ROOT)/$(WLAN_LOGGING_INC_DIR) +WLAN_LOGGING_OBJS := $(WLAN_LOGGING_SRC_DIR)/wlan_logging_sock_svc.o + +############ SYS ############ +SYS_DIR := core/mac/src/sys + +SYS_INC := -I$(WLAN_ROOT)/$(SYS_DIR)/common/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)/platform/src/sys_wrapper.o \ + $(SYS_LEGACY_SRC_DIR)/system/src/mac_init_api.o \ + $(SYS_LEGACY_SRC_DIR)/system/src/sys_entry_func.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/dot11f.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/log_api.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/mac_trace.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/parser_api.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/utils_api.o \ + $(SYS_LEGACY_SRC_DIR)/utils/src/utils_parser.o + +############ CDF (Connectivity driver framework) ############ +CDF_DIR := core/cdf +CDF_INC_DIR := $(CDF_DIR)/inc +CDF_SRC_DIR := $(CDF_DIR)/src + +CDF_INC := -I$(WLAN_ROOT)/$(CDF_INC_DIR) \ + -I$(WLAN_ROOT)/$(CDF_SRC_DIR) + +CDF_OBJS := $(CDF_SRC_DIR)/cdf_event.o \ + $(CDF_SRC_DIR)/cdf_list.o \ + $(CDF_SRC_DIR)/cdf_lock.o \ + $(CDF_SRC_DIR)/cdf_memory.o \ + $(CDF_SRC_DIR)/cdf_threads.o \ + $(CDF_SRC_DIR)/cdf_mc_timer.o \ + $(CDF_SRC_DIR)/cdf_trace.o \ + $(CDF_SRC_DIR)/cdf_nbuf.o \ + $(CDF_SRC_DIR)/cdf_defer.o + +############ CDS (Connectivity driver services) ############ +CDS_DIR := core/cds +CDS_INC_DIR := $(CDS_DIR)/inc +CDS_SRC_DIR := $(CDS_DIR)/src + +CDS_INC := -I$(WLAN_ROOT)/$(CDS_INC_DIR) \ + -I$(WLAN_ROOT)/$(CDS_SRC_DIR) + +CDS_OBJS := $(CDS_SRC_DIR)/cds_api.o \ + $(CDS_SRC_DIR)/cds_get_bin.o \ + $(CDS_SRC_DIR)/cds_reg_service.o \ + $(CDS_SRC_DIR)/cds_mq.o \ + $(CDS_SRC_DIR)/cds_packet.o \ + $(CDS_SRC_DIR)/cds_regdomain.o \ + $(CDS_SRC_DIR)/cds_sched.o \ + $(CDS_SRC_DIR)/cds_concurrency.o \ + $(CDS_SRC_DIR)/cds_utils.o + + +########### BMI ########### +BMI_DIR := core/bmi + +BMI_INC := -I$(WLAN_ROOT)/$(BMI_DIR)/inc + +ifneq ($(CONFIG_ICNSS), y) +BMI_OBJS := $(BMI_DIR)/src/bmi.o \ + $(BMI_DIR)/src/ol_fw.o +ifeq ($(CONFIG_FEATURE_BMI_2), y) +BMI_OBJS += $(BMI_DIR)/src/bmi_2.o +else +BMI_OBJS += $(BMI_DIR)/src/bmi_1.o +endif +endif +########### WMI ########### +WMI_DIR := core/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 + +############ TXRX ############ +TXRX_DIR := core/dp/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.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 + +ifeq ($(CONFIG_WLAN_TX_FLOW_CONTROL_V2), y) +TXRX_OBJS += $(TXRX_DIR)/ol_txrx_flow_control.o +endif + +############ OL ############ +OL_DIR := core/dp/ol +OL_INC := -I$(WLAN_ROOT)/$(OL_DIR)/inc + +############ 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/dp/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/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 + +########### HIF ########### +HIF_DIR := core/hif +HIF_CE_DIR := $(HIF_DIR)/src/ce +HIF_CNSS_STUB_DIR := $(HIF_DIR)/src/icnss_stub + +ifeq ($(CONFIG_HIF_PCI), 1) +HIF_PCIE_DIR := $(HIF_DIR)/src/pcie +else +HIF_SNOC_DIR := $(HIF_DIR)/src/snoc +endif + +HIF_INC := -I$(WLAN_ROOT)/$(HIF_DIR)/inc \ + -I$(WLAN_ROOT)/$(HIF_DIR)/src \ + -I$(WLAN_ROOT)/$(HIF_CE_DIR) \ + -I$(WLAN_ROOT)/$(HIF_CNSS_STUB_DIR) + +ifeq ($(CONFIG_HIF_PCI), 1) +HIF_INC += -I$(WLAN_ROOT)/$(HIF_PCIE_DIR) +else +HIF_INC += -I$(WLAN_ROOT)/$(HIF_SNOC_DIR) +endif + +HIF_OBJS := $(HIF_DIR)/src/ath_procfs.o \ + $(HIF_CE_DIR)/ce_diag.o \ + $(HIF_CE_DIR)/ce_main.o \ + $(HIF_CE_DIR)/ce_service.o \ + $(HIF_CE_DIR)/ce_tasklet.o \ + $(HIF_DIR)/src/hif_main.o \ + $(HIF_DIR)/src/mp_dev.o \ + $(HIF_DIR)/src/regtable.o + +ifeq ($(CONFIG_CNSS), y) +HIF_OBJS += $(HIF_CNSS_STUB_DIR)/icnss_stub.o \ + $(HIF_CE_DIR)/ce_bmi.o +endif + +ifeq ($(CONFIG_WLAN_NAPI), y) +HIF_OBJS += $(HIF_DIR)/src/hif_napi.o +endif + +ifeq ($(CONFIG_HIF_PCI), 1) +HIF_PCIE_OBJS := $(HIF_PCIE_DIR)/if_pci.o + +HIF_OBJS += $(HIF_PCIE_OBJS) +else +HIF_SNOC_OBJS := $(HIF_SNOC_DIR)/if_snoc.o + +HIF_OBJS += $(HIF_SNOC_OBJS) +endif + +############ WMA ############ +WMA_DIR := core/wma + +WMA_INC_DIR := $(WMA_DIR)/inc +WMA_SRC_DIR := $(WMA_DIR)/src + +WMA_INC := -I$(WLAN_ROOT)/$(WMA_INC_DIR) \ + -I$(WLAN_ROOT)/$(WMA_SRC_DIR) + +WMA_OBJS := $(WMA_SRC_DIR)/wma_main.o \ + $(WMA_SRC_DIR)/wma_scan_roam.o \ + $(WMA_SRC_DIR)/wma_dev_if.o \ + $(WMA_SRC_DIR)/wma_mgmt.o \ + $(WMA_SRC_DIR)/wma_power.o \ + $(WMA_SRC_DIR)/wma_data.o \ + $(WMA_SRC_DIR)/wma_utils.o \ + $(WMA_SRC_DIR)/wma_features.o \ + $(WMA_SRC_DIR)/wma_dfs_interface.o \ + $(WMA_SRC_DIR)/wma_ocb.o \ + $(WMA_SRC_DIR)/wlan_qct_wma_legacy.o + +ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y) +WMA_OBJS += $(WMA_SRC_DIR)/wma_utils_ut.o +endif + +TARGET_INC := -I$(WLAN_ROOT)/target/inc + +LINUX_INC := -Iinclude/linux + +INCS := $(HDD_INC) \ + $(EPPING_INC) \ + $(LINUX_INC) \ + $(MAC_INC) \ + $(SAP_INC) \ + $(SME_INC) \ + $(SYS_INC) \ + $(CDF_INC) \ + $(CDS_INC) \ + $(DFS_INC) + +INCS += $(WMA_INC) \ + $(UAPI_INC) \ + $(COMMON_INC) \ + $(WMI_INC) \ + $(FWLOG_INC) \ + $(TXRX_INC) \ + $(OL_INC) \ + $(PKTLOG_INC) \ + $(HTT_INC) \ + $(HTC_INC) \ + $(DFS_INC) + +INCS += $(HIF_INC) \ + $(BMI_INC) + +INCS += $(TARGET_INC) + +INCS += $(NLINK_INC) \ + $(PTT_INC) \ + $(WLAN_LOGGING_INC) + +ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) +INCS += $(PKTLOG_INC) +endif + +ifeq ($(BUILD_DIAG_VERSION), 1) +INCS += $(HOST_DIAG_LOG_INC) +endif + +OBJS := $(HDD_OBJS) \ + $(EPPING_OBJS) \ + $(MAC_OBJS) \ + $(SAP_OBJS) \ + $(SME_OBJS) \ + $(SYS_OBJS) \ + $(CDF_OBJS) \ + $(CDS_OBJS) \ + $(DFS_OBJS) + +OBJS += $(WMA_OBJS) \ + $(TXRX_OBJS) \ + $(WMI_OBJS) \ + $(FWLOG_OBJS) \ + $(HTC_OBJS) \ + $(DFS_OBJS) + +OBJS += $(HIF_OBJS) \ + $(BMI_OBJS) \ + $(HTT_OBJS) + +OBJS += $(WLAN_LOGGING_OBJS) +OBJS += $(NLINK_OBJS) +OBJS += $(PTT_OBJS) + +ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) +OBJS += $(PKTLOG_OBJS) +endif + +ifeq ($(BUILD_DIAG_VERSION), 1) +OBJS += $(HOST_DIAG_LOG_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 \ + -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_SOFTAP_VSTA_FEATURE \ + -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 \ + -DWLAN_FEATURE_MBSSID \ + -DCONFIG_160MHZ_SUPPORT + +ifeq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) +CDEFINES += -DQCA_WIFI_3_0 +CDEFINES += -DQCA_WIFI_3_0_EMU +endif + +ifeq (y,$(filter y,$(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) +CDEFINES += -DQCA_WIFI_3_0_ADRASTEA +CDEFINES += -DADRASTEA_SHADOW_REGISTERS +endif + +ifeq ($(CONFIG_WLAN_FASTPATH), y) +CDEFINES += -DWLAN_FEATURE_FASTPATH +endif + +ifeq ($(CONFIG_WLAN_NAPI), y) +CDEFINES += -DFEATURE_NAPI +ifeq ($(CONFIG_WLAN_NAPI_DEBUG), y) +CDEFINES += -DFEATURE_NAPI_DEBUG +endif +endif + +ifeq ($(CONFIG_FEATURE_BMI_2), y) +CDEFINES += -DFEATURE_BMI_2 +endif + +ifeq ($(CONFIG_ARCH_MSM), y) +CDEFINES += -DMSM_PLATFORM +endif + +CDEFINES += -DQCA_SUPPORT_TXRX_LOCAL_PEER_ID + +ifeq ($(CONFIG_WLAN_TX_FLOW_CONTROL_V2), y) +CDEFINES += -DQCA_LL_TX_FLOW_CONTROL_V2 +CDEFINES += -DQCA_LL_TX_FLOW_GLOBAL_MGMT_POOL +else +ifeq ($(CONFIG_ROME_IF),pci) +CDEFINES += -DQCA_LL_LEGACY_TX_FLOW_CONTROL +endif +endif + +ifeq ($(CONFIG_DEBUG_LL),y) +CDEFINES += -DQCA_PKT_PROTO_TRACE +endif + +ifneq ($(CONFIG_QCA_CLD_WLAN),) +CDEFINES += -DWCN_PRONTO +CDEFINES += -DWCN_PRONTO_V1 +endif + +ifeq ($(BUILD_DEBUG_VERSION),1) +CDEFINES += -DWLAN_DEBUG \ + -DTRACE_RECORD \ + -DLIM_TRACE_RECORD \ + -DSME_TRACE_RECORD \ + -DHDD_TRACE_RECORD \ + -DPE_DEBUG_LOGW \ + -DPE_DEBUG_LOGE \ + -DDEBUG +endif + +ifeq ($(CONFIG_SLUB_DEBUG_ON),y) +CDEFINES += -DTIMER_MANAGER +CDEFINES += -DMEMORY_DEBUG +endif + +ifeq ($(HAVE_CFG80211),1) +CDEFINES += -DWLAN_FEATURE_P2P +CDEFINES += -DWLAN_FEATURE_WFD +ifeq ($(CONFIG_QCOM_VOWIFI_11R),y) +CDEFINES += -DKERNEL_SUPPORT_11R_CFG80211 +CDEFINES += -DUSE_80211_WMMTSPEC_FOR_RIC +endif +endif + +ifeq ($(CONFIG_QCOM_ESE),y) +CDEFINES += -DFEATURE_WLAN_ESE +CDEFINES += -DQCA_COMPUTE_TX_DELAY +CDEFINES += -DQCA_COMPUTE_TX_DELAY_PER_TID +ifeq ($(CONFIG_QCOM_ESE_UPLOAD),y) +CDEFINES += -DFEATURE_WLAN_ESE_UPLOAD +endif +endif + +#normally, TDLS negative behavior is not needed +ifeq ($(CONFIG_QCOM_TDLS),y) +CDEFINES += -DFEATURE_WLAN_TDLS +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 +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 ($(WLAN_OPEN_SOURCE), 1) +CDEFINES += -DWLAN_OPEN_SOURCE +endif + +ifeq ($(CONFIG_FEATURE_STATS_EXT), 1) +CDEFINES += -DWLAN_FEATURE_STATS_EXT +endif + +ifeq ($(CONFIG_QCACLD_FEATURE_NAN),y) +CDEFINES += -DWLAN_FEATURE_NAN +endif + +ifeq ($(CONFIG_QCA_IBSS_SUPPORT), 1) +CDEFINES += -DQCA_IBSS_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 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 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 +endif + +ifneq ($(CONFIG_ARCH_MDM9630), y) +ifeq ($(CONFIG_ARCH_MDM9640), y) +CDEFINES += -DQCA_CONFIG_SMP +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 + +ifeq ($(CONFIG_WLAN_FEATURE_RX_WAKELOCK), y) +CDEFINES += -DWLAN_FEATURE_HOLD_RX_WAKELOCK +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 + +#enable wlan auto shutdown feature +CDEFINES += -DFEATURE_WLAN_AUTO_SHUTDOWN + +#enable for MBSSID +CDEFINES += -DWLAN_FEATURE_MBSSID + +#enable AP-AP ACS Optimization +CDEFINES += -DFEATURE_WLAN_AP_AP_ACS_OPTIMIZE + +#Enable 4address scheme +CDEFINES += -DFEATURE_WLAN_STA_4ADDR_SCHEME + +#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 + +#Green AP feature +ifeq ($(CONFIG_QCACLD_FEATURE_GREEN_AP),y) +CDEFINES += -DFEATURE_GREEN_AP +endif + +#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_FEATURE_SECURE_FIRMWARE), 1) +CDEFINES += -DFEATURE_SECURE_FIRMWARE +endif + +ifeq ($(CONFIG_ATH_PCIE_ACCESS_DEBUG), 1) +CDEFINES += -DCONFIG_ATH_PCIE_ACCESS_DEBUG +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 + +# NOTE: CONFIG_64BIT_PADDR requires CONFIG_HELIUMPLUS +ifeq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) +CONFIG_HELIUMPLUS := y +CONFIG_64BIT_PADDR := y +CONFIG_FEATURE_TSO := y +CONFIG_FEATURE_TSO_DEBUG := y +ifeq ($(CONFIG_HELIUMPLUS),y) +CDEFINES += -DHELIUMPLUS_PADDR64 +CDEFINES += -DHELIUMPLUS +ifeq ($(CONFIG_64BIT_PADDR),y) +CDEFINES += -DHTT_PADDR64 +endif +endif +endif + +ifeq ($(CONFIG_FEATURE_TSO),y) +CDEFINES += -DFEATURE_TSO +endif +ifeq ($(CONFIG_FEATURE_TSO_DEBUG),y) +CDEFINES += -DFEATURE_TSO_DEBUG +endif + +ifeq ($(CONFIG_WLAN_LRO), y) +CDEFINES += -DFEATURE_LRO +endif + +ifeq ($(CONFIG_MOBILE_ROUTER), y) +CDEFINES += -DFEATURE_AP_MCC_CH_AVOIDANCE +endif + +ifeq ($(CONFIG_MPC_UT_FRAMEWORK), y) +CDEFINES += -DMPC_UT_FRAMEWORK +endif + +ifeq ($(CONFIG_WLAN_OFFLOAD_PACKETS),y) +CDEFINES += -DWLAN_FEATURE_OFFLOAD_PACKETS +endif + +ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) +CDEFINES += -DWLAN_FEATURE_MEMDUMP +endif + +ifeq ($(CONFIG_STATICALLY_ADD_11P_CHANNELS),y) +CDEFINES += -DFEATURE_STATICALLY_ADD_11P_CHANNELS +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/Kconfig b/Kconfig new file mode 100644 index 000000000000..9cf8e1d9d01e --- /dev/null +++ b/Kconfig @@ -0,0 +1,110 @@ +comment "Qualcomm Atheros CLD WLAN module" + +config QCA_CLD_WLAN + + tristate "Qualcomm Atheros CLD WLAN module" + default n + help + Add support for the Qualcomm Atheros CLD WLAN module + +if QCA_CLD_WLAN != n + +config QCACLD_WLAN_LFR3 + bool "Enable the WLAN Legacy Fast Roaming feature Version 3" + default n + +config PRIMA_WLAN_OKC + bool "Enable the Prima WLAN Opportunistic Key Caching feature" + default n + +config PRIMA_WLAN_11AC_HIGH_TP + bool "Enable the Prima WLAN 802.11ac High Throughput option (depends upon kernel support)" + default n + +config WLAN_FEATURE_11W + bool "Enable the WLAN 802.11w Protected Management Frames feature" + default n + +config WLAN_FEATURE_LPSS + bool "Enable the WLAN LPSS feature" + default n + +config QCOM_VOWIFI_11R + bool "Enable Fast Transition (11r) feature" + default n + +config QCACLD_FEATURE_NAN + bool "Enable NAN feature" + default n + +config QCACLD_FEATURE_GREEN_AP + bool "Enable Green AP feature" + default n + +config HELIUMPLUS + bool "Enable Beeliner based descriptor structures for Helium" + default n + +config 64BIT_PADDR + bool "Enable 37-bit physical/bus addresses" + depends on HELIUMPLUS + default n + +config QCOM_TDLS + bool "Enable TDLS feature" + default n + +config QCOM_LTE_COEX + bool "Enable QCOM LTE Coex feature" + default n + +config MPC_UT_FRAMEWORK + bool "Enable Unit test framework for multiport concurrency" + default n + +config WLAN_OFFLOAD_PACKETS + bool "Enable offload packets feature" + default n + +config WLAN_FEATURE_MEMDUMP + bool "Enable MEMDUMP feature" + default n + +config FEATURE_TSO + bool "Enable TCP Segmentation Offload" + depends on HELIUMPLUS + default n + +config FEATURE_TSO_DEBUG + bool "Enable TCP Segmentation Offload with debug" + depends on FEATURE_TSO + default n + +config WLAN_FASTPATH + bool "Enable fastpath for datapackets" + default n + +config WLAN_NAPI + bool "Enable NAPI - datapath rx" + default n + +config WLAN_NAPI_DEBUG + bool "Enable debug logging on NAPI" + depends on WLAN_NAPI + default n + +config WLAN_TX_FLOW_CONTROL_V2 + bool "Enable tx flow control version:2" + default n + +config WLAN_LRO + bool "Enable Large Receive Offload" + depends on HELIUMPLUS + depends on CONFIG_INET_LRO + default n + +config WLAN_FEATURE_RX_WAKELOCK + bool "Enable RX wake lock feature" + default n + +endif # QCA_CLD_WLAN diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..914198392f79 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build + +KBUILD_OPTIONS := WLAN_ROOT=$(PWD) +KBUILD_OPTIONS += MODNAME=wlan + +#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 += $(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/README.txt b/README.txt new file mode 100644 index 000000000000..bdf3e7a7adc4 --- /dev/null +++ b/README.txt @@ -0,0 +1 @@ +This is CNSS WLAN Host Driver for products starting from iHelium diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini new file mode 100644 index 000000000000..3deddd75a766 --- /dev/null +++ b/config/WCNSS_qcom_cfg.ini @@ -0,0 +1,591 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan + +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only +# 7 = 11b only 8 = 11ac only. +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=0 + +InfraUapsdViSrvIntv=0 + +InfraUapsdBeSrvIntv=0 + +InfraUapsdBkSrvIntv=0 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +# WAPIIsEnabled=0 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=3 + + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + +#Flag to enable HostNSOffload feature or not + +hostNSOffload=1 + +# This flag enables IP, TCP and UDP checksum offload +gEnableIpTcpUdpChecksumOffload=1 + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=1048576 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=1 + +# 802.11h support + +g11hSupportEnabled=1 + +# DFS Master Capability +gEnableDFSMasterCap=1 + +# ESE Support and fast transition +EseEnabled=1 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-ESE, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=3 + +# If the RSSI of any available candidate is better than currently associated +# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without +# registering for reassoc threshold). +# NOTE: Value of 0 means that we would register for reassoc threshold. +gImmediateRoamRssiDiff=10 + +# To enable, set gRoamIntraBand=1 (Roaming within band) +# To disable, set gRoamIntraBand=0 (Roaming across band) +gRoamIntraBand=0 + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + +#Auto Shutdown wlan : Value in Seconds. 0 means disabled. Max 1 day = 86400 sec +gWlanAutoShutdown = 0 + +# Not used. +gApAutoChannelSelection=0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=0 + +beaconEarlyTerminationWakeInterval=3 + + +#Channel Bonding +gChannelBondingMode5GHz=1 + + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod = 30 + +#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). +#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) +#For both active and power save clients. + +#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. +#If doesn't honor for 5 seconds then DUT remove client. + +#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on +#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. +#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. + +#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period +#where we send NULL frame. + +#gApLinkMonitorPeriod = 10 + +#gGoLinkMonitorPeriod = 10 + +#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. +#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. + + +gGoKeepAlivePeriod = 20 + +gApKeepAlivePeriod = 20 + + +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + +# Enable DFS channel roam +# 0: DISABLE, 1: ENABLED_NORMAL, 2: ENABLED_ACTIVE +gAllowDFSChannelRoam=1 + +gVhtChannelWidth=2 +gEnableLogp=1 + + +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=1 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=2 + +# VHT Tx/Rx MCS values for 2x2 +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gEnable2x2=1 +gVhtRxMCS2x2=2 +gVhtTxMCS2x2=2 + +# Set txchainmask and rxchainmask +# These parameters are used only if gEnable2x2 is 0 +# Valid values are 1,2 +# Set gSetTxChainmask1x1=1 or gSetRxChainmask1x1=1 to select chain0. +# Set gSetTxChainmask1x1=2 or gSetRxChainmask1x1=2 to select chain1. +gSetTxChainmask1x1=1 +gSetRxChainmask1x1=1 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +gActiveMaxChannelTime=40 +gActiveMinChannelTime=20 + +#If set to 0, MCC is not allowed. +gEnableMCCMode=1 + +# MCC to SCC Switch mode: 0-Disable 1-Enable 2-Force SCC if same band +gWlanMccToSccSwitchMode = 0 + +# 1=enable STBC; 0=disable STBC +gEnableRXSTBC=1 + +# 1=enable tx STBC; 0=disable +gEnableTXSTBC=1 + +# 1=enable rx LDPC; 0=disable +gEnableRXLDPC=1 + +#Enable/Disable Tx beamforming +gTxBFEnable=1 + +# Enable Tx beamforming in VHT20MHz +# Valid values are 0,1. If commented out, the default value is 0. +# 0=disable, 1=enable +gEnableTxBFin20MHz=1 + +#Enable/Disable SU Tx beamformer support. +gEnableTxSUBeamformer=1 + +#Enable Scan Results Aging based on timer +#Timer value is in seconds +#If Set to 0 it will not enable the feature +gScanAgingTime=30 + +#Enable Scan Results Aging based on number of scans +gScanResultAgeCount=1 + +#Enable Power saving mechanism Based on Android Framework +#If set to 0 Driver internally control the Power saving mechanism +#If set to 1 Android Framwrok control the Power saving mechanism +isAndroidPsEn=0 + +#Enable thermal mitigation +gThermalMitigationEnable=0 + +gEnableFastRoamInConcurrency=1 + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=1 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +#Disable split scan, the FW will take care of it +gNumChanCombinedConc=60 + +#Enable Power Save offload +gEnablePowerSaveOffload=2 + +#Enable firmware uart print +gEnablefwprint=0 + +#Enable firmware log +gEnablefwlog=1 + +#IPA config +gIPAConfig=0 +gIPADescSize=800 +gIPAPreFilterEnable=1 +gIPARMEnable=1 +gIPAIPv6Enable=1 + +IpaUcOffloadEnabled=0 +gIpaUcStaOffload=0 + +#P2P Listen offload +gEnableP2pListenOffload=1 + +# Maximum Receive AMPDU size (VHT only. Valid values: 0->8k 1->16k 2->32k 3->64k 4->128k) +gVhtAmpduLenExponent=7 + +# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) +gVhtMpduLen=2 + +# Maximum number of wow filters required +#gMaxWoWFilters=22 + +# WOW Enable/Disable. +# 0 - Disable both magic pattern match and pattern byte match. +# 1 - Enable magic pattern match on all interfaces. +# 2 - Enable pattern byte match on all interfaces. +# 3 - Enable both magic patter and pattern byte match on all interfaces. +# Default value of gEnableWoW is 3. +# gEnableWoW=0 + +# Enable or Disable MCC Adaptive Scheduler at the FW +# 1=Enable (default), 0=Disable +gEnableMCCAdaptiveScheduler=1 + +#Enable or Disable p2p device address administered +isP2pDeviceAddrAdministrated=0 + +#Enable Rx thread +gEnableRxThread=1 + +#Enable NAPI +gEnableNAPI=0 + +# Set Thermal Power limit +TxPower2g=10 +TxPower5g=10 + +# Remove Overlap channel restriction +gEnableOverLapCh=0 + +#Enable VHT on 2.4Ghz +gEnableVhtFor24GHzBand=1 + +#Enable or Disable 5G early beacon termination +gEnable5gEBT=1 + +#Maximum number of offload peers supported +# gMaxOffloadPeers=2 + +# controlling the following offload patterns +# through ini parameter. Default value is 1 +# to disable set it to zero. ssdp = 0 +# Setup multicast pattern for mDNS 224.0.0.251, +# SSDP 239.255.255.250 and LLMNR 224.0.0.252 +ssdp = 0 + +#Enable Memory Deep Sleep +gEnableMemDeepSleep=1 + +# Bus bandwidth threshold values in terms of number of packets +gBusBandwidthHighThreshold=2000 +gBusBandwidthMediumThreshold=500 +gBusBandwidthLowThreshold=150 + +# Bus bandwidth compute timeout value in ms +gBusBandwidthComputeInterval=100 + +# Regulatory Setting; 0=STRICT; 1=CUSTOM +gRegulatoryChangeCountry=1 +# RA filtering rate limit param, the current value would not +# help if the lifetime in RA is less than 3*60=3min. Then +# we need to change it, though it is uncommon. +# gRAFilterEnable=0 +gRArateLimitInterval=600 + +# Maximum number of concurrent connections +gMaxConcurrentActiveSessions=2 + +# Disable/Enable GreenAP +# 0 to disable, 1 to enable, default: 1 +gEnableGreenAp=1 + +# Radar PRI multiplier +gDFSradarMappingPriMultiplier=4 + +gPNOScanSupport=1 + +# Enable/Disable RX full reorder offload +gReorderOffloadSupported=1 + +#Enable/Disable LPASS support +# 0 to disable, 1 to enable +gEnableLpassSupport=0 + +# Whether userspace country code setting shld have priority +gCountryCodePriority=1 + +# Enable(1)/Disable(0) SIFS burst +gEnableSifsBurst=1 + +# Enable or Disable Multi-user MIMO +# 1=Enable (default), 0=Disable +gEnableMuBformee=1 + +# Enable/Disable channel avoidance for SAP in SCC scenario +# 0 - disable +# 1 - enable +gSapSccChanAvoidance=0 + +# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode +gIbssTxSpEndInactivityTime=10 + +# Enable/Disable Roaming Offload Support (a.k.a Key Management Offload) +# 0 to disable, 1 to enable +gRoamOffloadEnabled=0 + +# Enable support for TDLS +# 0 - disable +# 1 - enable +gEnableTDLSSupport=1 + +# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall +# initiate TDLS Discovery towards a peer whenever setup criteria (throughput +# and RSSI) is met and then will initiate teardown when teardown criteria +# (idle packet count and RSSI) is met. +# 0 - disable +# 1 - enable +gEnableTDLSImplicitTrigger=1 + +# Enable TDLS External Control. That is, user space application has to +# first configure a peer MAC in wlan driver towards which TDLS is desired. +# Device will establish TDLS only towards those configured peers whenever +# TDLS criteria (throughput and RSSI threshold) is met and teardown TDLS +# when teardown criteria (idle packet count and RSSI) is met. However, +# device will accept TDLS connection if it is initiated from any other peer, +# even if that peer is not configured. +# 0 - disable +# 1 - enable +# For TDLS External Control, Implicit Trigger must also be enabled. +gTDLSExternalControl=1 + +# Enable support for TDLS off-channel operation +# 0 - disable +# 1 - enable +# TDLS off-channel operation will be invoked when there is only one +# TDLS connection. +gEnableTDLSOffChannel=1 + +# Enable or Disable Random MAC (Spoofing) +# 1=Enable, 0=Disable (default) +gEnableMacAddrSpoof=0 + +END + +# Note: Configuration parser would not read anything past the END marker + diff --git a/core/bmi/inc/bmi.h b/core/bmi/inc/bmi.h new file mode 100644 index 000000000000..4548fd711160 --- /dev/null +++ b/core/bmi/inc/bmi.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +/* ================================================================ */ +/* BMI declarations and prototypes */ +/* */ +/* ================================================================= */ + +#ifndef _BMI_H_ +#define _BMI_H_ +#include "bmi_msg.h" +#include "cdf_trace.h" +#include "ol_if_athvar.h" +#include "hif.h" + +#ifdef HIF_PCI +void bmi_cleanup(struct ol_softc *scn); +CDF_STATUS bmi_done(struct ol_softc *scn); +CDF_STATUS bmi_download_firmware(struct ol_softc *scn); +#else +static inline void bmi_cleanup(struct ol_softc *scn) +{ + return; +} + +static inline CDF_STATUS bmi_done(struct ol_softc *scn) +{ + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS bmi_download_firmware(struct ol_softc *scn) +{ + return CDF_STATUS_SUCCESS; +} +#endif +#endif /* _BMI_H_ */ diff --git a/core/bmi/inc/ol_fw.h b/core/bmi/inc/ol_fw.h new file mode 100644 index 000000000000..a9918d7cd82c --- /dev/null +++ b/core/bmi/inc/ol_fw.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. + */ + +#ifndef _OL_FW_H_ +#define _OL_FW_H_ + +#ifdef QCA_WIFI_FTM +#include "cdf_types.h" +#endif +#include "hif.h" + +#define AR6004_VERSION_REV1_3 0x31c8088a + +#define AR9888_REV2_VERSION 0x4100016c +#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 AR6320_REV3_2_VERSION 0x5030000 +#define AR6320_REV4_VERSION AR6320_REV2_1_VERSION +#define AR6320_DEV_VERSION 0x1000000 + +#ifdef HIF_PCI +void ol_target_failure(void *instance, CDF_STATUS status); +uint8_t ol_get_number_of_peers_supported(struct ol_softc *scn); +#else +static inline void ol_target_failure(void *instance, CDF_STATUS status) +{ + return; +} + +static inline uint8_t ol_get_number_of_peers_supported(struct ol_softc *scn) +{ + return 1; +} +#endif +#endif /* _OL_FW_H_ */ diff --git a/core/bmi/inc/ol_if_athvar.h b/core/bmi/inc/ol_if_athvar.h new file mode 100644 index 000000000000..c820cbe2f006 --- /dev/null +++ b/core/bmi/inc/ol_if_athvar.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + +/* + * Defintions for the Atheros Wireless LAN controller driver. + */ +#ifndef _DEV_OL_ATH_ATHVAR_H +#define _DEV_OL_ATH_ATHVAR_H + +#include +#include "cdf_types.h" +#include "cdf_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 { + uint32_t host_ver; + uint32_t target_ver; + uint32_t wlan_ver; + uint32_t wlan_ver_1; + uint32_t abi_ver; +}; + +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 +}; + +/* + * 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; +}; + +#endif /* _DEV_OL_ATH_ATHVAR_H */ diff --git a/core/bmi/src/bmi.c b/core/bmi/src/bmi.c new file mode 100644 index 000000000000..7104619faffe --- /dev/null +++ b/core/bmi/src/bmi.c @@ -0,0 +1,470 @@ +/* + * 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. + */ + +#include "i_bmi.h" + +/* APIs visible to the driver */ + +/* BMI_1 refers QCA6174 target; the ADDR is AXI addr */ +#define BMI_1_TEST_ADDR (0xa0000) +/* BMI_2 ; */ +#define BMI_2_TEST_ADDR (0x6E0000) +/* Enable BMI_TEST COMMANDs; The Value 0x09 is randomly choosen */ +#define BMI_TEST_ENABLE (0x09) + +static CDF_STATUS +bmi_command_test(uint32_t command, uint32_t address, uint8_t *data, + uint32_t length, struct ol_softc *scn) +{ + switch (command) { + case BMI_NO_COMMAND: + return bmi_no_command(scn); + case BMI_WRITE_MEMORY: + return bmi_write_memory(address, data, length, scn); + case BMI_READ_MEMORY: + return bmi_read_memory(address, data, length, scn); + case BMI_EXECUTE: + return bmi_execute(address, (uint32_t *)data, scn); + default: + break; + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS bmi_init(struct ol_softc *scn) +{ + if (!scn) { + BMI_ERR("Invalid scn Context"); + bmi_assert(0); + return CDF_STATUS_NOT_INITIALIZED; + } + scn->bmi_done = false; + + if (!scn->bmi_cmd_buff) { + scn->bmi_cmd_buff = cdf_os_mem_alloc_consistent(scn->cdf_dev, + MAX_BMI_CMDBUF_SZ, &scn->bmi_cmd_da, 0); + if (!scn->bmi_cmd_buff) { + BMI_ERR("No Memory for BMI Command"); + return CDF_STATUS_E_NOMEM; + } + } + + if (!scn->bmi_rsp_buff) { + scn->bmi_rsp_buff = cdf_os_mem_alloc_consistent(scn->cdf_dev, + MAX_BMI_CMDBUF_SZ, &scn->bmi_rsp_da, 0); + if (!scn->bmi_rsp_buff) { + BMI_ERR("No Memory for BMI Response"); + goto end; + } + } + return CDF_STATUS_SUCCESS; +end: + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_cmd_buff, scn->bmi_cmd_da, 0); + scn->bmi_cmd_buff = NULL; + return CDF_STATUS_E_NOMEM; +} + +void bmi_cleanup(struct ol_softc *scn) +{ + if (scn->bmi_cmd_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_cmd_buff, scn->bmi_cmd_da, 0); + scn->bmi_cmd_buff = NULL; + scn->bmi_cmd_da = 0; + } + + if (scn->bmi_rsp_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_rsp_buff, scn->bmi_rsp_da, 0); + scn->bmi_rsp_buff = NULL; + scn->bmi_rsp_da = 0; + } +} + + +CDF_STATUS bmi_done(struct ol_softc *scn) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + hif_claim_device(scn, scn); + + if (IHELIUM_NO_BMI) + return status; + + status = bmi_done_local(scn); + + if (status != CDF_STATUS_SUCCESS) + BMI_ERR("BMI_DONE Failed status:%d", status); + return status; +} + +CDF_STATUS +bmi_get_target_info(struct bmi_target_info *targ_info, + struct ol_softc *scn) +{ + int status = 0; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + uint32_t cid, length; + + if (scn->bmi_done) { + BMI_ERR("BMI Phase is Already Done"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("%s:BMI CMD/RSP Buffer is NULL", __func__); + return CDF_STATUS_NOT_INITIALIZED; + } + cid = BMI_GET_TARGET_INFO; + + cdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); + length = sizeof(struct bmi_target_info); + + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, sizeof(cid), + (uint8_t *)bmi_rsp_buff, &length, + BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_ERR("Failed to target info: status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(targ_info, bmi_rsp_buff, length); + return CDF_STATUS_SUCCESS; +} + +#ifdef FEATURE_BMI_2 +static inline uint32_t bmi_get_test_addr(void) +{ + return BMI_2_TEST_ADDR; +} +#else +static inline uint32_t bmi_get_test_addr(void) +{ + return BMI_1_TEST_ADDR; +} +#endif + +CDF_STATUS bmi_download_firmware(struct ol_softc *scn) +{ + uint8_t data[10], out[10]; + uint32_t address; + int32_t ret; + + if (IHELIUM_NO_BMI) + return CDF_STATUS_SUCCESS; /* no BMI for Q6 bring up */ + + if (!scn) { + BMI_ERR("Invalid scn context"); + bmi_assert(0); + return CDF_STATUS_NOT_INITIALIZED; + } +#ifdef CONFIG_CNSS + if (BMI_TEST_ENABLE == cnss_get_bmi_setup()) { + ret = snprintf(data, 10, "ABCDEFGHI"); + BMI_DBG("ret:%d writing data:%s\n", ret, data); + address = bmi_get_test_addr(); + + if (bmi_init(scn) != CDF_STATUS_SUCCESS) { + BMI_WARN("BMI_INIT Failed; No Memory!"); + goto end; + } + bmi_command_test(BMI_NO_COMMAND, address, data, 9, scn); + bmi_command_test(BMI_WRITE_MEMORY, address, data, 9, scn); + bmi_command_test(BMI_READ_MEMORY, address, out, 9, scn); + BMI_DBG("Output:%s", out); + } +#endif +end: + return bmi_firmware_download(scn); +} + +CDF_STATUS +bmi_read_soc_register(uint32_t address, uint32_t *param, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset, param_len; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + + bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + cdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address)); + cdf_mem_set(bmi_rsp_buff, 0, sizeof(cid) + sizeof(address)); + + if (scn->bmi_done) { + BMI_DBG("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + BMI_DBG("BMI Read SOC Register:device: 0x%p, address: 0x%x", + scn, address); + + cid = BMI_READ_SOC_REGISTER; + + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address)); + offset += sizeof(address); + param_len = sizeof(*param); + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + bmi_rsp_buff, ¶m_len, BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_DBG("Unable to read from the device; status:%d", status); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(param, bmi_rsp_buff, sizeof(*param)); + + BMI_DBG("BMI Read SOC Register: Exit value: %d", *param); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_write_soc_register(uint32_t address, uint32_t param, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint32_t size = sizeof(cid) + sizeof(address) + sizeof(param); + bmi_assert(BMI_COMMAND_FITS(size)); + cdf_mem_set(bmi_cmd_buff, 0, size); + + if (scn->bmi_done) { + BMI_DBG("Command disallowed"); + return CDF_STATUS_E_FAILURE; + } + + BMI_DBG("SOC Register Write:device:0x%p, addr:0x%x, param:%d", + scn, address, param); + + cid = BMI_WRITE_SOC_REGISTER; + + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), ¶m, sizeof(param)); + offset += sizeof(param); + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + NULL, NULL, 0); + if (status) { + BMI_ERR("Unable to write to the device: status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + BMI_DBG("BMI Read SOC Register: Exit"); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmilz_data(uint8_t *buffer, uint32_t length, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint32_t remaining, txlen; + const uint32_t header = sizeof(cid) + sizeof(length); + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header); + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + BMI_DBG("BMI Send LZ Data: device: 0x%p, length: %d", + scn, length); + + cid = BMI_LZ_DATA; + + remaining = length; + while (remaining) { + txlen = (remaining < (BMI_DATASZ_MAX - header)) ? + remaining : (BMI_DATASZ_MAX - header); + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + cdf_mem_copy(&(bmi_cmd_buff[offset]), + &buffer[length - remaining], txlen); + offset += txlen; + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + NULL, NULL, 0); + if (status) { + BMI_ERR("Failed to write to the device: status:%d", + status); + return CDF_STATUS_E_FAILURE; + } + remaining -= txlen; + } + + BMI_DBG("BMI LZ Data: Exit"); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_sign_stream_start(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + const uint32_t header = sizeof(cid) + sizeof(address) + sizeof(length); + uint8_t aligned_buf[BMI_DATASZ_MAX + 4]; + uint8_t *src; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint32_t remaining, txlen; + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header); + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + BMI_ERR("Sign Stream start:device:0x%p, addr:0x%x, length:%d", + scn, address, length); + + cid = BMI_SIGN_STREAM_START; + remaining = length; + while (remaining) { + src = &buffer[length - remaining]; + if (remaining < (BMI_DATASZ_MAX - header)) { + if (remaining & 0x3) { + remaining = remaining + (4 - (remaining & 0x3)); + memcpy(aligned_buf, src, remaining); + src = aligned_buf; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, + sizeof(address)); + offset += sizeof(offset); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + cdf_mem_copy(&(bmi_cmd_buff[offset]), src, txlen); + offset += txlen; + status = hif_exchange_bmi_msg(scn, + bmi_cmd_buff, offset, + NULL, NULL, BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_ERR("Unable to write to the device: status:%d", + status); + return CDF_STATUS_E_FAILURE; + } + remaining -= txlen; + } + BMI_DBG("BMI SIGN Stream Start: Exit"); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmilz_stream_start(uint32_t address, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + + bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + cdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address)); + + if (scn->bmi_done) { + BMI_DBG("Command disallowed"); + return CDF_STATUS_E_PERM; + } + BMI_DBG("BMI LZ Stream Start: (device: 0x%p, address: 0x%x)", + scn, address); + + cid = BMI_LZ_STREAM_START; + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address)); + offset += sizeof(address); + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + NULL, NULL, 0); + if (status) { + BMI_ERR("Unable to Start LZ Stream to the device status:%d", + status); + return CDF_STATUS_E_FAILURE; + } + BMI_DBG("BMI LZ Stream: Exit"); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_fast_download(uint32_t address, uint8_t *buffer, + uint32_t length, struct ol_softc *scn) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t last_word = 0; + uint32_t last_word_offset = length & ~0x3; + uint32_t unaligned_bytes = length & 0x3; + + status = bmilz_stream_start(address, scn); + if (status != CDF_STATUS_SUCCESS) + goto end; + + /* copy the last word into a zero padded buffer */ + if (unaligned_bytes) + cdf_mem_copy(&last_word, &buffer[last_word_offset], + unaligned_bytes); + + status = bmilz_data(buffer, last_word_offset, scn); + + if (status != CDF_STATUS_SUCCESS) + goto end; + + if (unaligned_bytes) + status = bmilz_data((uint8_t *) &last_word, 4, scn); + + if (status != CDF_STATUS_SUCCESS) + /* + * Close compressed stream and open a new (fake) one. + * This serves mainly to flush Target caches. + */ + status = bmilz_stream_start(0x00, scn); +end: + return status; +} + diff --git a/core/bmi/src/bmi_1.c b/core/bmi/src/bmi_1.c new file mode 100644 index 000000000000..2d0783a5a41a --- /dev/null +++ b/core/bmi/src/bmi_1.c @@ -0,0 +1,321 @@ +/* + * 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. + */ + +#include "i_bmi.h" + +/* APIs visible to the driver */ + +CDF_STATUS +bmi_read_memory(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint32_t remaining, rxlen; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + uint32_t align; + + if (scn->bmi_done) { + BMI_DBG("command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!scn->bmi_cmd_buff || !scn->bmi_rsp_buff) { + BMI_ERR("BMI Initialization hasn't done"); + return CDF_STATUS_NOT_INITIALIZED; + } + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + + sizeof(address) + sizeof(length))); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + sizeof(cid) + + sizeof(address) + sizeof(length)); + cdf_mem_set(bmi_rsp_buff, 0, BMI_DATASZ_MAX + sizeof(cid) + + sizeof(address) + sizeof(length)); + + BMI_DBG("BMI Read: device: 0x%p, address: 0x%x, length: %d", + scn, address, length); + + cid = BMI_READ_MEMORY; + align = 0; + remaining = length; + + while (remaining) { + rxlen = (remaining < BMI_DATASZ_MAX) ? + remaining : BMI_DATASZ_MAX; + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, + sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &rxlen, sizeof(rxlen)); + offset += sizeof(length); + + /* note we reuse the same buffer to receive on */ + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + bmi_rsp_buff, &rxlen, BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_ERR("Unable to read from the device"); + return CDF_STATUS_E_FAILURE; + } + if (remaining == rxlen) { + cdf_mem_copy(&buffer[length - remaining + align], + bmi_rsp_buff, rxlen - align); + /* last align bytes are invalid */ + } else { + cdf_mem_copy(&buffer[length - remaining + align], + bmi_rsp_buff, rxlen); + } + remaining -= rxlen; + address += rxlen; + } + + BMI_DBG("BMI Read Memory: Exit"); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_write_memory(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint32_t remaining, txlen; + const uint32_t header = sizeof(cid) + sizeof(address) + sizeof(length); + uint8_t aligned_buffer[BMI_DATASZ_MAX]; + uint8_t *src; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff) { + BMI_ERR("BMI initialization hasn't done"); + return CDF_STATUS_E_PERM; + } + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header); + + BMI_DBG("BMI Write Memory:device: 0x%p, address: 0x%x, length: %d", + scn, 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(aligned_buffer, src, remaining); + src = aligned_buffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, + sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + cdf_mem_copy(&(bmi_cmd_buff[offset]), src, txlen); + offset += txlen; + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + NULL, NULL, BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_ERR("Unable to write to the device; status:%d", + status); + return CDF_STATUS_E_FAILURE; + } + remaining -= txlen; + address += txlen; + } + + BMI_DBG("BMI Write Memory: Exit"); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_execute(uint32_t address, A_UINT32 *param, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t offset; + uint32_t param_len; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + uint32_t size = sizeof(cid) + sizeof(address) + sizeof(param); + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("%s:BMI CMD/RSP Buffer is NULL", __func__); + return CDF_STATUS_NOT_INITIALIZED; + } + + bmi_assert(BMI_COMMAND_FITS(size)); + cdf_mem_set(bmi_cmd_buff, 0, size); + cdf_mem_set(bmi_rsp_buff, 0, size); + + + BMI_DBG("BMI Execute: device: 0x%p, address: 0x%x, param: %d", + scn, address, *param); + + cid = BMI_EXECUTE; + + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), param, sizeof(*param)); + offset += sizeof(*param); + param_len = sizeof(*param); + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + bmi_rsp_buff, ¶m_len, 0); + if (status) { + BMI_ERR("Unable to read from the device status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(param, bmi_rsp_buff, sizeof(*param)); + + BMI_DBG("BMI Execute: Exit (param: %d)", *param); + return CDF_STATUS_SUCCESS; +} + +inline CDF_STATUS +bmi_no_command(struct ol_softc *scn) +{ + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_firmware_download(struct ol_softc *scn) +{ + CDF_STATUS status; + struct bmi_target_info targ_info; + cdf_mem_zero(&targ_info, sizeof(targ_info)); + + /* Initialize BMI */ + status = bmi_init(scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI Initialization Failed err:%d", status); + return status; + } + + /* Get target information */ + status = bmi_get_target_info(&targ_info, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI Target Info get failed: status:%d", status); + return status; + } + + scn->target_type = targ_info.target_type; + scn->target_version = targ_info.target_ver; + + /* Configure target */ + status = ol_configure_target(scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI Configure Target Failed status:%d", status); + return status; + } + + status = ol_download_firmware(scn); + if (status != CDF_STATUS_SUCCESS) + BMI_ERR("BMI Download Firmware Failed Status:%d", status); + + return status; +} + +CDF_STATUS bmi_done_local(struct ol_softc *scn) +{ + int status; + uint32_t cid; + + if (!scn) { + BMI_ERR("Invalid scn context"); + bmi_assert(0); + return CDF_STATUS_NOT_INITIALIZED; + } + + if (scn->bmi_done) { + BMI_DBG("bmi_done_local skipped"); + return CDF_STATUS_E_PERM; + } + + BMI_DBG("BMI Done: Enter (device: 0x%p)", scn); + + scn->bmi_done = true; + cid = BMI_DONE; + + if (!scn->bmi_cmd_buff) { + BMI_ERR("Invalid scn BMICmdBuff"); + bmi_assert(0); + return CDF_STATUS_NOT_INITIALIZED; + } + + cdf_mem_copy(scn->bmi_cmd_buff, &cid, sizeof(cid)); + + status = hif_exchange_bmi_msg(scn, scn->bmi_cmd_buff, + sizeof(cid), NULL, NULL, 0); + if (status) { + BMI_ERR("Failed to write to the device; status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + if (scn->bmi_cmd_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_cmd_buff, scn->bmi_cmd_da, 0); + scn->bmi_cmd_buff = NULL; + scn->bmi_cmd_da = 0; + } + + if (scn->bmi_rsp_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_rsp_buff, scn->bmi_rsp_da, 0); + scn->bmi_rsp_buff = NULL; + scn->bmi_rsp_da = 0; + } + + return CDF_STATUS_SUCCESS; +} diff --git a/core/bmi/src/bmi_2.c b/core/bmi/src/bmi_2.c new file mode 100644 index 000000000000..cd8ce45bcf26 --- /dev/null +++ b/core/bmi/src/bmi_2.c @@ -0,0 +1,452 @@ +/* + * 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. + */ +#include "i_bmi.h" +/* This need to defined in firmware interface files. + * Defining here to address compilation issues. + * Will be deleted once firmware interface files for + * target are merged + */ +#define BMI_LOAD_IMAGE 18 + +CDF_STATUS +bmi_no_command(struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t length; + uint8_t ret = 0; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed: BMI DONE ALREADY"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); + return CDF_STATUS_NOT_INITIALIZED; + } + cid = BMI_NO_COMMAND; + + cdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); + length = sizeof(ret); + + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, sizeof(cid), + bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); + + if (status) { + BMI_ERR("Failed to write bmi no command status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&ret, bmi_rsp_buff, length); + if (ret != 0) { + BMI_ERR("bmi no command response error ret 0x%x", ret); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_done_local(struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t length; + uint8_t ret = 0; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); + return CDF_STATUS_NOT_INITIALIZED; + } + cid = BMI_DONE; + + cdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); + length = sizeof(ret); + + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, sizeof(cid), + bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); + + if (status) { + BMI_ERR("Failed to close BMI on target status:%d", status); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(&ret, bmi_rsp_buff, length); + + if (ret != 0) { + BMI_ERR("BMI DONE response failed:%d", ret); + return CDF_STATUS_E_FAILURE; + } + + if (scn->bmi_cmd_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_cmd_buff, scn->bmi_cmd_da, 0); + scn->bmi_cmd_buff = NULL; + scn->bmi_cmd_da = 0; + } + + if (scn->bmi_rsp_buff) { + cdf_os_mem_free_consistent(scn->cdf_dev, MAX_BMI_CMDBUF_SZ, + scn->bmi_rsp_buff, scn->bmi_rsp_da, 0); + scn->bmi_rsp_buff = NULL; + scn->bmi_rsp_da = 0; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_write_memory(uint32_t address, + uint8_t *buffer, + uint32_t length, + struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t rsp_len; + uint8_t ret = 0; + uint32_t offset; + uint32_t remaining, txlen; + const uint32_t header = sizeof(cid) + sizeof(address) + sizeof(length); + uint8_t aligned_buffer[BMI_DATASZ_MAX]; + uint8_t *src; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("BMI Initialization is not happened"); + return CDF_STATUS_NOT_INITIALIZED; + } + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header); + + cid = BMI_WRITE_MEMORY; + rsp_len = sizeof(ret); + + 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(aligned_buffer, src, remaining); + src = aligned_buffer; + } + txlen = remaining; + } else { + txlen = (BMI_DATASZ_MAX - header); + } + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, + sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen)); + offset += sizeof(txlen); + cdf_mem_copy(&(bmi_cmd_buff[offset]), src, txlen); + offset += txlen; + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + bmi_rsp_buff, &rsp_len, BMI_EXCHANGE_TIMEOUT_MS); + if (status) { + BMI_ERR("BMI Write Memory Failed status:%d", status); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(&ret, bmi_rsp_buff, rsp_len); + if (ret != 0) { + BMI_ERR("BMI Write memory response fail: %x", ret); + return CDF_STATUS_E_FAILURE; + } + remaining -= txlen; address += txlen; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_read_memory(uint32_t address, uint8_t *buffer, + uint32_t length, struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint8_t ret = 0; + uint32_t offset; + uint32_t remaining, rxlen, rsp_len, total_len; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + /* note we reuse the same buffer to receive on */ + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + uint32_t size = sizeof(cid) + sizeof(address) + sizeof(length); + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("BMI Initialization is not done"); + return CDF_STATUS_NOT_INITIALIZED; + } + + bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + size)); + cdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + size); + cdf_mem_set(bmi_rsp_buff, 0, BMI_DATASZ_MAX + size); + + cid = BMI_READ_MEMORY; + rsp_len = sizeof(ret); + remaining = length; + + while (remaining) { + rxlen = (remaining < BMI_DATASZ_MAX - rsp_len) ? remaining : + (BMI_DATASZ_MAX - rsp_len); + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &address, + sizeof(address)); + offset += sizeof(address); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &rxlen, sizeof(rxlen)); + offset += sizeof(length); + + total_len = rxlen + rsp_len; + + status = hif_exchange_bmi_msg(scn, + bmi_cmd_buff, + offset, + bmi_rsp_buff, + &total_len, + BMI_EXCHANGE_TIMEOUT_MS); + + if (status) { + BMI_ERR("BMI Read memory failed status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&ret, bmi_rsp_buff, rsp_len); + + if (ret != 0) { + BMI_ERR("bmi read memory response fail %x", ret); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&buffer[length - remaining], + (uint8_t *)bmi_rsp_buff + rsp_len, rxlen); + remaining -= rxlen; address += rxlen; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS +bmi_execute(uint32_t address, uint32_t *param, + struct ol_softc *scn) +{ + uint32_t cid; + int status; + uint32_t length; + uint8_t ret = 0; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("No Memory Allocated for bmi buffers"); + return CDF_STATUS_NOT_INITIALIZED; + } + + cid = BMI_EXECUTE; + + cdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); + length = sizeof(ret); + + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, sizeof(cid), + bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); + + if (status) { + BMI_ERR("Failed to do BMI_EXECUTE status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&ret, bmi_rsp_buff, length); + + if (ret != 0) { + BMI_ERR("%s: ret 0x%x", __func__, ret); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS +bmi_load_image(dma_addr_t address, + uint32_t size, struct ol_softc *scn) +{ + uint32_t cid; + CDF_STATUS status; + uint32_t offset; + uint32_t length; + uint8_t ret = 0; + uint8_t *bmi_cmd_buff = scn->bmi_cmd_buff; + uint8_t *bmi_rsp_buff = scn->bmi_rsp_buff; + uint32_t addr_h, addr_l; + + if (scn->bmi_done) { + BMI_ERR("Command disallowed"); + return CDF_STATUS_E_PERM; + } + + if (!bmi_cmd_buff || !bmi_rsp_buff) { + BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); + return CDF_STATUS_NOT_INITIALIZED; + } + + bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); + cdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address)); + + + BMI_DBG("%s: Enter device: 0x%p, size %d", __func__, scn, size); + + cid = BMI_LOAD_IMAGE; + + offset = 0; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); + offset += sizeof(cid); + addr_l = address & 0xffffffff; + addr_h = 0x00; + cdf_mem_copy(&(bmi_cmd_buff[offset]), &addr_l, sizeof(addr_l)); + offset += sizeof(addr_l); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &addr_h, sizeof(addr_h)); + offset += sizeof(addr_h); + cdf_mem_copy(&(bmi_cmd_buff[offset]), &size, sizeof(size)); + offset += sizeof(size); + length = sizeof(ret); + + status = hif_exchange_bmi_msg(scn, bmi_cmd_buff, offset, + bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); + + if (status) { + BMI_ERR("BMI Load Image Failed; status:%d", status); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&ret, bmi_rsp_buff, length); + if (ret != 0) { + BMI_ERR("%s: ret 0x%x", __func__, ret); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS bmi_enable(struct ol_softc *scn) +{ + struct bmi_target_info targ_info; + struct image_desc_info image_desc_info; + CDF_STATUS status; + + if (!scn) { + BMI_ERR("Invalid scn context"); + bmi_assert(0); + return CDF_STATUS_NOT_INITIALIZED; + } + + if (scn->bmi_cmd_buff == NULL || scn->bmi_rsp_buff == NULL) { + BMI_ERR("bmi_open failed!"); + return CDF_STATUS_NOT_INITIALIZED; + } + + status = bmi_get_target_info(&targ_info, scn); + if (status != CDF_STATUS_SUCCESS) + return status; + + BMI_DBG("%s: target type 0x%x, target ver 0x%x", __func__, + targ_info.target_type, targ_info.target_ver); + scn->target_type = targ_info.target_type; + scn->target_version = targ_info.target_ver; + + if (cnss_get_fw_image(&image_desc_info) != 0) { + BMI_ERR("Failed to get fw image"); + return CDF_STATUS_E_FAILURE; + } + + status = bmi_load_image(image_desc_info.bdata_addr, + image_desc_info.bdata_size, + scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Load board data failed! status:%d", status); + return status; + } + + status = bmi_load_image(image_desc_info.fw_addr, + image_desc_info.fw_size, + scn); + if (status != CDF_STATUS_SUCCESS) + BMI_ERR("Load fw image failed! status:%d", status); + + return status; +} + +CDF_STATUS bmi_firmware_download(struct ol_softc *scn) +{ + CDF_STATUS status; + + if (IHELIUM_NO_BMI) + return CDF_STATUS_SUCCESS; + + status = bmi_init(scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI_INIT Failed status:%d", status); + goto end; + } + + status = bmi_enable(scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI_ENABLE failed status:%d\n", status); + goto err_bmi_enable; + } + + return status; +err_bmi_enable: + bmi_cleanup(scn); +end: + return status; +} diff --git a/core/bmi/src/i_ar6320v2_regtable.h b/core/bmi/src/i_ar6320v2_regtable.h new file mode 100644 index 000000000000..9022e1291d29 --- /dev/null +++ b/core/bmi/src/i_ar6320v2_regtable.h @@ -0,0 +1,607 @@ +/* + * 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 _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/core/bmi/src/i_bmi.h b/core/bmi/src/i_bmi.h new file mode 100644 index 000000000000..9df099d02669 --- /dev/null +++ b/core/bmi/src/i_bmi.h @@ -0,0 +1,149 @@ +/* + * 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. + */ +/* =================================================================== + * Internal BMI Header File + */ + +#ifndef _I_BMI_H_ +#define _I_BMI_H_ + +#ifdef CONFIG_CNSS +#include +#endif + +#include "hif.h" +#include "bmi_msg.h" +#include "bmi.h" +#include "ol_fw.h" + +#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 QCA_FIRMWARE_EPPING_FILE "epping.bin" +/* + * 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 + +#define DRAM_LOCATION 0x00400000 +#define DRAM_SIZE 0x000a8000 +/* The local base addr is used to read the target dump using pcie I/O reads */ +#define DRAM_LOCAL_BASE_ADDR (0x100000) + +#define IRAM_LOCATION 0x00980000 +#define IRAM_SIZE 0x00038000 + +#define AXI_LOCATION 0x000a0000 +#define AXI_SIZE 0x00018000 + +#define CE_OFFSET 0x00000400 +#define CE_USEFUL_SIZE 0x00000058 + +#define TOTAL_DUMP_SIZE 0x00200000 +#define PCIE_READ_LIMIT 0x00005000 + +#define SHA256_DIGEST_SIZE 32 + +/* BMI LOGGING WRAPPERS */ + +#define BMI_LOG(level, args...) CDF_TRACE(CDF_MODULE_ID_BMI, \ + level, ##args) +#define BMI_ERR(args ...) BMI_LOG(CDF_TRACE_LEVEL_ERROR, args) +#define BMI_DBG(args ...) BMI_LOG(CDF_TRACE_LEVEL_DEBUG, args) +#define BMI_WARN(args ...) BMI_LOG(CDF_TRACE_LEVEL_WARN, args) +#define BMI_INFO(args ...) BMI_LOG(CDF_TRACE_LEVEL_INFO, args) +/* End of BMI Logging Wrappers */ + +/* BMI Assert Wrappers */ +#define bmi_assert CDF_BUG +/* + * 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(uint32_t) /* cmd */ + \ + sizeof(uint32_t) /* addr */ + \ + sizeof(uint32_t)) /* length */ +#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ) +#define BMI_EXCHANGE_TIMEOUT_MS 1000 + +struct hash_fw { + u8 qwlan[SHA256_DIGEST_SIZE]; + u8 otp[SHA256_DIGEST_SIZE]; + u8 bdwlan[SHA256_DIGEST_SIZE]; + u8 utf[SHA256_DIGEST_SIZE]; +}; + +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; + +#if defined(QCA_WIFI_3_0_IHELIUM) || defined(QCA_WIFI_3_0_ADRASTEA) +#define IHELIUM_NO_BMI 1 +#else +#define IHELIUM_NO_BMI 0 +#endif + +CDF_STATUS bmi_execute(uint32_t address, uint32_t *param, + struct ol_softc *scn); +CDF_STATUS bmi_init(struct ol_softc *scn); +CDF_STATUS bmi_no_command(struct ol_softc *scn); +CDF_STATUS bmi_read_memory(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn); +CDF_STATUS bmi_write_memory(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn); +CDF_STATUS bmi_fast_download(uint32_t address, + uint8_t *buffer, uint32_t length, struct ol_softc *scn); +CDF_STATUS bmi_read_soc_register(uint32_t address, + uint32_t *param, struct ol_softc *scn); +CDF_STATUS bmi_write_soc_register(uint32_t address, + uint32_t param, struct ol_softc *scn); +CDF_STATUS bmi_get_target_info( + struct bmi_target_info *targ_info, struct ol_softc *scn); + +CDF_STATUS bmi_firmware_download(struct ol_softc *scn); +CDF_STATUS bmi_done_local(struct ol_softc *scn); + +CDF_STATUS ol_download_firmware(struct ol_softc *scn); +CDF_STATUS ol_configure_target(struct ol_softc *scn); +#endif diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c new file mode 100644 index 000000000000..94488b922986 --- /dev/null +++ b/core/bmi/src/ol_fw.c @@ -0,0 +1,1637 @@ +/* + * 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. + */ + +#include +#include "ol_if_athvar.h" +#include "targaddrs.h" +#include "ol_cfg.h" +#include "cds_api.h" +#include "wma_api.h" +#include "wma.h" +#include "bin_sig.h" +#include "i_ar6320v2_regtable.h" +#include "epping_main.h" +#include "ce_reg.h" +#if defined(CONFIG_CNSS) +#include +#endif + +#include "i_bmi.h" +#include "qwlan_version.h" + +#ifdef FEATURE_SECURE_FIRMWARE +static struct hash_fw fw_hash; +#endif + +static uint32_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 */ +}; + +static int ol_target_coredump(void *inst, void *memory_block, + uint32_t block_len); +#ifdef FEATURE_SECURE_FIRMWARE +static int ol_check_fw_hash(const u8 *data, u32 fw_size, ATH_BIN_FILE file) +{ + u8 *hash = NULL; +#ifdef CONFIG_CNSS + u8 *fw_mem = NULL; + 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 (cds_get_conparam() == CDF_FTM_MODE) { + hash = fw_hash.utf; + break; + } +#endif + hash = fw_hash.qwlan; + default: + break; + } + + if (!hash) { + BMI_INFO("No entry for file:%d Download FW in non-secure mode", + file); + goto end; + } + + if (!cdf_mem_compare(hash, temp, SHA256_DIGEST_SIZE)) { + BMI_INFO("Download FW in non-secure mode:%d", file); + goto end; + } + +#ifdef CONFIG_CNSS + fw_mem = (u8 *)cnss_get_fw_ptr(); + if (!fw_mem || (fw_size > MAX_FIRMWARE_SIZE)) { + BMI_ERR("No Memory to copy FW data"); + ret = -1; + goto end; + } + cdf_mem_copy(fw_mem, data, fw_size); + + ret = cnss_get_sha_hash(fw_mem, fw_size, "sha256", digest); + + if (ret) { + BMI_ERR("Sha256 Hash computation failed err:%d", ret); + goto end; + } + + if (cdf_mem_compare(hash, digest, SHA256_DIGEST_SIZE) != 0) { + BMI_ERR("Hash Mismatch"); + cdf_trace_hex_dump(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + digest, SHA256_DIGEST_SIZE); + cdf_trace_hex_dump(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + hash, SHA256_DIGEST_SIZE); + ret = CDF_STATUS_E_FAILURE; + } +#endif +end: + return ret; +} +#endif + +static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + uint32_t address, bool compressed) +{ + int status = EOK; + const char *filename = NULL; + const struct firmware *fw_entry; + uint32_t fw_entry_size; + uint8_t *temp_eeprom; + uint32_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 + + switch (file) { + default: + BMI_ERR("%s: Unknown file type", __func__); + return -1; + case ATH_OTP_FILE: +#if defined(CONFIG_CNSS) + 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(cds_get_conparam())) { +#if defined(CONFIG_CNSS) + filename = scn->fw_files.epping_file; +#else + filename = QCA_FIRMWARE_EPPING_FILE; +#endif + BMI_INFO("%s: Loading epping firmware file %s", + __func__, filename); + break; + } +#ifdef QCA_WIFI_FTM + if (cds_get_conparam() == CDF_FTM_MODE) { +#if defined(CONFIG_CNSS) + filename = scn->fw_files.utf_file; +#else + filename = QCA_UTF_FIRMWARE_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = true; +#endif + BMI_INFO("%s: Loading firmware file %s", + __func__, filename); + break; + } +#endif +#if defined(CONFIG_CNSS) + 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: + BMI_INFO("%s: no Patch file defined", __func__); + return 0; + case ATH_BOARD_DATA_FILE: +#ifdef QCA_WIFI_FTM + if (cds_get_conparam() == CDF_FTM_MODE) { +#if defined(CONFIG_CNSS) + filename = scn->fw_files.utf_board_data; +#else + filename = QCA_BOARD_DATA_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = true; +#endif + BMI_INFO("%s: Loading board data file %s", + __func__, filename); + break; + } +#endif /* QCA_WIFI_FTM */ +#if defined(CONFIG_CNSS) + filename = scn->fw_files.board_data; +#else + filename = QCA_BOARD_DATA_FILE; +#endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = false; +#endif + break; + case ATH_SETUP_FILE: + if (cds_get_conparam() != CDF_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { +#ifdef CONFIG_CNSS + BMI_INFO("%s: no Setup file defined", __func__); + return -1; +#else + filename = QCA_SETUP_FILE; +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + bin_sign = true; +#endif + BMI_INFO("%s: Loading setup file %s", + __func__, filename); +#endif /* CONFIG_CNSS */ + } else { + BMI_INFO("%s: no Setup file needed", __func__); + return -1; + } + break; + } + + if (request_firmware(&fw_entry, filename, scn->aps_osdev.device) != 0) { + BMI_ERR("%s: Failed to get %s", __func__, filename); + + if (file == ATH_OTP_FILE) + return -ENOENT; + +#if defined(QCA_WIFI_FTM) && defined(CONFIG_CNSS) + /* Try default board data file if FTM specific + * board data file is not present. */ + if (filename == scn->fw_files.utf_board_data) { + filename = scn->fw_files.board_data; + BMI_INFO("%s: Trying to load default %s", + __func__, filename); + if (request_firmware(&fw_entry, filename, + scn->aps_osdev.device) != 0) { + BMI_ERR("%s: Failed to get %s", + __func__, filename); + return -1; + } + } else { + return -1; + } +#else + return -1; +#endif + } + + if (!fw_entry || !fw_entry->data) { + BMI_ERR("Invalid fw_entries"); + return CDF_STATUS_E_FAILURE; + } + + fw_entry_size = fw_entry->size; + temp_eeprom = NULL; + +#ifdef FEATURE_SECURE_FIRMWARE + + if (ol_check_fw_hash(fw_entry->data, fw_entry_size, file)) { + BMI_ERR("Hash Check failed for file:%s", filename); + status = CDF_STATUS_E_FAILURE; + goto end; + } +#endif + + if (file == ATH_BOARD_DATA_FILE) { + uint32_t board_ext_address; + int32_t board_ext_data_size; + + temp_eeprom = cdf_mem_malloc(fw_entry_size); + if (!temp_eeprom) { + BMI_ERR("%s: Memory allocation failed", __func__); + release_firmware(fw_entry); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(temp_eeprom, (uint8_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 */ + bmi_read_memory(HOST_INTEREST_ITEM_ADDRESS(scn->target_type, + hi_board_ext_data), + (uint8_t *) &board_ext_address, 4, scn); + BMI_INFO("Board extended Data download address: 0x%x", + 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))) { + uint32_t param; + + status = bmi_write_memory(board_ext_address, + (uint8_t *)(temp_eeprom + + board_data_size), + board_ext_data_size, scn); + + if (status != EOK) + goto end; + + /* Record extended board Data initialized */ + param = (board_ext_data_size << 16) | 1; + bmi_write_memory( + HOST_INTEREST_ITEM_ADDRESS(scn->target_type, + hi_board_ext_data_config), + (uint8_t *)¶m, 4, scn); + + fw_entry_size = board_data_size; + } + } +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT + if (bin_sign) { + uint32_t chip_id; + + if (fw_entry_size < sizeof(SIGN_HEADER_T)) { + BMI_ERR("Invalid binary size %d", fw_entry_size); + status = CDF_STATUS_E_FAILURE; + 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 = bmi_sign_stream_start(address, + (uint8_t *)fw_entry->data, + sizeof(SIGN_HEADER_T), scn); + if (status != EOK) { + BMI_ERR("unable to start sign stream"); + status = CDF_STATUS_E_FAILURE; + 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 = bmi_fast_download(address, + (uint8_t *) fw_entry->data + bin_off, + bin_len, scn); + } else { + if (file == ATH_BOARD_DATA_FILE && fw_entry->data) { + status = bmi_write_memory(address, + (uint8_t *) temp_eeprom, + fw_entry_size, scn); + } else { + status = bmi_write_memory(address, + (uint8_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 = bmi_sign_stream_start(0, + (uint8_t *)fw_entry->data + + bin_off, bin_len, scn); + if (status != EOK) + BMI_ERR("sign stream error"); + } + } +#else + if (compressed) { + status = bmi_fast_download(address, + (uint8_t *) fw_entry->data, + fw_entry_size, scn); + } else { + if (file == ATH_BOARD_DATA_FILE && fw_entry->data) { + status = bmi_write_memory(address, + (uint8_t *) temp_eeprom, + fw_entry_size, scn); + } else { + status = bmi_write_memory(address, + (uint8_t *) fw_entry->data, + fw_entry_size, scn); + } + } +#endif /* QCA_SIGNED_SPLIT_BINARY_SUPPORT */ + +end: + if (temp_eeprom) + cdf_mem_free(temp_eeprom); + + if (status != EOK) { + BMI_ERR("%s, BMI operation failed: %d", __func__, __LINE__); + release_firmware(fw_entry); + return CDF_STATUS_E_FAILURE; + } + + release_firmware(fw_entry); + + BMI_INFO("transferring file: %s size %d bytes done!", + (filename != NULL) ? filename : " ", fw_entry_size); + + return status; +} + +static int ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, + uint32_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; +} + +int dump_ce_register(struct ol_softc *scn) +{ + uint32_t ce_reg_address = CE0_BASE_ADDRESS; + uint32_t ce_reg_values[8][CE_USEFUL_SIZE >> 2]; + uint32_t ce_reg_word_size = CE_USEFUL_SIZE >> 2; + uint16_t i, j; + + for (i = 0; i < 8; i++, ce_reg_address += CE_OFFSET) { + if (hif_diag_read_mem(scn, ce_reg_address, + (uint8_t *) &ce_reg_values[i][0], ce_reg_word_size * + sizeof(uint32_t)) != CDF_STATUS_SUCCESS) { + BMI_ERR("Dumping CE register failed!"); + return -EACCES; + } + } + + for (i = 0; i < 8; i++) { + BMI_ERR("CE%d Registers:", i); + for (j = 0; j < ce_reg_word_size; j++) { + BMI_ERR("0x%08x ", ce_reg_values[i][j]); + if (!((j + 1) % 5) || (ce_reg_word_size - 1) == j) + BMI_ERR(" "); + } + } + + return 0; +} + +#if defined(CONFIG_CNSS) + +static struct ol_softc *ramdump_scn; + +int ol_copy_ramdump(struct ol_softc *scn) +{ + int ret; + + if (!scn->ramdump_base || !scn->ramdump_size) { + BMI_ERR("%s:ramdump collection fail", __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) +{ + int ret; + uint32_t host_interest_address; + uint32_t dram_dump_values[4]; + + if (!ramdump_scn) { + BMI_ERR("%s:Ramdump_scn is null:", __func__); + goto out_fail; + } +#ifdef DEBUG + ret = hif_check_soc_status(ramdump_scn); + if (ret) + goto out_fail; + + ret = dump_ce_register(ramdump_scn); + if (ret) + goto out_fail; + + dump_ce_debug_register(ramdump_scn); +#endif + + if (hif_diag_read_mem(ramdump_scn, + hif_hia_item_address(ramdump_scn->target_type, + offsetof(struct host_interest_s, hi_failure_state)), + (uint8_t *)&host_interest_address, + sizeof(uint32_t)) != CDF_STATUS_SUCCESS) { + BMI_ERR("HifDiagReadiMem FW Dump Area Pointer failed!"); + ol_copy_ramdump(ramdump_scn); + cnss_device_crashed(); + return; + } + + BMI_ERR("Host interest item address: 0x%08x", host_interest_address); + + if (hif_diag_read_mem(ramdump_scn, host_interest_address, + (uint8_t *) &dram_dump_values[0], + 4 * sizeof(uint32_t)) != CDF_STATUS_SUCCESS) { + BMI_ERR("HifDiagReadiMem FW Dump Area failed!"); + goto out_fail; + } + BMI_ERR("FW Assertion at PC: 0x%08x BadVA: 0x%08x TargetID: 0x%08x", + dram_dump_values[2], dram_dump_values[3], dram_dump_values[0]); + + if (ol_copy_ramdump(ramdump_scn)) + goto out_fail; + + BMI_ERR("%s: RAM dump collecting completed!", __func__); + /* notify SSR framework the target has crashed. */ + cnss_device_crashed(); + return; + +out_fail: + /* Silent SSR on dump failure */ +#ifdef CNSS_SELF_RECOVERY + cnss_device_self_recovery(); +#else + cnss_device_crashed(); +#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) +{ + cnss_device_self_recovery(); +} + +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 + +void ol_target_failure(void *instance, CDF_STATUS status) +{ + struct ol_softc *scn = (struct ol_softc *)instance; + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + int ret; + + cdf_event_set(&wma->recovery_event); + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + BMI_ERR("Target is already asserted, ignore!"); + return; + } + scn->target_status = OL_TRGET_STATUS_RESET; + + if (cds_is_logp_in_progress()) { + BMI_ERR("%s: LOGP is in progress, ignore!\n", __func__); + return; + } + + if (cds_is_load_unload_in_progress()) { + BMI_ERR("%s: Loading/Unloading is in progress, ignore!", + __func__); + return; + } + cds_set_logp_in_progress(true); + +#ifdef CONFIG_CNSS + ret = hif_check_fw_reg(scn); + if (0 == ret) { + if (scn->enable_self_recovery) { + ol_schedule_fw_indication_work(scn); + return; + } + } else if (-1 == ret) { + return; + } +#endif + + BMI_ERR("XXX TARGET ASSERTED XXX"); + +#if defined(CONFIG_CNSS) + /* Collect the RAM dump through a workqueue */ + if (scn->enable_ramdump_collection) + ol_schedule_ramdump_work(scn); + else + pr_debug("%s: athdiag read for target reg\n", __func__); +#endif + + return; +} + +CDF_STATUS ol_configure_target(struct ol_softc *scn) +{ + uint32_t param; +#ifdef CONFIG_CNSS + struct cnss_platform_cap cap; + int ret; +#endif + + /* Tell target which HTC version it is used */ + param = HTC_PROTOCOL_VERSION; + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_app_host_interest)), + (uint8_t *) ¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("bmi_write_memory for htc version failed"); + return CDF_STATUS_E_FAILURE; + } + + /* set the firmware mode to STA/IBSS/AP */ + { + if (bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("bmi_read_memory for setting fwmode failed"); + return CDF_STATUS_E_FAILURE; + } + + /* TODO following parameters need to be re-visited. */ + param |= (1 << HI_OPTION_NUM_DEV_SHIFT); /* num_device */ + /* Firmware mode ?? */ + param |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT); + /* mac_addr_method */ + param |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); + /* firmware_bridge */ + param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); + /* fwsubmode */ + param |= (0 << HI_OPTION_FW_SUBMODE_SHIFT); + + BMI_INFO("NUM_DEV=%d FWMODE=0x%x FWSUBMODE=0x%x FWBR_BUF %d", + 1, HI_OPTION_FW_MODE_AP, 0, 0); + + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI WRITE for setting fwmode failed"); + return CDF_STATUS_E_FAILURE; + } + } + +#if (CONFIG_DISABLE_CDC_MAX_PERF_WAR) + { + /* set the firmware to disable CDC max perf WAR */ + if (bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *) ¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI READ for setting cdc max perf failed"); + return CDF_STATUS_E_FAILURE; + } + + param |= HI_OPTION_DISABLE_CDC_MAX_PERF_WAR; + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("setting cdc max perf failed"); + return CDF_STATUS_E_FAILURE; + } + } +#endif /* CONFIG_CDC_MAX_PERF_WAR */ + +#ifdef CONFIG_CNSS + + ret = cnss_get_platform_cap(&cap); + if (ret) + BMI_ERR("platform capability info from CNSS not available"); + + if (!ret && cap.cap_flag & CNSS_HAS_EXTERNAL_SWREG) { + if (bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("bmi_read_memory for setting" + "external SWREG failed"); + return CDF_STATUS_E_FAILURE; + } + + param |= HI_OPTION_USE_EXT_LDO; + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI WRITE for setting external SWREG fail"); + return CDF_STATUS_E_FAILURE; + } + } +#endif + +#ifdef WLAN_FEATURE_LPSS + if (scn->enablelpasssupport) { + if (bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *) ¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI READ:Setting LPASS Support failed"); + return CDF_STATUS_E_FAILURE; + } + + param |= HI_OPTION_DBUART_SUPPORT; + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)), + (uint8_t *)¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI_READ for setting LPASS Support fail"); + return CDF_STATUS_E_FAILURE; + } + } +#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 (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_be)), + (uint8_t *) ¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("setting host CPU BE mode failed"); + return CDF_STATUS_E_FAILURE; + } + } + + /* FW descriptor/Data swap flags */ + param = 0; + if (bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_fw_swap)), + (uint8_t *) ¶m, 4, scn) != CDF_STATUS_SUCCESS) { + BMI_ERR("BMI WRITE failed setting FW data/desc swap flags"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +static int ol_check_dataset_patch(struct ol_softc *scn, uint32_t *address) +{ + /* Check if patch file needed for this target type/version. */ + return 0; +} + + +CDF_STATUS ol_fw_populate_clk_settings(A_refclk_speed_t refclk, + struct cmnos_clock_s *clock_s) +{ + if (!clock_s) + return CDF_STATUS_E_FAILURE; + + 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 CDF_STATUS_E_FAILURE; + } + + clock_s->refclk_hz = refclk_speed_to_hz[refclk]; + clock_s->wlan_pll.refdiv = 0; + clock_s->wlan_pll.outdiv = 1; + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS ol_patch_pll_switch(struct ol_softc *scn) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t addr = 0; + uint32_t reg_val = 0; + uint32_t mem_val = 0; + struct cmnos_clock_s clock_s; + uint32_t cmnos_core_clk_div_addr = 0; + uint32_t cmnos_cpu_pll_init_done_addr = 0; + uint32_t cmnos_cpu_speed_addr = 0; + + 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: + 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: + BMI_ERR("%s: Unsupported target version %x", __func__, + scn->target_version); + goto end; + } + + addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read EFUSE Addr"); + goto end; + } + + status = ol_fw_populate_clk_settings(EFUSE_XTAL_SEL_GET(reg_val), + &clock_s); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to set clock settings"); + goto end; + } + BMI_DBG("crystal_freq: %dHz", clock_s.refclk_hz); + + /* ------Step 1---- */ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read PLL_CONFIG Addr"); + goto end; + } + BMI_DBG("Step 1a: %8X", 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 = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_CONFIG Addr"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back PLL_CONFIG Addr"); + goto end; + } + BMI_DBG("Step 1b: %8X", reg_val); + + /* ------Step 2---- */ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read PLL_SETTLE Addr"); + goto end; + } + BMI_DBG("Step 2a: %8X", reg_val); + + reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK; + reg_val |= WLAN_PLL_SETTLE_TIME_SET(clock_s.pll_settling_time); + status = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_SETTLE Addr"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back PLL_SETTLE Addr"); + goto end; + } + BMI_DBG("Step 2b: %8X", reg_val); + + /* ------Step 3---- */ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read CLK_CTRL Addr"); + goto end; + } + BMI_DBG("Step 3a: %8X", reg_val); + + reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK; + reg_val |= SOC_CORE_CLK_CTRL_DIV_SET(1); + status = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write CLK_CTRL Addr"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back CLK_CTRL Addr"); + goto end; + } + BMI_DBG("Step 3b: %8X", reg_val); + + /* ------Step 4----- */ + mem_val = 1; + status = bmi_write_memory(cmnos_core_clk_div_addr, + (uint8_t *) &mem_val, 4, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write CLK_DIV Addr"); + goto end; + } + + /* ------Step 5----- */ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read PLL_CTRL Addr"); + goto end; + } + BMI_DBG("Step 5a: %8X", 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 = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_CTRL Addr"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back PLL_CTRL Addr"); + goto end; + } + OS_DELAY(100); + BMI_DBG("Step 5b: %8X", reg_val); + + /* ------Step 6------- */ + do { + reg_val = 0; + status = bmi_read_soc_register((RTC_WMAC_BASE_ADDRESS | + RTC_SYNC_STATUS_OFFSET), ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read RTC_SYNC_STATUS Addr"); + goto end; + } + } while (RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val)); + + /* ------Step 7------- */ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read PLL_CTRL Addr for CTRL_BYPASS"); + goto end; + } + BMI_DBG("Step 7a: %8X", reg_val); + + reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK; + reg_val |= WLAN_PLL_CONTROL_BYPASS_SET(0); + status = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_CTRL Addr for CTRL_BYPASS"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back PLL_CTRL Addr for CTRL_BYPASS"); + goto end; + } + BMI_DBG("Step 7b: %8X", reg_val); + + /* ------Step 8-------- */ + do { + reg_val = 0; + status = bmi_read_soc_register((RTC_WMAC_BASE_ADDRESS | + RTC_SYNC_STATUS_OFFSET), ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read SYNC_STATUS Addr"); + goto end; + } + } while (RTC_SYNC_STATUS_PLL_CHANGING_GET(reg_val)); + + /* ------Step 9-------- */ + reg_val = 0; + addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read CPU_CLK Addr"); + goto end; + } + BMI_DBG("Step 9a: %8X", reg_val); + + reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK; + reg_val |= SOC_CPU_CLOCK_STANDARD_SET(1); + status = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write CPU_CLK Addr"); + goto end; + } + + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back CPU_CLK Addr"); + goto end; + } + BMI_DBG("Step 9b: %8X", reg_val); + + /* ------Step 10------- */ + reg_val = 0; + addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET); + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read PLL_CTRL Addr for NOPWD"); + goto end; + } + BMI_DBG("Step 10a: %8X", reg_val); + + reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK; + status = bmi_write_soc_register(addr, reg_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_CTRL Addr for NOPWD"); + goto end; + } + reg_val = 0; + status = bmi_read_soc_register(addr, ®_val, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to read back PLL_CTRL Addr for NOPWD"); + goto end; + } + BMI_DBG("Step 10b: %8X", reg_val); + + /* ------Step 11------- */ + mem_val = 1; + status = bmi_write_memory(cmnos_cpu_pll_init_done_addr, + (uint8_t *) &mem_val, 4, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write PLL_INIT Addr"); + goto end; + } + + mem_val = TARGET_CPU_FREQ; + status = bmi_write_memory(cmnos_cpu_speed_addr, + (uint8_t *) &mem_val, 4, scn); + if (status != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to write CPU_SPEED Addr"); + goto end; + } + +end: + return status; +} + +#ifdef CONFIG_CNSS +/* AXI Start Address */ +#define TARGET_ADDR (0xa0000) + +void ol_transfer_codeswap_struct(struct ol_softc *scn) +{ + struct codeswap_codeseg_info wlan_codeswap; + CDF_STATUS rv; + + if (!scn) { + BMI_ERR("%s: ol_softc is null", __func__); + return; + } + if (cnss_get_codeswap_struct(&wlan_codeswap)) { + BMI_ERR("%s: failed to get codeswap structure", __func__); + return; + } + + rv = bmi_write_memory(TARGET_ADDR, + (uint8_t *) &wlan_codeswap, sizeof(wlan_codeswap), + scn); + + if (rv != CDF_STATUS_SUCCESS) { + BMI_ERR("Failed to Write 0xa0000 to Target"); + return; + } + BMI_INFO("codeswap structure is successfully downloaded"); +} +#endif + +CDF_STATUS ol_download_firmware(struct ol_softc *scn) +{ + uint32_t param, address = 0; + int status = !EOK; + CDF_STATUS ret; + +#ifdef CONFIG_CNSS + if (0 != cnss_get_fw_files_for_target(&scn->fw_files, + scn->target_type, + scn->target_version)) { + BMI_ERR("%s: No FW files from CNSS driver", __func__); + return CDF_STATUS_E_FAILURE; + } +#endif + /* Transfer Board Data from Target EEPROM to Target RAM */ + /* Determine where in Target RAM to write Board Data */ + bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_board_data)), + (uint8_t *)&address, 4, scn); + + if (!address) { + address = AR6004_REV5_BOARD_DATA_ADDRESS; + BMI_DBG("%s: Target address not known! Using 0x%x", + __func__, address); + } + ret = ol_patch_pll_switch(scn); + if (ret != CDF_STATUS_SUCCESS) { + BMI_ERR("pll switch failed. status %d", ret); + return ret; + } + 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; + bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_board_data_initialized)), + (uint8_t *) ¶m, 4, scn); + } else { + /* Flash is either not available or invalid */ + if (ol_transfer_bin_file + (scn, ATH_BOARD_DATA_FILE, address, false) != EOK) { + return -1; + } + + /* Record the fact that Board Data is initialized */ + param = 1; + bmi_write_memory( + hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, + hi_board_data_initialized)), + (uint8_t *) ¶m, 4, scn); + + /* Transfer One Time Programmable data */ + address = BMI_SEGMENTED_WRITE_ADDR; + BMI_INFO("%s: Using 0x%x for the remainder of init", + __func__, address); + +#ifdef CONFIG_CNSS + ol_transfer_codeswap_struct(scn); +#endif + status = ol_transfer_bin_file(scn, ATH_OTP_FILE, + address, true); + /* Execute the OTP code only if entry found and downloaded */ + if (status == EOK) { + param = 0; +#ifndef FEATURE_BMI_2 + bmi_execute(address, ¶m, scn); +#endif + } else if (status < 0) { + return status; + } + } + + if (ol_transfer_bin_file(scn, ATH_SETUP_FILE, + BMI_SEGMENTED_WRITE_ADDR, true) == EOK) { + param = 0; +#ifndef FEATURE_BMI_2 + bmi_execute(address, ¶m, scn); +#endif + } + + /* Download Target firmware + * TODO point to target specific files in runtime + */ + address = BMI_SEGMENTED_WRITE_ADDR; + 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; + } + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_dset_list_head)), + (uint8_t *) &address, 4, scn); + } + + if (scn->enableuartprint || + (WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && + WLAN_IS_EPPING_FW_UART(cds_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 AR6320_REV4_VERSION: + case AR6320_DEV_VERSION: + param = 6; + break; + default: + /* Configure GPIO AR9888 UART */ + param = 7; + } + + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_dbg_uart_txpin)), + (uint8_t *)¶m, 4, scn); + param = 1; + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_serial_enable)), + (uint8_t *)¶m, 4, scn); + } else { + /* + * Explicitly setting UART prints to zero as target turns it on + * based on scratch registers. + */ + param = 0; + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_serial_enable)), + (uint8_t *)¶m, 4, scn); + } + + if (scn->enablefwlog) { + bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *)¶m, 4, scn); + + param &= ~(HI_OPTION_DISABLE_DBGLOG); + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *)¶m, 4, scn); + } else { + /* + * Explicitly setting fwlog prints to zero as target turns it on + * based on scratch registers. + */ + bmi_read_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *)¶m, 4, scn); + + param |= HI_OPTION_DISABLE_DBGLOG; + bmi_write_memory(hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag)), + (uint8_t *) ¶m, 4, scn); + } + + return status; +} + +int ol_diag_read(struct ol_softc *scn, uint8_t *buffer, + uint32_t pos, size_t count) +{ + int result = 0; + + if ((4 == count) && ((pos & 3) == 0)) { + result = hif_diag_read_access(scn, pos, + (uint32_t *) buffer); + } else { + size_t amount_read = 0; + size_t readSize = PCIE_READ_LIMIT; + size_t remainder = 0; + if (count > PCIE_READ_LIMIT) { + while ((amount_read < count) && (0 == result)) { + result = hif_diag_read_mem(scn, pos, + buffer, readSize); + if (0 == result) { + buffer += readSize; + pos += readSize; + amount_read += readSize; + remainder = count - amount_read; + if (remainder < PCIE_READ_LIMIT) + readSize = remainder; + } + } + } else { + result = hif_diag_read_mem(scn, pos, + buffer, count); + } + } + + if (!result) + return count; + else + return -EIO; +} + +static int ol_ath_get_reg_table(uint32_t target_version, + tgt_reg_table *reg_table) +{ + int section_len = 0; + + if (!reg_table) { + cdf_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: + 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, uint8_t *buffer, + uint32_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) { + BMI_ERR("%s: failed to get reg table", __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) { + BMI_ERR("Not enough memory to dump the registers:" + " %d: 0x%08x-0x%08x", 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 { + BMI_ERR("%s: can't read reg 0x%08x len = %d", + __func__, curr_sec->start_addr, dump_len); + result = -EIO; + goto out; + } + + if (result < section_len) { + next_sec = (tgt_reg_section *) ((uint8_t *) curr_sec + + sizeof(*curr_sec)); + fill_len = next_sec->start_addr - curr_sec->end_addr; + if ((buffer_len - result) < fill_len) { + BMI_ERR("Not enough memory to fill registers:" + " %d: 0x%08x-0x%08x", 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(struct ol_softc *scn, void *memory_block) +{ + char *buffer_loc = memory_block; + u_int32_t section_count = 0; + u_int32_t address = 0; + u_int32_t size = 0; + + for (; section_count < 2; section_count++) { + switch (section_count) { + case 0: + address = DRAM_LOCAL_BASE_ADDR; + size = DRAM_SIZE; + break; + case 1: + address = AXI_LOCATION; + size = AXI_SIZE; + default: + break; + } + hif_dump_target_memory(scn, buffer_loc, address, size); + buffer_loc += size; + } +} + +/**--------------------------------------------------------------------------- +* \brief ol_target_coredump +* +* Function to perform core dump for the target +* +* \param: scn - ol_softc handler +* memory_block - non-NULL reserved memory location +* block_len - size of the dump to collect +* +* \return: None +* --------------------------------------------------------------------------*/ +static int ol_target_coredump(void *inst, void *memory_block, + uint32_t block_len) +{ + struct ol_softc *scn = (struct ol_softc *)inst; + int8_t *buffer_loc = memory_block; + int result = 0; + int ret = 0; + uint32_t amount_read = 0; + uint32_t section_count = 0; + uint32_t pos = 0; + uint32_t read_len = 0; + + /* + * SECTION = DRAM + * START = 0x00400000 + * LENGTH = 0x000a8000 + * + * SECTION = AXI + * START = 0x000a0000 + * LENGTH = 0x00018000 + * + * SECTION = REG + * START = 0x00000800 + * LENGTH = 0x0007F820 + */ + + while ((section_count < 3) && (amount_read < block_len)) { + switch (section_count) { + case 0: + /* DRAM SECTION */ + pos = DRAM_LOCATION; + read_len = DRAM_SIZE; + BMI_ERR("%s: Dumping DRAM section...", __func__); + break; + case 1: + /* AXI SECTION */ + pos = AXI_LOCATION; + read_len = AXI_SIZE; + BMI_ERR("%s: Dumping AXI section...", __func__); + break; + case 2: + /* REG SECTION */ + pos = REGISTER_LOCATION; + /* ol_diag_read_reg_loc checks for buffer overrun */ + read_len = 0; + BMI_ERR("%s: Dumping Register section...", __func__); + break; + } + + if ((block_len - amount_read) >= read_len) { + if (pos == REGISTER_LOCATION) + result = ol_diag_read_reg_loc(scn, buffer_loc, + block_len - + amount_read); + else + result = ol_diag_read(scn, buffer_loc, + pos, read_len); + if (result != -EIO) { + amount_read += result; + buffer_loc += result; + section_count++; + } else { + BMI_ERR("Could not read dump section!"); + dump_ce_register(scn); + dump_ce_debug_register(scn); + ol_dump_target_memory(scn, memory_block); + ret = -EACCES; + break; /* Could not read the section */ + } + } else { + BMI_ERR("Insufficient room in dump buffer!"); + break; /* Insufficient room in buffer */ + } + } + return ret; +} + +#define MAX_SUPPORTED_PEERS_REV1_1 14 +#define MAX_SUPPORTED_PEERS_REV1_3 32 + +uint8_t ol_get_number_of_peers_supported(struct ol_softc *scn) +{ + uint8_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_REV1_3) + max_no_of_peers = MAX_SUPPORTED_PEERS_REV1_3; + else + max_no_of_peers = scn->max_no_of_peers; + break; + + } + return max_no_of_peers; +} diff --git a/core/cdf/inc/cdf_atomic.h b/core/cdf/inc/cdf_atomic.h new file mode 100644 index 000000000000..230d4eda3057 --- /dev/null +++ b/core/cdf/inc/cdf_atomic.h @@ -0,0 +1,140 @@ +/* + * 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. + */ + +/** + * DOC: cdf_atomic.h + * This file abstracts an atomic counter. + */ + +#ifndef _CDF_ATOMIC_H +#define _CDF_ATOMIC_H + +#include + +/** + * cdf_atomic_t - 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 __cdf_atomic_t cdf_atomic_t; + +/** + * cdf_atomic_init() - initialize an atomic type variable + * @v: A pointer to an opaque atomic variable + * + * Return: None + */ +static inline void cdf_atomic_init(cdf_atomic_t *v) +{ + __cdf_atomic_init(v); +} + +/** + * cdf_atomic_read() - read the value of an atomic variable + * @v: A pointer to an opaque atomic variable + * + * Return: The current value of the variable + */ +static inline uint32_t cdf_atomic_read(cdf_atomic_t *v) +{ + return __cdf_atomic_read(v); +} + +/** + * cdf_atomic_inc() - increment the value of an atomic variable + * @v: A pointer to an opaque atomic variable + * + * Return: None + */ +static inline void cdf_atomic_inc(cdf_atomic_t *v) +{ + __cdf_atomic_inc(v); +} + +/** + * cdf_atomic_dec() - decrement the value of an atomic variable + * @v: A pointer to an opaque atomic variable + * + * Return: None + */ +static inline void cdf_atomic_dec(cdf_atomic_t *v) +{ + __cdf_atomic_dec(v); +} + +/** + * cdf_atomic_add() - add a value to the value of an atomic variable + * @v: A pointer to an opaque atomic variable + * @i: The amount by which to increase the atomic counter + * + * Return: None + */ +static inline void cdf_atomic_add(int i, cdf_atomic_t *v) +{ + __cdf_atomic_add(i, v); +} + +/** + * cdf_atomic_dec_and_test() - decrement an atomic variable and check if the + * new value is zero + * @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 uint32_t cdf_atomic_dec_and_test(cdf_atomic_t *v) +{ + return __cdf_atomic_dec_and_test(v); +} + +/** + * cdf_atomic_set() - set a value to the value of an atomic variable + * @v: A pointer to an opaque atomic variable + * + * Return: None + */ +static inline void cdf_atomic_set(cdf_atomic_t *v, int i) +{ + __cdf_atomic_set(v, i); +} + +/** + * cdf_atomic_inc_return() - return the incremented value of an atomic variable + * @v: A pointer to an opaque atomic variable + * + * Return: The current value of the variable + */ +static inline uint32_t cdf_atomic_inc_return(cdf_atomic_t *v) +{ + return __cdf_atomic_inc_return(v); +} + +#endif diff --git a/core/cdf/inc/cdf_defer.h b/core/cdf/inc/cdf_defer.h new file mode 100644 index 000000000000..fa527f3b3dbc --- /dev/null +++ b/core/cdf/inc/cdf_defer.h @@ -0,0 +1,138 @@ +/* + * 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. + */ + +/** + * DOC: cdf_defer.h + * This file abstracts deferred execution contexts. + */ + +#ifndef __CDF_DEFER_H +#define __CDF_DEFER_H + +#include +#include + +/** + * 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?? + */ + +/* cdf_work_t - representation of a work queue */ +typedef __cdf_work_t cdf_work_t; + +/* cdf_work_t - representation of a bottom half */ +typedef __cdf_bh_t cdf_bh_t; + +/** + * cdf_create_bh() - this creates the Bottom half deferred handler + * @hdl: OS handle + * @bh: Bottom instance + * @func: Func deferred function to run at bottom half interrupt + * context + * Return: None + */ +static inline void +cdf_create_bh(cdf_handle_t hdl, cdf_bh_t *bh, cdf_defer_fn_t func, void *arg) +{ + __cdf_init_bh(hdl, bh, func, arg); +} + +/** + * cdf_sched_bh() - schedule a bottom half (DPC) + * @hdl: OS handle + * @bh: Bottom instance + * + * Return: None + */ +static inline void cdf_sched_bh(cdf_handle_t hdl, cdf_bh_t *bh) +{ + __cdf_sched_bh(hdl, bh); +} + +/** + * cdf_destroy_bh() - destroy a bottom half (DPC) + * @hdl: OS handle + * @bh: Bottom instance + * + * Return: None + */ +static inline void cdf_destroy_bh(cdf_handle_t hdl, cdf_bh_t *bh) +{ + __cdf_disable_bh(hdl, bh); +} + +/*********************Non-Interrupt Context deferred Execution***************/ + +/** + * cdf_create_work() - create a work/task queue, This runs in non-interrupt + * context, so can be preempted by H/W & S/W intr + * @hdl: OS handle + * @work: Work instance + * @func: Deferred function to run at bottom half non-interrupt + * context + * @arg: Argument for the deferred function + * + * Return: None + */ +static inline void +cdf_create_work(cdf_handle_t hdl, cdf_work_t *work, + cdf_defer_fn_t func, void *arg) +{ + __cdf_init_work(hdl, work, func, arg); +} + +/** + * cdf_sched_work() - schedule a deferred task on non-interrupt context + * @hdl: OS handle + * @work: Work instance + * + * Return: None + */ +static inline void cdf_sched_work(cdf_handle_t hdl, cdf_work_t *work) +{ + __cdf_sched_work(hdl, work); +} + +/** + * cdf_destroy_work() - destroy the deferred task (synchronous) + * @hdl: OS handle + * @work: Work instance + * + * Return: None + */ +static inline void cdf_destroy_work(cdf_handle_t hdl, cdf_work_t *work) +{ + __cdf_disable_work(hdl, work); +} + +#endif /*__CDF_DEFER_H*/ diff --git a/core/cdf/inc/cdf_event.h b/core/cdf/inc/cdf_event.h new file mode 100644 index 000000000000..e18588063636 --- /dev/null +++ b/core/cdf/inc/cdf_event.h @@ -0,0 +1,154 @@ +/* + * 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(__CDF_EVENT_H) +#define __CDF_EVENT_H + +/** + * DOC: cdf_event.h + * + * Connectivity driver framework (CDF) events API + * + **/ + +/* Include Files */ +#include "cdf_status.h" +#include "cdf_types.h" +#include "i_cdf_event.h" + +/* Preprocessor definitions and constants */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Type declarations */ + +/* Function declarations and documenation */ + +/** + * cdf_event_init() - initializes the specified event + * + * @event: Pointer to CDF event object to initialize + * + * Initializes the specified event. Upon successful initialization the state + * of the event becomes initialized and not signaled. + * + * Return: + * CDF_STATUS_SUCCESS - Event was successfully initialized and is ready to + * be used + * Otherwise failure CDF reason code + */ + +CDF_STATUS cdf_event_init(cdf_event_t *event); + +/** + * cdf_event_set() - set a CDF event + * + * @event: Pointer of CDF event to set to the signalled state + * + * The state of the specified event is set to 'signalled by calling + * cdf_event_set(). The state of the event remains signalled until an + * explicit call to cdf_event_reset(). + * + * Any threads waiting on the event as a result of a cdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to cdf_event_set(). + * + * Return: + * CDF_STATUS_SUCCESS - Event was successfully set + * Otherwise failure CDF reason code + */ +CDF_STATUS cdf_event_set(cdf_event_t *event); + +/** + * cdf_event_reset() - reset a CDF event + * + * @event: Pointer of CDF event to reset + * + * The state of the specified event is set to 'NOT signalled' by calling + * cdf_event_reset(). The state of the event remains NOT signalled until an + * explicit call to cdf_event_set(). + * + * This function sets the event to a NOT signalled state even if the event was + * signalled multiple times before being signaled. + * + * Return: + * CDF_STATUS_SUCCESS - Event was successfully reset + * Otherwise failure CDF reason code + */ +CDF_STATUS cdf_event_reset(cdf_event_t *event); + +/** + * cdf_event_destroy() - destroy a CDF event + * + * @event: Pointer of CDF event to destroy + * + * The function destroys the event object referenced by event. + * After a successful return from cdf_event_destroy() the event object becomes, + * in effect, uninitialized. + * + * A destroyed event object can be reinitialized using cdf_event_init(); + * the results of otherwise referencing the object after it has been destroyed + * are undefined. Calls to CDF event functions to manipulate the lock such + * as cdf_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. + * + * Return: + * CDF_STATUS_SUCCESS - Event was successfully destroyed + * Otherwise failure CDF reason code + */ +CDF_STATUS cdf_event_destroy(cdf_event_t *event); + +/** + * cdf_wait_single_event() - wait for a single input CDF event to be set + * + * @event: Pointer of CDF event to wait on + * @timeout: Timeout value in milli seconds + * + * This API waits for the event to be set. 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: + * CDF_STATUS_SUCCESS - the wait was satisifed by the event being + * set. + * + * CDF_STATUS_E_TIMEOUT - the timeout interval elapsed before the + * event was set. + * + * CDF_STATUS_E_INVAL - The value specified by event is invalid. + */ +CDF_STATUS cdf_wait_single_event(cdf_event_t *pEvent, + uint32_t timeout); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __CDF_EVENT_H */ diff --git a/core/cdf/inc/cdf_list.h b/core/cdf/inc/cdf_list.h new file mode 100644 index 000000000000..d4b793e39c9d --- /dev/null +++ b/core/cdf/inc/cdf_list.h @@ -0,0 +1,110 @@ +/* + * 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(__CDF_LIST_H) +#define __CDF_LIST_H + +/** + * DOC: cdf_list.h + * + * Connectivity driver framework (CDF) list APIs + * + * Definitions for CDF 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 + * cdf_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. + * + * CDF linked list APIs are NOT thread safe so make sure to use appropriate + * locking mechanisms to assure operations on the list are thread safe. + */ + +/* Include Files */ +#include +#include +#include +#include + +/* Preprocessor definitions and constants */ + +/* Type declarations */ + +typedef struct list_head cdf_list_node_t; + +typedef struct cdf_list_s { + cdf_list_node_t anchor; + uint32_t count; + uint32_t max_size; +} cdf_list_t; + +/* Function declarations */ + +CDF_INLINE_FN void cdf_list_init(cdf_list_t *p_list, uint32_t max_size) +{ + INIT_LIST_HEAD(&p_list->anchor); + p_list->count = 0; + p_list->max_size = max_size; +} + +CDF_INLINE_FN void cdf_list_destroy(cdf_list_t *p_list) +{ + if (p_list->count != 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: list length not equal to zero", __func__); + CDF_ASSERT(0); + } +} + +CDF_INLINE_FN void cdf_list_size(cdf_list_t *p_list, uint32_t *p_size) +{ + *p_size = p_list->count; +} + +CDF_STATUS cdf_list_insert_front(cdf_list_t *p_list, cdf_list_node_t *p_node); + +CDF_STATUS cdf_list_insert_back(cdf_list_t *p_list, cdf_list_node_t *p_node); + +CDF_STATUS cdf_list_insert_back_size(cdf_list_t *p_list, + cdf_list_node_t *p_node, uint32_t *p_size); + +CDF_STATUS cdf_list_remove_front(cdf_list_t *p_list, cdf_list_node_t **pp_node); + +CDF_STATUS cdf_list_remove_back(cdf_list_t *p_list, cdf_list_node_t **pp_node); + +CDF_STATUS cdf_list_peek_front(cdf_list_t *p_list, cdf_list_node_t **pp_node); + +CDF_STATUS cdf_list_peek_next(cdf_list_t *p_list, cdf_list_node_t *p_node, + cdf_list_node_t **pp_node); + +CDF_STATUS cdf_list_remove_node(cdf_list_t *p_list, + cdf_list_node_t *p_node_to_remove); + +#endif /* __CDF_LIST_H */ diff --git a/core/cdf/inc/cdf_lock.h b/core/cdf/inc/cdf_lock.h new file mode 100644 index 000000000000..82fd160959c3 --- /dev/null +++ b/core/cdf/inc/cdf_lock.h @@ -0,0 +1,296 @@ +/* + * 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(__CDF_LOCK_H) +#define __CDF_LOCK_H + +/** + * + * @file cdf_lock.h + * + * @brief Connectivity driver framework (CDF) lock APIs + * + * Definitions for CDF locks + * + */ + +/* Include Files */ +#include "cdf_status.h" +#include "i_cdf_lock.h" + +/* Preprocessor definitions and constants */ + +/* Type declarations */ +/** + * @brief Platform spinlock object + */ +typedef __cdf_spinlock_t cdf_spinlock_t; +/** + * @brief Platform mutex object + */ +typedef __cdf_semaphore_t cdf_semaphore_t; + +/* Function declarations and documenation */ + +/** + * cdf_semaphore_init() - initialize a semaphore + * @m: Semaphore to initialize + * + * Return: None + */ + +static inline void cdf_semaphore_init(cdf_semaphore_t *m) +{ + __cdf_semaphore_init(m); +} + +/** + * cdf_semaphore_acquire() - take the semaphore + * @m: Semaphore to take + * + * Return: None + */ +static inline int cdf_semaphore_acquire(cdf_device_t osdev, cdf_semaphore_t *m) +{ + return __cdf_semaphore_acquire(osdev, m); +} + +/** + * cdf_semaphore_release () - give the semaphore + * @m: Semaphore to give + * + * Return: None + */ +static inline void +cdf_semaphore_release(cdf_device_t osdev, cdf_semaphore_t *m) +{ + __cdf_semaphore_release(osdev, m); +} + +/** + * cdf_mutex_init() - initialize a CDF lock + * @lock: Pointer to the opaque lock object to initialize + * + * cdf_mutex_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 cdf_mutex_init() before it + * may be used in any other lock functions. + * + * Attempting to initialize an already initialized lock results in + * a failure. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_init(cdf_mutex_t *lock); + +/** + * cdf_mutex_acquire () - acquire a CDF lock + * @lock: Pointer to the opaque lock object to acquire + * + * A lock object is acquired by calling cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_acquire(cdf_mutex_t *lock); + +/** + * cdf_mutex_release() - release a CDF lock + * @lock: Pointer to the opaque lock object to be released + * + * cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_release(cdf_mutex_t *lock); + +/** + * cdf_mutex_destroy() - destroy a CDF lock + * @lock: Pointer to the opaque lock object to be destroyed + * + * cdf_mutex_destroy() function shall destroy the lock object + * referenced by lock. After a successful return from \a cdf_mutex_destroy() + * the lock object becomes, in effect, uninitialized. + * + * A destroyed lock object can be reinitialized using cdf_mutex_init(); + * the results of otherwise referencing the object after it has been destroyed + * are undefined. Calls to CDF lock functions to manipulate the lock such + * as cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_destroy(cdf_mutex_t *lock); + +/** + * cdf_spinlock_init() - initialize a spinlock + * @lock: Spinlock object pointer + * + * Return: None + */ +static inline void cdf_spinlock_init(cdf_spinlock_t *lock) +{ + __cdf_spinlock_init(lock); +} + +/** + * cdf_spinlock_destroy() - delete a spinlock + * @lock: Spinlock object pointer + * + * Return: None + */ +static inline void cdf_spinlock_destroy(cdf_spinlock_t *lock) +{ + __cdf_spinlock_destroy(lock); +} + +/** + * cdf_spin_lock_bh() - locks the spinlock semaphore in soft irq context + * @lock: Spinlock object pointer + * + * Return: None + */ +static inline void cdf_spin_lock_bh(cdf_spinlock_t *lock) +{ + __cdf_spin_lock_bh(lock); +} + +/** + * cdf_spin_lock_bh() - unlocks the spinlock semaphore in soft irq context + * @lock: Spinlock object pointer + * + * Return: None + */ +static inline void cdf_spin_unlock_bh(cdf_spinlock_t *lock) +{ + __cdf_spin_unlock_bh(lock); +} + +/** + * cdf_wake_lock_init() - initializes a CDF wake lock + * @lock: The wake lock to initialize + * @name: Name of wake lock + * + * Return: + * CDF status success : if wake lock is initialized + * CDF status fialure : if wake lock was not initialized + */ +CDF_STATUS cdf_wake_lock_init(cdf_wake_lock_t *lock, const char *name); + +/** + * cdf_wake_lock_acquire() - acquires a wake lock + * @lock: The wake lock to acquire + * @reason: Reason for taking wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_acquire(cdf_wake_lock_t *pLock, uint32_t reason); + +/** + * cdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout + * @lock: The wake lock to acquire + * @reason: Reason for taking wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_timeout_acquire(cdf_wake_lock_t *pLock, + uint32_t msec, uint32_t reason); + +/** + * cdf_wake_lock_release() - releases a wake lock + * @lock: the wake lock to release + * @@reason: Reason for taking wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_release(cdf_wake_lock_t *pLock, uint32_t reason); + +/** + * cdf_wake_lock_destroy() - destroys a wake lock + * @lock: The wake lock to destroy + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_destroy(cdf_wake_lock_t *pLock); + +/** + * cdf_spinlock_acquire() - acquires a spin lock + * @lock: Spin lock to acquire + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_spinlock_acquire(cdf_spinlock_t *pLock); + +/** + * cdf_spinlock_release() - release a spin lock + * @lock: Spin lock to release + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status fialure : if wake lock was not acquired + */ +CDF_STATUS cdf_spinlock_release(cdf_spinlock_t *pLock); + +#define cdf_spin_lock(_lock) __cdf_spin_lock(_lock) +#define cdf_spin_unlock(_lock) __cdf_spin_unlock(_lock) +#define cdf_spin_lock_irqsave(_lock) __cdf_spin_lock_irqsave(_lock) +#define cdf_spin_unlock_irqrestore(_lock) \ + __cdf_spin_unlock_irqrestore(_lock) +#define cdf_spin_lock_irq(_pLock, _flags) __cdf_spin_lock_irq(_pLock, _flags) +#define cdf_spin_unlock_irq(_pLock, _flags) \ + __cdf_spin_unlock_irq(_pLock, _flags) + +#define cdf_in_softirq() __cdf_in_softirq() + +#endif /* __CDF_LOCK_H */ diff --git a/core/cdf/inc/cdf_mc_timer.h b/core/cdf/inc/cdf_mc_timer.h new file mode 100644 index 000000000000..b8740d78315e --- /dev/null +++ b/core/cdf/inc/cdf_mc_timer.h @@ -0,0 +1,253 @@ +/* + * 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(__CDF_MC_TIMER_H) +#define __CDF_MC_TIMER_H + +/** + * DOC: cdf_mc_timer + * + * Connectivity driver framework timer APIs serialized to MC thread + */ + +/* Include Files */ +#include +#include +#include +#include + +#ifdef TIMER_MANAGER +#include +#endif + +/* Preprocessor definitions and constants */ +#define CDF_TIMER_STATE_COOKIE (0x12) +#define CDF_MC_TIMER_TO_MS_UNIT (1000) +#define CDF_MC_TIMER_TO_SEC_UNIT (1000000) + +/* Type declarations */ +/* cdf Timer callback function prototype (well, actually a prototype for + a pointer to this callback function) */ +typedef void (*cdf_mc_timer_callback_t)(void *userData); + +typedef enum { + CDF_TIMER_STATE_UNUSED = CDF_TIMER_STATE_COOKIE, + CDF_TIMER_STATE_STOPPED, + CDF_TIMER_STATE_STARTING, + CDF_TIMER_STATE_RUNNING, +} CDF_TIMER_STATE; + +#ifdef TIMER_MANAGER +struct cdf_mc_timer_s; +typedef struct cdf_mc_timer_node_s { + cdf_list_node_t pNode; + char *fileName; + unsigned int lineNum; + struct cdf_mc_timer_s *cdf_timer; +} cdf_mc_timer_node_t; +#endif + +typedef struct cdf_mc_timer_s { +#ifdef TIMER_MANAGER + cdf_mc_timer_node_t *ptimerNode; +#endif + + cdf_mc_timer_platform_t platformInfo; + cdf_mc_timer_callback_t callback; + void *userData; + cdf_mutex_t lock; + CDF_TIMER_TYPE type; + CDF_TIMER_STATE state; +} cdf_mc_timer_t; + +/* Function declarations and documenation */ +#ifdef TIMER_MANAGER +void cdf_mc_timer_manager_init(void); +void cdf_mc_timer_exit(void); +#else +/** + * cdf_mc_timer_manager_init() - initialize CDF debug timer manager + * + * This API initializes CDF timer debug functionality. + * + * Return: none + */ +static inline void cdf_mc_timer_manager_init(void) +{ +} + +/** + * cdf_mc_timer_exit() - exit CDF timer debug functionality + * + * This API exists CDF timer debug functionality + * + * Return: none + */ +static inline void cdf_mc_timer_exit(void) +{ +} +#endif +/** + * cdf_mc_timer_get_current_state() - get the current state of the timer + * @pTimer: Pointer to timer object + * + * Return: + * CDF_TIMER_STATE - cdf timer state + */ + +CDF_TIMER_STATE cdf_mc_timer_get_current_state(cdf_mc_timer_t *pTimer); + +/** + * cdf_mc_timer_init() - initialize a CDF timer + * @pTimer: Pointer to timer object + * @timerType: Type of timer + * @callback: Callback to be called after timer expiry + * @serData: User data which will be passed to callback function + * + * This API initializes a CDF Timer object. + * + * cdf_mc_timer_init() initializes a CDF Timer object. A timer must be + * initialized by calling cdf_mc_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 + * cdf_mc_timer_init(). The results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Calls to CDF timer functions to manipulate the timer such + * as cdf_mc_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 CDS main thread unless it is + * initialized from the Tx thread flow, in which case it will be executed + * within the tx thread flow. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +#ifdef TIMER_MANAGER +#define cdf_mc_timer_init(timer, timerType, callback, userdata) \ + cdf_mc_timer_init_debug(timer, timerType, callback, userdata, \ + __FILE__, __LINE__) + +CDF_STATUS cdf_mc_timer_init_debug(cdf_mc_timer_t *timer, + CDF_TIMER_TYPE timerType, + cdf_mc_timer_callback_t callback, + void *userData, char *fileName, + uint32_t lineNum); +#else +CDF_STATUS cdf_mc_timer_init(cdf_mc_timer_t *timer, CDF_TIMER_TYPE timerType, + cdf_mc_timer_callback_t callback, + void *userData); +#endif + +/** + * cdf_mc_timer_destroy() - destroy CDF timer + * @timer: Pointer to timer object + * + * cdf_mc_timer_destroy() function shall destroy the timer object. + * After a successful return from \a cdf_mc_timer_destroy() the timer + * object becomes, in effect, uninitialized. + * + * A destroyed timer object can be re-initialized by calling + * cdf_mc_timer_init(). The results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Calls to CDF timer functions to manipulate the timer, such + * as cdf_mc_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. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_destroy(cdf_mc_timer_t *timer); + +/** + * cdf_mc_timer_start() - start a CDF Timer object + * @timer: Pointer to timer object + * @expirationTime: Time to expire + * + * cdf_mc_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, cdf_mc_timer_start() has to be called after the timer runs + * or has been cancelled. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_start(cdf_mc_timer_t *timer, uint32_t expirationTime); + +/** + * cdf_mc_timer_stop() - stop a CDF Timer + * @timer: Pointer to timer object + * cdf_mc_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 cdf_mc_timer_start(). + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_stop(cdf_mc_timer_t *timer); + +/** + * cdf_mc_timer_get_system_ticks() - get the system time in 10ms ticks + + * cdf_mc_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. + * + * Return: + * The current system tick count (in 10msec intervals). This + * function cannot fail. + */ +v_TIME_t cdf_mc_timer_get_system_ticks(void); + +/** + * cdf_mc_timer_get_system_time() - Get the system time in milliseconds + * + * cdf_mc_timer_get_system_time() function returns the number of milliseconds + * that have elapsed since the system was started + * + * Return: + * The current system time in milliseconds + */ +v_TIME_t cdf_mc_timer_get_system_time(void); + +#endif /* #if !defined __CDF_MC_TIMER_H */ diff --git a/core/cdf/inc/cdf_memory.h b/core/cdf/inc/cdf_memory.h new file mode 100644 index 000000000000..7380089214ea --- /dev/null +++ b/core/cdf/inc/cdf_memory.h @@ -0,0 +1,225 @@ +/* + * 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(__CDF_MEMORY_H) +#define __CDF_MEMORY_H + +/** + * DOC: cdf_memory + * + * Connectivity driver framework (CDF) memory management APIs + */ + +/* Include Files */ +#include + +/* Preprocessor definitions and constants */ + +#ifdef MEMORY_DEBUG +void cdf_mem_clean(void); +void cdf_mem_init(void); +void cdf_mem_exit(void); +#else +/** + * cdf_mem_init() - initialize cdf memory debug functionality + * + * Return: none + */ +static inline void cdf_mem_init(void) +{ +} + +/** + * cdf_mem_exit() - exit cdf memory debug functionality + * + * Return: none + */ +static inline void cdf_mem_exit(void) +{ +} +#endif +/* Type declarations */ + +/* Function declarations and documenation */ + +/** + * cdf_mem_malloc() - allocation CDF memory + * @size: Number of bytes of memory to allocate. + * + * This function will dynamicallly allocate the specified number of bytes of + * memory. + * + * + * 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. + * + */ +#ifdef MEMORY_DEBUG +#define cdf_mem_malloc(size) cdf_mem_malloc_debug(size, __FILE__, __LINE__) +void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum); +#else +void *cdf_mem_malloc(size_t size); +#endif + +/** + * cdf_mem_free() - free CDF memory + * @ptr: Pointer to the starting address of the memory to be free'd. + * + * This function will free the memory pointed to by 'ptr'. + * + * Return: + * Nothing + * + */ +void cdf_mem_free(void *ptr); + +/** + * cdf_mem_set() - set (fill) memory with a specified byte value. + * @pMemory: Pointer to memory that will be set + * @numBytes: Number of bytes to be set + * @value: Byte set in memory + * + * Return: + * Nothing + * + */ +void cdf_mem_set(void *ptr, uint32_t numBytes, uint32_t value); + +/** + * cdf_mem_zero() - zero out memory + * @pMemory: pointer to memory that will be set to zero + * @numBytes: number of bytes zero + * @value: byte set in memory + * + * This function sets the memory location to all zeros, essentially clearing + * the memory. + * + * Return: + * Nothing + * + */ +void cdf_mem_zero(void *ptr, uint32_t numBytes); + +/** + * cdf_mem_copy() - copy memory + * @pDst: Pointer to destination memory location (to copy to) + * @pSrc: Pointer to source memory location (to copy from) + * @numBytes: Number of bytes to copy. + * + * 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 cdf_mem_move() if the memory locations + * for the source and destination are overlapping (or could be overlapping!) + * + * Return: + * Nothing + * + */ +void cdf_mem_copy(void *pDst, const void *pSrc, uint32_t numBytes); + +/** + * cdf_mem_move() - move memory + * @pDst: pointer to destination memory location (to move to) + * @pSrc: pointer to source memory location (to move from) + * @numBytes: number of bytes to move. + * + * 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. + + * Return: + * Nothing + */ +void cdf_mem_move(void *pDst, const void *pSrc, uint32_t numBytes); + +/** + * cdf_mem_compare() - memory compare + * @pMemory1: pointer to one location in memory to compare. + * @pMemory2: pointer to second location in memory to compare. + * @numBytes: the number of bytes to compare. + * + * Function to compare two pieces of memory, similar to memcmp function + * in standard C. + * + * Return: + * bool - returns a bool value that tells if the memory locations + * are equal or not equal. + * + */ +bool cdf_mem_compare(const void *pMemory1, const void *pMemory2, + uint32_t numBytes); + +/** + * cdf_mem_compare2() - memory compare + * @pMemory1: pointer to one location in memory to compare. + * @pMemory2: pointer to second location in memory to compare. + * @numBytes: the number of bytes to compare. + * + * Function to compare two pieces of memory, similar to memcmp function + * in standard C. + * Return: + * int32_t - returns a bool 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 + */ +int32_t cdf_mem_compare2(const void *pMemory1, const void *pMemory2, + uint32_t numBytes); + +void *cdf_os_mem_alloc_consistent(cdf_device_t osdev, cdf_size_t size, + cdf_dma_addr_t *paddr, + cdf_dma_context_t mctx); +void +cdf_os_mem_free_consistent(cdf_device_t osdev, + cdf_size_t size, + void *vaddr, + cdf_dma_addr_t paddr, cdf_dma_context_t memctx); + +void +cdf_os_mem_dma_sync_single_for_device(cdf_device_t osdev, + cdf_dma_addr_t bus_addr, + cdf_size_t size, + enum dma_data_direction direction); + +/** + * cdf_str_len() - returns the length of a string + * @str: input string + * + * Return: + * length of string + */ +static inline int32_t cdf_str_len(const char *str) +{ + return strlen(str); +} + +#endif /* __CDF_MEMORY_H */ diff --git a/core/cdf/inc/cdf_nbuf.h b/core/cdf/inc/cdf_nbuf.h new file mode 100644 index 000000000000..95981820d52b --- /dev/null +++ b/core/cdf/inc/cdf_nbuf.h @@ -0,0 +1,1053 @@ +/* + * 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. + */ + +/** + * DOC: cdf_nbuf_public network buffer API + * This file defines the network buffer abstraction. + */ + +#ifndef _CDF_NBUF_H +#define _CDF_NBUF_H +#include +#include +#include +#include +#include +#include + +#define IPA_NBUF_OWNER_ID 0xaa55aa55 +#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 NBUF_PKT_ERROR 1 + +/* Tracked Packet types */ +#define NBUF_TX_PKT_INVALID 0 +#define NBUF_TX_PKT_DATA_TRACK 1 +#define NBUF_TX_PKT_MGMT_TRACK 2 + +/* Different Packet states */ +#define NBUF_TX_PKT_HDD 1 +#define NBUF_TX_PKT_TXRX_ENQUEUE 2 +#define NBUF_TX_PKT_TXRX_DEQUEUE 3 +#define NBUF_TX_PKT_TXRX 4 +#define NBUF_TX_PKT_HTT 5 +#define NBUF_TX_PKT_HTC 6 +#define NBUF_TX_PKT_HIF 7 +#define NBUF_TX_PKT_CE 8 +#define NBUF_TX_PKT_FREE 9 +#define NBUF_TX_PKT_STATE_MAX 10 + + +/** + * @cdf_nbuf_t - Platform indepedent packet abstraction + */ +typedef __cdf_nbuf_t cdf_nbuf_t; + +/** + * @cdf_dma_map_cb_t - Dma map callback prototype + */ +typedef void (*cdf_dma_map_cb_t)(void *arg, cdf_nbuf_t buf, + cdf_dma_map_t dmap); + +/** + * @__CDF_NBUF_NULL - invalid handle + */ +#define CDF_NBUF_NULL __CDF_NBUF_NULL +/** + * @cdf_nbuf_queue_t - Platform independent packet queue abstraction + */ +typedef __cdf_nbuf_queue_t cdf_nbuf_queue_t; + +/* BUS/DMA mapping routines */ + +/** + * cdf_nbuf_map() - map a buffer to local bus address space + * @osdev: OS device + * @buf: Buf to be mapped (mapping info is stored in the buf's meta-data area) + * @dir: DMA direction + * + * Return: Status of the operation + */ +static inline CDF_STATUS +cdf_nbuf_map(cdf_device_t osdev, cdf_nbuf_t buf, cdf_dma_dir_t dir) +{ + return __cdf_nbuf_map(osdev, buf, dir); +} + +/** + * cdf_nbuf_unmap() - unmap a previously mapped buf + * @osdev: OS device + * @buf: Buf to be unmapped (mapping info is stored in the buf's meta-data area) + * @dir: DMA direction + * + * Return: none + */ +static inline void +cdf_nbuf_unmap(cdf_device_t osdev, cdf_nbuf_t buf, cdf_dma_dir_t dir) +{ + __cdf_nbuf_unmap(osdev, buf, dir); +} + +/** + * cdf_nbuf_map_single() - map a single buffer to local bus address space + * @osdev: OS device + * @buf: Buf to be mapped (mapping info is stored in the buf's meta-data area) + * @dir: DMA direction + * + * Return: Status of the operation + */ +static inline CDF_STATUS +cdf_nbuf_map_single(cdf_device_t osdev, cdf_nbuf_t buf, cdf_dma_dir_t dir) +{ + return __cdf_nbuf_map_single(osdev, buf, dir); +} + +/** + * cdf_nbuf_unmap_single() - unmap a previously mapped buf + * @osdev: OS device + * @buf: Buf to be unmapped (mapping info is stored in the buf's meta-data area) + * @dir: DMA direction + * + * Return: none + */ +static inline void +cdf_nbuf_unmap_single(cdf_device_t osdev, cdf_nbuf_t buf, cdf_dma_dir_t dir) +{ + __cdf_nbuf_unmap_single(osdev, buf, dir); +} + +/** + * cdf_nbuf_get_num_frags() - get number of fragments + * @buf: Network buffer + * + * Return: Number of fragments + */ +static inline int cdf_nbuf_get_num_frags(cdf_nbuf_t buf) +{ + return __cdf_nbuf_get_num_frags(buf); +} + +/** + * cdf_nbuf_get_frag_len() - get fragment length + * @buf: Network buffer + * @frag_num: Fragment number + * + * Return: Fragment length + */ +static inline int cdf_nbuf_get_frag_len(cdf_nbuf_t buf, int frag_num) +{ + return __cdf_nbuf_get_frag_len(buf, frag_num); +} + +/** + * cdf_nbuf_get_frag_vaddr() - get fragment virtual address + * @buf: Network buffer + * @frag_num: Fragment number + * + * Return: Fragment virtual address + */ +static inline unsigned char *cdf_nbuf_get_frag_vaddr(cdf_nbuf_t buf, + int frag_num) +{ + return __cdf_nbuf_get_frag_vaddr(buf, frag_num); +} + +/** + * cdf_nbuf_get_frag_paddr_lo() - get fragment physical address low order bytes + * @buf: Network buffer + * @frag_num: Fragment number + * + * Return: Fragment physical address lo + */ +static inline uint32_t cdf_nbuf_get_frag_paddr_lo(cdf_nbuf_t buf, int frag_num) +{ + return __cdf_nbuf_get_frag_paddr_lo(buf, frag_num); +} + +/** + * cdf_nbuf_get_frag_is_wordstream() - is fragment wordstream + * @buf: Network buffer + * @frag_num: Fragment number + * + * Return: Fragment wordstream or not + */ +static inline int cdf_nbuf_get_frag_is_wordstream(cdf_nbuf_t buf, int frag_num) +{ + return __cdf_nbuf_get_frag_is_wordstream(buf, frag_num); +} + +/** + * cdf_nbuf_set_frag_is_wordstream() - set fragment wordstream + * @buf: Network buffer + * @frag_num: Fragment number + * @is_wordstream: Wordstream + * + * Return: none + */ +static inline void +cdf_nbuf_set_frag_is_wordstream(cdf_nbuf_t buf, int frag_num, int is_wordstream) +{ + __cdf_nbuf_set_frag_is_wordstream(buf, frag_num, is_wordstream); +} + +/** + * cdf_nbuf_frag_push_head() - push fragment head + * @buf: Network buffer + * @frag_len: Fragment length + * @frag_vaddr: Fragment virtual address + * @frag_paddr_lo: Fragment physical address lo + * @frag_paddr_hi: Fragment physical address hi + * + * Return: none + */ +static inline void +cdf_nbuf_frag_push_head(cdf_nbuf_t buf, + int frag_len, + char *frag_vaddr, + uint32_t frag_paddr_lo, uint32_t frag_paddr_hi) +{ + __cdf_nbuf_frag_push_head(buf, frag_len, frag_vaddr, frag_paddr_lo, + frag_paddr_hi); +} + +#ifdef MEMORY_DEBUG +void cdf_net_buf_debug_init(void); +void cdf_net_buf_debug_exit(void); +void cdf_net_buf_debug_clean(void); +void cdf_net_buf_debug_add_node(cdf_nbuf_t net_buf, size_t size, + uint8_t *file_name, uint32_t line_num); +void cdf_net_buf_debug_delete_node(cdf_nbuf_t net_buf); +void cdf_net_buf_debug_release_skb(cdf_nbuf_t net_buf); + +/* nbuf allocation rouines */ + +/** + * cdf_nbuf_alloc() - Allocate cdf_nbuf + * @hdl: Platform device object + * @size: Data buffer size for this cdf_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) + * + * The nbuf created is guarenteed to have only 1 physical segment + * + * Return: The new cdf_nbuf instance or NULL if there's not enough memory. + */ + +#define cdf_nbuf_alloc(d, s, r, a, p) \ + cdf_nbuf_alloc_debug(d, s, r, a, p, __FILE__, __LINE__) +static inline cdf_nbuf_t +cdf_nbuf_alloc_debug(cdf_device_t osdev, cdf_size_t size, int reserve, + int align, int prio, uint8_t *file_name, + uint32_t line_num) +{ + cdf_nbuf_t net_buf; + net_buf = __cdf_nbuf_alloc(osdev, size, reserve, align, prio); + + /* Store SKB in internal CDF tracking table */ + if (cdf_likely(net_buf)) + cdf_net_buf_debug_add_node(net_buf, size, file_name, line_num); + + return net_buf; +} + +/** + * cdf_nbuf_free() - free cdf_nbuf + * @net_buf: Network buffer to free + * + * Return: none + */ +static inline void cdf_nbuf_free(cdf_nbuf_t net_buf) +{ + /* Remove SKB from internal CDF tracking table */ + if (cdf_likely(net_buf)) + cdf_net_buf_debug_delete_node(net_buf); + + __cdf_nbuf_free(net_buf); +} + +#else + +static inline void cdf_net_buf_debug_release_skb(cdf_nbuf_t net_buf) +{ + return; +} + +/* Nbuf allocation rouines */ + +/** + * cdf_nbuf_alloc() - allocate cdf_nbuf + * @hdl: Platform device object + * @size: Data buffer size for this cdf_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) + * + * The nbuf created is guarenteed to have only 1 physical segment + * + * Return: new cdf_nbuf instance or NULL if there's not enough memory. + */ +static inline cdf_nbuf_t +cdf_nbuf_alloc(cdf_device_t osdev, + cdf_size_t size, int reserve, int align, int prio) +{ + return __cdf_nbuf_alloc(osdev, size, reserve, align, prio); +} + +/** + * cdf_nbuf_free() - free cdf_nbuf + * @buf: Network buffer to free + * + * Return: none + */ +static inline void cdf_nbuf_free(cdf_nbuf_t buf) +{ + __cdf_nbuf_free(buf); +} + +#endif + +/** + * cdf_nbuf_tx_free() - free a list of cdf_nbufs and tell the OS their tx + * status (if req'd) + * @bufs: List of netbufs to free + * @tx_err: Whether the tx frames were transmitted successfully + * + * Return: none + */ +static inline void cdf_nbuf_tx_free(cdf_nbuf_t buf_list, int tx_err) +{ + __cdf_nbuf_tx_free(buf_list, tx_err); +} + +/** + * cdf_nbuf_copy() - copy src buffer into dst. + * @buf: source nbuf to copy from + * + * 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. + * + * + * Return: new nbuf + */ +static inline cdf_nbuf_t cdf_nbuf_copy(cdf_nbuf_t buf) +{ + return __cdf_nbuf_copy(buf); +} + +/** + * cdf_nbuf_cat() - link two nbufs, the new buf is piggybacked into older one + * @dst: Buffer to piggyback into + * @src: Buffer to put + * + * Return: Status of the call - 0 successful + */ +static inline CDF_STATUS cdf_nbuf_cat(cdf_nbuf_t dst, cdf_nbuf_t src) +{ + return __cdf_nbuf_cat(dst, src); +} + +/** + * @cdf_nbuf_copy_bits() - return the length of the copy bits for skb + * @skb: SKB pointer + * @offset: offset + * @len: Length + * @to: To + * + * Return: int32_t + */ +static inline int32_t +cdf_nbuf_copy_bits(cdf_nbuf_t nbuf, uint32_t offset, uint32_t len, void *to) +{ + return __cdf_nbuf_copy_bits(nbuf, offset, len, to); +} + +/** + * cdf_nbuf_clone() - clone the nbuf (copy is readonly) + * @buf: nbuf to clone from + * + * Return: cloned buffer + */ +static inline cdf_nbuf_t cdf_nbuf_clone(cdf_nbuf_t buf) +{ + return __cdf_nbuf_clone(buf); +} + +/* nbuf manipulation routines */ + +/** + * @cdf_nbuf_head() - return the address of an nbuf's buffer + * @buf: netbuf + * + * Return: head address + */ +static inline uint8_t *cdf_nbuf_head(cdf_nbuf_t buf) +{ + return __cdf_nbuf_head(buf); +} + +/** + * cdf_nbuf_data() - Return the address of the start of data within an nbuf + * @buf: Network buffer + * + * Return: Data address + */ +static inline uint8_t *cdf_nbuf_data(cdf_nbuf_t buf) +{ + return __cdf_nbuf_data(buf); +} + +/** + * cdf_nbuf_headroom() - amount of headroom int the current nbuf + * @buf: Network buffer + * + * Return: Amount of head room + */ +static inline uint32_t cdf_nbuf_headroom(cdf_nbuf_t buf) +{ + return __cdf_nbuf_headroom(buf); +} + +/** + * cdf_nbuf_tailroom() - amount of tail space available + * @buf: Network buffer + * + * Return: amount of tail room + */ +static inline uint32_t cdf_nbuf_tailroom(cdf_nbuf_t buf) +{ + return __cdf_nbuf_tailroom(buf); +} + +/** + * cdf_nbuf_push_head() - push data in the front + * @buf: Network buf instance + * @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 *cdf_nbuf_push_head(cdf_nbuf_t buf, cdf_size_t size) +{ + return __cdf_nbuf_push_head(buf, size); +} + +/** + * cdf_nbuf_put_tail() - puts data in the end + * @buf: Network buf instance + * @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 *cdf_nbuf_put_tail(cdf_nbuf_t buf, cdf_size_t size) +{ + return __cdf_nbuf_put_tail(buf, size); +} + +/** + * cdf_nbuf_pull_head() - pull data out from the front + * @buf: Network buf instance + * @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 *cdf_nbuf_pull_head(cdf_nbuf_t buf, cdf_size_t size) +{ + return __cdf_nbuf_pull_head(buf, size); +} + +/** + * cdf_nbuf_trim_tail() - trim data out from the end + * @buf: Network buf instance + * @size: Size to be popped + * + * Return: none + */ +static inline void cdf_nbuf_trim_tail(cdf_nbuf_t buf, cdf_size_t size) +{ + __cdf_nbuf_trim_tail(buf, size); +} + +/** + * cdf_nbuf_len() - get the length of the buf + * @buf: Network buf instance + * + * Return: total length of this buf. + */ +static inline cdf_size_t cdf_nbuf_len(cdf_nbuf_t buf) +{ + return __cdf_nbuf_len(buf); +} + +/** + * cdf_nbuf_set_pktlen() - set the length of the buf + * @buf: Network buf instance + * @size: Size to be set + * + * Return: none + */ +static inline void cdf_nbuf_set_pktlen(cdf_nbuf_t buf, uint32_t len) +{ + __cdf_nbuf_set_pktlen(buf, len); +} + +/** + * cdf_nbuf_reserve() - trim data out from the end + * @buf: Network buf instance + * @size: Size to be popped + * + * Return: none + */ +static inline void cdf_nbuf_reserve(cdf_nbuf_t buf, cdf_size_t size) +{ + __cdf_nbuf_reserve(buf, size); +} + +/** + * cdf_nbuf_peek_header() - return the data pointer & length of the header + * @buf: Network nbuf + * @addr: Data pointer + * @len: Length of the data + * + * Return: none + */ +static inline void +cdf_nbuf_peek_header(cdf_nbuf_t buf, uint8_t **addr, uint32_t *len) +{ + __cdf_nbuf_peek_header(buf, addr, len); +} + +/* nbuf private context routines */ + +/* nbuf queue routines */ + +/** + * cdf_nbuf_queue_init() - initialize buf queue + * @head: Network buf queue head + * + * Return: none + */ +static inline void cdf_nbuf_queue_init(cdf_nbuf_queue_t *head) +{ + __cdf_nbuf_queue_init(head); +} + +/** + * cdf_nbuf_queue_add() - append a nbuf to the tail of the buf queue + * @head: Network buf queue head + * @buf: Network buf + * + * Return: none + */ +static inline void cdf_nbuf_queue_add(cdf_nbuf_queue_t *head, cdf_nbuf_t buf) +{ + __cdf_nbuf_queue_add(head, buf); +} + +/** + * cdf_nbuf_queue_insert_head() - insert nbuf at the head of queue + * @head: Network buf queue head + * @buf: Network buf + * + * Return: none + */ +static inline void +cdf_nbuf_queue_insert_head(cdf_nbuf_queue_t *head, cdf_nbuf_t buf) +{ + __cdf_nbuf_queue_insert_head(head, buf); +} + +/** + * cdf_nbuf_queue_remove() - retrieve a buf from the head of the buf queue + * @head: Network buf queue head + * + * Return: The head buf in the buf queue. + */ +static inline cdf_nbuf_t cdf_nbuf_queue_remove(cdf_nbuf_queue_t *head) +{ + return __cdf_nbuf_queue_remove(head); +} + +/** + * cdf_nbuf_queue_len() - get the length of the queue + * @head: Network buf queue head + * + * Return: length of the queue + */ +static inline uint32_t cdf_nbuf_queue_len(cdf_nbuf_queue_t *head) +{ + return __cdf_nbuf_queue_len(head); +} + +/** + * cdf_nbuf_queue_next() - get the next guy/packet of the given buffer + * @buf: Network buffer + * + * Return: next buffer/packet + */ +static inline cdf_nbuf_t cdf_nbuf_queue_next(cdf_nbuf_t buf) +{ + return __cdf_nbuf_queue_next(buf); +} + +/** + * @cdf_nbuf_is_queue_empty() - check if the buf queue is empty + * @nbq: Network buf queue handle + * + * Return: true if queue is empty + * false if queue is not emty + */ +static inline bool cdf_nbuf_is_queue_empty(cdf_nbuf_queue_t *nbq) +{ + return __cdf_nbuf_is_queue_empty(nbq); +} + +/** + * cdf_nbuf_next() - get the next packet in the linked list + * @buf: Network buffer + * + * This function can be used when nbufs are directly linked into a list, + * rather than using a separate network buffer queue object. + * + * Return: next network buffer in the linked list + */ +static inline cdf_nbuf_t cdf_nbuf_next(cdf_nbuf_t buf) +{ + return __cdf_nbuf_next(buf); +} + +/** + * cdf_nbuf_get_protocol() - return the protocol value of the skb + * @skb: Pointer to network buffer + * + * Return: skb protocol + */ +static inline uint16_t cdf_nbuf_get_protocol(struct sk_buff *skb) +{ + return __cdf_nbuf_get_protocol(skb); +} + +/** + * cdf_nbuf_get_ip_summed() - return the ip checksum value of the skb + * @skb: Pointer to network buffer + * + * Return: skb ip_summed + */ +static inline uint8_t cdf_nbuf_get_ip_summed(struct sk_buff *skb) +{ + return __cdf_nbuf_get_ip_summed(skb); +} + +/** + * cdf_nbuf_set_ip_summed() - sets the ip_summed value of the skb + * @skb: Pointer to network buffer + * @ip_summed: ip checksum + * + * Return: none + */ +static inline void cdf_nbuf_set_ip_summed(struct sk_buff *skb, uint8_t ip_summed) +{ + __cdf_nbuf_set_ip_summed(skb, ip_summed); +} + +/** + * cdf_nbuf_set_next() - add a packet to a linked list + * @this_buf: Predecessor buffer + * @next_buf: Successor buffer + * + * This function can be used to directly link nbufs, rather than using + * a separate network buffer queue object. + * + * Return: none + */ +static inline void cdf_nbuf_set_next(cdf_nbuf_t this_buf, cdf_nbuf_t next_buf) +{ + __cdf_nbuf_set_next(this_buf, next_buf); +} + +/* nbuf extension routines */ + +/** + * cdf_nbuf_set_next_ext() - link extension of this packet contained in a new + * nbuf + * @this_buf: predecessor buffer + * @next_buf: successor buffer + * + * 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 + * + * Return: none + */ +static inline void +cdf_nbuf_set_next_ext(cdf_nbuf_t this_buf, cdf_nbuf_t next_buf) +{ + __cdf_nbuf_set_next_ext(this_buf, next_buf); +} + +/** + * cdf_nbuf_next_ext() - get the next packet extension in the linked list + * @buf: Network buffer + * + * Return: Next network buffer in the linked list + */ +static inline cdf_nbuf_t cdf_nbuf_next_ext(cdf_nbuf_t buf) +{ + return __cdf_nbuf_next_ext(buf); +} + +/** + * cdf_nbuf_append_ext_list() - link list of packet extensions to the head + * segment + * @head_buf: Network buf holding head segment (single) + * @ext_list: Network buf list holding linked extensions to the head + * @ext_len: Total length of all buffers in the extension list + * + * This function is used to link up a list of packet extensions (seg1, 2, + * ...) to the nbuf holding the head segment (seg0) + * + * Return: none + */ +static inline void +cdf_nbuf_append_ext_list(cdf_nbuf_t head_buf, cdf_nbuf_t ext_list, + cdf_size_t ext_len) +{ + __cdf_nbuf_append_ext_list(head_buf, ext_list, ext_len); +} + +/** + * cdf_nbuf_get_tx_cksum() - gets the tx checksum offload demand + * @buf: Network buffer + * + * Return: cdf_nbuf_tx_cksum_t checksum offload demand for the frame + */ +static inline cdf_nbuf_tx_cksum_t cdf_nbuf_get_tx_cksum(cdf_nbuf_t buf) +{ + return __cdf_nbuf_get_tx_cksum(buf); +} + +/** + * cdf_nbuf_set_rx_cksum() - drivers that support hw checksumming use this to + * indicate checksum info to the stack. + * @buf: Network buffer + * @cksum: Checksum + * + * Return: none + */ +static inline void +cdf_nbuf_set_rx_cksum(cdf_nbuf_t buf, cdf_nbuf_rx_cksum_t *cksum) +{ + __cdf_nbuf_set_rx_cksum(buf, cksum); +} + +/** + * cdf_nbuf_get_tid() - this function extracts the TID value from nbuf + * @buf: Network buffer + * + * Return: TID value + */ +static inline uint8_t cdf_nbuf_get_tid(cdf_nbuf_t buf) +{ + return __cdf_nbuf_get_tid(buf); +} + +/** + * cdf_nbuf_set_tid() - this function sets the TID value in nbuf + * @buf: Network buffer + * @tid: TID value + * + * Return: none + */ +static inline void cdf_nbuf_set_tid(cdf_nbuf_t buf, uint8_t tid) +{ + __cdf_nbuf_set_tid(buf, tid); +} + +/** + * cdf_nbuf_get_exemption_type() - this function extracts the exemption type + * from nbuf + * @buf: Network buffer + * + * Return: Exemption type + */ +static inline uint8_t cdf_nbuf_get_exemption_type(cdf_nbuf_t buf) +{ + return __cdf_nbuf_get_exemption_type(buf); +} + +/** + * cdf_nbuf_set_protocol() - this function peeks data into the buffer at given + * offset + * @buf: Network buffer + * @proto: Protocol + * + * Return: none + */ +static inline void cdf_nbuf_set_protocol(cdf_nbuf_t buf, uint16_t proto) +{ + __cdf_nbuf_set_protocol(buf, proto); +} + +/** + * cdf_nbuf_trace_get_proto_type() - this function return packet proto type + * @buf: Network buffer + * + * Return: Packet protocol type + */ +static inline uint8_t cdf_nbuf_trace_get_proto_type(cdf_nbuf_t buf) +{ + return __cdf_nbuf_trace_get_proto_type(buf); +} + +#ifdef QCA_PKT_PROTO_TRACE +/** + * cdf_nbuf_trace_set_proto_type() - this function updates packet proto type + * @buf: Network buffer + * @proto_type: Protocol type + * + * Return: none + */ +static inline void +cdf_nbuf_trace_set_proto_type(cdf_nbuf_t buf, uint8_t proto_type) +{ + __cdf_nbuf_trace_set_proto_type(buf, proto_type); +} +#else +#define cdf_nbuf_trace_set_proto_type(buf, proto_type) /*NO OP*/ +#endif + +/** + * cdf_nbuf_reg_trace_cb() - this function registers protocol trace callback + * @cb_func_ptr: Callback pointer + * + * Return: none + */ +static inline void cdf_nbuf_reg_trace_cb(cdf_nbuf_trace_update_t cb_func_ptr) +{ + __cdf_nbuf_reg_trace_cb(cb_func_ptr); +} + +/** + * cdf_nbuf_trace_update() - this function updates protocol event + * @buf: Network buffer + * @event_string: Event string pointer + * + * Return: none + */ +static inline void cdf_nbuf_trace_update(cdf_nbuf_t buf, char *event_string) +{ + __cdf_nbuf_trace_update(buf, event_string); +} + +/** + * cdf_nbuf_set_tx_parallel_dnload_frm() - set tx parallel download + * @buf: Network buffer + * @candi: Candidate of parallel download frame + * + * 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. + * + * Return: none + */ +static inline void +cdf_nbuf_set_tx_parallel_dnload_frm(cdf_nbuf_t buf, uint8_t candi) +{ + __cdf_nbuf_set_tx_htt2_frm(buf, candi); +} + +/** + * cdf_nbuf_get_tx_parallel_dnload_frm() - get tx parallel download + * @buf: Network buffer + * + * This function return whether this TX frame is allow to download though a 2nd + * TX data pipe or not. + * + * Return: none + */ +static inline uint8_t cdf_nbuf_get_tx_parallel_dnload_frm(cdf_nbuf_t buf) +{ + return __cdf_nbuf_get_tx_htt2_frm(buf); +} + +/** + * cdf_invalidate_range() - invalidate the virtual address range specified by + * start and end addresses. + * Note: This does not write back the cache entries. + * + * Return: none + */ +static inline void cdf_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 */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Cache invalidate not yet implemneted for non-MSM platform"); + return; +#endif +} + +#if defined(FEATURE_TSO) +/** + * cdf_nbuf_dec_num_frags() - decrement the number of fragments + * @buf: Network buffer + * + * Return: Number of fragments + */ +static inline int cdf_nbuf_dec_num_frags(cdf_nbuf_t buf) +{ + return __cdf_nbuf_dec_num_frags(buf); +} + +/** + * cdf_nbuf_is_tso() - is the network buffer a jumbo packet? + * @buf: Network buffer + * + * Return: 1 - this is a jumbo packet 0 - not a jumbo packet + */ +static inline uint8_t cdf_nbuf_is_tso(cdf_nbuf_t nbuf) +{ + return __cdf_nbuf_is_tso(nbuf); +} + +/** + * cdf_nbuf_get_tso_info() - function to divide a jumbo TSO + * network buffer into segments + * @nbuf: network buffer to be segmented + * @tso_info: This is the output. The information about the + * TSO segments will be populated within this. + * + * This function fragments a TCP jumbo packet into smaller + * segments to be transmitted by the driver. It chains the TSO + * segments created into a list. + * + * Return: number of TSO segments + */ +static inline uint32_t cdf_nbuf_get_tso_info(cdf_device_t osdev, + cdf_nbuf_t nbuf, struct cdf_tso_info_t *tso_info) +{ + return __cdf_nbuf_get_tso_info(osdev, nbuf, tso_info); +} + +/** + * cdf_nbuf_get_tso_num_seg() - function to calculate the number + * of TCP segments within the TSO jumbo packet + * @nbuf: TSO jumbo network buffer to be segmented + * + * This function calculates the number of TCP segments that the + network buffer can be divided into. + * + * Return: number of TCP segments + */ +static inline uint32_t cdf_nbuf_get_tso_num_seg(cdf_nbuf_t nbuf) +{ + return __cdf_nbuf_get_tso_num_seg(nbuf); +} + +/** + * cdf_nbuf_inc_users() - function to increment the number of + * users referencing this network buffer + * + * @nbuf: network buffer + * + * This function increments the number of users referencing this + * network buffer + * + * Return: the network buffer + */ +static inline cdf_nbuf_t cdf_nbuf_inc_users(cdf_nbuf_t nbuf) +{ + return __cdf_nbuf_inc_users(nbuf); +} +#endif /*TSO*/ + +/** + * cdf_nbuf_data_attr_get() - Get data_attr field from cvg_nbuf_cb + * + * @nbuf: Network buffer (skb on linux) + * + * This function returns the values of data_attr field + * in struct cvg_nbuf_cb{}, to which skb->cb is typecast. + * This value is actually the value programmed in CE descriptor. + * + * Return: Value of data_attr + */ +static inline +uint32_t cdf_nbuf_data_attr_get(cdf_nbuf_t buf) +{ + return __cdf_nbuf_data_attr_get(buf); +} + +/** + * cdf_nbuf_data_attr_set() - Sets data_attr field in cvg_nbuf_cb + * + * @nbuf: Network buffer (skb on linux) + * @data_attr: Value to be stored cvg_nbuf_cb->data_attr + * + * This function stores the value to be programmed in CE + * descriptor as part skb->cb which is typecast to struct cvg_nbuf_cb{} + * + * Return: void + */ +static inline +void cdf_nbuf_data_attr_set(cdf_nbuf_t buf, uint32_t data_attr) +{ + __cdf_nbuf_data_attr_set(buf, data_attr); +} + +/** + * cdf_nbuf_tx_info_get() - Parse skb and get Tx metadata + * + * @nbuf: Network buffer (skb on linux) + * + * This function parses the payload to figure out relevant + * Tx meta-data e.g. whether to enable tx_classify bit + * in CE. + * + * Return: void + */ +#define cdf_nbuf_tx_info_get __cdf_nbuf_tx_info_get + +void cdf_nbuf_set_state(cdf_nbuf_t nbuf, uint8_t current_state); +void cdf_nbuf_tx_desc_count_display(void); +void cdf_nbuf_tx_desc_count_clear(void); + +#endif diff --git a/core/cdf/inc/cdf_net_types.h b/core/cdf/inc/cdf_net_types.h new file mode 100644 index 000000000000..fc70c110e39c --- /dev/null +++ b/core/cdf/inc/cdf_net_types.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/** + * DOC: cdf_net_types + * This file defines types used in the networking stack abstraction. + */ + +#ifndef _CDF_NET_TYPES_H +#define _CDF_NET_TYPES_H + +#include /* uint8_t, etc. */ + +#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 + +/* Extended Traffic ID passed to target if the TID is unknown */ +#define ADF_NBUF_TX_EXT_TID_INVALID 0x1f + +/** + * cdf_nbuf_exemption_type - CDF net buf exemption types for encryption + * @CDF_NBUF_EXEMPT_NO_EXEMPTION: No exemption + * @CDF_NBUF_EXEMPT_ALWAYS: Exempt always + * @CDF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: Exempt on key mapping + */ +enum cdf_nbuf_exemption_type { + CDF_NBUF_EXEMPT_NO_EXEMPTION = 0, + CDF_NBUF_EXEMPT_ALWAYS, + CDF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE +}; + +/** + * typedef cdf_nbuf_tx_cksum_t - transmit checksum offload types + * @CDF_NBUF_TX_CKSUM_NONE: No checksum offload + * @CDF_NBUF_TX_CKSUM_IP: IP header checksum offload + * @CDF_NBUF_TX_CKSUM_TCP_UDP: TCP/UDP checksum offload + * @CDF_NBUF_TX_CKSUM_TCP_UDP_IP: TCP/UDP and IP header checksum offload + */ + +typedef enum { + CDF_NBUF_TX_CKSUM_NONE, + CDF_NBUF_TX_CKSUM_IP, + CDF_NBUF_TX_CKSUM_TCP_UDP, + CDF_NBUF_TX_CKSUM_TCP_UDP_IP, + +} cdf_nbuf_tx_cksum_t; + +/** + * typedef cdf_nbuf_l4_rx_cksum_type_t - receive checksum API types + * @CDF_NBUF_RX_CKSUM_TCP: Rx checksum TCP + * @CDF_NBUF_RX_CKSUM_UDP: Rx checksum UDP + * @CDF_NBUF_RX_CKSUM_TCPIPV6: Rx checksum TCP IPV6 + * @CDF_NBUF_RX_CKSUM_UDPIPV6: Rx checksum UDP IPV6 + * @CDF_NBUF_RX_CKSUM_TCP_NOPSEUDOHEADER: Rx checksum TCP no pseudo header + * @CDF_NBUF_RX_CKSUM_UDP_NOPSEUDOHEADER: Rx checksum UDP no pseudo header + * @CDF_NBUF_RX_CKSUM_TCPSUM16: Rx checksum TCP SUM16 + */ +typedef enum { + CDF_NBUF_RX_CKSUM_TCP = 0x0001, + CDF_NBUF_RX_CKSUM_UDP = 0x0002, + CDF_NBUF_RX_CKSUM_TCPIPV6 = 0x0010, + CDF_NBUF_RX_CKSUM_UDPIPV6 = 0x0020, + CDF_NBUF_RX_CKSUM_TCP_NOPSEUDOHEADER = 0x0100, + CDF_NBUF_RX_CKSUM_UDP_NOPSEUDOHEADER = 0x0200, + CDF_NBUF_RX_CKSUM_TCPSUM16 = 0x1000, +} cdf_nbuf_l4_rx_cksum_type_t; + +/** + * typedef cdf_nbuf_l4_rx_cksum_result_t - receive checksum status types + * @CDF_NBUF_RX_CKSUM_NONE: Device failed to checksum + * @CDF_NBUF_RX_CKSUM_TCP_UDP_HW: TCP/UDP cksum successful and value returned + * @CDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY: TCP/UDP cksum successful, no value + */ +typedef enum { + CDF_NBUF_RX_CKSUM_NONE = 0x0000, + CDF_NBUF_RX_CKSUM_TCP_UDP_HW = 0x0010, + CDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY = 0x0020, +} cdf_nbuf_l4_rx_cksum_result_t; + +/** + * typedef cdf_nbuf_rx_cksum_t - receive checksum type + * @l4_type: L4 type + * @l4_result: L4 result + */ +typedef struct { + cdf_nbuf_l4_rx_cksum_type_t l4_type; + cdf_nbuf_l4_rx_cksum_result_t l4_result; + uint32_t val; +} cdf_nbuf_rx_cksum_t; + +#endif /*_CDF_NET_TYPES_H*/ diff --git a/core/cdf/inc/cdf_softirq_timer.h b/core/cdf/inc/cdf_softirq_timer.h new file mode 100644 index 000000000000..d05a9509f59d --- /dev/null +++ b/core/cdf/inc/cdf_softirq_timer.h @@ -0,0 +1,118 @@ +/* + * 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. + */ + +/** + * DOC: cdf_softirq_timer + * This file abstracts OS timers running in soft IRQ context. + */ + +#ifndef _CDF_SOFTIRQ_TIMER_H +#define _CDF_SOFTIRQ_TIMER_H + +#include +#include + +/* Platform timer object */ +typedef __cdf_softirq_timer_t cdf_softirq_timer_t; + +/** + * cdf_softirq_timer_init() - initialize a softirq timer + * @hdl: OS handle + * @timer: Timer object pointer + * @func: Timer function + * @arg: Arguement of timer function + * @type: deferrable or non deferrable timer type + * + * Timer type CDF_TIMER_TYPE_SW means its a deferrable sw timer which will + * not cause CPU wake upon expiry + * Timer type CDF_TIMER_TYPE_WAKE_APPS means its a non-deferrable timer which + * will cause CPU wake up on expiry + * + * Return: none + */ +static inline void +cdf_softirq_timer_init(cdf_handle_t hdl, + cdf_softirq_timer_t *timer, + cdf_softirq_timer_func_t func, void *arg, + CDF_TIMER_TYPE type) +{ + __cdf_softirq_timer_init(hdl, timer, func, arg, type); +} + +/** + * cdf_softirq_timer_start() - start a one-shot softirq timer + * @timer: Timer object pointer + * @msec: Expiration period in milliseconds + * + * Return: none + */ +static inline void +cdf_softirq_timer_start(cdf_softirq_timer_t *timer, int msec) +{ + __cdf_softirq_timer_start(timer, msec); +} + +/** + * cdf_softirq_timer_mod() - modify existing timer to new timeout value + * @timer: Timer object pointer + * @msec: Expiration period in milliseconds + * + * Return: none + */ +static inline void cdf_softirq_timer_mod(cdf_softirq_timer_t *timer, int msec) +{ + __cdf_softirq_timer_mod(timer, msec); +} + +/** + * cdf_softirq_timer_cancel() - cancel cdf softirq timer + * @timer: Timer object pointer + * @retval: Timer was cancelled and deactived + * @retval: Timer was cancelled but already got fired. + * + * The function will return after any running timer completes. + * + * Return: none + */ +static inline bool cdf_softirq_timer_cancel(cdf_softirq_timer_t *timer) +{ + return __cdf_softirq_timer_cancel(timer); +} + +/** + * cdf_softirq_timer_free() - free cdf softirq timer + * @timer: Timer object pointer + * + * The function will return after any running timer completes. + * Return: none + */ +static inline void cdf_softirq_timer_free(cdf_softirq_timer_t *timer) +{ + __cdf_softirq_timer_free(timer); +} + +#endif diff --git a/core/cdf/inc/cdf_status.h b/core/cdf/inc/cdf_status.h new file mode 100644 index 000000000000..635b4ad33bc2 --- /dev/null +++ b/core/cdf/inc/cdf_status.h @@ -0,0 +1,111 @@ +/* + * 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(__CDF_STATUS_H) +#define __CDF_STATUS_H + +/** + * DOC: cdf_status + * + * Connectivity driver framework (CDF) status codes + * + * Basic status codes/definitions used by CDF + */ + +/** + * typedef CDF_STATUS - CDF error codes + * @CDF_STATUS_SUCCESS: success + * @CDF_STATUS_E_RESOURCES: system resource(other than memory) not available + * @CDF_STATUS_E_NOMEM: not enough memory + * @CDF_STATUS_E_AGAIN: try again + * @CDF_STATUS_E_INVAL: invalid request + * @CDF_STATUS_E_FAULT: system fault + * @CDF_STATUS_E_ALREADY: another request already in progress + * @CDF_STATUS_E_BADMSG: bad message + * @CDF_STATUS_E_BUSY: device or resource busy + * @CDF_STATUS_E_CANCELED: request cancelled + * @CDF_STATUS_E_ABORTED: request aborted + * @CDF_STATUS_E_NOSUPPORT: request not supported + * @CDF_STATUS_E_PERM: operation not permitted + * @CDF_STATUS_E_EMPTY: empty condition + * @CDF_STATUS_E_EXISTS: existence failure + * @CDF_STATUS_E_TIMEOUT: operation timeout + * @CDF_STATUS_E_FAILURE: unknown reason do not use unless nothign else applies + * @CDF_STATUS_NOT_INITIALIZED: resource not initialized + * @CDF_STATUS_E_NULL_VALUE: request is null + * @CDF_STATUS_PMC_PENDING: request pendign in pmc + * @CDF_STATUS_PMC_DISABLED: pmc is disabled + * @CDF_STATUS_PMC_NOT_NOW: pmc not ready now + * @CDF_STATUS_PMC_AC_POWER: pmc ac power + * @CDF_STATUS_PMC_SYS_ERROR: pmc system error + * @CDF_STATUS_HEARTBEAT_TMOUT: hearbeat timeout error + * @CDF_STATUS_NTH_BEACON_DELIVERY: Nth beacon delivery + * @CDF_STATUS_CSR_WRONG_STATE: csr in wrong state + * @CDF_STATUS_FT_PREAUTH_KEY_SUCCESS: ft preauth key success + * @CDF_STATUS_FT_PREAUTH_KEY_FAILED: ft preauth key failed + * @CDF_STATUS_CMD_NOT_QUEUED: command not queued + * @CDF_STATUS_FW_MSG_TIMEDOUT: target message timeout + * @CDF_STATUS_MAX: not a realy value just a place holder for max + */ +typedef enum { + CDF_STATUS_SUCCESS, + CDF_STATUS_E_RESOURCES, + CDF_STATUS_E_NOMEM, + CDF_STATUS_E_AGAIN, + CDF_STATUS_E_INVAL, + CDF_STATUS_E_FAULT, + CDF_STATUS_E_ALREADY, + CDF_STATUS_E_BADMSG, + CDF_STATUS_E_BUSY, + CDF_STATUS_E_CANCELED, + CDF_STATUS_E_ABORTED, + CDF_STATUS_E_NOSUPPORT, + CDF_STATUS_E_PERM, + CDF_STATUS_E_EMPTY, + CDF_STATUS_E_EXISTS, + CDF_STATUS_E_TIMEOUT, + CDF_STATUS_E_FAILURE, + CDF_STATUS_NOT_INITIALIZED, + CDF_STATUS_E_NULL_VALUE, + CDF_STATUS_PMC_PENDING, + CDF_STATUS_PMC_DISABLED, + CDF_STATUS_PMC_NOT_NOW, + CDF_STATUS_PMC_AC_POWER, + CDF_STATUS_PMC_SYS_ERROR, + CDF_STATUS_HEARTBEAT_TMOUT, + CDF_STATUS_NTH_BEACON_DELIVERY, + CDF_STATUS_CSR_WRONG_STATE, + CDF_STATUS_FT_PREAUTH_KEY_SUCCESS, + CDF_STATUS_FT_PREAUTH_KEY_FAILED, + CDF_STATUS_CMD_NOT_QUEUED, + CDF_STATUS_FW_MSG_TIMEDOUT, + CDF_STATUS_MAX +} CDF_STATUS; + +#define CDF_IS_STATUS_SUCCESS(status) (CDF_STATUS_SUCCESS == (status)) + +#endif /* if !defined __CDF_STATUS_H */ diff --git a/core/cdf/inc/cdf_threads.h b/core/cdf/inc/cdf_threads.h new file mode 100644 index 000000000000..8aa320c50d75 --- /dev/null +++ b/core/cdf/inc/cdf_threads.h @@ -0,0 +1,83 @@ +/* + * 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(__CDF_THREADS_H) +#define __CDF_THREADS_H + +/** + * DOC: cdf_threads + * + * Connectivity driver framework (CDF) thread related APIs + * + */ + +/* Include Files */ +#include + +/* Preprocessor definitions and constants */ + +/* Type declarations */ + +/* Function declarations and documenation */ + +/** + * cdf_sleep() - sleep + * @msInterval : Number of milliseconds to suspend the current thread. + * A value of 0 may or may not cause the current thread to yield. + * + * This function suspends the execution of the current thread + * until the specified time out interval elapses. + * + * Return: nothing + */ +void cdf_sleep(uint32_t msInterval); + +/** + * cdf_sleep_us() - sleep + * @usInterval : Number of microseconds to suspend the current thread. + * A value of 0 may or may not cause the current thread to yield. + * + * This function suspends the execution of the current thread + * until the specified time out interval elapses. + * + * Return : nothing + */ +void cdf_sleep_us(uint32_t usInterval); + +/** + * cdf_busy_wait() - busy wait + * @usInterval : Number of microseconds to busy wait. + * + * This 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. + * + * Return : nothing + */ +void cdf_busy_wait(uint32_t usInterval); + +#endif /* __CDF_THREADS_H */ diff --git a/core/cdf/inc/cdf_time.h b/core/cdf/inc/cdf_time.h new file mode 100644 index 000000000000..6f5d1f5214df --- /dev/null +++ b/core/cdf/inc/cdf_time.h @@ -0,0 +1,184 @@ +/* + * 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. + */ + +/** + * DOC: cdf_time + * This file abstracts time related functionality. + */ + +#ifndef _CDF_OS_TIME_H +#define _CDF_OS_TIME_H + +#include +#ifdef CONFIG_CNSS +#include +#endif + +typedef __cdf_time_t cdf_time_t; + +/** + * cdf_system_ticks() - Count the number of ticks elapsed from the time when + * the system booted + * + * Return: ticks + */ +static inline unsigned long cdf_system_ticks(void) +{ + return __cdf_system_ticks(); +} + +/** + * cdf_system_ticks_to_msecs() - convert ticks to milliseconds + * @clock_ticks: Number of ticks + * + * Return: Time in milliseconds + */ +static inline uint32_t cdf_system_ticks_to_msecs(unsigned long clock_ticks) +{ + return __cdf_system_ticks_to_msecs(clock_ticks); +} + +/** + * cdf_system_msecs_to_ticks() - convert milliseconds to ticks + * @msec: Time in milliseconds + * + * Return: number of ticks + */ +static inline unsigned long cdf_system_msecs_to_ticks(uint32_t msecs) +{ + return __cdf_system_msecs_to_ticks(msecs); +} + +/** + * cdf_get_system_uptime() - Return a monotonically increasing time. + * This increments once per HZ ticks + * + * Return: system up time + */ +static inline unsigned long cdf_get_system_uptime(void) +{ + return __cdf_get_system_uptime(); +} + +/** + * cdf_get_system_timestamp() - brief Return current timestamp + * + * Return: none + */ +static inline unsigned long cdf_get_system_timestamp(void) +{ + return __cdf_get_system_timestamp(); +} + +/** + * cdf_udelay() - delay in microseconds + * @usecs: Number of microseconds to delay + * + * Return: none + */ +static inline void cdf_udelay(int usecs) +{ + __cdf_udelay(usecs); +} + +/** + * cdf_mdelay() - Delay in milliseconds. + * @msec: Number of milliseconds to delay + * + * Return: none + */ +static inline void cdf_mdelay(int msecs) +{ + __cdf_mdelay(msecs); +} + +/* Check if _a is later than _b */ +#define cdf_system_time_after(_a, _b) __cdf_system_time_after(_a, _b) + +/* Check if _a is prior to _b */ +#define cdf_system_time_before(_a, _b) __cdf_system_time_before(_a, _b) + +/* Check if _a atleast as recent as _b, if not later */ +#define cdf_system_time_after_eq(_a, _b) __cdf_system_time_after_eq(_a, _b) + +#ifdef QCA_WIFI_3_0_ADRASTEA +/** + * cdf_get_log_timestamp() - get time stamp for logging + * + * For adrastea this API returns QTIMER tick which is needed to synchronize + * host and fw log timestamps + * + * For ROME and other discrete solution this API returns system boot time stamp + * + * Return: + * QTIMER ticks(19.2MHz) for adrastea + * System tick for rome and other future discrete solutions + */ +static inline uint64_t cdf_get_log_timestamp(void) +{ + return __cdf_get_qtimer_ticks(); +} +#else +/** + * cdf_get_log_timestamp() - get time stamp for logging + * + * For adrastea this API returns QTIMER tick which is needed to synchronize + * host and fw log timestamps + * + * For ROME and other discrete solution this API returns system boot time stamp + * + * Return: + * QTIMER ticks(19.2MHz) for adrastea + * System tick for rome and other future discrete solutions + */ +static inline uint64_t cdf_get_log_timestamp(void) +{ +#ifdef CONFIG_CNSS + struct timespec ts; + + cnss_get_boottime(&ts); + + return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); +#else + return cdf_system_ticks_to_msecs(cdf_system_ticks()) * 1000; +#endif /* CONFIG_CNSS */ +} +#endif /* QCA_WIFI_3_0_ADRASTEA */ + +/** + * cdf_get_monotonic_boottime() - get monotonic kernel boot time + * This API is similar to cdf_get_system_boottime but it includes + * time spent in suspend. + * + * Return: Time in microseconds + */ +static inline uint64_t cdf_get_monotonic_boottime(void) +{ + return __cdf_get_monotonic_boottime(); +} + +#endif diff --git a/core/cdf/inc/cdf_trace.h b/core/cdf/inc/cdf_trace.h new file mode 100644 index 000000000000..bbf78b9cf6b6 --- /dev/null +++ b/core/cdf/inc/cdf_trace.h @@ -0,0 +1,283 @@ +/* + * 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(__CDF_TRACE_H) +#define __CDF_TRACE_H + +/** + * DOC: cdf_trace + * + * Connectivity driver framework trace APIs + * + * Trace, logging, and debugging definitions and APIs + * + */ + +/* Include Files */ +#include /* For CDF_MODULE_ID... */ +#include /* For va_list... */ +#include +#include +#include +#include + +/* Type declarations */ + +typedef enum { + /* NONE means NO traces will be logged. This value is in place + * for the cdf_trace_setlevel() to allow the user to turn off + * all traces + */ + CDF_TRACE_LEVEL_NONE = 0, + + /* Following trace levels are the ones that 'callers' of CDF_TRACE() + * can specify in for the CDF_TRACE_LEVEL parameter. Traces are + * classified by severity. FATAL being more serious than INFO for + * example + */ + CDF_TRACE_LEVEL_FATAL, + CDF_TRACE_LEVEL_ERROR, + CDF_TRACE_LEVEL_WARN, + CDF_TRACE_LEVEL_INFO, + CDF_TRACE_LEVEL_INFO_HIGH, + CDF_TRACE_LEVEL_INFO_MED, + CDF_TRACE_LEVEL_INFO_LOW, + CDF_TRACE_LEVEL_DEBUG, + + /* All means all trace levels will be active. This value is in place + * for the cdf_trace_setlevel() to allow the user to turn ON all traces + */ + CDF_TRACE_LEVEL_ALL, + + /* Not a real level. Used to identify the maximum number of + * CDF_TRACE_LEVELs defined + */ + CDF_TRACE_LEVEL_MAX +} CDF_TRACE_LEVEL; + +/* By default Data Path module will have all log levels enabled, except debug + * log level. Debug level will be left up to the framework or user space modules + * to be enabled when issue is detected + */ +#define CDF_DATA_PATH_TRACE_LEVEL \ + ((1 << CDF_TRACE_LEVEL_FATAL) | (1 << CDF_TRACE_LEVEL_ERROR) | \ + (1 << CDF_TRACE_LEVEL_WARN) | (1 << CDF_TRACE_LEVEL_INFO) | \ + (1 << CDF_TRACE_LEVEL_INFO_HIGH) | (1 << CDF_TRACE_LEVEL_INFO_MED) | \ + (1 << CDF_TRACE_LEVEL_INFO_LOW)) + +/* Preprocessor definitions and constants */ +#define ASSERT_BUFFER_SIZE (512) + +#define CDF_ENABLE_TRACING +#define MAX_CDF_TRACE_RECORDS 4000 +#define INVALID_CDF_TRACE_ADDR 0xffffffff +#define DEFAULT_CDF_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 cdf_trace_record_s { + uint64_t time; + uint8_t module; + uint8_t code; + uint16_t session; + uint32_t data; + uint32_t pid; +} cdf_trace_record_t, *tp_cdf_trace_record; + +typedef struct s_cdf_trace_data { + /* 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 + */ + uint32_t head; + uint32_t tail; + uint32_t num; + uint16_t numSinceLastDump; + + /* config for controlling the trace */ + uint8_t enable; + /* Dump after number of records reach this number */ + uint16_t dumpCount; +} t_cdf_trace_data; + +#define CASE_RETURN_STRING(str) case ((str)): return (uint8_t *)(# str); + +/* DP Trace Implementation */ +#define DPTRACE(p) p + +#define MAX_CDF_DP_TRACE_RECORDS 4000 +#define CDF_DP_TRACE_RECORD_SIZE 16 +#define INVALID_CDF_DP_TRACE_ADDR 0xffffffff +#define CDF_DP_TRACE_VERBOSITY_HIGH 3 +#define CDF_DP_TRACE_VERBOSITY_MEDIUM 2 +#define CDF_DP_TRACE_VERBOSITY_LOW 1 +#define CDF_DP_TRACE_VERBOSITY_DEFAULT 0 + +/** + * enum CDF_DP_TRACE_ID - Generic ID to identify various events in data path + * @CDF_DP_TRACE_INVALID: Invalid ID + * @CDF_DP_TRACE_DROP_PACKET_RECORD: Dropped packet stored with this id + * @CDF_DP_TRACE_HDD_PACKET_PTR_RECORD: nbuf->data ptr of HDD + * @CDF_DP_TRACE_HDD_PACKET_RECORD: nbuf->data stored with this id + * @CDF_DP_TRACE_CE_PACKET_PTR_RECORD: nbuf->data ptr of CE + * @CDF_DP_TRACE_CE_PACKET_RECORD: nbuf->data stored with this id + * @CDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD: nbuf->data ptr of txrx queue + * @CDF_DP_TRACE_TXRX_PACKET_PTR_RECORD: nbuf->data ptr of txrx + * @CDF_DP_TRACE_HTT_PACKET_PTR_RECORD: nbuf->data ptr of htt + * @CDF_DP_TRACE_HTC_PACKET_PTR_RECORD: nbuf->data ptr of htc + * @CDF_DP_TRACE_HIF_PACKET_PTR_RECORD: nbuf->data ptr of hif + * @CDF_DP_TRACE_HDD_TX_TIMEOUT: hdd tx timeout event + * @CDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: hdd tx softap timeout event + * @CDF_DP_TRACE_VDEV_PAUSE: vdev pause event + * @CDF_DP_TRACE_VDEV_UNPAUSE: vdev unpause event + * + */ +enum CDF_DP_TRACE_ID { + CDF_DP_TRACE_INVALID = 0, + CDF_DP_TRACE_DROP_PACKET_RECORD = 1, + CDF_DP_TRACE_HDD_PACKET_PTR_RECORD = 2, + CDF_DP_TRACE_HDD_PACKET_RECORD = 3, + CDF_DP_TRACE_CE_PACKET_PTR_RECORD = 4, + CDF_DP_TRACE_CE_PACKET_RECORD = 5, + CDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD = 6, + CDF_DP_TRACE_TXRX_PACKET_PTR_RECORD = 7, + CDF_DP_TRACE_HTT_PACKET_PTR_RECORD = 8, + CDF_DP_TRACE_HTC_PACKET_PTR_RECORD = 9, + CDF_DP_TRACE_HIF_PACKET_PTR_RECORD = 10, + CDF_DP_TRACE_HDD_TX_TIMEOUT = 11, + CDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT = 12, + CDF_DP_TRACE_VDEV_PAUSE = 13, + CDF_DP_TRACE_VDEV_UNPAUSE = 14, + CDF_DP_TRACE_MAX + +}; + +/** + * struct cdf_dp_trace_record_s - Describes a record in DP trace + * @time: time when it got stored + * @code: Describes the particular event + * @data: buffer to store data + * @size: Length of the valid data stored in this record + * @pid : process id which stored the data in this record + */ +struct cdf_dp_trace_record_s { + uint64_t time; + uint8_t code; + uint8_t data[CDF_DP_TRACE_RECORD_SIZE]; + uint8_t size; + uint32_t pid; +}; + +/** + * struct cdf_dp_trace_data - Parameters to configure/control DP trace + * @head: Position of first record + * @tail: Position of last record + * @num: Current index + * @proto_bitmap: defines which protocol to be traced + * @no_of_record: defines every nth packet to be traced + * @verbosity : defines verbosity level + * @enable: enable/disable DP trace + * @count: current packet number + */ +struct s_cdf_dp_trace_data { + uint32_t head; + uint32_t tail; + uint32_t num; + + /* config for controlling the trace */ + uint8_t proto_bitmap; + uint8_t no_of_record; + uint8_t verbosity; + bool enable; + uint32_t count; +}; +/* Function declarations and documenation */ + +/** + * cdf_trace_set_level() - Set the trace level for a particular module + * @level : trace level + * + * Trace level is a member of the CDF_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. + * + * This is an external API that allows trace levels to be set for each module. + * + * Return: nothing + */ +void cdf_trace_set_level(CDF_MODULE_ID module, CDF_TRACE_LEVEL level); + +/** + * cdf_trace_get_level() - get the trace level + * @level : trace level + * + * This is an external API that returns a bool value to signify if a + * particular trace level is set for the specified module. + * A member of the CDF_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. CDF_TRACE_LEVEL_NONE and CDF_TRACE_LEVEL_ALL + * are not valid input and will return false + * + * Return: + * false - the specified trace level for the specified module is OFF + * true - the specified trace level for the specified module is ON + */ +bool cdf_trace_get_level(CDF_MODULE_ID module, CDF_TRACE_LEVEL level); + +typedef void (*tp_cdf_trace_cb)(void *pMac, tp_cdf_trace_record, uint16_t); +void cdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data); +void cdf_trace_register(CDF_MODULE_ID, tp_cdf_trace_cb); +CDF_STATUS cdf_trace_spin_lock_init(void); +void cdf_trace_init(void); +void cdf_trace_enable(uint32_t, uint8_t enable); +void cdf_trace_dump_all(void *, uint8_t, uint8_t, uint32_t, uint32_t); + +void cdf_dp_trace_spin_lock_init(void); +void cdf_dp_trace_init(void); +void cdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_records, + uint8_t verbosity); +void cdf_dp_trace_set_track(cdf_nbuf_t nbuf); +void cdf_dp_trace(cdf_nbuf_t nbuf, enum CDF_DP_TRACE_ID code, + uint8_t *data, uint8_t size); +void cdf_dp_trace_dump_all(uint32_t count); +typedef void (*tp_cdf_dp_trace_cb)(struct cdf_dp_trace_record_s* , uint16_t); +void cdf_dp_display_record(struct cdf_dp_trace_record_s *record, + uint16_t index); +#endif diff --git a/core/cdf/inc/cdf_types.h b/core/cdf/inc/cdf_types.h new file mode 100644 index 000000000000..49099450ce5c --- /dev/null +++ b/core/cdf/inc/cdf_types.h @@ -0,0 +1,492 @@ +/* + * 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(__CDF_TYPES_H) +#define __CDF_TYPES_H +/** + * DOC: cdf_types.h + * + * Connectivity driver framework (CDF) basic type definitions + */ + +/* Include Files */ +#include "i_cdf_types.h" +#include + +/* Preprocessor definitions and constants */ + +/** + * CDF_MAX - get maximum of two values + * @_x: 1st arguement + * @_y: 2nd arguement + */ +#define CDF_MAX(_x, _y) (((_x) > (_y)) ? (_x) : (_y)) + +/** + * CDF_MIN - get minimum of two values + * @_x: 1st arguement + * @_y: 2nd arguement + */ +#define CDF_MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y)) + +/** + * CDF_SWAP_U16 - swap input u16 value + * @_x: variable to swap + */ +#define CDF_SWAP_U16(_x) \ + ((((_x) << 8) & 0xFF00) | (((_x) >> 8) & 0x00FF)) + +/** + * CDF_SWAP_U32 - swap input u32 value + * @_x: variable to swap + */ +#define CDF_SWAP_U32(_x) \ + (((((_x) << 24) & 0xFF000000) | (((_x) >> 24) & 0x000000FF)) | \ + ((((_x) << 8) & 0x00FF0000) | (((_x) >> 8) & 0x0000FF00))) + +#define CDF_TICKS_PER_SECOND (1000) + +/** + * CDF_ARRAY_SIZE - get array size + * @_arr: array variable name + */ +#define CDF_ARRAY_SIZE(_arr) (sizeof(_arr) / sizeof((_arr)[0])) + +/* endian operations for Big Endian and Small Endian modes */ +#ifdef ANI_LITTLE_BYTE_ENDIAN + +#define cdf_be16_to_cpu(_x) CDF_SWAP_U16(_x) + +#endif + +#ifdef ANI_BIG_BYTE_ENDIAN + +#define cdf_be16_to_cpu(_x) (_x) + +#endif + +#ifndef __ahdecl +#ifdef __i386__ +#define __ahdecl __attribute__((regparm(0))) +#else +#define __ahdecl +#endif +#endif + +#define CDF_OS_MAX_SCATTER __CDF_OS_MAX_SCATTER + +/** + * @brief denotes structure is packed. + */ +#define cdf_packed __cdf_packed + +/** + * typedef cdf_handle_t - handles opaque to each other + */ +typedef void *cdf_handle_t; + +/** + * typedef cdf_device_t - Platform/bus generic handle. + * Used for bus specific functions. + */ +typedef __cdf_device_t cdf_device_t; + +/** + * typedef cdf_size_t - size of an object + */ +typedef __cdf_size_t cdf_size_t; + +/** + * typedef cdf_dma_map_t - DMA mapping object. + */ +typedef __cdf_dma_map_t cdf_dma_map_t; + +/** + * tyepdef cdf_dma_addr_t - DMA address. + */ +typedef __cdf_dma_addr_t cdf_dma_addr_t; + +/** + * tyepdef cdf_dma_context_t - DMA context. + */ +typedef __cdf_dma_context_t cdf_dma_context_t; + + +#define cdf_iomem_t __cdf_iomem_t; +/** + * typedef enum CDF_TIMER_TYPE - CDF timer type + * @CDF_TIMER_TYPE_SW: Deferrable SW timer it will not cause CPU to wake up + * on expiry + * @CDF_TIMER_TYPE_WAKE_APPS: Non deferrable timer which will cause CPU to + * wake up on expiry + */ +typedef enum { + CDF_TIMER_TYPE_SW, + CDF_TIMER_TYPE_WAKE_APPS +} CDF_TIMER_TYPE; + +/** + * tyepdef cdf_resource_type_t - hw resources + * + * @CDF_RESOURCE_TYPE_MEM: memory resource + * @CDF_RESOURCE_TYPE_IO: io resource + * + * Define the hw resources the OS has allocated for the device + * Note that start defines a mapped area. + */ +typedef enum { + CDF_RESOURCE_TYPE_MEM, + CDF_RESOURCE_TYPE_IO, +} cdf_resource_type_t; + +/** + * tyepdef cdf_resource_t - representation of a h/w resource. + * + * @start: start + * @end: end + * @type: resource type + */ +typedef struct { + uint64_t start; + uint64_t end; + cdf_resource_type_t type; +} cdf_resource_t; + +/** + * typedef cdf_dma_dir_t - DMA directions + * + * @CDF_DMA_BIDIRECTIONAL: bidirectional data + * @CDF_DMA_TO_DEVICE: data going from device to memory + * @CDF_DMA_FROM_DEVICE: data going from memory to device + */ +typedef enum { + CDF_DMA_BIDIRECTIONAL = __CDF_DMA_BIDIRECTIONAL, + CDF_DMA_TO_DEVICE = __CDF_DMA_TO_DEVICE, + CDF_DMA_FROM_DEVICE = __CDF_DMA_FROM_DEVICE, +} cdf_dma_dir_t; + +/* work queue(kernel thread)/DPC function callback */ +typedef void (*cdf_defer_fn_t)(void *); + +/* Prototype of the critical region function that is to be + * executed with spinlock held and interrupt disalbed + */ +typedef bool (*cdf_irqlocked_func_t)(void *); + +/* Prototype of timer function */ +typedef void (*cdf_softirq_timer_func_t)(void *); + +#define cdf_print __cdf_print +#define cdf_vprint __cdf_vprint +#define cdf_snprint __cdf_snprint + +#define cdf_offsetof(type, field) offsetof(type, field) + +/** + * typedef CDF_MODULE_ID - CDF Module IDs + * + * @CDF_MODULE_ID_TLSHIM: TLSHIM module ID + * @CDF_MODULE_ID_WMI: WMI module ID + * @CDF_MODULE_ID_HTT: HTT module ID + * @CDF_MODULE_ID_RSV4: Reserved + * @CDF_MODULE_ID_HDD: HDD module ID + * @CDF_MODULE_ID_SME: SME module ID + * @CDF_MODULE_ID_PE: PE module ID + * @CDF_MODULE_ID_WMA: WMA module ID + * @CDF_MODULE_ID_SYS: SYS module ID + * @CDF_MODULE_ID_CDF: CDF module ID + * @CDF_MODULE_ID_SAP: SAP module ID + * @CDF_MODULE_ID_HDD_SOFTAP: HDD SAP module ID + * @CDF_MODULE_ID_HDD_DATA: HDD DATA module ID + * @CDF_MODULE_ID_HDD_SAP_DATA: HDD SAP DATA module ID + * @CDF_MODULE_ID_HIF: HIF module ID + * @CDF_MODULE_ID_HTC: HTC module ID + * @CDF_MODULE_ID_TXRX: TXRX module ID + * @CDF_MODULE_ID_CDF_DEVICE: CDF DEVICE module ID + * @CDF_MODULE_ID_CFG: CFG module ID + * @CDF_MODULE_ID_BMI: BMI module ID + * @CDF_MODULE_ID_EPPING: EPPING module ID + * @CDF_MODULE_ID_MAX: Max place holder module ID + * + * These are generic IDs that identify the various modules in the software + * system + * 0 is unused for historical purposes + * 3 & 4 are unused for historical purposes + */ +typedef enum { + CDF_MODULE_ID_TLSHIM = 1, + CDF_MODULE_ID_WMI = 2, + CDF_MODULE_ID_HTT = 3, + CDF_MODULE_ID_RSV4 = 4, + CDF_MODULE_ID_HDD = 5, + CDF_MODULE_ID_SME = 6, + CDF_MODULE_ID_PE = 7, + CDF_MODULE_ID_WMA = 8, + CDF_MODULE_ID_SYS = 9, + CDF_MODULE_ID_CDF = 10, + CDF_MODULE_ID_SAP = 11, + CDF_MODULE_ID_HDD_SOFTAP = 12, + CDF_MODULE_ID_HDD_DATA = 14, + CDF_MODULE_ID_HDD_SAP_DATA = 15, + + CDF_MODULE_ID_HIF = 16, + CDF_MODULE_ID_HTC = 17, + CDF_MODULE_ID_TXRX = 18, + CDF_MODULE_ID_CDF_DEVICE = 19, + CDF_MODULE_ID_CFG = 20, + CDF_MODULE_ID_BMI = 21, + CDF_MODULE_ID_EPPING = 22, + + CDF_MODULE_ID_MAX +} CDF_MODULE_ID; + +/** + * typedef enum tCDF_CON_MODE - Concurrency role. + * + * @CDF_STA_MODE: STA mode + * @CDF_SAP_MODE: SAP mode + * @CDF_P2P_CLIENT_MODE: P2P client mode + * @CDF_P2P_GO_MODE: P2P GO mode + * @CDF_FTM_MODE: FTM mode + * @CDF_IBSS_MODE: IBSS mode + * @CDF_P2P_DEVICE_MODE: P2P device mode + * @CDF_EPPING_MODE: EPPING device mode + * @CDF_OCB_MODE: OCB device mode + * @CDF_MAX_NO_OF_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +typedef enum { + CDF_STA_MODE = 0, + CDF_SAP_MODE = 1, + CDF_P2P_CLIENT_MODE, + CDF_P2P_GO_MODE, + CDF_FTM_MODE = 5, + CDF_IBSS_MODE, + CDF_P2P_DEVICE_MODE, + CDF_EPPING_MODE, + CDF_OCB_MODE, + CDF_MAX_NO_OF_MODE +} tCDF_CON_MODE; + +#ifdef WLAN_OPEN_P2P_INTERFACE +/* This should match with WLAN_MAX_INTERFACES */ +#define CDF_MAX_CONCURRENCY_PERSONA (4) +#else +#define CDF_MAX_CONCURRENCY_PERSONA (3) +#endif + +#define CDF_STA_MASK (1 << CDF_STA_MODE) +#define CDF_SAP_MASK (1 << CDF_SAP_MODE) +#define CDF_P2P_CLIENT_MASK (1 << CDF_P2P_CLIENT_MODE) +#define CDF_P2P_GO_MASK (1 << CDF_P2P_GO_MODE) + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef enum { + CDF_MCC_TO_SCC_SWITCH_DISABLE = 0, + CDF_MCC_TO_SCC_SWITCH_ENABLE, + CDF_MCC_TO_SCC_SWITCH_FORCE, + CDF_MCC_TO_SCC_SWITCH_MAX +} tCDF_MCC_TO_SCC_SWITCH_MODE; +#endif + +#if !defined(NULL) +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* 'Time' type */ +typedef unsigned long v_TIME_t; + +/* typedef for CDF Context... */ +typedef void *v_CONTEXT_t; + +#define CDF_MAC_ADDR_SIZE (6) + +/** + * struct cdf_mac_addr - mac address array + * @bytes: MAC address bytes + */ +struct cdf_mac_addr { + uint8_t bytes[CDF_MAC_ADDR_SIZE]; +}; + +/* This macro is used to initialize a CDF MacAddress to the broadcast + * MacAddress. It is used like this... + * struct cdf_mac_addr macAddress = CDF_MAC_ADDR_BROADCAST_INITIALIZER + */ +#define CDF_MAC_ADDR_BROADCAST_INITIALIZER { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } + +/* This macro is used to initialize a CDF MacAddress to zero + * It is used like this... + * struct cdf_mac_addr macAddress = CDF_MAC_ADDR_ZERO_INITIALIZER + */ +#define CDF_MAC_ADDR_ZERO_INITIALIZER { { 0, 0, 0, 0, 0, 0 } } + +#define CDF_IPV4_ADDR_SIZE (4) + +/** + * struct cdf_tso_frag_t - fragments of a single TCP segment + * @paddr_low_32: Lower 32 bits of the buffer pointer + * @paddr_upper_16: upper 16 bits of the buffer pointer + * @length: length of the buffer + * @vaddr: virtual address + * + * This structure holds the fragments of a single TCP segment of a + * given jumbo TSO network buffer + */ +struct cdf_tso_frag_t { + uint32_t paddr_low_32; + uint32_t paddr_upper_16:16, + length:16; + unsigned char *vaddr; +}; + +#define FRAG_NUM_MAX 6 + +/** + * struct cdf_tso_flags_t - TSO specific flags + * @tso_enable: Enable transmit segmentation offload + * @tcp_flags_mask: Tcp_flag is inserted into the header based + * on the mask + * @l2_len: L2 length for the msdu + * @ip_len: IP length for the msdu + * @tcp_seq_num: TCP sequence number + * @ip_id: IP identification number + * + * This structure holds the TSO specific flags extracted from the TSO network + * buffer for a given TCP segment + */ +struct cdf_tso_flags_t { + u_int32_t tso_enable:1, + reserved_0a:6, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1, + ns:1, + tcp_flags_mask:9, + reserved_0b:7; +/* ------------------------------------------------------------------- */ + + u_int32_t l2_len:16, + ip_len:16; +/* ------------------------------------------------------------------- */ + + u_int32_t tcp_seq_num; +/* ------------------------------------------------------------------- */ + + u_int32_t ip_id:16, + ipv4_checksum_en:1, + udp_ipv4_checksum_en:1, + udp_ipv6_checksum_en:1, + tcp_ipv4_checksum_en:1, + tcp_ipv6_checksum_en:1, + partial_checksum_en:1, + reserved_3a:10; +/* ------------------------------------------------------------------- */ + + u_int32_t checksum_offset:14, + reserved_4a:2, + payload_start_offset:14, + reserved_4b:2; +/* ------------------------------------------------------------------- */ + + u_int32_t payload_end_offset:14, + reserved_5:18; +}; + +/** + * struct cdf_tso_seg_t - single TSO segment + * @tso_flags: TSO flags + * @num_frags: number of fragments + * @tso_frags: array holding the fragments + * + * This structure holds the information of a single TSO segment of a jumbo + * TSO network buffer + */ +struct cdf_tso_seg_t { + struct cdf_tso_flags_t tso_flags; +/* ------------------------------------------------------------------- */ + uint32_t num_frags; + struct cdf_tso_frag_t tso_frags[FRAG_NUM_MAX]; +}; + +struct cdf_tso_seg_elem_t { + struct cdf_tso_seg_t seg; + struct cdf_tso_seg_elem_t *next; +}; + +/** + * struct cdf_tso_info_t - TSO information extracted + * @is_tso: is this is a TSO frame + * @num_segs: number of segments + * @total_len: total length of the packet + * @tso_seg_list: list of TSO segments for this jumbo packet + * @curr_seg: segment that is currently being processed + * + * This structure holds the TSO information extracted after parsing the TSO + * jumbo network buffer. It contains a chain of the TSO segments belonging to + * the jumbo packet + */ +struct cdf_tso_info_t { + uint8_t is_tso; + uint32_t num_segs; + uint32_t total_len; + struct cdf_tso_seg_elem_t *tso_seg_list; + struct cdf_tso_seg_elem_t *curr_seg; +}; + +/** + * Used to set classify bit in CE desc. + */ +#define CDF_CE_TX_CLASSIFY_BIT_S 5 + +/** + * 2 bits starting at bit 6 in CE desc. + */ +#define CDF_CE_TX_PKT_TYPE_BIT_S 6 + +/** + * 12 bits --> 16-27, in the CE desciptor, the length of HTT/HTC descriptor + */ +#define CDF_CE_TX_PKT_OFFSET_BIT_S 16 + +/** + * Mask for packet offset in the CE descriptor. + */ +#define CDF_CE_TX_PKT_OFFSET_BIT_M 0x0fff0000 + +#endif /* if !defined __CDF_TYPES_H */ diff --git a/core/cdf/inc/cdf_util.h b/core/cdf/inc/cdf_util.h new file mode 100644 index 000000000000..c00ac564833f --- /dev/null +++ b/core/cdf/inc/cdf_util.h @@ -0,0 +1,325 @@ +/* + * 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. + */ + +/** + * DOC: cdf_util.h + * + * This file defines utility functions. + */ + +#ifndef _CDF_UTIL_H +#define _CDF_UTIL_H + +#include + +/** + * cdf_unlikely - Compiler-dependent macro denoting code likely to execute + * @_expr: expression to be checked + */ +#define cdf_unlikely(_expr) __cdf_unlikely(_expr) + +/** + * cdf_likely - Compiler-dependent macro denoting code unlikely to execute + * @_expr: expression to be checked + */ +#define cdf_likely(_expr) __cdf_likely(_expr) + +CDF_INLINE_FN int cdf_status_to_os_return(CDF_STATUS status) +{ + return __cdf_status_to_os_return(status); +} + +/** + * cdf_assert - assert "expr" evaluates to false + * @expr: assert expression + */ +#ifdef CDF_OS_DEBUG +#define cdf_assert(expr) __cdf_assert(expr) +#else +#define cdf_assert(expr) +#endif /* CDF_OS_DEBUG */ + +/** + * @cdf_assert_always- alway assert "expr" evaluates to false + * @expr: assert expression + */ +#define cdf_assert_always(expr) __cdf_assert(expr) + +/** + * cdf_os_cpu_to_le64 - Convert a 64-bit value from CPU byte order to + * little-endian byte order + * @x: value to be converted + */ +#define cdf_os_cpu_to_le64(x) __cdf_os_cpu_to_le64(x) + +/** + * cdf_le16_to_cpu - Convert a 16-bit value from little-endian byte order + * to CPU byte order + * @x: value to be converted + */ +#define cdf_le16_to_cpu(x) __cdf_le16_to_cpu(x) + +/** + * cdf_le32_to_cpu - Convert a 32-bit value from little-endian byte order to + * CPU byte order + * @x: value to be converted + */ +#define cdf_le32_to_cpu(x) __cdf_le32_to_cpu(x) + +/** + * cdf_in_interrupt - returns true if in interrupt context + */ +#define cdf_in_interrupt in_interrupt + +/** + * cdf_container_of - cast a member of a structure out to the containing + * structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define cdf_container_of(ptr, type, member) \ + __cdf_container_of(ptr, type, member) + +/** + * cdf_is_macaddr_equal() - compare two CDF MacAddress + * @pMacAddr1: Pointer to one cdf MacAddress to compare + * @pMacAddr2: Pointer to the other cdf MacAddress to compare + * + * This function returns a bool that tells if a two CDF MacAddress' + * are equivalent. + * + * Return: true if the MacAddress's are equal + * not true if the MacAddress's are not equal + */ +CDF_INLINE_FN bool cdf_is_macaddr_equal(struct cdf_mac_addr *pMacAddr1, + struct cdf_mac_addr *pMacAddr2) +{ + return 0 == memcmp(pMacAddr1, pMacAddr2, CDF_MAC_ADDR_SIZE); +} + +/** + * cdf_is_macaddr_zero() - check for a MacAddress of all zeros. + * @pMacAddr - pointer to the struct cdf_mac_addr to check. + * + * This function returns a bool that tells if a MacAddress is made up of + * all zeros. + * + * + * Return: true if the MacAddress is all Zeros + * flase if the MacAddress is not all Zeros. + * + */ +CDF_INLINE_FN bool cdf_is_macaddr_zero(struct cdf_mac_addr *pMacAddr) +{ + struct cdf_mac_addr zeroMacAddr = CDF_MAC_ADDR_ZERO_INITIALIZER; + + return cdf_is_macaddr_equal(pMacAddr, &zeroMacAddr); +} + +/** + * cdf_zero_macaddr() - zero out a MacAddress + * @pMacAddr: pointer to the struct cdf_mac_addr to zero. + * + * This function zeros out a CDF MacAddress type. + * + * Return: nothing + */ +CDF_INLINE_FN void cdf_zero_macaddr(struct cdf_mac_addr *pMacAddr) +{ + memset(pMacAddr, 0, CDF_MAC_ADDR_SIZE); +} + +/** + * cdf_is_macaddr_group() - check for a MacAddress is a 'group' address + * @pMacAddr1: pointer to the cdf MacAddress to check + * + * This function returns a bool that tells if a the input CDF 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. + * + * Return: true if the input MacAddress is a Group address + * false if the input MacAddress is not a Group address + */ +CDF_INLINE_FN bool cdf_is_macaddr_group(struct cdf_mac_addr *pMacAddr) +{ + return pMacAddr->bytes[0] & 0x01; +} + +/** + * cdf_is_macaddr_broadcast() - check for a MacAddress is a broadcast address + * + * This function returns a bool that tells if a the input CDF MacAddress + * is a "broadcast" address. + * + * @pMacAddr: Pointer to the cdf MacAddress to check + * + * Return: true if the input MacAddress is a broadcast address + * flase if the input MacAddress is not a broadcast address + */ +CDF_INLINE_FN bool cdf_is_macaddr_broadcast(struct cdf_mac_addr *pMacAddr) +{ + struct cdf_mac_addr broadcastMacAddr = + CDF_MAC_ADDR_BROADCAST_INITIALIZER; + + return cdf_is_macaddr_equal(pMacAddr, &broadcastMacAddr); +} + +/** + * cdf_copy_macaddr() - copy a CDF MacAddress + * @pDst - pointer to the cdf MacAddress to copy TO (the destination) + * @pSrc - pointer to the cdf MacAddress to copy FROM (the source) + * + * This function copies a CDF MacAddress into another CDF MacAddress. + * + * + * Return: nothing + */ +CDF_INLINE_FN void cdf_copy_macaddr(struct cdf_mac_addr *pDst, + struct cdf_mac_addr *pSrc) +{ + *pDst = *pSrc; +} + +/** + * cdf_set_macaddr_broadcast() - set a CDF MacAddress to the 'broadcast' + * @pMacAddr: pointer to the cdf MacAddress to set to broadcast + * + * This function sets a CDF MacAddress to the 'broadcast' MacAddress. Broadcast + * MacAddress contains all 0xFF bytes. + * + * Return: nothing + */ +CDF_INLINE_FN void cdf_set_macaddr_broadcast(struct cdf_mac_addr *pMacAddr) +{ + memset(pMacAddr, 0xff, CDF_MAC_ADDR_SIZE); +} + +#if defined(ANI_LITTLE_BYTE_ENDIAN) + +/** + * i_cdf_htonl() - convert from host byte order to network byte order + * @ul: input to be converted + * + * Return: converted network byte order + */ +CDF_INLINE_FN unsigned long i_cdf_htonl(unsigned long ul) +{ + return ((ul & 0x000000ff) << 24) | + ((ul & 0x0000ff00) << 8) | + ((ul & 0x00ff0000) >> 8) | ((ul & 0xff000000) >> 24); +} + +/** + * i_cdf_ntohl() - convert network byte order to host byte order + * @ul: input to be converted + * + * Return: converted host byte order + */ +CDF_INLINE_FN unsigned long i_cdf_ntohl(unsigned long ul) +{ + return i_cdf_htonl(ul); +} + +#endif + +/** + * cdf_set_u16() - Assign 16-bit unsigned value to a byte array base on CPU's + * endianness. + * @ptr: Starting address of a byte array + * @value: The value to assign to the byte array + * + * Caller must validate the byte array has enough space to hold the vlaue + * + * Return: The address to the byte after the assignment. This may or may not + * be valid. Caller to verify. + */ +CDF_INLINE_FN uint8_t *cdf_set_u16(uint8_t *ptr, uint16_t value) +{ +#if defined(ANI_BIG_BYTE_ENDIAN) + *(ptr) = (uint8_t) (value >> 8); + *(ptr + 1) = (uint8_t) (value); +#else + *(ptr + 1) = (uint8_t) (value >> 8); + *(ptr) = (uint8_t) (value); +#endif + + return ptr + 2; +} + +/** + * cdf_get_u16() - Retrieve a 16-bit unsigned value from a byte array base on + * CPU's endianness. + * @ptr: Starting address of a byte array + * @pValue: Pointer to a caller allocated buffer for 16 bit value. Value is to + * assign to this location. + * + * Caller must validate the byte array has enough space to hold the vlaue + * + * Return: The address to the byte after the assignment. This may or may not + * be valid. Caller to verify. + */ +CDF_INLINE_FN uint8_t *cdf_get_u16(uint8_t *ptr, uint16_t *pValue) +{ +#if defined(ANI_BIG_BYTE_ENDIAN) + *pValue = (((uint16_t) (*ptr << 8)) | ((uint16_t) (*(ptr + 1)))); +#else + *pValue = (((uint16_t) (*(ptr + 1) << 8)) | ((uint16_t) (*ptr))); +#endif + + return ptr + 2; +} + +/** + * cdf_get_u32() - retrieve a 32-bit unsigned value from a byte array base on + * CPU's endianness. + * @ptr: Starting address of a byte array + * @pValue: Pointer to a caller allocated buffer for 32 bit value. Value is to + * assign to this location. + * + * Caller must validate the byte array has enough space to hold the vlaue + * + * Return: The address to the byte after the assignment. This may or may not + * be valid. Caller to verify. + */ +CDF_INLINE_FN uint8_t *cdf_get_u32(uint8_t *ptr, uint32_t *pValue) +{ +#if defined(ANI_BIG_BYTE_ENDIAN) + *pValue = ((uint32_t) (*(ptr) << 24) | + (uint32_t) (*(ptr + 1) << 16) | + (uint32_t) (*(ptr + 2) << 8) | (uint32_t) (*(ptr + 3))); +#else + *pValue = ((uint32_t) (*(ptr + 3) << 24) | + (uint32_t) (*(ptr + 2) << 16) | + (uint32_t) (*(ptr + 1) << 8) | (uint32_t) (*(ptr))); +#endif + return ptr + 4; +} + +#endif /*_CDF_UTIL_H*/ diff --git a/core/cdf/inc/osdep.h b/core/cdf/inc/osdep.h new file mode 100644 index 000000000000..a14a65390512 --- /dev/null +++ b/core/cdf/inc/osdep.h @@ -0,0 +1,300 @@ +/* + * 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 _OSDEP_H +#define _OSDEP_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * enum ath_hal_bus_type - Supported Bus types + * @HAL_BUS_TYPE_PCI: PCI Bus + * @HAL_BUS_TYPE_AHB: AHB Bus + * @HAL_BUS_TYPE_SNOC: SNOC Bus + * @HAL_BUS_TYPE_SIM: Simulator + */ +enum ath_hal_bus_type { + HAL_BUS_TYPE_PCI, + HAL_BUS_TYPE_AHB, + HAL_BUS_TYPE_SNOC, + HAL_BUS_TYPE_SIM +}; + +/** + * sturct hal_bus_context - Bus to hal context handoff + * @bc_tag: bus context tag + * @bc_handle: bus context handle + * @bc_bustype: bus type + */ +typedef struct hal_bus_context { + int bc_tag; + char *bc_handle; + enum ath_hal_bus_type bc_bustype; +} HAL_BUS_CONTEXT; + +#define INLINE inline + +/* 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 +#ifndef ASSERT +#define ASSERT(expr) cdf_assert(expr) +#endif +#else +#define ASSERT(expr) +#endif /* ATH_DEBUG */ + +/* + * 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 + +/* + * Deduce if tasklets are available. If not then + * fall back to using the immediate work queue. + */ +#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 + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 /* IEEE 802.11. */ +#endif + +/* + * Normal Delay functions. Time specified in microseconds. + */ +#define OS_DELAY(_us) cdf_udelay(_us) + +/* + * memory data manipulation functions. + */ +#define OS_MEMCPY(_dst, _src, _len) cdf_mem_copy(_dst, _src, _len) +#define OS_MEMMOVE(_dst, _src, _len) cdf_mem_move(_dst, _src, _len) +#define OS_MEMZERO(_buf, _len) cdf_mem_zero(_buf, _len) +#define OS_MEMSET(_buf, _ch, _len) cdf_mem_set(_buf, _len, _ch) +#define OS_MEMCMP(_mem1, _mem2, _len) cdf_mem_compare(_mem1, _mem2, _len) + +#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 */ + +#else +#define OS_SUPPORT_ASYNC_Q 0 +#endif /* ifdef CONFIG_SMP */ + + +/* + * System time interface + */ +typedef cdf_time_t systime_t; +typedef cdf_time_t systick_t; + +static INLINE cdf_time_t os_get_timestamp(void) +{ + return cdf_system_ticks(); /* Fix double conversion from jiffies to ms */ +} + +struct _NIC_DEV; + +typedef struct _NIC_DEV *osdev_t; + +typedef struct timer_list os_timer_t; + +typedef struct _os_mesg_t { + STAILQ_ENTRY(_os_mesg_t) mesg_next; + uint16_t mesg_type; + uint16_t mesg_len; + /* followed by mesg_len bytes */ +} os_mesg_t; + +typedef void (*os_mesg_handler_t)(void *ctx, + uint16_t mesg_type, + uint16_t mesg_len, void *mesg); + +typedef struct { + osdev_t dev_handle; + int32_t num_queued; + int32_t mesg_len; + uint8_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; + uint8_t is_synchronous : 1; +} os_mesg_queue_t; + +/* + * 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) */ + cdf_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 + uint8_t isDeviceAsleep; +#endif /* ATH_BUS_PM */ +}; + +static INLINE unsigned char *os_malloc(osdev_t pNicDev, + unsigned long ulSizeInBytes, int gfp) +{ + return cdf_mem_malloc(ulSizeInBytes); +} + +#define OS_FREE(_p) cdf_mem_free(_p) + +#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 + +/* + * 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) \ + cdf_softirq_timer_init(_osdev, _timer, _fn, _ctx, type) + +#define OS_SET_TIMER(_timer, _ms) cdf_softirq_timer_mod(_timer, _ms) + +#define OS_CANCEL_TIMER(_timer) cdf_softirq_timer_cancel(_timer) + +#define OS_FREE_TIMER(_timer) cdf_softirq_timer_cancel(_timer) + +/* + * These are required for network manager support + */ +#ifndef SET_NETDEV_DEV +#define SET_NETDEV_DEV(ndev, pdev) +#endif + +#endif /* end of _OSDEP_H */ diff --git a/core/cdf/src/cdf_defer.c b/core/cdf/src/cdf_defer.c new file mode 100644 index 000000000000..061f3c5b99f0 --- /dev/null +++ b/core/cdf/src/cdf_defer.c @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "i_cdf_defer.h" + +/** + * __cdf_defer_func() - defer work handler + * @work: Pointer to defer work + * + * Return: none + */ +void __cdf_defer_func(struct work_struct *work) +{ + __cdf_work_t *ctx = container_of(work, __cdf_work_t, work); + if (ctx->fn == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "No callback registered !!"); + return; + } + ctx->fn(ctx->arg); +} diff --git a/core/cdf/src/cdf_event.c b/core/cdf/src/cdf_event.c new file mode 100644 index 000000000000..ce39b4854636 --- /dev/null +++ b/core/cdf/src/cdf_event.c @@ -0,0 +1,270 @@ +/* + * 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. + */ + +/** + * DOC: cdf_event.c + * + * This source file contains linux specific definitions for CDF event APIs + * The 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. + */ + +/* Include Files */ +#include "cdf_event.h" +#include "cdf_trace.h" + +/* Preprocessor Definitions and Constants */ + +/* Type Declarations */ + +/* Global Data Definitions */ + +/* Static Variable Definitions */ + +/* Function Definitions and Documentation */ + +/** + * cdf_event_init() - initializes a CDF event + * @event: Pointer to the opaque event object to initialize + * + * The cdf_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. + * + * Return: CDF status + */ +CDF_STATUS cdf_event_init(cdf_event_t *event) +{ + /* check for null pointer */ + if (NULL == event) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check for 'already initialized' event */ + if (LINUX_EVENT_COOKIE == event->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Initialized event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_BUSY; + } + + /* initialize new event */ + init_completion(&event->complete); + event->cookie = LINUX_EVENT_COOKIE; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_event_set() - sets a CDF event + * @event: The event to set to the signalled state + * + * The state of the specified event is set to signalled by calling + * cdf_event_set(). + * + * Any threads waiting on the event as a result of a cdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to cdf_event_set(). + * + * + * Return: CDF status + */ + +CDF_STATUS cdf_event_set(cdf_event_t *event) +{ + /* check for null pointer */ + if (NULL == event) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check if event refers to an initialized object */ + if (LINUX_EVENT_COOKIE != event->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + complete(&event->complete); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_event_reset() - resets a CDF event + * @event: The event to set to the NOT signalled state + * + * 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 + * cdf_event_reset(). The state of the event remains NOT signalled until an + * explicit call to cdf_event_set(). + * + * This function sets the event to a NOT signalled state even if the event was + * signalled multiple times before being signaled. + * + * + * Return: CDF status + */ +CDF_STATUS cdf_event_reset(cdf_event_t *event) +{ + /* check for null pointer */ + if (NULL == event) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check to make sure it is an 'already initialized' event */ + if (LINUX_EVENT_COOKIE != event->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + /* (re)initialize event */ + INIT_COMPLETION(event->complete); + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_event_destroy() - Destroys a CDF event + * @event: The event object to be destroyed. + * + * 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 cdf_event_destroy() + * the event object becomes, in effect, uninitialized. + * + * A destroyed event object can be reinitialized using cdf_event_init(); + * the results of otherwise referencing the object after it has been destroyed + * are undefined. Calls to CDF event functions to manipulate the lock such + * as cdf_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. + * + * Return: CDF status + */ + +CDF_STATUS cdf_event_destroy(cdf_event_t *event) +{ + /* check for null pointer */ + if (NULL == event) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check to make sure it is an 'already initialized' event */ + if (LINUX_EVENT_COOKIE != event->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + /* make sure nobody is waiting on the event */ + complete_all(&event->complete); + + /* destroy the event */ + memset(event, 0, sizeof(cdf_event_t)); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_wait_single_event() - Waits for a single event to be set. + * + * This API waits for the event to be set. + * + * @pEvent: Pointer to an event to wait on. + * @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: CDF status + */ +CDF_STATUS cdf_wait_single_event(cdf_event_t *event, uint32_t timeout) +{ + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s cannot be called from interrupt context!!!", + __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check for null pointer */ + if (NULL == event) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "NULL event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check if cookie is same as that of initialized event */ + if (LINUX_EVENT_COOKIE != event->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Uninitialized event passed into %s", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + if (timeout) { + long ret; + ret = wait_for_completion_timeout(&event->complete, + msecs_to_jiffies(timeout)); + if (0 >= ret) + return CDF_STATUS_E_TIMEOUT; + } else { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Zero timeout value passed into %s", __func__); + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_SUCCESS; +} diff --git a/core/cdf/src/cdf_list.c b/core/cdf/src/cdf_list.c new file mode 100644 index 000000000000..1d60f9e21027 --- /dev/null +++ b/core/cdf/src/cdf_list.c @@ -0,0 +1,225 @@ +/* + * 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. + */ + +/** + * DOC: cdf_list.c + * + * Connectivity driver framework list manipulation APIs. CDF linked list + * APIs are NOT thread safe so make sure to use appropriate locking mechanisms + * to assure operations on the list are thread safe. + */ + +/* Include files */ +#include +#include + +/* Preprocessor definitions and constants */ + +/* Type declarations */ + +/* Function declarations and documenation */ + +/** + * cdf_list_insert_front() - insert input node at front of the list + * @pList: Pointer to list + * @pNode: Pointer to input node + * + * Return: CDF status + */ +CDF_STATUS cdf_list_insert_front(cdf_list_t *pList, cdf_list_node_t *pNode) +{ + list_add(pNode, &pList->anchor); + pList->count++; + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_insert_back() - insert input node at back of the list + * @pList: Pointer to list + * @pNode: Pointer to input node + * + * Return: CDF status + */ +CDF_STATUS cdf_list_insert_back(cdf_list_t *pList, cdf_list_node_t *pNode) +{ + list_add_tail(pNode, &pList->anchor); + pList->count++; + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_insert_back_size() - insert input node at back of list and save + * list size + * @pList: Pointer to list + * @pNode: Pointer to input node + * @pSize: Pointer to store list size + * + * Return: CDF status + */ +CDF_STATUS cdf_list_insert_back_size(cdf_list_t *pList, + cdf_list_node_t *pNode, uint32_t *pSize) +{ + list_add_tail(pNode, &pList->anchor); + pList->count++; + *pSize = pList->count; + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_remove_front() - remove node from front of the list + * @pList: Pointer to list + * @ppNode: Double pointer to store the node which is removed from list + * + * Return: CDF status + */ +CDF_STATUS cdf_list_remove_front(cdf_list_t *pList, cdf_list_node_t **ppNode) +{ + struct list_head *listptr; + + if (list_empty(&pList->anchor)) + return CDF_STATUS_E_EMPTY; + + listptr = pList->anchor.next; + *ppNode = listptr; + list_del(pList->anchor.next); + pList->count--; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_remove_back() - remove node from end of the list + * @pList: Pointer to list + * @ppNode: Double pointer to store node which is removed from list + * + * Return: CDF status + */ +CDF_STATUS cdf_list_remove_back(cdf_list_t *pList, cdf_list_node_t **ppNode) +{ + struct list_head *listptr; + + if (list_empty(&pList->anchor)) + return CDF_STATUS_E_EMPTY; + + listptr = pList->anchor.prev; + *ppNode = listptr; + list_del(pList->anchor.prev); + pList->count--; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_remove_node() - remove input node from list + * @pList: Pointer to list + * @pNodeToRemove: Pointer to node which needs to be removed + * + * Return: CDF status + */ +CDF_STATUS cdf_list_remove_node(cdf_list_t *pList, + cdf_list_node_t *pNodeToRemove) +{ + cdf_list_node_t *tmp; + int found = 0; + + if (list_empty(&pList->anchor)) + return CDF_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 CDF_STATUS_E_INVAL; + + list_del(pNodeToRemove); + pList->count--; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_peek_front() - peek front node from list + * @pList: Pointer to list + * @ppNode: Double pointer to store peeked node pointer + * + * Return: CDF status + */ +CDF_STATUS cdf_list_peek_front(cdf_list_t *pList, cdf_list_node_t **ppNode) +{ + struct list_head *listptr; + if (list_empty(&pList->anchor)) + return CDF_STATUS_E_EMPTY; + + listptr = pList->anchor.next; + *ppNode = listptr; + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_list_peek_next() - peek next node of input node in the list + * @pList: Pointer to list + * @pNode: Pointer to input node + * @ppNode: Double pointer to store peeked node pointer + * + * Return: CDF status + */ +CDF_STATUS cdf_list_peek_next(cdf_list_t *pList, cdf_list_node_t *pNode, + cdf_list_node_t **ppNode) +{ + struct list_head *listptr; + int found = 0; + cdf_list_node_t *tmp; + + if ((pList == NULL) || (pNode == NULL) || (ppNode == NULL)) + return CDF_STATUS_E_FAULT; + + if (list_empty(&pList->anchor)) + return CDF_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 CDF_STATUS_E_INVAL; + + listptr = pNode->next; + if (listptr == &pList->anchor) + return CDF_STATUS_E_EMPTY; + + *ppNode = listptr; + + return CDF_STATUS_SUCCESS; +} diff --git a/core/cdf/src/cdf_lock.c b/core/cdf/src/cdf_lock.c new file mode 100644 index 000000000000..283cd510cd05 --- /dev/null +++ b/core/cdf/src/cdf_lock.c @@ -0,0 +1,491 @@ +/* + * 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. + */ + +/** + * DOC: cdf_lock.c + * + * OVERVIEW: This source file contains definitions for CDF 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 + */ + +/* Include Files */ + +#include "cdf_lock.h" +#include "cdf_memory.h" +#include "cdf_trace.h" +#include +#ifdef CONFIG_CNSS +#include +#endif +#include "i_host_diag_core_event.h" +#include "cds_api.h" +#include "ani_global.h" + +/* Preprocessor Definitions and Constants */ +#define LINUX_LOCK_COOKIE 0x12345678 + +#define WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT 0 +#define WIFI_POWER_EVENT_WAKELOCK_TAKEN 0 +#define WIFI_POWER_EVENT_WAKELOCK_RELEASED 1 + +/* Type Declarations */ + +enum { + LOCK_RELEASED = 0x11223344, + LOCK_ACQUIRED, + LOCK_DESTROYED +}; + +/* Global Data Definitions */ + +/* Function Definitions and Documentation */ + +/** + * cdf_mutex_init() - initialize a CDF lock + * @lock: Pointer to the opaque lock object to initialize + * + * cdf_mutex_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 cdf_mutex_init() before it + * may be used in any other lock functions. + * + * Attempting to initialize an already initialized lock results in + * a failure. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_init(cdf_mutex_t *lock) +{ + /* check for invalid pointer */ + if (lock == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return CDF_STATUS_E_FAULT; + } + /* check for 'already initialized' lock */ + if (LINUX_LOCK_COOKIE == lock->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: already initialized lock", __func__); + return CDF_STATUS_E_BUSY; + } + + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + return CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * cdf_mutex_acquire() - acquire a CDF lock + * @lock: Pointer to the opaque lock object to acquire + * + * A lock object is acquired by calling cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_acquire(cdf_mutex_t *lock) +{ + int rc; + /* check for invalid pointer */ + if (lock == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + /* check if lock refers to an initialized object */ + if (LINUX_LOCK_COOKIE != lock->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: uninitialized lock", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + if ((lock->processID == current->pid) && + (lock->state == LOCK_ACQUIRED)) { + lock->refcount++; +#ifdef CDF_NESTED_LOCK_DEBUG + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: %x %d %d", __func__, lock, current->pid, + lock->refcount); +#endif + return CDF_STATUS_SUCCESS; + } + /* acquire a Lock */ + mutex_lock(&lock->m_lock); + rc = mutex_is_locked(&lock->m_lock); + if (rc == 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: unable to lock mutex (rc = %d)", __func__, rc); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } +#ifdef CDF_NESTED_LOCK_DEBUG + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 CDF_STATUS_SUCCESS; + } else { + /* lock is already destroyed */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Lock is already destroyed", __func__); + mutex_unlock(&lock->m_lock); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } +} + +/** + * cdf_mutex_release() - release a CDF lock + * @lock: Pointer to the opaque lock object to be released + * + * cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_release(cdf_mutex_t *lock) +{ + /* check for invalid pointer */ + if (lock == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check if lock refers to an uninitialized object */ + if (LINUX_LOCK_COOKIE != lock->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: uninitialized lock", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + CDF_ASSERT(0); + return CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: current task pid does not match original task pid!!", + __func__); +#ifdef CDF_NESTED_LOCK_DEBUG + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Lock held by=%d being released by=%d", + __func__, lock->processID, current->pid); +#endif + CDF_ASSERT(0); + return CDF_STATUS_E_PERM; + } + if ((lock->processID == current->pid) && + (lock->state == LOCK_ACQUIRED)) { + if (lock->refcount > 0) + lock->refcount--; + } +#ifdef CDF_NESTED_LOCK_DEBUG + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: %x %d %d", __func__, lock, lock->processID, + lock->refcount); +#endif + if (lock->refcount) + return CDF_STATUS_SUCCESS; + + lock->processID = 0; + lock->refcount = 0; + lock->state = LOCK_RELEASED; + /* release a Lock */ + mutex_unlock(&lock->m_lock); +#ifdef CDF_NESTED_LOCK_DEBUG + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Freeing lock %x %d %d", lock, lock->processID, + lock->refcount); +#endif + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_mutex_destroy() - destroy a CDF lock + * @lock: Pointer to the opaque lock object to be destroyed + * + * cdf_mutex_destroy() function shall destroy the lock object + * referenced by lock. After a successful return from cdf_mutex_destroy() + * the lock object becomes, in effect, uninitialized. + * + * A destroyed lock object can be reinitialized using cdf_mutex_init(); + * the results of otherwise referencing the object after it has been destroyed + * are undefined. Calls to CDF lock functions to manipulate the lock such + * as cdf_mutex_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. + * + * Return: + * CDF_STATUS_SUCCESS: lock was successfully initialized + * CDF failure reason codes: lock is not initialized and can't be used + */ +CDF_STATUS cdf_mutex_destroy(cdf_mutex_t *lock) +{ + /* check for invalid pointer */ + if (NULL == lock) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed in", __func__); + return CDF_STATUS_E_FAULT; + } + + if (LINUX_LOCK_COOKIE != lock->cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: uninitialized lock", __func__); + return CDF_STATUS_E_INVAL; + } + + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + return CDF_STATUS_E_FAULT; + } + + /* check if lock is released */ + if (!mutex_trylock(&lock->m_lock)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: lock is not released", __func__); + return CDF_STATUS_E_BUSY; + } + lock->cookie = 0; + lock->state = LOCK_DESTROYED; + lock->processID = 0; + lock->refcount = 0; + + mutex_unlock(&lock->m_lock); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_spinlock_acquire() - acquires a spin lock + * @pLock: Spin lock to acquire + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_spinlock_acquire(cdf_spinlock_t *pLock) +{ + spin_lock(&pLock->spinlock); + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_spinlock_release() - release a spin lock + * @pLock: Spin lock to release + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_spinlock_release(cdf_spinlock_t *pLock) +{ + spin_unlock(&pLock->spinlock); + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_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 *cdf_wake_lock_name(cdf_wake_lock_t *pLock) +{ +#if defined CONFIG_CNSS + if (pLock->name) + return pLock->name; +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + if (pLock->ws.name) + return pLock->ws.name; +#endif + return "UNNAMED_WAKELOCK"; +} + +/** + * cdf_wake_lock_init() - initializes a CDF wake lock + * @pLock: The wake lock to initialize + * @name: Name of wake lock + * + * Return: + * CDF status success : if wake lock is initialized + * CDF status failure : if wake lock was not initialized + */ +CDF_STATUS cdf_wake_lock_init(cdf_wake_lock_t *pLock, const char *name) +{ +#if defined CONFIG_CNSS + cnss_pm_wake_lock_init(pLock, name); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_init(pLock, WAKE_LOCK_SUSPEND, name); +#endif + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_wake_lock_acquire() - acquires a wake lock + * @pLock: The wake lock to acquire + * @reason: Reason for wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_acquire(cdf_wake_lock_t *pLock, uint32_t reason) +{ + host_diag_log_wlock(reason, cdf_wake_lock_name(pLock), + WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); +#if defined CONFIG_CNSS + cnss_pm_wake_lock(pLock); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock(pLock); +#endif + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_wake_lock_timeout_acquire() - acquires a wake lock with a timeout + * @pLock: The wake lock to acquire + * @reason: Reason for wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_timeout_acquire(cdf_wake_lock_t *pLock, uint32_t msec, + uint32_t reason) +{ + /* Wakelock for Rx is frequent. + * It is reported only during active debug + */ + if (((cds_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)) { + host_diag_log_wlock(reason, cdf_wake_lock_name(pLock), msec, + WIFI_POWER_EVENT_WAKELOCK_TAKEN); + } +#if defined CONFIG_CNSS + cnss_pm_wake_lock_timeout(pLock, msec); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_timeout(pLock, msecs_to_jiffies(msec)); +#endif + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_wake_lock_release() - releases a wake lock + * @pLock: the wake lock to release + * @reason: Reason for wakelock + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_release(cdf_wake_lock_t *pLock, uint32_t reason) +{ + host_diag_log_wlock(reason, cdf_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); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_unlock(pLock); +#endif + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_wake_lock_destroy() - destroys a wake lock + * @pLock: The wake lock to destroy + * + * Return: + * CDF status success : if wake lock is acquired + * CDF status failure : if wake lock was not acquired + */ +CDF_STATUS cdf_wake_lock_destroy(cdf_wake_lock_t *pLock) +{ +#if defined CONFIG_CNSS + cnss_pm_wake_lock_destroy(pLock); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_destroy(pLock); +#endif + return CDF_STATUS_SUCCESS; +} diff --git a/core/cdf/src/cdf_mc_timer.c b/core/cdf/src/cdf_mc_timer.c new file mode 100644 index 000000000000..cefdfccd7fba --- /dev/null +++ b/core/cdf/src/cdf_mc_timer.c @@ -0,0 +1,800 @@ +/* + * 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. + */ + +/** + * DOC: cdf_mc_timer + * + * Connectivity driver framework timer APIs serialized to MC thread + */ + +/* Include Files */ +#include +#include +#include +#include "wlan_qct_sys.h" +#include "cds_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 persistent_timer_count; +static cdf_mutex_t persistent_timer_count_lock; + +/* Function declarations and documenation */ + +/** + * try_allowing_sleep() - clean up timer states after it has been deactivated + * @type: Timer type + * + * Clean up timer states after it has been deactivated check and try to allow + * sleep after a timer has been stopped or expired. + * + * Return: none + */ +static void try_allowing_sleep(CDF_TIMER_TYPE type) +{ + if (CDF_TIMER_TYPE_WAKE_APPS == type) { + /* cdf_mutex_acquire(&persistent_timer_count_lock); */ + persistent_timer_count--; + if (0 == persistent_timer_count) { + /* since the number of persistent timers has + decreased from 1 to 0, the timer should allow + sleep sleep_assert_okts( sleepClientHandle ); */ + } + /* cdf_mutex_release(&persistent_timer_count_lock); */ + } +} + +/** + * cdf_linux_timer_callback() - internal cdf entry point which is + * called when the timer interval expires + * @data: pointer to the timer control block which describes the + * timer that expired + * + * This function in turn calls the CDF client callback and changes the + * state of the timer from running (ACTIVE) to expired (INIT). + * + * 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. + * + * Return: nothing + */ + +static void cdf_linux_timer_callback(unsigned long data) +{ + cdf_mc_timer_t *timer = (cdf_mc_timer_t *) data; + cds_msg_t msg; + CDF_STATUS vStatus; + unsigned long flags; + + cdf_mc_timer_callback_t callback = NULL; + void *userData = NULL; + int threadId; + CDF_TIMER_TYPE type = CDF_TIMER_TYPE_SW; + + CDF_ASSERT(timer); + + if (timer == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 CDF_TIMER_STATE_STARTING: + /* we are in this state because someone just started the timer, + * MC timer got started and expired, but the time content have + * not been updated this is a rare race condition! + */ + timer->state = CDF_TIMER_STATE_STOPPED; + vStatus = CDF_STATUS_E_ALREADY; + break; + + case CDF_TIMER_STATE_STOPPED: + vStatus = CDF_STATUS_E_ALREADY; + break; + + case CDF_TIMER_STATE_UNUSED: + vStatus = CDF_STATUS_E_EXISTS; + break; + + case CDF_TIMER_STATE_RUNNING: + /* need to go to stop state here because the call-back function + * may restart timer (to emulate periodic timer) + */ + timer->state = CDF_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 = CDF_STATUS_SUCCESS; + break; + + default: + CDF_ASSERT(0); + vStatus = CDF_STATUS_E_FAULT; + break; + } + + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + + if (CDF_STATUS_SUCCESS != vStatus) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "TIMER callback called in a wrong state=%d", + timer->state); + return; + } + + try_allowing_sleep(type); + + if (callback == NULL) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: No TIMER callback, Could not enqueue timer to any queue", + __func__); + return; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "TIMER callback: running on MC thread"); + + /* serialize to the MC thread */ + sys_build_message_header(SYS_MSG_ID_MC_TIMER, &msg); + msg.callback = callback; + msg.bodyptr = userData; + msg.bodyval = 0; + + if (cds_mq_post_message(CDS_MQ_ID_SYS, &msg) == CDF_STATUS_SUCCESS) + return; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Could not enqueue timer to any queue", __func__); + CDF_ASSERT(0); +} + +/** + * cdf_mc_timer_get_current_state() - get the current state of the timer + * @pTimer: Pointer to timer object + * + * Return: + * CDF_TIMER_STATE - cdf timer state + */ +CDF_TIMER_STATE cdf_mc_timer_get_current_state(cdf_mc_timer_t *pTimer) +{ + if (NULL == pTimer) { + CDF_ASSERT(0); + return CDF_TIMER_STATE_UNUSED; + } + + switch (pTimer->state) { + case CDF_TIMER_STATE_STOPPED: + case CDF_TIMER_STATE_STARTING: + case CDF_TIMER_STATE_RUNNING: + case CDF_TIMER_STATE_UNUSED: + return pTimer->state; + default: + CDF_ASSERT(0); + return CDF_TIMER_STATE_UNUSED; + } +} + +/** + * cdf_timer_module_init() - initializes a CDF timer module. + * + * This API initializes the CDF timer module. This needs to be called + * exactly once prior to using any CDF timers. + * + * Return: none + */ +void cdf_timer_module_init(void) +{ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "Initializing the CDF timer module"); + cdf_mutex_init(&persistent_timer_count_lock); +} + +#ifdef TIMER_MANAGER + +cdf_list_t cdf_timer_list; +cdf_spinlock_t cdf_timer_list_lock; + +static void cdf_timer_clean(void); + +/** + * cdf_mc_timer_manager_init() - initialize CDF debug timer manager + * + * This API initializes CDF timer debug functionality. + * + * Return: none + */ +void cdf_mc_timer_manager_init(void) +{ + /* Initalizing the list with maximum size of 60000 */ + cdf_list_init(&cdf_timer_list, 1000); + cdf_spinlock_init(&cdf_timer_list_lock); + return; +} + +/** + * cdf_timer_clean() - clean up CDF timer debug functionality + * + * This API cleans up CDF timer debug functionality and prints which CDF timers + * are leaked. This is called during driver unload. + * + * Return: none + */ +static void cdf_timer_clean(void) +{ + uint32_t listSize; + + cdf_list_size(&cdf_timer_list, &listSize); + + if (listSize) { + cdf_list_node_t *pNode; + CDF_STATUS cdf_status; + + cdf_mc_timer_node_t *ptimerNode; + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: List is not Empty. listSize %d ", + __func__, (int)listSize); + + do { + cdf_spin_lock_irqsave(&cdf_timer_list_lock); + cdf_status = + cdf_list_remove_front(&cdf_timer_list, &pNode); + cdf_spin_unlock_irqrestore(&cdf_timer_list_lock); + if (CDF_STATUS_SUCCESS == cdf_status) { + ptimerNode = (cdf_mc_timer_node_t *) pNode; + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_FATAL, + "Timer Leak@ File %s, @Line %d", + ptimerNode->fileName, + (int)ptimerNode->lineNum); + cdf_mem_free(ptimerNode); + } + } while (cdf_status == CDF_STATUS_SUCCESS); + } +} + +/** + * cdf_mc_timer_exit() - exit CDF timer debug functionality + * + * This API exists CDF timer debug functionality + * + * Return: none + */ +void cdf_mc_timer_exit(void) +{ + cdf_timer_clean(); + cdf_list_destroy(&cdf_timer_list); +} +#endif + +/** + * cdf_mc_timer_init() - initialize a CDF timer + * @pTimer: Pointer to timer object + * @timerType: Type of timer + * @callback: Callback to be called after timer expiry + * @serData: User data which will be passed to callback function + * + * This API initializes a CDF Timer object. + * + * cdf_mc_timer_init() initializes a CDF Timer object. A timer must be + * initialized by calling cdf_mc_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 + * cdf_mc_timer_init(). The results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Calls to CDF timer functions to manipulate the timer such + * as cdf_mc_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 CDS main thread unless it is + * initialized from the Tx thread flow, in which case it will be executed + * within the tx thread flow. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +#ifdef TIMER_MANAGER +CDF_STATUS cdf_mc_timer_init_debug(cdf_mc_timer_t *timer, + CDF_TIMER_TYPE timerType, + cdf_mc_timer_callback_t callback, + void *userData, char *fileName, + uint32_t lineNum) +{ + CDF_STATUS cdf_status; + + /* check for invalid pointer */ + if ((timer == NULL) || (callback == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + timer->ptimerNode = cdf_mem_malloc(sizeof(cdf_mc_timer_node_t)); + + if (timer->ptimerNode == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for timeNode", + __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set(timer->ptimerNode, sizeof(cdf_mc_timer_node_t), 0); + + timer->ptimerNode->fileName = fileName; + timer->ptimerNode->lineNum = lineNum; + timer->ptimerNode->cdf_timer = timer; + + cdf_spin_lock_irqsave(&cdf_timer_list_lock); + cdf_status = cdf_list_insert_front(&cdf_timer_list, + &timer->ptimerNode->pNode); + cdf_spin_unlock_irqrestore(&cdf_timer_list_lock); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Unable to insert node into List cdf_status %d", + __func__, cdf_status); + } + + /* set the various members of the timer structure + * with arguments passed or with default values + */ + spin_lock_init(&timer->platformInfo.spinlock); + if (CDF_TIMER_TYPE_SW == timerType) + init_timer_deferrable(&(timer->platformInfo.Timer)); + else + init_timer(&(timer->platformInfo.Timer)); + timer->platformInfo.Timer.function = cdf_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 = CDF_TIMER_STATE_STOPPED; + + return CDF_STATUS_SUCCESS; +} +#else +CDF_STATUS cdf_mc_timer_init(cdf_mc_timer_t *timer, CDF_TIMER_TYPE timerType, + cdf_mc_timer_callback_t callback, + void *userData) +{ + /* check for invalid pointer */ + if ((timer == NULL) || (callback == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + CDF_ASSERT(0); + return CDF_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 (CDF_TIMER_TYPE_SW == timerType) + init_timer_deferrable(&(timer->platformInfo.Timer)); + else + init_timer(&(timer->platformInfo.Timer)); + timer->platformInfo.Timer.function = cdf_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 = CDF_TIMER_STATE_STOPPED; + + return CDF_STATUS_SUCCESS; +} +#endif + +/** + * cdf_mc_timer_destroy() - destroy CDF timer + * @timer: Pointer to timer object + * + * cdf_mc_timer_destroy() function shall destroy the timer object. + * After a successful return from \a cdf_mc_timer_destroy() the timer + * object becomes, in effect, uninitialized. + * + * A destroyed timer object can be re-initialized by calling + * cdf_mc_timer_init(). The results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Calls to CDF timer functions to manipulate the timer, such + * as cdf_mc_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. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +#ifdef TIMER_MANAGER +CDF_STATUS cdf_mc_timer_destroy(cdf_mc_timer_t *timer) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + unsigned long flags; + + /* check for invalid pointer */ + if (NULL == timer) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null timer pointer being passed", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* Check if timer refers to an uninitialized object */ + if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot destroy uninitialized timer", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + cdf_spin_lock_irqsave(&cdf_timer_list_lock); + vStatus = cdf_list_remove_node(&cdf_timer_list, + &timer->ptimerNode->pNode); + cdf_spin_unlock_irqrestore(&cdf_timer_list_lock); + if (vStatus != CDF_STATUS_SUCCESS) { + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + cdf_mem_free(timer->ptimerNode); + + spin_lock_irqsave(&timer->platformInfo.spinlock, flags); + + switch (timer->state) { + + case CDF_TIMER_STATE_STARTING: + vStatus = CDF_STATUS_E_BUSY; + break; + + case CDF_TIMER_STATE_RUNNING: + /* Stop the timer first */ + del_timer(&(timer->platformInfo.Timer)); + vStatus = CDF_STATUS_SUCCESS; + break; + case CDF_TIMER_STATE_STOPPED: + vStatus = CDF_STATUS_SUCCESS; + break; + + case CDF_TIMER_STATE_UNUSED: + vStatus = CDF_STATUS_E_ALREADY; + break; + + default: + vStatus = CDF_STATUS_E_FAULT; + break; + } + + if (CDF_STATUS_SUCCESS == vStatus) { + timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE; + timer->state = CDF_TIMER_STATE_UNUSED; + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + return vStatus; + } + + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot destroy timer in state = %d", __func__, + timer->state); + CDF_ASSERT(0); + + return vStatus; +} + +#else + +/** + * cdf_mc_timer_destroy() - destroy CDF timer + * @timer: Pointer to timer object + * + * cdf_mc_timer_destroy() function shall destroy the timer object. + * After a successful return from \a cdf_mc_timer_destroy() the timer + * object becomes, in effect, uninitialized. + * + * A destroyed timer object can be re-initialized by calling + * cdf_mc_timer_init(). The results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Calls to CDF timer functions to manipulate the timer, such + * as cdf_mc_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. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_destroy(cdf_mc_timer_t *timer) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + unsigned long flags; + + /* check for invalid pointer */ + if (NULL == timer) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null timer pointer being passed", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + /* check if timer refers to an uninitialized object */ + if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot destroy uninitialized timer", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + spin_lock_irqsave(&timer->platformInfo.spinlock, flags); + + switch (timer->state) { + + case CDF_TIMER_STATE_STARTING: + vStatus = CDF_STATUS_E_BUSY; + break; + + case CDF_TIMER_STATE_RUNNING: + /* Stop the timer first */ + del_timer(&(timer->platformInfo.Timer)); + vStatus = CDF_STATUS_SUCCESS; + break; + + case CDF_TIMER_STATE_STOPPED: + vStatus = CDF_STATUS_SUCCESS; + break; + + case CDF_TIMER_STATE_UNUSED: + vStatus = CDF_STATUS_E_ALREADY; + break; + + default: + vStatus = CDF_STATUS_E_FAULT; + break; + } + + if (CDF_STATUS_SUCCESS == vStatus) { + timer->platformInfo.cookie = LINUX_INVALID_TIMER_COOKIE; + timer->state = CDF_TIMER_STATE_UNUSED; + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + return vStatus; + } + + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot destroy timer in state = %d", __func__, + timer->state); + CDF_ASSERT(0); + + return vStatus; +} +#endif + +/** + * cdf_mc_timer_start() - start a CDF Timer object + * @timer: Pointer to timer object + * @expirationTime: Time to expire + * + * cdf_mc_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, cdf_mc_timer_start() has to be called after the timer runs + * or has been cancelled. + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_start(cdf_mc_timer_t *timer, uint32_t expirationTime) +{ + unsigned long flags; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "Timer Addr inside cds_enable : 0x%p ", timer); + + /* check for invalid pointer */ + if (NULL == timer) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s Null timer pointer being passed", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + /* check if timer refers to an uninitialized object */ + if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot start uninitialized timer", __func__); + if (LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie) + CDF_ASSERT(0); + + return CDF_STATUS_E_INVAL; + } + + /* check if timer has expiration time less than 10 ms */ + if (expirationTime < 10) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot start a timer with expiration less than 10 ms", + __func__); + CDF_ASSERT(0); + return CDF_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 (CDF_TIMER_STATE_STOPPED != timer->state) { + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Cannot start timer in state = %d ", __func__, + timer->state); + return CDF_STATUS_E_ALREADY; + } + + /* start the timer */ + mod_timer(&(timer->platformInfo.Timer), + jiffies + msecs_to_jiffies(expirationTime)); + + timer->state = CDF_TIMER_STATE_RUNNING; + + /* get the thread ID on which the timer is being started */ + timer->platformInfo.threadID = current->pid; + + if (CDF_TIMER_TYPE_WAKE_APPS == timer->type) { + persistent_timer_count++; + if (1 == persistent_timer_count) { + /* since we now have one persistent timer, + * we need to disallow sleep + * sleep_negate_okts(sleepClientHandle); + */ + } + } + + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_mc_timer_stop() - stop a CDF Timer + * @timer: Pointer to timer object + * cdf_mc_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 cdf_mc_timer_start(). + * + * Return: + * CDF_STATUS_SUCCESS - Timer is initialized successfully + * CDF failure status - Timer initialization failed + */ +CDF_STATUS cdf_mc_timer_stop(cdf_mc_timer_t *timer) +{ + unsigned long flags; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Timer Addr inside cds_disable : 0x%p", __func__, timer); + + /* check for invalid pointer */ + if (NULL == timer) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s Null timer pointer being passed", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + /* check if timer refers to an uninitialized object */ + if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot stop uninitialized timer", __func__); + if (LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie) + CDF_ASSERT(0); + + return CDF_STATUS_E_INVAL; + } + + /* ensure the timer state is correct */ + spin_lock_irqsave(&timer->platformInfo.spinlock, flags); + + if (CDF_TIMER_STATE_RUNNING != timer->state) { + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Cannot stop timer in state = %d", + __func__, timer->state); + return CDF_STATUS_SUCCESS; + } + + timer->state = CDF_TIMER_STATE_STOPPED; + + del_timer(&(timer->platformInfo.Timer)); + + spin_unlock_irqrestore(&timer->platformInfo.spinlock, flags); + + try_allowing_sleep(timer->type); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_mc_timer_get_system_ticks() - get the system time in 10ms ticks + + * cdf_mc_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. + * + * Return: + * The current system tick count (in 10msec intervals). This + * function cannot fail. + */ +v_TIME_t cdf_mc_timer_get_system_ticks(void) +{ + return jiffies_to_msecs(jiffies) / 10; +} + +/** + * cdf_mc_timer_get_system_time() - Get the system time in milliseconds + * + * cdf_mc_timer_get_system_time() function returns the number of milliseconds + * that have elapsed since the system was started + * + * Return: + * The current system time in milliseconds + */ +v_TIME_t cdf_mc_timer_get_system_time(void) +{ + struct timeval tv; + do_gettimeofday(&tv); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c new file mode 100644 index 000000000000..732d1e59c9ff --- /dev/null +++ b/core/cdf/src/cdf_memory.c @@ -0,0 +1,631 @@ +/* + * 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. + */ + +/** + * DOC: cdf_memory + * + * Connectivity driver framework (CDF) memory management APIs + */ + +/* Include Files */ +#include "cdf_memory.h" +#include "cdf_nbuf.h" +#include "cdf_trace.h" +#include "cdf_lock.h" + +#if defined(CONFIG_CNSS) +#include +#endif + +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC +#include +#endif + +#ifdef MEMORY_DEBUG +#include + +cdf_list_t cdf_mem_list; +cdf_spinlock_t cdf_mem_list_lock; + +static uint8_t WLAN_MEM_HEADER[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68 }; +static uint8_t WLAN_MEM_TAIL[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87 }; + +struct s_cdf_mem_struct { + cdf_list_node_t pNode; + char *fileName; + unsigned int lineNum; + unsigned int size; + uint8_t header[8]; +}; +#endif + +/* Preprocessor Definitions and Constants */ + +/* Type Declarations */ + +/* Data definitions */ + +/* External Function implementation */ +#ifdef MEMORY_DEBUG + +/** + * cdf_mem_init() - initialize cdf memory debug functionality + * + * Return: none + */ +void cdf_mem_init(void) +{ + /* Initalizing the list with maximum size of 60000 */ + cdf_list_init(&cdf_mem_list, 60000); + cdf_spinlock_init(&cdf_mem_list_lock); + cdf_net_buf_debug_init(); + return; +} + +/** + * cdf_mem_clean() - display memory leak debug info and free leaked pointers + * + * Return: none + */ +void cdf_mem_clean(void) +{ + uint32_t listSize; + cdf_list_size(&cdf_mem_list, &listSize); + + cdf_net_buf_debug_clean(); + + if (listSize) { + cdf_list_node_t *pNode; + CDF_STATUS cdf_status; + + struct s_cdf_mem_struct *memStruct; + char *prev_mleak_file = ""; + unsigned int prev_mleak_lineNum = 0; + unsigned int prev_mleak_sz = 0; + unsigned int mleak_cnt = 0; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: List is not Empty. listSize %d ", + __func__, (int)listSize); + + do { + cdf_spin_lock(&cdf_mem_list_lock); + cdf_status = + cdf_list_remove_front(&cdf_mem_list, &pNode); + cdf_spin_unlock(&cdf_mem_list_lock); + if (CDF_STATUS_SUCCESS == cdf_status) { + memStruct = (struct s_cdf_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_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++; + kfree((void *)memStruct); + } + } while (cdf_status == CDF_STATUS_SUCCESS); + + /* Print last memory leak from the module */ + if (mleak_cnt) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 + } +} + +/** + * cdf_mem_exit() - exit cdf memory debug functionality + * + * Return: none + */ +void cdf_mem_exit(void) +{ + cdf_net_buf_debug_exit(); + cdf_mem_clean(); + cdf_list_destroy(&cdf_mem_list); +} + +/** + * cdf_mem_malloc_debug() - debug version of CDF memory allocation API + * @size: Number of bytes of memory to allocate. + * @fileName: File name from which memory allocation is called + * @lineNum: Line number from which memory allocation is called + * + * This function will dynamicallly allocate the specified number of bytes of + * memory and ad it in cdf tracking list to check against memory leaks and + * corruptions + * + * + * 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. + * + */ +void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum) +{ + struct s_cdf_mem_struct *memStruct; + void *memPtr = NULL; + uint32_t new_size; + int flags = GFP_KERNEL; + + if (size > (1024 * 1024)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: called with arg > 1024K; passed in %zu !!!", + __func__, size); + return NULL; + } + +#if defined(CONFIG_CNSS) && defined(CONFIG_WCNSS_MEM_PRE_ALLOC) + if (size > WCNSS_PRE_ALLOC_GET_THRESHOLD) { + void *pmem; + pmem = wcnss_prealloc_get(size); + if (NULL != pmem) { + memset(pmem, 0, size); + return pmem; + } + } +#endif + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + new_size = size + sizeof(struct s_cdf_mem_struct) + 8; + + memStruct = (struct s_cdf_mem_struct *)kzalloc(new_size, flags); + + if (memStruct != NULL) { + CDF_STATUS cdf_status; + + memStruct->fileName = fileName; + memStruct->lineNum = lineNum; + memStruct->size = size; + + cdf_mem_copy(&memStruct->header[0], + &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)); + + cdf_mem_copy((uint8_t *) (memStruct + 1) + size, + &WLAN_MEM_TAIL[0], sizeof(WLAN_MEM_TAIL)); + + cdf_spin_lock_irqsave(&cdf_mem_list_lock); + cdf_status = cdf_list_insert_front(&cdf_mem_list, + &memStruct->pNode); + cdf_spin_unlock_irqrestore(&cdf_mem_list_lock); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Unable to insert node into List cdf_status %d", + __func__, cdf_status); + } + + memPtr = (void *)(memStruct + 1); + } + return memPtr; +} + +/** + * cdf_mem_free() - debug version of CDF memory free API + * @ptr: Pointer to the starting address of the memory to be free'd. + * + * This function will free the memory pointed to by 'ptr'. It also checks + * is memory is corrupted or getting double freed and panic. + * + * Return: + * Nothing + */ +void cdf_mem_free(void *ptr) +{ + if (ptr != NULL) { + CDF_STATUS cdf_status; + struct s_cdf_mem_struct *memStruct = + ((struct s_cdf_mem_struct *)ptr) - 1; + +#if defined(CONFIG_CNSS) && defined(CONFIG_WCNSS_MEM_PRE_ALLOC) + if (wcnss_prealloc_put(ptr)) + return; +#endif + + cdf_spin_lock_irqsave(&cdf_mem_list_lock); + cdf_status = + cdf_list_remove_node(&cdf_mem_list, &memStruct->pNode); + cdf_spin_unlock_irqrestore(&cdf_mem_list_lock); + + if (CDF_STATUS_SUCCESS == cdf_status) { + if (0 == cdf_mem_compare(memStruct->header, + &WLAN_MEM_HEADER[0], + sizeof(WLAN_MEM_HEADER))) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_FATAL, + "Memory Header is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, + (int)memStruct->lineNum); + CDF_BUG(0); + } + if (0 == + cdf_mem_compare((uint8_t *) ptr + memStruct->size, + &WLAN_MEM_TAIL[0], + sizeof(WLAN_MEM_TAIL))) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_FATAL, + "Memory Trailer is corrupted. MemInfo: Filename %s, LineNum %d", + memStruct->fileName, + (int)memStruct->lineNum); + CDF_BUG(0); + } + kfree((void *)memStruct); + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Unallocated memory (double free?)", + __func__); + CDF_BUG(0); + } + } +} +#else +/** + * cdf_mem_malloc() - allocation CDF memory + * @size: Number of bytes of memory to allocate. + * + * This function will dynamicallly allocate the specified number of bytes of + * memory. + * + * + * 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. + * + */ +void *cdf_mem_malloc(size_t size) +{ + int flags = GFP_KERNEL; +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC + void *pmem; +#endif + if (size > (1024 * 1024)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: called with arg > 1024K; passed in %zu !!", + __func__, size); + return NULL; + } + +#if defined(CONFIG_CNSS) && defined(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 + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + return kzalloc(size, flags); +} + +/** + * cdf_mem_free() - free CDF memory + * @ptr: Pointer to the starting address of the memory to be free'd. + * + * This function will free the memory pointed to by 'ptr'. + * + * Return: + * Nothing + * + */ +void cdf_mem_free(void *ptr) +{ + if (ptr == NULL) + return; + +#if defined(CONFIG_CNSS) && defined(CONFIG_WCNSS_MEM_PRE_ALLOC) + if (wcnss_prealloc_put(ptr)) + return; +#endif + + kfree(ptr); +} +#endif + +/** + * cdf_mem_set() - set (fill) memory with a specified byte value. + * @pMemory: Pointer to memory that will be set + * @numBytes: Number of bytes to be set + * @value: Byte set in memory + * + * Return: + * Nothing + * + */ +void cdf_mem_set(void *ptr, uint32_t numBytes, uint32_t value) +{ + if (ptr == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter ptr", __func__); + return; + } + memset(ptr, value, numBytes); +} + +/** + * cdf_mem_zero() - zero out memory + * @pMemory: pointer to memory that will be set to zero + * @numBytes: number of bytes zero + * @value: byte set in memory + * + * This function sets the memory location to all zeros, essentially clearing + * the memory. + * + * Return: + * Nothing + * + */ +void cdf_mem_zero(void *ptr, uint32_t numBytes) +{ + if (0 == numBytes) { + /* special case where ptr can be NULL */ + return; + } + + if (ptr == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter ptr", __func__); + return; + } + memset(ptr, 0, numBytes); +} + +/** + * cdf_mem_copy() - copy memory + * @pDst: Pointer to destination memory location (to copy to) + * @pSrc: Pointer to source memory location (to copy from) + * @numBytes: Number of bytes to copy. + * + * 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 cdf_mem_move() if the memory locations + * for the source and destination are overlapping (or could be overlapping!) + * + * Return: + * Nothing + * + */ +void cdf_mem_copy(void *pDst, const void *pSrc, uint32_t numBytes) +{ + if (0 == numBytes) { + /* special case where pDst or pSrc can be NULL */ + return; + } + + if ((pDst == NULL) || (pSrc == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, source:%p destination:%p", + __func__, pSrc, pDst); + CDF_ASSERT(0); + return; + } + memcpy(pDst, pSrc, numBytes); +} + +/** + * cdf_mem_move() - move memory + * @pDst: pointer to destination memory location (to move to) + * @pSrc: pointer to source memory location (to move from) + * @numBytes: number of bytes to move. + * + * 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. + + * Return: + * Nothing + */ +void cdf_mem_move(void *pDst, const void *pSrc, uint32_t numBytes) +{ + if (0 == numBytes) { + /* special case where pDst or pSrc can be NULL */ + return; + } + + if ((pDst == NULL) || (pSrc == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, source:%p destination:%p", + __func__, pSrc, pDst); + CDF_ASSERT(0); + return; + } + memmove(pDst, pSrc, numBytes); +} + +/** + * cdf_mem_compare() - memory compare + * @pMemory1: pointer to one location in memory to compare. + * @pMemory2: pointer to second location in memory to compare. + * @numBytes: the number of bytes to compare. + * + * Function to compare two pieces of memory, similar to memcmp function + * in standard C. + * + * Return: + * bool - returns a bool value that tells if the memory locations + * are equal or not equal. + * + */ +bool cdf_mem_compare(const void *pMemory1, const void *pMemory2, + uint32_t numBytes) +{ + if (0 == numBytes) { + /* special case where pMemory1 or pMemory2 can be NULL */ + return true; + } + + if ((pMemory1 == NULL) || (pMemory2 == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s called with NULL parameter, p1:%p p2:%p", + __func__, pMemory1, pMemory2); + CDF_ASSERT(0); + return false; + } + return memcmp(pMemory1, pMemory2, numBytes) ? false : true; +} + +/** + * cdf_mem_compare2() - memory compare + * @pMemory1: pointer to one location in memory to compare. + * @pMemory2: pointer to second location in memory to compare. + * @numBytes: the number of bytes to compare. + * + * Function to compare two pieces of memory, similar to memcmp function + * in standard C. + * Return: + * int32_t - returns a bool 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 + */ +int32_t cdf_mem_compare2(const void *pMemory1, const void *pMemory2, + uint32_t numBytes) +{ + return (int32_t) memcmp(pMemory1, pMemory2, numBytes); +} + +/** + * cdf_os_mem_alloc_consistent() - allocates consistent cdf memory + * @osdev: OS device handle + * @size: Size to be allocated + * @paddr: Physical address + * @mctx: Pointer to DMA context + * + * Return: pointer of allocated memory or null if memory alloc fails + */ +inline void *cdf_os_mem_alloc_consistent(cdf_device_t osdev, cdf_size_t size, + cdf_dma_addr_t *paddr, + cdf_dma_context_t memctx) +{ +#if defined(A_SIMOS_DEVHOST) + static int first = 1; + void *vaddr; + + if (first) { + first = 0; + pr_err("Warning: bypassing %s\n", __func__); + } + vaddr = cdf_mem_malloc(size); + *paddr = ((cdf_dma_addr_t) vaddr); + return vaddr; +#else + int flags = GFP_KERNEL; + void *alloc_mem = NULL; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + flags = GFP_ATOMIC; + + alloc_mem = dma_alloc_coherent(osdev->dev, size, paddr, flags); + if (alloc_mem == NULL) + pr_err("%s Warning: unable to alloc consistent memory of size %zu!\n", + __func__, size); + return alloc_mem; +#endif +} + +/** + * cdf_os_mem_free_consistent() - free consistent cdf memory + * @osdev: OS device handle + * @size: Size to be allocated + * @paddr: Physical address + * @mctx: Pointer to DMA context + * + * Return: none + */ +inline void +cdf_os_mem_free_consistent(cdf_device_t osdev, + cdf_size_t size, + void *vaddr, + cdf_dma_addr_t paddr, cdf_dma_context_t memctx) +{ +#if defined(A_SIMOS_DEVHOST) + static int first = 1; + + if (first) { + first = 0; + pr_err("Warning: bypassing %s\n", __func__); + } + cdf_mem_free(vaddr); + return; +#else + dma_free_coherent(osdev->dev, size, vaddr, paddr); +#endif +} + + +/** + * cdf_os_mem_dma_sync_single_for_device() - assign memory to device + * @osdev: OS device handle + * @bus_addr: dma address to give to the device + * @size: Size of the memory block + * @direction: direction data will be dma'ed + * + * Assgin memory to the remote device. + * The cache lines are flushed to ram or invalidated as needed. + * + * Return: none + */ + +inline void +cdf_os_mem_dma_sync_single_for_device(cdf_device_t osdev, + cdf_dma_addr_t bus_addr, + cdf_size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_device(osdev->dev, bus_addr, size, direction); +} diff --git a/core/cdf/src/cdf_nbuf.c b/core/cdf/src/cdf_nbuf.c new file mode 100644 index 000000000000..382ff2b1ef14 --- /dev/null +++ b/core/cdf/src/cdf_nbuf.c @@ -0,0 +1,1017 @@ +/* + * 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. + */ + +/** + * DOC: cdf_nbuf.c + * + * Connectivity driver framework(CDF) network buffer management APIs + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(FEATURE_TSO) +#include +#include +#include +#include +#include +#endif /* FEATURE_TSO */ + +/* Packet Counter */ +static uint32_t nbuf_tx_mgmt[NBUF_TX_PKT_STATE_MAX]; +static uint32_t nbuf_tx_data[NBUF_TX_PKT_STATE_MAX]; + +/** + * cdf_nbuf_tx_desc_count_display() - Displays the packet counter + * + * Return: none + */ +void cdf_nbuf_tx_desc_count_display(void) +{ + cdf_print("Current Snapshot of the Driver:\n"); + cdf_print("Data Packets:\n"); + cdf_print("HDD %d TXRX_Q %d TXRX %d HTT %d", + nbuf_tx_data[NBUF_TX_PKT_HDD] - + (nbuf_tx_data[NBUF_TX_PKT_TXRX] + + nbuf_tx_data[NBUF_TX_PKT_TXRX_ENQUEUE] - + nbuf_tx_data[NBUF_TX_PKT_TXRX_DEQUEUE]), + nbuf_tx_data[NBUF_TX_PKT_TXRX_ENQUEUE] - + nbuf_tx_data[NBUF_TX_PKT_TXRX_DEQUEUE], + nbuf_tx_data[NBUF_TX_PKT_TXRX] - nbuf_tx_data[NBUF_TX_PKT_HTT], + nbuf_tx_data[NBUF_TX_PKT_HTT] - nbuf_tx_data[NBUF_TX_PKT_HTC]); + cdf_print(" HTC %d HIF %d CE %d TX_COMP %d\n", + nbuf_tx_data[NBUF_TX_PKT_HTC] - nbuf_tx_data[NBUF_TX_PKT_HIF], + nbuf_tx_data[NBUF_TX_PKT_HIF] - nbuf_tx_data[NBUF_TX_PKT_CE], + nbuf_tx_data[NBUF_TX_PKT_CE] - nbuf_tx_data[NBUF_TX_PKT_FREE], + nbuf_tx_data[NBUF_TX_PKT_FREE]); + cdf_print("Mgmt Packets:\n"); + cdf_print("TXRX_Q %d TXRX %d HTT %d HTC %d HIF %d CE %d TX_COMP %d\n", + nbuf_tx_mgmt[NBUF_TX_PKT_TXRX_ENQUEUE] - + nbuf_tx_mgmt[NBUF_TX_PKT_TXRX_DEQUEUE], + nbuf_tx_mgmt[NBUF_TX_PKT_TXRX] - nbuf_tx_mgmt[NBUF_TX_PKT_HTT], + nbuf_tx_mgmt[NBUF_TX_PKT_HTT] - nbuf_tx_mgmt[NBUF_TX_PKT_HTC], + nbuf_tx_mgmt[NBUF_TX_PKT_HTC] - nbuf_tx_mgmt[NBUF_TX_PKT_HIF], + nbuf_tx_mgmt[NBUF_TX_PKT_HIF] - nbuf_tx_mgmt[NBUF_TX_PKT_CE], + nbuf_tx_mgmt[NBUF_TX_PKT_CE] - nbuf_tx_mgmt[NBUF_TX_PKT_FREE], + nbuf_tx_mgmt[NBUF_TX_PKT_FREE]); +} + +/** + * cdf_nbuf_tx_desc_count_update() - Updates the layer packet counter + * @packet_type : packet type either mgmt/data + * @current_state : layer at which the packet currently present + * + * Return: none + */ +static inline void cdf_nbuf_tx_desc_count_update(uint8_t packet_type, + uint8_t current_state) +{ + switch (packet_type) { + case NBUF_TX_PKT_MGMT_TRACK: + nbuf_tx_mgmt[current_state]++; + break; + case NBUF_TX_PKT_DATA_TRACK: + nbuf_tx_data[current_state]++; + break; + default: + break; + } +} + +/** + * cdf_nbuf_tx_desc_count_clear() - Clears packet counter for both data, mgmt + * + * Return: none + */ +void cdf_nbuf_tx_desc_count_clear(void) +{ + memset(nbuf_tx_mgmt, 0, sizeof(nbuf_tx_mgmt)); + memset(nbuf_tx_data, 0, sizeof(nbuf_tx_data)); +} + +/** + * cdf_nbuf_set_state() - Updates the packet state + * @nbuf: network buffer + * @current_state : layer at which the packet currently is + * + * This function updates the packet state to the layer at which the packet + * currently is + * + * Return: none + */ +void cdf_nbuf_set_state(cdf_nbuf_t nbuf, uint8_t current_state) +{ + /* + * Only Mgmt, Data Packets are tracked. WMI messages + * such as scan commands are not tracked + */ + uint8_t packet_type; + packet_type = NBUF_GET_PACKET_TRACK(nbuf); + + if ((packet_type != NBUF_TX_PKT_DATA_TRACK) && + (packet_type != NBUF_TX_PKT_MGMT_TRACK)) { + return; + } + NBUF_SET_PACKET_STATE(nbuf, current_state); + cdf_nbuf_tx_desc_count_update(packet_type, + current_state); +} + +cdf_nbuf_trace_update_t trace_update_cb = NULL; + +/** + * __cdf_nbuf_alloc() - Allocate nbuf + * @hdl: Device handle + * @size: Netbuf requested size + * @reserve: Reserve + * @align: Align + * @prio: Priority + * + * 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. + * + * Return: nbuf or %NULL if no memory + */ +struct sk_buff *__cdf_nbuf_alloc(cdf_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 = dev_alloc_skb(size); + + if (!skb) { + pr_err("ERROR:NBUF alloc failed\n"); + return NULL; + } + 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; +} + +/** + * __cdf_nbuf_free() - free the nbuf its interrupt safe + * @skb: Pointer to network buffer + * + * Return: none + */ +void __cdf_nbuf_free(struct sk_buff *skb) +{ + if ((NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID) && NBUF_CALLBACK_FN(skb)) + NBUF_CALLBACK_FN_EXEC(skb); + else + dev_kfree_skb_any(skb); +} + +/** + * __cdf_nbuf_map() - get the dma map of the nbuf + * @osdev: OS device + * @bmap: Bitmap + * @skb: Pointer to network buffer + * @dir: Direction + * + * Return: CDF_STATUS + */ +CDF_STATUS +__cdf_nbuf_map(cdf_device_t osdev, struct sk_buff *skb, cdf_dma_dir_t dir) +{ +#ifdef CDF_OS_DEBUG + struct skb_shared_info *sh = skb_shinfo(skb); +#endif + cdf_assert((dir == CDF_DMA_TO_DEVICE) + || (dir == CDF_DMA_FROM_DEVICE)); + + /* + * Assume there's only a single fragment. + * To support multiple fragments, it would be necessary to change + * cdf_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. + */ + cdf_assert(sh->nr_frags == 0); + + return __cdf_nbuf_map_single(osdev, skb, dir); + + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_nbuf_unmap() - to unmap a previously mapped buf + * @osdev: OS device + * @skb: Pointer to network buffer + * @dir: Direction + * + * Return: none + */ +void +__cdf_nbuf_unmap(cdf_device_t osdev, struct sk_buff *skb, cdf_dma_dir_t dir) +{ + cdf_assert((dir == CDF_DMA_TO_DEVICE) + || (dir == CDF_DMA_FROM_DEVICE)); + + cdf_assert(((dir == CDF_DMA_TO_DEVICE) + || (dir == CDF_DMA_FROM_DEVICE))); + /* + * Assume there's a single fragment. + * If this is not true, the assertion in __cdf_nbuf_map will catch it. + */ + __cdf_nbuf_unmap_single(osdev, skb, dir); +} + +/** + * __cdf_nbuf_map_single() - dma map of the nbuf + * @osdev: OS device + * @skb: Pointer to network buffer + * @dir: Direction + * + * Return: CDF_STATUS + */ +CDF_STATUS +__cdf_nbuf_map_single(cdf_device_t osdev, cdf_nbuf_t buf, cdf_dma_dir_t dir) +{ + uint32_t paddr_lo; + +/* tempory hack for simulation */ +#ifdef A_SIMOS_DEVHOST + NBUF_MAPPED_PADDR_LO(buf) = paddr_lo = (uint32_t) buf->data; + return CDF_STATUS_SUCCESS; +#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) ? + CDF_STATUS_E_FAILURE : CDF_STATUS_SUCCESS; +#endif /* #ifdef A_SIMOS_DEVHOST */ +} + +/** + * __cdf_nbuf_unmap_single() - dma unmap nbuf + * @osdev: OS device + * @skb: Pointer to network buffer + * @dir: Direction + * + * Return: none + */ +void +__cdf_nbuf_unmap_single(cdf_device_t osdev, cdf_nbuf_t buf, cdf_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) */ +} + +/** + * __cdf_nbuf_set_rx_cksum() - set rx checksum + * @skb: Pointer to network buffer + * @cksum: Pointer to checksum value + * + * Return: CDF_STATUS + */ +CDF_STATUS +__cdf_nbuf_set_rx_cksum(struct sk_buff *skb, cdf_nbuf_rx_cksum_t *cksum) +{ + switch (cksum->l4_result) { + case CDF_NBUF_RX_CKSUM_NONE: + skb->ip_summed = CHECKSUM_NONE; + break; + case CDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY: + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + case CDF_NBUF_RX_CKSUM_TCP_UDP_HW: + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = cksum->val; + break; + default: + pr_err("ADF_NET:Unknown checksum type\n"); + cdf_assert(0); + return CDF_STATUS_E_NOSUPPORT; + } + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_nbuf_get_tx_cksum() - get tx checksum + * @skb: Pointer to network buffer + * + * Return: TX checksum value + */ +cdf_nbuf_tx_cksum_t __cdf_nbuf_get_tx_cksum(struct sk_buff *skb) +{ + switch (skb->ip_summed) { + case CHECKSUM_NONE: + return CDF_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 CDF_NBUF_TX_CKSUM_TCP_UDP; + case CHECKSUM_COMPLETE: + return CDF_NBUF_TX_CKSUM_TCP_UDP_IP; + default: + return CDF_NBUF_TX_CKSUM_NONE; + } +} + +/** + * __cdf_nbuf_get_tid() - get tid + * @skb: Pointer to network buffer + * + * Return: tid + */ +uint8_t __cdf_nbuf_get_tid(struct sk_buff *skb) +{ + return skb->priority; +} + +/** + * __cdf_nbuf_set_tid() - set tid + * @skb: Pointer to network buffer + * + * Return: none + */ +void __cdf_nbuf_set_tid(struct sk_buff *skb, uint8_t tid) +{ + skb->priority = tid; +} + +/** + * __cdf_nbuf_set_tid() - set tid + * @skb: Pointer to network buffer + * + * Return: none + */ +uint8_t __cdf_nbuf_get_exemption_type(struct sk_buff *skb) +{ + return CDF_NBUF_EXEMPT_NO_EXEMPTION; +} + +/** + * __cdf_nbuf_reg_trace_cb() - register trace callback + * @cb_func_ptr: Pointer to trace callback function + * + * Return: none + */ +void __cdf_nbuf_reg_trace_cb(cdf_nbuf_trace_update_t cb_func_ptr) +{ + trace_update_cb = cb_func_ptr; + return; +} + +#ifdef QCA_PKT_PROTO_TRACE +/** + * __cdf_nbuf_trace_update() - update trace event + * @skb: Pointer to network buffer + * @event_string: Pointer to trace callback function + * + * Return: none + */ +void __cdf_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 (!cdf_nbuf_trace_get_proto_type(buf)) + return; + + /* Buffer over flow */ + if (NBUF_PKT_TRAC_MAX_STRING <= + (cdf_str_len(event_string) + NBUF_PKT_TRAC_PROTO_STRING)) { + return; + } + + cdf_mem_zero(string_buf, NBUF_PKT_TRAC_MAX_STRING); + cdf_mem_copy(string_buf, event_string, cdf_str_len(event_string)); + if (NBUF_PKT_TRAC_TYPE_EAPOL & cdf_nbuf_trace_get_proto_type(buf)) { + cdf_mem_copy(string_buf + cdf_str_len(event_string), + "EPL", NBUF_PKT_TRAC_PROTO_STRING); + } else if (NBUF_PKT_TRAC_TYPE_DHCP & cdf_nbuf_trace_get_proto_type(buf)) { + cdf_mem_copy(string_buf + cdf_str_len(event_string), + "DHC", NBUF_PKT_TRAC_PROTO_STRING); + } else if (NBUF_PKT_TRAC_TYPE_MGMT_ACTION & + cdf_nbuf_trace_get_proto_type(buf)) { + cdf_mem_copy(string_buf + cdf_str_len(event_string), + "MACT", NBUF_PKT_TRAC_PROTO_STRING); + } + + trace_update_cb(string_buf); + return; +} +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef MEMORY_DEBUG +#define CDF_NET_BUF_TRACK_MAX_SIZE (1024) + +/** + * struct cdf_nbuf_track_t - Network buffer track structure + * + * @p_next: Pointer to next + * @net_buf: Pointer to network buffer + * @file_name: File name + * @line_num: Line number + * @size: Size + */ +struct cdf_nbuf_track_t { + struct cdf_nbuf_track_t *p_next; + cdf_nbuf_t net_buf; + uint8_t *file_name; + uint32_t line_num; + size_t size; +}; + +spinlock_t g_cdf_net_buf_track_lock; +typedef struct cdf_nbuf_track_t CDF_NBUF_TRACK; + +CDF_NBUF_TRACK *gp_cdf_net_buf_track_tbl[CDF_NET_BUF_TRACK_MAX_SIZE]; + +/** + * cdf_net_buf_debug_init() - initialize network buffer debug functionality + * + * CDF network buffer debug feature tracks all SKBs allocated by WLAN driver + * in a hash table and when driver is unloaded it reports about leaked SKBs. + * WLAN driver module whose allocated SKB is freed by network stack are + * suppose to call cdf_net_buf_debug_release_skb() such that the SKB is not + * reported as memory leak. + * + * Return: none + */ +void cdf_net_buf_debug_init(void) +{ + uint32_t i; + unsigned long irq_flag; + + spin_lock_init(&g_cdf_net_buf_track_lock); + + spin_lock_irqsave(&g_cdf_net_buf_track_lock, irq_flag); + + for (i = 0; i < CDF_NET_BUF_TRACK_MAX_SIZE; i++) + gp_cdf_net_buf_track_tbl[i] = NULL; + + spin_unlock_irqrestore(&g_cdf_net_buf_track_lock, irq_flag); + + return; +} + +/** + * cdf_net_buf_debug_init() - exit network buffer debug functionality + * + * Exit network buffer tracking debug functionality and log SKB memory leaks + * + * Return: none + */ +void cdf_net_buf_debug_exit(void) +{ + uint32_t i; + unsigned long irq_flag; + CDF_NBUF_TRACK *p_node; + CDF_NBUF_TRACK *p_prev; + + spin_lock_irqsave(&g_cdf_net_buf_track_lock, irq_flag); + + for (i = 0; i < CDF_NET_BUF_TRACK_MAX_SIZE; i++) { + p_node = gp_cdf_net_buf_track_tbl[i]; + while (p_node) { + p_prev = p_node; + p_node = p_node->p_next; + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "SKB buf memory Leak@ File %s, @Line %d, size %zu\n", + p_prev->file_name, p_prev->line_num, + p_prev->size); + } + } + + spin_unlock_irqrestore(&g_cdf_net_buf_track_lock, irq_flag); + + return; +} + +/** + * cdf_net_buf_debug_clean() - clean up network buffer debug functionality + * + * Return: none + */ +void cdf_net_buf_debug_clean(void) +{ + uint32_t i; + unsigned long irq_flag; + CDF_NBUF_TRACK *p_node; + CDF_NBUF_TRACK *p_prev; + + spin_lock_irqsave(&g_cdf_net_buf_track_lock, irq_flag); + + for (i = 0; i < CDF_NET_BUF_TRACK_MAX_SIZE; i++) { + p_node = gp_cdf_net_buf_track_tbl[i]; + while (p_node) { + p_prev = p_node; + p_node = p_node->p_next; + cdf_mem_free(p_prev); + } + } + + spin_unlock_irqrestore(&g_cdf_net_buf_track_lock, irq_flag); + + return; +} + +/** + * cdf_net_buf_debug_hash() - hash network buffer pointer + * + * Return: hash value + */ +uint32_t cdf_net_buf_debug_hash(cdf_nbuf_t net_buf) +{ + uint32_t i; + + i = (uint32_t) ((uintptr_t) net_buf & (CDF_NET_BUF_TRACK_MAX_SIZE - 1)); + + return i; +} + +/** + * cdf_net_buf_debug_look_up() - look up network buffer in debug hash table + * + * Return: If skb is found in hash table then return pointer to network buffer + * else return %NULL + */ +CDF_NBUF_TRACK *cdf_net_buf_debug_look_up(cdf_nbuf_t net_buf) +{ + uint32_t i; + CDF_NBUF_TRACK *p_node; + + i = cdf_net_buf_debug_hash(net_buf); + p_node = gp_cdf_net_buf_track_tbl[i]; + + while (p_node) { + if (p_node->net_buf == net_buf) + return p_node; + p_node = p_node->p_next; + } + + return NULL; + +} + +/** + * cdf_net_buf_debug_add_node() - store skb in debug hash table + * + * Return: none + */ +void cdf_net_buf_debug_add_node(cdf_nbuf_t net_buf, size_t size, + uint8_t *file_name, uint32_t line_num) +{ + uint32_t i; + unsigned long irq_flag; + CDF_NBUF_TRACK *p_node; + + spin_lock_irqsave(&g_cdf_net_buf_track_lock, irq_flag); + + i = cdf_net_buf_debug_hash(net_buf); + p_node = cdf_net_buf_debug_look_up(net_buf); + + if (p_node) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Double allocation of skb ! Already allocated from %s %d", + p_node->file_name, p_node->line_num); + CDF_ASSERT(0); + goto done; + } else { + p_node = (CDF_NBUF_TRACK *) cdf_mem_malloc(sizeof(*p_node)); + if (p_node) { + p_node->net_buf = net_buf; + p_node->file_name = file_name; + p_node->line_num = line_num; + p_node->size = size; + p_node->p_next = gp_cdf_net_buf_track_tbl[i]; + gp_cdf_net_buf_track_tbl[i] = p_node; + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Mem alloc failed ! Could not track skb from %s %d of size %zu", + file_name, line_num, size); + CDF_ASSERT(0); + } + } + +done: + spin_unlock_irqrestore(&g_cdf_net_buf_track_lock, irq_flag); + + return; +} + +/** + * cdf_net_buf_debug_delete_node() - remove skb from debug hash table + * + * Return: none + */ +void cdf_net_buf_debug_delete_node(cdf_nbuf_t net_buf) +{ + uint32_t i; + bool found = false; + CDF_NBUF_TRACK *p_head; + CDF_NBUF_TRACK *p_node; + unsigned long irq_flag; + CDF_NBUF_TRACK *p_prev; + + spin_lock_irqsave(&g_cdf_net_buf_track_lock, irq_flag); + + i = cdf_net_buf_debug_hash(net_buf); + p_head = gp_cdf_net_buf_track_tbl[i]; + + /* Unallocated SKB */ + if (!p_head) + goto done; + + p_node = p_head; + /* Found at head of the table */ + if (p_head->net_buf == net_buf) { + gp_cdf_net_buf_track_tbl[i] = p_node->p_next; + cdf_mem_free((void *)p_node); + found = true; + goto done; + } + + /* Search in collision list */ + while (p_node) { + p_prev = p_node; + p_node = p_node->p_next; + if ((NULL != p_node) && (p_node->net_buf == net_buf)) { + p_prev->p_next = p_node->p_next; + cdf_mem_free((void *)p_node); + found = true; + break; + } + } + +done: + if (!found) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Unallocated buffer ! Double free of net_buf %p ?", + net_buf); + CDF_ASSERT(0); + } + + spin_unlock_irqrestore(&g_cdf_net_buf_track_lock, irq_flag); + + return; +} + +/** + * cdf_net_buf_debug_release_skb() - release skb to avoid memory leak + * + * WLAN driver module whose allocated SKB is freed by network stack are + * suppose to call this API before returning SKB to network stack such + * that the SKB is not reported as memory leak. + * + * Return: none + */ +void cdf_net_buf_debug_release_skb(cdf_nbuf_t net_buf) +{ + cdf_net_buf_debug_delete_node(net_buf); +} + +#endif /*MEMORY_DEBUG */ +#if defined(FEATURE_TSO) + +struct cdf_tso_cmn_seg_info_t { + uint16_t ethproto; + uint16_t ip_tcp_hdr_len; + uint16_t l2_len; + unsigned char *eit_hdr; + unsigned int eit_hdr_len; + struct tcphdr *tcphdr; + uint16_t ipv4_csum_en; + uint16_t tcp_ipv4_csum_en; + uint16_t tcp_ipv6_csum_en; + uint16_t ip_id; + uint32_t tcp_seq_num; +}; + +/** + * __cdf_nbuf_get_tso_cmn_seg_info() - get TSO common + * information + * + * Get the TSO information that is common across all the TCP + * segments of the jumbo packet + * + * Return: 0 - success 1 - failure + */ +uint8_t __cdf_nbuf_get_tso_cmn_seg_info(struct sk_buff *skb, + struct cdf_tso_cmn_seg_info_t *tso_info) +{ + /* Get ethernet type and ethernet header length */ + tso_info->ethproto = vlan_get_protocol(skb); + + /* Determine whether this is an IPv4 or IPv6 packet */ + if (tso_info->ethproto == htons(ETH_P_IP)) { /* IPv4 */ + /* for IPv4, get the IP ID and enable TCP and IP csum */ + struct iphdr *ipv4_hdr = ip_hdr(skb); + tso_info->ip_id = ntohs(ipv4_hdr->id); + tso_info->ipv4_csum_en = 1; + tso_info->tcp_ipv4_csum_en = 1; + if (cdf_unlikely(ipv4_hdr->protocol != IPPROTO_TCP)) { + cdf_print("TSO IPV4 proto 0x%x not TCP\n", + ipv4_hdr->protocol); + return 1; + } + } else if (tso_info->ethproto == htons(ETH_P_IPV6)) { /* IPv6 */ + /* for IPv6, enable TCP csum. No IP ID or IP csum */ + tso_info->tcp_ipv6_csum_en = 1; + } else { + cdf_print("TSO: ethertype 0x%x is not supported!\n", + tso_info->ethproto); + return 1; + } + + tso_info->l2_len = (skb_network_header(skb) - skb_mac_header(skb)); + tso_info->tcphdr = tcp_hdr(skb); + tso_info->tcp_seq_num = ntohl(tcp_hdr(skb)->seq); + /* get pointer to the ethernet + IP + TCP header and their length */ + tso_info->eit_hdr = skb->data; + tso_info->eit_hdr_len = (skb_transport_header(skb) + - skb_mac_header(skb)) + tcp_hdrlen(skb); + tso_info->ip_tcp_hdr_len = tso_info->eit_hdr_len - tso_info->l2_len; + return 0; +} + +/** + * __cdf_nbuf_get_tso_info() - function to divide a TSO nbuf + * into segments + * @nbuf: network buffer to be segmented + * @tso_info: This is the output. The information about the + * TSO segments will be populated within this. + * + * This function fragments a TCP jumbo packet into smaller + * segments to be transmitted by the driver. It chains the TSO + * segments created into a list. + * + * Return: number of TSO segments + */ +uint32_t __cdf_nbuf_get_tso_info(cdf_device_t osdev, struct sk_buff *skb, + struct cdf_tso_info_t *tso_info) +{ + /* common accross all segments */ + struct cdf_tso_cmn_seg_info_t tso_cmn_info; + + /* segment specific */ + char *tso_frag_vaddr; + uint32_t tso_frag_paddr_32 = 0; + uint32_t num_seg = 0; + struct cdf_tso_seg_elem_t *curr_seg; + const struct skb_frag_struct *frag = NULL; + uint32_t tso_frag_len = 0; /* tso segment's fragment length*/ + uint32_t skb_frag_len = 0; /* skb's fragment length (continous memory)*/ + uint32_t foffset = 0; /* offset into the skb's fragment */ + uint32_t skb_proc = 0; /* bytes of the skb that have been processed*/ + uint32_t tso_seg_size = skb_shinfo(skb)->gso_size; + + memset(&tso_cmn_info, 0x0, sizeof(tso_cmn_info)); + + if (cdf_unlikely(__cdf_nbuf_get_tso_cmn_seg_info(skb, &tso_cmn_info))) { + cdf_print("TSO: error getting common segment info\n"); + return 0; + } + curr_seg = tso_info->tso_seg_list; + + /* length of the first chunk of data in the skb */ + skb_proc = skb_frag_len = skb->len - skb->data_len; + + /* the 0th tso segment's 0th fragment always contains the EIT header */ + /* update the remaining skb fragment length and TSO segment length */ + skb_frag_len -= tso_cmn_info.eit_hdr_len; + skb_proc -= tso_cmn_info.eit_hdr_len; + + /* get the address to the next tso fragment */ + tso_frag_vaddr = skb->data + tso_cmn_info.eit_hdr_len; + /* get the length of the next tso fragment */ + tso_frag_len = min(skb_frag_len, tso_seg_size); + tso_frag_paddr_32 = dma_map_single(osdev->dev, + tso_frag_vaddr, tso_frag_len, DMA_TO_DEVICE); + + num_seg = tso_info->num_segs; + tso_info->num_segs = 0; + tso_info->is_tso = 1; + + while (num_seg && curr_seg) { + int i = 1; /* tso fragment index */ + int j = 0; /* skb fragment index */ + uint8_t more_tso_frags = 1; + uint8_t from_frag_table = 0; + + /* Initialize the flags to 0 */ + memset(&curr_seg->seg, 0x0, sizeof(curr_seg->seg)); + tso_info->num_segs++; + + /* The following fields remain the same across all segments of + a jumbo packet */ + curr_seg->seg.tso_flags.tso_enable = 1; + curr_seg->seg.tso_flags.partial_checksum_en = 0; + curr_seg->seg.tso_flags.ipv4_checksum_en = + tso_cmn_info.ipv4_csum_en; + curr_seg->seg.tso_flags.tcp_ipv6_checksum_en = + tso_cmn_info.tcp_ipv6_csum_en; + curr_seg->seg.tso_flags.tcp_ipv4_checksum_en = + tso_cmn_info.tcp_ipv4_csum_en; + curr_seg->seg.tso_flags.l2_len = 0; + curr_seg->seg.tso_flags.tcp_flags_mask = 0x1FF; + curr_seg->seg.num_frags = 0; + + /* The following fields change for the segments */ + curr_seg->seg.tso_flags.ip_id = tso_cmn_info.ip_id; + tso_cmn_info.ip_id++; + + curr_seg->seg.tso_flags.syn = tso_cmn_info.tcphdr->syn; + curr_seg->seg.tso_flags.rst = tso_cmn_info.tcphdr->rst; + curr_seg->seg.tso_flags.psh = tso_cmn_info.tcphdr->psh; + curr_seg->seg.tso_flags.ack = tso_cmn_info.tcphdr->ack; + curr_seg->seg.tso_flags.urg = tso_cmn_info.tcphdr->urg; + curr_seg->seg.tso_flags.ece = tso_cmn_info.tcphdr->ece; + curr_seg->seg.tso_flags.cwr = tso_cmn_info.tcphdr->cwr; + + curr_seg->seg.tso_flags.tcp_seq_num = tso_cmn_info.tcp_seq_num; + + /* First fragment for each segment always contains the ethernet, + IP and TCP header */ + curr_seg->seg.tso_frags[0].vaddr = tso_cmn_info.eit_hdr; + curr_seg->seg.tso_frags[0].length = tso_cmn_info.eit_hdr_len; + tso_info->total_len = curr_seg->seg.tso_frags[0].length; + curr_seg->seg.tso_frags[0].paddr_low_32 = + dma_map_single(osdev->dev, tso_cmn_info.eit_hdr, + tso_cmn_info.eit_hdr_len, DMA_TO_DEVICE); + curr_seg->seg.tso_flags.ip_len = tso_cmn_info.ip_tcp_hdr_len; + curr_seg->seg.num_frags++; + + while (more_tso_frags) { + curr_seg->seg.tso_frags[i].vaddr = tso_frag_vaddr; + curr_seg->seg.tso_frags[i].length = tso_frag_len; + tso_info->total_len += + curr_seg->seg.tso_frags[i].length; + curr_seg->seg.tso_flags.ip_len += + curr_seg->seg.tso_frags[i].length; + curr_seg->seg.num_frags++; + skb_proc = skb_proc - curr_seg->seg.tso_frags[i].length; + + /* increment the TCP sequence number */ + tso_cmn_info.tcp_seq_num += tso_frag_len; + curr_seg->seg.tso_frags[i].paddr_upper_16 = 0; + curr_seg->seg.tso_frags[i].paddr_low_32 = + tso_frag_paddr_32; + + /* if there is no more data left in the skb */ + if (!skb_proc) + return tso_info->num_segs; + + /* get the next payload fragment information */ + /* check if there are more fragments in this segment */ + if ((tso_seg_size - tso_frag_len)) { + more_tso_frags = 1; + i++; + } else { + more_tso_frags = 0; + /* reset i and the tso payload size */ + i = 1; + tso_seg_size = skb_shinfo(skb)->gso_size; + } + + /* if the next fragment is contiguous */ + if (tso_frag_len < skb_frag_len) { + skb_frag_len = skb_frag_len - tso_frag_len; + tso_frag_len = min(skb_frag_len, tso_seg_size); + tso_frag_vaddr = tso_frag_vaddr + tso_frag_len; + if (from_frag_table) { + tso_frag_paddr_32 = + skb_frag_dma_map(osdev->dev, + frag, foffset, + tso_frag_len, + DMA_TO_DEVICE); + } else { + tso_frag_paddr_32 = + dma_map_single(osdev->dev, + tso_frag_vaddr, + tso_frag_len, + DMA_TO_DEVICE); + } + } else { /* the next fragment is not contiguous */ + tso_frag_len = min(skb_frag_len, tso_seg_size); + frag = &skb_shinfo(skb)->frags[j]; + skb_frag_len = skb_frag_size(frag); + + tso_frag_vaddr = skb_frag_address(frag); + tso_frag_paddr_32 = skb_frag_dma_map(osdev->dev, + frag, 0, tso_frag_len, + DMA_TO_DEVICE); + foffset += tso_frag_len; + from_frag_table = 1; + j++; + } + } + num_seg--; + /* if TCP FIN flag was set, set it in the last segment */ + if (!num_seg) + curr_seg->seg.tso_flags.fin = tso_cmn_info.tcphdr->fin; + + curr_seg = curr_seg->next; + } + return tso_info->num_segs; +} + +/** + * __cdf_nbuf_get_tso_num_seg() - function to divide a TSO nbuf + * into segments + * @nbuf: network buffer to be segmented + * @tso_info: This is the output. The information about the + * TSO segments will be populated within this. + * + * This function fragments a TCP jumbo packet into smaller + * segments to be transmitted by the driver. It chains the TSO + * segments created into a list. + * + * Return: 0 - success, 1 - failure + */ +uint32_t __cdf_nbuf_get_tso_num_seg(struct sk_buff *skb) +{ + uint32_t gso_size, tmp_len, num_segs = 0; + + gso_size = skb_shinfo(skb)->gso_size; + tmp_len = skb->len - ((skb_transport_header(skb) - skb_mac_header(skb)) + + tcp_hdrlen(skb)); + while (tmp_len) { + num_segs++; + if (tmp_len > gso_size) + tmp_len -= gso_size; + else + break; + } + return num_segs; +} + +struct sk_buff *__cdf_nbuf_inc_users(struct sk_buff *skb) +{ + atomic_inc(&skb->users); + return skb; +} + +#endif /* FEATURE_TSO */ diff --git a/core/cdf/src/cdf_threads.c b/core/cdf/src/cdf_threads.c new file mode 100644 index 000000000000..6b408d567850 --- /dev/null +++ b/core/cdf/src/cdf_threads.c @@ -0,0 +1,107 @@ +/* + * 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. + */ + +/** + * DOC: cdf_threads + * + * Connectivity driver framework (CDF) thread APIs + * + */ + +/* Include Files */ +#include +#include +#include +#include +#include +#include + +/* Preprocessor definitions and constants */ + +/* Type declarations */ + +/* Function declarations and documenation */ + +/** + * cdf_sleep() - sleep + * @msInterval : Number of milliseconds to suspend the current thread. + * A value of 0 may or may not cause the current thread to yield. + * + * This function suspends the execution of the current thread + * until the specified time out interval elapses. + * + * Return: nothing + */ +void cdf_sleep(uint32_t msInterval) +{ + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + return; + } + msleep_interruptible(msInterval); +} + +/** + * cdf_sleep_us() - sleep + * @usInterval : Number of microseconds to suspend the current thread. + * A value of 0 may or may not cause the current thread to yield. + * + * This function suspends the execution of the current thread + * until the specified time out interval elapses. + * + * Return : nothing + */ +void cdf_sleep_us(uint32_t usInterval) +{ + unsigned long timeout = usecs_to_jiffies(usInterval) + 1; + if (in_interrupt()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s cannot be called from interrupt context!!!", + __func__); + return; + } + + while (timeout && !signal_pending(current)) + timeout = schedule_timeout_interruptible(timeout); +} + +/** + * cdf_busy_wait() - busy wait + * @usInterval : Number of microseconds to busy wait. + * + * This 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. + * + * Return : nothing + */ +void cdf_busy_wait(uint32_t usInterval) +{ + udelay(usInterval); +} diff --git a/core/cdf/src/cdf_trace.c b/core/cdf/src/cdf_trace.c new file mode 100644 index 000000000000..3d59c53d272f --- /dev/null +++ b/core/cdf/src/cdf_trace.c @@ -0,0 +1,1018 @@ +/* + * 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. + */ + +/** + * DOC: cdf_trace + * + * Connectivity driver framework (CDF) trace APIs + * + * Trace, logging, and debugging definitions and APIs + * + */ + +/* Include Files */ +#include +#include +#include +#include "cdf_time.h" +/* Preprocessor definitions and constants */ + +#define CDF_TRACE_BUFFER_SIZE (512) + +/* macro to map cdf trace levels into the bitmask */ +#define CDF_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 CDF_TRACE_LEVEL. For example, each bit represents + * one of the bits in CDF_TRACE_LEVEL that may be turned on to have + * traces at that level logged, i.e. if CDF_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 + */ + uint16_t moduleTraceLevel; + + /* 3 character string name for the module */ + unsigned char moduleNameStr[4]; /* 3 chars plus the NULL */ +} moduleTraceInfo; + +#define CDF_DEFAULT_TRACE_LEVEL \ + ((1 << CDF_TRACE_LEVEL_FATAL) | (1 << CDF_TRACE_LEVEL_ERROR)) + +/* Array of static data that contains all of the per module trace + * information. This includes the trace level for the module and + * the 3 character 'name' of the module for marking the trace logs + */ +moduleTraceInfo g_cdf_trace_info[CDF_MODULE_ID_MAX] = { + [CDF_MODULE_ID_TLSHIM] = {CDF_DEFAULT_TRACE_LEVEL, "DP"}, + [CDF_MODULE_ID_WMI] = {CDF_DEFAULT_TRACE_LEVEL, "WMI"}, + [CDF_MODULE_ID_HDD] = {CDF_DEFAULT_TRACE_LEVEL, "HDD"}, + [CDF_MODULE_ID_SME] = {CDF_DEFAULT_TRACE_LEVEL, "SME"}, + [CDF_MODULE_ID_PE] = {CDF_DEFAULT_TRACE_LEVEL, "PE "}, + [CDF_MODULE_ID_WMA] = {CDF_DEFAULT_TRACE_LEVEL, "WMA"}, + [CDF_MODULE_ID_SYS] = {CDF_DEFAULT_TRACE_LEVEL, "SYS"}, + [CDF_MODULE_ID_CDF] = {CDF_DEFAULT_TRACE_LEVEL, "CDF"}, + [CDF_MODULE_ID_SAP] = {CDF_DEFAULT_TRACE_LEVEL, "SAP"}, + [CDF_MODULE_ID_HDD_SOFTAP] = {CDF_DEFAULT_TRACE_LEVEL, "HSP"}, + [CDF_MODULE_ID_HDD_DATA] = {CDF_DEFAULT_TRACE_LEVEL, "HDP"}, + [CDF_MODULE_ID_HDD_SAP_DATA] = {CDF_DEFAULT_TRACE_LEVEL, "SDP"}, + [CDF_MODULE_ID_BMI] = {CDF_DEFAULT_TRACE_LEVEL, "BMI"}, + [CDF_MODULE_ID_HIF] = {CDF_DEFAULT_TRACE_LEVEL, "HIF"}, + [CDF_MODULE_ID_TXRX] = {CDF_DEFAULT_TRACE_LEVEL, "TRX"}, + [CDF_MODULE_ID_HTT] = {CDF_DEFAULT_TRACE_LEVEL, "HTT"}, +}; + +/* Static and Global variables */ +static spinlock_t ltrace_lock; + +static cdf_trace_record_t g_cdf_trace_tbl[MAX_CDF_TRACE_RECORDS]; +/* global cdf trace data */ +static t_cdf_trace_data g_cdf_trace_data; +/* + * all the call back functions for dumping MTRACE messages from ring buffer + * are stored in cdf_trace_cb_table,these callbacks are initialized during init + * only so, we will make a copy of these call back functions and maintain in to + * cdf_trace_restore_cb_table. Incase if we make modifications to + * cdf_trace_cb_table, we can certainly retrieve all the call back functions + * back from Restore Table + */ +static tp_cdf_trace_cb cdf_trace_cb_table[CDF_MODULE_ID_MAX]; +static tp_cdf_trace_cb cdf_trace_restore_cb_table[CDF_MODULE_ID_MAX]; + +/* Static and Global variables */ +static spinlock_t l_dp_trace_lock; + +static struct cdf_dp_trace_record_s + g_cdf_dp_trace_tbl[MAX_CDF_DP_TRACE_RECORDS]; + +/* + * all the options to configure/control DP trace are + * defined in this structure + */ +static struct s_cdf_dp_trace_data g_cdf_dp_trace_data; +/* + * all the call back functions for dumping DPTRACE messages from ring buffer + * are stored in cdf_dp_trace_cb_table, callbacks are initialized during init + */ +static tp_cdf_dp_trace_cb cdf_dp_trace_cb_table[CDF_DP_TRACE_MAX]; + +/** + * cdf_trace_set_level() - Set the trace level for a particular module + * @level : trace level + * + * Trace level is a member of the CDF_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. + * + * This is an external API that allows trace levels to be set for each module. + * + * Return: nothing + */ +void cdf_trace_set_level(CDF_MODULE_ID module, CDF_TRACE_LEVEL level) +{ + /* make sure the caller is passing in a valid LEVEL */ + if (level >= CDF_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 (CDF_TRACE_LEVEL_NONE == level) + g_cdf_trace_info[module].moduleTraceLevel = + CDF_TRACE_LEVEL_NONE; + else + /* set the desired bit in the bit mask for the module trace + * level */ + g_cdf_trace_info[module].moduleTraceLevel |= + CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); +} + +/** + * cdf_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 cdf_trace_set_module_trace_level(CDF_MODULE_ID module, uint32_t level) +{ + if (module < 0 || module >= CDF_MODULE_ID_MAX) { + pr_err("%s: Invalid module id %d passed\n", __func__, module); + return; + } + g_cdf_trace_info[module].moduleTraceLevel = level; +} + +void cdf_trace_set_value(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + uint8_t on) +{ + /* make sure the caller is passing in a valid LEVEL */ + if (level < 0 || level >= CDF_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 >= CDF_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 (CDF_TRACE_LEVEL_NONE == level) { + g_cdf_trace_info[module].moduleTraceLevel = + CDF_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 (CDF_TRACE_LEVEL_ALL == level) { + g_cdf_trace_info[module].moduleTraceLevel = 0xFFFF; + } else { + if (on) + /* set the desired bit in the bit mask for the module + trace level */ + g_cdf_trace_info[module].moduleTraceLevel |= + CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); + else + /* clear the desired bit in the bit mask for the module + trace level */ + g_cdf_trace_info[module].moduleTraceLevel &= + ~(CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level)); + } +} + +/** + * cdf_trace_get_level() - get the trace level + * @level : trace level + * + * This is an external API that returns a bool value to signify if a + * particular trace level is set for the specified module. + * A member of the CDF_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. CDF_TRACE_LEVEL_NONE and CDF_TRACE_LEVEL_ALL + * are not valid input and will return false + * + * Return: + * false - the specified trace level for the specified module is OFF + * true - the specified trace level for the specified module is ON + */ +bool cdf_trace_get_level(CDF_MODULE_ID module, CDF_TRACE_LEVEL level) +{ + bool traceOn = false; + + if ((CDF_TRACE_LEVEL_NONE == level) || + (CDF_TRACE_LEVEL_ALL == level) || (level >= CDF_TRACE_LEVEL_MAX)) { + traceOn = false; + } else { + traceOn = (level & g_cdf_trace_info[module].moduleTraceLevel) + ? true : false; + } + + return traceOn; +} + +void cdf_snprintf(char *strBuffer, unsigned int size, char *strFormat, ...) +{ + va_list val; + + va_start(val, strFormat); + snprintf(strBuffer, size, strFormat, val); + va_end(val); +} + +#ifdef CDF_ENABLE_TRACING + +/** + * cdf_trace_msg() - externally called trace function + * @module : Module identifier a member of the CDF_MODULE_ID + * enumeration that identifies the module issuing the trace message. + * @level : Trace level a member of the CDF_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. + * @strFormat : Format string in which the message to be logged. This format + * string contains printf-like replacement parameters, which follow + * this parameter in the variable argument list. + * + * Checks the level of severity and accordingly prints the trace messages + * + * Return: nothing + * + */ +void cdf_trace_msg(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + char *strFormat, ...) +{ + char strBuffer[CDF_TRACE_BUFFER_SIZE]; + int n; + + /* Print the trace message when the desired level bit is set in + the module tracel level mask */ + if (g_cdf_trace_info[module].moduleTraceLevel & + CDF_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 CDF_TRACE_LEVEL) so we can index into this array with + * the level and get the right string. The cdf 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, CDF_TRACE_BUFFER_SIZE, + "wlan: [%d:%2s:%3s] ", + in_interrupt() ? 0 : current->pid, + (char *)TRACE_LEVEL_STR[level], + (char *)g_cdf_trace_info[module].moduleNameStr); + + /* print the formatted log message after the prefix string */ + if ((n >= 0) && (n < CDF_TRACE_BUFFER_SIZE)) { + vsnprintf(strBuffer + n, CDF_TRACE_BUFFER_SIZE - n, + strFormat, val); +#if defined(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 cdf_trace_display(void) +{ + CDF_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 < CDF_MODULE_ID_MAX; ++moduleId) { + pr_err + ("%2d)%s %s %s %s %s %s %s %s %s\n", + (int)moduleId, g_cdf_trace_info[moduleId].moduleNameStr, + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_FATAL)) ? "X" : + " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_ERROR)) ? "X" : + " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_WARN)) ? "X" : + " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_INFO)) ? "X" : + " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_INFO_HIGH)) ? "X" + : " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_INFO_MED)) ? "X" + : " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_INFO_LOW)) ? "X" + : " ", + (g_cdf_trace_info[moduleId]. + moduleTraceLevel & (1 << CDF_TRACE_LEVEL_DEBUG)) ? "X" : + " "); + } +} + +/** + * cdf_trace_hex_dump() - externally called hex dump function + * @module : Module identifier a member of the CDF_MODULE_ID enumeration that + * identifies the module issuing the trace message. + * @level : Trace level a member of the CDF_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. + * @data : The base address of the buffer to be logged. + * @buf_len : The size of the buffer to be logged. + * + * Checks the level of severity and accordingly prints the trace messages + * + * Return : nothing + */ +void cdf_trace_hex_dump(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + void *data, int buf_len) +{ + char *buf = (char *)data; + int i; + + if (!(g_cdf_trace_info[module].moduleTraceLevel & + CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level))) + return; + + for (i = 0; (i + 15) < buf_len; i += 16) { + cdf_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++) + cdf_trace_msg(module, level, "%02x ", buf[i]); +} + +#endif + +/** + * cdf_trace_enable() - Enable MTRACE for specific modules + * @bitmask_of_moduleId : Bitmask according to enum of the modules. + * 32 [dec] = 0010 0000 [bin] + * 64 [dec] = 0100 0000 [bin] + * 128 [dec] = 1000 0000 [bin] + * @enable : can be true or false true implies enabling MTRACE false implies + * disabling MTRACE. + * + * 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. + * + * + * Return : nothing + */ +void cdf_trace_enable(uint32_t bitmask_of_moduleId, uint8_t enable) +{ + int i; + if (bitmask_of_moduleId) { + for (i = 0; i < CDF_MODULE_ID_MAX; i++) { + if (((bitmask_of_moduleId >> i) & 1)) { + if (enable) { + if (NULL != + cdf_trace_restore_cb_table[i]) { + cdf_trace_cb_table[i] = + cdf_trace_restore_cb_table[i]; + } + } else { + cdf_trace_restore_cb_table[i] = + cdf_trace_cb_table[i]; + cdf_trace_cb_table[i] = NULL; + } + } + } + } else { + if (enable) { + for (i = 0; i < CDF_MODULE_ID_MAX; i++) { + if (NULL != cdf_trace_restore_cb_table[i]) { + cdf_trace_cb_table[i] = + cdf_trace_restore_cb_table[i]; + } + } + } else { + for (i = 0; i < CDF_MODULE_ID_MAX; i++) { + cdf_trace_restore_cb_table[i] = + cdf_trace_cb_table[i]; + cdf_trace_cb_table[i] = NULL; + } + } + } +} + +/** + * cdf_trace_init() - initializes cdf trace structures and variables + * + * Called immediately after cds_preopen, so that we can start recording HDD + * events ASAP. + * + * Return : nothing + */ +void cdf_trace_init(void) +{ + uint8_t i; + g_cdf_trace_data.head = INVALID_CDF_TRACE_ADDR; + g_cdf_trace_data.tail = INVALID_CDF_TRACE_ADDR; + g_cdf_trace_data.num = 0; + g_cdf_trace_data.enable = true; + g_cdf_trace_data.dumpCount = DEFAULT_CDF_TRACE_DUMP_COUNT; + g_cdf_trace_data.numSinceLastDump = 0; + + for (i = 0; i < CDF_MODULE_ID_MAX; i++) { + cdf_trace_cb_table[i] = NULL; + cdf_trace_restore_cb_table[i] = NULL; + } +} + +/** + * cdf_trace() - puts the messages in to ring-buffer + * @module : Enum of module, basically module id. + * @param : Code to be recorded + * @session : Session ID of the log + * @data : Actual message contents + * + * This function will be called from each module who wants record the messages + * in circular queue. Before calling this functions make sure you have + * registered your module with cdf through cdf_trace_register function. + * + * + * Return : nothing + */ +void cdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data) +{ + tp_cdf_trace_record rec = NULL; + unsigned long flags; + + if (!g_cdf_trace_data.enable) + return; + + /* if module is not registered, don't record for that module */ + if (NULL == cdf_trace_cb_table[module]) + return; + + /* Aquire the lock so that only one thread at a time can fill the ring + * buffer + */ + spin_lock_irqsave(<race_lock, flags); + + g_cdf_trace_data.num++; + + if (g_cdf_trace_data.num > MAX_CDF_TRACE_RECORDS) + g_cdf_trace_data.num = MAX_CDF_TRACE_RECORDS; + + if (INVALID_CDF_TRACE_ADDR == g_cdf_trace_data.head) { + /* first record */ + g_cdf_trace_data.head = 0; + g_cdf_trace_data.tail = 0; + } else { + /* queue is not empty */ + uint32_t tail = g_cdf_trace_data.tail + 1; + + if (MAX_CDF_TRACE_RECORDS == tail) + tail = 0; + + if (g_cdf_trace_data.head == tail) { + /* full */ + if (MAX_CDF_TRACE_RECORDS == ++g_cdf_trace_data.head) + g_cdf_trace_data.head = 0; + } + g_cdf_trace_data.tail = tail; + } + + rec = &g_cdf_trace_tbl[g_cdf_trace_data.tail]; + rec->code = code; + rec->session = session; + rec->data = data; + rec->time = cdf_get_log_timestamp(); + rec->module = module; + rec->pid = (in_interrupt() ? 0 : current->pid); + g_cdf_trace_data.numSinceLastDump++; + spin_unlock_irqrestore(<race_lock, flags); +} + +/** + * cdf_trace_spin_lock_init() - initializes the lock variable before use + * + * This function will be called from cds_alloc_global_context, we will have lock + * available to use ASAP + * + * Return : nothing + */ +CDF_STATUS cdf_trace_spin_lock_init(void) +{ + spin_lock_init(<race_lock); + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_trace_register() - registers the call back functions + * @moduleID - enum value of module + * @cdf_trace_callback - call back functions to display the messages in + * particular format. + * + * 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. + * + * Return : nothing + */ +void cdf_trace_register(CDF_MODULE_ID moduleID, + tp_cdf_trace_cb cdf_trace_callback) +{ + cdf_trace_cb_table[moduleID] = cdf_trace_callback; +} + +/** + * cdf_trace_dump_all() - Dump data from ring buffer via call back functions + * registered with CDF + * @pMac : Context of particular module + * @code : Reason code + * @session : Session id of log + * @count : Number of lines to dump starting from tail to head + * + * 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. + * + * Return : nothing + */ +void cdf_trace_dump_all(void *pMac, uint8_t code, uint8_t session, + uint32_t count, uint32_t bitmask_of_module) +{ + cdf_trace_record_t pRecord; + int32_t i, tail; + + if (!g_cdf_trace_data.enable) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, "Tracing Disabled"); + return; + } + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Total Records: %d, Head: %d, Tail: %d", + g_cdf_trace_data.num, g_cdf_trace_data.head, + g_cdf_trace_data.tail); + + /* aquire the lock so that only one thread at a time can read + * the ring buffer + */ + spin_lock(<race_lock); + + if (g_cdf_trace_data.head != INVALID_CDF_TRACE_ADDR) { + i = g_cdf_trace_data.head; + tail = g_cdf_trace_data.tail; + + if (count) { + if (count > g_cdf_trace_data.num) + count = g_cdf_trace_data.num; + if (tail >= (count - 1)) + i = tail - count + 1; + else if (count != MAX_CDF_TRACE_RECORDS) + i = MAX_CDF_TRACE_RECORDS - ((count - 1) - + tail); + } + + pRecord = g_cdf_trace_tbl[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 + */ + g_cdf_trace_data.numSinceLastDump = 0; + spin_unlock(<race_lock); + for (;; ) { + if ((code == 0 || (code == pRecord.code)) && + (cdf_trace_cb_table[pRecord.module] != NULL)) { + if (0 == bitmask_of_module) { + cdf_trace_cb_table[pRecord. + module] (pMac, + &pRecord, + (uint16_t) + i); + } else { + if (bitmask_of_module & + (1 << pRecord.module)) { + cdf_trace_cb_table[pRecord. + module] + (pMac, &pRecord, + (uint16_t) i); + } + } + } + + if (i == tail) + break; + i += 1; + + spin_lock(<race_lock); + if (MAX_CDF_TRACE_RECORDS == i) { + i = 0; + pRecord = g_cdf_trace_tbl[0]; + } else { + pRecord = g_cdf_trace_tbl[i]; + } + spin_unlock(<race_lock); + } + } else { + spin_unlock(<race_lock); + } +} + +/** + * cdf_dp_trace_init() - enables the DP trace + * Called during driver load and it enables DP trace + * + * Return: None + */ +void cdf_dp_trace_init(void) +{ + uint8_t i; + + cdf_dp_trace_spin_lock_init(); + g_cdf_dp_trace_data.head = INVALID_CDF_DP_TRACE_ADDR; + g_cdf_dp_trace_data.tail = INVALID_CDF_DP_TRACE_ADDR; + g_cdf_dp_trace_data.num = 0; + g_cdf_dp_trace_data.proto_bitmap = 0; + g_cdf_dp_trace_data.no_of_record = 0; + g_cdf_dp_trace_data.verbosity = CDF_DP_TRACE_VERBOSITY_DEFAULT; + g_cdf_dp_trace_data.enable = true; + + for (i = 0; i < CDF_DP_TRACE_MAX; i++) + cdf_dp_trace_cb_table[i] = cdf_dp_display_record; +} + +/** + * cdf_dp_trace_set_value() - Configure the value to control DP trace + * @proto_bitmap : defines the protocol to be tracked + * @no_of_records : defines the nth packet which is traced + * @verbosity : defines the verbosity level + * + * Return: None + */ +void cdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record, + uint8_t verbosity) +{ + g_cdf_dp_trace_data.proto_bitmap = proto_bitmap; + g_cdf_dp_trace_data.no_of_record = no_of_record; + g_cdf_dp_trace_data.verbosity = verbosity; + return; +} + +/** + * cdf_dp_trace_enable_track() - enable the tracing for netbuf + * @code : defines the event + * + * Return: true or false depends on whether tracing enabled + */ +static bool cdf_dp_trace_enable_track(enum CDF_DP_TRACE_ID code) +{ + if (g_cdf_dp_trace_data.verbosity == CDF_DP_TRACE_VERBOSITY_HIGH) + return true; + if (g_cdf_dp_trace_data.verbosity == CDF_DP_TRACE_VERBOSITY_MEDIUM + && (code <= CDF_DP_TRACE_HIF_PACKET_PTR_RECORD)) + return true; + if (g_cdf_dp_trace_data.verbosity == CDF_DP_TRACE_VERBOSITY_LOW + && (code <= CDF_DP_TRACE_CE_PACKET_RECORD)) + return true; + if (g_cdf_dp_trace_data.verbosity == CDF_DP_TRACE_VERBOSITY_DEFAULT + && (code == CDF_DP_TRACE_DROP_PACKET_RECORD)) + return true; + return false; +} + +/** + * cdf_dp_trace_set_track() - Marks whether the packet needs to be traced + * @nbuf : defines the netbuf + * + * Return: None + */ +void cdf_dp_trace_set_track(cdf_nbuf_t nbuf) +{ + spin_lock_bh(&l_dp_trace_lock); + g_cdf_dp_trace_data.count++; + if (g_cdf_dp_trace_data.proto_bitmap != 0) { + if (cds_pkt_get_proto_type(nbuf, + g_cdf_dp_trace_data.proto_bitmap, 0)) { + CDF_NBUF_SET_DP_TRACE(nbuf, 1); + } + } + if ((g_cdf_dp_trace_data.no_of_record != 0) && + (g_cdf_dp_trace_data.count % + g_cdf_dp_trace_data.no_of_record == 0)) { + CDF_NBUF_SET_DP_TRACE(nbuf, 1); + } + spin_unlock_bh(&l_dp_trace_lock); + return; +} + +/** + * dump_hex_trace() - Display the data in buffer + * @buf: buffer which contains data to be displayed + * @buf_len: defines the size of the data to be displayed + * + * Return: None + */ +static void dump_hex_trace(uint8_t *buf, uint8_t buf_len) +{ + uint8_t i = 0; + /* Dump the bytes in the last line */ + cdf_print("DATA: "); + for (i = 0; i < buf_len; i++) + cdf_print("%02x ", buf[i]); + cdf_print("\n"); +} + +/** + * cdf_dp_display_trace() - Displays a record in DP trace + * @pRecord : pointer to a record in DP trace + * @recIndex : record index + * + * Return: None + */ +void cdf_dp_display_record(struct cdf_dp_trace_record_s *pRecord , + uint16_t recIndex) +{ + cdf_print("INDEX: %04d TIME: %012llu CODE: %02d\n", recIndex, + pRecord->time, pRecord->code); + switch (pRecord->code) { + case CDF_DP_TRACE_HDD_TX_TIMEOUT: + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "HDD TX Timeout\n"); + break; + case CDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "HDD SoftAP TX Timeout\n"); + break; + case CDF_DP_TRACE_VDEV_PAUSE: + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "VDEV Pause\n"); + break; + case CDF_DP_TRACE_VDEV_UNPAUSE: + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "VDEV UnPause\n"); + break; + default: + dump_hex_trace(pRecord->data, pRecord->size); + } + return; +} + +/** + * cdf_dp_trace() - Stores the data in buffer + * @nbuf : defines the netbuf + * @code : defines the event + * @data : defines the data to be stored + * @size : defines the size of the data record + * + * Return: None + */ +void cdf_dp_trace(cdf_nbuf_t nbuf, enum CDF_DP_TRACE_ID code, + uint8_t *data, uint8_t size) +{ + struct cdf_dp_trace_record_s *rec = NULL; + + /* Return when Dp trace is not enabled */ + if (!g_cdf_dp_trace_data.enable) + return; + + /* If nbuf is NULL, check for VDEV PAUSE, UNPAUSE, TIMEOUT */ + if (!nbuf) { + switch (code) { + case CDF_DP_TRACE_HDD_TX_TIMEOUT: + case CDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: + case CDF_DP_TRACE_VDEV_PAUSE: + case CDF_DP_TRACE_VDEV_UNPAUSE: + if (cdf_dp_trace_enable_track(code)) + goto register_record; + else + return; + + default: + return; + } + } + + /* Return when the packet is not a data packet */ + if (NBUF_GET_PACKET_TRACK(nbuf) != NBUF_TX_PKT_DATA_TRACK) + return; + + /* Return when nbuf is not marked for dp tracing or + * verbosity does not allow + */ + if (cdf_dp_trace_enable_track(code) == false || + !CDF_NBUF_GET_DP_TRACE(nbuf)) + return; + + /* Acquire the lock so that only one thread at a time can fill the ring + * buffer + */ + +register_record: + + spin_lock_bh(&l_dp_trace_lock); + + g_cdf_dp_trace_data.num++; + + if (g_cdf_dp_trace_data.num > MAX_CDF_DP_TRACE_RECORDS) + g_cdf_dp_trace_data.num = MAX_CDF_DP_TRACE_RECORDS; + + if (INVALID_CDF_DP_TRACE_ADDR == g_cdf_dp_trace_data.head) { + /* first record */ + g_cdf_dp_trace_data.head = 0; + g_cdf_dp_trace_data.tail = 0; + } else { + /* queue is not empty */ + g_cdf_dp_trace_data.tail++; + + if (MAX_CDF_DP_TRACE_RECORDS == g_cdf_dp_trace_data.tail) + g_cdf_dp_trace_data.tail = 0; + + if (g_cdf_dp_trace_data.head == g_cdf_dp_trace_data.tail) { + /* full */ + if (MAX_CDF_DP_TRACE_RECORDS == + ++g_cdf_dp_trace_data.head) + g_cdf_dp_trace_data.head = 0; + } + } + + rec = &g_cdf_dp_trace_tbl[g_cdf_dp_trace_data.tail]; + rec->code = code; + rec->size = 0; + if (data != NULL && size > 0) { + if (size > CDF_DP_TRACE_RECORD_SIZE) + size = CDF_DP_TRACE_RECORD_SIZE; + + rec->size = size; + switch (code) { + case CDF_DP_TRACE_HDD_PACKET_PTR_RECORD: + case CDF_DP_TRACE_CE_PACKET_PTR_RECORD: + case CDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD: + case CDF_DP_TRACE_TXRX_PACKET_PTR_RECORD: + case CDF_DP_TRACE_HTT_PACKET_PTR_RECORD: + case CDF_DP_TRACE_HTC_PACKET_PTR_RECORD: + case CDF_DP_TRACE_HIF_PACKET_PTR_RECORD: + cdf_mem_copy(rec->data, (uint8_t *)(&data), size); + break; + + case CDF_DP_TRACE_DROP_PACKET_RECORD: + case CDF_DP_TRACE_HDD_PACKET_RECORD: + case CDF_DP_TRACE_CE_PACKET_RECORD: + cdf_mem_copy(rec->data, data, size); + break; + default: + break; + } + } + rec->time = cdf_get_log_timestamp(); + rec->pid = (in_interrupt() ? 0 : current->pid); + spin_unlock_bh(&l_dp_trace_lock); +} + +/** + * cdf_dp_trace_spin_lock_init() - initializes the lock variable before use + * This function will be called from cds_alloc_global_context, we will have lock + * available to use ASAP + * + * Return : nothing + */ +void cdf_dp_trace_spin_lock_init(void) +{ + spin_lock_init(&l_dp_trace_lock); + + return; +} + +/** + * cdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions + * registered with CDF + * @code : Reason code + * @count : Number of lines to dump starting from tail to head + * + * Return : nothing + */ +void cdf_dp_trace_dump_all(uint32_t count) +{ + struct cdf_dp_trace_record_s pRecord; + int32_t i, tail; + + if (!g_cdf_dp_trace_data.enable) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, "Tracing Disabled"); + return; + } + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Total Records: %d, Head: %d, Tail: %d", + g_cdf_dp_trace_data.num, g_cdf_dp_trace_data.head, + g_cdf_dp_trace_data.tail); + + /* aquire the lock so that only one thread at a time can read + * the ring buffer + */ + spin_lock_bh(&l_dp_trace_lock); + + if (g_cdf_dp_trace_data.head != INVALID_CDF_DP_TRACE_ADDR) { + i = g_cdf_dp_trace_data.head; + tail = g_cdf_dp_trace_data.tail; + + if (count) { + if (count > g_cdf_dp_trace_data.num) + count = g_cdf_dp_trace_data.num; + if (tail >= (count - 1)) + i = tail - count + 1; + else if (count != MAX_CDF_DP_TRACE_RECORDS) + i = MAX_CDF_DP_TRACE_RECORDS - ((count - 1) - + tail); + } + + pRecord = g_cdf_dp_trace_tbl[i]; + spin_unlock_bh(&l_dp_trace_lock); + for (;; ) { + + cdf_dp_trace_cb_table[pRecord. + code] (&pRecord, (uint16_t)i); + if (i == tail) + break; + i += 1; + + spin_lock_bh(&l_dp_trace_lock); + if (MAX_CDF_DP_TRACE_RECORDS == i) + i = 0; + + pRecord = g_cdf_dp_trace_tbl[i]; + spin_unlock_bh(&l_dp_trace_lock); + } + } else { + spin_unlock_bh(&l_dp_trace_lock); + } +} diff --git a/core/cdf/src/i_cdf_atomic.h b/core/cdf/src/i_cdf_atomic.h new file mode 100644 index 000000000000..f74b7dfd47c7 --- /dev/null +++ b/core/cdf/src/i_cdf_atomic.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. + */ +#ifndef I_CDF_ATOMIC_H +#define I_CDF_ATOMIC_H + +#include /* CDF_STATUS */ + +#include + +typedef atomic_t __cdf_atomic_t; + +static inline CDF_STATUS __cdf_atomic_init(__cdf_atomic_t *v) +{ + atomic_set(v, 0); + + return CDF_STATUS_SUCCESS; +} + +static inline uint32_t __cdf_atomic_read(__cdf_atomic_t *v) +{ + return atomic_read(v); +} + +static inline void __cdf_atomic_inc(__cdf_atomic_t *v) +{ + atomic_inc(v); +} + +static inline void __cdf_atomic_dec(__cdf_atomic_t *v) +{ + atomic_dec(v); +} + +static inline void __cdf_atomic_add(int i, __cdf_atomic_t *v) +{ + atomic_add(i, v); +} + +static inline uint32_t __cdf_atomic_dec_and_test(__cdf_atomic_t *v) +{ + return atomic_dec_and_test(v); +} + +static inline void __cdf_atomic_set(__cdf_atomic_t *v, int i) +{ + atomic_set(v, i); +} + +static inline uint32_t __cdf_atomic_inc_return(__cdf_atomic_t *v) +{ + return atomic_inc_return(v); +} + +#endif diff --git a/core/cdf/src/i_cdf_defer.h b/core/cdf/src/i_cdf_defer.h new file mode 100644 index 000000000000..fc9bd7796eae --- /dev/null +++ b/core/cdf/src/i_cdf_defer.h @@ -0,0 +1,106 @@ +/* + * 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 _I_CDF_DEFER_H +#define _I_CDF_DEFER_H + +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif +#include +#include +#include + +typedef struct tasklet_struct __cdf_bh_t; + +typedef void (*__cdf_bh_fn_t)(unsigned long arg); + +/* wrapper around the real task func */ +typedef struct { + struct work_struct work; + cdf_defer_fn_t fn; + void *arg; +} __cdf_work_t; + +extern void __cdf_defer_func(struct work_struct *work); + +static inline CDF_STATUS +__cdf_init_work(cdf_handle_t hdl, + __cdf_work_t *work, cdf_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, __cdf_defer_func); +#else + INIT_WORK(&work->work, __cdf_defer_func); +#endif + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS __cdf_sched_work(cdf_handle_t hdl, __cdf_work_t *work) +{ + schedule_work(&work->work); + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS +__cdf_disable_work(cdf_handle_t hdl, __cdf_work_t *work) +{ + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS __cdf_init_bh(cdf_handle_t hdl, + struct tasklet_struct *bh, + cdf_defer_fn_t func, void *arg) +{ + tasklet_init(bh, (__cdf_bh_fn_t) func, (unsigned long)arg); + + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS +__cdf_sched_bh(cdf_handle_t hdl, struct tasklet_struct *bh) +{ + tasklet_schedule(bh); + + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS +__cdf_disable_bh(cdf_handle_t hdl, struct tasklet_struct *bh) +{ + tasklet_kill(bh); + + return CDF_STATUS_SUCCESS; +} + +#endif /*_I_CDF_DEFER_H*/ diff --git a/core/cdf/src/i_cdf_event.h b/core/cdf/src/i_cdf_event.h new file mode 100644 index 000000000000..beac5d93fd2b --- /dev/null +++ b/core/cdf/src/i_cdf_event.h @@ -0,0 +1,62 @@ +/* + * 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_CDF_EVENT_H) +#define __I_CDF_EVENT_H + +/** + * DOC: i_cdf_event.h + * + * Linux-specific definitions for CDF Events + */ + +/* Include Files */ +#include +#include + +/* Preprocessor definitions and constants */ +#define LINUX_EVENT_COOKIE 0x12341234 + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) +#define INIT_COMPLETION(event) reinit_completion(&event) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Type declarations */ + +typedef struct evt { + struct completion complete; + uint32_t cookie; +} cdf_event_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __I_CDF_EVENT_H */ diff --git a/core/cdf/src/i_cdf_lock.h b/core/cdf/src/i_cdf_lock.h new file mode 100644 index 000000000000..634728db05d3 --- /dev/null +++ b/core/cdf/src/i_cdf_lock.h @@ -0,0 +1,255 @@ +/* + * 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_CDF_LOCK_H) +#define __I_CDF_LOCK_H + +/** + * DOC: i_cdf_lock.h + * + * Linux-specific definitions for CDF Locks + * + */ + +/* Include Files */ +#include +#include +#include +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif + +/* Preprocessor definitions and constants */ + +/* define for flag */ +#define ADF_OS_LINUX_UNLOCK_BH 1 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * typedef struct - cdf_mutex_t + * @m_lock: Mutex lock + * @cookie: Lock cookie + * @processID: Process ID to track lock + * @state: Lock status + * @refcount: Reference count for recursive lock + */ +typedef struct cdf_lock_s { + struct mutex m_lock; + uint32_t cookie; + int processID; + uint32_t state; + uint8_t refcount; +} cdf_mutex_t; + +/** + * typedef struct - cdf_spinlock_t + * @spinlock: Spin lock + * @flags: Lock flag + * @_flags: Internal lock flag + */ +typedef struct __cdf_spinlock { + spinlock_t spinlock; + unsigned int flags; + unsigned long _flags; +} cdf_spinlock_t; + +typedef cdf_spinlock_t __cdf_spinlock_t; +typedef struct semaphore __cdf_semaphore_t; + +#if defined CONFIG_CNSS +typedef struct wakeup_source cdf_wake_lock_t; +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +typedef struct wake_lock cdf_wake_lock_t; +#else +typedef int cdf_wake_lock_t; +#endif + +/* Function declarations and documenation */ + +/** + * __cdf_semaphore_init() - initialize the semaphore + * @m: Semaphore object + * + * Return: CDF_STATUS_SUCCESS + */ +static inline CDF_STATUS __cdf_semaphore_init(struct semaphore *m) +{ + sema_init(m, 1); + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_semaphore_acquire() - acquire semaphore + * @m: Semaphore object + * + * Return: 0 + */ +static inline int +__cdf_semaphore_acquire(cdf_device_t osdev, struct semaphore *m) +{ + down(m); + return 0; +} + +/** + * __cdf_semaphore_release() - release semaphore + * @m: Semaphore object + * + * Return: result of UP operation in integer + */ +static inline void +__cdf_semaphore_release(cdf_device_t osdev, struct semaphore *m) +{ + up(m); +} + +/** + * __cdf_spinlock_init() - initialize spin lock + * @lock: Spin lock object + * + * Return: CDF_STATUS_SUCCESS + */ +static inline CDF_STATUS __cdf_spinlock_init(__cdf_spinlock_t *lock) +{ + spin_lock_init(&lock->spinlock); + lock->flags = 0; + + return CDF_STATUS_SUCCESS; +} + +#define __cdf_spinlock_destroy(lock) +/** + * __cdf_spin_lock() - Acquire a Spinlock(SMP) & disable Preemption (Preemptive) + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_lock(__cdf_spinlock_t *lock) +{ + spin_lock(&lock->spinlock); +} + +/** + * __cdf_spin_unlock() - Unlock the spinlock and enables the Preemption + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_unlock(__cdf_spinlock_t *lock) +{ + spin_unlock(&lock->spinlock); +} + +/** + * __cdf_spin_lock_irqsave() - Acquire a Spinlock (SMP) & disable Preemption + * (Preemptive) and disable IRQs + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_lock_irqsave(__cdf_spinlock_t *lock) +{ + spin_lock_irqsave(&lock->spinlock, lock->_flags); +} +/** + * __cdf_spin_unlock_irqrestore() - Unlock the spinlock and enables the + * Preemption and enable IRQ + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_unlock_irqrestore(__cdf_spinlock_t *lock) +{ + spin_unlock_irqrestore(&lock->spinlock, lock->_flags); +} + +/* + * Synchronous versions - only for OS' that have interrupt disable + */ +#define __cdf_spin_lock_irq(_pLock, _flags) spin_lock_irqsave(_pLock, _flags) +#define __cdf_spin_unlock_irq(_pLock, _flags) spin_unlock_irqrestore(_pLock, _flags) + +/** + * __cdf_spin_lock_bh() - Acquire the spinlock and disable bottom halves + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_lock_bh(__cdf_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; + } + +} + +/** + * __cdf_spin_unlock_bh() - Release the spinlock and enable bottom halves + * @lock: Lock object + * + * Return: none + */ +static inline void +__cdf_spin_unlock_bh(__cdf_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); +} + +/** + * __cdf_in_softirq() - in soft irq context + * + * Return: true if in softirs context else false + */ +static inline bool __cdf_in_softirq(void) +{ + return in_softirq(); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __I_CDF_LOCK_H */ diff --git a/core/cdf/src/i_cdf_mc_timer.h b/core/cdf/src/i_cdf_mc_timer.h new file mode 100644 index 000000000000..95634ff89589 --- /dev/null +++ b/core/cdf/src/i_cdf_mc_timer.h @@ -0,0 +1,61 @@ +/* + * 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_CDF_MC_TIMER_H) +#define __I_CDF_MC_TIMER_H + +/** + * DOC: i_cdf_mc_timer.h + * + * Linux-specific definitions for CDF timers serialized to MC thread + */ + +/* Include Files */ +#include +#include +#include +#include +#include + +/* Preprocessor definitions and constants */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/* Type declarations */ + +typedef struct cdf_mc_timer_platform_s { + struct timer_list Timer; + int threadID; + uint32_t cookie; + spinlock_t spinlock; +} cdf_mc_timer_platform_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __I_CDF_MC_TIMER_H */ diff --git a/core/cdf/src/i_cdf_nbuf.h b/core/cdf/src/i_cdf_nbuf.h new file mode 100644 index 000000000000..75536f09ff84 --- /dev/null +++ b/core/cdf/src/i_cdf_nbuf.h @@ -0,0 +1,1092 @@ +/* + * 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. + */ + +/** + * DOC: i_cdf_nbuf.h + * + * Linux implementation of skbuf + */ +#ifndef _I_CDF_NET_BUF_H +#define _I_CDF_NET_BUF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define __CDF_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 *__cdf_nbuf_t; + +typedef void (*__cdf_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 (*cdf_nbuf_trace_update_t)(char *); + +/** + * struct cvg_nbuf_cb - network buffer control block + * @data_attr: Value that is programmed in CE descriptor, contains: + * 1) CE classification enablement bit + * 2) Pkt type (802.3 or Ethernet Type II) + * 3) Pkt Offset (Usually the length of HTT/HTC desc.) + * @trace: info for DP tracing + * @mapped_paddr_lo: DMA mapping info + * @extra_frags: Extra tx fragments + * @owner_id: Owner id + * @cdf_nbuf_callback_fn: Callback function + * @priv_data: IPA specific priv data + * @proto_type: Protocol type + * @vdev_id: vdev id + * @tx_htt2_frm: HTT 2 frame + * @tx_htt2_reserved: HTT 2 reserved bits + */ +struct cvg_nbuf_cb { + uint32_t data_attr; + /* + * Store info for data path tracing + */ + struct { + uint8_t packet_state; + uint8_t packet_track; + uint8_t dp_trace; + } trace; + + /* + * Store the DMA mapping info for the network buffer fragments + * provided by the OS. + */ + uint32_t mapped_paddr_lo[CVG_NBUF_MAX_OS_FRAGS]; + + /* 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 + */ + uint32_t paddr_lo[CVG_NBUF_MAX_EXTRA_FRAGS]; + uint16_t len[CVG_NBUF_MAX_EXTRA_FRAGS]; + uint8_t num; /* how many extra frags has the driver added */ + uint8_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; + uint32_t owner_id; + __cdf_nbuf_callback_fn cdf_nbuf_callback_fn; + unsigned long priv_data; +#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 */ +}; +#define NBUF_OWNER_ID(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->owner_id) +#define NBUF_OWNER_PRIV_DATA(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->priv_data) +#define NBUF_CALLBACK_FN(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->cdf_nbuf_callback_fn) +#define NBUF_CALLBACK_FN_EXEC(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->cdf_nbuf_callback_fn)(skb) +#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 */ + +#define NBUF_DATA_ATTR_SET(skb, data_attr) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->data_attr = data_attr) + +#define NBUF_DATA_ATTR_GET(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->data_attr) + +#if defined(FEATURE_LRO) +/** + * struct nbuf_rx_cb - network buffer control block + * on the receive path of the skb + * @lro_eligible: indicates whether the msdu is LRO eligible + * @tcp_proto: indicates if this is a TCP packet + * @ipv6_proto: indicates if this is an IPv6 packet + * @ip_offset: offset to the IP header + * @tcp_offset: offset to the TCP header + * @tcp_udp_chksum: TCP payload checksum + * @tcp_seq_num: TCP sequence number + * @tcp_ack_num: TCP acknowledgement number + * @flow_id_toeplitz: 32 bit 5-tuple flow id toeplitz hash + */ +struct nbuf_rx_cb { + uint32_t lro_eligible:1, + tcp_proto:1, + tcp_pure_ack:1, + ipv6_proto:1, + ip_offset:7, + tcp_offset:7; + uint32_t tcp_udp_chksum:16, + tcp_win:16; + uint32_t tcp_seq_num; + uint32_t tcp_ack_num; + uint32_t flow_id_toeplitz; +}; + +#define NBUF_LRO_ELIGIBLE(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->lro_eligible) +#define NBUF_TCP_PROTO(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_proto) +#define NBUF_TCP_PURE_ACK(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_pure_ack) +#define NBUF_IPV6_PROTO(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->ipv6_proto) +#define NBUF_IP_OFFSET(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->ip_offset) +#define NBUF_TCP_OFFSET(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_offset) +#define NBUF_TCP_CHKSUM(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_udp_chksum) +#define NBUF_TCP_SEQ_NUM(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_seq_num) +#define NBUF_TCP_ACK_NUM(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_ack_num) +#define NBUF_TCP_WIN(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->tcp_win) +#define NBUF_FLOW_ID_TOEPLITZ(skb) \ + (((struct nbuf_rx_cb *)((skb)->cb))->flow_id_toeplitz) + +/** + * cdf_print_lro_info() - prints the LRO information + * @skb : network buffer + * + * This function prints out the LRO related fields in the rx + * descriptor + * + * Return: none + */ +static inline void cdf_print_lro_info(struct sk_buff *skb) +{ + cdf_print("NBUF_LRO_ELIGIBLE 0x%x\n" + "NBUF_TCP_PROTO 0x%x\n" + "NBUF_TCP_PURE_ACK 0x%x\n" + "NBUF_TCP_CHKSUM 0x%x\n" + "NBUF_IPV6_PROTO 0x%x\n" + "NBUF_IP_OFFSET 0x%x\n" + "NBUF_TCP_OFFSET 0x%x\n" + "NBUF_TCP_SEQ_NUM 0x%x\n" + "NBUF_TCP_ACK_NUM 0x%x\n" + "NBUF_TCP_WIN 0x%x\n" + "NBUF_FLOW_ID_TOEPLITZ 0x%x\n", + NBUF_LRO_ELIGIBLE(skb), + NBUF_TCP_PROTO(skb), + NBUF_TCP_PURE_ACK(skb), + NBUF_TCP_CHKSUM(skb), + NBUF_IPV6_PROTO(skb), + NBUF_IP_OFFSET(skb), + NBUF_TCP_OFFSET(skb), + NBUF_TCP_SEQ_NUM(skb), + NBUF_TCP_ACK_NUM(skb), + NBUF_TCP_WIN(skb), + NBUF_FLOW_ID_TOEPLITZ(skb)); +} +#endif /* FEATURE_LRO */ + +#define NBUF_SET_PACKET_STATE(skb, pkt_state) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.packet_state = \ + pkt_state) +#define NBUF_GET_PACKET_STATE(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.packet_state) + +#define NBUF_SET_PACKET_TRACK(skb, pkt_track) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.packet_track = \ + pkt_track) +#define NBUF_GET_PACKET_TRACK(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.packet_track) + +#define NBUF_UPDATE_TX_PKT_COUNT(skb, PACKET_STATE) \ + cdf_nbuf_set_state(skb, PACKET_STATE) + +#define CDF_NBUF_SET_DP_TRACE(skb, enable) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.dp_trace \ + = enable) +#define CDF_NBUF_GET_DP_TRACE(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->trace.dp_trace) + +#define __cdf_nbuf_get_num_frags(skb) \ + /* assume the OS provides a single fragment */ \ + (NBUF_NUM_EXTRA_FRAGS(skb) + 1) + +#if defined(FEATURE_TSO) +#define __cdf_nbuf_dec_num_frags(skb) \ + (NBUF_NUM_EXTRA_FRAGS(skb)--) +#endif + +#define __cdf_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 __cdf_nbuf_get_frag_len(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + NBUF_EXTRA_FRAG_LEN(skb, frag_num) : (skb)->len) + +#define __cdf_nbuf_get_frag_vaddr(skb, frag_num) \ + ((frag_num < NBUF_NUM_EXTRA_FRAGS(skb)) ? \ + NBUF_EXTRA_FRAG_VADDR(skb, frag_num) : ((skb)->data)) + +#define __cdf_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 __cdf_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 __cdf_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 __cdf_nbuf_trace_set_proto_type(skb, proto_type) \ + NBUF_SET_PROTO_TYPE(skb, proto_type) +#define __cdf_nbuf_trace_get_proto_type(skb) \ + NBUF_GET_PROTO_TYPE(skb); + +/** + * __cdf_nbuf_data_attr_get() - Retrieves the data_attr value + * from cvg_nbuf_cb (skb->cb) + * @skb: Pointer to struct sk_buff + * + * Return: data_attr + */ +#define __cdf_nbuf_data_attr_get(skb) \ + NBUF_DATA_ATTR_GET(skb) + +/** + * __cdf_nbuf_data_attr_set() - Sets the data_attr value + * in cvg_nbuf_cb (skb->cb) + * @skb: Pointer to struct sk_buff + * @data_attr: packet type from the enum cdf_txrx_pkt_type + * + * Return: + */ +static inline void +__cdf_nbuf_data_attr_set(struct sk_buff *skb, + uint32_t data_attr) +{ + NBUF_DATA_ATTR_SET(skb, data_attr); +} + +/** + * typedef struct __cdf_nbuf_queue_t - network buffer queue + * @head: Head pointer + * @tail: Tail pointer + * @qlen: Queue length + */ +typedef struct __cdf_nbuf_qhead { + struct sk_buff *head; + struct sk_buff *tail; + unsigned int qlen; +} __cdf_nbuf_queue_t; + +/* + * Use sk_buff_head as the implementation of cdf_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 cdf_nbuf.c + */ +__cdf_nbuf_t __cdf_nbuf_alloc(__cdf_device_t osdev, size_t size, int reserve, + int align, int prio); +void __cdf_nbuf_free(struct sk_buff *skb); +CDF_STATUS __cdf_nbuf_map(__cdf_device_t osdev, + struct sk_buff *skb, cdf_dma_dir_t dir); +void __cdf_nbuf_unmap(__cdf_device_t osdev, + struct sk_buff *skb, cdf_dma_dir_t dir); +CDF_STATUS __cdf_nbuf_map_single(__cdf_device_t osdev, + struct sk_buff *skb, cdf_dma_dir_t dir); +void __cdf_nbuf_unmap_single(__cdf_device_t osdev, + struct sk_buff *skb, cdf_dma_dir_t dir); +void __cdf_nbuf_reg_trace_cb(cdf_nbuf_trace_update_t cb_func_ptr); + +#ifdef QCA_PKT_PROTO_TRACE +void __cdf_nbuf_trace_update(struct sk_buff *buf, char *event_string); +#else +#define __cdf_nbuf_trace_update(skb, event_string) +#endif /* QCA_PKT_PROTO_TRACE */ + +/** + * __cdf_os_to_status() - OS to CDF status conversion + * @error : OS error + * + * Return: CDF status + */ +static inline CDF_STATUS __cdf_os_to_status(signed int error) +{ + switch (error) { + case 0: + return CDF_STATUS_SUCCESS; + case ENOMEM: + case -ENOMEM: + return CDF_STATUS_E_NOMEM; + default: + return CDF_STATUS_E_NOSUPPORT; + } +} + +/** + * __cdf_nbuf_len() - return the amount of valid data in the skb + * @skb: Pointer to network buffer + * + * This API returns the amount of valid data in the skb, If there are frags + * then it returns total length. + * + * Return: network buffer length + */ +static inline size_t __cdf_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; +} + +/** + * __cdf_nbuf_cat() - link two nbufs + * @dst: Buffer to piggyback into + * @src: Buffer to put + * + * Link tow nbufs the new buf is piggybacked into the older one. The older + * (src) skb is released. + * + * Return: CDF_STATUS (status of the call) if failed the src skb + * is released + */ +static inline CDF_STATUS +__cdf_nbuf_cat(struct sk_buff *dst, struct sk_buff *src) +{ + CDF_STATUS error = 0; + + cdf_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 __cdf_os_to_status(error); + } + memcpy(skb_tail_pointer(dst), src->data, src->len); + + skb_put(dst, src->len); + dev_kfree_skb_any(src); + + return __cdf_os_to_status(error); +} + +/**************************nbuf manipulation routines*****************/ + +/** + * __cdf_nbuf_headroom() - return the amount of tail space available + * @buf: Pointer to network buffer + * + * Return: amount of tail room + */ +static inline int __cdf_nbuf_headroom(struct sk_buff *skb) +{ + return skb_headroom(skb); +} + +/** + * __cdf_nbuf_tailroom() - return the amount of tail space available + * @buf: Pointer to network buffer + * + * Return: amount of tail room + */ +static inline uint32_t __cdf_nbuf_tailroom(struct sk_buff *skb) +{ + return skb_tailroom(skb); +} + +/** + * __cdf_nbuf_push_head() - Push data in the front + * @skb: Pointer to network buffer + * @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 *__cdf_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); +} + +/** + * __cdf_nbuf_put_tail() - Puts data in the end + * @skb: Pointer to network buffer + * @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 *__cdf_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); +} + +/** + * __cdf_nbuf_pull_head() - pull data out from the front + * @skb: Pointer to network buffer + * @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 *__cdf_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); +} + +/** + * __cdf_nbuf_trim_tail() - trim data out from the end + * @skb: Pointer to network buffer + * @size: size to be popped + * + * Return: none + */ +static inline void __cdf_nbuf_trim_tail(struct sk_buff *skb, size_t size) +{ + return skb_trim(skb, skb->len - size); +} + +/*********************nbuf private buffer routines*************/ + +/** + * __cdf_nbuf_peek_header() - return the header's addr & m_len + * @skb: Pointer to network buffer + * @addr: Pointer to store header's addr + * @m_len: network buffer length + * + * Return: none + */ +static inline void +__cdf_nbuf_peek_header(struct sk_buff *skb, uint8_t **addr, uint32_t *len) +{ + *addr = skb->data; + *len = skb->len; +} + +/******************Custom queue*************/ + +/** + * __cdf_nbuf_queue_init() - initiallize the queue head + * @qhead: Queue head + * + * Return: CDF status + */ +static inline CDF_STATUS __cdf_nbuf_queue_init(__cdf_nbuf_queue_t *qhead) +{ + memset(qhead, 0, sizeof(struct __cdf_nbuf_qhead)); + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_nbuf_queue_add() - add an skb in the tail of the queue + * @qhead: Queue head + * @skb: Pointer to network buffer + * + * This is a lockless version, driver must acquire locks if it + * needs to synchronize + * + * Return: none + */ +static inline void +__cdf_nbuf_queue_add(__cdf_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++; +} + +/** + * __cdf_nbuf_queue_insert_head() - add an skb at the head of the queue + * @qhead: Queue head + * @skb: Pointer to network buffer + * + * This is a lockless version, driver must acquire locks if it needs to + * synchronize + * + * Return: none + */ +static inline void +__cdf_nbuf_queue_insert_head(__cdf_nbuf_queue_t *qhead, __cdf_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++; +} + +/** + * __cdf_nbuf_queue_remove() - remove a skb from the head of the queue + * @qhead: Queue head + * + * This is a lockless version. Driver should take care of the locks + * + * Return: skb or NULL + */ +static inline +struct sk_buff *__cdf_nbuf_queue_remove(__cdf_nbuf_queue_t *qhead) +{ + __cdf_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; +} + +/** + * __cdf_nbuf_queue_len() - return the queue length + * @qhead: Queue head + * + * Return: Queue length + */ +static inline uint32_t __cdf_nbuf_queue_len(__cdf_nbuf_queue_t *qhead) +{ + return qhead->qlen; +} + +/** + * __cdf_nbuf_queue_next() - return the next skb from packet chain + * @skb: Pointer to network buffer + * + * This API returns the next skb from packet chain, remember the skb is + * still in the queue + * + * Return: NULL if no packets are there + */ +static inline struct sk_buff *__cdf_nbuf_queue_next(struct sk_buff *skb) +{ + return skb->next; +} + +/** + * __cdf_nbuf_is_queue_empty() - check if the queue is empty or not + * @qhead: Queue head + * + * Return: true if length is 0 else false + */ +static inline bool __cdf_nbuf_is_queue_empty(__cdf_nbuf_queue_t *qhead) +{ + return qhead->qlen == 0; +} + +/* + * Use sk_buff_head as the implementation of cdf_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 cdf_nbuf.c + */ +cdf_nbuf_tx_cksum_t __cdf_nbuf_get_tx_cksum(struct sk_buff *skb); +CDF_STATUS __cdf_nbuf_set_rx_cksum(struct sk_buff *skb, + cdf_nbuf_rx_cksum_t *cksum); +uint8_t __cdf_nbuf_get_tid(struct sk_buff *skb); +void __cdf_nbuf_set_tid(struct sk_buff *skb, uint8_t tid); +uint8_t __cdf_nbuf_get_exemption_type(struct sk_buff *skb); + +/* + * cdf_nbuf_pool_delete() implementation - do nothing in linux + */ +#define __cdf_nbuf_pool_delete(osdev) + +/** + * __cdf_nbuf_clone() - clone the nbuf (copy is readonly) + * @skb: Pointer to network buffer + * + * 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()" + * + * Return: cloned skb + */ +static inline struct sk_buff *__cdf_nbuf_clone(struct sk_buff *skb) +{ + return skb_clone(skb, GFP_ATOMIC); +} + +/** + * __cdf_nbuf_copy() - returns a private copy of the skb + * @skb: Pointer to network buffer + * + * This API returns a private copy of the skb, the skb returned is completely + * modifiable by callers + * + * Return: skb or NULL + */ +static inline struct sk_buff *__cdf_nbuf_copy(struct sk_buff *skb) +{ + return skb_copy(skb, GFP_ATOMIC); +} + +#define __cdf_nbuf_reserve skb_reserve + +/***********************XXX: misc api's************************/ + +/** + * __cdf_nbuf_head() - return the pointer the skb's head pointer + * @skb: Pointer to network buffer + * + * Return: Pointer to head buffer + */ +static inline uint8_t *__cdf_nbuf_head(struct sk_buff *skb) +{ + return skb->head; +} + +/** + * __cdf_nbuf_data() - return the pointer to data header in the skb + * @skb: Pointer to network buffer + * + * Return: Pointer to skb data + */ +static inline uint8_t *__cdf_nbuf_data(struct sk_buff *skb) +{ + return skb->data; +} + +/** + * __cdf_nbuf_get_protocol() - return the protocol value of the skb + * @skb: Pointer to network buffer + * + * Return: skb protocol + */ +static inline uint16_t __cdf_nbuf_get_protocol(struct sk_buff *skb) +{ + return skb->protocol; +} + +/** + * __cdf_nbuf_get_ip_summed() - return the ip checksum value of the skb + * @skb: Pointer to network buffer + * + * Return: skb ip_summed + */ +static inline uint8_t __cdf_nbuf_get_ip_summed(struct sk_buff *skb) +{ + return skb->ip_summed; +} + +/** + * __cdf_nbuf_set_ip_summed() - sets the ip_summed value of the skb + * @skb: Pointer to network buffer + * @ip_summed: ip checksum + * + * Return: none + */ +static inline void __cdf_nbuf_set_ip_summed(struct sk_buff *skb, uint8_t ip_summed) +{ + skb->ip_summed = ip_summed; +} + +/** + * __cdf_nbuf_get_priority() - return the priority value of the skb + * @skb: Pointer to network buffer + * + * Return: skb priority + */ +static inline uint32_t __cdf_nbuf_get_priority(struct sk_buff *skb) +{ + return skb->priority; +} + +/** + * __cdf_nbuf_set_priority() - sets the priority value of the skb + * @skb: Pointer to network buffer + * @p: priority + * + * Return: none + */ +static inline void __cdf_nbuf_set_priority(struct sk_buff *skb, uint32_t p) +{ + skb->priority = p; +} + +/** + * __cdf_nbuf_set_next() - sets the next skb pointer of the current skb + * @skb: Current skb + * @next_skb: Next skb + * + * Return: void + */ +static inline void +__cdf_nbuf_set_next(struct sk_buff *skb, struct sk_buff *skb_next) +{ + skb->next = skb_next; +} + +/** + * __cdf_nbuf_next() - return the next skb pointer of the current skb + * @skb: Current skb + * + * Return: the next skb pointed to by the current skb + */ +static inline struct sk_buff *__cdf_nbuf_next(struct sk_buff *skb) +{ + return skb->next; +} + +/** + * __cdf_nbuf_set_next_ext() - sets the next skb pointer of the current skb + * @skb: Current skb + * @next_skb: Next skb + * + * This fn is used to link up extensions to the head skb. Does not handle + * linking to the head + * + * Return: none + */ +static inline void +__cdf_nbuf_set_next_ext(struct sk_buff *skb, struct sk_buff *skb_next) +{ + skb->next = skb_next; +} + +/** + * __cdf_nbuf_next_ext() - return the next skb pointer of the current skb + * @skb: Current skb + * + * Return: the next skb pointed to by the current skb + */ +static inline struct sk_buff *__cdf_nbuf_next_ext(struct sk_buff *skb) +{ + return skb->next; +} + +/** + * __cdf_nbuf_append_ext_list() - link list of packet extensions to the head + * @skb_head: head_buf nbuf holding head segment (single) + * @ext_list: nbuf list holding linked extensions to the head + * @ext_len: Total length of all buffers in the extension list + * + * This function is used to link up a list of packet extensions (seg1, 2,* ...) + * to the nbuf holding the head segment (seg0) + * + * Return: none + */ +static inline void +__cdf_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; +} + +/** + * __cdf_nbuf_tx_free() - free skb list + * @skb: Pointer to network buffer + * @tx_err: TX error + * + * Return: none + */ +static inline void __cdf_nbuf_tx_free(struct sk_buff *bufs, int tx_err) +{ + while (bufs) { + struct sk_buff *next = __cdf_nbuf_next(bufs); + __cdf_nbuf_free(bufs); + bufs = next; + } +} + +/** + * __cdf_nbuf_get_age() - return the checksum value of the skb + * @skb: Pointer to network buffer + * + * Return: checksum value + */ +static inline uint32_t __cdf_nbuf_get_age(struct sk_buff *skb) +{ + return skb->csum; +} + +/** + * __cdf_nbuf_set_age() - sets the checksum value of the skb + * @skb: Pointer to network buffer + * @v: Value + * + * Return: none + */ +static inline void __cdf_nbuf_set_age(struct sk_buff *skb, uint32_t v) +{ + skb->csum = v; +} + +/** + * __cdf_nbuf_adj_age() - adjusts the checksum/age value of the skb + * @skb: Pointer to network buffer + * @adj: Adjustment value + * + * Return: none + */ +static inline void __cdf_nbuf_adj_age(struct sk_buff *skb, uint32_t adj) +{ + skb->csum -= adj; +} + +/** + * __cdf_nbuf_copy_bits() - return the length of the copy bits for skb + * @skb: Pointer to network buffer + * @offset: Offset value + * @len: Length + * @to: Destination pointer + * + * Return: length of the copy bits for skb + */ +static inline int32_t +__cdf_nbuf_copy_bits(struct sk_buff *skb, int32_t offset, int32_t len, void *to) +{ + return skb_copy_bits(skb, offset, to, len); +} + +/** + * __cdf_nbuf_set_pktlen() - sets the length of the skb and adjust the tail + * @skb: Pointer to network buffer + * @len: Packet length + * + * Return: none + */ +static inline void __cdf_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); + cdf_assert(0); + } + } + skb_put(skb, (len - skb->len)); + } +} + +/** + * __cdf_nbuf_set_protocol() - sets the protocol value of the skb + * @skb: Pointer to network buffer + * @protocol: Protocol type + * + * Return: none + */ +static inline void +__cdf_nbuf_set_protocol(struct sk_buff *skb, uint16_t protocol) +{ + skb->protocol = protocol; +} + +#define __cdf_nbuf_set_tx_htt2_frm(skb, candi) \ + NBUF_SET_TX_HTT2_FRM(skb, candi) +#define __cdf_nbuf_get_tx_htt2_frm(skb) \ + NBUF_GET_TX_HTT2_FRM(skb) + +#if defined(FEATURE_TSO) +uint32_t __cdf_nbuf_get_tso_info(cdf_device_t osdev, struct sk_buff *skb, + struct cdf_tso_info_t *tso_info); + +uint32_t __cdf_nbuf_get_tso_num_seg(struct sk_buff *skb); + +static inline uint8_t __cdf_nbuf_is_tso(struct sk_buff *skb) +{ + return skb_is_gso(skb); +} + +struct sk_buff *__cdf_nbuf_inc_users(struct sk_buff *skb); +#endif /* TSO */ + +/** + * __cdf_nbuf_tx_info_get() - Modify pkt_type, set pkt_subtype, + * and get hw_classify by peeking + * into packet + * @nbuf: Network buffer (skb on Linux) + * @pkt_type: Pkt type (from enum htt_pkt_type) + * @pkt_subtype: Bit 4 of this field in HTT descriptor + * needs to be set in case of CE classification support + * Is set by this macro. + * @hw_classify: This is a flag which is set to indicate + * CE classification is enabled. + * Do not set this bit for VLAN packets + * OR for mcast / bcast frames. + * + * This macro parses the payload to figure out relevant Tx meta-data e.g. + * whether to enable tx_classify bit in CE. + * + * Overrides pkt_type only if required for 802.3 frames (original ethernet) + * If protocol is less than ETH_P_802_3_MIN (0x600), then + * it is the length and a 802.3 frame else it is Ethernet Type II + * (RFC 894). + * Bit 4 in pkt_subtype is the tx_classify bit + * + * Return: void + */ +#define __cdf_nbuf_tx_info_get(skb, pkt_type, \ + pkt_subtype, hw_classify) \ +do { \ + struct ethhdr *eh = (struct ethhdr *)skb->data; \ + uint16_t ether_type = ntohs(eh->h_proto); \ + bool is_mc_bc; \ + \ + is_mc_bc = is_broadcast_ether_addr((uint8_t *)eh) || \ + is_multicast_ether_addr((uint8_t *)eh); \ + \ + if (likely((ether_type != ETH_P_8021Q) && !is_mc_bc)) { \ + hw_classify = 1; \ + pkt_subtype = 0x01 << \ + HTT_TX_CLASSIFY_BIT_S; \ + } \ + \ + if (unlikely(ether_type < ETH_P_802_3_MIN)) \ + pkt_type = htt_pkt_type_ethernet; \ + \ +} while (0) +#endif /*_I_CDF_NET_BUF_H */ diff --git a/core/cdf/src/i_cdf_softirq_timer.h b/core/cdf/src/i_cdf_softirq_timer.h new file mode 100644 index 000000000000..31cbd68e5970 --- /dev/null +++ b/core/cdf/src/i_cdf_softirq_timer.h @@ -0,0 +1,152 @@ +/* + * 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 _I_CDF_SOFTIRQ_TIMER_H +#define _I_CDF_SOFTIRQ_TIMER_H + +#include +#include +#include +#include +#include + +/* timer data type */ +typedef struct timer_list __cdf_softirq_timer_t; + +/* ugly - but every other OS takes, sanely, a void */ + +typedef void (*cdf_dummy_timer_func_t)(unsigned long arg); + +/** + * __cdf_softirq_timer_init() - initialize a softirq timer + * @hdl: OS handle + * @timer: Pointer to timer object + * @func: Function pointer + * @arg: Arguement + * @type: deferrable or non deferrable timer type + * + * Timer type CDF_TIMER_TYPE_SW means its a deferrable sw timer which will + * not cause CPU wake upon expiry + * Timer type CDF_TIMER_TYPE_WAKE_APPS means its a non-deferrable timer which + * will cause CPU wake up on expiry + * + * Return: none + */ +static inline CDF_STATUS +__cdf_softirq_timer_init(cdf_handle_t hdl, + struct timer_list *timer, + cdf_softirq_timer_func_t func, void *arg, + CDF_TIMER_TYPE type) +{ + if (CDF_TIMER_TYPE_SW == type) + init_timer_deferrable(timer); + else + init_timer(timer); + timer->function = (cdf_dummy_timer_func_t) func; + timer->data = (unsigned long)arg; + + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_softirq_timer_start() - start a cdf softirq timer + * @timer: Pointer to timer object + * @delay: Delay in milli seconds + * + * Return: none + */ +static inline CDF_STATUS +__cdf_softirq_timer_start(struct timer_list *timer, uint32_t delay) +{ + timer->expires = jiffies + msecs_to_jiffies(delay); + add_timer(timer); + + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_softirq_timer_mod() - modify a timer + * @timer: Pointer to timer object + * @delay: Delay in milli seconds + * + * Return: none + */ +static inline CDF_STATUS +__cdf_softirq_timer_mod(struct timer_list *timer, uint32_t delay) +{ + mod_timer(timer, jiffies + msecs_to_jiffies(delay)); + + return CDF_STATUS_SUCCESS; +} + +/** + * __cdf_softirq_timer_cancel() - cancel a timer + * @timer: Pointer to timer object + * + * Return: true if timer was cancelled and deactived, + * false if timer was cancelled but already got fired. + */ +static inline bool __cdf_softirq_timer_cancel(struct timer_list *timer) +{ + if (likely(del_timer(timer))) + return 1; + else + return 0; +} + +/** + * __cdf_softirq_timer_free() - free a cdf timer + * @timer: Pointer to timer object + * + * Return: true if timer was cancelled and deactived, + * false if timer was cancelled but already got fired. + */ +static inline void __cdf_softirq_timer_free(struct timer_list *timer) +{ + del_timer_sync(timer); +} + +/** + * __cdf_sostirq_timer_sync_cancel() - Synchronously canel a timer + * @timer: Pointer to timer object + * + * Synchronization Rules: + * 1. caller must make sure timer function will not use + * cdf_softirq_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. + * + * Return: true if timer was cancelled and deactived, + * false if timer was cancelled but already got fired. + */ +static inline bool __cdf_sostirq_timer_sync_cancel(struct timer_list *timer) +{ + return del_timer_sync(timer); +} + +#endif /*_ADF_OS_TIMER_PVT_H*/ diff --git a/core/cdf/src/i_cdf_time.h b/core/cdf/src/i_cdf_time.h new file mode 100644 index 000000000000..08cf5b4a15e4 --- /dev/null +++ b/core/cdf/src/i_cdf_time.h @@ -0,0 +1,217 @@ +/* + * 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. + */ + +/** + * DOC: i_cdf_time.h + * + * Linux specific CDF timing APIs implementation + */ + +#ifndef _I_CDF_TIME_H +#define _I_CDF_TIME_H + +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif + +typedef unsigned long __cdf_time_t; + +/** + * __cdf_system_ticks() - get system ticks + * + * Return: system tick in jiffies + */ +static inline __cdf_time_t __cdf_system_ticks(void) +{ + return jiffies; +} + +/** + * __cdf_system_ticks_to_msecs() - convert system ticks into milli seconds + * @ticks: System ticks + * + * Return: system tick converted into milli seconds + */ +static inline uint32_t __cdf_system_ticks_to_msecs(unsigned long ticks) +{ + return jiffies_to_msecs(ticks); +} + +/** + * __cdf_system_msecs_to_ticks() - convert milli seconds into system ticks + * @msecs: Milli seconds + * + * Return: milli seconds converted into system ticks + */ +static inline __cdf_time_t __cdf_system_msecs_to_ticks(uint32_t msecs) +{ + return msecs_to_jiffies(msecs); +} + +/** + * __cdf_get_system_uptime() - get system uptime + * + * Return: system uptime in jiffies + */ +static inline __cdf_time_t __cdf_get_system_uptime(void) +{ + return jiffies; +} + +static inline __cdf_time_t __cdf_get_system_timestamp(void) +{ + return (jiffies / HZ) * 1000 + (jiffies % HZ) * (1000 / HZ); +} + +/** + * __cdf_udelay() - delay execution for given microseconds + * @usecs: Micro seconds to delay + * + * Return: none + */ +static inline void __cdf_udelay(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 + */ + + uint32_t mticks; + 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 +} + +/** + * __cdf_mdelay() - delay execution for given milli seconds + * @usecs: Milli seconds to delay + * + * Return: none + */ +static inline void __cdf_mdelay(uint32_t msecs) +{ + mdelay(msecs); +} + +/** + * __cdf_system_time_after() - Check if a is later than b + * @a: Time stamp value a + * @b: Time stamp value b + * + * Return: + * true if a < b else false + */ +static inline bool __cdf_system_time_after(__cdf_time_t a, __cdf_time_t b) +{ + return (long)(b) - (long)(a) < 0; +} + +/** + * __cdf_system_time_before() - Check if a is before b + * @a: Time stamp value a + * @b: Time stamp value b + * + * Return: + * true if a is before b else false + */ +static inline bool __cdf_system_time_before(__cdf_time_t a, __cdf_time_t b) +{ + return __cdf_system_time_after(b, a); +} + +/** + * __cdf_system_time_before() - Check if a atleast as recent as b, if not + * later + * @a: Time stamp value a + * @b: Time stamp value b + * + * Return: + * true if a >= b else false + */ +static inline bool __cdf_system_time_after_eq(__cdf_time_t a, __cdf_time_t b) +{ + return (long)(a) - (long)(b) >= 0; +} + +/** + * __cdf_get_monotonic_boottime() - get monotonic kernel boot time + * This API is similar to cdf_get_system_boottime but it includes + * time spent in suspend. + * + * Return: Time in microseconds + */ +#ifdef CONFIG_CNSS +static inline uint64_t __cdf_get_monotonic_boottime(void) +{ + struct timespec ts; + + cnss_get_monotonic_boottime(&ts); + + return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); +} +#else +static inline uint64_t __cdf_get_monotonic_boottime(void) +{ + return __cdf_system_ticks_to_msecs(__cdf_system_ticks()) * 1000; +} +#endif /* CONFIG_CNSS */ + +#ifdef QCA_WIFI_3_0_ADRASTEA +/** + * __cdf_get_qtimer_ticks() - get QTIMER ticks + * + * Returns QTIMER(19.2 MHz) clock ticks. To convert it into seconds + * divide it by 19200. + * + * Return: QTIMER(19.2 MHz) clock ticks + */ +static inline uint64_t __cdf_get_qtimer_ticks(void) +{ + return arch_counter_get_cntpct(); +} +#endif /* QCA_WIFI_3_0_ADRASTEA */ + +#endif diff --git a/core/cdf/src/i_cdf_trace.h b/core/cdf/src/i_cdf_trace.h new file mode 100644 index 000000000000..a3b36ee8c55c --- /dev/null +++ b/core/cdf/src/i_cdf_trace.h @@ -0,0 +1,145 @@ +/* + * 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_CDF_TRACE_H) +#define __I_CDF_TRACE_H + +#if !defined(__printf) +#define __printf(a, b) +#endif + +/** + * DOC: i_cdf_trace.h + * + * Linux-specific definitions for CDF trace + * + */ + +/* Include Files */ + +/** + * cdf_trace_msg()- logging API + * @module: Module identifier. A member of the CDF_MODULE_ID enumeration that + * identifies the module issuing the trace message. + * @level: Trace level. A member of the CDF_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. + * @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. + * + * Users wishing to add tracing information to their code should use + * CDF_TRACE. CDF_TRACE() will compile into a call to cdf_trace_msg() when + * tracing is enabled. + * + * Return: nothing + * + */ +void __printf(3, 4) cdf_trace_msg(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + char *strFormat, ...); + +void cdf_trace_hex_dump(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + void *data, int buf_len); + +void cdf_trace_display(void); + +void cdf_trace_set_value(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, + uint8_t on); + +void cdf_trace_set_module_trace_level(CDF_MODULE_ID module, uint32_t level); + +/* CDF_TRACE is the macro invoked to add trace messages to code. See the + * documenation for cdf_trace_msg() for the parameters etc. for this function. + * + * NOTE: Code CDF_TRACE() macros into the source code. Do not code directly + * to the cdf_trace_msg() function. + * + * NOTE 2: cdf 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 CDF_TRACE cdf_trace_msg +#define CDF_TRACE_HEX_DUMP cdf_trace_hex_dump +#else +#define CDF_TRACE(arg ...) +#define CDF_TRACE_HEX_DUMP(arg ...) +#endif + +void __printf(3, 4) cdf_snprintf(char *strBuffer, unsigned int size, + char *strFormat, ...); +#define CDF_SNPRINTF cdf_snprintf + +#ifdef CDF_ENABLE_TRACING + +#define CDF_ASSERT(_condition) \ + do { \ + if (!(_condition)) { \ + pr_err("CDF 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' */ +CDF_INLINE_FN void cdf_trace_msg(CDF_MODULE_ID module, ...) +{ +} + +#define CDF_ASSERT(_condition) + +#endif + +#ifdef PANIC_ON_BUG + +#define CDF_BUG(_condition) \ + do { \ + if (!(_condition)) { \ + pr_err("CDF BUG in %s Line %d\n", \ + __func__, __LINE__); \ + BUG_ON(1); \ + } \ + } while (0) + +#else + +#define CDF_BUG(_condition) \ + do { \ + if (!(_condition)) { \ + pr_err("CDF BUG in %s Line %d\n", \ + __func__, __LINE__); \ + WARN_ON(1); \ + } \ + } while (0) + +#endif + +#endif diff --git a/core/cdf/src/i_cdf_types.h b/core/cdf/src/i_cdf_types.h new file mode 100644 index 000000000000..febbaff2352c --- /dev/null +++ b/core/cdf/src/i_cdf_types.h @@ -0,0 +1,234 @@ +/* + * 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. + */ + +/** + * DOC: i_cdf_types.h + * + * Connectivity driver framework (CDF) types + */ + +#if !defined(__I_CDF_TYPES_H) +#define __I_CDF_TYPES_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __KERNEL__ +#define __iomem +#endif +#include +#include +#include + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#else + +/* + * 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 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 __CDF_OS_MAX_SCATTER 1 + +#if defined(__LITTLE_ENDIAN_BITFIELD) +#define CDF_LITTLE_ENDIAN_MACHINE +#elif defined (__BIG_ENDIAN_BITFIELD) +#define CDF_BIG_ENDIAN_MACHINE +#else +#error "Please fix " +#endif + +#define __cdf_packed __attribute__ ((packed)) + +typedef int (*__cdf_os_intr)(void *); +/** + * Private definitions of general data types + */ +typedef dma_addr_t __cdf_dma_addr_t; +typedef dma_addr_t __cdf_dma_context_t; + +#define cdf_dma_mem_context(context) dma_addr_t context +#define cdf_get_dma_mem_context(var, field) ((cdf_dma_context_t)(var->field)) + +/** + * typedef struct __cdf_resource_t - cdf resource type + * @paddr: Physical address + * @paddr: Virtual address + * @len: Length + */ +typedef struct __cdf_os_resource { + unsigned long paddr; + void __iomem *vaddr; + unsigned long len; +} __cdf_resource_t; + +/** + * struct __cdf_device - generic cdf device type + * @drv: Pointer to driver + * @drv_hdl: Pointer to driver handle + * @drv_name: Pointer to driver name + * @irq: IRQ + * @dev: Pointer to device + * @res: CDF resource + * @func: Interrupt handler + */ +struct __cdf_device { + void *drv; + void *drv_hdl; + char *drv_name; + int irq; + struct device *dev; + __cdf_resource_t res; + __cdf_os_intr func; +}; + +typedef struct __cdf_device *__cdf_device_t; + +typedef size_t __cdf_size_t; +typedef uint8_t __iomem *__cdf_iomem_t; + +/** + * typedef struct __cdf_segment_t - cdf segment + * @daddr: DMA address + * @len: Length + */ +typedef struct __cdf_segment { + dma_addr_t daddr; + uint32_t len; +} __cdf_segment_t; + +/** + * struct __cdf_dma_map - dma map + * @mapped: dma is mapped or not + * @nsegs: Number of segments + * @coherent: Coherent + * @seg: Segment array + */ +struct __cdf_dma_map { + uint32_t mapped; + uint32_t nsegs; + uint32_t coherent; + __cdf_segment_t seg[__CDF_OS_MAX_SCATTER]; +}; +typedef struct __cdf_dma_map *__cdf_dma_map_t; +typedef uint32_t ath_dma_addr_t; + +#define __cdf_print printk +#define __cdf_vprint vprintk +#define __cdf_snprint snprintf +#define __cdf_vsnprint vsnprintf + +#define __CDF_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL +#define __CDF_DMA_TO_DEVICE DMA_TO_DEVICE +#define __CDF_DMA_FROM_DEVICE DMA_FROM_DEVICE +#define __cdf_inline inline + +/* + * 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. 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 CDF_COMPILER_MSC +/* assuming that if we build with MSC, OS is WinMobile */ +#define CDF_OS_WINMOBILE + +#elif defined(__GNUC__) + +#define CDF_COMPILER_GNUC +#define CDF_OS_LINUX /* assuming if building with GNUC, OS is Linux */ + +#endif + +#if defined(CDF_COMPILER_MSC) + +#define CDF_INLINE_FN __inline + +/* Does nothing on Windows. packing individual structs is not + * supported on the Windows compiler + */ +#define CDF_PACK_STRUCT_1 +#define CDF_PACK_STRUCT_2 +#define CDF_PACK_STRUCT_4 +#define CDF_PACK_STRUCT_8 +#define CDF_PACK_STRUCT_16 + +#elif defined(CDF_COMPILER_GNUC) + +#define CDF_INLINE_FN static inline + +#else +#error "Compiling with an unknown compiler!!" +#endif + +#endif /* __I_CDF_TYPES_H */ diff --git a/core/cdf/src/i_cdf_util.h b/core/cdf/src/i_cdf_util.h new file mode 100644 index 000000000000..db2f11fa7e62 --- /dev/null +++ b/core/cdf/src/i_cdf_util.h @@ -0,0 +1,107 @@ +/* + * 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 _I_CDF_UTIL_H +#define _I_CDF_UTIL_H + +#include +#include +#include +#include + +#include + +#include +#include +#include +/* + * Generic compiler-dependent macros if defined by the OS + */ + +#define __cdf_unlikely(_expr) unlikely(_expr) +#define __cdf_likely(_expr) likely(_expr) + +/** + * cdf_status_to_os_return(): translates cdf_status types to linux return types + * @status: status to translate + * + * Translates error types that linux may want to handle specially. + * + * return: 0 or the linux error code that most closely matches the CDF_STATUS. + * defaults to -1 (EPERM) + */ +static inline int __cdf_status_to_os_return(CDF_STATUS status) +{ + switch (status) { + case CDF_STATUS_SUCCESS: + return 0; + case CDF_STATUS_E_NULL_VALUE: + case CDF_STATUS_E_FAULT: + return -EFAULT; + case CDF_STATUS_E_TIMEOUT: + case CDF_STATUS_E_BUSY: + return -EBUSY; + case CDF_STATUS_NOT_INITIALIZED: + case CDF_STATUS_E_AGAIN: + return -EAGAIN; + case CDF_STATUS_E_NOSUPPORT: + return -ENOSYS; + case CDF_STATUS_E_ALREADY: + return -EALREADY; + case CDF_STATUS_E_NOMEM: + return -ENOMEM; + default: + return -EPERM; + } +} + + +/** + * @brief memory barriers. + */ + +#define __cdf_min(_a, _b) ((_a) < (_b) ? _a : _b) +#define __cdf_max(_a, _b) ((_a) > (_b) ? _a : _b) + +/** + * @brief Assert + */ +#define __cdf_assert(expr) do { \ + if (unlikely(!(expr))) { \ + pr_err("Assertion failed! %s:%s %s:%d\n", \ + # expr, __func__, __FILE__, __LINE__); \ + dump_stack(); \ + panic("Take care of the assert first\n"); \ + } \ +} while (0) + +#define __cdf_os_cpu_to_le64 cpu_to_le64 +#define __cdf_le16_to_cpu le16_to_cpu +#define __cdf_le32_to_cpu le32_to_cpu +#define __cdf_container_of(ptr, type, member) container_of(ptr, type, member) + +#endif /*_I_CDF_UTIL_H*/ diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h new file mode 100644 index 000000000000..01618a578322 --- /dev/null +++ b/core/cds/inc/cds_api.h @@ -0,0 +1,124 @@ +/* + * 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(__CDS_API_H) +#define __CDS_API_H + +/** + * DOC: cds_api.h + * + * Connectivity driver services public API + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Amount of time to wait for WMA to perform an asynchronous activity. + * This value should be larger than the timeout used by WMI to wait for + * a response from target + */ +#define CDS_WMA_TIMEOUT (15000) + +CDF_STATUS cds_alloc_global_context(v_CONTEXT_t *p_cds_context); + +CDF_STATUS cds_free_global_context(v_CONTEXT_t *p_cds_context); + +CDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context); + +CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize); + +CDF_STATUS cds_enable(v_CONTEXT_t cds_context); + +CDF_STATUS cds_disable(v_CONTEXT_t cds_context); + +CDF_STATUS cds_close(v_CONTEXT_t cds_context); + +CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context); + +void cds_core_return_msg(void *pVContext, p_cds_msg_wrapper pMsgWrapper); + +void *cds_get_context(CDF_MODULE_ID moduleId); + +v_CONTEXT_t cds_get_global_context(void); + +uint8_t cds_is_logp_in_progress(void); +void cds_set_logp_in_progress(uint8_t value); + +uint8_t cds_is_load_unload_in_progress(void); +void cds_set_load_unload_in_progress(uint8_t value); + +CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, + void **ppModuleContext, uint32_t size); + +CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID, + void *pModuleContext); + +CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type, + uint32_t *subType); + +void cds_flush_work(void *work); +void cds_flush_delayed_work(void *dwork); + +bool cds_is_packet_log_enabled(void); + +uint64_t cds_get_monotonic_boottime(void); + +void cds_trigger_recovery(void); + +void cds_set_wakelock_logging(bool value); +bool cds_is_wakelock_enabled(void); +void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level); +enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id); +void cds_set_multicast_logging(uint8_t value); +uint8_t cds_is_multicast_logging(void); +CDF_STATUS cds_set_log_completion(uint32_t is_fatal, + uint32_t type, + uint32_t sub_type); +void cds_get_log_completion(uint32_t *is_fatal, + uint32_t *type, + uint32_t *sub_type); +bool cds_is_log_report_in_progress(void); +void cds_init_log_completion(void); +void cds_deinit_log_completion(void); +CDF_STATUS cds_flush_logs(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code); +void cds_logging_set_fw_flush_complete(void); +#endif /* if !defined __CDS_API_H */ diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h new file mode 100644 index 000000000000..972941c07818 --- /dev/null +++ b/core/cds/inc/cds_concurrency.h @@ -0,0 +1,732 @@ +/* + * 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 __CDS_CONCURRENCY_H +#define __CDS_CONCURRENCY_H + +/** + * DOC: cds_concurrency.h + * + * CDS Concurrenct Connection Management entity + */ + +/* Include files */ + +#include "wlan_hdd_main.h" + +#define MAX_NUMBER_OF_CONC_CONNECTIONS 3 +#define MAX_NUM_CHAN 128 +#define DBS_OPPORTUNISTIC_TIME 10 + +/** + * enum cds_chain_mode - Chain Mask tx & rx combination. + * + * @CDS_ONE_ONE: One for Tx, One for Rx + * @CDS_TWO_TWO: Two for Tx, Two for Rx + * @CDS_MAX_NO_OF_CHAIN_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_chain_mode { + CDS_ONE_ONE = 0, + CDS_TWO_TWO, + CDS_MAX_NO_OF_CHAIN_MODE +}; + +/** + * enum cds_conc_priority_mode - t/p, powersave, latency. + * + * @CDS_THROUGHPUT: t/p is the priority + * @CDS_POWERSAVE: powersave is the priority + * @CDS_LATENCY: latency is the priority + * @CDS_MAX_CONC_PRIORITY_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_conc_priority_mode { + CDS_THROUGHPUT = 0, + CDS_POWERSAVE, + CDS_LATENCY, + CDS_MAX_CONC_PRIORITY_MODE +}; + +/** + * enum cds_con_mode - concurrency mode for PCL table + * + * @CDS_STA_MODE: station mode + * @CDS_SAP_MODE: SAP mode + * @CDS_P2P_CLIENT_MODE: P2P client mode + * @CDS_P2P_GO_MODE: P2P Go mode + * @CDS_IBSS_MODE: IBSS mode + * @CDS_MAX_NUM_OF_MODE: max value place holder + */ +enum cds_con_mode { + CDS_STA_MODE = 0, + CDS_SAP_MODE, + CDS_P2P_CLIENT_MODE, + CDS_P2P_GO_MODE, + CDS_IBSS_MODE, + CDS_MAX_NUM_OF_MODE +}; + +/** + * enum cds_pcl_type - Various types of Preferred channel list (PCL). + * + * @CDS_NONE: No channel preference + * @CDS_24G: 2.4 Ghz channels only + * @CDS_5G: 5 Ghz channels only + * @CDS_SCC_CH: SCC channel only + * @CDS_MCC_CH: MCC channels only + * @CDS_SCC_CH_24G: SCC channel & 2.4 Ghz channels + * @CDS_SCC_CH_5G: SCC channel & 5 Ghz channels + * @CDS_24G_SCC_CH: 2.4 Ghz channels & SCC channel + * @CDS_5G_SCC_CH: 5 Ghz channels & SCC channel + * @CDS_SCC_ON_5_SCC_ON_24_24G: SCC channel on 5 Ghz, SCC + * channel on 2.4 Ghz & 2.4 Ghz channels + * @CDS_SCC_ON_5_SCC_ON_24_5G: SCC channel on 5 Ghz, SCC channel + * on 2.4 Ghz & 5 Ghz channels + * @CDS_SCC_ON_24_SCC_ON_5_24G: SCC channel on 2.4 Ghz, SCC + * channel on 5 Ghz & 2.4 Ghz channels + * @CDS_SCC_ON_24_SCC_ON_5_5G: SCC channel on 2.4 Ghz, SCC + * channel on 5 Ghz & 5 Ghz channels + * @CDS_SCC_ON_5_SCC_ON_24: SCC channel on 5 Ghz, SCC channel on + * 2.4 Ghz + * @CDS_SCC_ON_24_SCC_ON_5: SCC channel on 2.4 Ghz, SCC channel + * on 5 Ghz + * @CDS_MCC_CH_24G: MCC channels & 2.4 Ghz channels + * @CDS_MCC_CH_5G: MCC channels & 5 Ghz channels + * @CDS_24G_MCC_CH: 2.4 Ghz channels & MCC channels + * @CDS_5G_MCC_CH: 5 Ghz channels & MCC channels + * @CDS_MAX_PCL_TYPE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_pcl_type { + CDS_NONE = 0, + CDS_24G, + CDS_5G, + CDS_SCC_CH, + CDS_MCC_CH, + CDS_SCC_CH_24G, + CDS_SCC_CH_5G, + CDS_24G_SCC_CH, + CDS_5G_SCC_CH, + CDS_SCC_ON_5_SCC_ON_24_24G, + CDS_SCC_ON_5_SCC_ON_24_5G, + CDS_SCC_ON_24_SCC_ON_5_24G, + CDS_SCC_ON_24_SCC_ON_5_5G, + CDS_SCC_ON_5_SCC_ON_24, + CDS_SCC_ON_24_SCC_ON_5, + CDS_MCC_CH_24G, + CDS_MCC_CH_5G, + CDS_24G_MCC_CH, + CDS_5G_MCC_CH, + + CDS_MAX_PCL_TYPE +}; + +/** + * enum cds_one_connection_mode - Combination of first connection + * type, band & spatial stream used. + * + * @CDS_STA_24_1x1: STA connection using 1x1@2.4 Ghz + * @CDS_STA_24_2x2: STA connection using 2x2@2.4 Ghz + * @CDS_STA_5_1x1: STA connection using 1x1@5 Ghz + * @CDS_STA_5_2x2: STA connection using 2x2@5 Ghz + * @CDS_P2P_CLI_24_1x1: P2P Client connection using 1x1@2.4 Ghz + * @CDS_P2P_CLI_24_2x2: P2P Client connection using 2x2@2.4 Ghz + * @CDS_P2P_CLI_5_1x1: P2P Client connection using 1x1@5 Ghz + * @CDS_P2P_CLI_5_2x2: P2P Client connection using 2x2@5 Ghz + * @CDS_P2P_GO_24_1x1: P2P GO connection using 1x1@2.4 Ghz + * @CDS_P2P_GO_24_2x2: P2P GO connection using 2x2@2.4 Ghz + * @CDS_P2P_GO_5_1x1: P2P GO connection using 1x1@5 Ghz + * @CDS_P2P_GO_5_2x2: P2P GO connection using 2x2@5 Ghz + * @CDS_SAP_24_1x1: SAP connection using 1x1@2.4 Ghz + * @CDS_SAP_24_2x2: SAP connection using 2x2@2.4 Ghz + * @CDS_SAP_5_1x1: SAP connection using 1x1@5 Ghz + * @CDS_SAP_5_1x1: SAP connection using 2x2@5 Ghz + * @CDS_IBSS_24_1x1: IBSS connection using 1x1@2.4 Ghz + * @CDS_IBSS_24_2x2: IBSS connection using 2x2@2.4 Ghz + * @CDS_IBSS_5_1x1: IBSS connection using 1x1@5 Ghz + * @CDS_IBSS_5_2x2: IBSS connection using 2x2@5 Ghz + * @CDS_MAX_ONE_CONNECTION_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_one_connection_mode { + CDS_STA_24_1x1 = 0, + CDS_STA_24_2x2, + CDS_STA_5_1x1, + CDS_STA_5_2x2, + CDS_P2P_CLI_24_1x1, + CDS_P2P_CLI_24_2x2, + CDS_P2P_CLI_5_1x1, + CDS_P2P_CLI_5_2x2, + CDS_P2P_GO_24_1x1, + CDS_P2P_GO_24_2x2, + CDS_P2P_GO_5_1x1, + CDS_P2P_GO_5_2x2, + CDS_SAP_24_1x1, + CDS_SAP_24_2x2, + CDS_SAP_5_1x1, + CDS_SAP_5_2x2, + CDS_IBSS_24_1x1, + CDS_IBSS_24_2x2, + CDS_IBSS_5_1x1, + CDS_IBSS_5_2x2, + + CDS_MAX_ONE_CONNECTION_MODE +}; + +/** + * enum cds_two_connection_mode - Combination of first two + * connections type, concurrency state, band & spatial stream + * used. + * + * @CDS_STA_SAP_SCC_24_1x1: STA & SAP connection on SCC using + * 1x1@2.4 Ghz + * @CDS_STA_SAP_SCC_24_2x2: STA & SAP connection on SCC using + * 2x2@2.4 Ghz + * @CDS_STA_SAP_MCC_24_1x1: STA & SAP connection on MCC using + * 1x1@2.4 Ghz + * @CDS_STA_SAP_MCC_24_2x2: STA & SAP connection on MCC using + * 2x2@2.4 Ghz + * @CDS_STA_SAP_SCC_5_1x1: STA & SAP connection on SCC using + * 1x1@5 Ghz + * @CDS_STA_SAP_SCC_5_2x2: STA & SAP connection on SCC using + * 2x2@5 Ghz + * @CDS_STA_SAP_MCC_5_1x1: STA & SAP connection on MCC using + * 1x1@5 Ghz + * @CDS_STA_SAP_MCC_5_2x2: STA & SAP connection on MCC using + * 2x2@5 Ghz + * @CDS_STA_SAP_DBS_1x1,: STA & SAP connection on DBS using 1x1 + * @CDS_STA_P2P_GO_SCC_24_1x1: STA & P2P GO connection on SCC + * using 1x1@2.4 Ghz + * @CDS_STA_P2P_GO_SCC_24_2x2: STA & P2P GO connection on SCC + * using 2x2@2.4 Ghz + * @CDS_STA_P2P_GO_MCC_24_1x1: STA & P2P GO connection on MCC + * using 1x1@2.4 Ghz + * @CDS_STA_P2P_GO_MCC_24_2x2: STA & P2P GO connection on MCC + * using 2x2@2.4 Ghz + * @CDS_STA_P2P_GO_SCC_5_1x1: STA & P2P GO connection on SCC + * using 1x1@5 Ghz + * @CDS_STA_P2P_GO_SCC_5_2x2: STA & P2P GO connection on SCC + * using 2x2@5 Ghz + * @CDS_STA_P2P_GO_MCC_5_1x1: STA & P2P GO connection on MCC + * using 1x1@5 Ghz + * @CDS_STA_P2P_GO_MCC_5_2x2: STA & P2P GO connection on MCC + * using 2x2@5 Ghz + * @CDS_STA_P2P_GO_DBS_1x1: STA & P2P GO connection on DBS using + * 1x1 + * @CDS_STA_P2P_CLI_SCC_24_1x1: STA & P2P CLI connection on SCC + * using 1x1@2.4 Ghz + * @CDS_STA_P2P_CLI_SCC_24_2x2: STA & P2P CLI connection on SCC + * using 2x2@2.4 Ghz + * @CDS_STA_P2P_CLI_MCC_24_1x1: STA & P2P CLI connection on MCC + * using 1x1@2.4 Ghz + * @CDS_STA_P2P_CLI_MCC_24_2x2: STA & P2P CLI connection on MCC + * using 2x2@2.4 Ghz + * @CDS_STA_P2P_CLI_SCC_5_1x1: STA & P2P CLI connection on SCC + * using 1x1@5 Ghz + * @CDS_STA_P2P_CLI_SCC_5_2x2: STA & P2P CLI connection on SCC + * using 2x2@5 Ghz + * @CDS_STA_P2P_CLI_MCC_5_1x1: STA & P2P CLI connection on MCC + * using 1x1@5 Ghz + * @CDS_STA_P2P_CLI_MCC_5_2x2: STA & P2P CLI connection on MCC + * using 2x2@5 Ghz + * @CDS_STA_P2P_CLI_DBS_1x1: STA & P2P CLI connection on DBS + * using 1x1 + * @CDS_P2P_GO_P2P_CLI_SCC_24_1x1: P2P GO & CLI connection on + * SCC using 1x1@2.4 Ghz + * @CDS_P2P_GO_P2P_CLI_SCC_24_2x2: P2P GO & CLI connection on + * SCC using 2x2@2.4 Ghz + * @CDS_P2P_GO_P2P_CLI_MCC_24_1x1: P2P GO & CLI connection on + * MCC using 1x1@2.4 Ghz + * @CDS_P2P_GO_P2P_CLI_MCC_24_2x2: P2P GO & CLI connection on + * MCC using 2x2@2.4 Ghz + * @CDS_P2P_GO_P2P_CLI_SCC_5_1x1: P2P GO & CLI connection on + * SCC using 1x1@5 Ghz + * @CDS_P2P_GO_P2P_CLI_SCC_5_2x2: P2P GO & CLI connection on + * SCC using 2x2@5 Ghz + * @CDS_P2P_GO_P2P_CLI_MCC_5_1x1: P2P GO & CLI connection on + * MCC using 1x1@5 Ghz + * @CDS_P2P_GO_P2P_CLI_MCC_5_2x2: P2P GO & CLI connection on + * MCC using 2x2@5 Ghz + * @CDS_P2P_GO_P2P_CLI_DBS_1x1: P2P GO & CLI connection on DBS + * using 1x1 + * @CDS_P2P_GO_SAP_SCC_24_1x1: P2P GO & SAP connection on + * SCC using 1x1@2.4 Ghz + * @CDS_P2P_GO_SAP_SCC_24_2x2: P2P GO & SAP connection on + * SCC using 2x2@2.4 Ghz + * @CDS_P2P_GO_SAP_MCC_24_1x1: P2P GO & SAP connection on + * MCC using 1x1@2.4 Ghz + * @CDS_P2P_GO_SAP_MCC_24_2x2: P2P GO & SAP connection on + * MCC using 2x2@2.4 Ghz + * @CDS_P2P_GO_SAP_SCC_5_1x1: P2P GO & SAP connection on + * SCC using 1x1@5 Ghz + * @CDS_P2P_GO_SAP_SCC_5_2x2: P2P GO & SAP connection on + * SCC using 2x2@5 Ghz + * @CDS_P2P_GO_SAP_MCC_5_1x1: P2P GO & SAP connection on + * MCC using 1x1@5 Ghz + * @CDS_P2P_GO_SAP_MCC_5_2x2: P2P GO & SAP connection on + * MCC using 2x2@5 Ghz + * @CDS_P2P_GO_SAP_DBS_1x1: P2P GO & SAP connection on DBS using + * 1x1 + * @CDS_MAX_TWO_CONNECTION_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_two_connection_mode { + CDS_STA_SAP_SCC_24_1x1 = 0, + CDS_STA_SAP_SCC_24_2x2, + CDS_STA_SAP_MCC_24_1x1, + CDS_STA_SAP_MCC_24_2x2, + CDS_STA_SAP_SCC_5_1x1, + CDS_STA_SAP_SCC_5_2x2, + CDS_STA_SAP_MCC_5_1x1, + CDS_STA_SAP_MCC_5_2x2, + CDS_STA_SAP_MCC_24_5_1x1, + CDS_STA_SAP_MCC_24_5_2x2, + CDS_STA_SAP_DBS_1x1, + CDS_STA_P2P_GO_SCC_24_1x1, + CDS_STA_P2P_GO_SCC_24_2x2, + CDS_STA_P2P_GO_MCC_24_1x1, + CDS_STA_P2P_GO_MCC_24_2x2, + CDS_STA_P2P_GO_SCC_5_1x1, + CDS_STA_P2P_GO_SCC_5_2x2, + CDS_STA_P2P_GO_MCC_5_1x1, + CDS_STA_P2P_GO_MCC_5_2x2, + CDS_STA_P2P_GO_MCC_24_5_1x1, + CDS_STA_P2P_GO_MCC_24_5_2x2, + CDS_STA_P2P_GO_DBS_1x1, + CDS_STA_P2P_CLI_SCC_24_1x1, + CDS_STA_P2P_CLI_SCC_24_2x2, + CDS_STA_P2P_CLI_MCC_24_1x1, + CDS_STA_P2P_CLI_MCC_24_2x2, + CDS_STA_P2P_CLI_SCC_5_1x1, + CDS_STA_P2P_CLI_SCC_5_2x2, + CDS_STA_P2P_CLI_MCC_5_1x1, + CDS_STA_P2P_CLI_MCC_5_2x2, + CDS_STA_P2P_CLI_MCC_24_5_1x1, + CDS_STA_P2P_CLI_MCC_24_5_2x2, + CDS_STA_P2P_CLI_DBS_1x1, + CDS_P2P_GO_P2P_CLI_SCC_24_1x1, + CDS_P2P_GO_P2P_CLI_SCC_24_2x2, + CDS_P2P_GO_P2P_CLI_MCC_24_1x1, + CDS_P2P_GO_P2P_CLI_MCC_24_2x2, + CDS_P2P_GO_P2P_CLI_SCC_5_1x1, + CDS_P2P_GO_P2P_CLI_SCC_5_2x2, + CDS_P2P_GO_P2P_CLI_MCC_5_1x1, + CDS_P2P_GO_P2P_CLI_MCC_5_2x2, + CDS_P2P_GO_P2P_CLI_MCC_24_5_1x1, + CDS_P2P_GO_P2P_CLI_MCC_24_5_2x2, + CDS_P2P_GO_P2P_CLI_DBS_1x1, + CDS_P2P_GO_SAP_SCC_24_1x1, + CDS_P2P_GO_SAP_SCC_24_2x2, + CDS_P2P_GO_SAP_MCC_24_1x1, + CDS_P2P_GO_SAP_MCC_24_2x2, + CDS_P2P_GO_SAP_SCC_5_1x1, + CDS_P2P_GO_SAP_SCC_5_2x2, + CDS_P2P_GO_SAP_MCC_5_1x1, + CDS_P2P_GO_SAP_MCC_5_2x2, + CDS_P2P_GO_SAP_MCC_24_5_1x1, + CDS_P2P_GO_SAP_MCC_24_5_2x2, + CDS_P2P_GO_SAP_DBS_1x1, + + CDS_MAX_TWO_CONNECTION_MODE +}; + +/** + * enum cds_conc_next_action - actions to be taken on old + * connections. + * + * @CDS_NOP: No action + * @CDS_DBS: switch to DBS mode + * @CDS_DBS_DOWNGRADE: switch to DBS mode & downgrade to 1x1 + * @CDS_MCC: switch to MCC/SCC mode + * @CDS_MCC_UPGRADE: switch to MCC/SCC mode & upgrade to 2x2 + * @CDS_MAX_CONC_PRIORITY_MODE: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_conc_next_action { + CDS_NOP = 0, + CDS_DBS, + CDS_DBS_DOWNGRADE, + CDS_MCC, + CDS_MCC_UPGRADE, + CDS_MAX_CONC_NEXT_ACTION +}; + +/** + * enum cds_band - wifi band. + * + * @CDS_BAND_24: 2.4 Ghz band + * @CDS_BAND_5: 5 Ghz band + * @CDS_MAX_BAND: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum cds_band { + CDS_BAND_24 = 0, + CDS_BAND_5, + CDS_MAX_BAND +}; + +/** + * struct cds_conc_connection_info - information of all existing + * connections in the wlan system + * + * @mode: connection type + * @chan: channel of the connection + * @mac: The HW mac it is running + * @tx_spatial_stream: Tx spatial stream used by the connection + * @rx_spatial_stream: Tx spatial stream used by the connection + * @original_nss: nss negotiated at connection time + * @vdev_id: vdev id of the connection + * @in_use: if the table entry is active + */ +struct cds_conc_connection_info { + enum cds_con_mode mode; + uint8_t chan; + uint8_t mac; + enum cds_chain_mode chain_mask; + uint8_t tx_spatial_stream; + uint8_t rx_spatial_stream; + uint32_t original_nss; + uint32_t vdev_id; + bool in_use; +}; + +bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx); +void cds_dump_concurrency_info(hdd_context_t *pHddCtx); +void cds_set_concurrency_mode(hdd_context_t *pHddCtx, tCDF_CON_MODE mode); +void cds_clear_concurrency_mode(hdd_context_t *pHddCtx, + tCDF_CON_MODE mode); +uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); +/** + * cds_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 +cds_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; +} + +/** + * cds_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 +cds_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); +} + +/** + * cds_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 +cds_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; +} + +/** + * cds_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 +cds_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); +} + +/** + * cds_set_connection_in_progress() - to set the connection in progress flag + * @hdd_ctx: pointer to hdd context + * @value: value to set + * + * This function will set the passed value to connection in progress flag. + * If value is previously being set to true then no need to set it again. + * + * Return: true if value is being set correctly and false otherwise. + */ +static inline bool +cds_set_connection_in_progress(hdd_context_t *hdd_ctx, + bool value) +{ + bool status = true; + spin_lock(&hdd_ctx->connection_status_lock); + /* + * if the value is set to true previously and if someone is + * trying to make it true again then it could be some race + * condition being triggered. Avoid this situation by returning + * false + */ + if (hdd_ctx->connection_in_progress && value) + status = false; + else + hdd_ctx->connection_in_progress = value; + spin_unlock(&hdd_ctx->connection_status_lock); + return status; +} + + +int cds_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); +uint32_t cds_get_concurrency_mode(void); +CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, + eCsrRoamResult roam_result, + hdd_station_ctx_t *hdd_sta_ctx); +void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile); +#ifdef FEATURE_WLAN_CH_AVOID +bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile, + uint32_t *roam_id); +#else +static inline bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile, + uint32_t *roam_id) +{ + return true; +} +#endif /* FEATURE_WLAN_CH_AVOID */ +bool cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC +void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result); +#else +static inline void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, + eCsrRoamResult roam_result) +{ + +} +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +void cds_check_concurrent_intf_and_restart_sap( + hdd_context_t *hdd_ctx, + hdd_station_ctx_t *hdd_sta_ctx, + hdd_adapter_t *adapter); +#else +static inline void cds_check_concurrent_intf_and_restart_sap( + hdd_context_t *hdd_ctx, + hdd_station_ctx_t *hdd_sta_ctx, + hdd_adapter_t *adapter) +{ + +} +#endif /* FEATURE_WLAN_MCC_TO_SCC_SWITCH */ +uint8_t cds_is_mcc_in_24G(hdd_context_t *hdd_ctx); +int32_t cds_set_mas(hdd_adapter_t *adapter, uint8_t mas_value); +int cds_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, + uint32_t set_value); +CDF_STATUS cds_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter); +int cds_go_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, + uint32_t set_value); +void cds_set_mcc_latency(hdd_adapter_t *adapter, int set_value); +#if defined(FEATURE_WLAN_MCC_TO_SCC_SWITCH) || \ + defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) +void cds_restart_sap(hdd_adapter_t *ap_adapter); +#else +static inline void cds_restart_sap(hdd_adapter_t *ap_adapter) +{ + +} +#endif /* FEATURE_WLAN_MCC_TO_SCC_SWITCH || + * FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + */ + +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE +void cds_check_and_restart_sap_with_non_dfs_acs(hdd_context_t *hdd_ctx); +#else +static inline void cds_check_and_restart_sap_with_non_dfs_acs( + hdd_context_t *hdd_ctx) +{ + +} +#endif /* FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE */ +void cds_incr_active_session(hdd_context_t *pHddCtx, tCDF_CON_MODE mode, + uint8_t sessionId); +void cds_decr_active_session(hdd_context_t *pHddCtx, tCDF_CON_MODE mode, + uint8_t sessionId); +void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, + tCDF_CON_MODE mode, + uint8_t session_id); +CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx); +CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, + uint8_t *pcl_Channels, uint32_t *len); +bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, + uint8_t channel, enum hw_mode_bandwidth bw); +enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( + hdd_context_t *hdd_ctx); +enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( + hdd_context_t *hdd_ctx); +enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( + hdd_context_t *hdd_ctx); +CDF_STATUS cds_mode_switch_dbs_to_mcc(hdd_context_t *hdd_ctx); +CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx); +CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, + uint32_t vdev_id); +CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, + uint32_t vdev_id); +CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, + uint32_t vdev_id); +CDF_STATUS cds_current_connections_update( + hdd_context_t *hdd_ctx, uint8_t channel); +#ifdef MPC_UT_FRAMEWORK +CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, + uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id); +CDF_STATUS cds_update_connection_info_utfw(hdd_context_t *hdd_ctx, + uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id); +CDF_STATUS cds_decr_connection_count_utfw(hdd_context_t *hdd_ctx, + uint32_t del_all, uint32_t vdev_id); +struct cds_conc_connection_info *cds_get_conn_info(hdd_context_t *hdd_ctx, + uint32_t *len); +enum cds_pcl_type get_pcl_from_first_conn_table( + enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref); +enum cds_pcl_type get_pcl_from_second_conn_table( + enum cds_one_connection_mode idx, enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref, uint8_t dbs_capable); +enum cds_pcl_type get_pcl_from_third_conn_table( + enum cds_two_connection_mode idx, enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref, uint8_t dbs_capable); +#else +static inline CDF_STATUS cds_incr_connection_count_utfw( + hdd_context_t *hdd_ctx, uint32_t vdev_id, + uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id) +{ + return CDF_STATUS_SUCCESS; +} +static inline CDF_STATUS cds_update_connection_info_utfw( + hdd_context_t *hdd_ctx, uint32_t vdev_id, + uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id) +{ + return CDF_STATUS_SUCCESS; +} +static inline CDF_STATUS cds_decr_connection_count_utfw( + hdd_context_t *hdd_ctx, + uint32_t del_all, uint32_t vdev_id) +{ + return CDF_STATUS_SUCCESS; +} +static inline struct cds_conc_connection_info *cds_get_conn_info( + hdd_context_t *hdd_ctx, uint32_t *len) +{ + return NULL; +} +#endif +enum cds_con_mode cds_convert_device_mode_to_hdd_type( + device_mode_t device_mode); +uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); +CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + enum hw_mode_ss_config mac0_ss, + enum hw_mode_bandwidth mac0_bw, + enum hw_mode_ss_config mac1_ss, + enum hw_mode_bandwidth mac1_bw, + enum hw_mode_dbs_capab dbs, + enum hw_mode_agile_dfs_capab dfs); +enum cds_conc_next_action cds_need_opportunistic_upgrade( + hdd_context_t *hdd_ctx); +CDF_STATUS cds_next_actions( + hdd_context_t *hdd_ctx, enum cds_conc_next_action action); +void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, + uint8_t dbs_val, + uint8_t dbs_plus_agile_scan_val, + uint8_t single_mac_scan_with_dbs_val); +void cds_set_dual_mac_fw_mode_config(hdd_context_t *hdd_ctx, + uint8_t dbs, + uint8_t dfs); +void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, + uint32_t scan_config, + uint32_t fw_mode_config); +bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, + tCDF_CON_MODE *old_mode, enum cds_con_mode *new_mode); +CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile, uint8_t *channel); +#endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/inc/cds_crypto.h b/core/cds/inc/cds_crypto.h new file mode 100644 index 000000000000..7df3b7dd7076 --- /dev/null +++ b/core/cds/inc/cds_crypto.h @@ -0,0 +1,183 @@ +/* + * 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(__CDS_CRYPTO_H) +#define __CDS_CRYPTO_H + +/** + * DOC: cds_crypto.h + * + * Crypto APIs + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#include +#endif + +#ifdef CONFIG_CNSS +static inline struct crypto_ahash *cds_crypto_alloc_ahash(const char *alg_name, + u32 type, u32 mask) +{ + return wcnss_wlan_crypto_alloc_ahash(alg_name, type, mask); +} +#else +static inline struct crypto_ahash *cds_crypto_alloc_ahash(const char *alg_name, + u32 type, u32 mask) +{ + return crypto_alloc_ahash(alg_name, type, mask); +} +#endif + +#ifdef CONFIG_CNSS +static inline struct crypto_cipher * +cds_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask) +{ + return wcnss_wlan_crypto_alloc_cipher(alg_name, type, mask); +} +#else +static inline struct crypto_cipher * +cds_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask) +{ + return crypto_alloc_cipher(alg_name, type, mask); +} +#endif + +#ifdef CONFIG_CNSS +static inline void cds_cmac_calc_mic(struct crypto_cipher *tfm, u8 *m, + u16 length, u8 *mac) +{ + wcnss_wlan_cmac_calc_mic(tfm, m, length, mac); +} +#endif + +#ifdef CONFIG_CNSS +static inline void cds_crypto_free_cipher(struct crypto_cipher *tfm) +{ + wcnss_wlan_crypto_free_cipher(tfm); +} +#else +static inline void cds_crypto_free_cipher(struct crypto_cipher *tfm) +{ + crypto_free_cipher(tfm); +} +#endif + +#ifdef CONFIG_CNSS +static inline void cds_crypto_free_ahash(struct crypto_ahash *tfm) +{ + wcnss_wlan_crypto_free_ahash(tfm); +} +#else +static inline void cds_crypto_free_ahash(struct crypto_ahash *tfm) +{ + crypto_free_ahash(tfm); +} +#endif + +#ifdef CONFIG_CNSS +static inline int cds_crypto_ahash_setkey(struct crypto_ahash *tfm, + const u8 *key, unsigned int keylen) +{ + return wcnss_wlan_crypto_ahash_setkey(tfm, key, keylen); +} +#else +static inline int cds_crypto_ahash_setkey(struct crypto_ahash *tfm, + const u8 *key, unsigned int keylen) +{ + return crypto_ahash_setkey(tfm, key, keylen); +} +#endif + +#ifdef CONFIG_CNSS +static inline int cds_crypto_ahash_digest(struct ahash_request *req) +{ + return wcnss_wlan_crypto_ahash_digest(req); +} +#else +static inline int cds_crypto_ahash_digest(struct ahash_request *req) +{ + return crypto_ahash_digest(req); +} +#endif + +#ifdef CONFIG_CNSS +static inline struct crypto_ablkcipher * +cds_crypto_alloc_ablkcipher(const char *alg_name, u32 type, u32 mask) +{ + return wcnss_wlan_crypto_alloc_ablkcipher(alg_name, type, mask); +} +#else +static inline struct crypto_ablkcipher * +cds_crypto_alloc_ablkcipher(const char *alg_name, u32 type, u32 mask) +{ + return crypto_alloc_ablkcipher(alg_name, type, mask); +} +#endif + +#ifdef CONFIG_CNSS +static inline void cds_ablkcipher_request_free(struct ablkcipher_request *req) +{ + wcnss_wlan_ablkcipher_request_free(req); +} +#else +static inline void cds_ablkcipher_request_free(struct ablkcipher_request *req) +{ + ablkcipher_request_free(req); +} +#endif + +#ifdef CONFIG_CNSS +static inline void cds_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm) +{ + wcnss_wlan_crypto_free_ablkcipher(tfm); +} +#else +static inline void cds_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm) +{ + crypto_free_ablkcipher(tfm); +} +#endif + +#endif /* if !defined __CDS_CRYPTO_H */ diff --git a/core/cds/inc/cds_get_bin.h b/core/cds/inc/cds_get_bin.h new file mode 100644 index 000000000000..a561e955148c --- /dev/null +++ b/core/cds/inc/cds_get_bin.h @@ -0,0 +1,75 @@ +/* + * 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( __CDS_GETBIN_H ) +#define __CDS_GETBIN_H + +/**========================================================================= + + \file cds_getBin.h + + \brief Connectivity driver services (CDS) 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. + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/**---------------------------------------------------------------------------- + \brief cds_get_conparam()- function to read the insmod parameters + -----------------------------------------------------------------------------*/ +tCDF_CON_MODE cds_get_conparam(void); +bool cds_concurrent_open_sessions_running(void); +bool cds_max_concurrent_connections_reached(void); +void cds_clear_concurrent_session_count(void); +bool cds_is_multiple_active_sta_sessions(void); +bool cds_is_sta_active_connection_exists(void); + +#ifdef WLAN_FEATURE_MBSSID +bool cds_concurrent_beaconing_sessions_running(void); +#endif +#endif /* !defined __CDS_GETBIN_H */ diff --git a/core/cds/inc/cds_ieee80211_common.h b/core/cds/inc/cds_ieee80211_common.h new file mode 100644 index 000000000000..9b8faf7575c6 --- /dev/null +++ b/core/cds/inc/cds_ieee80211_common.h @@ -0,0 +1,2105 @@ +/* + * 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 EXTERNAL_USE_ONLY +#include "osdep.h" +#endif /* EXTERNAL_USE_ONLY */ +#include "cds_ieee80211_common_i.h" + +#ifndef CDS_COMMON_IEEE80211_H_ +#define CDS_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 { + uint16_t i_sfd; + uint8_t i_signal; + uint8_t i_service; + uint16_t i_length; + uint16_t i_crc; +} __packed; + +#define IEEE80211_PLCP_SFD 0xF3A0 +#define IEEE80211_PLCP_SERVICE 0x00 + +/* + * generic definitions for IEEE 802.11 frames + */ +struct ieee80211_frame { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + union { + struct { + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + }; + uint8_t i_addr_all[3 * IEEE80211_ADDR_LEN]; + }; + uint8_t i_seq[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; + +struct ieee80211_qosframe { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + uint8_t i_seq[2]; + uint8_t i_qos[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; + +struct ieee80211_qoscntl { + uint8_t i_qos[2]; +}; + +struct ieee80211_frame_addr4 { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + uint8_t i_seq[2]; + uint8_t i_addr4[IEEE80211_ADDR_LEN]; +} __packed; + +struct ieee80211_qosframe_addr4 { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + uint8_t i_seq[2]; + uint8_t i_addr4[IEEE80211_ADDR_LEN]; + uint8_t i_qos[2]; +} __packed; + +/* HTC frame for TxBF*/ +/* for TxBF RC */ +struct ieee80211_frame_min_one { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + +} __packed; /* For TxBF RC */ + +struct ieee80211_qosframe_htc { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + uint8_t i_seq[2]; + uint8_t i_qos[2]; + uint8_t i_htc[4]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __packed; +struct ieee80211_qosframe_htc_addr4 { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_t i_addr2[IEEE80211_ADDR_LEN]; + uint8_t i_addr3[IEEE80211_ADDR_LEN]; + uint8_t i_seq[2]; + uint8_t i_addr4[IEEE80211_ADDR_LEN]; + uint8_t i_qos[2]; + uint8_t i_htc[4]; +} __packed; +struct ieee80211_htc { + uint8_t i_htc[4]; +}; +/*HTC frame for TxBF*/ + +struct ieee80211_ctlframe_addr2 { + uint8_t i_fc[2]; + uint8_t i_aidordur[2]; /* AID or duration */ + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_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 { + uint8_t element_id; /* Element Id */ + uint8_t length; /* IE Length */ +} __packed; + +/* + * Country information element. + */ +#define IEEE80211_COUNTRY_MAX_TRIPLETS (83) +struct ieee80211_ie_country { + uint8_t country_id; + uint8_t country_len; + uint8_t country_str[3]; + uint8_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 { + uint8_t wme_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t wme_len; /* length in bytes */ + uint8_t wme_oui[3]; /* 0x00, 0x50, 0xf2 */ + uint8_t wme_type; /* OUI type */ + uint8_t wme_subtype; /* OUI subtype */ + uint8_t wme_version; /* spec revision */ + uint8_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 { + uint8_t one : 1, direction : 2, tid : 4, reserved1 : 1; + uint8_t reserved2 : 2, dot1Dtag : 3, psb : 1, reserved3 : 1, zero : 1; + uint8_t reserved5 : 7, reserved4 : 1; +} __packed; +#else +struct ieee80211_tsinfo_bitmap { + uint8_t reserved1 : 1, tid : 4, direction : 2, one : 1; + uint8_t zero : 1, reserved3 : 1, psb : 1, dot1Dtag : 3, reserved2 : 2; + uint8_t reserved4 : 1, reserved5 : 7; +} __packed; +#endif + +/* + * WME/802.11e Tspec Element + */ +struct ieee80211_wme_tspec { + uint8_t ts_id; + uint8_t ts_len; + uint8_t ts_oui[3]; + uint8_t ts_oui_type; + uint8_t ts_oui_subtype; + uint8_t ts_version; + uint8_t ts_tsinfo[3]; + uint8_t ts_nom_msdu[2]; + uint8_t ts_max_msdu[2]; + uint8_t ts_min_svc[4]; + uint8_t ts_max_svc[4]; + uint8_t ts_inactv_intv[4]; + uint8_t ts_susp_intv[4]; + uint8_t ts_start_svc[4]; + uint8_t ts_min_rate[4]; + uint8_t ts_mean_rate[4]; + uint8_t ts_peak_rate[4]; + uint8_t ts_max_burst[4]; + uint8_t ts_delay[4]; + uint8_t ts_min_phy[4]; + uint8_t ts_surplus[2]; + uint8_t ts_medium_time[2]; +} __packed; + +/* + * WME AC parameter field + */ +struct ieee80211_wme_acparams { + uint8_t acp_aci_aifsn; + uint8_t acp_logcwminmax; + uint16_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 { + uint8_t param_id; + uint8_t param_len; + uint8_t param_oui[3]; + uint8_t param_oui_type; + uint8_t param_oui_sybtype; + uint8_t param_version; + uint8_t param_qosInfo; + uint8_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 { + uint8_t athAdvCap_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t athAdvCap_len; /* length in bytes */ + uint8_t athAdvCap_oui[3]; /* 0x00, 0x03, 0x7f */ + uint8_t athAdvCap_type; /* OUI type */ + uint16_t athAdvCap_version; /* spec revision */ + uint8_t athAdvCap_capability; /* Capability info */ + uint16_t athAdvCap_defKeyIndex; +} __packed; + +/* + * Atheros Extended Capability information element. + */ +struct ieee80211_ie_ath_extcap { + uint8_t ath_extcap_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t ath_extcap_len; /* length in bytes */ + uint8_t ath_extcap_oui[3]; /* 0x00, 0x03, 0x7f */ + uint8_t ath_extcap_type; /* OUI type */ + uint8_t ath_extcap_subtype; /* OUI subtype */ + uint8_t ath_extcap_version; /* spec revision */ + uint32_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 { + uint8_t param_id; + uint8_t param_len; + uint8_t param_oui[3]; + uint8_t param_oui_type; + uint8_t param_oui_sybtype; + uint8_t param_version; + uint8_t param_Info; + uint8_t param_base_bssid[IEEE80211_ADDR_LEN]; + uint8_t param_xr_bssid[IEEE80211_ADDR_LEN]; + uint16_t param_xr_beacon_interval; + uint8_t param_base_ath_capability; + uint8_t param_xr_ath_capability; +} __packed; + +/* + * SFA information element. + */ +struct ieee80211_ie_sfa { + uint8_t sfa_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t sfa_len; /* length in bytes */ + uint8_t sfa_oui[3]; /* 0x00, 0x40, 0x96 */ + uint8_t sfa_type; /* OUI type */ + uint8_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 = uint16_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 { + uint16_t ess : 1; + uint16_t ibss : 1; + uint16_t cf_pollable : 1; + uint16_t cf_poll_request : 1; + uint16_t privacy : 1; + uint16_t short_preamble : 1; + uint16_t pbcc : 1; + uint16_t channel_agility : 1; + uint16_t spectrum_management : 1; + uint16_t qos : 1; + uint16_t short_slot_time : 1; + uint16_t apsd : 1; + uint16_t reserved2 : 1; + uint16_t dsss_ofdm : 1; + uint16_t del_block_ack : 1; + uint16_t immed_block_ack : 1; + }; + + uint16_t value; +} __packed; + +struct ieee80211_beacon_frame { + uint8_t timestamp[8]; /* the value of sender's TSFTIMER */ + uint16_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 { + uint8_t ia_category; + uint8_t ia_action; +} __packed; + +/* spectrum action frame header */ +struct ieee80211_action_measrep_header { + struct ieee80211_action action_header; + uint8_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; + uint8_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; + uint8_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; + uint8_t mimo_control[MIMO_CONTROL_LEN]; +} __packed; + +/*HT - V/CV report frame*/ +struct ieee80211_action_ht_txbf_rpt { + struct ieee80211_action as_header; + uint8_t mimo_control[MIMO_CONTROL_LEN]; +} __packed; + +/* + * 802.11ac Operating Mode Notification + */ +struct ieee80211_ie_op_mode { +#if _BYTE_ORDER == _BIG_ENDIAN + uint8_t rx_nss_type : 1, rx_nss : 3, reserved : 2, ch_width : 2; +#else + uint8_t ch_width : 2, reserved : 2, rx_nss : 3, rx_nss_type : 1; +#endif +} __packed; + +struct ieee80211_ie_op_mode_ntfy { + uint8_t elem_id; + uint8_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; + uint8_t dst_addr[IEEE80211_ADDR_LEN]; + uint8_t src_addr[IEEE80211_ADDR_LEN]; + uint16_t capa_info; + uint16_t timeout; +} __packed; + +struct ieee80211_dls_response { + struct ieee80211_action hdr; + uint16_t statuscode; + uint8_t dst_addr[IEEE80211_ADDR_LEN]; + uint8_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 + uint16_t buffersize : 10, /* B6-15 buffer size */ + tid : 4, /* B2-5 TID */ + bapolicy : 1, /* B1 block ack policy */ + amsdusupported : 1; /* B0 amsdu supported */ +#else + uint16_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 + uint16_t startseqnum : 12, /* B4-15 starting sequence number */ + fragnum : 4; /* B0-3 fragment number */ +#else + uint16_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 + uint16_t tid : 4, /* B12-15 tid */ + initiator : 1, /* B11 initiator */ + reserved0 : 11; /* B0-10 reserved */ +#else + uint16_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; + uint8_t rq_dialogtoken; + struct ieee80211_ba_parameterset rq_baparamset; + uint16_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; + uint8_t rs_dialogtoken; + uint16_t rs_statuscode; + struct ieee80211_ba_parameterset rs_baparamset; + uint16_t rs_batimeout; /* in TUs */ +} __packed; + +/* BA - DELBA */ +struct ieee80211_action_ba_delba { + struct ieee80211_action dl_header; + struct ieee80211_delba_parameterset dl_delbaparamset; + uint16_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; + uint8_t ts_dialogtoken; + uint8_t ts_statuscode; + struct ieee80211_wme_tspec ts_tspecie; +} __packed; + +/* + * Control frames. + */ +struct ieee80211_frame_min { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_addr1[IEEE80211_ADDR_LEN]; + uint8_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; + uint16_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 { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_ra[IEEE80211_ADDR_LEN]; + uint8_t i_ta[IEEE80211_ADDR_LEN]; + uint16_t i_ctl; + uint16_t i_seq; + /* FCS */ +} __packed; + +struct ieee80211_frame_rts { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_ra[IEEE80211_ADDR_LEN]; + uint8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cts { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_ack { + uint8_t i_fc[2]; + uint8_t i_dur[2]; + uint8_t i_ra[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_pspoll { + uint8_t i_fc[2]; + uint8_t i_aid[2]; + uint8_t i_bssid[IEEE80211_ADDR_LEN]; + uint8_t i_ta[IEEE80211_ADDR_LEN]; + /* FCS */ +} __packed; + +struct ieee80211_frame_cfend { /* NB: also CF-End+CF-Ack */ + uint8_t i_fc[2]; + uint8_t i_dur[2]; /* should be zero */ + uint8_t i_ra[IEEE80211_ADDR_LEN]; + uint8_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 uint8_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 { + uint8_t wpa_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t wpa_len; /* length in bytes */ + uint8_t wpa_oui[3]; /* 0x00, 0x50, 0xf2 */ + uint8_t wpa_type; /* OUI type */ + uint16_t wpa_version; /* spec revision */ + uint32_t wpa_mcipher[1]; /* multicast/group key cipher */ + uint16_t wpa_uciphercnt; /* # pairwise key ciphers */ + uint32_t wpa_uciphers[8]; /* ciphers */ + uint16_t wpa_authselcnt; /* authentication selector cnt */ + uint32_t wpa_authsels[8]; /* selectors */ + uint16_t wpa_caps; /* 802.11i capabilities */ + uint16_t wpa_pmkidcnt; /* 802.11i pmkid count */ + uint16_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 + uint32_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 + uint32_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 + }; + + uint32_t value; +} __packed; +#endif + +struct ieee80211_ie_htcap_cmn { + uint16_t hc_cap; /* HT capabilities */ +#if _BYTE_ORDER == _BIG_ENDIAN + uint8_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 + uint8_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 + uint8_t hc_mcsset[16]; /* supported MCS set */ + uint16_t hc_extcap; /* extended HT capabilities */ +#ifdef ATH_SUPPORT_TxBF + union ieee80211_hc_txbf hc_txbf; /* txbf capabilities */ +#else + uint32_t hc_txbf; /* txbf capabilities */ +#endif + uint8_t hc_antenna; /* antenna capabilities */ +} __packed; + +/* + * 802.11n HT Capability IE + */ +struct ieee80211_ie_htcap { + uint8_t hc_id; /* element ID */ + uint8_t hc_len; /* length in bytes */ + struct ieee80211_ie_htcap_cmn hc_ie; +} __packed; + +/* + * Temporary vendor private HT Capability IE + */ +struct vendor_ie_htcap { + uint8_t hc_id; /* element ID */ + uint8_t hc_len; /* length in bytes */ + uint8_t hc_oui[3]; + uint8_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 { + uint8_t hi_ctrlchannel; /* control channel */ +#if _BYTE_ORDER == _BIG_ENDIAN + uint8_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 + + */ + + uint8_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 */ + + uint8_t hi_reserved0; /* B0-7 (B8-15 in 11n) reserved */ + +/* The following 2 consecutive bytes are defined in word in 80211n spec. */ + + uint8_t hi_dualctsprot : 1, /* B7 dual CTS protection */ + hi_dualbeacon : 1, /* B6 dual beacon */ + hi_reserved2 : 6; /* B0-5 reserved */ + uint8_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 + uint8_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 */ + uint16_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 */ + uint16_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 + uint8_t hi_basicmcsset[16]; /* basic MCS set */ +} __packed; + +/* + * 802.11n HT Information IE + */ +struct ieee80211_ie_htinfo { + uint8_t hi_id; /* element ID */ + uint8_t hi_len; /* length in bytes */ + struct ieee80211_ie_htinfo_cmn hi_ie; +} __packed; + +/* + * Temporary vendor private HT Information IE + */ +struct vendor_ie_htinfo { + uint8_t hi_id; /* element ID */ + uint8_t hi_len; /* length in bytes */ + uint8_t hi_oui[3]; + uint8_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 { + uint8_t tim_ie; /* IEEE80211_ELEMID_TIM */ + uint8_t tim_len; + uint8_t tim_count; /* DTIM count */ + uint8_t tim_period; /* DTIM period */ + uint8_t tim_bitctl; /* bitmap control */ + uint8_t tim_bitmap[1]; /* variable-length bitmap */ +} __packed; +#endif + +/* Country IE channel triplet */ +struct country_ie_triplet { + union { + uint8_t schan; /* starting channel */ + uint8_t regextid; /* Regulatory Extension Identifier */ + }; + union { + uint8_t nchan; /* number of channels */ + uint8_t regclass; /* Regulatory Class */ + }; + union { + uint8_t maxtxpwr; /* tx power */ + uint8_t coverageclass; /* Coverage Class */ + }; +} __packed; + +struct ieee80211_country_ie { + uint8_t ie; /* IEEE80211_ELEMID_COUNTRY */ + uint8_t len; + uint8_t cc[3]; /* ISO CC+(I)ndoor/(O)utdoor */ + struct country_ie_triplet triplet[1]; +} __packed; + +struct ieee80211_fh_ie { + uint8_t ie; /* IEEE80211_ELEMID_FHPARMS */ + uint8_t len; + uint16_t dwell_time; /* endianess?? */ + uint8_t hop_set; + uint8_t hop_pattern; + uint8_t hop_index; +} __packed; + +struct ieee80211_ds_ie { + uint8_t ie; /* IEEE80211_ELEMID_DSPARMS */ + uint8_t len; + uint8_t current_channel; +} __packed; + +struct ieee80211_erp_ie { + uint8_t ie; /* IEEE80211_ELEMID_ERP */ + uint8_t len; + uint8_t value; +} __packed; + +/* TODO -> Need to Check Redefinition Error used in only UMAC */ +#if 0 +struct ieee80211_quiet_ie { + uint8_t ie; /* IEEE80211_ELEMID_QUIET */ + uint8_t len; + uint8_t tbttcount; /* quiet start */ + uint8_t period; /* beacon intervals between quiets */ + uint16_t duration; /* TUs of each quiet */ + uint16_t offset; /* TUs of from TBTT of quiet start */ +} __packed; +#endif + +struct ieee80211_channelswitch_ie { + uint8_t ie; /* IEEE80211_ELEMID_CHANSWITCHANN */ + uint8_t len; + uint8_t switchmode; + uint8_t newchannel; + uint8_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 { + uint8_t ie; /* IEEE80211_ELEMID_EXTCHANSWITCHANN */ + uint8_t len; + uint8_t switchmode; + uint8_t newClass; + uint8_t newchannel; + uint8_t tbttcount; +} __packed; + +struct ieee80211_tpc_ie { + uint8_t ie; + uint8_t len; + uint8_t pwrlimit; +} __packed; + +/* + * MHDRIE included in TKIP MFP protected management frames + */ +struct ieee80211_ese_mhdr_ie { + uint8_t mhdr_id; + uint8_t mhdr_len; + uint8_t mhdr_oui[3]; + uint8_t mhdr_oui_type; + uint8_t mhdr_fc[2]; + uint8_t mhdr_bssid[IEEE80211_ADDR_LEN]; +} __packed; + +/* + * SSID IE + */ +struct ieee80211_ie_ssid { + uint8_t ssid_id; + uint8_t ssid_len; + uint8_t ssid[32]; +} __packed; + +/* + * Supported rates + */ +#define IEEE80211_MAX_SUPPORTED_RATES 8 + +struct ieee80211_ie_rates { + uint8_t rate_id; /* Element Id */ + uint8_t rate_len; /* IE Length */ + uint8_t rate[IEEE80211_MAX_SUPPORTED_RATES]; /* IE Length */ +} __packed; + +/* + * Extended rates + */ +#define IEEE80211_MAX_EXTENDED_RATES 256 + +struct ieee80211_ie_xrates { + uint8_t xrate_id; /* Element Id */ + uint8_t xrate_len; /* IE Length */ + uint8_t xrate[IEEE80211_MAX_EXTENDED_RATES]; /* IE Length */ +} __packed; + +/* + * WPS SSID list information element (maximally sized). + */ +struct ieee80211_ie_ssidl { + uint8_t ssidl_id; /* IEEE80211_ELEMID_VENDOR */ + uint8_t ssidl_len; /* length in bytes */ + uint8_t ssidl_oui[3]; /* 0x00, 0x50, 0xf2 */ + uint8_t ssidl_type; /* OUI type */ + uint8_t ssidl_prim_cap; /* Primary capabilities */ + uint8_t ssidl_count; /* # of secondary SSIDs */ + uint16_t ssidl_value[248]; +} __packed; + +#if _BYTE_ORDER == _BIG_ENDIAN +struct ieee80211_sec_ssid_cap { + uint32_t reserved0 : 1, + akmlist : 6, reserved1 : 4, reeserved2 : 2, ucipher : 15, mcipher : 4; +}; +#else +struct ieee80211_sec_ssid_cap { + uint32_t mcipher : 4, + ucipher : 15, reserved2 : 2, reserved1 : 4, akmlist : 6, reserved0 : 1; +}; +#endif + +struct ieee80211_ie_qbssload { + uint8_t elem_id; /* IEEE80211_ELEMID_QBSS_LOAD */ + uint8_t length; /* length in bytes */ + uint16_t station_count; /* number of station associated */ + uint8_t channel_utilization; /* channel busy time in 0-255 scale */ + uint16_t aac; /* available admission capacity */ +} __packed; + +#define SEC_SSID_HEADER_LEN 6 +#define SSIDL_IE_HEADER_LEN 6 + +struct ieee80211_sec_ssid { + uint8_t sec_ext_cap; + struct ieee80211_sec_ssid_cap sec_cap; + uint8_t sec_ssid_len; + uint8_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) + +/* + * AUTH management packets + * + * octet algo[2] + * octet seq[2] + * octet status[2] + * octet chal.id + * octet chal.length + * octet chal.text[253] + */ + +typedef uint8_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 { + uint8_t elem_id; + uint8_t elem_len; + uint16_t scan_passive_dwell; + uint16_t scan_active_dwell; + uint16_t scan_interval; + uint16_t scan_passive_total; + uint16_t scan_active_total; + uint16_t scan_delay; + uint16_t scan_thresh; +} __packed; + +/* + * Extended capability ie + */ +struct ieee80211_ie_ext_cap { + uint8_t elem_id; + uint8_t elem_len; + uint32_t ext_capflags; + uint32_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 { + uint8_t elem_id; + uint8_t elem_len; +#if _BYTE_ORDER == _BIG_ENDIAN + uint8_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 + uint8_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 { + uint8_t elem_id; + uint8_t elem_len; + uint8_t reg_class; + uint8_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 { + uint8_t elem_id; + uint8_t elem_len; + uint8_t interval_type; + uint32_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 { + uint8_t element_id; + uint8_t length; + uint16_t key_id; + uint8_t sequence_number[6]; + uint8_t mic[8]; +} __packed; +#endif + +/* + * 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 { + uint8_t elem_id; + uint8_t len; + uint8_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 { + uint8_t elem_id; + uint8_t elem_len; + uint8_t txpwr_info; /* Transmit Power Information */ + uint8_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 { + uint8_t elem_id; + uint8_t elem_len; + uint8_t new_ch_width; /* New channel width */ + uint8_t new_ch_freq_seg1; /* Channel Center frequency 1 */ + uint8_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 /* CDS_COMMON_IEEE80211_H_ */ diff --git a/core/cds/inc/cds_ieee80211_defines.h b/core/cds/inc/cds_ieee80211_defines.h new file mode 100644 index 000000000000..037ad4295050 --- /dev/null +++ b/core/cds/inc/cds_ieee80211_defines.h @@ -0,0 +1,1374 @@ +/* + * 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 CDS_IEEE80211_DEFINES_H_ +#define CDS_IEEE80211_DEFINES_H_ + +#include "cds_ieee80211_common.h" + +/* + * 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; + uint8_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 + uint8_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) + uint32_t ts_tstamp; /* tx time stamp */ +#endif +#ifdef ATH_SUPPORT_FLOWMAC_MODULE + uint8_t ts_flowmac_flags; +#define IEEE80211_TX_FLOWMAC_DONE 0x01 +#endif + uint32_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 */ + uint8_t rs_rssictl[IEEE80211_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ + uint8_t rs_rssiextn[IEEE80211_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ + uint8_t rs_isvalidrssi; /* rs_rssi is valid or not */ + + enum ieee80211_phymode rs_phymode; + int rs_freq; + + union { + uint8_t data[8]; + uint64_t tsf; + } rs_tstamp; + + /* + * Detail channel structure of recv frame. + * It could be NULL if not available + */ + struct ieee80211_channel *rs_full_chan; + + uint8_t rs_isaggr; + uint8_t rs_isapsd; + int16_t rs_noisefloor; + uint16_t rs_channel; +#ifdef ATH_SUPPORT_TxBF + uint32_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. */ + + uint16_t rs_cryptodecapcount; /* Crypto bytes decapped/demic'ed. */ + uint8_t rs_padspace; /* No. of padding bytes present after header + in wbuf. */ + uint8_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 *, uint32_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 uint16_t IEEE80211_SCAN_REQUESTOR; +typedef uint32_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 */ + uint32_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 */ + uint8_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 */ + uint8_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 uint32_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 */ + uint8_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; + uint32_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 */ + uint8_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; + uint32_t rate; /* average rate in kbps */ + uint32_t lastrate; /* last packet rate in kbps */ + uint8_t mcs; /* mcs index . is valid if rate type is MCS20 or MCS40 */ + uint8_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 { + uint32_t ns_rx_data; /* rx data frames */ + uint32_t ns_rx_mgmt; /* rx management frames */ + uint32_t ns_rx_ctrl; /* rx control frames */ + uint32_t ns_rx_ucast; /* rx unicast frames */ + uint32_t ns_rx_mcast; /* rx multi/broadcast frames */ + uint64_t ns_rx_bytes; /* rx data count (bytes) */ + uint64_t ns_rx_beacons; /* rx beacon frames */ + uint32_t ns_rx_proberesp; /* rx probe response frames */ + + uint32_t ns_rx_dup; /* rx discard 'cuz dup */ + uint32_t ns_rx_noprivacy; /* rx w/ wep but privacy off */ + uint32_t ns_rx_wepfail; /* rx wep processing failed */ + uint32_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. */ + uint32_t ns_rx_tkipmic; /* rx TKIP MIC failure */ + uint32_t ns_rx_ccmpmic; /* rx CCMP MIC failure */ + uint32_t ns_rx_wpimic; /* rx WAPI MIC failure */ + uint32_t ns_rx_tkipicv; /* rx ICV check failed (TKIP) */ + uint32_t ns_rx_decap; /* rx decapsulation failed */ + uint32_t ns_rx_defrag; /* rx defragmentation failed */ + uint32_t ns_rx_disassoc; /* rx disassociation */ + uint32_t ns_rx_deauth; /* rx deauthentication */ + uint32_t ns_rx_action; /* rx action */ + uint32_t ns_rx_decryptcrc; /* rx decrypt failed on crc */ + uint32_t ns_rx_unauth; /* rx on unauthorized port */ + uint32_t ns_rx_unencrypted; /* rx unecrypted w/ privacy */ + + uint32_t ns_tx_data; /* tx data frames */ + uint32_t ns_tx_data_success; /* tx data frames successfully + transmitted (unicast only) */ + uint32_t ns_tx_mgmt; /* tx management frames */ + uint32_t ns_tx_ucast; /* tx unicast frames */ + uint32_t ns_tx_mcast; /* tx multi/broadcast frames */ + uint64_t ns_tx_bytes; /* tx data count (bytes) */ + uint64_t ns_tx_bytes_success; /* tx success data count - unicast only + (bytes) */ + uint32_t ns_tx_probereq; /* tx probe request frames */ + uint32_t ns_tx_uapsd; /* tx on uapsd queue */ + uint32_t ns_tx_discard; /* tx dropped by NIC */ + + uint32_t ns_tx_novlantag; /* tx discard 'cuz no tag */ + uint32_t ns_tx_vlanmismatch; /* tx discard 'cuz bad tag */ + + uint32_t ns_tx_eosplost; /* uapsd EOSP retried out */ + + uint32_t ns_ps_discard; /* ps discard 'cuz of age */ + + uint32_t ns_uapsd_triggers; /* uapsd triggers */ + uint32_t ns_uapsd_duptriggers; /* uapsd duplicate triggers */ + uint32_t ns_uapsd_ignoretriggers; /* uapsd duplicate triggers */ + uint32_t ns_uapsd_active; /* uapsd duplicate triggers */ + uint32_t ns_uapsd_triggerenabled; /* uapsd duplicate triggers */ + + /* MIB-related state */ + uint32_t ns_tx_assoc; /* [re]associations */ + uint32_t ns_tx_assoc_fail; /* [re]association failures */ + uint32_t ns_tx_auth; /* [re]authentications */ + uint32_t ns_tx_auth_fail; /* [re]authentication failures */ + uint32_t ns_tx_deauth; /* deauthentications */ + uint32_t ns_tx_deauth_code; /* last deauth reason */ + uint32_t ns_tx_disassoc; /* disassociations */ + uint32_t ns_tx_disassoc_code; /* last disassociation reason */ + uint32_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 { + uint16_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 ((uint16_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 */ + uint16_t keylen; /* length of the key data fields */ + uint8_t *macaddr; /* mac address of length IEEE80211_ADDR_LEN . all bytes are 0xff for multicast key */ + uint64_t keyrsc; + uint64_t keytsc; + uint16_t txmic_offset; /* TKIP/SMS4 only: offset to tx mic key */ + uint16_t rxmic_offset; /* TKIP/SMS4 only: offset to rx mic key */ + uint8_t *keydata; +#ifdef ATH_SUPPORT_WAPI + uint8_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 { + uint8_t bssid[IEEE80211_ADDR_LEN]; + uint8_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; + uint8_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 (uint16_t)0x00F1 +#define WAPI_UNICAST_REKEY (uint16_t)0x00F2 +#define WAPI_STA_AGING (uint16_t)0x00F3 +#define WAPI_MULTI_REKEY (uint16_t)0x00F4 +#define WAPI_STA_STATS (uint16_t)0x00F5 + +/* + * IEEE80211 PHY Statistics. + */ +struct ieee80211_phy_stats { + uint64_t ips_tx_packets; /* frames successfully transmitted */ + uint64_t ips_tx_multicast; /* multicast/broadcast frames successfully transmitted */ + uint64_t ips_tx_fragments; /* fragments successfully transmitted */ + uint64_t ips_tx_xretries; /* frames that are xretried. NB: not number of retries */ + uint64_t ips_tx_retries; /* frames transmitted after retries. NB: not number of retries */ + uint64_t ips_tx_multiretries; /* frames transmitted after more than one retry. */ + uint64_t ips_tx_timeout; /* frames that expire the dot11MaxTransmitMSDULifetime */ + uint64_t ips_rx_packets; /* frames successfully received */ + uint64_t ips_rx_multicast; /* multicast/broadcast frames successfully received */ + uint64_t ips_rx_fragments; /* fragments successfully received */ + uint64_t ips_rx_timeout; /* frmaes that expired the dot11MaxReceiveLifetime */ + uint64_t ips_rx_dup; /* duplicated fragments */ + uint64_t ips_rx_mdup; /* multiple duplicated fragments */ + uint64_t ips_rx_promiscuous; /* frames that are received only because promiscuous filter is on */ + uint64_t ips_rx_promiscuous_fragments; /* fragments that are received only because promiscuous filter is on */ + uint64_t ips_tx_rts; /* RTS success count */ + uint64_t ips_tx_shortretry; /* tx on-chip retries (short). RTSFailCnt */ + uint64_t ips_tx_longretry; /* tx on-chip retries (long). DataFailCnt */ + uint64_t ips_rx_crcerr; /* rx failed 'cuz of bad CRC */ + uint64_t ips_rx_fifoerr; /* rx failed 'cuz of FIFO overrun */ + uint64_t ips_rx_decrypterr; /* rx decryption error */ +}; + +struct ieee80211_chan_stats { + uint32_t chan_clr_cnt; + uint32_t cycle_cnt; + uint32_t phy_err_cnt; +}; + +struct ieee80211_mac_stats { + uint64_t ims_tx_packets; /* frames successfully transmitted */ + uint64_t ims_rx_packets; /* frames successfully received */ + uint64_t ims_tx_bytes; /* bytes successfully transmitted */ + uint64_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 */ + uint64_t ims_tx_data_packets; /* data frames successfully transmitted */ + uint64_t ims_rx_data_packets; /* data frames successfully received */ + uint64_t ims_tx_data_bytes; /* data bytes successfully transmitted, + inclusive of FCS. */ + uint64_t ims_rx_data_bytes; /* data bytes successfully received, + inclusive of FCS. */ + + uint64_t ims_tx_datapyld_bytes; /* data payload bytes successfully + transmitted */ + uint64_t ims_rx_datapyld_bytes; /* data payload successfully + received */ + + /* Decryption errors */ + uint64_t ims_rx_unencrypted; /* rx w/o wep and privacy on */ + uint64_t ims_rx_badkeyid; /* rx w/ incorrect keyid */ + uint64_t ims_rx_decryptok; /* rx decrypt okay */ + uint64_t ims_rx_decryptcrc; /* rx decrypt failed on crc */ + uint64_t ims_rx_wepfail; /* rx wep processing failed */ + uint64_t ims_rx_tkipreplay; /* rx seq# violation (TKIP) */ + uint64_t ims_rx_tkipformat; /* rx format bad (TKIP) */ + uint64_t ims_rx_tkipmic; /* rx MIC check failed (TKIP) */ + uint64_t ims_rx_tkipicv; /* rx ICV check failed (TKIP) */ + uint64_t ims_rx_ccmpreplay; /* rx seq# violation (CCMP) */ + uint64_t ims_rx_ccmpformat; /* rx format bad (CCMP) */ + uint64_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 */ + uint64_t ims_rx_wpireplay; /* rx seq# violation (WPI) */ + uint64_t ims_rx_wpimic; /* rx MIC check failed (WPI) */ +/* #endif */ + /* Other Tx/Rx errors */ + uint64_t ims_tx_discard; /* tx dropped by NIC */ + uint64_t ims_rx_discard; /* rx dropped by NIC */ + + uint64_t ims_rx_countermeasure; /* rx TKIP countermeasure activation count */ +}; + +/* + * Summary statistics. + */ +struct ieee80211_stats { + uint32_t is_rx_badversion; /* rx frame with bad version */ + uint32_t is_rx_tooshort; /* rx frame too short */ + uint32_t is_rx_wrongbss; /* rx from wrong bssid */ + uint32_t is_rx_wrongdir; /* rx w/ wrong direction */ + uint32_t is_rx_mcastecho; /* rx discard 'cuz mcast echo */ + uint32_t is_rx_notassoc; /* rx discard 'cuz sta !assoc */ + uint32_t is_rx_noprivacy; /* rx w/ wep but privacy off */ + uint32_t is_rx_decap; /* rx decapsulation failed */ + uint32_t is_rx_mgtdiscard; /* rx discard mgt frames */ + uint32_t is_rx_ctl; /* rx discard ctrl frames */ + uint32_t is_rx_beacon; /* rx beacon frames */ + uint32_t is_rx_rstoobig; /* rx rate set truncated */ + uint32_t is_rx_elem_missing; /* rx required element missing */ + uint32_t is_rx_elem_toobig; /* rx element too big */ + uint32_t is_rx_elem_toosmall; /* rx element too small */ + uint32_t is_rx_elem_unknown; /* rx element unknown */ + uint32_t is_rx_badchan; /* rx frame w/ invalid chan */ + uint32_t is_rx_chanmismatch; /* rx frame chan mismatch */ + uint32_t is_rx_nodealloc; /* rx frame dropped */ + uint32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */ + uint32_t is_rx_auth_unsupported; /* rx w/ unsupported auth alg */ + uint32_t is_rx_auth_fail; /* rx sta auth failure */ + uint32_t is_rx_auth_countermeasures; /* rx auth discard 'cuz CM */ + uint32_t is_rx_assoc_bss; /* rx assoc from wrong bssid */ + uint32_t is_rx_assoc_notauth; /* rx assoc w/o auth */ + uint32_t is_rx_assoc_capmismatch; /* rx assoc w/ cap mismatch */ + uint32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */ + uint32_t is_rx_assoc_badwpaie; /* rx assoc w/ bad WPA IE */ + uint32_t is_rx_deauth; /* rx deauthentication */ + uint32_t is_rx_disassoc; /* rx disassociation */ + uint32_t is_rx_action; /* rx action mgt */ + uint32_t is_rx_badsubtype; /* rx frame w/ unknown subtype */ + uint32_t is_rx_nobuf; /* rx failed for lack of buf */ + uint32_t is_rx_ahdemo_mgt; /* rx discard ahdemo mgt frame */ + uint32_t is_rx_bad_auth; /* rx bad auth request */ + uint32_t is_rx_unauth; /* rx on unauthorized port */ + uint32_t is_rx_badcipher; /* rx failed 'cuz key type */ + uint32_t is_tx_nodefkey; /* tx failed 'cuz no defkey */ + uint32_t is_tx_noheadroom; /* tx failed 'cuz no space */ + uint32_t is_rx_nocipherctx; /* rx failed 'cuz key !setup */ + uint32_t is_rx_acl; /* rx discard 'cuz acl policy */ + uint32_t is_rx_ffcnt; /* rx fast frames */ + uint32_t is_rx_badathtnl; /* driver key alloc failed */ + uint32_t is_rx_nowds; /* 4-addr packets received with no wds enabled */ + uint32_t is_tx_nobuf; /* tx failed for lack of buf */ + uint32_t is_tx_nonode; /* tx failed for no node */ + uint32_t is_tx_unknownmgt; /* tx of unknown mgt frame */ + uint32_t is_tx_badcipher; /* tx failed 'cuz key type */ + uint32_t is_tx_ffokcnt; /* tx fast frames sent success */ + uint32_t is_tx_fferrcnt; /* tx fast frames sent success */ + uint32_t is_scan_active; /* active scans started */ + uint32_t is_scan_passive; /* passive scans started */ + uint32_t is_node_timeout; /* nodes timed out inactivity */ + uint32_t is_crypto_nomem; /* no memory for crypto ctx */ + uint32_t is_crypto_tkip; /* tkip crypto done in s/w */ + uint32_t is_crypto_tkipenmic; /* tkip en-MIC done in s/w */ + uint32_t is_crypto_tkipdemic; /* tkip de-MIC done in s/w */ + uint32_t is_crypto_tkipcm; /* tkip counter measures */ + uint32_t is_crypto_ccmp; /* ccmp crypto done in s/w */ + uint32_t is_crypto_wep; /* wep crypto done in s/w */ + uint32_t is_crypto_setkey_cipher; /* cipher rejected key */ + uint32_t is_crypto_setkey_nokey; /* no key index for setkey */ + uint32_t is_crypto_delkey; /* driver key delete failed */ + uint32_t is_crypto_badcipher; /* unknown cipher */ + uint32_t is_crypto_nocipher; /* cipher not available */ + uint32_t is_crypto_attachfail; /* cipher attach failed */ + uint32_t is_crypto_swfallback; /* cipher fallback to s/w */ + uint32_t is_crypto_keyfail; /* driver key alloc failed */ + uint32_t is_crypto_enmicfail; /* en-MIC failed */ + uint32_t is_ibss_capmismatch; /* merge failed-cap mismatch */ + uint32_t is_ibss_norate; /* merge failed-rate mismatch */ + uint32_t is_ps_unassoc; /* ps-poll for unassoc. sta */ + uint32_t is_ps_badaid; /* ps-poll w/ incorrect aid */ + uint32_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 { + uint8_t traffic_type; + uint8_t direction; + uint8_t dot1Dtag; + uint8_t tid; + uint8_t acc_policy_edca; + uint8_t acc_policy_hcca; + uint8_t aggregation; + uint8_t psb; + uint8_t ack_policy; + uint16_t norminal_msdu_size; + uint16_t max_msdu_size; + uint32_t min_srv_interval; + uint32_t max_srv_interval; + uint32_t inactivity_interval; + uint32_t suspension_interval; + uint32_t srv_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t max_burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw; + uint16_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; + uint8_t action; + uint8_t tid; + uint16_t status; + uint16_t aid; + uint32_t arg1; + uint32_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 { + uint16_t mic_count_in_60s; + uint32_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 { + uint32_t length; + uint8_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/core/cds/inc/cds_if_upperproto.h b/core/cds/inc/cds_if_upperproto.h new file mode 100644 index 000000000000..072c6bca2edb --- /dev/null +++ b/core/cds/inc/cds_if_upperproto.h @@ -0,0 +1,238 @@ +/* + * 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 _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 { + uint8_t ether_dhost[ETHER_ADDR_LEN]; + uint8_t ether_shost[ETHER_ADDR_LEN]; + uint16_t ether_type; +} __packed; +#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 { + uint8_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 { + uint8_t version_ihl; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_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 { + uint8_t type; + uint8_t code; /* For newer IGMP */ + uint16_t csum; + uint32_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 { + uint8_t grec_type; + uint8_t grec_auxwords; + uint16_t grec_nsrcs; + uint32_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 { + uint8_t type; + uint8_t resv1; + uint16_t csum; + uint16_t resv2; + uint16_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/core/cds/inc/cds_mq.h b/core/cds/inc/cds_mq.h new file mode 100644 index 000000000000..8f76bee22447 --- /dev/null +++ b/core/cds/inc/cds_mq.h @@ -0,0 +1,165 @@ +/* + * 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( __CDS_MQ_H ) +#define __CDS_MQ_H + +/**========================================================================= + + \file cds_mq.h + + \brief virtual Operating System Services (CDF) message queue APIs + + Message Queue Definitions and API + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/* cds Message Type. + This represnets a message that can be posted to another module through + the cds Message Queues. + \note This is mapped directly to the tSirMsgQ for backward + compatibility with the legacy MAC code */ + +typedef struct cds_msg_s { + uint16_t type; + /* + * This field can be used as sequence number/dialog token for matching + * requests and responses. + */ + uint16_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; + + uint32_t bodyval; + + /* + * Some messages provide a callback function. The function signature + * must be agreed upon between the two entities exchanging the message + */ + void *callback; + +} cds_msg_t; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/* Message Queue IDs */ +typedef enum { + /* Message Queue ID for messages bound for SME */ + CDS_MQ_ID_SME = CDF_MODULE_ID_SME, + + /* Message Queue ID for messages bound for PE */ + CDS_MQ_ID_PE = CDF_MODULE_ID_PE, + + /* Message Queue ID for messages bound for WMA */ + CDS_MQ_ID_WMA = CDF_MODULE_ID_WMA, + + /* Message Queue ID for messages bound for the SYS module */ + CDS_MQ_ID_SYS = CDF_MODULE_ID_SYS, + +} CDS_MQ_ID; + +/**--------------------------------------------------------------------------- + + \brief cds_mq_post_message() - post a message to a message queue + + This API allows messages to be posted to a specific message queue. Messages + can be posted to the following message queues: + +
    +
  • SME +
  • PE +
  • HAL +
  • TL +
+ + \param msgQueueId - identifies the message queue upon which the message + will be posted. + + \param message - a pointer to a message buffer. Memory for this message + buffer is allocated by the caller and free'd by the CDF 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 CDF_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + CDF_STATUS_E_INVAL - The value specified by msgQueueId does not + refer to a valid Message Queue Id. + + CDF_STATUS_E_FAULT - message is an invalid pointer. + + CDF_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS cds_mq_post_message(CDS_MQ_ID msgQueueId, cds_msg_t *message); + +/**--------------------------------------------------------------------------- + + \brief cds_send_mb_message_to_mac() - post a message to a message queue + + \param pBuf is a buffer allocated by caller. The actual structure varies + base on message type + + \return CDF_STATUS_SUCCESS - the message has been successfully posted + to the message queue. + + CDF_STATUS_E_FAILURE - the message queue handler has reported + an unknown failure. + + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS cds_send_mb_message_to_mac(void *pBuf); + +#endif /* if !defined __CDS_MQ_H */ diff --git a/core/cds/inc/cds_pack_align.h b/core/cds/inc/cds_pack_align.h new file mode 100644 index 000000000000..f213115d2c0b --- /dev/null +++ b/core/cds/inc/cds_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( __CDS_PACK_ALIGN_H ) +#define __CDS_PACK_ALIGN_H + +/**========================================================================= + + \file cds_pack_align.h + + \brief Connectivity driver services (CDS) pack and align primitives + + Definitions for platform independent means of packing and aligning + data structures + + ========================================================================*/ + +/* + + Place the macro CDS_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 CDS_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 + + CDS_PACK_START + typedef CDS_PACK_PRE struct foo_s { ... } CDS_PACK_POST foo_t; + CDS_PACK_END + + 2. 2-byte alignment for foo_t across all platforms + + typedef CDS_ALIGN_PRE(2) struct foo_s { ... } CDS_ALIGN_POST(2) foo_t; + + 3. Pack-size 1-byte and 2-byte alignment for foo_t across all platforms + + CDS_PACK_START + typedef CDS_PACK_PRE CDS_ALIGN_PRE(2) struct foo_s { ... } CDS_ALIGN_POST(2) CDS_PACK_POST foo_t; + CDS_PACK_END + + */ + +#if defined __GNUC__ + +#define CDS_PACK_START +#define CDS_PACK_END + +#define CDS_PACK_PRE +#define CDS_PACK_POST __attribute__((__packed__)) + +#define CDS_ALIGN_PRE(__value) +#define CDS_ALIGN_POST(__value) __attribute__((__aligned__(__value))) + +#elif defined __arm + +#define CDS_PACK_START +#define CDS_PACK_END + +#define CDS_PACK_PRE __packed +#define CDS_PACK_POST + +#define CDS_ALIGN_PRE(__value) __align(__value) +#define CDS_ALIGN_POST(__value) + +#elif defined _MSC_VER + +#define CDS_PACK_START __pragma(pack(push,1)) +#define CDS_PACK_END __pragma(pack(pop)) + +#define CDS_PACK_PRE +#define CDS_PACK_POST + +#define CDS_ALIGN_PRE(__value) __declspec(align(__value)) +#define CDS_ALIGN_POST(__value) + +#else + +#error Unsupported compiler!!! + +#endif + +#endif /* __CDS_PACK_ALIGN_H */ diff --git a/core/cds/inc/cds_packet.h b/core/cds/inc/cds_packet.h new file mode 100644 index 000000000000..f3a87d3e645c --- /dev/null +++ b/core/cds/inc/cds_packet.h @@ -0,0 +1,185 @@ +/* + * 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( __CDS_PKT_H ) +#define __CDS_PKT_H + +/**========================================================================= + + \file cds_packet.h + + \brief Connectivity driver services (CDS) network Packet APIs + + Network Protocol packet/buffer support interfaces + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +struct cds_pkt_t; +typedef struct cds_pkt_t cds_pkt_t; + +#include "cdf_nbuf.h" + +#define CDS_PKT_TRAC_TYPE_EAPOL NBUF_PKT_TRAC_TYPE_EAPOL +#define CDS_PKT_TRAC_TYPE_DHCP NBUF_PKT_TRAC_TYPE_DHCP +#define CDS_PKT_TRAC_TYPE_MGMT_ACTION NBUF_PKT_TRAC_TYPE_MGMT_ACTION /* Managment action frame */ + +#define CDS_PKT_TRAC_DUMP_CMD 9999 + +/*--------------------------------------------------------------------------- + +* brief cds_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 + + ---------------------------------------------------------------------------*/ +uint8_t cds_pkt_get_proto_type + (struct sk_buff *skb, uint8_t tracking_map, uint8_t dot11_type); + +#ifdef QCA_PKT_PROTO_TRACE +/*--------------------------------------------------------------------------- + +* brief cds_pkt_trace_buf_update() - + Update storage buffer with interest event string + +* event_string Event String may packet type or outstanding event + + ---------------------------------------------------------------------------*/ +void cds_pkt_trace_buf_update(char *event_string); + +/*--------------------------------------------------------------------------- + +* brief cds_pkt_trace_buf_dump() - + Dump stored information into kernel log + + ---------------------------------------------------------------------------*/ +void cds_pkt_trace_buf_dump(void); + +/*--------------------------------------------------------------------------- + +* brief cds_pkt_proto_trace_init() - + Initialize protocol trace functionality, allocate required resource + + ---------------------------------------------------------------------------*/ +void cds_pkt_proto_trace_init(void); + +/*--------------------------------------------------------------------------- + +* brief cds_pkt_proto_trace_close() - + Free required resource + + ---------------------------------------------------------------------------*/ +void cds_pkt_proto_trace_close(void); +#endif /* QCA_PKT_PROTO_TRACE */ + +/** + * cds_pkt_return_packet Free the cds Packet + * @ cds Packet + */ +CDF_STATUS cds_pkt_return_packet(cds_pkt_t *packet); + +/** + * cds_pkt_get_packet_length Returns the packet length + * @ cds Packet + */ +CDF_STATUS cds_pkt_get_packet_length(cds_pkt_t *pPacket, + uint16_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 CDS_PKT_SIZE_BUFFER ((30 * 128) + 32) + +/* cds Packet Types */ +typedef enum { + /* cds Packet is used to transmit 802.11 Management frames. */ + CDS_PKT_TYPE_TX_802_11_MGMT, + + /* cds Packet is used to transmit 802.11 Data frames. */ + CDS_PKT_TYPE_TX_802_11_DATA, + + /* cds Packet is used to transmit 802.3 Data frames. */ + CDS_PKT_TYPE_TX_802_3_DATA, + + /* cds Packet contains Received data of an unknown frame type */ + CDS_PKT_TYPE_RX_RAW, + + /* Invalid sentinel value */ + CDS_PKT_TYPE_MAXIMUM +} CDS_PKT_TYPE; + +/* user IDs. These IDs are needed on the cds_pkt_get/set_user_data_ptr() + to identify the user area in the cds Packet. */ +typedef enum { + CDS_PKT_USER_DATA_ID_TL = 0, + CDS_PKT_USER_DATA_ID_BAL, + CDS_PKT_USER_DATA_ID_WMA, + CDS_PKT_USER_DATA_ID_HDD, + CDS_PKT_USER_DATA_ID_BSL, + + CDS_PKT_USER_DATA_ID_MAX +} CDS_PKT_USER_DATA_ID; + +#ifdef MEMORY_DEBUG +#define cds_packet_alloc(s, d, p) \ + cds_packet_alloc_debug(s, d, p, __FILE__, __LINE__) + +CDF_STATUS cds_packet_alloc_debug(uint16_t size, void **data, void **ppPacket, + uint8_t *file_name, uint32_t line_num); +#else +CDF_STATUS cds_packet_alloc(uint16_t size, void **data, void **ppPacket); +#endif + +void cds_packet_free(void *pPacket); + +typedef CDF_STATUS (*cds_pkt_get_packet_callback)(cds_pkt_t *pPacket, + void *userData); + +#endif /* !defined( __CDS_PKT_H ) */ diff --git a/core/cds/inc/cds_queue.h b/core/cds/inc/cds_queue.h new file mode 100644 index 000000000000..030ff2536dde --- /dev/null +++ b/core/cds/inc/cds_queue.h @@ -0,0 +1,33 @@ +/* + * 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 _CDS_QUEUE_H +#define _CDS_QUEUE_H + +#include /* include BSD queue */ + +#endif /* end of _CDS_QUEUE_H */ diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h new file mode 100644 index 000000000000..02a6965c5c4c --- /dev/null +++ b/core/cds/inc/cds_reg_service.h @@ -0,0 +1,310 @@ +/* + * 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 __CDS_REG_SERVICE_H +#define __CDS_REG_SERVICE_H + +/**========================================================================= + + \file cds_reg_service.h + + \brief Connectivity driver services (CDS): Non-Volatile storage API + + ========================================================================*/ + +#include "cdf_status.h" + +#define CDS_COUNTRY_CODE_LEN 2 +#define CDS_MAC_ADDRESS_LEN 6 + +typedef enum { + REGDOMAIN_FCC, + REGDOMAIN_ETSI, + REGDOMAIN_JAPAN, + REGDOMAIN_WORLD, + REGDOMAIN_COUNT +} v_REGDOMAIN_t; + +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, + + RF_CHAN_144, + + /* 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, + + RF_CHAN_BOND_142, + + 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, + NUM_24GHZ_CHANNELS = (MAX_2_4GHZ_CHANNEL - MIN_2_4GHZ_CHANNEL + 1), + + 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_5_9GHZ_CHANNEL = RF_CHAN_170, + MAX_5_9GHZ_CHANNEL = RF_CHAN_184, + + INVALID_RF_CHANNEL = 0xBAD, + RF_CHANNEL_INVALID_MAX_FIELD = 0x7FFFFFFF +} eRfChannels; + +typedef enum { + CHANNEL_STATE_DISABLE, + CHANNEL_STATE_ENABLE, + CHANNEL_STATE_DFS, + CHANNEL_STATE_INVALID +} CHANNEL_STATE; + +typedef int8_t tPowerdBm; + +typedef struct { + uint32_t enabled:4; + uint32_t flags:28; + tPowerdBm pwrLimit; +} sRegulatoryChannel; + +typedef struct { + sRegulatoryChannel channels[NUM_RF_CHANNELS]; +} sRegulatoryDomain; + +typedef struct { + uint16_t targetFreq; + uint16_t channelNum; +} tRfChannelProps; + +typedef struct { + uint8_t chanId; + tPowerdBm pwr; +} tChannelListWithPower; + +typedef enum { + COUNTRY_INIT, + COUNTRY_IE, + COUNTRY_USER, + COUNTRY_QUERY, + COUNTRY_MAX = COUNTRY_QUERY +} v_CountryInfoSource_t; + +/** + * enum chan_width: channel width + * + * @CHAN_WIDTH_0MHZ: channel disabled or invalid + * @CHAN_WIDTH_5MHZ: channel width 5 MHZ + * @CHAN_WIDTH_10MHZ: channel width 10 MHZ + * @CHAN_WIDTH_20MHZ: channel width 20 MHZ + * @CHAN_WIDTH_40MHZ: channel width 40 MHZ + * @CHAN_WIDTH_80MHZ: channel width 80MHZ + * @CHAN_WIDTH_160MHZ: channel width 160 MHZ + */ +enum channel_width { + CHAN_WIDTH_0MHZ, + CHAN_WIDTH_5MHZ, + CHAN_WIDTH_10MHZ, + CHAN_WIDTH_20MHZ, + CHAN_WIDTH_40MHZ, + CHAN_WIDTH_80MHZ, + CHAN_WIDTH_160MHZ +}; + +/** + * @country_code_t : typedef for country code. One extra + * char for holding null character + */ +typedef uint8_t country_code_t[CDS_COUNTRY_CODE_LEN + 1]; + +typedef struct { + sRegulatoryDomain regDomains[REGDOMAIN_COUNT]; + country_code_t default_country; +} t_reg_table; + + +CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *pRegDomain, + const country_code_t countryCode, + v_CountryInfoSource_t source); + +CDF_STATUS cds_read_default_country(country_code_t default_country); + +CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower + *pChannels20MHz, + uint8_t *pNum20MHzChannelsFound, + tChannelListWithPower + *pChannels40MHz, + uint8_t *pNum40MHzChannelsFound); + +CDF_STATUS cds_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); + +CHANNEL_STATE cds_get_channel_state(uint32_t rfChannel); + +#define CDS_IS_DFS_CH(channel) (cds_get_channel_state((channel)) == \ + CHANNEL_STATE_DFS) + +#define CDS_IS_PASSIVE_OR_DISABLE_CH(channel) \ + (cds_get_channel_state((channel)) != CHANNEL_STATE_ENABLE) + +#define CDS_MAX_24GHz_CHANNEL_NUMBER \ + (rf_channels[MAX_2_4GHZ_CHANNEL].channelNum) +#define CDS_MIN_5GHz_CHANNEL_NUMBER (rf_channels[RF_CHAN_36].channelNum) +#define CDS_MAX_5GHz_CHANNEL_NUMBER (rf_channels[MAX_5GHZ_CHANNEL].channelNum) + +#define CDS_IS_CHANNEL_5GHZ(chnNum) \ + (((chnNum) >= CDS_MIN_5GHz_CHANNEL_NUMBER) && ((chnNum) <= CDS_MAX_5GHz_CHANNEL_NUMBER)) + +#define CDS_IS_CHANNEL_24GHZ(chnNum) \ + (((chnNum) > 0) && ((chnNum) <= CDS_MAX_24GHz_CHANNEL_NUMBER)) + +#define CDS_IS_SAME_BAND_CHANNELS(ch1, ch2) \ + (ch1 && ch2 && \ + (CDS_IS_CHANNEL_5GHZ(ch1) == CDS_IS_CHANNEL_5GHZ(ch2))) + +CDF_STATUS cds_regulatory_init(void); +CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region); +CDF_STATUS cds_set_dfs_region(uint8_t dfs_region); +bool cds_is_dsrc_channel(uint16_t); +CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, + enum channel_width ch_width); +enum channel_width cds_get_max_channel_bw(uint32_t chan_num); + +#endif /* __CDS_REG_SERVICE_H */ diff --git a/core/cds/inc/cds_regdomain.h b/core/cds/inc/cds_regdomain.h new file mode 100644 index 000000000000..262677f201a1 --- /dev/null +++ b/core/cds/inc/cds_regdomain.h @@ -0,0 +1,1098 @@ +/* + * 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. + */ + +/* + * 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 {(uint64_t) 0, (uint64_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)) ? (((uint64_t) 1) << _fa) : (uint64_t) 0) | \ + (((_fb >= 0) && (_fb < 64)) ? (((uint64_t) 1) << _fb) : (uint64_t) 0) | \ + (((_fc >= 0) && (_fc < 64)) ? (((uint64_t) 1) << _fc) : (uint64_t) 0) | \ + (((_fd >= 0) && (_fd < 64)) ? (((uint64_t) 1) << _fd) : (uint64_t) 0) | \ + (((_fe >= 0) && (_fe < 64)) ? (((uint64_t) 1) << _fe) : (uint64_t) 0) | \ + (((_ff >= 0) && (_ff < 64)) ? (((uint64_t) 1) << _ff) : (uint64_t) 0) | \ + (((_fg >= 0) && (_fg < 64)) ? (((uint64_t) 1) << _fg) : (uint64_t) 0) | \ + (((_fh >= 0) && (_fh < 64)) ? (((uint64_t) 1) << _fh) : (uint64_t) 0) | \ + (((_fi >= 0) && (_fi < 64)) ? (((uint64_t) 1) << _fi) : (uint64_t) 0) | \ + (((_fj >= 0) && (_fj < 64)) ? (((uint64_t) 1) << _fj) : (uint64_t) 0) | \ + (((_fk >= 0) && (_fk < 64)) ? (((uint64_t) 1) << _fk) : (uint64_t) 0) | \ + (((_fl >= 0) && (_fl < 64)) ? (((uint64_t) 1) << _fl) : (uint64_t) 0) ) \ + ,(((((_fa > 63) && (_fa < 128)) ? (((uint64_t) 1) << (_fa - 64)) : (uint64_t) 0) | \ + (((_fb > 63) && (_fb < 128)) ? (((uint64_t) 1) << (_fb - 64)) : (uint64_t) 0) | \ + (((_fc > 63) && (_fc < 128)) ? (((uint64_t) 1) << (_fc - 64)) : (uint64_t) 0) | \ + (((_fd > 63) && (_fd < 128)) ? (((uint64_t) 1) << (_fd - 64)) : (uint64_t) 0) | \ + (((_fe > 63) && (_fe < 128)) ? (((uint64_t) 1) << (_fe - 64)) : (uint64_t) 0) | \ + (((_ff > 63) && (_ff < 128)) ? (((uint64_t) 1) << (_ff - 64)) : (uint64_t) 0) | \ + (((_fg > 63) && (_fg < 128)) ? (((uint64_t) 1) << (_fg - 64)) : (uint64_t) 0) | \ + (((_fh > 63) && (_fh < 128)) ? (((uint64_t) 1) << (_fh - 64)) : (uint64_t) 0) | \ + (((_fi > 63) && (_fi < 128)) ? (((uint64_t) 1) << (_fi - 64)) : (uint64_t) 0) | \ + (((_fj > 63) && (_fj < 128)) ? (((uint64_t) 1) << (_fj - 64)) : (uint64_t) 0) | \ + (((_fk > 63) && (_fk < 128)) ? (((uint64_t) 1) << (_fk - 64)) : (uint64_t) 0) | \ + (((_fl > 63) && (_fl < 128)) ? (((uint64_t) 1) << (_fl - 64)) : (uint64_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 { + uint16_t regDmnEnum; /* 16 bit reg domain pair */ + uint16_t regDmn5GHz; /* 5GHz reg domain */ + uint16_t regDmn2GHz; /* 2GHz reg domain */ + uint32_t flags5GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint32_t flags2GHz; /* Requirements flags (AdHoc + disallow, noise floor cal needed, + etc) */ + uint64_t pscanMask; /* Passive Scan flags which + can override unitary domain + passive scan flags. This + value is used as a mask on + the unitary flags */ + uint16_t singleCC; /* Country code of single country if + a one-on-one mapping exists */ +} REG_DMN_PAIR_MAPPING; + +typedef struct { + uint16_t countryCode; + uint16_t regDmnEnum; + const char *isoName; + const char *name; + uint16_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 */ + uint16_t outdoorChanStart; +} COUNTRY_CODE_TO_ENUM_RD; + +typedef struct RegDmnFreqBand { + uint16_t lowChannel; /* Low channel center in MHz */ + uint16_t highChannel; /* High Channel center in MHz */ + uint8_t powerDfs; /* Max power (dBm) for channel + range when using DFS */ + uint8_t antennaMax; /* Max allowed antenna gain */ + uint8_t channelBW; /* Bandwidth of the channel */ + uint8_t channelSep; /* Channel separation within + the band */ + uint64_t useDfs; /* Use DFS in the RegDomain + if corresponding bit is set */ + uint64_t usePassScan; /* Use Passive Scan in the RegDomain + if corresponding bit is set */ + uint8_t regClassId; /* Regulatory class id */ +} REG_DMN_FREQ_BAND; + +typedef struct reg_domain { + uint16_t regDmnEnum; /* value from EnumRd table */ + uint8_t conformance_test_limit; + uint64_t dfsMask; /* DFS bitmask for 5Ghz tables */ + uint64_t pscan; /* Bitmask for passive scan */ + uint32_t flags; /* Requirement flags (AdHoc disallow, noise + floor cal needed, etc) */ + uint64_t chan11a[BMLEN]; /* 128 bit bitmask for channel/band selection */ + uint64_t chan11a_turbo[BMLEN]; /* 128 bit bitmask for channel/band select */ + uint64_t chan11a_dyn_turbo[BMLEN]; /* 128 bit mask for chan/band select */ + + uint64_t chan11b[BMLEN]; /* 128 bit bitmask for channel/band selection */ + uint64_t chan11g[BMLEN]; /* 128 bit bitmask for channel/band selection */ + uint64_t chan11g_turbo[BMLEN]; +} REG_DOMAIN; + +struct cmode { + uint32_t mode; + uint32_t flags; +}; + +#define YES true +#define NO false + +/* mapping of old skus to new skus for Japan */ +typedef struct { + uint16_t domain; + uint16_t newdomain_pre53; /* pre eeprom version 5.3 */ + uint16_t newdomain_post53; /* post eeprom version 5.3 */ +} JAPAN_SKUMAP; + +/* mapping of countrycode to new skus for Japan */ +typedef struct { + uint16_t ccode; + uint16_t newdomain_pre53; /* pre eeprom version 5.3 */ + uint16_t newdomain_post53; /* post eeprom version 5.3 */ +} JAPAN_COUNTRYMAP; + +/* check rd flags in eeprom for japan */ +typedef struct { + uint16_t freqbandbit; + uint32_t eepromflagtocheck; +} JAPAN_BANDCHECK; + +/* Common mode power table for 5Ghz */ +typedef struct { + uint16_t lchan; + uint16_t hchan; + uint8_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; + + uint16_t regDomainPairsCt; /* Num reg domain pair entries */ + uint16_t allCountriesCt; /* Num country entries */ + uint16_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 cds_fill_some_regulatory_info(struct regulatory *reg); +void cds_fill_and_send_ctl_to_fw(struct regulatory *reg); +int32_t cds_get_country_from_alpha2(uint8_t *alpha2); +void cds_fill_send_ctl_info_to_fw(struct regulatory *reg, uint32_t modesAvail, + uint32_t modeSelect); +void cds_set_wma_dfs_region(struct regulatory *reg); + +#endif /* REGULATORY_H */ diff --git a/core/cds/inc/cds_regdomain_common.h b/core/cds/inc/cds_regdomain_common.h new file mode 100644 index 000000000000..7feaf55c3928 --- /dev/null +++ b/core/cds/inc/cds_regdomain_common.h @@ -0,0 +1,2218 @@ +/* + * 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 "cds_ieee80211_common.h" +#include +#include "wlan_defs.h" + +#define MAX_CHANNELS_PER_OPERATING_CLASS 25 + +enum EnumRd { + /* + * The following regulatory domain definitions are + * found in the EEPROM. Each regulatory domain + * can operate in either a 5GHz or 2.4GHz wireless mode or + * both 5GHz and 2.4GHz wireless modes. + * In general, the value holds no special + * meaning and is used to decode into either specific + * 2.4GHz or 5GHz wireless mode for that particular + * regulatory domain. + */ + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */ + NULL1_ETSIB = 0x07, /* Israel */ + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, /* USA */ + FCC1_WORLD = 0x11, /* Hong Kong */ + FCC4_FCCA = 0x12, /* USA - Public Safety */ + FCC5_FCCA = 0x13, /* US with no DFS (UNII-1 + UNII-3 Only) */ + FCC6_FCCA = 0x14, /* Canada for AP only */ + + FCC2_FCCA = 0x20, /* Canada */ + FCC2_WORLD = 0x21, /* Australia & HK */ + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, /* Australia for AP only */ + FRANCE_RES = 0x31, /* Legacy France for OEM */ + FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */ + FCC3_ETSIC = 0x3F, /* New Zealand, DFS enabled */ + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, /* France (optional) */ + ETSI2_WORLD = 0x35, /* Hungary & others */ + ETSI3_WORLD = 0x36, /* France & others */ + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, /* Bulgaria */ + ETSI8_WORLD = 0x3D, /* Russia */ + ETSI9_WORLD = 0x3E, /* Ukraine */ + ETSI_RESERVED = 0x33, /* Reserved (Do not used) */ + + MKK1_MKKA = 0x40, /* Japan (JP1) */ + MKK1_MKKB = 0x41, /* Japan (JP0) */ + APL4_WORLD = 0x42, /* Singapore and Morocco */ + MKK2_MKKA = 0x43, /* Japan with 4.9G channels */ + APL_RESERVED = 0x44, /* Reserved (Do not used) */ + APL2_WORLD = 0x45, /* Korea */ + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, /* Japan (JP1-1) */ + APL2_APLD = 0x49, /* Korea with 2.3G channels */ + MKK1_MKKA1 = 0x4A, /* Japan (JE1) */ + MKK1_MKKA2 = 0x4B, /* Japan (JE2) */ + MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */ + APL2_FCCA = 0x4D, /* Mobile customer */ + APL11_FCCA = 0x4F, /* Specific AP Customer 5GHz, For APs Only */ + + APL3_FCCA = 0x50, + APL12_WORLD = 0x51, + APL1_WORLD = 0x52, /* Latin America */ + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, /* Venezuela */ + APL5_WORLD = 0x58, /* Chile */ + APL13_WORLD = 0x5A, /* Algeria */ + APL6_WORLD = 0x5B, /* Singapore */ + APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */ + APL8_WORLD = 0x5D, /* Malaysia 5GHz */ + APL9_MKKC = 0x5E, /* Korea 5GHz, Before 11/2007. Now used only by APs */ + APL10_MKKC = 0x5F, /* Korea 5GHz, After 11/2007. For STAs only */ + + /* + * World mode SKUs + */ + WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */ + WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */ + WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */ + WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */ + WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */ + WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */ + + WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */ + WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */ + EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */ + + WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */ + WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */ + WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */ + WORC_WORLD = 0x6C, /* WorldC (WOC SKU) */ + + MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */ + MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */ + MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */ + + MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */ + MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */ + MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */ + + MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */ + MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */ + MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */ + MKK5_FCCA = 0x9A, + + MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */ + MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */ + MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */ + + MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */ + MKK7_MKKA2 = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */ + MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */ + + MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */ + MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */ + MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */ + + MKK14_MKKA1 = 0x92, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz + MKKA1 */ + MKK15_MKKA1 = 0x93, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz + MKKA1 */ + + MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */ + MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */ + MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */ + MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */ + + MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA */ + MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + FCCA */ + MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA1 */ + MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKC */ + MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA2 */ + + MKK13_MKKB = 0xDE, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB + All passive + no adhoc */ + + /* Following definitions are used only by s/w to map old + * Japan SKUs. + */ + MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */ + MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */ + MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */ + MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */ + MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */ + MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */ + MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */ + MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */ + MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */ + MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */ + MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */ + MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */ + MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */ + MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */ + + /* + * Regulator domains ending in a number (e.g. APL1, + * MK1, ETSI4, etc) apply to 5GHz channel and power + * information. Regulator domains ending in a letter + * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and + * power information. + */ + APL1 = 0x0150, /* LAT & Asia */ + APL2 = 0x0250, /* LAT & Asia */ + APL3 = 0x0350, /* Taiwan */ + APL4 = 0x0450, /* Jordan */ + APL5 = 0x0550, /* Chile */ + APL6 = 0x0650, /* Singapore */ + APL7 = 0x0750, /* Taiwan, disable ch52 */ + APL8 = 0x0850, /* Malaysia */ + APL9 = 0x0950, /* Korea. Before 11/2007. Now used only by APs */ + APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */ + APL11 = 0x1150, /* Specific AP Customer 5GHz, For APs Only */ + APL12 = 0x1160, /* Kenya */ + + ETSI1 = 0x0130, /* Europe & others */ + ETSI2 = 0x0230, /* Europe & others */ + ETSI3 = 0x0330, /* Europe & others */ + ETSI4 = 0x0430, /* Europe & others */ + ETSI5 = 0x0530, /* Europe & others */ + ETSI6 = 0x0630, /* Europe & others */ + ETSI8 = 0x0830, /* Russia */ + ETSI9 = 0x0930, /* Ukraine */ + ETSIA = 0x0A30, /* France */ + ETSIB = 0x0B30, /* Israel */ + ETSIC = 0x0C30, /* Latin America */ + + FCC1 = 0x0110, /* US & others */ + FCC2 = 0x0120, /* Canada, Australia & New Zealand */ + FCC3 = 0x0160, /* US w/new middle band & DFS */ + FCC4 = 0x0165, /* US Public Safety */ + FCC5 = 0x0510, + FCC6 = 0x0610, /* Canada & Australia */ + FCCA = 0x0A10, + + APLD = 0x0D50, /* South Korea */ + + MKK1 = 0x0140, /* Japan (UNI-1 odd) */ + MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */ + MKK3 = 0x0340, /* Japan (UNI-1 even) */ + MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */ + MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */ + MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */ + MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */ + MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */ + MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */ + MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */ + MKK13 = 0x0C40, /* Same as MKK8 but all passive and no adhoc 11a */ + MKK14 = 0x1440, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz */ + MKK15 = 0x1540, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz */ + MKKA = 0x0A40, /* Japan */ + MKKC = 0x0A50, + + NULL1 = 0x0198, + WORLD = 0x0199, + DEBUG_REG_DMN = 0x01ff, +}; + +enum { /* conformance test limits */ + FCC = 0x10, + MKK = 0x40, + ETSI = 0x30, +}; +/* + * The following are flags for different requirements per reg domain. + * These requirements are either inhereted from the reg domain pair or + * from the unitary reg domain if the reg domain pair flags value is + * 0 + */ + +enum { + NO_REQ = 0x00000000, + DISALLOW_ADHOC_11A = 0x00000001, + DISALLOW_ADHOC_11A_TURB = 0x00000002, + NEED_NFC = 0x00000004, + + ADHOC_PER_11D = 0x00000008, /* Start Ad-Hoc mode */ + ADHOC_NO_11A = 0x00000010, + + PUBLIC_SAFETY_DOMAIN = 0x00000020, /* public safety domain */ + LIMIT_FRAME_4MS = 0x00000040, /* 4msec limit on the frame length */ + + NO_HOSTAP = 0x00000080, /* No HOSTAP mode opereation */ + + REQ_MASK = 0x000000FF, /* Requirements bit mask */ +}; + +static const REG_DMN_PAIR_MAPPING ah_cmn_reg_domain_pairs[] = { + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, + 0}, + {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + + {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC3_ETSIC, FCC3, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + NO_REQ, PSCAN_DEFER, 0}, + {FCC5_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + + {ETSI1_WORLD, ETSI1, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI2_WORLD, ETSI2, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI3_WORLD, ETSI3, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI4_WORLD, ETSI4, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI5_WORLD, ETSI5, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI6_WORLD, ETSI6, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI8_WORLD, ETSI8, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {ETSI9_WORLD, ETSI9, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + + {ETSI3_ETSIA, ETSI3, WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + + {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL2_FCCA, APL2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL7_FCCA, APL7, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL9_MKKC, APL9, MKKC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL10_MKKC, APL10, MKKC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + + {MKK1_MKKA, MKK1, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN}, + {MKK1_MKKB, MKK1, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, + CTRY_JAPAN1}, + {MKK1_FCCA, MKK1, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1, CTRY_JAPAN2}, + {MKK1_MKKA1, MKK1, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4}, + {MKK1_MKKA2, MKK1, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5}, + {MKK1_MKKC, MKK1, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1, CTRY_JAPAN6}, + + /* MKK2 */ + {MKK2_MKKA, MKK2, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, + CTRY_JAPAN3}, + + /* MKK3 */ + {MKK3_MKKA, MKK3, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKKA, CTRY_JAPAN25}, + {MKK3_MKKB, MKK3, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7}, + {MKK3_MKKA1, MKK3, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26}, + {MKK3_MKKA2, MKK3, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8}, + {MKK3_MKKC, MKK3, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + NO_PSCAN, CTRY_JAPAN9}, + {MKK3_FCCA, MKK3, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + NO_PSCAN, CTRY_JAPAN27}, + + /* MKK4 */ + {MKK4_MKKA, MKK4, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN36}, + {MKK4_MKKB, MKK4, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, + CTRY_JAPAN10}, + {MKK4_MKKA1, MKK4, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28}, + {MKK4_MKKA2, MKK4, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11}, + {MKK4_MKKC, MKK4, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN12}, + {MKK4_FCCA, MKK4, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN29}, + + /* MKK5 */ +/* {MKK5_MKKA, MKK5, MKKA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN56 },*/ + {MKK5_MKKB, MKK5, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, + CTRY_JAPAN13}, + {MKK5_MKKA2, MKK5, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14}, + {MKK5_MKKC, MKK5, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN15}, + {MKK5_FCCA, MKK5, FCCA, DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN56 }, + + /* MKK6 */ + {MKK6_MKKB, MKK6, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16}, + {MKK6_MKKA1, MKK6, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30}, + {MKK6_MKKA2, MKK6, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17}, + {MKK6_MKKC, MKK6, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1, CTRY_JAPAN18}, + {MKK6_FCCA, MKK6, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1, CTRY_JAPAN31}, + + /* MKK7 */ + {MKK7_MKKB, MKK7, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19}, + {MKK7_MKKA1, MKK7, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32}, + {MKK7_MKKA2, MKK7, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20}, + {MKK7_MKKC, MKK7, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21}, + {MKK7_FCCA, MKK7, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33}, + + /* MKK8 */ + {MKK8_MKKB, MKK8, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22}, + {MKK8_MKKA2, MKK8, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23}, + {MKK8_MKKC, MKK8, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN24}, + + {MKK9_MKKA, MKK9, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN34}, + {MKK9_FCCA, MKK9, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + NO_PSCAN, CTRY_JAPAN37}, + {MKK9_MKKA1, MKK9, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38}, + {MKK9_MKKA2, MKK9, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40}, + {MKK9_MKKC, MKK9, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + NO_PSCAN, CTRY_JAPAN39}, + + {MKK10_MKKA, MKK10, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN35}, + {MKK10_FCCA, MKK10, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN41}, + {MKK10_MKKA1, MKK10, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42}, + {MKK10_MKKA2, MKK10, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44}, + {MKK10_MKKC, MKK10, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN43}, + + {MKK11_MKKA, MKK11, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN45}, + {MKK11_FCCA, MKK11, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN46}, + {MKK11_MKKA1, MKK11, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47}, + {MKK11_MKKA2, MKK11, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49}, + {MKK11_MKKC, MKK11, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK3, CTRY_JAPAN48}, + + {MKK12_MKKA, MKK12, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50}, + {MKK12_FCCA, MKK12, FCCA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51}, + {MKK12_MKKA1, MKK12, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN52}, + {MKK12_MKKA2, MKK12, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN54}, + {MKK12_MKKC, MKK12, MKKC, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53}, + + {MKK13_MKKB, MKK13, MKKA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | + LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN57}, + + {MKK14_MKKA1, MKK14, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58}, + {MKK15_MKKA1, MKK15, MKKA, + DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, + PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59}, + + /* These are super domains */ + {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, + PSCAN_DEFER, 0}, + {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, + {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WORA_WORLD, WORA_WORLD, WORA_WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WORB_WORLD, WORB_WORLD, WORB_WORLD, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0}, + {WORC_WORLD, WORC_WORLD, WORC_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, +}; + +static const COUNTRY_CODE_TO_ENUM_RD ah_cmn_all_countries[] = { + {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, YES, NO, + NO, NO, 7000}, + {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, YES, NO, + NO, NO, 7000}, + {CTRY_ARGENTINA, FCC3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES, YES, + YES, YES, YES, 7000}, + {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES, YES, + YES, NO, NO, 7000}, + {CTRY_ARUBA, ETSI1_WORLD, "AW", "ARUBA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_AUSTRALIA, FCC3_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_BAHAMAS, FCC3_WORLD, "BS", "BAHAMAS", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES, YES, + NO, NO, 7000}, + {CTRY_BANGLADESH, NULL1_WORLD, "BD", "BANGLADESH", YES, NO, YES, YES, + YES, NO, NO, NO, 7000}, + {CTRY_BARBADOS, FCC2_WORLD, "BB", "BARBADOS", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BELGIUM2, ETSI4_WORLD, "BE", "BELGIUM2", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_BERMUDA, FCC3_FCCA, "BM", "BERMUDA", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLIVIA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA AND HERZEGOVINA", YES, NO, + YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, YES, YES, + YES, YES, 7000}, + {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN", "BRUNEI DARUSSALAM", YES, + YES, YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_BULGARIA, ETSI1_WORLD, "BG", "BULGARIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_CAMBODIA, ETSI1_WORLD, "KH", "CAMBODIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_CANADA, FCC3_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES, YES, + YES, YES, NO, NO, 7000}, + {CTRY_CROATIA, ETSI1_WORLD, "HR", "CROATIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_CZECH, ETSI1_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC", YES, + YES, YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES, YES, + NO, NO, 7000}, + {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES, YES, + NO, NO, 7000}, + {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, YES, + YES, YES, NO, NO, 7000}, + {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_GREENLAND, ETSI1_WORLD, "GL", "GREENLAND", YES, NO, YES, YES, YES, + YES, NO, NO, 7000}, + {CTRY_GRENADA, FCC3_FCCA, "GD", "GRENADA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_GUAM, FCC1_FCCA, "GU", "GUAM", YES, NO, YES, YES, YES, YES, NO, + NO, 7000}, + {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_HAITI, ETSI1_WORLD, "HT", "HAITI", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_HONDURAS, FCC3_WORLD, "HN", "HONDURAS", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_HONG_KONG, FCC3_WORLD, "HK", "HONG KONG", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_INDONESIA, APL2_WORLD, "ID", "INDONESIA", YES, NO, YES, YES, YES, + YES, NO, NO, 7000}, + {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES, YES, + YES, 7000}, + {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_ISRAEL, ETSI3_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_JAMAICA, FCC3_WORLD, "JM", "JAMAICA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_JAPAN, MKK5_MKKA2, "JP", "JAPAN", YES, NO, NO, YES, YES, YES, NO, + NO, 7000}, + {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES, YES, NO, + NO, 7000}, + {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES, YES, NO, + NO, 7000}, + {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES, YES, NO, + NO, 7000}, + {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES, YES, + NO, NO, 7000}, + {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES, YES, + NO, NO, 7000}, + {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES, YES, NO, + NO, 7000}, + {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, +/* {CTRY_JAPAN55, MKK5_MKKA, "JP", "JAPAN55", YES, NO, NO, YES, YES, YES, YES, NO, 7000 },*/ + {CTRY_JAPAN56, MKK5_FCCA, "JP", "JAPAN56", YES, NO, NO, + YES, YES, YES, YES, NO, 7000 }, + {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, YES, + YES, NO, NO, NO, 7000}, + {CTRY_KENYA, APL1_WORLD, "KE", "KENYA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_KOREA_NORTH, APL9_MKKC, "KP", "NORTH KOREA", YES, NO, NO, YES, + NO, YES, NO, NO, 7000}, + {CTRY_KOREA_ROC, APL10_MKKC, "KR", "KOREA REPUBLIC", YES, NO, NO, YES, + YES, YES, YES, YES, 7000}, + {CTRY_KOREA_ROC3, APL9_MKKC, "KR", "KOREA REPUBLIC3", YES, NO, NO, YES, + NO, YES, NO, NO, 7000}, + {CTRY_KUWAIT, ETSI3_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_LEBANON, APL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, YES, + YES, YES, YES, YES, YES, 7000}, + {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU SAR", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_MACEDONIA, ETSI1_WORLD, "MK", "MACEDONIA, FYRO", YES, NO, YES, + YES, YES, YES, YES, YES, 7000}, + {CTRY_MALAYSIA, FCC1_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, YES, + YES, YES, YES, 7000}, + {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_MAURITIUS, ETSI1_WORLD, "MU", "MAURITIUS", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_MEXICO, FCC1_WORLD, "MX", "MEXICO", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_MOROCCO, APL4_WORLD, "MA", "MOROCCO", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN", "NETHERLANDS ANTILLES", + YES, NO, YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_NICARAGUA, FCC3_FCCA, "NI", "NICARAGUA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_OMAN, FCC3_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES, YES, + YES, 7000}, + {CTRY_PAKISTAN, APL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES, YES, + YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_PARAGUAY, FCC3_WORLD, "PY", "PARAGUAY", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_PERU, FCC3_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES, YES, + YES, 7000}, + {CTRY_PHILIPPINES, FCC3_WORLD, "PH", "PHILIPPINES", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_QATAR, APL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_ROMANIA, ETSI1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_RUSSIA, ETSI8_WORLD, "RU", "RUSSIA", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_RWANDA, APL1_WORLD, "RW", "RWANDA", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_SAUDI_ARABIA, FCC2_WORLD, "SA", "SAUDI ARABIA", YES, NO, YES, YES, + YES, YES, NO, NO, 7000}, + {CTRY_SERBIA, ETSI1_WORLD, "RS", "REPUBLIC OF SERBIA", YES, NO, YES, + YES, YES, YES, YES, YES, 7000}, + {CTRY_MONTENEGRO, ETSI1_WORLD, "ME", "MONTENEGRO", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_SINGAPORE, FCC3_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAKIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES, YES, + YES, NO, NO, 7000}, + {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIAN ARAB REPUBLIC", YES, NO, YES, + YES, YES, NO, NO, NO, 7000}, + {CTRY_TAIWAN, APL7_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_TANZANIA, APL1_WORLD, "TZ", "TANZANIA", YES, YES, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_THAILAND, FCC3_WORLD, "TH", "THAILAND", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT", "TRINIDAD AND TOBAGO", YES, + NO, YES, YES, YES, YES, YES, YES, 7000}, + {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES, YES, + YES, NO, NO, 7000}, + {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES, YES, + NO, NO, 7000}, + {CTRY_UGANDA, FCC3_WORLD, "UG", "UGANDA", YES, NO, NO, YES, YES, YES, + YES, YES, 7000}, + {CTRY_UKRAINE, ETSI9_WORLD, "UA", "UKRAINE", YES, NO, NO, YES, YES, YES, + YES, NO, 7000}, + {CTRY_UAE, ETSI1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO, YES, + YES, YES, YES, YES, YES, 7000}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES, YES, + YES, YES, YES, YES, YES, 5825}, + {CTRY_UNITED_STATES2, FCC6_FCCA, "US", "UNITED STATES2", YES, YES, YES, + YES, YES, YES, YES, YES, 7000}, + {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", + "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES, YES, + YES, 7000}, + {CTRY_URUGUAY, FCC3_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES, YES, + YES, YES, 7000}, + {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, YES, + YES, YES, YES, YES, 7000}, + {CTRY_VENEZUELA, FCC1_WORLD, "VE", "VENEZUELA", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_VIET_NAM, ETSI3_WORLD, "VN", "VIET NAM", YES, NO, YES, YES, YES, + YES, YES, YES, 7000}, + {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES, NO, NO, + NO, 7000}, + {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, YES, + NO, NO, NO, 7000} +}; + +/* Bit masks for DFS per regdomain */ + +enum { + NO_DFS = 0x0000000000000000ULL, + DFS_FCC3 = 0x0000000000000001ULL, + DFS_ETSI = 0x0000000000000002ULL, + DFS_MKK4 = 0x0000000000000004ULL, +}; + +/* The table of frequency bands is indexed by a bitmask. The ordering + * must be consistent with the enum below. When adding a new + * frequency band, be sure to match the location in the enum with the + * comments + */ + +/* + * 5GHz 11A channel tags + */ +enum { + F1_4912_4947, + F1_4915_4925, + F2_4915_4925, + F1_4935_4945, + F2_4935_4945, + F1_4920_4980, + F2_4920_4980, + F1_4942_4987, + F1_4945_4985, + F1_4950_4980, + F1_5032_5057, + F1_5035_5040, + F2_5035_5040, + F1_5035_5045, + F1_5040_5040, + F1_5040_5080, + F2_5040_5080, + F1_5055_5055, + F2_5055_5055, + + F1_5120_5240, + + F1_5170_5230, + F2_5170_5230, + + F1_5180_5240, + F2_5180_5240, + F3_5180_5240, + F4_5180_5240, + F5_5180_5240, + F6_5180_5240, + F7_5180_5240, + F8_5180_5240, + F9_5180_5240, + F10_5180_5240, + + F1_5240_5280, + + F1_5260_5280, + + F1_5260_5320, + F2_5260_5320, + F3_5260_5320, + F4_5260_5320, + F5_5260_5320, + F6_5260_5320, + F7_5260_5320, + + F1_5260_5700, + + F1_5280_5320, + F2_5280_5320, + F1_5500_5560, + + F1_5500_5580, + F2_5500_5580, + + F1_5500_5620, + + F1_5500_5660, + + F1_5500_5720, + F2_5500_5700, + F3_5500_5700, + F4_5500_5700, + F5_5500_5700, + F6_5500_5700, + + F1_5660_5700, + F2_5660_5720, + F3_5660_5720, + + F1_5745_5765, + + F1_5745_5805, + F2_5745_5805, + F3_5745_5805, + F4_5745_5805, + + F1_5745_5825, + F2_5745_5825, + F3_5745_5825, + F4_5745_5825, + F5_5745_5825, + F6_5745_5825, + F7_5745_5825, + F8_5745_5825, + F9_5745_5825, + + F1_5845_5865, + + W1_4920_4980, + W1_5040_5080, + W1_5170_5230, + W1_5180_5240, + W1_5260_5320, + W1_5745_5825, + W1_5500_5700, + A_DEMO_ALL_CHANNELS +}; + +static const REG_DMN_FREQ_BAND reg_dmn5_ghz_freq[] = { + {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 reg_dmn2_ghz_freq[] = { + {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 reg_dmn2_ghz11g_freq[] = { + {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 reg_dmn2_ghz11g_turbo_freq[] = { + {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 ah_cmn_reg_domains[] = { + + {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ, + CHAN_11A_BM(A_DEMO_ALL_CHANNELS, F6_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(T1_5130_5650, T1_5150_5670, F6_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, + -1, -1, -1, -1, -1, -1, -1, -1) + BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, + -1, -1, -1, -1, -1, -1, -1, -1), + BM(G_DEMO_ALMOST_ALL_CHANNELS, + G1_2484_2484, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, + -1, -1, -1, -1, -1, -1, -1, -1, -1)}, + + {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL3, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, + BM(F1_5280_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F5_5180_5240, F9_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC, NO_REQ, + BM(F9_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL7, FCC, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, NO_REQ, + BM(F2_5280_5320, F2_5500_5580, F3_5660_5720, F7_5745_5825, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL8, ETSI, NO_DFS, NO_PSCAN, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL10, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL11, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F9_5180_5240, F2_5260_5320, F5_5500_5700, F7_5745_5825, + F1_5845_5865, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {APL12, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F5_5180_5240, F1_5500_5560, F1_5745_5765, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F2_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {ETSI8, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F1_5660_5700, F4_5745_5825, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO}, + + {ETSI9, ETSI, DFS_ETSI, PSCAN_ETSI, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F1_5500_5660, F8_5745_5825, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO}, + + {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, -1, + -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, + BM(F2_5180_5240, F3_5260_5320, F1_5500_5720, F5_5745_5825, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + /* + + Bug Fix: EV 98583 Public Safety channel + Exclude the following channel in FCC Public safety domain + Uni-1: 5180, 5200, 5220, 5240 + Uni-2: 5260, 5280, 5300, 5320 + Uni-3: 5745, 5765, 5785, 5805, 5825 + */ + {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, + BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ, + BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, + BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F2_5660_5720, + F6_5745_5825, -1, -1, -1, -1, -1, -1, -1), + BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, -1, + -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {MKK1, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_5170_5230, F10_5180_5240, F7_5260_5320, F4_5500_5700, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + {MKK2, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F2_4915_4925, F2_4935_4945, F1_4920_4980, F1_5035_5040, + F2_5055_5055, F1_5040_5080, F1_5170_5230, F10_5180_5240, -1, -1, -1, + -1), + BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 even */ + {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 even + UNI-2 */ + {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 even + UNI-2 + mid-band */ + {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F4_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + even */ + {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + UNI-1 even + UNI-2 */ + {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, + -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 even + 4.9 GHZ */ + {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, + F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, + F4_5180_5240, -1, -1, -1), + BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 even + UNI-2 + 4.9 GHZ */ + {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, + F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, + F4_5180_5240, F2_5260_5320, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz */ + {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4912_4947, F1_5032_5057, F1_4915_4925, F1_4935_4945, + F2_4920_4980, F1_5035_5045, F1_5055_5055, F2_5040_5080, + F4_5180_5240, F2_5260_5320, F6_5500_5700, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz */ + {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, + F1_5055_5055, F2_5040_5080, F2_5170_5230, F4_5180_5240, + F2_5260_5320, F6_5500_5700, -1, -1), + BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */ + {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + BM(F2_5170_5230, F7_5180_5240, F2_5260_5320, F6_5500_5700, -1, -1, -1, + -1, -1, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + UNI-1 even + 4.9GHz */ + {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, + F2_5040_5080, F1_5055_5055, F2_5170_5230, F4_5180_5240, -1, -1, -1, + -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /* UNI-1 odd + UNI-1 even + UNI-2 + 4.9GHz */ + {MKK15, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, + BM(F1_4915_4925, F1_4935_4945, F2_4920_4980, F1_5040_5040, + F2_5040_5080, F1_5055_5055, F2_5170_5230, F4_5180_5240, + F2_5260_5320, -1, -1, -1), + BMZERO, + BMZERO, + BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, + + /*=== 2 GHz ===*/ + + /* Defined here to use when 2G channels are authorised for country K2 */ + {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F2_2312_2372, F4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G2_2312_2372, G4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BMZERO}, + + {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO CHAN_11A_BMZERO CHAN_11A_BMZERO BM(F1_2457_2472, -1, + -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO CHAN_11A_BMZERO CHAN_11A_BMZERO BM(F1_2432_2442, -1, + -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, + DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO CHAN_11A_BMZERO CHAN_11A_BMZERO BM(F3_2412_2472, -1, + -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1), + BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {MKKA, MKK, NO_DFS, + PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | PSCAN_MKKA2 | + PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB, + CHAN_11A_BMZERO CHAN_11A_BMZERO CHAN_11A_BMZERO BM(F2_2412_2462, + F1_2467_2472, + F2_2484_2484, + -1, -1, -1, -1, -1, + -1, -1, -1, -1), + BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(F4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + BM(G4_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, + W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, + W1_2417_2432, + W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), + BM(WG2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + W1_5500_5700, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, + W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, + W1_2447_2457, + -1, -1, -1, -1, -1, -1, -1), + BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, + -1, -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {WORC_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, + CHAN_11A_BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, W1_5745_5825, + -1, -1, -1, -1, -1, -1, -1, -1) + CHAN_11A_BMZERO + CHAN_11A_BMZERO + BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, + W1_2417_2432, + W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), + BM(WG1_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), + CHAN_TURBO_G_BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1)}, + + {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, + CHAN_11A_BMZERO CHAN_11A_BMZERO CHAN_11A_BMZERO BMZERO, + BMZERO, + CHAN_TURBO_G_BMZERO}, +}; + +static const struct cmode modes[] = { + {REGDMN_MODE_TURBO, IEEE80211_CHAN_ST}, /* TURBO means 11a Static Turbo */ + {REGDMN_MODE_11A, IEEE80211_CHAN_A}, + {REGDMN_MODE_11B, IEEE80211_CHAN_B}, + {REGDMN_MODE_11G, IEEE80211_CHAN_PUREG}, + {REGDMN_MODE_11G_TURBO, IEEE80211_CHAN_108G}, + {REGDMN_MODE_11A_TURBO, IEEE80211_CHAN_108A}, + {REGDMN_MODE_11NG_HT20, IEEE80211_CHAN_11NG_HT20}, + {REGDMN_MODE_11NG_HT40PLUS, IEEE80211_CHAN_11NG_HT40PLUS}, + {REGDMN_MODE_11NG_HT40MINUS, IEEE80211_CHAN_11NG_HT40MINUS}, + {REGDMN_MODE_11NA_HT20, IEEE80211_CHAN_11NA_HT20}, + {REGDMN_MODE_11NA_HT40PLUS, IEEE80211_CHAN_11NA_HT40PLUS}, + {REGDMN_MODE_11NA_HT40MINUS, IEEE80211_CHAN_11NA_HT40MINUS}, + {REGDMN_MODE_11AC_VHT20, IEEE80211_CHAN_11AC_VHT20}, + {REGDMN_MODE_11AC_VHT40PLUS, IEEE80211_CHAN_11AC_VHT40PLUS}, + {REGDMN_MODE_11AC_VHT40MINUS, IEEE80211_CHAN_11AC_VHT40MINUS}, + {REGDMN_MODE_11AC_VHT80, IEEE80211_CHAN_11AC_VHT80}, + {REGDMN_MODE_11AC_VHT20_2G, IEEE80211_CHAN_11AC_VHT20_2G}, + {REGDMN_MODE_11AC_VHT40_2G, IEEE80211_CHAN_11AC_VHT40_2G}, + {REGDMN_MODE_11AC_VHT80_2G, IEEE80211_CHAN_11AC_VHT80_2G}, +}; + +typedef enum offset { + BW20 = 0, + BW40_LOW_PRIMARY = 1, + BW40_HIGH_PRIMARY = 3, + BW80, + BWALL +} offset_t; + +typedef struct _regdm_op_class_map { + uint8_t op_class; + uint8_t ch_spacing; + offset_t offset; + uint8_t channels[MAX_CHANNELS_PER_OPERATING_CLASS]; +} regdm_op_class_map_t; + +typedef struct _regdm_supp_op_classes { + uint8_t num_classes; + uint8_t classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} regdm_supp_op_classes; + +uint16_t cds_regdm_get_opclass_from_channel(uint8_t *country, uint8_t channel, + uint8_t offset); +uint16_t cds_regdm_set_curr_opclasses(uint8_t num_classes, uint8_t *class); +uint16_t cds_regdm_get_curr_opclasses(uint8_t *num_classes, uint8_t *class); diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h new file mode 100644 index 000000000000..c9acbdce02e7 --- /dev/null +++ b/core/cds/inc/cds_sched.h @@ -0,0 +1,451 @@ +/* + * 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( __CDS_SCHED_H ) +#define __CDS_SCHED_H + +/**========================================================================= + + \file cds_sched.h + + \brief Connectivity driver services scheduler + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include "i_cdf_types.h" +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include +#include +#include "cdf_lock.h" + +#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 CDS_CORE_MAX_MESSAGES 8000 + +#ifdef QCA_CONFIG_SMP +/* +** Maximum number of cds messages to be allocated for +** OL Rx thread. +*/ +#define CDS_MAX_OL_RX_PKT 4000 + +typedef void (*cds_ol_rx_thread_cb)(void *context, void *rxpkt, uint16_t staid); +#endif + +/* +** CDF Message queue definition. +*/ +typedef struct _cds_mq_type { + /* Lock use to synchronize access to this message queue */ + spinlock_t mqLock; + + /* List of vOS Messages waiting on this queue */ + struct list_head mqList; + +} cds_mq_type, *p_cds_mq_type; + +#ifdef QCA_CONFIG_SMP +/* +** CDS message wrapper for data rx from TXRX +*/ +struct cds_ol_rx_pkt { + struct list_head list; + void *context; + + /* Rx skb */ + void *Rxpkt; + + /* Station id to which this packet is destined */ + uint16_t staId; + + /* Call back to further send this packet to txrx layer */ + cds_ol_rx_thread_cb callback; + +}; +#endif + +/* +** CDS 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 _cds_sched_context { + /* Place holder to the CDS Context */ + void *pVContext; + /* WMA Message queue on the Main thread */ + cds_mq_type wmaMcMq; + + /* PE Message queue on the Main thread */ + cds_mq_type peMcMq; + + /* SME Message queue on the Main thread */ + cds_mq_type smeMcMq; + + /* SYS Message queue on the Main thread */ + cds_mq_type sysMcMq; + + /* Handle of Event for MC thread to signal startup */ + struct completion McStartEvent; + + struct task_struct *McThread; + + /* completion object for MC thread shutdown */ + struct completion McShutdown; + + /* Wait queue for MC thread */ + wait_queue_head_t mcWaitQueue; + + unsigned long mcEventFlag; + + /* Completion object to resume Mc thread */ + struct completion ResumeMcEvent; + + /* lock to make sure that McThread suspend/resume mechanism is in sync */ + spinlock_t McThreadLock; +#ifdef QCA_CONFIG_SMP + spinlock_t ol_rx_thread_lock; + + /* OL Rx thread handle */ + struct task_struct *ol_rx_thread; + + /* Handle of Event for Rx thread to signal startup */ + struct completion ol_rx_start_event; + + /* Completion object to suspend OL rx thread */ + struct completion ol_suspend_rx_event; + + /* Completion objext to resume OL rx thread */ + struct completion ol_resume_rx_event; + + /* Completion object for OL Rxthread shutdown */ + struct completion ol_rx_shutdown; + + /* Waitq for OL Rx thread */ + wait_queue_head_t ol_rx_wait_queue; + + unsigned long ol_rx_event_flag; + + /* Rx buffer queue */ + struct list_head ol_rx_thread_queue; + + /* Spinlock to synchronize between tasklet and thread */ + spinlock_t ol_rx_queue_lock; + + /* Rx queue length */ + unsigned int ol_rx_queue_len; + + /* Lock to synchronize free buffer queue access */ + spinlock_t cds_ol_rx_pkt_freeq_lock; + + /* Free message queue for OL Rx processing */ + struct list_head cds_ol_rx_pkt_freeq; + + /* cpu hotplug notifier */ + struct notifier_block *cpu_hot_plug_notifier; +#endif +} cds_sched_context, *p_cds_sched_context; + +/** + * struct cds_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 cds_log_complete { + uint32_t is_fatal; + uint32_t indicator; + uint32_t reason_code; + bool is_report_in_progress; +}; + +/* +** CDS Sched Msg Wrapper +** Wrapper messages so that they can be chained to their respective queue +** in the scheduler. +*/ +typedef struct _cds_msg_wrapper { + /* Message node */ + struct list_head msgNode; + + /* the Vos message it is associated to */ + cds_msg_t *pVosMsg; + +} cds_msg_wrapper, *p_cds_msg_wrapper; + +typedef struct _cds_context_type { + /* Messages buffers */ + cds_msg_t aMsgBuffers[CDS_CORE_MAX_MESSAGES]; + + cds_msg_wrapper aMsgWrappers[CDS_CORE_MAX_MESSAGES]; + + /* Free Message queue */ + cds_mq_type freeVosMq; + + /* Scheduler Context */ + cds_sched_context cdf_sched; + + /* HDD Module Context */ + void *pHDDContext; + + /* MAC Module Context */ + void *pMACContext; + +#ifndef WLAN_FEATURE_MBSSID + /* SAP Context */ + void *pSAPContext; +#endif + + cdf_event_t ProbeEvent; + + volatile uint8_t isLogpInProgress; + + cdf_event_t wmaCompleteEvent; + + /* WMA Context */ + void *pWMAContext; + + void *pHIFContext; + + void *htc_ctx; + + void *epping_ctx; + /* + * cdf_ctx will be used by cdf + * while allocating dma memory + * to access dev information. + */ + cdf_device_t cdf_ctx; + + void *pdev_txrx_ctx; + + /* Configuration handle used to get system configuration */ + void *cfg_ctx; + + volatile uint8_t isLoadUnloadInProgress; + + 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 cds_log_complete log_complete; + cdf_spinlock_t bug_report_lock; + cdf_event_t connection_update_done_evt; + +} cds_context_type, *p_cds_contextType; + +/*--------------------------------------------------------------------------- + Function declarations and documenation + ---------------------------------------------------------------------------*/ + +#ifdef QCA_CONFIG_SMP +/*--------------------------------------------------------------------------- + \brief cds_drop_rxpkt_by_staid() - API to drop pending Rx packets for a sta + The \a cds_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 CDS Sched Context + \param staId - Station Id + + \return Nothing + \sa cds_drop_rxpkt_by_staid() + -------------------------------------------------------------------------*/ +void cds_drop_rxpkt_by_staid(p_cds_sched_context pSchedContext, uint16_t staId); + +/*--------------------------------------------------------------------------- + \brief cds_indicate_rxpkt() - API to Indicate rx data packet + The \a cds_indicate_rxpkt() enqueues the rx packet onto ol_rx_thread_queue + and notifies cds_ol_rx_thread(). + \param Arg - pointer to the global CDS Sched Context + \param pkt - Vos data message buffer + + \return Nothing + \sa cds_indicate_rxpkt() + -------------------------------------------------------------------------*/ +void cds_indicate_rxpkt(p_cds_sched_context pSchedContext, + struct cds_ol_rx_pkt *pkt); + +/*--------------------------------------------------------------------------- + \brief cds_alloc_ol_rx_pkt() - API to return next available cds message + The \a cds_alloc_ol_rx_pkt() returns next available cds message buffer + used for Rx Data processing. + \param pSchedContext - pointer to the global CDS Sched Context + + \return pointer to cds message buffer + \sa cds_alloc_ol_rx_pkt() + -------------------------------------------------------------------------*/ +struct cds_ol_rx_pkt *cds_alloc_ol_rx_pkt(p_cds_sched_context pSchedContext); + +/*--------------------------------------------------------------------------- + \brief cds_free_ol_rx_pkt() - API to release cds message to the freeq + The \a cds_free_ol_rx_pkt() returns the cds message used for Rx data + to the free queue. + \param pSchedContext - pointer to the global CDS Sched Context + \param pkt - Vos message buffer to be returned to free queue. + + \return Nothing + \sa cds_free_ol_rx_pkt() + -------------------------------------------------------------------------*/ +void cds_free_ol_rx_pkt(p_cds_sched_context pSchedContext, + struct cds_ol_rx_pkt *pkt); +/*--------------------------------------------------------------------------- + \brief cds_free_ol_rx_pkt_freeq() - Free cdss buffer free queue + The \a cds_free_ol_rx_pkt_freeq() does mem free of the buffers + available in free cds buffer queue which is used for Data rx processing + from Tlshim. + \param pSchedContext - pointer to the global CDS Sched Context + + \return Nothing + \sa cds_free_ol_rx_pkt_freeq() + -------------------------------------------------------------------------*/ +void cds_free_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext); +#endif + +/*--------------------------------------------------------------------------- + + \brief cds_sched_open() - initialize the CDS Scheduler + + The \a cds_sched_open() function initializes the CDS 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 p_cds_context - pointer to the global CDF Context + + \param p_cds_sched_context - pointer to a previously allocated buffer big + enough to hold a scheduler context. + \ + + \return CDF_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + CDF_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable to initilize the scheduler + + CDF_STATUS_E_NOMEM - insufficient memory exists to initialize + the scheduler + + CDF_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + + CDF_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa cds_sched_open() + + -------------------------------------------------------------------------*/ +CDF_STATUS cds_sched_open(void *p_cds_context, + p_cds_sched_context pSchedCxt, uint32_t SchedCtxSize); + +/*--------------------------------------------------------------------------- + + \brief cds_sched_close() - Close the CDS Scheduler + + The \a cds_sched_closes() function closes the CDS Scheduler + Upon successful closing: + + - All the message queues are flushed + + - The Main Controller thread is closed + + - The Tx thread is closed + + \param p_cds_context - pointer to the global CDF Context + + \return CDF_STATUS_SUCCESS - Scheduler was successfully initialized and + is ready to be used. + + CDF_STATUS_E_INVAL - Invalid parameter passed to the scheduler Open + function + + CDF_STATUS_E_FAILURE - Failure to initialize the scheduler/ + + \sa cds_sched_close() + + ---------------------------------------------------------------------------*/ +CDF_STATUS cds_sched_close(void *p_cds_context); + +/* Helper routines provided to other CDS API's */ +CDF_STATUS cds_mq_init(p_cds_mq_type pMq); +void cds_mq_deinit(p_cds_mq_type pMq); +void cds_mq_put(p_cds_mq_type pMq, p_cds_msg_wrapper pMsgWrapper); +p_cds_msg_wrapper cds_mq_get(p_cds_mq_type pMq); +bool cds_is_mq_empty(p_cds_mq_type pMq); +p_cds_sched_context get_cds_sched_ctxt(void); +CDF_STATUS cds_sched_init_mqs(p_cds_sched_context pSchedContext); +void cds_sched_deinit_mqs(p_cds_sched_context pSchedContext); +void cds_sched_flush_mc_mqs(p_cds_sched_context pSchedContext); + +void cdf_timer_module_init(void); +void cds_ssr_protect_init(void); +void cds_ssr_protect(const char *caller_func); +void cds_ssr_unprotect(const char *caller_func); +bool cds_is_ssr_ready(const char *caller_func); + +#define cds_wait_for_work_thread_completion(func) cds_is_ssr_ready(func) + +#endif /* #if !defined __CDS_SCHED_H */ diff --git a/core/cds/inc/cds_utils.h b/core/cds/inc/cds_utils.h new file mode 100644 index 000000000000..5e4b2f61d6ea --- /dev/null +++ b/core/cds/inc/cds_utils.h @@ -0,0 +1,189 @@ +/* + * 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( __CDS_UTILS_H ) +#define __CDS_UTILS_H + +/**========================================================================= + + \file cds_utils.h + + \brief Connectivity driver services (CDS) utility APIs + + Various utility functions + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include "ani_global.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define CDS_DIGEST_SHA1_SIZE (20) +#define CDS_DIGEST_MD5_SIZE (16) +#define CDS_BAND_2GHZ (1) +#define CDS_BAND_5GHZ (2) + +#define CDS_24_GHZ_BASE_FREQ (2407) +#define CDS_5_GHZ_BASE_FREQ (5000) +#define CDS_24_GHZ_CHANNEL_14 (14) +#define CDS_24_GHZ_CHANNEL_15 (15) +#define CDS_24_GHZ_CHANNEL_27 (27) +#define CDS_5_GHZ_CHANNEL_170 (170) +#define CDS_CHAN_SPACING_5MHZ (5) +#define CDS_CHAN_SPACING_20MHZ (20) +#define CDS_CHAN_14_FREQ (2484) +#define CDS_CHAN_15_FREQ (2512) +#define CDS_CHAN_170_FREQ (5852) + +#define cds_log(level, args...) CDF_TRACE(CDF_MODULE_ID_CDF, level, ## args) +#define cds_logfl(level, format, args...) cds_log(level, FL(format), ## args) + +#define cds_alert(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_FATAL, format, ## args) +#define cds_err(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_ERROR, format, ## args) +#define cds_warn(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_WARN, format, ## args) +#define cds_notice(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_INFO, format, ## args) +#define cds_info(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_INFO_HIGH, format, ## args) +#define cds_debug(format, args...) \ + cds_logfl(CDF_TRACE_LEVEL_DEBUG, format, ## args) +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +CDF_STATUS cds_crypto_init(uint32_t *phCryptProv); + +CDF_STATUS cds_crypto_deinit(uint32_t hCryptProv); + +/** + * cds_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 CDF_STATUS_SUCCSS if the operation succeeds + */ +CDF_STATUS cds_rand_get_bytes(uint32_t handle, uint8_t *pbBuf, + uint32_t numBytes); + +/** + * cds_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 CDF_STATUS_SUCCSS if the operation succeeds + * + */ +CDF_STATUS cds_sha1_hmac_str(uint32_t cryptHandle, /* Handle */ + uint8_t * text, /* pointer to data stream */ + uint32_t textLen, /* length of data stream */ + uint8_t * key, /* pointer to authentication key */ + uint32_t keyLen, /* length of authentication key */ + uint8_t digest[CDS_DIGEST_SHA1_SIZE]); /* caller digest to be filled in */ + +/** + * cds_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 CDF_STATUS_SUCCSS if the operation succeeds + * + */ +CDF_STATUS cds_md5_hmac_str(uint32_t cryptHandle, /* Handle */ + uint8_t * text, /* pointer to data stream */ + uint32_t textLen, /* length of data stream */ + uint8_t * key, /* pointer to authentication key */ + uint32_t keyLen, /* length of authentication key */ + uint8_t digest[CDS_DIGEST_MD5_SIZE]); /* caller digest to be filled in */ + +CDF_STATUS cds_encrypt_aes(uint32_t cryptHandle, /* Handle */ + uint8_t *pText, /* pointer to data stream */ + uint8_t *Encrypted, uint8_t *pKey); /* pointer to authentication key */ + +CDF_STATUS cds_decrypt_aes(uint32_t cryptHandle, /* Handle */ + uint8_t *pText, /* pointer to data stream */ + uint8_t *pDecrypted, uint8_t *pKey); /* pointer to authentication key */ + +uint32_t cds_chan_to_freq(uint8_t chan); +uint8_t cds_freq_to_chan(uint32_t freq); +uint8_t cds_chan_to_band(uint32_t chan); +#ifdef WLAN_FEATURE_11W +bool cds_is_mmie_valid(uint8_t *key, uint8_t *ipn, + uint8_t *frm, uint8_t *efrm); +bool cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id, + uint8_t *frm, uint8_t *efrm, uint16_t frmLen); +uint8_t cds_get_mmie_size(void); +#endif /* WLAN_FEATURE_11W */ +CDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal pMac); +#endif /* #if !defined __CDS_UTILS_H */ diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c new file mode 100644 index 000000000000..ffcb5edb7513 --- /dev/null +++ b/core/cds/src/cds_api.c @@ -0,0 +1,2085 @@ +/* + * 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. + */ + +/** + * DOC: cds_api.c + * + * Connectivity driver services APIs + */ + +#include +#include "cds_sched.h" +#include +#include "sir_types.h" +#include "sir_api.h" +#include "sir_mac_prot_def.h" +#include "sme_api.h" +#include "mac_init_api.h" +#include "wlan_qct_sys.h" +#include "wlan_hdd_misc.h" +#include "i_cds_packet.h" +#include "cds_reg_service.h" +#include "wma_types.h" +#include "wlan_hdd_main.h" +#include +#ifdef CONFIG_CNSS +#include +#endif + +#include "sap_api.h" +#include "cdf_trace.h" +#include "bmi.h" +#include "ol_fw.h" +#include "ol_if_athvar.h" +#include "hif.h" + +#include "cds_utils.h" +#include "wlan_logging_sock_svc.h" +#include "wma.h" + +#include "wlan_hdd_ipa.h" +/* Preprocessor Definitions and Constants */ + +/* Maximum number of cds message queue get wrapper failures to cause panic */ +#define CDS_WRAPPER_MAX_FAIL_COUNT (CDS_CORE_MAX_MESSAGES * 3) + +#ifdef IPA_OFFLOAD +#define CDS_IPA_CE_SR_BASE_PADDR \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_base_paddr) +#define CDS_IPA_CE_RING_SIZE \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_ring_size) +#define CDS_IPA_CE_REG_PADDR \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_reg_paddr) +#define CDS_IPA_TX_COMP_BASE_PADDR \ + (&((hdd_context_t *) \ + (gp_cds_context->pHDDContext))->tx_comp_ring_base_paddr) +#define CDS_IPA_TX_COMP_RING_SIZE \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_comp_ring_size) +#define CDS_IPA_TX_NUM_BUFF \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_num_alloc_buffer) +#define CDS_IPA_RX_RDY_RING_BASE_PADDR \ + (&((hdd_context_t *) \ + (gp_cds_context->pHDDContext))->rx_rdy_ring_base_paddr) +#define CDS_IPA_RX_RDY_RING_SIZE \ + (&((hdd_context_t *)(gp_cds_context->pHDDContext))->rx_rdy_ring_size) +#define CDS_IPA_RX_PROC_DONE_IDX_PADDR \ + (&((hdd_context_t *) \ + (gp_cds_context->pHDDContext))->rx_proc_done_idx_paddr) +#else +#define CDS_IPA_CE_SR_BASE_PADDR (NULL) +#define CDS_IPA_CE_RING_SIZE (NULL) +#define CDS_IPA_CE_REG_PADDR (NULL) +#define CDS_IPA_TX_COMP_BASE_PADDR (NULL) +#define CDS_IPA_TX_COMP_RING_SIZE (NULL) +#define CDS_IPA_TX_NUM_BUFF (NULL) +#define CDS_IPA_RX_RDY_RING_BASE_PADDR (NULL) +#define CDS_IPA_RX_RDY_RING_SIZE (NULL) +#define CDS_IPA_RX_PROC_DONE_IDX_PADDR (NULL) +#endif /* IPA_OFFLOAD */ + +/* Data definitions */ +static cds_context_type g_cds_context; +static p_cds_contextType gp_cds_context; +static struct __cdf_device g_cdf_ctx; + +/* Debug variable to detect MC thread stuck */ +static atomic_t cds_wrapper_empty_count; + +static uint8_t cds_multicast_logging; + +void cds_sys_probe_thread_cback(void *pUserData); + +/** + * cds_alloc_global_context() - allocate CDS global context + * @p_cds_context: A pointer to where to store the CDS Context + * + * cds_alloc_global_context() function allocates the CDS global Context, + * but does not initialize all the members. This overal initialization will + * happen at cds_open(). + * + * Return: CDF status + */ +CDF_STATUS cds_alloc_global_context(v_CONTEXT_t *p_cds_context) +{ + if (p_cds_context == NULL) + return CDF_STATUS_E_FAILURE; + + /* allocate the CDS Context */ + *p_cds_context = NULL; + gp_cds_context = &g_cds_context; + + cdf_mem_zero(gp_cds_context, sizeof(cds_context_type)); + *p_cds_context = gp_cds_context; + + gp_cds_context->cdf_ctx = &g_cdf_ctx; + cdf_mem_zero(&g_cdf_ctx, sizeof(g_cdf_ctx)); + + /* initialize the spinlock */ + cdf_trace_spin_lock_init(); + /* it is the right time to initialize MTRACE structures */ +#if defined(TRACE_RECORD) + cdf_trace_init(); +#endif + + cdf_dp_trace_init(); + return CDF_STATUS_SUCCESS; +} /* cds_alloc_global_context() */ + +/** + * cds_free_global_context() - free CDS global context + * @p_cds_context: A pointer to where the CDS Context was stored + * + * cds_free_global_context() function frees the CDS Context. + * + * Return: CDF status + */ +CDF_STATUS cds_free_global_context(v_CONTEXT_t *p_cds_context) +{ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: De-allocating the CDS Context", __func__); + + if ((p_cds_context == NULL) || (*p_cds_context == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: vOS Context is Null", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (gp_cds_context != *p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Context mismatch", __func__); + return CDF_STATUS_E_FAILURE; + } + gp_cds_context->cdf_ctx = NULL; + *p_cds_context = gp_cds_context = NULL; + + return CDF_STATUS_SUCCESS; +} /* cds_free_global_context() */ + +#ifdef WLAN_FEATURE_NAN +/** + * cds_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 cds_set_nan_enable(tMacOpenParameters *param, + hdd_context_t *hdd_ctx) +{ + param->is_nan_enabled = hdd_ctx->config->enable_nan_support; +} +#else +static void cds_set_nan_enable(tMacOpenParameters *param, + hdd_context_t *pHddCtx) +{ +} +#endif + +/** + * cds_open() - open the CDS Module + * @p_cds_context: A pointer to where the CDS Context was stored + * @hddContextSize: Size of the HDD context to allocate. + * + * cds_open() function opens the CDS Scheduler + * Upon successful initialization: + * - All CDS submodules should have been initialized + * + * - The CDS scheduler should have opened + * + * - All the WLAN SW components should have been opened. This includes + * SYS, MAC, SME, WMA and TL. + * + * Return: CDF status + */ +CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int iter = 0; + tSirRetStatus sirStatus = eSIR_SUCCESS; + tMacOpenParameters mac_openParms; + cdf_device_t cdf_ctx; + HTC_INIT_INFO htcInfo; + struct ol_softc *scn; + void *HTCHandle; + hdd_context_t *pHddCtx; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Opening CDS", __func__); + + if (NULL == gp_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Trying to open CDS without a PreOpen", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* Initialize the timer module */ + cdf_timer_module_init(); + + /* Initialize bug reporting structure */ + cds_init_log_completion(); + + /* Initialize the probe event */ + if (cdf_event_init(&gp_cds_context->ProbeEvent) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Unable to init probeEvent", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + if (cdf_event_init(&(gp_cds_context->wmaCompleteEvent)) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Unable to init wmaCompleteEvent", __func__); + CDF_ASSERT(0); + goto err_probe_event; + } + + /* Initialize the free message queue */ + cdf_status = cds_mq_init(&gp_cds_context->freeVosMq); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to initialize CDS free message queue", + __func__); + CDF_ASSERT(0); + goto err_wma_complete_event; + } + + for (iter = 0; iter < CDS_CORE_MAX_MESSAGES; iter++) { + (gp_cds_context->aMsgWrappers[iter]).pVosMsg = + &(gp_cds_context->aMsgBuffers[iter]); + INIT_LIST_HEAD(&gp_cds_context->aMsgWrappers[iter].msgNode); + cds_mq_put(&gp_cds_context->freeVosMq, + &(gp_cds_context->aMsgWrappers[iter])); + } + + /* Now Open the CDS Scheduler */ + cdf_status = cds_sched_open(gp_cds_context, &gp_cds_context->cdf_sched, + sizeof(cds_sched_context)); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to open CDS Scheduler", __func__); + CDF_ASSERT(0); + goto err_msg_queue; + } + + pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); + if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Hdd Context is Null", __func__); + CDF_ASSERT(0); + goto err_sched_close; + } + + scn = cds_get_context(CDF_MODULE_ID_HIF); + if (!scn) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + goto err_sched_close; + } + scn->enableuartprint = pHddCtx->config->enablefwprint; + scn->enablefwlog = pHddCtx->config->enablefwlog; + scn->max_no_of_peers = pHddCtx->config->maxNumberOfPeers; +#ifdef WLAN_FEATURE_LPSS + scn->enablelpasssupport = pHddCtx->config->enablelpasssupport; +#endif + scn->enable_ramdump_collection = + pHddCtx->config->is_ramdump_enabled; + scn->enable_self_recovery = pHddCtx->config->enableSelfRecovery; + + /* Initialize BMI and Download firmware */ + cdf_status = bmi_download_firmware(scn); + if (cdf_status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "BMI FIALED status:%d", cdf_status); + goto err_bmi_close; + } + + htcInfo.pContext = gp_cds_context->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + + /* Create HTC */ + gp_cds_context->htc_ctx = + htc_create(htcInfo.pContext, &htcInfo, cdf_ctx); + if (!gp_cds_context->htc_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + goto err_bmi_close; + } + + if (bmi_done(scn)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_htc_close; + } + + /* + ** Need to open WMA first because it calls WDI_Init, which calls wpalOpen + ** The reason that is needed becasue cds_packet_open need to use PAL APIs + */ + + /*Open the WMA module */ + cdf_mem_set(&mac_openParms, sizeof(mac_openParms), 0); + /* UMA is supported in hardware for performing the + ** frame translation 802.11 <-> 802.3 + */ + mac_openParms.frameTransRequired = 1; + mac_openParms.driverType = eDRIVER_TYPE_PRODUCTION; + mac_openParms.powersaveOffloadEnabled = + pHddCtx->config->enablePowersaveOffload; + mac_openParms.staDynamicDtim = pHddCtx->config->enableDynamicDTIM; + mac_openParms.staModDtim = pHddCtx->config->enableModulatedDTIM; + mac_openParms.staMaxLIModDtim = pHddCtx->config->fMaxLIModulatedDTIM; + mac_openParms.wowEnable = pHddCtx->config->wowEnable; + mac_openParms.maxWoWFilters = pHddCtx->config->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->config->fhostArpOffload) + mac_openParms.olIniInfo = mac_openParms.olIniInfo | 0x1; + if (pHddCtx->config->fhostNSOffload) + mac_openParms.olIniInfo = mac_openParms.olIniInfo | 0x2; + /* + * Copy the DFS Phyerr Filtering Offload status. + * This parameter reflects the value of the + * dfsPhyerrFilterOffload flag as set in the ini. + */ + mac_openParms.dfsPhyerrFilterOffload = + pHddCtx->config->fDfsPhyerrFilterOffload; + if (pHddCtx->config->ssdp) + mac_openParms.ssdp = pHddCtx->config->ssdp; +#ifdef FEATURE_WLAN_RA_FILTERING + mac_openParms.RArateLimitInterval = + pHddCtx->config->RArateLimitInterval; + mac_openParms.IsRArateLimitEnabled = + pHddCtx->config->IsRArateLimitEnabled; +#endif + + mac_openParms.apMaxOffloadPeers = pHddCtx->config->apMaxOffloadPeers; + + mac_openParms.apMaxOffloadReorderBuffs = + pHddCtx->config->apMaxOffloadReorderBuffs; + + mac_openParms.apDisableIntraBssFwd = + pHddCtx->config->apDisableIntraBssFwd; + + mac_openParms.dfsRadarPriMultiplier = + pHddCtx->config->dfsRadarPriMultiplier; + mac_openParms.reorderOffload = pHddCtx->config->reorderOffloadSupport; + + /* IPA micro controller data path offload resource config item */ + mac_openParms.ucOffloadEnabled = hdd_ipa_uc_is_enabled(pHddCtx); + mac_openParms.ucTxBufCount = pHddCtx->config->IpaUcTxBufCount; + mac_openParms.ucTxBufSize = pHddCtx->config->IpaUcTxBufSize; + mac_openParms.ucRxIndRingCount = pHddCtx->config->IpaUcRxIndRingCount; + mac_openParms.ucTxPartitionBase = pHddCtx->config->IpaUcTxPartitionBase; + mac_openParms.max_scan = pHddCtx->config->max_scan_count; + + mac_openParms.ip_tcp_udp_checksum_offload = + pHddCtx->config->enable_ip_tcp_udp_checksum_offload; + mac_openParms.enable_rxthread = pHddCtx->config->enableRxThread; + mac_openParms.ce_classify_enabled = + pHddCtx->config->ce_classify_enabled; + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + mac_openParms.tx_flow_stop_queue_th = + pHddCtx->config->TxFlowStopQueueThreshold; + mac_openParms.tx_flow_start_queue_offset = + pHddCtx->config->TxFlowStartQueueOffset; +#endif + cds_set_nan_enable(&mac_openParms, pHddCtx); + + mac_openParms.tx_chain_mask_cck = pHddCtx->config->tx_chain_mask_cck; + mac_openParms.self_gen_frm_pwr = pHddCtx->config->self_gen_frm_pwr; + + cdf_status = wma_open(gp_cds_context, + hdd_update_tgt_cfg, + hdd_dfs_indicate_radar, &mac_openParms); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to open WMA module", __func__); + CDF_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 mac_openParms.maxStation. So, make sure + * config entry pHddCtx->config->maxNumberOfPeers has adjusted value + */ + pHddCtx->config->maxNumberOfPeers = mac_openParms.maxStation; + HTCHandle = cds_get_context(CDF_MODULE_ID_HTC); + if (!HTCHandle) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: HTCHandle is null!", __func__); + goto err_wma_close; + } + if (htc_wait_target(HTCHandle)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_wma_close; + } + + /* Now proceed to open the MAC */ + + /* UMA is supported in hardware for performing the + * frame translation 802.11 <-> 802.3 + */ + mac_openParms.frameTransRequired = 1; + + sirStatus = + mac_open(&(gp_cds_context->pMACContext), gp_cds_context->pHDDContext, + &mac_openParms); + + if (eSIR_SUCCESS != sirStatus) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to open MAC", __func__); + CDF_ASSERT(0); + goto err_wma_close; + } + + /* Now proceed to open the SME */ + cdf_status = sme_open(gp_cds_context->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to open SME", __func__); + CDF_ASSERT(0); + goto err_mac_close; + } + + gp_cds_context->pdev_txrx_ctx = + ol_txrx_pdev_alloc(gp_cds_context->cfg_ctx, + gp_cds_context->htc_ctx, + gp_cds_context->cdf_ctx); + if (!gp_cds_context->pdev_txrx_ctx) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to open TXRX", __func__); + CDF_ASSERT(0); + goto err_sme_close; + } + + ol_txrx_ipa_uc_get_resource(gp_cds_context->pdev_txrx_ctx, + CDS_IPA_CE_SR_BASE_PADDR, + CDS_IPA_CE_RING_SIZE, + CDS_IPA_CE_REG_PADDR, + CDS_IPA_TX_COMP_BASE_PADDR, + CDS_IPA_TX_COMP_RING_SIZE, + CDS_IPA_TX_NUM_BUFF, + CDS_IPA_RX_RDY_RING_BASE_PADDR, + CDS_IPA_RX_RDY_RING_SIZE, + CDS_IPA_RX_PROC_DONE_IDX_PADDR); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS successfully Opened", __func__); + + *p_cds_context = gp_cds_context; + + return CDF_STATUS_SUCCESS; + +err_sme_close: + sme_close(gp_cds_context->pMACContext); + +err_mac_close: + mac_close(gp_cds_context->pMACContext); + +err_wma_close: + wma_close(gp_cds_context); + + wma_wmi_service_close(gp_cds_context); + +err_htc_close: + if (gp_cds_context->htc_ctx) { + htc_destroy(gp_cds_context->htc_ctx); + gp_cds_context->htc_ctx = NULL; + } + +err_bmi_close: + bmi_cleanup(scn); + +err_sched_close: + cds_sched_close(gp_cds_context); + +err_msg_queue: + cds_mq_deinit(&gp_cds_context->freeVosMq); + +err_wma_complete_event: + cdf_event_destroy(&gp_cds_context->wmaCompleteEvent); + +err_probe_event: + cdf_event_destroy(&gp_cds_context->ProbeEvent); + + return CDF_STATUS_E_FAILURE; +} /* cds_open() */ + +/** + * cds_pre_enable() - pre enable cds + * @cds_context: CDS context + * + * Return: CDF status + */ +CDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; + void *scn; + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, "cds prestart"); + + if (gp_cds_context != p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Context mismatch", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + if (p_cds_context->pMACContext == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: MAC NULL context", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + if (p_cds_context->pWMAContext == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: WMA NULL context", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + + scn = cds_get_context(CDF_MODULE_ID_HIF); + if (!scn) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + return CDF_STATUS_E_FAILURE; + } + + /* Reset wma wait event */ + cdf_event_reset(&gp_cds_context->wmaCompleteEvent); + + /*call WMA pre start */ + cdf_status = wma_pre_start(gp_cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_FATAL, + "Failed to WMA prestart"); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* Need to update time out of complete */ + cdf_status = cdf_wait_single_event(&gp_cds_context->wmaCompleteEvent, + CDS_WMA_TIMEOUT); + if (cdf_status != CDF_STATUS_SUCCESS) { + if (cdf_status == CDF_STATUS_E_TIMEOUT) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Timeout occurred before WMA complete", + __func__); + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: wma_pre_start reporting other error", + __func__); + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Test MC thread by posting a probe message to SYS", + __func__); + wlan_sys_probe(); + + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + cdf_status = htc_start(gp_cds_context->htc_ctx); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_FATAL, + "Failed to Start HTC"); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + cdf_status = wma_wait_for_ready_event(gp_cds_context->pWMAContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Failed to get ready event from target firmware"); + htc_set_target_to_sleep(scn); + htc_stop(gp_cds_context->htc_ctx); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + if (ol_txrx_pdev_attach(gp_cds_context->pdev_txrx_ctx)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Failed to attach pdev"); + htc_set_target_to_sleep(scn); + htc_stop(gp_cds_context->htc_ctx); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + htc_set_target_to_sleep(scn); + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_enable() - start/enable cds module + * @cds_context: CDS context + * + * Return: CDF status + */ +CDF_STATUS cds_enable(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tSirRetStatus sirStatus = eSIR_SUCCESS; + p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; + tHalMacStartParameters halStartParams; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Starting Libra SW", __func__); + + /* We support only one instance for now ... */ + if (gp_cds_context != p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: mismatch in context", __func__); + return CDF_STATUS_E_FAILURE; + } + + if ((p_cds_context->pWMAContext == NULL) || + (p_cds_context->pMACContext == NULL)) { + if (p_cds_context->pWMAContext == NULL) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: WMA NULL context", __func__); + else + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: MAC NULL context", __func__); + + return CDF_STATUS_E_FAILURE; + } + + /* Start the wma */ + cdf_status = wma_start(p_cds_context); + if (cdf_status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to start wma", __func__); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: wma correctly started", __func__); + + /* Start the MAC */ + cdf_mem_zero(&halStartParams, + sizeof(tHalMacStartParameters)); + + /* Start the MAC */ + sirStatus = + mac_start(p_cds_context->pMACContext, &halStartParams); + + if (eSIR_SUCCESS != sirStatus) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to start MAC", __func__); + goto err_wma_stop; + } + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: MAC correctly started", __func__); + + /* START SME */ + cdf_status = sme_start(p_cds_context->pMACContext); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to start SME", __func__); + goto err_mac_stop; + } + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: SME correctly started", __func__); + + if (ol_txrx_pdev_attach_target + (p_cds_context->pdev_txrx_ctx) != A_OK) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed attach target", __func__); + goto err_sme_stop; + } + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "TL correctly started"); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: CDS Start is successful!!", __func__); + + return CDF_STATUS_SUCCESS; + +err_sme_stop: + sme_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET); + +err_mac_stop: + mac_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET); + +err_wma_stop: + cdf_event_reset(&(gp_cds_context->wmaCompleteEvent)); + cdf_status = wma_stop(p_cds_context, HAL_STOP_TYPE_RF_KILL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop wma", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + wma_setneedshutdown(cds_context); + } else { + cdf_status = + cdf_wait_single_event(&(gp_cds_context->wmaCompleteEvent), + CDS_WMA_TIMEOUT); + if (cdf_status != CDF_STATUS_SUCCESS) { + if (cdf_status == CDF_STATUS_E_TIMEOUT) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_FATAL, + "%s: Timeout occurred before WMA_stop complete", + __func__); + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_FATAL, + "%s: WMA_stop reporting other error", + __func__); + } + CDF_ASSERT(0); + wma_setneedshutdown(cds_context); + } + } + + return CDF_STATUS_E_FAILURE; +} /* cds_enable() */ + +/** + * cds_disable() - stop/disable cds module + * @cds_context: CDS context + * + * Return: CDF status + */ +CDF_STATUS cds_disable(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status; + + /* wma_stop is called before the SYS so that the processing of target + * pending responses will not be handled during uninitialization of + * WLAN driver + */ + cdf_event_reset(&(gp_cds_context->wmaCompleteEvent)); + + cdf_status = wma_stop(cds_context, HAL_STOP_TYPE_RF_KILL); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop wma", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + wma_setneedshutdown(cds_context); + } + + hif_disable_isr(((cds_context_type *) cds_context)->pHIFContext); + hif_reset_soc(((cds_context_type *) cds_context)->pHIFContext); + + /* SYS STOP will stop SME and MAC */ + cdf_status = sys_stop(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop SYS", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_close() - close cds module + * @cds_context: CDS context + * + * Return: CDF status + */ +CDF_STATUS cds_close(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status; + + if (gp_cds_context->htc_ctx) { + htc_stop(gp_cds_context->htc_ctx); + htc_destroy(gp_cds_context->htc_ctx); + gp_cds_context->htc_ctx = NULL; + } + + ol_txrx_pdev_detach(gp_cds_context->pdev_txrx_ctx, 1); + cds_free_context(cds_context, CDF_MODULE_ID_TXRX, + gp_cds_context->pdev_txrx_ctx); + + cdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close SME", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + ((p_cds_contextType) cds_context)->pMACContext = NULL; + + if (true == wma_needshutdown(cds_context)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to shutdown wma", __func__); + } else { + cdf_status = wma_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + } + + cdf_status = wma_wmi_service_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq); + + cdf_status = cdf_event_destroy(&gp_cds_context->wmaCompleteEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: failed to destroy wmaCompleteEvent", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cdf_status = cdf_event_destroy(&gp_cds_context->ProbeEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: failed to destroy ProbeEvent", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cds_deinit_log_completion(); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_get_context() - get context data area + * + * @moduleId: ID of the module who's context data is being retrived. + * + * Each module in the system has a context / data area that is allocated + * and managed by CDS. This API allows any user to get a pointer to its + * allocated context data area from the CDS global context. + * + * Return: pointer to the context data area of the module ID + * specified, or NULL if the context data is not allocated for + * the module ID specified + */ +void *cds_get_context(CDF_MODULE_ID moduleId) +{ + void *pModContext = NULL; + + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: cds context pointer is null", __func__); + return NULL; + } + + switch (moduleId) { +#ifndef WLAN_FEATURE_MBSSID + case CDF_MODULE_ID_SAP: + { + pModContext = gp_cds_context->pSAPContext; + break; + } +#endif + + case CDF_MODULE_ID_HDD: + { + pModContext = gp_cds_context->pHDDContext; + break; + } + + case CDF_MODULE_ID_SME: + case CDF_MODULE_ID_PE: + { + /* In all these cases, we just return the MAC Context */ + pModContext = gp_cds_context->pMACContext; + break; + } + + case CDF_MODULE_ID_WMA: + { + /* For wma module */ + pModContext = gp_cds_context->pWMAContext; + break; + } + + case CDF_MODULE_ID_CDF: + { + /* For SYS this is CDS itself */ + pModContext = gp_cds_context; + break; + } + + case CDF_MODULE_ID_HIF: + { + pModContext = gp_cds_context->pHIFContext; + break; + } + + case CDF_MODULE_ID_HTC: + { + pModContext = gp_cds_context->htc_ctx; + break; + } + + case CDF_MODULE_ID_CDF_DEVICE: + { + pModContext = gp_cds_context->cdf_ctx; + break; + } + + case CDF_MODULE_ID_TXRX: + { + pModContext = gp_cds_context->pdev_txrx_ctx; + break; + } + + case CDF_MODULE_ID_CFG: + { + pModContext = gp_cds_context->cfg_ctx; + break; + } + + default: + { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i does not have its context maintained by CDS", + __func__, moduleId); + CDF_ASSERT(0); + return NULL; + } + } + + if (pModContext == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i context is Null", __func__, + moduleId); + } + + return pModContext; +} /* cds_get_context() */ + +/** + * cds_get_global_context() - get CDS global Context + * + * This API allows any user to get the CDS Global Context pointer from a + * module context data area. + * + * Return: pointer to the CDS global context, NULL if the function is + * unable to retreive the CDS context. + */ +v_CONTEXT_t cds_get_global_context(void) +{ + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + } + + return gp_cds_context; +} /* cds_get_global_context() */ + +/** + * cds_is_logp_in_progress() - check if ssr/self recovery is going on + * + * Return: true if ssr/self recvoery is going on else false + */ +uint8_t cds_is_logp_in_progress(void) +{ + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + return 1; + } + + return gp_cds_context->isLogpInProgress; +} + +/** + * cds_set_logp_in_progress() - set ssr/self recovery in progress + * @value: value to set + * + * Return: none + */ +void cds_set_logp_in_progress(uint8_t value) +{ + hdd_context_t *pHddCtx = NULL; + + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + return; + } + gp_cds_context->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 = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: HDD context is Null", __func__); + return; + } + pHddCtx->isLogpInProgress = value; +} + +/** + * cds_is_load_unload_in_progress() - check if driver load/unload in progress + * + * Return: true if load/unload is going on else false + */ +uint8_t cds_is_load_unload_in_progress(void) +{ + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + return 0; + } + + return gp_cds_context->isLoadUnloadInProgress; +} + +/** + * cds_set_load_unload_in_progress() - set load/unload in progress + * @value: value to set + * + * Return: none + */ +void cds_set_load_unload_in_progress(uint8_t value) +{ + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + return; + } + gp_cds_context->isLoadUnloadInProgress = value; + +#ifdef CONFIG_CNSS + if (value) + cnss_set_driver_status(CNSS_LOAD_UNLOAD); + else + cnss_set_driver_status(CNSS_INITIALIZED); +#endif +} + +/** + * cds_alloc_context() - allocate a context within the CDS global Context + * @p_cds_context: pointer to the global Vos context + * @moduleId: module ID who's context area is being allocated. + * @ppModuleContext: pointer to location where the pointer to the + * allocated context is returned. Note this output pointer + * is valid only if the API returns CDF_STATUS_SUCCESS + * @param size: size of the context area to be allocated. + * + * This API allows any user to allocate a user context area within the + * CDS Global Context. + * + * Return: CDF status + */ +CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, + void **ppModuleContext, uint32_t size) +{ + void **pGpModContext = NULL; + + if (p_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is null", __func__); + return CDF_STATUS_E_FAILURE; + } + + if ((gp_cds_context != p_cds_context) || (ppModuleContext == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: context mismatch or null param passed", + __func__); + return CDF_STATUS_E_FAILURE; + } + + switch (moduleID) { + +#ifndef WLAN_FEATURE_MBSSID + case CDF_MODULE_ID_SAP: + { + pGpModContext = &(gp_cds_context->pSAPContext); + break; + } +#endif + + case CDF_MODULE_ID_WMA: + { + pGpModContext = &(gp_cds_context->pWMAContext); + break; + } + + case CDF_MODULE_ID_HIF: + { + pGpModContext = &(gp_cds_context->pHIFContext); + break; + } + + case CDF_MODULE_ID_EPPING: + { + pGpModContext = &(gp_cds_context->epping_ctx); + break; + } + case CDF_MODULE_ID_SME: + case CDF_MODULE_ID_PE: + case CDF_MODULE_ID_HDD: + case CDF_MODULE_ID_HDD_SOFTAP: + default: + { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i " + "does not have its context allocated by CDS", + __func__, moduleID); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + } + + if (NULL != *pGpModContext) { + /* Context has already been allocated! + * Prevent double allocation + */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i context has already been allocated", + __func__, moduleID); + return CDF_STATUS_E_EXISTS; + } + + /* Dynamically allocate the context for module */ + + *ppModuleContext = cdf_mem_malloc(size); + + if (*ppModuleContext == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to " "allocate Context for module ID %i", + __func__, moduleID); + CDF_ASSERT(0); + return CDF_STATUS_E_NOMEM; + } + + if (moduleID == CDF_MODULE_ID_TLSHIM) + cdf_mem_zero(*ppModuleContext, size); + + *pGpModContext = *ppModuleContext; + + return CDF_STATUS_SUCCESS; +} /* cds_alloc_context() */ + +/** + * cds_free_context() - free an allocated context within the + * CDS global Context + * @p_cds_context: pointer to the global Vos context + * @moduleId: module ID who's context area is being free + * @pModuleContext: pointer to module context area to be free'd. + * + * This API allows a user to free the user context area within the + * CDS Global Context. + * + * Return: CDF status + */ +CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID, + void *pModuleContext) +{ + void **pGpModContext = NULL; + + if ((p_cds_context == NULL) || (gp_cds_context != p_cds_context) || + (pModuleContext == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null params or context mismatch", __func__); + return CDF_STATUS_E_FAILURE; + } + + switch (moduleID) { +#ifndef WLAN_FEATURE_MBSSID + case CDF_MODULE_ID_SAP: + { + pGpModContext = &(gp_cds_context->pSAPContext); + break; + } +#endif + + case CDF_MODULE_ID_WMA: + { + pGpModContext = &(gp_cds_context->pWMAContext); + break; + } + + case CDF_MODULE_ID_HIF: + { + pGpModContext = &(gp_cds_context->pHIFContext); + break; + } + + case CDF_MODULE_ID_EPPING: + { + pGpModContext = &(gp_cds_context->epping_ctx); + break; + } + + case CDF_MODULE_ID_TXRX: + { + pGpModContext = &(gp_cds_context->pdev_txrx_ctx); + break; + } + + case CDF_MODULE_ID_HDD: + case CDF_MODULE_ID_SME: + case CDF_MODULE_ID_PE: + case CDF_MODULE_ID_HDD_SOFTAP: + default: + { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i " + "does not have its context allocated by CDS", + __func__, moduleID); + CDF_ASSERT(0); + return CDF_STATUS_E_INVAL; + } + } + + if (NULL == *pGpModContext) { + /* Context has not been allocated or freed already! */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Module ID %i " + "context has not been allocated or freed already", + __func__, moduleID); + return CDF_STATUS_E_FAILURE; + } + + if (*pGpModContext != pModuleContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: pGpModContext != pModuleContext", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (pModuleContext != NULL) + cdf_mem_free(pModuleContext); + + *pGpModContext = NULL; + + return CDF_STATUS_SUCCESS; +} /* cds_free_context() */ + +/** + * cds_mq_post_message() - post a message to a message queue + * @msgQueueId: identifies the message queue upon which the message + * will be posted. + * @message: a pointer to a message buffer. Memory for this message + * buffer is allocated by the caller and free'd by the CDF 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: CDF status + */ +CDF_STATUS cds_mq_post_message(CDS_MQ_ID msgQueueId, cds_msg_t *pMsg) +{ + p_cds_mq_type pTargetMq = NULL; + p_cds_msg_wrapper pMsgWrapper = NULL; + uint32_t debug_count = 0; + + if ((gp_cds_context == NULL) || (pMsg == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null params or global cds context is null", + __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + switch (msgQueueId) { + /* Message Queue ID for messages bound for SME */ + case CDS_MQ_ID_SME: + { + pTargetMq = &(gp_cds_context->cdf_sched.smeMcMq); + break; + } + + /* Message Queue ID for messages bound for PE */ + case CDS_MQ_ID_PE: + { + pTargetMq = &(gp_cds_context->cdf_sched.peMcMq); + break; + } + + /* Message Queue ID for messages bound for wma */ + case CDS_MQ_ID_WMA: + { + pTargetMq = &(gp_cds_context->cdf_sched.wmaMcMq); + break; + } + + /* Message Queue ID for messages bound for the SYS module */ + case CDS_MQ_ID_SYS: + { + pTargetMq = &(gp_cds_context->cdf_sched.sysMcMq); + break; + } + + default: + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("%s: Trying to queue msg into unknown MC Msg queue ID %d"), + __func__, msgQueueId); + + return CDF_STATUS_E_FAILURE; + } + + CDF_ASSERT(NULL != pTargetMq); + if (pTargetMq == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: pTargetMq == NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + /* Try and get a free Msg wrapper */ + pMsgWrapper = cds_mq_get(&gp_cds_context->freeVosMq); + + if (NULL == pMsgWrapper) { + debug_count = atomic_inc_return(&cds_wrapper_empty_count); + if (1 == debug_count) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: CDS Core run out of message wrapper %d", + __func__, debug_count); + + if (CDS_WRAPPER_MAX_FAIL_COUNT == debug_count) + CDF_BUG(0); + + return CDF_STATUS_E_RESOURCES; + } + + atomic_set(&cds_wrapper_empty_count, 0); + + /* Copy the message now */ + cdf_mem_copy((void *)pMsgWrapper->pVosMsg, + (void *)pMsg, sizeof(cds_msg_t)); + + cds_mq_put(pTargetMq, pMsgWrapper); + + set_bit(MC_POST_EVENT_MASK, &gp_cds_context->cdf_sched.mcEventFlag); + wake_up_interruptible(&gp_cds_context->cdf_sched.mcWaitQueue); + + return CDF_STATUS_SUCCESS; +} /* cds_mq_post_message() */ + +/** + * cds_sys_probe_thread_cback() - probe mc thread callback + * @pUserData: pointer to user data + * + * Return: none + */ +void cds_sys_probe_thread_cback(void *pUserData) +{ + if (gp_cds_context != pUserData) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: gp_cds_context != pUserData", __func__); + return; + } + + if (cdf_event_set(&gp_cds_context->ProbeEvent) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: cdf_event_set failed", __func__); + return; + } +} /* cds_sys_probe_thread_cback() */ + +/** + * cds_wma_complete_cback() - wma complete callback + * @pUserData: pointer to user data + * + * Return: none + */ +void cds_wma_complete_cback(void *pUserData) +{ + if (gp_cds_context != pUserData) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: gp_cds_context != pUserData", __func__); + return; + } + + if (cdf_event_set(&gp_cds_context->wmaCompleteEvent) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: cdf_event_set failed", __func__); + return; + } +} /* cds_wma_complete_cback() */ + +/** + * cds_core_return_msg() - return core message + * @pVContext: pointer to cds context + * @pMsgWrapper: pointer to message wrapper + * + * Return: none + */ +void cds_core_return_msg(void *pVContext, p_cds_msg_wrapper pMsgWrapper) +{ + p_cds_contextType p_cds_context = (p_cds_contextType) pVContext; + + CDF_ASSERT(gp_cds_context == p_cds_context); + + if (gp_cds_context != p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: gp_cds_context != p_cds_context", __func__); + return; + } + + CDF_ASSERT(NULL != pMsgWrapper); + + if (pMsgWrapper == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper == NULL in function", __func__); + return; + } + + /* + ** Return the message on the free message queue + */ + INIT_LIST_HEAD(&pMsgWrapper->msgNode); + cds_mq_put(&p_cds_context->freeVosMq, pMsgWrapper); +} /* cds_core_return_msg() */ + + +/** + * cds_shutdown() - shutdown CDS + * @cds_context: global cds context + * + * Return: CDF status + */ +CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status; + tpAniSirGlobal pmac = (((p_cds_contextType)cds_context)->pMACContext); + + ol_txrx_pdev_detach(gp_cds_context->pdev_txrx_ctx, 1); + cds_free_context(cds_context, CDF_MODULE_ID_TXRX, + gp_cds_context->pdev_txrx_ctx); + + cdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close SME", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + /* + * 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) { + cdf_mc_timer_stop(&pmac->sap.SapDfsInfo.sap_dfs_cac_timer); + pmac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + cdf_mc_timer_destroy(&pmac->sap.SapDfsInfo.sap_dfs_cac_timer); + } + + cdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + ((p_cds_contextType) cds_context)->pMACContext = NULL; + + if (false == wma_needshutdown(cds_context)) { + + cdf_status = wma_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma!", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + } + + if (gp_cds_context->htc_ctx) { + htc_stop(gp_cds_context->htc_ctx); + htc_destroy(gp_cds_context->htc_ctx); + gp_cds_context->htc_ctx = NULL; + } + + cdf_status = wma_wmi_service_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service!", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq); + + cdf_status = cdf_event_destroy(&gp_cds_context->wmaCompleteEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: failed to destroy wmaCompleteEvent", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cdf_status = cdf_event_destroy(&gp_cds_context->ProbeEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: failed to destroy ProbeEvent", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_get_vdev_types() - get vdev type + * @mode: mode + * @type: type + * @sub_type: sub_type + * + * Return: WMI vdev type + */ +CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type, + uint32_t *sub_type) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + *type = 0; + *sub_type = 0; + + switch (mode) { + case CDF_STA_MODE: + *type = WMI_VDEV_TYPE_STA; + break; + case CDF_SAP_MODE: + *type = WMI_VDEV_TYPE_AP; + break; + case CDF_P2P_DEVICE_MODE: + *type = WMI_VDEV_TYPE_AP; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; + break; + case CDF_P2P_CLIENT_MODE: + *type = WMI_VDEV_TYPE_STA; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT; + break; + case CDF_P2P_GO_MODE: + *type = WMI_VDEV_TYPE_AP; + *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO; + break; + case CDF_OCB_MODE: + *type = WMI_VDEV_TYPE_OCB; + break; + default: + hddLog(CDF_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); + status = CDF_STATUS_E_INVAL; + break; + } + return status; +} + +/** + * cds_flush_work() - flush pending works + * @work: pointer to work + * + * Return: none + */ +void cds_flush_work(void *work) +{ +#if defined (CONFIG_CNSS) + cnss_flush_work(work); +#elif defined (WLAN_OPEN_SOURCE) + cancel_work_sync(work); +#endif +} + +/** + * cds_flush_delayed_work() - flush delayed works + * @dwork: pointer to delayed work + * + * Return: none + */ +void cds_flush_delayed_work(void *dwork) +{ +#if defined (CONFIG_CNSS) + cnss_flush_delayed_work(dwork); +#elif defined (WLAN_OPEN_SOURCE) + cancel_delayed_work_sync(dwork); +#endif +} + +/** + * cds_is_packet_log_enabled() - check if packet log is enabled + * + * Return: true if packet log is enabled else false + */ +bool cds_is_packet_log_enabled(void) +{ + hdd_context_t *pHddCtx; + + pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); + if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Hdd Context is Null", __func__); + return false; + } + + return pHddCtx->config->enablePacketLog; +} + +/** + * cds_trigger_recovery() - trigger self recovery + * + * Return: none + */ +void cds_trigger_recovery(void) +{ + tp_wma_handle wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (!wma_handle) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "WMA context is invald!"); + return; + } + + wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0); + + status = cdf_wait_single_event(&wma_handle->recovery_event, + WMA_CRASH_INJECT_TIMEOUT); + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "CRASH_INJECT command is timed out!"); + #ifdef CONFIG_CNSS + if (cds_is_logp_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "LOGP is in progress, ignore!"); + return; + } + cds_set_logp_in_progress(true); + cnss_schedule_recovery_work(); + #endif + + return; + } +} + +/** + * cds_get_monotonic_boottime() - Get kernel boot time. + * + * Return: Time in microseconds + */ + +uint64_t cds_get_monotonic_boottime(void) +{ +#ifdef CONFIG_CNSS + struct timespec ts; + + cnss_get_monotonic_boottime(&ts); + return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); +#else + return ((uint64_t)cdf_system_ticks_to_msecs(cdf_system_ticks()) * + 1000); +#endif +} + +/** + * cds_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 cds_set_wakelock_logging(bool value) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "cds context is Invald"); + return; + } + p_cds_context->is_wakelock_log_enabled = value; +} + +/** + * cds_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 cds_is_wakelock_enabled(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "cds context is Invald"); + return false; + } + return p_cds_context->is_wakelock_log_enabled; +} + +/** + * cds_set_ring_log_level() - Sets the log level of a particular ring + * @ring_id: ring_id + * @log_levelvalue: Log level specificed + * + * This function converts HLOS values to driver log levels and sets the log + * level of a particular ring accordingly. + * + * Return: None + */ +void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level) +{ + p_cds_contextType p_cds_context; + uint32_t log_val; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds 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) { + p_cds_context->wakelock_log_level = log_val; + return; + } else if (ring_id == RING_ID_CONNECTIVITY) { + p_cds_context->connectivity_log_level = log_val; + return; + } else if (ring_id == RING_ID_PER_PACKET_STATS) { + p_cds_context->packet_stats_log_level = log_val; + return; + } else if (ring_id == RIND_ID_DRIVER_DEBUG) { + p_cds_context->driver_debug_log_level = log_val; + return; + } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { + p_cds_context->fw_debug_log_level = log_val; + return; + } +} + +/** + * cds_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 cds_get_ring_log_level(uint32_t ring_id) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invald", __func__); + return WLAN_LOG_LEVEL_OFF; + } + + if (ring_id == RING_ID_WAKELOCK) + return p_cds_context->wakelock_log_level; + else if (ring_id == RING_ID_CONNECTIVITY) + return p_cds_context->connectivity_log_level; + else if (ring_id == RING_ID_PER_PACKET_STATS) + return p_cds_context->packet_stats_log_level; + else if (ring_id == RIND_ID_DRIVER_DEBUG) + return p_cds_context->driver_debug_log_level; + else if (ring_id == RING_ID_FIRMWARE_DEBUG) + return p_cds_context->fw_debug_log_level; + + return WLAN_LOG_LEVEL_OFF; +} + +/** + * cds_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 cds_set_multicast_logging(uint8_t value) +{ + cds_multicast_logging = value; +} + +/** + * cds_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 cds_is_multicast_logging(void) +{ + return cds_multicast_logging; +} + +/* + * cds_init_log_completion() - Initialize log param structure + * + * This function is used to initialize the logging related + * parameters + * + * Return: None + */ +void cds_init_log_completion(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return; + } + + p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; + p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; + p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; + p_cds_context->log_complete.is_report_in_progress = false; + /* Attempting to initialize an already initialized lock + * results in a failure. This must be ok here. + */ + cdf_spinlock_init(&p_cds_context->bug_report_lock); +} + +/** + * cds_deinit_log_completion() - Deinitialize log param structure + * + * This function is used to deinitialize the logging related + * parameters + * + * Return: None + */ +void cds_deinit_log_completion(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return; + } + + cdf_spinlock_destroy(&p_cds_context->bug_report_lock); +} + +/** + * cds_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 + */ +CDF_STATUS cds_set_log_completion(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return CDF_STATUS_E_FAILURE; + } + + cdf_spinlock_acquire(&p_cds_context->bug_report_lock); + p_cds_context->log_complete.is_fatal = is_fatal; + p_cds_context->log_complete.indicator = indicator; + p_cds_context->log_complete.reason_code = reason_code; + p_cds_context->log_complete.is_report_in_progress = true; + cdf_spinlock_release(&p_cds_context->bug_report_lock); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_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 cds_get_log_completion(uint32_t *is_fatal, + uint32_t *indicator, + uint32_t *reason_code) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return; + } + + cdf_spinlock_acquire(&p_cds_context->bug_report_lock); + *is_fatal = p_cds_context->log_complete.is_fatal; + *indicator = p_cds_context->log_complete.indicator; + *reason_code = p_cds_context->log_complete.reason_code; + p_cds_context->log_complete.is_report_in_progress = false; + cdf_spinlock_release(&p_cds_context->bug_report_lock); +} + +/** + * cds_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 cds_is_log_report_in_progress(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return true; + } + return p_cds_context->log_complete.is_report_in_progress; +} + +/** + * cds_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 + */ +CDF_STATUS cds_flush_logs(uint32_t is_fatal, + uint32_t indicator, + uint32_t reason_code) +{ + uint32_t ret; + CDF_STATUS status; + + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (cds_is_log_report_in_progress() == true) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", + __func__, is_fatal, indicator, reason_code); + return CDF_STATUS_E_FAILURE; + } + + status = cds_set_log_completion(is_fatal, indicator, reason_code); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to set log trigger params", __func__); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", + __func__, is_fatal, indicator, reason_code); + + ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext); + if (0 != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to send flush FW log", __func__); + cds_init_log_completion(); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_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 cds_logging_set_fw_flush_complete(void) +{ + wlan_logging_set_fw_flush_complete(); +} diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c new file mode 100644 index 000000000000..71a0464baa59 --- /dev/null +++ b/core/cds/src/cds_concurrency.c @@ -0,0 +1,6823 @@ +/* + * 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. + */ + +/** + * DOC: cds_concurrency.c + * + * WLAN Concurrenct Connection Management functions + * + */ + +/* Include files */ + +#include +#include +#include +#include +#include +#include +#include "wlan_hdd_trace.h" +#include "wlan_hdd_hostapd.h" +#include "cds_concurrency.h" +#include "cdf_types.h" +#include "cdf_trace.h" + +#include +#include +#include +#include +#include +#include +#include "sap_api.h" +#include +#include +#include +#include "cfg_api.h" +#include "qwlan_version.h" +#include "wma_types.h" +#include "wma.h" +#include "wma_api.h" +#include "cds_utils.h" +#include "cds_reg_service.h" +#include "wlan_hdd_ipa.h" + +#define CDS_MAX_FEATURE_SET 8 +static struct cds_conc_connection_info + conc_connection_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + +#define CONC_CONNECTION_LIST_VALID_INDEX(index) \ + ((MAX_NUMBER_OF_CONC_CONNECTIONS > index) && \ + (conc_connection_list[index].in_use)) + +#define CDS_MAX_CON_STRING_LEN 50 +/** + * first_connection_pcl_table - table which provides PCL for the + * very first connection in the system + */ +static const enum cds_pcl_type +first_connection_pcl_table[CDS_MAX_NUM_OF_MODE] + [CDS_MAX_CONC_PRIORITY_MODE] = { + [CDS_STA_MODE] = {CDS_NONE, CDS_NONE, CDS_NONE}, + [CDS_SAP_MODE] = {CDS_5G, CDS_5G, CDS_5G }, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_5G, CDS_5G }, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_5G, CDS_5G }, + [CDS_IBSS_MODE] = {CDS_NONE, CDS_NONE, CDS_NONE}, +}; + +/** + * second_connection_pcl_dbs_table - table which provides PCL + * for the 2nd connection, when we have a connection already in + * the system (with DBS supported by HW) + */ +static const enum cds_pcl_type +second_connection_pcl_dbs_table[CDS_MAX_ONE_CONNECTION_MODE] + [CDS_MAX_NUM_OF_MODE][CDS_MAX_CONC_PRIORITY_MODE] = { + [CDS_STA_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = {CDS_5G, CDS_5G, CDS_5G } }, + + [CDS_STA_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = {CDS_5G, CDS_5G, CDS_5G } }, + + [CDS_STA_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = {CDS_24G, CDS_24G, CDS_24G } }, + + [CDS_STA_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = {CDS_24G, CDS_24G, CDS_24G } }, + + [CDS_P2P_CLI_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_5_1x1] = { + [CDS_STA_MODE] = {CDS_24G_SCC_CH, CDS_24G_SCC_CH, CDS_24G_SCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_5_2x2] = { + [CDS_STA_MODE] = {CDS_24G_SCC_CH, CDS_24G_SCC_CH, CDS_24G_SCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +}; + +/** + * second_connection_pcl_nodbs_table - table which provides PCL + * for the 2nd connection, when we have a connection already in + * the system (with DBS not supported by HW) + */ +static const enum cds_pcl_type +second_connection_pcl_nodbs_table[CDS_MAX_ONE_CONNECTION_MODE] + [CDS_MAX_NUM_OF_MODE][CDS_MAX_CONC_PRIORITY_MODE] = { + [CDS_STA_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH_5G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_24_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_24_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_24_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_24_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_SAP_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_24_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_24_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_IBSS_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +}; + +/** + * third_connection_pcl_dbs_table - table which provides PCL for + * the 3rd connection, when we have two connections already in + * the system (with DBS supported by HW) + */ +static const enum cds_pcl_type +third_connection_pcl_dbs_table[CDS_MAX_TWO_CONNECTION_MODE] + [CDS_MAX_NUM_OF_MODE][CDS_MAX_CONC_PRIORITY_MODE] = { + [CDS_STA_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_STA_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_STA_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif + [CDS_STA_P2P_GO_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_STA_P2P_GO_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_STA_P2P_GO_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif + [CDS_STA_P2P_CLI_SCC_24_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_24_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_IBSS_MODE] = {CDS_NONE, CDS_NONE, CDS_NONE} }, + + [CDS_STA_P2P_CLI_MCC_24_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_MCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_STA_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_STA_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif + [CDS_P2P_GO_P2P_CLI_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_24G, CDS_24G, CDS_24G}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_P2P_GO_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_P2P_GO_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_CLIENT_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_P2P_GO_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif + [CDS_P2P_GO_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_P2P_GO_SAP_DBS_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_ON_5_SCC_ON_24_5G, + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_SCC_ON_5_SCC_ON_24_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_P2P_GO_SAP_DBS_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_ON_5_SCC_ON_24, + CDS_SCC_ON_5_SCC_ON_24, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif +}; + +/** + * third_connection_pcl_nodbs_table - table which provides PCL + * for the 3rd connection, when we have two connections already + * in the system (with DBS not supported by HW) + */ +static const enum cds_pcl_type +third_connection_pcl_nodbs_table[CDS_MAX_TWO_CONNECTION_MODE] + [CDS_MAX_NUM_OF_MODE][CDS_MAX_CONC_PRIORITY_MODE] = { + [CDS_STA_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_GO_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_24_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_24_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_5G, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH_5G, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_SCC_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_5_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_MCC_24_5_2x2] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_STA_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = { + CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_CLIENT_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_P2P_CLI_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_GO_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +}; + +/** + * next_action_two_connection_table - table which provides next + * action while a new connection is coming up, with one + * connection already in the system + */ +static const enum cds_conc_next_action +next_action_two_connection_table[CDS_MAX_ONE_CONNECTION_MODE][CDS_MAX_BAND] = { + [CDS_STA_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_CLI_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_CLI_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_CLI_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_CLI_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_GO_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_GO_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_GO_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_SAP_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_SAP_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_SAP_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_SAP_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_IBSS_24_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_IBSS_24_2x2] = {CDS_NOP, CDS_NOP}, + [CDS_IBSS_5_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_IBSS_5_2x2] = {CDS_NOP, CDS_NOP}, +}; + +/** + * next_action_three_connection_table - table which provides next + * action while a new connection is coming up, with two + * connections already in the system + */ +static const enum cds_conc_next_action +next_action_three_connection_table[CDS_MAX_TWO_CONNECTION_MODE] + [CDS_MAX_BAND] = { + [CDS_STA_SAP_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_SAP_SCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_SAP_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_SAP_MCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_SAP_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_SAP_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_SAP_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_SAP_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_SAP_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_STA_SAP_MCC_24_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_STA_SAP_DBS_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_STA_P2P_GO_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_P2P_GO_SCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_GO_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_P2P_GO_MCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_GO_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_P2P_GO_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_P2P_GO_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_P2P_GO_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_P2P_GO_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_STA_P2P_GO_MCC_24_5_2x2] = { + CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_GO_DBS_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_STA_P2P_CLI_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_P2P_CLI_SCC_24_2x2] = { + CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_CLI_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_STA_P2P_CLI_MCC_24_2x2] = { + CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_CLI_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_P2P_CLI_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_P2P_CLI_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_STA_P2P_CLI_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_STA_P2P_CLI_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_STA_P2P_CLI_MCC_24_5_2x2] = { + CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_STA_P2P_CLI_DBS_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_P2P_GO_P2P_CLI_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_GO_P2P_CLI_SCC_24_2x2] = { + CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_P2P_CLI_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_GO_P2P_CLI_MCC_24_2x2] = { + CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_P2P_CLI_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_GO_P2P_CLI_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_GO_P2P_CLI_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_GO_P2P_CLI_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_GO_P2P_CLI_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_P2P_GO_P2P_CLI_MCC_24_5_2x2] = { + CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_P2P_CLI_DBS_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_P2P_GO_SAP_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_GO_SAP_SCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_SAP_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_GO_SAP_MCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_SAP_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_GO_SAP_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_GO_SAP_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_GO_SAP_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_GO_SAP_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_P2P_GO_SAP_MCC_24_5_2x2] = { + CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_P2P_GO_SAP_DBS_1x1] = {CDS_NOP, CDS_NOP}, +}; + +/** + * cds_update_conc_list() - Update the concurrent connection list + * @conn_index: Connection index + * @mode: Mode + * @chan: Channel + * @mac: Mac id + * @chain_mask: Chain mask + * @tx_spatial_stream: Tx spatial stream + * @rx_spatial_stream: Rx spatial stream + * @vdev_id: vdev id + * @in_use: Flag to indicate if the index is in use or not + * + * Updates the index value of the concurrent connection list + * + * Return: None + */ +static void cds_update_conc_list(uint32_t conn_index, + enum cds_con_mode mode, + uint8_t chan, + uint8_t mac, + enum cds_chain_mode chain_mask, + uint8_t tx_spatial_stream, + uint8_t rx_spatial_stream, + uint32_t original_nss, + uint32_t vdev_id, + bool in_use) +{ + if (conn_index >= MAX_NUMBER_OF_CONC_CONNECTIONS) { + cds_err("Number of connections exceeded conn_index: %d", + conn_index); + return; + } + conc_connection_list[conn_index].mode = mode; + conc_connection_list[conn_index].chan = chan; + conc_connection_list[conn_index].mac = mac; + conc_connection_list[conn_index].chain_mask = chain_mask; + conc_connection_list[conn_index].tx_spatial_stream = tx_spatial_stream; + conc_connection_list[conn_index].rx_spatial_stream = rx_spatial_stream; + conc_connection_list[conn_index].original_nss = original_nss; + conc_connection_list[conn_index].vdev_id = vdev_id; + conc_connection_list[conn_index].in_use = in_use; +} + +/** + * cds_mode_specific_connection_count() - provides the + * count of connections of specific mode + * @hdd_ctx: HDD Context + * @mode: type of connection + * @list: To provide the indices on conc_connection_list + * (optional) + * + * This function provides the count of current connections + * + * Return: connection count of specific type + */ +static uint32_t cds_mode_specific_connection_count(hdd_context_t *hdd_ctx, + enum cds_con_mode mode, + uint32_t *list) +{ + uint32_t conn_index = 0, count = 0; + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list[conn_index].mode == mode) && + conc_connection_list[conn_index].in_use) { + if (list != NULL) + list[count] = conn_index; + count++; + } + } + return count; +} + +/** + * cds_store_and_del_conn_info() - Store and del a connection info + * @hdd_ctx: HDD context + * @mode: Mode whose entry has to be deleted + * @info: Struture pointer where the connection info will be saved + * + * Saves the connection info corresponding to the provided mode + * and deleted that corresponding entry based on vdev from the + * connection info structure + * + * Return: None + */ +static void cds_store_and_del_conn_info(hdd_context_t *hdd_ctx, + enum cds_con_mode mode, + struct cds_conc_connection_info *info) +{ + uint32_t conn_index = 0; + bool found = false; + + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (mode == conc_connection_list[conn_index].mode) { + found = true; + break; + } + conn_index++; + } + + if (!found) { + cds_err("Mode:%d not available in the conn info", mode); + return; + } + + /* Storing the STA entry which will be temporarily deleted */ + *info = conc_connection_list[conn_index]; + + /* Deleting the STA entry */ + cds_decr_connection_count(hdd_ctx, info->vdev_id); + + cds_info("Stored %d (%d), deleted STA entry with vdev id %d, index %d", + info->vdev_id, info->mode, info->vdev_id, conn_index); + + /* Caller should set the PCL and restore the STA entry in conn info */ +} + +/** + * cds_restore_deleted_conn_info() - Restore connection info + * @hdd_ctx: HDD context + * @info: Saved connection info that is to be restored + * + * Restores the connection info of STA that was saved before + * updating the PCL to the FW + * + * Return: None + */ +static void cds_restore_deleted_conn_info(hdd_context_t *hdd_ctx, + struct cds_conc_connection_info *info) +{ + uint32_t conn_index; + + conn_index = cds_get_connection_count(hdd_ctx); + if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { + cds_err("Failed to restore the deleted information %d/%d", + conn_index, MAX_NUMBER_OF_CONC_CONNECTIONS); + return; + } + + conc_connection_list[conn_index] = *info; + + cds_info("Restored the deleleted conn info, vdev:%d, index:%d", + info->vdev_id, conn_index); +} + +/** + * cds_update_hw_mode_conn_info() - Update connection info based on HW mode + * @num_vdev_mac_entries: Number of vdev-mac id entries that follow + * @vdev_mac_map: Mapping of vdev-mac id + * @hw_mode: HW mode + * + * Updates the connection info parameters based on the new HW mode + * + * Return: None + */ +static void cds_update_hw_mode_conn_info(uint32_t num_vdev_mac_entries, + struct sir_vdev_mac_map *vdev_mac_map, + struct sir_hw_mode_params hw_mode) +{ + uint32_t i, conn_index, found; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + cds_err("Invalid HDD Context"); + return; + } + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + for (i = 0; i < num_vdev_mac_entries; i++) { + conn_index = 0; + found = 0; + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_mac_map[i].vdev_id == + conc_connection_list[conn_index].vdev_id) { + found = 1; + break; + } + conn_index++; + } + if (found) { + conc_connection_list[conn_index].mac = + vdev_mac_map[i].mac_id; + if (vdev_mac_map[i].mac_id == 0) { + conc_connection_list[conn_index]. + tx_spatial_stream = hw_mode.mac0_tx_ss; + conc_connection_list[conn_index]. + rx_spatial_stream = hw_mode.mac0_rx_ss; + } else { + conc_connection_list[conn_index]. + tx_spatial_stream = hw_mode.mac1_tx_ss; + conc_connection_list[conn_index]. + rx_spatial_stream = hw_mode.mac1_rx_ss; + } + cds_info("vdev:%d, mac:%d, tx ss:%d, rx ss;%d", + conc_connection_list[conn_index].vdev_id, + conc_connection_list[conn_index].mac, + conc_connection_list[conn_index].tx_spatial_stream, + conc_connection_list[conn_index].rx_spatial_stream); + } + } + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); +} + +/** + * cds_soc_set_dual_mac_cfg_cb() - Callback for set dual mac config + * @status: Status of set dual mac config + * @scan_config: Current scan config whose status is the first param + * @fw_mode_config: Current FW mode config whose status is the first param + * + * Callback on setting the dual mac configuration + * + * Return: None + */ +void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, + uint32_t scan_config, + uint32_t fw_mode_config) +{ + cds_info("Status:%d for scan_config:%x fw_mode_config:%x", + status, scan_config, fw_mode_config); +} + +/** + * cds_set_dual_mac_scan_config() - Set the dual MAC scan config + * @hdd_ctx: HDD context + * @dbs_val: Value of DBS bit + * @dbs_plus_agile_scan_val: Value of DBS plus agile scan bit + * @single_mac_scan_with_dbs_val: Value of Single MAC scan with DBS + * + * Set the values of scan config. For FW mode config, the existing values + * will be retained + * + * Return: None + */ +void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, + uint8_t dbs_val, + uint8_t dbs_plus_agile_scan_val, + uint8_t single_mac_scan_with_dbs_val) +{ + struct sir_dual_mac_config cfg; + CDF_STATUS status; + + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + + /* Any non-zero positive value is treated as 1 */ + if (dbs_val != 0) + dbs_val = 1; + if (dbs_plus_agile_scan_val != 0) + dbs_plus_agile_scan_val = 1; + if (single_mac_scan_with_dbs_val != 0) + single_mac_scan_with_dbs_val = 1; + + status = wma_get_updated_scan_config(&cfg.scan_config, + dbs_val, + dbs_plus_agile_scan_val, + single_mac_scan_with_dbs_val); + if (status != CDF_STATUS_SUCCESS) { + cds_err("wma_get_updated_scan_config failed %d", status); + return; + } + + status = wma_get_updated_fw_mode_config(&cfg.fw_mode_config, + wma_get_dbs_config(), + wma_get_agile_dfs_config()); + if (status != CDF_STATUS_SUCCESS) { + cds_err("wma_get_updated_fw_mode_config failed %d", status); + return; + } + + cfg.set_dual_mac_cb = (void *)cds_soc_set_dual_mac_cfg_cb; + + cds_info("scan_config:%x fw_mode_config:%x", + cfg.scan_config, cfg.fw_mode_config); + + status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg); + if (status != CDF_STATUS_SUCCESS) { + cds_err("sme_soc_set_dual_mac_config failed %d", status); + return; + } +} + +/** + * cds_set_dual_mac_fw_mode_config() - Set the dual mac FW mode config + * @hdd_ctx: HDD context + * @dbs: DBS bit + * @dfs: Agile DFS bit + * + * Set the values of fw mode config. For scan config, the existing values + * will be retain. + * + * Return: None + */ +void cds_set_dual_mac_fw_mode_config(hdd_context_t *hdd_ctx, + uint8_t dbs, + uint8_t dfs) +{ + struct sir_dual_mac_config cfg; + CDF_STATUS status; + + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + + /* Any non-zero positive value is treated as 1 */ + if (dbs != 0) + dbs = 1; + if (dfs != 0) + dfs = 1; + + status = wma_get_updated_scan_config(&cfg.scan_config, + wma_get_dbs_scan_config(), + wma_get_dbs_plus_agile_scan_config(), + wma_get_single_mac_scan_with_dfs_config()); + if (status != CDF_STATUS_SUCCESS) { + cds_err("wma_get_updated_scan_config failed %d", status); + return; + } + + status = wma_get_updated_fw_mode_config(&cfg.fw_mode_config, + dbs, dfs); + if (status != CDF_STATUS_SUCCESS) { + cds_err("wma_get_updated_fw_mode_config failed %d", status); + return; + } + + cfg.set_dual_mac_cb = (void *)cds_soc_set_dual_mac_cfg_cb; + + cds_info("scan_config:%x fw_mode_config:%x", + cfg.scan_config, cfg.fw_mode_config); + + status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg); + if (status != CDF_STATUS_SUCCESS) { + cds_err("sme_soc_set_dual_mac_config failed %d", status); + return; + } +} + +/** + * cds_soc_set_hw_mode_cb() - Callback for set hw mode + * @status: Status + * @cfgd_hw_mode_index: Configured HW mode index + * @num_vdev_mac_entries: Number of vdev-mac id mapping that follows + * @vdev_mac_map: vdev-mac id map. This memory will be freed by the caller. + * So, make local copy if needed. + * + * Provides the status and configured hw mode index set + * by the FW + * + * Return: None + */ +static void cds_soc_set_hw_mode_cb(uint32_t status, + uint32_t cfgd_hw_mode_index, + uint32_t num_vdev_mac_entries, + struct sir_vdev_mac_map *vdev_mac_map) +{ + CDF_STATUS ret; + struct sir_hw_mode_params hw_mode; + uint32_t i; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return; + } + + if (status != SET_HW_MODE_STATUS_OK) { + cds_err("Set HW mode failed with status %d", status); + return; + } + + if (!vdev_mac_map) { + cds_err("vdev_mac_map is NULL"); + return; + } + + cds_info("cfgd_hw_mode_index=%d", cfgd_hw_mode_index); + + for (i = 0; i < num_vdev_mac_entries; i++) + cds_info("vdev_id:%d mac_id:%d", + vdev_mac_map[i].vdev_id, + vdev_mac_map[i].mac_id); + + ret = wma_get_hw_mode_from_idx(cfgd_hw_mode_index, &hw_mode); + if (ret != CDF_STATUS_SUCCESS) { + cds_err("Get HW mode failed: %d", ret); + return; + } + + cds_info("MAC0: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac0_tx_ss, hw_mode.mac0_rx_ss, hw_mode.mac0_bw); + cds_info("MAC1: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac1_tx_ss, hw_mode.mac1_rx_ss, hw_mode.mac1_bw); + cds_info("DBS:%d, Agile DFS:%d", + hw_mode.dbs_cap, hw_mode.agile_dfs_cap); + + /* update conc_connection_list */ + cds_update_hw_mode_conn_info(num_vdev_mac_entries, + vdev_mac_map, + hw_mode); + + ret = cdf_event_set(&cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(ret)) + cds_err("ERROR: set connection_update_done event failed"); + + return; +} + +/** + * cds_hw_mode_transition_cb() - Callback for HW mode transition from FW + * @old_hw_mode_index: Old HW mode index + * @new_hw_mode_index: New HW mode index + * @num_vdev_mac_entries: Number of vdev-mac id mapping that follows + * @vdev_mac_map: vdev-mac id map. This memory will be freed by the caller. + * So, make local copy if needed. + * + * Provides the old and new HW mode index set by the FW + * + * Return: None + */ +static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, + uint32_t new_hw_mode_index, + uint32_t num_vdev_mac_entries, + struct sir_vdev_mac_map *vdev_mac_map) +{ + CDF_STATUS status; + struct sir_hw_mode_params hw_mode; + uint32_t i; + + if (!vdev_mac_map) { + cds_err("vdev_mac_map is NULL"); + return; + } + + cds_info("old_hw_mode_index=%d, new_hw_mode_index=%d", + old_hw_mode_index, new_hw_mode_index); + + for (i = 0; i < num_vdev_mac_entries; i++) + cds_info("vdev_id:%d mac_id:%d", + vdev_mac_map[i].vdev_id, + vdev_mac_map[i].mac_id); + + status = wma_get_hw_mode_from_idx(new_hw_mode_index, &hw_mode); + if (status != CDF_STATUS_SUCCESS) { + cds_err("Get HW mode failed: %d", status); + return; + } + + cds_info("MAC0: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac0_tx_ss, hw_mode.mac0_rx_ss, hw_mode.mac0_bw); + cds_info("MAC1: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac1_tx_ss, hw_mode.mac1_rx_ss, hw_mode.mac1_bw); + cds_info("DBS:%d, Agile DFS:%d", + hw_mode.dbs_cap, hw_mode.agile_dfs_cap); + + /* update conc_connection_list */ + cds_update_hw_mode_conn_info(num_vdev_mac_entries, + vdev_mac_map, + hw_mode); + + return; +} + +/** + * cds_soc_set_hw_mode() - Set HW mode command to SME + * @hdd_ctx: HDD context + * @mac0_ss: MAC0 spatial stream configuration + * @mac0_bw: MAC0 bandwidth configuration + * @mac1_ss: MAC1 spatial stream configuration + * @mac1_bw: MAC1 bandwidth configuration + * @dbs: HW DBS capability + * @dfs: HW Agile DFS capability + * + * Sends the set hw mode to the SME module which will pass on + * this message to WMA layer + * + * e.g.: To configure 2x2_80 + * mac0_ss = HW_MODE_SS_2x2, mac0_bw = HW_MODE_80_MHZ + * mac1_ss = HW_MODE_SS_0x0, mac1_bw = HW_MODE_BW_NONE + * dbs = HW_MODE_DBS_NONE, dfs = HW_MODE_AGILE_DFS_NONE + * e.g.: To configure 1x1_80_1x1_40 (DBS) + * mac0_ss = HW_MODE_SS_1x1, mac0_bw = HW_MODE_80_MHZ + * mac1_ss = HW_MODE_SS_1x1, mac1_bw = HW_MODE_40_MHZ + * dbs = HW_MODE_DBS, dfs = HW_MODE_AGILE_DFS_NONE + * e.g.: To configure 1x1_80_1x1_40 (Agile DFS) + * mac0_ss = HW_MODE_SS_1x1, mac0_bw = HW_MODE_80_MHZ + * mac1_ss = HW_MODE_SS_1x1, mac1_bw = HW_MODE_40_MHZ + * dbs = HW_MODE_DBS, dfs = HW_MODE_AGILE_DFS + * + * Return: Success if the message made it down to the next layer + */ +CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + enum hw_mode_ss_config mac0_ss, + enum hw_mode_bandwidth mac0_bw, + enum hw_mode_ss_config mac1_ss, + enum hw_mode_bandwidth mac1_bw, + enum hw_mode_dbs_capab dbs, + enum hw_mode_agile_dfs_capab dfs) +{ + int8_t hw_mode_index; + struct sir_hw_mode msg; + CDF_STATUS status; + + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return CDF_STATUS_E_FAILURE; + } + + hw_mode_index = wma_get_hw_mode_idx_from_dbs_hw_list(mac0_ss, + mac0_bw, mac1_ss, mac1_bw, dbs, dfs); + if (hw_mode_index < 0) { + cds_err("Invalid HW mode index obtained"); + return CDF_STATUS_E_FAILURE; + } + + msg.hw_mode_index = hw_mode_index; + msg.set_hw_mode_cb = (void *)cds_soc_set_hw_mode_cb; + + cds_info("set hw mode to sme: hw_mode_index: %d", + msg.hw_mode_index); + + status = sme_soc_set_hw_mode(hdd_ctx->hHal, msg); + if (status != CDF_STATUS_SUCCESS) { + cds_err("Failed to set hw mode to SME"); + return status; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_is_connection_in_progress() - check if connection is in progress + * @hdd_ctx - HDD context + * + * Go through each adapter and check if Connection is in progress + * + * Return: true if connection is in progress else false + */ +bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_station_ctx_t *hdd_sta_ctx = NULL; + hdd_adapter_t *adapter = NULL; + CDF_STATUS status = 0; + uint8_t sta_id = 0; + uint8_t *sta_mac = NULL; + + if (true == hdd_ctx->btCoexModeSet) { + cds_info("BTCoex Mode operation in progress"); + return true; + } + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + if (!adapter) + goto end; + + cds_info("Adapter with device mode %s(%d) exists", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + if (((WLAN_HDD_INFRA_STATION == adapter->device_mode) + || (WLAN_HDD_P2P_CLIENT == adapter->device_mode) + || (WLAN_HDD_P2P_DEVICE == adapter->device_mode)) + && (eConnectionState_Connecting == + (WLAN_HDD_GET_STATION_CTX_PTR(adapter))-> + conn_info.connState)) { + cds_err("%p(%d) Connection is in progress", + WLAN_HDD_GET_STATION_CTX_PTR(adapter), + adapter->sessionId); + return true; + } + if ((WLAN_HDD_INFRA_STATION == adapter->device_mode) && + sme_neighbor_middle_of_roaming( + WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId)) { + cds_err("%p(%d) Reassociation in progress", + WLAN_HDD_GET_STATION_CTX_PTR(adapter), + adapter->sessionId); + return true; + } + if ((WLAN_HDD_INFRA_STATION == adapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == adapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == adapter->device_mode)) { + hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if ((eConnectionState_Associated == + hdd_sta_ctx->conn_info.connState) + && (false == + hdd_sta_ctx->conn_info.uIsAuthenticated)) { + sta_mac = (uint8_t *) + &(adapter->macAddressCurrent.bytes[0]); + cds_err("client " MAC_ADDRESS_STR + " is in middle of WPS/EAPOL exchange.", + MAC_ADDR_ARRAY(sta_mac)); + return true; + } + } else if ((WLAN_HDD_SOFTAP == adapter->device_mode) || + (WLAN_HDD_P2P_GO == adapter->device_mode)) { + for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; + sta_id++) { + if (!((adapter->aStaInfo[sta_id].isUsed) + && (ol_txrx_peer_state_conn == + adapter->aStaInfo[sta_id].tlSTAState))) + continue; + + sta_mac = (uint8_t *) + &(adapter->aStaInfo[sta_id]. + macAddrSTA.bytes[0]); + cds_err("client " MAC_ADDRESS_STR + " of SAP/GO is in middle of WPS/EAPOL exchange", + MAC_ADDR_ARRAY(sta_mac)); + return true; + } + if (hdd_ctx->connection_in_progress) { + cds_err("AP/GO: connection is in progress"); + return true; + } + } +end: + status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); + adapter_node = next; + } + return false; +} + +/** + * cds_dump_current_concurrency_one_connection() - To dump the + * current concurrency info with one connection + * @hdd_ctx: HDD context + * @cc_mode: connection string + * @length: Maximum size of the string + * + * This routine is called to dump the concurrency info + * + * Return: length of the string + */ +static uint32_t cds_dump_current_concurrency_one_connection( + hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +{ + uint32_t count = 0; + + switch (conc_connection_list[0].mode) { + case CDS_STA_MODE: + count = strlcat(cc_mode, "STA", + length); + break; + case CDS_SAP_MODE: + count = strlcat(cc_mode, "SAP", + length); + break; + case CDS_P2P_CLIENT_MODE: + count = strlcat(cc_mode, "P2P CLI", + length); + break; + case CDS_P2P_GO_MODE: + count = strlcat(cc_mode, "P2P GO", + length); + break; + case CDS_IBSS_MODE: + count = strlcat(cc_mode, "IBSS", + length); + break; + default: + /* err msg */ + cds_err("unexpected mode %d", conc_connection_list[0].mode); + break; + } + return count; +} + +/** + * cds_dump_current_concurrency_two_connection() - To dump the + * current concurrency info with two connections + * @hdd_ctx: HDD context + * @cc_mode: connection string + * @length: Maximum size of the string + * + * This routine is called to dump the concurrency info + * + * Return: length of the string + */ +static uint32_t cds_dump_current_concurrency_two_connection( + hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +{ + uint32_t count = 0; + + switch (conc_connection_list[1].mode) { + case CDS_STA_MODE: + count = cds_dump_current_concurrency_one_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+STA", + length); + break; + case CDS_SAP_MODE: + count = cds_dump_current_concurrency_one_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+SAP", + length); + break; + case CDS_P2P_CLIENT_MODE: + count = cds_dump_current_concurrency_one_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+P2P CLI", + length); + break; + case CDS_P2P_GO_MODE: + count = cds_dump_current_concurrency_one_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+P2P GO", + length); + break; + case CDS_IBSS_MODE: + count = cds_dump_current_concurrency_one_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+IBSS", + length); + break; + default: + /* err msg */ + cds_err("unexpected mode %d", conc_connection_list[1].mode); + break; + } + return count; +} + +/** + * cds_dump_current_concurrency_three_connection() - To dump the + * current concurrency info with three connections + * @hdd_ctx: HDD context + * @cc_mode: connection string + * @length: Maximum size of the string + * + * This routine is called to dump the concurrency info + * + * Return: length of the string + */ +static uint32_t cds_dump_current_concurrency_three_connection( + hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +{ + uint32_t count = 0; + + switch (conc_connection_list[2].mode) { + case CDS_STA_MODE: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+STA", + length); + break; + case CDS_SAP_MODE: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+SAP", + length); + break; + case CDS_P2P_CLIENT_MODE: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+P2P CLI", + length); + break; + case CDS_P2P_GO_MODE: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+P2P GO", + length); + break; + case CDS_IBSS_MODE: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, length); + count += strlcat(cc_mode, "+IBSS", + length); + break; + default: + /* err msg */ + cds_err("unexpected mode %d", conc_connection_list[2].mode); + break; + } + return count; +} + +/** + * cds_dump_dbs_concurrency() - To dump the dbs concurrency + * combination + * @cc_mode: connection string + * + * This routine is called to dump the concurrency info + * + * Return: None + */ +static void cds_dump_dbs_concurrency(char *cc_mode, uint32_t length) +{ + strlcat(cc_mode, " DBS", length); + if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (0 == conc_connection_list[0].mac) + strlcat(cc_mode, " with SCC on mac0", + length); + else + strlcat(cc_mode, " with SCC on mac1", + length); + } else { + if (0 == conc_connection_list[0].mac) + strlcat(cc_mode, " with MCC on mac0", + length); + else + strlcat(cc_mode, " with MCC on mac1", + length); + } + } + if (conc_connection_list[0].mac == conc_connection_list[2].mac) { + if (conc_connection_list[0].chan == + conc_connection_list[2].chan) { + if (0 == conc_connection_list[0].mac) + strlcat(cc_mode, " with SCC on mac0", + length); + else + strlcat(cc_mode, " with SCC on mac1", + length); + } else { + if (0 == conc_connection_list[0].mac) + strlcat(cc_mode, " with MCC on mac0", + length); + else + strlcat(cc_mode, " with MCC on mac1", + length); + } + } + if (conc_connection_list[1].mac == conc_connection_list[2].mac) { + if (conc_connection_list[1].chan == + conc_connection_list[2].chan) { + if (0 == conc_connection_list[1].mac) + strlcat(cc_mode, " with SCC on mac0", + length); + else + strlcat(cc_mode, " with SCC on mac1", + length); + } else { + if (0 == conc_connection_list[1].mac) + strlcat(cc_mode, " with MCC on mac0", + length); + else + strlcat(cc_mode, " with MCC on mac1", + length); + } + } +} + +/** + * cds_dump_current_concurrency() - To dump the current + * concurrency combination + * @hdd_ctx: HDD context + * + * This routine is called to dump the concurrency info + * + * Return: None + */ +static void cds_dump_current_concurrency(hdd_context_t *hdd_ctx) +{ + uint32_t num_connections = 0; + char cc_mode[CDS_MAX_CON_STRING_LEN] = {0}; + uint32_t count = 0; + + num_connections = cds_get_connection_count(hdd_ctx); + + switch (num_connections) { + case 1: + cds_dump_current_concurrency_one_connection(hdd_ctx, cc_mode, + sizeof(cc_mode)); + cds_err("%s Standalone", cc_mode); + break; + case 2: + count = cds_dump_current_concurrency_two_connection( + hdd_ctx, cc_mode, sizeof(cc_mode)); + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + strlcat(cc_mode, " SCC", sizeof(cc_mode)); + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + strlcat(cc_mode, " MCC", sizeof(cc_mode)); + } else + strlcat(cc_mode, " DBS", sizeof(cc_mode)); + cds_err("%s", cc_mode); + break; + case 3: + count = cds_dump_current_concurrency_three_connection( + hdd_ctx, cc_mode, sizeof(cc_mode)); + if ((conc_connection_list[0].chan == + conc_connection_list[1].chan) && + (conc_connection_list[0].chan == + conc_connection_list[2].chan)){ + strlcat(cc_mode, " SCC", + sizeof(cc_mode)); + } else if ((conc_connection_list[0].mac == + conc_connection_list[1].mac) + && (conc_connection_list[0].mac == + conc_connection_list[2].mac)) { + strlcat(cc_mode, " MCC on single MAC", + sizeof(cc_mode)); + } else { + cds_dump_dbs_concurrency(cc_mode, sizeof(cc_mode)); + } + cds_err("%s", cc_mode); + break; + default: + /* err msg */ + cds_err("unexpected num_connections value %d", + num_connections); + break; + } + + return; +} + +/** + * cds_current_concurrency_is_scc() - To check the current + * concurrency combination if it is doing SCC + * @hdd_ctx: HDD context + * + * This routine is called to check if it is doing SCC + * + * Return: True - SCC, False - Otherwise + */ +static bool cds_current_concurrency_is_scc(hdd_context_t *hdd_ctx) +{ + uint32_t num_connections = 0; + bool is_scc = false; + + num_connections = cds_get_connection_count(hdd_ctx); + + switch (num_connections) { + case 1: + is_scc = true; + break; + case 2: + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + is_scc = true; + } + break; + case 3: + if ((conc_connection_list[0].chan == + conc_connection_list[1].chan) && + (conc_connection_list[0].chan == + conc_connection_list[2].chan)){ + is_scc = true; + } + break; + default: + /* err msg */ + cds_err("unexpected num_connections value %d", + num_connections); + break; + } + + return is_scc; +} + +/** + * cds_dump_legacy_concurrency() - To dump the current + * concurrency combination + * @hdd_ctx: HDD context + * @sta_channel: Channel STA connection has come up + * @ap_channel: Channel SAP connection has come up + * @p2p_channel: Channel P2P connection has come up + * @sta_bssid: BSSID to which STA is connected to + * @p2p_bssid: BSSID to which P2P is connected to + * @ap_bssid: BSSID of the AP + * @p2p_mode: P2P Client or GO + * + * This routine is called to dump the concurrency info + * + * Return: None + */ +static void cds_dump_legacy_concurrency(hdd_context_t *hdd_ctx, + uint8_t sta_channel, uint8_t ap_channel, uint8_t p2p_channel, + struct cdf_mac_addr sta_bssid, struct cdf_mac_addr p2p_bssid, + struct cdf_mac_addr ap_bssid, const char *p2p_mode) +{ + const char *cc_mode = "Standalone"; + + if (sta_channel > 0) { + if (ap_channel > 0) { + if (p2p_channel > 0) { + /* STA + AP + P2P */ + if (p2p_channel == sta_channel + && ap_channel == sta_channel) { + cc_mode = "STA+AP+P2P SCC"; + } else { + if (p2p_channel == sta_channel) + cc_mode = + "STA+P2P SCC, SAP MCC"; + else if (ap_channel == sta_channel) + cc_mode = + "STA+SAP SCC, P2P MCC"; + else if (ap_channel == p2p_channel) + cc_mode = + "P2P+SAP SCC, STA MCC"; + } + } else { + /* STA + AP */ + cc_mode = (ap_channel == sta_channel) ? + "SCC" : "MCC"; + } + } else { + if (p2p_channel > 0) { + /* STA + P2P */ + cc_mode = (p2p_channel == sta_channel) ? + "SCC" : "MCC"; + } + } + } else { + if (ap_channel > 0) { + if (p2p_channel > 0) { + /* AP + P2P */ + cc_mode = (p2p_channel == ap_channel) ? + "SCC" : "MCC"; + } + } + } + if (sta_channel > 0) + cds_err("wlan(%d) " MAC_ADDRESS_STR " %s", + sta_channel, MAC_ADDR_ARRAY(sta_bssid.bytes), cc_mode); + + if (p2p_channel > 0) + cds_err("p2p-%s(%d) " MAC_ADDRESS_STR " %s", + p2p_mode, p2p_channel, MAC_ADDR_ARRAY(p2p_bssid.bytes), + cc_mode); + + if (ap_channel > 0) + cds_err("AP(%d) " MAC_ADDRESS_STR " %s", + ap_channel, MAC_ADDR_ARRAY(ap_bssid.bytes), cc_mode); + + hdd_ctx->mcc_mode = strcmp(cc_mode, "SCC"); +} + +/** + * cds_dump_concurrency_info() - To dump concurrency info + * @hdd_ctx: HDD context + * + * This routine is called to dump the concurrency info + * + * Return: None + */ +void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + hdd_station_ctx_t *pHddStaCtx; + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + struct cdf_mac_addr staBssid = CDF_MAC_ADDR_ZERO_INITIALIZER; + struct cdf_mac_addr p2pBssid = CDF_MAC_ADDR_ZERO_INITIALIZER; + struct cdf_mac_addr apBssid = CDF_MAC_ADDR_ZERO_INITIALIZER; + uint8_t staChannel = 0, p2pChannel = 0, apChannel = 0; + const char *p2pMode = "DEV"; + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + uint8_t targetChannel = 0; + uint8_t preAdapterChannel = 0; + uint8_t channel24; + uint8_t channel5; + hdd_adapter_t *preAdapterContext = NULL; + hdd_adapter_t *adapter2_4 = NULL; + hdd_adapter_t *adapter5 = NULL; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + switch (adapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (eConnectionState_Associated == + pHddStaCtx->conn_info.connState) { + staChannel = + pHddStaCtx->conn_info.operationChannel; + cdf_copy_macaddr(&staBssid, + &pHddStaCtx->conn_info.bssId); +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + targetChannel = staChannel; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + } + break; + case WLAN_HDD_P2P_CLIENT: + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (eConnectionState_Associated == + pHddStaCtx->conn_info.connState) { + p2pChannel = + pHddStaCtx->conn_info.operationChannel; + cdf_copy_macaddr(&p2pBssid, + &pHddStaCtx->conn_info.bssId); + p2pMode = "CLI"; +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + targetChannel = p2pChannel; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + } + break; + case WLAN_HDD_P2P_GO: + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); + if (hostapd_state->bssState == BSS_START + && hostapd_state->cdf_status == + CDF_STATUS_SUCCESS) { + p2pChannel = hdd_ap_ctx->operatingChannel; + cdf_copy_macaddr(&p2pBssid, + &adapter->macAddressCurrent); +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + targetChannel = p2pChannel; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + } + p2pMode = "GO"; + break; + case WLAN_HDD_SOFTAP: + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); + hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); + if (hostapd_state->bssState == BSS_START + && hostapd_state->cdf_status == + CDF_STATUS_SUCCESS) { + apChannel = hdd_ap_ctx->operatingChannel; + cdf_copy_macaddr(&apBssid, + &adapter->macAddressCurrent); +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + targetChannel = apChannel; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + } + break; + case WLAN_HDD_IBSS: + return; /* skip printing station message below */ + default: + break; + } +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + if (targetChannel) { + /* + * This is first adapter detected as active + * set as default for none concurrency case + */ + if (!preAdapterChannel) { + /* If IPA UC data path is enabled, + * target should reserve extra tx descriptors + * for IPA data path. + * Then host data path should allow less TX + * packet pumping in case IPA + * data path enabled + */ + if (hdd_ipa_uc_is_enabled(hdd_ctx) && + (WLAN_HDD_SOFTAP == adapter->device_mode)) { + adapter->tx_flow_low_watermark = + hdd_ctx->config->TxFlowLowWaterMark + + WLAN_TFC_IPAUC_TX_DESC_RESERVE; + } else { + adapter->tx_flow_low_watermark = + hdd_ctx->config-> + TxFlowLowWaterMark; + } + adapter->tx_flow_high_watermark_offset = + hdd_ctx->config->TxFlowHighWaterMarkOffset; + ol_txrx_ll_set_tx_pause_q_depth( + adapter->sessionId, + hdd_ctx->config->TxFlowMaxQueueDepth); + /* Temporary set log level as error + * TX Flow control feature settled down, + * will lower log level + */ + cds_err("MODE %d,CH %d,LWM %d,HWM %d,TXQDEP %d", + adapter->device_mode, + targetChannel, + adapter->tx_flow_low_watermark, + adapter->tx_flow_low_watermark + + adapter->tx_flow_high_watermark_offset, + hdd_ctx->config->TxFlowMaxQueueDepth); + preAdapterChannel = targetChannel; + preAdapterContext = adapter; + } 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 */ + adapter->tx_flow_low_watermark = 0; + adapter-> + tx_flow_high_watermark_offset = 0; + ol_txrx_ll_set_tx_pause_q_depth( + adapter->sessionId, + hdd_ctx->config-> + TxHbwFlowMaxQueueDepth); + cds_err("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string( + adapter->device_mode), + adapter->device_mode, + targetChannel, + adapter->tx_flow_low_watermark, + adapter->tx_flow_low_watermark + + adapter-> + tx_flow_high_watermark_offset, + hdd_ctx->config-> + TxHbwFlowMaxQueueDepth); + + if (!preAdapterContext) { + cds_err("SCC: Previous adapter context NULL"); + continue; + } + + /* Previous adapter */ + preAdapterContext-> + tx_flow_low_watermark = 0; + preAdapterContext-> + tx_flow_high_watermark_offset = 0; + ol_txrx_ll_set_tx_pause_q_depth( + preAdapterContext->sessionId, + hdd_ctx->config-> + TxHbwFlowMaxQueueDepth); + /* + * Temporary set log level as error + * TX Flow control feature settled down, + * will lower log level + */ + cds_err("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, + hdd_ctx->config-> + 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; + adapter2_4 = adapter; + adapter5 = preAdapterContext; + } else { + /* Current channel is 5 */ + channel24 = preAdapterChannel; + channel5 = targetChannel; + adapter2_4 = preAdapterContext; + adapter5 = adapter; + } + + if (!adapter5) { + cds_err("MCC: 5GHz adapter context NULL"); + continue; + } + adapter5->tx_flow_low_watermark = + hdd_ctx->config-> + TxHbwFlowLowWaterMark; + adapter5-> + tx_flow_high_watermark_offset = + hdd_ctx->config-> + TxHbwFlowHighWaterMarkOffset; + ol_txrx_ll_set_tx_pause_q_depth( + adapter5->sessionId, + hdd_ctx->config-> + TxHbwFlowMaxQueueDepth); + /* + * Temporary set log level as error + * TX Flow control feature settled down, + * will lower log level + */ + cds_err("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string( + adapter5->device_mode), + adapter5->device_mode, + channel5, + adapter5->tx_flow_low_watermark, + adapter5-> + tx_flow_low_watermark + + adapter5-> + tx_flow_high_watermark_offset, + hdd_ctx->config-> + TxHbwFlowMaxQueueDepth); + + if (!adapter2_4) { + cds_err("MCC: 2.4GHz adapter context NULL"); + continue; + } + adapter2_4->tx_flow_low_watermark = + hdd_ctx->config-> + TxLbwFlowLowWaterMark; + adapter2_4-> + tx_flow_high_watermark_offset = + hdd_ctx->config-> + TxLbwFlowHighWaterMarkOffset; + ol_txrx_ll_set_tx_pause_q_depth( + adapter2_4->sessionId, + hdd_ctx->config-> + TxLbwFlowMaxQueueDepth); + /* + * Temporary set log level as error + * TX Flow control feature settled down, + * will lower log level + */ + cds_err("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + hdd_device_mode_to_string( + adapter2_4->device_mode), + adapter2_4->device_mode, + channel24, + adapter2_4-> + tx_flow_low_watermark, + adapter2_4-> + tx_flow_low_watermark + + adapter2_4-> + tx_flow_high_watermark_offset, + hdd_ctx->config-> + TxLbwFlowMaxQueueDepth); + + } + } + } + targetChannel = 0; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + if (hdd_ctx->config->policy_manager_enabled) { + cds_dump_current_concurrency(hdd_ctx); + hdd_ctx->mcc_mode = !cds_current_concurrency_is_scc(hdd_ctx); + } else { + /* hdd_ctx->mcc_mode gets updated inside below function, which + * gets used by IPA + */ + cds_dump_legacy_concurrency(hdd_ctx, + staChannel, apChannel, p2pChannel, + staBssid, p2pBssid, apBssid, p2pMode); + } +} + +/** + * cds_set_concurrency_mode() - To set concurrency mode + * @hdd_ctx: HDD context + * @mode: Concurrency mode + * + * This routine is called to set the concurrency mode + * + * Return: NONE + */ +void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) +{ + switch (mode) { + case CDF_STA_MODE: + case CDF_P2P_CLIENT_MODE: + case CDF_P2P_GO_MODE: + case CDF_SAP_MODE: + hdd_ctx->concurrency_mode |= (1 << mode); + hdd_ctx->no_of_open_sessions[mode]++; + break; + default: + break; + } + cds_info("concurrency_mode = 0x%x Number of open sessions for mode %d = %d", + hdd_ctx->concurrency_mode, mode, + hdd_ctx->no_of_open_sessions[mode]); +} + +/** + * cds_clear_concurrency_mode() - To clear concurrency mode + * @hdd_ctx: HDD context + * @mode: Concurrency mode + * + * This routine is called to clear the concurrency mode + * + * Return: NONE + */ +void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, + tCDF_CON_MODE mode) +{ + switch (mode) { + case CDF_STA_MODE: + case CDF_P2P_CLIENT_MODE: + case CDF_P2P_GO_MODE: + case CDF_SAP_MODE: + hdd_ctx->no_of_open_sessions[mode]--; + if (!(hdd_ctx->no_of_open_sessions[mode])) + hdd_ctx->concurrency_mode &= (~(1 << mode)); + break; + default: + break; + } + cds_info("concurrency_mode = 0x%x Number of open sessions for mode %d = %d", + hdd_ctx->concurrency_mode, mode, + hdd_ctx->no_of_open_sessions[mode]); +} + +/** + * cds_soc_set_pcl() - Sets PCL to FW + * @hdd_ctx: HDD context + * @mode: Connection mode + * + * Fetches the PCL and sends the PCL to SME + * module which in turn will send the WMI + * command WMI_SOC_SET_PCL_CMDID to the fw + * + * Return: None + */ +static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) +{ + CDF_STATUS status; + enum cds_con_mode con_mode; + struct sir_pcl_list pcl; + pcl.pcl_len = 0; + + switch (mode) { + case CDF_STA_MODE: + con_mode = CDS_STA_MODE; + break; + case CDF_P2P_CLIENT_MODE: + con_mode = CDS_P2P_CLIENT_MODE; + break; + case CDF_P2P_GO_MODE: + con_mode = CDS_P2P_GO_MODE; + break; + case CDF_SAP_MODE: + con_mode = CDS_SAP_MODE; + break; + case CDF_IBSS_MODE: + con_mode = CDS_IBSS_MODE; + break; + default: + cds_err("Unable to set PCL to FW: %d", mode); + return; + } + + cds_debug("get pcl to set it to the FW"); + + status = cds_get_pcl(hdd_ctx, con_mode, + pcl.pcl_list, &pcl.pcl_len); + if (status != CDF_STATUS_SUCCESS) { + cds_err("Unable to set PCL to FW, Get PCL failed"); + return; + } + + status = sme_soc_set_pcl(hdd_ctx->hHal, pcl); + if (status != CDF_STATUS_SUCCESS) + cds_err("Send soc set PCL to SME failed"); + else + cds_info("Set PCL to FW for mode:%d", mode); +} + +/** + * cds_incr_active_session() - increments the number of active sessions + * @hdd_ctx: HDD Context + * @mode: Device mode + * @session_id: session ID for the connection session + * + * This function increments the number of active sessions maintained per device + * mode. In the case of STA/P2P CLI/IBSS upon connection indication it is + * incremented; In the case of SAP/P2P GO upon bss start it is incremented + * + * Return: None + */ +void cds_incr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, + uint8_t session_id) +{ + switch (mode) { + case CDF_STA_MODE: + case CDF_P2P_CLIENT_MODE: + case CDF_P2P_GO_MODE: + case CDF_SAP_MODE: + hdd_ctx->no_of_active_sessions[mode]++; + break; + default: + break; + } + cds_info("No.# of active sessions for mode %d = %d", + mode, hdd_ctx->no_of_active_sessions[mode]); + /* + * Get PCL logic makes use of the connection info structure. + * Let us set the PCL to the FW before updating the connection + * info structure about the new connection. + */ + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + if (mode == CDF_STA_MODE) { + /* Set PCL of STA to the FW */ + cds_soc_set_pcl(hdd_ctx, mode); + cds_info("Set PCL of STA to FW"); + } + cds_incr_connection_count(hdd_ctx, session_id); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); +} + +/** + * cds_need_opportunistic_upgrade() - Tells us if we really + * need an upgrade to 2x2 + * @hdd_ctx: HDD context + * + * This function returns if updrade to 2x2 is needed + * + * Return: CDS_NOP = upgrade is not needed, otherwise upgrade is + * needed + */ +enum cds_conc_next_action cds_need_opportunistic_upgrade( + hdd_context_t *hdd_ctx) +{ + uint32_t conn_index; + enum cds_conc_next_action upgrade = CDS_NOP; + uint8_t mac = 0; + + if (wma_is_hw_dbs_capable() == false) { + cds_err("driver isn't dbs capable, no further action needed"); + return upgrade; + } + + /* Are both mac's still in use*/ + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list[conn_index].mac == 0) && + conc_connection_list[conn_index].in_use) { + mac |= 1; + if (3 == mac) + goto done; + } else if ((conc_connection_list[conn_index].mac == 1) && + conc_connection_list[conn_index].in_use) { + mac |= 2; + if (3 == mac) + goto done; + } + } +#ifdef QCA_WIFI_3_0_EMU + /* For emulation only: if we have a connection on 2.4, stay in DBS */ + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) + goto done; +#endif + /* Let's request for single MAC mode */ + upgrade = CDS_MCC; + /* Is there any connection had an initial connection with 2x2 */ + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list[conn_index].original_nss == 1) && + conc_connection_list[conn_index].in_use) { + upgrade = CDS_MCC_UPGRADE; + goto done; + } + } + +done: + return upgrade; +} + + +/** + * cds_set_pcl_for_existing_combo() - Set PCL for existing connection + * @hdd_ctx: HDD context + * @mode: Connection mode of type 'cds_con_mode' + * + * Set the PCL for an existing connection + * + * Return: None + */ +static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, + enum cds_con_mode mode) +{ + struct cds_conc_connection_info info; + tCDF_CON_MODE pcl_mode; + + switch (mode) { + case CDS_STA_MODE: + pcl_mode = CDF_STA_MODE; + break; + case CDS_SAP_MODE: + pcl_mode = CDF_SAP_MODE; + break; + case CDS_P2P_CLIENT_MODE: + pcl_mode = CDF_P2P_CLIENT_MODE; + break; + case CDS_P2P_GO_MODE: + pcl_mode = CDF_P2P_GO_MODE; + break; + case CDS_IBSS_MODE: + pcl_mode = CDF_IBSS_MODE; + break; + default: + cds_err("Invalid mode to set PCL"); + return; + }; + + if (cds_mode_specific_connection_count( + hdd_ctx, mode, NULL) > 0) { + /* Check, store and temp delete the mode's parameter */ + cds_store_and_del_conn_info(hdd_ctx, mode, + &info); + /* Set the PCL to the FW since connection got updated */ + cds_soc_set_pcl(hdd_ctx, pcl_mode); + cds_info("Set PCL to FW for mode:%d", mode); + /* Restore the connection info */ + cds_restore_deleted_conn_info(hdd_ctx, &info); + } +} + +/** + * cds_decr_session_set_pcl() - Decrement session count and set PCL + * @hdd_ctx: HDD context + * @mode: Connection mode + * @session_id: Session id + * + * Decrements the active session count and sets the PCL if a STA connection + * exists + * + * Return: None + */ +void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, + tCDF_CON_MODE mode, + uint8_t session_id) +{ + CDF_STATUS cdf_status; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cds_decr_active_session(hdd_ctx, mode, session_id); + /* + * After the removal of this connection, we need to check if + * a STA connection still exists. The reason for this is that + * if one or more STA exists, we need to provide the updated + * PCL to the FW for cases like LFR. + * + * Since cds_get_pcl provides PCL list based on the new + * connection that is going to come up, we will find the + * existing STA entry, save it and delete it temporarily. + * After this we will get PCL as though as new STA connection + * is coming up. This will give the exact PCL that needs to be + * given to the FW. After setting the PCL, we need to restore + * the entry that we have saved before. + */ + cds_set_pcl_for_existing_combo(hdd_ctx, CDS_STA_MODE); + /* do we need to change the HW mode */ + if (cds_need_opportunistic_upgrade(hdd_ctx)) { + /* let's start the timer */ + cdf_mc_timer_stop(&hdd_ctx->dbs_opportunistic_timer); + cdf_status = cdf_mc_timer_start( + &hdd_ctx->dbs_opportunistic_timer, + DBS_OPPORTUNISTIC_TIME * + 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cds_err("Failed to start dbs opportunistic timer"); + } + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + + return; +} + + +/** + * cds_decr_active_session() - decrements the number of active sessions + * @hdd_ctx: HDD Context + * @mode: Device mode + * @session_id: session ID for the connection session + * + * This function decrements the number of active sessions maintained per device + * mode. In the case of STA/P2P CLI/IBSS upon disconnection it is decremented + * In the case of SAP/P2P GO upon bss stop it is decremented + * + * Return: None + */ +void cds_decr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, + uint8_t session_id) +{ + switch (mode) { + case CDF_STA_MODE: + case CDF_P2P_CLIENT_MODE: + case CDF_P2P_GO_MODE: + case CDF_SAP_MODE: + if (hdd_ctx->no_of_active_sessions[mode]) + hdd_ctx->no_of_active_sessions[mode]--; + break; + default: + break; + } + cds_info("No.# of active sessions for mode %d = %d", + mode, hdd_ctx->no_of_active_sessions[mode]); + cds_decr_connection_count(hdd_ctx, session_id); +} + +/** + * cds_dbs_opportunistic_timer_handler() - handler of + * dbs_opportunistic_timer + * @data: HDD context + * + * handler for dbs_opportunistic_timer + * + * Return: None + */ +void cds_dbs_opportunistic_timer_handler(void *data) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) data; + enum cds_conc_next_action action = CDS_NOP; + + if (NULL == hdd_ctx) { + cds_err("hdd_ctx is NULL"); + return; + } + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + /* if we still need it */ + action = cds_need_opportunistic_upgrade(hdd_ctx); + if (action) { + /* lets call for action */ + cds_next_actions(hdd_ctx, action); + } + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + +} + +/** + * cds_init_policy_mgr() - Initialize the policy manager + * related data structures + * @hdd_ctx: HDD Context + * + * Initialize the policy manager related data structures + * + * Return: Success if the policy manager is initialized completely + */ +CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) +{ + CDF_STATUS status; + p_cds_contextType p_cds_context; + + cds_debug("Initializing the policy manager"); + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + cds_err("Invalid CDS context"); + return CDF_STATUS_E_FAILURE; + } + + /* init conc_connection_list */ + cdf_mem_zero(conc_connection_list, sizeof(conc_connection_list)); + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init( + &hdd_ctx->hdd_conc_list_lock))) { + cds_err("Failed to init hdd_conc_list_lock"); + /* Lets us not proceed further */ + return CDF_STATUS_E_FAILURE; + } + + sme_register_hw_mode_trans_cb(hdd_ctx->hHal, + cds_hw_mode_transition_cb); + status = cdf_mc_timer_init(&hdd_ctx->dbs_opportunistic_timer, + CDF_TIMER_TYPE_SW, + cds_dbs_opportunistic_timer_handler, + (void *)hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("Failed to init DBS opportunistic timer"); + return status; + } + + status = cdf_event_init(&p_cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("connection_update_done_evt init failed"); + return status; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_get_connection_for_vdev_id() - provides the + * perticular connection with the requested vdev id + * @hdd_ctx: HDD Context + * @vdev_id: vdev id of the connection + * + * This function provides the specific connection with the + * requested vdev id + * + * Return: index in the connection table + */ +uint32_t cds_get_connection_for_vdev_id(hdd_context_t *hdd_ctx, + uint32_t vdev_id) +{ + uint32_t conn_index = 0; + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list[conn_index].vdev_id == vdev_id) && + conc_connection_list[conn_index].in_use) { + break; + } + } + return conn_index; +} + + +/** + * cds_get_connection_count() - provides the count of + * current connections + * @hdd_ctx: HDD Context + * + * + * This function provides the count of current connections + * + * Return: connection count + */ +uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx) +{ + uint32_t conn_index, count = 0; + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if (conc_connection_list[conn_index].in_use) + count++; + } + return count; +} + +/** + * cds_get_mode() - Get mode from type and subtype + * @type: type + * @subtype: subtype + * + * Get the concurrency mode from the type and subtype + * of the interface + * + * Return: cds_con_mode + */ +enum cds_con_mode cds_get_mode(uint8_t type, uint8_t subtype) +{ + enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE; + if (type == WMI_VDEV_TYPE_AP) { + switch (subtype) { + case 0: + mode = CDS_SAP_MODE; + break; + case WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO: + mode = CDS_P2P_GO_MODE; + break; + default: + /* err msg*/ + cds_err("Unknown subtype %d for type %d", + subtype, type); + break; + } + } else if (type == WMI_VDEV_TYPE_STA) { + switch (subtype) { + case 0: + mode = CDS_STA_MODE; + break; + case WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT: + mode = CDS_P2P_CLIENT_MODE; + break; + default: + /* err msg*/ + cds_err("Unknown subtype %d for type %d", + subtype, type); + break; + } + } else if (type == WMI_VDEV_TYPE_IBSS) { + mode = CDS_IBSS_MODE; + } else { + /* err msg */ + cds_err("Unknown type %d", type); + } + + return mode; +} + +/** + * cds_incr_connection_count() - adds the new connection to + * the current connections list + * @hdd_ctx: HDD Context + * + * + * This function adds the new connection to the current + * connections list + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, + uint32_t vdev_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t conn_index; + struct wma_txrx_node *wma_conn_table_entry; + + conn_index = cds_get_connection_count(hdd_ctx); + if (hdd_ctx->config->gMaxConcurrentActiveSessions < conn_index) { + /* err msg */ + cds_err("exceeded max connection limit %d", + hdd_ctx->config->gMaxConcurrentActiveSessions); + return status; + } + + wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id); + + if (NULL == wma_conn_table_entry) { + /* err msg*/ + cds_err("can't find vdev_id %d in WMA table", vdev_id); + return status; + } + + /* add the entry */ + cds_update_conc_list(conn_index, + cds_get_mode(wma_conn_table_entry->type, + wma_conn_table_entry->sub_type), + cds_freq_to_chan(wma_conn_table_entry->mhz), + wma_conn_table_entry->mac_id, + wma_conn_table_entry->chain_mask, + wma_conn_table_entry->tx_streams, + wma_conn_table_entry->rx_streams, + wma_conn_table_entry->nss, vdev_id, true); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_update_connection_info() - updates the existing + * connection in the current connections list + * @hdd_ctx: HDD Context + * + * + * This function adds the new connection to the current + * connections list + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, + uint32_t vdev_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t conn_index = 0; + bool found = false; + struct wma_txrx_node *wma_conn_table_entry; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_id == conc_connection_list[conn_index].vdev_id) { + /* debug msg */ + found = true; + break; + } + conn_index++; + } + if (!found) { + /* err msg */ + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cds_err("can't find vdev_id %d in conc_connection_list", + vdev_id); + return status; + } + + wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id); + + if (NULL == wma_conn_table_entry) { + /* err msg*/ + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cds_err("can't find vdev_id %d in WMA table", vdev_id); + return status; + } + + /* add the entry */ + cds_update_conc_list(conn_index, + cds_get_mode(wma_conn_table_entry->type, + wma_conn_table_entry->sub_type), + cds_freq_to_chan(wma_conn_table_entry->mhz), + wma_conn_table_entry->mac_id, + wma_conn_table_entry->chain_mask, + wma_conn_table_entry->tx_streams, + wma_conn_table_entry->rx_streams, + wma_conn_table_entry->nss, vdev_id, true); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_decr_connection_count() - remove the old connection + * from the current connections list + * @hdd_ctx: HDD Context + * @vdev_id: vdev id of the old connection + * + * + * This function removes the old connection from the current + * connections list + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, + uint32_t vdev_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t conn_index = 0, next_conn_index = 0; + bool found = false; + + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_id == conc_connection_list[conn_index].vdev_id) { + /* debug msg */ + found = true; + break; + } + conn_index++; + } + if (!found) { + /* err msg */ + cds_err("can't find vdev_id %d in conc_connection_list", + vdev_id); + return status; + } + next_conn_index = conn_index + 1; + while (CONC_CONNECTION_LIST_VALID_INDEX(next_conn_index)) { + conc_connection_list[conn_index].vdev_id = + conc_connection_list[next_conn_index].vdev_id; + conc_connection_list[conn_index].tx_spatial_stream = + conc_connection_list[next_conn_index].tx_spatial_stream; + conc_connection_list[conn_index].rx_spatial_stream = + conc_connection_list[next_conn_index].rx_spatial_stream; + conc_connection_list[conn_index].mode = + conc_connection_list[next_conn_index].mode; + conc_connection_list[conn_index].mac = + conc_connection_list[next_conn_index].mac; + conc_connection_list[conn_index].chan = + conc_connection_list[next_conn_index].chan; + conc_connection_list[conn_index].chain_mask = + conc_connection_list[next_conn_index].chain_mask; + conc_connection_list[conn_index].original_nss = + conc_connection_list[next_conn_index].original_nss; + conc_connection_list[conn_index].in_use = + conc_connection_list[next_conn_index].in_use; + conn_index++; + next_conn_index++; + } + + /* clean up the entry */ + cdf_mem_zero(&conc_connection_list[next_conn_index - 1], + sizeof(*conc_connection_list)); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_get_connection_channels() - provides the channel(s) + * on which current connection(s) is + * @hdd_ctx: HDD Context + * @channels: the channel(s) on which current connection(s) is + * @len: Number of channels + * @order: no order OR 2.4 Ghz channel followed by 5 Ghz + * channel OR 5 Ghz channel followed by 2.4 Ghz channel + * + * + * This function provides the channel(s) on which current + * connection(s) is/are + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_get_connection_channels(hdd_context_t *hdd_ctx, + uint8_t *channels, uint32_t *len, uint8_t order) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t conn_index = 0, num_channels = 0; + + if (NULL == hdd_ctx) { + /* err msg*/ + cds_err("hdd_ctx is NULL"); + status = CDF_STATUS_E_FAILURE; + return status; + } + + if ((NULL == channels) || (NULL == len)) { + /* err msg*/ + cds_err("channels or len is NULL"); + status = CDF_STATUS_E_FAILURE; + return status; + } + + if (0 == order) { + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + channels[num_channels++] = + conc_connection_list[conn_index++].chan; + } + *len = num_channels; + } else if (1 == order) { + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[conn_index].chan)) { + channels[num_channels++] = + conc_connection_list[conn_index++].chan; + } else + conn_index++; + } + conn_index = 0; + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[conn_index].chan)) { + channels[num_channels++] = + conc_connection_list[conn_index++].chan; + } else + conn_index++; + } + *len = num_channels; + } else if (2 == order) { + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[conn_index].chan)) { + channels[num_channels++] = + conc_connection_list[conn_index++].chan; + } else + conn_index++; + } + conn_index = 0; + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[conn_index].chan)) { + channels[num_channels++] = + conc_connection_list[conn_index++].chan; + } else + conn_index++; + } + *len = num_channels; + } else { + cds_err("unknown order %d", order); + status = CDF_STATUS_E_FAILURE; + } + return status; +} + +/** + * cds_update_with_safe_channel_list() - provides the safe + * channel list + * @hdd_ctx: HDD Context + * @pcl_channels: channel list + * @len: length of the list + * + * This function provides the safe channel list from the list + * provided after consulting the channel avoidance list + * + * Return: None + */ +#ifdef CONFIG_CNSS +void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, + uint8_t *pcl_channels, uint32_t *len) +{ + uint16_t unsafe_channel_list[MAX_NUM_CHAN]; + uint8_t current_channel_list[MAX_NUM_CHAN]; + uint16_t unsafe_channel_count = 0; + uint8_t is_unsafe = 1; + uint8_t i, j; + uint32_t safe_channel_count = 0, current_channel_count = 0; + + if (len) { + current_channel_count = CDF_MIN(*len, MAX_NUM_CHAN); + } else { + cds_err("invalid number of channel length"); + return; + } + + cnss_get_wlan_unsafe_channel(unsafe_channel_list, + &unsafe_channel_count, + sizeof(unsafe_channel_list)); + + if (unsafe_channel_count) { + cdf_mem_copy(current_channel_list, pcl_channels, + current_channel_count); + cdf_mem_zero(pcl_channels, + sizeof(*pcl_channels)*current_channel_count); + + for (i = 0; i < current_channel_count; i++) { + is_unsafe = 0; + for (j = 0; j < unsafe_channel_count; j++) { + if (current_channel_list[i] == + unsafe_channel_list[j]) { + /* Found unsafe channel, update it */ + is_unsafe = 1; + cds_warn("CH %d is not safe", + current_channel_list[i]); + break; + } + } + if (!is_unsafe) { + pcl_channels[safe_channel_count++] = + current_channel_list[i]; + } + } + *len = safe_channel_count; + } + return; +} +#else +void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, + uint8_t *pcl_channels, uint32_t *len) +{ + return; +} +#endif +/** + * cds_get_channel_list() - provides the channel list + * suggestion for new connection + * @hdd_ctx: HDD Context + * @pcl: The preferred channel list enum + * @pcl_channels: PCL channels + * @len: lenght of the PCL + * + * This function provides the actual channel list based on the + * current regulatory domain derived using preferred channel + * list enum obtained from one of the pcl_table + * + * Return: Channel List + */ +CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, + enum cds_pcl_type pcl, + uint8_t *pcl_channels, uint32_t *len) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t num_channels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + uint32_t chan_index = 0, chan_index_24 = 0, chan_index_5 = 0; + uint8_t channel_list[MAX_NUM_CHAN] = {0}; + uint8_t channel_list_24[MAX_NUM_CHAN] = {0}; + uint8_t channel_list_5[MAX_NUM_CHAN] = {0}; + + if (NULL == hdd_ctx) { + /* err msg*/ + cds_err("hdd_ctx is NULL"); + return status; + } + + if ((NULL == pcl_channels) || (NULL == len)) { + /* err msg*/ + cds_err("pcl_channels or len is NULL"); + return status; + } + + if (CDS_MAX_PCL_TYPE == pcl) { + /* msg */ + cds_err("pcl is invalid"); + return status; + } + + if (CDS_NONE == pcl) { + /* msg */ + cds_err("pcl is 0"); + return CDF_STATUS_SUCCESS; + } + /* get the channel list for current domain */ + status = sme_get_cfg_valid_channels(hdd_ctx->hHal, channel_list, + &num_channels); + if (CDF_STATUS_SUCCESS != status) { + /* err msg*/ + cds_err("No valid channel"); + return status; + } + /* Let's divide the list in 2.4 & 5 Ghz lists */ + while ((channel_list[chan_index] <= 11) && + (chan_index_24 < MAX_NUM_CHAN)) + channel_list_24[chan_index_24++] = channel_list[chan_index++]; + if (channel_list[chan_index] == 12) { + channel_list_24[chan_index_24++] = channel_list[chan_index++]; + if (channel_list[chan_index] == 13) { + channel_list_24[chan_index_24++] = + channel_list[chan_index++]; + if (channel_list[chan_index] == 14) + channel_list_24[chan_index_24++] = + channel_list[chan_index++]; + } + } + while ((chan_index < num_channels) && + (chan_index_5 < MAX_NUM_CHAN)) + channel_list_5[chan_index_5++] = channel_list[chan_index++]; + + num_channels = 0; + switch (pcl) { + case CDS_24G: + cdf_mem_copy(pcl_channels, channel_list_24, + chan_index_24); + *len = chan_index_24; + status = CDF_STATUS_SUCCESS; + break; + case CDS_5G: + cdf_mem_copy(pcl_channels, channel_list_5, + chan_index_5); + *len = chan_index_5; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_CH: + case CDS_MCC_CH: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 0); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_CH_24G: + case CDS_MCC_CH_24G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 0); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_24, chan_index_24); + *len += chan_index_24; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_CH_5G: + case CDS_MCC_CH_5G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 0); + cdf_mem_copy(pcl_channels, channel_list, + num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_5, chan_index_5); + *len += chan_index_5; + status = CDF_STATUS_SUCCESS; + break; + case CDS_24G_SCC_CH: + case CDS_24G_MCC_CH: + cdf_mem_copy(pcl_channels, channel_list_24, + chan_index_24); + *len = chan_index_24; + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 0); + cdf_mem_copy(&pcl_channels[chan_index_24], + channel_list, num_channels); + *len += num_channels; + status = CDF_STATUS_SUCCESS; + break; + case CDS_5G_SCC_CH: + case CDS_5G_MCC_CH: + cdf_mem_copy(pcl_channels, channel_list_5, + chan_index_5); + *len = chan_index_5; + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 0); + cdf_mem_copy(&pcl_channels[chan_index_5], + channel_list, num_channels); + *len += num_channels; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_24_SCC_ON_5: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 1); + cdf_mem_copy(pcl_channels, channel_list, + num_channels); + *len = num_channels; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_5_SCC_ON_24: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 2); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_24_SCC_ON_5_24G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 1); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_24, chan_index_24); + *len += chan_index_24; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_24_SCC_ON_5_5G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 1); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_5, chan_index_5); + *len += chan_index_5; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_5_SCC_ON_24_24G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 2); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_24, chan_index_24); + *len += chan_index_24; + status = CDF_STATUS_SUCCESS; + break; + case CDS_SCC_ON_5_SCC_ON_24_5G: + cds_get_connection_channels(hdd_ctx, + channel_list, &num_channels, 2); + cdf_mem_copy(pcl_channels, channel_list, num_channels); + *len = num_channels; + cdf_mem_copy(&pcl_channels[num_channels], + channel_list_5, chan_index_5); + *len += chan_index_5; + status = CDF_STATUS_SUCCESS; + break; + default: + /* err msg */ + cds_err("unknown pcl value %d", pcl); + break; + } + + /* check the channel avoidance list */ + cds_update_with_safe_channel_list(hdd_ctx, pcl_channels, len); + + return status; +} + +/** + * cds_map_concurrency_mode() - to map concurrency mode between sme and hdd + * @hdd_ctx: hdd context + * @old_mode: sme provided concurrency mode + * @new_mode: hdd provided concurrency mode + * + * This routine will map concurrency mode between sme and hdd + * + * Return: true or false + */ +bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, + tCDF_CON_MODE *old_mode, enum cds_con_mode *new_mode) +{ + bool status = true; + + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + + switch (*old_mode) { + + case CDF_STA_MODE: + *new_mode = CDS_STA_MODE; + break; + case CDF_SAP_MODE: + *new_mode = CDS_SAP_MODE; + break; + case CDF_P2P_CLIENT_MODE: + *new_mode = CDS_P2P_CLIENT_MODE; + break; + case CDF_P2P_GO_MODE: + *new_mode = CDS_P2P_GO_MODE; + break; + case CDF_IBSS_MODE: + *new_mode = CDS_IBSS_MODE; + break; + default: + *new_mode = CDS_MAX_NUM_OF_MODE; + status = false; + break; + } + return status; +} + +/** + * cds_get_pcl() - provides the preferred channel list for + * new connection + * @hdd_ctx: HDD Context + * @mode: Device mode + * @pcl_channels: PCL channels + * @len: lenght of the PCL + * + * This function provides the preferred channel list on which + * policy manager wants the new connection to come up. Various + * connection decision making entities will using this function + * to query the PCL info + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, + uint8_t *pcl_channels, uint32_t *len) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t num_connections = 0; + enum cds_conc_priority_mode first_index = 0; + enum cds_one_connection_mode second_index = 0; + enum cds_two_connection_mode third_index = 0; + enum cds_pcl_type pcl = CDS_NONE; + enum cds_conc_priority_mode conc_system_pref = 0; + /* find the current connection state from conc_connection_list*/ + num_connections = cds_get_connection_count(hdd_ctx); + cds_debug("connections:%d pref:%d requested mode:%d", + num_connections, hdd_ctx->config->conc_system_pref, mode); + + switch (hdd_ctx->config->conc_system_pref) { + case 0: + conc_system_pref = CDS_THROUGHPUT; + break; + case 1: + conc_system_pref = CDS_POWERSAVE; + break; + case 2: + conc_system_pref = CDS_LATENCY; + break; + default: + /* err msg */ + cds_err("unknown conc_system_pref value %d", + hdd_ctx->config->conc_system_pref); + break; + } + + switch (num_connections) { + case 0: + first_index = + cds_get_first_connection_pcl_table_index(hdd_ctx); + pcl = first_connection_pcl_table[mode][first_index]; + break; + case 1: + second_index = + cds_get_second_connection_pcl_table_index(hdd_ctx); + if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { + /* err msg */ + cds_err("couldn't find index for 2nd connection pcl table"); + return status; + } + if (wma_is_hw_dbs_capable() == true) { + pcl = second_connection_pcl_dbs_table + [second_index][mode][conc_system_pref]; + } else { + pcl = second_connection_pcl_nodbs_table + [second_index][mode][conc_system_pref]; + } + + break; + case 2: + third_index = + cds_get_third_connection_pcl_table_index(hdd_ctx); + if (CDS_MAX_TWO_CONNECTION_MODE == third_index) { + /* err msg */ + cds_err("couldn't find index for 3rd connection pcl table"); + return status; + } + if (wma_is_hw_dbs_capable() == true) { + pcl = third_connection_pcl_dbs_table + [third_index][mode][conc_system_pref]; + } else { + pcl = third_connection_pcl_nodbs_table + [third_index][mode][conc_system_pref]; + } + break; + default: + /* err msg */ + cds_err("unexpected num_connections value %d", + num_connections); + break; + } + + cds_debug("index1:%d index2:%d index3:%d pcl:%d dbs:%d", + first_index, second_index, third_index, + pcl, wma_is_hw_dbs_capable()); + + /* once the PCL enum is obtained find out the exact channel list with + * help from sme_get_cfg_valid_channels + */ + status = cds_get_channel_list(hdd_ctx, pcl, pcl_channels, len); + if (status == CDF_STATUS_SUCCESS) { + uint32_t i; + cds_debug("pcl len:%d", *len); + for (i = 0; i < *len; i++) + cds_debug("chan:%d", pcl_channels[i]); + } + + return status; +} + +/** + * cds_disallow_mcc() - Check for mcc + * + * @hdd_ctx: HDD Context + * @channel: channel on which new connection is coming up + * + * When a new connection is about to come up check if current + * concurrency combination including the new connection is + * causing MCC + * + * Return: True/False + */ +bool cds_disallow_mcc(hdd_context_t *hdd_ctx, uint8_t channel) +{ + uint32_t index = 0; + bool match = false; + while (CONC_CONNECTION_LIST_VALID_INDEX(index)) { + if (wma_is_hw_dbs_capable() == false) { + if (conc_connection_list[index].chan != + channel) { + match = true; + break; + } + } else if (CDS_IS_CHANNEL_5GHZ + (conc_connection_list[index].chan)) { + if (conc_connection_list[index].chan != channel) { + match = true; + break; + } + } + index++; + } + return match; +} + +/** + * cds_allow_new_home_channel() - Check for allowed number of + * home channels + * + * @hdd_ctx: HDD Context + * @channel: channel on which new connection is coming up + * @num_connections: number of current connections + * + * When a new connection is about to come up check if current + * concurrency combination including the new connection is + * allowed or not based on the HW capability + * + * Return: True/False + */ +bool cds_allow_new_home_channel(hdd_context_t *hdd_ctx, + uint8_t channel, uint32_t num_connections) +{ + bool status = true; + + if ((num_connections == 2) && + (conc_connection_list[0].chan != conc_connection_list[1].chan) + && + (conc_connection_list[0].mac == conc_connection_list[1].mac)) { + if (wma_is_hw_dbs_capable() == false) { + if ((channel != conc_connection_list[0].chan) && + (channel != conc_connection_list[1].chan)) { + /* err msg */ + cds_err("don't allow 3rd home channel on same MAC"); + status = false; + } + } else if (((CDS_IS_CHANNEL_24GHZ(channel)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[1].chan))) || + ((CDS_IS_CHANNEL_5GHZ(channel)) && + (CDS_IS_CHANNEL_5GHZ + (conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ + (conc_connection_list[1].chan)))) { + /* err msg */ + cds_err("don't allow 3rd home channel on same MAC"); + status = false; + } +#ifndef QCA_WIFI_3_0_EMU + } +#else + } else if ((num_connections == 1) && + (conc_connection_list[0].chan != channel)) { + if (((CDS_IS_CHANNEL_24GHZ(channel)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan))) || + ((CDS_IS_CHANNEL_5GHZ(channel)) && + (CDS_IS_CHANNEL_5GHZ + (conc_connection_list[0].chan)))) { + /* err msg */ + cds_err("don't allow 2nd home channel on same MAC"); + status = false; + } + } +#endif + return status; +} + +/** + * cds_allow_concurrency() - Check for allowed concurrency + * combination + * + * @hdd_ctx: HDD Context + * @mode: new connection mode + * @channel: channel on which new connection is coming up + * @bw: Bandwidth requested by the connection (optional) + * + * When a new connection is about to come up check if current + * concurrency combination including the new connection is + * allowed or not based on the HW capability + * + * Return: True/False + */ +bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, + uint8_t channel, enum hw_mode_bandwidth bw) +{ + uint32_t num_connections = 0, count = 0, index = 0; + bool status = false, match = false; + uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + /* find the current connection state from conc_connection_list*/ + num_connections = cds_get_connection_count(hdd_ctx); + + if (cds_max_concurrent_connections_reached()) { + cds_err("Reached max concurrent connections: %d", + hdd_ctx->config->gMaxConcurrentActiveSessions); + goto done; + } + + if (channel) { + /* don't allow 3rd home channel on same MAC */ + if (!cds_allow_new_home_channel(hdd_ctx, channel, + num_connections)) + goto done; + + /* don't allow MCC if SAP/GO on DFS channel or about to come up + * on DFS channel + */ + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_P2P_GO_MODE, list); + while (index < count) { + if ((CDS_IS_DFS_CH( + conc_connection_list[list[index]].chan)) && + (CDS_IS_CHANNEL_5GHZ(channel)) && + (channel != + conc_connection_list[list[index]].chan)) { + /* err msg */ + cds_err("don't allow MCC if SAP/GO on DFS channel"); + goto done; + } + index++; + } + + index = 0; + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_SAP_MODE, list); + while (index < count) { + if ((CDS_IS_DFS_CH( + conc_connection_list[list[index]].chan)) && + (CDS_IS_CHANNEL_5GHZ(channel)) && + (channel != + conc_connection_list[list[index]].chan)) { + /* err msg */ + cds_err("don't allow MCC if SAP/GO on DFS channel"); + goto done; + } + index++; + } + + index = 0; + if ((CDS_P2P_GO_MODE == mode) || (CDS_SAP_MODE == mode)) { + if (CDS_IS_DFS_CH(channel)) + match = cds_disallow_mcc(hdd_ctx, channel); + } + if (true == match) { + cds_err("No MCC, SAP/GO about to come up on DFS channel"); + goto done; + } + } + + /* don't allow IBSS + STA MCC */ + /* don't allow IBSS + STA SCC if IBSS is on DFS channel */ + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_STA_MODE, list); + if ((CDS_IBSS_MODE == mode) && + (cds_mode_specific_connection_count(hdd_ctx, + CDS_IBSS_MODE, list)) && count) { + /* err msg */ + cds_err("No 2nd IBSS, we already have STA + IBSS"); + goto done; + } + if ((CDS_IBSS_MODE == mode) && + (CDS_IS_DFS_CH(channel)) && count) { + /* err msg */ + cds_err("No IBSS + STA SCC/MCC, IBSS is on DFS channel"); + goto done; + } + if (CDS_IBSS_MODE == mode) { + if (wma_is_hw_dbs_capable() == true) { + if (num_connections > 1) { + /* err msg */ + cds_err("No IBSS, we have concurrent connections already"); + goto done; + } + if (CDS_STA_MODE != conc_connection_list[0].mode) { + /* err msg */ + cds_err("No IBSS, we have a non STA connection"); + goto done; + } + if (channel && + (conc_connection_list[0].chan != channel) && + CDS_IS_SAME_BAND_CHANNELS( + conc_connection_list[0].chan, channel)) { + /* err msg */ + cds_err("No IBSS + STA MCC"); + goto done; + } + } else if (num_connections) { + /* err msg */ + cds_err("No IBSS, we have one connection already"); + goto done; + } + } + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_STA_MODE, list); + if ((CDS_STA_MODE == mode) && + (cds_mode_specific_connection_count(hdd_ctx, + CDS_IBSS_MODE, list)) && count) { + /* err msg */ + cds_err("No 2nd STA, we already have STA + IBSS"); + goto done; + } + + if ((CDS_STA_MODE == mode) && + (cds_mode_specific_connection_count(hdd_ctx, + CDS_IBSS_MODE, list))) { + if (wma_is_hw_dbs_capable() == true) { + if (num_connections > 1) { + /* err msg */ + cds_err("No 2nd STA, we already have IBSS concurrency"); + goto done; + } + if (channel && + (CDS_IS_DFS_CH(conc_connection_list[0].chan)) + && (CDS_IS_CHANNEL_5GHZ(channel))) { + /* err msg */ + cds_err("No IBSS + STA SCC/MCC, IBSS is on DFS channel"); + goto done; + } + if ((conc_connection_list[0].chan != channel) && + CDS_IS_SAME_BAND_CHANNELS( + conc_connection_list[0].chan, channel)) { + /* err msg */ + cds_err("No IBSS + STA MCC"); + goto done; + } + } else { + /* err msg */ + cds_err("No STA, we have IBSS connection already"); + goto done; + } + } + + /* can we allow vht160 */ + if (num_connections && + ((bw == HW_MODE_80_PLUS_80_MHZ) || (bw == HW_MODE_160_MHZ))) { + /* err msg */ + cds_err("No VHT160, we have one connection already"); + goto done; + } + status = true; + +done: + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + return status; +} + +/** + * cds_get_first_connection_pcl_table_index() - provides the + * row index to firstConnectionPclTable to get to the correct + * pcl + * @hdd_ctx: HDD Context + * + * This function provides the row index to + * firstConnectionPclTable. The index is the preference config. + * + * Return: table index + */ +enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( + hdd_context_t *hdd_ctx) +{ + if (hdd_ctx->config->conc_system_pref >= CDS_MAX_CONC_PRIORITY_MODE) + return CDS_THROUGHPUT; + return hdd_ctx->config->conc_system_pref; +} + +/** + * cds_get_second_connection_pcl_table_index() - provides the + * row index to secondConnectionPclTable to get to the correct + * pcl + * @hdd_ctx: HDD Context + * + * This function provides the row index to + * secondConnectionPclTable. The index is derived based on + * current connection, band on which it is on & chain mask it is + * using, as obtained from conc_connection_list. + * + * Return: table index + */ +enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( + hdd_context_t *hdd_ctx) +{ + enum cds_one_connection_mode index = CDS_MAX_ONE_CONNECTION_MODE; + + if (CDS_STA_MODE == conc_connection_list[0].mode) { + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_STA_24_1x1; + else + index = CDS_STA_24_2x2; + } else { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_STA_5_1x1; + else + index = CDS_STA_5_2x2; + } + } else if (CDS_SAP_MODE == conc_connection_list[0].mode) { + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_SAP_24_1x1; + else + index = CDS_SAP_24_2x2; + } else { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_SAP_5_1x1; + else + index = CDS_SAP_5_2x2; + } + } else if (CDS_P2P_CLIENT_MODE == conc_connection_list[0].mode) { + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_24_1x1; + else + index = CDS_P2P_CLI_24_2x2; + } else { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_5_1x1; + else + index = CDS_P2P_CLI_5_2x2; + } + } else if (CDS_P2P_GO_MODE == conc_connection_list[0].mode) { + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_24_1x1; + else + index = CDS_P2P_GO_24_2x2; + } else { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_5_1x1; + else + index = CDS_P2P_GO_5_2x2; + } + } else if (CDS_IBSS_MODE == conc_connection_list[0].mode) { + if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_IBSS_24_1x1; + else + index = CDS_IBSS_24_2x2; + } else { + if (CDS_ONE_ONE == conc_connection_list[0].chain_mask) + index = CDS_IBSS_5_1x1; + else + index = CDS_IBSS_5_2x2; + } + } + + cds_debug("mode:%d chan:%d chain:%d index:%d", + conc_connection_list[0].mode, conc_connection_list[0].chan, + conc_connection_list[0].chain_mask, index); + + return index; +} + +/** + * cds_get_third_connection_pcl_table_index() - provides the + * row index to thirdConnectionPclTable to get to the correct + * pcl + * @hdd_ctx: HDD Context + * + * This function provides the row index to + * thirdConnectionPclTable. The index is derived based on + * current connection, band on which it is on & chain mask it is + * using, as obtained from conc_connection_list. + * + * Return: table index + */ +enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( + hdd_context_t *hdd_ctx) +{ + enum cds_one_connection_mode index = CDS_MAX_TWO_CONNECTION_MODE; + + /* STA + SAP */ + if (((CDS_STA_MODE == conc_connection_list[0].mode) && + (CDS_SAP_MODE == conc_connection_list[1].mode)) || + ((CDS_SAP_MODE == conc_connection_list[0].mode) && + (CDS_STA_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_SAP_SCC_24_1x1; + else + index = CDS_STA_SAP_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_SAP_SCC_5_1x1; + else + index = CDS_STA_SAP_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_SAP_MCC_24_1x1; + else + index = CDS_STA_SAP_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_SAP_MCC_5_1x1; + else + index = CDS_STA_SAP_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_SAP_MCC_24_5_1x1; + else + index = CDS_STA_SAP_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_STA_SAP_DBS_1x1; + } else /* STA + P2P GO */ + if (((CDS_STA_MODE == conc_connection_list[0].mode) && + (CDS_P2P_GO_MODE == conc_connection_list[1].mode)) || + ((CDS_P2P_GO_MODE == conc_connection_list[0].mode) && + (CDS_STA_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_GO_SCC_24_1x1; + else + index = CDS_STA_P2P_GO_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_GO_SCC_5_1x1; + else + index = CDS_STA_P2P_GO_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_GO_MCC_24_1x1; + else + index = CDS_STA_P2P_GO_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_GO_MCC_5_1x1; + else + index = CDS_STA_P2P_GO_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_GO_MCC_24_5_1x1; + else + index = CDS_STA_P2P_GO_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_STA_P2P_GO_DBS_1x1; + } else /* STA + P2P CLI */ + if (((CDS_STA_MODE == conc_connection_list[0].mode) && + (CDS_P2P_CLIENT_MODE == conc_connection_list[1].mode)) || + ((CDS_P2P_CLIENT_MODE == conc_connection_list[0].mode) && + (CDS_STA_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_CLI_SCC_24_1x1; + else + index = CDS_STA_P2P_CLI_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_CLI_SCC_5_1x1; + else + index = CDS_STA_P2P_CLI_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_CLI_MCC_24_1x1; + else + index = CDS_STA_P2P_CLI_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_CLI_MCC_5_1x1; + else + index = CDS_STA_P2P_CLI_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_STA_P2P_CLI_MCC_24_5_1x1; + else + index = CDS_STA_P2P_CLI_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_STA_P2P_CLI_DBS_1x1; + } else /* P2P GO + P2P CLI */ + if (((CDS_P2P_GO_MODE == conc_connection_list[0].mode) && + (CDS_P2P_CLIENT_MODE == conc_connection_list[1].mode)) || + ((CDS_P2P_CLIENT_MODE == conc_connection_list[0].mode) && + (CDS_P2P_GO_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_P2P_CLI_SCC_24_1x1; + else + index = CDS_P2P_GO_P2P_CLI_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_P2P_CLI_SCC_5_1x1; + else + index = CDS_P2P_GO_P2P_CLI_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_P2P_CLI_MCC_24_1x1; + else + index = CDS_P2P_GO_P2P_CLI_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_P2P_CLI_MCC_5_1x1; + else + index = CDS_P2P_GO_P2P_CLI_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_P2P_CLI_MCC_24_5_1x1; + else + index = CDS_P2P_GO_P2P_CLI_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_P2P_GO_P2P_CLI_DBS_1x1; + } else /* STA + P2P CLI */ + if (((CDS_SAP_MODE == conc_connection_list[0].mode) && + (CDS_P2P_GO_MODE == conc_connection_list[1].mode)) || + ((CDS_P2P_GO_MODE == conc_connection_list[0].mode) && + (CDS_SAP_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_SAP_SCC_24_1x1; + else + index = CDS_P2P_GO_SAP_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_SAP_SCC_5_1x1; + else + index = CDS_P2P_GO_SAP_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_SAP_MCC_24_1x1; + else + index = CDS_P2P_GO_SAP_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_SAP_MCC_5_1x1; + else + index = CDS_P2P_GO_SAP_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_GO_SAP_MCC_24_5_1x1; + else + index = CDS_P2P_GO_SAP_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_P2P_GO_SAP_DBS_1x1; + } + + cds_debug("mode0:%d mode1:%d chan0:%d chan1:%d chain:%d index:%d", + conc_connection_list[0].mode, conc_connection_list[1].mode, + conc_connection_list[0].chan, conc_connection_list[1].chan, + conc_connection_list[0].chain_mask, index); + + return index; +} + +/** + * cds_mode_switch_dbs_to_mcc() - initiates a mode switch + * from DBS to MCC + * @hdd_ctx: HDD Context + * + * This function initiates a mode switch from DBS to MCC if any + * change in concurrency scenario or some other external entity + * (looking for range, thermal mitigation etc.) made an explicit + * request. Notifies FW as well + * + * Return: CDF_STATUS enum + */ +CDF_STATUS cds_mode_switch_dbs_to_mcc(hdd_context_t *hdd_ctx) +{ + return CDF_STATUS_SUCCESS; +} + +/** + * cds_mode_switch_mcc_to_dbs() - initiates a mode switch + * from MCC to DBS + * @hdd_ctx: HDD Context + * + * This function initiates a mode switch from MCC to DBS if any + * change in concurrency scenario or some other external entity + * (powersave, thermal mitigation etc.) made an explicit + * request. Notifies FW as well + * + * Return: CDF_STATUS enum + */ +CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) +{ + return CDF_STATUS_SUCCESS; +} + +/** + * cds_current_connections_update() - initiates actions + * needed on current connections once channel has been decided + * for the new connection + * @hdd_ctx: HDD Context + * @channel: Channel on which new connection will be + * + * This function initiates initiates actions + * needed on current connections once channel has been decided + * for the new connection. Notifies UMAC & FW as well + * + * Return: CDF_STATUS enum + */ +CDF_STATUS cds_current_connections_update( + hdd_context_t *hdd_ctx, + uint8_t channel) +{ + enum cds_conc_next_action next_action = CDS_NOP; + uint32_t num_connections = 0; + enum cds_one_connection_mode second_index = 0; + enum cds_two_connection_mode third_index = 0; + enum cds_band band; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (wma_is_hw_dbs_capable() == false) { + cds_err("driver isn't dbs capable, no further action needed"); + return CDF_STATUS_E_NOSUPPORT; + } + if (CDS_IS_CHANNEL_24GHZ(channel)) + band = CDS_BAND_24; + else + band = CDS_BAND_5; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + num_connections = cds_get_connection_count(hdd_ctx); + + cds_debug("num_connections=%d channel=%d", + num_connections, channel); + + switch (num_connections) { + case 0: + next_action = CDS_NOP; +#ifdef QCA_WIFI_3_0_EMU + /* For emulation only: if it is a connection on 2.4, + * request DBS + */ + if (CDS_IS_CHANNEL_24GHZ(channel)) + next_action = CDS_DBS; +#endif + break; + case 1: + second_index = + cds_get_second_connection_pcl_table_index(hdd_ctx); + if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { + /* err msg */ + cds_err("couldn't find index for 2nd connection next action table"); + goto done; + } + next_action = + next_action_two_connection_table[second_index][band]; + break; + case 2: + third_index = + cds_get_third_connection_pcl_table_index(hdd_ctx); + if (CDS_MAX_TWO_CONNECTION_MODE == third_index) { + /* err msg */ + cds_err("couldn't find index for 3rd connection next action table"); + goto done; + } + next_action = + next_action_three_connection_table[third_index][band]; + break; + default: + /* err msg */ + cds_err("unexpected num_connections value %d", num_connections); + break; + } + + if (CDS_NOP != next_action) + status = cds_next_actions(hdd_ctx, next_action); + else + status = CDF_STATUS_E_NOSUPPORT; + + cds_debug("index2=%d index3=%d next_action=%d, band=%d status=%d", + second_index, third_index, next_action, band, status); + +done: + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + return status; +} + +/** + * cds_wait_for_nss_update() - finds out if we need to wait + * for all nss update to finish before requesting for HW mode + * update + * @hdd_ctx: HDD Context + * @action: next action to happen at policy mgr after + * beacon update + * + * This function finds out if we need to wait + * for all nss update to finish before requesting for HW mode + * update + * + * Return: boolean. True = wait for nss update, False = go ahead + * with HW mode update + */ +bool cds_wait_for_nss_update(hdd_context_t *hdd_ctx, uint8_t action) +{ + uint32_t conn_index = 0; + bool wait = false; + if (CDS_DBS == action) { + for (conn_index = 0; + conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list + [conn_index].original_nss == 1) && + (conc_connection_list + [conn_index].tx_spatial_stream == 2) && + (conc_connection_list + [conn_index].rx_spatial_stream == 2) && + conc_connection_list[conn_index].in_use) { + wait = true; + break; + } + } + } else if (CDS_MCC == action) { + for (conn_index = 0; + conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((conc_connection_list + [conn_index].original_nss == 1) && + (conc_connection_list + [conn_index].tx_spatial_stream == 1) && + (conc_connection_list + [conn_index].rx_spatial_stream == 1) && + conc_connection_list[conn_index].in_use) { + wait = true; + break; + } + } + } + return wait; +} + +/** + * cds_nss_update_cb() - callback from SME confirming nss + * update + * @hdd_ctx: HDD Context + * @tx_status: tx completion status for updated beacon with new + * nss value + * @vdev_id: vdev id for the specific connection + * @next_action: next action to happen at policy mgr after + * beacon update + * + * This function is the callback registered with SME at nss + * update request time + * + * Return: None + */ +void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, + uint8_t next_action) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *)context; + uint32_t conn_index = 0; + bool wait = true; + + if (CDF_STATUS_E_FAILURE == tx_status) { + cds_err("nss update failed for vdev %d", vdev_id); + return; + } + if (NULL == hdd_ctx) { + cds_err("NULL hdd_ctx"); + return; + } + + /** + * Check if we are ok to request for HW mode change now + */ + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + conn_index = cds_get_connection_for_vdev_id(hdd_ctx, vdev_id); + if (MAX_NUMBER_OF_CONC_CONNECTIONS == conn_index) { + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cds_err("connection not found for vdev %d", vdev_id); + return; + } + switch (next_action) { + case CDS_DBS: + conc_connection_list[conn_index].tx_spatial_stream = 1; + conc_connection_list[conn_index].rx_spatial_stream = 1; + wait = cds_wait_for_nss_update(hdd_ctx, next_action); + break; + case CDS_MCC: + conc_connection_list[conn_index].tx_spatial_stream = 2; + conc_connection_list[conn_index].rx_spatial_stream = 2; + wait = cds_wait_for_nss_update(hdd_ctx, next_action); + break; + default: + cds_err("unexpected action %d", next_action); + break; + } + if (!wait) + cds_next_actions(hdd_ctx, next_action); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + return; +} + +/** + * cds_complete_action() - initiates actions needed on + * current connections once channel has been decided for the new + * connection + * @hdd_ctx: HDD Context + * @new_nss: the new nss value + * @next_action: next action to happen at policy mgr after + * beacon update + * + * This function initiates initiates actions + * needed on current connections once channel has been decided + * for the new connection. Notifies UMAC & FW as well + * + * Return: CDF_STATUS enum + */ +CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, + uint8_t new_nss, uint8_t next_action) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t index = 0, count = 0; + uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + uint32_t conn_index = 0; + + if (wma_is_hw_dbs_capable() == false) { + cds_err("driver isn't dbs capable, no further action needed"); + return CDF_STATUS_E_NOSUPPORT; + } + + /* cds_complete_action() is called by cds_next_actions(). + * All other callers of cds_next_actions() have taken mutex + * protection. So, not taking any lock inside cds_complete_action() + * during conc_connection_list access. + */ + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_P2P_GO_MODE, list); + while (index < count) { + conn_index = cds_get_connection_for_vdev_id(hdd_ctx, + conc_connection_list[list[index]].vdev_id); + if (MAX_NUMBER_OF_CONC_CONNECTIONS == conn_index) { + cds_err("connection not found for vdev %d", + conc_connection_list[list[index]].vdev_id); + continue; + } + + if (1 == conc_connection_list[list[index]].original_nss) { + status = sme_nss_update_request(hdd_ctx->hHal, + conc_connection_list + [list[index]].vdev_id, new_nss, + cds_nss_update_cb, + next_action, hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("sme_nss_update_request() failed for vdev %d", + conc_connection_list[list[index]].vdev_id); + } + } + index++; + } + + index = 0; + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_SAP_MODE, list); + while (index < count) { + if (1 == conc_connection_list[list[index]].original_nss) { + status = sme_nss_update_request(hdd_ctx->hHal, + conc_connection_list + [list[index]].vdev_id, new_nss, + cds_nss_update_cb, + next_action, hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("sme_nss_update_request() failed for vdev %d", + conc_connection_list[list[index]].vdev_id); + } + } + index++; + } + if (!CDF_IS_STATUS_SUCCESS(status)) + status = cds_next_actions(hdd_ctx, next_action); + + return status; +} + +/** + * cds_next_actions() - initiates actions needed on current + * connections once channel has been decided for the new + * connection + * @hdd_ctx: HDD Context + * @action: action to be executed + * + * This function initiates initiates actions + * needed on current connections once channel has been decided + * for the new connection. Notifies UMAC & FW as well + * + * Return: CDF_STATUS enum + */ +CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, + enum cds_conc_next_action action) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + struct sir_hw_mode_params hw_mode; + + if (wma_is_hw_dbs_capable() == false) { + cds_err("driver isn't dbs capable, no further action needed"); + return CDF_STATUS_E_NOSUPPORT; + } + + /* check for the current HW index to see if really need any action */ + status = wma_get_current_hw_mode(&hw_mode); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("wma_get_current_hw_mode failed"); + return status; + } + /** + * if already in DBS no need to request DBS or if already in + * non dbs no need request for non dbs again. Might be needed + * to extend the logic when multiple dbs HW mode is available + */ + if ((((CDS_DBS_DOWNGRADE == action) || (CDS_DBS == action)) + && hw_mode.dbs_cap) || + (((CDS_MCC_UPGRADE == action) || (CDS_MCC == action)) + && !hw_mode.dbs_cap)) { + cds_err("driver is already in %s mode, no further action needed", + (hw_mode.dbs_cap) ? "dbs" : "non dbs"); + return CDF_STATUS_E_ALREADY; + } + + switch (action) { + case CDS_DBS_DOWNGRADE: + /* + * check if we have a beaconing entity that is using 2x2. If yes, + * update the beacon template & notify FW. Once FW confirms + * beacon updated, send down the HW mode change req + */ + status = cds_complete_action(hdd_ctx, 1, CDS_DBS); + break; + case CDS_DBS: + status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE); + break; + case CDS_MCC_UPGRADE: + /* + * check if we have a beaconing entity that advertised 2x2 + * intially. If yes, update the beacon template & notify FW. + * Once FW confirms beacon updated, send the HW mode change req + */ + status = cds_complete_action(hdd_ctx, 0, CDS_MCC); + break; + case CDS_MCC: + status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_0x0, HW_MODE_BW_NONE, + HW_MODE_DBS_NONE, + HW_MODE_AGILE_DFS_NONE); + break; + default: + /* err msg */ + cds_err("unexpected action value %d", action); + status = CDF_STATUS_E_FAILURE; + break; + } + + return status; +} + +/** + * cds_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix + * @wiphy: pointer phy adapter + * @wdev: pointer to wireless device structure + * @data: pointer to data buffer + * @data_len: length of data + * + * This routine will give concurrency matrix + * + * Return: int status code + */ +static int __cds_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint32_t feature_set_matrix[CDS_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 (CDF_FTM_MODE == hdd_get_conparam()) { + cds_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + cds_err("HDD context is not valid"); + return ret; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX, + data, data_len, NULL)) { + cds_err("Invalid ATTR"); + return -EINVAL; + } + + /* Parse and fetch max feature set */ + if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) { + cds_err("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]); + cds_info("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 = CDF_MIN(feature_sets, max_feature_sets); + cds_info("Number of feature sets (%d)", feature_sets); + cds_info("Feature set matrix"); + for (i = 0; i < feature_sets; i++) + cds_info("[%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)) { + cds_err("nla put fail"); + kfree_skb(reply_skb); + return -EINVAL; + } + return cfg80211_vendor_cmd_reply(reply_skb); + } + cds_err("Feature set matrix: buffer alloc fail"); + return -ENOMEM; +} + +/** + * cds_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. + */ +int +cds_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __cds_cfg80211_get_concurrency_matrix(wiphy, wdev, data, + data_len); + cds_ssr_unprotect(__func__); + return ret; +} + +/** + * cds_get_concurrency_mode() - return concurrency mode + * + * This routine is used to retrieve concurrency mode + * + * Return: uint32_t value of concurrency mask + */ +uint32_t cds_get_concurrency_mode(void) +{ + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != hdd_ctx) { + cds_info("concurrency_mode = 0x%x", + hdd_ctx->concurrency_mode); + return hdd_ctx->concurrency_mode; + } + + /* we are in an invalid state :( */ + cds_err("Invalid context"); + return CDF_STA_MASK; +} + +/** + * cds_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 cds_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); + cds_ssr_protect(__func__); + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + cds_err("HDD context is not valid"); + cds_ssr_unprotect(__func__); + return; + } + sap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (sap_adapter == NULL) { + cds_err("sap_adapter is NULL"); + cds_ssr_unprotect(__func__); + return; + } + wlan_hdd_start_sap(sap_adapter); + + cds_change_sap_restart_required_status(hdd_ctx, false); + cds_ssr_unprotect(__func__); +} + +/** + * cds_check_and_restart_sap() - Check and restart sap if required + * @hdd_ctx: pointer to HDD context + * @roam_result: Roam result + * @hdd_sta_ctx: HDD station context + * + * This routine will restart the SAP if restart is pending + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, + eCsrRoamResult roam_result, + hdd_station_ctx_t *hdd_sta_ctx) +{ + hdd_adapter_t *sap_adapter = NULL; + hdd_ap_ctx_t *hdd_ap_ctx = NULL; + uint8_t default_sap_channel = 6; + + if (!(hdd_ctx->config->conc_custom_rule1 && + (true == cds_is_sap_restart_required(hdd_ctx)))) + return CDF_STATUS_SUCCESS; + + sap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (sap_adapter == NULL) { + cds_err("sap_adapter is NULL"); + return CDF_STATUS_E_FAILURE; + } + + if (test_bit(SOFTAP_BSS_STARTED, &sap_adapter->event_flags)) { + cds_err("SAP is already in started state"); + return CDF_STATUS_E_FAILURE; + } + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(sap_adapter); + if (hdd_ap_ctx == NULL) { + cds_err("HDD sap context is NULL"); + return CDF_STATUS_E_FAILURE; + } + if ((eCSR_ROAM_RESULT_ASSOCIATED == roam_result) && + hdd_sta_ctx->conn_info.operationChannel < + SIR_11A_CHANNEL_BEGIN) { + cds_err("Starting SAP on chnl [%d] after STA assoc complete", + hdd_sta_ctx->conn_info.operationChannel); + hdd_ap_ctx->operatingChannel = + hdd_sta_ctx->conn_info.operationChannel; + } else { + /* start on default SAP channel */ + hdd_ap_ctx->operatingChannel = + default_sap_channel; + cds_err("Starting SAP on channel [%d] after STA assoc failed", + default_sap_channel); + } + hdd_ap_ctx->sapConfig.ch_params.ch_width = + hdd_ap_ctx->sapConfig.ch_width_orig; + sme_set_ch_params(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.ch_params); + /* + * Create a workqueue and let the workqueue handle the restart + * of 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(&hdd_ctx->sap_start_work, + cds_sap_restart_handle); +#else + INIT_WORK(&hdd_ctx->sap_start_work, + cds_sap_restart_handle); +#endif + schedule_work(&hdd_ctx->sap_start_work); + return CDF_STATUS_SUCCESS; +} + +/** + * cds_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 cds_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; + CDF_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); + if (CDF_STATUS_SUCCESS != status) { + cds_err("wlan_hdd_check_custom_con_channel_rules failed!"); + /* Not returning */ + } + status = sme_scan_result_purge( + WLAN_HDD_GET_HAL_CTX(sta_adapter), + scan_cache); + if (CDF_STATUS_SUCCESS != status) { + cds_err("sme_scan_result_purge failed!"); + /* Not returning */ + } + /* + * 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) { + cds_info("Stop AP due to mismatch with STA channel"); + wlan_hdd_stop_sap(ap_adapter); + cds_change_sap_restart_required_status(hdd_ctx, true); + return false; + } else { + cds_info("sap channels are same"); + } + } + return true; +} + +#ifdef FEATURE_WLAN_CH_AVOID +/** + * cds_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 cds_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; + CDF_STATUS status; + bool ret; + + 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); + if (CDF_STATUS_SUCCESS != status) { + cds_err("wlan_hdd_check_custom_con_channel_rules failed"); + /* Not returning */ + } + /* + * 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 == cds_is_sta_connection_pending(hdd_ctx)) { + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CLEAR_JOIN_REQ, + sta_adapter->sessionId, *roam_id)); + ret = sme_clear_joinreq_param( + WLAN_HDD_GET_HAL_CTX(sta_adapter), + sta_adapter->sessionId); + if (true != ret) { + cds_err("sme_clear_joinreq_param failed"); + /* Not returning */ + } + cds_change_sta_conn_pending_status(hdd_ctx, + false); + cds_info("===>Clear pending join req"); + } + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_STORE_JOIN_REQ, + sta_adapter->sessionId, *roam_id)); + /* store the scan cache here */ + ret = sme_store_joinreq_param( + WLAN_HDD_GET_HAL_CTX(sta_adapter), + roam_profile, + scan_cache, + roam_id, + sta_adapter->sessionId); + if (true != ret) { + cds_err("sme_store_joinreq_param failed"); + /* Not returning */ + } + cds_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 <= 14) { + freq = ieee80211_channel_to_frequency( + p2pgo_channel_num, + IEEE80211_BAND_2GHZ); + } else { + freq = ieee80211_channel_to_frequency( + p2pgo_channel_num, + IEEE80211_BAND_5GHZ); + } + cdf_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); + cds_info("===>Sending chnl_avoid ch[%d] freq[%d]", + p2pgo_channel_num, freq); + cds_info("=>Stop GO due to mismatch with STA channel"); + return false; + } else { + cds_info("===>p2pgo channels are same"); + status = sme_scan_result_purge( + WLAN_HDD_GET_HAL_CTX(sta_adapter), + scan_cache); + if (CDF_STATUS_SUCCESS != status) { + cds_err("sme_scan_result_purge failed"); + /* Not returning */ + } + } + } + return true; +} +#endif + +/** + * cds_handle_conc_rule1() - Check if concurrency rule1 is enabled + * @hdd_ctx: HDD context + * @adapter: HDD adpater + * @roam_profile: Profile for connection + * + * Check if concurrency rule1 is enabled. As per rule1, 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 + * + * Return: None + */ +void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile) +{ + bool ret; + + /* + * 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 (hdd_ctx->config->conc_custom_rule1 && + (WLAN_HDD_INFRA_STATION == adapter->device_mode)) { + ret = cds_sta_sap_concur_handle(hdd_ctx, adapter, + roam_profile); + if (true != ret) { + cds_err("cds_sta_sap_concur_handle failed"); + /* Nothing to do for now */ + } + } +} + +#ifdef FEATURE_WLAN_CH_AVOID +/** + * cds_handle_conc_rule2() - Check if concurrency rule2 is enabled + * @hdd_ctx: HDD context + * @adapter: HDD adpater + * @roam_profile: Profile for connection + * + * Check if concurrency rule1 is enabled. As per rule1, 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 + * + * Return: None + */ +bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile, + uint32_t *roam_id) +{ + /* + * 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 (hdd_ctx->config->conc_custom_rule2 && + (WLAN_HDD_INFRA_STATION == adapter->device_mode)) { + if (false == cds_sta_p2pgo_concur_handle(hdd_ctx, + adapter, roam_profile, roam_id)) { + cds_err("P2PGO-STA chnl diff, cache join req"); + return false; + } + } + return true; +} +#endif + +/** + * cds_get_channel_from_scan_result() - to get channel from scan result + * @adapter: station adapter + * @roam_profile: pointer to roam profile + * @channel: channel to be filled + * + * This routine gets channel which most likely a candidate to which STA + * will make connection. + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, + tCsrRoamProfile *roam_profile, uint8_t *channel) +{ + CDF_STATUS status; + tScanResultHandle scan_cache = NULL; + + status = sme_get_ap_channel_from_scan_cache( + WLAN_HDD_GET_HAL_CTX(adapter), + roam_profile, &scan_cache, + channel); + sme_scan_result_purge(WLAN_HDD_GET_HAL_CTX(adapter), scan_cache); + return status; +} + +/** + * cds_handle_conc_multiport() - to handle multiport concurrency + * @session_id: Session ID + * @channel: Channel number + * + * This routine will handle STA side concurrency when policy manager + * is enabled. + * + * Return: true or false + */ +bool cds_handle_conc_multiport(uint8_t session_id, + uint8_t channel) +{ + bool ret = true; + CDF_STATUS status; + p_cds_contextType cds_context; + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return false; + } + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return false; + } + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id); + if (!adapter) { + cds_err("Invalid HDD adapter"); + return false; + } + + if (channel == 0) { + cds_err("Invalid channel number 0"); + return false; + } + /* Take care of 160MHz and 80+80Mhz later */ + ret = cds_allow_concurrency(hdd_ctx, + cds_convert_device_mode_to_hdd_type( + adapter->device_mode), + channel, HW_MODE_20_MHZ); + if (false == ret) { + cds_err("Connection failed due to conc check fail"); + return false; + } + + status = cdf_event_reset(&cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(status)) + cds_err("clearing event failed"); + + status = cds_current_connections_update(hdd_ctx, channel); + if (CDF_STATUS_E_FAILURE == status) { + cds_err("connections update failed"); + return false; + } + /* + * wait only if status is successful. connection update API + * will return success only in case if DBS update is required. + */ + if (CDF_STATUS_SUCCESS == status) { + status = cdf_wait_single_event( + &cds_context->connection_update_done_evt, 500); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("wait for event failed"); + return false; + } + } + return true; +} + +#ifdef FEATURE_WLAN_FORCE_SAP_SCC +/** + * cds_restart_softap() - restart SAP on STA channel to support + * STA + SAP concurrency. + * + * @hdd_ctx: pointer to hdd context + * @pHostapdAdapter: pointer to hdd adapter + * + * Return: None + */ +void cds_restart_softap(hdd_context_t *hdd_ctx, + hdd_adapter_t *pHostapdAdapter) +{ + tHddAvoidFreqList hdd_avoid_freq_list; + + /* generate vendor specific event */ + cdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); + hdd_avoid_freq_list.avoidFreqRange[0].startFreq = + cds_chan_to_freq(pHostapdAdapter->sessionCtx.ap. + operatingChannel); + hdd_avoid_freq_list.avoidFreqRange[0].endFreq = + cds_chan_to_freq(pHostapdAdapter->sessionCtx.ap. + operatingChannel); + hdd_avoid_freq_list.avoidFreqRangeCount = 1; + wlan_hdd_send_avoid_freq_event(hdd_ctx, &hdd_avoid_freq_list); +} + +/** + * cds_force_sap_on_scc() - Force SAP on SCC + * @hdd_ctx: Pointer to HDD context + * @roam_result: Roam result + * + * Restarts SAP on SCC if its operating channel is different from that of the + * STA-AP interface + * + * Return: None + */ +void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result) +{ + hdd_adapter_t *hostapd_adapter; + + if (!(eCSR_ROAM_RESULT_ASSOCIATED == roam_result && + hdd_ctx->config->SapSccChanAvoidance)) { + cds_err("Not able to force SAP on SCC"); + return; + } + hostapd_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (hostapd_adapter != NULL) { + /* Restart SAP if its operating channel is different + * from AP channel. + */ + if (hostapd_adapter->sessionCtx.ap.operatingChannel != + pRoamInfo->pBssDesc->channelId) { + cds_err("Restart SAP: SAP channel-%d, STA channel-%d", + hostapd_adapter->sessionCtx.ap.operatingChannel, + pRoamInfo->pBssDesc->channelId); + cds_restart_softap(hdd_ctx, hostapd_adapter); + } + } +} +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + +/** + * cds_check_sta_ap_concurrent_ch_intf() - Restart SAP in STA-AP case + * @data: Pointer to STA adapter + * + * Restarts the SAP interface in STA-AP concurrency scenario + * + * Restart: None + */ +static void cds_check_sta_ap_concurrent_ch_intf(void *data) +{ + hdd_adapter_t *ap_adapter = NULL, *sta_adapter = (hdd_adapter_t *) data; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(sta_adapter); + tHalHandle *hal_handle; + hdd_ap_ctx_t *hdd_ap_ctx; + uint16_t intf_ch = 0; + + if ((hdd_ctx->config->WlanMccToSccSwitchMode == + CDF_MCC_TO_SCC_SWITCH_DISABLE) + || !(cds_concurrent_open_sessions_running() + || !(cds_get_concurrency_mode() == + (CDF_STA_MASK | CDF_SAP_MASK)))) + return; + + ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (ap_adapter == NULL) + return; + + if (!test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) + return; + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + hal_handle = WLAN_HDD_GET_HAL_CTX(ap_adapter); + + if (hal_handle == NULL) + return; + +#ifdef WLAN_FEATURE_MBSSID + intf_ch = wlansap_check_cc_intf(hdd_ap_ctx->sapContext); +#else + intf_ch = wlansap_check_cc_intf(hdd_ctx->pcds_context); +#endif + if (intf_ch == 0) + return; + + hdd_ap_ctx->sapConfig.channel = intf_ch; + hdd_ap_ctx->sapConfig.ch_params.ch_width = + hdd_ap_ctx->sapConfig.ch_width_orig; + sme_set_ch_params(hal_handle, + hdd_ap_ctx->sapConfig.SapHw_mode, + hdd_ap_ctx->sapConfig.channel, + hdd_ap_ctx->sapConfig.sec_ch, + &hdd_ap_ctx->sapConfig.ch_params); + cds_restart_sap(ap_adapter); +} +/** + * cds_check_concurrent_intf_and_restart_sap() - Check concurrent change intf + * @hdd_ctx: Pointer to HDD context + * @hdd_sta_ctx: Pointer to HDD STA context + * + * Checks the concurrent change interface and restarts SAP + * Return: None + */ +void cds_check_concurrent_intf_and_restart_sap(hdd_context_t *hdd_ctx, + hdd_station_ctx_t *hdd_sta_ctx, hdd_adapter_t *adapter) +{ + if ((hdd_ctx->config->WlanMccToSccSwitchMode + != CDF_MCC_TO_SCC_SWITCH_DISABLE) && + ((0 == hdd_ctx->config->conc_custom_rule1) && + (0 == hdd_ctx->config->conc_custom_rule2)) +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + && !CDS_IS_DFS_CH(hdd_sta_ctx->conn_info. + operationChannel) +#endif + ) { + cdf_create_work(0, &hdd_ctx->sta_ap_intf_check_work, + cds_check_sta_ap_concurrent_ch_intf, + (void *)adapter); + cdf_sched_work(0, &hdd_ctx->sta_ap_intf_check_work); + cds_info("Checking for Concurrent Change interference"); + } +} +#endif /* FEATURE_WLAN_MCC_TO_SCC_SWITCH */ + +/** + * cds_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 cds_is_mcc_in_24G(hdd_context_t *hdd_ctx) +{ + CDF_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 && CDF_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; + } + 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->cdf_status == + CDF_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))) { + cds_err("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; +} + +/** + * cds_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 cds_set_mas(hdd_adapter_t *adapter, uint8_t mas_value) +{ + hdd_context_t *hdd_ctx = NULL; + CDF_STATUS 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->config->enableMCCAdaptiveScheduler) { + if (cfg_set_int(hdd_ctx->hHal, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, 0) + != eSIR_SUCCESS) { + cds_err("Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM"); + } + ret_status = sme_set_mas(false); + if (CDF_STATUS_SUCCESS != ret_status) { + cds_err("Failed to disable MAS"); + return -EBUSY; + } + } + + /* Config p2p quota */ + if (adapter->device_mode == WLAN_HDD_INFRA_STATION) + cds_set_mcc_p2p_quota(adapter, + 100 - HDD_DEFAULT_MCC_P2P_QUOTA); + else if (adapter->device_mode == WLAN_HDD_P2P_GO) + cds_go_set_mcc_p2p_quota(adapter, + HDD_DEFAULT_MCC_P2P_QUOTA); + else + cds_set_mcc_p2p_quota(adapter, + HDD_DEFAULT_MCC_P2P_QUOTA); + } else { + /* Reset p2p quota */ + if (adapter->device_mode == WLAN_HDD_P2P_GO) + cds_go_set_mcc_p2p_quota(adapter, + HDD_RESET_MCC_P2P_QUOTA); + else + cds_set_mcc_p2p_quota(adapter, + HDD_RESET_MCC_P2P_QUOTA); + + /* Miracast is OFF. Enable MAS and reset P2P quota */ + if (hdd_ctx->config->enableMCCAdaptiveScheduler) { + if (cfg_set_int(hdd_ctx->hHal, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, 1) + != eSIR_SUCCESS) { + cds_err("Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CCM"); + } + + /* Enable MAS */ + ret_status = sme_set_mas(true); + if (CDF_STATUS_SUCCESS != ret_status) { + cds_err("Unable to enable MAS"); + return -EBUSY; + } + } + } + + return 0; +} + +/** + * cds_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 cds_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 *sta_adapter = NULL; + int32_t ret = 0; /* success */ + + uint32_t concurrent_state = cds_get_concurrency_mode(); + + /* + * Check if concurrency mode is active. + * Need to modify this code to support MCC modes other than STA/P2P + */ + if ((concurrent_state == (CDF_STA_MASK | CDF_P2P_CLIENT_MASK)) || + (concurrent_state == (CDF_STA_MASK | CDF_P2P_GO_MASK))) { + cds_info("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 + ); + cds_info("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 & CDF_P2P_CLIENT_MASK) != 0) { + /* The 2nd MCC vdev is P2P client */ + sta_adapter = hdd_get_adapter( + hostapd_adapater->pHddCtx, + WLAN_HDD_P2P_CLIENT); + } else { + /* The 2nd MCC vdev is P2P GO */ + sta_adapter = hdd_get_adapter( + hostapd_adapater->pHddCtx, + WLAN_HDD_P2P_GO); + } + } else { + /* + * iwpriv cmd was issued on p2p0; + * get wlan0 vdev channel + */ + sta_adapter = hdd_get_adapter(hostapd_adapater->pHddCtx, + WLAN_HDD_INFRA_STATION); + } + if (sta_adapter != NULL) { + second_adapter_opertaing_channel = + hdd_get_operating_channel + ( + sta_adapter->pHddCtx, + sta_adapter->device_mode + ); + cds_info("2nd vdev channel No. is:%d", + second_adapter_opertaing_channel); + + if (second_adapter_opertaing_channel == 0 || + first_adapter_operating_channel == 0) { + cds_err("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 = wma_cli_set_command(hostapd_adapater->sessionId, + WMA_VDEV_MCC_SET_TIME_QUOTA, + set_value, VDEV_CMD); + } else { + cds_err("NULL adapter handle. Exit"); + } + } else { + cds_info("MCC is not active. Exit w/o setting latency"); + } + return ret; +} + +/** + * cds_change_mcc_go_beacon_interval() - Change MCC beacon interval + * @pHostapdAdapter: HDD adapter + * + * Updates the beacon parameters of the GO in MCC scenario + * + * Return: Success or Failure depending on the overall function behavior + */ +CDF_STATUS cds_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal; + + cds_info("UPDATE Beacon Params"); + + if (CDF_SAP_MODE == cds_get_conparam()) { + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if (NULL == hHal) { + cds_err("Hal ctx is null"); + return CDF_STATUS_E_FAULT; + } + cdf_ret_status = + sme_change_mcc_beacon_interval(hHal, + pHostapdAdapter-> + sessionId); + if (cdf_ret_status == CDF_STATUS_E_FAILURE) { + cds_err("Failed to update Beacon Params"); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} + +/** + * cds_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 cds_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; + uint32_t concurrent_state = 0; + hdd_adapter_t *sta_adapter = 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 = cds_get_concurrency_mode(); + if (concurrent_state == (CDF_STA_MASK | CDF_P2P_GO_MASK)) { + cds_info("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_adapter->pHddCtx, + hostapd_adapter->device_mode); + + cds_info("1st channel No.:%d and quota:%dms", + 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 & CDF_P2P_CLIENT_MASK) != 0) { + /* The 2nd MCC vdev is P2P client */ + sta_adapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_P2P_CLIENT + ); + } else { + /* The 2nd MCC vdev is P2P GO */ + sta_adapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_P2P_GO + ); + } + } else { + /* iwpriv cmd issued on p2p0; get channel for wlan0 */ + sta_adapter = hdd_get_adapter + ( + hostapd_adapter->pHddCtx, + WLAN_HDD_INFRA_STATION + ); + } + if (sta_adapter != NULL) { + second_adapter_opertaing_channel = + hdd_get_operating_channel + ( + sta_adapter->pHddCtx, + sta_adapter->device_mode + ); + cds_info("2nd vdev channel No. is:%d", + second_adapter_opertaing_channel); + + if (second_adapter_opertaing_channel == 0 || + first_adapter_operating_channel == 0) { + cds_err("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 = wma_cli_set_command(hostapd_adapter->sessionId, + WMA_VDEV_MCC_SET_TIME_QUOTA, + set_value, VDEV_CMD); + } else { + cds_err("NULL adapter handle. Exit"); + } + } else { + cds_info("MCC is not active. Exit w/o setting latency"); + } + return ret; +} + +/** + * cds_set_mcc_latency() - Set MCC latency + * @adapter: Pointer to HDD adapter + * @set_value: Latency value + * + * Sets the MCC latency value during STA-P2P concurrency + * + * Return: None + */ +void cds_set_mcc_latency(hdd_adapter_t *adapter, int set_value) +{ + uint32_t concurrent_state = 0; + uint8_t first_adapter_operating_channel = 0; + int ret = 0; /* success */ + + cds_info("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 = cds_get_concurrency_mode(); + if ((concurrent_state == (CDF_STA_MASK | CDF_P2P_CLIENT_MASK)) || + (concurrent_state == (CDF_STA_MASK | CDF_P2P_GO_MASK))) { + cds_info("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 + (adapter->pHddCtx, adapter->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 = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_MCC_SET_TIME_LATENCY, + set_value, VDEV_CMD); + } else { + cds_info("%s: MCC is not active. Exit w/o setting latency", + __func__); + } +} + +#if defined(FEATURE_WLAN_MCC_TO_SCC_SWITCH) || \ + defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) +/** + * cds_restart_sap() - This function is used to restart SAP in + * driver internally + * + * @ap_adapter: Pointer to SAP hdd_adapter_t structure + * + * Return: None + */ +void cds_restart_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); +#ifdef CFG80211_DEL_STA_V2 + struct tagCsrDelStaParams delStaParams; +#endif + tsap_Config_t *sap_config; + + hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); + sap_config = &ap_adapter->sessionCtx.ap.sapConfig; + + 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); + cdf_event_reset(&hostapd_state->cdf_stop_bss_event); + if (CDF_STATUS_SUCCESS == wlansap_stop_bss( +#ifdef WLAN_FEATURE_MBSSID + hdd_ap_ctx->sapContext +#else + hdd_ctx->pcds_context +#endif + )) { + cdf_status = + cdf_wait_single_event(&hostapd_state-> + cdf_stop_bss_event, + BSS_WAIT_TIMEOUT); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cds_err("SAP Stop Failed"); + goto end; + } + } + clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + cds_decr_session_set_pcl(hdd_ctx, + ap_adapter->device_mode, ap_adapter->sessionId); + cds_err("SAP Stop Success"); + + if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) { + cds_err("SAP Not able to set AP IEs"); + wlansap_reset_sap_config_add_ie(sap_config, + eUPDATE_IE_ALL); + goto end; + } + + if (wlansap_start_bss( +#ifdef WLAN_FEATURE_MBSSID + hdd_ap_ctx->sapContext, +#else + hdd_ctx->pcds_context, +#endif + hdd_hostapd_sap_event_cb, + &hdd_ap_ctx->sapConfig, + ap_adapter->dev) != + CDF_STATUS_SUCCESS) { + cds_err("SAP Start Bss fail"); + goto end; + } + + cds_info("Waiting for SAP to start"); + cdf_status = + cdf_wait_single_event(&hostapd_state->cdf_event, + BSS_WAIT_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cds_err("SAP Start failed"); + goto end; + } + cds_err("SAP Start Success"); + set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, + ap_adapter->sessionId); + hostapd_state->bCommit = true; + } +end: + mutex_unlock(&hdd_ctx->sap_lock); + return; +} +#endif + +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE +/** + * cds_check_and_restart_sap_with_non_dfs_acs() - Restart SAP with non dfs acs + * @hdd_ctx: HDD context + * + * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported + * + * Return: None + */ +void cds_check_and_restart_sap_with_non_dfs_acs(hdd_context_t *hdd_ctx) +{ + hdd_adapter_t *ap_adapter; + + if (cds_get_concurrency_mode() != (CDF_STA_MASK | CDF_SAP_MASK)) { + cds_info("Concurrency mode is not SAP"); + return; + } + + ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (ap_adapter != NULL && + test_bit(SOFTAP_BSS_STARTED, + &ap_adapter->event_flags) + && CDS_IS_DFS_CH(ap_adapter->sessionCtx.ap. + operatingChannel)) { + + cds_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; + + cds_restart_sap(ap_adapter); + } +} +#endif +#ifdef MPC_UT_FRAMEWORK +CDF_STATUS cds_update_connection_info_utfw(hdd_context_t *hdd_ctx, + uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t conn_index = 0, found = 0; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_id == conc_connection_list[conn_index].vdev_id) { + /* debug msg */ + found = 1; + break; + } + conn_index++; + } + if (!found) { + /* err msg */ + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cds_err("can't find vdev_id %d in conc_connection_list", + vdev_id); + return status; + } + cds_info("--> updating entry at index[%d]", conn_index); + + cds_update_conc_list(conn_index, + cds_get_mode(type, sub_type), + channelid, mac_id, chain_mask, tx_streams, + rx_streams, 0, vdev_id, true); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, + uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, + uint32_t chain_mask, uint32_t type, uint32_t sub_type, + uint32_t channelid, uint32_t mac_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t conn_index = 0; + + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + conn_index = cds_get_connection_count(hdd_ctx); + if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { + /* err msg */ + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cds_err("exceeded max connection limit %d", + MAX_NUMBER_OF_CONC_CONNECTIONS); + return status; + } + cds_info("--> filling entry at index[%d]", conn_index); + + cds_update_conc_list(conn_index, + cds_get_mode(type, sub_type), + channelid, mac_id, chain_mask, tx_streams, + rx_streams, 0, vdev_id, true); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS cds_decr_connection_count_utfw(hdd_context_t *hdd_ctx, + uint32_t del_all, uint32_t vdev_id) +{ + CDF_STATUS status; + + if (del_all) { + status = cds_init_policy_mgr(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("Policy manager initialization failed"); + return CDF_STATUS_E_FAILURE; + } + } else { + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cds_decr_connection_count(hdd_ctx, vdev_id); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + } + + return CDF_STATUS_SUCCESS; +} + +struct cds_conc_connection_info *cds_get_conn_info(hdd_context_t *hdd_ctx, + uint32_t *len) +{ + struct cds_conc_connection_info *conn_ptr = &conc_connection_list[0]; + *len = MAX_NUMBER_OF_CONC_CONNECTIONS; + + return conn_ptr; +} + +enum cds_pcl_type get_pcl_from_first_conn_table( + enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref) +{ + if ((sys_pref >= CDS_MAX_CONC_PRIORITY_MODE) || + (type >= CDS_MAX_NUM_OF_MODE)) + return CDS_MAX_PCL_TYPE; + return first_connection_pcl_table[type][sys_pref]; +} + +enum cds_pcl_type get_pcl_from_second_conn_table( + enum cds_one_connection_mode idx, enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref, uint8_t dbs_capable) +{ + if ((idx >= CDS_MAX_ONE_CONNECTION_MODE) || + (sys_pref >= CDS_MAX_CONC_PRIORITY_MODE) || + (type >= CDS_MAX_NUM_OF_MODE)) + return CDS_MAX_PCL_TYPE; + if (dbs_capable) + return second_connection_pcl_dbs_table[idx][type][sys_pref]; + else + return second_connection_pcl_nodbs_table[idx][type][sys_pref]; +} + +enum cds_pcl_type get_pcl_from_third_conn_table( + enum cds_two_connection_mode idx, enum cds_con_mode type, + enum cds_conc_priority_mode sys_pref, uint8_t dbs_capable) +{ + if ((idx >= CDS_MAX_TWO_CONNECTION_MODE) || + (sys_pref >= CDS_MAX_CONC_PRIORITY_MODE) || + (type >= CDS_MAX_NUM_OF_MODE)) + return CDS_MAX_PCL_TYPE; + if (dbs_capable) + return third_connection_pcl_dbs_table[idx][type][sys_pref]; + else + return third_connection_pcl_nodbs_table[idx][type][sys_pref]; +} +#endif + +/** + * cds_convert_device_mode_to_hdd_type() - provides the + * type translation from HDD to policy manager type + * @device_mode: Generic connection mode type + * + * + * This function provides the type translation + * + * Return: cds_con_mode enum + */ +enum cds_con_mode cds_convert_device_mode_to_hdd_type( + device_mode_t device_mode) +{ + enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE; + switch (device_mode) { + case WLAN_HDD_INFRA_STATION: + mode = CDS_STA_MODE; + break; + case WLAN_HDD_P2P_CLIENT: + mode = CDS_P2P_CLIENT_MODE; + break; + case WLAN_HDD_P2P_GO: + mode = CDS_P2P_GO_MODE; + break; + case WLAN_HDD_SOFTAP: + mode = CDS_SAP_MODE; + break; + case WLAN_HDD_IBSS: + mode = CDS_IBSS_MODE; + break; + default: + cds_err("Unsupported mode (%d)", + device_mode); + } + return mode; +} diff --git a/core/cds/src/cds_get_bin.c b/core/cds/src/cds_get_bin.c new file mode 100644 index 000000000000..ac87dd5db866 --- /dev/null +++ b/core/cds/src/cds_get_bin.c @@ -0,0 +1,166 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +tCDF_CON_MODE cds_get_conparam(void) +{ + tCDF_CON_MODE con_mode; + con_mode = hdd_get_conparam(); + return con_mode; +} + +bool cds_concurrent_open_sessions_running(void) +{ + uint8_t i = 0; + uint8_t j = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) { + j += pHddCtx->no_of_open_sessions[i]; + } + } + + return j > 1; +} + +#ifdef WLAN_FEATURE_MBSSID +bool cds_concurrent_beaconing_sessions_running(void) +{ + uint8_t i = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + i = pHddCtx->no_of_open_sessions[CDF_SAP_MODE] + + pHddCtx->no_of_open_sessions[CDF_P2P_GO_MODE] + + pHddCtx->no_of_open_sessions[CDF_IBSS_MODE]; + } + return i > 1; +} +#endif + +/**--------------------------------------------------------------------------- +* +* \brief cds_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 - true or false +* +* --------------------------------------------------------------------------*/ +bool cds_max_concurrent_connections_reached(void) +{ + uint8_t i = 0, j = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) + j += pHddCtx->no_of_active_sessions[i]; + return j > + (pHddCtx->config-> + gMaxConcurrentActiveSessions - 1); + } + + return false; +} + +void cds_clear_concurrent_session_count(void) +{ + uint8_t i = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) + pHddCtx->no_of_active_sessions[i] = 0; + } +} + +/**--------------------------------------------------------------------------- +* +* \brief cds_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 +* +* --------------------------------------------------------------------------*/ +bool cds_is_multiple_active_sta_sessions(void) +{ + hdd_context_t *pHddCtx; + uint8_t j = 0; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) + j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; + + return j > 1; +} + +/**--------------------------------------------------------------------------- +* +* \brief cds_is_sta_active_connection_exists() +* +* This function checks for the presence of active sta connection +* and it returns true if exists. +* +* \param - None +* +* \return - true or false +* +* --------------------------------------------------------------------------*/ +bool cds_is_sta_active_connection_exists(void) +{ + hdd_context_t *pHddCtx; + uint8_t j = 0; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) + j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; + + return j ? true : false; +} diff --git a/core/cds/src/cds_ieee80211_common_i.h b/core/cds/src/cds_ieee80211_common_i.h new file mode 100644 index 000000000000..166c8e6ff737 --- /dev/null +++ b/core/cds/src/cds_ieee80211_common_i.h @@ -0,0 +1,545 @@ +/* + * 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 CDS_COMMON__IEEE80211_I_H_ +#define CDS_COMMON__IEEE80211_I_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; + uint32_t series; + uint32_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 { + uint8_t rs_nrates; + uint8_t rs_rates[IEEE80211_RATE_MAXSIZE]; +}; + +struct ieee80211_beacon_info { + uint8_t essid[IEEE80211_NWID_LEN + 1]; + uint8_t esslen; + uint8_t rssi_ctl_0; + uint8_t rssi_ctl_1; + uint8_t rssi_ctl_2; + int numchains; +}; + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ + +struct ieee80211_ibss_peer_list { + uint8_t bssid[IEEE80211_ADDR_LEN]; +}; + +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 */ + uint8_t pad1; + uint8_t rate11a; /* rate thresh for 11a bss */ + uint8_t rate11b; /* for 11g sta in 11b bss */ + uint8_t rate11bOnly; /* for 11b sta */ + uint8_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 */ + +/* 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 { + uint32_t tx_frame_count; + uint32_t rx_frame_count; + uint32_t rx_clear_count; + uint32_t cycle_count; + uint8_t is_rx_active; + uint8_t is_tx_active; +}; + +struct ieee80211_chanutil_info { + uint32_t rx_clear_count; + uint32_t cycle_count; + uint8_t value; + uint32_t beacon_count; + uint8_t beacon_intervals; +}; + +#endif /* CDS_COMMON__IEEE80211_I_H_ */ diff --git a/core/cds/src/cds_mq.c b/core/cds/src/cds_mq.c new file mode 100644 index 000000000000..6354e04dc922 --- /dev/null +++ b/core/cds/src/cds_mq.c @@ -0,0 +1,215 @@ +/* + * 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. + */ + +/** + * DOC: cds_mq.c + * + * Connectivity driver services (CDS) message queue APIs + * + * Message Queue Definitions and API + */ + +/* Include Files */ +#include +#include "cds_sched.h" +#include +#include "sir_types.h" + +/* Preprocessor definitions and constants */ + +/* Type declarations */ + +/* Function declarations and documenation */ + +tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, void *pMb); + +/** + * cds_mq_init() - initialize cds message queue + * @pMq: Pointer to the message queue + * + * This function initializes the Message queue. + * + * Return: cdf status + */ +inline CDF_STATUS cds_mq_init(p_cds_mq_type pMq) +{ + + if (pMq == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed", __func__); + return CDF_STATUS_E_FAILURE; + } + + /* Now initialize the lock */ + spin_lock_init(&pMq->mqLock); + + /* Now initialize the List data structure */ + INIT_LIST_HEAD(&pMq->mqList); + + return CDF_STATUS_SUCCESS; +} /* cds_mq_init() */ + +/** + * cds_mq_deinit() - de-initialize cds message queue + * @pMq: Pointer to the message queue + * + * This function de-initializes cds message queue + * + * Return: none + */ +inline void cds_mq_deinit(p_cds_mq_type pMq) +{ + if (pMq == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed", __func__); + return; + } + + /* we don't have to do anything with the embedded list or spinlock */ +} /* cds_mq_deinit() */ + +/** + * cds_mq_put() - add a message to the message queue + * @pMq: Pointer to the message queue + * @pMsgWrapper: Msg wrapper containing the message + * + * Return: none + */ +inline void cds_mq_put(p_cds_mq_type pMq, p_cds_msg_wrapper pMsgWrapper) +{ + unsigned long flags; + + if ((pMq == NULL) || (pMsgWrapper == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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); + +} /* cds_mq_put() */ + +/** + * cds_mq_get() - get a message with its wrapper from a message queue + * @pMq: Pointer to the message queue + * + * Return: pointer to the message wrapper + */ +inline p_cds_msg_wrapper cds_mq_get(p_cds_mq_type pMq) +{ + p_cds_msg_wrapper pMsgWrapper = NULL; + + struct list_head *listptr; + unsigned long flags; + + if (pMq == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed", __func__); + return NULL; + } + + spin_lock_irqsave(&pMq->mqLock, flags); + + if (list_empty(&pMq->mqList)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_WARN, + "%s: CDS Message Queue is empty", __func__); + } else { + listptr = pMq->mqList.next; + pMsgWrapper = + (p_cds_msg_wrapper) list_entry(listptr, cds_msg_wrapper, + msgNode); + list_del(pMq->mqList.next); + } + + spin_unlock_irqrestore(&pMq->mqLock, flags); + + return pMsgWrapper; + +} /* cds_mq_get() */ + +/** + * cds_is_mq_empty() - check if the message queue is empty + * @pMq: Pointer to the message queue + * + * Return: true if message queue is emtpy + * false otherwise + */ +inline bool cds_is_mq_empty(p_cds_mq_type pMq) +{ + bool state = false; + unsigned long flags; + + if (pMq == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer passed", __func__); + return CDF_STATUS_E_FAILURE; + } + + spin_lock_irqsave(&pMq->mqLock, flags); + state = list_empty(&pMq->mqList) ? true : false; + spin_unlock_irqrestore(&pMq->mqLock, flags); + + return state; +} /* cds_mq_get() */ + +/** + * cds_send_mb_message_to_mac() - post a message to a message queue + * @pBuf: Pointer to buffer allocated by caller + * + * Return: cdf status + */ +CDF_STATUS cds_send_mb_message_to_mac(void *pBuf) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + tSirRetStatus sirStatus; + v_CONTEXT_t cds_context; + void *hHal; + + cds_context = cds_get_global_context(); + if (NULL == cds_context) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "%s: invalid cds_context", __func__); + } else { + hHal = cds_get_context(CDF_MODULE_ID_SME); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "%s: invalid hHal", __func__); + } else { + sirStatus = u_mac_post_ctrl_msg(hHal, pBuf); + if (eSIR_SUCCESS == sirStatus) + cdf_ret_status = CDF_STATUS_SUCCESS; + } + } + + cdf_mem_free(pBuf); + + return cdf_ret_status; +} diff --git a/core/cds/src/cds_packet.c b/core/cds/src/cds_packet.c new file mode 100644 index 000000000000..70e5fc10732a --- /dev/null +++ b/core/cds/src/cds_packet.c @@ -0,0 +1,348 @@ +/* + * 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 cds_packet.c + + \brief Connectivity driver services (CDS) network Packet APIs + + Network Protocol packet/buffer support interfaces + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "cdf_nbuf.h" +#include "cdf_memory.h" + +#define TX_PKT_MIN_HEADROOM (64) + +/* Protocol specific packet tracking feature */ +#define CDS_PKT_TRAC_ETH_TYPE_OFFSET (12) +#define CDS_PKT_TRAC_IP_OFFSET (14) +#define CDS_PKT_TRAC_IP_HEADER_SIZE (20) +#define CDS_PKT_TRAC_DHCP_SRV_PORT (67) +#define CDS_PKT_TRAC_DHCP_CLI_PORT (68) +#define CDS_PKT_TRAC_EAPOL_ETH_TYPE (0x888E) +#ifdef QCA_PKT_PROTO_TRACE +#define CDS_PKT_TRAC_MAX_STRING_LEN (12) +#define CDS_PKT_TRAC_MAX_TRACE_BUF (50) +#define CDS_PKT_TRAC_MAX_STRING_BUF (64) + +/* protocol Storage Structure */ +typedef struct { + uint32_t order; + v_TIME_t event_time; + char event_string[CDS_PKT_TRAC_MAX_STRING_LEN]; +} cds_pkt_proto_trace_t; + +cds_pkt_proto_trace_t *trace_buffer = NULL; +unsigned int trace_buffer_order = 0; +cdf_spinlock_t trace_buffer_lock; +#endif /* QCA_PKT_PROTO_TRACE */ + +/** + * cds_pkt_return_packet Free the cds Packet + * @ cds Packet + */ +CDF_STATUS cds_pkt_return_packet(cds_pkt_t *packet) +{ + /* Validate the input parameter pointer */ + if (unlikely(packet == NULL)) { + return CDF_STATUS_E_INVAL; + } + + /* Free up the Adf nbuf */ + cdf_nbuf_free(packet->pkt_buf); + + packet->pkt_buf = NULL; + + /* Free up the Rx packet */ + cdf_mem_free(packet); + + return CDF_STATUS_SUCCESS; +} + +/**-------------------------------------------------------------------------- + + \brief cds_pkt_get_packet_length() - Get packet length for a cds Packet + + This API returns the total length of the data in a cds Packet. + + \param pPacket - the cds Packet to get the packet length from. + + \param pPacketSize - location to return the total size of the data contained + in the cds Packet. + \return + + \sa + + ---------------------------------------------------------------------------*/ +CDF_STATUS +cds_pkt_get_packet_length(cds_pkt_t *pPacket, uint16_t *pPacketSize) +{ + /* Validate the parameter pointers */ + if (unlikely((pPacket == NULL) || (pPacketSize == NULL)) || + (pPacket->pkt_buf == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "VPKT [%d]: NULL pointer", __LINE__); + return CDF_STATUS_E_INVAL; + } + /* return the requested information */ + *pPacketSize = cdf_nbuf_len(pPacket->pkt_buf); + return CDF_STATUS_SUCCESS; +} + +/*--------------------------------------------------------------------------- +* @brief cds_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 + ---------------------------------------------------------------------------*/ +uint8_t cds_pkt_get_proto_type(struct sk_buff *skb, uint8_t tracking_map, + uint8_t dot11_type) +{ + uint8_t pkt_proto_type = 0; + uint16_t ether_type; + uint16_t SPort; + uint16_t DPort; + + if (dot11_type) { + if (dot11_type == + (CDS_PKT_TRAC_TYPE_MGMT_ACTION & tracking_map)) + pkt_proto_type |= CDS_PKT_TRAC_TYPE_MGMT_ACTION; + + /* Protocol type map */ + return pkt_proto_type; + } + + /* EAPOL Tracking enabled */ + if (CDS_PKT_TRAC_TYPE_EAPOL & tracking_map) { + ether_type = (uint16_t) (*(uint16_t *) + (skb->data + + CDS_PKT_TRAC_ETH_TYPE_OFFSET)); + if (CDS_PKT_TRAC_EAPOL_ETH_TYPE == CDF_SWAP_U16(ether_type)) { + pkt_proto_type |= CDS_PKT_TRAC_TYPE_EAPOL; + } + } + + /* DHCP Tracking enabled */ + if (CDS_PKT_TRAC_TYPE_DHCP & tracking_map) { + SPort = (uint16_t) (*(uint16_t *) + (skb->data + CDS_PKT_TRAC_IP_OFFSET + + CDS_PKT_TRAC_IP_HEADER_SIZE)); + DPort = (uint16_t) (*(uint16_t *) + (skb->data + CDS_PKT_TRAC_IP_OFFSET + + CDS_PKT_TRAC_IP_HEADER_SIZE + + sizeof(uint16_t))); + if (((CDS_PKT_TRAC_DHCP_SRV_PORT == CDF_SWAP_U16(SPort)) + && (CDS_PKT_TRAC_DHCP_CLI_PORT == CDF_SWAP_U16(DPort))) + || ((CDS_PKT_TRAC_DHCP_CLI_PORT == CDF_SWAP_U16(SPort)) + && (CDS_PKT_TRAC_DHCP_SRV_PORT == CDF_SWAP_U16(DPort)))) { + pkt_proto_type |= CDS_PKT_TRAC_TYPE_DHCP; + } + } + + /* Protocol type map */ + return pkt_proto_type; +} + +#ifdef QCA_PKT_PROTO_TRACE +/*--------------------------------------------------------------------------- +* @brief cds_pkt_trace_buf_update() - + Update storage buffer with interest event string + +* event_string Event String may packet type or outstanding event + ---------------------------------------------------------------------------*/ +void cds_pkt_trace_buf_update(char *event_string) +{ + uint32_t slot; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s %d, %s", __func__, __LINE__, event_string); + cdf_spinlock_acquire(&trace_buffer_lock); + slot = trace_buffer_order % CDS_PKT_TRAC_MAX_TRACE_BUF; + trace_buffer[slot].order = trace_buffer_order; + trace_buffer[slot].event_time = cdf_mc_timer_get_system_time(); + cdf_mem_zero(trace_buffer[slot].event_string, + sizeof(trace_buffer[slot].event_string)); + cdf_mem_copy(trace_buffer[slot].event_string, + event_string, + (CDS_PKT_TRAC_MAX_STRING_LEN < strlen(event_string)) ? + CDS_PKT_TRAC_MAX_STRING_LEN : strlen(event_string)); + trace_buffer_order++; + cdf_spinlock_release(&trace_buffer_lock); + + return; +} + +/*--------------------------------------------------------------------------- +* @brief cds_pkt_trace_buf_dump() - + Dump stored information into kernel log + ---------------------------------------------------------------------------*/ +void cds_pkt_trace_buf_dump(void) +{ + uint32_t slot, idx; + + cdf_spinlock_acquire(&trace_buffer_lock); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "PACKET TRACE DUMP START Current Timestamp %u", + (unsigned int)cdf_mc_timer_get_system_time()); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "ORDER : TIME : EVT"); + if (CDS_PKT_TRAC_MAX_TRACE_BUF > trace_buffer_order) { + for (slot = 0; slot < trace_buffer_order; slot++) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 < CDS_PKT_TRAC_MAX_TRACE_BUF; idx++) { + slot = + (trace_buffer_order + + idx) % CDS_PKT_TRAC_MAX_TRACE_BUF; + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%5d :%12u : %s", trace_buffer[slot].order, + (unsigned int)trace_buffer[slot].event_time, + trace_buffer[slot].event_string); + } + } + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "PACKET TRACE DUMP END"); + cdf_spinlock_release(&trace_buffer_lock); + + return; +} + +/*--------------------------------------------------------------------------- +* @brief cds_pkt_proto_trace_init() - + Initialize protocol trace functionality, allocate required resource + ---------------------------------------------------------------------------*/ +void cds_pkt_proto_trace_init(void) +{ + /* Init spin lock to protect global memory */ + cdf_spinlock_init(&trace_buffer_lock); + trace_buffer_order = 0; + trace_buffer = + cdf_mem_malloc(CDS_PKT_TRAC_MAX_TRACE_BUF * + sizeof(cds_pkt_proto_trace_t)); + cdf_mem_zero((void *)trace_buffer, + CDS_PKT_TRAC_MAX_TRACE_BUF * + sizeof(cds_pkt_proto_trace_t)); + + /* Register callback function to NBUF + * Lower layer event also will be reported to here */ + cdf_nbuf_reg_trace_cb(cds_pkt_trace_buf_update); + return; +} + +/*--------------------------------------------------------------------------- +* @brief cds_pkt_proto_trace_close() - + Free required resource + ---------------------------------------------------------------------------*/ +void cds_pkt_proto_trace_close(void) +{ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s %d", __func__, __LINE__); + cdf_mem_free(trace_buffer); + cdf_spinlock_destroy(&trace_buffer_lock); + + return; +} +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef MEMORY_DEBUG +/*--------------------------------------------------------------------------- +* @brief cds_packet_alloc_debug() - + Allocate a network buffer for TX + ---------------------------------------------------------------------------*/ +CDF_STATUS cds_packet_alloc_debug(uint16_t size, void **data, void **ppPacket, + uint8_t *file_name, uint32_t line_num) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + cdf_nbuf_t nbuf; + + nbuf = + cdf_nbuf_alloc_debug(NULL, roundup(size + TX_PKT_MIN_HEADROOM, 4), + TX_PKT_MIN_HEADROOM, sizeof(uint32_t), false, + file_name, line_num); + + if (nbuf != NULL) { + cdf_nbuf_put_tail(nbuf, size); + cdf_nbuf_set_protocol(nbuf, ETH_P_CONTROL); + *ppPacket = nbuf; + *data = cdf_nbuf_data(nbuf); + cdf_ret_status = CDF_STATUS_SUCCESS; + } + + return cdf_ret_status; +} +#else +/*--------------------------------------------------------------------------- +* @brief cds_packet_alloc() - + Allocate a network buffer for TX + ---------------------------------------------------------------------------*/ +CDF_STATUS cds_packet_alloc(uint16_t size, void **data, void **ppPacket) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + cdf_nbuf_t nbuf; + + nbuf = cdf_nbuf_alloc(NULL, roundup(size + TX_PKT_MIN_HEADROOM, 4), + TX_PKT_MIN_HEADROOM, sizeof(uint32_t), false); + + if (nbuf != NULL) { + cdf_nbuf_put_tail(nbuf, size); + cdf_nbuf_set_protocol(nbuf, ETH_P_CONTROL); + *ppPacket = nbuf; + *data = cdf_nbuf_data(nbuf); + cdf_ret_status = CDF_STATUS_SUCCESS; + } + + return cdf_ret_status; +} + +#endif +/*--------------------------------------------------------------------------- +* @brief cds_packet_free() - + Free input network buffer + ---------------------------------------------------------------------------*/ +void cds_packet_free(void *pPacket) +{ + cdf_nbuf_free((cdf_nbuf_t) pPacket); +} diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c new file mode 100644 index 000000000000..f8d275113245 --- /dev/null +++ b/core/cds/src/cds_reg_service.c @@ -0,0 +1,1439 @@ +/* + * 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: cds_reg_service.c + OVERVIEW: This source file contains definitions for CDS regulatory APIs + DEPENDENCIES: None + ============================================================================*/ + +#include +#include "cdf_types.h" +#include "cds_reg_service.h" +#include "cdf_trace.h" +#include "sme_api.h" +#include "wlan_hdd_main.h" +#include "cds_regdomain.h" +#include "cds_regdomain_common.h" + +#define WORLD_SKU_MASK 0x00F0 +#define WORLD_SKU_PREFIX 0x0060 +#define MAX_COUNTRY_COUNT 300 + +#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 bool init_by_driver = false; +/* true if init happens thru init time callback from regulatory core. + this should be set to true during driver reload */ +static bool init_by_reg_core = false; + +#define REG_WAIT_TIME 50 + +#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) + +static const struct ieee80211_regdomain cds_world_regdom_60_61_62 = { + .n_reg_rules = 6, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2412_2462, + REG_RULE_2467_2472, + REG_RULE_2484, + REG_RULE_5180_5320, + REG_RULE_5500_5720, + REG_RULE_5745_5925, + } +}; + +static const struct ieee80211_regdomain cds_world_regdom_63_65 = { + .n_reg_rules = 4, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2412_2462, + REG_RULE_2467_2472, + REG_RULE_5180_5320, + REG_RULE_5745_5925, + } +}; + +static const struct ieee80211_regdomain cds_world_regdom_64 = { + .n_reg_rules = 3, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2412_2462, + REG_RULE_5180_5320, + REG_RULE_5745_5925, + } +}; + +static const struct ieee80211_regdomain cds_world_regdom_66_69 = { + .n_reg_rules = 4, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2412_2462, + REG_RULE_5180_5320, + REG_RULE_5500_5720, + REG_RULE_5745_5925, + } +}; + +static const struct ieee80211_regdomain cds_world_regdom_67_68_6A_6C = { + .n_reg_rules = 5, + .alpha2 = "00", + .reg_rules = { + REG_RULE_2412_2462, + REG_RULE_2467_2472, + REG_RULE_5180_5320, + REG_RULE_5500_5720, + REG_RULE_5745_5925, + } +}; + +typedef struct { + uint8_t regDomain; + country_code_t countryCode; +} CountryInfo_t; + +typedef struct { + uint16_t countryCount; + CountryInfo_t countryInfo[MAX_COUNTRY_COUNT]; +} CountryInfoTable_t; + +static CountryInfoTable_t country_info_table = { + /* 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 */ + } +}; + +const tRfChannelProps rf_channels[NUM_RF_CHANNELS] = { + {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}, + {2422, 3}, + {2427, 4}, + {2432, 5}, + {2437, 6}, + {2442, 7}, + {2447, 8}, + {2452, 9}, + {2457, 10}, + {2462, 11}, + {4930, 242}, + {4950, 246}, + {4970, 250}, + {5050, 210}, + {5070, 214}, + {5190, 38}, + {5210, 42}, + {5230, 46}, + {5250, 50}, + {5270, 54}, + {5290, 58}, + {5310, 62}, + {5510, 102}, + {5530, 106}, + {5550, 110}, + {5570, 114}, + {5590, 118}, + {5610, 122}, + {5630, 126}, + {5650, 130}, + {5670, 134}, + {5690, 138}, + {5710, 142}, + {5755, 151}, + {5775, 155}, + {5795, 159}, + {5815, 163, }, +}; + +static t_reg_table reg_table; + +const sRegulatoryChannel *reg_channels = + reg_table.regDomains[0].channels; + + +/** + * cds_is_wwr_sku() - is regdomain world sku + * @regd: integer regulatory domain + * + * Return: bool + */ +static inline bool cds_is_wwr_sku(u16 regd) +{ + return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && + (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || + (regd == WORLD)); +} + +/** + * cds_is_world_regdomain() - whether world regdomain + * @regd: integer regulatory domain + * + * Return: bool + */ +bool cds_is_world_regdomain(uint32_t regd) +{ + return cds_is_wwr_sku(regd & ~WORLDWIDE_ROAMING_FLAG); +} + + +/** + * cds_world_regdomain() - which constant world regdomain + * @reg: regulatory data + * + * Return: regdomain ptr + */ +static const struct ieee80211_regdomain +*cds_world_regdomain(struct regulatory *reg) +{ + REG_DMN_PAIR_MAPPING *regpair = + (REG_DMN_PAIR_MAPPING *)reg->regpair; + + switch (regpair->regDmnEnum) { + case 0x60: + case 0x61: + case 0x62: + return &cds_world_regdom_60_61_62; + case 0x63: + case 0x65: + return &cds_world_regdom_63_65; + case 0x64: + return &cds_world_regdom_64; + case 0x66: + case 0x69: + return &cds_world_regdom_66_69; + case 0x67: + case 0x68: + case 0x6A: + case 0x6C: + return &cds_world_regdom_67_68_6A_6C; + default: + WARN_ON(1); + return &cds_world_regdom_60_61_62; + } +} + +/** + * cds_regulatory_wiphy_init() - regulatory wiphy init + * @hdd_ctx: hdd context + * @reg: regulatory data + * @wiphy: wiphy structure + * + * Return: int + */ +static int cds_regulatory_wiphy_init(hdd_context_t *hdd_ctx, + struct regulatory *reg, + struct wiphy *wiphy) +{ + const struct ieee80211_regdomain *reg_domain; + + if (cds_is_world_regdomain(reg->reg_domain)) { + reg_domain = cds_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 (hdd_ctx->config->fRegChangeDefCountry) { +#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 + reg_domain = &cds_world_regdom_60_61_62; + } else { +#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 + reg_domain = &cds_world_regdom_60_61_62; + } + + /* + * save the original driver regulatory flags + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) + hdd_ctx->reg.reg_flags = wiphy->regulatory_flags; +#else + hdd_ctx->reg.reg_flags = wiphy->flags; +#endif + wiphy_apply_custom_regulatory(wiphy, reg_domain); + + /* + * 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 = hdd_ctx->reg.reg_flags; +#else + wiphy->flags = hdd_ctx->reg.reg_flags; +#endif + + return 0; +} + +/** + * cds_update_regulatory_info() - update regulatory info + * @hdd_ctx: hdd context + * + * Return: CDF_STATUS + */ +static void cds_update_regulatory_info(hdd_context_t *hdd_ctx) +{ + uint32_t country_code; + + country_code = cds_get_country_from_alpha2(hdd_ctx->reg.alpha2); + + hdd_ctx->reg.reg_domain = COUNTRY_ERD_FLAG; + hdd_ctx->reg.reg_domain |= country_code; + + cds_fill_some_regulatory_info(&hdd_ctx->reg); + + return; +} + + +/** + * cds_get_channel_list_with_power() - retrieve channel list with power + * @base_channels: base channels + * @num_base_channels: number of base channels + * @channels_40mhz: 40 MHz channels + * @num_40mhz_channels: number of 40 Mhz channels + * + * Return: CDF_STATUS_SUCCESS + */ +CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * + base_channels, + uint8_t *num_base_channels, + tChannelListWithPower * + channels_40mhz, + uint8_t *num_40mhz_channels) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + int i, count; + + if (base_channels && num_base_channels) { + count = 0; + for (i = 0; i <= RF_CHAN_14; i++) { + if (reg_channels[i].enabled) { + base_channels[count].chanId = + rf_channels[i].channelNum; + base_channels[count++].pwr = + reg_channels[i].pwrLimit; + } + } + for (i = RF_CHAN_36; i <= RF_CHAN_184; i++) { + if (reg_channels[i].enabled) { + base_channels[count].chanId = + rf_channels[i].channelNum; + base_channels[count++].pwr = + reg_channels[i].pwrLimit; + } + } + *num_base_channels = count; + } + + if (channels_40mhz && num_40mhz_channels) { + count = 0; + + for (i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++) { + if (reg_channels[i].enabled) { + channels_40mhz[count].chanId = + rf_channels[i].channelNum; + channels_40mhz[count++].pwr = + reg_channels[i].pwrLimit; + } + } + + for (i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++) { + if (reg_channels[i].enabled) { + channels_40mhz[count].chanId = + rf_channels[i].channelNum; + channels_40mhz[count++].pwr = + reg_channels[i].pwrLimit; + } + } + *num_40mhz_channels = count; + } + + return status; +} + +/** + * cds_read_default_country() - set the default country + * @default_country: default country + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_read_default_country(country_code_t default_country) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + memcpy(default_country, + reg_table.default_country, + sizeof(country_code_t)); + + pr_info("DefaultCountry is %c%c\n", + default_country[0], + default_country[1]); + + return status; +} + +/** + * cds_get_channel_enum() - get the channel enumeration + * @chan_num: channel number + * + * Return: enum for the channel + */ +static eRfChannels cds_get_channel_enum(uint32_t chan_num) +{ + uint32_t loop; + + for (loop = 0; loop <= RF_CHAN_184; loop++) + if (rf_channels[loop].channelNum == chan_num) + return loop; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "invalid channel number %d", chan_num); + + return INVALID_RF_CHANNEL; +} + + +/** + * cds_get_channel_state() - get the channel state + * @channel_num: channel number + * + * Return: CHANNEL_STATE + */ +CHANNEL_STATE cds_get_channel_state(uint32_t chan_num) +{ + eRfChannels chan_enum; + + chan_enum = cds_get_channel_enum(chan_num); + if (INVALID_RF_CHANNEL == chan_enum) + return CHANNEL_STATE_INVALID; + else + return reg_channels[chan_enum].enabled; +} + + +/** + * cds_get_bonded_channel_state() - get the bonded channel state + * @channel_num: channel number + * + * Return: CHANNEL_STATE + */ +CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, + enum channel_width ch_width) +{ + eRfChannels chan_enum; + bool bw_enabled = false; + + chan_enum = cds_get_channel_enum(chan_num); + if (INVALID_RF_CHANNEL == chan_enum) + return CHANNEL_STATE_INVALID; + + if (reg_channels[chan_enum].enabled) { + if (CHAN_WIDTH_5MHZ == ch_width) + bw_enabled = 1; + else if (CHAN_WIDTH_10MHZ == ch_width) + bw_enabled = !(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_10MHZ); + else if (CHAN_WIDTH_20MHZ == ch_width) + bw_enabled = !(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_20MHZ); + else if (CHAN_WIDTH_40MHZ == ch_width) + bw_enabled = !(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_HT40); + else if (CHAN_WIDTH_80MHZ == ch_width) + bw_enabled = !(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_80MHZ); + else if (CHAN_WIDTH_160MHZ == ch_width) + bw_enabled = !(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_160MHZ); + } + + if (bw_enabled) + return reg_channels[chan_enum].enabled; + else + return CHANNEL_STATE_DISABLE; +} + +/** + * cds_get_max_channel_bw() - get the max channel bandwidth + * @channel_num: channel number + * + * Return: channel_width + */ +enum channel_width cds_get_max_channel_bw(uint32_t chan_num) +{ + eRfChannels chan_enum; + enum channel_width chan_bw = CHAN_WIDTH_0MHZ; + + chan_enum = cds_get_channel_enum(chan_num); + + if ((INVALID_RF_CHANNEL != chan_enum) && + (CHANNEL_STATE_DISABLE != reg_channels[chan_enum].enabled)) { + + if (!(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_160MHZ)) + chan_bw = CHAN_WIDTH_160MHZ; + else if (!(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_80MHZ)) + chan_bw = CHAN_WIDTH_80MHZ; + else if (!(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_HT40)) + chan_bw = CHAN_WIDTH_40MHZ; + else if (!(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_20MHZ)) + chan_bw = CHAN_WIDTH_20MHZ; + else if (!(reg_channels[chan_enum].flags & + IEEE80211_CHAN_NO_10MHZ)) + chan_bw = CHAN_WIDTH_10MHZ; + else + chan_bw = CHAN_WIDTH_5MHZ; + } + + return chan_bw; + +} + +static int cds_bw20_ch_index_to_bw40_ch_index(int k) +{ + int m = -1; + if (k >= RF_CHAN_1 && k <= RF_CHAN_14) { + 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; + } + else if (k >= RF_CHAN_100 && k <= RF_CHAN_144) + { + m = k - RF_CHAN_100 + RF_CHAN_BOND_102; + if (m > RF_CHAN_BOND_142) + m = RF_CHAN_BOND_142; + } 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; +} + +/** + * cds_set_dfs_region() - set the dfs_region + * @dfs_region: the dfs_region to set + * + * Return: CDF_STATUS_SUCCESS if dfs_region set correctly + * CDF_STATUS_E_EXISTS if hdd context not found + */ +CDF_STATUS cds_set_dfs_region(uint8_t dfs_region) +{ + hdd_context_t *hdd_ctx_ptr = NULL; + + hdd_ctx_ptr = cds_get_context(CDF_MODULE_ID_HDD); + + if (NULL == hdd_ctx_ptr) + return CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * cds_get_dfs_region() - get the dfs_region + * @dfs_region: the dfs_region to return + * + * Return: CDF_STATUS_SUCCESS if dfs_region set correctly + * CDF_STATUS_E_EXISTS if hdd context not found + */ +CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region) +{ + hdd_context_t *hdd_ctx_ptr = NULL; + + hdd_ctx_ptr = cds_get_context(CDF_MODULE_ID_HDD); + + if (NULL == hdd_ctx_ptr) + return CDF_STATUS_E_EXISTS; + + *dfs_region = hdd_ctx_ptr->reg.dfs_region; + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_get_reg_domain_from_country_code() - get the regulatory domain + * @reg_domain_ptr: ptr to store regulatory domain + * + * Return: CDF_STATUS_SUCCESS on success + * CDF_STATUS_E_FAULT on error + * CDF_STATUS_E_EMPTY country table empty + */ +CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, + const country_code_t + country_code, + v_CountryInfoSource_t source) +{ + v_CONTEXT_t cds_context = NULL; + hdd_context_t *hdd_ctx = NULL; + struct wiphy *wiphy = NULL; + int i; + + if (NULL == reg_domain_ptr) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Invalid reg domain pointer")); + return CDF_STATUS_E_FAULT; + } + + *reg_domain_ptr = REGDOMAIN_COUNT; + + if (NULL == country_code) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Country code array is NULL")); + return CDF_STATUS_E_FAULT; + } + + if (0 == country_info_table.countryCount) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Reg domain table is empty")); + return CDF_STATUS_E_EMPTY; + } + + cds_context = cds_get_global_context(); + + if (NULL != cds_context) + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + else + return CDF_STATUS_E_EXISTS; + + if (NULL == hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer")); + return CDF_STATUS_E_FAULT; + } + + wiphy = hdd_ctx->wiphy; + + if (cds_is_logp_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "SSR in progress, return"); + *reg_domain_ptr = temp_reg_domain; + return CDF_STATUS_SUCCESS; + } + + temp_reg_domain = REGDOMAIN_COUNT; + for (i = 0; i < country_info_table.countryCount && + REGDOMAIN_COUNT == temp_reg_domain; i++) { + if (memcmp(country_code, + country_info_table.countryInfo[i].countryCode, + CDS_COUNTRY_CODE_LEN) == 0) { + + temp_reg_domain = + country_info_table.countryInfo[i].regDomain; + break; + } + } + + if (REGDOMAIN_COUNT == temp_reg_domain) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Country does not map to any Regulatory domain")); + temp_reg_domain = REGDOMAIN_WORLD; + } + + if (COUNTRY_QUERY == source) { + *reg_domain_ptr = temp_reg_domain; + return CDF_STATUS_SUCCESS; + } + + if ((COUNTRY_INIT == source) && (false == init_by_reg_core)) { + init_by_driver = true; + if (('0' != country_code[0]) || ('0' != country_code[1])) { + INIT_COMPLETION(hdd_ctx->reg_init); + regulatory_hint(wiphy, country_code); + wait_for_completion_timeout(&hdd_ctx->reg_init, + msecs_to_jiffies(REG_WAIT_TIME)); + } + } else if (COUNTRY_IE == source || COUNTRY_USER == source) { + regulatory_hint_user(country_code, + NL80211_USER_REG_HINT_USER); + } + + *reg_domain_ptr = temp_reg_domain; + return CDF_STATUS_SUCCESS; +} + +/* + * cds_is_dsrc_channel() - is the channel DSRC + * @center_freq: center freq of the channel + * + * Return: true if dsrc channel + * false otherwise + */ +bool cds_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; +} + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS +#define DEFAULT_11P_POWER (30) +#endif + +/** + * cds_process_regulatory_data() - process regulatory data + * @wiphy: wiphy + * @band_capability: band_capability + * + * Return: int + */ +static int cds_process_regulatory_data(struct wiphy *wiphy, + uint8_t band_capability, bool reset) +{ + int i, j, m; + int k = 0, n = 0; + hdd_context_t *hdd_ctx; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *chan; + sRegulatoryChannel *temp_chan_k; + sRegulatoryChannel *temp_chan_n; + sRegulatoryChannel *temp_chan; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL == hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "invalid hdd_ctx pointer"); + return CDF_STATUS_E_FAULT; + } + + hdd_ctx->isVHT80Allowed = 0; + + if (band_capability == eCSR_BAND_24) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "band capability is set to 2G only"); + + for (i = 0, m = 0; i < IEEE80211_NUM_BANDS; i++) { + + if (i == IEEE80211_BAND_2GHZ && band_capability == eCSR_BAND_5G) + continue; + + else if (i == IEEE80211_BAND_5GHZ + && band_capability == eCSR_BAND_24) + continue; + + if (wiphy->bands[i] == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "error: wiphy->bands is NULL, i = %d", i); + continue; + } + + if (i == 0) + m = 0; + else + m = wiphy->bands[i-1]->n_channels + m; + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) { + + k = m + j; + n = cds_bw20_ch_index_to_bw40_ch_index(k); + + chan = &(wiphy->bands[i]->channels[j]); + temp_chan_k = + &(reg_table.regDomains[temp_reg_domain]. + channels[k]); + + temp_chan_n = + &(reg_table.regDomains[temp_reg_domain]. + channels[n]); + + 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 + reg_rule = freq_reg_info(wiphy, + MHZ_TO_KHZ(chan-> + center_freq)); + + if (!IS_ERR(reg_rule)) { + chan->flags &= + ~IEEE80211_CHAN_DISABLED; + + if (!(reg_rule->flags & + NL80211_RRF_DFS)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Remove passive scan restriction for %u", + __func__, + chan->center_freq); + chan->flags &= + ~IEEE80211_CHAN_RADAR; + } + + if (!(reg_rule->flags & + NL80211_RRF_PASSIVE_SCAN)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Remove passive scan restriction for %u", + __func__, + chan->center_freq); + chan->flags &= + ~IEEE80211_CHAN_PASSIVE_SCAN; + } + + if (!(reg_rule->flags & + NL80211_RRF_NO_IBSS)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Remove no ibss restriction for %u", + __func__, + chan->center_freq); + chan->flags &= + ~IEEE80211_CHAN_NO_IBSS; + } + + chan->max_power = MBM_TO_DBM(reg_rule-> + power_rule. + max_eirp); + } + } + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS + if (is_dsrc_channel(chan->center_freq)) { + temp_chan_k->enabled = + CHANNEL_STATE_ENABLE; + temp_chan_k->pwrLimit = + DEFAULT_11P_POWER; + temp_chan_k->flags = chan->flags; + } else +#endif + if (chan->flags & IEEE80211_CHAN_DISABLED) { + temp_chan_k->enabled = + CHANNEL_STATE_DISABLE; + temp_chan_k->flags = chan->flags; + if (n != -1) { + temp_chan_n->enabled = + CHANNEL_STATE_DISABLE; + temp_chan_n->flags = chan->flags; + } + } else if (chan->flags & + (IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_PASSIVE_SCAN +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + | + IEEE80211_CHAN_INDOOR_ONLY +#endif + )) { + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + if (chan->flags & + IEEE80211_CHAN_INDOOR_ONLY) + chan->flags |= + IEEE80211_CHAN_PASSIVE_SCAN; +#endif + temp_chan_k->enabled = CHANNEL_STATE_DFS; + temp_chan_k->pwrLimit = + chan->max_power; + temp_chan_k->flags = chan->flags; + + if (n != -1) { + if ((chan->flags & + IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40) { + temp_chan_n->enabled = + CHANNEL_STATE_DISABLE; + } else { + temp_chan_n->enabled = + CHANNEL_STATE_DFS; + temp_chan_n->pwrLimit = + chan->max_power-3; + } + temp_chan_n->flags = chan->flags; + } + if ((chan->flags & + IEEE80211_CHAN_NO_80MHZ) == 0) + hdd_ctx->isVHT80Allowed = 1; + } else { + temp_chan_k->enabled = CHANNEL_STATE_ENABLE; + temp_chan_k->pwrLimit = chan->max_power; + temp_chan_k->flags = chan->flags; + if (n != -1) { + if ((chan->flags & + IEEE80211_CHAN_NO_HT40) == + IEEE80211_CHAN_NO_HT40) { + temp_chan_n->enabled = + CHANNEL_STATE_DISABLE; + } else { + temp_chan_n->enabled = + CHANNEL_STATE_ENABLE; + temp_chan_n->pwrLimit = + chan->max_power - 3; + } + temp_chan_n->flags = chan->flags; + } + if ((chan->flags & + IEEE80211_CHAN_NO_80MHZ) == 0) + hdd_ctx->isVHT80Allowed = 1; + } + } + } + + if (0 == (hdd_ctx->reg.eeprom_rd_ext & + (1 << WHAL_REG_EXT_FCC_CH_144))) { + temp_chan = &(reg_table.regDomains[temp_reg_domain]. + channels[RF_CHAN_144]); + temp_chan->enabled = + CHANNEL_STATE_DISABLE; + } + + 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 + +/** + * hdd_reg_notifier() - regulatory notifier + * @wiphy: wiphy + * @request: regulatory request + * + * Return: void or int + */ +void hdd_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + eCsrBand band_capability = eCSR_BAND_ALL; + country_code_t country_code; + int i; + bool vht80_allowed; + bool reset = false; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + FL("country: %c%c, initiator %d, dfs_region: %d"), + request->alpha2[0], + request->alpha2[1], + request->initiator, + request->dfs_region); + + if (NULL == hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer")); + return; + } + + if (hdd_ctx->isUnloadInProgress || hdd_ctx->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Unloading or SSR in Progress, Ignore!!!", + __func__); + return; + } + + sme_get_freq_band(hdd_ctx->hHal, &band_capability); + + /* 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 ((false == init_by_driver) && + (false == init_by_reg_core)) { + + if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { + return; + } + init_by_reg_core = true; + } + + if ((NL80211_REGDOM_SET_BY_DRIVER == request->initiator) && + (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 = hdd_ctx->reg.reg_flags; +#else + wiphy->flags = hdd_ctx->reg.reg_flags; +#endif + } + + if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { + hdd_ctx->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) + hdd_ctx->reg.cc_src = COUNTRY_CODE_SET_BY_DRIVER; + else { + hdd_ctx->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]; + + hdd_ctx->reg.alpha2[0] = request->alpha2[0]; + hdd_ctx->reg.alpha2[1] = request->alpha2[1]; + + cds_update_regulatory_info(hdd_ctx); + + temp_reg_domain = REGDOMAIN_COUNT; + for (i = 0; i < country_info_table.countryCount && + REGDOMAIN_COUNT == temp_reg_domain; i++) { + if (memcmp(country_code, + country_info_table.countryInfo[i].countryCode, + CDS_COUNTRY_CODE_LEN) == 0) { + + temp_reg_domain = + country_info_table.countryInfo[i].regDomain; + break; + } + } + + if (REGDOMAIN_COUNT == temp_reg_domain) + temp_reg_domain = REGDOMAIN_WORLD; + + vht80_allowed = hdd_ctx->isVHT80Allowed; + if (cds_process_regulatory_data(wiphy, band_capability, + reset) == 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + (" regulatory entry created")); + } + if (hdd_ctx->isVHT80Allowed != vht80_allowed) + hdd_checkandupdate_phymode(hdd_ctx); + + if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) + complete(&hdd_ctx->reg_init); + + if (request->alpha2[0] == '0' + && request->alpha2[1] == '0') { + sme_generic_change_country_code(hdd_ctx->hHal, + country_code, + REGDOMAIN_COUNT); + } else { + sme_generic_change_country_code(hdd_ctx->hHal, + country_code, + temp_reg_domain); + } + + cds_fill_and_send_ctl_to_fw(&hdd_ctx->reg); + + cds_set_dfs_region(request->dfs_region); + + cds_set_wma_dfs_region(&hdd_ctx->reg); + default: + break; + } + + return; +} + +/** + * cds_regulatory_init() - regulatory_init + * Return: CDF_STATUS + */ +CDF_STATUS cds_regulatory_init(void) +{ + v_CONTEXT_t cds_context = NULL; + hdd_context_t *hdd_ctx = NULL; + struct wiphy *wiphy = NULL; + int ret_val = 0; + struct regulatory *reg_info; + + cds_context = cds_get_global_context(); + + if (!cds_context) + return CDF_STATUS_E_FAULT; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Invalid pHddCtx pointer")); + return CDF_STATUS_E_FAULT; + } + + wiphy = hdd_ctx->wiphy; + + reg_info = &hdd_ctx->reg; + + cds_regulatory_wiphy_init(hdd_ctx, reg_info, wiphy); + + temp_reg_domain = REGDOMAIN_WORLD; + + if (cds_process_regulatory_data(wiphy, + hdd_ctx->config-> + nBandCapability, true) != 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Error while creating regulatory entry")); + return CDF_STATUS_E_FAULT; + } + + reg_info->cc_src = COUNTRY_CODE_SET_BY_DRIVER; + + ret_val = cds_fill_some_regulatory_info(reg_info); + if (ret_val) { + cdf_print(KERN_ERR "Error in getting country code\n"); + return ret_val; + } + + reg_table.default_country[0] = reg_info->alpha2[0]; + reg_table.default_country[1] = reg_info->alpha2[1]; + + init_completion(&hdd_ctx->reg_init); + + cds_fill_and_send_ctl_to_fw(reg_info); + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_set_reg_domain() - set regulatory domain + * @client_ctxt: client context + * @reg_domain: regulatory domain + * + * Return: CDF_STATUS + */ +CDF_STATUS cds_set_reg_domain(void *client_ctxt, v_REGDOMAIN_t reg_domain) +{ + if (reg_domain >= REGDOMAIN_COUNT) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "CDS set reg domain, invalid REG domain ID %d", + reg_domain); + return CDF_STATUS_E_INVAL; + } + + reg_channels = reg_table.regDomains[reg_domain].channels; + + return CDF_STATUS_SUCCESS; +} diff --git a/core/cds/src/cds_regdomain.c b/core/cds/src/cds_regdomain.c new file mode 100644 index 000000000000..3a935293c289 --- /dev/null +++ b/core/cds/src/cds_regdomain.c @@ -0,0 +1,699 @@ +/* + * 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. + */ + +/* + * 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 "cds_regdomain.h" +#include "cds_regdomain_common.h" + +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}}, + {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}}, + {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 = { + ah_cmn_reg_domain_pairs, /* regDomainPairs */ + ah_cmn_all_countries, /* allCountries */ + ah_cmn_reg_domains, /* allRegDomains */ + CDF_ARRAY_SIZE(ah_cmn_reg_domain_pairs), /* regDomainPairsCt */ + CDF_ARRAY_SIZE(ah_cmn_all_countries), /* allCountriesCt */ + CDF_ARRAY_SIZE(ah_cmn_reg_domains), /* allRegDomainCt */ +}; + +static uint16_t get_eeprom_rd(uint16_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(uint16_t rd) +{ + int32_t i; + + if (rd & COUNTRY_ERD_FLAG) { + uint16_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 */ + cdf_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(uint16_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 cds_get_country_from_alpha2(uint8_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; +} + +static uint16_t regdmn_get_default_country(uint16_t rd) +{ + int32_t i; + + if (rd & COUNTRY_ERD_FLAG) { + const COUNTRY_CODE_TO_ENUM_RD *country = NULL; + uint16_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(uint16_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(uint16_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(uint16_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 cds_fill_some_regulatory_info(struct regulatory *reg) +{ + uint16_t country_code; + uint16_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 */ + cdf_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 */ + cdf_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(uint8_t *alpha2) +{ + uint8_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 is_chan_bit_mask_zero(const uint64_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. + */ +static uint32_t regdmn_getwmodesnreg(uint32_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) && + (is_chan_bit_mask_zero(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 cds_fill_send_ctl_info_to_fw(struct regulatory *reg, uint32_t modesAvail, + uint32_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) { + cdf_print(KERN_ERR "Failed to get regdmn 2G"); + return; + } + + regdomain5G = get_regdmn(regpair->regDmn5GHz); + if (!regdomain5G) { + cdf_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[CDF_ARRAY_SIZE(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: + cdf_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_to_fw(reg->reg_domain, regpair->regDmn2GHz, + regpair->regDmn5GHz, ctl_2g, ctl_5g); +} + +/* cds_set_wma_dfs_region() - to set the dfs region to wma + * + * @reg: the regulatory handle + * + * Return: none + */ +void cds_set_wma_dfs_region(struct regulatory *reg) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + + if (!wma) { + cdf_print(KERN_ERR "%s: Unable to get WMA handle", __func__); + return; + } + + cdf_print("%s: dfs_region: %d", __func__, reg->dfs_region); + wma_set_dfs_region(wma, reg->dfs_region); +} + +void cds_fill_and_send_ctl_to_fw(struct regulatory *reg) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + uint32_t modeSelect = 0xFFFFFFFF; + + if (!wma) { + WMA_LOGE("%s: Unable to get WMA handle", __func__); + return; + } + + wma_get_modeselect(wma, &modeSelect); + + cds_fill_send_ctl_info_to_fw(reg, wma->reg_cap.wireless_modes, + modeSelect); + return; +} + +/* get the ctl from regdomain */ +uint8_t cds_get_ctl_for_regdmn(uint32_t reg_dmn) +{ + uint8_t i; + uint8_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 + */ +uint16_t cds_get_regdmn_5g(uint32_t reg_dmn) +{ + uint16_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; + } + } + cdf_print("%s: invalid regulatory domain/country code 0x%x\n", + __func__, reg_dmn); + return 0; +} + +/* + * Get operating class for a given channel + */ +uint16_t cds_regdm_get_opclass_from_channel(uint8_t *country, uint8_t channel, + uint8_t offset) +{ + regdm_op_class_map_t *class = NULL; + uint16_t i = 0; + + if (true == cdf_mem_compare(country, "US", 2)) { + class = us_op_class; + } else if (true == cdf_mem_compare(country, "EU", 2)) { + class = euro_op_class; + } else if (true == cdf_mem_compare(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 + */ +uint16_t cds_regdm_set_curr_opclasses(uint8_t num_classes, uint8_t *class) +{ + uint8_t i; + + if (SIR_MAC_MAX_SUPP_OPER_CLASSES < num_classes) { + cdf_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 + */ +uint16_t cds_regdm_get_curr_opclasses(uint8_t *num_classes, uint8_t *class) +{ + uint8_t i; + + if (!num_classes || !class) { + cdf_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/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c new file mode 100644 index 000000000000..07c8df060a53 --- /dev/null +++ b/core/cds/src/cds_sched.c @@ -0,0 +1,1270 @@ +/* + * 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: cds_sched.c + * + * DOC: CDS Scheduler Implementation + */ + + /* Include Files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cds_sched.h" +#include +#include "wma_types.h" +#include +#include +#include +#if defined(QCA_CONFIG_SMP) && defined(CONFIG_CNSS) +#include +#endif +/* Preprocessor Definitions and Constants */ +#define CDS_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 - sub system restart(ssr) protection tracking table + * @func: Function which needs ssr protection + * @free: Flag to tell whether entry is free in table or not + * @pid: Process id which needs ssr protection + */ +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]; + +static p_cds_sched_context gp_cds_sched_context; + +static int cds_mc_thread(void *Arg); +#ifdef QCA_CONFIG_SMP +static int cds_ol_rx_thread(void *arg); +static unsigned long affine_cpu; +static CDF_STATUS cds_alloc_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext); +#endif + +#ifdef QCA_CONFIG_SMP +#define CDS_CORE_PER_CLUSTER (4) +static int cds_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 +} + +/** + * cds_cpu_hotplug_notify() - hot plug notify + * @block: Pointer to block + * @state: State + * @hcpu: Pointer to hotplug cpu + * + * Return: NOTIFY_OK + */ +static int +cds_cpu_hotplug_notify(struct notifier_block *block, + unsigned long state, void *hcpu) +{ + unsigned long cpu = (unsigned long)hcpu; + unsigned long pref_cpu = 0; + p_cds_sched_context pSchedContext = get_cds_sched_ctxt(); + int i; + unsigned int multi_cluster; + unsigned int num_cpus; + + if ((NULL == pSchedContext) || (NULL == pSchedContext->ol_rx_thread)) + return NOTIFY_OK; + + if (cds_is_load_unload_in_progress()) + return NOTIFY_OK; + + num_cpus = num_possible_cpus(); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_LOW, + "%s: RX CORE %d, STATE %d, NUM CPUS %d", + __func__, (int)affine_cpu, (int)state, num_cpus); + multi_cluster = (num_cpus > CDS_CORE_PER_CLUSTER) ? 1 : 0; + + switch (state) { + case CPU_ONLINE: + if ((!multi_cluster) && (affine_cpu != 0)) + return NOTIFY_OK; + + for_each_online_cpu(i) { + if (i == 0) + continue; + pref_cpu = i; + if (!multi_cluster) + 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; + if (!multi_cluster) + break; + } + } + + if (pref_cpu == 0) + return NOTIFY_OK; + + if (!cds_set_cpus_allowed_ptr(pSchedContext->ol_rx_thread, pref_cpu)) + affine_cpu = pref_cpu; + + return NOTIFY_OK; +} + +static struct notifier_block cds_cpu_hotplug_notifier = { + .notifier_call = cds_cpu_hotplug_notify, +}; +#endif + +/** + * cds_sched_open() - initialize the CDS Scheduler + * @p_cds_context: Pointer to the global CDS Context + * @pSchedContext: Pointer to a previously allocated buffer big + * enough to hold a scheduler context. + * @SchedCtxSize: CDS scheduler context size + * + * This function initializes the CDS Scheduler + * Upon successful initialization: + * - All the message queues are initialized + * - The Main Controller thread is created and ready to receive and + * dispatch messages. + * + * + * Return: CDF status + */ +CDF_STATUS cds_sched_open(void *p_cds_context, + p_cds_sched_context pSchedContext, + uint32_t SchedCtxSize) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Opening the CDS Scheduler", __func__); + /* Sanity checks */ + if ((p_cds_context == NULL) || (pSchedContext == NULL)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return CDF_STATUS_E_FAILURE; + } + if (sizeof(cds_sched_context) != SchedCtxSize) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Incorrect CDS Sched Context size passed", + __func__); + return CDF_STATUS_E_INVAL; + } + cdf_mem_zero(pSchedContext, sizeof(cds_sched_context)); + pSchedContext->pVContext = p_cds_context; + vStatus = cds_sched_init_mqs(pSchedContext); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to initialize CDS Scheduler MQs", + __func__); + return vStatus; + } + /* Initialize the helper events and event queues */ + init_completion(&pSchedContext->McStartEvent); + init_completion(&pSchedContext->McShutdown); + init_completion(&pSchedContext->ResumeMcEvent); + + spin_lock_init(&pSchedContext->McThreadLock); +#ifdef QCA_CONFIG_SMP + spin_lock_init(&pSchedContext->ol_rx_thread_lock); +#endif + + init_waitqueue_head(&pSchedContext->mcWaitQueue); + pSchedContext->mcEventFlag = 0; + +#ifdef QCA_CONFIG_SMP + init_waitqueue_head(&pSchedContext->ol_rx_wait_queue); + init_completion(&pSchedContext->ol_rx_start_event); + init_completion(&pSchedContext->ol_suspend_rx_event); + init_completion(&pSchedContext->ol_resume_rx_event); + init_completion(&pSchedContext->ol_rx_shutdown); + pSchedContext->ol_rx_event_flag = 0; + spin_lock_init(&pSchedContext->ol_rx_queue_lock); + spin_lock_init(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + INIT_LIST_HEAD(&pSchedContext->ol_rx_thread_queue); + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + INIT_LIST_HEAD(&pSchedContext->cds_ol_rx_pkt_freeq); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + if (cds_alloc_ol_rx_pkt_freeq(pSchedContext) != CDF_STATUS_SUCCESS) { + return CDF_STATUS_E_FAILURE; + } + register_hotcpu_notifier(&cds_cpu_hotplug_notifier); + pSchedContext->cpu_hot_plug_notifier = &cds_cpu_hotplug_notifier; +#endif + gp_cds_sched_context = pSchedContext; + + /* Create the CDS Main Controller thread */ + pSchedContext->McThread = kthread_create(cds_mc_thread, pSchedContext, + "cds_mc_thread"); + if (IS_ERR(pSchedContext->McThread)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Could not Create CDS Main Thread Controller", + __func__); + goto MC_THREAD_START_FAILURE; + } + wake_up_process(pSchedContext->McThread); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS Main Controller thread Created", __func__); + +#ifdef QCA_CONFIG_SMP + pSchedContext->ol_rx_thread = kthread_create(cds_ol_rx_thread, + pSchedContext, + "cds_ol_rx_thread"); + if (IS_ERR(pSchedContext->ol_rx_thread)) { + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Could not Create CDS OL RX Thread", + __func__); + goto OL_RX_THREAD_START_FAILURE; + + } + wake_up_process(pSchedContext->ol_rx_thread); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + ("CDS OL 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); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS MC Thread has started", __func__); +#ifdef QCA_CONFIG_SMP + wait_for_completion_interruptible(&pSchedContext->ol_rx_start_event); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS OL Rx Thread has started", __func__); +#endif + /* We're good now: Let's get the ball rolling!!! */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS Scheduler successfully Opened", __func__); + return CDF_STATUS_SUCCESS; + +#ifdef QCA_CONFIG_SMP +OL_RX_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); +#endif + +MC_THREAD_START_FAILURE: + /* De-initialize all the message queues */ + cds_sched_deinit_mqs(pSchedContext); + +#ifdef QCA_CONFIG_SMP + unregister_hotcpu_notifier(&cds_cpu_hotplug_notifier); + cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); +#endif + + return CDF_STATUS_E_RESOURCES; + +} /* cds_sched_open() */ + +/** + * cds_mc_thread() - cds main controller thread execution handler + * @Arg: Pointer to the global CDS Sched Context + * + * Return: thread exit code + */ +static int cds_mc_thread(void *Arg) +{ + p_cds_sched_context pSchedContext = (p_cds_sched_context) Arg; + p_cds_msg_wrapper pMsgWrapper = NULL; + tpAniSirGlobal pMacContext = NULL; + tSirRetStatus macStatus = eSIR_SUCCESS; + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + int retWaitStatus = 0; + bool shutdown = false; + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t p_cds_context = NULL; + + if (Arg == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: MC Thread %d (%s) starting up", __func__, current->pid, + current->comm); + + /* Get the Global CDS Context */ + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Global CDS context is Null", + __func__); + return 0; + } + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + hddLog(CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: wait_event_interruptible returned -ERESTARTSYS", + __func__); + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: MC thread signaled to shutdown", + __func__); + shutdown = 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 (!cds_is_mq_empty(&pSchedContext->sysMcMq)) { + /* Service the SYS message queue */ + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Servicing the CDS SYS MC Message queue", + __func__); + pMsgWrapper = + cds_mq_get(&pSchedContext->sysMcMq); + if (pMsgWrapper == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", + __func__); + CDF_ASSERT(0); + break; + } + vStatus = + sys_mc_process_msg(pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: Issue Processing SYS message", + __func__); + } + /* return message to the Core */ + cds_core_return_msg(pSchedContext->pVContext, + pMsgWrapper); + continue; + } + /* Check the WMA queue */ + if (!cds_is_mq_empty(&pSchedContext->wmaMcMq)) { + /* Service the WMA message queue */ + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Servicing the CDS WMA MC Message queue", + __func__); + pMsgWrapper = + cds_mq_get(&pSchedContext->wmaMcMq); + if (pMsgWrapper == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", + __func__); + CDF_ASSERT(0); + break; + } + vStatus = + wma_mc_process_msg(pSchedContext->pVContext, + pMsgWrapper->pVosMsg); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: Issue Processing WMA message", + __func__); + } + /* return message to the Core */ + cds_core_return_msg(pSchedContext->pVContext, + pMsgWrapper); + continue; + } + /* Check the PE queue */ + if (!cds_is_mq_empty(&pSchedContext->peMcMq)) { + /* Service the PE message queue */ + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Servicing the CDS PE MC Message queue", + __func__); + pMsgWrapper = + cds_mq_get(&pSchedContext->peMcMq); + if (NULL == pMsgWrapper) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", + __func__); + CDF_ASSERT(0); + break; + } + + /* Need some optimization */ + pMacContext = + cds_get_context(CDF_MODULE_ID_PE); + if (NULL == pMacContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "MAC Context not ready yet"); + cds_core_return_msg + (pSchedContext->pVContext, + pMsgWrapper); + continue; + } + + macStatus = + pe_process_messages(pMacContext, + (tSirMsgQ *) + pMsgWrapper->pVosMsg); + if (eSIR_SUCCESS != macStatus) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: Issue Processing PE message", + __func__); + } + /* return message to the Core */ + cds_core_return_msg(pSchedContext->pVContext, + pMsgWrapper); + continue; + } + /** Check the SME queue **/ + if (!cds_is_mq_empty(&pSchedContext->smeMcMq)) { + /* Service the SME message queue */ + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Servicing the CDS SME MC Message queue", + __func__); + pMsgWrapper = + cds_mq_get(&pSchedContext->smeMcMq); + if (NULL == pMsgWrapper) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: pMsgWrapper is NULL", + __func__); + CDF_ASSERT(0); + break; + } + + /* Need some optimization */ + pMacContext = + cds_get_context(CDF_MODULE_ID_SME); + if (NULL == pMacContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "MAC Context not ready yet"); + cds_core_return_msg + (pSchedContext->pVContext, + pMsgWrapper); + continue; + } + + vStatus = + sme_process_msg((tHalHandle) pMacContext, + pMsgWrapper->pVosMsg); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: Issue Processing SME message", + __func__); + } + /* return message to the Core */ + cds_core_return_msg(pSchedContext->pVContext, + pMsgWrapper); + continue; + } + /* Check for any Suspend Indication */ + if (test_bit + (MC_SUSPEND_EVENT_MASK, + &pSchedContext->mcEventFlag)) { + clear_bit(MC_SUSPEND_EVENT_MASK, + &pSchedContext->mcEventFlag); + spin_lock(&pSchedContext->McThreadLock); + + /* Mc Thread Suspended */ + complete(&pHddCtx->mc_sus_event_var); + + INIT_COMPLETION(pSchedContext->ResumeMcEvent); + spin_unlock(&pSchedContext->McThreadLock); + + /* Wait foe Resume Indication */ + wait_for_completion_interruptible + (&pSchedContext->ResumeMcEvent); + } + break; /* All queues are empty now */ + } /* while message loop processing */ + } /* while true */ + /* If we get here the MC thread must exit */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: MC Thread exiting!!!!", __func__); + complete_and_exit(&pSchedContext->McShutdown, 0); +} /* cds_mc_thread() */ + +#ifdef QCA_CONFIG_SMP +/** + * cds_free_ol_rx_pkt_freeq() - free cds buffer free queue + * @pSchedContext - pointer to the global CDS Sched Context + * + * This API does mem free of the buffers available in free cds buffer + * queue which is used for Data rx processing. + * + * Return: none + */ +void cds_free_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext) +{ + struct cds_ol_rx_pkt *pkt, *tmp; + + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + list_for_each_entry_safe(pkt, tmp, &pSchedContext->cds_ol_rx_pkt_freeq, + list) { + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + cdf_mem_free(pkt); + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + } + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); +} + +/** + * cds_alloc_ol_rx_pkt_freeq() - Function to allocate free buffer queue + * @pSchedContext - pointer to the global CDS Sched Context + * + * This API allocates CDS_MAX_OL_RX_PKT number of cds message buffers + * which are used for Rx data processing. + * + * Return: status of memory allocation + */ +static CDF_STATUS cds_alloc_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext) +{ + struct cds_ol_rx_pkt *pkt, *tmp; + int i; + + for (i = 0; i < CDS_MAX_OL_RX_PKT; i++) { + pkt = cdf_mem_malloc(sizeof(*pkt)); + if (!pkt) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s Vos packet allocation for ol rx thread failed", + __func__); + goto free; + } + memset(pkt, 0, sizeof(*pkt)); + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + list_add_tail(&pkt->list, &pSchedContext->cds_ol_rx_pkt_freeq); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + } + + return CDF_STATUS_SUCCESS; + +free: + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + list_for_each_entry_safe(pkt, tmp, &pSchedContext->cds_ol_rx_pkt_freeq, + list) { + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + cdf_mem_free(pkt); + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + } + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + return CDF_STATUS_E_NOMEM; +} + +/** + * cds_free_ol_rx_pkt() - api to release cds message to the freeq + * This api returns the cds message used for Rx data to the free queue + * @pSchedContext: Pointer to the global CDS Sched Context + * @pkt: CDS message buffer to be returned to free queue. + * + * Return: none + */ +void +cds_free_ol_rx_pkt(p_cds_sched_context pSchedContext, + struct cds_ol_rx_pkt *pkt) +{ + memset(pkt, 0, sizeof(*pkt)); + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + list_add_tail(&pkt->list, &pSchedContext->cds_ol_rx_pkt_freeq); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); +} + +/** + * cds_alloc_ol_rx_pkt() - API to return next available cds message + * @pSchedContext: Pointer to the global CDS Sched Context + * + * This api returns next available cds message buffer used for rx data + * processing + * + * Return: Pointer to cds message buffer + */ +struct cds_ol_rx_pkt *cds_alloc_ol_rx_pkt(p_cds_sched_context pSchedContext) +{ + struct cds_ol_rx_pkt *pkt; + + spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + if (list_empty(&pSchedContext->cds_ol_rx_pkt_freeq)) { + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + return NULL; + } + pkt = list_first_entry(&pSchedContext->cds_ol_rx_pkt_freeq, + struct cds_ol_rx_pkt, list); + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); + return pkt; +} + +/** + * cds_indicate_rxpkt() - indicate rx data packet + * @Arg: Pointer to the global CDS Sched Context + * @pkt: CDS data message buffer + * + * This api enqueues the rx packet into ol_rx_thread_queue and notifies + * cds_ol_rx_thread() + * + * Return: none + */ +void +cds_indicate_rxpkt(p_cds_sched_context pSchedContext, + struct cds_ol_rx_pkt *pkt) +{ + spin_lock_bh(&pSchedContext->ol_rx_queue_lock); + list_add_tail(&pkt->list, &pSchedContext->ol_rx_thread_queue); + spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); + set_bit(RX_POST_EVENT_MASK, &pSchedContext->ol_rx_event_flag); + wake_up_interruptible(&pSchedContext->ol_rx_wait_queue); +} + +/** + * cds_drop_rxpkt_by_staid() - api to drop pending rx packets for a sta + * @pSchedContext: Pointer to the global CDS Sched Context + * @staId: Station Id + * + * This api drops queued packets for a station, to drop all the pending + * packets the caller has to send WLAN_MAX_STA_COUNT as staId. + * + * Return: none + */ +void cds_drop_rxpkt_by_staid(p_cds_sched_context pSchedContext, uint16_t staId) +{ + struct list_head local_list; + struct cds_ol_rx_pkt *pkt, *tmp; + cdf_nbuf_t buf, next_buf; + + INIT_LIST_HEAD(&local_list); + spin_lock_bh(&pSchedContext->ol_rx_queue_lock); + if (list_empty(&pSchedContext->ol_rx_thread_queue)) { + spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); + return; + } + list_for_each_entry_safe(pkt, tmp, &pSchedContext->ol_rx_thread_queue, + list) { + if (pkt->staId == staId || staId == WLAN_MAX_STA_COUNT) + list_move_tail(&pkt->list, &local_list); + } + spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); + + list_for_each_entry(pkt, &local_list, list) { + list_del(&pkt->list); + buf = pkt->Rxpkt; + while (buf) { + next_buf = cdf_nbuf_queue_next(buf); + cdf_nbuf_free(buf); + buf = next_buf; + } + cds_free_ol_rx_pkt(pSchedContext, pkt); + } +} + +/** + * cds_rx_from_queue() - function to process pending Rx packets + * @pSchedContext: Pointer to the global CDS Sched Context + * + * This api traverses the pending buffer list and calling the callback. + * This callback would essentially send the packet to HDD. + * + * Return: none + */ +static void cds_rx_from_queue(p_cds_sched_context pSchedContext) +{ + struct cds_ol_rx_pkt *pkt; + uint16_t sta_id; + + spin_lock_bh(&pSchedContext->ol_rx_queue_lock); + while (!list_empty(&pSchedContext->ol_rx_thread_queue)) { + pkt = list_first_entry(&pSchedContext->ol_rx_thread_queue, + struct cds_ol_rx_pkt, list); + list_del(&pkt->list); + spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); + sta_id = pkt->staId; + pkt->callback(pkt->context, pkt->Rxpkt, sta_id); + cds_free_ol_rx_pkt(pSchedContext, pkt); + spin_lock_bh(&pSchedContext->ol_rx_queue_lock); + } + spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); +} + +/** + * cds_ol_rx_thread() - cds main tlshim rx thread + * @Arg: pointer to the global CDS Sched Context + * + * This api is the thread handler for Tlshim Data packet processing. + * + * Return: thread exit code + */ +static int cds_ol_rx_thread(void *arg) +{ + p_cds_sched_context pSchedContext = (p_cds_sched_context) arg; + unsigned long pref_cpu = 0; + bool shutdown = false; + int status, i; + unsigned int num_cpus; + + set_user_nice(current, -1); +#ifdef MSM_PLATFORM + set_wake_up_idle(true); +#endif + + num_cpus = num_possible_cpus(); + /* 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; + if (num_cpus <= CDS_CORE_PER_CLUSTER) + break; + } + if (pref_cpu != 0 && (!cds_set_cpus_allowed_ptr(current, pref_cpu))) + affine_cpu = pref_cpu; + + if (!arg) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Bad Args passed", __func__); + return 0; + } + + complete(&pSchedContext->ol_rx_start_event); + + while (!shutdown) { + status = + wait_event_interruptible(pSchedContext->ol_rx_wait_queue, + test_bit(RX_POST_EVENT_MASK, + &pSchedContext->ol_rx_event_flag) + || test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->ol_rx_event_flag)); + if (status == -ERESTARTSYS) + break; + + clear_bit(RX_POST_EVENT_MASK, &pSchedContext->ol_rx_event_flag); + while (true) { + if (test_bit(RX_SHUTDOWN_EVENT_MASK, + &pSchedContext->ol_rx_event_flag)) { + clear_bit(RX_SHUTDOWN_EVENT_MASK, + &pSchedContext->ol_rx_event_flag); + if (test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->ol_rx_event_flag)) { + clear_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->ol_rx_event_flag); + complete + (&pSchedContext->ol_suspend_rx_event); + } + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Shutting down OL RX Thread", + __func__); + shutdown = true; + break; + } + cds_rx_from_queue(pSchedContext); + + if (test_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->ol_rx_event_flag)) { + clear_bit(RX_SUSPEND_EVENT_MASK, + &pSchedContext->ol_rx_event_flag); + spin_lock(&pSchedContext->ol_rx_thread_lock); + complete(&pSchedContext->ol_suspend_rx_event); + INIT_COMPLETION + (pSchedContext->ol_resume_rx_event); + spin_unlock(&pSchedContext->ol_rx_thread_lock); + wait_for_completion_interruptible + (&pSchedContext->ol_resume_rx_event); + } + break; + } + } + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Exiting CDS OL rx thread", __func__); + complete_and_exit(&pSchedContext->ol_rx_shutdown, 0); +} +#endif + +/** + * cds_sched_close() - close the cds scheduler + * @p_cds_context: Pointer to the global CDS Context + * + * This api closes the CDS Scheduler upon successful closing: + * - All the message queues are flushed + * - The Main Controller thread is closed + * - The Tx thread is closed + * + * + * Return: cdf status + */ +CDF_STATUS cds_sched_close(void *p_cds_context) +{ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: invoked", __func__); + if (gp_cds_sched_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: gp_cds_sched_context == NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + /* shut down MC Thread */ + set_bit(MC_SHUTDOWN_EVENT_MASK, &gp_cds_sched_context->mcEventFlag); + set_bit(MC_POST_EVENT_MASK, &gp_cds_sched_context->mcEventFlag); + wake_up_interruptible(&gp_cds_sched_context->mcWaitQueue); + /* Wait for MC to exit */ + wait_for_completion(&gp_cds_sched_context->McShutdown); + gp_cds_sched_context->McThread = 0; + + /* Clean up message queues of MC thread */ + cds_sched_flush_mc_mqs(gp_cds_sched_context); + + /* Deinit all the queues */ + cds_sched_deinit_mqs(gp_cds_sched_context); + +#ifdef QCA_CONFIG_SMP + /* Shut down Tlshim Rx thread */ + set_bit(RX_SHUTDOWN_EVENT_MASK, &gp_cds_sched_context->ol_rx_event_flag); + set_bit(RX_POST_EVENT_MASK, &gp_cds_sched_context->ol_rx_event_flag); + wake_up_interruptible(&gp_cds_sched_context->ol_rx_wait_queue); + wait_for_completion_interruptible + (&gp_cds_sched_context->ol_rx_shutdown); + gp_cds_sched_context->ol_rx_thread = NULL; + cds_drop_rxpkt_by_staid(gp_cds_sched_context, WLAN_MAX_STA_COUNT); + cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); + unregister_hotcpu_notifier(&cds_cpu_hotplug_notifier); +#endif + return CDF_STATUS_SUCCESS; +} /* cds_sched_close() */ + +/** + * cds_sched_init_mqs() - initialize the cds scheduler message queues + * @p_cds_sched_context: Pointer to the Scheduler Context. + * + * This api initializes the cds scheduler message queues. + * + * Return: CDF status + */ +CDF_STATUS cds_sched_init_mqs(p_cds_sched_context pSchedContext) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + /* Now intialize all the message queues */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the WMA MC Message queue", __func__); + vStatus = cds_mq_init(&pSchedContext->wmaMcMq); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to init WMA MC Message queue", __func__); + CDF_ASSERT(0); + return vStatus; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the PE MC Message queue", __func__); + vStatus = cds_mq_init(&pSchedContext->peMcMq); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to init PE MC Message queue", __func__); + CDF_ASSERT(0); + return vStatus; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the SME MC Message queue", __func__); + vStatus = cds_mq_init(&pSchedContext->smeMcMq); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to init SME MC Message queue", __func__); + CDF_ASSERT(0); + return vStatus; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Initializing the SYS MC Message queue", __func__); + vStatus = cds_mq_init(&pSchedContext->sysMcMq); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to init SYS MC Message queue", __func__); + CDF_ASSERT(0); + return vStatus; + } + + return CDF_STATUS_SUCCESS; +} /* cds_sched_init_mqs() */ + +/** + * cds_sched_deinit_mqs() - Deinitialize the cds scheduler message queues + * @p_cds_sched_context: Pointer to the Scheduler Context. + * + * Return: none + */ +void cds_sched_deinit_mqs(p_cds_sched_context pSchedContext) +{ + /* Now de-intialize all message queues */ + + /* MC WMA */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the WMA MC Message queue", __func__); + cds_mq_deinit(&pSchedContext->wmaMcMq); + /* MC PE */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the PE MC Message queue", __func__); + cds_mq_deinit(&pSchedContext->peMcMq); + /* MC SME */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the SME MC Message queue", __func__); + cds_mq_deinit(&pSchedContext->smeMcMq); + /* MC SYS */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s De-Initializing the SYS MC Message queue", __func__); + cds_mq_deinit(&pSchedContext->sysMcMq); + +} /* cds_sched_deinit_mqs() */ + +/** + * cds_sched_flush_mc_mqs() - flush all the MC thread message queues + * @pSchedContext: Pointer to global cds context + * + * Return: none + */ +void cds_sched_flush_mc_mqs(p_cds_sched_context pSchedContext) +{ + p_cds_msg_wrapper pMsgWrapper = NULL; + p_cds_contextType cds_ctx; + + /* Here each of the MC thread MQ shall be drained and returned to the + * Core. Before returning a wrapper to the Core, the CDS message shall + * be freed first + */ + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + ("Flushing the MC Thread message queue")); + + if (NULL == pSchedContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: pSchedContext is NULL", __func__); + return; + } + + cds_ctx = (p_cds_contextType) (pSchedContext->pVContext); + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: cds_ctx is NULL", __func__); + return; + } + + /* Flush the SYS Mq */ + while (NULL != (pMsgWrapper = cds_mq_get(&pSchedContext->sysMcMq))) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Freeing MC SYS message type %d ", __func__, + pMsgWrapper->pVosMsg->type); + cds_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the WMA Mq */ + while (NULL != (pMsgWrapper = cds_mq_get(&pSchedContext->wmaMcMq))) { + if (pMsgWrapper->pVosMsg != NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Freeing MC WMA MSG message type %d", + __func__, pMsgWrapper->pVosMsg->type); + if (pMsgWrapper->pVosMsg->bodyptr) { + cdf_mem_free((void *)pMsgWrapper-> + pVosMsg->bodyptr); + } + + pMsgWrapper->pVosMsg->bodyptr = NULL; + pMsgWrapper->pVosMsg->bodyval = 0; + pMsgWrapper->pVosMsg->type = 0; + } + cds_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + + /* Flush the PE Mq */ + while (NULL != (pMsgWrapper = cds_mq_get(&pSchedContext->peMcMq))) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Freeing MC PE MSG message type %d", __func__, + pMsgWrapper->pVosMsg->type); + pe_free_msg(cds_ctx->pMACContext, + (tSirMsgQ *) pMsgWrapper->pVosMsg); + cds_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } + /* Flush the SME Mq */ + while (NULL != (pMsgWrapper = cds_mq_get(&pSchedContext->smeMcMq))) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_INFO, + "%s: Freeing MC SME MSG message type %d", __func__, + pMsgWrapper->pVosMsg->type); + sme_free_msg(cds_ctx->pMACContext, pMsgWrapper->pVosMsg); + cds_core_return_msg(pSchedContext->pVContext, pMsgWrapper); + } +} /* cds_sched_flush_mc_mqs() */ + +/** + * get_cds_sched_ctxt() - get cds scheduler context + * + * Return: none + */ +p_cds_sched_context get_cds_sched_ctxt(void) +{ + /* Make sure that Vos Scheduler context has been initialized */ + if (gp_cds_sched_context == NULL) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: gp_cds_sched_context == NULL", __func__); + + return gp_cds_sched_context; +} + +/** + * cds_ssr_protect_init() - initialize ssr protection debug functionality + * + * Return: + * void + */ +void cds_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++; + } +} + +/** + * cds_print_external_threads() - print external threads stuck in driver + * + * Return: + * void + */ + +static void cds_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); +} + +/** + * cds_ssr_protect() - start ssr protection + * @caller_func: name of calling function. + * + * This function is called to keep track of active driver entry points + * + * Return: none + */ +void cds_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) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Could not track PID %d call %s: log is full", + current->pid, caller_func); +} + +/** + * cds_ssr_unprotect() - stop ssr protection + * @caller_func: name of calling function. + * + * Return: none + */ +void cds_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) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Untracked call %s", caller_func); +} + +/** + * cds_is_ssr_ready() - check if the calling execution can proceed with ssr + * + * @caller_func: name of calling function. + * + * Return: true if there is no active entry points in driver + * false if there is at least one active entry in driver + */ +bool cds_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + cds_print_external_threads(); + return false; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "Allowing SSR for %s", caller_func); + + return true; +} diff --git a/core/cds/src/cds_utils.c b/core/cds/src/cds_utils.c new file mode 100644 index 000000000000..fd186ae6bbf7 --- /dev/null +++ b/core/cds/src/cds_utils.c @@ -0,0 +1,1135 @@ +/* + * 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: cds_utils.c + + OVERVIEW: This source file contains definitions for CDS 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: + cds_crypto_init() - Initializes Crypto module + cds_crypto_deinit() - De-initializes Crypto module + cds_rand_get_bytes() - Generates random byte + cds_sha1_hmac_str() - Generate the HMAC-SHA1 of a string given a key + cds_encrypt_aes() - Generate AES Encrypted byte stream + cds_decrypt_aes() - Decrypts an AES Encrypted byte stream + + DEPENDENCIES: + ============================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ + +#include "cdf_trace.h" +#include "cds_utils.h" +#include "cdf_memory.h" +#include "cds_crypto.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cds_ieee80211_common.h" +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define AAD_LEN 20 +#define IV_SIZE_AES_128 16 +#define CMAC_IPN_LEN 6 +#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + Function Definitions and Documentation + * -------------------------------------------------------------------------*/ +#ifdef CONFIG_ICNSS +#ifdef WLAN_FEATURE_11W +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; + } +} + +static void cds_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); + + memcpy(mac, x, CMAC_TLEN); +} +#endif +#endif + +/*-------------------------------------------------------------------------- + + \brief cds_crypto_init() - Initializes Crypto module + + The cds_crypto_init() function initializes Crypto module. + + \param phCryptProv - pointer to the Crypt handle + + \return CDF_STATUS_SUCCESS - Successfully generated random memory. + + CDF_STATUS_E_FAULT - pbBuf is an invalid pointer. + + CDF_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***CDF_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ +CDF_STATUS cds_crypto_init(uint32_t *phCryptProv) +{ + CDF_STATUS uResult = CDF_STATUS_E_FAILURE; + + /* This implementation doesn't require a crypto context */ + *phCryptProv = 0; + uResult = CDF_STATUS_SUCCESS; + return (uResult); +} + +CDF_STATUS cds_crypto_deinit(uint32_t hCryptProv) +{ + CDF_STATUS uResult = CDF_STATUS_E_FAILURE; + + /* CryptReleaseContext succeeded */ + uResult = CDF_STATUS_SUCCESS; + + return (uResult); +} + +/*-------------------------------------------------------------------------- + + \brief cds_rand_get_bytes() - Generates random byte + + The cds_rand_get_bytes() function generate random bytes. + + Buffer should be allocated before calling cds_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 CDF_STATUS_SUCCESS - Successfully generated random memory. + + CDF_STATUS_E_FAULT - pbBuf is an invalid pointer. + + CDF_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***CDF_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ +CDF_STATUS +cds_rand_get_bytes(uint32_t cryptHandle, uint8_t *pbBuf, uint32_t numBytes) +{ + CDF_STATUS uResult = CDF_STATUS_E_FAILURE; + + /* check for invalid pointer */ + if (NULL == pbBuf) { + uResult = CDF_STATUS_E_FAULT; + return (uResult); + } + + get_random_bytes(pbBuf, numBytes); + /* "Random sequence generated." */ + uResult = CDF_STATUS_SUCCESS; + return (uResult); +} + +#ifdef WLAN_FEATURE_11W +uint8_t cds_get_mmie_size() +{ + return sizeof(struct ieee80211_mmie); +} + +/*-------------------------------------------------------------------------- + + \brief cds_increase_seq() - Increase the IPN aka Sequence number by one unit + + The cds_increase_seq() function increases the IPN by one unit. + + \param ipn - pointer to the IPN aka Sequence number [6 bytes] + + --------------------------------------------------------------------------*/ +static void cds_increase_seq(uint8_t *ipn) +{ + uint64_t value = 0; + if (ipn) { + value = (0xffffffffffff) & (*((uint64_t *) ipn)); + value = value + 1; + cdf_mem_copy(ipn, &value, IEEE80211_MMIE_IPNLEN); + } +} + +/*-------------------------------------------------------------------------- + + \brief cds_attach_mmie() - attches the complete MMIE at the end of frame + + The cds_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 true on success and false on + failure. + + --------------------------------------------------------------------------*/ + +bool +cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id, + uint8_t *frm, uint8_t *efrm, uint16_t frmLen) +{ + struct ieee80211_mmie *mmie; + struct ieee80211_frame *wh; + uint8_t aad[AAD_LEN], mic[CMAC_TLEN], *input = NULL; + uint8_t previous_ipn[IEEE80211_MMIE_IPNLEN] = { 0 }; + uint16_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))) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid frame length", __func__); + return 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 + */ + cdf_mem_copy(&previous_ipn[0], ipn, IEEE80211_MMIE_IPNLEN); + cds_increase_seq(ipn); + cdf_mem_copy(mmie->sequence_number, ipn, IEEE80211_MMIE_IPNLEN); + + /* + * Calculate MIC and then copy + */ + tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 */ + cdf_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 = (uint8_t *) cdf_mem_malloc(nBytes); + if (NULL == input) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed", __func__); + ret = CDF_STATUS_E_NOMEM; + goto err_tfm; + } + + /* + * Copy the AAD, Management frame body, and + * MMIE with 8 bit MIC zeroed out + */ + cdf_mem_zero(input, nBytes); + cdf_mem_copy(input, aad, AAD_LEN); + /* Copy Management Frame Body and MMIE without MIC */ + cdf_mem_copy(input + AAD_LEN, + (uint8_t *) (efrm - + (frmLen - sizeof(struct ieee80211_frame))), + nBytes - AAD_LEN - CMAC_TLEN); + + cds_cmac_calc_mic(tfm, input, nBytes, mic); + cdf_mem_free(input); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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]); + cdf_mem_copy(mmie->mic, mic, IEEE80211_MMIE_MICLEN); + +err_tfm: + if (ret) { + cdf_mem_copy(ipn, previous_ipn, IEEE80211_MMIE_IPNLEN); + } + + if (tfm) + cds_crypto_free_cipher(tfm); + return !ret ? true : false; +} + +bool +cds_is_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm, uint8_t *efrm) +{ + struct ieee80211_mmie *mmie; + struct ieee80211_frame *wh; + uint8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input; + uint16_t nBytes = 0; + int ret = 0; + struct crypto_cipher *tfm; + + /* Check if frame is invalid length */ + if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Invalid frame length"); + return false; + } + + mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie)); + + /* Check Element ID */ + if ((mmie->element_id != IEEE80211_ELEMID_MMIE) || + (mmie->length != (sizeof(*mmie) - 2))) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "IE is not Mgmt MIC IE or Invalid length"); + /* IE is not Mgmt MIC IE or invalid length */ + return false; + } + + /* Validate IPN */ + rx_ipn = mmie->sequence_number; + if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0) { + /* Replay error */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 false; + } + tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_alloc_cipher failed (%d)", ret); + goto err_tfm; + } + + ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 */ + cdf_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 - (uint8_t *) (wh + 1)); + input = (uint8_t *) cdf_mem_malloc(nBytes); + if (NULL == input) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Memory allocation failed"); + ret = CDF_STATUS_E_NOMEM; + goto err_tfm; + } + + /* Copy the AAD, MMIE with 8 bit MIC zeroed out */ + cdf_mem_zero(input, nBytes); + cdf_mem_copy(input, aad, AAD_LEN); + cdf_mem_copy(input + AAD_LEN, (uint8_t *) (wh + 1), + nBytes - AAD_LEN - CMAC_TLEN); + + cds_cmac_calc_mic(tfm, input, nBytes, mic); + cdf_mem_free(input); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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 false; + } + + /* Update IPN */ + cdf_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN); + +err_tfm: + if (tfm) + cds_crypto_free_cipher(tfm); + + return !ret ? true : false; +} + +#endif /* WLAN_FEATURE_11W */ +/** + * cds_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 CDF_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(uint8_t *key, uint8_t ksize, char *plaintext, uint8_t psize, + uint8_t *output, uint8_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); + + tfm = cds_crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); + if (IS_ERR(tfm)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_alloc_ahash failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "failed to kzalloc hash_buff"); + ret = -ENOMEM; + goto err_hash_buf; + } + + memset(hash_result, 0, 64); + memcpy(hash_buff, plaintext, psize); + sg_init_one(&sg, hash_buff, psize); + + if (ksize) { + crypto_ahash_clear_flags(tfm, ~0); + ret = cds_crypto_ahash_setkey(tfm, key, ksize); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_ahash_setkey failed"); + goto err_setkey; + } + } + + ahash_request_set_crypt(req, &sg, hash_result, psize); + ret = cds_crypto_ahash_digest(req); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + INIT_COMPLETION(tresult.completion); + break; + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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: + cds_crypto_free_ahash(tfm); +err_tfm: + return ret; +} + +CDF_STATUS cds_sha1_hmac_str(uint32_t cryptHandle, /* Handle */ + uint8_t *pText, /* pointer to data stream */ + uint32_t textLen, /* length of data stream */ + uint8_t *pKey, /* pointer to authentication key */ + uint32_t keyLen, /* length of authentication key */ + uint8_t digest[CDS_DIGEST_SHA1_SIZE]) +{ /* caller digest to be filled in */ + int ret = 0; + + ret = hmac_sha1(pKey, /* uint8_t *key, */ + (uint8_t) keyLen, /* uint8_t ksize, */ + (char *)pText, /* char *plaintext, */ + (uint8_t) textLen, /* uint8_t psize, */ + digest, /* uint8_t *output, */ + CDS_DIGEST_SHA1_SIZE /* uint8_t outlen */ + ); + + if (ret != 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "hmac_sha1() call failed"); + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_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 CDF_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(uint8_t *key, uint8_t ksize, char *plaintext, uint8_t psize, + uint8_t *output, uint8_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); + + tfm = cds_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, + CRYPTO_ALG_TYPE_AHASH_MASK); + if (IS_ERR(tfm)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_alloc_ahash failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "failed to kzalloc hash_buff"); + ret = -ENOMEM; + goto err_hash_buf; + } + + memset(hash_result, 0, 64); + memcpy(hash_buff, plaintext, psize); + sg_init_one(&sg, hash_buff, psize); + + if (ksize) { + crypto_ahash_clear_flags(tfm, ~0); + ret = cds_crypto_ahash_setkey(tfm, key, ksize); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_ahash_setkey failed"); + goto err_setkey; + } + } + + ahash_request_set_crypt(req, &sg, hash_result, psize); + ret = cds_crypto_ahash_digest(req); + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + INIT_COMPLETION(tresult.completion); + break; + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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: + cds_crypto_free_ahash(tfm); +err_tfm: + return ret; +} + +CDF_STATUS cds_md5_hmac_str(uint32_t cryptHandle, /* Handle */ + uint8_t *pText, /* pointer to data stream */ + uint32_t textLen, /* length of data stream */ + uint8_t *pKey, /* pointer to authentication key */ + uint32_t keyLen, /* length of authentication key */ + uint8_t digest[CDS_DIGEST_MD5_SIZE]) +{ /* caller digest to be filled in */ + int ret = 0; + + ret = hmac_md5(pKey, /* uint8_t *key, */ + (uint8_t) keyLen, /* uint8_t ksize, */ + (char *)pText, /* char *plaintext, */ + (uint8_t) textLen, /* uint8_t psize, */ + digest, /* uint8_t *output, */ + CDS_DIGEST_MD5_SIZE /* uint8_t outlen */ + ); + + if (ret != 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "hmac_md5() call failed"); + return CDF_STATUS_E_FAULT; + } + + return CDF_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 cds_encrypt_aes() - Generate AES Encrypted byte stream + + The cds_encrypt_aes() function generates the encrypted byte stream for given text. + + Buffer should be allocated before calling cds_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 CDF_STATUS_SUCCESS - Successfully generated random memory. + + CDF_STATUS_E_FAULT - pbBuf is an invalid pointer. + + CDF_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***CDF_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ + +CDF_STATUS cds_encrypt_aes(uint32_t cryptHandle, /* Handle */ + uint8_t *pPlainText, /* pointer to data stream */ + uint8_t *pCiphertext, uint8_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); + + tfm = cds_crypto_alloc_ablkcipher("cbc(aes)", 0, 0); + if (IS_ERR(tfm)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_alloc_ablkcipher failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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: + cds_ablkcipher_request_free(req); +err_req: + cds_crypto_free_ablkcipher(tfm); +err_tfm: + /* return ret; */ + if (ret != 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s() call failed", __func__); + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief cds_decrypt_aes() - Decrypts an AES Encrypted byte stream + + The cds_decrypt_aes() function decrypts the encrypted byte stream. + + Buffer should be allocated before calling cds_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 CDF_STATUS_SUCCESS - Successfully generated random memory. + + CDF_STATUS_E_FAULT - pbBuf is an invalid pointer. + + CDF_STATUS_E_FAILURE - default return value if it fails due to + unknown reasons + + ***CDF_STATUS_E_RESOURCES - System resources (other than memory) + are unavailable + \sa + + ( *** return value not considered yet ) + --------------------------------------------------------------------------*/ + +CDF_STATUS cds_decrypt_aes(uint32_t cryptHandle, /* Handle */ + uint8_t *pText, /* pointer to data stream */ + uint8_t *pDecrypted, uint8_t *pKey) +{ /* pointer to authentication key */ +/* CDF_STATUS uResult = CDF_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); + + tfm = cds_crypto_alloc_ablkcipher("cbc(aes)", 0, 0); + if (IS_ERR(tfm)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "crypto_alloc_ablkcipher failed"); + ret = PTR_ERR(tfm); + goto err_tfm; + } + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_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: + cds_ablkcipher_request_free(req); +err_req: + cds_crypto_free_ablkcipher(tfm); +err_tfm: + /* return ret; */ + if (ret != 0) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s() call failed", __func__); + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_SUCCESS; +} + +uint32_t cds_chan_to_freq(uint8_t chan) +{ + if (chan < CDS_24_GHZ_CHANNEL_14) /* ch 0 - ch 13 */ + return CDS_24_GHZ_BASE_FREQ + chan * CDS_CHAN_SPACING_5MHZ; + else if (chan == CDS_24_GHZ_CHANNEL_14) /* ch 14 */ + return CDS_CHAN_14_FREQ; + else if (chan < CDS_24_GHZ_CHANNEL_27) /* ch 15 - ch 26 */ + return CDS_CHAN_15_FREQ + + (chan - CDS_24_GHZ_CHANNEL_15) * CDS_CHAN_SPACING_20MHZ; + else if (chan == CDS_5_GHZ_CHANNEL_170) + return CDS_CHAN_170_FREQ; + else + return CDS_5_GHZ_BASE_FREQ + chan * CDS_CHAN_SPACING_5MHZ; +} + +uint8_t cds_freq_to_chan(uint32_t freq) +{ + uint8_t chan; + + if (freq > CDS_24_GHZ_BASE_FREQ && freq < CDS_CHAN_14_FREQ) + chan = ((freq - CDS_24_GHZ_BASE_FREQ) / CDS_CHAN_SPACING_5MHZ); + else if (freq == CDS_CHAN_14_FREQ) + chan = CDS_24_GHZ_CHANNEL_14; + else if ((freq > CDS_24_GHZ_BASE_FREQ) && (freq < CDS_5_GHZ_BASE_FREQ)) + chan = (((freq - CDS_CHAN_15_FREQ) / CDS_CHAN_SPACING_20MHZ) + + CDS_24_GHZ_CHANNEL_15); + else + chan = (freq - CDS_5_GHZ_BASE_FREQ) / CDS_CHAN_SPACING_5MHZ; + return chan; +} + +uint8_t cds_chan_to_band(uint32_t chan) +{ + if (chan <= CDS_24_GHZ_CHANNEL_14) + return CDS_BAND_2GHZ; + + return CDS_BAND_5GHZ; +} diff --git a/core/cds/src/i_cds_packet.h b/core/cds/src/i_cds_packet.h new file mode 100644 index 000000000000..23858fedd2bc --- /dev/null +++ b/core/cds/src/i_cds_packet.h @@ -0,0 +1,76 @@ +/* + * 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_CDS_PACKET_H ) +#define __I_CDS_PACKET_H + +/**========================================================================= + + \file i_cds_packet.h + + \brief Connectivity driver services network packet APIs + + Network Protocol packet/buffer internal include file + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_types.h" +/* + * Rx Packet Struct + */ +typedef struct { + uint8_t channel; + uint8_t snr; + uint32_t rssi; + uint32_t timestamp; + uint8_t *mpdu_hdr_ptr; + uint8_t *mpdu_data_ptr; + uint32_t mpdu_len; + uint32_t mpdu_hdr_len; + uint32_t mpdu_data_len; + uint8_t offloadScanLearn : 1; + uint8_t roamCandidateInd : 1; + uint8_t scan : 1; + uint8_t scan_src; + uint8_t dpuFeedback; + uint8_t sessionId; + uint32_t tsf_delta; +} t_packetmeta, *tp_packetmeta; + +/* implementation specific cds packet type */ +struct cds_pkt_t { + /* Packet Meta Information */ + t_packetmeta pkt_meta; + + /* Pointer to Packet */ + void *pkt_buf; +}; + +#endif /* !defined( __I_CDS_PACKET_H ) */ diff --git a/core/cds/src/queue.h b/core/cds/src/queue.h new file mode 100644 index 000000000000..73200429eaf7 --- /dev/null +++ b/core/cds/src/queue.h @@ -0,0 +1,571 @@ +/* + * 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/core/dp/htt/htt.c b/core/dp/htt/htt.c new file mode 100644 index 000000000000..06d0a7ea1eba --- /dev/null +++ b/core/dp/htt/htt.c @@ -0,0 +1,562 @@ +/* + * 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 /* cdf_mem_malloc */ +#include /* cdf_device_t, cdf_print */ + +#include /* htt_tx_msdu_desc_t */ +#include +#include /* ol_tx_dowload_done_ll, etc. */ +#include + +#include +#include "hif.h" + +#define HTT_HTC_PKT_POOL_INIT_SIZE 100 /* enough for a large A-MPDU */ + +A_STATUS(*htt_h2t_rx_ring_cfg_msg)(struct htt_pdev_t *pdev); + +#ifdef IPA_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_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 = cdf_mem_malloc(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; + cdf_mem_free(pkt); + pkt = next; + } + pdev->htt_htc_pkt_freelist = NULL; +} + +#ifdef ATH_11AC_TXCOMPACT +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); +} + +void htt_htc_misc_pkt_pool_free(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt_union *pkt, *next; + cdf_nbuf_t netbuf; + pkt = pdev->htt_htc_pkt_misclist; + + while (pkt) { + next = pkt->u.next; + netbuf = (cdf_nbuf_t) (pkt->u.pkt.htc_pkt.pNetBufContext); + cdf_nbuf_unmap(pdev->osdev, netbuf, CDF_DMA_TO_DEVICE); + cdf_nbuf_free(netbuf); + cdf_mem_free(pkt); + pkt = next; + } + pdev->htt_htc_pkt_misclist = NULL; +} +#endif + +/** + * htt_pdev_alloc() - allocate HTT pdev + * @txrx_pdev: txrx pdev + * @ctrl_pdev: cfg pdev + * @htc_pdev: HTC pdev + * @osdev: os device + * + * Return: HTT pdev handle + */ +htt_pdev_handle +htt_pdev_alloc(ol_txrx_pdev_handle txrx_pdev, + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, cdf_device_t osdev) +{ + struct htt_pdev_t *pdev; + + pdev = cdf_mem_malloc(sizeof(*pdev)); + if (!pdev) + goto fail1; + + pdev->osdev = osdev; + pdev->ctrl_pdev = ctrl_pdev; + pdev->txrx_pdev = txrx_pdev; + pdev->htc_pdev = htc_pdev; + + cdf_mem_set(&pdev->stats, sizeof(pdev->stats), 0); + pdev->htt_htc_pkt_freelist = NULL; +#ifdef ATH_11AC_TXCOMPACT + pdev->htt_htc_pkt_misclist = NULL; +#endif + 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); + cdf_print("is_full_reorder_offloaded? %d\n", + (int)pdev->cfg.is_full_reorder_offload); + + pdev->cfg.ce_classify_enabled = + ol_cfg_is_ce_classify_enabled(ctrl_pdev); + cdf_print("ce_classify_enabled %d\n", + pdev->cfg.ce_classify_enabled); + + pdev->targetdef = htc_get_targetdef(htc_pdev); +#if defined(HELIUMPLUS_PADDR64) + /* TODO: OKA: Remove hard-coding */ + HTT_SET_WIFI_IP(pdev, 2, 0); +#endif /* defined(HELIUMPLUS_PADDR64) */ + + /* + * 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 + + return pdev; + +fail2: + cdf_mem_free(pdev); + +fail1: + return NULL; + +} + +/** + * htt_attach() - Allocate and setup HTT TX/RX descriptors + * @pdev: pdev ptr + * @desc_pool_size: size of tx descriptors + * + * Return: 0 for success or error code. + */ +int +htt_attach(struct htt_pdev_t *pdev, int desc_pool_size) +{ + int i; + enum wlan_frm_fmt frm_type; + int ret = 0; + + ret = htt_tx_attach(pdev, desc_pool_size); + if (ret) + goto fail1; + + ret = htt_rx_attach(pdev); + if (ret) + goto fail2; + + 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 = cdf_mem_malloc(sizeof(*pkt)); + if (!pkt) + break; + htt_htc_pkt_free(pdev, &pkt->u.pkt); + } + + /* + * 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. + */ + + /* 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 { + cdf_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 0; + +fail2: + htt_tx_detach(pdev); + +fail1: + return ret; +} + +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 defined(HELIUMPLUS_PADDR64) + /* + * Send the frag_desc info to target. + */ + htt_h2t_frag_desc_bank_cfg_msg(pdev); +#endif /* defined(HELIUMPLUS_PADDR64) */ + + + /* + * 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); +} + +/** + * htt_pdev_free() - Free HTT pdev + * @pdev: htt pdev + * + * Return: none + */ +void htt_pdev_free(htt_pdev_handle pdev) +{ + cdf_mem_free(pdev); +} + +void htt_detach_target(htt_pdev_handle pdev) +{ +} + +#ifdef WLAN_FEATURE_FASTPATH +/** + * htt_pkt_dl_len_get() HTT packet download length for fastpath case + * + * @htt_dev: pointer to htt device. + * + * As fragment one already downloaded HTT/HTC header, download length is + * remaining bytes. + * + * Return: download length + */ +int htt_pkt_dl_len_get(struct htt_pdev_t *htt_dev) +{ + return htt_dev->download_len - sizeof(struct htt_host_tx_desc_t); +} +#else +int htt_pkt_dl_len_get(struct htt_pdev_t *htt_dev) +{ + return 0; +} +#endif + +int htt_htc_attach(struct htt_pdev_t *pdev) +{ + HTC_SERVICE_CONNECT_REQ connect; + HTC_SERVICE_CONNECT_RESP response; + A_STATUS status; + + cdf_mem_set(&connect, sizeof(connect), 0); + cdf_mem_set(&response, sizeof(response), 0); + + 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; + + /* 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 htc_send_pkt 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 */ +#ifndef HIF_SDIO + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; +#endif + + /* connect to control service */ + connect.ServiceID = HTT_DATA_MSG_SVC; + + status = htc_connect_service(pdev->htc_pdev, &connect, &response); + + if (status != A_OK) + return -EIO; /* failure */ + + pdev->htc_endpoint = response.Endpoint; +#if defined(HIF_PCI) + hif_save_htc_htt_config_endpoint(pdev->htc_endpoint); +#endif + + return 0; /* success */ +} + +#if HTT_DEBUG_LEVEL > 5 +void htt_display(htt_pdev_handle pdev, int indent) +{ + cdf_print("%*s%s:\n", indent, " ", "HTT"); + cdf_print("%*stx desc pool: %d elems of %d bytes, %d allocated\n", + indent + 4, " ", + pdev->tx_descs.pool_elems, + pdev->tx_descs.size, pdev->tx_descs.alloc_cnt); + cdf_print("%*srx ring: space for %d elems, filled with %d buffers\n", + indent + 4, " ", + pdev->rx_ring.size, pdev->rx_ring.fill_level); + cdf_print("%*sat %p (%#x paddr)\n", indent + 8, " ", + pdev->rx_ring.buf.paddrs_ring, pdev->rx_ring.base_paddr); + cdf_print("%*snetbuf ring @ %p\n", indent + 8, " ", + pdev->rx_ring.buf.netbufs_ring); + cdf_print("%*sFW_IDX shadow register: vaddr = %p, paddr = %#x\n", + indent + 8, " ", + pdev->rx_ring.alloc_idx.vaddr, pdev->rx_ring.alloc_idx.paddr); + cdf_print("%*sSW enqueue idx= %d, SW dequeue idx: 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_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) { + cdf_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) { + cdf_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, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + uint32_t *rx_proc_done_idx_paddr) +{ + /* Release allocated resource to client */ + *tx_comp_ring_base_paddr = + (uint32_t) pdev->ipa_uc_tx_rsc.tx_comp_base.paddr; + *tx_comp_ring_size = + (uint32_t) ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev); + *tx_num_alloc_buffer = (uint32_t) pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt; + *rx_rdy_ring_base_paddr = + (uint32_t) pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr; + *rx_rdy_ring_size = (uint32_t) pdev->ipa_uc_rx_rsc.rx_ind_ring_size; + *rx_proc_done_idx_paddr = + (uint32_t) pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr; + + /* Get copy engine, bus resource */ + htc_ipa_get_ce_resource(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, + uint32_t ipa_uc_tx_doorbell_paddr, + uint32_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_OFFLOAD */ diff --git a/core/dp/htt/htt_fw_stats.c b/core/dp/htt/htt_fw_stats.c new file mode 100644 index 000000000000..aee627d0e617 --- /dev/null +++ b/core/dp/htt/htt_fw_stats.c @@ -0,0 +1,1155 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* cdf_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 char *bw_str_arr[] = {"20MHz", "40MHz", "80MHz", "160MHz"}; + +/* + * Defined the macro tx_rate_stats_print_cmn() + * so that this could be used in both + * htt_t2h_stats_tx_rate_stats_print() & + * htt_t2h_stats_tx_rate_stats_print_v2(). + * Each of these functions take a different structure as argument, + * but with common fields in the structures--so using a macro + * to bypass the strong type-checking of a function seems a simple + * trick to use to avoid the code duplication. + */ +#define tx_rate_stats_print_cmn(_tx_rate_info, _concise) \ +{ \ + int i; \ + \ + cdf_print("TX Rate Info:\n"); \ + \ + /* MCS */ \ + cdf_print("MCS counts (0..9): "); \ + cdf_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 */ \ + cdf_print("SGI counts (0..9): "); \ + cdf_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 */ \ + cdf_print("NSS counts: "); \ + cdf_print("1x1 %d, 2x2 %d, 3x3 %d\n", \ + _tx_rate_info->nss[0], \ + _tx_rate_info->nss[1], _tx_rate_info->nss[2]);\ + \ + /* BW */ \ + cdf_print("BW counts: "); \ + \ + for (i = 0; \ + i < sizeof(_tx_rate_info->bw) / sizeof(_tx_rate_info->bw[0]);\ + i++) { \ + cdf_print("%s %d ", bw_str_arr[i], _tx_rate_info->bw[i]);\ + } \ + cdf_print("\n"); \ + \ + /* Preamble */ \ + cdf_print("Preamble (O C H V) counts: "); \ + cdf_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 */ \ + cdf_print("STBC rate counts (0..9): "); \ + cdf_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 */ \ + cdf_print("LDPC Counts: "); \ + cdf_print("%d\n", _tx_rate_info->ldpc); \ + cdf_print("RTS Counts: "); \ + cdf_print("%d\n", _tx_rate_info->rts_cnt); \ + /* RSSI Values for last ack frames */ \ + cdf_print("Ack RSSI: %d\n", _tx_rate_info->ack_rssi);\ +} + +static void htt_t2h_stats_tx_rate_stats_print(wlan_dbg_tx_rate_info_t * + tx_rate_info, int concise) +{ + tx_rate_stats_print_cmn(tx_rate_info, concise); +} + +static void htt_t2h_stats_tx_rate_stats_print_v2(wlan_dbg_tx_rate_info_v2_t * + tx_rate_info, int concise) +{ + tx_rate_stats_print_cmn(tx_rate_info, concise); +} + +/* + * Defined the macro rx_rate_stats_print_cmn() + * so that this could be used in both + * htt_t2h_stats_rx_rate_stats_print() & + * htt_t2h_stats_rx_rate_stats_print_v2(). + * Each of these functions take a different structure as argument, + * but with common fields in the structures -- so using a macro + * to bypass the strong type-checking of a function seems a simple + * trick to use to avoid the code duplication. + */ +#define rx_rate_stats_print_cmn(_rx_phy_info, _concise) \ +{ \ + int i; \ + \ + cdf_print("RX Rate Info:\n"); \ + \ + /* MCS */ \ + cdf_print("MCS counts (0..9): "); \ + cdf_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 */ \ + cdf_print("SGI counts (0..9): "); \ + cdf_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 */ \ + cdf_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. */ \ + cdf_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 */ \ + cdf_print("NSTS count: "); \ + cdf_print("%d\n", _rx_phy_info->nsts); \ + \ + /* BW */ \ + cdf_print("BW counts: "); \ + for (i = 0; \ + i < sizeof(_rx_phy_info->bw) / sizeof(_rx_phy_info->bw[0]); \ + i++) { \ + cdf_print("%s %d ", bw_str_arr[i], _rx_phy_info->bw[i]);\ + } \ + cdf_print("\n"); \ + \ + /* Preamble */ \ + cdf_print("Preamble counts: "); \ + cdf_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 */ \ + cdf_print("STBC rate counts (0..9): "); \ + cdf_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 */ \ + cdf_print("LDPC TXBF Counts: "); \ + cdf_print("%d, %d\n", _rx_phy_info->ldpc, _rx_phy_info->txbf);\ + /* RSSI Values for last received frames */ \ + cdf_print("RSSI (data, mgmt): %d, %d\n", _rx_phy_info->data_rssi,\ + _rx_phy_info->mgmt_rssi); \ + \ + cdf_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)); \ + \ + cdf_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)); \ + \ + cdf_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_rx_rate_stats_print(wlan_dbg_rx_rate_info_t * + rx_phy_info, int concise) +{ + rx_rate_stats_print_cmn(rx_phy_info, concise); +} + +static void htt_t2h_stats_rx_rate_stats_print_v2(wlan_dbg_rx_rate_info_v2_t * + rx_phy_info, int concise) +{ + rx_rate_stats_print_cmn(rx_phy_info, concise); +} + +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; + + cdf_print("WAL Pdev stats:\n"); + cdf_print("\n### Tx ###\n"); + + /* Num HTT cookies queued to dispatch list */ + cdf_print("comp_queued :\t%d\n", tx->comp_queued); + /* Num HTT cookies dispatched */ + cdf_print("comp_delivered :\t%d\n", tx->comp_delivered); + /* Num MSDU queued to WAL */ + cdf_print("msdu_enqued :\t%d\n", tx->msdu_enqued); + /* Num MPDU queued to WAL */ + cdf_print("mpdu_enqued :\t%d\n", tx->mpdu_enqued); + /* Num MSDUs dropped by WMM limit */ + cdf_print("wmm_drop :\t%d\n", tx->wmm_drop); + /* Num Local frames queued */ + cdf_print("local_enqued :\t%d\n", tx->local_enqued); + /* Num Local frames done */ + cdf_print("local_freed :\t%d\n", tx->local_freed); + /* Num queued to HW */ + cdf_print("hw_queued :\t%d\n", tx->hw_queued); + /* Num PPDU reaped from HW */ + cdf_print("hw_reaped :\t%d\n", tx->hw_reaped); + /* Num underruns */ + cdf_print("mac underrun :\t%d\n", tx->underrun); + /* Num underruns */ + cdf_print("phy underrun :\t%d\n", tx->phy_underrun); + /* Num PPDUs cleaned up in TX abort */ + cdf_print("tx_abort :\t%d\n", tx->tx_abort); + /* Num MPDUs requed by SW */ + cdf_print("mpdus_requed :\t%d\n", tx->mpdus_requed); + /* Excessive retries */ + cdf_print("excess retries :\t%d\n", tx->tx_ko); + /* last data rate */ + cdf_print("last rc :\t%d\n", tx->data_rc); + /* scheduler self triggers */ + cdf_print("sched self trig :\t%d\n", tx->self_triggers); + /* SW retry failures */ + cdf_print("ampdu retry failed:\t%d\n", tx->sw_retry_failure); + /* ilegal phy rate errirs */ + cdf_print("illegal rate errs :\t%d\n", tx->illgl_rate_phy_err); + /* pdev continous excessive retries */ + cdf_print("pdev cont xretry :\t%d\n", tx->pdev_cont_xretry); + /* pdev continous excessive retries */ + cdf_print("pdev tx timeout :\t%d\n", tx->pdev_tx_timeout); + /* pdev resets */ + cdf_print("pdev resets :\t%d\n", tx->pdev_resets); + /* PPDU > txop duration */ + cdf_print("ppdu txop ovf :\t%d\n", tx->txop_ovf); + + cdf_print("\n### Rx ###\n"); + /* Cnts any change in ring routing mid-ppdu */ + cdf_print("ppdu_route_change :\t%d\n", rx->mid_ppdu_route_change); + /* Total number of statuses processed */ + cdf_print("status_rcvd :\t%d\n", rx->status_rcvd); + /* Extra frags on rings 0-3 */ + cdf_print("r0_frags :\t%d\n", rx->r0_frags); + cdf_print("r1_frags :\t%d\n", rx->r1_frags); + cdf_print("r2_frags :\t%d\n", rx->r2_frags); + cdf_print("r3_frags :\t%d\n", rx->r3_frags); + /* MSDUs / MPDUs delivered to HTT */ + cdf_print("htt_msdus :\t%d\n", rx->htt_msdus); + cdf_print("htt_mpdus :\t%d\n", rx->htt_mpdus); + /* MSDUs / MPDUs delivered to local stack */ + cdf_print("loc_msdus :\t%d\n", rx->loc_msdus); + cdf_print("loc_mpdus :\t%d\n", rx->loc_mpdus); + /* AMSDUs that have more MSDUs than the status ring size */ + cdf_print("oversize_amsdu :\t%d\n", rx->oversize_amsdu); + /* Number of PHY errors */ + cdf_print("phy_errs :\t%d\n", rx->phy_errs); + /* Number of PHY errors dropped */ + cdf_print("phy_errs dropped :\t%d\n", rx->phy_err_drop); + /* Number of mpdu errors - FCS, MIC, ENC etc. */ + cdf_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) +{ + cdf_print("Rx reorder statistics:\n"); + cdf_print(" %u non-QoS frames received\n", stats_ptr->deliver_non_qos); + cdf_print(" %u frames received in-order\n", + stats_ptr->deliver_in_order); + cdf_print(" %u frames flushed due to timeout\n", + stats_ptr->deliver_flush_timeout); + cdf_print(" %u frames flushed due to moving out of window\n", + stats_ptr->deliver_flush_oow); + cdf_print(" %u frames flushed due to receiving DELBA\n", + stats_ptr->deliver_flush_delba); + cdf_print(" %u frames discarded due to FCS error\n", + stats_ptr->fcs_error); + cdf_print(" %u frames discarded due to invalid peer\n", + stats_ptr->invalid_peer); + cdf_print + (" %u frames discarded due to duplication (non aggregation)\n", + stats_ptr->dup_non_aggr); + cdf_print(" %u frames discarded due to duplication in reorder queue\n", + stats_ptr->dup_in_reorder); + cdf_print(" %u frames discarded due to processed before\n", + stats_ptr->dup_past); + cdf_print(" %u times reorder timeout happened\n", + stats_ptr->reorder_timeout); + cdf_print(" %u times incorrect bar received\n", + stats_ptr->invalid_bar_ssn); + cdf_print(" %u times bar ssn reset happened\n", + stats_ptr->ssn_reset); + cdf_print(" %u times flushed due to peer delete\n", + stats_ptr->deliver_flush_delpeer); + cdf_print(" %u times flushed due to offload\n", + stats_ptr->deliver_flush_offload); + cdf_print(" %u times flushed due to ouf of buffer\n", + stats_ptr->deliver_flush_oob); + cdf_print(" %u MPDU's dropped due to PN check fail\n", + stats_ptr->pn_fail); + cdf_print(" %u MPDU's dropped due to lack of memory\n", + stats_ptr->store_fail); + cdf_print(" %u times tid pool alloc succeeded\n", + stats_ptr->tid_pool_alloc_succ); + cdf_print(" %u times MPDU pool alloc succeeded\n", + stats_ptr->mpdu_pool_alloc_succ); + cdf_print(" %u times MSDU pool alloc succeeded\n", + stats_ptr->msdu_pool_alloc_succ); + cdf_print(" %u times tid pool alloc failed\n", + stats_ptr->tid_pool_alloc_fail); + cdf_print(" %u times MPDU pool alloc failed\n", + stats_ptr->mpdu_pool_alloc_fail); + cdf_print(" %u times MSDU pool alloc failed\n", + stats_ptr->msdu_pool_alloc_fail); + cdf_print(" %u times tid pool freed\n", + stats_ptr->tid_pool_free); + cdf_print(" %u times MPDU pool freed\n", + stats_ptr->mpdu_pool_free); + cdf_print(" %u times MSDU pool freed\n", + stats_ptr->msdu_pool_free); + cdf_print(" %u MSDUs undelivered to HTT, queued to Rx MSDU free list\n", + stats_ptr->msdu_queued); + cdf_print(" %u MSDUs released from Rx MSDU list to MAC ring\n", + stats_ptr->msdu_recycled); + cdf_print(" %u MPDUs with invalid peer but A2 found in AST\n", + stats_ptr->invalid_peer_a2_in_ast); + cdf_print(" %u MPDUs with invalid peer but A3 found in AST\n", + stats_ptr->invalid_peer_a3_in_ast); + cdf_print(" %u MPDUs with invalid peer, Broadcast or Mulitcast frame\n", + stats_ptr->invalid_peer_bmc_mpdus); + cdf_print(" %u MSDUs with err attention word\n", + stats_ptr->rxdesc_err_att); + cdf_print(" %u MSDUs with flag of peer_idx_invalid\n", + stats_ptr->rxdesc_err_peer_idx_inv); + cdf_print(" %u MSDUs with flag of peer_idx_timeout\n", + stats_ptr->rxdesc_err_peer_idx_to); + cdf_print(" %u MSDUs with flag of overflow\n", + stats_ptr->rxdesc_err_ov); + cdf_print(" %u MSDUs with flag of msdu_length_err\n", + stats_ptr->rxdesc_err_msdu_len); + cdf_print(" %u MSDUs with flag of mpdu_length_err\n", + stats_ptr->rxdesc_err_mpdu_len); + cdf_print(" %u MSDUs with flag of tkip_mic_err\n", + stats_ptr->rxdesc_err_tkip_mic); + cdf_print(" %u MSDUs with flag of decrypt_err\n", + stats_ptr->rxdesc_err_decrypt); + cdf_print(" %u MSDUs with flag of fcs_err\n", + stats_ptr->rxdesc_err_fcs); + cdf_print(" %u Unicast frames with invalid peer handler\n", + stats_ptr->rxdesc_uc_msdus_inv_peer); + cdf_print(" %u unicast frame directly to DUT with invalid peer handler\n", + stats_ptr->rxdesc_direct_msdus_inv_peer); + cdf_print(" %u Broadcast/Multicast frames with invalid peer handler\n", + stats_ptr->rxdesc_bmc_msdus_inv_peer); + cdf_print(" %u MSDUs dropped due to no first MSDU flag\n", + stats_ptr->rxdesc_no_1st_msdu); + cdf_print(" %u MSDUs dropped due to ring overflow\n", + stats_ptr->msdu_drop_ring_ov); + cdf_print(" %u MSDUs dropped due to FC mismatch\n", + stats_ptr->msdu_drop_fc_mismatch); + cdf_print(" %u MSDUs dropped due to mgt frame in Remote ring\n", + stats_ptr->msdu_drop_mgmt_remote_ring); + cdf_print(" %u MSDUs dropped due to misc non error\n", + stats_ptr->msdu_drop_misc); + cdf_print(" %u MSDUs go to offload before reorder\n", + stats_ptr->offload_msdu_wal); + cdf_print(" %u data frame dropped by offload after reorder\n", + stats_ptr->offload_msdu_reorder); + cdf_print(" %u MPDUs with SN in the past & within BA window\n", + stats_ptr->dup_past_within_window); + cdf_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) +{ + cdf_print("Rx Remote Buffer Statistics:\n"); + cdf_print(" %u MSDU's reaped for Rx processing\n", + stats_ptr->remote_reaped); + cdf_print(" %u MSDU's recycled within firmware\n", + stats_ptr->remote_recycled); + cdf_print(" %u MSDU's stored by Data Rx\n", + stats_ptr->data_rx_msdus_stored); + cdf_print(" %u HTT indications from WAL Rx MSDU\n", + stats_ptr->wal_rx_ind); + cdf_print(" %u HTT indications unconsumed from WAL Rx MSDU\n", + stats_ptr->wal_rx_ind_unconsumed); + cdf_print(" %u HTT indications from Data Rx MSDU\n", + stats_ptr->data_rx_ind); + cdf_print(" %u HTT indications unconsumed from Data Rx MSDU\n", + stats_ptr->data_rx_ind_unconsumed); + cdf_print(" %u HTT indications from ATHBUF\n", + stats_ptr->athbuf_rx_ind); + cdf_print(" %u Remote buffers requested for refill\n", + stats_ptr->refill_buf_req); + cdf_print(" %u Remote buffers filled by host\n", + stats_ptr->refill_buf_rsp); + cdf_print(" %u times MAC has no buffers\n", + stats_ptr->mac_no_bufs); + cdf_print(" %u times f/w write & read indices on MAC ring are equal\n", + stats_ptr->fw_indices_equal); + cdf_print(" %u times f/w has no remote buffers to post to MAC\n", + stats_ptr->host_no_bufs); +} + +static void +htt_t2h_stats_txbf_info_buf_stats_print( + struct wlan_dbg_txbf_data_stats *stats_ptr) +{ + cdf_print("TXBF data Statistics:\n"); + cdf_print("tx_txbf_vht (0..9): "); + cdf_print("%u, %u, %u, %u, %u, %u, %u, %u, %u, %d\n", + stats_ptr->tx_txbf_vht[0], + stats_ptr->tx_txbf_vht[1], + stats_ptr->tx_txbf_vht[2], + stats_ptr->tx_txbf_vht[3], + stats_ptr->tx_txbf_vht[4], + stats_ptr->tx_txbf_vht[5], + stats_ptr->tx_txbf_vht[6], + stats_ptr->tx_txbf_vht[7], + stats_ptr->tx_txbf_vht[8], + stats_ptr->tx_txbf_vht[9]); + cdf_print("rx_txbf_vht (0..9): "); + cdf_print("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u\n", + stats_ptr->rx_txbf_vht[0], + stats_ptr->rx_txbf_vht[1], + stats_ptr->rx_txbf_vht[2], + stats_ptr->rx_txbf_vht[3], + stats_ptr->rx_txbf_vht[4], + stats_ptr->rx_txbf_vht[5], + stats_ptr->rx_txbf_vht[6], + stats_ptr->rx_txbf_vht[7], + stats_ptr->rx_txbf_vht[8], + stats_ptr->rx_txbf_vht[9]); + cdf_print("tx_txbf_ht (0..7): "); + cdf_print("%u, %u, %u, %u, %u, %u, %u, %u\n", + stats_ptr->tx_txbf_ht[0], + stats_ptr->tx_txbf_ht[1], + stats_ptr->tx_txbf_ht[2], + stats_ptr->tx_txbf_ht[3], + stats_ptr->tx_txbf_ht[4], + stats_ptr->tx_txbf_ht[5], + stats_ptr->tx_txbf_ht[6], + stats_ptr->tx_txbf_ht[7]); + cdf_print("tx_txbf_ofdm (0..7): "); + cdf_print("%u, %u, %u, %u, %u, %u, %u, %u\n", + stats_ptr->tx_txbf_ofdm[0], + stats_ptr->tx_txbf_ofdm[1], + stats_ptr->tx_txbf_ofdm[2], + stats_ptr->tx_txbf_ofdm[3], + stats_ptr->tx_txbf_ofdm[4], + stats_ptr->tx_txbf_ofdm[5], + stats_ptr->tx_txbf_ofdm[6], + stats_ptr->tx_txbf_ofdm[7]); + cdf_print("tx_txbf_cck (0..6): "); + cdf_print("%u, %u, %u, %u, %u, %u, %u\n", + stats_ptr->tx_txbf_cck[0], + stats_ptr->tx_txbf_cck[1], + stats_ptr->tx_txbf_cck[2], + stats_ptr->tx_txbf_cck[3], + stats_ptr->tx_txbf_cck[4], + stats_ptr->tx_txbf_cck[5], + stats_ptr->tx_txbf_cck[6]); +} + +static void +htt_t2h_stats_txbf_snd_buf_stats_print( + struct wlan_dbg_txbf_snd_stats *stats_ptr) +{ + cdf_print("TXBF snd Buffer Statistics:\n"); + cdf_print("cbf_20: "); + cdf_print("%u, %u, %u, %u\n", + stats_ptr->cbf_20[0], + stats_ptr->cbf_20[1], + stats_ptr->cbf_20[2], + stats_ptr->cbf_20[3]); + cdf_print("cbf_40: "); + cdf_print("%u, %u, %u, %u\n", + stats_ptr->cbf_40[0], + stats_ptr->cbf_40[1], + stats_ptr->cbf_40[2], + stats_ptr->cbf_40[3]); + cdf_print("cbf_80: "); + cdf_print("%u, %u, %u, %u\n", + stats_ptr->cbf_80[0], + stats_ptr->cbf_80[1], + stats_ptr->cbf_80[2], + stats_ptr->cbf_80[3]); + cdf_print("sounding: "); + cdf_print("%u, %u, %u, %u, %u, %u, %u, %u, %u\n", + stats_ptr->sounding[0], + stats_ptr->sounding[1], + stats_ptr->sounding[2], + stats_ptr->sounding[3], + stats_ptr->sounding[4], + stats_ptr->sounding[5], + stats_ptr->sounding[6], + stats_ptr->sounding[7], + stats_ptr->sounding[8]); +} + +static void +htt_t2h_stats_tx_selfgen_buf_stats_print( + struct wlan_dbg_tx_selfgen_stats *stats_ptr) +{ + cdf_print("Tx selfgen Buffer Statistics:\n"); + cdf_print(" %u su_ndpa\n", + stats_ptr->su_ndpa); + cdf_print(" %u mu_ndp\n", + stats_ptr->mu_ndp); + cdf_print(" %u mu_ndpa\n", + stats_ptr->mu_ndpa); + cdf_print(" %u mu_ndp\n", + stats_ptr->mu_ndp); + cdf_print(" %u mu_brpoll_1\n", + stats_ptr->mu_brpoll_1); + cdf_print(" %u mu_brpoll_2\n", + stats_ptr->mu_brpoll_2); + cdf_print(" %u mu_bar_1\n", + stats_ptr->mu_bar_1); + cdf_print(" %u mu_bar_2\n", + stats_ptr->mu_bar_2); + cdf_print(" %u cts_burst\n", + stats_ptr->cts_burst); + cdf_print(" %u su_ndp_err\n", + stats_ptr->su_ndp_err); + cdf_print(" %u su_ndpa_err\n", + stats_ptr->su_ndpa_err); + cdf_print(" %u mu_ndp_err\n", + stats_ptr->mu_ndp_err); + cdf_print(" %u mu_brp1_err\n", + stats_ptr->mu_brp1_err); + cdf_print(" %u mu_brp2_err\n", + stats_ptr->mu_brp2_err); +} + +static void +htt_t2h_stats_wifi2_error_stats_print( + struct wlan_dbg_wifi2_error_stats *stats_ptr) +{ + int i; + + cdf_print("Scheduler error Statistics:\n"); + cdf_print("urrn_stats: "); + cdf_print("%d, %d, %d\n", + stats_ptr->urrn_stats[0], + stats_ptr->urrn_stats[1], + stats_ptr->urrn_stats[2]); + cdf_print("flush_errs (0..%d): ", + WHAL_DBG_FLUSH_REASON_MAXCNT); + for (i = 0; i < WHAL_DBG_FLUSH_REASON_MAXCNT; i++) + cdf_print(" %u", stats_ptr->flush_errs[i]); + cdf_print("\n"); + cdf_print("schd_stall_errs (0..3): "); + cdf_print("%d, %d, %d, %d\n", + stats_ptr->schd_stall_errs[0], + stats_ptr->schd_stall_errs[1], + stats_ptr->schd_stall_errs[2], + stats_ptr->schd_stall_errs[3]); + cdf_print("schd_cmd_result (0..%d): ", + WHAL_DBG_CMD_RESULT_MAXCNT); + for (i = 0; i < WHAL_DBG_CMD_RESULT_MAXCNT; i++) + cdf_print(" %u", stats_ptr->schd_cmd_result[i]); + cdf_print("\n"); + cdf_print("sifs_status (0..%d): ", + WHAL_DBG_SIFS_STATUS_MAXCNT); + for (i = 0; i < WHAL_DBG_SIFS_STATUS_MAXCNT; i++) + cdf_print(" %u", stats_ptr->sifs_status[i]); + cdf_print("\n"); + cdf_print("phy_errs (0..%d): ", + WHAL_DBG_PHY_ERR_MAXCNT); + for (i = 0; i < WHAL_DBG_PHY_ERR_MAXCNT; i++) + cdf_print(" %u", stats_ptr->phy_errs[i]); + cdf_print("\n"); + cdf_print(" %u rx_rate_inval\n", + stats_ptr->rx_rate_inval); +} + +static void +htt_t2h_rx_musu_ndpa_pkts_stats_print( + struct rx_txbf_musu_ndpa_pkts_stats *stats_ptr) +{ + cdf_print("Rx TXBF MU/SU Packets and NDPA Statistics:\n"); + cdf_print(" %u Number of TXBF MU packets received\n", + stats_ptr->number_mu_pkts); + cdf_print(" %u Number of TXBF SU packets received\n", + stats_ptr->number_su_pkts); + cdf_print(" %u Number of TXBF directed NDPA\n", + stats_ptr->txbf_directed_ndpa_count); + cdf_print(" %u Number of TXBF retried NDPA\n", + stats_ptr->txbf_ndpa_retry_count); + cdf_print(" %u Total number of TXBF NDPA\n", + stats_ptr->txbf_total_ndpa_count); +} + +#define HTT_TICK_TO_USEC(ticks, microsec_per_tick) (ticks * microsec_per_tick) +static inline int htt_rate_flags_to_mhz(uint8_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_bitmaps_pr(uint32_t *queued_ptr, uint32_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; + + cdf_mem_set(queued_str, HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW, '0'); + cdf_mem_set(acked_str, HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW, '-'); + i = 0; + for (word = 0; word < 2; word++) { + uint32_t queued = *(queued_ptr + word); + uint32_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'; + cdf_print("%s\n", queued_str); + cdf_print("%s\n", acked_str); +} + +static inline uint16_t htt_msg_read16(uint16_t *p16) +{ +#ifdef BIG_ENDIAN_HOST + /* + * During upload, the bytes within each uint32_t word were + * swapped by the HIF HW. This results in the lower and upper bytes + * of each uint16_t to be in the correct big-endian order with + * respect to each other, but for each even-index uint16_t to + * have its position switched with its successor neighbor uint16_t. + * Undo this uint16_t position swapping. + */ + return (((size_t) p16) & 0x2) ? *(p16 - 1) : *(p16 + 1); +#else + return *p16; +#endif +} + +static inline uint8_t htt_msg_read8(uint8_t *p8) +{ +#ifdef BIG_ENDIAN_HOST + /* + * During upload, the bytes within each uint32_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(uint32_t *aligned_data, + char *buffer, int space, int max_elems) +{ + uint8_t *p8 = (uint8_t *) aligned_data; + char *buf_p = buffer; + while (max_elems-- > 0) { + int bytes; + uint8_t val; + + val = htt_msg_read8(p8); + if (val == 0) + /* not enough data to fill the reserved msg buffer*/ + break; + + bytes = cdf_snprint(buf_p, space, "%d,", val); + space -= bytes; + if (space > 0) + buf_p += bytes; + else /* not enough print buffer space for all the data */ + break; + 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(uint32_t *aligned_data, + char *buffer, int space, int max_elems) +{ + uint16_t *p16 = (uint16_t *) aligned_data; + char *buf_p = buffer; + while (max_elems-- > 0) { + int bytes; + uint16_t val; + + val = htt_msg_read16(p16); + if (val == 0) + /* not enough data to fill the reserved msg buffer */ + break; + bytes = cdf_snprint(buf_p, space, "%d,", val); + space -= bytes; + if (space > 0) + buf_p += bytes; + else /* not enough print buffer space for all the data */ + break; + + 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(uint16_t) + + hdr->mpdu_msdus_array_len * sizeof(uint8_t) + + hdr->msdu_bytes_array_len * sizeof(uint16_t); + num_records = (length - sizeof(*hdr)) / record_size; + cdf_print("Tx PPDU log elements:\n"); + + for (i = 0; i < num_records; i++) { + uint16_t start_seq_num; + uint16_t start_pn_lsbs; + uint8_t num_mpdus; + uint16_t peer_id; + uint8_t ext_tid; + uint8_t rate_code; + uint8_t rate_flags; + uint8_t tries; + uint8_t complete; + uint32_t time_enqueue_us; + uint32_t time_completion_us; + uint32_t *msg_word = (uint32_t *) record; + + /* fields used for both concise and complete printouts */ + start_seq_num = + ((*(msg_word + OL_FW_TX_DBG_PPDU_START_SEQ_NUM_16)) & + 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_16)) & + 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]; + uint8_t *p8; + time_enqueue_us = + HTT_TICK_TO_USEC(record->timestamp_enqueue, + hdr->microsec_per_tick); + time_completion_us = + HTT_TICK_TO_USEC(record->timestamp_completion, + hdr->microsec_per_tick); + + start_pn_lsbs = + ((* + (msg_word + + OL_FW_TX_DBG_PPDU_START_PN_LSBS_16)) & + 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_16))& + 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_16)) & + 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_16)) & + 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_16))& + 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_RATEFLAGS_16))& + 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_16)) & + OL_FW_TX_DBG_PPDU_TRIES_M) >> + OL_FW_TX_DBG_PPDU_TRIES_S; + + cdf_print(" - PPDU tx to peer %d, TID %d\n", peer_id, + ext_tid); + cdf_print + (" start seq num= %u, start PN LSBs= %#04x\n", + start_seq_num, start_pn_lsbs); + cdf_print + (" PPDU: %d MPDUs, (?) MSDUs, %d bytes\n", + num_mpdus, + /* num_msdus - not yet computed in target */ + record->num_bytes); + if (complete) { + cdf_print + (" enqueued: %u, completed: %u usec)\n", + time_enqueue_us, time_completion_us); + cdf_print + (" %d tries, last tx used rate %d ", + tries, rate_code); + cdf_print("on %d MHz chan (flags = %#x)\n", + htt_rate_flags_to_mhz + (rate_flags), rate_flags); + cdf_print + (" enqueued and acked MPDU bitmaps:\n"); + htt_t2h_tx_ppdu_bitmaps_pr(msg_word + + OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_16, + msg_word + + OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_16); + } else { + cdf_print + (" enqueued: %d us, not yet completed\n", + time_enqueue_us); + } + /* skip the regular msg fields to reach the tail area */ + p8 = (uint8_t *) record; + p8 += sizeof(struct ol_fw_tx_dbg_ppdu_base); + if (hdr->mpdu_bytes_array_len) { + htt_make_u16_list_str((uint32_t *) p8, buf, + BUF_SIZE, + hdr-> + mpdu_bytes_array_len); + cdf_print(" MPDU bytes: %s\n", buf); + } + p8 += hdr->mpdu_bytes_array_len * sizeof(uint16_t); + if (hdr->mpdu_msdus_array_len) { + htt_make_u8_list_str((uint32_t *) p8, buf, + BUF_SIZE, + hdr->mpdu_msdus_array_len); + cdf_print(" MPDU MSDUs: %s\n", buf); + } + p8 += hdr->mpdu_msdus_array_len * sizeof(uint8_t); + if (hdr->msdu_bytes_array_len) { + htt_make_u16_list_str((uint32_t *) p8, buf, + BUF_SIZE, + hdr-> + msdu_bytes_array_len); + cdf_print(" MSDU bytes: %s\n", buf); + } + } else { + /* concise */ + cdf_print("start seq num = %u ", start_seq_num); + cdf_print("enqueued and acked MPDU bitmaps:\n"); + if (complete) { + htt_t2h_tx_ppdu_bitmaps_pr(msg_word + + OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_16, + msg_word + + OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_16); + } else { + cdf_print("(not completed)\n"); + } + } + record = (struct ol_fw_tx_dbg_ppdu_base *) + (((uint8_t *) record) + record_size); + } +} + +void htt_t2h_stats_print(uint8_t *stats_data, int concise) +{ + uint32_t *msg_word = (uint32_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) { + cdf_print("Target doesn't support stats type %d\n", type); + return; + } else if (status == HTT_DBG_STATS_STATUS_ERROR) { + cdf_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_RX_RATE_INFO_V2: + { + wlan_dbg_rx_rate_info_v2_t *rx_phy_info; + rx_phy_info = + (wlan_dbg_rx_rate_info_v2_t *) (msg_word + 1); + htt_t2h_stats_rx_rate_stats_print_v2(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) { + cdf_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_TX_RATE_INFO_V2: + { + wlan_dbg_tx_rate_info_v2_t *tx_rate_info; + tx_rate_info = + (wlan_dbg_tx_rate_info_v2_t *) (msg_word + 1); + htt_t2h_stats_tx_rate_stats_print_v2(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_INFO: + { + struct wlan_dbg_txbf_data_stats *txbf_info_buf; + + txbf_info_buf = + (struct wlan_dbg_txbf_data_stats *)(msg_word + 1); + htt_t2h_stats_txbf_info_buf_stats_print(txbf_info_buf); + break; + } + case HTT_DBG_STATS_SND_INFO: + { + struct wlan_dbg_txbf_snd_stats *txbf_snd_buf; + + txbf_snd_buf = + (struct wlan_dbg_txbf_snd_stats *)(msg_word + 1); + htt_t2h_stats_txbf_snd_buf_stats_print(txbf_snd_buf); + break; + } + case HTT_DBG_STATS_TX_SELFGEN_INFO: + { + struct wlan_dbg_tx_selfgen_stats *tx_selfgen_buf; + + tx_selfgen_buf = + (struct wlan_dbg_tx_selfgen_stats *)(msg_word + 1); + htt_t2h_stats_tx_selfgen_buf_stats_print(tx_selfgen_buf); + break; + } + case HTT_DBG_STATS_ERROR_INFO: + { + struct wlan_dbg_wifi2_error_stats *wifi2_error_buf; + + wifi2_error_buf = + (struct wlan_dbg_wifi2_error_stats *)(msg_word + 1); + htt_t2h_stats_wifi2_error_stats_print(wifi2_error_buf); + 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); + break; + } + default: + break; + } +} diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c new file mode 100644 index 000000000000..437460ca0d27 --- /dev/null +++ b/core/dp/htt/htt_h2t.c @@ -0,0 +1,904 @@ +/* + * 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 /* cdf_mem_copy */ +#include /* cdf_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 + +static void +htt_h2t_send_complete_free_netbuf(void *pdev, A_STATUS status, + cdf_nbuf_t netbuf, uint16_t msdu_id) +{ + cdf_nbuf_free(netbuf); +} + +void htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt) +{ + void (*send_complete_part2)(void *pdev, A_STATUS status, + cdf_nbuf_t msdu, uint16_t msdu_id); + struct htt_pdev_t *pdev = (struct htt_pdev_t *)context; + struct htt_htc_pkt *htt_pkt; + cdf_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 = (cdf_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); + } + /* 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; +} + +#if defined(HELIUMPLUS_PADDR64) +A_STATUS htt_h2t_frag_desc_bank_cfg_msg(struct htt_pdev_t *pdev) +{ + A_STATUS rc = A_OK; + + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + u_int32_t *msg_word; + struct htt_tx_frag_desc_bank_cfg_t *bank_cfg; + + 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 = cdf_nbuf_alloc( + pdev->osdev, + HTT_MSG_BUF_SIZE(sizeof(struct htt_tx_frag_desc_bank_cfg_t)), + /* 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. + */ + cdf_nbuf_put_tail(msg, sizeof(struct htt_tx_frag_desc_bank_cfg_t)); + + /* fill in the message contents */ + msg_word = (u_int32_t *) cdf_nbuf_data(msg); + + memset(msg_word, 0 , sizeof(struct htt_tx_frag_desc_bank_cfg_t)); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG); + + bank_cfg = (struct htt_tx_frag_desc_bank_cfg_t *)msg_word; + + /** @note @todo Hard coded to 0 Assuming just one pdev for now.*/ + HTT_H2T_FRAG_DESC_BANK_PDEVID_SET(*msg_word, 0); + /** @note Hard coded to 1.*/ + HTT_H2T_FRAG_DESC_BANK_NUM_BANKS_SET(*msg_word, 1); + HTT_H2T_FRAG_DESC_BANK_DESC_SIZE_SET(*msg_word, pdev->frag_descs.size); + HTT_H2T_FRAG_DESC_BANK_SWAP_SET(*msg_word, 0); + + /** Bank specific data structure.*/ +#if HTT_PADDR64 + bank_cfg->bank_base_address[0].lo = pdev->frag_descs.pool_paddr; + bank_cfg->bank_base_address[0].hi = 0; +#else /* ! HTT_PADDR64 */ + bank_cfg->bank_base_address[0] = pdev->frag_descs.pool_paddr; +#endif /* HTT_PADDR64 */ + /* Logical Min index */ + HTT_H2T_FRAG_DESC_BANK_MIN_IDX_SET(bank_cfg->bank_info[0], 0); + /* Logical Max index */ + HTT_H2T_FRAG_DESC_BANK_MAX_IDX_SET(bank_cfg->bank_info[0], + pdev->frag_descs.pool_elems-1); + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + cdf_nbuf_data(msg), + cdf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + rc = htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); + + return rc; +} + +#endif /* defined(HELIUMPLUS_PADDR64) */ + +A_STATUS htt_h2t_ver_req_msg(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for the HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES), + 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 cdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + cdf_nbuf_put_tail(msg, HTT_VER_REQ_BYTES); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ); + + SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + cdf_nbuf_data(msg), cdf_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 (htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + return A_OK; +} + +A_STATUS htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for the HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_RX_RING_CFG_BYTES(1)), + 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 cdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + cdf_nbuf_put_tail(msg, HTT_RX_RING_CFG_BYTES(1)); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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; +#if HTT_PADDR64 + HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_LO_SET(*msg_word, + pdev->rx_ring.alloc_idx.paddr); + msg_word++; + HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_HI_SET(*msg_word, 0); +#else /* ! HTT_PADDR64 */ + HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET(*msg_word, + pdev->rx_ring.alloc_idx.paddr); +#endif /* HTT_PADDR64 */ + + msg_word++; + *msg_word = 0; +#if HTT_PADDR64 + HTT_RX_RING_CFG_BASE_PADDR_LO_SET(*msg_word, + pdev->rx_ring.base_paddr); + msg_word++; + HTT_RX_RING_CFG_BASE_PADDR_HI_SET(*msg_word, 0); +#else /* ! HTT_PADDR64 */ + HTT_RX_RING_CFG_BASE_PADDR_SET(*msg_word, pdev->rx_ring.base_paddr); +#endif /* HTT_PADDR64 */ + + 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 */ + cdf_print("Pkt log is enabled\n"); + htt_htc_disable_aspm(); + } else { + cdf_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); + /* always present? */ + HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(*msg_word, 1); + 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_DESC_HDR_STATUS_OFFSET32); + HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(*msg_word, + HTT_RX_DESC_RESERVATION32); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(*msg_word, + RX_DESC_PPDU_START_OFFSET32); + HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(*msg_word, + RX_DESC_PPDU_END_OFFSET32); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(*msg_word, + RX_DESC_MPDU_START_OFFSET32); + HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(*msg_word, + RX_DESC_MPDU_END_OFFSET32); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(*msg_word, + RX_DESC_MSDU_START_OFFSET32); + HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(*msg_word, + RX_DESC_MSDU_END_OFFSET32); + + msg_word++; + *msg_word = 0; + HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(*msg_word, + RX_DESC_ATTN_OFFSET32); + HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(*msg_word, + RX_DESC_FRAG_INFO_OFFSET32); + + SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + cdf_nbuf_data(msg), + cdf_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 (htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + return A_OK; +} + +int +htt_h2t_dbg_stats_get(struct htt_pdev_t *pdev, + uint32_t stats_type_upload_mask, + uint32_t stats_type_reset_mask, + uint8_t cfg_stat_type, uint32_t cfg_val, uint64_t cookie) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) + return -EINVAL; /* 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? */ + cdf_print("%#x %#x stats not supported\n", + stats_type_upload_mask, stats_type_reset_mask); + return -EINVAL; /* 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 = cdf_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 -EINVAL; /* failure */ + } + /* set the length of the message */ + cdf_nbuf_put_tail(msg, HTT_H2T_STATS_REQ_MSG_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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, + cdf_nbuf_data(msg), + cdf_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 (htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + return 0; +} + +A_STATUS htt_h2t_sync_msg(struct htt_pdev_t *pdev, uint8_t sync_cnt) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, HTT_MSG_BUF_SIZE(HTT_H2T_SYNC_MSG_SZ), + 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 */ + cdf_nbuf_put_tail(msg, HTT_H2T_SYNC_MSG_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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, + cdf_nbuf_data(msg), + cdf_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 (htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + 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; + cdf_nbuf_t msg; + uint32_t *msg_word; + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) + return -EINVAL; /* 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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, HTT_MSG_BUF_SIZE(HTT_AGGR_CFG_MSG_SZ), + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, + false); + if (!msg) { + htt_htc_pkt_free(pdev, pkt); + return -EINVAL; /* failure */ + } + /* set the length of the message */ + cdf_nbuf_put_tail(msg, HTT_AGGR_CFG_MSG_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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, + cdf_nbuf_data(msg), + cdf_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 (htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) + htt_htc_misc_pkt_list_add(pdev, pkt); +#else + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); +#endif + + return 0; +} + +#ifdef IPA_OFFLOAD +int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, HTT_MSG_BUF_SIZE(HTT_WDI_IPA_CFG_SZ), + 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 */ + cdf_nbuf_put_tail(msg, HTT_WDI_IPA_CFG_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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; + /* TX COMP RING BASE LO */ + HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_base.paddr); + msg_word++; + *msg_word = 0; + /* TX COMP RING BASE HI, NONE */ + + 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_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr); + msg_word++; + *msg_word = 0; + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr); + msg_word++; + *msg_word = 0; + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_LO_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_BASE_ADDR_HI_SET(*msg_word, + 0); + + 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_LO_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_RD_IDX_ADDR_HI_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr); + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_HI_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr); + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_RING2_BASE_ADDR_HI_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_RING2_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_RING2_RD_IDX_ADDR_LO_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_RING2_RD_IDX_ADDR_HI_SET(*msg_word, + 0); + + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_SET(*msg_word, + (unsigned int)pdev->ipa_uc_rx_rsc.rx2_rdy_idx_paddr); + msg_word++; + *msg_word = 0; + HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_SET(*msg_word, + 0); + + cdf_trace_hex_dump(CDF_MODULE_ID_HTT, CDF_TRACE_LEVEL_FATAL, + (void *)cdf_nbuf_data(msg), 40); + + SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, + htt_h2t_send_complete_free_netbuf, + cdf_nbuf_data(msg), + cdf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); + + return A_OK; +} + +int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, + bool uc_active, bool is_tx) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_t *msg_word; + uint8_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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_WDI_IPA_OP_REQUEST_SZ), + 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 */ + cdf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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, + cdf_nbuf_data(msg), + cdf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); + + return A_OK; +} + +int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, + HTT_MSG_BUF_SIZE(HTT_WDI_IPA_OP_REQUEST_SZ), + 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 */ + cdf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + + *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, + cdf_nbuf_data(msg), + cdf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); + + return A_OK; +} +#endif /* IPA_OFFLOAD */ diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h new file mode 100644 index 000000000000..1bc710f7366d --- /dev/null +++ b/core/dp/htt/htt_internal.h @@ -0,0 +1,500 @@ +/* + * 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 _HTT_INTERNAL__H_ +#define _HTT_INTERNAL__H_ + +#include /* A_STATUS */ +#include /* cdf_nbuf_t */ +#include /* cdf_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_DESC_ATTN_OFFSET32 (RX_STD_DESC_ATTN_OFFSET >> 2) +#define RX_DESC_FRAG_INFO_OFFSET32 (RX_STD_DESC_FRAG_INFO_OFFSET >> 2) +#define RX_DESC_MPDU_START_OFFSET32 (RX_STD_DESC_MPDU_START_OFFSET >> 2) +#define RX_DESC_MSDU_START_OFFSET32 (RX_STD_DESC_MSDU_START_OFFSET >> 2) +#define RX_DESC_MSDU_END_OFFSET32 (RX_STD_DESC_MSDU_END_OFFSET >> 2) +#define RX_DESC_MPDU_END_OFFSET32 (RX_STD_DESC_MPDU_END_OFFSET >> 2) +#define RX_DESC_PPDU_START_OFFSET32 (RX_STD_DESC_PPDU_START_OFFSET >> 2) +#define RX_DESC_PPDU_END_OFFSET32 (RX_STD_DESC_PPDU_END_OFFSET >> 2) +#define RX_DESC_HDR_STATUS_OFFSET32 (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_DESC_RESERVATION32 \ + (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(cdf_nbuf_t msdu) +{ + return (struct htt_host_rx_desc_base *) + (((size_t) (cdf_nbuf_head(msdu) + HTT_RX_DESC_ALIGN_MASK)) & + ~HTT_RX_DESC_ALIGN_MASK); +} + +#if defined(FEATURE_LRO) +/** + * htt_print_rx_desc_lro() - print LRO information in the rx + * descriptor + * @rx_desc: HTT rx descriptor + * + * Prints the LRO related fields in the HTT rx descriptor + * + * Return: none + */ +static inline void htt_print_rx_desc_lro(struct htt_host_rx_desc_base *rx_desc) +{ + cdf_print + ("----------------------RX DESC LRO----------------------\n"); + cdf_print("msdu_end.lro_eligible:0x%x\n", + rx_desc->msdu_end.lro_eligible); + cdf_print("msdu_start.tcp_only_ack:0x%x\n", + rx_desc->msdu_start.tcp_only_ack); + cdf_print("msdu_end.tcp_udp_chksum:0x%x\n", + rx_desc->msdu_end.tcp_udp_chksum); + cdf_print("msdu_end.tcp_seq_number:0x%x\n", + rx_desc->msdu_end.tcp_seq_number); + cdf_print("msdu_end.tcp_ack_number:0x%x\n", + rx_desc->msdu_end.tcp_ack_number); + cdf_print("msdu_start.tcp_proto:0x%x\n", + rx_desc->msdu_start.tcp_proto); + cdf_print("msdu_start.ipv6_proto:0x%x\n", + rx_desc->msdu_start.ipv6_proto); + cdf_print("msdu_start.ipv4_proto:0x%x\n", + rx_desc->msdu_start.ipv4_proto); + cdf_print("msdu_start.l3_offset:0x%x\n", + rx_desc->msdu_start.l3_offset); + cdf_print("msdu_start.l4_offset:0x%x\n", + rx_desc->msdu_start.l4_offset); + cdf_print("msdu_start.flow_id_toeplitz:0x%x\n", + rx_desc->msdu_start.flow_id_toeplitz); + cdf_print + ("---------------------------------------------------------\n"); +} + +/** + * htt_print_rx_desc_lro() - extract LRO information from the rx + * descriptor + * @msdu: network buffer + * @rx_desc: HTT rx descriptor + * + * Extracts the LRO related fields from the HTT rx descriptor + * and stores them in the network buffer's control block + * + * Return: none + */ +static inline void htt_rx_extract_lro_info(cdf_nbuf_t msdu, + struct htt_host_rx_desc_base *rx_desc) +{ + NBUF_LRO_ELIGIBLE(msdu) = rx_desc->msdu_end.lro_eligible; + if (rx_desc->msdu_end.lro_eligible) { + NBUF_TCP_PURE_ACK(msdu) = rx_desc->msdu_start.tcp_only_ack; + NBUF_TCP_CHKSUM(msdu) = rx_desc->msdu_end.tcp_udp_chksum; + NBUF_TCP_SEQ_NUM(msdu) = rx_desc->msdu_end.tcp_seq_number; + NBUF_TCP_ACK_NUM(msdu) = rx_desc->msdu_end.tcp_ack_number; + NBUF_TCP_WIN(msdu) = rx_desc->msdu_end.window_size; + NBUF_TCP_PROTO(msdu) = rx_desc->msdu_start.tcp_proto; + NBUF_IPV6_PROTO(msdu) = rx_desc->msdu_start.ipv6_proto; + NBUF_IP_OFFSET(msdu) = rx_desc->msdu_start.l3_offset; + NBUF_TCP_OFFSET(msdu) = rx_desc->msdu_start.l4_offset; + NBUF_FLOW_ID_TOEPLITZ(msdu) = + rx_desc->msdu_start.flow_id_toeplitz; + } +} +#else +static inline void htt_print_rx_desc_lro(struct htt_host_rx_desc_base *rx_desc) +{} +static inline void htt_rx_extract_lro_info(cdf_nbuf_t msdu, + struct htt_host_rx_desc_base *rx_desc) {} +#endif /* FEATURE_LRO */ + +static inline void htt_print_rx_desc(struct htt_host_rx_desc_base *rx_desc) +{ + cdf_print + ("----------------------RX DESC----------------------------\n"); + cdf_print("attention: %#010x\n", + (unsigned int)(*(uint32_t *) &rx_desc->attention)); + cdf_print("frag_info: %#010x\n", + (unsigned int)(*(uint32_t *) &rx_desc->frag_info)); + cdf_print("mpdu_start: %#010x %#010x %#010x\n", + (unsigned int)(((uint32_t *) &rx_desc->mpdu_start)[0]), + (unsigned int)(((uint32_t *) &rx_desc->mpdu_start)[1]), + (unsigned int)(((uint32_t *) &rx_desc->mpdu_start)[2])); + cdf_print("msdu_start: %#010x %#010x %#010x\n", + (unsigned int)(((uint32_t *) &rx_desc->msdu_start)[0]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_start)[1]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_start)[2])); + cdf_print("msdu_end: %#010x %#010x %#010x %#010x %#010x\n", + (unsigned int)(((uint32_t *) &rx_desc->msdu_end)[0]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_end)[1]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_end)[2]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_end)[3]), + (unsigned int)(((uint32_t *) &rx_desc->msdu_end)[4])); + cdf_print("mpdu_end: %#010x\n", + (unsigned int)(*(uint32_t *) &rx_desc->mpdu_end)); + cdf_print("ppdu_start: " "%#010x %#010x %#010x %#010x %#010x\n" + "%#010x %#010x %#010x %#010x %#010x\n", + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[0]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[1]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[2]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[3]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[4]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[5]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[6]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[7]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[8]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_start)[9])); + cdf_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)(((uint32_t *) &rx_desc->ppdu_end)[0]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[1]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[2]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[3]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[4]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[5]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[6]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[7]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[8]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[9]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[10]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[11]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[12]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[13]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[14]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[15]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[16]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[17]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[18]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[19]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[20]), + (unsigned int)(((uint32_t *) &rx_desc->ppdu_end)[21])); + cdf_print + ("---------------------------------------------------------\n"); +} + +#ifndef HTT_ASSERT_LEVEL +#define HTT_ASSERT_LEVEL 3 +#endif + +#define HTT_ASSERT_ALWAYS(condition) cdf_assert_always((condition)) + +#define HTT_ASSERT0(condition) cdf_assert((condition)) +#if HTT_ASSERT_LEVEL > 0 +#define HTT_ASSERT1(condition) cdf_assert((condition)) +#else +#define HTT_ASSERT1(condition) +#endif + +#if HTT_ASSERT_LEVEL > 1 +#define HTT_ASSERT2(condition) cdf_assert((condition)) +#else +#define HTT_ASSERT2(condition) +#endif + +#if HTT_ASSERT_LEVEL > 2 +#define HTT_ASSERT3(condition) cdf_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) \ + cdf_spinlock_init(_mutex) + +#define HTT_TX_MUTEX_ACQUIRE(_mutex) \ + cdf_spin_lock_bh(_mutex) + +#define HTT_TX_MUTEX_RELEASE(_mutex) \ + cdf_spin_unlock_bh(_mutex) + +#define HTT_TX_MUTEX_DESTROY(_mutex) \ + cdf_spinlock_destroy(_mutex) + +#define HTT_TX_DESC_PADDR(_pdev, _tx_desc_vaddr) \ + ((_pdev)->tx_descs.pool_paddr + (uint32_t) \ + ((char *)(_tx_desc_vaddr) - \ + (char *)((_pdev)->tx_descs.pool_vaddr))) + +#ifdef ATH_11AC_TXCOMPACT + +#define HTT_TX_NBUF_QUEUE_MUTEX_INIT(_pdev) \ + cdf_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) do { \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + _msdu = cdf_nbuf_queue_remove(&_pdev->txnbufq);\ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex); \ + } while (0) + +#define HTT_TX_NBUF_QUEUE_ADD(_pdev, _msdu) do { \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + cdf_nbuf_queue_add(&_pdev->txnbufq, _msdu); \ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex); \ + } while (0) + +#define HTT_TX_NBUF_QUEUE_INSERT_HEAD(_pdev, _msdu) do { \ + HTT_TX_MUTEX_ACQUIRE(&_pdev->txnbufq_mutex); \ + cdf_nbuf_queue_insert_head(&_pdev->txnbufq, _msdu);\ + HTT_TX_MUTEX_RELEASE(&_pdev->txnbufq_mutex); \ + } while (0) +#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_h2t_send_complete(void *context, HTC_PACKET *pkt); + +A_STATUS htt_h2t_ver_req_msg(struct htt_pdev_t *pdev); + +#if defined(HELIUMPLUS_PADDR64) +A_STATUS +htt_h2t_frag_desc_bank_cfg_msg(struct htt_pdev_t *pdev); +#endif /* defined(HELIUMPLUS_PADDR64) */ + +extern A_STATUS htt_h2t_rx_ring_cfg_msg_ll(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, uint32_t paddr, + cdf_nbuf_t netbuf); + +cdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr); + +#ifdef IPA_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); +#else +static inline 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) +{ + return 0; +} + +static inline int +htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, unsigned int rx_ind_ring_size) +{ + return 0; +} + +static inline int htt_tx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + return 0; +} + +static inline int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + return 0; +} +#endif /* IPA_OFFLOAD */ +#endif /* _HTT_INTERNAL__H_ */ diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c new file mode 100644 index 000000000000..697763d09144 --- /dev/null +++ b/core/dp/htt/htt_rx.c @@ -0,0 +1,2444 @@ +/* + * 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 /* cdf_mem_malloc,free, etc. */ +#include /* cdf_print, bool */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_softirq_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 */ + +#ifdef DEBUG_DMA_DONE +#include +#include +#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 > than one large A-MPDU */ +#endif + +#ifndef HTT_RX_RING_SIZE_MAX +#define HTT_RX_RING_SIZE_MAX 2048 /* ~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 + +/*--- RX In Order Definitions ------------------------------------------------*/ + +/* 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 + +/* 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) +{ + + uint32_t i; + struct htt_rx_hash_entry *hash_entry; + struct 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) { + cdf_nbuf_free(hash_entry->netbuf); + hash_entry->paddr = 0; + } + list_iter = list_iter->next; + + if (!hash_entry->fromlist) + cdf_mem_free(hash_entry); + } + + cdf_mem_free(pdev->rx_ring.hash_table[i].entries); + + } + cdf_mem_free(pdev->rx_ring.hash_table); + pdev->rx_ring.hash_table = NULL; +} + +static int ceil_pwr2(int value) +{ + int log2; + if (IS_PWR2(value)) + return value; + + log2 = 0; + while (value) { + value >>= 1; + log2++; + } + return 1 << log2; +} + +static bool +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 (bool) + (((*(((uint32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_FIRST_MSDU_MASK) >> + RX_MSDU_END_4_FIRST_MSDU_LSB); +} + +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; + else 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; + CDF_STATUS status; + struct htt_host_rx_desc_base *rx_desc; + + idx = *(pdev->rx_ring.alloc_idx.vaddr); + while (num > 0) { + uint32_t paddr; + cdf_nbuf_t rx_netbuf; + int headroom; + + rx_netbuf = + cdf_nbuf_alloc(pdev->osdev, HTT_RX_BUF_SIZE, + 0, 4, false); + if (!rx_netbuf) { + cdf_softirq_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 + cdf_softirq_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); + *(uint32_t *) &rx_desc->attention = 0; + +#ifdef DEBUG_DMA_DONE + *(uint32_t *) &rx_desc->msdu_end = 1; + +#define MAGIC_PATTERN 0xDEADBEEF + *(uint32_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 cdf_nbuf_data to point to the location in the buffer + * where the rx descriptor will be filled in. + */ + headroom = cdf_nbuf_data(rx_netbuf) - (uint8_t *) rx_desc; + cdf_nbuf_push_head(rx_netbuf, headroom); + +#ifdef DEBUG_DMA_DONE + status = + cdf_nbuf_map(pdev->osdev, rx_netbuf, + CDF_DMA_BIDIRECTIONAL); +#else + status = + cdf_nbuf_map(pdev->osdev, rx_netbuf, + CDF_DMA_FROM_DEVICE); +#endif + if (status != CDF_STATUS_SUCCESS) { + cdf_nbuf_free(rx_netbuf); + goto fail; + } + paddr = cdf_nbuf_get_frag_paddr_lo(rx_netbuf, 0); + if (pdev->cfg.is_full_reorder_offload) { + if (cdf_unlikely + (htt_rx_hash_list_insert(pdev, paddr, + rx_netbuf))) { + cdf_print("%s: hash insert failed!\n", + __func__); +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, rx_netbuf, + CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, rx_netbuf, + CDF_DMA_FROM_DEVICE); +#endif + cdf_nbuf_free(rx_netbuf); + goto fail; + } + } else { + pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf; + } +#if HTT_PADDR64 + pdev->rx_ring.buf.paddrs_ring[idx] = 0; + pdev->rx_ring.buf.paddrs_ring[idx] = (uint32_t)paddr; +#else + pdev->rx_ring.buf.paddrs_ring[idx] = paddr; +#endif /* HTT_PADDR64 */ + 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) +{ + cdf_softirq_timer_cancel(&pdev->rx_ring.refill_retry_timer); + cdf_softirq_timer_free(&pdev->rx_ring.refill_retry_timer); + + if (pdev->cfg.is_full_reorder_offload) { + cdf_os_mem_free_consistent(pdev->osdev, + sizeof(uint32_t), + pdev->rx_ring.target_idx.vaddr, + pdev->rx_ring.target_idx.paddr, + cdf_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 + cdf_nbuf_unmap(pdev->osdev, + pdev->rx_ring.buf. + netbufs_ring[sw_rd_idx], + CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, + pdev->rx_ring.buf. + netbufs_ring[sw_rd_idx], + CDF_DMA_FROM_DEVICE); +#endif + cdf_nbuf_free(pdev->rx_ring.buf. + netbufs_ring[sw_rd_idx]); + sw_rd_idx++; + sw_rd_idx &= pdev->rx_ring.size_mask; + } + cdf_mem_free(pdev->rx_ring.buf.netbufs_ring); + } + + cdf_os_mem_free_consistent(pdev->osdev, + sizeof(uint32_t), + pdev->rx_ring.alloc_idx.vaddr, + pdev->rx_ring.alloc_idx.paddr, + cdf_get_dma_mem_context((&pdev->rx_ring. + alloc_idx), + memctx)); + + cdf_os_mem_free_consistent(pdev->osdev, + pdev->rx_ring.size * sizeof(uint32_t), + pdev->rx_ring.buf.paddrs_ring, + pdev->rx_ring.base_paddr, + cdf_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); +} + +uint16_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 + (uint16_t) (((*((uint32_t *) &rx_desc->mpdu_start)) & + RX_MPDU_START_0_SEQ_NUM_MASK) >> + RX_MPDU_START_0_SEQ_NUM_LSB); +} + +/* 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 |= ((uint64_t) + ((*(((uint32_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] |= + ((uint64_t) ((*(((uint32_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] |= + ((uint64_t) ((*(((uint32_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] |= + ((uint64_t) rx_desc->msdu_end.ext_wapi_pn_127_96) << 32; + break; + default: + cdf_print("Error: invalid length spec (%d bits) for PN\n", + pn_len_bits); + }; +} + +/** + * 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); +} + +uint32_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 */ +bool 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 (bool) + (((*(((uint32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_LAST_MSDU_MASK) >> RX_MSDU_END_4_LAST_MSDU_LSB); +} + +/* 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 + ((*(((uint32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_FIRST_MSDU_MASK) >> RX_MSDU_END_4_FIRST_MSDU_LSB; +} + +/* FIX THIS: APPLIES TO LL ONLY */ +bool 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 + ((*((uint32_t *) &rx_desc->attention)) & + RX_ATTENTION_0_MCAST_BCAST_MASK) + >> RX_ATTENTION_0_MCAST_BCAST_LSB; +} + +/* 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 + ((*((uint32_t *) &rx_desc->attention)) & + RX_ATTENTION_0_FRAGMENT_MASK) >> RX_ATTENTION_0_FRAGMENT_LSB; +} + +static inline +uint8_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 *(((uint8_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) +{ + uint8_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 cdf_nbuf_t htt_rx_netbuf_pop(htt_pdev_handle pdev) +{ + int idx; + cdf_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 cdf_nbuf_t +htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, uint32_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, cdf_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 cdf_nbuf_l4_rx_cksum_type_t + cksum_table[][MAX_PROTO_VAL][MAX_IP_VER] = { + { + /* non-fragmented IP packet */ + /* non TCP/UDP packet */ + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + /* TCP packet */ + {CDF_NBUF_RX_CKSUM_TCP, CDF_NBUF_RX_CKSUM_TCPIPV6}, + /* UDP packet */ + {CDF_NBUF_RX_CKSUM_UDP, CDF_NBUF_RX_CKSUM_UDPIPV6}, + /* invalid packet type */ + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + }, + { + /* fragmented IP packet */ + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + {CDF_NBUF_RX_CKSUM_NONE, CDF_NBUF_RX_CKSUM_NONE}, + } + }; + + cdf_nbuf_rx_cksum_t cksum = { + cksum_table[rx_msdu->ip_frag][proto][rx_msdu->ipv6_proto], + CDF_NBUF_RX_CKSUM_NONE, + 0 + }; + + if (cksum.l4_type != + (cdf_nbuf_l4_rx_cksum_type_t) CDF_NBUF_RX_CKSUM_NONE) { + cksum.l4_result = + ((*(uint32_t *) &rx_desc->attention) & + RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK) ? + CDF_NBUF_RX_CKSUM_NONE : + CDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; + } + cdf_nbuf_set_rx_cksum(msdu, &cksum); +#undef MAX_IP_VER +#undef MAX_PROTO_VAL +} +#else +#define htt_set_checksum_result_ll(pdev, msdu, rx_desc) /* no-op */ +#endif + +#ifdef DEBUG_DMA_DONE +void htt_rx_print_rx_indication(cdf_nbuf_t rx_ind_msg, htt_pdev_handle pdev) +{ + uint32_t *msg_word; + int byte_offset; + int mpdu_range, num_mpdu_range; + + msg_word = (uint32_t *) cdf_nbuf_data(rx_ind_msg); + + cdf_print + ("------------------HTT RX IND-----------------------------\n"); + cdf_print("alloc idx paddr %x (*vaddr) %d\n", + pdev->rx_ring.alloc_idx.paddr, + *pdev->rx_ring.alloc_idx.vaddr); + + cdf_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); + + cdf_print("dbg_ring_idx %d\n", pdev->rx_ring.dbg_ring_idx); + + cdf_print("fill_level %d fill_cnt %d\n", pdev->rx_ring.fill_level, + pdev->rx_ring.fill_cnt); + + cdf_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 */ + + cdf_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)); + + cdf_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))); + + cdf_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); + + cdf_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); + + cdf_print("mpdu_range %x status %x num_mpdus %x\n", + pdev->rx_ind_msdu_byte_idx, status, num_mpdus); + } + cdf_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, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_nbuf_t *tail_msdu) +{ + int msdu_len, msdu_chaining = 0; + cdf_nbuf_t msdu; + struct htt_host_rx_desc_base *rx_desc; + uint8_t *rx_ind_data; + uint32_t *msg_word, num_msdu_bytes; + enum htt_t2h_msg_type msg_type; + uint8_t pad_bytes = 0; + + HTT_ASSERT1(htt_rx_ring_elems(pdev) != 0); + rx_ind_data = cdf_nbuf_data(rx_ind_msg); + msg_word = (uint32_t *) rx_ind_data; + + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + + if (cdf_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. + */ + cdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_DMA_FROM_DEVICE); +#endif + + /* cache consistency has been taken care of by cdf_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); +#if defined(HELIUMPLUS_PADDR64) + if (HTT_WIFI_IP(pdev, 2, 0)) + pad_bytes = rx_desc->msdu_end.l3_header_padding; +#endif /* defined(HELIUMPLUS_PADDR64) */ + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + + cdf_nbuf_pull_head(msdu, + HTT_RX_STD_DESC_RESERVATION + pad_bytes); + + /* + * 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 (cdf_unlikely(!((*(uint32_t *) &rx_desc->attention) + & RX_ATTENTION_0_MSDU_DONE_MASK))) { + + int dbg_iter = MAX_DONE_BIT_CHECK_ITER; + + cdf_print("malformed frame\n"); + + while (dbg_iter && + (!((*(uint32_t *) &rx_desc->attention) & + RX_ATTENTION_0_MSDU_DONE_MASK))) { + cdf_mdelay(1); + + cdf_invalidate_range((void *)rx_desc, + (void *)((char *)rx_desc + + HTT_RX_STD_DESC_RESERVATION)); + + cdf_print("debug iter %d success %d\n", + dbg_iter, + pdev->rx_ring.dbg_sync_success); + + dbg_iter--; + } + + if (cdf_unlikely(!((*(uint32_t *) &rx_desc->attention) + & RX_ATTENTION_0_MSDU_DONE_MASK))) { + +#ifdef HTT_RX_RESTORE + cdf_print("RX done bit error detected!\n"); + cdf_nbuf_set_next(msdu, NULL); + *tail_msdu = msdu; + pdev->rx_ring.rx_reset = 1; + return msdu_chaining; +#else + wma_cli_set_command(0, GEN_PARAM_CRASH_INJECT, + 0, GEN_CMD); + HTT_ASSERT_ALWAYS(0); +#endif + } + pdev->rx_ring.dbg_sync_success++; + cdf_print("debug iter %d success %d\n", dbg_iter, + pdev->rx_ring.dbg_sync_success); + } +#else + HTT_ASSERT_ALWAYS((*(uint32_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 (cdf_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); + + *((uint8_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. + */ + /* cdf_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 the MPDU. + * + * FIX THIS - the FW descriptors are actually for MSDUs + * in the end of this A-MSDU instead of the beginning. + */ + *((uint8_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 = (*(uint32_t *) &rx_desc->attention) & + RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + msdu_chained = (((*(uint32_t *) &rx_desc->frag_info) & + RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK) >> + RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB); + msdu_len = + ((*((uint32_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 + cdf_nbuf_trim_tail(msdu, + HTT_RX_BUF_SIZE - + (RX_STD_DESC_SIZE + + msdu_len)); + } + } while (0); + + while (msdu_chained--) { + cdf_nbuf_t next = htt_rx_netbuf_pop(pdev); + cdf_nbuf_set_pktlen(next, HTT_RX_BUF_SIZE); + msdu_len -= HTT_RX_BUF_SIZE; + cdf_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 + * causing 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); + } + + cdf_nbuf_trim_tail(next, + HTT_RX_BUF_SIZE - + (RX_STD_DESC_SIZE + + msdu_len)); + } + } + + last_msdu = + ((*(((uint32_t *) &rx_desc->msdu_end) + 4)) & + RX_MSDU_END_4_LAST_MSDU_MASK) >> + RX_MSDU_END_4_LAST_MSDU_LSB; + + if (last_msdu) { + cdf_nbuf_set_next(msdu, NULL); + break; + } else { + cdf_nbuf_t next = htt_rx_netbuf_pop(pdev); + cdf_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 (sth 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_offload_msdu_pop_ll(htt_pdev_handle pdev, + cdf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + uint8_t *fw_desc, + cdf_nbuf_t *head_buf, cdf_nbuf_t *tail_buf) +{ + cdf_nbuf_t buf; + uint32_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); + cdf_nbuf_set_pktlen(buf, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, buf, CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, buf, CDF_DMA_FROM_DEVICE); +#endif + msdu_hdr = (uint32_t *) cdf_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); + + cdf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES); + cdf_nbuf_set_pktlen(buf, msdu_len); + return 0; +} + +int +htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev, + uint32_t *msg_word, + int msdu_iter, + int *vdev_id, + int *peer_id, + int *tid, + uint8_t *fw_desc, + cdf_nbuf_t *head_buf, cdf_nbuf_t *tail_buf) +{ + cdf_nbuf_t buf; + uint32_t *msdu_hdr, msdu_len; + uint32_t *curr_msdu; + uint32_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 (cdf_unlikely(NULL == buf)) { + cdf_print("%s: netbuf pop failed!\n", __func__); + return 0; + } + cdf_nbuf_set_pktlen(buf, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, buf, CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, buf, CDF_DMA_FROM_DEVICE); +#endif + msdu_hdr = (uint32_t *) cdf_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); + + cdf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES); + cdf_nbuf_set_pktlen(buf, msdu_len); + return 0; +} + +extern void +dump_pkt(cdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len); + +#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, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_nbuf_t *tail_msdu) +{ + cdf_nbuf_t msdu, next, prev = NULL; + uint8_t *rx_ind_data; + uint32_t *msg_word; + unsigned int msdu_count = 0; + uint8_t offload_ind; + struct htt_host_rx_desc_base *rx_desc; + + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + + rx_ind_data = cdf_nbuf_data(rx_ind_msg); + msg_word = (uint32_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 = + (uint32_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 (cdf_unlikely(NULL == msdu)) { + cdf_print("%s: netbuf pop failed!\n", __func__); + *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. + */ + cdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_DMA_FROM_DEVICE); +#endif + + /* cache consistency has been taken care of by cdf_nbuf_unmap */ + rx_desc = htt_rx_desc(msdu); + + htt_rx_extract_lro_info(msdu, rx_desc); + + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + cdf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION); +#if HTT_PADDR64 +#define NEXT_FIELD_OFFSET_IN32 2 +#else /* ! HTT_PADDR64 */ +#define NEXT_FIELD_OFFSET_IN32 1 +#endif /* HTT_PADDR64 */ +# + cdf_nbuf_trim_tail(msdu, + HTT_RX_BUF_SIZE - + (RX_STD_DESC_SIZE + + HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET( + *(msg_word + NEXT_FIELD_OFFSET_IN32)))); +#if defined(HELIUMPLUS_DEBUG) + dump_pkt(msdu, 0, 64); +#endif + *((uint8_t *) &rx_desc->fw_desc.u.val) = + HTT_RX_IN_ORD_PADDR_IND_FW_DESC_GET(*(msg_word + NEXT_FIELD_OFFSET_IN32)); +#undef NEXT_FIELD_OFFSET_IN32 + + msdu_count--; + + if (cdf_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; + cdf_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 (cdf_unlikely(NULL == next)) { + cdf_print("%s: netbuf pop failed!\n", + __func__); + *tail_msdu = NULL; + return 0; + } + + /* if this is not the first msdu, update the + * next pointer of the preceding msdu + */ + if (prev) { + cdf_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 (cdf_unlikely(NULL == next)) { + cdf_print("%s: netbuf pop failed!\n", + __func__); + *tail_msdu = NULL; + return 0; + } + cdf_nbuf_set_next(msdu, next); + prev = msdu; + msdu = next; + } else { + *tail_msdu = msdu; + cdf_nbuf_set_next(msdu, NULL); + } + } + + return 1; +} + +/* Util fake function that has same prototype as cdf_nbuf_clone that just + * retures the same nbuf + */ +cdf_nbuf_t htt_rx_cdf_noclone_buf(cdf_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; +#ifdef HELIUMPLUS + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_ah_sig_a_2 & 0xFFF) << 4; + rs->rs_ratephy |= + (ppdu_start->ht_sig_vht_sig_ah_sig_a_1 & 0xFFFF) << 16; +#else + 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; +#endif + } + + 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. + */ +cdf_nbuf_t +htt_rx_restitch_mpdu_from_msdus(htt_pdev_handle pdev, + cdf_nbuf_t head_msdu, + struct ieee80211_rx_status *rx_status, + unsigned clone_not_reqd) +{ + + cdf_nbuf_t msdu, mpdu_buf, prev_buf, msdu_orig, head_frag_list_cloned; + cdf_nbuf_t (*clone_nbuf_fn)(cdf_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_cdf_noclone_buf : cdf_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 = cdf_nbuf_len(mpdu_buf); + + /* Drop the zero-length msdu */ + if (!msdu_len) + goto mpdu_stitch_fail; + + msdu_orig = cdf_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 = cdf_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 */ + cdf_nbuf_set_next_ext(prev_buf, msdu); + + /* Move to the next */ + prev_buf = msdu; + msdu_orig = cdf_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; + + cdf_nbuf_trim_tail(prev_buf, HTT_FCS_LEN); + + /* If there were more fragments to this RAW frame */ + if (head_frag_list_cloned) { + cdf_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 = cdf_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 = cdf_nbuf_put_tail(prev_buf, wifi_hdr_len); + if (!dest) + goto mpdu_stitch_fail; + cdf_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; + + /* 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 */ + cdf_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 = cdf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); + dest += amsdu_pad; + cdf_mem_copy(dest, hdr_desc, msdu_llc_len); + + /* Push the MSDU buffer beyond the decap header */ + cdf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); + frag_list_sum_len += + msdu_llc_len + cdf_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 + cdf_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 = cdf_nbuf_next(msdu_orig); + + } + + /* TODO: Convert this to suitable cdf routines */ + cdf_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) +#ifdef HELIUMPLUS + rx_status->rs_tstamp.tsf = + rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; +#else + rx_status->rs_tstamp.tsf = rx_desc->ppdu_end.tsf_timestamp; +#endif + /* 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 = cdf_nbuf_next(msdu); + cdf_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) + cdf_nbuf_free(mpdu_buf); + + /* Free the partial list */ + while (head_frag_list_cloned) { + msdu = head_frag_list_cloned; + head_frag_list_cloned = + cdf_nbuf_next_ext(head_frag_list_cloned); + cdf_nbuf_free(msdu); + } + } else { + /* Free the alloced head buffer */ + if (decap_format != HW_RX_DECAP_FORMAT_RAW) + if (mpdu_buf) + cdf_nbuf_free(mpdu_buf); + + /* Free the orig buffers */ + msdu = head_msdu; + while (msdu) { + msdu_orig = msdu; + msdu = cdf_nbuf_next(msdu); + cdf_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_rx_in_order_pop_ll. + */ +int (*htt_rx_amsdu_pop)(htt_pdev_handle pdev, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_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 + */ +int (*htt_rx_frag_pop)(htt_pdev_handle pdev, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_nbuf_t *tail_msdu); + +int +(*htt_rx_offload_msdu_pop)(htt_pdev_handle pdev, + cdf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + uint8_t *fw_desc, + cdf_nbuf_t *head_buf, cdf_nbuf_t *tail_buf); + +void * (*htt_rx_mpdu_desc_list_next)(htt_pdev_handle pdev, + cdf_nbuf_t rx_ind_msg); + +bool (*htt_rx_mpdu_desc_retry)( + htt_pdev_handle pdev, void *mpdu_desc); + +uint16_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); + +bool (*htt_rx_msdu_desc_completes_mpdu)(htt_pdev_handle pdev, void *msdu_desc); + +bool (*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); + +bool (*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, cdf_nbuf_t msdu); + +bool (*htt_rx_mpdu_is_encrypted)(htt_pdev_handle pdev, void *mpdu_desc); + +bool (*htt_rx_msdu_desc_key_id)(htt_pdev_handle pdev, + void *mpdu_desc, uint8_t *key_id); + +void *htt_rx_mpdu_desc_list_next_ll(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg) +{ + int idx = pdev->rx_ring.sw_rd_idx.msdu_desc; + cdf_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); +} + +bool (*htt_rx_msdu_chan_info_present)( + htt_pdev_handle pdev, + void *mpdu_desc); + +bool (*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_in_ord_mpdu_desc_list_next_ll(htt_pdev_handle pdev, + cdf_nbuf_t netbuf) +{ + return (void *)htt_rx_desc(netbuf); +} + +void *htt_rx_msdu_desc_retrieve_ll(htt_pdev_handle pdev, cdf_nbuf_t msdu) +{ + return htt_rx_desc(msdu); +} + +bool 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 (((*((uint32_t *) &rx_desc->mpdu_start)) & + RX_MPDU_START_0_ENCRYPTED_MASK) >> + RX_MPDU_START_0_ENCRYPTED_LSB) ? true : false; +} + +bool htt_rx_msdu_chan_info_present_ll(htt_pdev_handle pdev, void *mpdu_desc) +{ + return false; +} + +bool 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 false; +} + +bool +htt_rx_msdu_desc_key_id_ll(htt_pdev_handle pdev, void *mpdu_desc, + uint8_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 false; + + *key_id = ((*(((uint32_t *) &rx_desc->msdu_end) + 1)) & + (RX_MSDU_END_1_KEY_ID_OCT_MASK >> + RX_MSDU_END_1_KEY_ID_OCT_LSB)); + + return true; +} + +void htt_rx_desc_frame_free(htt_pdev_handle htt_pdev, cdf_nbuf_t msdu) +{ + cdf_nbuf_free(msdu); +} + +void htt_rx_msdu_desc_free(htt_pdev_handle htt_pdev, cdf_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 (cdf_atomic_dec_and_test(&pdev->rx_ring.refill_ref_cnt)) { + 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 */); + } + cdf_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, +}; + +/*--- RX In Order Hash Code --------------------------------------------------*/ + +/* Initializes the circular linked list */ +static inline void htt_list_init(struct htt_list_node *head) +{ + head->prev = head; + head->next = head; +} + +/* Adds entry to the end of the linked list */ +static inline void htt_list_add_tail(struct htt_list_node *head, + struct 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(struct 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(cdf_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, uint32_t paddr, + cdf_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 (cdf_unlikely(NULL == hash_element)) { + HTT_ASSERT_ALWAYS(0); + return 1; + } + + htt_list_remove(pdev->rx_ring.hash_table[i].freepool.next); + } else { + hash_element = cdf_mem_malloc(sizeof(struct htt_rx_hash_entry)); + if (cdf_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(cdf_print("rx hash: %s: paddr 0x%x netbuf %p bucket %d\n", + __func__, 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 */ +cdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr) +{ + uint32_t i; + struct htt_list_node *list_iter = NULL; + cdf_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) { + /* 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 + cdf_mem_free(hash_entry); + + break; + } + } + + RX_HASH_LOG(cdf_print("rx hash: %s: paddr 0x%x, netbuf %p, bucket %d\n", + __func__, paddr, netbuf, (int)i)); + HTT_RX_HASH_COUNT_PRINT(pdev->rx_ring.hash_table[i]); + + if (netbuf == NULL) { + cdf_print("rx hash: %s: no entry found for 0x%x!!!\n", + __func__, 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)); + + pdev->rx_ring.hash_table = + cdf_mem_malloc(RX_NUM_HASH_BUCKETS * + sizeof(struct htt_rx_hash_bucket)); + + if (NULL == pdev->rx_ring.hash_table) { + cdf_print("rx hash table allocation failed!\n"); + return 1; + } + + for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) { + 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); + + /* pre-allocate a pool of entries for this bucket */ + pdev->rx_ring.hash_table[i].entries = + cdf_mem_malloc(RX_ENTRIES_SIZE * + sizeof(struct htt_rx_hash_entry)); + + if (NULL == pdev->rx_ring.hash_table[i].entries) { + cdf_print("rx hash bucket %d entries alloc failed\n", + (int)i); + while (i) { + i--; + cdf_mem_free(pdev->rx_ring.hash_table[i]. + entries); + } + cdf_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 = + cdf_offsetof(struct htt_rx_hash_entry, listnode); + + return 0; +} + +void htt_rx_hash_dump_table(struct htt_pdev_t *pdev) +{ + uint32_t i; + struct htt_rx_hash_entry *hash_entry; + struct 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); + cdf_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) +{ + cdf_dma_addr_t paddr; +#if HTT_PADDR64 + uint32_t ring_elem_size = sizeof(uint64_t); +#else + uint32_t ring_elem_size = sizeof(uint32_t); +#endif /* HTT_PADDR64 */ + 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. + * 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. + */ + 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 = + cdf_os_mem_alloc_consistent(pdev->osdev, + sizeof(uint32_t), + &paddr, + cdf_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 = + cdf_mem_malloc(pdev->rx_ring.size * sizeof(cdf_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 = + cdf_os_mem_alloc_consistent( + pdev->osdev, + pdev->rx_ring.size * ring_elem_size, + &paddr, + cdf_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 = + cdf_os_mem_alloc_consistent( + pdev->osdev, + sizeof(uint32_t), + &paddr, + cdf_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. + */ + cdf_atomic_init(&pdev->rx_ring.refill_ref_cnt); + cdf_atomic_inc(&pdev->rx_ring.refill_ref_cnt); + + /* Initialize the Rx refill retry timer */ + cdf_softirq_timer_init(pdev->osdev, + &pdev->rx_ring.refill_retry_timer, + htt_rx_ring_refill_retry, (void *)pdev, + CDF_TIMER_TYPE_SW); + + 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 + htt_rx_ring_fill_n(pdev, pdev->rx_ring.fill_level); + + if (pdev->cfg.is_full_reorder_offload) { + cdf_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; + + return 0; /* success */ + +fail3: + cdf_os_mem_free_consistent(pdev->osdev, + pdev->rx_ring.size * sizeof(uint32_t), + pdev->rx_ring.buf.paddrs_ring, + pdev->rx_ring.base_paddr, + cdf_get_dma_mem_context((&pdev->rx_ring.buf), + memctx)); + +fail2: + if (pdev->cfg.is_full_reorder_offload) { + cdf_os_mem_free_consistent(pdev->osdev, + sizeof(uint32_t), + pdev->rx_ring.target_idx.vaddr, + pdev->rx_ring.target_idx.paddr, + cdf_get_dma_mem_context((&pdev-> + rx_ring. + target_idx), + memctx)); + htt_rx_hash_deinit(pdev); + } else { + cdf_mem_free(pdev->rx_ring.buf.netbufs_ring); + } + +fail1: + return 1; /* failure */ +} + +#ifdef IPA_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 = + cdf_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, + cdf_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) { + cdf_print("%s: RX IND RING alloc fail", __func__); + return -ENOBUFS; + } + + /* 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); + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx_ind_ring_size); + + /* Allocate RX process done index */ + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + 4, + &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, + cdf_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) { + cdf_print("%s: RX PROC DONE IND alloc fail", __func__); + cdf_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, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx_ind_ring_base), + memctx)); + return -ENOBUFS; + } + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr, 4); + + /* Allocate RX2 indication ring */ + /* RX2 IND ring element + * 4bytes: pointer + * 2bytes: VDEV ID + * 2bytes: length */ + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + rx_ind_ring_elements * + sizeof(struct ipa_uc_rx_ring_elem_t), + &pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx2_ind_ring_base), + memctx)); + if (!pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { + cdf_print("%s: RX IND RING alloc fail", __func__); + return -ENOBUFS; + } + + /* RX indication ring size, by bytes */ + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size = + rx_ind_ring_elements * sizeof(struct ipa_uc_rx_ring_elem_t); + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size); + + /* Allocate RX process done index */ + pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + 4, + &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx_ipa_prc_done_idx), + memctx)); + if (!pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { + cdf_print("%s: RX PROC DONE IND alloc fail", __func__); + cdf_os_mem_free_consistent( + pdev->osdev, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx2_ind_ring_base), + memctx)); + return -ENOBUFS; + } + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr, 4); + return 0; +} + +int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + if (pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { + cdf_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, + cdf_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) { + cdf_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, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx_ipa_prc_done_idx), + memctx)); + } + if (pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { + cdf_os_mem_free_consistent( + pdev->osdev, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx2_ind_ring_base), + memctx)); + } + + if (pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { + cdf_os_mem_free_consistent( + pdev->osdev, + 4, + pdev->ipa_uc_rx_rsc. + rx_ipa_prc_done_idx.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. + rx_ipa_prc_done_idx), + memctx)); + } + return 0; +} +#endif /* IPA_OFFLOAD */ diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c new file mode 100644 index 000000000000..92d847285c02 --- /dev/null +++ b/core/dp/htt/htt_t2h.c @@ -0,0 +1,935 @@ +/* + * 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 /* cdf_nbuf_t */ + +#include +#include +#include /* htt_tx_status */ + +#include /* HTT_TX_SCHED, etc. */ +#include +#include +#include +#include +/*--- target->host HTT message dispatch function ----------------------------*/ + +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +static uint8_t *htt_t2h_mac_addr_deswizzle(uint8_t *tgt_mac_addr, + uint8_t *buffer) +{ +#ifdef BIG_ENDIAN_HOST + /* + * The host endianness is opposite of the target endianness. + * To make uint32_t elements come out correctly, the target->host + * upload has swizzled the bytes in each uint32_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 +} + +static void htt_rx_frag_set_last_msdu(struct htt_pdev_t *pdev, cdf_nbuf_t msg) +{ + uint32_t *msg_word; + unsigned num_msdu_bytes; + cdf_nbuf_t msdu; + struct htt_host_rx_desc_base *rx_desc; + int start_idx; + uint8_t *p_fw_msdu_rx_desc = 0; + + msg_word = (uint32_t *) cdf_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 = ((uint8_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]; + cdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_DMA_FROM_DEVICE); + rx_desc = htt_rx_desc(msdu); + *((uint8_t *) &rx_desc->fw_desc.u.val) = *p_fw_msdu_rx_desc; + rx_desc->msdu_end.last_msdu = 1; + cdf_nbuf_map(pdev->osdev, msdu, CDF_DMA_FROM_DEVICE); +} + +/* Target to host Msg/event handler for low priority messages*/ +void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) +{ + struct htt_pdev_t *pdev = (struct htt_pdev_t *)context; + uint32_t *msg_word; + enum htt_t2h_msg_type msg_type; + + msg_word = (uint32_t *) cdf_nbuf_data(htt_t2h_msg); + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + switch (msg_type) { + case HTT_T2H_MSG_TYPE_VERSION_CONF: + { + pdev->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); + pdev->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); + cdf_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) + cdf_print + ("*** Incompatible host/target HTT versions!\n"); + /* abort if the target is incompatible with the host */ + cdf_assert(pdev->tgt_ver.major == + HTT_CURRENT_VERSION_MAJOR); + if (pdev->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { + cdf_print("*** Warning: host/target HTT versions are "); + cdf_print(" different, though compatible!\n"); + } + break; + } + case HTT_T2H_MSG_TYPE_RX_FLUSH: + { + uint16_t peer_id; + uint8_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: + { + uint16_t peer_id; + uint8_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: + { + uint16_t peer_id; + uint8_t tid; + uint8_t win_sz; + uint16_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: + { + uint16_t peer_id; + uint8_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: + { + uint8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; + uint8_t *peer_mac_addr; + uint16_t peer_id; + uint8_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( + (uint8_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: + { + uint16_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: + { + uint16_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; + + compl_msg = + (struct htt_mgmt_tx_compl_ind *)(msg_word + 1); + + ol_tx_single_completion_handler(pdev->txrx_pdev, + compl_msg->status, + compl_msg->desc_id); + HTT_TX_SCHED(pdev); + break; + } + case HTT_T2H_MSG_TYPE_STATS_CONF: + { + uint64_t cookie; + uint8_t *stats_info_list; + + cookie = *(msg_word + 1); + cookie |= ((uint64_t) (*(msg_word + 2))) << 32; + + stats_info_list = (uint8_t *) (msg_word + 3); + ol_txrx_fw_stats_handler(pdev->txrx_pdev, cookie, + stats_info_list); + break; + } +#ifndef REMOVE_PKT_LOG + case HTT_T2H_MSG_TYPE_PKTLOG: + { + uint32_t *pl_hdr; + uint32_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: + { + uint32_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; + ol_tx_credit_completion_handler(pdev->txrx_pdev, + htt_credit_delta); + break; + } + + case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE: + { + uint8_t op_code; + uint16_t len; + uint8_t *op_msg_buffer; + uint8_t *msg_start_ptr; + + msg_start_ptr = (uint8_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 = + cdf_mem_malloc(sizeof + (struct htt_wdi_ipa_op_response_t) + + len); + if (!op_msg_buffer) { + cdf_print("OPCODE messsage buffer alloc fail"); + break; + } + cdf_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; + } + + case HTT_T2H_MSG_TYPE_FLOW_POOL_MAP: + { + uint8_t num_flows; + struct htt_flow_pool_map_payload_t *pool_map_payoad; + + num_flows = HTT_FLOW_POOL_MAP_NUM_FLOWS_GET(*msg_word); + + msg_word++; + while (num_flows) { + pool_map_payoad = (struct htt_flow_pool_map_payload_t *) + msg_word; + ol_tx_flow_pool_map_handler(pool_map_payoad->flow_id, + pool_map_payoad->flow_type, + pool_map_payoad->flow_pool_id, + pool_map_payoad->flow_pool_size); + + msg_word += (HTT_FLOW_POOL_MAP_PAYLOAD_SZ / + HTT_FLOW_POOL_MAP_HEADER_SZ); + num_flows--; + } + break; + } + + case HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP: + { + struct htt_flow_pool_unmap_t *pool_numap_payload; + + pool_numap_payload = (struct htt_flow_pool_unmap_t *)msg_word; + ol_tx_flow_pool_unmap_handler(pool_numap_payload->flow_id, + pool_numap_payload->flow_type, + pool_numap_payload->flow_pool_id); + break; + } + + default: + break; + }; + /* Free the indication buffer */ + cdf_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; + cdf_nbuf_t htt_t2h_msg = (cdf_nbuf_t) pkt->pPktContext; + uint32_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++; + cdf_nbuf_free(htt_t2h_msg); + return; + } +#ifdef HTT_RX_RESTORE + if (cdf_unlikely(pdev->rx_ring.rx_reset)) { + cdf_print("rx restore ..\n"); + cdf_nbuf_free(htt_t2h_msg); + return; + } +#endif + + /* confirm alignment */ + HTT_ASSERT3((((unsigned long)cdf_nbuf_data(htt_t2h_msg)) & 0x3) == 0); + + msg_word = (uint32_t *) cdf_nbuf_data(htt_t2h_msg); + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s %d: msg_word 0x%x msg_type %d\n", + __func__, __LINE__, *msg_word, msg_type); +#endif + + switch (msg_type) { + case HTT_T2H_MSG_TYPE_RX_IND: + { + unsigned num_mpdu_ranges; + unsigned num_msdu_bytes; + uint16_t peer_id; + uint8_t tid; + + if (cdf_unlikely(pdev->cfg.is_full_reorder_offload)) { + cdf_print("HTT_T2H_MSG_TYPE_RX_IND not supported "); + cdf_print("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); + + 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; + + 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]; + } + } + 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: + { + uint16_t peer_id; + uint8_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 = (uint8_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: + { + uint16_t peer_id; + uint8_t tid; + uint8_t offload_ind, frag_ind; + + if (cdf_unlikely(!pdev->cfg.is_full_reorder_offload)) { + cdf_print("HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND not "); + cdf_print("supported when full reorder offload is "); + cdf_print("disabled in the configuration.\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 defined(HELIUMPLUS_DEBUG) + cdf_print("%s %d: peerid %d tid %d offloadind %d fragind %d\n", + __func__, __LINE__, peer_id, tid, offload_ind, + frag_ind); +#endif + if (cdf_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 */ + cdf_nbuf_free(htt_t2h_msg); +} + +/*--- target->host HTT message Info Element access methods ------------------*/ + +/*--- tx completion message ---*/ + +uint16_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 *(((uint16_t *) iterator) + num); +} + +/*--- rx indication message ---*/ + +int htt_rx_ind_flush(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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, + cdf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, unsigned *seq_num_end) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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, cdf_nbuf_t rx_ind_msg) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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, + cdf_nbuf_t rx_ind_msg, + unsigned *seq_num_start, unsigned *seq_num_end) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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, + cdf_nbuf_t rx_ind_msg, + int mpdu_range_num, + enum htt_rx_status *status, int *mpdu_count) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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, cdf_nbuf_t rx_ind_msg) +{ + int8_t rssi; + uint32_t *msg_word; + + msg_word = (uint32_t *) + (cdf_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, or HTT_INVALID_RSSI + */ +int16_t +htt_rx_ind_rssi_dbm_chain(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg, + int8_t chain) +{ + int8_t rssi; + uint32_t *msg_word; + + if (chain < 0 || chain > 3) + return HTT_RSSI_INVALID; + + msg_word = (uint32_t *) + (cdf_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, cdf_nbuf_t rx_ind_msg, + uint8_t *legacy_rate, uint8_t *legacy_rate_sel) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) + (cdf_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, cdf_nbuf_t rx_ind_msg, + uint32_t *timestamp_microsec, + uint8_t *timestamp_submicrosec) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) + (cdf_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); +} + +#define INVALID_TSF -1 +/** + * 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, cdf_nbuf_t rx_ind_msg) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) + (cdf_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 INVALID_TSF; + + 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, cdf_nbuf_t rx_ind_msg) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) + (cdf_nbuf_data(rx_ind_msg)); + + return HTT_RX_IND_EXT_TID_GET(*msg_word); +} + +/*--- stats confirmation message ---*/ + +void +htt_t2h_dbg_stats_hdr_parse(uint8_t *stats_info_list, + enum htt_dbg_stats_type *type, + enum htt_dbg_stats_status *status, + int *length, uint8_t **stats_data) +{ + uint32_t *msg_word = (uint32_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 len */ + *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, + cdf_nbuf_t rx_frag_ind_msg, + int *seq_num_start, int *seq_num_end) +{ + uint32_t *msg_word; + + msg_word = (uint32_t *) cdf_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/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c new file mode 100644 index 000000000000..dc25cbc2e000 --- /dev/null +++ b/core/dp/htt/htt_tx.c @@ -0,0 +1,864 @@ +/* + * 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_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 /* uint32_t, offsetof, etc. */ +#include /* cdf_dma_addr_t */ +#include /* cdf_os_mem_alloc_consistent et al */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_mdelay */ + +#include /* htt_tx_msdu_desc_t */ +#include /* HTC_HDR_LENGTH */ +#include /* htc_flush_surprise_remove */ +#include /* ol_cfg_netbuf_frags_max, etc. */ +#include /* HTT_TX_DESC_VADDR_OFFSET */ +#include /* ol_tx_msdu_id_storage */ +#include + +/* 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 subtyp | 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 + +/*--- setup / tear-down functions -------------------------------------------*/ + +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS +uint32_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, pool_size; + uint32_t **p; + cdf_dma_addr_t pool_paddr; + +#if defined(HELIUMPLUS_PADDR64) + pdev->tx_descs.size = sizeof(struct htt_host_tx_desc_t); + + if (HTT_WIFI_IP_VERSION(pdev->wifi_ip_ver.major, 0x2)) { + /* + * sizeof MSDU_EXT/Fragmentation descriptor. + */ + pdev->frag_descs.size = sizeof(struct msdu_ext_desc_t); + } else { + /* + * 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) + */ + pdev->frag_descs.size = + (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev)+1) * 8 + + 4; + } +#else /* ! defined(HELIUMPLUS_PADDR64) */ + /* + * Start with the size of the base struct + * that actually gets downloaded. + * + * 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) + */ + pdev->tx_descs.size = + sizeof(struct htt_host_tx_desc_t) + + (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev) + 1) * 8 + /* 2x uint32_t */ + + 4; /* uint32_t fragmentation list terminator */ + + if (pdev->tx_descs.size < sizeof(uint32_t *)) + pdev->tx_descs.size = sizeof(uint32_t *); +#endif /* defined(HELIUMPLUS_PADDR64) */ + /* + * 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; + + pdev->tx_descs.pool_vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, pool_size, + &pool_paddr, + cdf_get_dma_mem_context((&pdev->tx_descs), memctx)); + + pdev->tx_descs.pool_paddr = pool_paddr; + + if (!pdev->tx_descs.pool_vaddr) + return -ENOBUFS; /* failure */ + + cdf_print("%s:htt_desc_start:0x%p htt_desc_end:0x%p\n", __func__, + pdev->tx_descs.pool_vaddr, + (uint32_t *) (pdev->tx_descs.pool_vaddr + pool_size)); + +#if defined(HELIUMPLUS_PADDR64) + pdev->frag_descs.pool_elems = desc_pool_elems; + /* + * Allocate space for MSDU extension descriptor + * H/W expects this in contiguous memory + */ + pool_size = pdev->frag_descs.pool_elems * pdev->frag_descs.size; + + pdev->frag_descs.pool_vaddr = cdf_os_mem_alloc_consistent( + pdev->osdev, pool_size, &pool_paddr, + cdf_get_dma_mem_context((&pdev->frag_descs), memctx)); + + if (!pdev->frag_descs.pool_vaddr) + return -ENOBUFS; /* failure */ + + pdev->frag_descs.pool_paddr = pool_paddr; + + cdf_print("%s:MSDU Ext.Table Start:0x%p MSDU Ext.Table End:0x%p\n", + __func__, pdev->frag_descs.pool_vaddr, + (u_int32_t *) (pdev->frag_descs.pool_vaddr + pool_size)); +#endif /* defined(HELIUMPLUS_PADDR64) */ + +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS + g_dbg_htt_desc_end_addr = (uint32_t *) + (pdev->tx_descs.pool_vaddr + pool_size); + g_dbg_htt_desc_start_addr = (uint32_t *) pdev->tx_descs.pool_vaddr; +#endif + + /* link tx descriptors into a freelist */ + pdev->tx_descs.freelist = (uint32_t *) pdev->tx_descs.pool_vaddr; + p = (uint32_t **) pdev->tx_descs.freelist; + for (i = 0; i < desc_pool_elems - 1; i++) { + *p = (uint32_t *) (((char *)p) + pdev->tx_descs.size); + p = (uint32_t **) *p; + } + *p = NULL; + + return 0; /* success */ +} + +void htt_tx_detach(struct htt_pdev_t *pdev) +{ + if (pdev) { + cdf_os_mem_free_consistent( + pdev->osdev, + /* pool_size */ + pdev->tx_descs.pool_elems * pdev->tx_descs.size, + pdev->tx_descs.pool_vaddr, + pdev->tx_descs.pool_paddr, + cdf_get_dma_mem_context((&pdev->tx_descs), memctx)); +#if defined(HELIUMPLUS_PADDR64) + cdf_os_mem_free_consistent( + pdev->osdev, + /* pool_size */ + pdev->frag_descs.pool_elems * + pdev->frag_descs.size, + pdev->frag_descs.pool_vaddr, + pdev->frag_descs.pool_paddr, + cdf_get_dma_mem_context((&pdev->frag_descs), memctx)); +#endif /* defined(HELIUMPLUS_PADDR64) */ + } +} + +/*--- descriptor allocation functions ---------------------------------------*/ + +void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo) +{ + struct htt_host_tx_desc_t *htt_host_tx_desc; /* includes HTC hdr */ + struct htt_tx_msdu_desc_t *htt_tx_desc; /* doesn't include HTC hdr */ + uint16_t index; + uint32_t *fragmentation_descr_field_ptr; + + 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 = + *((uint32_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. + */ + fragmentation_descr_field_ptr = (uint32_t *) + ((uint32_t *) htt_tx_desc) + + HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD; + + index = ((char *)htt_host_tx_desc - + (char *)(((struct htt_host_tx_desc_t *) + pdev->tx_descs.pool_vaddr))) / + pdev->tx_descs.size; + /* + * The fragmentation descriptor is allocated from consistent + * memory. Therefore, we can use the address directly rather + * than having to map it from a virtual/CPU address to a + * physical/bus address. + */ +#if defined(HELIUMPLUS_PADDR64) +#if HTT_PADDR64 + /* this is: frags_desc_ptr.lo */ + *fragmentation_descr_field_ptr = (uint32_t) + (pdev->frag_descs.pool_paddr + + (pdev->frag_descs.size * index)); + fragmentation_descr_field_ptr++; + /* frags_desc_ptr.hi */ + *fragmentation_descr_field_ptr = 0; +#else /* ! HTT_PADDR64 */ + *fragmentation_descr_field_ptr = (uint32_t) + (pdev->frag_descs.pool_paddr + + (pdev->frag_descs.size * index)); + cdf_print("%s %d: i %d frag_paddr 0x%x\n", + __func__, __LINE__, index, + (*fragmentation_descr_field_ptr)); +#endif /* HTT_PADDR64 */ +#else /* !HELIUMPLUS_PADDR64 */ + *fragmentation_descr_field_ptr = + HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN; +#endif /* HELIUMPLUS_PADDR64 */ + + /* + * Include the headroom for the HTC frame header when specifying the + * physical address for the HTT tx descriptor. + */ + *paddr_lo = (uint32_t) HTT_TX_DESC_PADDR(pdev, 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); + *((uint32_t **) htt_host_tx_desc) = pdev->tx_descs.freelist; + pdev->tx_descs.freelist = (uint32_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, + uint32_t paddr, + uint32_t frag_desc_paddr_lo, + int reset) +{ + uint32_t *fragmentation_descr_field_ptr; + + fragmentation_descr_field_ptr = (uint32_t *) + ((uint32_t *) htt_tx_desc) + + HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD; + if (reset) { +#if defined(HELIUMPLUS_PADDR64) + *fragmentation_descr_field_ptr = frag_desc_paddr_lo; +#else + *fragmentation_descr_field_ptr = + HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN; +#endif + } else { + *fragmentation_descr_field_ptr = paddr; + } +} + +#if defined(HELIUMPLUS_PADDR64) +void * +htt_tx_frag_alloc(htt_pdev_handle pdev, + u_int16_t index, + u_int32_t *frag_paddr_lo) +{ + /** Index should never be 0, since its used by the hardware + to terminate the link. */ + if (index >= pdev->tx_descs.pool_elems) + return NULL; + + *frag_paddr_lo = (uint32_t) + (pdev->frag_descs.pool_paddr + (pdev->frag_descs.size * index)); + + return ((char *) pdev->frag_descs.pool_vaddr) + + (pdev->frag_descs.size * index); +} +#endif /* defined(HELIUMPLUS_PADDR64) */ + +/* PUT THESE AS INLINE IN ol_htt_tx_api.h */ + +void htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc) +{ +} + +void htt_tx_pending_discard(htt_pdev_handle pdev) +{ + htc_flush_surprise_remove(pdev->htc_pdev); +} + +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) +{ + cdf_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 = cdf_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 + * of 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 = + htc_send_data_pkt(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, cdf_nbuf_t msdu, uint16_t msdu_id) +{ + + int download_len = pdev->download_len; + + int packet_len; + + /* packet length includes HTT tx desc frag added above */ + packet_len = cdf_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 of 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; + } + + NBUF_UPDATE_TX_PKT_COUNT(msdu, NBUF_TX_PKT_HTT); + DPTRACE(cdf_dp_trace(msdu, CDF_DP_TRACE_HTT_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(msdu)), + sizeof(cdf_nbuf_data(msdu)))); + if (cdf_nbuf_queue_len(&pdev->txnbufq) > 0) { + HTT_TX_NBUF_QUEUE_ADD(pdev, msdu); + htt_tx_sched(pdev); + return 0; + } + + cdf_nbuf_trace_update(msdu, "HT:T:"); + if (htc_send_data_pkt + (pdev->htc_pdev, msdu, pdev->htc_endpoint, download_len)) { + HTT_TX_NBUF_QUEUE_ADD(pdev, msdu); + } + + return 0; /* success */ + +} + +cdf_nbuf_t +htt_tx_send_batch(htt_pdev_handle pdev, cdf_nbuf_t head_msdu, int num_msdus) +{ + cdf_print("*** %s curently only applies for HL systems\n", __func__); + cdf_assert(0); + return head_msdu; + +} + +int +htt_tx_send_nonstd(htt_pdev_handle pdev, + cdf_nbuf_t msdu, + uint16_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); + cdf_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, cdf_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) && + cdf_nbuf_get_tx_parallel_dnload_frm(msdu) && + (cdf_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, + cdf_nbuf_t msdu, + uint16_t msdu_id, int download_len, uint8_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 *) + cdf_nbuf_get_frag_vaddr(msdu, 0); + + pkt = htt_htc_pkt_alloc(pdev); + if (!pkt) + return -ENOBUFS; /* failure */ + + pkt->msdu_id = msdu_id; + pkt->pdev_ctxt = pdev->txrx_pdev; + + /* packet length includes HTT tx desc frag added above */ + packet_len = cdf_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); + + cdf_nbuf_trace_update(msdu, "HT:T:"); + NBUF_UPDATE_TX_PKT_COUNT(msdu, NBUF_TX_PKT_HTT); + DPTRACE(cdf_dp_trace(msdu, CDF_DP_TRACE_HTT_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(msdu)), + sizeof(cdf_nbuf_data(msdu)))); + htc_send_data_pkt(pdev->htc_pdev, &pkt->htc_pkt, more_data); + + return 0; /* success */ +} + +cdf_nbuf_t +htt_tx_send_batch(htt_pdev_handle pdev, cdf_nbuf_t head_msdu, int num_msdus) +{ + cdf_nbuf_t rejected = NULL; + uint16_t *msdu_id_storage; + uint16_t msdu_id; + cdf_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--) { + cdf_nbuf_t next_msdu = cdf_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)) { + cdf_nbuf_set_next(msdu, rejected); + rejected = msdu; + } + msdu = next_msdu; + } + return rejected; +} + +int +htt_tx_send_nonstd(htt_pdev_handle pdev, + cdf_nbuf_t msdu, + uint16_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, cdf_nbuf_t msdu, uint16_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 */ + cdf_print("HTT tx desc (@ %p):\n", htt_tx_desc); + cdf_print(" msg type = %d\n", htt_tx_desc->msg_type); + cdf_print(" pkt subtype = %d\n", htt_tx_desc->pkt_subtype); + cdf_print(" pkt type = %d\n", htt_tx_desc->pkt_type); + cdf_print(" vdev ID = %d\n", htt_tx_desc->vdev_id); + cdf_print(" ext TID = %d\n", htt_tx_desc->ext_tid); + cdf_print(" postponed = %d\n", htt_tx_desc->postponed); +#if HTT_PADDR64 + cdf_print(" reserved_dword0_bits28 = %d\n", htt_tx_desc->reserved_dword0_bits28); + cdf_print(" cksum_offload = %d\n", htt_tx_desc->cksum_offload); + cdf_print(" tx_compl_req= %d\n", htt_tx_desc->tx_compl_req); +#else /* !HTT_PADDR64 */ + cdf_print(" batch more = %d\n", htt_tx_desc->more_in_batch); +#endif /* HTT_PADDR64 */ + cdf_print(" length = %d\n", htt_tx_desc->len); + cdf_print(" id = %d\n", htt_tx_desc->id); +#if HTT_PADDR64 + cdf_print(" frag desc addr.lo = %#x\n", + htt_tx_desc->frags_desc_ptr.lo); + cdf_print(" frag desc addr.hi = %#x\n", + htt_tx_desc->frags_desc_ptr.hi); + cdf_print(" peerid = %d\n", htt_tx_desc->peerid); + cdf_print(" chanfreq = %d\n", htt_tx_desc->chanfreq); +#else /* ! HTT_PADDR64 */ + cdf_print(" frag desc addr = %#x\n", htt_tx_desc->frags_desc_ptr); +#endif /* HTT_PADDR64 */ +} +#endif + +#ifdef IPA_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; + cdf_nbuf_t buffer_vaddr; + uint32_t buffer_paddr; + uint32_t *header_ptr; + uint32_t *ring_vaddr; + int return_code = 0; + unsigned int tx_comp_ring_size; + + /* Allocate CE Write Index WORD */ + pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + 4, + &pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, + cdf_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), + memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { + cdf_print("%s: CE Write Index WORD alloc fail", __func__); + return -ENOBUFS; + } + + /* Allocate TX COMP Ring */ + tx_comp_ring_size = uc_tx_buf_cnt * sizeof(cdf_nbuf_t); + pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + tx_comp_ring_size, + &pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_tx_rsc. + tx_comp_base), + memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { + cdf_print("%s: TX COMP ring alloc fail", __func__); + return_code = -ENOBUFS; + goto free_tx_ce_idx; + } + + cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, tx_comp_ring_size); + + /* Allocate TX BUF vAddress Storage */ + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg = + (cdf_nbuf_t *) cdf_mem_malloc(uc_tx_buf_cnt * + sizeof(cdf_nbuf_t)); + if (!pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg) { + cdf_print("%s: TX BUF POOL vaddr storage alloc fail", __func__); + return_code = -ENOBUFS; + goto free_tx_comp_base; + } + cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg, + uc_tx_buf_cnt * sizeof(cdf_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 = cdf_nbuf_alloc(pdev->osdev, + uc_tx_buf_sz, 0, 4, false); + if (!buffer_vaddr) { + cdf_print("%s: TX BUF alloc fail, loop index: %d", + __func__, tx_buffer_count); + return 0; + } + + /* Init buffer */ + cdf_mem_zero(cdf_nbuf_data(buffer_vaddr), uc_tx_buf_sz); + header_ptr = (uint32_t *) cdf_nbuf_data(buffer_vaddr); + + /* HTT control header */ + *header_ptr = HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT; + header_ptr++; + + /* PKT ID */ + *header_ptr |= ((uint16_t) uc_tx_partition_base + + tx_buffer_count) << 16; + + cdf_nbuf_map(pdev->osdev, buffer_vaddr, CDF_DMA_BIDIRECTIONAL); + buffer_paddr = cdf_nbuf_get_frag_paddr_lo(buffer_vaddr, 0); + header_ptr++; + + /* Frag Desc Pointer */ + /* 64bits descriptor, Low 32bits */ + *header_ptr = (uint32_t) (buffer_paddr + 20); + header_ptr++; + + /* 64bits descriptor, high 32bits */ + *header_ptr = 0; + header_ptr++; + + /* chanreq, peerid */ + *header_ptr = 0xFFFFFFFF; + + /* FRAG Header */ + /* 6 words TSO header */ + header_ptr += 6; + *header_ptr = buffer_paddr + 64; + + *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 += 2; + } + + pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; + + return 0; + +free_tx_comp_base: + cdf_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, + cdf_get_dma_mem_context((&pdev-> + ipa_uc_tx_rsc. + tx_comp_base), + memctx)); +free_tx_ce_idx: + cdf_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, + cdf_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) +{ + uint16_t idx; + + if (pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { + cdf_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, + cdf_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), + memctx)); + } + + if (pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { + cdf_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, + cdf_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]) { + cdf_nbuf_unmap(pdev->osdev, + pdev->ipa_uc_tx_rsc. + tx_buf_pool_vaddr_strg[idx], + CDF_DMA_FROM_DEVICE); + cdf_nbuf_free(pdev->ipa_uc_tx_rsc. + tx_buf_pool_vaddr_strg[idx]); + } + } + + /* Free storage */ + cdf_mem_free(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg); + + return 0; +} +#endif /* IPA_OFFLOAD */ + +#if defined(FEATURE_TSO) +void +htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc, + struct cdf_tso_info_t *tso_info) +{ + u_int32_t *word; + int i; + struct cdf_tso_seg_elem_t *tso_seg = tso_info->curr_seg; + struct msdu_ext_desc_t *msdu_ext_desc = (struct msdu_ext_desc_t *)desc; + + word = (u_int32_t *)(desc); + + /* Initialize the TSO flags per MSDU */ + ((struct msdu_ext_desc_t *)msdu_ext_desc)->tso_flags = + tso_seg->seg.tso_flags; + + /* First 24 bytes (6*4) contain the TSO flags */ + word += 6; + + for (i = 0; i < tso_seg->seg.num_frags; i++) { + /* [31:0] first 32 bits of the buffer pointer */ + *word = tso_seg->seg.tso_frags[i].paddr_low_32; + word++; + /* [15:0] the upper 16 bits of the first buffer pointer */ + /* [31:16] length of the first buffer */ + *word = (tso_seg->seg.tso_frags[i].length << 16); + word++; + } + + if (tso_seg->seg.num_frags < FRAG_NUM_MAX) { + *word = 0; + word++; + *word = 0; + } +} +#endif /* FEATURE_TSO */ diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h new file mode 100644 index 000000000000..4082a850e210 --- /dev/null +++ b/core/dp/htt/htt_types.h @@ -0,0 +1,373 @@ +/* + * 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 _HTT_TYPES__H_ +#define _HTT_TYPES__H_ + +#include /* uint16_t, dma_addr_t */ +#include /* cdf_device_t */ +#include /* cdf_spinlock_t */ +#include /* cdf_softirq_timer_t */ +#include /* cdf_atomic_inc */ +#include /* cdf_nbuf_t */ +#include /* HTC_PACKET */ + +#include /* ol_pdev_handle */ +#include /* ol_txrx_pdev_handle */ + +#define DEBUG_DMA_DONE + +#define HTT_TX_MUTEX_TYPE cdf_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 */ + + +struct htt_htc_pkt { + void *pdev_ctxt; + dma_addr_t nbuf_paddr; + HTC_PACKET htc_pkt; + uint16_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. + * htc_send_data_pkt expects this header space at the front of the + * initial fragment (i.e. tx descriptor) that is downloaded. + */ +struct htt_host_tx_desc_t { + uint8_t htc_header[HTC_HEADER_LEN]; + /* force the tx_desc field to begin on a 4-byte boundary */ + union { + uint32_t dummy_force_align; + struct htt_tx_msdu_desc_t tx_desc; + } align32; +}; + +struct htt_tx_mgmt_desc_buf { + cdf_nbuf_t msg_buf; + A_BOOL is_inuse; + cdf_nbuf_t mgmt_frm; +}; + +struct htt_tx_mgmt_desc_ctxt { + struct htt_tx_mgmt_desc_buf *pool; + A_UINT32 pending_cnt; +}; + +struct htt_list_node { + struct htt_list_node *prev; + struct htt_list_node *next; +}; + +struct htt_rx_hash_entry { + A_UINT32 paddr; + cdf_nbuf_t netbuf; + A_UINT8 fromlist; + struct htt_list_node listnode; +#ifdef RX_HASH_DEBUG + A_UINT32 cookie; +#endif +}; + +struct htt_rx_hash_bucket { + struct htt_list_node listhead; + struct htt_rx_hash_entry *entries; + struct htt_list_node freepool; +#ifdef RX_HASH_DEBUG + A_UINT32 count; +#endif +}; + +/* IPA micro controller + wlan host driver + firmware shared memory structure */ +struct uc_shared_mem_t { + uint32_t *vaddr; + cdf_dma_addr_t paddr; + cdf_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; + + uint32_t tx_comp_idx_paddr; + cdf_nbuf_t *tx_buf_pool_vaddr_strg; + uint32_t alloc_tx_buf_cnt; +}; + +/* Micro controller datapath offload + * WLAN RX resources */ +struct htt_ipa_uc_rx_resource_t { + cdf_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; + uint32_t rx_ind_ring_size; + + /* 2nd RX ring */ + cdf_dma_addr_t rx2_rdy_idx_paddr; + struct uc_shared_mem_t rx2_ind_ring_base; + struct uc_shared_mem_t rx2_ipa_prc_done_idx; + uint32_t rx2_ind_ring_size; +}; + +struct ipa_uc_rx_ring_elem_t { + uint32_t rx_packet_paddr; + uint16_t vdev_id; + uint16_t rx_packet_leng; +}; + +#if defined(HELIUMPLUS_PADDR64) +struct msdu_ext_desc_t { +#if defined(FEATURE_TSO) + struct cdf_tso_flags_t tso_flags; +#else + u_int32_t tso_flag0; + u_int32_t tso_flag1; + u_int32_t tso_flag2; + u_int32_t tso_flag3; + u_int32_t tso_flag4; + u_int32_t tso_flag5; +#endif + u_int32_t frag_ptr0; + u_int32_t frag_len0; + u_int32_t frag_ptr1; + u_int32_t frag_len1; + u_int32_t frag_ptr2; + u_int32_t frag_len2; + u_int32_t frag_ptr3; + u_int32_t frag_len3; + u_int32_t frag_ptr4; + u_int32_t frag_len4; + u_int32_t frag_ptr5; + u_int32_t frag_len5; +}; +#endif /* defined(HELIUMPLUS_PADDR64) */ + +struct htt_pdev_t { + ol_pdev_handle ctrl_pdev; + ol_txrx_pdev_handle txrx_pdev; + HTC_HANDLE htc_pdev; + cdf_device_t osdev; + + HTC_ENDPOINT_ID htc_endpoint; + +#ifdef QCA_TX_HTT2_SUPPORT + HTC_ENDPOINT_ID htc_tx_htt2_endpoint; + uint16_t htc_tx_htt2_max_size; +#endif /* QCA_TX_HTT2_SUPPORT */ + +#ifdef ATH_11AC_TXCOMPACT + HTT_TX_MUTEX_TYPE txnbufq_mutex; + cdf_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_full_reorder_offload; + int default_tx_comp_req; + int ce_classify_enabled; + } cfg; + struct { + uint8_t major; + uint8_t minor; + } tgt_ver; +#if defined(HELIUMPLUS_PADDR64) + struct { + u_int8_t major; + u_int8_t minor; + } wifi_ip_ver; +#endif /* defined(HELIUMPLUS_PADDR64) */ + 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 nw + * buffer objects whose data buffers the HW has filled. + */ + cdf_nbuf_t *netbufs_ring; + /* + * Ring of buffer addresses - + * This ring holds the "physical" device address of the + * rx buffers the host SW provides for MAC HW to fill. + */ +#if HTT_PADDR64 + uint64_t *paddrs_ring; +#else /* ! HTT_PADDR64 */ + uint32_t *paddrs_ring; +#endif + cdf_dma_mem_context(memctx); + } buf; + /* + * Base address of ring, as a "physical" device address rather + * than a CPU address. + */ + uint32_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; /* # of rx buffers (full+empty) 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 { + uint32_t *vaddr; + uint32_t paddr; + cdf_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 { + uint32_t *vaddr; + uint32_t paddr; + cdf_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 + */ + cdf_softirq_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. + */ + cdf_atomic_t refill_ref_cnt; +#ifdef DEBUG_DMA_DONE + uint32_t dbg_initial_msdu_payld; + uint32_t dbg_mpdu_range; + uint32_t dbg_mpdu_count; + uint32_t dbg_ring_idx; + uint32_t dbg_refill_cnt; + uint32_t dbg_sync_success; +#endif +#ifdef HTT_RX_RESTORE + int rx_reset; + uint8_t htt_rx_restore; +#endif + struct htt_rx_hash_bucket *hash_table; + uint32_t listnode_offset; + } rx_ring; + 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; + uint32_t pool_paddr; + uint32_t *freelist; + cdf_dma_mem_context(memctx); + } tx_descs; +#if defined(HELIUMPLUS_PADDR64) + struct { + int size; /* of each Fragment/MSDU-Ext descriptor */ + int pool_elems; + char *pool_vaddr; + uint32_t pool_paddr; + cdf_dma_mem_context(memctx); + } frag_descs; +#endif /* defined(HELIUMPLUS_PADDR64) */ + + int download_len; + void (*tx_send_complete_part2)(void *pdev, A_STATUS status, + cdf_nbuf_t msdu, uint16_t msdu_id); + + HTT_TX_MUTEX_TYPE htt_tx_mutex; + + struct { + int htc_err_cnt; + } stats; + + struct htt_tx_mgmt_desc_ctxt tx_mgmt_desc_ctxt; + struct targetdef_s *targetdef; + struct ce_reg_def *target_ce_def; + + struct htt_ipa_uc_tx_resource_t ipa_uc_tx_rsc; + struct htt_ipa_uc_rx_resource_t ipa_uc_rx_rsc; +}; + +#define HTT_EPID_GET(_htt_pdev_hdl) \ + (((struct htt_pdev_t *)(_htt_pdev_hdl))->htc_endpoint) + +#if defined(HELIUMPLUS_PADDR64) +#define HTT_WIFI_IP(pdev, x, y) (((pdev)->wifi_ip_ver.major == (x)) && \ + ((pdev)->wifi_ip_ver.minor == (y))) + +#define HTT_SET_WIFI_IP(pdev, x, y) (((pdev)->wifi_ip_ver.major = (x)) && \ + ((pdev)->wifi_ip_ver.minor = (y))) +#endif /* defined(HELIUMPLUS_PADDR64) */ + +#endif /* _HTT_TYPES__H_ */ diff --git a/core/dp/htt/rx_desc.h b/core/dp/htt/rx_desc.h new file mode 100644 index 000000000000..66963d1e2b30 --- /dev/null +++ b/core/dp/htt/rx_desc.h @@ -0,0 +1,533 @@ +/* + * 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 _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] */ + volatile + uint32_t ring4_more_count:8, /* [7:0] */ + ring5_more_count:8, /* [15:8] */ + ring6_more_count:8, /* [23:16] */ + ring7_more_count:8; /* [31:24] */ +}; + +struct rx_msdu_start { + volatile + uint32_t msdu_length:14, /* [13:0] */ +#if defined(HELIUMPLUS) + l3_offset:7, /* [20:14] */ + ipsec_ah:1, /* [21] */ + reserved_0a:2, /* [23:22] */ + l4_offset:7, /* [30:24] */ + ipsec_esp:1; /* [31] */ +#else + ip_offset:6, /* [19:14] */ + ring_mask:4, /* [23:20] */ + tcp_udp_offset:7, /* [30:24] */ + reserved_0c:1; /* [31] */ +#endif /* defined(HELIUMPLUS) */ +#if defined(HELIUMPLUS) + volatile uint32_t flow_id_toeplitz:32; /* [31:0] */ +#else + volatile uint32_t flow_id_crc:32; /* [31:0] */ +#endif /* defined(HELIUMPLUS) */ + 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] */ +#if defined(HELIUMPLUS_PADDR64) + volatile + uint32_t da_idx:11, /* [10:0] */ + da_is_bcast_mcast:1, /* [11] */ + reserved_3a:4, /* [15:12] */ + ip4_protocol_ip6_next_header:8, /* [23:16] */ + ring_mask:8; /* [31:24] */ + volatile uint32_t toeplitz_hash_2_or_4:32; /* [31:0] */ +#endif /* defined(HELIUMPLUS_PADDR64) */ +}; + +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] */ +#if defined(HELIUMPLUS) + classification_rule:6, /* [13:8] */ + classify_not_done_truncate:1, /* [14] */ + classify_not_done_cce_dis:1, /* [15] */ +#else + classification_filter:8, /* [15:8] */ +#endif /* defined(HELIUMPLUS) */ + 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] */ +#if defined(HELIUMPLUS) + sa_idx_timeout:1, /* [16] */ + da_idx_timeout:1, /* [17] */ + msdu_limit_error:1, /* [18] */ + classify_ring_mask:8, /* [26:19] */ +#endif /* defined(HELIUMPLUS) */ + reserved_3a:3, /* [29:27] */ + pre_delim_err:1, /* [30] */ + reserved_3b:1; /* [31] */ +#if defined(HELIUMPLUS_PADDR64) + volatile uint32_t ipv6_options_crc:32; + volatile uint32_t tcp_seq_number:32; + volatile uint32_t tcp_ack_number:32; + volatile + uint32_t tcp_flag:9, /* [8:0] */ + lro_eligible:1, /* [9] */ + l3_header_padding:3, /* [12:10] */ + reserved_8a:3, /* [15:13] */ + window_size:16; /* [31:16] */ + volatile + uint32_t da_offset:6, /* [5:0] */ + sa_offset:6, /* [11:6] */ + da_offset_valid:1, /* [12] */ + sa_offset_valid:1, /* [13] */ + type_offset:7, /* [20:14] */ + reserved_9a:11; /* [31:21] */ + volatile uint32_t rule_indication_31_0:32; + volatile uint32_t rule_indication_63_32:32; + volatile uint32_t rule_indication_95_64:32; + volatile uint32_t rule_indication_127_96:32; +#endif /* defined(HELIUMPLUS_PADDR64) */ +}; + +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] */ +}; + + +#if defined(HELIUMPLUS) + +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] */ + reserved: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] */ + toeplitz_hash:2, /* [17:16] */ + reserved_2:10, /* [27:18] */ + tid:4; /* [31:28] */ +}; + + +struct rx_ppdu_start { + volatile + uint32_t rssi_pri_chain0:8, /* [7:0] */ + rssi_sec20_chain0:8, /* [15:8] */ + rssi_sec40_chain0:8, /* [23:16] */ + rssi_sec80_chain0:8; /* [31:24] */ + volatile + uint32_t rssi_pri_chain1:8, /* [7:0] */ + rssi_sec20_chain1:8, /* [15:8] */ + rssi_sec40_chain1:8, /* [23:16] */ + rssi_sec80_chain1:8; /* [31:24] */ + volatile + uint32_t rssi_pri_chain2:8, /* [7:0] */ + rssi_sec20_chain2:8, /* [15:8] */ + rssi_sec40_chain2:8, /* [23:16] */ + rssi_sec80_chain2:8; /* [31:24] */ + volatile + uint32_t rssi_pri_chain3:8, /* [7:0] */ + rssi_sec20_chain3:8, /* [15:8] */ + rssi_sec40_chain3:8, /* [23:16] */ + rssi_sec80_chain3:8; /* [31:24] */ + volatile + uint32_t rssi_comb:8, /* [7:0] */ + bandwidth:3, /* [10:8] */ + reserved_4a:5, /* [15:11] */ + rssi_comb_ht:8, /* [23:16] */ + reserved_4b:8; /* [31:24] */ + 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_ah_sig_a_1:24, /* [23:0] */ + captured_implicit_sounding:1, /* [24] */ + reserved_6:7; /* [31:25] */ + volatile + uint32_t ht_sig_vht_sig_ah_sig_a_2:24, /* [23:0] */ + reserved_7:8; /* [31:24] */ + volatile uint32_t vht_sig_b:32; /* [31:0] */ + volatile + uint32_t service:16, /* [15:0] */ + reserved_9:16; /* [31:16] */ +}; +struct rx_location_info { + volatile + uint32_t rtt_fac_legacy:14, /* [13:0] */ + rtt_fac_legacy_status:1, /* [14] */ + rtt_fac_vht:14, /* [28:15] */ + rtt_fac_vht_status:1, /* [29] */ + rtt_cfr_status:1, /* [30] */ + rtt_cir_status:1; /* [31] */ + volatile + uint32_t rtt_fac_sifs:10, /* [9:0] */ + rtt_fac_sifs_status:2, /* [11:10] */ + rtt_channel_dump_size:11, /* [22:12] */ + rtt_mac_phy_phase:2, /* [24:23] */ + rtt_hw_ifft_mode:1, /* [25] */ + rtt_btcf_status:1, /* [26] */ + rtt_preamble_type:2, /* [28:27] */ + rtt_pkt_bw:2, /* [30:29] */ + rtt_gi_type:1; /* [31] */ + volatile + uint32_t rtt_mcs_rate:4, /* [3:0] */ + rtt_strongest_chain:2, /* [5:4] */ + rtt_phase_jump:7, /* [12:6] */ + rtt_rx_chain_mask:4, /* [16:13] */ + rtt_tx_data_start_x_phase:1, /* [17] */ + reserved_2:13, /* [30:18] */ + rx_location_info_valid:1; /* [31] */ +}; + +struct rx_pkt_end { + volatile + uint32_t rx_success:1, /* [0] */ + reserved_0a:2, /* [2:1] */ + error_tx_interrupt_rx:1, /* [3] */ + error_ofdm_power_drop:1, /* [4] */ + error_ofdm_restart:1, /* [5] */ + error_cck_power_drop:1, /* [6] */ + error_cck_restart:1, /* [7] */ + reserved_0b:24; /* [31:8] */ + volatile uint32_t phy_timestamp_1_lower_32:32; /* [31:0] */ + volatile uint32_t phy_timestamp_1_upper_32:32; /* [31:0] */ + volatile uint32_t phy_timestamp_2_lower_32:32; /* [31:0] */ + volatile uint32_t phy_timestamp_2_upper_32:32; /* [31:0] */ + struct rx_location_info rx_location_info; +}; + +struct rx_phy_ppdu_end { + volatile + uint32_t reserved_0a:2, /* [1:0] */ + error_radar:1, /* [2] */ + error_rx_abort:1, /* [3] */ + error_rx_nap:1, /* [4] */ + error_ofdm_timing:1, /* [5] */ + error_ofdm_signal_parity:1, /* [6] */ + error_ofdm_rate_illegal:1, /* [7] */ + error_ofdm_length_illegal:1, /* [8] */ + error_ppdu_ofdm_restart:1, /* [9] */ + error_ofdm_service:1, /* [10] */ + error_ppdu_ofdm_power_drop:1, /* [11] */ + error_cck_blocker:1, /* [12] */ + error_cck_timing:1, /* [13] */ + error_cck_header_crc:1, /* [14] */ + error_cck_rate_illegal:1, /* [15] */ + error_cck_length_illegal:1, /* [16] */ + error_ppdu_cck_restart:1, /* [17] */ + error_cck_service:1, /* [18] */ + error_ppdu_cck_power_drop:1, /* [19] */ + error_ht_crc_err:1, /* [20] */ + error_ht_length_illegal:1, /* [21] */ + error_ht_rate_illegal:1, /* [22] */ + error_ht_zlf:1, /* [23] */ + error_false_radar_ext:1, /* [24] */ + error_green_field:1, /* [25] */ + error_spectral_scan:1, /* [26] */ + error_rx_bw_gt_dyn_bw:1, /* [27] */ + error_leg_ht_mismatch:1, /* [28] */ + error_vht_crc_error:1, /* [29] */ + error_vht_siga_unsupported:1, /* [30] */ + error_vht_lsig_len_invalid:1; /* [31] */ + volatile + uint32_t error_vht_ndp_or_zlf:1, /* [0] */ + error_vht_nsym_lt_zero:1, /* [1] */ + error_vht_rx_extra_symbol_mismatch:1, /* [2] */ + error_vht_rx_skip_group_id0:1, /* [3] */ + error_vht_rx_skip_group_id1to62:1, /* [4] */ + error_vht_rx_skip_group_id63:1, /* [5] */ + error_ofdm_ldpc_decoder_disabled:1, /* [6] */ + error_defer_nap:1, /* [7] */ + error_fdomain_timeout:1, /* [8] */ + error_lsig_rel_check:1, /* [9] */ + error_bt_collision:1, /* [10] */ + error_unsupported_mu_feedback:1, /* [11] */ + error_ppdu_tx_interrupt_rx:1, /* [12] */ + error_rx_unsupported_cbf:1, /* [13] */ + reserved_1:18; /* [31:14] */ +}; + +struct rx_timing_offset { + volatile + uint32_t timing_offset:12, /* [11:0] */ + reserved:20; /* [31:12] */ +}; + +struct rx_ppdu_end { + volatile uint32_t evm_p0:32; + volatile uint32_t evm_p1:32; + volatile uint32_t evm_p2:32; + volatile uint32_t evm_p3:32; + volatile uint32_t evm_p4:32; + volatile uint32_t evm_p5:32; + volatile uint32_t evm_p6:32; + volatile uint32_t evm_p7:32; + volatile uint32_t evm_p8:32; + volatile uint32_t evm_p9:32; + volatile uint32_t evm_p10:32; + volatile uint32_t evm_p11:32; + volatile uint32_t evm_p12:32; + volatile uint32_t evm_p13:32; + volatile uint32_t evm_p14:32; + volatile uint32_t evm_p15:32; + volatile uint32_t reserved_16:32; + volatile uint32_t reserved_17:32; + volatile uint32_t wb_timestamp_lower_32:32; + volatile uint32_t wb_timestamp_upper_32:32; + struct rx_pkt_end rx_pkt_end; + struct rx_phy_ppdu_end rx_phy_ppdu_end; + struct rx_timing_offset rx_timing_offset; + volatile + uint32_t rx_antenna:24, /* [23:0] */ + tx_ht_vht_ack:1, /* [24] */ + rx_pkt_end_valid:1, /* [25] */ + rx_phy_ppdu_end_valid:1, /* [26] */ + rx_timing_offset_valid:1, /* [27] */ + bb_captured_channel:1, /* [28] */ + unsupported_mu_nc:1, /* [29] */ + otp_txbf_disable:1, /* [30] */ + reserved_31:1; /* [31] */ + volatile + uint32_t coex_bt_tx_from_start_of_rx:1, /* [0] */ + coex_bt_tx_after_start_of_rx:1, /* [1] */ + coex_wan_tx_from_start_of_rx:1, /* [2] */ + coex_wan_tx_after_start_of_rx:1, /* [3] */ + coex_wlan_tx_from_start_of_rx:1, /* [4] */ + coex_wlan_tx_after_start_of_rx:1, /* [5] */ + mpdu_delimiter_errors_seen:1, /* [6] */ + ftm:1, /* [7] */ + ftm_dialog_token:8, /* [15:8] */ + ftm_follow_up_dialog_token:8, /* [23:16] */ + reserved_32:8; /* [31:24] */ + volatile + uint32_t before_mpdu_cnt_passing_fcs:8, /* [7:0] */ + before_mpdu_cnt_failing_fcs:8, /* [15:8] */ + after_mpdu_cnt_passing_fcs:8, /* [23:16] */ + after_mpdu_cnt_failing_fcs:8; /* [31:24] */ + volatile uint32_t phy_timestamp_tx_lower_32:32; /* [31:0] */ + volatile uint32_t phy_timestamp_tx_upper_32:32; /* [31:0] */ + volatile + uint32_t bb_length:16, /* [15:0] */ + bb_data:1, /* [16] */ + peer_idx_valid:1, /* [17] */ + peer_idx:11, /* [28:18] */ + reserved_26:2, /* [30:29] */ + ppdu_done:1; /* [31] */ +}; +#else +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_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_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 /* defined(HELIUMPLUS) */ + +#endif /*_RX_DESC_H_*/ diff --git a/core/dp/ol/inc/ol_cfg.h b/core/dp/ol/inc/ol_cfg.h new file mode 100644 index 000000000000..4e59ea397d30 --- /dev/null +++ b/core/dp/ol/inc/ol_cfg.h @@ -0,0 +1,543 @@ +/* + * 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_CFG__H_ +#define _OL_CFG__H_ + +#include /* uint32_t */ +#include /* ol_pdev_handle */ +#include /* ieee80211_qosframe_htc_addr4 */ +#include /* LLC_SNAP_HDR_LEN */ +#include "wlan_tgt_def_config.h" + +/** + * @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, +}; + +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; +}; + +/* 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; + struct wlan_ipa_uc_rsc_t ipa_uc_rsc; + bool ip_tcp_udp_checksum_offload; + bool enable_rxthread; + bool ce_classify_enabled; +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + uint32_t tx_flow_stop_queue_th; + uint32_t tx_flow_start_queue_offset; +#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 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, uint8_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); + +/** + * @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 + */ +uint16_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); + +int ol_cfg_is_rx_thread_enabled(ol_pdev_handle pdev); + +/** + * ol_cfg_is_ip_tcp_udp_checksum_offload_enabled() - return + * ip_tcp_udp_checksum_offload is enable/disable + * @pdev : handle to the physical device + * + * Return: 1 - enable, 0 - disable + */ +static inline +int ol_cfg_is_ip_tcp_udp_checksum_offload_enabled(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ip_tcp_udp_checksum_offload; +} + + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +int ol_cfg_get_tx_flow_stop_queue_th(ol_pdev_handle pdev); + +int ol_cfg_get_tx_flow_start_queue_offset(ol_pdev_handle pdev); +#endif + +bool ol_cfg_is_ce_classify_enabled(ol_pdev_handle pdev); + +enum wlan_target_fmt_translation_caps { + wlan_frm_tran_cap_raw = 0x01, + wlan_frm_tran_cap_native_wifi = 0x02, + wlan_frm_tran_cap_8023 = 0x04, +}; + +/** + * @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 uint8_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, uint8_t val); + +/** + * @brief Get packet log config from HTT config + */ +uint8_t ol_cfg_is_packet_log_enabled(ol_pdev_handle pdev); + +#ifdef IPA_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); +#else +static inline unsigned int ol_cfg_ipa_uc_offload_enabled( + ol_pdev_handle pdev) +{ + return 0; +} + +static inline unsigned int ol_cfg_ipa_uc_tx_buf_size( + ol_pdev_handle pdev) +{ + return 0; +} + +static inline unsigned int ol_cfg_ipa_uc_tx_max_buf_cnt( + ol_pdev_handle pdev) +{ + return 0; +} + +static inline unsigned int ol_cfg_ipa_uc_rx_ind_ring_size( + ol_pdev_handle pdev) +{ + return 0; +} + +static inline unsigned int ol_cfg_ipa_uc_tx_partition_base( + ol_pdev_handle pdev) +{ + return 0; +} +#endif /* IPA_OFFLOAD */ +#endif /* _OL_CFG__H_ */ diff --git a/core/dp/ol/inc/ol_ctrl_addba_api.h b/core/dp/ol/inc/ol_ctrl_addba_api.h new file mode 100644 index 000000000000..31854e61086d --- /dev/null +++ b/core/dp/ol/inc/ol_ctrl_addba_api.h @@ -0,0 +1,43 @@ +/* + * 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 _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/core/dp/ol/inc/ol_ctrl_api.h b/core/dp/ol/inc/ol_ctrl_api.h new file mode 100644 index 000000000000..c3e6eb347480 --- /dev/null +++ b/core/dp/ol/inc/ol_ctrl_api.h @@ -0,0 +1,44 @@ +/* + * 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_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/core/dp/ol/inc/ol_defines.h b/core/dp/ol/inc/ol_defines.h new file mode 100644 index 000000000000..8b83adb85f91 --- /dev/null +++ b/core/dp/ol/inc/ol_defines.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/* + * 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, + uint8_t *event_buf, uint32_t len); + +#endif /* _DEV_OL_DEFINES_H */ diff --git a/core/dp/ol/inc/ol_htt_api.h b/core/dp/ol/inc/ol_htt_api.h new file mode 100644 index 000000000000..4e9e58f1a004 --- /dev/null +++ b/core/dp/ol/inc/ol_htt_api.h @@ -0,0 +1,353 @@ +/* + * 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 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 /* cdf_device_t */ +#include /* cdf_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; + +htt_pdev_handle +htt_pdev_alloc(ol_txrx_pdev_handle txrx_pdev, + ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, cdf_device_t osdev); + +/** + * @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 pdev - data SW's physical device handle + * (used as context pointer during HTT -> txrx calls) + * @param desc_pool_size - number of HTT descriptors to (pre)allocate + * @return success -> HTT pdev handle; failure -> NULL + */ +int +htt_attach(struct htt_pdev_t *pdev, 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); + +/** + * enum htt_op_mode - Virtual device operation mode + * + * @htt_op_mode_unknown: Unknown mode + * @htt_op_mode_ap: AP mode + * @htt_op_mode_ibss: IBSS mode + * @htt_op_mode_sta: STA (client) mode + * @htt_op_mode_monitor: Monitor mode + * @htt_op_mode_ocb: 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) + +void htt_pdev_free(htt_pdev_handle pdev); + +/** + * @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, uint8_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, + uint32_t stats_type_upload_mask, + uint32_t stats_type_reset_mask, + uint8_t cfg_stats_type, + uint32_t cfg_val, uint64_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(uint8_t *stats_info_list, + enum htt_dbg_stats_type *type, + enum htt_dbg_stats_status *status, + int *length, uint8_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(uint8_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_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, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + 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, + uint32_t ipa_uc_tx_doorbell_paddr, + 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, bool uc_active, bool 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); +#else +static inline int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) +{ + return 0; +} + +static inline int +htt_ipa_uc_get_resource(htt_pdev_handle pdev, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + uint32_t *rx_proc_done_idx_paddr) +{ + return 0; +} + +static inline int +htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, + uint32_t ipa_uc_tx_doorbell_paddr, + uint32_t ipa_uc_rx_doorbell_paddr) +{ + return 0; +} + +static inline int +htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, bool uc_active, + bool is_tx) +{ + return 0; +} + +static inline int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) +{ + return 0; +} + +static inline int htt_ipa_uc_attach(struct htt_pdev_t *pdev) +{ + return 0; +} + +static inline void htt_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + return; +} +#endif /* IPA_OFFLOAD */ + +#endif /* _OL_HTT_API__H_ */ diff --git a/core/dp/ol/inc/ol_htt_rx_api.h b/core/dp/ol/inc/ol_htt_rx_api.h new file mode 100644 index 000000000000..d94c707da432 --- /dev/null +++ b/core/dp/ol/inc/ol_htt_rx_api.h @@ -0,0 +1,863 @@ +/* + * 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 / * uint16_t, etc. * / */ +#include /* uint16_t, etc. */ +#include /* cdf_nbuf_t */ +#include /* bool */ + +#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 + +/** + * struct ocb_rx_stats_hdr_t - RX stats header + * @version: The version must be 1. + * @length: The length of this structure + * @channel_freq: The center frequency for the packet + * @rssi_cmb: combined RSSI from all chains + * @rssi[4]: rssi for chains 0 through 3 (for 20 MHz bandwidth) + * @tsf32: timestamp in TSF units + * @timestamp_microsec: timestamp in microseconds + * @datarate: MCS index + * @timestamp_submicrosec: submicrosecond portion of the timestamp + * @ext_tid: Extended TID + * @reserved: Ensure the size of the structure is a multiple of 4. + * Must be 0. + * + * 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 { + uint16_t version; + uint16_t length; + uint16_t channel_freq; + int16_t rssi_cmb; + int16_t rssi[4]; + uint32_t tsf32; + uint32_t timestamp_microsec; + uint8_t datarate; + uint8_t timestamp_submicrosec; + uint8_t ext_tid; + uint8_t 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, cdf_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, + cdf_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, cdf_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, + cdf_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, + cdf_nbuf_t rx_ind_msg, + int mpdu_range_num, + enum htt_rx_status *status, int *mpdu_count); + +/** + * @brief Return the RSSI provided in a rx indication message. + * @details + * Return the RSSI from an rx indication message, converted to dBm units. + * + * @param pdev - the HTT instance the rx data was received on + * @param rx_ind_msg - the netbuf containing the rx indication message + * @return RSSI in dBm, or HTT_INVALID_RSSI + */ +int16_t +htt_rx_ind_rssi_dbm(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg); + +int16_t +htt_rx_ind_rssi_dbm_chain(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg, + int8_t chain); + +void +htt_rx_ind_legacy_rate(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg, + uint8_t *legacy_rate, uint8_t *legacy_rate_sel); + + +void +htt_rx_ind_timestamp(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg, + uint32_t *timestamp_microsec, + uint8_t *timestamp_submicrosec); + +uint32_t +htt_rx_ind_tsf32(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg); + +uint8_t +htt_rx_ind_ext_tid(htt_pdev_handle pdev, cdf_nbuf_t rx_ind_msg); + + +/*==================== rx MPDU descriptor access methods ====================*/ + +/** + * @brief Check if the retry bit is set in Rx-descriptor + * @details + * This function returns the retry bit of the 802.11 header for the + * provided rx MPDU descriptor. + * + * @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 boolean -- true if retry is set, false otherwise + */ +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 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 */ + uint32_t pn24; + + /* TKIP or CCMP: 48-bit PN */ + uint64_t pn48; + + /* WAPI: 128-bit PN */ + uint64_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); + +/** + * @brief This function Returns the TID value from the Rx descriptor + * for Low Latency driver + * @details + * 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. + * @pdev: Handle (pointer) to HTT pdev. + * @param mpdu_desc - the abstract descriptor for the MPDU in question + * @return: Actual TID set in the packet header. + */ +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 + */ +uint32_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 bool (*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 bool (*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 bool (*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 bool (*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 + * true - Success + * false - if this is not first msdu + */ +extern bool +(*htt_rx_msdu_desc_key_id)(htt_pdev_handle pdev, + void *mpdu_desc, uint8_t *key_id); + +extern bool +(*htt_rx_msdu_chan_info_present)( + htt_pdev_handle pdev, + void *mpdu_desc); + +extern bool +(*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, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_nbuf_t *tail_msdu); + +extern int +(*htt_rx_frag_pop)(htt_pdev_handle pdev, + cdf_nbuf_t rx_ind_msg, + cdf_nbuf_t *head_msdu, cdf_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, + cdf_nbuf_t offload_deliver_msg, + int *vdev_id, + int *peer_id, + int *tid, + uint8_t *fw_desc, + cdf_nbuf_t *head_buf, cdf_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, cdf_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, cdf_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, cdf_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, cdf_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 + */ +cdf_nbuf_t +htt_rx_restitch_mpdu_from_msdus(htt_pdev_handle pdev, + cdf_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, + cdf_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 + * + */ +uint16_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(cdf_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, + uint32_t *msg_word, + int msdu_iter, + int *vdev_id, + int *peer_id, + int *tid, + uint8_t *fw_desc, + cdf_nbuf_t *head_buf, cdf_nbuf_t *tail_buf); +#endif /* _OL_HTT_RX_API__H_ */ diff --git a/core/dp/ol/inc/ol_htt_tx_api.h b/core/dp/ol/inc/ol_htt_tx_api.h new file mode 100644 index 000000000000..58ebabc47c49 --- /dev/null +++ b/core/dp/ol/inc/ol_htt_tx_api.h @@ -0,0 +1,969 @@ +/* + * 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_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 / * uint16_t, etc. * / */ +#include /* uint16_t, etc. */ +#include /* cdf_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, +}; + +/** + * struct ocb_tx_ctrl_hdr_t - TX control header + * @version: must be 1 + * @length: length of this structure + * @channel_freq: channel on which to transmit the packet + * @valid_pwr: bit 0: if set, tx pwr spec is valid + * @valid_datarate: bit 1: if set, tx MCS mask spec is valid + * @valid_retries: bit 2: if set, tx retries spec is valid + * @valid_chain_mask: bit 3: if set, chain mask is valid + * @valid_expire_tsf: bit 4: if set, tx expire TSF spec is valid + * @valid_tid: bit 5: if set, TID is valid + * @reserved0_15_6: bits 15:6 - unused, set to 0x0 + * @all_flags: union of all the flags + * @expire_tsf_lo: TX expiry time (TSF) LSBs + * @expire_tsf_hi: TX expiry time (TSF) MSBs + * @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. + * @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 + * @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. + * @chain_mask: specify which chains to transmit from + * @ext_tid: Extended Traffic ID (0-15) + * @reserved: Ensure that the size of the structure is a multiple of + * 4. Must be 0. + * + * 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 { + uint16_t version; + uint16_t length; + uint16_t channel_freq; + + union { + struct { + uint16_t + valid_pwr:1, + valid_datarate:1, + valid_retries:1, + valid_chain_mask:1, + valid_expire_tsf:1, + valid_tid:1, + reserved0_15_6:10; + }; + uint16_t all_flags; + }; + + uint32_t expire_tsf_lo; + uint32_t expire_tsf_hi; + int8_t pwr; + uint8_t datarate; + uint8_t retry_limit; + uint8_t chain_mask; + uint8_t ext_tid; + uint8_t 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 { + uint16_t ethertype; +#define HTT_INVALID_PEER_ID 0xffff + uint16_t peer_id; + uint8_t vdev_id; + uint8_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 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. + */ + uint8_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. + */ + uint8_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. + */ + uint8_t frame_subtype; /* enum htt_frm_subtype */ + uint8_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. + uint8_t *dest_addr; + */ + + uint8_t l3_hdr_offset; /* wrt cdf_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. + */ + /* uint8_t l4_hdr_offset; - wrt cdf_nbuf_data(msdu), in bytes */ + } info; + /* the action sub-struct specifies how to process the MSDU */ + struct { + uint8_t use_6mbps; /* mgmt frames: option to force + 6 Mbps rate */ + uint8_t do_encrypt; + uint8_t do_tx_complete; + uint8_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 + */ + cdf_nbuf_tx_cksum_t cksum_offload; + } action; +}; + +static inline void htt_msdu_info_dump(struct htt_msdu_info_t *msdu_info) +{ + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "HTT MSDU info object (%p)\n", msdu_info); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " ethertype: %#x\n", msdu_info->info.ethertype); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " peer_id: %d\n", msdu_info->info.peer_id); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " vdev_id: %d\n", msdu_info->info.vdev_id); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " ext_tid: %d\n", msdu_info->info.ext_tid); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " l2_hdr_type: %d\n", msdu_info->info.l2_hdr_type); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " frame_type: %d\n", msdu_info->info.frame_type); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " frame_subtype: %d\n", msdu_info->info.frame_subtype); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " is_unicast: %u\n", msdu_info->info.is_unicast); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " l3_hdr_offset: %u\n", msdu_info->info.l3_hdr_offset); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " use 6 Mbps: %d\n", msdu_info->action.use_6mbps); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " do_encrypt: %d\n", msdu_info->action.do_encrypt); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " do_tx_complete: %d\n", msdu_info->action.do_tx_complete); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + " is_unicast: %u\n", msdu_info->info.is_unicast); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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 + */ +uint16_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, uint32_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); + +#if defined(HELIUMPLUS_PADDR64) +/* TODO: oka: use kernel-doc format */ +/** + * @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_frag_alloc(htt_pdev_handle pdev, + u_int16_t index, + u_int32_t *frag_paddr_lo); +#endif /* defined(HELIUMPLUS_PADDR64) */ +/** + * @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 + * @param[OUT] frag_paddr_lo - physical address of the fragment descriptor + * (MSDU Link Extension Descriptor) + */ +void htt_tx_pending_discard(htt_pdev_handle pdev); + +/** + * @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 cdf_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, cdf_nbuf_t msdu, uint16_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 + */ +cdf_nbuf_t +htt_tx_send_batch(htt_pdev_handle htt_pdev, + cdf_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, + cdf_nbuf_t msdu, + uint16_t msdu_id, enum htt_pkt_type pkt_type); + +/** + * htt_pkt_dl_len_get() Gets the HTT PKT download length. + * @pdev: pointer to struct htt_pdev_t + * + * Return: size of HTT packet download length. + */ +int +htt_pkt_dl_len_get(struct htt_pdev_t *pdev); + +#define HTT_TX_CLASSIFY_BIT_S 4 /* Used to set + * classify bit in HTT desc.*/ + +/** + * enum htt_ce_tx_pkt_type - enum of packet types to be set in CE + * descriptor + * @tx_pkt_type_raw: Value set for RAW frames + * @tx_pkt_type_native_wifi: Value set for NATIVE WIFI frames + * @tx_pkt_type_eth2: Value set for Ethernet II frames (mostly default) + * @tx_pkt_type_802_3: Value set for 802.3 / original ethernet frames + * @tx_pkt_type_mgmt: Value set for MGMT frames over HTT + * + */ +enum htt_ce_tx_pkt_type { + tx_pkt_type_raw = 0, + tx_pkt_type_native_wifi = 1, + tx_pkt_type_eth2 = 2, + tx_pkt_type_802_3 = 3, + tx_pkt_type_mgmt = 4 +}; + + +extern const uint32_t htt_to_ce_pkt_type[]; + +/** + * 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 + +/** + * htt_tx_desc_init() - Initialize the per packet HTT Tx descriptor + * @pdev: The handle of the physical device sending the + * tx data + * @htt_tx_desc: Abstract handle to the tx descriptor + * @htt_tx_desc_paddr_lo: Physical address of the HTT tx descriptor + * @msdu_id: ID to tag the descriptor with. + * The FW sends this ID back to host as a cookie + * during Tx completion, which the host uses to + * identify the MSDU. + * This ID is an index into the OL Tx desc. array. + * @msdu: The MSDU that is being prepared for transmission + * @msdu_info: Tx MSDU meta-data + * @tso_info: Storage for TSO meta-data + * + * This function initializes the HTT tx descriptor. + * HTT Tx descriptor is a host-f/w interface structure, and meta-data + * accompanying every packet downloaded to f/w via the HTT interface. + */ +static inline +void +htt_tx_desc_init(htt_pdev_handle pdev, + void *htt_tx_desc, + uint32_t htt_tx_desc_paddr_lo, + uint16_t msdu_id, + cdf_nbuf_t msdu, struct htt_msdu_info_t *msdu_info, + struct cdf_tso_info_t *tso_info, + struct ocb_tx_ctrl_hdr_t *tx_ctrl, + uint8_t is_dsrc) +{ + uint8_t pkt_type, pkt_subtype = 0, ce_pkt_type = 0; + uint32_t hw_classify = 0, data_attr = 0; + uint32_t *word0, *word1, local_word3; +#if HTT_PADDR64 + uint32_t *word4; +#else /* ! HTT_PADDR64 */ + uint32_t *word3; +#endif /* HTT_PADDR64 */ + uint32_t local_word0, local_word1; + 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 = (uint32_t *) htt_tx_desc; + word1 = word0 + 1; + /* + * word2 is frag desc pointer + * word3 or 4 is peer_id + */ +#if HTT_PADDR64 + word4 = word0 + 4; /* Dword 3 */ +#else /* ! HTT_PADDR64 */ + word3 = word0 + 3; /* Dword 3 */ +#endif /* HTT_PADDR64 */ + + pkt_type = msdu_info->info.l2_hdr_type; + + if (cdf_likely(pdev->cfg.ce_classify_enabled)) { + if (cdf_likely(pkt_type == htt_pkt_type_eth2 || + pkt_type == htt_pkt_type_ethernet)) + cdf_nbuf_tx_info_get(msdu, pkt_type, pkt_subtype, + hw_classify); + + ce_pkt_type = htt_to_ce_pkt_type[pkt_type]; + if (0xffffffff == ce_pkt_type) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_DEBUG, + "Invalid HTT pkt type %d\n", pkt_type); + return; + } + } + + /* + * HTT Tx Desc is in uncached memory. Used cached writes per word, to + * reduce unnecessary memory access. + */ + + local_word0 = 0; + if (msdu_info) { + HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM); + HTT_TX_DESC_PKT_TYPE_SET(local_word0, pkt_type); + HTT_TX_DESC_PKT_SUBTYPE_SET(local_word0, pkt_subtype); + 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_EXTENSION_SET(local_word0, desc_ext_required); + 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_NO_ENCRYPT_SET(local_word0, + msdu_info->action.do_encrypt ? + 0 : 1); + } + + *word0 = local_word0; + + local_word1 = 0; + +#if defined(FEATURE_TSO) + if (tso_info->is_tso) + HTT_TX_DESC_FRM_LEN_SET(local_word1, tso_info->total_len); + else +#endif + HTT_TX_DESC_FRM_LEN_SET(local_word1, cdf_nbuf_len(msdu)); + + HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id); + *word1 = local_word1; + + /* Initialize peer_id to INVALID_PEER because + 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); +#if HTT_PADDR64 + *word4 = local_word3; +#else /* ! HTT_PADDR64 */ + *word3 = local_word3; +#endif /* HTT_PADDR64 */ + + /* + * 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); + + cdf_nbuf_push_head(msdu, sizeof(local_desc_ext)); + cdf_mem_copy(cdf_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. + */ + cdf_nbuf_set_frag_is_wordstream(msdu, cdf_nbuf_get_num_frags(msdu) - 1, + 0); + + /* store a link to the HTT tx descriptor within the netbuf */ + cdf_nbuf_frag_push_head(msdu, sizeof(struct htt_host_tx_desc_t), + (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 uint32_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. + */ + cdf_nbuf_set_frag_is_wordstream(msdu, 0, 1); + + if (cdf_likely(pdev->cfg.ce_classify_enabled && + (msdu_info->info.l2_hdr_type != htt_pkt_type_mgmt))) { + uint32_t pkt_offset = cdf_nbuf_get_frag_len(msdu, 0); + data_attr = hw_classify << CDF_CE_TX_CLASSIFY_BIT_S; + data_attr |= ce_pkt_type << CDF_CE_TX_PKT_TYPE_BIT_S; + data_attr |= pkt_offset << CDF_CE_TX_PKT_OFFSET_BIT_S; + } + + cdf_nbuf_data_attr_set(msdu, data_attr); +} + +/** + * @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, uint32_t num_frags) +{ + /* + * Set the element after the valid frag elems to 0x0, + * to terminate the list of fragments. + */ +#if defined(HELIUMPLUS_PADDR64) + if (HTT_WIFI_IP(pdev, 2, 0)) { + /** Skip TSO related 4 dwords WIFI2.0*/ + desc = (void *)&(((struct msdu_ext_desc_t *)desc)->frag_ptr0); + /* Frag ptr is 48 bit wide so clear the next dword as well */ + *((uint32_t *)(((char *)desc) + (num_frags << 3))) = 0; + *((uint32_t *) + (((char *)desc) + (num_frags << 3) + sizeof(uint32_t))) = 0; + /* TODO: OKA: remove the magic constants */ + } else { + /* XXXOKA -- Looks like a bug, called with htt_frag_desc */ + *((u_int32_t *) + (((char *) desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0; + } +#else /* ! HELIUMPLUS_PADDR64 */ + *((uint32_t *) + (((char *)desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0; +#endif /* HELIUMPLUS_PADDR64 */ +} + +/* checksum offload flags for hw */ +#define IPV4_CSUM_EN 0x00010000 +#define UDP_IPV4_CSUM_EN 0x00020000 +#define UDP_IPV6_CSUM_EN 0x00040000 +#define TCP_IPV4_CSUM_EN 0x00080000 +#define TCP_IPV6_CSUM_EN 0x00100000 +#define PARTIAL_CSUM_EN 0x00200000 + +/** + * @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, uint32_t frag_phys_addr, uint16_t frag_len) +{ + u_int32_t *word; + +#if defined(HELIUMPLUS_PADDR64) + if (HTT_WIFI_IP(pdev, 2, 0)) { + word = (u_int32_t *)(desc); + /* Initialize top 6 words of TSO flags per packet */ + *word++ = 0; + *word++ = 0; + *word++ = 0; + if (((struct txrx_pdev_cfg_t *)(pdev->ctrl_pdev)) + ->ip_tcp_udp_checksum_offload) + *word |= (IPV4_CSUM_EN | TCP_IPV4_CSUM_EN | + TCP_IPV6_CSUM_EN | UDP_IPV4_CSUM_EN | + UDP_IPV6_CSUM_EN); + else + *word = 0; + word++; + *word++ = 0; + *word++ = 0; + + cdf_assert_always(word == &(((struct msdu_ext_desc_t *) + desc)->frag_ptr0)); + + /* Each fragment consumes 2 DWORDS */ + word += (frag_num << 1); + *word = frag_phys_addr; + + word++; + *word = (frag_len<<16); + + } else { + /* For Helium+, this block cannot exist */ + CDF_ASSERT(0); + } +#else /* !defined(HELIUMPLUS_PADDR64) */ + word = (uint32_t *) (((char *)desc) + HTT_TX_DESC_LEN + frag_num * 8); + *word = frag_phys_addr; + word++; + *word = frag_len; +#endif /* defined(HELIUMPLUS_PADDR64) */ +} + +void htt_tx_desc_frags_table_set(htt_pdev_handle pdev, + void *desc, + uint32_t paddr, + uint32_t frag_desc_paddr_lo, + 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, uint8_t sub_type) +{ + uint32_t *word0; + + word0 = (uint32_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 + */ +cdf_nbuf_t +htt_tx_mgmt_desc_alloc(struct htt_pdev_t *pdev, A_UINT32 *desc_id, + cdf_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, uint16_t peer_id) +{ + uint16_t *peer_id_field_ptr; + + peer_id_field_ptr = (uint16_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, uint16_t chanfreq) +{ + uint16_t *chanfreq_field_ptr; + + /* The reason we dont use CHAN_FREQ_OFFSET_BYTES is because + it uses DWORD as unit */ + /* The reason we dont use the SET macro in htt.h is because + htt_tx_desc is incomplete type */ + chanfreq_field_ptr = (uint16_t *) + (htt_tx_desc + + HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES + + sizeof(A_UINT16)); + + *chanfreq_field_ptr = chanfreq; +} + +#if defined(FEATURE_TSO) +void +htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc, + struct cdf_tso_info_t *tso_info); +#else +#define htt_tx_desc_fill_tso_info(pdev, desc, tso_info) +#endif +#endif /* _OL_HTT_TX_API__H_ */ diff --git a/core/dp/ol/inc/ol_osif_api.h b/core/dp/ol/inc/ol_osif_api.h new file mode 100644 index 000000000000..9344a5fa5fea --- /dev/null +++ b/core/dp/ol/inc/ol_osif_api.h @@ -0,0 +1,42 @@ +/* + * 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_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/core/dp/ol/inc/ol_params.h b/core/dp/ol/inc/ol_params.h new file mode 100644 index 000000000000..89eff22faad1 --- /dev/null +++ b/core/dp/ol/inc/ol_params.h @@ -0,0 +1,103 @@ +/* + * 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_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 +*/ + +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, +}; + +/* +** Enumeration of PDEV Configuration parameter +*/ + +enum ol_hal_param_t { + OL_HAL_CONFIG_DMA_BEACON_RESPONSE_TIME = 0 +}; + +/* +** 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/core/dp/ol/inc/ol_txrx_api.h b/core/dp/ol/inc/ol_txrx_api.h new file mode 100644 index 000000000000..289d49e32341 --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_api.h @@ -0,0 +1,113 @@ +/* + * 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_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/core/dp/ol/inc/ol_txrx_ctrl_api.h b/core/dp/ol/inc/ol_txrx_ctrl_api.h new file mode 100644 index 000000000000..44d5cf100dd7 --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_ctrl_api.h @@ -0,0 +1,1312 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* cdf_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 */ + +#define OL_ATH_TX_DRAIN_WAIT_DELAY 50 + +/* Maximum number of station supported by data path, including BC. */ +#define WLAN_MAX_STA_COUNT (HAL_NUM_STA) + +/* 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) + +/** + * enum wlan_op_mode - Virtual device operation mode + * + * @wlan_op_mode_unknown: Unknown mode + * @wlan_op_mode_ap: AP mode + * @wlan_op_mode_ibss: IBSS mode + * @wlan_op_mode_sta: STA (client) mode + * @wlan_op_mode_monitor: Monitor mode + * @wlan_op_mode_ocb: 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_THERMAL_MITIGATION (1 << 4) + + +/** + * enum netif_action_type - Type of actions on netif queues + * @WLAN_STOP_ALL_NETIF_QUEUE: stop all netif queues + * @WLAN_START_ALL_NETIF_QUEUE: start all netif queues + * @WLAN_WAKE_ALL_NETIF_QUEUE: wake all netif queues + * @WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER: stop all queues and off carrier + * @WLAN_START_ALL_NETIF_QUEUE_N_CARRIER: start all queues and on carrier + * @WLAN_NETIF_TX_DISABLE: disable tx + * @WLAN_NETIF_TX_DISABLE_N_CARRIER: disable tx and off carrier + * @WLAN_NETIF_CARRIER_ON: on carrier + * @WLAN_NETIF_CARRIER_OFF: off carrier + */ +enum netif_action_type { + WLAN_STOP_ALL_NETIF_QUEUE, + WLAN_START_ALL_NETIF_QUEUE, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_NETIF_TX_DISABLE, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_NETIF_CARRIER_ON, + WLAN_NETIF_CARRIER_OFF, + WLAN_NETIF_ACTION_TYPE_MAX, +}; + +/** + * enum netif_reason_type - reason for netif queue action + * @WLAN_CONTROL_PATH: action from control path + * @WLAN_DATA_FLOW_CONTROL: because of flow control + * @WLAN_FW_PAUSE: because of firmware pause + * @WLAN_TX_ABORT: because of tx abort + * @WLAN_VDEV_STOP: because of vdev stop + * @WLAN_PEER_UNAUTHORISED: because of peer is unauthorised + * @WLAN_THERMAL_MITIGATION: because of thermal mitigation + */ +enum netif_reason_type { + WLAN_CONTROL_PATH, + WLAN_DATA_FLOW_CONTROL, + WLAN_FW_PAUSE, + WLAN_TX_ABORT, + WLAN_VDEV_STOP, + WLAN_PEER_UNAUTHORISED, + WLAN_THERMAL_MITIGATION, + WLAN_REASON_TYPE_MAX, +}; + + +/* command options for dumpStats*/ +#define WLAN_HDD_STATS 0 +#define WLAN_TXRX_STATS 1 +#define WLAN_TXRX_HIST_STATS 2 +#define WLAN_TXRX_TSO_STATS 3 +#define WLAN_HDD_NETIF_OPER_HISTORY 4 +#define WLAN_DUMP_TX_FLOW_POOL_INFO 5 +#define WLAN_TXRX_DESC_STATS 6 + +ol_txrx_pdev_handle +ol_txrx_pdev_alloc(ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, cdf_device_t osdev); + +/** + * @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 pdev - txrx_pdev handle + * @return 0 for success or error code + */ +int +ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev); + +/** + * @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, + uint8_t *vdev_mac_addr, + uint8_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, uint8_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. + */ +union ol_txrx_peer_update_param_t { + uint8_t qos_capable; + uint8_t uapsd_mask; + enum ol_sec_type sec_type; +}; + +/** + * @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. + */ +enum ol_txrx_peer_update_select_t { + ol_txrx_peer_update_qos_capable = 1, + ol_txrx_peer_update_uapsdMask, + ol_txrx_peer_update_peer_security, +}; + +/** + * @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, uint8_t *peer_mac, + union ol_txrx_peer_update_param_t *param, + enum 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 ol_txrx_set_wmm_param + * @details + * The struct is used to specify informaiton to update TX WMM scheduler. + */ +struct ol_tx_ac_param_t { + uint32_t aifs; + uint32_t cwmin; + uint32_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 + */ +#define ol_txrx_set_wmm_param(data_pdev, wmm_param) /* no-op */ + +/** + * @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 + */ +#define ol_txrx_peer_tid_unpause(data_peer, tid) /* no-op */ + +/** + * @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 + */ +#define ol_txrx_tx_release(peer, tid_mask, max_frms) /* no-op */ + +/** + * @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(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +void ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, uint32_t reason); +#else +static inline +void ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, uint32_t reason) +{ + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * @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(QCA_LL_LEGACY_TX_FLOW_CONTROL) +void ol_txrx_vdev_flush(ol_txrx_vdev_handle data_vdev); +#else +#define ol_txrx_vdev_flush(data_vdev) /* no-op */ +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * @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(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +void ol_txrx_vdev_unpause(ol_txrx_vdev_handle data_vdev, uint32_t reason); +#else +static inline +void ol_txrx_vdev_unpause(ol_txrx_vdev_handle data_vdev, uint32_t reason) +{ + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * @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. + */ +#define ol_txrx_throttle_pause(data_pdev) /* no-op */ + +/** + * @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. + */ +#define ol_txrx_throttle_unpause(data_pdev) /* no-op */ + +/** + * @brief Suspend all tx data for the specified physical device. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * 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 + */ +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +void ol_txrx_pdev_pause(struct ol_txrx_pdev_t *data_pdev, uint32_t reason); +#else +static inline +void ol_txrx_pdev_pause(struct ol_txrx_pdev_t *data_pdev, uint32_t reason) +{ + return; +} +#endif + +/** + * @brief Resume tx for the specified physical device. + * @details + * This function applies only to HL systems - in LL systems, tx flow control + * is handled entirely within the target FW. + * + * @param data_pdev - the physical device being unpaused + */ +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +void ol_txrx_pdev_unpause(struct ol_txrx_pdev_t *pdev, uint32_t reason); +#else +static inline +void ol_txrx_pdev_unpause(struct ol_txrx_pdev_t *pdev, uint32_t reason) +{ + return; +} +#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 ol_txrx_tx_sync(ol_txrx_pdev_handle data_pdev, uint8_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, cdf_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 + */ +cdf_nbuf_t +ol_tx_non_std(ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, cdf_nbuf_t msdu_list); + +typedef void +(*ol_txrx_mgmt_tx_cb)(void *ctxt, cdf_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, + uint8_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, + cdf_nbuf_t tx_mgmt_frm, + uint8_t type, uint8_t use_6mbps, uint16_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, uint32_t chan_mhz); + +CDF_STATUS ol_txrx_bus_suspend(void); +CDF_STATUS ol_txrx_bus_resume(void); +CDF_STATUS ol_txrx_wait_for_pending_tx(int timeout); + +/** + * @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); + +/** + * @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, uint32_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, uint32_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, uint32_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 successful */ +}; + +/** + * @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 + * + * Return: CDF Status + */ +CDF_STATUS +ol_txrx_peer_state_update(ol_txrx_pdev_handle pdev, uint8_t *peer_addr, + enum ol_txrx_peer_state state); + +void +ol_txrx_peer_keyinstalled_state_update(ol_txrx_peer_handle data_peer, + uint8_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, uint8_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, uint8_t local_peer_id); +#else +#define ol_txrx_peer_find_by_local_id(pdev, local_peer_id) NULL +#endif + +struct ol_txrx_peer_stats_t { + struct { + struct { + uint32_t ucast; + uint32_t mcast; + uint32_t bcast; + } frms; + struct { + uint32_t ucast; + uint32_t mcast; + uint32_t bcast; + } bytes; + } tx; + struct { + struct { + uint32_t ucast; + uint32_t mcast; + uint32_t bcast; + } frms; + struct { + uint32_t ucast; + uint32_t mcast; + uint32_t bcast; + } bytes; + } rx; +}; + +/** + * @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 { + uint8_t is_full_reorder_offload; + /* IPA Micro controller data path offload enable flag */ + uint8_t is_uc_offload_enabled; + /* IPA Micro controller data path offload TX buffer count */ + uint32_t uc_tx_buffer_count; + /* IPA Micro controller data path offload TX buffer size */ + uint32_t uc_tx_buffer_size; + /* IPA Micro controller data path offload RX indication ring count */ + uint32_t uc_rx_indication_ring_count; + /* IPA Micro controller data path offload TX partition base */ + uint32_t uc_tx_partition_base; + /* IP, TCP and UDP checksum offload */ + bool ip_tcp_udp_checksum_offload; + /* Rx processing in thread from TXRX */ + bool enable_rxthread; + /* CE classification enabled through INI */ + bool ce_classify_enabled; +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + /* Threshold to stop queue in percentage */ + uint32_t tx_flow_stop_queue_th; + /* Start queue offset in percentage */ + uint32_t tx_flow_start_queue_offset; +#endif +}; + +/** + * @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(cdf_device_t osdev, + struct txrx_pdev_cfg_param_t cfg_param); + +CDF_STATUS ol_txrx_get_vdevid(struct ol_txrx_peer_t *peer, uint8_t *vdev_id); +void *ol_txrx_get_vdev_by_sta_id(uint8_t sta_id); + + +#define OL_TXRX_INVALID_LOCAL_PEER_ID 0xffff +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID +uint16_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, + uint8_t *peer_addr, + uint8_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, + uint8_t *peer_addr, uint8_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 +uint16_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, uint32_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, + uint16_t *out_packet_count, + uint16_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, + uint32_t *queue_delay_microsec, + uint32_t *tx_delay_microsec, int category); +#else +static inline void +ol_tx_delay(ol_txrx_pdev_handle pdev, + uint32_t *queue_delay_microsec, + uint32_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, uint16_t *bin_values, int category); +#else +static inline void +ol_tx_delay_hist(ol_txrx_pdev_handle pdev, uint16_t *bin_values, int category) +{ + /* no-op version if QCA_COMPUTE_TX_DELAY is not set */ + cdf_assert(bin_values); + cdf_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, bool val); + + +#ifdef IPA_OFFLOAD +/** + * @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 + */ +void +ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + 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 + */ +void +ol_txrx_ipa_uc_set_doorbell_paddr(ol_txrx_pdev_handle pdev, + uint32_t ipa_tx_uc_doorbell_paddr, + uint32_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, bool uc_active, bool 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, uint8_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)(uint8_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 +static inline void +ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + uint32_t *rx_proc_done_idx_paddr) +{ + return; +} + +static inline void +ol_txrx_ipa_uc_set_doorbell_paddr(ol_txrx_pdev_handle pdev, + uint32_t ipa_tx_uc_doorbell_paddr, + uint32_t ipa_rx_uc_doorbell_paddr) +{ + return; +} + +static inline void +ol_txrx_ipa_uc_set_active(ol_txrx_pdev_handle pdev, + bool uc_active, bool is_tx) +{ + return; +} + +static inline void +ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) +{ + return; +} + +static inline void +ol_txrx_ipa_uc_register_op_cb(ol_txrx_pdev_handle pdev, + void (*ipa_uc_op_cb_type)(uint8_t *op_msg, + void *osif_ctxt), + void *osif_dev) +{ + return; +} + +static inline void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev) +{ + return; +} +#endif /* IPA_OFFLOAD */ + +void ol_txrx_display_stats(uint16_t bitmap); +void ol_txrx_clear_stats(uint16_t bitmap); +int ol_txrx_stats(uint8_t vdev_id, char *buffer, unsigned buf_len); + +CDF_STATUS ol_txrx_register_ocb_peer(void *cds_ctx, uint8_t *mac_addr, + uint8_t *peer_id); + +void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t *peer); + +bool ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_peer_t **peer); + +/* TX FLOW Control related functions */ +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +#define TX_FLOW_MGMT_POOL_ID 0xEF + +#ifdef QCA_LL_TX_FLOW_GLOBAL_MGMT_POOL +#define TX_FLOW_MGMT_POOL_SIZE 32 +#else +#define TX_FLOW_MGMT_POOL_SIZE 0 +#endif + +void ol_tx_register_flow_control(struct ol_txrx_pdev_t *pdev); +void ol_tx_deregister_flow_control(struct ol_txrx_pdev_t *pdev); +void ol_tx_dump_flow_pool_info(void); +void ol_tx_clear_flow_pool_stats(void); +void ol_tx_flow_pool_map_handler(uint8_t flow_id, uint8_t flow_type, + uint8_t flow_pool_id, uint16_t flow_pool_size); +void ol_tx_flow_pool_unmap_handler(uint8_t flow_id, uint8_t flow_type, + uint8_t flow_pool_id); +struct ol_tx_flow_pool_t *ol_tx_create_flow_pool(uint8_t flow_pool_id, + uint16_t flow_pool_size); +int ol_tx_delete_flow_pool(struct ol_tx_flow_pool_t *pool); +void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc); +#else + +static inline void ol_tx_register_flow_control(struct ol_txrx_pdev_t *pdev) +{ + return; +} +static inline void ol_tx_deregister_flow_control(struct ol_txrx_pdev_t *pdev) +{ + return; +} +static inline void ol_tx_dump_flow_pool_info(void) +{ + return; +} +static inline void ol_tx_clear_flow_pool_stats(void) +{ + return; +} +static inline void ol_tx_flow_pool_map_handler(uint8_t flow_id, + uint8_t flow_type, uint8_t flow_pool_id, uint16_t flow_pool_size) +{ + return; +} +static inline void ol_tx_flow_pool_unmap_handler(uint8_t flow_id, + uint8_t flow_type, uint8_t flow_pool_id) +{ + return; +} +static inline struct ol_tx_flow_pool_t *ol_tx_create_flow_pool( + uint8_t flow_pool_id, uint16_t flow_pool_size) +{ + return NULL; +} +static inline int ol_tx_delete_flow_pool(struct ol_tx_flow_pool_t *pool) +{ + return 0; +} +static inline void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc) +{ + return; +} +#endif + +#endif /* _OL_TXRX_CTRL_API__H_ */ diff --git a/core/dp/ol/inc/ol_txrx_dbg.h b/core/dp/ol/inc/ol_txrx_dbg.h new file mode 100644 index 000000000000..035010936527 --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_dbg.h @@ -0,0 +1,203 @@ +/* + * 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 ol_txrx_dbg.h + * @brief Functions provided for visibility and debugging. + */ +#ifndef _OL_TXRX_DBG__H_ +#define _OL_TXRX_DBG__H_ + +#include /* A_STATUS, uint64_t */ +#include /* cdf_semaphore_t */ +#include /* htt_dbg_stats_type */ +#include /* ol_txrx_stats */ + +typedef void (*ol_txrx_stats_callback)(void *ctxt, + enum htt_dbg_stats_type type, + uint8_t *buf, int bytes); + +struct ol_txrx_stats_req { + uint32_t stats_type_upload_mask; /* which stats to upload */ + uint32_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 { + uint8_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; + cdf_semaphore_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, + uint8_t cfg_stats_type, uint32_t cfg_val); + +int ol_txrx_fw_stats_get(ol_txrx_vdev_handle vdev, + struct ol_txrx_stats_req *req); + +int ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev, + int max_subfrms_ampdu, int max_subfrms_amsdu); + +enum { + TXRX_DBG_MASK_OBJS = 0x01, + TXRX_DBG_MASK_STATS = 0x02, + TXRX_DBG_MASK_PROT_ANALYZE = 0x04, + TXRX_DBG_MASK_RX_REORDER_TRACE = 0x08, + TXRX_DBG_MASK_RX_PN_TRACE = 0x10 +}; + +/*--- txrx printouts ---*/ + +/* + * Uncomment this to enable txrx printouts with dynamically adjustable + * verbosity. These printouts should not impact performance. + */ +#define TXRX_PRINT_ENABLE 1 +/* uncomment this for verbose txrx printouts (may impact performance) */ +/* #define TXRX_PRINT_VERBOSE_ENABLE 1 */ + +void ol_txrx_print_level_set(unsigned level); + +/*--- txrx object (pdev, vdev, peer) display debug functions ---*/ + +#if TXRX_DEBUG_LEVEL > 5 +void ol_txrx_pdev_display(ol_txrx_pdev_handle pdev, int indent); +void ol_txrx_vdev_display(ol_txrx_vdev_handle vdev, int indent); +void ol_txrx_peer_display(ol_txrx_peer_handle peer, int indent); +#else +#define ol_txrx_pdev_display(pdev, indent) +#define ol_txrx_vdev_display(vdev, indent) +#define ol_txrx_peer_display(peer, indent) +#endif + +/*--- txrx stats display debug functions ---*/ + + +void ol_txrx_stats_display(ol_txrx_pdev_handle pdev); + +void ol_txrx_stats_clear(ol_txrx_pdev_handle pdev); + + +/*--- 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 */ +/* #define ENABLE_TX_QUEUE_LOG 1 */ + +#define ol_tx_queue_log_display(pdev) + +#endif /* ATH_PERF_PWR_OFFLOAD */ +/*----------------------------------------*/ + +#endif /* _OL_TXRX_DBG__H_ */ diff --git a/core/dp/ol/inc/ol_txrx_htt_api.h b/core/dp/ol/inc/ol_txrx_htt_api.h new file mode 100644 index 000000000000..09041cadf3ce --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_htt_api.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. + */ + +/** + * @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 /* cdf_nbuf_t */ + +#include /* ol_txrx_pdev_handle */ + +static inline uint16_t *ol_tx_msdu_id_storage(cdf_nbuf_t msdu) +{ + cdf_assert(cdf_nbuf_headroom(msdu) >= (sizeof(uint16_t) * 2 - 1)); + return (uint16_t *) (((cdf_size_t) (cdf_nbuf_head(msdu) + 1)) & ~0x1); +} + +/** + * @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, cdf_nbuf_t msdu, uint16_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, cdf_nbuf_t msdu, uint16_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, + cdf_nbuf_t msdu, uint16_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 - host could not deliver the tx frame to target */ + htt_tx_status_download_fail = HTT_HOST_ONLY_STATUS_CODE_START, +}; + +/** + * @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); + +/** + * @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, uint16_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, + cdf_nbuf_t rx_ind_msg, + uint16_t peer_id, uint8_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, + cdf_nbuf_t rx_frag_ind_msg, + uint16_t peer_id, uint8_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, + cdf_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, + uint16_t peer_id, + uint8_t vdev_id, uint8_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, uint16_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, uint16_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, + uint16_t peer_id, + enum htt_sec_type sec_type, + int is_unicast, uint32_t *michael_key, uint32_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, + uint16_t peer_id, + uint8_t tid, + uint8_t win_sz, uint16_t start_seq_num, uint8_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, uint16_t peer_id, uint8_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, + uint16_t peer_id, + uint8_t tid, + uint16_t seq_num_start, + uint16_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, + uint16_t peer_id, + uint8_t tid, + int seq_num_start, + int seq_num_end, uint8_t pn_ie_cnt, uint8_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, + uint64_t cookie, uint8_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 + */ +uint8_t +ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_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 + */ +uint8_t +ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_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, + cdf_nbuf_t rx_ind_msg, + uint16_t peer_id, + uint8_t tid, uint8_t is_offload); + +#endif /* _OL_TXRX_HTT_API__H_ */ diff --git a/core/dp/ol/inc/ol_txrx_osif_api.h b/core/dp/ol/inc/ol_txrx_osif_api.h new file mode 100644 index 000000000000..69b6dcf6d1c5 --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_osif_api.h @@ -0,0 +1,283 @@ +/* + * Copyright (c) 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. + */ + +/** + * @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 /* cdf_nbuf_t */ + +#include /* ol_osif_vdev_handle */ +#include /* ol_txrx_pdev_handle, etc. */ +#include +#include "cds_sched.h" + +/** + * struct ol_rx_cached_buf - rx cached buffer + * @list: linked list + * @buf: skb buffer + */ +struct ol_rx_cached_buf { + struct list_head list; + cdf_nbuf_t buf; +}; + +/** + * @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, cdf_nbuf_t msdus); + +/** + * @typedef ol_txrx_tx_fp + * @brief top-level transmit function + */ +typedef cdf_nbuf_t (*ol_txrx_tx_fp)(ol_txrx_vdev_handle data_vdev, + cdf_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 cdf_nbuf_t (*ol_txrx_tx_non_std_fp)(ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, + cdf_nbuf_t msdu_list); + +struct txrx_rx_metainfo; + +/** + * @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 tx_resume - tx os q should be resumed or not + */ +typedef void (*ol_txrx_tx_flow_control_fp)(void *osif_dev, + bool tx_resume); + +/** + * struct ol_txrx_desc_type - txrx descriptor type + * @sta_id: sta id + * @is_qos_enabled: is station qos enabled + * @is_wapi_supported: is station wapi supported + */ +struct ol_txrx_desc_type { + uint8_t sta_id; + uint8_t is_qos_enabled; + uint8_t is_wapi_supported; +}; + + +typedef CDF_STATUS (*ol_rx_callback_fp)(void *p_cds_gctx, + cdf_nbuf_t pDataBuff, + uint8_t ucSTAId); + +typedef void (*ol_tx_pause_callback_fp)(uint8_t vdev_id, + enum netif_action_type action, + enum netif_reason_type reason); + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +CDF_STATUS ol_txrx_register_pause_cb(ol_tx_pause_callback_fp pause_cb); +#else +static inline +CDF_STATUS ol_txrx_register_pause_cb(ol_tx_pause_callback_fp pause_cb) +{ + return CDF_STATUS_SUCCESS; + +} +#endif + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + +int ol_txrx_register_tx_flow_control (uint8_t vdev_id, + ol_txrx_tx_flow_control_fp flowControl, + void *osif_fc_ctx); + +int ol_txrx_deregister_tx_flow_control_cb(uint8_t vdev_id); + +void ol_txrx_flow_control_cb(ol_txrx_vdev_handle vdev, + bool tx_resume); +bool +ol_txrx_get_tx_resource(uint8_t sta_id, + unsigned int low_watermark, + unsigned int high_watermark_offset); + +int +ol_txrx_ll_set_tx_pause_q_depth(uint8_t vdev_id, int pause_q_depth); +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * @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 + */ +cdf_nbuf_t ol_txrx_osif_tso_segment(ol_txrx_vdev_handle txrx_vdev, + int max_seg_payload_bytes, + cdf_nbuf_t jumbo_tcp_frame); + +cdf_nbuf_t ol_tx_send_data_frame(uint8_t sta_id, cdf_nbuf_t skb, + uint8_t proto_type); + +#ifdef IPA_OFFLOAD +cdf_nbuf_t ol_tx_send_ipa_data_frame(void *vdev, + cdf_nbuf_t skb); +#endif + +CDF_STATUS ol_txrx_register_peer(ol_rx_callback_fp rxcb, + struct ol_txrx_desc_type *sta_desc); + +CDF_STATUS ol_txrx_clear_peer(uint8_t sta_id); + +CDF_STATUS ol_txrx_change_peer_state(uint8_t sta_id, + enum ol_txrx_peer_state sta_state, + bool roam_synch_in_progress); + +void ol_rx_data_process(struct ol_txrx_peer_t *peer, + cdf_nbuf_t rx_buf_list); + +void ol_txrx_flush_rx_frames(struct ol_txrx_peer_t *peer, + bool drop); + +#if defined(FEATURE_LRO) +void ol_register_lro_flush_cb(void (handler)(void *), void *data); +#endif +#endif /* _OL_TXRX_OSIF_API__H_ */ diff --git a/core/dp/ol/inc/ol_txrx_stats.h b/core/dp/ol/inc/ol_txrx_stats.h new file mode 100644 index 000000000000..44b384d5b245 --- /dev/null +++ b/core/dp/ol/inc/ol_txrx_stats.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 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. + */ + +/** + * @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 /* uint64_t */ + + + +struct ol_txrx_stats_elem { + uint64_t pkts; + uint64_t bytes; +}; + +#define NUM_MAX_TSO_SEGS 8 +#define NUM_MAX_TSO_SEGS_MASK (NUM_MAX_TSO_SEGS - 1) + +#define NUM_MAX_TSO_MSDUS 128 +#define NUM_MAX_TSO_MSDUS_MASK (NUM_MAX_TSO_MSDUS - 1) + +struct ol_txrx_stats_tso_msdu { + struct cdf_tso_seg_t tso_segs[NUM_MAX_TSO_SEGS]; + uint32_t num_seg; + uint32_t tso_seg_idx; +}; + +struct ol_txrx_stats_tso_info { + struct ol_txrx_stats_tso_msdu tso_msdu_info[NUM_MAX_TSO_MSDUS]; + uint32_t tso_msdu_idx; +}; + +/** + * @brief data stats published by the host txrx layer + */ +struct ol_txrx_stats { + struct { + /* MSDUs given to the txrx layer by the management stack */ + struct ol_txrx_stats_elem mgmt; + /* MSDUs successfully sent across the WLAN */ + struct ol_txrx_stats_elem delivered; + struct { + /* MSDUs that the host did not accept */ + struct ol_txrx_stats_elem host_reject; + /* MSDUs which could not be downloaded to the target */ + struct ol_txrx_stats_elem download_fail; + /* MSDUs which the target discarded + (lack of memory or old age) */ + struct ol_txrx_stats_elem target_discard; + /* MSDUs which the target sent but + couldn't get an ack for */ + struct ol_txrx_stats_elem no_ack; + } dropped; + /* contains information of packets recevied per tx completion*/ + struct { + uint32_t pkts_1; + uint32_t pkts_2_10; + uint32_t pkts_11_20; + uint32_t pkts_21_30; + uint32_t pkts_31_40; + uint32_t pkts_41_50; + uint32_t pkts_51_60; + uint32_t pkts_61_plus; + } comp_histogram; + /* TSO (TCP segmentation offload) information */ + struct { + struct ol_txrx_stats_elem tso_pkts; +#if defined(FEATURE_TSO) + struct ol_txrx_stats_tso_info tso_info; +#endif + } tso; + } tx; + struct { + /* MSDUs given to the OS shim */ + struct 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/core/dp/ol/inc/ol_vowext_dbg_defs.h b/core/dp/ol/inc/ol_vowext_dbg_defs.h new file mode 100644 index 000000000000..3be07aca6368 --- /dev/null +++ b/core/dp/ol/inc/ol_vowext_dbg_defs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 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. + */ + +#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 V2 + 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 { + uint8_t rx_rssi_ctl0; /* control channel chain0 rssi */ + uint8_t rx_rssi_ctl1; /* control channel chain1 rssi */ + uint8_t rx_rssi_ctl2; /* control channel chain2 rssi */ + uint8_t rx_rssi_ext0; /* extention channel chain0 rssi */ + uint8_t rx_rssi_ext1; /* extention channel chain1 rssi */ + uint8_t rx_rssi_ext2; /* extention channel chain2 rssi */ + uint8_t rx_rssi_comb; /* combined RSSI value */ + uint8_t rx_bw; /* Band width 0-20, 1-40, 2-80 */ + uint8_t rx_sgi; /* Guard interval, 0-Long GI, 1-Short GI */ + uint8_t rx_nss; /* Number of spatial streams */ + uint8_t rx_mcs; /* Rate MCS value */ + uint8_t rx_ratecode; /* Hardware rate code */ + uint8_t rx_rs_flags; /* Recieve misc flags */ + uint8_t rx_moreaggr; /* 0 - non aggr frame */ + uint32_t rx_macTs; /* Time stamp */ + uint16_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, cdf_nbuf_t msdu); + +#endif /* _VOW_DEFINES__H_ */ diff --git a/core/dp/txrx/ipv6_defs.h b/core/dp/txrx/ipv6_defs.h new file mode 100644 index 000000000000..c1c52babe485 --- /dev/null +++ b/core/dp/txrx/ipv6_defs.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 _IPV6__H_ +#define _IPV6__H_ + +#if defined(ATH_TARGET) +#include /* A_UINT8 */ +#else +#include /* A_UINT8 */ +#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/core/dp/txrx/ol_cfg.c b/core/dp/txrx/ol_cfg.c new file mode 100644 index 000000000000..2e6a8e767fc6 --- /dev/null +++ b/core/dp/txrx/ol_cfg.c @@ -0,0 +1,323 @@ +/* + * 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 +#include + +unsigned int vow_config = 0; + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_tx_set_flow_control_parameters() - set flow control parameters + * @cfg_ctx: cfg context + * @cfg_param: cfg parameters + * + * Return: none + */ +static +void ol_tx_set_flow_control_parameters(struct txrx_pdev_cfg_t *cfg_ctx, + struct txrx_pdev_cfg_param_t cfg_param) +{ + cfg_ctx->tx_flow_start_queue_offset = + cfg_param.tx_flow_start_queue_offset; + cfg_ctx->tx_flow_stop_queue_th = + cfg_param.tx_flow_stop_queue_th; +} +#else +static +void ol_tx_set_flow_control_parameters(struct txrx_pdev_cfg_t *cfg_ctx, + struct txrx_pdev_cfg_param_t cfg_param) +{ + return; +} +#endif + +/* 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(cdf_device_t osdev, + struct txrx_pdev_cfg_param_t cfg_param) +{ + struct txrx_pdev_cfg_t *cfg_ctx; + + cfg_ctx = cdf_mem_malloc(sizeof(*cfg_ctx)); + if (!cfg_ctx) { + printk(KERN_ERR "cfg ctx allocation failed\n"); + return NULL; + } + + /* + * 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; + /* 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; +#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; + 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; + cfg_ctx->enable_rxthread = cfg_param.enable_rxthread; + cfg_ctx->ip_tcp_udp_checksum_offload = + cfg_param.ip_tcp_udp_checksum_offload; + cfg_ctx->ce_classify_enabled = cfg_param.ce_classify_enabled; + + ol_tx_set_flow_control_parameters(cfg_ctx, cfg_param); + 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, uint8_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, uint8_t val) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + cfg->is_packet_log_enabled = val; +} + +uint8_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; +} + +uint16_t ol_cfg_target_tx_credit(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + uint16_t rc; + uint16_t vow_max_sta = (cfg->vow_config & 0xffff0000) >> 16; + uint16_t vow_max_desc_persta = cfg->vow_config & 0x0000ffff; + + rc = (cfg->target_tx_credit + (vow_max_sta * vow_max_desc_persta)); + + return rc; +} + +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; +} + +/** + * ol_cfg_is_rx_thread_enabled() - return rx_thread is enable/disable + * @pdev : handle to the physical device + * + * Return: 1 - enable, 0 - disable + */ +int ol_cfg_is_rx_thread_enabled(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->enable_rxthread; +} + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_cfg_get_tx_flow_stop_queue_th() - return stop queue threshold + * @pdev : handle to the physical device + * + * Return: stop queue threshold + */ +int ol_cfg_get_tx_flow_stop_queue_th(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->tx_flow_stop_queue_th; +} + +/** + * ol_cfg_get_tx_flow_start_queue_offset() - return start queue offset + * @pdev : handle to the physical device + * + * Return: start queue offset + */ +int ol_cfg_get_tx_flow_start_queue_offset(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->tx_flow_start_queue_offset; +} +#endif + +#ifdef IPA_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_OFFLOAD */ + +/** + * ol_cfg_is_ce_classify_enabled() - Return if CE classification is enabled + * or disabled + * @pdev : handle to the physical device + * + * Return: 1 - enabled, 0 - disabled + */ +bool ol_cfg_is_ce_classify_enabled(ol_pdev_handle pdev) +{ + struct txrx_pdev_cfg_t *cfg = (struct txrx_pdev_cfg_t *)pdev; + return cfg->ce_classify_enabled; +} diff --git a/core/dp/txrx/ol_ctrl_txrx_api.h b/core/dp/txrx/ol_ctrl_txrx_api.h new file mode 100644 index 000000000000..49a952e2733f --- /dev/null +++ b/core/dp/txrx/ol_ctrl_txrx_api.h @@ -0,0 +1,190 @@ +/* + * 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_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 / * uint8_t * / */ +#include /* uint8_t */ +#include /* cdf_nbuf_t */ + +#include /* ol_vdev_handle */ +#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, uint16_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, + uint8_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, + uint8_t vdev_id, + uint8_t *peer_mac_addr, + int tid, + uint32_t tsf32, + enum ol_rx_err_type err_type, + cdf_nbuf_t rx_frame, uint64_t *pn, uint8_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 +ol_rx_notify(ol_pdev_handle pdev, + uint8_t vdev_id, + uint8_t *peer_mac_addr, + int tid, + uint32_t tsf32, + enum ol_rx_notify_type notify_type, cdf_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 */ + +void ol_txrx_set_peer_authorized_event(struct ol_txrx_vdev_t *vdev); + + +#endif /* _OL_CTRL_TXRX_API__H_ */ diff --git a/core/dp/txrx/ol_osif_txrx_api.h b/core/dp/txrx/ol_osif_txrx_api.h new file mode 100644 index 000000000000..b47a0b6cdbbf --- /dev/null +++ b/core/dp/txrx/ol_osif_txrx_api.h @@ -0,0 +1,51 @@ +/* + * 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 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 /* cdf_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(cdf_device_t osdev); + +#endif /* _OL_OSIF_TXRX_API_H_ */ diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c new file mode 100644 index 000000000000..7d007aaab897 --- /dev/null +++ b/core/dp/txrx/ol_rx.c @@ -0,0 +1,1493 @@ +/* + * 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 /* cdf_nbuf_t, etc. */ +#include /* cdf_os_cpu_to_le64 */ +#include /* bool */ +#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 +#include + +#ifdef HTT_RX_RESTORE +#if defined(CONFIG_CNSS) +#include +#endif +#endif + +void ol_rx_data_process(struct ol_txrx_peer_t *peer, + cdf_nbuf_t rx_buf_list); + + +#ifdef HTT_RX_RESTORE + +static void ol_rx_restore_handler(struct work_struct *htt_rx) +{ + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + "Enter: %s", __func__); + cnss_device_self_recovery(); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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, cdf_nbuf_t head_msdu, + cdf_nbuf_t tail_msdu) +{ + cdf_nbuf_t next; + + while (head_msdu) { + next = cdf_nbuf_next(head_msdu); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + "freeing %p\n", head_msdu); + cdf_nbuf_free(head_msdu); + head_msdu = next; + } + + if (!htt_pdev->rx_ring.htt_rx_restore) { + cds_set_logp_in_progress(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, cdf_nbuf_t msdu) +{ + 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 */ + cdf_mem_copy(a1, wh->i_addr1, IEEE80211_ADDR_LEN); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (cdf_mem_compare(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, cdf_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 discard_msdus(htt_pdev_handle htt_pdev, + cdf_nbuf_t head_msdu, + cdf_nbuf_t tail_msdu) +{ + while (1) { + cdf_nbuf_t next; + next = cdf_nbuf_next( + head_msdu); + htt_rx_desc_frame_free + (htt_pdev, + head_msdu); + if (head_msdu == + tail_msdu) { + break; + } + head_msdu = next; + } + return; +} + +void chain_msdus(htt_pdev_handle htt_pdev, + cdf_nbuf_t head_msdu, + cdf_nbuf_t tail_msdu) +{ + while (1) { + cdf_nbuf_t next; + next = cdf_nbuf_next(head_msdu); + htt_rx_desc_frame_free( + htt_pdev, + head_msdu); + if (head_msdu == tail_msdu) + break; + head_msdu = next; + } + return; +} + +void process_reorder(ol_txrx_pdev_handle pdev, + void *rx_mpdu_desc, + uint8_t tid, + struct ol_txrx_peer_t *peer, + cdf_nbuf_t head_msdu, + cdf_nbuf_t tail_msdu, + int num_mpdu_ranges, + int num_pdus, + bool rx_ind_release + ) +{ + htt_pdev_handle htt_pdev = pdev->htt_pdev; + 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. + */ + discard_msdus(htt_pdev, head_msdu, tail_msdu); + /* + * 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 = 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); + } + } + return; +} /* process_reorder */ + +void +ol_rx_indication_handler(ol_txrx_pdev_handle pdev, + cdf_nbuf_t rx_ind_msg, + uint16_t peer_id, uint8_t tid, int num_mpdu_ranges) +{ + int mpdu_range, i; + unsigned seq_num_start = 0, seq_num_end = 0; + bool rx_ind_release = 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; + bool 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 cdf_nbuf_t + * for msg and payload are the same buf. And the buf will be + * changed during processing */ + rx_ind_release = 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; + cdf_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 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 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 == 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. + */ + chain_msdus(htt_pdev, + head_msdu, + tail_msdu); + } else { + process_reorder(pdev, rx_mpdu_desc, + tid, peer, + head_msdu, tail_msdu, + num_mpdu_ranges, + num_mpdus, + rx_ind_release); + } + + } + } 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; + uint8_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) == 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 */ + cdf_nbuf_t next; + next = cdf_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 ((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, + uint16_t peer_id, + enum htt_sec_type sec_type, + int is_unicast, uint32_t *michael_key, uint32_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 */ + cdf_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) { + cdf_mem_set(peer->tids_last_pn_valid, + OL_TXRX_NUM_EXT_TIDS, 0x00); + } 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; + cdf_mem_copy((uint8_t *) &peer->tids_last_pn[i], + (uint8_t *) rx_pn, + sizeof(union htt_rx_pn_t)); + peer->tids_last_pn[i].pn128[1] = + cdf_os_cpu_to_le64( + peer->tids_last_pn[i].pn128[1]); + peer->tids_last_pn[i].pn128[0] = + cdf_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(cdf_nbuf_t msdu) +{ + struct ieee80211_frame *wh; + uint32_t hdrsize; + struct llc *llchdr; + struct ether_header *eth_hdr; + uint16_t ether_type = 0; + uint8_t a1[IEEE80211_ADDR_LEN]; + uint8_t a2[IEEE80211_ADDR_LEN]; + uint8_t a3[IEEE80211_ADDR_LEN]; + uint8_t fc1; + + wh = (struct ieee80211_frame *)cdf_nbuf_data(msdu); + cdf_mem_copy(a1, wh->i_addr1, IEEE80211_ADDR_LEN); + cdf_mem_copy(a2, wh->i_addr2, IEEE80211_ADDR_LEN); + cdf_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 *)(((uint8_t *) cdf_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) + */ + cdf_nbuf_pull_head(msdu, + (hdrsize + sizeof(struct llc) - + sizeof(struct ether_header))); + eth_hdr = (struct ether_header *)(cdf_nbuf_data(msdu)); + switch (fc1) { + case IEEE80211_FC1_DIR_NODS: + cdf_mem_copy(eth_hdr->ether_dhost, a1, IEEE80211_ADDR_LEN); + cdf_mem_copy(eth_hdr->ether_shost, a2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + cdf_mem_copy(eth_hdr->ether_dhost, a3, IEEE80211_ADDR_LEN); + cdf_mem_copy(eth_hdr->ether_shost, a2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + cdf_mem_copy(eth_hdr->ether_dhost, a1, IEEE80211_ADDR_LEN); + cdf_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, + uint8_t vdev_id, + uint8_t *peer_mac_addr, + int tid, + uint32_t tsf32, + enum ol_rx_notify_type notify_type, cdf_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, cdf_nbuf_t msdu, void *rx_desc) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + uint8_t *data, *l3_hdr; + uint16_t ethertype; + int offset; + + data = cdf_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, + cdf_nbuf_t msg, int msdu_cnt) +{ + int vdev_id, peer_id, tid; + cdf_nbuf_t head_buf, tail_buf, buf; + struct ol_txrx_peer_t *peer; + uint8_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) { + ol_rx_data_process(peer, head_buf); + } else { + buf = head_buf; + while (1) { + cdf_nbuf_t next; + next = cdf_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); +} + +void +ol_rx_mic_error_handler( + ol_txrx_pdev_handle pdev, + u_int8_t tid, + u_int16_t peer_id, + void *msdu_desc, + cdf_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) == 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); + } + } + } + } +} + +/** + * @brief Check the first msdu to decide whether the a-msdu should be accepted. + */ +bool +ol_rx_filter(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, cdf_nbuf_t msdu, void *rx_desc) +{ +#define FILTER_STATUS_REJECT 1 +#define FILTER_STATUS_ACCEPT 0 + uint8_t *wh; + uint32_t offset = 0; + uint16_t ether_type = 0; + bool is_encrypted = false, is_mcast = false; + uint8_t i; + enum 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 = cdf_nbuf_data(msdu); + + /* get ether type */ + ether_type = (wh[offset] << 8) | wh[offset + 1]; + /* get packet type */ + if (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 ((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++) { + enum privacy_filter filter_type; + enum 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 (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 || (true == is_encrypted)) + return FILTER_STATUS_ACCEPT; + + /* + * If this is a open connection, it will be accepted. + */ + sec_idx = (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 ((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, cdf_nbuf_t msdu_list) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + cdf_nbuf_t deliver_list_head = NULL; + cdf_nbuf_t deliver_list_tail = NULL; + cdf_nbuf_t msdu; + bool filter = false; +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + struct ol_rx_decap_info_t info; + cdf_mem_set(&info, sizeof(info), 0); +#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; + cdf_nbuf_t next = cdf_nbuf_next(msdu); + + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); + +#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], + cdf_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 || (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 */); + cdf_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) { + /* add NULL terminator */ + cdf_nbuf_set_next(deliver_list_tail, NULL); + } + } 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 frontof 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; + cdf_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; + + cdf_nbuf_push_head(msdu, + sizeof(rx_header)); + cdf_mem_copy(cdf_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 = CDF_SWAP_U16( + ETHERTYPE_OCB_RX); + cdf_nbuf_push_head(msdu, + sizeof(eth_header)); + cdf_mem_copy(cdf_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 = cdf_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_data_process(peer, deliver_list_head); +} + +void +ol_rx_discard(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, unsigned tid, cdf_nbuf_t msdu_list) +{ + ol_txrx_pdev_handle pdev = vdev->pdev; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + while (msdu_list) { + cdf_nbuf_t msdu = msdu_list; + + msdu_list = cdf_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) +{ + uint8_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; + cdf_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, cdf_nbuf_t frames) +{ + cdf_nbuf_t next, frag = frames; + + while (frag) { + next = cdf_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, + cdf_nbuf_t rx_ind_msg, + uint16_t peer_id, + uint8_t tid, uint8_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; + cdf_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", __func__); + cdf_assert_always(pdev); + return; + } + +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s %d: rx_ind_msg 0x%p peer_id %d tid %d is_offload %d\n", + __func__, __LINE__, rx_ind_msg, peer_id, tid, is_offload); +#endif + + /* + * 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 (cdf_unlikely(0 == status)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: Pop status is 0, returning here\n", __func__); + 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 */ + cdf_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", + __func__, peer_id); + while (head_msdu) { + cdf_nbuf_t msdu = head_msdu; + head_msdu = cdf_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, cdf_nbuf_t msdu_list) +{ + cdf_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) { + cdf_nbuf_t next = cdf_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_data_process(peer, msdu_list); +} + +void +ol_rx_offload_paddr_deliver_ind_handler(htt_pdev_handle htt_pdev, + uint32_t msdu_count, + uint32_t *msg_word) +{ + int vdev_id, peer_id, tid; + cdf_nbuf_t head_buf, tail_buf, buf; + struct ol_txrx_peer_t *peer; + uint8_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) { + ol_rx_data_process(peer, head_buf); + } else { + buf = head_buf; + while (1) { + cdf_nbuf_t next; + next = cdf_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); +} + + +#ifdef NEVERDEFINED +/** + * @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, cdf_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 { + uint8_t *data, *l3_hdr, *bp; + uint16_t ethertype; + int offset; + struct vow_extstats vowstats; + + data = cdf_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; + /* rsflags */ + *bp++ = vowstats.rx_rs_flags; + + /* Time stamp Lo */ + *bp++ = (uint8_t) + ((vowstats. + rx_macTs & 0x0000ff00) >> 8); + *bp++ = (uint8_t) + (vowstats.rx_macTs & 0x0000ff); + /* rx phy errors */ + *bp++ = (uint8_t) + ((scn->chan_stats. + phy_err_cnt >> 8) & 0xff); + *bp++ = + (uint8_t) (scn->chan_stats. + phy_err_cnt & 0xff); + /* rx clear count */ + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + rx_clear_count >> 24) & 0xff); + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + rx_clear_count >> 16) & 0xff); + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + rx_clear_count >> 8) & 0xff); + *bp++ = (uint8_t) + (scn->mib_cycle_cnts. + rx_clear_count & 0xff); + /* rx cycle count */ + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + cycle_count >> 24) & 0xff); + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + cycle_count >> 16) & 0xff); + *bp++ = (uint8_t) + ((scn->mib_cycle_cnts. + cycle_count >> 8) & 0xff); + *bp++ = (uint8_t) + (scn->mib_cycle_cnts. + cycle_count & 0xff); + + *bp++ = vowstats.rx_ratecode; + *bp++ = vowstats.rx_moreaggr; + + /* sequence number */ + *bp++ = (uint8_t) + ((vowstats.rx_seqno >> 8) & + 0xff); + *bp++ = (uint8_t) + (vowstats.rx_seqno & 0xff); + } + } + } + } +} + +#endif diff --git a/core/dp/txrx/ol_rx.h b/core/dp/txrx/ol_rx.h new file mode 100644 index 000000000000..33d749fccf00 --- /dev/null +++ b/core/dp/txrx/ol_rx.h @@ -0,0 +1,67 @@ +/* + * 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 _OL_RX__H_ +#define _OL_RX__H_ + +#include /* cdf_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, cdf_nbuf_t head_msdu); + +void +ol_rx_discard(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, unsigned tid, cdf_nbuf_t head_msdu); + +void ol_rx_frames_free(htt_pdev_handle htt_pdev, cdf_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, cdf_nbuf_t head_msdu); + +void +ol_rx_offload_paddr_deliver_ind_handler(htt_pdev_handle htt_pdev, + uint32_t msdu_count, + uint32_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, + cdf_nbuf_t msdu); + +#endif /* _OL_RX__H_ */ diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c new file mode 100644 index 000000000000..4fb2cbc2e48e --- /dev/null +++ b/core/dp/txrx/ol_rx_defrag.c @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*- + * 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 /* cdf_system_time */ + +#define DEFRAG_IEEE80211_ADDR_EQ(a1, a2) \ + (cdf_mem_compare(a1, a2, IEEE80211_ADDR_LEN) == 0) + +#define DEFRAG_IEEE80211_ADDR_COPY(dst, src) \ + cdf_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, +}; + +inline struct ieee80211_frame *ol_rx_frag_get_mac_hdr( + htt_pdev_handle htt_pdev, + cdf_nbuf_t frag) +{ + return + (struct ieee80211_frame *) cdf_nbuf_data(frag); +} +#define ol_rx_frag_pull_hdr(pdev, frag, hdrsize) \ + cdf_nbuf_pull_head(frag, hdrsize); +#define OL_RX_FRAG_CLONE(frag) NULL /* no-op */ + +static inline void +ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev, + cdf_nbuf_t msdu, + void **rx_desc_old_position, + void **ind_old_position, int *rx_desc_len) +{ + *rx_desc_old_position = NULL; + *ind_old_position = NULL; + *rx_desc_len = 0; +} + +/* + * Process incoming fragments + */ +void +ol_rx_frag_indication_handler(ol_txrx_pdev_handle pdev, + cdf_nbuf_t rx_frag_ind_msg, + uint16_t peer_id, uint8_t tid) +{ + uint16_t seq_num; + int seq_num_start, seq_num_end; + struct ol_txrx_peer_t *peer; + htt_pdev_handle htt_pdev; + cdf_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); + + 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 + * separate 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); + cdf_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, uint16_t seq_num, cdf_nbuf_t frag) +{ + struct ieee80211_frame *fmac_hdr, *mac_hdr; + uint8_t fragno, more_frag, all_frag_present = 0; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + uint16_t frxseq, rxseq, seq; + htt_pdev_handle htt_pdev = pdev->htt_pdev; + + seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask; + cdf_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 = cdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) >> + IEEE80211_SEQ_SEQ_SHIFT; + fragno = cdf_le16_to_cpu(*(uint16_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; + cdf_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 = cdf_le16_to_cpu(*(uint16_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) { + uint32_t now_ms = cdf_system_ticks_to_msecs(cdf_system_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, + cdf_nbuf_t *head_addr, + cdf_nbuf_t *tail_addr, + cdf_nbuf_t frag, uint8_t *all_frag_present) +{ + cdf_nbuf_t next, prev = NULL, cur = *head_addr; + struct ieee80211_frame *mac_hdr, *cmac_hdr, *next_hdr, *lmac_hdr; + uint8_t fragno, cur_fragno, lfragno, next_fragno; + uint8_t last_morefrag = 1, count = 0; + cdf_nbuf_t frag_clone; + + cdf_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 = cdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + + if (!(*head_addr)) { + *head_addr = frag; + *tail_addr = frag; + cdf_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 = cdf_le16_to_cpu(*(uint16_t *) lmac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + if (fragno > lfragno) { + cdf_nbuf_set_next(*tail_addr, frag); + *tail_addr = frag; + cdf_nbuf_set_next(*tail_addr, NULL); + } else { + do { + cmac_hdr = (struct ieee80211_frame *) + ol_rx_frag_get_mac_hdr(htt_pdev, cur); + cur_fragno = + cdf_le16_to_cpu(*(uint16_t *) cmac_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + prev = cur; + cur = cdf_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 { + cdf_nbuf_set_next(prev, frag); + cdf_nbuf_set_next(frag, cur); + } + } + next = cdf_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 = + cdf_le16_to_cpu(*(uint16_t *) next_hdr->i_seq) & + IEEE80211_SEQ_FRAG_MASK; + count++; + if (next_fragno != count) + break; + + next = cdf_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_next != NULL || + 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; + } +} + +#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; + uint32_t now_ms = cdf_system_ticks_to_msecs(cdf_system_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 /* frags 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, cdf_nbuf_t frag_list) +{ + struct ol_txrx_vdev_t *vdev = NULL; + cdf_nbuf_t tmp_next, msdu, prev = NULL, cur = frag_list; + uint8_t index, tkip_demic = 0; + uint16_t hdr_space; + void *rx_desc; + struct ieee80211_frame *wh; + uint8_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 = cdf_nbuf_next(cur); + cdf_nbuf_set_next(cur, NULL); + if (!ol_rx_pn_check_base(vdev, peer, tid, cur)) { + /* PN check failed,discard frags */ + if (prev) { + cdf_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 */ + cdf_nbuf_trim_tail(cur, DEFRAG_IEEE80211_FCS_LEN); + prev = cur; + cdf_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); + cdf_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 = cdf_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 = cdf_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 = cdf_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) { + cdf_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, + cdf_nbuf_t msdu, uint16_t hdrlen) +{ + uint8_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 = (uint8_t *) (cdf_nbuf_data(msdu) + rx_desc_len); + + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) + return OL_RX_DEFRAG_ERR; + + cdf_mem_move(origHdr + f_tkip.ic_header, origHdr, hdrlen); + cdf_nbuf_pull_head(msdu, f_tkip.ic_header); + cdf_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, cdf_nbuf_t msdu, uint16_t hdrlen) +{ + uint8_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 = (uint8_t *) (cdf_nbuf_data(msdu) + rx_desc_len); + cdf_mem_move(origHdr + f_wep.ic_header, origHdr, hdrlen); + cdf_nbuf_pull_head(msdu, f_wep.ic_header); + cdf_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 uint8_t *key, + cdf_nbuf_t msdu, uint16_t hdrlen) +{ + int status; + uint32_t pktlen; + uint8_t mic[IEEE80211_WEP_MICLEN]; + uint8_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 (cdf_mem_compare(mic, mic0, f_tkip.ic_miclen)) + return OL_RX_DEFRAG_ERR; + + cdf_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, + cdf_nbuf_t nbuf, uint16_t hdrlen) +{ + uint8_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 = (uint8_t *) (cdf_nbuf_data(nbuf) + rx_desc_len); + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) + return OL_RX_DEFRAG_ERR; + + cdf_mem_move(origHdr + f_ccmp.ic_header, origHdr, hdrlen); + cdf_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, + cdf_nbuf_t wbuf, uint16_t hdrlen) +{ + uint8_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 = (uint8_t *) (cdf_nbuf_data(wbuf) + rx_desc_len); + + ivp = origHdr + hdrlen; + if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)) + return OL_RX_DEFRAG_ERR; + + cdf_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, uint8_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 uint8_t *key, + cdf_nbuf_t wbuf, + uint16_t off, uint16_t data_len, uint8_t mic[]) +{ + uint8_t hdr[16] = { 0, }; + uint32_t l, r; + const uint8_t *data; + uint32_t space; + 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); + + ol_rx_defrag_michdr((struct ieee80211_frame *)(cdf_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 = (uint8_t *) cdf_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(uint32_t)) { + l ^= get_le32(data); + michael_block(l, r); + data += sizeof(uint32_t); + space -= sizeof(uint32_t); + data_len -= sizeof(uint32_t); + } + if (data_len < sizeof(uint32_t)) + break; + + wbuf = cdf_nbuf_next(wbuf); + if (wbuf == NULL) + return OL_RX_DEFRAG_ERR; + + rx_desc_len = 0; + + if (space != 0) { + const uint8_t *data_next; + /* + * Block straddles buffers, split references. + */ + data_next = + (uint8_t *) cdf_nbuf_data(wbuf) + rx_desc_len; + if ((ol_rx_defrag_len(wbuf) - rx_desc_len) < + sizeof(uint32_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(uint32_t); + } else { + /* + * Setup for next buffer. + */ + data = (uint8_t *) cdf_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 + */ +uint16_t ol_rx_frag_hdrsize(const void *data) +{ + const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data; + uint16_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(uint16_t); + if (wh->i_fc[1] & IEEE80211_FC1_ORDER) + size += sizeof(struct ieee80211_htc); + } + return size; +} + +/* + * Recombine and decap fragments + */ +cdf_nbuf_t +ol_rx_defrag_decap_recombine(htt_pdev_handle htt_pdev, + cdf_nbuf_t frag_list, uint16_t hdrsize) +{ + cdf_nbuf_t tmp; + cdf_nbuf_t msdu = frag_list; + cdf_nbuf_t rx_nbuf = frag_list; + struct ieee80211_frame *wh; + + msdu = cdf_nbuf_next(msdu); + cdf_nbuf_set_next(rx_nbuf, NULL); + while (msdu) { + htt_rx_msdu_desc_free(htt_pdev, msdu); + tmp = cdf_nbuf_next(msdu); + cdf_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); + cdf_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; + *(uint16_t *) wh->i_seq &= ~IEEE80211_SEQ_FRAG_MASK; + + return rx_nbuf; +} + +void ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev, cdf_nbuf_t msdu) +{ + struct ieee80211_frame wh; + 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 *)(cdf_nbuf_data(msdu) + rx_desc_len); + cdf_mem_copy(&wh, wh_ptr, sizeof(wh)); + hdrsize = sizeof(struct ieee80211_frame); + cdf_mem_copy(&llchdr, ((uint8_t *) (cdf_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) + */ + cdf_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 *)(cdf_nbuf_data(msdu)); + switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { + case IEEE80211_FC1_DIR_NODS: + cdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1, + IEEE80211_ADDR_LEN); + cdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + cdf_mem_copy(eth_hdr->dest_addr, wh.i_addr3, + IEEE80211_ADDR_LEN); + cdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + cdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1, + IEEE80211_ADDR_LEN); + cdf_mem_copy(eth_hdr->src_addr, wh.i_addr3, IEEE80211_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + break; + } + + cdf_mem_copy(eth_hdr->ethertype, llchdr.ethertype, + sizeof(llchdr.ethertype)); +} + +/* + * Handling QOS for defragmentation + */ +void +ol_rx_defrag_qos_decap(ol_txrx_pdev_handle pdev, + cdf_nbuf_t nbuf, uint16_t hdrlen) +{ + struct ieee80211_frame *wh; + uint16_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 *)(cdf_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; + cdf_mem_move((uint8_t *) wh + qoslen, wh, hdrlen); + wh = (struct ieee80211_frame *)cdf_nbuf_pull_head(nbuf, + rx_desc_len + + qoslen); + /* clear QoS bit */ + /* + * KW# 6154 'cdf_nbuf_pull_head' in turn calls + * __cdf_nbuf_pull_head, + * which returns NULL if there is not sufficient data to pull. + * It's guaranteed that cdf_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 cdf_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; + + } +} diff --git a/core/dp/txrx/ol_rx_defrag.h b/core/dp/txrx/ol_rx_defrag.h new file mode 100644 index 000000000000..512fa5dacb2c --- /dev/null +++ b/core/dp/txrx/ol_rx_defrag.h @@ -0,0 +1,197 @@ +/* + * 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_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; + uint16_t ic_header; + uint8_t ic_trailer; + uint8_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) \ + cdf_nbuf_copy_bits(buf, offset, len, _to) + +#define ol_rx_defrag_len(buf) \ + cdf_nbuf_len(buf) + +void +ol_rx_fraglist_insert(htt_pdev_handle htt_pdev, + cdf_nbuf_t *head_addr, + cdf_nbuf_t *tail_addr, + cdf_nbuf_t frag, uint8_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, cdf_nbuf_t frag_list); + +int +ol_rx_frag_tkip_decap(ol_txrx_pdev_handle pdev, + cdf_nbuf_t msdu, uint16_t hdrlen); + +int +ol_rx_frag_wep_decap(ol_txrx_pdev_handle pdev, + cdf_nbuf_t nbuf, uint16_t hdrlen); + +void ol_rx_defrag_nwifi_to_8023(ol_txrx_pdev_handle pdev, cdf_nbuf_t msdu); + +void +ol_rx_defrag_qos_decap(ol_txrx_pdev_handle pdev, + cdf_nbuf_t nbuf, uint16_t hdrlen); + +int +ol_rx_frag_tkip_demic(ol_txrx_pdev_handle pdev, + const uint8_t *key, cdf_nbuf_t msdu, uint16_t hdrlen); + +int +ol_rx_frag_ccmp_decap(ol_txrx_pdev_handle pdev, + cdf_nbuf_t nbuf, uint16_t hdrlen); + +int +ol_rx_frag_ccmp_demic(ol_txrx_pdev_handle pdev, + cdf_nbuf_t wbuf, uint16_t hdrlen); + +uint16_t ol_rx_frag_hdrsize(const void *data); + +void ol_rx_defrag_michdr(const struct ieee80211_frame *wh0, uint8_t hdr[]); + +void +ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev, + struct ol_txrx_peer_t *peer, + unsigned tid, uint16_t seq_num, cdf_nbuf_t frag); + +cdf_nbuf_t +ol_rx_defrag_decap_recombine(htt_pdev_handle htt_pdev, + cdf_nbuf_t frag_list, uint16_t hdrsize); + +int +ol_rx_defrag_mic(ol_txrx_pdev_handle pdev, + const uint8_t *key, + cdf_nbuf_t wbuf, + uint16_t off, uint16_t data_len, uint8_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(uint8_t *b, const uint8_t *a, cdf_size_t len) +{ + cdf_size_t i; + + for (i = 0; i < len; i++) + b[i] ^= a[i]; +} + +static inline uint32_t rotl(uint32_t val, int bits) +{ + return (val << bits) | (val >> (32 - bits)); +} + +static inline uint32_t rotr(uint32_t val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + +static inline uint32_t xswap(uint32_t val) +{ + return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); +} + +static inline uint32_t +get_le32_split(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) +{ + return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); +} + +static inline uint32_t get_le32(const uint8_t *p) +{ + return get_le32_split(p[0], p[1], p[2], p[3]); +} + +static inline void put_le32(uint8_t *p, uint32_t v) +{ + p[0] = (v) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; +} + +static inline uint8_t ol_rx_defrag_concat(cdf_nbuf_t dst, cdf_nbuf_t src) +{ + /* + * Inside cdf_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 (cdf_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/core/dp/txrx/ol_rx_fwd.c b/core/dp/txrx/ol_rx_fwd.c new file mode 100644 index 000000000000..e97f34f05717 --- /dev/null +++ b/core/dp/txrx/ol_rx_fwd.c @@ -0,0 +1,232 @@ +/* + * 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. + */ + +/* standard header files */ +#include /* cdf_nbuf_map */ +#include /* cdf_mem_compare */ + +/* 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 */ +#include +/* + * 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, cdf_nbuf_t msdu) +{ + struct ieee80211_frame *mac_header; + unsigned char tmp_addr[IEEE80211_ADDR_LEN]; + unsigned char type; + unsigned char subtype; + unsigned char fromds; + unsigned char tods; + + mac_header = (struct ieee80211_frame *)(cdf_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)) || + (cdf_mem_compare + (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, cdf_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. + */ + cdf_nbuf_map_single(pdev->osdev, msdu, CDF_DMA_TO_DEVICE); + cdf_nbuf_set_next(msdu, NULL); /* add NULL terminator */ + + msdu = OL_TX_LL(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. + */ + cdf_nbuf_unmap_single(pdev->osdev, msdu, CDF_DMA_TO_DEVICE); + cdf_nbuf_tx_free(msdu, NBUF_PKT_ERROR); + } +} + +void +ol_rx_fwd_check(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, unsigned tid, cdf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + cdf_nbuf_t deliver_list_head = NULL; + cdf_nbuf_t deliver_list_tail = NULL; + cdf_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 = cdf_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)) { + /* + * 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) { + cdf_nbuf_set_tid(msdu, tid); + } else { + cdf_nbuf_set_tid(msdu, + ADF_NBUF_TX_EXT_TID_INVALID); + } + /* + * 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 (htt_rx_msdu_discard(pdev->htt_pdev, rx_desc)) { + htt_rx_msdu_desc_free(pdev->htt_pdev, msdu); + cdf_net_buf_debug_release_skb(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 { + cdf_nbuf_t copy; + copy = cdf_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) { + /* add NULL terminator */ + cdf_nbuf_set_next(deliver_list_tail, NULL); + 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/core/dp/txrx/ol_rx_fwd.h b/core/dp/txrx/ol_rx_fwd.h new file mode 100644 index 000000000000..fe570c5acb4c --- /dev/null +++ b/core/dp/txrx/ol_rx_fwd.h @@ -0,0 +1,75 @@ +/* + * 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_FWD_H_ +#define _OL_RX_FWD_H_ + +#include /* cdf_nbuf_t, etc. */ + +#include /* ol_txrx_peer_t, etc. */ + +cdf_nbuf_t +ol_rx_fwd_mcast_check_sta(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + cdf_nbuf_t msdu, void *rx_desc, int is_wlan_mcast); + +cdf_nbuf_t +ol_rx_fwd_mcast_check_ap(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + cdf_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, cdf_nbuf_t msdu_list); + +#endif /* _OL_RX_FWD_H_ */ diff --git a/core/dp/txrx/ol_rx_pn.c b/core/dp/txrx/ol_rx_pn.c new file mode 100644 index 000000000000..362616c71f2d --- /dev/null +++ b/core/dp/txrx/ol_rx_pn.c @@ -0,0 +1,348 @@ +/* + * 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. + */ + +#include /* cdf_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 { \ + cdf_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) +{ + int rc = ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff)); + return rc; +} + +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 rc = ((new_pn->pn48 & 0xffffffffffffULL) <= + (old_pn->pn48 & 0xffffffffffffULL)); + return rc; +} + +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; +} + +cdf_nbuf_t +ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, cdf_nbuf_t msdu_list) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + union htt_rx_pn_t *last_pn; + cdf_nbuf_t out_list_head = NULL; + cdf_nbuf_t out_list_tail = NULL; + cdf_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 (cdf_atomic_read(&peer->fw_pn_check)) + return msdu_list; + + /* First, check whether the PN check applies */ + rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu_list); + cdf_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) { + cdf_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) { + cdf_nbuf_t msdu; + static uint32_t last_pncheck_print_time /* = 0 */; + int log_level; + uint32_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 = + cdf_system_ticks_to_msecs(cdf_system_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 { + cdf_nbuf_t next_msdu; + OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, + rx_desc, OL_RX_ERR_PN); + next_msdu = cdf_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) + cdf_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, cdf_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, cdf_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 = + cdf_mem_malloc(sizeof(*pdev->rx_pn_trace.data) * num_elems); + if (!pdev->rx_pn_trace.data) + return A_NO_MEMORY; + return A_OK; +} + +void ol_rx_pn_trace_detach(ol_txrx_pdev_handle pdev) +{ + cdf_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, uint16_t tid, void *rx_desc) +{ + uint32_t idx = pdev->rx_pn_trace.idx; + union htt_rx_pn_t pn; + uint32_t pn32; + uint16_t seq_num; + uint8_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 */; + uint32_t i, start, end; + uint64_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; + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " seq PN"); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " count idx peer tid uni num LSBs"); + do { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " %6lld %4d %p %2d %d %4d %8d", + 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/core/dp/txrx/ol_rx_pn.h b/core/dp/txrx/ol_rx_pn.h new file mode 100644 index 000000000000..845dc9177394 --- /dev/null +++ b/core/dp/txrx/ol_rx_pn.h @@ -0,0 +1,105 @@ +/* + * 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_PN_H_ +#define _OL_RX_PN_H_ + +#include /* cdf_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, cdf_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, cdf_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 + */ +cdf_nbuf_t +ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev, + struct ol_txrx_peer_t *peer, + unsigned tid, cdf_nbuf_t msdu_list); + +#endif /* _OL_RX_PN_H_ */ diff --git a/core/dp/txrx/ol_rx_reorder.c b/core/dp/txrx/ol_rx_reorder.c new file mode 100644 index 000000000000..da0d486dddeb --- /dev/null +++ b/core/dp/txrx/ol_rx_reorder.c @@ -0,0 +1,827 @@ +/* + * 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 /* cdf_nbuf_t, etc. */ +#include /* cdf_mem_malloc */ + +#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) { \ + cdf_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, uint8_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 (cdf_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 (cdf_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 (cdf_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, cdf_nbuf_t head_msdu, cdf_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) { + cdf_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; + cdf_nbuf_t head_msdu; + cdf_nbuf_t tail_msdu; + + OL_RX_REORDER_IDX_START_SELF_SELECT(peer, tid, &idx_start); + /* may get reset below */ + peer->tids_next_rel_idx[tid] = (uint16_t) idx_end; + + 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) { + uint16_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 */ + cdf_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; + uint8_t win_sz_mask; + struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem; + cdf_nbuf_t head_msdu = NULL; + cdf_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] = (uint16_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; + } + cdf_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) { + uint16_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 */ + cdf_nbuf_set_next(tail_msdu, NULL); + if (action == htt_rx_flush_release) { + peer->rx_opt_proc(vdev, peer, tid, head_msdu); + } else { + do { + cdf_nbuf_t next; + next = cdf_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, + uint16_t peer_id, + uint8_t tid, + uint8_t win_sz, uint16_t start_seq_num, uint8_t failed) +{ + uint8_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 = cdf_mem_malloc(array_size); + TXRX_ASSERT1(rx_reorder->array); + cdf_mem_set(rx_reorder->array, array_size, 0x0); + + 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, uint16_t peer_id, uint8_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); + cdf_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, + uint16_t peer_id, + uint8_t tid, + uint16_t idx_start, + uint16_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, + uint16_t peer_id, + uint8_t tid, + int seq_num_start, + int seq_num_end, uint8_t pn_ie_cnt, uint8_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; + cdf_nbuf_t head_msdu = NULL; + cdf_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; + + cdf_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])) { + cdf_nbuf_t msdu, next_msdu, mpdu_head, + mpdu_tail; + static uint32_t last_pncheck_print_time; + /* Do not need to initialize as C does it */ + + int log_level; + uint32_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 = cdf_system_ticks_to_msecs( + cdf_system_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 = cdf_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 { + cdf_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 */ + cdf_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 = cdf_mem_malloc( + sizeof(*pdev->rx_reorder_trace.data) * num_elems); + if (!pdev->rx_reorder_trace.data) + return A_NO_MEMORY; + + 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) +{ + cdf_mem_free(pdev->rx_reorder_trace.data); +} + +void +ol_rx_reorder_trace_add(ol_txrx_pdev_handle pdev, + uint8_t tid, + uint16_t reorder_idx, uint16_t seq_num, int num_mpdus) +{ + uint32_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; + uint32_t i, start, end; + uint64_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; + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " log array seq"); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " count idx tid idx num (LSBs)"); + do { + uint16_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)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " %6lld %4d %3d %4d %4d (%d)", + 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); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " %6lld %4d err %d (%d MPDUs)", + 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/core/dp/txrx/ol_rx_reorder.h b/core/dp/txrx/ol_rx_reorder.h new file mode 100644 index 000000000000..7629c6a9b2f7 --- /dev/null +++ b/core/dp/txrx/ol_rx_reorder.h @@ -0,0 +1,93 @@ +/* + * 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 _OL_RX_REORDER__H_ +#define _OL_RX_REORDER__H_ + +#include /* cdf_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, + cdf_nbuf_t head_msdu, cdf_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, uint8_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/core/dp/txrx/ol_rx_reorder_timeout.c b/core/dp/txrx/ol_rx_reorder_timeout.c new file mode 100644 index 000000000000..cc2e2a32c78f --- /dev/null +++ b/core/dp/txrx/ol_rx_reorder_timeout.c @@ -0,0 +1,219 @@ +/* + * 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. + */ + +/*=== header file includes ===*/ +/* generic utilities */ +#include /* cdf_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, uint32_t time_now_ms) +{ + uint32_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; + cdf_softirq_timer_start(&rx_reorder_timeout_ac->timer, duration_ms); +} + +static inline void +ol_rx_reorder_timeout_add(struct ol_txrx_peer_t *peer, uint8_t tid) +{ + uint32_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 = cdf_system_ticks_to_msecs(cdf_system_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, uint8_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; + uint32_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 = cdf_system_ticks_to_msecs(cdf_system_ticks()); + + pdev = rx_reorder_timeout_ac->pdev; + cdf_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); + + cdf_spin_unlock(&pdev->rx.mutex); +} + +void ol_rx_reorder_timeout_init(struct ol_txrx_pdev_t *pdev) +{ + int i; + + for (i = 0; i < CDF_ARRAY_SIZE(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 */ + cdf_softirq_timer_init(pdev->osdev, + &rx_reorder_timeout_ac->timer, + ol_rx_reorder_timeout, + rx_reorder_timeout_ac); + /* 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 < CDF_ARRAY_SIZE(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]; + cdf_softirq_timer_cancel(&rx_reorder_timeout_ac->timer); + cdf_softirq_timer_free(&rx_reorder_timeout_ac->timer); + } +} + +#endif /* QCA_SUPPORT_OL_RX_REORDER_TIMEOUT */ diff --git a/core/dp/txrx/ol_rx_reorder_timeout.h b/core/dp/txrx/ol_rx_reorder_timeout.h new file mode 100644 index 000000000000..1f43871eeb64 --- /dev/null +++ b/core/dp/txrx/ol_rx_reorder_timeout.h @@ -0,0 +1,66 @@ +/* + * 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_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, uint8_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) \ + cdf_spin_lock(&(pdev)->rx.mutex) +#define OL_RX_REORDER_TIMEOUT_MUTEX_UNLOCK(pdev) \ + cdf_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/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c new file mode 100644 index 000000000000..f1941c2cba46 --- /dev/null +++ b/core/dp/txrx/ol_tx.c @@ -0,0 +1,1364 @@ +/* + * 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. + */ + +/* OS abstraction libraries */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_atomic_read, etc. */ +#include /* cdf_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_enqueue */ + +/* internal header files relevant only for specific systems (Pronto) */ +#include /* OL_TX_ENCAP, etc */ +#include + +#ifdef WLAN_FEATURE_FASTPATH +#include /* HIF_DEVICE */ +#include /* Layering violation, but required for fast path */ +#include +#include /* htc_endpoint */ + +int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, + unsigned int num_msdus, unsigned int transfer_id); +#endif /* WLAN_FEATURE_FASTPATH */ + +/* + * 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. + */ +#define ol_tx_prepare_ll(tx_desc, vdev, msdu, msdu_info) \ + do { \ + struct ol_txrx_pdev_t *pdev = vdev->pdev; \ + (msdu_info)->htt.info.frame_type = pdev->htt_pkt_type; \ + tx_desc = ol_tx_desc_ll(pdev, vdev, msdu, msdu_info); \ + if (cdf_unlikely(!tx_desc)) { \ + TXRX_STATS_MSDU_LIST_INCR( \ + pdev, tx.dropped.host_reject, msdu); \ + return msdu; /* the list of unaccepted MSDUs */ \ + } \ + } while (0) + +#define ol_tx_prepare_tso(vdev, msdu, msdu_info) \ + do { \ + msdu_info.tso_info.curr_seg = NULL; \ + if (cdf_nbuf_is_tso(msdu)) { \ + int num_seg = cdf_nbuf_get_tso_num_seg(msdu); \ + msdu_info.tso_info.tso_seg_list = NULL; \ + msdu_info.tso_info.num_segs = num_seg; \ + while (num_seg) { \ + struct cdf_tso_seg_elem_t *tso_seg = \ + ol_tso_alloc_segment(vdev->pdev); \ + if (tso_seg) { \ + tso_seg->next = \ + msdu_info.tso_info.tso_seg_list; \ + msdu_info.tso_info.tso_seg_list \ + = tso_seg; \ + num_seg--; \ + } else {\ + cdf_print("TSO seg alloc failed!\n"); \ + } \ + } \ + cdf_nbuf_get_tso_info(vdev->pdev->osdev, \ + msdu, &msdu_info.tso_info); \ + msdu_info.tso_info.curr_seg = \ + msdu_info.tso_info.tso_seg_list; \ + num_seg = msdu_info.tso_info.num_segs; \ + } else { \ + msdu_info.tso_info.is_tso = 0; \ + msdu_info.tso_info.num_segs = 1; \ + } \ + } while (0) + +/** + * ol_tx_send_data_frame() - send data frame + * @sta_id: sta id + * @skb: skb + * @proto_type: proto type + * + * Return: skb/NULL for success + */ +cdf_nbuf_t ol_tx_send_data_frame(uint8_t sta_id, cdf_nbuf_t skb, + uint8_t proto_type) +{ + void *cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_txrx_peer_t *peer; + cdf_nbuf_t ret; + CDF_STATUS status; + + if (cdf_unlikely(!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s:pdev is null", __func__); + return skb; + } + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s:Invalid sta id", __func__); + return skb; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + if (!peer) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s:Invalid peer", __func__); + return skb; + } + + if (peer->state < ol_txrx_peer_state_conn) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: station to be yet registered..dropping pkt", __func__); + return skb; + } + + status = cdf_nbuf_map_single(cdf_ctx, skb, CDF_DMA_TO_DEVICE); + if (cdf_unlikely(status != CDF_STATUS_SUCCESS)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: nbuf map failed", __func__); + return skb; + } + + cdf_nbuf_trace_set_proto_type(skb, proto_type); + + if ((ol_cfg_is_ip_tcp_udp_checksum_offload_enabled(pdev->ctrl_pdev)) + && (cdf_nbuf_get_protocol(skb) == htons(ETH_P_IP)) + && (cdf_nbuf_get_ip_summed(skb) == CHECKSUM_PARTIAL)) + cdf_nbuf_set_ip_summed(skb, CHECKSUM_COMPLETE); + + /* Terminate the (single-element) list of tx frames */ + cdf_nbuf_set_next(skb, NULL); + ret = OL_TX_LL(peer->vdev, skb); + if (ret) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: Failed to tx", __func__); + cdf_nbuf_unmap_single(cdf_ctx, ret, CDF_DMA_TO_DEVICE); + return ret; + } + + return NULL; +} + +#ifdef IPA_OFFLOAD +/** + * ol_tx_send_ipa_data_frame() - send IPA data frame + * @vdev: vdev + * @skb: skb + * + * Return: skb/ NULL is for success + */ +cdf_nbuf_t ol_tx_send_ipa_data_frame(void *vdev, + cdf_nbuf_t skb) +{ + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + cdf_nbuf_t ret; + + if (cdf_unlikely(!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pdev is NULL", __func__); + return skb; + } + + if ((ol_cfg_is_ip_tcp_udp_checksum_offload_enabled(pdev->ctrl_pdev)) + && (cdf_nbuf_get_protocol(skb) == htons(ETH_P_IP)) + && (cdf_nbuf_get_ip_summed(skb) == CHECKSUM_PARTIAL)) + cdf_nbuf_set_ip_summed(skb, CHECKSUM_COMPLETE); + + /* Terminate the (single-element) list of tx frames */ + cdf_nbuf_set_next(skb, NULL); + ret = OL_TX_LL((struct ol_txrx_vdev_t *)vdev, skb); + if (ret) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "%s: Failed to tx", __func__); + return ret; + } + + return NULL; +} +#endif + + +#if defined(FEATURE_TSO) +cdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + cdf_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) { + cdf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + int segments = 1; + + msdu_info.htt.info.ext_tid = cdf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + + ol_tx_prepare_tso(vdev, msdu, msdu_info); + segments = msdu_info.tso_info.num_segs; + + /* + * 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 = cdf_nbuf_next(msdu); + /* init the current segment to the 1st segment in the list */ + while (segments) { + + if (msdu_info.tso_info.curr_seg) + NBUF_MAPPED_PADDR_LO(msdu) = msdu_info.tso_info. + curr_seg->seg.tso_frags[0].paddr_low_32; + + segments--; + + /** + * if this is a jumbo nbuf, then increment the number + * of nbuf users for each additional segment of the msdu. + * This will ensure that the skb is freed only after + * receiving tx completion for all segments of an nbuf + */ + if (segments) + cdf_nbuf_inc_users(msdu); + + 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); + + ol_tx_send(vdev->pdev, tx_desc, msdu); + + if (msdu_info.tso_info.curr_seg) { + msdu_info.tso_info.curr_seg = + msdu_info.tso_info.curr_seg->next; + } + + cdf_nbuf_dec_num_frags(msdu); + + if (msdu_info.tso_info.is_tso) { + TXRX_STATS_TSO_INC_SEG(vdev->pdev); + TXRX_STATS_TSO_INC_SEG_IDX(vdev->pdev); + } + } /* while segments */ + + msdu = next; + if (msdu_info.tso_info.is_tso) { + TXRX_STATS_TSO_INC_MSDU_IDX(vdev->pdev); + TXRX_STATS_TSO_RESET_MSDU(vdev->pdev); + } + } /* while msdus */ + return NULL; /* all MSDUs were accepted */ +} +#else /* TSO */ + +cdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + cdf_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; + msdu_info.tso_info.is_tso = 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) { + cdf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + + msdu_info.htt.info.ext_tid = cdf_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 = cdf_nbuf_next(msdu); + ol_tx_send(vdev->pdev, tx_desc, msdu); + msdu = next; + } + return NULL; /* all MSDUs were accepted */ +} +#endif /* TSO */ + +#ifdef WLAN_FEATURE_FASTPATH +/** + * ol_tx_prepare_ll_fast() Alloc and prepare Tx descriptor + * + * Allocate and prepare Tx descriptor with msdu and fragment descritor + * inforamtion. + * + * @pdev: pointer to ol pdev handle + * @vdev: pointer to ol vdev handle + * @msdu: linked list of msdu packets + * @pkt_download_len: packet download length + * @ep_id: endpoint ID + * @msdu_info: Handle to msdu_info + * + * Return: Pointer to Tx descriptor + */ +static inline struct ol_tx_desc_t * +ol_tx_prepare_ll_fast(struct ol_txrx_pdev_t *pdev, + ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu, + uint32_t pkt_download_len, uint32_t ep_id, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ol_tx_desc_t *tx_desc = NULL; + uint32_t *htt_tx_desc; + void *htc_hdr_vaddr; + u_int32_t num_frags, i; + + tx_desc = ol_tx_desc_alloc_wrapper(pdev, vdev, msdu_info); + if (cdf_unlikely(!tx_desc)) + return NULL; + + tx_desc->netbuf = msdu; + if (msdu_info->tso_info.is_tso) { + tx_desc->tso_desc = msdu_info->tso_info.curr_seg; + tx_desc->pkt_type = ol_tx_frm_tso; + TXRX_STATS_MSDU_INCR(pdev, tx.tso.tso_pkts, msdu); + } else { + tx_desc->pkt_type = ol_tx_frm_std; + } + + htt_tx_desc = tx_desc->htt_tx_desc; + + /* Make sure frags num is set to 0 */ + /* + * Do this here rather than in hardstart, so + * that we can hopefully take only one cache-miss while + * accessing skb->cb. + */ + + /* HTT Header */ + /* TODO : Take care of multiple fragments */ + + /* TODO: Precompute and store paddr in ol_tx_desc_t */ + /* Virtual address of the HTT/HTC header, added by driver */ + htc_hdr_vaddr = (char *)htt_tx_desc - HTC_HEADER_LEN; + htt_tx_desc_init(pdev->htt_pdev, htt_tx_desc, + tx_desc->htt_tx_desc_paddr, tx_desc->id, msdu, + &msdu_info->htt, &msdu_info->tso_info, + NULL, vdev->opmode == wlan_op_mode_ocb); + + num_frags = cdf_nbuf_get_num_frags(msdu); + /* num_frags are expected to be 2 max */ + num_frags = (num_frags > CVG_NBUF_MAX_EXTRA_FRAGS) ? + CVG_NBUF_MAX_EXTRA_FRAGS : num_frags; +#if defined(HELIUMPLUS_PADDR64) + /* + * Use num_frags - 1, since 1 frag is used to store + * the HTT/HTC descriptor + * Refer to htt_tx_desc_init() + */ + htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_frag_desc, + num_frags - 1); +#else /* ! defined(HELIUMPLUSPADDR64) */ + htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_tx_desc, + num_frags-1); +#endif /* defined(HELIUMPLUS_PADDR64) */ + if (msdu_info->tso_info.is_tso) { + htt_tx_desc_fill_tso_info(pdev->htt_pdev, + tx_desc->htt_frag_desc, &msdu_info->tso_info); + TXRX_STATS_TSO_SEG_UPDATE(pdev, + msdu_info->tso_info.curr_seg->seg); + } else { + for (i = 1; i < num_frags; i++) { + cdf_size_t frag_len; + u_int32_t frag_paddr; + + frag_len = cdf_nbuf_get_frag_len(msdu, i); + frag_paddr = cdf_nbuf_get_frag_paddr_lo(msdu, i); +#if defined(HELIUMPLUS_PADDR64) + htt_tx_desc_frag(pdev->htt_pdev, tx_desc->htt_frag_desc, + i - 1, frag_paddr, frag_len); +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s:%d: htt_fdesc=%p frag_paddr=%u len=%zu\n", + __func__, __LINE__, tx_desc->htt_frag_desc, + frag_paddr, frag_len); + dump_pkt(netbuf, frag_paddr, 64); +#endif /* HELIUMPLUS_DEBUG */ +#else /* ! defined(HELIUMPLUSPADDR64) */ + htt_tx_desc_frag(pdev->htt_pdev, tx_desc->htt_tx_desc, + i - 1, frag_paddr, frag_len); +#endif /* defined(HELIUMPLUS_PADDR64) */ + } + } + + /* + * Do we want to turn on word_stream bit-map here ? For linux, non-TSO + * this is not required. We still have to mark the swap bit correctly, + * when posting to the ring + */ + /* Check to make sure, data download length is correct */ + + /* + * TODO : Can we remove this check and always download a fixed length ? + * */ + if (cdf_unlikely(cdf_nbuf_len(msdu) < pkt_download_len)) + pkt_download_len = cdf_nbuf_len(msdu); + + /* Fill the HTC header information */ + /* + * Passing 0 as the seq_no field, we can probably get away + * with it for the time being, since this is not checked in f/w + */ + /* TODO : Prefill this, look at multi-fragment case */ + HTC_TX_DESC_FILL(htc_hdr_vaddr, pkt_download_len, ep_id, 0); + + return tx_desc; +} +#if defined(FEATURE_TSO) +/** + * ol_tx_ll_fast() Update metadata information and send msdu to HIF/CE + * + * @vdev: handle to ol_txrx_vdev_t + * @msdu_list: msdu list to be sent out. + * + * Return: on success return NULL, pointer to nbuf when it fails to send. + */ +cdf_nbuf_t +ol_tx_ll_fast(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + cdf_nbuf_t msdu = msdu_list; + struct ol_txrx_pdev_t *pdev = vdev->pdev; + uint32_t pkt_download_len = + ((struct htt_pdev_t *)(pdev->htt_pdev))->download_len; + uint32_t ep_id = HTT_EPID_GET(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) { + cdf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + int segments = 1; + + msdu_info.htt.info.ext_tid = cdf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + + ol_tx_prepare_tso(vdev, msdu, msdu_info); + segments = msdu_info.tso_info.num_segs; + + /* + * The netbuf may get linked into a different list + * inside the ce_send_fast function, so store the next + * pointer before the ce_send call. + */ + next = cdf_nbuf_next(msdu); + /* init the current segment to the 1st segment in the list */ + while (segments) { + + if (msdu_info.tso_info.curr_seg) + NBUF_MAPPED_PADDR_LO(msdu) = msdu_info.tso_info. + curr_seg->seg.tso_frags[0].paddr_low_32; + + segments--; + + /** + * if this is a jumbo nbuf, then increment the number + * of nbuf users for each additional segment of the msdu. + * This will ensure that the skb is freed only after + * receiving tx completion for all segments of an nbuf + */ + if (segments) + cdf_nbuf_inc_users(msdu); + + msdu_info.htt.info.frame_type = pdev->htt_pkt_type; + msdu_info.htt.info.vdev_id = vdev->vdev_id; + msdu_info.htt.action.cksum_offload = + cdf_nbuf_get_tx_cksum(msdu); + switch (cdf_nbuf_get_exemption_type(msdu)) { + case CDF_NBUF_EXEMPT_NO_EXEMPTION: + case CDF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: + /* We want to encrypt this frame */ + msdu_info.htt.action.do_encrypt = 1; + break; + case CDF_NBUF_EXEMPT_ALWAYS: + /* We don't want to encrypt this frame */ + msdu_info.htt.action.do_encrypt = 0; + break; + default: + msdu_info.htt.action.do_encrypt = 1; + cdf_assert(0); + break; + } + + tx_desc = ol_tx_prepare_ll_fast(pdev, vdev, msdu, + pkt_download_len, ep_id, + &msdu_info); + + if (cdf_likely(tx_desc)) { + /* + * 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); + if ((0 == ce_send_fast(pdev->ce_tx_hdl, &msdu, + 1, ep_id))) { + /* + * The packet could not be sent. + * Free the descriptor, return the + * packet to the caller. + */ + ol_tx_desc_free(pdev, tx_desc); + return msdu; + } + if (msdu_info.tso_info.curr_seg) { + msdu_info.tso_info.curr_seg = + msdu_info.tso_info.curr_seg->next; + } + + if (msdu_info.tso_info.is_tso) { + cdf_nbuf_dec_num_frags(msdu); + TXRX_STATS_TSO_INC_SEG(vdev->pdev); + TXRX_STATS_TSO_INC_SEG_IDX(vdev->pdev); + } + } else { + TXRX_STATS_MSDU_LIST_INCR( + pdev, tx.dropped.host_reject, msdu); + /* the list of unaccepted MSDUs */ + return msdu; + } + } /* while segments */ + + msdu = next; + if (msdu_info.tso_info.is_tso) { + TXRX_STATS_TSO_INC_MSDU_IDX(vdev->pdev); + TXRX_STATS_TSO_RESET_MSDU(vdev->pdev); + } + } /* while msdus */ + return NULL; /* all MSDUs were accepted */ +} +#else +cdf_nbuf_t +ol_tx_ll_fast(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + cdf_nbuf_t msdu = msdu_list; + struct ol_txrx_pdev_t *pdev = vdev->pdev; + uint32_t pkt_download_len = + ((struct htt_pdev_t *)(pdev->htt_pdev))->download_len; + uint32_t ep_id = HTT_EPID_GET(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; + msdu_info.tso_info.is_tso = 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) { + cdf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + + msdu_info.htt.info.ext_tid = cdf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + + msdu_info.htt.info.frame_type = pdev->htt_pkt_type; + msdu_info.htt.info.vdev_id = vdev->vdev_id; + msdu_info.htt.action.cksum_offload = + cdf_nbuf_get_tx_cksum(msdu); + switch (cdf_nbuf_get_exemption_type(msdu)) { + case CDF_NBUF_EXEMPT_NO_EXEMPTION: + case CDF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: + /* We want to encrypt this frame */ + msdu_info.htt.action.do_encrypt = 1; + break; + case CDF_NBUF_EXEMPT_ALWAYS: + /* We don't want to encrypt this frame */ + msdu_info.htt.action.do_encrypt = 0; + break; + default: + msdu_info.htt.action.do_encrypt = 1; + cdf_assert(0); + break; + } + + tx_desc = ol_tx_prepare_ll_fast(pdev, vdev, msdu, + pkt_download_len, ep_id, + &msdu_info); + + if (cdf_likely(tx_desc)) { + /* + * 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 ce_send_fast function, so store the next + * pointer before the ce_send call. + */ + next = cdf_nbuf_next(msdu); + if ((0 == ce_send_fast(pdev->ce_tx_hdl, &msdu, 1, + ep_id))) { + /* The packet could not be sent */ + /* Free the descriptor, return the packet to the + * caller */ + ol_tx_desc_free(pdev, tx_desc); + return msdu; + } + msdu = next; + } else { + TXRX_STATS_MSDU_LIST_INCR( + pdev, tx.dropped.host_reject, msdu); + return msdu; /* the list of unaccepted MSDUs */ + } + } + + return NULL; /* all MSDUs were accepted */ +} +#endif /* FEATURE_TSO */ +#endif /* WLAN_FEATURE_FASTPATH */ + +#ifdef WLAN_FEATURE_FASTPATH +/** + * ol_tx_ll_wrapper() wrapper to ol_tx_ll + * + */ +static inline cdf_nbuf_t +ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + struct ol_softc *hif_device = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + + if (cdf_likely(hif_device && hif_device->fastpath_mode_on)) + msdu_list = ol_tx_ll_fast(vdev, msdu_list); + else + msdu_list = ol_tx_ll(vdev, msdu_list); + + return msdu_list; +} +#else +static inline cdf_nbuf_t +ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + return ol_tx_ll(vdev, msdu_list); +} +#endif /* WLAN_FEATURE_FASTPATH */ + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + +#define OL_TX_VDEV_PAUSE_QUEUE_SEND_MARGIN 400 +#define OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS 5 +static void ol_tx_vdev_ll_pause_queue_send_base(struct ol_txrx_vdev_t *vdev) +{ + int max_to_accept; + + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.paused_reason) { + cdf_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) { + cdf_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 = cdf_nbuf_next(tx_msdu); + if (NULL == vdev->ll_pause.txq.head) + vdev->ll_pause.txq.tail = NULL; + cdf_nbuf_set_next(tx_msdu, NULL); + NBUF_UPDATE_TX_PKT_COUNT(tx_msdu, + NBUF_TX_PKT_TXRX_DEQUEUE); + tx_msdu = ol_tx_ll_wrapper(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) { + cdf_nbuf_unmap(vdev->pdev->osdev, tx_msdu, + CDF_DMA_TO_DEVICE); + cdf_nbuf_tx_free(tx_msdu, NBUF_PKT_ERROR); + } + } + } + if (vdev->ll_pause.txq.depth) { + cdf_softirq_timer_cancel(&vdev->ll_pause.timer); + cdf_softirq_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++; + } + + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); +} + +static cdf_nbuf_t +ol_tx_vdev_pause_queue_append(struct ol_txrx_vdev_t *vdev, + cdf_nbuf_t msdu_list, uint8_t start_timer) +{ + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + while (msdu_list && + vdev->ll_pause.txq.depth < vdev->ll_pause.max_q_depth) { + cdf_nbuf_t next = cdf_nbuf_next(msdu_list); + NBUF_UPDATE_TX_PKT_COUNT(msdu_list, NBUF_TX_PKT_TXRX_ENQUEUE); + DPTRACE(cdf_dp_trace(msdu_list, + CDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(msdu_list)), + sizeof(cdf_nbuf_data(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 { + cdf_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) + cdf_nbuf_set_next(vdev->ll_pause.txq.tail, NULL); + + if (start_timer) { + cdf_softirq_timer_cancel(&vdev->ll_pause.timer); + cdf_softirq_timer_start(&vdev->ll_pause.timer, + OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + vdev->ll_pause.is_q_timer_on = true; + } + cdf_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. + */ +cdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list) +{ + uint16_t eth_type; + uint32_t paused_reason; + + if (msdu_list == NULL) + return NULL; + + paused_reason = vdev->ll_pause.paused_reason; + if (paused_reason) { + if (cdf_unlikely((paused_reason & + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED) == + paused_reason)) { + eth_type = (((struct ethernet_hdr_t *) + cdf_nbuf_data(msdu_list))-> + ethertype[0] << 8) | + (((struct ethernet_hdr_t *) + cdf_nbuf_data(msdu_list))->ethertype[1]); + if (ETHERTYPE_IS_EAPOL_WAPI(eth_type)) { + msdu_list = ol_tx_ll_wrapper(vdev, msdu_list); + return msdu_list; + } + } + 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_wrapper(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 */ + cdf_nbuf_t tx_msdu; + struct ol_txrx_vdev_t *vdev = NULL; + uint8_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 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) { + + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.txq.depth) { + if (vdev->ll_pause.paused_reason) { + cdf_spin_unlock_bh(&vdev->ll_pause. + mutex); + continue; + } + + tx_msdu = vdev->ll_pause.txq.head; + if (NULL == tx_msdu) { + cdf_spin_unlock_bh(&vdev->ll_pause. + mutex); + continue; + } + + max_to_send--; + vdev->ll_pause.txq.depth--; + + vdev->ll_pause.txq.head = + cdf_nbuf_next(tx_msdu); + + if (NULL == vdev->ll_pause.txq.head) + vdev->ll_pause.txq.tail = NULL; + + cdf_nbuf_set_next(tx_msdu, NULL); + tx_msdu = ol_tx_ll_wrapper(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) { + cdf_nbuf_unmap(pdev->osdev, tx_msdu, + CDF_DMA_TO_DEVICE); + cdf_nbuf_tx_free(tx_msdu, + NBUF_PKT_ERROR); + } + } + /*check if there are more msdus to transmit */ + if (vdev->ll_pause.txq.depth) + more = 1; + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + } + } while (more && max_to_send); + + vdev = NULL; + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.txq.depth) { + cdf_softirq_timer_cancel(&pdev->tx_throttle.tx_timer); + cdf_softirq_timer_start( + &pdev->tx_throttle.tx_timer, + OL_TX_VDEV_PAUSE_QUEUE_SEND_PERIOD_MS); + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + return; + } + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + } +} + +void ol_tx_vdev_ll_pause_queue_send(void *context) +{ + struct ol_txrx_vdev_t *vdev = (struct ol_txrx_vdev_t *)context; + struct ol_txrx_pdev_t *pdev = vdev->pdev; + + if (pdev->tx_throttle.current_throttle_level != THROTTLE_LEVEL_0 && + pdev->tx_throttle.current_throttle_phase == THROTTLE_PHASE_OFF) + return; + ol_tx_vdev_ll_pause_queue_send_base(vdev); +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +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 uint8_t ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec) +{ + uint8_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; +} + +cdf_nbuf_t +ol_tx_non_std_ll(ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, cdf_nbuf_t msdu_list) +{ + cdf_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) { + cdf_nbuf_t next; + struct ol_tx_desc_t *tx_desc; + + msdu_info.htt.info.ext_tid = cdf_nbuf_get_tid(msdu); + msdu_info.peer = NULL; + msdu_info.tso_info.is_tso = 0; + + 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 = cdf_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) { + uint8_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 */ + uint8_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) { \ + cdf_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 (cdf_nbuf_t) + */ +#define OCB_HEADER_VERSION 1 +bool parse_ocb_tx_header(cdf_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 *) cdf_nbuf_data(msdu); + if (eth_hdr_p->ether_type != CDF_SWAP_U16(ETHERTYPE_OCB_TX)) + /* TX control header is not present. Nothing to do.. */ + return true; + + /* Remove the ethernet header */ + cdf_nbuf_pull_head(msdu, sizeof(struct ether_header)); + + /* Parse the TX control header */ + tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t *) cdf_nbuf_data(msdu); + + if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) { + if (tx_ctrl) + cdf_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 */ + cdf_nbuf_pull_head(msdu, tx_ctrl_hdr->length); + return true; +} + +cdf_nbuf_t +ol_tx_non_std(ol_txrx_vdev_handle vdev, + enum ol_tx_spec tx_spec, cdf_nbuf_t msdu_list) +{ + 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, + uint8_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; +} + +#if defined(HELIUMPLUS_PADDR64) +void dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc) +{ + uint32_t *frag_ptr_i_p; + int i; + + cdf_print("OL TX Descriptor 0x%p msdu_id %d\n", + tx_desc, tx_desc->index); + cdf_print("HTT TX Descriptor vaddr: 0x%p paddr: 0x%x\n", + tx_desc->htt_tx_desc, tx_desc->htt_tx_desc_paddr); + cdf_print("%s %d: Fragment Descriptor 0x%p\n", + __func__, __LINE__, tx_desc->htt_frag_desc); + + /* it looks from htt_tx_desc_frag() that tx_desc->htt_frag_desc + is already de-referrable (=> in virtual address space) */ + frag_ptr_i_p = tx_desc->htt_frag_desc; + + /* Dump 6 words of TSO flags */ + print_hex_dump(KERN_DEBUG, "MLE Desc:TSO Flags: ", + DUMP_PREFIX_NONE, 8, 4, + frag_ptr_i_p, 24, true); + + frag_ptr_i_p += 6; /* Skip 6 words of TSO flags */ + + i = 0; + while (*frag_ptr_i_p) { + print_hex_dump(KERN_DEBUG, "MLE Desc:Frag Ptr: ", + DUMP_PREFIX_NONE, 8, 4, + frag_ptr_i_p, 8, true); + i++; + if (i > 5) /* max 6 times: frag_ptr0 to frag_ptr5 */ + break; + else /* jump to next pointer - skip length */ + frag_ptr_i_p += 2; + } + return; +} +#endif /* HELIUMPLUS_PADDR64 */ + +int +ol_txrx_mgmt_send(ol_txrx_vdev_handle vdev, + cdf_nbuf_t tx_mgmt_frm, + uint8_t type, uint8_t use_6mbps, uint16_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.tso_info.is_tso = 0; + + 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; + + cdf_nbuf_map_single(pdev->osdev, tx_mgmt_frm, CDF_DMA_TO_DEVICE); + /* 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 defined(HELIUMPLUS_PADDR64) + /* dump_frag_desc("ol_txrx_mgmt_send(): after ol_tx_desc_ll", + tx_desc); */ +#endif /* defined(HELIUMPLUS_PADDR64) */ + 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, + cdf_nbuf_get_frag_paddr_lo(tx_mgmt_frm, 1), + 0, 0); +#if defined(HELIUMPLUS_PADDR64) && defined(HELIUMPLUS_DEBUG) + dump_frag_desc( + "after htt_tx_desc_frags_table_set", + tx_desc); +#endif /* defined(HELIUMPLUS_PADDR64) */ + } + if (!tx_desc) { + cdf_nbuf_unmap_single(pdev->osdev, tx_mgmt_frm, + CDF_DMA_TO_DEVICE); + return -EINVAL; /* 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; + + htt_tx_desc_set_chanfreq(tx_desc->htt_tx_desc, chanfreq); + NBUF_SET_PACKET_TRACK(tx_desc->netbuf, NBUF_TX_PKT_MGMT_TRACK); + 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, uint8_t sync_cnt) +{ + htt_h2t_sync_msg(pdev->htt_pdev, sync_cnt); +} + +cdf_nbuf_t ol_tx_reinject(struct ol_txrx_vdev_t *vdev, + cdf_nbuf_t msdu, uint16_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; + msdu_info.tso_info.is_tso = 0; + + ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); + HTT_TX_DESC_POSTPONED_SET(*((uint32_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; +} + +#if defined(FEATURE_TSO) +void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg) +{ + int i; + pdev->tso_seg_pool.pool_size = num_seg; + pdev->tso_seg_pool.num_free = num_seg; + + pdev->tso_seg_pool.array = NULL; + pdev->tso_seg_pool.array = cdf_mem_malloc(num_seg * + sizeof(struct cdf_tso_seg_elem_t)); + if (!pdev->tso_seg_pool.array) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s Could not allocate TSO array!\n", __func__); + return; + } + + pdev->tso_seg_pool.freelist = &pdev->tso_seg_pool.array[0]; + + for (i = 0; i < (num_seg - 1); i++) + pdev->tso_seg_pool.array[i].next = + &pdev->tso_seg_pool.array[i + 1]; + + pdev->tso_seg_pool.array[i].next = NULL; + + cdf_spinlock_init(&pdev->tso_seg_pool.tso_mutex); +} + +void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev) +{ + cdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); + if (pdev->tso_seg_pool.array) { + cdf_mem_free(pdev->tso_seg_pool.array); + pdev->tso_seg_pool.array = NULL; + } + + pdev->tso_seg_pool.freelist = NULL; + pdev->tso_seg_pool.num_free = 0; + pdev->tso_seg_pool.pool_size = 0; + cdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + cdf_spinlock_destroy(&pdev->tso_seg_pool.tso_mutex); +} +#endif /* FEATURE_TSO */ diff --git a/core/dp/txrx/ol_tx.h b/core/dp/txrx/ol_tx.h new file mode 100644 index 000000000000..8f4bbfe3a5a3 --- /dev/null +++ b/core/dp/txrx/ol_tx.h @@ -0,0 +1,82 @@ +/* + * 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_tx.h + * @brief Internal definitions for the high-level tx module. + */ +#ifndef _OL_TX__H_ +#define _OL_TX__H_ + +#include /* cdf_nbuf_t */ +#include +#include /* ol_txrx_vdev_handle */ + +#include /* ol_tx_desc_t, ol_txrx_msdu_info_t */ + +cdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list); +#ifdef WLAN_FEATURE_FASTPATH +cdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list); +#endif + +cdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, cdf_nbuf_t msdu_list); + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +#define OL_TX_LL ol_tx_ll_queue +#else +#define OL_TX_LL ol_tx_ll +#endif + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +void ol_tx_vdev_ll_pause_queue_send(void *context); +void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev); +#else +static inline void ol_tx_vdev_ll_pause_queue_send(void *context) +{ + return; +} +static inline +void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev) +{ + return; +} +#endif +cdf_nbuf_t +ol_tx_non_std_ll(ol_txrx_vdev_handle data_vdev, + enum ol_tx_spec tx_spec, cdf_nbuf_t msdu_list); + +cdf_nbuf_t +ol_tx_reinject(struct ol_txrx_vdev_t *vdev, cdf_nbuf_t msdu, uint16_t peer_id); + +void ol_txrx_mgmt_tx_complete(void *ctxt, cdf_nbuf_t netbuf, int err); + + +#if defined(FEATURE_TSO) +void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg); +void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev); +#endif +#endif /* _OL_TX__H_ */ diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c new file mode 100644 index 000000000000..3395b9103a22 --- /dev/null +++ b/core/dp/txrx/ol_tx_desc.c @@ -0,0 +1,621 @@ +/* + * 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. + */ + +#include /* CDF_NBUF_EXEMPT_NO_EXEMPTION, etc. */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_assert */ +#include /* cdf_spinlock */ +#ifdef QCA_COMPUTE_TX_DELAY +#include /* cdf_system_ticks */ +#endif + +#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 uint32_t *g_dbg_htt_desc_end_addr, *g_dbg_htt_desc_start_addr; +#endif + +#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS +static inline void ol_tx_desc_sanity_checks(struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc) +{ + if (tx_desc->pkt_type != 0xff) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s Potential tx_desc corruption pkt_type:0x%x pdev:0x%p", + __func__, tx_desc->pkt_type, pdev); + cdf_assert(0); + } + if ((uint32_t *) tx_desc->htt_tx_desc < + g_dbg_htt_desc_start_addr + || (uint32_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); + cdf_assert(0); + } +} +static inline void ol_tx_desc_reset_pkt_type(struct ol_tx_desc_t *tx_desc) +{ + tx_desc->pkt_type = 0xff; +} +#ifdef QCA_COMPUTE_TX_DELAY +static inline void ol_tx_desc_compute_delay(struct ol_tx_desc_t *tx_desc) +{ + if (tx_desc->entry_timestamp_ticks != 0xffffffff) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s Timestamp:0x%x\n", + __func__, tx_desc->entry_timestamp_ticks); + cdf_assert(0); + } + tx_desc->entry_timestamp_ticks = cdf_system_ticks(); +} +static inline void ol_tx_desc_reset_timestamp(struct ol_tx_desc_t *tx_desc) +{ + tx_desc->entry_timestamp_ticks = 0xffffffff; +} +#endif +#else +static inline void ol_tx_desc_sanity_checks(struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc) +{ + return; +} +static inline void ol_tx_desc_reset_pkt_type(struct ol_tx_desc_t *tx_desc) +{ + return; +} +static inline void ol_tx_desc_compute_delay(struct ol_tx_desc_t *tx_desc) +{ + return; +} +static inline void ol_tx_desc_reset_timestamp(struct ol_tx_desc_t *tx_desc) +{ + return; +} +#endif + +#ifndef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_tx_desc_alloc() - allocate descriptor from freelist + * @pdev: pdev handle + * @vdev: vdev handle + * + * Return: tx descriptor pointer/ NULL in case of error + */ +static +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; + + cdf_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; + ol_tx_desc_sanity_checks(pdev, tx_desc); + ol_tx_desc_compute_delay(tx_desc); + + } + cdf_spin_unlock_bh(&pdev->tx_mutex); + if (!tx_desc) + return NULL; + +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + tx_desc->vdev = vdev; + cdf_atomic_inc(&vdev->tx_desc_count); +#endif + + return tx_desc; +} + +/** + * ol_tx_desc_alloc_wrapper() -allocate tx descriptor + * @pdev: pdev handler + * @vdev: vdev handler + * @msdu_info: msdu handler + * + * Return: tx descriptor or NULL + */ +struct ol_tx_desc_t * +ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_msdu_info_t *msdu_info) +{ + return ol_tx_desc_alloc(pdev, vdev); +} + +#else +/** + * ol_tx_desc_alloc() -allocate tx descriptor + * @pdev: pdev handler + * @vdev: vdev handler + * @pool: flow pool + * + * Return: tx descriptor or NULL + */ +static +struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + struct ol_tx_flow_pool_t *pool) +{ + struct ol_tx_desc_t *tx_desc = NULL; + + if (pool) { + cdf_spin_lock_bh(&pool->flow_pool_lock); + if (pool->avail_desc) { + tx_desc = &pool->freelist->tx_desc; + pool->freelist = pool->freelist->next; + if (cdf_unlikely(--pool->avail_desc < pool->stop_th)) { + pool->status = FLOW_POOL_ACTIVE_PAUSED; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + /* pause network queues */ + pdev->pause_cb(vdev->vdev_id, + WLAN_STOP_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + } else { + cdf_spin_unlock_bh(&pool->flow_pool_lock); + } + ol_tx_desc_sanity_checks(pdev, tx_desc); + ol_tx_desc_compute_delay(tx_desc); + } else { + cdf_spin_unlock_bh(&pool->flow_pool_lock); + pdev->pool_stats.pkt_drop_no_desc++; + } + } else { + pdev->pool_stats.pkt_drop_no_pool++; + } + + return tx_desc; +} + +/** + * ol_tx_desc_alloc_wrapper() -allocate tx descriptor + * @pdev: pdev handler + * @vdev: vdev handler + * @msdu_info: msdu handler + * + * Return: tx descriptor or NULL + */ +#ifdef QCA_LL_TX_FLOW_GLOBAL_MGMT_POOL +struct ol_tx_desc_t * +ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_msdu_info_t *msdu_info) +{ + if (cdf_unlikely(msdu_info->htt.info.frame_type == htt_pkt_type_mgmt)) + return ol_tx_desc_alloc(pdev, vdev, pdev->mgmt_pool); + else + return ol_tx_desc_alloc(pdev, vdev, vdev->pool); +} +#else +struct ol_tx_desc_t * +ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_msdu_info_t *msdu_info) +{ + return ol_tx_desc_alloc(pdev, vdev, vdev->pool); +} +#endif +#endif + +/* TBD: make this inline in the .h file? */ +struct ol_tx_desc_t *ol_tx_desc_find(struct ol_txrx_pdev_t *pdev, + uint16_t tx_desc_id) +{ + return &pdev->tx_desc.array[tx_desc_id].tx_desc; +} + +#ifndef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_tx_desc_free() - put descriptor to freelist + * @pdev: pdev handle + * @tx_desc: tx descriptor + * + * Return: None + */ +void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + cdf_spin_lock_bh(&pdev->tx_mutex); +#if defined(FEATURE_TSO) + if (tx_desc->pkt_type == ol_tx_frm_tso) { + if (cdf_unlikely(tx_desc->tso_desc == NULL)) + cdf_print("%s %d TSO desc is NULL!\n", + __func__, __LINE__); + else + ol_tso_free_segment(pdev, tx_desc->tso_desc); + } +#endif + ol_tx_desc_reset_pkt_type(tx_desc); + ol_tx_desc_reset_timestamp(tx_desc); + + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + pdev->tx_desc.freelist; + pdev->tx_desc.freelist = (union ol_tx_desc_list_elem_t *)tx_desc; + pdev->tx_desc.num_free++; +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + if ((cdf_atomic_read(&tx_desc->vdev->os_q_paused)) && + (cdf_atomic_read(&tx_desc->vdev->tx_desc_count) < + TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK)) { + /* wakeup netif_queue */ + cdf_atomic_set(&tx_desc->vdev->os_q_paused, 0); + ol_txrx_flow_control_cb(tx_desc->vdev, true); + } +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + cdf_atomic_dec(&tx_desc->vdev->tx_desc_count); + tx_desc->vdev = NULL; +#endif + cdf_spin_unlock_bh(&pdev->tx_mutex); +} + +#else +/** + * ol_tx_desc_free() - put descriptor to pool freelist + * @pdev: pdev handle + * @tx_desc: tx descriptor + * + * Return: None + */ +void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + struct ol_tx_flow_pool_t *pool = tx_desc->pool; + +#if defined(FEATURE_TSO) + if (tx_desc->pkt_type == ol_tx_frm_tso) { + if (cdf_unlikely(tx_desc->tso_desc == NULL)) + cdf_print("%s %d TSO desc is NULL!\n", + __func__, __LINE__); + else + ol_tso_free_segment(pdev, tx_desc->tso_desc); + } +#endif + ol_tx_desc_reset_pkt_type(tx_desc); + ol_tx_desc_reset_timestamp(tx_desc); + + cdf_spin_lock_bh(&pool->flow_pool_lock); + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + pool->freelist; + pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; + pool->avail_desc++; + switch (pool->status) { + case FLOW_POOL_ACTIVE_PAUSED: + if (pool->avail_desc > pool->start_th) { + pdev->pause_cb(pool->member_flow_id, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + pool->status = FLOW_POOL_ACTIVE_UNPAUSED; + } + break; + case FLOW_POOL_INVALID: + if (pool->avail_desc == pool->flow_pool_size) { + cdf_spin_unlock_bh(&pool->flow_pool_lock); + ol_tx_free_invalid_flow_pool(pool); + cdf_print("%s %d pool is INVALID State!!\n", + __func__, __LINE__); + return; + } + break; + case FLOW_POOL_ACTIVE_UNPAUSED: + break; + default: + cdf_print("%s %d pool is INACTIVE State!!\n", + __func__, __LINE__); + break; + }; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + +} +#endif + +extern void +dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc); + +void +dump_pkt(cdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len) +{ + cdf_print("%s: Pkt: VA 0x%p PA 0x%x len %d\n", __func__, + cdf_nbuf_data(nbuf), nbuf_paddr, len); + print_hex_dump(KERN_DEBUG, "Pkt: ", DUMP_PREFIX_NONE, 16, 4, + cdf_nbuf_data(nbuf), len, true); +} + +const uint32_t htt_to_ce_pkt_type[] = { + [htt_pkt_type_raw] = tx_pkt_type_raw, + [htt_pkt_type_native_wifi] = tx_pkt_type_native_wifi, + [htt_pkt_type_ethernet] = tx_pkt_type_802_3, + [htt_pkt_type_mgmt] = tx_pkt_type_mgmt, + [htt_pkt_type_eth2] = tx_pkt_type_eth2, + [htt_pkt_num_types] = 0xffffffff +}; + +struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + cdf_nbuf_t netbuf, + struct ol_txrx_msdu_info_t *msdu_info) +{ + struct ol_tx_desc_t *tx_desc; + unsigned int i; + uint32_t num_frags; + + msdu_info->htt.info.vdev_id = vdev->vdev_id; + msdu_info->htt.action.cksum_offload = cdf_nbuf_get_tx_cksum(netbuf); + switch (cdf_nbuf_get_exemption_type(netbuf)) { + case CDF_NBUF_EXEMPT_NO_EXEMPTION: + case CDF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE: + /* We want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 1; + break; + case CDF_NBUF_EXEMPT_ALWAYS: + /* We don't want to encrypt this frame */ + msdu_info->htt.action.do_encrypt = 0; + break; + default: + cdf_assert(0); + break; + } + + /* allocate the descriptor */ + tx_desc = ol_tx_desc_alloc_wrapper(pdev, vdev, msdu_info); + if (!tx_desc) + return NULL; + + /* initialize the SW tx descriptor */ + tx_desc->netbuf = netbuf; + + if (msdu_info->tso_info.is_tso) { + tx_desc->tso_desc = msdu_info->tso_info.curr_seg; + tx_desc->pkt_type = ol_tx_frm_tso; + TXRX_STATS_MSDU_INCR(pdev, tx.tso.tso_pkts, netbuf); + } else { + 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, + &msdu_info->tso_info, + 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 = cdf_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; +#if defined(HELIUMPLUS_PADDR64) + /* + * Use num_frags - 1, since 1 frag is used to store + * the HTT/HTC descriptor + * Refer to htt_tx_desc_init() + */ + htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_frag_desc, + num_frags - 1); +#else /* ! defined(HELIUMPLUSPADDR64) */ + htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_tx_desc, + num_frags - 1); +#endif /* defined(HELIUMPLUS_PADDR64) */ + + if (msdu_info->tso_info.is_tso) { + htt_tx_desc_fill_tso_info(pdev->htt_pdev, + tx_desc->htt_frag_desc, &msdu_info->tso_info); + TXRX_STATS_TSO_SEG_UPDATE(pdev, + msdu_info->tso_info.curr_seg->seg); + } else { + for (i = 1; i < num_frags; i++) { + cdf_size_t frag_len; + uint32_t frag_paddr; + + frag_len = cdf_nbuf_get_frag_len(netbuf, i); + frag_paddr = cdf_nbuf_get_frag_paddr_lo(netbuf, i); +#if defined(HELIUMPLUS_PADDR64) + htt_tx_desc_frag(pdev->htt_pdev, tx_desc->htt_frag_desc, i - 1, + frag_paddr, frag_len); +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s:%d: htt_fdesc=%p frag_paddr=%u len=%zu\n", + __func__, __LINE__, tx_desc->htt_frag_desc, + frag_paddr, frag_len); + dump_pkt(netbuf, frag_paddr, 64); +#endif /* HELIUMPLUS_DEBUG */ +#else /* ! defined(HELIUMPLUSPADDR64) */ + htt_tx_desc_frag(pdev->htt_pdev, tx_desc->htt_tx_desc, i - 1, + frag_paddr, frag_len); +#endif /* defined(HELIUMPLUS_PADDR64) */ + } + } + +#if defined(HELIUMPLUS_DEBUG) + dump_frag_desc("ol_tx_desc_ll()", tx_desc); +#endif + 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; + cdf_nbuf_t msdus = NULL; + + TAILQ_FOREACH_SAFE(tx_desc, tx_descs, tx_desc_list_elem, tmp) { + cdf_nbuf_t msdu = tx_desc->netbuf; + + cdf_atomic_init(&tx_desc->ref_cnt); /* clear the ref cnt */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* restore original hdr offset */ + OL_TX_RESTORE_HDR(tx_desc, msdu); +#endif + cdf_nbuf_unmap(pdev->osdev, msdu, CDF_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 */ + cdf_nbuf_set_next(msdu, msdus); + msdus = msdu; + } + /* free the netbufs as a batch */ + cdf_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; + + cdf_atomic_init(&tx_desc->ref_cnt); /* clear the ref cnt */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* restore original hdr offset */ + OL_TX_RESTORE_HDR(tx_desc, (tx_desc->netbuf)); +#endif + trace_str = (had_error) ? "OT:C:F:" : "OT:C:S:"; + cdf_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) { + cdf_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 */ + } + cdf_nbuf_unmap(pdev->osdev, tx_desc->netbuf, CDF_DMA_TO_DEVICE); + /* check the frame type to see what kind of special steps are needed */ + if ((tx_desc->pkt_type >= OL_TXRX_MGMT_TYPE_BASE) && + (tx_desc->pkt_type != 0xff)) { + uint32_t frag_desc_paddr_lo = 0; + +#if defined(HELIUMPLUS_PADDR64) + frag_desc_paddr_lo = tx_desc->htt_frag_desc_paddr; + /* 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. + */ +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s %d: Frag Descriptor Reset [%d] to 0x%x\n", + __func__, __LINE__, tx_desc->index, + frag_desc_paddr_lo); +#endif /* HELIUMPLUS_DEBUG */ +#endif /* HELIUMPLUS_PADDR64 */ + htt_tx_desc_frags_table_set(pdev->htt_pdev, + tx_desc->htt_tx_desc, 0, + frag_desc_paddr_lo, 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 */ + cdf_nbuf_free(tx_desc->netbuf); + } else { + /* single regular frame */ + cdf_nbuf_set_next(tx_desc->netbuf, NULL); + cdf_nbuf_tx_free(tx_desc->netbuf, had_error); + } + /* free the tx desc */ + ol_tx_desc_free(pdev, tx_desc); +} + +#if defined(FEATURE_TSO) +/** + * htt_tso_alloc_segment() - function to allocate a TSO segment + * element + * @pdev: HTT pdev + * @tso_seg: This is the output. The TSO segment element. + * + * Allocates a TSO segment element from the free list held in + * the HTT pdev + * + * Return: none + */ +struct cdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev) +{ + struct cdf_tso_seg_elem_t *tso_seg = NULL; + + cdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); + if (pdev->tso_seg_pool.freelist) { + pdev->tso_seg_pool.num_free--; + tso_seg = pdev->tso_seg_pool.freelist; + pdev->tso_seg_pool.freelist = pdev->tso_seg_pool.freelist->next; + } + cdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + if (!tso_seg) + return NULL; + + return tso_seg; +} + +/** + * ol_tso_free_segment() - function to free a TSO segment + * element + * @pdev: HTT pdev + * @tso_seg: The TSO segment element to be freed + * + * Returns a TSO segment element to the free list held in the + * HTT pdev + * + * Return: none + */ + +void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev, + struct cdf_tso_seg_elem_t *tso_seg) +{ + cdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); + tso_seg->next = pdev->tso_seg_pool.freelist; + pdev->tso_seg_pool.freelist = tso_seg; + pdev->tso_seg_pool.num_free++; + cdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); +} +#endif diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h new file mode 100644 index 000000000000..5094c4236cf9 --- /dev/null +++ b/core/dp/txrx/ol_tx_desc.h @@ -0,0 +1,171 @@ +/* + * 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_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 /* cdf_nbuf_t */ +#include /* ol_tx_desc_t */ +#include /*TXRX_ASSERT2 */ + +struct ol_tx_desc_t * +ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev, + struct ol_txrx_vdev_t *vdev, + struct ol_txrx_msdu_info_t *msdu_info); + + +/** + * @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, + cdf_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, + uint16_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 - bool 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 - bool 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 uint16_t +ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) +{ + TXRX_ASSERT2(((union ol_tx_desc_list_elem_t *)tx_desc - + pdev->tx_desc.array) < pdev->tx_desc.pool_size); + return (uint16_t) + ((union ol_tx_desc_list_elem_t *)tx_desc - pdev->tx_desc.array); +} + +/* + * @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); + +#if defined(FEATURE_TSO) +struct cdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev); + +void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev, + struct cdf_tso_seg_elem_t *tso_seg); +#endif + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool); +#else +static inline int ol_tx_free_invalid_flow_pool(void *pool) +{ + return 0; +} +#endif + +#endif /* _OL_TX_DESC__H_ */ diff --git a/core/dp/txrx/ol_tx_queue.c b/core/dp/txrx/ol_tx_queue.c new file mode 100644 index 000000000000..d24ae0bb2f0e --- /dev/null +++ b/core/dp/txrx/ol_tx_queue.c @@ -0,0 +1,428 @@ +/* + * 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 /* cdf_nbuf_t, etc. */ +#include /* cdf_atomic_read, 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 +#include /* ENABLE_TX_QUEUE_LOG */ +#include /* bool */ + +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) + +void ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, uint32_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__); + + cdf_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; + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + + DPTRACE(cdf_dp_trace(NULL, CDF_DP_TRACE_VDEV_PAUSE, + NULL, 0)); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void ol_txrx_vdev_unpause(ol_txrx_vdev_handle vdev, uint32_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__); + + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + if (vdev->ll_pause.paused_reason & reason) { + vdev->ll_pause.paused_reason &= ~reason; + if (!vdev->ll_pause.paused_reason) { + vdev->ll_pause.is_q_paused = false; + vdev->ll_pause.q_unpause_cnt++; + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + ol_tx_vdev_ll_pause_queue_send(vdev); + } else { + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + } + } else { + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + } + DPTRACE(cdf_dp_trace(NULL, CDF_DP_TRACE_VDEV_UNPAUSE, + NULL, 0)); + TX_SCHED_DEBUG_PRINT("Leave %s\n", __func__); +} + +void ol_txrx_vdev_flush(ol_txrx_vdev_handle vdev) +{ + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + cdf_softirq_timer_cancel(&vdev->ll_pause.timer); + vdev->ll_pause.is_q_timer_on = false; + while (vdev->ll_pause.txq.head) { + cdf_nbuf_t next = + cdf_nbuf_next(vdev->ll_pause.txq.head); + cdf_nbuf_set_next(vdev->ll_pause.txq.head, NULL); + cdf_nbuf_unmap(vdev->pdev->osdev, + vdev->ll_pause.txq.head, + CDF_DMA_TO_DEVICE); + cdf_nbuf_tx_free(vdev->ll_pause.txq.head, + NBUF_PKT_ERROR); + vdev->ll_pause.txq.head = next; + } + vdev->ll_pause.txq.tail = NULL; + vdev->ll_pause.txq.depth = 0; + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); +} + +#endif /* defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) */ + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + +/** + * ol_txrx_map_to_netif_reason_type() - map to netif_reason_type + * @reason: reason + * + * Return: netif_reason_type + */ +enum netif_reason_type +ol_txrx_map_to_netif_reason_type(uint32_t reason) +{ + switch (reason) { + case OL_TXQ_PAUSE_REASON_FW: + return WLAN_FW_PAUSE; + case OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED: + return WLAN_PEER_UNAUTHORISED; + case OL_TXQ_PAUSE_REASON_TX_ABORT: + return WLAN_TX_ABORT; + case OL_TXQ_PAUSE_REASON_VDEV_STOP: + return WLAN_VDEV_STOP; + case OL_TXQ_PAUSE_REASON_THERMAL_MITIGATION: + return WLAN_THERMAL_MITIGATION; + default: + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: reason not supported %d\n", + __func__, reason); + return WLAN_REASON_TYPE_MAX; + } +} + +/** + * ol_txrx_vdev_pause() - pause vdev network queues + * @vdev: vdev handle + * @reason: reason + * + * Return: none + */ +void ol_txrx_vdev_pause(ol_txrx_vdev_handle vdev, uint32_t reason) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + enum netif_reason_type netif_reason; + + if (cdf_unlikely((!pdev) || (!pdev->pause_cb))) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid pdev\n", __func__); + return; + } + + netif_reason = ol_txrx_map_to_netif_reason_type(reason); + if (netif_reason == WLAN_REASON_TYPE_MAX) + return; + + pdev->pause_cb(vdev->vdev_id, WLAN_NETIF_TX_DISABLE, netif_reason); +} + +/** + * ol_txrx_vdev_unpause() - unpause vdev network queues + * @vdev: vdev handle + * @reason: reason + * + * Return: none + */ +void ol_txrx_vdev_unpause(ol_txrx_vdev_handle vdev, uint32_t reason) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + enum netif_reason_type netif_reason; + + if (cdf_unlikely((!pdev) || (!pdev->pause_cb))) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid pdev\n", __func__); + return; + } + + netif_reason = ol_txrx_map_to_netif_reason_type(reason); + if (netif_reason == WLAN_REASON_TYPE_MAX) + return; + + pdev->pause_cb(vdev->vdev_id, WLAN_WAKE_ALL_NETIF_QUEUE, + netif_reason); + +} + +/** + * ol_txrx_pdev_pause() - pause network queues for each vdev + * @pdev: pdev handle + * @reason: reason + * + * Return: none + */ +void ol_txrx_pdev_pause(struct ol_txrx_pdev_t *pdev, uint32_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() - unpause network queues for each vdev + * @pdev: pdev handle + * @reason: reason + * + * Return: none + */ +void ol_txrx_pdev_unpause(struct ol_txrx_pdev_t *pdev, uint32_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); + } + +} +#endif + +/*--- LL tx throttle queue code --------------------------------------------*/ +#if defined(QCA_SUPPORT_TX_THROTTLE) +uint8_t ol_tx_pdev_is_target_empty(void) +{ + /* TM TODO */ + return 1; +} + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_txrx_thermal_pause() - pause due to thermal mitigation + * @pdev: pdev handle + * + * Return: none + */ +static inline +void ol_txrx_thermal_pause(struct ol_txrx_pdev_t *pdev) +{ + ol_txrx_pdev_pause(pdev, OL_TXQ_PAUSE_REASON_THERMAL_MITIGATION); + return; +} +/** + * ol_txrx_thermal_unpause() - unpause due to thermal mitigation + * @pdev: pdev handle + * + * Return: none + */ +static inline +void ol_txrx_thermal_unpause(struct ol_txrx_pdev_t *pdev) +{ + ol_txrx_pdev_unpause(pdev, OL_TXQ_PAUSE_REASON_THERMAL_MITIGATION); + return; +} +#else +/** + * ol_txrx_thermal_pause() - pause due to thermal mitigation + * @pdev: pdev handle + * + * Return: none + */ +static inline +void ol_txrx_thermal_pause(struct ol_txrx_pdev_t *pdev) +{ + return; +} + +/** + * ol_txrx_thermal_unpause() - unpause due to thermal mitigation + * @pdev: pdev handle + * + * Return: none + */ +static inline +void ol_txrx_thermal_unpause(struct ol_txrx_pdev_t *pdev) +{ + ol_tx_pdev_ll_pause_queue_send_all(pdev); + return; +} +#endif + +void ol_tx_pdev_throttle_phase_timer(void *context) +{ + struct ol_txrx_pdev_t *pdev = (struct ol_txrx_pdev_t *)context; + int ms; + enum throttle_level cur_level; + enum 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) { + /* Traffic is stopped */ + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "throttle phase --> OFF\n"); + ol_txrx_thermal_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); + cdf_softirq_timer_start(&pdev->tx_throttle. + phase_timer, ms); + } + } else { + /* Traffic can go */ + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "throttle phase --> ON\n"); + ol_txrx_thermal_unpause(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); + cdf_softirq_timer_start(&pdev->tx_throttle.phase_timer, + ms); + } + } +} + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +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 = (enum throttle_level) level; + + /* 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]; + + cdf_softirq_timer_cancel(&pdev->tx_throttle.phase_timer); + + if (level != THROTTLE_LEVEL_0) + cdf_softirq_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 uint8_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) +{ + uint32_t throttle_period; + + pdev->tx_throttle.current_throttle_level = THROTTLE_LEVEL_0; + pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + cdf_spinlock_init(&pdev->tx_throttle.mutex); + + throttle_period = ol_cfg_throttle_period_ms(pdev->ctrl_pdev); + + ol_tx_throttle_init_period(pdev, throttle_period); + + cdf_softirq_timer_init(pdev->osdev, + &pdev->tx_throttle.phase_timer, + ol_tx_pdev_throttle_phase_timer, pdev, + CDF_TIMER_TYPE_SW); + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + cdf_softirq_timer_init(pdev->osdev, + &pdev->tx_throttle.tx_timer, + ol_tx_pdev_throttle_tx_timer, pdev, + CDF_TIMER_TYPE_SW); +#endif + + pdev->tx_throttle.tx_threshold = THROTTLE_TX_THRESHOLD; +} +#endif /* QCA_SUPPORT_TX_THROTTLE */ +/*--- End of LL tx throttle queue code ---------------------------------------*/ diff --git a/core/dp/txrx/ol_tx_queue.h b/core/dp/txrx/ol_tx_queue.h new file mode 100644 index 000000000000..be809134a1c0 --- /dev/null +++ b/core/dp/txrx/ol_tx_queue.h @@ -0,0 +1,92 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* bool */ + +/*--- function prototypes for optional queue log feature --------------------*/ +#if defined(ENABLE_TX_QUEUE_LOG) + +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 */ + +#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 */ + +void +ol_tx_queue_log_sched(struct ol_txrx_pdev_t *pdev, + int credit, + int *num_active_tids, + uint32_t **active_bitmap, uint8_t **data); + +#define OL_TX_QUEUE_LOG_SCHED( \ + pdev, credit, num_active_tids, active_bitmap, data) + +#define ol_tx_queues_display(pdev) /* no-op */ + +#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 +#endif /* _OL_TX_QUEUE__H_ */ diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c new file mode 100644 index 000000000000..b4ba774bd2c6 --- /dev/null +++ b/core/dp/txrx/ol_tx_send.c @@ -0,0 +1,969 @@ +/* + * 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 /* cdf_atomic_inc, etc. */ +#include /* cdf_os_spinlock */ +#include /* cdf_system_ticks, etc. */ +#include /* cdf_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 +#endif +#include /* OL_TX_DESC_NO_REFS, etc. */ +#include +#include /* ol_tx_reinject */ + +#include /* ol_cfg_is_high_latency */ +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP +#include /* OL_TX_RESTORE_HDR, etc */ +#endif + +#ifdef TX_CREDIT_RECLAIM_SUPPORT + +#define OL_TX_CREDIT_RECLAIM(pdev) \ + do { \ + if (cdf_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(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) \ + cdf_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) \ + cdf_atomic_add(-1 * delta, &pdev->target_tx_credit) +#define OL_TX_TARGET_CREDIT_INCR_INT(pdev, delta) \ + cdf_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_LEGACY_TX_FLOW_CONTROL +#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 (cdf_atomic_read(&vdev->os_q_paused) && \ + (vdev->tx_fl_hwm != 0)) { \ + cdf_spin_lock(&pdev->tx_mutex); \ + if (pdev->tx_desc.num_free > \ + vdev->tx_fl_hwm) { \ + cdf_atomic_set(&vdev->os_q_paused, 0); \ + cdf_spin_unlock(&pdev->tx_mutex); \ + ol_txrx_flow_control_cb(vdev, true);\ + } \ + else { \ + cdf_spin_unlock(&pdev->tx_mutex); \ + } \ + } \ + } \ + } while (0) +#else +#define OL_TX_FLOW_CT_UNPAUSE_OS_Q(pdev) +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +static inline uint16_t +ol_tx_send_base(struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc, cdf_nbuf_t msdu) +{ + int msdu_credit_consumed; + + TX_CREDIT_DEBUG_PRINT("TX %d bytes\n", cdf_nbuf_len(msdu)); + TX_CREDIT_DEBUG_PRINT(" Decrease credit %d - 1 = %d, len:%d.\n", + cdf_atomic_read(&pdev->target_tx_credit), + cdf_atomic_read(&pdev->target_tx_credit) - 1, + cdf_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, cdf_nbuf_t msdu) +{ + int msdu_credit_consumed; + uint16_t id; + int failed; + + msdu_credit_consumed = ol_tx_send_base(pdev, tx_desc, msdu); + id = ol_tx_desc_id(pdev, tx_desc); + NBUF_UPDATE_TX_PKT_COUNT(msdu, NBUF_TX_PKT_TXRX); + DPTRACE(cdf_dp_trace(msdu, CDF_DP_TRACE_TXRX_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(msdu)), + sizeof(cdf_nbuf_data(msdu)))); + failed = htt_tx_send_std(pdev->htt_pdev, msdu, id); + if (cdf_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, + cdf_nbuf_t head_msdu, int num_msdus) +{ + cdf_nbuf_t rejected; + OL_TX_CREDIT_RECLAIM(pdev); + + rejected = htt_tx_send_batch(pdev->htt_pdev, head_msdu, num_msdus); + while (cdf_unlikely(rejected)) { + struct ol_tx_desc_t *tx_desc; + uint16_t *msdu_id_storage; + cdf_nbuf_t next; + + next = cdf_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, + cdf_nbuf_t msdu, enum htt_pkt_type pkt_type) +{ + int msdu_credit_consumed; + uint16_t id; + int failed; + + msdu_credit_consumed = ol_tx_send_base(pdev, tx_desc, msdu); + id = ol_tx_desc_id(pdev, tx_desc); + NBUF_UPDATE_TX_PKT_COUNT(msdu, NBUF_TX_PKT_TXRX); + 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, cdf_nbuf_t msdu, uint16_t msdu_id) +{ + struct ol_tx_desc_t *tx_desc; + + tx_desc = ol_tx_desc_find(pdev, msdu_id); + cdf_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, cdf_nbuf_t msdu, uint16_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, + cdf_nbuf_t msdu, uint16_t msdu_id) +{ + struct ol_txrx_pdev_t *pdev = txrx_pdev; + ol_tx_download_done_base(pdev, status, msdu, msdu_id); +} + +void +ol_tx_download_done_hl_free(void *txrx_pdev, + A_STATUS status, cdf_nbuf_t msdu, uint16_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); + cdf_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)) { + cdf_atomic_add(1, &pdev->tx_queue.rsrc_cnt); + ol_tx_desc_frame_free_nonstd(pdev, tx_desc, status != A_OK); + } +} + +void ol_tx_target_credit_init(struct ol_txrx_pdev_t *pdev, int credit_delta) +{ + cdf_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", + cdf_atomic_read(&pdev->target_tx_credit), + credit_delta, + cdf_atomic_read(&pdev->target_tx_credit) + + credit_delta); + cdf_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, + uint16_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) \ + TAILQ_INSERT_TAIL(&(_tx_descs), (_tx_desc), tx_desc_list_elem) +#ifndef ATH_11AC_TXCOMPACT +#define ol_tx_msdu_complete_single(_pdev, _tx_desc, _netbuf,\ + _lcl_freelist, _tx_desc_last) \ + do { \ + cdf_atomic_init(&(_tx_desc)->ref_cnt); \ + /* restore orginal hdr offset */ \ + OL_TX_RESTORE_HDR((_tx_desc), (_netbuf)); \ + cdf_nbuf_unmap((_pdev)->osdev, (_netbuf), CDF_DMA_TO_DEVICE); \ + cdf_nbuf_free((_netbuf)); \ + ((union ol_tx_desc_list_elem_t *)(_tx_desc))->next = \ + (_lcl_freelist); \ + if (cdf_unlikely(!lcl_freelist)) { \ + (_tx_desc_last) = (union ol_tx_desc_list_elem_t *)\ + (_tx_desc); \ + } \ + (_lcl_freelist) = (union 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 { \ + /* restore orginal hdr offset */ \ + OL_TX_RESTORE_HDR((_tx_desc), (_netbuf)); \ + cdf_nbuf_unmap((_pdev)->osdev, (_netbuf), CDF_DMA_TO_DEVICE); \ + cdf_nbuf_free((_netbuf)); \ + ((union ol_tx_desc_list_elem_t *)(_tx_desc))->next = \ + (_lcl_freelist); \ + if (cdf_unlikely(!lcl_freelist)) { \ + (_tx_desc_last) = (union ol_tx_desc_list_elem_t *)\ + (_tx_desc); \ + } \ + (_lcl_freelist) = (union 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 (cdf_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 (cdf_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 (cdf_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); + + /* 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; + uint16_t *desc_ids = (uint16_t *) tx_desc_id_iterator; + uint16_t tx_desc_id; + struct ol_tx_desc_t *tx_desc; + char *trace_str; + + uint32_t byte_cnt = 0; + union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + cdf_nbuf_t netbuf; + + union ol_tx_desc_list_elem_t *lcl_freelist = NULL; + union 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; + + cdf_nbuf_trace_update(netbuf, trace_str); + /* Per SDU update of byte count */ + byte_cnt += cdf_nbuf_len(netbuf); + if (OL_TX_DESC_NO_REFS(tx_desc)) { + ol_tx_statistics( + pdev->ctrl_pdev, + HTT_TX_DESC_VDEV_ID_GET(*((uint32_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); + } + NBUF_UPDATE_TX_PKT_COUNT(netbuf, NBUF_TX_PKT_FREE); +#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) { + cdf_spin_lock(&pdev->tx_mutex); + tx_desc_last->next = pdev->tx_desc.freelist; + pdev->tx_desc.freelist = lcl_freelist; + pdev->tx_desc.num_free += (uint16_t) num_msdus; + cdf_spin_unlock(&pdev->tx_mutex); + } else { + ol_tx_desc_frame_list_free(pdev, &tx_descs, + status != htt_tx_status_ok); + } + + 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); +} + +/* + * 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, uint16_t tx_desc_id) +{ + struct ol_tx_desc_t *tx_desc; + union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + cdf_nbuf_t netbuf; + + tx_desc = &td_array[tx_desc_id].tx_desc; + tx_desc->status = status; + netbuf = tx_desc->netbuf; + + NBUF_UPDATE_TX_PKT_COUNT(netbuf, NBUF_TX_PKT_FREE); + /* Do one shot statistics */ + TXRX_STATS_UPDATE_TX_STATS(pdev, status, 1, cdf_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", + cdf_atomic_read(&pdev->target_tx_credit), + 1, cdf_atomic_read(&pdev->target_tx_credit) + 1); + + + cdf_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) +{ + uint16_t vdev_id, i; + struct ol_txrx_vdev_t *vdev; + uint16_t *desc_ids = (uint16_t *) tx_desc_id_iterator; + uint16_t tx_desc_id; + struct ol_tx_desc_t *tx_desc; + union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; + union ol_tx_desc_list_elem_t *lcl_freelist = NULL; + union ol_tx_desc_list_elem_t *tx_desc_last = NULL; + cdf_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(*((uint32_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 (cdf_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) { + cdf_spin_lock(&pdev->tx_mutex); + tx_desc_last->next = pdev->tx_desc.freelist; + pdev->tx_desc.freelist = lcl_freelist; + cdf_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", + cdf_atomic_read(&pdev->target_tx_credit), + num_msdus, + cdf_atomic_read(&pdev->target_tx_credit) + + num_msdus); + + 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, uint32_t interval) +{ + pdev->tx_delay.avg_period_ticks = cdf_system_msecs_to_ticks(interval); +} + +void +ol_tx_packet_count(ol_txrx_pdev_handle pdev, + uint16_t *out_packet_count, + uint16_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; +} + +uint32_t ol_tx_delay_avg(uint64_t sum, uint32_t num) +{ + uint32_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 = (uint32_t) sum; + num >>= shift; + return (sum32 + (num >> 1)) / num; /* round to nearest */ +} + +void +ol_tx_delay(ol_txrx_pdev_handle pdev, + uint32_t *queue_delay_microsec, + uint32_t *tx_delay_microsec, int category) +{ + int index; + uint32_t avg_delay_ticks; + struct ol_tx_delay_data *data; + + cdf_assert(category >= 0 && category < QCA_TX_DELAY_NUM_CATEGORIES); + + cdf_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 = + cdf_system_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 = + cdf_system_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; + } + + cdf_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +void +ol_tx_delay_hist(ol_txrx_pdev_handle pdev, + uint16_t *report_bin_values, int category) +{ + int index, i, j; + struct ol_tx_delay_data *data; + + cdf_assert(category >= 0 && category < QCA_TX_DELAY_NUM_CATEGORIES); + + cdf_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++) { + uint16_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 */ + + cdf_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +#ifdef QCA_COMPUTE_TX_DELAY_PER_TID +static inline uint8_t *ol_tx_dest_addr_find(struct ol_txrx_pdev_t *pdev, + cdf_nbuf_t tx_nbuf) +{ + uint8_t *hdr_ptr; + void *datap = cdf_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 { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid standard frame type: %d", + pdev->frame_format); + cdf_assert(0); + hdr_ptr = NULL; + } + return hdr_ptr; +} + +static uint8_t +ol_tx_delay_tid_from_l3_hdr(struct ol_txrx_pdev_t *pdev, + cdf_nbuf_t msdu, struct ol_tx_desc_t *tx_desc) +{ + uint16_t ethertype; + uint8_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 *)cdf_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 *) + (cdf_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 *)(cdf_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 = cdf_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, uint16_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; + uint8_t tid; + + cdf_nbuf_t msdu = tx_desc->netbuf; + tid = cdf_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 -EINVAL; + } + } + return tid; +#else + return 0; +#endif +} + +static inline int +ol_tx_delay_hist_bin(struct ol_txrx_pdev_t *pdev, uint32_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, + uint16_t *desc_ids, int num_msdus) +{ + int i, index, cat; + uint32_t now_ticks = cdf_system_ticks(); + uint32_t tx_delay_transmit_ticks, tx_delay_queue_ticks; + uint32_t avg_time_ticks; + struct ol_tx_delay_data *data; + + cdf_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 */ + cdf_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++) { + uint16_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; + cdf_mem_zero(&pdev->tx_delay.cats[cat].copies[index], + sizeof(pdev->tx_delay.cats[cat].copies[index])); + } + + cdf_spin_unlock_bh(&pdev->tx_delay.mutex); +} + +#endif /* QCA_COMPUTE_TX_DELAY */ diff --git a/core/dp/txrx/ol_tx_send.h b/core/dp/txrx/ol_tx_send.h new file mode 100644 index 000000000000..db4881202350 --- /dev/null +++ b/core/dp/txrx/ol_tx_send.h @@ -0,0 +1,86 @@ +/* + * 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_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 /* cdf_nbuf_t */ +#include /* ol_tx_send_t */ + +/** + * @flush the ol tx when surprise remove. + * + */ +void ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev); + +/** + * @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, cdf_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, + cdf_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, + cdf_nbuf_t msdu, enum htt_pkt_type pkt_type); +#endif /* _OL_TX_SEND__H_ */ diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c new file mode 100644 index 000000000000..566a5ced1607 --- /dev/null +++ b/core/dp/txrx/ol_txrx.c @@ -0,0 +1,3173 @@ +/* + * 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 /* uint32_t, etc. */ +#include /* cdf_mem_malloc,free */ +#include /* cdf_device_t, cdf_print */ +#include /* cdf_spinlock */ +#include /* cdf_atomic_read */ + +/* Required for WLAN_FEATURE_FASTPATH */ +#include +/* 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_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 +#include "wma.h" + + + +/*=== function definitions ===*/ + +#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, + uint8_t *peer_addr, uint8_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; + cdf_atomic_dec(&peer->ref_cnt); + return peer; +} + +CDF_STATUS ol_txrx_get_vdevid(struct ol_txrx_peer_t *peer, uint8_t *vdev_id) +{ + if (!peer) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "peer argument is null!!"); + return CDF_STATUS_E_FAILURE; + } + + *vdev_id = peer->vdev->vdev_id; + return CDF_STATUS_SUCCESS; +} + +void *ol_txrx_get_vdev_by_sta_id(uint8_t sta_id) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid sta id passed"); + return NULL; + } + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "PDEV not found for sta_id [%d]", sta_id); + return NULL; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + if (!peer) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "PEER [%d] not found", sta_id); + return NULL; + } + + return peer->vdev; +} + +ol_txrx_peer_handle ol_txrx_find_peer_by_addr(ol_txrx_pdev_handle pdev, + uint8_t *peer_addr, + uint8_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; + cdf_atomic_dec(&peer->ref_cnt); + return peer; +} + +uint16_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, + uint8_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; + } + + cdf_spin_lock_bh(&pdev->local_peer_ids.lock); + peer = pdev->local_peer_ids.map[local_peer_id]; + cdf_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; + + cdf_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; + + cdf_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; + } + cdf_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 */ + cdf_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; + cdf_spin_unlock_bh(&pdev->local_peer_ids.lock); +} + +static void ol_txrx_local_peer_id_cleanup(struct ol_txrx_pdev_t *pdev) +{ + cdf_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 WLAN_FEATURE_FASTPATH +/** + * setup_fastpath_ce_handles() Update pdev with ce_handle for fastpath use. + * + * @osc: pointer to HIF context + * @pdev: pointer to ol pdev + * + * Return: void + */ +static inline void +setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev) +{ + /* + * Before the HTT attach, set up the CE handles + * CE handles are (struct CE_state *) + * This is only required in the fast path + */ + pdev->ce_tx_hdl = (struct CE_handle *) + osc->ce_id_to_state[CE_HTT_H2T_MSG]; + +} + +/** + * init_txdesc_id() initialize Tx desc with id + * + * @pdev: handle OL pdev + * @desc_num: Tx descriptor number + * + * Return: void + */ +static inline void +init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num) +{ + pdev->tx_desc.array[desc_num].tx_desc.id = desc_num; + cdf_atomic_init(&pdev->tx_desc.array[desc_num].tx_desc.ref_cnt); +} +#else /* not WLAN_FEATURE_FASTPATH */ +static inline void +setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev) +{ +} +static inline void +init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num) +{ +} +#endif /* WLAN_FEATURE_FASTPATH */ + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_tx_set_desc_global_pool_size() - set global pool size + * @num_msdu_desc: total number of descriptors + * + * Return: none + */ +inline +void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + cdf_print("%s: pdev is NULL\n", __func__); + return; + } + pdev->num_msdu_desc = num_msdu_desc + TX_FLOW_MGMT_POOL_SIZE; + return; +} + +/** + * ol_tx_get_desc_global_pool_size() - get global pool size + * @pdev: pdev handle + * + * Return: global pool size + */ +static inline +uint32_t ol_tx_get_desc_global_pool_size(struct ol_txrx_pdev_t *pdev) +{ + return pdev->num_msdu_desc; +} +#else +/** + * ol_tx_get_desc_global_pool_size() - get global pool size + * @pdev: pdev handle + * + * Return: global pool size + */ +static inline +uint32_t ol_tx_get_desc_global_pool_size(struct ol_txrx_pdev_t *pdev) +{ + return ol_cfg_target_tx_credit(pdev->ctrl_pdev); +} +#endif + +/** + * ol_txrx_pdev_alloc() - allocate txrx pdev + * @ctrl_pdev: cfg pdev + * @htc_pdev: HTC pdev + * @osdev: os dev + * + * Return: txrx pdev handle + * NULL for failure + */ +ol_txrx_pdev_handle +ol_txrx_pdev_alloc(ol_pdev_handle ctrl_pdev, + HTC_HANDLE htc_pdev, cdf_device_t osdev) +{ + struct ol_txrx_pdev_t *pdev; + int i; + + pdev = cdf_mem_malloc(sizeof(*pdev)); + if (!pdev) + goto fail0; + cdf_mem_zero(pdev, sizeof(*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; + + pdev->htt_pdev = + htt_pdev_alloc(pdev, ctrl_pdev, htc_pdev, osdev); + if (!pdev->htt_pdev) + goto fail2; + + return pdev; + +fail2: + ol_txrx_peer_find_detach(pdev); + +fail1: + cdf_mem_free(pdev); + +fail0: + return NULL; +} + +/** + * ol_txrx_pdev_attach() - attach txrx pdev + * @pdev: txrx pdev + * + * Return: 0 for success + */ +int +ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) +{ + int i; + int ret = 0; + uint16_t desc_pool_size; + struct ol_softc *osc = cds_get_context(CDF_MODULE_ID_HIF); + + if (!osc) { + ret = -EINVAL; + goto fail0; + } + + /* + * 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. + */ + + /* initialize the counter of the target's tx buffer availability */ + cdf_atomic_init(&pdev->target_tx_credit); + cdf_atomic_init(&pdev->orig_target_tx_credit); + /* + * LL - initialize the target credit outselves. + * HL - wait for a HTT target credit initialization during htt_attach. + */ + + cdf_atomic_add(ol_cfg_target_tx_credit(pdev->ctrl_pdev), + &pdev->target_tx_credit); + + desc_pool_size = ol_tx_get_desc_global_pool_size(pdev); + + setup_fastpath_ce_handles(osc, pdev); + + ret = htt_attach(pdev->htt_pdev, desc_pool_size); + if (ret) + goto fail0; + + /* Update CE's pkt download length */ + ce_pkt_dl_len_set((void *)osc, htt_pkt_dl_len_get(pdev->htt_pdev)); + + /* Attach micro controller data path offload resource */ + if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) + if (htt_ipa_uc_attach(pdev->htt_pdev)) + goto fail1; + + pdev->tx_desc.array = + cdf_mem_malloc(desc_pool_size * + sizeof(union ol_tx_desc_list_elem_t)); + if (!pdev->tx_desc.array) + goto fail2; + cdf_mem_set(pdev->tx_desc.array, + desc_pool_size * sizeof(union ol_tx_desc_list_elem_t), 0); + + /* + * 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; + for (i = 0; i < desc_pool_size; i++) { + void *htt_tx_desc; +#if defined(HELIUMPLUS_PADDR64) + void *htt_frag_desc; + uint32_t frag_paddr_lo; +#endif /* defined(HELIUMPLUS_PADDR64) */ + uint32_t paddr_lo; + + htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo); + if (!htt_tx_desc) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, + "%s: failed to alloc HTT tx desc (%d of %d)", + __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 fail3; + } + 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; + +#if defined(HELIUMPLUS_PADDR64) + htt_frag_desc = htt_tx_frag_alloc(pdev->htt_pdev, i, + &frag_paddr_lo); + if (!htt_frag_desc) { + cdf_print("%s: failed to alloc HTT frag dsc (%d/%d)\n", + __func__, i, desc_pool_size); + /* Is there a leak here, is this handling correct? */ + goto fail3; + } + /* Initialize the first 6 words (TSO flags) + of the frag descriptor */ + memset(htt_frag_desc, 0, 6*sizeof(uint32_t)); + + pdev->tx_desc.array[i].tx_desc.htt_frag_desc = htt_frag_desc; +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s:%d %d %p\n", __func__, __LINE__, + i, pdev->tx_desc.array[i].tx_desc.htt_frag_desc); +#endif /* HELIUMPLUS_DEBUG */ + pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr = + frag_paddr_lo; +#if defined(HELIUMPLUS_DEBUG) + cdf_print("%s:%d - %d FRAG VA 0x%p FRAG PA 0x%x\n", + __func__, __LINE__, i, + pdev->tx_desc.array[i].tx_desc.htt_frag_desc, + pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr); +#endif /* HELIUMPLUS_DEBUG */ +#endif /* defined(HELIUMPLUS_PADDR64) */ + + pdev->tx_desc.array[i].tx_desc.index = i; +#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 + init_txdesc_id(pdev, 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__, + (uint32_t *) pdev->tx_desc.freelist, + (uint32_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) { + if (ol_cfg_is_ce_classify_enabled(pdev->ctrl_pdev)) + pdev->htt_pkt_type = htt_pkt_type_eth2; + else + pdev->htt_pkt_type = htt_pkt_type_ethernet; + } else { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s Invalid standard frame type: %d", + __func__, pdev->frame_format); + goto fail4; + } + + /* 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(pdev->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: + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid std frame type; [en/de]cap: f:%x t:%x r:%x", + pdev->frame_format, + pdev->target_tx_tran_caps, pdev->target_rx_tran_caps); + goto fail4; + } +#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 { +#define TRACESTR01 "invalid config: if rx PN check is on the host,"\ +"rx->tx forwarding check needs to also be on the host" + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_TRACE_LEVEL_ERROR, + "%s: %s", __func__, TRACESTR01); +#undef TRACESTR01 + goto fail4; + } + } 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 */ + cdf_spinlock_init(&pdev->tx_mutex); + cdf_spinlock_init(&pdev->peer_ref_mutex); + cdf_spinlock_init(&pdev->rx.mutex); + cdf_spinlock_init(&pdev->last_real_peer_mutex); + OL_TXRX_PEER_STATS_MUTEX_INIT(pdev); + + if (OL_RX_REORDER_TRACE_ATTACH(pdev) != A_OK) + goto fail5; + + if (OL_RX_PN_TRACE_ATTACH(pdev) != A_OK) + goto fail6; + +#ifdef PERE_IP_HDR_ALIGNMENT_WAR + pdev->host_80211_enable = ol_scn_host_80211_enable_get(pdev->ctrl_pdev); +#endif + + /* + * WDI event attach + */ + wdi_event_attach(pdev); + + /* + * Initialize rx PN check characteristics for different security types. + */ + cdf_mem_set(&pdev->rx_pn[0], sizeof(pdev->rx_pn), 0); + + /* 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); + + pdev->cfg.host_addba = ol_cfg_host_addba(pdev->ctrl_pdev); + +#ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI +#define OL_TXRX_RSSI_UPDATE_SHIFT_DEFAULT 3 + +/* #if 1 -- TODO: clean this up */ +#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(pdev->ctrl_pdev); + +#ifdef QCA_COMPUTE_TX_DELAY + cdf_mem_zero(&pdev->tx_delay, sizeof(pdev->tx_delay)); + cdf_spinlock_init(&pdev->tx_delay.mutex); + + /* initialize compute interval with 5 seconds (ESE default) */ + pdev->tx_delay.avg_period_ticks = cdf_system_msecs_to_ticks(5000); + { + uint32_t bin_width_1000ticks; + bin_width_1000ticks = + cdf_system_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 uint32_t size. This should + * result in a relatively large multiplier value, which + * minimizes 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-res, + * 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 + + +#if defined(FEATURE_TSO) + ol_tso_seg_list_init(pdev, desc_pool_size); +#endif + + ol_tx_register_flow_control(pdev); + + return 0; /* success */ + +fail6: + OL_RX_REORDER_TRACE_DETACH(pdev); + +fail5: + cdf_spinlock_destroy(&pdev->tx_mutex); + cdf_spinlock_destroy(&pdev->peer_ref_mutex); + cdf_spinlock_destroy(&pdev->rx.mutex); + cdf_spinlock_destroy(&pdev->last_real_peer_mutex); + OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev); + +fail4: + 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); + +fail3: + cdf_mem_free(pdev->tx_desc.array); + +fail2: + if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) + htt_ipa_uc_detach(pdev->htt_pdev); +fail1: + htt_detach(pdev->htt_pdev); + +fail0: + return ret; /* 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; + /*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); + +#ifdef QCA_SUPPORT_TX_THROTTLE + /* Thermal Mitigation */ + cdf_softirq_timer_cancel(&pdev->tx_throttle.phase_timer); + cdf_softirq_timer_free(&pdev->tx_throttle.phase_timer); +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + cdf_softirq_timer_cancel(&pdev->tx_throttle.tx_timer); + cdf_softirq_timer_free(&pdev->tx_throttle.tx_timer); +#endif +#endif + + ol_tx_deregister_flow_control(pdev); + + 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 msg + * 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. + * 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 (cdf_atomic_read(&pdev->tx_desc.array[i].tx_desc.ref_cnt)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + "Warning: freeing tx frame (no compltn)\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); + } + + cdf_mem_free(pdev->tx_desc.array); + + /* Detach micro controller data path offload resource */ + if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) + htt_ipa_uc_detach(pdev->htt_pdev); + + htt_detach(pdev->htt_pdev); + htt_pdev_free(pdev->htt_pdev); + + ol_txrx_peer_find_detach(pdev); + + cdf_spinlock_destroy(&pdev->tx_mutex); + cdf_spinlock_destroy(&pdev->peer_ref_mutex); + cdf_spinlock_destroy(&pdev->last_real_peer_mutex); + cdf_spinlock_destroy(&pdev->rx.mutex); +#ifdef QCA_SUPPORT_TX_THROTTLE + /* Thermal Mitigation */ + cdf_spinlock_destroy(&pdev->tx_throttle.mutex); +#endif + OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev); + + OL_RX_REORDER_TRACE_DETACH(pdev); + OL_RX_PN_TRACE_DETACH(pdev); + /* + * WDI event detach + */ + wdi_event_detach(pdev); + ol_txrx_local_peer_id_cleanup(pdev); + +#ifdef QCA_COMPUTE_TX_DELAY + cdf_spinlock_destroy(&pdev->tx_delay.mutex); +#endif +} + +ol_txrx_vdev_handle +ol_txrx_vdev_attach(ol_txrx_pdev_handle pdev, + uint8_t *vdev_mac_addr, + uint8_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 = cdf_mem_malloc(sizeof(*vdev)); + if (!vdev) + return NULL; /* failure */ + + /* store provided params */ + vdev->pdev = pdev; + vdev->vdev_id = vdev_id; + vdev->opmode = op_mode; + + vdev->delete.pending = 0; + vdev->safemode = 0; + vdev->drop_unenc = 1; + vdev->num_filters = 0; +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + cdf_atomic_init(&vdev->tx_desc_count); +#endif + + cdf_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; + +#ifdef QCA_IBSS_SUPPORT + vdev->ibss_peer_num = 0; + vdev->ibss_peer_heart_beat_timer = 0; +#endif + + cdf_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; + cdf_softirq_timer_init(pdev->osdev, + &vdev->ll_pause.timer, + ol_tx_vdev_ll_pause_queue_send, vdev, + CDF_TIMER_TYPE_SW); + cdf_atomic_init(&vdev->os_q_paused); + cdf_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; + cdf_spinlock_init(&vdev->flow_control_lock); + vdev->osif_flow_control_cb = NULL; + vdev->osif_fc_ctx = 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; + txrx_ops->tx.std = vdev->tx = OL_TX_LL; + txrx_ops->tx.non_std = ol_tx_non_std_ll; +} + +void ol_txrx_set_curchan(ol_txrx_pdev_handle pdev, uint32_t chan_mhz) +{ + return; +} + +void ol_txrx_set_safemode(ol_txrx_vdev_handle vdev, uint32_t val) +{ + vdev->safemode = val; +} + +void +ol_txrx_set_privacy_filters(ol_txrx_vdev_handle vdev, + void *filters, uint32_t num) +{ + cdf_mem_copy(vdev->privacy_filters, filters, + num * sizeof(struct privacy_exemption)); + vdev->num_filters = num; +} + +void ol_txrx_set_drop_unenc(ol_txrx_vdev_handle vdev, uint32_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); + + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + cdf_softirq_timer_cancel(&vdev->ll_pause.timer); + cdf_softirq_timer_free(&vdev->ll_pause.timer); + vdev->ll_pause.is_q_timer_on = false; + while (vdev->ll_pause.txq.head) { + cdf_nbuf_t next = cdf_nbuf_next(vdev->ll_pause.txq.head); + cdf_nbuf_set_next(vdev->ll_pause.txq.head, NULL); + cdf_nbuf_unmap(pdev->osdev, vdev->ll_pause.txq.head, + CDF_DMA_TO_DEVICE); + cdf_nbuf_tx_free(vdev->ll_pause.txq.head, NBUF_PKT_ERROR); + vdev->ll_pause.txq.head = next; + } + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + cdf_spinlock_destroy(&vdev->ll_pause.mutex); + + cdf_spin_lock_bh(&vdev->flow_control_lock); + vdev->osif_flow_control_cb = NULL; + vdev->osif_fc_ctx = NULL; + cdf_spin_unlock_bh(&vdev->flow_control_lock); + cdf_spinlock_destroy(&vdev->flow_control_lock); + + /* 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. + */ + cdf_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; + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + return; + } + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: deleting vdev obj %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. + */ + cdf_mem_free(vdev); + if (callback) + callback(context); +} + +/** + * ol_txrx_flush_rx_frames() - flush cached rx frames + * @peer: peer + * @drop: set flag to drop frames + * + * Return: None + */ +void ol_txrx_flush_rx_frames(struct ol_txrx_peer_t *peer, + bool drop) +{ + struct ol_rx_cached_buf *cache_buf; + CDF_STATUS ret; + ol_rx_callback_fp data_rx = NULL; + void *cds_ctx = cds_get_global_context(); + + if (cdf_atomic_inc_return(&peer->flush_in_progress) > 1) { + cdf_atomic_dec(&peer->flush_in_progress); + return; + } + + cdf_assert(cds_ctx); + cdf_spin_lock_bh(&peer->peer_info_lock); + if (peer->state >= ol_txrx_peer_state_conn) + data_rx = peer->osif_rx; + else + drop = true; + cdf_spin_unlock_bh(&peer->peer_info_lock); + + cdf_spin_lock_bh(&peer->bufq_lock); + cache_buf = list_entry((&peer->cached_bufq)->next, + typeof(*cache_buf), list); + while (!list_empty(&peer->cached_bufq)) { + list_del(&cache_buf->list); + cdf_spin_unlock_bh(&peer->bufq_lock); + if (drop) { + cdf_nbuf_free(cache_buf->buf); + } else { + /* Flush the cached frames to HDD */ + ret = data_rx(cds_ctx, cache_buf->buf, peer->local_id); + if (ret != CDF_STATUS_SUCCESS) + cdf_nbuf_free(cache_buf->buf); + } + cdf_mem_free(cache_buf); + cdf_spin_lock_bh(&peer->bufq_lock); + cache_buf = list_entry((&peer->cached_bufq)->next, + typeof(*cache_buf), list); + } + cdf_spin_unlock_bh(&peer->bufq_lock); + cdf_atomic_dec(&peer->flush_in_progress); +} + +ol_txrx_peer_handle +ol_txrx_peer_attach(ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, uint8_t *peer_mac_addr) +{ + struct ol_txrx_peer_t *peer; + struct ol_txrx_peer_t *temp_peer; + uint8_t i; + int differs; + bool wait_on_deletion = false; + unsigned long rc; + + /* preconditions */ + TXRX_ASSERT2(pdev); + TXRX_ASSERT2(vdev); + TXRX_ASSERT2(peer_mac_addr); + + cdf_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 (cdf_atomic_read(&temp_peer->delete_in_progress)) { + vdev->wait_on_peer_id = temp_peer->local_id; + cdf_event_init(&vdev->wait_delete_comp); + wait_on_deletion = true; + } else { + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + return NULL; + } + } + } + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + + if (wait_on_deletion) { + /* wait for peer deletion */ + rc = cdf_wait_single_event(&vdev->wait_delete_comp, + cdf_system_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 = cdf_mem_malloc(sizeof(*peer)); + if (!peer) + return NULL; /* failure */ + cdf_mem_zero(peer, sizeof(*peer)); + + /* store provided params */ + peer->vdev = vdev; + cdf_mem_copy(&peer->mac_addr.raw[0], peer_mac_addr, + OL_TXRX_MAC_ADDR_LEN); + + INIT_LIST_HEAD(&peer->cached_bufq); + cdf_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); + cdf_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; + + + peer->osif_rx = NULL; + cdf_spinlock_init(&peer->peer_info_lock); + cdf_spinlock_init(&peer->bufq_lock); + + cdf_atomic_init(&peer->delete_in_progress); + cdf_atomic_init(&peer->flush_in_progress); + + cdf_atomic_init(&peer->ref_cnt); + + /* keep one reference for attach */ + cdf_atomic_inc(&peer->ref_cnt); + + /* keep one reference for ol_rx_peer_map_handler */ + cdf_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 = + cdf_mem_compare(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; +} + +CDF_STATUS +ol_txrx_peer_state_update(struct ol_txrx_pdev_t *pdev, uint8_t *peer_mac, + enum ol_txrx_peer_state state) +{ + struct ol_txrx_peer_t *peer; + + if (cdf_unlikely(!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Pdev is NULL"); + cdf_assert(0); + return CDF_STATUS_E_INVAL; + } + + 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 CDF_STATUS_E_INVAL; + } + + /* 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", + __func__); +#endif + cdf_atomic_dec(&peer->ref_cnt); + return CDF_STATUS_SUCCESS; + } + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO2, "%s: change from %d to %d\n", + __func__, 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); + } + } + cdf_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; + return CDF_STATUS_SUCCESS; +} + +void +ol_txrx_peer_keyinstalled_state_update(struct ol_txrx_peer_t *peer, uint8_t val) +{ + peer->keyinstalled = val; +} + +void +ol_txrx_peer_update(ol_txrx_vdev_handle vdev, + uint8_t *peer_mac, + union ol_txrx_peer_update_param_t *param, + enum 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", + __func__); + 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: + { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "ERROR: unknown param %d in %s", select, + __func__); + break; + } + } + cdf_atomic_dec(&peer->ref_cnt); +} + +uint8_t +ol_txrx_peer_uapsdmask_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_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; +} + +uint8_t +ol_txrx_peer_qoscapable_get(struct ol_txrx_pdev_t *txrx_pdev, uint16_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 assert if it does.) + */ + + if (0 == cdf_atomic_read(&(peer->ref_cnt))) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "The Peer is not present anymore\n"); + cdf_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. + */ + cdf_spin_lock_bh(&pdev->peer_ref_mutex); + if (cdf_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 */ + cdf_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) { + cdf_event_set(&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)) { + /* + * Now that there are no references to the peer, we can + * release the peer reference lock. + */ + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + /* + * 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) { + ol_txrx_vdev_delete_cb vdev_delete_cb = + vdev->delete.callback; + void *vdev_delete_context = + vdev->delete.context; + + 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 */ + cdf_mem_free(vdev); + if (vdev_delete_cb) + vdev_delete_cb(vdev_delete_context); + } + } else + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + + /* + * '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 arr, tid:%d\n", + __func__, i); + cdf_mem_free(peer->tids_rx_reorder[i].array); + ol_rx_reorder_init(&peer->tids_rx_reorder[i], + (uint8_t) i); + } + } + + cdf_mem_free(peer); + } else { + cdf_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 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]); + ol_txrx_flush_rx_frames(peer, 1); + + if (peer->vdev->last_real_peer == peer) + peer->vdev->last_real_peer = NULL; + + cdf_spin_lock_bh(&vdev->pdev->last_real_peer_mutex); + if (vdev->last_real_peer == peer) + vdev->last_real_peer = NULL; + cdf_spin_unlock_bh(&vdev->pdev->last_real_peer_mutex); + htt_rx_reorder_log_print(peer->vdev->pdev->htt_pdev); + + cdf_spinlock_destroy(&peer->peer_info_lock); + cdf_spinlock_destroy(&peer->bufq_lock); + /* set delete_in_progress to identify that wma + * is waiting for unmap massage for this peer */ + cdf_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, uint8_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 total and free count + * @txrx_pdev: Pointer to txrx pdev + * + * Return: none + */ +static void ol_txrx_dump_tx_desc(ol_txrx_pdev_handle pdev_handle) +{ + struct ol_txrx_pdev_t *pdev = (ol_txrx_pdev_handle) pdev_handle; + uint32_t total; + + total = ol_tx_get_desc_global_pool_size(pdev); + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "total tx credit %d num_free %d", + total, pdev->tx_desc.num_free); + + return; +} + +/** + * ol_txrx_wait_for_pending_tx() - wait for tx queue to be empty + * @timeout: timeout in ms + * + * Wait for tx queue to be empty, return timeout error if + * queue doesn't empty before timeout occurs. + * + * Return: + * CDF_STATUS_SUCCESS if the queue empties, + * CDF_STATUS_E_TIMEOUT in case of timeout, + * CDF_STATUS_E_FAULT in case of missing handle + */ +CDF_STATUS ol_txrx_wait_for_pending_tx(int timeout) +{ + ol_txrx_pdev_handle txrx_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (txrx_pdev == NULL) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: txrx context is null", __func__); + return CDF_STATUS_E_FAULT; + } + + while (ol_txrx_get_tx_pending(txrx_pdev)) { + cdf_sleep(OL_ATH_TX_DRAIN_WAIT_DELAY); + if (timeout <= 0) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: tx frames are pending", __func__); + ol_txrx_dump_tx_desc(txrx_pdev); + return CDF_STATUS_E_TIMEOUT; + } + timeout = timeout - OL_ATH_TX_DRAIN_WAIT_DELAY; + } + return CDF_STATUS_SUCCESS; +} + +#ifndef QCA_WIFI_3_0_EMU +#define SUSPEND_DRAIN_WAIT 500 +#else +#define SUSPEND_DRAIN_WAIT 3000 +#endif + +/** + * ol_txrx_bus_suspend() - bus suspend + * + * Ensure that ol_txrx is ready for bus suspend + * + * Return: CDF_STATUS + */ +CDF_STATUS ol_txrx_bus_suspend(void) +{ + return ol_txrx_wait_for_pending_tx(SUSPEND_DRAIN_WAIT); +} + +/** + * ol_txrx_bus_resume() - bus resume + * + * Dummy function for symetry + * + * Return: CDF_STATUS_SUCCESS + */ +CDF_STATUS ol_txrx_bus_resume(void) +{ + return CDF_STATUS_SUCCESS; +} + +int ol_txrx_get_tx_pending(ol_txrx_pdev_handle pdev_handle) +{ + struct ol_txrx_pdev_t *pdev = (ol_txrx_pdev_handle) pdev_handle; + uint32_t total; + + total = ol_tx_get_desc_global_pool_size(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 cdf_atomic_dec_and_test(&tx_desc->ref_cnt) + * then let htt do the cdf_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, 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 + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, + "The driver is compiled without TXRX prints enabled.\n" + "To enable them, recompile with TXRX_PRINT_ENABLE defined"); +#else + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + "TXRX printout level changed from %d to %d", + 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 +uint64_t ol_txrx_stats_ptr_to_u64(struct ol_txrx_stats_req_internal *req) +{ + return (uint64_t) ((size_t) req); +} + +static inline +struct ol_txrx_stats_req_internal *ol_txrx_u64_to_stats_ptr(uint64_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, + uint8_t cfg_stats_type, uint32_t cfg_val) +{ + uint64_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; + uint64_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 = cdf_mem_malloc(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)) { + cdf_mem_free(non_volatile_req); + return A_ERROR; + } + + if (req->wait.blocking) + while (cdf_semaphore_acquire(pdev->osdev, req->wait.sem_ptr)) + ; + + return A_OK; +} +#endif +void +ol_txrx_fw_stats_handler(ol_txrx_pdev_handle pdev, + uint64_t cookie, uint8_t *stats_info_list) +{ + enum htt_dbg_stats_type type; + enum htt_dbg_stats_status status; + int length; + uint8_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) { + uint8_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 lmt; + + lmt = sizeof(struct wlan_dbg_stats); + if (req->base.copy.byte_limit < lmt) + lmt = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, lmt); + } + break; + case HTT_DBG_STATS_RX_REORDER: + bytes = sizeof(struct rx_reorder_stats); + if (req->base.copy.buf) { + int lmt; + + lmt = sizeof(struct rx_reorder_stats); + if (req->base.copy.byte_limit < lmt) + lmt = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, lmt); + } + break; + case HTT_DBG_STATS_RX_RATE_INFO: + bytes = sizeof(wlan_dbg_rx_rate_info_t); + if (req->base.copy.buf) { + int lmt; + + lmt = sizeof(wlan_dbg_rx_rate_info_t); + if (req->base.copy.byte_limit < lmt) + lmt = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, lmt); + } + break; + + case HTT_DBG_STATS_TX_RATE_INFO: + bytes = sizeof(wlan_dbg_tx_rate_info_t); + if (req->base.copy.buf) { + int lmt; + + lmt = sizeof(wlan_dbg_tx_rate_info_t); + if (req->base.copy.byte_limit < lmt) + lmt = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, lmt); + } + 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 buf */ + + 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; + cdf_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_TXBF_INFO: + bytes = sizeof(struct wlan_dbg_txbf_data_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct wlan_dbg_txbf_data_stats); + if (req->base.copy.byte_limit < limit) + limit = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_SND_INFO: + bytes = sizeof(struct wlan_dbg_txbf_snd_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct wlan_dbg_txbf_snd_stats); + if (req->base.copy.byte_limit < limit) + limit = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_TX_SELFGEN_INFO: + bytes = sizeof(struct wlan_dbg_tx_selfgen_stats); + if (req->base.copy.buf) { + int limit; + + limit = sizeof(struct wlan_dbg_tx_selfgen_stats); + if (req->base.copy.byte_limit < limit) + limit = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_mem_copy(buf, stats_data, limit); + } + break; + + case HTT_DBG_STATS_ERROR_INFO: + bytes = + sizeof(struct wlan_dbg_wifi2_error_stats); + if (req->base.copy.buf) { + int limit; + + limit = + sizeof(struct wlan_dbg_wifi2_error_stats); + if (req->base.copy.byte_limit < limit) + limit = req->base.copy.byte_limit; + buf = req->base.copy.buf + req->offset; + cdf_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; + cdf_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) + cdf_semaphore_release(pdev->osdev, + req->base.wait.sem_ptr); + cdf_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 + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, + "The pdev,vdev,peer display functions are disabled.\n" + "To enable them, recompile with TXRX_DEBUG_LEVEL > 5"); +#endif + } + if (debug_specs & TXRX_DBG_MASK_STATS) { + ol_txrx_stats_display(vdev->pdev); + } + if (debug_specs & TXRX_DBG_MASK_PROT_ANALYZE) { +#if defined(ENABLE_TXRX_PROT_ANALYZE) + ol_txrx_prot_ans_display(vdev->pdev); +#else + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, + "txrx protocol analysis is disabled.\n" + "To enable it, recompile with " + "ENABLE_TXRX_PROT_ANALYZE defined"); +#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 + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, + "rx reorder seq num trace is disabled.\n" + "To enable it, recompile with " + "ENABLE_RX_REORDER_TRACE defined"); +#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; + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*s%s:\n", indent, " ", "txrx pdev"); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*spdev object: %p", indent + 4, " ", pdev); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*svdev list:", 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); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*stx desc pool: %d elems @ %p", indent + 4, " ", + pdev->tx_desc.pool_size, pdev->tx_desc.array); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, " "); + htt_display(pdev->htt_pdev, indent); +} + +void ol_txrx_vdev_display(ol_txrx_vdev_handle vdev, int indent) +{ + struct ol_txrx_peer_t *peer; + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*stxrx vdev: %p\n", indent, " ", vdev); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*sID: %d\n", indent + 4, " ", vdev->vdev_id); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*sMAC addr: %d:%d:%d:%d:%d:%d", + 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]); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*speer list:", 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; + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*stxrx peer: %p", indent, " ", peer); + for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) { + if (peer->peer_ids[i] != HTT_INVALID_PEER) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*sID: %d", indent + 4, " ", + peer->peer_ids[i]); + } + } +} +#endif /* TXRX_DEBUG_LEVEL */ + +#if defined(FEATURE_TSO) && defined(FEATURE_TSO_DEBUG) +void ol_txrx_stats_display_tso(ol_txrx_pdev_handle pdev) +{ + int msdu_idx; + int seg_idx; + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "TSO pkts %lld, bytes %lld\n", + pdev->stats.pub.tx.tso.tso_pkts.pkts, + pdev->stats.pub.tx.tso.tso_pkts.bytes); + + for (msdu_idx = 0; msdu_idx < NUM_MAX_TSO_MSDUS; msdu_idx++) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "curr msdu idx: %d curr seg idx: %d num segs %d\n", + TXRX_STATS_TSO_MSDU_IDX(pdev), + TXRX_STATS_TSO_SEG_IDX(pdev), + TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, msdu_idx)); + for (seg_idx = 0; + ((seg_idx < TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, msdu_idx)) && + (seg_idx < NUM_MAX_TSO_SEGS)); + seg_idx++) { + struct cdf_tso_seg_t tso_seg = + TXRX_STATS_TSO_SEG(pdev, msdu_idx, seg_idx); + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "msdu idx: %d seg idx: %d\n", + msdu_idx, seg_idx); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "tso_enable: %d\n", + tso_seg.tso_flags.tso_enable); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "fin %d syn %d rst %d psh %d ack %d\n" + "urg %d ece %d cwr %d ns %d\n", + tso_seg.tso_flags.fin, tso_seg.tso_flags.syn, + tso_seg.tso_flags.rst, tso_seg.tso_flags.psh, + tso_seg.tso_flags.ack, tso_seg.tso_flags.urg, + tso_seg.tso_flags.ece, tso_seg.tso_flags.cwr, + tso_seg.tso_flags.ns); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "tcp_seq_num: 0x%x ip_id: %d\n", + tso_seg.tso_flags.tcp_seq_num, + tso_seg.tso_flags.ip_id); + } + } +} +#endif + +/** + * ol_txrx_stats() - update ol layer stats + * @vdev_id: vdev_id + * @buffer: pointer to buffer + * @buf_len: length of the buffer + * + * Return: length of string + */ +int +ol_txrx_stats(uint8_t vdev_id, char *buffer, unsigned buf_len) +{ + uint32_t len = 0; + + ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (!vdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: vdev is NULL", __func__); + snprintf(buffer, buf_len, "vdev not found"); + return len; + } + + len = scnprintf(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")); + return len; +} + +void ol_txrx_stats_display(ol_txrx_pdev_handle pdev) +{ + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, "txrx stats:"); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + " tx: sent %lld msdus (%lld B), " + " rejected %lld (%lld B), dropped %lld (%lld B)", + 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); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + " download fail: %lld (%lld B), " + "target discard: %lld (%lld B), " + "no ack: %lld (%lld B)", + 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); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "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); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + " rx: %lld ppdus, %lld mpdus, %lld msdus, %lld bytes, %lld errs", + 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); + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + " 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) +{ + cdf_mem_zero(&pdev->stats, sizeof(pdev->stats)); +} + +#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) +{ + cdf_assert(pdev && peer && stats); + cdf_spin_lock_bh(&pdev->peer_stat_mutex); + cdf_mem_copy(stats, &peer->stats, sizeof(*stats)); + cdf_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, bool val) +{ + if (NULL == vdev) + return; + + vdev->disable_intrabss_fwd = val; +} + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + +/** + * ol_txrx_get_vdev_from_sta_id() - get vdev from sta_id + * @sta_id: sta_id + * + * Return: vdev handle + * NULL if not found. + */ +static ol_txrx_vdev_handle ol_txrx_get_vdev_from_sta_id(uint8_t sta_id) +{ + struct ol_txrx_peer_t *peer = NULL; + ol_txrx_pdev_handle pdev = NULL; + + if (sta_id >= WLAN_MAX_STA_COUNT) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid sta id passed"); + return NULL; + } + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "PDEV not found for sta_id [%d]", sta_id); + return NULL; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + + if (!peer) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "PEER [%d] not found", sta_id); + return NULL; + } + + return peer->vdev; +} + +/** + * ol_txrx_register_tx_flow_control() - register tx flow control callback + * @vdev_id: vdev_id + * @flowControl: flow control callback + * @osif_fc_ctx: callback context + * + * Return: 0 for sucess or error code + */ +int ol_txrx_register_tx_flow_control (uint8_t vdev_id, + ol_txrx_tx_flow_control_fp flowControl, + void *osif_fc_ctx) +{ + ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (NULL == vdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid vdev_id %d", __func__, vdev_id); + return -EINVAL; + } + + cdf_spin_lock_bh(&vdev->flow_control_lock); + vdev->osif_flow_control_cb = flowControl; + vdev->osif_fc_ctx = osif_fc_ctx; + cdf_spin_unlock_bh(&vdev->flow_control_lock); + return 0; +} + +/** + * ol_txrx_de_register_tx_flow_control_cb() - deregister tx flow control callback + * @vdev_id: vdev_id + * + * Return: 0 for success or error code + */ +int ol_txrx_deregister_tx_flow_control_cb(uint8_t vdev_id) +{ + ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (NULL == vdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid vdev_id", __func__); + return -EINVAL; + } + + cdf_spin_lock_bh(&vdev->flow_control_lock); + vdev->osif_flow_control_cb = NULL; + vdev->osif_fc_ctx = NULL; + cdf_spin_unlock_bh(&vdev->flow_control_lock); + return 0; +} + +/** + * ol_txrx_get_tx_resource() - if tx resource less than low_watermark + * @sta_id: sta id + * @low_watermark: low watermark + * @high_watermark_offset: high watermark offset value + * + * Return: true/false + */ +bool +ol_txrx_get_tx_resource(uint8_t sta_id, + unsigned int low_watermark, + unsigned int high_watermark_offset) +{ + ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_sta_id(sta_id); + if (NULL == vdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid sta_id %d", __func__, sta_id); + /* Return true so caller do not understand that resource + * is less than low_watermark. + * sta_id validation will be done in ol_tx_send_data_frame + * and if sta_id is not registered then host will drop + * packet. + */ + return true; + } + + cdf_spin_lock_bh(&vdev->pdev->tx_mutex); + if (vdev->pdev->tx_desc.num_free < (uint16_t) low_watermark) { + vdev->tx_fl_lwm = (uint16_t) low_watermark; + vdev->tx_fl_hwm = + (uint16_t) (low_watermark + high_watermark_offset); + /* Not enough free resource, stop TX OS Q */ + cdf_atomic_set(&vdev->os_q_paused, 1); + cdf_spin_unlock_bh(&vdev->pdev->tx_mutex); + return false; + } + cdf_spin_unlock_bh(&vdev->pdev->tx_mutex); + return true; +} + +/** + * ol_txrx_ll_set_tx_pause_q_depth() - set pause queue depth + * @vdev_id: vdev id + * @pause_q_depth: pause queue depth + * + * Return: 0 for success or error code + */ +int +ol_txrx_ll_set_tx_pause_q_depth(uint8_t vdev_id, int pause_q_depth) +{ + ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (NULL == vdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid vdev_id %d", __func__, vdev_id); + return -EINVAL; + } + + cdf_spin_lock_bh(&vdev->ll_pause.mutex); + vdev->ll_pause.max_q_depth = pause_q_depth; + cdf_spin_unlock_bh(&vdev->ll_pause.mutex); + + return 0; +} + +/** + * ol_txrx_flow_control_cb() - call osif flow control callback + * @vdev: vdev handle + * @tx_resume: tx resume flag + * + * Return: none + */ +inline void ol_txrx_flow_control_cb(ol_txrx_vdev_handle vdev, + bool tx_resume) +{ + cdf_spin_lock_bh(&vdev->flow_control_lock); + if ((vdev->osif_flow_control_cb) && (vdev->osif_fc_ctx)) + vdev->osif_flow_control_cb(vdev->osif_fc_ctx, tx_resume); + cdf_spin_unlock_bh(&vdev->flow_control_lock); + + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +#ifdef IPA_OFFLOAD +void +ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr, + uint32_t *tx_comp_ring_base_paddr, + uint32_t *tx_comp_ring_size, + uint32_t *tx_num_alloc_buffer, + uint32_t *rx_rdy_ring_base_paddr, + uint32_t *rx_rdy_ring_size, + uint32_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, + uint32_t ipa_tx_uc_doorbell_paddr, + uint32_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, bool uc_active, bool is_tx) +{ + htt_h2t_ipa_uc_set_active(pdev->htt_pdev, uc_active, is_tx); +} + +/** + * ol_txrx_ipa_uc_fw_op_event_handler() - opcode event handler + * @context: pdev context + * @rxpkt: received packet + * @staid: peer id + * + * Return: None + */ +void ol_txrx_ipa_uc_fw_op_event_handler(void *context, + void *rxpkt, + uint16_t staid) +{ + ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)context; + + if (cdf_unlikely(!pdev)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid context", __func__); + return; + } + + if (pdev->ipa_uc_op_cb) + pdev->ipa_uc_op_cb(rxpkt, pdev->osif_dev); + else + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: ipa_uc_op_cb NULL", __func__); +} + + +void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) +{ + p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); + struct cds_ol_rx_pkt *pkt; + + if (cdf_unlikely(!sched_ctx)) + return; + + pkt = cds_alloc_ol_rx_pkt(sched_ctx); + if (cdf_unlikely(!pkt)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate context", __func__); + return; + } + + pkt->callback = (cds_ol_rx_thread_cb) ol_txrx_ipa_uc_fw_op_event_handler; + pkt->context = pdev; + pkt->Rxpkt = (void *)op_msg; + pkt->staId = 0; + cds_indicate_rxpkt(sched_ctx, pkt); +} + +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(uint16_t value) +{ + ol_txrx_pdev_handle pdev; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: pdev is NULL", __func__); + return; + } + + switch (value) { + case WLAN_TXRX_STATS: + ol_txrx_stats_display(pdev); + break; + case WLAN_TXRX_TSO_STATS: +#if defined(FEATURE_TSO) && defined(FEATURE_TSO_DEBUG) + ol_txrx_stats_display_tso(pdev); +#else + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: TSO not supported", __func__); +#endif + break; + case WLAN_DUMP_TX_FLOW_POOL_INFO: + ol_tx_dump_flow_pool_info(); + break; + case WLAN_TXRX_DESC_STATS: + cdf_nbuf_tx_desc_count_display(); + break; + default: + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Unknown value", __func__); + break; + } +} + +void ol_txrx_clear_stats(uint16_t value) +{ + ol_txrx_pdev_handle pdev; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: pdev is NULL", __func__); + return; + } + + switch (value) { + case WLAN_TXRX_STATS: + ol_txrx_stats_clear(pdev); + break; + case WLAN_DUMP_TX_FLOW_POOL_INFO: + ol_tx_clear_flow_pool_stats(); + break; + case WLAN_TXRX_DESC_STATS: + cdf_nbuf_tx_desc_count_clear(); + break; + default: + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Unknown value", __func__); + break; + } +} + +/** + * ol_rx_data_cb() - data rx callback + * @peer: peer + * @buf_list: buffer list + * + * Return: None + */ +static void ol_rx_data_cb(struct ol_txrx_peer_t *peer, + cdf_nbuf_t buf_list) +{ + void *cds_ctx = cds_get_global_context(); + cdf_nbuf_t buf, next_buf; + CDF_STATUS ret; + ol_rx_callback_fp data_rx = NULL; + + if (cdf_unlikely(!cds_ctx)) + goto free_buf; + + cdf_spin_lock_bh(&peer->peer_info_lock); + if (cdf_unlikely(!(peer->state >= ol_txrx_peer_state_conn))) { + cdf_spin_unlock_bh(&peer->peer_info_lock); + goto free_buf; + } + data_rx = peer->osif_rx; + cdf_spin_unlock_bh(&peer->peer_info_lock); + + cdf_spin_lock_bh(&peer->bufq_lock); + if (!list_empty(&peer->cached_bufq)) { + cdf_spin_unlock_bh(&peer->bufq_lock); + /* Flush the cached frames to HDD before passing new rx frame */ + ol_txrx_flush_rx_frames(peer, 0); + } else + cdf_spin_unlock_bh(&peer->bufq_lock); + + buf = buf_list; + while (buf) { + next_buf = cdf_nbuf_queue_next(buf); + cdf_nbuf_set_next(buf, NULL); /* Add NULL terminator */ + ret = data_rx(cds_ctx, buf, peer->local_id); + if (ret != CDF_STATUS_SUCCESS) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Frame Rx to HDD failed"); + cdf_nbuf_free(buf); + } + buf = next_buf; + } + return; + +free_buf: + TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "%s:Dropping frames", __func__); + buf = buf_list; + while (buf) { + next_buf = cdf_nbuf_queue_next(buf); + cdf_nbuf_free(buf); + buf = next_buf; + } +} + +/** + * ol_rx_data_process() - process rx frame + * @peer: peer + * @rx_buf_list: rx buffer list + * + * Return: None + */ +void ol_rx_data_process(struct ol_txrx_peer_t *peer, + cdf_nbuf_t rx_buf_list) +{ + /* 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 */ + cdf_nbuf_t buf, next_buf; + ol_rx_callback_fp data_rx = NULL; + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if ((!peer) || (!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "peer/pdev is NULL"); + goto drop_rx_buf; + } + + cdf_spin_lock_bh(&peer->peer_info_lock); + if (peer->state >= ol_txrx_peer_state_conn) + data_rx = peer->osif_rx; + cdf_spin_unlock_bh(&peer->peer_info_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 ol_rx_cached_buf *cache_buf; + buf = rx_buf_list; + while (buf) { + next_buf = cdf_nbuf_queue_next(buf); + cache_buf = cdf_mem_malloc(sizeof(*cache_buf)); + if (!cache_buf) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Failed to allocate buf to cache the rx frames"); + cdf_nbuf_free(buf); + } else { + /* Add NULL terminator */ + cdf_nbuf_set_next(buf, NULL); + cache_buf->buf = buf; + cdf_spin_lock_bh(&peer->bufq_lock); + list_add_tail(&cache_buf->list, + &peer->cached_bufq); + cdf_spin_unlock_bh(&peer->bufq_lock); + } + buf = next_buf; + } + } else { +#ifdef QCA_CONFIG_SMP + /* + * If the kernel is SMP, schedule rx thread to + * better use multicores. + */ + if (!ol_cfg_is_rx_thread_enabled(pdev->ctrl_pdev)) { + ol_rx_data_cb(peer, rx_buf_list); + } else { + p_cds_sched_context sched_ctx = + get_cds_sched_ctxt(); + struct cds_ol_rx_pkt *pkt; + + if (unlikely(!sched_ctx)) + goto drop_rx_buf; + + pkt = cds_alloc_ol_rx_pkt(sched_ctx); + if (!pkt) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "No available Rx message buffer"); + goto drop_rx_buf; + } + pkt->callback = (cds_ol_rx_thread_cb) + ol_rx_data_cb; + pkt->context = (void *)peer; + pkt->Rxpkt = (void *)rx_buf_list; + pkt->staId = peer->local_id; + cds_indicate_rxpkt(sched_ctx, pkt); + } +#else /* QCA_CONFIG_SMP */ + ol_rx_data_cb(peer, rx_buf_list, 0); +#endif /* QCA_CONFIG_SMP */ + } + + return; + +drop_rx_buf: + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Dropping rx packets"); + buf = rx_buf_list; + while (buf) { + next_buf = cdf_nbuf_queue_next(buf); + cdf_nbuf_free(buf); + buf = next_buf; + } +} + +/** + * ol_txrx_register_peer() - register peer + * @rxcb: rx callback + * @sta_desc: sta descriptor + * + * Return: CDF Status + */ +CDF_STATUS ol_txrx_register_peer(ol_rx_callback_fp rxcb, + struct ol_txrx_desc_type *sta_desc) +{ + struct ol_txrx_peer_t *peer; + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + union ol_txrx_peer_update_param_t param; + struct privacy_exemption privacy_filter; + + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Pdev is NULL"); + return CDF_STATUS_E_INVAL; + } + + if (sta_desc->sta_id >= WLAN_MAX_STA_COUNT) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Invalid sta id :%d", + sta_desc->sta_id); + return CDF_STATUS_E_INVAL; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_desc->sta_id); + if (!peer) + return CDF_STATUS_E_FAULT; + + cdf_spin_lock_bh(&peer->peer_info_lock); + peer->osif_rx = rxcb; + peer->state = ol_txrx_peer_state_conn; + cdf_spin_unlock_bh(&peer->peer_info_lock); + + param.qos_capable = sta_desc->is_qos_enabled; + ol_txrx_peer_update(peer->vdev, peer->mac_addr.raw, ¶m, + ol_txrx_peer_update_qos_capable); + + if (sta_desc->is_wapi_supported) { + /*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); + } + + ol_txrx_flush_rx_frames(peer, 0); + return CDF_STATUS_SUCCESS; +} + +/** + * ol_txrx_clear_peer() - clear peer + * @sta_id: sta id + * + * Return: CDF Status + */ +CDF_STATUS ol_txrx_clear_peer(uint8_t sta_id) +{ + struct ol_txrx_peer_t *peer; + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Unable to find pdev!", + __func__); + return CDF_STATUS_E_FAILURE; + } + + if (sta_id >= WLAN_MAX_STA_COUNT) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Invalid sta id %d", sta_id); + return CDF_STATUS_E_INVAL; + } + +#ifdef QCA_CONFIG_SMP + { + p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); + /* Drop pending Rx frames in CDS */ + if (sched_ctx) + cds_drop_rxpkt_by_staid(sched_ctx, sta_id); + } +#endif + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + if (!peer) + return CDF_STATUS_E_FAULT; + + /* Purge the cached rx frame queue */ + ol_txrx_flush_rx_frames(peer, 1); + + cdf_spin_lock_bh(&peer->peer_info_lock); + peer->osif_rx = NULL; + peer->state = ol_txrx_peer_state_disc; + cdf_spin_unlock_bh(&peer->peer_info_lock); + + return CDF_STATUS_SUCCESS; +} + +/** + * ol_txrx_register_ocb_peer - Function to register the OCB peer + * @cds_ctx: Pointer to the global OS context + * @mac_addr: MAC address of the self peer + * @peer_id: Pointer to the peer ID + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS ol_txrx_register_ocb_peer(void *cds_ctx, uint8_t *mac_addr, + uint8_t *peer_id) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_peer_handle peer; + + if (!cds_ctx) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Invalid context", + __func__); + return CDF_STATUS_E_FAILURE; + } + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Unable to find pdev!", + __func__); + return CDF_STATUS_E_FAILURE; + } + + peer = ol_txrx_find_peer_by_addr(pdev, mac_addr, peer_id); + if (!peer) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Unable to find OCB peer!", + __func__); + return CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * ol_txrx_set_ocb_peer - Function to store the OCB peer + * @pdev: Handle to the HTT instance + * @peer: Pointer to the 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); +} + +/** + * ol_txrx_get_ocb_peer - Function to retrieve the OCB peer + * @pdev: Handle to the HTT instance + * @peer: Pointer to the returned peer + * + * Return: true if the peer is valid, false if not + */ +bool 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 = false; + goto exit; + } + + if (pdev->ocb_peer_valid) { + *peer = pdev->ocb_peer; + rc = true; + } else { + rc = false; + } + +exit: + return rc; +} + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_txrx_register_pause_cb() - register pause callback + * @pause_cb: pause callback + * + * Return: CDF status + */ +CDF_STATUS ol_txrx_register_pause_cb(ol_tx_pause_callback_fp pause_cb) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev || !pause_cb) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "pdev or pause_cb is NULL"); + return CDF_STATUS_E_INVAL; + } + pdev->pause_cb = pause_cb; + return CDF_STATUS_SUCCESS; +} +#endif + +#if defined(FEATURE_LRO) +void ol_txrx_lro_flush_handler(void *context, + void *rxpkt, + uint16_t staid) +{ + ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)context; + + if (cdf_unlikely(!pdev)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid context", __func__); + cdf_assert(0); + return; + } + + if (pdev->lro_info.lro_flush_cb) + pdev->lro_info.lro_flush_cb(pdev->lro_info.lro_data); + else + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: lro_flush_cb NULL", __func__); +} + +void ol_txrx_lro_flush(void *data) +{ + p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); + struct cds_ol_rx_pkt *pkt; + ol_txrx_pdev_handle pdev = (ol_txrx_pdev_handle)data; + + if (cdf_unlikely(!sched_ctx)) + return; + + if (!ol_cfg_is_rx_thread_enabled(pdev->ctrl_pdev)) { + ol_txrx_lro_flush_handler((void *)pdev, NULL, 0); + } else { + pkt = cds_alloc_ol_rx_pkt(sched_ctx); + if (cdf_unlikely(!pkt)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate context", __func__); + return; + } + + pkt->callback = (cds_ol_rx_thread_cb) ol_txrx_lro_flush_handler; + pkt->context = pdev; + pkt->Rxpkt = NULL; + pkt->staId = 0; + cds_indicate_rxpkt(sched_ctx, pkt); + } +} + +void ol_register_lro_flush_cb(void (handler)(void *), void *data) +{ + struct ol_softc *hif_device = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + pdev->lro_info.lro_flush_cb = handler; + pdev->lro_info.lro_data = data; + + ce_lro_flush_cb_register(hif_device, ol_txrx_lro_flush, pdev); +} +#endif /* FEATURE_LRO */ diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h new file mode 100644 index 000000000000..01590093520f --- /dev/null +++ b/core/dp/txrx/ol_txrx.h @@ -0,0 +1,70 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* ol_txrx_vdev_t, etc. */ +#include /* ol_pdev_handle */ +#include "cds_sched.h" + +void ol_txrx_peer_unref_delete(struct ol_txrx_peer_t *peer); + +#ifndef OL_TX_AVG_FRM_BYTES +#define OL_TX_AVG_FRM_BYTES 1000 +#endif + +#ifdef CONFIG_PER_VDEV_TX_DESC_POOL +#define TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK 400 +#endif + +/** + * ol_txrx_get_vdev_from_vdev_id() - get vdev from vdev_id + * @vdev_id: vdev_id + * + * Return: vdev handle + * NULL if not found. + */ +static inline ol_txrx_vdev_handle ol_txrx_get_vdev_from_vdev_id(uint8_t vdev_id) +{ + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + ol_txrx_vdev_handle vdev = NULL; + + if (cdf_unlikely(!pdev)) { + return NULL; + } + + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (vdev->vdev_id == vdev_id) + break; + } + + return vdev; +} + +#endif /* _OL_TXRX__H_ */ diff --git a/core/dp/txrx/ol_txrx_encap.c b/core/dp/txrx/ol_txrx_encap.c new file mode 100644 index 000000000000..a7471da73748 --- /dev/null +++ b/core/dp/txrx/ol_txrx_encap.c @@ -0,0 +1,593 @@ +/* + * 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_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 /* cdf_nbuf_t, etc. */ +#include /* ieee80211_frame */ +#include /* struct llc, struct ether_header, etc. */ +#include /* TXRX_ASSERT1 */ +#include /* struct ol_txrx_vdev_t, 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 *)cdf_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 (cdf_nbuf_len(msdu) < hdsize) { \ + return A_ERROR; \ + } \ + cdf_mem_copy(localbuf, wh, hdsize); \ + wh = (struct ieee80211_frame *)localbuf; \ + } while (0) + +static inline A_STATUS +ol_tx_copy_native_wifi_header(cdf_nbuf_t msdu, + uint8_t *hdsize, uint8_t *localbuf) +{ + struct ieee80211_frame *wh = + (struct ieee80211_frame *)cdf_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 (cdf_nbuf_len(msdu) < *hdsize) + return A_ERROR; + + cdf_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, + cdf_nbuf_t msdu, + struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + uint8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4)]; + struct ieee80211_frame *wh; + uint8_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; + +#ifdef NEVERDEFINED + 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 */ + cdf_mem_copy((void *) + htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, + new_hdsize), localbuf, + new_hdsize); + cdf_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); + cdf_mem_copy((void *)wh, localbuf, hdsize); + cdf_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, + cdf_nbuf_t msdu, struct ol_txrx_msdu_info_t *tx_msdu_info) +{ + uint8_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; + uint8_t hdsize, new_l2_hdsize, new_hdsize; + struct ieee80211_qoscntl *qos_cntl; + const uint8_t ethernet_II_llc_snap_header_prefix[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + struct ol_txrx_peer_t *peer; + uint16_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 *)cdf_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; + *(uint16_t *) wh->i_dur = 0; + new_hdsize = 0; + + switch (vdev->opmode) { + case wlan_op_mode_ap: + /* DA , BSSID , SA */ + cdf_mem_copy(wh->i_addr1, eth_hdr->dest_addr, + IEEE80211_ADDR_LEN); + cdf_mem_copy(wh->i_addr2, &vdev->mac_addr.raw, + IEEE80211_ADDR_LEN); + cdf_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 */ + cdf_mem_copy(wh->i_addr1, eth_hdr->dest_addr, + IEEE80211_ADDR_LEN); + cdf_mem_copy(wh->i_addr2, eth_hdr->src_addr, + IEEE80211_ADDR_LEN); + /* need to check the bssid behaviour for IBSS vdev */ + cdf_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 */ + cdf_mem_copy(wh->i_addr1, &peer->mac_addr.raw, + IEEE80211_ADDR_LEN); + cdf_mem_copy(wh->i_addr2, eth_hdr->src_addr, + IEEE80211_ADDR_LEN); + cdf_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; +#ifdef NEVERDEFINED + 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) { + cdf_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? */ + } + } + cdf_mem_copy((void *) + htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, + new_l2_hdsize), localbuf, + new_hdsize); + cdf_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, + cdf_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, + cdf_nbuf_t msdu, + struct ol_rx_decap_info_t *info, + struct ethernet_hdr_t *ethr_hdr) +{ + struct ieee80211_frame_addr4 *wh; + uint16_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 *)cdf_nbuf_push_head(msdu, hdsize); + TXRX_ASSERT2(wh != NULL); + TXRX_ASSERT2(hdsize <= info->hdr_len); + cdf_mem_copy((uint8_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: + cdf_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, + ETHERNET_ADDR_LEN); + cdf_mem_copy(wh->i_addr2, ethr_hdr->src_addr, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + cdf_mem_copy(wh->i_addr2, ethr_hdr->src_addr, + ETHERNET_ADDR_LEN); + cdf_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + cdf_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, + ETHERNET_ADDR_LEN); + cdf_mem_copy(wh->i_addr3, ethr_hdr->src_addr, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + cdf_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, + ETHERNET_ADDR_LEN); + cdf_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, + cdf_nbuf_t msdu, + struct ol_rx_decap_info_t *info, + struct ethernet_hdr_t *ethr_hdr) +{ + struct llc_snap_hdr_t *llc_hdr; + uint16_t ether_type; + uint16_t l2_hdr_space; + struct ieee80211_frame_addr4 *wh; + uint8_t local_buf[ETHERNET_HDR_LEN]; + uint8_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 = (uint8_t *) cdf_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 = cdf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN); + else if (l2_hdr_space < ETHERNET_HDR_LEN) + buf = cdf_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: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + cdf_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 { + uint32_t pktlen = + cdf_nbuf_len(msdu) - sizeof(ethr_hdr->ethertype); + TXRX_ASSERT2(pktlen <= ETHERNET_MTU); + ether_type = (uint16_t) pktlen; + ether_type = cdf_nbuf_len(msdu) - sizeof(struct ethernet_hdr_t); + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } + cdf_mem_copy(buf, ethr_hdr, ETHERNET_HDR_LEN); +} + +static inline A_STATUS +ol_rx_decap_subfrm_amsdu(struct ol_txrx_vdev_t *vdev, + cdf_nbuf_t msdu, struct ol_rx_decap_info_t *info) +{ + struct ol_txrx_pdev_t *pdev = vdev->pdev; + uint8_t *subfrm_hdr; + uint8_t localbuf[ETHERNET_HDR_LEN]; + struct ethernet_hdr_t *ether_hdr = (struct ethernet_hdr_t *)localbuf; + + subfrm_hdr = (uint8_t *) cdf_nbuf_data(msdu); + if (pdev->frame_format == wlan_frm_fmt_native_wifi) { + /* decap to native wifi */ + cdf_mem_copy(ether_hdr, subfrm_hdr, ETHERNET_HDR_LEN); + cdf_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 + */ + cdf_mem_copy(ether_hdr, subfrm_hdr, ETHERNET_HDR_LEN); + cdf_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, + cdf_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 *)cdf_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)); + cdf_mem_copy(info->hdr, /* use info->hdr as temp buf. */ + wh, info->hdr_len); + cdf_nbuf_pull_head(msdu, info->hdr_len); + ol_rx_decap_to_native_wifi(vdev, msdu, info, NULL); + /* 802.11 hdr^ eth_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)); + cdf_mem_copy(info->hdr, /* use info->hdr as temp buf. */ + wh, info->hdr_len); + cdf_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, + cdf_nbuf_t msdu, struct ol_rx_decap_info_t *info) +{ + A_STATUS status; + uint8_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 = cdf_nbuf_data(msdu); + info->hdr_len = + ol_txrx_ieee80211_hdrsize(mpdu_hdr); + TXRX_ASSERT2(info->hdr_len <= + sizeof(info->hdr)); + cdf_mem_copy(info->hdr, mpdu_hdr, + info->hdr_len); + cdf_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/core/dp/txrx/ol_txrx_encap.h b/core/dp/txrx/ol_txrx_encap.h new file mode 100644 index 000000000000..5795b3bbd4f3 --- /dev/null +++ b/core/dp/txrx/ol_txrx_encap.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 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. + */ + +/** + * @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 /* cdf_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 - cdf_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, + cdf_nbuf_t msdu, struct ol_txrx_msdu_info_t *msdu_info); + +struct ol_rx_decap_info_t { + uint8_t hdr[sizeof(struct ieee80211_qosframe_htc_addr4)]; + int hdr_len; + uint8_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 - cdf_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, + cdf_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, + cdf_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, + cdf_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) \ + do { \ + if (__tx_desc->orig_l2_hdr_bytes != 0) \ + cdf_nbuf_push_head(__msdu, \ + __tx_desc->orig_l2_hdr_bytes); \ + } while (0) +#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/core/dp/txrx/ol_txrx_event.c b/core/dp/txrx/ol_txrx_event.c new file mode 100644 index 000000000000..3410a14083a0 --- /dev/null +++ b/core/dp/txrx/ol_txrx_event.c @@ -0,0 +1,228 @@ +/* + * 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 "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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid subscriber in %s\n", __func__); + 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; + } + /* cdf_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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid WDI event in %s\n", __func__); + return; + } + if (!txrx_pdev) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid txrx_pdev in %s", __func__); + return A_ERROR; + } + if (!event_cb_sub) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid callback in %s", __func__); + return A_ERROR; + } + if ((!event) || (event >= WDI_EVENT_LAST) || (event < WDI_EVENT_BASE)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid event in %s", __func__); + 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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid callback in %s", __func__); + 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; + + /* cdf_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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid device in %s\nWDI event attach failed", + __func__); + return A_ERROR; + } + /* Separate subscriber list for each event */ + txrx_pdev->wdi_event_list = (wdi_event_subscribe **) + cdf_mem_malloc( + sizeof(wdi_event_subscribe *) * + WDI_NUM_EVENTS); + if (!txrx_pdev->wdi_event_list) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Invalid device in %s\nWDI detach failed", + __func__); + return A_ERROR; + } + if (!txrx_pdev->wdi_event_list) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: wdi_event_list is NULL", __func__); + 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 */ + cdf_mem_free(txrx_pdev->wdi_event_list); + return A_OK; +} + +#endif /* WDI_EVENT_ENABLE */ diff --git a/core/dp/txrx/ol_txrx_flow_control.c b/core/dp/txrx/ol_txrx_flow_control.c new file mode 100644 index 000000000000..fd759baee8dc --- /dev/null +++ b/core/dp/txrx/ol_txrx_flow_control.c @@ -0,0 +1,707 @@ +/* + * 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. + */ + +/* OS abstraction libraries */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_atomic_read, etc. */ +#include /* cdf_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_enqueue */ + +/* internal header files relevant only for specific systems (Pronto) */ +#include /* OL_TX_ENCAP, etc */ +#include +#include + +#define TX_FLOW_START_TH 25 +#define TX_FLOW_STOP_TH 10 +#define INVALID_FLOW_ID 0xFF +#define MAX_INVALID_BIN 3 + + +#ifdef QCA_LL_TX_FLOW_GLOBAL_MGMT_POOL +#define TX_FLOW_MGMT_POOL_ID 0xEF +#define TX_FLOW_MGMT_POOL_SIZE 32 + +/** + * ol_tx_register_global_mgmt_pool() - register global pool for mgmt packets + * @pdev: pdev handler + * + * Return: none + */ +static void +ol_tx_register_global_mgmt_pool(struct ol_txrx_pdev_t *pdev) +{ + pdev->mgmt_pool = ol_tx_create_flow_pool(TX_FLOW_MGMT_POOL_ID, + TX_FLOW_MGMT_POOL_SIZE); + if (!pdev->mgmt_pool) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Management pool creation failed\n"); + } + return; +} + +/** + * ol_tx_deregister_global_mgmt_pool() - Deregister global pool for mgmt packets + * @pdev: pdev handler + * + * Return: none + */ +static void +ol_tx_deregister_global_mgmt_pool(struct ol_txrx_pdev_t *pdev) +{ + ol_tx_delete_flow_pool(pdev->mgmt_pool); + return; +} +#else +static inline void +ol_tx_register_global_mgmt_pool(struct ol_txrx_pdev_t *pdev) +{ + return; +} +static inline void +ol_tx_deregister_global_mgmt_pool(struct ol_txrx_pdev_t *pdev) +{ + return; +} +#endif + +/** + * ol_tx_register_flow_control() - Register fw based tx flow control + * @pdev: pdev handle + * + * Return: none + */ +void ol_tx_register_flow_control(struct ol_txrx_pdev_t *pdev) +{ + cdf_spinlock_init(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_INIT(&pdev->tx_desc.flow_pool_list); + + ol_tx_register_global_mgmt_pool(pdev); +} + +/** + * ol_tx_deregister_flow_control() - Deregister fw based tx flow control + * @pdev: pdev handle + * + * Return: none + */ +void ol_tx_deregister_flow_control(struct ol_txrx_pdev_t *pdev) +{ + ol_tx_deregister_global_mgmt_pool(pdev); + + cdf_spinlock_destroy(&pdev->tx_desc.flow_pool_list_lock); + if (!TAILQ_EMPTY(&pdev->tx_desc.flow_pool_list)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "flow pool list is not empty!!!\n"); + } +} + +/** + * ol_tx_dump_flow_pool_info() - dump global_pool and flow_pool info + * + * Return: none + */ +void ol_tx_dump_flow_pool_info(void) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *pool = NULL; + struct ol_tx_flow_pool_t tmp_pool; + + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global Pool\n"); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Total %d :: Available %d\n", + pdev->tx_desc.pool_size, pdev->tx_desc.num_free); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Invalid flow_pool %d\n", + pdev->tx_desc.num_invalid_bin); + + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool map received %d\n", + pdev->pool_stats.pool_map_count); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool unmap received %d\n", + pdev->pool_stats.pool_unmap_count); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Pkt dropped due to unavailablity of pool %d\n", + pdev->pool_stats.pkt_drop_no_pool); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Pkt dropped due to unavailablity of descriptors %d\n", + pdev->pool_stats.pkt_drop_no_desc); + + /* + * Nested spin lock. + * Always take in below order. + * flow_pool_list_lock -> flow_pool_lock + */ + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_FOREACH(pool, &pdev->tx_desc.flow_pool_list, + flow_pool_list_elem) { + cdf_spin_lock_bh(&pool->flow_pool_lock); + cdf_mem_copy(&tmp_pool, pool, sizeof(tmp_pool)); + cdf_spin_unlock_bh(&pool->flow_pool_lock); + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Flow_pool_id %d :: status %d\n", + tmp_pool.flow_pool_id, tmp_pool.status); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Total %d :: Available %d :: Deficient %d\n", + tmp_pool.flow_pool_size, tmp_pool.avail_desc, + tmp_pool.deficient_desc); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Start_TH %d :: Stop_TH %d\n", + tmp_pool.start_th, tmp_pool.stop_th); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "Member flow_id %d :: flow_type %d\n", + tmp_pool.member_flow_id, tmp_pool.flow_type); + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + } + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + return; +} + +/** + * ol_tx_clear_flow_pool_stats() - clear flow pool statistics + * + * Return: none + */ +void ol_tx_clear_flow_pool_stats(void) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: pdev is null\n", + __func__); + return; + } + cdf_mem_zero(&pdev->pool_stats, sizeof(pdev->pool_stats)); +} + +/** + * ol_tx_move_desc_n() - Move n descriptors from src_pool to dst_pool. + * @src_pool: source pool + * @dst_pool: destination pool + * @desc_move_count: descriptor move count + * + * Return: actual descriptors moved + */ +static int ol_tx_move_desc_n(struct ol_tx_flow_pool_t *src_pool, + struct ol_tx_flow_pool_t *dst_pool, + int desc_move_count) +{ + uint16_t count = 0, i; + struct ol_tx_desc_t *tx_desc; + union ol_tx_desc_list_elem_t *temp_list = NULL; + + /* Take descriptors from source pool and put it in temp_list */ + cdf_spin_lock_bh(&src_pool->flow_pool_lock); + for (i = 0; i < desc_move_count; i++) { + tx_desc = &src_pool->freelist->tx_desc; + src_pool->freelist = src_pool->freelist->next; + src_pool->avail_desc--; + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = temp_list; + temp_list = (union ol_tx_desc_list_elem_t *)tx_desc; + + } + cdf_spin_unlock_bh(&src_pool->flow_pool_lock); + + /* Take descriptors from temp_list and put it in destination pool */ + cdf_spin_lock_bh(&dst_pool->flow_pool_lock); + for (i = 0; i < desc_move_count; i++) { + if (dst_pool->deficient_desc) + dst_pool->deficient_desc--; + else + break; + tx_desc = &temp_list->tx_desc; + temp_list = temp_list->next; + tx_desc->pool = dst_pool; + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + dst_pool->freelist; + dst_pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; + dst_pool->avail_desc++; + count++; + } + cdf_spin_unlock_bh(&dst_pool->flow_pool_lock); + + /* If anything is there in temp_list put it back to source pool */ + cdf_spin_lock_bh(&src_pool->flow_pool_lock); + while (temp_list) { + tx_desc = &temp_list->tx_desc; + temp_list = temp_list->next; + tx_desc->pool = src_pool; + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + src_pool->freelist; + src_pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; + src_pool->avail_desc++; + } + cdf_spin_unlock_bh(&src_pool->flow_pool_lock); + + return count; +} + + +/** + * ol_tx_distribute_descs_to_deficient_pools() - Distribute descriptors + * @src_pool: source pool + * + * Distribute all descriptors of source pool to all + * deficient pools as per flow_pool_list. + * + * Return: 0 for sucess + */ +int +ol_tx_distribute_descs_to_deficient_pools(struct ol_tx_flow_pool_t *src_pool) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *dst_pool = NULL; + uint16_t desc_count = src_pool->avail_desc; + uint16_t desc_move_count = 0; + + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pdev is NULL\n", __func__); + return -EINVAL; + } + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_FOREACH(dst_pool, &pdev->tx_desc.flow_pool_list, + flow_pool_list_elem) { + cdf_spin_lock_bh(&dst_pool->flow_pool_lock); + if (dst_pool->deficient_desc) { + desc_move_count = + (dst_pool->deficient_desc > desc_count) ? + desc_count : dst_pool->deficient_desc; + cdf_spin_unlock_bh(&dst_pool->flow_pool_lock); + desc_move_count = ol_tx_move_desc_n(src_pool, + dst_pool, desc_move_count); + desc_count -= desc_move_count; + cdf_spin_lock_bh(&dst_pool->flow_pool_lock); + } + cdf_spin_unlock_bh(&dst_pool->flow_pool_lock); + if (desc_count == 0) + break; + } + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + return 0; +} + + +/** + * ol_tx_create_flow_pool() - create flow pool + * @flow_pool_id: flow pool id + * @flow_pool_size: flow pool size + * + * Return: flow_pool pointer / NULL for error + */ +struct ol_tx_flow_pool_t *ol_tx_create_flow_pool(uint8_t flow_pool_id, + uint16_t flow_pool_size) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *pool; + uint16_t size = 0, i; + struct ol_tx_desc_t *tx_desc; + union ol_tx_desc_list_elem_t *temp_list = NULL; + uint32_t stop_threshold = + ol_cfg_get_tx_flow_stop_queue_th(pdev->ctrl_pdev); + uint32_t start_threshold = stop_threshold + + ol_cfg_get_tx_flow_start_queue_offset(pdev->ctrl_pdev); + + if (!pdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pdev is NULL\n", __func__); + return NULL; + } + + pool = cdf_mem_malloc(sizeof(*pool)); + if (!pool) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: malloc failed\n", __func__); + return NULL; + } + + pool->flow_pool_id = flow_pool_id; + pool->flow_pool_size = flow_pool_size; + pool->status = FLOW_POOL_ACTIVE_UNPAUSED; + pool->start_th = (start_threshold * flow_pool_size)/100; + pool->stop_th = (stop_threshold * flow_pool_size)/100; + cdf_spinlock_init(&pool->flow_pool_lock); + + /* Take TX descriptor from global_pool and put it in temp_list*/ + cdf_spin_lock_bh(&pdev->tx_mutex); + if (pdev->tx_desc.num_free >= pool->flow_pool_size) + size = pool->flow_pool_size; + else + size = pdev->tx_desc.num_free; + + for (i = 0; i < size; i++) { + pdev->tx_desc.num_free--; + tx_desc = &pdev->tx_desc.freelist->tx_desc; + pdev->tx_desc.freelist = pdev->tx_desc.freelist->next; + tx_desc->pool = pool; + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = temp_list; + temp_list = (union ol_tx_desc_list_elem_t *)tx_desc; + + } + cdf_spin_unlock_bh(&pdev->tx_mutex); + + /* put temp_list to flow_pool */ + pool->freelist = temp_list; + pool->avail_desc = size; + pool->deficient_desc = pool->flow_pool_size - pool->avail_desc; + + /* Add flow_pool to flow_pool_list */ + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_INSERT_TAIL(&pdev->tx_desc.flow_pool_list, pool, + flow_pool_list_elem); + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + return pool; +} + +/** + * ol_tx_delete_flow_pool() - delete flow pool + * @pool: flow pool pointer + * + * Delete flow_pool if all tx descriptors are available. + * Otherwise put it in FLOW_POOL_INVALID state. + * + * Return: 0 for success or error + */ +int ol_tx_delete_flow_pool(struct ol_tx_flow_pool_t *pool) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + uint16_t i, size; + union ol_tx_desc_list_elem_t *temp_list = NULL; + struct ol_tx_desc_t *tx_desc = NULL; + + if (!pool) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pool is NULL\n", __func__); + return -ENOMEM; + } + + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_REMOVE(&pdev->tx_desc.flow_pool_list, pool, flow_pool_list_elem); + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + cdf_spin_lock_bh(&pool->flow_pool_lock); + if (pool->avail_desc == pool->flow_pool_size) + pool->status = FLOW_POOL_INACTIVE; + else + pool->status = FLOW_POOL_INVALID; + + /* Take all free descriptors and put it in temp_list */ + temp_list = pool->freelist; + size = pool->avail_desc; + pool->freelist = NULL; + pool->avail_desc = 0; + + if (pool->status == FLOW_POOL_INACTIVE) { + cdf_spin_unlock_bh(&pool->flow_pool_lock); + /* Free flow_pool */ + cdf_spinlock_destroy(&pool->flow_pool_lock); + cdf_mem_free(pool); + } else { /* FLOW_POOL_INVALID case*/ + pool->flow_pool_size -= size; + pool->flow_pool_id = INVALID_FLOW_ID; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + + pdev->tx_desc.num_invalid_bin++; + if (pdev->tx_desc.num_invalid_bin > MAX_INVALID_BIN) + ASSERT(0); + + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_INSERT_TAIL(&pdev->tx_desc.flow_pool_list, pool, + flow_pool_list_elem); + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + } + + /* put free descriptors to global pool */ + cdf_spin_lock_bh(&pdev->tx_mutex); + for (i = 0; i < size; i++) { + tx_desc = &temp_list->tx_desc; + temp_list = temp_list->next; + + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + pdev->tx_desc.freelist; + pdev->tx_desc.freelist = + (union ol_tx_desc_list_elem_t *)tx_desc; + pdev->tx_desc.num_free++; + + } + cdf_spin_unlock_bh(&pdev->tx_mutex); + + return 0; +} + + +/** + * ol_tx_free_invalid_flow_pool() - free invalid pool + * @pool: pool + * + * Return: 0 for success or failure + */ +int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if ((!pdev) || (!pool) || (pool->status != FLOW_POOL_INVALID)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: Invalid pool/pdev\n", __func__); + return -EINVAL; + } + + /* direclty distribute to other deficient pools */ + ol_tx_distribute_descs_to_deficient_pools(pool); + + cdf_spin_lock_bh(&pool->flow_pool_lock); + pool->flow_pool_size = pool->avail_desc; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + + pdev->tx_desc.num_invalid_bin--; + + return ol_tx_delete_flow_pool(pool); +} + +/** + * ol_tx_get_flow_pool() - get flow_pool from flow_pool_id + * @flow_pool_id: flow pool id + * + * Return: flow_pool ptr / NULL if not found + */ +struct ol_tx_flow_pool_t *ol_tx_get_flow_pool(uint8_t flow_pool_id) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *pool = NULL; + bool is_found = false; + + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_FOREACH(pool, &pdev->tx_desc.flow_pool_list, + flow_pool_list_elem) { + cdf_spin_lock_bh(&pool->flow_pool_lock); + if (pool->flow_pool_id == flow_pool_id) { + cdf_spin_unlock_bh(&pool->flow_pool_lock); + is_found = true; + break; + } + cdf_spin_unlock_bh(&pool->flow_pool_lock); + } + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + if (is_found == false) + pool = NULL; + + return pool; + +} + + +/** + * ol_tx_flow_pool_vdev_map() - Map flow_pool with vdev + * @pool: flow_pool + * @vdev_id: flow_id /vdev_id + * + * Return: none + */ +void ol_tx_flow_pool_vdev_map(struct ol_tx_flow_pool_t *pool, + uint8_t vdev_id) +{ + ol_txrx_vdev_handle vdev; + + vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (!vdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid vdev_id %d\n", + __func__, vdev_id); + return; + } + + vdev->pool = pool; + cdf_spin_lock_bh(&pool->flow_pool_lock); + pool->member_flow_id = vdev_id; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + + return; +} + +/** + * ol_tx_flow_pool_vdev_unmap() - Unmap flow_pool from vdev + * @pool: flow_pool + * @vdev_id: flow_id /vdev_id + * + * Return: none + */ +void ol_tx_flow_pool_vdev_unmap(struct ol_tx_flow_pool_t *pool, + uint8_t vdev_id) +{ + ol_txrx_vdev_handle vdev; + + vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + if (!vdev) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid vdev_id %d\n", + __func__, vdev_id); + return; + } + + vdev->pool = NULL; + cdf_spin_lock_bh(&pool->flow_pool_lock); + pool->member_flow_id = INVALID_FLOW_ID; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + + return; +} + +/** + * ol_tx_flow_pool_map_handler() - Map flow_id with pool of descriptors + * @flow_id: flow id + * @flow_type: flow type + * @flow_pool_id: pool id + * @flow_pool_size: pool size + * + * Process below target to host message + * HTT_T2H_MSG_TYPE_FLOW_POOL_MAP + * + * Return: none + */ +void ol_tx_flow_pool_map_handler(uint8_t flow_id, uint8_t flow_type, + uint8_t flow_pool_id, uint16_t flow_pool_size) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *pool; + uint8_t pool_create = 0; + enum htt_flow_type type = flow_type; + + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: flow_id %d flow_type %d flow_pool_id %d flow_pool_size %d\n", + __func__, flow_id, flow_type, flow_pool_id, flow_pool_size); + + if (cdf_unlikely(!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pdev is NULL", __func__); + return; + } + pdev->pool_stats.pool_map_count++; + + pool = ol_tx_get_flow_pool(flow_pool_id); + if (!pool) { + pool = ol_tx_create_flow_pool(flow_pool_id, flow_pool_size); + if (pool == NULL) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: creation of flow_pool %d size %d failed\n", + __func__, flow_pool_id, flow_pool_size); + return; + } + pool_create = 1; + } + + switch (type) { + + case FLOW_TYPE_VDEV: + ol_tx_flow_pool_vdev_map(pool, flow_id); + break; + default: + if (pool_create) + ol_tx_delete_flow_pool(pool); + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: flow type %d not supported !!!\n", + __func__, type); + break; + } + + return; +} + +/** + * ol_tx_flow_pool_unmap_handler() - Unmap flow_id from pool of descriptors + * @flow_id: flow id + * @flow_type: flow type + * @flow_pool_id: pool id + * + * Process below target to host message + * HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP + * + * Return: none + */ +void ol_tx_flow_pool_unmap_handler(uint8_t flow_id, uint8_t flow_type, + uint8_t flow_pool_id) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_tx_flow_pool_t *pool; + enum htt_flow_type type = flow_type; + + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, + "%s: flow_id %d flow_type %d flow_pool_id %d\n", + __func__, flow_id, flow_type, flow_pool_id); + + if (cdf_unlikely(!pdev)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: pdev is NULL", __func__); + return; + } + pdev->pool_stats.pool_unmap_count++; + + pool = ol_tx_get_flow_pool(flow_pool_id); + if (!pool) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: flow_pool not available flow_pool_id %d\n", + __func__, type); + return; + } + + switch (type) { + + case FLOW_TYPE_VDEV: + ol_tx_flow_pool_vdev_unmap(pool, flow_id); + break; + default: + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: flow type %d not supported !!!\n", + __func__, type); + return; + } + + /* only delete if all descriptors are available */ + ol_tx_delete_flow_pool(pool); + + return; +} + + diff --git a/core/dp/txrx/ol_txrx_internal.h b/core/dp/txrx/ol_txrx_internal.h new file mode 100644 index 000000000000..30315e64ce1b --- /dev/null +++ b/core/dp/txrx/ol_txrx_internal.h @@ -0,0 +1,737 @@ +/* + * 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_TXRX_INTERNAL__H_ +#define _OL_TXRX_INTERNAL__H_ + +#include /* cdf_assert */ +#include /* cdf_nbuf_t */ +#include /* cdf_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) \ + cdf_atomic_dec_and_test(&tx_desc->ref_cnt) +#define OL_TX_DESC_REF_INIT(tx_desc) cdf_atomic_init(&tx_desc->ref_cnt) +#define OL_TX_DESC_REF_INC(tx_desc) cdf_atomic_inc(&tx_desc->ref_cnt) +#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) cdf_assert((condition)) +#else +#define TXRX_ASSERT1(condition) +#endif + +#if TXRX_ASSERT_LEVEL > 1 +#define TXRX_ASSERT2(condition) cdf_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 /* cdf_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) \ + cdf_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) \ + cdf_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, ...) cdf_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, ...) cdf_print(fmt, ## __VA_ARGS__) +#else +#define TX_SCHED_DEBUG_PRINT(fmt, ...) +#endif +#define TX_SCHED_DEBUG_PRINT_ALWAYS(fmt, ...) cdf_print(fmt, ## __VA_ARGS__) + +#define OL_TXRX_LIST_APPEND(head, tail, elem) \ + do { \ + if (!(head)) { \ + (head) = (elem); \ + } else { \ + cdf_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, + cdf_nbuf_t *mpdu_tail, cdf_nbuf_t *next_mpdu) +{ + htt_pdev_handle htt_pdev = pdev->htt_pdev; + cdf_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 = cdf_nbuf_next(msdu); + TXRX_ASSERT2(msdu); + } + /* msdu now points to the last MSDU within the first MPDU */ + *mpdu_tail = msdu; + *next_mpdu = cdf_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) \ + cdf_mem_set(&((_pdev)->stats), sizeof((_pdev)->stats), 0x0) +#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, cdf_nbuf_len(netbuf)); \ + } while (0) + +/* conditional defs based on verbosity level */ + + +#define TXRX_STATS_MSDU_LIST_INCR(pdev, field, netbuf_list) \ + do { \ + cdf_nbuf_t tmp_list = netbuf_list; \ + while (tmp_list) { \ + TXRX_STATS_MSDU_INCR(pdev, field, tmp_list); \ + tmp_list = cdf_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); \ + else if (status == htt_tx_status_discard) \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.target_discard, \ + netbuf); \ + else if (status == htt_tx_status_no_ack) \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.no_ack, netbuf); \ + else if (status == htt_tx_status_download_fail) \ + TXRX_STATS_MSDU_INCR(pdev, tx.dropped.download_fail, \ + netbuf); \ + else \ + /* NO-OP */; \ + } while (0) + +#define TXRX_STATS_UPDATE_TX_COMP_HISTOGRAM(_pdev, _p_cntrs) \ + do { \ + if (_p_cntrs == 1) { \ + TXRX_STATS_ADD(_pdev, pub.tx.comp_histogram.pkts_1, 1);\ + } else if (_p_cntrs > 2 && _p_cntrs <= 10) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_2_10, 1); \ + } else if (_p_cntrs > 10 && _p_cntrs <= 20) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_11_20, 1); \ + } else if (_p_cntrs > 20 && _p_cntrs <= 30) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_21_30, 1); \ + } else if (_p_cntrs > 30 && _p_cntrs <= 40) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_31_40, 1); \ + } else if (_p_cntrs > 40 && _p_cntrs <= 50) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_41_50, 1); \ + } else if (_p_cntrs > 50 && _p_cntrs <= 60) { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_51_60, 1); \ + } else { \ + TXRX_STATS_ADD(_pdev, \ + pub.tx.comp_histogram.pkts_61_plus, 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) + + +/*--- 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, + uint8_t tid, + uint16_t reorder_idx, + uint16_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, + uint16_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(uint16_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, + cdf_nbuf_t frm, + enum ol_txrx_frm_dump_options display_options, int max_len) +{ +#define TXRX_FRM_DUMP_MAX_LEN 128 + uint8_t local_buf[TXRX_FRM_DUMP_MAX_LEN] = { 0 }; + uint8_t *p; + + if (name) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, "%s\n", + name); + } + while (frm) { + p = cdf_nbuf_data(frm); + if (display_options & ol_txrx_frm_dump_tcp_seq) { + int tcp_offset; + int l2_hdr_size; + uint16_t ethtype; + uint8_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? + */ + ethtype = (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; + ethtype = (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; + ethtype = (llc_hdr->ethertype[0] << 8) | + llc_hdr->ethertype[1]; + } + if (ethtype == 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 (ethtype == 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 { + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_TRACE_LEVEL_INFO, + "frame %p non-IP ethertype (%x)\n", + frm, ethtype); + goto NOT_IP_TCP; + } + if (ip_prot == IP_PROTOCOL_TCP) { +#if NEVERDEFINED + struct tcp_hdr_t *tcp_hdr; + uint32_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); + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_TRACE_LEVEL_INFO, + "frame %p: TCP seq num = %d\n", frm, + tcp_seq_num); +#else + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_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 { + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_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 > cdf_nbuf_len(frm)) + len_lim = cdf_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 = + cdf_nbuf_get_frag_len(frm, frag_num); + if (frag_bytes > len_lim - i) + frag_bytes = len_lim - i; + if (frag_bytes > 0) { + p = cdf_nbuf_get_frag_vaddr(frm, + frag_num); + cdf_mem_copy(&local_buf[i], p, + frag_bytes); + } + frag_num++; + i += frag_bytes; + } + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + "frame %p data (%p), hex dump of bytes 0-%d of %d:\n", + frm, p, len_lim - 1, (int)cdf_nbuf_len(frm)); + p = local_buf; + while (len_lim > 16) { + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + " " /* indent */); + while (len_lim > 0) { + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_TRACE_LEVEL_INFO, "%02x ", *p); + p++; + len_lim--; + } + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO, + "\n"); + } + frm = cdf_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_frame_type(pdev->ctrl_pdev) == \ + wlan_frm_fmt_native_wifi) { \ + /* For windows, it is always native wifi header .*/ \ + wh = (struct ieee80211_frame *)cdf_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; \ + if (rx_status == htt_rx_status_decrypt_err) \ + err_type = OL_RX_ERR_DECRYPT; \ + else if (rx_status == htt_rx_status_tkip_mic_err) \ + err_type = OL_RX_ERR_TKIP_MIC; \ + else if (rx_status == htt_rx_status_mpdu_length_err) \ + err_type = OL_RX_ERR_MPDU_LENGTH; \ + else if (rx_status == htt_rx_status_mpdu_encrypt_required_err) \ + err_type = OL_RX_ERR_ENCRYPT_REQUIRED; \ + else if (rx_status == htt_rx_status_err_dup) \ + err_type = OL_RX_ERR_DUP; \ + else if (rx_status == htt_rx_status_err_fcs) \ + err_type = OL_RX_ERR_FCS; \ + else \ + err_type = OL_RX_ERR_UNKNOWN; \ + \ + 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 { \ + cdf_spin_lock_bh(&peer->vdev->pdev->peer_stat_mutex); \ + peer->stats.tx_or_rx.frms.type += 1; \ + peer->stats.tx_or_rx.bytes.type += cdf_nbuf_len(msdu); \ + cdf_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; \ + uint8_t *dest_addr; \ + if (pdev->frame_format == wlan_frm_fmt_802_3) { \ + dest_addr = cdf_nbuf_data(msdu); \ + } else { /* 802.11 format */ \ + struct ieee80211_frame *frm; \ + frm = (struct ieee80211_frame *) cdf_nbuf_data(msdu); \ + if (vdev->opmode == wlan_op_mode_ap) { \ + dest_addr = (uint8_t *) &(frm->i_addr1[0]); \ + } else { \ + dest_addr = (uint8_t *) &(frm->i_addr3[0]); \ + } \ + } \ + if (cdf_unlikely(IEEE80211_IS_BROADCAST(dest_addr))) { \ + OL_TXRX_PEER_STATS_UPDATE_BASE(peer, tx_or_rx, \ + bcast, msdu); \ + } else if (cdf_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) \ + cdf_spinlock_init(&pdev->peer_stat_mutex) +#define OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev) \ + cdf_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 + +#if defined(FEATURE_TSO_DEBUG) +#define TXRX_STATS_TSO_RESET_MSDU(pdev) \ + do { \ + int idx = TXRX_STATS_TSO_MSDU_IDX(pdev);\ + pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].num_seg = 0; \ + pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].tso_seg_idx = 0; \ + } while (0) + +#define TXRX_STATS_TSO_MSDU_IDX(pdev) \ + pdev->stats.pub.tx.tso.tso_info.tso_msdu_idx + +#define TXRX_STATS_TSO_MSDU(pdev, idx) \ + pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx] + +#define TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, idx) \ + pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].num_seg + +#define TXRX_STATS_TSO_CURR_MSDU(pdev) \ + TXRX_STATS_TSO_MSDU(pdev, TXRX_STATS_TSO_MSDU_IDX(pdev)) + +#define TXRX_STATS_TSO_INC_MSDU_IDX(pdev) \ + do { \ + TXRX_STATS_TSO_MSDU_IDX(pdev)++; \ + TXRX_STATS_TSO_MSDU_IDX(pdev) &= NUM_MAX_TSO_MSDUS_MASK; \ + } while (0) + +#define TXRX_STATS_TSO_SEG_IDX(pdev) \ + TXRX_STATS_TSO_CURR_MSDU(pdev).tso_seg_idx + +#define TXRX_STATS_TSO_INC_SEG(pdev) \ + TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg++ + +#define TXRX_STATS_TSO_RST_SEG(pdev) \ + TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg = 0 + +#define TXRX_STATS_TSO_RST_SEG_IDX(pdev) \ + TXRX_STATS_TSO_CURR_MSDU(pdev).tso_seg_idx = 0 + +#define TXRX_STATS_TSO_SEG(pdev, msdu_idx, seg_idx) \ + TXRX_STATS_TSO_MSDU(pdev, msdu_idx).tso_segs[seg_idx] + +#define TXRX_STATS_TSO_CURR_SEG(pdev) \ + TXRX_STATS_TSO_SEG(pdev, TXRX_STATS_TSO_MSDU_IDX(pdev), \ + TXRX_STATS_TSO_SEG_IDX(pdev)) \ + +#define TXRX_STATS_TSO_INC_SEG_IDX(pdev) \ + do { \ + TXRX_STATS_TSO_SEG_IDX(pdev)++; \ + TXRX_STATS_TSO_SEG_IDX(pdev) &= NUM_MAX_TSO_SEGS_MASK; \ + } while (0) + +#define TXRX_STATS_TSO_SEG_UPDATE(pdev, tso_seg) \ + (TXRX_STATS_TSO_CURR_SEG(pdev) = tso_seg) + +#else +#define TXRX_STATS_TSO_RESET_MSDU(pdev) /* no-op */ +#define TXRX_STATS_TSO_MSDU_IDX(pdev) /* no-op */ +#define TXRX_STATS_TSO_MSDU(pdev, idx) /* no-op */ +#define TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, idx) /* no-op */ +#define TXRX_STATS_TSO_CURR_MSDU(pdev) /* no-op */ +#define TXRX_STATS_TSO_INC_MSDU_IDX(pdev) /* no-op */ +#define TXRX_STATS_TSO_SEG_IDX(pdev) /* no-op */ +#define TXRX_STATS_TSO_SEG(pdev, msdu_idx, seg_idx) /* no-op */ +#define TXRX_STATS_TSO_CURR_SEG(pdev) /* no-op */ +#define TXRX_STATS_TSO_INC_SEG_IDX(pdev) /* no-op */ +#define TXRX_STATS_TSO_SEG_UPDATE(pdev, tso_seg) /* no-op */ +#define TXRX_STATS_TSO_INC_SEG(pdev) /* no-op */ +#define TXRX_STATS_TSO_RST_SEG(pdev) /* no-op */ +#define TXRX_STATS_TSO_RST_SEG_IDX(pdev) /* no-op */ + +#endif /* FEATURE_TSO_DEBUG */ + +#endif /* _OL_TXRX_INTERNAL__H_ */ diff --git a/core/dp/txrx/ol_txrx_peer_find.c b/core/dp/txrx/ol_txrx_peer_find.c new file mode 100644 index 000000000000..1c743f7d5c33 --- /dev/null +++ b/core/dp/txrx/ol_txrx_peer_find.c @@ -0,0 +1,494 @@ +/* + * 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 /* uint32_t, etc. */ +#include /* cdf_mem_malloc, etc. */ +#include /* cdf_device_t, cdf_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, uint16_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 = + cdf_mem_malloc(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) +{ + cdf_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); + cdf_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); + cdf_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, + uint8_t *peer_mac_addr, + int mac_addr_is_aligned, + uint8_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 { + cdf_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); + cdf_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 */ + cdf_atomic_inc(&peer->ref_cnt); + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + return peer; + } + } + cdf_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, + uint8_t *peer_mac_addr, + int mac_addr_is_aligned, + uint8_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 { + cdf_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); + cdf_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 */ + cdf_atomic_inc(&peer->ref_cnt); + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + return peer; + } + } + cdf_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. + */ + /* cdf_spin_lock_bh(&pdev->peer_ref_mutex); */ + TAILQ_REMOVE(&pdev->peer_hash.bins[index], peer, hash_list_elem); + /* cdf_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. + */ + cdf_atomic_init(&peer->ref_cnt); /* set to 0 */ + cdf_atomic_inc(&peer->ref_cnt); /* incr to 1 */ + 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 = cdf_mem_malloc(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. + */ + cdf_mem_set(pdev->peer_id_to_obj_map, peer_map_size, 0); + + return 0; /* success */ +} + +static void ol_txrx_peer_find_map_detach(struct ol_txrx_pdev_t *pdev) +{ + cdf_mem_free(pdev->peer_id_to_obj_map); +} + +static inline void +ol_txrx_peer_find_add_id(struct ol_txrx_pdev_t *pdev, + uint8_t *peer_mac_addr, uint16_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) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Delete Peer %p\n", + __func__, peer); + ol_txrx_peer_unref_delete(peer); + } + if (ol_txrx_peer_find_add_id_to_obj(peer, peer_id)) { + /* TBDXXX: assert for now */ + cdf_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, + uint16_t peer_id, + uint8_t vdev_id, uint8_t *peer_mac_addr, int tx_ready) +{ + ol_txrx_peer_find_add_id(pdev, peer_mac_addr, peer_id); +} + +void ol_txrx_peer_tx_ready_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id) +{ +} + +void ol_rx_peer_unmap_handler(ol_txrx_pdev_handle pdev, uint16_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; + + cdf_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) { + cdf_atomic_inc(&vdev->last_real_peer->ref_cnt); + peer = vdev->last_real_peer; + } else { + peer = NULL; + } + cdf_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; + + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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]) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%*sid %d -> %p\n", + indent + 4, " ", i, + pdev->peer_id_to_obj_map[i]); + } + } + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_TXRX, + CDF_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/core/dp/txrx/ol_txrx_peer_find.h b/core/dp/txrx/ol_txrx_peer_find.h new file mode 100644 index 000000000000..25886cae1cf0 --- /dev/null +++ b/core/dp/txrx/ol_txrx_peer_find.h @@ -0,0 +1,116 @@ +/* + * 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_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 bool, + * 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, + uint16_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, + uint8_t *peer_mac_addr, + int mac_addr_is_aligned, + uint8_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, + uint8_t *peer_mac_addr, + int mac_addr_is_aligned, + uint8_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/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h new file mode 100644 index 000000000000..50a4bd9eeb19 --- /dev/null +++ b/core/dp/txrx/ol_txrx_types.h @@ -0,0 +1,1018 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* TAILQ */ +#include /* A_UINT8 */ +#include /* htt_sec_type, htt_pkt_type, etc. */ +#include /* cdf_atomic_t */ +#include /* wdi_event_subscribe */ +#include /* cdf_softirq_timer_t */ +#include /* cdf_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 +#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 cdf_spinlock_t +#define OL_RX_MUTEX_TYPE cdf_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 */ + +enum privacy_filter { + PRIVACY_FILTER_ALWAYS, + PRIVACY_FILTER_KEY_UNAVAILABLE, +}; + +enum privacy_filter_packet_type { + PRIVACY_FILTER_PACKET_UNICAST, + PRIVACY_FILTER_PACKET_MULTICAST, + PRIVACY_FILTER_PACKET_BOTH +}; + +struct privacy_exemption { + /* ethertype - + * type of ethernet frames this filter applies to, in host byte order + */ + uint16_t ether_type; + enum privacy_filter filter_type; + enum privacy_filter_packet_type packet_type; +}; + +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 hdr added */ + ol_tx_frm_no_free, /* frame requires special tx completion callback */ +}; + +struct ol_tx_desc_t { + cdf_nbuf_t netbuf; + void *htt_tx_desc; +#ifdef WLAN_FEATURE_FASTPATH + uint16_t id; +#endif /* WLAN_FEATURE_FASTPATH */ + uint32_t htt_tx_desc_paddr; +#if defined(HELIUMPLUS_PADDR64) + void *htt_frag_desc; /* struct msdu_ext_desc_t * */ + uint32_t htt_frag_desc_paddr; +#endif /* defined(HELIUMPLUS_PADDR64) */ + uint32_t index; + cdf_atomic_t ref_cnt; + enum htt_tx_status status; + +#ifdef QCA_COMPUTE_TX_DELAY + uint32_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. + */ + uint8_t pkt_type; +#ifdef QCA_SUPPORT_SW_TXRX_ENCAP + /* used by tx encap, to restore the os buf start offset + after tx complete */ + uint8_t orig_l2_hdr_bytes; +#endif +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + struct ol_txrx_vdev_t *vdev; +#endif +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + struct ol_tx_flow_pool_t *pool; +#endif + void *tso_desc; +}; + +typedef TAILQ_HEAD(some_struct_name, ol_tx_desc_t) ol_tx_desc_list; + +union ol_tx_desc_list_elem_t { + union ol_tx_desc_list_elem_t *next; + struct ol_tx_desc_t tx_desc; +}; + +union ol_txrx_align_mac_addr_t { + uint8_t raw[OL_TXRX_MAC_ADDR_LEN]; + struct { + uint16_t bytes_ab; + uint16_t bytes_cd; + uint16_t bytes_ef; + } align2; + struct { + uint32_t bytes_abcd; + uint16_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; + uint32_t timestamp_ms; + struct ol_txrx_peer_t *peer; + uint8_t tid; + uint8_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) + +struct ol_tx_reorder_cat_timeout_t { + TAILQ_HEAD(, ol_rx_reorder_timeout_list_elem_t) virtual_timer_list; + cdf_softirq_timer_t timer; + uint32_t duration_ms; + struct ol_txrx_pdev_t *pdev; +}; + +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; + struct cdf_tso_info_t tso_info; +}; + +enum { + ol_tx_aggr_untried = 0, + ol_tx_aggr_enabled, + ol_tx_aggr_disabled, + ol_tx_aggr_retry, + ol_tx_aggr_in_progress, +}; + +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; + uint8_t aggr_state; + struct { + uint8_t total; + /* pause requested by ctrl SW rather than txrx SW */ + uint8_t by_ctrl; + } paused_count; + uint8_t ext_tid; + uint16_t frms; + uint32_t bytes; + ol_tx_desc_list head; + enum ol_tx_queue_status flag; +}; + +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 { + uint32_t active_bitmap; + uint16_t credit; + uint8_t num_cats_active; + uint8_t data[1]; +}; + +struct ol_tx_log_queue_add_t { + uint8_t num_frms; + uint8_t tid; + uint16_t peer_id; + uint16_t num_bytes; +}; + +struct ol_mac_addr { + uint8_t mac_addr[OL_TXRX_MAC_ADDR_LEN]; +}; + +#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 uint8_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 { + uint64_t transmit_sum_ticks; + uint64_t queue_sum_ticks; + uint32_t transmit_num; + uint32_t queue_num; + } avgs; + uint16_t hist_bins_queue[QCA_TX_DELAY_HIST_INTERNAL_BINS]; +}; + +#endif /* QCA_COMPUTE_TX_DELAY */ + +/* Thermal Mitigation */ + +enum throttle_level { + THROTTLE_LEVEL_0, + THROTTLE_LEVEL_1, + THROTTLE_LEVEL_2, + THROTTLE_LEVEL_3, + /* Invalid */ + THROTTLE_LEVEL_MAX, +}; + +enum throttle_phase { + THROTTLE_PHASE_OFF, + THROTTLE_PHASE_ON, + /* Invalid */ + THROTTLE_PHASE_MAX, +}; + +#define THROTTLE_TX_THRESHOLD (100) + +typedef void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *osif_ctxt); + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + +/** + * enum flow_pool_status - flow pool status + * @FLOW_POOL_ACTIVE_UNPAUSED : pool is active (can take/put descriptors) + * and network queues are unpaused + * @FLOW_POOL_ACTIVE_PAUSED: pool is active (can take/put descriptors) + * and network queues are paused + * @FLOW_POOL_INVALID: pool is invalid (put descriptor) + * @FLOW_POOL_INACTIVE: pool is inactive (pool is free) + */ +enum flow_pool_status { + FLOW_POOL_ACTIVE_UNPAUSED = 0, + FLOW_POOL_ACTIVE_PAUSED = 1, + FLOW_POOL_INVALID = 2, + FLOW_POOL_INACTIVE = 3, +}; + +/** + * struct ol_txrx_pool_stats - flow pool related statistics + * @pool_map_count: flow pool map received + * @pool_unmap_count: flow pool unmap received + * @pkt_drop_no_pool: packets dropped due to unavailablity of pool + * @pkt_drop_no_desc: packets dropped due to unavailablity of descriptors + */ +struct ol_txrx_pool_stats { + uint16_t pool_map_count; + uint16_t pool_unmap_count; + uint16_t pkt_drop_no_pool; + uint16_t pkt_drop_no_desc; +}; + +/** + * struct ol_tx_flow_pool_t - flow_pool info + * @flow_pool_list_elem: flow_pool_list element + * @flow_pool_lock: flow_pool lock + * @flow_pool_id: flow_pool id + * @flow_pool_size: flow_pool size + * @avail_desc: available descriptors + * @deficient_desc: deficient descriptors + * @status: flow pool status + * @flow_type: flow pool type + * @member_flow_id: member flow id + * @stop_th: stop threshold + * @start_th: start threshold + * @freelist: tx descriptor freelist + */ +struct ol_tx_flow_pool_t { + TAILQ_ENTRY(ol_tx_flow_pool_t) flow_pool_list_elem; + cdf_spinlock_t flow_pool_lock; + uint8_t flow_pool_id; + uint16_t flow_pool_size; + uint16_t avail_desc; + uint16_t deficient_desc; + enum flow_pool_status status; + enum htt_flow_type flow_type; + uint8_t member_flow_id; + uint16_t stop_th; + uint16_t start_th; + union ol_tx_desc_list_elem_t *freelist; +}; + +#endif + +/* + * 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 */ + cdf_device_t osdev; + + htt_pdev_handle htt_pdev; + +#ifdef WLAN_FEATURE_FASTPATH + struct CE_handle *ce_tx_hdl; /* Handle to Tx packet posting CE */ + struct CE_handle *ce_htt_msg_hdl; /* Handle to TxRx completion CE */ +#endif /* WLAN_FEATURE_FASTPATH */ + + 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 */ + uint8_t sw_tx_encap; + uint8_t sw_rx_decap; + uint8_t target_tx_tran_caps; + uint8_t target_rx_tran_caps; + /* llc process */ + uint8_t sw_tx_llc_proc_enable; + uint8_t sw_rx_llc_proc_enable; + /* A-MSDU */ + uint8_t sw_subfrm_hdr_recovery_enable; + /* Protected Frame bit handling */ + uint8_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 + */ + cdf_atomic_t target_tx_credit; + cdf_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; + uint32_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; + cdf_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, cdf_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; + + struct { + uint16_t pool_size; + uint16_t num_free; + union ol_tx_desc_list_elem_t *array; + union ol_tx_desc_list_elem_t *freelist; +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + uint8_t num_invalid_bin; + cdf_spinlock_t flow_pool_list_lock; + TAILQ_HEAD(flow_pool_list_t, ol_tx_flow_pool_t) flow_pool_list; +#endif + } tx_desc; + +#if defined(QCA_LL_TX_FLOW_CONTROL_V2) + struct ol_txrx_pool_stats pool_stats; + uint32_t num_msdu_desc; +#ifdef QCA_LL_TX_FLOW_GLOBAL_MGMT_POOL + struct ol_tx_flow_pool_t *mgmt_pool; +#endif +#endif + + 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; + + struct { + struct { + struct { + struct { + uint64_t ppdus; + uint64_t mpdus; + } normal; + struct { + /* + * mpdu_bad is general - + * replace it with the specific counters + * below + */ + uint64_t mpdu_bad; + /* uint64_t mpdu_fcs; */ + /* uint64_t mpdu_duplicate; */ + /* uint64_t mpdu_pn_replay; */ + /* uint64_t mpdu_bad_sender; */ + /* ^ comment: peer not found */ + /* uint64_t mpdu_flushed; */ + /* uint64_t msdu_defrag_mic_err; */ + uint64_t msdu_mc_dup_drop; + } err; + } rx; + } priv; + struct ol_txrx_stats pub; + } stats; + +#if defined(ENABLE_RX_REORDER_TRACE) + struct { + uint32_t mask; + uint32_t idx; + uint64_t cnt; +#define TXRX_RX_REORDER_TRACE_SIZE_LOG2 8 /* 256 entries */ + struct { + uint16_t reorder_idx; + uint16_t seq_num; + uint8_t num_mpdus; + uint8_t tid; + } *data; + } rx_reorder_trace; +#endif /* ENABLE_RX_REORDER_TRACE */ + +#if defined(ENABLE_RX_PN_TRACE) + struct { + uint32_t mask; + uint32_t idx; + uint64_t cnt; +#define TXRX_RX_PN_TRACE_SIZE_LOG2 5 /* 32 entries */ + struct { + struct ol_txrx_peer_t *peer; + uint32_t pn32; + uint16_t seq_num; + uint8_t unicast; + uint8_t tid; + } *data; + } rx_pn_trace; +#endif /* ENABLE_RX_PN_TRACE */ + +#if defined(PERE_IP_HDR_ALIGNMENT_WAR) + bool host_80211_enable; +#endif + + /* + * 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 { + cdf_atomic_t rsrc_cnt; + /* threshold_lo - when to start tx desc margin replenishment */ + uint16_t rsrc_threshold_lo; + /* threshold_hi - where to stop during tx desc margin + replenishment */ + uint16_t rsrc_threshold_hi; + } tx_queue; + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS + cdf_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; + cdf_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 { + cdf_spinlock_t mutex; + struct { + struct ol_tx_delay_data copies[2]; /* ping-pong */ + int in_progress_idx; + uint32_t avg_start_time_ticks; + } cats[QCA_TX_DELAY_NUM_CATEGORIES]; + uint32_t tx_compl_timestamp_ticks; + uint32_t avg_period_ticks; + uint32_t hist_internal_bin_width_mult; + uint32_t hist_internal_bin_width_shift; + } tx_delay; + + uint16_t packet_count[QCA_TX_DELAY_NUM_CATEGORIES]; + uint16_t packet_loss_count[QCA_TX_DELAY_NUM_CATEGORIES]; + +#endif /* QCA_COMPUTE_TX_DELAY */ + + struct { + cdf_spinlock_t mutex; + /* timer used to monitor the throttle "on" phase and + "off" phase */ + cdf_softirq_timer_t phase_timer; + /* timer used to send tx frames */ + cdf_softirq_timer_t tx_timer; + /* This is the time in ms of the throttling window, it will + * include an "on" phase and an "off" phase */ + uint32_t throttle_period_ms; + /* Current throttle level set by the client ex. level 0, + level 1, etc */ + enum throttle_level current_throttle_level; + /* Index that points to the phase within the throttle period */ + enum throttle_phase current_throttle_phase; + /* Maximum number of frames to send to the target at one time */ + uint32_t tx_threshold; + /* stores time in ms of on/off phase for each throttle level */ + int throttle_time_ms[THROTTLE_LEVEL_MAX][THROTTLE_PHASE_MAX]; + /* mark true if traffic is paused due to thermal throttling */ + bool is_paused; + } tx_throttle; + +#ifdef IPA_OFFLOAD + ipa_uc_op_cb_type ipa_uc_op_cb; + void *osif_dev; +#endif /* IPA_UC_OFFLOAD */ + +#if defined(FEATURE_TSO) + struct { + uint16_t pool_size; + uint16_t num_free; + struct cdf_tso_seg_elem_t *array; + struct cdf_tso_seg_elem_t *freelist; + /* tso mutex */ + OL_TX_MUTEX_TYPE tso_mutex; + } tso_seg_pool; +#endif + uint8_t ocb_peer_valid; + struct ol_txrx_peer_t *ocb_peer; + ol_tx_pause_callback_fp pause_cb; + + struct { + void *lro_data; + void (*lro_flush_cb)(void *); + } lro_info; +}; + +struct ol_txrx_ocb_chan_info { + uint32_t chan_freq; + uint16_t disable_rx_stats_hdr:1; +}; + +struct ol_txrx_vdev_t { + struct ol_txrx_pdev_t *pdev; /* pdev - the physical device that is + the parent of this virtual device */ + uint8_t vdev_id; /* ID used to specify a particular vdev + to the target */ + void *osif_dev; + union ol_txrx_align_mac_addr_t mac_addr; /* MAC address */ + /* tx paused - NO LONGER NEEDED? */ + TAILQ_ENTRY(ol_txrx_vdev_t) vdev_list_elem; /* node in the pdev's list + of vdevs */ + TAILQ_HEAD(peer_list_t, ol_txrx_peer_t) peer_list; + struct ol_txrx_peer_t *last_real_peer; /* last real peer created for + this vdev (not "self" + pseudo-peer) */ + ol_txrx_tx_fp tx; /* transmit function used by this vdev */ + + 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 */ + uint32_t safemode; + + /* rx filter related */ + uint32_t drop_unenc; + struct privacy_exemption privacy_filters[MAX_PRIVACY_FILTERS]; + uint32_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 + + struct { + struct { + cdf_nbuf_t head; + cdf_nbuf_t tail; + int depth; + } txq; + uint32_t paused_reason; + cdf_spinlock_t mutex; + cdf_softirq_timer_t timer; + int max_q_depth; + bool is_q_paused; + bool is_q_timer_on; + uint32_t q_pause_cnt; + uint32_t q_unpause_cnt; + uint32_t q_overflow_cnt; + } ll_pause; + bool disable_intrabss_fwd; + cdf_atomic_t os_q_paused; + uint16_t tx_fl_lwm; + uint16_t tx_fl_hwm; + cdf_spinlock_t flow_control_lock; + ol_txrx_tx_flow_control_fp osif_flow_control_cb; + void *osif_fc_ctx; + +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + cdf_atomic_t tx_desc_count; +#endif + uint16_t wait_on_peer_id; + cdf_event_t wait_delete_comp; +#if defined(FEATURE_TSO) + struct { + int pool_elems; /* total number of elements in the pool */ + int alloc_cnt; /* number of allocated elements */ + uint32_t *freelist; /* free list of cdf_tso_seg_elem_t */ + } tso_pool_t; +#endif + + /* 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; + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + struct ol_tx_flow_pool_t *pool; +#endif +}; + +struct ol_rx_reorder_array_elem_t { + cdf_nbuf_t head; + cdf_nbuf_t tail; +}; + +struct ol_rx_reorder_t { + uint8_t win_sz; + uint8_t win_sz_mask; + uint8_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; + uint32_t defrag_timeout_ms; + /* get back to parent ol_txrx_peer_t when ol_rx_reorder_t is in a + * waitlist */ + uint16_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; + + cdf_atomic_t ref_cnt; + cdf_atomic_t delete_in_progress; + cdf_atomic_t flush_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; + cdf_spinlock_t peer_info_lock; + ol_rx_callback_fp osif_rx; + cdf_spinlock_t bufq_lock; + struct list_head cached_bufq; + + ol_tx_filter_func tx_filter; + + /* peer ID(s) for this peer */ + uint16_t peer_ids[MAX_NUM_PEER_ID_PER_PEER]; +#ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID + uint16_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]; + uint8_t tids_last_pn_valid[OL_TXRX_NUM_EXT_TIDS]; + uint16_t tids_next_rel_idx[OL_TXRX_NUM_EXT_TIDS]; + uint16_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; + uint32_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, cdf_nbuf_t msdu_list); + +#ifdef QCA_ENABLE_OL_TXRX_PEER_STATS + ol_txrx_peer_stats_t stats; +#endif + int16_t rssi_dbm; + + /* NAWDS Flag and Bss Peer bit */ + uint16_t nawds_enabled:1, bss_peer:1, valid:1; + + /* QoS info */ + uint8_t qos_capable; + /* U-APSD tid mask */ + uint8_t uapsd_mask; + /*flag indicating key installed */ + uint8_t keyinstalled; + + /* Bit to indicate if PN check is done in fw */ + cdf_atomic_t fw_pn_check; + +#ifdef WLAN_FEATURE_11W + /* PN counter for Robust Management Frames */ + uint64_t last_rmf_pn; + uint32_t rmf_pn_replays; + uint8_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; +}; + +#endif /* _OL_TXRX_TYPES__H_ */ diff --git a/core/dp/txrx/txrx.h b/core/dp/txrx/txrx.h new file mode 100644 index 000000000000..a9808f19be0e --- /dev/null +++ b/core/dp/txrx/txrx.h @@ -0,0 +1,235 @@ +/* + * 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_H +#define TXRX_H + +#include "cds_api.h" +#include "cdf_nbuf.h" +#include "csr_api.h" +#include "sap_api.h" +#include "cdf_nbuf.h" +#include "ol_txrx_osif_api.h" + +/* wait on peer deletion timeout value in milliseconds */ +#define PEER_DELETION_TIMEOUT 500 + +enum txrx_wmm_ac { + TXRX_WMM_AC_VO, + TXRX_WMM_AC_VI, + TXRX_WMM_AC_BK, + TXRX_WMM_AC_BE, + + 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; + +CDF_STATUS wlan_register_mgmt_client(void *pdev_txrx, + CDF_STATUS (*rx_mgmt)(void *g_cdsctx, + void *buf)); + +typedef void (*ol_txrx_vdev_delete_cb)(void *context); + +/** + * @typedef ol_txrx_tx_fp + * @brief top-level transmit function + */ +typedef cdf_nbuf_t +(*ol_txrx_tx_fp)(struct ol_txrx_vdev_t *vdev, cdf_nbuf_t msdu_list); + +typedef void +(*ol_txrx_mgmt_tx_cb)(void *ctxt, cdf_nbuf_t tx_mgmt_frm, int had_error); + +/* If RSSI realm is changed, send notification to Clients, SME, HDD */ +typedef CDF_STATUS (*wlan_txrx_rssi_cross_thresh)(void *adapter, u8 rssi, + void *usr_ctx, + int8_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; +}; + + +/* Rx callback registered with txrx */ +typedef int (*wlan_txrx_cb_type)(void *g_cdsctx, cdf_nbuf_t buf, u8 sta_id, + struct txrx_rx_metainfo *rx_meta_info); + +static inline int wlan_txrx_get_rssi(void *g_cdsctx, u8 sta_id, int8_t *rssi) +{ + return 0; +} + +static inline int wlan_txrx_enable_uapsd_ac(void *g_cdsctx, 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_cdsctx, u8 sta_id, + enum txrx_wmm_ac ac) +{ + return 0; +} + +static inline int wlan_change_sta_state(void *g_cdsctx, u8 sta_id, + enum wlan_sta_state state) +{ + return 0; +} + +static inline int wlan_deregister_mgmt_client(void *g_cdsctx) +{ + return 0; +} + +static inline void wlan_assoc_failed(u8 staid) +{ +} + +static inline int wlan_get_ap_stats(void *g_cdsctx, tSap_SoftapStats *buf, + bool reset) +{ + return 0; +} + +static inline int wlan_get_txrx_stats(void *g_cdsctx, + struct wlan_txrx_stats *stats, u8 sta_id) +{ + return 0; +} + +static inline int wlan_txrx_update_rssi_bmps(void *g_cdsctx, u8 sta_id, + int8_t rssi) +{ + return 0; +} + +static inline int wlan_txrx_deregister_rssi_indcb(void *g_cdsctx, + int8_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_cdsctx, + int8_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_cdsctx, cds_msg_t *msg) +{ + return 0; +} + +static inline int wlan_txrx_tx_process_msg(void *g_cdsctx, cds_msg_t *msg) +{ + return 0; +} + +static inline void wlan_txrx_mc_free_msg(void *g_cdsctx, cds_msg_t *msg) +{ +} + +static inline void wlan_txrx_tx_free_msg(void *g_cdsctx, cds_msg_t *msg) +{ +} +#endif diff --git a/core/dp/txrx/wdi_event.h b/core/dp/txrx/wdi_event.h new file mode 100644 index 000000000000..d1019eefb093 --- /dev/null +++ b/core/dp/txrx/wdi_event.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 _WDI_EVENT_H_ +#define _WDI_EVENT_H_ + +#include "athdefs.h" +#include "cdf_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 { + cdf_nbuf_t msdu; + struct ieee80211_frame *wh; + uint8_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/core/dp/txrx/wdi_event_api.h b/core/dp/txrx/wdi_event_api.h new file mode 100644 index 000000000000..5e2ce5471b7b --- /dev/null +++ b/core/dp/txrx/wdi_event_api.h @@ -0,0 +1,95 @@ +/* + * 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 _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); + +#else + +static inline void wdi_event_handler(enum WDI_EVENT event, + struct ol_txrx_pdev_t *txrx_pdev, void *data) +{ + return; +} +static inline A_STATUS wdi_event_attach(struct ol_txrx_pdev_t *txrx_pdev) +{ + return A_OK; +} +static inline A_STATUS wdi_event_detach(struct ol_txrx_pdev_t *txrx_pdev) +{ + return A_OK; +} +#endif /* WDI_EVENT_ENABLE */ + +#endif /* _WDI_EVENT_API_H_ */ diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h new file mode 100644 index 000000000000..5fee04fcc6e3 --- /dev/null +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef _QC_SAP_IOCTL_H_ +#define _QC_SAP_IOCTL_H_ + +/* + * QCSAP ioctls. + */ + +/* + * Max size of optional information elements. We artificially + * constrain this; it's limited only by the max frame size (and + * the max parameter size of the wireless extensions). + */ +#define QCSAP_MAX_OPT_IE 256 +#define QCSAP_MAX_WSC_IE 256 +#define QCSAP_MAX_GET_STA_INFO 512 + +typedef struct sSSID { + uint8_t length; + uint8_t ssId[32]; +} tSSID; + +typedef struct sSSIDInfo { + tSSID ssid; + uint8_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 uint8_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 { + uint8_t wpa_ie[QCSAP_MAX_OPT_IE]; + uint8_t wpa_macaddr[QCSAP_ADDR_LEN]; +}; + +/* + * Retrieve the WSC information element for an associated station. + */ +struct sQcSapreq_wscie { + uint8_t wsc_macaddr[QCSAP_ADDR_LEN]; + uint8_t wsc_ie[QCSAP_MAX_WSC_IE]; +}; + +/* + * Retrieve the WPS PBC Probe Request IEs. + */ +typedef struct sQcSapreq_WPSPBCProbeReqIES { + uint8_t macaddr[QCSAP_ADDR_LEN]; + uint16_t probeReqIELen; + uint8_t probeReqIE[512]; +} sQcSapreq_WPSPBCProbeReqIES_t; + +/* + * Channel List Info + */ + +typedef struct { + uint8_t num_channels; + uint8_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 */ +/* (SIOCIWFIRSTPRIV+3) is unused */ +#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) +/* (SIOCIWFIRSTPRIV+12) is unused */ +/* 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 +#define WE_SET_DP_TRACE 2 +#define WE_SET_SAP_CHANNELS 3 +#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV+16) +#define WE_UNIT_TEST_CMD 7 +#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV+17) + +#define WE_P2P_NOA_CMD 2 + +#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_GET_INI_CFG (SIOCIWFIRSTPRIV+25) +#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV+26) +#define QCSAP_IOCTL_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) +#ifdef DEBUG +#define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 +#endif +#define QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL 2 + +#define MAX_VAR_ARGS 7 +#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, + 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, + QCASAP_DUMP_STATS, + QCASAP_CLEAR_STATS, + QCASAP_SET_RADAR_DBG, +}; + +int iw_softap_get_channel_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +#endif /* __linux__ */ + +#endif /*_QC_SAP_IOCTL_H_*/ diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h new file mode 100644 index 000000000000..cf136b4325dc --- /dev/null +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined(WLAN_HDD_ASSOC_H__) +#define WLAN_HDD_ASSOC_H__ + +/** + * DOC: wlan_hdd_assoc.h + * + */ + +/* Include files */ +#include +#include +#include +#include "ol_txrx_ctrl_api.h" + +/* Preprocessor Definitions and Constants */ +#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 + +/* Type Declarations */ +/** + * typedef eConnectionState - Connection states + * @eConnectionState_NotConnected: Not associated in Infra or participating + * in an IBSS / Ad-hoc network + * @eConnectionState_Connecting: While connection in progress + * @eConnectionState_Associated: Associated in an Infrastructure network + * @eConnectionState_IbssDisconnected: Participating in an IBSS network though + * disconnected (no partner stations in the IBSS) + * @eConnectionState_IbssConnected: Participating in an IBSS network with + * partner stations also present + * eConnectionState_Disconnecting: Disconnecting in an Infrastructure network + */ +typedef enum { + eConnectionState_NotConnected, + eConnectionState_Connecting, + eConnectionState_Associated, + eConnectionState_IbssDisconnected, + eConnectionState_IbssConnected, + eConnectionState_Disconnecting +} eConnectionState; + +/** + * typedef ePeerStatus - Peer status + * @ePeerConnected: peer connected + * @ePeerDisconnected: peer disconnected + */ +typedef enum { + ePeerConnected = 1, + ePeerDisconnected +} ePeerStatus; + +/** + * typedef connection_info_t - structure to store connection information + * @connState: connection state of the NIC + * @connDot11DesiredBssType: 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 + * @bssId: BSSID + * @SSID: SSID Info + * @staId: Station ID + * @peerMacAddress:Peer Mac Address of the IBSS Stations + * @authType: Auth Type + * @ucEncryptionType: Unicast Encryption Type + * @mcEncryptionType: Multicast Encryption Type + * @Keys: Keys + * @operationChannel: Operation Channel + * @uIsAuthenticated: Remembers authenticated state + * @dot11Mode: dot11Mode + * @proxyARPService: proxy arp service + */ +typedef struct connection_info_s { + eConnectionState connState; + eMib_dot11DesiredBssType connDot11DesiredBssType; + struct cdf_mac_addr bssId; + tCsrSSIDInfo SSID; + uint8_t staId[MAX_IBSS_PEERS]; + struct cdf_mac_addr peerMacAddress[MAX_IBSS_PEERS]; + eCsrAuthType authType; + eCsrEncryptionType ucEncryptionType; + eCsrEncryptionType mcEncryptionType; + tCsrKeys Keys; + uint8_t operationChannel; + uint8_t uIsAuthenticated; + uint32_t dot11Mode; + uint8_t proxyARPService; +} connection_info_t; + +/* Forward declarations */ +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; + +/** + * hdd_is_connecting() - Function to check connection progress + * @hdd_sta_ctx: pointer to global HDD Station context + * + * Return: true if connecting, false otherwise + */ +bool hdd_is_connecting(hdd_station_ctx_t *hdd_sta_ctx); + +/** + * hdd_conn_is_connected() - Function to check connection status + * @pHddStaCtx: pointer to global HDD Station context + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_conn_is_connected(hdd_station_ctx_t *pHddStaCtx); + +/** + * hdd_conn_get_connected_band() - get current connection radio band + * @pHddStaCtx: pointer to global HDD Station context + * + * Return: eCSR_BAND_24 or eCSR_BAND_5G based on current AP connection + * eCSR_BAND_ALL if not connected + */ +eCsrBand hdd_conn_get_connected_band(hdd_station_ctx_t *pHddStaCtx); + +/** + * hdd_sme_roam_callback() - hdd sme roam callback + * @pContext: pointer to adapter context + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult); + +/** + * hdd_conn_get_connected_bss_type() - get current bss type + * @pHddStaCtx: pointer to global HDD Station context + * @pConnectedBssType: pointer to connected bss type + * + * Return: false if any errors encountered, true otherwise + */ +bool +hdd_conn_get_connected_bss_type(hdd_station_ctx_t *pHddStaCtx, + eMib_dot11DesiredBssType *pConnectedBssType); + +/** + * hdd_set_genie_to_csr() - set genie to csr + * @pAdapter: pointer to adapter + * @RSNAuthType: pointer to auth type + * + * Return: 0 on success, error number otherwise + */ +int hdd_set_genie_to_csr(hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType); + +/** + * hdd_set_csr_auth_type() - set csr auth type + * @pAdapter: pointer to adapter + * @RSNAuthType: auth type + * + * Return: 0 on success, error number otherwise + */ +int hdd_set_csr_auth_type(hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType); + +/** + * hdd_roam_register_tdlssta() - register new TDLS station + * @pAdapter: pointer to adapter + * @peerMac: pointer to peer MAC address + * @staId: station identifier + * @ucastSig: unicast signature + * + * Construct the staDesc and register with TL the new STA. + * This is called as part of ADD_STA in the TDLS setup. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_roam_register_tdlssta(hdd_adapter_t *pAdapter, + const uint8_t *peerMac, uint16_t staId, + uint8_t ucastSig); + +/** + * hdd_perform_roam_set_key_complete() - perform set key complete + * @pAdapter: pointer to adapter + * + * Return: none + */ +void hdd_perform_roam_set_key_complete(hdd_adapter_t *pAdapter); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * hdd_indicate_ese_bcn_report_no_results() - beacon report no scan results + * @pAdapter: pointer to adapter + * @measurementToken: measurement token + * @flag: flag + * @numBss: number of bss + * + * If the measurement is none and no scan results found, + * indicate the supplicant about measurement done. + * + * Return: none + */ +void +hdd_indicate_ese_bcn_report_no_results(const hdd_adapter_t *pAdapter, + const uint16_t measurementToken, + const bool flag, + const uint8_t numBss); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +CDF_STATUS hdd_change_peer_state(hdd_adapter_t *pAdapter, + uint8_t sta_id, + enum ol_txrx_peer_state sta_state, + bool roam_synch_in_progress); +#endif diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h new file mode 100644 index 000000000000..9b8095a43e88 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -0,0 +1,3351 @@ +/* + * 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__ + +/** + * + * DOC: wlan_hdd_config.h + * + * WLAN Adapter Configuration functions + */ + +/* $HEADER$ */ + +/* Include files */ +#include +#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 512 + +/* 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 */ + +/* 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_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 */ + +#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) + +/* PS = PowerSave */ +#define CFG_ENABLE_PS_NAME "gEnableBmps" +#define CFG_ENABLE_PS_MIN (0) +#define CFG_ENABLE_PS_MAX (1) +#define CFG_ENABLE_PS_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) + +#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 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; + +#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_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_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 (CDF_MCC_TO_SCC_SWITCH_DISABLE) +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX (CDF_MCC_TO_SCC_SWITCH_FORCE) +#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_DEFAULT (CDF_MCC_TO_SCC_SWITCH_DISABLE) +#endif + +#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_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_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) + +#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) + +#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_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) + +/*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 + +#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) + +#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) + +#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) +#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) + +#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_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 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) /* Seperate 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) + +#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) + +#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 (4) +#define CFG_VHT_CHANNEL_WIDTH_DEFAULT (3) + +#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) + +#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 (0) + +#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) + +#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 "" + +#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 + +#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 */ + +/* + * CDF 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 cdf_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_CDF_TRACE_ENABLE_WDI_NAME "cdf_trace_enable_wdi" +#define CFG_CDF_TRACE_ENABLE_HDD_NAME "cdf_trace_enable_hdd" +#define CFG_CDF_TRACE_ENABLE_SME_NAME "cdf_trace_enable_sme" +#define CFG_CDF_TRACE_ENABLE_PE_NAME "cdf_trace_enable_pe" +#define CFG_CDF_TRACE_ENABLE_PMC_NAME "cdf_trace_enable_pmc" +#define CFG_CDF_TRACE_ENABLE_WMA_NAME "cdf_trace_enable_wma" +#define CFG_CDF_TRACE_ENABLE_SYS_NAME "cdf_trace_enable_sys" +#define CFG_CDF_TRACE_ENABLE_CDF_NAME "cdf_trace_enable_cdf" +#define CFG_CDF_TRACE_ENABLE_SAP_NAME "cdf_trace_enable_sap" +#define CFG_CDF_TRACE_ENABLE_HDD_SAP_NAME "cdf_trace_enable_hdd_sap" +#define CFG_CDF_TRACE_ENABLE_BMI_NAME "cdf_trace_enable_bmi" + +#define CFG_CDF_TRACE_ENABLE_MIN (0) +#define CFG_CDF_TRACE_ENABLE_MAX (0xff) +#define CFG_CDF_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 + +/*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) + +/* + * 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) + +/* + * 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) + +/* + * Enable/Disable Thermal Mitigation feature + * Default: Enable + */ +#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) + +#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 (5000) + +#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 (100) + +#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) + +#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 (5) + +#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) +/* Buffer STA is not enabled in CLD 2.0 yet */ +#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) + +#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) +#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) + +#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) + +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER "gEnableTxSUBeamformer" +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MIN (0) +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MAX (1) +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_DEFAULT (0) + +/* 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 + +/* + * 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 + +/* + * Enable legacy fast roaming (LFR) on STA link during concurrent sessions + */ +#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) + +/* + * 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 (6) +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MIN (0) +#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_MAX (0xffffffff) +#endif + +#define CFG_AMSDU_SUPPORT_IN_AMPDU_NAME "gAmsduSupportInAMPDU" +#define CFG_AMSDU_SUPPORT_IN_AMPDU_MIN (0) +#define CFG_AMSDU_SUPPORT_IN_AMPDU_MAX (1) +#define CFG_AMSDU_SUPPORT_IN_AMPDU_DEFAULT (0) /* disabled */ + +/* 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 */ + +/* It enables IP, TCP and UDP checksum offload in hardware + * and also advertise same to network stack. + */ +#define CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD "gEnableIpTcpUdpChecksumOffload" +#define CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_DISABLE (0) +#define CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_ENABLE (1) +#define CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_DEFAULT (CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_ENABLE) + +/* + * 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 WLAN_FEATURE_FASTPATH +#define CFG_ENABLE_FASTPATH "gEnableFastPath" +#define CFG_ENABLE_FASTPATH_MIN (0) +#define CFG_ENABLE_FASTPATH_MAX (1) +#define CFG_ENABLE_FASTPATH_DEFAULT (CFG_ENABLE_FASTPATH_MIN) +#endif /* WLAN_FEATURE_FASTPATH */ + +/* + * 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) + +/* + * 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 (3) + +#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 (WOW_MAX_BITMAP_FILTERS) +#define CFG_MAX_WOW_FILTERS_DEFAULT (WOW_MAX_BITMAP_FILTERS) + +/* + * 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) + +/* This will be used only for debugging purpose, will be removed after sometime */ +#define CFG_ENABLE_RX_THREAD "gEnableRxThread" +#define CFG_ENABLE_RX_THREAD_MIN (0) +#define CFG_ENABLE_RX_THREAD_MAX (1) +#define CFG_ENABLE_RX_THREAD_DEFAULT (1) + +/* SAR Thermal limit values for 2g and 5g */ + +#define CFG_SET_TXPOWER_LIMIT2G_NAME "TxPower2g" +#define CFG_SET_TXPOWER_LIMIT2G_MIN (0) +#define CFG_SET_TXPOWER_LIMIT2G_MAX (30) +#define CFG_SET_TXPOWER_LIMIT2G_DEFAULT (15) + +#define CFG_SET_TXPOWER_LIMIT5G_NAME "TxPower5g" +#define CFG_SET_TXPOWER_LIMIT5G_MIN (0) +#define CFG_SET_TXPOWER_LIMIT5G_MAX (30) +#define CFG_SET_TXPOWER_LIMIT5G_DEFAULT (15) + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +#define CFG_LL_TX_FLOW_LWM "TxFlowLowWaterMark" +#define CFG_LL_TX_FLOW_LWM_MIN (0) +#define CFG_LL_TX_FLOW_LWM_MAX (1000) + +#define CFG_LL_TX_FLOW_LWM_DEFAULT (300) + +#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) + +#define CFG_LL_TX_FLOW_HWM_OFFSET_DEFAULT (94) + +#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) +#define CFG_LL_TX_LBW_FLOW_LWM_MAX (1000) + +#define CFG_LL_TX_LBW_FLOW_LWM_DEFAULT (450) + +#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) + +#define CFG_LL_TX_LBW_FLOW_HWM_OFFSET_DEFAULT (50) + +#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) +#define CFG_LL_TX_HBW_FLOW_LWM_MAX (1000) + +#define CFG_LL_TX_HBW_FLOW_LWM_DEFAULT (406) + +#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) + +#define CFG_LL_TX_HBW_FLOW_HWM_OFFSET_DEFAULT (94) + +#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_LEGACY_TX_FLOW_CONTROL */ + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + +#define CFG_LL_TX_FLOW_STOP_QUEUE_TH "TxFlowStopQueueThreshold" +#define CFG_LL_TX_FLOW_STOP_QUEUE_TH_DEFAULT (15) +#define CFG_LL_TX_FLOW_STOP_QUEUE_TH_MIN (0) +#define CFG_LL_TX_FLOW_STOP_QUEUE_TH_MAX (50) + +#define CFG_LL_TX_FLOW_START_QUEUE_OFFSET "TxFlowStartQueueOffset" +#define CFG_LL_TX_FLOW_START_QUEUE_OFFSET_DEFAULT (10) +#define CFG_LL_TX_FLOW_START_QUEUE_OFFSET_MIN (0) +#define CFG_LL_TX_FLOW_START_QUEUE_OFFSET_MAX (30) + +#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ + +#define CFG_SAP_MAX_OFFLOAD_PEERS "gMaxOffloadPeers" +#define CFG_SAP_MAX_OFFLOAD_PEERS_MIN (2) +#define CFG_SAP_MAX_OFFLOAD_PEERS_MAX (5) +#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 (3) +#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) + +/* Enable Memory Debug */ +#ifdef MEMORY_DEBUG +#define CFG_ENABLE_MEMORY_DEBUG_NAME "gEnableMemoryDebug" +#define CFG_ENABLE_MEMORY_DEBUG_MIN (0) +#define CFG_ENABLE_MEMORY_DEBUG_MAX (1) +#define CFG_ENABLE_MEMORY_DEBUG_DEFAULT (1) +#endif + +#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_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) +#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 + +#define CFG_IPA_UC_TX_BUF_COUNT_NAME "IpaUcTxBufCount" +#define CFG_IPA_UC_TX_BUF_COUNT_MIN (0) +#define CFG_IPA_UC_TX_BUF_COUNT_MAX (2048) +#define CFG_IPA_UC_TX_BUF_COUNT_DEFAULT (512) + +#define CFG_IPA_UC_TX_BUF_SIZE_NAME "IpaUcTxBufSize" +#define CFG_IPA_UC_TX_BUF_SIZE_MIN (0) +#define CFG_IPA_UC_TX_BUF_SIZE_MAX (4096) +#define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT (2048) + +#define CFG_IPA_UC_RX_IND_RING_COUNT_NAME "IpaUcRxIndRingCount" +#define CFG_IPA_UC_RX_IND_RING_COUNT_MIN (0) +#define CFG_IPA_UC_RX_IND_RING_COUNT_MAX (2048) +#define CFG_IPA_UC_RX_IND_RING_COUNT_DEFAULT (1024) + +#define CFG_IPA_UC_TX_PARTITION_BASE_NAME "IpaUcTxPartitionBase" +#define CFG_IPA_UC_TX_PARTITION_BASE_MIN (0) +#define CFG_IPA_UC_TX_PARTITION_BASE_MAX (9000) +#define CFG_IPA_UC_TX_PARTITION_BASE_DEFAULT (3000) + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +/* Enable WLAN Logging to app space */ +#define CFG_WLAN_LOGGING_SUPPORT_NAME "wlanLoggingEnable" +#define CFG_WLAN_LOGGING_SUPPORT_ENABLE (1) +#define CFG_WLAN_LOGGING_SUPPORT_DISABLE (0) +#define CFG_WLAN_LOGGING_SUPPORT_DEFAULT (1) + +/* Enable FATAL and ERROR logs for kmsg console */ +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_NAME "wlanLoggingFEToConsole" +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_ENABLE (1) +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DISABLE (0) +#define CFG_WLAN_LOGGING_FE_CONSOLE_SUPPORT_DEFAULT (1) + +/* Number of buffers to be used for WLAN logging */ +#define CFG_WLAN_LOGGING_NUM_BUF_NAME "wlanLoggingNumBuf" +#define CFG_WLAN_LOGGING_NUM_BUF_MIN (4) +#define CFG_WLAN_LOGGING_NUM_BUF_MAX (512) +#define CFG_WLAN_LOGGING_NUM_BUF_DEFAULT (256) +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ + +#define CFG_ENABLE_SIFS_BURST "gEnableSifsBurst" +#define CFG_ENABLE_SIFS_BURST_MIN (0) +#define CFG_ENABLE_SIFS_BURST_MAX (1) +#define CFG_ENABLE_SIFS_BURST_DEFAULT (0) + +#ifdef WLAN_FEATURE_LPSS +#define CFG_ENABLE_LPASS_SUPPORT "gEnableLpassSupport" +#define CFG_ENABLE_LPASS_SUPPORT_DEFAULT (0) +#define CFG_ENABLE_LPASS_SUPPORT_MIN (0) +#define CFG_ENABLE_LPASS_SUPPORT_MAX (1) +#endif + +/* + * NaN feature support configuration + * gEnableNanSupport = 0 means NaN is not supported + * gEnableNanSupport = 1 means NaN is supported + */ +#ifdef WLAN_FEATURE_NAN +#define CFG_ENABLE_NAN_SUPPORT "gEnableNanSupport" +#define CFG_ENABLE_NAN_SUPPORT_DEFAULT (0) +#define CFG_ENABLE_NAN_SUPPORT_MIN (0) +#define CFG_ENABLE_NAN_SUPPORT_MAX (1) +#endif + +#define CFG_ENABLE_SELF_RECOVERY "gEnableSelfRecovery" +#define CFG_ENABLE_SELF_RECOVERY_MIN (0) +#define CFG_ENABLE_SELF_RECOVERY_MAX (1) +#define CFG_ENABLE_SELF_RECOVERY_DEFAULT (0) + +#define CFG_ENABLE_SAP_SUSPEND "gEnableSapSuspend" +#define CFG_ENABLE_SAP_SUSPEND_MIN (0) +#define CFG_ENABLE_SAP_SUSPEND_MAX (1) +#define CFG_ENABLE_SAP_SUSPEND_DEFAULT (1) + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define CFG_EXTWOW_GO_TO_SUSPEND "gExtWoWgotoSuspend" +#define CFG_EXTWOW_GO_TO_SUSPEND_MIN (0) +#define CFG_EXTWOW_GO_TO_SUSPEND_MAX (1) +#define CFG_EXTWOW_GO_TO_SUSPEND_DEFAULT (1) + +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER "gExtWowApp1WakeupPinNumber" +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MIN (0) +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_MAX (255) +#define CFG_EXTWOW_APP1_WAKE_PIN_NUMBER_DEFAULT (12) + +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER "gExtWowApp2WakeupPinNumber" +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MIN (0) +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_MAX (255) +#define CFG_EXTWOW_APP2_WAKE_PIN_NUMBER_DEFAULT (16) + +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL "gExtWoWApp2KAInitPingInterval" +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_MIN (0) +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_MAX (0xffffffff) +#define CFG_EXTWOW_KA_INIT_PING_INTERVAL_DEFAULT (240) + +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL "gExtWoWApp2KAMinPingInterval" +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_MIN (0) +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_MAX (0xffffffff) +#define CFG_EXTWOW_KA_MIN_PING_INTERVAL_DEFAULT (240) + +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL "gExtWoWApp2KAMaxPingInterval" +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_MIN (0) +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_MAX (0xffffffff) +#define CFG_EXTWOW_KA_MAX_PING_INTERVAL_DEFAULT (1280) + +#define CFG_EXTWOW_KA_INC_PING_INTERVAL "gExtWoWApp2KAIncPingInterval" +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_MIN (0) +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_MAX (0xffffffff) +#define CFG_EXTWOW_KA_INC_PING_INTERVAL_DEFAULT (4) + +#define CFG_EXTWOW_TCP_SRC_PORT "gExtWoWApp2TcpSrcPort" +#define CFG_EXTWOW_TCP_SRC_PORT_MIN (0) +#define CFG_EXTWOW_TCP_SRC_PORT_MAX (65535) +#define CFG_EXTWOW_TCP_SRC_PORT_DEFAULT (5000) + +#define CFG_EXTWOW_TCP_DST_PORT "gExtWoWApp2TcpDstPort" +#define CFG_EXTWOW_TCP_DST_PORT_MIN (0) +#define CFG_EXTWOW_TCP_DST_PORT_MAX (65535) +#define CFG_EXTWOW_TCP_DST_PORT_DEFAULT (5001) + +#define CFG_EXTWOW_TCP_TX_TIMEOUT "gExtWoWApp2TcpTxTimeout" +#define CFG_EXTWOW_TCP_TX_TIMEOUT_MIN (0) +#define CFG_EXTWOW_TCP_TX_TIMEOUT_MAX (0xffffffff) +#define CFG_EXTWOW_TCP_TX_TIMEOUT_DEFAULT (200) + +#define CFG_EXTWOW_TCP_RX_TIMEOUT "gExtWoWApp2TcpRxTimeout" +#define CFG_EXTWOW_TCP_RX_TIMEOUT_MIN (0) +#define CFG_EXTWOW_TCP_RX_TIMEOUT_MAX (0xffffffff) +#define CFG_EXTWOW_TCP_RX_TIMEOUT_DEFAULT (200) +#endif + +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_NAME "gEnableDeauthToDisassocMap" +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MIN (0) +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_MAX (1) +#define CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP_DEFAULT (0) + +#ifdef DHCP_SERVER_OFFLOAD +#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) + +#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 (8) +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT (CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX) + +#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) + +/* + * 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) + +#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_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_SAP_DOT11MC "gSapDot11mc" +#define CFG_SAP_DOT11MC_MIN (0) +#define CFG_SAP_DOT11MC_MAX (1) +#define CFG_SAP_DOT11MC_DEFAULT (0) + +#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) + +#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) + +/* + * wlan system preference option to help policy manager decide + * on Preferred Channel List for a new connection. For possible + * values refer to enum hdd_conc_priority_mode + */ +#define CFG_CONC_SYSTEM_PREF "gSystemPref" +#define CFG_CONC_SYSTEM_PREF_MIN (0) +#define CFG_CONC_SYSTEM_PREF_MAX (2) +#define CFG_CONC_SYSTEM_PREF_DEFAULT (0) + +#define CFG_POLICY_MNGR_ENABLE "gPolicyManagerEnable" +#define CFG_POLICY_MNGR_ENABLE_MIN (0) +#define CFG_POLICY_MNGR_ENABLE_MAX (1) +#define CFG_POLICY_MNGR_ENABLE_DEFAULT (1) + +#define CFG_TSO_ENABLED_NAME "TSOEnable" +#define CFG_TSO_ENABLED_MIN (0) +#define CFG_TSO_ENABLED_MAX (1) +#define CFG_TSO_ENABLED_DEFAULT (0) + +/* + * Configuration option to enable or disable LRO (Large Receive Offload) + * in the WLAN driver + * Set 1 - enable, 0 - disable + */ +#define CFG_LRO_ENABLED_NAME "LROEnable" +#define CFG_LRO_ENABLED_MIN (0) +#define CFG_LRO_ENABLED_MAX (1) +#define CFG_LRO_ENABLED_DEFAULT (0) + +/* + * In static display use case when APPS is in stand alone power save mode enable + * active offload mode which helps FW to filter out MC/BC data packets to avoid + * APPS wake up and save more power. + * + * By default enable active mode offload as it helps to save more power in + * static display usecase(APPS stand alone power collapse). + * + * If active mode offload(gActiveModeOffload=1) is enabled then all applicable + * data offload/filtering is enabled immediately in FW once config is available + * in WLAN driver and FW caches this configuration accross suspend/resume + * + * If active mode offload is disabled(gActiveModeOffload=0) then all applicable + * data offload/filtering is enabled during cfg80211 suspend and disabled + * during cfg80211 resume + * + * Active mode offload feature is bydefault enabled for adrastea and disabled + * for non adrastea targets like ROME + */ + +#define CFG_ACTIVE_MODE_OFFLOAD "gActiveModeOffload" +#define CFG_ACTIVE_MODE_OFFLOAD_MIN (0) +#define CFG_ACTIVE_MODE_OFFLOAD_MAX (1) +#ifdef QCA_WIFI_3_0_ADRASTEA +#define CFG_ACTIVE_MODE_OFFLOAD_DEFAULT (1) +#else +#define CFG_ACTIVE_MODE_OFFLOAD_DEFAULT (0) +#endif + +/* + * 0: disable the cck tx chain mask (default) + * 1: enable the cck tx chain mask + */ +#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) + +/* + * set the self gen power value from + * 0 to 0xffff + */ +#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) + +/* + * Maximum number of scans that host can queue at firmware is controlled + * through the configuration item 'max_scan_count'. + * + * Rome - Rome firmware support 8 scan queue size and 4 are reserved + * for internal scan requests like roaming. So host can send 4 + * scan requests. + * + * ihelium - There is no constraint in number of scan queue size at + * firmware but the current uses cases needs support of maximum + * of 4 scan request from host. + */ +#define CFG_MAX_SCAN_COUNT_NAME "max_scan_count" +#define CFG_MAX_SCAN_COUNT_MIN (1) +#define CFG_MAX_SCAN_COUNT_MAX (8) +#define CFG_MAX_SCAN_COUNT_DEFAULT (4) + +/** + * enum dot11p_mode - The 802.11p mode of operation + * @WLAN_HDD_11P_DISABLED: 802.11p mode is disabled + * @WLAN_HDD_11P_STANDALONE: 802.11p-only operation + * @WLAN_HDD_11P_CONCURRENT: 802.11p and WLAN operate concurrently + */ +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_NAPI_NAME "gEnableNAPI" +#define CFG_NAPI_MIN (0) +#define CFG_NAPI_MAX (1) +#define CFG_NAPI_DEFAULT (0) + +#ifdef FEATURE_WLAN_EXTSCAN +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_NAME "gExtScanPassiveMaxChannelTime" +#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MIN (110) +#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 (60) +#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 (40) +#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 (20) +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_MAX (110) +#define CFG_EXTSCAN_ACTIVE_MIN_CHANNEL_TIME_DEFAULT (20) +#endif + +#define CFG_CE_CLASSIFY_ENABLE_NAME "gCEClassifyEnable" +#define CFG_CE_CLASSIFY_ENABLE_MIN (0) +#define CFG_CE_CLASSIFY_ENABLE_MAX (1) +#define CFG_CE_CLASSIFY_ENABLE_DEFAULT (0) + +#define CFG_DUAL_MAC_FEATURE_DISABLE "gDualMacFeatureDisable" +#define CFG_DUAL_MAC_FEATURE_DISABLE_MIN (0) +#define CFG_DUAL_MAC_FEATURE_DISABLE_MAX (1) +#define CFG_DUAL_MAC_FEATURE_DISABLE_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 (5) + +/* 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 (0) + +/* 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 (15000) +#define CFG_ROAM_SCAN_HI_RSSI_DELAY_DEFAULT (5000) + +/* 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 (-76) +#define CFG_ROAM_SCAN_HI_RSSI_UB_MAX (-30) +#define CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT (-45) + +/*--------------------------------------------------------------------------- + Type declarations + -------------------------------------------------------------------------*/ + +struct hdd_config { + /* Bitmap to track what is explicitly configured */ + DECLARE_BITMAP(bExplicitCfg, MAX_CFG_INI_ITEMS); + + /* Config parameters */ + uint32_t RTSThreshold; + uint32_t FragmentationThreshold; + uint8_t OperatingChannel; + bool ShortSlotTimeEnabled; + bool Is11dSupportEnabled; + bool Is11hSupportEnabled; + bool fSupplicantCountryCodeHasPriority; + uint32_t HeartbeatThresh24; + char PowerUsageControl[4]; + bool fIsLogpEnabled; + bool fIsImpsEnabled; + bool is_ps_enabled; + uint32_t nBmpsModListenInterval; + uint32_t nBmpsMaxListenInterval; + uint32_t nBmpsMinListenInterval; + eHddDot11Mode dot11Mode; + uint32_t nChannelBondingMode24GHz; + uint32_t nChannelBondingMode5GHz; + uint32_t MaxRxAmpduFactor; + uint16_t TxRate; + uint32_t ShortGI20MhzEnable; + uint32_t ScanResultAgeCount; + uint32_t nScanAgeTimeNCNPS; + uint32_t nScanAgeTimeNCPS; + uint32_t nScanAgeTimeCNPS; + uint32_t nScanAgeTimeCPS; + uint8_t nRssiCatGap; + bool fIsShortPreamble; + struct cdf_mac_addr IbssBssid; + uint32_t AdHocChannel5G; + uint32_t AdHocChannel24G; + uint8_t intfAddrMask; + struct cdf_mac_addr intfMacAddr[CDF_MAX_CONCURRENCY_PERSONA]; + + bool apUapsdEnabled; + bool apRandomBssidEnabled; + bool apProtEnabled; + uint16_t apProtection; + bool apOBSSProtEnabled; + bool apDisableIntraBssFwd; + uint8_t nEnableListenMode; + uint32_t nAPAutoShutOff; + uint8_t enableLTECoex; + uint32_t apKeepAlivePeriod; + uint32_t goKeepAlivePeriod; + uint32_t apLinkMonitorPeriod; + uint32_t goLinkMonitorPeriod; + uint32_t nBeaconInterval; + uint8_t nTxPowerCap; /* In dBm */ + bool fIsLowGainOverride; + uint8_t disablePacketFilter; +#if defined WLAN_FEATURE_VOWIFI + bool fRrmEnable; + uint8_t nInChanMeasMaxDuration; + uint8_t nOutChanMeasMaxDuration; + uint16_t nRrmRandnIntvl; +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Vowifi 11r params */ + bool fFTResourceReqSupported; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + uint16_t nNeighborScanPeriod; + uint8_t nNeighborLookupRssiThreshold; + uint8_t delay_before_vdev_stop; + uint8_t nOpportunisticThresholdDiff; + uint8_t nRoamRescanRssiDiff; + uint8_t neighborScanChanList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint16_t nNeighborScanMinChanTime; + uint16_t nNeighborScanMaxChanTime; + uint16_t nMaxNeighborReqTries; + uint16_t nNeighborResultsRefreshPeriod; + uint16_t nEmptyScanRefreshPeriod; + uint8_t nRoamBmissFirstBcnt; + uint8_t nRoamBmissFinalBcnt; + uint8_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 */ + uint32_t nRoamingTime; + uint16_t nVccRssiTrigger; + uint32_t nVccUlMacLossThreshold; + + uint32_t nPassiveMinChnTime; /* in units of milliseconds */ + uint32_t nPassiveMaxChnTime; /* in units of milliseconds */ + uint32_t nActiveMinChnTime; /* in units of milliseconds */ + uint32_t nActiveMaxChnTime; /* in units of milliseconds */ + + uint32_t nInitialDwellTime; /* in units of milliseconds */ + bool initial_scan_no_dfs_chnl; + +#ifdef WLAN_AP_STA_CONCURRENCY + uint32_t nPassiveMinChnTimeConc; /* in units of milliseconds */ + uint32_t nPassiveMaxChnTimeConc; /* in units of milliseconds */ + uint32_t nActiveMinChnTimeConc; /* in units of milliseconds */ + uint32_t nActiveMaxChnTimeConc; /* in units of milliseconds */ + uint32_t nRestTimeConc; /* in units of milliseconds */ + uint8_t nNumStaChanCombinedConc; /* number of channels combined for */ + /* STA in each split scan operation */ + uint8_t nNumP2PChanCombinedConc; /* number of channels combined for */ + /* P2P in each split scan operation */ +#endif + + uint8_t nMaxPsPoll; + + uint8_t nRssiFilterPeriod; + bool fIgnoreDtim; + uint8_t fMaxLIModulatedDTIM; + + uint8_t nRxAnt; + uint8_t fEnableFwHeartBeatMonitoring; + uint8_t fEnableFwBeaconFiltering; + bool fEnableFwRssiMonitoring; + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + uint8_t nDataInactivityTimeout; + + /* WMM QoS Configuration */ + hdd_wmm_user_mode_t WmmMode; + bool b80211eIsEnabled; + uint8_t UapsdMask; /* what ACs to setup U-APSD for at assoc */ + uint32_t InfraUapsdVoSrvIntv; + uint32_t InfraUapsdVoSuspIntv; + uint32_t InfraUapsdViSrvIntv; + uint32_t InfraUapsdViSuspIntv; + uint32_t InfraUapsdBeSrvIntv; + uint32_t InfraUapsdBeSuspIntv; + uint32_t InfraUapsdBkSrvIntv; + uint32_t InfraUapsdBkSuspIntv; +#ifdef FEATURE_WLAN_LFR + bool isFastRoamIniFeatureEnabled; + bool MAWCEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + uint32_t InfraInactivityInterval; + bool isEseIniFeatureEnabled; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + bool isFastTransitionEnabled; + uint8_t RoamRssiDiff; + bool isWESModeEnabled; +#endif +#ifdef FEATURE_WLAN_OKC + bool isOkcIniFeatureEnabled; +#endif + bool isRoamOffloadScanEnabled; + hdd_wmm_classification_t PktClassificationBasis; /* DSCP or 802.1Q */ + bool bImplicitQosEnabled; + + /* default TSPEC parameters for AC_VO */ + sme_QosWmmDirType InfraDirAcVo; + uint16_t InfraNomMsduSizeAcVo; + uint32_t InfraMeanDataRateAcVo; + uint32_t InfraMinPhyRateAcVo; + uint16_t InfraSbaAcVo; + + /* default TSPEC parameters for AC_VI */ + sme_QosWmmDirType InfraDirAcVi; + uint16_t InfraNomMsduSizeAcVi; + uint32_t InfraMeanDataRateAcVi; + uint32_t InfraMinPhyRateAcVi; + uint16_t InfraSbaAcVi; + + /* default TSPEC parameters for AC_BE */ + sme_QosWmmDirType InfraDirAcBe; + uint16_t InfraNomMsduSizeAcBe; + uint32_t InfraMeanDataRateAcBe; + uint32_t InfraMinPhyRateAcBe; + uint16_t InfraSbaAcBe; + + /* default TSPEC parameters for AC_BK */ + sme_QosWmmDirType InfraDirAcBk; + uint16_t InfraNomMsduSizeAcBk; + uint32_t InfraMeanDataRateAcBk; + uint32_t InfraMinPhyRateAcBk; + uint16_t InfraSbaAcBk; + + uint32_t DelayedTriggerFrmInt; + + /* Wowl pattern */ + char wowlPattern[1024]; + + /* Control for Replay counetr. value 1 means + single replay counter for all TID */ + bool bSingleTidRc; + uint8_t mcastBcastFilterSetting; + bool fhostArpOffload; + bool ssdp; +#ifdef FEATURE_WLAN_RA_FILTERING + bool IsRArateLimitEnabled; + uint16_t RArateLimitInterval; +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + bool PnoOffload; +#endif + bool fhostNSOffload; + bool burstSizeDefinition; + uint8_t tsInfoAckPolicy; + + /* RF Settling Time Clock */ + uint32_t rfSettlingTimeUs; + + uint8_t dynamicPsPollValue; + bool AddTSWhenACMIsOff; + bool fValidateScanList; + + uint32_t infraStaKeepAlivePeriod; + uint8_t nNullDataApRespTimeout; + uint8_t nBandCapability; + + uint32_t apDataAvailPollPeriodInMs; + bool fEnableBeaconEarlyTermination; + bool teleBcnWakeupEn; + +/* CDF Trace Control*/ + uint16_t cdf_trace_enable_wdi; + uint16_t cdf_trace_enable_hdd; + uint16_t cdf_trace_enable_sme; + uint16_t cdf_trace_enable_pe; + uint16_t cdf_trace_enable_pmc; + uint16_t cdf_trace_enable_wma; + uint16_t cdf_trace_enable_sys; + uint16_t cdf_trace_enable_cdf; + uint16_t cdf_trace_enable_sap; + uint16_t cdf_trace_enable_hdd_sap; + uint16_t cdf_trace_enable_bmi; + + uint16_t nTeleBcnTransListenInterval; + uint16_t nTeleBcnMaxListenInterval; + uint16_t nTeleBcnTransLiNumIdleBeacons; + uint16_t nTeleBcnMaxLiNumIdleBeacons; + uint8_t bcnEarlyTermWakeInterval; + uint32_t enableCloseLoop; + uint8_t enableBypass11d; + uint8_t enableDFSChnlScan; + uint8_t enable_dfs_pno_chnl_scan; + uint8_t enableDynamicDTIM; + uint8_t enableAutomaticTxPowerControl; + uint8_t ShortGI40MhzEnable; + eHddLinkSpeedReportType reportMaxLinkSpeed; + int32_t linkSpeedRssiHigh; + int32_t linkSpeedRssiMid; + int32_t linkSpeedRssiLow; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + bool nRoamPrefer5GHz; + bool nRoamIntraBand; + uint8_t nProbes; + uint16_t nRoamScanHomeAwayTime; +#endif + uint8_t enableMCC; + uint8_t allowMCCGODiffBI; + bool isP2pDeviceAddrAdministrated; + uint8_t thermalMitigationEnable; + uint32_t throttlePeriod; + uint8_t vhtChannelWidth; + uint8_t vhtRxMCS; + uint8_t vhtTxMCS; + bool enableTxBF; + uint8_t txBFCsnValue; + bool enable_su_tx_bformer; + uint8_t vhtRxMCS2x2; + uint8_t vhtTxMCS2x2; + bool enable2x2; + bool txchainmask1x1; + bool rxchainmask1x1; + bool enableMuBformee; + bool enableVhtpAid; + bool enableVhtGid; + bool enableTxBFin20MHz; + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmps; + uint8_t enableModulatedDTIM; + uint32_t fEnableMCAddrList; + bool enableFirstScan2GOnly; + bool skipDfsChnlInP2pSearch; + bool ignoreDynamicDtimInP2pMode; + bool enableRxSTBC; + bool enableTxSTBC; + bool enableRxLDPC; + bool enable5gEBT; +#ifdef FEATURE_WLAN_TDLS + bool fEnableTDLSSupport; + bool fEnableTDLSImplicitTrigger; + uint32_t fTDLSTxStatsPeriod; + uint32_t fTDLSTxPacketThreshold; + uint32_t fTDLSMaxDiscoveryAttempt; + uint32_t fTDLSIdlePacketThreshold; + int32_t fTDLSRSSITriggerThreshold; + int32_t fTDLSRSSITeardownThreshold; + int32_t fTDLSRSSIDelta; + uint32_t fTDLSUapsdMask; /* what ACs to setup U-APSD for TDLS */ + uint32_t fEnableTDLSBufferSta; + uint32_t fEnableTDLSSleepSta; + uint32_t fTDLSPuapsdInactivityTimer; + uint32_t fTDLSRxFrameThreshold; + uint32_t fTDLSPuapsdPTIWindow; + uint32_t fTDLSPuapsdPTRTimeout; + bool fTDLSExternalControl; + uint32_t fEnableTDLSOffChannel; + uint32_t fEnableTDLSWmmMode; + uint8_t fTDLSPrefOffChanNum; + uint8_t fTDLSPrefOffChanBandwidth; + uint8_t enable_tdls_scan; +#endif +#ifdef WLAN_SOFTAP_VSTA_FEATURE + bool fEnableVSTASupport; +#endif + uint32_t enableLpwrImgTransition; + uint8_t scanAgingTimeout; + bool enableTxLdpc; + uint8_t disableLDPCWithTxbfAP; + uint8_t enableMCCAdaptiveScheduler; + bool isAndroidPsEn; + bool sapAllowAllChannel; + uint8_t retryLimitZero; + uint8_t retryLimitOne; + uint8_t retryLimitTwo; + bool enableSSR; + uint32_t cfgMaxMediumTime; + bool enableVhtFor24GHzBand; + /* Flag indicating whether legacy fast roam during concurrency is enabled in cfg.ini or not */ + bool bFastRoamInConIniFeatureEnabled; + bool fEnableAdaptRxDrain; + uint8_t flexConnectPowerFactor; + bool enableIbssHeartBeatOffload; + uint32_t antennaDiversity; + bool fEnableSNRMonitoring; + /*PNO related parameters */ +#ifdef FEATURE_WLAN_SCAN_PNO + bool configPNOScanSupport; + uint32_t configPNOScanTimerRepeatValue; +#endif + uint8_t isAmsduSupportInAMPDU; + uint8_t nSelect5GHzMargin; + uint8_t isCoalesingInIBSSAllowed; + + /* IBSS Power Save related parameters */ + uint32_t ibssATIMWinSize; + uint8_t isIbssPowerSaveAllowed; + uint8_t isIbssPowerCollapseAllowed; + uint8_t isIbssAwakeOnTxRx; + uint32_t ibssInactivityCount; + uint32_t ibssTxSpEndInactivityTime; + uint32_t ibssPsWarmupTime; + uint32_t ibssPs1RxChainInAtimEnable; + + bool enable_ip_tcp_udp_checksum_offload; + bool enablePowersaveOffload; + bool enablefwprint; + bool enablefwlog; +#ifdef WLAN_FEATURE_11AC + uint8_t fVhtAmpduLenExponent; + uint32_t vhtMpduLen; +#endif + uint32_t IpaConfig; + bool IpaClkScalingEnable; + uint32_t IpaDescSize; + uint32_t IpaHighBandwidthMbps; + uint32_t IpaMediumBandwidthMbps; + uint32_t IpaLowBandwidthMbps; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint32_t WlanMccToSccSwitchMode; +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + uint32_t WlanAutoShutdown; +#endif + uint8_t maxWoWFilters; + uint8_t wowEnable; + uint8_t maxNumberOfPeers; + uint8_t disableDFSChSwitch; + uint8_t enableDFSMasterCap; + uint16_t thermalTempMinLevel0; + uint16_t thermalTempMaxLevel0; + uint16_t thermalTempMinLevel1; + uint16_t thermalTempMaxLevel1; + uint16_t thermalTempMinLevel2; + uint16_t thermalTempMaxLevel2; + uint16_t thermalTempMinLevel3; + uint16_t thermalTempMaxLevel3; + uint32_t TxPower2g; + uint32_t TxPower5g; + uint32_t gEnableDebugLog; + uint8_t enableRxThread; + bool fDfsPhyerrFilterOffload; + uint8_t gSapPreferredChanLocation; + uint8_t gDisableDfsJapanW53; + bool gEnableOverLapCh; + bool fRegChangeDefCountry; +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + uint32_t TxFlowLowWaterMark; + uint32_t TxFlowHighWaterMarkOffset; + uint32_t TxFlowMaxQueueDepth; + uint32_t TxLbwFlowLowWaterMark; + uint32_t TxLbwFlowHighWaterMarkOffset; + uint32_t TxLbwFlowMaxQueueDepth; + uint32_t TxHbwFlowLowWaterMark; + uint32_t TxHbwFlowHighWaterMarkOffset; + uint32_t TxHbwFlowMaxQueueDepth; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + uint32_t TxFlowStopQueueThreshold; + uint32_t TxFlowStartQueueOffset; +#endif + uint8_t apMaxOffloadPeers; + uint8_t apMaxOffloadReorderBuffs; + bool advertiseConcurrentOperation; + bool enableMemDeepSleep; + + uint32_t defaultRateIndex24Ghz; +#ifdef MEMORY_DEBUG + bool IsMemoryDebugSupportEnabled; +#endif + + uint8_t allowDFSChannelRoam; + + bool debugP2pRemainOnChannel; + + bool enablePacketLog; +#ifdef MSM_PLATFORM + uint32_t busBandwidthHighThreshold; + uint32_t busBandwidthMediumThreshold; + uint32_t busBandwidthLowThreshold; + uint32_t busBandwidthComputeInterval; + uint32_t tcpDelackThresholdHigh; + uint32_t tcpDelackThresholdLow; +#endif /* MSM_PLATFORM */ + + /* FW debug log parameters */ + uint32_t enableFwLogType; + uint32_t enableFwLogLevel; + uint8_t enableFwModuleLogLevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH]; + +#ifdef WLAN_FEATURE_11W + uint32_t pmfSaQueryMaxRetries; + uint32_t pmfSaQueryRetryInterval; +#endif + + uint8_t gMaxConcurrentActiveSessions; + + uint8_t ignoreCAC; + bool IsSapDfsChSifsBurstEnabled; + +#ifdef FEATURE_GREEN_AP + bool enableGreenAP; +#endif + uint8_t force_sap_acs; + uint8_t force_sap_acs_st_ch; + uint8_t force_sap_acs_end_ch; + + int32_t dfsRadarPriMultiplier; + uint8_t reorderOffloadSupport; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + bool isRoamOffloadEnabled; +#endif + + uint32_t IpaUcTxBufCount; + uint32_t IpaUcTxBufSize; + uint32_t IpaUcRxIndRingCount; + uint32_t IpaUcTxPartitionBase; +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + /* WLAN Logging */ + uint32_t wlanLoggingEnable; + uint32_t wlanLoggingFEToConsole; + uint32_t wlanLoggingNumBuf; +#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ + + bool enableSifsBurst; + +#ifdef WLAN_FEATURE_LPSS + bool enablelpasssupport; +#endif +#ifdef WLAN_FEATURE_NAN + bool enable_nan_support; +#endif + bool enableSelfRecovery; +#ifdef FEATURE_WLAN_FORCE_SAP_SCC + uint8_t SapSccChanAvoidance; +#endif /* FEATURE_WLAN_FORCE_SAP_SCC */ + + bool enableSapSuspend; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + uint8_t extWowGotoSuspend; + uint8_t extWowApp1WakeupPinNumber; + uint8_t extWowApp2WakeupPinNumber; + uint32_t extWowApp2KAInitPingInterval; + uint32_t extWowApp2KAMinPingInterval; + uint32_t extWowApp2KAMaxPingInterval; + uint32_t extWowApp2KAIncPingInterval; + uint16_t extWowApp2TcpSrcPort; + uint16_t extWowApp2TcpDstPort; + uint32_t extWowApp2TcpTxTimeout; + uint32_t extWowApp2TcpRxTimeout; +#endif + bool gEnableDeauthToDisassocMap; +#ifdef DHCP_SERVER_OFFLOAD + bool enableDHCPServerOffload; + uint32_t dhcpMaxNumClients; + uint8_t dhcpServerIP[IPADDR_STRING_LENGTH]; +#endif /* DHCP_SERVER_OFFLOAD */ + bool enable_mac_spoofing; + uint8_t conc_custom_rule1; + uint8_t conc_custom_rule2; + uint8_t is_sta_connection_in_5gz_enabled; + uint16_t p2p_listen_defer_interval; + uint32_t sta_miracast_mcc_rest_time_val; + bool is_ramdump_enabled; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + bool sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + uint8_t sap_p2p_11ac_override; + uint8_t sap_dot11mc; + uint8_t prefer_non_dfs_on_radar; + bool ignore_peer_erp_info; + uint8_t multicast_host_fw_msgs; + uint8_t conc_system_pref; + bool sendDeauthBeforeCon; + bool policy_manager_enabled; + bool tso_enable; + bool lro_enable; + bool active_mode_offload; + uint32_t fine_time_meas_cap; + uint8_t max_scan_count; +#ifdef WLAN_FEATURE_FASTPATH + bool fastpath_enable; +#endif + uint8_t dot11p_mode; +#ifdef FEATURE_NAPI + bool napi_enable; +#endif +#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 + bool ce_classify_enabled; + uint32_t dual_mac_feature_disable; + bool tx_chain_mask_cck; + uint8_t tx_chain_mask_1ss; + uint16_t self_gen_frm_pwr; +}; + +#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) +#define VAR_SIZE(_Struct, _Var) (sizeof(((_Struct *)0)->_Var)) + +#define VAR_FLAGS_NONE (0) + +/* bit 0 is Required or Optional */ +#define VAR_FLAGS_REQUIRED (1 << 0) +#define VAR_FLAGS_OPTIONAL (0 << 0) + +/* + * 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 (1 << 1) +#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 dynamicially + * 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 util_min(unsigned long a, unsigned long b) +{ + unsigned long r; + + r = ((a < b) ? a : b); + return r; +} + +/* Function declarations and documenation */ +CDF_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx); +CDF_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx); +CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx); +CDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx); +bool hdd_update_config_dat(hdd_context_t *pHddCtx); +CDF_STATUS hdd_cfg_get_global_config(hdd_context_t *pHddCtx, char *pBuf, + int buflen); + +eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode(eHddDot11Mode dot11Mode); +CDF_STATUS hdd_execute_global_config_command(hdd_context_t *pHddCtx, + char *command); + +bool hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx); +CDF_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, uint32_t val); + +void hdd_update_tgt_cfg(void *context, void *param); +void hdd_dfs_indicate_radar(void *context, void *param); + +CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, + uint8_t intArrayMaxLen); +void hdd_cfg_print(hdd_context_t *pHddCtx); + +CDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss); + +#endif diff --git a/core/hdd/inc/wlan_hdd_conc_ut.h b/core/hdd/inc/wlan_hdd_conc_ut.h new file mode 100644 index 000000000000..95e13f344c04 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_conc_ut.h @@ -0,0 +1,79 @@ +/* + * 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 __WLAN_HDD_CONC_UT_H +#define __WLAN_HDD_CONC_UT_H + +/* Include files */ + +#include "wlan_hdd_main.h" +#include "cds_concurrency.h" +#ifdef MPC_UT_FRAMEWORK +void clean_report(hdd_context_t *hdd_ctx); +void fill_report(hdd_context_t *hdd_ctx, char *title, + uint32_t first_persona, uint32_t second_persona, uint32_t third_persona, + uint32_t chnl_1st_conn, uint32_t chnl_2nd_conn, uint32_t chnl_3rd_conn, + bool status, enum cds_pcl_type pcl_type, char *reason, uint8_t *pcl); +void print_report(hdd_context_t *hdd_ctx); +void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx); +void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, enum cds_chain_mode first_chain_mask); +void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, uint8_t second_chnl, + enum cds_chain_mode chain_mask, uint8_t use_same_mac); +#else +static inline void clean_report(hdd_context_t *hdd_ctx) +{ +} + +static inline void fill_report(hdd_context_t *hdd_ctx, char *title, + uint32_t first_persona, uint32_t second_persona, uint32_t third_persona, + uint32_t chnl_1st_conn, uint32_t chnl_2nd_conn, uint32_t chnl_3rd_conn, + bool status, enum hdd_pcl_type pcl_type, char *reason, uint8_t *pcl) +{ +} + +static inline void print_report(hdd_context_t *hdd_ctx) +{ +} + +static inline void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) +{ +} + +static inline void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, enum hdd_chain_mode first_chain_mask) +{ +} + +static inline void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, uint8_t second_chnl, + enum hdd_chain_mode chain_mask, uint8_t use_same_mac) +{ +} +#endif +#endif diff --git a/core/hdd/inc/wlan_hdd_debugfs.h b/core/hdd/inc/wlan_hdd_debugfs.h new file mode 100644 index 000000000000..be513177f83b --- /dev/null +++ b/core/hdd/inc/wlan_hdd_debugfs.h @@ -0,0 +1,44 @@ +/* + * 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_DEBUGFS_H +#define _WLAN_HDD_DEBUGFS_H + +#ifdef WLAN_OPEN_SOURCE +CDF_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter); +void hdd_debugfs_exit(hdd_context_t *pHddCtx); +#else +inline CDF_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter) +{ + return CDF_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/core/hdd/inc/wlan_hdd_driver_ops.h b/core/hdd/inc/wlan_hdd_driver_ops.h new file mode 100644 index 000000000000..4619cf8a7775 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_driver_ops.h @@ -0,0 +1,39 @@ +/* + * 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 __WLAN_HDD_DRIVER_OPS_H__ +#define __WLAN_HDD_DRIVER_OPS_H__ + +/** + * DOC: wlan_hdd_driver_ops.h + * + * Functions to register the wlan driver. +*/ +int wlan_hdd_register_driver(void); +void wlan_hdd_unregister_driver(void); +int wlan_hdd_bus_suspend(pm_message_t state); +#endif /* __WLAN_HDD_DRIVER_OPS_H__ */ diff --git a/core/hdd/inc/wlan_hdd_ether.h b/core/hdd/inc/wlan_hdd_ether.h new file mode 100644 index 000000000000..cc20ad9b2fb0 --- /dev/null +++ b/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/core/hdd/inc/wlan_hdd_ftm.h b/core/hdd/inc/wlan_hdd_ftm.h new file mode 100644 index 000000000000..c9ed3557052c --- /dev/null +++ b/core/hdd/inc/wlan_hdd_ftm.h @@ -0,0 +1,68 @@ +/* + * 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 WLAN_HDD_FTM_H +#define WLAN_HDD_FTM_H + +/** + * DOC: wlan_hdd_ftm.h + * + * WLAN Host Device Driver Factory Test Mode header file + */ + +#include "cdf_status.h" +#include "cds_mq.h" +#include "cds_api.h" +#include "msg.h" +#include "cdf_types.h" +#include + +enum wlan_hdd_ftm_state { + WLAN_FTM_INITIALIZED, + WLAN_FTM_STOPPED, + WLAN_FTM_STARTED, +}; + +/** + * struct wlan_hdd_ftm_status - FTM status + * @ftm_state: The current state of the FTM process + */ +struct wlan_hdd_ftm_status { + enum wlan_hdd_ftm_state ftm_state; +}; + +int wlan_hdd_ftm_open(hdd_context_t *hdd_ctx); +int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx); + +#if defined(QCA_WIFI_FTM) +CDF_STATUS wlan_hdd_ftm_testmode_cmd(void *data, int len); +int wlan_hdd_qcmbr_unified_ioctl(hdd_adapter_t *adapter, struct ifreq *ifr); +int hdd_ftm_start(hdd_context_t *hdd_ctx); +int hdd_ftm_stop(hdd_context_t *hdd_ctx); +#endif + +#endif diff --git a/core/hdd/inc/wlan_hdd_host_offload.h b/core/hdd/inc/wlan_hdd_host_offload.h new file mode 100644 index 000000000000..515a8285510a --- /dev/null +++ b/core/hdd/inc/wlan_hdd_host_offload.h @@ -0,0 +1,60 @@ +/* + * 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 { + uint8_t offloadType; + uint8_t enableOrDisable; + union { + uint8_t hostIpv4Addr[4]; + uint8_t hostIpv6Addr[16]; + } params; + struct cdf_mac_addr bssId; +} tHostOffloadRequest, *tpHostOffloadRequest; + +#endif /* __WLAN_HDD_HOST_OFFLOAD_H__ */ diff --git a/core/hdd/inc/wlan_hdd_includes.h b/core/hdd/inc/wlan_hdd_includes.h new file mode 100644 index 000000000000..cb2e63e85830 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_includes.h @@ -0,0 +1,69 @@ +/* + * 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 "ol_txrx_ctrl_api.h" +#include +#include +#include "wlan_hdd_assoc.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/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h new file mode 100644 index 000000000000..a2f5fb32e1c1 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -0,0 +1,151 @@ +/* + * 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__ + +/** + * DOC: wlan_hdd_ipa.h + * + * WLAN IPA interface module headers + * Originally written by Qualcomm Atheros, Inc + */ + +#include + +#ifdef IPA_OFFLOAD +/* Include files */ +CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx); +CDF_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx); +CDF_STATUS hdd_ipa_process_rxt(void *cds_context, cdf_nbuf_t rxBuf, + uint8_t sta_id); +int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, + enum ipa_wlan_event type, uint8_t *mac_addr); +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); +void hdd_ipa_uc_stat_query(hdd_context_t *hdd_ctx, uint32_t *ipa_tx_diff, + uint32_t *ipa_rx_diff); +void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx); +void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, uint8_t reason); +bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx); +bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx); +int hdd_ipa_send_mcc_scc_msg(hdd_context_t *pHddCtx, bool mcc_mode); +#else +static inline CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) +{ + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) +{ + return CDF_STATUS_SUCCESS; +} + +static inline CDF_STATUS hdd_ipa_process_rxt(void *cds_context, + cdf_nbuf_t rxBuf, uint8_t sta_id) +{ + return CDF_STATUS_SUCCESS; +} + +static inline int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, + enum ipa_wlan_event type, uint8_t *mac_addr) +{ + return 0; +} + +static inline int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, + bool mcc_mode) +{ + return 0; +} + +static inline int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, + uint64_t tx_packets, + uint64_t rx_packets) +{ + return 0; +} + +static inline int hdd_ipa_suspend(hdd_context_t *hdd_ctx) +{ + return 0; +} + +static inline int hdd_ipa_resume(hdd_context_t *hdd_ctx) +{ + return 0; +} + +static inline void hdd_ipa_uc_stat_query(hdd_context_t *hdd_ctx, + uint32_t *ipa_tx_diff, + uint32_t *ipa_rx_diff) +{ + *ipa_tx_diff = 0; + *ipa_rx_diff = 0; + return; +} + +static inline void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, + uint8_t reason) +{ + return; +} + +static void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx) +{ + return; +} + +static inline bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx) +{ + return false; +} + +static inline bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx) +{ + return false; +} +#endif /* IPA_OFFLOAD */ + +#ifdef IPA_UC_OFFLOAD +int hdd_ipa_uc_ssr_reinit(void); +int hdd_ipa_uc_ssr_deinit(void); +#else +static inline int hdd_ipa_uc_ssr_reinit(void) +{ + return false; +} + +static inline int hdd_ipa_uc_ssr_deinit(void) +{ + return false; +} +#endif + +#endif /* #ifndef HDD_IPA_H__ */ diff --git a/core/hdd/inc/wlan_hdd_lro.h b/core/hdd/inc/wlan_hdd_lro.h new file mode 100644 index 000000000000..db4ea2778105 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_lro.h @@ -0,0 +1,145 @@ +/* + * 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 __WLAN_HDD_LRO_H__ +#define __WLAN_HDD_LRO_H__ +/** + * DOC: wlan_hdd_lro.h + * + * WLAN LRO interface module headers + */ + +/** + * enum hdd_lro_rx_status - LRO receive frame status + * @HDD_LRO_RX: frame sent over the LRO interface + * @HDD_LRO_NO_RX: frame not sent over the LRO interface + */ +enum hdd_lro_rx_status { + HDD_LRO_RX = 0, + HDD_LRO_NO_RX = 1, +}; + +#if defined(FEATURE_LRO) + +#include +#include + +/* LRO_DESC_TABLE_SZ must be a power of 2 */ +#define LRO_DESC_TABLE_SZ 16 +#define LRO_DESC_TABLE_SZ_MASK (LRO_DESC_TABLE_SZ - 1) +#define LRO_DESC_POOL_SZ 10 + +/** + * hdd_lro_desc_entry - defines the LRO descriptor + * element stored in the list + * @lro_node: node of the list + * @lro_desc: the LRO descriptor contained in this list entry + */ +struct hdd_lro_desc_entry { + struct list_head lro_node; + struct net_lro_desc *lro_desc; +}; + +/** + * hdd_lro_desc_pool - pool of free LRO descriptors + * @lro_desc_array: array of LRO descriptors allocated + * @lro_free_list_head: head of the list + * @lro_pool_lock: lock to protect access to the list + */ +struct hdd_lro_desc_pool { + struct hdd_lro_desc_entry *lro_desc_array; + struct list_head lro_free_list_head; + cdf_spinlock_t lro_pool_lock; +}; + +/** + * hdd_lro_desc_table - defines each entry of the LRO + * hash table + * @lro_desc_list: list of LRO descriptors + */ +struct hdd_lro_desc_table { + struct list_head lro_desc_list; +}; + +/** + * hdd_lro_desc_info - structure containing the LRO + * descriptor information + * @lro_hash_table: hash table used for a quick desc. look-up + * @lro_hash_lock: lock to protect access to the hash table + * @lro_desc_pool: Free pool of LRO descriptors + */ +struct hdd_lro_desc_info { + struct hdd_lro_desc_table *lro_hash_table; + cdf_spinlock_t lro_hash_lock; + struct hdd_lro_desc_pool lro_desc_pool; +}; + +/** + * hdd_lro_s - LRO information per HDD adapter + * @lro_mgr: LRO manager + * @lro_desc_info: LRO descriptor information + */ +struct hdd_lro_s { + struct net_lro_mgr *lro_mgr; + struct hdd_lro_desc_info lro_desc_info; +}; + +int hdd_lro_init(hdd_context_t *hdd_ctx); + +int hdd_lro_enable(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter); + +void hdd_lro_disable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter); + +enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, struct sk_buff *skb); + +void hdd_lro_flush_all(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter); +#else +struct hdd_lro_s {}; + +static inline int hdd_lro_enable(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + return 0; +} + +static inline enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, struct sk_buff *skb) +{ + return HDD_LRO_NO_RX; +} + +static inline int hdd_lro_init(hdd_context_t *hdd_ctx) +{ + return 0; +} + +static inline void hdd_lro_disable(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter){} +#endif /* FEATURE_LRO */ +#endif /* __WLAN_HDD_LRO_H__ */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h new file mode 100644 index 000000000000..3e4ad444ec1c --- /dev/null +++ b/core/hdd/inc/wlan_hdd_main.h @@ -0,0 +1,1529 @@ +/* + * 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(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 "sir_mac_prot_def.h" +#include "csr_api.h" +#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 "sap_api.h" +#endif +#include "ol_txrx_osif_api.h" +#include "ol_txrx_ctrl_api.h" +#include + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ +/** Number of Tx Queues */ +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +#define NUM_TX_QUEUES 5 +#else +#define NUM_TX_QUEUES 4 +#endif +/** Bytes to reserve in the headroom */ +#define LIBRA_HW_NEEDED_HEADROOM 128 +/** 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 **/ +#ifdef QCA_WIFI_3_0_EMU +#define WLAN_WAIT_TIME_DISCONNECT 3000 +#else +#define WLAN_WAIT_TIME_DISCONNECT 2000 +#endif +#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 + +/** 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 + +/* 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 ...) CDF_TRACE(CDF_MODULE_ID_HDD, level, ## args) + +#define hdd_log(level, args...) CDF_TRACE(CDF_MODULE_ID_HDD, level, ## args) +#define hdd_logfl(level, format, args...) hdd_log(level, FL(format), ## args) + +#define hdd_alert(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_FATAL, format, ## args) +#define hdd_err(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_ERROR, format, ## args) +#define hdd_warn(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_WARN, format, ## args) +#define hdd_notice(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_INFO, format, ## args) +#define hdd_info(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_INFO_HIGH, format, ## args) +#define hdd_debug(format, args...) \ + hdd_logfl(CDF_TRACE_LEVEL_DEBUG, format, ## args) + +#define ENTER() hdd_logfl(CDF_TRACE_LEVEL_INFO_LOW, "enter") +#define EXIT() hdd_logfl(CDF_TRACE_LEVEL_INFO_LOW, "exit") + +#define WLAN_HDD_GET_PRIV_PTR(__dev__) (hdd_adapter_t *)(netdev_priv((__dev__))) + +#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 + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define GTK_OFFLOAD_ENABLE 0 +#define GTK_OFFLOAD_DISABLE 1 +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +#define HDD_PNO_SCAN_TIMERS_SET_ONE 1 +/* value should not be greater than PNO_MAX_SCAN_TIMERS */ +#define HDD_PNO_SCAN_TIMERS_SET_MULTIPLE 6 +#endif + +#define MAX_USER_COMMAND_SIZE 4096 + +#define HDD_MIN_TX_POWER (-100) /* minimum tx power */ +#define HDD_MAX_TX_POWER (+100) /* maximum tx power */ + +/* If IPA UC data path is enabled, target should reserve extra tx descriptors + * for IPA data path. + * Then host data path should allow less TX packet pumping in case + * IPA data path enabled + */ +#define WLAN_TFC_IPAUC_TX_DESC_RESERVE 100 + +#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 + +#define BSS_WAIT_TIMEOUT 10000 + +/* + * 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; +}; + +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) */ + +/* 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 + +#define HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390 +#define HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390 +#define HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780 +#define HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780 + + +#define NUM_TX_RX_HISTOGRAM 1024 +#define NUM_TX_RX_HISTOGRAM_MASK (NUM_TX_RX_HISTOGRAM - 1) + +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; +}; + +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]; + + /* txflow stats */ + 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_t numUnprotDeauthRx; + uint8_t 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 struct roaming_info_s { + HDD_ROAM_STATE roamingState; + cdf_event_t roamingEvent; + + tSirMacAddr bssid; + tSirMacAddr peerMac; + uint32_t roamId; + eRoamCmdStatus roamStatus; + bool 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 { + uint8_t bkid[16]; +} WAPI_BKID, *pWAPI_BKID; + +/** WAPI Association information structure definition */ +struct _WAPI_AssocInfo { + uint8_t elementID; + uint8_t length; + uint16_t version; + uint16_t akmSuiteCount; + uint32_t akmSuite[MAX_NUM_AKM_SUITES]; + uint16_t unicastSuiteCount; + uint32_t unicastSuite[MAX_NUM_UNI_SUITES]; + uint32_t multicastSuite; + uint16_t wapiCability; + uint16_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 */ + uint8_t keyId; + uint8_t addrIndex[MAX_ADDR_INDEX]; /*reserved for future use */ + int wpiekLen; + uint8_t wpiek[MAX_WPI_KEY_LENGTH]; + int wpickLen; + uint8_t wpick[MAX_WPI_KEY_LENGTH]; + uint8_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 { + uint32_t length; + uint32_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 { + uint32_t nWapiMode; + bool fIsWapiSta; + struct cdf_mac_addr cachedMacAddr; + uint8_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; + +/* MAINTAIN 1 - 1 CORRESPONDENCE WITH tCDF_CON_MODE */ +typedef enum device_mode { + WLAN_HDD_INFRA_STATION, + WLAN_HDD_SOFTAP, + WLAN_HDD_P2P_CLIENT, + WLAN_HDD_P2P_GO, + /* Mode 5 is reserved for FTM */ + WLAN_HDD_FTM = 5, + 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; + +typedef struct action_pkt_buffer { + uint8_t *frame_ptr; + uint32_t frame_length; + uint16_t 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; + cdf_mc_timer_t hdd_remain_on_chan_timer; + action_pkt_buffer_t action_pkt_buff; + bool hdd_remain_on_chan_cancel_in_progress; + uint32_t scan_id; +} hdd_remain_on_chan_ctx_t; + +/* RoC Request entry */ +typedef struct hdd_roc_req { + cdf_list_node_t node; /* MUST be first element */ + hdd_adapter_t *pAdapter; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; +} hdd_roc_req_t; + +/** + * struct hdd_scan_req - Scan Request entry + * @node : List entry element + * @adapter: Adapter address + * @scan_request: scan request holder + * @scan_id: scan identifier used across host layers which is generated at WMI + * @cookie: scan request identifier sent to userspace + * @source: scan request originator (NL/Vendor scan) + * @timestamp: scan request timestamp + * + * Scan request linked list element + */ +struct hdd_scan_req { + cdf_list_node_t node; + hdd_adapter_t *adapter; + struct cfg80211_scan_request *scan_request; + uint32_t scan_id; + uint8_t source; + uint32_t timestamp; +}; + +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 { + uint16_t current_freq; + u64 action_cookie; + uint8_t *buf; + size_t len; + 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 */ + bool ibss_enc_key_installed; + + /*Save the wep/wpa-none keys */ + tCsrRoamSetKey ibss_enc_key; + + bool hdd_ReassocScenario; + + /* STA ctx debug variables */ + int staDebugState; +}; + +#define BSS_STOP 0 +#define BSS_START 1 +typedef struct hdd_hostapd_state_s { + int bssState; + cdf_event_t cdf_event; + cdf_event_t cdf_stop_bss_event; + CDF_STATUS cdf_status; + bool 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 */ + bool isUsed; + + /** Station ID reported back from HAL (through SAP). Broadcast + * uses station ID zero by default in both libra and volans. */ + uint8_t ucSTAId; + + /** MAC address of the station */ + struct cdf_mac_addr macAddrSTA; + + /** Current Station state so HDD knows how to deal with packet + * queue. Most recent states used to change TLSHIM STA state */ + enum ol_txrx_peer_state tlSTAState; + + /** Track QoS status of station */ + bool isQosEnabled; + + /** The station entry for which Deauth is in progress */ + bool isDeauthInProgress; +} hdd_station_info_t; + +struct hdd_ap_ctx_s { + hdd_hostapd_state_t HostapdState; + + /* Memory differentiation mode is enabled */ + /* uint16_t uMemoryDiffThreshold; */ + /* uint8_t uNumActiveAC; */ + /* uint8_t uActiveACMask; */ + + /** Packet Count to update uNumActiveAC and uActiveACMask */ + /* uint16_t uUpdatePktCount; */ + + /** Station ID assigned after BSS starts */ + uint8_t uBCStaId; + + uint8_t uPrivacy; /* The privacy bits of configuration */ + + tSirWPSPBCProbeReq WPSPBCProbeReq; + + tsap_Config_t sapConfig; + + struct semaphore semWpsPBCOverlapInd; + + bool apDisableIntraBssFwd; + + cdf_mc_timer_t hdd_ap_inactivity_timer; + + uint8_t operatingChannel; + + bool 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; + + bool bApActive; +#ifdef WLAN_FEATURE_MBSSID + /* SAP Context */ + void *sapContext; +#endif + bool dfs_cac_block_tx; +}; + +typedef struct hdd_scaninfo_s { + /* The scan pending */ + uint32_t mScanPending; + + /* Counter for mScanPending so that the scan pending + error log is not printed for more than 5 times */ + uint32_t mScanPendingCounter; + + /* Additional IE for scan */ + tSirAddie scanAddIE; + + /* Scan mode */ + tSirScanType scan_mode; + + /* completion variable for abortscan */ + struct completion abortscan_event_var; + +} hdd_scaninfo_t; + +#define WLAN_HDD_MAX_MC_ADDR_LIST 10 + +#ifdef WLAN_FEATURE_PACKET_FILTERING +typedef struct multicast_addr_list { + uint8_t isFilterApplied; + uint8_t mc_cnt; + uint8_t addr[WLAN_HDD_MAX_MC_ADDR_LIST][ETH_ALEN]; +} t_multicast_add_list; +#endif + +#define WLAN_HDD_MAX_HISTORY_ENTRY 10 + +/** + * struct hdd_netif_queue_stats - netif queue operation statistics + * @pause_count - pause counter + * @unpause_count - unpause counter + */ +struct hdd_netif_queue_stats { + uint16_t pause_count; + uint16_t unpause_count; +}; + +/** + * struct hdd_netif_queue_history - netif queue operation history + * @time: timestamp + * @netif_action: action type + * @netif_reason: reason type + * @pause_map: pause map + */ +struct hdd_netif_queue_history { + cdf_time_t time; + uint16_t netif_action; + uint16_t netif_reason; + uint32_t pause_map; +}; + + +#define WLAN_HDD_ADAPTER_MAGIC 0x574c414e /* ASCII "WLAN" */ + + +struct hdd_adapter_s { + void *pHddCtx; + + device_mode_t device_mode; + + /** Handle to the network device */ + struct net_device *dev; + + /** 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 + */ + uint8_t ops; + uint32_t ctw; + + /** Current MAC Address for the adapter */ + struct cdf_mac_addr 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; + + uint8_t sessionId; + + /* Completion variable for session close */ + struct completion session_close_comp_var; + + /* Completion variable for session open */ + struct completion session_open_comp_var; + + /* 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; + + struct completion sta_authorized_event; +#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; + CDF_STATUS tdlsAddStaStatus; +#endif + + /* Track whether the linkup handling is needed */ + bool isLinkUpSvcNeeded; + + /* Mgmt Frames TX completion status code */ + uint32_t mgmtTxCompletionStatus; + + /* 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]; + /* uint8_t uNumActiveStation; */ + +/************************************************************* + */ + +#ifdef FEATURE_WLAN_WAPI + hdd_wapi_info_t wapi_info; +#endif + + int8_t rssi; +#ifdef WLAN_FEATURE_LPSS + bool rssi_send; +#endif + + uint8_t snr; + + struct work_struct monTxWorkQueue; + struct sk_buff *skb_to_tx; + + union { + hdd_station_ctx_t station; + hdd_ap_ctx_t ap; + } sessionCtx; + + hdd_cfg80211_state_t cfg80211State; + +#ifdef WLAN_FEATURE_PACKET_FILTERING + t_multicast_add_list mc_addr_list; +#endif + uint8_t addr_filter_pattern; + + /* Magic cookie for adapter sanity verification */ + uint32_t magic; + bool higherDtimTransition; + bool 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 */ + uint8_t psbChanged; + /* UAPSD psb value configured through framework */ + uint8_t configuredPsb; +#ifdef IPA_OFFLOAD + void *ipa_context; +#endif + /* Use delayed work for Sec AP ACS as Pri AP Startup need to complete + * since CSR (PMAC Struct) Config is same for both AP + */ + struct delayed_work acs_pending_work; + + struct work_struct scan_block_work; +#ifdef MSM_PLATFORM + unsigned long prev_rx_packets; + unsigned long prev_tx_packets; + int connection; +#endif + bool is_roc_inprogress; + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + cdf_mc_timer_t tx_flow_control_timer; + bool tx_flow_timer_initialized; + unsigned int tx_flow_low_watermark; + unsigned int tx_flow_high_watermark_offset; +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + bool offloads_configured; + + /* DSCP to UP QoS Mapping */ + sme_QosWmmUpType hddWmmDscpToUpMap[WLAN_HDD_MAX_DSCP + 1]; + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + bool isLinkLayerStatsSet; +#endif + uint8_t linkStatus; + + /* variable for temperature in Celsius */ + int temperature; + + /* Time stamp for last completed RoC request */ + v_TIME_t last_roc_ts; + + /* Time stamp for start RoC request */ + v_TIME_t start_roc_ts; + + /* 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[CDF_MAX_CONCURRENCY_PERSONA]; + int ocb_mac_addr_count; + + /* BITMAP indicating pause reason */ + uint32_t pause_map; + spinlock_t pause_map_lock; + + uint8_t history_index; + struct hdd_netif_queue_history + queue_oper_history[WLAN_HDD_MAX_HISTORY_ENTRY]; + struct hdd_netif_queue_stats queue_oper_stats[WLAN_REASON_TYPE_MAX]; + struct hdd_lro_s lro_info; +}; + +#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 { + cdf_list_node_t node; /* MUST be first element */ + hdd_adapter_t *pAdapter; +} hdd_adapter_list_node_t; + +typedef struct hdd_priv_data_s { + uint8_t *buf; + int used_len; + int total_len; +} hdd_priv_data_t; + +#define MAX_MOD_LOGLEVEL 10 +typedef struct { + uint8_t enable; + uint8_t dl_type; + uint8_t dl_report; + uint8_t dl_loglevel; + uint8_t index; + uint32_t dl_mod_loglevel[MAX_MOD_LOGLEVEL]; + +} fw_log_info; + +#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 structure definition */ + +struct hdd_context_s { + /** Global CDS context */ + v_CONTEXT_t pcds_context; + + /** HAL handle...*/ + tHalHandle hHal; + + struct wiphy *wiphy; + /* TODO Remove this from here. */ + + cdf_spinlock_t hdd_adapter_lock; + cdf_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 + CDF_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 to the parent device */ + struct device *parent_dev; + + /** Config values read from qcom_cfg.ini file */ + struct hdd_config *config; + + struct wlan_hdd_ftm_status ftm; + + /* Completion variable to indicate Mc Thread Suspended */ + struct completion mc_sus_event_var; + + struct completion reg_init; + + bool isMcThreadSuspended; + +#ifdef QCA_CONFIG_SMP + bool is_ol_rx_thread_suspended; +#endif + + volatile bool isLogpInProgress; + + bool isLoadInProgress; + + bool isUnloadInProgress; + + /* Track whether Mcast/Bcast Filter is enabled. */ + bool hdd_mcastbcast_filter_set; + + bool hdd_wlan_suspended; + bool suspended; + + /* Lock to avoid race condition during start/stop bss */ + struct mutex sap_lock; + +#ifdef WLAN_KD_READY_NOTIFIER + bool kd_nl_init; +#endif /* WLAN_KD_READY_NOTIFIER */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + /* OEM App registered or not */ + bool oem_app_registered; + + /* OEM App Process ID */ + int32_t oem_pid; +#endif + + /** Concurrency Parameters*/ + uint32_t concurrency_mode; + + uint8_t no_of_open_sessions[CDF_MAX_NO_OF_MODE]; + uint8_t no_of_active_sessions[CDF_MAX_NO_OF_MODE]; + + /** P2P Device MAC Address for the adapter */ + struct cdf_mac_addr p2pDeviceAddress; + +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + cdf_wake_lock_t rx_wake_lock; +#endif + + cdf_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 */ + uint16_t max_num_tdls_sta; + /* TDLS peer connected count */ + uint16_t connected_peer_count; + tdls_scan_context_t tdls_scan_ctxt; + /* Lock to avoid race condition during TDLS operations */ + struct mutex tdls_lock; + uint8_t tdls_off_channel; + uint16_t tdls_channel_offset; +#endif + +#ifdef IPA_OFFLOAD + void *hdd_ipa; + /* CE resources */ + uint32_t ce_sr_base_paddr; + uint32_t ce_sr_ring_size; + cdf_dma_addr_t ce_reg_paddr; + + /* WLAN TX:IPA->WLAN */ + uint32_t tx_comp_ring_base_paddr; + uint32_t tx_comp_ring_size; + uint32_t tx_num_alloc_buffer; + + /* WLAN RX:WLAN->IPA */ + uint32_t rx_rdy_ring_base_paddr; + uint32_t rx_rdy_ring_size; + uint32_t rx_proc_done_idx_paddr; + + /* IPA UC doorbell registers paddr */ + uint32_t tx_comp_doorbell_paddr; + uint32_t rx_ready_doorbell_paddr; +#endif /* IPA_OFFLOAD */ + + /* MC/BC Filter state variable + * This always contains the value that is currently + * configured + * */ + uint8_t configuredMcastBcastFilter; + + uint8_t sus_res_mcastbcast_filter; + + bool 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 */ + bool isWiphySuspended; + + /* Indicates about pending sched_scan results */ + bool isSchedScanUpdatePending; + +#ifdef MSM_PLATFORM + /* DDR bus bandwidth compute timer + */ + cdf_mc_timer_t bus_bw_timer; + int cur_vote_level; + spinlock_t bus_bw_lock; + int cur_rx_level; + uint64_t prev_rx; +#endif + /* VHT80 allowed */ + bool isVHT80Allowed; + + struct completion ready_to_suspend; + /* defining the solution type */ + uint32_t target_type; + + /* defining the firmware version */ + uint32_t target_fw_version; + uint32_t dfs_radar_found; + + /* defining the chip/rom version */ + uint32_t target_hw_version; + /* defining the chip/rom revision */ + uint32_t target_hw_revision; + /* chip/rom name */ + const char *target_hw_name; + struct regulatory reg; +#ifdef FEATURE_WLAN_CH_AVOID + uint16_t unsafe_channel_count; + uint16_t unsafe_channel_list[NUM_20MHZ_RF_CHANNELS]; +#endif /* FEATURE_WLAN_CH_AVOID */ + + uint8_t max_intf_count; + uint8_t current_intf_count; +#ifdef WLAN_FEATURE_LPSS + uint8_t lpss_support; +#endif + uint8_t ap_arpns_support; + tSirScanType ioctl_scan_mode; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + cdf_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; + + uint8_t dev_dfs_cac_status; + + bool btCoexModeSet; +#ifdef FEATURE_GREEN_AP + struct hdd_green_ap_ctx *green_ap_ctx; +#endif + fw_log_info fw_log_settings; +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + cdf_mc_timer_t skip_acs_scan_timer; + uint8_t skip_acs_scan_status; +#endif + + cdf_wake_lock_t sap_dfs_wakelock; + atomic_t sap_dfs_ref_cnt; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + bool is_extwow_app_type1_param_set; + bool is_extwow_app_type2_param_set; + bool ext_wow_should_suspend; + struct completion ready_to_extwow; +#endif + + /* Time since boot up to extscan start (in micro seconds) */ + uint64_t ext_scan_start_since_boot; + unsigned long g_event_flags; + /* RoC request queue and work */ + struct delayed_work roc_req_work; + cdf_spinlock_t hdd_roc_req_q_lock; + cdf_list_t hdd_roc_req_q; + cdf_spinlock_t hdd_scan_req_q_lock; + cdf_list_t hdd_scan_req_q; + uint8_t miracast_value; +#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; + + /* 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_FEATURE_OFFLOAD_PACKETS + struct hdd_offloaded_packets_ctx op_ctx; +#endif + bool mcc_mode; +#ifdef WLAN_FEATURE_MEMDUMP + uint8_t *fw_dump_loc; + uint32_t dump_loc_paddr; + cdf_mc_timer_t memdump_cleanup_timer; + struct mutex memdump_lock; + bool memdump_in_progress; +#endif /* WLAN_FEATURE_MEMDUMP */ + + cdf_mc_timer_t dbs_opportunistic_timer; + bool connection_in_progress; + spinlock_t connection_status_lock; + cdf_mutex_t hdd_conc_list_lock; + + uint16_t hdd_txrx_hist_idx; + struct hdd_tx_rx_histogram hdd_txrx_hist[NUM_TX_RX_HISTOGRAM]; +}; + +/*--------------------------------------------------------------------------- + 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); + +CDF_STATUS hdd_get_front_adapter(hdd_context_t *pHddCtx, + hdd_adapter_list_node_t **ppAdapterNode); + +CDF_STATUS hdd_get_next_adapter(hdd_context_t *pHddCtx, + hdd_adapter_list_node_t *pAdapterNode, + hdd_adapter_list_node_t **pNextAdapterNode); + +CDF_STATUS hdd_remove_adapter(hdd_context_t *pHddCtx, + hdd_adapter_list_node_t *pAdapterNode); + +CDF_STATUS hdd_remove_front_adapter(hdd_context_t *pHddCtx, + hdd_adapter_list_node_t **ppAdapterNode); + +CDF_STATUS hdd_add_adapter_back(hdd_context_t *pHddCtx, + hdd_adapter_list_node_t *pAdapterNode); + +CDF_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, uint8_t session_type, + const char *name, tSirMacAddr macAddr, + uint8_t rtnl_held); +CDF_STATUS hdd_close_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + uint8_t rtnl_held); +CDF_STATUS hdd_close_all_adapters(hdd_context_t *pHddCtx); +CDF_STATUS hdd_stop_all_adapters(hdd_context_t *pHddCtx); +CDF_STATUS hdd_reset_all_adapters(hdd_context_t *pHddCtx); +CDF_STATUS hdd_start_all_adapters(hdd_context_t *pHddCtx); +hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *pHddCtx, + uint32_t vdev_id); +hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *pHddCtx, + tSirMacAddr macAddr); +CDF_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); +CDF_STATUS hdd_stop_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, + const bool bCloseSession); +void hdd_set_station_ops(struct net_device *pWlanDev); +uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *pHddCtx); +void wlan_hdd_release_intf_addr(hdd_context_t *pHddCtx, uint8_t *releaseAddr); +uint8_t hdd_get_operating_channel(hdd_context_t *pHddCtx, device_mode_t mode); + +void hdd_set_conparam(uint32_t newParam); +tCDF_CON_MODE hdd_get_conparam(void); + +void hdd_abort_mac_scan(hdd_context_t *pHddCtx, uint8_t sessionId, + eCsrAbortReason reason); +void hdd_cleanup_actionframe(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter); + +void crda_regulatory_entry_default(uint8_t *countryCode, int domain_id); +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(uint32_t timeout, uint32_t reason); +bool hdd_is_ssr_required(void); +void hdd_set_ssr_required(e_hdd_ssr_required value); + +void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy); +CDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *pAdapter); +CDF_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx); +void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx); +int wlan_hdd_validate_context(hdd_context_t *pHddCtx); +bool hdd_is_valid_mac_address(const uint8_t *pMacAddr); +CDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx); + +void hdd_checkandupdate_phymode(hdd_context_t *pHddCtx); + +#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, uint16_t staId, + struct cdf_mac_addr macAddrSTA, int width); +#endif + +#ifdef WLAN_FEATURE_LPSS +void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter, + hdd_station_ctx_t *pHddStaCtx, + uint8_t is_on, uint8_t is_connected); +void wlan_hdd_send_version_pkg(uint32_t fw_version, + uint32_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, bool enable); +#endif + +hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter, + bool check_start_bss); + +bool hdd_is_5g_supported(hdd_context_t *pHddCtx); + +int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter); + +#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); +static inline bool hdd_link_layer_stats_supported(void) +{ + return true; +} +#else +static inline bool hdd_link_layer_stats_supported(void) +{ + return false; +} +#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); + +#ifdef WLAN_FEATURE_MEMDUMP +/** + * 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 + */ +static inline bool hdd_is_memdump_supported(void) +{ + return true; +} +#else +static inline bool hdd_is_memdump_supported(void) +{ + return false; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +void hdd_update_macaddr(struct hdd_config *config, + struct cdf_mac_addr hw_macaddr); +#if defined(FEATURE_WLAN_LFR) +void wlan_hdd_disable_roaming(hdd_adapter_t *pAdapter); +void wlan_hdd_enable_roaming(hdd_adapter_t *pAdapter); +#endif + +CDF_STATUS hdd_post_cds_enable_config(hdd_context_t *pHddCtx); + +CDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx); + +CDF_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 +cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void); + +#ifdef QCA_CONFIG_SMP +int wlan_hdd_get_cpu(void); +#else +static inline int wlan_hdd_get_cpu(void) +{ + return 0; +} +#endif + +void wlan_hdd_txrx_pause_cb(uint8_t vdev_id, + enum netif_action_type action, enum netif_reason_type reason); + +void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value); +void wlan_hdd_display_tx_rx_histogram(hdd_context_t *pHddCtx); +void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx); +void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx); +void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx); +const char *hdd_get_fwpath(void); + +#endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/inc/wlan_hdd_memdump.h b/core/hdd/inc/wlan_hdd_memdump.h new file mode 100644 index 000000000000..c3fa8391a9ea --- /dev/null +++ b/core/hdd/inc/wlan_hdd_memdump.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * DOC : wlan_hdd_memdump.h + * + * WLAN Host Device Driver file for dumping firmware memory + * + */ + +#if !defined(WLAN_HDD_MEMDUMP_H) +#define WLAN_HDD_MEMDUMP_H + +#include "wlan_hdd_main.h" + +#ifdef WLAN_FEATURE_MEMDUMP +/** + * enum qca_wlan_vendor_attr_memory_dump - values for memory dump attributes + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID - Invalid + * @QCA_WLAN_VENDOR_ATTR_REQUEST_ID - Indicate request ID + * @QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE - Indicate size of the memory dump + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - To keep track of the last enum + * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX - max value possible for this type + * + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP sub command. + */ +enum qca_wlan_vendor_attr_memory_dump { + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_REQUEST_ID = 1, + QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE = 2, + + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX = + QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - 1, +}; + +/* Size of fw memory dump is estimated to be 327680 bytes */ +#define FW_MEM_DUMP_SIZE 327680 +#define FW_DRAM_LOCATION 0x00400000 +#define FW_MEM_DUMP_REQ_ID 1 +#define FW_MEM_DUMP_NUM_SEG 1 +#define MEMDUMP_COMPLETION_TIME_MS 5000 + +int memdump_init(void); +void memdump_deinit(void); +int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); +#else +static inline int memdump_init(void) +{ + return -ENOTSUPP; +} + +static inline void memdump_deinit(void) +{ +} + +static inline int wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + return -ENOTSUPP; +} +#endif + +#endif /* if !defined(WLAN_HDD_MEMDUMP_H)*/ diff --git a/core/hdd/inc/wlan_hdd_mib.h b/core/hdd/inc/wlan_hdd_mib.h new file mode 100644 index 000000000000..8fe44a8e9600 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_mib.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. + */ + +#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 { + uint32_t cEntries; + + struct cdf_mac_addr 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 { + uint32_t ssidLength; + uint8_t ssid[MIB_DOT11_SSID_MAX_LENGTH]; + +} sDot11Ssid; + +typedef struct { + uint32_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 { + uint32_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 = false, + eMib_dot11NICPowerState_ON = true +} eMib_dot11NICPowerState; + +typedef enum { + eMib_dot11HardwarePHYState_OFF = false, + eMib_dot11HardwarePHYState_ON = 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 { + uint32_t cEntries; + + struct cdf_mac_addr 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 { + uint16_t uEtherType; + eMib_dot11ExemptAction exemptAction; + eMib_dot11ExemptPacket exemptPacket; + +} sMib_dot11PrivacyExemption; + +typedef struct { + uint32_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 */ + /* mamipulated 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; + + bool dot11IbssJoinOnly; + bool HiddenNetworkEnabled; + +} sHddMib_t; + +#endif diff --git a/core/hdd/inc/wlan_hdd_misc.h b/core/hdd/inc/wlan_hdd_misc.h new file mode 100644 index 000000000000..e0a0db23ce75 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_misc.h @@ -0,0 +1,39 @@ +/* + * 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_MAC_FILE "wlan/qca_cld/wlan_mac.bin" +#else +#define WLAN_INI_FILE "wlan/qcom_cfg.ini" +#define WLAN_MAC_FILE "wlan/wlan_mac.bin" +#endif /* MSM_PLATFORM */ + +#endif /* WLAN_HDD_MISC_H */ diff --git a/core/hdd/inc/wlan_hdd_nan.h b/core/hdd/inc/wlan_hdd_nan.h new file mode 100644 index 000000000000..ac2f62f38be9 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_nan.h @@ -0,0 +1,59 @@ +/* + * 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_NAN_H +#define __WLAN_HDD_NAN_H + +/** + * DOC: wlan_hdd_nan.h + * + * WLAN Host Device Driver NAN API specification + */ + +struct hdd_context_s; + +#ifdef WLAN_FEATURE_NAN +struct wiphy; +struct wireless_dev; + +int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +bool wlan_hdd_nan_is_supported(void); +void wlan_hdd_nan_init(struct hdd_context_s *hdd_ctx); +#else +static inline bool wlan_hdd_nan_is_supported(void) +{ + return false; +} +static inline void wlan_hdd_nan_init(struct hdd_context_s *hdd_ctx) +{ +} +#endif /* WLAN_FEATURE_NAN */ +#endif /* __WLAN_HDD_NAN_H */ diff --git a/core/hdd/inc/wlan_hdd_napi.h b/core/hdd/inc/wlan_hdd_napi.h new file mode 100644 index 000000000000..3c1683ded84c --- /dev/null +++ b/core/hdd/inc/wlan_hdd_napi.h @@ -0,0 +1,82 @@ +/* + * 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 __HDD_NAPI_H__ +#define __HDD_NAPI_H__ + +#ifdef FEATURE_NAPI +/** + * DOC: wlan_hdd_napi.h + * + * WLAN NAPI interface module headers + */ + +/* CLD headers */ +#include "hif_napi.h" +/* Linux headers */ +#include /* net_device */ + +#define HDD_NAPI_ANY (-1) + +int hdd_napi_enabled(int id); +int hdd_napi_create(void); +int hdd_napi_destroy(int force); + +int hdd_napi_stats(char *buf, + int max, + char *indp, + struct qca_napi_data *napid); + +/* the following triggers napi_enable/disable as required */ +int hdd_napi_event(enum qca_napi_event event, void *data); + +int hdd_napi_poll(struct napi_struct *napi, int budget); + +struct qca_napi_data *hdd_napi_get_all(void); + +#else /* ! defined(FEATURE_NAPI) */ +#include "hif_napi.h" +/** + * Stub API + * + */ + +#define HDD_NAPI_ANY (-1) + +static inline int hdd_napi_enabled(int id) { return 0; } +static inline int hdd_napi_create(void) { return -EPERM; } +static inline int hdd_napi_destroy(int force) { return 0; } +static inline int hdd_napi_stats(char *buf, int max, char *indp, + struct qca_napi_data *napid) +{ return 0; } +static inline int hdd_napi_event(enum qca_napi_event event, void *data) +{ return 0; } +static inline struct qca_napi_data *hdd_napi_get_all(void) { return NULL; } + +#endif /* FEATURE_NAPI */ + +#endif /* HDD_NAPI_H__ */ diff --git a/core/hdd/inc/wlan_hdd_oemdata.h b/core/hdd/inc/wlan_hdd_oemdata.h new file mode 100644 index 000000000000..9107dc315afe --- /dev/null +++ b/core/hdd/inc/wlan_hdd_oemdata.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * DOC: wlan_hdd_oemdata.h + * + * 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 eOemErrorCode - OEM error codes + * @OEM_ERR_NULL_CONTEXT: %NULL context + * @OEM_ERR_APP_NOT_REGISTERED: OEM App is not registered + * @OEM_ERR_INVALID_SIGNATURE: Invalid signature + * @OEM_ERR_NULL_MESSAGE_HEADER: Invalid message header + * @OEM_ERR_INVALID_MESSAGE_TYPE: Invalid message type + * @OEM_ERR_INVALID_MESSAGE_LENGTH: Invalid length in message body + */ +typedef enum { + OEM_ERR_NULL_CONTEXT = 1, + OEM_ERR_APP_NOT_REGISTERED, + OEM_ERR_INVALID_SIGNATURE, + OEM_ERR_NULL_MESSAGE_HEADER, + OEM_ERR_INVALID_MESSAGE_TYPE, + OEM_ERR_INVALID_MESSAGE_LENGTH +} eOemErrorCode; + +/** + * typedef tDriverVersion - Driver version identifier (w.x.y.z) + * @major: Version ID major number + * @minor: Version ID minor number + * @patch: Version ID patch number + * @build: Version ID build number + */ +typedef struct cdf_packed { + uint8_t major; + uint8_t minor; + uint8_t patch; + uint8_t build; +} tDriverVersion; + +/** + * typedef t_iw_oem_data_cap - OEM Data Capabilities + * @oem_target_signature: Signature of chipset vendor, e.g. QUALCOMM + * @oem_target_type: Chip type + * @oem_fw_version: Firmware version + * @driver_version: Host software version + * @allowed_dwell_time_min: Channel dwell time - allowed minimum + * @allowed_dwell_time_max: Channel dwell time - allowed maximum + * @curr_dwell_time_min: Channel dwell time - current minimim + * @curr_dwell_time_max: Channel dwell time - current maximum + * @supported_bands: Supported bands, 2.4G or 5G Hz + * @num_channels: Num of channels IDs to follow + * @channel_list: List of channel IDs + */ +typedef struct cdf_packed { + uint8_t oem_target_signature[OEM_TARGET_SIGNATURE_LEN]; + uint32_t oem_target_type; + uint32_t oem_fw_version; + tDriverVersion driver_version; + uint16_t allowed_dwell_time_min; + uint16_t allowed_dwell_time_max; + uint16_t curr_dwell_time_min; + uint16_t curr_dwell_time_max; + uint16_t supported_bands; + uint16_t num_channels; + uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS]; +} t_iw_oem_data_cap; + +/** + * typedef tHddChannelInfo - Channel information + * @chan_id: channel id + * @reserved0: reserved for padding and future use + * @mhz: primary 20 MHz channel frequency in mhz + * @band_center_freq1: Center frequency 1 in MHz + * @band_center_freq2: Center frequency 2 in MHz, valid only for 11ac + * VHT 80+80 mode + * @info: channel info + * @reg_info_1: regulatory information field 1 which contains min power, + * max power, reg power and reg class id + * @reg_info_2: regulatory information field 2 which contains antennamax + */ +typedef struct cdf_packed { + uint32_t chan_id; + uint32_t reserved0; + uint32_t mhz; + uint32_t band_center_freq1; + uint32_t band_center_freq2; + uint32_t info; + uint32_t reg_info_1; + uint32_t reg_info_2; +} tHddChannelInfo; + +/** + * typedef tPeerStatusInfo - Status information for a given peer + * @peer_mac_addr: peer mac address + * @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED + * @vdev_id: vdev_id for the peer mac + * @peer_capability: peer capability: 0: RTT/RTT2, 1: RTT3. Default is 0 + * @reserved0: reserved0 + * @peer_chan_info: channel info on which peer is connected + */ +typedef struct cdf_packed { + uint8_t peer_mac_addr[ETH_ALEN]; + uint8_t peer_status; + uint8_t vdev_id; + uint32_t peer_capability; + uint32_t reserved0; + tHddChannelInfo peer_chan_info; +} tPeerStatusInfo; + +void hdd_send_peer_status_ind_to_oem_app(struct cdf_mac_addr *peerMac, + uint8_t peerStatus, + uint8_t peerTimingMeasCap, + uint8_t sessionId, + tSirSmeChanInfo *chan_info); + +int iw_get_oem_data_cap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int oem_activate_service(struct hdd_context_s *hdd_ctx); + +void hdd_send_oem_data_rsp_msg(int length, uint8_t *oemDataRsp); + +#endif /* __WLAN_HDD_OEM_DATA_H__ */ + +#endif /* FEATURE_OEM_DATA_SUPPORT */ diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h new file mode 100644 index 000000000000..b9ef3445f627 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __P2P_H +#define __P2P_H +/**=========================================================================== + + \file wlan_hdd_p2p.h + + \brief Linux HDD P2P include file + + ==========================================================================*/ +#define ACTION_FRAME_TX_TIMEOUT 2000 +#define WAIT_CANCEL_REM_CHAN 1000 +#define WAIT_REM_CHAN_READY 1000 +#define WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX 3000 +#define ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX 20 +#define COMPLETE_EVENT_PROPOGATE_TIME 10 + +#ifdef QCA_WIFI_3_0_EMU +#define ACTION_FRAME_DEFAULT_WAIT 500 +#else +#define ACTION_FRAME_DEFAULT_WAIT 200 +#endif + +#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-" + +#ifdef QCA_WIFI_3_0_EMU +#define P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT 2 +#define P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT 3 +#else +#define P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT 2 +#define P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT 5 +#endif + +#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 +#define MAX_ROC_REQ_QUEUE_ENTRY 10 + +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 global_p2p_connection_status; +#endif + +typedef struct p2p_app_setP2pPs { + uint8_t opp_ps; + uint32_t ctWindow; + uint8_t count; + uint32_t duration; + uint32_t interval; + uint32_t single_noa_duration; + uint8_t psSelection; +} p2p_app_setP2pPs_t; + +int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + 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)) + 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)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie); + +int hdd_set_p2p_ps(struct net_device *dev, void *msgData); +int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command); +int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command); + +void hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, + uint32_t nFrameLength, uint8_t *pbFrames, + uint8_t frameType, uint32_t rxChan, int8_t rxRssi); + +void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, + uint32_t scan_id); +void hdd_send_action_cnf(hdd_adapter_t *pAdapter, bool actionSendSuccess); +int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter); +void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) +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)) + 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)) +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)) +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); + +void wlan_hdd_roc_request_dequeue(struct work_struct *work); +#endif /* __P2P_H */ diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h new file mode 100644 index 000000000000..c6157f037516 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_power.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 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. + */ + +#ifndef __WLAN_HDD_POWER_H +#define __WLAN_HDD_POWER_H + +/** + * DOC: wlan_hdd_power.h + * + * HDD Power Management API + */ + +#include "wlan_hdd_main.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 + +/** + * enum pkt_filter_protocol_layer - packet filter protocol layer + * @HDD_FILTER_PROTO_TYPE_INVALID: Invalid initial value + * @HDD_FILTER_PROTO_TYPE_MAC: MAC protocol + * @HDD_FILTER_PROTO_TYPE_ARP: ARP protocol + * @HDD_FILTER_PROTO_TYPE_IPV4: IP V4 protocol + * @HDD_FILTER_PROTO_TYPE_IPV6: IP V6 protocol + * @HDD_FILTER_PROTO_TYPE_UDP: UDP protocol + * @HDD_FILTER_PROTO_TYPE_INVALID: Max place holder value + */ +enum pkt_filter_protocol_layer { + 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 +}; + +/** + * enum pkt_filter_action - packet filter action + * @HDD_RCV_FILTER_INVALID: Invalid initial value + * @HDD_RCV_FILTER_SET: Packet filter set + * @HDD_RCV_FILTER_CLEAR: Packet filter clear + * @HDD_RCV_FILTER_MAX: Max place holder value + */ +enum pkt_filter_action { + HDD_RCV_FILTER_INVALID = 0, + HDD_RCV_FILTER_SET = 1, + HDD_RCV_FILTER_CLEAR = 2, + HDD_RCV_FILTER_MAX +}; + +/** + * enum pkt_filter_compare_flag - packet filter compare flag + * @HDD_FILTER_CMP_TYPE_INVALID: Invalid initial value + * @HDD_FILTER_CMP_TYPE_EQUAL: Compare if filter is equal + * @HDD_FILTER_CMP_TYPE_MASK_EQUAL: Compare if filter mask is equal + * @HDD_FILTER_CMP_TYPE_NOT_EQUAL: Compare if filter is not equal + * @HDD_FILTER_CMP_TYPE_MASK_NOT_EQUAL: Compare if filter mask is not equal + * @HDD_FILTER_CMP_TYPE_MAX: Max place holder value + */ +enum pkt_filter_compare_flag { + 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 +}; + +/** + * struct pkt_filter_param_cfg - packet filter parameter config + * @protocol_layer: Protocol layer + * @compare_flag: Compare flag + * @data_fffset: Data offset + * @data_length: Data length + * @compare_data: Compare data + * @data_mask: Data mask + */ +struct pkt_filter_param_cfg { + uint8_t protocol_layer; + uint8_t compare_flag; + uint8_t data_offset; + uint8_t data_length; + uint8_t compare_data[SIR_MAX_FILTER_TEST_DATA_LEN]; + uint8_t data_mask[SIR_MAX_FILTER_TEST_DATA_LEN]; +}; + +/** + * struct pkt_filter_cfg - packet filter config received from user space + * @filter_action: Filter action + * @filter_id: Filter id + * @num_params: Number of parameters + * @params_data: Packet filter parameters detail + */ +struct pkt_filter_cfg { + uint8_t filter_action; + uint8_t filter_id; + uint8_t num_params; + struct pkt_filter_param_cfg params_data[HDD_MAX_CMP_PER_PACKET_FILTER]; +}; + +#endif + + +/* SSR shutdown & re-init functions */ +CDF_STATUS hdd_wlan_shutdown(void); +CDF_STATUS hdd_wlan_re_init(void *hif_sc); + +void hdd_conf_mcastbcast_filter(hdd_context_t *pHddCtx, bool setfilter); +CDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool fenable); +void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable); + +#ifdef WLAN_FEATURE_PACKET_FILTERING +void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set); +#else +static inline void +wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) +{ +} +#endif + +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow); + +int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy); + +void hdd_ipv4_notifier_work_queue(struct work_struct *work); +#ifdef WLAN_NS_OFFLOAD +void hdd_ipv6_notifier_work_queue(struct work_struct *work); +#endif + +int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + struct wireless_dev *wdev, +#endif + int *dbm); +int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + struct wireless_dev *wdev, +#endif + enum nl80211_tx_power_setting type, + int dbm); +int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, bool mode, + int timeout); + +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 /* __WLAN_HDD_POWER_H */ diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h new file mode 100644 index 000000000000..2061ec72c689 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_softap_tx_rx.h @@ -0,0 +1,94 @@ +/* + * 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(WLAN_HDD_SOFTAP_TX_RX_H) +#define WLAN_HDD_SOFTAP_TX_RX_H + +/** + * DOC: wlan_hdd_softap_tx_rx.h + * + *Linux HDD SOFTAP Tx/RX APIs + */ + +#include + +int hdd_softap_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev); +void hdd_softap_tx_timeout(struct net_device *dev); +CDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter); +CDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter); +CDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, + uint8_t STAId, + struct cdf_mac_addr *pmacAddrSTA); +CDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, + uint8_t STAId); +CDF_STATUS hdd_softap_rx_packet_cbk(void *cds_context, + cdf_nbuf_t rxBufChain, + uint8_t staId); +#ifdef IPA_OFFLOAD +CDF_STATUS hdd_softap_rx_mul_packet_cbk(void *cds_context, + cdf_nbuf_t rx_buf_list, uint8_t staId); +#endif /* IPA_OFFLOAD */ + +CDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, + uint8_t staId); +CDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter, + bool fAuthRequired, + bool fPrivacyBit, + uint8_t staId, + uint8_t ucastSig, + uint8_t bcastSig, + struct cdf_mac_addr *pPeerMacAddress, + bool fWmmEnabled); +CDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter, + bool fPrivacyBit); +CDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter); +CDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pHostapdAdapter); +CDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter, + struct cdf_mac_addr *pDestMacAddress, + enum ol_txrx_peer_state state); +CDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter, + struct cdf_mac_addr *pMacAddress, + uint8_t *staId); + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context); +void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume); +#else +static inline +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context) +{ + return; +} +static inline +void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume) +{ + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +#endif /* end #if !defined(WLAN_HDD_SOFTAP_TX_RX_H) */ diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h new file mode 100644 index 000000000000..285bb7856769 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -0,0 +1,633 @@ +/* + * 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 __HDD_TDLS_H +#define __HDD_TDLS_H +/** + * DOC: wlan_hdd_tdls.h + * WLAN Host Device Driver TDLS include file + */ + +#ifdef FEATURE_WLAN_TDLS + +#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 + +#define EXTTDLS_EVENT_BUF_SIZE (4096) + +/** + * struct tdls_config_params_t - tdls config params + * + * @tdls: tdls + * @tx_period_t: tx period + * @tx_packet_n: tx packets number + * @discovery_tries_n: discovery tries + * @idle_packet_n: idle packet number + * @rssi_trigger_threshold: rssi trigger threshold + * @rssi_teardown_threshold: rssi tear down threshold + * @rssi_delta: rssi delta + */ +typedef struct { + uint32_t tdls; + uint32_t tx_period_t; + uint32_t tx_packet_n; + uint32_t discovery_tries_n; + uint32_t idle_packet_n; + int32_t rssi_trigger_threshold; + int32_t rssi_teardown_threshold; + int32_t rssi_delta; +} tdls_config_params_t; + +/** + * struct tdls_scan_context_t - tdls scan context + * + * @wiphy: pointer to wiphy structure + * @dev: pointer to netdev + * @scan_request: scan request + * @magic: magic + * @attempt: attempt + * @reject: reject + * @tdls_scan_work: delayed tdls scan work + */ +typedef struct { + struct wiphy *wiphy; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + 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; + +/** + * enum eTDLSSupportMode - tdls support mode + * + * @eTDLS_SUPPORT_NOT_ENABLED: tdls support not enabled + * @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 + */ +typedef enum { + eTDLS_SUPPORT_NOT_ENABLED = 0, + eTDLS_SUPPORT_DISABLED, + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, + eTDLS_SUPPORT_ENABLED, +} eTDLSSupportMode; + +/** + * enum tTDLSCapType - tdls capability type + * + * @eTDLS_CAP_NOT_SUPPORTED: tdls not supported + * @eTDLS_CAP_UNKNOWN: unknown capability + * @eTDLS_CAP_SUPPORTED: tdls capability supported + */ +typedef enum eTDLSCapType { + eTDLS_CAP_NOT_SUPPORTED = -1, + eTDLS_CAP_UNKNOWN = 0, + eTDLS_CAP_SUPPORTED = 1, +} tTDLSCapType; + +/** + * enum tTDLSLinkStatus - tdls link status + * + * @eTDLS_LINK_IDLE: tdls link idle + * @eTDLS_LINK_DISCOVERING: tdls link discovering + * @eTDLS_LINK_DISCOVERED: tdls link discovered + * @eTDLS_LINK_CONNECTING: tdls link connecting + * @eTDLS_LINK_CONNECTED: tdls link connected + * @eTDLS_LINK_TEARING: tdls link tearing + */ +typedef enum eTDLSLinkStatus { + eTDLS_LINK_IDLE = 0, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_DISCOVERED, + eTDLS_LINK_CONNECTING, + eTDLS_LINK_CONNECTED, + eTDLS_LINK_TEARING, +} tTDLSLinkStatus; + +/** + * enum tTDLSLinkReason - tdls link reason + * + * @eTDLS_LINK_SUCCESS: Success + * @eTDLS_LINK_UNSPECIFIED: Unspecified reason + * @eTDLS_LINK_NOT_SUPPORTED: Remote side doesn't support TDLS + * @eTDLS_LINK_UNSUPPORTED_BAND: Remote side doesn't support this band + * @eTDLS_LINK_NOT_BENEFICIAL: Going to AP is better than direct + * @eTDLS_LINK_DROPPED_BY_REMOTE: Remote side doesn't want it anymore + */ +typedef enum { + eTDLS_LINK_SUCCESS, + eTDLS_LINK_UNSPECIFIED = -1, + eTDLS_LINK_NOT_SUPPORTED = -2, + eTDLS_LINK_UNSUPPORTED_BAND = -3, + eTDLS_LINK_NOT_BENEFICIAL = -4, + eTDLS_LINK_DROPPED_BY_REMOTE = -5 +} tTDLSLinkReason; + +/** + * struct tdls_req_params_t - tdls request parameters + * + * @channel: channel hint, in channel number (NOT frequency) + * @global_operating_class: operating class to use + * @max_latency_ms: max latency that can be tolerated by apps + * @min_bandwidth_kbps: bandwidth required by apps, in kilo bits per second + */ +typedef struct { + int channel; + int global_operating_class; + int max_latency_ms; + int min_bandwidth_kbps; +} tdls_req_params_t; + +/** + * enum tdls_state_t - tdls state + * + * @QCA_WIFI_HAL_TDLS_DISABLED: 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 established using MCC + * @QCA_WIFI_HAL_TDLS_DROPPED: Direct link was established, but is now dropped + * @QCA_WIFI_HAL_TDLS_FAILED: Direct link failed + */ +typedef enum { + QCA_WIFI_HAL_TDLS_DISABLED = 1, + QCA_WIFI_HAL_TDLS_ENABLED, + QCA_WIFI_HAL_TDLS_ESTABLISHED, + QCA_WIFI_HAL_TDLS_ESTABLISHED_OFF_CHANNEL, + QCA_WIFI_HAL_TDLS_DROPPED, + QCA_WIFI_HAL_TDLS_FAILED +} tdls_state_t; + +typedef int (*cfg80211_exttdls_callback)(const uint8_t *mac, + uint32_t state, + int32_t reason, void *ctx); + +/** + * struct tdls_tx_tput_config_t - tdls tx throughput config + * + * @period: period + * @bytes: bytes + */ +typedef struct { + uint16_t period; + uint16_t bytes; +} tdls_tx_tput_config_t; + +/** + * struct tdls_discovery_config_t - tdls discovery config + * + * @period: period + * @tries: number of tries + */ +typedef struct { + uint16_t period; + uint16_t tries; +} tdls_discovery_config_t; + +/** + * struct tdls_rx_idle_config_t - tdls rx idle config + * + * @timeout: timeout + */ +typedef struct { + uint16_t timeout; +} tdls_rx_idle_config_t; + +/** + * struct tdls_rssi_config_t - tdls rssi config + * + * @rssi_thres: rssi_thres + */ +typedef struct { + uint16_t rssi_thres; +} tdls_rssi_config_t; + +struct _hddTdlsPeer_t; + +/** + * struct tdlsCtx_t - tdls context + * + * @peer_list: peer list + * @pAdapter: pointer to adapter + * @peerDiscoverTimer: peer discovery timer + * @peerDiscoveryTimeoutTimer: peer discovery timeout timer + * @threshold_config: threshold config + * @discovery_peer_cnt: discovery peer count + * @discovery_sent_cnt: discovery sent count + * @ap_rssi: ap rssi + * @curr_candidate: current candidate + * @implicit_setup: implicit setup work queue + * @magic: magic + * + */ +typedef struct { + struct list_head peer_list[TDLS_PEER_LIST_SIZE]; + hdd_adapter_t *pAdapter; + cdf_mc_timer_t peerDiscoveryTimeoutTimer; + tdls_config_params_t threshold_config; + int32_t discovery_peer_cnt; + uint32_t discovery_sent_cnt; + int8_t ap_rssi; + struct _hddTdlsPeer_t *curr_candidate; + struct work_struct implicit_setup; + uint32_t magic; +} tdlsCtx_t; + +/** + * struct hddTdlsPeer_t - tdls peer data + * + * @node: node + * @pHddTdlsCtx: pointer to tdls context + * @peerMac: peer mac address + * @staId: station identifier + * @rssi: rssi + * @tdls_support: tdls support + * @link_status: tdls link status + * @signature: signature + * @is_responder: is responder + * @discovery_processed: discovery processed flag + * @discovery_attempt: discovery attempt + * @tx_pkt: tx packet + * @rx_pkt: rx packet + * @uapsdQueues: uapsd queues + * @maxSp: max sp + * @isBufSta: is buffer sta + * @isOffChannelSupported: is offchannel supported flag + * @supported_channels_len: supported channels length + * @supported_channels: supported channels + * @supported_oper_classes_len: supported operation classes length + * @supported_oper_classes: supported operation classes + * @isForcedPeer: is forced peer + * @op_class_for_pref_off_chan: op class for preferred off channel + * @pref_off_chan_num: preferred off channel number + * @op_class_for_pref_off_chan_is_set: op class for preferred off channel set + * @reason: reason + * @state_change_notification: state change notification + */ +typedef struct _hddTdlsPeer_t { + struct list_head node; + tdlsCtx_t *pHddTdlsCtx; + tSirMacAddr peerMac; + uint16_t staId; + int8_t rssi; + tTDLSCapType tdls_support; + tTDLSLinkStatus link_status; + uint8_t signature; + uint8_t is_responder; + uint8_t discovery_processed; + uint16_t discovery_attempt; + uint16_t tx_pkt; + uint16_t rx_pkt; + uint8_t uapsdQueues; + uint8_t maxSp; + uint8_t isBufSta; + uint8_t isOffChannelSupported; + uint8_t supported_channels_len; + uint8_t supported_channels[SIR_MAC_MAX_SUPP_CHANNELS]; + uint8_t supported_oper_classes_len; + uint8_t supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; + bool isForcedPeer; + uint8_t op_class_for_pref_off_chan; + uint8_t pref_off_chan_num; + uint8_t op_class_for_pref_off_chan_is_set; + tTDLSLinkReason reason; + cfg80211_exttdls_callback state_change_notification; +} hddTdlsPeer_t; + +/** + * struct tdlsConnInfo_t - tdls connection info + * + * @sessionId: Session ID + * @staId: TDLS peer station id + * @peerMac: peer mac address + */ +typedef struct { + uint8_t sessionId; + uint8_t staId; + struct cdf_mac_addr peerMac; +} tdlsConnInfo_t; + +/** + * struct tdlsInfo_t - tdls info + * + * @vdev_id: vdev id + * @tdls_state: tdls state + * @notification_interval_ms: notification interval in ms + * @tx_discovery_threshold: tx discovery threshold + * @tx_teardown_threshold: tx teardown threshold + * @rssi_teardown_threshold: rx teardown threshold + * @rssi_delta: rssi delta + * @tdls_options: tdls options + * @peer_traffic_ind_window: peer traffic indication window + * @peer_traffic_response_timeout: peer traffic response timeout + * @puapsd_mask: puapsd mask + * @puapsd_inactivity_time: puapsd inactivity time + * @puapsd_rx_frame_threshold: puapsd rx frame threshold + */ +typedef struct { + uint32_t vdev_id; + uint32_t tdls_state; + uint32_t notification_interval_ms; + uint32_t tx_discovery_threshold; + uint32_t tx_teardown_threshold; + int32_t rssi_teardown_threshold; + int32_t rssi_delta; + uint32_t tdls_options; + uint32_t peer_traffic_ind_window; + uint32_t peer_traffic_response_timeout; + uint32_t puapsd_mask; + uint32_t puapsd_inactivity_time; + uint32_t puapsd_rx_frame_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, uint8_t *mac); + +void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, uint8_t *mac); + +int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, + const uint8_t *mac, uint8_t tx); + +int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t staId); + +hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, + const uint8_t *mac, bool mutexLock); + +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, + const uint8_t *mac); + +int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter, + const uint8_t *mac, + tCsrTdlsLinkEstablishParams * + tdlsLinkEstablishParams); +hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, + const uint8_t *mac); + +int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const uint8_t *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 uint8_t *mac, + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason); + +int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, + const uint8_t *mac); + +int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, + const uint8_t *mac, + tCsrStaParams *StaParams, + bool isBufSta, bool isOffChannelSupported); + +int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, const uint8_t *mac, + int8_t rxRssi); + +int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t responder); + +int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t 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 uint8_t *mac); + +uint16_t wlan_hdd_tdls_connected_peers(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, + uint32_t statusCode); + +void wlan_hdd_tdls_tncrement_peer_count(hdd_adapter_t *pAdapter); + +void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter); + +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, + const uint8_t *mac, uint8_t 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)) + 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)) + 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, + cdf_mc_timer_t *timer, + uint32_t expirationTime); +void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, + hddTdlsPeer_t *curr_peer, + uint16_t reason); + +void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t *pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate); + +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 uint8_t *mac, + bool forcePeer); + +int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, + const uint8_t *peer); +int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, + const uint8_t *peer, + cfg80211_exttdls_callback callback, + uint32_t chan, + uint32_t max_latency, + uint32_t op_class, + uint32_t min_bandwidth); +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + const uint8_t *mac, int32_t *state, + int32_t *reason); +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + int32_t *state, int32_t *reason); +int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, + cfg80211_exttdls_callback callback); +void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, + bool tdls_chan_swit_prohibited); + +int wlan_hdd_tdls_add_station(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *mac, + bool update, tCsrStaParams *StaParams); + +int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *peer, + enum nl80211_tdls_operation oper); +#else +int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + uint8_t *peer, + enum nl80211_tdls_operation oper); +#endif + +#ifdef TDLS_MGMT_VERSION2 +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 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) +int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + bool initiator, const uint8_t *buf, + size_t len); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + const uint8_t *buf, size_t len); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) +int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + const uint8_t *buf, size_t len); +#else +int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, const uint8_t *buf, + size_t len); +#endif +#endif + +void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, + hdd_context_t *hddctx); +void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx); + +hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *adapter); +int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel); +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset); +int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode); +int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val); + +#else +static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, + hdd_context_t *hddctx) +{ +} +static inline void +wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) +{ +} +static inline void wlan_hdd_tdls_exit(hdd_adapter_t *adapter) +{ +} +#endif /* End of FEATURE_WLAN_TDLS */ + +#endif /* __HDD_TDLS_H */ diff --git a/core/hdd/inc/wlan_hdd_trace.h b/core/hdd/inc/wlan_hdd_trace.h new file mode 100644 index 000000000000..52208168d01e --- /dev/null +++ b/core/hdd/inc/wlan_hdd_trace.h @@ -0,0 +1,138 @@ +/* + * 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 "mac_trace.h" + +#define NO_SESSION 0xFF + +#undef ENUMS +#define ENUMS \ + ENUM(TRACE_CODE_HDD_OPEN_REQUEST) \ + ENUM(TRACE_CODE_HDD_STOP_REQUEST) \ + ENUM(TRACE_CODE_HDD_TX_TIMEOUT) \ + ENUM(TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETROAMDELTA_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETROAMDELTA_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETBAND_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETCOUNTRYREV_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_STOP_REQUEST) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_UNINIT_REQUEST) \ + ENUM(TRACE_CODE_HDD_SOFTAP_TX_TIMEOUT) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_SET_MAC_ADDR) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_P2P_SET_NOA_IOCTL) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_P2P_SET_PS_IOCTL) \ + ENUM(TRACE_CODE_HDD_HOSTAPD_SET_SAP_CHANNEL_LIST_IOCTL) \ + ENUM(TRACE_CODE_HDD_ADD_VIRTUAL_INTF) \ + ENUM(TRACE_CODE_HDD_DEL_VIRTUAL_INTF) \ + ENUM(TRACE_CODE_HDD_CHANGE_VIRTUAL_INTF) \ + ENUM(TRACE_CODE_HDD_CFG80211_START_AP) \ + ENUM(TRACE_CODE_HDD_CFG80211_CHANGE_BEACON) \ + ENUM(TRACE_CODE_HDD_CFG80211_STOP_AP) \ + ENUM(TRACE_CODE_HDD_CFG80211_CHANGE_BSS) \ + ENUM(TRACE_CODE_HDD_CFG80211_ADD_KEY) \ + ENUM(TRACE_CODE_HDD_CFG80211_GET_KEY) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY) \ + ENUM(TRACE_CODE_HDD_CFG80211_CONNECT) \ + ENUM(TRACE_CODE_HDD_CFG80211_DISCONNECT) \ + ENUM(TRACE_CODE_HDD_CFG80211_JOIN_IBSS) \ + ENUM(TRACE_CODE_HDD_CFG80211_LEAVE_IBSS) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_TXPOWER) \ + ENUM(TRACE_CODE_HDD_CFG80211_GET_TXPOWER) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_CHANNEL) \ + ENUM(TRACE_CODE_HDD_CFG80211_ADD_BEACON) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_BEACON) \ + ENUM(TRACE_CODE_HDD_CFG80211_CHANGE_IFACE) \ + ENUM(TRACE_CODE_HDD_CHANGE_STATION) \ + ENUM(TRACE_CODE_HDD_CFG80211_UPDATE_BSS) \ + ENUM(TRACE_CODE_HDD_CFG80211_SCAN) \ + ENUM(TRACE_CODE_HDD_REMAIN_ON_CHANNEL) \ + ENUM(TRACE_CODE_HDD_REMAINCHANREADYHANDLER) \ + ENUM(TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL) \ + ENUM(TRACE_CODE_HDD_ACTION) \ + ENUM(TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT) \ + ENUM(TRACE_CODE_HDD_CFG80211_GET_STA) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT) \ + ENUM(TRACE_CODE_HDD_CFG80211_DEL_STA) \ + ENUM(TRACE_CODE_HDD_CFG80211_ADD_STA) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_PMKSA) \ + ENUM(TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES) \ + ENUM(TRACE_CODE_HDD_CFG80211_TDLS_MGMT) \ + ENUM(TRACE_CODE_HDD_CFG80211_TDLS_OPER) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA) \ + ENUM(TRACE_CODE_HDD_UNSUPPORTED_IOCTL) \ + ENUM(TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL) \ + ENUM(TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL) \ + ENUM(TRACE_CODE_HDD_STORE_JOIN_REQ) \ + ENUM(TRACE_CODE_HDD_CLEAR_JOIN_REQ) \ + ENUM(TRACE_CODE_HDD_ISSUE_JOIN_REQ) + +enum { +#undef ENUM +#define ENUM(enum) enum, + ENUMS +}; + +/** + * hdd_trace_event_string() - Convert trace event to string + * @code: trace event enumeration to convert + * + * Return: string representation of the input enumeration + */ +static inline const char *hdd_trace_event_string(uint32_t code) +{ + switch (code) { + default: + return "UNKNOWN"; + break; +#undef ENUM +#define ENUM(enum) CASE_RETURN_STRING(enum) + ENUMS + } +} + +#undef ENUMS +#undef ENUM + +#ifdef HDD_TRACE_RECORD +void hdd_trace_init(void); +#else +static inline void hdd_trace_init(void) {} +#endif + +#endif diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h new file mode 100644 index 000000000000..b4b29cca5adf --- /dev/null +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -0,0 +1,154 @@ +/* + * 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_TX_RX_H) +#define WLAN_HDD_TX_RX_H + +/** + * + * DOC: wlan_hdd_tx_rx.h + * + * Linux HDD Tx/RX APIs + */ + +#include +#include +#include +#include "ol_txrx_osif_api.h" + +#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 + +int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); +void hdd_tx_timeout(struct net_device *dev); +CDF_STATUS hdd_init_tx_rx(hdd_adapter_t *pAdapter); +CDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter); +CDF_STATUS hdd_rx_packet_cbk(void *cds_context, cdf_nbuf_t rxBufChain, + uint8_t staId); + +#ifdef IPA_OFFLOAD +CDF_STATUS hdd_rx_mul_packet_cbk(void *cds_context, + cdf_nbuf_t rx_buf_list, uint8_t staId); +#endif /* IPA_OFFLOAD */ + +CDF_STATUS hdd_ibss_get_sta_id(hdd_station_ctx_t *pHddStaCtx, + struct cdf_mac_addr *pMacAddress, + uint8_t *staId); + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +void hdd_tx_resume_cb(void *adapter_context, bool tx_resume); +void hdd_tx_resume_timer_expired_handler(void *adapter_context); +void hdd_register_tx_flow_control(hdd_adapter_t *adapter, + cdf_mc_timer_callback_t timer_callback, + ol_txrx_tx_flow_control_fp flowControl); +void hdd_deregister_tx_flow_control(hdd_adapter_t *adapter); +void hdd_get_tx_resource(hdd_adapter_t *adapter, + uint8_t STAId, uint16_t timer_value); + +#else +static inline void hdd_tx_resume_cb(void *adapter_context, bool tx_resume) +{ + return; +} +static inline void hdd_tx_resume_timer_expired_handler(void *adapter_context) +{ + return; +} +static inline void hdd_register_tx_flow_control(hdd_adapter_t *adapter, + cdf_mc_timer_callback_t timer_callback, + ol_txrx_tx_flow_control_fp flowControl) +{ + return; +} +static inline void hdd_deregister_tx_flow_control(hdd_adapter_t *adapter) +{ + return; +} +static inline void hdd_get_tx_resource(hdd_adapter_t *adapter, + uint8_t STAId, uint16_t timer_value) +{ + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +#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 */ + + +const char *hdd_reason_type_to_string(enum netif_reason_type reason); +const char *hdd_action_type_to_string(enum netif_action_type action); +void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter, + enum netif_action_type action, enum netif_reason_type reason); + + +#endif /* end #if !defined(WLAN_HDD_TX_RX_H) */ diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h new file mode 100644 index 000000000000..de61e903e6ae --- /dev/null +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WEXT_IW_H__ +#define __WEXT_IW_H__ + +#include +#include +#include +#include +#include +#include +#include "cdf_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 exchnage 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 exchnage 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; + +/* + * 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 */ + struct cdf_mac_addr req_bssId; + + /** The association status code */ + uint32_t statusCode; + + /** wpa version WPA/WPA2/None*/ + int32_t wpaVersion; + + /**WPA or RSN IE*/ + uint8_t WPARSNIE[MAX_WPA_RSN_IE_LEN]; + + /**gen IE */ + tSirAddie genIE; + + /**Additional IE for assoc */ + tSirAddie assocAddIE; + + /**auth key mgmt */ + int32_t authKeyMgmt; + + /* cdf event */ + cdf_event_t hdd_cdf_event; + + cdf_event_t scanevent; + + /**Counter measure state, Started/Stopped*/ + bool mTKIPCounterMeasures; + + /**Completion Variable*/ + struct completion completion_var; + +#ifdef FEATURE_WLAN_ESE + /* ESE state variables */ + bool isESEConnection; + eCsrAuthType collectedAuthType; /* Collected from ALL SIOCSIWAUTH Ioctls. Will be negotiatedAuthType - in tCsrProfile */ +#endif +} hdd_wext_state_t; + +typedef struct ccp_freq_chan_map_s { + /* List of frequencies */ + uint32_t freq; + uint32_t chan; +} hdd_freq_chan_map_t; + +/* Packet Types. */ +#define WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 +#define WLAN_KEEP_ALIVE_NULL_PKT 1 + +/* Offload request. */ +typedef struct { + uint8_t packetType; + uint32_t timePeriod; + uint8_t hostIpv4Addr[4]; + uint8_t destIpv4Addr[4]; + uint8_t destMacAddr[ETH_ALEN]; + uint8_t bssIdx; +} tKeepAliveRequest, *tpKeepAliveRequest; + +#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_unregister_wext(struct net_device *dev); +extern int hdd_register_wext(struct net_device *dev); +extern int hdd_wlan_get_freq(uint32_t chan, uint32_t *freq); +extern int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu); +extern int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu); +extern void hdd_wlan_get_version(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu, char *extra); + +extern void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, + char *buffer, uint16_t buf_len); + +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); + +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 CDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, + tSirMacAddr macAddress); +void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter); + +uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size, + uint8_t *ie, int ie_len); + +CDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter); + +CDF_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter); + +CDF_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, int8_t *rssi_value); + +CDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr); + +#ifdef FEATURE_WLAN_TDLS +CDF_STATUS iw_set_tdls_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, int nOffset); +#endif + +void wlan_hdd_change_country_code_callback(void *pAdapter); + +int hdd_set_band(struct net_device *dev, u8 ui_band); +int hdd_set_band_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 wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature); +int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed); +#endif /* __WEXT_IW_H__ */ diff --git a/core/hdd/inc/wlan_hdd_wmm.h b/core/hdd/inc/wlan_hdd_wmm.h new file mode 100644 index 000000000000..864a1e73fc01 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_wmm.h @@ -0,0 +1,404 @@ +/* + * 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 + +/** + * DOC: HDD WMM + * + * 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 priortization. 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 + +/*Maximum number of ACs */ +#define WLAN_MAX_AC 4 + + +/* 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 */ + +/** + * enum hdd_wmm_classification: types of classification supported + */ +typedef enum hdd_wmm_classification { + HDD_WMM_CLASSIFICATION_DSCP = 0, + HDD_WMM_CLASSIFICATION_802_1Q = 1 +} hdd_wmm_classification_t; + +/** + * enum hdd_wmm_user_mode - WMM modes of operation + * + * @HDD_WMM_USER_MODE_AUTO: 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_QBSS_ONLY - SME will add the extra logic to make sure + * STA associates with a QAP only + * @HDD_WMM_USER_MODE_NO_QOS - 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. + */ +typedef enum hdd_wmm_user_mode { + HDD_WMM_USER_MODE_AUTO = 0, + HDD_WMM_USER_MODE_QBSS_ONLY = 1, + 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 + +/** + * struct hdd_wmm_qos_context - HDD WMM QoS Context + * + * This structure holds the context for a single flow which has either + * been confgured explicitly from userspace or implicitly via the + * Implicit QoS feature. + * + * @node: list node which can be used to put the context into a list + * of contexts + * @handle: identifer which uniquely identifies this context to userspace + * @qosFlowID: identifier which uniquely identifies this flow to SME + * @pAdapter: adapter upon which this flow was configured + * @acType: access category for this flow + * @lastStatus: the status of the last operation performed on this flow by SME + * @wmmAcSetupImplicitQos: work structure used for deferring implicit QoS work + * from softirq context to thread context + * @magic: magic number used to verify that this is a valid context when + * referenced anonymously + */ +typedef struct hdd_wmm_qos_context { + struct list_head node; + uint32_t handle; + uint32_t qosFlowId; + hdd_adapter_t *pAdapter; + sme_ac_enum_type acType; + hdd_wlan_wmm_status_e lastStatus; + struct work_struct wmmAcSetupImplicitQos; + uint32_t magic; + bool is_inactivity_timer_running; +} hdd_wmm_qos_context_t; + +/** + * struct hdd_wmm_ac_status - WMM related per-AC state & status info + * @wmmAcAccessRequired - does the AP require access to this AC? + * @wmmAcAccessNeeded - does the worker thread need to acquire access to + * this AC? + * @wmmAcAccessPending - is implicit QoS negotiation currently taking place? + * @wmmAcAccessFailed - has implicit QoS negotiation already failed? + * @wmmAcAccessGranted - has implicit QoS negotiation already succeeded? + * @wmmAcAccessAllowed - is access to this AC allowed, either because we + * are not doing WMM, we are not doing implicit QoS, implict QoS has + * completed, or explicit QoS has completed? + * @wmmAcTspecValid - is the wmmAcTspecInfo valid? + * @wmmAcUapsdInfoValid - are the wmmAcUapsd* fields valid? + * @wmmAcTspecInfo - current (possibly aggregate) Tspec for this AC + * @wmmAcIsUapsdEnabled - is UAPSD enabled on this AC? + * @wmmAcUapsdServiceInterval - service interval for this AC + * @wmmAcUapsdSuspensionInterval - suspension interval for this AC + * @wmmAcUapsdDirection - direction for this AC + * @wmmInactivityTime - inactivity time for this AC + * @wmmPrevTrafficCnt - TX counter used for inactivity detection + * @wmmInactivityTimer - timer used for inactivity detection + */ +typedef struct hdd_wmm_ac_status { + bool wmmAcAccessRequired; + bool wmmAcAccessNeeded; + bool wmmAcAccessPending; + bool wmmAcAccessFailed; + bool wmmAcAccessGranted; + bool wmmAcAccessAllowed; + bool wmmAcTspecValid; + bool wmmAcUapsdInfoValid; + sme_QosWmmTspecInfo wmmAcTspecInfo; + bool wmmAcIsUapsdEnabled; + uint32_t wmmAcUapsdServiceInterval; + uint32_t wmmAcUapsdSuspensionInterval; + sme_QosWmmDirType wmmAcUapsdDirection; + +#ifdef FEATURE_WLAN_ESE + uint32_t wmmInactivityTime; + uint32_t wmmPrevTrafficCnt; + cdf_mc_timer_t wmmInactivityTimer; +#endif + +} hdd_wmm_ac_status_t; + +/** + * struct hdd_wmm_status - WMM status maintained per-adapter + * @wmmContextList - list of WMM contexts active on the adapter + * @wmmLock - mutex used for exclusive access to this adapter's WMM status + * @wmmACStatus - per-AC WMM status + * @wmmQap - is this connected to a QoS-enabled AP? + * @wmmQosConnection - is this a QoS connection? + */ +typedef struct hdd_wmm_status { + struct list_head wmmContextList; + struct mutex wmmLock; + hdd_wmm_ac_status_t wmmAcStatus[WLAN_MAX_AC]; + bool wmmQap; + bool wmmQosConnection; +} hdd_wmm_status_t; + +extern const uint8_t hdd_qdisc_ac_to_tl_ac[]; +extern const uint8_t hdd_wmm_up_to_ac_map[]; +extern const uint8_t hdd_linux_up_to_ac_map[]; + +#define WLAN_HDD_MAX_DSCP 0x3f + +/** + * hdd_wmmps_helper() - Function to set uapsd psb dynamically + * + * @pAdapter: [in] pointer to adapter structure + * @ptr: [in] pointer to command buffer + * + * Return: Zero on success, appropriate error on failure. + */ +int hdd_wmmps_helper(hdd_adapter_t *pAdapter, uint8_t *ptr); + +/** + * hdd_wmm_init() - initialize the WMM DSCP configuation + * @pAdapter : [in] pointer to Adapter context + * + * This function will initialize the WMM DSCP configuation of an + * adapter to an initial state. The configuration can later be + * overwritten via application APIs or via QoS Map sent OTA. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_init(hdd_adapter_t *pAdapter); + +/** + * hdd_wmm_adapter_init() - initialize the WMM configuration of an adapter + * @pAdapter: [in] pointer to Adapter context + * + * This function will initialize the WMM configuation and status of an + * adapter to an initial state. The configuration can later be + * overwritten via application APIs + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_init(hdd_adapter_t *pAdapter); + +/** + * hdd_wmm_close() - WMM close function + * @pAdapter: [in] pointer to adapter context + * + * Function which will perform any necessary work to to clean up the + * WMM functionality prior to the kernel module unload. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_close(hdd_adapter_t *pAdapter); + +/** + * hdd_wmm_select_queue() - Function which will classify the packet + * according to linux qdisc expectation. + * + * @dev: [in] pointer to net_device structure + * @skb: [in] pointer to os packet + * + * Return: Qdisc queue index + */ +uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb); + +/** + * hdd_hostapd_select_queue() - Function which will classify the packet + * according to linux qdisc expectation. + * + * @dev: [in] pointer to net_device structure + * @skb: [in] pointer to os packet + * + * Return: Qdisc queue index + */ +uint16_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 +); + +/** + * 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 + * + * @pAdapter: [in] pointer to adapter structure + * @acType: [in] WMM AC type of OS packet + * + * Return: void + */ +void hdd_wmm_acquire_access_required(hdd_adapter_t *pAdapter, + sme_ac_enum_type acType); + +/** + * hdd_wmm_acquire_access() - Function which will attempt to acquire + * admittance for a WMM AC + * + * @pAdapter: [in] pointer to adapter context + * @acType: [in] WMM AC type of OS packet + * @pGranted: [out] pointer to bool flag when indicates if access + * has been granted or not + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_acquire_access(hdd_adapter_t *pAdapter, + sme_ac_enum_type acType, bool *pGranted); + +/** + * hdd_wmm_assoc() - Function which will handle the housekeeping + * required by WMM when association takes place + * + * @pAdapter: [in] pointer to adapter context + * @pRoamInfo: [in] pointer to roam information + * @eBssType: [in] type of BSS + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_assoc(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType); + +/** + * hdd_wmm_connect() - Function which will handle the housekeeping + * required by WMM when a connection is established + * + * @pAdapter : [in] pointer to adapter context + * @pRoamInfo: [in] pointer to roam information + * @eBssType : [in] type of BSS + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_connect(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType); + +/** + * hdd_wmm_get_uapsd_mask() - Function which will calculate the + * initial value of the UAPSD mask based upon the device configuration + * + * @pAdapter : [in] pointer to adapter context + * @pUapsdMask: [out] pointer to where the UAPSD Mask is to be stored + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_get_uapsd_mask(hdd_adapter_t *pAdapter, + uint8_t *pUapsdMask); + +/** + * hdd_wmm_is_active() - Function which will determine if WMM is + * active on the current connection + * + * @pAdapter: [in] pointer to adapter context + * + * Return: true if WMM is enabled, false if WMM is not enabled + */ +bool hdd_wmm_is_active(hdd_adapter_t *pAdapter); + +/** + * hdd_wmm_addts() - Function which will add a traffic spec at the + * request of an application + * + * @pAdapter : [in] pointer to adapter context + * @handle : [in] handle to uniquely identify a TS + * @pTspec : [in] pointer to the traffic spec + * + * Return: HDD_WLAN_WMM_STATUS_* + */ +hdd_wlan_wmm_status_e hdd_wmm_addts(hdd_adapter_t *pAdapter, + uint32_t handle, + sme_QosWmmTspecInfo *pTspec); + +/** + * hdd_wmm_delts() - Function which will delete a traffic spec at the + * request of an application + * + * @pAdapter: [in] pointer to adapter context + * @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, uint32_t handle); + +/** + * hdd_wmm_checkts() - Function which will return the status of a traffic + * spec at the request of an application + * + * @pAdapter: [in] pointer to adapter context + * @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, + uint32_t handle); +/** + * hdd_wmm_adapter_clear() - Function which will clear the WMM status + * for all the ACs + * + * @pAdapter: [in] pointer to Adapter context + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_clear(hdd_adapter_t *pAdapter); + +void wlan_hdd_process_peer_unauthorised_pause(hdd_adapter_t *adapter); +#endif /* #ifndef _WLAN_HDD_WMM_H */ diff --git a/core/hdd/inc/wlan_hdd_wowl.h b/core/hdd/inc/wlan_hdd_wowl.h new file mode 100644 index 000000000000..3230f6a78794 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_wowl.h @@ -0,0 +1,183 @@ +/* + * 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 _WLAN_HDD_WOWL_H +#define _WLAN_HDD_WOWL_H + +/** + * DOC: wlan_hdd_wowl + * + * 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 explcitly 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 deleimiting 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 deafult 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. + * + * Mangement frames are not subjected to WoWL filtering and are + * discarded when WoWL is enabled. + * + * Whenever a patern 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. + */ + +#include + +#define WOWL_PTRN_MAX_SIZE 146 +#define WOWL_PTRN_MASK_MAX_SIZE 19 +#define WOWL_MAX_PTRNS_ALLOWED CFG_MAX_WOW_FILTERS_MAX + +/** + * hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be + * used when PBM filtering is enabled + * @pAdapter: pointer to the adapter + * @ptrn: pointer to the pattern string to be added + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_add_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn); + +/** + * hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern + * @pAdapter: pointer to the adapter + * @ptrn: pointer to the pattern string to be removed + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_del_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn); + +/** + * hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern + * sent from debugfs interface + * @pAdapter: pointer to the adapter + * @pattern_idx: index of the pattern to be added + * @pattern_offset: offset of the pattern in the frame payload + * @pattern_buf: pointer to the pattern hex string to be added + * @pattern_mask: pointer to the pattern mask hex string + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx, + uint8_t pattern_offset, char *pattern_buf, + char *pattern_mask); + +/** + * hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern + * sent from debugfs interface + * @pAdapter: pointer to the adapter + * @pattern_idx: index of the pattern to be removed + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx); + +/** + * hdd_enter_wowl() - Function which will enable WoWL. At least one + * of MP and PBM must be enabled + * @pAdapter: pointer to the adapter + * @enable_mp: Whether to enable magic packet WoWL mode + * @enable_pbm: Whether to enable pattern byte matching WoWL mode + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_enter_wowl(hdd_adapter_t *pAdapter, bool enable_mp, bool enable_pbm); + +/** + * hdd_exit_wowl() - Function which will disable WoWL + * @pAdapter: pointer to the adapter + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_exit_wowl(hdd_adapter_t *pAdapter); + +/** + * hdd_init_wowl() - Init function which will initialize the WoWL module + * and perform any required initial configuration + * @pAdapter: pointer to the adapter + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_init_wowl(hdd_adapter_t *pAdapter); + +#endif /* #ifndef _WLAN_HDD_WOWL_H */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c new file mode 100644 index 000000000000..ea597dbe04bd --- /dev/null +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -0,0 +1,5426 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_assoc.c + * + * WLAN Host Device Driver implementation + * + */ + +#include "wlan_hdd_includes.h" +#include +#include "dot11f.h" +#include "wlan_hdd_power.h" +#include +#include +#include +#include +#include "wlan_hdd_cfg80211.h" +#include "csr_inside_api.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" +#include +#include +#include "cds_concurrency.h" +#include "sme_power_save_api.h" +#include "ol_txrx_ctrl_api.h" +#include "ol_txrx_types.h" + +/* These are needed to recognize WPA and RSN suite types */ +#define HDD_WPA_OUI_SIZE 4 +#define HDD_RSN_OUI_SIZE 4 +uint8_t ccp_wpa_oui00[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x00 }; +uint8_t ccp_wpa_oui01[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x01 }; +uint8_t ccp_wpa_oui02[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; +uint8_t ccp_wpa_oui03[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x03 }; +uint8_t ccp_wpa_oui04[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x04 }; +uint8_t ccp_wpa_oui05[HDD_WPA_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x05 }; + +#ifdef FEATURE_WLAN_ESE +/* CCKM */ +uint8_t ccp_wpa_oui06[HDD_WPA_OUI_SIZE] = { 0x00, 0x40, 0x96, 0x00 }; +/* CCKM */ +uint8_t ccp_rsn_oui06[HDD_RSN_OUI_SIZE] = { 0x00, 0x40, 0x96, 0x00 }; +#endif /* FEATURE_WLAN_ESE */ + +/* group cipher */ +uint8_t ccp_rsn_oui00[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x00 }; + +/* WEP-40 or RSN */ +uint8_t ccp_rsn_oui01[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x01 }; + +/* TKIP or RSN-PSK */ +uint8_t ccp_rsn_oui02[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x02 }; + +/* Reserved */ +uint8_t ccp_rsn_oui03[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x03 }; + +/* AES-CCMP */ +uint8_t ccp_rsn_oui04[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x04 }; + +/* WEP-104 */ +uint8_t ccp_rsn_oui05[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x05 }; + +#ifdef WLAN_FEATURE_11W +/* RSN-PSK-SHA256 */ +uint8_t ccp_rsn_oui07[HDD_RSN_OUI_SIZE] = { 0x00, 0x0F, 0xAC, 0x06 }; + +/* RSN-8021X-SHA256 */ +uint8_t ccp_rsn_oui08[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 HDD_PEER_AUTHORIZE_WAIT 10 + +/** + * hdd_conn_set_authenticated() - set authentication state + * @pAdapter: pointer to the adapter + * @authState: authentication state + * + * This function updates the global HDD station context + * authentication state. + * + * Return: none + */ +static void +hdd_conn_set_authenticated(hdd_adapter_t *pAdapter, uint8_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->roc_req_work, 0); +} + +/** + * hdd_conn_set_connection_state() - set connection state + * @pAdapter: pointer to the adapter + * @connState: connection state + * + * This function updates the global HDD station context connection state. + * + * Return: none + */ +void hdd_conn_set_connection_state(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->roc_req_work, 0); +} + +/** + * hdd_conn_get_connection_state() - get connection state + * @pAdapter: pointer to the adapter + * @pConnState: pointer to connection state + * + * This function updates the global HDD station context connection state. + * + * Return: true if (Infra Associated or IBSS Connected) + * and sets output parameter pConnState; + * false otherwise + */ +static inline bool hdd_conn_get_connection_state(hdd_station_ctx_t *pHddStaCtx, + eConnectionState *pConnState) +{ + bool fConnected = false; + eConnectionState connState; + + /* get the connection state. */ + connState = pHddStaCtx->conn_info.connState; + + if (eConnectionState_Associated == connState || + eConnectionState_IbssConnected == connState || + eConnectionState_IbssDisconnected == connState) { + fConnected = true; + } + + if (pConnState) + *pConnState = connState; + + return fConnected; +} + +/** + * hdd_is_connecting() - Function to check connection progress + * @hdd_sta_ctx: pointer to global HDD Station context + * + * Return: true if connecting, false otherwise + */ +bool hdd_is_connecting(hdd_station_ctx_t *hdd_sta_ctx) +{ + return hdd_sta_ctx->conn_info.connState == + eConnectionState_Connecting; +} + +/** + * hdd_conn_is_connected() - Function to check connection status + * @pHddStaCtx: pointer to global HDD Station context + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_conn_is_connected(hdd_station_ctx_t *pHddStaCtx) +{ + return hdd_conn_get_connection_state(pHddStaCtx, NULL); +} + +/** + * hdd_conn_get_connected_band() - get current connection radio band + * @pHddStaCtx: pointer to global HDD Station context + * + * Return: eCSR_BAND_24 or eCSR_BAND_5G based on current AP connection + * eCSR_BAND_ALL if not connected + */ +eCsrBand hdd_conn_get_connected_band(hdd_station_ctx_t *pHddStaCtx) +{ + uint8_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; +} + +/** + * hdd_conn_get_connected_cipher_algo() - get current connection cipher type + * @pHddStaCtx: pointer to global HDD Station context + * @pConnectedCipherAlgo: pointer to connected cipher algo + * + * Return: false if any errors encountered, true otherwise + */ +static inline bool +hdd_conn_get_connected_cipher_algo(hdd_station_ctx_t *pHddStaCtx, + eCsrEncryptionType *pConnectedCipherAlgo) +{ + bool fConnected = false; + + fConnected = hdd_conn_get_connection_state(pHddStaCtx, NULL); + + if (pConnectedCipherAlgo) + *pConnectedCipherAlgo = pHddStaCtx->conn_info.ucEncryptionType; + + return fConnected; +} + +/** + * hdd_conn_get_connected_bss_type() - get current bss type + * @pHddStaCtx: pointer to global HDD Station context + * @pConnectedBssType: pointer to connected bss type + * + * Return: false if any errors encountered, true otherwise + */ +inline bool +hdd_conn_get_connected_bss_type(hdd_station_ctx_t *pHddStaCtx, + eMib_dot11DesiredBssType *pConnectedBssType) +{ + bool fConnected = false; + + fConnected = hdd_conn_get_connection_state(pHddStaCtx, NULL); + + if (pConnectedBssType) { + *pConnectedBssType = + pHddStaCtx->conn_info.connDot11DesiredBssType; + } + + return fConnected; +} + +/** + * hdd_conn_save_connected_bss_type() - set connected bss type + * @pHddStaCtx: pointer to global HDD Station context + * @csr_roamBssType: bss type + * + * Return: none + */ +static inline void +hdd_conn_save_connected_bss_type(hdd_station_ctx_t *pHddStaCtx, + eCsrRoamBssType csr_roamBssType) +{ + switch (csr_roamBssType) { + 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: + CDF_ASSERT(0); + break; + } +} + +/** + * hdd_conn_save_connect_info() - save current connection information + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @eBssType: bss type + * + * Return: none + */ +static void +hdd_conn_save_connect_info(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; + + CDF_ASSERT(pRoamInfo); + + if (pRoamInfo) { + /* Save the BSSID for the connection */ + if (eCSR_BSS_TYPE_INFRASTRUCTURE == eBssType) { + CDF_ASSERT(pRoamInfo->pBssDesc); + cdf_copy_macaddr(&pHddStaCtx->conn_info.bssId, + &pRoamInfo->bssid); + + /* + * 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) { + cdf_copy_macaddr(&pHddStaCtx->conn_info.bssId, + &pRoamInfo->bssid); + } else { + /* + * can't happen. We need a valid IBSS or Infra setting + * in the BSSDescription or we can't function. + */ + CDF_ASSERT(0); + } + + /* notify WMM */ + hdd_wmm_connect(pAdapter, pRoamInfo, eBssType); + + if (!pRoamInfo->u.pConnectedProfile) { + CDF_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 */ + cdf_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; + } + } + /* save the connected BssType */ + hdd_conn_save_connected_bss_type(pHddStaCtx, eBssType); +} + +#if defined(WLAN_FEATURE_VOWIFI_11R) +/** + * hdd_send_ft_assoc_response() - send fast transition assoc response + * @dev: pointer to net device + * @pAdapter: pointer to adapter + * @pCsrRoamInfo: pointer to roam info + * + * 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. + * + * Return: none + */ +static void +hdd_send_ft_assoc_response(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, + FL("pCsrRoamInfo->nAssocRspLength=%d"), + (int)pCsrRoamInfo->nAssocRspLength); + return; + } + + pFTAssocRsp = + (u8 *) (pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength + + pCsrRoamInfo->nAssocReqLength); + if (pFTAssocRsp == NULL) { + hddLog(LOGE, FL("AssocReq or AssocRsp is NULL")); + return; + } + /* 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]); + + /* We need to send the IEs to the supplicant. */ + buff = kmalloc(IW_GENERIC_IE_MAX, GFP_ATOMIC); + if (buff == NULL) { + hddLog(LOGE, FL("kmalloc unable to allocate memory")); + 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 +/** + * hdd_send_ft_event() - send fast transition event + * @pAdapter: pointer to adapter + * + * 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. + * + * Return: none + */ +static void hdd_send_ft_event(hdd_adapter_t *pAdapter) +{ + uint16_t auth_resp_len = 0; + uint32_t 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; + uint8_t ftIe[DOT11F_IE_FTINFO_MAX_LEN]; + uint8_t ricIe[DOT11F_IE_RICDESCRIPTOR_MAX_LEN]; + struct net_device *dev = pAdapter->dev; +#else + char *buff; + union iwreq_data wrqu; + uint16_t str_len; +#endif + +#if defined(KERNEL_SUPPORT_11R_CFG80211) + cdf_mem_zero(ftIe, DOT11F_IE_FTINFO_MAX_LEN); + cdf_mem_zero(ricIe, DOT11F_IE_RICDESCRIPTOR_MAX_LEN); + + sme_get_rici_es(pHddCtx->hHal, pAdapter->sessionId, (u8 *) ricIe, + DOT11F_IE_RICDESCRIPTOR_MAX_LEN, &ric_ies_length); + if (ric_ies_length == 0) { + hddLog(LOGW, + FL("RIC IEs is of length 0 not sending RIC Information for now")); + } + + ftEvent.ric_ies = ricIe; + ftEvent.ric_ies_len = ric_ies_length; + hddLog(LOG1, FL("RIC IEs is of length %d"), (int)ric_ies_length); + + sme_get_ft_pre_auth_response(pHddCtx->hHal, pAdapter->sessionId, + (u8 *) ftIe, DOT11F_IE_FTINFO_MAX_LEN, + &auth_resp_len); + + if (auth_resp_len == 0) { + hddLog(LOGE, FL("AuthRsp FTIES is of length 0")); + return; + } + + sme_set_ft_pre_auth_state(pHddCtx->hHal, pAdapter->sessionId, true); + + ftEvent.target_ap = ftIe; + + ftEvent.ies = (u8 *) (ftIe + CDF_MAC_ADDR_SIZE); + ftEvent.ies_len = auth_resp_len - CDF_MAC_ADDR_SIZE; + + hddLog(LOG1, FL("ftEvent.ies_len %zu"), ftEvent.ies_len); + hddLog(LOG1, FL("ftEvent.ric_ies_len %zu"), ftEvent.ric_ies_len); + hddLog(LOG1, FL("ftEvent.target_ap %2x-%2x-%2x-%2x-%2x-%2x"), + 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, FL("kmalloc unable to allocate memory")); + return; + } + cdf_mem_zero(buff, IW_CUSTOM_MAX); + + /* Sme needs to send the RIC IEs first */ + str_len = strlcpy(buff, "RIC=", IW_CUSTOM_MAX); + sme_get_rici_es(pHddCtx->hHal, pAdapter->sessionId, + (u8 *) &(buff[str_len]), (IW_CUSTOM_MAX - str_len), + &ric_ies_length); + if (ric_ies_length == 0) { + hddLog(LOGW, + FL("RIC IEs is of length 0 not sending RIC Information for now")); + } else { + wrqu.data.length = str_len + ric_ies_length; + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff); + } + + /* Sme needs to provide the Auth Resp */ + cdf_mem_zero(buff, IW_CUSTOM_MAX); + str_len = strlcpy(buff, "AUTH=", IW_CUSTOM_MAX); + sme_get_ft_pre_auth_response(pHddCtx->hHal, pAdapter->sessionId, + (u8 *) &buff[str_len], + (IW_CUSTOM_MAX - str_len), &auth_resp_len); + + if (auth_resp_len == 0) { + kfree(buff); + hddLog(LOGE, FL("AuthRsp FTIES is of length 0")); + 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 +/** + * hdd_send_new_ap_channel_info() - send new ap channel info + * @dev: pointer to net device + * @pAdapter: pointer to adapter + * @pCsrRoamInfo: pointer to roam info + * + * 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. + * + * Return: none + */ +static void +hdd_send_new_ap_channel_info(struct net_device *dev, hdd_adapter_t *pAdapter, + tCsrRoamInfo *pCsrRoamInfo) +{ + union iwreq_data wrqu; + tSirBssDescription *descriptor = pCsrRoamInfo->pBssDesc; + + if (descriptor == NULL) { + hddLog(LOGE, FL("pCsrRoamInfo->pBssDesc(%p)"), descriptor); + return; + } + /* + * Send the Channel event, the supplicant needs this to generate + * the Adjacent AP report. + */ + hddLog(LOGW, FL("Sending up an SIOCGIWFREQ, channelId(%d)"), + 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 */ + +/** + * hdd_send_update_beacon_ies_event() - send update beacons ie event + * @pAdapter: pointer to adapter + * @pCsrRoamInfo: pointer to roam info + * + * Return: none + */ +static void +hdd_send_update_beacon_ies_event(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, FL("pCsrRoamInfo->nBeaconFrameLength = 0")); + return; + } + pBeaconIes = (u8 *) (pCsrRoamInfo->pbFrames + BEACON_FRAME_IES_OFFSET); + if (pBeaconIes == NULL) { + hddLog(LOGW, FL("Beacon IEs is NULL")); + return; + } + /* pBeaconIes needs to point to the IEs */ + hddLog(LOG1, FL("Beacon IEs is now at %02x%02x"), + (unsigned int)pBeaconIes[0], (unsigned int)pBeaconIes[1]); + hddLog(LOG1, FL("Beacon IEs length = %d"), + 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, FL("kmalloc unable to allocate memory")); + return; + } + cdf_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. + */ + cdf_mem_zero(&buff[strLen + 1], IW_CUSTOM_MAX - (strLen + 1)); + currentLen = + CDF_MIN(totalIeLen, IW_CUSTOM_MAX - (strLen + 1) - 1); + cdf_mem_copy(&buff[strLen + 1], pBeaconIes + currentOffset, + currentLen); + currentOffset += currentLen; + totalIeLen -= currentLen; + wrqu.data.length = strLen + 1 + currentLen; + if (totalIeLen) + buff[strLen] = 1; /* more chunks pending */ + else + buff[strLen] = 0; /* last chunk */ + + hddLog(LOG1, FL("Beacon IEs length to supplicant = %d"), + currentLen); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buff); + } while (totalIeLen > 0); + + kfree(buff); +} + +/** + * hdd_send_association_event() - send association event + * @dev: pointer to net device + * @pCsrRoamInfo: pointer to roam info + * + * Return: none + */ +static void hdd_send_association_event(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; + struct cdf_mac_addr peerMacAddr; + +#ifdef 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 */ + hddLog(LOG4, "LFR3:hdd_send_association_event"); +#endif + if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { + if (!pCsrRoamInfo) { + hddLog(LOGE, FL("STA in associated state but pCsrRoamInfo is null")); + return; + } + + cds_incr_active_session(pHddCtx, pAdapter->device_mode, + pAdapter->sessionId); + memcpy(wrqu.ap_addr.sa_data, pCsrRoamInfo->pBssDesc->bssId, + sizeof(pCsrRoamInfo->pBssDesc->bssId)); + +#ifdef WLAN_FEATURE_P2P_DEBUG + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { + if (global_p2p_connection_status == + P2P_CLIENT_CONNECTING_STATE_1) { + global_p2p_connection_status = + P2P_CLIENT_CONNECTED_STATE_1; + hddLog(LOGE, + "[P2P State] Changing state from Connecting state to Connected State for 8-way Handshake"); + } else if (global_p2p_connection_status == + P2P_CLIENT_CONNECTING_STATE_2) { + global_p2p_connection_status = + P2P_CLIENT_COMPLETED_STATE; + hddLog(LOGE, + "[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_send_update_beacon_ies_event(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_send_ft_assoc_response(dev, pAdapter, pCsrRoamInfo); + } +#endif + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { + tSirSmeChanInfo chan_info; + cdf_copy_macaddr(&peerMacAddr, + &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_send_peer_status_ind_to_oem_app(&peerMacAddr, + ePeerConnected, + pCsrRoamInfo-> + timingMeasCap, + pAdapter->sessionId, + &chan_info); + } +#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 == /* IBss Associated */ + pHddStaCtx->conn_info.connState) { + cds_incr_active_session(pHddCtx, pAdapter->device_mode, + pAdapter->sessionId); + memcpy(wrqu.ap_addr.sa_data, pHddStaCtx->conn_info.bssId.bytes, + ETH_ALEN); + pr_info("wlan: new IBSS connection to " MAC_ADDRESS_STR "\n", + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId.bytes)); + } else { /* Not Associated */ + + pr_info("wlan: disconnected\n"); + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + cds_decr_session_set_pcl( + pHddCtx, pAdapter->device_mode, + pAdapter->sessionId); +#if defined(FEATURE_WLAN_LFR) + wlan_hdd_enable_roaming(pAdapter); +#endif + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, true); +#endif + + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { + cdf_copy_macaddr(&peerMacAddr, + &pHddStaCtx->conn_info.bssId); + + /* send peer status indication to oem app */ + hdd_send_peer_status_ind_to_oem_app(&peerMacAddr, + ePeerDisconnected, 0, + pAdapter->sessionId, + NULL); + } +#ifdef WLAN_FEATURE_LPSS + pAdapter->rssi_send = false; + wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 0); +#endif +#ifdef FEATURE_WLAN_TDLS + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) && + (pCsrRoamInfo)) { + hddLog(LOG4, + 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 + /* 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 + } + cds_dump_concurrency_info(pHddCtx); + /* Send SCC/MCC Switching event to IPA */ + hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); + + 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) { + if ((pRoamProfile->AuthType.authType[0] == + eCSR_AUTH_TYPE_CCKM_RSN) || + (pRoamProfile->AuthType.authType[0] == + eCSR_AUTH_TYPE_CCKM_WPA)) + hdd_send_new_ap_channel_info(dev, pAdapter, + pCsrRoamInfo); + } +#endif + } +} + +/** + * hdd_conn_remove_connect_info() - remove connection info + * @pHddStaCtx: pointer to global HDD station context + * @pCsrRoamInfo: pointer to roam info + * + * Return: none + */ +static void hdd_conn_remove_connect_info(hdd_station_ctx_t *pHddStaCtx) +{ + /* Remove staId, bssId and peerMacAddress */ + pHddStaCtx->conn_info.staId[0] = 0; + cdf_mem_zero(&pHddStaCtx->conn_info.bssId, CDF_MAC_ADDR_SIZE); + cdf_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[0], + CDF_MAC_ADDR_SIZE); + + /* 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; + + cdf_mem_zero(&pHddStaCtx->conn_info.Keys, sizeof(tCsrKeys)); + cdf_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; + + cdf_mem_zero(&pHddStaCtx->conn_info.SSID, sizeof(tCsrSSIDInfo)); +} + +/** + * hdd_roam_deregister_sta() - deregister station + * @pAdapter: pointer to adapter + * @staId: station identifier + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +hdd_roam_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId) +{ + CDF_STATUS cdf_status; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + 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. + */ + } + + cdf_status = ol_txrx_clear_peer(staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, + FL("ol_txrx_clear_peer() failed for staID %d. Status(%d) [0x%08X]"), + staId, cdf_status, cdf_status); + } + return cdf_status; +} + +/** + * hdd_dis_connect_handler() - disconnect event handler + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam identifier + * @roamStatus: roam status + * @roamResult: roam result + * + * This function handles disconnect event: + * 1. Disable transmit queues; + * 2. Clean up internal connection states and data structures; + * 3. Send disconnect indication to supplicant. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_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); + uint8_t sta_id; + bool sendDisconInd = true; + + if (dev == NULL) { + hddLog(LOGE, FL("net_dev is released return")); + return CDF_STATUS_E_FAILURE; + } + /* notify apps that we can't pass traffic anymore */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + if (hdd_ipa_is_enabled(pHddCtx)) + hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0], + WLAN_STA_DISCONNECT, + pHddStaCtx->conn_info.bssId.bytes); + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, true); +#endif + +#ifdef QCA_PKT_PROTO_TRACE + /* STA disconnected, update into trace buffer */ + if (pHddCtx->config->gEnableDebugLog) + cds_pkt_trace_buf_update("ST:DISASC"); +#endif /* QCA_PKT_PROTO_TRACE */ + + /* HDD has initiated disconnect, do not send disconnect indication + * to kernel. Sending disconnected event to kernel for userspace + * initiated disconnect will be handled by hdd_DisConnectHandler call + * to cfg80211_disconnected. + */ + if ((eConnectionState_Disconnecting == + pHddStaCtx->conn_info.connState) || + (eConnectionState_NotConnected == + pHddStaCtx->conn_info.connState)) { + hddLog(LOG1, + 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); + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_Disconnecting")); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Disconnecting); + } + + hdd_clear_roam_profile_ie(pAdapter); + hdd_wmm_init(pAdapter); + + /* indicate 'disconnect' status to wpa_supplicant... */ + hdd_send_association_event(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) + cfg80211_disconnected(dev, pRoamInfo-> + reasonCode, NULL, + 0, GFP_KERNEL); + else + cfg80211_disconnected(dev, + WLAN_REASON_UNSPECIFIED, + NULL, 0, + GFP_KERNEL); + + hdd_info("sent disconnected event to nl80211, rssi: %d", + pAdapter->rssi); + } + /* + * 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)) { +#ifdef WLAN_FEATURE_P2P_DEBUG + if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { + if (global_p2p_connection_status == + P2P_CLIENT_CONNECTED_STATE_1) { + global_p2p_connection_status = + P2P_CLIENT_DISCONNECTED_STATE; + hddLog(LOGE, + "[P2P State] 8 way Handshake completed and moved to disconnected state"); + } else if (global_p2p_connection_status == + P2P_CLIENT_COMPLETED_STATE) { + global_p2p_connection_status = + P2P_NOT_ACTIVE; + hddLog(LOGE, + "[P2P State] P2P Client is removed and moved to inactive state"); + } + } +#endif + + } + } + + hdd_wmm_adapter_clear(pAdapter); +#if defined(WLAN_FEATURE_VOWIFI_11R) + sme_ft_reset(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId); +#endif + if (eCSR_ROAM_IBSS_LEAVE == roamStatus) { + sta_id = IBSS_BROADCAST_STAID; + vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(LOGE, + FL("hdd_roam_deregister_sta() failed for staID %d Status=%d [0x%x]"), + sta_id, status, status); + status = CDF_STATUS_E_FAILURE; + } + pHddCtx->sta_to_adapter[sta_id] = NULL; + } + sta_id = pHddStaCtx->conn_info.staId[0]; + + /* We should clear all sta register with TL, for now, only one. */ + vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(LOGE, + "hdd_roam_deregister_sta() failed to for staID %d. Status= %d [0x%x]", + sta_id, status, status); + status = CDF_STATUS_E_FAILURE; + } + + pHddCtx->sta_to_adapter[sta_id] = NULL; + /* Clear saved connection information in HDD */ + hdd_conn_remove_connect_info(pHddStaCtx); + hddLog(LOG1, FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_conn_set_connection_state(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 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { + sme_ps_disable_auto_ps_timer(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId); + } + /* Unblock anyone waiting for disconnect to complete */ + complete(&pAdapter->disconnect_comp_var); + return status; +} + +/** + * hdd_set_peer_authorized_event() - set peer_authorized_event + * @vdev_id: vdevid + * + * Return: None + */ +void hdd_set_peer_authorized_event(uint32_t vdev_id) +{ + hdd_context_t *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + hdd_adapter_t *adapter = NULL; + + adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id); + if (adapter == NULL) { + hddLog(LOGE, + "%s: Invalid vdev_id", __func__); + } + complete(&adapter->sta_authorized_event); +} + +/** + * hdd_change_peer_state() - change peer state + * @pAdapter: HDD adapter + * @sta_state: peer state + * @roam_synch_in_progress: roam synch in progress + * + * Return: CDF status + */ +CDF_STATUS hdd_change_peer_state(hdd_adapter_t *pAdapter, + uint8_t sta_id, + enum ol_txrx_peer_state sta_state, + bool roam_synch_in_progress) +{ + struct ol_txrx_peer_t *peer; + CDF_STATUS err; + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (!pdev) { + hdd_err("Failed to get txrx context"); + return CDF_STATUS_E_FAULT; + } + + if (sta_id >= WLAN_MAX_STA_COUNT) { + hddLog(LOGE, "Invalid sta id :%d", sta_id); + return CDF_STATUS_E_INVAL; + } + + peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); + if (!peer) + return CDF_STATUS_E_FAULT; + + err = ol_txrx_peer_state_update(pdev, + (u_int8_t *) peer->mac_addr.raw, sta_state); + if (err != CDF_STATUS_SUCCESS) { + hddLog(LOGE, "peer state update failed"); + return CDF_STATUS_E_FAULT; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_synch_in_progress) + return CDF_STATUS_SUCCESS; +#endif + + if (sta_state == ol_txrx_peer_state_auth) { +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + /* make sure event is reset */ + INIT_COMPLETION(pAdapter->sta_authorized_event); +#endif + + err = sme_set_peer_authorized(peer->mac_addr.raw, + hdd_set_peer_authorized_event, + pAdapter->sessionId); + if (err != CDF_STATUS_SUCCESS) { + hddLog(LOGE, "Failed to set the peer state to authorized"); + return CDF_STATUS_E_FAULT; + } + + if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + unsigned long rc; + + /* wait for event from firmware to set the event */ + rc = wait_for_completion_timeout( + &pAdapter->sta_authorized_event, + msecs_to_jiffies(HDD_PEER_AUTHORIZE_WAIT)); + if (!rc) { + hddLog(LOG1, "%s: timeout waiting for sta_authorized_event", + __func__); + } + ol_txrx_vdev_unpause(peer->vdev, + OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED); +#endif + } + } + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_roam_register_sta() - register station + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @staId: station identifier + * @pPeerMacAddress: peer MAC address + * @pBssDesc: pointer to BSS description + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint8_t staId, + struct cdf_mac_addr *pPeerMacAddress, + tSirBssDescription *pBssDesc) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + struct ol_txrx_desc_type staDesc = { 0 }; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (NULL == pBssDesc) + return CDF_STATUS_E_FAILURE; + + /* Get the Station ID from the one saved during the association */ + staDesc.sta_id = staId; + + /* set the QoS field appropriately */ + if (hdd_wmm_is_active(pAdapter)) + staDesc.is_qos_enabled = 1; + else + staDesc.is_qos_enabled = 0; + +#ifdef FEATURE_WLAN_WAPI + hddLog(LOG1, FL("WAPI STA Registered: %d"), + pAdapter->wapi_info.fIsWapiSta); + if (pAdapter->wapi_info.fIsWapiSta) + staDesc.is_wapi_supported = 1; + else + staDesc.is_wapi_supported = 0; +#endif /* FEATURE_WLAN_WAPI */ + + cdf_status = ol_txrx_register_peer(hdd_rx_packet_cbk, + &staDesc); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGW, + "ol_txrx_register_peer() failed to register. Status=%d [0x%08X]", + cdf_status, cdf_status); + return cdf_status; + } + + if (!pRoamInfo->fAuthRequired) { + /* + * Connections that do not need Upper layer auth, transition + * TLSHIM directly to 'Authenticated' state + */ + cdf_status = + hdd_change_peer_state(pAdapter, staDesc.sta_id, + ol_txrx_peer_state_auth, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + + hdd_conn_set_authenticated(pAdapter, true); + } else { + hddLog(LOG3, + "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", + pHddStaCtx->conn_info.staId[0]); + cdf_status = + hdd_change_peer_state(pAdapter, staDesc.sta_id, + ol_txrx_peer_state_conn, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + hdd_conn_set_authenticated(pAdapter, false); + } + return cdf_status; +} + +/** + * hdd_send_re_assoc_event() - send reassoc event + * @dev: pointer to net device + * @pAdapter: pointer to adapter + * @pCsrRoamInfo: pointer to roam info + * @reqRsnIe: pointer to RSN Information element + * @reqRsnLength: length of RSN IE + * + * Return: none + */ +static void hdd_send_re_assoc_event(struct net_device *dev, + hdd_adapter_t *pAdapter, tCsrRoamInfo *pCsrRoamInfo, + uint8_t *reqRsnIe, uint32_t reqRsnLength) +{ + unsigned int len = 0; + u8 *pFTAssocRsp = NULL; + uint8_t *rspRsnIe = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); + uint32_t 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-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. + */ + cds_decr_session_set_pcl( + pHddCtx, pAdapter->device_mode, + pAdapter->sessionId); + + /* Send the Assoc Resp, the supplicant needs this for initial Auth */ + len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; + rspRsnLength = len; + cdf_mem_copy(rspRsnIe, pFTAssocRsp, len); + cdf_mem_zero(rspRsnIe + len, IW_GENERIC_IE_MAX - len); + + chan = ieee80211_get_channel(pAdapter->wdev.wiphy, + (int)pCsrRoamInfo->pBssDesc->channelId); + cdf_mem_zero(&roam_profile, sizeof(tCsrRoamConnectedProfile)); + sme_roam_get_connect_profile(hal_handle, pAdapter->sessionId, + &roam_profile); + bss = cfg80211_get_bss(pAdapter->wdev.wiphy, chan, + pCsrRoamInfo->bssid.bytes, + &roam_profile.SSID.ssId[0], roam_profile.SSID.length, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + + 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++; + cdf_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:")); + hddLog(CDF_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; + cdf_mem_copy(buf_ptr, buf_ssid_ie, ssid_ie_len); + buf_ptr += ssid_ie_len; + cdf_mem_copy(buf_ptr, reqRsnIe, reqRsnLength); + cdf_mem_copy(rspRsnIe, pFTAssocRsp, len); + cdf_mem_zero(final_req_ie + (ssid_ie_len + reqRsnLength), + IW_GENERIC_IE_MAX - (ssid_ie_len + reqRsnLength)); + hddLog(LOG2, FL("Req RSN IE:")); + hddLog(CDF_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->config->isRoamOffloadEnabled && + pCsrRoamInfo->roamSynchInProgress) + wlan_hdd_send_roam_auth_event(pHddCtx, + pCsrRoamInfo->bssid.bytes, + reqRsnIe, reqRsnLength, rspRsnIe, + rspRsnLength, pCsrRoamInfo); +done: + sme_roam_free_connect_profile(hal_handle, &roam_profile); + if (final_req_ie) + kfree(final_req_ie); + kfree(rspRsnIe); +} + +/** + * hdd_roam_set_key_complete_handler() - Update the security parameters + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_roam_set_key_complete_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + eCsrEncryptionType connectedCipherAlgo; + bool fConnected = false; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + ENTER(); + + if (NULL == pRoamInfo) { + hddLog(LOG2, FL("pRoamInfo is NULL")); + return CDF_STATUS_E_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. + */ + hddLog(LOG2, "Set Key completion roamStatus =%d roamResult=%d " + MAC_ADDRESS_STR, roamStatus, roamResult, + MAC_ADDR_ARRAY(pRoamInfo->peerMac.bytes)); + + fConnected = hdd_conn_get_connected_cipher_algo(pHddStaCtx, + &connectedCipherAlgo); + if (fConnected) { + if (WLAN_HDD_IBSS == pAdapter->device_mode) { + uint8_t staId; + + if (cdf_is_macaddr_broadcast(&pRoamInfo->peerMac)) { + pHddStaCtx->roam_info.roamingState = + HDD_ROAM_STATE_NONE; + } else { + cdf_status = hdd_ibss_get_sta_id( + pHddStaCtx, + &pRoamInfo->peerMac, + &staId); + if (CDF_STATUS_SUCCESS == cdf_status) { + hddLog(LOG2, + "WLAN TL STA Ptk Installed for STAID=%d", + 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 + */ + cdf_status = + hdd_change_peer_state(pAdapter, pHddStaCtx->conn_info.staId[0], + ol_txrx_peer_state_auth, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + hdd_conn_set_authenticated(pAdapter, true); + if ((eCSR_ROAM_RESULT_AUTHENTICATED == roamResult) && + (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired) { + hddLog(LOG3, + "Key set for StaId= %d. Changing TL state to AUTHENTICATED", + pHddStaCtx->conn_info.staId[0]); + + /* + * Connections that do not need Upper layer + * authentication, transition TL to + * 'Authenticated' state after the keys are set. + */ + cdf_status = + hdd_change_peer_state(pAdapter, + pHddStaCtx->conn_info.staId[0], + ol_txrx_peer_state_auth, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + + hdd_conn_set_authenticated(pAdapter, true); + if ((WLAN_HDD_INFRA_STATION == + pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == + pAdapter->device_mode)) { + sme_ps_enable_auto_ps_timer + (WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + pHddStaCtx->hdd_ReassocScenario); + } + } + + 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 CDF_STATUS_SUCCESS; +} + +/** + * hdd_perform_roam_set_key_complete() - perform set key complete + * @pAdapter: pointer to adapter + * + * Return: none + */ +void hdd_perform_roam_set_key_complete(hdd_adapter_t *pAdapter) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamInfo roamInfo; + roamInfo.fAuthRequired = false; + cdf_mem_copy(roamInfo.bssid.bytes, + pHddStaCtx->roam_info.bssid, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(roamInfo.peerMac.bytes, + pHddStaCtx->roam_info.peerMac, CDF_MAC_ADDR_SIZE); + + cdf_ret_status = + hdd_roam_set_key_complete_handler(pAdapter, + &roamInfo, + pHddStaCtx->roam_info.roamId, + pHddStaCtx->roam_info.roamStatus, + eCSR_ROAM_RESULT_AUTHENTICATED); + if (cdf_ret_status != CDF_STATUS_SUCCESS) + hddLog(LOGE, FL("Set Key complete failure")); + + pHddStaCtx->roam_info.deferKeyComplete = false; +} + +/** + * hdd_association_completion_handler() - association completion handler + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t 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); + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + uint8_t reqRsnIe[DOT11F_IE_RSN_MAX_LEN]; + uint32_t 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 + bool hddDisconInProgress = false; + unsigned long rc; + + if (!pHddCtx) { + hdd_err("HDD context is NULL"); + return CDF_STATUS_E_FAILURE; + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo && pRoamInfo->roamSynchInProgress) { + /* change logging before release */ + hddLog(LOG3, "LFR3:hdd_association_completion_handler"); + } +#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) + && ((eCSR_ROAM_RESULT_ASSOCIATED == roamResult) + || (eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus))) { + hddLog(LOG1, FL("Disconnect from HDD in progress")); + hddDisconInProgress = true; + } + + if (eCSR_ROAM_RESULT_ASSOCIATED == roamResult) { + if (NULL == pRoamInfo) { + hddLog(LOGE, FL("pRoamInfo is NULL")); + return CDF_STATUS_E_FAILURE; + } + if (!hddDisconInProgress) { + hddLog(LOG1, FL("Set HDD connState to eConnectionState_Associated")); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Associated); + } + /* Save the connection info from CSR... */ + hdd_conn_save_connect_info(pAdapter, pRoamInfo, + eCSR_BSS_TYPE_INFRASTRUCTURE); +#ifdef FEATURE_WLAN_WAPI + if (pRoamInfo->u.pConnectedProfile->AuthType == + eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE + || pRoamInfo->u.pConnectedProfile->AuthType == + eCSR_AUTH_TYPE_WAPI_WAI_PSK) { + pAdapter->wapi_info.fIsWapiSta = 1; + } else { + pAdapter->wapi_info.fIsWapiSta = 0; + } +#endif /* FEATURE_WLAN_WAPI */ + + /* Indicate 'connect' status to user space */ + hdd_send_association_event(dev, pRoamInfo); + + if (cds_is_mcc_in_24G(pHddCtx)) { + if (pHddCtx->miracast_value) + cds_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 */ + wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_CARRIER_ON, + WLAN_CONTROL_PATH); + + /* + * 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(LOGW, FL("Warning:ASSOC_LINKUP_TIMEOUT")); + + /* + * 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 + if ((WLAN_MAX_STA_COUNT + 3) > pRoamInfo->staId) + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; + else + hddLog(LOGE, "%s: Wrong Staid: %d", __func__, + pRoamInfo->staId); + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; + + if (hdd_ipa_is_enabled(pHddCtx)) + hdd_ipa_wlan_evt(pAdapter, pRoamInfo->staId, + WLAN_STA_CONNECT, + pRoamInfo->bssid.bytes); + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, false); +#endif + + cds_check_concurrent_intf_and_restart_sap(pHddCtx, + pHddStaCtx, + pAdapter); + +#ifdef FEATURE_WLAN_TDLS + wlan_hdd_tdls_connection_callback(pAdapter); +#endif + +#ifdef QCA_PKT_PROTO_TRACE + /* STA Associated, update into trace buffer */ + if (pHddCtx->config->gEnableDebugLog) + cds_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 + uint8_t rspRsnIe[DOT11F_IE_RSN_MAX_LEN]; + uint32_t 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"); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_CARRIER_OFF, + WLAN_CONTROL_PATH); + return CDF_STATUS_E_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, + FL("AssocRsp is now at %02x%02x"), + (unsigned int)pFTAssocRsp[0], + (unsigned int)pFTAssocRsp[1]); + assocRsplen = + pRoamInfo->nAssocRspLength - + FT_ASSOC_RSP_IES_OFFSET; + } else { + hddLog(LOGE, FL("AssocRsp is NULL")); + 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, + FL("pFTAssocReq is now at %02x%02x"), + (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, FL("AssocReq is NULL")); + 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. + */ + cds_decr_session_set_pcl + (pHddCtx, + pAdapter->device_mode, + pAdapter->sessionId); + hddLog(LOG1, + FL("ft_carrier_on is %d, sending roamed indication"), + 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.bytes, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + GFP_KERNEL); + if (pRoamInfo->roamSynchInProgress) + wlan_hdd_send_roam_auth_event( + pHddCtx, + pRoamInfo->bssid.bytes, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + pRoamInfo); + } + if (sme_get_ftptk_state + (WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId)) { + sme_set_ftptk_state + (WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, + false); + pRoamInfo->fAuthRequired = + false; + + cdf_mem_copy(pHddStaCtx-> + roam_info.bssid, + pRoamInfo->bssid.bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pHddStaCtx-> + roam_info.peerMac, + pRoamInfo->peerMac.bytes, + CDF_MAC_ADDR_SIZE); + pHddStaCtx->roam_info.roamId = + roamId; + pHddStaCtx->roam_info. + roamStatus = roamStatus; + pHddStaCtx->roam_info. + deferKeyComplete = true; + } + } else if (!hddDisconInProgress) { + hddLog(LOG1, + FL("ft_carrier_on is %d, sending connect indication"), + ft_carrier_on); + cfg80211_connect_result(dev, + pRoamInfo-> + bssid.bytes, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + } else +#endif + { + /* + * wpa supplicant expecting WPA/RSN IE in + * connect result. + */ + csr_roam_get_wpa_rsn_req_ie(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, + &reqRsnLength, + reqRsnIe); + + csr_roam_get_wpa_rsn_rsp_ie(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_send_re_assoc_event(dev, + pAdapter, + pRoamInfo, + reqRsnIe, + reqRsnLength); + else +#endif /* FEATURE_WLAN_ESE */ + + { + hddLog(LOG1, + FL("sending connect indication to nl80211:for bssid " + MAC_ADDRESS_STR + " reason:%d and Status:%d"), + MAC_ADDR_ARRAY + (pRoamInfo->bssid.bytes), + roamResult, roamStatus); + + /* inform connect result to nl80211 */ + cfg80211_connect_result(dev, + pRoamInfo-> + bssid.bytes, + reqRsnIe, + reqRsnLength, + rspRsnIe, + rspRsnLength, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + } + } + if (!hddDisconInProgress) { + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + 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_roam_register_sta, since + * hdd_roam_register_sta will flush any cached + * data frames immediately. + */ + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + + /* + * Register the Station with TL after associated + */ + cdf_status = hdd_roam_register_sta(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. + */ + csr_roam_get_wpa_rsn_req_ie( + WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &reqRsnLength, reqRsnIe); + + hdd_send_re_assoc_event(dev, pAdapter, pRoamInfo, + reqRsnIe, reqRsnLength); + /* Reassoc successfully */ + if (pRoamInfo->fAuthRequired) { + cdf_status = + hdd_change_peer_state(pAdapter, + pHddStaCtx->conn_info.staId[0], + ol_txrx_peer_state_conn, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + hdd_conn_set_authenticated(pAdapter, false); + } else { + hddLog(LOG2, + FL("staId: %d Changing TL state to AUTHENTICATED"), + pHddStaCtx->conn_info.staId[0]); + cdf_status = + hdd_change_peer_state(pAdapter, + pHddStaCtx->conn_info.staId[0], + ol_txrx_peer_state_auth, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pRoamInfo->roamSynchInProgress +#else + false +#endif + ); + hdd_conn_set_authenticated(pAdapter, true); + } + + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + /* + * 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(LOG3, "LFR3:netif_tx_wake_all_queues"); +#endif + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + } + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, + "STA register with TL failed. status(=%d) [%08X]", + cdf_status, cdf_status); + } +#ifdef WLAN_FEATURE_11W + cdf_mem_zero(&pAdapter->hdd_stats.hddPmfStats, + sizeof(pAdapter->hdd_stats.hddPmfStats)); +#endif + } else { + hdd_wext_state_t *pWextState = + WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + if (pRoamInfo) + pr_info("wlan: connection failed with " MAC_ADDRESS_STR + " reason:%d and Status:%d\n", + MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes), + roamResult, roamStatus); + else + pr_info("wlan: connection failed with " MAC_ADDRESS_STR + " reason:%d and Status:%d\n", + MAC_ADDR_ARRAY(pWextState->req_bssId.bytes), + roamResult, roamStatus); + + /* + * 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(LOGE, + FL("send connect failure to nl80211: for bssid " + MAC_ADDRESS_STR + " reason:%d and Status:%d "), + MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes), + roamResult, roamStatus); + else + hddLog(LOGE, + FL("connect failed: for bssid " + MAC_ADDRESS_STR + " reason:%d and Status:%d "), + MAC_ADDR_ARRAY(pWextState->req_bssId.bytes), + roamResult, roamStatus); + + hdd_clear_roam_profile_ie(pAdapter); + + /* inform association failure event to nl80211 */ + if (eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == + roamResult) { + if (pRoamInfo) + cfg80211_connect_result(dev, + pRoamInfo->bssid.bytes, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + else + cfg80211_connect_result(dev, + pWextState->req_bssId.bytes, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } else { + if (pRoamInfo) { + eCsrAuthType authType = + pWextState->roamProfile.AuthType. + authType[0]; + bool isWep = + (authType == + eCSR_AUTH_TYPE_OPEN_SYSTEM) + || (authType == + eCSR_AUTH_TYPE_SHARED_KEY); + + /* + * In case of OPEN-WEP or SHARED-WEP + * authentication, send exact protocol + * reason code. This enables user + * applications to reconnect the station + * with correct configuration. + */ + cfg80211_connect_result(dev, + pRoamInfo->bssid.bytes, NULL, 0, + NULL, 0, + isWep ? pRoamInfo->reasonCode : + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else + cfg80211_connect_result(dev, + pWextState->req_bssId.bytes, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } + } + + if (pRoamInfo) { + if ((eSIR_SME_JOIN_TIMEOUT_RESULT_CODE == + pRoamInfo->statusCode) + || (eSIR_SME_AUTH_TIMEOUT_RESULT_CODE == + pRoamInfo->statusCode) + || (eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE == + pRoamInfo->statusCode)) { + wlan_hdd_cfg80211_update_bss_list(pAdapter, + pRoamInfo); + } + } + + /* + * Set connection state to eConnectionState_NotConnected only + * when CSR has completed operation - with a + * ASSOCIATION_FAILURE status. + */ + if (eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus + && !hddDisconInProgress) { + hddLog(LOG1, + FL("state to eConnectionState_NotConnected")); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_NotConnected); + } + hdd_wmm_init(pAdapter); + + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + } + + if (CDF_STATUS_SUCCESS != cds_check_and_restart_sap(pHddCtx, + roamResult, pHddStaCtx)) + return CDF_STATUS_E_FAILURE; + + cds_force_sap_on_scc(pHddCtx, roamResult); + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_roam_ibss_indication_handler() - update the status of the IBSS + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * Here we update the status of the Ibss when we receive information that we + * have started/joined an ibss session. + * + * Return: none + */ +static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + hddLog(LOG1, "%s: id %d, status %d, result %d", + 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; + struct cdf_mac_addr broadcastMacAddr = + CDF_MAC_ADDR_BROADCAST_INITIALIZER; + + if (NULL == pRoamInfo) { + CDF_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). + */ + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_IbssDisconnected")); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_IbssDisconnected); + /* notify wmm */ + hdd_wmm_connect(pAdapter, pRoamInfo, + eCSR_BSS_TYPE_IBSS); + pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = + pAdapter; + hdd_roam_register_sta(pAdapter, pRoamInfo, + IBSS_BROADCAST_STAID, + &broadcastMacAddr, + pRoamInfo->pBssDesc); + + if (pRoamInfo->pBssDesc) { + struct cfg80211_bss *bss; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + struct ieee80211_channel *chan; + int chan_no; + unsigned int freq; +#endif + /* we created the IBSS, notify supplicant */ + hddLog(LOG1, + FL("%s: created ibss " MAC_ADDRESS_STR), + 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(LOGE, + FL("%s: unable to create IBSS entry"), + pAdapter->dev->name); + return; + } + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + chan_no = pRoamInfo->pBssDesc->channelId; + + if (chan_no <= 14) + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency(chan_no, + IEEE80211_BAND_5GHZ); + + chan = ieee80211_get_channel(pAdapter->wdev.wiphy, freq); + + if (chan) + cfg80211_ibss_joined(pAdapter->dev, + bss->bssid, chan, + GFP_KERNEL); + else + hddLog(LOGE, FL("%s: chanId: %d, can't find channel"), + pAdapter->dev->name, + (int)pRoamInfo->pBssDesc->channelId); +#else + cfg80211_ibss_joined(pAdapter->dev, bss->bssid, + GFP_KERNEL); +#endif + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + pHddCtx->wiphy, +#endif + bss); + } + + break; + } + + case eCSR_ROAM_RESULT_IBSS_START_FAILED: + { + hddLog(LOGE, + FL("%s: unable to create IBSS"), pAdapter->dev->name); + break; + } + + default: + hddLog(LOGE, FL("%s: unexpected result %d"), + pAdapter->dev->name, (int)roamResult); + break; + } + + return; +} + +/** + * roam_save_ibss_station() - Save the IBSS peer MAC address in the adapter + * @pHddStaCtx: pointer to global HDD station context + * @staId: station id + * @peerMacAddress: pointer to peer MAC address + * + * This information is passed to iwconfig later. The peer that joined + * last is passed as information to iwconfig. + * + * Return: + * true if we add MAX_IBSS_PEERS or less STA + * false otherwise. + */ +static bool roam_save_ibss_station(hdd_station_ctx_t *pHddStaCtx, uint8_t staId, + struct cdf_mac_addr *peerMacAddress) +{ + bool fSuccess = false; + int idx = 0; + + for (idx = 0; idx < MAX_IBSS_PEERS; idx++) { + if (0 == pHddStaCtx->conn_info.staId[idx]) { + pHddStaCtx->conn_info.staId[idx] = staId; + + cdf_copy_macaddr(&pHddStaCtx->conn_info. + peerMacAddress[idx], peerMacAddress); + + fSuccess = true; + break; + } + } + + return fSuccess; +} + +/** + * roam_remove_ibss_station() - Remove the IBSS peer MAC address in the adapter + * @pAdapter: pointer to adapter + * @staId: station id + * + * Return: + * true if we remove MAX_IBSS_PEERS or less STA + * false otherwise. + */ +static bool roam_remove_ibss_station(hdd_adapter_t *pAdapter, uint8_t staId) +{ + bool fSuccess = false; + int idx = 0; + uint8_t valid_idx = 0; + uint8_t del_idx = 0; + uint8_t empty_slots = 0; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + for (idx = 0; idx < MAX_IBSS_PEERS; idx++) { + if (staId == pHddStaCtx->conn_info.staId[idx]) { + pHddStaCtx->conn_info.staId[idx] = 0; + + cdf_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 (MAX_IBSS_PEERS == empty_slots) { + /* Last peer departed, set the IBSS state appropriately */ + pHddStaCtx->conn_info.connState = + eConnectionState_IbssDisconnected; + hddLog(LOGE, "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]; + cdf_copy_macaddr(&pHddStaCtx->conn_info. + peerMacAddress[0], + &pHddStaCtx->conn_info. + peerMacAddress[valid_idx]); + + pHddStaCtx->conn_info.staId[valid_idx] = 0; + cdf_zero_macaddr(&pHddStaCtx->conn_info. + peerMacAddress[valid_idx]); + } + } + } + return fSuccess; +} + +/** + * roam_ibss_connect_handler() - IBSS connection handler + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * + * We update the status of the IBSS to connected in this function. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS roam_ibss_connect_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo) +{ + struct cfg80211_bss *bss; + hddLog(LOG1, FL("IBSS Connect Indication from SME. Set HDD connState to eConnectionState_IbssConnected")); + /* + * Set the internal connection state to show 'IBSS Connected' (IBSS with + * a partner stations). + */ + hdd_conn_set_connection_state(pAdapter, eConnectionState_IbssConnected); + + /* Save the connection info from CSR... */ + hdd_conn_save_connect_info(pAdapter, pRoamInfo, eCSR_BSS_TYPE_IBSS); + + /* Send the bssid address to the wext. */ + hdd_send_association_event(pAdapter->dev, pRoamInfo); + /* add bss_id to cfg80211 data base */ + bss = wlan_hdd_cfg80211_update_bss_db(pAdapter, pRoamInfo); + if (NULL == bss) { + hddLog(LOGE, + FL("%s: unable to create IBSS entry"), + pAdapter->dev->name); + return CDF_STATUS_E_FAILURE; + } + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + WLAN_HDD_GET_CTX(pAdapter)->wiphy, +#endif + bss); + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_roam_mic_error_indication_handler() - MIC error indication handler + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * This function indicates the Mic failure to the supplicant + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +hdd_roam_mic_error_indication_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * roam_roam_connect_status_update_handler() - IBSS connect status update + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * The Ibss connection status is updated regularly here in this function. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +roam_roam_connect_status_update_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + CDF_STATUS cdf_status; + + 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.bytes), + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId.bytes), + pRoamInfo->staId); + + if (!roam_save_ibss_station + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), + pRoamInfo->staId, + &pRoamInfo->peerMac)) { + hddLog(LOGW, "Max reached: Can't register new IBSS peer"); + break; + } + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; + + pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = + pAdapter; + + /* Register the Station with TL for the new peer. */ + cdf_status = hdd_roam_register_sta(pAdapter, + pRoamInfo, + pRoamInfo->staId, + &pRoamInfo->peerMac, + pRoamInfo->pBssDesc); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, + "Cannot register STA with TL for IBSS. Failed with cdf_status = %d [%08X]", + cdf_status, cdf_status); + } + 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.bytes, + &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; + cdf_copy_macaddr(&pHddStaCtx->ibss_enc_key.peerMac, + &pRoamInfo->peerMac); + + hddLog(LOG2, "New peer joined set PTK encType=%d", + pHddStaCtx->ibss_enc_key.encType); + + cdf_status = + sme_roam_set_key(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, + &pHddStaCtx->ibss_enc_key, + &roamId); + + if (CDF_STATUS_SUCCESS != cdf_status) { + hddLog(LOGE, + FL("sme_roam_set_key failed, status=%d"), + cdf_status); + return CDF_STATUS_E_FAILURE; + } + } + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); + break; + } + + case eCSR_ROAM_RESULT_IBSS_CONNECT: + { + + roam_ibss_connect_handler(pAdapter, pRoamInfo); + + break; + } + case eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED: + { + hdd_station_ctx_t *pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (!roam_remove_ibss_station(pAdapter, pRoamInfo->staId)) + hddLog(LOGW, + "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.bytes), + MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId.bytes), + pRoamInfo->staId); + + hdd_roam_deregister_sta(pAdapter, pRoamInfo->staId); + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = NULL; + pHddStaCtx->ibss_sta_generation++; + + cfg80211_del_sta(pAdapter->dev, + (const u8 *)&pRoamInfo->peerMac.bytes, + GFP_KERNEL); + break; + } + case eCSR_ROAM_RESULT_IBSS_INACTIVE: + { + hddLog(LOG3, + "Received eCSR_ROAM_RESULT_IBSS_INACTIVE from SME"); + /* Stop only when we are inactive */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_NotConnected); + + /* Send the bssid address to the wext. */ + hdd_send_association_event(pAdapter->dev, pRoamInfo); + break; + } + default: + break; + + } + + return CDF_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_TDLS +/** + * hdd_roam_register_tdlssta() - register new TDLS station + * @pAdapter: pointer to adapter + * @peerMac: pointer to peer MAC address + * @staId: station identifier + * @ucastSig: unicast signature + * + * Construct the staDesc and register with TL the new STA. + * This is called as part of ADD_STA in the TDLS setup. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_roam_register_tdlssta(hdd_adapter_t *pAdapter, + const uint8_t *peerMac, uint16_t staId, + uint8_t ucastSig) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + struct ol_txrx_desc_type staDesc = { 0 }; + + /* + * 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.sta_id = staId; + + /* set the QoS field appropriately .. */ + (hdd_wmm_is_active(pAdapter)) ? (staDesc.is_qos_enabled = 1) + : (staDesc.is_qos_enabled = 0); + + + /* Register the Station with TL... */ + cdf_status = ol_txrx_register_peer(hdd_rx_packet_cbk, + &staDesc); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("ol_txrx_register_peer() failed to register. Status=%d [0x%08X]"), + cdf_status, cdf_status); + return cdf_status; + } + + return cdf_status; +} + +/** + * hdd_roam_deregister_tdlssta() - deregister new TDLS station + * @pAdapter: pointer to adapter + * @staId: station identifier + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_roam_deregister_tdlssta(hdd_adapter_t *pAdapter, + uint8_t staId) +{ + CDF_STATUS cdf_status; + cdf_status = ol_txrx_clear_peer(staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGW, FL("ol_txrx_clear_peer() failed for staID %d. Status=%d [0x%08X]"), + staId, cdf_status, cdf_status); + } + return cdf_status; +} + +/** + * hdd_roam_tdls_status_update_handler() - TDLS status update handler + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * 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. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + tSmeTdlsPeerStateParams smeTdlsPeerStateParams; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint8_t staIdx; + hddTdlsPeer_t *curr_peer; + uint32_t reason; + + hddLog(LOG2, + ("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.bytes)); + + if (!pHddTdlsCtx) { + hddLog(LOG1, + FL("TDLS ctx is null, ignore roamResult (%d)"), + roamResult); + return status; + } + + switch (roamResult) { + case eCSR_ROAM_RESULT_ADD_TDLS_PEER: + { + if (eSIR_SME_SUCCESS != pRoamInfo->statusCode) { + hddLog(LOGE, FL("Add Sta failed. status code(=%d)"), + 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; + + hddLog(LOGW, + ("TDLS: STA IDX at %d is %d " + "of mac " + MAC_ADDRESS_STR), + staIdx, + pHddCtx-> + tdlsConnInfo[staIdx]. + staId, + MAC_ADDR_ARRAY + (pRoamInfo->peerMac.bytes)); + + cdf_copy_macaddr(&pHddCtx-> + tdlsConnInfo + [staIdx]. + peerMac, + &pRoamInfo-> + peerMac); + status = CDF_STATUS_SUCCESS; + break; + } + } + if (staIdx < pHddCtx->max_num_tdls_sta) { + if (-1 == + wlan_hdd_tdls_set_sta_id(pAdapter, + pRoamInfo-> + peerMac.bytes, + pRoamInfo-> + staId)) { + hddLog(LOGE, + "wlan_hdd_tdls_set_sta_id() failed"); + return CDF_STATUS_E_FAILURE; + } + + (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.bytes, + pRoamInfo-> + ucastSig); + } else { + status = CDF_STATUS_E_FAILURE; + hddLog(LOGE, + FL("no available slot in conn_info. staId %d cannot be stored"), + 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) { + hddLog(LOGE, + FL("Add Sta failed. status code(=%d)"), + 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) { + hddLog(LOGE, + FL("Link Establish Request failed. status(=%d)"), + 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) { + hddLog(LOGW, + ("HDD: del STA IDX = %x"), + pRoamInfo->staId); + + curr_peer = + wlan_hdd_tdls_find_peer(pAdapter, + pRoamInfo-> + peerMac.bytes, + true); + if (NULL != curr_peer + && TDLS_IS_CONNECTED(curr_peer)) { + hdd_roam_deregister_tdlssta + (pAdapter, + pRoamInfo->staId); + wlan_hdd_tdls_decrement_peer_count + (pAdapter); + } + wlan_hdd_tdls_reset_peer(pAdapter, + pRoamInfo-> + peerMac.bytes); + + pHddCtx->tdlsConnInfo[staIdx].staId = 0; + pHddCtx->tdlsConnInfo[staIdx]. + sessionId = 255; + cdf_mem_zero(&pHddCtx-> + tdlsConnInfo[staIdx]. + peerMac, + CDF_MAC_ADDR_SIZE); + status = CDF_STATUS_SUCCESS; + break; + } + } + complete(&pAdapter->tdls_del_station_comp); + } + break; + case eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND: + { + hddLog(LOGE, + FL("Sending teardown to supplicant with reason code %u"), + pRoamInfo->reasonCode); + + curr_peer = + wlan_hdd_tdls_find_peer(pAdapter, + pRoamInfo->peerMac.bytes, true); + wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, + pRoamInfo->reasonCode); + status = CDF_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) { + hddLog(LOGW, + ("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_roam_deregister_tdlssta(pAdapter, + pHddCtx-> + tdlsConnInfo + [staIdx]. + staId); + cdf_mem_zero(&smeTdlsPeerStateParams, + sizeof + (smeTdlsPeerStateParams)); + smeTdlsPeerStateParams.vdevId = + pHddCtx->tdlsConnInfo[staIdx]. + sessionId; + cdf_mem_copy(&smeTdlsPeerStateParams. + peerMacAddr, + &pHddCtx-> + tdlsConnInfo[staIdx]. + peerMac.bytes, + CDF_MAC_ADDR_SIZE); + smeTdlsPeerStateParams.peerState = + eSME_TDLS_PEER_STATE_TEARDOWN; + + hddLog(LOG1, + FL("calling sme_update_tdls_peer_state for staIdx %d " + MAC_ADDRESS_STR), + pHddCtx->tdlsConnInfo[staIdx]. + staId, + MAC_ADDR_ARRAY(pHddCtx-> + tdlsConnInfo + [staIdx]. + peerMac. + bytes)); + status = + sme_update_tdls_peer_state( + pHddCtx->hHal, + &smeTdlsPeerStateParams); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("sme_update_tdls_peer_state failed for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY + (pHddCtx-> + tdlsConnInfo[staIdx]. + peerMac.bytes)); + } + wlan_hdd_tdls_decrement_peer_count + (pAdapter); + + cdf_mem_zero(&pHddCtx-> + tdlsConnInfo[staIdx]. + peerMac, + CDF_MAC_ADDR_SIZE); + pHddCtx->tdlsConnInfo[staIdx].staId = 0; + pHddCtx->tdlsConnInfo[staIdx]. + sessionId = 255; + + status = CDF_STATUS_SUCCESS; + } + } + break; + } + case eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER: + { + /* ignore TDLS_SHOULD_DISCOVER if any concurrency detected */ + if (((1 << CDF_STA_MODE) != pHddCtx->concurrency_mode) || + (pHddCtx->no_of_active_sessions[CDF_STA_MODE] > 1)) { + hddLog(LOG2, + FL("concurrency detected. ignore SHOULD_DISCOVER concurrency_mode: 0x%x, active_sessions: %d"), + pHddCtx->concurrency_mode, + pHddCtx->no_of_active_sessions[CDF_STA_MODE]); + status = CDF_STATUS_E_FAILURE; + break; + } + + curr_peer = + wlan_hdd_tdls_get_peer(pAdapter, + pRoamInfo->peerMac.bytes); + if (!curr_peer) { + hddLog(LOGE, FL("curr_peer is null")); + status = CDF_STATUS_E_FAILURE; + } else { + if (eTDLS_LINK_CONNECTED == + curr_peer->link_status) { + hddLog(LOGE, + FL("TDLS link status is connected, ignore SHOULD_DISCOVER")); + } else { + /* + * If external control is enabled then initiate + * TDLS only if forced peer is set otherwise + * ignore should Discover trigger from fw. + */ + if (pHddCtx->config-> + fTDLSExternalControl + && (false == + curr_peer->isForcedPeer)) { + hddLog(LOG2, + FL + ("TDLS ExternalControl enabled but curr_peer is not forced, ignore SHOULD_DISCOVER")); + status = CDF_STATUS_SUCCESS; + break; + } else { + hddLog(LOG2, + FL + ("initiate TDLS setup on SHOULD_DISCOVER, fTDLSExternalControl: %d, curr_peer->isForcedPeer: %d, reason: %d"), + pHddCtx->config-> + fTDLSExternalControl, + curr_peer->isForcedPeer, + pRoamInfo->reasonCode); + } + wlan_hdd_tdls_pre_setup_init_work + (pHddTdlsCtx, curr_peer); + } + status = CDF_STATUS_SUCCESS; + } + break; + } + + case eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN: + { + curr_peer = + wlan_hdd_tdls_find_peer(pAdapter, + pRoamInfo->peerMac.bytes, true); + if (!curr_peer) { + hddLog(LOGE, FL("curr_peer is null")); + status = CDF_STATUS_E_FAILURE; + } else { + if (eTDLS_LINK_CONNECTED == + curr_peer->link_status) { + hddLog(LOGE, + FL + ("Received SHOULD_TEARDOWN for peer " + MAC_ADDRESS_STR + " staId: %d, reason: %d"), + MAC_ADDR_ARRAY(pRoamInfo-> + peerMac.bytes), + 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 { + hddLog(LOGE, + FL + ("TDLS link is not connected, ignore SHOULD_TEARDOWN, reason: %d"), + pRoamInfo->reasonCode); + } + status = CDF_STATUS_SUCCESS; + } + break; + } + + case eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED: + { + curr_peer = + wlan_hdd_tdls_find_peer(pAdapter, + pRoamInfo->peerMac.bytes, true); + if (!curr_peer) { + hddLog(LOGE, FL("curr_peer is null")); + status = CDF_STATUS_E_FAILURE; + } else { + if (eTDLS_LINK_CONNECTED == + curr_peer->link_status) { + hddLog(LOGE, + FL + ("Received SHOULD_PEER_DISCONNECTED for peer " + MAC_ADDRESS_STR + " staId: %d, reason: %d"), + MAC_ADDR_ARRAY(pRoamInfo->peerMac.bytes), + 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 { + hddLog(LOGE, + FL + ("TDLS link is not connected, ignore SHOULD_PEER_DISCONNECTED, reason: %d"), + pRoamInfo->reasonCode); + } + status = CDF_STATUS_SUCCESS; + } + break; + } + default: + { + break; + } + } + + return status; +} +#endif + +#ifdef WLAN_FEATURE_11W +/** + * hdd_indicate_unprot_mgmt_frame() - 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_indicate_unprot_mgmt_frame(hdd_adapter_t *pAdapter, uint32_t nFrameLength, + uint8_t *pbFrames, uint8_t frameType) +{ + uint8_t type = 0; + uint8_t 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)) + 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)) + 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) +/** + * hdd_indicate_tsm_ie() - send traffic stream metrics ie + * @pAdapter: pointer to adapter + * @tid: traffic identifier + * @state: state + * @measInterval: measurement interval + * + * This function sends traffic stream metrics IE information to + * the supplicant via wireless event. + * + * Return: none + */ +static void +hdd_indicate_tsm_ie(hdd_adapter_t *pAdapter, uint8_t tid, + uint8_t state, uint16_t 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(LOG1, "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); +} + +/** + * hdd_indicate_cckm_pre_auth() - send cckm preauth indication + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * + * This function sends cckm preauth indication to the supplicant + * via wireless custom event. + * + * Return: none + */ +static void +hdd_indicate_cckm_pre_auth(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(LOG1, + "CCXPREAUTHNOTIFY=" MAC_ADDRESS_STR " %d:%d", + MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes), + pRoamInfo->timestamp[0], pRoamInfo->timestamp[1]); + + nBytes = snprintf(pos, freeBytes, "CCXPREAUTHNOTIFY="); + pos += nBytes; + freeBytes -= nBytes; + + cdf_mem_copy(pos, pRoamInfo->bssid.bytes, CDF_MAC_ADDR_SIZE); + pos += CDF_MAC_ADDR_SIZE; + freeBytes -= CDF_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); +} + +/** + * hdd_indicate_ese_adj_ap_rep_ind() - send adjacent AP report indication + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * + * Return: none + */ +static void +hdd_indicate_ese_adj_ap_rep_ind(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(LOG1, "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); +} + +/** + * hdd_indicate_ese_bcn_report_no_results() - beacon report no scan results + * @pAdapter: pointer to adapter + * @measurementToken: measurement token + * @flag: flag + * @numBss: number of bss + * + * If the measurement is none and no scan results found, + * indicate the supplicant about measurement done. + * + * Return: none + */ +void +hdd_indicate_ese_bcn_report_no_results(const hdd_adapter_t *pAdapter, + const uint16_t measurementToken, + const bool flag, const uint8_t 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(LOG1, 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); +} + +/** + * hdd_indicate_ese_bcn_report_ind() - send beacon report indication + * @pAdapter: pointer to adapter + * @pRoamInfo: pointer to roam info + * + * If the measurement is none and no scan results found, + * indicate the supplicant about measurement done. + * + * Return: none + */ +static void +hdd_indicate_ese_bcn_report_ind(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; + uint8_t i = 0, len = 0; + uint8_t tot_bcn_ieLen = 0; /* total size of the beacon report data */ + uint8_t lastSent = 0, sendBss = 0; + int bcnRepFieldSize = + sizeof(pRoamInfo->pEseBcnReportRsp->bcnRepBssInfo[0]. + bcnReportFields); + uint8_t 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(LOG1, + "Measurement Done but no scan results"); + /* If the measurement is none and no scan results found, + indicate the supplicant about measurement done */ + hdd_indicate_ese_bcn_report_no_results( + 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(LOG1, "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(LOG1, "Sending %d BSS Info", + sendBss); + hddLog(LOG1, "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 */ + cdf_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(LOG1, + "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); + cdf_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; + cdf_mem_copy(pos, (char *)&len, sizeof(len)); + pos += sizeof(len); + freeBytes -= sizeof(len); + + /* copy IE from scan results */ + cdf_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 */ + +/** + * hdd_sme_roam_callback() - hdd sme roam callback + * @pContext: pointer to adapter context + * @pRoamInfo: pointer to roam info + * @roamId: roam id + * @roamStatus: roam status + * @roamResult: roam result + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS +hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, + eRoamCmdStatus roamStatus, eCsrRoamResult roamResult) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = (hdd_adapter_t *) pContext; + hdd_wext_state_t *pWextState = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; + + hddLog(LOG2, + "CSR Callback: status= %d result= %d roamID=%d", + roamStatus, roamResult, roamId); + + /* Sanity check */ + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGP, "invalid adapter or adapter has invalid magic"); + return CDF_STATUS_E_FAILURE; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + switch (roamStatus) { + case eCSR_ROAM_SESSION_OPENED: + if (pAdapter != NULL) { + 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); + cdf_ret_status = + hdd_dis_connect_handler(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. + */ + { + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, + WLAN_CONTROL_PATH); + status = + hdd_roam_deregister_sta(pAdapter, + pHddStaCtx->conn_info. + staId[0]); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGW, + FL + ("hdd_roam_deregister_sta() failed to for staID %d. Status=%d [0x%x]"), + pHddStaCtx->conn_info.staId[0], + status, status); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + } + pHddStaCtx->ft_carrier_on = true; + pHddStaCtx->hdd_ReassocScenario = 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 */ + { + 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")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE, + WLAN_CONTROL_PATH); +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ +defined(FEATURE_WLAN_LFR) + if (pHddStaCtx->ft_carrier_on == false) { +#endif + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_CARRIER_OFF, + WLAN_CONTROL_PATH); +#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_roam_deregister_sta(pAdapter, + pHddStaCtx->conn_info. + staId[0]); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGW, + FL + ("hdd_roam_deregister_sta() failed to for staID %d. Status=%d [0x%x]"), + pHddStaCtx->conn_info.staId[0], + status, status); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } +#endif + } + break; + case eCSR_ROAM_LOSTLINK: + if (roamResult == eCSR_ROAM_RESULT_LOSTLINK) { + hddLog(LOG2, "Roaming started due to connection lost"); + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + break; + } + case eCSR_ROAM_DISASSOCIATED: + { + hddLog(LOG1, "****eCSR_ROAM_DISASSOCIATED****"); + cdf_ret_status = + hdd_dis_connect_handler(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 (true == + pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx-> + sus_res_mcastbcast_filter_valid = + false; + } + + hddLog(LOG1, + "offload: disassociation happening, restoring configuredMcastBcastFilter"); + hddLog(LOG1, + "McastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(LOG1, + "offload: already called mcastbcast filter"); + (WLAN_HDD_GET_CTX(pAdapter))-> + hdd_mcastbcast_filter_set = false; + } + /* Call to clear any MC Addr List filter applied after + * successful connection. + */ + wlan_hdd_set_mc_addr_list(pAdapter, false); + } + break; + case eCSR_ROAM_IBSS_LEAVE: + hddLog(LOG1, "****eCSR_ROAM_IBSS_LEAVE****"); + cdf_ret_status = + hdd_dis_connect_handler(pAdapter, pRoamInfo, roamId, + roamStatus, roamResult); + break; + case eCSR_ROAM_ASSOCIATION_COMPLETION: + hddLog(LOG1, "****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_conn_remove_connect_info( + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)); + } + cdf_ret_status = + hdd_association_completion_handler(pAdapter, pRoamInfo, + roamId, roamStatus, + roamResult); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pRoamInfo) + pRoamInfo->roamSynchInProgress = false; +#endif + break; + case eCSR_ROAM_ASSOCIATION_FAILURE: + cdf_ret_status = hdd_association_completion_handler(pAdapter, + pRoamInfo, + roamId, + roamStatus, + roamResult); + break; + case eCSR_ROAM_IBSS_IND: + hdd_roam_ibss_indication_handler(pAdapter, pRoamInfo, roamId, + roamStatus, roamResult); + break; + + case eCSR_ROAM_CONNECT_STATUS_UPDATE: + cdf_ret_status = + roam_roam_connect_status_update_handler(pAdapter, + pRoamInfo, + roamId, + roamStatus, + roamResult); + break; + + case eCSR_ROAM_MIC_ERROR_IND: + cdf_ret_status = + hdd_roam_mic_error_indication_handler(pAdapter, + pRoamInfo, + roamId, + roamStatus, + roamResult); + break; + + case eCSR_ROAM_SET_KEY_COMPLETE: + { + cdf_ret_status = + hdd_roam_set_key_complete_handler(pAdapter, pRoamInfo, + roamId, roamStatus, + roamResult); + if (eCSR_ROAM_RESULT_AUTHENTICATED == roamResult) { + pHddStaCtx->hdd_ReassocScenario = 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 = false; +#endif + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_ROAM_FT_RESPONSE: + hdd_send_ft_event(pAdapter); + break; +#endif +#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + 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 */ + cdf_ret_status = + 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 (CDF_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth(pAdapter, + pRoamInfo)) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case eCSR_ROAM_PREAUTH_STATUS_SUCCESS: + /* + * This event will notify pre-auth completion in case of success + */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth_status(pAdapter, + pRoamInfo, 1)) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case eCSR_ROAM_PREAUTH_STATUS_FAILURE: + /* + * This event will notify pre-auth completion incase of failure. + */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_preauth_status(pAdapter, + pRoamInfo, 0)) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case eCSR_ROAM_HANDOVER_SUCCESS: + /* This event is to notify handover success. + It will be only invoked on success */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_cfg80211_roam_metrics_handover(pAdapter, + pRoamInfo)) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; +#endif + + case eCSR_ROAM_INDICATE_MGMT_FRAME: + hdd_indicate_mgmt_frame(pAdapter, + pRoamInfo->nFrameLength, + pRoamInfo->pbFrames, + pRoamInfo->frameType, + pRoamInfo->rxChan, pRoamInfo->rxRssi); + break; + case eCSR_ROAM_REMAIN_CHAN_READY: + hdd_remain_chan_ready_handler(pAdapter, pRoamInfo->roc_scan_id); + break; + case eCSR_ROAM_SEND_ACTION_CNF: + hdd_send_action_cnf(pAdapter, + (roamResult == + eCSR_ROAM_RESULT_NONE) ? true : false); + break; +#ifdef FEATURE_WLAN_TDLS + case eCSR_ROAM_TDLS_STATUS_UPDATE: + cdf_ret_status = + hdd_roam_tdls_status_update_handler(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_indicate_unprot_mgmt_frame(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_indicate_tsm_ie(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_indicate_cckm_pre_auth(pAdapter, pRoamInfo); + } + break; + } + + case eCSR_ROAM_ESE_ADJ_AP_REPORT_IND: + { + hdd_indicate_ese_adj_ap_rep_ind(pAdapter, pRoamInfo); + break; + } + + case eCSR_ROAM_ESE_BCN_REPORT_IND: + { + hdd_indicate_ese_bcn_report_ind(pAdapter, pRoamInfo); + break; + } +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + default: + break; + } + return cdf_ret_status; +} + +/** + * hdd_translate_rsn_to_csr_auth_type() - Translate RSN to CSR auth type + * @auth_suite: auth suite + * + * Return: eCsrAuthType enumeration + */ +eCsrAuthType hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]) +{ + eCsrAuthType auth_type; + /* is the auth type supported? */ + if (memcmp(auth_suite, ccp_rsn_oui01, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_RSN; + } else if (memcmp(auth_suite, ccp_rsn_oui02, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_RSN_PSK; + } else +#ifdef WLAN_FEATURE_VOWIFI_11R + if (memcmp(auth_suite, ccp_rsn_oui04, 4) == 0) { + /* Check for 11r FT Authentication with PSK */ + auth_type = eCSR_AUTH_TYPE_FT_RSN_PSK; + } else if (memcmp(auth_suite, ccp_rsn_oui03, 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, ccp_rsn_oui06, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_CCKM_RSN; + } else +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W + if (memcmp(auth_suite, ccp_rsn_oui07, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256; + } else if (memcmp(auth_suite, ccp_rsn_oui08, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_RSN_8021X_SHA256; + } else +#endif + { + auth_type = eCSR_AUTH_TYPE_UNKNOWN; + } + return auth_type; +} + +/** + * hdd_translate_wpa_to_csr_auth_type() - Translate WPA to CSR auth type + * @auth_suite: auth suite + * + * Return: eCsrAuthType enumeration + */ +eCsrAuthType hdd_translate_wpa_to_csr_auth_type(uint8_t auth_suite[4]) +{ + eCsrAuthType auth_type; + /* is the auth type supported? */ + if (memcmp(auth_suite, ccp_wpa_oui01, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_WPA; + } else if (memcmp(auth_suite, ccp_wpa_oui02, 4) == 0) { + auth_type = eCSR_AUTH_TYPE_WPA_PSK; + } else +#ifdef FEATURE_WLAN_ESE + if (memcmp(auth_suite, ccp_wpa_oui06, 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; +} + +/** + * hdd_translate_rsn_to_csr_encryption_type() - + * Translate RSN to CSR encryption type + * @cipher_suite: cipher suite + * + * Return: eCsrEncryptionType enumeration + */ +eCsrEncryptionType +hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]) +{ + eCsrEncryptionType cipher_type; + + if (memcmp(cipher_suite, ccp_rsn_oui04, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_AES; + else if (memcmp(cipher_suite, ccp_rsn_oui02, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_TKIP; + else if (memcmp(cipher_suite, ccp_rsn_oui00, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_NONE; + else if (memcmp(cipher_suite, ccp_rsn_oui01, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + else if (memcmp(cipher_suite, ccp_rsn_oui05, 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; +} + +/** + * hdd_translate_wpa_to_csr_encryption_type() - + * Translate WPA to CSR encryption type + * @cipher_suite: cipher suite + * + * Return: eCsrEncryptionType enumeration + */ +eCsrEncryptionType +hdd_translate_wpa_to_csr_encryption_type(uint8_t cipher_suite[4]) +{ + eCsrEncryptionType cipher_type; + + if (memcmp(cipher_suite, ccp_wpa_oui04, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_AES; + else if (memcmp(cipher_suite, ccp_wpa_oui02, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_TKIP; + else if (memcmp(cipher_suite, ccp_wpa_oui00, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_NONE; + else if (memcmp(cipher_suite, ccp_wpa_oui01, 4) == 0) + cipher_type = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + else if (memcmp(cipher_suite, ccp_wpa_oui05, 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; +} + +/** + * hdd_process_genie() - process gen ie + * @pAdapter: pointer to adapter + * @bssid: pointer to mac address + * @pEncryptType: pointer to encryption type + * @mcEncryptType: pointer to multicast encryption type + * @pAuthType: pointer to auth type + * + * Return: 0 on success, error number otherwise + */ +static int32_t hdd_process_genie(hdd_adapter_t *pAdapter, + u8 *bssid, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, +#ifdef WLAN_FEATURE_11W + uint8_t *pMfpRequired, uint8_t *pMfpCapable, +#endif + uint16_t gen_ie_len, uint8_t *gen_ie) +{ + tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + CDF_STATUS result; + tDot11fIERSN dot11RSNIE; + tDot11fIEWPA dot11WPAIE; + uint32_t i; + uint8_t *pRsnIe; + uint16_t RSNIeLen; + tPmkidCacheInfo PMKIDCache[4]; /* Local transfer memory */ + bool 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, FL("Invalid DOT11F RSN IE length :%d"), + 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 */ + dot11f_unpack_ie_rsn((tpAniSirGlobal) halHandle, + pRsnIe, RSNIeLen, &dot11RSNIE); + /* Copy out the encryption and authentication types */ + hddLog(LOG1, FL("pairwise cipher suite count: %d"), + dot11RSNIE.pwise_cipher_suite_count); + hddLog(LOG1, FL("authentication suite count: %d"), + 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_translate_rsn_to_csr_auth_type( + dot11RSNIE.akm_suites[0]); + /* dot11RSNIE.pwise_cipher_suite_count */ + *pEncryptType = + hdd_translate_rsn_to_csr_encryption_type( + dot11RSNIE.pwise_cipher_suites[0]); + /* dot11RSNIE.gp_cipher_suite_count */ + *mcEncryptType = + hdd_translate_rsn_to_csr_encryption_type( + 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; i < dot11RSNIE.pmkid_count; i++) { + if (is_zero_ether_addr(bssid)) { + hddLog(LOGE, FL("MAC address is all zeroes")); + break; + } + updatePMKCache = true; + /* + * For right now, I assume setASSOCIATE() has passed + * in the bssid. + */ + cdf_mem_copy(PMKIDCache[i].BSSID.bytes, + bssid, ETHER_ADDR_LEN); + cdf_mem_copy(PMKIDCache[i].PMKID, + dot11RSNIE.pmkid[i], CSR_RSN_PMKID_SIZE); + } + + if (updatePMKCache) { + /* + * Calling csr_roam_set_pmkid_cache to configure the + * PMKIDs into the cache. + */ + hddLog(LOG1, + FL("Calling sme_roam_set_pmkid_cache with cache entry %d."), + i); + /* Finally set the PMKSA ID Cache in CSR */ + result = + sme_roam_set_pmkid_cache(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, FL("Invalid DOT11F WPA IE length :%d"), + gen_ie_len); + return -EINVAL; + } + /* Skip past the EID and length byte - and four byte WiFi OUI */ + pRsnIe = gen_ie + 2 + 4; + RSNIeLen = gen_ie_len - (2 + 4); + /* Unpack the WPA IE */ + dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle, + pRsnIe, RSNIeLen, &dot11WPAIE); + /* Copy out the encryption and authentication types */ + hddLog(LOG1, FL("WPA unicast cipher suite count: %d"), + dot11WPAIE.unicast_cipher_count); + hddLog(LOG1, FL("WPA authentication suite count: %d"), + dot11WPAIE.auth_suite_count); + /* dot11WPAIE.auth_suite_count */ + /* Just translate the FIRST one */ + *pAuthType = + hdd_translate_wpa_to_csr_auth_type( + dot11WPAIE.auth_suites[0]); + /* dot11WPAIE.unicast_cipher_count */ + *pEncryptType = + hdd_translate_wpa_to_csr_encryption_type( + dot11WPAIE.unicast_ciphers[0]); + /* dot11WPAIE.unicast_cipher_count */ + *mcEncryptType = + hdd_translate_wpa_to_csr_encryption_type( + dot11WPAIE.multicast_cipher); + } else { + hddLog(LOGW, FL("gen_ie[0]: %d"), gen_ie[0]); + return -EINVAL; + } + return 0; +} + +/** + * hdd_set_genie_to_csr() - set genie to csr + * @pAdapter: pointer to adapter + * @RSNAuthType: pointer to auth type + * + * Return: 0 on success, error number otherwise + */ +int hdd_set_genie_to_csr(hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + uint32_t status = 0; + eCsrEncryptionType RSNEncryptType; + eCsrEncryptionType mcRSNEncryptType; +#ifdef WLAN_FEATURE_11W + uint8_t RSNMfpRequired = 0; + uint8_t RSNMfpCapable = 0; +#endif + u8 bssid[ETH_ALEN]; /* MAC address of assoc peer */ + /* MAC address of assoc peer */ + /* But, this routine is only called when we are NOT associated. */ + cdf_mem_copy(bssid, + pWextState->roamProfile.BSSIDs.bssid, + sizeof(bssid)); + 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_process_genie(pAdapter, bssid, + &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; +} + +/** + * hdd_set_csr_auth_type() - set csr auth type + * @pAdapter: pointer to adapter + * @RSNAuthType: auth type + * + * Return: 0 on success, error number otherwise + */ +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, FL("pHddStaCtx->conn_info.authType = %d"), + 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, + FL("set authType to CCKM WPA. AKM also 802.1X.")); + pRoamProfile->AuthType.authType[0] = + eCSR_AUTH_TYPE_CCKM_WPA; + } else if (RSNAuthType == eCSR_AUTH_TYPE_CCKM_WPA) { + hddLog(LOG1, + FL("Last chance to set authType to CCKM WPA.")); + 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, + FL("set authType to CCKM RSN. AKM also 802.1X.")); + pRoamProfile->AuthType.authType[0] = + eCSR_AUTH_TYPE_CCKM_RSN; + } else if (RSNAuthType == eCSR_AUTH_TYPE_CCKM_RSN) { + hddLog(LOG1, + FL("Last chance to set authType to CCKM RSN.")); + 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, FL("In default, unknown auth type.")); +#endif /* FEATURE_WLAN_ESE */ + pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_UNKNOWN; + break; + } + + hddLog(LOG1, FL("Set roam Authtype to %d"), + 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; + uint32_t status = 0; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + uint32_t roamId; + tCsrRoamProfile *pRoamProfile; + eMib_dot11DesiredBssType connectedBssType; + eCsrAuthType RSNAuthType; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(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 (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; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + if (pWextState->mTKIPCounterMeasures == TKIP_COUNTER_MEASURE_STARTED) { + hddLog(LOG2, FL("Counter measure is in progress")); + return -EBUSY; + } + if (SIR_MAC_MAX_SSID_LENGTH < wrqu->essid.length) + return -EINVAL; + + pRoamProfile = &pWextState->roamProfile; + if (hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType) || + (eMib_dot11DesiredBssType_independent == + pHddStaCtx->conn_info.connDot11DesiredBssType)) { + CDF_STATUS cdf_status; + + /* Need to issue a disconnect to CSR. */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + cdf_status = sme_roam_disconnect(hHal, pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + + if (CDF_STATUS_SUCCESS == cdf_status) { + 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 (CDF_STATUS_SUCCESS != status) + pWextState->roamProfile.uapsd_mask = 0; + + pWextState->roamProfile.SSIDs.numOfSSIDs = 1; + + pWextState->roamProfile.SSIDs.SSIDList->SSID.length = + wrqu->essid.length; + + cdf_mem_zero(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId, + sizeof(pWextState->roamProfile.SSIDs.SSIDList->SSID.ssId)); + cdf_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_set_genie_to_csr(pAdapter, &RSNAuthType); + + /* set auth */ + hdd_set_csr_auth_type(pAdapter, RSNAuthType); + } +#ifdef FEATURE_WLAN_WAPI + hddLog(LOG1, FL("Setting WAPI AUTH Type and Encryption Mode values")); + if (pAdapter->wapi_info.nWapiMode) { + switch (pAdapter->wapi_info.wapiAuthMode) { + case WAPI_AUTH_MODE_PSK: + { + hddLog(LOG1, FL("WAPI AUTH TYPE: PSK: %d"), + 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, FL("WAPI AUTH TYPE: CERT: %d"), + 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, FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI")); + 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_set_dhcp_till_power_active_flag(WLAN_HDD_GET_HAL_CTX(pAdapter), + true); + + pWextState->roamProfile.csrPersona = pAdapter->device_mode; + + if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType) { + hdd_select_cbmode(pAdapter, + (WLAN_HDD_GET_CTX(pAdapter))->config-> + AdHocChannel5G); + } + status = sme_roam_connect(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; + + cds_ssr_protect(__func__); + ret = __iw_set_essid(dev, info, wrqu, extra); + cds_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 + * @dwrq: pointer to iw_point + * @extra: pointer to the data + * + * Return: 0 on success, error number otherwise + */ +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; + + cds_ssr_protect(__func__); + ret = __iw_get_essid(dev, info, wrqu, extra); + cds_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 iwreq_data + * @extra: pointer to the data + * + * Return: 0 on success, error number otherwise + */ +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, FL("value %d UNKNOWN IW_AUTH_CIPHER"), + 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, FL("value %d UNKNOWN IW_AUTH_CIPHER"), + 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(LOG1, FL("CCKM AKM Set %d"), 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 = 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->collectedAuthType = + eCSR_AUTH_TYPE_RSN; + } else + if (!(wrqu->param.value & IW_AUTH_KEY_MGMT_802_1X)) { + pWextState->collectedAuthType = eCSR_AUTH_TYPE_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->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(LOG2, + "Counter Measure started %d", + wrqu->param.value); + pWextState->mTKIPCounterMeasures = + TKIP_COUNTER_MEASURE_STARTED; + } else { + hddLog(LOG2, + "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, FL("called with unsupported auth type %d"), + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_auth(dev, info, wrqu, extra); + cds_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 iwreq_data + * @extra: pointer to the data + * + * Return: 0 on success, error number otherwise + */ +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, FL("called with unknown auth type")); + 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, FL("called with WPA PSK auth type")); + 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, FL("called with RSN PSK auth type")); + wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; + return -EIO; + default: + hddLog(LOGE, FL("called with unknown auth type")); + 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, FL("called with unknown auth type %d"), + 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, FL("called with unknown auth type %d"), + pRoamProfile->negotiatedMCEncryptionType); + return -EIO; + } + } + + hddLog(LOG1, FL("called with auth type %d"), + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_auth(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_ap_address() - set ap address + * @dev: pointer to the net device + * @info: pointer to the iw request info + * @wrqu: pointer to iwreq_data + * @extra: pointer to the data + * + * This function updates the HDD global station context connection info + * BSSID with the MAC address received from the wpa_supplicant. + * + * Return: 0 on success, error number otherwise + */ +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)); + uint8_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 = (uint8_t *) wrqu->ap_addr.sa_data; + hddLog(LOG1, FL(" " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMacAddress)); + cdf_mem_copy(pHddStaCtx->conn_info.bssId.bytes, pMacAddress, + sizeof(struct cdf_mac_addr)); + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_ap_address(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_ap_address() - get ap address + * @dev: pointer to the net device + * @info: pointer to the iw request info + * @wrqu: pointer to iwreq_data + * @extra: pointer to the data + * + * This function returns currently associated BSSID. + * + * Return: 0 on success, error number otherwise + */ +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) { + cdf_mem_copy(wrqu->ap_addr.sa_data, + pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + } 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; + + cds_ssr_protect(__func__); + ret = __iw_get_ap_address(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c new file mode 100644 index 000000000000..734bd4ba4e5d --- /dev/null +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -0,0 +1,6612 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_cfg.c + * + * WLAN Host Device Driver configuration interface implementation + */ + +/* 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 +cb_notify_set_roam_prefer5_g_hz(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + sme_update_roam_prefer5_g_hz(pHddCtx->hHal, + pHddCtx->config->nRoamPrefer5GHz); +} + +static void +cb_notify_set_roam_rssi_diff(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + sme_update_roam_rssi_diff(pHddCtx->hHal, + 0, pHddCtx->config->RoamRssiDiff); +} + +static void +cb_notify_set_fast_transition_enabled(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_update_fast_transition_enabled(pHddCtx->hHal, + pHddCtx->config-> + isFastTransitionEnabled); +} + +static void +cb_notify_set_roam_intra_band(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + sme_set_roam_intra_band(pHddCtx->hHal, pHddCtx->config->nRoamIntraBand); +} + +static void cb_notify_set_wes_mode(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_wes_mode(pHddCtx->hHal, pHddCtx->config->isWESModeEnabled, 0); +} + +static void +cb_notify_set_roam_scan_n_probes(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + sme_update_roam_scan_n_probes(pHddCtx->hHal, 0, pHddCtx->config->nProbes); +} + +static void +cb_notify_set_roam_scan_home_away_time(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + sme_update_roam_scan_home_away_time(pHddCtx->hHal, 0, + pHddCtx->config->nRoamScanHomeAwayTime, + true); +} +#endif + +#ifdef FEATURE_WLAN_OKC +static void +cb_notify_set_okc_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ +} +#endif + +#ifdef FEATURE_WLAN_LFR +static void +notify_is_fast_roam_ini_feature_enabled(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_is_fast_roam_ini_feature_enabled(pHddCtx->hHal, 0, + pHddCtx->config-> + isFastRoamIniFeatureEnabled); +} + +static void +notify_is_mawc_ini_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_is_mawc_ini_feature_enabled(pHddCtx->hHal, + pHddCtx->config->MAWCEnabled); +} +#endif + +#ifdef FEATURE_WLAN_ESE +static void +cb_notify_set_ese_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_is_ese_feature_enabled(pHddCtx->hHal, 0, + pHddCtx->config->isEseIniFeatureEnabled); +} +#endif + +static void +cb_notify_set_fw_rssi_monitoring(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_config_fw_rssi_monitoring(pHddCtx->hHal, + pHddCtx->config-> + fEnableFwRssiMonitoring); +} + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +static void cb_notify_set_opportunistic_scan_threshold_diff(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_roam_opportunistic_scan_threshold_diff(pHddCtx->hHal, 0, + pHddCtx->config-> + nOpportunisticThresholdDiff); +} + +static void cb_notify_set_roam_rescan_rssi_diff(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_roam_rescan_rssi_diff(pHddCtx->hHal, + 0, pHddCtx->config->nRoamRescanRssiDiff); +} + +static void +cb_notify_set_neighbor_lookup_rssi_threshold(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_neighbor_lookup_rssi_threshold(pHddCtx->hHal, 0, + pHddCtx->config-> + nNeighborLookupRssiThreshold); +} + +static void +cb_notify_set_delay_before_vdev_stop(hdd_context_t *hdd_ctx, + unsigned long notify_id) +{ + /* + * At the point this routine is called, the value in the cfg_ini + * table has already been updated + */ + sme_set_delay_before_vdev_stop(hdd_ctx->hHal, 0, + hdd_ctx->config->delay_before_vdev_stop); +} + +static void +cb_notify_set_neighbor_scan_period(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_neighbor_scan_period(pHddCtx->hHal, 0, + pHddCtx->config->nNeighborScanPeriod); +} + +static void +cb_notify_set_neighbor_results_refresh_period(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_neighbor_scan_refresh_period(pHddCtx->hHal, 0, + pHddCtx->config-> + nNeighborResultsRefreshPeriod); +} + +static void +cb_notify_set_empty_scan_refresh_period(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_empty_scan_refresh_period(pHddCtx->hHal, 0, + pHddCtx->config-> + nEmptyScanRefreshPeriod); +} + +static void +cb_notify_set_neighbor_scan_min_chan_time(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_neighbor_scan_min_chan_time(pHddCtx->hHal, + pHddCtx->config-> + nNeighborScanMinChanTime, 0); +} + +static void +cb_notify_set_neighbor_scan_max_chan_time(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_set_neighbor_scan_max_chan_time(pHddCtx->hHal, 0, + pHddCtx->config-> + nNeighborScanMaxChanTime); +} + +static void cb_notify_set_roam_bmiss_first_bcnt(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_set_roam_bmiss_first_bcnt(pHddCtx->hHal, + 0, pHddCtx->config->nRoamBmissFirstBcnt); +} + +static void cb_notify_set_roam_bmiss_final_bcnt(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_set_roam_bmiss_final_bcnt(pHddCtx->hHal, 0, + pHddCtx->config->nRoamBmissFinalBcnt); +} + +static void cb_notify_set_roam_beacon_rssi_weight(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_set_roam_beacon_rssi_weight(pHddCtx->hHal, 0, + pHddCtx->config->nRoamBeaconRssiWeight); +} + +static void +cb_notify_set_dfs_scan_mode(hdd_context_t *pHddCtx, unsigned long notifyId) +{ + /* At the point this routine is called, the value in the hdd config + table has already been updated */ + sme_update_dfs_scan_mode(pHddCtx->hHal, 0, + pHddCtx->config->allowDFSChannelRoam); +} + +#endif + +static void cb_notify_set_enable_ssr(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_update_enable_ssr(pHddCtx->hHal, pHddCtx->config->enableSSR); +} + +static void cb_notify_set_g_sap_preferred_chan_location(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + wlansap_set_dfs_preferred_channel_location(pHddCtx->hHal, + pHddCtx->config-> + gSapPreferredChanLocation); +} +static void ch_notify_set_g_disable_dfs_japan_w53(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + wlansap_set_dfs_restrict_japan_w53(pHddCtx->hHal, + pHddCtx->config-> + gDisableDfsJapanW53); +} +static void +cb_notify_update_roam_scan_offload_enabled(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_update_roam_scan_offload_enabled(pHddCtx->hHal, + pHddCtx->config-> + isRoamOffloadScanEnabled); + if (0 == pHddCtx->config->isRoamOffloadScanEnabled) { + pHddCtx->config->bFastRoamInConIniFeatureEnabled = 0; + sme_update_enable_fast_roam_in_concurrency(pHddCtx->hHal, + pHddCtx->config-> + bFastRoamInConIniFeatureEnabled); + } +} + +static void +cb_notify_set_enable_fast_roam_in_concurrency(hdd_context_t *pHddCtx, + unsigned long notifyId) +{ + sme_update_enable_fast_roam_in_concurrency(pHddCtx->hHal, + pHddCtx->config-> + bFastRoamInConIniFeatureEnabled); +} + +/** + * 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 hdd 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->config->nhi_rssi_scan_max_count; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID: + val = hdd_ctx->config->nhi_rssi_scan_rssi_delta; + break; + + case eCSR_HI_RSSI_SCAN_DELAY_ID: + val = hdd_ctx->config->nhi_rssi_scan_delay; + break; + + case eCSR_HI_RSSI_SCAN_RSSI_UB_ID: + val = hdd_ctx->config->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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_COUNTRY_CODE_PRIORITY_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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_HEARTBEAT_THRESH_24_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, PowerUsageControl, + VAR_FLAGS_OPTIONAL, + (void *)CFG_POWER_USAGE_DEFAULT), + + REG_VARIABLE(CFG_ENABLE_LOGP_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_PS_NAME, WLAN_PARAM_Integer, + struct hdd_config, is_ps_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_PS_DEFAULT, + CFG_ENABLE_PS_MIN, + CFG_ENABLE_PS_MAX), + + REG_VARIABLE(CFG_BMPS_MINIMUM_LI_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_DOT11_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_FIXED_RATE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_SCAN_RESULT_AGE_COUNT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, IbssBssid, + VAR_FLAGS_OPTIONAL, + (void *)CFG_IBSS_BSSID_DEFAULT), + + REG_VARIABLE_STRING(CFG_INTF0_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + struct hdd_config, intfMacAddr[0], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF0_MAC_ADDR_DEFAULT), + + REG_VARIABLE_STRING(CFG_INTF1_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + struct hdd_config, intfMacAddr[1], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF1_MAC_ADDR_DEFAULT), + + REG_VARIABLE_STRING(CFG_INTF2_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + struct hdd_config, intfMacAddr[2], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF2_MAC_ADDR_DEFAULT), + + REG_VARIABLE_STRING(CFG_INTF3_MAC_ADDR_NAME, WLAN_PARAM_MacAddr, + struct hdd_config, intfMacAddr[3], + VAR_FLAGS_OPTIONAL, + (void *)CFG_INTF3_MAC_ADDR_DEFAULT), + + REG_VARIABLE(CFG_AP_QOS_UAPSD_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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(CFG_AP_ENABLE_RANDOM_BSSID_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_LTE_COEX, WLAN_PARAM_Integer, + struct hdd_config, 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_FORCE_SAP_ACS, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_AP_KEEP_ALIVE_PERIOD_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, nBeaconInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, + CFG_BEACON_INTERVAL_DEFAULT, + CFG_BEACON_INTERVAL_MIN, + CFG_BEACON_INTERVAL_MAX), + + REG_VARIABLE(CFG_ROAMING_TIME_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_RETRY_LIMIT_ZERO_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + +#ifdef WLAN_AP_STA_CONCURRENCY + REG_VARIABLE(CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_NUM_STA_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_fw_rssi_monitoring, 0), + + REG_VARIABLE(CFG_FW_MCC_RTS_CTS_PROT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_QOS_WMM_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_ese_feature_enabled, 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, + struct hdd_config, 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, + notify_is_fast_roam_ini_feature_enabled, 0), + + /* flag to turn ON/OFF Motion assistance for Legacy Fast Roaming */ + REG_DYNAMIC_VARIABLE(CFG_LFR_MAWC_FEATURE_ENABLED_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + notify_is_mawc_ini_feature_enabled, 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, + struct hdd_config, 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, + cb_notify_set_fast_transition_enabled, 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, + struct hdd_config, 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, + cb_notify_set_roam_rssi_diff, 0), + + REG_DYNAMIC_VARIABLE(CFG_ENABLE_WES_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_wes_mode, 0), +#endif +#ifdef FEATURE_WLAN_OKC + REG_DYNAMIC_VARIABLE(CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_okc_feature_enabled, 0), +#endif + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_update_roam_scan_offload_enabled, 0), + REG_VARIABLE(CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, wowlPattern, + VAR_FLAGS_OPTIONAL, + (void *)CFG_WOWL_PATTERN_DEFAULT), + + REG_VARIABLE(CFG_QOS_IMPLICIT_SETUP_ENABLED_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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_AP_LISTEN_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + REG_VARIABLE(CFG_FT_RESOURCE_REQ_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_neighbor_scan_period, 0), + + REG_DYNAMIC_VARIABLE(CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_neighbor_lookup_rssi_threshold, 0), + + REG_DYNAMIC_VARIABLE(CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_opportunistic_scan_threshold_diff, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_RESCAN_RSSI_DIFF_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_rescan_rssi_diff, 0), + + REG_VARIABLE_STRING(CFG_NEIGHBOR_SCAN_CHAN_LIST_NAME, WLAN_PARAM_String, + struct hdd_config, neighborScanChanList, + VAR_FLAGS_OPTIONAL, + (void *)CFG_NEIGHBOR_SCAN_CHAN_LIST_DEFAULT), + + REG_DYNAMIC_VARIABLE(CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_neighbor_scan_min_chan_time, 0), + + REG_DYNAMIC_VARIABLE(CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_neighbor_scan_max_chan_time, 0), + + REG_VARIABLE(CFG_11R_NEIGHBOR_REQ_MAX_TRIES_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_neighbor_results_refresh_period, 0), + + REG_DYNAMIC_VARIABLE(CFG_EMPTY_SCAN_REFRESH_PERIOD_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_empty_scan_refresh_period, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_BMISS_FIRST_BCNT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_bmiss_first_bcnt, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_BMISS_FINAL_BCNT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_bmiss_final_bcnt, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_BEACON_RSSI_WEIGHT_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_beacon_rssi_weight, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAMING_DFS_CHANNEL_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_dfs_scan_mode, 0), + + REG_DYNAMIC_VARIABLE(CFG_DELAY_BEFORE_VDEV_STOP_NAME, + WLAN_PARAM_Integer, + struct hdd_config, + 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, + struct hdd_config, + 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, + struct hdd_config, + 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, + struct hdd_config, + 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, + struct hdd_config, + 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_IGNORE_PEER_ERP_INFO_NAME, WLAN_PARAM_Integer, + struct hdd_config, ignore_peer_erp_info, + 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_HOST_SSDP_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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_NSOFFLOAD_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_CDF_TRACE_ENABLE Parameters */ + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_WDI_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_wdi, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_HDD_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_hdd, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_BMI_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_bmi, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_SME_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_sme, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_PE_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_pe, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_WMA_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_wma, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_SYS_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_sys, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_CDF_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_cdf, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_SAP_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_sap, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_HDD_SAP_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_hdd_sap, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_TELE_BCN_TRANS_LI_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_roam_prefer5_g_hz, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_INTRA_BAND, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_intra_band, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_N_PROBES, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_scan_n_probes, 0), + + REG_DYNAMIC_VARIABLE(CFG_ROAM_SCAN_HOME_AWAY_TIME, WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_roam_scan_home_away_time, 0), + +#endif + + REG_VARIABLE(CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + cb_notify_set_g_sap_preferred_chan_location, 0), + REG_DYNAMIC_VARIABLE(CFG_DISABLE_DFS_JAPAN_W53, WLAN_PARAM_Integer, + struct hdd_config, 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, + ch_notify_set_g_disable_dfs_japan_w53, 0), + REG_VARIABLE(CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_RX_STBC, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_MAX_DISCOVERY_ATTEMPT, WLAN_PARAM_Integer, + struct hdd_config, 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_PACKET_THRESHOLD, WLAN_PARAM_Integer, + struct hdd_config, 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_TRIGGER_THRESHOLD, WLAN_PARAM_SignedInteger, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), +#endif + +#ifdef WLAN_SOFTAP_VSTA_FEATURE + REG_VARIABLE(CFG_VSTA_SUPPORT_ENABLE, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_LPWR_IMG_TRANSITION_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + + REG_VARIABLE(CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + + REG_VARIABLE(CFG_VHT_ENABLE_TX_SU_BEAM_FORMER, WLAN_PARAM_Integer, + struct hdd_config, enable_su_tx_bformer, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_DEFAULT, + CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MIN, + CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MAX), + + REG_VARIABLE(CFG_SAP_ALLOW_ALL_CHANNEL_PARAM_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_DYNAMIC_VARIABLE(CFG_ENABLE_SSR, WLAN_PARAM_Integer, + struct hdd_config, enableSSR, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SSR_DEFAULT, + CFG_ENABLE_SSR_MIN, + CFG_ENABLE_SSR_MAX, + cb_notify_set_enable_ssr, 0), + + REG_VARIABLE(CFG_MAX_MEDIUM_TIME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, enableVhtFor24GHzBand, + VAR_FLAGS_OPTIONAL, + CFG_ENABLE_VHT_FOR_24GHZ_DEFAULT, + CFG_ENABLE_VHT_FOR_24GHZ_MIN, + CFG_ENABLE_VHT_FOR_24GHZ_MAX), +#endif + + REG_DYNAMIC_VARIABLE(CFG_ENABLE_FAST_ROAM_IN_CONCURRENCY, + WLAN_PARAM_Integer, + struct hdd_config, 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, + cb_notify_set_enable_fast_roam_in_concurrency, 0), + + REG_VARIABLE(CFG_ENABLE_ADAPT_RX_DRAIN_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), +#endif + REG_VARIABLE(CFG_AMSDU_SUPPORT_IN_AMPDU_NAME, WLAN_PARAM_Integer, + struct hdd_config, isAmsduSupportInAMPDU, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_AMSDU_SUPPORT_IN_AMPDU_DEFAULT, + CFG_AMSDU_SUPPORT_IN_AMPDU_MIN, + CFG_AMSDU_SUPPORT_IN_AMPDU_MAX), + + REG_VARIABLE(CFG_STRICT_5GHZ_PREF_BY_MARGIN, WLAN_PARAM_Integer, + struct hdd_config, 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_IP_TCP_UDP_CHKSUM_OFFLOAD, WLAN_PARAM_Integer, + struct hdd_config, enable_ip_tcp_udp_checksum_offload, + VAR_FLAGS_OPTIONAL, + CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_DEFAULT, + CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_DISABLE, + CFG_ENABLE_IP_TCP_UDP_CHKSUM_OFFLOAD_ENABLE), + + REG_VARIABLE(CFG_POWERSAVE_OFFLOAD_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + +#ifdef IPA_OFFLOAD + REG_VARIABLE(CFG_IPA_OFFLOAD_CONFIG_NAME, WLAN_PARAM_HexInteger, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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 + +#ifdef WLAN_FEATURE_11AC + REG_VARIABLE(CFG_VHT_AMPDU_LEN_EXPONENT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + + REG_VARIABLE(CFG_THERMAL_TEMP_MIN_LEVEL0_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_RX_THREAD, WLAN_PARAM_Integer, + struct hdd_config, enableRxThread, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_RX_THREAD_DEFAULT, + CFG_ENABLE_RX_THREAD_MIN, + CFG_ENABLE_RX_THREAD_MAX), + + REG_VARIABLE(CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + REG_VARIABLE(CFG_LL_TX_FLOW_LWM, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_LEGACY_TX_FLOW_CONTROL */ +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + + REG_VARIABLE(CFG_LL_TX_FLOW_STOP_QUEUE_TH, WLAN_PARAM_Integer, + struct hdd_config, TxFlowStopQueueThreshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_FLOW_STOP_QUEUE_TH_DEFAULT, + CFG_LL_TX_FLOW_STOP_QUEUE_TH_MIN, + CFG_LL_TX_FLOW_STOP_QUEUE_TH_MAX), + + REG_VARIABLE(CFG_LL_TX_FLOW_START_QUEUE_OFFSET, WLAN_PARAM_Integer, + struct hdd_config, TxFlowStartQueueOffset, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LL_TX_FLOW_START_QUEUE_OFFSET_DEFAULT, + CFG_LL_TX_FLOW_START_QUEUE_OFFSET_MIN, + CFG_LL_TX_FLOW_START_QUEUE_OFFSET_MAX), + +#endif + REG_VARIABLE(CFG_INITIAL_DWELL_TIME_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_SAP_MAX_OFFLOAD_PEERS, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + +#ifdef MEMORY_DEBUG + REG_VARIABLE(CFG_ENABLE_MEMORY_DEBUG_NAME, WLAN_PARAM_Integer, + struct hdd_config, IsMemoryDebugSupportEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_MEMORY_DEBUG_DEFAULT, + CFG_ENABLE_MEMORY_DEBUG_MIN, + CFG_ENABLE_MEMORY_DEBUG_MAX), +#endif + + REG_VARIABLE(CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), +#endif + + REG_VARIABLE(CFG_ENABLE_FW_LOG_TYPE, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_STRING(CFG_ENABLE_FW_MODULE_LOG_LEVEL, WLAN_PARAM_String, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_IGNORE_CAC_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + + REG_VARIABLE(CFG_IPA_UC_TX_BUF_COUNT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + REG_VARIABLE(CFG_WLAN_LOGGING_SUPPORT_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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_STRING(CFG_DHCP_SERVER_IP_NAME, WLAN_PARAM_String, + struct hdd_config, dhcpServerIP, + VAR_FLAGS_OPTIONAL, + (void *)CFG_DHCP_SERVER_IP_DEFAULT), +#endif /* DHCP_SERVER_OFFLOAD */ + + REG_VARIABLE(CFG_ENABLE_DEAUTH_BEFORE_CONNECTION, WLAN_PARAM_Integer, + struct hdd_config, 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_ENABLE_MAC_ADDR_SPOOFING, WLAN_PARAM_Integer, + struct hdd_config, 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), + + REG_VARIABLE(CFG_ENABLE_CUSTOM_CONC_RULE1_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + + REG_VARIABLE(CFG_STA_MIRACAST_MCC_REST_TIME_VAL, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, + 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, + struct hdd_config, 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_RAMDUMP_COLLECTION, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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_ENABLE_NON_DFS_CHAN_ON_RADAR, WLAN_PARAM_Integer, + struct hdd_config, 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_MULTICAST_HOST_FW_MSGS, WLAN_PARAM_Integer, + struct hdd_config, 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_CONC_SYSTEM_PREF, WLAN_PARAM_Integer, + struct hdd_config, conc_system_pref, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CONC_SYSTEM_PREF_DEFAULT, + CFG_CONC_SYSTEM_PREF_MIN, + CFG_CONC_SYSTEM_PREF_MAX), + + REG_VARIABLE(CFG_POLICY_MNGR_ENABLE, WLAN_PARAM_Integer, + struct hdd_config, policy_manager_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_POLICY_MNGR_ENABLE_DEFAULT, + CFG_POLICY_MNGR_ENABLE_MIN, + CFG_POLICY_MNGR_ENABLE_MAX), + + REG_VARIABLE(CFG_TSO_ENABLED_NAME, WLAN_PARAM_Integer, + struct hdd_config, tso_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TSO_ENABLED_DEFAULT, + CFG_TSO_ENABLED_MIN, + CFG_TSO_ENABLED_MAX), + + REG_VARIABLE(CFG_LRO_ENABLED_NAME, WLAN_PARAM_Integer, + struct hdd_config, lro_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_LRO_ENABLED_DEFAULT, + CFG_LRO_ENABLED_MIN, + CFG_LRO_ENABLED_MAX), + + REG_VARIABLE(CFG_ACTIVE_MODE_OFFLOAD, WLAN_PARAM_Integer, + struct hdd_config, active_mode_offload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ACTIVE_MODE_OFFLOAD_DEFAULT, + CFG_ACTIVE_MODE_OFFLOAD_MIN, + CFG_ACTIVE_MODE_OFFLOAD_MAX), + + REG_VARIABLE(CFG_FINE_TIME_MEAS_CAPABILITY, WLAN_PARAM_HexInteger, + struct hdd_config, 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), + +#ifdef WLAN_FEATURE_FASTPATH + REG_VARIABLE(CFG_ENABLE_FASTPATH, WLAN_PARAM_Integer, + struct hdd_config, fastpath_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FASTPATH_DEFAULT, + CFG_ENABLE_FASTPATH_MIN, + CFG_ENABLE_FASTPATH_MAX), +#endif + REG_VARIABLE(CFG_MAX_SCAN_COUNT_NAME, WLAN_PARAM_Integer, + struct hdd_config, max_scan_count, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_SCAN_COUNT_DEFAULT, + CFG_MAX_SCAN_COUNT_MIN, + CFG_MAX_SCAN_COUNT_MAX), + + REG_VARIABLE(CFG_DOT11P_MODE_NAME, WLAN_PARAM_Integer, + struct hdd_config, dot11p_mode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DOT11P_MODE_DEFAULT, + CFG_DOT11P_MODE_MIN, + CFG_DOT11P_MODE_MAX), + +#ifdef FEATURE_NAPI + REG_VARIABLE(CFG_NAPI_NAME, WLAN_PARAM_Integer, + struct hdd_config, napi_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NAPI_DEFAULT, + CFG_NAPI_MIN, + CFG_NAPI_MAX), +#endif /* FEATURE_NAPI */ + +#ifdef FEATURE_WLAN_EXTSCAN + REG_VARIABLE(CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_NAME, + WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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 + + REG_VARIABLE(CFG_CE_CLASSIFY_ENABLE_NAME, WLAN_PARAM_Integer, + struct hdd_config, ce_classify_enabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CE_CLASSIFY_ENABLE_DEFAULT, + CFG_CE_CLASSIFY_ENABLE_MIN, + CFG_CE_CLASSIFY_ENABLE_MAX), + + REG_VARIABLE(CFG_DUAL_MAC_FEATURE_DISABLE, WLAN_PARAM_HexInteger, + struct hdd_config, dual_mac_feature_disable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DUAL_MAC_FEATURE_DISABLE_DEFAULT, + CFG_DUAL_MAC_FEATURE_DISABLE_MIN, + CFG_DUAL_MAC_FEATURE_DISABLE_MAX), + + REG_VARIABLE(CFG_TX_CHAIN_MASK_CCK, WLAN_PARAM_Integer, + struct hdd_config, 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, + struct hdd_config, 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, + struct hdd_config, 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), + +}; + + +/** + * get_next_line() - find and locate the new line pointer + * @str: pointer to string + * + * This function returns a pointer to the character after the occurence + * of a new line character. It also modifies the original string by replacing + * the '\n' character with the null character. + * + * Return: the pointer to the character at new line, + * or NULL if no new line character was found + */ +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) == ' ') + +/** + * i_trim() - trims any leading and trailing white spaces + * @str: pointer to string + * + * Return: the pointer of the string + */ +static char *i_trim(char *str) +{ + char *ptr; + + if (*str == '\0') + return str; + + /* Find the first non white-space */ + ptr = str; + while (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; + + while (ptr != str && i_isspace(*ptr)) + ptr--; + + /* Null terminate the following character */ + ptr[1] = '\0'; + + return str; +} + +/* Maximum length of the confgiuration name and value */ +#define CFG_VALUE_MAX_LEN 256 +#define CFG_ENTRY_MAX_LEN (32+CFG_VALUE_MAX_LEN) + +/** + * hdd_cfg_get_config() - get the configuration content + * @reg_table: pointer to configuration table + * @cRegTableEntries: number of the configuration entries + * @ini_struct: pointer to the hdd config knob + * @pHddCtx: pointer to hdd context + * @pBuf: buffer to store the configuration + * @buflen: size of the buffer + * + * Return: CDF_STATUS_SUCCESS if the configuration and buffer size can carry + * the content, otherwise CDF_STATUS_E_RESOURCES + */ +static CDF_STATUS hdd_cfg_get_config(REG_TABLE_ENTRY *reg_table, + unsigned long cRegTableEntries, + uint8_t *ini_struct, + hdd_context_t *pHddCtx, char *pBuf, + int buflen) +{ + unsigned int idx; + REG_TABLE_ENTRY *pRegEntry = reg_table; + uint32_t value; + char valueStr[CFG_VALUE_MAX_LEN]; + char configStr[CFG_ENTRY_MAX_LEN]; + char *fmt; + void *pField; + struct cdf_mac_addr *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 = (struct cdf_mac_addr *) 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->config-> + 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 CDF_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 CDF_STATUS_SUCCESS; +} + +/** struct tCfgIniEntry - ini configuration entry + * + * @name: name of the entry + * @value: value of the entry + */ +typedef struct { + char *name; + char *value; +} tCfgIniEntry; + +/** + * find_cfg_item() - find the configuration item + * @iniTable: pointer to configuration table + * @entries: number fo the configuration entries + * @name: the interested configuration to find + * @value: the value to read back + * + * Return: CDF_STATUS_SUCCESS if the interested configuration is found, + * otherwise CDF_STATUS_E_FAILURE + */ +static CDF_STATUS find_cfg_item(tCfgIniEntry *iniTable, unsigned long entries, + char *name, char **value) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + unsigned long i; + + for (i = 0; i < entries; i++) { + if (strcmp(iniTable[i].name, name) == 0) { + *value = iniTable[i].value; + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Found %s entry for Name=[%s] Value=[%s] ", + WLAN_INI_FILE, name, *value); + return CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/** + * parse_hex_digit() - conversion to hex value + * @c: the character to convert + * + * Return: the hex value, otherwise 0 + */ +static int parse_hex_digit(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; +} + +/** + * update_mac_from_string() - convert string to 6 bytes mac address + * @pHddCtx: the pointer to hdd context + * @macTable: the macTable to carry the conversion + * @num: number of the interface + * + * 00AA00BB00CC -> 0x00 0xAA 0x00 0xBB 0x00 0xCC + * + * Return: None + */ +static void update_mac_from_string(hdd_context_t *pHddCtx, + tCfgIniEntry *macTable, int num) +{ + int i = 0, j = 0, res = 0; + char *candidate = NULL; + struct cdf_mac_addr macaddr[CDF_MAX_CONCURRENCY_PERSONA]; + + memset(macaddr, 0, sizeof(macaddr)); + + for (i = 0; i < num; i++) { + candidate = macTable[i].value; + for (j = 0; j < CDF_MAC_ADDR_SIZE; j++) { + res = + hex2bin(&macaddr[i].bytes[j], &candidate[(j << 1)], + 1); + if (res < 0) + break; + } + if (res == 0 && !cdf_is_macaddr_zero(&macaddr[i])) { + cdf_mem_copy((uint8_t *) &pHddCtx->config-> + intfMacAddr[i].bytes[0], + (uint8_t *) &macaddr[i].bytes[0], + CDF_MAC_ADDR_SIZE); + } + } +} + +/** + * hdd_apply_cfg_ini() - apply the ini configuration file + * @pHddCtx: the pointer to hdd context + * @iniTable: pointer to configuration table + * @entries: number fo the configuration entries + * It overwrites the MAC address if config file exist. + * + * Return: CDF_STATUS_SUCCESS if the ini configuration file is correctly parsed, + * otherwise CDF_STATUS_E_INVAL + */ +static CDF_STATUS hdd_apply_cfg_ini(hdd_context_t *pHddCtx, + tCfgIniEntry *iniTable, + unsigned long entries) +{ + CDF_STATUS match_status = CDF_STATUS_E_FAILURE; + CDF_STATUS ret_status = CDF_STATUS_SUCCESS; + unsigned int idx; + void *pField; + char *value_str = NULL; + unsigned long len_value_str; + char *candidate; + uint32_t value; + int32_t svalue; + void *pStructBase = pHddCtx->config; + REG_TABLE_ENTRY *pRegEntry = g_registry_table; + unsigned long cRegTableEntries = CDF_ARRAY_SIZE(g_registry_table); + uint32_t cbOutString; + int i; + int rv; + + /* sanity test */ + if (MAX_CFG_INI_ITEMS < cRegTableEntries) { + hddLog(LOGE, + "%s: MAX_CFG_INI_ITEMS too small, must be at least %ld", + __func__, cRegTableEntries); + } + + for (idx = 0; idx < cRegTableEntries; idx++, pRegEntry++) { + /* Calculate the address of the destination field in the structure. */ + pField = ((uint8_t *) pStructBase) + pRegEntry->VarOffset; + + match_status = + find_cfg_item(iniTable, entries, pRegEntry->RegName, + &value_str); + + if ((match_status != CDF_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 = CDF_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 == CDF_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 == CDF_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 (CDF_STATUS_SUCCESS == match_status) { + rv = kstrtos32(value_str, 10, &svalue); + if (rv < 0) { + hddLog(CDF_TRACE_LEVEL_WARN, + "%s: Reg Parameter %s invalid. Enforcing Default", + __func__, pRegEntry->RegName); + svalue = + (int32_t) pRegEntry->VarDefault; + } + } else { + svalue = (int32_t) pRegEntry->VarDefault; + } + + /* If this parameter needs range checking, do it here. */ + if (pRegEntry->Flags & VAR_FLAGS_RANGE_CHECK) { + if (svalue > (int32_t) pRegEntry->VarMax) { + hddLog(LOGE, + "%s: Reg Parameter %s > allowed Maximum " + "[%d > %d]. Enforcing Maximum", + __func__, pRegEntry->RegName, + svalue, (int)pRegEntry->VarMax); + svalue = (int32_t) pRegEntry->VarMax; + } + + if (svalue < (int32_t) pRegEntry->VarMin) { + hddLog(LOGE, + "%s: Reg Parameter %s < allowed Minimum " + "[%d < %d]. Enforcing Minimum", + __func__, pRegEntry->RegName, + svalue, (int)pRegEntry->VarMin); + svalue = (int32_t) pRegEntry->VarMin; + } + } + /* If this parameter needs range checking, do it here. */ + else if (pRegEntry-> + Flags & VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT) { + if (svalue > (int32_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 = + (int32_t) pRegEntry->VarDefault; + } + + if (svalue < (int32_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 + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 == CDF_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 = + util_min(strlen + ((char *)pRegEntry-> + VarDefault), + pRegEntry->VarSize - 1); + memcpy(pField, + (void *)(pRegEntry->VarDefault), + cbOutString); + ((uint8_t *) pField)[cbOutString] = + '\0'; + } else { + memcpy(pField, (void *)(value_str), + len_value_str); + ((uint8_t *) pField)[len_value_str] = + '\0'; + } + } else { + /* Failed to read the string parameter from the registry. Use the default. */ + cbOutString = + util_min(strlen((char *)pRegEntry->VarDefault), + pRegEntry->VarSize - 1); + memcpy(pField, (void *)(pRegEntry->VarDefault), + cbOutString); + ((uint8_t *) pField)[cbOutString] = '\0'; + } + } else if (WLAN_PARAM_MacAddr == pRegEntry->RegType) { + if (pRegEntry->VarSize != CDF_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 == CDF_STATUS_SUCCESS) { + len_value_str = strlen(value_str); + if (len_value_str != (CDF_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; i < CDF_MAC_ADDR_SIZE; i++) { + ((char *)pField)[i] = + (char)(parse_hex_digit(candidate[i * 2]) * + 16 + + parse_hex_digit(candidate[i * 2 + 1])); + } + } else { + hddLog(LOGE, + "%s: Unknown param type for name[%s] in registry table", + __func__, pRegEntry->RegName); + } + + /* did we successfully parse a cfg item for this parameter? */ + if ((match_status == CDF_STATUS_SUCCESS) && + (idx < MAX_CFG_INI_ITEMS)) { + set_bit(idx, (void *)&pHddCtx->config->bExplicitCfg); + } + } + + return ret_status; +} + +/** + * hdd_execute_config_command() - executes an arbitrary configuration command + * @reg_table: the pointer to configuration table + * @tableSize: the size of the configuration table + * @ini_struct: pointer to the hdd config knob + * @pHddCtx: the pointer to hdd context + * @command: the command to run + * + * Return: CDF_STATUS_SUCCESS if the command is found and able to execute, + * otherwise the appropriate CDF_STATUS will be returned + */ +static CDF_STATUS hdd_execute_config_command(REG_TABLE_ENTRY *reg_table, + unsigned long tableSize, + uint8_t *ini_struct, + hdd_context_t *pHddCtx, + char *command) +{ + REG_TABLE_ENTRY *pRegEntry; + char *clone; + char *pCmd; + void *pField; + char *name; + char *value_str; + uint32_t value; + int32_t svalue; + size_t len_value_str; + unsigned int idx; + unsigned int i; + CDF_STATUS vstatus; + int rv; + + /* assume failure until proven otherwise */ + vstatus = CDF_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 = CDF_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 < (int32_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 > (int32_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 != (CDF_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, (CDF_MAC_ADDR_SIZE * 2)); + goto done; + } + /* parse the string and store it in the byte array */ + for (i = 0; i < CDF_MAC_ADDR_SIZE; i++) { + ((char *)pField)[i] = (char) + ((parse_hex_digit(value_str[(i * 2)]) * 16) + + parse_hex_digit(value_str[(i * 2) + 1])); + } + break; + + default: + goto done; + } + + /* if we get here, we had a successful modification */ + vstatus = CDF_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->config->bExplicitCfg); + } +done: + kfree(clone); + return vstatus; +} + +/** + * hdd_set_power_save_offload_config() - set power save offload configuration + * @pHddCtx: the pointer to hdd context + * + * Return: none + */ +static void hdd_set_power_save_offload_config(hdd_context_t *pHddCtx) +{ + struct hdd_config *pConfig = pHddCtx->config; + uint32_t 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 + */ + sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, + listenInterval); + } + +} + +/** + * hdd_cfg_print() - print the hdd configuration + * @iniTable: pointer to hdd context + * + * Return: None + */ +void hdd_cfg_print(hdd_context_t *pHddCtx) +{ + int i; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "*********Config values in HDD Adapter*******"); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [RTSThreshold] Value = %u", + pHddCtx->config->RTSThreshold); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [OperatingChannel] Value = [%u]", + pHddCtx->config->OperatingChannel); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [PowerUsageControl] Value = [%s]", + pHddCtx->config->PowerUsageControl); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fIsImpsEnabled] Value = [%u]", + pHddCtx->config->fIsImpsEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nVccRssiTrigger] Value = [%u]", + pHddCtx->config->nVccRssiTrigger); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssBssid] Value =[" MAC_ADDRESS_STR "]", + MAC_ADDR_ARRAY(pHddCtx->config->IbssBssid.bytes)); + + for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [Intf%dMacAddress] Value =[" MAC_ADDRESS_STR "]", + i, MAC_ADDR_ARRAY(pHddCtx->config->intfMacAddr[i].bytes)); + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApEnableUapsd] value = [%u]", + pHddCtx->config->apUapsdEnabled); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableApProt] value = [%u]", + pHddCtx->config->apProtEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gAPAutoShutOff] Value = [%u]", + pHddCtx->config->nAPAutoShutOff); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gWlanMccToSccSwitchMode] Value = [%u]", + pHddCtx->config->WlanMccToSccSwitchMode); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gWlanAutoShutdown] Value = [%u]", + pHddCtx->config->WlanAutoShutdown); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableListenMode] Value = [%u]", + pHddCtx->config->nEnableListenMode); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApProtection] value = [%u]", + pHddCtx->config->apProtection); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableApOBSSProt] value = [%u]", + pHddCtx->config->apOBSSProtEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS, + pHddCtx->config->force_sap_acs); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS_START_CH, + pHddCtx->config->force_sap_acs_st_ch); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_FORCE_SAP_ACS_END_CH, + pHddCtx->config->force_sap_acs_end_ch); +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [sap_channel_avoidance] value = [%u]", + pHddCtx->config->sap_channel_avoidance); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] value = [%u]", CFG_SAP_P2P_11AC_OVERRIDE_NAME, + pHddCtx->config->sap_p2p_11ac_override); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [ChannelBondingMode] Value = [%u]", + pHddCtx->config->nChannelBondingMode24GHz); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [ChannelBondingMode] Value = [%u]", + pHddCtx->config->nChannelBondingMode5GHz); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [dot11Mode] Value = [%u]", + pHddCtx->config->dot11Mode); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [WmmMode] Value = [%u] ", pHddCtx->config->WmmMode); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [UapsdMask] Value = [0x%x] ", + pHddCtx->config->UapsdMask); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [PktClassificationBasis] Value = [%u] ", + pHddCtx->config->PktClassificationBasis); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [ImplicitQosIsEnabled] Value = [%u]", + (int)pHddCtx->config->bImplicitQosEnabled); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdVoSrvIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdVoSrvIntv); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdVoSuspIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdVoSuspIntv); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdViSrvIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdViSrvIntv); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdViSuspIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdViSuspIntv); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdBeSrvIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdBeSrvIntv); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdBeSuspIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdBeSuspIntv); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdBkSrvIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdBkSrvIntv); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraUapsdBkSuspIntv] Value = [%u] ", + pHddCtx->config->InfraUapsdBkSuspIntv); +#ifdef FEATURE_WLAN_ESE + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraInactivityInterval] Value = [%u] ", + pHddCtx->config->InfraInactivityInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [EseEnabled] Value = [%u] ", + pHddCtx->config->isEseIniFeatureEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [FastTransitionEnabled] Value = [%u] ", + pHddCtx->config->isFastTransitionEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gTxPowerCap] Value = [%u] dBm ", + pHddCtx->config->nTxPowerCap); +#endif +#ifdef FEATURE_WLAN_LFR + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [FastRoamEnabled] Value = [%u] ", + pHddCtx->config->isFastRoamIniFeatureEnabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [MAWCEnabled] Value = [%u] ", + pHddCtx->config->MAWCEnabled); +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [RoamRssiDiff] Value = [%u] ", + pHddCtx->config->RoamRssiDiff); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [isWESModeEnabled] Value = [%u] ", + pHddCtx->config->isWESModeEnabled); +#endif +#ifdef FEATURE_WLAN_OKC + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [OkcEnabled] Value = [%u] ", + pHddCtx->config->isOkcIniFeatureEnabled); +#endif +#ifdef FEATURE_WLAN_SCAN_PNO + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [configPNOScanSupport] Value = [%u] ", + pHddCtx->config->configPNOScanSupport); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [configPNOScanTimerRepeatValue] Value = [%u] ", + pHddCtx->config->configPNOScanTimerRepeatValue); +#endif +#ifdef FEATURE_WLAN_TDLS + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fEnableTDLSSupport] Value = [%u] ", + pHddCtx->config->fEnableTDLSSupport); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fEnableTDLSImplicitTrigger] Value = [%u] ", + pHddCtx->config->fEnableTDLSImplicitTrigger); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fTDLSExternalControl] Value = [%u] ", + pHddCtx->config->fTDLSExternalControl); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fTDLSUapsdMask] Value = [%u] ", + pHddCtx->config->fTDLSUapsdMask); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fEnableTDLSBufferSta] Value = [%u] ", + pHddCtx->config->fEnableTDLSBufferSta); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fEnableTDLSWmmMode] Value = [%u] ", + pHddCtx->config->fEnableTDLSWmmMode); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [enable_tdls_scan] Value = [%u]", + pHddCtx->config->enable_tdls_scan); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraDirAcVo] Value = [%u] ", + pHddCtx->config->InfraDirAcVo); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraNomMsduSizeAcVo] Value = [0x%x] ", + pHddCtx->config->InfraNomMsduSizeAcVo); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMeanDataRateAcVo] Value = [0x%x] ", + pHddCtx->config->InfraMeanDataRateAcVo); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMinPhyRateAcVo] Value = [0x%x] ", + pHddCtx->config->InfraMinPhyRateAcVo); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraSbaAcVo] Value = [0x%x] ", + pHddCtx->config->InfraSbaAcVo); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraDirAcVi] Value = [%u] ", + pHddCtx->config->InfraDirAcVi); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraNomMsduSizeAcVi] Value = [0x%x] ", + pHddCtx->config->InfraNomMsduSizeAcVi); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMeanDataRateAcVi] Value = [0x%x] ", + pHddCtx->config->InfraMeanDataRateAcVi); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMinPhyRateAcVi] Value = [0x%x] ", + pHddCtx->config->InfraMinPhyRateAcVi); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraSbaAcVi] Value = [0x%x] ", + pHddCtx->config->InfraSbaAcVi); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraDirAcBe] Value = [%u] ", + pHddCtx->config->InfraDirAcBe); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraNomMsduSizeAcBe] Value = [0x%x] ", + pHddCtx->config->InfraNomMsduSizeAcBe); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMeanDataRateAcBe] Value = [0x%x] ", + pHddCtx->config->InfraMeanDataRateAcBe); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMinPhyRateAcBe] Value = [0x%x] ", + pHddCtx->config->InfraMinPhyRateAcBe); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraSbaAcBe] Value = [0x%x] ", + pHddCtx->config->InfraSbaAcBe); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraDirAcBk] Value = [%u] ", + pHddCtx->config->InfraDirAcBk); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraNomMsduSizeAcBk] Value = [0x%x] ", + pHddCtx->config->InfraNomMsduSizeAcBk); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMeanDataRateAcBk] Value = [0x%x] ", + pHddCtx->config->InfraMeanDataRateAcBk); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraMinPhyRateAcBk] Value = [0x%x] ", + pHddCtx->config->InfraMinPhyRateAcBk); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [InfraSbaAcBk] Value = [0x%x] ", + pHddCtx->config->InfraSbaAcBk); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [DelayedTriggerFrmInt] Value = [%u] ", + pHddCtx->config->DelayedTriggerFrmInt); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [mcastBcastFilterSetting] Value = [%u] ", + pHddCtx->config->mcastBcastFilterSetting); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fhostArpOffload] Value = [%u] ", + pHddCtx->config->fhostArpOffload); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [ssdp] Value = [%u] ", pHddCtx->config->ssdp); +#ifdef FEATURE_WLAN_RA_FILTERING + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [RArateLimitInterval] Value = [%u] ", + pHddCtx->config->RArateLimitInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [IsRArateLimitEnabled] Value = [%u] ", + pHddCtx->config->IsRArateLimitEnabled); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fFTResourceReqSupported] Value = [%u] ", + pHddCtx->config->fFTResourceReqSupported); +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nNeighborLookupRssiThreshold] Value = [%u] ", + pHddCtx->config->nNeighborLookupRssiThreshold); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [delay_before_vdev_stop] Value = [%u] ", + pHddCtx->config->delay_before_vdev_stop); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nOpportunisticThresholdDiff] Value = [%u] ", + pHddCtx->config->nOpportunisticThresholdDiff); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamRescanRssiDiff] Value = [%u] ", + pHddCtx->config->nRoamRescanRssiDiff); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nNeighborScanMinChanTime] Value = [%u] ", + pHddCtx->config->nNeighborScanMinChanTime); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nNeighborScanMaxChanTime] Value = [%u] ", + pHddCtx->config->nNeighborScanMaxChanTime); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nMaxNeighborRetries] Value = [%u] ", + pHddCtx->config->nMaxNeighborReqTries); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nNeighborScanPeriod] Value = [%u] ", + pHddCtx->config->nNeighborScanPeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nNeighborScanResultsRefreshPeriod] Value = [%u] ", + pHddCtx->config->nNeighborResultsRefreshPeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nEmptyScanRefreshPeriod] Value = [%u] ", + pHddCtx->config->nEmptyScanRefreshPeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamBmissFirstBcnt] Value = [%u] ", + pHddCtx->config->nRoamBmissFirstBcnt); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamBmissFinalBcnt] Value = [%u] ", + pHddCtx->config->nRoamBmissFinalBcnt); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nRoamBeaconRssiWeight] Value = [%u] ", + pHddCtx->config->nRoamBeaconRssiWeight); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [allowDFSChannelRoam] Value = [%u] ", + pHddCtx->config->allowDFSChannelRoam); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_max_count] Value = [%u] ", + pHddCtx->config->nhi_rssi_scan_max_count); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_rssi_delta] Value = [%u] ", + pHddCtx->config->nhi_rssi_scan_rssi_delta); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_delay] Value = [%u] ", + pHddCtx->config->nhi_rssi_scan_delay); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nhi_rssi_scan_rssi_ub] Value = [%u] ", + pHddCtx->config->nhi_rssi_scan_rssi_ub); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [burstSizeDefinition] Value = [0x%x] ", + pHddCtx->config->burstSizeDefinition); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [tsInfoAckPolicy] Value = [0x%x] ", + pHddCtx->config->tsInfoAckPolicy); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [rfSettlingTimeUs] Value = [%u] ", + pHddCtx->config->rfSettlingTimeUs); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [bSingleTidRc] Value = [%u] ", + pHddCtx->config->bSingleTidRc); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gDynamicPSPollvalue] Value = [%u] ", + pHddCtx->config->dynamicPsPollValue); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gAddTSWhenACMIsOff] Value = [%u] ", + pHddCtx->config->AddTSWhenACMIsOff); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gValidateScanList] Value = [%u] ", + pHddCtx->config->fValidateScanList); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gStaKeepAlivePeriod] Value = [%u] ", + pHddCtx->config->infraStaKeepAlivePeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApDataAvailPollInterVal] Value = [%u] ", + pHddCtx->config->apDataAvailPollPeriodInMs); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [BandCapability] Value = [%u] ", + pHddCtx->config->nBandCapability); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fEnableBeaconEarlyTermination] Value = [%u] ", + pHddCtx->config->fEnableBeaconEarlyTermination); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [teleBcnWakeupEnable] Value = [%u] ", + pHddCtx->config->teleBcnWakeupEn); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [transListenInterval] Value = [%u] ", + pHddCtx->config->nTeleBcnTransListenInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [transLiNumIdleBeacons] Value = [%u] ", + pHddCtx->config->nTeleBcnTransLiNumIdleBeacons); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [maxListenInterval] Value = [%u] ", + pHddCtx->config->nTeleBcnMaxListenInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [maxLiNumIdleBeacons] Value = [%u] ", + pHddCtx->config->nTeleBcnMaxLiNumIdleBeacons); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [bcnEarlyTermWakeInterval] Value = [%u] ", + pHddCtx->config->bcnEarlyTermWakeInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApDataAvailPollInterVal] Value = [%u] ", + pHddCtx->config->apDataAvailPollPeriodInMs); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableBypass11d] Value = [%u] ", + pHddCtx->config->enableBypass11d); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableDFSChnlScan] Value = [%u] ", + pHddCtx->config->enableDFSChnlScan); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableDFSPnoChnlScan] Value = [%u] ", + pHddCtx->config->enable_dfs_pno_chnl_scan); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gReportMaxLinkSpeed] Value = [%u] ", + pHddCtx->config->reportMaxLinkSpeed); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [thermalMitigationEnable] Value = [%u] ", + pHddCtx->config->thermalMitigationEnable); +#ifdef WLAN_FEATURE_11AC + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gVhtChannelWidth] value = [%u]", + pHddCtx->config->vhtChannelWidth); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [enableFirstScan2GOnly] Value = [%u] ", + pHddCtx->config->enableFirstScan2GOnly); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [skipDfsChnlInP2pSearch] Value = [%u] ", + pHddCtx->config->skipDfsChnlInP2pSearch); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [ignoreDynamicDtimInP2pMode] Value = [%u] ", + pHddCtx->config->ignoreDynamicDtimInP2pMode); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [enableRxSTBC] Value = [%u] ", + pHddCtx->config->enableRxSTBC); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableLpwrImgTransition] Value = [%u] ", + pHddCtx->config->enableLpwrImgTransition); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSSR] Value = [%u] ", + pHddCtx->config->enableSSR); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableVhtFor24GHzBand] Value = [%u] ", + pHddCtx->config->enableVhtFor24GHzBand); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gFlexConnectPowerFactor] Value = [%u] ", + pHddCtx->config->flexConnectPowerFactor); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableIbssHeartBeatOffload] Value = [%u] ", + pHddCtx->config->enableIbssHeartBeatOffload); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gAntennaDiversity] Value = [%u] ", + pHddCtx->config->antennaDiversity); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gGoLinkMonitorPeriod] Value = [%u]", + pHddCtx->config->goLinkMonitorPeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApLinkMonitorPeriod] Value = [%u]", + pHddCtx->config->apLinkMonitorPeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gGoKeepAlivePeriod] Value = [%u]", + pHddCtx->config->goKeepAlivePeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gApKeepAlivePeriod]Value = [%u]", + pHddCtx->config->apKeepAlivePeriod); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gAmsduSupportInAMPDU] Value = [%u] ", + pHddCtx->config->isAmsduSupportInAMPDU); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [nSelect5GHzMargin] Value = [%u] ", + pHddCtx->config->nSelect5GHzMargin); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gCoalesingInIBSS] Value = [%u] ", + pHddCtx->config->isCoalesingInIBSSAllowed); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssATIMWinSize] Value = [%u] ", + pHddCtx->config->ibssATIMWinSize); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssIsPowerSaveAllowed] Value = [%u] ", + pHddCtx->config->isIbssPowerSaveAllowed); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssIsPowerCollapseAllowed] Value = [%u] ", + pHddCtx->config->isIbssPowerCollapseAllowed); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssAwakeOnTxRx] Value = [%u] ", + pHddCtx->config->isIbssAwakeOnTxRx); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssInactivityTime] Value = [%u] ", + pHddCtx->config->ibssInactivityCount); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssTxSpEndInactivityTime] Value = [%u] ", + pHddCtx->config->ibssTxSpEndInactivityTime); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssPsWarmupTime] Value = [%u] ", + pHddCtx->config->ibssPsWarmupTime); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIbssPs1RxChainInAtim] Value = [%u] ", + pHddCtx->config->ibssPs1RxChainInAtimEnable); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fDfsPhyerrFilterOffload] Value = [%u] ", + pHddCtx->config->fDfsPhyerrFilterOffload); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIgnorePeerErpInfo] Value = [%u] ", + pHddCtx->config->ignore_peer_erp_info); +#ifdef IPA_OFFLOAD + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIPAConfig] Value = [0x%x] ", + pHddCtx->config->IpaConfig); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIPADescSize] Value = [%u] ", + pHddCtx->config->IpaDescSize); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [IpaHighBandwidthMbpsg] Value = [%u] ", + pHddCtx->config->IpaHighBandwidthMbps); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [IpaMediumBandwidthMbps] Value = [%u] ", + pHddCtx->config->IpaMediumBandwidthMbps); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [IpaLowBandwidthMbps] Value = [%u] ", + pHddCtx->config->IpaLowBandwidthMbps); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableOverLapCh] Value = [%u] ", + pHddCtx->config->gEnableOverLapCh); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gMaxOffloadPeers] Value = [%u] ", + pHddCtx->config->apMaxOffloadPeers); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gMaxOffloadReorderBuffs] value = [%u] ", + pHddCtx->config->apMaxOffloadReorderBuffs); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gAllowDFSChannelRoam] Value = [%u] ", + pHddCtx->config->allowDFSChannelRoam); + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gMaxConcurrentActiveSessions] Value = [%u] ", + pHddCtx->config->gMaxConcurrentActiveSessions); + +#ifdef MSM_PLATFORM + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthHighThreshold] Value = [%u] ", + pHddCtx->config->busBandwidthHighThreshold); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthMediumThreshold] Value = [%u] ", + pHddCtx->config->busBandwidthMediumThreshold); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gBusBandwidthLowThreshold] Value = [%u] ", + pHddCtx->config->busBandwidthLowThreshold); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gbusBandwidthComputeInterval] Value = [%u] ", + pHddCtx->config->busBandwidthComputeInterval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gTcpDelAckThresholdHigh] Value = [%u] ", + pHddCtx->config->tcpDelackThresholdHigh); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gTcpDelAckThresholdLow] Value = [%u] ", + pHddCtx->config->tcpDelackThresholdLow); +#endif + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gIgnoreCAC] Value = [%u] ", + pHddCtx->config->ignoreCAC); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gSapPreferredChanLocation] Value = [%u] ", + pHddCtx->config->gSapPreferredChanLocation); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gDisableDfsJapanW53] Value = [%u] ", + pHddCtx->config->gDisableDfsJapanW53); +#ifdef FEATURE_GREEN_AP + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableGreenAp] Value = [%u] ", + pHddCtx->config->enableGreenAP); +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [isRoamOffloadEnabled] Value = [%u]", + pHddCtx->config->isRoamOffloadEnabled); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSifsBurst] Value = [%u]", + pHddCtx->config->enableSifsBurst); + +#ifdef WLAN_FEATURE_LPSS + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableLpassSupport] Value = [%u] ", + pHddCtx->config->enablelpasssupport); +#endif + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSelfRecovery] Value = [%u]", + pHddCtx->config->enableSelfRecovery); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSapSuspend] Value = [%u]", + pHddCtx->config->enableSapSuspend); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWgotoSuspend] Value = [%u]", + pHddCtx->config->extWowGotoSuspend); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWowApp1WakeupPinNumber] Value = [%u]", + pHddCtx->config->extWowApp1WakeupPinNumber); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWowApp2WakeupPinNumber] Value = [%u]", + pHddCtx->config->extWowApp2WakeupPinNumber); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAInitPingInterval] Value = [%u]", + pHddCtx->config->extWowApp2KAInitPingInterval); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAMinPingInterval] Value = [%u]", + pHddCtx->config->extWowApp2KAMinPingInterval); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAMaxPingInterval] Value = [%u]", + pHddCtx->config->extWowApp2KAMaxPingInterval); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2KAIncPingInterval] Value = [%u]", + pHddCtx->config->extWowApp2KAIncPingInterval); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpSrcPort] Value = [%u]", + pHddCtx->config->extWowApp2TcpSrcPort); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpDstPort] Value = [%u]", + pHddCtx->config->extWowApp2TcpDstPort); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpTxTimeout] Value = [%u]", + pHddCtx->config->extWowApp2TcpTxTimeout); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gExtWoWApp2TcpRxTimeout] Value = [%u]", + pHddCtx->config->extWowApp2TcpRxTimeout); +#endif + +#ifdef DHCP_SERVER_OFFLOAD + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerOffloadEnable] Value = [%u]", + pHddCtx->config->enableDHCPServerOffload); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPMaxNumClients] Value = [%u]", + pHddCtx->config->dhcpMaxNumClients); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerIP] Value = [%s]", + pHddCtx->config->dhcpServerIP); +#endif + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableDumpCollect] Value = [%u]", + pHddCtx->config->is_ramdump_enabled); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gP2PListenDeferInterval] Value = [%u]", + pHddCtx->config->p2p_listen_defer_interval); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [is_ps_enabled] value = [%d]", + pHddCtx->config->is_ps_enabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [policy_manager_enabled] value = [%d]", + pHddCtx->config->policy_manager_enabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [tso_enable] value = [%d]", + pHddCtx->config->tso_enable); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [LROEnable] value = [%d]", + pHddCtx->config->lro_enable); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [active_mode_offload] value = [%d]", + pHddCtx->config->active_mode_offload); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [gfine_time_meas_cap] value = [%u]", + pHddCtx->config->fine_time_meas_cap); +#ifdef WLAN_FEATURE_FASTPATH + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [fastpath_enable] Value = [%u]", + pHddCtx->config->fastpath_enable); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [max_scan_count] value = [%d]", + pHddCtx->config->max_scan_count); +#ifdef FEATURE_NAPI_DEBUG + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [%s] value = [%d]", + CFG_ENABLE_RX_THREAD, pHddCtx->config->enableRxThread); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [%s] value = [%d]", + CFG_NAPI_NAME, pHddCtx->config->napi_enable); +#endif + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] Value = [%u]", + CFG_CE_CLASSIFY_ENABLE_NAME, + pHddCtx->config->ce_classify_enabled); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Name = [%s] value = [%u]", + CFG_DUAL_MAC_FEATURE_DISABLE, + pHddCtx->config->dual_mac_feature_disable); +} + + +/** + * hdd_update_mac_config() - update MAC address from cfg file + * @pHddCtx: the pointer to hdd context + * + * It overwrites the MAC address if config file exist. + * + * Return: CDF_STATUS_SUCCESS if the MAC address is found from cfg file + * and overwritten, otherwise CDF_STATUS_E_INVAL + */ +CDF_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[CDF_MAX_CONCURRENCY_PERSONA]; + tSirMacAddr customMacAddr; + + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + memset(macTable, 0, sizeof(macTable)); + status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + + if (status) { + hddLog(CDF_TRACE_LEVEL_WARN, "%s: request_firmware failed %d", + __func__, status); + cdf_status = CDF_STATUS_E_FAILURE; + return cdf_status; + } + if (!fw || !fw->data || !fw->size) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: invalid firmware", __func__); + cdf_status = CDF_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 = strnchr(buffer, strlen(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 >= CDF_MAX_CONCURRENCY_PERSONA) + break; + } + } + } + buffer = line; + } + if (i <= CDF_MAX_CONCURRENCY_PERSONA) { + hddLog(CDF_TRACE_LEVEL_INFO, "%s: %d Mac addresses provided", + __func__, i); + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: invalid number of Mac address provided, nMac = %d", + __func__, i); + cdf_status = CDF_STATUS_E_INVAL; + goto config_exit; + } + + update_mac_from_string(pHddCtx, &macTable[0], i); + + cdf_mem_copy(&customMacAddr, + &pHddCtx->config->intfMacAddr[0].bytes[0], + sizeof(tSirMacAddr)); + sme_set_custom_mac_addr(customMacAddr); + +config_exit: + release_firmware(fw); + return cdf_status; +} + +/** + * hdd_parse_config_ini() - parse the ini configuration file + * @pHddCtx: the pointer to hdd context + * + * This function reads the qcom_cfg.ini file and + * parses each 'Name=Value' pair in the ini file + * + * Return: CDF_STATUS_SUCCESS if the qcom_cfg.ini is correctly read, + * otherwise CDF_STATUS_E_INVAL + */ +CDF_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]; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + memset(cfgIniTable, 0, sizeof(cfgIniTable)); + + status = request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); + + if (status) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: request_firmware failed %d", + __func__, status); + cdf_status = CDF_STATUS_E_FAILURE; + goto config_exit; + } + if (!fw || !fw->data || !fw->size) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: %s download failed", + __func__, WLAN_INI_FILE); + cdf_status = CDF_STATUS_E_FAILURE; + goto config_exit; + } + + hddLog(LOG1, "%s: qcom_cfg.ini Size %zu", __func__, fw->size); + + buffer = (char *)cdf_mem_malloc(fw->size); + + if (NULL == buffer) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("cdf_mem_malloc failure")); + release_firmware(fw); + return CDF_STATUS_E_NOMEM; + } + pTemp = buffer; + + cdf_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 (!i_isspace(*buffer) + && *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 */ + cdf_status = hdd_apply_cfg_ini(pHddCtx, cfgIniTable, i); +#ifdef FEATURE_NAPI + if (CDF_STATUS_SUCCESS == cdf_status) + hdd_napi_event(NAPI_EVT_INI_FILE, + (void *)pHddCtx->config->napi_enable); +#endif /* FEATURE_NAPI */ + +config_exit: + release_firmware(fw); + cdf_mem_free(pTemp); + return cdf_status; +} + +/** + * hdd_cfg_xlate_to_csr_phy_mode() - convert PHY mode + * @dot11Mode: the mode to convert + * + * Convert the configuration PHY mode to CSR PHY mode + * + * Return: the CSR phy mode value + */ +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; + } + +} + +/** + * hdd_set_idle_ps_config() - set idle power save configuration + * @pHddCtx: the pointer to hdd context + * @val: the value to configure + * + * Return: CDF_STATUS_SUCCESS if command set correctly, + * otherwise the CDF_STATUS return from SME layer + */ +CDF_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, uint32_t val) +{ + struct hdd_config *pConfig = pHddCtx->config; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + hddLog(LOG1, "hdd_set_idle_ps_config: Enter Val %d", val); + + if (pConfig->fIsImpsEnabled) { + status = sme_set_idle_powersave_config(pHddCtx->pcds_context, + pHddCtx->hHal, val); + if (CDF_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) +{ + struct hdd_config *config = hdd_ctx->config; + 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_string_to_u8_array() - scan the string and convert to u8 array + * @str: the pointer to the string + * @intArray: the pointer of buffer to store the u8 value + * @len: size of the buffer + * + * Return: CDF_STATUS_SUCCESS if the conversion is done, + * otherwise CDF_STATUS_E_INVAL + */ +CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, + uint8_t intArrayMaxLen) +{ + char *s = str; + + if (str == NULL || intArray == NULL || len == NULL) { + return CDF_STATUS_E_INVAL; + } + *len = 0; + + while ((s != NULL) && (*len < intArrayMaxLen)) { + int val; + /* Increment length only if sscanf succesfully extracted one element. + * Any other return value means error. Ignore it. + */ + if (sscanf(s, "%d", &val) == 1) { + intArray[*len] = (uint8_t) val; + *len += 1; + } + s = strpbrk(s, ","); + if (s) + s++; + } + + return CDF_STATUS_SUCCESS; + +} + +/** + * hdd_update_config_dat() - scan the string and convery to u8 array + * @str: the pointer to the string + * @intArray: the pointer of buffer to store the u8 value + * @len: size of the buffer + * + * Return: CDF_STATUS_SUCCESS if the configuration could be updated corectly, + * otherwise CDF_STATUS_E_INVAL + */ +bool hdd_update_config_dat(hdd_context_t *pHddCtx) +{ + bool fStatus = true; + uint32_t val; + uint16_t val16; + + struct hdd_config *pConfig = pHddCtx->config; + tSirMacHTCapabilityInfo *phtCapInfo; + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_SHORT_GI_20MHZ, + pConfig->ShortGI20MhzEnable) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_20MHZ to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_FIXED_RATE, pConfig->TxRate) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_FIXED_RATE to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_MAX_RX_AMPDU_FACTOR, + pConfig->MaxRxAmpduFactor) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_SHORT_PREAMBLE, + pConfig->fIsShortPreamble) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_SHORT_PREAMBLE to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + pConfig->nPassiveMinChnTime) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME" + " to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pConfig->nPassiveMaxChnTime) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME" + " to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_BEACON_INTERVAL, + pConfig->nBeaconInterval) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_BEACON_INTERVAL to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_MAX_PS_POLL, + pConfig->nMaxPsPoll) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_MAX_PS_POLL to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_CURRENT_RX_ANTENNA, + pConfig->nRxAnt) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_CURRENT_RX_ANTENNA to CFG"); + } + + if (sme_cfg_set_int (pHddCtx->hHal, WNI_CFG_LOW_GAIN_OVERRIDE, + pConfig->fIsLowGainOverride) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_LOW_GAIN_OVERRIDE to HAL"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RSSI_FILTER_PERIOD, + pConfig->nRssiFilterPeriod) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RSSI_FILTER_PERIOD to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, + pConfig->fIgnoreDtim) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_IGNORE_DTIM to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_PS_ENABLE_HEART_BEAT, + pConfig->fEnableFwHeartBeatMonitoring) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PS_HEART_BEAT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_PS_ENABLE_BCN_FILTER, + pConfig->fEnableFwBeaconFiltering) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PS_BCN_FILTER to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR, + pConfig->fEnableFwRssiMonitoring) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PS_RSSI_MONITOR to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + pConfig->nDataInactivityTimeout) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_ENABLE_LTE_COEX, + pConfig->enableLTECoex) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_LTE_COEX to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE, + pConfig->nEnableListenMode) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_AP_KEEP_ALIVE_TIMEOUT, + pConfig->apKeepAlivePeriod) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_AP_KEEP_ALIVE_TIMEOUT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_GO_KEEP_ALIVE_TIMEOUT, + pConfig->goKeepAlivePeriod) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_GO_KEEP_ALIVE_TIMEOUT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_AP_LINK_MONITOR_TIMEOUT, + pConfig->apLinkMonitorPeriod) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_AP_LINK_MONITOR_TIMEOUT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_GO_LINK_MONITOR_TIMEOUT, + pConfig->goLinkMonitorPeriod) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_GO_LINK_MONITOR_TIMEOUT to CFG"); + } + +#if defined WLAN_FEATURE_VOWIFI + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RRM_ENABLED, pConfig->fRrmEnable) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RRM_ENABLE to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RRM_OPERATING_CHAN_MAX, + pConfig->nInChanMeasMaxDuration) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RRM_OPERATING_CHAN_MAX to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, + pConfig->nOutChanMeasMaxDuration) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RRM_OUT_CHAN_MAX to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_MCAST_BCAST_FILTER_SETTING, + pConfig->mcastBcastFilterSetting) == CDF_STATUS_E_FAILURE) + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_MCAST_BCAST_FILTER_SETTING to CFG"); +#endif + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_SINGLE_TID_RC, + pConfig->bSingleTidRc) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_SINGLE_TID_RC to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_TELE_BCN_WAKEUP_EN, + pConfig->teleBcnWakeupEn) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TELE_BCN_WAKEUP_EN to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI, + pConfig->nTeleBcnTransListenInterval) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TELE_BCN_TRANS_LI to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI, + pConfig->nTeleBcnMaxListenInterval) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TELE_BCN_MAX_LI to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS, + pConfig->nTeleBcnTransLiNumIdleBeacons) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS, + pConfig->nTeleBcnMaxLiNumIdleBeacons) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RF_SETTLING_TIME_CLK, + pConfig->rfSettlingTimeUs) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RF_SETTLING_TIME_CLK to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, + pConfig->infraStaKeepAlivePeriod) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD to CFG"); + } + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_DYNAMIC_PS_POLL_VALUE, + pConfig->dynamicPsPollValue) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DYNAMIC_PS_POLL_VALUE to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT, + pConfig->nNullDataApRespTimeout) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_PS_NULLDATA_DELAY_TIMEOUT to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, + pConfig->apDataAvailPollPeriodInMs) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD to CFG"); + } + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, + pConfig->FragmentationThreshold) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_FRAGMENTATION_THRESHOLD to CFG"); + } + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_RTS_THRESHOLD, + pConfig->RTSThreshold) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_RTS_THRESHOLD to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_11D_ENABLED, + pConfig->Is11dSupportEnabled) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_11D_ENABLED to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_DFS_MASTER_ENABLED, + pConfig->enableDFSMasterCap) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Failure: Could not set value for WNI_CFG_DFS_MASTER_ENABLED"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + pConfig->enableTxBFin20MHz) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not set value for WNI_CFG_VHT_ENABLE_TXBF_20MHZ"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_HEART_BEAT_THRESHOLD, + pConfig->HeartbeatThresh24) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_HEART_BEAT_THRESHOLD to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, + pConfig->apDataAvailPollPeriodInMs) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_ENABLE_CLOSE_LOOP, + pConfig->enableCloseLoop) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_CLOSE_LOOP to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TX_PWR_CTRL_ENABLE, + pConfig->enableAutomaticTxPowerControl) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TX_PWR_CTRL_ENABLE to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_SHORT_GI_40MHZ, + pConfig->ShortGI40MhzEnable) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_SHORT_GI_40MHZ to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_ENABLE_MC_ADDR_LIST, + pConfig->fEnableMCAddrList) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_MC_ADDR_LIST to CFG"); + } + /* 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)) { + uint32_t temp = 0; + + sme_cfg_get_int(pHddCtx->hHal, + WNI_CFG_VHT_BASIC_MCS_SET, &temp); + temp = (temp & 0xFFFC) | pConfig->vhtRxMCS; + if (pConfig->enable2x2) + temp = (temp & 0xFFF3) | (pConfig->vhtRxMCS2x2 << 2); + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_BASIC_MCS_SET, temp) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_BASIC_MCS_SET to CFG"); + } + + sme_cfg_get_int(pHddCtx->hHal, WNI_CFG_VHT_RX_MCS_MAP, + &temp); + temp = (temp & 0xFFFC) | pConfig->vhtRxMCS; + if (pConfig->enable2x2) + temp = (temp & 0xFFF3) | (pConfig->vhtRxMCS2x2 << 2); + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_RX_MCS_MAP, temp) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_RX_MCS_MAP to CFG"); + } + sme_cfg_get_int(pHddCtx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp); + temp = (temp & 0xFFFC) | pConfig->vhtTxMCS; + if (pConfig->enable2x2) + temp = (temp & 0xFFF3) | (pConfig->vhtTxMCS2x2 << 2); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "vhtRxMCS2x2 - %x temp - %u enable2x2 %d", + pConfig->vhtRxMCS2x2, temp, + pConfig->enable2x2); + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_TX_MCS_MAP, + temp) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_TX_MCS_MAP to CFG"); + } + /* Currently shortGI40Mhz is used for shortGI80Mhz */ + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ, + pConfig->ShortGI40MhzEnable) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass WNI_VHT_SHORT_GI_80MHZ to CFG"); + } + /* Hardware is capable of doing + * 128K AMPDU in 11AC mode */ + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + pConfig->fVhtAmpduLenExponent) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_AMPDU_LEN_EXPONENT to CFG"); + } + /* Change MU Bformee only when TxBF is enabled */ + if (pConfig->enableTxBF) { + sme_cfg_get_int(pHddCtx->hHal, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, &temp); + + if (temp != pConfig->enableMuBformee) { + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + pConfig->enableMuBformee + ) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_MU_BEAMFORMEE_CAP to CFG"); + } + } + } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH, + pConfig->vhtMpduLen) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_MAX_MPDU_LENGTH to CFG"); + } + + if (pConfig->enable2x2 && pConfig->enable_su_tx_bformer) { + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, + pConfig->enable_su_tx_bformer) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hdd_err("set SU_BEAMFORMER_CAP to CFG failed"); + } + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS, + NUM_OF_SOUNDING_DIMENSIONS) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hdd_err("failed to set NUM_OF_SOUNDING_DIM"); + } + } + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_HT_RX_STBC, + pConfig->enableRxSTBC) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_RX_STBC to CFG"); + } + + sme_cfg_get_int(pHddCtx->hHal, WNI_CFG_HT_CAP_INFO, &val); + val16 = (uint16_t) val; + phtCapInfo = (tSirMacHTCapabilityInfo *) &val16; + phtCapInfo->rxSTBC = pConfig->enableRxSTBC; + phtCapInfo->advCodingCap = pConfig->enableRxLDPC; + val = val16; + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_HT_CAP_INFO, val) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_CAP_INFO to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_RXSTBC, + pConfig->enableRxSTBC) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RXSTBC to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_TXSTBC, + pConfig->enableTxSTBC) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_TXSTBC to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP, + pConfig->enableRxLDPC) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_LDPC_CODING_CAP to CFG"); + } +#ifdef WLAN_SOFTAP_VSTA_FEATURE + if (pConfig->fEnableVSTASupport) { + sme_cfg_get_int(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 (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, val) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ASSOC_STA_LIMIT to CFG"); + } +#endif + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_ENABLE_LPWR_IMG_TRANSITION, + pConfig->enableLpwrImgTransition) + == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_LPWR_IMG_TRANSITION to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + pConfig->enableMCCAdaptiveScheduler) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED to CFG"); + } + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, + pConfig->disableLDPCWithTxbfAP) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_ZERO, + pConfig->retryLimitZero) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_ZERO to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_ONE, + pConfig->retryLimitOne) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_ONE to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_DYNAMIC_THRESHOLD_TWO, + pConfig->retryLimitTwo) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_TWO to CFG"); + } + + if (sme_cfg_set_int + (pHddCtx->hHal, WNI_CFG_MAX_MEDIUM_TIME, + pConfig->cfgMaxMediumTime) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_MAX_MEDIUM_TIME to CFG"); + } +#ifdef FEATURE_WLAN_TDLS + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + pConfig->fTDLSUapsdMask) == CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK to CFG"); + } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_BUF_STA_ENABLED, + pConfig->fEnableTDLSBufferSta) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_BUF_STA_ENABLED to CFG"); + } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_PUAPSD_INACT_TIME, + pConfig->fTDLSPuapsdInactivityTimer) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_PUAPSD_INACT_TIME to CFG"); + } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_RX_FRAME_THRESHOLD, + pConfig->fTDLSRxFrameThreshold) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_RX_FRAME_THRESHOLD to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + pConfig->fEnableTDLSOffChannel) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_BUF_STA_ENABLED to CFG"); + } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_TDLS_WMM_MODE_ENABLED, + pConfig->fEnableTDLSWmmMode) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_TDLS_WMM_MODE_ENABLED to CFG"); + } +#endif + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_ENABLE_ADAPT_RX_DRAIN, + pConfig->fEnableAdaptRxDrain) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ENABLE_ADAPT_RX_DRAIN to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_FLEX_CONNECT_POWER_FACTOR, + pConfig->flexConnectPowerFactor) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, "Failure: Could not pass on " + "WNI_CFG_FLEX_CONNECT_POWER_FACTOR to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_ANTENNA_DIVESITY, + pConfig->antennaDiversity) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_ANTENNA_DIVESITY to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ, + pConfig->defaultRateIndex24Ghz) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DEFAULT_RATE_INDEX_24GHZ to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL, + pConfig->debugP2pRemainOnChannel) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL to CFG"); + } +#ifdef WLAN_FEATURE_11W + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + pConfig->pmfSaQueryMaxRetries) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_SA_QUERY_MAX_RETRIES to CFG"); + } + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + pConfig->pmfSaQueryRetryInterval) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_SA_QUERY_RETRY_INTERVAL to CFG"); + } +#endif + + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_ATIM_WIN_SIZE, + pConfig->ibssATIMWinSize) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CFG"); + } + return fStatus; +} + +/** + * hdd_set_sme_config() -initializes the sme configuration parameters + * + * @pHddCtx: the pointer to hdd context + * + * Return: CDF_STATUS_SUCCESS if configuration is correctly applied, + * otherwise the appropriate CDF_STATUS would be returned + */ +CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeConfigParams *smeConfig; + + struct hdd_config *pConfig = pHddCtx->config; + + smeConfig = cdf_mem_malloc(sizeof(*smeConfig)); + if (NULL == smeConfig) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: unable to allocate smeConfig", __func__); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(smeConfig, sizeof(*smeConfig)); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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.fSupplicantCountryCodeHasPriority = + pConfig->fSupplicantCountryCodeHasPriority; + smeConfig->csrConfig.bCatRssiOffset = pConfig->nRssiCatGap; + smeConfig->csrConfig.vccRssiThreshold = pConfig->nVccRssiTrigger; + smeConfig->csrConfig.vccUlMacLossThreshold = + pConfig->nVccUlMacLossThreshold; + smeConfig->csrConfig.nRoamingTime = pConfig->nRoamingTime; + 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; +#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.nNumStaChanCombinedConc = + pConfig->nNumStaChanCombinedConc; + smeConfig->csrConfig.nNumP2PChanCombinedConc = + pConfig->nNumP2PChanCombinedConc; + +#endif + smeConfig->csrConfig.Is11eSupportEnabled = pConfig->b80211eIsEnabled; + smeConfig->csrConfig.WMMSupportMode = pConfig->WmmMode; + +#if defined WLAN_FEATURE_VOWIFI + smeConfig->rrmConfig.rrmEnabled = pConfig->fRrmEnable; + smeConfig->rrmConfig.maxRandnInterval = pConfig->nRrmRandnIntvl; +#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.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 (CDF_SAP_MODE != hdd_get_conparam()) + smeConfig->csrConfig.Csr11dinfo.Channels.numChannels = 0; + + hdd_set_power_save_offload_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.isWESModeEnabled = pConfig->isWESModeEnabled; +#endif + 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; + } +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + 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.isAmsduSupportInAMPDU = + pConfig->isAmsduSupportInAMPDU; + smeConfig->csrConfig.nSelect5GHzMargin = pConfig->nSelect5GHzMargin; + + smeConfig->csrConfig.isCoalesingInIBSSAllowed = + pHddCtx->config->isCoalesingInIBSSAllowed; + smeConfig->csrConfig.ignore_peer_erp_info = + pConfig->ignore_peer_erp_info; + /* update SSR config */ + sme_update_enable_ssr((tHalHandle) (pHddCtx->hHal), + pHddCtx->config->enableSSR); + +#ifdef FEATURE_WLAN_SCAN_PNO + /* Update PNO offoad status */ + smeConfig->pnoOffload = pHddCtx->config->PnoOffload; +#endif + + /* Update maximum interfaces information */ + smeConfig->max_intf_count = pHddCtx->max_intf_count; + + smeConfig->fEnableDebugLog = pHddCtx->config->gEnableDebugLog; + + smeConfig->enable5gEBT = pHddCtx->config->enable5gEBT; + + smeConfig->enableSelfRecovery = pHddCtx->config->enableSelfRecovery; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + smeConfig->csrConfig.isRoamOffloadEnabled = + pHddCtx->config->isRoamOffloadEnabled; +#endif + smeConfig->csrConfig.conc_custom_rule1 = + pHddCtx->config->conc_custom_rule1; + smeConfig->csrConfig.conc_custom_rule2 = + pHddCtx->config->conc_custom_rule2; + smeConfig->csrConfig.is_sta_connection_in_5gz_enabled = + pHddCtx->config->is_sta_connection_in_5gz_enabled; + + smeConfig->f_sta_miracast_mcc_rest_time_val = + pHddCtx->config->sta_miracast_mcc_rest_time_val; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + smeConfig->sap_channel_avoidance = + pHddCtx->config->sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + smeConfig->f_prefer_non_dfs_on_radar = + pHddCtx->config->prefer_non_dfs_on_radar; + + smeConfig->is_ps_enabled = pHddCtx->config->is_ps_enabled; + hdd_set_fine_time_meas_cap(pHddCtx, smeConfig); + + cds_set_multicast_logging(pHddCtx->config->multicast_host_fw_msgs); + + smeConfig->csrConfig.sendDeauthBeforeCon = pConfig->sendDeauthBeforeCon; + + smeConfig->policy_manager_enabled = + pHddCtx->config->policy_manager_enabled; + smeConfig->csrConfig.max_scan_count = + pHddCtx->config->max_scan_count; + + /* Update 802.11p config */ + smeConfig->csrConfig.enable_dot11p = + (pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED); + + smeConfig->dual_mac_feature_disable = + pHddCtx->config->dual_mac_feature_disable; + + status = sme_update_config(pHddCtx->hHal, smeConfig); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, "sme_update_config() return failure %d", + status); + } + + cdf_mem_free(smeConfig); + return status; +} + +/** + * hdd_execute_global_config_command() - execute the global config command + * @pHddCtx: the pointer to hdd context + * @command: the command to run + * + * Return: the CDF_STATUS return from hdd_execute_config_command + */ +CDF_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), + (uint8_t *) pHddCtx->config, + pHddCtx, command); +} + +/** + * hdd_cfg_get_global_config() - get the configuration table + * @pHddCtx: pointer to hdd context + * @pBuf: buffer to store the configuration + * @buflen: size of the buffer + * + * Return: CDF_STATUS_SUCCESS if the configuration and buffer size can carry + * the content, otherwise CDF_STATUS_E_RESOURCES + */ +CDF_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), + (uint8_t *) pHddCtx->config, pHddCtx, pBuf, + buflen); +} + +/** + * hdd_is_okc_mode_enabled() - returns whether OKC mode is enabled or not + * @pHddCtx: the pointer to hdd context + * + * Return: true if OKC is enabled, otherwise false + */ +bool hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx) +{ + if (NULL == pHddCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: pHddCtx is NULL", __func__); + return -EINVAL; + } +#ifdef FEATURE_WLAN_OKC + return pHddCtx->config->isOkcIniFeatureEnabled; +#else + return false; +#endif +} + +/** + * hdd_update_nss() - Update the number of spatial streams supported. + * Ensure that nss is either 1 or 2 before calling this. + * + * @hdd_ctx: the pointer to hdd context + * @nss: the number of spatial streams to be updated + * + * This function is used to modify the number of spatial streams + * supported when not in connected state. + * + * Return: CDF_STATUS_SUCCESS if nss is correctly updated, + * otherwise CDF_STATUS_E_FAILURE would be returned + */ +CDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss) +{ + struct hdd_config *hdd_config = hdd_ctx->config; + uint32_t temp = 0; + uint32_t rx_supp_data_rate, tx_supp_data_rate; + bool 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 CDF_STATUS_E_INVAL; + } + + enable2x2 = (nss == 1) ? 0 : 1; + + if (hdd_config->enable2x2 == enable2x2) { + hddLog(LOGE, "NSS same as requested"); + return CDF_STATUS_SUCCESS; + } + + if (true == sme_is_any_session_in_connected_state(hdd_ctx->hHal)) { + hddLog(LOGE, "Connected sessions present, Do not change NSS"); + return CDF_STATUS_E_INVAL; + } + + hdd_config->enable2x2 = enable2x2; + + if (!hdd_config->enable2x2) { + /* 1x1 */ + rx_supp_data_rate = HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + tx_supp_data_rate = HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; + } else { + /* 2x2 */ + rx_supp_data_rate = HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + tx_supp_data_rate = HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2; + } + + /* Update Rx Highest Long GI data Rate */ + if (sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + rx_supp_data_rate) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CFG"); + } + + /* Update Tx Highest Long GI data Rate */ + if (sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + tx_supp_data_rate) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE to CFG"); + } + + sme_cfg_get_int(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 (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, + temp) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, "Could not pass on WNI_CFG_HT_CAP_INFO to CFG"); + } + + sme_cfg_get_int(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 (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, + temp) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_VHT_BASIC_MCS_SET to CFG"); + } + + sme_cfg_get_int(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 (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, + temp) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RX_MCS_MAP to CFG"); + } + + sme_cfg_get_int(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 (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, + temp) == CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, "Could not pass on WNI_CFG_VHT_TX_MCS_MAP to CFG"); + } + +#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff + val = SIZE_OF_SUPPORTED_MCS_SET; + sme_cfg_get_str(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 (sme_cfg_set_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, + mcs_set, + SIZE_OF_SUPPORTED_MCS_SET) == + CDF_STATUS_E_FAILURE) { + status = false; + hddLog(LOGE, "Could not pass on MCS SET to CFG"); + } +#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES + + if (CDF_STATUS_SUCCESS != sme_update_nss(hdd_ctx->hHal, nss)) + status = false; + + return (status == false) ? CDF_STATUS_E_FAILURE : CDF_STATUS_SUCCESS; +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c new file mode 100644 index 000000000000..9012628af8b6 --- /dev/null +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -0,0 +1,10706 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_cfg80211.c + * + * WLAN Host Device Driver cfg80211 APIs implementation + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_CNSS +#include +#endif +#include +#include +#include "sir_params.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_power.h" +#include "wlan_hdd_trace.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cds_utils.h" +#include "cds_sched.h" +#include "wlan_hdd_scan.h" +#include +#include "wlan_hdd_tdls.h" +#include "wlan_hdd_wmm.h" +#include "wma_types.h" +#include "wlan_hdd_misc.h" +#include "wlan_hdd_nan.h" +#include +#include "wlan_logging_sock_svc.h" + +#ifdef FEATURE_WLAN_EXTSCAN +#include "wlan_hdd_ext_scan.h" +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +#include "wlan_hdd_stats.h" +#endif +#include "cds_concurrency.h" +#include "qwlan_version.h" +#include "wlan_hdd_memdump.h" + +#include "wlan_hdd_ocb.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 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) + +/* + * Refer @tCfgProtection structure for definition of the bit map. + * below value is obtained by setting the following bit-fields. + * enable obss, fromllb, overlapOBSS and overlapFromllb protection. + */ +#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 CONNECTION_UPDATE_TIMEOUT 500 + +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), + HDD5GHZCHAN(5720, 144, 0), + 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, +}; + +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, +}; + +/* 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)) +/* 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 = (CDF_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 = CDF_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) + } +}; + +/* SAP + P2P combination */ +static const struct ieee80211_iface_limit +wlan_hdd_sap_p2p_iface_limit[] = { + { + /* 1 dedicated for p2p0 which is a STA type */ + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + /* The p2p interface in SAP+P2P can be GO/CLI. + * The p2p connection can be formed on p2p0 or p2p-p2p0-x. + */ + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) + }, + { + /* SAP+GO to support only one SAP interface */ + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) + } +}; + +/* P2P + P2P combination */ +static const struct ieee80211_iface_limit +wlan_hdd_p2p_p2p_iface_limit[] = { + { + /* 1 dedicated for p2p0 which is a STA type */ + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + /* The p2p interface in P2P+P2P can be GO/CLI. + * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x. + */ + .max = 2, + .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) + }, +}; + +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 + CDF_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 + CDF_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 concrnt 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, + }, + /* SAP + P2P */ + { + .limits = wlan_hdd_sap_p2p_iface_limit, + .num_different_channels = 2, + /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */ + .max_interfaces = 3, + .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit), + .beacon_int_infra_match = true, + }, + /* P2P + P2P */ + { + .limits = wlan_hdd_p2p_p2p_iface_limit, + .num_different_channels = 2, + /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */ + .max_interfaces = 3, + .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit), + .beacon_int_infra_match = true, + }, +}; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */ + +static struct cfg80211_ops wlan_hdd_cfg80211_ops; + + +#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 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) +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 + +#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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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->config->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->config->fTDLSExternalControl ? + WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0); + set = set | (hdd_ctx->config->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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +#ifdef QCA_HT_2040_COEX +static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work); +#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 userspace + */ +int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, + tHddAvoidFreqList *pAvoidFreqList) +{ + struct sk_buff *vendor_event; + + ENTER(); + + if (!pHddCtx) { + hddLog(LOGE, FL("HDD context is null")); + return -EINVAL; + } + + if (!pAvoidFreqList) { + hddLog(LOGE, FL("pAvoidFreqList is null")); + return -EINVAL; + } + + vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy, + NULL, + sizeof(tHddAvoidFreqList), + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX, + GFP_KERNEL); + if (!vendor_event) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + + 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 */ + +/* 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 */ + [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 */ + [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI + }, +#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_SCAN_DONE_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE + }, + [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN + }, + /* OCB events */ + [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT + }, +}; + +/** + * __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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0)) + 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) { + hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail")); + kfree_skb(temp_skbuff); + + return ret_val; + } + + return cfg80211_vendor_cmd_reply(temp_skbuff); + } + + hddLog(LOGE, FL("dfs capability: buffer alloc fail")); + 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; + + cds_ssr_protect(__func__); + ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len); + cds_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 +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 (!cds_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 (!CDS_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) + cdf_mem_free(sap_config->acs_cfg.ch_list); + + cdf_mem_copy(&sap_config->acs_cfg, + &con_sap_config->acs_cfg, + sizeof(struct sap_acs_cfg)); + sap_config->acs_cfg.ch_list = cdf_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; + } + + cdf_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 +int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter) +{ + return 0; +} +#endif + +/** + * 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 = rf_channels[RF_CHAN_1].channelNum; + sap_cfg->acs_cfg.end_ch = rf_channels[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 = rf_channels[RF_CHAN_1].channelNum; + sap_cfg->acs_cfg.end_ch = rf_channels[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 = rf_channels[RF_CHAN_36].channelNum; + sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_165].channelNum; + } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) { + sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg; + sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_1].channelNum; + sap_cfg->acs_cfg.end_ch = rf_channels[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_sap_event_cb; + + cdf_mem_copy(sap_config->self_macaddr.bytes, + adapter->macAddressCurrent.bytes, sizeof(struct cdf_mac_addr)); + 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->pcds_context, +#endif + acs_event_callback, sap_config, 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 function 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 length + * + * 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; + + /* ***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 }, + */ + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (hdd_ctx->config->force_sap_acs) { + hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled")); + return -EPERM; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + goto out; + } + sap_config = &adapter->sessionCtx.ap.sapConfig; + cdf_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(CDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + goto out; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) { + hddLog(CDF_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 = CH_WIDTH_80MHZ; + else if (ch_width == 40) + sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ; + else + sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ; + + /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and + * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and + * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the + * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored + * since it contains the frequency values of the channels in + * the channel list. + * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr + * is present + */ + 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 = cdf_mem_malloc( + sizeof(uint8_t) * + sap_config->acs_cfg.ch_list_count); + if (sap_config->acs_cfg.ch_list == NULL) + goto out; + + cdf_mem_copy(sap_config->acs_cfg.ch_list, tmp, + sap_config->acs_cfg.ch_list_count); + } + } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) { + uint32_t *freq = + nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]); + sap_config->acs_cfg.ch_list_count = nla_len( + tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) / + sizeof(uint32_t); + if (sap_config->acs_cfg.ch_list_count) { + sap_config->acs_cfg.ch_list = cdf_mem_malloc( + 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; + } + + /* convert frequency to channel */ + for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) + sap_config->acs_cfg.ch_list[i] = + ieee80211_frequency_to_channel(freq[i]); + } + } + + hdd_debug("get pcl for DO_ACS vendor command"); + + /* consult policy manager to get PCL */ + status = cds_get_pcl(hdd_ctx, CDS_SAP_MODE, + sap_config->acs_cfg.pcl_channels, + &sap_config->acs_cfg.pcl_ch_count); + if (CDF_STATUS_SUCCESS != status) + hddLog(LOGE, FL("Get PCL failed")); + + wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled); + + /* ACS override for android */ + if (hdd_ctx->config->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->config->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 function 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len); + cds_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; + 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; + } + + ret_val = hdd_vendor_put_ifindex(vendor_event, adapter->dev->ifindex); + if (ret_val) { + hddLog(LOGE, FL("NL80211_ATTR_IFINDEX put fail")); + kfree_skb(vendor_event); + return; + } + + 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 == CH_WIDTH_80MHZ) + ch_width = 80; + else if (sap_cfg->acs_cfg.ch_width == CH_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; + } + if (sap_cfg->acs_cfg.pri_ch > 14) + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, + QCA_ACS_MODE_IEEE80211A); + else + ret_val = nla_put_u8(vendor_event, + QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, + QCA_ACS_MODE_IEEE80211G); + + if (ret_val) { + hddLog(LOGE, + FL( + "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE 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 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; + uint32_t fset = 0; + int ret; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("Hdd context not valid")); + 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 + fset |= WIFI_FEATURE_SOFT_AP; + + /* HOTSPOT is a supplicant feature, enable it by default */ + fset |= WIFI_FEATURE_HOTSPOT; + +#ifdef FEATURE_WLAN_EXTSCAN + if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) { + hddLog(LOG1, FL("EXTScan is supported by firmware")); + fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO; + } +#endif + if (wlan_hdd_nan_is_supported()) { + hddLog(LOG1, FL("NAN is supported by firmware")); + fset |= WIFI_FEATURE_NAN; + } + if (sme_is_feature_supported_by_fw(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->config->configPNOScanSupport && + sme_is_feature_supported_by_fw(PNO)) { + hddLog(LOG1, FL("PNO is supported by firmware")); + fset |= WIFI_FEATURE_PNO; + } +#endif + fset |= WIFI_FEATURE_ADDITIONAL_STA; +#ifdef FEATURE_WLAN_TDLS + if ((true == pHddCtx->config->fEnableTDLSSupport) && + sme_is_feature_supported_by_fw(TDLS)) { + hddLog(LOG1, FL("TDLS is supported by firmware")); + fset |= WIFI_FEATURE_TDLS; + } + if (sme_is_feature_supported_by_fw(TDLS) && + (true == pHddCtx->config->fEnableTDLSOffChannel) && + sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) { + hddLog(LOG1, FL("TDLS off-channel is supported by firmware")); + fset |= WIFI_FEATURE_TDLS_OFFCHANNEL; + } +#endif +#ifdef WLAN_AP_STA_CONCURRENCY + 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; + } + return cfg80211_vendor_cmd_reply(skb); +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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev, + data, data_len); + cds_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]; + CDF_STATUS status; + int ret; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (false == pHddCtx->config->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 = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + 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_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("sme_set_scanning_mac_oui failed(err=%d)"), status); + goto fail; + } + return 0; +fail: + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * 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. + **/ +#define MAX_CONCURRENT_CHAN_ON_24G 2 +#define MAX_CONCURRENT_CHAN_ON_5G 2 +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; + uint32_t dbs_capability = 0; + bool one_by_one_dbs, two_by_two_dbs; + CDF_STATUS ret = CDF_STATUS_E_FAILURE; + int ret_val; + + uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0}; + hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy); + + ret_val = wlan_hdd_validate_context(hdd_ctx_ptr); + if (ret_val) + return ret_val; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (hdd_ctx_ptr->config->isRoamOffloadEnabled) { + hddLog(LOG1, FL("Key Mgmt Offload is supported")); + wlan_hdd_cfg80211_set_feature(feature_flags, + QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD); + } + + wlan_hdd_cfg80211_set_feature(feature_flags, + QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY); + if (wma_is_scan_simultaneous_capable()) + wlan_hdd_cfg80211_set_feature(feature_flags, + QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS); + 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; + + ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs); + if (CDF_STATUS_SUCCESS == ret) { + if (one_by_one_dbs) + dbs_capability = DRV_DBS_CAPABILITY_1X1; + + if (two_by_two_dbs) + dbs_capability = DRV_DBS_CAPABILITY_2X2; + + if (!one_by_one_dbs && !two_by_two_dbs) + dbs_capability = DRV_DBS_CAPABILITY_DISABLED; + } else { + hdd_err("wma_get_dbs_hw_mode failed"); + dbs_capability = DRV_DBS_CAPABILITY_DISABLED; + } + + hdd_info("dbs_capability is %d", dbs_capability); + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND, + MAX_CONCURRENT_CHAN_ON_24G)) + goto nla_put_failure; + + if (nla_put_u32(skb, + QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND, + MAX_CONCURRENT_CHAN_ON_5G)) + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + + +/** + * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters + * @wiphy: The wiphy structure + * @wdev: The wireless device + * @data: Data passed by framework + * @data_len: Parameters to be configured passed as data + * + * The roaming related parameters are configured by the framework + * using this interface. + * + * Return: Return either 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) +{ + 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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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; + cdf_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(CDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id); + hddLog(CDF_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(CDF_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 buffer length")); + } + } + roam_params.num_ssid_allowed_list = i; + hddLog(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"), + roam_params.rssi_diff); + /* Parse and fetch Alert 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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +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_check_dfs_channel_for_adapter() - check dfs channel in adapter + * @hdd_ctx: HDD context + * @device_mode: device mode + * Return: bool + */ +static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx, + device_mode_t device_mode) +{ + hdd_adapter_t *adapter; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_ap_ctx_t *ap_ctx; + hdd_station_ctx_t *sta_ctx; + CDF_STATUS cdf_status; + + cdf_status = hdd_get_front_adapter(hdd_ctx, + &adapter_node); + + while ((NULL != adapter_node) && + (CDF_STATUS_SUCCESS == cdf_status)) { + adapter = adapter_node->pAdapter; + + if ((device_mode == adapter->device_mode) && + (device_mode == WLAN_HDD_SOFTAP)) { + ap_ctx = + WLAN_HDD_GET_AP_CTX_PTR(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 (CHANNEL_STATE_DFS == + cds_get_channel_state( + ap_ctx->operatingChannel)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("SAP running on DFS channel")); + return true; + } + } + + if ((device_mode == adapter->device_mode) && + (device_mode == WLAN_HDD_INFRA_STATION)) { + sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + /* + * if STA is already connected on DFS channel, + * do not disable scan on dfs channels + */ + if (hdd_conn_is_connected(sta_ctx) && + (CHANNEL_STATE_DFS == + cds_get_channel_state( + sta_ctx->conn_info.operationChannel))) { + hddLog(LOGE, + FL("client connected on DFS channel")); + return true; + } + } + + cdf_status = hdd_get_next_adapter(hdd_ctx, + adapter_node, + &next); + adapter_node = next; + } + + return false; +} + +/** + * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration + * @wiphy: corestack handler + * @wdev: wireless device + * @data: data + * @data_len: data length + * Return: success(0) or reason code for failure + */ +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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1]; + CDF_STATUS status; + int ret_val = -EPERM; + uint32_t no_dfs_flag = 0; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return -EINVAL; + } + + 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(CDF_TRACE_LEVEL_ERROR, FL("invalid attr")); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("attr dfs flag failed")); + return -EINVAL; + } + + no_dfs_flag = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]); + + hddLog(CDF_TRACE_LEVEL_INFO, FL(" DFS flag = %d"), + no_dfs_flag); + + if (no_dfs_flag > 1) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("invalid value of dfs flag")); + return -EINVAL; + } + + if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) { + if (no_dfs_flag) { + status = wlan_hdd_check_dfs_channel_for_adapter( + hdd_ctx, WLAN_HDD_INFRA_STATION); + + if (true == status) + return -EOPNOTSUPP; + + status = wlan_hdd_check_dfs_channel_for_adapter( + hdd_ctx, WLAN_HDD_SOFTAP); + + if (true == status) + return -EOPNOTSUPP; + } + + hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag; + + hdd_abort_mac_scan_all_adapters(hdd_ctx); + + /* + * call the SME API to tunnel down the new channel list + * to the firmware + */ + status = sme_handle_dfs_chan_scan( + h_hal, hdd_ctx->config->enableDFSChnlScan); + + if (CDF_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_scan_flush_result(h_hal); + if (CDF_STATUS_SUCCESS != status) + ret_val = -EPERM; + } + + } else { + hddLog(CDF_TRACE_LEVEL_INFO, + 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) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +#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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal, + hdd_adapter_ptr->sessionId, + true); + cdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE); + cdf_mem_copy(local_pmk, data, data_len); + sme_roam_set_psk_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len); + cds_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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len); + cds_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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev, + data, data_len); + cds_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(CDF_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_t) + 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(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"), + roam_info_ptr->synchAuthStatus); + if (roam_info_ptr->synchAuthStatus == + CSR_ROAM_AUTH_STATUS_AUTHENTICATED) { + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + } else { + hddLog(CDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's")); + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, + false)) { + hddLog(CDF_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 + +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: Error code. + */ +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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = 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; + CDF_STATUS status; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret_val = wlan_hdd_validate_context(hdd_ctx); + if (ret_val) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret_val; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, + data, data_len, + wlan_hdd_wifi_config_policy)) { + hddLog(LOGE, FL("invalid attr")); + return -EINVAL; + } + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) { + modulated_dtim = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]); + + status = sme_configure_modulated_dtim(hdd_ctx->hHal, + adapter->sessionId, + modulated_dtim); + + if (CDF_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(hdd_ctx->hHal, + adapter->sessionId, + stats_avg_factor); + + if (CDF_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(hdd_ctx->hHal, + adapter->sessionId, + guard_time); + + if (CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +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 enables or disables 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) +{ + CDF_STATUS 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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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(LOGE, 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(LOGE, 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(LOGE, FL("flag=%d"), start_log.flag); + + cds_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) + cds_set_wakelock_logging(true); + else + cds_set_wakelock_logging(false); + return 0; + } + + status = sme_wifi_start_logger(hdd_ctx->hHal, start_log); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"), + status); + return -EINVAL; + } + return 0; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, + wdev, data, data_len); + cds_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) +{ + CDF_STATUS status; + 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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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")); + + status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_INDICATOR_FRAMEWORK, + WLAN_LOG_REASON_CODE_UNUSED); + if (CDF_STATUS_SUCCESS != status) { + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, + wdev, data, data_len); + cds_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; + CDF_STATUS status; + uint32_t request_id, ret, len; + uint8_t pattern_id = 0; + struct cdf_mac_addr dst_addr; + uint16_t eth_type = htons(ETH_P_IP); + + if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hddLog(LOGE, FL("Not in Connected state!")); + return -ENOTSUPP; + } + + add_req = cdf_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], + CDF_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, + CDF_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], CDF_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 - + ETH_HLEN)) { + hddLog(LOGE, FL("Invalid IP packet len: %d"), + add_req->ucPtrnSize); + goto fail; + } + + len = 0; + cdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, CDF_MAC_ADDR_SIZE); + len += CDF_MAC_ADDR_SIZE; + cdf_mem_copy(&add_req->ucPattern[len], add_req->macAddress, + CDF_MAC_ADDR_SIZE); + len += CDF_MAC_ADDR_SIZE; + cdf_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 | + * ------------------------------------------------------------ + */ + cdf_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_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status); + goto fail; + } + + EXIT(); + cdf_mem_free(add_req); + return 0; + +fail: + cdf_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; + CDF_STATUS 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 = cdf_mem_malloc(sizeof(*del_req)); + if (!del_req) { + hddLog(LOGE, FL("memory allocation failed")); + return -ENOMEM; + } + + cdf_mem_copy(del_req->macAddress, adapter->macAddressCurrent.bytes, + CDF_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_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status); + goto fail; + } + + EXIT(); + cdf_mem_free(del_req); + return 0; + +fail: + cdf_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 = CDF_MAC_ADDR_SIZE }, + [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY, + .len = CDF_MAC_ADDR_SIZE }, + [PARAM_PERIOD] = { .type = NLA_U32 }, + }; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (!sme_is_feature_supported_by_fw(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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy, + wdev, data, data_len); + cds_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; + CDF_STATUS 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_conn_is_connected(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 (!CDF_IS_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len); + cds_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. + * + * Return: none + */ +void hdd_rssi_threshold_breached(void *hddctx, + struct rssi_breach_event *data) +{ + hdd_context_t *hdd_ctx = hddctx; + struct sk_buff *skb; + + 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, + GFP_KERNEL); + + 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, GFP_KERNEL); + return; + +fail: + kfree_skb(skb); + return; +} + +/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * This function return the preferred frequency list generated by the policy + * manager. + * + * Return: success or failure code + */ +static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int i, ret = 0; + CDF_STATUS status; + uint8_t pcl[MAX_NUM_CHAN]; + uint32_t pcl_len = 0; + uint32_t freq_list[MAX_NUM_CHAN]; + enum cds_con_mode intf_mode; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1]; + struct sk_buff *reply_skb; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX, + data, data_len, NULL)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) { + hdd_err("attr interface type failed"); + return -EINVAL; + } + + intf_mode = nla_get_u32(tb + [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]); + + if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) { + hdd_err("Invalid interface type"); + return -EINVAL; + } + + hdd_debug("Userspace requested pref freq list"); + + status = cds_get_pcl(hdd_ctx, intf_mode, pcl, &pcl_len); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("Get pcl failed"); + return -EINVAL; + } + + /* convert channel number to frequency */ + for (i = 0; i < pcl_len; i++) { + if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz)) + freq_list[i] = + ieee80211_channel_to_frequency(pcl[i], + IEEE80211_BAND_2GHZ); + else + freq_list[i] = + ieee80211_channel_to_frequency(pcl[i], + IEEE80211_BAND_5GHZ); + } + + /* send the freq_list back to supplicant */ + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(u32) * + pcl_len + + NLMSG_HDRLEN); + + if (!reply_skb) { + hdd_err("Allocate reply_skb failed"); + return -EINVAL; + } + + if (nla_put_u32(reply_skb, + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE, + intf_mode) || + nla_put(reply_skb, + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST, + sizeof(uint32_t) * pcl_len, + freq_list)) { + hdd_err("nla put fail"); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); +} + +/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * This function return the preferred frequency list generated by the policy + * manager. + * + * Return: success or failure code + */ +static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel + * @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_set_probable_oper_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int ret = 0; + enum cds_con_mode intf_mode; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1]; + uint32_t channel_hint; + p_cds_contextType p_cds_context; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hdd_err("Invalid CDS context"); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX, + data, data_len, NULL)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) { + hdd_err("attr interface type failed"); + return -EINVAL; + } + + intf_mode = nla_get_u32(tb + [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]); + + if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) { + hdd_err("Invalid interface type"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) { + hdd_err("attr probable freq failed"); + return -EINVAL; + } + + channel_hint = cds_freq_to_chan(nla_get_u32(tb + [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ])); + + /* check pcl table */ + if (!cds_allow_concurrency(hdd_ctx, intf_mode, + channel_hint, HW_MODE_20_MHZ)) { + hdd_err("Set channel hint failed due to concurrency check"); + return -EINVAL; + } + + if (hdd_ctx->config->policy_manager_enabled) { + ret = cdf_event_reset( + &p_cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(ret)) + hdd_err("clearing event failed"); + + ret = cds_current_connections_update(hdd_ctx, + channel_hint); + if (CDF_STATUS_E_FAILURE == ret) { + /* return in the failure case */ + hdd_err("ERROR: connections update failed!!"); + return -EINVAL; + } + + if (CDF_STATUS_SUCCESS == ret) { + /* + * Success is the only case for which we expect hw mode + * change to take place, hence we need to wait. + * For any other return value it should be a pass + * through + */ + ret = cdf_wait_single_event( + &p_cds_context->connection_update_done_evt, + CONNECTION_UPDATE_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + hdd_err("ERROR: cdf wait for event failed!!"); + return -EINVAL; + } + + } + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel + * @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_set_probable_oper_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = is_driver_dfs_capable + }, + +#ifdef WLAN_FEATURE_NAN + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_nan_request + }, +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_stats_ext_request + }, +#endif +#ifdef FEATURE_WLAN_EXTSCAN + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_start + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_stop + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_extscan_get_valid_channels + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_get_capabilities + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_get_cached_results + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE, + .flags = + WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_set_significant_change + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE, + .flags = + WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_significant_change + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_epno_list + }, +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_clear + }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_set + }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_ll_stats_get + }, +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +#ifdef FEATURE_WLAN_TDLS + { + .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_GET_CONCURRENCY_MATRIX, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = cds_cfg80211_get_concurrency_matrix + }, + { + .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_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 +#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 + }, + { + .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 + }, + { + .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 + }, + { + .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 + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_preferred_freq_list + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_probable_oper_channel + }, +#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 +#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_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_TRIGGER_SCAN, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_vendor_scan + }, + + /* 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 + }, +}; + +/* + * 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(CDF_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; + CHANNEL_STATE channelEnabledState; + + ENTER(); + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + + if (NULL == wiphy->bands[i]) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: wiphy->bands[i] is NULL, i = %d", __func__, + i); + continue; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + channelEnabledState = + cds_get_channel_state(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) + && CHANNEL_STATE_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 (CHANNEL_STATE_DISABLE == channelEnabledState || + CHANNEL_STATE_INVALID == channelEnabledState) { + band->channels[j].flags |= + IEEE80211_CHAN_DISABLED; + } else if (CHANNEL_STATE_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, struct hdd_config *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)) + 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)) + 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)) + 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)) + 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 (cds_get_conparam() != CDF_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 = hdd_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)) + 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 capabilitied based + * on ini values*/ + if (!pCfg->ShortGI20MhzEnable) { + wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &= + ~IEEE80211_HT_CAP_SGI_20; + } + + if (!pCfg->ShortGI40MhzEnable) { + wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } + + if (!pCfg->nChannelBondingMode5GHz) { + wlan_hdd_band_5_ghz.ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + + wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz; + if (true == hdd_is_5g_supported(pHddCtx)) { + wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz; + } + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + + if (NULL == wiphy->bands[i]) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: wiphy->bands[i] is NULL, i = %d", __func__, + 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; + + if (cds_get_conparam() != CDF_FTM_MODE) { + 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)) + 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 + + EXIT(); + return 0; +} + +/* + * In this function, wiphy structure is updated after CDF + * 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, struct hdd_config *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(CDF_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); + struct hdd_config *pCfg = pHddCtx->config; + + /* 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 */ + uint16_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_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_INITIAL_REQ, + GAS_INITIAL_REQ_SIZE); + + /* GAS Initial Response */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_INITIAL_RSP, + GAS_INITIAL_RSP_SIZE); + + /* GAS Comeback Request */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_COMEBACK_REQ, + GAS_COMEBACK_REQ_SIZE); + + /* GAS Comeback Response */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_COMEBACK_RSP, + GAS_COMEBACK_RSP_SIZE); + + /* P2P Public Action */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) P2P_PUBLIC_ACTION_FRAME, + P2P_PUBLIC_ACTION_FRAME_SIZE); + + /* P2P Action */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) P2P_ACTION_FRAME, + P2P_ACTION_FRAME_SIZE); + + /* WNM BSS Transition Request frame */ + sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) WNM_BSS_ACTION_FRAME, + WNM_BSS_ACTION_FRAME_SIZE); + + /* WNM-Notification */ + sme_register_mgmt_frame(hHal, pAdapter->sessionId, type, + (uint8_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 */ + uint16_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_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_INITIAL_REQ, + GAS_INITIAL_REQ_SIZE); + + /* GAS Initial Response */ + sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_INITIAL_RSP, + GAS_INITIAL_RSP_SIZE); + + /* GAS Comeback Request */ + sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_COMEBACK_REQ, + GAS_COMEBACK_REQ_SIZE); + + /* GAS Comeback Response */ + sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) GAS_COMEBACK_RSP, + GAS_COMEBACK_RSP_SIZE); + + /* P2P Public Action */ + sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) P2P_PUBLIC_ACTION_FRAME, + P2P_PUBLIC_ACTION_FRAME_SIZE); + + /* P2P Action */ + sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type, + (uint8_t *) P2P_ACTION_FRAME, + P2P_ACTION_FRAME_SIZE); + + /* WNM-Notification */ + sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type, + (uint8_t *) WNM_NOTIFICATION_FRAME, + WNM_NOTIFICATION_FRAME_SIZE); +} + +#ifdef FEATURE_WLAN_WAPI +void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index, + const uint8_t *mac_addr, const uint8_t *key, + int key_Len) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamSetKey setKey; + bool isConnected = true; + int status = 0; + uint32_t roamId = 0xFF; + uint8_t *pKeyPtr = NULL; + int n = 0; + + hddLog(LOG1, "Device_mode %s(%d)", + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + cdf_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 Directionn both TX and RX */ + setKey.paeRole = 0; /* the PAE role */ + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { + cdf_set_macaddr_broadcast(&setKey.peerMac); + } else { + cdf_mem_copy(setKey.peerMac.bytes, mac_addr, CDF_MAC_ADDR_SIZE); + } + setKey.keyLength = key_Len; + pKeyPtr = setKey.Key; + memcpy(pKeyPtr, key, key_Len); + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x", + __func__, key_Len); + for (n = 0; n < key_Len; n++) + hddLog(CDF_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_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId); + } + if (status != 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "[%4d] sme_roam_set_key returned ERROR status= %d", + __LINE__, status); + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } +} +#endif /* FEATURE_WLAN_WAPI */ + +uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length, + uint8_t eid) +{ + int left = length; + uint8_t *ptr = (uint8_t *)ies_ptr; + uint8_t elem_id, elem_len; + + while (left >= 2) { + elem_id = ptr[0]; + elem_len = ptr[1]; + left -= 2; + if (elem_len > left) { + hddLog(CDF_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; +} + +/* + * FUNCTION: wlan_hdd_validate_operation_channel + * called by wlan_hdd_cfg80211_start_bss() and + * wlan_hdd_set_channel() + * This function validates whether given channel is part of valid + * channel list. + */ +CDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter, + int channel) +{ + + uint32_t num_ch = 0; + u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + u32 indx = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint8_t fValidChannel = false, count = 0; + struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config; + + 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 == rf_channels[count].channelNum) { + fValidChannel = true; + break; + } + } + if (fValidChannel != true) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return CDF_STATUS_E_FAILURE; + } + } else { + if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST, + valid_ch, &num_ch)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: failed to get valid channel list", + __func__); + return CDF_STATUS_E_FAILURE; + } + for (indx = 0; indx < num_ch; indx++) { + if (channel == valid_ch[indx]) { + break; + } + } + + if (indx >= num_ch) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d]", __func__, channel); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; + +} + +#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; + uint8_t numEntries = 0; + uint8_t srv_ip[IPADDR_NUM_ENTRIES]; + uint8_t num; + uint32_t temp; + pDhcpSrvInfo = cdf_mem_malloc(sizeof(*pDhcpSrvInfo)); + if (NULL == pDhcpSrvInfo) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: could not allocate tDhcpSrvOffloadInfo!", __func__); + return; + } + cdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo)); + pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId; + pDhcpSrvInfo->dhcpSrvOffloadEnabled = true; + pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients; + hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP, + srv_ip, &numEntries, IPADDR_NUM_ENTRIES); + if (numEntries != IPADDR_NUM_ENTRIES) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: incorrect IP address (%s) assigned for DHCP server!", + __func__, pHddCtx->config->dhcpServerIP); + goto end; + } + if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: invalid IP address (%s)! It could NOT be multicast IP address!", + __func__, pHddCtx->config->dhcpServerIP); + goto end; + } + if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: invalid IP address (%s)! The last field must be less than 100!", + __func__, pHddCtx->config->dhcpServerIP); + goto end; + } + for (num = 0; num < numEntries; num++) { + temp = srv_ip[num]; + pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num)); + } + if (CDF_STATUS_SUCCESS != + sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: sme_setDHCPSrvOffload fail!", __func__); + goto end; + } + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + "%s: enable DHCP Server offload successfully!", __func__); +end: + cdf_mem_free(pDhcpSrvInfo); + return; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +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; + CDF_STATUS cdf_ret_status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return ret; + } + + 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; + + cdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal, + pAdapter->sessionId, + pAdapter->sessionCtx. + ap. + apDisableIntraBssFwd); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + 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); + struct hdd_config *pConfig = pHddCtx->config; + 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; + CDF_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, 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 (!(cds_get_concurrency_mode() & (CDF_SAP_MASK | CDF_P2P_GO_MASK))) + hdd_set_conparam(0); + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +/* FUNCTION: wlan_hdd_change_country_code_cd + * to wait for contry 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; + struct hdd_config *pConfig = NULL; + eMib_dot11DesiredBssType connectedBssType; + unsigned long rc; + CDF_STATUS vstatus; + int status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + 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; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_CHANGE_IFACE, + pAdapter->sessionId, type)); + + hddLog(CDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"), + pAdapter->device_mode, type); + + if (!cds_allow_concurrency(pHddCtx, + wlan_hdd_convert_nl_iftype_to_hdd_type(type), + 0, HW_MODE_20_MHZ)) { + hddLog(CDF_TRACE_LEVEL_DEBUG, + FL("This concurrency combination is not allowed")); + return -EINVAL; + } + + pConfig = pHddCtx->config; + wdev = ndev->ieee80211_ptr; + + /* Reset the current device mode bit mask */ + cds_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 != CDF_STATUS_SUCCESS) + return -EINVAL; + + hdd_register_tx_flow_control(pAdapter, + hdd_tx_resume_timer_expired_handler, + hdd_tx_resume_cb); + + goto done; + + case NL80211_IFTYPE_ADHOC: + wlan_hdd_tdls_exit(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(CDF_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, + true); + hdd_deinit_adapter(pHddCtx, + pP2pAdapter, true); + hdd_close_adapter(pHddCtx, + pP2pAdapter, + true); + } + } + hdd_stop_adapter(pHddCtx, pAdapter, 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; + + /* + * Fw will take care incase of concurrency + */ + + 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, + CDF_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); + + vstatus = hdd_init_ap_mode(pAdapter); + if (vstatus != CDF_STATUS_SUCCESS) { + hddLog(LOGP, + FL + ("Error initializing the ap mode")); + return -EINVAL; + } + hdd_set_conparam(1); + + hdd_register_tx_flow_control(pAdapter, + hdd_softap_tx_resume_timer_expired_handler, + hdd_softap_tx_resume_cb); + + /* Interface type changed update in wiphy structure */ + if (wdev) { + wdev->iftype = 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 != CDF_STATUS_SUCCESS) + return status; + + if ((NL80211_IFTYPE_P2P_CLIENT == type) || + (NL80211_IFTYPE_STATION == type)) { + + hdd_register_tx_flow_control(pAdapter, + hdd_tx_resume_timer_expired_handler, + hdd_tx_resume_cb); + } + 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; + + hdd_register_tx_flow_control(pAdapter, + hdd_softap_tx_resume_timer_expired_handler, + hdd_softap_tx_resume_cb); + 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_conn_get_connected_bss_type + (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 (CDF_STATUS_SUCCESS == + sme_roam_disconnect(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 */ + cds_set_concurrency_mode(pHddCtx, pAdapter->device_mode); + +#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; + + cds_ssr_protect(__func__); + ret = + __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_TDLS +static bool wlan_hdd_is_duplicate_channel(uint8_t *arr, + int index, uint8_t match) +{ + int i; + for (i = 0; i < index; i++) { + if (arr[i] == match) + return true; + } + return false; +} +#endif + +/** + * __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)) +static int __wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *mac, + struct station_parameters *params) +#else +static int __wlan_hdd_change_station(struct wiphy *wiphy, + struct net_device *dev, + uint8_t *mac, + struct station_parameters *params) +#endif +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + struct cdf_mac_addr STAMacAddress; +#ifdef FEATURE_WLAN_TDLS + tCsrStaParams StaParams = { 0 }; + uint8_t isBufSta = 0; + uint8_t isOffChannelSupported = 0; +#endif + int ret; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return ret; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + cdf_mem_copy(STAMacAddress.bytes, mac, CDF_MAC_ADDR_SIZE); + + 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, + ol_txrx_peer_state_auth); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_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. + */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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]; + + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: Unique Channel List", __func__); + for (i = 0; i < num_unique_channels; i++) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: StaParams.supported_channels[%d]: %d,", + __func__, i, + StaParams. + supported_channels[i]); + } + if (MAX_CHANNEL < num_unique_channels) + num_unique_channels = MAX_CHANNEL; + StaParams.supported_channels_len = + num_unique_channels; + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: After removing duplcates StaParams.supported_channels_len: %d", + __func__, + StaParams.supported_channels_len); + } + cdf_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) + cdf_mem_copy(StaParams.extn_capability, + params->ext_capab, + sizeof(StaParams.extn_capability)); + + if (NULL != params->ht_capa) { + StaParams.htcap_present = 1; + cdf_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 propogating till Add Sta + * to the firmware has to be modified , if the supplicant (ieee80211) is + * modified to send more rates. + */ + + /* To avoid Data Currption , 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; + cdf_mem_copy(StaParams.supported_rates, + params->supported_rates, + StaParams.supported_rates_len); + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "Supported Rates with Length %d", + StaParams.supported_rates_len); + for (i = 0; i < StaParams.supported_rates_len; + i++) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "[%d]: %0x", i, + StaParams.supported_rates[i]); + } + + if (NULL != params->vht_capa) { + StaParams.vhtcap_present = 1; + cdf_mem_copy(&StaParams.VHTCap, + params->vht_capa, + sizeof(tSirVHTCap)); + } + + if (0 != params->ext_capab_len) { + /*Define A Macro : TODO Sunil */ + if ((1 << 4) & StaParams.extn_capability[3]) { + isBufSta = 1; + } + /* TDLS Channel Switching Support */ + if ((1 << 6) & StaParams.extn_capability[3]) { + isOffChannelSupported = 1; + } + } + + status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac, + &StaParams, + isBufSta, + isOffChannelSupported); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_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 (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_change_station(wiphy, dev, mac, params); + cds_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; + int status; + uint32_t roamId = 0xFF; +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context; +#endif + hdd_hostapd_state_t *pHostapdState; + CDF_STATUS cdf_ret_status; + hdd_context_t *pHddCtx; + hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + 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(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", + __func__, key_index); + + return -EINVAL; + } + + if (CSR_MAX_KEY_LEN < params->key_len) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", + __func__, params->key_len); + + return -EINVAL; + } + + hddLog(CDF_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 */ + cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; + setKey.keyLength = params->key_len; + cdf_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; + + cdf_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) */ + cdf_mem_copy(pKey, params->key, 16); + + /*Copy the rx mic first */ + cdf_mem_copy(&pKey[16], ¶ms->key[24], 8); + + /*Copy the tx mic */ + cdf_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: + { + cdf_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(CDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u", + __func__, params->cipher); + return -EOPNOTSUPP; + } + + hddLog(CDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d", + __func__, setKey.encType); + + if (!pairwise) { + /* set group key */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s- %d: setting Broadcast key", __func__, __LINE__); + setKey.keyDirection = eSIR_RX_ONLY; + cdf_set_macaddr_broadcast(&setKey.peerMac); + } else { + /* set pairwise key */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s- %d: setting pairwise key", __func__, __LINE__); + setKey.keyDirection = eSIR_TX_RX; + cdf_mem_copy(setKey.peerMac.bytes, mac_addr, CDF_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(CDF_TRACE_LEVEL_INFO_MED, + "%s: IBSS key installed already", __func__); + return 0; + } + + setKey.keyDirection = eSIR_TX_RX; + /*Set the group key */ + status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId); + + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: sme_roam_set_key failed, returned %d", + __func__, status); + return -EINVAL; + } + /*Save the keys here and call sme_roam_set_key for setting + the PTK after peer joins the IBSS network */ + cdf_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_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR + (pAdapter), &setKey); +#else + status = wlansap_set_key_sta(p_cds_context, &setKey); +#endif + if (status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "[%4d] wlansap_set_key_sta returned ERROR status= %d", + __LINE__, status); + } + } + + /* Save the key in ap ctx for use on START_BASS and restart */ + if (pairwise || + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType || + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType) + cdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey, + sizeof(tCsrRoamSetKey)); + else + cdf_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s- %d: Perform Set key Complete", + __func__, __LINE__); + hdd_perform_roam_set_key_complete(pAdapter); + } + } + + pWextState->roamProfile.Keys.KeyLength[key_index] = + (u8) params->key_len; + + pWextState->roamProfile.Keys.defaultIndex = key_index; + + cdf_mem_copy(&pWextState->roamProfile.Keys. + KeyMaterial[key_index][0], params->key, + params->key_len); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + hddLog(LOG2, + FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"), + MAC_ADDR_ARRAY(setKey.peerMac.bytes), + 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 */ + cdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey); + if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } else if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_FAILED) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); + return -EINVAL; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + /* issue set key request to SME */ + status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, &roamId); + + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: sme_roam_set_key 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 intialized 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; + cdf_set_macaddr_broadcast(&setKey.peerMac); + + hddLog(LOG2, + FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"), + MAC_ADDR_ARRAY(setKey.peerMac.bytes), + setKey.keyDirection); + + status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, + &roamId); + + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: sme_roam_set_key failed for group key (IBSS), returned %d", + __func__, status); + pHddStaCtx->roam_info.roamingState = + HDD_ROAM_STATE_NONE; + return -EINVAL; + } + } + } + + 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; + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise, + mac_addr, params); + cds_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 (CDF_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(CDF_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(cdf_trace(CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise, + mac_addr, cookie, callback); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station + * @wiphy: wiphy interface context + * @ndev: pointer to net device + * @key_index: Key index used in 802.11 frames + * @unicast: true if it is unicast key + * @multicast: true if it is multicast key + * + * This function is required for cfg80211_ops API. + * It is used to delete the key information + * Underlying hardware implementation does not have API to delete the + * encryption key. It is automatically deleted when the peer is + * removed. Hence this function currently does nothing. + * Future implementation may interprete delete key operation to + * replacing the key with a random junk value, effectively making it + * useless. + * + * Return: status code, always 0. + */ + +static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, const u8 *mac_addr) +{ + EXIT(); + return 0; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index, + pairwise, mac_addr); + cds_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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + 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; + uint32_t roamId = 0xFF; + tCsrKeys *Keys = &pWextState->roamProfile.Keys; + + hddLog(LOG2, FL("Default tx key index %d"), key_index); + + Keys->defaultIndex = (u8) key_index; + cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + setKey.keyId = key_index; + setKey.keyLength = Keys->KeyLength[key_index]; + + cdf_mem_copy(&setKey.Key[0], + &Keys->KeyMaterial[key_index][0], + Keys->KeyLength[key_index]); + + setKey.keyDirection = eSIR_TX_RX; + + cdf_copy_macaddr(&setKey.peerMac, + &pHddStaCtx->conn_info.bssId); + + 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 canse the key length is 5 but the + * encryption type is 104 hence checking the key langht(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_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey, + &roamId); + + if (0 != status) { + hddLog(LOGE, + FL("sme_roam_set_key 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; + } + } + + 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; + cds_ssr_protect(__func__); + ret = + __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast, + multicast); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211 + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * + * Return: struct cfg80211_bss pointer + */ +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, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + 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; +} + +/** + * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211 + * @pAdapter: Pointer to adapter + * @bss_desc: Pointer to bss descriptor + * + * This function is used to inform the BSS details to nl80211 interface. + * + * Return: struct cfg80211_bss pointer + */ +static 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 + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return NULL; + } + + 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 timestamp 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 = + cdf_mc_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_set_band_helper function) as part of the scan abort, message will be + * queued to PE and we proceed with flushing and changinh 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 correponding 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 correponding 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 continuosly 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; + } + + /* Supplicant takes the signal strength in terms of mBm(100*dBm) */ + rssi = (CDF_MIN((bss_desc->rssi + bss_desc->sinr), 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); + return bss_status; +} + +/** + * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211 + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * + * This function is used to update the BSS data base of CFG8011 + * + * Return: struct cfg80211_bss pointer + */ +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_roam_get_connect_profile(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 returned NULL")); + + sme_roam_free_connect_profile(hHal, &roamProfile); + } else { + hddLog(LOGE, FL("roamProfile.pBssDesc is NULL")); + } + EXIT(); + return bss; +} +/** + * wlan_hdd_cfg80211_update_bss() - update bss + * @wiphy: Pointer to wiphy + * @pAdapter: Pointer to adapter + * @scan_time: scan request timestamp + * + * Return: zero if success, non-zero otherwise + */ +int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, + hdd_adapter_t *pAdapter, + uint32_t scan_time) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tCsrScanResultInfo *pScanResult; + CDF_STATUS status = 0; + tScanResultHandle pResult; + struct cfg80211_bss *bss_status = NULL; + hdd_context_t *pHddCtx; + int ret; + + ENTER(); + + MTRACE(cdf_trace(CDF_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; + } + + /* start getting scan results and populate cgf80211 BSS database */ + status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult); + + /* no scan results */ + if (NULL == pResult) { + hddLog(LOGE, FL("No scan result Status %d"), status); + return status; + } + + pScanResult = sme_scan_result_get_first(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 thebss 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. + * - Update BSS only if beacon timestamp is later than + * scan request timestamp. + */ + if ((scan_time == 0) || + (scan_time < + pScanResult->BssDescriptor.nReceivedTime)) { + bss_status = + wlan_hdd_cfg80211_inform_bss_frame(pAdapter, + &pScanResult->BssDescriptor); + + if (NULL == bss_status) { + hdd_info("NULL returned by cfg80211_inform_bss_frame"); + } else { + cfg80211_put_bss( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + wiphy, +#endif + bss_status); + } + } else { + hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped", + MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId)); + } + pScanResult = sme_scan_result_get_next(hHal, pResult); + } + + sme_scan_result_purge(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_scan_flush_result(hHal); + + EXIT(); + return 0; +} + +#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +/** + * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * @index: Index + * @preauth: Preauth flag + * + * This function is used to notify the supplicant of a new PMKSA candidate. + * + * Return: 0 for success, non-zero for failure + */ +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 (true == hdd_is_okc_mode_enabled(pHddCtx)) { + hddLog(LOG1, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes)); + cfg80211_pmksa_candidate_notify(dev, index, + pRoamInfo->bssid.bytes, + preauth, GFP_KERNEL); + } +#endif /* FEATURE_WLAN_OKC */ + return 0; +} +#endif /* FEATURE_WLAN_LFR */ + +#ifdef FEATURE_WLAN_LFR_METRICS +/** + * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * + * 802.11r/LFR metrics reporting function to report preauth initiation + * + * Return: CDF status + */ +#define MAX_LFR_METRICS_EVENT_LENGTH 100 +CDF_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, FL("pAdapter is NULL!")); + return CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * @preauth_status: Preauth status + * + * 802.11r/LFR metrics reporting function to report handover initiation + * + * Return: CDF status + */ +CDF_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, FL("pAdapter is NULL!")); + return CDF_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) + strlcat(metrics_notification, " true", + sizeof(metrics_notification)); + else + strlcat(metrics_notification, " false", + sizeof(metrics_notification)); + + wrqu.data.pointer = metrics_notification; + wrqu.data.length = strlen(metrics_notification); + + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, + metrics_notification); + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over + * @pAdapter: Pointer to adapter + * @pRoamInfo: Pointer to roam info + * + * 802.11r/LFR metrics reporting function to report handover initiation + * + * Return: CDF status + */ +CDF_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, FL("pAdapter is NULL!")); + return CDF_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 CDF_STATUS_SUCCESS; +} +#endif + +/** + * hdd_select_cbmode() - select channel bonding mode + * @pAdapter: Pointer to adapter + * @operatingChannel: Operating channel + * + * Return: none + */ +void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel) +{ + uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode; + eHddDot11Mode hddDot11Mode = iniDot11Mode; + chan_params_t ch_params; + ch_params.ch_width = + (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth; + + hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode); + switch (iniDot11Mode) { + case eHDD_DOT11_MODE_AUTO: + case eHDD_DOT11_MODE_11ac: + case eHDD_DOT11_MODE_11ac_ONLY: +#ifdef WLAN_FEATURE_11AC + if (sme_is_feature_supported_by_fw(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_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal), + hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode), + operationChannel, 0, + &ch_params); +} + + +/* + * FUNCTION: wlan_hdd_cfg80211_connect_start + * wlan_hdd_cfg80211_connect_start() - start connection + * @pAdapter: Pointer to adapter + * @ssid: Pointer ot ssid + * @ssid_len: Length of ssid + * @bssid: Pointer to bssid + * @operatingChannel: Operating channel + * + * This function is used to start the association process + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, + const u8 *ssid, size_t ssid_len, + const u8 *bssid_hint, const u8 *bssid, + u8 operatingChannel) +{ + int status = 0; + hdd_wext_state_t *pWextState; + hdd_context_t *pHddCtx; + uint32_t roamId; + tCsrRoamProfile *pRoamProfile; + eCsrAuthType RSNAuthType; + tSmeConfigParams *sme_config; + + ENTER(); + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + status = wlan_hdd_validate_context(pHddCtx); + if (status) { + hddLog(LOGE, + FL("HDD context is not valid!")); + return status; + } + + if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) { + hddLog(LOGE, FL("wrong SSID len")); + 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))->config->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))->config->UapsdMask; + } + + pRoamProfile->SSIDs.numOfSSIDs = 1; + pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len; + cdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId, + sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); + cdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId), + ssid, ssid_len); + + if (bssid) { + pRoamProfile->BSSIDs.numOfBSSIDs = 1; + cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), + bssid, CDF_MAC_ADDR_SIZE); + /* Save BSSID in seperate 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 + */ + cdf_mem_copy((void *)(pWextState->req_bssId.bytes), + bssid, CDF_MAC_ADDR_SIZE); + } else if (bssid_hint) { + pRoamProfile->BSSIDs.numOfBSSIDs = 1; + cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), + bssid_hint, CDF_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 + */ + cdf_mem_copy((void *)(pWextState->req_bssId.bytes), + bssid_hint, CDF_MAC_ADDR_SIZE); + hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(bssid_hint)); + } else { + cdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid), + CDF_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_set_genie_to_csr(pAdapter, &RSNAuthType); + /*set auth */ + hdd_set_csr_auth_type(pAdapter, RSNAuthType); + } +#ifdef FEATURE_WLAN_WAPI + if (pAdapter->wapi_info.nWapiMode) { + hddLog(LOG1, + FL("Setting WAPI AUTH Type and Encryption Mode values")); + switch (pAdapter->wapi_info.wapiAuthMode) { + case WAPI_AUTH_MODE_PSK: + { + hddLog(LOG1, + FL("WAPI AUTH TYPE: PSK: %d"), + pAdapter->wapi_info.wapiAuthMode); + pRoamProfile->AuthType.authType[0] = + eCSR_AUTH_TYPE_WAPI_WAI_PSK; + break; + } + case WAPI_AUTH_MODE_CERT: + { + hddLog(LOG1, + FL("WAPI AUTH TYPE: CERT: %d"), + 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, + FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI")); + 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_set_ibss_power_save_params(pAdapter); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("Set IBSS Power Save Params Failed")); + return -EINVAL; + } + hdd_select_cbmode(pAdapter, operatingChannel); + } + + if (pHddCtx->config->policy_manager_enabled && + (true == cds_is_connection_in_progress(pHddCtx))) { + hdd_err("Connection refused: conn in progress"); + return -EINVAL; + } + + /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect() + * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state + * If direct path, conn_state will be accordingly changed to NotConnected or Associated + * by either hdd_association_completion_handler() or hdd_dis_connect_handler() 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) { + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_Connecting")); + hdd_conn_set_connection_state(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 addtional 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; + } + /* + * When policy manager is enabled from ini file, we shouldn't + * check for other concurrency rules. + */ + if (!pHddCtx->config->policy_manager_enabled) { + cds_handle_conc_rule1(pHddCtx, pAdapter, + pRoamProfile); + if (true != cds_handle_conc_rule2(pHddCtx, + pAdapter, pRoamProfile, &roamId)) + return 0; + } + + sme_config = cdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + hdd_err("unable to allocate sme_config"); + return -ENOMEM; + } + cdf_mem_zero(sme_config, sizeof(*sme_config)); + sme_get_config_param(pHddCtx->hHal, sme_config); + /* These values are not sessionized. So, any change in these SME + * configs on an older or parallel interface will affect the + * cb mode. So, restoring the default INI params before starting + * interfaces such as sta, cli etc., + */ + sme_config->csrConfig.channelBondingMode5GHz = + pHddCtx->config->nChannelBondingMode5GHz; + sme_config->csrConfig.channelBondingMode24GHz = + pHddCtx->config->nChannelBondingMode24GHz; + sme_update_config(pHddCtx->hHal, sme_config); + cdf_mem_free(sme_config); + + status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, pRoamProfile, + &roamId); + + if ((CDF_STATUS_SUCCESS != status) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { + hddLog(LOGE, + FL("sme_roam_connect (session %d) failed with " + "status %d. -> NotConnected"), + pAdapter->sessionId, status); + /* change back to NotAssociated */ + hdd_conn_set_connection_state(pAdapter, + eConnectionState_NotConnected); + } + + pRoamProfile->ChannelInfo.ChannelList = NULL; + pRoamProfile->ChannelInfo.numOfChannels = 0; + + } else { + hddLog(LOGE, FL("No valid Roam profile")); + return -EINVAL; + } + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_set_auth_type() - set auth type + * @pAdapter: Pointer to adapter + * @auth_type: Auth type + * + * This function is used to set the authentication type (OPEN/SHARED). + * + * Return: 0 for success, non-zero for failure + */ +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(LOG1, + FL("set authentication type to AUTOSWITCH")); + 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(LOG1, + FL("set authentication type to OPEN")); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + break; + + case NL80211_AUTHTYPE_SHARED_KEY: + hddLog(LOG1, + FL("set authentication type to SHARED")); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; + break; +#ifdef FEATURE_WLAN_ESE + case NL80211_AUTHTYPE_NETWORK_EAP: + hddLog(LOG1, + FL("set authentication type to CCKM WPA")); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA; + break; +#endif + + default: + hddLog(LOGE, + FL("Unsupported authentication type %d"), auth_type); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN; + return -EINVAL; + } + + pWextState->roamProfile.AuthType.authType[0] = + pHddStaCtx->conn_info.authType; + return 0; +} + +/** + * wlan_hdd_set_akm_suite() - set key management type + * @pAdapter: Pointer to adapter + * @key_mgmt: Key management type + * + * This function is used to set the key mgmt type(PSK/8021x). + * + * Return: 0 for success, non-zero for failure + */ +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(); + +#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(LOG1, FL("setting key mgmt type to PSK")); + 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(LOG1, + FL("setting key mgmt type to 8021x")); + 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(LOG1, + FL("setting key mgmt type to CCKM")); + 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(LOG1, + FL("setting key mgmt type to OSEN")); + pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X; + break; + + default: + hddLog(LOGE, + FL("Unsupported key mgmt type %d"), key_mgmt); + return -EINVAL; + + } + return 0; +} + +/** + * wlan_hdd_cfg80211_set_cipher() - set encryption type + * @pAdapter: Pointer to adapter + * @cipher: Cipher type + * @ucast: Unicast flag + * + * This function is used to set the encryption type + * (NONE/WEP40/WEP104/TKIP/CCMP). + * + * Return: 0 for success, non-zero for failure + */ +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(LOGE, + 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(LOGE, + FL("Unsupported cipher type %d"), cipher); + return -EOPNOTSUPP; + } + } + + if (ucast) { + hddLog(LOG1, + FL("setting unicast cipher type to %d"), encryptionType); + pHddStaCtx->conn_info.ucEncryptionType = encryptionType; + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] = + encryptionType; + } else { + hddLog(LOG1, + FL("setting mcast cipher type to %d"), encryptionType); + pHddStaCtx->conn_info.mcEncryptionType = encryptionType; + pWextState->roamProfile.mcEncryptionType.numEntries = 1; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = + encryptionType; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_ie() - set IEs + * @pAdapter: Pointer to adapter + * @ie: Pointer ot ie + * @ie: IE length + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie, + size_t ie_len) +{ + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + const uint8_t *genie = ie; + uint16_t remLen = ie_len; +#ifdef FEATURE_WLAN_WAPI + uint32_t akmsuite[MAX_NUM_AKM_SUITES]; + u16 *tmp; + uint16_t akmsuiteCount; + int *akmlist; +#endif + ENTER(); + + /* clear previous assocAddIE */ + pWextState->assocAddIE.length = 0; + pWextState->roamProfile.bWPSAssociation = false; + pWextState->roamProfile.bOSENAssociation = false; + + while (remLen >= 2) { + uint16_t eLen = 0; + uint8_t elementId; + elementId = *genie++; + eLen = *genie++; + remLen -= 2; + + hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), 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(LOGE, FL("Invalid WPA IE")); + return -EINVAL; + } else if (0 == + memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set WPS IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, + FL("Cannot accommodate assocAddIE. Need bigger buffer space")); + CDF_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 = true; + pWextState->roamProfile.pAddIEAssoc = + pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = + pWextState->assocAddIE.length; + } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) { + hddLog(LOG1, + FL("Set WPA IE (len %d)"), eLen + 2); + 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; /* ie_len; */ + } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE, + P2P_OUI_TYPE_SIZE))) { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set P2P IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, + FL("Cannot accommodate assocAddIE Need bigger buffer space")); + CDF_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)) { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set WFD IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, + FL("Cannot accommodate assocAddIE Need bigger buffer space")); + CDF_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 Assiciation Request */ + else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE, + HS20_OUI_TYPE_SIZE))) { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set HS20 IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, + FL("Cannot accommodate assocAddIE Need bigger buffer space")); + CDF_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 Assiciation Request */ + else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE, + OSEN_OUI_TYPE_SIZE))) { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set OSEN IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, + FL("Cannot accommodate assocAddIE Need bigger buffer space")); + CDF_ASSERT(0); + return -ENOMEM; + } + memcpy(pWextState->assocAddIE.addIEdata + + curAddIELen, genie - 2, eLen + 2); + pWextState->assocAddIE.length += eLen + 2; + + pWextState->roamProfile.bOSENAssociation = true; + pWextState->roamProfile.pAddIEAssoc = + pWextState->assocAddIE.addIEdata; + pWextState->roamProfile.nAddIEAssocLength = + pWextState->assocAddIE.length; + } else { + uint16_t add_ie_len = + pWextState->assocAddIE.length; + + hdd_info("Set OSEN IE(len %d)", eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hdd_err("Cannot accommodate assocAddIE Need bigger buffer space"); + CDF_ASSERT(0); + return -ENOMEM; + } + + memcpy(pWextState->assocAddIE.addIEdata + + add_ie_len, 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(LOG1, FL("Set RSN IE(len %d)"), eLen + 2); + 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; /* ie_len; */ + break; + /* + * Appending Extended Capabilities with Interworking bit set + * in Assoc Req. + * + * In assoc req this EXT Cap will only be taken into account if + * interworkingService bit is set to 1. Currently + * driver is only interested in interworkingService capability + * from supplicant. If in future any other EXT Cap info is + * required from supplicat, it needs to be handled while + * sending Assoc Req in LIM. + */ + case DOT11F_EID_EXTCAP: + { + uint16_t curAddIELen = + pWextState->assocAddIE.length; + hddLog(LOG1, + FL("Set Extended CAPS IE(len %d)"), eLen + 2); + + if (SIR_MAC_MAX_ADD_IE_LENGTH < + (pWextState->assocAddIE.length + eLen)) { + hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space")); + CDF_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: + /* Setting WAPI Mode to ON=1 */ + pAdapter->wapi_info.nWapiMode = 1; + hddLog(LOG1, + FL("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(LOGE, + FL("Invalid akmSuite count")); + CDF_ASSERT(0); + return -EINVAL; + } + + if (WAPI_PSK_AKM_SUITE == akmsuite[0]) { + hddLog(LOG1, + FL("WAPI AUTH MODE SET TO PSK")); + pAdapter->wapi_info.wapiAuthMode = + WAPI_AUTH_MODE_PSK; + } + if (WAPI_CERT_AKM_SUITE == akmsuite[0]) { + hddLog(LOG1, + FL("WAPI AUTH MODE SET TO CERTIFICATE")); + pAdapter->wapi_info.wapiAuthMode = + WAPI_AUTH_MODE_CERT; + } + break; +#endif + default: + hddLog(LOGE, + FL("Set UNKNOWN IE %X"), 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; +} + +/** + * hdd_is_wpaie_present() - check for WPA ie + * @ie: Pointer to ie + * @ie_len: Ie length + * + * Parse the received IE to find the WPA IE + * + * Return: true if wpa ie is found else false + */ +static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len) +{ + uint8_t eLen = 0; + uint16_t remLen = ie_len; + uint8_t elementId = 0; + + while (remLen >= 2) { + elementId = *ie++; + eLen = *ie++; + remLen -= 2; + if (eLen > remLen) { + hddLog(CDF_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; +} + +/** + * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection + * @pAdapter: Pointer to adapter + * @req: Pointer to security parameters + * + * Return: 0 for success, non-zero for failure + */ +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(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion); + + /*set authentication type */ + status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type); + + if (0 > status) { + hddLog(LOGE, FL("failed to set authentication type ")); + 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(LOGE, FL("failed to set akm suite")); + 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(LOGE, FL("failed to set unicast cipher type")); + return status; + } + } else { + /*Reset previous cipher suite to none */ + status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true); + if (0 > status) { + hddLog(LOGE, FL("failed to set unicast cipher type")); + return status; + } + } + + /*set group cipher type */ + status = + wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group, + false); + + if (0 > status) { + hddLog(LOGE, FL("failed to set mcast cipher type")); + return status; + } +#ifdef WLAN_FEATURE_11W + pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED); +#endif + + /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */ + if (req->ie_len) { + status = + wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len); + if (0 > status) { + hddLog(LOGE, 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(LOGE, + FL("Dynamic WEP not supported")); + 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(LOG1, + FL("setting default wep key, key_idx = %hu key_len %hu"), + key_idx, key_len); + cdf_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; +} + +/** + * wlan_hdd_try_disconnect() - try disconnnect from previous connection + * @pAdapter: Pointer to adapter + * + * This function is used to disconnect from previous connection + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter) +{ + unsigned long rc; + hdd_station_ctx_t *pHddStaCtx; + eMib_dot11DesiredBssType connectedBssType; + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType); + + if ((eMib_dot11DesiredBssType_independent == connectedBssType) || + (eConnectionState_Associated == pHddStaCtx->conn_info.connState) || + (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) { + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Disconnecting); + /* Issue disconnect to CSR */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + if (CDF_STATUS_SUCCESS == + sme_roam_disconnect(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("Sme disconnect event timed out session Id %d staDebugState %d"), + pAdapter->sessionId, + pHddStaCtx->staDebugState); + return -EALREADY; + } + } + } 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); + return -EALREADY; + } + } + + return 0; +} + +/** + * __wlan_hdd_cfg80211_connect() - cfg80211 connect api + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @req: Pointer to cfg80211 connect request + * + * This function is used to start the association process + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *req) +{ + int status; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("Device_mode %s(%d) is not supported"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddCtx) { + hddLog(LOGE, FL("HDD context is null")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + if (req->channel) { + if (!cds_allow_concurrency(pHddCtx, + cds_convert_device_mode_to_hdd_type( + pAdapter->device_mode), + req->channel->hw_value, HW_MODE_20_MHZ)) { + hdd_err("This concurrency combination is not allowed"); + return -ECONNREFUSED; + } + } else { + if (!cds_allow_concurrency(pHddCtx, + cds_convert_device_mode_to_hdd_type( + pAdapter->device_mode), 0, HW_MODE_20_MHZ)) { + hdd_err("This concurrency combination is not allowed"); + return -ECONNREFUSED; + } + } +#if defined(FEATURE_WLAN_LFR) + wlan_hdd_disable_roaming(pAdapter); +#endif + + /*Try disconnecting if already in connected state */ + status = wlan_hdd_try_disconnect(pAdapter); + if (0 > status) { + hddLog(LOGE, + FL("Failed to disconnect the existing connection")); + return -EALREADY; + } + + /*initialise security parameters */ + status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); + + if (0 > status) { + hddLog(LOGE, + FL("failed to set security params")); + return status; + } + + if (req->channel) { + status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, + req->ssid_len, + req->bssid, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \ + defined(CFG80211_BSSID_HINT_BACKPORT) + req->bssid_hint, +#else + NULL, +#endif + req->channel-> + hw_value); + } else { + status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, + req->ssid_len, + req->bssid, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \ + defined(CFG80211_BSSID_HINT_BACKPORT) + req->bssid_hint, +#else + NULL, +#endif + 0); + } + + if (0 > status) { + hddLog(LOGE, FL("connect failed")); + return status; + } + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_connect() - cfg80211 connect api + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @req: Pointer to cfg80211 connect request + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *req) +{ + int ret; + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_disconnect() - hdd disconnect api + * @pAdapter: Pointer to adapter + * @reason: Disconnect reason code + * + * This function is used to issue a disconnect request to SME + * + * Return: 0 for success, non-zero for failure + */ +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); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, + FL("HDD context is not valid")); + return status; + } + + /*stop tx queues */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_Disconnecting")); + pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting; + INIT_COMPLETION(pAdapter->disconnect_comp_var); + + /*issue disconnect */ + + status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, reason); + if (CDF_STATUS_CMD_NOT_QUEUED == status) { + hddLog(LOG1, FL("status = %d, already disconnected"), + (int)status); + goto disconnected; + } else if (0 != status) { + hddLog(LOGE, + FL("csr_roam_disconnect 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) { + hddLog(LOGE, + FL("Failed to disconnect, timed out")); + result = -ETIMEDOUT; + } +disconnected: + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_NotConnected")); + hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) + /* Sending disconnect event to userspace for kernel version < 3.11 + * is handled by __cfg80211_disconnect call to __cfg80211_disconnected + */ + hddLog(LOG1, FL("Send disconnected event to userspace")); + cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, + NULL, 0, GFP_KERNEL); +#endif + + return result; +} + +/** + * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @reason: Disconnect reason code + * + * This function is used to issue a disconnect request to SME + * + * Return: 0 for success, non-zero for failure + */ +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 + uint8_t staIdx; +#endif + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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(LOGE, FL("HDD context is not valid")); + return status; + } + + /* 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->config-> + 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; + } + hddLog(LOG1, + FL("convert to internal reason %d to reasonCode %d"), + reason, reasonCode); + pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; + pScanInfo = &pAdapter->scan_info; + if (pScanInfo->mScanPending) { + hddLog(LOG1, + FL("Disconnect is in progress, Aborting Scan")); + hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } +#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_t *mac; + mac = + pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes; + hddLog(LOG1, + "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d " + MAC_ADDRESS_STR, __func__, + pHddCtx->tdlsConnInfo[staIdx].staId, + pAdapter->sessionId, + MAC_ADDR_ARRAY(mac)); + sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, mac); + } + } +#endif + hddLog(LOG1, FL("Disconnecting with reasoncode:%u"), + reasonCode); + status = wlan_hdd_disconnect(pAdapter, reasonCode); + if (0 != status) { + hddLog(LOGE, + FL("failure, returned %d"), status); + return -EINVAL; + } + } else { + hddLog(LOGE, + FL("unexpected cfg disconnect called while in state (%d)"), + pHddStaCtx->conn_info.connState); + } + + return status; +} + +/** + * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @reason: Disconnect reason code + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *dev, u16 reason) +{ + int ret; + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy + * @pAdapter: Pointer to adapter + * @param: Pointer to IBSS parameters + * + * This function is used to initialize the security settings in IBSS mode + * + * Return: 0 for success, non-zero for failure + */ +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; + cdf_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_is_wpaie_present(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 */ + dot11f_unpack_ie_wpa((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_translate_wpa_to_csr_encryption_type + (dot11WPAIE.multicast_cipher); + } + } + + status = + wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, + params->ie_len); + + if (0 > status) { + hddLog(LOGE, 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 paramters, 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; + } + hddLog(LOG2, FL("encryptionType=%d"), encryptionType); + pHddStaCtx->conn_info.ucEncryptionType = encryptionType; + pWextState->roamProfile.EncryptionType.numEntries = 1; + pWextState->roamProfile.EncryptionType.encryptionType[0] = + encryptionType; + return status; +} + +/** + * __wlan_hdd_cfg80211_join_ibss() - join ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to IBSS join parameters + * + * This function is used to create/join an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +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); + struct cdf_mac_addr bssid; + u8 channelNum = 0; + p_cds_contextType p_cds_context; + + ENTER(); + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hdd_err("Invalid CDS context"); + return -EINVAL; + } + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if (NULL != +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + params->chandef.chan) +#else + params->channel) +#endif + { + uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + uint8_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)) + params-> + chandef. + chan-> + center_freq); +#else + params-> + channel-> + center_freq); +#endif + + if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans)) { + hddLog(LOGE, FL("No valid channel list")); + return -EOPNOTSUPP; + } + + for (indx = 0; indx < numChans; indx++) { + if (channelNum == validChan[indx]) { + break; + } + } + if (indx >= numChans) { + hddLog(LOGE, + FL("Not valid Channel %d"), channelNum); + return -EINVAL; + } + } + + if (!cds_allow_concurrency(pHddCtx, CDS_IBSS_MODE, channelNum, + HW_MODE_20_MHZ)) { + hdd_err("This concurrency combination is not allowed"); + return -ECONNREFUSED; + } + if (pHddCtx->config->policy_manager_enabled) { + status = cdf_event_reset( + &p_cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(status)) + hdd_err("ERR: clear event failed"); + + status = cds_current_connections_update(pHddCtx, + channelNum); + if (CDF_STATUS_E_FAILURE == status) { + hdd_err("ERROR: connections update failed!!"); + return -EINVAL; + } + + if (CDF_STATUS_SUCCESS == status) { + status = cdf_wait_single_event( + &p_cds_context->connection_update_done_evt, + CONNECTION_UPDATE_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("ERROR: cdf wait for event failed!!"); + return -EINVAL; + } + } + } + + /*Try disconnecting if already in connected state */ + status = wlan_hdd_try_disconnect(pAdapter); + if (0 > status) { + hddLog(LOGE, + FL("Failed to disconnect the existing IBSS connection")); + return -EALREADY; + } + + pRoamProfile = &pWextState->roamProfile; + + if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) { + hddLog(LOGE, + FL("Interface type is not set to IBSS")); + return -EINVAL; + } + + /* enable selected protection checks in IBSS mode */ + pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK; + + if (CDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal, + WNI_CFG_IBSS_ATIM_WIN_SIZE, + pHddCtx->config-> + ibssATIMWinSize)) { + hddLog(LOGE, + FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM")); + } + + /* BSSID is provided by upper layers hence no need to AUTO generate */ + if (NULL != params->bssid) { + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0) + == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID")); + return -EIO; + } + cdf_mem_copy(bssid.bytes, params->bssid, CDF_MAC_ADDR_SIZE); + } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) { + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0) + == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID")); + return -EIO; + } + cdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid); + } + 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(LOG2, + FL("input beacon interval %d TU is invalid, use default %d TU"), + params->beacon_interval, pRoamProfile->beaconInterval); + } + + /* Set Channel */ + if (channelNum) { + /* Set the Operational Channel */ + hddLog(LOG2, FL("set channel %d"), 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(LOGE, + FL("failed to set security parameters")); + return status; + } + + /* Issue connect start */ + status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, + params->ssid_len, + bssid.bytes, + NULL, + pHddStaCtx->conn_info. + operationChannel); + + if (0 > status) { + hddLog(LOGE, FL("connect failed")); + return status; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_join_ibss() - join ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to IBSS join parameters + * + * This function is used to create/join an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_leave_ibss() - leave ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * This function is used to leave an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +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; + CDF_STATUS hal_status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + if (NULL == pWextState) { + hddLog(LOGE, 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(LOGE, + FL("BSS Type is not set to IBSS")); + return -EINVAL; + } + + /* Issue Disconnect request */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + if (!CDF_IS_STATUS_SUCCESS(hal_status)) { + hddLog(LOGE, + FL("sme_roam_disconnect failed hal_status(%d)"), + hal_status); + return -EAGAIN; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_leave_ibss() - leave ibss + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * This function is used to leave an IBSS network + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters + * @wiphy: Pointer to wiphy + * @changed: Parameters changed + * + * This function is used to set the phy parameters. RTS Threshold/FRAG + * Threshold/Retry Count etc. + * + * Return: 0 for success, non-zero for failure + */ +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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS, + NO_SESSION, wiphy->rts_threshold)); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, + FL("HDD context is not valid")); + return status; + } + + 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(LOGE, + FL("Invalid RTS Threshold value %u"), + rts_threshold); + return -EINVAL; + } + + if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD, + rts_threshold)) { + hddLog(LOGE, + FL("sme_cfg_set_int failed for rts_threshold value %u"), + rts_threshold); + return -EIO; + } + + hddLog(LOG2, FL("set rts threshold %u"), 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(LOGE, + FL("Invalid frag_threshold value %hu"), + frag_threshold); + return -EINVAL; + } + + if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, + frag_threshold)) { + hddLog(LOGE, + FL("sme_cfg_set_int failed for frag_threshold value %hu"), + frag_threshold); + return -EIO; + } + + hddLog(LOG2, FL("set frag threshold %hu"), 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(LOGE, + FL("Invalid Retry count %hu"), retry_value); + return -EINVAL; + } + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + if (0 != sme_cfg_set_int(hHal, + WNI_CFG_LONG_RETRY_LIMIT, + retry_value)) { + hddLog(LOGE, + FL("sme_cfg_set_int failed for long retry count %hu"), + retry_value); + return -EIO; + } + hddLog(LOG2, + FL("set long retry count %hu"), retry_value); + } else if (changed & WIPHY_PARAM_RETRY_SHORT) { + if (0 != sme_cfg_set_int(hHal, + WNI_CFG_SHORT_RETRY_LIMIT, + retry_value)) { + hddLog(LOGE, + FL("sme_cfg_set_int failed for short retry count %hu"), + retry_value); + return -EIO; + } + hddLog(LOG2, + FL("set short retry count %hu"), retry_value); + } + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters + * @wiphy: Pointer to wiphy + * @changed: Parameters changed + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt + * key + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @key_index: Key index + * + * Return: 0 + */ +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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index); + cds_ssr_unprotect(__func__); + + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +/** + * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @params: Pointer to tx queue parameters + * + * Return: 0 + */ +static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_txq_params *params) +{ + ENTER(); + return 0; +} +#else +/** + * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params + * @wiphy: Pointer to wiphy + * @params: Pointer to tx queue parameters + * + * Return: 0 + */ +static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + ENTER(); + return 0; +} +#endif /* LINUX_VERSION_CODE */ + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_set_txq_params(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} +#else +static int wlan_hdd_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_set_txq_params(wiphy, params); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif /* LINUX_VERSION_CODE */ + +/** + * __wlan_hdd_cfg80211_del_station() - delete station v2 + * @wiphy: Pointer to wiphy + * @param: Pointer to delete station parameter + * + * Return: 0 for success, non-zero for failure + */ +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; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + hdd_hostapd_state_t *hapd_state; + int status; + uint8_t staId; + uint8_t *mac; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes; + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + + hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + if (!hapd_state) { + hddLog(LOGE, "%s: Hostapd State is Null", __func__); + return 0; + } + + if (cdf_is_macaddr_broadcast((struct cdf_mac_addr *) mac)) { + uint16_t i; + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if ((pAdapter->aStaInfo[i].isUsed) && + (!pAdapter->aStaInfo[i]. + isDeauthInProgress)) { + cdf_mem_copy( + mac, + pAdapter->aStaInfo[i]. + macAddrSTA.bytes, + ETHER_ADDR_LEN); + if (hdd_ipa_uc_is_enabled(pHddCtx)) { + hdd_ipa_wlan_evt(pAdapter, + pAdapter-> + aStaInfo[i]. + ucSTAId, + WLAN_CLIENT_DISCONNECT, + mac); + } + hddLog(LOG1, + FL("Delete STA with MAC::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + + if (pHddCtx->dev_dfs_cac_status == + DFS_CAC_IN_PROGRESS) + goto fn_end; + + cdf_event_reset(&hapd_state->cdf_event); + hdd_softap_sta_disassoc(pAdapter, + mac); + cdf_status = + hdd_softap_sta_deauth(pAdapter, + pDelStaParams); + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + pAdapter->aStaInfo[i]. + isDeauthInProgress = true; + cdf_status = + cdf_wait_single_event( + &hapd_state->cdf_event, + 1000); + if (!CDF_IS_STATUS_SUCCESS( + cdf_status)) + hddLog(LOGE, + "%s: Deauth wait time expired", + __func__); + } + } + } + } else { + cdf_status = + hdd_softap_get_sta_id(pAdapter, + (struct cdf_mac_addr *) mac, + &staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOG1, + FL("Skip DEL STA as this is not used::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + return -ENOENT; + } + + if (hdd_ipa_uc_is_enabled(pHddCtx)) { + hdd_ipa_wlan_evt(pAdapter, staId, + WLAN_CLIENT_DISCONNECT, mac); + } + + if (pAdapter->aStaInfo[staId].isDeauthInProgress == + true) { + hddLog(LOG1, + FL("Skip DEL STA as deauth is in progress::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + return -ENOENT; + } + + pAdapter->aStaInfo[staId].isDeauthInProgress = true; + + hddLog(LOG1, + FL("Delete STA with MAC::" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + + /* Case: SAP in ACS selected DFS ch and client connected + * Now Radar detected. Then if random channel is another + * DFS ch then new CAC is initiated and no TX allowed. + * So 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; + + cdf_event_reset(&hapd_state->cdf_event); + hdd_softap_sta_disassoc(pAdapter, mac); + cdf_status = hdd_softap_sta_deauth(pAdapter, + pDelStaParams); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pAdapter->aStaInfo[staId].isDeauthInProgress = + false; + hddLog(LOG1, + FL("STA removal failed for ::" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + return -ENOENT; + } else { + cdf_status = cdf_wait_single_event( + &hapd_state->cdf_event, + 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, + "%s: Deauth wait time expired", + __func__); + } + } + } + +fn_end: + EXIT(); + return 0; +} + +#ifdef CFG80211_DEL_STA_V2 +/** + * wlan_hdd_cfg80211_del_station() - delete station v2 + * @wiphy: Pointer to wiphy + * @param: Pointer to delete station parameter + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + struct station_del_parameters *param) +#else +/** + * wlan_hdd_cfg80211_del_station() - delete station + * @wiphy: Pointer to wiphy + * @mac: Pointer to station mac address + * + * Return: 0 for success, non-zero for failure + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *mac) +#else +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + uint8_t *mac) +#endif +#endif +{ + int ret; + struct tagCsrDelStaParams delStaParams; + + cds_ssr_protect(__func__); +#ifdef CFG80211_DEL_STA_V2 + if (NULL == param) { + hddLog(LOGE, FL("Invalid argumet passed")); + return -EINVAL; + } + wlansap_populate_del_sta_params(param->mac, param->reason_code, + param->subtype, &delStaParams); +#else + wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + (SIR_MAC_MGMT_DEAUTH >> 4), + &delStaParams); +#endif + ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_add_station() - add station + * @wiphy: Pointer to wiphy + * @mac: Pointer to station mac address + * @pmksa: Pointer to add station parameter + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *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 (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_ADD_STA, + pAdapter->sessionId, params->listen_interval)); + + if (0 != wlan_hdd_validate_context(pHddCtx)) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + mask = params->sta_flags_mask; + + set = params->sta_flags_set; + + hddLog(LOG1, 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 + return status; +} + +/** + * wlan_hdd_cfg80211_add_station() - add station + * @wiphy: Pointer to wiphy + * @mac: Pointer to station mac address + * @pmksa: Pointer to add station parameter + * + * Return: 0 for success, non-zero for failure + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *mac, + struct station_parameters *params) +#else +static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, uint8_t *mac, + struct station_parameters *params) +#endif +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef FEATURE_WLAN_LFR +/** + * __wlan_hdd_cfg80211_set_pmksa() - set pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @pmksa: Pointer to set pmksa parameter + * + * Return: 0 for success, non-zero for failure + */ +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; + CDF_STATUS result = CDF_STATUS_SUCCESS; + int status; + tPmkidCacheInfo pmk_id; + + if (CDF_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(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + cdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, ETHER_ADDR_LEN); + cdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE); + + /* Add to the PMKSA ID Cache in CSR */ + result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId, + &pmk_id, 1, false); + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_PMKSA, + pAdapter->sessionId, result)); + + return CDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL; +} + +/** + * wlan_hdd_cfg80211_set_pmksa() - set pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @pmksa: Pointer to set pmksa parameter + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @pmksa: Pointer to pmksa parameter + * + * Return: 0 for success, non-zero for failure + */ +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; + + if (CDF_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(CDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + /* Delete the PMKID CSR cache */ + if (CDF_STATUS_SUCCESS != + sme_roam_del_pmkid_from_cache(halHandle, + pAdapter->sessionId, pmksa->bssid, + false)) { + hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pmksa->bssid)); + status = -EINVAL; + } + + return status; +} + +/** + * wlan_hdd_cfg80211_del_pmksa() - delete pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @pmksa: Pointer to pmksa parameter + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_pmksa *pmksa) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa); + cds_ssr_unprotect(__func__); + + return ret; + +} + +/** + * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * Return: 0 for success, non-zero for failure + */ +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; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + hddLog(LOGW, FL("Flushing PMKSA")); + + 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; + } + + /* Retrieve halHandle */ + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + /* Flush the PMKID cache in CSR */ + if (CDF_STATUS_SUCCESS != + sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL, + true)) { + hddLog(LOGE, FL("Cannot flush PMKIDCache")); + status = -EINVAL; + } + + return status; +} + +/** + * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) +/** + * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @ftie: Pointer to fast transition ie parameter + * + * Return: 0 for success, non-zero for failure + */ +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; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, + (const u8 *)ftie->ie, ftie->ie_len); + return 0; +} + +/** + * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @ftie: Pointer to fast transition ie parameter + * + * Return: 0 for success, non-zero for failure + */ +static int +wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/** + * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback + * @callbackContext: Callback context + * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter + * + * Callback rountine called upon receiving response for get offload info + * + * Return: none + */ +void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext, + tpSirGtkOffloadGetInfoRspParams + pGtkOffloadGetInfoRsp) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext; + uint8_t tempReplayCounter[8]; + hdd_station_ctx_t *pHddStaCtx; + + ENTER(); + + if (NULL == pAdapter) { + hddLog(LOGE, FL("HDD adapter is Null")); + return; + } + + if (NULL == pGtkOffloadGetInfoRsp) { + hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null")); + return; + } + + if (CDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) { + hddLog(LOGE, FL("wlan Failed to get replay counter value")); + 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; + uint8_t *p = + (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter; + + for (i = 0; i < 8; i++) { + tempReplayCounter[7 - i] = (uint8_t) p[i]; + } + } + + /* Update replay counter to NL */ + cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId, + tempReplayCounter, GFP_KERNEL); +} + +/** + * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @data: Pointer to rekey data + * + * This function is used to offload GTK rekeying job to the firmware. + * + * Return: 0 for success, non-zero for failure + */ +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; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA, + pAdapter->sessionId, pAdapter->device_mode)); + + result = wlan_hdd_validate_context(pHddCtx); + + if (0 != result) { + hddLog(LOGE, FL("HDD context is not valid")); + return result; + } + + 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, CDF_MAC_ADDR_SIZE); + { + /* changing from big to little endian since driver + * works on little endian format + */ + uint8_t *p = + (uint8_t *) &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_set_gtk_offload(hHal, &hddGtkOffloadReqParams, + pAdapter->sessionId); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"), + status); + return -EINVAL; + } + hddLog(LOG1, FL("sme_set_gtk_offload successful")); + } else { + hddLog(LOG1, + FL("wlan not suspended GTKOffload request is stored")); + } + + return result; +} + +/** + * wlan_hdd_cfg80211_set_rekey_data() - set rekey data + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @data: Pointer to rekey data + * + * This function is used to offload GTK rekeying job to the firmware. + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_gtk_rekey_data *data) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif /*WLAN_FEATURE_GTK_OFFLOAD */ + +/** + * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @param: Pointer to access control parameter + * + * Return: 0 for success, non-zero for failure + */ +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 p_cds_context = NULL; + hdd_context_t *pHddCtx; + int status; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (NULL == params) { + hddLog(LOGE, FL("params is Null")); + return -EINVAL; + } + + 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; + } + + p_cds_context = pHddCtx->pcds_context; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + if (NULL == pHostapdState) { + hddLog(LOGE, FL("pHostapdState is Null")); + return -EINVAL; + } + + hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy, + params->n_acl_entries); + + 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 { + hddLog(LOGE, FL("Acl Policy : %d is not supported"), + 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++) { + hddLog(LOG1, + FL("** Add ACL MAC entry %i in WhiletList :" + MAC_ADDRESS_STR), i, + MAC_ADDR_ARRAY( + params->mac_addrs[i].addr)); + + cdf_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++) { + hddLog(LOG1, + FL("** Add ACL MAC entry %i in BlackList :" + MAC_ADDRESS_STR), i, + MAC_ADDR_ARRAY( + params->mac_addrs[i].addr)); + + cdf_mem_copy(&pConfig->deny_mac[i], + params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } +#ifdef WLAN_FEATURE_MBSSID + cdf_status = + wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), + pConfig); +#else + cdf_status = wlansap_set_mac_acl(p_cds_context, pConfig); +#endif + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("SAP Set Mac Acl fail")); + return -EINVAL; + } + } else { + hddLog(LOG1, FL("Invalid device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + return -EINVAL; + } + + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_NL80211_TESTMODE +#ifdef FEATURE_WLAN_LPHB +/** + * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication + * @pHddCtx: Pointer to hdd context + * @lphbInd: Pointer to low power heart beat indication parameter + * + * Return: none + */ +void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd) +{ + struct sk_buff *skb; + + hddLog(LOGE, FL("LPHB indication arrived")); + + if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx)) { + hddLog(LOGE, FL("invalid argument pHddCtx")); + return; + } + + if (NULL == lphbInd) { + hddLog(LOGE, FL("invalid argument lphbInd")); + return; + } + + skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)-> + wiphy, sizeof(tSirLPHBInd), + GFP_ATOMIC); + if (!skb) { + hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail")); + return; + } + + if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) { + hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail")); + goto nla_put_failure; + } + if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) { + hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail")); + goto nla_put_failure; + } + if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) { + hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail")); + goto nla_put_failure; + } + cfg80211_testmode_event(skb, GFP_ATOMIC); + return; + +nla_put_failure: + hddLog(LOGE, FL("NLA Put fail")); + kfree_skb(skb); + + return; +} +#endif /* FEATURE_WLAN_LPHB */ + +/** + * __wlan_hdd_cfg80211_testmode() - test mode + * @wiphy: Pointer to wiphy + * @data: Data pointer + * @len: Data length + * + * Return: 0 for success, non-zero for failure + */ +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); + + err = wlan_hdd_validate_context(pHddCtx); + if (err) + return err; + + 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; + } + + 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; + CDF_STATUS smeStatus; + + 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 *) cdf_mem_malloc(sizeof(tSirLPHBReq)); + if (NULL == hb_params) { + hddLog(LOGE, FL("Request Buffer Alloc Fail")); + return -ENOMEM; + } + + cdf_mem_copy(hb_params, buf, buf_len); + smeStatus = + sme_lphb_config_req((tHalHandle) (pHddCtx->hHal), + hb_params, + wlan_hdd_cfg80211_lphb_ind_handler); + if (CDF_STATUS_SUCCESS != smeStatus) { + hddLog(LOGE, "LPHB Config Fail, disable"); + cdf_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; + CDF_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 != CDF_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; + } + + return err; +} + +/** + * wlan_hdd_cfg80211_testmode() - test mode + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @data: Data pointer + * @len: Data length + * + * Return: 0 for success, non-zero for failure + */ +static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) + struct wireless_dev *wdev, +#endif + void *data, int len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len); + cds_ssr_unprotect(__func__); + + return ret; +} + +#if defined(QCA_WIFI_FTM) +/** + * wlan_hdd_testmode_rx_event() - test mode rx event handler + * @buf: Pointer to buffer + * @buf_len: Buffer length + * + * Return: none + */ +void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len) +{ + struct sk_buff *skb; + hdd_context_t *hdd_ctx; + + if (!buf || !buf_len) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: buf or buf_len invalid, buf = %p buf_len = %zu", + __func__, buf, buf_len); + return; + } + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: hdd context invalid", __func__); + return; + } + + skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy, + buf_len, GFP_KERNEL); + if (!skb) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: nla_put failed on testmode rx skb!", __func__); +} +#endif +#endif /* CONFIG_NL80211_TESTMODE */ + +#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; + CDF_STATUS status; + tSmeConfigParams sme_config; + bool cbModeChange; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + 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; + } + + cdf_mem_zero(&sme_config, sizeof(tSmeConfigParams)); + sme_get_config_param(pHddCtx->hHal, &sme_config); + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20: + if (sme_config.csrConfig.channelBondingMode24GHz != + eCSR_INI_SINGLE_CHANNEL_CENTERED) { + sme_config.csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sme_update_config(pHddCtx->hHal, &sme_config); + cbModeChange = true; + } + break; + + case NL80211_CHAN_WIDTH_40: + if (sme_config.csrConfig.channelBondingMode24GHz == + eCSR_INI_SINGLE_CHANNEL_CENTERED) { + if (NL80211_CHAN_HT40MINUS == + cfg80211_get_chandef_type(chandef)) + sme_config.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + else + sme_config.csrConfig.channelBondingMode24GHz = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + sme_update_config(pHddCtx->hHal, &sme_config); + 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"), + sme_config.csrConfig.channelBondingMode24GHz); + + /* Change SAP ht2040 mode */ + status = hdd_set_sap_ht2040_mode(pAdapter, + cfg80211_get_chandef_type(chandef)); + if (status != CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +/** + * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type + * translation from NL to policy manager type + * @type: Generic connection mode type defined in NL + * + * + * This function provides the type translation + * + * Return: cds_con_mode enum + */ +enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type( + enum nl80211_iftype type) +{ + enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE; + switch (type) { + case NL80211_IFTYPE_STATION: + mode = CDS_STA_MODE; + break; + case NL80211_IFTYPE_P2P_CLIENT: + mode = CDS_P2P_CLIENT_MODE; + break; + case NL80211_IFTYPE_P2P_GO: + mode = CDS_P2P_GO_MODE; + break; + case NL80211_IFTYPE_AP: + mode = CDS_SAP_MODE; + break; + case NL80211_IFTYPE_ADHOC: + mode = CDS_IBSS_MODE; + break; + default: + hddLog(LOGE, FL("Unsupported interface type (%d)"), + type); + } + return mode; +} + +/** + * struct cfg80211_ops - cfg80211_ops + * + * @add_virtual_intf: Add virtual interface + * @del_virtual_intf: Delete virtual interface + * @change_virtual_intf: Change virtual interface + * @change_station: Change station + * @add_beacon: Add beacon in sap mode + * @del_beacon: Delete beacon in sap mode + * @set_beacon: Set beacon in sap mode + * @start_ap: Start ap + * @change_beacon: Change beacon + * @stop_ap: Stop ap + * @change_bss: Change bss + * @add_key: Add key + * @get_key: Get key + * @del_key: Delete key + * @set_default_key: Set default key + * @set_channel: Set channel + * @scan: Scan + * @connect: Connect + * @disconnect: Disconnect + * @join_ibss = Join ibss + * @leave_ibss = Leave ibss + * @set_wiphy_params = Set wiphy params + * @set_tx_power = Set tx power + * @get_tx_power = get tx power + * @remain_on_channel = Remain on channel + * @cancel_remain_on_channel = Cancel remain on channel + * @mgmt_tx = Tx management frame + * @mgmt_tx_cancel_wait = Cancel management tx wait + * @set_default_mgmt_key = Set default management key + * @set_txq_params = Set tx queue parameters + * @get_station = Get station + * @set_power_mgmt = Set power management + * @del_station = Delete station + * @add_station = Add station + * @set_pmksa = Set pmksa + * @del_pmksa = Delete pmksa + * @flush_pmksa = Flush pmksa + * @update_ft_ies = Update FT IEs + * @tdls_mgmt = Tdls management + * @tdls_oper = Tdls operation + * @set_rekey_data = Set rekey data + * @sched_scan_start = Scheduled scan start + * @sched_scan_stop = Scheduled scan stop + * @resume = Resume wlan + * @suspend = Suspend wlan + * @set_mac_acl = Set mac acl + * @testmode_cmd = Test mode command + * @set_ap_chanwidth = Set AP channel bandwidth + * @dump_survey = Dump survey + * @key_mgmt_set_pmk = Set pmk key management + */ +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)) + .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, + .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, +}; diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h new file mode 100644 index 000000000000..7357451f4ca1 --- /dev/null +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -0,0 +1,2279 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_cfg80211.h + * + * WLAN host device driver cfg80211 functions declaration + */ + +#if !defined(HDD_CFG80211_H__) +#define HDD_CFG80211_H__ + +/* 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-" +#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 + +#define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) +#define MAX_SCAN_SSID 10 + +/** + * typedef struct qcom_ie_age - age ie + * + * @element_id: Element id + * @len: Length + * @oui_1: OUI 1 + * @oui_2: OUI 2 + * @oui_3: OUI 3 + * @type: Type + * @age: Age + * @tsf_delta: tsf delta from FW + */ +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 + +/** + * enum eDFS_CAC_STATUS: CAC status + * + * @DFS_CAC_NEVER_DONE: CAC never done + * @DFS_CAC_IN_PROGRESS: CAC is in progress + * @DFS_CAC_IN_PROGRESS: CAC already done + */ +typedef enum { + DFS_CAC_NEVER_DONE, + DFS_CAC_IN_PROGRESS, + DFS_CAC_ALREADY_DONE, +} eDFS_CAC_STATUS; + +/* 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: NL 80211 vendor sub command + * + * @QCA_NL80211_VENDOR_SUBCMD_UNSPEC: Unspecified + * @QCA_NL80211_VENDOR_SUBCMD_TEST: Test + * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Avoid frequency. + * Sub commands 2 to 9 are not used + * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: DFS capability + * @QCA_NL80211_VENDOR_SUBCMD_NAN: Nan + * @QCA_NL80211_VENDOR_SUBCMD_STATS_EXT: Ext stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET: Link layer stats set + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET: Link layer stats get + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR: Link layer stats clear + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS: Link layer stats radio + * results + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS: Link layer stats interface + * results + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS: Link layer stats peer + * results + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START: Ext scan start + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP: Ext scan stop + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS: Ext scan get valid + * channels + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES: Ext scan get capability + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS: Ext scan get cached + * results + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE: Ext scan results + * available. Used when report_threshold is reached in scan cache. + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT: Ext scan full scan + * result. 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_SCAN_EVENT: Ext scan event from target. + * Indicates progress of scanning state-machine. + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND: Ext scan hotlist + * ap found + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST: Ext scan set hotlist + * bssid + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST: Ext scan reset + * hotlist bssid + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE: Ext scan significant + * change + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE: Ext scan set + * significant change + * ap found + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE: Ext scan reset + * significant change + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE: Ext tdls enable + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE: Ext tdls disable + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS: Ext tdls get status + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE: Ext tdls state + * @QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES: Get supported features + * @QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI: Set scanning_mac_oui + * @QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG: No DFS flag + * @QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX: Get Concurrency Matrix + * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Get the key mgmt offload keys + * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: After roaming, send the + * roaming and auth information. + * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED: Set OCB schedule + * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS offload flag + * @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Get the supported features by the + * driver. + * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Indicate that driver + * started CAC on DFS channel + * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED: Indicate that driver + * completed the CAC check on DFS channel + * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED: Indicate that the CAC + * check was aborted by the driver + * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED: Indicate that the + * driver completed NOP + * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Indicate that the + * driver detected radar signal on the current operating channel + * @QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO: get wlan driver information + * @QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START: start wifi logger + * @QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP: memory dump request + * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: get logger feature set + * @QCA_NL80211_VENDOR_SUBCMD_ROAM: roam + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST: extscan set ssid hotlist + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST: + * extscan reset ssid hotlist + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND: hotlist ssid found + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST: hotlist ssid lost + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST: set pno list + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST: set passpoint list + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST: + * reset passpoint list + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND: pno network found + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND: + * passpoint network found + * @QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION: set wifi config + * @QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION: get wifi config + * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: get logging features + * @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command + * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete + */ + +enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, + QCA_NL80211_VENDOR_SUBCMD_TEST = 1, + 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, + + 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, + + 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, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE = 25, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT = 26, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT = 27, + 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, + + 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, + + QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES = 38, + + QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39, + 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, + + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50, + QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51, + + /* Deprecated */ + QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED = 53, + + QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54, + + 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, + + QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61, + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62, + 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, + + /* DBS subcommands */ + QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103, + QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104, + + /* Vendor scan commands */ + QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN = 106, + QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE = 107, +}; + +/** + * enum qca_nl80211_vendor_subcmds_index - vendor sub commands index + * + * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX: Avoid frequency + * @QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX: Nan + * @QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX: Ext stats + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX: Ext scan start + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX: Ext scan stop + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX: Ext scan get + * capability + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX: Ext scan get + * cached results + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX: Ext scan + * results available + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX: Ext scan full + * scan result + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX: Ext scan event + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX: Ext scan hot list + * AP found + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX: Ext scan set + * bssid hotlist + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX: Ext scan reset + * bssid hotlist + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX: Ext scan + * significant change + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX: Ext scan + * set significant change + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX: Ext scan + * reset significant change + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX: Set stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX: Get stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX: Clear stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX: Radio stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX: Iface stats + * @QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX: Peer info stats + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX: Ext tdls state change + * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX: ACS command + * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX: Pass Roam and Auth info + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX: hotlist ap lost + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX: + * pno network found index + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX: + * passpoint match found index + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX: + * set ssid hotlist index + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX: + * reset ssid hotlist index + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX: + * hotlist ssid found index + * @QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX: + * hotlist ssid lost index + * @QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX + * dcc stats event index + * @QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX: vendor scan index + * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX: + * vendor scan complete event index + */ + +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 */ + + QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX, + 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, + 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 /* FEATURE_WLAN_EXTSCAN */ + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX, +#ifdef WLAN_FEATURE_MEMDUMP + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX, +#endif /* WLAN_FEATURE_MEMDUMP */ + /* OCB events */ + QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX, + QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX, + QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX, +}; + +/** + * enum qca_wlan_vendor_attr_tdls_enable - TDLS enable attribute + * + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR: An array of 6 x Unsigned 8-bit + * value + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL: Signed 32-bit value, but lets + * keep as unsigned for now + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS: operating class + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS: Enable max latency in ms + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS: Enable min bandwidth + * in KBPS + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX: Max value + */ +enum qca_wlan_vendor_attr_tdls_enable { + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR, + 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, + 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: tdls disable attribute + * + * @QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR: An array of 6 x Unsigned + * 8-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX: Max value + */ +enum qca_wlan_vendor_attr_tdls_disable { + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR, + 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 - tdls get status attribute + * + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR: An array of 6 x Unsigned + * 8-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE: get status state, + * unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON: get status reason + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL: get status channel, + * unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS: get operating + * class, unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX: Max value + */ +enum qca_wlan_vendor_attr_tdls_get_status { + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR, + 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, + 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 - tdls state attribute + * + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_INVALID: Initial invalid value + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR: An array of 6 x Unsigned + * 8-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE: TDLS new state, + * unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON: TDLS state reason + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL: TDLS state channel, + * unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS: TDLS state + * operating class, unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX: Max value + */ +enum qca_wlan_vendor_attr_tdls_state { + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR, + 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, + 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 - wlan vendor attribute + * + * @QCA_WLAN_VENDOR_ATTR_INVALID: Initial invalid value + * @QCA_WLAN_VENDOR_ATTR_DFS: DFS attribute which is used by + * QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY + * @QCA_WLAN_VENDOR_ATTR_NAN: NAN attribute which is used by + * QCA_NL80211_VENDOR_SUBCMD_NAN + * @QCA_WLAN_VENDOR_ATTR_STATS_EXT: Ext stats attribute which is used by + * QCA_NL80211_VENDOR_SUBCMD_STATS_EXT + * @QCA_WLAN_VENDOR_ATTR_IFINDEX: After IFINDEX + * @QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS: Supported Features + * @QCA_WLAN_VENDOR_ATTR_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_MAX: Max value + */ +enum qca_wlan_vendor_attr { + QCA_WLAN_VENDOR_ATTR_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DFS = 1, + QCA_WLAN_VENDOR_ATTR_NAN = 2, + QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, + QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, + QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7, + QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA = 9, + QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, + QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11, + /* 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 - ext scan config params + * + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_INVALID: Invalid initial + * value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID: + * 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_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND: + * NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS sub command. + * It is unsigned 32-bit value. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS: + * Unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL: + * 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_DWELL_TIME: Unsigned 32-bit value; + * dwell time in ms + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE: Unsigned 8-bit value: + * 0: active; 1: passive; N/A for DFS + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS: Unsigned 8-bit value + * channel class + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX: Unsigned 8-bit value + * bucket index, 0 based + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND: Unsigned 8-bit value; band + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD: Unsigned 32-bit value; + * desired period, in ms + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS: Unsigned 8-bit + * value; report events semantics + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS: Unsigned 32-bit + * value. Followed by a nested array of EXTSCAN_CHANNEL_SPEC_* attributes. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC: + * 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_SCAN_CMD_PARAMS_BASE_PERIOD: Unsigned 32-bit + * value; base timer period in ms + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN: 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_REPORT_THRESHOLD_PERCENT: + * Unsigned 8-bit value; in %, when scan buffer is this much full, + * wake up APPS. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS: 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_BUCKET_SPEC: 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_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH: + * Unsigned 8-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX: + * Unsigned 32-bit value; maximum number of results to be returned + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID: An array of + * 6 x Unsigned 8-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: Signed 32-bit + * value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL: Signed 32-bit + * value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP: 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_AP_THRESHOLD_PARAM: 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_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE: + * Unsigned 32bit value; number of samples for averaging RSSI + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE: + * Unsigned 32bit value; number of samples to confirm AP loss + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING: + * Unsigned 32bit value; number of APs breaching threshold. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP: + * 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_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE: + * Unsigned 32bit value; number of samples to confirm AP loss. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD: + * 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_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: + * Unsigned 8-bit value; in number of scans, wake up AP after these + * many scans. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE: + * Unsigned 32bit value; number of samples to confirm SSID loss + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID: + * 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_THRESHOLD_PARAM: + * 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_SSID: + * An array of 33 x Unsigned 8-bit value; NULL terminated SSID + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND: + * Signed 32-bit value; band + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW: + * Signed 32-bit value; low rssi + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH: + * Signed 32-bit value; high rssi + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS: + * Unsigned 32-bit value; a bitmask w/additional extscan config flag. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX: Max value + */ +enum qca_wlan_vendor_attr_extscan_config_params { + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS, + + 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 - vendor attribute ext scan results + * + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID: 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_STATUS: Unsigned 32-bit value used to + * indicate the status response from firmware/driver for the vendor + * sub-command + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS: EXTSCAN Valid Channels + * attributes. Unsigned 32bit value followed by a nested array of CHANNELS + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS: An array of NUM_CHANNELS x + * Unsigned 32bit value integers representing channel numbers. + * @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: + * Unsigned 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_APS: + * 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: + * Unsigned 32bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE: Unsigned 32-bit + * value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST: An array of + * NUM_RESULTS_AVAILABLE x QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_* + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP: Unsigned + * 64-bit value age of sample at the time of retrieval + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID: 33 x unsigned 8-bit + * value; NULL terminated SSID + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID: An array of 6 x + * Unsigned 8-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL: Unsigned 32-bit + * value; channel frequency in MHz + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI: Signed 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 32-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 16-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH: + * Unsigned 32-bit value; size of the IE DATA blob + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA: + * 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_MORE_DATA: + * Unsigned 8-bit value; set by driver to indicate more scan results are + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE: Unsigned 8-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS: Unsigned 32-bit + * value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID: + * An array of 6 x Unsigned 8-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: + * Unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST: + * 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_CACHED_RESULTS_LIST: + * An array of NUM_RESULTS_AVAILABLE x + * QCA_NL80211_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_* + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID: + * Unsigned 32-bit value; a unique identifier for the scan unit + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS: + * Unsigned 32-bit value; a bitmask w/additional information about scan + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES: + * Unsigned 32-bit value; number of found network matches + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST: + * 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_ID: + * Unsigned 32-bit value; network block id for the matched network + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN: + * Unsigned 32-bit value; ANQP length + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP: + * 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_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS: + * Unsigned 32bit value; Max hotlist ssids. + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS: + * Unsigned 32bit value; Max number of epno networks + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID: + * Unsigned 32bit value; Max number of epno networks by ssid + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID: + * Unsigned 32bit value; Max number of whitelisted ssids + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX: Max value + */ +enum qca_wlan_vendor_attr_extscan_results { + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA, + 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. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE, + 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. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_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_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. + */ + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS, + /* 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_PNO_NETWORK_FOUND sub-command. + */ + /* Use QCA_WLAN_VENDOR_ATTR_EXTSCAN_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_NUM_RESULTS_AVAILABLE. + */ + + /* EXTSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND sub-command. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST, + 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. + */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP, + + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID, + 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 - vendor attribute set stats + * + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD: Size threshold + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING: + * Aggresive stats gathering + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX: Max value + */ +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 - vendor attribute get stats + * + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID: 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_MASK: Get config request mask + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK: Config response mask + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP: Config stop response + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX: Max value + */ +enum qca_wlan_vendor_attr_ll_stats_get { + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID, + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK, + 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 - vendor attribute clear stats + * + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK: Config request mask + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ: Config stop mask + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK: Config response mask + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP: Config stop response + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX: Max value + */ +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 - vendor attribute stats results + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are nested + * within the interface stats. + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could be nested + * within the interface stats. + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* are nested + * within the interface stats. + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* could be nested + * within the peer info stats. + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* could be + * nested within the channel stats. + * + * Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ could be nested + * within the radio stats. + * + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID: 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: Unsigned 32bit value + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE: Interface mode, e.g., STA, + * SOFTAP, IBSS, etc. Type = enum wifi_interface_mode + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR: Interface MAC address. + * An array of 6 Unsigned int8_t + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE: + * Type = enum wifi_connection_state, e.g., DISCONNECTED, AUTHENTICATING, + * etc. Valid for STA, CLI only + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING: + * 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_CAPABILITIES: Unsigned 32bit value. + * WIFI_CAPABILITY_XXX + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID: NULL terminated SSID. An + * array of 33 Unsigned 8bit values + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID: BSSID. An array of 6 + * Unsigned 8bit values + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR: Country string + * advertised by AP. An array of 3 Unsigned 8bit values + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR: Country string for + * this association. An array of 3 Unsigned 8bit values + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC: Type = enum wifi_traffic_ac e.g. + * V0, VI, BE and BK + * @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 value + * corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN: Unsigned int 32 + * value corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX: Unsigned int 32 + * value corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG: Unsigned int 32 + * value corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES: Unsigned int 32 + * value corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS: Unsigned int 32 + * value corresponding to respective AC + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE: Type = enum wifi_peer_type + * Peer type, e.g., STA, AP, P2P GO etc + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS: MAC addr corresponding + * to respective peer. An array of 6 Unsigned 8bit values + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES: Unsigned int 32bit + * value representing capabilities corresponding to respective peer. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES: Unsigned 32bit value. + * Number of rates + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE: Unsigned int 8bit value: + * 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS: Unsigned int 8bit value: + * 0:1x1, 1:2x2, 3:3x3, 4:4x4 + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW: Unsigned int 8bit value: + * 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX: 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_BIT_RATE: Unsigned 32bit value. + * Bit rate in units of 100Kbps + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU: 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_RX_MPDU: Unsigned int 32bit value. + * Number of received data pkts corresponding to the respective rate + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST: 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_RETRIES: Unsigned int 32bit value. + * Total number of data pkt retries for the respective rate + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT: Unsigned int 32bit value. + * Total number of short data pkt retries for the respective rate + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG: Unsigned int 32bit value. + * Total number of long data pkt retries for the respective rate + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID: Radio id + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME: Unsigned 32bit value. + * Total number of msecs the radio is awake accruing over time + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME: Unsigned 32bit value. + * Total number of msecs the radio is transmitting accruing over time + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME: Unsigned 32bit value. + * Total number of msecs the radio is in active receive 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 all scan 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 NAN 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 GSCAN 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 roam 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 PNO scan accruing over + * time. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20: 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_NUM_CHANNELS: Unsigned 32bit value. + * Number of channels + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH: + * Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80, etc. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ: + * Unsigned 32bit value. Primary 20MHz channel. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0: + * Unsigned 32bit value. Center frequency (MHz) first segment. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1: + * Unsigned 32bit value. Center frequency (MHz) second segment. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME: Unsigned int 32bit value + * representing total number of msecs the radio is awake on that channel + * accruing over time, corresponding to the respective channel. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_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_NUM_RADIOS: Number of radios + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO: Channel info + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO: Peer info + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO: Peer rate info + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO: WMM info + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA: 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_IFACE_AVERAGE_TSF_OFFSET: tsf offset + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED: leaky ap detected + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED: + * average number of frames leaked + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME: guard time + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX: Max value + */ + +enum qca_wlan_vendor_attr_ll_stats_results { + QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG, + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES, + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20, + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME, + 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, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED, + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED, + 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 - get supported feature + * + * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET: Unsigned 32bit value + * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX: Max value + */ +enum qca_wlan_vendor_attr_get_supported_features { + QCA_WLAN_VENDOR_ATTR_FEATURE_SET_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_FEATURE_SET = 1, + 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 - set scanning mac oui + * + * @QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI: An array of 3 x Unsigned 8-bit + * value + * @QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX: Max value + */ +enum qca_wlan_vendor_attr_set_scanning_mac_oui { + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI = 1, + 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_scan - Specifies vendor scan attributes + * + * @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan + * @QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES: Nested unsigned 32-bit attributes + * with frequencies to be scanned (in MHz) + * @QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS: Nested attribute with SSIDs to be scanned + * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported + * rates to be included + * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests + * at non CCK rate in 2GHz band + * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags + * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the + * driver for the specific scan request + * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan + * request decoded as in enum scan_status + * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation + * scan flag is set + * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with + * randomisation + */ +enum qca_wlan_vendor_attr_scan { + QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0, + QCA_WLAN_VENDOR_ATTR_SCAN_IE, + QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES, + QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS, + QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES, + QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE, + QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, + QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, + QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, + QCA_WLAN_VENDOR_ATTR_SCAN_MAC, + QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK, + QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SCAN_MAX = + QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1 +}; + +/** + * enum scan_status - Specifies the valid values the vendor scan attribute + * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take + * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with + * new scan results + * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between + */ +enum scan_status { + VENDOR_SCAN_STATUS_NEW_RESULTS, + VENDOR_SCAN_STATUS_ABORTED, + VENDOR_SCAN_STATUS_MAX, +}; + +/** + * enum qca_wlan_vendor_attr_get_concurrency_matrix - get concurrency matrix + * + * NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX sub command. + * + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX: + * Unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE: + * Unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET: Set results. An + * array of SET_SIZE x Unsigned 32bit values representing concurrency + * combinations + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX: Max value + */ +enum qca_wlan_vendor_attr_get_concurrency_matrix { + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX + = 1, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE = 2, + QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET = 3, + 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_vendor_attr_set_no_dfs_flag - vendor attribute set no dfs flag + * + * @QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG: Unsigned 32-bit value + * @QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX: Max value + */ +enum qca_wlan_vendor_attr_set_no_dfs_flag { + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG = 1, + 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 +}; + +/** + * enum qca_wlan_vendor_attr_wifi_config - wifi config + * + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_DYNAMIC_DTIM: dynamic DTIM + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_STATS_AVG_FACTOR: avg factor + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_GUARD_TIME: guard time + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_MAX: max value + */ +enum qca_wlan_vendor_attr_wifi_config { + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_DYNAMIC_DTIM = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_STATS_AVG_FACTOR = 2, + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_GUARD_TIME = 3, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_CONFIG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_epno_type - the type of request to the EPNO command + * @QCA_WLAN_EPNO: epno type request + * @QCA_WLAN_PNO: pno type request + */ +enum qca_wlan_epno_type { + QCA_WLAN_EPNO, + QCA_WLAN_PNO +}; + +/** + * enum qca_wlan_vendor_attr_pno_config_params - pno config params + * + * @QCA_WLAN_VENDOR_ATTR_PNO_INVALID - Invalid initial value + * + * NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST sub command. + * @QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM: + * Unsigned 32-bit value; pno passpoint number of networks + * @QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY: + * 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_NETWORK_PARAM_ID: + * Unsigned 32-bit value; network id + * @QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM: + * 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_ROAM_CNSRTM_ID: + * 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_PLMN: + * An array of 6 x Unsigned 8-bit value; mcc/mnc combination, 0s if + * unspecified. + * + * NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST sub command. + * @QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS: + * Unsigned 32-bit value; set pno number of networks + * @QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST: + * 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_NETWORK_SSID: + * An array of 33 x Unsigned 8-bit value; NULL terminated SSID + * @QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD: + * 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_FLAGS: + * Unsigned 8-bit value; WIFI_PNO_FLAG_XXX + * @QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT: + * Unsigned 8-bit value; auth bit field for matching WPA IE + * @QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_TYPE + * Unsigned 8-bit to indicate ePNO type; values from qca_wlan_epno_type + * @QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_PNO_MAX: max + */ +enum qca_wlan_vendor_attr_pno_config_params { + QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM = 1, + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY = 2, + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID = 3, + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM = 4, + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID = 5, + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN = 6, + + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS = 7, + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST = 8, + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID = 9, + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD = 10, + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS = 11, + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT = 12, + 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 - roaming config params + * + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD: roaming sub command + * @QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID: Request id + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: + * number of whitelist networks + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: + * Whitelist ssid list + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: + * white list ssid + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD: + * 'a' band boost threshold + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD: + * 'a' band penalty threshold + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR: + * 'a' band boost factor + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR: + * 'a' band penalty factor + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST: + * 'a' band max boost + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS: + * lazy roam histeresys + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER: + * alert roam rssi trigger + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: + * set lazy roam enable + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS: + * set bssid preference + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID: + * set lazy roam number of bssid + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID: + * set lazy roam bssid + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER: + * set lazy roam rssi modifier + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS: + * set bssid params + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID: + * set bssid params num bssid + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID: + * set bssid params bssid + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST: After last + * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX: Max + */ +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, + + 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, + + 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, + + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE = 13, + + 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, + + 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, +}; + +/** + * enum qca_wlan_vendor_attr_roam_subcmd - roam sub commands + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST: ssid white list + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS: roam params + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM: set lazy roam + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS: set bssid prefs + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PARAMS: set bssid params + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID: set blacklist bssid + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX: subcmd max + */ +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, +}; + +/** + * enum qca_wlan_vendor_attr_get_wifi_info - wifi driver information + * + * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION: get host driver version + * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION: ger firmware version + * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX: subcmd max + */ +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, +}; + +/** + * 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. + * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports + * simultaneous off-channel operations. + */ +enum qca_wlan_vendor_features { + QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, + QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, + QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, + /* 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 */ + +/** + * 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)), +}; + +/* 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) + +#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC) +#define HDD_MAX_AVOID_FREQ_RANGES 4 +/** + * typedef struct sHddAvoidFreqRange - avoid frequency range + * + * @startFreq: Start frequency range + * @endFreq: End frequency range + */ +typedef struct sHddAvoidFreqRange { + u32 startFreq; + u32 endFreq; +} tHddAvoidFreqRange; + +/** + * typedef struct sHddAvoidFreqList - avoid frequency list + * + * @avoidFreqRangeCount: Avoid frequency range count + * @avoidFreqRange: Avoid frequency list + */ +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_PRIMARY_CHANNEL: ACS selected primary channel + * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL: ACS selected secondary channel + * @QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE: hw_mode for ACS + * @QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED: indicate if HT capability is enabled + * @QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED: indicate HT capability + */ +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, + QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST, + /* 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: 11b mode + * @QCA_ACS_MODE_IEEE80211G: 11g mode + * @QCA_ACS_MODE_IEEE80211A: 11a mode + * @QCA_ACS_MODE_IEEE80211AD: 11ad mode + */ +enum qca_wlan_vendor_acs_hw_mode { + QCA_ACS_MODE_IEEE80211B, + QCA_ACS_MODE_IEEE80211G, + QCA_ACS_MODE_IEEE80211A, + QCA_ACS_MODE_IEEE80211AD, + QCA_ACS_MODE_IEEE80211ANY, +}; + +/** + * enum qca_wlan_vendor_config: wifi config attr + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID: invalid config + * @QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM: modulated dtim + * @QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR: stats avg. factor + * @QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME: guard time + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LAST: last config + * @QCA_WLAN_VENDOR_ATTR_CONFIG_MAX: max config + */ +enum qca_wlan_vendor_config { + QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM, + QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, + QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_wifi_logger_start - Enum for wifi logger starting + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID: Invalid attribute + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID: Ring ID + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL: Verbose level + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS: Flag + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST: Last value + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX: Max value + */ +enum qca_wlan_vendor_attr_wifi_logger_start { + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL = 2, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS = 3, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST - 1, +}; + +/* + * enum qca_wlan_vendor_attr_wifi_logger_get_ring_data - Get ring data + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_INVALID: Invalid attribute + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID: Ring ID + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST: Last value + * @QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX: Max value + */ +enum qca_wlan_vendor_attr_wifi_logger_get_ring_data { + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_AFTER_LAST - 1, +}; + +#ifdef WLAN_FEATURE_OFFLOAD_PACKETS +/** + * enum wlan_offloaded_packets_control - control commands + * @WLAN_START_OFFLOADED_PACKETS: start offloaded packets + * @WLAN_STOP_OFFLOADED_PACKETS: stop offloaded packets + * + */ +enum wlan_offloaded_packets_control { + WLAN_START_OFFLOADED_PACKETS = 1, + WLAN_STOP_OFFLOADED_PACKETS = 2 +}; + +/** + * enum qca_wlan_vendor_attr_offloaded_packets - offloaded packets + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID: invalid + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL: control + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID: request id + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA: ip packet data + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR: src mac address + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR: destination mac address + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD: period in milli seconds + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX: max + */ +enum qca_wlan_vendor_attr_offloaded_packets { + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, + + /* Packet in hex format */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX = + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1, +}; +#endif + +/** + * enum qca_wlan_rssi_monitoring_control - rssi control commands + * @QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID: invalid + * @QCA_WLAN_RSSI_MONITORING_START: rssi monitoring start + * @QCA_WLAN_RSSI_MONITORING_STOP: rssi monitoring stop + */ +enum qca_wlan_rssi_monitoring_control { + QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0, + QCA_WLAN_RSSI_MONITORING_START, + QCA_WLAN_RSSI_MONITORING_STOP, +}; + +/** + * enum qca_wlan_vendor_attr_rssi_monitoring - rssi monitoring + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID: Invalid + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL: control + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI: max rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI: min rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID: current bssid + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI: current rssi + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX: max + */ +enum qca_wlan_vendor_attr_rssi_monitoring { + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, + + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, + + /* attributes to be used/received in callback */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX = + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1, +}; + +/** + * enum qca_vendor_attr_get_preferred_freq_list - get preferred channel list + * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID: invalid value + * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE: interface type + * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST: preferred frequency list + * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX: max + */ +enum qca_vendor_attr_get_preferred_freq_list { + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID, + /* A 32-unsigned value; the interface type/mode for which the preferred + * frequency list is requested (see enum qca_iface_type for possible + * values); used in both south- and north-bound. + */ + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE, + /* An array of 32-unsigned values; values are frequency (MHz); used + * in north-bound only. + */ + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX = + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST - 1 +}; + +/** + * enum qca_vendor_attr_probable_oper_channel - channel hint + * @QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_INVALID: invalid value + * @QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE: interface type + * @QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ: frequency hint value + * @QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST: last + * @QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX: max + */ +enum qca_vendor_attr_probable_oper_channel { + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_INVALID, + /* 32-bit unsigned value; indicates the connection/iface type likely to + * come on this channel (see enum qca_iface_type). + */ + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE, + /* 32-bit unsigned value; the frequency (MHz) of the probable channel */ + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX = + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST - 1 +}; + +/** + * enum drv_dbs_capability - DBS capability + * @DRV_DBS_CAPABILITY_DISABLED: DBS disabled + * @DRV_DBS_CAPABILITY_1X1: 1x1 + * @DRV_DBS_CAPABILITY_2X2: 2x2 + */ +enum drv_dbs_capability { + DRV_DBS_CAPABILITY_DISABLED, /* not supported or disabled */ + DRV_DBS_CAPABILITY_1X1, + DRV_DBS_CAPABILITY_2X2, +}; + +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 +CDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo); + +CDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t * + pAdapter, + tCsrRoamInfo * + pRoamInfo, + bool preauth_status); + +CDF_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, uint8_t key_index, + const uint8_t *mac_addr, const uint8_t *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)) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request); + +int wlan_hdd_cfg80211_init(struct device *dev, + struct wiphy *wiphy, struct hdd_config *pCfg); + +void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *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)) +void hdd_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); +#else +int hdd_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); +#endif + +extern void hdd_conn_set_connection_state(hdd_adapter_t *pAdapter, + eConnectionState connState); +CDF_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_replay_counter_callback(void + *callbackContext, + tpSirGtkOffloadGetInfoRspParams + pGtkOffloadGetInfoRsp); +#endif +void *wlan_hdd_change_country_code_cb(void *pAdapter); +void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel); + +uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length, + uint8_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)) +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *mac); +#else +int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, + uint8_t *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 + +#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 uint16_t 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_update_bss(struct wiphy *wiphy, + hdd_adapter_t *pAdapter, + uint32_t scan_timestamp); + +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); +#endif + +int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *adapter); + +#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 +int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter); + +enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type( + enum nl80211_iftype type); +#endif + diff --git a/core/hdd/src/wlan_hdd_conc_ut.c b/core/hdd/src/wlan_hdd_conc_ut.c new file mode 100644 index 000000000000..8ed71dd2338f --- /dev/null +++ b/core/hdd/src/wlan_hdd_conc_ut.c @@ -0,0 +1,865 @@ +/* + * 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. + */ + +/* Include files */ + +#include +#include +#include +#include +#include +#include "wlan_hdd_trace.h" +#include "cds_concurrency.h" +#include "wlan_hdd_conc_ut.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cds_utils.h" +#include "cds_reg_service.h" +#include "wma_types.h" +#include "wma.h" +#include "wma_api.h" + +#define NUMBER_OF_SCENARIO 300 +#define MAX_ALLOWED_CHAR_IN_REPORT 50 + +/** + * struct report_t: Data structure to fill report + * + * @title: title of the concurrency case scenario + * @first_persona: device type of first persona + * @second_persona: device type of second persona + * @third_persona: device type of third persona + * @dbs_value: string to mention whether dbs enable or disable + * @system_conf: string to mention what is system's configuration + * @status: status field + * @result_code: string to mention whether test case passed or failed + * @reason: reason why test case failed + * @pcl: preferred channel list + * + * This structure will be used by unit test framework to fill + * report after running various concurrency scenarios. + */ +struct report_t { + char title[2 * MAX_ALLOWED_CHAR_IN_REPORT]; + char first_persona[MAX_ALLOWED_CHAR_IN_REPORT]; + char second_persona[MAX_ALLOWED_CHAR_IN_REPORT]; + char third_persona[MAX_ALLOWED_CHAR_IN_REPORT]; + char dbs_value[MAX_ALLOWED_CHAR_IN_REPORT]; + char system_conf[MAX_ALLOWED_CHAR_IN_REPORT]; + bool status; + char result_code[MAX_ALLOWED_CHAR_IN_REPORT]; + char reason[MAX_ALLOWED_CHAR_IN_REPORT]; + char pcl[2 * MAX_NUM_CHAN]; +}; + +static struct report_t report[NUMBER_OF_SCENARIO]; +static uint32_t report_idx; + +static uint8_t wlan_hdd_valid_type_of_persona(uint32_t sub_type) +{ + switch (sub_type) { + case CDS_STA_MODE: + return WMI_VDEV_TYPE_STA; + case CDS_IBSS_MODE: + return WMI_VDEV_TYPE_IBSS; + case CDS_SAP_MODE: + case CDS_P2P_CLIENT_MODE: + case CDS_P2P_GO_MODE: + return WMI_VDEV_TYPE_AP; + default: + return WMI_VDEV_TYPE_STA; + } +} + +static const char *system_config_to_string(uint8_t idx) +{ + switch (idx) { + CASE_RETURN_STRING(CDS_THROUGHPUT); + CASE_RETURN_STRING(CDS_POWERSAVE); + CASE_RETURN_STRING(CDS_LATENCY); + default: + return "Unknown"; + } + +} + +static const char *device_mode_to_string(uint8_t idx) +{ + switch (idx) { + CASE_RETURN_STRING(CDS_STA_MODE); + CASE_RETURN_STRING(CDS_SAP_MODE); + CASE_RETURN_STRING(CDS_P2P_CLIENT_MODE); + CASE_RETURN_STRING(CDS_P2P_GO_MODE); + CASE_RETURN_STRING(CDS_IBSS_MODE); + default: + return "none"; + } +} + +static const char *pcl_type_to_string(uint8_t idx) +{ + switch (idx) { + CASE_RETURN_STRING(CDS_NONE); + CASE_RETURN_STRING(CDS_24G); + CASE_RETURN_STRING(CDS_5G); + CASE_RETURN_STRING(CDS_SCC_CH); + CASE_RETURN_STRING(CDS_MCC_CH); + CASE_RETURN_STRING(CDS_SCC_CH_24G); + CASE_RETURN_STRING(CDS_SCC_CH_5G); + CASE_RETURN_STRING(CDS_24G_SCC_CH); + CASE_RETURN_STRING(CDS_5G_SCC_CH); + CASE_RETURN_STRING(CDS_SCC_ON_5_SCC_ON_24_24G); + CASE_RETURN_STRING(CDS_SCC_ON_5_SCC_ON_24_5G); + CASE_RETURN_STRING(CDS_SCC_ON_24_SCC_ON_5_24G); + CASE_RETURN_STRING(CDS_SCC_ON_24_SCC_ON_5_5G); + CASE_RETURN_STRING(CDS_SCC_ON_5_SCC_ON_24); + CASE_RETURN_STRING(CDS_SCC_ON_24_SCC_ON_5); + CASE_RETURN_STRING(CDS_MCC_CH_24G); + CASE_RETURN_STRING(CDS_MCC_CH_5G); + CASE_RETURN_STRING(CDS_24G_MCC_CH); + CASE_RETURN_STRING(CDS_5G_MCC_CH); + default: + return "Unknown"; + } +} + +void clean_report(hdd_context_t *hdd_ctx) +{ + uint32_t idx = 0; + while (idx < NUMBER_OF_SCENARIO) { + cdf_mem_zero(&report[idx], sizeof(struct report_t)); + idx++; + } + report_idx = 0; +} + +void print_report(hdd_context_t *hdd_ctx) +{ + uint32_t idx = 0; + pr_info("+----------Report start -----------+\n"); + while (idx < report_idx) { + pr_info("Idx:[%d]\nTitle:%s\nResult:[%s]\n\t1st_person[%s]\n\t2nd_persona[%s]\n\t3rd_persona[%s]\n\tDBS[%s]\n\tsystem_config[%s]\n\treason[%s]\n\tpcl[%s]\n", + idx, + report[idx].title, report[idx].result_code, + report[idx].first_persona, report[idx].second_persona, + report[idx].third_persona, report[idx].dbs_value, + report[idx].system_conf, report[idx].reason, + report[idx].pcl); + idx++; + } + pr_info("+----------Report end -----------+\n"); +} + +void fill_report(hdd_context_t *hdd_ctx, char *title, + uint32_t first_persona, uint32_t second_persona, uint32_t third_persona, + uint32_t chnl_1st_conn, uint32_t chnl_2nd_conn, uint32_t chnl_3rd_conn, + bool status, enum cds_pcl_type pcl_type, char *reason, uint8_t *pcl) +{ + int i; + char buf[4] = {0}; + + if (report_idx >= NUMBER_OF_SCENARIO) + return; + snprintf(report[report_idx].title, + 2 * MAX_ALLOWED_CHAR_IN_REPORT, "pcl for[%s] pcl_type[%s]", + title, pcl_type_to_string(pcl_type)); + if (chnl_1st_conn == 0) + snprintf(report[report_idx].first_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + device_mode_to_string(first_persona)); + else + snprintf(report[report_idx].first_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + "%s-chnl{%d}", + device_mode_to_string(first_persona), chnl_1st_conn); + if (chnl_2nd_conn == 0) + snprintf(report[report_idx].second_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + device_mode_to_string(second_persona)); + else + snprintf(report[report_idx].second_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + "%s-chnl{%d}", + device_mode_to_string(second_persona), chnl_2nd_conn); + if (chnl_3rd_conn == 0) + snprintf(report[report_idx].third_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + device_mode_to_string(third_persona)); + else + snprintf(report[report_idx].third_persona, + MAX_ALLOWED_CHAR_IN_REPORT, + "%s-chnl{%d}", + device_mode_to_string(third_persona), chnl_3rd_conn); + + report[report_idx].status = status; + snprintf(report[report_idx].dbs_value, + MAX_ALLOWED_CHAR_IN_REPORT, + wma_is_hw_dbs_capable() ? "enable" : "disable"); + snprintf(report[report_idx].system_conf, + MAX_ALLOWED_CHAR_IN_REPORT, + system_config_to_string(hdd_ctx->config->conc_system_pref)); + snprintf(report[report_idx].result_code, + MAX_ALLOWED_CHAR_IN_REPORT, + status ? "PASS" : "FAIL"); + snprintf(report[report_idx].reason, + MAX_ALLOWED_CHAR_IN_REPORT, + reason); + if (pcl) { + cdf_mem_zero(report[report_idx].pcl, + sizeof(report[report_idx].pcl)); + for (i = 0; i < MAX_NUM_CHAN; i++) { + if (pcl[i] == 0) + break; + cdf_mem_zero(buf, sizeof(buf)); + snprintf(buf, sizeof(buf), "%d ", pcl[i]); + strlcat(report[report_idx].pcl, buf, + sizeof(report[report_idx].pcl)); + strlcat(report[report_idx].pcl, ", ", + sizeof(report[report_idx].pcl)); + } + } + report_idx++; +} + +static bool wlan_hdd_validate_pcl(hdd_context_t *hdd_ctx, + enum cds_pcl_type pcl_type, uint8_t *pcl, uint32_t pcl_len, + uint8_t first_connection_chnl, uint8_t second_connection_chnl, + char *reason, uint32_t reason_length) +{ + bool status = true; + uint32_t first_idx = 0; + + if ((pcl_type != CDS_NONE) && (pcl_len == 0)) { + snprintf(reason, reason_length, "no of channels = 0"); + return false; + } + + switch (pcl_type) { + case CDS_NONE: + if (pcl_len != 0) { + snprintf(reason, reason_length, "no of channels>0"); + return false; + } + break; + case CDS_5G: + for (first_idx = 0; first_idx < pcl_len; first_idx++) { + if (!CDS_IS_CHANNEL_5GHZ(pcl[first_idx])) { + snprintf(reason, reason_length, + "2G channel found"); + return false; + } + } + break; + case CDS_24G: + for (first_idx = 0; first_idx < pcl_len; first_idx++) { + if (!CDS_IS_CHANNEL_24GHZ(pcl[first_idx])) { + snprintf(reason, reason_length, + "5G channel found"); + return false; + } + } + break; + case CDS_SCC_CH: + if (second_connection_chnl > 0 && + (first_connection_chnl != second_connection_chnl)) { + snprintf(reason, reason_length, + "invalid connections"); + return false; + } + if (pcl[0] != first_connection_chnl) { + snprintf(reason, reason_length, + "No SCC found"); + return false; + } + break; + case CDS_MCC_CH: + if ((pcl[0] != first_connection_chnl) && + ((second_connection_chnl > 0) && + (pcl[0] != second_connection_chnl))) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if ((second_connection_chnl > 0) && + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + break; + case CDS_SCC_CH_24G: + if (second_connection_chnl > 0 && + (first_connection_chnl != second_connection_chnl)) { + snprintf(reason, reason_length, + "invalid connections"); + return false; + } + if (pcl[0] != first_connection_chnl) { + snprintf(reason, reason_length, + "No SCC found"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 2.4Ghz chnl"); + return false; + } + break; + case CDS_SCC_CH_5G: + if (second_connection_chnl > 0 && + (first_connection_chnl != second_connection_chnl)) { + snprintf(reason, reason_length, + "invalid connections"); + return false; + } + if (pcl[0] != first_connection_chnl) { + snprintf(reason, reason_length, + "No SCC found"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 5Ghz chnl"); + return false; + } + break; + case CDS_24G_SCC_CH: + if (!CDS_IS_CHANNEL_24GHZ(pcl[0])) { + snprintf(reason, reason_length, + "No 2.4Ghz chnl"); + return false; + } + if (second_connection_chnl > 0 && + (first_connection_chnl != second_connection_chnl)) { + snprintf(reason, reason_length, + "invalid connections"); + return false; + } + if (pcl[pcl_len-1] != first_connection_chnl) { + snprintf(reason, reason_length, + "No SCC found"); + return false; + } + break; + case CDS_5G_SCC_CH: + if (!CDS_IS_CHANNEL_5GHZ(pcl[0])) { + snprintf(reason, reason_length, + "No 5Ghz chnl"); + return false; + } + if (second_connection_chnl > 0 && + (first_connection_chnl != second_connection_chnl)) { + snprintf(reason, reason_length, + "invalid connections"); + return false; + } + if (pcl[pcl_len-1] != first_connection_chnl) { + snprintf(reason, reason_length, + "No SCC found"); + return false; + } + break; + case CDS_MCC_CH_24G: + if ((pcl[0] != first_connection_chnl) && + ((second_connection_chnl > 0) && + (pcl[0] != second_connection_chnl))) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if ((second_connection_chnl > 0) && + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 24Ghz chnl"); + return false; + } + break; + case CDS_MCC_CH_5G: + if ((pcl[0] != first_connection_chnl) && + ((second_connection_chnl > 0) && + (pcl[0] != second_connection_chnl))) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if ((second_connection_chnl > 0) && + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 5Ghz chnl"); + return false; + } + break; + case CDS_24G_MCC_CH: + if (!CDS_IS_CHANNEL_24GHZ(pcl[0])) { + snprintf(reason, reason_length, + "No 24Ghz chnl"); + return false; + } + if ((pcl[pcl_len-1] != first_connection_chnl) && + ((second_connection_chnl > 0) && + (pcl[pcl_len-1] != second_connection_chnl))) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if ((second_connection_chnl > 0) && + (pcl[pcl_len-2] != first_connection_chnl && + pcl[pcl_len-2] != second_connection_chnl)) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + break; + case CDS_5G_MCC_CH: + if (!CDS_IS_CHANNEL_5GHZ(pcl[0])) { + snprintf(reason, reason_length, + "No 5Ghz chnl"); + return false; + } + if ((pcl[pcl_len-1] != first_connection_chnl) && + ((second_connection_chnl > 0) && + (pcl[pcl_len-1] != second_connection_chnl))) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + if ((second_connection_chnl > 0) && + (pcl[pcl_len-2] != first_connection_chnl && + pcl[pcl_len-2] != second_connection_chnl)) { + snprintf(reason, reason_length, + "MCC invalid"); + return false; + } + break; + case CDS_SCC_ON_5_SCC_ON_24_24G: + if (!CDS_IS_CHANNEL_5GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 24Ghz chnls"); + return false; + } + break; + case CDS_SCC_ON_5_SCC_ON_24_5G: + if (!CDS_IS_CHANNEL_5GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 5Ghz chnls"); + return false; + } + break; + case CDS_SCC_ON_24_SCC_ON_5_24G: + if (!CDS_IS_CHANNEL_24GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 24Ghz chnls"); + return false; + } + break; + case CDS_SCC_ON_24_SCC_ON_5_5G: + if (!CDS_IS_CHANNEL_24GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[pcl_len-1])) { + snprintf(reason, reason_length, + "No 5Ghz chnls"); + return false; + } + break; + case CDS_SCC_ON_5_SCC_ON_24: + if (!CDS_IS_CHANNEL_5GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_24GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (pcl_len != 2) { + snprintf(reason, reason_length, + "more than 2 chnls"); + return false; + } + break; + case CDS_SCC_ON_24_SCC_ON_5: + if (!CDS_IS_CHANNEL_24GHZ(pcl[0]) || + (pcl[0] != first_connection_chnl && + pcl[0] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 24Ghz chnl/scc"); + return false; + } + if (!CDS_IS_CHANNEL_5GHZ(pcl[1]) || + (pcl[1] != first_connection_chnl && + pcl[1] != second_connection_chnl)) { + snprintf(reason, reason_length, + "No 5Ghz chnl/scc"); + return false; + } + if (pcl_len != 2) { + snprintf(reason, reason_length, + "more than 2 chnls"); + return false; + } + break; + default: + snprintf(reason, reason_length, + "Unknown option"); + status = false; + } + if (status == true) { + snprintf(reason, reason_length, + "success"); + } + return status; +} + +static void wlan_hdd_map_subtypes_hdd_wma(enum cds_con_mode *dst, + enum cds_con_mode *src) +{ + /* + * wma defined sap subtype as 0 + * Rest of the mappings are same + * In future, if mapping gets changed then re-map it here + */ + if (*src == CDS_SAP_MODE) + *dst = 0; + else + *dst = *src; +} + +void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) +{ + enum cds_con_mode sub_type; + enum cds_conc_priority_mode system_pref = + hdd_ctx->config->conc_system_pref; + uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint32_t pcl_len = 0; + bool status = false; + enum cds_pcl_type pcl_type; + char reason[20] = {0}; + CDF_STATUS ret; + + /* flush the entire table first */ + ret = cds_init_policy_mgr(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + hdd_err("Policy manager initialization failed"); + return; + } + + for (sub_type = 0; sub_type < CDS_MAX_NUM_OF_MODE; sub_type++) { + /* validate one connection is created or no */ + if (cds_get_connection_count(hdd_ctx) != 0) { + hddLog(LOGE, + FL("Test failed - No. of connection is not 0")); + return; + } + cdf_mem_zero(pcl, sizeof(pcl)); + pcl_len = 0; + pcl_type = get_pcl_from_first_conn_table(sub_type, system_pref); + + /* check PCL value for second connection is correct or no */ + cds_get_pcl(hdd_ctx, sub_type, pcl, &pcl_len); + status = wlan_hdd_validate_pcl(hdd_ctx, + pcl_type, pcl, pcl_len, 0, 0, + reason, sizeof(reason)); + if ((pcl_type == CDS_MAX_PCL_TYPE) && (pcl[0] == 0)) + continue; + + fill_report(hdd_ctx, "1 connection", sub_type, + CDS_MAX_NUM_OF_MODE, + CDS_MAX_NUM_OF_MODE, + 0, 0, 0, + status, pcl_type, reason, pcl); + } +} + +void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, enum cds_chain_mode first_chain_mask) +{ + uint8_t vdevid = 0, tx_stream = 2, rx_stream = 2; + uint8_t type = WMI_VDEV_TYPE_STA, channel_id = first_chnl, mac_id = 1; + uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint32_t pcl_len = 0; + enum cds_chain_mode chain_mask = first_chain_mask; + enum cds_con_mode sub_type, next_sub_type, dummy_type; + enum cds_conc_priority_mode system_pref = + hdd_ctx->config->conc_system_pref; + enum cds_pcl_type pcl_type; + enum cds_one_connection_mode second_index; + char reason[20] = {0}; + bool status = false; + CDF_STATUS ret; + + for (sub_type = CDS_STA_MODE; + sub_type < CDS_MAX_NUM_OF_MODE; sub_type++) { + type = wlan_hdd_valid_type_of_persona(sub_type); + + /* flush the entire table first */ + ret = cds_init_policy_mgr(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + hdd_err("Policy manager initialization failed"); + return; + } + + /* sub_type mapping between HDD and WMA are different */ + wlan_hdd_map_subtypes_hdd_wma(&dummy_type, &sub_type); + /* add first connection as STA */ + cds_incr_connection_count_utfw(hdd_ctx, vdevid, tx_stream, + rx_stream, chain_mask, type, dummy_type, + channel_id, mac_id); + /* validate one connection is created or no */ + if (cds_get_connection_count(hdd_ctx) != 1) { + hddLog(LOGE, + FL("Test failed - No. of connection is not 1")); + return; + } + next_sub_type = CDS_STA_MODE; + while (next_sub_type < CDS_MAX_NUM_OF_MODE) { + /* get the PCL value & check the channels accordingly */ + second_index = + cds_get_second_connection_pcl_table_index( + hdd_ctx); + if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { + /* not valid combination*/ + hddLog(LOGE, FL("couldn't find index for 2nd connection pcl table")); + next_sub_type++; + continue; + } + cdf_mem_zero(pcl, sizeof(pcl)); + pcl_len = 0; + pcl_type = get_pcl_from_second_conn_table(second_index, + next_sub_type, system_pref, + wma_is_hw_dbs_capable()); + /* check PCL for second connection is correct or no */ + cds_get_pcl(hdd_ctx, next_sub_type, pcl, &pcl_len); + status = wlan_hdd_validate_pcl(hdd_ctx, + pcl_type, pcl, pcl_len, channel_id, 0, + reason, sizeof(reason)); + if ((pcl_type == CDS_MAX_PCL_TYPE) && (pcl[0] == 0)) { + next_sub_type++; + continue; + } + fill_report(hdd_ctx, "2 connections", sub_type, + next_sub_type, + CDS_MAX_NUM_OF_MODE, first_chnl, + 0, 0, status, pcl_type, reason, pcl); + next_sub_type++; + } + } +} + +void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, + uint8_t first_chnl, uint8_t second_chnl, + enum cds_chain_mode chain_mask, uint8_t use_same_mac) +{ + uint8_t vdevid_1 = 0, tx_stream_1 = 2, rx_stream_1 = 2; + uint8_t vdevid_2 = 1, tx_stream_2 = 2, rx_stream_2 = 2; + uint8_t channel_id_1 = first_chnl, channel_id_2 = second_chnl; + uint8_t mac_id_1, mac_id_2; + uint8_t type_1 = WMI_VDEV_TYPE_STA, type_2 = WMI_VDEV_TYPE_STA; + uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint32_t pcl_len = 0; + enum cds_chain_mode chain_mask_1; + enum cds_chain_mode chain_mask_2; + enum cds_con_mode sub_type_1, sub_type_2, next_sub_type; + enum cds_con_mode dummy_type_1, dummy_type_2; + enum cds_conc_priority_mode system_pref = + hdd_ctx->config->conc_system_pref; + enum cds_pcl_type pcl_type; + enum cds_two_connection_mode third_index; + char reason[20] = {0}; + bool status = false; + CDF_STATUS ret; + + /* let's set the chain_mask, mac_ids*/ + if (chain_mask == CDS_TWO_TWO) { + mac_id_1 = 1; + mac_id_2 = 1; + chain_mask_1 = CDS_TWO_TWO; + chain_mask_2 = CDS_TWO_TWO; + } else if (use_same_mac == 1) { + mac_id_1 = 1; + mac_id_2 = 1; + chain_mask_1 = CDS_ONE_ONE; + chain_mask_2 = CDS_ONE_ONE; + } else { + mac_id_1 = 1; + mac_id_2 = 2; + chain_mask_1 = CDS_ONE_ONE; + chain_mask_2 = CDS_ONE_ONE; + } + + for (sub_type_1 = CDS_STA_MODE; + sub_type_1 < CDS_MAX_NUM_OF_MODE; sub_type_1++) { + + type_1 = wlan_hdd_valid_type_of_persona(sub_type_1); + /* flush the entire table first */ + ret = cds_init_policy_mgr(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + hdd_err("Policy manager initialization failed"); + return; + } + + /* sub_type mapping between HDD and WMA are different */ + wlan_hdd_map_subtypes_hdd_wma(&dummy_type_1, &sub_type_1); + /* add first connection as STA */ + cds_incr_connection_count_utfw(hdd_ctx, vdevid_1, + tx_stream_1, rx_stream_1, chain_mask_1, type_1, + dummy_type_1, channel_id_1, mac_id_1); + /* validate one connection is created or no */ + if (cds_get_connection_count(hdd_ctx) != 1) { + hddLog(LOGE, + FL("Test fail - No. of connection not 1")); + return; + } + for (sub_type_2 = CDS_STA_MODE; + sub_type_2 < CDS_MAX_NUM_OF_MODE; sub_type_2++) { + + type_2 = wlan_hdd_valid_type_of_persona(sub_type_2); + /* sub_type mapping between HDD and WMA are different */ + wlan_hdd_map_subtypes_hdd_wma(&dummy_type_2, + &sub_type_2); + cds_incr_connection_count_utfw(hdd_ctx, vdevid_2, + tx_stream_2, rx_stream_2, chain_mask_2, type_2, + dummy_type_2, channel_id_2, mac_id_2); + /* validate two connections are created or no */ + if (cds_get_connection_count(hdd_ctx) != 2) { + hddLog(LOGE, + FL("Test fail - No. connection not 2")); + return; + } + next_sub_type = CDS_STA_MODE; + while (next_sub_type < CDS_MAX_NUM_OF_MODE) { + third_index = + cds_get_third_connection_pcl_table_index( + hdd_ctx); + if (CDS_MAX_TWO_CONNECTION_MODE == + third_index) { + /* not valid combination */ + next_sub_type++; + continue; + } + cdf_mem_zero(pcl, sizeof(pcl)); + pcl_len = 0; + pcl_type = + get_pcl_from_third_conn_table( + third_index, next_sub_type, + system_pref, + wma_is_hw_dbs_capable()); + cds_get_pcl(hdd_ctx, next_sub_type, + pcl, &pcl_len); + status = wlan_hdd_validate_pcl(hdd_ctx, + pcl_type, pcl, pcl_len, + channel_id_1, channel_id_2, + reason, sizeof(reason)); + if ((pcl_type == CDS_MAX_PCL_TYPE) && + (pcl[0] == 0)) { + next_sub_type++; + continue; + } + fill_report(hdd_ctx, "3 connections", + sub_type_1, sub_type_2, + next_sub_type, first_chnl, + second_chnl, 0, status, + pcl_type, reason, pcl); + next_sub_type++; + } + /* remove entry to make a room for next iteration */ + cds_decr_connection_count(hdd_ctx, vdevid_2); + } + next_sub_type = CDS_STA_MODE; + } +} diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c new file mode 100644 index 000000000000..cf7747ee45fa --- /dev/null +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -0,0 +1,648 @@ +/* + * 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: wlan_hdd_debugfs.c + * + * This driver currently supports the following debugfs files: + * wlan_wcnss/wow_enable to enable/disable WoWL. + * wlan_wcnss/wow_pattern to configure WoWL patterns. + * wlan_wcnss/pattern_gen to configure periodic TX patterns. + */ + +#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() - wow_enable debugfs handler + * @file: debugfs file handle + * @buf: text being written to the debugfs + * @count: size of @buf + * @ppos: (unused) offset into the virtual file system + * + * Return: number of bytes processed + */ +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; + uint8_t wow_enable = 0; + uint8_t wow_mp = 0; + uint8_t wow_pbm = 0; + int ret; + + pAdapter = (hdd_adapter_t *)file->private_data; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_is_feature_supported_by_fw(WOW)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Wake-on-Wireless feature is not supported in firmware!", + __func__); + + return -EINVAL; + } + + if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: hdd_enter_wowl failed!", __func__); + + return -EFAULT; + } + + 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; + + cds_ssr_protect(__func__); + ret = __wcnss_wowenable_write(file, buf, count, ppos); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wcnss_wowpattern_write() - wow_pattern debugfs handler + * @file: debugfs file handle + * @buf: text being written to the debugfs + * @count: size of @buf + * @ppos: (unused) offset into the virtual file system + * + * Return: number of bytes processed + */ +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; + uint8_t pattern_idx = 0; + uint8_t pattern_offset = 0; + char *pattern_buf; + char *pattern_mask; + int ret; + + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_is_feature_supported_by_fw(WOW)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Wake-on-Wireless feature is not supported in firmware!", + __func__); + + return -EINVAL; + } + + if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + + 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; + + cds_ssr_protect(__func__); + ret = __wcnss_wowpattern_write(file, buf, count, ppos); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wcnss_patterngen_write() - pattern_gen debugfs handler + * @file: debugfs file handle + * @buf: text being written to the debugfs + * @count: size of @buf + * @ppos: (unused) offset into the virtual file system + * + * Return: number of bytes processed + */ +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; + uint8_t pattern_idx = 0; + uint8_t pattern_duration = 0; + char *pattern_buf; + uint16_t pattern_len = 0; + uint16_t i = 0; + CDF_STATUS status; + int ret; + + + pAdapter = (hdd_adapter_t *)file->private_data; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 = cdf_mem_malloc(count + 1); + else { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Command length is larger than %d bytes.", + __func__, MAX_USER_COMMAND_SIZE_FRAME); + + return -EINVAL; + } + + if (!cmd) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation for cmd failed!")); + return -ENOMEM; + } + + if (copy_from_user(cmd, buf, count)) { + cdf_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 = + cdf_mem_malloc(sizeof(tSirDelPeriodicTxPtrn)); + if (!delPeriodicTxPtrnParams) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failed!")); + cdf_mem_free(cmd); + return -ENOMEM; + } + delPeriodicTxPtrnParams->ucPtrnId = pattern_idx; + delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; + cdf_mem_copy(delPeriodicTxPtrnParams->macAddress, + pAdapter->macAddressCurrent.bytes, 6); + + /* Delete pattern */ + status = sme_del_periodic_tx_ptrn(pHddCtx->hHal, + delPeriodicTxPtrnParams); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_del_periodic_tx_ptrn() failed!", + __func__); + + cdf_mem_free(delPeriodicTxPtrnParams); + goto failure; + } + cdf_mem_free(cmd); + cdf_mem_free(delPeriodicTxPtrnParams); + return count; + } + + /* + * In SAP mode allow configuration without any connection check + * In STA mode check if it's in connected state before adding + * patterns + */ + hdd_info("device mode %d", pAdapter->device_mode); + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Malformed pattern!", __func__); + + goto failure; + } else + pattern_len >>= 1; + + if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Not an 802.3 frame!", __func__); + + goto failure; + } + + addPeriodicTxPtrnParams = cdf_mem_malloc(sizeof(tSirAddPeriodicTxPtrn)); + if (!addPeriodicTxPtrnParams) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failed!")); + cdf_mem_free(cmd); + return -ENOMEM; + } + + addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; + addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; + addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; + cdf_mem_copy(addPeriodicTxPtrnParams->macAddress, + pAdapter->macAddressCurrent.bytes, 6); + + /* Extract the pattern */ + for (i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) { + addPeriodicTxPtrnParams->ucPattern[i] = + (hex_to_bin(pattern_buf[0]) << 4) + + hex_to_bin(pattern_buf[1]); + + /* Skip to next byte */ + pattern_buf += 2; + } + + /* Add pattern */ + status = sme_add_periodic_tx_ptrn(pHddCtx->hHal, + addPeriodicTxPtrnParams); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_add_periodic_tx_ptrn() failed!", __func__); + + cdf_mem_free(addPeriodicTxPtrnParams); + goto failure; + } + cdf_mem_free(cmd); + cdf_mem_free(addPeriodicTxPtrnParams); + return count; + +failure: + cdf_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; + + cds_ssr_protect(__func__); + ret = __wcnss_patterngen_write(file, buf, count, ppos); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wcnss_debugfs_open() - Generic debugfs open() handler + * @inode: inode of the debugfs file + * @file: file handle of the debugfs file + * + * Return: 0 + */ +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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + 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; + + cds_ssr_protect(__func__); + ret = __wcnss_debugfs_open(inode, file); + cds_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, +}; + +/** + * hdd_debugfs_init() - Initialize debugfs interface + * @pAdapter: primary wlan adapter + * + * Register support for the debugfs files supported by the driver. + * + * NB: The current implementation only supports debugfs operations + * on the primary interface, i.e. wlan0 + * + * Return: CDF_STATUS_SUCCESS if all files registered, + * CDF_STATUS_E_FAILURE on failure + */ +CDF_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 CDF_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("wow_enable", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, + &fops_wowenable)) + return CDF_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, + &fops_wowpattern)) + return CDF_STATUS_E_FAILURE; + + if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR, + pHddCtx->debugfs_phy, pAdapter, + &fops_patterngen)) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_debugfs_exit() - Shutdown debugfs interface + * @pHddCtx: the global HDD context + * + * Unregister support for the debugfs files supported by the driver. + * + * Return: None + */ +void hdd_debugfs_exit(hdd_context_t *pHddCtx) +{ + debugfs_remove_recursive(pHddCtx->debugfs_phy); +} +#endif /* #ifdef WLAN_OPEN_SOURCE */ diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c new file mode 100644 index 000000000000..d8a1f67364ce --- /dev/null +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -0,0 +1,642 @@ +/* + * 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. + */ + +#include +#include +#ifdef HIF_PCI +#ifdef CONFIG_CNSS +#include +#endif /* CONFIG_CNSS */ +#else +#include +#endif /* HIF_PCI */ +#include "cds_api.h" +#include "cdf_status.h" +#include "cdf_lock.h" +#include "cds_sched.h" +#include "osdep.h" +#include "hif.h" +#include "epping_main.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_power.h" +#include "wlan_logging_sock_svc.h" +#include "wma_api.h" +#include "wlan_hdd_napi.h" + +#ifdef MODULE +#define WLAN_MODULE_NAME module_name(THIS_MODULE) +#else +#define WLAN_MODULE_NAME "wlan" +#endif + +#ifdef HIF_PCI +#ifdef CONFIG_CNSS +#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ + cnss_wlan_register_driver(wlan_drv_ops) +#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ + cnss_wlan_unregister_driver(wlan_drv_ops) +#else +#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ + pci_register_driver(wlan_drv_ops) +#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ + pci_unregister_driver(wlan_drv_ops) +#endif /* CONFIG_CNSS */ +#else +#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ + icnss_register_driver(wlan_drv_ops) +#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ + icnss_unregister_driver(wlan_drv_ops) +#endif /* HIF_PCI */ + +/** + * wlan_hdd_probe() - handles probe request + * + * This function is called to probe the wlan driver + * + * @dev: wlan device structure + * @bdev: bus device structure + * @bid: bus identifier for shared busses + * @bus_type: underlying bus type + * @reinit: true if we are reinitiallizing the driver after a subsystem restart + * + * Return: 0 on successfull probe + */ +static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, + enum ath_hal_bus_type bus_type, bool reinit) +{ + void *hif_ctx; + CDF_STATUS status; + int ret; + + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + status = epping_open(); + if (status != CDF_STATUS_SUCCESS) + return status; + } + + status = hif_open(); + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("hif_open error = %d"), status); + return -EFAULT; + } + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + if (reinit) + hdd_napi_destroy(true); + status = hdd_napi_create(); + if (hdd_napi_enabled(HDD_NAPI_ANY)) { + hdd_info("hdd_napi_create returned: %d\n", status); + if (status <= 0) { + hdd_err("NAPI creation error, rc: 0x%x, reinit = %d", + status, reinit); + return -EFAULT; + } + } + + status = hif_enable(hif_ctx, dev, bdev, bid, + bus_type, (reinit == true) ? + HIF_ENABLE_TYPE_REINIT : HIF_ENABLE_TYPE_PROBE); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("hif_enable error = %d, reinit = %d", + status, reinit); + ret = -EIO; + goto end; + } + + if (reinit) + ret = hdd_wlan_re_init(hif_ctx); + else + ret = hdd_wlan_startup(dev, hif_ctx); + +end: + if (ret) { + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + hif_pktlogmod_exit(hif_ctx); + epping_disable(); + htc_destroy(cds_get_context(CDF_MODULE_ID_HTC)); + hif_disable(hif_ctx, (reinit == true) ? + HIF_ENABLE_TYPE_REINIT : HIF_ENABLE_TYPE_PROBE); + cds_free_context(NULL, CDF_MODULE_ID_HTC, NULL); + epping_close(); + } else { + hif_pktlogmod_exit(hif_ctx); + __hdd_wlan_exit(); + hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); + } + hif_close(hif_ctx); + } + + if (reinit) + cds_set_logp_in_progress(false); + + return ret; +} + +/** + * wlan_hdd_remove() - wlan_hdd_remove + * + * This function is called by the platform driver to remove the + * driver + * + * Return: void + */ +static void wlan_hdd_remove(void) +{ + void *hif_ctx; + v_CONTEXT_t p_cds_context = NULL; + + /* Get the global cds context */ + p_cds_context = cds_get_global_context(); + + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + hif_pktlogmod_exit(hif_ctx); + epping_disable(); + htc_destroy(cds_get_context(CDF_MODULE_ID_HTC)); + hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); + cds_free_context(NULL, CDF_MODULE_ID_HTC, NULL); + epping_close(); + } else { + hif_pktlogmod_exit(hif_ctx); + __hdd_wlan_exit(); + hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); + } + + hdd_napi_destroy(true); + hif_close(hif_ctx); + + cds_free_global_context(&p_cds_context); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif + + cdf_wake_lock_destroy(hdd_wlan_get_wake_lock_ptr()); + + pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME); +} + +/** + * wlan_hdd_shutdown() - wlan_hdd_shutdown + * + * This is routine is called by platform driver to shutdown the + * driver + * + * Return: void + */ +static void wlan_hdd_shutdown(void) +{ + void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + + if (cds_is_load_unload_in_progress()) { + hddLog(LOGE, + FL("Load/unload in progress, ignore SSR shutdown")); + return; + } + /* this is for cases, where shutdown invoked from CNSS */ + cds_set_logp_in_progress(true); + + if (cds_get_conparam() != CDF_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + hif_pktlogmod_exit(hif_ctx); + + if (!cds_is_ssr_ready(__func__)) + hddLog(LOGE, + FL("Host is not ready for SSR, attempting anyway")); + + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + hdd_wlan_shutdown(); + + hif_disable(hif_ctx, HIF_DISABLE_TYPE_SHUTDOWN); + hif_close(hif_ctx); +} + +/** + * wlan_hdd_crash_shutdown() - wlan_hdd_crash_shutdown + * + * HDD crash shutdown funtion: This function is called by + * platfrom driver's crash shutdown routine + * + * Return: void + */ +void wlan_hdd_crash_shutdown(void) +{ + hif_crash_shutdown(cds_get_context(CDF_MODULE_ID_HIF)); +} + +/** + * wlan_hdd_notify_handler() - wlan_hdd_notify_handler + * + * This function is called by the platform driver to notify the + * COEX + * + * @state: state + * + * Return: void + */ +void wlan_hdd_notify_handler(int state) +{ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + int ret = 0; + ret = hdd_wlan_notify_modem_power_state(state); + if (ret < 0) + hddLog(LOGE, FL("Fail to send notify")); + } +} + +/** + * __wlan_hdd_bus_suspend() - handles platform supsend + * @state: suspend message from the kernel + * + * Does precondtion validation. Ensures that a subsystem restart isn't in + * progress. Ensures that no load or unload is in progress. + * Calls ol_txrx_bus_suspend to ensure the layer is ready for a bus suspend. + * Calls wma_suspend to configure offloads. + * Calls hif_suspend to suspend the bus. + * + * Return: 0 for success, -EFAULT for null pointers, + * -EBUSY or -EAGAIN if another opperation is in progress and + * wlan will not be ready to suspend in time. + */ +static int __wlan_hdd_bus_suspend(pm_message_t state) +{ + void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + int err = wlan_hdd_validate_context(hdd_ctx); + int status; + + hdd_info("event %d", state.event); + + if (err) + goto done; + + err = cdf_status_to_os_return( + ol_txrx_bus_suspend()); + if (err) + goto done; + + err = wma_bus_suspend(); + if (err) + goto resume_oltxrx; + + err = hif_bus_suspend(); + if (err) + goto resume_wma; + + hdd_info("suspend done, status = %d", err); + return err; + +resume_wma: + status = wma_bus_resume(); + CDF_BUG(!status); +resume_oltxrx: + status = ol_txrx_bus_resume(); + CDF_BUG(!status); +done: + hdd_err("suspend done, status = %d", err); + return err; +} + +/** + * wlan_hdd_bus_suspend() - suspend the wlan bus + * + * This function is called by the platform driver to suspend the + * wlan bus + * + * @state: state + * + * Return: CDF_STATUS + */ +int wlan_hdd_bus_suspend(pm_message_t state) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_bus_suspend(state); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_bus_resume() - handles platform resume + * + * Does precondtion validation. Ensures that a subsystem restart isn't in + * progress. Ensures that no load or unload is in progress. Ensures that + * it has valid pointers for the required contexts. + * Calls into hif to resume the bus opperation. + * Calls into wma to handshake with firmware and notify it that the bus is up. + * Calls into ol_txrx for symetry. + * Failures are treated as catastrophic. + * + * return: error code or 0 for success + */ +static int __wlan_hdd_bus_resume(void) +{ + void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + int status = wlan_hdd_validate_context(hdd_ctx); + + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + status = hif_bus_resume(); + CDF_BUG(!status); + + status = wma_bus_resume(); + CDF_BUG(!status); + + status = ol_txrx_bus_resume(); + CDF_BUG(!status); + + hdd_info("resume done"); + return status; +} + +/** + * wlan_hdd_bus_resume(): wake up the bus + * + * This function is called by the platform driver to resume wlan + * bus + * + * Return: void + */ +static int wlan_hdd_bus_resume(void) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_bus_resume(); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef HIF_PCI +/** + * wlan_hdd_pci_probe() - probe callback for pci platform driver + * @pdev: bus dev + * + * Return: void + */ +static int wlan_hdd_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + return wlan_hdd_probe(&pdev->dev, pdev, (void *)id, + HAL_BUS_TYPE_PCI, false); +} + +/** + * wlan_hdd_pci_remove() - wlan_hdd_pci_remove + * + * Return: void + */ +void wlan_hdd_pci_remove(struct pci_dev *pdev) +{ + wlan_hdd_remove(); +} + +/** + * wlan_hdd_pci_reinit() - wlan_hdd_pci_reinit + * @pdev: bus dev + * @id: bus id + * + * Return: int + */ +int wlan_hdd_pci_reinit(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + return wlan_hdd_probe(&pdev->dev, pdev, id, + HAL_BUS_TYPE_PCI, true); +} + +/** + * wlan_hdd_pci_shutdown() - wlan_hdd_pci_shutdown + * @pdev: pdev + * + * Return: void + */ +void wlan_hdd_pci_shutdown(struct pci_dev *pdev) +{ + wlan_hdd_shutdown(); +} + +/** + * wlan_hdd_pci_crash_shutdown() - wlan_hdd_pci_crash_shutdown + * @pdev: pdev + * + * Return: void + */ +void wlan_hdd_pci_crash_shutdown(struct pci_dev *pdev) +{ + wlan_hdd_crash_shutdown(); +} + +/** + * wlan_hdd_pci_notify_handler() - wlan_hdd_pci_notify_handler + * @pdev: pdev + * @state: state + * + * Return: void + */ +void wlan_hdd_pci_notify_handler(struct pci_dev *pdev, int state) +{ + wlan_hdd_notify_handler(state); +} + +/** + * wlan_hdd_pci_suspend() - wlan_hdd_pci_suspend + * @pdev: pdev + * @state: state + * + * Return: void + */ +static int wlan_hdd_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + return wlan_hdd_bus_suspend(state); +} + +/** + * wlan_hdd_pci_resume() - wlan_hdd_pci_resume + * @pdev: pdev + * + * Return: void + */ +static int wlan_hdd_pci_resume(struct pci_dev *pdev) +{ + return wlan_hdd_bus_resume(); +} +#else +/** + * wlan_hdd_snoc_probe() - wlan_hdd_snoc_probe + * @dev: dev + * + * Return: int + */ +static int wlan_hdd_snoc_probe(struct device *dev) +{ + return wlan_hdd_probe(dev, NULL, NULL, HAL_BUS_TYPE_SNOC, false); +} + +/** + * wlan_hdd_snoc_remove() - wlan_hdd_snoc_remove + * @dev: dev + * + * Return: void + */ +void wlan_hdd_snoc_remove(struct device *dev) +{ + wlan_hdd_remove(); +} + +/** + * wlan_hdd_snoc_shutdown() - wlan_hdd_snoc_shutdown + * @dev: dev + * + * Return: void + */ +void wlan_hdd_snoc_shutdown(struct device *dev) +{ + wlan_hdd_shutdown(); +} + +/** + * wlan_hdd_snoc_reinit() - wlan_hdd_snoc_reinit + * @dev: dev + * + * Return: int + */ +int wlan_hdd_snoc_reinit(struct device *dev) +{ + return wlan_hdd_probe(dev, NULL, NULL, HAL_BUS_TYPE_SNOC, true); +} + +/** + * wlan_hdd_snoc_crash_shutdown() - wlan_hdd_snoc_crash_shutdown + * @dev: dev + * + * Return: void + */ +void wlan_hdd_snoc_crash_shutdown(void *pdev) +{ + wlan_hdd_crash_shutdown(); +} + +/** + * wlan_hdd_snoc_suspend() - wlan_hdd_snoc_suspend + * @dev: dev + * @state: state + * + * Return: int + */ +static int wlan_hdd_snoc_suspend(struct device *dev, pm_message_t state) +{ + return wlan_hdd_bus_suspend(state); +} + +/** + * wlan_hdd_snoc_resume() - wlan_hdd_snoc_resume + * @dev: dev + * + * Return: int + */ +static int wlan_hdd_snoc_resume(struct device *dev) +{ + return wlan_hdd_bus_resume(); +} +#endif /* HIF_PCI */ + +#ifdef HIF_PCI +static struct pci_device_id wlan_hdd_pci_id_table[] = { + { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID }, + { 0 } +}; + +#ifdef CONFIG_CNSS +struct cnss_wlan_driver wlan_drv_ops = { + .name = "wlan_hdd_pci", + .id_table = wlan_hdd_pci_id_table, + .probe = wlan_hdd_pci_probe, + .remove = wlan_hdd_pci_remove, + .reinit = wlan_hdd_pci_reinit, + .shutdown = wlan_hdd_pci_shutdown, + .crash_shutdown = wlan_hdd_pci_crash_shutdown, + .modem_status = wlan_hdd_pci_notify_handler, +#ifdef ATH_BUS_PM + .suspend = wlan_hdd_pci_suspend, + .resume = wlan_hdd_pci_resume, +#endif /* ATH_BUS_PM */ +}; +#else +MODULE_DEVICE_TABLE(pci, wlan_hdd_pci_id_table); +struct pci_driver wlan_drv_ops = { + .name = "wlan_hdd_pci", + .id_table = wlan_hdd_pci_id_table, + .probe = wlan_hdd_pci_probe, + .remove = wlan_hdd_pci_remove, +#ifdef ATH_BUS_PM + .suspend = wlan_hdd_pci_suspend, + .resume = wlan_hdd_pci_resume, +#endif /* ATH_BUS_PM */ +}; +#endif /* CONFIG_CNSS */ +#else +struct icnss_driver_ops wlan_drv_ops = { + .name = "wlan_hdd_drv", + .probe = wlan_hdd_snoc_probe, + .remove = wlan_hdd_snoc_remove, + .shutdown = wlan_hdd_snoc_shutdown, + .reinit = wlan_hdd_snoc_reinit, + .crash_shutdown = wlan_hdd_snoc_crash_shutdown, + .suspend = wlan_hdd_snoc_suspend, + .resume = wlan_hdd_snoc_resume, +}; +#endif + +/** + * wlan_hdd_register_driver() - wlan_hdd_register_driver + * + * Return: int + */ +int wlan_hdd_register_driver(void) +{ + return WLAN_HDD_REGISTER_DRIVER(&wlan_drv_ops); +} + +/** + * wlan_hdd_unregister_driver() - wlan_hdd_unregister_driver + * + * Return: void + */ +void wlan_hdd_unregister_driver(void) +{ + WLAN_HDD_UNREGISTER_DRIVER(&wlan_drv_ops); +} diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c new file mode 100644 index 000000000000..e5cf724e4560 --- /dev/null +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -0,0 +1,4605 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_ext_scan.c + * + * WLAN Host Device Driver EXT SCAN feature implementation + * + */ + +#ifdef FEATURE_WLAN_EXTSCAN + +#include "wlan_hdd_ext_scan.h" +#include "cds_utils.h" +#include "cds_sched.h" + +/* amount of time to wait for a synchronous request/response operation */ +#define WLAN_WAIT_TIME_EXTSCAN 1000 + +/** + * 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 + * @context_lock: Spinlock to serialize all context accesses + * @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; + spinlock_t context_lock; + struct ext_scan_capabilities_response capability_response; +}; +static struct hdd_ext_scan_context ext_scan_context; + +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}, +}; + +/** + * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target + * @ctx: Pointer to hdd context + * @data: Pointer to ext scan capabilities response from fw + * + * 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 = ctx; + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + context = &ext_scan_context; + + spin_lock(&context->context_lock); + /* validate response received from target*/ + if (context->request_id != data->requestId) { + spin_unlock(&context->context_lock); + hddLog(LOGE, + FL("Target response id did not match: request_id %d response_id %d"), + context->request_id, data->requestId); + return; + } else { + context->capability_response = *data; + complete(&context->response_event); + } + + spin_unlock(&context->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.bytes) || + 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, populated 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 = ctx; + struct sk_buff *skb = NULL; + struct hdd_ext_scan_context *context; + struct extscan_cached_scan_result *result; + tSirWifiScanResult *ap; + uint32_t i, j, nl_buf_len; + bool ignore_cached_results = false; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !data) { + hddLog(LOGE, FL("HDD ctx invalid or data(%p) is null"), data); + return; + } + + context = &ext_scan_context; + spin_lock(&context->context_lock); + ignore_cached_results = context->ignore_cached_results; + spin_unlock(&context->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(LOG1, 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_cmd_alloc_reply_skb 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.bytes), + 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(&context->context_lock); + context->response_status = 0; + complete(&context->response_event); + spin_unlock(&context->context_lock); + } + return; + +fail: + if (skb) + kfree_skb(skb); + + spin_lock(&context->context_lock); + context->response_status = -EINVAL; + spin_unlock(&context->context_lock); + + return; +} + +/** + * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind + * @ctx: Pointer to hdd context + * @pData: Pointer to ext scan result event + * + * 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; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !data) { + hddLog(LOGE, FL("HDD ctx invalid or data(%p) is null"), data); + 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, GFP_KERNEL); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hdd_info("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 = cdf_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.bytes), + 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.bytes) || + 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, GFP_KERNEL); + return; + +fail: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() - + * significant wifi change results indication + * @ctx: Pointer to hdd context + * @pData: Pointer to signif wifi change event + * + * 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; + int32_t *rssi; + uint32_t i, j; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !pData) { + hddLog(LOGE, FL("HDD ctx 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, + GFP_KERNEL); + + 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.bytes), + 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, + CDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) || + 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, GFP_KERNEL); + return; + +fail: + kfree_skb(skb); + return; + +} + +/** + * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event + * @ctx: Pointer to hdd context + * @pData: Pointer to full scan result event + * + * 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 + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !pData) { + hddLog(LOGE, FL("HDD ctx invalid or pData(%p) is null"), pData); + return; + } + + if ((sizeof(*pData) + pData->ap.ieLength) >= 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_FULL_SCAN_RESULT_INDEX, + GFP_KERNEL); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + + pData->ap.channel = cds_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.bytes), + 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.bytes) || + 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, GFP_KERNEL); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event + * @ctx: Pointer to hdd context + * @pData: Pointer to scan results available indication param + * + * 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; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !pData) { + hddLog(LOGE, FL("HDD ctx 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_SCAN_RESULTS_AVAILABLE_INDEX, + GFP_KERNEL); + + 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, GFP_KERNEL); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event + * @ctx: Pointer to hdd context + * @pData: Pointer to scan event indication param + * + * 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; + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx) || !pData) { + hddLog(LOGE, FL("HDD ctx 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_SCAN_EVENT_INDEX, + GFP_KERNEL); + + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); + return; + } + hddLog(LOG1, "Req 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, GFP_KERNEL); + 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. + * + * 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; + + 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, + GFP_KERNEL); + + 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 = cds_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.bytes), + 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, GFP_KERNEL); + return; + +fail: + 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 + * + * 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; + + 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, + GFP_KERNEL); + + 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.bytes), + 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, GFP_KERNEL); + return; + +fail: + kfree_skb(skb); + 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. + * + * 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; + uint32_t i, index; + + 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, + GFP_KERNEL); + + 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.bytes), + 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.bytes) || + 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, GFP_KERNEL); + 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 %u"), + response->request_id, response->status); + + context = &ext_scan_context; + spin_lock(&context->context_lock); + if (context->request_id == response->request_id) { + context->response_status = response->status ? -EINVAL : 0; + complete(&context->response_event); + } + spin_unlock(&context->context_lock); + + return; +} + +/** + * wlan_hdd_cfg80211_extscan_callback() - ext scan callback + * @ctx: Pointer to hdd context + * @evType: Event type + * @pMag: Pointer to message + * + * Return: none + */ +void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType, + void *pMsg) +{ + hdd_context_t *pHddCtx = (hdd_context_t *) ctx; + + if (wlan_hdd_validate_context(pHddCtx)) { + hddLog(LOGE, FL("HDD ctx invalid received event: %d"), evType); + 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(LOG1, + 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_HOTLIST_SSID_MATCH_IND: + wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx, + (tpSirWifiScanResultEvent)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; + + default: + hddLog(LOGE, FL("Unknown event type %u"), evType); + break; + } +} + +/* + * 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 = &(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 + +/** + * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: none + */ +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]; + CDF_STATUS status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + data, data_len, wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 = &ext_scan_context; + spin_lock(&context->context_lock); + context->request_id = pReqMsg->requestId; + INIT_COMPLETION(context->response_event); + spin_unlock(&context->context_lock); + + status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_ext_scan_get_capabilities 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")); + + return ret; +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data, + data_len); + cds_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 nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + + 1]; + struct hdd_ext_scan_context *context; + CDF_STATUS status; + int retval = 0; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + 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; + } + + pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 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); + + context = &ext_scan_context; + spin_lock(&context->context_lock); + context->request_id = pReqMsg->requestId; + context->ignore_cached_results = false; + INIT_COMPLETION(context->response_event); + spin_unlock(&context->context_lock); + + status = sme_get_cached_results(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_get_cached_results 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(&context->context_lock); + context->ignore_cached_results = true; + spin_unlock(&context->context_lock); + } else { + spin_lock(&context->context_lock); + retval = context->response_status; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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. + */ +int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data, + data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: none + */ +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; + CDF_STATUS status; + uint8_t i; + int rem, retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + 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 = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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]); + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Number of AP %d Session Id %d"), + pReqMsg->numAp, pReqMsg->sessionId); + + /* 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); + + 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.bytes, + tb2 + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID], + CDF_MAC_ADDR_SIZE); + hddLog(LOG1, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes)); + + /* 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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_set_bss_hotlist 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_set_bss_hotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data, + data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + + +/** + * __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: none + */ +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; + CDF_STATUS status; + uint8_t i; + int rem, retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + 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 = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 breacing */ + 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.bytes, + tb2 + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID], + CDF_MAC_ADDR_SIZE); + hddLog(LOG1, MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes)); + + /* 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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_set_significant_change(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_significant_change failed(err=%d)"), status); + cdf_mem_free(pReqMsg); + return -EINVAL; + } + + /* 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_significant_change timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_remove_dsrc_channels () - remove dsrc chanels + * @wiphy: Pointer to wireless phy + * @chan_list: channel list + * @num_channels: number of channels + * + * Return: none + */ +void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list, + uint8_t *num_channels) +{ + uint8_t num_chan_temp = 0; + int i; + + for (i = 0; i < *num_channels; i++) { + if (!cds_is_dsrc_channel(chan_list[i])) { + chan_list[num_chan_temp] = chan_list[i]; + num_chan_temp++; + } + } + + *num_channels = num_chan_temp; +} + +/** + * hdd_remove_indoor_channels () - remove indoor channels + * @wiphy: Pointer to wireless phy + * @chan_list: channel list + * @num_channels: number of channels + * + * Return: none + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list, + uint8_t *num_channels) +{ + uint8_t num_chan_temp = 0; + int i, j, k; + + 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_temp] = chan_list[i]; + num_chan_temp++; + } + } + } + + *num_channels = num_chan_temp; +} +#else +void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list, + uint8_t *num_channels) +{ + *num_channels = 0; +} +#endif + +/** + * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: none + */ +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; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + + 1]; + uint32_t requestId, maxChannels; + tWifiBand wifiBand; + CDF_STATUS status; + struct sk_buff *reply_skb; + uint8_t i; + int ret; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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_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); + + 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_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal), + wifiBand, chan_list, + &num_channels); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("sme_get_valid_channels_by_band failed (err=%d)"), + status); + return -EINVAL; + } + + num_channels = CDF_MIN(num_channels, maxChannels); + + hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels); + + if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + !strncmp(hdd_get_fwpath(), "ap", 2)) + hdd_remove_indoor_channels(wiphy, chan_list, &num_channels); + + hddLog(LOG1, FL("Number of channels %d"), num_channels); + for (i = 0; i < num_channels; i++) + hddLog(LOG1, "Channel: %u ", chan_list[i]); + + reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + + sizeof(u32) * + num_channels + + NLMSG_HDRLEN); + + if (reply_skb) { + if (nla_put_u32(reply_skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS, + num_channels) || + nla_put(reply_skb, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS, + sizeof(u32) * num_channels, chan_list)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(reply_skb); + return -EINVAL; + } + + return cfg80211_vendor_cmd_reply(reply_skb); + } + + 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 + */ +int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data, + data_len); + cds_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) { + hdd_warn( + "max #of channels %d reached, take only first %d bucket(s)", + total_channels, req->numBuckets); + return true; + } + return false; +} + +/** + * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec + * @hdd_ctx: HDD global context + * @req_msg: Pointer to request structure + * @tb: pointer to NL attributes + * + * Return: 0 on success; error number otherwise + */ +static int hdd_extscan_start_fill_bucket_channel_spec( + hdd_context_t *hdd_ctx, + tpSirWifiScanCmdReqParams req_msg, + 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; + CDF_STATUS status; + uint8_t bkt_index, j, num_channels, total_channels = 0; + uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + uint32_t min_dwell_time_active_bucket = + hdd_ctx->config->extscan_active_max_chn_time; + uint32_t max_dwell_time_active_bucket = + hdd_ctx->config->extscan_active_max_chn_time; + uint32_t min_dwell_time_passive_bucket = + hdd_ctx->config->extscan_passive_max_chn_time; + uint32_t max_dwell_time_passive_bucket = + hdd_ctx->config->extscan_passive_max_chn_time; + + bkt_index = 0; + req_msg->min_dwell_time_active = + req_msg->max_dwell_time_active = + hdd_ctx->config->extscan_active_max_chn_time; + + req_msg->min_dwell_time_passive = + req_msg->max_dwell_time_passive = + hdd_ctx->config->extscan_passive_max_chn_time; + req_msg->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; + } + req_msg->buckets[bkt_index].bucket = nla_get_u8( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]); + hddLog(LOG1, FL("Bucket spec Index %d"), + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].band = nla_get_u8( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]); + hddLog(LOG1, FL("Wifi band %d"), + req_msg->buckets[bkt_index].band); + + /* Parse and fetch period */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) { + hddLog(LOGE, FL("attr period failed")); + return -EINVAL; + } + req_msg->buckets[bkt_index].period = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]); + hddLog(LOG1, FL("period %d"), + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].reportEvents = nla_get_u8( + bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]); + hddLog(LOG1, FL("report events %d"), + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].max_period = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]); + hddLog(LOG1, FL("max period %u"), + req_msg->buckets[bkt_index].max_period); + + /* Parse and fetch exponent */ + if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]) { + hddLog(LOGE, FL("attr exponent failed")); + return -EINVAL; + } + req_msg->buckets[bkt_index].exponent = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]); + hddLog(LOG1, FL("exponent %u"), + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].step_count = nla_get_u32( + bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]); + hddLog(LOG1, FL("Step count %u"), + req_msg->buckets[bkt_index].step_count); + + /* start with known good values for bucket dwell times */ + req_msg->buckets[bkt_index].min_dwell_time_active = + req_msg->buckets[bkt_index].max_dwell_time_active = + hdd_ctx->config->extscan_active_max_chn_time; + + req_msg->buckets[bkt_index].min_dwell_time_passive = + req_msg->buckets[bkt_index].max_dwell_time_passive = + hdd_ctx->config->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 (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) { + if (hdd_extscan_channel_max_reached(req_msg, + total_channels)) + return 0; + + num_channels = 0; + hddLog(LOG1, "WiFi band is specified, driver to fill channel list"); + status = sme_get_valid_channels_by_band(hdd_ctx->hHal, + req_msg->buckets[bkt_index].band, + chan_list, &num_channels); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_GetValidChannelsByBand failed (err=%d)"), + status); + return -EINVAL; + } + hddLog(LOG1, FL("before trimming, num_channels: %d"), + num_channels); + + req_msg->buckets[bkt_index].numChannels = + CDF_MIN(num_channels, + (WLAN_EXTSCAN_MAX_CHANNELS - + total_channels)); + hdd_info("Adj Num channels/bucket: %d total_channels: %d", + req_msg->buckets[bkt_index].numChannels, + total_channels); + total_channels += + req_msg->buckets[bkt_index].numChannels; + + for (j = 0; j < req_msg->buckets[bkt_index].numChannels; + j++) { + req_msg->buckets[bkt_index].channels[j].channel = + chan_list[j]; + req_msg->buckets[bkt_index].channels[j]. + chnlClass = 0; + if (CDS_IS_PASSIVE_OR_DISABLE_CH( + cds_freq_to_chan(chan_list[j]))) { + req_msg->buckets[bkt_index].channels[j]. + passive = 1; + req_msg->buckets[bkt_index].channels[j]. + dwellTimeMs = + hdd_ctx->config-> + extscan_passive_max_chn_time; + /* reconfigure per-bucket dwell time */ + if (min_dwell_time_passive_bucket > + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + min_dwell_time_passive_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + if (max_dwell_time_passive_bucket < + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + max_dwell_time_passive_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + + } else { + req_msg->buckets[bkt_index].channels[j]. + passive = 0; + req_msg->buckets[bkt_index].channels[j]. + dwellTimeMs = + hdd_ctx->config->extscan_active_max_chn_time; + /* reconfigure per-bucket dwell times */ + if (min_dwell_time_active_bucket > + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + min_dwell_time_active_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + if (max_dwell_time_active_bucket < + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + max_dwell_time_active_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + + } + + hddLog(LOG1, + "Channel: %u Passive: %u Dwell time: %u ms Class: %u", + req_msg->buckets[bkt_index].channels[j].channel, + req_msg->buckets[bkt_index].channels[j].passive, + req_msg->buckets[bkt_index].channels[j].dwellTimeMs, + req_msg->buckets[bkt_index].channels[j].chnlClass); + } + + hdd_extscan_update_dwell_time_limits( + req_msg, bkt_index, + min_dwell_time_active_bucket, + max_dwell_time_active_bucket, + min_dwell_time_passive_bucket, + max_dwell_time_passive_bucket); + + hddLog(LOG1, FL("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d"), + bkt_index, + req_msg->buckets[bkt_index].min_dwell_time_active, + req_msg->buckets[bkt_index].max_dwell_time_active, + req_msg->buckets[bkt_index].min_dwell_time_passive, + req_msg->buckets[bkt_index].max_dwell_time_passive); + + bkt_index++; + req_msg->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; + } + req_msg->buckets[bkt_index].numChannels = + nla_get_u32(bucket[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]); + hdd_info("before trimming: num channels %d", + req_msg->buckets[bkt_index].numChannels); + + req_msg->buckets[bkt_index].numChannels = + CDF_MIN(req_msg->buckets[bkt_index].numChannels, + (WLAN_EXTSCAN_MAX_CHANNELS - total_channels)); + hdd_info("Num channels/bucket: %d total_channels: %d", + req_msg->buckets[bkt_index].numChannels, + total_channels); + if (hdd_extscan_channel_max_reached(req_msg, 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 (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; + } + + if (hdd_extscan_channel_max_reached(req_msg, + total_channels)) + break; + + /* Parse and fetch channel */ + if (!channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) { + hddLog(LOGE, FL("attr channel failed")); + return -EINVAL; + } + req_msg->buckets[bkt_index].channels[j].channel = + nla_get_u32(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]); + hddLog(LOG1, FL("channel %u"), + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].channels[j].dwellTimeMs = + nla_get_u32(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]); + + /* Override dwell time if required */ + if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs < + hdd_ctx->config->extscan_active_min_chn_time || + req_msg->buckets[bkt_index].channels[j].dwellTimeMs > + hdd_ctx->config->extscan_active_max_chn_time) { + hddLog(LOG1, FL("WiFi band is unspecified, dwellTime:%d"), + req_msg->buckets[bkt_index].channels[j].dwellTimeMs); + + if (CDS_IS_PASSIVE_OR_DISABLE_CH( + cds_freq_to_chan( + req_msg->buckets[bkt_index].channels[j].channel))) { + req_msg->buckets[bkt_index].channels[j].dwellTimeMs = + hdd_ctx->config->extscan_passive_max_chn_time; + } else { + req_msg->buckets[bkt_index].channels[j].dwellTimeMs = + hdd_ctx->config->extscan_active_max_chn_time; + } + } + + hddLog(LOG1, FL("New Dwell time %u ms"), + req_msg->buckets[bkt_index].channels[j].dwellTimeMs); + + if (CDS_IS_PASSIVE_OR_DISABLE_CH( + cds_freq_to_chan( + req_msg->buckets[bkt_index].channels[j].channel))) { + if (min_dwell_time_passive_bucket > + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + min_dwell_time_passive_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + if (max_dwell_time_passive_bucket < + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + max_dwell_time_passive_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + } else { + if (min_dwell_time_active_bucket > + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + min_dwell_time_active_bucket = + req_msg->buckets[bkt_index].channels[j].dwellTimeMs; + } + if (max_dwell_time_active_bucket < + req_msg->buckets[bkt_index].channels[j].dwellTimeMs) { + max_dwell_time_active_bucket = + req_msg->buckets[bkt_index].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; + } + req_msg->buckets[bkt_index].channels[j].passive = + nla_get_u8(channel[ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]); + hddLog(LOG1, FL("Chnl spec passive %u"), + req_msg->buckets[bkt_index].channels[j].passive); + /* Override scan type if required */ + if (CDS_IS_PASSIVE_OR_DISABLE_CH( + cds_freq_to_chan( + req_msg->buckets[bkt_index].channels[j].channel))) { + req_msg->buckets[bkt_index].channels[j].passive = true; + } else { + req_msg->buckets[bkt_index].channels[j].passive = false; + } + j++; + total_channels++; + } + + hdd_extscan_update_dwell_time_limits( + req_msg, bkt_index, + 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"), + bkt_index, + req_msg->buckets[bkt_index].min_dwell_time_active, + req_msg->buckets[bkt_index].max_dwell_time_active, + req_msg->buckets[bkt_index].min_dwell_time_passive, + req_msg->buckets[bkt_index].max_dwell_time_passive); + + bkt_index++; + req_msg->numBuckets++; + } + + hddLog(LOG1, FL("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d"), + req_msg->min_dwell_time_active, + req_msg->max_dwell_time_active, + req_msg->min_dwell_time_passive, + req_msg->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() - ext scan start + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Return: 0 on success; error number otherwise + */ +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; + CDF_STATUS status; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + 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; + } + + pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + 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; + } + + 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) { + hdd_warn("Exceeded MAX number of buckets: %d", + WLAN_EXTSCAN_MAX_BUCKETS); + } + hdd_info("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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_ext_scan_start failed(err=%d)"), status); + goto fail; + } + + pHddCtx->ext_scan_start_since_boot = cdf_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_ext_scan_start timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len); + cds_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() - ext scan stop + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: none + */ +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 nlattr *tb[PARAM_MAX + 1]; + struct hdd_ext_scan_context *context; + CDF_STATUS status; + uint32_t request_id; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + 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; + } + + pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_ext_scan_stop 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_ext_scan_stop timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_mem_free(pReqMsg); + return -EINVAL; +} +/* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_stop() + */ +#undef PARAM_MAX +#undef 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 + */ +int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + + +/** + * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Data length + * + * Return: none + */ +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; + CDF_STATUS status; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + 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 = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_reset_bss_hotlist 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_reset_bss_hotlist timed out")); + retval = -ETIMEDOUT; + } else { + spin_lock(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_mem_free(pReqMsg); + return -EINVAL; +} + +/** + * 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 + */ +int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __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: none + */ +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; + CDF_STATUS status; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + retval = wlan_hdd_validate_context(pHddCtx); + if (0 != retval) { + hddLog(LOGE, FL("HDD context is not valid")); + 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 = cdf_mem_malloc(sizeof(*pReqMsg)); + if (!pReqMsg) { + hddLog(LOGE, FL("cdf_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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = pReqMsg->requestId; + spin_unlock(&context->context_lock); + + status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_reset_significant_change failed(err=%d)"), + status); + cdf_mem_free(pReqMsg); + return -EINVAL; + } + + /* 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(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev, + data, data_len); + cds_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]); + cdf_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]; + CDF_STATUS 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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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 = cdf_mem_malloc(len); + if (!req_msg) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + cdf_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]); + hddLog(LOG1, FL("Req Id %u"), req_msg->request_id); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Session Id %d"), 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 (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("sme_set_epno_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + cdf_mem_free(req_msg); + return 0; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev, + data, data_len); + cds_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; + } + cdf_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")); + + /* 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]; + CDF_STATUS status; + uint32_t num_networks = 0; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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 = cdf_mem_malloc(sizeof(*req_msg) + + (num_networks * sizeof(req_msg->networks[0]))); + if (!req_msg) { + hddLog(LOGE, FL("cdf_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 (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_passpoint_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + cdf_mem_free(req_msg); + return 0; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev, + data, data_len); + cds_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]; + CDF_STATUS status; + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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 = cdf_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + hddLog(LOGE, FL("cdf_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 (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_reset_passpoint_list failed(err=%d)"), status); + goto fail; + } + + EXIT(); + cdf_mem_free(req_msg); + return 0; + +fail: + cdf_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 + */ +int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev, + data, data_len); + cds_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, i, rem; + CDF_STATUS status; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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 = cdf_mem_malloc(sizeof(*request)); + if (!request) { + hddLog(LOGE, FL("cdf_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 = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = request->request_id; + spin_unlock(&context->context_lock); + + status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_ssid_hotlist failed(err=%d)"), status); + goto fail; + } + + cdf_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(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_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 + */ +int +wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data, + data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/* + * 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_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; + CDF_STATUS status; + int retval; + unsigned long rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + 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 = cdf_mem_malloc(sizeof(*request)); + if (!request) { + hddLog(LOGE, FL("cdf_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); + + request->session_id = adapter->sessionId; + hddLog(LOG1, FL("Session Id %d"), request->session_id); + + request->lost_ssid_sample_size = 0; + request->ssid_count = 0; + + context = &ext_scan_context; + spin_lock(&context->context_lock); + INIT_COMPLETION(context->response_event); + context->request_id = request_id = request->request_id; + spin_unlock(&context->context_lock); + + status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_reset_ssid_hotlist failed(err=%d)"), status); + goto fail; + } + + cdf_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(&context->context_lock); + if (context->request_id == request_id) + retval = context->response_status; + else + retval = -EINVAL; + spin_unlock(&context->context_lock); + } + + return retval; + +fail: + cdf_mem_free(request); + return -EINVAL; +} + +/* + * 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 + +/** + * 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 + */ +int +wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_init_completion_extwow() - Initialize ext wow variable + * @hdd_ctx: Global HDD context + * + * Return: none + */ +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx) +{ + init_completion(&pHddCtx->ready_to_extwow); +} +#else +static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx) +{ + return; +} +#endif + +/** + * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature + * @hdd_ctx: Global HDD context + * + * Return: none + */ +void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx) +{ + wlan_hdd_init_completion_extwow(hdd_ctx); + init_completion(&ext_scan_context.response_event); + spin_lock_init(&ext_scan_context.context_lock); +} + +#endif /* FEATURE_WLAN_EXTSCAN */ diff --git a/core/hdd/src/wlan_hdd_ext_scan.h b/core/hdd/src/wlan_hdd_ext_scan.h new file mode 100644 index 000000000000..0772a67a940f --- /dev/null +++ b/core/hdd/src/wlan_hdd_ext_scan.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +#if !defined(WLAN_HDD_EXT_SCAN_H) +#define WLAN_HDD_EXT_SCAN_H + +/** + * DOC: wlan_hdd_ext_scan.h + * + * WLAN Host Device Driver EXT SCAN feature implementation + * + */ + +#ifdef FEATURE_WLAN_EXTSCAN + +#include "wlan_hdd_main.h" + +/* + * 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 + +int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, + struct wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy + *wiphy, + struct + wireless_dev + *wdev, const void *data, + int data_len); + +int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int +wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +int +wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx); + +#else /* FEATURE_WLAN_EXTSCAN */ + +static void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx) +{ +} + +#endif /* End of FEATURE_WLAN_EXTSCAN */ + +#endif /* end #if !defined(WLAN_HDD_EXT_SCAN_H) */ + diff --git a/core/hdd/src/wlan_hdd_ftm.c b/core/hdd/src/wlan_hdd_ftm.c new file mode 100644 index 000000000000..c002991115bc --- /dev/null +++ b/core/hdd/src/wlan_hdd_ftm.c @@ -0,0 +1,1061 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_ftm.c + * + * This file contains the WLAN factory test mode implementation + */ + +#include +#include "cds_sched.h" +#include +#include "sir_types.h" +#include "cdf_types.h" +#include "sir_api.h" +#include "sir_mac_prot_def.h" +#include "sme_api.h" +#include "mac_init_api.h" +#include "wlan_qct_sys.h" +#include "wlan_hdd_misc.h" +#include "i_cds_packet.h" +#include "cds_reg_service.h" +#include "wlan_hdd_main.h" +#include "qwlan_version.h" +#include "wma_types.h" +#include "cfg_api.h" + +#if defined(QCA_WIFI_FTM) +#include "bmi.h" +#include "ol_fw.h" +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_main.h" +#include "hif.h" +#endif + +#define HDD_FTM_WMA_PRE_START_TIMEOUT (30000) /* 30 seconds */ + +#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 + +/** + * wlan_ftm_postmsg() - Post FTM message + * @cmd_ptr: Pointer to FTM command buffer + * @cmd_len: Length of command in @cmd_ptr + * + * This function is used to send FTM commands to firmware + * + * Return: 0 for success, non zero for failure + */ +static uint32_t wlan_ftm_postmsg(uint8_t *cmd_ptr, uint16_t cmd_len) +{ + cds_msg_t ftmMsg; + + ENTER(); + + ftmMsg.type = WMA_FTM_CMD_REQ; + ftmMsg.reserved = 0; + ftmMsg.bodyptr = (uint8_t *) cmd_ptr; + ftmMsg.bodyval = 0; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, + &ftmMsg)) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: : Failed to post Msg to HAL", + __func__); + + return CDF_STATUS_E_FAILURE; + } + + EXIT(); + return CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_ftm_update_tgt_cfg() - Update target configuration + * @context: context registered with WMA + * @param: target configuration + * + * This function is registered with WMA via wma_open(), and is + * invoked via callback when target parameters are received + * from firmware. + * + * Return: None + */ +static void wlan_hdd_ftm_update_tgt_cfg(void *context, void *param) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) context; + struct wma_tgt_cfg *cfg = (struct wma_tgt_cfg *)param; + + if (!cdf_is_macaddr_zero(&cfg->hw_macaddr)) { + hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr); + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Invalid MAC passed from target, using MAC from ini file" + MAC_ADDRESS_STR, __func__, + MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes)); + } +} + +/** + * wlan_ftm_cds_open() - Open the CDS Module in FTM mode + * @p_cds_context: pointer to the global CDS context + * @hddContextSize: Size of the HDD context to allocate. + * + * The wlan_ftm_cds_open() function opens the CDF Scheduler + * Upon successful initialization: + * - All CDS submodules should have been initialized + * - The CDS scheduler should have opened + * - All the WLAN SW components should have been opened. This includes MAC. + * + * Returns: + * CDF_STATUS_SUCCESS - Scheduler was successfully initialized and + * is ready to be used. + * CDF_STATUS_E_RESOURCES - System resources (other than memory) + * are unavailable to initialize the scheduler + * CDF_STATUS_E_FAILURE - Failure to initialize the scheduler + */ +static CDF_STATUS wlan_ftm_cds_open(v_CONTEXT_t p_cds_context, + uint32_t hddContextSize) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + int iter = 0; + tSirRetStatus sirStatus = eSIR_SUCCESS; + tMacOpenParameters mac_openParms; + p_cds_contextType gp_cds_context = (p_cds_contextType) p_cds_context; +#if defined(QCA_WIFI_FTM) + cdf_device_t cdf_ctx; + HTC_INIT_INFO htcInfo; + void *pHifContext = NULL; + void *pHtcContext = NULL; +#endif + hdd_context_t *hdd_ctx; + + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Opening CDS", __func__); + + if (NULL == gp_cds_context) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Trying to open CDS without a PreOpen", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* Initialize the probe event */ + if (cdf_event_init(&gp_cds_context->ProbeEvent) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Unable to init probeEvent", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + if (cdf_event_init(&(gp_cds_context->wmaCompleteEvent)) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Unable to init wmaCompleteEvent", __func__); + CDF_ASSERT(0); + + goto err_probe_event; + } + + /* Initialize the free message queue */ + vStatus = cds_mq_init(&gp_cds_context->freeVosMq); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to initialize CDS free message queue %d", + __func__, vStatus); + CDF_ASSERT(0); + goto err_wma_complete_event; + } + + for (iter = 0; iter < CDS_CORE_MAX_MESSAGES; iter++) { + (gp_cds_context->aMsgWrappers[iter]).pVosMsg = + &(gp_cds_context->aMsgBuffers[iter]); + INIT_LIST_HEAD(&gp_cds_context->aMsgWrappers[iter].msgNode); + cds_mq_put(&gp_cds_context->freeVosMq, + &(gp_cds_context->aMsgWrappers[iter])); + } + + /* Now Open the CDS Scheduler */ + vStatus = cds_sched_open(gp_cds_context, &gp_cds_context->cdf_sched, + sizeof(cds_sched_context)); + + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to open CDS Scheduler %d", __func__, + vStatus); + CDF_ASSERT(0); + goto err_msg_queue; + } +#if defined(QCA_WIFI_FTM) + /* Initialize BMI and Download firmware */ + pHifContext = cds_get_context(CDF_MODULE_ID_HIF); + if (!pHifContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: failed to get HIF context", __func__); + goto err_sched_close; + } + + if (bmi_download_firmware(pHifContext)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: BMI failed to download target", __func__); + goto err_bmi_close; + } + htcInfo.pContext = gp_cds_context->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + + /* Create HTC */ + gp_cds_context->htc_ctx = + htc_create(htcInfo.pContext, &htcInfo, cdf_ctx); + if (!gp_cds_context->htc_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + goto err_bmi_close; + } + + if (bmi_done(pHifContext)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_htc_close; + } +#endif /* QCA_WIFI_FTM */ + + /*Open the WMA module */ + cdf_mem_set(&mac_openParms, sizeof(mac_openParms), 0); + mac_openParms.driverType = eDRIVER_TYPE_MFG; + + hdd_ctx = (hdd_context_t *) (gp_cds_context->pHDDContext); + if ((NULL == hdd_ctx) || (NULL == hdd_ctx->config)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Hdd Context is Null", __func__); + CDF_ASSERT(0); + goto err_htc_close; + } + + mac_openParms.powersaveOffloadEnabled = + hdd_ctx->config->enablePowersaveOffload; + +#ifdef WLAN_FEATURE_LPSS + mac_openParms.is_lpass_enabled = hdd_ctx->config->enablelpasssupport; +#endif + + vStatus = wma_open(gp_cds_context, + wlan_hdd_ftm_update_tgt_cfg, NULL, &mac_openParms); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to open WMA module %d", __func__, + vStatus); + CDF_ASSERT(0); + goto err_htc_close; + } +#if defined(QCA_WIFI_FTM) + ((struct ol_softc *)pHifContext)->enable_ramdump_collection = + hdd_ctx->config->is_ramdump_enabled; + + pHtcContext = cds_get_context(CDF_MODULE_ID_HTC); + if (!pHtcContext) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: failed to get HTC context", __func__); + goto err_wma_close; + } + if (htc_wait_target(pHtcContext)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto err_wma_close; + } +#endif + + /* Now proceed to open the MAC */ + + /* UMA is supported in hardware for performing the + * frame translation 802.11 <-> 802.3 + */ + mac_openParms.frameTransRequired = 1; + + sirStatus = + mac_open(&(gp_cds_context->pMACContext), + gp_cds_context->pHDDContext, + &mac_openParms); + + if (eSIR_SUCCESS != sirStatus) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to open MAC %d", __func__, sirStatus); + CDF_ASSERT(0); + goto err_wma_close; + } +#ifndef QCA_WIFI_FTM + /* Now proceed to open the SME */ + vStatus = sme_open(gp_cds_context->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + /* Critical Error ... Cannot proceed further */ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to open SME %d", __func__, vStatus); + goto err_mac_close; + } + + vStatus = sme_init_chan_list(gp_cds_context->pMACContext, + hdd_ctx->reg.alpha2, hdd_ctx->reg.cc_src); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to init sme channel list", __func__); + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: CDS successfully Opened", __func__); + return CDF_STATUS_SUCCESS; + } +#else + return CDF_STATUS_SUCCESS; +#endif + +#ifndef QCA_WIFI_FTM +err_mac_close: +#endif + mac_close(gp_cds_context->pMACContext); + +err_wma_close: + wma_close(gp_cds_context); + +err_htc_close: +#if defined(QCA_WIFI_FTM) + if (gp_cds_context->htc_ctx) { + htc_destroy(gp_cds_context->htc_ctx); + gp_cds_context->htc_ctx = NULL; + } + +err_bmi_close: + bmi_cleanup(pHifContext); +#endif /* QCA_WIFI_FTM */ + +err_sched_close: + cds_sched_close(gp_cds_context); +err_msg_queue: + cds_mq_deinit(&gp_cds_context->freeVosMq); + +err_wma_complete_event: + cdf_event_destroy(&gp_cds_context->wmaCompleteEvent); + +err_probe_event: + cdf_event_destroy(&gp_cds_context->ProbeEvent); + + return CDF_STATUS_E_FAILURE; + +} /* wlan_ftm_cds_open() */ + +/** + * wlan_ftm_cds_close() - Close the CDF Module in FTM mode + * @cds_context: context of cds + * + * The wlan_ftm_cds_close() function closes the CDF Module + * + * Return: CDF_STATUS_SUCCESS - successfully closed + */ +static CDF_STATUS wlan_ftm_cds_close(v_CONTEXT_t cds_context) +{ + CDF_STATUS cdf_status; + p_cds_contextType gp_cds_context = (p_cds_contextType) cds_context; + +#ifndef QCA_WIFI_FTM + cdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close SME %d", __func__, cdf_status); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } +#endif + + cdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close MAC %d", __func__, cdf_status); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + ((p_cds_contextType) cds_context)->pMACContext = NULL; + + + cdf_status = wma_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close WMA %d", __func__, cdf_status); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } +#if defined(QCA_WIFI_FTM) + if (gp_cds_context->htc_ctx) { + htc_stop(gp_cds_context->htc_ctx); + htc_destroy(gp_cds_context->htc_ctx); + gp_cds_context->htc_ctx = NULL; + } + cdf_status = wma_wmi_service_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + hif_disable_isr(gp_cds_context->pHIFContext); +#endif + + cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq); + + cdf_status = cdf_event_destroy(&gp_cds_context->ProbeEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to destroy ProbeEvent %d", __func__, + cdf_status); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + cdf_status = cdf_event_destroy(&gp_cds_context->wmaCompleteEvent); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to destroy wmaCompleteEvent %d", __func__, + cdf_status); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cds_ftm_pre_start() - Pre-start CDS Module in FTM Mode + * @cds_context: The CDS context + * + * The cds_ftm_pre_start() function performs all pre-start activities + * in FTM mode. + * + * Return: CDF_STATUS_SUCCESS if pre-start was successful, an + * appropriate CDF_STATUS_E_* error code otherwise + */ +static CDF_STATUS cds_ftm_pre_start(v_CONTEXT_t cds_context) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; +#if defined(QCA_WIFI_FTM) + p_cds_contextType gp_cds_context = + cds_get_global_context(); +#endif + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, "cds prestart"); + if (NULL == p_cds_context->pWMAContext) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "%s: WMA NULL context", __func__); + return CDF_STATUS_E_FAILURE; + } + + /* Reset WMA wait event */ + cdf_event_reset(&p_cds_context->wmaCompleteEvent); + + /*call WMA pre start */ + vStatus = wma_pre_start(p_cds_context); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Failed to WMA prestart "); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* Need to update time out of complete */ + vStatus = cdf_wait_single_event(&p_cds_context->wmaCompleteEvent, + HDD_FTM_WMA_PRE_START_TIMEOUT); + if (vStatus != CDF_STATUS_SUCCESS) { + if (vStatus == CDF_STATUS_E_TIMEOUT) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Timeout occurred before WMA complete", + __func__); + } else { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: wma_pre_start reporting other error", + __func__); + } + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } +#if defined(QCA_WIFI_FTM) + vStatus = htc_start(gp_cds_context->htc_ctx); + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_FATAL, + "Failed to Start HTC"); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + wma_wait_for_ready_event(gp_cds_context->pWMAContext); +#endif /* QCA_WIFI_FTM */ + + return CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_ftm_open() - Open HDD in FTM Mode + * @hdd_ctx: global HDD context + * + * The function hdd_wlan_startup calls this function to initialize the + * FTM specific modules. + * + * Return: 0 on success, non-zero on error + */ +int wlan_hdd_ftm_open(hdd_context_t *hdd_ctx) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + p_cds_contextType p_cds_context = NULL; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Opening CDS", __func__); + + p_cds_context = cds_get_global_context(); + + if (NULL == p_cds_context) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Trying to open CDS without a PreOpen", __func__); + CDF_ASSERT(0); + goto err_cdf_status_failure; + } + + vStatus = wlan_ftm_cds_open(p_cds_context, 0); + + if (!CDF_IS_STATUS_SUCCESS(vStatus)) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_open failed", __func__); + goto err_cdf_status_failure; + } + + /* + * only needed to start WMA, which happens in wlan_hdd_ftm_start() + */ + + /* Save the hal context in Adapter */ + hdd_ctx->hHal = + (tHalHandle) cds_get_context(CDF_MODULE_ID_SME); + + if (NULL == hdd_ctx->hHal) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: HAL context is null", + __func__); + goto err_ftm_close; + } + + return 0; + +err_ftm_close: + wlan_ftm_cds_close(p_cds_context); + +err_cdf_status_failure: + return -EPERM; +} + +/** + * hdd_ftm_service_registration() - Register FTM service + * @hdd_ctx: global HDD context + * + * Return: 0 on success, non-zero on failure + */ +static int hdd_ftm_service_registration(hdd_context_t *hdd_ctx) +{ + hdd_adapter_t *adapter; + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_FTM, "wlan%d", + wlan_hdd_get_intf_addr(hdd_ctx), false); + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", + __func__); + goto err_adapter_open_failure; + } + + hdd_ctx->ftm.ftm_state = WLAN_FTM_INITIALIZED; + + return 0; + +err_adapter_open_failure: + + return -EPERM; +} + +/** + * wlan_ftm_stop() - Stop HDD in FTM mode + * @hdd_ctx: pointer to HDD context + * + * This function stops the following modules + * 1. MAC + * 2. WMA + * + * Return: 0 on success, non-zero on failure + */ +static int wlan_ftm_stop(hdd_context_t *hdd_ctx) +{ + CDF_STATUS cdf_status; + + if (hdd_ctx->ftm.ftm_state != WLAN_FTM_STARTED) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s:Ftm has not started. Please start the ftm. ", + __func__); + return -EPERM; + } + + { + /* STOP MAC only */ + void *hHal; + hHal = cds_get_context(CDF_MODULE_ID_SME); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: NULL hHal", __func__); + } else { + cdf_status = + mac_stop(hHal, HAL_STOP_TYPE_SYS_DEEP_SLEEP); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop SYS", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + } + wma_stop(hdd_ctx->pcds_context, HAL_STOP_TYPE_RF_KILL); + } + return 0; +} + +/** + * wlan_hdd_ftm_close() - Close HDD in FTM mode + * @hdd_ctx: pointer to HDD context + * + * Return: 0 on success, non-zero on failure + */ +int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx) +{ + CDF_STATUS cdf_status; + v_CONTEXT_t cds_context = hdd_ctx->pcds_context; + + hdd_adapter_t *adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_FTM); + ENTER(); + if (adapter == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s:adapter is NULL", __func__); + return -ENXIO; + } + + if (WLAN_FTM_STARTED == hdd_ctx->ftm.ftm_state) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s: Ftm has been started. stopping ftm", __func__); + wlan_ftm_stop(hdd_ctx); + } + + hdd_close_all_adapters(hdd_ctx); + + cdf_status = cds_sched_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close CDS Scheduler", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + /* Close CDS */ + wlan_ftm_cds_close(cds_context); + +#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; + +} + + +/** + * hdd_ftm_mc_process_msg() - Process FTM mailbox message + * @message: FTM response message + * + * Process FTM mailbox message + * + * Return: void + */ +static void hdd_ftm_mc_process_msg(void *message) +{ + void *data; + uint32_t data_len; + + if (!message) { + hdd_err("Message is NULL, nothing to process."); + return; + } + + data_len = *((uint32_t *) message); + data = (uint32_t *) message + 1; + +#if defined(LINUX_QCMBR) + wlanqcmbr_mc_process_msg(message); +#else +#ifdef CONFIG_NL80211_TESTMODE + wlan_hdd_testmode_rx_event(data, (size_t) data_len); +#endif +#endif + return; +} + +/** + * wlan_hdd_ftm_start() - Start HDD in FTM mode + * @hdd_ctx: Global HDD context + * + * This function starts the following modules. + * 1) WMA Start. + * 2) HTC Start. + * 3) MAC Start to download the firmware. + * + * Return: 0 for success, non zero for failure + */ +static int wlan_hdd_ftm_start(hdd_context_t *hdd_ctx) +{ + CDF_STATUS vStatus = CDF_STATUS_SUCCESS; + p_cds_contextType p_cds_context = + (p_cds_contextType) (hdd_ctx->pcds_context); + + if (WLAN_FTM_STARTED == hdd_ctx->ftm.ftm_state) { + return 0; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Starting CLD SW", __func__); + + /* We support only one instance for now ... */ + if (p_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: mismatch in context", __func__); + goto err_status_failure; + } + + if (p_cds_context->pMACContext == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: MAC NULL context", __func__); + goto err_status_failure; + } + + /* Vos preStart is calling */ + if (!CDF_IS_STATUS_SUCCESS(cds_ftm_pre_start(hdd_ctx->pcds_context))) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_pre_enable failed", + __func__); + goto err_status_failure; + } + + sme_register_ftm_msg_processor(hdd_ctx->hHal, hdd_ftm_mc_process_msg); + + vStatus = wma_start(p_cds_context); + if (vStatus != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to start WMA", __func__); + goto err_status_failure; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: MAC correctly started", __func__); + + if (hdd_ftm_service_registration(hdd_ctx)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: failed", __func__); + goto err_ftm_service_reg; + } + + hdd_ctx->ftm.ftm_state = WLAN_FTM_STARTED; + + return 0; + +err_ftm_service_reg: + wlan_hdd_ftm_close(hdd_ctx); + +err_status_failure: + + return -EPERM; + +} + +#if defined(QCA_WIFI_FTM) +/** + * hdd_ftm_start() - Start HDD in FTM mode + * @hdd_ctx: Global HDD context + * + * Return: 0 for success, non zero for failure + */ +int hdd_ftm_start(hdd_context_t *hdd_ctx) +{ + return wlan_hdd_ftm_start(hdd_ctx); +} +#endif + +#if defined(QCA_WIFI_FTM) +/** + * hdd_ftm_stop() - Stop HDD in FTM mode + * @hdd_ctx: Global HDD context + * + * Return: 0 for success, non zero for failure + */ +int hdd_ftm_stop(hdd_context_t *hdd_ctx) +{ + return wlan_ftm_stop(hdd_ctx); +} +#endif + +#if defined(QCA_WIFI_FTM) +#if defined(LINUX_QCMBR) +/** + * wlan_hdd_qcmbr_command() - QCMBR command handler + * @adapter: adapter upon which the command was received + * @pqcmbr_data: QCMBR command + * + * Return: 0 on success, non-zero on error + */ +static int wlan_hdd_qcmbr_command(hdd_adapter_t *adapter, + 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) + != CDF_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 +/** + * wlan_hdd_qcmbr_ioctl() - Compatability-mode QCMBR ioctl handler + * @adapter: adapter upon which the ioctl was received + * @ifr: the ioctl request + * + * Return: 0 on success, non-zero on error + */ +static int wlan_hdd_qcmbr_compat_ioctl(hdd_adapter_t *adapter, + 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(adapter, 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 *adapter, + struct ifreq *ifr) +{ + return 0; +} +#endif /* CONFIG_COMPAT */ + +/** + * wlan_hdd_qcmbr_ioctl() - Standard QCMBR ioctl handler + * @adapter: adapter upon which the ioctl was received + * @ifr: the ioctl request + * + * Return: 0 on success, non-zero on error + */ +static int wlan_hdd_qcmbr_ioctl(hdd_adapter_t *adapter, 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(adapter, 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; +} + +/** + * wlan_hdd_qcmbr_unified_ioctl() - Unified QCMBR ioctl handler + * @adapter: adapter upon which the ioctl was received + * @ifr: the ioctl request + * + * Return: 0 on success, non-zero on error + */ +int wlan_hdd_qcmbr_unified_ioctl(hdd_adapter_t *adapter, struct ifreq *ifr) +{ + int ret = 0; + + if (is_compat_task()) { + ret = wlan_hdd_qcmbr_compat_ioctl(adapter, ifr); + } else { + ret = wlan_hdd_qcmbr_ioctl(adapter, ifr); + } + + return ret; +} + +/** + * wlanqcmbr_mc_process_msg() - Process QCMBR response message + * @message: QCMBR message + * + * Return: None + */ +static void wlanqcmbr_mc_process_msg(void *message) +{ + qcmbr_queue_t *qcmbr_buf = NULL; + uint32_t data_len; + + data_len = *((uint32_t *) message) + sizeof(uint32_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 */ + +/** + * wlan_hdd_ftm_testmode_cmd() - Process FTM testmode command + * @data: FTM testmode command + * @len: length of @data + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS wlan_hdd_ftm_testmode_cmd(void *data, int len) +{ + struct ar6k_testmode_cmd_data *cmd_data; + + cmd_data = (struct ar6k_testmode_cmd_data *) + cdf_mem_malloc(sizeof(*cmd_data)); + + if (!cmd_data) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + ("Failed to allocate FTM command data")); + return CDF_STATUS_E_NOMEM; + } + + cmd_data->data = cdf_mem_malloc(len); + + if (!cmd_data->data) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + ("Failed to allocate FTM command data buffer")); + cdf_mem_free(cmd_data); + return CDF_STATUS_E_NOMEM; + } + + cmd_data->len = len; + cdf_mem_copy(cmd_data->data, data, len); + + if (wlan_ftm_postmsg((uint8_t *) cmd_data, sizeof(*cmd_data))) { + cdf_mem_free(cmd_data->data); + cdf_mem_free(cmd_data); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /*QCA_WIFI_FTM */ diff --git a/core/hdd/src/wlan_hdd_green_ap.c b/core/hdd/src/wlan_hdd_green_ap.c new file mode 100644 index 000000000000..7cf2c23212f6 --- /dev/null +++ b/core/hdd/src/wlan_hdd_green_ap.c @@ -0,0 +1,449 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_green_ap.c + * + * WLAN Host Device Driver Green AP implementation + * + */ + +/* Include Files */ +#include +#include +#include "wlan_hdd_green_ap.h" +#include "wma_api.h" +#include "cds_concurrency.h" + +#define GREEN_AP_PS_ON_TIME (0) +#define GREEN_AP_PS_DELAY_TIME (20) + +/** + * enum hdd_green_ap_ps_state - Green-AP power save states + * @GREEN_AP_PS_IDLE_STATE: the Green_AP is not enabled + * @GREEN_AP_PS_OFF_STATE: in Power Saving OFF state + * @GREEN_AP_PS_WAIT_STATE: in transition to Power Saving ON state + * @GREEN_AP_PS_ON_STATE: in Power Saving ON state + */ +enum hdd_green_ap_ps_state { + GREEN_AP_PS_IDLE_STATE = 1, + GREEN_AP_PS_OFF_STATE, + GREEN_AP_PS_WAIT_STATE, + GREEN_AP_PS_ON_STATE, +}; + +/** + * enum hdd_green_ap_event - Green-AP power save events + * @GREEN_AP_PS_START_EVENT: event to indicate to enable Green_AP + * @GREEN_AP_PS_START_EVENT: event to indicate to disable Green_AP + * @GREEN_AP_ADD_STA_EVENT: event to indicate a new STA connected + * @GREEN_AP_DEL_STA_EVENT: event to indicate a STA disconnected + * @GREEN_AP_PS_ON_EVENT: event to indicate to enter Power Saving state + * @GREEN_AP_PS_WAIT_EVENT: event to indicate in the transition to Power Saving + */ +enum hdd_green_ap_event { + 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, +}; + +/** + * struct hdd_green_ap_ctx - Green-AP context + * @ps_enable: Whether or not Green AP is enabled + * @ps_on_time: Amount of time to stay in Green AP power saving state + * @ps_delay_time: Amount of time to delay when changing states + * @num_nodes: Number of connected clients + * @ps_state: Current state + * @ps_event: Event to trigger when timer expires + * @ps_timer: Event timer + */ +struct hdd_green_ap_ctx { + uint8_t ps_enable; + uint32_t ps_on_time; + uint32_t ps_delay_time; + uint32_t num_nodes; + + enum hdd_green_ap_ps_state ps_state; + enum hdd_green_ap_event ps_event; + + cdf_mc_timer_t ps_timer; +}; + +/** + * hdd_wlan_green_ap_update() - update the current State and Event + * @hdd_ctx: Global HDD context + * @state: New state + * @event: New event + * + * Return: none + */ +static void hdd_wlan_green_ap_update(struct hdd_context_s *hdd_ctx, + enum hdd_green_ap_ps_state state, + enum hdd_green_ap_event event) +{ + struct hdd_green_ap_ctx *green_ap = hdd_ctx->green_ap_ctx; + + green_ap->ps_state = state; + green_ap->ps_event = event; +} + +/** + * hdd_wlan_green_ap_enable() - Send Green AP configuration to firmware + * @adapter: Adapter upon which Green AP is being configured + * @enable: Flag which indicates if Green AP is being enabled or disabled + * + * Return: 0 upon success, non-zero upon failure + */ +static int hdd_wlan_green_ap_enable(hdd_adapter_t *adapter, + uint8_t enable) +{ + int ret; + + hddLog(LOG1, FL("Set Green-AP val: %d"), enable); + + ret = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, + enable, DBG_CMD); + + return ret; +} + +/** + * hdd_wlan_green_ap_mc() - Green AP state machine + * @hdd_ctx: HDD global context + * @event: New event being processed + * + * Return: none + */ +static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, + enum hdd_green_ap_event event) +{ + struct hdd_green_ap_ctx *green_ap; + hdd_adapter_t *adapter; + + green_ap = hdd_ctx->green_ap_ctx; + if (green_ap == NULL) + return; + + hddLog(LOG1, FL("Green-AP event: %d, state: %d, num_nodes: %d"), + 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 (!(cds_get_concurrency_mode() & CDF_SAP_MASK)) + 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, FL("invalid event %d"), event); + break; + } + + /* Confirm that power save is enabled before doing state transitions */ + if (!green_ap->ps_enable) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("Green-AP is disabled")); + hdd_wlan_green_ap_update(hdd_ctx, + GREEN_AP_PS_IDLE_STATE, + GREEN_AP_PS_WAIT_EVENT); + goto done; + } + + adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); + if (adapter == 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(hdd_ctx, + 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(hdd_ctx, + GREEN_AP_PS_WAIT_STATE, + GREEN_AP_PS_WAIT_EVENT); + cdf_mc_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(hdd_ctx, + GREEN_AP_PS_ON_STATE, + GREEN_AP_PS_WAIT_EVENT); + + hdd_wlan_green_ap_enable(adapter, 1); + + if (green_ap->ps_on_time) { + hdd_wlan_green_ap_update(hdd_ctx, + 0, + GREEN_AP_PS_WAIT_EVENT); + cdf_mc_timer_start(&green_ap->ps_timer, + green_ap->ps_on_time); + } + } else { + hdd_wlan_green_ap_update(hdd_ctx, + 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(adapter, 0)) { + hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + goto done; + } + hdd_wlan_green_ap_update(hdd_ctx, + 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(hdd_ctx, + GREEN_AP_PS_WAIT_STATE, + GREEN_AP_PS_ON_EVENT); + + if (hdd_wlan_green_ap_enable(adapter, 0)) { + hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + goto done; + } + + cdf_mc_timer_start(&green_ap->ps_timer, + green_ap->ps_delay_time); + } + break; + + default: + hddLog(LOGE, FL("invalid state %d"), green_ap->ps_state); + hdd_wlan_green_ap_update(hdd_ctx, GREEN_AP_PS_OFF_STATE, + GREEN_AP_PS_WAIT_EVENT); + break; + } + +done: + return; +} + +/** + * hdd_wlan_green_ap_timer_fn() - Green AP Timer handler + * @ctx: Global HDD context + * + * Return: none + */ +static void hdd_wlan_green_ap_timer_fn(void *ctx) +{ + struct hdd_context_s *hdd_ctx = ctx; + struct hdd_green_ap_ctx *green_ap; + + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + + green_ap = hdd_ctx->green_ap_ctx; + if (green_ap) + hdd_wlan_green_ap_mc(hdd_ctx, green_ap->ps_event); +} + +/** + * hdd_wlan_green_ap_attach() - Attach Green AP context to HDD context + * @hdd_ctx: Global HDD contect + * + * Return: CDF_STATUS_SUCCESS on success, otherwise CDF_STATUS_E_* error + */ +static CDF_STATUS hdd_wlan_green_ap_attach(struct hdd_context_s *hdd_ctx) +{ + struct hdd_green_ap_ctx *green_ap; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + ENTER(); + + green_ap = cdf_mem_malloc(sizeof(*green_ap)); + if (!green_ap) { + hddLog(LOGP, FL("Memory allocation for Green-AP failed!")); + status = CDF_STATUS_E_NOMEM; + goto error; + } + + cdf_mem_zero(green_ap, sizeof(*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; + + cdf_mc_timer_init(&green_ap->ps_timer, + CDF_TIMER_TYPE_SW, + hdd_wlan_green_ap_timer_fn, hdd_ctx); + +error: + hdd_ctx->green_ap_ctx = green_ap; + + EXIT(); + return status; +} + +/** + * hdd_wlan_green_ap_deattach() - Detach Green AP context from HDD context + * @hdd_ctx: Global HDD contect + * + * Return: CDF_STATUS_SUCCESS on success, otherwise CDF_STATUS_E_* error + */ +static CDF_STATUS hdd_wlan_green_ap_deattach(struct hdd_context_s *hdd_ctx) +{ + struct hdd_green_ap_ctx *green_ap = hdd_ctx->green_ap_ctx; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + ENTER(); + + if (green_ap == NULL) { + hddLog(LOG1, FL("Green-AP is not enabled")); + status = CDF_STATUS_E_NOSUPPORT; + goto done; + } + + /* check if the timer status is destroyed */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&green_ap->ps_timer)) + cdf_mc_timer_stop(&green_ap->ps_timer); + + /* Destroy the Green AP timer */ + if (!CDF_IS_STATUS_SUCCESS(cdf_mc_timer_destroy(&green_ap->ps_timer))) + hddLog(LOG1, FL("Cannot deallocate Green-AP's timer")); + + /* release memory */ + cdf_mem_zero(green_ap, sizeof(*green_ap)); + cdf_mem_free(green_ap); + hdd_ctx->green_ap_ctx = NULL; + +done: + + EXIT(); + return status; +} + +/** + * hdd_wlan_green_ap_init() - Initialize Green AP feature + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx) +{ + if (!CDF_IS_STATUS_SUCCESS(hdd_wlan_green_ap_attach(hdd_ctx))) + hddLog(LOGE, FL("Failed to allocate Green-AP resource")); +} + +/** + * hdd_wlan_green_ap_deinit() - De-initialize Green AP feature + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_deinit(struct hdd_context_s *hdd_ctx) +{ + if (!CDF_IS_STATUS_SUCCESS(hdd_wlan_green_ap_deattach(hdd_ctx))) + hddLog(LOGE, FL("Cannot deallocate Green-AP resource")); +} + +/** + * hdd_wlan_green_ap_start_bss() - Notify Green AP of Start BSS event + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) +{ + struct hdd_config *cfg = hdd_ctx->config; + + if (!(CDF_STA_MASK & hdd_ctx->concurrency_mode) && + cfg->enable2x2 && cfg->enableGreenAP) { + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_START_EVENT); + } else { + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT); + hddLog(LOG1, + "Green-AP: is disabled, due to sta_concurrency: %d, enable2x2: %d, enableGreenAP: %d", + CDF_STA_MASK & hdd_ctx->concurrency_mode, + cfg->enable2x2, cfg->enableGreenAP); + } +} + +/** + * hdd_wlan_green_ap_stop_bss() - Notify Green AP of Stop BSS event + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_stop_bss(struct hdd_context_s *hdd_ctx) +{ + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT); +} + +/** + * hdd_wlan_green_ap_add_sta() - Notify Green AP of Add Station event + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_add_sta(struct hdd_context_s *hdd_ctx) +{ + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_ADD_STA_EVENT); +} + +/** + * hdd_wlan_green_ap_del_sta() - Notify Green AP of Delete Station event + * @hdd_ctx: HDD global context + * + * Return: none + */ +void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx) +{ + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_DEL_STA_EVENT); +} diff --git a/core/hdd/src/wlan_hdd_green_ap.h b/core/hdd/src/wlan_hdd_green_ap.h new file mode 100644 index 000000000000..8844d71d870b --- /dev/null +++ b/core/hdd/src/wlan_hdd_green_ap.h @@ -0,0 +1,54 @@ +/* + * 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_HDD_GREEN_AP_H +#define __WLAN_HDD_GREEN_AP_H + +/** + * DOC: wlan_hdd_green_ap.h + * + * WLAN Host Device Driver Green AP API specification + */ + +struct hdd_context_s; + +#ifdef FEATURE_GREEN_AP +void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx); +void hdd_wlan_green_ap_deinit(struct hdd_context_s *hdd_ctx); +void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx); +void hdd_wlan_green_ap_stop_bss(struct hdd_context_s *hdd_ctx); +void hdd_wlan_green_ap_add_sta(struct hdd_context_s *hdd_ctx); +void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx); +#else +static inline void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_green_ap_deinit(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_green_ap_stop_bss(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_green_ap_add_sta(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx) {} +#endif /* FEATURE_GREEN_AP */ +#endif /* __WLAN_HDD_GREEN_AP_H */ diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c new file mode 100644 index 000000000000..6024539d8b40 --- /dev/null +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -0,0 +1,8421 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_hostapd.c + * + * WLAN Host Device Driver 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 "wlan_hdd_p2p.h" +#include +#include "cfg_api.h" +#include "wni_cfg.h" +#include "wlan_hdd_misc.h" +#include +#if defined CONFIG_CNSS +#include +#endif + +#include "wma.h" +#ifdef DEBUG +#include "wma_api.h" +#endif +#include "wlan_hdd_trace.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "wlan_hdd_cfg.h" +#include "cds_concurrency.h" +#include "wlan_hdd_green_ap.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 +#define CONNECTION_UPDATE_TIMEOUT 500 + +#define DUMP_DP_TRACE 0 + +/* Function definitions */ + +/** + * hdd_hostapd_channel_wakelock_init() - init the channel wakelock + * @pHddCtx: pointer to hdd context + * + * Return: None + */ +void hdd_hostapd_channel_wakelock_init(hdd_context_t *pHddCtx) +{ + /* Initialize the wakelock */ + cdf_wake_lock_init(&pHddCtx->sap_dfs_wakelock, "sap_dfs_wakelock"); + atomic_set(&pHddCtx->sap_dfs_ref_cnt, 0); +} + +/** + * hdd_hostapd_channel_allow_suspend() - allow suspend in a channel. + * Called when, 1. bss stopped, 2. channel switch + * + * @pAdapter: pointer to hdd adapter + * @channel: current channel + * + * Return: None + */ +void hdd_hostapd_channel_allow_suspend(hdd_adapter_t *pAdapter, + uint8_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 (CHANNEL_STATE_DFS == cds_get_channel_state(channel)) { + if (atomic_dec_and_test(&pHddCtx->sap_dfs_ref_cnt)) { + hddLog(LOGE, FL("DFS: allowing suspend (chan %d)"), + channel); + cdf_wake_lock_release(&pHddCtx->sap_dfs_wakelock, + WIFI_POWER_EVENT_WAKELOCK_DFS); + } + } +} + +/** + * hdd_hostapd_channel_prevent_suspend() - prevent suspend in a channel. + * Called when, 1. bss started, 2. channel switch + * + * @pAdapter: pointer to hdd adapter + * @channel: current channel + * + * Return - None + */ +void hdd_hostapd_channel_prevent_suspend(hdd_adapter_t *pAdapter, + uint8_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 (CHANNEL_STATE_DFS == cds_get_channel_state(channel)) { + if (atomic_inc_return(&pHddCtx->sap_dfs_ref_cnt) == 1) { + hddLog(LOGE, FL("DFS: preventing suspend (chan %d)"), + channel); + cdf_wake_lock_acquire(&pHddCtx->sap_dfs_wakelock, + WIFI_POWER_EVENT_WAKELOCK_DFS); + } + } +} + +/** + * hdd_hostapd_channel_wakelock_deinit() - destroy the channel wakelock + * + * @pHddCtx: 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 */ + cdf_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 */ + cdf_wake_lock_destroy(&pHddCtx->sap_dfs_wakelock); +} + +/** + * __hdd_hostapd_open() - hdd open function for hostapd interface + * This is called in response to ifconfig up + * @dev: pointer to net_device structure + * + * Return - 0 for success non-zero for failure + */ +static int __hdd_hostapd_open(struct net_device *dev) +{ + hdd_adapter_t *pAdapter = netdev_priv(dev); + + ENTER(); + + MTRACE(cdf_trace(CDF_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; + } + /* Enable all Tx queues */ + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); +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; + + cds_ssr_protect(__func__); + ret = __hdd_hostapd_open(dev); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_hostapd_stop() - hdd stop function for hostapd interface + * This is called in response to ifconfig down + * + * @dev: pointer to net_device structure + * + * Return - 0 for success non-zero for failure + */ +static int __hdd_hostapd_stop(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + ENTER(); + + /* Stop all tx queues */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + 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; + + cds_ssr_protect(__func__); + ret = __hdd_hostapd_stop(dev); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_hostapd_uninit() - hdd uninit function + * This is called during the netdev unregister to uninitialize all data + * associated with the device. + * + * @dev: pointer to net_device structure + * + * Return: None + */ +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) +{ + cds_ssr_protect(__func__); + __hdd_hostapd_uninit(dev); + cds_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; + + cds_ssr_protect(__func__); + ret = __hdd_hostapd_change_mtu(dev, new_mtu); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef QCA_HT_2040_COEX +CDF_STATUS hdd_set_sap_ht2040_mode(hdd_adapter_t *pHostapdAdapter, + uint8_t channel_type) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + + hddLog(LOGE, FL("change HT20/40 mode")); + + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if (NULL == hHal) { + hddLog(LOGE, FL("Hal ctx is null")); + return CDF_STATUS_E_FAULT; + } + cdf_ret_status = + sme_set_ht2040_mode(hHal, pHostapdAdapter->sessionId, + channel_type, true); + if (cdf_ret_status == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, FL("Failed to change HT20/40 mode")); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} +#endif + +/** + * __hdd_hostapd_set_mac_address() - + * This function sets the user specified mac address using + * the command ifconfig wlanX hw ether . + * + * @dev: pointer to the net device. + * @addr: pointer to the sockaddr. + * + * Return: 0 for success, non zero for failure + */ +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; + + cds_ssr_protect(__func__); + ret = __hdd_hostapd_set_mac_address(dev, addr); + cds_ssr_unprotect(__func__); + + return ret; +} + +void hdd_hostapd_inactivity_timer_cb(void *usrDataForCallback) +{ + struct net_device *dev = (struct net_device *)usrDataForCallback; + uint8_t we_custom_event[64]; + union iwreq_data wrqu; +#ifdef DISABLE_CONCURRENCY_AUTOSAVE + CDF_STATUS cdf_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; + + /* For the NULL at the end */ + int event_len = strlen(autoShutEvent) + 1; + + ENTER(); + +#ifdef DISABLE_CONCURRENCY_AUTOSAVE + if (cds_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); + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + cdf_status = + cdf_mc_timer_start(&pHddApCtx->hdd_ap_inactivity_timer, + (WLAN_HDD_GET_CTX(pHostapdAdapter))-> + config->nAPAutoShutOff * 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_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(); +} + +void hdd_clear_all_sta(hdd_adapter_t *pHostapdAdapter, + void *usrDataForCallback) +{ + uint8_t staId = 0; + struct net_device *dev; + 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)) { + /* Disconnect all the stations */ + hdd_softap_sta_disassoc(pHostapdAdapter, + &pHostapdAdapter-> + aStaInfo[staId].macAddrSTA. + bytes[0]); + } + } +} + +static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter, + void *usrDataForCallback) +{ + struct net_device *dev; + hdd_context_t *pHddCtx = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + dev = (struct net_device *)usrDataForCallback; + ENTER(); + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { +#ifdef WLAN_FEATURE_MBSSID + status = + wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR( + pHostapdAdapter)); +#else + status = + wlansap_stop_bss((WLAN_HDD_GET_CTX(pHostapdAdapter))-> + pcds_context); +#endif + if (CDF_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Deleting SAP/P2P link!!!!!!")); + + clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + cds_decr_session_set_pcl(pHddCtx, + pHostapdAdapter->device_mode, + pHostapdAdapter->sessionId); + } + EXIT(); + return (status == CDF_STATUS_SUCCESS) ? 0 : -EBUSY; +} + +/** + * hdd_issue_stored_joinreq() - This function will trigger stations's + * cached connect request to proceed. + * @hdd_ctx: pointer to hdd context. + * @sta_adater: pointer to station adapter. + * + * This function will call SME to release station's stored/cached connect + * request to proceed. + * + * Return: none. + */ +static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, + hdd_context_t *hdd_ctx) +{ + tHalHandle hal_handle; + uint32_t roam_id; + + if (NULL == sta_adapter) { + hddLog(LOGE, + FL + ("Invalid station adapter, ignore issueing join req")); + return; + } + hal_handle = WLAN_HDD_GET_HAL_CTX(sta_adapter); + + if (true == cds_is_sta_connection_pending(hdd_ctx)) { + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_ISSUE_JOIN_REQ, + sta_adapter->sessionId, roam_id)); + if (CDF_STATUS_SUCCESS != + sme_issue_stored_joinreq(hal_handle, + &roam_id, + sta_adapter->sessionId)) { + /* change back to NotAssociated */ + hdd_conn_set_connection_state(sta_adapter, + eConnectionState_NotConnected); + } + cds_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 + * + */ +CDF_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) { + hdd_err("hal is NULL"); + return CDF_STATUS_E_FAILURE; + } + + freq = cds_chan_to_freq(oper_chan); + + chan = __ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq); + + if (!chan) { + hdd_err("Invalid input frequency for channel conversion"); + return CDF_STATUS_E_FAILURE; + } + + phy_mode = sme_get_phy_mode(hal); + + if (oper_chan <= 14) + cb_mode = sme_get_cb_phy_state_from_cb_ini_value( + sme_get_channel_bonding_mode24_g(hal)); + else + cb_mode = sme_get_cb_phy_state_from_cb_ini_value( + sme_get_channel_bonding_mode5_g(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; + } + + cfg80211_chandef_create(&chandef, chan, channel_type); + + cfg80211_ch_switch_notify(dev, &chandef); + + return CDF_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 + * + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + + freq = cds_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 CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, + void *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; + uint8_t *we_custom_event_generic = NULL; + int we_event = 0; + int i = 0; + uint8_t staId; + CDF_STATUS cdf_status; + bool bWPSState; + bool bAuthRequired = true; + tpSap_AssocMacAddr pAssocStasArray = NULL; + char unknownSTAEvent[IW_CUSTOM_MAX + 1]; + char maxAssocExceededEvent[IW_CUSTOM_MAX + 1]; + uint8_t we_custom_start_event[64]; + char *startBssEvent; + hdd_context_t *pHddCtx; + hdd_scaninfo_t *pScanInfo = NULL; + struct iw_michaelmicfailure msg; + uint8_t ignoreCAC = 0; + struct hdd_config *cfg = NULL; + struct wlan_dfs_info dfs_info; + uint8_t cc_len = WLAN_SVC_COUNTRY_CODE_LEN; + hdd_adapter_t *con_sap_adapter; + CDF_STATUS status = CDF_STATUS_SUCCESS; +#if defined CONFIG_CNSS + int ret = 0; +#endif + + dev = (struct net_device *)usrDataForCallback; + if (!dev) { + hddLog(LOGE, FL("usrDataForCallback is null")); + return CDF_STATUS_E_FAILURE; + } + + pHostapdAdapter = netdev_priv(dev); + + if ((NULL == pHostapdAdapter) || + (WLAN_HDD_ADAPTER_MAGIC != pHostapdAdapter->magic)) { + hddLog(LOGE, "invalid adapter or adapter has invalid magic"); + return CDF_STATUS_E_FAILURE; + } + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + + if (!pSapEvent) { + hddLog(LOGE, FL("pSapEvent is null")); + return CDF_STATUS_E_FAILURE; + } + + sapEvent = pSapEvent->sapHddEventCode; + memset(&wrqu, '\0', sizeof(wrqu)); + pHddCtx = (hdd_context_t *) (pHostapdAdapter->pHddCtx); + + if (!pHddCtx) { + hddLog(LOGE, FL("HDD context is null")); + return CDF_STATUS_E_FAILURE; + } + + cfg = pHddCtx->config; + + if (!cfg) { + hddLog(LOGE, FL("HDD config is null")); + return CDF_STATUS_E_FAILURE; + } + + dfs_info.channel = pHddApCtx->operatingChannel; + sme_get_country_code(pHddCtx->hHal, dfs_info.country_code, &cc_len); + + switch (sapEvent) { + case eSAP_START_BSS_EVENT: + hddLog(LOG1, + FL("BSS 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->cdf_status = + pSapEvent->sapevt.sapStartBssCompleteEvent.status; + cdf_status = cdf_event_set(&pHostapdState->cdf_event); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status) + || pHostapdState->cdf_status) { + hddLog(LOGE, ("ERROR: startbss event failed!!")); + goto stopbss; + } else { + sme_ch_avoid_update_req(pHddCtx->hHal); + + pHddApCtx->uBCStaId = + pSapEvent->sapevt.sapStartBssCompleteEvent.staId; + + hdd_register_tx_flow_control(pHostapdAdapter, + hdd_softap_tx_resume_timer_expired_handler, + hdd_softap_tx_resume_cb); + + /* @@@ need wep logic here to set privacy bit */ + cdf_status = + hdd_softap_register_bc_sta(pHostapdAdapter, + pHddApCtx->uPrivacy); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGW, FL("Failed to register BC STA %d"), + cdf_status); + hdd_stop_bss_link(pHostapdAdapter, + usrDataForCallback); + } + } + + if (hdd_ipa_is_enabled(pHddCtx)) { + status = hdd_ipa_wlan_evt(pHostapdAdapter, + pHddApCtx->uBCStaId, + WLAN_AP_CONNECT, + pHostapdAdapter->dev->dev_addr); + if (status) { + hddLog(LOGE, + ("WLAN_AP_CONNECT event failed!!")); + goto stopbss; + } + } + + if (0 != + (WLAN_HDD_GET_CTX(pHostapdAdapter))->config-> + nAPAutoShutOff) { + /* AP Inactivity timer init and start */ + cdf_status = + cdf_mc_timer_init(&pHddApCtx-> + hdd_ap_inactivity_timer, + CDF_TIMER_TYPE_SW, + hdd_hostapd_inactivity_timer_cb, + dev); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, + FL("Failed to init inactivity timer")); + + cdf_status = + cdf_mc_timer_start(&pHddApCtx-> + hdd_ap_inactivity_timer, + (WLAN_HDD_GET_CTX + (pHostapdAdapter))->config-> + nAPAutoShutOff * 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, + FL("Failed to init inactivity timer")); + + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, true); +#endif + pHddApCtx->operatingChannel = + pSapEvent->sapevt.sapStartBssCompleteEvent.operatingChannel; + + hdd_hostapd_channel_prevent_suspend(pHostapdAdapter, + pHddApCtx-> + operatingChannel); + + pHostapdState->bssState = BSS_START; + hdd_wlan_green_ap_start_bss(pHddCtx); + + /* Set group key / WEP key every time when BSS is restarted */ + if (pHddApCtx->groupKey.keyLength) { + status = wlansap_set_key_sta( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + (WLAN_HDD_GET_CTX + (pHostapdAdapter))-> + pcds_context, +#endif + &pHddApCtx->groupKey); + if (!CDF_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("wlansap_set_key_sta failed")); + } else { + for (i = 0; i < CSR_MAX_NUM_KEY; i++) { + if (!pHddApCtx->wepKey[i].keyLength) + continue; + + status = wlansap_set_key_sta( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + (WLAN_HDD_GET_CTX(pHostapdAdapter))-> + pcds_context, +#endif + &pHddApCtx-> + wepKey[i]); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("set_key failed idx %d"), i); + } + } + } + + pHddCtx->dfs_radar_found = false; + wlansap_get_dfs_ignore_cac(pHddCtx->hHal, &ignoreCAC); + + /* DFS requirement: DO NOT transmit during CAC. */ + if ((CHANNEL_STATE_DFS != + cds_get_channel_state(pHddApCtx->operatingChannel)) + || ignoreCAC + || pHddCtx->dev_dfs_cac_status == DFS_CAC_ALREADY_DONE) + pHddApCtx->dfs_cac_block_tx = false; + else + pHddApCtx->dfs_cac_block_tx = true; + + hddLog(LOG3, "The value of dfs_cac_block_tx[%d] for ApCtx[%p]", + pHddApCtx->dfs_cac_block_tx, pHddApCtx); + + if ((CHANNEL_STATE_DFS == + cds_get_channel_state(pHddApCtx->operatingChannel)) + && (pHddCtx->config->IsSapDfsChSifsBurstEnabled == 0)) { + + hddLog(LOG1, + FL("Set SIFS Burst disable for DFS channel %d"), + pHddApCtx->operatingChannel); + + if (wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_PDEV_PARAM_BURST_ENABLE, + 0, PDEV_CMD)) { + hddLog(LOGE, + FL("Failed to Set SIFS Burst %d"), + 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; + cds_dump_concurrency_info(pHddCtx); + /* Send SCC/MCC Switching event to IPA */ + hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); + 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_hostapd_channel_allow_suspend(pHostapdAdapter, + pHddApCtx->operatingChannel); + + hdd_wlan_green_ap_stop_bss(pHddCtx); + + /* Free up Channel List incase if it is set */ +#ifdef WLAN_FEATURE_MBSSID + sap_cleanup_channel_list(WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter)); +#else + sap_cleanup_channel_list(); +#endif + /* Invalidate the channel info. */ + pHddApCtx->operatingChannel = 0; + if (hdd_ipa_is_enabled(pHddCtx)) { + status = hdd_ipa_wlan_evt(pHostapdAdapter, + pHddApCtx->uBCStaId, + WLAN_AP_DISCONNECT, + pHostapdAdapter->dev->dev_addr); + if (status) { + hddLog(LOGE, + ("WLAN_AP_DISCONNECT event failed!!")); + goto stopbss; + } + } + + /* 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->config->conc_custom_rule2 && + (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) { + hdd_adapter_t *sta_adapter = hdd_get_adapter(pHddCtx, + WLAN_HDD_INFRA_STATION); + hddLog(LOG2, + 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 (CDF_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 { + hdd_info("Sent CAC start to user space"); + } + 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 (CDF_STATUS_SUCCESS != + hdd_send_radar_event(pHddCtx, eSAP_DFS_CAC_END, + dfs_info, &pHostapdAdapter->wdev)) { + hdd_err("Unable to indicate CAC end (interrupted) event"); + } else { + hdd_info("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 = false; + pHddCtx->dev_dfs_cac_status = DFS_CAC_ALREADY_DONE; + if (CDF_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 { + hdd_info("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 (CDF_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 { + hdd_info("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 CDF_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, CDF_MAC_ADDR_SIZE); + 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 = (uint8_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, CDF_MAC_ADDR_SIZE); + 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))-> + pcds_context, &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 == true) { + cdf_status = hdd_softap_register_sta( + pHostapdAdapter, + true, + pHddApCtx->uPrivacy, + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + staId, 0, 0, + (struct cdf_mac_addr *) + wrqu.addr.sa_data, + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + wmmEnabled); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGW, + FL("Failed to register STA %d " + MAC_ADDRESS_STR ""), cdf_status, + MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + } else { + cdf_status = hdd_softap_register_sta( + pHostapdAdapter, + false, + pHddApCtx->uPrivacy, + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + staId, 0, 0, + (struct cdf_mac_addr *) + wrqu.addr.sa_data, + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + wmmEnabled); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGW, + FL("Failed to register STA %d " + MAC_ADDRESS_STR ""), cdf_status, + MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + } + + 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) { + hddLog(LOGE, + FL("WLAN_CLIENT_CONNECT_EX event failed")); + goto stopbss; + } + } + +#ifdef QCA_PKT_PROTO_TRACE + /* Peer associated, update into trace buffer */ + if (pHddCtx->config->gEnableDebugLog) { + cds_pkt_trace_buf_update("HA:ASSOC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef MSM_PLATFORM + /* start timer in sap/p2p_go */ + if (pHddApCtx->bApActive == 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 = true; + /* Stop AP inactivity timer */ + if (pHddApCtx->hdd_ap_inactivity_timer.state == + CDF_TIMER_STATE_RUNNING) { + cdf_status = + cdf_mc_timer_stop(&pHddApCtx-> + hdd_ap_inactivity_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, + FL("Failed to start inactivity timer")); + } + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, false); +#endif + cdf_wake_lock_timeout_acquire(&pHddCtx->sap_wake_lock, + HDD_SAP_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_SAP); + { + struct station_info staInfo; + uint16_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)) + 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_send_peer_status_ind_to_oem_app(&pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + staMac, ePeerConnected, + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + timingMeasCap, + pHostapdAdapter-> + sessionId, + &pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + chan_info); + } + hdd_wlan_green_ap_add_sta(pHddCtx); + break; + + case eSAP_STA_DISASSOC_EVENT: + memcpy(wrqu.addr.sa_data, + &pSapEvent->sapevt.sapStationDisassocCompleteEvent. + staMac, CDF_MAC_ADDR_SIZE); + hddLog(LOG1, " disassociated " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(wrqu.addr.sa_data)); + + cdf_status = cdf_event_set(&pHostapdState->cdf_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, "ERR: Station Deauth event Set failed"); + + if (pSapEvent->sapevt.sapStationDisassocCompleteEvent.reason == + eSAP_USR_INITATED_DISASSOC) + hddLog(LOG1, " User initiated disassociation"); + else + hddLog(LOG1, " MAC initiated disassociation"); + we_event = IWEVEXPIRED; + cdf_status = + hdd_softap_get_sta_id(pHostapdAdapter, + &pSapEvent->sapevt. + sapStationDisassocCompleteEvent.staMac, + &staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("ERROR: HDD Failed to find sta id!!")); + return CDF_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) { + hddLog(LOGE, + ("ERROR: WLAN_CLIENT_DISCONNECT event failed!!")); + goto stopbss; + } + } +#endif +#ifdef QCA_PKT_PROTO_TRACE + /* Peer dis-associated, update into trace buffer */ + if (pHddCtx->config->gEnableDebugLog) { + cds_pkt_trace_buf_update("HA:DISASC"); + } +#endif /* QCA_PKT_PROTO_TRACE */ + hdd_softap_deregister_sta(pHostapdAdapter, staId); + + pHddApCtx->bApActive = 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 = 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))->config-> + nAPAutoShutOff)) { + if (pHddApCtx->bApActive == false) { + if (pHddApCtx->hdd_ap_inactivity_timer.state == + CDF_TIMER_STATE_STOPPED) { + cdf_status = + cdf_mc_timer_start(&pHddApCtx-> + hdd_ap_inactivity_timer, + (WLAN_HDD_GET_CTX + (pHostapdAdapter))-> + config-> + nAPAutoShutOff * + 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, + FL("Failed to init AP inactivity timer")); + } else + CDF_ASSERT + (cdf_mc_timer_get_current_state + (&pHddApCtx-> + hdd_ap_inactivity_timer) == + CDF_TIMER_STATE_STOPPED); + } + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, true); +#endif + + cfg80211_del_sta(dev, + (const u8 *)&pSapEvent->sapevt. + sapStationDisassocCompleteEvent.staMac. + bytes[0], GFP_KERNEL); + + /* Update the beacon Interval if it is P2P GO */ + cdf_status = cds_change_mcc_go_beacon_interval(pHostapdAdapter); + if (CDF_STATUS_SUCCESS != cdf_status) { + hddLog(LOGE, FL("failed to update Beacon interval %d"), + cdf_status); + } + if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) { + /* send peer status indication to oem app */ + hdd_send_peer_status_ind_to_oem_app(&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 + hdd_wlan_green_ap_del_sta(pHddCtx); + 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; + + cdf_mem_copy(pHddApCtx->WPSPBCProbeReq.probeReqIE, + pSapEvent->sapevt.sapPBCProbeReqEvent. + WPSPBCProbeReq.probeReqIE, + pHddApCtx->WPSPBCProbeReq.probeReqIELen); + + cdf_mem_copy(pHddApCtx->WPSPBCProbeReq.peerMacAddr, + pSapEvent->sapevt.sapPBCProbeReqEvent. + WPSPBCProbeReq.peerMacAddr, + CDF_MAC_ADDR_SIZE); + 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 CDF_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++; + } + } + cdf_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas); /* Release caller allocated memory here */ + pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas = NULL; + return CDF_STATUS_SUCCESS; + case eSAP_INDICATE_MGMT_FRAME: + hdd_indicate_mgmt_frame(pHostapdAdapter, + pSapEvent->sapevt.sapManagementFrameInfo. + nFrameLength, + pSapEvent->sapevt.sapManagementFrameInfo. + pbFrames, + pSapEvent->sapevt.sapManagementFrameInfo. + frameType, + pSapEvent->sapevt.sapManagementFrameInfo. + rxChan, 0); + return CDF_STATUS_SUCCESS; + case eSAP_REMAIN_CHAN_READY: + hdd_remain_chan_ready_handler(pHostapdAdapter, + pSapEvent->sapevt.sap_roc_ind.scan_id); + return CDF_STATUS_SUCCESS; + case eSAP_SEND_ACTION_CNF: + hdd_send_action_cnf(pHostapdAdapter, + (eSAP_STATUS_SUCCESS == + pSapEvent->sapevt.sapActionCnf. + actionSendSuccess) ? true : false); + return CDF_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 = (uint8_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 = (uint8_t *) maxAssocExceededEvent; + hddLog(LOG1, "%s", maxAssocExceededEvent); + break; + case eSAP_STA_ASSOC_IND: + return CDF_STATUS_SUCCESS; + + case eSAP_DISCONNECT_ALL_P2P_CLIENT: + hddLog(LOG1, FL(" Disconnecting all the P2P Clients....")); + hdd_clear_all_sta(pHostapdAdapter, usrDataForCallback); + return CDF_STATUS_SUCCESS; + + case eSAP_MAC_TRIG_STOP_BSS_EVENT: + cdf_status = + hdd_stop_bss_link(pHostapdAdapter, usrDataForCallback); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGW, FL("hdd_stop_bss_link failed %d"), + cdf_status); + } + return CDF_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.sap_ch_selected.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.sap_ch_selected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.pri_ch = + pSapEvent->sapevt.sap_ch_selected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.ht_sec_ch = + pSapEvent->sapevt.sap_ch_selected.ht_sec_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg0_center_ch = + pSapEvent->sapevt.sap_ch_selected.vht_seg0_center_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg1_center_ch = + pSapEvent->sapevt.sap_ch_selected.vht_seg1_center_ch; + pHddApCtx->sapConfig.acs_cfg.ch_width = + pSapEvent->sapevt.sap_ch_selected.ch_width; + + /* Indicate operating channel change to hostapd + * only for non driver override acs + */ + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP && + pHddCtx->config->force_sap_acs) + return CDF_STATUS_SUCCESS; + else + return hdd_chan_change_notify(pHostapdAdapter, dev, + pSapEvent->sapevt.sap_ch_selected.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); + cdf_mc_timer_stop(&pHddCtx->skip_acs_scan_timer); + cdf_status = cdf_mc_timer_start(&pHddCtx->skip_acs_scan_timer, + ACS_SCAN_EXPIRY_TIMEOUT_S * + 1000); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, + FL("Failed to start ACS scan expiry timer")); + return CDF_STATUS_SUCCESS; +#endif + + case eSAP_DFS_NOL_GET: + hddLog(LOG1, + 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(LOG2, + FL("Get %d bytes of dfs nol from cnss"), ret); + return CDF_STATUS_SUCCESS; + } else { + hddLog(LOG2, + FL("No dfs nol entry in CNSS, ret: %d"), ret); + return CDF_STATUS_E_FAULT; + } +#else + return CDF_STATUS_E_FAILURE; +#endif + case eSAP_DFS_NOL_SET: + hddLog(LOG1, 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(LOG2, + FL("Failed to set dfs nol - ret: %d"), + ret); + } else { + hddLog(LOG2, FL(" Set %d bytes dfs nol to cnss"), + pSapEvent->sapevt.sapDfsNolInfo.sDfsList); + } +#else + return CDF_STATUS_E_FAILURE; +#endif + return CDF_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.sap_ch_selected.pri_ch; + pHddApCtx->sapConfig.acs_cfg.ht_sec_ch = + pSapEvent->sapevt.sap_ch_selected.ht_sec_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg0_center_ch = + pSapEvent->sapevt.sap_ch_selected.vht_seg0_center_ch; + pHddApCtx->sapConfig.acs_cfg.vht_seg1_center_ch = + pSapEvent->sapevt.sap_ch_selected.vht_seg1_center_ch; + pHddApCtx->sapConfig.acs_cfg.ch_width = + pSapEvent->sapevt.sap_ch_selected.ch_width; + /* send vendor event to hostapd only for hostapd based acs*/ + if (!pHddCtx->config->force_sap_acs) + wlan_hdd_cfg80211_acs_ch_select_evt(pHostapdAdapter); + return CDF_STATUS_SUCCESS; + default: + hddLog(LOG1, "SAP message is not handled"); + goto stopbss; + return CDF_STATUS_SUCCESS; + } + wireless_send_event(dev, we_event, &wrqu, + (char *)we_custom_event_generic); + return CDF_STATUS_SUCCESS; + +stopbss: + { + uint8_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))->config-> + nAPAutoShutOff) { + if (CDF_TIMER_STATE_RUNNING == + pHddApCtx->hdd_ap_inactivity_timer.state) { + cdf_status = + cdf_mc_timer_stop(&pHddApCtx-> + hdd_ap_inactivity_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, + FL("Failed to stop AP inactivity timer")); + } + } + + cdf_status = + cdf_mc_timer_destroy(&pHddApCtx-> + hdd_ap_inactivity_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, FL("Failed to Destroy AP inactivity timer")); + } +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + wlan_hdd_auto_shutdown_enable(pHddCtx, 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 */ + cdf_status = hdd_softap_stop_bss(pHostapdAdapter); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGW, + FL("hdd_softap_stop_bss failed %d"), + cdf_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) + cdf_event_set(&pHostapdState->cdf_stop_bss_event); + + /* notify userspace 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); + cds_dump_concurrency_info(pHddCtx); + /* Send SCC/MCC Switching event to IPA */ + hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); + } + return CDF_STATUS_SUCCESS; +} + +int hdd_softap_unpack_ie(tHalHandle halHandle, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, + bool *pMFPCapable, + bool *pMFPRequired, + uint16_t gen_ie_len, uint8_t *gen_ie) +{ + tDot11fIERSN dot11RSNIE; + tDot11fIEWPA dot11WPAIE; + + uint8_t *pRsnIe; + uint16_t RSNIeLen; + + if (NULL == halHandle) { + hddLog(LOGE, FL("Error haHandle returned NULL")); + return -EINVAL; + } + /* Validity checks */ + if ((gen_ie_len < CDF_MIN(DOT11F_IE_RSN_MIN_LEN, DOT11F_IE_WPA_MIN_LEN)) + || (gen_ie_len > + CDF_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 CDF_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)); + dot11f_unpack_ie_rsn((tpAniSirGlobal) halHandle, + pRsnIe, RSNIeLen, &dot11RSNIE); + /* Copy out the encryption and authentication types */ + hddLog(LOG1, FL("pairwise cipher suite count: %d"), + dot11RSNIE.pwise_cipher_suite_count); + hddLog(LOG1, FL("authentication suite count: %d"), + 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_translate_rsn_to_csr_auth_type(dot11RSNIE.akm_suites[0]); + /* dot11RSNIE.pwise_cipher_suite_count */ + *pEncryptType = + hdd_translate_rsn_to_csr_encryption_type(dot11RSNIE. + pwise_cipher_suites[0]); + /* dot11RSNIE.gp_cipher_suite_count */ + *mcEncryptType = + hdd_translate_rsn_to_csr_encryption_type(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 csr_roam_set_pmkid_cache 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 CDF_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)); + dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle, + pRsnIe, RSNIeLen, &dot11WPAIE); + /* Copy out the encryption and authentication types */ + hddLog(LOG1, FL("WPA unicast cipher suite count: %d"), + dot11WPAIE.unicast_cipher_count); + hddLog(LOG1, FL("WPA authentication suite count: %d"), + dot11WPAIE.auth_suite_count); + /* dot11WPAIE.auth_suite_count */ + /* Just translate the FIRST one */ + *pAuthType = + hdd_translate_wpa_to_csr_auth_type(dot11WPAIE.auth_suites[0]); + /* dot11WPAIE.unicast_cipher_count */ + *pEncryptType = + hdd_translate_wpa_to_csr_encryption_type(dot11WPAIE. + unicast_ciphers[0]); + /* dot11WPAIE.unicast_cipher_count */ + *mcEncryptType = + hdd_translate_wpa_to_csr_encryption_type(dot11WPAIE. + multicast_cipher); + *pMFPCapable = false; + *pMFPRequired = false; + } else { + hddLog(LOGW, FL("gen_ie[0]: %d"), gen_ie[0]); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_softap_set_channel_change() - + * This function to support SAP channel change with CSA IE + * set in the beacons. + * + * @dev: pointer to the net device. + * @target_channel: target channel number. + * + * Return: 0 for success, non zero for failure + */ +static +int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) +{ + CDF_STATUS status; + int ret = 0; + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx = NULL; + +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = + (WLAN_HDD_GET_CTX(pHostapdAdapter))->pcds_context; +#endif + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret) { + hddLog(LOGE, FL("invalid HDD context")); + ret = -EBUSY; + return ret; + } + + if (pHddCtx->dfs_radar_found == true) { + hddLog(LOGE, FL("Channel switch in progress!!")); + return -EBUSY; + } + /* + * 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 = true; + + /* + * Post the Channel Change request to SAP. + */ + status = wlansap_set_channel_change_with_csa( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + p_cds_context, +#endif + (uint32_t) + target_channel); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("SAP set channel failed for channel = %d"), + target_channel); + /* + * If channel change command fails then clear the + * radar found flag and also restart the netif + * queues. + */ + + pHddCtx->dfs_radar_found = false; + + 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) +{ + CDF_STATUS vstatus; + int ret = 0; /* success */ + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx; + + if (pAdapter == NULL) { + hddLog(LOGE, FL("pAdapter is NULL!")); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (ret != 0) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + hddLog(LOG1, FL("Received data %s"), extra); + + vstatus = hdd_execute_global_config_command(pHddCtx, extra); + if (CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_softap_set_ini_cfg(dev, info, wrqu, extra); + cds_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + hddLog(LOG1, FL("Printing CLD global INI Config")); + 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_get_ini_cfg(dev, info, wrqu, extra); + cds_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) { + hddLog(LOGE, FL("HDD context is not valid!")); + 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]); + ret = wma_cli_set2_command(pAdapter->sessionId, + GEN_PARAM_CRASH_INJECT, + value[1], value[2], + GEN_CMD); + break; +#endif + case QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL: + hdd_info("WE_DUMP_DP_TRACE: %d %d", + value[1], value[2]); + if (value[1] == DUMP_DP_TRACE) + cdf_dp_trace_dump_all(value[2]); + break; + default: + hddLog(LOGE, FL("Invalid IOCTL command %d"), 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_set_two_ints_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +static void print_mac_list(struct cdf_mac_addr *macList, uint8_t size) +{ + int i; + uint8_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 CDF_STATUS hdd_print_acl(hdd_adapter_t *pHostapdAdapter) +{ + eSapMacAddrACL acl_mode; + struct cdf_mac_addr MacList[MAX_ACL_MAC_ADDRESS]; + uint8_t listnum; + void *p_cds_gctx = NULL; + +#ifdef WLAN_FEATURE_MBSSID + p_cds_gctx = WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter); +#else + p_cds_gctx = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pcds_context; +#endif + cdf_mem_zero(&MacList[0], sizeof(MacList)); + if (CDF_STATUS_SUCCESS == wlansap_get_acl_mode(p_cds_gctx, &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 CDF_STATUS_E_FAILURE; + } + } else { + return CDF_STATUS_E_FAILURE; + } + + if (CDF_STATUS_SUCCESS == wlansap_get_acl_accept_list(p_cds_gctx, + &MacList[0], + &listnum)) { + pr_info("******* WHITE LIST ***********\n"); + if (listnum <= MAX_ACL_MAC_ADDRESS) + print_mac_list(&MacList[0], listnum); + } else { + return CDF_STATUS_E_FAILURE; + } + + if (CDF_STATUS_SUCCESS == wlansap_get_acl_deny_list(p_cds_gctx, + &MacList[0], + &listnum)) { + pr_info("******* BLACK LIST ***********\n"); + if (listnum <= MAX_ACL_MAC_ADDRESS) + print_mac_list(&MacList[0], listnum); + } else { + return CDF_STATUS_E_FAILURE; + } + return CDF_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]; + CDF_STATUS status; + int ret = 0; /* success */ + v_CONTEXT_t p_cds_context; + hdd_context_t *hdd_ctx; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid ret:%d"), ret); + return -EINVAL; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + if (!hHal) { + hddLog(LOGE, FL("Hal ctx is null")); + return -EINVAL; + } + + p_cds_context = hdd_ctx->pcds_context; + if (!p_cds_context) { + hddLog(LOGE, FL("cds ctx is null")); + return -ENOENT; + } + + switch (sub_cmd) { + case QCASAP_SET_RADAR_DBG: + hddLog(LOG1, FL("QCASAP_SET_RADAR_DBG called with: value: %d"), + set_value); + wlan_sap_enable_phy_error_logs(hHal, (bool) set_value); + break; + + case QCSAP_PARAM_CLR_ACL: + if (CDF_STATUS_SUCCESS != wlansap_clear_acl( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter) +#else + p_cds_context +#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_set_mode(WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), set_value); +#else + wlansap_set_mode(p_cds_context, set_value); +#endif + + } + break; + + case QCSAP_PARAM_SET_CHANNEL_CHANGE: + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + hddLog(LOG1, + "SET SAP 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_AUTO_CHANNEL: + if (set_value == 0 || set_value == 1) + (WLAN_HDD_GET_CTX( + pHostapdAdapter))->config->force_sap_acs = + set_value; + else + 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 %d > max allowed %d."), + set_value, + WNI_CFG_ASSOC_STA_LIMIT_STAMAX); + hddLog(LOGW, + FL("Setting it to max allowed and continuing")); + set_value = WNI_CFG_ASSOC_STA_LIMIT_STAMAX; + } + status = sme_cfg_set_int(hHal, WNI_CFG_ASSOC_STA_LIMIT, + set_value); + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, + FL("setMaxAssoc failure, status %d"), + status); + ret = -EIO; + } + } + break; + + case QCSAP_PARAM_HIDE_SSID: + { + CDF_STATUS status = CDF_STATUS_SUCCESS; + status = + sme_hide_ssid(hHal, pHostapdAdapter->sessionId, + set_value); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("QCSAP_PARAM_HIDE_SSID failed")); + return status; + } + break; + } + case QCSAP_PARAM_SET_MC_RATE: + { + tSirRateUpdateInd rateUpdate = {0}; + struct hdd_config *pConfig = hdd_ctx->config; + + hddLog(LOG1, "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; + status = sme_send_rate_update_ind(hHal, &rateUpdate); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("SET_MC_RATE failed")); + ret = -1; + } + break; + } + + case QCSAP_PARAM_SET_TXRX_FW_STATS: + { + hddLog(LOG1, "QCSAP_PARAM_SET_TXRX_FW_STATS val %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_DBGLOG_MOD_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case QCSAP_DBGLOG_TYPE: + { + hddLog(LOG1, "QCSAP_DBGLOG_TYPE val %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_DBGLOG_TYPE, + set_value, DBG_CMD); + break; + } + case QCSAP_DBGLOG_REPORT_ENABLE: + { + hddLog(LOG1, "QCSAP_DBGLOG_REPORT_ENABLE val %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_DBGLOG_REPORT_ENABLE, + set_value, DBG_CMD); + break; + } + case QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY: + { + cds_set_mcc_latency(pHostapdAdapter, set_value); + break; + } + + case QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA: + { + hddLog(LOG1, + FL("iwpriv cmd to set MCC quota value %dms"), + set_value); + ret = cds_go_set_mcc_p2p_quota(pHostapdAdapter, + set_value); + break; + } + + case QCASAP_TXRX_FWSTATS_RESET: + { + hddLog(LOG1, "WE_TXRX_FWSTATS_RESET val %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, + set_value, VDEV_CMD); + break; + } + + case QCSAP_PARAM_RTSCTS: + { + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + 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: + { + uint8_t preamble = 0, nss = 0, rix = 0; + tsap_Config_t *pConfig = + &pHostapdAdapter->sessionCtx.ap.sapConfig; + + hddLog(LOG1, "SET_HT_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(LOGE, "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(LOGE, "Not valid for OFDM"); + ret = -EIO; + break; + } + preamble = WMI_RATE_PREAMBLE_OFDM; + } + set_value = (preamble << 6) | (nss << 4) | rix; + } + hddLog(LOG1, "SET_HT_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case QCASAP_SET_VHT_RATE: + { + uint8_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(LOGE, + FL("SET_VHT_RATE error: SapHw_mode= 0x%x, ch = %d"), + 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, "SET_VHT_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case QCASAP_SHORT_GI: + { + hddLog(LOG1, "QCASAP_SET_SHORT_GI val %d", set_value); + + /* same as 40MHZ */ + ret = sme_update_ht_config(hHal, pHostapdAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ, + set_value); + if (ret) + hddLog(LOGE, + "Failed to set ShortGI value ret(%d)", ret); + break; + } + + case QCSAP_SET_AMPDU: + { + hddLog(LOG1, "QCSAP_SET_AMPDU %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + GEN_VDEV_PARAM_AMPDU, + set_value, GEN_CMD); + break; + } + + case QCSAP_SET_AMSDU: + { + hddLog(LOG1, "QCSAP_SET_AMSDU %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 (CDS_PKT_TRAC_DUMP_CMD == set_value) { + cds_pkt_trace_buf_dump(); + break; + } + pHddCtx->config->gEnableDebugLog = set_value; + break; + } +#endif /* QCA_PKT_PROTO_TRACE */ + + case QCASAP_SET_TM_LEVEL: + { + hddLog(LOG1, "Set Thermal Mitigation Level %d", set_value); + (void)sme_set_thermal_level(hHal, set_value); + break; + } + + case QCASAP_SET_DFS_IGNORE_CAC: + { + hddLog(LOG1, "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(LOG1, "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_dfs_nol( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + p_cds_context, +#endif + (eSapDfsNolType) set_value); + break; + + case QCASAP_SET_RADAR_CMD: + { + hdd_context_t *pHddCtx = + WLAN_HDD_GET_CTX(pHostapdAdapter); + uint8_t ch = + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))-> + operatingChannel; + bool isDfsch; + + isDfsch = (CHANNEL_STATE_DFS == + cds_get_channel_state(ch)); + + hddLog(LOG1, FL("Set QCASAP_SET_RADAR_CMD val %d"), set_value); + + if (!pHddCtx->dfs_radar_found && isDfsch) { + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMA_VDEV_DFS_CONTROL_CMDID, + set_value, VDEV_CMD); + } else { + hddLog(LOGE, + FL("Ignore, radar_found: %d, 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + 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 = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_NSS, + set_value, VDEV_CMD); + break; + } + + case QCSAP_IPA_UC_STAT: + { + /* If input value is non-zero get stats */ + switch (set_value) { + case 1: + hdd_ipa_uc_stat_request(pHostapdAdapter, set_value); + break; + case 3: + hdd_ipa_uc_rt_debug_host_dump( + WLAN_HDD_GET_CTX(pHostapdAdapter)); + break; + default: + /* place holder for stats clean up + * Stats clean not implemented yet on firmware and ipa + */ + break; + } + return ret; + } + + 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); + switch (set_value) { + case WLAN_HDD_STATS: + memset(&pHostapdAdapter->stats, 0, + sizeof(pHostapdAdapter->stats)); + memset(&pHostapdAdapter->hdd_stats, 0, + sizeof(pHostapdAdapter->hdd_stats)); + break; + case WLAN_TXRX_HIST_STATS: + wlan_hdd_clear_tx_rx_histogram(hdd_ctx); + break; + case WLAN_HDD_NETIF_OPER_HISTORY: + wlan_hdd_clear_netif_queue_history(hdd_ctx); + break; + default: + ol_txrx_clear_stats(set_value); + } + break; + } + default: + hddLog(LOGE, FL("Invalid setparam command %d value %d"), + sub_cmd, set_value); + ret = -EINVAL; + break; + } + + return ret; +} + +int +static iw_softap_setparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_setparam(dev, info, wrqu, extra); + cds_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]; + CDF_STATUS status; + int ret; + hdd_context_t *hdd_ctx; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (sub_cmd) { + case QCSAP_PARAM_MAX_ASSOC: + status = + sme_cfg_get_int(hHal, WNI_CFG_ASSOC_STA_LIMIT, + (uint32_t *) value); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, + FL("failed to get WNI_CFG_ASSOC_STA_LIMIT from cfg %d"), + status); + ret = -EIO; + } + break; + + case QCSAP_PARAM_AUTO_CHANNEL: + *value = (WLAN_HDD_GET_CTX + (pHostapdAdapter))->config->force_sap_acs; + break; + + case QCSAP_PARAM_GET_WLAN_DBG: + { + cdf_trace_display(); + *value = 0; + break; + } + + case QCSAP_PARAM_RTSCTS: + { + *value = wma_cli_get_command(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_ENABLE_RTSCTS, + VDEV_CMD); + break; + } + + case QCASAP_SHORT_GI: + { + *value = (int)sme_get_ht_config(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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_GTX_BW_MASK, + GTX_CMD); + break; + } + + case QCASAP_GET_DFS_NOL: + { + wlansap_get_dfs_nol( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter) +#else + pHddCtx->pcds_context +#endif + ); + } + break; + + case QCSAP_GET_ACL: + { + hddLog(LOG1, FL("QCSAP_GET_ACL")); + if (hdd_print_acl(pHostapdAdapter) != + CDF_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(pHostapdAdapter->sessionId, + 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(pHostapdAdapter->sessionId, + WMI_PDEV_PARAM_RX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case QCASAP_NSS_CMD: + { + hddLog(LOG1, "QCASAP_NSS_CMD"); + *value = wma_cli_get_command(pHostapdAdapter->sessionId, + WMI_VDEV_PARAM_NSS, + VDEV_CMD); + break; + } + case QCASAP_GET_TEMP_CMD: + { + hddLog(LOG1, "QCASAP_GET_TEMP_CMD"); + ret = wlan_hdd_get_temperature(pHostapdAdapter, value); + break; + } + default: + hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd); + ret = -EINVAL; + break; + + } + + return ret; +} + +int +static iw_softap_getparam(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_getparam(dev, info, wrqu, extra); + cds_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)); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t cds_ctx; +#endif + uint8_t *value = (uint8_t *) extra; + uint8_t pPeerStaMac[CDF_MAC_ADDR_SIZE]; + int listType, cmd, i; + int ret; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + 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; + +#ifndef WLAN_FEATURE_MBSSID + cds_ctx = hdd_ctx->pcds_context; + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Vos Context is NULL", __func__); + return -EINVAL; + } +#endif + + for (i = 0; i < CDF_MAC_ADDR_SIZE; i++) + pPeerStaMac[i] = *(value + i); + + listType = (int)(*(value + i)); + i++; + cmd = (int)(*(value + i)); + + hddLog(LOG1, FL("Modify ACL mac:" MAC_ADDRESS_STR " type: %d cmd: %d"), + MAC_ADDR_ARRAY(pPeerStaMac), listType, cmd); + +#ifdef WLAN_FEATURE_MBSSID + cdf_status = + wlansap_modify_acl(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), + pPeerStaMac, (eSapACLType) listType, + (eSapACLCmdType) cmd); +#else + cdf_status = + wlansap_modify_acl(p_cds_context, pPeerStaMac, + (eSapACLType) listType, (eSapACLCmdType) cmd); +#endif + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("Modify ACL failed")); + ret = -EIO; + } + EXIT(); + return ret; +} + +static +int iw_softap_modify_acl(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_modify_acl(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +int +static __iw_softap_getchannel(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 *value = (int *)extra; + int ret; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + *value = 0; + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + *value = (WLAN_HDD_GET_AP_CTX_PTR( + pHostapdAdapter))->operatingChannel; + return 0; +} + +int +static iw_softap_getchannel(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_getchannel(dev, info, wrqu, extra); + cds_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; + + 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 */ + cdf_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(selfMac, pHostapdAdapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + + set_value = value[0]; + if (CDF_STATUS_SUCCESS != + sme_set_max_tx_power(hHal, bssid, selfMac, set_value)) { + hddLog(LOGE, FL("Setting maximum tx power failed")); + return -EIO; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_set_max_tx_power(dev, info, wrqu, extra); + cds_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; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (NULL == value) + return -ENOMEM; + + cdf_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + + set_value = value[0]; + if (CDF_STATUS_SUCCESS != + sme_set_tx_power(hHal, pHostapdAdapter->sessionId, bssid, + pHostapdAdapter->device_mode, set_value)) { + hddLog(LOGE, FL("Setting tx power failed")); + return -EIO; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_set_tx_power(dev, info, wrqu, extra); + cds_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 userspace */ + u32 maclist_index; + + /* + * 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 userspace, 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" + * userspace 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. + */ + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* make sure userspace allocated a reasonable buffer size */ + if (wrqu->data.length < sizeof(maclist_index)) { + hddLog(LOG1, FL("invalid userspace buffer")); + return -EINVAL; + } + + /* allocate local buffer to build the response */ + buf = kmalloc(wrqu->data.length, GFP_KERNEL); + if (!buf) { + hddLog(LOG1, FL("failed to allocate response buffer")); + 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 >= CDF_MAC_ADDR_SIZE)) { + if ((pStaInfo[cnt].isUsed) && + (!IS_BROADCAST_MAC(pStaInfo[cnt].macAddrSTA.bytes))) { + memcpy(&buf[maclist_index], &(pStaInfo[cnt].macAddrSTA), + CDF_MAC_ADDR_SIZE); + maclist_index += CDF_MAC_ADDR_SIZE; + left -= CDF_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, FL("failed to copy response to user buffer")); + ret = -EFAULT; + } + kfree(buf); + 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_getassoc_stamacaddr(dev, info, wrqu, extra); + cds_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; + uint8_t *peerMacAddr; + int ret; + + ENTER(); + + 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 = (uint8_t *) (extra); + + hddLog(LOG1, FL("data " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peerMacAddr)); + hdd_softap_sta_disassoc(pHostapdAdapter, peerMacAddr); + 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; + + cds_ssr_protect(__func__); + ret = __iw_softap_disassoc_sta(dev, info, wrqu, extra); + cds_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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + CDF_STATUS status; + int sub_cmd = wrqu->data.flags; + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + status = wlan_hdd_validate_context(hdd_ctx); + if (status != 0) + return status; + + switch (sub_cmd) { + case QCSAP_GET_STATS: + hdd_wlan_get_stats(adapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + } + + EXIT(); + return status; +} + +static int iw_get_char_setnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_get_char_setnone(dev, info, wrqu, extra); + cds_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 (wlan_hdd_validate_operation_channel(adapter, value[0]) != + CDF_STATUS_SUCCESS || + wlan_hdd_validate_operation_channel(adapter, value[1]) != + CDF_STATUS_SUCCESS) { + return -EINVAL; + } else { + hdd_ctx->config->force_sap_acs_st_ch = value[0]; + hdd_ctx->config->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; + cds_ssr_protect(__func__); + ret = wlan_hdd_set_force_acs_ch_range(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + return ret; +} + +static int __iw_softap_get_channel_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + uint32_t num_channels = 0; + uint8_t i = 0; + uint8_t bandStartChannel = RF_CHAN_1; + uint8_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; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (CDF_STATUS_SUCCESS != sme_get_freq_band(hHal, &curBand)) { + hddLog(LOGE, FL("not able get the current frequency band")); + return -EIO; + } + wrqu->data.length = sizeof(tChannelListInfo); + ENTER(); + + if (eCSR_BAND_24 == curBand) { + bandStartChannel = RF_CHAN_1; + bandEndChannel = RF_CHAN_14; + } else if (eCSR_BAND_5G == curBand) { + bandStartChannel = RF_CHAN_36; + bandEndChannel = RF_CHAN_184; + } + + hddLog(LOG1, FL("curBand = %d, StartChannel = %hu, EndChannel = %hu "), + curBand, bandStartChannel, bandEndChannel); + + for (i = bandStartChannel; i <= bandEndChannel; i++) { + if ((CHANNEL_STATE_ENABLE == reg_channels[i].enabled) || + (CHANNEL_STATE_DFS == reg_channels[i].enabled)) { + channel_list->channels[num_channels] = + rf_channels[i].channelNum; + num_channels++; + } + } + + hddLog(LOG1, FL(" number of channels %d"), num_channels); + + if (num_channels > IW_MAX_FREQUENCIES) { + num_channels = IW_MAX_FREQUENCIES; + } + + channel_list->num_channels = num_channels; + EXIT(); + + return 0; +} + +int iw_softap_get_channel_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_get_channel_list(dev, info, wrqu, extra); + cds_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 cds_ctx; +#endif + CDF_STATUS status; + uint32_t length = DOT11F_IE_RSN_MAX_LEN; + uint8_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 + cds_ctx = hdd_ctx->pcds_context; + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: vos context is not valid ", __func__); + return -EINVAL; + } +#endif + + hddLog(LOG1, FL("getGEN_IE ioctl")); + /* + * Actually retrieve the RSN IE from CSR. + * (We previously sent it down in the CSR Roam Profile.) + */ + status = wlan_sap_getstation_ie_information( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + cds_ctx, +#endif + &length, genIeBytes); + if (status == CDF_STATUS_SUCCESS) { + length = CDF_MIN(length, DOT11F_IE_RSN_MAX_LEN); + if (wrqu->data.length < length || + copy_to_user(wrqu->data.pointer, (void *)genIeBytes, length)) { + hddLog(LOG1, FL("failed to copy data to user buffer")); + return -EFAULT; + } + wrqu->data.length = length; + hddLog(LOG1, FL(" RSN IE of %d bytes returned"), + wrqu->data.length); + } else { + wrqu->data.length = 0; + hddLog(LOG1, FL(" RSN IE failed to populate")); + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_genie(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +static +int __iw_get_wpspbc_probe_req_ies(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; + + hddLog(LOG1, FL("get_WPSPBCProbeReqIEs ioctl")); + memset((void *)&WPSPBCProbeReqIEs, 0, sizeof(WPSPBCProbeReqIEs)); + + WPSPBCProbeReqIEs.probeReqIELen = + pHddApCtx->WPSPBCProbeReq.probeReqIELen; + cdf_mem_copy(&WPSPBCProbeReqIEs.probeReqIE, + pHddApCtx->WPSPBCProbeReq.probeReqIE, + WPSPBCProbeReqIEs.probeReqIELen); + cdf_mem_copy(&WPSPBCProbeReqIEs.macaddr, + pHddApCtx->WPSPBCProbeReq.peerMacAddr, + CDF_MAC_ADDR_SIZE); + if (copy_to_user(wrqu->data.pointer, + (void *)&WPSPBCProbeReqIEs, + sizeof(WPSPBCProbeReqIEs))) { + hddLog(LOG1, FL("failed to copy data to user buffer")); + 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_wpspbc_probe_req_ies(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_get_wpspbc_probe_req_ies(dev, info, wrqu, extra); + cds_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, + "Counter Measure started %d", wrqu->param.value); + pWextState->mTKIPCounterMeasures = + TKIP_COUNTER_MEASURE_STARTED; + } else { + hddLog(LOG2, + "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; + + cds_ssr_protect(__func__); + ret = __iw_set_auth_hostap(dev, info, wrqu, extra); + cds_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 cds_ctx; +#endif + hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); + hdd_context_t *hdd_ctx; + int ret; + CDF_STATUS vstatus; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int key_index; + struct iw_point *encoding = &wrqu->encoding; + tCsrRoamSetKey setKey; + 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 + cds_ctx = hdd_ctx->pcds_context; + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: pVosContext is NULL", __func__); + return -EINVAL; + } +#endif + + 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) + return ret; + + cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + + setKey.keyId = key_index; + setKey.keyLength = ext->key_len; + + if (ext->key_len <= CSR_MAX_KEY_LEN) { + cdf_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; + cdf_set_macaddr_broadcast(&setKey.peerMac); + } else { + + setKey.keyDirection = eSIR_TX_RX; + cdf_mem_copy(setKey.peerMac.bytes, ext->addr.sa_data, + CDF_MAC_ADDR_SIZE); + } + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + setKey.keyDirection = eSIR_TX_DEFAULT; + cdf_mem_copy(setKey.peerMac.bytes, ext->addr.sa_data, + CDF_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, FL("uPrivacy=%d"), pHddApCtx->uPrivacy); + break; + + case IW_ENCODE_ALG_TKIP: + { + uint8_t *pKey = &setKey.Key[0]; + + setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + + cdf_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) */ + cdf_mem_copy(pKey, ext->key, 16); + + /*Copy the rx mic first */ + cdf_mem_copy(&pKey[16], &ext->key[24], 8); + + /*Copy the tx mic */ + cdf_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; + } + + hddLog(LOG1, FL(":EncryptionType:%d key_len:%d, KeyId:%d"), + setKey.encType, setKey.keyLength, setKey.keyId); + for (i = 0; i < ext->key_len; i++) + hddLog(LOG1, "%02x", setKey.Key[i]); + +#ifdef WLAN_FEATURE_MBSSID + vstatus = + wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), + &setKey); +#else + vstatus = wlansap_set_key_sta(cds_ctx, &setKey); +#endif + + if (vstatus != CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("wlansap_set_key_sta failed, status= %d"), + vstatus); + ret = -EINVAL; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_ap_encodeext(dev, info, wrqu, extra); + cds_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) +{ + return 0; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_set_ap_mlme(dev, info, wrqu, extra); + cds_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; + + cds_ssr_protect(__func__); + ret = __iw_get_ap_rts_threshold(dev, info, wrqu, extra); + cds_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; + + cds_ssr_protect(__func__); + ret = __iw_get_ap_frag_threshold(dev, info, wrqu, extra); + cds_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) { + uint32_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 (sme_cfg_get_int(hHal, WNI_CFG_CURRENT_CHANNEL, &channel) + != CDF_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; + } + } + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_ap_freq(dev, info, wrqu, extra); + cds_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; + + cds_ssr_protect(__func__); + ret = __iw_get_mode(dev, info, wrqu, extra); + cds_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 cds_ctx; +#endif + hdd_hostapd_state_t *pHostapdState; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + uint8_t *wps_genie; + uint8_t *fwps_genie; + uint8_t *pos; + tpSap_WPSIE pSap_WPSIe; + uint8_t WPSIeType; + uint16_t length; + struct iw_point s_priv_data; + 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 + cds_ctx = hdd_ctx->pcds_context; + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD 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, FL("failed to alloc mem and copy data")); + return -EFAULT; + } + + fwps_genie = wps_genie; + + pSap_WPSIe = cdf_mem_malloc(sizeof(tSap_WPSIE)); + if (NULL == pSap_WPSIe) { + hddLog(LOGE, "CDF unable to allocate memory"); + kfree(fwps_genie); + return -ENOMEM; + } + cdf_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); + + hddLog(LOG1, FL("WPS IE type[0x%X] IE[0x%X], LEN[%d]"), + 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) { + cdf_mem_free(pSap_WPSIe); + kfree(fwps_genie); + return -EINVAL; + } else if (memcmp(&wps_genie[2], + "\x00\x50\xf2\x04", 4) == 0) { + hddLog(LOG1, FL("Set WPS BEACON IE(len %d)"), + wps_genie[1] + 2); + pos = &wps_genie[6]; + while (((size_t) pos - + (size_t) &wps_genie[6]) < + (wps_genie[1] - 4)) { + switch ((uint16_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; + cdf_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))); + cdf_mem_free(pSap_WPSIe); + kfree(fwps_genie); + return -EINVAL; + } + } + } else { + hddLog(LOGE, FL("WPS IE Mismatch %X"), + wps_genie[0]); + } + break; + + default: + hddLog(LOGE, FL("Set UNKNOWN IE %X"), wps_genie[0]); + cdf_mem_free(pSap_WPSIe); + kfree(fwps_genie); + return 0; + } + } 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) { + cdf_mem_free(pSap_WPSIe); + kfree(fwps_genie); + return -EINVAL; + } else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) + == 0) { + hddLog(LOG1, FL("Set WPS PROBE RSP IE(len %d)"), + wps_genie[1] + 2); + pos = &wps_genie[6]; + while (((size_t) pos - + (size_t) &wps_genie[6]) < + (wps_genie[1] - 4)) { + switch ((uint16_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; + cdf_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; + pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE. + Manufacture.num_name = + length; + cdf_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; + pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE.ModelName. + num_text = length; + cdf_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; + pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE. + ModelNumber.num_text = + length; + cdf_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; + pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE. + SerialNumber.num_text = + length; + cdf_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; + + cdf_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; + pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE.DeviceName. + num_text = length; + cdf_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, + FL("WPS IE Mismatch %X"), wps_genie[0]); + } + + } /* switch */ + } +#ifdef WLAN_FEATURE_MBSSID + cdf_ret_status = + wlansap_set_wps_ie(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), + pSap_WPSIe); +#else + cdf_ret_status = wlansap_set_wps_ie(p_cds_context, pSap_WPSIe); +#endif + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + if (pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) { +#ifdef WLAN_FEATURE_MBSSID + wlansap_update_wps_ie(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + wlansap_update_wps_ie(p_cds_context); +#endif + } + + cdf_mem_free(pSap_WPSIe); + kfree(fwps_genie); + EXIT(); + return cdf_ret_status; +} + +static int iw_softap_setwpsie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_setwpsie(dev, info, wrqu, extra); + cds_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)); + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + status = wlan_hdd_validate_context(hdd_ctx); + 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); + + cdf_event_reset(&pHostapdState->cdf_stop_bss_event); +#ifdef WLAN_FEATURE_MBSSID + status = + wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + status = + wlansap_stop_bss((WLAN_HDD_GET_CTX(pHostapdAdapter))-> + pcds_context); +#endif + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + cdf_wait_single_event(&pHostapdState-> + cdf_stop_bss_event, + 10000); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("wait for single_event failed!!")); + CDF_ASSERT(0); + } + } + clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + cds_decr_session_set_pcl(hdd_ctx, + pHostapdAdapter->device_mode, + pHostapdAdapter->sessionId); + } + EXIT(); + return (status == CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_softap_stopbss(dev, info, wrqu, extra); + cds_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 0; +} + +static int iw_softap_version(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_version(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +static +CDF_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, uint8_t *pBuf, + int buf_len) { + uint8_t i; + uint8_t maxSta = 0; + int len = 0; + const char sta_info_header[] = "staId staAddress"; + hdd_context_t *hdd_ctx; + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Adapter is NULL", __func__); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return CDF_STATUS_E_FAULT; + + len = scnprintf(pBuf, buf_len, sta_info_header); + pBuf += len; + buf_len -= len; + + maxSta = hdd_ctx->config->maxNumberOfPeers; + + for (i = 0; i <= maxSta; i++) { + if (pAdapter->aStaInfo[i].isUsed) { + len = + scnprintf(pBuf, buf_len, + "%5d .%02x:%02x:%02x:%02x:%02x:%02x", + pAdapter->aStaInfo[i].ucSTAId, + pAdapter->aStaInfo[i].macAddrSTA.bytes[0], + pAdapter->aStaInfo[i].macAddrSTA.bytes[1], + pAdapter->aStaInfo[i].macAddrSTA.bytes[2], + pAdapter->aStaInfo[i].macAddrSTA.bytes[3], + pAdapter->aStaInfo[i].macAddrSTA.bytes[4], + pAdapter->aStaInfo[i].macAddrSTA. + bytes[5]); + pBuf += len; + buf_len -= len; + } + if (WE_GET_STA_INFO_SIZE > buf_len) { + break; + } + } + return CDF_STATUS_SUCCESS; +} + +static int __iw_softap_get_sta_info(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + CDF_STATUS status; + hdd_context_t *hdd_ctx; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + status = + hdd_softap_get_sta_info(pHostapdAdapter, extra, + WE_SAP_MAX_STA_INFO); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("Failed to get sta info: %d"), status); + return -EINVAL; + } + wrqu->data.length = strlen(extra); + EXIT(); + return 0; +} + +static int iw_softap_get_sta_info(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_get_sta_info(dev, info, wrqu, extra); + cds_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 cds_ctx; +#endif + hdd_context_t *hdd_ctx; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + uint8_t *genie = (uint8_t *)extra; + 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 + cds_ctx = hdd_ctx->pcds_context; + if (NULL == cds_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: CDF 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 + cdf_ret_status = + wlansap_set_wparsn_ies(WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), genie, + wrqu->data.length); +#else + cdf_ret_status = + wlansap_set_wparsn_ies(cds_ctx, genie, + wrqu->data.length); +#endif + break; + + default: + hddLog(LOGE, FL("Set UNKNOWN IE %X"), genie[0]); + cdf_ret_status = 0; + } + + EXIT(); + return cdf_ret_status; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_set_ap_genie(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +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 *hdd_ctx; + char *pLinkSpeed = (char *)extra; + uint32_t link_speed = 0; + int len = sizeof(uint32_t) + 1; + tSirMacAddr macAddress; + char pmacAddress[MAC_ADDRESS_STR_LEN + 1]; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int rc, valid, i; + + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); + valid = wlan_hdd_validate_context(hdd_ctx); + if (0 != valid) + return valid; + + hddLog(LOG1, FL("wrqu->data.length(%d)"), wrqu->data.length); + + if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) { + if (copy_from_user((void *)pmacAddress, + wrqu->data.pointer, MAC_ADDRESS_STR_LEN)) { + hddLog(LOG1, FL("failed to copy data to user buffer")); + return -EFAULT; + } + pmacAddress[MAC_ADDRESS_STR_LEN] = '\0'; + + if (!mac_pton(pmacAddress, macAddress)) { + hddLog(LOGE, FL("String to Hex conversion Failed")); + return -EINVAL; + } + } + /* 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 || !CDF_IS_STATUS_SUCCESS(status)) { + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if (pHostapdAdapter->aStaInfo[i].isUsed && + (!cdf_is_macaddr_broadcast + (&pHostapdAdapter->aStaInfo[i].macAddrSTA))) { + cdf_copy_macaddr( + (struct cdf_mac_addr *) macAddress, + &pHostapdAdapter->aStaInfo[i]. + macAddrSTA); + status = CDF_STATUS_SUCCESS; + break; + } + } + } + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("Invalid peer macaddress")); + return -EINVAL; + } + status = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, + macAddress); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, 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(LOGE, FL("Unable to encode link speed")); + return -EIO; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_softap_linkspeed(dev, info, wrqu, extra); + cds_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_SET_CHANNEL_CHANGE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "setChanChange" + }, { + QCSAP_PARAM_AUTO_CHANNEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "setAutoChannel" + }, + /* 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" + }, + { + QCSAP_IPA_UC_STAT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ipaucstat" + }, + { + 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" + }, { + 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_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_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" + } + /* 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_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 sub-ioctl */ + { + WE_SET_DP_TRACE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_dp_trace" + } + , + /* handlers for main ioctl */ + { + QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, "" + } + , { + WE_P2P_NOA_CMD, IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, "SetP2pPs" + } + , { + WE_UNIT_TEST_CMD, IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, + "setUnitTestCmd" + } + , + /* 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" + } + , + /* 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 */ + { + /* 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 + { + QCASAP_SET_RADAR_DBG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setRadarDbg" + } + , + /* dump dp trace - descriptor or dp trace records */ + { + QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "dump_dp_trace" + } + , +}; + +static const iw_handler hostapd_private[] = { + /* set priv ioctl */ + [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, + /* get priv ioctl */ + [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, + /* get station genIE */ + [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, + [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, + /* stop bss */ + [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, + /* get driver version */ + [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, + [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = + iw_get_wpspbc_probe_req_ies, + [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_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = + iw_get_char_setnone, + [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - + SIOCIWFIRSTPRIV] = + iw_set_three_ints_getnone, + [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - + SIOCIWFIRSTPRIV] = + iw_set_var_ints_getnone, + [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = + iw_softap_set_force_acs_ch_range, + [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = + iw_softap_modify_acl, + [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = + iw_softap_get_channel_list, + [QCSAP_IOCTL_GET_STA_INFO - SIOCIWFIRSTPRIV] = + iw_softap_get_sta_info, + [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - + SIOCIWFIRSTPRIV] = + iw_get_softap_linkspeed, + [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = + iw_softap_set_tx_power, + [QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] = + iw_softap_set_max_tx_power, + [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, +}; +const struct iw_handler_def hostapd_handler_def = { + .num_standard = CDF_ARRAY_SIZE(hostapd_handler), + .num_private = CDF_ARRAY_SIZE(hostapd_private), + .num_private_args = CDF_ARRAY_SIZE(hostapd_private_args), + .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_get_stats, + .ndo_set_mac_address = hdd_hostapd_set_mac_address, + .ndo_do_ioctl = hdd_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 CDF_STATUS_SUCCESS; +} + +void hdd_set_ap_ops(struct net_device *pWlanHostapdDev) +{ + pWlanHostapdDev->netdev_ops = &net_ops_struct; +} + +CDF_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); + CDF_STATUS status; +#ifdef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context; + v_CONTEXT_t sapContext = NULL; +#endif + int ret; + + ENTER(); + +#ifdef WLAN_FEATURE_MBSSID + sapContext = wlansap_open(p_cds_context); + if (sapContext == NULL) { + hddLog(LOGE, ("ERROR: wlansap_open failed!!")); + return CDF_STATUS_E_FAULT; + } + + pAdapter->sessionCtx.ap.sapContext = sapContext; + + status = wlansap_start(sapContext); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, ("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_set_curr_device_mode(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 (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, ("ERROR: hdd_set_hostapd failed!!")); +#ifdef WLAN_FEATURE_MBSSID + wlansap_close(sapContext); +#endif + return status; + } + + status = cdf_event_init(&phostapdBuf->cdf_event); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, ("ERROR: Hostapd HDD cdf event init failed!!")); +#ifdef WLAN_FEATURE_MBSSID + wlansap_close(sapContext); +#endif + return status; + } + + status = cdf_event_init(&phostapdBuf->cdf_stop_bss_event); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGP, FL("hdd_softap_init_tx_rx failed")); + } + + status = hdd_wmm_adapter_init(pAdapter); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + "hdd_wmm_adapter_init() failed code %08d [x%08x]", + status, status); + goto error_wmm_init; + } + + set_bit(WMM_INIT_DONE, &pAdapter->event_flags); + + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_PDEV_PARAM_BURST_ENABLE, + pHddCtx->config->enableSifsBurst, + PDEV_CMD); + + if (0 != ret) { + hddLog(LOGE, + FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"), ret); + } + pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false; + cdf_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + cdf_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_wlan_create_ap_dev() - create an AP-mode device + * @pHddCtx: Global HDD context + * @macAddr: MAC address to assign to the interface + * @iface_name: User-visible name of the interface + * + * This function will allocate a Linux net_device and configuration it + * for an AP mode of operation. Note that the device is NOT actually + * registered with the kernel at this time. + * + * Return: A pointer to the private data portion of the net_device if + * the allocation and initialization was successful, NULL otherwise. + */ +hdd_adapter_t *hdd_wlan_create_ap_dev(hdd_context_t *pHddCtx, + tSirMacAddr macAddr, + uint8_t *iface_name) { + struct net_device *pWlanHostapdDev = NULL; + hdd_adapter_t *pHostapdAdapter = NULL; + + hddLog(LOG4, FL("iface_name = %s"), iface_name); + + pWlanHostapdDev = + alloc_netdev_mq(sizeof(hdd_adapter_t), iface_name, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) + 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. */ + cdf_mem_zero(pHostapdAdapter, sizeof(hdd_adapter_t)); + pHostapdAdapter->dev = pWlanHostapdDev; + pHostapdAdapter->pHddCtx = pHddCtx; + pHostapdAdapter->magic = WLAN_HDD_ADAPTER_MAGIC; + + hddLog(LOG4, + FL("pWlanHostapdDev = %p, pHostapdAdapter = %p, concurrency_mode=0x%x"), + pWlanHostapdDev, + pHostapdAdapter, + (int)cds_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; + + cdf_mem_copy(pWlanHostapdDev->dev_addr, (void *)macAddr, + sizeof(tSirMacAddr)); + cdf_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->sta_authorized_event); + init_completion(&pHostapdAdapter->offchannel_tx_event); + init_completion(&pHostapdAdapter->scan_info. + abortscan_event_var); + + SET_NETDEV_DEV(pWlanHostapdDev, pHddCtx->parent_dev); + spin_lock_init(&pHostapdAdapter->pause_map_lock); + } + return pHostapdAdapter; +} + +/** + * hdd_register_hostapd() - register hostapd + * @pAdapter: Pointer to hostapd adapter + * @rtnl_lock_held: RTNL lock held + * + * Return: CDF status + */ +CDF_STATUS hdd_register_hostapd(hdd_adapter_t *pAdapter, + uint8_t rtnl_lock_held) { + struct net_device *dev = pAdapter->dev; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + ENTER(); + + if (rtnl_lock_held) { + if (strnchr(dev->name, strlen(dev->name), '%')) { + if (dev_alloc_name(dev, dev->name) < 0) { + hddLog(LOGE, FL("Failed:dev_alloc_name")); + return CDF_STATUS_E_FAILURE; + } + } + if (register_netdevice(dev)) { + hddLog(LOGE, FL("Failed:register_netdevice")); + return CDF_STATUS_E_FAILURE; + } + } else { + if (register_netdev(dev)) { + hddLog(LOGE, FL("Failed:register_netdev")); + return CDF_STATUS_E_FAILURE; + } + } + set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags); + + EXIT(); + return status; +} + +/** + * hdd_unregister_hostapd() - unregister hostapd + * @pAdapter: Pointer to hostapd adapter + * @rtnl_held: true if rtnl lock held; false otherwise + * + * Return: CDF_STATUS enumaration + */ +CDF_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held) +{ +#ifdef WLAN_FEATURE_MBSSID + CDF_STATUS status; + void *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 (!CDF_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Failed:wlansap_stop")); + + status = wlansap_close(sapContext); + if (!CDF_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Failed:WLANSAP_close")); + pAdapter->sessionCtx.ap.sapContext = NULL; +#endif + + EXIT(); + return 0; +} + +/** + * wlan_hdd_rate_is_11g() - check if rate is 11g rate or not + * @rate: Rate to be checked + * + * Return: true if rate if 11g else false + */ +static bool 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; +} + +#ifdef QCA_HT_2040_COEX +/** + * wlan_hdd_get_sap_obss() - Get SAP OBSS enable config based on HT_CAPAB IE + * @pHostapdAdapter: Pointer to hostapd adapter + * + * Return: HT support channel width config value + */ +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]) { + cdf_mem_copy(ht_cap_ie, &ie[2], DOT11F_IE_HTCAPS_MAX_LEN); + dot11f_unpack_ie_ht_caps((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 +/** + * wlan_hdd_set_channel() - set channel in sap mode + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * @chandef: Pointer to channel definition structure + * @channel_type: Channel type + * + * Return: 0 for success non-zero for failure + */ +static int wlan_hdd_set_channel(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + enum nl80211_channel_type channel_type) +{ + hdd_adapter_t *pAdapter = NULL; + uint32_t num_ch = 0; + int channel = 0; + int channel_seg2 = 0; + hdd_context_t *pHddCtx; + int status; + + tSmeConfigParams smeConfig; + tsap_Config_t *sap_config; + + ENTER(); + + + if (NULL == dev) { + hddLog(LOGE, FL("Called with dev = NULL.")); + return -ENODEV; + } + pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + + MTRACE(cdf_trace(CDF_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, chandef->chan->center_freq); + + 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; + } + + /* + * Do freq to chan conversion + * TODO: for 11a + */ + + channel = ieee80211_frequency_to_channel(chandef->chan->center_freq); + if (NL80211_CHAN_WIDTH_80P80 == chandef->width) + channel_seg2 = ieee80211_frequency_to_channel(chandef->center_freq2); + else + channel_seg2 = 0; + + /* Check freq range */ + if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) || + (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel)) { + hddLog(LOGE, + FL("Channel [%d] is outside valid range from %d to %d"), + channel, WNI_CFG_CURRENT_CHANNEL_STAMIN, + WNI_CFG_CURRENT_CHANNEL_STAMAX); + return -EINVAL; + } + + /* Check freq range */ + + if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel_seg2) || + (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel_seg2)) { + hddLog(LOGE, + FL("Channel [%d] is outside valid range from %d to %d"), + channel_seg2, 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 (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, channel)) { + hddLog(LOGE, FL("Invalid Channel [%d]"), 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(LOGE, + FL("IBSS Associated, can't set the channel")); + 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 (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, + channel)) { + hddLog(LOGE, + FL("Invalid Channel [%d]"), channel); + return -EINVAL; + } + sap_config->channel = channel; + sap_config->ch_params.center_freq_seg1 = channel_seg2; + } else { + /* set channel to what hostapd configured */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, + channel)) { + hddLog(LOGE, + FL("Invalid Channel [%d]"), channel); + return -EINVAL; + } + + sap_config->channel = channel; + sap_config->ch_params.center_freq_seg1 = channel_seg2; + + cdf_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_get_config_param(pHddCtx->hHal, &smeConfig); + switch (channel_type) { + case NL80211_CHAN_HT20: + case NL80211_CHAN_NO_HT: + smeConfig.csrConfig.obssEnabled = false; + if (channel <= 14) + smeConfig.csrConfig. + channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + else + smeConfig.csrConfig. + channelBondingMode5GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + 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(LOGE, + FL("Error!!! Invalid HT20/40 mode !")); + return -EINVAL; + } + smeConfig.csrConfig.obssEnabled = wlan_hdd_get_sap_obss( + pAdapter); + sme_update_config(pHddCtx->hHal, &smeConfig); + } + } else { + hddLog(LOGE, + FL("Invalid device mode failed to set valid channel")); + return -EINVAL; + } + EXIT(); + return status; +} + +/** + * wlan_hdd_check_11gmode() - check for 11g mode + * @pIe: Pointer to IE + * @require_ht: Pointer to require ht + * @require_vht: Pointer to require vht + * @pCheckRatesfor11g: Pointer to check rates for 11g mode + * @pSapHw_mode: SAP HW mode + * + * Check for 11g rate and set proper 11g only mode + * + * Return: none + */ +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; +} + +/** + * wlan_hdd_add_ie() - add ie + * @pHostapdAdapter: Pointer to hostapd adapter + * @genie: Pointer to ie to be added + * @total_ielen: Pointer to store total ie length + * @oui: Pointer to oui + * @oui_size: Size of oui + * + * Return: 0 for success non-zero for failure + */ +static int wlan_hdd_add_ie(hdd_adapter_t *pHostapdAdapter, uint8_t *genie, + uint8_t *total_ielen, uint8_t *oui, + uint8_t oui_size) +{ + uint16_t ielen = 0; + uint8_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) { + cdf_mem_copy(&genie[*total_ielen], pIe, ielen); + } else { + hddLog(LOGE, + "**Ie Length is too big***"); + return -EINVAL; + } + *total_ielen += ielen; + } + return 0; +} + +/** + * wlan_hdd_add_hostapd_conf_vsie() - configure vsie in sap mode + * @pHostapdAdapter: Pointer to hostapd adapter + * @genie: Pointer to vsie + * @total_ielen: Pointer to store total ie length + * + * Return: none + */ +static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t *pHostapdAdapter, + uint8_t *genie, + uint8_t *total_ielen) +{ + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + int left = pBeacon->tail_len; + uint8_t *ptr = pBeacon->tail; + uint8_t elem_id, elem_len; + uint16_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(LOGE, + FL("****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) { + cdf_mem_copy(&genie[*total_ielen], ptr, + ielen); + *total_ielen += ielen; + } else { + hddLog(LOGE, + FL("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; +} + +/** + * wlan_hdd_add_extra_ie() - add extra ies in beacon + * @pHostapdAdapter: Pointer to hostapd adapter + * @genie: Pointer to extra ie + * @total_ielen: Pointer to store total ie length + * @temp_ie_id: ID of extra ie + * + * Return: none + */ +static void wlan_hdd_add_extra_ie(hdd_adapter_t *pHostapdAdapter, + uint8_t *genie, uint8_t *total_ielen, + uint8_t temp_ie_id) +{ + beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon; + int left = pBeacon->tail_len; + uint8_t *ptr = pBeacon->tail; + uint8_t elem_id, elem_len; + uint16_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(LOGE, + FL("****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) { + cdf_mem_copy(&genie[*total_ielen], ptr, ielen); + *total_ielen += ielen; + } else { + hddLog(LOGE, + FL("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; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +/** + * wlan_hdd_cfg80211_alloc_new_beacon() - alloc beacon in ap mode + * @pAdapter: Pointer to hostapd adapter + * @ppBeacon: Pointer to pointer to beacon data + * @params: Pointer to beacon parameters + * + * Return: 0 for success non-zero for failure + */ +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, + beacon_data_t **ppBeacon, + struct beacon_parameters *params) +#else +/** + * wlan_hdd_cfg80211_alloc_new_beacon() - alloc beacon in ap mode + * @pAdapter: Pointer to hostapd adapter + * @ppBeacon: Pointer to pointer to beacon data + * @params: Pointer to beacon parameters + * @dtim_period: DTIM period + * + * Return: 0 for success non-zero for failure + */ +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) { + hddLog(LOGE, FL("head_len is NULL")); + return -EINVAL; + } + + old = pAdapter->sessionCtx.ap.beacon; + + if (!params->head && !old) { + hddLog(LOGE, FL("session(%d) old and new heads points 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) { + hddLog(LOGE, + FL("Mem allocation for beacon failed")); + return -ENOMEM; + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) + 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; + +} + +/** + * wlan_hdd_cfg80211_update_apies() - update ap mode ies + * @adapter: Pointer to hostapd adapter + * + * Return: 0 for success non-zero for failure + */ +int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *adapter) +{ + uint8_t *genie; + uint8_t total_ielen = 0; + int ret = 0; + tsap_Config_t *pConfig; + tSirUpdateIE updateIE; + beacon_data_t *beacon = NULL; + + pConfig = &adapter->sessionCtx.ap.sapConfig; + beacon = adapter->sessionCtx.ap.beacon; + + genie = cdf_mem_malloc(MAX_GENIE_LEN); + + if (genie == NULL) + return -ENOMEM; + + if (0 != wlan_hdd_add_ie(adapter, 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(adapter, 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 == adapter->device_mode) { + wlan_hdd_add_extra_ie(adapter, genie, &total_ielen, + WLAN_EID_WAPI); + } +#endif + + if (adapter->device_mode == WLAN_HDD_SOFTAP || + adapter->device_mode == WLAN_HDD_P2P_GO) + wlan_hdd_add_hostapd_conf_vsie(adapter, genie, + &total_ielen); + + if (wlan_hdd_add_ie(adapter, genie, + &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0) { + hddLog(LOGE, FL("Adding P2P IE failed")); + ret = -EINVAL; + goto done; + } + +#ifdef QCA_HT_2040_COEX + if (WLAN_HDD_SOFTAP == adapter->device_mode) { + tSmeConfigParams smeConfig; + cdf_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_get_config_param(WLAN_HDD_GET_HAL_CTX(adapter), + &smeConfig); + if (smeConfig.csrConfig.obssEnabled) + wlan_hdd_add_extra_ie(adapter, genie, + &total_ielen, + WLAN_EID_OVERLAP_BSS_SCAN_PARAM); + } +#endif + cdf_mem_copy(updateIE.bssid, adapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = adapter->sessionId; + + if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { + updateIE.ieBufferlength = total_ielen; + updateIE.pAdditionIEBuffer = genie; + updateIE.append = false; + updateIE.notify = true; + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), + &updateIE, + eUPDATE_IE_PROBE_BCN) == + CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL("Could not pass on Add Ie probe beacon data")); + ret = -EINVAL; + goto done; + } + wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_PROBE_BCN); + } else { + wlansap_update_sap_config_add_ie(pConfig, + genie, + total_ielen, + eUPDATE_IE_PROBE_BCN); + } + + /* Added for Probe Response IE */ + if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { + updateIE.ieBufferlength = beacon->proberesp_ies_len; + updateIE.pAdditionIEBuffer = (uint8_t *) beacon->proberesp_ies; + updateIE.append = false; + updateIE.notify = false; + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), + &updateIE, + eUPDATE_IE_PROBE_RESP) == + CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL("Could not pass on PROBE_RESP add Ie data")); + ret = -EINVAL; + goto done; + } + wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_PROBE_RESP); + } else { + wlansap_update_sap_config_add_ie(pConfig, + beacon->proberesp_ies, + beacon->proberesp_ies_len, + eUPDATE_IE_PROBE_RESP); + } + + /* Assoc resp Add ie Data */ + if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { + updateIE.ieBufferlength = beacon->assocresp_ies_len; + updateIE.pAdditionIEBuffer = (uint8_t *) beacon->assocresp_ies; + updateIE.append = false; + updateIE.notify = false; + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), + &updateIE, + eUPDATE_IE_ASSOC_RESP) == + CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL("Could not pass on Add Ie Assoc Response data")); + ret = -EINVAL; + goto done; + } + wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_ASSOC_RESP); + } else { + wlansap_update_sap_config_add_ie(pConfig, + beacon->assocresp_ies, + beacon->assocresp_ies_len, + eUPDATE_IE_ASSOC_RESP); + } + +done: + cdf_mem_free(genie); + return ret; +} + +/** + * wlan_hdd_set_sap_hwmode() - set sap hw mode + * @pHostapdAdapter: Pointer to hostapd adapter + * + * Return: none + */ +static void wlan_hdd_set_sap_hwmode(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; + } +} + +/** + * wlan_hdd_config_acs() - config ACS needed parameters + * @hdd_ctx: HDD context + * @adapter: Adapter pointer + * + * This function get ACS related INI paramters and populated + * sap config and smeConfig for ACS needed configurations. + * + * Return: The CDF_STATUS code associated with performing the operation. + */ +CDF_STATUS wlan_hdd_config_acs(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) +{ + tsap_Config_t *sap_config; + struct hdd_config *ini_config; + tHalHandle hal; + + hal = WLAN_HDD_GET_HAL_CTX(adapter); + sap_config = &adapter->sessionCtx.ap.sapConfig; + ini_config = hdd_ctx->config; + + sap_config->enOverLapCh = !!hdd_ctx->config->gEnableOverLapCh; + +#if defined(WLAN_FEATURE_MBSSID) && defined(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 && + con_sap_config->acs_cfg.hw_mode == + sap_config->acs_cfg.hw_mode) { + uint8_t con_sap_st_ch, con_sap_end_ch; + uint8_t cur_sap_st_ch, cur_sap_end_ch; + uint8_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 CDF_STATUS_SUCCESS; +} + +/** + * 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->config->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->config->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->config->vhtChannelWidth; + else + sap_cfg->ch_width_orig = + hdd_ctx->config->nChannelBondingMode24GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + } + sap_cfg->ch_params.ch_width = sap_cfg->ch_width_orig; + sme_set_ch_params(h_hal, sap_cfg->SapHw_mode, sap_cfg->channel, + sap_cfg->sec_ch, &sap_cfg->ch_params); + + 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->config->force_sap_acs_st_ch; + sap_cfg->acs_cfg.end_ch = hdd_ctx->config->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->config->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 HW Mode %d + CH range <%d - %d>"), + 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->config->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->config->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->config->nChannelBondingMode24GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + else + sap_cfg->ch_width_orig = + hdd_ctx->config->nChannelBondingMode5GHz ? + eHT_CHANNEL_WIDTH_40MHZ : + eHT_CHANNEL_WIDTH_20MHZ; + } + sap_cfg->acs_cfg.ch_width = sap_cfg->ch_width_orig; + + hddLog(LOG1, FL("Force ACS Config: HW_MODE: %d ACS_BW: %d"), + sap_cfg->acs_cfg.hw_mode, sap_cfg->acs_cfg.ch_width); + hddLog(LOG1, FL("Force ACS Config: ST_CH: %d END_CH: %d"), + sap_cfg->acs_cfg.start_ch, sap_cfg->acs_cfg.end_ch); + + return 0; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +/** + * wlan_hdd_cfg80211_start_bss() - start bss + * @pHostapdAdapter: Pointer to hostapd adapter + * @params: Pointer to start bss beacon parameters + * + * Return: 0 for success non-zero for failure + */ +static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, + struct beacon_parameters *params) +#else +/** + * wlan_hdd_cfg80211_start_bss() - start bss + * @pHostapdAdapter: Pointer to hostapd adapter + * @params: Pointer to start bss beacon parameters + * @ssid: Pointer ssid + * @ssid_len: Length of ssid + * @hidden_ssid: Hidden SSID parameter + * + * Return: 0 for success non-zero for failure + */ +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; + uint8_t *pIe = NULL; + uint16_t capab_info; + eCsrAuthType RSNAuthType; + eCsrEncryptionType RSNEncryptType; + eCsrEncryptionType mcRSNEncryptType; + int status = CDF_STATUS_SUCCESS, ret; + tpWLAN_SAPEventCB pSapEventCallback; + hdd_hostapd_state_t *pHostapdState; +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = + (WLAN_HDD_GET_CTX(pHostapdAdapter))->pcds_context; +#endif + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); + struct qc_mac_acl_entry *acl_entry = NULL; + int32_t i; + struct hdd_config *iniConfig; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + tSmeConfigParams sme_config; + bool MFPCapable = false; + bool MFPRequired = false; + uint16_t prev_rsn_length = 0; + ENTER(); + + if (cds_is_connection_in_progress(pHddCtx)) { + hdd_err("Can't start BSS: connection is in progress"); + return -EINVAL; + } + + iniConfig = pHddCtx->config; + 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(LOG2, FL("****pConfig->dtim_period=%d***"), + pConfig->dtim_period); + + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) { + pIe = + wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, + pBeacon->tail_len, + WLAN_EID_COUNTRY); + if (pIe) { + pConfig->ieee80211d = 1; + cdf_mem_copy(pConfig->countryCode, &pIe[2], 3); + sme_set_reg_info(hHal, pConfig->countryCode); + sme_apply_channel_power_info_to_fw(hHal); + } 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) { + return ret; + } else { + if (ret == 0) { + if (CDS_IS_DFS_CH(pConfig->channel)) + pHddCtx->dev_dfs_cac_status = + DFS_CAC_NEVER_DONE; + } + } + + if (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pHostapdAdapter, + pConfig->channel)) { + hddLog(LOGE, FL("Invalid Channel [%d]"), + pConfig->channel); + return -EINVAL; + } + + /* reject SAP if DFS channel scan is not allowed */ + if (!(pHddCtx->config->enableDFSChnlScan) && + (CHANNEL_STATE_DFS == cds_get_channel_state( + pConfig->channel))) { + hddLog(LOGE, + FL("not allowed to start SAP on DFS channel")); + return -EOPNOTSUPP; + } + wlansap_set_dfs_ignore_cac(hHal, iniConfig->ignoreCAC); + wlansap_set_dfs_restrict_japan_w53(hHal, + iniConfig->gDisableDfsJapanW53); + 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 + } 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; + } + + capab_info = pMgmt_frame->u.beacon.capab_info; + + pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & + WLAN_CAPABILITY_PRIVACY) ? true : 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(LOGE, + FL("**Wps Ie Length is too small***")); + return -EINVAL; + } else if (memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == + 0) { + hddLog(LOG1, FL("** WPS IE(len %d) ***"), (pIe[1] + 2)); + /* Check 15 bit of WPS IE as it contain information for + * 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 { + hdd_info("WPS disabled"); + pConfig->wps_state = SAP_WPS_DISABLED; + } + /* Forward WPS PBC probe request frame up */ + pConfig->fwdWPSPBCProbeReq = 1; + + 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, + FL("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_unpack_ie(cds_get_context + (CDF_MODULE_ID_SME), + &RSNEncryptType, &mcRSNEncryptType, + &RSNAuthType, &MFPCapable, + &MFPRequired, + pConfig->RSNWPAReqIE[1] + 2, + pConfig->RSNWPAReqIE); + + if (CDF_STATUS_SUCCESS == status) { + /* Now copy over all the security attributes you have + * parsed out. Use the cipher type in the RSN IE + */ + pConfig->RSNEncryptType = RSNEncryptType; + 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_unpack_ie + (cds_get_context(CDF_MODULE_ID_SME), + &RSNEncryptType, + &mcRSNEncryptType, &RSNAuthType, + &MFPCapable, &MFPRequired, + pConfig->RSNWPAReqIE[1] + 2, + pConfig->RSNWPAReqIE); + + if (CDF_STATUS_SUCCESS == status) { + /* Now copy over all the security attributes + * you have parsed out. Use the cipher type + * in the RSN IE + */ + pConfig->RSNEncryptType = RSNEncryptType; + 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(LOGE, + FL("**RSNWPAReqIELength is too large***")); + return -EINVAL; + } + + pConfig->SSIDinfo.ssidHidden = false; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) + if (params->ssid != NULL) { + cdf_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) { + cdf_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 + + cdf_mem_copy(pConfig->self_macaddr.bytes, + pHostapdAdapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + + /* 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->config->conc_custom_rule1) || + (pHddCtx->config->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(LOG1, + FL("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++) { + cdf_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(LOG1, FL("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++) { + cdf_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, + sizeof(qcmacaddr)); + acl_entry++; + } + } + + wlan_hdd_set_sap_hwmode(pHostapdAdapter); + cdf_mem_zero(&sme_config, sizeof(tSmeConfigParams)); + sme_get_config_param(pHddCtx->hHal, &sme_config); + /* Override hostapd.conf wmm_enabled only for 11n and 11AC configs (IOT) + * As per spec 11N/AC STA are QOS STA and may not connect or throughput + * may not be good with non QOS 11N AP + * Default: enable QOS for SAP unless WMM IE not present for 11bga + */ + 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_update_config(pHddCtx->hHal, &sme_config); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + /* 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_80P80) { + if (pHddCtx->isVHT80Allowed == false) + pConfig->ch_width_orig = CH_WIDTH_40MHZ; + else + pConfig->ch_width_orig = CH_WIDTH_80P80MHZ; + } else if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_160) { + if (pHddCtx->isVHT80Allowed == false) + pConfig->ch_width_orig = CH_WIDTH_40MHZ; + else + pConfig->ch_width_orig = CH_WIDTH_160MHZ; + } else if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_80) { + if (pHddCtx->isVHT80Allowed == false) + pConfig->ch_width_orig = CH_WIDTH_40MHZ; + else + pConfig->ch_width_orig = CH_WIDTH_80MHZ; + } else if (pConfig->ch_width_orig == NL80211_CHAN_WIDTH_40) { + pConfig->ch_width_orig = CH_WIDTH_40MHZ; + } else { + pConfig->ch_width_orig = CH_WIDTH_20MHZ; + } + + if (wlan_hdd_setup_driver_overrides(pHostapdAdapter)) + return -EINVAL; + + /* 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_reset_sap_config_add_ie(pConfig, eUPDATE_IE_ALL); + return -EINVAL; + } + /* Uapsd Enabled Bit */ + pConfig->UapsdEnable = iniConfig->apUapsdEnabled; + /* Enable OBSS protection */ + pConfig->obssProtEnabled = iniConfig->apOBSSProtEnabled; + + if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP) + pConfig->sap_dot11mc = + (WLAN_HDD_GET_CTX(pHostapdAdapter))->config->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"), + 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_reset_sap_config_add_ie(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 (!cds_allow_concurrency(pHddCtx, + cds_convert_device_mode_to_hdd_type( + pHostapdAdapter->device_mode), + pConfig->channel, HW_MODE_20_MHZ)) { + hddLog(LOGW, + FL("This concurrency combination is not allowed")); + return -EINVAL; + } + + if (!cds_set_connection_in_progress(pHddCtx, true)) { + hdd_err("Can't start BSS: set connnection in progress failed"); + return -EINVAL; + } + + pConfig->persona = pHostapdAdapter->device_mode; + + pSapEventCallback = hdd_hostapd_sap_event_cb; + + (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->dfs_cac_block_tx = true; + + cdf_event_reset(&pHostapdState->cdf_event); + status = wlansap_start_bss( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pHostapdAdapter), +#else + p_cds_context, +#endif + pSapEventCallback, pConfig, + pHostapdAdapter->dev); + if (!CDF_IS_STATUS_SUCCESS(status)) { + wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_ALL); + cds_set_connection_in_progress(pHddCtx, false); + hddLog(LOGE, FL("SAP Start Bss fail")); + return -EINVAL; + } + + hddLog(LOG1, + FL("Waiting for Scan to complete(auto mode) and BSS to start")); + + status = cdf_wait_single_event(&pHostapdState->cdf_event, 10000); + + wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_ALL); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("ERROR: HDD cdf wait for single_event failed!!")); + cds_set_connection_in_progress(pHddCtx, false); + sme_get_command_q_status(hHal); +#ifdef WLAN_FEATURE_MBSSID + wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); +#else + wlansap_stop_bss(p_cds_context); +#endif + CDF_ASSERT(0); + return -EINVAL; + } + /* Succesfully started Bss update the state bit. */ + set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + /* Initialize WMM configuation */ + hdd_wmm_init(pHostapdAdapter); + cds_incr_active_session(pHddCtx, pHostapdAdapter->device_mode, + pHostapdAdapter->sessionId); +#ifdef DHCP_SERVER_OFFLOAD + if (iniConfig->enableDHCPServerOffload) + wlan_hdd_set_dhcp_server_offload(pHostapdAdapter); +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_P2P_DEBUG + if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) { + if (global_p2p_connection_status == P2P_GO_NEG_COMPLETED) { + global_p2p_connection_status = P2P_GO_COMPLETED_STATE; + hddLog(LOGE, + FL("[P2P State] From Go nego completed to Non-autonomous Group started")); + } else if (global_p2p_connection_status == P2P_NOT_ACTIVE) { + global_p2p_connection_status = P2P_GO_COMPLETED_STATE; + hddLog(LOGE, + FL("[P2P State] From Inactive to Autonomous Group started")); + } + } +#endif + + cds_set_connection_in_progress(pHddCtx, false); + pHostapdState->bCommit = true; + EXIT(); + + return 0; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +/** + * __wlan_hdd_cfg80211_add_beacon() - add beacon in soft ap mode + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * @params: Pointer to add beacon parameters + * + * Return: 0 for success non-zero for failure + */ +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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if (!cds_allow_concurrency(pHddCtx, + cds_convert_device_mode_to_hdd_type( + pAdapter->device_mode), 0, HDD_20_MHZ)) { + hddLog(LOGE, + FL("This concurrency combination is not allowed")); + 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(LOGW, + FL("already beacon info added to session(%d)"), + pAdapter->sessionId); + return -EALREADY; + } + + status = + wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, + &new, params); + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, + 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 + */ +int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_add_beacon(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_beacon() - set beacon in soft ap mode + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * @params: Pointer to set beacon parameters + * + * Return: 0 for success non-zero for failure + */ +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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + 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 != CDF_STATUS_SUCCESS) { + hddLog(LOGE, + 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 + */ +int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_beacon(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +/** + * __wlan_hdd_cfg80211_del_beacon() - stop soft ap + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * + * Return: 0 for success non-zero for failure + */ +static int __wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, + struct net_device *dev) +#else +/** + * __wlan_hdd_cfg80211_stop_ap() - stop soft ap + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * + * Return: 0 for success non-zero for failure + */ +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; + CDF_STATUS status = CDF_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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_STOP_AP, + pAdapter->sessionId, pAdapter->device_mode)); + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + return -EOPNOTSUPP; + } + + hddLog(LOG1, FL("Device_mode %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_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")); + CDF_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->config->conc_custom_rule1 && + (WLAN_HDD_SOFTAP == pAdapter->device_mode)) { + cds_flush_work(&pHddCtx->sap_start_work); + hddLog(LOGW, FL("Canceled the pending restart work")); + spin_lock(&pHddCtx->sap_update_info_lock); + pHddCtx->is_sap_restart_required = false; + spin_unlock(&pHddCtx->sap_update_info_lock); + } + pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false; + if (pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) + cdf_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list); + cdf_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(LOGE, + 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); + + cdf_event_reset(&pHostapdState->cdf_stop_bss_event); +#ifdef WLAN_FEATURE_MBSSID + status = wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter)); +#else + status = wlansap_stop_bss(pHddCtx->pcds_context); +#endif + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + cdf_wait_single_event(&pHostapdState-> + cdf_stop_bss_event, + 10000); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("HDD cdf wait for single_event failed!!")); + CDF_ASSERT(0); + } + } + clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags); + /*BSS stopped, clear the active sessions for this device mode*/ + cds_decr_session_set_pcl(pHddCtx, + pAdapter->device_mode, + pAdapter->sessionId); + pAdapter->sessionCtx.ap.beacon = NULL; + kfree(old); + } + mutex_unlock(&pHddCtx->sap_lock); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("Stopping the BSS")); + return -EINVAL; + } + + cdf_mem_copy(updateIE.bssid, pAdapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = pAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = true; + updateIE.notify = true; + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, + eUPDATE_IE_PROBE_BCN) == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } + + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter), + &updateIE, + eUPDATE_IE_ASSOC_RESP) == CDF_STATUS_E_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) && + (global_p2p_connection_status == P2P_GO_COMPLETED_STATE)) { + hddLog(LOGE, + "[P2P State] From GO completed to Inactive state GO got removed"); + global_p2p_connection_status = P2P_NOT_ACTIVE; + } +#endif + EXIT(); + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +/** + * wlan_hdd_get_channel_bw() - get channel bandwidth + * @width: input channel width in nl80211_chan_width value + * + * Return: channel width value defined by driver + */ +static enum hw_mode_bandwidth wlan_hdd_get_channel_bw( + enum nl80211_chan_width width) +{ + enum hw_mode_bandwidth ch_bw = HW_MODE_20_MHZ; + + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + ch_bw = HW_MODE_20_MHZ; + break; + case NL80211_CHAN_WIDTH_40: + ch_bw = HW_MODE_40_MHZ; + break; + case NL80211_CHAN_WIDTH_80: + ch_bw = HW_MODE_80_MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + ch_bw = HW_MODE_80_PLUS_80_MHZ; + break; + case NL80211_CHAN_WIDTH_160: + ch_bw = HW_MODE_160_MHZ; + break; + default: + hdd_err("Invalid width: %d, using default 20MHz", width); + break; + } + + return ch_bw; +} +#endif + +#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 + */ +int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_del_beacon(wiphy, dev); + cds_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 + */ +int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_stop_ap(wiphy, dev); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) +/** + * __wlan_hdd_cfg80211_start_ap() - start soft ap mode + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * @params: Pointer to AP settings parameters + * + * Return: 0 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) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + tSirWifiChannelWidth channel_width; + int status; + uint8_t channel; + p_cds_contextType p_cds_context; + + ENTER(); + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hdd_err("Invalid CDS context"); + return -EINVAL; + } + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_START_AP, pAdapter->sessionId, + params->beacon_interval)); + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + hddLog(LOGE, FL("HDD adapter magic is invalid")); + return -ENODEV; + } + + 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; + } + + hddLog(LOG2, FL("pAdapter = %p, Device mode %s(%d)"), pAdapter, + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) + channel_width = wlan_hdd_get_channel_bw(params->chandef.width); + channel = ieee80211_frequency_to_channel( + params->chandef.chan->center_freq); +#else + channel_width = HW_MODE_20_MHZ; + channel = 0; +#endif + /* check if concurrency is allowed */ + if (!cds_allow_concurrency(pHddCtx, + cds_convert_device_mode_to_hdd_type( + pAdapter->device_mode), + channel, + channel_width)) { + hdd_err("Connection failed due to concurrency check failure"); + return -EINVAL; + } + if (pHddCtx->config->policy_manager_enabled) { + status = cdf_event_reset( + &p_cds_context->connection_update_done_evt); + if (!CDF_IS_STATUS_SUCCESS(status)) + hdd_err("ERR: clear event failed"); + + status = cds_current_connections_update(pHddCtx, channel); + if (CDF_STATUS_E_FAILURE == status) { + hdd_err("ERROR: connections update failed!!"); + return -EINVAL; + } + + if (CDF_STATUS_SUCCESS == status) { + status = cdf_wait_single_event( + &p_cds_context->connection_update_done_evt, + CONNECTION_UPDATE_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("ERROR: cdf wait for event failed!!"); + 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)) + enum nl80211_channel_type channel_type; +#endif + + old = pAdapter->sessionCtx.ap.beacon; + + if (old) + return -EALREADY; + + status = + wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, + ¶ms->beacon, + params->dtim_period); + + if (status != 0) { + hddLog(LOGE, FL("Error!!! Allocating the new beacon")); + return -EINVAL; + } + pAdapter->sessionCtx.ap.beacon = new; + + if (params->chandef.width < NL80211_CHAN_WIDTH_80) + channel_type = cfg80211_get_chandef_type( + &(params->chandef)); + else + channel_type = NL80211_CHAN_HT40PLUS; + + + wlan_hdd_set_channel(wiphy, dev, + ¶ms->chandef, + channel_type); + + /* 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)) + 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); + } + + 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 + */ +int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_start_ap(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_change_beacon() - change beacon for sofatap/p2p go + * @wiphy: Pointer to wiphy structure + * @dev: Pointer to net_device structure + * @params: Pointer to change beacon parameters + * + * Return: 0 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) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + beacon_data_t *old, *new; + int status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || + pAdapter->device_mode == WLAN_HDD_P2P_GO)) { + return -EOPNOTSUPP; + } + + old = pAdapter->sessionCtx.ap.beacon; + + if (!old) { + hddLog(LOGE, 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 != CDF_STATUS_SUCCESS) { + hddLog(LOGE, 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 + */ +int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *params) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_change_beacon(wiphy, dev, params); + cds_ssr_unprotect(__func__); + + return ret; +} + +#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) */ diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h new file mode 100644 index 000000000000..02965d8457f7 --- /dev/null +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -0,0 +1,128 @@ +/* + * 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 + +/** + * DOC: wlan_hdd_hostapd.h + * + * WLAN Host Device driver hostapd header file + */ + +/* Include files */ + +#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, uint8_t *name); + +CDF_STATUS hdd_register_hostapd(hdd_adapter_t *pAdapter, uint8_t rtnl_held); + +CDF_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held); + +eCsrAuthType +hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]); + +eCsrEncryptionType +hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]); + +eCsrEncryptionType +hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]); + +eCsrAuthType +hdd_translate_wpa_to_csr_auth_type(uint8_t auth_suite[4]); + +eCsrEncryptionType +hdd_translate_wpa_to_csr_encryption_type(uint8_t cipher_suite[4]); + +CDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *, + struct tagCsrDelStaParams *); +void hdd_softap_sta_disassoc(hdd_adapter_t *, uint8_t *); +void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *, bool); +int hdd_softap_unpack_ie(tHalHandle halHandle, + eCsrEncryptionType *pEncryptType, + eCsrEncryptionType *mcEncryptType, + eCsrAuthType *pAuthType, + bool *pMFPCapable, + bool *pMFPRequired, + uint16_t gen_ie_len, uint8_t *gen_ie); + +CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, + void *usrDataForCallback); +CDF_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 +CDF_STATUS hdd_set_sap_ht2040_mode(hdd_adapter_t *pHostapdAdapter, + uint8_t channel_type); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params); + +int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct beacon_parameters *params); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) +int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, + struct net_device *dev); +#else +int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, + struct net_device *dev); +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) +int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params); +#endif + +int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_beacon_data *params); + +CDF_STATUS wlan_hdd_config_acs(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter); +#endif /* end #if !defined(WLAN_HDD_HOSTAPD_H) */ diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c new file mode 100644 index 000000000000..43c213ffa348 --- /dev/null +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -0,0 +1,6314 @@ +/* + * 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 Files */ + +#include +#include +#include "wlan_hdd_trace.h" +#include "wlan_hdd_ioctl.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_driver_ops.h" +#include "cds_concurrency.h" + +#include "wlan_hdd_p2p.h" +#include +#include "wma.h" +#include "wlan_hdd_napi.h" + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#include +#include +#endif +#include "hif.h" + +#if defined(LINUX_QCMBR) +#define SIOCIOCTLTX99 (SIOCDEVPRIVATE+13) +#endif + +/* + * Size of Driver command strings from upper layer + */ +#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */ +#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */ + + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define TID_MIN_VALUE 0 +#define TID_MAX_VALUE 15 +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/* + * Maximum buffer size used for returning the data back to user space + */ +#define WLAN_MAX_BUF_SIZE 1024 +#define WLAN_PRIV_DATA_MAX_LEN 8192 + +/* + * Driver miracast parameters 0-Disabled + * 1-Source, 2-Sink + */ +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0 +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2 + +/* + * When ever we need to print IBSSPEERINFOALL for more than 16 STA + * we will split the printing. + */ +#define NUM_OF_STA_DATA_TO_PRINT 16 + +/* + * Android DRIVER command structures + */ +struct android_wifi_reassoc_params { + unsigned char bssid[18]; + int channel; +}; + +#define ANDROID_WIFI_ACTION_FRAME_SIZE 1040 +struct android_wifi_af_params { + unsigned char bssid[18]; + int channel; + int dwell_time; + int len; + unsigned char data[ANDROID_WIFI_ACTION_FRAME_SIZE]; +}; + +/* + * Define HDD driver command handling entry, each contains a command + * string and the handler. + */ +typedef int (*hdd_drv_cmd_handler_t)(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *cmd, + uint8_t cmd_name_len, + hdd_priv_data_t *priv_data); + +typedef struct { + const char *cmd; + hdd_drv_cmd_handler_t handler; +} hdd_drv_cmd_t; + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define WLAN_WAIT_TIME_READY_TO_EXTWOW 2000 +#define WLAN_HDD_MAX_TCP_PORT 65535 +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static void hdd_get_tsm_stats_cb(tAniTrafStrmMetrics tsm_metrics, + const uint32_t staId, void *context) +{ + struct statsContext *stats_context = NULL; + hdd_adapter_t *adapter = NULL; + + if (NULL == context) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Bad param, context [%p]", __func__, context); + 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); + + stats_context = context; + adapter = stats_context->pAdapter; + if ((NULL == adapter) || + (STATS_CONTEXT_MAGIC != stats_context->magic)) { + /* + * the caller presumably timed out so there is + * nothing we can do + */ + spin_unlock(&hdd_context_lock); + hddLog(CDF_TRACE_LEVEL_WARN, + "%s: Invalid context, adapter [%p] magic [%08x]", + __func__, adapter, stats_context->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + stats_context->magic = 0; + + /* copy over the tsm stats */ + adapter->tsmStats.UplinkPktQueueDly = tsm_metrics.UplinkPktQueueDly; + cdf_mem_copy(adapter->tsmStats.UplinkPktQueueDlyHist, + tsm_metrics.UplinkPktQueueDlyHist, + sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) / + sizeof(adapter->tsmStats.UplinkPktQueueDlyHist[0])); + adapter->tsmStats.UplinkPktTxDly = tsm_metrics.UplinkPktTxDly; + adapter->tsmStats.UplinkPktLoss = tsm_metrics.UplinkPktLoss; + adapter->tsmStats.UplinkPktCount = tsm_metrics.UplinkPktCount; + adapter->tsmStats.RoamingCount = tsm_metrics.RoamingCount; + adapter->tsmStats.RoamingDly = tsm_metrics.RoamingDly; + + /* notify the caller */ + complete(&stats_context->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +static +CDF_STATUS hdd_get_tsm_stats(hdd_adapter_t *adapter, + const uint8_t tid, + tAniTrafStrmMetrics *tsm_metrics) +{ + hdd_station_ctx_t *hdd_sta_ctx = NULL; + CDF_STATUS hstatus; + CDF_STATUS vstatus = CDF_STATUS_SUCCESS; + unsigned long rc; + struct statsContext context; + hdd_context_t *hdd_ctx = NULL; + + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: adapter is NULL", __func__); + return CDF_STATUS_E_FAULT; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + /* we are connected prepare our callback context */ + init_completion(&context.completion); + context.pAdapter = adapter; + context.magic = STATS_CONTEXT_MAGIC; + + /* query tsm stats */ + hstatus = sme_get_tsm_stats(hdd_ctx->hHal, hdd_get_tsm_stats_cb, + hdd_sta_ctx->conn_info.staId[0], + hdd_sta_ctx->conn_info.bssId, + &context, hdd_ctx->pcds_context, tid); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics", __func__); + vstatus = CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: SME timed out while retrieving statistics", + __func__); + vstatus = CDF_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 (CDF_STATUS_SUCCESS == vstatus) { + tsm_metrics->UplinkPktQueueDly = + adapter->tsmStats.UplinkPktQueueDly; + cdf_mem_copy(tsm_metrics->UplinkPktQueueDlyHist, + adapter->tsmStats.UplinkPktQueueDlyHist, + sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) / + sizeof(adapter->tsmStats. + UplinkPktQueueDlyHist[0])); + tsm_metrics->UplinkPktTxDly = adapter->tsmStats.UplinkPktTxDly; + tsm_metrics->UplinkPktLoss = adapter->tsmStats.UplinkPktLoss; + tsm_metrics->UplinkPktCount = adapter->tsmStats.UplinkPktCount; + tsm_metrics->RoamingCount = adapter->tsmStats.RoamingCount; + tsm_metrics->RoamingDly = adapter->tsmStats.RoamingDly; + } + return vstatus; +} +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +static void hdd_get_band_helper(hdd_context_t *hdd_ctx, int *pBand) +{ + eCsrBand band = -1; + sme_get_freq_band((tHalHandle) (hdd_ctx->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(CDF_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, + band); + *pBand = -1; + break; + } +} + +/** + * _hdd_parse_bssid_and_chan() - helper function to parse bssid and channel + * @data: input data + * @target_ap_bssid: pointer to bssid (output parameter) + * @channel: pointer to channel (output parameter) + * + * Return: 0 if parsing is successful; -EINVAL otherwise + */ +static int _hdd_parse_bssid_and_chan(const uint8_t **data, + uint8_t *bssid, + uint8_t *channel) +{ + const uint8_t *in_ptr; + int v = 0; + int temp_int; + uint8_t temp_buf[32]; + + /* 12 hexa decimal digits, 5 ':' and '\0' */ + uint8_t mac_addr[18]; + + if (!data || !*data) + return -EINVAL; + + in_ptr = *data; + + in_ptr = strnchr(in_ptr, strlen(in_ptr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == in_ptr) + goto error; + /* no space after the command */ + else if (SPACE_ASCII_VALUE != *in_ptr) + goto error; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *in_ptr) && ('\0' != *in_ptr)) + in_ptr++; + + /* no argument followed by spaces */ + if ('\0' == *in_ptr) + goto error; + + v = sscanf(in_ptr, "%17s", mac_addr); + if (!((1 == v) && hdd_is_valid_mac_address(mac_addr))) { + hddLog(LOGE, + FL( + "Invalid MAC address or All hex inputs are not read (%d)" + ), + v); + goto error; + } + + bssid[0] = hex_to_bin(mac_addr[0]) << 4 | + hex_to_bin(mac_addr[1]); + bssid[1] = hex_to_bin(mac_addr[3]) << 4 | + hex_to_bin(mac_addr[4]); + bssid[2] = hex_to_bin(mac_addr[6]) << 4 | + hex_to_bin(mac_addr[7]); + bssid[3] = hex_to_bin(mac_addr[9]) << 4 | + hex_to_bin(mac_addr[10]); + bssid[4] = hex_to_bin(mac_addr[12]) << 4 | + hex_to_bin(mac_addr[13]); + bssid[5] = hex_to_bin(mac_addr[15]) << 4 | + hex_to_bin(mac_addr[16]); + + /* point to the next argument */ + in_ptr = strnchr(in_ptr, strlen(in_ptr), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == in_ptr) + goto error; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *in_ptr) && ('\0' != *in_ptr)) + in_ptr++; + + /* no argument followed by spaces */ + if ('\0' == *in_ptr) + goto error; + + /* get the next argument ie the channel number */ + v = sscanf(in_ptr, "%31s ", temp_buf); + if (1 != v) + goto error; + + v = kstrtos32(temp_buf, 10, &temp_int); + if ((v < 0) || (temp_int < 0) || + (temp_int > WNI_CFG_CURRENT_CHANNEL_STAMAX)) + return -EINVAL; + + *channel = temp_int; + *data = in_ptr; + return 0; +error: + *data = in_ptr; + return -EINVAL; +} + +/** + * hdd_parse_send_action_frame_data() - HDD Parse send action frame data + * @pValue: Pointer to input data + * @pTargetApBssid: Pointer to target Ap bssid + * @pChannel: Pointer to the Target AP channel + * @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 uint8_t *pValue, + uint8_t *pTargetApBssid, + uint8_t *pChannel, uint8_t *pDwellTime, + uint8_t **pBuf, uint8_t *pBufLen) +{ + const uint8_t *inPtr = pValue; + const uint8_t *dataEnd; + int tempInt; + int j = 0; + int i = 0; + int v = 0; + uint8_t tempBuf[32]; + uint8_t tempByte = 0; + + if (_hdd_parse_bssid_and_chan(&inPtr, pTargetApBssid, pChannel)) + return -EINVAL; + + /* 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 = cdf_mem_malloc((*pBufLen + 1) / 2); + if (NULL == *pBuf) { + hddLog(LOGE, FL("cdf_mem_alloc failed")); + return -ENOMEM; + } + + /* 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 = hex_to_bin(inPtr[j]); + } else { + tempByte = + (hex_to_bin(inPtr[j]) << 4) | + (hex_to_bin(inPtr[j + 1])); + } + (*pBuf)[i++] = tempByte; + } + *pBufLen = i; + return 0; +} + +/** + * hdd_parse_reassoc_command_data() - HDD Parse reassoc command data + * @pValue: Pointer to input data (its a NULL 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 uint8_t *pValue, + uint8_t *pTargetApBssid, + uint8_t *pChannel) +{ + const uint8_t *inPtr = pValue; + + if (_hdd_parse_bssid_and_chan(&inPtr, pTargetApBssid, pChannel)) + return -EINVAL; + + return 0; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/** + * hdd_reassoc() - perform a userspace-directed reassoc + * @adapter: Adapter upon which the command was received + * @bssid: BSSID with which to reassociate + * @channel: channel upon which to reassociate + * + * This function performs a userspace-directed reassoc operation + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_reassoc(hdd_adapter_t *adapter, const uint8_t *bssid, + const uint8_t channel) +{ + hdd_station_ctx_t *pHddStaCtx; + int ret = 0; + + if (WLAN_HDD_INFRA_STATION != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hddLog(CDF_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.bytes, + CDF_MAC_ADDR_SIZE)) { + hddLog(LOG1, + FL("Reassoc BSSID is same as currently associated AP bssid")); + ret = -EINVAL; + goto exit; + } + + /* Check channel number is a valid channel number */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(adapter, channel)) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid Channel %d", + __func__, channel); + ret = -EINVAL; + goto exit; + } + + /* Proceed with reassoc */ + { + tCsrHandoffRequest handoffInfo; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + handoffInfo.channel = channel; + handoffInfo.src = REASSOC; + cdf_mem_copy(handoffInfo.bssid.bytes, bssid, CDF_MAC_ADDR_SIZE); + sme_handoff_request(hdd_ctx->hHal, adapter->sessionId, + &handoffInfo); + } +exit: + return ret; +} + +/** + * hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command + * @adapter: Adapter upon which the command was received + * @command: ASCII text command that was received + * + * 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 + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_reassoc_v1(hdd_adapter_t *adapter, const char *command) +{ + uint8_t channel = 0; + tSirMacAddr bssid; + int ret; + + ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel); + if (ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse reassoc command data", __func__); + } else { + ret = hdd_reassoc(adapter, bssid, channel); + } + return ret; +} + +/** + * hdd_parse_reassoc_v2() - parse version 2 of the REASSOC command + * @adapter: Adapter upon which the command was received + * @command: Command that was received, ASCII command + * followed by binary data + * + * This function parses the v2 REASSOC command with the format + * + * REASSOC + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, 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(adapter, bssid, params.channel); + } + return ret; +} + +/** + * hdd_parse_reassoc() - parse the REASSOC command + * @adapter: Adapter upon which the command was received + * @command: Command that was received + * + * 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. + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_reassoc(hdd_adapter_t *adapter, 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(adapter, command); + } else { + ret = hdd_parse_reassoc_v2(adapter, command); + } + + return ret; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/** + * hdd_sendactionframe() - send a userspace-supplied action frame + * @adapter: Adapter upon which the command was received + * @bssid: BSSID target of the action frame + * @channel: Channel upon which to send the frame + * @dwell_time: Amount of time to dwell when the frame is sent + * @payload_len:Length of the payload + * @payload: Payload of the frame + * + * This function sends a userspace-supplied action frame + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_sendactionframe(hdd_adapter_t *adapter, const uint8_t *bssid, + const uint8_t channel, const uint8_t dwell_time, + const uint8_t payload_len, const uint8_t *payload) +{ + struct ieee80211_channel chan; + uint8_t frame_len; + uint8_t *frame; + struct ieee80211_hdr_3addr *hdr; + u64 cookie; + hdd_station_ctx_t *pHddStaCtx; + hdd_context_t *hdd_ctx; + int ret = 0; + tpSirMacVendorSpecificFrameHdr pVendorSpecific = + (tpSirMacVendorSpecificFrameHdr) payload; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) + struct cfg80211_mgmt_tx_params params; +#endif + + if (WLAN_HDD_INFRA_STATION != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + /* if not associated, no need to send action frame */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hddLog(CDF_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.bytes, + CDF_MAC_ADDR_SIZE)) { + hddLog(LOG1, FL("STA is not associated to this AP")); + ret = -EINVAL; + goto exit; + } + + chan.center_freq = sme_chn_to_freq(channel); + /* Check if it is specific action frame */ + if (pVendorSpecific->category == + SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY) { + static const uint8_t Oui[] = { 0x00, 0x00, 0xf0 }; + if (cdf_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(CDF_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_abort_roam_scan(hdd_ctx->hHal, + adapter->sessionId); + } else { + /* + * 0 is accepted as current home channel, + * delayed transmission of action frame is ok. + */ + chan.center_freq = + sme_chn_to_freq(pHddStaCtx->conn_info. + operationChannel); + } + } + } + if (chan.center_freq == 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s:invalid channel number %d", + __func__, channel); + ret = -EINVAL; + goto exit; + } + + frame_len = payload_len + 24; + frame = cdf_mem_malloc(frame_len); + if (!frame) { + hddLog(LOGE, FL("memory allocation failed")); + ret = -ENOMEM; + goto exit; + } + cdf_mem_zero(frame, frame_len); + + hdr = (struct ieee80211_hdr_3addr *)frame; + hdr->frame_control = + cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); + cdf_mem_copy(hdr->addr1, bssid, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(hdr->addr2, adapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(hdr->addr3, bssid, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(hdr + 1, payload, payload_len); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) + 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, &adapter->wdev, ¶ms, &cookie); +#else + ret = wlan_hdd_mgmt_tx(NULL, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + &(adapter->wdev), +#else + adapter->dev, +#endif + &chan, 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + NL80211_CHAN_HT20, 1, +#endif + dwell_time, frame, frame_len, 1, 1, &cookie); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ + + cdf_mem_free(frame); +exit: + return ret; +} + +/** + * hdd_parse_sendactionframe_v1() - parse version 1 of the + * SENDACTIONFRAME command + * @adapter: Adapter upon which the command was received + * @command: ASCII text command that was received + * + * 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 + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_sendactionframe_v1(hdd_adapter_t *adapter, const char *command) +{ + uint8_t channel = 0; + uint8_t dwell_time = 0; + uint8_t payload_len = 0; + uint8_t *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(CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse send action frame data", __func__); + } else { + ret = hdd_sendactionframe(adapter, bssid, channel, + dwell_time, payload_len, payload); + cdf_mem_free(payload); + } + + return ret; +} + +/** + * hdd_parse_sendactionframe_v2() - parse version 2 of the + * SENDACTIONFRAME command + * @adapter: Adapter upon which the command was received + * @command: Command that was received, ASCII command + * followed by binary data + * + * 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 *adapter, const char *command) +{ + struct android_wifi_af_params *params; + tSirMacAddr bssid; + int ret; + + /* params are large so keep off the stack */ + params = kmalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + /* The params are located after "SENDACTIONFRAME " */ + memcpy(params, command + 16, sizeof(*params)); + + if (!mac_pton(params->bssid, (u8 *) &bssid)) { + hddLog(LOGE, "%s: MAC address parsing failed", __func__); + ret = -EINVAL; + } else { + ret = hdd_sendactionframe(adapter, bssid, params->channel, + params->dwell_time, params->len, + params->data); + } + kfree(params); + return ret; +} + +/** + * hdd_parse_sendactionframe() - parse the SENDACTIONFRAME command + * @adapter: Adapter upon which the command was received + * @command: Command that was received + * + * 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. + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_sendactionframe(hdd_adapter_t *adapter, const char *command) +{ + int ret; + + /* + * both versions start with "SENDACTIONFRAME " + * v1 has a bssid and other parameters as an ASCII string + * SENDACTIONFRAME xx:xx:xx:xx:xx:xx CH DWELL LEN FRAME + * v2 has a C struct + * SENDACTIONFRAME + * + * The first field in the v2 struct is also the bssid in ASCII. + * But in the case of a v2 message the BSSID is NUL-terminated. + * Hence we can peek at that offset to see if this is V1 or V2 + * SENDACTIONFRAME xx:xx:xx:xx:xx:xx* + * 111111111122222222223333 + * 0123456789012345678901234567890123 + */ + if (command[33]) { + ret = hdd_parse_sendactionframe_v1(adapter, command); + } else { + ret = hdd_parse_sendactionframe_v2(adapter, command); + } + + return ret; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +/** + * hdd_parse_channellist() - HDD Parse channel list + * @pValue: Pointer to input channel list + * @ChannelList: Pointer to local output array to record + * channel list + * @pNumChannels: Pointer to number of roam scan channels + * + * This function parses the channel list passed in the format + * SETROAMSCANCHANNELSChannel 1Channel 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 uint8_t *pValue, uint8_t *pChannelList, + uint8_t *pNumChannels) +{ + const uint8_t *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; + } + + /* no space after the command */ + else if (SPACE_ASCII_VALUE != *inPtr) { + return -EINVAL; + } + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) + inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) { + return -EINVAL; + } + + /* get 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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + } + } + + /* remove 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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Channel %d added to preferred channel list", + pChannelList[j]); + } + + return 0; +} + +/** + * hdd_parse_set_roam_scan_channels_v1() - parse version 1 of the + * SETROAMSCANCHANNELS command + * @adapter: Adapter upon which the command was received + * @command: ASCII text command that was received + * + * 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 + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_set_roam_scan_channels_v1(hdd_adapter_t *adapter, + const char *command) +{ + uint8_t channel_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t num_chan = 0; + CDF_STATUS status; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; + + ret = hdd_parse_channellist(command, channel_list, &num_chan); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse channel list information", + __func__); + goto exit; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL, + adapter->sessionId, num_chan)); + + if (num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_change_roam_scan_channel_list(hdd_ctx->hHal, + adapter->sessionId, + channel_list, num_chan); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", + __func__); + ret = -EINVAL; + goto exit; + } +exit: + return ret; +} + +/** + * hdd_parse_set_roam_scan_channels_v2() - parse version 2 of the + * SETROAMSCANCHANNELS command + * @adapter: Adapter upon which the command was received + * @command: Command that was received, ASCII command + * followed by binary data + * + * 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] + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_set_roam_scan_channels_v2(hdd_adapter_t *adapter, + const char *command) +{ + const uint8_t *value; + uint8_t channel_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t channel; + uint8_t num_chan; + int i; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + CDF_STATUS 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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL, + adapter->sessionId, num_chan)); + + for (i = 0; i < num_chan; i++) { + channel = *value++; + if (channel > WNI_CFG_CURRENT_CHANNEL_STAMAX) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: index %d invalid channel %d", __func__, + i, channel); + ret = -EINVAL; + goto exit; + } + channel_list[i] = channel; + } + status = + sme_change_roam_scan_channel_list(hdd_ctx->hHal, + adapter->sessionId, + channel_list, num_chan); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", + __func__); + ret = -EINVAL; + goto exit; + } +exit: + return ret; +} + +/** + * hdd_parse_set_roam_scan_channels() - parse the + * SETROAMSCANCHANNELS command + * @adapter: Adapter upon which the command was received + * @command: Command that was received + * + * There are two different versions of the SETROAMSCANCHANNELS command. + * Version 1 of the command contains a parameter list that is ASCII + * characters whereas version 2 contains a binary payload. Determine + * if a version 1 or a version 2 command is being parsed by examining + * the parameters, and then dispatch the parser that is appropriate for + * the command. + * + * Return: 0 for success non-zero for failure + */ +static int +hdd_parse_set_roam_scan_channels(hdd_adapter_t *adapter, 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(adapter, command); + } else { + ret = hdd_parse_set_roam_scan_channels_v2(adapter, command); + } + + return ret; +} +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * hdd_parse_plm_cmd() - HDD Parse Plm command + * @pValue: Pointer to input data + * @pPlmRequest:Pointer to output struct tpSirPlmReq + * + * This function parses the plm command passed in the format + * CCXPLMREQ + * + * + * + * + * + * Return: 0 for success non-zero for failure + */ +CDF_STATUS hdd_parse_plm_cmd(uint8_t *pValue, tSirPlmReq *pPlmRequest) +{ + uint8_t *cmdPtr = NULL; + int count, content = 0, ret = 0; + char buf[32]; + + /* move to argument list */ + cmdPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* no space after the command */ + if (SPACE_ASCII_VALUE != *cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* START/STOP PLM req */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->enable = content; + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove 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 CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->diag_token = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "diag token %d", + pPlmRequest->diag_token); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove 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 CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->meas_token = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "meas token %d", + pPlmRequest->meas_token); + + hddLog(CDF_TRACE_LEVEL_ERROR, + "PLM req %s", pPlmRequest->enable ? "START" : "STOP"); + if (pPlmRequest->enable) { + + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove 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 CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->numBursts = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "num burst %d", + pPlmRequest->numBursts); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* burst interval in seconds */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content <= 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->burstInt = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "burst Int %d", + pPlmRequest->burstInt); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove 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 CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content <= 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->measDuration = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "measDur %d", + pPlmRequest->measDuration); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* burst length of PLM bursts */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content <= 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->burstLen = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "burstLen %d", + pPlmRequest->burstLen); + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove 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 CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content <= 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->desiredTxPwr = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, + "desiredTxPwr %d", pPlmRequest->desiredTxPwr); + + for (count = 0; count < CDF_MAC_ADDR_SIZE; count++) { + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) + && ('\0' != *cmdPtr)) + cmdPtr++; + + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 16, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->macAddr[count] = content; + } + + hddLog(CDF_TRACE_LEVEL_DEBUG, "MC addr " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPlmRequest->macAddr)); + + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) && ('\0' != *cmdPtr)) + cmdPtr++; + + /* number of channels */ + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content < 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->plmNumCh = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, "numch %d", + pPlmRequest->plmNumCh); + + /* Channel numbers */ + for (count = 0; count < pPlmRequest->plmNumCh; count++) { + cmdPtr = strpbrk(cmdPtr, " "); + + if (NULL == cmdPtr) + return CDF_STATUS_E_FAILURE; + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *cmdPtr) + && ('\0' != *cmdPtr)) + cmdPtr++; + + ret = sscanf(cmdPtr, "%31s ", buf); + if (1 != ret) + return CDF_STATUS_E_FAILURE; + + ret = kstrtos32(buf, 10, &content); + if (ret < 0) + return CDF_STATUS_E_FAILURE; + + if (content <= 0) + return CDF_STATUS_E_FAILURE; + + pPlmRequest->plmChList[count] = content; + hddLog(CDF_TRACE_LEVEL_DEBUG, " ch- %d", + pPlmRequest->plmChList[count]); + } + } + /* If PLM START */ + return CDF_STATUS_SUCCESS; +} +#endif + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +static void wlan_hdd_ready_to_extwow(void *callbackContext, bool is_success) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) callbackContext; + int rc; + + rc = wlan_hdd_validate_context(hdd_ctx); + if (0 != rc) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + hdd_ctx->ext_wow_should_suspend = is_success; + complete(&hdd_ctx->ready_to_extwow); +} + +static int hdd_enable_ext_wow(hdd_adapter_t *adapter, + tpSirExtWoWParams arg_params) +{ + tSirExtWoWParams params; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); + int rc; + + cdf_mem_copy(¶ms, arg_params, sizeof(params)); + + INIT_COMPLETION(hdd_ctx->ready_to_extwow); + + cdf_ret_status = sme_configure_ext_wo_w(hHal, ¶ms, + &wlan_hdd_ready_to_extwow, + hdd_ctx); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("sme_configure_ext_wo_w returned failure %d"), + cdf_ret_status); + return -EPERM; + } + + rc = wait_for_completion_timeout(&hdd_ctx->ready_to_extwow, + msecs_to_jiffies(WLAN_WAIT_TIME_READY_TO_EXTWOW)); + if (!rc) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to get ready to extwow", __func__); + return -EPERM; + } + + if (hdd_ctx->ext_wow_should_suspend) { + if (hdd_ctx->config->extWowGotoSuspend) { + pm_message_t state; + + state.event = PM_EVENT_SUSPEND; + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received ready to ExtWoW. Going to suspend", + __func__); + + rc = wlan_hdd_cfg80211_suspend_wlan(hdd_ctx->wiphy, NULL); + if (rc < 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: wlan_hdd_cfg80211_suspend_wlan failed, error = %d", + __func__, rc); + return rc; + } + cdf_ret_status = wlan_hdd_bus_suspend(state); + if (cdf_ret_status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: wlan_hdd_suspend failed, status = %d", + __func__, cdf_ret_status); + wlan_hdd_cfg80211_resume_wlan(hdd_ctx->wiphy); + return -EPERM; + } + } + } else { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Received ready to ExtWoW failure", __func__); + return -EPERM; + } + + return 0; +} + +static int hdd_enable_ext_wow_parser(hdd_adapter_t *adapter, int vdev_id, + int value) +{ + tSirExtWoWParams params; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int rc; + + rc = wlan_hdd_validate_context(hdd_ctx); + if (0 != rc) { + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("Invalid type")); + return -EINVAL; + } + + if (value == EXT_WOW_TYPE_APP_TYPE1 && + hdd_ctx->is_extwow_app_type1_param_set) + params.type = value; + else if (value == EXT_WOW_TYPE_APP_TYPE2 && + hdd_ctx->is_extwow_app_type2_param_set) + params.type = value; + else if (value == EXT_WOW_TYPE_APP_TYPE1_2 && + hdd_ctx->is_extwow_app_type1_param_set && + hdd_ctx->is_extwow_app_type2_param_set) + params.type = value; + else { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Set app params before enable it value %d"), value); + return -EINVAL; + } + + params.vdev_id = vdev_id; + params.wakeup_pin_num = hdd_ctx->config->extWowApp1WakeupPinNumber | + (hdd_ctx->config->extWowApp2WakeupPinNumber + << 8); + + return hdd_enable_ext_wow(adapter, ¶ms); +} + +static int hdd_set_app_type1_params(tHalHandle hHal, + tpSirAppType1Params arg_params) +{ + tSirAppType1Params params; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + cdf_mem_copy(¶ms, arg_params, sizeof(params)); + + cdf_ret_status = sme_configure_app_type1_params(hHal, ¶ms); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("sme_configure_app_type1_params returned failure %d"), + cdf_ret_status); + return -EPERM; + } + + return 0; +} + +static int hdd_set_app_type1_parser(hdd_adapter_t *adapter, + char *arg, int len) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); + char id[20], password[20]; + tSirAppType1Params params; + int rc, i; + + rc = wlan_hdd_validate_context(hdd_ctx); + if (0 != rc) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (2 != sscanf(arg, "%8s %16s", id, password)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Invalid Number of arguments")); + return -EINVAL; + } + + memset(¶ms, 0, sizeof(tSirAppType1Params)); + params.vdev_id = adapter->sessionId; + for (i = 0; i < ETHER_ADDR_LEN; i++) + params.wakee_mac_addr[i] = + adapter->macAddressCurrent.bytes[i]; + + params.id_length = strlen(id); + cdf_mem_copy(params.identification_id, id, params.id_length); + params.pass_length = strlen(password); + cdf_mem_copy(params.password, password, params.pass_length); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + cdf_mem_copy(¶ms, arg_params, sizeof(params)); + + cdf_ret_status = sme_configure_app_type2_params(hHal, ¶ms); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("sme_configure_app_type2_params returned failure %d"), + cdf_ret_status); + return -EPERM; + } + + return 0; +} + +static int hdd_set_app_type2_parser(hdd_adapter_t *adapter, + char *arg, int len) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); + char mac_addr[20], rc4_key[20]; + unsigned int gateway_mac[6], i; + tSirAppType2Params params; + int ret; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(CDF_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 %u %u %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, + (unsigned int *)¶ms.tcp_src_port, + (unsigned int *)¶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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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])) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + cdf_mem_copy(params.rc4_key, rc4_key, params.rc4_key_len); + + params.vdev_id = adapter->sessionId; + params.tcp_src_port = (params.tcp_src_port != 0) ? + params.tcp_src_port : hdd_ctx->config->extWowApp2TcpSrcPort; + params.tcp_dst_port = (params.tcp_dst_port != 0) ? + params.tcp_dst_port : hdd_ctx->config->extWowApp2TcpDstPort; + params.keepalive_init = (params.keepalive_init != 0) ? + params.keepalive_init : hdd_ctx->config-> + extWowApp2KAInitPingInterval; + params.keepalive_min = + (params.keepalive_min != 0) ? + params.keepalive_min : + hdd_ctx->config->extWowApp2KAMinPingInterval; + params.keepalive_max = + (params.keepalive_max != 0) ? + params.keepalive_max : + hdd_ctx->config->extWowApp2KAMaxPingInterval; + params.keepalive_inc = + (params.keepalive_inc != 0) ? + params.keepalive_inc : + hdd_ctx->config->extWowApp2KAIncPingInterval; + params.tcp_tx_timeout_val = + (params.tcp_tx_timeout_val != 0) ? + params.tcp_tx_timeout_val : + hdd_ctx->config->extWowApp2TcpTxTimeout; + params.tcp_rx_timeout_val = + (params.tcp_rx_timeout_val != 0) ? + params.tcp_rx_timeout_val : + hdd_ctx->config->extWowApp2TcpRxTimeout; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 /* WLAN_FEATURE_EXTWOW_SUPPORT */ + +/** + * hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command + * @pValue: Pointer to MAXTXPOWER command + * @pDbm: Pointer to tx power + * + * 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 + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_setmaxtxpower_command(uint8_t *pValue, int *pTxPower) +{ + uint8_t *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; + } + + /* remove 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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "SETMAXTXPOWER: %d", *pTxPower); + + return 0; +} /* End of hdd_parse_setmaxtxpower_command */ + +static int hdd_get_dwell_time(struct hdd_config *pCfg, uint8_t *command, + char *extra, uint8_t n, uint8_t *len) +{ + int ret = 0; + + if (!pCfg || !command || !extra || !len) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 *adapter, uint8_t *command) +{ + tHalHandle hHal; + struct hdd_config *pCfg; + uint8_t *value = command; + tSmeConfigParams smeConfig; + int val = 0, temp = 0; + + pCfg = (WLAN_HDD_GET_CTX(adapter))->config; + hHal = WLAN_HDD_GET_HAL_CTX(adapter); + if (!pCfg || !hHal) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME is incorrect")); + return -EINVAL; + } + + cdf_mem_zero(&smeConfig, sizeof(smeConfig)); + sme_get_config_param(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) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME ACTIVE MAX is incorrect")); + return -EFAULT; + } + pCfg->nActiveMaxChnTime = val; + smeConfig.csrConfig.nActiveMaxChnTime = val; + sme_update_config(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) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME ACTIVE MIN is incorrect")); + return -EFAULT; + } + pCfg->nActiveMinChnTime = val; + smeConfig.csrConfig.nActiveMinChnTime = val; + sme_update_config(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) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME PASSIVE MAX is incorrect")); + return -EFAULT; + } + pCfg->nPassiveMaxChnTime = val; + smeConfig.csrConfig.nPassiveMaxChnTime = val; + sme_update_config(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) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME PASSIVE MIN is incorrect")); + return -EFAULT; + } + pCfg->nPassiveMinChnTime = val; + smeConfig.csrConfig.nPassiveMinChnTime = val; + sme_update_config(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) { + hddLog(LOGE, + FL("argument passed for SETDWELLTIME is incorrect")); + return -EFAULT; + } + pCfg->nActiveMaxChnTime = val; + smeConfig.csrConfig.nActiveMaxChnTime = val; + sme_update_config(hHal, &smeConfig); + } else { + return -EINVAL; + } + + return 0; +} + +static void hdd_get_link_status_cb(uint8_t status, void *context) +{ + struct statsContext *pLinkContext; + hdd_adapter_t *adapter; + + if (NULL == context) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Bad context [%p]", + __func__, context); + return; + } + + pLinkContext = context; + adapter = pLinkContext->pAdapter; + + spin_lock(&hdd_context_lock); + + if ((NULL == adapter) || + (LINK_STATUS_MAGIC != pLinkContext->magic)) { + /* + * the caller presumably timed out so there is + * nothing we can do + */ + spin_unlock(&hdd_context_lock); + hddLog(CDF_TRACE_LEVEL_WARN, + "%s: Invalid context, adapter [%p] magic [%08x]", + __func__, adapter, pLinkContext->magic); + return; + } + + /* context is valid so caller is still waiting */ + + /* paranoia: invalidate the magic */ + pLinkContext->magic = 0; + + /* copy over the status */ + adapter->linkStatus = status; + + /* notify the caller */ + complete(&pLinkContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * 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 *adapter) +{ + + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_station_ctx_t *pHddStaCtx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct statsContext context; + CDF_STATUS hstatus; + unsigned long rc; + + if (hdd_ctx->isLogpInProgress) { + hddLog(LOGW, FL("LOGP in Progress. Ignore!!!")); + return 0; + } + + if ((WLAN_HDD_INFRA_STATION != adapter->device_mode) && + (WLAN_HDD_P2P_CLIENT != adapter->device_mode)) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return 0; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + 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 = adapter; + context.magic = LINK_STATUS_MAGIC; + hstatus = sme_get_link_status(WLAN_HDD_GET_HAL_CTX(adapter), + hdd_get_link_status_cb, + &context, adapter->sessionId); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_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(CDF_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 adapter stats or it has cached data */ + return adapter->linkStatus; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * hdd_parse_ese_beacon_req() - Parse ese beacon request + * @pValue: Pointer to data + * @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 int hdd_parse_ese_beacon_req(uint8_t *pValue, + tCsrEseBeaconReq *pEseBcnReq) +{ + uint8_t *inPtr = pValue; + int tempInt = 0; + int j = 0, i = 0, v = 0; + char buf[32]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) { + return -EINVAL; + } + /* no space after the command */ + else if (SPACE_ASCII_VALUE != *inPtr) { + return -EINVAL; + } + + /* remove empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) + inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) + return -EINVAL; + + /* get the first argument ie measurement token */ + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) + return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if (v < 0) + return -EINVAL; + + pEseBcnReq->numBcnReqIe = tempInt; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe); + + for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++) { + for (i = 0; i < 4; i++) { + /* + * inPtr pointing to the beginning of 1st space + * after number of ie fields + */ + inPtr = strpbrk(inPtr, " "); + /* no ie data after the number of ie fields argument */ + if (NULL == inPtr) + return -EINVAL; + + /* remove empty space */ + while ((SPACE_ASCII_VALUE == *inPtr) + && ('\0' != *inPtr)) + inPtr++; + + /* + * no ie data after the number of ie fields + * argument and spaces + */ + if ('\0' == *inPtr) + return -EINVAL; + + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) + return -EINVAL; + + v = kstrtos32(buf, 10, &tempInt); + if (v < 0) + return -EINVAL; + + switch (i) { + case 0: /* Measurement token */ + if (tempInt <= 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Invalid Measurement Token(%d)", + tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].measurementToken = + tempInt; + break; + + case 1: /* Channel number */ + if ((tempInt <= 0) || + (tempInt > + WNI_CFG_CURRENT_CHANNEL_STAMAX)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Invalid Scan Mode(%d) Expected{0|1|2}", + tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].scanMode = tempInt; + break; + + case 3: /* Measurement duration */ + if (((tempInt <= 0) + && (pEseBcnReq->bcnReq[j].scanMode != + eSIR_BEACON_TABLE)) || + ((tempInt < 0) && + (pEseBcnReq->bcnReq[j].scanMode == + eSIR_BEACON_TABLE))) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Invalid Measurement Duration(%d)", + tempInt); + return -EINVAL; + } + pEseBcnReq->bcnReq[j].measurementDuration = + tempInt; + break; + } + } + } + + for (j = 0; j < pEseBcnReq->numBcnReqIe; j++) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 0; +} +#endif /* defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) */ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * 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 + * SETCCKMIE + * + * Return: 0 for success non-zero for failure + */ +static int hdd_parse_get_cckm_ie(uint8_t *pValue, uint8_t **pCckmIe, + uint8_t *pCckmIeLen) +{ + uint8_t *inPtr = pValue; + uint8_t *dataEnd; + int j = 0; + int i = 0; + uint8_t tempByte = 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; + } + /* remove 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 = cdf_mem_malloc((*pCckmIeLen + 1) / 2); + if (NULL == *pCckmIe) { + hddLog(LOGE, FL("cdf_mem_alloc failed")); + return -ENOMEM; + } + cdf_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 = (hex_to_bin(inPtr[j]) << 4) | + (hex_to_bin(inPtr[j + 1])); + (*pCckmIe)[i++] = tempByte; + } + *pCckmIeLen = i; + return 0; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +int wlan_hdd_set_mc_rate(hdd_adapter_t *pAdapter, int targetRate) +{ + tSirRateUpdateInd rateUpdate = {0}; + CDF_STATUS status; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + struct hdd_config *pConfig = NULL; + + if (pHddCtx == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is null", __func__); + 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 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->config; + 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_send_rate_update_ind(pHddCtx->hHal, &rateUpdate); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: SETMCRATE failed", + __func__); + return -EFAULT; + } + return 0; +} + +static int drv_cmd_p2p_dev_addr(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL, + adapter->sessionId, + (unsigned)(*(hdd_ctx->p2pDeviceAddress.bytes + 2) + << 24 | *(hdd_ctx->p2pDeviceAddress.bytes + + 3) << 16 | *(hdd_ctx-> + p2pDeviceAddress.bytes + 4) << 8 | + *(hdd_ctx->p2pDeviceAddress.bytes + + 5)))); + + if (copy_to_user(priv_data->buf, hdd_ctx->p2pDeviceAddress.bytes, + sizeof(tSirMacAddr))) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +/** + * drv_cmd_p2p_set_noa() - Handler for P2P_SET_NOA driver command + * @adapter: Adapter on which the command was received + * @hdd_ctx: HDD global context + * @command: Entire driver command received from userspace + * @command_len: Length of @command + * @priv_data: Pointer to ioctl private data structure + * + * This is a trivial command hander function which simply forwards the + * command to the actual command processor within the P2P module. + * + * Return: 0 on success, non-zero on failure + */ +static int drv_cmd_p2p_set_noa(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_set_p2p_noa(adapter->dev, command); +} + +/** + * drv_cmd_p2p_set_ps() - Handler for P2P_SET_PS driver command + * @adapter: Adapter on which the command was received + * @hdd_ctx: HDD global context + * @command: Entire driver command received from userspace + * @command_len: Length of @command + * @priv_data: Pointer to ioctl private data structure + * + * This is a trivial command hander function which simply forwards the + * command to the actual command processor within the P2P module. + * + * Return: 0 on success, non-zero on failure + */ +static int drv_cmd_p2p_set_ps(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_set_p2p_opps(adapter->dev, command); +} + +static int drv_cmd_set_band(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + + uint8_t *ptr = command; + + /* Change band request received */ + + /* + * First 8 bytes will have "SETBAND " and + * 9 byte will have band setting value + */ + hddLog(CDF_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_set_band_helper(adapter->dev, ptr); + + return ret; +} + +static int drv_cmd_set_wmmps(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_wmmps_helper(adapter, command); +} + +static int drv_cmd_country(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + CDF_STATUS status; + unsigned long rc; + char *country_code; + + country_code = command + 8; + + INIT_COMPLETION(adapter->change_country_code); + + status = sme_change_country_code(hdd_ctx->hHal, + wlan_hdd_change_country_code_callback, + country_code, + adapter, + hdd_ctx->pcds_context, + eSIR_TRUE, + eSIR_TRUE); + if (status == CDF_STATUS_SUCCESS) { + rc = wait_for_completion_timeout( + &adapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: SME while setting country code timed out", + __func__); + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: SME Change Country code fail, status=%d", + __func__, status); + ret = -EINVAL; + } + + return ret; +} + +static int drv_cmd_set_roam_trigger(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + int8_t rssi = 0; + uint8_t lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* Move pointer to ahead of SETROAMTRIGGER */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL, + adapter->sessionId, lookUpThreshold)); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam trigger (Neighbor lookup threshold) = %d", + __func__, + lookUpThreshold); + + hdd_ctx->config->nNeighborLookupRssiThreshold = lookUpThreshold; + status = sme_set_neighbor_lookup_rssi_threshold(hdd_ctx->hHal, + adapter->sessionId, + lookUpThreshold); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to set roam trigger, try again", + __func__); + ret = -EPERM; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_roam_trigger(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t lookUpThreshold = + sme_get_neighbor_lookup_rssi_threshold(hdd_ctx->hHal); + int rssi = (-1) * lookUpThreshold; + char extra[32]; + uint8_t len = 0; + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL, + adapter->sessionId, lookUpThreshold)); + + len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_scan_period(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t roamScanPeriod = 0; + uint16_t neighborEmptyScanRefreshPeriod = + CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT; + + /* input refresh period is in terms of seconds */ + + /* Move pointer to ahead of SETROAMSCANPERIOD */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL, + adapter->sessionId, roamScanPeriod)); + neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan period (Empty Scan refresh period) = %d", + __func__, + roamScanPeriod); + + hdd_ctx->config->nEmptyScanRefreshPeriod = + neighborEmptyScanRefreshPeriod; + sme_update_empty_scan_refresh_period(hdd_ctx->hHal, + adapter->sessionId, + neighborEmptyScanRefreshPeriod); + +exit: + return ret; +} + +static int drv_cmd_get_roam_scan_period(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t nEmptyScanRefreshPeriod = + sme_get_empty_scan_refresh_period(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL, + adapter->sessionId, + nEmptyScanRefreshPeriod)); + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANPERIOD", + (nEmptyScanRefreshPeriod / 1000)); + /* Returned value is in units of seconds */ + len = CDF_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; + } + + return ret; +} + +static int drv_cmd_set_roam_scan_refresh_period(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t roamScanRefreshPeriod = 0; + uint16_t neighborScanRefreshPeriod = + CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT; + + /* input refresh period is in terms of seconds */ + /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan refresh period (Scan refresh period) = %d", + __func__, + roamScanRefreshPeriod); + + hdd_ctx->config->nNeighborResultsRefreshPeriod = + neighborScanRefreshPeriod; + sme_set_neighbor_scan_refresh_period(hdd_ctx->hHal, + adapter->sessionId, + neighborScanRefreshPeriod); + +exit: + return ret; +} + +static int drv_cmd_get_roam_scan_refresh_period(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t value = + sme_get_neighbor_scan_refresh_period(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANREFRESHPERIOD", + (value / 1000)); + /* Returned value is in units of seconds */ + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 + * notify_is_fast_roam_ini_feature_enabled 0/1 is to + * enable/disable. So, we have to invert the value + * to call sme_update_is_fast_roam_ini_feature_enabled. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */ + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */ + + hdd_ctx->config->isFastRoamIniFeatureEnabled = roamMode; + if (roamMode) { + hdd_ctx->config->isRoamOffloadScanEnabled = roamMode; + sme_update_roam_scan_offload_enabled( + (tHalHandle)(hdd_ctx->hHal), + hdd_ctx->config->isRoamOffloadScanEnabled); + sme_update_is_fast_roam_ini_feature_enabled( + hdd_ctx->hHal, + adapter->sessionId, + roamMode); + } else { + sme_update_is_fast_roam_ini_feature_enabled( + hdd_ctx->hHal, + adapter->sessionId, + roamMode); + hdd_ctx->config->isRoamOffloadScanEnabled = roamMode; + sme_update_roam_scan_offload_enabled( + (tHalHandle)(hdd_ctx->hHal), + hdd_ctx->config->isRoamOffloadScanEnabled); + } + + +exit: + return ret; +} + +static int drv_cmd_get_roam_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool roamMode = sme_get_is_lfr_feature_enabled(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + /* + * roamMode value shall be inverted because the sementics 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 = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_delta(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT; + + /* Move pointer to ahead of SETROAMDELTA */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam rssi diff = %d", + __func__, roamRssiDiff); + + hdd_ctx->config->RoamRssiDiff = roamRssiDiff; + sme_update_roam_rssi_diff(hdd_ctx->hHal, + adapter->sessionId, + roamRssiDiff); + +exit: + return ret; +} + +static int drv_cmd_get_roam_delta(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t roamRssiDiff = + sme_get_roam_rssi_diff(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMDELTA_IOCTL, + adapter->sessionId, roamRssiDiff)); + + len = scnprintf(extra, sizeof(extra), "%s %d", + command, roamRssiDiff); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_get_band(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + int band = -1; + char extra[32]; + uint8_t len = 0; + + hdd_get_band_helper(hdd_ctx, &band); + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETBAND_IOCTL, + adapter->sessionId, band)); + + len = scnprintf(extra, sizeof(extra), "%s %d", command, band); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_scan_channels(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_parse_set_roam_scan_channels(adapter, command); +} + +static int drv_cmd_get_roam_scan_channels(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t numChannels = 0; + uint8_t j = 0; + char extra[128] = { 0 }; + int len; + + if (CDF_STATUS_SUCCESS != + sme_get_roam_scan_channel_list(hdd_ctx->hHal, + ChannelList, + &numChannels, + adapter->sessionId)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_FATAL, + "%s: failed to get roam scan channel list", + __func__); + ret = -EFAULT; + goto exit; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL, + adapter->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 = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_ccx_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool eseMode = sme_get_is_ese_feature_enabled(hdd_ctx->hHal); + char extra[32]; + uint8_t 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(hdd_ctx) && + sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_okc_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool okcMode = hdd_is_okc_mode_enabled(hdd_ctx); + char extra[32]; + uint8_t len = 0; + + /* + * Check if the features OKC/ESE/11R are supported simultaneously, + * then this operation is not permitted (return FAILURE) + */ + if (okcMode && + sme_get_is_ese_feature_enabled(hdd_ctx->hHal) && + sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_fast_roam(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool lfrMode = sme_get_is_lfr_feature_enabled(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETFASTROAM", lfrMode); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_get_fast_transition(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool ft = sme_get_is_ft_feature_enabled(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETFASTTRANSITION", ft); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_scan_channel_min_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT; + + /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL, + adapter->sessionId, minTime)); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change channel min time = %d", + __func__, minTime); + + hdd_ctx->config->nNeighborScanMinChanTime = minTime; + sme_set_neighbor_scan_min_chan_time(hdd_ctx->hHal, + minTime, + adapter->sessionId); + +exit: + return ret; +} + +static int drv_cmd_send_action_frame(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_parse_sendactionframe(adapter, command); +} + +static int drv_cmd_get_roam_scan_channel_min_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t val = sme_get_neighbor_scan_min_chan_time(hdd_ctx->hHal, + adapter->sessionId); + char extra[32]; + uint8_t len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMSCANCHANNELMINTIME", val); + len = CDF_MIN(priv_data->total_len, len + 1); + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL, + adapter->sessionId, val)); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_scan_channel_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint16_t maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT; + + /* Move pointer to ahead of SETSCANCHANNELTIME */ + value = value + command_len + 1; + + /* 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 kstrtou8 fails + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change channel max time = %d", + __func__, maxTime); + + hdd_ctx->config->nNeighborScanMaxChanTime = maxTime; + sme_set_neighbor_scan_max_chan_time(hdd_ctx->hHal, + adapter->sessionId, + maxTime); + +exit: + return ret; +} + +static int drv_cmd_get_scan_channel_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t val = sme_get_neighbor_scan_max_chan_time(hdd_ctx->hHal, + adapter->sessionId); + char extra[32]; + uint8_t len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETSCANCHANNELTIME", val); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_scan_home_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint16_t val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT; + + /* Move pointer to ahead of SETSCANHOMETIME */ + value = value + command_len + 1; + + /* 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 kstrtou8 fails + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change scan home time = %d", + __func__, val); + + hdd_ctx->config->nNeighborScanPeriod = val; + sme_set_neighbor_scan_period(hdd_ctx->hHal, + adapter->sessionId, val); + +exit: + return ret; +} + +static int drv_cmd_get_scan_home_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t val = sme_get_neighbor_scan_period(hdd_ctx->hHal, + adapter-> + sessionId); + char extra[32]; + uint8_t len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETSCANHOMETIME", val); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_intra_band(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t val = CFG_ROAM_INTRA_BAND_DEFAULT; + + /* Move pointer to ahead of SETROAMINTRABAND */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change intra band = %d", + __func__, val); + + hdd_ctx->config->nRoamIntraBand = val; + sme_set_roam_intra_band(hdd_ctx->hHal, val); + +exit: + return ret; +} + +static int drv_cmd_get_roam_intra_band(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t val = sme_get_roam_intra_band(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + /* value is interms of msec */ + len = scnprintf(extra, sizeof(extra), "%s %d", + "GETROAMINTRABAND", val); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_scan_n_probes(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT; + + /* Move pointer to ahead of SETSCANNPROBES */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set nProbes = %d", + __func__, nProbes); + + hdd_ctx->config->nProbes = nProbes; + sme_update_roam_scan_n_probes(hdd_ctx->hHal, + adapter->sessionId, nProbes); + +exit: + return ret; +} + +static int drv_cmd_get_scan_n_probes(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t val = sme_get_roam_scan_n_probes(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_scan_home_away_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint16_t homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; + + /* input value is in units of msec */ + + /* Move pointer to ahead of SETSCANHOMEAWAYTIME */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set scan away time = %d", + __func__, homeAwayTime); + + if (hdd_ctx->config->nRoamScanHomeAwayTime != + homeAwayTime) { + hdd_ctx->config->nRoamScanHomeAwayTime = homeAwayTime; + sme_update_roam_scan_home_away_time(hdd_ctx->hHal, + adapter->sessionId, + homeAwayTime, + true); + } + +exit: + return ret; +} + +static int drv_cmd_get_scan_home_away_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint16_t val = sme_get_roam_scan_home_away_time(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = CDF_MIN(priv_data->total_len, len + 1); + + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_reassoc(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_parse_reassoc(adapter, command); +} + +static int drv_cmd_set_wes_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT; + + /* Move pointer to ahead of SETWESMODE */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set WES Mode rssi diff = %d", + __func__, wesMode); + + hdd_ctx->config->isWESModeEnabled = wesMode; + sme_update_wes_mode(hdd_ctx->hHal, wesMode, adapter->sessionId); + +exit: + return ret; +} + +static int drv_cmd_get_wes_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool wesMode = sme_get_wes_mode(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_opportunistic_rssi_diff(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t nOpportunisticThresholdDiff = + CFG_OPPORTUNISTIC_SCAN_THRESHOLD_DIFF_DEFAULT; + + /* Move pointer to ahead of SETOPPORTUNISTICRSSIDIFF */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed.", __func__); + ret = -EINVAL; + goto exit; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set Opportunistic Threshold diff = %d", + __func__, nOpportunisticThresholdDiff); + + sme_set_roam_opportunistic_scan_threshold_diff(hdd_ctx->hHal, + adapter->sessionId, + nOpportunisticThresholdDiff); + +exit: + return ret; +} + +static int drv_cmd_get_opportunistic_rssi_diff(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + int8_t val = sme_get_roam_opportunistic_scan_threshold_diff( + hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_roam_rescan_rssi_diff(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t nRoamRescanRssiDiff = CFG_ROAM_RESCAN_RSSI_DIFF_DEFAULT; + + /* Move pointer to ahead of SETROAMRESCANRSSIDIFF */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed.", __func__); + ret = -EINVAL; + goto exit; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam Rescan RSSI Diff = %d", + __func__, nRoamRescanRssiDiff); + + sme_set_roam_rescan_rssi_diff(hdd_ctx->hHal, + adapter->sessionId, + nRoamRescanRssiDiff); + +exit: + return ret; +} + +static int drv_cmd_get_roam_rescan_rssi_diff(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t val = sme_get_roam_rescan_rssi_diff(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, val); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_set_fast_roam(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + + /* Move pointer to ahead of SETFASTROAM */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change lfr mode = %d", + __func__, lfrMode); + + hdd_ctx->config->isFastRoamIniFeatureEnabled = lfrMode; + sme_update_is_fast_roam_ini_feature_enabled(hdd_ctx->hHal, + adapter-> + sessionId, + lfrMode); + +exit: + return ret; +} + +static int drv_cmd_set_fast_transition(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT; + + /* Move pointer to ahead of SETFASTROAM */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change ft mode = %d", + __func__, ft); + + hdd_ctx->config->isFastTransitionEnabled = ft; + sme_update_fast_transition_enabled(hdd_ctx->hHal, ft); + +exit: + return ret; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void hdd_wma_send_fastreassoc_cmd(int sessionId, tSirMacAddr bssid, + int channel) +{ + struct wma_roam_invoke_cmd *fastreassoc; + cds_msg_t msg = {0}; + + fastreassoc = cdf_mem_malloc(sizeof(*fastreassoc)); + if (NULL == fastreassoc) { + hddLog(LOGE, FL("cdf_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 (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, + &msg)) { + cdf_mem_free(fastreassoc); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post ROAM_INVOKE_CMD message to WMA")); + } +} +#endif +static int drv_cmd_fast_reassoc(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t channel = 0; + tSirMacAddr targetApBssid; + uint32_t roamId = 0; + tCsrRoamModifyProfileFields modProfileFields; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tCsrHandoffRequest handoffInfo; +#endif + hdd_station_ctx_t *pHddStaCtx; + + if (WLAN_HDD_INFRA_STATION != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s:Not associated!", __func__); + ret = -EINVAL; + goto exit; + } + + ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, + &channel); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 (true == cdf_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE)) { + /* Reassoc to same AP, only supported for Open Security*/ + if ((pHddStaCtx->conn_info.ucEncryptionType || + pHddStaCtx->conn_info.mcEncryptionType)) { + hddLog(LOGE, + FL("Reassoc to same AP, only supported for Open Security")); + return -ENOTSUPP; + } + hddLog(LOG1, + FL("Reassoc BSSID is same as currently associated AP bssid")); + sme_get_modify_profile_fields(hdd_ctx->hHal, adapter->sessionId, + &modProfileFields); + sme_roam_reassoc(hdd_ctx->hHal, adapter->sessionId, + NULL, modProfileFields, &roamId, 1); + return 0; + } + + /* Check channel number is a valid channel number */ + if (CDF_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(adapter, channel)) { + hddLog(LOGE, FL("Invalid Channel [%d]"), channel); + return -EINVAL; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (hdd_ctx->config->isRoamOffloadEnabled) { + hdd_wma_send_fastreassoc_cmd((int)adapter->sessionId, + targetApBssid, (int)channel); + goto exit; + } +#endif + /* Proceed with reassoc */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + handoffInfo.channel = channel; + handoffInfo.src = FASTREASSOC; + cdf_mem_copy(handoffInfo.bssid, targetApBssid, + sizeof(tSirMacAddr)); + sme_handoff_request(hdd_ctx->hHal, adapter->sessionId, + &handoffInfo); +#endif + +exit: + return ret; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static int drv_cmd_ccx_plm_req(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpSirPlmReq pPlmRequest = NULL; + + pPlmRequest = cdf_mem_malloc(sizeof(tSirPlmReq)); + if (NULL == pPlmRequest) { + ret = -ENOMEM; + goto exit; + } + + status = hdd_parse_plm_cmd(value, pPlmRequest); + if (CDF_STATUS_SUCCESS != status) { + cdf_mem_free(pPlmRequest); + pPlmRequest = NULL; + ret = -EINVAL; + goto exit; + } + pPlmRequest->sessionId = adapter->sessionId; + + status = sme_set_plm_request(hdd_ctx->hHal, pPlmRequest); + if (CDF_STATUS_SUCCESS != status) { + cdf_mem_free(pPlmRequest); + pPlmRequest = NULL; + ret = -EINVAL; + goto exit; + } + +exit: + return ret; +} +#endif + +#ifdef FEATURE_WLAN_ESE +static int drv_cmd_set_ccx_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t 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_get_is_ese_feature_enabled(hdd_ctx->hHal) && + hdd_is_okc_mode_enabled(hdd_ctx) && + sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change ese mode = %d", + __func__, eseMode); + + hdd_ctx->config->isEseIniFeatureEnabled = eseMode; + sme_update_is_ese_feature_enabled(hdd_ctx->hHal, + adapter->sessionId, + eseMode); + +exit: + return ret; +} +#endif + +static int drv_cmd_set_roam_scan_control(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t roamScanControl = 0; + + /* Move pointer to ahead of SETROAMSCANCONTROL */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed ", __func__); + ret = -EINVAL; + goto exit; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_set_roam_scan_control(hdd_ctx->hHal, + adapter->sessionId, + roamScanControl); + +exit: + return ret; +} + +static int drv_cmd_set_okc_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t 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_get_is_ese_feature_enabled(hdd_ctx->hHal) && + hdd_is_okc_mode_enabled(hdd_ctx) && + sme_get_is_ft_feature_enabled(hdd_ctx->hHal)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to change okc mode = %d", + __func__, okcMode); + + hdd_ctx->config->isOkcIniFeatureEnabled = okcMode; + +exit: + return ret; +} + +static int drv_cmd_get_roam_scan_control(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + bool roamScanControl = sme_get_roam_scan_control(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", + command, roamScanControl); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_bt_coex_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + char *bcMode; + + bcMode = command + 11; + if ('1' == *bcMode) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + hdd_ctx->btCoexModeSet = true; + ret = wlan_hdd_scan_abort(adapter); + if (ret < 0) { + hddLog(LOGE, + FL("Failed to abort existing scan status:%d"), ret); + } + } else if ('2' == *bcMode) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_DEBUG, + FL("BTCOEXMODE %d"), *bcMode); + hdd_ctx->btCoexModeSet = false; + } + + return ret; +} + +static int drv_cmd_scan_active(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + return 0; +} + +static int drv_cmd_scan_passive(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + hdd_ctx->ioctl_scan_mode = eSIR_PASSIVE_SCAN; + return 0; +} + +static int drv_cmd_get_dwell_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + struct hdd_config *pCfg = + (WLAN_HDD_GET_CTX(adapter))->config; + char extra[32]; + uint8_t len = 0; + + memset(extra, 0, sizeof(extra)); + ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len); + len = CDF_MIN(priv_data->total_len, len + 1); + if (ret != 0 || copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + goto exit; + } + ret = len; +exit: + return ret; +} + +static int drv_cmd_set_dwell_time(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_set_dwell_time(adapter, command); +} + +static int drv_cmd_miracast(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + CDF_STATUS ret_status; + int ret = 0; + tHalHandle hHal; + uint8_t filterType = 0; + hdd_context_t *pHddCtx = NULL; + uint8_t *value; + + pHddCtx = WLAN_HDD_GET_CTX(adapter); + if (0 != wlan_hdd_validate_context(pHddCtx)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s pHddCtx is not valid, Unable to set miracast mode", + __func__); + 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", + __func__); + ret = -EINVAL; + goto exit; + } + if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL) + || (filterType > + WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source, 2-Sink ", + __func__); + ret = -EINVAL; + goto exit; + } + /* Filtertype value should be either 0-Disabled, 1-Source, 2-sink */ + pHddCtx->miracast_value = filterType; + + ret_status = sme_set_miracast(hHal, filterType); + if (CDF_STATUS_SUCCESS != ret_status) { + hddLog(LOGE, "Failed to set miracast"); + return -EBUSY; + } + + if (cds_is_mcc_in_24G(pHddCtx)) + return cds_set_mas(adapter, filterType); + +exit: + return ret; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +static int drv_cmd_set_ccx_roam_scan_channels(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t numChannels = 0; + CDF_STATUS status; + + ret = hdd_parse_channellist(value, ChannelList, &numChannels); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse channel list information", + __func__); + goto exit; + } + if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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_set_ese_roam_scan_channel_list(hdd_ctx->hHal, + adapter->sessionId, + ChannelList, + numChannels); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to update channel list information", + __func__); + ret = -EINVAL; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_get_tsm_stats(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + char extra[128] = { 0 }; + int len = 0; + uint8_t tid = 0; + hdd_station_ctx_t *pHddStaCtx; + tAniTrafStrmMetrics tsm_metrics; + + if ((WLAN_HDD_INFRA_STATION != adapter->device_mode) && + (WLAN_HDD_P2P_CLIENT != adapter->device_mode)) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + /* if not associated, return error */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s:Not associated!", __func__); + ret = -EINVAL; + goto exit; + } + + /* Move pointer to ahead of GETTSMSTATS */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: Received Command to get tsm stats tid = %d", + __func__, tid); + if (CDF_STATUS_SUCCESS != + hdd_get_tsm_stats(adapter, tid, &tsm_metrics)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to get tsm stats", + __func__); + ret = -EFAULT; + goto exit; + } + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)", + tsm_metrics.UplinkPktQueueDly, + tsm_metrics.UplinkPktQueueDlyHist[0], + tsm_metrics.UplinkPktQueueDlyHist[1], + tsm_metrics.UplinkPktQueueDlyHist[2], + tsm_metrics.UplinkPktQueueDlyHist[3], + tsm_metrics.UplinkPktTxDly, + tsm_metrics.UplinkPktLoss, + tsm_metrics.UplinkPktCount, + tsm_metrics.RoamingCount, + tsm_metrics.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, + tsm_metrics.UplinkPktQueueDly, + tsm_metrics.UplinkPktQueueDlyHist[0], + tsm_metrics.UplinkPktQueueDlyHist[1], + tsm_metrics.UplinkPktQueueDlyHist[2], + tsm_metrics.UplinkPktQueueDlyHist[3], + tsm_metrics.UplinkPktTxDly, + tsm_metrics.UplinkPktLoss, + tsm_metrics.UplinkPktCount, + tsm_metrics.RoamingCount, + tsm_metrics.RoamingDly); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + goto exit; + } + +exit: + return ret; +} + +static int drv_cmd_set_cckm_ie(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + uint8_t *cckmIe = NULL; + uint8_t cckmIeLen = 0; + + ret = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse cckm ie data", + __func__); + goto exit; + } + + if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: CCKM Ie input length is more than max[%d]", + __func__, DOT11F_IE_RSN_MAX_LEN); + if (NULL != cckmIe) { + cdf_mem_free(cckmIe); + cckmIe = NULL; + } + ret = -EINVAL; + goto exit; + } + + sme_set_cckm_ie(hdd_ctx->hHal, adapter->sessionId, + cckmIe, cckmIeLen); + if (NULL != cckmIe) { + cdf_mem_free(cckmIe); + cckmIe = NULL; + } + +exit: + return ret; +} + +static int drv_cmd_ccx_beacon_req(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + tCsrEseBeaconReq eseBcnReq; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (WLAN_HDD_INFRA_STATION != adapter->device_mode) { + hdd_warn("Unsupported in mode %s(%d)", + hdd_device_mode_to_string(adapter->device_mode), + adapter->device_mode); + return -EINVAL; + } + + ret = hdd_parse_ese_beacon_req(value, &eseBcnReq); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to parse ese beacon req", + __func__); + goto exit; + } + + if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("Not associated")); + hdd_indicate_ese_bcn_report_no_results(adapter, + eseBcnReq.bcnReq[0].measurementToken, + 0x02, /* BIT(1) set for measurement done */ + 0); /* no BSS */ + goto exit; + } + + status = sme_set_ese_beacon_request(hdd_ctx->hHal, + adapter->sessionId, + &eseBcnReq); + + if (CDF_STATUS_E_RESOURCES == status) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("sme_set_ese_beacon_request failed (%d), a request already in progress"), + status); + ret = -EBUSY; + goto exit; + } else if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: sme_set_ese_beacon_request failed (%d)", + __func__, status); + ret = -EINVAL; + goto exit; + } + +exit: + return ret; +} +#endif /* #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) */ + +static int drv_cmd_set_mc_rate(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + int targetRate; + + /* input value is in units of hundred kbps */ + + /* Move pointer to ahead of SETMCRATE */ + value = value + command_len + 1; + + /* Convert the value from ascii to integer, decimal base */ + ret = kstrtouint(value, 10, &targetRate); + + ret = wlan_hdd_set_mc_rate(adapter, targetRate); + return ret; +} + +static int drv_cmd_max_tx_power(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + int status; + int txPower; + CDF_STATUS cdf_status; + CDF_STATUS smeStatus; + uint8_t *value = command; + tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + tSirMacAddr selfMac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + + status = hdd_parse_setmaxtxpower_command(value, &txPower); + if (status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Invalid MAXTXPOWER command "); + ret = -EINVAL; + goto exit; + } + + cdf_status = hdd_get_front_adapter(hdd_ctx, &pAdapterNode); + while (NULL != pAdapterNode + && CDF_STATUS_SUCCESS == cdf_status) { + adapter = pAdapterNode->pAdapter; + /* Assign correct self MAC address */ + cdf_mem_copy(bssid, + adapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(selfMac, + adapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); + + hddLog(CDF_TRACE_LEVEL_INFO, + "Device mode %d max tx power %d selfMac: " MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ", + adapter->device_mode, txPower, + MAC_ADDR_ARRAY(selfMac), + MAC_ADDR_ARRAY(bssid)); + + smeStatus = sme_set_max_tx_power((tHalHandle)(hdd_ctx->hHal), + bssid, selfMac, txPower); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s:Set max tx power failed", + __func__); + ret = -EINVAL; + goto exit; + } + hddLog(CDF_TRACE_LEVEL_INFO, + "%s: Set max tx power success", + __func__); + cdf_status = hdd_get_next_adapter(hdd_ctx, pAdapterNode, + &pNext); + pAdapterNode = pNext; + } + +exit: + return ret; +} + +static int drv_cmd_set_dfs_scan_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t *value = command; + uint8_t dfsScanMode = CFG_ROAMING_DFS_CHANNEL_DEFAULT; + + /* Move pointer to ahead of SETDFSSCANMODE */ + value = value + command_len + 1; + + /* 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Command to Set DFS Scan Mode = %d", + __func__, dfsScanMode); + + hdd_ctx->config->allowDFSChannelRoam = dfsScanMode; + sme_update_dfs_scan_mode(hdd_ctx->hHal, adapter->sessionId, + dfsScanMode); + +exit: + return ret; +} + +static int drv_cmd_get_dfs_scan_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + uint8_t dfsScanMode = sme_get_dfs_scan_mode(hdd_ctx->hHal); + char extra[32]; + uint8_t len = 0; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +static int drv_cmd_get_link_status(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret = 0; + int value = wlan_hdd_get_link_status(adapter); + char extra[32]; + uint8_t len; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, value); + len = CDF_MIN(priv_data->total_len, len + 1); + if (copy_to_user(priv_data->buf, &extra, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", + __func__); + ret = -EFAULT; + } + + return ret; +} + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +static int drv_cmd_enable_ext_wow(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + uint8_t *value = command; + int set_value; + + /* Move pointer to ahead of ENABLEEXTWOW */ + value = value + command_len; + + sscanf(value, "%d", &set_value); + + return hdd_enable_ext_wow_parser(adapter, + adapter->sessionId, + set_value); +} + +static int drv_cmd_set_app1_params(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + + /* Move pointer to ahead of SETAPP1PARAMS */ + value = value + command_len; + + ret = hdd_set_app_type1_parser(adapter, + value, strlen(value)); + if (ret >= 0) + hdd_ctx->is_extwow_app_type1_param_set = true; + + return ret; +} + +static int drv_cmd_set_app2_params(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + + /* Move pointer to ahead of SETAPP2PARAMS */ + value = value + command_len; + + ret = hdd_set_app_type2_parser(adapter, value, strlen(value)); + if (ret >= 0) + hdd_ctx->is_extwow_app_type2_param_set = true; + + return ret; +} +#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */ + +#ifdef FEATURE_WLAN_TDLS +/** + * drv_cmd_tdls_secondary_channel_offset() - secondary tdls off channel offset + * @adapter: Pointer to the HDD adapter + * @hdd_ctx: Pointer to the HDD context + * @command: Driver command string + * @command_len: Driver command string length + * @priv_data: Private data coming with the driver command. Unused here + * + * This function handles driver command that sets the secondary tdls off channel + * offset + * + * Return: 0 on success; negative errno otherwise + */ +static int drv_cmd_tdls_secondary_channel_offset(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + int set_value; + + /* Move pointer to point the string */ + value += command_len; + + ret = sscanf(value, "%d", &set_value); + if (ret != 1) + return -EINVAL; + + hddLog(LOG1, FL("Tdls offchannel offset:%d"), set_value); + + ret = hdd_set_tdls_secoffchanneloffset(hdd_ctx, set_value); + + return ret; +} + +/** + * drv_cmd_tdls_off_channel_mode() - set tdls off channel mode + * @adapter: Pointer to the HDD adapter + * @hdd_ctx: Pointer to the HDD context + * @command: Driver command string + * @command_len: Driver command string length + * @priv_data: Private data coming with the driver command. Unused here + * + * This function handles driver command that sets tdls off channel mode + * + * Return: 0 on success; negative errno otherwise + */ +static int drv_cmd_tdls_off_channel_mode(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + int set_value; + + /* Move pointer to point the string */ + value += command_len; + + ret = sscanf(value, "%d", &set_value); + if (ret != 1) + return -EINVAL; + + hddLog(LOG1, FL("Tdls offchannel mode:%d"), set_value); + + ret = hdd_set_tdls_offchannelmode(adapter, set_value); + + return ret; +} + +/** + * drv_cmd_tdls_off_channel() - set tdls off channel number + * @adapter: Pointer to the HDD adapter + * @hdd_ctx: Pointer to the HDD context + * @command: Driver command string + * @command_len: Driver command string length + * @priv_data: Private data coming with the driver command. Unused here + * + * This function handles driver command that sets tdls off channel number + * + * Return: 0 on success; negative errno otherwise + */ +static int drv_cmd_tdls_off_channel(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + int set_value; + + /* Move pointer to point the string */ + value += command_len; + + ret = sscanf(value, "%d", &set_value); + if (ret != 1) + return -EINVAL; + + hddLog(LOG1, FL("Tdls offchannel num: %d"), set_value); + + ret = hdd_set_tdls_offchannel(hdd_ctx, set_value); + + return ret; +} + +/** + * drv_cmd_tdls_scan() - set tdls scan type + * @adapter: Pointer to the HDD adapter + * @hdd_ctx: Pointer to the HDD context + * @command: Driver command string + * @command_len: Driver command string length + * @priv_data: Private data coming with the driver command. Unused here + * + * This function handles driver command that sets tdls scan type + * + * Return: 0 on success; negative errno otherwise + */ +static int drv_cmd_tdls_scan(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint8_t *value = command; + int set_value; + + /* Move pointer to point the string */ + value += command_len; + + ret = sscanf(value, "%d", &set_value); + if (ret != 1) + return -EINVAL; + + hddLog(LOG1, FL("Tdls scan type val: %d"), set_value); + + ret = hdd_set_tdls_scan_type(hdd_ctx, set_value); + + return ret; +} +#endif + +static int drv_cmd_get_rssi(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + int8_t rssi = 0; + char extra[32]; + uint8_t len = 0; + + wlan_hdd_get_rssi(adapter, &rssi); + + len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi); + len = CDF_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; + } + + return ret; +} + +static int drv_cmd_get_linkspeed(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int ret; + uint32_t link_speed = 0; + char extra[32]; + uint8_t len = 0; + + ret = wlan_hdd_get_link_speed(adapter, &link_speed); + if (0 != ret) + return ret; + + len = scnprintf(extra, sizeof(extra), "%s %d", command, link_speed); + len = CDF_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; + } + + return ret; +} + +#ifdef FEATURE_NAPI +/** + * hdd_parse_napi() - helper functions to drv_cmd_napi + * @str : source string to parse + * @cmd : pointer to cmd part after parsing + * @sub : pointer to subcmd part after parsing + * @aux : pointer to optional aux part after parsing + * + * Example: + * NAPI SCALE +-- IN str + * | | +------ OUT aux + * | +------------ OUT subcmd + * +----------------- OUT cmd + * + * Return: ==0: success; !=0: failure + */ +static int hdd_parse_napi(char **str, char **cmd, char **sub, char **aux) +{ + int rc; + char *token, *lcmd = NULL, *lsub = NULL, *laux = NULL; + + NAPI_DEBUG("-->\n"); + + token = strsep(str, " \t"); + if (NULL == token) { + hdd_err("cannot parse cmd"); + goto parse_end; + } + lcmd = token; + + token = strsep(str, " \t"); + if (NULL == token) { + hdd_err("cannot parse subcmd"); + goto parse_end; + } + lsub = token; + + token = strsep(str, " \t"); + if (NULL == token) + hdd_warn("cannot parse aux\n"); + else + laux = token; + +parse_end: + if ((NULL == lcmd) || (NULL == lsub)) + rc = -EINVAL; + else { + rc = 0; + *cmd = lcmd; + *sub = lsub; + if (NULL != aux) + *aux = laux; + } + NAPI_DEBUG("<--[rc=%d]\n", rc); + return rc; +} + + +/** + * hdd_parse_stats() - print NAPI stats into a buffer + * @buf : buffer to write stats into + * @max : "size of buffer" + * @idp : NULL: all stats, otherwise, ptr to the NAPI instance + * @napid: binary structure to retrieve the stats from + * + * Return: number of bytes written into the buffer + */ +int hdd_napi_stats(char *buf, + int max, + char *indp, + struct qca_napi_data *napid) +{ + int n = 0; + int i, j, k; /* NAPI, CPU, bucket indices */ + int from, to; + struct qca_napi_info *napii; + struct qca_napi_stat *napis; + + NAPI_DEBUG("-->\n"); + + if (NULL == indp) { + from = 0; + to = sizeof(uint32_t) * CE_COUNT_MAX; + } else { + if (0 > kstrtoint(indp, 10, &to)) { + from = 0; + to = sizeof(uint32_t) * CE_COUNT_MAX; + } else + from = to; + } + + for (i = from; i < to; i++) + if (napid->ce_map & (0x01 << i)) { + napii = &(napid->napis[i]); + for (j = 0; j < NR_CPUS; j++) { + napis = &(napii->stats[j]); + n += scnprintf(buf + n, max - n, + "STATS: NAPI[%d] CPU: %d scheds: %d polls: %d completes: %d done: %d ", + i, j, + napis->napi_schedules, + napis->napi_polls, + napis->napi_completes, + napis->napi_workdone); + + for (k = 0; k < QCA_NAPI_NUM_BUCKETS; k++) { + n += scnprintf( + buf + n, max - n, + " %d", + napis->napi_budget_uses[k]); + } + n += scnprintf(buf+n, max - n, "\n"); + } + } + + NAPI_DEBUG("<--[n=%d]\n", n); + return n; +} + +/** + * napi_set_scale() - sets the scale attribute in all NAPI entries + * @sc : scale to set + * + * Return: void + */ +static void napi_set_scale(uint8_t sc) +{ + uint32_t i; + struct qca_napi_data *napi_data; + + napi_data = hdd_napi_get_all(); + for (i = 0; i < sizeof(uint32_t)*8; i++) + if (napi_data->ce_map & (0x01 << i)) + napi_data->napis[i].scale = sc; + + return; +} +/** + * drv_cmd_napi() - processes NAPI commands + * @adapter : net_device + * @hdd_ctx : HDD context + * @command : command string from user command (including "NAPI") + * @command_len: length of command + * @priv_data : ifr_data + * + * Commands supported: + * NAPI ENABLE : enables NAPI administratively. Note that this may not + * enable NAPI functionally, as some other conditions + * may not have been satisfied yet + * NAPI DISABLE : reverse operation of "enable" + * NAPI STATUS : get global status of NAPI instances + * NAPI STATS [] : get the stats for a given NAPI instance + * NAPI SCALE : set the scale factor + * + * Return: 0: success; 0>: failure + */ +static int drv_cmd_napi(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + int rc = 0; + int n, l; + char *cmd = NULL, *subcmd = NULL, *aux = NULL; + char *synopsis = "NAPI ENABLE\n" + "NAPI DISABLE\n" + "NAPI STATUS\n" + "NAPI STATS [] -- if no then all\n" + "NAPI SCALE -- set the scale\n"; + char *reply = NULL; + + /* make a local copy, as strsep modifies the str in place */ + char *str = NULL; + + NAPI_DEBUG("-->\n"); + + /** + * NOTE TO MAINTAINER: from this point to the end of the function, + * please do not return anywhere in the code except the very end + * to avoid memory leakage (goto end_drv_napi instead) + * or make sure that reply+str is freed + */ + reply = kmalloc(MAX_USER_COMMAND_SIZE, GFP_KERNEL); + if (NULL == reply) { + hdd_err("could not allocate reply buffer"); + rc = -ENOMEM; + goto end_drv_napi; + } + + str = kmalloc(strlen(command) + 1, GFP_KERNEL); + if (NULL == str) { + hdd_err("could not allocate copy of input buffer"); + rc = -ENOMEM; + goto end_drv_napi; + } + + strlcpy(str, command, strlen(command) + 1); + hdd_debug("parsing command into cmd=0x%p sub=0x%p aux=0x%p\n", + cmd, subcmd, aux); + + + rc = hdd_parse_napi(&str, &cmd, &subcmd, &aux); + + if (0 != rc) { + const char *msg = "unknown or badly formatted cmd\n%s"; + l = CDF_MIN(MAX_USER_COMMAND_SIZE, + strlen(msg)+strlen(synopsis)); + n = scnprintf(reply, l, msg, synopsis); + + if (copy_to_user(priv_data->buf, reply, + CDF_MIN(priv_data->total_len, l))) + hdd_err("failed to copy data to user buffer"); + hdd_debug("reply: %s", reply); + + rc = -EINVAL; + } else { + hdd_debug("cmd=(%s) subcmd=(%s) aux=(%s)\n", + cmd, subcmd, aux); + if (!strcmp(subcmd, "ENABLE")) + hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)1); + else if (!strcmp(subcmd, "DISABLE")) + hdd_napi_event(NAPI_EVT_CMD_STATE, (void *)0); + else if (!strcmp(subcmd, "STATUS")) { + int n = 0; + uint32_t i; + struct qca_napi_data *napi_data; + + napi_data = hdd_napi_get_all(); + n += scnprintf(reply+n, MAX_USER_COMMAND_SIZE - n, + "NAPI state: 0x%08x map: 0x%08x\n", + napi_data->state, + napi_data->ce_map); + + for (i = 0; i < sizeof(uint32_t)*8; i++) + if (napi_data->ce_map & (0x01 << i)) { + n += scnprintf( + reply + n, + MAX_USER_COMMAND_SIZE - n, + "#%d: id: %d, scale=%d\n", + i, + napi_data->napis[i].id, + napi_data->napis[i].scale); + } + hdd_info("wlan: STATUS DATA:\n%s", reply); + if (copy_to_user(priv_data->buf, reply, + CDF_MIN(n, priv_data->total_len))) + rc = -EINVAL; + } else if (!strcmp(subcmd, "STATS")) { + int n = 0; + struct qca_napi_data *napi_data; + + napi_data = hdd_napi_get_all(); + n = hdd_napi_stats(reply, MAX_USER_COMMAND_SIZE, + aux, napi_data); + NAPI_DEBUG("STATS: returns %d\n", n); + + if (n > 0) { + if (copy_to_user(priv_data->buf, reply, + CDF_MIN(priv_data->total_len, + n))) + rc = -EINVAL; + hdd_info("wlan: STATS_DATA\n%s\n", reply); + } else + rc = -EINVAL; + } else if (!strcmp(subcmd, "SCALE")) { + if (NULL == aux) { + rc = -EINVAL; + hdd_err("wlan: SCALE cmd requires "); + } else { + uint8_t sc; + rc = kstrtou8(aux, 10, &sc); + if (rc) { + hdd_err("wlan: bad scale (%s)", aux); + rc = -EINVAL; + } else + napi_set_scale(sc); + } + } /* SCALE */ + } +end_drv_napi: + if (NULL != str) + kfree(str); + if (NULL != reply) + kfree(reply); + + NAPI_DEBUG("<--[rc=%d]\n", rc); + return rc; +} +#endif /* FEATURE_NAPI */ + +/** + * hdd_set_rx_filter() - set RX filter + * @adapter: Pointer to adapter + * @action: Filter action + * @pattern: Address pattern + * + * Address pattern is most significant byte of address for example + * 0x01 for IPV4 multicast address + * 0x33 for IPV6 multicast address + * 0xFF for broadcast address + * + * Return: 0 for success, non-zero for failure + */ +static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, + uint8_t pattern) +{ + int ret; + uint8_t i; + tHalHandle handle; + tSirRcvFltMcAddrList *filter; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + handle = hdd_ctx->hHal; + + if (NULL == handle) { + hdd_err("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_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + + + filter = cdf_mem_malloc(sizeof(*filter)); + if (NULL == filter) { + hdd_err("Could not allocate Memory"); + return -ENOMEM; + } + filter->action = action; + for (i = 0; i < adapter->mc_addr_list.mc_cnt; i++) { + if (!memcmp(adapter->mc_addr_list.addr[i], + &pattern, 1)) { + memcpy(filter->multicastAddr[i], + adapter->mc_addr_list.addr[i], + sizeof(adapter->mc_addr_list.addr[i])); + filter->ulMulticastAddrCnt++; + hdd_err("%s RX filter : addr =" + MAC_ADDRESS_STR, + action ? "setting" : "clearing", + MAC_ADDR_ARRAY(filter->multicastAddr[i])); + } + } + /* Set rx filter */ + sme_8023_multicast_list(handle, adapter->sessionId, filter); + cdf_mem_free(filter); + } else { + hdd_err("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) { + hdd_err("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: + hdd_info("Unsupported RXFILTER type %d", type); + break; + } + + return ret; +} + +/** + * drv_cmd_rx_filter_remove() - RXFILTER REMOVE driver command handler + * @adapter: Pointer to network adapter + * @hdd_ctx: Pointer to hdd context + * @command: Pointer to input command + * @command_len: Command length + * @priv_data: Pointer to private data in command + */ +static int drv_cmd_rx_filter_remove(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_driver_rxfilter_comand_handler(command, adapter, false); +} + +/** + * drv_cmd_rx_filter_add() - RXFILTER ADD driver command handler + * @adapter: Pointer to network adapter + * @hdd_ctx: Pointer to hdd context + * @command: Pointer to input command + * @command_len: Command length + * @priv_data: Pointer to private data in command + */ +static int drv_cmd_rx_filter_add(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + return hdd_driver_rxfilter_comand_handler(command, adapter, true); +} + +/* + * dummy (no-op) hdd driver command handler + */ +static int drv_cmd_dummy(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + hdd_info("%s: Ignoring driver command \"%s\"", + adapter->dev->name, command); + return 0; +} + +/* + * handler for any unsupported wlan hdd driver command + */ +static int drv_cmd_invalid(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_UNSUPPORTED_IOCTL, + adapter->sessionId, 0)); + + hdd_warn("%s: Unsupported driver command \"%s\"", + adapter->dev->name, command); + + return -ENOTSUPP; +} + +/** + * drv_cmd_set_fcc_channel() - handle fcc constraint request + * @adapter: HDD adapter + * @hdd_ctx: HDD context + * @command: command ptr, SET_FCC_CHANNEL 0/1 is the command + * @command_len: command len + * @priv_data: private data + * + * Return: status + */ +static int drv_cmd_set_fcc_channel(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + uint8_t *value; + uint8_t fcc_constraint; + CDF_STATUS status; + int ret = 0; + + /* + * this command would 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 would 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 + */ + + value = command + command_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 + */ + hdd_err("value out of range"); + return -EINVAL; + } + + status = sme_disable_non_fcc_channel(hdd_ctx->hHal, !fcc_constraint); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("sme disable fn. returned err"); + ret = -EPERM; + } + + return ret; +} + +/* + * The following table contains all supported WLAN HDD + * IOCTL driver commands and the handler for each of them. + */ +static const hdd_drv_cmd_t hdd_drv_cmds[] = { + {"P2P_DEV_ADDR", drv_cmd_p2p_dev_addr}, + {"P2P_SET_NOA", drv_cmd_p2p_set_noa}, + {"P2P_SET_PS", drv_cmd_p2p_set_ps}, + {"SETBAND", drv_cmd_set_band}, + {"SETWMMPS", drv_cmd_set_wmmps}, + {"COUNTRY", drv_cmd_country}, + {"SETSUSPENDMODE", drv_cmd_dummy}, + {"SET_AP_WPS_P2P_IE", drv_cmd_dummy}, + {"BTCOEXSCAN", drv_cmd_dummy}, + {"RXFILTER", drv_cmd_dummy}, +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + {"SETROAMTRIGGER", drv_cmd_set_roam_trigger}, + {"GETROAMTRIGGER", drv_cmd_get_roam_trigger}, + {"SETROAMSCANPERIOD", drv_cmd_set_roam_scan_period}, + {"GETROAMSCANPERIOD", drv_cmd_get_roam_scan_period}, + {"SETROAMSCANREFRESHPERIOD", drv_cmd_set_roam_scan_refresh_period}, + {"GETROAMSCANREFRESHPERIOD", drv_cmd_get_roam_scan_refresh_period}, +#ifdef FEATURE_WLAN_LFR + {"SETROAMMODE", drv_cmd_set_roam_mode}, + {"GETROAMMODE", drv_cmd_get_roam_mode}, +#endif +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + {"SETROAMDELTA", drv_cmd_set_roam_delta}, + {"GETROAMDELTA", drv_cmd_get_roam_delta}, +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + {"GETBAND", drv_cmd_get_band}, + {"SETROAMSCANCHANNELS", drv_cmd_set_roam_scan_channels}, + {"GETROAMSCANCHANNELS", drv_cmd_get_roam_scan_channels}, + {"GETCCXMODE", drv_cmd_get_ccx_mode}, + {"GETOKCMODE", drv_cmd_get_okc_mode}, + {"GETFASTROAM", drv_cmd_get_fast_roam}, + {"GETFASTTRANSITION", drv_cmd_get_fast_transition}, + {"SETROAMSCANCHANNELMINTIME", drv_cmd_set_roam_scan_channel_min_time}, + {"SENDACTIONFRAME", drv_cmd_send_action_frame}, + {"GETROAMSCANCHANNELMINTIME", drv_cmd_get_roam_scan_channel_min_time}, + {"SETSCANCHANNELTIME", drv_cmd_set_scan_channel_time}, + {"GETSCANCHANNELTIME", drv_cmd_get_scan_channel_time}, + {"SETSCANHOMETIME", drv_cmd_set_scan_home_time}, + {"GETSCANHOMETIME", drv_cmd_get_scan_home_time}, + {"SETROAMINTRABAND", drv_cmd_set_roam_intra_band}, + {"GETROAMINTRABAND", drv_cmd_get_roam_intra_band}, + {"SETSCANNPROBES", drv_cmd_set_scan_n_probes}, + {"GETSCANNPROBES", drv_cmd_get_scan_n_probes}, + {"SETSCANHOMEAWAYTIME", drv_cmd_set_scan_home_away_time}, + {"GETSCANHOMEAWAYTIME", drv_cmd_get_scan_home_away_time}, + {"REASSOC", drv_cmd_reassoc}, + {"SETWESMODE", drv_cmd_set_wes_mode}, + {"GETWESMODE", drv_cmd_get_wes_mode}, + {"SETOPPORTUNISTICRSSIDIFF", drv_cmd_set_opportunistic_rssi_diff}, + {"GETOPPORTUNISTICRSSIDIFF", drv_cmd_get_opportunistic_rssi_diff}, + {"SETROAMRESCANRSSIDIFF", drv_cmd_set_roam_rescan_rssi_diff}, + {"GETROAMRESCANRSSIDIFF", drv_cmd_get_roam_rescan_rssi_diff}, +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ +#ifdef FEATURE_WLAN_LFR + {"SETFASTROAM", drv_cmd_set_fast_roam}, +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + {"SETFASTTRANSITION", drv_cmd_set_fast_transition}, + {"FASTREASSOC", drv_cmd_fast_reassoc}, +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + {"CCXPLMREQ", drv_cmd_ccx_plm_req}, +#endif +#ifdef FEATURE_WLAN_ESE + {"SETCCXMODE", drv_cmd_set_ccx_mode}, +#endif + {"SETROAMSCANCONTROL", drv_cmd_set_roam_scan_control}, +#ifdef FEATURE_WLAN_OKC + {"SETOKCMODE", drv_cmd_set_okc_mode}, +#endif /* FEATURE_WLAN_OKC */ + {"GETROAMSCANCONTROL", drv_cmd_get_roam_scan_control}, + {"BTCOEXMODE", drv_cmd_bt_coex_mode}, + {"SCAN-ACTIVE", drv_cmd_scan_active}, + {"SCAN-PASSIVE", drv_cmd_scan_passive}, + {"GETDWELLTIME", drv_cmd_get_dwell_time}, + {"SETDWELLTIME", drv_cmd_set_dwell_time}, + {"MIRACAST", drv_cmd_miracast}, +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + {"SETCCXROAMSCANCHANNELS", drv_cmd_set_ccx_roam_scan_channels}, + {"GETTSMSTATS", drv_cmd_get_tsm_stats}, + {"SETCCKMIE", drv_cmd_set_cckm_ie}, + {"CCXBEACONREQ", drv_cmd_ccx_beacon_req}, +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + {"SETMCRATE", drv_cmd_set_mc_rate}, + {"MAXTXPOWER", drv_cmd_max_tx_power}, + {"SETDFSSCANMODE", drv_cmd_set_dfs_scan_mode}, + {"GETDFSSCANMODE", drv_cmd_get_dfs_scan_mode}, + {"GETLINKSTATUS", drv_cmd_get_link_status}, +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + {"ENABLEEXTWOW", drv_cmd_enable_ext_wow}, + {"SETAPP1PARAMS", drv_cmd_set_app1_params}, + {"SETAPP2PARAMS", drv_cmd_set_app2_params}, +#endif +#ifdef FEATURE_WLAN_TDLS + {"TDLSSECONDARYCHANNELOFFSET", drv_cmd_tdls_secondary_channel_offset}, + {"TDLSOFFCHANNELMODE", drv_cmd_tdls_off_channel_mode}, + {"TDLSOFFCHANNEL", drv_cmd_tdls_off_channel}, + {"TDLSSCAN", drv_cmd_tdls_scan}, +#endif + {"RSSI", drv_cmd_get_rssi}, + {"LINKSPEED", drv_cmd_get_linkspeed}, +#ifdef FEATURE_NAPI + {"NAPI", drv_cmd_napi}, +#endif /* FEATURE_NAPI */ + {"RXFILTER-REMOVE", drv_cmd_rx_filter_remove}, + {"RXFILTER-ADD", drv_cmd_rx_filter_add}, + {"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel}, +}; + +/** + * hdd_drv_cmd_process() - chooses and runs the proper + * handler based on the input command + * @adapter: Pointer to the hdd adapter + * @cmd: Pointer to the driver command + * @priv_data: Pointer to the data associated with the command + * + * This function parses the input hdd driver command and runs + * the proper handler + * + * Return: 0 for success non-zero for failure + */ +static int hdd_drv_cmd_process(hdd_adapter_t *adapter, + uint8_t *cmd, + hdd_priv_data_t *priv_data) +{ + hdd_context_t *hdd_ctx; + int i; + const int cmd_num_total = ARRAY_SIZE(hdd_drv_cmds); + uint8_t *cmd_i = NULL; + hdd_drv_cmd_handler_t handler = NULL; + int len = 0; + + if (!adapter || !cmd || !priv_data) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: at least 1 param is NULL", __func__); + return -EINVAL; + } + + hdd_ctx = (hdd_context_t *)adapter->pHddCtx; + + for (i = 0; i < cmd_num_total; i++) { + + cmd_i = (uint8_t *)hdd_drv_cmds[i].cmd; + handler = hdd_drv_cmds[i].handler; + len = strlen(cmd_i); + + if (!handler) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: no. %d handler is NULL", __func__, i); + return -EINVAL; + } + + if (strncasecmp(cmd, cmd_i, len) == 0) + return handler(adapter, hdd_ctx, + cmd, len, priv_data); + } + + return drv_cmd_invalid(adapter, hdd_ctx, cmd, len, priv_data); +} + +/** + * hdd_driver_command() - top level wlan hdd driver command handler + * @adapter: Pointer to the hdd adapter + * @priv_data: Pointer to the raw command data + * + * This function is the top level wlan hdd driver command handler. It + * handles the command with the help of hdd_drv_cmd_process() + * + * Return: 0 for success non-zero for failure + */ +static int hdd_driver_command(hdd_adapter_t *adapter, + hdd_priv_data_t *priv_data) +{ + uint8_t *command = NULL; + int ret = 0; + + if (CDF_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 */ + if (priv_data->total_len <= 0 || + priv_data->total_len > WLAN_PRIV_DATA_MAX_LEN) { + hddLog(CDF_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(CDF_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'; + + hdd_info("%s: %s", adapter->dev->name, command); + ret = hdd_drv_cmd_process(adapter, command, priv_data); + +exit: + if (command) + kfree(command); + + return ret; +} + +#ifdef CONFIG_COMPAT +static int hdd_driver_compat_ioctl(hdd_adapter_t *adapter, 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 adapter 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(adapter, &priv_data); +exit: + return ret; +} +#else /* CONFIG_COMPAT */ +static int hdd_driver_compat_ioctl(hdd_adapter_t *adapter, struct ifreq *ifr) +{ + /* will never be invoked */ + return 0; +} +#endif /* CONFIG_COMPAT */ + +static int hdd_driver_ioctl(hdd_adapter_t *adapter, struct ifreq *ifr) +{ + hdd_priv_data_t priv_data; + int ret = 0; + + /* + * Note that adapter 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(adapter, &priv_data); + + return ret; +} + +/** + * __hdd_ioctl() - ioctl handler for wlan network interfaces + * @dev: device upon which the ioctl was received + * @ifr: ioctl request information + * @cmd: ioctl command + * + * This function does initial processing of wlan device ioctls. + * Currently two flavors of ioctls are supported. The primary ioctl + * that is supported is the (SIOCDEVPRIVATE + 1) ioctl which is used + * for Android "DRIVER" commands. The other ioctl that is + * conditionally supported is the SIOCIOCTLTX99 ioctl which is used + * for FTM on some platforms. This function simply verifies that the + * driver is in a sane state, and that the ioctl is one of the + * supported flavors, in which case flavor-specific handlers are + * dispatched. + * + * Return: 0 on success, non-zero on error + */ +static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; + + if (dev != adapter->dev) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s: HDD adapter/dev inconsistency", __func__); + ret = -ENODEV; + goto exit; + } + + if ((!ifr) || (!ifr->ifr_data)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: invalid data", __func__); + ret = -EINVAL; + goto exit; + } +#if defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR) + if (CDF_FTM_MODE == hdd_get_conparam()) { + if (SIOCIOCTLTX99 == cmd) { + ret = wlan_hdd_qcmbr_unified_ioctl(adapter, ifr); + goto exit; + } + } +#endif + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + ret = -EBUSY; + goto exit; + } + + switch (cmd) { + case (SIOCDEVPRIVATE + 1): + if (is_compat_task()) + ret = hdd_driver_compat_ioctl(adapter, ifr); + else + ret = hdd_driver_ioctl(adapter, ifr); + break; + default: + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d", + __func__, cmd); + ret = -EINVAL; + break; + } +exit: + return ret; +} + +/** + * hdd_ioctl() - ioctl handler (wrapper) for wlan network interfaces + * @dev: device upon which the ioctl was received + * @ifr: ioctl request information + * @cmd: ioctl command + * + * This function acts as an SSR-protecting wrapper to __hdd_ioctl() + * which is where the ioctls are really handled. + * + * Return: 0 on success, non-zero on error + */ +int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __hdd_ioctl(dev, ifr, cmd); + cds_ssr_unprotect(__func__); + return ret; +} diff --git a/core/hdd/src/wlan_hdd_ioctl.h b/core/hdd/src/wlan_hdd_ioctl.h new file mode 100644 index 000000000000..c1862ba242cc --- /dev/null +++ b/core/hdd/src/wlan_hdd_ioctl.h @@ -0,0 +1,39 @@ +/* + * 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(WLAN_HDD_IOCTL_H) +#define WLAN_HDD_IOCTL_H + +#include +#include +#include "wlan_hdd_main.h" + +int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +int wlan_hdd_set_mc_rate(hdd_adapter_t *pAdapter, int targetRate); + +#endif /* end #if !defined(WLAN_HDD_IOCTL_H) */ + diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c new file mode 100644 index 000000000000..c7efbc12fd18 --- /dev/null +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -0,0 +1,3935 @@ +/* + * 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: wlan_hdd_ipa.c + * + * WLAN HDD and ipa interface implementation + * Originally written by Qualcomm Atheros, Inc + */ + +#ifdef IPA_OFFLOAD + +/* Include Files */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cds_sched.h" + +#include "wma.h" +#include "wma_api.h" + +#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 +#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 HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0 +#define HDD_IPA_MAX_IFACE 3 +#define HDD_IPA_MAX_SYSBAM_PIPE 4 +#define HDD_IPA_RX_PIPE HDD_IPA_MAX_IFACE +#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_UC_ENABLE_MASK BIT(5) +#define HDD_IPA_UC_STA_ENABLE_MASK BIT(6) +#define HDD_IPA_REAL_TIME_DEBUGGING BIT(8) + +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, + /* keep this last */ + HDD_IPA_UC_OPCODE_MAX +} hdd_ipa_uc_op_code; + +/** + * enum - Reason codes for stat query + * + * @HDD_IPA_UC_STAT_REASON_NONE: Initial value + * @HDD_IPA_UC_STAT_REASON_DEBUG: For debug/info + * @HDD_IPA_UC_STAT_REASON_BW_CAL: For bandwidth calibration + */ +enum { + HDD_IPA_UC_STAT_REASON_NONE, + HDD_IPA_UC_STAT_REASON_DEBUG, + HDD_IPA_UC_STAT_REASON_BW_CAL +}; + +/** + * enum hdd_ipa_rm_state - IPA resource manager state + * @HDD_IPA_RM_RELEASED: PROD pipe resource released + * @HDD_IPA_RM_GRANT_PENDING: PROD pipe resource requested but not granted yet + * @HDD_IPA_RM_GRANTED: PROD pipe resource granted + */ +enum hdd_ipa_rm_state { + HDD_IPA_RM_RELEASED, + HDD_IPA_RM_GRANT_PENDING, + HDD_IPA_RM_GRANTED, +}; + +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; + +struct frag_header { + uint32_t + length:16, /* length field is LSB of the FRAG DESC */ + reserved16:16; + uint32_t reserved32; +} __packed; + +struct ipa_header { + uint32_t + 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; + +#define HDD_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header) +#define HDD_IPA_WLAN_IPA_HEADER sizeof(struct frag_header) + +/** + * struct hdd_ipa_cld_hdr - IPA CLD Header + * @reserved: reserved fields + * @iface_id: interface ID + * @sta_id: Station ID + * + * Packed 32-bit structure + * +----------+----------+--------------+--------+ + * | 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; +}; + +struct hdd_ipa_uc_rx_hdr { + struct ethhdr eth; +} __packed; + +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 */ + cdf_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; +}; + +struct ipa_uc_stas_map { + bool 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 { + cdf_list_node_t node; + hdd_adapter_t *adapter; + enum ipa_wlan_event type; + uint8_t sta_id; + uint8_t mac_addr[CDF_MAC_ADDR_SIZE]; +}; + +/** + * struct uc_rm_work_struct + * @work: uC RM work + * @event: IPA RM event + */ +struct uc_rm_work_struct { + struct work_struct work; + enum ipa_rm_event event; +}; + +/** + * struct uc_op_work_struct + * @work: uC OP work + * @msg: OP message + */ +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 + * @time: system time + * @ipa_excep_count: IPA exception packet count + * @rx_drop_count: IPA Rx drop packet count + * @net_sent_count: IPA Rx packet sent to network stack count + * @rx_discard_count: IPA Rx discard packet count + * @rx_mcbc_count: IPA Rx BCMC packet count + * @tx_mcbc_count: IPA Tx BCMC packet countt + * @tx_fwd_count: IPA Tx forward packet count + * @rx_destructor_call: IPA Rx packet destructor count + */ +struct uc_rt_debug_info { + v_TIME_t time; + uint64_t ipa_excep_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; +}; + +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 cdf + * APIs as it is taken care gracefully. Without this, kernel would throw + * an warning if spin_lock_bh is used while IRQ is disabled + */ + cdf_spinlock_t rm_lock; + struct uc_rm_work_struct uc_rm_work; + struct uc_op_work_struct uc_op_work[HDD_IPA_UC_OPCODE_MAX]; + cdf_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; + cdf_nbuf_queue_t pm_queue_head; + struct work_struct pm_work; + cdf_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; + + uint8_t activated_fw_pipe; + uint8_t sap_num_connected_sta; + uint8_t sta_connected; + uint32_t tx_pipe_handle; + uint32_t rx_pipe_handle; + bool resource_loading; + bool resource_unloading; + bool pending_cons_req; + struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT]; + cdf_list_t pending_event; + cdf_mutex_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; + uint32_t stat_req_reason; + 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; + cdf_mc_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; + cdf_mc_timer_t rt_debug_fill_timer; + cdf_mutex_t rt_debug_lock; +}; + +#define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr) +#define HDD_IPA_UC_WLAN_CLD_HDR_LEN 0 +#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_tx_hdr) +#define HDD_IPA_UC_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_uc_tx_hdr) +#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr) +#define HDD_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_uc_rx_hdr) + +#define HDD_IPA_GET_IFACE_ID(_data) \ + (((struct hdd_ipa_cld_hdr *) (_data))->iface_id) + +#define HDD_IPA_LOG(LVL, fmt, args ...) \ + CDF_TRACE(CDF_MODULE_ID_HDD, LVL, \ + "%s:%d: "fmt, __func__, __LINE__, ## args) + +#define HDD_IPA_DBG_DUMP(_lvl, _prefix, _buf, _len) \ + do { \ + CDF_TRACE(CDF_MODULE_ID_HDD, _lvl, "%s:", _prefix); \ + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_HDD, _lvl, _buf, _len); \ + } while (0) + +#define HDD_IPA_IS_CONFIG_ENABLED(_hdd_ctx, _mask) \ + (((_hdd_ctx)->config->IpaConfig & (_mask)) == (_mask)) + +#define HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa) \ + do { \ + hdd_ipa->ipa_rx_internel_drop_count++; \ + } while (0) +#define HDD_IPA_INCREASE_NET_SEND_COUNT(hdd_ipa) \ + do { \ + hdd_ipa->ipa_rx_net_send_count++; \ + } while (0) +#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) + +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] = { + { + IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD + }, { + IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD + }, { + IPA_CLIENT_WLAN4_CONS, IPA_CLIENT_WLAN1_PROD + }, +}; + +/* 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 + } +}; + +/* 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 */ + } +}; + +static const char *op_string[] = { + "TX_SUSPEND", + "TX_RESUME", + "RX_SUSPEND", + "RX_RESUME", + "STATS", +}; + +static struct hdd_ipa_priv *ghdd_ipa; + +/* 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_cleanup_iface(struct hdd_ipa_iface_context *iface_context); + +/** + * hdd_ipa_is_enabled() - Is IPA enabled? + * @hdd_ctx: Global HDD context + * + * Return: true if IPA is enabled, false otherwise + */ +bool hdd_ipa_is_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_ENABLE_MASK); +} + +/** + * hdd_ipa_uc_is_enabled() - Is IPA uC offload enabled? + * @hdd_ctx: Global HDD context + * + * Return: true if IPA uC offload is enabled, false otherwise + */ +bool hdd_ipa_uc_is_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_ENABLE_MASK); +} + +/** + * hdd_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled? + * @hdd_ctx: Global HDD context + * + * Return: true if STA mode IPA uC offload is enabled, false otherwise + */ +static inline bool hdd_ipa_uc_sta_is_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_STA_ENABLE_MASK); +} + +/** + * hdd_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled? + * @hdd_ipa: Global HDD IPA context + * + * Return: true if pre-filter is enabled, otherwise false + */ +static inline bool hdd_ipa_is_pre_filter_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, + HDD_IPA_PRE_FILTER_ENABLE_MASK); +} + +/** + * hdd_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled? + * @hdd_ipa: Global HDD IPA context + * + * Return: true if IPv6 is enabled, otherwise false + */ +static inline bool hdd_ipa_is_ipv6_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_IPV6_ENABLE_MASK); +} + +/** + * hdd_ipa_is_rm_enabled() - Is IPA resource manager enabled? + * @hdd_ipa: Global HDD IPA context + * + * Return: true if resource manager is enabled, otherwise false + */ +static inline bool hdd_ipa_is_rm_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_RM_ENABLE_MASK); +} + +/** + * hdd_ipa_is_rt_debugging_enabled() - Is IPA real-time debug enabled? + * @hdd_ipa: Global HDD IPA context + * + * Return: true if resource manager is enabled, otherwise false + */ +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); +} + +/** + * hdd_ipa_is_clk_scaling_enabled() - Is IPA clock scaling enabled? + * @hdd_ipa: Global HDD IPA context + * + * Return: true if clock scaling is enabled, otherwise false + */ +static inline bool hdd_ipa_is_clk_scaling_enabled(hdd_context_t *hdd_ctx) +{ + return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, + HDD_IPA_CLK_SCALING_ENABLE_MASK | + HDD_IPA_RM_ENABLE_MASK); +} + +/** + * 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 = (hdd_context_t *)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(hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA UC is not enabled", __func__); + return; + } + + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + cdf_mutex_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]; + + dump_info->time = cdf_mc_timer_get_system_time(); + dump_info->ipa_excep_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++; + cdf_mutex_release(&hdd_ipa->rt_debug_lock); + + cdf_mc_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 + * @hdd_ctx: 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(hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA UC is not enabled", __func__); + return; + } + + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "========= WLAN-IPA DEBUG BUF DUMP ==========\n"); + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + " TM : EXEP : DROP : NETS : MCBC : TXFD : DSTR : DSCD\n"); + + cdf_mutex_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]; + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%12lu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n", + dump_info->time, dump_info->ipa_excep_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); + } + cdf_mutex_release(&hdd_ipa->rt_debug_lock); + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "======= 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 = (hdd_context_t *)ctext; + struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + void *dummy_ptr = NULL; + + if (wlan_hdd_validate_context(hdd_ctx)) + return; + + if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA RT debug is not enabled", __func__); + return; + } + + /* Allocate dummy buffer periodically and free immediately. this will + * proactively detect OOM and if allocation fails dump ipa stats + */ + dummy_ptr = kmalloc(HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE, + GFP_KERNEL | GFP_ATOMIC); + if (!dummy_ptr) { + HDD_IPA_LOG(CDF_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); + } + + cdf_mc_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(CDF_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 + * @hdd_ctx: hdd main context + * + * free all rt debugging resources + * + * Return: none + */ +static void hdd_ipa_uc_rt_debug_deinit(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + if (CDF_TIMER_STATE_STOPPED != + cdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_fill_timer)) { + cdf_mc_timer_stop(&hdd_ipa->rt_debug_fill_timer); + } + cdf_mc_timer_destroy(&hdd_ipa->rt_debug_fill_timer); + cdf_mutex_destroy(&hdd_ipa->rt_debug_lock); + + if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA RT debug is not enabled", __func__); + return; + } + + if (CDF_TIMER_STATE_STOPPED != + cdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_timer)) { + cdf_mc_timer_stop(&hdd_ipa->rt_debug_timer); + } + cdf_mc_timer_destroy(&hdd_ipa->rt_debug_timer); +} + +/** + * hdd_ipa_uc_rt_debug_init - intialize resources to handle rt debugging + * @hdd_ctx: 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 = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + cdf_mutex_init(&hdd_ipa->rt_debug_lock); + cdf_mc_timer_init(&hdd_ipa->rt_debug_fill_timer, CDF_TIMER_TYPE_SW, + hdd_ipa_uc_rt_debug_host_fill, (void *)hdd_ctx); + hdd_ipa->rt_buf_fill_index = 0; + cdf_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; + + cdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer, + HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL); + + /* Reatime debug enable on feature enable */ + if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA RT debug is not enabled", __func__); + return; + } + cdf_mc_timer_init(&hdd_ipa->rt_debug_timer, CDF_TIMER_TYPE_SW, + hdd_ipa_uc_rt_debug_handler, (void *)hdd_ctx); + cdf_mc_timer_start(&hdd_ipa->rt_debug_timer, + HDD_IPA_UC_RT_DEBUG_PERIOD); + +} + +/** + * hdd_ipa_uc_stat_query() - Query the IPA stats + * @hdd_ctx: Global HDD context + * @ipa_tx_diff: tx packet count diff from previous + * tx packet count + * @ipa_rx_diff: rx packet count diff from previous + * rx packet count + * + * Return: true if IPA is enabled, false otherwise + */ +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(pHddCtx))) { + return; + } + + cdf_mutex_acquire(&hdd_ipa->event_lock); + if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && + (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(LOG1, "STAT Query TX DIFF %d, RX DIFF %d", + *ipa_tx_diff, *ipa_rx_diff); + } + cdf_mutex_release(&hdd_ipa->event_lock); + return; +} + +/** + * hdd_ipa_uc_stat_request() - Get IPA stats from IPA. + * @adapter: network adapter + * @reason: STAT REQ Reason + * + * Return: None + */ +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(pHddCtx))) { + return; + } + + HDD_IPA_LOG(LOG1, "STAT REQ Reason %d", reason); + cdf_mutex_acquire(&hdd_ipa->event_lock); + if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && + (false == hdd_ipa->resource_loading)) { + hdd_ipa->stat_req_reason = reason; + wma_cli_set_command( + (int)adapter->sessionId, + (int)WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID, + 0, VDEV_CMD); + } + cdf_mutex_release(&hdd_ipa->event_lock); +} + +/** + * hdd_ipa_uc_find_add_assoc_sta() - Find associated station + * @hdd_ipa: Global HDD IPA context + * @sta_add: Should station be added + * @sta_id: ID of the station being queried + * + * Return: true if the station was found + */ +static bool hdd_ipa_uc_find_add_assoc_sta(struct hdd_ipa_priv *hdd_ipa, + bool sta_add, uint8_t sta_id) +{ + bool sta_found = 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 = true; + break; + } + } + if (sta_add && sta_found) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: STA ID %d already exist, cannot add", + __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].is_reserved = true; + hdd_ipa->assoc_stas_map[idx].sta_id = sta_id; + return sta_found; + } + } + } + if (!sta_add && !sta_found) { + HDD_IPA_LOG(CDF_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 = + false; + hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF; + return sta_found; + } + } + } + return sta_found; +} + +/** + * hdd_ipa_uc_enable_pipes() - Enable IPA uC pipes + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno if error + */ +static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) +{ + int result; + p_cds_contextType cds_ctx = hdd_ipa->hdd_ctx->pcds_context; + + /* ACTIVATE TX PIPE */ + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Enable TX PIPE", __func__); + result = ipa_enable_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: Resume TX PIPE fail, code %d", + __func__, result); + return result; + } + ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, true); + + /* ACTIVATE RX PIPE */ + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Enable RX PIPE", __func__); + result = ipa_enable_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: Resume RX PIPE fail, code %d", + __func__, result); + return result; + } + ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, false); + + return 0; +} + +/** + * hdd_ipa_uc_disable_pipes() - Disable IPA uC pipes + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno if error + */ +static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa) +{ + int result; + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable RX PIPE", __func__); + result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle); + if (result) { + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: Disable RX PIPE fail, code %d", + __func__, result); + return result; + } + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable TX PIPE", __func__); + result = ipa_suspend_wdi_pipe(hdd_ipa->tx_pipe_handle); + if (result) { + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: Disable TX PIPE fail, code %d", + __func__, result); + return result; + } + + return 0; +} + +/** + * hdd_ipa_uc_handle_first_con() - Handle first uC IPA connection + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno if error + */ +static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa) +{ + hdd_ipa->activated_fw_pipe = 0; + hdd_ipa->resource_loading = true; + /* If RM feature enabled + * Request PROD Resource first + * PROD resource may return sync or async manners */ + if ((hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) && + (!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(CDF_TRACE_LEVEL_ERROR, + "%s: IPA WDI Pipes activate fail", + __func__); + hdd_ipa->resource_loading = false; + return -EBUSY; + } + } else { + /* RM Disabled + * Just enabled all the PIPEs */ + if (hdd_ipa_uc_enable_pipes(hdd_ipa)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: IPA WDI Pipes activate fail", + __func__); + hdd_ipa->resource_loading = false; + return -EBUSY; + } + hdd_ipa->resource_loading = false; + } + return 0; +} + +/** + * hdd_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection + * @hdd_ipa: Global HDD IPA context + * + * Return: None + */ +static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa) +{ + p_cds_contextType cds_ctx = hdd_ipa->hdd_ctx->pcds_context; + + hdd_ipa->resource_unloading = true; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable FW RX PIPE", __func__); + ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, false, false); + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable FW TX PIPE", __func__); + ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, false, true); +} + +/** + * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler + * @context: User context registered with TL (the IPA Global context is + * registered + * @rxpkt: Packet containing the notification + * @staid: ID of the station associated with the packet + * + * Return: None + */ +static void +hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event) +{ + struct hdd_ipa_priv *hdd_ipa = context; + CDF_STATUS status = CDF_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(CDF_TRACE_LEVEL_ERROR, "HDD context is not valid"); + return; + } + + if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + return; + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s, event code %d", + __func__, event); + + switch (event) { + case IPA_RM_RESOURCE_GRANTED: + /* Differed RM Granted */ + hdd_ipa_uc_enable_pipes(hdd_ipa); + cdf_mutex_acquire(&hdd_ipa->event_lock); + if ((false == hdd_ipa->resource_unloading) && + (!hdd_ipa->activated_fw_pipe)) { + hdd_ipa_uc_enable_pipes(hdd_ipa); + } + cdf_mutex_release(&hdd_ipa->event_lock); + if (hdd_ipa->pending_cons_req) { + ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED, + IPA_RM_RESOURCE_WLAN_CONS); + } + hdd_ipa->pending_cons_req = false; + break; + + case IPA_RM_RESOURCE_RELEASED: + /* Differed RM Released */ + hdd_ipa->resource_unloading = false; + if (hdd_ipa->pending_cons_req) { + ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED, + IPA_RM_RESOURCE_WLAN_CONS); + } + hdd_ipa->pending_cons_req = false; + break; + + default: + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s, invalid event code %d", __func__, event); + break; + } +} + +/** + * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification + * @hdd_ipa: Global HDD IPA context + * @event: IPA resource manager event to be deferred + * + * This function is called when a resource manager event is received + * from firmware in interrupt context. This function will defer the + * handling to the OL RX thread + * + * Return: None + */ +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); + + cds_ssr_protect(__func__); + event = uc_rm_work->event; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, + "%s, posted event %d", __func__, event); + + hdd_ipa_uc_rm_notify_handler(hdd_ipa, event); + cds_ssr_unprotect(__func__); + + return; +} + +/** + * hdd_ipa_uc_proc_pending_event() - Process IPA uC pending events + * @hdd_ipa: Global HDD IPA context + * + * Return: None + */ +static void hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa) +{ + unsigned int pending_event_count; + struct ipa_uc_pending_event *pending_event = NULL; + + cdf_list_size(&hdd_ipa->pending_event, &pending_event_count); + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s, Pending Event Count %d", __func__, pending_event_count); + if (!pending_event_count) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s, No Pending Event", __func__); + return; + } + + cdf_list_remove_front(&hdd_ipa->pending_event, + (cdf_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); + cdf_mem_free(pending_event); + pending_event = NULL; + cdf_list_remove_front(&hdd_ipa->pending_event, + (cdf_list_node_t **)&pending_event); + } +} + +/** + * hdd_ipa_uc_op_cb() - IPA uC operation callback + * @op_msg: operation message received from firmware + * @usr_ctxt: user context registered with TL (we register the HDD Global + * context) + * + * Return: None + */ +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; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (!op_msg || !usr_ctxt) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "%s, INVALID ARG", __func__); + return; + } + + if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s, INVALID OPCODE %d", __func__, msg->op_code); + return; + } + + hdd_ctx = (hdd_context_t *) usr_ctxt; + + /* + * When SSR is going on or driver is unloading, just return. + */ + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "HDD context is not valid"); + cdf_mem_free(op_msg); + return; + } + + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + + HDD_IPA_LOG(CDF_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)) { + cdf_mutex_acquire(&hdd_ipa->event_lock); + hdd_ipa->activated_fw_pipe++; + if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) { + hdd_ipa->resource_loading = false; + hdd_ipa_uc_proc_pending_event(hdd_ipa); + } + cdf_mutex_release(&hdd_ipa->event_lock); + } + + if ((HDD_IPA_UC_OPCODE_TX_SUSPEND == msg->op_code) || + (HDD_IPA_UC_OPCODE_RX_SUSPEND == msg->op_code)) { + cdf_mutex_acquire(&hdd_ipa->event_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->hdd_ctx)) && + (!ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD))) { + /* Sync return success from IPA + * Enable/resume all the PIPEs */ + hdd_ipa->resource_unloading = false; + hdd_ipa_uc_proc_pending_event(hdd_ipa); + } else { + hdd_ipa->resource_unloading = false; + hdd_ipa_uc_proc_pending_event(hdd_ipa); + } + } + cdf_mutex_release(&hdd_ipa->event_lock); + } + + if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) && + (HDD_IPA_UC_STAT_REASON_DEBUG == hdd_ipa->stat_req_reason)) { + + /* STATs from host */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST CE ====\n" + "CE RING BASE: 0x%x\n" + "CE RING SIZE: %d\n" + "CE REG ADDR : 0x%llx", + hdd_ctx->ce_sr_base_paddr, + hdd_ctx->ce_sr_ring_size, + (uint64_t) hdd_ctx->ce_reg_paddr); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "==== IPA_UC WLAN_HOST CONTROL ====\n" + "SAP NUM STAs: %d\n" + "STA CONNECTED: %d\n" + "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, + hdd_ipa->sta_connected, + 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 *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + cdf_mutex_acquire(&hdd_ipa->event_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); + cdf_mutex_release(&hdd_ipa->event_lock); + } else { + HDD_IPA_LOG(LOGE, "INVALID REASON %d", + hdd_ipa->stat_req_reason); + } + cdf_mem_free(op_msg); +} + + +/** + * hdd_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw + * @adapter: device adapter instance + * @offload_type: MCC or SCC + * @enable: TX offload enable or disable + * + * Return: none + */ +static void hdd_ipa_uc_offload_enable_disable(hdd_adapter_t *adapter, + uint32_t offload_type, uint32_t 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 (WLAN_HDD_SOFTAP == adapter->device_mode && adapter->ipa_context) + return; + + /* 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; + + cdf_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(CDF_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 (CDF_STATUS_SUCCESS != + sme_ipa_offload_enable_disable(WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId, &ipa_offload_enable_disable)) { + HDD_IPA_LOG(CDF_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); + } +} + +/** + * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler + * @work: uC OP work + * + * Return: None + */ +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; + + cds_ssr_protect(__func__); + + msg = uc_op_work->msg; + uc_op_work->msg = NULL; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, + "%s, posted msg %d", __func__, msg->op_code); + + hdd_ipa_uc_op_cb(msg, hdd_ipa->hdd_ctx); + + cds_ssr_unprotect(__func__); + + return; +} + +/** + * hdd_ipa_uc_op_event_handler() - Adapter lookup + * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler + * @op_msg: operation message received from firmware + * @hdd_ctx: Global HDD context + * + * Return: None + */ +static void hdd_ipa_uc_op_event_handler(uint8_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; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "HDD context is not valid"); + 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(CDF_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: + cdf_mem_free(op_msg); +} + +/** + * hdd_ipa_uc_ol_init() - Initialize IPA uC offload + * @hdd_ctx: Global HDD context + * + * Return: CDF_STATUS + */ +static CDF_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; + p_cds_contextType cds_ctx = hdd_ctx->pcds_context; + uint8_t i; + + cdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi_in_params)); + cdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params)); + + cdf_list_init(&ipa_ctxt->pending_event, 1000); + cdf_mutex_init(&ipa_ctxt->event_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->config->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(hdd_ctx)) { + HDD_IPA_LOG(CDF_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; + + /* Connect WDI IPA PIPE */ + ipa_connect_wdi_pipe(&pipe_in, &pipe_out); + /* Micro Controller Doorbell register */ + hdd_ctx->tx_comp_doorbell_paddr = (uint32_t) pipe_out.uc_door_bell_pa; + /* WLAN TX PIPE Handle */ + ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl; + HDD_IPA_LOG(CDF_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->config->IpaDescSize + + sizeof(struct sps_iovec); + pipe_in.sys.notify = hdd_ipa_w2i_cb; + if (!hdd_ipa_is_rm_enabled(hdd_ctx)) { + HDD_IPA_LOG(CDF_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; + + ipa_connect_wdi_pipe(&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(CDF_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); + + ol_txrx_ipa_uc_set_doorbell_paddr(cds_ctx->pdev_txrx_ctx, + (uint32_t) hdd_ctx->tx_comp_doorbell_paddr, + (uint32_t) hdd_ctx->rx_ready_doorbell_paddr); + + ol_txrx_ipa_uc_register_op_cb(cds_ctx->pdev_txrx_ctx, + 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 CDF_STATUS_SUCCESS; +} + +#ifdef IPA_UC_OFFLOAD +/** + * 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(void) +{ + 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); + + cdf_wake_lock_acquire(&hdd_ipa->event_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; + } + cdf_wake_lock_release(&hdd_ipa->event_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(void) +{ + 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; +} +#endif + +/** + * hdd_ipa_wake_lock_timer_func() - Wake lock work handler + * @work: scheduled work + * + * When IPA resources are released in hdd_ipa_rm_try_release() we do + * not want to immediately release the wake lock since the system + * would then potentially try to suspend when there is a healthy data + * rate. Deferred work is scheduled and this function handles the + * work. When this function is called, if the IPA resource is still + * released then we release the wake lock. + * + * Return: None + */ +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); + + cdf_spin_lock_bh(&hdd_ipa->rm_lock); + + if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) + goto end; + + hdd_ipa->wake_lock_released = true; + cdf_wake_lock_release(&hdd_ipa->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_IPA); + +end: + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); +} + +/** + * hdd_ipa_rm_request() - Request resource from IPA + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno on error + */ +static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa) +{ + int ret = 0; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + return 0; + + cdf_spin_lock_bh(&hdd_ipa->rm_lock); + + switch (hdd_ipa->rm_state) { + case HDD_IPA_RM_GRANTED: + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + return 0; + case HDD_IPA_RM_GRANT_PENDING: + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EINPROGRESS; + case HDD_IPA_RM_RELEASED: + hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING; + break; + } + + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + + ret = ipa_rm_inactivity_timer_request_resource( + IPA_RM_RESOURCE_WLAN_PROD); + + cdf_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) { + cdf_wake_lock_acquire(&hdd_ipa->wake_lock, + WIFI_POWER_EVENT_WAKELOCK_IPA); + hdd_ipa->wake_lock_released = false; + } + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + + return ret; +} + +/** + * hdd_ipa_rm_try_release() - Attempt to release IPA resource + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 if resources released, negative errno otherwise + */ +static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa) +{ + int ret = 0; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + return 0; + + if (atomic_read(&hdd_ipa->tx_ref_cnt)) + return -EAGAIN; + + spin_lock_bh(&hdd_ipa->q_lock); + if (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) && + (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); + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + + if (!cdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) { + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + return -EAGAIN; + } + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + + cdf_spin_lock_bh(&hdd_ipa->rm_lock); + switch (hdd_ipa->rm_state) { + case HDD_IPA_RM_GRANTED: + break; + case HDD_IPA_RM_GRANT_PENDING: + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EINPROGRESS; + case HDD_IPA_RM_RELEASED: + cdf_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++; + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + + ret = + ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_WLAN_PROD); + + cdf_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)); + + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + + return ret; +} + +/** + * hdd_ipa_rm_notify() - IPA resource manager notifier callback + * @user_data: user data registered with IPA + * @event: the IPA resource manager event that occurred + * @data: the data associated with the event + * + * Return: None + */ +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->hdd_ctx)) + return; + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "Evt: %d", event); + + switch (event) { + case IPA_RM_RESOURCE_GRANTED: + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + /* 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; + } + cdf_spin_lock_bh(&hdd_ipa->rm_lock); + hdd_ipa->rm_state = HDD_IPA_RM_GRANTED; + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + hdd_ipa->stats.num_rm_grant++; + break; + + case IPA_RM_RESOURCE_RELEASED: + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "RM Release"); + hdd_ipa->resource_unloading = false; + break; + + default: + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event); + break; + } +} + +/** + * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler + * + * Callback function registered with IPA that is called when IPA wants + * to release the WLAN consumer resource + * + * Return: 0 if the request is granted, negative errno otherwise + */ +static int hdd_ipa_rm_cons_release(void) +{ + return 0; +} + +/** + * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler + * + * Callback function registered with IPA that is called when IPA wants + * to access the WLAN consumer resource + * + * Return: 0 if the request is granted, negative errno otherwise + */ +static int hdd_ipa_rm_cons_request(void) +{ + if ((ghdd_ipa->resource_loading) || (ghdd_ipa->resource_unloading)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: ipa resource loading/unloading in progress", + __func__); + ghdd_ipa->pending_cons_req = true; + return -EPERM; + } + return 0; +} + +/** + * hdd_ipa_set_perf_level() - Set IPA performance level + * @hdd_ctx: Global HDD context + * @tx_packets: Number of packets transmitted in the last sample period + * @rx_packets: Number of packets received in the last sample period + * + * Return: 0 on success, negative errno on error + */ +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_ctx))) + return 0; + + memset(&profile, 0, sizeof(profile)); + + if (tx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2)) + next_cons_bw = hdd_ctx->config->IpaHighBandwidthMbps; + else if (tx_packets > + (hdd_ctx->config->busBandwidthMediumThreshold / 2)) + next_cons_bw = hdd_ctx->config->IpaMediumBandwidthMbps; + else + next_cons_bw = hdd_ctx->config->IpaLowBandwidthMbps; + + if (rx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2)) + next_prod_bw = hdd_ctx->config->IpaHighBandwidthMbps; + else if (rx_packets > + (hdd_ctx->config->busBandwidthMediumThreshold / 2)) + next_prod_bw = hdd_ctx->config->IpaMediumBandwidthMbps; + else + next_prod_bw = hdd_ctx->config->IpaLowBandwidthMbps; + + HDD_IPA_LOG(LOG1, + "CONS perf curr: %d, next: %d", + hdd_ipa->curr_cons_bw, next_cons_bw); + HDD_IPA_LOG(LOG1, + "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(CDF_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(CDF_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(CDF_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(CDF_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; +} + +/** + * hdd_ipa_setup_rm() - Setup IPA resource management + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno on error + */ +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->hdd_ctx)) + return 0; + + cnss_init_work(&hdd_ipa->uc_rm_work.work, hdd_ipa_uc_rm_notify_defer); + 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(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_ERROR, + "Set perf level failed: %d", ret); + goto set_perf_failed; + } + + cdf_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 + cdf_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; +} + +/** + * hdd_ipa_destroy_rm_resource() - Destroy IPA resources + * @hdd_ipa: Global HDD IPA context + * + * Destroys all resources associated with the IPA resource manager + * + * Return: None + */ +static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa) +{ + int ret; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + return; + + cancel_delayed_work_sync(&hdd_ipa->wake_lock_work); + cdf_wake_lock_destroy(&hdd_ipa->wake_lock); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&hdd_ipa->uc_rm_work.work); +#endif + cdf_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(CDF_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(CDF_TRACE_LEVEL_ERROR, + "RM CONS resource delete failed %d", ret); +} + +/** + * hdd_ipa_send_skb_to_network() - Send skb to kernel + * @skb: network buffer + * @adapter: network adapter + * + * Called when a network buffer is received which should not be routed + * to the IPA module. + * + * Return: None + */ +static void hdd_ipa_send_skb_to_network(cdf_nbuf_t skb, + hdd_adapter_t *adapter) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + unsigned int cpu_index; + + if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_LOW, "Invalid adapter: 0x%p", + adapter); + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + cdf_nbuf_free(skb); + return; + } + + if (hdd_ipa->hdd_ctx->isUnloadInProgress) { + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + cdf_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]; + if (netif_rx_ni(skb) == 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; +} + +#define FW_RX_DESC_DISCARD_M 0x1 +#define FW_RX_DESC_FORWARD_M 0x2 + +/** + * hdd_ipa_w2i_cb() - WLAN to IPA callback handler + * @priv: pointer to private data registered with IPA (we register a + * pointer to the global IPA context) + * @evt: the IPA event which triggered the callback + * @data: data associated with the event + * + * Return: None + */ +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; + cdf_nbuf_t skb; + uint8_t iface_id; + uint8_t session_id; + struct hdd_ipa_iface_context *iface_context; + cdf_nbuf_t copy; + uint8_t fw_desc; + int ret; + + hdd_ipa = (struct hdd_ipa_priv *)priv; + + switch (evt) { + case IPA_RECEIVE: + skb = (cdf_nbuf_t) data; + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + session_id = (uint8_t)skb->cb[0]; + iface_id = vdev_to_iface[session_id]; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, + "IPA_RECEIVE: session_id=%u, iface_id=%u", + session_id, iface_id); + } else { + iface_id = HDD_IPA_GET_IFACE_ID(skb->data); + } + + if (iface_id >= HDD_IPA_MAX_IFACE) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "IPA_RECEIVE: Invalid iface_id: %u", + iface_id); + HDD_IPA_DBG_DUMP(CDF_TRACE_LEVEL_INFO_HIGH, + "w2i -- skb", skb->data, 8); + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + cdf_nbuf_free(skb); + return; + } + + iface_context = &hdd_ipa->iface_context[iface_id]; + adapter = iface_context->adapter; + + HDD_IPA_DBG_DUMP(CDF_TRACE_LEVEL_DEBUG, + "w2i -- skb", skb->data, 8); + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + hdd_ipa->stats.num_rx_excep++; + skb_pull(skb, HDD_IPA_UC_WLAN_CLD_HDR_LEN); + } else { + skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN); + } + + iface_context->stats.num_rx_ipa_excep++; + + /* Disable to forward Intra-BSS Rx packets when + * ap_isolate=1 in hostapd.conf + */ + if (adapter->sessionCtx.ap.apDisableIntraBssFwd) { + /* + * 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_DISCARD_M) { + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + hdd_ipa->ipa_rx_discard++; + cdf_nbuf_free(skb); + break; + } + + if (fw_desc & FW_RX_DESC_FORWARD_M) { + HDD_IPA_LOG( + CDF_TRACE_LEVEL_DEBUG, + "Forward packet to Tx (fw_desc=%d)", + fw_desc); + copy = cdf_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( + CDF_TRACE_LEVEL_DEBUG, + "Forward packet tx fail"); + hdd_ipa->stats. + num_tx_bcmc_err++; + } else { + hdd_ipa->stats.num_tx_bcmc++; + } + } + } + } else { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, + "Intra-BSS FWD is disabled-skip forward to Tx"); + } + + hdd_ipa_send_skb_to_network(skb, adapter); + break; + + default: + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "w2i cb wrong event: 0x%x", evt); + return; + } +} + +/** + * hdd_ipa_nbuf_cb() - IPA TX complete callback + * @skb: packet buffer which was transmitted + * + * Return: None + */ +static void hdd_ipa_nbuf_cb(cdf_nbuf_t skb) +{ + struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; + + HDD_IPA_LOG(CDF_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); +} + +/** + * hdd_ipa_send_pkt_to_tl() - Send an IPA packet to TL + * @iface_context: interface-specific IPA context + * @ipa_tx_desc: packet data descriptor + * + * Return: None + */ +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; + uint8_t interface_id; + hdd_adapter_t *adapter = NULL; + cdf_nbuf_t skb; + + cdf_spin_lock_bh(&iface_context->interface_lock); + adapter = iface_context->adapter; + if (!adapter) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_WARN, "Interface Down"); + ipa_free_skb(ipa_tx_desc); + iface_context->stats.num_tx_drop++; + cdf_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); + cdf_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; + + cdf_spin_unlock_bh(&iface_context->interface_lock); + + skb = ipa_tx_desc->skb; + + cdf_mem_set(skb->cb, sizeof(skb->cb), 0); + NBUF_OWNER_ID(skb) = IPA_NBUF_OWNER_ID; + NBUF_CALLBACK_FN(skb) = hdd_ipa_nbuf_cb; + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { + NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr + + HDD_IPA_WLAN_FRAG_HEADER + + HDD_IPA_WLAN_IPA_HEADER; + ipa_tx_desc->skb->len -= + HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER; + } else + NBUF_MAPPED_PADDR_LO(skb) = ipa_tx_desc->dma_addr; + + NBUF_OWNER_PRIV_DATA(skb) = (unsigned long)ipa_tx_desc; + + adapter->stats.tx_bytes += ipa_tx_desc->skb->len; + + skb = ol_tx_send_ipa_data_frame(iface_context->tl_context, + ipa_tx_desc->skb); + if (skb) { + HDD_IPA_LOG(CDF_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++; + +} + +/** + * hdd_ipa_pm_send_pkt_to_tl() - Send queued packets to TL + * @work: pointer to the scheduled work + * + * Called during PM resume to send packets to TL which were queued + * while host was in the process of suspending. + * + * Return: None + */ +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; + cdf_nbuf_t skb; + uint32_t dequeued = 0; + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + + while (((skb = cdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head)) != NULL)) { + cdf_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); + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + } + + cdf_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; +} + +/** + * hdd_ipa_i2w_cb() - IPA to WLAN callback + * @priv: pointer to private data registered with IPA (we register a + * pointer to the interface-specific IPA context) + * @evt: the IPA event which triggered the callback + * @data: data associated with the event + * + * Return: None + */ +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; + cdf_nbuf_t skb; + struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (evt != IPA_RECEIVE) { + skb = (cdf_nbuf_t) data; + dev_kfree_skb_any(skb); + iface_context->stats.num_tx_drop++; + return; + } + + iface_context = (struct hdd_ipa_iface_context *)priv; + 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(CDF_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(CDF_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); + + cdf_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) { + cdf_mem_set(skb->cb, sizeof(skb->cb), 0); + 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; + cdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb); + hdd_ipa->stats.num_tx_queued++; + + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + return; + } + + cdf_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); +} + +/** + * hdd_ipa_suspend() - Suspend IPA + * @hdd_ctx: Global HDD context + * + * Return: 0 on success, negativer errno on error + */ +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; + + cdf_spin_lock_bh(&hdd_ipa->rm_lock); + + if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) { + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + return -EAGAIN; + } + cdf_spin_unlock_bh(&hdd_ipa->rm_lock); + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + hdd_ipa->suspended = true; + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + + return 0; +} + +/** + * hdd_ipa_resume() - Resume IPA following suspend + * hdd_ctx: Global HDD context + * + * Return: 0 on success, negative errno on error + */ +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); + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + hdd_ipa->suspended = false; + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + + return 0; +} + +/** + * hdd_ipa_setup_sys_pipe() - Setup all IPA Sys pipes + * @hdd_ipa: Global HDD IPA context + * + * Return: 0 on success, negative errno on error + */ +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->config->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; + + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { + 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; + } + ipa->ipa_ep_cfg.mode.mode = IPA_BASIC; + + if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + ipa->keep_ipa_awake = 1; + + ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); + if (ret) { + HDD_IPA_LOG(CDF_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; + } + + if (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { + /* + * 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->hdd_ctx)) + ipa->keep_ipa_awake = 1; + + ret = ipa_setup_sys_pipe(ipa, &(hdd_ipa->sys_pipe[i].conn_hdl)); + if (ret) { + HDD_IPA_LOG(CDF_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; + } + + return ret; + +setup_sys_pipe_fail: + + while (--i >= 0) { + ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].conn_hdl); + cdf_mem_zero(&hdd_ipa->sys_pipe[i], + sizeof(struct hdd_ipa_sys_pipe)); + } + + return ret; +} + +/** + * hdd_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes + * @hdd_ipa: Global HDD IPA context + * + * Return: None + */ +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(CDF_TRACE_LEVEL_ERROR, "Failed: %d", + ret); + + hdd_ipa->sys_pipe[i].conn_hdl_valid = 0; + } + } +} + +/** + * hdd_ipa_register_interface() - register IPA interface + * @hdd_ipa: Global IPA context + * @iface_context: Per-interface IPA context + * + * Return: 0 on success, negative errno on error + */ +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->hdd_ctx)) + num_prop++; + + /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */ + tx_prop = + cdf_mem_malloc(sizeof(struct ipa_ioc_tx_intf_prop) * num_prop); + if (!tx_prop) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "tx_prop allocation failed"); + goto register_interface_fail; + } + + /* Allocate RX properties, 1 each for IPv4 & IPv6 */ + rx_prop = + cdf_mem_malloc(sizeof(struct ipa_ioc_rx_intf_prop) * num_prop); + if (!rx_prop) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "rx_prop allocation failed"); + goto register_interface_fail; + } + + cdf_mem_zero(&tx_intf, sizeof(tx_intf)); + cdf_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; + rx_prop[IPA_IP_v4].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; + 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->hdd_ctx)) { + rx_prop[IPA_IP_v6].ip = IPA_IP_v6; + rx_prop[IPA_IP_v6].src_pipe = iface_context->prod_client; + rx_prop[IPA_IP_v6].hdr_l2_type = IPA_HDR_L2_ETHERNET_II; + rx_prop[IPA_IP_v4].attrib.attrib_mask = IPA_FLT_META_DATA; + rx_prop[IPA_IP_v4].attrib.meta_data = + htonl(iface_context->adapter->sessionId << 16); + rx_prop[IPA_IP_v4].attrib.meta_data_mask = htonl(0x00FF0000); + + rx_intf.num_props++; + } + + tx_prop[IPA_IP_v4].ip = IPA_IP_v4; + 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; + 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->hdd_ctx)) { + tx_prop[IPA_IP_v6].ip = IPA_IP_v6; + 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; + 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: + cdf_mem_free(tx_prop); + cdf_mem_free(rx_prop); + return ret; +} + +/** + * hdd_remove_ipa_header() - Remove a specific header from IPA + * @name: Name of the header to be removed + * + * Return: None + */ +static void hdd_ipa_remove_header(char *name) +{ + struct ipa_ioc_get_hdr hdrlookup; + int ret = 0, len; + struct ipa_ioc_del_hdr *ipa_hdr; + + cdf_mem_zero(&hdrlookup, sizeof(hdrlookup)); + strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name)); + ret = ipa_get_hdr(&hdrlookup); + if (ret) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "Hdr deleted already %s, %d", + name, ret); + return; + } + + HDD_IPA_LOG(CDF_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 *)cdf_mem_malloc(len); + if (ipa_hdr == NULL) { + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, "Delete header failed: %d", + ret); + + cdf_mem_free(ipa_hdr); +} + +/** + * hdd_ipa_add_header_info() - Add IPA header for a given interface + * @hdd_ipa: Global HDD IPA context + * @iface_context: Interface-specific HDD IPA context + * @mac_addr: Interface MAC address + * + * Return: 0 on success, negativer errno value on error + */ +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; + struct hdd_ipa_uc_tx_hdr *uc_tx_hdr = NULL; + + ifname = adapter->dev->name; + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "Add Partial hdr: %s, %pM", + ifname, mac_addr); + + /* dynamically allocate the memory to add the hdrs */ + ipa_hdr = cdf_mem_malloc(sizeof(struct ipa_ioc_add_hdr) + + sizeof(struct ipa_hdr_add)); + if (!ipa_hdr) { + HDD_IPA_LOG(CDF_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->hdd_ctx)) { + 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(CDF_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); + } 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(CDF_TRACE_LEVEL_ERROR, "%s IPv4 add hdr failed: %d", + ifname, ret); + goto end; + } + + HDD_IPA_LOG(CDF_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->hdd_ctx)) { + snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s", + ifname, HDD_IPA_IPV6_NAME_EXT); + + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + 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 { + /* 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(CDF_TRACE_LEVEL_ERROR, + "%s: IPv6 add hdr failed: %d", ifname, ret); + goto clean_ipv4_hdr; + } + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: IPv6 hdr_hdl: 0x%x", + ipa_hdr->hdr[0].name, ipa_hdr->hdr[0].hdr_hdl); + } + + cdf_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_ipa_remove_header(ipa_hdr->hdr[0].name); +end: + if (ipa_hdr) + cdf_mem_free(ipa_hdr); + + return ret; +} + +/** + * hdd_ipa_clean_hdr() - Cleanup IPA on a given adapter + * @adapter: Adapter upon which IPA was previously configured + * + * Return: None + */ +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_ipa_remove_header(name_ipa); + + if (hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx)) { + snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s", + adapter->dev->name, HDD_IPA_IPV6_NAME_EXT); + hdd_ipa_remove_header(name_ipa); + } + /* unregister the interface with IPA */ + ret = ipa_deregister_intf(adapter->dev->name); + if (ret) + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: ipa_deregister_intf fail: %d", + adapter->dev->name, ret); +} + +/** + * hdd_ipa_cleanup_iface() - Cleanup IPA on a given interface + * @iface_context: interface-specific IPA context + * + * Return: None + */ +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); + + cdf_spin_lock_bh(&iface_context->interface_lock); + iface_context->adapter->ipa_context = NULL; + iface_context->adapter = NULL; + iface_context->tl_context = NULL; + cdf_spin_unlock_bh(&iface_context->interface_lock); + iface_context->ifa_address = 0; + if (!iface_context->hdd_ipa->num_iface) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "NUM INTF 0, Invalid"); + CDF_ASSERT(0); + } + iface_context->hdd_ipa->num_iface--; +} + +/** + * hdd_ipa_setup_iface() - Setup IPA on a given interface + * @hdd_ipa: HDD IPA global context + * @adapter: Interface upon which IPA is being setup + * @sta_id: Station ID of the API instance + * + * Return: 0 on success, negative errno value on error + */ +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(CDF_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 = ol_txrx_get_vdev_by_sta_id(sta_id); + + if (tl_context == NULL) { + HDD_IPA_LOG(CDF_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; +} + +/** + * hdd_ipa_msg_free_fn() - Free an IPA message + * @buff: pointer to the IPA message + * @len: length of the IPA message + * @type: type of IPA message + * + * Return: None + */ +static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type) +{ + hddLog(LOG1, "msg type:%d, len:%d", type, len); + ghdd_ipa->stats.num_free_msg++; + cdf_mem_free(buff); +} + +/** + * hdd_ipa_send_mcc_scc_msg() - send IPA WLAN_SWITCH_TO_MCC/SCC message + * @mcc_mode: 0=MCC/1=SCC + * + * Return: 0 on success, negative errno value on error + */ +int hdd_ipa_send_mcc_scc_msg(hdd_context_t *pHddCtx, bool mcc_mode) +{ + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + CDF_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(pHddCtx)) + return -EINVAL; + + if (!pHddCtx->mcc_mode) { + /* Flush TxRx queue for each adapter before switch to SCC */ + status = hdd_get_front_adapter(pHddCtx, &adapter_node); + while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) { + pAdapter = adapter_node->pAdapter; + if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_SOFTAP) { + hddLog(CDF_TRACE_LEVEL_INFO, + "MCC->SCC: Flush TxRx queue(d_mode=%d)", + pAdapter->device_mode); + hdd_deinit_tx_rx(pAdapter); + } + status = hdd_get_next_adapter( + pHddCtx, adapter_node, &next); + adapter_node = next; + } + } + + /* Send SCC/MCC Switching event to IPA */ + meta.msg_len = sizeof(*msg); + msg = cdf_mem_malloc(meta.msg_len); + if (msg == NULL) { + hddLog(LOGE, "msg allocation failed"); + return -ENOMEM; + } + + meta.msg_type = mcc_mode ? + WLAN_SWITCH_TO_MCC : WLAN_SWITCH_TO_SCC; + hddLog(LOG1, "ipa_send_msg(Evt:%d)", meta.msg_type); + + ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn); + + if (ret) { + hddLog(LOGE, "ipa_send_msg(Evt:%d) - fail=%d", + meta.msg_type, ret); + cdf_mem_free(msg); + } + + return ret; +} + +/** + * hdd_ipa_wlan_event_to_str() - convert IPA WLAN event to string + * @event: IPA WLAN event to be converted to a string + * + * Return: ASCII string representing the IPA WLAN event + */ +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"; + } +} + +/** + * hdd_ipa_wlan_evt() - IPA event handler + * @adapter: adapter upon which the event was received + * @sta_id: station id for the event + * @type: the event type + * @mac_address: MAC address associated with the event + * + * Return: 0 on success, negative errno value on error + */ +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(CDF_TRACE_LEVEL_INFO, "%s: %s evt, MAC: %pM sta_id: %d", + adapter->dev->name, hdd_ipa_wlan_event_to_str(type), + mac_addr, sta_id); + + if (type >= IPA_WLAN_EVENT_MAX) + return -EINVAL; + + if (WARN_ON(is_zero_ether_addr(mac_addr))) + return -EINVAL; + + if (!hdd_ipa || !hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "IPA OFFLOAD NOT ENABLED"); + return -EINVAL; + } + + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) && + !hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) && + (WLAN_HDD_SOFTAP != adapter->device_mode)) { + return 0; + } + + /* + * During IPA UC resource loading/unloading new events can be issued. + * Store the events separately and handle them later. + */ + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) && + ((hdd_ipa->resource_loading) || + (hdd_ipa->resource_unloading))) { + struct ipa_uc_pending_event *pending_evet = NULL; + + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s, RL/RUL inprogress", __func__); + pending_evet = (struct ipa_uc_pending_event *)cdf_mem_malloc( + sizeof(struct ipa_uc_pending_event)); + if (!pending_evet) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "Pending event memory alloc fail"); + return -ENOMEM; + } + pending_evet->adapter = adapter; + pending_evet->sta_id = sta_id; + pending_evet->type = type; + cdf_mem_copy(pending_evet->mac_addr, + mac_addr, + CDF_MAC_ADDR_SIZE); + cdf_list_insert_back(&hdd_ipa->pending_event, + &pending_evet->node); + return 0; + } + + hdd_ipa->stats.event[type]++; + + switch (type) { + case WLAN_STA_CONNECT: + /* STA already 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_ctx)) && + (!hdd_ipa->sta_connected)) + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 1); + + cdf_mutex_acquire(&hdd_ipa->event_lock); + + if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(CDF_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) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "handle 1st con ret %d", ret); + } else { + cdf_mutex_release(&hdd_ipa->event_lock); + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); + goto end; + } + } + ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id); + if (ret) { + cdf_mutex_release(&hdd_ipa->event_lock); + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); + goto end; + +#ifdef IPA_UC_OFFLOAD + vdev_to_iface[adapter->sessionId] = + ((struct hdd_ipa_iface_context *) + (adapter->ipa_context))->iface_id; +#endif /* IPA_UC_OFFLOAD */ + } + + cdf_mutex_release(&hdd_ipa->event_lock); + + hdd_ipa->sta_connected = 1; + 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; + + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_AP_RX_DATA_OFFLOAD, 1); + } + cdf_mutex_acquire(&hdd_ipa->event_lock); + ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id); + if (ret) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Evt: %d, Interface setup failed", + msg_ex->name, meta.msg_type); + cdf_mutex_release(&hdd_ipa->event_lock); + goto end; + +#ifdef IPA_UC_OFFLOAD + vdev_to_iface[adapter->sessionId] = + ((struct hdd_ipa_iface_context *) + (adapter->ipa_context))->iface_id; +#endif /* IPA_UC_OFFLOAD */ + } + cdf_mutex_release(&hdd_ipa->event_lock); + break; + + case WLAN_STA_DISCONNECT: + cdf_mutex_acquire(&hdd_ipa->event_lock); + hdd_ipa_cleanup_iface(adapter->ipa_context); + + if (!hdd_ipa->sta_connected) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Evt: %d, STA already disconnected", + msg_ex->name, meta.msg_type); + cdf_mutex_release(&hdd_ipa->event_lock); + return -EINVAL; + } + hdd_ipa->sta_connected = 0; + if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(CDF_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_ctx)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_STA_RX_DATA_OFFLOAD, 0); + vdev_to_iface[adapter->sessionId] = HDD_IPA_MAX_IFACE; + } + + cdf_mutex_release(&hdd_ipa->event_lock); + break; + + case WLAN_AP_DISCONNECT: + if (!adapter->ipa_context) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Evt: %d, SAP already disconnected", + msg_ex->name, meta.msg_type); + return -EINVAL; + } + + cdf_mutex_acquire(&hdd_ipa->event_lock); + hdd_ipa_cleanup_iface(adapter->ipa_context); + 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 unloading WLAN driver is in + * progress + */ + hdd_ipa_uc_disable_pipes(hdd_ipa); + } else { + HDD_IPA_LOG(CDF_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_ctx)) { + hdd_ipa_uc_offload_enable_disable(adapter, + SIR_AP_RX_DATA_OFFLOAD, 0); + vdev_to_iface[adapter->sessionId] = HDD_IPA_MAX_IFACE; + } + cdf_mutex_release(&hdd_ipa->event_lock); + break; + + case WLAN_CLIENT_CONNECT_EX: + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%d %d", + adapter->dev->ifindex, sta_id); + + if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED", + adapter->dev->name, meta.msg_type); + return 0; + } + + cdf_mutex_acquire(&hdd_ipa->event_lock); + if (hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, + true, sta_id)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: STA ID %d found, not valid", + adapter->dev->name, sta_id); + cdf_mutex_release(&hdd_ipa->event_lock); + return 0; + } + hdd_ipa->sap_num_connected_sta++; + hdd_ipa->pending_cons_req = false; + cdf_mutex_release(&hdd_ipa->event_lock); + + meta.msg_type = type; + meta.msg_len = (sizeof(struct ipa_wlan_msg_ex) + + sizeof(struct ipa_wlan_hdr_attrib_val)); + msg_ex = cdf_mem_malloc(meta.msg_len); + + if (msg_ex == NULL) { + HDD_IPA_LOG(CDF_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; + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + msg_ex->attribs[0].offset = + HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET; + } else { + 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(CDF_TRACE_LEVEL_INFO, "%s: Evt: %d : %d", + msg_ex->name, meta.msg_type, ret); + cdf_mem_free(msg_ex); + return ret; + } + hdd_ipa->stats.num_send_msg++; + + cdf_mutex_acquire(&hdd_ipa->event_lock); + /* Enable IPA UC Data PIPEs when first STA connected */ + if ((1 == hdd_ipa->sap_num_connected_sta) + && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) + || !hdd_ipa->sta_connected)) { + ret = hdd_ipa_uc_handle_first_con(hdd_ipa); + if (ret) { + cdf_mutex_release(&hdd_ipa->event_lock); + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: handle 1st con ret %d", + adapter->dev->name, ret); + return ret; + } + } + cdf_mutex_release(&hdd_ipa->event_lock); + + return ret; + + case WLAN_CLIENT_DISCONNECT: + if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA UC OFFLOAD NOT ENABLED", + msg_ex->name); + return 0; + } + + cdf_mutex_acquire(&hdd_ipa->event_lock); + if (!hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, false, sta_id)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: STA ID %d NOT found, not valid", + msg_ex->name, sta_id); + cdf_mutex_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 + && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) || + !hdd_ipa->sta_connected) + && (false == hdd_ipa->resource_unloading) + && (HDD_IPA_UC_NUM_WDI_PIPE == + hdd_ipa->activated_fw_pipe)) + hdd_ipa_uc_handle_last_discon(hdd_ipa); + cdf_mutex_release(&hdd_ipa->event_lock); + break; + + default: + return 0; + } + + meta.msg_len = sizeof(struct ipa_wlan_msg); + msg = cdf_mem_malloc(meta.msg_len); + if (msg == NULL) { + HDD_IPA_LOG(CDF_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(CDF_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(CDF_TRACE_LEVEL_INFO, "%s: Evt: %d fail:%d", + msg->name, meta.msg_type, ret); + cdf_mem_free(msg); + return ret; + } + + hdd_ipa->stats.num_send_msg++; + +end: + return ret; +} + +/** + * hdd_ipa_rm_state_to_str() - Convert IPA RM state to string + * @state: IPA RM state value + * + * Return: ASCII string representing the IPA RM state + */ +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"; +} + +/** + * hdd_ipa_init() - IPA initialization function + * @hdd_ctx: HDD global context + * + * Allocate hdd_ipa resources, ipa pipe resource and register + * wlan interface with IPA module. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa = NULL; + int ret, i; + struct hdd_ipa_iface_context *iface_context = NULL; + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return CDF_STATUS_SUCCESS; + + hdd_ipa = cdf_mem_malloc(sizeof(*hdd_ipa)); + if (!hdd_ipa) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed"); + goto fail_setup_rm; + } + + 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; + cdf_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 + cdf_spinlock_init(&hdd_ipa->pm_lock); + cdf_nbuf_queue_init(&hdd_ipa->pm_queue_head); + + ret = hdd_ipa_setup_rm(hdd_ipa); + if (ret) + goto fail_setup_rm; + + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { + hdd_ipa_uc_rt_debug_init(hdd_ctx); + cdf_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 = false; + hdd_ipa->resource_unloading = false; + hdd_ipa->sta_connected = 0; + + /* Setup IPA sys_pipe for MCC */ + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { + ret = hdd_ipa_setup_sys_pipe(hdd_ipa); + if (ret) + goto fail_create_sys_pipe; + } + hdd_ipa_uc_ol_init(hdd_ctx); + } else { + ret = hdd_ipa_setup_sys_pipe(hdd_ipa); + if (ret) + goto fail_create_sys_pipe; + } + + return CDF_STATUS_SUCCESS; + +fail_create_sys_pipe: + hdd_ipa_destroy_rm_resource(hdd_ipa); +fail_setup_rm: + if (hdd_ipa) + cdf_mem_free(hdd_ipa); + + return CDF_STATUS_E_FAILURE; +} + +/** + * hdd_ipa_cleanup - IPA cleanup function + * @hdd_ctx: HDD global context + * + * Return: CDF_STATUS enumeration + */ +CDF_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; + cdf_nbuf_t skb; + struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; + + if (!hdd_ipa_is_enabled(hdd_ctx)) + return CDF_STATUS_SUCCESS; + + if (!hdd_ipa_uc_is_enabled(hdd_ctx)) { + unregister_inetaddr_notifier(&hdd_ipa->ipv4_notifier); + hdd_ipa_teardown_sys_pipe(hdd_ipa); + } + + /* Teardown IPA sys_pipe for MCC */ + if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) + hdd_ipa_teardown_sys_pipe(hdd_ipa); + + hdd_ipa_destroy_rm_resource(hdd_ipa); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&hdd_ipa->pm_work); +#endif + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + + while (((skb = cdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head)) != NULL)) { + cdf_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); + + cdf_spin_lock_bh(&hdd_ipa->pm_lock); + } + cdf_spin_unlock_bh(&hdd_ipa->pm_lock); + + cdf_spinlock_destroy(&hdd_ipa->pm_lock); + + /* destory the interface lock */ + for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { + iface_context = &hdd_ipa->iface_context[i]; + cdf_spinlock_destroy(&iface_context->interface_lock); + } + + /* 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(CDF_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(CDF_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); + } + if (hdd_ipa_uc_is_enabled(hdd_ctx)) { + hdd_ipa_uc_rt_debug_deinit(hdd_ctx); + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Disconnect TX PIPE", __func__); + ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle); + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: Disconnect RX PIPE", __func__); + ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle); + cdf_mutex_destroy(&hdd_ipa->event_lock); + cdf_list_destroy(&hdd_ipa->pending_event); + +#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 + } + + cdf_mem_free(hdd_ipa); + hdd_ctx->hdd_ipa = NULL; + + return CDF_STATUS_SUCCESS; +} +#endif /* IPA_OFFLOAD */ diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c new file mode 100644 index 000000000000..14b9be616658 --- /dev/null +++ b/core/hdd/src/wlan_hdd_lro.c @@ -0,0 +1,663 @@ +/* + * 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_lro.c + * + * WLAN HDD LRO interface implementation + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define LRO_MAX_AGGR_SIZE 100 + +#define LRO_VALID_FIELDS \ + (LRO_DESC | LRO_ELIGIBILITY_CHECKED | LRO_TCP_ACK_NUM | \ + LRO_TCP_DATA_CSUM | LRO_TCP_SEQ_NUM | LRO_TCP_WIN) + +/** + * hdd_lro_get_skb_header() - LRO callback function + * @skb: network buffer + * @ip_hdr: contains a pointer to the IP header + * @tcpudp_hdr: contains a pointer to the TCP header + * @hdr_flags: indicates if this is a TCP, IPV4 frame + * @priv: private driver specific opaque pointer + * + * Get the IP and TCP headers from the skb + * + * Return: 0 - success, < 0 - failure + */ +static int hdd_lro_get_skb_header(struct sk_buff *skb, void **ip_hdr, + void **tcpudp_hdr, u64 *hdr_flags, void *priv) +{ + if (NBUF_IPV6_PROTO(skb)) { + hdr_flags = 0; + return -EINVAL; + } + + *hdr_flags |= (LRO_IPV4 | LRO_TCP); + (*ip_hdr) = skb->data; + (*tcpudp_hdr) = skb->data + NBUF_TCP_OFFSET(skb); + return 0; +} + +/** + * hdd_lro_desc_pool_init() - Initialize the free pool of LRO + * descriptors + * @lro_desc_pool: free pool of the LRO descriptors + * @lro_mgr: LRO manager + * + * Initialize a list that holds the free LRO descriptors + * + * Return: none + */ +static void hdd_lro_desc_pool_init(struct hdd_lro_desc_pool *lro_desc_pool, + struct net_lro_mgr *lro_mgr) +{ + int i; + + INIT_LIST_HEAD(&lro_desc_pool->lro_free_list_head); + + for (i = 0; i < LRO_DESC_POOL_SZ; i++) { + lro_desc_pool->lro_desc_array[i].lro_desc = + &lro_mgr->lro_arr[i]; + list_add_tail(&lro_desc_pool->lro_desc_array[i].lro_node, + &lro_desc_pool->lro_free_list_head); + } + cdf_spinlock_init(&lro_desc_pool->lro_pool_lock); +} + +/** + * hdd_lro_desc_info_init() - Initialize the LRO descriptors + * @hdd_info: HDD LRO data structure + * + * Initialize the free pool of LRO descriptors and the entries + * of the hash table + * + * Return: none + */ +static void hdd_lro_desc_info_init(struct hdd_lro_s *hdd_info) +{ + int i; + + /* Initialize pool of free LRO desc.*/ + hdd_lro_desc_pool_init(&hdd_info->lro_desc_info.lro_desc_pool, + hdd_info->lro_mgr); + + /* Initialize the hash table of LRO desc.*/ + for (i = 0; i < LRO_DESC_TABLE_SZ; i++) { + /* initialize the flows in the hash table */ + INIT_LIST_HEAD(&hdd_info->lro_desc_info. + lro_hash_table[i].lro_desc_list); + } + + cdf_spinlock_init(&hdd_info->lro_desc_info.lro_hash_lock); +} + +/** + * hdd_lro_desc_pool_deinit() - Free the LRO descriptor list + * @hdd_info: HDD LRO data structure + * + * Free the pool of LRO descriptors + * + * Return: none + */ +static void hdd_lro_desc_pool_deinit(struct hdd_lro_desc_pool *lro_desc_pool) +{ + + if (lro_desc_pool->lro_desc_array) { + cdf_mem_free(lro_desc_pool->lro_desc_array); + lro_desc_pool->lro_desc_array = NULL; + } + + INIT_LIST_HEAD(&lro_desc_pool->lro_free_list_head); + + cdf_spinlock_destroy(&lro_desc_pool->lro_pool_lock); +} + +/** + * hdd_lro_desc_info_deinit() - Deinitialize the LRO descriptors + * + * @hdd_info: HDD LRO data structure + * + * Deinitialize the free pool of LRO descriptors and the entries + * of the hash table + * + * Return: none + */ +static void hdd_lro_desc_info_deinit(struct hdd_lro_s *hdd_info) +{ + int i; + struct hdd_lro_desc_info *desc_info = &hdd_info->lro_desc_info; + + cdf_mem_free(hdd_info->lro_mgr->lro_arr); + hdd_info->lro_mgr->lro_arr = NULL; + hdd_lro_desc_pool_deinit(&desc_info->lro_desc_pool); + /* Free the a list of LRO desc for each entry of the hash table */ + for (i = 0; i < LRO_DESC_TABLE_SZ; i++) + INIT_LIST_HEAD(&desc_info->lro_hash_table[i].lro_desc_list); + + cdf_spinlock_destroy(&desc_info->lro_hash_lock); + cdf_mem_free(desc_info->lro_hash_table); + desc_info->lro_hash_table = NULL; +} + +/** + * hdd_lro_tcp_flow_match() - function to check for a flow match + * @iph: IP header + * @tcph: TCP header + * @lro_desc: LRO decriptor + * + * Checks if the descriptor belongs to the same flow as the one + * indicated by the TCP and IP header. + * + * Return: true - flow match, false - flow does not match + */ +static inline bool hdd_lro_tcp_flow_match(struct net_lro_desc *lro_desc, + struct iphdr *iph, + struct tcphdr *tcph) +{ + if ((lro_desc->tcph->source != tcph->source) || + (lro_desc->tcph->dest != tcph->dest) || + (lro_desc->iph->saddr != iph->saddr) || + (lro_desc->iph->daddr != iph->daddr)) + return false; + + return true; + +} + +/** + * hdd_lro_desc_find() - LRO descriptor look-up function + * + * @adapter: HDD adaptor + * @skb: network buffer + * @iph: IP header + * @tcph: TCP header + * @lro_desc: contains a pointer to the LRO decriptor + * + * Look-up the LRO descriptor in the hash table based on the + * flow ID toeplitz. If the flow is not found, allocates a new + * LRO descriptor and places it in the hash table + * + * Return: 0 - success, < 0 - failure + */ +static int hdd_lro_desc_find(hdd_adapter_t *adapter, + struct sk_buff *skb, struct iphdr *iph, struct tcphdr *tcph, + struct net_lro_desc **lro_desc) +{ + uint32_t i; + struct hdd_lro_desc_table *lro_hash_table; + struct list_head *ptr; + struct hdd_lro_desc_entry *entry; + struct hdd_lro_desc_pool free_pool; + struct hdd_lro_desc_info *desc_info = &adapter->lro_info.lro_desc_info; + + *lro_desc = NULL; + i = NBUF_FLOW_ID_TOEPLITZ(skb) & LRO_DESC_TABLE_SZ_MASK; + + lro_hash_table = &desc_info->lro_hash_table[i]; + + if (!lro_hash_table) { + hdd_err("Invalid hash entry"); + CDF_ASSERT(0); + return -EINVAL; + } + + cdf_spin_lock_bh(&desc_info->lro_hash_lock); + /* Check if this flow exists in the descriptor list */ + list_for_each(ptr, &lro_hash_table->lro_desc_list) { + struct net_lro_desc *tmp_lro_desc = NULL; + entry = list_entry(ptr, struct hdd_lro_desc_entry, lro_node); + tmp_lro_desc = entry->lro_desc; + if (tmp_lro_desc->active) { + if (hdd_lro_tcp_flow_match(tmp_lro_desc, iph, tcph)) { + *lro_desc = entry->lro_desc; + cdf_spin_unlock_bh(&desc_info->lro_hash_lock); + return 0; + } + } + } + cdf_spin_unlock_bh(&desc_info->lro_hash_lock); + + /* no existing flow found, a new LRO desc needs to be allocated */ + free_pool = adapter->lro_info.lro_desc_info.lro_desc_pool; + cdf_spin_lock_bh(&free_pool.lro_pool_lock); + entry = list_first_entry_or_null( + &free_pool.lro_free_list_head, + struct hdd_lro_desc_entry, lro_node); + if (NULL == entry) { + hdd_err("Could not allocate LRO desc!"); + cdf_spin_unlock_bh(&free_pool.lro_pool_lock); + return -ENOMEM; + } + + list_del_init(&entry->lro_node); + cdf_spin_unlock_bh(&free_pool.lro_pool_lock); + + if (NULL == entry->lro_desc) { + hdd_err("entry->lro_desc is NULL!\n"); + return -EINVAL; + } + + cdf_mem_zero((void *)entry->lro_desc, sizeof(struct net_lro_desc)); + + /* + * lro_desc->active should be 0 and lro_desc->tcp_rcv_tsval + * should be 0 for newly allocated lro descriptors + */ + cdf_spin_lock_bh(&desc_info->lro_hash_lock); + list_add_tail(&entry->lro_node, + &lro_hash_table->lro_desc_list); + cdf_spin_unlock_bh(&desc_info->lro_hash_lock); + *lro_desc = entry->lro_desc; + + return 0; +} + +/** + * hdd_lro_get_desc() - LRO descriptor look-up function + * @iph: IP header + * @tcph: TCP header + * @lro_arr: Array of LRO decriptors + * @lro_mgr: LRO manager + * + * Looks-up the LRO descriptor for a given flow + * + * Return: LRO descriptor + */ +static struct net_lro_desc *hdd_lro_get_desc(struct net_lro_mgr *lro_mgr, + struct net_lro_desc *lro_arr, + struct iphdr *iph, + struct tcphdr *tcph) +{ + int i; + + for (i = 0; i < lro_mgr->max_desc; i++) { + if (lro_arr[i].active) + if (hdd_lro_tcp_flow_match(&lro_arr[i], iph, tcph)) + return &lro_arr[i]; + } + + return NULL; +} + +/** + * hdd_lro_eligible() - LRO eligibilty check + * @iph: IP header + * @tcph: TCP header + * @adapter: HDD adaptor + * @desc: LRO descriptor + * @skb: network buffer + * + * Determines if the frame is LRO eligible + * + * Return: true - LRO eligible frame, false - frame is not LRO + * eligible + */ +static bool hdd_lro_eligible(hdd_adapter_t *adapter, struct sk_buff *skb, + struct iphdr *iph, struct tcphdr *tcph, struct net_lro_desc **desc) +{ + struct net_lro_desc *lro_desc = NULL; + int hw_lro_eligible = + NBUF_LRO_ELIGIBLE(skb) && (!NBUF_TCP_PURE_ACK(skb)); + + if (!hw_lro_eligible) + return false; + + if (0 != hdd_lro_desc_find(adapter, skb, iph, tcph, desc)) { + hdd_err("finding the LRO desc failed"); + return false; + } + + lro_desc = *desc; + if (!lro_desc) + return false; + + /* if this is not the first skb, check the timestamp option */ + if (lro_desc->tcp_rcv_tsval) { + if (tcph->doff == 8) { + __be32 *topt = (__be32 *)(tcph + 1); + + if (*topt != htonl((TCPOPT_NOP << 24) + |(TCPOPT_NOP << 16) + | (TCPOPT_TIMESTAMP << 8) + | TCPOLEN_TIMESTAMP)) + return true; + + /* timestamp should be in right order */ + topt++; + if (after(ntohl(lro_desc->tcp_rcv_tsval), + ntohl(*topt))) + return false; + + /* timestamp reply should not be zero */ + topt++; + if (*topt == 0) + return false; + } + } + + return true; +} + +/** + * hdd_lro_desc_free() - Free the LRO descriptor + * @adapter: HDD adaptor + * @desc: LRO descriptor + * + * Return the LRO descriptor to the free pool + * + * Return: none + */ +static void hdd_lro_desc_free(struct net_lro_desc *desc, + hdd_adapter_t *adapter) +{ + struct hdd_lro_desc_entry *entry; + struct net_lro_desc *arr_base = adapter->lro_info.lro_mgr->lro_arr; + struct hdd_lro_desc_info *desc_info = &adapter->lro_info.lro_desc_info; + int i = desc - arr_base; + + if (i >= LRO_DESC_POOL_SZ) { + hdd_err("invalid index %d", i); + return; + } + + entry = &desc_info->lro_desc_pool.lro_desc_array[i]; + + cdf_spin_lock_bh(&desc_info->lro_hash_lock); + list_del_init(&entry->lro_node); + cdf_spin_unlock_bh(&desc_info->lro_hash_lock); + + cdf_spin_lock_bh(&desc_info->lro_desc_pool.lro_pool_lock); + list_add_tail(&entry->lro_node, &desc_info-> + lro_desc_pool.lro_free_list_head); + cdf_spin_unlock_bh(&desc_info->lro_desc_pool.lro_pool_lock); +} + +/** + * hdd_lro_flush_pkt() - function to flush the LRO flow + * @iph: IP header + * @tcph: TCP header + * @adapter: HDD adaptor + * @lro_mgr: LRO manager + * + * Flush all the packets aggregated in the LRO manager for the + * flow indicated by the TCP and IP header + * + * Return: none + */ +void hdd_lro_flush_pkt(struct net_lro_mgr *lro_mgr, + struct iphdr *iph, struct tcphdr *tcph, hdd_adapter_t *adapter) +{ + struct net_lro_desc *lro_desc; + + lro_desc = hdd_lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph); + + if (!lro_desc) + return; + + hdd_lro_desc_free(lro_desc, adapter); + lro_flush_desc(lro_mgr, lro_desc); +} + +/** + * hdd_lro_flush() - LRO flush callback + * @data: opaque pointer containing HDD specific information + * + * Callback registered to flush all the packets aggregated in + * the LRO manager for all the flows + * + * Return: none + */ +void hdd_lro_flush(void *data) +{ + hdd_adapter_t *adapter = (hdd_adapter_t *)data; + int i; + + for (i = 0; i < adapter->lro_info.lro_mgr->max_desc; i++) { + if (adapter->lro_info.lro_mgr->lro_arr[i].active) { + hdd_lro_desc_free( + &adapter->lro_info.lro_mgr->lro_arr[i], + (void *)adapter); + lro_flush_desc(adapter->lro_info.lro_mgr, + &adapter->lro_info.lro_mgr->lro_arr[i]); + } + } +} + +/** + * hdd_lro_init() - initialization for LRO + * @hdd_ctx: HDD context + * + * This function sends the LRO configuration to the firmware + * via WMA + * + * Return: 0 - success, < 0 - failure + */ +int hdd_lro_init(hdd_context_t *hdd_ctx) +{ + struct wma_lro_config_cmd_t lro_config; + + if (!hdd_ctx->config->lro_enable) { + hdd_err(FL("LRO Disabled")); + return 0; + } + + lro_config.lro_enable = 1; + lro_config.tcp_flag = TCPHDR_ACK; + lro_config.tcp_flag_mask = TCPHDR_FIN | TCPHDR_SYN | TCPHDR_RST | + TCPHDR_ACK | TCPHDR_URG | TCPHDR_ECE | TCPHDR_CWR; + + get_random_bytes(lro_config.toeplitz_hash_ipv4, + (sizeof(lro_config.toeplitz_hash_ipv4[0]) * + LRO_IPV4_SEED_ARR_SZ)); + + get_random_bytes(lro_config.toeplitz_hash_ipv6, + (sizeof(lro_config.toeplitz_hash_ipv6[0]) * + LRO_IPV6_SEED_ARR_SZ)); + + hdd_debug("sending the LRO configuration to the fw"); + if (0 != wma_lro_init(&lro_config)) { + hdd_err("Failed to send LRO configuration!"); + hdd_ctx->config->lro_enable = 0; + return -EAGAIN; + } + + return 0; +} + +/** + * hdd_lro_enable() - enable LRO + * @hdd_ctx: HDD context + * @adapter: HDD adapter + * + * This function enables LRO in the network device attached to + * the HDD adapter. It also allocates the HDD LRO instance for + * that network device + * + * Return: 0 - success, < 0 - failure + */ +int hdd_lro_enable(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + struct hdd_lro_s *hdd_lro; + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + size_t lro_mgr_sz, desc_arr_sz, desc_pool_sz, hash_table_sz; + uint8_t *lro_mem_ptr; + + if (!hdd_ctx->config->lro_enable || + NL80211_IFTYPE_STATION != adapter->wdev.iftype) { + hdd_info("LRO Disabled"); + return 0; + } + + hdd_info("LRO Enabled"); + + hdd_lro = &adapter->lro_info; + cdf_mem_zero((void *)hdd_lro, sizeof(struct hdd_lro_s)); + /* + * Allocate all the LRO data structures at once and then carve + * them up as needed + */ + lro_mgr_sz = sizeof(struct net_lro_mgr); + desc_arr_sz = (LRO_DESC_POOL_SZ * sizeof(struct net_lro_desc)); + desc_pool_sz = (LRO_DESC_POOL_SZ * sizeof(struct hdd_lro_desc_entry)); + hash_table_sz = (sizeof(struct hdd_lro_desc_table) * LRO_DESC_TABLE_SZ); + + lro_mem_ptr = cdf_mem_malloc(lro_mgr_sz + desc_arr_sz + desc_pool_sz + + hash_table_sz); + + if (NULL == lro_mem_ptr) { + hdd_err("Unable to allocate memory for LRO"); + hdd_ctx->config->lro_enable = 0; + return -ENOMEM; + } + + /* LRO manager */ + hdd_lro->lro_mgr = (struct net_lro_mgr *)lro_mem_ptr; + lro_mem_ptr += lro_mgr_sz; + + /* LRO decriptor array */ + hdd_lro->lro_mgr->lro_arr = (struct net_lro_desc *)lro_mem_ptr; + lro_mem_ptr += desc_arr_sz; + + /* LRO descriptor pool */ + hdd_lro->lro_desc_info.lro_desc_pool.lro_desc_array = + (struct hdd_lro_desc_entry *)lro_mem_ptr; + lro_mem_ptr += desc_pool_sz; + + /* hash table to store the LRO descriptors */ + hdd_lro->lro_desc_info.lro_hash_table = + (struct hdd_lro_desc_table *)lro_mem_ptr; + + /* Initialize the LRO descriptors */ + hdd_lro_desc_info_init(hdd_lro); + + hdd_lro->lro_mgr->dev = adapter->dev; + if (ol_cfg_is_rx_thread_enabled(pdev->ctrl_pdev)) + hdd_lro->lro_mgr->features = LRO_F_NI; + + if (hdd_napi_enabled(HDD_NAPI_ANY)) + hdd_lro->lro_mgr->features |= LRO_F_NAPI; + + hdd_lro->lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; + hdd_lro->lro_mgr->max_aggr = LRO_MAX_AGGR_SIZE; + hdd_lro->lro_mgr->get_skb_header = hdd_lro_get_skb_header; + hdd_lro->lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; + hdd_lro->lro_mgr->max_desc = LRO_DESC_POOL_SZ; + + adapter->dev->features |= NETIF_F_LRO; + + /* Register the flush callback */ + ol_register_lro_flush_cb(hdd_lro_flush, adapter); + + return 0; +} + +/** + * hdd_lro_disable() - disable LRO + * @hdd_ctx: HDD context + * @adapter: HDD adapter + * + * This function frees the HDD LRO instance for the network + * device attached to the HDD adapter + * + * Return: none + */ +void hdd_lro_disable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) +{ + if (!hdd_ctx->config->lro_enable || + NL80211_IFTYPE_STATION != adapter->wdev.iftype) + return; + + hdd_lro_desc_info_deinit(&adapter->lro_info); + cdf_mem_free(adapter->lro_info.lro_mgr); + adapter->lro_info.lro_mgr = NULL; + return; +} + +/** + * hdd_lro_rx() - LRO receive function + * @hdd_ctx: HDD context + * @adapter: HDD adapter + * @skb: network buffer + * + * Delivers LRO eligible frames to the LRO manager + * + * Return: HDD_LRO_RX - frame delivered to LRO manager + * HDD_LRO_NO_RX - frame not delivered + */ +enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, struct sk_buff *skb) +{ + enum hdd_lro_rx_status status = HDD_LRO_NO_RX; + + if ((adapter->dev->features & NETIF_F_LRO) && + NBUF_TCP_PROTO(skb)) { + struct iphdr *iph; + struct tcphdr *tcph; + struct net_lro_desc *lro_desc = NULL; + iph = (struct iphdr *)skb->data; + tcph = (struct tcphdr *)(skb->data + NBUF_TCP_OFFSET(skb)); + if (hdd_lro_eligible(adapter, skb, iph, tcph, &lro_desc)) { + struct net_lro_info hdd_lro_info; + + hdd_lro_info.valid_fields = LRO_VALID_FIELDS; + + hdd_lro_info.lro_desc = lro_desc; + hdd_lro_info.lro_eligible = 1; + hdd_lro_info.tcp_ack_num = NBUF_TCP_ACK_NUM(skb); + hdd_lro_info.tcp_data_csum = + csum_unfold(htons(NBUF_TCP_CHKSUM(skb))); + hdd_lro_info.tcp_seq_num = NBUF_TCP_SEQ_NUM(skb); + hdd_lro_info.tcp_win = NBUF_TCP_WIN(skb); + + lro_receive_skb_ext(adapter->lro_info.lro_mgr, skb, + (void *)adapter, &hdd_lro_info); + + if (!hdd_lro_info.lro_desc->active) + hdd_lro_desc_free(lro_desc, adapter); + + status = HDD_LRO_RX; + } else { + hdd_lro_flush_pkt(adapter->lro_info.lro_mgr, + iph, tcph, adapter); + } + } + return status; +} diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c new file mode 100644 index 000000000000..64a72991cde3 --- /dev/null +++ b/core/hdd/src/wlan_hdd_main.c @@ -0,0 +1,6731 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_main.c + * + * WLAN Host Device Driver implementation + * + */ + +/* Include Files */ +#include +#include +#include +#ifdef WLAN_FEATURE_LPSS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlan_hdd_trace.h" +#include "wlan_hdd_ioctl.h" +#include "wlan_hdd_ftm.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_stats.h" +#include "cdf_types.h" +#include "cdf_trace.h" + +#include +#include +#include +#include +#include +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_ext_scan.h" +#include "wlan_hdd_p2p.h" +#include +#include "sap_api.h" +#include +#include +#include +#ifdef MSM_PLATFORM +#ifdef CONFIG_CNSS +#include +#endif +#endif +#include +#include +#include "cfg_api.h" +#include "qwlan_version.h" +#include "wma_types.h" +#include "wlan_hdd_tdls.h" +#ifdef FEATURE_WLAN_CH_AVOID +#ifdef CONFIG_CNSS +#include +#endif + +#include "wlan_hdd_ocb.h" + +extern int hdd_hostapd_stop(struct net_device *dev); +#endif /* FEATURE_WLAN_CH_AVOID */ + +#include "wlan_hdd_nan.h" +#include "wlan_hdd_debugfs.h" +#include "wlan_hdd_driver_ops.h" +#include "epping_main.h" +#include "wlan_hdd_memdump.h" + +#include +#include "hif.h" +#include "wma.h" +#include "cds_concurrency.h" +#include "wlan_hdd_green_ap.h" + +#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 200 +/* 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); + +static cdf_wake_lock_t wlan_wake_lock; +/* set when SSR is needed after unload */ +static e_hdd_ssr_required is_ssr_required = 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)) +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 declaration */ + +struct sock *cesium_nl_srv_sock; + +struct completion wlan_start_comp; +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +void wlan_hdd_auto_shutdown_cb(void); +#endif + +/** + * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer + * @vdev_id: vdev_id + * @action: action type + * @reason: reason type + * + * Return: none + */ +void wlan_hdd_txrx_pause_cb(uint8_t vdev_id, + enum netif_action_type action, enum netif_reason_type reason) +{ + hdd_context_t *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + hdd_adapter_t *adapter; + + if (!hdd_ctx) { + hdd_err("hdd ctx is NULL"); + return; + } + adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id); + + wlan_hdd_netif_queue_control(adapter, action, reason); + return; +} + +/* + * 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 + */ +uint8_t 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_FTM); + CASE_RETURN_STRING(WLAN_HDD_IBSS); + CASE_RETURN_STRING(WLAN_HDD_P2P_DEVICE); + CASE_RETURN_STRING(WLAN_HDD_OCB); + default: + return "Unknown"; + } +} + +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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + + /* Make sure that this callback corresponds to our device. */ + if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3))) + return NOTIFY_DONE; + + if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) && + (adapter->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; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (NULL == hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer")); + CDF_ASSERT(0); + return NOTIFY_DONE; + } + if (hdd_ctx->isLogpInProgress) + return NOTIFY_DONE; + + hddLog(CDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"), + dev->name, state); + + switch (state) { + case NETDEV_REGISTER: + break; + + case NETDEV_UNREGISTER: + break; + + case NETDEV_UP: + sme_ch_avoid_update_req(hdd_ctx->hHal); + break; + + case NETDEV_DOWN: + break; + + case NETDEV_CHANGE: + if (true == adapter->isLinkUpSvcNeeded) + complete(&adapter->linkup_event_var); + break; + + case NETDEV_GOING_DOWN: + if (adapter->scan_info.mScanPending != false) { + unsigned long rc; + INIT_COMPLETION(adapter->scan_info. + abortscan_event_var); + hdd_abort_mac_scan(adapter->pHddCtx, + adapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + rc = wait_for_completion_timeout( + &adapter->scan_info.abortscan_event_var, + msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN)); + if (!rc) { + hddLog(LOGE, + FL("Timeout occurred while waiting for abortscan")); + } + } else { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("Scan is not Pending from user")); + } + 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; + + cds_ssr_protect(__func__); + ret = __hdd_netdev_notifier_call(nb, state, ndev); + cds_ssr_unprotect(__func__); + + return ret; +} + +struct notifier_block hdd_netdev_notifier = { + .notifier_call = hdd_netdev_notifier_call, +}; + +/* 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 userspace 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 userspace. 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 + +/** + * hdd_cdf_trace_enable() - configure initial CDF Trace enable + * @moduleId: Module whose trace level is being configured + * @bitmask: Bitmask of log levels to be enabled + * + * Called immediately after the cfg.ini is read in order to configure + * the desired trace levels. + * + * Return: None + */ +static void hdd_cdf_trace_enable(CDF_MODULE_ID moduleId, uint32_t bitmask) +{ + CDF_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_CDF_TRACE_ENABLE_DEFAULT == bitmask) { + return; + } + + /* a mask was specified. start by disabling all logging */ + cdf_trace_set_value(moduleId, CDF_TRACE_LEVEL_NONE, 0); + + /* now cycle through the bitmask until all "set" bits are serviced */ + level = CDF_TRACE_LEVEL_FATAL; + while (0 != bitmask) { + if (bitmask & 1) { + cdf_trace_set_value(moduleId, level, 1); + } + level++; + bitmask >>= 1; + } +} + +/** + * wlan_hdd_validate_context() - check the HDD context + * @hdd_ctx: HDD context pointer + * + * Return: 0 if the context is valid. Error code otherwise + */ +int wlan_hdd_validate_context(hdd_context_t *hdd_ctx) +{ + ENTER(); + + if (NULL == hdd_ctx || NULL == hdd_ctx->config) { + hddLog(LOGE, FL("HDD context is Null")); + return -ENODEV; + } + + if (hdd_ctx->isLogpInProgress) { + hddLog(LOGE, FL("LOGP in Progress. Ignore!!!")); + return -EAGAIN; + } + + if ((hdd_ctx->isLoadInProgress) || (hdd_ctx->isUnloadInProgress)) { + hddLog(LOGE, FL("Unloading/Loading in Progress. Ignore!!!")); + return -EAGAIN; + } + return 0; +} + +void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx) +{ + hdd_adapter_t *adapter = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + eCsrPhyMode phyMode; + struct hdd_config *cfg_param = NULL; + + if (NULL == hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!")); + return; + } + + adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION); + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("adapter is null !!")); + return; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + cfg_param = hdd_ctx->config; + if (NULL == cfg_param) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("cfg_params not available !!")); + return; + } + + phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter)); + + if (!hdd_ctx->isVHT80Allowed) { + if ((eCSR_DOT11_MODE_AUTO == phyMode) || + (eCSR_DOT11_MODE_11ac == phyMode) || + (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("Setting phymode to 11n!!")); + sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter), + eCSR_DOT11_MODE_11n); + } + } else { + /* + * New country Supports 11ac as well resetting value back from + * .ini + */ + sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter), + 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))) { + CDF_STATUS cdf_status; + + /* need to issue a disconnect to CSR. */ + INIT_COMPLETION(adapter->disconnect_comp_var); + cdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + + if (CDF_STATUS_SUCCESS == cdf_status) { + unsigned long rc; + + rc = wait_for_completion_timeout( + &adapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(LOGE, + FL("failure waiting for disconnect_comp_var")); + } + } +} + +/** + * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA. + * @hdd_adapter_t Hdd adapter. + * + * 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. + * + * Return: CDF_STATUS CDF_STATUS_SUCCESS on Success and CDF_STATUS_E_FAILURE + * on failure. + */ +CDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter) +{ + int ret; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (hdd_ctx == NULL) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD context is null")); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE, + hdd_ctx->config->ibssATIMWinSize, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED, + hdd_ctx->config->isIbssPowerSaveAllowed, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"), + ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED, + hdd_ctx->config-> + isIbssPowerCollapseAllowed, VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"), + ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX, + hdd_ctx->config->isIbssAwakeOnTxRx, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_INACTIVITY_TIME, + hdd_ctx->config->ibssInactivityCount, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME, + hdd_ctx->config->ibssTxSpEndInactivityTime, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d" + ), + ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS, + hdd_ctx->config->ibssPsWarmupTime, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"), + ret); + return CDF_STATUS_E_FAILURE; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW, + hdd_ctx->config->ibssPs1RxChainInAtimEnable, + VDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d" + ), + ret); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +#if defined(WLAN_FEATURE_VOWIFI_11R) ||\ + defined(FEATURE_WLAN_ESE) ||\ + defined(FEATURE_WLAN_LFR) + +#define INTF_MACADDR_MASK 0x7 + +/** + * hdd_update_macaddr() - update mac address + * @config: hdd configuration + * @hw_macaddr: mac address + * + * 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 + * admistered 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. + * + * Return: None + */ +void hdd_update_macaddr(struct hdd_config *config, + struct cdf_mac_addr hw_macaddr) +{ + int8_t i; + uint8_t macaddr_b3, tmp_br3; + + cdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes, + CDF_MAC_ADDR_SIZE); + for (i = 1; i < CDF_MAX_CONCURRENCY_PERSONA; i++) { + cdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes, + CDF_MAC_ADDR_SIZE); + macaddr_b3 = config->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 */ + config->intfMacAddr[i].bytes[0] |= 0x02; + config->intfMacAddr[i].bytes[3] = macaddr_b3; + hddLog(CDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: " + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes)); + } +} + +static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, + struct wma_tgt_services *cfg) +{ + struct hdd_config *config = hdd_ctx->config; + tpAniSirGlobal pMac = PMAC_STRUCT(hdd_ctx->hHal); + + /* Set up UAPSD */ + config->apUapsdEnabled &= cfg->uapsd; + +#ifdef WLAN_FEATURE_11AC + /* 11AC mode support */ + if ((config->dot11Mode == eHDD_DOT11_MODE_11ac || + config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac) + config->dot11Mode = eHDD_DOT11_MODE_AUTO; +#endif /* #ifdef WLAN_FEATURE_11AC */ + + /* ARP offload: override user setting if invalid */ + config->fhostArpOffload &= cfg->arp_offload; + +#ifdef FEATURE_WLAN_SCAN_PNO + /* PNO offload */ + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("PNO Capability in f/w = %d"), cfg->pno_offload); + if (cfg->pno_offload) + config->PnoOffload = true; +#endif + pMac->lteCoexAntShare = cfg->lte_coex_ant_share; +#ifdef FEATURE_WLAN_TDLS + config->fEnableTDLSSupport &= cfg->en_tdls; + config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan; + config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta; + if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) { + config->fEnableTDLSSleepSta = true; + } else { + config->fEnableTDLSSleepSta = false; + } +#endif + pMac->beacon_offload = cfg->beacon_offload; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + config->isRoamOffloadEnabled &= cfg->en_roam_offload; +#endif + +} + +static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx, + struct wma_tgt_ht_cap *cfg) +{ + CDF_STATUS status; + uint32_t value, val32; + uint16_t val16; + struct hdd_config *pconfig = hdd_ctx->config; + tSirMacHTCapabilityInfo *phtCapInfo; + uint8_t 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 = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get MPDU DENSITY")); + value = 0; + } + + /* + * MPDU density: + * override user's setting if value is larger + * than the one supported by target + */ + if (value > cfg->mpdu_density) { + status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, + cfg->mpdu_density); + + if (status == CDF_STATUS_E_FAILURE) + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set MPDU DENSITY to CCM")); + } + + /* get the HT capability info */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get HT capability info")); + return; + } + val16 = (uint16_t) 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 && (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 (sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1) + == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL( + "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM" + )); + } + + /* Update Tx Highest Long GI data Rate */ + if (sme_cfg_set_int + (hdd_ctx->hHal, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) == + CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL( + "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 = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32); + if (status != CDF_STATUS_SUCCESS) + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set HT capability to CCM")); +#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff + value = SIZE_OF_SUPPORTED_MCS_SET; + if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set, + &value) == CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("Read MCS rate set")); + + if (pconfig->enable2x2) { + for (value = 0; value < cfg->num_rf_chains; value++) + mcs_set[value] = + WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES; + + status = + sme_cfg_set_str(hdd_ctx->hHal, + WNI_CFG_SUPPORTED_MCS_SET, + mcs_set, + SIZE_OF_SUPPORTED_MCS_SET); + if (status == CDF_STATUS_E_FAILURE) + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set MCS SET to CCM")); + } + } +#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 wma_tgt_vht_cap *cfg) +{ + CDF_STATUS status; + uint32_t value = 0; + struct hdd_config *pconfig = hdd_ctx->config; + struct wiphy *wiphy = hdd_ctx->wiphy; + struct ieee80211_supported_band *band_5g = + wiphy->bands[IEEE80211_BAND_5GHZ]; + + /* Get the current MPDU length */ + status = + sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH")); + 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 = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_MAX_MPDU_LENGTH, + cfg->vht_max_mpdu); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set VHT MAX MPDU LENGTH")); + } + } + + /* Get the current supported chan width */ + status = sme_cfg_get_int(hdd_ctx->hHal, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get MPDU LENGTH")); + value = 0; + } + + /* Get the current RX LDPC setting */ + status = + sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT LDPC CODING CAP")); + value = 0; + } + + /* Set the LDPC capability */ + if (value && !cfg->vht_rx_ldpc) { + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_LDPC_CODING_CAP, + cfg->vht_rx_ldpc); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set VHT LDPC CODING CAP to CCM")); + } + } + + /* Get current GI 80 value */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get SHORT GI 80MHZ")); + value = 0; + } + + /* set the Guard interval 80MHz */ + if (value && !cfg->vht_short_gi_80) { + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_SHORT_GI_80MHZ, + cfg->vht_short_gi_80); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set SHORT GI 80MHZ to CCM")); + } + } + + /* Get current GI 160 value */ + status = sme_cfg_get_int(hdd_ctx->hHal, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get SHORT GI 80 & 160")); + value = 0; + } + + /* Get VHT TX STBC cap */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT TX STBC")); + value = 0; + } + + /* VHT TX STBC cap */ + if (value && !cfg->vht_tx_stbc) { + status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, + cfg->vht_tx_stbc); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set the VHT TX STBC to CCM")); + } + } + + /* Get VHT RX STBC cap */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT RX STBC")); + value = 0; + } + + /* VHT RX STBC cap */ + if (value && !cfg->vht_rx_stbc) { + status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, + cfg->vht_rx_stbc); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set the VHT RX STBC to CCM")); + } + } + + /* Get VHT SU Beamformer cap */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT SU BEAMFORMER CAP")); + value = 0; + } + + /* set VHT SU Beamformer cap */ + if (value && !cfg->vht_su_bformer) { + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, + cfg->vht_su_bformer); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set VHT SU BEAMFORMER CAP")); + } + } + + /* check and update SU BEAMFORMEE capabality */ + if (pconfig->enableTxBF && !cfg->vht_su_bformee) + pconfig->enableTxBF = cfg->vht_su_bformee; + + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + pconfig->enableTxBF); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set VHT SU BEAMFORMEE CAP")); + } + + /* Get VHT MU Beamformer cap */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT MU BEAMFORMER CAP")); + value = 0; + } + + /* set VHT MU Beamformer cap */ + if (value && !cfg->vht_mu_bformer) { + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_MU_BEAMFORMER_CAP, + cfg->vht_mu_bformer); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "could not set the VHT MU BEAMFORMER CAP to CCM" + )); + } + } + + /* Get VHT MU Beamformee cap */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT MU BEAMFORMEE CAP")); + value = 0; + } + + /* set VHT MU Beamformee cap */ + if (value && !cfg->vht_mu_bformee) { + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + cfg->vht_mu_bformee); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set VHT MU BEAMFORMER CAP")); + } + } + + /* Get VHT MAX AMPDU Len exp */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT AMPDU LEN")); + 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 = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + cfg->vht_max_ampdu_len_exp); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set the VHT AMPDU LEN EXP")); + } + } + + /* Get VHT TXOP PS CAP */ + status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("could not get VHT TXOP PS")); + value = 0; + } + + /* set VHT TXOP PS cap */ + if (value && !cfg->vht_txop_ps) { + status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, + cfg->vht_txop_ps); + + if (status == CDF_STATUS_E_FAILURE) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("could not set the VHT TXOP PS")); + } + } + + if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; + else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; + else + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; + + + if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) { + band_5g->vht_cap.cap |= + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + } + if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) { + band_5g->vht_cap.cap |= + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + } + + if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; + + if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; + if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160; + + if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; + + if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; + if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2; + if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3; + + band_5g->vht_cap.cap |= + (cfg->vht_max_ampdu_len_exp << + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); + + if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; + if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; + if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; + if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; + + if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS) + band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS; + +} +#endif /* #ifdef WLAN_FEATURE_11AC */ + +void hdd_update_tgt_cfg(void *context, void *param) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) context; + struct wma_tgt_cfg *cfg = param; + uint8_t temp_band_cap; + + /* first store the INI band capability */ + temp_band_cap = hdd_ctx->config->nBandCapability; + + hdd_ctx->config->nBandCapability = cfg->band_cap; + + /* now overwrite the target band capability with INI + setting if INI setting is a subset */ + + if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) && + (temp_band_cap != eCSR_BAND_ALL)) + hdd_ctx->config->nBandCapability = temp_band_cap; + else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) && + (temp_band_cap != eCSR_BAND_ALL) && + (hdd_ctx->config->nBandCapability != temp_band_cap)) { + hddLog(CDF_TRACE_LEVEL_WARN, + FL("ini BandCapability not supported by the target")); + } + + if (!cds_is_logp_in_progress()) { + 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 (!cdf_is_macaddr_zero(&cfg->hw_macaddr)) { + hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr); + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "Invalid MAC passed from target, using MAC from ini file" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(hdd_ctx->config->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); + + 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_dfs_indicate_radar() - handle radar detection on current SAP channel + * @context: HDD context pointer + * @param: HDD radar indication pointer + * + * This function is invoked when a radar in 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. + * + * Return: None + */ +void hdd_dfs_indicate_radar(void *context, void *param) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) context; + struct wma_dfs_radar_ind *hdd_radar_event = + (struct wma_dfs_radar_ind *)param; + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + hdd_adapter_t *adapter; + CDF_STATUS status; + + if (hdd_ctx == NULL) + return; + + if (hdd_radar_event == NULL) + return; + + if (hdd_ctx->config->disableDFSChSwitch) + return; + + if (true == hdd_radar_event->dfs_radar_status) { + hdd_ctx->dfs_radar_found = true; + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if (WLAN_HDD_SOFTAP == adapter->device_mode || + WLAN_HDD_P2P_GO == adapter->device_mode) { + WLAN_HDD_GET_AP_CTX_PTR(adapter)-> + dfs_cac_block_tx = true; + } + + status = hdd_get_next_adapter(hdd_ctx, + adapterNode, + &pNext); + adapterNode = pNext; + } + } +} +#endif + +/** + * hdd_is_valid_mac_address() - validate MAC address + * @pMacAddr: Pointer to the input 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. + * + * Return: 1 for valid and 0 for invalid + */ +bool hdd_is_valid_mac_address(const uint8_t *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; non-zero for failure + */ +static int __hdd_open(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, + adapter->sessionId, adapter->device_mode)); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); + if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hddLog(LOG1, FL("Enabling Tx Queues")); + /* Enable TX queues only when we are connected */ + wlan_hdd_netif_queue_control(adapter, + WLAN_START_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + } + + return ret; +} + +/** + * hdd_open() - Wrapper function for __hdd_open to protect it from SSR + * @dev: Pointer to net_device structure + * + * This is called in response to ifconfig up + * + * Return: 0 for success; non-zero for failure + */ +int hdd_open(struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __hdd_open(dev); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __hdd_stop() - HDD stop function + * @dev: Pointer to net_device structure + * + * This is called in response to ifconfig down + * + * Return: 0 for success; non-zero for failure + */ +static int __hdd_stop(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; + + ENTER(); + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST, + adapter->sessionId, adapter->device_mode)); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) { + hddLog(LOGE, FL("HDD context is not valid")); + return ret; + } + + /* Nothing to be done if the interface is not opened */ + if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("NETDEV Interface is not OPENED")); + return -ENODEV; + } + + /* Make sure the interface is marked as closed */ + clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); + hddLog(CDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues")); + + /* + * Disable TX on the interface, after this hard_start_xmit() will not + * be called on that interface + */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + /* + * 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(hdd_ctx, adapter, false); + + /* DeInit the adapter. This ensures datapath cleanup as well */ + hdd_deinit_adapter(hdd_ctx, adapter, true); + + 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 + */ +int hdd_stop(struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __hdd_stop(dev); + cds_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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + ENTER(); + + do { + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hddLog(LOGP, FL("Invalid magic")); + break; + } + + if (NULL == adapter->pHddCtx) { + hddLog(LOGP, FL("NULL hdd_ctx")); + break; + } + + if (dev != adapter->dev) { + hddLog(LOGP, FL("Invalid device reference")); + /* + * we haven't validated all cases so let this go for + * now + */ + } + + hdd_deinit_adapter(adapter->pHddCtx, adapter, true); + + /* after uninit our adapter structure will no longer be valid */ + adapter->dev = NULL; + adapter->magic = 0; + } while (0); + + EXIT(); +} + +/** + * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR + * @dev: pointer to net_device structure + * + * This is called during the netdev unregister to uninitialize all data + * associated with the device + * + * Return: none + */ +static void hdd_uninit(struct net_device *dev) +{ + cds_ssr_protect(__func__); + __hdd_uninit(dev); + cds_ssr_unprotect(__func__); +} + +/** + * __hdd_set_mac_address() - set the user specified mac address + * @dev: Pointer to the net device. + * @addr: Pointer to the sockaddr. + * + * This function sets the user specified mac address using + * the command ifconfig wlanX hw ether . + * + * Return: 0 for success, non zero for failure + */ +static int __hdd_set_mac_address(struct net_device *dev, void *addr) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + struct sockaddr *psta_mac_addr = addr; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN); + memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); + + EXIT(); + return cdf_ret_status; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __hdd_set_mac_address(dev, addr); + cds_ssr_unprotect(__func__); + + return ret; +} + +uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx) +{ + int i; + for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) { + if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i))) + break; + } + + if (CDF_MAX_CONCURRENCY_PERSONA == i) + return NULL; + + hdd_ctx->config->intfAddrMask |= (1 << i); + return &hdd_ctx->config->intfMacAddr[i].bytes[0]; +} + +void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr) +{ + int i; + for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) { + if (!memcmp(releaseAddr, + &hdd_ctx->config->intfMacAddr[i].bytes[0], + 6)) { + hdd_ctx->config->intfAddrMask &= ~(1 << i); + break; + } + } + return; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/** + * __hdd_set_multicast_list() - set the multicast address list + * @dev: Pointer to the WLAN device. + * @skb: Pointer to OS packet (sk_buff). + * + * This funciton sets the multicast address list. + * + * Return: None + */ +static void __hdd_set_multicast_list(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + int mc_count; + int i = 0, status; + struct netdev_hw_addr *ha; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + static const uint8_t ipv6_router_solicitation[] + = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hdd_err("hdd_ctx is not valid"); + return; + } + + if (dev->flags & IFF_ALLMULTI) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("allow all multicast frames")); + adapter->mc_addr_list.mc_cnt = 0; + } else { + mc_count = netdev_mc_count(dev); + hddLog(CDF_TRACE_LEVEL_INFO, + FL("mc_count = %u"), mc_count); + if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL( + "No free filter available; allow all multicast frames" + )); + adapter->mc_addr_list.mc_cnt = 0; + return; + } + + adapter->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)) || + (adapter->addr_filter_pattern && (!memcmp(ha->addr, + &adapter->addr_filter_pattern, 1)))) { + hdd_err("MC/BC filtering Skip addr ="MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(ha->addr)); + adapter->mc_addr_list.mc_cnt--; + continue; + } + + memset(&(adapter->mc_addr_list.addr[i][0]), 0, + ETH_ALEN); + memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr, + ETH_ALEN); + hddLog(CDF_TRACE_LEVEL_INFO, + FL("mlist[%d] = " MAC_ADDRESS_STR), i, + MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i])); + i++; + } + } + if (hdd_ctx->config->active_mode_offload) { + hdd_info("enable mc filtering"); + wlan_hdd_set_mc_addr_list(adapter, true); + } else { + hdd_info("skip mc filtering enable it during cfg80211 suspend"); + } + 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) +{ + cds_ssr_protect(__func__); + __hdd_set_multicast_list(dev); + cds_ssr_unprotect(__func__); +} +#endif + +/** + * hdd_select_queue() - used by Linux OS to decide which queue to use first + * @dev: Pointer to the WLAN device. + * @skb: Pointer to OS packet (sk_buff). + * + * This function is registered with the Linux OS for network + * core to decide which queue to use first. + * + * Return: ac, Queue Index/access category corresponding to UP in IP header + */ +static uint16_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_get_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)) + .ndo_set_rx_mode = hdd_set_multicast_list, +#else + .ndo_set_multicast_list = hdd_set_multicast_list, +#endif /* LINUX_VERSION_CODE */ +#endif +}; + +void hdd_set_station_ops(struct net_device *pWlanDev) +{ + pWlanDev->netdev_ops = &wlan_drv_ops; +} + +static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, + tSirMacAddr macAddr, + const char *name) +{ + struct net_device *pWlanDev = NULL; + hdd_adapter_t *adapter = NULL; + /* + * cfg80211 initialization and registration.... + */ + pWlanDev = + alloc_netdev_mq(sizeof(hdd_adapter_t), name, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) + NET_NAME_UNKNOWN, +#endif + ether_setup, + NUM_TX_QUEUES); + + if (pWlanDev != NULL) { + + /* Save the pointer to the net_device in the HDD adapter */ + adapter = (hdd_adapter_t *) netdev_priv(pWlanDev); + + cdf_mem_zero(adapter, sizeof(hdd_adapter_t)); + + adapter->dev = pWlanDev; + adapter->pHddCtx = hdd_ctx; + adapter->magic = WLAN_HDD_ADAPTER_MAGIC; + + init_completion(&adapter->session_open_comp_var); + init_completion(&adapter->session_close_comp_var); + init_completion(&adapter->disconnect_comp_var); + init_completion(&adapter->linkup_event_var); + init_completion(&adapter->cancel_rem_on_chan_var); + init_completion(&adapter->rem_on_chan_ready_event); + init_completion(&adapter->sta_authorized_event); + init_completion(&adapter->offchannel_tx_event); + init_completion(&adapter->tx_action_cnf_event); +#ifdef FEATURE_WLAN_TDLS + init_completion(&adapter->tdls_add_station_comp); + init_completion(&adapter->tdls_del_station_comp); + init_completion(&adapter->tdls_mgmt_comp); + init_completion(&adapter->tdls_link_establish_req_comp); +#endif + init_completion(&adapter->change_country_code); + + + init_completion(&adapter->scan_info.abortscan_event_var); + + adapter->offloads_configured = false; + adapter->isLinkUpSvcNeeded = false; + adapter->higherDtimTransition = true; + /* Init the net_device structure */ + strlcpy(pWlanDev->name, name, IFNAMSIZ); + + cdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr, + sizeof(tSirMacAddr)); + pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT; + pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM; + + if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload) + pWlanDev->features |= + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + pWlanDev->features |= NETIF_F_RXCSUM; + +#if defined(FEATURE_TSO) + if (hdd_ctx->config->tso_enable) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("TSO Enabled\n")); + pWlanDev->features |= + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG; + } +#endif + hdd_set_station_ops(adapter->dev); + + pWlanDev->destructor = free_netdev; + pWlanDev->ieee80211_ptr = &adapter->wdev; + adapter->wdev.wiphy = hdd_ctx->wiphy; + adapter->wdev.netdev = pWlanDev; + /* set pWlanDev's parent to underlying device */ + SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev); + hdd_wmm_init(adapter); + spin_lock_init(&adapter->pause_map_lock); + } + + return adapter; +} + +CDF_STATUS hdd_register_interface(hdd_adapter_t *adapter, + uint8_t rtnl_lock_held) +{ + struct net_device *pWlanDev = adapter->dev; + /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */ + /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */ + /* CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; */ + + if (rtnl_lock_held) { + if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) { + if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Failed:dev_alloc_name")); + return CDF_STATUS_E_FAILURE; + } + } + if (register_netdevice(pWlanDev)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Failed:register_netdev")); + return CDF_STATUS_E_FAILURE; + } + } else { + if (register_netdev(pWlanDev)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Failed:register_netdev")); + return CDF_STATUS_E_FAILURE; + } + } + set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags); + + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS hdd_sme_close_session_callback(void *pContext) +{ + hdd_adapter_t *adapter = pContext; + + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("NULL adapter")); + return CDF_STATUS_E_INVAL; + } + + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid magic")); + return CDF_STATUS_NOT_INITIALIZED; + } + + clear_bit(SME_SESSION_OPENED, &adapter->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 workqueue 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 signaling completion + */ + if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic) + complete(&adapter->session_close_comp_var); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter) +{ + struct net_device *pWlanDev = adapter->dev; + hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t type, subType; + unsigned long rc; + int ret_val; + + INIT_COMPLETION(adapter->session_open_comp_var); + sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode); + status = cds_get_vdev_types(adapter->device_mode, &type, &subType); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("failed to get vdev type")); + goto error_sme_open; + } + /* Open a SME session for future operation */ + cdf_ret_status = + sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter, + (uint8_t *) &adapter->macAddressCurrent, + &adapter->sessionId, type, subType); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + hddLog(LOGP, + FL("sme_open_session() failed, status code %08d [x%08x]"), + cdf_ret_status, cdf_ret_status); + status = CDF_STATUS_E_FAILURE; + goto error_sme_open; + } + /* Block on a completion variable. Can't wait forever though. */ + rc = wait_for_completion_timeout( + &adapter->session_open_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (!rc) { + hddLog(LOGP, + FL("Session is not opened within timeout period code %ld"), + rc); + status = CDF_STATUS_E_FAILURE; + goto error_sme_open; + } + + /* Register wireless extensions */ + cdf_ret_status = hdd_register_wext(pWlanDev); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + hddLog(LOGP, + FL("hdd_register_wext() failed, status code %08d [x%08x]"), + cdf_ret_status, cdf_ret_status); + status = CDF_STATUS_E_FAILURE; + goto error_register_wext; + } + /* Set the Connection State to Not Connected */ + hddLog(LOG1, + FL("Set HDD connState to eConnectionState_NotConnected")); + pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; + + /* Set the default operation channel */ + pHddStaCtx->conn_info.operationChannel = + hdd_ctx->config->OperatingChannel; + + /* Make the default Auth Type as OPEN */ + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; + + status = hdd_init_tx_rx(adapter); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGP, + FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"), + status, status); + goto error_init_txrx; + } + + set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); + + status = hdd_wmm_adapter_init(adapter); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGP, + FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"), + status, status); + goto error_wmm_init; + } + + set_bit(WMM_INIT_DONE, &adapter->event_flags); + + ret_val = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_PARAM_BURST_ENABLE, + hdd_ctx->config->enableSifsBurst, + PDEV_CMD); + + if (0 != ret_val) { + hddLog(LOGE, + FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"), + ret_val); + } +#ifdef FEATURE_WLAN_TDLS + if (0 != wlan_hdd_tdls_init(adapter)) { + status = CDF_STATUS_E_FAILURE; + hddLog(LOGE, FL("wlan_hdd_tdls_init failed")); + goto error_tdls_init; + } + set_bit(TDLS_INIT_DONE, &adapter->event_flags); +#endif + + return CDF_STATUS_SUCCESS; + +#ifdef FEATURE_WLAN_TDLS +error_tdls_init: + clear_bit(WMM_INIT_DONE, &adapter->event_flags); + hdd_wmm_adapter_close(adapter); +#endif +error_wmm_init: + clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); + hdd_deinit_tx_rx(adapter); +error_init_txrx: + hdd_unregister_wext(pWlanDev); +error_register_wext: + if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { + INIT_COMPLETION(adapter->session_close_comp_var); + if (CDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal, + adapter->sessionId, + hdd_sme_close_session_callback, + adapter)) { + unsigned long rc; + + /* + * Block on a completion variable. + * Can't wait forever though. + */ + rc = wait_for_completion_timeout( + &adapter->session_close_comp_var, + msecs_to_jiffies + (WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (rc <= 0) + hddLog(LOGE, + FL("Session is not opened within timeout period code %ld"), + rc); + } + } +error_sme_open: + return status; +} + +void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) +{ + hdd_cfg80211_state_t *cfgState; + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter); + + if (NULL != cfgState->buf) { + unsigned long rc; + INIT_COMPLETION(adapter->tx_action_cnf_event); + rc = wait_for_completion_timeout( + &adapter->tx_action_cnf_event, + msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT)); + if (!rc) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD Wait for Action Confirmation Failed!!")); + } + } + return; +} + +void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + bool rtnl_held) +{ + ENTER(); + switch (adapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + { + if (test_bit + (INIT_TX_RX_SUCCESS, &adapter->event_flags)) { + hdd_deinit_tx_rx(adapter); + clear_bit(INIT_TX_RX_SUCCESS, + &adapter->event_flags); + } + + if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { + hdd_wmm_adapter_close(adapter); + clear_bit(WMM_INIT_DONE, + &adapter->event_flags); + } + + hdd_cleanup_actionframe(hdd_ctx, adapter); + wlan_hdd_tdls_exit(adapter); + break; + } + + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + { + + if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { + hdd_wmm_adapter_close(adapter); + clear_bit(WMM_INIT_DONE, + &adapter->event_flags); + } + + hdd_cleanup_actionframe(hdd_ctx, adapter); + + hdd_unregister_hostapd(adapter, rtnl_held); + + /* set con_mode to STA only when no SAP concurrency mode */ + if (! + (cds_get_concurrency_mode() & + (CDF_SAP_MASK | CDF_P2P_GO_MASK))) + hdd_set_conparam(0); + + break; + } + + default: + break; + } + + EXIT(); +} + +void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + uint8_t rtnl_held) +{ + struct net_device *pWlanDev = NULL; + + if (adapter) + pWlanDev = adapter->dev; + else { + hddLog(LOGE, FL("adapter is Null")); + return; + } + + hdd_lro_disable(hdd_ctx, adapter); + /* + * 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, &adapter->event_flags); + + if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) { + if (rtnl_held) { + unregister_netdevice(pWlanDev); + } else { + unregister_netdev(pWlanDev); + } + /* + * Note that the adapter is no longer valid at this point + * since the memory has been reclaimed + */ + } +} + +CDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx, + tSirMacAddr macAddr) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + hdd_adapter_t *adapter; + CDF_STATUS status; + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if (adapter + && cdf_mem_compare(adapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr))) { + return CDF_STATUS_E_FAILURE; + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + return CDF_STATUS_SUCCESS; +} +hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, + const char *iface_name, tSirMacAddr macAddr, + uint8_t rtnl_held) +{ + hdd_adapter_t *adapter = NULL; + hdd_adapter_list_node_t *pHddAdapterNode = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + hdd_cfg80211_state_t *cfgState; + int ret; + + hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type); + + if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) { + /* + * Max limit reached on the number of vdevs configured by the + * host. Return error + */ + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d" + ), + hdd_ctx->current_intf_count, hdd_ctx->max_intf_count); + return NULL; + } + + if (macAddr == NULL) { + /* Not received valid macAddr */ + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "Unable to add virtual intf: Not able to get valid mac address" + )); + return NULL; + } + status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr); + if (CDF_STATUS_E_FAILURE == status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "Duplicate MAC addr: " MAC_ADDRESS_STR + " already exists", + MAC_ADDR_ARRAY(macAddr)); + 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: + { + adapter = + hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name); + + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), + session_type); + return NULL; + } + + if (WLAN_HDD_P2P_CLIENT == session_type) + adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + else if (WLAN_HDD_P2P_DEVICE == session_type) + adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; +#endif + else + adapter->wdev.iftype = NL80211_IFTYPE_STATION; + + adapter->device_mode = session_type; + + status = hdd_init_station_mode(adapter); + if (CDF_STATUS_SUCCESS != status) + goto err_free_netdev; + + hdd_lro_enable(hdd_ctx, adapter); + + /* + * Workqueue which gets scheduled in IPv4 notification + * callback + */ +#ifdef CONFIG_CNSS + cnss_init_work(&adapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); +#else + INIT_WORK(&adapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); +#endif + +#ifdef WLAN_NS_OFFLOAD + /* + * Workqueue which gets scheduled in IPv6 + * notification callback. + */ +#ifdef CONFIG_CNSS + cnss_init_work(&adapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#else + INIT_WORK(&adapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#endif +#endif + status = hdd_register_interface(adapter, rtnl_held); + if (CDF_STATUS_SUCCESS != status) { + hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); + goto err_lro_cleanup; + } + + /* Stop the Interface TX queue. */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + hdd_register_tx_flow_control(adapter, + hdd_tx_resume_timer_expired_handler, + hdd_tx_resume_cb); + + break; + } + + case WLAN_HDD_P2P_GO: + case WLAN_HDD_SOFTAP: + { + adapter = + hdd_wlan_create_ap_dev(hdd_ctx, macAddr, + (uint8_t *) iface_name); + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("failed to allocate adapter for session %d"), + session_type); + return NULL; + } + + adapter->wdev.iftype = + (session_type == + WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP : + NL80211_IFTYPE_P2P_GO; + adapter->device_mode = session_type; + + status = hdd_init_ap_mode(adapter); + if (CDF_STATUS_SUCCESS != status) + goto err_free_netdev; + + status = hdd_register_hostapd(adapter, rtnl_held); + if (CDF_STATUS_SUCCESS != status) { + hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); + goto err_free_netdev; + } + + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + hdd_set_conparam(1); + + break; + } + case WLAN_HDD_FTM: + { + adapter = + hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name); + + if (NULL == adapter) { + hddLog(CDF_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. + */ + adapter->wdev.iftype = NL80211_IFTYPE_STATION; + adapter->device_mode = session_type; + status = hdd_register_interface(adapter, rtnl_held); + + hdd_init_tx_rx(adapter); + + /* Stop the Interface TX queue. */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + } + break; + default: + { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Invalid session type %d"), + session_type); + CDF_ASSERT(0); + return NULL; + } + } + + cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter); + mutex_init(&cfgState->remain_on_chan_ctx_lock); + + if (CDF_STATUS_SUCCESS == status) { + /* Add it to the hdd's session list. */ + pHddAdapterNode = + cdf_mem_malloc(sizeof(hdd_adapter_list_node_t)); + if (NULL == pHddAdapterNode) { + status = CDF_STATUS_E_NOMEM; + } else { + pHddAdapterNode->pAdapter = adapter; + status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode); + } + } + + if (CDF_STATUS_SUCCESS != status) { + if (NULL != adapter) { + hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held); + adapter = NULL; + } + if (NULL != pHddAdapterNode) { + cdf_mem_free(pHddAdapterNode); + } + return NULL; + } + + if (CDF_STATUS_SUCCESS == status) { + cds_set_concurrency_mode(hdd_ctx, session_type); + + /* Initialize the WoWL service */ + if (!hdd_init_wowl(adapter)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("hdd_init_wowl failed")); + goto err_lro_cleanup; + } + + /* Adapter successfully added. Increment the vdev count */ + hdd_ctx->current_intf_count++; + + hddLog(CDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"), + hdd_ctx->current_intf_count); + + cds_check_and_restart_sap_with_non_dfs_acs(hdd_ctx); + } + + if ((cds_get_conparam() != CDF_FTM_MODE) + && (!hdd_ctx->config->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 value + * as param_id << 29 | param_value. + * Below param_value = 0(disable) + */ + ret = wma_cli_set_command(adapter->sessionId, + WMI_STA_SMPS_PARAM_CMDID, + HDD_DTIM_1CHAIN_RX_ID << + HDD_SMPS_PARAM_VALUE_S, + VDEV_CMD); + + if (ret != 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("DTIM 1 chain set failed %d"), ret); + goto err_lro_cleanup; + } + + ret = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_PARAM_TX_CHAIN_MASK, + hdd_ctx->config->txchainmask1x1, + PDEV_CMD); + if (ret != 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"), + ret); + goto err_lro_cleanup; + } + ret = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_PARAM_RX_CHAIN_MASK, + hdd_ctx->config->rxchainmask1x1, + PDEV_CMD); + if (ret != 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"), + ret); + goto err_lro_cleanup; + } +#undef HDD_DTIM_1CHAIN_RX_ID +#undef HDD_SMPS_PARAM_VALUE_S + } + + if (CDF_FTM_MODE != cds_get_conparam()) { + ret = wma_cli_set_command(adapter->sessionId, + WMI_PDEV_PARAM_HYST_EN, + hdd_ctx->config->enableMemDeepSleep, + PDEV_CMD); + + if (ret != 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("WMI_PDEV_PARAM_HYST_EN set failed %d"), + ret); + goto err_lro_cleanup; + } + } + +#ifdef CONFIG_FW_LOGS_BASED_ON_INI + + /* Enable FW logs based on INI configuration */ + if ((CDF_FTM_MODE != cds_get_conparam()) && + (hdd_ctx->config->enablefwlog)) { + uint8_t count = 0; + uint32_t value = 0; + uint8_t numEntries = 0; + uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH]; + + hdd_ctx->fw_log_settings.dl_type = + hdd_ctx->config->enableFwLogType; + ret = wma_cli_set_command(adapter->sessionId, + WMI_DBGLOG_TYPE, + hdd_ctx->config->enableFwLogType, + DBG_CMD); + if (ret != 0) { + hddLog(LOGE, FL("Failed to enable FW log type ret %d"), + ret); + } + + hdd_ctx->fw_log_settings.dl_loglevel = + hdd_ctx->config->enableFwLogLevel; + ret = wma_cli_set_command(adapter->sessionId, + WMI_DBGLOG_LOG_LEVEL, + hdd_ctx->config->enableFwLogLevel, + DBG_CMD); + if (ret != 0) { + hddLog(LOGE, FL("Failed to enable FW log level ret %d"), + ret); + } + + hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel, + moduleLoglevel, + &numEntries, + FW_MODULE_LOG_LEVEL_STRING_LENGTH); + while (count < numEntries) { + /* + * FW module log level input string looks like below: + * gFwDebugModuleLoglevel=,,... + * For example: + * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6 + * 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 + */ + + /* FW expects WMI command value = + * Module ID * 10 + Module Log level + */ + value = ((moduleLoglevel[count] * 10) + + moduleLoglevel[count + 1]); + ret = wma_cli_set_command(adapter->sessionId, + 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 + + return adapter; + +err_lro_cleanup: + hdd_lro_disable(hdd_ctx, adapter); +err_free_netdev: + free_netdev(adapter->dev); + wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes); + + return NULL; +} + +CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + uint8_t rtnl_held) +{ + hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext; + CDF_STATUS status; + + status = hdd_get_front_adapter(hdd_ctx, &pCurrent); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"), + status); + return status; + } + + while (pCurrent->pAdapter != adapter) { + status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext); + if (CDF_STATUS_SUCCESS != status) + break; + + pCurrent = pNext; + } + adapterNode = pCurrent; + if (CDF_STATUS_SUCCESS == status) { + cds_clear_concurrency_mode(hdd_ctx, adapter->device_mode); + hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held); + + hdd_remove_adapter(hdd_ctx, adapterNode); + cdf_mem_free(adapterNode); + adapterNode = NULL; + + /* Adapter removed. Decrement vdev count */ + if (hdd_ctx->current_intf_count != 0) + hdd_ctx->current_intf_count--; + + /* Fw will take care incase of concurrency */ + return CDF_STATUS_SUCCESS; + } + return CDF_STATUS_E_FAILURE; +} + +CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *pHddAdapterNode; + CDF_STATUS status; + + ENTER(); + + do { + status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode); + if (pHddAdapterNode && CDF_STATUS_SUCCESS == status) { + hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter, + false); + cdf_mem_free(pHddAdapterNode); + } + } while (NULL != pHddAdapterNode && CDF_STATUS_E_EMPTY != status); + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter) +{ + uint8_t *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 = (uint8_t *) &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_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; + } + + cdf_mem_copy(updateIE.bssid, bssid, sizeof(tSirMacAddr)); + updateIE.smeSessionId = pHostapdAdapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = true; + updateIE.notify = false; + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), + &updateIE, + eUPDATE_IE_PROBE_RESP) == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE")); + } +} + +CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, + const bool bCloseSession) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); + union iwreq_data wrqu; + tSirUpdateIE updateIE; + unsigned long rc; + + ENTER(); + + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + switch (adapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + if (hdd_conn_is_connected( + WLAN_HDD_GET_STATION_CTX_PTR(adapter)) || + hdd_is_connecting( + WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + if (pWextState->roamProfile.BSSType == + eCSR_BSS_TYPE_START_IBSS) + cdf_ret_status = + sme_roam_disconnect(hdd_ctx->hHal, + adapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + else + cdf_ret_status = + sme_roam_disconnect(hdd_ctx->hHal, + adapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + /* success implies disconnect command got queued up successfully */ + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + rc = wait_for_completion_timeout( + &adapter->disconnect_comp_var, + msecs_to_jiffies + (WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "wait on disconnect_comp_var failed" + )); + } + } else { + hddLog(LOGE, + FL( + "failed to post disconnect event to SME" + )); + } + memset(&wrqu, '\0', sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu, + NULL); + } else { + hdd_abort_mac_scan(hdd_ctx, adapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + + if (adapter->device_mode != WLAN_HDD_INFRA_STATION) + wlan_hdd_cleanup_remain_on_channel_ctx(adapter); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&adapter->ipv4NotifierWorkQueue); +#endif + + hdd_deregister_tx_flow_control(adapter); + +#ifdef WLAN_NS_OFFLOAD +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&adapter->ipv6NotifierWorkQueue); +#endif +#endif + + /* + * It is possible that the caller of this function does not + * wish to close the session + */ + if (true == bCloseSession && + test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { + INIT_COMPLETION(adapter->session_close_comp_var); + if (CDF_STATUS_SUCCESS == + sme_close_session(hdd_ctx->hHal, adapter->sessionId, + hdd_sme_close_session_callback, + adapter)) { + /* + * Block on a completion variable. Can't wait + * forever though. + */ + rc = wait_for_completion_timeout( + &adapter->session_close_comp_var, + msecs_to_jiffies + (WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + if (!rc) { + hddLog(LOGE, + FL( + "failure waiting for session_close_comp_var" + )); + } + } + } + break; + + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + if (hdd_ctx->config->conc_custom_rule1 && + (WLAN_HDD_SOFTAP == adapter->device_mode)) { + /* + * Before stopping the sap adapter, lets make sure there + * is no sap restart work pending. + */ + cds_flush_work(&hdd_ctx->sap_start_work); + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Canceled the pending SAP restart work")); + cds_change_sap_restart_required_status(hdd_ctx, false); + } + /* Any softap specific cleanup here... */ + if (adapter->device_mode == WLAN_HDD_P2P_GO) + wlan_hdd_cleanup_remain_on_channel_ctx(adapter); + + hdd_deregister_tx_flow_control(adapter); + + mutex_lock(&hdd_ctx->sap_lock); + if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { + CDF_STATUS status; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + /* Stop Bss. */ +#ifdef WLAN_FEATURE_MBSSID + status = wlansap_stop_bss( + WLAN_HDD_GET_SAP_CTX_PTR(adapter)); +#else + status = wlansap_stop_bss(hdd_ctx->pcds_context); +#endif + + if (CDF_IS_STATUS_SUCCESS(status)) { + hdd_hostapd_state_t *hostapd_state = + WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); + cdf_event_reset(&hostapd_state-> + cdf_stop_bss_event); + status = + cdf_wait_single_event(&hostapd_state-> + cdf_stop_bss_event, + BSS_WAIT_TIMEOUT); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL( + "failure waiting for wlansap_stop_bss %d" + ), + status); + } + } else { + hddLog(LOGE, FL("failure in wlansap_stop_bss")); + } + clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); + cds_decr_session_set_pcl(hdd_ctx, + adapter->device_mode, + adapter->sessionId); + + cdf_mem_copy(updateIE.bssid, + adapter->macAddressCurrent.bytes, + sizeof(tSirMacAddr)); + updateIE.smeSessionId = adapter->sessionId; + updateIE.ieBufferlength = 0; + updateIE.pAdditionIEBuffer = NULL; + updateIE.append = false; + updateIE.notify = false; + /* Probe bcn reset */ + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), + &updateIE, eUPDATE_IE_PROBE_BCN) + == CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL( + "Could not pass on PROBE_RSP_BCN data to PE" + )); + } + /* Assoc resp reset */ + if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), + &updateIE, + eUPDATE_IE_ASSOC_RESP) == + CDF_STATUS_E_FAILURE) { + hddLog(LOGE, + FL( + "Could not pass on ASSOC_RSP data to PE" + )); + } + /* Reset WNI_CFG_PROBE_RSP Flags */ + wlan_hdd_reset_prob_rspies(adapter); + kfree(adapter->sessionCtx.ap.beacon); + adapter->sessionCtx.ap.beacon = NULL; + } + mutex_unlock(&hdd_ctx->sap_lock); + break; + case WLAN_HDD_OCB: + ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)-> + conn_info.staId[0]); + break; + default: + break; + } + + EXIT(); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + + ENTER(); + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + hdd_stop_adapter(hdd_ctx, adapter, true); + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + + ENTER(); + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(adapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + adapter->sessionCtx.station.hdd_ReassocScenario = false; + + hdd_deinit_tx_rx(adapter); + cds_decr_session_set_pcl(hdd_ctx, + adapter->device_mode, + adapter->sessionId); + if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { + hdd_wmm_adapter_close(adapter); + clear_bit(WMM_INIT_DONE, &adapter->event_flags); + } + + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; +#ifndef MSM_PLATFORM + struct cdf_mac_addr bcastMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER; +#endif + eConnectionState connState; + + ENTER(); + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + + hdd_wmm_init(adapter); + + switch (adapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_P2P_DEVICE: + + connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter)) + ->conn_info.connState; + + hdd_init_station_mode(adapter); + /* Open the gates for HDD to receive Wext commands */ + adapter->isLinkUpSvcNeeded = false; + adapter->scan_info.mScanPending = false; + + /* Indicate disconnect event to supplicant if associated previously */ + if (eConnectionState_Associated == connState || + eConnectionState_IbssConnected == 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(adapter->dev, SIOCGIWAP, + &wrqu, NULL); + adapter->sessionCtx.station. + hdd_ReassocScenario = false; + + /* indicate disconnected event to nl80211 */ + cfg80211_disconnected(adapter->dev, + WLAN_REASON_UNSPECIFIED, + NULL, 0, GFP_KERNEL); + } else if (eConnectionState_Connecting == connState) { + /* + * Indicate connect failure to supplicant if we were in the + * process of connecting + */ + cfg80211_connect_result(adapter->dev, NULL, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } + + hdd_register_tx_flow_control(adapter, + hdd_tx_resume_timer_expired_handler, + hdd_tx_resume_cb); + + break; + + case WLAN_HDD_SOFTAP: + /* softAP can handle SSR */ + break; + + case WLAN_HDD_P2P_GO: +#ifdef MSM_PLATFORM + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("[SSR] send stop ap to supplicant")); + cfg80211_ap_stopped(adapter->dev, GFP_KERNEL); +#else + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("[SSR] send restart supplicant")); + /* event supplicant to restart */ + cfg80211_del_sta(adapter->dev, + (const u8 *)&bcastMac.bytes[0], + GFP_KERNEL); +#endif + break; + + default: + break; + } + + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +bool hdd_is_ssr_required(void) +{ + return is_ssr_required == 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 == is_ssr_required) + return; + + is_ssr_required = value; +} + +CDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t **padapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_peek_front(&hdd_ctx->hddAdapters, + (cdf_list_node_t **) padapterNode); + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +CDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t *adapterNode, + hdd_adapter_list_node_t **pNextAdapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_peek_next(&hdd_ctx->hddAdapters, + (cdf_list_node_t *) adapterNode, + (cdf_list_node_t **) pNextAdapterNode); + + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +CDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t *adapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_remove_node(&hdd_ctx->hddAdapters, + &adapterNode->node); + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +CDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t **padapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_remove_front(&hdd_ctx->hddAdapters, + (cdf_list_node_t **) padapterNode); + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +CDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t *adapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_insert_back(&hdd_ctx->hddAdapters, + (cdf_list_node_t *) adapterNode); + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +CDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx, + hdd_adapter_list_node_t *adapterNode) +{ + CDF_STATUS status; + cdf_spin_lock(&hdd_ctx->hdd_adapter_lock); + status = cdf_list_insert_front(&hdd_ctx->hddAdapters, + (cdf_list_node_t *) adapterNode); + cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock); + return status; +} + +hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx, + tSirMacAddr macAddr) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + hdd_adapter_t *adapter; + CDF_STATUS status; + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + + if (adapter + && cdf_mem_compare(adapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr))) { + return adapter; + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + return NULL; + +} + +hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx, + uint32_t vdev_id) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + hdd_adapter_t *adapter; + CDF_STATUS cdf_status; + + cdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while ((NULL != adapterNode) && (CDF_STATUS_SUCCESS == cdf_status)) { + adapter = adapterNode->pAdapter; + + if (adapter->sessionId == vdev_id) + return adapter; + + cdf_status = + hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("vdev_id %d does not exist with host"), vdev_id); + + return NULL; +} + +hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + hdd_adapter_t *adapter; + CDF_STATUS status; + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + + if (adapter && (mode == adapter->device_mode)) + return adapter; + + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + return NULL; + +} + +/** + * hdd_get_operating_channel() - return operating channel of the device mode + * @hdd_ctx: Pointer to the HDD context. + * @mode: Device mode for which operating channel is required. + * Suported modes: + * WLAN_HDD_INFRA_STATION, + * WLAN_HDD_P2P_CLIENT, + * WLAN_HDD_SOFTAP, + * WLAN_HDD_P2P_GO. + * + * This API returns the operating channel of the requested device mode + * + * Return: channel number. "0" id the requested device is not found OR it is + * not connected. + */ +uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + uint8_t operatingChannel = 0; + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + + if (mode == adapter->device_mode) { + switch (adapter->device_mode) { + case WLAN_HDD_INFRA_STATION: + case WLAN_HDD_P2P_CLIENT: + if (hdd_conn_is_connected + (WLAN_HDD_GET_STATION_CTX_PTR + (adapter))) { + operatingChannel = + (WLAN_HDD_GET_STATION_CTX_PTR + (adapter))->conn_info. + operationChannel; + } + break; + case WLAN_HDD_SOFTAP: + case WLAN_HDD_P2P_GO: + /* softap connection info */ + if (test_bit + (SOFTAP_BSS_STARTED, + &adapter->event_flags)) + operatingChannel = + (WLAN_HDD_GET_AP_CTX_PTR + (adapter))->operatingChannel; + break; + default: + break; + } + + break; /* Found the device of interest. break the loop */ + } + + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + return operatingChannel; +} + +static inline CDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t * + hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + + ENTER(); + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) || + (adapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (adapter->device_mode == WLAN_HDD_IBSS) || + (adapter->device_mode == WLAN_HDD_P2P_DEVICE) || + (adapter->device_mode == WLAN_HDD_SOFTAP) || + (adapter->device_mode == WLAN_HDD_P2P_GO)) { + wlan_hdd_cfg80211_deregister_frames(adapter); + hdd_unregister_wext(adapter->dev); + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + + ENTER(); + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) || + (adapter->device_mode == WLAN_HDD_P2P_CLIENT) || + (adapter->device_mode == WLAN_HDD_IBSS) || + (adapter->device_mode == WLAN_HDD_P2P_DEVICE) || + (adapter->device_mode == WLAN_HDD_SOFTAP) || + (adapter->device_mode == WLAN_HDD_P2P_GO)) { + hdd_abort_mac_scan(hdd_ctx, adapter->sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +#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(LOGE, 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 + +/** + * hdd_wlan_exit() - HDD WLAN exit function + * @hdd_ctx: Pointer to the HDD Context + * + * This is the driver exit point (invoked during rmmod) + * + * Return: None + */ +void hdd_wlan_exit(hdd_context_t *hdd_ctx) +{ + v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context; + CDF_STATUS cdf_status; + struct wiphy *wiphy = hdd_ctx->wiphy; + struct hdd_config *pConfig = hdd_ctx->config; + + ENTER(); + + hddLog(LOGE, FL("Unregister IPv6 notifier")); + hdd_wlan_unregister_ip6_notifier(hdd_ctx); + hddLog(LOGE, FL("Unregister IPv4 notifier")); + unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier); + + hdd_unregister_wext_all_adapters(hdd_ctx); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("FTM MODE")); +#if defined(QCA_WIFI_FTM) + if (hdd_ftm_stop(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("hdd_ftm_stop Failed")); + CDF_ASSERT(0); + } + hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED; +#endif + wlan_hdd_ftm_close(hdd_ctx); + hddLog(CDF_TRACE_LEVEL_FATAL, FL("FTM driver unloaded")); + goto free_hdd_ctx; + } + + /* + * 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 canceling 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(hdd_ctx); + +#ifdef MSM_PLATFORM + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) { + cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer); + } + + if (!CDF_IS_STATUS_SUCCESS + (cdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Cannot deallocate Bus bandwidth timer")); + } +#endif + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) { + cdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer); + } + + if (!CDF_IS_STATUS_SUCCESS + (cdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Cannot deallocate ACS Skip timer")); + } +#endif + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &hdd_ctx->dbs_opportunistic_timer)) { + cdf_mc_timer_stop(&hdd_ctx->dbs_opportunistic_timer); + } + + if (!CDF_IS_STATUS_SUCCESS + (cdf_mc_timer_destroy( + &hdd_ctx->dbs_opportunistic_timer))) { + hdd_err("Cannot deallocate dbs opportunistic timer"); + } + + /* + * Powersave Offload Case + * Disable Idle Power Save Mode + */ + hdd_set_idle_ps_config(hdd_ctx, false); + + hdd_debugfs_exit(hdd_ctx); + + /* 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 cds_scheduler is + * still available to handle those control messages + */ + hdd_stop_all_adapters(hdd_ctx); + + /* Stop all the modules */ + cdf_status = cds_disable(p_cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to stop CDS")); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } + + /* + * Close the scheduler before calling cds_close to make sure no thread + * is scheduled after the each module close is called i.e after all the + * data structures are freed. + */ + cdf_status = cds_sched_close(p_cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to close CDS Scheduler")); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + } +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + /* Destroy the wake lock */ + cdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock); +#endif + /* Destroy the wake lock */ + cdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock); + + hdd_hostapd_channel_wakelock_deinit(hdd_ctx); + + /* + * Close CDS + * This frees pMac(HAL) context. There should not be any call + * that requires pMac access after this. + */ + cds_close(p_cds_context); + + hdd_wlan_green_ap_deinit(hdd_ctx); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + if (pConfig && pConfig->wlanLoggingEnable) { + wlan_logging_sock_deactivate_svc(); + } +#endif +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + ptt_sock_deactivate_svc(); +#endif /* WLAN_KD_READY_NOTIFIER */ + nl_srv_exit(); + + hdd_close_all_adapters(hdd_ctx); + + hdd_ipa_cleanup(hdd_ctx); + + /* Free up RoC request queue and flush workqueue */ + cds_flush_work(&hdd_ctx->roc_req_work); + cdf_list_destroy(&hdd_ctx->hdd_roc_req_q); + cdf_list_destroy(&hdd_ctx->hdd_scan_req_q); + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy( + &hdd_ctx->hdd_conc_list_lock))) { + hdd_err("Failed to destroy hdd_conc_list_lock"); + /* Proceed and complete the clean up */ + } + +free_hdd_ctx: + + /* Free up dynamically allocated members inside HDD Adapter */ + if (hdd_ctx->config) { + kfree(hdd_ctx->config); + hdd_ctx->config = NULL; + } + + 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(false); +} + +void __hdd_wlan_exit(void) +{ + hdd_context_t *hdd_ctx; + + ENTER(); + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context")); + EXIT(); + return; + } + + /* module exit should never proceed if SSR is not completed */ + while (hdd_ctx->isLogpInProgress) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("SSR in Progress; block rmmod for 1 second!!!")); + msleep(1000); + } + + hdd_ctx->isUnloadInProgress = true; + + cds_set_load_unload_in_progress(true); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + + /* Do all the cleanup before deregistering the driver */ + hdd_wlan_exit(hdd_ctx); + 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; + + hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip")); + hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN; + + if (!hdd_ctx->hHal) + return; + sme_scan_flush_result(hdd_ctx->hHal); +} +#endif + +#ifdef QCA_HT_2040_COEX +/** + * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode + * @adapter: pointer to adapter + * @staId: station id + * @macAddrSTA: station MAC address + * @channel_type: channel type + * + * This function notifies FW with HT20/HT40 mode + * + * Return: 0 if successful, error number otherwise + */ +int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId, + struct cdf_mac_addr macAddrSTA, int channel_type) +{ + int status; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx = NULL; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + if (!hdd_ctx->hHal) + return -EINVAL; + + cdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA, + adapter->sessionId, channel_type); + if (CDF_STATUS_SUCCESS != cdf_status) { + hddLog(LOGE, "Fail to send notification with ht2040 mode"); + return -EINVAL; + } + + return 0; +} +#endif + +/** + * hdd_wlan_notify_modem_power_state() - notify FW with modem power status + * @state: state + * + * This function notifies FW with modem power status + * + * Return: 0 if successful, error number otherwise + */ +int hdd_wlan_notify_modem_power_state(int state) +{ + int status; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + if (!hdd_ctx->hHal) + return -EINVAL; + + cdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state); + if (CDF_STATUS_SUCCESS != cdf_status) { + hddLog(LOGE, + "Fail to send notification with modem power state %d", + state); + return -EINVAL; + } + return 0; +} + +/** + * + * hdd_post_cds_enable_config() - HDD post cds start config helper + * @adapter - Pointer to the HDD + * + * Return: None + */ +CDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx) +{ + CDF_STATUS cdf_ret_status; + + /* + * Send ready indication to the HDD. This will kick off the MAC + * into a 'running' state and should kick off an initial scan. + */ + cdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "sme_hdd_ready_ind() failed with status code %08d [x%08x]" + ), + cdf_ret_status, cdf_ret_status); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/* wake lock APIs for HDD */ +void hdd_prevent_suspend(uint32_t reason) +{ + cdf_wake_lock_acquire(&wlan_wake_lock, reason); +} + +void hdd_allow_suspend(uint32_t reason) +{ + cdf_wake_lock_release(&wlan_wake_lock, reason); +} + +void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason) +{ + cdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason); +} + +/** + * hdd_exchange_version_and_caps() - exchange version and capability with target + * @hdd_ctx: Pointer to HDD context + * + * This is the HDD function to exchange version and capability information + * between Host and Target + * + * This function gets reported version of FW. + * It also finds the version of target 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 target i.e. host + * and target exchange a msg indicating the features they support through a + * bitmap + * + * Return: None + */ +void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx) +{ + + tSirVersionType versionCompiled; + tSirVersionType versionReported; + tSirVersionString versionString; + uint8_t fwFeatCapsMsgSupported = 0; + CDF_STATUS vstatus; + + memset(&versionCompiled, 0, sizeof(versionCompiled)); + memset(&versionReported, 0, sizeof(versionReported)); + + /* retrieve and display WCNSS version information */ + do { + + vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal, + &versionCompiled); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "unable to retrieve WCNSS WLAN compiled version" + )); + break; + } + + vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal, + &versionReported); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "unable to retrieve WCNSS WLAN reported version" + )); + 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_get_wcnss_software_version(hdd_ctx->hHal, + versionString, + sizeof(versionString)); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "unable to retrieve WCNSS software version string" + )); + break; + } + + pr_info("%s: WCNSS software version %s\n", + WLAN_MODULE_NAME, versionString); + + vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal, + versionString, + sizeof(versionString)); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "unable to retrieve WCNSS hardware version string" + )); + 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 + * target 1.1 so send the message only if it the target is 1.1 + * minor numbers for different target 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) { + /* + * Indicate if IBSS heartbeat monitoring needs to be + * offloaded + */ + if (!hdd_ctx->config->enableIbssHeartBeatOffload) { + sme_disable_feature_capablity + (IBSS_HEARTBEAT_OFFLOAD); + } + + sme_feature_caps_exchange(hdd_ctx->hHal); + } + + } while (0); + +} + +/* Initialize channel list in sme based on the country code */ +CDF_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); +} + +/** + * hdd_is_5g_supported() - check if hardware supports 5GHz + * @hdd_ctx: Pointer to the hdd context + * + * HDD function to know if hardware supports 5GHz + * + * Return: true if hardware supports 5GHz + */ +bool hdd_is_5g_supported(hdd_context_t *hdd_ctx) +{ + /* + * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1); + * then hardware support 5Ghz. + */ + return true; +} + +static CDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx) +{ + struct wiphy *wiphy; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + wiphy = hdd_ctx->wiphy; + + /* + * The channel information in + * wiphy needs to be initialized before wiphy registration + */ + status = cds_regulatory_init(); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("cds_init_wiphy failed")); + return status; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) + 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(CDF_TRACE_LEVEL_ERROR, FL("wiphy register failed")); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +#ifdef MSM_PLATFORM +void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, + uint64_t tx_packets, uint64_t rx_packets) +{ +#ifdef CONFIG_CNSS + uint64_t total = tx_packets + rx_packets; + enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE; + + uint64_t temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2; + enum cnss_bus_width_type next_rx_level = CNSS_BUS_WIDTH_NONE; + if (total > hdd_ctx->config->busBandwidthHighThreshold) + next_vote_level = CNSS_BUS_WIDTH_HIGH; + else if (total > hdd_ctx->config->busBandwidthMediumThreshold) + next_vote_level = CNSS_BUS_WIDTH_MEDIUM; + else + next_vote_level = CNSS_BUS_WIDTH_LOW; + + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level + = next_vote_level; + + if (hdd_ctx->cur_vote_level != next_vote_level) { + hddLog(CDF_TRACE_LEVEL_DEBUG, + FL( + "trigger level %d, tx_packets: %lld, rx_packets: %lld" + ), + next_vote_level, tx_packets, rx_packets); + hdd_ctx->cur_vote_level = next_vote_level; + cnss_request_bus_bandwidth(next_vote_level); + } + hdd_ctx->prev_rx = rx_packets; + if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) + next_rx_level = CNSS_BUS_WIDTH_HIGH; + else + next_rx_level = CNSS_BUS_WIDTH_LOW; + + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level + = next_rx_level; + + if (hdd_ctx->cur_rx_level != next_rx_level) { + hddLog(CDF_TRACE_LEVEL_DEBUG, + FL("TCP DELACK trigger level %d, average_rx: %llu"), + next_rx_level, temp_rx); + hdd_ctx->cur_rx_level = next_rx_level; + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, + &next_rx_level, + sizeof(next_rx_level)); + } + + hdd_ctx->hdd_txrx_hist_idx++; + hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; +#endif +} + +#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) +static void hdd_bus_bw_compute_cbk(void *priv) +{ + hdd_context_t *hdd_ctx = (hdd_context_t *) priv; + hdd_adapter_t *adapter = NULL; + uint64_t tx_packets = 0, rx_packets = 0; + uint64_t total_tx = 0, total_rx = 0; + hdd_adapter_list_node_t *adapterNode = NULL; + CDF_STATUS status = 0; + bool connected = false; + uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0; + + for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + NULL != adapterNode && CDF_STATUS_SUCCESS == status; + status = + hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) { + + if (adapterNode->pAdapter == NULL) + continue; + adapter = adapterNode->pAdapter; + + if ((adapter->device_mode == WLAN_HDD_INFRA_STATION || + adapter->device_mode == WLAN_HDD_P2P_CLIENT) && + WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState + != eConnectionState_Associated) { + + continue; + } + + if ((adapter->device_mode == WLAN_HDD_SOFTAP || + adapter->device_mode == WLAN_HDD_P2P_GO) && + WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) { + + continue; + } + + tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets, + adapter->prev_tx_packets); + rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets, + adapter->prev_rx_packets); + + total_rx += adapter->stats.rx_packets; + total_tx += adapter->stats.tx_packets; + + spin_lock_bh(&hdd_ctx->bus_bw_lock); + adapter->prev_tx_packets = adapter->stats.tx_packets; + adapter->prev_rx_packets = adapter->stats.rx_packets; + spin_unlock_bh(&hdd_ctx->bus_bw_lock); + connected = true; + } + + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx; + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx; + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx = + rx_packets; + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx = + tx_packets; + + hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets); + tx_packets += (uint64_t)ipa_tx_packets; + rx_packets += (uint64_t)ipa_rx_packets; + + if (!connected) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("bus bandwidth timer running in disconnected state")); + return; + } + + hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets); + + hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets); + hdd_ipa_uc_stat_request(adapter, 2); + + cdf_mc_timer_start(&hdd_ctx->bus_bw_timer, + hdd_ctx->config->busBandwidthComputeInterval); +} +#endif + +/** + * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram + * @hdd_ctx: hdd context + * + * Return: none + */ +void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx) +{ + int i; + +#ifdef MSM_PLATFORM + hddLog(CDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d", + hdd_ctx->config->busBandwidthComputeInterval, + hdd_ctx->hdd_txrx_hist_idx); + hddLog(CDF_TRACE_LEVEL_ERROR, + "BW High TH: %d BW Med TH: %d BW Low TH: %d", + hdd_ctx->config->busBandwidthHighThreshold, + hdd_ctx->config->busBandwidthMediumThreshold, + hdd_ctx->config->busBandwidthLowThreshold); + hddLog(CDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d", + hdd_ctx->config->tcpDelackThresholdHigh, + hdd_ctx->config->tcpDelackThresholdLow); +#endif + + hddLog(CDF_TRACE_LEVEL_ERROR, "index, total_rx, interval_rx," + "total_tx, interval_tx, next_vote_level, next_rx_level"); + + for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%d: %llu, %llu, %llu, %llu, %d, %d", + i, hdd_ctx->hdd_txrx_hist[i].total_rx, + hdd_ctx->hdd_txrx_hist[i].interval_rx, + hdd_ctx->hdd_txrx_hist[i].total_tx, + hdd_ctx->hdd_txrx_hist[i].interval_tx, + hdd_ctx->hdd_txrx_hist[i].next_vote_level, + hdd_ctx->hdd_txrx_hist[i].next_rx_level); + } + return; +} + +/** + * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram + * @hdd_ctx: hdd context + * + * Return: none + */ +void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx) +{ + hdd_ctx->hdd_txrx_hist_idx = 0; + cdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist)); +} + +/** + * wlan_hdd_display_netif_queue_history() - display netif queue operation history + * @pHddCtx: hdd context + * + * Return: none + */ +void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx) +{ + + hdd_adapter_t *adapter = NULL; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + CDF_STATUS status; + int i; + + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + + hddLog(CDF_TRACE_LEVEL_ERROR, + "Session_id %d device mode %d current index %d", + adapter->sessionId, adapter->device_mode, + adapter->history_index); + + hddLog(CDF_TRACE_LEVEL_ERROR, + "Netif queue operation statistics:"); + hddLog(CDF_TRACE_LEVEL_ERROR, + "Current pause_map value %x", adapter->pause_map); + hddLog(CDF_TRACE_LEVEL_ERROR, + " reason_type: pause_cnt: unpause_cnt"); + + for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: %d: %d", + hdd_reason_type_to_string(i), + adapter->queue_oper_stats[i].pause_count, + adapter->queue_oper_stats[i].unpause_count); + } + + hddLog(CDF_TRACE_LEVEL_ERROR, + "Netif queue operation history:"); + hddLog(CDF_TRACE_LEVEL_ERROR, + "index: time: action_type: reason_type: pause_map"); + + for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%d: %u: %s: %s: %x", + i, cdf_system_ticks_to_msecs( + adapter->queue_oper_history[i].time), + hdd_action_type_to_string( + adapter->queue_oper_history[i].netif_action), + hdd_reason_type_to_string( + adapter->queue_oper_history[i].netif_reason), + adapter->queue_oper_history[i].pause_map); + } + + status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); + adapter_node = next; + } + + +} + +/** + * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history + * @hdd_ctx: hdd context + * + * Return: none + */ +void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx) +{ + hdd_adapter_t *adapter = NULL; + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + CDF_STATUS status; + + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) { + adapter = adapter_node->pAdapter; + + cdf_mem_zero(adapter->queue_oper_stats, + sizeof(adapter->queue_oper_stats)); + cdf_mem_zero(adapter->queue_oper_history, + sizeof(adapter->queue_oper_history)); + + status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); + adapter_node = next; + } +} + +/** + * hdd_11d_scan_done() - callback for 11d scan completion of flushing results + * @halHandle: Hal handle + * @pContext: Pointer to the context + * @sessionId: Session ID + * @scanId: Scan ID + * @status: Status + * + * This is the 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: CDF_STATUS_SUCCESS + */ +static CDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext, + uint8_t sessionId, uint32_t scanId, + eCsrScanStatus status) +{ + ENTER(); + + sme_scan_flush_result(halHandle); + + EXIT(); + + return CDF_STATUS_SUCCESS; +} + +#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 + +#ifdef WLAN_FEATURE_FASTPATH +/** + * hdd_enable_fastpath() - Enable fastpath if enabled in config INI + * @hdd_cfg: hdd config + * @context: lower layer context + * + * Return: none + */ +static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, + void *context) +{ + if (hdd_cfg->fastpath_enable) + hif_enable_fastpath(context); +} +#else +static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, + void *context) +{ +} +#endif + +#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) +/** + * hdd_set_thermal_level_cb() - set thermal level callback function + * @hdd_ctxt: hdd context pointer + * @level: thermal level + * + * Change IPA data path to SW path when the thermal throttle level greater + * than 0, and restore the original data path when throttle level is 0 + * + * Return: none + */ +static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, 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(hdd_ctx, true); + else + /* restore original concurrency mode */ + hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode); +} + +/** + * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel + * @hdd_ctxt: hdd context pointer + * @ap_adapter: hdd hostapd adapter pointer + * + * Try to find safe channel within preferred channel + * In case 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) { + hdd_err("invalid context/adapter"); + return 0; + } + + safe_channel_count = 0; + unsafe_channel_count = CDF_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 (rf_channels[i].channelNum == + hdd_ctxt->unsafe_channel_list[channel_loop]) { + is_unsafe = 1; + break; + } + } + if (!is_unsafe) { + safe_channels[safe_channel_count] = + rf_channels[i].channelNum; + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("safe channel %d"), + safe_channels[safe_channel_count]); + safe_channel_count++; + } + } + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("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) { + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("safe channel %d is in perferred range"), + safe_channels[i]); + return 1; + } + } + return 0; +} + +/** + * hdd_ch_avoid_cb() - Avoid notified channels from FW handler + * @adapter: HDD adapter pointer + * @indParam: Channel avoid notification parameter + * + * Avoid channel notification from FW handler. + * FW will send un-safe channel list to avoid over wrapping. + * hostapd should not use notified channel + * + * Return: None + */ +static 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; + uint8_t range_loop; + eRfChannels channel_loop, start_channel_idx = INVALID_RF_CHANNEL, + end_channel_idx = INVALID_RF_CHANNEL; + uint16_t start_channel; + uint16_t end_channel; + v_CONTEXT_t cds_context; + static int restart_sap_in_progress; + tHddAvoidFreqList hdd_avoid_freq_list; + uint32_t i; + + /* Basic sanity */ + if (!hdd_context || !indi_param) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid arguments")); + return; + } + + hdd_ctxt = (hdd_context_t *) hdd_context; + ch_avoid_indi = (tSirChAvoidIndType *) indi_param; + cds_context = hdd_ctxt->pcds_context; + + /* Make unsafe channel list */ + hddLog(CDF_TRACE_LEVEL_INFO, + FL("band count %d"), + ch_avoid_indi->avoid_range_count); + + /* generate vendor specific event */ + cdf_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; + cdf_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); + hddLog(LOG1, "%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 (rf_channels[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 (rf_channels[channel_loop].targetFreq >= + ch_avoid_indi->avoid_freq_range[ + range_loop].end_freq) { + end_channel_idx = channel_loop; + if (rf_channels[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++] = + rf_channels[channel_loop].channelNum; + if (hdd_ctxt->unsafe_channel_count >= + NUM_20MHZ_RF_CHANNELS) { + hddLog(LOGW, FL("LTECoex unsafe ch list full")); + break; + } + } + } + + hddLog(CDF_TRACE_LEVEL_INFO, + FL("number of unsafe channels is %d "), + hdd_ctxt->unsafe_channel_count); + + if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list, + hdd_ctxt->unsafe_channel_count)) { + hdd_err("Failed to set unsafe channel"); + + /* clear existing unsafe channel cache */ + hdd_ctxt->unsafe_channel_count = 0; + cdf_mem_zero(hdd_ctxt->unsafe_channel_list, + sizeof(hdd_ctxt->unsafe_channel_list)); + + return; + } + + for (channel_loop = 0; + channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("channel %d is not safe "), + hdd_ctxt->unsafe_channel_list[channel_loop]); + } + + /* + * 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 (hdd_ctxt->unsafe_channel_count) { + hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP); + if (hostapd_adapter) { + if ((hostapd_adapter->sessionCtx.ap.sapConfig. + acs_cfg.acs_mode) && + (!hdd_find_prefd_safe_chnl(hdd_ctxt, + hostapd_adapter))) + return; + + hddLog(CDF_TRACE_LEVEL_INFO, + FL( + "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d" + ), + hostapd_adapter->sessionCtx.ap. + operatingChannel, + 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(CDF_TRACE_LEVEL_INFO, + 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); + break; + } + } + } + } + return; +} + +/** + * hdd_init_channel_avoidance() - Initialize channel avoidance + * @hdd_ctx: HDD global context + * + * Initialize the channel avoidance logic by retrieving the unsafe + * channel list from the CNSS platform driver and plumbing the data + * down to the lower layers. Then subscribe to subsequent channel + * avoidance events. + * + * Return: None + */ +static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) +{ + uint16_t unsafe_channel_count; + int index; + + cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list, + &(hdd_ctx->unsafe_channel_count), + sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS); + + hddLog(CDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"), + hdd_ctx->unsafe_channel_count); + + unsafe_channel_count = CDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count, + (uint16_t)NUM_20MHZ_RF_CHANNELS); + + for (index = 0; index < unsafe_channel_count; index++) { + hddLog(CDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"), + hdd_ctx->unsafe_channel_list[index]); + + } + + /* Plug in avoid channel notification callback */ + sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb); +} +#else +static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) +{ +} +static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, u_int8_t level) +{ +} +#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */ + +/** + * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features + * @hdd_ctx: HDD context + * + * Disables all the dual mac features like DBS, Agile DFS etc. + * + * Return: CDF_STATUS_SUCCESS on success + */ +static CDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx) +{ + struct sir_dual_mac_config cfg; + CDF_STATUS status; + + if (!hdd_ctx) { + hdd_err("HDD context is NULL"); + return CDF_STATUS_E_FAILURE; + } + + cfg.scan_config = 0; + cfg.fw_mode_config = 0; + cfg.set_dual_mac_cb = + (void *)cds_soc_set_dual_mac_cfg_cb; + + hdd_debug("Disabling all dual mac features..."); + + status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("sme_soc_set_dual_mac_config failed %d", status); + return status; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wlan_startup() - HDD init function + * @dev: Pointer to the underlying device + * + * This is the driver startup code executed once a WLAN device has been detected + * + * Return: 0 for success, < 0 for failure + */ +int hdd_wlan_startup(struct device *dev, void *hif_sc) +{ + CDF_STATUS status; + hdd_adapter_t *adapter = NULL; +#ifdef WLAN_OPEN_P2P_INTERFACE + hdd_adapter_t *pP2adapter = NULL; +#endif + hdd_context_t *hdd_ctx = NULL; + v_CONTEXT_t p_cds_context = NULL; + int ret; + int i; + struct wiphy *wiphy; + unsigned long rc; + tSmeThermalParams thermalParam; + tSirTxPowerLimit *hddtxlimit; + uint8_t rtnl_lock_enable; + uint8_t reg_netdev_notifier_done = false; + hdd_adapter_t *dot11_adapter = NULL; + + ENTER(); + + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + ret = epping_enable(dev); + EXIT(); + return ret; + } + + /* cfg80211: wiphy allocation */ + wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)); + + if (wiphy == NULL) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("cfg80211 init failed")); + return -EIO; + } + + hdd_ctx = wiphy_priv(wiphy); + + /* Initialize the adapter context to zeros. */ + cdf_mem_zero(hdd_ctx, sizeof(hdd_context_t)); + + hdd_ctx->wiphy = wiphy; + hdd_ctx->isLoadInProgress = true; + hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + cds_set_wakelock_logging(false); + + cds_set_load_unload_in_progress(true); + + /* Get cds context here bcoz cds_open requires it */ + p_cds_context = cds_get_global_context(); + + if (p_cds_context == NULL) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed cds_get_global_context")); + goto err_free_hdd_context; + } + /* Save the Global CDS context in adapter context for future. */ + hdd_ctx->pcds_context = p_cds_context; + + /* Save the adapter context in global context for future. */ + ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx; + + hdd_ctx->parent_dev = dev; + + hdd_init_ll_stats_ctx(); + + init_completion(&hdd_ctx->mc_sus_event_var); + init_completion(&hdd_ctx->ready_to_suspend); + + spin_lock_init(&hdd_ctx->schedScan_lock); + + cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock); + cdf_list_init(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); + + wlan_hdd_cfg80211_extscan_init(hdd_ctx); + +#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(&hdd_ctx->tdls_lock); +#endif + + /* store target type and target version info in hdd ctx */ + hdd_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type; + hdd_init_offloaded_packets_ctx(hdd_ctx); + /* Load all config first as TL config is needed during cds_open */ + hdd_ctx->config = + (struct hdd_config *) kmalloc(sizeof(struct hdd_config), GFP_KERNEL); + if (hdd_ctx->config == NULL) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed kmalloc struct hdd_config")); + goto err_config; + } + + cdf_mem_zero(hdd_ctx->config, sizeof(struct hdd_config)); + + /* Read and parse the qcom_cfg.ini file */ + status = hdd_parse_config_ini(hdd_ctx); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("error parsing %s"), + WLAN_INI_FILE); + goto err_config; + } + + hdd_ctx->current_intf_count = 0; + hdd_ctx->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 + */ + hdd_ctx->configuredMcastBcastFilter = + hdd_ctx->config->mcastBcastFilterSetting; + hddLog(CDF_TRACE_LEVEL_INFO, + FL("Setting configuredMcastBcastFilter: %d"), + hdd_ctx->config->mcastBcastFilterSetting); + + if (false == hdd_is_5g_supported(hdd_ctx)) { + /* 5Ghz is not supported. */ + if (1 != hdd_ctx->config->nBandCapability) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL( + "Setting hdd_ctx->config->nBandCapability = 1" + )); + hdd_ctx->config->nBandCapability = 1; + } + } + + /* + * cfg80211: Initialization ... + */ + if (0 < wlan_hdd_cfg80211_init(dev, wiphy, hdd_ctx->config)) { + hddLog(LOGE, + FL("wlan_hdd_cfg80211_init return failure")); + goto err_config; + } + + hdd_enable_fastpath(hdd_ctx->config, hif_sc); + /* + * Initialize struct for saving f/w log setting will be used + * after ssr + */ + hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enablefwlog; + hdd_ctx->fw_log_settings.dl_type = 0; + hdd_ctx->fw_log_settings.dl_report = 0; + hdd_ctx->fw_log_settings.dl_loglevel = 0; + hdd_ctx->fw_log_settings.index = 0; + for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { + hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0; + } + /* Update CDF trace levels based upon the cfg.ini */ + hdd_cdf_trace_enable(CDF_MODULE_ID_WMI, + hdd_ctx->config->cdf_trace_enable_wdi); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD, + hdd_ctx->config->cdf_trace_enable_hdd); + hdd_cdf_trace_enable(CDF_MODULE_ID_SME, + hdd_ctx->config->cdf_trace_enable_sme); + hdd_cdf_trace_enable(CDF_MODULE_ID_PE, + hdd_ctx->config->cdf_trace_enable_pe); + hdd_cdf_trace_enable(CDF_MODULE_ID_WMA, + hdd_ctx->config->cdf_trace_enable_wma); + hdd_cdf_trace_enable(CDF_MODULE_ID_SYS, + hdd_ctx->config->cdf_trace_enable_sys); + hdd_cdf_trace_enable(CDF_MODULE_ID_CDF, + hdd_ctx->config->cdf_trace_enable_cdf); + hdd_cdf_trace_enable(CDF_MODULE_ID_SAP, + hdd_ctx->config->cdf_trace_enable_sap); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SOFTAP, + hdd_ctx->config->cdf_trace_enable_hdd_sap); + hdd_cdf_trace_enable(CDF_MODULE_ID_BMI, + hdd_ctx->config->cdf_trace_enable_bmi); + hdd_cfg_print(hdd_ctx); + + if (CDF_FTM_MODE == hdd_get_conparam()) + goto ftm_processing; + + hdd_ctx->isLogpInProgress = false; + cds_set_logp_in_progress(false); + + cds_set_connection_in_progress(hdd_ctx, false); + + status = cds_open(&p_cds_context, 0); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed")); + goto err_cds_open; + } + + wlan_hdd_update_wiphy(wiphy, hdd_ctx->config); + + hdd_ctx->hHal = cds_get_context(CDF_MODULE_ID_SME); + + if (NULL == hdd_ctx->hHal) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("HAL context is null")); + goto err_cds_close; + } + + status = cds_pre_enable(hdd_ctx->pcds_context); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed")); + goto err_cds_close; + } + + ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb); + + status = wlan_hdd_regulatory_init(hdd_ctx); + + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to init channel list")); + goto err_cds_close; + } + + /* + * Set 802.11p config + * TODO-OCB: This has been temporarily added here to ensure this + * parameter 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(hdd_ctx); + + if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) { + hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan; + hddLog(CDF_TRACE_LEVEL_INFO, + FL("module enable_dfs_chan_scan set to %d"), + enable_dfs_chan_scan); + } + if (0 == enable_11d || 1 == enable_11d) { + hdd_ctx->config->Is11dSupportEnabled = enable_11d; + hddLog(CDF_TRACE_LEVEL_INFO, FL("module enable_11d set to %d"), + enable_11d); + } + + /* + * Note that the cds_pre_enable() 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(hdd_ctx); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config")); + goto err_wiphy_unregister; + } + + ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, + hdd_ctx->config->tx_chain_mask_1ss, + PDEV_CMD); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", + __func__, ret); + } + + status = hdd_set_sme_chan_list(hdd_ctx); + if (status != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to init channel list")); + goto err_wiphy_unregister; + } + + /* Apply the cfg.ini to cfg.dat */ + if (false == hdd_update_config_dat(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("config update failed")); + goto err_wiphy_unregister; + } + + if (CDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_WARN, + FL("can't update mac config, using MAC from ini file")); + } + + { + CDF_STATUS cdf_ret_status; + /* + * 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. + */ + cdf_ret_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, + (uint8_t *) &hdd_ctx->config-> + intfMacAddr[0], + sizeof(hdd_ctx->config-> + intfMacAddr[0])); + + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "Failed to set MAC Address. HALStatus is %08d [x%08x]" + ), + cdf_ret_status, cdf_ret_status); + goto err_wiphy_unregister; + } + } + + if (hdd_ipa_init(hdd_ctx) == CDF_STATUS_E_FAILURE) + goto err_wiphy_unregister; + + /* + * Start CDS which starts up the SME/MAC/HAL modules and everything + * else + */ + status = cds_enable(hdd_ctx->pcds_context); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_enable failed")); + goto err_wiphy_unregister; + } + + hdd_init_channel_avoidance(hdd_ctx); + + status = hdd_post_cds_enable_config(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("hdd_post_cds_enable_config failed")); + goto err_cds_disable; + } +#ifdef QCA_PKT_PROTO_TRACE + cds_pkt_proto_trace_init(); +#endif /* QCA_PKT_PROTO_TRACE */ + +ftm_processing: + if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_STATUS_SUCCESS != wlan_hdd_ftm_open(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("wlan_hdd_ftm_open Failed")); + goto err_config; + } +#if defined(QCA_WIFI_FTM) + if (hdd_ftm_start(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("hdd_ftm_start Failed")); + 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; + } + + cds_set_load_unload_in_progress(false); + hdd_ctx->isLoadInProgress = false; + hddLog(LOGE, FL("FTM driver loaded")); + complete(&wlan_start_comp); + return CDF_STATUS_SUCCESS; + } +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + rtnl_lock(); + rtnl_lock_enable = true; +#else + rtnl_lock_enable = false; +#endif + + if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) + /* Create only 802.11p interface */ + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_lock_enable); + else + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, + "wlan%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_lock_enable); + +#ifdef WLAN_OPEN_P2P_INTERFACE + /* Open P2P device interface */ + if (adapter != NULL) { + if (hdd_ctx->config->isP2pDeviceAddrAdministrated && + !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) { + cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes, + hdd_ctx->config->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. + */ + hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02; + } else { + uint8_t *p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx); + if (p2p_dev_addr != NULL) { + cdf_mem_copy(&hdd_ctx->p2pDeviceAddress. + bytes[0], p2p_dev_addr, + CDF_MAC_ADDR_SIZE); + } else { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "Failed to allocate mac_address for p2p_device" + )); + goto err_close_adapter; + } + } + + pP2adapter = + hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d", + &hdd_ctx->p2pDeviceAddress.bytes[0], + rtnl_lock_enable); + + if (NULL == pP2adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "Failed to do hdd_open_adapter for P2P Device Interface" + )); + goto err_close_adapter; + } + } +#endif + + if (adapter == NULL) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("hdd_open_adapter failed")); + goto err_close_adapter; + } + + /* Open 802.11p Interface */ + if (adapter != NULL) { + if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { + dot11_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, + "wlanocb%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_lock_enable); + if (dot11_adapter == NULL) { + hddLog(LOGE, + FL("failed to open 802.11p Interface")); + goto err_close_adapter; + } + } + } + + /* + * target hw version/revision would only be retrieved after firmware + * donwload + */ + hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version, + &hdd_ctx->target_hw_revision, + &hdd_ctx->target_hw_name); + + /* Get the wlan hw/fw version */ + hdd_wlan_get_version(adapter, NULL, NULL); + + /* pass target_fw_version to HIF layer */ + hif_set_fw_info(hif_sc, hdd_ctx->target_fw_version); + + if (country_code) { + CDF_STATUS ret; + + INIT_COMPLETION(adapter->change_country_code); + + ret = sme_change_country_code(hdd_ctx->hHal, + wlan_hdd_change_country_code_callback, + country_code, adapter, + hdd_ctx->pcds_context, eSIR_TRUE, + eSIR_TRUE); + if (CDF_STATUS_SUCCESS == ret) { + rc = wait_for_completion_timeout( + &adapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) { + hddLog(LOGE, + FL("SME while setting country code timed out")); + } + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL( + "SME Change Country code from module param fail ret=%d" + ), + ret); + ret = -EINVAL; + } + } + + sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done); + +#ifdef FEATURE_OEM_DATA_SUPPORT + sme_register_oem_data_rsp_callback(hdd_ctx->hHal, + hdd_send_oem_data_rsp_msg); +#endif + + /* Open debugfs interface */ + if (CDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("hdd_debugfs_init failed!")); + } + + /* FW capabilities received, Set the Dot11 mode */ + sme_setdef_dot11mode(hdd_ctx->hHal); +#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(CDF_TRACE_LEVEL_ERROR, + FL("register_netdevice_notifier failed")); + goto err_free_power_on_lock; + } + reg_netdev_notifier_done = true; +#endif + /* Initialize the nlink service */ + if (nl_srv_init() != 0) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed")); + goto err_reg_netdev; + } +#ifdef WLAN_KD_READY_NOTIFIER + hdd_ctx->kd_nl_init = 1; +#endif /* WLAN_KD_READY_NOTIFIER */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + /* Initialize the OEM service */ + if (oem_activate_service(hdd_ctx) != 0) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("oem_activate_service failed")); + goto err_nl_srv; + } +#endif + +#ifdef PTT_SOCK_SVC_ENABLE + /* Initialize the PTT service */ + if (ptt_sock_activate_svc() != 0) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("ptt_sock_activate_svc failed")); + goto err_nl_srv; + } +#endif + + /* Initialize the CNSS-DIAG service */ + if (cnss_diag_activate_service() < 0) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("cnss_diag_activate_service failed")); + goto err_nl_srv; + } +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + if (hdd_ctx->config->wlanLoggingEnable) { + if (wlan_logging_sock_activate_svc + (hdd_ctx->config->wlanLoggingFEToConsole, + hdd_ctx->config->wlanLoggingNumBuf)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("wlan_logging_sock_activate_svc failed")); + goto err_nl_srv; + } + } +#endif + if (cds_is_multicast_logging()) + wlan_logging_set_log_level(); + + if (CDF_SAP_MODE != hdd_get_conparam()) { + /* + * Action frame registered in one adapter which will + * applicable to all interfaces + */ + wlan_hdd_cfg80211_register_frames(adapter); + } + + mutex_init(&hdd_ctx->sap_lock); + + hdd_ctx->isLoadInProgress = false; + +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) + if (rtnl_lock_enable == true) { + rtnl_lock_enable = false; + rtnl_unlock(); + } + ret = register_netdevice_notifier(&hdd_netdev_notifier); + if (ret < 0) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("register_netdevice_notifier failed")); + goto err_nl_srv; + } + reg_netdev_notifier_done = true; +#endif +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + /* Initialize the wake lcok */ + cdf_wake_lock_init(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock"); +#endif + /* Initialize the wake lcok */ + cdf_wake_lock_init(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock"); + + hdd_hostapd_channel_wakelock_init(hdd_ctx); + + cds_set_load_unload_in_progress(false); + + hdd_set_idle_ps_config(hdd_ctx, true); +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + if (hdd_ctx->config->WlanAutoShutdown != 0) + if (sme_set_auto_shutdown_cb + (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb) + != CDF_STATUS_SUCCESS) + hddLog(LOGE, + FL( + "Auto shutdown feature could not be enabled" + )); +#endif + +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + status = cdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer, + CDF_TIMER_TYPE_SW, + hdd_skip_acs_scan_timer_handler, + (void *)hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) + hddLog(LOGE, FL("Failed to init ACS Skip timer")); +#endif + + hdd_wlan_green_ap_init(hdd_ctx); + wlan_hdd_nan_init(hdd_ctx); + status = cds_init_policy_mgr(hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Policy manager initialization failed"); + goto err_nl_srv; + } + + /* Thermal Mitigation */ + thermalParam.smeThermalMgmtEnabled = + hdd_ctx->config->thermalMitigationEnable; + thermalParam.smeThrottlePeriod = hdd_ctx->config->throttlePeriod; + + thermalParam.smeThermalLevels[0].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel0; + thermalParam.smeThermalLevels[0].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel0; + thermalParam.smeThermalLevels[1].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel1; + thermalParam.smeThermalLevels[1].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel1; + thermalParam.smeThermalLevels[2].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel2; + thermalParam.smeThermalLevels[2].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel2; + thermalParam.smeThermalLevels[3].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel3; + thermalParam.smeThermalLevels[3].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel3; + + if (0 != hdd_lro_init(hdd_ctx)) + hdd_err("Unable to initialize LRO in fw"); + + if (CDF_STATUS_SUCCESS != + sme_init_thermal_info(hdd_ctx->hHal, thermalParam)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Error while initializing thermal information")); + } + + /* Plug in set thermal level callback */ + sme_add_set_thermal_level_callback(hdd_ctx->hHal, + (sme_set_thermal_level_callback)hdd_set_thermal_level_cb); + + /* SAR power limit */ + hddtxlimit = cdf_mem_malloc(sizeof(tSirTxPowerLimit)); + if (!hddtxlimit) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation for TxPowerLimit failed!")); + goto err_nl_srv; + } + hddtxlimit->txPower2g = hdd_ctx->config->TxPower2g; + hddtxlimit->txPower5g = hdd_ctx->config->TxPower5g; + + if (CDF_STATUS_SUCCESS != sme_txpower_limit(hdd_ctx->hHal, hddtxlimit)) + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Error setting txlimit in sme")); + +#ifdef MSM_PLATFORM + spin_lock_init(&hdd_ctx->bus_bw_lock); + cdf_mc_timer_init(&hdd_ctx->bus_bw_timer, + CDF_TIMER_TYPE_SW, + hdd_bus_bw_compute_cbk, (void *)hdd_ctx); +#endif + +#ifdef WLAN_FEATURE_STATS_EXT + wlan_hdd_cfg80211_stats_ext_init(hdd_ctx); +#endif +#ifdef FEATURE_WLAN_EXTSCAN + sme_ext_scan_register_callback(hdd_ctx->hHal, + wlan_hdd_cfg80211_extscan_callback); +#endif /* FEATURE_WLAN_EXTSCAN */ + sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal, + hdd_rssi_threshold_breached); +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + wlan_hdd_cfg80211_link_layer_stats_init(hdd_ctx); +#endif + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_all_scan_intf_info(hdd_ctx); + wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version, + hdd_ctx->target_hw_version, + hdd_ctx->target_hw_name); +#endif + + cdf_spinlock_init(&hdd_ctx->hdd_roc_req_q_lock); + cdf_list_init((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY); + cdf_spinlock_init(&hdd_ctx->hdd_scan_req_q_lock); + cdf_list_init((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX); +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&hdd_ctx->roc_req_work, + wlan_hdd_roc_request_dequeue); +#else + INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue); +#endif + + /* + * Register IPv6 notifier to notify if any change in IP + * So that we can reconfigure the offload parameters + */ + hdd_wlan_register_ip6_notifier(hdd_ctx); + + /* + * Register IPv4 notifier to notify if any change in IP + * So that we can reconfigure the offload parameters + */ + hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; + ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier); + if (ret) + hddLog(LOGE, FL("Failed to register IPv4 notifier")); + else + hddLog(LOGE, FL("Registered IPv4 notifier")); + + wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx); + + if (hdd_ctx->config->dual_mac_feature_disable) { + status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("Failed to disable dual mac features"); + goto err_nl_srv; + } + } + + hif_enable_power_gating(hif_sc); + + complete(&wlan_start_comp); + goto success; + +err_nl_srv: +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + ptt_sock_deactivate_svc(); +#endif /* WLAN_KD_READY_NOTIFIER */ + nl_srv_exit(); + + if (!CDF_IS_STATUS_SUCCESS + (cdf_mutex_destroy(&hdd_ctx->hdd_conc_list_lock))) { + hdd_err("Failed to destroy hdd_conc_list_lock"); + /* Proceed and complete the clean up */ + } +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 + hdd_debugfs_exit(hdd_ctx); + +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(hdd_ctx); + +err_cds_disable: + cds_disable(p_cds_context); + +err_wiphy_unregister: + wiphy_unregister(wiphy); + +err_cds_close: + status = cds_sched_close(p_cds_context); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to close CDS Scheduler")); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); + } + cds_close(p_cds_context); + +err_cds_open: + + if (CDF_FTM_MODE == hdd_get_conparam()) { +#if defined(QCA_WIFI_FTM) +err_free_ftm_open: + wlan_hdd_ftm_close(hdd_ctx); +#endif + } + +err_config: + kfree(hdd_ctx->config); + hdd_ctx->config = NULL; + +err_free_hdd_context: + /* wiphy_free() will free the HDD context so remove global reference */ + if (p_cds_context) + ((cds_context_type *) (p_cds_context))->pHDDContext = NULL; + + wiphy_free(wiphy); + /* kfree(wdev) ; */ + CDF_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(false); + + return -EIO; + +success: + EXIT(); + return 0; +} + +/* + * 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 durint driver load for reducing interrupt latency. + */ + +#ifdef CONFIG_CNSS +static inline void hdd_request_pm_qos(int val) +{ + cnss_request_pm_qos(val); +} + +static inline void hdd_remove_pm_qos(void) +{ + cnss_remove_pm_qos(); +} +#else +static inline void hdd_request_pm_qos(int val) +{ +} + +static inline void hdd_remove_pm_qos(void) +{ +} +#endif + +/** + * hdd_driver_init() - Core Driver Init Function + * + * This is the driver entry point - called in different timeline depending + * on whether the driver is statically or dynamically linked + * + * Return: 0 for success, non zero for failure + */ +static int hdd_driver_init(void) +{ + CDF_STATUS status; + v_CONTEXT_t p_cds_context = NULL; + int ret_status = 0; + unsigned long rc; + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_init_svc(); +#endif + + ENTER(); + + cdf_wake_lock_init(&wlan_wake_lock, "wlan"); + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + /* + * The Krait is going to Idle/Stand Alone Power Save + * more aggressively which is resulting in the longer driver load time. + * The Fix is to not allow Krait to enter Idle Power Save during driver + * load. + */ + hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); + cds_ssr_protect_init(); + + pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + + do { + cdf_mc_timer_manager_init(); + cdf_mem_init(); + /* Allocate CDS global context */ + status = cds_alloc_global_context(&p_cds_context); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to preOpen CDS")); + ret_status = -1; + break; + } + + hdd_trace_init(); + +#ifndef MODULE + /* + * For statically linked driver, call hdd_set_conparam to update + * curr_con_mode + */ + hdd_set_conparam((uint32_t) con_mode); +#endif + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define HDD_WLAN_START_WAIT_TIME (3600 * 1000) +#else +#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) +#endif + + init_completion(&wlan_start_comp); + ret_status = wlan_hdd_register_driver(); + if (!ret_status) { + rc = wait_for_completion_timeout( + &wlan_start_comp, + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); + if (!rc) { + hddLog(LOGP, + FL("timed-out waiting for wlan_hdd_register_driver")); + ret_status = -1; + } else + ret_status = 0; + } + + hdd_remove_pm_qos(); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + + if (ret_status) { + hddLog(LOGP, FL("WLAN Driver Initialization failed")); + wlan_hdd_unregister_driver(); + cds_free_global_context(&p_cds_context); + ret_status = -ENODEV; + break; + } else { + pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); + memdump_init(); + return 0; + } + + } while (0); + + if (0 != ret_status) { + cdf_mc_timer_exit(); + cdf_mem_exit(); + cdf_wake_lock_destroy(&wlan_wake_lock); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif + memdump_deinit(); + pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); + } else { + pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); + } + + EXIT(); + + return ret_status; +} + +/** + * hdd_module_init() - Init Function + * + * This is the driver entry point (invoked when module is loaded using insmod) + * + * 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 */ + +/** + * hdd_driver_exit() - Exit function + * + * This is the driver exit point (invoked when module is unloaded using rmmod + * or con_mode was changed by userspace) + * + * Return: None + */ +static void hdd_driver_exit(void) +{ + hdd_context_t *hdd_ctx = NULL; + int retry = 0; + + pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR); + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("module exit called before probe")); + } else { +#ifdef QCA_PKT_PROTO_TRACE + cds_pkt_proto_trace_close(); +#endif /* QCA_PKT_PROTO_TRACE */ + while (hdd_ctx->isLogpInProgress || + cds_is_logp_in_progress()) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "SSR in Progress; block rmmod for 1 second!!!" + )); + msleep(1000); + + if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("SSR never completed, fatal error")); + CDF_BUG(0); + } + } + + rtnl_lock(); + hdd_ctx->isUnloadInProgress = true; + cds_set_load_unload_in_progress(true); + rtnl_unlock(); + } + + cds_wait_for_work_thread_completion(__func__); + memdump_deinit(); + + wlan_hdd_unregister_driver(); + return; +} + +/** + * hdd_module_exit() - Exit function + * + * This is the driver exit point (invoked when module is unloaded using rmmod) + * + * 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 */ +/** + * kickstart_driver() - driver entry point + * + * This is the driver entry point + * - delayed driver initialization when driver is statically linked + * - invoked when module parameter fwpath is modified from userspace to signal + * initializing the WLAN driver or when con_mode is modified from userspace + * to signal a switch in operating mode + * + * Return: 0 for success, non zero for failure + */ +static int kickstart_driver(void) +{ + int ret_status; + + 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; +} + +/** + * 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(); + return ret; +} + +#if !defined(QCA_WIFI_FTM) +/** + * con_mode_handler() - handls module param con_mode change + * + * Handler function for module param con_mode when it is changed by userspace + * Dynamically linked - do nothing + * Statically linked - exit and init driver, as in rmmod and insmod + * + * 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(); + return ret; +} +#endif +#endif /* #ifdef MODULE */ + +/** + * hdd_get_conparam() - driver exit point + * + * This is the driver exit point (invoked when module is unloaded using rmmod) + * + * Return: tCDF_CON_MODE + */ +tCDF_CON_MODE hdd_get_conparam(void) +{ +#ifdef MODULE + return (tCDF_CON_MODE) con_mode; +#else + return (tCDF_CON_MODE) curr_con_mode; +#endif +} + +void hdd_set_conparam(uint32_t newParam) +{ + con_mode = newParam; +#ifndef MODULE + curr_con_mode = con_mode; +#endif +} + +/** + * hdd_softap_sta_deauth() - handle deauth req from HDD + * @adapter: Pointer to the HDD + * @enable: bool value + * + * This to take counter measure to handle deauth req from HDD + * + * Return: None + */ +CDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter, + struct tagCsrDelStaParams *pDelStaParams) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; +#endif + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; + + ENTER(); + + hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); + + /* Ignore request to deauth bcmc station */ + if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) + return cdf_status; + +#ifdef WLAN_FEATURE_MBSSID + cdf_status = + wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + pDelStaParams); +#else + cdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams); +#endif + + EXIT(); + return cdf_status; +} + +/** + * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD + * @adapter: Pointer to the HDD + * + * This to take counter measure to handle deauth req from HDD + * + * Return: None + */ +void hdd_softap_sta_disassoc(hdd_adapter_t *adapter, + uint8_t *pDestMacAddress) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; +#endif + + ENTER(); + + hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); + + /* Ignore request to disassoc bcmc station */ + if (pDestMacAddress[0] & 0x1) + return; + +#ifdef WLAN_FEATURE_MBSSID + wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + pDestMacAddress); +#else + wlansap_disassoc_sta(p_cds_context, pDestMacAddress); +#endif +} + +void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter, + bool enable) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; +#endif + + ENTER(); + + hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); + +#ifdef WLAN_FEATURE_MBSSID + wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + (bool) enable); +#else + wlansap_set_counter_measure(p_cds_context, (bool) enable); +#endif +} + +/** + * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected + * @hdd_ctx: HDD Context + * + * API to find if there is any STA or P2P-Client is connected + * + * Return: true if connected; false otherwise + */ +CDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx) +{ + return sme_is_sta_p2p_client_connected(hdd_ctx->hHal); +} + +#ifdef WLAN_FEATURE_LPSS +int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data, + hdd_adapter_t *adapter, + hdd_station_ctx_t *pHddStaCtx, + uint8_t is_on, uint8_t is_connected) +{ + hdd_context_t *hdd_ctx = NULL; + uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN; + + if (!data) { + hddLog(LOGE, FL("invalid data pointer")); + return -EINVAL; + } + if (!adapter) { + if (is_on) { + /* no active interface */ + data->lpss_support = 0; + data->is_on = is_on; + return 0; + } + hddLog(LOGE, FL("invalid adapter pointer")); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (hdd_ctx->lpss_support && hdd_ctx->config->enablelpasssupport) + data->lpss_support = 1; + else + data->lpss_support = 0; + data->numChannels = WLAN_SVC_MAX_NUM_CHAN; + sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list, + &data->numChannels); + sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen); + data->is_on = is_on; + data->vdev_id = adapter->sessionId; + data->vdev_mode = adapter->device_mode; + if (pHddStaCtx) { + data->is_connected = is_connected; + data->rssi = adapter->rssi; + data->freq = + cds_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 (CDF_MAC_ADDR_SIZE >= + sizeof(pHddStaCtx->conn_info.bssId)) + memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + } + return 0; +} + +int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data, + uint32_t fw_version, + uint32_t chip_id, const char *chip_name) +{ + if (!data) { + hddLog(LOGE, FL("invalid data pointer")); + return -EINVAL; + } + + 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) +/** + * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one + * @adapter: HDD adapter pointer + * + * 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. + * + * Return: None + */ +void wlan_hdd_disable_roaming(hdd_adapter_t *adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_adapter_t *adapterIdx = NULL; + hdd_adapter_list_node_t *adapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + CDF_STATUS status; + + if (hdd_ctx->config->isFastRoamIniFeatureEnabled && + hdd_ctx->config->isRoamOffloadScanEnabled && + WLAN_HDD_INFRA_STATION == adapter->device_mode && + cds_is_sta_active_connection_exists()) { + hddLog(LOG1, FL("Connect received on STA sessionId(%d)"), + adapter->sessionId); + /* + * Loop through adapter and disable roaming for each STA device + * mode except the input adapter. + */ + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapterIdx = adapterNode->pAdapter; + + if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode + && adapter->sessionId != adapterIdx->sessionId) { + hddLog(LOG1, + FL("Disable Roaming on sessionId(%d)"), + adapterIdx->sessionId); + sme_stop_roaming(WLAN_HDD_GET_HAL_CTX + (adapterIdx), + adapterIdx->sessionId, 0); + } + + status = hdd_get_next_adapter(hdd_ctx, + adapterNode, + &pNext); + adapterNode = pNext; + } + } +} + +/** + * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one + * @adapter: HDD adapter pointer + * + * 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. + * + * Return: None + */ +void wlan_hdd_enable_roaming(hdd_adapter_t *adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_adapter_t *adapterIdx = NULL; + hdd_adapter_list_node_t *adapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + CDF_STATUS status; + + if (hdd_ctx->config->isFastRoamIniFeatureEnabled && + hdd_ctx->config->isRoamOffloadScanEnabled && + WLAN_HDD_INFRA_STATION == adapter->device_mode && + cds_is_sta_active_connection_exists()) { + hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"), + adapter->sessionId); + /* + * Loop through adapter and enable roaming for each STA device + * mode except the input adapter. + */ + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapterIdx = adapterNode->pAdapter; + + if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode + && adapter->sessionId != adapterIdx->sessionId) { + hddLog(LOG1, + FL("Enabling Roaming on sessionId(%d)"), + adapterIdx->sessionId); + sme_start_roaming(WLAN_HDD_GET_HAL_CTX + (adapterIdx), + adapterIdx->sessionId, + REASON_CONNECT); + } + + status = hdd_get_next_adapter(hdd_ctx, + adapterNode, + &pNext); + adapterNode = 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) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed")); + 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: + 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: + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("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 *adapter, + hdd_station_ctx_t *pHddStaCtx, + uint8_t is_on, uint8_t is_connected) +{ + int ret = 0; + struct wlan_status_data data; + + if (CDF_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, adapter, 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(uint32_t fw_version, + uint32_t chip_id, const char *chip_name) +{ + int ret = 0; + struct wlan_version_data data; +#ifdef CONFIG_CNSS + struct cnss_platform_cap cap; + + ret = cnss_get_platform_cap(&cap); + if (ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("platform capability info from CNSS not available")); + return; + } + + if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS)) + return; +#endif + + if (CDF_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 *hdd_ctx) +{ + hdd_adapter_t *pDataAdapter = NULL; + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + bool scan_intf_found = false; + CDF_STATUS status; + + if (!hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("NULL pointer for hdd_ctx")); + return; + } + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + pDataAdapter = adapterNode->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 = true; + wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, + 0); + } + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + if (!scan_intf_found) + wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0); +} +#endif + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +void wlan_hdd_auto_shutdown_cb(void) +{ + hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event..")); + 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, bool enable) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *adapter; + bool ap_connected = false, sta_connected = false; + tHalHandle hal_handle; + + hal_handle = hdd_ctx->hHal; + if (hal_handle == NULL) + return; + + if (hdd_ctx->config->WlanAutoShutdown == 0) + return; + + if (enable == false) { + if (sme_set_auto_shutdown_timer(hal_handle, 0) != + CDF_STATUS_SUCCESS) { + hddLog(LOGE, + FL("Failed to stop wlan auto shutdown timer")); + } + return; + } + + /* To enable shutdown timer check conncurrency */ + if (cds_concurrent_open_sessions_running()) { + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if (adapter + && adapter->device_mode == + WLAN_HDD_INFRA_STATION) { + if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)-> + conn_info.connState == + eConnectionState_Associated) { + sta_connected = true; + break; + } + } + if (adapter + && adapter->device_mode == WLAN_HDD_SOFTAP) { + if (WLAN_HDD_GET_AP_CTX_PTR(adapter)-> + bApActive == true) { + ap_connected = true; + break; + } + } + status = hdd_get_next_adapter(hdd_ctx, + adapterNode, + &pNext); + adapterNode = pNext; + } + } + + if (ap_connected == true || sta_connected == true) { + hddLog(LOG1, + FL("CC Session active. Shutdown timer not enabled")); + return; + } else { + if (sme_set_auto_shutdown_timer(hal_handle, + hdd_ctx->config-> + WlanAutoShutdown) + != CDF_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->config->WlanAutoShutdown); + + } +} +#endif + +hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter, + bool check_start_bss) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter); + hdd_adapter_t *adapter, *con_sap_adapter; + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + + con_sap_adapter = NULL; + + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) || + (adapter->device_mode == WLAN_HDD_P2P_GO)) && + adapter != this_sap_adapter) { + if (check_start_bss) { + if (test_bit(SOFTAP_BSS_STARTED, + &adapter->event_flags)) { + con_sap_adapter = adapter; + break; + } + } else { + con_sap_adapter = adapter; + break; + } + } + status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); + adapterNode = pNext; + } + + return con_sap_adapter; +} + +#ifdef MSM_PLATFORM +void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) + return; + + cdf_mc_timer_start(&hdd_ctx->bus_bw_timer, + hdd_ctx->config->busBandwidthComputeInterval); +} + +void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter) +{ + hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + bool can_stop = true; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (CDF_TIMER_STATE_RUNNING != + cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) { + /* trying to stop timer, when not running is not good */ + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("bus band width compute timer is not running")); + return; + } + + if (cds_concurrent_open_sessions_running()) { + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); + + while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { + adapter = adapterNode->pAdapter; + if (adapter + && (adapter->device_mode == WLAN_HDD_INFRA_STATION + || adapter->device_mode == WLAN_HDD_P2P_CLIENT) + && WLAN_HDD_GET_STATION_CTX_PTR(adapter)-> + conn_info.connState == + eConnectionState_Associated) { + can_stop = false; + break; + } + if (adapter + && (adapter->device_mode == WLAN_HDD_SOFTAP + || adapter->device_mode == WLAN_HDD_P2P_GO) + && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == + true) { + can_stop = false; + break; + } + status = hdd_get_next_adapter(hdd_ctx, + adapterNode, + &pNext); + adapterNode = pNext; + } + } + + if (can_stop == true) + cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer); +} +#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: CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE. + */ +CDF_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; + CDF_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 ((CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_ERROR, + FL("Finding AP from scan cache failed")); + return CDF_STATUS_E_FAILURE; + } + return CDF_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: None + */ +void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx; +#ifdef CFG80211_DEL_STA_V2 + struct station_del_parameters delStaParams; +#endif + + if (NULL == ap_adapter) { + hddLog(CDF_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)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + 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); + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Now doing SAP STOPBSS")); + cdf_event_reset(&hostapd_state->cdf_stop_bss_event); + if (CDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx-> + sapContext)) { + cdf_status = cdf_wait_single_event(&hostapd_state-> + cdf_stop_bss_event, + BSS_WAIT_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + mutex_unlock(&hdd_ctx->sap_lock); + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("SAP Stop Failed")); + return; + } + } + clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + cds_decr_session_set_pcl(hdd_ctx, + ap_adapter->device_mode, + ap_adapter->sessionId); + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("SAP Stop Success")); + } else { + hddLog(CDF_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: None + */ +void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx; + tsap_Config_t *sap_config; + + if (NULL == ap_adapter) { + hddLog(CDF_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); + sap_config = &ap_adapter->sessionCtx.ap.sapConfig; + + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + 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_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); + goto end; + } + + if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb, + &hdd_ap_ctx->sapConfig, + ap_adapter->dev) + != CDF_STATUS_SUCCESS) + goto end; + + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Waiting for SAP to start")); + cdf_status = cdf_wait_single_event(&hostapd_state->cdf_event, + BSS_WAIT_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("SAP Start failed")); + goto end; + } + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success")); + set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, + ap_adapter->sessionId); + hostapd_state->bCommit = true; + +end: + mutex_unlock(&hdd_ctx->sap_lock); + return; +} +#endif + +/** + * hdd_wlan_get_wake_lock_ptr(): get HDD's wake lock pointer + * + * This function returns the wake lock pointer to the caller + * + * Return: cdf_wake_lock_t + */ +cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void) +{ + return &wlan_wake_lock; +} + +/** + * 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; +} + +#ifdef QCA_CONFIG_SMP +/** + * wlan_hdd_get_cpu() - get cpu_index + * + * Return: cpu_index + */ +int wlan_hdd_get_cpu(void) +{ + 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/core/hdd/src/wlan_hdd_memdump.c b/core/hdd/src/wlan_hdd_memdump.c new file mode 100644 index 000000000000..d1ad781ed929 --- /dev/null +++ b/core/hdd/src/wlan_hdd_memdump.c @@ -0,0 +1,647 @@ +/* + * 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 +#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; + cdf_dma_addr_t paddr; + cdf_dma_addr_t dma_ctx = 0; + cdf_device_t cdf_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; + } + + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + if (!cdf_ctx) { + hddLog(LOGE, FL("CDF context is NULL")); + return; + } + + paddr = hdd_ctx->dump_loc_paddr; + mutex_lock(&hdd_ctx->memdump_lock); + cdf_os_mem_free_consistent(cdf_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; + CDF_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; + cdf_dma_addr_t paddr; + cdf_dma_addr_t dma_ctx = 0; + cdf_device_t cdf_ctx; + unsigned long rc; + struct hdd_fw_dump_context *context; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return status; + } + + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + if (!cdf_ctx) { + hddLog(LOGE, FL("CDF 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 = cdf_os_mem_alloc_consistent( + cdf_ctx, FW_MEM_DUMP_SIZE, &paddr, dma_ctx); + if (!hdd_ctx->fw_dump_loc) { + mutex_unlock(&hdd_ctx->memdump_lock); + hddLog(LOGE, FL("cdf_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. + */ + cdf_mc_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 (CDF_STATUS_SUCCESS != sme_status) { + hddLog(LOGE, FL("sme_fw_mem_dump Failed")); + mutex_lock(&hdd_ctx->memdump_lock); + cdf_os_mem_free_consistent(cdf_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 (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &hdd_ctx->memdump_cleanup_timer)) { + cdf_mc_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_fw_mem_dump(wiphy, wdev, data, data_len); + cds_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; + cdf_dma_addr_t paddr; + cdf_dma_addr_t dma_ctx = 0; + cdf_device_t cdf_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; + } + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + if (!cdf_ctx) { + hddLog(LOGE, FL("CDF 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); + cdf_os_mem_free_consistent(cdf_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 (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &hdd_ctx->memdump_cleanup_timer)) { + cdf_mc_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 + * + * 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) +{ + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + 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; + int status = 0; + CDF_STATUS cb_status; + CDF_STATUS cdf_status; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hddLog(LOGE , FL("Invalid HDD context")); + return -EINVAL; + } + + if (CDF_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 (CDF_STATUS_SUCCESS != cb_status) { + hddLog(LOGE , FL("Failed to register the callback")); + return -EINVAL; + } + + status = memdump_procfs_init(); + if (status) { + hddLog(LOGE , FL("Failed to create proc file")); + return status; + } + + init_completion(&fw_dump_context.response_event); + + cdf_status = cdf_mc_timer_init(&hdd_ctx->memdump_cleanup_timer, + CDF_TIMER_TYPE_SW, memdump_cleanup_timer_cb, + (void *)hdd_ctx); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("Failed to init memdump cleanup timer")); + return -EINVAL; + } + + mutex_init(&hdd_ctx->memdump_lock); + + return 0; +} + +/** + * memdump_deinit() - De initialize memdump feature + * + * This function removes proc file created for memdump feature. + * + * Return: None + */ +void memdump_deinit(void) +{ + hdd_context_t *hdd_ctx; + cdf_dma_addr_t paddr; + cdf_dma_addr_t dma_ctx = 0; + cdf_device_t cdf_ctx; + CDF_STATUS cdf_status; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hddLog(LOGE , FL("Invalid HDD context")); + return; + } + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Not deinitializing memdump in FTM mode")); + return; + } + + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + if (!cdf_ctx) { + hddLog(LOGE, FL("CDF 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; + cdf_os_mem_free_consistent(cdf_ctx, + FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); + hdd_ctx->fw_dump_loc = NULL; + hdd_ctx->memdump_in_progress = false; + } + mutex_unlock(&hdd_ctx->memdump_lock); + + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&hdd_ctx->memdump_cleanup_timer)) { + cdf_mc_timer_stop(&hdd_ctx->memdump_cleanup_timer); + } + + cdf_status = cdf_mc_timer_destroy(&hdd_ctx->memdump_cleanup_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hddLog(LOGE, FL("Failed to deallocate timer")); +} diff --git a/core/hdd/src/wlan_hdd_nan.c b/core/hdd/src/wlan_hdd_nan.c new file mode 100644 index 000000000000..4fff12bd158d --- /dev/null +++ b/core/hdd/src/wlan_hdd_nan.c @@ -0,0 +1,194 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_nan.c + * + * WLAN Host Device Driver NAN API implementation + */ + +#include +#include +#include +#include +#include +#include "sme_api.h" +#include "nan_api.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_nan.h" + +/** + * __wlan_hdd_cfg80211_nan_request() - cfg80211 NAN request handler + * @wiphy: driver's wiphy struct + * @wdev: wireless device to which the request is targeted + * @data: actual request data (netlink-encapsulated) + * @data_len: length of @data + * + * This is called when userspace needs to send a nan request to + * firmware. The wlan host driver simply de-encapsulates the + * request from the netlink payload and then forwards it to + * firmware via SME. + * + * 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; + CDF_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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (!hdd_ctx->config->enable_nan_support) { + hdd_err("NaN support is not enabled in INI"); + return -EPERM; + } + + nan_req.request_data_len = data_len; + nan_req.request_data = data; + + status = sme_nan_request(&nan_req); + if (CDF_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 + */ +int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) + +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_nan_request(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_nan_callback() - cfg80211 NAN event handler + * @ctx: global HDD context + * @msg: NAN event message + * + * This is a callback function and it gets called when we need to report + * a nan event to userspace. The wlan host driver simply encapsulates the + * event into a netlink payload and then forwards it to userspace via a + * cfg80211 vendor event. + * + * Return: nothing + */ +static void wlan_hdd_cfg80211_nan_callback(void *ctx, tSirNanEvent *msg) +{ + hdd_context_t *hdd_ctx = ctx; + struct sk_buff *vendor_event; + int status; + + if (NULL == msg) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("msg received here is null")); + return; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return; + } + + vendor_event = + cfg80211_vendor_event_alloc(hdd_ctx->wiphy, + NULL, + msg->event_data_len + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return; + } + if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NAN, + msg->event_data_len, msg->event_data)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR_NAN put fail")); + kfree_skb(vendor_event); + return; + } + cfg80211_vendor_event(vendor_event, GFP_KERNEL); +} + +/** + * wlan_hdd_nan_is_supported() - HDD NAN support query function + * + * This function is called to determine if NAN is supported by the + * driver and by the firmware. + * + * Return: true if NAN is supported by the driver and firmware + */ +bool wlan_hdd_nan_is_supported(void) +{ + return sme_is_feature_supported_by_fw(NAN); +} + +/** + * wlan_hdd_nan_init() - HDD NAN initialization function + * @hdd_ctx: Global HDD context + * + * This function is called to initialize the HDD NAN feature. Currently + * the only operation required is to register a callback with SME. + * + * Return: void + */ +void wlan_hdd_nan_init(hdd_context_t *hdd_ctx) +{ + sme_nan_register_callback(hdd_ctx->hHal, + wlan_hdd_cfg80211_nan_callback); +} diff --git a/core/hdd/src/wlan_hdd_napi.c b/core/hdd/src/wlan_hdd_napi.c new file mode 100644 index 000000000000..4bca8b9a22a3 --- /dev/null +++ b/core/hdd/src/wlan_hdd_napi.c @@ -0,0 +1,262 @@ +/* + * 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_napi.c + * + * WLAN HDD NAPI interface implementation + */ +#include /* get_cpu */ + +#include "wlan_hdd_napi.h" +#include "cds_api.h" /* cds_get_context */ +#include "hif.h" /* hif_map_service...*/ +#include "wlan_hdd_main.h" /* hdd_err/warn... */ +#include "cdf_types.h" /* CDF_MODULE_ID_... */ +#include "ce_api.h" + +/* guaranteed to be initialized to zero/NULL by the standard */ +static struct qca_napi_data *hdd_napi_ctx; + +/** + * hdd_napi_get_all() - return the whole NAPI structure from HIF + * + * Gets to the data structure common to all NAPI instances. + * + * Return: + * NULL : probably NAPI not initialized yet. + * : the address of the whole NAPI structure + */ +struct qca_napi_data *hdd_napi_get_all(void) +{ + struct qca_napi_data *rp; + struct ol_softc *hif; + + NAPI_DEBUG("-->\n"); + + hif = cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif != NULL); + rp = hif_napi_get_all(hif); + + NAPI_DEBUG("<-- [addr=%p]\n", rp); + return rp; +} + +/** + * hdd_napi_get_map() - get a copy of napi pipe map + * + * Return: + * uint32_t : copy of pipe map + */ +static uint32_t hdd_napi_get_map(void) +{ + uint32_t map; + + NAPI_DEBUG("-->\n"); + /* cache once, use forever */ + if (hdd_napi_ctx == NULL) + hdd_napi_ctx = hdd_napi_get_all(); + map = hdd_napi_ctx->ce_map; + + NAPI_DEBUG("<--[map=0x%08x]\n", map); + return map; +} + +/** + * hdd_napi_create() - creates the NAPI structures for a given netdev + * + * Creates NAPI instances. This function is called + * unconditionally during initialization. It creates + * napi structures through the proper HTC/HIF calls. + * The structures are disabled on creation. + * + * Return: + * single-queue: <0: err, >0=id, 0 (should not happen) + * multi-queue: bitmap of created instances (0: none) + */ +int hdd_napi_create(void) +{ + struct ol_softc *hif_ctx; + uint8_t ul, dl; + int ul_polled, dl_polled; + int rc = 0; + + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif_ctx != NULL); + + NAPI_DEBUG("-->\n"); + + /* + * hif_service_to_pipe currently returns one pipe id per service. + * However for Adrestea, we will need to figure out how to map + * DATA service to multiple pipes. Either we will need to create + * family of services, or this function may return a bitmap (of + * at least #MAX_CEs bits) and then we will need to iterate on + * the bitmap for hif_napi_create() calls. + * For Rome, there is only one service, so there is a single call + * TODO: clarify for multi-queue/Adrestea + */ + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(hif_ctx, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + hdd_err("cannot map service to pipe"); + rc = -EINVAL; + } else { + rc = hif_napi_create(hif_ctx, dl, hdd_napi_poll, + QCA_NAPI_BUDGET, QCA_NAPI_DEF_SCALE); + if (rc < 0) + hdd_err("ERR(%d) creating NAPI on pipe %d", rc, dl); + else { + hdd_info("napi instance %d created on pipe %d", + rc, dl); + /* rc = (0x01 << rc); -- phase 2 */ + } + } + NAPI_DEBUG("<-- [rc=%d]\n", rc); + + return rc; +} + +/** + * hdd_napi_destroy() - destroys the NAPI structures for a given netdev + * @force: if set, will force-disable the instance before _del'ing + * + * Destroy NAPI instances. This function is called + * unconditionally during module removal. It destroy + * napi structures through the proper HTC/HIF calls. + * + * Return: + * number of NAPI instances destroyed + */ +int hdd_napi_destroy(int force) +{ + int rc = 0; + int i; + uint32_t hdd_napi_map = hdd_napi_get_map(); + + NAPI_DEBUG("--> (force=%d)\n", force); + if (hdd_napi_map) { + struct ol_softc *hif_ctx; + + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif_ctx != NULL); + + for (i = 0; i < (sizeof(uint32_t)*8); i++) + if (hdd_napi_map & (0x01 << i)) { + if (0 <= hif_napi_destroy(hif_ctx, + NAPI_PIPE2ID(i), + force)) { + rc++; + hdd_napi_map &= ~(0x01 << i); + } else + hdd_err("cannot destroy napi inst %d: (pipe:%d), f=%d\n", + i, NAPI_PIPE2ID(i), force); + } + } + + /* if all instances are removed, it is likely that hif_context has been + * removed as well, so the cached value of the napi context also needs + * to be removed + */ + if (force) + CDF_ASSERT(hdd_napi_map == 0); + if (0 == hdd_napi_map) + hdd_napi_ctx = NULL; + + NAPI_DEBUG("<-- [rc=%d]\n", rc); + return rc; +} + +/** + * hdd_napi_enabled() - checks if NAPI is enabled (for a given id) + * @id: the id of the NAPI to check (any= -1) + * + * Return: + * int: 0 = false (NOT enabled) + * !0 = true (enabbled) + */ +inline int hdd_napi_enabled(int id) +{ + struct ol_softc *hif; + + hif = cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif != NULL); + if (-1 == id) + return hif_napi_enabled(hif, id); + else + return hif_napi_enabled(hif, NAPI_ID2PIPE(id)); +} + +/** + * hdd_napi_event() - relay the event detected by HDD to HIF NAPI decision maker + * @event: event code + * @data : event-specific auxiliary data + * + * Return code does not indicate a change, but whether or not NAPI is + * enabled at the time of the return of the function. That is, if NAPI + * was disabled before the call, and the event does not cause NAPI to be + * enabled, a value of 0 will be returned indicating that it is (still) + * disabled. + * + * Return: + * < 0: error code + * = 0: NAPI state = disabled (after processing the event) + * = 1: NAPI state = enabled (after processing the event) + */ +int hdd_napi_event(enum qca_napi_event event, void *data) +{ + int rc; + struct ol_softc *hif; + + NAPI_DEBUG("-->(event=%d, aux=%p)\n", event, data); + + hif = cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif != NULL); + rc = hif_napi_event(hif, event, data); + + NAPI_DEBUG("<--[rc=%d]\n", rc); + return rc; +} + +/** + * hdd_napi_poll() - NAPI poll function + * @napi : pointer to NAPI struct + * @budget: the pre-declared budget + * + * Implementation of poll function. This function is called + * by kernel during softirq processing. + * + * NOTE FOR THE MAINTAINER: + * Make sure this is very close to the ce_tasklet code. + * + * Return: + * int: the amount of work done ( <= budget ) + */ +int hdd_napi_poll(struct napi_struct *napi, int budget) +{ + return hif_napi_poll(napi, budget); +} diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c new file mode 100644 index 000000000000..a34959d2f292 --- /dev/null +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -0,0 +1,2112 @@ +/* + * 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: wlan_hdd_ocb.c + * + * WLAN Host Device Driver 802.11p OCB implementation + */ + +#include "cds_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 "sch_api.h" +#include "wma_api.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->config->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; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) || \ + defined(FEATURE_STATICALLY_ADD_11P_CHANNELS) +/* + * 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) +#endif + +#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS + +#define DOT11P_TX_PWR_MAX 30 +#define DOT11P_TX_ANTENNA_MAX 6 +#define NUM_DOT11P_CHANNELS 10 +/** + * 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) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + struct ol_txrx_desc_type 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); + uint8_t peer_id; + + cdf_status = ol_txrx_register_ocb_peer(hdd_ctx->pcds_context, + adapter->macAddressCurrent.bytes, + &peer_id); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("Error registering OCB Self Peer!")); + return -EINVAL; + } + + hdd_ctx->sta_to_adapter[peer_id] = adapter; + + sta_desc.sta_id = peer_id; + sta_desc.is_qos_enabled = 1; + + cdf_status = ol_txrx_register_peer(hdd_rx_packet_cbk, + &sta_desc); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("Failed to register. Status= %d [0x%08X]"), + cdf_status, cdf_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; + cdf_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 = cdf_mem_malloc(len); + if (!cursor) + goto fail; + + cdf_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: + cdf_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; + CDF_STATUS cdf_status; + 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 */ + cdf_status = sme_ocb_set_config( + ((hdd_context_t *)adapter->pHddCtx)->hHal, &context, + hdd_ocb_set_config_callback, config); + if (cdf_status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error calling SME function.")); + /* Convert from ecdf_status 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; + struct sir_ocb_config_channel *curr_chan; + + 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; + + curr_chan = &(config->channels[config->channel_count]); + + curr_chan->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. + */ + curr_chan->max_pwr = sched->channels[i].tx_power / 2; + curr_chan->bandwidth = sched->channels[i].channel_bandwidth; + /* assume 10 as default if not provided */ + if (curr_chan->bandwidth == 0) + curr_chan->bandwidth = 10; + + /* + * Setup locally administered mac addresses for each channel. + * First channel uses the adapter's address. + */ + if (i == 0) { + cdf_mem_copy(curr_chan->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; + } + cdf_mem_copy(config->channels[ + config->channel_count].mac_address, + mac_addr, sizeof(tSirMacAddr)); + /* Save the mac address to release later */ + cdf_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++) { + curr_chan->qos_params[j].aifsn = + sched->channels[i].qos_params[j].aifsn; + curr_chan->qos_params[j].cwmin = + sched->channels[i].qos_params[j].cwmin; + curr_chan->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: + cdf_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; + + cds_ssr_protect(__func__); + ret = __iw_set_dot11p_channel_sched(dev, info, wrqu, extra); + cds_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]; + struct sir_qos_params 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; + + cdf_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; + cdf_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 (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) { + cdf_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; + } + cdf_mem_copy(config->channels[i].mac_address, + mac_addr, sizeof(tSirMacAddr)); + /* Save the mac address to release later */ + cdf_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; + } + cdf_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; + cdf_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; + cdf_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: + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_set_config(wiphy, wdev, data, data_len); + cds_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 (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 = cdf_mem_malloc(sizeof(*utc)); + if (!utc) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + utc->vdev_id = adapter->sessionId; + cdf_mem_copy(utc->utc_time, nla_data(utc_attr), SIZE_UTC_TIME); + cdf_mem_copy(utc->time_error, nla_data(time_error_attr), + SIZE_UTC_TIME_ERROR); + + if (sme_ocb_set_utc_time(hdd_ctx->hHal, utc) != CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while setting UTC time")); + rc = -EINVAL; + } else { + rc = 0; + } + + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_set_utc_time(wiphy, wdev, data, data_len); + cds_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 (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 = cdf_mem_malloc(sizeof(*timing_advert)); + if (!timing_advert) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + cdf_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 = + sch_gen_timing_advert_frame(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(hdd_ctx->hHal, timing_advert) != + CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while starting timing advert")); + rc = -EINVAL; + } else { + rc = 0; + } + +fail: + if (timing_advert->template_value) + cdf_mem_free(timing_advert->template_value); + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_start_timing_advert(wiphy, wdev, + data, data_len); + cds_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 (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 = cdf_mem_malloc(sizeof(*timing_advert)); + if (!timing_advert) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + cdf_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(hdd_ctx->hHal, timing_advert) != + CDF_STATUS_SUCCESS) { + hddLog(LOGE, FL("Error while stopping timing advert")); + rc = -EINVAL; + } else { + rc = 0; + } + +fail: + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_stop_timing_advert(wiphy, wdev, + data, data_len); + cds_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 (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 ecdf_status 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ocb_get_tsf_timer(wiphy, wdev, + data, data_len); + cds_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) { + cdf_mem_free( + context->adapter->dcc_get_stats_resp); + } + context->adapter->dcc_get_stats_resp = + cdf_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); + cdf_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 (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 cdf_status 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; + cdf_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_get_stats(wiphy, wdev, + data, data_len); + cds_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 (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(hdd_ctx->hHal, adapter->sessionId, + nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP])) != + CDF_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_clear_stats(wiphy, wdev, + data, data_len); + cds_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 (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 cdf_status 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dcc_update_ndl(wiphy, wdev, + data, data_len); + cds_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/core/hdd/src/wlan_hdd_ocb.h b/core/hdd/src/wlan_hdd_ocb.h new file mode 100644 index 000000000000..0ca97bf607fb --- /dev/null +++ b/core/hdd/src/wlan_hdd_ocb.h @@ -0,0 +1,292 @@ +/* + * 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 "sir_api.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 + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS: + * flag to set the absolute expiry + */ +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); + +void hdd_remove_ocb_tx_header(struct sk_buff *skb); + +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/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c new file mode 100644 index 000000000000..63ae62ef9a27 --- /dev/null +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -0,0 +1,847 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * DOC: wlan_hdd_oemdata.c + * + * Support for generic OEM Data Request handling + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "qwlan_version.h" +#include "cds_utils.h" +#include "wma.h" + +static struct hdd_context_s *p_hdd_ctx; + +/** + * hdd_oem_data_req_callback() - OEM Data request callback handler + * @hHal: MAC handle + * @pContext: User context. For this callback the net device was registered + * @oemDataReqID: The ID of the request + * @oemDataReqStatus: Status of the request + * + * This function reports the results of the request to user space + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_oem_data_req_callback(tHalHandle hHal, + void *pContext, + uint32_t oemDataReqID, + eOemDataReqStatus oemDataReqStatus) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct net_device *dev = (struct net_device *)pContext; + union iwreq_data wrqu; + char buffer[IW_CUSTOM_MAX + 1]; + + memset(&wrqu, '\0', sizeof(wrqu)); + memset(buffer, '\0', sizeof(buffer)); + + if (oemDataReqStatus == eOEM_DATA_REQ_FAILURE) { + snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-FAILED"); + hddLog(LOGW, "%s: oem data req %d failed", __func__, + oemDataReqID); + } else if (oemDataReqStatus == eOEM_DATA_REQ_INVALID_MODE) { + snprintf(buffer, IW_CUSTOM_MAX, + "QCOM: OEM-DATA-REQ-INVALID-MODE"); + hddLog(LOGW, + "%s: oem data req %d failed because the driver is in invalid mode (IBSS|AP)", + __func__, oemDataReqID); + } else { + snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-SUCCESS"); + } + + wrqu.data.pointer = buffer; + wrqu.data.length = strlen(buffer); + + wireless_send_event(dev, IWEVCUSTOM, &wrqu, buffer); + + return status; +} + +/** + * iw_get_oem_data_cap() - Get OEM Data Capabilities + * @dev: net device upon which the request was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl data payload + * + * This function gets the capability information for OEM Data Request + * and Response. + * + * Return: 0 for success, negative errno value on failure + */ +int iw_get_oem_data_cap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + CDF_STATUS status; + t_iw_oem_data_cap oemDataCap; + t_iw_oem_data_cap *pHddOemDataCap; + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + hdd_context_t *pHddContext; + struct hdd_config *pConfig; + uint32_t numChannels; + uint8_t chanList[OEM_CAP_MAX_NUM_CHANNELS]; + uint32_t i; + int ret; + + ENTER(); + + pHddContext = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddContext); + if (0 != ret) + return ret; + + pConfig = pHddContext->config; + if (!pConfig) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s:HDD configuration is null", __func__); + return -ENOENT; + } + + do { + cdf_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_get_neighbor_scan_min_chan_time(pHddContext->hHal, + pAdapter->sessionId); + oemDataCap.curr_dwell_time_max = + sme_get_neighbor_scan_max_chan_time(pHddContext->hHal, + pAdapter->sessionId); + oemDataCap.supported_bands = pConfig->nBandCapability; + + /* request for max num of channels */ + numChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + status = sme_get_cfg_valid_channels(pHddContext->hHal, + &chanList[0], &numChannels); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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); + cdf_mem_copy(pHddOemDataCap, &oemDataCap, + sizeof(*pHddOemDataCap)); + } while (0); + + EXIT(); + return 0; +} + +/** + * send_oem_reg_rsp_nlink_msg() - send oem registration response + * + * This function sends oem message to registered application process + * + * Return: none + */ +static void send_oem_reg_rsp_nlink_msg(void) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + uint8_t *buf; + uint8_t *numInterfaces; + uint8_t *deviceMode; + uint8_t *vdevId; + hdd_adapter_list_node_t *pAdapterNode = NULL; + hdd_adapter_list_node_t *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + CDF_STATUS status = 0; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (p_hdd_ctx->oem_pid == 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return; + } + + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL); + if (skb == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(p_hdd_ctx, &pAdapterNode); + while ((CDF_STATUS_SUCCESS == status) && pAdapterNode) { + pAdapter = pAdapterNode->pAdapter; + if (pAdapter) { + deviceMode = buf++; + vdevId = buf++; + *deviceMode = pAdapter->device_mode; + *vdevId = pAdapter->sessionId; + (*numInterfaces)++; + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: numInterfaces: %d, deviceMode: %d, vdevId: %d", + __func__, *numInterfaces, *deviceMode, + *vdevId); + } + status = hdd_get_next_adapter(p_hdd_ctx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + aniHdr->length = + sizeof(uint8_t) + (*numInterfaces) * 2 * sizeof(uint8_t); + nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length)); + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: sending App Reg Response length (%d) to process pid (%d)", + __func__, aniHdr->length, p_hdd_ctx->oem_pid); + + (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + + return; +} + +/** + * send_oem_err_rsp_nlink_msg() - send oem error response + * @app_pid: PID of oem application process + * @error_code: response error code + * + * This function sends error response to oem app + * + * Return: none + */ +static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + uint8_t *buf; + + skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL); + if (skb == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(uint8_t); + 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)); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; +} + +/** + * hdd_send_oem_data_rsp_msg() - send oem data response + * @length: length of the OEM Data Response message + * @oemDataRsp: the actual OEM Data Response message + * + * This function sends an OEM Data Response message to a registered + * application process over the netlink socket. + * + * Return: 0 for success, non zero for failure + */ +void hdd_send_oem_data_rsp_msg(int length, uint8_t *oemDataRsp) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + uint8_t *oemData; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (p_hdd_ctx->oem_pid == 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return; + } + + if (length > OEM_DATA_RSP_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 = (uint8_t *) ((char *)aniHdr + sizeof(tAniMsgHdr)); + cdf_mem_copy(oemData, oemDataRsp, length); + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: sending Oem Data Response of len (%d) to process pid (%d)", + __func__, length, p_hdd_ctx->oem_pid); + + (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + + return; +} + +/** + * oem_process_data_req_msg() - process oem data request + * @oemDataLen: Length to OEM Data buffer + * @oemData: Pointer to OEM Data buffer + * + * This function sends oem message to SME + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS oem_process_data_req_msg(int oemDataLen, char *oemData) +{ + hdd_adapter_t *pAdapter = NULL; + tOemDataReqConfig oemDataReqConfig; + uint32_t oemDataReqID = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* for now, STA interface only */ + pAdapter = hdd_get_adapter(p_hdd_ctx, WLAN_HDD_INFRA_STATION); + if (!pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: No adapter for STA mode", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (!oemData) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: oemData is null", __func__); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig)); + + cdf_mem_copy((&oemDataReqConfig)->oemDataReq, oemData, oemDataLen); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: calling sme_oem_data_req", __func__); + + status = sme_oem_data_req(p_hdd_ctx->hHal, + pAdapter->sessionId, + &oemDataReqConfig, + &oemDataReqID, + &hdd_oem_data_req_callback, pAdapter->dev); + return status; +} + +/** + * oem_process_channel_info_req_msg() - process oem channel_info request + * @numOfChannels: number of channels + * @chanList: list of channel information + * + * This function responds with channel info to oem process + * + * 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; + uint8_t chanId; + uint32_t reg_info_1; + uint32_t reg_info_2; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int i; + uint8_t *buf; + + /* OEM message is always to a specific process and cannot be a broadcast */ + if (p_hdd_ctx->oem_pid == 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: invalid dest pid", __func__); + return -EPERM; + } + + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(uint8_t) + + numOfChannels * sizeof(tHddChannelInfo)), + GFP_KERNEL); + if (skb == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: alloc_skb failed", __func__); + return -ENOMEM; + } + + 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(uint8_t) + 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_get_reg_info(p_hdd_ctx->hHal, chanId, + ®_info_1, ®_info_2); + if (CDF_STATUS_SUCCESS == status) { + /* copy into hdd chan info struct */ + hddChanInfo.chan_id = chanId; + hddChanInfo.reserved0 = 0; + hddChanInfo.mhz = cds_chan_to_freq(chanId); + hddChanInfo.band_center_freq1 = hddChanInfo.mhz; + hddChanInfo.band_center_freq2 = 0; + + hddChanInfo.info = 0; + if (CHANNEL_STATE_DFS == + cds_get_channel_state(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 { + /* channel info is not returned, fill in zeros in channel + * info struct + */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: sme_get_reg_info 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; + } + cdf_mem_copy(pHddChanInfo, &hddChanInfo, + sizeof(tHddChannelInfo)); + } + + skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length))); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: sending channel info resp for num channels (%d) to pid (%d)", + __func__, numOfChannels, p_hdd_ctx->oem_pid); + + (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT); + + return 0; +} + +/** + * hdd_send_peer_status_ind_to_oem_app() - + * Function to send peer status to a registered application + * @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 + * @chan_info: operating channel information + * + * Return: none + */ +void hdd_send_peer_status_ind_to_oem_app(struct cdf_mac_addr *peerMac, + uint8_t peerStatus, + uint8_t peerTimingMeasCap, + uint8_t sessionId, + tSirSmeChanInfo *chan_info) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + tAniMsgHdr *aniHdr; + tPeerStatusInfo *pPeerInfo; + + if (!p_hdd_ctx || !p_hdd_ctx->hHal) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 ((!p_hdd_ctx->oem_app_registered) || (p_hdd_ctx->oem_pid == 0)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: OEM app is not registered(%d) or pid is invalid(%d)", + __func__, p_hdd_ctx->oem_app_registered, + p_hdd_ctx->oem_pid); + return; + } + + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + + sizeof(tPeerStatusInfo)), + GFP_KERNEL); + if (skb == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)); + + cdf_mem_copy(pPeerInfo->peer_mac_addr, peerMac->bytes, + sizeof(peerMac->bytes)); + pPeerInfo->peer_status = peerStatus; + pPeerInfo->vdev_id = sessionId; + 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))); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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, + p_hdd_ctx->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, p_hdd_ctx->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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Netlink header null", __func__); + return -EPERM; + } + + ret = wlan_hdd_validate_context(p_hdd_ctx); + if (0 != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return ret; + } + + msg_hdr = NLMSG_DATA(nlh); + + if (!msg_hdr) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Message header null", __func__); + 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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)", + __func__, 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 */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received App Req Req from App process pid(%d), len(%d)", + __func__, 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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Valid App Req Req from oem app process pid(%d)", + __func__, nlh->nlmsg_pid); + + p_hdd_ctx->oem_app_registered = true; + p_hdd_ctx->oem_pid = nlh->nlmsg_pid; + send_oem_reg_rsp_nlink_msg(); + } else { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid signature in App Reg Request from pid(%d)", + __func__, 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: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received Oem Data Request length(%d) from pid: %d", + __func__, msg_hdr->length, nlh->nlmsg_pid); + + if ((!p_hdd_ctx->oem_app_registered) || + (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: OEM DataReq: app not registered(%d) or incorrect pid(%d)", + __func__, p_hdd_ctx->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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid length (%d) in Oem Data Request", + __func__, 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: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received channel info request, num channel(%d) from pid: %d", + __func__, msg_hdr->length, nlh->nlmsg_pid); + + if ((!p_hdd_ctx->oem_app_registered) || + (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) { + /* either oem app is not registered yet or pid is different */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Chan InfoReq: app not registered(%d) or incorrect pid(%d)", + __func__, p_hdd_ctx->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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid length (%d) in channel info request", + __func__, 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: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Received Invalid message type (%d), length (%d)", + __func__, 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; + + cds_ssr_protect(__func__); + ret = oem_msg_callback(skb); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * oem_activate_service() - Activate oem message handler + * @hdd_ctx: pointer to global HDD context + * + * This function registers a handler to receive netlink message from + * an OEM application process. + * + * Return: zero on success + * On error, error number will be returned. + */ +int oem_activate_service(struct hdd_context_s *hdd_ctx) +{ + p_hdd_ctx = hdd_ctx; + + /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */ + return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback); +} + +#endif diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c new file mode 100644 index 000000000000..a6d5accaad6c --- /dev/null +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -0,0 +1,2626 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * + * @file wlan_hdd_p2p.c + * + * @brief WLAN Host Device Driver implementation for P2P commands interface + * + */ + +#include +#include +#include +#include "sme_api.h" +#include "sme_qos_api.h" +#include "wlan_hdd_p2p.h" +#include "sap_api.h" +#include "wlan_hdd_main.h" +#include "cdf_trace.h" +#include +#include +#include +#include +#include "wlan_hdd_tdls.h" +#include "wlan_hdd_trace.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cds_sched.h" +#include "cds_concurrency.h" + +/* Ms to Micro Sec */ +#define MS_TO_MUS(x) ((x) * 1000) + +static uint8_t *hdd_get_action_string(uint16_t 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_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 global_p2p_connection_status = 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"}; + +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 +CDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx, + CDF_STATUS status, uint32_t scan_id) +{ + 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 (!hdd_ctx) { + hdd_err("Invalid HDD context"); + return CDF_STATUS_E_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 CDF_STATUS_SUCCESS; + } + + hddLog(LOG1, "Received remain on channel rsp"); + cdf_mc_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer); + cdf_mc_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; + /* + * If the allow suspend is done later, the scheduled roc wil prevent + * the system from going into suspend and immediately this logic + * will allow the system to go to suspend breaking the exising logic. + * Basically, the system must not go into suspend while roc is in + * progress. + */ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + + if (REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { + if (cfgState->buf) { + hddLog(LOGP, + "%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)) + pRemainChanCtx->dev-> + ieee80211_ptr, +#else + pRemainChanCtx->dev, +#endif + pRemainChanCtx-> + cookie, + &pRemainChanCtx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + pRemainChanCtx-> + chan_type, +#endif + GFP_KERNEL); + pAdapter->last_roc_ts = cdf_mc_timer_get_system_time(); + } + + /* Schedule any pending RoC: Any new roc request during this time + * would have got queued in 'wlan_hdd_request_remain_on_channel' + * since the queue is not empty. So, the roc at the head of the + * queue will only get the priority. Scheduling the work queue + * after sending any cancel remain on channel event will also + * ensure that the cancel roc is sent without any delays. + */ + schedule_delayed_work(&hdd_ctx->roc_req_work, 0); + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) + ) { + uint8_t sessionId = pAdapter->sessionId; + if (REMAIN_ON_CHANNEL_REQUEST == + pRemainChanCtx->rem_on_chan_request) { + sme_deregister_mgmt_frame(hHal, sessionId, + (SIR_MAC_MGMT_FRAME << 2) | + (SIR_MAC_MGMT_PROBE_REQ << 4), + NULL, 0); + } + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) { + wlansap_de_register_mgmt_frame( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pAdapter), +#else + (WLAN_HDD_GET_CTX + (pAdapter))->pcds_context, +#endif + (SIR_MAC_MGMT_FRAME << 2) | + (SIR_MAC_MGMT_PROBE_REQ << + 4), NULL, 0); + + } + + if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL + && pRemainChanCtx->action_pkt_buff.frame_length != 0) { + cdf_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); + pRemainChanCtx->action_pkt_buff.frame_ptr = NULL; + pRemainChanCtx->action_pkt_buff.frame_length = 0; + } + cdf_mem_free(pRemainChanCtx); + complete(&pAdapter->cancel_rem_on_chan_var); + if (CDF_STATUS_SUCCESS != status) + complete(&pAdapter->rem_on_chan_ready_event); + return CDF_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; + 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 (CDF_TIMER_STATE_RUNNING == cdf_mc_timer_get_current_state( + &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer)) + cdf_mc_timer_stop(&cfgState->remain_on_chan_ctx-> + hdd_remain_on_chan_timer); + + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == + true) { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + hddLog(LOGE, + "ROC timer cancellation in progress," + " wait for completion"); + rc = wait_for_completion_timeout(&pAdapter-> + cancel_rem_on_chan_var, + msecs_to_jiffies + (WAIT_CANCEL_REM_CHAN)); + if (!rc) { + hddLog(LOGE, + "%s:wait on cancel_rem_on_chan_var timed out", + __func__); + } + return; + } + pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = true; + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + /* Wait till remain on channel ready indication before issuing cancel + * remain on channel request, otherwise if remain on channel not + * received and if the driver issues cancel remain on channel then lim + * will be in unknown state. + */ + rc = wait_for_completion_timeout(&pAdapter-> + rem_on_chan_ready_event, + msecs_to_jiffies + (WAIT_REM_CHAN_READY)); + if (!rc) { + hddLog(LOGE, + "%s: timeout waiting for remain on channel ready indication", + __func__); + } + + INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); + + /* Issue abort remain on chan request to sme. + * The remain on channel callback will make sure the remain_on_chan + * expired event is sent. + */ + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) + ) { + sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, + pRemainChanCtx->scan_id); + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) + || (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) { + wlansap_cancel_remain_on_channel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR + (pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, +#endif + pRemainChanCtx->scan_id); + } + + 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__); + } + 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; +} + +/** + * wlan_hdd_cancel_pending_roc() - Cancel pending roc + * @adapter: HDD adapter + * + * Cancels any pending remain on channel request + * + * Return: None + */ +void wlan_hdd_cancel_pending_roc(hdd_adapter_t *adapter) +{ + hdd_remain_on_chan_ctx_t *roc_ctx; + unsigned long rc; + hdd_cfg80211_state_t *cfg_state = WLAN_HDD_GET_CFG_STATE_PTR(adapter); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: ROC completion is not received.!!!", + __func__); + + mutex_lock(&cfg_state->remain_on_chan_ctx_lock); + roc_ctx = cfg_state->remain_on_chan_ctx; + + if (roc_ctx->hdd_remain_on_chan_cancel_in_progress) { + mutex_unlock(&cfg_state->remain_on_chan_ctx_lock); + hdd_debug("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(&cfg_state->remain_on_chan_ctx_lock); + + if (adapter->device_mode == WLAN_HDD_P2P_GO) { + wlansap_cancel_remain_on_channel((WLAN_HDD_GET_CTX + (adapter))->pcds_context, + cfg_state->remain_on_chan_ctx->scan_id); + } else if (adapter->device_mode == WLAN_HDD_P2P_CLIENT + || adapter->device_mode == + WLAN_HDD_P2P_DEVICE) { + sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX + (adapter), + adapter->sessionId, + cfg_state->remain_on_chan_ctx->scan_id); + } + +wait: + rc = wait_for_completion_timeout(&adapter->cancel_rem_on_chan_var, + msecs_to_jiffies + (WAIT_CANCEL_REM_CHAN)); + if (!rc) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Timeout occurred while waiting for RoC Cancellation", + __func__); + mutex_lock(&cfg_state->remain_on_chan_ctx_lock); + roc_ctx = cfg_state->remain_on_chan_ctx; + if (roc_ctx != NULL) { + cfg_state->remain_on_chan_ctx = NULL; + cdf_mc_timer_stop(&roc_ctx->hdd_remain_on_chan_timer); + cdf_mc_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) { + cdf_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; + } + cdf_mem_free(roc_ctx); + adapter->is_roc_inprogress = false; + } + mutex_unlock(&cfg_state->remain_on_chan_ctx_lock); + } +} + +/* Clean up RoC context at hdd_stop_adapter*/ +void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter) +{ + uint8_t retry = 0; + hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter); + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + while (pAdapter->is_roc_inprogress) { + mutex_unlock(&cfgState->remain_on_chan_ctx_lock); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: ROC in progress for session %d!!!", + __func__, pAdapter->sessionId); + msleep(500); + if (retry++ > 3) { + wlan_hdd_cancel_pending_roc(pAdapter); + /* 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_remain_on_chan_ctx_t *pRemainChanCtx; + hdd_cfg80211_state_t *cfgState; + + if (NULL == pAdapter) { + hddLog(LOGE, "%s: pAdapter is NULL !!!", __func__); + return; + } + + 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_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + pRemainChanCtx->scan_id); + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) { + wlansap_cancel_remain_on_channel( + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, + pRemainChanCtx->scan_id); + } + + 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); + CDF_STATUS cdf_status = CDF_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; + CDF_STATUS status; + bool isGoPresent = 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(CDF_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 */ + cdf_status = + cdf_mc_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer, + CDF_TIMER_TYPE_SW, + wlan_hdd_remain_on_chan_timeout, pAdapter); + if (cdf_status != CDF_STATUS_SUCCESS) { + hddLog(CDF_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); + cdf_mem_free(pRemainChanCtx); + return -EINVAL; + } + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) { + pAdapter_temp = pAdapterNode->pAdapter; + if (pAdapter_temp->device_mode == WLAN_HDD_P2P_GO) { + isGoPresent = true; + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + /* Extending duration for proactive extension logic for RoC */ + duration = pRemainChanCtx->duration; + if (isGoPresent == 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); + 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) + ) { + uint8_t sessionId = pAdapter->sessionId; + /* call sme API to start remain on channel. */ + + if (CDF_STATUS_SUCCESS != sme_remain_on_channel( + WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, + pRemainChanCtx->chan.hw_value, duration, + wlan_hdd_remain_on_channel_callback, + pAdapter, + (pRemainChanCtx->rem_on_chan_request == + REMAIN_ON_CHANNEL_REQUEST) ? true : false, + &pRemainChanCtx->scan_id)) { + hddLog(LOGE, FL("sme_remain_on_channel failed")); + 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); + cdf_mc_timer_destroy( + &pRemainChanCtx->hdd_remain_on_chan_timer); + cdf_mem_free(pRemainChanCtx); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return -EINVAL; + } + + if (REMAIN_ON_CHANNEL_REQUEST == + pRemainChanCtx->rem_on_chan_request) { + if (CDF_STATUS_SUCCESS != sme_register_mgmt_frame( + WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, + (SIR_MAC_MGMT_FRAME << 2) | + (SIR_MAC_MGMT_PROBE_REQ << 4), + NULL, 0)) + hddLog(LOGE, + FL("sme_register_mgmt_frame failed")); + } + + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + /* call sme API to start remain on channel. */ + if (CDF_STATUS_SUCCESS != wlansap_remain_on_channel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, +#endif + pRemainChanCtx->chan.hw_value, + duration, wlan_hdd_remain_on_channel_callback, + pAdapter, &pRemainChanCtx->scan_id)) { + hddLog(LOGE, FL("wlansap_remain_on_channel failed")); + 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); + cdf_mc_timer_destroy( + &pRemainChanCtx->hdd_remain_on_chan_timer); + cdf_mem_free(pRemainChanCtx); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return -EINVAL; + } + + if (CDF_STATUS_SUCCESS != wlansap_register_mgmt_frame( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, +#endif + (SIR_MAC_MGMT_FRAME << 2) | + (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("wlansap_register_mgmt_frame return fail")); + wlansap_cancel_remain_on_channel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, +#endif + pRemainChanCtx->scan_id); + 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; + CDF_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 = cdf_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 */ + cdf_spin_lock(&hdd_ctx->hdd_roc_req_q_lock); + status = cdf_list_insert_back(&hdd_ctx->hdd_roc_req_q, + &hdd_roc_req->node); + cdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGP, FL("Not able to enqueue RoC Req context")); + cdf_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) +{ + hdd_debug("indicate roc drop to userspace"); + cfg80211_ready_on_channel( + adapter->dev->ieee80211_ptr, + (uintptr_t)ctx, + &ctx->chan, + ctx->duration, GFP_KERNEL); + + cfg80211_remain_on_channel_expired( + ctx->dev->ieee80211_ptr, + ctx->cookie, + &ctx->chan, + 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) +{ + CDF_STATUS status; + int ret = 0; + hdd_roc_req_t *hdd_roc_req; + hdd_context_t *hdd_ctx = + container_of(work, hdd_context_t, roc_req_work.work); + + hdd_debug("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. + */ + cdf_spin_lock(&hdd_ctx->hdd_roc_req_q_lock); + if (list_empty(&hdd_ctx->hdd_roc_req_q.anchor)) { + cdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock); + hdd_debug("list is empty"); + return; + } + status = cdf_list_remove_front(&hdd_ctx->hdd_roc_req_q, + (cdf_list_node_t **) &hdd_roc_req); + cdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock); + if (CDF_STATUS_SUCCESS != status) { + hdd_debug("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(CDF_TRACE_LEVEL_ERROR, + FL("dropping RoC request")); + wlan_hdd_indicate_roc_drop(hdd_roc_req->pAdapter, + hdd_roc_req->pRemainChanCtx); + cdf_mem_free(hdd_roc_req->pRemainChanCtx); + } + cdf_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)) + 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; + hdd_remain_on_chan_ctx_t *pRemainChanCtx; + bool isBusy = false; + uint32_t size = 0; + hdd_adapter_t *sta_adapter; + int ret; + int status = 0; + + 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)) + 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 + 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 (cds_is_connection_in_progress( + (hdd_context_t *) pAdapter->pHddCtx)) { + hddLog(LOGE, FL("Connection is in progress")); + isBusy = true; + } + pRemainChanCtx = cdf_mem_malloc(sizeof(hdd_remain_on_chan_ctx_t)); + if (NULL == pRemainChanCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: Not able to allocate memory for Channel context", + __func__); + return -ENOMEM; + } + + cdf_mem_zero(pRemainChanCtx, sizeof(*pRemainChanCtx)); + cdf_mem_copy(&pRemainChanCtx->chan, chan, + sizeof(struct ieee80211_channel)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + pRemainChanCtx->chan_type = channel_type; +#endif + pRemainChanCtx->duration = duration; + 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_conn_is_connected( + WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter))) { + if (pAdapter->last_roc_ts !=0 && + ((cdf_mc_timer_get_system_time() - + pAdapter->last_roc_ts) < + pHddCtx->config->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->roc_req_work, + msecs_to_jiffies( + pHddCtx->config->p2p_listen_defer_interval)); + hddLog(LOG1, "Defer interval is %hu, pAdapter %p", + pHddCtx->config->p2p_listen_defer_interval, + pAdapter); + return 0; + } + } + } + + cdf_spin_lock(&pHddCtx->hdd_roc_req_q_lock); + cdf_list_size(&(pHddCtx->hdd_roc_req_q), &size); + cdf_spin_unlock(&pHddCtx->hdd_roc_req_q_lock); + if ((isBusy == false) && (!size)) { + status = wlan_hdd_execute_remain_on_channel(pAdapter, + pRemainChanCtx); + if (status == -EBUSY) { + if (wlan_hdd_roc_request_enqueue(pAdapter, + pRemainChanCtx)) { + cdf_mem_free(pRemainChanCtx); + return -EAGAIN; + } + } + return 0; + } else { + if (wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx)) { + cdf_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 == false && pAdapter->is_roc_inprogress == false) { + hdd_debug("scheduling delayed work: no connection/roc active"); + schedule_delayed_work(&pHddCtx->roc_req_work, 0); + } + return 0; +} + +int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + enum nl80211_channel_type + channel_type, +#endif + unsigned int duration, u64 *cookie) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct net_device *dev = wdev->netdev; +#endif + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_REMAIN_ON_CHANNEL, + pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST)); + return wlan_hdd_request_remain_on_channel(wiphy, dev, chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + channel_type, +#endif + duration, cookie, + REMAIN_ON_CHANNEL_REQUEST); +} + +int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + struct ieee80211_channel *chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 *cookie) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + wdev, +#else + dev, +#endif + chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + channel_type, +#endif + duration, cookie); + cds_ssr_unprotect(__func__); + + return ret; +} + +void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, + uint32_t scan_id) +{ + hdd_cfg80211_state_t *cfgState = NULL; + hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL; + CDF_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 %d", scan_id); + + pAdapter->start_roc_ts = cdf_mc_timer_get_system_time(); + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + pRemainChanCtx = cfgState->remain_on_chan_ctx; + if (pRemainChanCtx != NULL) { + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_REMAINCHANREADYHANDLER, + pAdapter->sessionId, + pRemainChanCtx->duration)); + /* start timer for actual duration */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &pRemainChanCtx->hdd_remain_on_chan_timer)) { + hddLog(LOGE, "Timer Started before ready event!!!"); + cdf_mc_timer_stop(&pRemainChanCtx-> + hdd_remain_on_chan_timer); + } + status = + cdf_mc_timer_start(&pRemainChanCtx-> + hdd_remain_on_chan_timer, + (pRemainChanCtx->duration + + COMPLETE_EVENT_PROPOGATE_TIME)); + if (status != CDF_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)) + pAdapter->dev-> + ieee80211_ptr, +#else + pAdapter->dev, +#endif + (uintptr_t) + pRemainChanCtx, + &pRemainChanCtx->chan, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) + 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) { + hddLog(LOGE, + "%s: Sent cached action frame to supplicant", + __func__); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 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); +#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 */ + + cdf_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)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + 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; + cdf_list_node_t *tmp, *q; + hdd_roc_req_t *curr_roc_req; + + hddLog(LOG1, "Cancel remain on channel"); + + if (CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + cdf_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 = cdf_list_remove_node(&pHddCtx->hdd_roc_req_q, + (cdf_list_node_t *) + curr_roc_req); + cdf_spin_unlock(&pHddCtx->hdd_roc_req_q_lock); + if (status == CDF_STATUS_SUCCESS) { + cdf_mem_free(curr_roc_req->pRemainChanCtx); + cdf_mem_free(curr_roc_req); + } + return 0; + } + } + cdf_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) { + cdf_mc_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) + ) { + + uint8_t sessionId = pAdapter->sessionId; + sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, + pRemainChanCtx->scan_id); + } else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode) + ) { + wlansap_cancel_remain_on_channel( +#ifdef WLAN_FEATURE_MBSSID + WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, +#endif + pRemainChanCtx->scan_id); + + } 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__); + } + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + return 0; +} + +int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + u64 cookie) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + wdev, +#else + dev, +#endif + cookie); + cds_ssr_unprotect(__func__); + + return ret; +} + +#if (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)) + 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)) + 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); + uint16_t extendedWait = 0; + uint8_t type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); + uint8_t subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); + tActionFrmType actionFrmType; + bool noack = 0; + int status; + unsigned long rc; + hdd_adapter_t *goAdapter; + uint16_t current_freq; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_ACTION, pAdapter->sessionId, + pAdapter->device_mode)); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + hddLog(LOG1, FL("Device_mode %s(%d) type: %d"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode, type); + +#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(CDF_TRACE_LEVEL_ERROR, + "[P2P] unknown[%d] ---> OTA to " MAC_ADDRESS_STR, + actionFrmType, + MAC_ADDR_ARRAY(&buf + [WLAN_HDD_80211_FRM_DA_OFFSET])); + } else { + hddLog(CDF_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) + && (global_p2p_connection_status == P2P_NOT_ACTIVE)) { + global_p2p_connection_status = P2P_GO_NEG_PROCESS; + hddLog(LOGE, "[P2P State]Inactive state to " + "GO negotiation progress state"); + } else if ((actionFrmType == WLAN_HDD_GO_NEG_CNF) && + (global_p2p_connection_status == + P2P_GO_NEG_PROCESS)) { + global_p2p_connection_status = + 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)) + 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) { + + uint32_t current_time = cdf_mc_timer_get_system_time(); + int remaining_roc_time = + ((int) cfgState->remain_on_chan_ctx->duration - + (current_time - pAdapter->start_roc_ts)); + + 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 received + * 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. + */ + uint8_t dstMac[ETH_ALEN] = { 0 }; + memcpy(&dstMac, + &buf[WLAN_HDD_80211_FRM_DA_OFFSET], + ETH_ALEN); + hddLog(CDF_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_get_action_string(buf + [WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET])); + } + + goAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO); + + /* If GO adapter exists and operating on same frequency */ + /* then we will not request remain on channel */ + if (goAdapter && (ieee80211_frequency_to_channel(chan->center_freq) + == goAdapter->sessionCtx.ap.operatingChannel)) { + /* if GO exist and is not off channel + * wait time should be zero + */ + wait = 0; + 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 (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&cfgState-> + remain_on_chan_ctx-> + hdd_remain_on_chan_timer)) { + cdf_mc_timer_stop(&cfgState-> + remain_on_chan_ctx-> + hdd_remain_on_chan_timer); + status = + cdf_mc_timer_start(&cfgState-> + remain_on_chan_ctx-> + hdd_remain_on_chan_timer, + wait); + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, + "%s: Remain on Channel timer start failed", + __func__); + } + mutex_unlock(&cfgState-> + remain_on_chan_ctx_lock); + goto send_frame; + } else { + if (pRemainChanCtx-> + hdd_remain_on_chan_cancel_in_progress == + true) { + mutex_unlock(&cfgState-> + remain_on_chan_ctx_lock); + hddLog(CDF_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 = (uint16_t) 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)) + 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 = (uint16_t) 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 = cdf_mem_malloc(len); /* buf; */ + if (cfgState->buf == NULL) + return -ENOMEM; + + cfgState->len = len; + + cdf_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); + } + + /* + * Firmware needs channel information for action frames + * which are not sent on the current operating channel of VDEV + */ + if ((WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) { + if (chan && (chan->center_freq != 0)) + current_freq = chan->center_freq; + else + current_freq = cfgState->current_freq; + } else { + current_freq = 0; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) + ) { + uint8_t 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 (CDF_STATUS_SUCCESS != + sme_send_action(WLAN_HDD_GET_HAL_CTX(pAdapter), + sessionId, buf, len, extendedWait, noack, + current_freq)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_send_action returned fail", __func__); + goto err; + } + } else if (WLAN_HDD_SOFTAP == pAdapter->device_mode || + WLAN_HDD_P2P_GO == pAdapter->device_mode) { + if (CDF_STATUS_SUCCESS != +#ifdef WLAN_FEATURE_MBSSID + wlansap_send_action(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), +#else + wlansap_send_action((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, +#endif + buf, len, 0, current_freq)) { + hddLog(LOGE, + FL("wlansap_send_action returned fail")); + goto err; + } + } + + return 0; +err: + if (!noack) { + hdd_send_action_cnf(pAdapter, false); + } + return 0; +err_rem_channel: + *cookie = (uintptr_t) cfgState; + cfg80211_mgmt_tx_status( +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + pAdapter->dev->ieee80211_ptr, +#else + pAdapter->dev, +#endif + *cookie, buf, len, false, GFP_KERNEL); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) +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)) + 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; + + cds_ssr_protect(__func__); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) + 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)) + 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 */ + cds_ssr_unprotect(__func__); + + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + 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)) +int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie); + cds_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +void hdd_send_action_cnf(hdd_adapter_t *pAdapter, bool 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; + } + + /* + * 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)) + pAdapter->dev->ieee80211_ptr, +#else + pAdapter->dev, +#endif + cfgState->action_cookie, + cfgState->buf, cfgState->len, + actionSendSuccess, GFP_KERNEL); + + cdf_mem_free(cfgState->buf); + cfgState->buf = NULL; + + complete(&pAdapter->tx_action_cnf_event); +} + +/** + * hdd_set_p2p_noa + * + ***FUNCTION: + * This function is called from hdd_hostapd_ioctl function when Driver + * get P2P_SET_NOA comand 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_set_p2p_noa(struct net_device *dev, uint8_t *command) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tP2pPsConfig NoA; + int count, duration, start_time; + char *param; + int ret; + + param = strnchr(command, strlen(command), ' '); + if (param == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: P2P_SET GO NoA: fail to read params, ret=%d", + __func__, ret); + return -EINVAL; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_p2p_set_ps(hHal, &NoA); + return 0; +} + +/** + * hdd_set_p2p_opps + * + ***FUNCTION: + * This function is called from hdd_hostapd_ioctl function when Driver + * get P2P_SET_PS comand 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_set_p2p_opps(struct net_device *dev, uint8_t *command) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tP2pPsConfig NoA; + char *param; + int legacy_ps, opp_ps, ctwindow; + int ret; + + param = strnchr(command, strlen(command), ' '); + if (param == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: P2P_SET GO PS: fail to read params, ret=%d", + __func__, ret); + return -EINVAL; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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_p2p_set_ps(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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_p2p_set_ps(hHal, &NoA); + } + } + return 0; +} + +int hdd_set_p2p_ps(struct net_device *dev, void *msgData) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + CDF_STATUS status = CDF_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_p2p_set_ps(hHal, &NoA); + return status; +} + +static uint8_t wlan_hdd_get_session_type(enum nl80211_iftype type) +{ + uint8_t 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; + default: + sessionType = WLAN_HDD_INFRA_STATION; + break; + } + + return sessionType; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return ERR_PTR(-EINVAL); + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return ERR_PTR(ret); + } + + MTRACE(cdf_trace(CDF_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(LOGE, + "%s: Interface type %d already exists. " + "Two interfaces of same type are not supported currently.", + __func__, type); + return ERR_PTR(-EINVAL); + } + + wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx); + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (pAdapter != NULL) { + scan_info = &pAdapter->scan_info; + if (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; + if (pHddCtx->config->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. + */ + struct cdf_mac_addr p2pDeviceAddress = + pHddCtx->p2pDeviceAddress; + p2pDeviceAddress.bytes[4] ^= 0x80; + pAdapter = hdd_open_adapter(pHddCtx, + wlan_hdd_get_session_type(type), + name, p2pDeviceAddress.bytes, true); + } else { + pAdapter = + hdd_open_adapter(pHddCtx, wlan_hdd_get_session_type(type), + name, wlan_hdd_get_intf_addr(pHddCtx), + true); + } + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", + __func__); + return ERR_PTR(-ENOSPC); + } + EXIT(); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + return pAdapter->dev->ieee80211_ptr; +#else + return pAdapter->dev; +#endif +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +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; + + cds_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + cds_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; + + cds_ssr_protect(__func__); + wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + cds_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; + + cds_ssr_protect(__func__); + ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); + cds_ssr_unprotect(__func__); + return ndev; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +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)) + struct net_device *dev = wdev->netdev; +#endif + hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy); + hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int status; + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_DEL_VIRTUAL_INTF, + pVirtAdapter->sessionId, pVirtAdapter->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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + wlan_hdd_release_intf_addr(pHddCtx, + pVirtAdapter->macAddressCurrent.bytes); + + hdd_stop_adapter(pHddCtx, pVirtAdapter, true); + hdd_close_adapter(pHddCtx, pVirtAdapter, true); + EXIT(); + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +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; + + cds_ssr_protect(__func__); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + ret = __wlan_hdd_del_virtual_intf(wiphy, wdev); +#else + ret = __wlan_hdd_del_virtual_intf(wiphy, dev); +#endif + cds_ssr_unprotect(__func__); + + return ret; +} + +void hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, + uint32_t nFrameLength, + uint8_t *pbFrames, + uint8_t frameType, uint32_t rxChan, int8_t rxRssi) +{ + uint16_t freq; + uint16_t extend_time; + uint8_t type = 0; + uint8_t subType = 0; + tActionFrmType actionFrmType; + hdd_cfg80211_state_t *cfgState = NULL; + CDF_STATUS status; + hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL; + hdd_context_t *pHddCtx; + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d", + __func__, 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 assumtion that we don't receive any action + * frame with BCST as destination, + * we are dropping action frame + */ + hddLog(LOGP, + "pAdapter for action frame is NULL Macaddr = " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(&pbFrames + [WLAN_HDD_80211_FRM_DA_OFFSET])); + hddLog(LOGP, + FL("Frame Type = %d Frame Length = %d subType = %d"), + 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; + } + + /* 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) && + cdf_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(CDF_TRACE_LEVEL_ERROR, + "[P2P] unknown[%d] <--- OTA" + " from " MAC_ADDRESS_STR, + actionFrmType, + MAC_ADDR_ARRAY(macFrom)); + } else { + hddLog(CDF_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) + && (global_p2p_connection_status == + P2P_NOT_ACTIVE)) { + global_p2p_connection_status = + P2P_GO_NEG_PROCESS; + hddLog(LOGE, + "[P2P State]Inactive state to " + "GO negotiation progress state"); + } else + if ((actionFrmType == + WLAN_HDD_GO_NEG_CNF) + && (global_p2p_connection_status == + P2P_GO_NEG_PROCESS)) { + global_p2p_connection_status = + P2P_GO_NEG_COMPLETED; + hddLog(LOGE, + "[P2P State]GO negotiation progress to " + "GO negotiation completed state"); + } else + if ((actionFrmType == + WLAN_HDD_INVITATION_REQ) + && (global_p2p_connection_status == + P2P_NOT_ACTIVE)) { + global_p2p_connection_status = + 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 (CDF_TIMER_STATE_RUNNING == cdf_mc_timer_get_current_state(&pRemainChanCtx->hdd_remain_on_chan_timer)) { + cdf_mc_timer_stop + (&pRemainChanCtx-> + hdd_remain_on_chan_timer); + status = + cdf_mc_timer_start + (&pRemainChanCtx-> + hdd_remain_on_chan_timer, + extend_time); + if (status != + CDF_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 = + cdf_mem_malloc + (nFrameLength); + cdf_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_send_action_cnf(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(LOG1, + "[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(LOG1, + "[TDLS] unknown[%d] <--- OTA", + actionFrmType); + } else { + hddLog(LOG1, + "[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_update_dsc_pto_up_mapping(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)) + 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/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c new file mode 100644 index 000000000000..d7662e817147 --- /dev/null +++ b/core/hdd/src/wlan_hdd_power.c @@ -0,0 +1,2346 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_power.c + * + * WLAN power management functions + * + */ + +/* Include files */ + +#include +#include +#include +#include +#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) +#include +#endif +#include "cdf_types.h" +#include "sme_api.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "cfg_api.h" + +#include +#include +#include +#include +#include + +#include +#include "hif.h" +#include "sme_power_save_api.h" + +/* Preprocessor definitions and constants */ +#define HDD_SSR_BRING_UP_TIME 15000 + +/* Type declarations */ + +/** + * enum hdd_power_mode - Power Mode enumerations + * @DRIVER_POWER_MODE_AUTO: Driver can place device into power save + * @DRIVER_POWER_MODE_ACTIVE: Driver should operate at full power + */ +enum hdd_power_mode { + DRIVER_POWER_MODE_AUTO = 0, + DRIVER_POWER_MODE_ACTIVE = 1, +}; + +/* Function and variables declarations */ + +extern struct notifier_block hdd_netdev_notifier; + +static struct timer_list ssr_timer; +static bool ssr_timer_started; +/** + * hdd_conf_gtk_offload() - Configure GTK offload + * @pAdapter: pointer to the adapter + * @fenable: flag set to enable (1) or disable (0) GTK offload + * + * Central function to enable or disable GTK offload. + * + * Return: nothing + */ +#ifdef WLAN_FEATURE_GTK_OFFLOAD +static void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, bool fenable) +{ + CDF_STATUS 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)) { + cdf_mem_copy(&hddGtkOffloadReqParams, + &pHddStaCtx->gtkOffloadReqParams, + sizeof(tSirGtkOffloadParams)); + + ret = sme_set_gtk_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, + pAdapter->sessionId); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: sme_set_gtk_offload failed, returned %d", + __func__, ret); + return; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: sme_set_gtk_offload successfull", + __func__); + } + + } else { + if ((eConnectionState_Associated == + pHddStaCtx->conn_info.connState) + && (0 == + memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId, + &pHddStaCtx->conn_info.bssId, CDF_MAC_ADDR_SIZE)) + && (GTK_OFFLOAD_ENABLE == + pHddStaCtx->gtkOffloadReqParams.ulFlags)) { + + /* Host driver has previously offloaded GTK rekey */ + ret = sme_get_gtk_offload + (WLAN_HDD_GET_HAL_CTX(pAdapter), + wlan_hdd_cfg80211_update_replay_counter_callback, + pAdapter, pAdapter->sessionId); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: sme_get_gtk_offload failed, returned %d", + __func__, ret); + return; + } else { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: sme_get_gtk_offload successful", + __func__); + + /* Sending GTK offload dissable */ + memcpy(&hddGtkOffloadReqParams, + &pHddStaCtx->gtkOffloadReqParams, + sizeof(tSirGtkOffloadParams)); + hddGtkOffloadReqParams.ulFlags = + GTK_OFFLOAD_DISABLE; + ret = + sme_set_gtk_offload(WLAN_HDD_GET_HAL_CTX + (pAdapter), + &hddGtkOffloadReqParams, + pAdapter->sessionId); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: failed to dissable GTK offload, returned %d", + __func__, ret); + return; + } + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s: successfully dissabled GTK offload request to HAL", + __func__); + } + } + } + return; +} +#else /* WLAN_FEATURE_GTK_OFFLOAD */ +static void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, bool fenable) +{ +} +#endif /*WLAN_FEATURE_GTK_OFFLOAD */ + +#ifdef WLAN_NS_OFFLOAD +/** + * __wlan_hdd_ipv6_changed() - IPv6 notifier callback function + * @nb: notifier block that was registered with the kernel + * @data: (unused) generic data that was registered with the kernel + * @arg: (unused) generic argument that was registered with the kernel + * + * This is a callback function that is registered with the kernel via + * register_inet6addr_notifier() which allows the driver to be + * notified when there is an IPv6 address change. + * + * Return: NOTIFY_DONE to indicate we don't care what happens with + * other callbacks + */ +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_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx; + int status; + + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("Adapter context is invalid %p"), pAdapter); + return -EINVAL; + } + + if ((pAdapter->dev == ndev) && + (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + schedule_work(&pAdapter->ipv6NotifierWorkQueue); + } + + 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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_ipv6_changed(nb, data, arg); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_conf_ns_offload() - Configure NS offload + * @pAdapter: pointer to the adapter + * @fenable: flag to enable or disable + * 0 - disable + * 1 - enable + * + * Return: nothing + */ +static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable) +{ + struct inet6_dev *in6_dev; + struct inet6_ifaddr *ifp; + struct list_head *p; + uint8_t + selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] + [SIR_MAC_IPV6_ADDR_LEN] = { {0,} }; + bool selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = { 0 }; + tSirHostOffloadReq offLoadRequest; + hdd_context_t *pHddCtx; + + int i = 0; + CDF_STATUS 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) { + /* read_lock_bh(&in6_dev->lock); */ + list_for_each(p, &in6_dev->addr_list) { + if (count >= + SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { + hdd_err("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: + cdf_mem_copy(&selfIPv6Addr[count], + &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[count] = + SIR_IPV6_ADDR_VALID; + hdd_info("Index %d scope = %s Address : %pI6", + count, + (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ? + "LINK LOCAL" : "GLOBAL", + selfIPv6Addr[count]); + count += 1; + break; + default: + hdd_err("The Scope %d is not supported", + scope); + } + } + /* read_unlock_bh(&in6_dev->lock); */ + cdf_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; + cdf_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], + &selfIPv6Addr[i][0], SIR_MAC_IPV6_ADDR_LEN); + + offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[i] = + SIR_IPV6_ADDR_VALID; + + hdd_info("configuredMcastBcastFilter: %d", + pHddCtx->configuredMcastBcastFilter); + + if ((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))) { + hdd_info("Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE"); + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; + } + + cdf_mem_copy(&offLoadRequest.params.hostIpv6Addr, + &offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], + SIR_MAC_IPV6_ADDR_LEN); + + hdd_info("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; + cdf_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_set_host_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest); + if (CDF_STATUS_SUCCESS != returnStatus) { + hdd_err("Failed to enable HostOffload feature with status: %d", + returnStatus); + } + } else { + hdd_err("IPv6 dev does not exist. Failed to request NSOffload"); + return; + } + } else { + /* Disable NSOffload */ + cdf_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + + if (CDF_STATUS_SUCCESS != + sme_set_host_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) + hdd_err("Failed to disable NS Offload"); + } + EXIT(); + return; +} + +/** + * __hdd_ipv6_notifier_work_queue() - IPv6 notification work function + * @work: registered work item + * + * This function performs the work initially trigged by a callback + * from the IPv6 netdev notifier. Since this means there has been a + * change in IPv6 state for the interface, the NS offload is + * reconfigured. + * + * Return: None + */ +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; + + hddLog(LOG1, FL("Reconfiguring NS 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 (!pHddCtx->config->active_mode_offload) { + hdd_err("Active mode offload is disabled"); + return; + } + + if (false == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = true; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + if (pHddCtx->config->fhostNSOffload) + hdd_conf_ns_offload(pAdapter, true); +} + +/** + * 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) +{ + cds_ssr_protect(__func__); + __hdd_ipv6_notifier_work_queue(work); + cds_ssr_unprotect(__func__); +} + +/** + * hdd_conf_hostoffload() - Central function to configure the supported offloads + * @pAdapter: pointer to the adapter + * @fenable: flag set to enable (1) or disable (0) + * + * Central function to configure the supported offloads either + * enable or disable them. + * + * Return: nothing + */ +void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) +{ + hdd_context_t *pHddCtx; + + hdd_info("Configuring offloads with flag: %d", fenable); + + /* Get the HDD context. */ + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))) { + hdd_err("Offloads not supported in mode %d", + pAdapter->device_mode); + return; + } + + if (eConnectionState_Associated != + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) { + hdd_err("Offloads not supported in state %d", + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))-> + conn_info.connState); + return; + } + + hdd_conf_gtk_offload(pAdapter, fenable); + + /* Configure ARP/NS offload during cfg80211 suspend/resume only + * if active mode offload is disabled + */ + if (!pHddCtx->config->active_mode_offload) { + hdd_conf_arp_offload(pAdapter, fenable); + if (pHddCtx->config->fhostNSOffload) + hdd_conf_ns_offload(pAdapter, fenable); + } + return; +} +#endif + +/** + * __hdd_ipv4_notifier_work_queue() - IPv4 notification work function + * @work: registered work item + * + * This function performs the work initially trigged by a callback + * from the IPv4 netdev notifier. Since this means there has been a + * change in IPv4 state for the interface, the ARP offload is + * reconfigured. + * + * Return: None + */ +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; + + hdd_info("Configuring 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 (!pHddCtx->config->active_mode_offload) { + hdd_err("Active mode offload is disabled"); + return; + } + + if (false == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = true; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + hdd_conf_arp_offload(pAdapter, true); +} + +/** + * 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) +{ + cds_ssr_protect(__func__); + __hdd_ipv4_notifier_work_queue(work); + cds_ssr_unprotect(__func__); +} + +/** + * __wlan_hdd_ipv4_changed() - IPv4 notifier callback function + * @nb: notifier block that was registered with the kernel + * @data: (unused) generic data that was registered with the kernel + * @arg: (unused) generic argument that was registered with the kernel + * + * This is a callback function that is registered with the kernel via + * register_inetaddr_notifier() which allows the driver to be + * notified when there is an IPv4 address change. + * + * Return: NOTIFY_DONE to indicate we don't care what happens with + * other callbacks + */ +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_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); + hdd_context_t *pHddCtx; + int status; + + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, FL("Adapter context is invalid %p"), pAdapter); + return -EINVAL; + } + + if ((pAdapter && pAdapter->dev == ndev) && + (pAdapter->device_mode == WLAN_HDD_INFRA_STATION || + pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + if (!pHddCtx->config->fhostArpOffload) { + hddLog(LOG1, + FL("Offload not enabled ARPOffload=%d"), + pHddCtx->config->fhostArpOffload); + return NOTIFY_DONE; + } + + in_dev = __in_dev_get_rtnl(pAdapter->dev); + if (in_dev) { + 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) { + schedule_work(&pAdapter->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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_ipv4_changed(nb, data, arg); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_conf_arp_offload() - Configure ARP offload + * @pAdapter: Adapter context for which ARP offload is to be configured + * @fenable: true : enable ARP offload false : disable arp offload + * + * Return: + * CDF_STATUS_SUCCESS - on successful operation, + * CDF_STATUS_E_FAILURE - on failure of operation + */ +CDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool 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); + + hdd_info("fenable = %d", fenable); + + /* In SAP/P2P Go 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("ARP Offload is not supported in SAP/P2PGO mode")); + return CDF_STATUS_SUCCESS; + } + + if (fenable) { + in_dev = __in_dev_get_rtnl(pAdapter->dev); + if (in_dev) { + 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(CDF_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)) + && (true == + pHddCtx->sus_res_mcastbcast_filter_valid)) { + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + hddLog(CDF_TRACE_LEVEL_INFO, + "offload: inside arp offload conditional check"); + } + + hddLog(CDF_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(CDF_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 (CDF_STATUS_SUCCESS != + sme_set_host_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &offLoadRequest)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Failed to enable HostOffload feature", + __func__); + return CDF_STATUS_E_FAILURE; + } + } else { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("IP Address is not assigned")); + } + + return CDF_STATUS_SUCCESS; + } else { + cdf_mem_zero((void *)&offLoadRequest, + sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; + + if (CDF_STATUS_SUCCESS != + sme_set_host_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Failure to disable host " "offload feature", + __func__); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; + } +} + +/** + * hdd_mcbc_filter_modification() - MCBC Filter Modifier + * @pHddCtx: Global Hdd Context + * @pMcBcFilter: Multicast/Broadcast filter to be modified + * + * This function is called before setting mcbc filters + * to modify filter value considering different offloads + * + * Return: None. + */ +static void hdd_mcbc_filter_modification(hdd_context_t *pHddCtx, + uint8_t *pMcBcFilter) +{ + if (NULL == pHddCtx) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("NULL HDD context passed")); + return; + } + + *pMcBcFilter = pHddCtx->configuredMcastBcastFilter; + if (pHddCtx->config->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 + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + } +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->config->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 + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); + } +#endif + + pHddCtx->configuredMcastBcastFilter = *pMcBcFilter; +} + +/** + * hdd_conf_mcastbcast_filter() - Configure multicast/broadcast filter + * @pHddCtx: Global HDD context + * @setfilter: true if filter is being set, false if filter is being cleared + * + * Return: None. + */ +void hdd_conf_mcastbcast_filter(hdd_context_t *pHddCtx, bool setfilter) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + tpSirWlanSetRxpFilters wlanRxpFilterParam = + cdf_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: cdf_mem_alloc failed ", __func__); + return; + } + hddLog(CDF_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; + cdf_ret_status = + sme_configure_rxp_filter(pHddCtx->hHal, wlanRxpFilterParam); + + if (setfilter && (CDF_STATUS_SUCCESS == cdf_ret_status)) + pHddCtx->hdd_mcastbcast_filter_set = true; + + hddLog(LOG1, + FL("%s to post set/reset filter to lower mac with status %d configuredMcstBcstFilterSetting = %d setMcstBcstFilter = %d"), + (CDF_STATUS_SUCCESS != cdf_ret_status) ? "Failed" : "Success", + cdf_ret_status, + wlanRxpFilterParam->configuredMcstBcstFilterSetting, + wlanRxpFilterParam->setMcstBcstFilter); + + if (CDF_STATUS_SUCCESS != cdf_ret_status) + cdf_mem_free(wlanRxpFilterParam); +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/** + * wlan_hdd_set_mc_addr_list() - set MC address list in FW + * @pAdapter: adapter whose MC list is being set + * @set: flag which indicates if addresses are being set or cleared + */ +void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) +{ + uint8_t i; + tpSirRcvFltMcAddrList pMulticastAddrs = NULL; + tHalHandle hHal = NULL; + hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx; + + if (NULL == pHddCtx) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD CTX is NULL")); + return; + } + + hHal = pHddCtx->hHal; + + if (NULL == hHal) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HAL Handle is NULL")); + return; + } + + /* Check if INI is enabled or not, other wise just return + */ + if (!pHddCtx->config->fEnableMCAddrList) { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("gMCAddrListEnable is not enabled in INI")); + return; + } + pMulticastAddrs = cdf_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == pMulticastAddrs) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Could not allocate Memory")); + return; + } + cdf_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(CDF_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_8023_multicast_list(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_8023_multicast_list(hHal, pAdapter->sessionId, + pMulticastAddrs); + } + + } + /* MAddrCnt is MulticastAddrCnt */ + hddLog(CDF_TRACE_LEVEL_INFO, + "smeSessionId:%d; set:%d; MCAdddrCnt :%d", + pAdapter->sessionId, set, + pMulticastAddrs->ulMulticastAddrCnt); + + pAdapter->mc_addr_list.isFilterApplied = set ? true : false; + cdf_mem_free(pMulticastAddrs); + return; +} +#endif + +/** + * hdd_conf_suspend_ind() - Send Suspend notification + * @pHddCtx: HDD Global context + * @pAdapter: adapter being suspended + * @callback: callback function to be called upon completion + * @callbackContext: callback context to be passed back to callback function + * + * Return: None. + */ +static void hdd_conf_suspend_ind(hdd_context_t *pHddCtx, + hdd_adapter_t *pAdapter, + void (*callback)(void *callbackContext, + bool suspended), + void *callbackContext) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + tpSirWlanSuspendParam wlanSuspendParam = + cdf_mem_malloc(sizeof(tSirWlanSuspendParam)); + + if (false == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = true; + hddLog(CDF_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); + hddLog(CDF_TRACE_LEVEL_INFO, + "configuredMCastBcastFilter saved = %d", + pHddCtx->configuredMcastBcastFilter); + + } + + if (NULL == wlanSuspendParam) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: cdf_mem_alloc failed ", __func__); + return; + } + + hddLog(CDF_TRACE_LEVEL_INFO, + "%s: send wlan suspend indication", __func__); + + /* Configure supported OffLoads */ + hdd_conf_hostoffload(pAdapter, true); + wlanSuspendParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + + /* Enable MC address filtering during cfg80211 suspend if active mode + * mode offload is disabled in INI + */ + if (!pHddCtx->config->active_mode_offload) { + hdd_info("enable mc address filtering"); + wlan_hdd_set_mc_addr_list(pAdapter, true); + } + + 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; + cdf_ret_status = + sme_configure_suspend_ind(pHddCtx->hHal, wlanSuspendParam, + callback, callbackContext); + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + pHddCtx->hdd_mcastbcast_filter_set = true; + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("sme_configure_suspend_ind returned failure %d"), + cdf_ret_status); + + cdf_mem_free(wlanSuspendParam); + } +} + +/** + * hdd_conf_suspend_ind() - Send Resume notification + * @pAdapter: adapter being resumed + * + * Return: None. + */ +static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + cdf_ret_status = sme_configure_resume_req(pHddCtx->hHal, NULL); + + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: sme_configure_resume_req return failure %d", + __func__, cdf_ret_status); + + } + + hddLog(CDF_TRACE_LEVEL_INFO, + "%s: send wlan resume indication", __func__); + /* Disable supported OffLoads */ + hdd_conf_hostoffload(pAdapter, false); + pHddCtx->hdd_mcastbcast_filter_set = false; + + if (true == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = false; + } + + hddLog(CDF_TRACE_LEVEL_INFO, + "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); + hddLog(CDF_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + + /* Disable MC address filtering during cfg80211 suspend if active mode + * mode offload is disabled in INI + */ + if (!pHddCtx->config->active_mode_offload) { + hdd_info("disable mc address filtering"); + wlan_hdd_set_mc_addr_list(pAdapter, false); + } +} + +/** + * hdd_suspend_wlan() - Driver suspend function + * @callback: Callback function to invoke when driver is ready to suspend + * @callbackContext: Context to pass back to @callback function + * + * Return: None. + */ +static void +hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), + void *callbackContext) +{ + hdd_context_t *pHddCtx; + + CDF_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: WLAN being suspended by OS", + __func__); + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD context is Null", + __func__); + return; + } + + if (pHddCtx->isLogpInProgress) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Ignore suspend wlan, LOGP in progress!", __func__); + return; + } + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + + /* stop all TX queues before suspend */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, + WLAN_CONTROL_PATH); + + /* Send suspend notification down to firmware. + * + * N.B.: Keep this suspend indication at the end + * (before processing next adaptor). This indication + * is considered as trigger point to start WOW (if wow + * is enabled). + */ + hdd_conf_suspend_ind(pHddCtx, pAdapter, callback, + callbackContext); + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + pHddCtx->hdd_wlan_suspended = true; + + return; +} + +/** + * hdd_resume_wlan() - Driver resume function + * + * Return: None. + */ +static void hdd_resume_wlan(void) +{ + hdd_context_t *pHddCtx; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: WLAN being resumed by OS", + __func__); + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD context is Null", + __func__); + return; + } + + if (pHddCtx->isLogpInProgress) { + hddLog(CDF_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 && CDF_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + + /* wake the tx queues */ + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + + hdd_conf_resume_ind(pAdapter); + + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + hdd_ipa_resume(pHddCtx); + + return; +} + +/** + * DOC: SSR Timer + * + * When SSR is initiated, an SSR timer is started. Under normal + * circumstances SSR should complete amd the timer should be deleted + * before it fires. If the SSR timer does fire, it indicates SSR has + * taken too long, and our only recourse is to invoke the CDF_BUG() + * API which can allow a crashdump to be captured. + */ + +/** + * hdd_ssr_timer_init() - Initialize SSR Timer + * + * Return: None. + */ +static void hdd_ssr_timer_init(void) +{ + init_timer(&ssr_timer); +} + +/** + * hdd_ssr_timer_del() - Delete SSR Timer + * + * Return: None. + */ +static void hdd_ssr_timer_del(void) +{ + del_timer(&ssr_timer); + ssr_timer_started = false; +} + +/** + * hdd_ssr_timer_cb() - SSR Timer callback function + * @data: opaque data registered with timer infrastructure + * + * Return: None. + */ +static void hdd_ssr_timer_cb(unsigned long data) +{ + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired!", __func__); + CDF_BUG(0); +} + +/** + * hdd_ssr_timer_start() - Start SSR Timer + * @msec: Timer timeout value in milliseconds + * + * Return: None. + */ +static void hdd_ssr_timer_start(int msec) +{ + if (ssr_timer_started) { + hddLog(CDF_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; +} + +/** + * hdd_wlan_shutdown() - HDD SSR shutdown function + * + * This function is called by the HIF to shutdown the driver during SSR. + * + * Return: CDF_STATUS_SUCCESS if the driver was shut down, + * or an error status otherwise + */ +CDF_STATUS hdd_wlan_shutdown(void) +{ + CDF_STATUS cdf_status; + v_CONTEXT_t p_cds_context = NULL; + hdd_context_t *pHddCtx; + p_cds_sched_context cds_sched_context = NULL; + + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down!", + __func__); + +#ifdef WLAN_FEATURE_LPSS + wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); +#endif + + /* If SSR never completes, then do kernel panic. */ + hdd_ssr_timer_init(); + hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME); + + /* Get the global CDS context. */ + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Global CDS context is Null", + __func__); + return CDF_STATUS_E_FAILURE; + } + + /* Get the HDD context. */ + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD context is Null", + __func__); + return CDF_STATUS_E_FAILURE; + } + + pHddCtx->isLogpInProgress = true; + cds_set_logp_in_progress(true); + + cds_clear_concurrent_session_count(); + + hdd_reset_all_adapters(pHddCtx); + + hdd_ipa_uc_ssr_deinit(); + + cds_sched_context = get_cds_sched_ctxt(); + + /* Wakeup all driver threads */ + if (true == pHddCtx->isMcThreadSuspended) { + complete(&cds_sched_context->ResumeMcEvent); + pHddCtx->isMcThreadSuspended = false; + } +#ifdef QCA_CONFIG_SMP + if (true == pHddCtx->is_ol_rx_thread_suspended) { + complete(&cds_sched_context->ol_resume_rx_event); + pHddCtx->is_ol_rx_thread_suspended = false; + } +#endif + + /* 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(CDF_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread", __func__); + set_bit(MC_SHUTDOWN_EVENT_MASK, &cds_sched_context->mcEventFlag); + set_bit(MC_POST_EVENT_MASK, &cds_sched_context->mcEventFlag); + wake_up_interruptible(&cds_sched_context->mcWaitQueue); + wait_for_completion(&cds_sched_context->McShutdown); + +#ifdef QCA_CONFIG_SMP + /* Wait for OL RX to exit */ + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Shutting down OL RX thread", + __func__); + unregister_hotcpu_notifier(cds_sched_context->cpu_hot_plug_notifier); + set_bit(RX_SHUTDOWN_EVENT_MASK, &cds_sched_context->ol_rx_event_flag); + set_bit(RX_POST_EVENT_MASK, &cds_sched_context->ol_rx_event_flag); + wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue); + wait_for_completion(&cds_sched_context->ol_rx_shutdown); + cds_sched_context->ol_rx_thread = NULL; + cds_drop_rxpkt_by_staid(cds_sched_context, WLAN_MAX_STA_COUNT); + cds_free_ol_rx_pkt_freeq(cds_sched_context); +#endif + + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Doing WMA STOP", __func__); + cdf_status = wma_stop(p_cds_context, HAL_STOP_TYPE_RF_KILL); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop WMA", __func__); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + wma_setneedshutdown(p_cds_context); + } + + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Doing SME STOP", __func__); + /* Stop SME - Cannot invoke cds_disable as cds_disable relies + * on threads being running to process the SYS Stop + */ + cdf_status = sme_stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop sme %d", __func__, cdf_status); + CDF_ASSERT(0); + } + + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP", __func__); + /* Stop MAC (PE and HAL) */ + cdf_status = mac_stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to stop mac %d", __func__, cdf_status); + CDF_ASSERT(0); + } + + hif_disable_isr(((cds_context_type *) p_cds_context)->pHIFContext); + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: Flush Queues", __func__); + /* Clean up message queues of TX, RX and MC thread */ + cds_sched_flush_mc_mqs(cds_sched_context); + + /* Deinit all the TX, RX and MC queues */ + cds_sched_deinit_mqs(cds_sched_context); + + hddLog(CDF_TRACE_LEVEL_INFO, "%s: Doing CDS Shutdown", __func__); + /* shutdown CDS */ + cds_shutdown(p_cds_context); + + /*mac context has already been released in mac_close call + so setting it to NULL in hdd context */ + pHddCtx->hHal = (tHalHandle) NULL; + + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete", + __func__); + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wlan_re_init() - HDD SSR re-init function + * + * This function is called by the HIF to re-initialize the driver after SSR. + * + * Return: CDF_STATUS_SUCCESS if the driver was re-initialized, + * or an error status otherwise + */ +CDF_STATUS hdd_wlan_re_init(void *hif_sc) +{ + CDF_STATUS cdf_status; + v_CONTEXT_t p_cds_context = NULL; + hdd_context_t *pHddCtx = NULL; + CDF_STATUS cdf_ret_status; + hdd_adapter_t *pAdapter; + int i; + + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + + /* Get the CDS context */ + p_cds_context = cds_get_global_context(); + if (p_cds_context == NULL) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: Failed cds_get_global_context", __func__); + goto err_re_init; + } + + /* Get the HDD context */ + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (!pHddCtx) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD context is Null", + __func__); + goto err_re_init; + } + + if (!hif_sc) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: hif_sc is NULL", __func__); + goto err_re_init; + } + + ((cds_context_type *) p_cds_context)->pHIFContext = hif_sc; + + /* The driver should always be initialized in STA mode after SSR */ + hdd_set_conparam(0); + + /* Re-open CDS, it is a re-open b'se control transport was never closed. */ + cdf_status = cds_open(&p_cds_context, 0); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_open failed", __func__); + goto err_re_init; + } + + /* Save the hal context in Adapter */ + pHddCtx->hHal = cds_get_context(CDF_MODULE_ID_SME); + if (NULL == pHddCtx->hHal) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HAL context is null", + __func__); + goto err_cds_close; + } + + /* Set the SME configuration parameters. */ + cdf_status = hdd_set_sme_config(pHddCtx); + if (CDF_STATUS_SUCCESS != cdf_status) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", + __func__); + goto err_cds_close; + } + + cdf_status = cds_pre_enable(pHddCtx->pcds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_pre_enable failed", + __func__); + goto err_cds_close; + } + + ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb); + + cdf_status = hdd_set_sme_chan_list(pHddCtx); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: Failed to init channel list", __func__); + goto err_cds_close; + } + + /* Apply the cfg.ini to cfg.dat */ + if (false == hdd_update_config_dat(pHddCtx)) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: config update failed", + __func__); + goto err_cds_close; + } + + /* 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. */ + cdf_ret_status = cfg_set_str(pHddCtx->hHal, WNI_CFG_STA_ID, + (uint8_t *) &pHddCtx->config-> + intfMacAddr[0], + sizeof(pHddCtx->config->intfMacAddr[0])); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Failed to set MAC Address. " + "HALStatus is %08d [x%08x]", __func__, cdf_ret_status, + cdf_ret_status); + goto err_cds_close; + } + + /* Start CDS which starts up the SME/MAC/HAL modules and everything else + Note: Firmware image will be read and downloaded inside cds_enable API */ + cdf_status = cds_enable(p_cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_enable failed", __func__); + goto err_cds_close; + } + + cdf_status = hdd_post_cds_enable_config(pHddCtx); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: hdd_post_cds_enable_config failed", __func__); + goto err_cds_disable; + } + + /* 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(CDF_TRACE_LEVEL_FATAL, + "%s: Failed to get Adapter!", __func__); + } + } + } + + if (hdd_ipa_uc_ssr_reinit()) + hddLog(LOGE, "%s: HDD IPA UC reinit failed", __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) { + wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_MODULE_ENABLE, + pHddCtx->fw_log_settings.enable, + DBG_CMD); + } else { + wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_MODULE_DISABLE, + pHddCtx->fw_log_settings.enable, + DBG_CMD); + } + + if (pHddCtx->fw_log_settings.dl_report != 0) { + wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_REPORT_ENABLE, + pHddCtx->fw_log_settings. + dl_report, DBG_CMD); + + wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_TYPE, + pHddCtx->fw_log_settings. + dl_type, DBG_CMD); + + wma_cli_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) { + wma_cli_set_command( + pAdapter->sessionId, + WMI_DBGLOG_MOD_LOG_LEVEL, + pHddCtx->fw_log_settings. + dl_mod_loglevel[i], + DBG_CMD); + } + } + } + } + + pHddCtx->hdd_mcastbcast_filter_set = false; + pHddCtx->btCoexModeSet = false; + 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); + + sme_ext_scan_register_callback(pHddCtx->hHal, + wlan_hdd_cfg80211_extscan_callback); + 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 + + hif_enable_power_gating(hif_sc); + hddLog(LOGE, + "%s: WLAN host driver reinitiation completed!", __func__); + goto success; + +err_cds_disable: + cds_disable(p_cds_context); + +err_cds_close: + cds_close(p_cds_context); + cds_sched_close(p_cds_context); + if (pHddCtx) { + /* Unregister the Net Device Notifier */ + unregister_netdevice_notifier(&hdd_netdev_notifier); +#ifdef WLAN_KD_READY_NOTIFIER + cnss_diag_notify_wlan_close(); + ptt_sock_deactivate_svc(); +#endif /* WLAN_KD_READY_NOTIFIER */ + nl_srv_exit(); + + /* Free up dynamically allocated members inside HDD Adapter */ + kfree(pHddCtx->config); + pHddCtx->config = NULL; + + wiphy_unregister(pHddCtx->wiphy); + wiphy_free(pHddCtx->wiphy); + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy( + &pHddCtx->hdd_conc_list_lock))) { + hdd_err("Failed to destroy hdd_conc_list_lock"); + /* Proceed and complete the clean up */ + } + } + +err_re_init: + /* Allow the phone to go to sleep */ + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT); + CDF_BUG(0); + return -EPERM; + +success: + pHddCtx->isLogpInProgress = false; + return CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_set_powersave() - Set powersave mode + * @adapter: adapter upon which the request was received + * @mode: desired powersave mode + * + * Return: 0 on success, non-zero on any error + */ +static int +wlan_hdd_set_powersave(hdd_adapter_t *adapter, enum hdd_power_mode mode) +{ + tHalHandle hal; + hdd_context_t *hdd_ctx; + + if (NULL == adapter) { + hddLog(CDF_TRACE_LEVEL_FATAL, FL("Adapter NULL")); + return -ENODEV; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err(FL("hdd context is NULL")); + return -EINVAL; + } + + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("power mode=%d"), mode); + hal = WLAN_HDD_GET_HAL_CTX(adapter); + + + if (DRIVER_POWER_MODE_ACTIVE == mode) { + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Wlan driver Entering Full Power")); + + /* + * Enter Full power command received from GUI + * this means we are disconnected + */ + sme_ps_enable_disable(hal, adapter->sessionId, SME_PS_DISABLE); + } else if (DRIVER_POWER_MODE_AUTO == mode) { + if ((WLAN_HDD_INFRA_STATION == adapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == adapter->device_mode)) { + hddLog(LOG1, FL("Disabling Auto Power save timer")); + sme_ps_disable_auto_ps_timer(WLAN_HDD_GET_HAL_CTX + (adapter), + adapter->sessionId); + } + if (hdd_ctx->config && hdd_ctx->config->is_ps_enabled) { + hddLog(LOG1, FL("Wlan driver Entering Power save")); + + /* + * Enter Power Save command received from GUI + * this means DHCP is completed + */ + sme_ps_enable_disable(hal, adapter->sessionId, + SME_PS_ENABLE); + } else { + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Power Save is not enabled in the cfg")); + } + } + return 0; +} + +/** + * __wlan_hdd_cfg80211_resume_wlan() - cfg80211 resume callback + * @wiphy: Pointer to wiphy + * + * This API is called when cfg80211 driver resumes driver updates + * latest sched_scan scan result(if any) to cfg80211 database + * + * Return: integer status + */ +static 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; + CDF_STATUS status = CDF_STATUS_SUCCESS; + int result; + p_cds_sched_context cds_sched_context = get_cds_sched_ctxt(); + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + result = wlan_hdd_validate_context(pHddCtx); + if (0 != result) { + hddLog(LOGE, FL("HDD context is not valid")); + return result; + } +#ifdef CONFIG_CNSS + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_MEDIUM); +#endif + + /* Resume MC thread */ + if (pHddCtx->isMcThreadSuspended) { + complete(&cds_sched_context->ResumeMcEvent); + pHddCtx->isMcThreadSuspended = false; + } +#ifdef QCA_CONFIG_SMP + /* Resume tlshim Rx thread */ + if (pHddCtx->is_ol_rx_thread_suspended) { + complete(&cds_sched_context->ol_resume_rx_event); + pHddCtx->is_ol_rx_thread_suspended = false; + } +#endif + hdd_resume_wlan(); + + 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 updatating cfg80211 data old results again */ + pHddCtx->isSchedScanUpdatePending = false; + spin_unlock(&pHddCtx->schedScan_lock); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && CDF_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, 0)) { + 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. Whis 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")); + + return result; + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + hddLog(LOG1, FL("Failed to find Adapter")); + return result; +} + +/** + * wlan_hdd_cfg80211_ready_to_suspend() - set cfg80211 ready to suspend event + * @callbackContext: Pointer to callback context + * @suspended: Suspend flag + * + * Return: none + */ +static void wlan_hdd_cfg80211_ready_to_suspend(void *callbackContext, + bool suspended) +{ + hdd_context_t *pHddCtx = (hdd_context_t *) callbackContext; + pHddCtx->suspended = suspended; + complete(&pHddCtx->ready_to_suspend); +} + +/** + * wlan_hdd_cfg80211_resume_wlan() - cfg80211 resume callback + * @wiphy: Pointer to wiphy + * + * This API is called when cfg80211 driver resumes driver updates + * latest sched_scan scan result(if any) to cfg80211 database + * + * Return: integer status + */ +int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_resume_wlan(wiphy); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_suspend_wlan() - cfg80211 suspend callback + * @wiphy: Pointer to wiphy + * @wow: Pointer to wow + * + * This API is called when cfg80211 driver suspends + * + * Return: integer status + */ +static 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); + p_cds_sched_context cds_sched_context = get_cds_sched_ctxt(); + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter; + hdd_scaninfo_t *pScanInfo; + CDF_STATUS status; + int rc; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + rc = wlan_hdd_validate_context(pHddCtx); + if (0 != rc) { + hddLog(LOGE, FL("HDD context is not valid")); + return rc; + } + + /* 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 && CDF_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) { + if (BSS_START == + WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter)->bssState && + true == + WLAN_HDD_GET_AP_CTX_PTR(pAdapter)-> + dfs_cac_block_tx) { + hddLog(LOG1, + FL("RADAR detection in progress, do not allow suspend")); + return -EAGAIN; + } else if (!pHddCtx->config->enableSapSuspend) { + /* return -EOPNOTSUPP if SAP does not support + * suspend + */ + hddLog(LOGE, + FL("SAP does not support suspend!!")); + return -EOPNOTSUPP; + } + } else if (WLAN_HDD_P2P_GO == pAdapter->device_mode) { + if (!pHddCtx->config->enableSapSuspend) { + /* return -EOPNOTSUPP if GO does not support + * suspend + */ + hddLog(LOGE, + FL("GO does not support suspend!!")); + 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 && CDF_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + pScanInfo = &pAdapter->scan_info; + + if (sme_sta_in_middle_of_roaming + (pHddCtx->hHal, pAdapter->sessionId)) { + hddLog(LOG1, + FL("Roaming in progress, do not allow suspend")); + return -EAGAIN; + } + + if (pHddCtx->config->is_ps_enabled) { + if (sme_is_auto_ps_timer_running(pHddCtx->hHal, + pAdapter->sessionId)) { + hddLog(LOGE, + FL("Auto Power save timer is running; Do not allow suspend")); + return -EAGAIN; + } else { + sme_ps_enable_disable(pHddCtx->hHal, + pAdapter->sessionId, + SME_PS_ENABLE); + hddLog(LOG1, + FL("Auto PS timer is not running; allow suspend and enter into power save")); + } + } + + if (pScanInfo->mScanPending) { + 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) { + hddLog(LOGE, + FL("Timeout occurred while waiting for abort scan")); + return -ETIME; + } + } + status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + /* + * Suspend IPA early before proceeding to suspend other entities like + * firmware to avoid any race conditions. + */ + if (hdd_ipa_suspend(pHddCtx)) { + hddLog(LOG1, FL("IPA not ready to suspend!")); + return -EAGAIN; + } + + /* 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) { + hddLog(LOGE, FL("Failed to get ready to suspend")); + goto resume_tx; + } + + if (!pHddCtx->suspended) { + hddLog(LOGE, FL("Faied as suspend_status is wrong:%d"), + pHddCtx->suspended); + goto resume_tx; + } + + /* Suspend MC thread */ + set_bit(MC_SUSPEND_EVENT_MASK, &cds_sched_context->mcEventFlag); + wake_up_interruptible(&cds_sched_context->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, + &cds_sched_context->mcEventFlag); + hddLog(LOGE, FL("Failed to stop mc thread")); + goto resume_tx; + } + + pHddCtx->isMcThreadSuspended = true; + +#ifdef QCA_CONFIG_SMP + /* Suspend tlshim rx thread */ + set_bit(RX_SUSPEND_EVENT_MASK, &cds_sched_context->ol_rx_event_flag); + wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue); + rc = wait_for_completion_timeout(&cds_sched_context-> + ol_suspend_rx_event, + msecs_to_jiffies + (RX_TLSHIM_SUSPEND_TIMEOUT)); + if (!rc) { + clear_bit(RX_SUSPEND_EVENT_MASK, + &cds_sched_context->ol_rx_event_flag); + hddLog(LOGE, FL("Failed to stop tl_shim rx thread")); + goto resume_all; + } + pHddCtx->is_ol_rx_thread_suspended = true; +#endif + + 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(&cds_sched_context->ResumeMcEvent); + pHddCtx->isMcThreadSuspended = false; +#endif + +resume_tx: + + hdd_resume_wlan(); + return -ETIME; + +} + +/** + * wlan_hdd_cfg80211_suspend_wlan() - cfg80211 suspend callback + * @wiphy: Pointer to wiphy + * @wow: Pointer to wow + * + * This API is called when cfg80211 driver suspends + * + * Return: integer status + */ +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_power_mgmt() - set cfg80211 power management config + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @mode: Driver mode + * @timeout: Timeout value + * + * Return: 0 for success, non-zero for failure + */ +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; + CDF_STATUS cdf_status; + int status; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + if ((DRIVER_POWER_MODE_AUTO == !mode) && + (true == pHddCtx->hdd_wlan_suspended) && + (pHddCtx->config->fhostArpOffload) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { + + hddLog(LOG1, + FL("offload: in cfg80211_set_power_mgmt, calling arp offload")); + cdf_status = hdd_conf_arp_offload(pAdapter, true); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOG1, + FL("Failed to enable ARPOFFLOAD Feature %d"), + cdf_status); + } + } + + status = wlan_hdd_set_powersave(pAdapter, !mode); + + if (!mode) { + hddLog(LOGE, FL("DHCP start indicated through power save")); + sme_dhcp_start_ind(pHddCtx->hHal, pAdapter->device_mode, + pAdapter->macAddressCurrent.bytes, + pAdapter->sessionId); + } else { + hddLog(LOGW, FL("DHCP stop indicated through power save")); + sme_dhcp_stop_ind(pHddCtx->hHal, pAdapter->device_mode, + pAdapter->macAddressCurrent.bytes, + pAdapter->sessionId); + } + + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_set_power_mgmt() - set cfg80211 power management config + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @mode: Driver mode + * @timeout: Timeout value + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, bool mode, + int timeout) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, mode, timeout); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_set_txpower() - set TX power + * @wiphy: Pointer to wiphy + * @wdev: Pointer to network device + * @type: TX power setting type + * @dbm: TX power in dbm + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + 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(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SET_TXPOWER, + NO_SESSION, type)); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + hHal = pHddCtx->hHal; + + if (0 != sme_cfg_set_int(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, dbm)) { + hddLog(LOGE, FL("sme_cfg_set_int failed for tx power %hu"), + dbm); + return -EIO; + } + + hddLog(LOG2, 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_set_max_tx_power(hHal, bssid, selfMac, dbm) != + CDF_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; +} + +/** + * wlan_hdd_cfg80211_set_txpower() - set TX power + * @wiphy: Pointer to wiphy + * @wdev: Pointer to network device + * @type: TX power setting type + * @dbm: TX power in dbm + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + struct wireless_dev *wdev, +#endif + enum nl80211_tx_power_setting type, + int dbm) +{ + int ret; + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_txpower(wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + wdev, +#endif + type, dbm); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_get_txpower() - get TX power + * @wiphy: Pointer to wiphy + * @wdev: Pointer to network device + * @dbm: Pointer to TX power in dbm + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + struct wireless_dev *wdev, +#endif + int *dbm) +{ + + hdd_adapter_t *pAdapter; + hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy); + int status; + + ENTER(); + + if (CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + *dbm = 0; + return status; + } + + pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); + if (NULL == pAdapter) { + hddLog(LOGE, FL("pAdapter is NULL")); + return -ENOENT; + } + + wlan_hdd_get_class_astats(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. + */ +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; + + cds_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); + cds_ssr_unprotect(__func__); + + return ret; +} diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c new file mode 100644 index 000000000000..2804c59f2f69 --- /dev/null +++ b/core/hdd/src/wlan_hdd_scan.c @@ -0,0 +1,2429 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_scan.c + * + * WLAN Host Device Driver scan implementation + */ + +#include +#include + +#include "wlan_hdd_includes.h" +#include "cds_api.h" +#include "cds_api.h" +#include "ani_global.h" +#include "dot11f.h" +#include "cds_sched.h" +#include "wlan_hdd_p2p.h" +#include "wlan_hdd_trace.h" +#include "wlan_hdd_scan.h" +#include "cds_concurrency.h" +#include "wma_api.h" + +#define MAX_RATES 12 +#define HDD_WAKE_LOCK_SCAN_DURATION (5 * 1000) /* in msec */ + +#define SCAN_DONE_EVENT_BUF_SIZE 4096 +#define RATE_MASK 0x7f + +/** + * typedef tSSIDBcastType - SSID broadcast type + * @eBCAST_UNKNOWN: Broadcast unknown + * @eBCAST_NORMAL: Broadcast normal + * @eBCAST_HIDDEN: Broadcast hidden + */ +typedef enum eSSIDBcastType { + eBCAST_UNKNOWN = 0, + eBCAST_NORMAL = 1, + eBCAST_HIDDEN = 2, +} tSSIDBcastType; + + +/** + * typedef hdd_scan_info_t - HDD scan info + * @dev: Pointer to net device + * @info: Pointer to request info + * @start: Start pointer + * @end: End pointer + */ +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; + +/** + * hdd_translate_abg_rate_to_mbps_rate() - translate abg rate to Mbps rate + * @pFcRate: Rate pointer + * + * Return: Mbps rate in integer + */ +static int32_t hdd_translate_abg_rate_to_mbps_rate(uint8_t *pFcRate) +{ + /* Slightly more sophisticated processing has to take place here. + * Basic rates are rounded DOWN. HT rates are rounded UP + */ + return ((((int32_t) *pFcRate) & 0x007f) * 1000000) / 2; +} + +/** + * hdd_add_iw_stream_event() - add iw stream event + * @cmd: Command + * @length: Length + * @data: Pointer to data + * @pscanInfo: Pointer to scan info + * @last_event: Pointer to pointer to last event + * @current_event: Pointer to pointer to current event + * + * Return: 0 for success, non zero for failure + */ +static int hdd_add_iw_stream_event(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; + cdf_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; +} + +/** + * hdd_get_wparsn_ies() - get wpa RSN IEs + * @ieFields: Pointer to the Bss Descriptor IEs + * @ie_length: IE Length + * @last_event: Points to last event + * @current_event: Points to current event + * + * This function extract the WPA/RSN IE from the Bss descriptor IEs fields + * + * Return: 0 for success, non zero for failure + */ +static int hdd_get_wparsn_ies(uint8_t *ieFields, uint16_t ie_length, + char **last_event, char **current_event, + hdd_scan_info_t *pscanInfo) +{ + uint8_t eid, elen, *element; + uint16_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_add_iw_stream_event + (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; +} + +/** + * hdd_indicate_scan_result() - indicate scan results + * @scanInfo: Pointer to the scan info structure. + * @descriptor: Pointer to the Bss Descriptor. + * + * This function returns the scan results to the wpa_supplicant + * + * @Return: 0 for success, non zero for failure + */ +#define MAX_CUSTOM_LEN 64 +static int hdd_indicate_scan_result(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; + uint16_t ie_length = 0; + uint16_t capabilityInfo; + char *modestr; + int error; + char custom[MAX_CUSTOM_LEN]; + char *p; + + hddLog(LOG1, "hdd_indicate_scan_result " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(descriptor->bssId)); + + error = 0; + last_event = current_event; + cdf_mem_zero(&event, sizeof(event)); + + /* BSSID */ + event.cmd = SIOCGIWAP; + event.u.ap_addr.sa_family = ARPHRD_ETHER; + cdf_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_indicate_scan_result: no space for SIOCGIWAP "); + return -E2BIG; + } + + last_event = current_event; + cdf_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_indicate_scan_result: no space for SIOCGIWNAME"); + /* Error code, may be E2BIG */ + return -E2BIG; + } + + last_event = current_event; + cdf_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_indicate_scan_result: no space for SIOCGIWFREQ"); + return -E2BIG; + } + + last_event = current_event; + cdf_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_indicate_scan_result: 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; + + dot11f_unpack_beacon_i_es((tpAniSirGlobal) + hHal, (uint8_t *) descriptor->ieFields, + ie_length, &dot11BeaconIEs); + + pDot11SSID = &dot11BeaconIEs.SSID; + + if (pDot11SSID->present) { + last_event = current_event; + cdf_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_indicate_scan_result: no space for SIOCGIWESSID"); + return -E2BIG; + } + } + + if (hdd_get_wparsn_ies + ((uint8_t *) descriptor->ieFields, ie_length, &last_event, + ¤t_event, scanInfo) < 0) { + hddLog(LOGE, + "hdd_indicate_scan_result: no space for SIOCGIWESSID"); + return -E2BIG; + } + + last_event = current_event; + current_pad = current_event + IW_EV_LCP_LEN; + cdf_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; i < pDot11SuppRates->num_rates; i++) { + if (0 != (pDot11SuppRates->rates[i] & 0x7F)) { + event.u.bitrate.value = + hdd_translate_abg_rate_to_mbps_rate + (&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 = CDF_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_translate_abg_rate_to_mbps_rate + (&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_indicate_scan_result: no space for SIOCGIWRATE"); + return -E2BIG; + } + } + + last_event = current_event; + cdf_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) { + hddLog(LOGE, + "hdd_indicate_scan_result: no space for SIOCGIWENCODE"); + return -E2BIG; + } + } + + last_event = current_event; + cdf_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 = CDF_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_indicate_scan_result: no space for IWEVQUAL"); + return -E2BIG; + } + + /* AGE */ + event.cmd = IWEVCUSTOM; + p = custom; + p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu", + cdf_mc_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_indicate_scan_result: no space for IWEVCUSTOM (age)"); + return -E2BIG; + } + + scanInfo->start = current_event; + + return 0; +} + + +/** + * wlan_hdd_scan_request_enqueue() - enqueue Scan Request + * @adapter: Pointer to the adapter + * @scan_req: Pointer to the scan request + * + * Enqueue scan request in the global HDD scan list.This list + * stores the active scan request information. + * + * Return: 0 on success, error number otherwise + */ +static int wlan_hdd_scan_request_enqueue(hdd_adapter_t *adapter, + struct cfg80211_scan_request *scan_req, + uint8_t source, uint32_t scan_id, + uint32_t timestamp) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct hdd_scan_req *hdd_scan_req; + CDF_STATUS status; + + ENTER(); + hdd_scan_req = cdf_mem_malloc(sizeof(*hdd_scan_req)); + if (NULL == hdd_scan_req) { + hddLog(LOGP, FL("malloc failed for Scan req")); + return -ENOMEM; + } + + hdd_scan_req->adapter = adapter; + hdd_scan_req->scan_request = scan_req; + hdd_scan_req->source = source; + hdd_scan_req->scan_id = scan_id; + hdd_scan_req->timestamp = timestamp; + + cdf_spin_lock(&hdd_ctx->hdd_scan_req_q_lock); + status = cdf_list_insert_back(&hdd_ctx->hdd_scan_req_q, + &hdd_scan_req->node); + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + + if (CDF_STATUS_SUCCESS != status) { + hdd_err("Failed to enqueue Scan Req"); + cdf_mem_free(hdd_scan_req); + return -EINVAL; + } + EXIT(); + return 0; +} + +/** + * wlan_hdd_scan_request_dequeue() - dequeue scan request + * @hdd_ctx: Global HDD context + * @scan_id: scan id + * @req: scan request + * @source : returns source of the scan request + * @timestamp: scan request timestamp + * + * Return: CDF_STATUS + */ +CDF_STATUS wlan_hdd_scan_request_dequeue(hdd_context_t *hdd_ctx, + uint32_t scan_id, struct cfg80211_scan_request **req, uint8_t *source, + uint32_t *timestamp) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + struct hdd_scan_req *hdd_scan_req; + cdf_list_node_t *pNode = NULL, *ppNode = NULL; + + hdd_info("Dequeue Scan id: %d", scan_id); + + if ((source == NULL) && (timestamp == NULL) && (req == NULL)) + return CDF_STATUS_E_NULL_VALUE; + + cdf_spin_lock(&hdd_ctx->hdd_scan_req_q_lock); + + if (list_empty(&hdd_ctx->hdd_scan_req_q.anchor)) { + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + return CDF_STATUS_E_FAILURE; + } + + if (CDF_STATUS_SUCCESS != + cdf_list_peek_front(&hdd_ctx->hdd_scan_req_q, &ppNode)) { + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + hdd_err("Failed to remove Scan Req from queue"); + return CDF_STATUS_E_FAILURE; + } + + do { + pNode = ppNode; + hdd_scan_req = (struct hdd_scan_req *)pNode; + if (hdd_scan_req->scan_id == scan_id) { + status = cdf_list_remove_node(&hdd_ctx->hdd_scan_req_q, + pNode); + if (status == CDF_STATUS_SUCCESS) { + *req = hdd_scan_req->scan_request; + *source = hdd_scan_req->source; + *timestamp = hdd_scan_req->timestamp; + cdf_mem_free(hdd_scan_req); + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + hdd_info("removed Scan id: %d, req = %p", + scan_id, req); + return CDF_STATUS_SUCCESS; + } else { + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + hdd_err("Failed to remove node scan id %d", + scan_id); + return status; + } + } + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&hdd_ctx->hdd_scan_req_q, pNode, &ppNode)); + + cdf_spin_unlock(&hdd_ctx->hdd_scan_req_q_lock); + hdd_err("Failed to find scan id %d", scan_id); + return status; +} + +/** + * hdd_scan_request_callback() - scan complete callback from SME + * @halHandle: Pointer to the Hal Handle + * @pContext: Pointer to the data context + * @sessionId: Session identifier + * @scanId: Scan ID + * @status: CSR Status + * + * 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. + * + * Return: 0 for success, non zero for failure + */ + +static CDF_STATUS +hdd_scan_request_callback(tHalHandle halHandle, void *pContext, + uint8_t sessionId, uint32_t scanId, + eCsrScanStatus status) +{ + struct net_device *dev = (struct net_device *)pContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(pAdapter); + union iwreq_data wrqu; + int we_event; + char *msg; + uint8_t source; + struct cfg80211_scan_request *req; + uint32_t timestamp; + uint32_t size = 0; + + 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 CDF_STATUS_SUCCESS; + } + + wlan_hdd_scan_request_dequeue(hddctx, scanId, &req, &source, + ×tamp); + + if (req != NULL) + hdd_err("Got unexpected request struct for Scan id %d", + scanId); + + cdf_spin_lock(&hddctx->hdd_scan_req_q_lock); + cdf_list_size(&(hddctx->hdd_scan_req_q), &size); + if (!size) + /* Scan is no longer pending */ + pAdapter->scan_info.mScanPending = false; + cdf_spin_unlock(&hddctx->hdd_scan_req_q_lock); + + /* 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(); + return CDF_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 for success, non zero for failure + */ + +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 *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + tCsrScanRequest scanRequest; + CDF_STATUS status = CDF_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(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: enter !!!", + __func__); + + /* 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 (CDS_IS_DFS_CH(con_dfs_ch)) { + hddLog(LOGW, FL("##In DFS Master mode. Scan aborted")); + return -EOPNOTSUPP; + } + } + + cdf_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 == hdd_ctx->ioctl_scan_mode)) { + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } else { + scanRequest.scanType = eSIR_PASSIVE_SCAN; + } + + /* set bssid using sockaddr from iw_scan_req */ + cdf_mem_copy(scanRequest.bssid.bytes, + &scanReq->bssid.sa_data, + CDF_MAC_ADDR_SIZE); + + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + + if (scanReq->essid_len) { + scanRequest.SSIDs.numOfSSIDs = 1; + scanRequest.SSIDs.SSIDList = + (tCsrSSIDInfo *) + cdf_mem_malloc(sizeof(tCsrSSIDInfo)); + if (scanRequest.SSIDs.SSIDList) { + scanRequest.SSIDs.SSIDList->SSID. + length = scanReq->essid_len; + cdf_mem_copy(scanRequest.SSIDs. + SSIDList->SSID.ssId, + scanReq->essid, + scanReq->essid_len); + } else { + scanRequest.SSIDs.numOfSSIDs = 0; + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Unable to allocate memory", + __func__); + CDF_ASSERT(0); + } + } + } + + /* set min and max channel time */ + scanRequest.minChnTime = scanReq->min_channel_time; + scanRequest.maxChnTime = scanReq->max_channel_time; + + } else { + if (hdd_ctx->ioctl_scan_mode == eSIR_ACTIVE_SCAN) { + /* set the scan type to active */ + scanRequest.scanType = eSIR_ACTIVE_SCAN; + } else { + scanRequest.scanType = eSIR_PASSIVE_SCAN; + } + + cdf_set_macaddr_broadcast(&scanRequest.bssid); + + /* 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; + } + scanRequest.timestamp = cdf_mc_timer_get_system_ticks(); + status = sme_scan_request((WLAN_HDD_GET_CTX(pAdapter))->hHal, + pAdapter->sessionId, &scanRequest, + &hdd_scan_request_callback, dev); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s:sme_scan_request fail %d!!!", __func__, status); + goto error; + } + + wlan_hdd_scan_request_enqueue(pAdapter, NULL, NL_SCAN, + scanRequest.scan_id, + scanRequest.timestamp); + + pAdapter->scan_info.mScanPending = true; +error: + if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len)) + cdf_mem_free(scanRequest.SSIDs.SSIDList); + EXIT(); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: exit !!!", + __func__); + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_scan(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_scan() - 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. + * + * This function returns the scan results to the wpa_supplicant + * + * Return: 0 for success, non zero for failure + */ + +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); + hdd_context_t *hdd_ctx; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + tCsrScanResultInfo *pScanResult; + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_scan_info_t scanInfo; + tScanResultHandle pResult; + int i = 0; + int ret; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult); + + if (NULL == pResult) { + /* no scan results */ + hddLog(LOG1, "iw_get_scan: NULL Scan Result "); + return 0; + } + + pScanResult = sme_scan_result_get_first(hHal, pResult); + + while (pScanResult) { + status = hdd_indicate_scan_result(&scanInfo, pScanResult); + if (0 != status) { + break; + } + i++; + pScanResult = sme_scan_result_get_next(hHal, pResult); + } + + sme_scan_result_purge(hHal, pResult); + + EXIT(); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: exit total %d BSS reported !!!", __func__, i); + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_scan(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_abort_mac_scan() - aborts ongoing mac scan + * @pHddCtx: Pointer to hdd context + * @sessionId: session id + * @reason: abort reason + * + * Abort any MAC scan if in progress + * + * Return: none + */ +void hdd_abort_mac_scan(hdd_context_t *pHddCtx, uint8_t sessionId, + eCsrAbortReason reason) +{ + sme_abort_mac_scan(pHddCtx->hHal, sessionId, reason); +} + +/** + * hdd_vendor_scan_callback() - Scan completed callback event + * @hddctx: HDD context + * @req : Scan request + * @aborted : true scan aborted false scan success + * + * This function sends scan completed callback event to NL. + * + * Return: none + */ +static void hdd_vendor_scan_callback(hdd_adapter_t *adapter, + struct cfg80211_scan_request *req, + bool aborted) +{ + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(adapter); + struct sk_buff *skb; + struct nlattr *attr; + int i; + uint8_t scan_status; + uint64_t cookie; + + ENTER(); + + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hdd_err("Invalid adapter magic"); + return; + } + skb = cfg80211_vendor_event_alloc(hddctx->wiphy, NULL, + SCAN_DONE_EVENT_BUF_SIZE + 4 + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX, + GFP_KERNEL); + + if (!skb) { + hdd_err("skb alloc failed"); + return; + } + + if (0 != hdd_vendor_put_ifindex(skb, adapter->dev->ifindex)) + goto nla_put_failure; + + cookie = (uintptr_t)req; + + attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS); + if (!attr) + goto nla_put_failure; + for (i = 0; i < req->n_ssids; i++) { + if (nla_put(skb, i, req->ssids[i].ssid_len, req->ssids[i].ssid)) + goto nla_put_failure; + } + nla_nest_end(skb, attr); + + attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES); + if (!attr) + goto nla_put_failure; + for (i = 0; i < req->n_channels; i++) { + if (nla_put_u32(skb, i, req->channels[i]->center_freq)) + goto nla_put_failure; + } + nla_nest_end(skb, attr); + + if (req->ie && + nla_put(skb, QCA_WLAN_VENDOR_ATTR_SCAN_IE, req->ie_len, + req->ie)) + goto nla_put_failure; + + if (req->flags && + nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, req->flags)) + goto nla_put_failure; + + if (nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, cookie)) + goto nla_put_failure; + + scan_status = (aborted == true) ? VENDOR_SCAN_STATUS_ABORTED : + VENDOR_SCAN_STATUS_NEW_RESULTS; + if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return; + +nla_put_failure: + kfree_skb(skb); + return; +} + +/** + * hdd_cfg80211_scan_done_callback() - scan done callback function called after + * scan is finished + * @halHandle: Pointer to handle + * @pContext: Pointer to context + * @sessionId: Session Id + * @scanId: Scan Id + * @status: Scan status + * + * Return: CDF status + */ +static CDF_STATUS hdd_cfg80211_scan_done_callback(tHalHandle halHandle, + void *pContext, + uint8_t sessionId, + uint32_t scanId, + eCsrScanStatus status) +{ + struct net_device *dev = (struct net_device *)pContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info; + struct cfg80211_scan_request *req = NULL; + bool aborted = false; + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(pAdapter); + int ret = 0; + uint8_t source; + uint32_t scan_time; + uint32_t size = 0; + + hddLog(CDF_TRACE_LEVEL_INFO, + "%s called with hal = %p, pContext = %p, ID = %d, status = %d", + __func__, halHandle, pContext, (int)scanId, (int)status); + + pScanInfo->mScanPendingCounter = 0; + + if (pScanInfo->mScanPending != true) { + CDF_ASSERT(pScanInfo->mScanPending); + goto allow_suspend; + } + + if (CDF_STATUS_SUCCESS != + wlan_hdd_scan_request_dequeue(hddctx, scanId, &req, &source, + &scan_time)) { + hdd_err("Dequeue of scan request failed ID: %d", scanId); + goto allow_suspend; + } + + ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, + pAdapter, scan_time); + if (0 > ret) + hddLog(CDF_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + + /* + * cfg80211_scan_done informing NL80211 about completion + * of scanning + */ + if (status == eCSR_SCAN_ABORT || status == eCSR_SCAN_FAILURE) { + aborted = true; + } + + cdf_spin_lock(&hddctx->hdd_scan_req_q_lock); + cdf_list_size(&(hddctx->hdd_scan_req_q), &size); + if (!size) { + /* Scan is no longer pending */ + pScanInfo->mScanPending = false; + complete(&pScanInfo->abortscan_event_var); + } + cdf_spin_unlock(&hddctx->hdd_scan_req_q_lock); + /* + * Scan can be triggred from NL or vendor scan + * - If scan is triggered from NL then cfg80211 scan done should be + * called to updated scan completion to NL. + * - If scan is triggred through vendor command then + * scan done event will be posted + */ + if (NL_SCAN == source) + cfg80211_scan_done(req, aborted); + else + hdd_vendor_scan_callback(pAdapter, req, aborted); + +allow_suspend: + if (!size) { + /* 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 immediatly after the driver gets connect + * request(i.e after scan) from supplicant, this result in + * app's is suspending and not ableto process the connect + * request to AP + */ + hdd_prevent_suspend_timeout(1000, + WIFI_POWER_EVENT_WAKELOCK_SCAN); + } + +#ifdef FEATURE_WLAN_TDLS + wlan_hdd_tdls_scan_done_callback(pAdapter); +#endif + + EXIT(); + return 0; +} + + +/** + * wlan_hdd_cfg80211_scan_block_cb() - scan block work handler + * @work: Pointer to work + * + * Return: none + */ +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 = adapter->request; + + request->n_ssids = 0; + request->n_channels = 0; + + hddLog(LOGE, + FL("##In DFS Master mode. Scan aborted. Null result sent")); + cfg80211_scan_done(request, true); + adapter->request = NULL; +} + +/** + * __wlan_hdd_cfg80211_scan() - API to process cfg80211 scan request + * @wiphy: Pointer to wiphy + * @dev: Pointer to net device + * @request: Pointer to scan request + * @source: scan request source(NL/Vendor scan) + * + * This API responds to scan trigger and update cfg80211 scan database + * later, scan dump command can be used to recieve scan results + * + * Return: 0 for success, non zero for failure + */ +static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request, + uint8_t source) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) + 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); + struct hdd_config *cfg_param = NULL; + tCsrScanRequest scan_req; + uint8_t *channelList = NULL, i; + int status; + hdd_scaninfo_t *pScanInfo = NULL; + uint8_t *pP2pIe = NULL; + hdd_adapter_t *con_sap_adapter; + uint16_t con_dfs_ch; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_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) { + hddLog(LOGE, FL("HDD context is not valid")); + return status; + } + + cfg_param = pHddCtx->config; + 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.sapConfig.channel; + if (con_dfs_ch == AUTO_CHANNEL_SELECT) + con_dfs_ch = + con_sap_adapter->sessionCtx.ap.operatingChannel; + + if (CDS_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 (!wma_is_hw_dbs_capable()) { + if (true == pScanInfo->mScanPending) { + if (MAX_PENDING_LOG > + pScanInfo->mScanPendingCounter++) { + hddLog(LOGE, FL("mScanPending is true")); + } + 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(LOGE, FL("Remain On Channel Pending")); + 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)) + dev, +#endif + request); + if (status <= 0) { + if (!status) + hddLog(LOGE, + FL("TDLS in progress.scan rejected %d"), + status); + else + hddLog(LOGE, FL("TDLS teardown is ongoing %d"), + status); + return status; + } +#endif + + /* Check if scan is allowed at this point of time */ + if (cds_is_connection_in_progress(pHddCtx)) { + hddLog(LOGE, FL("Scan not allowed")); + return -EBUSY; + } + + cdf_mem_zero(&scan_req, sizeof(scan_req)); + + hddLog(LOG1, "scan request for ssid = %d", request->n_ssids); + scan_req.timestamp = cdf_mc_timer_get_system_ticks(); + + /* 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; + scan_req.SSIDs.numOfSSIDs = request->n_ssids; + /* Allocate num_ssid tCsrSSIDInfo structure */ + SsidInfo = scan_req.SSIDs.SSIDList = + cdf_mem_malloc(request->n_ssids * sizeof(tCsrSSIDInfo)); + + if (NULL == scan_req.SSIDs.SSIDList) { + hddLog(LOGE, FL("memory alloc failed SSIDInfo buffer")); + 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; + cdf_mem_copy(SsidInfo->SSID.ssId, + &request->ssids[j].ssid[0], + SsidInfo->SSID.length); + SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0'; + hddLog(LOG1, FL("SSID number %d: %s"), j, + SsidInfo->SSID.ssId); + } + /* set the scan type to active */ + scan_req.scanType = eSIR_ACTIVE_SCAN; + } else if (WLAN_HDD_P2P_GO == pAdapter->device_mode) { + /* set the scan type to active */ + scan_req.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) + scan_req.scanType = eSIR_PASSIVE_SCAN; + else + scan_req.scanType = pHddCtx->ioctl_scan_mode; + } + scan_req.minChnTime = cfg_param->nActiveMinChnTime; + scan_req.maxChnTime = cfg_param->nActiveMaxChnTime; + + /* set BSSType to default type */ + scan_req.BSSType = eCSR_BSS_TYPE_ANY; + + if (MAX_CHANNEL < request->n_channels) { + hddLog(LOGW, FL("No of Scan Channels exceeded limit: %d"), + request->n_channels); + request->n_channels = MAX_CHANNEL; + } + + hddLog(LOG1, FL("No of Scan Channels: %d"), request->n_channels); + + if (request->n_channels) { + char chList[(request->n_channels * 5) + 1]; + int len; + channelList = cdf_mem_malloc(request->n_channels); + if (NULL == channelList) { + hddLog(LOGE, + FL("channelList malloc failed channelList")); + status = -ENOMEM; + goto free_mem; + } + for (i = 0, len = 0; i < request->n_channels; i++) { + channelList[i] = request->channels[i]->hw_value; + len += snprintf(chList + len, 5, "%d ", channelList[i]); + } + + hddLog(LOG1, FL("Channel-List: %s"), chList); + + } + scan_req.ChannelInfo.numOfChannels = request->n_channels; + scan_req.ChannelInfo.ChannelList = channelList; + + /* set requestType to full scan */ + scan_req.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 shoudnt flush scan results. If + * driver flushes the scan results here and unfortunately if + * the AP doesnt respond to our probe req then association + * fails which is not desired + */ + + if (request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN) { + hddLog(CDF_TRACE_LEVEL_DEBUG, "Flushing P2P Results"); + sme_scan_flush_p2p_result(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; + } + + scan_req.uIEFieldLen = pScanInfo->scanAddIE.length; + scan_req.pIEField = pScanInfo->scanAddIE.addIEdata; + + pP2pIe = wlan_hdd_get_p2p_ie_ptr((uint8_t *) request->ie, + request->ie_len); + if (pP2pIe != NULL) { +#ifdef WLAN_FEATURE_P2P_DEBUG + if (((global_p2p_connection_status == P2P_GO_NEG_COMPLETED) + || (global_p2p_connection_status == + P2P_GO_NEG_PROCESS)) + && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { + global_p2p_connection_status = + P2P_CLIENT_CONNECTING_STATE_1; + hddLog(LOGE, + FL("[P2P State] Changing state from Go nego completed to Connection is started")); + hddLog(LOGE, + FL("[P2P]P2P Scanning is started for 8way Handshake")); + } else + if ((global_p2p_connection_status == + P2P_CLIENT_DISCONNECTED_STATE) + && (WLAN_HDD_P2P_CLIENT == + pAdapter->device_mode)) { + global_p2p_connection_status = + P2P_CLIENT_CONNECTING_STATE_2; + hddLog(LOGE, + FL("[P2P State] Changing state from Disconnected state to Connection is started")); + hddLog(LOGE, + FL("[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(CDF_TRACE_LEVEL_INFO, + "%s: This is a P2P Search", __func__); + scan_req.p2pSearch = 1; + + if (request->n_channels == + WLAN_HDD_P2P_SOCIAL_CHANNELS) { + /* set requestType to P2P Discovery */ + scan_req.requestType = + eCSR_SCAN_P2P_DISCOVERY; + } + + /* + * Skip Dfs Channel in case of P2P Search if it is set in + * ini file + */ + if (cfg_param->skipDfsChnlInP2pSearch) { + scan_req.skipDfsChnlInP2pSearch = 1; + } else { + scan_req.skipDfsChnlInP2pSearch = 0; + } + + } + } + } + + /* 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(LOG2, + FL("requestType %d, scanType %d, minChnTime %d, maxChnTime %d,p2pSearch %d, skipDfsChnlIn P2pSearch %d"), + scan_req.requestType, scan_req.scanType, + scan_req.minChnTime, scan_req.maxChnTime, + scan_req.p2pSearch, scan_req.skipDfsChnlInP2pSearch); + + status = sme_scan_request(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &scan_req, + &hdd_cfg80211_scan_done_callback, dev); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("sme_scan_request returned error %d"), status); + if (CDF_STATUS_E_RESOURCES == status) { + hddLog(LOGE, + FL("HO is in progress.So defer the scan by informing busy")); + status = -EBUSY; + } else { + status = -EIO; + } + + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN); + goto free_mem; + } + wlan_hdd_scan_request_enqueue(pAdapter, request, source, + scan_req.scan_id, scan_req.timestamp); + pAdapter->scan_info.mScanPending = true; + +free_mem: + if (scan_req.SSIDs.SSIDList) + cdf_mem_free(scan_req.SSIDs.SSIDList); + + if (channelList) + cdf_mem_free(channelList); + + EXIT(); + return status; +} + +/** + * wlan_hdd_cfg80211_scan() - API to process cfg80211 scan request + * @wiphy: Pointer to wiphy + * @dev: Pointer to net device + * @request: Pointer to scan request + * + * This API responds to scan trigger and update cfg80211 scan database + * later, scan dump command can be used to recieve scan results + * + * Return: 0 for success, non zero for failure + */ +int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ + int ret; + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_scan(wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + dev, +#endif + request, NL_SCAN); + cds_ssr_unprotect(__func__); + return ret; +} + +/** + * wlan_hdd_get_rates() -API to get the rates from scan request + * @wiphy: Pointer to wiphy + * @band: Band + * @rates: array of rates + * @rate_count: number of rates + * + * Return: o for failure, rate bitmap for success + */ +static uint32_t wlan_hdd_get_rates(struct wiphy *wiphy, + enum ieee80211_band band, + const u8 *rates, unsigned int rate_count) +{ + uint32_t j, count, rate_bitmap = 0; + uint32_t rate; + bool found; + + for (count = 0; count < rate_count; count++) { + rate = ((rates[count]) & RATE_MASK) * 5; + found = false; + for (j = 0; j < wiphy->bands[band]->n_bitrates; j++) { + if (wiphy->bands[band]->bitrates[j].bitrate == rate) { + found = true; + rate_bitmap |= (1 << j); + break; + } + } + if (!found) + return 0; + } + return rate_bitmap; +} + +/** + * wlan_hdd_send_scan_start_event() -API to send the scan start event + * @wiphy: Pointer to wiphy + * @wdev: Pointer to net device + * @cookie: scan identifier + * + * Return: return 0 on success and negative error code on failure + */ +static int wlan_hdd_send_scan_start_event(struct wiphy *wiphy, + struct wireless_dev *wdev, uint64_t cookie) +{ + struct sk_buff *skb; + int ret; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) + + NLA_HDRLEN + NLMSG_HDRLEN); + if (!skb) { + hddLog(LOGE, FL(" reply skb alloc failed")); + return -ENOMEM; + } + + if (nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, cookie)) { + hddLog(LOGE, FL("nla put fail")); + kfree_skb(skb); + return -EINVAL; + } + + ret = cfg80211_vendor_cmd_reply(skb); + + /* Send a scan started event to supplicant */ + skb = cfg80211_vendor_event_alloc(wiphy, wdev, + sizeof(u64) + 4 + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX, GFP_KERNEL); + if (!skb) { + hddLog(LOGE, FL("skb alloc failed")); + return -ENOMEM; + } + + ret = hdd_vendor_put_ifindex(skb, wdev->netdev->ifindex); + if (ret) { + kfree_skb(skb); + return -EINVAL; + } + + if (nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, cookie)) { + kfree_skb(skb); + return -EINVAL; + } + cfg80211_vendor_event(skb, GFP_KERNEL); + + return ret; +} +/** + * __wlan_hdd_cfg80211_vendor_scan() - API to process venor scan request + * @wiphy: Pointer to wiphy + * @wdev: Pointer to net device + * @data : Pointer to the data + * @data_len : length of the data + * + * API to process venor scan request. + * + * Return: return 0 on success and negative error code on failure + */ +static int __wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, + int data_len) +{ + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1]; + struct cfg80211_scan_request *request = NULL; + struct nlattr *attr; + enum ieee80211_band band; + uint8_t n_channels = 0, n_ssid = 0, ie_len = 0; + uint32_t tmp, count, j; + unsigned int len; + struct ieee80211_channel *chan; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX, data, + data_len, NULL)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) { + nla_for_each_nested(attr, + tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES], tmp) + n_channels++; + } else { + for (band = 0; band < IEEE80211_NUM_BANDS; band++) + if (wiphy->bands[band]) + n_channels += wiphy->bands[band]->n_channels; + } + + if (MAX_CHANNEL < n_channels) { + hdd_err("Exceed max number of channels: %d", n_channels); + return -EINVAL; + } + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) + nla_for_each_nested(attr, + tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS], tmp) + n_ssid++; + + if (MAX_SCAN_SSID < n_ssid) { + hdd_err("Exceed max number of SSID: %d", n_ssid); + return -EINVAL; + } + + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]) + ie_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]); + else + ie_len = 0; + + len = sizeof(*request) + (sizeof(*request->ssids) * n_ssid) + + (sizeof(*request->channels) * n_channels) + ie_len; + + request = cdf_mem_malloc(len); + if (!request) + goto error; + if (n_ssid) + request->ssids = (void *)&request->channels[n_channels]; + request->n_ssids = n_ssid; + if (ie_len) { + if (request->ssids) + request->ie = (void *)(request->ssids + n_ssid); + else + request->ie = (void *)(request->channels + n_channels); + } + + count = 0; + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) { + nla_for_each_nested(attr, + tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES], + tmp) { + chan = __ieee80211_get_channel(wiphy, + nla_get_u32(attr)); + if (!chan) + goto error; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + request->channels[count] = chan; + count++; + } + } else { + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!wiphy->bands[band]) + continue; + for (j = 0; j < wiphy->bands[band]->n_channels; + j++) { + chan = &wiphy->bands[band]->channels[j]; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + request->channels[count] = chan; + count++; + } + } + } + + if (!count) + goto error; + + request->n_channels = count; + count = 0; + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) { + nla_for_each_nested(attr, tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS], + tmp) { + request->ssids[count].ssid_len = nla_len(attr); + memcpy(request->ssids[count].ssid, nla_data(attr), + nla_len(attr)); + count++; + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]) { + request->ie_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]); + memcpy((void *)request->ie, + nla_data(tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]), + request->ie_len); + } + + for (count = 0; count < IEEE80211_NUM_BANDS; count++) + if (wiphy->bands[count]) + request->rates[count] = + (1 << wiphy->bands[count]->n_bitrates) - 1; + + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES]) { + nla_for_each_nested(attr, + tb[QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES], + tmp) { + band = nla_type(attr); + if (!wiphy->bands[band]) + continue; + request->rates[band] = wlan_hdd_get_rates(wiphy, + band, nla_data(attr), + nla_len(attr)); + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS]) { + request->flags = + nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS]); + if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && + !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { + hddLog(LOGE, FL("LOW PRIORITY SCAN not supported")); + goto error; + } + } + request->no_cck = + nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE]); + request->wdev = wdev; + request->wiphy = wiphy; + request->scan_start = jiffies; + + if (0 != __wlan_hdd_cfg80211_scan(wiphy, request, VENDOR_SCAN)) + goto error; + + ret = wlan_hdd_send_scan_start_event(wiphy, wdev, (uintptr_t)request); + + return ret; +error: + hdd_err("Scan Request Failed"); + cdf_mem_free(request); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_vendor_scan() -API to process venor scan request + * @wiphy: Pointer to wiphy + * @dev: Pointer to net device + * @data : Pointer to the data + * @data_len : length of the data + * + * This is called from userspace to request scan. + * + * Return: Return the Success or Failure code. + */ +int wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_vendor_scan(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} +/** + * wlan_hdd_scan_abort() - abort ongoing scan + * @pAdapter: Pointer to interface adapter + * + * Return: 0 for success, non zero for failure + */ +#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) { + 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) { + hddLog(LOGE, + FL("Timeout occurred while waiting for abort scan")); + return -ETIME; + } + } + return 0; +} + +/** + * hdd_sched_scan_callback - scheduled scan callback + * @callbackContext: Callback context + * @pPrefNetworkFoundInd: Preferred network found indication + * + * This is a callback function that is registerd with SME that is + * invoked when a preferred network is discovered by firmware. + * + * Return: none + */ +static void +hdd_sched_scan_callback(void *callbackContext, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + int ret; + hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext; + hdd_context_t *pHddCtx; + + ENTER(); + + if (NULL == pAdapter) { + hddLog(LOGE, FL("HDD adapter is Null")); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (NULL == pHddCtx) { + hddLog(LOGE, FL("HDD context is Null!!!")); + return; + } + + spin_lock(&pHddCtx->schedScan_lock); + if (true == pHddCtx->isWiphySuspended) { + pHddCtx->isSchedScanUpdatePending = true; + spin_unlock(&pHddCtx->schedScan_lock); + hddLog(LOG1, + FL("Update cfg80211 scan database after it resume")); + return; + } + spin_unlock(&pHddCtx->schedScan_lock); + + ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter, 0); + + if (0 > ret) + hddLog(LOG1, FL("NO SCAN result")); + + cfg80211_sched_scan_results(pHddCtx->wiphy); + hddLog(LOG1, + FL("cfg80211 scan result database updated")); +} + +/** + * 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 CDF_STATUS 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 CDF_STATUS_SUCCESS; + else + return CDF_STATUS_E_FAILURE; + +} + +/** + * __wlan_hdd_cfg80211_sched_scan_start() - cfg80211 scheduled scan(pno) start + * @wiphy: Pointer to wiphy + * @dev: Pointer network device + * @request: Pointer to cfg80211 scheduled scan start request + * + * Return: 0 for success, non zero for failure + */ +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; + uint32_t i, indx, num_ch, tempInterval, j; + u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int ret = 0; + hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info; + struct hdd_config *config = NULL; + uint32_t num_ignore_dfs_ch = 0; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + 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; + } + + config = pHddCtx->config; + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) { + hddLog(LOGE, FL("HAL context is Null!!!")); + return -EINVAL; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (eConnectionState_Connecting == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { + hddLog(LOGE, + FL("%p(%d) Connection in progress: sched_scan_start denied (EBUSY)"), + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), + pAdapter->sessionId); + return -EBUSY; + } + + /* + * 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_scan_flush_result(hHal); + if (true == pScanInfo->mScanPending) { + ret = wlan_hdd_scan_abort(pAdapter); + if (ret < 0) { + hddLog(LOGE, + FL("aborting the existing scan is unsuccessful")); + return -EBUSY; + } + } + + if (CDF_STATUS_E_FAILURE == wlan_hdd_is_pno_allowed(pAdapter)) { + hddLog(LOGE, FL("pno is not allowed")); + return -ENOTSUPP; + } + + pPnoRequest = (tpSirPNOScanReq) cdf_mem_malloc(sizeof(tSirPNOScanReq)); + if (NULL == pPnoRequest) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + 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)) { + hddLog(LOGE, FL("Network input is not correct %d"), + pPnoRequest->ucNetworksCount); + ret = -EINVAL; + goto error; + } + + if (SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels) { + hddLog(LOGE, FL("Incorrect number of channels %d"), + request->n_channels); + ret = -EINVAL; + goto error; + } + + /* Framework provides one set of channels(all) + * common for all saved profile */ + if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST, + channels_allowed, &num_channels_allowed)) { + hddLog(LOGE, + FL("failed to get valid channel list")); + 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) + && (CHANNEL_STATE_DFS == + cds_get_channel_state( + channels_allowed[indx]))) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + "%s : Dropping DFS channel : %d", + __func__, + channels_allowed[indx]); + num_ignore_dfs_ch++; + break; + } + + valid_ch[num_ch++] = + request->channels[i]->hw_value; + len += + snprintf(chList + len, 5, "%d ", + request->channels[i]-> + hw_value); + break; + } + } + } + hddLog(LOG1, FL("Channel-List: %s "), chList); + + /* If all channels are DFS and dropped, + * then ignore the PNO request + */ + if (num_ignore_dfs_ch == request->n_channels) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s : All requested channels are DFS channels", + __func__); + ret = -EINVAL; + goto error; + } + + } + /* Filling per profile params */ + for (i = 0; i < pPnoRequest->ucNetworksCount; i++) { + pPnoRequest->aNetworks[i].ssId.length = + request->match_sets[i].ssid.ssid_len; + + if ((0 == pPnoRequest->aNetworks[i].ssId.length) || + (pPnoRequest->aNetworks[i].ssId.length > 32)) { + hddLog(LOGE, + FL(" SSID Len %d is not correct for network %d"), + 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) + pPnoRequest->aNetworks[i].rssiThreshold = + request->match_sets[i].rssi_thold; +#else + pPnoRequest->aNetworks[i].rssiThreshold = 0; /* Default value */ +#endif + } + + 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++; + } + } + hddLog(LOG1, FL("Number of hidden networks being Configured = %d"), + request->n_ssids); + + hddLog(LOG1, FL("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 hardcoded in + * supplicant for 10000ms. Taking power consumption into account 6 timers + * will be used, Timervalue is increased exponentially i.e 10,20,40, + * 80,160,320 secs. And number of scan cycle for each timer + * is configurable through INI param gPNOScanTimerRepeatValue. + * If it is set to 0 only one timer will be used and PNO scan cycle + * will be repeated after each interval specified by supplicant + * till PNO is disabled. + */ + if (0 == pHddCtx->config->configPNOScanTimerRepeatValue) + pPnoRequest->scanTimers.ucScanTimersCount = + HDD_PNO_SCAN_TIMERS_SET_ONE; + else + pPnoRequest->scanTimers.ucScanTimersCount = + HDD_PNO_SCAN_TIMERS_SET_MULTIPLE; + + tempInterval = (request->interval) / 1000; + hddLog(LOG1, + FL("Base scan interval = %d PNOScanTimerRepeatValue = %d"), + tempInterval, pHddCtx->config->configPNOScanTimerRepeatValue); + for (i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++) { + pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat = + pHddCtx->config->configPNOScanTimerRepeatValue; + pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = + tempInterval; + tempInterval *= 2; + } + /* Repeat last timer until pno disabled. */ + pPnoRequest->scanTimers.aTimerValues[i - 1].uTimerRepeat = 0; + + pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE; + + hddLog(LOG1, + FL("SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d"), + pAdapter->sessionId, pPnoRequest->enable, + pPnoRequest->modePNO, + pPnoRequest->scanTimers.ucScanTimersCount); + + status = sme_set_preferred_network_list(WLAN_HDD_GET_HAL_CTX(pAdapter), + pPnoRequest, + pAdapter->sessionId, + hdd_sched_scan_callback, + pAdapter); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("Failed to enable PNO")); + ret = -EINVAL; + goto error; + } + + hddLog(LOG1, FL("PNO scanRequest offloaded")); + +error: + cdf_mem_free(pPnoRequest); + return ret; +} + +/** + * wlan_hdd_cfg80211_sched_scan_start() - cfg80211 scheduled scan(pno) start + * @wiphy: Pointer to wiphy + * @dev: Pointer network device + * @request: Pointer to cfg80211 scheduled scan start request + * + * Return: 0 for success, non zero for failure + */ +int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request + *request) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_sched_scan_start(wiphy, dev, request); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_sched_scan_stop() - stop cfg80211 scheduled scan(pno) + * @wiphy: Pointer to wiphy + * @dev: Pointer network device + * + * Return: 0 for success, non zero for failure + */ +static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + tHalHandle hHal; + tpSirPNOScanReq pPnoRequest = NULL; + int ret = 0; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (NULL == pHddCtx) { + hddLog(LOGE, FL("HDD context is Null")); + return -ENODEV; + } + + /* 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) { + hddLog(LOGE, FL("LOGP in Progress. Ignore!!!")); + return ret; + } + + if ((pHddCtx->isLoadInProgress) || (pHddCtx->isUnloadInProgress)) { + hddLog(LOGE, FL("Unloading/Loading in Progress. Ignore!!!")); + return ret; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) { + hddLog(LOGE, FL(" HAL context is Null!!!")); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) cdf_mem_malloc(sizeof(tSirPNOScanReq)); + if (NULL == pPnoRequest) { + hddLog(LOGE, FL("cdf_mem_malloc failed")); + return -ENOMEM; + } + + memset(pPnoRequest, 0, sizeof(tSirPNOScanReq)); + pPnoRequest->enable = 0; /* Disable PNO */ + pPnoRequest->ucNetworksCount = 0; + + status = sme_set_preferred_network_list(hHal, pPnoRequest, + pAdapter->sessionId, + NULL, pAdapter); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("Failed to disabled PNO")); + ret = -EINVAL; + } + + hddLog(LOG1, FL("PNO scan disabled")); + + cdf_mem_free(pPnoRequest); + + EXIT(); + return ret; +} + +/** + * wlan_hdd_cfg80211_sched_scan_stop() - stop cfg80211 scheduled scan(pno) + * @wiphy: Pointer to wiphy + * @dev: Pointer network device + * + * Return: 0 for success, non zero for failure + */ +int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_sched_scan_stop(wiphy, dev); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif /*FEATURE_WLAN_SCAN_PNO */ + +/** + * hdd_vendor_put_ifindex() -send interface index + * @skb: buffer pointer + * @ifindex: interface index + * + * Send the IF index to differentiate the events on each interface + * Return: 0 for success, non zero for failure + */ +int hdd_vendor_put_ifindex(struct sk_buff *skb, int ifindex) +{ + struct nlattr *attr; + + nla_nest_cancel(skb, ((void **)skb->cb)[2]); + if (nla_put_u32(skb, NL80211_ATTR_IFINDEX, ifindex)) + return -EINVAL; + + attr = nla_nest_start(skb, NL80211_ATTR_VENDOR_DATA); + ((void **)skb->cb)[2] = attr; + + return 0; +} diff --git a/core/hdd/src/wlan_hdd_scan.h b/core/hdd/src/wlan_hdd_scan.h new file mode 100644 index 000000000000..06ef03b3789c --- /dev/null +++ b/core/hdd/src/wlan_hdd_scan.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +/** + * DOC : wlan_hdd_scan.h + * + * WLAN Host Device Driver scan related implementation + * + */ + +#if !defined(WLAN_HDD_SCAN_H) +#define WLAN_HDD_SCAN_H + +#include "wlan_hdd_main.h" + +#define MAX_PENDING_LOG 5 + +/* + * enum scan_source - scan request source + * + * @NL_SCAN: Scan initiated from NL + * @VENDOR_SCAN: Scan intiated from vendor command +*/ +enum scan_source { + NL_SCAN, + VENDOR_SCAN, +}; + +int iw_get_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request); + +#ifdef FEATURE_WLAN_SCAN_PNO +int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request + *request); + +int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev); +#endif /* End of FEATURE_WLAN_SCAN_PNO */ + +int wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, + int data_len); + +int hdd_vendor_put_ifindex(struct sk_buff *skb, int ifindex); +#endif /* end #if !defined(WLAN_HDD_SCAN_H) */ + diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c new file mode 100644 index 000000000000..6626ca211f83 --- /dev/null +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -0,0 +1,943 @@ +/* + * 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 files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef IPA_OFFLOAD +#include +#endif + +/* Preprocessor definitions and constants */ +#undef QCA_HDD_SAP_DUMP_SK_BUFF + +/* Type declarations */ + +/* Function definitions and documenation */ +#ifdef QCA_HDD_SAP_DUMP_SK_BUFF +/** + * hdd_softap_dump_sk_buff() - Dump an skb + * @skb: skb to dump + * + * Return: None + */ +static void hdd_softap_dump_sk_buff(struct sk_buff *skb) +{ + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: head = %p ", __func__, skb->head); + /* CDF_TRACE( CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR,"%s: data = %p ", __func__, skb->data); */ + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: tail = %p ", __func__, skb->tail); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: end = %p ", __func__, skb->end); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: len = %d ", __func__, skb->len); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: data_len = %d ", __func__, skb->data_len); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: mac_len = %d", __func__, skb->mac_len); + + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_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]); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_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]); +} +#else +static void hdd_softap_dump_sk_buff(struct sk_buff *skb) +{ +} +#endif + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +/** + * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler + * @adapter_context: pointer to vdev adapter + * + * TX Q resume timer 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. + * + * Return: None + */ +void hdd_softap_tx_resume_timer_expired_handler(void *adapter_context) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context; + + if (!pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + return; +} + +/** + * hdd_softap_tx_resume_cb() - Resume OS TX Q. + * @adapter_context: pointer to vdev apdapter + * @tx_resume: TX Q resume trigger + * + * Q was stopped due to WLAN TX path low resource condition + * + * Return: None + */ +void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *) adapter_context; + + if (!pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: INV ARG", __func__); + /* INVALID ARG */ + return; + } + + /* Resume TX */ + if (true == tx_resume) { + if (CDF_TIMER_STATE_STOPPED != + cdf_mc_timer_get_current_state(&pAdapter-> + tx_flow_control_timer)) { + cdf_mc_timer_stop(&pAdapter->tx_flow_control_timer); + } + + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + } +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + else if (false == tx_resume) { /* Pause TX */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_STOP_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + if (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&pAdapter-> + tx_flow_control_timer)) { + CDF_STATUS status; + status = + cdf_mc_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + if (!CDF_IS_STATUS_SUCCESS(status)) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to start tx_flow_control_timer", + __func__); + else + pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + } + } +#endif + + return; +} +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * hdd_softap_hard_start_xmit() - Transmit a frame + * @skb: pointer to OS packet (sk_buff) + * @dev: pointer to network device + * + * Function registered with the Linux OS for transmitting + * packets. This version of the function directly passes + * the packet to Transport Layer. + * + * Return: Always returns NETDEV_TX_OK + */ +int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + sme_ac_enum_type ac = SME_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); + struct cdf_mac_addr *pDestMacAddress; + uint8_t STAId; + uint8_t proto_type = 0; +#ifdef QCA_PKT_PROTO_TRACE + hdd_context_t *hddCtxt = (hdd_context_t *) pAdapter->pHddCtx; +#endif /* QCA_PKT_PROTO_TRACE */ + + ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; + /* Prevent this function from being called during SSR since TL + * context may not be reinitialized at this time which may + * lead to a crash. + */ + if (pHddCtx->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%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 = (struct cdf_mac_addr *) skb->data; + + if (cdf_is_macaddr_broadcast(pDestMacAddress) || + cdf_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 (CDF_STATUS_SUCCESS != + hdd_softap_get_sta_id(pAdapter, + pDestMacAddress, &STAId)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_WARN, + "%s: Failed to find right station", __func__); + goto drop_pkt; + } + + if (STAId == HDD_WLAN_INVALID_STA_ID) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_WARN, + "%s: Failed to find right station", __func__); + goto drop_pkt; + } else if (false == pAdapter->aStaInfo[STAId].isUsed) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_WARN, + "%s: STA %d is unregistered", __func__, + STAId); + goto drop_pkt; + } + + if ((ol_txrx_peer_state_conn != + pAdapter->aStaInfo[STAId].tlSTAState) + && (ol_txrx_peer_state_auth != + pAdapter->aStaInfo[STAId].tlSTAState)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_WARN, + "%s: Station not connected yet", __func__); + goto drop_pkt; + } else if (ol_txrx_peer_state_conn == + pAdapter->aStaInfo[STAId].tlSTAState) { + if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_WARN, + "%s: NON-EAPOL packet in non-Authenticated state", + __func__); + goto drop_pkt; + } + } + } + + hdd_get_tx_resource(pAdapter, STAId, + WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + + /* Get TL AC corresponding to Qdisc queue index/AC. */ + ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping]; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac]; + +#if defined (IPA_OFFLOAD) + if (!(NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID)) { +#endif + /* Check if the buffer has enough header room */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + goto drop_pkt; + + if (skb_headroom(skb) < dev->hard_header_len) { + struct sk_buff *tmp; + tmp = skb; + skb = skb_realloc_headroom(tmp, dev->hard_header_len); + dev_kfree_skb(tmp); + if (!skb) + goto drop_pkt; + } +#if defined (IPA_OFFLOAD) + } +#endif + + wlan_hdd_log_eapol(skb, + WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) || + (hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) { + /* Proto Trace enabled */ + proto_type = cds_pkt_get_proto_type(skb, + hddCtxt->config-> + gEnableDebugLog, 0); + if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) { + cds_pkt_trace_buf_update("HA:T:EPL"); + } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) { + cds_pkt_trace_buf_update("HA:T:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + /* Zero out skb's context buffer for the driver to use */ + cdf_mem_set(skb->cb, sizeof(skb->cb), 0); + NBUF_SET_PACKET_TRACK(skb, NBUF_TX_PKT_DATA_TRACK); + NBUF_UPDATE_TX_PKT_COUNT(skb, NBUF_TX_PKT_HDD); + + cdf_dp_trace_set_track(skb); + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_PTR_RECORD, + (uint8_t *)skb->data, sizeof(skb->data))); + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_RECORD, + (uint8_t *)skb->data, cdf_nbuf_len(skb))); + if (cdf_nbuf_len(skb) > CDF_DP_TRACE_RECORD_SIZE) + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_RECORD, + (uint8_t *)&skb->data[CDF_DP_TRACE_RECORD_SIZE], + (cdf_nbuf_len(skb)-CDF_DP_TRACE_RECORD_SIZE))); + + if (ol_tx_send_data_frame(STAId, skb, + proto_type) != NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_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: + + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_DROP_PACKET_RECORD, + (uint8_t *)skb->data, cdf_nbuf_len(skb))); + if (cdf_nbuf_len(skb) > CDF_DP_TRACE_RECORD_SIZE) + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_DROP_PACKET_RECORD, + (uint8_t *)&skb->data[CDF_DP_TRACE_RECORD_SIZE], + (cdf_nbuf_len(skb)-CDF_DP_TRACE_RECORD_SIZE))); + + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + + return NETDEV_TX_OK; +} + +/** + * __hdd_softap_tx_timeout() - TX timeout handler + * @dev: pointer to network device + * + * This function is registered as a netdev ndo_tx_timeout method, and + * is invoked by the kernel if the driver takes too long to transmit a + * frame. + * + * 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; + + DPTRACE(cdf_dp_trace(NULL, CDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT, + NULL, 0)); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Transmission timeout occurred", __func__); + /* 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_ctx = WLAN_HDD_GET_CTX(adapter); + if (hdd_ctx->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return; + } +} + +/** + * 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) +{ + cds_ssr_protect(__func__); + __hdd_softap_tx_timeout(dev); + cds_ssr_unprotect(__func__); +} + +/** + * @hdd_softap_init_tx_rx() - Initialize Tx/RX module + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_softap_init_tx_rx(hdd_adapter_t *pAdapter) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + uint8_t STAId = 0; + + cdf_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats)); + + spin_lock_init(&pAdapter->staInfo_lock); + + for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) { + cdf_mem_zero(&pAdapter->aStaInfo[STAId], + sizeof(hdd_station_info_t)); + } + + return status; +} + +/** + * @hdd_softap_deinit_tx_rx() - Deinitialize Tx/RX module + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_softap_deinit_tx_rx(hdd_adapter_t *pAdapter) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + return status; +} + +/** + * hdd_softap_init_tx_rx_sta() - Initialize tx/rx for a softap station + * @pAdapter: pointer to adapter context + * @STAId: Station ID to initialize + * @pmacAddrSTA: pointer to the MAC address of the station + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_softap_init_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId, + struct cdf_mac_addr *pmacAddrSTA) +{ + spin_lock_bh(&pAdapter->staInfo_lock); + if (pAdapter->aStaInfo[STAId].isUsed) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Reinit station %d", __func__, STAId); + spin_unlock_bh(&pAdapter->staInfo_lock); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_zero(&pAdapter->aStaInfo[STAId], sizeof(hdd_station_info_t)); + + pAdapter->aStaInfo[STAId].isUsed = true; + pAdapter->aStaInfo[STAId].isDeauthInProgress = false; + cdf_copy_macaddr(&pAdapter->aStaInfo[STAId].macAddrSTA, pmacAddrSTA); + + spin_unlock_bh(&pAdapter->staInfo_lock); + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_softap_deinit_tx_rx_sta() - Deinitialize tx/rx for a softap station + * @pAdapter: pointer to adapter context + * @STAId: Station ID to deinitialize + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_softap_deinit_tx_rx_sta(hdd_adapter_t *pAdapter, uint8_t STAId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_hostapd_state_t *pHostapdState; + + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + spin_lock_bh(&pAdapter->staInfo_lock); + + if (false == pAdapter->aStaInfo[STAId].isUsed) { + spin_unlock_bh(&pAdapter->staInfo_lock); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Deinit station not inited %d", __func__, STAId); + return CDF_STATUS_E_FAILURE; + } + + pAdapter->aStaInfo[STAId].isUsed = false; + pAdapter->aStaInfo[STAId].isDeauthInProgress = false; + + spin_unlock_bh(&pAdapter->staInfo_lock); + return status; +} + +/** + * hdd_softap_rx_packet_cbk() - Receive packet handler + * @cds_context: pointer to CDS context + * @rxBuf: pointer to rx cdf_nbuf + * @staId: Station Id + * + * Receive callback registered with TL. TL will call this to notify + * the HDD when one or more packets were received for a registered + * STA. + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_softap_rx_packet_cbk(void *cds_context, + cdf_nbuf_t rxBuf, uint8_t staId) +{ + hdd_adapter_t *pAdapter = NULL; + int rxstat; + unsigned int cpu_index; + struct sk_buff *skb = NULL; + hdd_context_t *pHddCtx = NULL; +#ifdef QCA_PKT_PROTO_TRACE + uint8_t proto_type; +#endif /* QCA_PKT_PROTO_TRACE */ + + /* Sanity check on inputs */ + if ((NULL == cds_context) || (NULL == rxBuf)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return CDF_STATUS_E_FAILURE; + } + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL == pHddCtx) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return CDF_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[staId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, + FL("invalid adapter %p or adapter has invalid magic"), + pAdapter); + return CDF_STATUS_E_FAILURE; + } + + /* walk the chain until all are processed */ + skb = (struct sk_buff *)rxBuf; + + hdd_softap_dump_sk_buff(skb); + + skb->dev = pAdapter->dev; + + if (skb->dev == NULL) { + + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: ERROR!!Invalid netdevice", __func__); + return CDF_STATUS_E_FAILURE; + } + 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->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) || + (pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) { + proto_type = cds_pkt_get_proto_type(skb, + pHddCtx->config-> + gEnableDebugLog, 0); + if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) { + cds_pkt_trace_buf_update("HA:R:EPL"); + } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) { + cds_pkt_trace_buf_update("HA:R:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + + skb->protocol = eth_type_trans(skb, skb->dev); +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + cdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + + /* Remove SKB from internal tracking table before submitting + * it to stack + */ + cdf_net_buf_debug_release_skb(rxBuf); + + if (hdd_napi_enabled(HDD_NAPI_ANY)) + rxstat = netif_receive_skb(skb); + else + 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]; + } + + pAdapter->dev->last_rx = jiffies; + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId) + * @pAdapter: pointer to adapter context + * @staId: Station ID to deregister + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_deregister_sta(hdd_adapter_t *pAdapter, uint8_t staId) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + hdd_context_t *pHddCtx; + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return CDF_STATUS_E_INVAL; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid pAdapter magic", __func__); + return CDF_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. + */ + cdf_status = ol_txrx_clear_peer(staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "ol_txrx_clear_peer() failed to for staID %d. " + "Status= %d [0x%08X]", staId, cdf_status, cdf_status); + } + + if (pAdapter->aStaInfo[staId].isUsed) { + spin_lock_bh(&pAdapter->staInfo_lock); + cdf_mem_zero(&pAdapter->aStaInfo[staId], + sizeof(hdd_station_info_t)); + spin_unlock_bh(&pAdapter->staInfo_lock); + } + pHddCtx->sta_to_adapter[staId] = NULL; + + return cdf_status; +} + +/** + * hdd_softap_register_sta() - Register a SoftAP STA + * @pAdapter: pointer to adapter context + * @fAuthRequired: is additional authentication required? + * @fPrivacyBit: should 802.11 privacy bit be set? + * @staId: station ID assigned to this station + * @ucastSig: unicast security signature + * @bcastSig: broadcast security signature + * @pPeerMacAddress: station MAC address + * @fWmmEnabled: is WMM enabled for this STA? + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_register_sta(hdd_adapter_t *pAdapter, + bool fAuthRequired, + bool fPrivacyBit, + uint8_t staId, + uint8_t ucastSig, + uint8_t bcastSig, + struct cdf_mac_addr *pPeerMacAddress, + bool fWmmEnabled) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + struct ol_txrx_desc_type staDesc = { 0 }; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + + /* + * Clean up old entry if it is not cleaned up properly + */ + if (pAdapter->aStaInfo[staId].isUsed) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "clean up old entry for STA %d", staId); + hdd_softap_deregister_sta(pAdapter, staId); + } + /* Get the Station ID from the one saved during the assocation. */ + + staDesc.sta_id = staId; + + /*Save the pAdapter Pointer for this staId */ + pHddCtx->sta_to_adapter[staId] = pAdapter; + + cdf_status = + hdd_softap_init_tx_rx_sta(pAdapter, staId, + pPeerMacAddress); + + staDesc.is_qos_enabled = fWmmEnabled; + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "HDD SOFTAP register TL QoS_enabled=%d", + staDesc.is_qos_enabled); + + + cdf_status = + ol_txrx_register_peer(hdd_softap_rx_packet_cbk, + &staDesc); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "SOFTAP ol_txrx_register_peer() failed to register. Status= %d [0x%08X]", + cdf_status, cdf_status); + return cdf_status; + } + + /* 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 + */ + + pAdapter->aStaInfo[staId].ucSTAId = staId; + pAdapter->aStaInfo[staId].isQosEnabled = fWmmEnabled; + + if (!fAuthRequired) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_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. + */ + cdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id, + ol_txrx_peer_state_auth, false); + + pAdapter->aStaInfo[staId].tlSTAState = ol_txrx_peer_state_auth; + pAdapter->sessionCtx.ap.uIsAuthenticated = true; + } else { + + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", + pAdapter->aStaInfo[staId].ucSTAId); + + cdf_status = hdd_change_peer_state(pAdapter, staDesc.sta_id, + ol_txrx_peer_state_conn, false); + pAdapter->aStaInfo[staId].tlSTAState = ol_txrx_peer_state_conn; + + pAdapter->sessionCtx.ap.uIsAuthenticated = false; + + } + + /* Enable Tx queue */ + hddLog(LOG1, FL("Enabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, + WLAN_CONTROL_PATH); + + return cdf_status; +} + +/** + * hdd_softap_register_bc_sta() - Register the SoftAP broadcast STA + * @pAdapter: pointer to adapter context + * @fPrivacyBit: should 802.11 privacy bit be set? + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_register_bc_sta(hdd_adapter_t *pAdapter, + bool fPrivacyBit) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + struct cdf_mac_addr broadcastMacAddr = + CDF_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 + cdf_status = + hdd_softap_register_sta(pAdapter, false, fPrivacyBit, + (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))-> + uBCStaId, 0, 1, &broadcastMacAddr, 0); + + return cdf_status; +} + +/** + * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_deregister_bc_sta(hdd_adapter_t *pAdapter) +{ + return hdd_softap_deregister_sta(pAdapter, + (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))-> + uBCStaId); +} + +/** + * hdd_softap_stop_bss() - Stop the BSS + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + uint8_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s:Loading_unloading in Progress. Ignore!!!", + __func__); + return CDF_STATUS_E_PERM; + } + + cdf_status = hdd_softap_deregister_bc_sta(pAdapter); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_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++) { + /* This excludes BC sta as it is already deregistered */ + if (pAdapter->aStaInfo[staId].isUsed) { + cdf_status = hdd_softap_deregister_sta(pAdapter, staId); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, + CDF_TRACE_LEVEL_ERROR, + "%s: Failed to deregister sta Id %d", + __func__, staId); + } + } + } + return cdf_status; +} + +/** + * hdd_softap_change_sta_state() - Change the state of a SoftAP station + * @pAdapter: pointer to adapter context + * @pDestMacAddress: MAC address of the station + * @state: new state of the station + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS hdd_softap_change_sta_state(hdd_adapter_t *pAdapter, + struct cdf_mac_addr *pDestMacAddress, + enum ol_txrx_peer_state state) +{ + uint8_t ucSTAId = WLAN_MAX_STA_COUNT; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "%s: enter", __func__); + + if (CDF_STATUS_SUCCESS != + hdd_softap_get_sta_id(pAdapter, + pDestMacAddress, &ucSTAId)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to find right station", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (false == + cdf_is_macaddr_equal(&pAdapter->aStaInfo[ucSTAId].macAddrSTA, + pDestMacAddress)) { + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Station MAC address does not matching", + __func__); + return CDF_STATUS_E_FAILURE; + } + + cdf_status = + hdd_change_peer_state(pAdapter, ucSTAId, state, false); + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "%s: change station to state %d succeed", __func__, state); + + if (CDF_STATUS_SUCCESS == cdf_status) { + pAdapter->aStaInfo[ucSTAId].tlSTAState = + ol_txrx_peer_state_auth; + } + + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO, + "%s exit", __func__); + + return cdf_status; +} + +/* + * hdd_softap_get_sta_id() - Find station ID from MAC address + * @pAdapter: pointer to adapter context + * @pDestMacAddress: MAC address of the destination + * @staId: Station ID associated with the MAC address + * + * Return: CDF_STATUS_SUCCESS if a match was found, in which case + * staId is populated, CDF_STATUS_E_FAILURE if a match is + * not found + */ +CDF_STATUS hdd_softap_get_sta_id(hdd_adapter_t *pAdapter, + struct cdf_mac_addr *pMacAddress, + uint8_t *staId) +{ + uint8_t i; + + for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if (cdf_mem_compare + (&pAdapter->aStaInfo[i].macAddrSTA, pMacAddress, + CDF_MAC_ADDR_SIZE) && pAdapter->aStaInfo[i].isUsed) { + *staId = i; + return CDF_STATUS_SUCCESS; + } + } + + return CDF_STATUS_E_FAILURE; +} diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c new file mode 100644 index 000000000000..a08f133213a2 --- /dev/null +++ b/core/hdd/src/wlan_hdd_stats.c @@ -0,0 +1,2511 @@ +/* + * 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. + */ + +/** + * DOC : wlan_hdd_stats.c + * + * WLAN Host Device Driver statistics related implementation + * + */ + +#include "wlan_hdd_stats.h" +#include "sme_api.h" +#include "cds_sched.h" +#include "wlan_hdd_trace.h" + +#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; + spinlock_t context_lock; +}; + +static struct hdd_ll_stats_context ll_stats_context; + +#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */ + +/* 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 { + uint8_t beacon_rate_index; + uint16_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 +/* 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 /* End of WLAN_FEATURE_11AC */ + +/*array index ponints to MCS and array value points respective rssi*/ +static int rssi_mcs_tbl[][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 */ +}; + + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +/** + * put_wifi_rate_stat() - put wifi rate stats + * @stats: Pointer to stats context + * @vendor_event: Pointer to vendor event + * + * Return: bool + */ +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(CDF_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return false; + } + + return true; +} + +/** + * put_wifi_peer_info() - put wifi peer info + * @stats: Pointer to stats context + * @vendor_event: Pointer to vendor event + * + * Return: bool + */ +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, + CDF_MAC_ADDR_SIZE, &stats->peerMacAddress.bytes[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(CDF_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_t *) + 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(CDF_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; +} + +/** + * put_wifi_wmm_ac_stat() - put wifi wmm ac stats + * @stats: Pointer to stats context + * @vendor_event: Pointer to vendor event + * + * Return: bool + */ +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(CDF_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return false; + } + + return true; +} + +/** + * put_wifi_interface_info() - put wifi interface info + * @stats: Pointer to stats context + * @vendor_event: Pointer to vendor event + * + * Return: bool + */ +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, + CDF_MAC_ADDR_SIZE, stats->macAddr.bytes) || + 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, + CDF_MAC_ADDR_SIZE, stats->bssid.bytes) || + 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(CDF_TRACE_LEVEL_ERROR, + FL("QCA_WLAN_VENDOR_ATTR put fail")); + return false; + } + + return true; +} + +/** + * put_wifi_iface_stats() - put wifi interface stats + * @pWifiIfaceStat: Pointer to interface stats context + * @num_peer: Number of peers + * @vendor_event: Pointer to vendor event + * + * Return: bool + */ +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(CDF_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(CDF_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(CDF_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; +} + +/** + * hdd_map_device_to_ll_iface_mode() - map device to link layer interface mode + * @deviceMode: Device mode + * + * Return: interface mode + */ +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; + } +} + +/** + * hdd_get_interface_info() - get interface info + * @pAdapter: Pointer to device adapter + * @pInfo: Pointer to interface info + * + * Return: bool + */ +static bool hdd_get_interface_info(hdd_adapter_t *pAdapter, + tpSirWifiInterfaceInfo pInfo) +{ + uint8_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); + + cdf_copy_macaddr(&pInfo->macAddr, &pAdapter->macAddressCurrent); + + 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(CDF_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) + && (false == pHddStaCtx->conn_info.uIsAuthenticated)) { + staMac = + (uint8_t *) &(pAdapter->macAddressCurrent. + bytes[0]); + hddLog(CDF_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; + cdf_copy_macaddr(&pInfo->bssid, + &pHddStaCtx->conn_info.bssId); + cdf_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; + } + } + + cdf_mem_copy(pInfo->countryStr, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + + cdf_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 + * @pAdapter: Pointer to device adapter + * @more_data: More data + * @pData: Pointer to stats data + * + * 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. + * + * Return: None + */ +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); + tpSirWifiRateStat pWifiRateStat; + tpSirWifiPeerStat pWifiPeerStat; + tpSirWifiPeerInfo pWifiPeerInfo; + struct sk_buff *vendor_event; + int status, i, j; + struct nlattr *peers; + int numRate; + + pWifiPeerStat = pData; + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_PEER_ALL : numPeers %u, more data = %u", + pWifiPeerStat->numPeers, more_data); + + for (i = 0; i < pWifiPeerStat->numPeers; i++) { + pWifiPeerInfo = (tpSirWifiPeerInfo) + ((uint8_t *) pWifiPeerStat->peerInfo + + (i * sizeof(tSirWifiPeerInfo))); + + if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) + pWifiPeerInfo->type = WIFI_PEER_AP; + + if (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) + pWifiPeerInfo->type = WIFI_PEER_P2P_GO; + + hddLog(CDF_TRACE_LEVEL_INFO, + " %d) LL_STATS Channel Stats " + " Peer Type %u " + " peerMacAddress %pM " + " capabilities 0x%x " + " numRate %u ", + i, + pWifiPeerInfo->type, + pWifiPeerInfo->peerMacAddress.bytes, + pWifiPeerInfo->capabilities, pWifiPeerInfo->numRate); + { + for (j = 0; j < pWifiPeerInfo->numRate; j++) { + pWifiRateStat = (tpSirWifiRateStat) + ((uint8_t *) pWifiPeerInfo->rateStats + + (j * sizeof(tSirWifiRateStat))); + + hddLog(CDF_TRACE_LEVEL_INFO, + " peer Rate Stats " + " preamble %u " + " nss %u " + " bw %u " + " rateMcsIdx %u " + " reserved %u " + " bitrate %u " + " txMpdu %u " + " rxMpdu %u " + " mpduLost %u " + " retries %u " + " retriesShort %u " + " retriesLong %u", + pWifiRateStat->rate.preamble, + pWifiRateStat->rate.nss, + pWifiRateStat->rate.bw, + pWifiRateStat->rate.rateMcsIdx, + pWifiRateStat->rate.reserved, + pWifiRateStat->rate.bitrate, + pWifiRateStat->txMpdu, + pWifiRateStat->rxMpdu, + pWifiRateStat->mpduLost, + pWifiRateStat->retries, + pWifiRateStat->retriesShort, + pWifiRateStat->retriesLong); + } + } + } + + /* + * 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(LOGE, + 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_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(CDF_TRACE_LEVEL_ERROR, + "%s: QCA_WLAN_VENDOR_ATTR put fail", __func__); + + kfree_skb(vendor_event); + return; + } + + pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *) + 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(CDF_TRACE_LEVEL_ERROR, + FL("put_wifi_peer_info fail")); + kfree_skb(vendor_event); + return; + } + + pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *) + 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); + return; +} + +/** + * hdd_link_layer_process_iface_stats() - This function is called after + * @pAdapter: Pointer to device adapter + * @pData: Pointer to stats data + * @num_peers: Number of peers + * + * 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. + * + * Return: None + */ +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; + int i; + + pWifiIfaceStat = pData; + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + 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(CDF_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return; + } + + hddLog(CDF_TRACE_LEVEL_INFO, "WMI_LINK_STATS_IFACE Data"); + + if (false == hdd_get_interface_info(pAdapter, &pWifiIfaceStat->info)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("hdd_get_interface_info get fail")); + kfree_skb(vendor_event); + return; + } + + hddLog(CDF_TRACE_LEVEL_INFO, + " Num peers %u " + "LL_STATS_IFACE: " + " Mode %u " + " MAC %pM " + " State %u " + " Roaming %u " + " capabilities 0x%x " + " SSID %s " + " BSSID %pM", + num_peers, + pWifiIfaceStat->info.mode, + pWifiIfaceStat->info.macAddr.bytes, + pWifiIfaceStat->info.state, + pWifiIfaceStat->info.roaming, + pWifiIfaceStat->info.capabilities, + pWifiIfaceStat->info.ssid, pWifiIfaceStat->info.bssid.bytes); + + hddLog(CDF_TRACE_LEVEL_INFO, + " AP country str: %c%c%c", + pWifiIfaceStat->info.apCountryStr[0], + pWifiIfaceStat->info.apCountryStr[1], + pWifiIfaceStat->info.apCountryStr[2]); + + hddLog(CDF_TRACE_LEVEL_INFO, + " Country Str Association: %c%c%c", + pWifiIfaceStat->info.countryStr[0], + pWifiIfaceStat->info.countryStr[1], + pWifiIfaceStat->info.countryStr[2]); + + hddLog(CDF_TRACE_LEVEL_INFO, + " beaconRx %u " + " mgmtRx %u " + " mgmtActionRx %u " + " mgmtActionTx %u " + " rssiMgmt %u " + " rssiData %u " + " rssiAck %u " + " avg_bcn_spread_offset_high %u" + " avg_bcn_spread_offset_low %u" + " is leaky_ap %u" + " avg_rx_frms_leaked %u" + " rx_leak_window %u", + pWifiIfaceStat->beaconRx, + pWifiIfaceStat->mgmtRx, + pWifiIfaceStat->mgmtActionRx, + pWifiIfaceStat->mgmtActionTx, + pWifiIfaceStat->rssiMgmt, + pWifiIfaceStat->rssiData, + pWifiIfaceStat->rssiAck, + pWifiIfaceStat->avg_bcn_spread_offset_high, + pWifiIfaceStat->avg_bcn_spread_offset_low, + pWifiIfaceStat->is_leaky_ap, + pWifiIfaceStat->avg_rx_frms_leaked, + pWifiIfaceStat->rx_leak_window); + + for (i = 0; i < WIFI_AC_MAX; i++) { + hddLog(CDF_TRACE_LEVEL_INFO, + " %d) LL_STATS IFACE: " + " ac: %u txMpdu: %u " + " rxMpdu: %u txMcast: %u " + " rxMcast: %u rxAmpdu: %u " + " txAmpdu: %u mpduLost: %u " + " retries: %u retriesShort: %u " + " retriesLong: %u contentionTimeMin: %u " + " contentionTimeMax: %u contentionTimeAvg: %u " + " contentionNumSamples: %u", + i, + pWifiIfaceStat->AccessclassStats[i].ac, + pWifiIfaceStat->AccessclassStats[i].txMpdu, + pWifiIfaceStat->AccessclassStats[i].rxMpdu, + pWifiIfaceStat->AccessclassStats[i].txMcast, + pWifiIfaceStat->AccessclassStats[i].rxMcast, + pWifiIfaceStat->AccessclassStats[i].rxAmpdu, + pWifiIfaceStat->AccessclassStats[i].txAmpdu, + pWifiIfaceStat->AccessclassStats[i].mpduLost, + pWifiIfaceStat->AccessclassStats[i].retries, + pWifiIfaceStat->AccessclassStats[i].retriesShort, + pWifiIfaceStat->AccessclassStats[i].retriesLong, + pWifiIfaceStat->AccessclassStats[i].contentionTimeMin, + pWifiIfaceStat->AccessclassStats[i].contentionTimeMax, + pWifiIfaceStat->AccessclassStats[i].contentionTimeAvg, + pWifiIfaceStat->AccessclassStats[i]. + contentionNumSamples); + } + + if (false == + put_wifi_iface_stats(pWifiIfaceStat, num_peers, vendor_event)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("put_wifi_iface_stats fail")); + kfree_skb(vendor_event); + return; + } + + cfg80211_vendor_cmd_reply(vendor_event); + return; +} + +/** + * hdd_link_layer_process_radio_stats() - This function is called after + * @pAdapter: Pointer to device adapter + * @more_data: More data + * @pData: Pointer to stats data + * @num_radios: Number of radios + * + * 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. + * + * Return: None + */ +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); + + pWifiRadioStat = pData; + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + + hddLog(CDF_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(LOGE, + 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(CDF_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_t *) + pWifiRadioStat-> + channels + + (i * + sizeof + (tSirWifiChannelStats))); + + hddLog(CDF_TRACE_LEVEL_INFO, + " %d) Channel Info" + " width is %u " + " CenterFreq %u " + " CenterFreq0 %u " + " CenterFreq1 %u " + " onTime %u " + " ccaBusyTime %u", + i, + pWifiChannelStats->channel.width, + pWifiChannelStats->channel.centerFreq, + pWifiChannelStats->channel.centerFreq0, + pWifiChannelStats->channel.centerFreq1, + pWifiChannelStats->onTime, + pWifiChannelStats->ccaBusyTime); + + 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(CDF_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); + return; +} + +/** + * wlan_hdd_cfg80211_link_layer_stats_callback() - This function is called + * @ctx: Pointer to hdd context + * @indType: Indication type + * @pRsp: Pointer to response + * + * 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. + * + * Return: None + */ +static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, + int indType, void *pRsp) +{ + hdd_context_t *pHddCtx = (hdd_context_t *) ctx; + struct hdd_ll_stats_context *context; + hdd_adapter_t *pAdapter = NULL; + tpSirLLStatsResults linkLayerStatsResults = (tpSirLLStatsResults) pRsp; + int status; + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return; + } + + pAdapter = hdd_get_adapter_by_vdev(pHddCtx, + linkLayerStatsResults->ifaceId); + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: vdev_id %d does not exist with host", + __func__, linkLayerStatsResults->ifaceId); + return; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Link Layer Indication indType: %d", __func__, indType); + + switch (indType) { + case SIR_HAL_LL_STATS_RESULTS_RSP: + { + hddLog(CDF_TRACE_LEVEL_INFO, + FL("RESPONSE SIR_HAL_LL_STATS_RESULTS_RSP")); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE paramID = 0x%x", + linkLayerStatsResults->paramId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE ifaceId = %u", + linkLayerStatsResults->ifaceId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE respId = %u", + linkLayerStatsResults->rspId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE more data = %u", + linkLayerStatsResults->moreResultToFollow); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE num radio = %u", + linkLayerStatsResults->num_radio); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS RESULTS RESPONSE result = %p", + linkLayerStatsResults->results); + + context = &ll_stats_context; + spin_lock(&context->context_lock); + /* validate response received from target */ + if ((context->request_id != linkLayerStatsResults->rspId) || + !(context->request_bitmap & linkLayerStatsResults->paramId)) { + spin_unlock(&context->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(&context->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(&context->context_lock); + if (!linkLayerStatsResults->moreResultToFollow) + context->request_bitmap &= ~(WMI_LINK_STATS_RADIO); + spin_unlock(&context->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(&context->context_lock); + context->request_bitmap &= ~(WMI_LINK_STATS_IFACE); + spin_unlock(&context->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(&context->context_lock); + if (!linkLayerStatsResults->moreResultToFollow) + context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + spin_unlock(&context->context_lock); + + } else { + hddLog(LOGE, + FL("INVALID LL_STATS_NOTIFY RESPONSE")); + } + + spin_lock(&context->context_lock); + /* complete response event if all requests are completed */ + if (0 == context->request_bitmap) + complete(&context->response_event); + spin_unlock(&context->context_lock); + + break; + } + default: + hddLog(CDF_TRACE_LEVEL_ERROR, "invalid event type %d", indType); + break; + } + + return; +} + +/** + * wlan_hdd_cfg80211_link_layer_stats_init() - initialize link layer stats + * @pHddCtx: Pointer to hdd context + * + * Return: None + */ +void wlan_hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx) +{ + sme_set_link_layer_stats_ind_cb(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}, +}; + +/** + * __wlan_hdd_cfg80211_ll_stats_set() - set link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + 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(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_INFO, + "LL_STATS_SET reqId = %d", LinkLayerStatsSetReq.reqId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_SET staId = %d", LinkLayerStatsSetReq.staId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_SET mpduSizeThreshold = %d", + LinkLayerStatsSetReq.mpduSizeThreshold); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_SET aggressive Statistics Gathering = %d", + LinkLayerStatsSetReq.aggressiveStatisticsGathering); + + if (CDF_STATUS_SUCCESS != sme_ll_stats_set_req(pHddCtx->hHal, + &LinkLayerStatsSetReq)) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s:" + "sme_ll_stats_set_req Failed", __func__); + return -EINVAL; + } + + pAdapter->isLinkLayerStatsSet = 1; + + 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 + */ +int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_set(wiphy, wdev, data, data_len); + cds_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} +}; + +/** + * __wlan_hdd_cfg80211_ll_stats_get() - get link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (!pAdapter->isLinkLayerStatsSet) { + hddLog(CDF_TRACE_LEVEL_FATAL, + "%s: isLinkLayerStatsSet : %d", + __func__, 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(CDF_TRACE_LEVEL_ERROR, FL("max attribute not present")); + return -EINVAL; + } + + if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("Request Id Not present")); + return -EINVAL; + } + + if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]) { + hddLog(CDF_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(LOG1, + FL("LL_STATS_GET reqId = %d"), LinkLayerStatsGetReq.reqId); + hddLog(LOG1, + FL("LL_STATS_GET staId = %d"), LinkLayerStatsGetReq.staId); + hddLog(LOG1, + FL("LL_STATS_GET paramIdMask = %d"), + LinkLayerStatsGetReq.paramIdMask); + + context = &ll_stats_context; + spin_lock(&context->context_lock); + context->request_id = LinkLayerStatsGetReq.reqId; + context->request_bitmap = LinkLayerStatsGetReq.paramIdMask; + INIT_COMPLETION(context->response_event); + spin_unlock(&context->context_lock); + + if (CDF_STATUS_SUCCESS != sme_ll_stats_get_req(pHddCtx->hHal, + &LinkLayerStatsGetReq)) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s:" + "sme_ll_stats_get_req 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; + } + + 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 + */ +int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len); + cds_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}, +}; + +/** + * __wlan_hdd_cfg80211_ll_stats_clear() - clear link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + + if (!pAdapter->isLinkLayerStatsSet) { + hddLog(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_INFO, + "LL_STATS_CLEAR reqId = %d", LinkLayerStatsClearReq.reqId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_CLEAR staId = %d", LinkLayerStatsClearReq.staId); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_CLEAR statsClearReqMask = 0x%X", + LinkLayerStatsClearReq.statsClearReqMask); + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_CLEAR stopReq = %d", LinkLayerStatsClearReq.stopReq); + + if (CDF_STATUS_SUCCESS == sme_ll_stats_clear_req(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(CDF_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); + } + 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 + */ +int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_ll_stats_clear(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#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; + CDF_STATUS 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 (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + stats_ext_req.request_data_len = data_len; + stats_ext_req.request_data = (void *)data; + + status = sme_stats_ext_request(pAdapter->sessionId, &stats_ext_req); + + if (CDF_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 + */ +int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_stats_ext_request(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_stats_ext_callback() - ext stats callback + * @ctx: Pointer to HDD context + * @msg: Message received + * + * Return: nothing + */ +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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + + pAdapter = hdd_get_adapter_by_vdev(pHddCtx, data->vdev_id); + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(uint32_t) + + NLMSG_HDRLEN + NLMSG_HDRLEN, + QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + +} + +/** + * wlan_hdd_cfg80211_stats_ext_init() - ext stats init + * @ctx: Pointer to HDD context + * + * Return: nothing + */ +void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx) +{ + sme_stats_ext_register_callback(pHddCtx->hHal, + wlan_hdd_cfg80211_stats_ext_callback); +} +#endif /* End of WLAN_FEATURE_STATS_EXT */ + +/** + * __wlan_hdd_cfg80211_get_station() - get station statistics + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @mac: Pointer to mac + * @sinfo: Pointer to station info + * + * Return: 0 for success, non-zero for failure + */ +static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *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; + uint8_t rate_flags; + + hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy); + struct hdd_config *pCfg = pHddCtx->config; + + uint8_t OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX]; + uint32_t ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX; + uint8_t ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; + uint32_t ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX; + uint8_t MCSRates[SIZE_OF_BASIC_MCS_SET]; + uint32_t MCSLeng = SIZE_OF_BASIC_MCS_SET; + uint16_t maxRate = 0; + uint16_t myRate; + uint16_t currentRate = 0; + uint8_t maxSpeedMCS = 0; + uint8_t maxMCSIdx = 0; + uint8_t rateFlag = 1; + uint8_t i, j, rssidx; + uint8_t 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 + uint32_t vht_mcs_map; + enum eDataRate11ACMaxMcs vhtMaxMcs; +#endif /* WLAN_FEATURE_11AC */ + + + ENTER(); + + if (CDF_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(LOG1, FL("Not associated or Invalid ssidlen, %d"), + 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) { + hddLog(LOGE, FL("HDD context is not valid")); + 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 = 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; + } + } +#ifdef LINKSPEED_DEBUG_ENABLED + pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n", + 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); +#endif /* LINKSPEED_DEBUG_ENABLED */ + + 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(LOGE, + FL("Invalid value for reportMaxLinkSpeed: %u"), + pCfg->reportMaxLinkSpeed); + rssidx = 0; + } + + maxRate = 0; + + /* Get Basic Rate Set */ + if (0 != + sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_OPERATIONAL_RATE_SET, + OperationalRates, + &ORLeng)) { + hddLog(LOGE, FL("cfg get returned failure")); + /*To keep GUI happy */ + return 0; + } + + for (i = 0; i < ORLeng; i++) { + for (j = 0; + j < ARRAY_SIZE(supported_data_rate); 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 != + sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + ExtendedRates, &ERLeng)) { + hddLog(LOGE, FL("cfg get returned failure")); + /*To keep GUI happy */ + return 0; + } + + for (i = 0; i < ERLeng; i++) { + for (j = 0; + j < ARRAY_SIZE(supported_data_rate); 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 != + sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_CURRENT_MCS_SET, MCSRates, + &MCSLeng)) { + hddLog(LOGE, FL("cfg get returned failure")); + /*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 seperate rate table */ + if (rate_flags & + (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | + eHAL_TX_RATE_VHT80)) { + sme_cfg_get_int(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_VHT_TX_MCS_MAP, + &vht_mcs_map); + vhtMaxMcs = (enum 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 <= + rssi_mcs_tbl[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 <= + rssi_mcs_tbl[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]; + break; + } + } + + if ((j < MAX_HT_MCS_IDX) + && (currentRate > maxRate)) { + maxRate = currentRate; + maxSpeedMCS = 1; + maxMCSIdx = + supported_mcs_rate[j]. + beacon_rate_index; + } + } + } + } + + else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) { + maxRate = myRate; + maxSpeedMCS = 1; + maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index; + } + /* report a value at least as big as 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 */ + } + } + 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(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_GET_STA, + pAdapter->sessionId, maxRate)); + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_get_station() - get station statistics + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @mac: Pointer to mac + * @sinfo: Pointer to station info + * + * Return: 0 for success, non-zero for failure + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *mac, + struct station_info *sinfo) +#else +int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, uint8_t *mac, + struct station_info *sinfo) +#endif +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_get_stats() - Function to retrieve interface statistics + * @dev: pointer to network device + * + * This function is the ndo_get_stats method for all netdevs + * registered with the kernel + * + * Return: pointer to net_device_stats structure + */ +struct net_device_stats *hdd_get_stats(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + return &adapter->stats; +} +/** + * __wlan_hdd_cfg80211_dump_survey() - get survey related info + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @idx: Index + * @survey: Pointer to survey info + * + * Return: 0 for success, non-zero for failure + */ +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; + uint32_t channel = 0, freq = 0; /* Initialization Required */ + int8_t snr, rssi; + int status, i, j, filled = 0; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + 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; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (0 == pHddCtx->config->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 (!pHddStaCtx->hdd_ReassocScenario) { + hdd_err("Roaming in progress, hence return"); + return -ENONET; + } + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + wlan_hdd_get_snr(pAdapter, &snr); + wlan_hdd_get_rssi(pAdapter, &rssi); + + sme_get_operation_channel(halHandle, &channel, pAdapter->sessionId); + hdd_wlan_get_freq(channel, &freq); + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + if (NULL == wiphy->bands[i]) { + hddLog(LOG1, FL("wiphy->bands[i] is NULL, i = %d"), 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 == (uint16_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; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_dump_survey() - get survey related info + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @idx: Index + * @survey: Pointer to survey info + * + * Return: 0 for success, non-zero for failure + */ +int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, + struct net_device *dev, + int idx, struct survey_info *survey) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey); + cds_ssr_unprotect(__func__); + + return ret; +} +/** + * hdd_init_ll_stats_ctx() - initialize link layer stats context + * + * Return: none + */ +inline void hdd_init_ll_stats_ctx(void) +{ + spin_lock_init(&ll_stats_context.context_lock); + init_completion(&ll_stats_context.response_event); + ll_stats_context.request_bitmap = 0; + + return; +} diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h new file mode 100644 index 000000000000..ae5e84d0a215 --- /dev/null +++ b/core/hdd/src/wlan_hdd_stats.h @@ -0,0 +1,186 @@ +/* + * 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. + */ + +/** + * DOC : wlan_hdd_stats.h + * + * WLAN Host Device Driver statistics related implementation + * + */ + +#if !defined(WLAN_HDD_STATS_H) +#define WLAN_HDD_STATS_H + +#include "wlan_hdd_main.h" + +#define INVALID_MCS_IDX 255 +#define MAX_HT_MCS_IDX 8 +#define MAX_VHT_MCS_IDX 10 + +#ifdef WLAN_FEATURE_11AC +#define DATA_RATE_11AC_MCS_MASK 0x03 + +/* LL stats get request time out value */ +#define WLAN_WAIT_TIME_LL_STATS 5000 + +/** + * struct index_vht_data_rate_type - vht data rate type + * @beacon_rate_index: Beacon rate index + * @supported_VHT80_rate: VHT80 rate + * @supported_VHT40_rate: VHT40 rate + * @supported_VHT20_rate: VHT20 rate + */ +struct index_vht_data_rate_type { + uint8_t beacon_rate_index; + uint16_t supported_VHT80_rate[2]; + uint16_t supported_VHT40_rate[2]; + uint16_t supported_VHT20_rate[2]; +}; + +/** + * enum - eDataRate11ACMaxMcs + * @DATA_RATE_11AC_MAX_MCS_7: MCS7 rate + * @DATA_RATE_11AC_MAX_MCS_8: MCS8 rate + * @DATA_RATE_11AC_MAX_MCS_9: MCS9 rate + * @DATA_RATE_11AC_MAX_MCS_NA:i Not applicable + */ +enum eDataRate11ACMaxMcs{ + DATA_RATE_11AC_MAX_MCS_7, + DATA_RATE_11AC_MAX_MCS_8, + DATA_RATE_11AC_MAX_MCS_9, + DATA_RATE_11AC_MAX_MCS_NA +}; +#endif /* End of WLAN_FEATURE_11AC */ + +/** + * struct index_data_rate_type - non vht data rate type + * @beacon_rate_index: Beacon rate index + * @supported_rate: Supported rate table + */ +struct index_data_rate_type { + uint8_t beacon_rate_index; + uint16_t supported_rate[4]; +}; + +#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 + +/** + * wlan_hdd_cfg80211_ll_stats_set() - set link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +/** + * wlan_hdd_cfg80211_ll_stats_get() - get link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + + +/** + * wlan_hdd_cfg80211_ll_stats_clear() - clear link layer stats + * @wiphy: Pointer to wiphy + * @wdev: Pointer to wdev + * @data: Pointer to data + * @data_len: Data length + * + * Return: int + */ +int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); + +void hdd_init_ll_stats_ctx(void); +#else +static inline void hdd_init_ll_stats_ctx(void) +{ + return; +} + +#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */ + +#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 + */ +int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len); +#endif /* End of WLAN_FEATURE_STATS_EXT */ + +/** + * wlan_hdd_cfg80211_get_station() - get station statistics + * @wiphy: Pointer to wiphy + * @dev: Pointer to network device + * @mac: Pointer to mac + * @sinfo: Pointer to station info + * + * Return: 0 for success, non-zero for failure + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *mac, + struct station_info *sinfo); +#else +int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *dev, uint8_t *mac, + struct station_info *sinfo); +#endif + +struct net_device_stats *hdd_get_stats(struct net_device *dev); + +int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, + struct net_device *dev, + int idx, struct survey_info *survey); +#endif /* end #if !defined(WLAN_HDD_STATS_H) */ + diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c new file mode 100644 index 000000000000..459724608f9b --- /dev/null +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -0,0 +1,4705 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_tdls.c + * + * 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 "cds_sched.h" +#include "wma_types.h" + +static int32_t wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t * + pHddTdlsCtx); +static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx); +int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac); +static void wlan_hdd_tdls_pre_setup(struct work_struct *work); + +/** + * wlan_hdd_tdls_hash_key() - calculate tdls hash key given mac address + * @mac: mac address + * + * Return: hash key + */ +static u8 wlan_hdd_tdls_hash_key(const u8 *mac) +{ + int i; + u8 key = 0; + + for (i = 0; i < 6; i++) + key ^= mac[i]; + + return key; +} + +/** + * wlan_hdd_tdls_disable_offchan_and_teardown_links - Disable offchannel + * and teardown TDLS links + * @hddCtx : pointer to hdd context + * + * Return: None + */ +void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) +{ + u16 connected_tdls_peers = 0; + u8 staidx; + hddTdlsPeer_t *curr_peer = NULL; + hdd_adapter_t *adapter = NULL; + + if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) { + hddLog(LOG1, FL("TDLS mode is disabled OR not enabled in FW")); + return ; + } + + adapter = hdd_get_adapter(hddctx, WLAN_HDD_INFRA_STATION); + + if (adapter == NULL) { + hddLog(LOGE, FL("Station Adapter Not Found")); + return; + } + + connected_tdls_peers = wlan_hdd_tdls_connected_peers(adapter); + + if (!connected_tdls_peers) + return ; + + /* TDLS is not supported in case of concurrency. + * Disable TDLS Offchannel in FW to avoid more + * than two concurrent channels and generate TDLS + * teardown indication to supplicant. + * Below function Finds the first connected peer and + * disables TDLS offchannel for that peer. + * FW enables TDLS offchannel only when there is + * one TDLS peer. When there are more than one TDLS peer, + * there will not be TDLS offchannel in FW. + * So to avoid sending multiple request to FW, for now, + * just invoke offchannel mode functions only once + */ + hdd_set_tdls_offchannel(hddctx, hddctx->config->fTDLSPrefOffChanNum); + hdd_set_tdls_secoffchanneloffset(hddctx, + TDLS_SEC_OFFCHAN_OFFSET_40PLUS); + hdd_set_tdls_offchannelmode(adapter, DISABLE_CHANSWITCH); + + for (staidx = 0; staidx < hddctx->max_num_tdls_sta; + staidx++) { + if (!hddctx->tdlsConnInfo[staidx].staId) + continue; + + curr_peer = wlan_hdd_tdls_find_all_peer(hddctx, + hddctx->tdlsConnInfo[staidx].peerMac.bytes); + + if (!curr_peer) + continue; + + hddLog(LOG1, FL("indicate TDLS teardown (staId %d)"), + curr_peer->staId); + + wlan_hdd_tdls_indicate_teardown( + curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } +} + +/** + * hdd_tdls_notify_mode_change - Notify mode change + * @adapter: pointer to hdd adapter + * @hddCtx : pointer to hdd context + * + * Return: None + */ +void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, hdd_context_t *hddctx) +{ + if (adapter->device_mode != WLAN_HDD_INFRA_STATION) + wlan_hdd_tdls_disable_offchan_and_teardown_links(hddctx); +} + + +/** + * wlan_hdd_tdls_pre_setup_init_work() - schedule work for tdls pre-setup + * @pHddTdlsCtx: HDD TDLS context + * @curr_candidate: current candidate peer + * + * Return: None + */ +void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t *pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate) +{ + if (!pHddTdlsCtx || !curr_candidate) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: either pHddTdlsCtx or curr_candidate is null", + __func__); + return; + } + + if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic) { + /* When TDLS discovery attempt for a peer reaches to max configured + * threshold then tdls support for that peer would be disabled and + * in that case, ignore discovery trigger from FW for that peer. + */ + if (eTDLS_CAP_NOT_SUPPORTED == curr_candidate->tdls_support) { + hddLog(LOGW, + "%s: tdls_support is marked disabled for peer: " + MAC_ADDRESS_STR + ", ignore pre_setup_init_work", __func__, + MAC_ADDR_ARRAY(curr_candidate->peerMac)); + return; + } + + pHddTdlsCtx->curr_candidate = curr_candidate; + pHddTdlsCtx->magic = TDLS_CTX_MAGIC; + + schedule_work(&pHddTdlsCtx->implicit_setup); + } +} + +/** + * wlan_hdd_tdls_pre_setup_init_work() - get value of discovery counter sent + * @pHddCtx: HDD context + * + * Return: the value of the transmitted TDLS discovery counter + */ +static uint32_t 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; + CDF_STATUS status = 0; + uint32_t count = 0; + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_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; +} + +/** + * wlan_hdd_tdls_check_power_save_prohibited() - set/clear proper TDLS power + * save probihited bit + * @pAdapter: HDD adapter handle + * + * Ensure TDLS power save probihited bit is set/cleared properly + * + * Return: None + */ +static void wlan_hdd_tdls_check_power_save_prohibited(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 == pHddTdlsCtx) || (NULL == pHddCtx)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_set_tdls_power_save_prohibited(WLAN_HDD_GET_HAL_CTX + (pHddTdlsCtx->pAdapter), + pAdapter->sessionId, 0); + return; + } + sme_set_tdls_power_save_prohibited(WLAN_HDD_GET_HAL_CTX + (pHddTdlsCtx->pAdapter), + pAdapter->sessionId, 1); + return; +} + +/** + * wlan_hdd_tdls_free_scan_request() - free tdls scan request + * @tdls_scan_ctx: tdls scan context + * + * Return: None + */ +static void wlan_hdd_tdls_free_scan_request(tdls_scan_context_t *tdls_scan_ctx) +{ + if (NULL == tdls_scan_ctx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; +} + +/** + * wlan_hdd_tdls_discovery_timeout_peer_cb() - tdls discovery timeout callback + * @userData: tdls context + * + * Return: None + */ +static void wlan_hdd_tdls_discovery_timeout_peer_cb(void *userData) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; + + pHddTdlsCtx = (tdlsCtx_t *) userData; + + if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + if (NULL == 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) { + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(LOG1, + "%s: " MAC_ADDRESS_STR + " to idle state", __func__, + MAC_ADDR_ARRAY(tmp->peerMac)); + 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); + + return; +} + +/** + * wlan_hdd_tdls_free_list() - free TDLS peer list + * @pHddTdlsCtx: TDLS context + * + * Return: None + */ +static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + + if (NULL == pHddTdlsCtx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &pHddTdlsCtx->peer_list[i]; + list_for_each_safe(pos, q, head) { + tmp = list_entry(pos, hddTdlsPeer_t, node); + list_del(pos); + cdf_mem_free(tmp); + tmp = NULL; + } + } +} + +/** + * wlan_hdd_tdls_schedule_scan() - schedule scan for tdls + * @work: work_struct used to find tdls scan context + * + * Return: None + */ +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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) + scan_ctx->dev, +#endif + scan_ctx->scan_request); +} + +/** + * dump_tdls_state_param_setting() - print tdls state & parameters to send to fw + * @info: tdls setting to be sent to fw + * + * Return: void + */ +static void dump_tdls_state_param_setting(tdlsInfo_t *info) +{ + if (!info) + return; + + 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" + ), + info->vdev_id, + info->tdls_state, + info->notification_interval_ms, + info->tx_discovery_threshold, + info->tx_teardown_threshold, + info->rssi_teardown_threshold, + info->rssi_delta, + info->tdls_options, + info->peer_traffic_ind_window, + info->peer_traffic_response_timeout, + info->puapsd_mask, + info->puapsd_inactivity_time, + info->puapsd_rx_frame_threshold); +} + + +/** + * wlan_hdd_tdls_monitor_timers_stop() - stop all monitoring timers + * @hdd_tdls_ctx: TDLS context + * + * Return: none + */ +static void wlan_hdd_tdls_monitor_timers_stop(tdlsCtx_t *hdd_tdls_ctx) +{ + cdf_mc_timer_stop(&hdd_tdls_ctx->peerDiscoveryTimeoutTimer); +} + +/** + * wlan_hdd_tdls_timers_stop() - stop all the tdls timers running + * @hdd_tdls_ctx: TDLS context + * + * Return: none + */ +static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *hdd_tdls_ctx) +{ + wlan_hdd_tdls_monitor_timers_stop(hdd_tdls_ctx); +} + +/** + * wlan_hdd_tdls_del_non_forced_peers() - delete non forced tdls peers + * @hdd_tdls_ctx: TDLS context + * + * Return: none + */ +static void wlan_hdd_tdls_del_non_forced_peers(tdlsCtx_t *hdd_tdls_ctx) +{ + struct list_head *head, *pos, *q; + hddTdlsPeer_t *peer = NULL; + int i; + + /* remove entries from peer list only if peer is not forced */ + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &hdd_tdls_ctx->peer_list[i]; + list_for_each_safe(pos, q, head) { + peer = list_entry(pos, hddTdlsPeer_t, node); + if (false == peer->isForcedPeer) { + list_del(pos); + cdf_mem_free(peer); + } else { + peer->link_status = eTDLS_LINK_IDLE; + peer->reason = eTDLS_LINK_UNSPECIFIED; + peer->staId = 0; + peer->discovery_attempt = 0; + } + } + } +} + +/** + * wlan_hdd_tdls_init() - tdls initializaiton + * @pAdapter: hdd adapter + * + * Return: 0 for success or negative errno otherwise + */ +int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tdlsCtx_t *pHddTdlsCtx; + int i; + uint8_t staIdx; + tdlsInfo_t *tInfo; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (NULL == pHddCtx) + return -EINVAL; + + mutex_lock(&pHddCtx->tdls_lock); + + if (false == pHddCtx->config->fEnableTDLSSupport) { + pHddCtx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED; + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(LOGE, + FL("TDLS not enabled (%d) or FW doesn't support"), + pHddCtx->config->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 = cdf_mem_malloc(sizeof(tdlsCtx_t)); + + if (NULL == pHddTdlsCtx) { + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(LOGE, FL("malloc failed!")); + return -ENOMEM; + } + /* initialize TDLS pAdater context */ + cdf_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); + + cdf_mc_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, + CDF_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 { + pHddTdlsCtx = pAdapter->sessionCtx.station.pHddTdlsCtx; + + wlan_hdd_tdls_timers_stop(pHddTdlsCtx); + + wlan_hdd_tdls_del_non_forced_peers(pHddTdlsCtx); + + pHddCtx->connected_peer_count = 0; + } + + /* initialize TDLS global context */ + pHddCtx->connected_peer_count = 0; + sme_set_tdls_power_save_prohibited(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->config->fEnableTDLSSleepSta || + pHddCtx->config->fEnableTDLSBufferSta || + pHddCtx->config->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(LOG1, 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; + cdf_mem_zero(&pHddCtx->tdlsConnInfo[staIdx].peerMac, + CDF_MAC_ADDR_SIZE); + } + + 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->config->fTDLSTxStatsPeriod; + pHddTdlsCtx->threshold_config.tx_packet_n = + pHddCtx->config->fTDLSTxPacketThreshold; + pHddTdlsCtx->threshold_config.discovery_tries_n = + pHddCtx->config->fTDLSMaxDiscoveryAttempt; + pHddTdlsCtx->threshold_config.idle_packet_n = + pHddCtx->config->fTDLSIdlePacketThreshold; + pHddTdlsCtx->threshold_config.rssi_trigger_threshold = + pHddCtx->config->fTDLSRSSITriggerThreshold; + pHddTdlsCtx->threshold_config.rssi_teardown_threshold = + pHddCtx->config->fTDLSRSSITeardownThreshold; + pHddTdlsCtx->threshold_config.rssi_delta = + pHddCtx->config->fTDLSRSSIDelta; + + if (false == pHddCtx->config->fEnableTDLSImplicitTrigger) { + pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s TDLS Implicit trigger not enabled!", __func__); + } else { + pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED; + } + +#ifdef CONFIG_CNSS + cnss_init_work(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); +#else + INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); +#endif + +#ifdef CONFIG_CNSS + cnss_init_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, + wlan_hdd_tdls_schedule_scan); +#else + INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, + wlan_hdd_tdls_schedule_scan); +#endif + + /* + * Release tdls lock before calling in SME api + * which would try to acquire sme lock. + */ + mutex_unlock(&pHddCtx->tdls_lock); + tInfo = cdf_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL == tInfo) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("cdf_mem_alloc failed for tInfo")); + cdf_mc_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + cdf_mem_free(pHddTdlsCtx); + return -ENOMEM; + } + + 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->config->fEnableTDLSOffChannel) + tInfo->tdls_options |= ENA_TDLS_OFFCHAN; + if (pHddCtx->config->fEnableTDLSBufferSta) + tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->config->fEnableTDLSSleepSta) + tInfo->tdls_options |= ENA_TDLS_SLEEP_STA; + tInfo->peer_traffic_ind_window = pHddCtx->config->fTDLSPuapsdPTIWindow; + tInfo->peer_traffic_response_timeout = + pHddCtx->config->fTDLSPuapsdPTRTimeout; + tInfo->puapsd_mask = pHddCtx->config->fTDLSUapsdMask; + tInfo->puapsd_inactivity_time = + pHddCtx->config->fTDLSPuapsdInactivityTimer; + tInfo->puapsd_rx_frame_threshold = + pHddCtx->config->fTDLSRxFrameThreshold; + + dump_tdls_state_param_setting(tInfo); + + cdf_ret_status = sme_update_fw_tdls_state(pHddCtx->hHal, tInfo, true); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + cdf_mem_free(tInfo); + cdf_mc_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + cdf_mem_free(pHddTdlsCtx); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_tdls_exit() - TDLS de-initialization + * @pAdapter: HDD adapter + * + * Return: None + */ +void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) +{ + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; + tdlsInfo_t *tInfo; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddCtx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is NULL")); + return; + } + + if (!test_bit(TDLS_INIT_DONE, &pAdapter->event_flags)) { + hddLog(LOGE, FL("TDLS init was not done, exit")); + return; + } + + 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 + */ + hddLog(LOG2, + FL("pHddTdlsCtx is NULL, adapter device mode: %s(%d)"), + hdd_device_mode_to_string(pAdapter->device_mode), + pAdapter->device_mode); + goto done; + } + + cds_flush_work(&pHddTdlsCtx->implicit_setup); + cds_flush_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work); + + mutex_lock(&pHddCtx->tdls_lock); + + /* must stop timer here before freeing peer list, because peerIdleTimer is + part of peer list structure. */ + wlan_hdd_tdls_timers_destroy(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx); + + mutex_unlock(&pHddCtx->tdls_lock); + + wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt); + + /* No need to post message during driver unlaod because MC thread is + already shutdown */ + if (!pHddCtx->isUnloadInProgress) { + tInfo = cdf_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL != tInfo) { + tInfo->vdev_id = pAdapter->sessionId; + tInfo->tdls_state = eTDLS_SUPPORT_DISABLED; + 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->config->fEnableTDLSOffChannel) + tInfo->tdls_options |= ENA_TDLS_OFFCHAN; + if (pHddCtx->config->fEnableTDLSBufferSta) + tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->config->fEnableTDLSSleepSta) + tInfo->tdls_options |= ENA_TDLS_SLEEP_STA; + tInfo->peer_traffic_ind_window = + pHddCtx->config->fTDLSPuapsdPTIWindow; + tInfo->peer_traffic_response_timeout = + pHddCtx->config->fTDLSPuapsdPTRTimeout; + tInfo->puapsd_mask = pHddCtx->config->fTDLSUapsdMask; + tInfo->puapsd_inactivity_time = + pHddCtx->config->fTDLSPuapsdInactivityTimer; + tInfo->puapsd_rx_frame_threshold = + pHddCtx->config->fTDLSRxFrameThreshold; + + dump_tdls_state_param_setting(tInfo); + + cdf_ret_status = + sme_update_fw_tdls_state(pHddCtx->hHal, tInfo, false); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + cdf_mem_free(tInfo); + } + } else { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: cdf_mem_alloc failed for tInfo", __func__); + } + } + + pHddTdlsCtx->magic = 0; + pHddTdlsCtx->pAdapter = NULL; + + cdf_mem_free(pHddTdlsCtx); + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + pHddTdlsCtx = NULL; + +done: + clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags); +} + +/** + * wlan_hdd_tdls_monitor_timers_destroy() - destroy all tdls monitoring timers + * @pHddTdlsCtx: TDLS context + * + * Return: Void + */ +static void wlan_hdd_tdls_monitor_timers_destroy(tdlsCtx_t *pHddTdlsCtx) +{ + cdf_mc_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + cdf_mc_timer_destroy(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); +} + +/** + * wlan_hdd_tdls_timers_destroy() - Destroy all the tdls timers running + * @pHddTdlsCtx: TDLS Context + * + * Return: Void + */ +static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_monitor_timers_destroy(pHddTdlsCtx); +} + +/** + * wlan_hdd_tdls_get_peer() - find or add an peer given mac address + * @pAdapter: HDD adapter + * @mac: MAC address used to find or create peer + * + * Search peer given an MAC address and create one if not found. + * + * Return: Pointer to peer if mac address exist or peer creation + * succeeds; NULL if peer creation fails + */ +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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + 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 = cdf_mem_malloc(sizeof(hddTdlsPeer_t)); + if (NULL == peer) { + hddLog(CDF_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) { + cdf_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]; + + cdf_mem_zero(peer, sizeof(hddTdlsPeer_t)); + cdf_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac)); + peer->pHddTdlsCtx = pHddTdlsCtx; + peer->pref_off_chan_num = pHddCtx->config->fTDLSPrefOffChanNum; + + list_add_tail(&peer->node, head); + mutex_unlock(&pHddCtx->tdls_lock); + + return peer; +} + +/** + * wlan_hdd_tdls_set_cap() - set TDLS capability type + * @pAdapter: HDD adapter + * @mac: peer mac address + * @cap: TDLS capability type + * + * Return: 0 if successful or negative errno otherwise + */ +int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const uint8_t *mac, + tTDLSCapType cap) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->tdls_support = cap; + + return 0; +} + +/** + * wlan_hdd_tdls_set_peer_link_status() - set TDLS peer link status + * @curr_peer: peer + * @status: status + * @reason: reason + * + * Return: Void + */ +void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, + tTDLSLinkStatus status, + tTDLSLinkReason reason) +{ + int32_t state = 0; + int32_t res = 0; + hdd_context_t *pHddCtx; + if (curr_peer == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + return; + } + + if (curr_peer->pHddTdlsCtx == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + hddLog(CDF_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) { + curr_peer->reason = reason; + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + (*curr_peer->state_change_notification)(curr_peer->peerMac, + state, + res, + curr_peer-> + pHddTdlsCtx->pAdapter); + } + return; +} + +/** + * wlan_hdd_tdls_set_link_status() - set TDLS peer link status + * @pAdapter: HDD adapter + * @mac: mac address of TDLS peer + * @linkStatus: status + * @reason: reason + * + * Return: Void + */ +void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, + const uint8_t *mac, + tTDLSLinkStatus linkStatus, + tTDLSLinkReason reason) +{ + int32_t state = 0; + int32_t res = 0; + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); + if (curr_peer == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + curr_peer->reason = reason; + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, &state, &res); + (curr_peer->state_change_notification)(mac, + state, + res, + curr_peer->pHddTdlsCtx-> + pAdapter); + } + + return; +} + +/** + * wlan_hdd_tdls_recv_discovery_resp() - handling of tdls discovery response + * @pAdapter: HDD adapter + * @mac: mac address of peer from which the response was received + * + * Return: 0 for success or negative errno otherwise + */ +int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, + const uint8_t *mac) +{ + hddTdlsPeer_t *curr_peer; + tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx; + + if (NULL == pHddTdlsCtx) { + hddLog(LOGE, FL("pHddTdlsCtx is NULL")); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + hddLog(LOGE, FL("pHddCtx is not valid")); + return -EINVAL; + } + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (NULL == curr_peer) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + 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) { + cdf_mc_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); + } + + hddLog(LOG1, + "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 alredy met. Make sure RSSI + threshold is also met before setting up TDLS link */ + if ((int32_t) curr_peer->rssi > + (int32_t) pHddTdlsCtx->threshold_config. + rssi_trigger_threshold) { + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERED, + eTDLS_LINK_SUCCESS); + hddLog(LOG1, + "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 { + hddLog(LOG1, + "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--; + } + } + + curr_peer->tdls_support = eTDLS_CAP_SUPPORTED; + return 0; +} + +/** + * wlan_hdd_tdls_set_peer_caps() - set TDLS peer capability + * @pAdapter: HDD adapter + * @mac: MAC address of the TDLS peer + * @StaParams: CSR Station Parameter + * @isBufSta: is peer buffer station + * @isOffChannelSupported: Is off channel supported + * + * Return: 0 for success or negative errno otherwise + */ +int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter, + const uint8_t *mac, + tCsrStaParams *StaParams, + bool isBufSta, bool isOffChannelSupported) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->uapsdQueues = StaParams->uapsd_queues; + curr_peer->maxSp = StaParams->max_sp; + curr_peer->isBufSta = isBufSta; + curr_peer->isOffChannelSupported = isOffChannelSupported; + + cdf_mem_copy(curr_peer->supported_channels, + StaParams->supported_channels, + StaParams->supported_channels_len); + + curr_peer->supported_channels_len = StaParams->supported_channels_len; + + cdf_mem_copy(curr_peer->supported_oper_classes, + StaParams->supported_oper_classes, + StaParams->supported_oper_classes_len); + + curr_peer->supported_oper_classes_len = + StaParams->supported_oper_classes_len; + return 0; +} + +/** + * wlan_hdd_tdls_get_link_establish_params() - get TDLS link establish + * parameter + * @pAdapter: HDD adapter + * @mac: mac address + * @tdlsLinkEstablishParams: output parameter to store the result + * + * Return: 0 for success or negative errno otherwise + */ +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) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + 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; + + cdf_mem_copy(tdlsLinkEstablishParams->supportedChannels, + curr_peer->supported_channels, + curr_peer->supported_channels_len); + + tdlsLinkEstablishParams->supportedChannelsLen = + curr_peer->supported_channels_len; + + cdf_mem_copy(tdlsLinkEstablishParams->supportedOperClasses, + curr_peer->supported_oper_classes, + curr_peer->supported_oper_classes_len); + + tdlsLinkEstablishParams->supportedOperClassesLen = + curr_peer->supported_oper_classes_len; + return 0; +} + +/** + * wlan_hdd_tdls_set_rssi() - Set TDLS RSSI on peer given by mac + * @pAdapter: HDD adapter + * @mac: MAC address of Peer + * @rxRssi: rssi value + * + * Set RSSI on TDSL peer + * + * Return: 0 for success or -EINVAL otherwise + */ +int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, const uint8_t *mac, + int8_t rxRssi) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->rssi = rxRssi; + + return 0; +} + +/** + * wlan_hdd_tdls_set_responder() - Set/clear TDLS peer's responder role + * @pAdapter: HDD adapter + * @mac: MAC address of Peer + * @responder: flag that indicates if the TDLS peer should be responder or not + * + * Return: 0 for success or -EINVAL otherwise + */ +int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t responder) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->is_responder = responder; + + return 0; +} + +/** + * wlan_hdd_tdls_set_signature() - Set TDLS peer's signature + * @pAdapter: HDD adapter + * @mac: MAC address of TDLS Peer + * @uSignature: signature value + * + * Return: 0 for success or -EINVAL otherwise + */ +int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t uSignature) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->signature = uSignature; + + return 0; +} + +/** + * wlan_hdd_tdls_extract_da() - Extract destination address from socket buffer + * @skb: socket buffer + * @mac: output mac address buffer to store the destination address + * + * Return: Void + */ +void wlan_hdd_tdls_extract_da(struct sk_buff *skb, uint8_t *mac) +{ + memcpy(mac, skb->data, 6); +} + +/** + * wlan_hdd_tdls_extract_sa() - Extract source address from socket buffer + * @skb: socket buffer + * @mac: output mac address buffer to store the source address + * + * Return: Void + */ +void wlan_hdd_tdls_extract_sa(struct sk_buff *skb, uint8_t *mac) +{ + memcpy(mac, skb->data + 6, 6); +} + +/** + * wlan_hdd_tdls_increment_pkt_count() - update statistics counter on tdls peer + * @pAdapter: HDD adapter + * @mac: MAC address of the TDLS peer + * @tx: If 1, increment tx packet counter, if 0, increment rx packet counter + * + * Return: 0 for success or negative errno otherwise + */ +int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, + const uint8_t *mac, uint8_t tx) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode) + return -EINVAL; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOG1, FL("curr_peer is NULL")); + return -EINVAL; + } + + if (tx) + curr_peer->tx_pkt++; + else + curr_peer->rx_pkt++; + + return 0; +} + +/** + * wlan_hdd_tdls_check_config() - validate tdls configuration parameters + * @config: tdls configuration parameter structure + * + * Return: 0 if all parameters are valid; -EINVAL otherwise + */ +static int wlan_hdd_tdls_check_config(tdls_config_params_t *config) +{ + if (config->tdls > 2) { + hddLog(LOGE, + FL("Invalid 1st argument %d. <0...2>"), + config->tdls); + return -EINVAL; + } + if (config->tx_period_t < CFG_TDLS_TX_STATS_PERIOD_MIN || + config->tx_period_t > CFG_TDLS_TX_STATS_PERIOD_MAX) { + hddLog(LOGE, + FL("Invalid 2nd argument %d. <%d...%ld>"), + config->tx_period_t, CFG_TDLS_TX_STATS_PERIOD_MIN, + CFG_TDLS_TX_STATS_PERIOD_MAX); + return -EINVAL; + } + if (config->tx_packet_n < CFG_TDLS_TX_PACKET_THRESHOLD_MIN || + config->tx_packet_n > CFG_TDLS_TX_PACKET_THRESHOLD_MAX) { + hddLog(LOGE, + FL("Invalid 3rd argument %d. <%d...%ld>"), + config->tx_packet_n, CFG_TDLS_TX_PACKET_THRESHOLD_MIN, + CFG_TDLS_TX_PACKET_THRESHOLD_MAX); + return -EINVAL; + } + if (config->discovery_tries_n < CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN || + config->discovery_tries_n > CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX) { + hddLog(LOGE, + FL("Invalid 5th argument %d. <%d...%d>"), + config->discovery_tries_n, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, + CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX); + return -EINVAL; + } + if (config->idle_packet_n < CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN || + config->idle_packet_n > CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX) { + hddLog(LOGE, + FL("Invalid 7th argument %d. <%d...%d>"), + config->idle_packet_n, + CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN, + CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX); + return -EINVAL; + } + if (config->rssi_trigger_threshold < CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN + || config->rssi_trigger_threshold > + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX) { + hddLog(LOGE, + FL("Invalid 9th argument %d. <%d...%d>"), + config->rssi_trigger_threshold, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN, + CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MAX); + return -EINVAL; + } + if (config->rssi_teardown_threshold < + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN + || config->rssi_teardown_threshold > + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX) { + hddLog(LOGE, + FL("Invalid 10th argument %d. <%d...%d>"), + config->rssi_teardown_threshold, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, + CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX); + return -EINVAL; + } + return 0; +} + +/** + * wlan_tdd_tdls_reset_tx_rx() - reset tx/rx counters for all tdls peers + * @pHddTdlsCtx: TDLS context + * + * Caller has to take the TDLS lock before calling this function + * + * Return: Void + */ +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; +} + +/** + * wlan_hdd_tdls_implicit_disable() - disable implicit tdls triggering + * @pHddTdlsCtx: TDLS context + * + * Return: Void + */ +static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx) +{ + wlan_hdd_tdls_timers_stop(pHddTdlsCtx); +} + +/** + * wlan_hdd_tdls_implicit_enable() - enable implicit tdls triggering + * @pHddTdlsCtx: TDLS context + * + * Return: Void + */ +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); + +} + +/** + * wlan_hdd_tdls_set_mode() - set TDLS mode + * @pHddCtx: HDD context + * @tdls_mode: TDLS mode + * @bUpdateLast: Switch on if to set pHddCtx->tdls_mode_last to tdls_mode. + * If 1, set pHddCtx->tdls_mode_last to tdls_mode, otherwise + * set pHddCtx->tdls_mode_last to pHddCtx->tdls_mode + * + * Return: Void + */ +void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, + eTDLSSupportMode tdls_mode, bool bUpdateLast) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + CDF_STATUS status; + hdd_adapter_t *pAdapter; + tdlsCtx_t *pHddTdlsCtx; + + hddLog(LOG1, "%s mode %d", __func__, (int)tdls_mode); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + if (pHddCtx->tdls_mode == tdls_mode) { + mutex_unlock(&pHddCtx->tdls_lock); + hddLog(LOG1, FL("already in mode %d"), (int)tdls_mode); + return; + } + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + + while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) { + pAdapter = pAdapterNode->pAdapter; + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) { + if (eTDLS_SUPPORT_ENABLED == 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); +} + +/** + * wlan_hdd_tdls_set_params() - set TDLS parameters + * @dev: net device + * @config: TDLS configuration parameters + * + * Return: 0 if success or negative errno otherwise + */ +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; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (NULL == pHddTdlsCtx) { + hddLog(LOGE, FL("TDLS not enabled!")); + return -EINVAL; + } + + if (wlan_hdd_tdls_check_config(config) != 0) { + return -EINVAL; + } + + /* 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(LOGE, FL("Already in mode %d"), config->tdls); + return -EINVAL; + } + + /* copy the configuration only when given tdls mode is implicit trigger enable */ + if (eTDLS_SUPPORT_ENABLED == req_tdls_mode) { + memcpy(&pHddTdlsCtx->threshold_config, config, + sizeof(tdls_config_params_t)); + } + + hddLog(LOGE, + FL("iw set tdls params: %d %d %d %d %d %d %d"), + config->tdls, + config->tx_period_t, + config->tx_packet_n, + config->discovery_tries_n, + config->idle_packet_n, + config->rssi_trigger_threshold, + config->rssi_teardown_threshold); + + wlan_hdd_tdls_set_mode(pHddCtx, req_tdls_mode, true); + + tdlsParams = cdf_mem_malloc(sizeof(tdlsInfo_t)); + if (NULL == tdlsParams) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: cdf_mem_alloc failed for tdlsParams", __func__); + return -ENOMEM; + } + + 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->config->fEnableTDLSOffChannel) + tdlsParams->tdls_options |= ENA_TDLS_OFFCHAN; + if (pHddCtx->config->fEnableTDLSBufferSta) + tdlsParams->tdls_options |= ENA_TDLS_BUFFER_STA; + if (pHddCtx->config->fEnableTDLSSleepSta) + tdlsParams->tdls_options |= ENA_TDLS_SLEEP_STA; + tdlsParams->peer_traffic_ind_window = + pHddCtx->config->fTDLSPuapsdPTIWindow; + tdlsParams->peer_traffic_response_timeout = + pHddCtx->config->fTDLSPuapsdPTRTimeout; + tdlsParams->puapsd_mask = pHddCtx->config->fTDLSUapsdMask; + tdlsParams->puapsd_inactivity_time = + pHddCtx->config->fTDLSPuapsdInactivityTimer; + tdlsParams->puapsd_rx_frame_threshold = + pHddCtx->config->fTDLSRxFrameThreshold; + + hddLog(LOG1, + "%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 ", + __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); + + cdf_ret_status = sme_update_fw_tdls_state(pHddCtx->hHal, tdlsParams, true); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + cdf_mem_free(tdlsParams); + return -EINVAL; + } + + 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; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (!hdd_tdls_ctx) { + /* may be TDLS is not applicable for this adapter */ + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD TDLS context is null")); + return; + } + + /* If TDLS support is disabled then no need to update target */ + if (false == hdd_ctx->config->fEnableTDLSSupport) { + hddLog(CDF_TRACE_LEVEL_ERROR, 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->config->fEnableTDLSImplicitTrigger) { + hdd_ctx->tdls_mode = + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; + } else { + hdd_ctx->tdls_mode = eTDLS_SUPPORT_ENABLED; + } + } + mutex_unlock(&hdd_ctx->tdls_lock); + + tdls_param = cdf_mem_malloc(sizeof(*tdls_param)); + if (!tdls_param) { + hddLog(CDF_TRACE_LEVEL_ERROR, + 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->config->fEnableTDLSOffChannel) && + (!tdls_chan_swit_prohibited)) { + tdls_param->tdls_options |= ENA_TDLS_OFFCHAN; + } + + if (hdd_ctx->config->fEnableTDLSBufferSta) + tdls_param->tdls_options |= ENA_TDLS_BUFFER_STA; + + if (hdd_ctx->config->fEnableTDLSSleepSta) + tdls_param->tdls_options |= ENA_TDLS_SLEEP_STA; + + tdls_param->peer_traffic_ind_window = + hdd_ctx->config->fTDLSPuapsdPTIWindow; + tdls_param->peer_traffic_response_timeout = + hdd_ctx->config->fTDLSPuapsdPTRTimeout; + tdls_param->puapsd_mask = + hdd_ctx->config->fTDLSUapsdMask; + tdls_param->puapsd_inactivity_time = + hdd_ctx->config->fTDLSPuapsdInactivityTimer; + tdls_param->puapsd_rx_frame_threshold = + hdd_ctx->config->fTDLSRxFrameThreshold; + + hddLog(CDF_TRACE_LEVEL_DEBUG, + 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 "), + 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); + + cdf_ret_status = sme_update_fw_tdls_state(hdd_ctx->hHal, + tdls_param, + true); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + cdf_mem_free(tdls_param); + return; + } + return; +} + +/** + * wlan_hdd_tdls_set_sta_id() - set station ID on a tdls peer + * @pAdapter: HDD adapter + * @mac: MAC address of a tdls peer + * @staId: station ID + * + * Return: 0 if success; negative errno otherwise + */ +int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, const uint8_t *mac, + uint8_t staId) +{ + hddTdlsPeer_t *curr_peer; + + curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); + if (curr_peer == NULL) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + curr_peer->staId = staId; + + return 0; +} + +/** + * wlan_hdd_tdls_set_extctrl_param() - set external control parameter on a peer + * @pAdapter: HDD adapter + * @mac: MAC address of the peer + * @chan: Channel + * @max_latency: Maximum latency + * @op_class: Operation class + * @min_bandwidth: Minimal bandwidth + * + * Return: 0 for success; negative errno otherwise + */ +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 -EINVAL; + 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 -EINVAL; + } + curr_peer->op_class_for_pref_off_chan = (uint8_t) op_class; + curr_peer->pref_off_chan_num = (uint8_t) chan; + + if (curr_peer->op_class_for_pref_off_chan) + curr_peer->op_class_for_pref_off_chan_is_set = 1; + else + curr_peer->op_class_for_pref_off_chan_is_set = 0; + + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +/** + * wlan_hdd_tdls_set_force_peer() - set/clear isForcedPeer flag on a peer + * @pAdapter: HDD adapter + * @mac: MAC address of the tdls peer + * @forcePeer: value used to set isForcedPeer flag on the peer + * + * Return: 0 for success; negative errno otherwise + */ +int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, const uint8_t *mac, + bool forcePeer) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (!pHddCtx) + return -EINVAL; + + 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 -EINVAL; + } + + curr_peer->isForcedPeer = forcePeer; + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +/** + * wlan_hdd_tdls_find_peer() - find TDLS peer given its MAC address + * @pAdapter: HDD adapter + * @mac: MAC address of peer + * @mutexLock: Option to indicate if mutex locking is required for searching + * + * Return: 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 uint8_t *mac, bool mutexLock) +{ + uint8_t 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); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + 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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + return NULL; +} + +/** + * wlan_hdd_tdls_find_all_peer() - find all peers matching the input MAC + * @pHddCtx: HDD context + * @mac: MAC address + * + * Return: TDLS peer if a matching is detected; NULL otherwise + */ +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; + CDF_STATUS status = 0; + + mutex_lock(&pHddCtx->tdls_lock); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_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; +} + +/** + * wlan_hdd_tdls_reset_peer() - reset TDLS peer identified by MAC address + * @pAdapter: HDD adapter + * @mac: MAC address of the peer + * + * Return: 0 for success; negative errno otherwise + */ +int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *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) { + hddLog(LOGE, FL("curr_peer is NULL")); + return -EINVAL; + } + + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + curr_peer->staId = 0; + + return 0; +} + +/** + * wlan_hdd_tdls_peer_reset_discovery_processed() - reset discovery status + * @pHddTdlsCtx: TDLS context + * + * This function resets discovery processing bit for all TDLS peers + * + * Caller has to take the lock before calling this function + * + * Return: 0 + */ +static int32_t wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t * + pHddTdlsCtx) +{ + int i; + struct list_head *head; + hddTdlsPeer_t *tmp; + struct list_head *pos, *q; + + pHddTdlsCtx->discovery_peer_cnt = 0; + + 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; +} + +/** + * wlan_hdd_tdls_connected_peers() - Find the number of connected TDLS peers + * @pAdapter: HDD adapter + * + * Return: The number of connected TDLS peers or 0 if error is detected + */ +uint16_t wlan_hdd_tdls_connected_peers(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return 0; + } + + return pHddCtx->connected_peer_count; +} + +/** + * wlan_hdd_tdls_get_all_peers() - dump all TDLS peer info into output string + * @pAdapter: HDD adapter + * @buf: output string buffer to hold the peer info + * @buflen: the size of output string buffer + * + * Return: The size (in bytes) of the valid peer info in the output buffer + */ +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); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + 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); + return init_len - buflen; +} + +/** + * wlan_hdd_tdls_connection_callback() - callback after tdls connection + * @pAdapter: HDD adapter + * + * Return: Void + */ +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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + hddLog(LOG1, + FL("update %d"), + pHddTdlsCtx->threshold_config.tx_period_t); + + if (eTDLS_SUPPORT_ENABLED == 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); + +} + +/** + * wlan_hdd_tdls_disconnection_callback() - callback after tdls disconnection + * @pAdapter: HDD adapter + * + * Return: Void + */ +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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx or pHddTdlsCtx points to NULL")); + return; + } + + hddLog(LOG1, "%s", __func__); + + mutex_lock(&pHddCtx->tdls_lock); + + if (NULL == pHddTdlsCtx) { + mutex_unlock(&pHddCtx->tdls_lock); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return; + } + pHddTdlsCtx->discovery_sent_cnt = 0; + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx); + wlan_hdd_tdls_free_list(pHddTdlsCtx); + + pHddTdlsCtx->curr_candidate = NULL; + + mutex_unlock(&pHddCtx->tdls_lock); +} + +/** + * wlan_hdd_tdls_mgmt_completion_callback() - callback for TDLS management + * TX completion + * @pAdapter: HDD adapter + * @statusCode: management TX completion status + * + * Return: Void + */ +void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, + uint32_t statusCode) +{ + pAdapter->mgmtTxCompletionStatus = statusCode; + hddLog(LOG1, + "%s: Mgmt TX Completion %d", __func__, statusCode); + complete(&pAdapter->tdls_mgmt_comp); +} + +/** + * wlan_hdd_tdls_increment_peer_count() - increment connected TDLS peer counter + * @pAdapter: HDD adapter + * + * Return: Void + */ +void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + pHddCtx->connected_peer_count++; + wlan_hdd_tdls_check_power_save_prohibited(pAdapter); + + hddLog(LOG1, "%s: %d", + __func__, pHddCtx->connected_peer_count); + + mutex_unlock(&pHddCtx->tdls_lock); +} + +/** + * wlan_hdd_tdls_decrement_peer_count() - decrement connected TDLS peer counter + * @pAdapter: HDD adapter + * + * Return: Void + */ +void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + if (pHddCtx->connected_peer_count) + pHddCtx->connected_peer_count--; + wlan_hdd_tdls_check_power_save_prohibited(pAdapter); + + hddLog(LOG1, "%s: %d", + __func__, pHddCtx->connected_peer_count); + + mutex_unlock(&pHddCtx->tdls_lock); + +} + + +/** + * wlan_hdd_tdls_find_progress_peer() - find peer if TDLS is ongoing + * @pAdapter: HDD adapter + * @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. + * + * Return: Pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL. + */ +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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + hddLog(LOG1, + "%s:" MAC_ADDRESS_STR + " eTDLS_LINK_CONNECTING", + __func__, + MAC_ADDR_ARRAY(curr_peer-> + peerMac)); + return curr_peer; + } + } + } + } + return NULL; +} + +/** + * wlan_hdd_tdls_is_progress() - find the peer with ongoing TDLS progress + * @pHddCtx: HDD context + * @mac: mac address of the peer + * @skip_self: if 1, skip checking self. If 0, search includes self + * + * Return: TDLS peer if found; NULL otherwise + */ +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, + const uint8_t *mac, uint8_t 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; + CDF_STATUS status = 0; + + mutex_lock(&pHddCtx->tdls_lock); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_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; +} + +/** + * __wlan_hdd_tdls_pre_setup() - TDLS Pre implicit setup + * @work: work_struct used to find the TDLS context + * + * Return: Void + */ +static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) +{ + tdlsCtx_t *pHddTdlsCtx = container_of(work, tdlsCtx_t, implicit_setup); + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *temp_peer; + int status; + tSirMacAddr peer_mac; + + if (NULL == pHddTdlsCtx) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + return; + } + + if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: tdls magic number mis-match %u", + __func__, pHddTdlsCtx->magic); + return; + } + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + return; + } + + mutex_lock(&pHddCtx->tdls_lock); + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (NULL == curr_peer) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + goto done; + } + + cdf_mem_copy(&peer_mac, curr_peer->peerMac, sizeof(peer_mac)); + + mutex_unlock(&pHddCtx->tdls_lock); + + temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0); + + if (NULL != temp_peer) { + hddLog(LOG1, + "%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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + goto done; + } + } + + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_DISCOVERING, + eTDLS_LINK_SUCCESS); + + status = + wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter-> + wdev.wiphy, + pHddTdlsCtx->pAdapter->dev, + peer_mac); + + mutex_lock(&pHddCtx->tdls_lock); + + if (NULL == pHddTdlsCtx->curr_candidate) { + hddLog(LOGE, + "%s: current candidate Not valid any more", __func__); + goto done; + } + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (0 != status) { + hddLog(LOGE, + "%s: " MAC_ADDRESS_STR " discovery could not sent", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) { + mutex_unlock(&pHddCtx->tdls_lock); + wlan_hdd_tdls_set_peer_link_status(curr_peer, + eTDLS_LINK_IDLE, + eTDLS_LINK_UNSPECIFIED); + mutex_lock(&pHddCtx->tdls_lock); + } + goto done; + } + + pHddTdlsCtx->discovery_sent_cnt++; + + curr_peer->discovery_attempt++; + + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); + + hddLog(LOG1, + "%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); + return; +} + +/** + * wlan_hdd_tdls_pre_setup() - TDLS Pre implicit setup + * @work: work_struct used to find the TDLS context + * + * Return: Void + */ +void wlan_hdd_tdls_pre_setup(struct work_struct *work) +{ + cds_ssr_protect(__func__); + __wlan_hdd_tdls_pre_setup(work); + cds_ssr_unprotect(__func__); +} + +/** + * wlan_hdd_tdls_copy_scan_context() - Copy TDLS scan context + * @pHddCtx: HDD context + * @wiphy: wiphy pointer + * @dev: net device + * request: source scan context + * + * Copy the source scan context into the HDD context's TDLS scan context + * + * Return: 0 for success; negative errno otherwise + */ +int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + struct net_device *dev, +#endif + struct cfg80211_scan_request *request) +{ + tdls_scan_context_t *scan_ctx; + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + hddLog(LOGE, FL("pHddCtx is not valid")); + return -EINVAL; + } + + scan_ctx = &pHddCtx->tdls_scan_ctxt; + + scan_ctx->wiphy = wiphy; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + scan_ctx->dev = dev; +#endif + + scan_ctx->scan_request = request; + return 0; +} + +/** + * wlan_hdd_tdls_scan_init_work() - schedule tdls scan work + * @pHddCtx: HDD context + * @wiphy: wiphy pointer + * @dev: net device + * @request: scan request + * @delay: delay value to pass to the work scheduling + * + * Return: Void + */ +static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx, + struct wiphy *wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + 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)) + 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); +} + +/** + * wlan_hdd_tdls_scan_callback() - callback for TDLS scan operation + * @pAdapter: HDD adapter + * @wiphy: wiphy + * @dev: net device + * @request: scan request + * + * Return: negative = caller should stop and return error code immediately + * 0 = caller should stop and return success immediately + * 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)) + 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; + + 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; + hddLog(LOG1, + "%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; + } + hddLog(LOGW, + "%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_tdls_connected_peers(pAdapter); + if (connectedTdlsPeers + && (pHddCtx->tdls_scan_ctxt.attempt < + TDLS_MAX_SCAN_SCHEDULE)) { + delay = + (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION * + connectedTdlsPeers); + hddLog(LOG1, + "%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)) + dev, +#endif + request, + msecs_to_jiffies(delay)); + /* scan should not continue */ + return 0; + } + /* no connected peer or max retry reached, scan continue */ + hddLog(LOG1, + "%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_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode) { + /* disable implicit trigger logic & tdls operatoin */ + wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, false); + /* indicate the teardown all connected to peer */ + connectedTdlsPeers = wlan_hdd_tdls_connected_peers(pAdapter); + if (connectedTdlsPeers) { + uint8_t staIdx; + uint8_t num = 0; + uint8_t i; + bool 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->config->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->config->fEnableTDLSSleepSta) && + (allPeersBufStas)) { + /* All connected peers bufStas and we can be sleepSta + * so allow scan + */ + hddLog(LOG1, + "%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++) { + hddLog(LOG1, + "%s: indicate TDLS teadown (staId %d)", + __func__, + connectedPeerList[i]->staId); + + wlan_hdd_tdls_indicate_teardown + (connectedPeerList[i]->pHddTdlsCtx-> + pAdapter, connectedPeerList[i], + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } + } + /* schedule scan */ + delay = + (unsigned long)(TDLS_DELAY_SCAN_PER_CONNECTION * + connectedTdlsPeers); + + hddLog(LOG1, + "%s: tdls enabled (mode %d), connected_peers %d. schedule scan %lu msec", + __func__, pHddCtx->tdls_mode, + wlan_hdd_tdls_connected_peers(pAdapter), delay); + + wlan_hdd_tdls_scan_init_work(pHddCtx, wiphy, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + dev, +#endif + request, + msecs_to_jiffies(delay)); + /* scan should not continue */ + return 0; + } + /* no connected peer, scan continue */ + hddLog(LOG1, + "%s: tdls_mode %d, and no tdls connection. scan allowed", + __func__, pHddCtx->tdls_mode); + } + return 1; +} + +/** + * wlan_hdd_tdls_scan_done_callback() - callback for tdls scan done event + * @pAdapter: HDD adapter + * + * Return: Void + */ +void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("pHddCtx is not valid")); + 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_EXPLICIT_TRIGGER_ONLY == pHddCtx->tdls_mode_last) { + hddLog(LOG1, + ("%s: revert tdls mode %d"), __func__, + pHddCtx->tdls_mode_last); + + wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, false); + } +} + +/** + * wlan_hdd_tdls_timer_restart() - restart TDLS timer + * @pAdapter: HDD adapter + * @timer: timer to restart + * @expirationTime: new expiration time to set for the timer + * + * Return: Void + */ +void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter, + cdf_mc_timer_t *timer, + uint32_t expirationTime) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* Check whether driver load unload is in progress */ + if (cds_is_load_unload_in_progress()) { + hddLog(LOGE, FL("Driver load/unload is in progress.")); + return; + } + + if (hdd_conn_is_connected(pHddStaCtx)) { + cdf_mc_timer_stop(timer); + cdf_mc_timer_start(timer, expirationTime); + } +} + +/** + * wlan_hdd_tdls_indicate_teardown() - indicate tdls teardown + * @pAdapter: HDD adapter + * @curr_peer: peer tdls teardown happened + * @reason: teardown reason + * + * Return: Void + */ +void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, + hddTdlsPeer_t *curr_peer, uint16_t reason) +{ + if (NULL == pAdapter || NULL == curr_peer) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + cfg80211_tdls_oper_request(pAdapter->dev, + curr_peer->peerMac, + NL80211_TDLS_TEARDOWN, reason, GFP_KERNEL); +} + +/** + * wlan_hdd_set_callback() - set state change callback on current TDLS peer + * @curr_peer: current TDLS peer + * @callback: state change callback + * + * Return: 0 if success; negative errno otherwise + */ +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 -EINVAL; + pAdapter = curr_peer->pHddTdlsCtx->pAdapter; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if ((NULL == pHddCtx)) + return -EINVAL; + mutex_lock(&pHddCtx->tdls_lock); + curr_peer->state_change_notification = callback; + mutex_unlock(&pHddCtx->tdls_lock); + return 0; +} + +/** + * wlan_hdd_tdls_get_wifi_hal_state() - get tdls wifi hal state on current peer + * @curr_peer: current TDLS peer + * @state: output parameter to store the tdls wifi hal state + * @reason: output parameter to store the reason of the current peer + * + * Return: Void + */ +void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, + int32_t *state, int32_t *reason) +{ + *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: + *state = QCA_WIFI_HAL_TDLS_ESTABLISHED; + break; + case eTDLS_LINK_TEARING: + *state = QCA_WIFI_HAL_TDLS_DROPPED; + break; + } +} + +/** + * wlan_hdd_tdls_get_status() - get tdls status on current tdls peer + * @pAdapter: HDD adapter + * @mac: MAC address of current TDLS peer + * @state: output parameter to store the tdls wifi hal state + * @reason: output parameter to store the reason of the current peer + * + * Return: 0 if success; negative errno otherwise + */ +int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, + const uint8_t *mac, int32_t *state, + int32_t *reason) +{ + hddTdlsPeer_t *curr_peer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); + if (curr_peer == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("curr_peer is NULL")); + *state = QCA_WIFI_HAL_TDLS_DISABLED; + *reason = eTDLS_LINK_UNSPECIFIED; + } else { + if (pHddCtx->config->fTDLSExternalControl && + (false == curr_peer->isForcedPeer)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("curr_peer is not Forced")); + *state = QCA_WIFI_HAL_TDLS_DISABLED; + *reason = eTDLS_LINK_UNSPECIFIED; + } else { + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, + state, reason); + } + } + + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason); + return 0; +} + +#ifdef FEATURE_WLAN_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}, +}; + +/** + * __wlan_hdd_cfg80211_exttdls_get_status() - handle get status cfg80211 command + * @wiphy: wiphy + * @wdev: wireless dev + * @data: netlink buffer with the mac address of the peer to get the status for + * @data_len: length of data in bytes + */ +static int +__wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint8_t peer[ETH_ALEN] = { 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]; + CDF_STATUS ret; + uint32_t state; + int32_t reason; + uint32_t global_operating_class = 0; + uint32_t channel = 0; + struct sk_buff *skb = NULL; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + return -EINVAL; + } + if (pHddCtx->config->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(CDF_TRACE_LEVEL_ERROR, FL("Invalid attribute")); + return -EINVAL; + } + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); + ret = wlan_hdd_tdls_get_status(pAdapter, peer, &state, &reason); + if (0 != ret) { + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -EINVAL; + } + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + return cfg80211_vendor_cmd_reply(skb); +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. + */ +int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_get_status(wiphy, wdev, data, + data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_exttdls_callback() - notify cfg80211 state change + * @mac: MAC address of the peer with state change + * @state: New state + * @reason: Reason to enter new state + * @ctx: HDD adapter + * + * Return: 0 for success; negative errno otherwise + */ +static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac, + uint32_t state, + int32_t 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; + uint32_t global_operating_class = 0; + uint32_t channel = 0; + if (wlan_hdd_validate_context(pHddCtx)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid ")); + return -EINVAL; + } + if (pHddCtx->config->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(CDF_TRACE_LEVEL_ERROR, + FL("cfg80211_vendor_event_alloc failed")); + return -EINVAL; + } + hddLog(CDF_TRACE_LEVEL_INFO, FL("Reason: %d Status: %d Class: %d Channel: %d tdls 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, + CDF_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(CDF_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; +} + +/** + * __wlan_hdd_cfg80211_exttdls_enable() - enable an externally controllable + * TDLS peer and set parameters + * wiphy: wiphy + * @wdev: wireless dev pointer + * @data: netlink buffer with peer MAC address and configuration parameters + * @data_len: size of data in bytes + * + * This function sets channel, operation class, maximum latency and minimal + * bandwidth parameters on a TDLS peer that's externally controllable. + * + * Return: 0 for success; negative errno otherwise + */ +static int +__wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + uint8_t peer[ETH_ALEN] = { 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]; + CDF_STATUS status; + tdls_req_params_t pReqMsg = { 0 }; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + if (pHddCtx->config->fTDLSExternalControl == false) { + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("attr channel failed")); + return -EINVAL; + } + pReqMsg.channel = + nla_get_s32(tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]); + hddLog(CDF_TRACE_LEVEL_INFO, FL("Channel Num (%d)"), pReqMsg.channel); + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL("Operating class (%d)"), + pReqMsg.global_operating_class); + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL("Latency (%d)"), + pReqMsg.max_latency_ms); + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL("Bandwidth (%d)"), + pReqMsg.min_bandwidth_kbps); + return 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); +} + +/** + * 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. + */ +int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_enable(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_exttdls_disable() - disable an externally controllable + * TDLS peer + * wiphy: wiphy + * @wdev: wireless dev pointer + * @data: netlink buffer with peer MAC address + * @data_len: size of data in bytes + * + * This function disables an externally controllable TDLS peer + * + * Return: 0 for success; negative errno otherwise + */ +static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + u8 peer[ETH_ALEN] = {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]; + CDF_STATUS status; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return -EINVAL; + } + if (pHddCtx->config->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(CDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + return -EINVAL; + } + if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); + return wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); +} + +/** + * 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. + */ +int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_exttdls_disable(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_tdls_add_station() - add or change a TDLS peer station + * @wiphy: wiphy + * @dev: net device + * @mac: MAC address of the TDLS peer + * @update: if non-0, modify the peer with StaParams; if 0, add new peer + * @StaParams: station parameters for the TDLS to change + * + * Return: 0 if success; negative errno otherwise + */ +int wlan_hdd_tdls_add_station(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *mac, + bool update, tCsrStaParams *StaParams) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + CDF_STATUS status; + hddTdlsPeer_t *pTdlsPeer; + uint16_t numCurrTdlsPeers; + unsigned long rc; + long ret; + + ENTER(); + + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) { + hddLog(CDF_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)) { + hddLog(LOG1, + "%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) { + hddLog(LOGE, + "%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)))) { + hddLog(LOG1, + "%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)))) { + hddLog(LOGE, + "%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)) { + hddLog(LOG1, + "%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_tdls_connected_peers(pAdapter); + if (pHddCtx->max_num_tdls_sta <= numCurrTdlsPeers) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + hddLog(LOG1, + "%s: TDLS Peer Parameters.", __func__); + if (StaParams->htcap_present) { + hddLog(LOG1, + "ht_capa->cap_info: %0x", + StaParams->HTCap.capInfo); + hddLog(LOG1, + "ht_capa->extended_capabilities: %0x", + StaParams->HTCap.extendedHtCapInfo); + } + hddLog(LOG1, + "params->capability: %0x", StaParams->capability); + hddLog(LOG1, + "params->ext_capab_len: %0x", + StaParams->extn_capability[0]); + if (StaParams->vhtcap_present) { + hddLog(LOG1, + "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; + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "Supported rates:"); + for (i = 0; i < sizeof(StaParams->supported_rates); i++) + hddLog(LOG1, "[%d]: %x ", i, + StaParams->supported_rates[i]); + } + } /* end debug code */ + else if ((1 == update) && (NULL == StaParams)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s : update is true, but staParams is NULL. Error!", + __func__); + return -EPERM; + } + + INIT_COMPLETION(pAdapter->tdls_add_station_comp); + + if (!update) { + status = sme_add_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, mac); + } else { + status = sme_change_tdls_peer_sta(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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: timeout waiting for tdls add station indication", + __func__); + return -EPERM; + } + + if (CDF_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + +} + +#if TDLS_MGMT_VERSION2 +/** + * __wlan_hdd_cfg80211_tdls_mgmt() - handle management actions on a given peer + * @wiphy: wiphy + * @dev: net device + * @peer: MAC address of the TDLS peer + * @action_code: action code + * @dialog_token: dialog token + * @status_code: status code + * @peer_capability: peer capability + * @buf: additional IE to include + * @len: length of buf in bytes + * + * Return: 0 if success; negative errno otherwise + */ +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 +/** + * __wlan_hdd_cfg80211_tdls_mgmt() - handle management actions on a given peer + * @wiphy: wiphy + * @dev: net device + * @peer: MAC address of the TDLS peer + * @action_code: action code + * @dialog_token: dialog token + * @status_code: status code + * @buf: additional IE to include + * @len: length of buf in bytes + * + * Return: 0 if success; negative errno otherwise + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, const uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + bool initiator, const uint8_t *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 uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + const uint8_t *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, uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, uint32_t peer_capability, + const uint8_t *buf, size_t len) +#else +static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, + struct net_device *dev, uint8_t *peer, + uint8_t action_code, uint8_t dialog_token, + uint16_t status_code, const uint8_t *buf, + size_t len) +#endif +#endif +{ + + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + u8 peerMac[CDF_MAC_ADDR_SIZE]; + CDF_STATUS status; + int max_sta_failed = 0; + int responder; + unsigned long rc; + uint16_t numCurrTdlsPeers; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) +#if !(TDLS_MGMT_VERSION2) + u32 peer_capability; + peer_capability = 0; +#endif +#endif + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_TDLS_MGMT, + pAdapter->sessionId, action_code)); + + if (0 != wlan_hdd_validate_context(pHddCtx)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -EINVAL; + } + + if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) { + hddLog(LOG1, + "%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 << CDF_STA_MODE) != pHddCtx->concurrency_mode) || + (pHddCtx->no_of_active_sessions[CDF_STA_MODE] > 1)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Multiple STA OR Concurrency detected. Ignore TDLS MGMT frame. action_code=%d, concurrency_mode: 0x%x, active_sessions: %d", + __func__, + action_code, + pHddCtx->concurrency_mode, + pHddCtx->no_of_active_sessions[CDF_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) { + hddLog(LOG1, + "%s: " MAC_ADDRESS_STR + " TDLS mode is disabled. action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), action_code); + return -ENOTSUPP; + } + } + + if (WLAN_IS_TDLS_SETUP_ACTION(action_code)) { + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, true)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_tdls_connected_peers(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 addtion to add_station(). + Anyway, there is no hard to double-check. */ + if (SIR_MAC_TDLS_SETUP_REQ == action_code) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s:" MAC_ADDRESS_STR + " already connected. action %d declined.", + __func__, MAC_ADDR_ARRAY(peer), + action_code); + return -EPERM; + } + } + } + cdf_mem_copy(peerMac, peer, 6); + + hddLog(LOG1, + "%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, peerMac, true); + + if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + responder = pTdlsPeer->is_responder; + else { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR + " peer doesn't exist or not connected %d dialog_token %d status %d, len = %zu", + __func__, MAC_ADDR_ARRAY(peer), + (NULL == + pTdlsPeer) ? -1 : pTdlsPeer->link_status, + dialog_token, status_code, len); + return -EPERM; + } + } + + /* For explicit trigger of DIS_REQ come out of BMPS for + successfully receiving DIS_RSP from peer. */ + if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || + (SIR_MAC_TDLS_DIS_RSP == action_code) || + (SIR_MAC_TDLS_DIS_REQ == action_code)) { + /* Fw will take care if PS offload is enabled. */ + if (SIR_MAC_TDLS_DIS_REQ != action_code) + wlan_hdd_tdls_set_cap(pAdapter, peerMac, + eTDLS_CAP_SUPPORTED); + } + + /* make sure doesn't call send_mgmt() while it is pending */ + if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_send_tdls_mgmt_frame(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, peerMac, + action_code, dialog_token, status_code, + peer_capability, (uint8_t *) buf, len, + !responder); + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_send_tdls_mgmt_frame failed!", __func__); + pAdapter->mgmtTxCompletionStatus = false; + return -EINVAL; + } + + rc = wait_for_completion_timeout(&pAdapter->tdls_mgmt_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); + + if ((0 == rc) || (true != pAdapter->mgmtTxCompletionStatus)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Mgmt Tx Completion timed out TxCompletion %u", + __func__, pAdapter->mgmtTxCompletionStatus); + + if (pHddCtx->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + + if (pHddCtx->isUnloadInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", + __func__); + return -EAGAIN; + } + + pAdapter->mgmtTxCompletionStatus = false; + return -EINVAL; + } + + if (max_sta_failed) { + return max_sta_failed; + } + + if (SIR_MAC_TDLS_SETUP_RSP == action_code) { + return wlan_hdd_tdls_set_responder(pAdapter, peerMac, false); + } else if (SIR_MAC_TDLS_SETUP_CNF == action_code) { + return wlan_hdd_tdls_set_responder(pAdapter, peerMac, 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 +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) +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)) +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)) +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 +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; + + cds_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 + + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_tdls_extctrl_config_peer() - configure an externally controllable + * TDLS peer + * @pAdapter: HDD adapter + * @peer: MAC address of the TDLS peer + * @callback: Callback to set on the peer + * @chan: Channel + * @max_latency: Maximum latency + * @op_class: Operation class + * @min_bandwidth: Minimal bandwidth + * + * Return: 0 on success; negative otherwise + */ +int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, + const uint8_t *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); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + if ((false == pHddCtx->config->fTDLSExternalControl) || + (false == pHddCtx->config->fEnableTDLSImplicitTrigger)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s TDLS External control or Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); + if (pTdlsPeer == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s TDLS Add Force Peer Failed", __func__); + return -EINVAL; + } + if (0 != wlan_hdd_tdls_set_extctrl_param(pAdapter, peer, + chan, max_latency, + op_class, min_bandwidth)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s TDLS Set Peer's External Ctrl Parameter Failed", + __func__); + return -EINVAL; + } + if (0 != wlan_hdd_set_callback(pTdlsPeer, callback)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", __func__); + return -EINVAL; + } + return 0; +} + +/** + * wlan_hdd_tdls_extctrl_deconfig_peer() - de-configure an externally + * controllable TDLS peer + * @pAdapter: HDD adapter + * @peer: MAC address of the tdls peer + * + * Return: 0 if success; negative errno otherwisw + */ +int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, + const uint8_t *peer) +{ + hddTdlsPeer_t *pTdlsPeer; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + if ((false == pHddCtx->config->fTDLSExternalControl) || + (false == pHddCtx->config->fEnableTDLSImplicitTrigger)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s Failed", __func__); + return -EINVAL; + } + if (0 != wlan_hdd_set_callback(pTdlsPeer, NULL)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s TDLS set callback Failed", __func__); + return -EINVAL; + } + return 0; +} + +/** + * __wlan_hdd_cfg80211_tdls_oper() - helper function to handle cfg80211 operation + * on an TDLS peer + * @wiphy: wiphy + * @dev: net device + * @peer: MAC address of the TDLS peer + * @oper: cfg80211 TDLS operation + * + * Return: 0 on success; negative errno otherwise + */ +static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *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; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + hddTdlsPeer_t *pTdlsPeer; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_TDLS_OPER, + pAdapter->sessionId, oper)); + if (NULL == peer) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid arguments", __func__); + return -EINVAL; + } + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + /* QCA 2.0 Discrete ANDs feature capability in HDD config with that + * received from target, so HDD config gives combined intersected result + */ + if (false == pHddCtx->config->fEnableTDLSSupport) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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: + { + CDF_STATUS status; + unsigned long rc; + tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams; + + pTdlsPeer = + wlan_hdd_tdls_find_peer(pAdapter, peer, true); + + if (NULL == pTdlsPeer) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: peer matching " MAC_ADDRESS_STR + " not found, ignore NL80211_TDLS_ENABLE_LINK", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: invalid sta index %u for " + MAC_ADDRESS_STR + " TDLS_ENABLE_LINK failed", __func__, + pTdlsPeer->staId, + MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status) { + if (IS_ADVANCE_TDLS_ENABLE) { + + if (0 != + wlan_hdd_tdls_get_link_establish_params + (pAdapter, peer, + &tdlsLinkEstablishParams)) { + return -EINVAL; + } + INIT_COMPLETION(pAdapter-> + tdls_link_establish_req_comp); + + sme_send_tdls_link_establish_params + (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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Link Establish Request timed out", + __func__); + return -EINVAL; + } + } + wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, + eTDLS_LINK_CONNECTED, + eTDLS_LINK_SUCCESS); + /* start TDLS client registration with TL */ + status = + hdd_roam_register_tdlssta(pAdapter, peer, + pTdlsPeer->staId, + pTdlsPeer-> + signature); + if (CDF_STATUS_SUCCESS == status) { + uint8_t i; + + cdf_mem_zero(&smeTdlsPeerStateParams, + sizeof + (tSmeTdlsPeerStateParams)); + + smeTdlsPeerStateParams.vdevId = + pAdapter->sessionId; + cdf_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->config-> + fTDLSPrefOffChanBandwidth; + if (pTdlsPeer-> + op_class_for_pref_off_chan_is_set) { + smeTdlsPeerStateParams.peerCap. + opClassForPrefOffChanIsSet = + pTdlsPeer-> + op_class_for_pref_off_chan_is_set; + smeTdlsPeerStateParams.peerCap. + opClassForPrefOffChan = + pTdlsPeer-> + op_class_for_pref_off_chan; + } + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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_is_set: %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_is_set, + 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]; + } + + cdf_ret_status = + sme_update_tdls_peer_state(pHddCtx-> + hHal, + &smeTdlsPeerStateParams); + if (CDF_STATUS_SUCCESS != + cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: sme_update_tdls_peer_state failed for " + MAC_ADDRESS_STR, + __func__, + MAC_ADDR_ARRAY(peer)); + return -EPERM; + } + wlan_hdd_tdls_increment_peer_count + (pAdapter); + } + + /* Update TL about the UAPSD masks , to route the packets to firmware */ + if ((true == + pHddCtx->config->fEnableTDLSBufferSta) + || pHddCtx->config->fTDLSUapsdMask) { + int ac; + uint8_t ucAc[4] = { SME_AC_VO, + SME_AC_VI, + SME_AC_BK, + SME_AC_BE}; + uint8_t tlTid[4] = { 7, 5, 2, 3 }; + for (ac = 0; ac < 4; ac++) { + status = sme_enable_uapsd_for_ac( + (WLAN_HDD_GET_CTX(pAdapter))->pcds_context, + pTdlsPeer->staId, ucAc[ac], + tlTid[ac], tlTid[ac], 0, 0, + SME_BI_DIR, 1, + pAdapter->sessionId, + pHddCtx->config->DelayedTriggerFrmInt); + } + } + } + + } + break; + case NL80211_TDLS_DISABLE_LINK: + { + pTdlsPeer = + wlan_hdd_tdls_find_peer(pAdapter, peer, true); + + if (NULL == pTdlsPeer) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: peer matching " MAC_ADDRESS_STR + " not found, ignore NL80211_TDLS_DISABLE_LINK", + __func__, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_delete_tdls_peer_sta(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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Error in TDLS Teardown", + __func__); + return status; + } + } + break; + case NL80211_TDLS_SETUP: + { + status = wlan_hdd_tdls_extctrl_config_peer(pAdapter, + peer, NULL, + pHddCtx->config->fTDLSPrefOffChanNum, 0, 0, 0); + if (0 != status) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: Error in TDLS Setup", __func__); + return status; + } + } + break; + case NL80211_TDLS_DISCOVERY_REQ: + /* We don't support in-driver setup/teardown/discovery */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + "%s: We don't support in-driver setup/teardown/discovery", + __func__); + return -ENOTSUPP; + default: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: unsupported event", __func__); + return -ENOTSUPP; + } + return 0; +} + +/** + * wlan_hdd_cfg80211_tdls_oper() - handle cfg80211 operation on an TDLS peer + * @wiphy: wiphy + * @dev: net device + * @peer: MAC address of the TDLS peer + * @oper: cfg80211 TDLS operation + * + * Return: 0 on success; negative errno otherwise + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) +int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + const uint8_t *peer, + enum nl80211_tdls_operation oper) +#else +int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, + struct net_device *dev, + uint8_t *peer, + enum nl80211_tdls_operation oper) +#endif +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_cfg80211_send_tdls_discover_req() - send out TDLS discovery for + * a TDLS peer + * @wiphy: wiphy + * @dev: net device + * @peer: MAC address of the peer + * + * Return: 0 if success; negative errno otherwise + */ +int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy, + struct net_device *dev, u8 *peer) +{ + hddLog(CDF_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)) + 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 +#endif +} + +#endif /* End of FEATURE_WLAN_TDLS */ + +/** + * wlan_hdd_tdls_find_first_connected_peer() - find the 1st connected tdls peer + * @adapter: Pointer to the HDD adapter + * + * This function searchs for the 1st connected TDLS peer + * + * Return: The first connected TDLS peer if found; NULL otherwise + */ +hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *adapter) +{ + int i; + struct list_head *head; + struct list_head *pos; + hddTdlsPeer_t *curr_peer = NULL; + tdlsCtx_t *hdd_tdls_ctx; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (0 != (wlan_hdd_validate_context(hdd_ctx))) { + hddLog(LOGE, FL("hdd_ctx is not valid")); + return NULL; + } + mutex_lock(&hdd_ctx->tdls_lock); + hdd_tdls_ctx = WLAN_HDD_GET_TDLS_CTX_PTR(adapter); + if (NULL == hdd_tdls_ctx) { + mutex_unlock(&hdd_ctx->tdls_lock); + return NULL; + } + for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) { + head = &hdd_tdls_ctx->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(&hdd_ctx->tdls_lock); + hddLog(LOG1, + FL(MAC_ADDRESS_STR + " eTDLS_LINK_CONNECTED" + ), + MAC_ADDR_ARRAY(curr_peer->peerMac)); + return curr_peer; + } + } + } + mutex_unlock(&hdd_ctx->tdls_lock); + return NULL; +} + +/** + * hdd_set_tdls_offchannel() - set tdls off-channel number + * @adapter: Pointer to the HDD adapter + * @offchanmode: tdls off-channel number + * + * This function sets tdls off-channel number + * + * Return: 0 on success; negative errno otherwise + */ +int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel) +{ + if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + if (offchannel < CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN || + offchannel > CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) { + hddLog(LOGE, FL("Invalid tdls off channel %u"), + offchannel); + return -EINVAL; + } + } else { + hddLog(LOGE, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + hddLog(LOG1, + FL("change tdls off channel from %d to %d"), + hdd_ctx->tdls_off_channel, offchannel); + hdd_ctx->tdls_off_channel = offchannel; + return 0; +} + +/** + * hdd_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset + * @adapter: Pointer to the HDD adapter + * @offchanmode: tdls off-channel offset + * + * This function sets 2nd tdls off-channel offset + * + * Return: 0 on success; negative errno otherwise + */ +int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset) +{ + if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + hdd_ctx->tdls_channel_offset = 0; + + switch (offchanoffset) { + case TDLS_SEC_OFFCHAN_OFFSET_0: + hdd_ctx->tdls_channel_offset = (1 << BW_20_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_40PLUS: + case TDLS_SEC_OFFCHAN_OFFSET_40MINUS: + hdd_ctx->tdls_channel_offset = (1 << BW_40_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_80: + hdd_ctx->tdls_channel_offset = (1 << BW_80_OFFSET_BIT); + break; + case TDLS_SEC_OFFCHAN_OFFSET_160: + hdd_ctx->tdls_channel_offset = (1 << BW_160_OFFSET_BIT); + break; + default: + hddLog(LOGE, + FL( + "Invalid tdls secondary off channel offset %d" + ), + offchanoffset); + return -EINVAL; + } /* end switch */ + } else { + hddLog(LOGE, + FL("Either TDLS or TDLS Off-channel is not enabled")); + return -ENOTSUPP; + } + hddLog(LOG1, + FL("change tdls secondary off channel offset to 0x%x"), + hdd_ctx->tdls_channel_offset); + return 0; +} + +/** + * hdd_set_tdls_offchannelmode() - set tdls off-channel mode + * @adapter: Pointer to the HDD adapter + * @offchanmode: tdls off-channel mode + * + * This function sets tdls off-channel mode + * + * Return: 0 on success; negative errno otherwise + */ +int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) +{ + hddTdlsPeer_t *conn_peer = NULL; + hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + sme_tdls_chan_switch_params chan_switch_params; + + if (offchanmode < ENABLE_CHANSWITCH || + offchanmode > DISABLE_CHANSWITCH) { + hddLog(LOGE, + FL("Invalid tdls off channel mode %d"), + offchanmode); + return -EINVAL; + } + if (eConnectionState_Associated != hdd_sta_ctx->conn_info.connState) { + hddLog(LOGE, + FL( + "tdls off channel mode req in not associated state %d" + ), + offchanmode); + return -EPERM; + } + if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && + (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + conn_peer = wlan_hdd_tdls_find_first_connected_peer(adapter); + if (NULL == conn_peer) { + hddLog(LOGP, + FL("No TDLS Connected Peer")); + return -EPERM; + } + } else { + hddLog(LOGP, + FL("TDLS Connection not supported")); + return -ENOTSUPP; + } + hddLog(LOG1, + FL("TDLS Channel Switch in swmode=%d"), + offchanmode); + + switch (offchanmode) { + case ENABLE_CHANSWITCH: + case DISABLE_CHANSWITCH: + hddLog(LOG1, + FL( + "change tdls off channel mode %d tdls_off_channel %d offchanoffset %d" + ), + offchanmode, hdd_ctx->tdls_off_channel, + hdd_ctx->tdls_channel_offset); + if (hdd_ctx->tdls_off_channel && hdd_ctx->tdls_channel_offset) { + chan_switch_params.vdev_id = adapter->sessionId; + chan_switch_params.tdls_off_channel = + hdd_ctx->tdls_off_channel; + chan_switch_params.tdls_off_ch_bw_offset = + hdd_ctx->tdls_channel_offset; + chan_switch_params.tdls_off_ch_mode = offchanmode; + chan_switch_params.is_responder = + conn_peer->is_responder; + cdf_mem_copy(&chan_switch_params.peer_mac_addr, + &conn_peer->peerMac, + sizeof(tSirMacAddr)); + hddLog(LOG1, + FL("Peer " MAC_ADDRESS_STR + " vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d" + ), + MAC_ADDR_ARRAY(chan_switch_params. + peer_mac_addr), + chan_switch_params.vdev_id, + chan_switch_params.tdls_off_channel, + chan_switch_params.tdls_off_ch_bw_offset, + chan_switch_params.tdls_off_ch_mode, + chan_switch_params.is_responder); + + sme_send_tdls_chan_switch_req( + WLAN_HDD_GET_HAL_CTX(adapter), + &chan_switch_params); + } else { + hddLog(LOGE, + FL( + "TDLS off-channel parameters are not set yet!!!" + )); + return -EINVAL; + } + break; + default: + hddLog(LOGE, + FL( + "Incorrect Parameters mode: %d tdls_off_channel: %d offchanoffset: %d" + ), + offchanmode, hdd_ctx->tdls_off_channel, + hdd_ctx->tdls_channel_offset); + break; + } /* end switch */ + 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->config->enable_tdls_scan = val; + return 0; + } +} diff --git a/core/hdd/src/wlan_hdd_trace.c b/core/hdd/src/wlan_hdd_trace.c new file mode 100644 index 000000000000..ff25fb2bb455 --- /dev/null +++ b/core/hdd/src/wlan_hdd_trace.c @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifdef HDD_TRACE_RECORD + +/** + * DOC: wlan_hdd_trace.c + * + * WLAN Host Device Driver trace implementation + * + */ + +#include "cdf_trace.h" +#include "cdf_types.h" +#include "wlan_hdd_trace.h" +#include "wlan_hdd_main.h" + +/** + * hdd_trace_dump() - Dump an HDD-specific trace record + * @mac: (unused) global MAC handle + * @record: trace record that was previously recorded + * @index: index of the trace record + * + * Return: none + */ +static void +hdd_trace_dump(void *mac, tp_cdf_trace_record record, uint16_t index) +{ + hddLog(LOGE, "%04d %012llu S%d %-14s %-30s(0x%x) ", + index, record->time, record->session, + "HDD Event:", hdd_trace_event_string(record->code), + record->data); +} + +/** + * hdd_trace_init() - HDD trace subsystem initialization + * + * Registers HDD with the debug trace subsystem + * + * Return: none + */ +void hdd_trace_init(void) +{ + cdf_trace_register(CDF_MODULE_ID_HDD, hdd_trace_dump); +} + +#endif /* ifdef HDD_TRACE_RECORD */ diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c new file mode 100644 index 000000000000..3ea2d855eda8 --- /dev/null +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -0,0 +1,1065 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_tx_rx.c + * + * Linux HDD Tx/RX APIs + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "sap_api.h" +#include "wlan_hdd_wmm.h" + +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif +#include + +#include "wlan_hdd_ocb.h" + +#include "wlan_hdd_lro.h" + +#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 */ + +const uint8_t hdd_wmm_ac_to_highest_up[] = { + 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 SME AC. */ +const uint8_t hdd_qdisc_ac_to_tl_ac[] = { + SME_AC_VO, + SME_AC_VI, + SME_AC_BE, + SME_AC_BK, +}; + +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL +/** + * hdd_tx_resume_timer_expired_handler() - TX Q resume timer handler + * @adapter_context: pointer to vdev adapter + * + * If Blocked OS Q is not resumed during timeout period, to prevent + * permanent stall, resume OS Q forcefully. + * + * 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")); + wlan_hdd_netif_queue_control(pAdapter, WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_CONTROL_PATH); + return; +} + +/** + * hdd_tx_resume_cb() - Resume OS TX Q. + * @adapter_context: pointer to vdev apdapter + * @tx_resume: TX Q resume trigger + * + * Q was stopped due to WLAN TX path low resource condition + * + * Return: None + */ +void hdd_tx_resume_cb(void *adapter_context, bool 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 (true == tx_resume) { + if (CDF_TIMER_STATE_STOPPED != + cdf_mc_timer_get_current_state(&pAdapter-> + tx_flow_control_timer)) { + cdf_mc_timer_stop(&pAdapter->tx_flow_control_timer); + } + if (cdf_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")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_WAKE_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + } +#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) + else if (false == tx_resume) { /* Pause TX */ + hddLog(LOG1, FL("Disabling queues")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_STOP_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + if (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&pAdapter-> + tx_flow_control_timer)) { + CDF_STATUS status; + status = + cdf_mc_timer_start(&pAdapter->tx_flow_control_timer, + WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + if (!CDF_IS_STATUS_SUCCESS(status)) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; +} + +/** + * hdd_register_tx_flow_control() - Register TX Flow control + * @adapter: adapter handle + * @timer_callback: timer callback + * @flow_control_fp: txrx flow control + * + * Return: none + */ +void hdd_register_tx_flow_control(hdd_adapter_t *adapter, + cdf_mc_timer_callback_t timer_callback, + ol_txrx_tx_flow_control_fp flow_control_fp) +{ + if (adapter->tx_flow_timer_initialized == false) { + cdf_mc_timer_init(&adapter->tx_flow_control_timer, + CDF_TIMER_TYPE_SW, + timer_callback, + adapter); + adapter->tx_flow_timer_initialized = true; + } + ol_txrx_register_tx_flow_control(adapter->sessionId, + flow_control_fp, + adapter); + +} + +/** + * hdd_deregister_tx_flow_control() - Deregister TX Flow control + * @adapter: adapter handle + * + * Return: none + */ +void hdd_deregister_tx_flow_control(hdd_adapter_t *adapter) +{ + ol_txrx_deregister_tx_flow_control_cb(adapter->sessionId); + if (adapter->tx_flow_timer_initialized == true) { + cdf_mc_timer_stop(&adapter->tx_flow_control_timer); + cdf_mc_timer_destroy(&adapter->tx_flow_control_timer); + adapter->tx_flow_timer_initialized = false; + } +} + +/** + * hdd_get_tx_resource() - check tx resources and take action + * @adapter: adapter handle + * @STAId: station id + * @timer_value: timer value + * + * Return: none + */ +void hdd_get_tx_resource(hdd_adapter_t *adapter, + uint8_t STAId, uint16_t timer_value) +{ + if (false == + ol_txrx_get_tx_resource(STAId, + adapter->tx_flow_low_watermark, + adapter->tx_flow_high_watermark_offset)) { + hdd_info("Disabling queues lwm %d hwm offset %d", + adapter->tx_flow_low_watermark, + adapter->tx_flow_high_watermark_offset); + wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE, + WLAN_DATA_FLOW_CONTROL); + if ((adapter->tx_flow_timer_initialized == true) && + (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&adapter-> + tx_flow_control_timer))) { + cdf_mc_timer_start(&adapter->tx_flow_control_timer, + timer_value); + adapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; + adapter->hdd_stats.hddTxRxStats.txflow_pause_cnt++; + adapter->hdd_stats.hddTxRxStats.is_txflow_paused = true; + } + } +} + +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * 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) { + hdd_err(FL("skb is NULL")); + return false; + } + + ether_type = (uint16_t)(*(uint16_t *) + (skb->data + HDD_ETHERTYPE_802_1_X_FRAME_OFFSET)); + + if (ether_type == CDF_SWAP_U16(HDD_ETHERTYPE_802_1_X)) + return true; + + return false; +} + +/** + * wlan_hdd_is_eapol_or_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) { + hdd_err(FL("skb is NULL")); + return false; + } + + ether_type = (uint16_t)(*(uint16_t *) + (skb->data + HDD_ETHERTYPE_802_1_X_FRAME_OFFSET)); + + if (ether_type == CDF_SWAP_U16(HDD_ETHERTYPE_802_1_X) || + ether_type == CDF_SWAP_U16(HDD_ETHERTYPE_WAI)) + return true; + + /* No error msg handled since this will happen often */ + return false; +} + +/** + * hdd_hard_start_xmit() - Transmit a frame + * @skb: pointer to OS packet (sk_buff) + * @dev: pointer to network device + * + * Function registered with the Linux OS for transmitting + * packets. This version of the function directly passes + * the packet to Transport Layer. + * + * Return: Always returns NETDEV_TX_OK + */ +int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + CDF_STATUS status; + sme_ac_enum_type ac; + sme_QosWmmUpType up; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + bool granted; + uint8_t STAId = WLAN_MAX_STA_COUNT; + hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station; + uint8_t proto_type = 0; +#ifdef QCA_PKT_PROTO_TRACE + hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter); +#endif /* QCA_PKT_PROTO_TRACE */ + +#ifdef QCA_WIFI_FTM + if (hdd_get_conparam() == CDF_FTM_MODE) { + kfree_skb(skb); + return NETDEV_TX_OK; + } +#endif + + ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; + + if (WLAN_HDD_IBSS == pAdapter->device_mode) { + struct cdf_mac_addr *pDestMacAddress = + (struct cdf_mac_addr *) skb->data; + + if (CDF_STATUS_SUCCESS != + hdd_ibss_get_sta_id(&pAdapter->sessionCtx.station, + pDestMacAddress, &STAId)) + STAId = HDD_WLAN_INVALID_STA_ID; + + if ((STAId == HDD_WLAN_INVALID_STA_ID) && + (cdf_is_macaddr_broadcast(pDestMacAddress) || + cdf_is_macaddr_group(pDestMacAddress))) { + STAId = IBSS_BROADCAST_STAID; + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, + CDF_TRACE_LEVEL_INFO_LOW, "%s: BC/MC packet", + __func__); + } else if (STAId == HDD_WLAN_INVALID_STA_ID) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_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 { + STAId = pHddStaCtx->conn_info.staId[0]; + } + + + hdd_get_tx_resource(pAdapter, STAId, + WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); + + /* Get TL AC corresponding to Qdisc queue index/AC. */ + ac = hdd_qdisc_ac_to_tl_ac[skb->queue_mapping]; + + if (!(NBUF_OWNER_ID(skb) == IPA_NBUF_OWNER_ID)) { + /* Check if the buffer has enough header room */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + goto drop_pkt; + + if (skb_headroom(skb) < dev->hard_header_len) { + struct sk_buff *tmp; + tmp = skb; + skb = skb_realloc_headroom(tmp, dev->hard_header_len); + dev_kfree_skb(tmp); + if (!skb) + goto drop_pkt; + } + } + + /* 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 + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_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 == false) && + wlan_hdd_is_eapol_or_wai(skb))) { + granted = true; + } else { + status = hdd_wmm_acquire_access(pAdapter, ac, &granted); + pAdapter->psbChanged |= (1 << ac); + } + + if (!granted) { + bool isDefaultAc = false; + /* ADDTS request for this AC is sent, for now + * send this packet through next avaiable lower + * Access category until ADDTS negotiation completes. + */ + while (!likely + (pAdapter->hddWmmStatus.wmmAcStatus[ac]. + wmmAcAccessAllowed)) { + switch (ac) { + case SME_AC_VO: + ac = SME_AC_VI; + up = SME_QOS_WMM_UP_VI; + break; + case SME_AC_VI: + ac = SME_AC_BE; + up = SME_QOS_WMM_UP_BE; + break; + case SME_AC_BE: + ac = SME_AC_BK; + up = SME_QOS_WMM_UP_BK; + break; + default: + ac = SME_AC_BK; + up = SME_QOS_WMM_UP_BK; + isDefaultAc = true; + break; + } + if (isDefaultAc) + break; + } + skb->priority = up; + skb->queue_mapping = hdd_linux_up_to_ac_map[up]; + } + + wlan_hdd_log_eapol(skb, + WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) || + (hddCtxt->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) { + proto_type = cds_pkt_get_proto_type(skb, + hddCtxt->config-> + gEnableDebugLog, 0); + if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) { + cds_pkt_trace_buf_update("ST:T:EPL"); + } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) { + cds_pkt_trace_buf_update("ST:T:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + + pAdapter->stats.tx_bytes += skb->len; + ++pAdapter->stats.tx_packets; + + /* Zero out skb's context buffer for the driver to use */ + cdf_mem_set(skb->cb, sizeof(skb->cb), 0); + NBUF_SET_PACKET_TRACK(skb, NBUF_TX_PKT_DATA_TRACK); + NBUF_UPDATE_TX_PKT_COUNT(skb, NBUF_TX_PKT_HDD); + + cdf_dp_trace_set_track(skb); + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_PTR_RECORD, + (uint8_t *)skb->data, sizeof(skb->data))); + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_RECORD, + (uint8_t *)skb->data, cdf_nbuf_len(skb))); + if (cdf_nbuf_len(skb) > CDF_DP_TRACE_RECORD_SIZE) + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_HDD_PACKET_RECORD, + (uint8_t *)&skb->data[CDF_DP_TRACE_RECORD_SIZE], + (cdf_nbuf_len(skb)-CDF_DP_TRACE_RECORD_SIZE))); + + if (ol_tx_send_data_frame(STAId, (cdf_nbuf_t) skb, + proto_type) != NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_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: + + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_DROP_PACKET_RECORD, + (uint8_t *)skb->data, cdf_nbuf_len(skb))); + if (cdf_nbuf_len(skb) > CDF_DP_TRACE_RECORD_SIZE) + DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_DROP_PACKET_RECORD, + (uint8_t *)&skb->data[CDF_DP_TRACE_RECORD_SIZE], + (cdf_nbuf_len(skb)-CDF_DP_TRACE_RECORD_SIZE))); + + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac]; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +/** + * hdd_ibss_get_sta_id() - Get the StationID using the Peer Mac address + * @pHddStaCtx: pointer to HDD Station Context + * @pMacAddress: pointer to Peer Mac address + * @staID: pointer to returned Station Index + * + * Return: CDF_STATUS_SUCCESS/CDF_STATUS_E_FAILURE + */ + +CDF_STATUS hdd_ibss_get_sta_id(hdd_station_ctx_t *pHddStaCtx, + struct cdf_mac_addr *pMacAddress, uint8_t *staId) +{ + uint8_t idx; + + for (idx = 0; idx < MAX_IBSS_PEERS; idx++) { + if (cdf_mem_compare(&pHddStaCtx->conn_info.peerMacAddress[idx], + pMacAddress, CDF_MAC_ADDR_SIZE)) { + *staId = pHddStaCtx->conn_info.staId[idx]; + return CDF_STATUS_SUCCESS; + } + } + + return CDF_STATUS_E_FAILURE; +} + +/** + * __hdd_tx_timeout() - TX timeout handler + * @dev: pointer to network device + * + * This function is registered as a netdev ndo_tx_timeout method, and + * is invoked by the kernel if the driver takes too long to transmit a + * frame. + * + * Return: None + */ +static void __hdd_tx_timeout(struct net_device *dev) +{ + struct netdev_queue *txq; + int i = 0; + + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Transmission timeout occurred jiffies %lu trans_start %lu", + __func__, jiffies, dev->trans_start); + DPTRACE(cdf_dp_trace(NULL, CDF_DP_TRACE_HDD_TX_TIMEOUT, + NULL, 0)); + + /* 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 + */ + + for (i = 0; i < NUM_TX_QUEUES; i++) { + txq = netdev_get_tx_queue(dev, i); + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_INFO, + "Queue%d status: %d txq->trans_start %lu", + i, netif_tx_queue_stopped(txq), txq->trans_start); + } + + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_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) +{ + cds_ssr_protect(__func__); + __hdd_tx_timeout(dev); + cds_ssr_unprotect(__func__); +} + +/** + * @hdd_init_tx_rx() - Initialize Tx/RX module + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_init_tx_rx(hdd_adapter_t *pAdapter) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + return status; +} + +/** + * @hdd_deinit_tx_rx() - Deinitialize Tx/RX module + * @pAdapter: pointer to adapter context + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_ERROR, + FL("pAdapter is NULL")); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + return status; +} + +/** + * hdd_rx_packet_cbk() - Receive packet handler + * @cds_context: pointer to CDS context + * @rxBuf: pointer to rx cdf_nbuf + * @staId: Station Id + * + * Receive callback registered with TL. TL will call this to notify + * the HDD when one or more packets were received for a registered + * STA. + * + * Return: CDF_STATUS_E_FAILURE if any errors encountered, + * CDF_STATUS_SUCCESS otherwise + */ +CDF_STATUS hdd_rx_packet_cbk(void *cds_context, cdf_nbuf_t rxBuf, uint8_t staId) +{ + hdd_adapter_t *pAdapter = NULL; + hdd_context_t *pHddCtx = NULL; + int rxstat; + struct sk_buff *skb = NULL; +#ifdef QCA_PKT_PROTO_TRACE + uint8_t proto_type; +#endif /* QCA_PKT_PROTO_TRACE */ + hdd_station_ctx_t *pHddStaCtx = NULL; + unsigned int cpu_index; + + /* Sanity check on inputs */ + if ((NULL == cds_context) || (NULL == rxBuf)) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return CDF_STATUS_E_FAILURE; + } + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL == pHddCtx) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return CDF_STATUS_E_FAILURE; + } + + pAdapter = pHddCtx->sta_to_adapter[staId]; + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { + hddLog(LOGE, + FL("invalid adapter %p or adapter has invalid magic"), + pAdapter); + return CDF_STATUS_E_FAILURE; + } + cpu_index = wlan_hdd_get_cpu(); + + skb = (struct sk_buff *)rxBuf; + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_FATAL, + "Magic cookie(%x) for adapter sanity verification is invalid", + pAdapter->magic); + return CDF_STATUS_E_FAILURE; + } + + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if ((pHddStaCtx->conn_info.proxyARPService) && + cfg80211_is_gratuitous_arp_unsolicited_na(skb)) { + ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index]; + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_INFO, + "%s: Dropping HS 2.0 Gratuitous ARP or Unsolicited NA", + __func__); + /* Remove SKB from internal tracking table before submitting + * it to stack + */ + cdf_nbuf_free(skb); + return CDF_STATUS_SUCCESS; + } + + wlan_hdd_log_eapol(skb, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED); + +#ifdef QCA_PKT_PROTO_TRACE + if ((pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) || + (pHddCtx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) { + proto_type = cds_pkt_get_proto_type(skb, + pHddCtx->config-> + gEnableDebugLog, 0); + if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) { + cds_pkt_trace_buf_update("ST:R:EPL"); + } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) { + cds_pkt_trace_buf_update("ST:R:DHC"); + } + } +#endif /* QCA_PKT_PROTO_TRACE */ + + skb->dev = pAdapter->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + ++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; + ++pAdapter->stats.rx_packets; + pAdapter->stats.rx_bytes += skb->len; +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK + cdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock, + HDD_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_HOLD_RX); +#endif + + /* Remove SKB from internal tracking table before submitting + * it to stack + */ + cdf_net_buf_debug_release_skb(rxBuf); + + if (HDD_LRO_NO_RX == + hdd_lro_rx(pHddCtx, pAdapter, skb)) { + if (hdd_napi_enabled(HDD_NAPI_ANY)) + rxstat = netif_receive_skb(skb); + else + 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]; + + } else { + ++pAdapter->hdd_stats.hddTxRxStats. + rxDelivered[cpu_index]; + } + + pAdapter->dev->last_rx = jiffies; + + return CDF_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 and return the EAPOL parameters if + * the packet is an eapol packet. + * + * Return: -EINVAL if the packet is not an EAPOL packet and 0 on success + * + */ +static int wlan_hdd_get_eapol_params(struct sk_buff *skb, + struct host_event_wlan_eapol *eapol_params, + uint8_t event_type) +{ + bool ret; + uint8_t packet_type; + + ret = wlan_hdd_is_eapol(skb); + + if (!ret) + return -EINVAL; + + 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 */ + + cdf_mem_copy(eapol_params->dest_addr, + (skb->data + HDD_EAPOL_DEST_MAC_OFFSET), + sizeof(eapol_params->dest_addr)); + cdf_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 host_event_wlan_eapol eapol_params) +{ + WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_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; + cdf_mem_copy(wlan_diag_event.dest_addr, + eapol_params.dest_addr, + sizeof(wlan_diag_event.dest_addr)); + cdf_mem_copy(wlan_diag_event.src_addr, + eapol_params.src_addr, + sizeof(wlan_diag_event.src_addr)); + + WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL); +} + +/** + * wlan_hdd_log_eapol() - Logs the EAPOL parameters of a packet + * @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 and log + * them to user space, if the packet is EAPOL + * + * Return: None + * + */ +void wlan_hdd_log_eapol(struct sk_buff *skb, + uint8_t event_type) +{ + int ret; + struct host_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 */ + +/** + * hdd_reason_type_to_string() - return string conversion of reason type + * @reason: reason type + * + * This utility function helps log string conversion of reason type. + * + * Return: string conversion of device mode, if match found; + * "Unknown" otherwise. + */ +const char *hdd_reason_type_to_string(enum netif_reason_type reason) +{ + switch (reason) { + CASE_RETURN_STRING(WLAN_CONTROL_PATH); + CASE_RETURN_STRING(WLAN_DATA_FLOW_CONTROL); + CASE_RETURN_STRING(WLAN_FW_PAUSE); + CASE_RETURN_STRING(WLAN_TX_ABORT); + CASE_RETURN_STRING(WLAN_VDEV_STOP); + CASE_RETURN_STRING(WLAN_PEER_UNAUTHORISED); + CASE_RETURN_STRING(WLAN_THERMAL_MITIGATION); + default: + return "Unknown"; + } +} + +/** + * hdd_action_type_to_string() - return string conversion of action type + * @action: action type + * + * This utility function helps log string conversion of action_type. + * + * Return: string conversion of device mode, if match found; + * "Unknown" otherwise. + */ +const char *hdd_action_type_to_string(enum netif_action_type action) +{ + + switch (action) { + CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE); + CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE); + CASE_RETURN_STRING(WLAN_WAKE_ALL_NETIF_QUEUE); + CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER); + CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE_N_CARRIER); + CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE); + CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE_N_CARRIER); + CASE_RETURN_STRING(WLAN_NETIF_CARRIER_ON); + CASE_RETURN_STRING(WLAN_NETIF_CARRIER_OFF); + default: + return "Unknown"; + } +} + +/** + * wlan_hdd_update_queue_oper_stats - update queue operation statistics + * @adapter: adapter handle + * @action: action type + * @reason: reason type + */ +static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter, + enum netif_action_type action, enum netif_reason_type reason) +{ + switch (action) { + case WLAN_STOP_ALL_NETIF_QUEUE: + case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER: + case WLAN_NETIF_TX_DISABLE: + case WLAN_NETIF_TX_DISABLE_N_CARRIER: + adapter->queue_oper_stats[reason].pause_count++; + break; + case WLAN_START_ALL_NETIF_QUEUE: + case WLAN_WAKE_ALL_NETIF_QUEUE: + case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER: + adapter->queue_oper_stats[reason].unpause_count++; + break; + default: + break; + } + + return; +} + +/** + * wlan_hdd_netif_queue_control() - Use for netif_queue related actions + * @adapter: adapter handle + * @action: action type + * @reason: reason type + * + * This is single function which is used for netif_queue related + * actions like start/stop of network queues and on/off carrier + * option. + * + * Return: None + */ +void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter, + enum netif_action_type action, enum netif_reason_type reason) +{ + + if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) || + (!adapter->dev)) { + hdd_err("adapter is invalid"); + return; + } + + switch (action) { + + case WLAN_NETIF_CARRIER_ON: + netif_carrier_on(adapter->dev); + break; + + case WLAN_NETIF_CARRIER_OFF: + netif_carrier_off(adapter->dev); + break; + + case WLAN_STOP_ALL_NETIF_QUEUE: + spin_lock_bh(&adapter->pause_map_lock); + if (!adapter->pause_map) + netif_tx_stop_all_queues(adapter->dev); + adapter->pause_map |= (1 << reason); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_START_ALL_NETIF_QUEUE: + spin_lock_bh(&adapter->pause_map_lock); + adapter->pause_map &= ~(1 << reason); + if (!adapter->pause_map) + netif_tx_start_all_queues(adapter->dev); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_WAKE_ALL_NETIF_QUEUE: + spin_lock_bh(&adapter->pause_map_lock); + adapter->pause_map &= ~(1 << reason); + if (!adapter->pause_map) + netif_tx_wake_all_queues(adapter->dev); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER: + spin_lock_bh(&adapter->pause_map_lock); + if (!adapter->pause_map) + netif_tx_stop_all_queues(adapter->dev); + adapter->pause_map |= (1 << reason); + netif_carrier_off(adapter->dev); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER: + spin_lock_bh(&adapter->pause_map_lock); + netif_carrier_on(adapter->dev); + adapter->pause_map &= ~(1 << reason); + if (!adapter->pause_map) + netif_tx_start_all_queues(adapter->dev); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_NETIF_TX_DISABLE: + spin_lock_bh(&adapter->pause_map_lock); + if (!adapter->pause_map) + netif_tx_disable(adapter->dev); + adapter->pause_map |= (1 << reason); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + case WLAN_NETIF_TX_DISABLE_N_CARRIER: + spin_lock_bh(&adapter->pause_map_lock); + if (!adapter->pause_map) + netif_tx_disable(adapter->dev); + adapter->pause_map |= (1 << reason); + netif_carrier_off(adapter->dev); + spin_unlock_bh(&adapter->pause_map_lock); + break; + + default: + hdd_err("unsupported action %d", action); + } + + spin_lock_bh(&adapter->pause_map_lock); + if (adapter->pause_map & (1 << WLAN_PEER_UNAUTHORISED)) + wlan_hdd_process_peer_unauthorised_pause(adapter); + spin_unlock_bh(&adapter->pause_map_lock); + + + wlan_hdd_update_queue_oper_stats(adapter, action, reason); + + adapter->queue_oper_history[adapter->history_index].time = + cdf_system_ticks(); + adapter->queue_oper_history[adapter->history_index].netif_action = + action; + adapter->queue_oper_history[adapter->history_index].netif_reason = + reason; + adapter->queue_oper_history[adapter->history_index].pause_map = + adapter->pause_map; + if (++adapter->history_index == WLAN_HDD_MAX_HISTORY_ENTRY) + adapter->history_index = 0; + + return; +} + diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c new file mode 100644 index 000000000000..91076fe511b3 --- /dev/null +++ b/core/hdd/src/wlan_hdd_wext.c @@ -0,0 +1,10708 @@ +/* + * 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: wlan_hdd_wext.c + * + * Linux Wireless Extensions Implementation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sir_params.h" +#include "csr_api.h" +#include "csr_inside_api.h" +#if defined WLAN_FEATURE_VOWIFI +#include "sme_rrm_internal.h" +#endif +#include +#include "dot11f.h" +#include +#include +#include +#include "utils_api.h" +#include "wlan_hdd_p2p.h" +#ifdef FEATURE_WLAN_TDLS +#include "wlan_hdd_tdls.h" +#endif + +#include "cds_ieee80211_common.h" +#include "ol_if_athvar.h" +#include "dbglog_host.h" +#include "wma.h" + +#include "wlan_hdd_power.h" +#include "qwlan_version.h" +#include "wlan_hdd_host_offload.h" + +#include +#include + +#include "wlan_hdd_misc.h" + +#include "qc_sap_ioctl.h" +#include "sme_api.h" +#include "wma_types.h" +#include "cdf_trace.h" +#include "wlan_hdd_assoc.h" +#include "wlan_hdd_ioctl.h" +#include "wlan_hdd_scan.h" +#include "sme_power_save_api.h" +#include "cds_concurrency.h" +#include "wlan_hdd_conc_ut.h" +#include "wlan_hdd_ocb.h" +#include "wlan_hdd_napi.h" + +#ifdef QCA_PKT_PROTO_TRACE +#include "cds_packet.h" +#endif /* QCA_PKT_PROTO_TRACE */ + +#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])) + +/* 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_SCAN_DISABLE 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 +#define WE_SET_POWER_GATING 44 +/* Private ioctl for packet powe 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 +#define WE_SET_SAP_AUTO_CHANNEL_SELECTION 54 +#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 +#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 + +/* 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 +#define WE_GET_POWER_GATING 31 +#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_TEMPERATURE 56 + +/* 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 +#define WE_SET_DP_TRACE 2 +#define WE_SET_SAP_CHANNELS 3 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 5) +#define WE_WLAN_VERSION 1 +#define WE_GET_STATS 2 +#define WE_GET_CFG 3 +#define WE_GET_WMM_STATUS 4 +#define WE_GET_CHANNEL_LIST 5 +#ifdef WLAN_FEATURE_11AC +#define WE_GET_RSSI 6 +#endif +#ifdef FEATURE_WLAN_TDLS +#define WE_GET_TDLS_PEERS 8 +#endif +#ifdef WLAN_FEATURE_11W +#define WE_GET_11W_INFO 9 +#endif +#define WE_GET_STATES 10 + +#define WE_GET_PHYMODE 12 +#ifdef FEATURE_OEM_DATA_SUPPORT +#define WE_GET_OEM_DATA_CAP 13 +#endif +#define WE_GET_SNR 14 + +/* Private ioctls and their sub-ioctls */ +#define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) +#define WE_SET_REASSOC_TRIGGER 8 + +#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_P2P_NOA_CMD 2 + +/* subcommands 3 and 4 are unused */ + +#ifdef FEATURE_WLAN_TDLS +#define WE_TDLS_CONFIG_PARAMS 5 +#endif + +#define WE_UNIT_TEST_CMD 7 + +#define WE_MTRACE_DUMP_CMD 8 +#define WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD 9 + + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +#define WE_LED_FLASHING_PARAM 10 +#endif + +#define WE_POLICY_MANAGER_CLIST_CMD 11 +#define WE_POLICY_MANAGER_DLIST_CMD 12 +#define WE_POLICY_MANAGER_DBS_CMD 13 +#define WE_POLICY_MANAGER_PCL_CMD 14 +#define WE_POLICY_MANAGER_CINFO_CMD 15 +#define WE_POLICY_MANAGER_ULIST_CMD 16 +#define WE_POLICY_MANAGER_QUERY_ACTION_CMD 17 +#define WE_POLICY_MANAGER_QUERY_ALLOW_CMD 18 +#define WE_POLICY_MANAGER_SCENARIO_CMD 19 +#define WE_POLICY_SET_HW_MODE_CMD 20 + +#define WE_SET_DUAL_MAC_SCAN_CONFIG 21 +#define WE_SET_DUAL_MAC_FW_MODE_CONFIG 22 + +#ifdef FEATURE_WLAN_TDLS +#undef MAX_VAR_ARGS +#define MAX_VAR_ARGS 11 +#else +#undef MAX_VAR_ARGS +#define MAX_VAR_ARGS 9 +#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 + 10) is currently unused */ +/* (SIOCIWFIRSTPRIV + 12) is currently unused */ +/* (SIOCIWFIRSTPRIV + 14) is currently unused */ +/* (SIOCIWFIRSTPRIV + 15) is currently unused */ +/* (SIOCIWFIRSTPRIV + 16) is currently unused */ +/* (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) + +/* (SIOCIWFIRSTPRIV + 26) is currently unused */ +/* (SIOCIWFIRSTPRIV + 27) is currently unused */ + +/* 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 WE_DUMP_DP_TRACE_LEVEL 3 +#define DUMP_DP_TRACE 0 + +/* (SIOCIWFIRSTPRIV + 29) is currently unused */ + +/* 802.11p IOCTL */ +#define WLAN_SET_DOT11P_CHANNEL_SCHED (SIOCIWFIRSTPRIV + 30) + +#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) + +#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(CDF_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 + +/** + * mem_alloc_copy_from_user_helper - copy from user helper + * @wrqu_data: wireless extensions request data + * @len: length of @wrqu_data + * + * Helper function to allocate buffer and copy user data. + * + * Return: On success return a pointer to a kernel buffer containing a + * copy of the userspace data (with an additional NUL character + * appended for safety). On failure return %NULL. + */ +void *mem_alloc_copy_from_user_helper(const __user 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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Invalid length"); + return NULL; + } + + ptr = kmalloc(len + 1, GFP_KERNEL); + if (NULL == ptr) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "unable to allocate memory"); + return NULL; + } + + if (copy_from_user(ptr, wrqu_data, len)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + kfree(ptr); + return NULL; + } + ptr[len] = '\0'; + return ptr; +} + +/** + * hdd_priv_get_data() - Get pointer to ioctl private data + * @p_priv_data: pointer to iw_point struct to be filled + * @wrqu: Pointer to IOCTL Data received from userspace + * + * Helper function to get compatible struct iw_point passed to ioctl + * + * 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; +} + + +/** + * hdd_wlan_get_stats() - Get txrx stats in SAP mode + * @pAdapter: Pointer to the hdd adapter. + * @length: Size of the data copied + * @buffer: Pointer to char buffer. + * @buf_len: Length of the char buffer. + * + * This function called when the "iwpriv wlan0 get_stats" command is given. + * It used to collect the txrx stats when the device is configured in SAP mode. + * + * Return - none + */ +void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, + char *buffer, uint16_t buf_len) +{ + hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats; + uint32_t len = 0; + uint32_t total_rx_pkt = 0, total_rx_dropped = 0; + uint32_t total_rx_delv = 0, total_rx_refused = 0; + int i = 0; + + for (; i < NUM_CPUS; i++) { + total_rx_pkt += pStats->rxPackets[i]; + total_rx_dropped += pStats->rxDropped[i]; + total_rx_delv += pStats->rxDelivered[i]; + total_rx_refused += pStats->rxRefused[i]; + } + + len = scnprintf(buffer, buf_len, + "\nTransmit" + "\ncalled %u, dropped %u," + "\n dropped BK %u, BE %u, VI %u, VO %u" + "\n classified BK %u, BE %u, VI %u, VO %u" + "\ncompleted %u," + "\n\nReceive Total" + "\n packets %u, dropped %u, delivered %u, refused %u" + "\n", + pStats->txXmitCalled, + pStats->txXmitDropped, + + pStats->txXmitDroppedAC[SME_AC_BK], + pStats->txXmitDroppedAC[SME_AC_BE], + pStats->txXmitDroppedAC[SME_AC_VI], + pStats->txXmitDroppedAC[SME_AC_VO], + + pStats->txXmitClassifiedAC[SME_AC_BK], + pStats->txXmitClassifiedAC[SME_AC_BE], + pStats->txXmitClassifiedAC[SME_AC_VI], + pStats->txXmitClassifiedAC[SME_AC_VO], + + pStats->txCompleted, + total_rx_pkt, total_rx_dropped, total_rx_delv, total_rx_refused + ); + + for (i = 0; i < NUM_CPUS; i++) { + len += scnprintf(buffer + len, buf_len - len, + "\nReceive CPU: %d" + "\n packets %u, dropped %u, delivered %u, refused %u", + i, pStats->rxPackets[i], pStats->rxDropped[i], + pStats->rxDelivered[i], pStats->rxRefused[i]); + } + + len += scnprintf(buffer + len, buf_len - len, + "\n\nTX_FLOW" + "\nCurrent status: %s" + "\ntx-flow timer start count %u" + "\npause count %u, unpause count %u", + (pStats->is_txflow_paused == true ? "PAUSED" : "UNPAUSED"), + pStats->txflow_timer_cnt, + pStats->txflow_pause_cnt, + pStats->txflow_unpause_cnt); + + len += ol_txrx_stats(pAdapter->sessionId, + &buffer[len], (buf_len - len)); + + len += hdd_napi_stats(buffer + len, buf_len - len, + NULL, hdd_napi_get_all()); + + *length = len + 1; +} + +/** + * hdd_wlan_dump_stats() - display dump Stats + * @adapter: adapter handle + * @value: value from user + * + * Return: none + */ +void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + switch (value) { + + case WLAN_TXRX_HIST_STATS: + wlan_hdd_display_tx_rx_histogram(hdd_ctx); + break; + case WLAN_HDD_NETIF_OPER_HISTORY: + wlan_hdd_display_netif_queue_history(hdd_ctx); + break; + default: + ol_txrx_display_stats(value); + break; + } +} + +/** + * hdd_wlan_get_version() - Get driver version information + * @pAdapter: Pointer to the adapter. + * @wrqu: Pointer to IOCTL REQUEST Data. + * @extra: Pointer to destination buffer + * + * This function is used to get Wlan Driver, Firmware, & Hardware + * Version information. If @wrqu and @extra are specified, then the + * version string is returned. Otherwise it is simply printed to the + * kernel log. + * + * 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; + uint32_t MSPId = 0, mSPId = 0, SIId = 0, CRMId = 0; + + hdd_context_t *pHddContext; + + pHddContext = WLAN_HDD_GET_CTX(pAdapter); + if (!pHddContext) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + pHWversion = pHddContext->target_hw_name; + + if (wrqu && extra) { + 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; +} + +/** + * hdd_wlan_get_rts_threshold() - Get RTS threshold + * @pAdapter: adapter upon which the request was received + * @wrqu: pointer to the ioctl request + * + * This function retrieves the current RTS threshold value and stores + * it in the ioctl request structure + * + * Return: 0 if valid data was returned, non-zero on error + */ +int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint32_t threshold = 0; + hdd_context_t *hdd_ctx; + int ret = 0; + + ENTER(); + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 (CDF_STATUS_SUCCESS != + sme_cfg_get_int(hHal, WNI_CFG_RTS_THRESHOLD, &threshold)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + FL + ("failed to get ini parameter, WNI_CFG_RTS_THRESHOLD")); + return -EIO; + } + wrqu->rts.value = threshold; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + ("Rts-Threshold=%d!!"), wrqu->rts.value); + + EXIT(); + + return 0; +} + +/** + * hdd_wlan_get_frag_threshold() - Get fragmentation threshold + * @pAdapter: adapter upon which the request was received + * @wrqu: pointer to the ioctl request + * + * This function retrieves the current fragmentation threshold value + * and stores it in the ioctl request structure + * + * Return: 0 if valid data was returned, non-zero on error + */ +int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, + union iwreq_data *wrqu) +{ + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint32_t threshold = 0, status = 0; + hdd_context_t *hdd_ctx; + + ENTER(); + + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Adapter is NULL", __func__); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return status; + + if (sme_cfg_get_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold) + != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + FL + ("failed to get ini parameter, WNI_CFG_FRAGMENTATION_THRESHOLD")); + return -EIO; + } + wrqu->frag.value = threshold; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + ("Frag-Threshold=%d!!"), wrqu->frag.value); + + EXIT(); + + return 0; +} + +/** + * hdd_wlan_get_freq() - Convert channel to frequency + * @channel: channel to be converted + * @pfreq: where to store the frequency + * + * Return: 1 on success, otherwise a negative errno + */ +int hdd_wlan_get_freq(uint32_t channel, uint32_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; + } + } + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + ("Invalid channel no=%d!!"), channel); + return -EINVAL; +} + +/** + * hdd_is_auth_type_rsn() - RSN authentication type check + * @authType: authentication type to be checked + * + * Return: true if @authType is an RSN authentication type, + * false if it is not + */ +static bool hdd_is_auth_type_rsn(eCsrAuthType authType) +{ + bool rsnType = false; + /* is the authType supported? */ + switch (authType) { + case eCSR_AUTH_TYPE_NONE: /* never used */ + rsnType = false; + break; + /* MAC layer authentication types */ + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + rsnType = false; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + rsnType = false; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + rsnType = false; + break; + + /* Upper layer authentication types */ + case eCSR_AUTH_TYPE_WPA: + rsnType = true; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + rsnType = true; + break; + case eCSR_AUTH_TYPE_WPA_NONE: + rsnType = true; + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: +#endif + case eCSR_AUTH_TYPE_RSN: + rsnType = 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 = true; + break; + /* case eCSR_AUTH_TYPE_FAILED: */ + case eCSR_AUTH_TYPE_UNKNOWN: + rsnType = false; + break; + default: + hddLog(LOGE, FL("unknown authType %d, treat as open"), + authType); + rsnType = false; + break; + } + hddLog(LOG1, FL("called with authType: %d, returned: %d"), + authType, rsnType); + return rsnType; +} + +/** + * hdd_get_rssi_cb() - "Get RSSI" callback function + * @rssi: Current RSSI of the station + * @staId: ID of the station + * @pContext: opaque context originally passed to SME. HDD always passes + * a &struct statsContext + * + * Return: None + */ +static void hdd_get_rssi_cb(int8_t rssi, uint32_t 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(CDF_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(CDF_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; + + /* notify the caller */ + complete(&pStatsContext->completion); + + /* serialization is complete */ + spin_unlock(&hdd_context_lock); +} + +/** + * hdd_get_snr_cb() - "Get SNR" callback function + * @snr: Current SNR of the station + * @staId: ID of the station + * @pContext: opaque context originally passed to SME. HDD always passes + * a &struct statsContext + * + * Return: None + */ +static void hdd_get_snr_cb(int8_t snr, uint32_t 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(CDF_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(CDF_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); +} + +/** + * wlan_hdd_get_rssi() - Get the current RSSI + * @pAdapter: adapter upon which the measurement is requested + * @rssi_value: pointer to where the RSSI should be returned + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, int8_t *rssi_value) +{ + struct statsContext context; + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + CDF_STATUS hstatus; + unsigned long rc; + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_WARN, + "%s: Invalid context, pAdapter", __func__); + return CDF_STATUS_E_FAULT; + } + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s:LOGP in Progress. Ignore!!!", __func__); + /* return a cached value */ + *rssi_value = pAdapter->rssi; + return CDF_STATUS_SUCCESS; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + hdd_err("Not associated!, return last connected AP rssi!"); + *rssi_value = pAdapter->rssi; + return CDF_STATUS_SUCCESS; + } + + if (pHddStaCtx->hdd_ReassocScenario) { + hdd_info("Roaming in progress, return cached RSSI"); + *rssi_value = pAdapter->rssi; + return CDF_STATUS_SUCCESS; + } + + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = RSSI_CONTEXT_MAGIC; + + hstatus = sme_get_rssi(pHddCtx->hHal, hdd_get_rssi_cb, + pHddStaCtx->conn_info.staId[0], + pHddStaCtx->conn_info.bssId, pAdapter->rssi, + &context, pHddCtx->pcds_context); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_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(CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * wlan_hdd_get_snr() - Get the current SNR + * @pAdapter: adapter upon which the measurement is requested + * @snr: pointer to where the SNR should be returned + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_* on error + */ +CDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr) +{ + struct statsContext context; + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; + CDF_STATUS hstatus; + unsigned long rc; + int valid; + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Invalid context, pAdapter", __func__); + return CDF_STATUS_E_FAULT; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + valid = wlan_hdd_validate_context(pHddCtx); + if (0 != valid) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return CDF_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_get_snr(pHddCtx->hHal, hdd_get_snr_cb, + pHddStaCtx->conn_info.staId[0], + pHddStaCtx->conn_info.bssId, &context); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_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(CDF_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; + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_get_link_speed_cb() - Get link speed callback function + * @pLinkSpeed: pointer to the link speed record + * @pContext: pointer to the user context passed to SME + * + * This function is passed as the callback function to + * sme_get_link_speed() by wlan_hdd_get_linkspeed_for_peermac(). By + * agreement a &struct linkspeedContext is passed as @pContext. If + * the context is valid, then the contents of @pLinkSpeed are copied + * into the adapter record referenced by @pContext where they can be + * subsequently retrieved. If the context is invalid, then this + * function does nothing since it is assumed the caller has already + * timed-out and destroyed the context. + * + * Return: None. + */ +static void +hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext) +{ + struct linkspeedContext *pLinkSpeedContext; + hdd_adapter_t *pAdapter; + + if ((NULL == pLinkSpeed) || (NULL == pContext)) { + hddLog(CDF_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(CDF_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); +} + +/** + * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer + * @pAdapter: adapter upon which the peer is active + * @macAddress: MAC address of the peer + * + * This function will send a query to SME for the linkspeed of the + * given peer, and then wait for the callback to be invoked. + * + * Return: CDF_STATUS_SUCCESS if linkspeed data is available, + * otherwise a CDF_STATUS_E_* error. + */ +CDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, + tSirMacAddr macAddress) { + CDF_STATUS status; + unsigned long rc; + struct linkspeedContext context; + tSirLinkSpeedInfo *linkspeed_req; + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return CDF_STATUS_E_FAULT; + } + linkspeed_req = cdf_mem_malloc(sizeof(*linkspeed_req)); + if (NULL == linkspeed_req) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + return CDF_STATUS_E_NOMEM; + } + init_completion(&context.completion); + context.pAdapter = pAdapter; + context.magic = LINK_CONTEXT_MAGIC; + + cdf_mem_copy(linkspeed_req->peer_macaddr, macAddress, + sizeof(tSirMacAddr)); + status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter), + linkspeed_req, + &context, hdd_get_link_speed_cb); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics for link speed", + __func__); + cdf_mem_free(linkspeed_req); + } else { + rc = wait_for_completion_timeout + (&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * 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 { + CDF_STATUS status; + tSirMacAddr bssid; + + cdf_mem_copy(bssid, hdd_stactx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + + status = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid); + if (!CDF_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; +} + +/** + * hdd_statistics_cb() - "Get statistics" callback function + * @pStats: statistics payload + * @pContext: opaque context originally passed to SME. HDD always passes + * a pointer to an adapter + * + * Return: None + */ +void hdd_statistics_cb(void *pStats, void *pContext) +{ + hdd_adapter_t *pAdapter = (hdd_adapter_t *) pContext; + hdd_stats_t *pStatsCache = NULL; + hdd_wext_state_t *pWextState; + CDF_STATUS cdf_status = CDF_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) { + /* copy the stats into the cache we keep in the + * adapter instance structure + */ + cdf_mem_copy(&pStatsCache->summary_stat, pSummaryStats, + sizeof(pStatsCache->summary_stat)); + cdf_mem_copy(&pStatsCache->ClassA_stat, pClassAStats, + sizeof(pStatsCache->ClassA_stat)); + cdf_mem_copy(&pStatsCache->ClassB_stat, pClassBStats, + sizeof(pStatsCache->ClassB_stat)); + cdf_mem_copy(&pStatsCache->ClassC_stat, pClassCStats, + sizeof(pStatsCache->ClassC_stat)); + cdf_mem_copy(&pStatsCache->ClassD_stat, pClassDStats, + sizeof(pStatsCache->ClassD_stat)); + cdf_mem_copy(&pStatsCache->perStaStats, pPerStaStats, + sizeof(pStatsCache->perStaStats)); + } + + if (pAdapter) { + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + cdf_status = cdf_event_set(&pWextState->hdd_cdf_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(LOGE, FL("cdf_event_set failed")); + return; + } + } +} + +/** + * hdd_clear_roam_profile_ie() - Clear Roam Profile IEs + * @pAdapter: adapter who's IEs are to be cleared + * + * Return: None + */ +void hdd_clear_roam_profile_ie(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 = (uint8_t *) NULL; + pWextState->roamProfile.nRSNReqIELength = 0; + pWextState->roamProfile.pRSNReqIE = (uint8_t *) NULL; + +#ifdef FEATURE_WLAN_WAPI + pWextState->roamProfile.nWAPIReqIELength = 0; + pWextState->roamProfile.pWAPIReqIE = (uint8_t *) NULL; +#endif + + pWextState->roamProfile.bWPSAssociation = false; + pWextState->roamProfile.bOSENAssociation = false; + pWextState->roamProfile.pAddIEScan = (uint8_t *) NULL; + pWextState->roamProfile.nAddIEScanLength = 0; + pWextState->roamProfile.pAddIEAssoc = (uint8_t *) 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 = 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 + + cdf_zero_macaddr(&pWextState->req_bssId); + +} + +/** + * wlan_hdd_get_vendor_oui_ie_ptr() - Find a vendor OUI + * @oui: The OUI that is being searched for + * @oui_size: The length of @oui + * @ie: The set of IEs within which we're trying to find @oui + * @ie_len: The length of @ie + * + * This function will scan the IEs contained within @ie looking for @oui. + * + * Return: Pointer to @oui embedded within @ie if it is present, NULL + * if @oui is not present within @ie. + */ +uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size, + uint8_t *ie, int ie_len) +{ + int left = ie_len; + uint8_t *ptr = ie; + uint8_t elem_id, elem_len; + uint8_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(CDF_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; +} + +/** + * __iw_set_commit() - SIOCSIWCOMMIT 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_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; + + 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; + + hddLog(LOG1, "In %s", __func__); + /* 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; + + cds_ssr_protect(__func__); + ret = __iw_set_commit(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_name() - SIOCGIWNAME 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_name(struct net_device *dev, + struct iw_request_info *info, char *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; + + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_name(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_mode() - 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); + hdd_context_t *hdd_ctx; + tCsrRoamProfile *pRoamProfile; + eCsrRoamBssType LastBSSType; + eMib_dot11DesiredBssType connectedBssType; + struct hdd_config *pConfig; + struct wireless_dev *wdev; + 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))->config; + 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_conn_get_connected_bss_type + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType) + || (eCSR_BSS_TYPE_START_IBSS == LastBSSType)) { + CDF_STATUS cdf_status; + /* need to issue a disconnect to CSR. */ + INIT_COMPLETION(pAdapter->disconnect_comp_var); + cdf_status = + sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + if (CDF_STATUS_SUCCESS == cdf_status) { + unsigned long rc; + rc = wait_for_completion_timeout(&pAdapter-> + disconnect_comp_var, + msecs_to_jiffies + (WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) + hddLog(CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_mode(dev, info, wrqu, extra); + cds_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; + + cds_ssr_protect(__func__); + ret = __iw_get_mode(dev, info, wrqu, extra); + cds_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) +{ + uint32_t numChans = 0; + uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint32_t indx = 0; + int ret; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamProfile *pRoamProfile; + + 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 >= (uint32_t) 2.412e8) && + (wrqu->freq.m <= (uint32_t) 5.825e8)) { + uint32_t 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 (sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_freq(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_freq() - SIOCGIWFREQ 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_freq(struct net_device *dev, struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + uint32_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_get_operation_channel(hHal, &channel, pAdapter->sessionId) + != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_get_freq(dev, info, fwrq, extra); + cds_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 *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + int ret; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + wrqu->txpower.value = 0; + return 0; + } + wlan_hdd_get_class_astats(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; + + cds_ssr_protect(__func__); + ret = __iw_get_tx_power(dev, info, wrqu, extra); + cds_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 (sme_cfg_set_int(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + wrqu->txpower.value) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_tx_power(dev, info, wrqu, extra); + cds_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) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + CDF_STATUS status = CDF_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 ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return status; + } + + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { + wrqu->bitrate.value = 0; + } else { + status = + sme_get_statistics(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_statistics_cb, 0, + false, + pHddStaCtx->conn_info.staId[0], + pAdapter, pAdapter->sessionId); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve statistics", __func__); + return status; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + cdf_status = + cdf_wait_single_event(&pWextState->hdd_cdf_event, + WLAN_WAIT_TIME_STATS); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: SME timeout while retrieving statistics", + __func__); + return CDF_STATUS_E_FAILURE; + } + + wrqu->bitrate.value = + pAdapter->hdd_stats.ClassA_stat.tx_rate * 500 * 1000; + } + + EXIT(); + + return cdf_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; + + cds_ssr_protect(__func__); + ret = __iw_get_bitrate(dev, info, wrqu, extra); + cds_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); + uint8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; + uint32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; + uint32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; + uint32_t i, rate; + uint32_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 (sme_cfg_get_int(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_DOT11_MODE, + &active_phy_mode) == CDF_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 ((sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_SUPPORTED_RATES_11A, supp_rates, + &a_len) == CDF_STATUS_SUCCESS) + && + (sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_SUPPORTED_RATES_11B, supp_rates, + &b_len) == CDF_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 (sme_cfg_set_int(WLAN_HDD_GET_HAL_CTX(pAdapter), + WNI_CFG_FIXED_RATE, rate) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_bitrate(dev, info, wrqu, extra); + cds_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); + uint8_t *genie = NULL; + uint8_t *base_genie = NULL; + uint16_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_clear_roam_profile_ie(pAdapter); + EXIT(); + return 0; + } + + base_genie = mem_alloc_copy_from_user_helper(wrqu->data.pointer, + wrqu->data.length); + if (NULL == base_genie) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + uint16_t eLen = 0; + uint8_t elementId; + elementId = *genie++; + eLen = *genie++; + remLen -= 2; + + hddLog(CDF_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 */ + kfree(base_genie); + return -EINVAL; + } + + if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) { + uint16_t curGenIELen = pWextState->genIE.length; + hddLog(CDF_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(CDF_TRACE_LEVEL_FATAL, + "Cannot accommodate genIE. " + "Need bigger buffer space"); + CDF_ASSERT(0); + kfree(base_genie); + return -ENOMEM; + } + /* 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(CDF_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)); + pWextState->roamProfile.pWPAReqIE = + pWextState->WPARSNIE; + pWextState->roamProfile.nWPAReqIELength = + eLen + 2; + } else { /* any vendorId except WPA IE should be accumulated to genIE */ + + uint16_t curGenIELen = pWextState->genIE.length; + hddLog(CDF_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(CDF_TRACE_LEVEL_FATAL, + "Cannot accommodate genIE. " + "Need bigger buffer space"); + CDF_ASSERT(0); + kfree(base_genie); + return -ENOMEM; + } + /* 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); + 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); + kfree(base_genie); + return 0; + } + genie += eLen; + remLen -= eLen; + } + EXIT(); + kfree(base_genie); + return 0; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_set_genie(dev, info, wrqu, extra); + cds_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); + CDF_STATUS status; + uint32_t length = DOT11F_IE_RSN_MAX_LEN; + uint8_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 (!hdd_is_auth_type_rsn(pWextState->roamProfile.negotiatedAuthType)) { + return -ENXIO; + } + + /* Actually retrieve the RSN IE from CSR. (We previously sent + * it down in the CSR Roam Profile.) + */ + status = csr_roam_get_wpa_rsn_req_ie(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &length, genIeBytes); + length = CDF_MIN((uint16_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; + } + cdf_mem_copy(extra, (void *)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; + + cds_ssr_protect(__func__); + ret = __iw_get_genie(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_encode() - SIOCGIWENCODE 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_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]; + cdf_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; + + cds_ssr_protect(__func__); + ret = __iw_get_encode(dev, info, dwrq, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __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); + uint32_t status = 0; + + status = hdd_wlan_get_rts_threshold(pAdapter, wrqu); + + return status; +} + +/** + * __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 (sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD, wrqu->rts.value) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, FL + ("failed to set ini parameter, WNI_CFG_RTS_THRESHOLD")); + return -EIO; + } + + EXIT(); + + return 0; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_get_rts_threshold(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_set_rts_threshold(dev, info, wrqu, extra); + cds_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); + uint32_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; + + cds_ssr_protect(__func__); + ret = __iw_get_frag_threshold(dev, info, wrqu, extra); + cds_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 (sme_cfg_set_int + (hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, wrqu->frag.value) + != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_frag_threshold(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_power_mode() - SIOCGIWPOWER 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_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; + + cds_ssr_protect(__func__); + ret = __iw_get_power_mode(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_power_mode() - SIOCSIWPOWER 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_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; + + cds_ssr_protect(__func__); + ret = __iw_set_power_mode(dev, info, wrqu, extra); + cds_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; + + uint8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + uint32_t num_channels = sizeof(channels); + uint8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; + uint32_t a_len; + uint32_t b_len; + uint32_t active_phy_mode = 0; + uint8_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 (sme_cfg_get_int(hHal, + WNI_CFG_DOT11_MODE, + &active_phy_mode) == CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 (sme_cfg_get_str(hHal, + WNI_CFG_SUPPORTED_RATES_11A, + supp_rates, + &a_len) == CDF_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 (sme_cfg_get_str(hHal, + WNI_CFG_SUPPORTED_RATES_11B, + supp_rates, + &b_len) == CDF_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 (sme_cfg_get_str + ((hHal), WNI_CFG_VALID_CHANNEL_LIST, channels, + &num_channels) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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++) { + uint32_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; + + cds_ssr_protect(__func__); + ret = __iw_get_range(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_get_class_a_statistics_cb() - Get Class A stats callback function + * @pStats: pointer to Class A stats + * @pContext: user context originally registered with SME + * + * Return: None + */ +static void hdd_get_class_a_statistics_cb(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(CDF_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(CDF_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); +} + +/** + * wlan_hdd_get_class_astats() - Get Class A statistics + * @pAdapter: adapter for which statistics are desired + * + * Return: CDF_STATUS_SUCCESS if adapter's Class A statistics were updated + */ +CDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + CDF_STATUS hstatus; + unsigned long rc; + struct statsContext context; + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return CDF_STATUS_E_FAULT; + } + if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s:LOGP in Progress. Ignore!!!", __func__); + return CDF_STATUS_SUCCESS; + } + + /* we are connected so 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_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter), + eCSR_HDD, SME_GLOBAL_CLASSA_STATS, + hdd_get_class_a_statistics_cb, + 0, /* not periodic */ + false, /* non-cached results */ + pHddStaCtx->conn_info.staId[0], + &context, pAdapter->sessionId); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_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(CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * hdd_get_station_statistics_cb() - Get stats callback function + * @pStats: pointer to Class A stats + * @pContext: user context originally registered with SME + * + * Return: None + */ +static void hdd_get_station_statistics_cb(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(CDF_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(CDF_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); +} + +/** + * wlan_hdd_get_station_stats() - Get station statistics + * @pAdapter: adapter for which statistics are desired + * + * Return: CDF_STATUS_SUCCESS if adapter's statistics were updated + */ +CDF_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + CDF_STATUS hstatus; + unsigned long rc; + struct statsContext context; + + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); + return CDF_STATUS_SUCCESS; + } + + /* we are connected so 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_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter), + eCSR_HDD, + SME_SUMMARY_STATS | + SME_GLOBAL_CLASSA_STATS, + hdd_get_station_statistics_cb, + 0, /* not periodic */ + false, /* non-cached results */ + pHddStaCtx->conn_info.staId[0], + &context, pAdapter->sessionId); + if (CDF_STATUS_SUCCESS != hstatus) { + hddLog(CDF_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(CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * iw_get_linkspeed() - Get current link speed ioctl + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: extra ioctl buffer + * + * Return: 0 on success, non-zero on error + */ +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(uint32_t) + 1; + uint32_t link_speed = 0; + hdd_context_t *hdd_ctx; + int rc, valid; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + valid = wlan_hdd_validate_context(hdd_ctx); + if (0 != valid) + return valid; + + rc = wlan_hdd_get_link_speed(pAdapter, &link_speed); + if (0 != rc) { + return rc; + } + + wrqu->data.length = len; + /* return the linkspeed as a string */ + rc = snprintf(pLinkSpeed, len, "%u", link_speed); + if ((rc < 0) || (rc >= len)) { + /* encoding or length error? */ + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Unable to encode link speed")); + return -EIO; + } + + /* a value is being successfully returned */ + return 0; +} + +static int iw_get_linkspeed(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_get_linkspeed(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_change_country_code_callback() - Change country code callback + * @context: opaque context originally passed to SME. All functions + * which use this callback pass the adapter upon which the country + * code change is active + * + * This function is registered as the callback function when + * sme_change_country_code() is invoked. Callers of + * sme_change_country_code() subsequently wait for the adapter's + * @change_country_code completion variable, so all this function + * needs to do is set that completion variable so that execution can + * continue. + * + * Return: none + */ +void wlan_hdd_change_country_code_callback(void *context) +{ + + hdd_adapter_t *adapter = context; + + if (adapter && (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)) + complete(&adapter->change_country_code); + + return; +} + +/** + * __iw_set_nick() - SIOCSIWNICKN 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_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; + + cds_ssr_protect(__func__); + ret = __iw_set_nick(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_nick() - SIOCGIWNICKN 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_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; + + cds_ssr_protect(__func__); + ret = __iw_get_nick(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __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); + hdd_context_t *hdd_ctx; + struct iw_point *encoderq = &(wrqu->encoding); + uint32_t keyId; + uint8_t key_length; + eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; + bool fKeyPresent = 0; + int i; + CDF_STATUS status = CDF_STATUS_SUCCESS; + 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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + if (CDF_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(CDF_TRACE_LEVEL_ERROR, + FL + ("failed wait on disconnect_comp_var")); + } + } + + return status; + + } + + if (wrqu->data.flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) { + hddLog(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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))) { + + cdf_mem_copy(&pWextState->roamProfile.Keys. + KeyMaterial[keyId][0], extra, key_length); + + pWextState->roamProfile.Keys.KeyLength[keyId] = + (uint8_t) key_length; + pWextState->roamProfile.Keys.defaultIndex = + (uint8_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; + + cds_ssr_protect(__func__); + ret = __iw_set_encode(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_get_encodeext() - SIOCGIWENCODEEXT 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_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]; + cdf_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; + + cds_ssr_protect(__func__); + ret = __iw_get_encodeext(dev, info, dwrq, extra); + cds_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); + hdd_context_t *hdd_ctx; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; + int ret; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int key_index; + struct iw_point *encoding = &wrqu->encoding; + tCsrRoamSetKey setKey; + uint32_t roamId = 0xFF; + + 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 encrytion 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) { + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + cdf_mem_copy(&pRoamProfile->Keys. + KeyMaterial[key_index][0], + ext->key, ext->key_len); + pRoamProfile->Keys.KeyLength[key_index] = + (uint8_t) ext->key_len; + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + pRoamProfile->Keys.defaultIndex = + (uint8_t) key_index; + + } + } + return ret; + } + + cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey)); + + setKey.keyId = key_index; + setKey.keyLength = ext->key_len; + + if (ext->key_len <= CSR_MAX_KEY_LEN) { + cdf_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; + cdf_set_macaddr_broadcast(&setKey.peerMac); + } else { + + setKey.keyDirection = eSIR_TX_RX; + cdf_mem_copy(setKey.peerMac.bytes, ext->addr.sa_data, + CDF_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: + { + uint8_t *pKey = &setKey.Key[0]; + + setKey.encType = eCSR_ENCRYPT_TYPE_TKIP; + + cdf_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) */ + cdf_mem_copy(pKey, ext->key, 16); + + /* Copy the rx mic first */ + cdf_mem_copy(&pKey[16], &ext->key[24], 8); + + /* Copy the tx mic */ + cdf_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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 + */ + cdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &setKey); + if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } else if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_FAILED) { + hddLog(CDF_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; + + cdf_ret_status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &setKey, &roamId); + + if (cdf_ret_status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "[%4d] sme_roam_set_key returned ERROR status= %d", + __LINE__, cdf_ret_status); + + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; + } + + return cdf_ret_status; +} + +/** + * 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; + + cds_ssr_protect(__func__); + ret = __iw_set_encodeext(dev, info, wrqu, extra); + cds_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) { + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 (sme_cfg_set_int (hHal, WNI_CFG_LONG_RETRY_LIMIT, + wrqu->retry.value) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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 (sme_cfg_set_int (hHal, WNI_CFG_SHORT_RETRY_LIMIT, + wrqu->retry.value) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, FL + ("failed to set ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + } + } else { + return -EOPNOTSUPP; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_set_retry(dev, info, wrqu, extra); + cds_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); + uint32_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 (sme_cfg_get_int(hHal, WNI_CFG_LONG_RETRY_LIMIT, &retry) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 (sme_cfg_get_int(hHal, WNI_CFG_SHORT_RETRY_LIMIT, &retry) != + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + FL + ("failed to get ini parameter, WNI_CFG_LONG_RETRY_LIMIT")); + return -EIO; + } + + wrqu->retry.value = retry; + } else { + return -EOPNOTSUPP; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + cds_ssr_protect(__func__); + ret = __iw_get_retry(dev, info, wrqu, extra); + cds_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; + CDF_STATUS status = CDF_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_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, reason); + + if (CDF_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(CDF_TRACE_LEVEL_ERROR, + FL + ("failed wait on disconnect_comp_var")); + } else + hddLog(LOGE, + "%s %d Command Disassociate/Deauthenticate : csr_roam_disconnect 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")); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE_N_CARRIER, + WLAN_CONTROL_PATH); + + } 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; + + cds_ssr_protect(__func__); + ret = __iw_set_mlme(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * wlan_hdd_update_phymode() - handle change in PHY mode + * @net: device upon which PHY mode change was received + * @hal: umac handle for the driver + * @new_phymode: new PHY mode for the device + * @phddctx: pointer to the HDD context + * + * This function is called when the device is set to a new PHY mode. + * It takes a holistic look at the desired PHY mode along with the + * configured capabilities of the driver and the reported capabilities + * of the hardware in order to correctly configure all PHY-related + * parameters. + * + * Return: 0 on success, negative errno value on error + */ +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); + CDF_STATUS halStatus = CDF_STATUS_E_FAILURE; +#endif + bool band_24 = false, band_5g = false; + bool ch_bond24 = false, ch_bond5g = false; + tSmeConfigParams smeconfig; + uint32_t chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; +#ifdef WLAN_FEATURE_11AC + uint32_t vhtchanwidth; +#endif + eCsrPhyMode phymode = -EIO, old_phymode; + eHddDot11Mode hdd_dot11mode = phddctx->config->dot11Mode; + eCsrBand curr_band = eCSR_BAND_ALL; + + old_phymode = sme_get_phy_mode(hal); + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + sme_get_cb_phy_state_from_cb_ini_value(phddctx->config-> + nChannelBondingMode24GHz)) + ch_bond24 = true; + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + sme_get_cb_phy_state_from_cb_ini_value(phddctx->config-> + nChannelBondingMode5GHz)) + ch_bond5g = true; + + if (phddctx->config->nBandCapability == eCSR_BAND_ALL) { + band_24 = band_5g = true; + } else if (phddctx->config->nBandCapability == eCSR_BAND_24) { + band_24 = true; + } else if (phddctx->config->nBandCapability == eCSR_BAND_5G) { + band_5g = true; + } + + vhtchanwidth = phddctx->config->vhtChannelWidth; + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_set_phy_mode(hal, eCSR_DOT11_MODE_AUTO); + if (hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11A: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11a); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11B: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11b); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11G: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11g); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + /* UMAC doesnt 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_set_phy_mode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NA_HT40: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NG_HT20: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11NG_HT40: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_set_band(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_set_phy_mode(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_set_phy_mode(hal, eCSR_DOT11_MODE_11ac); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; +#endif + case IEEE80211_MODE_2G_AUTO: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_AUTO); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_5G_AUTO: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_AUTO); + if ((hdd_set_band(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_set_phy_mode(hal, old_phymode); + return -EIO; + } + break; + case IEEE80211_MODE_11AGN: + sme_set_phy_mode(hal, eCSR_DOT11_MODE_11n); + if ((hdd_set_band(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_set_phy_mode(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->config->vhtChannelWidth; + break; + } +#endif + + if (phymode != -EIO) { + sme_get_config_param(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 = false; + halStatus = sme_set_ht2040_mode(hal, + pAdapter->sessionId, + eHT_CHAN_HT20, false); + if (halStatus == CDF_STATUS_E_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 = true; + halStatus = sme_set_ht2040_mode(hal, + pAdapter->sessionId, + eHT_CHAN_HT20, true); + if (halStatus == CDF_STATUS_E_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->config->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_update_config(hal, &smeconfig); + + phddctx->config->dot11Mode = hdd_dot11mode; + phddctx->config->nBandCapability = curr_band; + phddctx->config->nChannelBondingMode24GHz = + smeconfig.csrConfig.channelBondingMode24GHz; + phddctx->config->nChannelBondingMode5GHz = + smeconfig.csrConfig.channelBondingMode5GHz; + phddctx->config->vhtChannelWidth = vhtchanwidth; + if (hdd_update_config_dat(phddctx) == false) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: could not update config_dat", __func__); + return -EIO; + } + if (phddctx->config->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; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + "New_Phymode= %d ch_bonding=%d band=%d VHT_ch_width=%u", + phymode, chwidth, curr_band, vhtchanwidth); + } + + return 0; +} + +/** + * hdd_get_temperature_cb() - "Get Temperature" callback function + * @temperature: measured temperature + * @pContext: callback context + * + * This function is passed to sme_get_temperature() as the callback + * function to be invoked when the temperature measurement is + * available. + * + * Return: None + */ +static void hdd_get_temperature_cb(int temperature, void *pContext) +{ + struct statsContext *pTempContext; + hdd_adapter_t *pAdapter; + ENTER(); + if (NULL == pContext) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("pContext is NULL")); + return; + } + pTempContext = pContext; + pAdapter = pTempContext->pAdapter; + spin_lock(&hdd_context_lock); + if ((NULL == pAdapter) || (TEMP_CONTEXT_MAGIC != pTempContext->magic)) { + spin_unlock(&hdd_context_lock); + hddLog(CDF_TRACE_LEVEL_WARN, + FL("Invalid context, pAdapter [%p] magic [%08x]"), + pAdapter, pTempContext->magic); + return; + } + if (temperature != 0) { + pAdapter->temperature = temperature; + } + complete(&pTempContext->completion); + spin_unlock(&hdd_context_lock); + EXIT(); +} + +/** + * wlan_hdd_get_temperature() - get current device temperature + * @pAdapter: device upon which the request was made + * @temperature: pointer to where the temperature is to be returned + * + * Return: 0 if a temperature value (either current or cached) was + * returned, otherwise a negative errno is returned. + * + */ +int wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature) +{ + CDF_STATUS status; + struct statsContext tempContext; + unsigned long rc; + + ENTER(); + if (NULL == pAdapter) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("pAdapter is NULL")); + return -EPERM; + } + init_completion(&tempContext.completion); + tempContext.pAdapter = pAdapter; + tempContext.magic = TEMP_CONTEXT_MAGIC; + status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(pAdapter), + &tempContext, hdd_get_temperature_cb); + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Unable to retrieve temperature")); + } else { + rc = wait_for_completion_timeout(&tempContext.completion, + msecs_to_jiffies + (WLAN_WAIT_TIME_STATS)); + if (!rc) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL + ("SME timed out while retrieving temperature")); + } + } + spin_lock(&hdd_context_lock); + tempContext.magic = 0; + spin_unlock(&hdd_context_lock); + *temperature = pAdapter->temperature; + EXIT(); + return 0; +} + +/** + * iw_setint_getnone() - Generic "set integer" private 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_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 *hdd_ctx; + tSmeConfigParams smeConfig; + int *value = (int *)extra; + int sub_cmd = value[0]; + int set_value = value[1]; + int ret; + int enable_pbm, enable_mp; + + INIT_COMPLETION(pWextState->completion_var); + + 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_11D_STATE: + { + if ((ENABLE_11D == set_value) + || (DISABLE_11D == set_value)) { + + memset(&smeConfig, 0x00, sizeof(smeConfig)); + sme_get_config_param(hHal, &smeConfig); + smeConfig.csrConfig.Is11dSupportEnabled = + (bool) set_value; + + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_INFO, + ("11D state=%d!!"), + smeConfig.csrConfig. + Is11dSupportEnabled); + + sme_update_config(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 1: + /* Enable PowerSave */ + sme_ps_enable_disable(hHal, pAdapter->sessionId, + SME_PS_ENABLE); + break; + case 2: + /* Disable PowerSave */ + sme_ps_enable_disable(hHal, pAdapter->sessionId, + SME_PS_DISABLE); + break; + case 3: /* Enable UASPD */ + sme_ps_uapsd_enable(hHal, pAdapter->sessionId); + break; + case 4: /* Disable UASPD */ + sme_ps_uapsd_disable(hHal, pAdapter->sessionId); + 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 (sme_cfg_set_int(hHal, WNI_CFG_ASSOC_STA_LIMIT, + set_value) + != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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))->config->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) || + (sme_cfg_set_int((WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + set_value) == CDF_STATUS_E_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; + + cdf_mem_copy(bssid, pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + if (sme_set_tx_power + (hHal, pAdapter->sessionId, bssid, + pAdapter->device_mode, + set_value) != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Setting tx power failed", __func__); + return -EIO; + } + break; + } + case WE_SET_MAX_TX_POWER: + { + tSirMacAddr bssid; + tSirMacAddr selfMac; + + hddLog(CDF_TRACE_LEVEL_INFO, + "%s: Setting maximum tx power %d dBm", __func__, + set_value); + cdf_mem_copy(bssid, pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(selfMac, pHddStaCtx->conn_info.bssId.bytes, + CDF_MAC_ADDR_SIZE); + + if (sme_set_max_tx_power(hHal, bssid, selfMac, set_value) + != CDF_STATUS_SUCCESS) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Setting maximum tx power failed", + __func__); + return -EIO; + } + + break; + } + case WE_SET_MAX_TX_POWER_2_4: + { + hddLog(CDF_TRACE_LEVEL_INFO, + "%s: Setting maximum tx power %d dBm for 2.4 GHz band", + __func__, set_value); + if (sme_set_max_tx_power_per_band(eCSR_BAND_24, set_value) != + CDF_STATUS_SUCCESS) { + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO, + "%s: Setting maximum tx power %d dBm for 5.0 GHz band", + __func__, set_value); + if (sme_set_max_tx_power_per_band(eCSR_BAND_5G, set_value) != + CDF_STATUS_SUCCESS) { + hddLog(CDF_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 == false) || (set_value == 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(CDF_TRACE_LEVEL_INFO, + "Set Thermal Mitigation Level %d", set_value); + (void)sme_set_thermal_level(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 (CDF_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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_GTX_BW_MASK, + set_value, GTX_CMD); + break; + } + + case WE_SET_LDPC: + { + uint32_t value; + union { + uint16_t nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + } uHTCapabilityInfo; + + hddLog(LOG1, "LDPC val %d", set_value); + /* get the HT capability info */ + ret = sme_cfg_get_int(hHal, WNI_CFG_HT_CAP_INFO, &value); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + return -EIO; + } + + uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; + if ((set_value + && (uHTCapabilityInfo.htCapInfo.advCodingCap)) + || (!set_value)) { + ret = + sme_update_ht_config(hHal, + pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_ADVANCE_CODING, + set_value); + } + + if (ret) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Failed to set LDPC value"); + + break; + } + + case WE_SET_TX_STBC: + { + uint32_t value; + union { + uint16_t nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + } uHTCapabilityInfo; + + hddLog(LOG1, "TX_STBC val %d", set_value); + /* get the HT capability info */ + ret = sme_cfg_get_int(hHal, WNI_CFG_HT_CAP_INFO, &value); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + return -EIO; + } + + uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; + if ((set_value && (uHTCapabilityInfo.htCapInfo.txSTBC)) + || (!set_value)) { + ret = + sme_update_ht_config(hHal, + pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_TX_STBC, + set_value); + } + + if (ret) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Failed to set TX STBC value"); + + break; + } + + case WE_SET_RX_STBC: + { + uint32_t value; + union { + uint16_t nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + } uHTCapabilityInfo; + + hddLog(LOG1, "WMI_VDEV_PARAM_RX_STBC val %d", + set_value); + /* get the HT capability info */ + ret = sme_cfg_get_int(hHal, WNI_CFG_HT_CAP_INFO, &value); + if (CDF_STATUS_SUCCESS != ret) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + return -EIO; + } + + uHTCapabilityInfo.nCfgValue16 = 0xFFFF & value; + if ((set_value && (uHTCapabilityInfo.htCapInfo.rxSTBC)) + || (!set_value)) { + ret = + sme_update_ht_config(hHal, + pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_RX_STBC, + (!set_value) ? set_value + : uHTCapabilityInfo. + htCapInfo.rxSTBC); + } + + if (ret) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Failed to set RX STBC value"); + break; + } + + case WE_SET_SHORT_GI: + { + hddLog(LOG1, "WMI_VDEV_PARAM_SGI val %d", set_value); + ret = sme_update_ht_config(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ, + set_value); + if (ret) + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + "Failed to set ShortGI value"); + break; + } + + case WE_SET_RTSCTS: + { + uint32_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))->config-> + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_ENABLE_RTSCTS, + set_value, VDEV_CMD); + if (!ret) { + if (sme_cfg_set_int + (hHal, WNI_CFG_RTS_THRESHOLD, value) != + CDF_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 != + csr_convert_cb_ini_value_to_phy_cb_state(phddctx->config-> + nChannelBondingMode5GHz))) + chwidth = true; + + memset(&smeConfig, 0x00, sizeof(smeConfig)); + sme_get_config_param(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->config-> + nChannelBondingMode5GHz; + else + return -EINVAL; + + break; +#ifdef WLAN_FEATURE_11AC + case eHT_CHANNEL_WIDTH_80MHZ: + if (chwidth) + smeConfig.csrConfig. + channelBondingMode5GHz = + phddctx->config-> + nChannelBondingMode5GHz; + else + return -EINVAL; + + break; +#endif + + default: + return -EINVAL; + } + + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_CHWIDTH, + set_value, VDEV_CMD); + if (!ret) + sme_update_config(hHal, &smeConfig); + + break; + } + + case WE_SET_ANI_EN_DIS: + { + hddLog(LOG1, "WMI_PDEV_PARAM_ANI_ENABLE val %d", + set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_PDEV_PARAM_CTS_CBW, + set_value, PDEV_CMD); + break; + } + + case WE_SET_11N_RATE: + { + uint8_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; + if (rix != 0x3) + /* Enable Short + * preamble always for + * CCK except 1mbps + */ + rix |= 0x4; + } else { + preamble = + WMI_RATE_PREAMBLE_OFDM; + } + } + set_value = (preamble << 6) | (nss << 4) | rix; + } + hdd_info("WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case WE_SET_VHT_RATE: + { + uint8_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; + } + hdd_info("WMI_VDEV_PARAM_FIXED_RATE val %d rix %d preamble %x nss %d", + set_value, rix, preamble, nss); + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_FIXED_RATE, + set_value, VDEV_CMD); + break; + } + + case WE_SET_AMPDU: + { + hddLog(LOG1, "SET AMPDU val %d", set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_VDEV_PARAM_AMPDU, + set_value, GEN_CMD); + break; + } + + case WE_SET_AMSDU: + { + hddLog(LOG1, "SET AMSDU val %d", set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_VDEV_PARAM_AMSDU, + set_value, GEN_CMD); + break; + } + + case WE_SET_BURST_ENABLE: + { + hddLog(LOG1, "SET Burst enable val %d", set_value); + if ((set_value == 0) || (set_value == 1)) { + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + set_value, PDEV_CMD); + break; + } + + case WE_SET_POWER_GATING: + { + hddLog(LOG1, "WMI_PDEV_PARAM_POWER_GATING_SLEEP val %d", + set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_PDEV_PARAM_POWER_GATING_SLEEP, + (set_value) ? true : false, PDEV_CMD); + break; + } + + /* Firmware debug log */ + case WE_DBGLOG_LOG_LEVEL: + { + hddLog(LOG1, "WE_DBGLOG_LOG_LEVEL val %d", set_value); + hdd_ctx->fw_log_settings.dl_loglevel = set_value; + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_VAP_DISABLE, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_MODULE_ENABLE: + { + hddLog(LOG1, "WE_DBGLOG_MODULE_ENABLE val %d", + set_value); + hdd_ctx->fw_log_settings.enable = set_value; + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_MODULE_ENABLE, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_MODULE_DISABLE: + { + hddLog(LOG1, "WE_DBGLOG_MODULE_DISABLE val %d", + set_value); + hdd_ctx->fw_log_settings.enable = set_value; + ret = wma_cli_set_command(pAdapter->sessionId, + 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 (hdd_ctx->fw_log_settings.index >= MAX_MOD_LOGLEVEL) + hdd_ctx->fw_log_settings.index = 0; + + hdd_ctx->fw_log_settings. + dl_mod_loglevel[hdd_ctx->fw_log_settings.index] = + set_value; + hdd_ctx->fw_log_settings.index++; + + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_MOD_LOG_LEVEL, + set_value, DBG_CMD); + break; + } + + case WE_DBGLOG_TYPE: + { + hddLog(LOG1, "WE_DBGLOG_TYPE val %d", set_value); + hdd_ctx->fw_log_settings.dl_type = set_value; + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_DBGLOG_TYPE, + set_value, DBG_CMD); + break; + } + case WE_DBGLOG_REPORT_ENABLE: + { + hddLog(LOG1, "WE_DBGLOG_REPORT_ENABLE val %d", + set_value); + hdd_ctx->fw_log_settings.dl_report = set_value; + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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); + ret = wma_cli_set_command(pAdapter->sessionId, + 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: + { + 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(hdd_ctx); + break; + case WLAN_HDD_NETIF_OPER_HISTORY: + wlan_hdd_clear_netif_queue_history(hdd_ctx); + break; + default: + ol_txrx_clear_stats(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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PPS_5G_EBT, + set_value, PPS_CMD); + break; + } + + case WE_SET_HTSMPS: + { + hddLog(LOG1, "WE_SET_HTSMPS val %d", set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command( + pAdapter->sessionId, + 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 = wma_cli_set_command( + pAdapter->sessionId, + 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 = wma_cli_set_command( + pAdapter->sessionId, + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + set_value, QPOWER_CMD); + break; + } + + case WE_MCC_CONFIG_LATENCY: + { + cds_set_mcc_latency(pAdapter, set_value); + break; + } + + case WE_MCC_CONFIG_QUOTA: + { + hddLog(LOG1, "iwpriv cmd to set MCC quota with val %dms", + set_value); + ret = cds_set_mcc_p2p_quota(pAdapter, set_value); + break; + } + case WE_SET_DEBUG_LOG: + { + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef QCA_PKT_PROTO_TRACE + /* Trace buffer dump only */ + if (CDS_PKT_TRAC_DUMP_CMD == set_value) { + cds_pkt_trace_buf_dump(); + break; + } +#endif /* QCA_PKT_PROTO_TRACE */ + hdd_ctx->config->gEnableDebugLog = set_value; + sme_update_connect_debug(hdd_ctx->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 = wma_cli_set_command( + pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command( + pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command( + pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + WMI_VDEV_PARAM_EARLY_RX_DRIFT_SAMPLE, + set_value, VDEV_CMD); + break; + } + case WE_SET_SCAN_DISABLE: + { + hddLog(LOG1, "SET SCAN DISABLE %d", set_value); + sme_set_scan_disable(WLAN_HDD_GET_HAL_CTX(pAdapter), set_value); + break; + } + default: + { + hddLog(LOGE, "%s: Invalid sub command %d", __func__, + sub_cmd); + ret = -EINVAL; + break; + } + } + return ret; +} + +static int iw_setint_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_setint_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_setchar_getnone() - Generic "set string" private 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_setchar_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + CDF_STATUS vstatus; + int sub_cmd; + int ret; + char *pBuffer = NULL; + hdd_adapter_t *pAdapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); +#ifdef WLAN_FEATURE_VOWIFI + struct hdd_config *pConfig = hdd_ctx->config; +#endif /* WLAN_FEATURE_VOWIFI */ + struct iw_point s_priv_data; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* 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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received length %d", __func__, s_priv_data.length); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Received data %s", __func__, pBuffer); + + switch (sub_cmd) { + case WE_WOWL_ADD_PTRN: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "ADD_PTRN"); + hdd_add_wowl_ptrn(pAdapter, pBuffer); + break; + case WE_WOWL_DEL_PTRN: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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); + cdf_mem_copy(neighborReq.ssid.ssId, + pBuffer, + neighborReq.ssid.length); + } + + callbackInfo.neighborRspCallback = NULL; + callbackInfo.neighborRspCallbackContext = NULL; + callbackInfo.timeout = 5000; /* 5 seconds */ + sme_neighbor_report_request(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_update_p2p_ie(WLAN_HDD_GET_HAL_CTX(pAdapter), pBuffer, + s_priv_data.length); + break; + case WE_SET_CONFIG: + vstatus = hdd_execute_global_config_command(hdd_ctx, pBuffer); + if (CDF_STATUS_SUCCESS != vstatus) { + ret = -EINVAL; + } + break; + default: + { + hddLog(LOGE, "%s: Invalid sub command %d", __func__, + sub_cmd); + ret = -EINVAL; + break; + } + } + kfree(pBuffer); + return ret; +} + +static int iw_setchar_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_setchar_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_setnone_getint() - Generic "get integer" private 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_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; + tSmeConfigParams smeConfig; + hdd_context_t *hdd_ctx; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (value[0]) { + case WE_GET_11D_STATE: + { + sme_get_config_param(hHal, &smeConfig); + + *value = smeConfig.csrConfig.Is11dSupportEnabled; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + ("11D state=%d!!"), *value); + + break; + } + + case WE_IBSS_STATUS: + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "****Return IBSS Status*****"); + break; + + case WE_GET_WLAN_DBG: + { + cdf_trace_display(); + *value = 0; + break; + } + case WE_GET_MAX_ASSOC: + { + if (sme_cfg_get_int + (hHal, WNI_CFG_ASSOC_STA_LIMIT, + (uint32_t *) value) != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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))->config->force_sap_acs; + break; + + case WE_GET_CONCURRENCY_MODE: + { + *value = cds_get_concurrency_mode(); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + ("concurrency mode=%d"), *value); + break; + } + + case WE_GET_NSS: + { + sme_get_config_param(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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + WMI_VDEV_PARAM_GTX_BW_MASK, + GTX_CMD); + break; + } + + case WE_GET_LDPC: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_LDPC"); + *value = sme_get_ht_config(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_ADVANCE_CODING); + break; + } + + case WE_GET_TX_STBC: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_TX_STBC"); + *value = sme_get_ht_config(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_TX_STBC); + break; + } + + case WE_GET_RX_STBC: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_RX_STBC"); + *value = sme_get_ht_config(hHal, pAdapter->sessionId, + WNI_CFG_HT_CAP_INFO_RX_STBC); + break; + } + + case WE_GET_SHORT_GI: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_SGI"); + *value = sme_get_ht_config(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(pAdapter->sessionId, + WMI_VDEV_PARAM_ENABLE_RTSCTS, + VDEV_CMD); + break; + } + + case WE_GET_CHWIDTH: + { + hddLog(LOG1, "GET WMI_VDEV_PARAM_CHWIDTH"); + *value = wma_cli_get_command(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + WMI_VDEV_PARAM_FIXED_RATE, + VDEV_CMD); + break; + } + + case WE_GET_AMPDU: + { + hddLog(LOG1, "GET AMPDU"); + *value = wma_cli_get_command(pAdapter->sessionId, + GEN_VDEV_PARAM_AMPDU, + GEN_CMD); + break; + } + + case WE_GET_AMSDU: + { + hddLog(LOG1, "GET AMSDU"); + *value = wma_cli_get_command(pAdapter->sessionId, + GEN_VDEV_PARAM_AMSDU, + GEN_CMD); + break; + } + + case WE_GET_BURST_ENABLE: + { + hddLog(LOG1, "GET Burst enable value"); + *value = wma_cli_get_command(pAdapter->sessionId, + WMI_PDEV_PARAM_BURST_ENABLE, + PDEV_CMD); + break; + } + case WE_GET_BURST_DUR: + { + hddLog(LOG1, "GET Burst Duration value"); + *value = wma_cli_get_command(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + WMI_PDEV_PARAM_RX_CHAIN_MASK, + PDEV_CMD); + break; + } + + case WE_GET_TXPOW_2G: + { + uint32_t txpow2g = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT2G"); + *value = wma_cli_get_command(pAdapter->sessionId, + WMI_PDEV_PARAM_TXPOWER_LIMIT2G, + PDEV_CMD); + if (CDF_STATUS_SUCCESS != + sme_cfg_get_int(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + &txpow2g)) { + return -EIO; + } + hddLog(LOG1, "2G tx_power %d", txpow2g); + break; + } + + case WE_GET_TXPOW_5G: + { + uint32_t txpow5g = 0; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hddLog(LOG1, "GET WMI_PDEV_PARAM_TXPOWER_LIMIT5G"); + *value = wma_cli_get_command(pAdapter->sessionId, + WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + PDEV_CMD); + if (CDF_STATUS_SUCCESS != + sme_cfg_get_int(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + &txpow5g)) { + return -EIO; + } + hddLog(LOG1, "5G tx_power %d", txpow5g); + break; + } + + case WE_GET_POWER_GATING: + { + hddLog(LOG1, "GET WMI_PDEV_PARAM_POWER_GATING_SLEEP"); + *value = wma_cli_get_command(pAdapter->sessionId, + WMI_PDEV_PARAM_POWER_GATING_SLEEP, + PDEV_CMD); + break; + } + + case WE_GET_PPS_PAID_MATCH: + { + hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); + *value = wma_cli_get_command(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + 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(pAdapter->sessionId, + WMI_STA_PS_PARAM_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL, + QPOWER_CMD); + break; + } + + case WE_GET_TEMPERATURE: + { + hddLog(CDF_TRACE_LEVEL_INFO, "WE_GET_TEMPERATURE"); + ret = wlan_hdd_get_temperature(pAdapter, value); + break; + } + default: + { + hddLog(LOGE, "Invalid IOCTL get_value command %d", + value[0]); + break; + } + } + + return ret; +} + +static int iw_setnone_getint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_setnone_getint(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_set_three_ints_getnone() - Generic "set 3 params" private 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_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); + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (sub_cmd) { + + case WE_SET_WLAN_DBG: + cdf_trace_set_value(value[1], value[2], value[3]); + break; + case WE_SET_DP_TRACE: + cdf_dp_trace_set_value(value[1], value[2], value[3]); + break; + + /* 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. + */ + case WE_SET_SAP_CHANNELS: + if (wlan_hdd_validate_operation_channel(pAdapter, value[1]) != + CDF_STATUS_SUCCESS || + wlan_hdd_validate_operation_channel(pAdapter, + value[2]) != CDF_STATUS_SUCCESS) { + ret = -EINVAL; + } else { + hdd_ctx->config->force_sap_acs_st_ch = value[1]; + hdd_ctx->config->force_sap_acs_end_ch = value[2]; + } + break; + case WE_SET_DUAL_MAC_SCAN_CONFIG: + hdd_debug("Ioctl to set dual mac scan config"); + if (hdd_ctx->config->dual_mac_feature_disable) { + hdd_err("Dual mac feature is disabled from INI"); + return -EPERM; + } + hdd_debug("%d %d %d", value[1], value[2], value[3]); + cds_set_dual_mac_scan_config(hdd_ctx, + value[1], value[2], + value[3]); + break; + default: + hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); + break; + + } + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_three_ints_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_connection_state_string() - Get connection state string + * @connection_state: enum to be converted to a string + * + * Return: the string equivalent of @connection_state + */ +static const char * +hdd_connection_state_string(eConnectionState connection_state) +{ + switch (connection_state) { + 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 "UNKNOWN"; + } +} + +/** + * iw_get_char_setnone() - Generic "get string" private 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_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 + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (sub_cmd) { + case WE_WLAN_VERSION: + { + hdd_wlan_get_version(pAdapter, wrqu, extra); + break; + } + + case WE_GET_STATS: + { + hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + } + + /* The case prints the current state of the HDD, SME, CSR, PE, + * TL it can be extended for WDI Global State as well. And + * currently it only checks P2P_CLIENT adapter. P2P_DEVICE + * and P2P_GO have not been added as of now. + */ + case WE_GET_STATES: + { + int buf = 0, len = 0; + int adapter_num = 0; + int count = 0, check = 1; + + 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); + + + 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", + hdd_connection_state_string + (pHddStaCtx->conn_info.connState), + mac_trace_get_neighbour_roam_state + (sme_get_neighbor_roam_state + (hHal, useAdapter->sessionId)), + mac_trace_getcsr_roam_state + (sme_get_current_roam_state + (hHal, useAdapter->sessionId)), + mac_trace_getcsr_roam_sub_state + (sme_get_current_roam_sub_state + (hHal, useAdapter->sessionId)) + ); + len += buf; + adapter_num++; + } + + if (pMac) { + /* 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", + mac_trace_get_lim_sme_state + (sme_get_lim_sme_state(hHal)), + mac_trace_get_lim_mlm_state + (sme_get_lim_sme_state(hHal)) + ); + len += buf; + + /* Printing the PE Sme and Mlm states for valid lim sessions */ + while (check < 3 && count < 255) { + if (sme_is_lim_session_valid(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, + mac_trace_get_lim_sme_state + (sme_get_lim_sme_session_state + (hHal, count)), + mac_trace_get_lim_mlm_state + (sme_get_lim_mlm_session_state + (hHal, count)) + ); + + len += buf; + check++; + } + count++; + } + } + + wrqu->data.length = strlen(extra) + 1; + break; + } + + case WE_GET_CFG: + { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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: + { + int8_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[SME_AC_VO].wmmAcAccessRequired, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_VO]. + wmmAcAccessAllowed ? "YES" : "NO", + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_VO].wmmAcTspecInfo. + ts_info.direction, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_VI].wmmAcAccessRequired, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_VI]. + wmmAcAccessAllowed ? "YES" : "NO", + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_VI].wmmAcTspecInfo. + ts_info.direction, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BE].wmmAcAccessRequired, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BE]. + wmmAcAccessAllowed ? "YES" : "NO", + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BE].wmmAcTspecInfo. + ts_info.direction, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BK].wmmAcAccessRequired, + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BK]. + wmmAcAccessAllowed ? "YES" : "NO", + pAdapter->hddWmmStatus. + wmmAcStatus[SME_AC_BK].wmmAcTspecInfo. + ts_info.direction); + + wrqu->data.length = strlen(extra) + 1; + break; + } + case WE_GET_CHANNEL_LIST: + { + CDF_STATUS status; + uint8_t i, len; + char *buf; + uint8_t ubuf[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t ubuf_len = WNI_CFG_COUNTRY_CODE_LEN; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + tChannelListInfo channel_list; + + memset(&channel_list, 0, sizeof(channel_list)); + status = + iw_softap_get_channel_list(dev, info, wrqu, + (char *)&channel_list); + if (!CDF_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 ifsufficient 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 (CDF_STATUS_SUCCESS == sme_get_country_code(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->bytes[0], + pWextState->roamProfile.BSSIDs.bssid->bytes[1], + pWextState->roamProfile.BSSIDs.bssid->bytes[2], + pWextState->roamProfile.BSSIDs.bssid->bytes[3], + pWextState->roamProfile.BSSIDs.bssid->bytes[4], + pWextState->roamProfile.BSSIDs.bssid->bytes[5], + pWextState->roamProfile.MFPEnabled, + pAdapter->hdd_stats.hddPmfStats. + numUnprotDisassocRx, + pAdapter->hdd_stats.hddPmfStats. + numUnprotDeauthRx); + + wrqu->data.length = strlen(extra) + 1; + break; + } +#endif + case WE_GET_PHYMODE: + { + bool ch_bond24 = false, ch_bond5g = 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_get_config_param(hal, &smeconfig); + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + smeconfig.csrConfig.channelBondingMode24GHz) + ch_bond24 = true; + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != + smeconfig.csrConfig.channelBondingMode5GHz) + ch_bond5g = true; + + phymode = sme_get_phy_mode(hal); + if ((CDF_STATUS_SUCCESS != + sme_get_freq_band(hal, &currBand))) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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->config->vhtChannelWidth == + eHT_CHANNEL_WIDTH_20MHZ) + snprintf(extra, WE_MAX_STR_LEN, + "11ACVHT20"); + else if (hddctx->config->vhtChannelWidth == + eHT_CHANNEL_WIDTH_40MHZ) + snprintf(extra, WE_MAX_STR_LEN, + "11ACVHT40"); + else if (hddctx->config->vhtChannelWidth == + eHT_CHANNEL_WIDTH_80MHZ) + snprintf(extra, WE_MAX_STR_LEN, + "11ACVHT80"); + else if (hddctx->config->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: + { + int8_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->config->fEnableSNRMonitoring || + eConnectionState_Associated != + pHddStaCtx->conn_info.connState) { + hddLog(LOGE, + "%s: getSNR failed: Enable SNR Monitoring-%d," + " ConnectionState-%d", __func__, + pHddCtx->config->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; + } + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_get_char_setnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_setnone_getnone() - Generic "action" private 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_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; + + 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 userspace, 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_get_recovery_stats(hal); + break; + } + + case WE_SET_REASSOC_TRIGGER: + { + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint32_t roamId = 0; + tCsrRoamModifyProfileFields modProfileFields; + hdd_station_ctx_t *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* Reassoc to same AP, only supported for Open Security*/ + if ((hdd_sta_ctx->conn_info.ucEncryptionType || + hdd_sta_ctx->conn_info.mcEncryptionType)) { + hddLog(LOGE, + FL("Reassoc to same AP, only supported for Open Security")); + return -ENOTSUPP; + } + + sme_get_modify_profile_fields(hHal, pAdapter->sessionId, + &modProfileFields); + sme_roam_reassoc(hHal, pAdapter->sessionId, + NULL, modProfileFields, &roamId, 1); + return 0; + } + + case WE_DUMP_AGC_START: + { + hddLog(LOG1, "WE_DUMP_AGC_START"); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_PARAM_DUMP_AGC_START, + 0, GEN_CMD); + break; + } + case WE_DUMP_AGC: + { + hddLog(LOG1, "WE_DUMP_AGC"); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_PARAM_DUMP_AGC, + 0, GEN_CMD); + break; + } + + case WE_DUMP_CHANINFO_START: + { + hddLog(LOG1, "WE_DUMP_CHANINFO_START"); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_PARAM_DUMP_CHANINFO_START, + 0, GEN_CMD); + break; + } + case WE_DUMP_CHANINFO: + { + hddLog(LOG1, "WE_DUMP_CHANINFO_START"); + ret = wma_cli_set_command(pAdapter->sessionId, + GEN_PARAM_DUMP_CHANINFO, + 0, GEN_CMD); + break; + } + case WE_DUMP_WATCHDOG: + { + hddLog(LOG1, "WE_DUMP_WATCHDOG"); + ret = wma_cli_set_command(pAdapter->sessionId, + 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 = wma_cli_set_command(pAdapter->sessionId, + GEN_PARAM_DUMP_PCIE_ACCESS_LOG, + 0, GEN_CMD); + break; + } +#endif + default: + { + hddLog(LOGE, "%s: unknown ioctl %d", __func__, sub_cmd); + break; + } + } + + return ret; +} + +static int iw_setnone_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_setnone_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __iw_set_var_ints_getnone - Generic "set many" private ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * This is an SSR-protected generic handler for private ioctls which + * take multiple arguments. Note that this implementation is also + * somewhat unique in that it is shared by both STA-mode and SAP-mode + * interfaces. + * + * Return: 0 on success, non-zero on error + */ +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_context_t *hdd_ctx; + int ret, num_args; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + 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); + + switch (sub_cmd) { + + case WE_P2P_NOA_CMD: + { + p2p_app_setP2pPs_t p2pNoA; + + 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_set_p2p_ps(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]); + cdf_trace_enable(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]); + cdf_trace_dump_all((void *)hHal, apps_args[0], + apps_args[1], apps_args[2], + apps_args[3]); + + } + break; + + case WE_POLICY_MANAGER_CLIST_CMD: + { + hddLog(LOGE, + FL(" is called\n")); + cds_incr_connection_count_utfw(hdd_ctx, apps_args[0], + apps_args[1], apps_args[2], apps_args[3], + apps_args[4], apps_args[5], apps_args[6], + apps_args[7]); + } + break; + + case WE_POLICY_MANAGER_DLIST_CMD: + { + hddLog(LOGE, + FL(" is called\n")); + cds_decr_connection_count_utfw(hdd_ctx, apps_args[0], + apps_args[1]); + } + break; + + case WE_POLICY_MANAGER_ULIST_CMD: + { + hddLog(LOGE, + FL(" is called\n")); + cds_update_connection_info_utfw(hdd_ctx, apps_args[0], + apps_args[1], apps_args[2], apps_args[3], + apps_args[4], apps_args[5], apps_args[6], + apps_args[7]); + } + break; + + case WE_POLICY_MANAGER_DBS_CMD: + { + hddLog(LOGE, + FL(" is called\n")); + if (apps_args[0] == 0) + wma_set_dbs_capability_ut(0); + else + wma_set_dbs_capability_ut(1); + + if (apps_args[1] >= CDS_THROUGHPUT && + apps_args[1] <= CDS_LATENCY) { + pr_info("setting system pref to [%d]\n", apps_args[1]); + hdd_ctx->config->conc_system_pref = apps_args[1]; + } + } + break; + + case WE_POLICY_MANAGER_PCL_CMD: + { + uint8_t pcl[MAX_NUM_CHAN] = {0}; + uint32_t pcl_len = 0, i = 0; + + hddLog(LOGE, + FL(" is called\n")); + + cds_get_pcl(hdd_ctx, apps_args[0], + pcl, &pcl_len); + pr_info("PCL list for role[%d] is {", apps_args[0]); + for (i = 0 ; i < pcl_len; i++) + pr_info(" %d, ", pcl[i]); + pr_info("}--------->\n"); + } + break; + + case WE_POLICY_MANAGER_CINFO_CMD: + { + struct cds_conc_connection_info *conn_info; + uint32_t i = 0, len = 0; + + hddLog(LOGE, + FL(" is called\n")); + conn_info = cds_get_conn_info(hdd_ctx, &len); + pr_info("+-----------------------------+\n"); + for (i = 0; i < len; i++) { + pr_info("|table_index[%d]\t\t|\n", i); + pr_info("|\t|vdev_id - %d\t\t|\n", conn_info->vdev_id); + pr_info("|\t|tx_spatial_stream - %d\t|\n", + conn_info->tx_spatial_stream); + pr_info("|\t|rx_spatial_stream - %d\t|\n", + conn_info->rx_spatial_stream); + pr_info("|\t|chain_mask - %d\t\t|\n", + conn_info->chain_mask); + pr_info("|\t|chan - %d\t\t|\n", conn_info->chan); + pr_info("|\t|mode - %d\t\t|\n", conn_info->mode); + pr_info("|\t|mac - %d\t\t|\n", conn_info->mac); + pr_info("|\t|in_use - %d\t\t|\n", conn_info->in_use); + pr_info("+-----------------------------+\n"); + conn_info++; + } + } + break; + + case WE_POLICY_SET_HW_MODE_CMD: + { + if (apps_args[0] == 0) { + hddLog(LOGE, + FL("set hw mode for single mac\n")); + cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_0x0, HW_MODE_BW_NONE, + HW_MODE_DBS_NONE, + HW_MODE_AGILE_DFS_NONE); + } else if (apps_args[0] == 1) { + hddLog(LOGE, + FL("set hw mode for dual mac\n")); + cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE); + } + } + break; + + case WE_POLICY_MANAGER_QUERY_ACTION_CMD: + { + enum cds_conc_next_action action; + hddLog(LOGE, + FL(" is called\n")); + action = cds_current_connections_update(hdd_ctx, + apps_args[0]); + pr_info("next action is %d {HDD_NOP = 0, HDD_DBS, HDD_DBS_DOWNGRADE, HDD_MCC, HDD_MCC_UPGRADE}", action); + } + break; + case WE_POLICY_MANAGER_QUERY_ALLOW_CMD: + { + bool allow; + hddLog(LOGE, + FL(" is called\n")); + allow = cds_allow_concurrency(hdd_ctx, + apps_args[0], apps_args[1], apps_args[2]); + pr_info("allow %d {0 = don't allow, 1 = allow}", allow); + } + break; + + case WE_POLICY_MANAGER_SCENARIO_CMD: + { + clean_report(hdd_ctx); + if (apps_args[0] == 1) { + wlan_hdd_one_connection_scenario(hdd_ctx); + } else if (apps_args[0] == 2) { + wlan_hdd_two_connections_scenario(hdd_ctx, + 6, CDS_TWO_TWO); + wlan_hdd_two_connections_scenario(hdd_ctx, + 36, CDS_TWO_TWO); + wlan_hdd_two_connections_scenario(hdd_ctx, + 6, CDS_ONE_ONE); + wlan_hdd_two_connections_scenario(hdd_ctx, + 36, CDS_ONE_ONE); + } else if (apps_args[0] == 3) { + /* MCC on same band with 2x2 same mac*/ + wlan_hdd_three_connections_scenario(hdd_ctx, + 6, 11, CDS_TWO_TWO, 0); + /* MCC on diff band with 2x2 same mac*/ + wlan_hdd_three_connections_scenario(hdd_ctx, + 6, 36, CDS_TWO_TWO, 0); + /* MCC on diff band with 1x1 diff mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 6, CDS_ONE_ONE, 0); + /* MCC on diff band with 1x1 same mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 6, CDS_ONE_ONE, 1); + /* SCC on same band with 2x2 same mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 36, CDS_TWO_TWO, 0); + /* SCC on same band with 1x1 same mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 36, CDS_ONE_ONE, 1); + /* MCC on same band with 2x2 same mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 149, CDS_TWO_TWO, 0); + /* MCC on same band with 1x1 same mac */ + wlan_hdd_three_connections_scenario(hdd_ctx, + 36, 149, CDS_ONE_ONE, 1); + } + print_report(hdd_ctx); + } + 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]; + /* ignore args[3] as discovery_period is not used anymore */ + tdlsParams.discovery_tries_n = apps_args[4]; + /* ignore args[5] as idle_timeout is not used anymore */ + tdlsParams.idle_packet_n = apps_args[6]; + /* ignore args[7] as rssi_hysteresis is not used anymore */ + 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; + cds_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 = cdf_mem_malloc(sizeof(*unitTestArgs)); + if (NULL == unitTestArgs) { + hddLog(LOGE, + FL("cdf_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 (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + cdf_mem_free(unitTestArgs); + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + FL + ("Not able to post UNIT_TEST_CMD message to WMA")); + return -EINVAL; + } + } + break; +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + case WE_LED_FLASHING_PARAM: + { + int i; + if (num_args != 4) { + hddLog(LOGE, + FL("gpio_control: 4 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_set_led_flashing(WLAN_HDD_GET_HAL_CTX(pAdapter), + 0, apps_args[0], apps_args[1]); + sme_set_led_flashing(WLAN_HDD_GET_HAL_CTX(pAdapter), + 1, apps_args[2], apps_args[3]); + } + break; +#endif + default: + { + hddLog(LOGE, FL("Invalid IOCTL command %d"), sub_cmd); + } + break; + } + + 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; + + /* 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; + } + + cds_ssr_protect(__func__); + ret = __iw_set_var_ints_getnone(dev, info, &u_priv_wrqu, + (char *)&apps_args); + cds_ssr_unprotect(__func__); + return ret; +} + +/** + * iw_set_var_ints_getnone - Generic "set many" private ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * This is a generic handler for private ioctls which take multiple + * arguments. Note that this implementation is also somewhat unique + * in that it is shared by both STA-mode and SAP-mode interfaces. + * + * Return: 0 on success, non-zero on error + */ +int iw_set_var_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_set_var_ints_getnone(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + return ret; +} + +/** + * iw_add_tspec - Add TSpec private 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_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; + uint32_t handle; + struct iw_point s_priv_data; + hdd_context_t *hdd_ctx; + int ret; + + 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 priviledged */ + /* 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(CDF_TRACE_LEVEL_ERROR, "***ts_info.up out of bounds***"); + return 0; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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); + return 0; +} + +static int iw_add_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_add_tspec(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_del_tspec - Delete TSpec private 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_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); + hdd_context_t *hdd_ctx; + int *params = (int *)extra; + hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *) extra; + uint32_t handle; + int ret; + + 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 priviledged */ + /* 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); + return 0; +} + +static int iw_del_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_del_tspec(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_get_tspec - Get TSpec private 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_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_context_t *hdd_ctx; + int *params = (int *)extra; + hdd_wlan_wmm_status_e *pStatus = (hdd_wlan_wmm_status_e *) extra; + uint32_t handle; + int ret; + + 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); + return 0; +} + +static int iw_get_tspec(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_get_tspec(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/** + * iw_set_fties - Set FT IEs private ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Each time the supplicant has the auth_request or reassoc request + * IEs ready they are pushed to the driver. The driver will in turn + * use it to send out the auth req and reassoc req for 11r FT Assoc. + * + * Return: 0 on success, non-zero on error + */ +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; + + 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_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, + extra, wrqu->data.length); + + return 0; +} + +static int iw_set_fties(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_set_fties(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + +/** + * iw_set_host_offload - Set host offload 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_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; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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(CDF_TRACE_LEVEL_WARN, + "%s: Host offload request: ARP reply", __func__); + switch (pRequest->enableOrDisable) { + case WLAN_OFFLOAD_DISABLE: + hddLog(CDF_TRACE_LEVEL_WARN, " disable"); + break; + case WLAN_OFFLOAD_ARP_AND_BC_FILTER_ENABLE: + hddLog(CDF_TRACE_LEVEL_WARN, " BC Filtering enable"); + case WLAN_OFFLOAD_ENABLE: + hddLog(CDF_TRACE_LEVEL_WARN, " ARP offload enable"); + hddLog(CDF_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(CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Host offload request: neighbor discovery", + __func__); + switch (pRequest->enableOrDisable) { + case WLAN_OFFLOAD_DISABLE: + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, " disable"); + break; + case WLAN_OFFLOAD_ENABLE: + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, " enable"); + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + " IP address: %x:%x:%x:%x:%x:%x:%x:%x", + *(uint16_t *) (pRequest->params.hostIpv6Addr), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 2), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 4), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 6), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 8), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 10), + *(uint16_t *) (pRequest->params.hostIpv6Addr + + 12), + *(uint16_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 (CDF_STATUS_SUCCESS != + sme_set_host_offload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offloadRequest)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Failure to execute host offload request", __func__); + return -EINVAL; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_host_offload(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * iw_set_keepalive_params - Set keepalive params 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_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); + tpKeepAliveRequest pRequest = (tpKeepAliveRequest) extra; + tSirKeepAliveReq keepaliveRequest; + hdd_context_t *hdd_ctx; + int ret; + + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (pRequest->timePeriod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) { + hddLog(LOGE, FL("Value of timePeriod %d exceed Max limit %d"), + pRequest->timePeriod, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX); + return -EINVAL; + } + + /* Debug display of request components. */ + hddLog(CDF_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(CDF_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", + __func__); + break; + + case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP: + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Keep Alive Request: Tx UnSolicited ARP RSP", + __func__); + + hddLog(CDF_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d", + pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1], + pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]); + + hddLog(CDF_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d", + pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1], + pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]); + + hddLog(CDF_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; + } + + /* Execute keep alive 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(&keepaliveRequest, pRequest, wrqu->data.length); + + hddLog(CDF_TRACE_LEVEL_ERROR, "set Keep: TP before SME %d", + keepaliveRequest.timePeriod); + + if (CDF_STATUS_SUCCESS != + sme_set_keep_alive(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &keepaliveRequest)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Failure to execute Keep Alive", __func__); + return -EINVAL; + } + + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_keepalive_params(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +/** + * wlan_hdd_set_filter() - Set packet filter + * @hdd_ctx: Global HDD context + * @request: Packet filter request struct + * @sessionId: Target session for the request + * + * Return: 0 on success, non-zero on error + */ +static int wlan_hdd_set_filter(hdd_context_t *hdd_ctx, + struct pkt_filter_cfg *request, + uint8_t sessionId) +{ + tSirRcvPktFilterCfgType packetFilterSetReq = {0}; + tSirRcvFltPktClearParam packetFilterClrReq = {0}; + int i = 0; + + if (hdd_ctx->config->disablePacketFilter) { + hdd_err("packet filtering disabled in ini returning"); + return 0; + } + + /* Debug display of request components. */ + hdd_info("Packet Filter Request : FA %d params %d", + request->filter_action, request->num_params); + + switch (request->filter_action) { + case HDD_RCV_FILTER_SET: + hdd_info("Set Packet Filter Request for Id: %d", + request->filter_id); + + packetFilterSetReq.filterId = request->filter_id; + if (request->num_params >= HDD_MAX_CMP_PER_PACKET_FILTER) { + hdd_err("Number of Params exceed Max limit %d", + request->num_params); + return -EINVAL; + } + packetFilterSetReq.numFieldParams = request->num_params; + packetFilterSetReq.coalesceTime = 0; + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + for (i = 0; i < request->num_params; i++) { + packetFilterSetReq.paramsData[i].protocolLayer = + request->params_data[i].protocol_layer; + packetFilterSetReq.paramsData[i].cmpFlag = + request->params_data[i].compare_flag; + packetFilterSetReq.paramsData[i].dataOffset = + request->params_data[i].data_offset; + packetFilterSetReq.paramsData[i].dataLength = + request->params_data[i].data_length; + packetFilterSetReq.paramsData[i].reserved = 0; + + if (request->params_data[i].data_length > + SIR_MAX_FILTER_TEST_DATA_LEN) { + hdd_err("Error invalid data length %d", + request->params_data[i].data_length); + return -EINVAL; + } + + hdd_info("Proto %d Comp Flag %d Filter Type %d", + request->params_data[i].protocol_layer, + request->params_data[i].compare_flag, + packetFilterSetReq.filterType); + + hdd_info("Data Offset %d Data Len %d", + request->params_data[i].data_offset, + request->params_data[i].data_length); + + memcpy(&packetFilterSetReq.paramsData[i].compareData, + request->params_data[i].compare_data, + request->params_data[i].data_length); + memcpy(&packetFilterSetReq.paramsData[i].dataMask, + request->params_data[i].data_mask, + request->params_data[i].data_length); + + hdd_info("CData %d CData %d CData %d CData %d CData %d CData %d", + request->params_data[i].compare_data[0], + request->params_data[i].compare_data[1], + request->params_data[i].compare_data[2], + request->params_data[i].compare_data[3], + request->params_data[i].compare_data[4], + request->params_data[i].compare_data[5]); + + hdd_info("MData %d MData %d MData %d MData %d MData %d MData %d", + request->params_data[i].data_mask[0], + request->params_data[i].data_mask[1], + request->params_data[i].data_mask[2], + request->params_data[i].data_mask[3], + request->params_data[i].data_mask[4], + request->params_data[i].data_mask[5]); + } + + if (CDF_STATUS_SUCCESS != + sme_receive_filter_set_filter(hdd_ctx->hHal, + &packetFilterSetReq, + sessionId)) { + hdd_err("Failure to execute Set Filter"); + return -EINVAL; + } + + break; + + case HDD_RCV_FILTER_CLEAR: + + hdd_info("Clear Packet Filter Request for Id: %d", + request->filter_id); + packetFilterClrReq.filterId = request->filter_id; + if (CDF_STATUS_SUCCESS != + sme_receive_filter_clear_filter(hdd_ctx->hHal, + &packetFilterClrReq, + sessionId)) { + hdd_err("Failure to execute Clear Filter"); + return -EINVAL; + } + break; + + default: + hdd_err("Packet Filter Request: Invalid %d", + request->filter_action); + return -EINVAL; + } + return 0; +} + +/** + * __iw_set_packet_filter_params() - set packet filter parameters in target + * @dev: Pointer to netdev + * @info: Pointer to iw request info + * @wrqu: Pointer to data + * @extra: Pointer to extra data + * + * Return: 0 on success, non-zero on error + */ +static int __iw_set_packet_filter_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + hdd_context_t *hdd_ctx; + struct iw_point priv_data; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct pkt_filter_cfg *request = NULL; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + if (hdd_priv_get_data(&priv_data, wrqu)) { + hdd_err("failed to get priv data"); + return -EINVAL; + } + + if ((NULL == priv_data.pointer) || (0 == priv_data.length)) { + hdd_err("invalid priv data %p or invalid priv data length %d", + priv_data.pointer, priv_data.length); + return -EINVAL; + } + + /* copy data using copy_from_user */ + request = mem_alloc_copy_from_user_helper(priv_data.pointer, + priv_data.length); + if (NULL == request) { + hdd_err("mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + ret = wlan_hdd_set_filter(hdd_ctx, request, adapter->sessionId); + + kfree(request); + + return ret; +} + +/** + * iw_set_packet_filter_params() - set packet filter parameters in target + * @dev: Pointer to netdev + * @info: Pointer to iw request info + * @wrqu: Pointer to data + * @extra: Pointer to extra data + * + * Return: 0 on success, non-zero on error + */ +static int iw_set_packet_filter_params(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_set_packet_filter_params(dev, info, wrqu, extra); + cds_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) +{ + + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_wext_state_t *pWextState; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + char *p = extra; + int tlen = 0; + tCsrSummaryStatsInfo *pStats = &(pAdapter->hdd_stats.summary_stat); + tCsrGlobalClassAStatsInfo *aStats = &(pAdapter->hdd_stats.ClassA_stat); + tCsrGlobalClassDStatsInfo *dStats = &(pAdapter->hdd_stats.ClassD_stat); + int ret; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + 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_get_statistics(hdd_ctx->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_statistics_cb, 0, false, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + pAdapter, pAdapter->sessionId); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: Unable to retrieve SME statistics", + __func__); + return -EINVAL; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + + cdf_status = + cdf_wait_single_event(&pWextState->hdd_cdf_event, + WLAN_WAIT_TIME_STATS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s: SME timeout while retrieving statistics", + __func__); + /*Remove the SME statistics list by passing NULL in callback argument */ + status = sme_get_statistics(hdd_ctx->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, (uint8_t) WLAN_STATS_RETRY_CNT, + (uint8_t) sizeof(pStats->retry_cnt), + (char *)&(pStats->retry_cnt[0]), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_MUL_RETRY_CNT, + (uint8_t) sizeof(pStats->multiple_retry_cnt), + (char *)&(pStats->multiple_retry_cnt[0]), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_FRM_CNT, + (uint8_t) sizeof(pStats->tx_frm_cnt), + (char *)&(pStats->tx_frm_cnt[0]), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_FRM_CNT, + (uint8_t) sizeof(pStats->rx_frm_cnt), + (char *)&(pStats->rx_frm_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_FRM_DUP_CNT, + (uint8_t) sizeof(pStats->frm_dup_cnt), + (char *)&(pStats->frm_dup_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_FAIL_CNT, + (uint8_t) sizeof(pStats->fail_cnt), + (char *)&(pStats->fail_cnt[0]), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RTS_FAIL_CNT, + (uint8_t) sizeof(pStats->rts_fail_cnt), + (char *)&(pStats->rts_fail_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_ACK_FAIL_CNT, + (uint8_t) sizeof(pStats->ack_fail_cnt), + (char *)&(pStats->ack_fail_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RTS_SUC_CNT, + (uint8_t) sizeof(pStats->rts_succ_cnt), + (char *)&(pStats->rts_succ_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_DISCARD_CNT, + (uint8_t) sizeof(pStats->rx_discard_cnt), + (char *)&(pStats->rx_discard_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_ERROR_CNT, + (uint8_t) sizeof(pStats->rx_error_cnt), + (char *)&(pStats->rx_error_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_BYTE_CNT, + (uint8_t) sizeof(dStats->tx_uc_byte_cnt[0]), + (char *)&(dStats->tx_uc_byte_cnt[0]), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_BYTE_CNT, + (uint8_t) sizeof(dStats->rx_byte_cnt), + (char *)&(dStats->rx_byte_cnt), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_RATE, + (uint8_t) sizeof(dStats->rx_rate), + (char *)&(dStats->rx_rate), tlen); + + /* Transmit rate, in units of 500 kbit/sec */ + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_RATE, + (uint8_t) sizeof(aStats->tx_rate), + (char *)&(aStats->tx_rate), tlen); + + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_UC_BYTE_CNT, + (uint8_t) sizeof(dStats->rx_uc_byte_cnt[0]), + (char *)&(dStats->rx_uc_byte_cnt[0]), tlen); + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_MC_BYTE_CNT, + (uint8_t) sizeof(dStats->rx_mc_byte_cnt), + (char *)&(dStats->rx_mc_byte_cnt), tlen); + FILL_TLV(p, (uint8_t) WLAN_STATS_RX_BC_BYTE_CNT, + (uint8_t) sizeof(dStats->rx_bc_byte_cnt), + (char *)&(dStats->rx_bc_byte_cnt), tlen); + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_UC_BYTE_CNT, + (uint8_t) sizeof(dStats->tx_uc_byte_cnt[0]), + (char *)&(dStats->tx_uc_byte_cnt[0]), tlen); + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_MC_BYTE_CNT, + (uint8_t) sizeof(dStats->tx_mc_byte_cnt), + (char *)&(dStats->tx_mc_byte_cnt), tlen); + FILL_TLV(p, (uint8_t) WLAN_STATS_TX_BC_BYTE_CNT, + (uint8_t) 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; + + cds_ssr_protect(__func__); + ret = __iw_get_statistics(dev, info, wrqu, extra); + cds_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(CDF_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); + +} + +/** + * __iw_set_pno() - Preferred Network Offload ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * This function parses a Preferred Network Offload command + * Input is string based and expected to be of the form: + * + * + * when enabling: + * + * for each network: + * + * + * + * for each timer: + * + * + * + * 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 1 + * + * this translates into: + * ----------------------------- + * enable PNO + * 2 networks + * Network 1: + * test - with authentication type 0 and encryption type 0, + * search 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 + * Network 2: + * test2 - with authentication type 4 and encryption type 4, + * search 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 + * 2 scan timers: + * scan every 5 seconds 2 times + * then scan every 300 seconds until stopped + * enable on suspend + */ +static int __iw_set_pno(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 ret; + int offset; + char *ptr; + uint8_t i, j, params, mode; + + /* request 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 request; + + ENTER(); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + hdd_notice("PNO data len %d data %s", wrqu->data.length, extra); + + request.enable = 0; + request.ucNetworksCount = 0; + + ptr = extra; + + if (1 != sscanf(ptr, "%hhu%n", &(request.enable), &offset)) { + hdd_err("PNO enable input is not valid %s", ptr); + return -EINVAL; + } + + if (0 == request.enable) { + /* Disable PNO, ignore any other params */ + memset(&request, 0, sizeof(request)); + sme_set_preferred_network_list(WLAN_HDD_GET_HAL_CTX(adapter), + &request, adapter->sessionId, + found_pref_network_cb, adapter); + return 0; + } + + ptr += offset; + + if (1 != + sscanf(ptr, "%hhu %n", &(request.ucNetworksCount), &offset)) { + hdd_err("PNO count input not valid %s", ptr); + return -EINVAL; + + } + + hdd_info("PNO enable %d networks count %d offset %d", + request.enable, request.ucNetworksCount, offset); + + if ((0 == request.ucNetworksCount) || + (request.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS)) { + hdd_err("Network count %d invalid", + request.ucNetworksCount); + return -EINVAL; + } + + ptr += offset; + + for (i = 0; i < request.ucNetworksCount; i++) { + + request.aNetworks[i].ssId.length = 0; + + params = sscanf(ptr, "%hhu %n", + &(request.aNetworks[i].ssId.length), + &offset); + + if (1 != params) { + hdd_err("PNO ssid length input is not valid %s", ptr); + return -EINVAL; + } + + if ((0 == request.aNetworks[i].ssId.length) || + (request.aNetworks[i].ssId.length > 32)) { + hdd_err("SSID Len %d is not correct for network %d", + request.aNetworks[i].ssId.length, i); + return -EINVAL; + } + + /* Advance to SSID */ + ptr += offset; + + memcpy(request.aNetworks[i].ssId.ssId, ptr, + request.aNetworks[i].ssId.length); + ptr += request.aNetworks[i].ssId.length; + + params = sscanf(ptr, "%u %u %hhu %n", + &(request.aNetworks[i].authentication), + &(request.aNetworks[i].encryption), + &(request.aNetworks[i].ucChannelCount), + &offset); + + if (3 != params) { + hdd_warn("Incorrect cmd %s", ptr); + return -EINVAL; + } + + hdd_notice("PNO len %d ssid %.*s auth %d encry %d channel count %d offset %d", + request.aNetworks[i].ssId.length, + request.aNetworks[i].ssId.length, + request.aNetworks[i].ssId.ssId, + request.aNetworks[i].authentication, + request.aNetworks[i].encryption, + request.aNetworks[i].ucChannelCount, offset); + + /* Advance to channel list */ + ptr += offset; + + if (SIR_PNO_MAX_NETW_CHANNELS < + request.aNetworks[i].ucChannelCount) { + hdd_warn("Incorrect number of channels"); + return -EINVAL; + } + + if (0 != request.aNetworks[i].ucChannelCount) { + for (j = 0; j < request.aNetworks[i].ucChannelCount; + j++) { + if (1 != + sscanf(ptr, "%hhu %n", + &(request.aNetworks[i]. + aChannels[j]), &offset)) { + hdd_err("PNO network channel input is not valid %s", + ptr); + return -EINVAL; + } + /* Advance to next channel number */ + ptr += offset; + } + } + + if (1 != sscanf(ptr, "%u %n", + &(request.aNetworks[i].bcastNetwType), + &offset)) { + hdd_err("PNO broadcast network type input is not valid %s", + ptr); + return -EINVAL; + } + + hdd_notice("PNO bcastNetwType %d offset %d", + request.aNetworks[i].bcastNetwType, offset); + + /* Advance to rssi Threshold */ + ptr += offset; + if (1 != sscanf(ptr, "%d %n", + &(request.aNetworks[i].rssiThreshold), + &offset)) { + hdd_err("PNO rssi threshold input is not valid %s", + ptr); + return -EINVAL; + } + hdd_notice("PNO rssi %d offset %d", + request.aNetworks[i].rssiThreshold, offset); + /* Advance to next network */ + ptr += offset; + } /* For ucNetworkCount */ + + params = sscanf(ptr, "%hhu %n", + &(request.scanTimers.ucScanTimersCount), &offset); + + /* Read the scan timers */ + if ((1 == params) && (request.scanTimers.ucScanTimersCount > 0)) { + ptr += offset; + + hdd_notice("Scan timer count %d offset %d", + request.scanTimers.ucScanTimersCount, offset); + + if (SIR_PNO_MAX_SCAN_TIMERS < + request.scanTimers.ucScanTimersCount) { + hdd_err("Incorrect cmd - too many scan timers"); + return -EINVAL; + } + + for (i = 0; i < request.scanTimers.ucScanTimersCount; i++) { + params = sscanf(ptr, "%u %u %n", + &(request.scanTimers. + aTimerValues[i].uTimerValue), + &(request.scanTimers. + aTimerValues[i].uTimerRepeat), + &offset); + + if (2 != params) { + hdd_err("Incorrect cmd - diff params then expected %d", + params); + return -EINVAL; + } + + hdd_notice("PNO Timer value %d Timer repeat %d offset %d", + request.scanTimers.aTimerValues[i]. + uTimerValue, + request.scanTimers.aTimerValues[i]. + uTimerRepeat, offset); + + ptr += offset; + } + + } else { + hdd_notice("No scan timers provided param count %d scan timers %d", + params, request.scanTimers.ucScanTimersCount); + + /* Scan timers defaults to 5 minutes */ + request.scanTimers.ucScanTimersCount = 1; + request.scanTimers.aTimerValues[0].uTimerValue = 60; + request.scanTimers.aTimerValues[0].uTimerRepeat = 0; + } + + params = sscanf(ptr, "%hhu %n", &(mode), &offset); + + request.modePNO = mode; + /* for LA we just expose suspend option */ + if ((1 != params) || (mode >= SIR_PNO_MODE_MAX)) { + request.modePNO = SIR_PNO_MODE_ON_SUSPEND; + } + + sme_set_preferred_network_list(WLAN_HDD_GET_HAL_CTX(adapter), + &request, + adapter->sessionId, + found_pref_network_cb, adapter); + + return 0; +} + +static int iw_set_pno(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_set_pno(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif /* FEATURE_WLAN_SCAN_PNO */ + +/* Common function to SetBand */ +int hdd_set_band(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; + + CDF_STATUS status; + hdd_context_t *pHddCtx; + hdd_adapter_list_node_t *pAdapterNode, *pNext; + eCsrBand currBand = eCSR_BAND_MAX; + eCsrBand connectedBand; + + 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; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: change band to %u", __func__, band); + + if (band == eCSR_BAND_MAX) { + /* Received change band request with invalid band value */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid band value %u", __func__, ui_band); + return -EINVAL; + } + + if ((band == eCSR_BAND_24 && pHddCtx->config->nBandCapability == 2) || + (band == eCSR_BAND_5G && pHddCtx->config->nBandCapability == 1)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: band value %u violate INI settings %u", __func__, + band, pHddCtx->config->nBandCapability); + return -EIO; + } + + if (band == eCSR_BAND_ALL) { + hddLog(LOG1, + FL("Auto band received. Setting band same as ini value %d"), + pHddCtx->config->nBandCapability); + band = pHddCtx->config->nBandCapability; + } + + if (CDF_STATUS_SUCCESS != sme_get_freq_band(hHal, &currBand)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Current band value = %u, new setting %u ", + __func__, currBand, band); + + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); + while (NULL != pAdapterNode && CDF_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_conn_get_connected_band + (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_conn_is_connected + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) + && (connectedBand != band)) { + CDF_STATUS status = CDF_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 in 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_roam_disconnect(WLAN_HDD_GET_HAL_CTX + (pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + + if (CDF_STATUS_SUCCESS != status) { + hddLog(CDF_TRACE_LEVEL_ERROR, + "%s csr_roam_disconnect 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(CDF_TRACE_LEVEL_ERROR, + "%s:Timeout while waiting for csr_roam_disconnect", + __func__); + return -ETIMEDOUT; + } + } + + sme_scan_flush_result(hHal); + + status = + hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (CDF_STATUS_SUCCESS != + sme_set_freq_band(hHal, pAdapter->sessionId, band)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, + FL("Failed to set the band value to %u"), + band); + return -EINVAL; + } + wlan_hdd_cfg80211_update_band(pHddCtx->wiphy, (eCsrBand) band); + } + return 0; +} + +int hdd_set_band_helper(struct net_device *dev, const char *command) +{ + uint8_t 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_set_band(dev, band); +} + +static int __iw_set_band_config(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int *value = (int *)extra; + + ENTER(); + + return hdd_set_band(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; + + cds_ssr_protect(__func__); + ret = __iw_set_band_config(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +static int __iw_set_two_ints_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int *value = (int *)extra; + int sub_cmd = value[0]; + int ret; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + switch (sub_cmd) { + case WE_SET_SMPS_PARAM: + hddLog(LOG1, "WE_SET_SMPS_PARAM val %d %d", value[1], value[2]); + ret = wma_cli_set_command(pAdapter->sessionId, + 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]); + ret = wma_cli_set2_command(pAdapter->sessionId, + GEN_PARAM_CRASH_INJECT, + value[1], value[2], GEN_CMD); + break; +#endif + case WE_SET_DUAL_MAC_FW_MODE_CONFIG: + hdd_debug("Ioctl to set dual fw mode config"); + if (hdd_ctx->config->dual_mac_feature_disable) { + hdd_err("Dual mac feature is disabled from INI"); + return -EPERM; + } + hdd_debug("%d %d", value[1], value[2]); + cds_set_dual_mac_fw_mode_config(hdd_ctx, + value[1], value[2]); + break; + case WE_DUMP_DP_TRACE_LEVEL: + hdd_info("WE_DUMP_DP_TRACE_LEVEL: %d %d", + value[1], value[2]); + if (value[1] == DUMP_DP_TRACE) + cdf_dp_trace_dump_all(value[2]); + break; + 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; + + cds_ssr_protect(__func__); + ret = __iw_set_two_ints_getnone(dev, info, wrqu, extra); + cds_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) 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) 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_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, +#endif + [WLAN_SET_BAND_CONFIG - SIOCIWFIRSTPRIV] = iw_set_band_config, + [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed, + [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_SCAN_DISABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "scan_disable"}, + + {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"}, + + {WE_SET_POWER_GATING, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "pwrgating"}, + + /* 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"}, + + /* 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"}, + + {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"}, + + {WLAN_PRIV_SET_NONE_GET_INT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + ""}, + + /* 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_POWER_GATING, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_pwrgating"}, + + {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_TEMPERATURE, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_temp"}, + /* 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"}, + + /* handlers for sub-ioctl */ + {WE_SET_DP_TRACE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "set_dp_trace"}, + + {WE_SET_SAP_CHANNELS, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "setsapchannels"}, + + {WE_SET_DUAL_MAC_SCAN_CONFIG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + 0, + "set_scan_cfg"}, + + /* handlers for main ioctl */ + {WLAN_PRIV_GET_CHAR_SET_NONE, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + ""}, + + /* handlers for sub-ioctl */ + {WE_WLAN_VERSION, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "version"}, + {WE_GET_STATS, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getStats"}, + {WE_GET_STATES, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getHostStates"}, + {WE_GET_CFG, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getConfig"}, +#ifdef WLAN_FEATURE_11AC + {WE_GET_RSSI, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getRSSI"}, +#endif + {WE_GET_WMM_STATUS, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getWmmStatus"}, + { + WE_GET_CHANNEL_LIST, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getChannelList" + }, +#ifdef FEATURE_WLAN_TDLS + { + WE_GET_TDLS_PEERS, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getTdlsPeers" + }, +#endif +#ifdef WLAN_FEATURE_11W + { + WE_GET_11W_INFO, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getPMFInfo" + }, +#endif + + {WE_GET_PHYMODE, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getphymode"}, +#ifdef FEATURE_OEM_DATA_SUPPORT + {WE_GET_OEM_DATA_CAP, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getOemDataCap"}, +#endif /* FEATURE_OEM_DATA_SUPPORT */ + {WE_GET_SNR, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getSNR"}, + + /* handlers for main ioctl */ + {WLAN_PRIV_SET_NONE_GET_NONE, + 0, + 0, + ""}, + + {WE_GET_RECOVERY_STAT, + 0, + 0, + "getRecoverStat"}, + { + 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_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"}, +#ifdef MPC_UT_FRAMEWORK + {WE_POLICY_MANAGER_CLIST_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_clist"}, + + {WE_POLICY_MANAGER_DLIST_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_dlist"}, + + {WE_POLICY_MANAGER_DBS_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_dbs"}, + + {WE_POLICY_MANAGER_PCL_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_pcl"}, + + {WE_POLICY_MANAGER_CINFO_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_cinfo"}, + + {WE_POLICY_MANAGER_ULIST_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_ulist"}, + + {WE_POLICY_MANAGER_QUERY_ACTION_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_query_action"}, + + {WE_POLICY_MANAGER_QUERY_ALLOW_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_query_allow"}, + + {WE_POLICY_MANAGER_SCENARIO_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_run_scenario"}, + + {WE_POLICY_SET_HW_MODE_CMD, + IW_PRIV_TYPE_INT | MAX_VAR_ARGS, + 0, + "pm_set_hw_mode"}, +#endif +#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 + /* 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 | WE_MAX_STR_LEN, + 0, + "setKeepAlive" + } + , +#ifdef WLAN_FEATURE_PACKET_FILTERING + { + WLAN_SET_PACKET_FILTER_PARAMS, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | + sizeof(struct pkt_filter_cfg), + 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" + } + , + { + 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 + {WE_SET_DUAL_MAC_FW_MODE_CONFIG, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_fw_mode_cfg"} + , + {WE_DUMP_DP_TRACE_LEVEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "dump_dp_trace"} + , +}; + +const struct iw_handler_def we_handler_def = { + .num_standard = CDF_ARRAY_SIZE(we_handler), + .num_private = CDF_ARRAY_SIZE(we_private), + .num_private_args = CDF_ARRAY_SIZE(we_private_args), + + .standard = (iw_handler *) we_handler, + .private = (iw_handler *) we_private, + .private_args = we_private_args, + .get_wireless_stats = NULL, +}; + +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_clear_roam_profile_ie(pAdapter); + + return CDF_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); + CDF_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 (!CDF_IS_STATUS_SUCCESS(status)) { + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + ("ERROR: hdd_set_wext failed!!")); + return CDF_STATUS_E_FAILURE; + } + + if (!CDF_IS_STATUS_SUCCESS(cdf_event_init(&pwextBuf->hdd_cdf_event))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + ("ERROR: HDD cdf event init failed!!")); + return CDF_STATUS_E_FAILURE; + } + + if (!CDF_IS_STATUS_SUCCESS(cdf_event_init(&pwextBuf->scanevent))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + ("ERROR: HDD scan event init failed!!")); + return CDF_STATUS_E_FAILURE; + } + /* Register as a wireless device */ + dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def; + + EXIT(); + return 0; +} + +int hdd_unregister_wext(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/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c new file mode 100644 index 000000000000..cdc1863ff40e --- /dev/null +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -0,0 +1,2590 @@ +/* + * 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: HDD WMM + * + * 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 priortization. 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 + +/* change logging behavior based upon debug flag */ +#ifdef HDD_WMM_DEBUG +#define WMM_TRACE_LEVEL_FATAL CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_ERROR CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_WARN CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO_HIGH CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_INFO_LOW CDF_TRACE_LEVEL_FATAL +#else +#define WMM_TRACE_LEVEL_FATAL CDF_TRACE_LEVEL_FATAL +#define WMM_TRACE_LEVEL_ERROR CDF_TRACE_LEVEL_ERROR +#define WMM_TRACE_LEVEL_WARN CDF_TRACE_LEVEL_WARN +#define WMM_TRACE_LEVEL_INFO CDF_TRACE_LEVEL_INFO +#define WMM_TRACE_LEVEL_INFO_HIGH CDF_TRACE_LEVEL_INFO_HIGH +#define WMM_TRACE_LEVEL_INFO_LOW CDF_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 uint8_t hdd_wmm_up_to_ac_map[] = { + SME_AC_BE, + SME_AC_BK, + SME_AC_BK, + SME_AC_BE, + SME_AC_VI, + SME_AC_VI, + SME_AC_VO, + SME_AC_VO +}; + +/** + * enum hdd_wmm_linuxac: AC/Queue Index values for Linux Qdisc to + * operate on different traffic. + */ +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +enum hdd_wmm_linuxac { + HDD_LINUX_AC_VO = 0, + HDD_LINUX_AC_VI = 1, + HDD_LINUX_AC_BE = 2, + HDD_LINUX_AC_BK = 3, + HDD_LINUX_AC_HI_PRIO = 4, +}; + +void wlan_hdd_process_peer_unauthorised_pause(hdd_adapter_t *adapter) +{ + /* Enable HI_PRIO queue */ + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VO); + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_VI); + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BE); + netif_stop_subqueue(adapter->dev, HDD_LINUX_AC_BK); + netif_wake_subqueue(adapter->dev, HDD_LINUX_AC_HI_PRIO); + +} +#else +enum hdd_wmm_linuxac { + HDD_LINUX_AC_VO = 0, + HDD_LINUX_AC_VI = 1, + HDD_LINUX_AC_BE = 2, + HDD_LINUX_AC_BK = 3 +}; + +void wlan_hdd_process_peer_unauthorised_pause(hdd_adapter_t *adapter) +{ + return; +} +#endif + +/* Linux based UP -> AC Mapping */ +const uint8_t hdd_linux_up_to_ac_map[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 +/** + * hdd_wmm_enable_tl_uapsd() - function which decides whether and + * how to update UAPSD parameters in TL + * + * @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; + sme_ac_enum_type acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + CDF_STATUS status; + uint32_t service_interval; + uint32_t suspension_interval; + sme_QosWmmDirType direction; + bool psb; + + /* The TSPEC must be valid */ + if (pAc->wmmAcTspecValid == false) { + CDF_TRACE(CDF_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 */ + CDF_TRACE(CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: No change in U-APSD parameters", __func__); + return; + } + /* everything is in place to notify TL */ + status = + sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))->pcds_context, + (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, + pHddCtx->config->DelayedTriggerFrmInt); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_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 = true; + pAc->wmmAcUapsdServiceInterval = service_interval; + pAc->wmmAcUapsdSuspensionInterval = suspension_interval; + pAc->wmmAcUapsdDirection = direction; + pAc->wmmAcIsUapsdEnabled = psb; + + CDF_TRACE(CDF_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); + +} + +/** + * hdd_wmm_disable_tl_uapsd() - function which decides whether + * to disable UAPSD parameters in TL + * + * @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; + sme_ac_enum_type acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + CDF_STATUS status; + uint32_t service_interval; + uint32_t suspension_interval; + uint8_t uapsd_mask; + uint8_t active_tspec = INVALID_TSPEC; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + struct hdd_config *cfg = hdd_ctx->config; + + /* have we previously enabled UAPSD? */ + if (pAc->wmmAcUapsdInfoValid == true) { + uapsd_mask = cfg->UapsdMask; + /* Finding uapsd_mask as per AC */ + uapsd_mask = uapsd_mask & (1 << (SME_AC_VO - acType)); + + sme_qos_tspec_active( + (tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), acType, + pAdapter->sessionId, &active_tspec); + + /* Call sme_enable_uapsd_for_ac only when static uapsd mask + * is present and no active tspecs. + */ + + if (uapsd_mask && !active_tspec) { + switch (acType) { + case SME_AC_VO: + service_interval = cfg->InfraUapsdVoSrvIntv; + suspension_interval = cfg->InfraUapsdVoSuspIntv; + break; + case SME_AC_VI: + service_interval = cfg->InfraUapsdViSrvIntv; + suspension_interval = cfg->InfraUapsdViSuspIntv; + break; + case SME_AC_BE: + service_interval = cfg->InfraUapsdBeSrvIntv; + suspension_interval = cfg->InfraUapsdBeSuspIntv; + break; + case SME_AC_BK: + service_interval = cfg->InfraUapsdBkSrvIntv; + suspension_interval = cfg->InfraUapsdBkSuspIntv; + break; + default: + return; + } + + /* restore the UAPSD intervals configuration */ + status = sme_enable_uapsd_for_ac(hdd_ctx->pcds_context, + (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, + pAc->wmmAcTspecInfo.ts_info.direction, + pAc->wmmAcTspecInfo.ts_info.psb, + pAdapter->sessionId, + cfg->DelayedTriggerFrmInt); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to set U-APSD for AC=%d", + acType); + } else { + /* TL no longer has valid UAPSD info */ + pAc->wmmAcUapsdInfoValid = false; + hdd_err("Disabled UAPSD in TL for AC=%d", + acType); + } + } + } +} + +#endif + +/** + * hdd_wmm_free_context() - function which frees a QoS context + * + * @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; + + CDF_TRACE(CDF_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 +/** + * hdd_wmm_notify_app() - function which notifies an application + * of changes in state of it flow + * + * @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]; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", __func__, pQosContext); + + if (unlikely((NULL == pQosContext) || + (HDD_WMM_CTX_MAGIC != pQosContext->magic))) { + CDF_TRACE(CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Sending [%s]", __func__, buf); + wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +} + +#ifdef FEATURE_WLAN_ESE +/** + * hdd_wmm_inactivity_timer_cb() - inactivity timer callback function + * + * @user_data: opaque user data registered with the timer. In the + * case of this timer, the associated wmm QoS context is registered. + * + * This timer handler function is called for every inactivity interval + * per AC. This function gets the current transmitted packets on the + * given AC, and checks if there was any TX activity from the previous + * interval. If there was no traffic then it would delete the TS that + * was negotiated on that AC. + * + * Return: None + */ +static void hdd_wmm_inactivity_timer_cb(void *user_data) +{ + hdd_wmm_qos_context_t *pQosContext = user_data; + hdd_adapter_t *pAdapter; + hdd_wmm_ac_status_t *pAc; + hdd_wlan_wmm_status_e status; + CDF_STATUS cdf_status; + uint32_t currentTrafficCnt = 0; + sme_ac_enum_type acType = pQosContext->acType; + + pAdapter = pQosContext->pAdapter; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + /* Get the Tx stats for this AC. */ + currentTrafficCnt = + pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[pQosContext-> + acType]; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + FL( + "WMM inactivity Timer for AC=%d, currentCnt=%d, prevCnt=%d" + ), + acType, (int)currentTrafficCnt, (int)pAc->wmmPrevTrafficCnt); + if (pAc->wmmPrevTrafficCnt == currentTrafficCnt) { + /* there is no traffic activity, delete the TSPEC for this AC */ + status = hdd_wmm_delts(pAdapter, pQosContext->handle); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 == CDF_TIMER_STATE_STOPPED) { + /* Restart the timer */ + cdf_status = + cdf_mc_timer_start(&pAc->wmmInactivityTimer, + pAc->wmmInactivityTime); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_ERROR, + FL( + "Restarting inactivity timer failed on AC %d" + ), + acType); + } + } else { + CDF_ASSERT(cdf_mc_timer_get_current_state + (&pAc->wmmInactivityTimer) == + CDF_TIMER_STATE_STOPPED); + } + } + + return; +} + +/** + * hdd_wmm_enable_inactivity_timer() - + * function to enable the traffic inactivity timer for the given AC + * + * @pQosContext: [in] pointer to pQosContext + * @inactivityTime: [in] value of the inactivity interval in millisecs + * + * When a QoS-Tspec is successfully setup, if the inactivity interval + * time specified in the AddTS parameters is non-zero, this function + * is invoked to start a traffic inactivity timer for the given AC. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +hdd_wmm_enable_inactivity_timer(hdd_wmm_qos_context_t *pQosContext, + uint32_t inactivityTime) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + hdd_adapter_t *pAdapter = pQosContext->pAdapter; + sme_ac_enum_type acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc; + + pAdapter = pQosContext->pAdapter; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + cdf_status = cdf_mc_timer_init(&pAc->wmmInactivityTimer, + CDF_TIMER_TYPE_SW, + hdd_wmm_inactivity_timer_cb, + pQosContext); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Initializing inactivity timer failed on AC %d"), + acType); + return cdf_status; + } + /* Start the inactivity timer */ + cdf_status = cdf_mc_timer_start(&pAc->wmmInactivityTimer, + inactivityTime); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("Starting inactivity timer failed on AC %d"), + acType); + cdf_status = cdf_mc_timer_destroy(&pAc->wmmInactivityTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hdd_err("Failed to destroy inactivity timer"); + } + return cdf_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 cdf_status; +} + +/** + * hdd_wmm_disable_inactivity_timer() - + * function to disable the traffic inactivity timer for the given AC. + * + * @pQosContext: [in] pointer to pQosContext + * + * This function is invoked to disable the traffic inactivity timer + * for the given AC. This is normally done when the TS is deleted. + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS +hdd_wmm_disable_inactivity_timer(hdd_wmm_qos_context_t *pQosContext) +{ + hdd_adapter_t *pAdapter = pQosContext->pAdapter; + sme_ac_enum_type acType = pQosContext->acType; + hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + CDF_STATUS cdf_status = CDF_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; + cdf_status = cdf_mc_timer_stop(&pAc->wmmInactivityTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hdd_err("Failed to stop inactivity timer"); + return cdf_status; + } + cdf_status = cdf_mc_timer_destroy(&pAc->wmmInactivityTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + hdd_err("Failed to destroy inactivity timer:Timer started"); + } + + return cdf_status; +} +#endif /* FEATURE_WLAN_ESE */ + +/** + * hdd_wmm_sme_callback() - callback for QoS notifications + * + * @hHal: [in] the HAL handle + * @hddCtx : [in] the HDD specified handle + * @pCurrentQosInfo : [in] the TSPEC params + * @smeStatus : [in] the QoS related SME status + * @qosFlowId: [in] the unique identifier of the flow + * + * This callback is 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). + * + * Return: CDF_STATUS enumeration + */ +static CDF_STATUS hdd_wmm_sme_callback(tHalHandle hHal, + void *hddCtx, + sme_QosWmmTspecInfo *pCurrentQosInfo, + sme_QosStatusType smeStatus, + uint32_t qosFlowId) +{ + hdd_wmm_qos_context_t *pQosContext = hddCtx; + hdd_adapter_t *pAdapter; + sme_ac_enum_type acType; + hdd_wmm_ac_status_t *pAc; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", __func__, pQosContext); + + if (unlikely((NULL == pQosContext) || + (HDD_WMM_CTX_MAGIC != pQosContext->magic))) { + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid QoS Context", __func__); + return CDF_STATUS_E_FAILURE; + } + + pAdapter = pQosContext->pAdapter; + acType = pQosContext->acType; + pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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 = true; + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo)); + } + pAc->wmmAcAccessAllowed = true; + pAc->wmmAcAccessGranted = true; + pAc->wmmAcAccessPending = false; + pAc->wmmAcAccessFailed = false; + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + + CDF_TRACE(CDF_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) { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setup is complete (U-APSD set previously)", + __func__); + + pAc->wmmAcAccessAllowed = true; + pAc->wmmAcAccessGranted = true; + pAc->wmmAcAccessPending = false; + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup failed", __func__); + /* QoS setup failed */ + + pAc->wmmAcAccessPending = false; + pAc->wmmAcAccessFailed = true; + pAc->wmmAcAccessAllowed = false; + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + + CDF_TRACE(CDF_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 now + * it has no information for this flow. + */ + hdd_wmm_free_context(pQosContext); + break; + + case SME_QOS_STATUS_SETUP_INVALID_PARAMS_RSP: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup Invalid Params, notify TL", __func__); + /* QoS setup failed */ + pAc->wmmAcAccessAllowed = false; + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) { + + /* 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 = false; + pAc->wmmAcAccessFailed = true; + pAc->wmmAcAccessAllowed = true; + + } else { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup failed, not a QoS AP", __func__); + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Setup modified", __func__); + if (pCurrentQosInfo) { + /* update the TSPEC */ + pAc->wmmAcTspecValid = true; + memcpy(&pAc->wmmAcTspecInfo, + pCurrentQosInfo, sizeof(pAc->wmmAcTspecInfo)); + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + CDF_TRACE(CDF_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) { + + /* this was triggered by implicit QoS so we + * know packets are pending + */ + pAc->wmmAcAccessPending = false; + pAc->wmmAcAccessGranted = true; + pAc->wmmAcAccessAllowed = true; + + } else { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Setup successful but U-APSD failed", __func__); + + if (HDD_WMM_HANDLE_IMPLICIT == pQosContext->handle) { + + /* 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 = true; + pAc->wmmAcAccessAllowed = true; + pAc->wmmAcAccessFailed = false; + pAc->wmmAcAccessPending = false; + + } else { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Release is complete", __func__); + + if (pCurrentQosInfo) { + CDF_TRACE(CDF_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 { + CDF_TRACE(CDF_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 = false; + + /* DELTS is successful, do not allow */ + pAc->wmmAcAccessAllowed = false; + + /* need to tell TL to update its UAPSD handling */ + hdd_wmm_disable_tl_uapsd(pQosContext); + } + + if (HDD_WMM_HANDLE_IMPLICIT != pQosContext->handle) { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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) { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: QOS Lost indication received", __func__); + + /* current TSPEC is no longer valid */ + pAc->wmmAcTspecValid = false; + /* AP has sent DELTS, do not allow */ + pAc->wmmAcAccessAllowed = 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 = false; + pAc->wmmAcAccessFailed = false; + } else { + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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 = 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: + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_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: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus); + CDF_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 = 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 = true; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: complete, access for TL AC %d is%sallowed", + __func__, acType, pAc->wmmAcAccessAllowed ? " " : " not "); + + return CDF_STATUS_SUCCESS; +} +#endif + +/** + * hdd_wmmps_helper() - Function to set uapsd psb dynamically + * + * @pAdapter: [in] pointer to adapter structure + * @ptr: [in] pointer to command buffer + * + * Return: Zero on success, appropriate error on failure. + */ +int hdd_wmmps_helper(hdd_adapter_t *pAdapter, uint8_t *ptr) +{ + if (NULL == pAdapter) { + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return -EINVAL; + } + if (NULL == ptr) { + CDF_TRACE(CDF_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; + sme_ac_enum_type acType; + hdd_wmm_ac_status_t *pAc; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_QosStatusType smeStatus; +#endif + sme_QosWmmTspecInfo qosInfo; + hdd_context_t *hdd_ctx; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered, context %p", __func__, pQosContext); + + if (unlikely(HDD_WMM_CTX_MAGIC != pQosContext->magic)) { + CDF_TRACE(CDF_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]; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: pAdapter %p acType %d", __func__, pAdapter, acType); + + if (!pAc->wmmAcAccessNeeded) { + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: AC %d doesn't need service", __func__, acType); + pQosContext->magic = 0; + kfree(pQosContext); + return; + } + + pAc->wmmAcAccessPending = true; + pAc->wmmAcAccessNeeded = false; + + memset(&qosInfo, 0, sizeof(qosInfo)); + + qosInfo.ts_info.psb = pAdapter->configuredPsb; + + switch (acType) { + case SME_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))->config-> + UapsdMask & SME_QOS_UAPSD_VO) ? 1 : 0; + } + qosInfo.ts_info.direction = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcVo; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraMeanDataRateAcVo; + qosInfo.min_phy_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcVo; + qosInfo.min_service_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdVoSrvIntv; + qosInfo.nominal_msdu_size = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcVo; + qosInfo.surplus_bw_allowance = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcVo; + qosInfo.suspension_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdVoSuspIntv; + break; + case SME_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))->config-> + UapsdMask & SME_QOS_UAPSD_VI) ? 1 : 0; + } + qosInfo.ts_info.direction = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcVi; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraMeanDataRateAcVi; + qosInfo.min_phy_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcVi; + qosInfo.min_service_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdViSrvIntv; + qosInfo.nominal_msdu_size = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcVi; + qosInfo.surplus_bw_allowance = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcVi; + qosInfo.suspension_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdViSuspIntv; + break; + default: + case SME_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))->config-> + UapsdMask & SME_QOS_UAPSD_BE) ? 1 : 0; + } + qosInfo.ts_info.direction = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcBe; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraMeanDataRateAcBe; + qosInfo.min_phy_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcBe; + qosInfo.min_service_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBeSrvIntv; + qosInfo.nominal_msdu_size = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcBe; + qosInfo.surplus_bw_allowance = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcBe; + qosInfo.suspension_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBeSuspIntv; + break; + case SME_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))->config-> + UapsdMask & SME_QOS_UAPSD_BK) ? 1 : 0; + } + qosInfo.ts_info.direction = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraDirAcBk; + qosInfo.ts_info.tid = 255; + qosInfo.mean_data_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraMeanDataRateAcBk; + qosInfo.min_phy_rate = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraMinPhyRateAcBk; + qosInfo.min_service_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBkSrvIntv; + qosInfo.nominal_msdu_size = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraNomMsduSizeAcBk; + qosInfo.surplus_bw_allowance = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraSbaAcBk; + qosInfo.suspension_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraUapsdBkSuspIntv; + break; + } +#ifdef FEATURE_WLAN_ESE + qosInfo.inactivity_interval = + (WLAN_HDD_GET_CTX(pAdapter))->config->InfraInactivityInterval; +#endif + qosInfo.ts_info.burst_size_defn = + (WLAN_HDD_GET_CTX(pAdapter))->config->burstSizeDefinition; + + switch ((WLAN_HDD_GET_CTX(pAdapter))->config->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_qos_is_ts_info_ack_policy_valid + ((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_qos_setup_req(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + &qosInfo, + hdd_wmm_sme_callback, + pQosContext, + qosInfo.ts_info.up, + &pQosContext->qosFlowId); + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: sme_qos_setup_req 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() + */ + CDF_TRACE(CDF_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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Setup is complete, notify TL", __func__); + + pAc->wmmAcAccessAllowed = true; + pAc->wmmAcAccessGranted = true; + pAc->wmmAcAccessPending = false; + + break; + + default: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus); + CDF_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) +{ + cds_ssr_protect(__func__); + __hdd_wmm_do_implicit_qos(work); + cds_ssr_unprotect(__func__); +} + +/** + * hdd_wmm_init() - initialize the WMM DSCP configuation + * @pAdapter : [in] pointer to Adapter context + * + * This function will initialize the WMM DSCP configuation of an + * adapter to an initial state. The configuration can later be + * overwritten via application APIs or via QoS Map sent OTA. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_init(hdd_adapter_t *pAdapter) +{ + sme_QosWmmUpType *hddWmmDscpToUpMap = pAdapter->hddWmmDscpToUpMap; + uint8_t dscp; + + CDF_TRACE(CDF_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 CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_adapter_init() - initialize the WMM configuration of an adapter + * @pAdapter: [in] pointer to Adapter context + * + * This function will initialize the WMM configuation and status of an + * adapter to an initial state. The configuration can later be + * overwritten via application APIs + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_init(hdd_adapter_t *pAdapter) +{ + hdd_wmm_ac_status_t *pAcStatus; + sme_ac_enum_type acType; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + + pAdapter->hddWmmStatus.wmmQap = false; + INIT_LIST_HEAD(&pAdapter->hddWmmStatus.wmmContextList); + mutex_init(&pAdapter->hddWmmStatus.wmmLock); + + for (acType = 0; acType < WLAN_MAX_AC; acType++) { + pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + pAcStatus->wmmAcAccessRequired = false; + pAcStatus->wmmAcAccessNeeded = false; + pAcStatus->wmmAcAccessPending = false; + pAcStatus->wmmAcAccessFailed = false; + pAcStatus->wmmAcAccessGranted = false; + pAcStatus->wmmAcAccessAllowed = false; + pAcStatus->wmmAcTspecValid = false; + pAcStatus->wmmAcUapsdInfoValid = false; + } + /* Invalid value(0xff) to indicate psb not configured through + * framework initially. + */ + pAdapter->configuredPsb = HDD_PSB_CFG_INVALID; + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_adapter_clear() - Function which will clear the WMM status + * for all the ACs + * + * @pAdapter: [in] pointer to Adapter context + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_clear(hdd_adapter_t *pAdapter) +{ + hdd_wmm_ac_status_t *pAcStatus; + sme_ac_enum_type acType; + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Entered", __func__); + for (acType = 0; acType < WLAN_MAX_AC; acType++) { + pAcStatus = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; + pAcStatus->wmmAcAccessRequired = false; + pAcStatus->wmmAcAccessNeeded = false; + pAcStatus->wmmAcAccessPending = false; + pAcStatus->wmmAcAccessFailed = false; + pAcStatus->wmmAcAccessGranted = false; + pAcStatus->wmmAcAccessAllowed = false; + pAcStatus->wmmAcTspecValid = false; + pAcStatus->wmmAcUapsdInfoValid = false; + } + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_close() - WMM close function + * @pAdapter: [in] pointer to adapter context + * + * Function which will perform any necessary work to to clean up the + * WMM functionality prior to the kernel module unload. + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_adapter_close(hdd_adapter_t *pAdapter) +{ + hdd_wmm_qos_context_t *pQosContext; + + CDF_TRACE(CDF_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) + cds_flush_work(&pQosContext->wmmAcSetupImplicitQos); + + hdd_wmm_free_context(pQosContext); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_classify_pkt() - Function which will classify an OS packet + * into a WMM AC based on either 802.1Q or DSCP + * + * @pAdapter: [in] adapter upon which the packet is being transmitted + * @skb: [in] the actual OS packet (sk_buff) being transmitted + * @pAcType: [out] WMM AC type of the OS packet + * @pUserPri: [out] User Priority of the OS packet + * + * Return: None + */ +static +void hdd_wmm_classify_pkt(hdd_adapter_t *pAdapter, + struct sk_buff *skb, + sme_ac_enum_type *pAcType, + sme_QosWmmUpType *pUserPri, + bool *is_eapol) +{ + unsigned char *pPkt; + union generic_ethhdr *pHdr; + struct iphdr *pIpHdr; + unsigned char tos; + unsigned char dscp; + sme_QosWmmUpType userPri; + sme_ac_enum_type acType; + + /* this code is executed for every packet therefore + * all debug code is kept conditional + */ + +#ifdef HDD_WMM_DEBUG + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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))->config->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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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; + *is_eapol = true; + } else + tos = 0; + } + + dscp = (tos >> 2) & 0x3f; + userPri = pAdapter->hddWmmDscpToUpMap[dscp]; + +#ifdef HDD_WMM_DEBUG + CDF_TRACE(CDF_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))->config-> + 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 + CDF_TRACE(CDF_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 + CDF_TRACE(CDF_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; + *is_eapol = true; + } else + userPri = SME_QOS_WMM_UP_BE; + } + } else { + /* default */ +#ifdef HDD_WMM_DEBUG + CDF_TRACE(CDF_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 = hdd_wmm_up_to_ac_map[userPri]; + +#ifdef HDD_WMM_DEBUG + CDF_TRACE(CDF_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; +} + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * hdd_get_queue_index() - get queue index + * @up: user priority + * @is_eapol: is_eapol flag + * + * Return: queue_index + */ +static +uint16_t hdd_get_queue_index(uint16_t up, bool is_eapol) +{ + if (cdf_unlikely(is_eapol == true)) + return HDD_LINUX_AC_HI_PRIO; + else + return hdd_linux_up_to_ac_map[up]; +} +#else +static +uint16_t hdd_get_queue_index(uint16_t up, bool is_eapol) +{ + return hdd_linux_up_to_ac_map[up]; +} +#endif + + +/** + * hdd_hostapd_select_queue() - Function which will classify the packet + * according to linux qdisc expectation. + * + * @dev: [in] pointer to net_device structure + * @skb: [in] pointer to os packet + * + * Return: Qdisc queue index + */ +uint16_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 + +) +{ + sme_ac_enum_type ac; + sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; + uint16_t queueIndex; + hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + bool is_eapol = false; + + if (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->config->WmmMode) { + /* Get the user priority from IP header & corresponding AC */ + hdd_wmm_classify_pkt(pAdapter, skb, &ac, &up, &is_eapol); + } + + skb->priority = up; + queueIndex = hdd_get_queue_index(skb->priority, is_eapol); + + return queueIndex; +} + +/** + * hdd_wmm_select_queue() - Function which will classify the packet + * according to linux qdisc expectation. + * + * @dev: [in] pointer to net_device structure + * @skb: [in] pointer to os packet + * + * Return: Qdisc queue index + */ +uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + sme_ac_enum_type ac; + sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; + uint16_t queueIndex; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + bool is_eapol = false; + + /* if we don't want QoS or the AP doesn't support Qos */ + /* All traffic will get equal opportuniy 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, &is_eapol); + } + + skb->priority = up; + queueIndex = hdd_get_queue_index(skb->priority, is_eapol); + return queueIndex; +} + +/** + * 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 + * + * @pAdapter: [in] pointer to adapter structure + * @acType: [in] WMM AC type of OS packet + * + * Return: void + */ +void hdd_wmm_acquire_access_required(hdd_adapter_t *pAdapter, + sme_ac_enum_type acType) +{ + /* Each bit in the LSB nibble indicates 1 AC. + * Clearing the particular bit in LSB nibble to indicate + * access required + */ + switch (acType) { + case SME_AC_BK: + /* clear first bit */ + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BK_CHANGED_MASK; + break; + case SME_AC_BE: + /* clear second bit */ + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_BE_CHANGED_MASK; + break; + case SME_AC_VI: + /* clear third bit */ + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VI_CHANGED_MASK; + break; + case SME_AC_VO: + /* clear fourth bit */ + pAdapter->psbChanged &= ~SME_QOS_UAPSD_CFG_VO_CHANGED_MASK; + break; + default: + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Invalid AC Type", __func__); + break; + } +} + +/** + * hdd_wmm_acquire_access() - Function which will attempt to acquire + * admittance for a WMM AC + * + * @pAdapter: [in] pointer to adapter context + * @acType: [in] WMM AC type of OS packet + * @pGranted: [out] pointer to bool flag when indicates if access + * has been granted or not + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_acquire_access(hdd_adapter_t *pAdapter, + sme_ac_enum_type acType, bool *pGranted) +{ + hdd_wmm_qos_context_t *pQosContext; + + CDF_TRACE(CDF_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))->config->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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: QoS not configured on both ends ", __func__); + + *pGranted = + pAdapter->hddWmmStatus.wmmAcStatus[acType]. + wmmAcAccessAllowed; + + return CDF_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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Implicit QoS for TL AC %d already scheduled", + __func__, acType); + + *pGranted = false; + return CDF_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 + */ + CDF_TRACE(CDF_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 = true; + *pGranted = true; + } else { + pAdapter->hddWmmStatus.wmmAcStatus[acType]. + wmmAcAccessAllowed = false; + *pGranted = false; + } + + return CDF_STATUS_SUCCESS; + } + /* we need to establish implicit QoS */ + CDF_TRACE(CDF_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 = true; + + pQosContext = kmalloc(sizeof(*pQosContext), GFP_ATOMIC); + if (NULL == pQosContext) { + /* no memory for QoS context. Nothing we can do but + * let data flow + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: Unable to allocate context", __func__); + pAdapter->hddWmmStatus.wmmAcStatus[acType].wmmAcAccessAllowed = + true; + *pGranted = true; + return CDF_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 + INIT_WORK(&pQosContext->wmmAcSetupImplicitQos, hdd_wmm_do_implicit_qos); +#endif + + CDF_TRACE(CDF_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 = false; + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_assoc() - Function which will handle the housekeeping + * required by WMM when association takes place + * + * @pAdapter: [in] pointer to adapter context + * @pRoamInfo: [in] pointer to roam information + * @eBssType: [in] type of BSS + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_assoc(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType) +{ + uint8_t uapsdMask; + CDF_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 + */ + + CDF_TRACE(CDF_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 + */ + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Reassoc so no work, Exiting", __func__); + + return CDF_STATUS_SUCCESS; + } + /* get the negotiated UAPSD Mask */ + uapsdMask = + pRoamInfo->u.pConnectedProfile->modifyProfileFields.uapsd_mask; + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: U-APSD mask is 0x%02x", __func__, (int)uapsdMask); + + if (uapsdMask & HDD_AC_VO) { + status = + sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + SME_AC_VO, 7, 7, + pHddCtx->config->InfraUapsdVoSrvIntv, + pHddCtx->config->InfraUapsdVoSuspIntv, + SME_BI_DIR, 1, + pAdapter->sessionId, + pHddCtx->config->DelayedTriggerFrmInt); + + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); + } + + if (uapsdMask & HDD_AC_VI) { + status = + sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + SME_AC_VI, 5, 5, + pHddCtx->config->InfraUapsdViSrvIntv, + pHddCtx->config->InfraUapsdViSuspIntv, + SME_BI_DIR, 1, + pAdapter->sessionId, + pHddCtx->config->DelayedTriggerFrmInt); + + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); + } + + if (uapsdMask & HDD_AC_BK) { + status = + sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + SME_AC_BK, 2, 2, + pHddCtx->config->InfraUapsdBkSrvIntv, + pHddCtx->config->InfraUapsdBkSuspIntv, + SME_BI_DIR, 1, + pAdapter->sessionId, + pHddCtx->config->DelayedTriggerFrmInt); + + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); + } + + if (uapsdMask & HDD_AC_BE) { + status = + sme_enable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + SME_AC_BE, 3, 3, + pHddCtx->config->InfraUapsdBeSrvIntv, + pHddCtx->config->InfraUapsdBeSuspIntv, + SME_BI_DIR, 1, + pAdapter->sessionId, + pHddCtx->config->DelayedTriggerFrmInt); + + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); + } + + status = sme_update_dsc_pto_up_mapping(pHddCtx->hHal, + pAdapter->hddWmmDscpToUpMap, + pAdapter->sessionId); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_wmm_init(pAdapter); + } + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Exiting", __func__); + + return CDF_STATUS_SUCCESS; +} + +static const uint8_t acm_mask_bit[WLAN_MAX_AC] = { + 0x4, /* SME_AC_BK */ + 0x8, /* SME_AC_BE */ + 0x2, /* SME_AC_VI */ + 0x1 /* SME_AC_VO */ +}; + +/** + * hdd_wmm_connect() - Function which will handle the housekeeping + * required by WMM when a connection is established + * + * @pAdapter : [in] pointer to adapter context + * @pRoamInfo: [in] pointer to roam information + * @eBssType : [in] type of BSS + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_connect(hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType) +{ + int ac; + bool qap; + bool qosConnection; + uint8_t acmMask; + + CDF_TRACE(CDF_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 { + qap = true; + qosConnection = true; + acmMask = 0x0; + } + + CDF_TRACE(CDF_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 < WLAN_MAX_AC; ac++) { + if (qap && qosConnection && (acmMask & acm_mask_bit[ac])) { + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: ac %d on", __func__, ac); + + /* admission is required */ + pAdapter->hddWmmStatus.wmmAcStatus[ac]. + wmmAcAccessRequired = true; + pAdapter->hddWmmStatus.wmmAcStatus[ac]. + wmmAcAccessAllowed = false; + pAdapter->hddWmmStatus.wmmAcStatus[ac]. + wmmAcAccessGranted = 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 = true; + } + } else { + CDF_TRACE(CDF_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 = false; + pAdapter->hddWmmStatus.wmmAcStatus[ac]. + wmmAcAccessAllowed = true; + } + + } + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Exiting", __func__); + + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_get_uapsd_mask() - Function which will calculate the + * initial value of the UAPSD mask based upon the device configuration + * + * @pAdapter : [in] pointer to adapter context + * @pUapsdMask: [out] pointer to where the UAPSD Mask is to be stored + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS hdd_wmm_get_uapsd_mask(hdd_adapter_t *pAdapter, + uint8_t *pUapsdMask) +{ + uint8_t uapsdMask; + + if (HDD_WMM_USER_MODE_NO_QOS == + (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) { + /* no QOS then no UAPSD */ + uapsdMask = 0; + } else { + /* start with the default mask */ + uapsdMask = (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask; + + /* disable UAPSD for any ACs with a 0 Service Interval */ + if ((WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraUapsdVoSrvIntv == 0) { + uapsdMask &= ~HDD_AC_VO; + } + + if ((WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraUapsdViSrvIntv == 0) { + uapsdMask &= ~HDD_AC_VI; + } + + if ((WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraUapsdBkSrvIntv == 0) { + uapsdMask &= ~HDD_AC_BK; + } + + if ((WLAN_HDD_GET_CTX(pAdapter))->config-> + InfraUapsdBeSrvIntv == 0) { + uapsdMask &= ~HDD_AC_BE; + } + } + + /* return calculated mask */ + *pUapsdMask = uapsdMask; + return CDF_STATUS_SUCCESS; +} + +/** + * hdd_wmm_is_active() - Function which will determine if WMM is + * active on the current connection + * + * @pAdapter: [in] pointer to adapter context + * + * Return: true if WMM is enabled, false if WMM is not enabled + */ +bool hdd_wmm_is_active(hdd_adapter_t *pAdapter) +{ + if ((!pAdapter->hddWmmStatus.wmmQosConnection) || + (!pAdapter->hddWmmStatus.wmmQap)) { + return false; + } else { + return true; + } +} + +/** + * hdd_wmm_addts() - Function which will add a traffic spec at the + * request of an application + * + * @pAdapter : [in] pointer to adapter context + * @handle : [in] handle to uniquely identify a TS + * @pTspec : [in] pointer to the traffic spec + * + * Return: HDD_WLAN_WMM_STATUS_* + */ +hdd_wlan_wmm_status_e hdd_wmm_addts(hdd_adapter_t *pAdapter, + uint32_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 + bool found = false; + + CDF_TRACE(CDF_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 = true; + break; + } + } + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + if (found) { + /* record with that handle already exists */ + CDF_TRACE(CDF_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_qos_modify_req(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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, + smeStatus); + CDF_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 */ + CDF_TRACE(CDF_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 = hdd_wmm_up_to_ac_map[pTspec->ts_info.up]; + else { + CDF_TRACE(CDF_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, hdd_wmm_up_to_ac_map[0]); + pQosContext->acType = hdd_wmm_up_to_ac_map[0]; + } + pQosContext->pAdapter = pAdapter; + pQosContext->qosFlowId = 0; + pQosContext->magic = HDD_WMM_CTX_MAGIC; + + CDF_TRACE(CDF_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_qos_setup_req(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + pTspec, + hdd_wmm_sme_callback, + pQosContext, + pTspec->ts_info.up, + &pQosContext->qosFlowId); + + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: sme_qos_setup_req 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 + * encounterd 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); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus); + CDF_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; +} + +/** + * hdd_wmm_delts() - Function which will delete a traffic spec at the + * request of an application + * + * @pAdapter: [in] pointer to adapter context + * @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, uint32_t handle) +{ + hdd_wmm_qos_context_t *pQosContext; + bool found = false; + sme_ac_enum_type acType = 0; + uint32_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 + + CDF_TRACE(CDF_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 = true; + acType = pQosContext->acType; + qosFlowId = pQosContext->qosFlowId; + break; + } + } + mutex_unlock(&pAdapter->hddWmmStatus.wmmLock); + + if (false == found) { + /* we didn't find the handle */ + CDF_TRACE(CDF_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; + } + + CDF_TRACE(CDF_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_qos_release_req(WLAN_HDD_GET_HAL_CTX(pAdapter), qosFlowId); + + CDF_TRACE(CDF_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 = + 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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, + "%s: unexpected SME Status=%d", __func__, smeStatus); + CDF_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; +} + +/** + * hdd_wmm_checkts() - Function which will return the status of a traffic + * spec at the request of an application + * + * @pAdapter: [in] pointer to adapter context + * @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, uint32_t handle) +{ + hdd_wmm_qos_context_t *pQosContext; + hdd_wlan_wmm_status_e status = HDD_WLAN_WMM_STATUS_LOST; + + CDF_TRACE(CDF_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) { + CDF_TRACE(CDF_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/core/hdd/src/wlan_hdd_wowl.c b/core/hdd/src/wlan_hdd_wowl.c new file mode 100644 index 000000000000..1c2ff5789ae7 --- /dev/null +++ b/core/hdd/src/wlan_hdd_wowl.c @@ -0,0 +1,600 @@ +/* + * 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_wowl.c + * + * @brief wake up on WLAN API file + */ + +/* 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]; +static bool g_hdd_wowl_ptrns_debugfs[WOWL_MAX_PTRNS_ALLOWED] = { 0 }; + +static uint8_t g_hdd_wowl_ptrns_count; + +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, CDF_STATUS cdf_ret_status) +{ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Return code = (%d)", __func__, cdf_ret_status); +} + +#ifdef WLAN_WAKEUP_EVENTS +static void hdd_wowl_wake_indication_callback(void *pContext, + tpSirWakeReasonInd wake_reason_ind) +{ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: Wake Reason %d", + __func__, wake_reason_ind->ulReason); + hdd_exit_wowl((hdd_adapter_t *) pContext); +} +#endif + +/** + * dump_hdd_wowl_ptrn() - log wow patterns + * @ptrn: pointer to wow pattern + * + * Return: none + */ +static void dump_hdd_wowl_ptrn(struct wow_add_pattern *ptrn) +{ + int i; + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Patetrn Id = 0x%x", __func__, ptrn->pattern_id); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: Pattern Byte Offset = 0x%x", __func__, + ptrn->pattern_byte_offset); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: pattern_size = 0x%x", __func__, ptrn->pattern_size); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: pattern_mask_size = 0x%x", __func__, + ptrn->pattern_mask_size); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: Pattern: ", + __func__); + for (i = 0; i < ptrn->pattern_size; i++) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, " %02X", + ptrn->pattern[i]); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: pattern_mask: ", + __func__); + for (i = 0; i < ptrn->pattern_mask_size; i++) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%02X", + ptrn->pattern_mask[i]); +} + +/** + * hdd_add_wowl_ptrn() - Function which will add the WoWL pattern to be + * used when PBM filtering is enabled + * @pAdapter: pointer to the adapter + * @ptrn: pointer to the pattern string to be added + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_add_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn) +{ + struct wow_add_pattern localPattern; + int i, first_empty_slot, len, offset; + CDF_STATUS cdf_ret_status; + const char *temp; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint8_t sessionId = pAdapter->sessionId; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + + len = find_ptrn_len(ptrn); + + /* There has to have at least 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; i < pHddCtx->config->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 + */ + CDF_TRACE(CDF_MODULE_ID_HDD, + CDF_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; i < pHddCtx->config->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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Cannot add anymore patterns. No free slot!", + __func__); + return false; + } + /* Validate the pattern */ + if (ptrn[2] != WOWL_INTRA_PTRN_TOKENIZER || + ptrn[5] != WOWL_INTRA_PTRN_TOKENIZER) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Malformed pattern string. Skip!", + __func__); + ptrn += len; + goto next_ptrn; + } + /* Extract the pattern size */ + localPattern.pattern_size = + (hex_to_bin(ptrn[0]) * 0x10) + + hex_to_bin(ptrn[1]); + + /* Extract the pattern mask size */ + localPattern.pattern_mask_size = + (hex_to_bin(ptrn[3]) * 0x10) + + hex_to_bin(ptrn[4]); + + if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE + || localPattern.pattern_mask_size > + WOWL_PTRN_MASK_MAX_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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.pattern_size + 1; + if ((offset >= len) || + (ptrn[offset] != WOWL_INTRA_PTRN_TOKENIZER)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Malformed pattern string..skip!", + __func__); + ptrn += len; + goto next_ptrn; + } + /* compute the end of pattern sring */ + offset = offset + 2 * localPattern.pattern_mask_size; + if (offset + 1 != len) { + /* offset begins with 0 */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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.pattern_size; i++) { + localPattern.pattern[i] = + (hex_to_bin(ptrn[0]) * 0x10) + + hex_to_bin(ptrn[1]); + ptrn += 2; /* skip to next byte */ + } + + /* Skip over the ':' seperator after the pattern */ + ptrn++; + + /* Extract the pattern Mask */ + for (i = 0; i < localPattern.pattern_mask_size; i++) { + localPattern.pattern_mask[i] = + (hex_to_bin(ptrn[0]) * 0x10) + + hex_to_bin(ptrn[1]); + ptrn += 2; /* skip to next byte */ + } + + /* All is good. Store the pattern locally */ + g_hdd_wowl_ptrns[first_empty_slot] = + kmalloc(len + 1, GFP_KERNEL); + if (g_hdd_wowl_ptrns[first_empty_slot] == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: kmalloc failure", __func__); + return false; + } + + memcpy(g_hdd_wowl_ptrns[first_empty_slot], temp, len); + g_hdd_wowl_ptrns[first_empty_slot][len] = '\0'; + localPattern.pattern_id = first_empty_slot; + localPattern.pattern_byte_offset = 0; + localPattern.session_id = sessionId; + + /* Register the pattern downstream */ + cdf_ret_status = + sme_wow_add_pattern(hHal, &localPattern, + sessionId); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + /* Add failed, so invalidate the local storage */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "sme_wowl_add_bcast_pattern failed with error code (%d)", + cdf_ret_status); + 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) { + /* move past the tokenizer */ + ptrn += 1; + len = find_ptrn_len(ptrn); + continue; + } else + break; + } + + return true; +} + +/** + * hdd_del_wowl_ptrn() - Function which will remove a WoWL pattern + * @pAdapter: pointer to the adapter + * @ptrn: pointer to the pattern string to be removed + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_del_wowl_ptrn(hdd_adapter_t *pAdapter, const char *ptrn) +{ + struct wow_delete_pattern delPattern; + unsigned char id; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + bool patternFound = false; + CDF_STATUS cdf_ret_status; + uint8_t sessionId = pAdapter->sessionId; + hdd_context_t *pHddCtx = pAdapter->pHddCtx; + + /* Detect pattern */ + for (id = 0; + id < pHddCtx->config->maxWoWFilters + && g_hdd_wowl_ptrns[id] != NULL; id++) { + if (!strcmp(ptrn, g_hdd_wowl_ptrns[id])) { + patternFound = true; + break; + } + } + + /* If pattern present, remove it from downstream */ + if (patternFound) { + delPattern.pattern_id = id; + delPattern.session_id = sessionId; + cdf_ret_status = + sme_wow_delete_pattern(hHal, &delPattern, + sessionId); + if (CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + /* Remove from local storage as well */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 true; + } + } + return false; +} + +/** + * hdd_add_wowl_ptrn_debugfs() - Function which will add a WoW pattern + * sent from debugfs interface + * @pAdapter: pointer to the adapter + * @pattern_idx: index of the pattern to be added + * @pattern_offset: offset of the pattern in the frame payload + * @pattern_buf: pointer to the pattern hex string to be added + * @pattern_mask: pointer to the pattern mask hex string + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_add_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx, + uint8_t pattern_offset, char *pattern_buf, + char *pattern_mask) +{ + struct wow_add_pattern localPattern; + CDF_STATUS cdf_ret_status; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + uint8_t session_id = pAdapter->sessionId; + uint16_t pattern_len, mask_len, i; + + if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern index %d is out of range (0 ~ %d).", + __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1); + + return false; + } + + pattern_len = strlen(pattern_buf); + + /* Since the pattern is a hex string, 2 characters represent 1 byte. */ + if (pattern_len % 2) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Malformed WoW pattern!", __func__); + + return false; + } else + pattern_len >>= 1; + + if (!pattern_len || pattern_len > WOWL_PTRN_MAX_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern length %d is out of range (1 ~ %d).", + __func__, pattern_len, WOWL_PTRN_MAX_SIZE); + + return false; + } + + localPattern.pattern_id = pattern_idx; + localPattern.pattern_byte_offset = pattern_offset; + localPattern.pattern_size = pattern_len; + localPattern.session_id = session_id; + + if (localPattern.pattern_size > SIR_WOWL_BCAST_PATTERN_MAX_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern size (%d) greater than max (%d)", + __func__, localPattern.pattern_size, + SIR_WOWL_BCAST_PATTERN_MAX_SIZE); + return false; + } + /* Extract the pattern */ + for (i = 0; i < localPattern.pattern_size; i++) { + localPattern.pattern[i] = + (hex_to_bin(pattern_buf[0]) << 4) + + hex_to_bin(pattern_buf[1]); + + /* Skip to next byte */ + pattern_buf += 2; + } + + /* Get pattern mask size by pattern length */ + localPattern.pattern_mask_size = pattern_len >> 3; + if (pattern_len % 8) + localPattern.pattern_mask_size += 1; + + mask_len = strlen(pattern_mask); + if ((mask_len % 2) + || (localPattern.pattern_mask_size != (mask_len >> 1))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: Malformed WoW pattern mask!", __func__); + + return false; + } + if (localPattern.pattern_mask_size > WOWL_PTRN_MASK_MAX_SIZE) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern mask size (%d) greater than max (%d)", + __func__, localPattern.pattern_mask_size, + WOWL_PTRN_MASK_MAX_SIZE); + return false; + } + /* Extract the pattern mask */ + for (i = 0; i < localPattern.pattern_mask_size; i++) { + localPattern.pattern_mask[i] = + (hex_to_bin(pattern_mask[0]) << 4) + + hex_to_bin(pattern_mask[1]); + + /* Skip to next byte */ + pattern_mask += 2; + } + + /* Register the pattern downstream */ + cdf_ret_status = + sme_wow_add_pattern(hHal, &localPattern, session_id); + + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_wowl_add_bcast_pattern failed with error code (%d).", + __func__, cdf_ret_status); + + return 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 true; +} + +/** + * hdd_del_wowl_ptrn_debugfs() - Function which will remove a WoW pattern + * sent from debugfs interface + * @pAdapter: pointer to the adapter + * @pattern_idx: index of the pattern to be removed + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_del_wowl_ptrn_debugfs(hdd_adapter_t *pAdapter, uint8_t pattern_idx) +{ + struct wow_delete_pattern delPattern; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + CDF_STATUS cdf_ret_status; + uint8_t sessionId = pAdapter->sessionId; + + if (pattern_idx > (WOWL_MAX_PTRNS_ALLOWED - 1)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern index %d is not in the range (0 ~ %d).", + __func__, pattern_idx, WOWL_MAX_PTRNS_ALLOWED - 1); + + return false; + } + + if (!g_hdd_wowl_ptrns_debugfs[pattern_idx]) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: WoW pattern %d is not in the table.", + __func__, pattern_idx); + + return false; + } + + delPattern.pattern_id = pattern_idx; + delPattern.session_id = sessionId; + cdf_ret_status = sme_wow_delete_pattern(hHal, &delPattern, + sessionId); + + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s: sme_wowl_del_bcast_pattern failed with error code (%d).", + __func__, cdf_ret_status); + + return false; + } + + g_hdd_wowl_ptrns_debugfs[pattern_idx] = 0; + g_hdd_wowl_ptrns_count--; + + return true; +} + +/** + * hdd_enter_wowl() - Function which will enable WoWL. At least one + * of MP and PBM must be enabled + * @pAdapter: pointer to the adapter + * @enable_mp: Whether to enable magic packet WoWL mode + * @enable_pbm: Whether to enable pattern byte matching WoWL mode + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_enter_wowl(hdd_adapter_t *pAdapter, bool enable_mp, bool enable_pbm) +{ + tSirSmeWowlEnterParams wowParams; + CDF_STATUS cdf_ret_status; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + + cdf_mem_zero(&wowParams, sizeof(tSirSmeWowlEnterParams)); + + wowParams.ucPatternFilteringEnable = enable_pbm; + wowParams.ucMagicPktEnable = enable_mp; + wowParams.sessionId = pAdapter->sessionId; + if (enable_mp) { + cdf_copy_macaddr((struct cdf_mac_addr *) &(wowParams.magicPtrn), + &(pAdapter->macAddressCurrent)); + } +#ifdef WLAN_WAKEUP_EVENTS + wowParams.ucWoWEAPIDRequestEnable = true; + wowParams.ucWoWEAPOL4WayEnable = true; + wowParams.ucWowNetScanOffloadMatch = true; + wowParams.ucWowGTKRekeyError = true; + wowParams.ucWoWBSSConnLoss = true; +#endif /* WLAN_WAKEUP_EVENTS */ + + /* Request to put Libra into WoWL */ + cdf_ret_status = sme_enter_wowl(hHal, hdd_wowl_callback, pAdapter, +#ifdef WLAN_WAKEUP_EVENTS + hdd_wowl_wake_indication_callback, + pAdapter, +#endif /* WLAN_WAKEUP_EVENTS */ + &wowParams, pAdapter->sessionId); + + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + if (CDF_STATUS_PMC_PENDING != cdf_ret_status) { + /* We failed to enter WoWL */ + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "sme_enter_wowl failed with error code (%d)", + cdf_ret_status); + return false; + } + } + return true; +} + +/** + * hdd_exit_wowl() - Function which will disable WoWL + * @pAdapter: pointer to the adapter + * + * Return: false if any errors encountered, true otherwise + */ +bool hdd_exit_wowl(hdd_adapter_t *pAdapter) +{ + tSirSmeWowlExitParams wowParams; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + CDF_STATUS cdf_ret_status; + + wowParams.sessionId = pAdapter->sessionId; + + cdf_ret_status = sme_exit_wowl(hHal, &wowParams); + if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "sme_exit_wowl failed with error code (%d)", + cdf_ret_status); + return false; + } + + return true; +} + +/** + * hdd_init_wowl() - Init function which will initialize the WoWL module + * and perform any required initial configuration + * @pAdapter: pointer to the adapter + * + * Return: false if any errors encountered, true otherwise + */ +bool 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)); + g_hdd_wowl_ptrns_count = 0; + + /* Add any statically configured patterns */ + hdd_add_wowl_ptrn(pAdapter, pHddCtx->config->wowlPattern); + + return true; +} diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h new file mode 100644 index 000000000000..0c9a41318a7d --- /dev/null +++ b/core/hif/inc/hif.h @@ -0,0 +1,650 @@ +/* + * 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_H_ +#define _HIF_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "athdefs.h" +#include "a_types.h" +#include "osapi_linux.h" +#include "cdf_status.h" +#include "cdf_nbuf.h" +#include "ol_if_athvar.h" +#include +#ifdef HIF_PCI +#include +#endif /* HIF_PCI */ + +#define ENABLE_MBOX_DUMMY_SPACE_FEATURE 1 + +typedef struct htc_callbacks HTC_CALLBACKS; +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 +#define HIF_TYPE_QCA6180 9 +#define HIF_TYPE_ADRASTEA 10 + +#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 +/* For QCA6180 target */ +#define TARGET_TYPE_QCA6180 15 +/* For Adrastea target */ +#define TARGET_TYPE_ADRASTEA 16 + +struct CE_state; +#define CE_COUNT_MAX 8 + +/* These numbers are selected so that the product is close to current + higher limit of packets HIF services at one shot (1000) */ +#define QCA_NAPI_BUDGET 64 +#define QCA_NAPI_DEF_SCALE 16 +/* NOTE: This is to adapt non-NAPI solution to use + the same "budget" as NAPI. Will be removed + `once decision about NAPI is made */ +#define HIF_NAPI_MAX_RECEIVES (QCA_NAPI_BUDGET * QCA_NAPI_DEF_SCALE) + +/* NOTE: "napi->scale" can be changed, + but this does not change the number of buckets */ +#define QCA_NAPI_NUM_BUCKETS (QCA_NAPI_BUDGET / QCA_NAPI_DEF_SCALE) +struct qca_napi_stat { + uint32_t napi_schedules; + uint32_t napi_polls; + uint32_t napi_completes; + uint32_t napi_workdone; + uint32_t napi_budget_uses[QCA_NAPI_NUM_BUCKETS]; +}; + +/** + * per NAPI instance data structure + * This data structure holds stuff per NAPI instance. + * Note that, in the current implementation, though scale is + * an instance variable, it is set to the same value for all + * instances. + */ +struct qca_napi_info { + struct napi_struct napi; /* one NAPI Instance per CE in phase I */ + uint8_t scale; /* currently same on all instances */ + uint8_t id; + struct qca_napi_stat stats[NR_CPUS]; +}; + +/** + * NAPI data-sructure common to all NAPI instances. + * + * A variable of this type will be stored in hif module context. + */ + +struct qca_napi_data { + /* NOTE: make sure the mutex is inited only at the very beginning + once for the lifetime of the driver. For now, granularity of one + is OK, but we might want to have a better granularity later */ + struct mutex mutex; + uint32_t state; + uint32_t ce_map; /* bitmap of created/registered NAPI + instances, indexed by pipe_id, + not used by clients (clients use an + id returned by create) */ + struct net_device netdev; /* dummy net_dev */ + struct qca_napi_info napis[CE_COUNT_MAX]; +}; + +struct ol_softc { + void __iomem *mem; /* IO mapped memory base address */ + cdf_dma_addr_t mem_pa; + uint32_t soc_version; + /* + * handle for code that uses the osdep.h version of OS + * abstraction primitives + */ + struct _NIC_DEV aps_osdev; + enum ath_hal_bus_type bus_type; + uint32_t lcr_val; + bool pkt_log_init; + bool request_irq_done; + /* + * handle for code that uses cdf version of OS + * abstraction primitives + */ + cdf_device_t cdf_dev; + + struct ol_version version; + + /* Packet statistics */ + struct ol_ath_stats pkt_stats; + + /* A_TARGET_TYPE_* */ + uint32_t target_type; + uint32_t target_fw_version; + uint32_t target_version; + uint32_t target_revision; + uint8_t crm_version_string[64]; + uint8_t wlan_version_string[64]; + ol_target_status target_status; + bool is_sim; + /* calibration data is stored in flash */ + uint8_t *cal_in_flash; + /* virtual address for the calibration data on the flash */ + void *cal_mem; + /* status of target init */ + WLAN_INIT_STATUS wlan_init_status; + + /* BMI info */ + /* OS-dependent private info for BMI */ + void *bmi_ol_priv; + bool bmi_done; + bool bmi_ua_done; + uint8_t *bmi_cmd_buff; + dma_addr_t bmi_cmd_da; + OS_DMA_MEM_CONTEXT(bmicmd_dmacontext) + + uint8_t *bmi_rsp_buff; + dma_addr_t bmi_rsp_da; + /* length of last response */ + uint32_t last_rxlen; + OS_DMA_MEM_CONTEXT(bmirsp_dmacontext) + + void *msi_magic; + dma_addr_t msi_magic_da; + OS_DMA_MEM_CONTEXT(msi_dmacontext) + + /* Handles for Lower Layers : filled in at init time */ + hif_handle_t hif_hdl; +#ifdef HIF_PCI + struct hif_pci_softc *hif_sc; +#endif + +#ifdef WLAN_FEATURE_FASTPATH + int fastpath_mode_on; /* Duplicating this for data path efficiency */ +#endif /* WLAN_FEATURE_FASTPATH */ + + /* HTC handles */ + void *htc_handle; + + bool fEnableBeaconEarlyTermination; + uint8_t bcnEarlyTermWakeInterval; + + /* UTF event information */ + struct { + uint8_t *data; + uint32_t length; + cdf_size_t offset; + uint8_t currentSeq; + uint8_t expectedSeq; + } utf_event_info; + + struct ol_wow_info *scn_wowInfo; + /* enable uart/serial prints from target */ + bool enableuartprint; + /* enable fwlog */ + bool enablefwlog; + + HAL_REG_CAPABILITIES hal_reg_capabilities; + struct ol_regdmn *ol_regdmn_handle; + uint8_t bcn_mode; + uint8_t arp_override; + /* + * Includes host side stack level stats + + * radio level athstats + */ + struct wlan_dbg_stats ath_stats; + /* noise_floor */ + int16_t chan_nf; + uint32_t min_tx_power; + uint32_t max_tx_power; + uint32_t txpowlimit2G; + uint32_t txpowlimit5G; + uint32_t txpower_scale; + uint32_t chan_tx_pwr; + uint32_t vdev_count; + uint32_t max_bcn_ie_size; + cdf_spinlock_t scn_lock; + uint8_t vow_extstats; + /* if dcs enabled or not */ + uint8_t scn_dcs; + wdi_event_subscribe scn_rx_peer_invalid_subscriber; + uint8_t proxy_sta; + uint8_t bcn_enabled; + /* Dynamic Tx Chainmask Selection enabled/disabled */ + uint8_t dtcs; + /* true if vht ies are set on target */ + uint32_t set_ht_vht_ies:1; + /*CWM enable/disable state */ + bool scn_cwmenable; + uint8_t max_no_of_peers; +#ifdef CONFIG_CNSS + struct cnss_fw_files fw_files; +#endif +#if defined(CONFIG_CNSS) + void *ramdump_base; + unsigned long ramdump_address; + unsigned long ramdump_size; +#endif + bool enable_self_recovery; +#ifdef WLAN_FEATURE_LPSS + bool enablelpasssupport; +#endif + bool enable_ramdump_collection; + struct targetdef_s *targetdef; + struct ce_reg_def *target_ce_def; + struct hostdef_s *hostdef; + struct host_shadow_regs_s *host_shadow_regs; + bool athdiag_procfs_inited; + /* + * Guard changes to Target HW state and to software + * structures that track hardware state. + */ + cdf_spinlock_t target_lock; + unsigned int ce_count; /* Number of Copy Engines supported */ + 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 */ + struct CE_state *ce_id_to_state[CE_COUNT_MAX]; /* CE id to CE_state */ +#ifdef FEATURE_NAPI + struct qca_napi_data napi_data; +#endif /* FEATURE_NAPI */ + int htc_endpoint; + bool recovery; + bool hif_init_done; + int linkstate_vote; + atomic_t link_suspended; + atomic_t wow_done; + atomic_t tasklet_from_intr; + atomic_t active_tasklet_cnt; + bool notice_send; +#ifdef HIF_PCI + cdf_spinlock_t irq_lock; + uint32_t ce_irq_summary; +#endif +}; + +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; + +/** + * enum hif_enable_type: what triggered the enabling of hif + * + * @HIF_ENABLE_TYPE_PROBE: probe triggered enable + * @HIF_ENABLE_TYPE_REINIT: reinit triggered enable + */ +enum hif_enable_type { + HIF_ENABLE_TYPE_PROBE, + HIF_ENABLE_TYPE_REINIT, + HIF_ENABLE_TYPE_MAX +}; + +/** + * enum hif_disable_type: what triggered the disabling of hif + * + * @HIF_DISABLE_TYPE_PROBE_ERROR: probe error triggered disable + * @HIF_DISABLE_TYPE_REINIT_ERROR: reinit error triggered + * disable + * @HIF_DISABLE_TYPE_REMOVE: remove triggered disable + * @HIF_DISABLE_TYPE_SHUTDOWN: shutdown triggered disable + */ +enum hif_disable_type { + HIF_DISABLE_TYPE_PROBE_ERROR, + HIF_DISABLE_TYPE_REINIT_ERROR, + HIF_DISABLE_TYPE_REMOVE, + HIF_DISABLE_TYPE_SHUTDOWN, + HIF_DISABLE_TYPE_MAX +}; + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +typedef struct _HID_ACCESS_LOG { + uint32_t seqnum; + bool is_write; + void *addr; + uint32_t 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 hif_read_write */ + 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; + +/* + * 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 hif_init(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 hif_claim_device(struct ol_softc *scn, void *claimedContext); +/* release the claimed device */ +void hif_release_device(struct ol_softc *scn); + +/* This API detaches the HTC layer from the HIF device */ +void hif_detach_htc(struct ol_softc *scn); + +/****************************************************************/ +/* BMI and Diag window abstraction */ +/****************************************************************/ + +#define HIF_BMI_EXCHANGE_NO_TIMEOUT ((uint32_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) */ +CDF_STATUS hif_exchange_bmi_msg(struct ol_softc *scn, + uint8_t *pSendMessage, + uint32_t Length, + uint8_t *pResponseMessage, + uint32_t *pResponseLength, uint32_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. + * + * hif_diag_read_access reads a 4 Byte aligned/length value from a + * Target register or memory word. + * + * hif_diag_read_mem reads an arbitrary length of arbitrarily aligned memory. + */ +CDF_STATUS hif_diag_read_access(struct ol_softc *scn, uint32_t address, + uint32_t *data); +CDF_STATUS hif_diag_read_mem(struct ol_softc *scn, uint32_t address, + uint8_t *data, int nbytes); +void hif_dump_target_memory(struct ol_softc *scn, void *ramdump_base, + uint32_t address, uint32_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. + * + * hif_diag_write_access writes a 4 Byte aligned/length value to a + * Target register or memory word. + * + * hif_diag_write_mem writes an arbitrary length of arbitrarily aligned memory. + */ +CDF_STATUS hif_diag_write_access(struct ol_softc *scn, uint32_t address, + uint32_t data); +CDF_STATUS hif_diag_write_mem(struct ol_softc *scn, uint32_t address, + uint8_t *data, int nbytes); + +/* + * Set the FASTPATH_mode_on flag in sc, for use by data path + */ +#ifdef WLAN_FEATURE_FASTPATH +void hif_enable_fastpath(struct ol_softc *hif_dev); +#endif + +#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. + */ + +/* + * 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 +#endif + +#ifdef IPA_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 hif_ipa_get_ce_resource(struct ol_softc *scn, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr); +#else +static inline void hif_ipa_get_ce_resource(struct ol_softc *scn, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr) +{ + return; +} +#endif /* IPA_OFFLOAD */ + + +void hif_read_phy_mem_base(struct ol_softc *scn, + cdf_dma_addr_t *bar_value); + +/** + * @brief List of callbacks - filled in by HTC. + */ +struct hif_msg_callbacks { + void *Context; + /**< context meaningful to HTC */ + CDF_STATUS (*txCompletionHandler)(void *Context, cdf_nbuf_t wbuf, + uint32_t transferID, + uint32_t toeplitz_hash_result); + CDF_STATUS (*rxCompletionHandler)(void *Context, cdf_nbuf_t wbuf, + uint8_t pipeID); + void (*txResourceAvailHandler)(void *context, uint8_t pipe); + void (*fwEventHandler)(void *context, CDF_STATUS status); +}; + +#define HIF_DATA_ATTR_SET_TX_CLASSIFY(attr, v) \ + (attr |= (v & 0x01) << 5) +#define HIF_DATA_ATTR_SET_ENCAPSULATION_TYPE(attr, v) \ + (attr |= (v & 0x03) << 6) +#define HIF_DATA_ATTR_SET_ADDR_X_SEARCH_DISABLE(attr, v) \ + (attr |= (v & 0x01) << 13) +#define HIF_DATA_ATTR_SET_ADDR_Y_SEARCH_DISABLE(attr, v) \ + (attr |= (v & 0x01) << 14) +#define HIF_DATA_ATTR_SET_TOEPLITZ_HASH_ENABLE(attr, v) \ + (attr |= (v & 0x01) << 15) +#define HIF_DATA_ATTR_SET_PACKET_OR_RESULT_OFFSET(attr, v) \ + (attr |= (v & 0x0FFF) << 16) +#define HIF_DATA_ATTR_SET_ENABLE_11H(attr, v) \ + (attr |= (v & 0x01) << 30) + +#ifdef HIF_PCI +typedef struct pci_device_id hif_bus_id; +#else +typedef struct device hif_bus_id; +#endif + +void hif_post_init(struct ol_softc *scn, void *hHTC, + struct hif_msg_callbacks *callbacks); +CDF_STATUS hif_start(struct ol_softc *scn); +void hif_stop(struct ol_softc *scn); +void hif_flush_surprise_remove(struct ol_softc *scn); +void hif_dump(struct ol_softc *scn, uint8_t CmdId, bool start); +CDF_STATUS hif_send_head(struct ol_softc *scn, uint8_t PipeID, + uint32_t transferID, uint32_t nbytes, + cdf_nbuf_t wbuf, uint32_t data_attr); +void hif_send_complete_check(struct ol_softc *scn, uint8_t PipeID, + int force); +void hif_cancel_deferred_target_sleep(struct ol_softc *scn); +void hif_get_default_pipe(struct ol_softc *scn, uint8_t *ULPipe, + uint8_t *DLPipe); +int hif_map_service_to_pipe(struct ol_softc *scn, uint16_t ServiceId, + uint8_t *ULPipe, uint8_t *DLPipe, + int *ul_is_polled, int *dl_is_polled); +uint16_t hif_get_free_queue_number(struct ol_softc *scn, uint8_t PipeID); +void *hif_get_targetdef(struct ol_softc *scn); +void hi_fsuspendwow(struct ol_softc *scn); +uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset); +void hif_set_target_sleep(struct ol_softc *scn, bool sleep_ok, + bool wait_for_it); +int hif_check_fw_reg(struct ol_softc *scn); +int hif_check_soc_status(struct ol_softc *scn); +void dump_ce_debug_register(struct ol_softc *scn); +void hif_get_hw_info(void *scn, u32 *version, u32 *revision, + const char **target_name); +void hif_set_fw_info(void *scn, u32 target_fw_version); +void hif_disable_isr(void *scn); +void hif_reset_soc(void *scn); +void hif_disable_aspm(void); +void hif_save_htc_htt_config_endpoint(int htc_endpoint); +CDF_STATUS hif_open(void); +void hif_close(void *hif_ctx); +CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, void *bdev, + const hif_bus_id *bid, enum ath_hal_bus_type bus_type, + enum hif_enable_type type); +void hif_disable(void *hif_ctx, enum hif_disable_type type); +void hif_enable_power_gating(void *hif_ctx); +int hif_bus_resume(void); +int hif_bus_suspend(void); +void hif_vote_link_down(void); +void hif_vote_link_up(void); +bool hif_can_suspend_link(void); +int dump_ce_register(struct ol_softc *scn); +int ol_copy_ramdump(struct ol_softc *scn); +void hif_pktlogmod_exit(void *hif_ctx); +void hif_crash_shutdown(void *hif_ctx); +#ifdef __cplusplus +} +#endif +#endif /* _HIF_H_ */ diff --git a/core/hif/inc/hif_napi.h b/core/hif/inc/hif_napi.h new file mode 100644 index 000000000000..c6f817f3140a --- /dev/null +++ b/core/hif/inc/hif_napi.h @@ -0,0 +1,153 @@ +/* + * 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 __HIF_NAPI_H__ +#define __HIF_NAPI_H__ + +/** + * DOC: hif_napi.h + * + * Interface to HIF implemented functions of NAPI. + * These are used by hdd_napi. + */ + + +/* CLD headers */ +#include /* struct ol_softc; */ + +/** + * common stuff + * The declarations until #ifdef FEATURE_NAPI below + * are valid whether or not FEATURE_NAPI has been + * defined. + */ + +/* the following triggers napi_enable/disable as required */ +enum qca_napi_event { + NAPI_EVT_INVALID, + NAPI_EVT_INI_FILE, + NAPI_EVT_CMD_STATE /* ioctl enable/disable commands */ +}; + +/** + * Macros to map ids -returned by ...create()- to pipes and vice versa + */ +#define NAPI_ID2PIPE(i) ((i)-1) +#define NAPI_PIPE2ID(p) ((p)+1) + + +#ifdef FEATURE_NAPI + +/** + * NAPI HIF API + * + * the declarations below only apply to the case + * where FEATURE_NAPI is defined + */ + +int hif_napi_create(struct ol_softc *hif, + uint8_t pipe_id, + int (*poll)(struct napi_struct *, int), + int budget, + int scale); +int hif_napi_destroy(struct ol_softc *hif, + uint8_t id, + int force); + +struct qca_napi_data *hif_napi_get_all(struct ol_softc *hif); + +int hif_napi_event(struct ol_softc *hif, + enum qca_napi_event event, + void *data); + +/* called from the ISR within hif, so, ce is known */ +int hif_napi_enabled(struct ol_softc *hif, int ce); + +/* called from hdd (napi_poll), using napi id as a selector */ +void hif_napi_enable_irq(struct ol_softc *hif, int id); + +/* called by ce_tasklet.c::ce_irq_handler */ +int hif_napi_schedule(struct ol_softc *scn, int ce_id); + +/* called by hdd_napi, which is called by kernel */ +int hif_napi_poll(struct napi_struct *napi, int budget); + +#ifdef FEATURE_NAPI_DEBUG +#define NAPI_DEBUG(fmt, ...) \ + cdf_print("wlan: NAPI: %s:%d "fmt, __func__, __LINE__, ##__VA_ARGS__); +#else +#define NAPI_DEBUG(fmt, ...) /* NO-OP */ +#endif /* FEATURE NAPI_DEBUG */ + +#else /* ! defined(FEATURE_NAPI) */ + +/** + * Stub API + * + * The declarations in this section are valid only + * when FEATURE_NAPI has *not* been defined. + */ + +#define NAPI_DEBUG(fmt, ...) /* NO-OP */ + +static inline int hif_napi_create(struct ol_softc *hif, + uint8_t pipe_id, + int (*poll)(struct napi_struct *, int), + int budget, + int scale) +{ return -EPERM; } + +static inline int hif_napi_destroy(struct ol_softc *hif, + uint8_t id, + int force) +{ return -EPERM; } + +static inline struct qca_napi_data *hif_napi_get_all(struct ol_softc *hif) +{ return NULL; } + +static inline int hif_napi_event(struct ol_softc *hif, + enum qca_napi_event event, + void *data) +{ return -EPERM; } + +/* called from the ISR within hif, so, ce is known */ +static inline int hif_napi_enabled(struct ol_softc *hif, int ce) +{ return 0; } + +/* called from hdd (napi_poll), using napi id as a selector */ +static inline void hif_napi_enable_irq(struct ol_softc *hif, int id) +{ return; } + +static inline int hif_napi_schedule(struct ol_softc *hif, int ce_id) +{ return 0; } + +static inline int hif_napi_poll(struct napi_struct *napi, int budget) +{ return -EPERM; } + +#endif /* FEATURE_NAPI */ + +#endif /* __HIF_NAPI_H__ */ diff --git a/core/hif/inc/regtable.h b/core/hif/inc/regtable.h new file mode 100644 index 000000000000..2aae9e8d89f9 --- /dev/null +++ b/core/hif/inc/regtable.h @@ -0,0 +1,33 @@ +/* + * 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 _REGTABLE_H_ +#define _REGTABLE_H_ + +#include "regtable_pcie.h" +#include "regtable_ce.h" +#endif diff --git a/core/hif/inc/regtable_ce.h b/core/hif/inc/regtable_ce.h new file mode 100644 index 000000000000..e5f5a9f10cca --- /dev/null +++ b/core/hif/inc/regtable_ce.h @@ -0,0 +1,259 @@ +/* + * 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 _REGTABLE_CE_H_ +#define _REGTABLE_CE_H_ + +/* + * @d_DST_WR_INDEX_ADDRESS: Destination ring write index + * + * @d_SRC_WATERMARK_ADDRESS: Source ring watermark + * + * @d_SRC_WATERMARK_LOW_MASK: Bits indicating low watermark from Source ring + * watermark + * + * @d_SRC_WATERMARK_HIGH_MASK: Bits indicating high watermark from Source ring + * watermark + * + * @d_DST_WATERMARK_LOW_MASK: Bits indicating low watermark from Destination + * ring watermark + * + * @d_DST_WATERMARK_HIGH_MASK: Bits indicating high watermark from Destination + * ring watermark + * + * @d_CURRENT_SRRI_ADDRESS: Current source ring read index.The Start Offset + * will be reflected after a CE transfer is completed. + * + * @d_CURRENT_DRRI_ADDRESS: Current Destination ring read index. The Start + * Offset will be reflected after a CE transfer + * is completed. + * + * @d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK: Source ring high watermark + * Interrupt Status + * + * @d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK: Source ring low watermark + * Interrupt Status + * + * @d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK: Destination ring high watermark + * Interrupt Status + * + * @d_HOST_IS_DST_RING_LOW_WATERMARK_MASK: Source ring low watermark + * Interrupt Status + * + * @d_HOST_IS_ADDRESS: Host Interrupt Status Register + * + * @d_MISC_IS_ADDRESS: Miscellaneous Interrupt Status Register + * + * @d_HOST_IS_COPY_COMPLETE_MASK: Bits indicating Copy complete interrupt + * status from the Host Interrupt Status + * register + * + * @d_CE_WRAPPER_BASE_ADDRESS: Copy Engine Wrapper Base Address + * + * @d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS: CE Wrapper summary for interrupts + * to host + * + * @d_CE_WRAPPER_INDEX_BASE_LOW: The LSB Base address to which source and + * destination read indices are written + * + * @d_CE_WRAPPER_INDEX_BASE_HIGH: The MSB Base address to which source and + * destination read indices are written + * + * @d_HOST_IE_ADDRESS: Host Line Interrupt Enable Register + * + * @d_HOST_IE_COPY_COMPLETE_MASK: Bits indicating Copy complete interrupt + * enable from the IE register + * + * @d_SR_BA_ADDRESS: LSB of Source Ring Base Address + * + * @d_SR_BA_ADDRESS_HIGH: MSB of Source Ring Base Address + * + * @d_SR_SIZE_ADDRESS: Source Ring size - number of entries and Start Offset + * + * @d_CE_CTRL1_ADDRESS: CE Control register + * + * @d_CE_CTRL1_DMAX_LENGTH_MASK: Destination buffer Max Length used for error + * check + * + * @d_DR_BA_ADDRESS: Destination Ring Base Address Low + * + * @d_DR_BA_ADDRESS_HIGH: Destination Ring Base Address High + * + * @d_DR_SIZE_ADDRESS: Destination Ring size - number of entries Start Offset + * + * @d_CE_CMD_REGISTER: Implements commands to all CE Halt Flush + * + * @d_CE_MSI_ADDRESS: CE MSI LOW Address register + * + * @d_CE_MSI_ADDRESS_HIGH: CE MSI High Address register + * + * @d_CE_MSI_DATA: CE MSI Data Register + * + * @d_CE_MSI_ENABLE_BIT: Bit in CTRL1 register indication the MSI enable + * + * @d_MISC_IE_ADDRESS: Miscellaneous Interrupt Enable Register + * + * @d_MISC_IS_AXI_ERR_MASK: Bit in Misc IS indicating AXI Timeout Interrupt + * status + * + * @d_MISC_IS_DST_ADDR_ERR_MASK: Bit in Misc IS indicating Destination Address + * Error + * + * @d_MISC_IS_SRC_LEN_ERR_MASK: Bit in Misc IS indicating Source Zero Length + * Error Interrupt status + * + * @d_MISC_IS_DST_MAX_LEN_VIO_MASK: Bit in Misc IS indicating Destination Max + * Length Violated Interrupt status + * + * @d_MISC_IS_DST_RING_OVERFLOW_MASK: Bit in Misc IS indicating Destination + * Ring Overflow Interrupt status + * + * @d_MISC_IS_SRC_RING_OVERFLOW_MASK: Bit in Misc IS indicating Source Ring + * Overflow Interrupt status + * + * @d_SRC_WATERMARK_LOW_LSB: Source Ring Low Watermark LSB + * + * @d_SRC_WATERMARK_HIGH_LSB: Source Ring Low Watermark MSB + * + * @d_DST_WATERMARK_LOW_LSB: Destination Ring Low Watermark LSB + * + * @d_DST_WATERMARK_HIGH_LSB: Destination Ring High Watermark LSB + * + * + * @d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK: Bits in + * d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDR + * indicating Copy engine + * miscellaneous interrupt summary + * + * @d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB:Bits in + * d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDR + * indicating Host interrupts summary + * + * @d_CE_CTRL1_DMAX_LENGTH_LSB: LSB of Destination buffer Max Length used for + * error check + * + * @d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK: Bits indicating Source ring Byte Swap + * enable. Treats source ring memory + * organisation as big-endian + * + * @d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK: Bits indicating Destination ring + * byte swap enable. Treats destination + * ring memory organisation as big-endian + * + * @d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB: LSB of Source ring Byte Swap enable + * + * @d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB: LSB of Destination ring Byte Swap enable + * + * @d_CE_WRAPPER_DEBUG_OFFSET: Offset of CE OBS BUS Select register + * + * @d_CE_WRAPPER_DEBUG_SEL_MSB: MSB of Control register selecting inputs for + * trace/debug + * + * @d_CE_WRAPPER_DEBUG_SEL_LSB: LSB of Control register selecting inputs for + * trace/debug + * + * @d_CE_WRAPPER_DEBUG_SEL_MASK: Bits indicating Control register selecting + * inputs for trace/debug + * + * @d_CE_DEBUG_OFFSET: Offset of Copy Engine FSM Debug Status + * + * @d_CE_DEBUG_SEL_MSB: MSB of Copy Engine FSM Debug Status + * + * @d_CE_DEBUG_SEL_LSB: LSB of Copy Engine FSM Debug Status + * + * @d_CE_DEBUG_SEL_MASK: Bits indicating Copy Engine FSM Debug Status + * +*/ + +struct ce_reg_def { + /* copy_engine.c */ + uint32_t d_DST_WR_INDEX_ADDRESS; + uint32_t d_SRC_WATERMARK_ADDRESS; + uint32_t d_SRC_WATERMARK_LOW_MASK; + uint32_t d_SRC_WATERMARK_HIGH_MASK; + uint32_t d_DST_WATERMARK_LOW_MASK; + uint32_t d_DST_WATERMARK_HIGH_MASK; + uint32_t d_CURRENT_SRRI_ADDRESS; + uint32_t d_CURRENT_DRRI_ADDRESS; + uint32_t d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK; + uint32_t d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK; + uint32_t d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK; + uint32_t d_HOST_IS_DST_RING_LOW_WATERMARK_MASK; + uint32_t d_HOST_IS_ADDRESS; + uint32_t d_MISC_IS_ADDRESS; + uint32_t d_HOST_IS_COPY_COMPLETE_MASK; + uint32_t d_CE_WRAPPER_BASE_ADDRESS; + uint32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS; + uint32_t d_CE_WRAPPER_INDEX_BASE_LOW; + uint32_t d_CE_WRAPPER_INDEX_BASE_HIGH; + uint32_t d_HOST_IE_ADDRESS; + uint32_t d_HOST_IE_COPY_COMPLETE_MASK; + uint32_t d_SR_BA_ADDRESS; + uint32_t d_SR_BA_ADDRESS_HIGH; + uint32_t d_SR_SIZE_ADDRESS; + uint32_t d_CE_CTRL1_ADDRESS; + uint32_t d_CE_CTRL1_DMAX_LENGTH_MASK; + uint32_t d_DR_BA_ADDRESS; + uint32_t d_DR_BA_ADDRESS_HIGH; + uint32_t d_DR_SIZE_ADDRESS; + uint32_t d_CE_CMD_REGISTER; + uint32_t d_CE_MSI_ADDRESS; + uint32_t d_CE_MSI_ADDRESS_HIGH; + uint32_t d_CE_MSI_DATA; + uint32_t d_CE_MSI_ENABLE_BIT; + uint32_t d_MISC_IE_ADDRESS; + uint32_t d_MISC_IS_AXI_ERR_MASK; + uint32_t d_MISC_IS_DST_ADDR_ERR_MASK; + uint32_t d_MISC_IS_SRC_LEN_ERR_MASK; + uint32_t d_MISC_IS_DST_MAX_LEN_VIO_MASK; + uint32_t d_MISC_IS_DST_RING_OVERFLOW_MASK; + uint32_t d_MISC_IS_SRC_RING_OVERFLOW_MASK; + uint32_t d_SRC_WATERMARK_LOW_LSB; + uint32_t d_SRC_WATERMARK_HIGH_LSB; + uint32_t d_DST_WATERMARK_LOW_LSB; + uint32_t d_DST_WATERMARK_HIGH_LSB; + uint32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK; + uint32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB; + uint32_t d_CE_CTRL1_DMAX_LENGTH_LSB; + uint32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK; + uint32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK; + uint32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB; + uint32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB; + uint32_t d_CE_WRAPPER_DEBUG_OFFSET; + uint32_t d_CE_WRAPPER_DEBUG_SEL_MSB; + uint32_t d_CE_WRAPPER_DEBUG_SEL_LSB; + uint32_t d_CE_WRAPPER_DEBUG_SEL_MASK; + uint32_t d_CE_DEBUG_OFFSET; + uint32_t d_CE_DEBUG_SEL_MSB; + uint32_t d_CE_DEBUG_SEL_LSB; + uint32_t d_CE_DEBUG_SEL_MASK; + uint32_t d_CE0_BASE_ADDRESS; + uint32_t d_CE1_BASE_ADDRESS; + uint32_t d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES; + uint32_t d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS; +}; +#endif /* _REGTABLE_CE_H_ */ diff --git a/core/hif/inc/regtable_pcie.h b/core/hif/inc/regtable_pcie.h new file mode 100644 index 000000000000..1ae7b181ab82 --- /dev/null +++ b/core/hif/inc/regtable_pcie.h @@ -0,0 +1,1030 @@ +/* + * 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_PCIE_H_ +#define _REGTABLE_PCIE_H_ + +#define MISSING 0 + +struct targetdef_s { + uint32_t d_RTC_SOC_BASE_ADDRESS; + uint32_t d_RTC_WMAC_BASE_ADDRESS; + uint32_t d_SYSTEM_SLEEP_OFFSET; + uint32_t d_WLAN_SYSTEM_SLEEP_OFFSET; + uint32_t d_WLAN_SYSTEM_SLEEP_DISABLE_LSB; + uint32_t d_WLAN_SYSTEM_SLEEP_DISABLE_MASK; + uint32_t d_CLOCK_CONTROL_OFFSET; + uint32_t d_CLOCK_CONTROL_SI0_CLK_MASK; + uint32_t d_RESET_CONTROL_OFFSET; + uint32_t d_RESET_CONTROL_MBOX_RST_MASK; + uint32_t d_RESET_CONTROL_SI0_RST_MASK; + uint32_t d_WLAN_RESET_CONTROL_OFFSET; + uint32_t d_WLAN_RESET_CONTROL_COLD_RST_MASK; + uint32_t d_WLAN_RESET_CONTROL_WARM_RST_MASK; + uint32_t d_GPIO_BASE_ADDRESS; + uint32_t d_GPIO_PIN0_OFFSET; + uint32_t d_GPIO_PIN1_OFFSET; + uint32_t d_GPIO_PIN0_CONFIG_MASK; + uint32_t d_GPIO_PIN1_CONFIG_MASK; + uint32_t d_SI_CONFIG_BIDIR_OD_DATA_LSB; + uint32_t d_SI_CONFIG_BIDIR_OD_DATA_MASK; + uint32_t d_SI_CONFIG_I2C_LSB; + uint32_t d_SI_CONFIG_I2C_MASK; + uint32_t d_SI_CONFIG_POS_SAMPLE_LSB; + uint32_t d_SI_CONFIG_POS_SAMPLE_MASK; + uint32_t d_SI_CONFIG_INACTIVE_CLK_LSB; + uint32_t d_SI_CONFIG_INACTIVE_CLK_MASK; + uint32_t d_SI_CONFIG_INACTIVE_DATA_LSB; + uint32_t d_SI_CONFIG_INACTIVE_DATA_MASK; + uint32_t d_SI_CONFIG_DIVIDER_LSB; + uint32_t d_SI_CONFIG_DIVIDER_MASK; + uint32_t d_SI_BASE_ADDRESS; + uint32_t d_SI_CONFIG_OFFSET; + uint32_t d_SI_TX_DATA0_OFFSET; + uint32_t d_SI_TX_DATA1_OFFSET; + uint32_t d_SI_RX_DATA0_OFFSET; + uint32_t d_SI_RX_DATA1_OFFSET; + uint32_t d_SI_CS_OFFSET; + uint32_t d_SI_CS_DONE_ERR_MASK; + uint32_t d_SI_CS_DONE_INT_MASK; + uint32_t d_SI_CS_START_LSB; + uint32_t d_SI_CS_START_MASK; + uint32_t d_SI_CS_RX_CNT_LSB; + uint32_t d_SI_CS_RX_CNT_MASK; + uint32_t d_SI_CS_TX_CNT_LSB; + uint32_t d_SI_CS_TX_CNT_MASK; + uint32_t d_BOARD_DATA_SZ; + uint32_t d_BOARD_EXT_DATA_SZ; + uint32_t d_MBOX_BASE_ADDRESS; + uint32_t d_LOCAL_SCRATCH_OFFSET; + uint32_t d_CPU_CLOCK_OFFSET; + uint32_t d_LPO_CAL_OFFSET; + uint32_t d_GPIO_PIN10_OFFSET; + uint32_t d_GPIO_PIN11_OFFSET; + uint32_t d_GPIO_PIN12_OFFSET; + uint32_t d_GPIO_PIN13_OFFSET; + uint32_t d_CLOCK_GPIO_OFFSET; + uint32_t d_CPU_CLOCK_STANDARD_LSB; + uint32_t d_CPU_CLOCK_STANDARD_MASK; + uint32_t d_LPO_CAL_ENABLE_LSB; + uint32_t d_LPO_CAL_ENABLE_MASK; + uint32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB; + uint32_t d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK; + uint32_t d_ANALOG_INTF_BASE_ADDRESS; + uint32_t d_WLAN_MAC_BASE_ADDRESS; + uint32_t d_FW_INDICATOR_ADDRESS; + uint32_t d_DRAM_BASE_ADDRESS; + uint32_t d_SOC_CORE_BASE_ADDRESS; + uint32_t d_CORE_CTRL_ADDRESS; + uint32_t d_CE_COUNT; + uint32_t d_MSI_NUM_REQUEST; + uint32_t d_MSI_ASSIGN_FW; + uint32_t d_MSI_ASSIGN_CE_INITIAL; + uint32_t d_PCIE_INTR_ENABLE_ADDRESS; + uint32_t d_PCIE_INTR_CLR_ADDRESS; + uint32_t d_PCIE_INTR_FIRMWARE_MASK; + uint32_t d_PCIE_INTR_CE_MASK_ALL; + uint32_t d_CORE_CTRL_CPU_INTR_MASK; + uint32_t d_SR_WR_INDEX_ADDRESS; + uint32_t d_DST_WATERMARK_ADDRESS; + + /* htt_rx.c */ + uint32_t d_RX_MSDU_END_4_FIRST_MSDU_MASK; + uint32_t d_RX_MSDU_END_4_FIRST_MSDU_LSB; + uint32_t d_RX_MPDU_START_0_RETRY_LSB; + uint32_t d_RX_MPDU_START_0_RETRY_MASK; + uint32_t d_RX_MPDU_START_0_SEQ_NUM_MASK; + uint32_t d_RX_MPDU_START_0_SEQ_NUM_LSB; + uint32_t d_RX_MPDU_START_2_PN_47_32_LSB; + uint32_t d_RX_MPDU_START_2_PN_47_32_MASK; + uint32_t d_RX_MPDU_START_2_TID_LSB; + uint32_t d_RX_MPDU_START_2_TID_MASK; + uint32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK; + uint32_t d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB; + uint32_t d_RX_MSDU_END_1_KEY_ID_OCT_MASK; + uint32_t d_RX_MSDU_END_1_KEY_ID_OCT_LSB; + uint32_t d_RX_MSDU_END_4_LAST_MSDU_MASK; + uint32_t d_RX_MSDU_END_4_LAST_MSDU_LSB; + uint32_t d_RX_ATTENTION_0_MCAST_BCAST_MASK; + uint32_t d_RX_ATTENTION_0_MCAST_BCAST_LSB; + uint32_t d_RX_ATTENTION_0_FRAGMENT_MASK; + uint32_t d_RX_ATTENTION_0_FRAGMENT_LSB; + uint32_t d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK; + uint32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK; + uint32_t d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB; + uint32_t d_RX_MSDU_START_0_MSDU_LENGTH_MASK; + uint32_t d_RX_MSDU_START_0_MSDU_LENGTH_LSB; + uint32_t d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET; + uint32_t d_RX_MSDU_START_2_DECAP_FORMAT_MASK; + uint32_t d_RX_MSDU_START_2_DECAP_FORMAT_LSB; + uint32_t d_RX_MPDU_START_0_ENCRYPTED_MASK; + uint32_t d_RX_MPDU_START_0_ENCRYPTED_LSB; + uint32_t d_RX_ATTENTION_0_MORE_DATA_MASK; + uint32_t d_RX_ATTENTION_0_MSDU_DONE_MASK; + uint32_t d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK; + /* end */ + + /* PLL start */ + uint32_t d_EFUSE_OFFSET; + uint32_t d_EFUSE_XTAL_SEL_MSB; + uint32_t d_EFUSE_XTAL_SEL_LSB; + uint32_t d_EFUSE_XTAL_SEL_MASK; + uint32_t d_BB_PLL_CONFIG_OFFSET; + uint32_t d_BB_PLL_CONFIG_OUTDIV_MSB; + uint32_t d_BB_PLL_CONFIG_OUTDIV_LSB; + uint32_t d_BB_PLL_CONFIG_OUTDIV_MASK; + uint32_t d_BB_PLL_CONFIG_FRAC_MSB; + uint32_t d_BB_PLL_CONFIG_FRAC_LSB; + uint32_t d_BB_PLL_CONFIG_FRAC_MASK; + uint32_t d_WLAN_PLL_SETTLE_TIME_MSB; + uint32_t d_WLAN_PLL_SETTLE_TIME_LSB; + uint32_t d_WLAN_PLL_SETTLE_TIME_MASK; + uint32_t d_WLAN_PLL_SETTLE_OFFSET; + uint32_t d_WLAN_PLL_SETTLE_SW_MASK; + uint32_t d_WLAN_PLL_SETTLE_RSTMASK; + uint32_t d_WLAN_PLL_SETTLE_RESET; + uint32_t d_WLAN_PLL_CONTROL_NOPWD_MSB; + uint32_t d_WLAN_PLL_CONTROL_NOPWD_LSB; + uint32_t d_WLAN_PLL_CONTROL_NOPWD_MASK; + uint32_t d_WLAN_PLL_CONTROL_BYPASS_MSB; + uint32_t d_WLAN_PLL_CONTROL_BYPASS_LSB; + uint32_t d_WLAN_PLL_CONTROL_BYPASS_MASK; + uint32_t d_WLAN_PLL_CONTROL_BYPASS_RESET; + uint32_t d_WLAN_PLL_CONTROL_CLK_SEL_MSB; + uint32_t d_WLAN_PLL_CONTROL_CLK_SEL_LSB; + uint32_t d_WLAN_PLL_CONTROL_CLK_SEL_MASK; + uint32_t d_WLAN_PLL_CONTROL_CLK_SEL_RESET; + uint32_t d_WLAN_PLL_CONTROL_REFDIV_MSB; + uint32_t d_WLAN_PLL_CONTROL_REFDIV_LSB; + uint32_t d_WLAN_PLL_CONTROL_REFDIV_MASK; + uint32_t d_WLAN_PLL_CONTROL_REFDIV_RESET; + uint32_t d_WLAN_PLL_CONTROL_DIV_MSB; + uint32_t d_WLAN_PLL_CONTROL_DIV_LSB; + uint32_t d_WLAN_PLL_CONTROL_DIV_MASK; + uint32_t d_WLAN_PLL_CONTROL_DIV_RESET; + uint32_t d_WLAN_PLL_CONTROL_OFFSET; + uint32_t d_WLAN_PLL_CONTROL_SW_MASK; + uint32_t d_WLAN_PLL_CONTROL_RSTMASK; + uint32_t d_WLAN_PLL_CONTROL_RESET; + uint32_t d_SOC_CORE_CLK_CTRL_OFFSET; + uint32_t d_SOC_CORE_CLK_CTRL_DIV_MSB; + uint32_t d_SOC_CORE_CLK_CTRL_DIV_LSB; + uint32_t d_SOC_CORE_CLK_CTRL_DIV_MASK; + uint32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MSB; + uint32_t d_RTC_SYNC_STATUS_PLL_CHANGING_LSB; + uint32_t d_RTC_SYNC_STATUS_PLL_CHANGING_MASK; + uint32_t d_RTC_SYNC_STATUS_PLL_CHANGING_RESET; + uint32_t d_RTC_SYNC_STATUS_OFFSET; + uint32_t d_SOC_CPU_CLOCK_OFFSET; + uint32_t d_SOC_CPU_CLOCK_STANDARD_MSB; + uint32_t d_SOC_CPU_CLOCK_STANDARD_LSB; + uint32_t d_SOC_CPU_CLOCK_STANDARD_MASK; + /* PLL end */ + + uint32_t d_SOC_POWER_REG_OFFSET; + uint32_t d_PCIE_INTR_CAUSE_ADDRESS; + uint32_t d_SOC_RESET_CONTROL_ADDRESS; + uint32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK; + uint32_t d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB; + uint32_t d_SOC_RESET_CONTROL_CE_RST_MASK; + uint32_t d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK; + uint32_t d_CPU_INTR_ADDRESS; + uint32_t d_SOC_LF_TIMER_CONTROL0_ADDRESS; + uint32_t d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK; + + /* chip id start */ + uint32_t d_SOC_CHIP_ID_ADDRESS; + uint32_t d_SOC_CHIP_ID_VERSION_MASK; + uint32_t d_SOC_CHIP_ID_VERSION_LSB; + uint32_t d_SOC_CHIP_ID_REVISION_MASK; + uint32_t d_SOC_CHIP_ID_REVISION_LSB; + /* chip id end */ + + uint32_t d_A_SOC_CORE_SCRATCH_0_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_1_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_2_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_3_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_4_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_5_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_6_ADDRESS; + uint32_t d_A_SOC_CORE_SCRATCH_7_ADDRESS; + uint32_t d_A_SOC_CORE_SPARE_0_REGISTER; + uint32_t d_PCIE_INTR_FIRMWARE_ROUTE_MASK; + uint32_t d_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1; + uint32_t d_A_SOC_CORE_SPARE_1_REGISTER; + uint32_t d_A_SOC_CORE_PCIE_INTR_CLR_GRP1; + uint32_t d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1; + uint32_t d_A_SOC_PCIE_PCIE_SCRATCH_0; + uint32_t d_A_SOC_PCIE_PCIE_SCRATCH_1; + uint32_t d_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA; + uint32_t d_A_SOC_PCIE_PCIE_SCRATCH_2; + uint32_t d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK; + + uint32_t d_WLAN_DEBUG_INPUT_SEL_OFFSET; + uint32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MSB; + uint32_t d_WLAN_DEBUG_INPUT_SEL_SRC_LSB; + uint32_t d_WLAN_DEBUG_INPUT_SEL_SRC_MASK; + uint32_t d_WLAN_DEBUG_CONTROL_OFFSET; + uint32_t d_WLAN_DEBUG_CONTROL_ENABLE_MSB; + uint32_t d_WLAN_DEBUG_CONTROL_ENABLE_LSB; + uint32_t d_WLAN_DEBUG_CONTROL_ENABLE_MASK; + uint32_t d_WLAN_DEBUG_OUT_OFFSET; + uint32_t d_WLAN_DEBUG_OUT_DATA_MSB; + uint32_t d_WLAN_DEBUG_OUT_DATA_LSB; + uint32_t d_WLAN_DEBUG_OUT_DATA_MASK; + uint32_t d_AMBA_DEBUG_BUS_OFFSET; + uint32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB; + uint32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB; + uint32_t d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK; + uint32_t d_AMBA_DEBUG_BUS_SEL_MSB; + uint32_t d_AMBA_DEBUG_BUS_SEL_LSB; + uint32_t d_AMBA_DEBUG_BUS_SEL_MASK; + +#ifdef QCA_WIFI_3_0_ADRASTEA + uint32_t d_Q6_ENABLE_REGISTER_0; + uint32_t d_Q6_ENABLE_REGISTER_1; + uint32_t d_Q6_CAUSE_REGISTER_0; + uint32_t d_Q6_CAUSE_REGISTER_1; + uint32_t d_Q6_CLEAR_REGISTER_0; + uint32_t d_Q6_CLEAR_REGISTER_1; +#endif +}; + +#define A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK) +#define A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1) +#define A_SOC_CORE_SPARE_1_REGISTER \ + (scn->targetdef->d_A_SOC_CORE_SPARE_1_REGISTER) +#define A_SOC_CORE_PCIE_INTR_CLR_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_CLR_GRP1) +#define A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1) +#define A_SOC_PCIE_PCIE_SCRATCH_0 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_0) +#define A_SOC_PCIE_PCIE_SCRATCH_1 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_1) +#define A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA \ + (scn->targetdef->d_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA) +#define A_SOC_PCIE_PCIE_SCRATCH_2 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_2) +/* end Q6 iHelium emu registers */ + +#define PCIE_INTR_FIRMWARE_ROUTE_MASK \ + (scn->targetdef->d_PCIE_INTR_FIRMWARE_ROUTE_MASK) +#define A_SOC_CORE_SPARE_0_REGISTER \ + (scn->targetdef->d_A_SOC_CORE_SPARE_0_REGISTER) +#define A_SOC_CORE_SCRATCH_0_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_0_ADDRESS) +#define A_SOC_CORE_SCRATCH_1_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_1_ADDRESS) +#define A_SOC_CORE_SCRATCH_2_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_2_ADDRESS) +#define A_SOC_CORE_SCRATCH_3_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_3_ADDRESS) +#define A_SOC_CORE_SCRATCH_4_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_4_ADDRESS) +#define A_SOC_CORE_SCRATCH_5_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_5_ADDRESS) +#define A_SOC_CORE_SCRATCH_6_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_6_ADDRESS) +#define A_SOC_CORE_SCRATCH_7_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_7_ADDRESS) +#define RTC_SOC_BASE_ADDRESS (scn->targetdef->d_RTC_SOC_BASE_ADDRESS) +#define RTC_WMAC_BASE_ADDRESS (scn->targetdef->d_RTC_WMAC_BASE_ADDRESS) +#define SYSTEM_SLEEP_OFFSET (scn->targetdef->d_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_OFFSET \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define CLOCK_CONTROL_OFFSET (scn->targetdef->d_CLOCK_CONTROL_OFFSET) +#define CLOCK_CONTROL_SI0_CLK_MASK \ + (scn->targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK) +#define RESET_CONTROL_OFFSET (scn->targetdef->d_RESET_CONTROL_OFFSET) +#define RESET_CONTROL_MBOX_RST_MASK \ + (scn->targetdef->d_RESET_CONTROL_MBOX_RST_MASK) +#define RESET_CONTROL_SI0_RST_MASK \ + (scn->targetdef->d_RESET_CONTROL_SI0_RST_MASK) +#define WLAN_RESET_CONTROL_OFFSET \ + (scn->targetdef->d_WLAN_RESET_CONTROL_OFFSET) +#define WLAN_RESET_CONTROL_COLD_RST_MASK \ + (scn->targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MASK \ + (scn->targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK) +#define GPIO_BASE_ADDRESS (scn->targetdef->d_GPIO_BASE_ADDRESS) +#define GPIO_PIN0_OFFSET (scn->targetdef->d_GPIO_PIN0_OFFSET) +#define GPIO_PIN1_OFFSET (scn->targetdef->d_GPIO_PIN1_OFFSET) +#define GPIO_PIN0_CONFIG_MASK (scn->targetdef->d_GPIO_PIN0_CONFIG_MASK) +#define GPIO_PIN1_CONFIG_MASK (scn->targetdef->d_GPIO_PIN1_CONFIG_MASK) +#define A_SOC_CORE_SCRATCH_0 (scn->targetdef->d_A_SOC_CORE_SCRATCH_0) +#define SI_CONFIG_BIDIR_OD_DATA_LSB \ + (scn->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB) +#define SI_CONFIG_BIDIR_OD_DATA_MASK \ + (scn->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_LSB (scn->targetdef->d_SI_CONFIG_I2C_LSB) +#define SI_CONFIG_I2C_MASK \ + (scn->targetdef->d_SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_LSB \ + (scn->targetdef->d_SI_CONFIG_POS_SAMPLE_LSB) +#define SI_CONFIG_POS_SAMPLE_MASK \ + (scn->targetdef->d_SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_LSB \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB) +#define SI_CONFIG_INACTIVE_CLK_MASK \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_LSB \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB) +#define SI_CONFIG_INACTIVE_DATA_MASK \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_LSB (scn->targetdef->d_SI_CONFIG_DIVIDER_LSB) +#define SI_CONFIG_DIVIDER_MASK (scn->targetdef->d_SI_CONFIG_DIVIDER_MASK) +#define SI_BASE_ADDRESS (scn->targetdef->d_SI_BASE_ADDRESS) +#define SI_CONFIG_OFFSET (scn->targetdef->d_SI_CONFIG_OFFSET) +#define SI_TX_DATA0_OFFSET (scn->targetdef->d_SI_TX_DATA0_OFFSET) +#define SI_TX_DATA1_OFFSET (scn->targetdef->d_SI_TX_DATA1_OFFSET) +#define SI_RX_DATA0_OFFSET (scn->targetdef->d_SI_RX_DATA0_OFFSET) +#define SI_RX_DATA1_OFFSET (scn->targetdef->d_SI_RX_DATA1_OFFSET) +#define SI_CS_OFFSET (scn->targetdef->d_SI_CS_OFFSET) +#define SI_CS_DONE_ERR_MASK (scn->targetdef->d_SI_CS_DONE_ERR_MASK) +#define SI_CS_DONE_INT_MASK (scn->targetdef->d_SI_CS_DONE_INT_MASK) +#define SI_CS_START_LSB (scn->targetdef->d_SI_CS_START_LSB) +#define SI_CS_START_MASK (scn->targetdef->d_SI_CS_START_MASK) +#define SI_CS_RX_CNT_LSB (scn->targetdef->d_SI_CS_RX_CNT_LSB) +#define SI_CS_RX_CNT_MASK (scn->targetdef->d_SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_LSB (scn->targetdef->d_SI_CS_TX_CNT_LSB) +#define SI_CS_TX_CNT_MASK (scn->targetdef->d_SI_CS_TX_CNT_MASK) +#define EEPROM_SZ (scn->targetdef->d_BOARD_DATA_SZ) +#define EEPROM_EXT_SZ (scn->targetdef->d_BOARD_EXT_DATA_SZ) +#define MBOX_BASE_ADDRESS (scn->targetdef->d_MBOX_BASE_ADDRESS) +#define LOCAL_SCRATCH_OFFSET (scn->targetdef->d_LOCAL_SCRATCH_OFFSET) +#define CPU_CLOCK_OFFSET (scn->targetdef->d_CPU_CLOCK_OFFSET) +#define LPO_CAL_OFFSET (scn->targetdef->d_LPO_CAL_OFFSET) +#define GPIO_PIN10_OFFSET (scn->targetdef->d_GPIO_PIN10_OFFSET) +#define GPIO_PIN11_OFFSET (scn->targetdef->d_GPIO_PIN11_OFFSET) +#define GPIO_PIN12_OFFSET (scn->targetdef->d_GPIO_PIN12_OFFSET) +#define GPIO_PIN13_OFFSET (scn->targetdef->d_GPIO_PIN13_OFFSET) +#define CLOCK_GPIO_OFFSET (scn->targetdef->d_CLOCK_GPIO_OFFSET) +#define CPU_CLOCK_STANDARD_LSB (scn->targetdef->d_CPU_CLOCK_STANDARD_LSB) +#define CPU_CLOCK_STANDARD_MASK (scn->targetdef->d_CPU_CLOCK_STANDARD_MASK) +#define LPO_CAL_ENABLE_LSB (scn->targetdef->d_LPO_CAL_ENABLE_LSB) +#define LPO_CAL_ENABLE_MASK (scn->targetdef->d_LPO_CAL_ENABLE_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB \ + (scn->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB) +#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK \ + (scn->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +#define ANALOG_INTF_BASE_ADDRESS (scn->targetdef->d_ANALOG_INTF_BASE_ADDRESS) +#define WLAN_MAC_BASE_ADDRESS (scn->targetdef->d_WLAN_MAC_BASE_ADDRESS) +#define FW_INDICATOR_ADDRESS (scn->targetdef->d_FW_INDICATOR_ADDRESS) +#define DRAM_BASE_ADDRESS (scn->targetdef->d_DRAM_BASE_ADDRESS) +#define SOC_CORE_BASE_ADDRESS (scn->targetdef->d_SOC_CORE_BASE_ADDRESS) +#define CORE_CTRL_ADDRESS (scn->targetdef->d_CORE_CTRL_ADDRESS) +#define CE_COUNT (scn->targetdef->d_CE_COUNT) +#define PCIE_INTR_ENABLE_ADDRESS (scn->targetdef->d_PCIE_INTR_ENABLE_ADDRESS) +#define PCIE_INTR_CLR_ADDRESS (scn->targetdef->d_PCIE_INTR_CLR_ADDRESS) +#define PCIE_INTR_FIRMWARE_MASK (scn->targetdef->d_PCIE_INTR_FIRMWARE_MASK) +#define PCIE_INTR_CE_MASK_ALL (scn->targetdef->d_PCIE_INTR_CE_MASK_ALL) +#define CORE_CTRL_CPU_INTR_MASK (scn->targetdef->d_CORE_CTRL_CPU_INTR_MASK) +#define PCIE_INTR_CAUSE_ADDRESS (scn->targetdef->d_PCIE_INTR_CAUSE_ADDRESS) +#define SOC_RESET_CONTROL_ADDRESS (scn->targetdef->d_SOC_RESET_CONTROL_ADDRESS) +#define HOST_GROUP0_MASK (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL | \ + A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK) +#define SOC_RESET_CONTROL_CE_RST_MASK \ + (scn->targetdef->d_SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK \ + (scn->targetdef->d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +#define CPU_INTR_ADDRESS (scn->targetdef->d_CPU_INTR_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ADDRESS \ + (scn->targetdef->d_SOC_LF_TIMER_CONTROL0_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK \ + (scn->targetdef->d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB \ + (scn->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK \ + (scn->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 (scn->targetdef->d_SOC_CHIP_ID_ADDRESS) +#define SOC_CHIP_ID_REVISION_MASK (scn->targetdef->d_SOC_CHIP_ID_REVISION_MASK) +#define SOC_CHIP_ID_REVISION_LSB (scn->targetdef->d_SOC_CHIP_ID_REVISION_LSB) +#define SOC_CHIP_ID_VERSION_MASK (scn->targetdef->d_SOC_CHIP_ID_VERSION_MASK) +#define SOC_CHIP_ID_VERSION_LSB (scn->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 (scn->targetdef->d_SR_WR_INDEX_ADDRESS) +#define DST_WATERMARK_ADDRESS (scn->targetdef->d_DST_WATERMARK_ADDRESS) +#define SOC_POWER_REG_OFFSET (scn->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 */ +/* end */ +/* PLL start */ +#define EFUSE_OFFSET (scn->targetdef->d_EFUSE_OFFSET) +#define EFUSE_XTAL_SEL_MSB (scn->targetdef->d_EFUSE_XTAL_SEL_MSB) +#define EFUSE_XTAL_SEL_LSB (scn->targetdef->d_EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_MASK (scn->targetdef->d_EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OFFSET (scn->targetdef->d_BB_PLL_CONFIG_OFFSET) +#define BB_PLL_CONFIG_OUTDIV_MSB (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_MSB) +#define BB_PLL_CONFIG_OUTDIV_LSB (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_MASK (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_MSB (scn->targetdef->d_BB_PLL_CONFIG_FRAC_MSB) +#define BB_PLL_CONFIG_FRAC_LSB (scn->targetdef->d_BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_MASK (scn->targetdef->d_BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_MSB (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_MSB) +#define WLAN_PLL_SETTLE_TIME_LSB (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_MASK (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_SETTLE_OFFSET (scn->targetdef->d_WLAN_PLL_SETTLE_OFFSET) +#define WLAN_PLL_SETTLE_SW_MASK (scn->targetdef->d_WLAN_PLL_SETTLE_SW_MASK) +#define WLAN_PLL_SETTLE_RSTMASK (scn->targetdef->d_WLAN_PLL_SETTLE_RSTMASK) +#define WLAN_PLL_SETTLE_RESET (scn->targetdef->d_WLAN_PLL_SETTLE_RESET) +#define WLAN_PLL_CONTROL_NOPWD_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MSB) +#define WLAN_PLL_CONTROL_NOPWD_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MSB) +#define WLAN_PLL_CONTROL_BYPASS_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_BYPASS_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_RESET) +#define WLAN_PLL_CONTROL_CLK_SEL_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MSB) +#define WLAN_PLL_CONTROL_CLK_SEL_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_RESET) +#define WLAN_PLL_CONTROL_REFDIV_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MSB) +#define WLAN_PLL_CONTROL_REFDIV_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_REFDIV_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_RESET) +#define WLAN_PLL_CONTROL_DIV_MSB (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_MSB) +#define WLAN_PLL_CONTROL_DIV_LSB (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_MASK (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_MASK) +#define WLAN_PLL_CONTROL_DIV_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_RESET) +#define WLAN_PLL_CONTROL_OFFSET (scn->targetdef->d_WLAN_PLL_CONTROL_OFFSET) +#define WLAN_PLL_CONTROL_SW_MASK (scn->targetdef->d_WLAN_PLL_CONTROL_SW_MASK) +#define WLAN_PLL_CONTROL_RSTMASK (scn->targetdef->d_WLAN_PLL_CONTROL_RSTMASK) +#define WLAN_PLL_CONTROL_RESET (scn->targetdef->d_WLAN_PLL_CONTROL_RESET) +#define SOC_CORE_CLK_CTRL_OFFSET (scn->targetdef->d_SOC_CORE_CLK_CTRL_OFFSET) +#define SOC_CORE_CLK_CTRL_DIV_MSB (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MSB) +#define SOC_CORE_CLK_CTRL_DIV_LSB (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_MASK \ + (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_MSB \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_LSB \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_MASK \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_RESET \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_RESET) +#define RTC_SYNC_STATUS_OFFSET (scn->targetdef->d_RTC_SYNC_STATUS_OFFSET) +#define SOC_CPU_CLOCK_OFFSET (scn->targetdef->d_SOC_CPU_CLOCK_OFFSET) +#define SOC_CPU_CLOCK_STANDARD_MSB \ + (scn->targetdef->d_SOC_CPU_CLOCK_STANDARD_MSB) +#define SOC_CPU_CLOCK_STANDARD_LSB \ + (scn->targetdef->d_SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_MASK \ + (scn->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 */ +/* 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 */ + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define Q6_ENABLE_REGISTER_0 \ + (scn->targetdef->d_Q6_ENABLE_REGISTER_0) +#define Q6_ENABLE_REGISTER_1 \ + (scn->targetdef->d_Q6_ENABLE_REGISTER_1) +#define Q6_CAUSE_REGISTER_0 \ + (scn->targetdef->d_Q6_CAUSE_REGISTER_0) +#define Q6_CAUSE_REGISTER_1 \ + (scn->targetdef->d_Q6_CAUSE_REGISTER_1) +#define Q6_CLEAR_REGISTER_0 \ + (scn->targetdef->d_Q6_CLEAR_REGISTER_0) +#define Q6_CLEAR_REGISTER_1 \ + (scn->targetdef->d_Q6_CLEAR_REGISTER_1) +#endif + +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; + uint32_t d_HOST_CE_COUNT; + uint32_t d_ENABLE_MSI; + uint32_t d_MUX_ID_MASK; + uint32_t d_TRANSACTION_ID_MASK; + uint32_t d_DESC_DATA_FLAG_MASK; + uint32_t d_A_SOC_PCIE_PCIE_BAR0_START; +}; +#define A_SOC_PCIE_PCIE_BAR0_START (scn->hostdef->d_A_SOC_PCIE_PCIE_BAR0_START) +#define DESC_DATA_FLAG_MASK (scn->hostdef->d_DESC_DATA_FLAG_MASK) +#define MUX_ID_MASK (scn->hostdef->d_MUX_ID_MASK) +#define TRANSACTION_ID_MASK (scn->hostdef->d_TRANSACTION_ID_MASK) +#define HOST_CE_COUNT (scn->hostdef->d_HOST_CE_COUNT) +#define ENABLE_MSI (scn->hostdef->d_ENABLE_MSI) +#define INT_STATUS_ENABLE_ERROR_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_LSB (scn->hostdef->d_INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_MASK (scn->hostdef->d_INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB \ + (scn->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK \ + (scn->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define INT_STATUS_ENABLE_ADDRESS \ + (scn->hostdef->d_INT_STATUS_ENABLE_ADDRESS) +#define CPU_INT_STATUS_ENABLE_BIT_LSB \ + (scn->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_MASK \ + (scn->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK) +#define HOST_INT_STATUS_ADDRESS (scn->hostdef->d_HOST_INT_STATUS_ADDRESS) +#define CPU_INT_STATUS_ADDRESS (scn->hostdef->d_CPU_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_ADDRESS (scn->hostdef->d_ERROR_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_WAKEUP_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_WAKEUP_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define COUNT_DEC_ADDRESS (scn->hostdef->d_COUNT_DEC_ADDRESS) +#define HOST_INT_STATUS_CPU_MASK (scn->hostdef->d_HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_CPU_LSB (scn->hostdef->d_HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_MASK (scn->hostdef->d_HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_ERROR_LSB (scn->hostdef->d_HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_MASK \ + (scn->hostdef->d_HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_COUNTER_LSB \ + (scn->hostdef->d_HOST_INT_STATUS_COUNTER_LSB) +#define RX_LOOKAHEAD_VALID_ADDRESS (scn->hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS) +#define WINDOW_DATA_ADDRESS (scn->hostdef->d_WINDOW_DATA_ADDRESS) +#define WINDOW_READ_ADDR_ADDRESS (scn->hostdef->d_WINDOW_READ_ADDR_ADDRESS) +#define WINDOW_WRITE_ADDR_ADDRESS (scn->hostdef->d_WINDOW_WRITE_ADDR_ADDRESS) +#define SOC_GLOBAL_RESET_ADDRESS (scn->hostdef->d_SOC_GLOBAL_RESET_ADDRESS) +#define RTC_STATE_ADDRESS (scn->hostdef->d_RTC_STATE_ADDRESS) +#define RTC_STATE_COLD_RESET_MASK (scn->hostdef->d_RTC_STATE_COLD_RESET_MASK) +#define PCIE_LOCAL_BASE_ADDRESS (scn->hostdef->d_PCIE_LOCAL_BASE_ADDRESS) +#define PCIE_SOC_WAKE_RESET (scn->hostdef->d_PCIE_SOC_WAKE_RESET) +#define PCIE_SOC_WAKE_ADDRESS (scn->hostdef->d_PCIE_SOC_WAKE_ADDRESS) +#define PCIE_SOC_WAKE_V_MASK (scn->hostdef->d_PCIE_SOC_WAKE_V_MASK) +#define RTC_STATE_V_MASK (scn->hostdef->d_RTC_STATE_V_MASK) +#define RTC_STATE_V_LSB (scn->hostdef->d_RTC_STATE_V_LSB) +#define FW_IND_EVENT_PENDING (scn->hostdef->d_FW_IND_EVENT_PENDING) +#define FW_IND_INITIALIZED (scn->hostdef->d_FW_IND_INITIALIZED) +#define FW_IND_HELPER (scn->hostdef->d_FW_IND_HELPER) +#define RTC_STATE_V_ON (scn->hostdef->d_RTC_STATE_V_ON) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_MASK \ + (scn->hostdef->d_HOST_INT_STATUS_MBOX_DATA_MASK) +#define HOST_INT_STATUS_MBOX_DATA_LSB \ + (scn->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 { + uint32_t refdiv; + uint32_t div; + uint32_t rnfrac; + uint32_t outdiv; +}; + +struct cmnos_clock_s { + A_refclk_speed_t refclk_speed; + uint32_t refclk_hz; + uint32_t pll_settling_time; /* 50us */ + struct wlan_pll_s wlan_pll; +}; + +typedef struct TGT_REG_SECTION { + uint32_t start_addr; + uint32_t end_addr; +} tgt_reg_section; + +typedef struct TGT_REG_TABLE { + tgt_reg_section *section; + uint32_t section_size; +} tgt_reg_table; + +struct ol_softc; +void target_register_tbl_attach(struct ol_softc *scn, u32 target_type); +void hif_register_tbl_attach(struct ol_softc *scn, u32 hif_type); + +struct host_shadow_regs_s { + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_0; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_1; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_2; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_3; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_4; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_5; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_6; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_7; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_8; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_9; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_10; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_11; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_12; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_13; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_14; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_15; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_16; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_17; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_18; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_19; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_20; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_21; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_22; + uint32_t d_A_LOCAL_SHADOW_REG_VALUE_23; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_0; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_1; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_2; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_3; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_4; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_5; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_6; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_7; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_8; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_9; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_10; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_11; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_12; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_13; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_14; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_15; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_16; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_17; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_18; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_19; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_20; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_21; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_22; + uint32_t d_A_LOCAL_SHADOW_REG_ADDRESS_23; +}; + +#endif /* _REGTABLE_PCIE_H_ */ diff --git a/core/hif/src/adrastea_reg_def.h b/core/hif/src/adrastea_reg_def.h new file mode 100644 index 000000000000..743d22ef5c28 --- /dev/null +++ b/core/hif/src/adrastea_reg_def.h @@ -0,0 +1,2352 @@ +/* + * 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 ADRASTEA_REG_DEF_H +#define ADRASTEA_REG_DEF_H + +/* + * Start auto-generated headers from register parser + * + * DO NOT CHANGE MANUALLY +*/ + + +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__SRC_FLUSH___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW (0x00241000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__SRC_RING_BYTE_SWAP_EN___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_MISC_P___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2 (0x00030028) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__FORCE_WAKE_CLEAR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__EXTERNAL_INTR___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW (0x00244000) +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SOFT_RESET___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR___M 0x000003FF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT_STATUS___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE (0x00032060) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6 (0x00030038) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_TIMEOUT_P___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH (0x00032064) +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID__BITS___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY___M 0x00FFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ERR_RESP_CLEAR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__FORCE_WAKE_CLEAR___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ECAHB_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__MCIM_INT___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN2_HW2SW_GRANT___M 0x00000080 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__SIZE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ECAHB_TIMEOUT___M 0x00000010 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__SRC_RING_BYTE_SWAP_EN___S 17 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS___M 0x0003FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_HIGH_WATERMARK___M 0x00000002 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX__SRC_WR_INDEX___M 0x0000FFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY___M 0x00FFF000 +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID___M 0x00FFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH__BASE_ADDR_HIGH___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4 (0x00030030) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_LEN_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_TIMEOUT_P___M 0x00000100 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ECAHB_TIMEOUT___S 4 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__DIRTY_BIT_SET___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX (0x00240040) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS (0x00240038) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_1_INTR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_PLL_REF_MUX_SEL___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR (0x002F1008) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_MAX_LEN_VIO___M 0x00000080 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_LOW_WATERMARK___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB__STATUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR___M 0x00000FFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__SRC_FLUSH___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20 (0x00030070) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12 (0x00032030) +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__CLOCK_GATE_DISABLE___M 0x00000002 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET__CE_INTR_LINE_HOST_P___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__EXTERNAL_INTR___S 18 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS__SELECT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX__DST_WR_INDEX___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES___M 0x00000FFF +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB (0x00032070) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN2_HW2SW_GRANT___M 0x00000080 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_OVERFLOW___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN2_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR__CE_INTR_LINE_HOST_P___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_SR_XO_SETTLE_TIMEOUT___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__COPY_COMPLETE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__BASE_ADDR_HIGH___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__SIZE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_HIGH_WATERMARK___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13 (0x00032034) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3 (0x0003002C) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID (0x000300E0) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22 (0x00032058) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_OVERFLOW___M 0x00000020 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__MSI_EN___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__VALUE_REG_UPDATED_WITH_INVALID_ADDR___M 0x00000020 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__SIZE___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__VALUE_REG_UPDATED_WITH_INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14 (0x00030058) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH___M 0x0000007F +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__CLOCK_GATE_DISABLE___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__IDX_UPD_EN___S 19 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB__STATUS___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1 (0x00032004) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_OVERFLOW___S 5 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_HIGH_WATER_MARK_THRESHOLD___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__BMH_INT___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__WCSS_CORE_WAKE_SLEEP_STATE___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_LOW_WATERMARK___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__DIRTY_BIT_SET_ENABLE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET__CE_INTR_LINE_HOST_P___M 0x00000FFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14 (0x00032038) +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_RF_XO_MUX_SEL___M 0x00000010 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__COPY_COMPLETE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__MISC___M 0x00000FFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_SR_XO_SETTLE_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY__ENABLE___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_STROBE_INTERRUPT___S 1 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_LOW_WATERMARK___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_LOW_WATERMARK___S 4 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS___M 0x0000001F +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23 (0x0003205C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE (0x00240034) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY (0x0024D000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15 (0x0003005C) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN1_SLP_TMR_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI__CURRENT_SRRI___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE (0x0024002C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_LOW_WATERMARK___S 4 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_SR_XO_SETTLE_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN2_HW2SW_GRANT___S 7 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH___M 0x0000001F +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__ADDRESS_BITS_17_TO_2___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ECAHB_TIMEOUT___M 0x00000010 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY___M 0x01FFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__PARSER_INT___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__COPY_COMPLETE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__ADDRESS_BITS_17_TO_2___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__ILL_REG___S 24 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_OVERFLOW___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__STATE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0 (0x00032000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_LOW_WATER_MARK_THRESOLD___M 0xFFFF0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR (0x00030014) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_MISC_P___M 0x00000080 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20 (0x00032050) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LMH_INT___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI__CURRENT_DRRI___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ERR_RESP_ENABLE___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN2_SLP_TMR_INTR___M 0x00008000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX__SRC_WR_INDEX___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__SRC_RING_BYTE_SWAP_EN___M 0x00020000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW (0x0024B000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET (0x002F1004) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2 (0x00032008) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__DESC_SKIP_DWORD___S 5 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_LOW_WATER_MARK_THRESHOLD___M 0xFFFF0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE__FORCE_WAKE_ENABLE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__BASE_ADDR_HIGH___POR 0x00 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__FORCE_WAKE_ENABLE___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__BMH_INT___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__DST_AXI_MAX_LEN___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__DESC_SKIP_DWORD___M 0x00000060 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SMH_INT___S 6 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__EXTERNAL_INTR___M 0x0FFC0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI__CURRENT_DRRI___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN1_HW2SW_GRANT___S 6 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_WCSS_WAKEUP_IRQ_ACK___S 8 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW (0x00245000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22 (0x00030078) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SMH_INT___M 0x00000040 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2___POR 0x00000005 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT_STATUS___S 3 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__DIRTY_BIT_SET___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__MISC___POR 0x000 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__FORCE_WAKE_ENABLE___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_OVERFLOW___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__ADDRESS_BITS_17_TO_2___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__DST_AXI_MAX_LEN___POR 0x1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK (0x0024004C) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ERR_RESP___M 0x00000004 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_WCSS_WAKEUP_IRQ_ACK___M 0x00000100 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_2_INTR___S 11 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17 (0x00030064) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW (0x0024000C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_1_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID__BITS___M 0x00FFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__DESC_SKIP_DWORD___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW (0x0024A000) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN1_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__MCIM_INT___S 4 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__SRC_AXI_MAX_LEN___M 0x00000003 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_OVERFLOW___M 0x00000040 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_WCSS_WAKEUP_IRQ_ACK___M 0x00000100 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS (0x00030008) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_PLL_REF_MUX_SEL___S 3 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__MSI_EN___M 0x00010000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__PARSER_INT___M 0x000FF800 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_LEN_ERR___S 8 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ECAHB_TIMEOUT___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19 (0x0003204C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_HIGH_WATERMARK___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5 (0x00030034) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_OVERFLOW___M 0x00000020 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR__CE_INTR_LINE_HOST_P___M 0x00000FFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__HOST___M 0x00FFF000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_RF_XO_MUX_SEL___S 4 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__MSI_EN___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__VALUE_REG_UPDATED_WITH_INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE___M 0x000FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__PARSER_INT___M 0x000FF800 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_HIGH_WATER_MARK_THRESHOLD___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WFSS_DBG_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__SIZE___M 0x0000FFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SW_SLP_TMR_INTR___M 0x00010000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_HIGH_WATER_MARK_THRESHOLD___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_WCSS_WAKEUP_IRQ_ACK___S 8 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB__STATUS___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_MAX_LEN_VIO___M 0x00000080 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__SIZE___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5 (0x00032014) +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS (0x0003000C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__DIRTY_BIT_SET_CLEAR___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH__BASE_ADDR_HIGH___M 0x0000001F +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__SRC_FLUSH___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_LOW_WATER_MARK_THRESHOLD___S 16 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9 (0x00032024) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__COPY_COMPLETE___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__WRITE_ACCESS___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE___M 0x0000001F +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__COPY_COMPLETE___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__PARSER_INT___S 11 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__HOST___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_OVERFLOW___S 6 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN1_SLP_TMR_INTR___M 0x00004000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ERR_RESP_CLEAR___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__WRITE_ACCESS___M 0x00020000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__VALUE_REG_UPDATED_WITH_INVALID_ADDR___S 5 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DEST_MAX_LENGTH___M 0x0000FFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT_STATUS___M 0x00000008 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_WCI2_INTERRUPT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_HIGH_WATERMARK___M 0x00000008 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1___POR 0x00000080 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__DIRTY_BIT_SET_CLEAR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_SR_XO_SETTLE_TIMEOUT___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18 (0x00032048) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__NOC_WCMN_INTR___M 0x00001000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK (0x00240050) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__DIRTY_BIT_SET___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB__STATUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__DIRTY_BIT_SET_ENABLE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__IDX_UPD_EN___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN1_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW (0x00243000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__START_OFFSET___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY (0x00030080) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW (0x00248000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_LOW_WATERMARK___S 2 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16 (0x00032040) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS___M 0x0000000F +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__START_OFFSET___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY (0x0024C000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN2_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__COPY_COMPLETE___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_2_INTR___M 0x00000800 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DST_RING_BYTE_SWAP_EN___S 18 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS (0x00032078) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB__STATUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH__SPARE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID__BITS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS__SELECT___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_LOW_WATERMARK___S 2 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LMH_INT___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_ADDRESS_VALID___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB__STATUS___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12 (0x00030050) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS__SELECT___M 0x00000007 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__PMH_INT___M 0x00000020 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__ENABLE_APSS_FULL_ACCESS___M 0x00000004 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN1_SLP_TMR_INTR___S 14 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_LOW_WATERMARK___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DST_RING_BYTE_SWAP_EN___M 0x00040000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_WCSS_WAKEUP_IRQ_ACK___S 8 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_LEN_ERR___M 0x00000100 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY__ENABLE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7 (0x0003003C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI__CURRENT_DRRI___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH__SPARE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_MAX_LEN_VIO___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET (0x002F0084) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET__CE_INTR_LINE_HOST_P___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_HIGH_WATER_MARK_THRESHOLD___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__READ_ACCESS___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__SIZE___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__ENABLE_APSS_FULL_ACCESS___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES__CE_INTR_LINE_HOST_P___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY__ENABLE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8 (0x00030040) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS (0x00240030) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_LOW_WATERMARK___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SOFT_RESET___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15 (0x0003203C) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_HIGH_WATERMARK___M 0x00000002 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__COPY_COMPLETE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH (0x00240004) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__STATE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__WRITE_ACCESS___S 17 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_OVERFLOW___S 6 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_SR_XO_SETTLE_TIMEOUT___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ECAHB_TIMEOUT___S 4 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DEST_MAX_LENGTH___POR 0x0080 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_LOW_WATER_MARK_THRESHOLD___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_SR_XO_SETTLE_TIMEOUT___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN1_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_HIGH_WATERMARK___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_HIGH_WATERMARK___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_WCSS_WAKEUP_IRQ_ACK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW (0x00240000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13 (0x00030054) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN2_SLP_TMR_INTR___S 15 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH (0x00240010) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__PARSER_INT___S 11 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ERR_RESP_CLEAR___S 2 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4 (0x00032010) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_WCSS_WAKEUP_IRQ_ACK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SW_SLP_TMR_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_MAX_LEN_VIO___S 7 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_MAX_LEN_VIO___S 7 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW (0x00246000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DST_RING_BYTE_SWAP_EN___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_2_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_WCSS_WAKEUP_IRQ_ACK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY__HOST___POR 0x000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__NOC_WCMN_INTR___S 12 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__PARSER_INT___POR 0x000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__DST_FLUSH___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23 (0x0003007C) +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL___M 0x0000001F +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_OVERFLOW___M 0x00000040 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SMH_INT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__SW_SLP_TMR_INTR___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY__HOST___S 12 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH__BASE_ADDR_HIGH___POR 0x00 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_LEN_ERR___M 0x00000100 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__VALUE_REG_UPDATED_WITH_INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH__SPARE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE__FORCE_WAKE_ENABLE___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX__SRC_WR_INDEX___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB__STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ERR_RESP_ENABLE___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__ILL_REG___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__SRC_AXI_MAX_LEN___POR 0x1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1 (0x00240018) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19 (0x0003006C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX (0x0024003C) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD___M 0x0000000F +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__VALUE_REG_UPDATED_WITH_INVALID_ADDR___S 5 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI__CURRENT_SRRI___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_RF_XO_MUX_SEL___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2___M 0x0000000F +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__INVALID_ADDR___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET___M 0x0FFFDDFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7 (0x0003201C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_LOW_WATERMARK___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__INVALID_ADDR___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__DST_AXI_MAX_LEN___M 0x0000000C +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__MISC___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__COPY_COMPLETE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_HIGH_WATER_MARK_THRESHOLD___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__CLOCK_GATE_DISABLE___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__DIRTY_BIT_SET_CLEAR___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ECAHB_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__FORCE_WAKE___S 1 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB__STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_SR_XO_SETTLE_TIMEOUT___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__VALUE_REG_UPDATED_WITH_INVALID_ADDR___S 5 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB__STATUS___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__VALUE_REG_UPDATED_WITH_INVALID_ADDR___M 0x00000020 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_MISC_P___S 7 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_OVERFLOW___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__INVALID_ADDR___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX__DST_WR_INDEX___M 0x0000FFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_STROBE_INTERRUPT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR___RWC QCSR_REG_WO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__PMM_SR_XO_SETTLE_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES__CE_INTR_LINE_HOST_P___M 0x00000FFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_LOW_WATER_MARK_THRESOLD___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__FORCE_WAKE___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16 (0x00030060) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS (0x00030144) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__START_OFFSET___POR 0x0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SR_PLL_REF_MUX_SEL___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17 (0x00032044) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS___M 0x000003FF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WFSS_DBG_INTR___M 0x00020000 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB__STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__ENABLE_APSS_FULL_ACCESS___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_HIGH_WATERMARK___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE__START_OFFSET___M 0xFFFF0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_HIGH_WATERMARK___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__CE_INTR_TIMEOUT_P___S 8 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__COPY_COMPLETE___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__START_OFFSET___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS___M 0x000FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ECAHB_TIMEOUT___S 4 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1___M 0x000FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__FORCE_WAKE_ENABLE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB__STATUS___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__INVALID_ADDR___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS___M 0x00000007 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN1_HW2SW_GRANT___S 6 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_HIGH_WATERMARK___S 1 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW (0x00242000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN2_HW2SW_GRANT___S 7 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_LOW_WATERMARK___S 4 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DEST_MAX_LENGTH___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE (0x00030010) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__FORCE_WAKE_CLEAR___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8 (0x00032020) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET___M 0x00000FFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__IDX_UPD_EN___M 0x00080000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__BMH_INT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL__SOFT_RESET___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN1_HW2SW_GRANT___S 6 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0 (0x00030020) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__PMH_INT___S 5 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY__HOST___M 0x00FFF000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX__DST_WR_INDEX___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_HIGH_WATER_MARK_THRESHOLD___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__ILL_REG___M 0x01000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WLAN2_SLP_TMR_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11 (0x0003004C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__PMH_INT___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__INVALID_BB_1_INTR___M 0x00000400 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_LOW_WATER_MARK_THRESOLD___POR 0x0000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB (0x0003206C) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__PMM_WCSS_WAKEUP_IRQ_ACK___M 0x00000100 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__DIRTY_BIT_SET_ENABLE___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX___M 0x0000FFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE (0x00240014) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__STATE___M 0x00000007 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11 (0x0003202C) +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI (0x00240048) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW__BASE_ADDR_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__WCSS_CORE_WAKE_SLEEP_STATE___S 3 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW (0x00249000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__DST_RING_LOW_WATERMARK___S 4 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_LEN_ERR___S 8 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_MISC_IS__AXI_TIMEOUT_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__ERR_RESP_ENABLE___M 0x00000004 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_WCI2_INTERRUPT___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_HIGH_WATERMARK___S 1 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS__WCSS_CORE_WAKE_SLEEP_STATE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__READ_ACCESS___S 16 +#define ADRASTEA_A_WCSS_SR_APSS_SR_TESTBUS___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_INVALID_ADDR_ACCESS__READ_ACCESS___M 0x00010000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_HIGH_WATERMARK___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_CLEAR__CE_INTR_LINE_HOST_P___POR 0x000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL (0x00030000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI (0x00240044) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_MAX_LEN_VIO___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY__BITS___M 0x00FFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE___M 0x000003FF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD (0x00240020) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_LOW_WATERMARK___M 0x00000004 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__NOC_WCMN_INTR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_SECURE_WRAPPER_CE_WRAPPER_INTERRUPT_SUMMARY__HOST___S 12 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_LSB___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__COPY_COMPLETE___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOWREG_STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB__STATUS___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES (0x002F1000) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_MISC_IS__AXI_TIMEOUT_ERR___M 0x00000400 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9 (0x00030044) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6 (0x00032018) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21 (0x00032054) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH__BASE_ADDR_HIGH___M 0x0000001F +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY___S 12 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__HALT___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW (0x00247000) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18 (0x00030068) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN1_HW2SW_GRANT___M 0x00000040 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_LOW_WATERMARK___M 0x00000010 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__INVALID_ADDR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_HIGH_WATERMARK___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ERR_RESP___S 2 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE (0x00240008) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_CONTROL___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY__BITS___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_HIGH_WATERMARK___S 3 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__WLAN1_HW2SW_GRANT___M 0x00000040 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LMH_INT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN2_HW2SW_GRANT___M 0x00000080 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1 (0x00030024) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2 (0x0024001C) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES__CE_INTR_LINE_HOST_P___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0__ADDRESS_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN2_HW2SW_GRANT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES_SET___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_STROBE_INTERRUPT___M 0x00000002 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__VALUE_REG_UPDATED_WITH_INVALID_ADDR___M 0x00000020 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__MCIM_INT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__FORCE_WAKE___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_MSB___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21 (0x00030074) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_DIRTY__BITS___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__DST_FLUSH___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__AXI_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__WLAN2_HW2SW_GRANT___S 7 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12__VALUE_REGISTER___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_LEN_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_WCSSAON_SR_MSB (0x00032074) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_HIGH_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE__FORCE_WAKE_ENABLE___M 0x00000001 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD__DST_FLUSH___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_LOW_WATERMARK___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE__START_OFFSET___M 0xFFFF0000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10 (0x00030048) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_OVERFLOW___S 5 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI__CURRENT_SRRI___M 0x0000FFFF +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4__ADDRESS_REGISTER___M 0x003FFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__SRC_RING_HIGH_WATERMARK___M 0x00000002 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__COPY_COMPLETE___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__ERR_RESP___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__COPY_COMPLETE___M 0x00000001 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20__VALUE_REGISTER___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW__BASE_ADDR_LOW___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_TIMEOUT_ERR___S 10 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW__BASE_ADDR_LOW___M 0xFFFFFFFF +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__INVALID_ADDR___S 3 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1___RWC QCSR_REG_RO +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__ECAHB_TIMEOUT___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SW_SCRATCH___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_BUS_ERR___S 9 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3__ADDRESS_REGISTER___POR 0x000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_LOW_WATERMARK___S 2 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL2__SRC_AXI_MAX_LEN___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_PMM_SR_LSB (0x00032068) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__WFSS_DBG_INTR___S 17 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_CLEAR__PMM_SR_XO_SETTLE_TIMEOUT___M 0x00000200 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH___S 0 +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_ENABLE__WLAN1_HW2SW_GRANT___M 0x00000040 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_BUS_ERR___M 0x00000200 +#define ADRASTEA_A_WCSS_SR_APSS_COMMIT_REPLAY (0x00030004) +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW___RWC QCSR_REG_RW +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21___S 0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_MISC_IS__AXI_BUS_ERR___POR 0x0 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_3_A_WCMN_QDSP_ERROR_INTR_ENABLES_SET__LCMH_WCI2_INTERRUPT___M 0x00000004 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__DST_RING_LOW_WATERMARK___POR 0x0 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10 (0x00032028) +#define ADRASTEA_A_WCSS_SR_APSS_SR_INTERRUPT_STATUS__INVALID_ADDR___M 0x00000008 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3 (0x0003200C) +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16__VALUE_REGISTER___POR 0x00000000 +#define ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE__SRC_RING_HIGH_WATERMARK___S 1 +#define ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12__ADDRESS_REGISTER___S 0 + + +/* End auto-generated headers from register parser */ + +#define MISSING 0 +#define MISSING_FOR_ADRASTEA MISSING +#define ADRASTEA_PCIE_LOCAL_REG_BASE_ADDRESS 0 +#define ADRASTEA_WIFI_RTC_REG_BASE_ADDRESS 0x45000 +#define ADRASTEA_RTC_SOC_REG_BASE_ADDRESS 0x113000 +#define ADRASTEA_GPIO_ATHR_WLAN_REG_BASE_ADDRESS 0x85000 +#define ADRASTEA_SI_REG_BASE_ADDRESS 0x84000 +#define ADRASTEA_SOC_CORE_REG_BASE_ADDRESS 0x113000 +#define ADRASTEA_CE_WRAPPER_REG_CSR_BASE_ADDRESS 0xC000 +#define ADRASTEA_MAC_WIFICMN_REG_BASE_ADDRESS MISSING + +/* Base Addresses */ +#define ADRASTEA_RTC_SOC_BASE_ADDRESS 0x00000000 +#define ADRASTEA_RTC_WMAC_BASE_ADDRESS 0x00000000 +#define ADRASTEA_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define ADRASTEA_BT_COEX_BASE_ADDRESS 0x00002000 +#define ADRASTEA_SOC_PCIE_BASE_ADDRESS 0x00130000 +#define ADRASTEA_SOC_CORE_BASE_ADDRESS 0x00000000 +#define ADRASTEA_WLAN_UART_BASE_ADDRESS 0x00111000 +#define ADRASTEA_WLAN_SI_BASE_ADDRESS 0x00010000 +#define ADRASTEA_WLAN_GPIO_BASE_ADDRESS 0x00000000 +#define ADRASTEA_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00000000 +#define ADRASTEA_WLAN_MAC_BASE_ADDRESS 0x00000000 +#define ADRASTEA_EFUSE_BASE_ADDRESS 0x00024000 +#define ADRASTEA_FPGA_REG_BASE_ADDRESS 0x00039000 +#define ADRASTEA_WLAN_UART2_BASE_ADDRESS 0x00054c00 + +#define ADRASTEA_CE_WRAPPER_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY +#define ADRASTEA_CE0_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW +#define ADRASTEA_CE1_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE1_SR_BA_LOW +#define ADRASTEA_CE2_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE2_SR_BA_LOW +#define ADRASTEA_CE3_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE3_SR_BA_LOW +#define ADRASTEA_CE4_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE4_SR_BA_LOW +#define ADRASTEA_CE5_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE5_SR_BA_LOW +#define ADRASTEA_CE6_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE6_SR_BA_LOW +#define ADRASTEA_CE7_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE7_SR_BA_LOW +#define ADRASTEA_CE8_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE8_SR_BA_LOW +#define ADRASTEA_CE9_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE9_SR_BA_LOW +#define ADRASTEA_CE10_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE10_SR_BA_LOW +#define ADRASTEA_CE11_BASE_ADDRESS \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE11_SR_BA_LOW + +#define ADRASTEA_A_SOC_PCIE_SOC_PCIE_REG MISSING +#define ADRASTEA_DBI_BASE_ADDRESS MISSING +#define ADRASTEA_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS MISSING +#define ADRASTEA_WIFICMN_BASE_ADDRESS MISSING +#define ADRASTEA_BOARD_DATA_SZ MISSING +#define ADRASTEA_BOARD_EXT_DATA_SZ MISSING +#define ADRASTEA_A_SOC_PCIE_PCIE_BAR0_START MISSING +#define ADRASTEA_A_SOC_CORE_SCRATCH_0_ADDRESS MISSING +#define ADRASTEA_A_SOC_CORE_SPARE_0_REGISTER MISSING +#define ADRASTEA_PCIE_INTR_FIRMWARE_ROUTE_MASK MISSING +#define ADRASTEA_SCRATCH_3_ADDRESS MISSING +#define ADRASTEA_TARG_DRAM_START 0x00400000 +#define ADRASTEA_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define ADRASTEA_SOC_RESET_CONTROL_OFFSET \ + (0x00000000 + _RTC_SOC_REG_BASE_ADDRESS) +#define ADRASTEA_SOC_CLOCK_CONTROL_OFFSET \ + (0x00000028 + _RTC_SOC_REG_BASE_ADDRESS) +#define ADRASTEA_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define ADRASTEA_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define ADRASTEA_WLAN_GPIO_PIN0_ADDRESS \ + (0x50 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN1_ADDRESS \ + (0x54 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define ADRASTEA_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define ADRASTEA_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define ADRASTEA_SOC_LPO_CAL_OFFSET \ + (0xe0 + _RTC_SOC_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN10_ADDRESS \ + (0x78 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN11_ADDRESS \ + (0x7c + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN12_ADDRESS \ + (0x80 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_GPIO_PIN13_ADDRESS \ + (0x84 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define ADRASTEA_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define ADRASTEA_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define ADRASTEA_SOC_LPO_CAL_ENABLE_LSB 20 +#define ADRASTEA_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define ADRASTEA_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define ADRASTEA_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define ADRASTEA_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000002 +#define ADRASTEA_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000001 +#define ADRASTEA_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define ADRASTEA_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define ADRASTEA_SI_CONFIG_I2C_LSB 16 +#define ADRASTEA_SI_CONFIG_I2C_MASK 0x00010000 +#define ADRASTEA_SI_CONFIG_POS_SAMPLE_LSB 7 +#define ADRASTEA_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define ADRASTEA_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define ADRASTEA_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define ADRASTEA_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define ADRASTEA_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define ADRASTEA_SI_CONFIG_DIVIDER_LSB 0 +#define ADRASTEA_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define ADRASTEA_SI_CONFIG_OFFSET (0x00000000 + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_TX_DATA0_OFFSET (0x00000008 + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_TX_DATA1_OFFSET (0x0000000c + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_RX_DATA0_OFFSET (0x00000010 + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_RX_DATA1_OFFSET (0x00000014 + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_CS_OFFSET (0x00000004 + _SI_REG_BASE_ADDRESS) +#define ADRASTEA_SI_CS_DONE_ERR_MASK 0x00000400 +#define ADRASTEA_SI_CS_DONE_INT_MASK 0x00000200 +#define ADRASTEA_SI_CS_START_LSB 8 +#define ADRASTEA_SI_CS_START_MASK 0x00000100 +#define ADRASTEA_SI_CS_RX_CNT_LSB 4 +#define ADRASTEA_SI_CS_RX_CNT_MASK 0x000000f0 +#define ADRASTEA_SI_CS_TX_CNT_LSB 0 +#define ADRASTEA_SI_CS_TX_CNT_MASK 0x0000000f +#define ADRASTEA_CE_COUNT 12 +#define ADRASTEA_SR_WR_INDEX_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WR_INDEX \ + - ADRASTEA_CE0_BASE_ADDRESS) +#define ADRASTEA_DST_WATERMARK_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK \ + - ADRASTEA_CE0_BASE_ADDRESS) +#define ADRASTEA_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define ADRASTEA_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define ADRASTEA_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define ADRASTEA_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define ADRASTEA_RX_MPDU_START_2_PN_47_32_LSB 0 +#define ADRASTEA_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define ADRASTEA_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define ADRASTEA_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define ADRASTEA_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define ADRASTEA_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define ADRASTEA_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define ADRASTEA_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define ADRASTEA_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define ADRASTEA_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define ADRASTEA_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define ADRASTEA_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define ADRASTEA_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define ADRASTEA_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define ADRASTEA_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define ADRASTEA_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define ADRASTEA_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define ADRASTEA_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define ADRASTEA_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define ADRASTEA_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 + +#define ADRASTEA_DST_WR_INDEX_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WR_INDEX\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_SRC_WATERMARK_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define ADRASTEA_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define ADRASTEA_DST_WATERMARK_LOW_MASK 0xffff0000 +#define ADRASTEA_DST_WATERMARK_HIGH_MASK 0x0000ffff + +#define ADRASTEA_CURRENT_SRRI_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_SRRI\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_CURRENT_DRRI_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CURRENT_DRRI\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define ADRASTEA_HOST_IS_SRC_RING_LOW_WATERMARK_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__SRC_RING_LOW_WATERMARK___M + +#define ADRASTEA_HOST_IS_DST_RING_HIGH_WATERMARK_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_HIGH_WATERMARK___M + +#define ADRASTEA_HOST_IS_DST_RING_LOW_WATERMARK_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__DST_RING_LOW_WATERMARK___M + +#define ADRASTEA_HOST_IS_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS \ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_MISC_IS_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS \ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_HOST_IS_COPY_COMPLETE_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__COPY_COMPLETE___M + +#define ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define ADRASTEA_CE_WRAPPER_INDEX_BASE_LOW 0x0004 +#define ADRASTEA_CE_WRAPPER_INDEX_BASE_HIGH 0x0008 + +#define ADRASTEA_HOST_IE_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_HOST_IE_COPY_COMPLETE_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE__COPY_COMPLETE___M + +#define ADRASTEA_SR_BA_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_LOW\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_SR_BA_ADDRESS_HIGH_OFFSET \ + (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_BA_HIGH \ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_SR_SIZE_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SR_SIZE \ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_CE_CTRL1_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1 \ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_CE_CTRL1_DMAX_LENGTH_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DEST_MAX_LENGTH___M + +#define ADRASTEA_DR_BA_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_LOW\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_DR_BA_ADDRESS_HIGH_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_BA_HIGH\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_DR_SIZE_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DR_SIZE\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_CE_CMD_REGISTER_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CMD\ + - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_MISC_IE_OFFSET \ + (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IE - ADRASTEA_CE0_BASE_ADDRESS) + +#define ADRASTEA_MISC_IS_AXI_ERR_MASK 0x00000100 + +#define ADRASTEA_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 + +#define ADRASTEA_MISC_IS_AXI_TIMEOUT_ERR \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__AXI_TIMEOUT_ERR___M + +#define ADRASTEA_MISC_IS_SRC_LEN_ERR_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_LEN_ERR___M + +#define ADRASTEA_MISC_IS_DST_MAX_LEN_VIO_MASK\ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_MAX_LEN_VIO___M + +#define ADRASTEA_MISC_IS_DST_RING_OVERFLOW_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__DST_RING_OVERFLOW___M + +#define ADRASTEA_MISC_IS_SRC_RING_OVERFLOW_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_MISC_IS__SRC_RING_OVERFLOW___M + +#define ADRASTEA_SRC_WATERMARK_LOW_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_LOW_WATER_MARK_THRESOLD___S + +#define ADRASTEA_SRC_WATERMARK_HIGH_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_SRC_WATERMARK__SR_HIGH_WATER_MARK_THRESHOLD___S + +#define ADRASTEA_DST_WATERMARK_LOW_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_LOW_WATER_MARK_THRESHOLD___S + +#define ADRASTEA_DST_WATERMARK_HIGH_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_DST_WATERMARK__DR_HIGH_WATER_MARK_THRESHOLD___S + +#define ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY__HOST___M + +#define ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY__HOST___S + +#define ADRASTEA_CE_CTRL1_DMAX_LENGTH_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DEST_MAX_LENGTH___S + +#define ADRASTEA_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__SRC_RING_BYTE_SWAP_EN___M + +#define ADRASTEA_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DST_RING_BYTE_SWAP_EN___M + +#define ADRASTEA_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__SRC_RING_BYTE_SWAP_EN___S + +#define ADRASTEA_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB \ + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__DST_RING_BYTE_SWAP_EN___S + +#define ADRASTEA_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x0000004 +#define ADRASTEA_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define ADRASTEA_SOC_GLOBAL_RESET_ADDRESS \ + (0x0008 + ADRASTEA_PCIE_LOCAL_REG_BASE_ADDRESS) +#define ADRASTEA_RTC_STATE_ADDRESS \ + (0x0000 + ADRASTEA_PCIE_LOCAL_REG_BASE_ADDRESS) +#define ADRASTEA_RTC_STATE_COLD_RESET_MASK 0x400 + +#define ADRASTEA_PCIE_SOC_WAKE_RESET 0x00000000 +#define ADRASTEA_PCIE_SOC_WAKE_ADDRESS (ADRASTEA_A_WCSS_SR_APSS_FORCE_WAKE) +#define ADRASTEA_PCIE_SOC_WAKE_V_MASK 0x00000001 + +#define ADRASTEA_RTC_STATE_V_MASK 0x00000007 +#define ADRASTEA_RTC_STATE_V_LSB 0 +#define ADRASTEA_RTC_STATE_V_ON 5 +#define ADRASTEA_PCIE_LOCAL_BASE_ADDRESS 0x0 +#define ADRASTEA_FW_IND_EVENT_PENDING 1 +#define ADRASTEA_FW_IND_INITIALIZED 2 +#define ADRASTEA_FW_IND_HELPER 4 + +#define ADRASTEA_PCIE_INTR_FIRMWARE_MASK 0x00000000 +#define ADRASTEA_PCIE_INTR_CE0_MASK 0x00000100 +#define ADRASTEA_PCIE_INTR_CE_MASK_ALL 0x00001ffe + +#define ADRASTEA_CPU_INTR_ADDRESS 0xffffffff +#define ADRASTEA_SOC_LF_TIMER_CONTROL0_ADDRESS 0xffffffff +#define ADRASTEA_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0xffffffff +#define ADRASTEA_SOC_RESET_CONTROL_ADDRESS \ + (0x00000000 + _RTC_SOC_REG_BASE_ADDRESS) +#define ADRASTEA_SOC_RESET_CONTROL_CE_RST_MASK 0x0100 +#define ADRASTEA_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define ADRASTEA_CORE_CTRL_ADDRESS (0x0000 + _SOC_CORE_REG_BASE_ADDRESS) +#define ADRASTEA_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define ADRASTEA_LOCAL_SCRATCH_OFFSET 0x00000018 +#define ADRASTEA_CLOCK_GPIO_OFFSET 0xffffffff +#define ADRASTEA_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define ADRASTEA_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define ADRASTEA_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define ADRASTEA_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define ADRASTEA_SOC_CHIP_ID_VERSION_LSB 18 +#define ADRASTEA_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define ADRASTEA_SOC_CHIP_ID_REVISION_LSB 8 +#define ADRASTEA_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define ADRASTEA_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define ADRASTEA_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define ADRASTEA_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define ADRASTEA_WLAN_DEBUG_OUT_DATA_MSB 19 +#define ADRASTEA_WLAN_DEBUG_OUT_DATA_LSB 0 +#define ADRASTEA_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define ADRASTEA_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define ADRASTEA_AMBA_DEBUG_BUS_SEL_MSB 4 +#define ADRASTEA_AMBA_DEBUG_BUS_SEL_LSB 0 +#define ADRASTEA_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define ADRASTEA_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define ADRASTEA_CE_WRAPPER_DEBUG_SEL_MSB 4 +#define ADRASTEA_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define ADRASTEA_CE_WRAPPER_DEBUG_SEL_MASK 0x0000001f +#define ADRASTEA_CE_DEBUG_OFFSET 0x0054 +#define ADRASTEA_CE_DEBUG_SEL_MSB 5 +#define ADRASTEA_CE_DEBUG_SEL_LSB 0 +#define ADRASTEA_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define ADRASTEA_EFUSE_OFFSET 0x0000032c +#define ADRASTEA_EFUSE_XTAL_SEL_MSB 10 +#define ADRASTEA_EFUSE_XTAL_SEL_LSB 8 +#define ADRASTEA_EFUSE_XTAL_SEL_MASK 0x00000700 +#define ADRASTEA_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define ADRASTEA_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define ADRASTEA_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define ADRASTEA_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define ADRASTEA_BB_PLL_CONFIG_FRAC_MSB 17 +#define ADRASTEA_BB_PLL_CONFIG_FRAC_LSB 0 +#define ADRASTEA_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define ADRASTEA_WLAN_PLL_SETTLE_TIME_MSB 10 +#define ADRASTEA_WLAN_PLL_SETTLE_TIME_LSB 0 +#define ADRASTEA_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define ADRASTEA_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define ADRASTEA_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define ADRASTEA_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define ADRASTEA_WLAN_PLL_SETTLE_RESET 0x00000400 +#define ADRASTEA_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define ADRASTEA_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define ADRASTEA_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define ADRASTEA_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define ADRASTEA_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define ADRASTEA_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define ADRASTEA_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define ADRASTEA_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define ADRASTEA_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define ADRASTEA_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define ADRASTEA_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define ADRASTEA_WLAN_PLL_CONTROL_DIV_MSB 9 +#define ADRASTEA_WLAN_PLL_CONTROL_DIV_LSB 0 +#define ADRASTEA_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define ADRASTEA_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define ADRASTEA_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define ADRASTEA_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define ADRASTEA_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define ADRASTEA_WLAN_PLL_CONTROL_RESET 0x00010011 +#define ADRASTEA_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define ADRASTEA_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define ADRASTEA_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define ADRASTEA_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define ADRASTEA_RTC_SYNC_STATUS_OFFSET 0x0244 +#define ADRASTEA_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define ADRASTEA_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define ADRASTEA_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define ADRASTEA_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define ADRASTEA_PCIE_INTR_CE_MASK(n) (ADRASTEA_PCIE_INTR_CE0_MASK << (n)) +#define ADRASTEA_DRAM_BASE_ADDRESS ADRASTEA_TARG_DRAM_START +#define ADRASTEA_FW_INDICATOR_ADDRESS \ + (ADRASTEA_WIFICMN_BASE_ADDRESS + ADRASTEA_SCRATCH_3_ADDRESS) +#define ADRASTEA_SYSTEM_SLEEP_OFFSET ADRASTEA_SOC_SYSTEM_SLEEP_OFFSET +#define ADRASTEA_WLAN_SYSTEM_SLEEP_OFFSET (0x002c + _WIFI_RTC_REG_BASE_ADDRESS) +#define ADRASTEA_WLAN_RESET_CONTROL_OFFSET (0x0000 + _WIFI_RTC_REG_BASE_ADDRESS) +#define ADRASTEA_CLOCK_CONTROL_OFFSET ADRASTEA_SOC_CLOCK_CONTROL_OFFSET +#define ADRASTEA_CLOCK_CONTROL_SI0_CLK_MASK \ + ADRASTEA_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define ADRASTEA_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define ADRASTEA_RESET_CONTROL_SI0_RST_MASK \ + ADRASTEA_SOC_RESET_CONTROL_SI0_RST_MASK +#define ADRASTEA_GPIO_BASE_ADDRESS ADRASTEA_WLAN_GPIO_BASE_ADDRESS +#define ADRASTEA_GPIO_PIN0_OFFSET ADRASTEA_WLAN_GPIO_PIN0_ADDRESS +#define ADRASTEA_GPIO_PIN1_OFFSET ADRASTEA_WLAN_GPIO_PIN1_ADDRESS +#define ADRASTEA_GPIO_PIN0_CONFIG_MASK ADRASTEA_WLAN_GPIO_PIN0_CONFIG_MASK +#define ADRASTEA_GPIO_PIN1_CONFIG_MASK ADRASTEA_WLAN_GPIO_PIN1_CONFIG_MASK +#define ADRASTEA_SI_BASE_ADDRESS 0x00000000 +#define ADRASTEA_CPU_CLOCK_OFFSET (0x20 + _RTC_SOC_REG_BASE_ADDRESS) +#define ADRASTEA_LPO_CAL_OFFSET ADRASTEA_SOC_LPO_CAL_OFFSET +#define ADRASTEA_GPIO_PIN10_OFFSET ADRASTEA_WLAN_GPIO_PIN10_ADDRESS +#define ADRASTEA_GPIO_PIN11_OFFSET ADRASTEA_WLAN_GPIO_PIN11_ADDRESS +#define ADRASTEA_GPIO_PIN12_OFFSET ADRASTEA_WLAN_GPIO_PIN12_ADDRESS +#define ADRASTEA_GPIO_PIN13_OFFSET ADRASTEA_WLAN_GPIO_PIN13_ADDRESS +#define ADRASTEA_CPU_CLOCK_STANDARD_LSB 0 +#define ADRASTEA_CPU_CLOCK_STANDARD_MASK 0x1 +#define ADRASTEA_LPO_CAL_ENABLE_LSB ADRASTEA_SOC_LPO_CAL_ENABLE_LSB +#define ADRASTEA_LPO_CAL_ENABLE_MASK ADRASTEA_SOC_LPO_CAL_ENABLE_MASK +#define ADRASTEA_ANALOG_INTF_BASE_ADDRESS ADRASTEA_WLAN_ANALOG_INTF_BASE_ADDRESS +#define ADRASTEA_MBOX_BASE_ADDRESS 0x00008000 +#define ADRASTEA_INT_STATUS_ENABLE_ERROR_LSB MISSING +#define ADRASTEA_INT_STATUS_ENABLE_ERROR_MASK MISSING +#define ADRASTEA_INT_STATUS_ENABLE_CPU_LSB MISSING +#define ADRASTEA_INT_STATUS_ENABLE_CPU_MASK MISSING +#define ADRASTEA_INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define ADRASTEA_INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define ADRASTEA_INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define ADRASTEA_INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define ADRASTEA_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define ADRASTEA_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define ADRASTEA_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define ADRASTEA_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define ADRASTEA_COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define ADRASTEA_COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define ADRASTEA_INT_STATUS_ENABLE_ADDRESS MISSING +#define ADRASTEA_CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define ADRASTEA_CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define ADRASTEA_HOST_INT_STATUS_ADDRESS MISSING +#define ADRASTEA_CPU_INT_STATUS_ADDRESS MISSING +#define ADRASTEA_ERROR_INT_STATUS_ADDRESS MISSING +#define ADRASTEA_ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define ADRASTEA_ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define ADRASTEA_ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define ADRASTEA_ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define ADRASTEA_ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define ADRASTEA_ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define ADRASTEA_COUNT_DEC_ADDRESS MISSING +#define ADRASTEA_HOST_INT_STATUS_CPU_MASK MISSING +#define ADRASTEA_HOST_INT_STATUS_CPU_LSB MISSING +#define ADRASTEA_HOST_INT_STATUS_ERROR_MASK MISSING +#define ADRASTEA_HOST_INT_STATUS_ERROR_LSB MISSING +#define ADRASTEA_HOST_INT_STATUS_COUNTER_MASK MISSING +#define ADRASTEA_HOST_INT_STATUS_COUNTER_LSB MISSING +#define ADRASTEA_RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define ADRASTEA_WINDOW_DATA_ADDRESS MISSING +#define ADRASTEA_WINDOW_READ_ADDR_ADDRESS MISSING +#define ADRASTEA_WINDOW_WRITE_ADDR_ADDRESS MISSING + +/* Shadow Registers - Start */ +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_0 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE0 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_1 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE1 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_2 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE2 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_3 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE3 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_4 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE4 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_5 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE5 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_6 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE6 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_7 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE7 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_8 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE8 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_9 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE9 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_10 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE10 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_11 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE11 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_12 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE12 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_13 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE13 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_14 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE14 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_15 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE15 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_16 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE16 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_17 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE17 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_18 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE18 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_19 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE19 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_20 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE20 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_21 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE21 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_22 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE22 +#define ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_23 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_VALUE23 + +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_0 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS0 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_1 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS1 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_2 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS2 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_3 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS3 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_4 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS4 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_5 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS5 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_6 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS6 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_7 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS7 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_8 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS8 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_9 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS9 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_10 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS10 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_11 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS11 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_12 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS12 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_13 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS13 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_14 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS14 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_15 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS15 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_16 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS16 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_17 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS17 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_18 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS18 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_19 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS19 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_20 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS20 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_21 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS21 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_22 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS22 +#define ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_23 \ + ADRASTEA_A_WCSS_SR_APSS_SHADOW_ADDRESS23 + +/* Q6 iHelium emulation registers */ +#define ADRASTEA_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 0x00113018 +#define ADRASTEA_A_SOC_CORE_SPARE_1_REGISTER 0x00113184 +#define ADRASTEA_A_SOC_CORE_PCIE_INTR_CLR_GRP1 0x00113020 +#define ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 0x00113010 +#define ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_0 0x00130040 +#define ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_1 0x00130044 + +#define ADRASTEA_HOST_ENABLE_REGISTER 0x00188000 +#define ADRASTEA_Q6_ENABLE_REGISTER_0 0x00188004 +#define ADRASTEA_Q6_ENABLE_REGISTER_1 0x00188008 +#define ADRASTEA_HOST_CAUSE_REGISTER 0x0018800c +#define ADRASTEA_Q6_CAUSE_REGISTER_0 0x00188010 +#define ADRASTEA_Q6_CAUSE_REGISTER_1 0x00188014 +#define ADRASTEA_HOST_CLEAR_REGISTER 0x00188018 +#define ADRASTEA_Q6_CLEAR_REGISTER_0 0x0018801c +#define ADRASTEA_Q6_CLEAR_REGISTER_1 0x00188020 + +#define ADRASTEA_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA 0x08 +#define ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_2 0x0013005C +#ifdef QCA_WIFI_3_0_IHELIUM +#define ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK 0xff +#else +#define ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK 0x0 +#endif /* QCA_WIFI_3_0_IHELIUM */ +/* end: Q6 iHelium emulation registers */ + +struct targetdef_s adrastea_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = ADRASTEA_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = ADRASTEA_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = ADRASTEA_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = ADRASTEA_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = + ADRASTEA_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = + ADRASTEA_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = ADRASTEA_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = ADRASTEA_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = ADRASTEA_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = ADRASTEA_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = ADRASTEA_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = ADRASTEA_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = + ADRASTEA_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = + ADRASTEA_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = ADRASTEA_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = ADRASTEA_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = ADRASTEA_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = ADRASTEA_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = ADRASTEA_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = ADRASTEA_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = ADRASTEA_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = ADRASTEA_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = ADRASTEA_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = ADRASTEA_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = ADRASTEA_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = ADRASTEA_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = ADRASTEA_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = ADRASTEA_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = ADRASTEA_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = ADRASTEA_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = ADRASTEA_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = ADRASTEA_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = ADRASTEA_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = ADRASTEA_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = ADRASTEA_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = ADRASTEA_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = ADRASTEA_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = ADRASTEA_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = ADRASTEA_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = ADRASTEA_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = ADRASTEA_SI_CS_START_LSB, + .d_SI_CS_START_MASK = ADRASTEA_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = ADRASTEA_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = ADRASTEA_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = ADRASTEA_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = ADRASTEA_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = ADRASTEA_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = ADRASTEA_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = ADRASTEA_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = ADRASTEA_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = ADRASTEA_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = ADRASTEA_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = ADRASTEA_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = ADRASTEA_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = ADRASTEA_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = ADRASTEA_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = ADRASTEA_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = ADRASTEA_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = ADRASTEA_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = ADRASTEA_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = ADRASTEA_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = ADRASTEA_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = + ADRASTEA_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = ADRASTEA_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = ADRASTEA_WLAN_MAC_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = ADRASTEA_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = ADRASTEA_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = ADRASTEA_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = ADRASTEA_CORE_CTRL_ADDRESS, + .d_CE_COUNT = ADRASTEA_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 = ADRASTEA_HOST_ENABLE_REGISTER, + .d_PCIE_INTR_CLR_ADDRESS = ADRASTEA_HOST_CLEAR_REGISTER, + .d_PCIE_INTR_FIRMWARE_MASK = ADRASTEA_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = ADRASTEA_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = ADRASTEA_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = ADRASTEA_SR_WR_INDEX_OFFSET, + .d_DST_WATERMARK_ADDRESS = ADRASTEA_DST_WATERMARK_OFFSET, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = + ADRASTEA_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = ADRASTEA_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = ADRASTEA_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = ADRASTEA_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = ADRASTEA_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = + ADRASTEA_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = + ADRASTEA_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = + ADRASTEA_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = ADRASTEA_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = ADRASTEA_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = + ADRASTEA_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = + ADRASTEA_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = ADRASTEA_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = ADRASTEA_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = + ADRASTEA_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = + ADRASTEA_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = + ADRASTEA_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = + ADRASTEA_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = + ADRASTEA_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = + ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = + ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = + ADRASTEA_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = + ADRASTEA_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = + ADRASTEA_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = + ADRASTEA_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = + ADRASTEA_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = + ADRASTEA_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + + /* PLL start */ + .d_EFUSE_OFFSET = ADRASTEA_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = ADRASTEA_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = ADRASTEA_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = ADRASTEA_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = ADRASTEA_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = ADRASTEA_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = ADRASTEA_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = ADRASTEA_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = ADRASTEA_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = ADRASTEA_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = ADRASTEA_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = ADRASTEA_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = ADRASTEA_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = ADRASTEA_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = ADRASTEA_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = ADRASTEA_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = ADRASTEA_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = ADRASTEA_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = ADRASTEA_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = ADRASTEA_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = ADRASTEA_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = ADRASTEA_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = ADRASTEA_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = ADRASTEA_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = + ADRASTEA_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = + ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = + ADRASTEA_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = ADRASTEA_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = ADRASTEA_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = ADRASTEA_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = + ADRASTEA_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = ADRASTEA_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = ADRASTEA_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = ADRASTEA_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = ADRASTEA_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = ADRASTEA_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = ADRASTEA_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = ADRASTEA_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = ADRASTEA_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = ADRASTEA_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = ADRASTEA_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = ADRASTEA_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = ADRASTEA_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = + ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = + ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = + ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = + ADRASTEA_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = ADRASTEA_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = ADRASTEA_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = ADRASTEA_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = ADRASTEA_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = ADRASTEA_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = ADRASTEA_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = ADRASTEA_HOST_CAUSE_REGISTER, + .d_SOC_RESET_CONTROL_ADDRESS = ADRASTEA_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = + ADRASTEA_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = + ADRASTEA_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = + ADRASTEA_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = + ADRASTEA_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = ADRASTEA_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = + ADRASTEA_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = + ADRASTEA_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = ADRASTEA_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = ADRASTEA_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = ADRASTEA_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = ADRASTEA_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = ADRASTEA_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ + .d_A_SOC_CORE_SCRATCH_0_ADDRESS = ADRASTEA_A_SOC_CORE_SCRATCH_0_ADDRESS, + .d_A_SOC_CORE_SPARE_0_REGISTER = ADRASTEA_A_SOC_CORE_SPARE_0_REGISTER, + .d_PCIE_INTR_FIRMWARE_ROUTE_MASK = + ADRASTEA_PCIE_INTR_FIRMWARE_ROUTE_MASK, + .d_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 = + ADRASTEA_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1, + .d_A_SOC_CORE_SPARE_1_REGISTER = + ADRASTEA_A_SOC_CORE_SPARE_1_REGISTER, + .d_A_SOC_CORE_PCIE_INTR_CLR_GRP1 = + ADRASTEA_A_SOC_CORE_PCIE_INTR_CLR_GRP1, + .d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 = + ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1, + .d_A_SOC_PCIE_PCIE_SCRATCH_0 = ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_0, + .d_A_SOC_PCIE_PCIE_SCRATCH_1 = ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_1, + .d_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA = + ADRASTEA_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA, + .d_A_SOC_PCIE_PCIE_SCRATCH_2 = ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_2, + .d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK = + ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK, + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = ADRASTEA_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = + ADRASTEA_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = ADRASTEA_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = + ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = + ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = + ADRASTEA_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = ADRASTEA_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = ADRASTEA_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = ADRASTEA_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = ADRASTEA_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = ADRASTEA_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = + ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = + ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = + ADRASTEA_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = ADRASTEA_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = ADRASTEA_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = ADRASTEA_AMBA_DEBUG_BUS_SEL_MASK, + +#ifdef QCA_WIFI_3_0_ADRASTEA + .d_Q6_ENABLE_REGISTER_0 = ADRASTEA_Q6_ENABLE_REGISTER_0, + .d_Q6_ENABLE_REGISTER_1 = ADRASTEA_Q6_ENABLE_REGISTER_1, + .d_Q6_CAUSE_REGISTER_0 = ADRASTEA_Q6_CAUSE_REGISTER_0, + .d_Q6_CAUSE_REGISTER_1 = ADRASTEA_Q6_CAUSE_REGISTER_1, + .d_Q6_CLEAR_REGISTER_0 = ADRASTEA_Q6_CLEAR_REGISTER_0, + .d_Q6_CLEAR_REGISTER_1 = ADRASTEA_Q6_CLEAR_REGISTER_1, +#endif +}; + +struct hostdef_s adrastea_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = ADRASTEA_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = ADRASTEA_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = ADRASTEA_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = ADRASTEA_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = + ADRASTEA_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = + ADRASTEA_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = + ADRASTEA_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = + ADRASTEA_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = + ADRASTEA_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = + ADRASTEA_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = + ADRASTEA_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = + ADRASTEA_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = + ADRASTEA_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = + ADRASTEA_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = ADRASTEA_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = + ADRASTEA_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = + ADRASTEA_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = ADRASTEA_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = ADRASTEA_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = ADRASTEA_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = ADRASTEA_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = ADRASTEA_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = + ADRASTEA_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = + ADRASTEA_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = + ADRASTEA_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = + ADRASTEA_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = ADRASTEA_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = ADRASTEA_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = ADRASTEA_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = ADRASTEA_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = ADRASTEA_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = ADRASTEA_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = ADRASTEA_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = ADRASTEA_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = ADRASTEA_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = ADRASTEA_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = ADRASTEA_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = ADRASTEA_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = ADRASTEA_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = ADRASTEA_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = ADRASTEA_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = ADRASTEA_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = ADRASTEA_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = ADRASTEA_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = ADRASTEA_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = ADRASTEA_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = ADRASTEA_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = ADRASTEA_FW_IND_INITIALIZED, + .d_FW_IND_HELPER = ADRASTEA_FW_IND_HELPER, + .d_RTC_STATE_V_ON = ADRASTEA_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = + ADRASTEA_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = + ADRASTEA_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, + .d_HOST_CE_COUNT = 8, + .d_ENABLE_MSI = 0, + .d_MUX_ID_MASK = 0xf000, + .d_TRANSACTION_ID_MASK = 0x0fff, + .d_DESC_DATA_FLAG_MASK = 0x1FFFE3E0, + .d_A_SOC_PCIE_PCIE_BAR0_START = ADRASTEA_A_SOC_PCIE_PCIE_BAR0_START, +}; + + +struct ce_reg_def adrastea_ce_targetdef = { + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = ADRASTEA_DST_WR_INDEX_OFFSET, + .d_SRC_WATERMARK_ADDRESS = ADRASTEA_SRC_WATERMARK_OFFSET, + .d_SRC_WATERMARK_LOW_MASK = ADRASTEA_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = ADRASTEA_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = ADRASTEA_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = ADRASTEA_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = ADRASTEA_CURRENT_SRRI_OFFSET, + .d_CURRENT_DRRI_ADDRESS = ADRASTEA_CURRENT_DRRI_OFFSET, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = + ADRASTEA_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = + ADRASTEA_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = + ADRASTEA_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = + ADRASTEA_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = ADRASTEA_HOST_IS_OFFSET, + .d_MISC_IS_ADDRESS = ADRASTEA_MISC_IS_OFFSET, + .d_HOST_IS_COPY_COMPLETE_MASK = ADRASTEA_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = ADRASTEA_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = + ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_CE_WRAPPER_INDEX_BASE_LOW = ADRASTEA_CE_WRAPPER_INDEX_BASE_LOW, + .d_CE_WRAPPER_INDEX_BASE_HIGH = ADRASTEA_CE_WRAPPER_INDEX_BASE_HIGH, + .d_HOST_IE_ADDRESS = ADRASTEA_HOST_IE_OFFSET, + .d_HOST_IE_COPY_COMPLETE_MASK = ADRASTEA_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = ADRASTEA_SR_BA_OFFSET, + .d_SR_SIZE_ADDRESS = ADRASTEA_SR_SIZE_OFFSET, + .d_CE_CTRL1_ADDRESS = ADRASTEA_CE_CTRL1_OFFSET, + .d_CE_CTRL1_DMAX_LENGTH_MASK = ADRASTEA_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = ADRASTEA_DR_BA_OFFSET, + .d_DR_SIZE_ADDRESS = ADRASTEA_DR_SIZE_OFFSET, + .d_CE_CMD_REGISTER = ADRASTEA_CE_CMD_REGISTER_OFFSET, + .d_CE_MSI_ADDRESS = MISSING_FOR_ADRASTEA, + .d_CE_MSI_ADDRESS_HIGH = MISSING_FOR_ADRASTEA, + .d_CE_MSI_DATA = MISSING_FOR_ADRASTEA, + .d_CE_MSI_ENABLE_BIT = MISSING_FOR_ADRASTEA, + .d_MISC_IE_ADDRESS = ADRASTEA_MISC_IE_OFFSET, + .d_MISC_IS_AXI_ERR_MASK = ADRASTEA_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = ADRASTEA_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = ADRASTEA_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = ADRASTEA_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = + ADRASTEA_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = + ADRASTEA_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = ADRASTEA_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = ADRASTEA_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = ADRASTEA_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = ADRASTEA_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = + ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = + ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = ADRASTEA_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = + ADRASTEA_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = + ADRASTEA_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = + ADRASTEA_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = + ADRASTEA_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_CE_WRAPPER_DEBUG_OFFSET = ADRASTEA_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = ADRASTEA_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = ADRASTEA_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = ADRASTEA_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = ADRASTEA_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = ADRASTEA_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = ADRASTEA_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = ADRASTEA_CE_DEBUG_SEL_MASK, + .d_CE0_BASE_ADDRESS = ADRASTEA_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = ADRASTEA_CE1_BASE_ADDRESS, + .d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES = + MISSING_FOR_ADRASTEA, + .d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS = + MISSING_FOR_ADRASTEA, +}; + + +struct host_shadow_regs_s adrastea_host_shadow_regs = { + .d_A_LOCAL_SHADOW_REG_VALUE_0 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_0, + .d_A_LOCAL_SHADOW_REG_VALUE_1 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_1, + .d_A_LOCAL_SHADOW_REG_VALUE_2 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_2, + .d_A_LOCAL_SHADOW_REG_VALUE_3 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_3, + .d_A_LOCAL_SHADOW_REG_VALUE_4 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_4, + .d_A_LOCAL_SHADOW_REG_VALUE_5 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_5, + .d_A_LOCAL_SHADOW_REG_VALUE_6 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_6, + .d_A_LOCAL_SHADOW_REG_VALUE_7 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_7, + .d_A_LOCAL_SHADOW_REG_VALUE_8 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_8, + .d_A_LOCAL_SHADOW_REG_VALUE_9 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_9, + .d_A_LOCAL_SHADOW_REG_VALUE_10 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_10, + .d_A_LOCAL_SHADOW_REG_VALUE_11 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_11, + .d_A_LOCAL_SHADOW_REG_VALUE_12 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_12, + .d_A_LOCAL_SHADOW_REG_VALUE_13 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_13, + .d_A_LOCAL_SHADOW_REG_VALUE_14 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_14, + .d_A_LOCAL_SHADOW_REG_VALUE_15 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_15, + .d_A_LOCAL_SHADOW_REG_VALUE_16 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_16, + .d_A_LOCAL_SHADOW_REG_VALUE_17 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_17, + .d_A_LOCAL_SHADOW_REG_VALUE_18 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_18, + .d_A_LOCAL_SHADOW_REG_VALUE_19 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_19, + .d_A_LOCAL_SHADOW_REG_VALUE_20 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_20, + .d_A_LOCAL_SHADOW_REG_VALUE_21 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_21, + .d_A_LOCAL_SHADOW_REG_VALUE_22 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_22, + .d_A_LOCAL_SHADOW_REG_VALUE_23 = + ADRASTEA_A_LOCAL_SHADOW_REG_VALUE_23, + .d_A_LOCAL_SHADOW_REG_ADDRESS_0 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_0, + .d_A_LOCAL_SHADOW_REG_ADDRESS_1 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_1, + .d_A_LOCAL_SHADOW_REG_ADDRESS_2 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_2, + .d_A_LOCAL_SHADOW_REG_ADDRESS_3 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_3, + .d_A_LOCAL_SHADOW_REG_ADDRESS_4 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_4, + .d_A_LOCAL_SHADOW_REG_ADDRESS_5 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_5, + .d_A_LOCAL_SHADOW_REG_ADDRESS_6 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_6, + .d_A_LOCAL_SHADOW_REG_ADDRESS_7 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_7, + .d_A_LOCAL_SHADOW_REG_ADDRESS_8 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_8, + .d_A_LOCAL_SHADOW_REG_ADDRESS_9 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_9, + .d_A_LOCAL_SHADOW_REG_ADDRESS_10 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_10, + .d_A_LOCAL_SHADOW_REG_ADDRESS_11 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_11, + .d_A_LOCAL_SHADOW_REG_ADDRESS_12 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_12, + .d_A_LOCAL_SHADOW_REG_ADDRESS_13 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_13, + .d_A_LOCAL_SHADOW_REG_ADDRESS_14 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_14, + .d_A_LOCAL_SHADOW_REG_ADDRESS_15 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_15, + .d_A_LOCAL_SHADOW_REG_ADDRESS_16 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_16, + .d_A_LOCAL_SHADOW_REG_ADDRESS_17 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_17, + .d_A_LOCAL_SHADOW_REG_ADDRESS_18 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_18, + .d_A_LOCAL_SHADOW_REG_ADDRESS_19 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_19, + .d_A_LOCAL_SHADOW_REG_ADDRESS_20 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_20, + .d_A_LOCAL_SHADOW_REG_ADDRESS_21 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_21, + .d_A_LOCAL_SHADOW_REG_ADDRESS_22 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_22, + .d_A_LOCAL_SHADOW_REG_ADDRESS_23 = + ADRASTEA_A_LOCAL_SHADOW_REG_ADDRESS_23 +}; + +#endif /* ADRASTEA_REG_DEF_H */ diff --git a/core/hif/src/ar6320def.h b/core/hif/src/ar6320def.h new file mode 100644 index 000000000000..eacce5d62894 --- /dev/null +++ b/core/hif/src/ar6320def.h @@ -0,0 +1,796 @@ +/* + * 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_MUX_ID_MASK 0x0000 +#define AR6320_TRANSACTION_ID_MASK 0x3fff +#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 +#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_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, + /* 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 */ + + .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, + +}; + +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, + .d_MUX_ID_MASK = AR6320_MUX_ID_MASK, + .d_TRANSACTION_ID_MASK = AR6320_TRANSACTION_ID_MASK, +#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, + .d_HOST_CE_COUNT = 8, + .d_ENABLE_MSI = 0, +}; + + +struct ce_reg_def ar6320_ce_targetdef = { + /* 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_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, + .d_CE0_BASE_ADDRESS = AR6320_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320_CE1_BASE_ADDRESS, + +}; + +#endif diff --git a/core/hif/src/ar6320v2def.h b/core/hif/src/ar6320v2def.h new file mode 100644 index 000000000000..1b3b92598fcc --- /dev/null +++ b/core/hif/src/ar6320v2def.h @@ -0,0 +1,815 @@ +/* + * 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_MUX_ID_MASK 0x0000 +#define AR6320V2_TRANSACTION_ID_MASK 0x3fff +#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 +#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_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_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_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, + /* 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 */ + + .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, +}; + +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, + .d_MUX_ID_MASK = AR6320V2_MUX_ID_MASK, + .d_TRANSACTION_ID_MASK = AR6320V2_TRANSACTION_ID_MASK, +#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, + .d_HOST_CE_COUNT = 8, + .d_ENABLE_MSI = 0, +}; + +struct ce_reg_def ar6320v2_ce_targetdef = { + /* 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_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, + .d_CE0_BASE_ADDRESS = AR6320V2_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR6320V2_CE1_BASE_ADDRESS, + +}; + +#endif diff --git a/core/hif/src/ar9888def.h b/core/hif/src/ar9888def.h new file mode 100644 index 000000000000..fd9987b6f8cd --- /dev/null +++ b/core/hif/src/ar9888def.h @@ -0,0 +1,590 @@ +/* + * 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 _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_MUX_ID_MASK 0x0000 +#define AR9888_TRANSACTION_ID_MASK 0x3fff +#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 +#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_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, + + .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, + .d_MUX_ID_MASK = AR9888_MUX_ID_MASK, + .d_TRANSACTION_ID_MASK = AR9888_TRANSACTION_ID_MASK, +#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, + .d_HOST_CE_COUNT = 8, + .d_ENABLE_MSI = 0, +}; + + +struct ce_reg_def ar9888_ce_targetdef = { + /* 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_CE0_BASE_ADDRESS = AR9888_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = AR9888_CE1_BASE_ADDRESS, + +}; +#endif diff --git a/core/hif/src/ath_procfs.c b/core/hif/src/ath_procfs.c new file mode 100644 index 000000000000..48b3021e146b --- /dev/null +++ b/core/hif/src/ath_procfs.c @@ -0,0 +1,201 @@ +/* + * 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(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 */ +#include "ol_if_athvar.h" +#include "hif.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 "cds_api.h" +#include "hif_debug.h" + +#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) +{ + struct ol_softc *scn; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) + scn = (struct ol_softc *)PDE_DATA(file_inode(file)); +#else + scn = (struct ol_softc *)( + PDE(file->f_path.dentry->d_inode)->data); +#endif + return (void *)scn; +} + +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; + uint8_t *read_buffer = NULL; + + read_buffer = cdf_mem_malloc(count); + if (NULL == read_buffer) { + HIF_ERROR("%s: cdf_mem_alloc failed", __func__); + return -ENOMEM; + } + + hif_hdl = get_hif_hdl_from_file(file); + HIF_DBG("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p", + read_buffer, count, (int)*pos, buf); + + if ((count == 4) && ((((uint32_t) (*pos)) & 3) == 0)) { + /* reading a word? */ + rv = hif_diag_read_access(hif_hdl, (uint32_t)(*pos), + (uint32_t *)read_buffer); + } else { + rv = hif_diag_read_mem(hif_hdl, (uint32_t)(*pos), + (uint8_t *)read_buffer, count); + } + + if (copy_to_user(buf, read_buffer, count)) { + cdf_mem_free(read_buffer); + HIF_ERROR("%s: copy_to_user error in /proc/%s", + __func__, PROCFS_NAME); + return -EFAULT; + } else + cdf_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; + uint8_t *write_buffer = NULL; + + write_buffer = cdf_mem_malloc(count); + if (NULL == write_buffer) { + HIF_ERROR("%s: cdf_mem_alloc failed", __func__); + return -ENOMEM; + } + if (copy_from_user(write_buffer, buf, count)) { + cdf_mem_free(write_buffer); + HIF_ERROR("%s: copy_to_user error in /proc/%s", + __func__, PROCFS_NAME); + return -EFAULT; + } + + hif_hdl = get_hif_hdl_from_file(file); + HIF_DBG("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x", + write_buffer, buf, count, + (int)*pos, *((uint32_t *) write_buffer)); + + if ((count == 4) && ((((uint32_t) (*pos)) & 3) == 0)) { + /* reading a word? */ + uint32_t value = *((uint32_t *)write_buffer); + rv = hif_diag_write_access(hif_hdl, (uint32_t)(*pos), value); + } else { + rv = hif_diag_write_mem(hif_hdl, (uint32_t)(*pos), + (uint8_t *)write_buffer, count); + } + + cdf_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); + HIF_ERROR("%s: Error: Could not initialize /proc/%s", + __func__, 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); + HIF_ERROR("%s: Could not initialize /proc/%s", + __func__, PROCFS_NAME); + return -ENOMEM; + } + + HIF_DBG("/proc/%s/%s created", PROCFS_DIR, PROCFS_NAME); + return 0; /* everything is ok */ +} + +/** + *This function is called when the module is unloaded + * + */ +void athdiag_procfs_remove(void) +{ + remove_proc_entry(PROCFS_NAME, proc_dir); + HIF_DBG("/proc/%s/%s removed", PROCFS_DIR, PROCFS_NAME); + remove_proc_entry(PROCFS_DIR, NULL); + HIF_DBG("/proc/%s removed", PROCFS_DIR); +} +#else +int athdiag_procfs_init(void *scn) +{ + return 0; +} +void athdiag_procfs_remove(void) {} +#endif diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h new file mode 100644 index 000000000000..8bde74dba5d7 --- /dev/null +++ b/core/hif/src/ce/ce_api.h @@ -0,0 +1,471 @@ +/* + * 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 __COPY_ENGINE_API_H__ +#define __COPY_ENGINE_API_H__ + +#include "ce_main.h" +/* 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, + cdf_dma_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int sw_index, + unsigned int hw_index, + uint32_t toeplitz_hash_result); + +/* + * "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, + cdf_dma_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, + cdf_dma_addr_t buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags, + unsigned int user_flags); + +#ifdef WLAN_FEATURE_FASTPATH +int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, + unsigned int num_msdus, unsigned int transfer_id); + +#endif +void ce_pkt_dl_len_set(void *hif_sc, unsigned int pkt_download_len); + +/* + * 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, + cdf_dma_addr_t buffer, + unsigned int nbytes, + uint32_t flags, /* OR-ed with internal flags */ + uint32_t user_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); + +/*==================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, + cdf_dma_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 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 + +void ce_enable_msi(struct ol_softc *scn, + unsigned int CE_id, + uint32_t msi_addr_lo, + uint32_t msi_addr_hi, + uint32_t msi_data); +/* + * 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, + cdf_dma_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, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx, + uint32_t *toeplitz_hash_result); + +/*==================CE Engine Initialization=================================*/ + +/* Initialize an instance of a CE */ +struct CE_handle *ce_init(struct ol_softc *scn, + 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. + */ +CDF_STATUS +ce_revoke_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + cdf_dma_addr_t *bufferp); + +/* + * Support clean shutdown by allowing the caller to cancel + * pending sends. Target DMA must be stopped before using + * this API. + */ +CDF_STATUS +ce_cancel_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + uint32_t *toeplitz_hash_result); + +void ce_fini(struct CE_handle *copyeng); + +/*==================CE Interrupt Handlers====================================*/ +void ce_per_engine_service_any(int irq, struct ol_softc *scn); +int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id); +void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id); + +/*===================CE cmpl interrupt Enable/Disable =======================*/ +void ce_disable_any_copy_compl_intr(struct ol_softc *scn); +void ce_enable_any_copy_compl_intr(struct ol_softc *scn); +void ce_disable_any_copy_compl_intr_nolock(struct ol_softc *scn); +void ce_enable_any_copy_compl_intr_nolock(struct ol_softc *scn); + +/* API to check if any of the copy engine pipes has + * pending frames for prcoessing + */ +bool ce_get_rx_pending(struct ol_softc *scn); + +/* 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 /* for shared IRQ's */ + +#ifdef IPA_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_ipa_get_resource(struct CE_handle *ce, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr); +#else +static inline void ce_ipa_get_resource(struct CE_handle *ce, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr) +{ + return; +} +#endif /* IPA_OFFLOAD */ + +static inline void ce_pkt_error_count_incr( + struct HIF_CE_state *_hif_state, + enum ol_ath_hif_pkt_ecodes _hif_ecode) +{ + if (_hif_ecode == HIF_PIPE_NO_RESOURCE) + (_hif_state->scn->pkt_stats.hif_pipe_no_resrc_count) + += 1; +} + +int hif_completion_thread(struct HIF_CE_state *hif_state); +bool ce_check_rx_pending(struct ol_softc *scn, int ce_id); +#if defined(FEATURE_LRO) +void ce_lro_flush_cb_register(struct ol_softc *scn, + void (handler)(void *), void *data); +#endif +#endif /* __COPY_ENGINE_API_H__ */ diff --git a/core/hif/src/ce/ce_assignment.h b/core/hif/src/ce/ce_assignment.h new file mode 100644 index 000000000000..b493d55502cd --- /dev/null +++ b/core/hif/src/ce/ce_assignment.h @@ -0,0 +1,291 @@ +/* + * 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. + */ + +/* + * Implementation of the Host-side Host InterFace (HIF) API + * for a Host/Target interconnect using Copy Engines over PCIe. + */ + +#ifndef __HIF_PCI_INTERNAL_H__ +#define __HIF_PCI_INTERNAL_H__ + +#define HIF_PCI_DEBUG ATH_DEBUG_MAKE_MODULE_MASK(0) +#define HIF_PCI_IPA_UC_ASSIGNED_CE 5 + +#if defined(DEBUG) +static ATH_DEBUG_MASK_DESCRIPTION g_hif_debug_description[] = { + {HIF_PCI_DEBUG, "hif_pci"}, +}; + +ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, "hif", "PCIe Host Interface", + ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO, + ATH_DEBUG_DESCRIPTION_COUNT + (g_hif_debug_description), + g_hif_debug_description); +#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 hif_target_dump_access_log(void); +#endif + +/* + * 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 + +/* Maximum number of Copy Engine's supported */ +#define CE_HTT_H2T_MSG_SRC_NENTRIES 2048 + +#define DIAG_CE_ID 7 +#define EPPING_CE_FLAGS_POLL \ + (CE_ATTR_DISABLE_INTR|CE_ATTR_ENABLE_POLL|CE_ATTR_FLAGS) +#ifdef QCA_WIFI_3_0 +static struct CE_attr host_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 2048, 0, NULL,}, + /* target->host HTT + HTC control */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* target->host WMI */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,}, + /* host->target WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + /* ipa_uc->target HTC control */ + { /* CE5 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + 1024, 512, 0, NULL,}, + /* Target autonomous HIF_memcpy */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; + +static struct CE_pipe_config target_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host HTT */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host WMI + HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* NB: 50% of src nentries, since tx has 2 frags */ + /* ipa_uc->target */ + { /* CE5 */ 5, PIPEDIR_OUT, 1024, 64, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Reserved for target autonomous HIF_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* CE8 used only by IPA */ + { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,} +}; + +static struct CE_attr host_ce_config_wlan_epping_poll[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 2048, 0, NULL,}, + /* target->host EP-ping */ + { /* CE1 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL,}, + /* target->host EP-ping */ + { /* CE2 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL,}, + /* host->target EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* EP-ping heartbeat */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* unused */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; + +static struct CE_attr host_ce_config_wlan_epping_irq[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 2048, 0, NULL,}, + /* target->host EP-ping */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* target->host EP-ping */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* host->target EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* EP-ping heartbeat */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* unused */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; +/* + * EP-ping firmware's CE configuration + */ +static struct CE_pipe_config target_ce_config_wlan_epping[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 16, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host EP-ping */ + { /* CE1 */ 1, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host EP-ping */ + { /* CE2 */ 2, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target 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,}, + /* EP-ping heartbeat */ + { /* CE5 */ 5, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* unused */ + { /* CE6 */ 6, PIPEDIR_INOUT, 0, 0, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, 0, 0,}, + /* CE8 used only by IPA */ + { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,} +}; +#else +static struct CE_attr host_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,}, + /* target->host HTT + HTC control */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* target->host WMI */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,}, + /* host->target WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + /* ipa_uc->target HTC control */ + { /* CE5 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, + 1024, 512, 0, NULL,}, + /* Target autonomous HIF_memcpy */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, + 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; + +static struct CE_pipe_config target_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0,}, + /* target->host HTT + HTC control */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host WMI */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0,}, + /* NB: 50% of src nentries, since tx has 2 frags */ + /* ipa_uc->target HTC control */ + { /* CE5 */ 5, PIPEDIR_OUT, 1024, 64, CE_ATTR_FLAGS, 0,}, + /* Reserved for target autonomous HIF_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, 0, 0,}, + /* CE8 used only by IPA */ + { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,} +}; + +static struct CE_attr host_ce_config_wlan_epping_poll[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,}, + /* target->host EP-ping */ + { /* CE1 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL,}, + /* target->host EP-ping */ + { /* CE2 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 128, NULL,}, + /* host->target EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* EP-ping heartbeat */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* unused */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; +static struct CE_attr host_ce_config_wlan_epping_irq[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,}, + /* target->host EP-ping */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* target->host EP-ping */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* host->target EP-ping */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* host->target EP-ping */ + { /* CE4 */ CE_ATTR_FLAGS, 0, 128, 2048, 0, NULL,}, + /* EP-ping heartbeat */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL,}, + /* unused */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; +/* + * EP-ping firmware's CE configuration + */ +static struct CE_pipe_config target_ce_config_wlan_epping[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 16, 256, CE_ATTR_FLAGS, 0,}, + /* target->host EP-ping */ + { /* CE1 */ 1, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host EP-ping */ + { /* CE2 */ 2, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target 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,}, + /* EP-ping heartbeat */ + { /* CE5 */ 5, PIPEDIR_IN, 128, 2048, CE_ATTR_FLAGS, 0,}, + /* unused */ + { /* CE6 */ 6, PIPEDIR_INOUT, 0, 0, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, 0, 0,}, + /* CE8 used only by IPA */ + { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,} +}; +#endif + +static struct CE_attr *host_ce_config = host_ce_config_wlan; +static struct CE_pipe_config *target_ce_config = target_ce_config_wlan; +static int target_ce_config_sz = sizeof(target_ce_config_wlan); +#endif /* __HIF_PCI_INTERNAL_H__ */ diff --git a/core/hif/src/ce/ce_bmi.c b/core/hif/src/ce/ce_bmi.c new file mode 100644 index 000000000000..b2d541d2d2f4 --- /dev/null +++ b/core/hif/src/ce/ce_bmi.c @@ -0,0 +1,293 @@ +/* + * 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. + */ + +#include +#include "a_types.h" +#include "athdefs.h" +#include "osapi_linux.h" +#include "targcfg.h" +#include "cdf_lock.h" +#include "cdf_status.h" +#include /* cdf_atomic_read */ +#include +#include +#include "hif_io32.h" +#include +#include "regtable.h" +#define ATH_MODULE_NAME hif +#include +#include "hif_main.h" +#include "ce_api.h" +#include "cdf_trace.h" +#include "cds_api.h" +#ifdef CONFIG_CNSS +#include +#else +#include "cnss_stub.h" +#endif +#include +#include "epping_main.h" +#include "hif_debug.h" + +/* Track a BMI transaction that is in progress */ +#ifndef BIT +#define BIT(n) (1 << (n)) +#endif + +enum { + BMI_REQ_SEND_DONE = BIT(0), /* the bmi tx completion */ + BMI_RESP_RECV_DONE = BIT(1), /* the bmi respond is received */ +}; + +struct BMI_transaction { + struct HIF_CE_state *hif_state; + cdf_semaphore_t bmi_transaction_sem; + uint8_t *bmi_request_host; /* Req BMI msg in Host addr space */ + cdf_dma_addr_t bmi_request_CE; /* Req BMI msg in CE addr space */ + uint32_t bmi_request_length; /* Length of BMI request */ + uint8_t *bmi_response_host; /* Rsp BMI msg in Host addr space */ + cdf_dma_addr_t bmi_response_CE; /* Rsp BMI msg in CE addr space */ + unsigned int bmi_response_length; /* Length of received response */ + unsigned int bmi_timeout_ms; + uint32_t bmi_transaction_flags; /* flags for the transcation */ +}; + +/* + * send/recv completion functions for BMI. + * NB: The "net_buf" parameter is actually just a + * straight buffer, not an sk_buff. + */ +void hif_bmi_send_done(struct CE_handle *copyeng, void *ce_context, + void *transfer_context, cdf_dma_addr_t data, + unsigned int nbytes, + unsigned int transfer_id, unsigned int sw_index, + unsigned int hw_index, uint32_t toeplitz_hash_result) +{ + struct BMI_transaction *transaction = + (struct BMI_transaction *)transfer_context; + struct ol_softc *scn = transaction->hif_state->scn; + +#ifdef BMI_RSP_POLLING + /* + * Fix EV118783, Release a semaphore after sending + * no matter whether a response is been expecting now. + */ + cdf_semaphore_release(scn->cdf_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)) { + cdf_semaphore_release(scn->cdf_dev, + &transaction->bmi_transaction_sem); + } +#endif +} + +#ifndef BMI_RSP_POLLING +void hif_bmi_recv_data(struct CE_handle *copyeng, void *ce_context, + void *transfer_context, cdf_dma_addr_t data, + unsigned int nbytes, + unsigned int transfer_id, unsigned int flags) +{ + struct BMI_transaction *transaction = + (struct BMI_transaction *)transfer_context; + struct ol_softc *scn = transaction->hif_state->scn; + + 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) { + cdf_semaphore_release(scn->cdf_dev, + &transaction->bmi_transaction_sem); + } +} +#endif + +CDF_STATUS hif_exchange_bmi_msg(struct ol_softc *scn, + uint8_t *bmi_request, + uint32_t request_length, + uint8_t *bmi_response, + uint32_t *bmi_response_lengthp, uint32_t TimeoutMS) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + struct HIF_CE_pipe_info *send_pipe_info = + &(hif_state->pipe_info[BMI_CE_NUM_TO_TARG]); + struct CE_handle *ce_send_hdl = send_pipe_info->ce_hdl; + cdf_dma_addr_t CE_request, CE_response = 0; + struct BMI_transaction *transaction = NULL; + int status = CDF_STATUS_SUCCESS; + 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; + unsigned int mux_id = 0; + unsigned int transaction_id = 0xffff; + unsigned int user_flags = 0; +#ifdef BMI_RSP_POLLING + cdf_dma_addr_t buf; + unsigned int completed_nbytes, id, flags; + int i; +#endif + + transaction = + (struct BMI_transaction *)cdf_mem_malloc(sizeof(*transaction)); + if (unlikely(!transaction)) { + HIF_ERROR("%s: no memory", __func__); + return CDF_STATUS_E_NOMEM; + } + transaction_id = (mux_id & MUX_ID_MASK) | + (transaction_id & TRANSACTION_ID_MASK); +#ifdef QCA_WIFI_3_0 + user_flags &= DESC_DATA_FLAG_MASK; +#endif + A_TARGET_ACCESS_LIKELY(scn); + + /* Initialize bmi_transaction_sem to block */ + cdf_semaphore_init(&transaction->bmi_transaction_sem); + cdf_semaphore_acquire(scn->cdf_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->bmi_cmd_da; + 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->bmi_rsp_da; + transaction->bmi_response_host = bmi_response; + transaction->bmi_response_CE = CE_response; + /* dma_cache_sync(dev, bmi_response, + BMI_DATASZ_MAX, DMA_FROM_DEVICE); */ + cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, + CE_response, + BMI_DATASZ_MAX, + DMA_FROM_DEVICE); + 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); */ + cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, CE_request, + request_length, DMA_TO_DEVICE); + + status = + ce_send(ce_send_hdl, transaction, + CE_request, request_length, + transaction_id, 0, user_flags); + ASSERT(status == CDF_STATUS_SUCCESS); + /* 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 (cdf_semaphore_acquire + (scn->cdf_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) != CDF_STATUS_SUCCESS) { + if (i++ > BMI_RSP_TO_MILLISEC) { + HIF_ERROR("%s:error, can't get bmi response\n", + __func__); + status = CDF_STATUS_E_BUSY; + break; + } + OS_DELAY(1000); + } + + if ((status == CDF_STATUS_SUCCESS) && bmi_response_lengthp) + *bmi_response_lengthp = completed_nbytes; +#else + if ((status == CDF_STATUS_SUCCESS) && 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 != CDF_STATUS_SUCCESS) { + cdf_dma_addr_t unused_buffer; + unsigned int unused_nbytes; + unsigned int unused_id; + unsigned int toeplitz_hash_result; + + ce_cancel_send_next(ce_send_hdl, + NULL, NULL, &unused_buffer, + &unused_nbytes, &unused_id, + &toeplitz_hash_result); + } + + A_TARGET_ACCESS_UNLIKELY(scn); + cdf_mem_free(transaction); + return status; +} diff --git a/core/hif/src/ce/ce_bmi.h b/core/hif/src/ce/ce_bmi.h new file mode 100644 index 000000000000..c09b211b6e3e --- /dev/null +++ b/core/hif/src/ce/ce_bmi.h @@ -0,0 +1,45 @@ +/* + * 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 __CE_BMI_H__ +#define __CE_BMI_H__ + +#include /* cdf_atomic_read */ +#include "cdf_lock.h" +#include "ce_api.h" +#include "cepci.h" + +void hif_bmi_recv_data(struct CE_handle *copyeng, void *ce_context, + void *transfer_context, cdf_dma_addr_t data, + unsigned int nbytes, + unsigned int transfer_id, unsigned int flags); +void hif_bmi_send_done(struct CE_handle *copyeng, void *ce_context, + void *transfer_context, cdf_dma_addr_t data, + unsigned int nbytes, + unsigned int transfer_id, unsigned int sw_index, + unsigned int hw_index, uint32_t toeplitz_hash_result); +#endif /* __CE_BMI_H__ */ diff --git a/core/hif/src/ce/ce_diag.c b/core/hif/src/ce/ce_diag.c new file mode 100644 index 000000000000..c078f218b01a --- /dev/null +++ b/core/hif/src/ce/ce_diag.c @@ -0,0 +1,456 @@ +/* + * 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. + */ + +#include +#include "a_types.h" +#include "athdefs.h" +#include "osapi_linux.h" +#include "targcfg.h" +#include "cdf_lock.h" +#include "cdf_status.h" +#include /* cdf_atomic_read */ +#include +#include +#include "hif_io32.h" +#include +#include +#include "regtable.h" +#include +#include "hif_main.h" +#include "ce_api.h" +#include "cdf_trace.h" +#include "cds_api.h" +#ifdef CONFIG_CNSS +#include +#endif +#include +#include "hif_debug.h" +#include "epping_main.h" + +void hif_dump_target_memory(struct ol_softc *scn, void *ramdump_base, + uint32_t address, uint32_t size) +{ + uint32_t loc = address; + uint32_t val = 0; + uint32_t j = 0; + u8 *temp = ramdump_base; + + A_TARGET_ACCESS_BEGIN(scn); + while (j < size) { + val = hif_read32_mb(scn->mem + loc + j); + cdf_mem_copy(temp, &val, 4); + j += 4; + temp += 4; + } + A_TARGET_ACCESS_END(scn); +} +/* + * 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. + */ +#ifdef QCA_WIFI_3_0 +#define TARG_CPU_SPACE_TO_CE_SPACE(pci_addr, addr) \ + (scn->mem_pa + addr) +#else +#define TARG_CPU_SPACE_TO_CE_SPACE(pci_addr, addr) \ + (((hif_read32_mb((pci_addr) + \ + (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \ + | 0x100000 | ((addr) & 0xfffff)) +#endif +/* 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. + */ + +CDF_STATUS +hif_diag_read_mem(struct ol_softc *scn, uint32_t address, uint8_t *data, + int nbytes) +{ + struct HIF_CE_state *hif_state; + CDF_STATUS status = CDF_STATUS_SUCCESS; + cdf_dma_addr_t buf; + unsigned int completed_nbytes, orig_nbytes, remaining_bytes; + unsigned int id; + unsigned int flags; + struct CE_handle *ce_diag; + cdf_dma_addr_t CE_data; /* Host buffer address in CE space */ + cdf_dma_addr_t CE_data_base = 0; + void *data_buf = NULL; + int i; + unsigned int mux_id = 0; + unsigned int transaction_id = 0xffff; + cdf_dma_addr_t ce_phy_addr = address; + unsigned int toeplitz_hash_result; + unsigned int user_flags = 0; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + transaction_id = (mux_id & MUX_ID_MASK) | + (transaction_id & TRANSACTION_ID_MASK); +#ifdef QCA_WIFI_3_0 + user_flags &= DESC_DATA_FLAG_MASK; +#endif + + /* 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 CDF_STATUS_E_INVAL; + + while ((nbytes >= 4) && + (CDF_STATUS_SUCCESS == (status = + hif_diag_read_access(scn, address, + (uint32_t *)data)))) { + + nbytes -= sizeof(uint32_t); + address += sizeof(uint32_t); + data += sizeof(uint32_t); + + } + + return status; + } + ce_diag = hif_state->ce_diag; + + A_TARGET_ACCESS_LIKELY(scn); + + /* + * 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 = cdf_os_mem_alloc_consistent(scn->cdf_dev, + orig_nbytes, &CE_data_base, 0); + if (!data_buf) { + status = CDF_STATUS_E_NOMEM; + goto done; + } + cdf_mem_set(data_buf, orig_nbytes, 0); + cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, CE_data_base, + orig_nbytes, DMA_FROM_DEVICE); + + 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 != CDF_STATUS_SUCCESS) + 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(scn); + ce_phy_addr = + TARG_CPU_SPACE_TO_CE_SPACE(scn->mem, address); + A_TARGET_ACCESS_END_RET(scn); + + status = + ce_send(ce_diag, NULL, ce_phy_addr, nbytes, + transaction_id, 0, user_flags); + if (status != CDF_STATUS_SUCCESS) + goto done; + } + + i = 0; + while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, NULL, NULL, + &toeplitz_hash_result) != CDF_STATUS_SUCCESS) { + cdf_mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = CDF_STATUS_E_BUSY; + goto done; + } + } + if (nbytes != completed_nbytes) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + if (buf != ce_phy_addr) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + i = 0; + while (ce_completed_recv_next + (ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, + &flags) != CDF_STATUS_SUCCESS) { + cdf_mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = CDF_STATUS_E_BUSY; + goto done; + } + } + if (nbytes != completed_nbytes) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + if (buf != CE_data) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + CE_data += nbytes; + } + +done: + A_TARGET_ACCESS_UNLIKELY(scn); + + if (status == CDF_STATUS_SUCCESS) + cdf_mem_copy(data, data_buf, orig_nbytes); + else + HIF_ERROR("%s failure (0x%x)", __func__, address); + + if (data_buf) + cdf_os_mem_free_consistent(scn->cdf_dev, orig_nbytes, + data_buf, CE_data_base, 0); + + return status; +} + +/* Read 4-byte aligned data from Target memory or register */ +CDF_STATUS hif_diag_read_access(struct ol_softc *scn, + uint32_t address, uint32_t *data) +{ + struct HIF_CE_state *hif_state; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + if (address >= DRAM_BASE_ADDRESS) { + /* Assume range doesn't cross this boundary */ + return hif_diag_read_mem(scn, address, (uint8_t *) data, + sizeof(uint32_t)); + } else { + A_TARGET_ACCESS_BEGIN_RET(scn); + *data = A_TARGET_READ(scn, address); + A_TARGET_ACCESS_END_RET(scn); + + return CDF_STATUS_SUCCESS; + } +} + +CDF_STATUS hif_diag_write_mem(struct ol_softc *scn, + uint32_t address, uint8_t *data, int nbytes) +{ + struct HIF_CE_state *hif_state; + CDF_STATUS status = CDF_STATUS_SUCCESS; + cdf_dma_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; + cdf_dma_addr_t CE_data; /* Host buffer address in CE space */ + cdf_dma_addr_t CE_data_base = 0; + int i; + unsigned int mux_id = 0; + unsigned int transaction_id = 0xffff; + cdf_dma_addr_t ce_phy_addr = address; + unsigned int toeplitz_hash_result; + unsigned int user_flags = 0; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + ce_diag = hif_state->ce_diag; + transaction_id = (mux_id & MUX_ID_MASK) | + (transaction_id & TRANSACTION_ID_MASK); +#ifdef QCA_WIFI_3_0 + user_flags &= DESC_DATA_FLAG_MASK; +#endif + + A_TARGET_ACCESS_LIKELY(scn); + + /* + * 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 = cdf_os_mem_alloc_consistent(scn->cdf_dev, + orig_nbytes, &CE_data_base, 0); + if (!data_buf) { + status = A_NO_MEMORY; + goto done; + } + + /* Copy caller's data to allocated DMA buf */ + cdf_mem_copy(data_buf, data, orig_nbytes); + cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, CE_data_base, + orig_nbytes, DMA_TO_DEVICE); + + /* + * 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(scn); + ce_phy_addr = TARG_CPU_SPACE_TO_CE_SPACE(scn->mem, address); + A_TARGET_ACCESS_END_RET(scn); + + 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, ce_phy_addr); + if (status != CDF_STATUS_SUCCESS) + goto done; + } + + { + /* + * Request CE to send caller-supplied data that + * was copied to bounce buffer to Target(!) address. + */ + status = + ce_send(ce_diag, NULL, + (cdf_dma_addr_t) CE_data, nbytes, + transaction_id, 0, user_flags); + if (status != CDF_STATUS_SUCCESS) + goto done; + } + + i = 0; + while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, + NULL, NULL, &toeplitz_hash_result) != + CDF_STATUS_SUCCESS) { + cdf_mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = CDF_STATUS_E_BUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + if (buf != CE_data) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + i = 0; + while (ce_completed_recv_next + (ce_diag, NULL, NULL, &buf, + &completed_nbytes, &id, + &flags) != CDF_STATUS_SUCCESS) { + cdf_mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + status = CDF_STATUS_E_BUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + if (buf != ce_phy_addr) { + status = CDF_STATUS_E_FAILURE; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + CE_data += nbytes; + } + +done: + A_TARGET_ACCESS_UNLIKELY(scn); + + if (data_buf) { + cdf_os_mem_free_consistent(scn->cdf_dev, orig_nbytes, + data_buf, CE_data_base, 0); + } + + if (status != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s failure (0x%llu)", __func__, + (uint64_t)ce_phy_addr); + } + + return status; +} + +/* Write 4B data to Target memory or register */ +CDF_STATUS +hif_diag_write_access(struct ol_softc *scn, uint32_t address, uint32_t data) +{ + struct HIF_CE_state *hif_state; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + if (address >= DRAM_BASE_ADDRESS) { + /* Assume range doesn't cross this boundary */ + uint32_t data_buf = data; + + return hif_diag_write_mem(scn, address, + (uint8_t *) &data_buf, + sizeof(uint32_t)); + } else { + A_TARGET_ACCESS_BEGIN_RET(scn); + A_TARGET_WRITE(scn, address, data); + A_TARGET_ACCESS_END_RET(scn); + + return CDF_STATUS_SUCCESS; + } +} diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h new file mode 100644 index 000000000000..b3fa70737007 --- /dev/null +++ b/core/hif/src/ce/ce_internal.h @@ -0,0 +1,314 @@ +/* + * 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 __COPY_ENGINE_INTERNAL_H__ +#define __COPY_ENGINE_INTERNAL_H__ + +#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 */ + cdf_dma_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 */ + cdf_dma_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 ol_softc *scn; + unsigned int id; + unsigned int attr_flags; /* CE_ATTR_* */ + uint32_t ctrl_addr; /* relative to BAR */ + enum CE_op_state state; + +#ifdef WLAN_FEATURE_FASTPATH + u_int32_t download_len; /* pkt download length for source ring */ +#endif /* WLAN_FEATURE_FASTPATH */ + + 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? */ + uint8_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; + cdf_softirq_timer_t poll_timer; + void (*lro_flush_cb)(void *); + void *lro_data; +}; + +/* Descriptor rings must be aligned to this boundary */ +#define CE_DESC_RING_ALIGN 8 + +#ifdef QCA_WIFI_3_0 +#define HIF_CE_DESC_ADDR_TO_DMA(desc) \ + (cdf_dma_addr_t)(((uint64_t)(desc)->buffer_addr + \ + ((uint64_t)((desc)->buffer_addr_hi & 0x1F) << 32))) +#else +#define HIF_CE_DESC_ADDR_TO_DMA(desc) \ + (cdf_dma_addr_t)((desc)->buffer_addr) +#endif + +#ifdef QCA_WIFI_3_0 +struct CE_src_desc { + uint32_t buffer_addr:32; +#if _BYTE_ORDER == _BIG_ENDIAN + uint32_t gather:1, + enable_11h:1, + meta_data_low:2, /* fw_metadata_low */ + packet_result_offset:12, + toeplitz_hash_enable:1, + addr_y_search_disable:1, + addr_x_search_disable:1, + misc_int_disable:1, + target_int_disable:1, + host_int_disable:1, + dest_byte_swap:1, + byte_swap:1, + type:2, + tx_classify:1, + buffer_addr_hi:5; + uint32_t meta_data:16, /* fw_metadata_high */ + nbytes:16; /* length in register map */ +#else + uint32_t buffer_addr_hi:5, + tx_classify:1, + type:2, + byte_swap:1, /* src_byte_swap */ + dest_byte_swap:1, + host_int_disable:1, + target_int_disable:1, + misc_int_disable:1, + addr_x_search_disable:1, + addr_y_search_disable:1, + toeplitz_hash_enable:1, + packet_result_offset:12, + meta_data_low:2, /* fw_metadata_low */ + enable_11h:1, + gather:1; + uint32_t nbytes:16, /* length in register map */ + meta_data:16; /* fw_metadata_high */ +#endif + uint32_t toeplitz_hash_result:32; +}; + +struct CE_dest_desc { + uint32_t buffer_addr:32; +#if _BYTE_ORDER == _BIG_ENDIAN + uint32_t gather:1, + enable_11h:1, + meta_data_low:2, /* fw_metadata_low */ + packet_result_offset:12, + toeplitz_hash_enable:1, + addr_y_search_disable:1, + addr_x_search_disable:1, + misc_int_disable:1, + target_int_disable:1, + host_int_disable:1, + byte_swap:1, + src_byte_swap:1, + type:2, + tx_classify:1, + buffer_addr_hi:5; + uint32_t meta_data:16, /* fw_metadata_high */ + nbytes:16; /* length in register map */ +#else + uint32_t buffer_addr_hi:5, + tx_classify:1, + type:2, + src_byte_swap:1, + byte_swap:1, /* dest_byte_swap */ + host_int_disable:1, + target_int_disable:1, + misc_int_disable:1, + addr_x_search_disable:1, + addr_y_search_disable:1, + toeplitz_hash_enable:1, + packet_result_offset:12, + meta_data_low:2, /* fw_metadata_low */ + enable_11h:1, + gather:1; + uint32_t nbytes:16, /* length in register map */ + meta_data:16; /* fw_metadata_high */ +#endif + uint32_t toeplitz_hash_result:32; +}; +#else +struct CE_src_desc { + uint32_t buffer_addr; +#if _BYTE_ORDER == _BIG_ENDIAN + uint32_t meta_data:14, + byte_swap:1, + gather:1, + nbytes:16; +#else + + uint32_t nbytes:16, + gather:1, + byte_swap:1, + meta_data:14; +#endif +}; + +struct CE_dest_desc { + uint32_t buffer_addr; +#if _BYTE_ORDER == _BIG_ENDIAN + uint32_t meta_data:14, + byte_swap:1, + gather:1, + nbytes:16; +#else + uint32_t nbytes:16, + gather:1, + byte_swap:1, + meta_data:14; +#endif +}; +#endif /* QCA_WIFI_3_0 */ + +#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 */ + uint32_t flags; + uint32_t user_flags; + } item[CE_SENDLIST_ITEMS_MAX]; +}; + +#ifdef WLAN_FEATURE_FASTPATH +void ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl); +#endif + +/* 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 */ +#endif /* __COPY_ENGINE_INTERNAL_H__ */ diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c new file mode 100644 index 000000000000..8cf00f13e9bb --- /dev/null +++ b/core/hif/src/ce/ce_main.c @@ -0,0 +1,2593 @@ +/* + * 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 "a_types.h" +#include "athdefs.h" +#include "osapi_linux.h" +#include "targcfg.h" +#include "cdf_lock.h" +#include "cdf_status.h" +#include /* cdf_atomic_read */ +#include +#include +#include "hif_io32.h" +#include +#include "regtable.h" +#define ATH_MODULE_NAME hif +#include +#include "hif_main.h" +#ifdef HIF_PCI +#include "ce_bmi.h" +#endif +#include "ce_api.h" +#include "cdf_trace.h" +#include "cds_api.h" +#ifdef CONFIG_CNSS +#include +#endif +#include +#include "epping_main.h" +#include "hif_debug.h" +#include "ce_internal.h" +#include "ce_reg.h" +#include "ce_assignment.h" +#include "ce_tasklet.h" +#ifdef HIF_PCI +#include "icnss_stub.h" +#else +#include +#endif +#include "qwlan_version.h" + +#define CE_POLL_TIMEOUT 10 /* ms */ + +/* Forward references */ +static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info); + +/* + * 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 + + +static int hif_post_recv_buffers(struct ol_softc *scn); + +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->scn, CE_state->id); + cdf_softirq_timer_mod(&CE_state->poll_timer, CE_POLL_TIMEOUT); + } +} + +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; + } + + CDF_ASSERT(0); /* n too large */ + return 0; +} + +/* + * 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 ol_softc *scn, + unsigned int CE_id, struct CE_attr *attr) +{ + struct CE_state *CE_state; + uint32_t ctrl_addr; + unsigned int nentries; + cdf_dma_addr_t base_addr; + bool malloc_CE_state = false; + bool malloc_src_ring = false; + + CDF_ASSERT(CE_id < scn->ce_count); + ctrl_addr = CE_BASE_ADDRESS(CE_id); + cdf_spin_lock(&scn->target_lock); + CE_state = scn->ce_id_to_state[CE_id]; + + if (!CE_state) { + cdf_spin_unlock(&scn->target_lock); + CE_state = + (struct CE_state *)cdf_mem_malloc(sizeof(*CE_state)); + if (!CE_state) { + HIF_ERROR("%s: CE_state has no mem", __func__); + return NULL; + } else + malloc_CE_state = true; + cdf_mem_zero(CE_state, sizeof(*CE_state)); + cdf_spin_lock(&scn->target_lock); + if (!scn->ce_id_to_state[CE_id]) { /* re-check under lock */ + scn->ce_id_to_state[CE_id] = CE_state; + + CE_state->id = CE_id; + CE_state->ctrl_addr = ctrl_addr; + CE_state->state = CE_RUNNING; + CE_state->attr_flags = attr->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). + */ + cdf_mem_free(CE_state); + malloc_CE_state = false; + CE_state = scn->ce_id_to_state[CE_id]; + } + } + CE_state->scn = scn; + cdf_spin_unlock(&scn->target_lock); + + cdf_atomic_init(&CE_state->rx_pending); + if (attr == NULL) { + /* Already initialized; caller wants the handle */ + return (struct CE_handle *)CE_state; + } + +#ifdef ADRASTEA_SHADOW_REGISTERS + HIF_ERROR("%s: Using Shadow Registers instead of CE Registers\n", + __func__); +#endif + + if (CE_state->src_sz_max) + CDF_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; + uint64_t dma_addr; + nentries = roundup_pwr2(nentries); + if (CE_state->src_ring) { + CDF_ASSERT(CE_state->src_ring->nentries == nentries); + } else { + CE_nbytes = sizeof(struct CE_ring_state) + + (nentries * sizeof(void *)); + ptr = cdf_mem_malloc(CE_nbytes); + if (!ptr) { + /* cannot allocate src ring. If the + * CE_state is allocated locally free + * CE_State and return error. + */ + HIF_ERROR("%s: src ring has no mem", __func__); + if (malloc_CE_state) { + /* allocated CE_state locally */ + cdf_spin_lock(&scn->target_lock); + scn->ce_id_to_state[CE_id] = NULL; + cdf_spin_unlock(&scn->target_lock); + cdf_mem_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; + } + cdf_mem_zero(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(scn); + src_ring->hw_index = + CE_SRC_RING_READ_IDX_GET(scn, ctrl_addr); + src_ring->sw_index = src_ring->hw_index; + src_ring->write_index = + CE_SRC_RING_WRITE_IDX_GET(scn, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(scn); + 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 = + cdf_os_mem_alloc_consistent(scn->cdf_dev, + (nentries * + sizeof(struct CE_src_desc) + + CE_DESC_RING_ALIGN), + &base_addr, 0); + if (src_ring->base_addr_owner_space_unaligned + == NULL) { + HIF_ERROR("%s: src ring has no DMA mem", + __func__); + 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 = + cdf_mem_malloc(nentries * + sizeof(struct CE_src_desc) + + CE_DESC_RING_ALIGN); + if (src_ring->shadow_base_unaligned == NULL) { + HIF_ERROR("%s: src ring no shadow_base mem", + __func__); + 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(scn); + dma_addr = src_ring->base_addr_CE_space; + CE_SRC_RING_BASE_ADDR_SET(scn, ctrl_addr, + (uint32_t)(dma_addr & 0xFFFFFFFF)); +#ifdef WLAN_ENABLE_QCA6180 + { + uint32_t tmp; + tmp = CE_SRC_RING_BASE_ADDR_HIGH_GET( + scn, ctrl_addr); + tmp &= ~0x1F; + dma_addr = ((dma_addr >> 32) & 0x1F)|tmp; + CE_SRC_RING_BASE_ADDR_HIGH_SET(scn, + ctrl_addr, (uint32_t)dma_addr); + } +#endif + CE_SRC_RING_SZ_SET(scn, ctrl_addr, nentries); + CE_SRC_RING_DMAX_SET(scn, 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(scn, ctrl_addr, 1); +#endif + CE_SRC_RING_LOWMARK_SET(scn, ctrl_addr, 0); + CE_SRC_RING_HIGHMARK_SET(scn, ctrl_addr, nentries); + A_TARGET_ACCESS_END_RET_PTR(scn); + } + } + + /* destination ring setup */ + nentries = attr->dest_nentries; + if (nentries) { + struct CE_ring_state *dest_ring; + unsigned CE_nbytes; + char *ptr; + uint64_t dma_addr; + + nentries = roundup_pwr2(nentries); + if (CE_state->dest_ring) { + CDF_ASSERT(CE_state->dest_ring->nentries == nentries); + } else { + CE_nbytes = sizeof(struct CE_ring_state) + + (nentries * sizeof(void *)); + ptr = cdf_mem_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. + */ + HIF_ERROR("%s: dest ring has no mem", + __func__); + if (malloc_src_ring) { + cdf_mem_free(CE_state->src_ring); + CE_state->src_ring = NULL; + malloc_src_ring = false; + } + if (malloc_CE_state) { + /* allocated CE_state locally */ + cdf_spin_lock(&scn->target_lock); + scn->ce_id_to_state[CE_id] = NULL; + cdf_spin_unlock(&scn->target_lock); + cdf_mem_free(CE_state); + malloc_CE_state = false; + } + return NULL; + } + cdf_mem_zero(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(scn); + dest_ring->sw_index = + CE_DEST_RING_READ_IDX_GET(scn, ctrl_addr); + dest_ring->write_index = + CE_DEST_RING_WRITE_IDX_GET(scn, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(scn); + 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 = + cdf_os_mem_alloc_consistent(scn->cdf_dev, + (nentries * + sizeof(struct CE_dest_desc) + + CE_DESC_RING_ALIGN), + &base_addr, 0); + if (dest_ring->base_addr_owner_space_unaligned + == NULL) { + HIF_ERROR("%s: dest ring has no DMA mem", + __func__); + 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 + */ + cdf_mem_zero(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(scn); + dma_addr = dest_ring->base_addr_CE_space; + CE_DEST_RING_BASE_ADDR_SET(scn, ctrl_addr, + (uint32_t)(dma_addr & 0xFFFFFFFF)); +#ifdef WLAN_ENABLE_QCA6180 + { + uint32_t tmp; + tmp = CE_DEST_RING_BASE_ADDR_HIGH_GET(scn, + ctrl_addr); + tmp &= ~0x1F; + dma_addr = ((dma_addr >> 32) & 0x1F)|tmp; + CE_DEST_RING_BASE_ADDR_HIGH_SET(scn, + ctrl_addr, (uint32_t)dma_addr); + } +#endif + CE_DEST_RING_SZ_SET(scn, ctrl_addr, nentries); +#ifdef BIG_ENDIAN_HOST + /* Enable Dest ring byte swap for big endian host */ + CE_DEST_RING_BYTE_SWAP_SET(scn, ctrl_addr, 1); +#endif + CE_DEST_RING_LOWMARK_SET(scn, ctrl_addr, 0); + CE_DEST_RING_HIGHMARK_SET(scn, ctrl_addr, nentries); + A_TARGET_ACCESS_END_RET_PTR(scn); + + /* epping */ + /* poll timer */ + if ((CE_state->attr_flags & CE_ATTR_ENABLE_POLL)) { + cdf_softirq_timer_init(scn->cdf_dev, + &CE_state->poll_timer, + ce_poll_timeout, + CE_state, + CDF_TIMER_TYPE_SW); + CE_state->timer_inited = true; + cdf_softirq_timer_mod(&CE_state->poll_timer, + CE_POLL_TIMEOUT); + } + } + } + + /* Enable CE error interrupts */ + A_TARGET_ACCESS_BEGIN_RET_PTR(scn); + CE_ERROR_INTR_ENABLE(scn, ctrl_addr); + A_TARGET_ACCESS_END_RET_PTR(scn); + + return (struct CE_handle *)CE_state; + +error_no_dma_mem: + ce_fini((struct CE_handle *)CE_state); + return NULL; +} + +#ifdef WLAN_FEATURE_FASTPATH +/** + * ce_h2t_tx_ce_cleanup() Place holder function for H2T CE cleanup. + * No processing is required inside this function. + * @ce_hdl: Cope engine handle + * Using an assert, this function makes sure that, + * the TX CE has been processed completely. + * Return: none + */ +void +ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl) +{ + struct CE_state *ce_state = (struct CE_state *)ce_hdl; + struct CE_ring_state *src_ring = ce_state->src_ring; + struct ol_softc *sc = ce_state->scn; + uint32_t sw_index, write_index; + + if (sc->fastpath_mode_on && (ce_state->id == CE_HTT_H2T_MSG)) { + HIF_INFO("%s %d Fastpath mode ON, Cleaning up HTT Tx CE\n", + __func__, __LINE__); + cdf_spin_lock_bh(&sc->target_lock); + sw_index = src_ring->sw_index; + write_index = src_ring->sw_index; + cdf_spin_unlock_bh(&sc->target_lock); + + /* At this point Tx CE should be clean */ + cdf_assert_always(sw_index == write_index); + } +} +#else +void ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl) +{ +} +#endif /* WLAN_FEATURE_FASTPATH */ + +void ce_fini(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + unsigned int CE_id = CE_state->id; + struct ol_softc *scn = CE_state->scn; + + CE_state->state = CE_UNUSED; + scn->ce_id_to_state[CE_id] = NULL; + if (CE_state->src_ring) { + /* Cleanup the HTT Tx ring */ + ce_h2t_tx_ce_cleanup(copyeng); + + if (CE_state->src_ring->shadow_base_unaligned) + cdf_mem_free(CE_state->src_ring->shadow_base_unaligned); + if (CE_state->src_ring->base_addr_owner_space_unaligned) + cdf_os_mem_free_consistent(scn->cdf_dev, + (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, 0); + cdf_mem_free(CE_state->src_ring); + } + if (CE_state->dest_ring) { + if (CE_state->dest_ring->base_addr_owner_space_unaligned) + cdf_os_mem_free_consistent(scn->cdf_dev, + (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, 0); + cdf_mem_free(CE_state->dest_ring); + + /* epping */ + if (CE_state->timer_inited) { + CE_state->timer_inited = false; + cdf_softirq_timer_free(&CE_state->poll_timer); + } + } + cdf_mem_free(CE_state); +} + +void hif_detach_htc(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + cdf_mem_zero(&hif_state->msg_callbacks_pending, + sizeof(hif_state->msg_callbacks_pending)); + cdf_mem_zero(&hif_state->msg_callbacks_current, + sizeof(hif_state->msg_callbacks_current)); +} + +/* Send the first nbytes bytes of the buffer */ +CDF_STATUS +hif_send_head(struct ol_softc *scn, + uint8_t pipe, unsigned int transfer_id, unsigned int nbytes, + cdf_nbuf_t nbuf, unsigned int data_attr) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + 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, i = 0; + unsigned int mux_id = 0; + + CDF_ASSERT(nbytes <= cdf_nbuf_len(nbuf)); + + transfer_id = + (mux_id & MUX_ID_MASK) | + (transfer_id & TRANSACTION_ID_MASK); + data_attr &= DESC_DATA_FLAG_MASK; + /* + * 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 { + uint32_t frag_paddr; + int frag_bytes; + + frag_paddr = cdf_nbuf_get_frag_paddr_lo(nbuf, nfrags); + frag_bytes = cdf_nbuf_get_frag_len(nbuf, nfrags); + /* + * Clear the packet offset for all but the first CE desc. + */ + if (i++ > 0) + data_attr &= ~CDF_CE_TX_PKT_OFFSET_BIT_M; + + status = ce_sendlist_buf_add(&sendlist, frag_paddr, + frag_bytes > + bytes ? bytes : frag_bytes, + cdf_nbuf_get_frag_is_wordstream + (nbuf, + nfrags) ? 0 : + CE_SEND_FLAG_SWAP_DISABLE, + data_attr); + if (status != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: error, frag_num %d larger than limit", + __func__, nfrags); + return status; + } + bytes -= frag_bytes; + nfrags++; + } while (bytes > 0); + + /* Make sure we have resources to handle this request */ + cdf_spin_lock_bh(&pipe_info->completion_freeq_lock); + if (pipe_info->num_sends_allowed < nfrags) { + cdf_spin_unlock_bh(&pipe_info->completion_freeq_lock); + ce_pkt_error_count_incr(hif_state, HIF_PIPE_NO_RESOURCE); + return CDF_STATUS_E_RESOURCES; + } + pipe_info->num_sends_allowed -= nfrags; + cdf_spin_unlock_bh(&pipe_info->completion_freeq_lock); + + if (cdf_unlikely(ce_hdl == NULL)) { + HIF_ERROR("%s: error CE handle is null", __func__); + return A_ERROR; + } + + NBUF_UPDATE_TX_PKT_COUNT(nbuf, NBUF_TX_PKT_HIF); + DPTRACE(cdf_dp_trace(nbuf, CDF_DP_TRACE_HIF_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(nbuf)), + sizeof(cdf_nbuf_data(nbuf)))); + status = ce_sendlist_send(ce_hdl, nbuf, &sendlist, transfer_id); + CDF_ASSERT(status == CDF_STATUS_SUCCESS); + + return status; +} + +void hif_send_complete_check(struct ol_softc *scn, uint8_t pipe, int force) +{ + 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 = hif_get_free_queue_number(scn, 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(scn, pipe); +#else + ce_per_engine_service(scn, pipe); +#endif +} + +uint16_t hif_get_free_queue_number(struct ol_softc *scn, uint8_t pipe) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + struct HIF_CE_pipe_info *pipe_info = &(hif_state->pipe_info[pipe]); + uint16_t rv; + + cdf_spin_lock_bh(&pipe_info->completion_freeq_lock); + rv = pipe_info->num_sends_allowed; + cdf_spin_unlock_bh(&pipe_info->completion_freeq_lock); + 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, cdf_dma_addr_t CE_data, + unsigned int nbytes, unsigned int transfer_id, + unsigned int sw_index, unsigned int hw_index, + unsigned int toeplitz_hash_result) +{ + 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; + 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) { + cdf_spin_lock(&pipe_info->completion_freeq_lock); + pipe_info->num_sends_allowed++; + cdf_spin_unlock(&pipe_info->completion_freeq_lock); + continue; + } + + cdf_spin_lock(&pipe_info->completion_freeq_lock); + compl_state = pipe_info->completion_freeq_head; + if (!compl_state) { + cdf_spin_unlock(&pipe_info->completion_freeq_lock); + HIF_ERROR("%s: ce_id:%d num_allowed:%d pipe_info:%p", + __func__, pipe_info->pipe_num, + pipe_info->num_sends_allowed, + pipe_info); + ASSERT(0); + break; + } + pipe_info->completion_freeq_head = compl_state->next; + cdf_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; + compl_state->toeplitz_hash_result = toeplitz_hash_result; + + /* 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, + &toeplitz_hash_result) == CDF_STATUS_SUCCESS); + + 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; + } + + cdf_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; + cdf_spin_unlock(&hif_state->completion_pendingq_lock); + } else { + hif_state->completion_pendingq_head = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + cdf_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, cdf_dma_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 ol_softc *scn = hif_state->scn; + struct HIF_CE_completion_state *compl_state; + struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail; + + compl_queue_head = compl_queue_tail = NULL; + do { + cdf_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; + cdf_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; + + cdf_nbuf_unmap_single(scn->cdf_dev, + (cdf_nbuf_t) transfer_context, + CDF_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 */ + scn->receive_count++; + if (cdf_unlikely(hif_max_num_receives_reached( + scn->receive_count))) { + scn->force_break = 1; + break; + } + } while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context, + &CE_data, &nbytes, &transfer_id, + &flags) == CDF_STATUS_SUCCESS); + + cdf_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; + cdf_spin_unlock(&hif_state->completion_pendingq_lock); + } else { + hif_state->completion_pendingq_head = compl_queue_head; + hif_state->completion_pendingq_tail = compl_queue_tail; + cdf_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 +hif_post_init(struct ol_softc *scn, void *unused, + struct hif_msg_callbacks *callbacks) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + spin_lock_init(&pcie_access_log_lock); +#endif + /* Save callbacks for later installation */ + cdf_mem_copy(&hif_state->msg_callbacks_pending, callbacks, + sizeof(hif_state->msg_callbacks_pending)); + +} + +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; + cdf_mem_free(tmp_list); + } +} + +static int hif_alloc_complete_state_list( + struct HIF_CE_pipe_info *pipe_info, + int completions_needed) +{ + 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 *) + cdf_mem_malloc(len); + if (!tmp_list) { + HIF_ERROR("%s: compl_state has no mem", __func__); + hif_pci_free_complete_state(pipe_info); + return -1; + } + cdf_mem_zero(tmp_list, len); + 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; + } + } + cdf_spinlock_init(&pipe_info->completion_freeq_lock); + return 0; +} +int hif_completion_thread_startup(struct HIF_CE_state *hif_state) +{ + struct CE_handle *ce_diag = hif_state->ce_diag; + int pipe_num; + struct ol_softc *scn = hif_state->scn; + + /* daemonize("hif_compl_thread"); */ + + cdf_spinlock_init(&hif_state->completion_pendingq_lock); + hif_state->completion_pendingq_head = + hif_state->completion_pendingq_tail = NULL; + + if (scn->ce_count == 0) { + HIF_ERROR("%s: Invalid ce_count\n", __func__); + return -EINVAL; + } + A_TARGET_ACCESS_LIKELY(scn); + for (pipe_num = 0; pipe_num < scn->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 */ + HIF_INFO_MED("%s: pipe_num:%d pipe_info:0x%p", + __func__, 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) { + int ret; + + ret = hif_alloc_complete_state_list(pipe_info, + completions_needed); + if (ret != 0) { + HIF_ERROR("%s: ce_id = %d, no mem", + __func__, pipe_info->pipe_num); + return ret; + } + } + } + A_TARGET_ACCESS_UNLIKELY(scn); + 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 ol_softc *scn = hif_state->scn; + 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) { + cdf_nbuf_t netbuf; + + netbuf = (cdf_nbuf_t) compl_state->transfer_context; + cdf_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 < scn->ce_count; pipe_num++) { + pipe_info = &hif_state->pipe_info[pipe_num]; + hif_pci_free_complete_state(pipe_info); + cdf_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) +{ + struct hif_msg_callbacks *msg_callbacks = + &hif_state->msg_callbacks_current; + struct HIF_CE_completion_state *compl_state; + + /* 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 (!cdf_atomic_dec_and_test(&hif_state->hif_thread_idle)) { + /* We were not the lucky one */ + cdf_atomic_inc(&hif_state->hif_thread_idle); + return 0; + } + + 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, + CDF_STATUS_E_FAILURE); + } + + if (hif_state->scn->target_status == OL_TRGET_STATUS_RESET) + return 0; + + for (;; ) { + struct HIF_CE_pipe_info *pipe_info; + int send_done = 0; + + cdf_spin_lock(&hif_state->completion_pendingq_lock); + + if (!hif_state->completion_pendingq_head) { + /* We are atomically sure that + * there is no pending work */ + cdf_atomic_inc(&hif_state->hif_thread_idle); + cdf_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; + cdf_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, + compl_state->toeplitz_hash_result); + send_done = 1; + } else { + /* compl_state->send_or_recv == HIF_CE_COMPLETE_RECV */ + cdf_nbuf_t netbuf; + unsigned int nbytes; + + atomic_inc(&pipe_info->recv_bufs_needed); + hif_post_recv_buffers(hif_state->scn); + + netbuf = (cdf_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 + */ + HIF_DBG("%s: netbuf=%p, nbytes=%d", + __func__, netbuf, nbytes); + if (nbytes <= pipe_info->buf_sz) { + cdf_nbuf_set_pktlen(netbuf, nbytes); + msg_callbacks-> + rxCompletionHandler(msg_callbacks->Context, + netbuf, + pipe_info->pipe_num); + } else { + HIF_ERROR( + "%s: Invalid Rx msg buf:%p nbytes:%d", + __func__, netbuf, nbytes); + cdf_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; + cdf_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; + cdf_spin_unlock(&pipe_info->completion_freeq_lock); + } + + 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(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + cdf_mem_copy(&hif_state->msg_callbacks_current, + &hif_state->msg_callbacks_pending, + sizeof(hif_state->msg_callbacks_pending)); +} + +void hif_claim_device(struct ol_softc *scn, void *claimedContext) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + hif_state->claimedContext = claimedContext; +} + +void hif_release_device(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + hif_state->claimedContext = NULL; +} + +void +hif_get_default_pipe(struct ol_softc *scn, uint8_t *ULPipe, uint8_t *DLPipe) +{ + int ul_is_polled, dl_is_polled; + + (void)hif_map_service_to_pipe(scn, HTC_CTRL_RSVD_SVC, + ULPipe, DLPipe, &ul_is_polled, &dl_is_polled); +} + +/* TBDXXX - temporary mapping while we have too few CE's */ +int +hif_map_service_to_pipe(struct ol_softc *scn, uint16_t ServiceId, + uint8_t *ULPipe, uint8_t *DLPipe, int *ul_is_polled, + int *dl_is_polled) +{ + int status = CDF_STATUS_SUCCESS; + + *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: + *ULPipe = 0; + *DLPipe = 2; + break; + + 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 = 2; + 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(cds_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; + + case WDI_IPA_TX_SVC: + *ULPipe = 5; + break; + + /* pipe 5 unused */ + /* pipe 6 reserved */ + /* pipe 7 reserved */ + + default: + status = CDF_STATUS_E_INVAL; + break; + } + *ul_is_polled = + (host_ce_config[*ULPipe].flags & CE_ATTR_DISABLE_INTR) != 0; + + return status; +} + +/** + * hif_dump_pipe_debug_count() - Log error count + * @scn: ol_softc pointer. + * + * Output the pipe error counts of each pipe to log file + * + * Return: N/A + */ +void hif_dump_pipe_debug_count(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state; + int pipe_num; + + if (scn == NULL) { + HIF_ERROR("%s scn is NULL", __func__); + return; + } + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + if (hif_state == NULL) { + HIF_ERROR("%s hif_state is NULL", __func__); + return; + } + for (pipe_num = 0; pipe_num < scn->ce_count; pipe_num++) { + struct HIF_CE_pipe_info *pipe_info; + + pipe_info = &hif_state->pipe_info[pipe_num]; + + if (pipe_info->nbuf_alloc_err_count > 0 || + pipe_info->nbuf_dma_err_count > 0 || + pipe_info->nbuf_ce_enqueue_err_count) + HIF_ERROR( + "%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; + cdf_size_t buf_sz; + struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; + struct ol_softc *scn = hif_state->scn; + CDF_STATUS 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; + + cdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + while (atomic_read(&pipe_info->recv_bufs_needed) > 0) { + cdf_dma_addr_t CE_data; /* CE space buffer address */ + cdf_nbuf_t nbuf; + int status; + + atomic_dec(&pipe_info->recv_bufs_needed); + cdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + + nbuf = cdf_nbuf_alloc(scn->cdf_dev, buf_sz, 0, 4, false); + if (!nbuf) { + cdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_alloc_err_count++; + cdf_spin_unlock_bh( + &pipe_info->recv_bufs_needed_lock); + HIF_ERROR( + "%s buf alloc error [%d] needed %d, nbuf_alloc_err_count = %u", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed), + pipe_info->nbuf_alloc_err_count); + atomic_inc(&pipe_info->recv_bufs_needed); + return 1; + } + + /* + * cdf_nbuf_peek_header(nbuf, &data, &unused); + * CE_data = dma_map_single(dev, data, buf_sz, ); + * DMA_FROM_DEVICE); + */ + ret = + cdf_nbuf_map_single(scn->cdf_dev, nbuf, + CDF_DMA_FROM_DEVICE); + + if (unlikely(ret != CDF_STATUS_SUCCESS)) { + cdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_dma_err_count++; + cdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + HIF_ERROR( + "%s buf alloc error [%d] needed %d, nbuf_dma_err_count = %u", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed), + pipe_info->nbuf_dma_err_count); + cdf_nbuf_free(nbuf); + atomic_inc(&pipe_info->recv_bufs_needed); + return 1; + } + + CE_data = cdf_nbuf_get_frag_paddr_lo(nbuf, 0); + + cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, CE_data, + buf_sz, DMA_FROM_DEVICE); + status = ce_recv_buf_enqueue(ce_hdl, (void *)nbuf, CE_data); + CDF_ASSERT(status == CDF_STATUS_SUCCESS); + if (status != EOK) { + cdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + pipe_info->nbuf_ce_enqueue_err_count++; + cdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + HIF_ERROR( + "%s buf alloc error [%d] needed %d, nbuf_alloc_err_count = %u", + __func__, pipe_info->pipe_num, + atomic_read(&pipe_info->recv_bufs_needed), + pipe_info->nbuf_ce_enqueue_err_count); + atomic_inc(&pipe_info->recv_bufs_needed); + cdf_nbuf_free(nbuf); + return 1; + } + + cdf_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; + + cdf_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(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + int pipe_num, rv = 0; + + A_TARGET_ACCESS_LIKELY(scn); + for (pipe_num = 0; pipe_num < scn->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(scn); + + return rv; +} + +CDF_STATUS hif_start(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + + if (hif_completion_thread_startup(hif_state)) + return CDF_STATUS_E_FAILURE; + + hif_msg_callbacks_install(scn); + + /* Post buffers once to start things off. */ + (void)hif_post_recv_buffers(scn); + + hif_state->started = true; + + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_FASTPATH +/** + * hif_enable_fastpath() Update that we have enabled fastpath mode + * @hif_device: HIF context + * + * For use in data path + * + * Retrun: void + */ +void +hif_enable_fastpath(struct ol_softc *hif_device) +{ + HIF_INFO("Enabling fastpath mode\n"); + hif_device->fastpath_mode_on = 1; +} +#endif /* WLAN_FEATURE_FASTPATH */ + +void hif_recv_buffer_cleanup_on_pipe(struct HIF_CE_pipe_info *pipe_info) +{ + struct ol_softc *scn; + struct CE_handle *ce_hdl; + uint32_t buf_sz; + struct HIF_CE_state *hif_state; + cdf_nbuf_t netbuf; + cdf_dma_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; + } + + scn = hif_state->scn; + ce_hdl = pipe_info->ce_hdl; + + if (scn->cdf_dev == NULL) { + return; + } + while (ce_revoke_recv_next + (ce_hdl, &per_CE_context, (void **)&netbuf, + &CE_data) == CDF_STATUS_SUCCESS) { + cdf_nbuf_unmap_single(scn->cdf_dev, netbuf, + CDF_DMA_FROM_DEVICE); + cdf_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; + cdf_nbuf_t netbuf; + void *per_CE_context; + cdf_dma_addr_t CE_data; + unsigned int nbytes; + unsigned int id; + uint32_t buf_sz; + uint32_t toeplitz_hash_result; + + 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, &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { + 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->scn->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, toeplitz_hash_result); + } + } +} + +/* + * 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) +{ + int pipe_num; + + for (pipe_num = 0; pipe_num < hif_state->scn->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 hif_flush_surprise_remove(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + hif_buffer_cleanup(hif_state); +} + +void hif_stop(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + int pipe_num; + + scn->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 (scn->athdiag_procfs_inited) { + athdiag_procfs_remove(); + scn->athdiag_procfs_inited = false; + } + + hif_buffer_cleanup(hif_state); + + for (pipe_num = 0; pipe_num < scn->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; + } + } + + if (hif_state->sleep_timer_init) { + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + cdf_softirq_timer_free(&hif_state->sleep_timer); + hif_state->sleep_timer_init = false; + } + + hif_state->started = false; +} + +#define ADRASTEA_SRC_WR_INDEX_OFFSET 0x3C +#define ADRASTEA_DST_WR_INDEX_OFFSET 0x40 + + +static struct shadow_reg_cfg target_shadow_reg_cfg_map[] = { + { 0, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 3, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 4, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 5, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 7, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 1, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 2, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 7, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 8, ADRASTEA_DST_WR_INDEX_OFFSET}, +}; + + + +/* CE_PCI TABLE */ +/* + * NOTE: the table below is out of date, though still a useful reference. + * Refer to target_service_to_ce_map and hif_map_service_to_pipe 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 + * hif_map_service_to_pipe - 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 */ + 2, + }, + { + 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 */ + 2, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 4, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + WDI_IPA_TX_SVC, + PIPEDIR_OUT, /* in = DL = target -> host */ + 5, + }, + /* (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 shadow_reg_cfg *target_shadow_reg_cfg = target_shadow_reg_cfg_map; +static int shadow_cfg_sz = sizeof(target_shadow_reg_cfg_map); + +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, 2,}, /* in = DL = target -> host */ + {HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0,}, /* out = UL = host -> target */ + {HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 2,}, /* 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 */ +}; + +#ifdef HIF_PCI +/* + * 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 ol_softc *scn) +{ + CDF_STATUS rv; + uint32_t core_ctrl; + + rv = hif_diag_read_access(scn, + SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS, + &core_ctrl); + CDF_ASSERT(rv == CDF_STATUS_SUCCESS); + /* A_INUM_FIRMWARE interrupt to Target CPU */ + core_ctrl |= CORE_CTRL_CPU_INTR_MASK; + + rv = hif_diag_write_access(scn, + SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS, + core_ctrl); + CDF_ASSERT(rv == CDF_STATUS_SUCCESS); +} +#endif + +static void hif_sleep_entry(void *arg) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)arg; + struct ol_softc *scn = hif_state->scn; + uint32_t idle_ms; + if (scn->recovery) + return; + + cdf_spin_lock_irqsave(&hif_state->keep_awake_lock); + if (hif_state->verified_awake == false) { + idle_ms = cdf_system_ticks_to_msecs(cdf_system_ticks() + - hif_state->sleep_ticks); + if (idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { + if (!cdf_atomic_read(&scn->link_suspended)) { + soc_wake_reset(scn); + hif_state->fake_sleep = false; + } + } else { + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + cdf_softirq_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + } else { + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + cdf_softirq_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + cdf_spin_unlock_irqrestore(&hif_state->keep_awake_lock); +} +#define HIF_HIA_MAX_POLL_LOOP 1000000 +#define HIF_HIA_POLLING_DELAY_MS 10 + +#ifndef HIF_PCI +int hif_set_hia(struct ol_softc *scn) +{ + return 0; +} +#else +int hif_set_hia(struct ol_softc *scn) +{ + CDF_STATUS rv; + uint32_t interconnect_targ_addr = 0; + uint32_t pcie_state_targ_addr = 0; + uint32_t pipe_cfg_targ_addr = 0; + uint32_t svc_to_pipe_map = 0; + uint32_t pcie_config_flags = 0; + uint32_t flag2_value = 0; + uint32_t flag2_targ_addr = 0; +#ifdef QCA_WIFI_3_0 + uint32_t host_interest_area = 0; + uint8_t i; +#else + uint32_t ealloc_value = 0; + uint32_t ealloc_targ_addr = 0; + uint8_t banks_switched = 1; + uint32_t chip_id; +#endif + uint32_t pipe_cfg_addr; + + HIF_TRACE("%s: E", __func__); + + if (IHELIUM_BU || ADRASTEA_BU) + return CDF_STATUS_SUCCESS; + +#ifdef QCA_WIFI_3_0 + i = 0; + while (i < HIF_HIA_MAX_POLL_LOOP) { + host_interest_area = hif_read32_mb(scn->mem + + A_SOC_CORE_SCRATCH_0_ADDRESS); + if ((host_interest_area & 0x01) == 0) { + cdf_mdelay(HIF_HIA_POLLING_DELAY_MS); + host_interest_area = 0; + i++; + if (i > HIF_HIA_MAX_POLL_LOOP && (i % 1000 == 0)) { + HIF_ERROR("%s: poll timeout(%d)", __func__, i); + } + } else { + host_interest_area &= (~0x01); + hif_write32_mb(scn->mem + 0x113014, 0); + break; + } + } + + if (i >= HIF_HIA_MAX_POLL_LOOP) { + HIF_ERROR("%s: hia polling timeout", __func__); + return -EIO; + } + + if (host_interest_area == 0) { + HIF_ERROR("%s: host_interest_area = 0", __func__); + return -EIO; + } + + interconnect_targ_addr = host_interest_area + + offsetof(struct host_interest_area_t, + hi_interconnect_state); + + flag2_targ_addr = host_interest_area + + offsetof(struct host_interest_area_t, hi_option_flag2); + +#else + interconnect_targ_addr = hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_interconnect_state)); + ealloc_targ_addr = hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_early_alloc)); + flag2_targ_addr = hif_hia_item_address(scn->target_type, + offsetof(struct host_interest_s, hi_option_flag2)); +#endif + /* Supply Target-side CE configuration */ + rv = hif_diag_read_access(scn, interconnect_targ_addr, + &pcie_state_targ_addr); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: interconnect_targ_addr = 0x%0x, ret = %d", + __func__, interconnect_targ_addr, rv); + goto done; + } + if (pcie_state_targ_addr == 0) { + rv = CDF_STATUS_E_FAILURE; + HIF_ERROR("%s: pcie state addr is 0", __func__); + goto done; + } + pipe_cfg_addr = pcie_state_targ_addr + + offsetof(struct pcie_state_s, + pipe_cfg_addr); + rv = hif_diag_read_access(scn, + pipe_cfg_addr, + &pipe_cfg_targ_addr); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: pipe_cfg_addr = 0x%0x, ret = %d", + __func__, pipe_cfg_addr, rv); + goto done; + } + if (pipe_cfg_targ_addr == 0) { + rv = CDF_STATUS_E_FAILURE; + HIF_ERROR("%s: pipe cfg addr is 0", __func__); + goto done; + } + + rv = hif_diag_write_mem(scn, pipe_cfg_targ_addr, + (uint8_t *) target_ce_config, + target_ce_config_sz); + + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: write pipe cfg (%d)", __func__, rv); + goto done; + } + + rv = hif_diag_read_access(scn, + pcie_state_targ_addr + + offsetof(struct pcie_state_s, + svc_to_pipe_map), + &svc_to_pipe_map); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: get svc/pipe map (%d)", __func__, rv); + goto done; + } + if (svc_to_pipe_map == 0) { + rv = CDF_STATUS_E_FAILURE; + HIF_ERROR("%s: svc_to_pipe map is 0", __func__); + goto done; + } + + rv = hif_diag_write_mem(scn, + svc_to_pipe_map, + (uint8_t *) target_service_to_ce_map, + target_service_to_ce_map_sz); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: write svc/pipe map (%d)", __func__, rv); + goto done; + } + + rv = hif_diag_read_access(scn, + pcie_state_targ_addr + + offsetof(struct pcie_state_s, + config_flags), + &pcie_config_flags); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: get pcie config_flags (%d)", __func__, 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 = hif_diag_write_mem(scn, + pcie_state_targ_addr + + offsetof(struct pcie_state_s, + config_flags), + (uint8_t *) &pcie_config_flags, + sizeof(pcie_config_flags)); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: write pcie config_flags (%d)", __func__, rv); + goto done; + } + +#ifndef QCA_WIFI_3_0 + /* configure early allocation */ + ealloc_targ_addr = hif_hia_item_address(scn->target_type, + offsetof( + struct host_interest_s, + hi_early_alloc)); + + rv = hif_diag_read_access(scn, ealloc_targ_addr, + &ealloc_value); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: get early alloc val (%d)", __func__, 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); + + rv = hif_diag_read_access(scn, + CHIP_ID_ADDRESS | + RTC_SOC_BASE_ADDRESS, &chip_id); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: get chip id val (%d)", __func__, 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 = hif_diag_write_access(scn, + ealloc_targ_addr, + ealloc_value); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: set early alloc val (%d)", __func__, rv); + goto done; + } +#endif + + /* Tell Target to proceed with initialization */ + flag2_targ_addr = hif_hia_item_address(scn->target_type, + offsetof( + struct host_interest_s, + hi_option_flag2)); + + rv = hif_diag_read_access(scn, flag2_targ_addr, + &flag2_value); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: get option val (%d)", __func__, rv); + goto done; + } + + flag2_value |= HI_OPTION_EARLY_CFG_DONE; + rv = hif_diag_write_access(scn, flag2_targ_addr, + flag2_value); + if (rv != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: set option val (%d)", __func__, rv); + goto done; + } + + hif_wake_target_cpu(scn); + +done: + + return rv; +} +#endif + +/** + * hif_wlan_enable(): call the platform driver to enable wlan + * + * This function passes the con_mode and CE configuration to + * platform driver to enable wlan. + * + * Return: void + */ +static int hif_wlan_enable(void) +{ + struct icnss_wlan_enable_cfg cfg; + enum icnss_driver_mode mode; + uint32_t con_mode = cds_get_conparam(); + + cfg.num_ce_tgt_cfg = target_ce_config_sz / + sizeof(struct CE_pipe_config); + cfg.ce_tgt_cfg = (struct ce_tgt_pipe_cfg *)target_ce_config; + cfg.num_ce_svc_pipe_cfg = target_service_to_ce_map_sz / + sizeof(struct service_to_pipe); + cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *)target_service_to_ce_map; + cfg.num_shadow_reg_cfg = shadow_cfg_sz / sizeof(struct shadow_reg_cfg); + cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *) target_shadow_reg_cfg; + + switch (con_mode) { + case CDF_FTM_MODE: + mode = ICNSS_FTM; + break; + case CDF_EPPING_MODE: + mode = ICNSS_EPPING; + break; + default: + mode = ICNSS_MISSION; + break; + } + return icnss_wlan_enable(&cfg, mode, QWLAN_VERSIONSTR); +} + +#if ((!defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA)) || defined(CONFIG_ICNSS)) +static inline void cnss_pcie_notify_q6(void) +{ + return; +} +#endif + +/* + * 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_config_ce(hif_handle_t hif_hdl) +{ + struct HIF_CE_state *hif_state; + struct HIF_CE_pipe_info *pipe_info; + int pipe_num; +#ifdef ADRASTEA_SHADOW_REGISTERS + int i; +#endif + CDF_STATUS rv = CDF_STATUS_SUCCESS; + int ret; + struct ol_softc *scn = hif_hdl; + struct icnss_soc_info soc_info; + + /* if epping is enabled we need to use the epping configuration. */ + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + if (WLAN_IS_EPPING_IRQ(cds_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); + } + + ret = hif_wlan_enable(); + + if (ret) { + HIF_ERROR("%s: hif_wlan_enable error = %d", __func__, ret); + return CDF_STATUS_NOT_INITIALIZED; + } + if (IHELIUM_BU) { + cnss_pcie_notify_q6(); + HIF_TRACE("%s: cnss_pcie_notify_q6 done, notice_send= %d", + __func__, scn->notice_send); + } + + scn->notice_send = true; + + cdf_mem_zero(&soc_info, sizeof(soc_info)); + ret = icnss_get_soc_info(&soc_info); + if (ret < 0) { + HIF_ERROR("%s: icnss_get_soc_info error = %d", __func__, ret); + return CDF_STATUS_NOT_INITIALIZED; + } + + hif_state = (struct HIF_CE_state *)cdf_mem_malloc(sizeof(*hif_state)); + if (!hif_state) { + return -ENOMEM; + } + cdf_mem_zero(hif_state, sizeof(*hif_state)); + + hif_state->scn = scn; + scn->hif_hdl = hif_state; + scn->mem = soc_info.v_addr; + scn->mem_pa = soc_info.p_addr; + scn->soc_version = soc_info.version; + + cdf_spinlock_init(&hif_state->keep_awake_lock); + + cdf_atomic_init(&hif_state->hif_thread_idle); + cdf_atomic_inc(&hif_state->hif_thread_idle); + + hif_state->keep_awake_count = 0; + + hif_state->fake_sleep = false; + hif_state->sleep_ticks = 0; + cdf_softirq_timer_init(NULL, &hif_state->sleep_timer, + hif_sleep_entry, (void *)hif_state, + CDF_TIMER_TYPE_WAKE_APPS); + hif_state->sleep_timer_init = true; + hif_state->fw_indicator_address = FW_INDICATOR_ADDRESS; +#ifdef HIF_PCI +#if CONFIG_ATH_PCIE_MAX_PERF || CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD + /* Force AWAKE forever/till the driver is loaded */ + if (hif_target_sleep_state_adjust(scn, false, true) < 0) + return -EACCES; +#endif +#endif + + /* During CE initializtion */ + scn->ce_count = HOST_CE_COUNT; + A_TARGET_ACCESS_LIKELY(scn); + for (pipe_num = 0; pipe_num < scn->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(scn, pipe_num, attr); + CDF_ASSERT(pipe_info->ce_hdl != NULL); + if (pipe_info->ce_hdl == NULL) { + rv = CDF_STATUS_E_FAILURE; + A_TARGET_ACCESS_UNLIKELY(scn); + goto err; + } + + if (pipe_num == DIAG_CE_ID) { + /* Reserve the ultimate CE for + * Diagnostic Window support */ + hif_state->ce_diag = + hif_state->pipe_info[scn->ce_count - 1].ce_hdl; + continue; + } + + pipe_info->buf_sz = (cdf_size_t) (attr->src_sz_max); + cdf_spinlock_init(&pipe_info->recv_bufs_needed_lock); + if (attr->dest_nentries > 0) { + atomic_set(&pipe_info->recv_bufs_needed, + init_buffer_count(attr->dest_nentries - 1)); + } else { + atomic_set(&pipe_info->recv_bufs_needed, 0); + } + ce_tasklet_init(hif_state, (1 << pipe_num)); + ce_register_irq(hif_state, (1 << pipe_num)); + scn->request_irq_done = true; + } + + if (athdiag_procfs_init(scn) != 0) { + A_TARGET_ACCESS_UNLIKELY(scn); + goto err; + } + scn->athdiag_procfs_inited = true; + + /* + * 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]; +#ifdef HIF_PCI + 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 +#endif + HIF_INFO_MED("%s: ce_init done", __func__); + + rv = hif_set_hia(scn); + + HIF_INFO_MED("%s: hif_set_hia done", __func__); + + A_TARGET_ACCESS_UNLIKELY(scn); + + if (rv != CDF_STATUS_SUCCESS) + goto err; + else + init_tasklet_workers(); + + HIF_TRACE("%s: X, ret = %d\n", __func__, rv); + +#ifdef ADRASTEA_SHADOW_REGISTERS + HIF_ERROR("Using Shadow Registers instead of CE Registers\n"); + for (i = 0; i < NUM_SHADOW_REGISTERS; i++) { + HIF_ERROR("%s Shadow Register%d is mapped to address %x\n", + __func__, i, + (A_TARGET_READ(scn, (SHADOW_ADDRESS(i))) << 2)); + } +#endif + + + return rv != CDF_STATUS_SUCCESS; + +err: + /* Failure, so clean up */ + for (pipe_num = 0; pipe_num < scn->ce_count; pipe_num++) { + pipe_info = &hif_state->pipe_info[pipe_num]; + if (pipe_info->ce_hdl) { + ce_unregister_irq(hif_state, (1 << pipe_num)); + scn->request_irq_done = false; + ce_fini(pipe_info->ce_hdl); + pipe_info->ce_hdl = NULL; + pipe_info->buf_sz = 0; + } + } + if (hif_state->sleep_timer_init) { + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + cdf_softirq_timer_free(&hif_state->sleep_timer); + hif_state->sleep_timer_init = false; + } + if (scn->hif_hdl) { + scn->hif_hdl = NULL; + cdf_mem_free(hif_state); + } + athdiag_procfs_remove(); + scn->athdiag_procfs_inited = false; + HIF_TRACE("%s: X, ret = %d\n", __func__, rv); + return CDF_STATUS_SUCCESS != CDF_STATUS_E_FAILURE; +} + + + + + + +#ifdef IPA_OFFLOAD +void hif_ipa_get_ce_resource(struct ol_softc *scn, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + 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_ipa_get_resource(ce_hdl, ce_sr_base_paddr, ce_sr_ring_size, + ce_reg_paddr); + return; +} +#endif /* IPA_OFFLOAD */ + + +#ifdef ADRASTEA_SHADOW_REGISTERS + +/* + Current shadow register config + + ----------------------------------------------------------- + Shadow Register | CE | src/dst write index + ----------------------------------------------------------- + 0 | 0 | src + 1 No Config - Doesn't point to anything + 2 No Config - Doesn't point to anything + 3 | 3 | src + 4 | 4 | src + 5 | 5 | src + 6 No Config - Doesn't point to anything + 7 | 7 | src + 8 No Config - Doesn't point to anything + 9 No Config - Doesn't point to anything + 10 No Config - Doesn't point to anything + 11 No Config - Doesn't point to anything + ----------------------------------------------------------- + 12 No Config - Doesn't point to anything + 13 | 1 | dst + 14 | 2 | dst + 15 No Config - Doesn't point to anything + 16 No Config - Doesn't point to anything + 17 No Config - Doesn't point to anything + 18 No Config - Doesn't point to anything + 19 | 7 | dst + 20 | 8 | dst + 21 No Config - Doesn't point to anything + 22 No Config - Doesn't point to anything + 23 No Config - Doesn't point to anything + ----------------------------------------------------------- + + + ToDo - Move shadow register config to following in the future + This helps free up a block of shadow registers towards the end. + Can be used for other purposes + + ----------------------------------------------------------- + Shadow Register | CE | src/dst write index + ----------------------------------------------------------- + 0 | 0 | src + 1 | 3 | src + 2 | 4 | src + 3 | 5 | src + 4 | 7 | src + ----------------------------------------------------------- + 5 | 1 | dst + 6 | 2 | dst + 7 | 7 | dst + 8 | 8 | dst + ----------------------------------------------------------- + 9 No Config - Doesn't point to anything + 12 No Config - Doesn't point to anything + 13 No Config - Doesn't point to anything + 14 No Config - Doesn't point to anything + 15 No Config - Doesn't point to anything + 16 No Config - Doesn't point to anything + 17 No Config - Doesn't point to anything + 18 No Config - Doesn't point to anything + 19 No Config - Doesn't point to anything + 20 No Config - Doesn't point to anything + 21 No Config - Doesn't point to anything + 22 No Config - Doesn't point to anything + 23 No Config - Doesn't point to anything + ----------------------------------------------------------- +*/ + +u32 shadow_sr_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) +{ + u32 addr = 0; + + switch (COPY_ENGINE_ID(ctrl_addr)) { + case 0: + addr = SHADOW_VALUE0; + break; + case 3: + addr = SHADOW_VALUE3; + break; + case 4: + addr = SHADOW_VALUE4; + break; + case 5: + addr = SHADOW_VALUE5; + break; + case 7: + addr = SHADOW_VALUE7; + break; + default: + printk("invalid CE ctrl_addr\n"); + CDF_ASSERT(0); + + } + return addr; + +} + +u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) +{ + u32 addr = 0; + + switch (COPY_ENGINE_ID(ctrl_addr)) { + case 1: + addr = SHADOW_VALUE13; + break; + case 2: + addr = SHADOW_VALUE14; + break; + case 7: + addr = SHADOW_VALUE19; + break; + case 8: + addr = SHADOW_VALUE20; + break; + default: + printk("invalid CE ctrl_addr\n"); + CDF_ASSERT(0); + } + + return addr; + +} +#endif + +void ce_lro_flush_cb_register(struct ol_softc *scn, + void (handler)(void *), void *data) +{ + struct CE_state *ce_state = scn->ce_id_to_state[CE_HTT_T2H_MSG]; + ce_state->lro_flush_cb = handler; + ce_state->lro_data = data; +} diff --git a/core/hif/src/ce/ce_main.h b/core/hif/src/ce/ce_main.h new file mode 100644 index 000000000000..570fd41fd799 --- /dev/null +++ b/core/hif/src/ce/ce_main.h @@ -0,0 +1,168 @@ +/* + * 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 __CE_H__ +#define __CE_H__ + +#include "cdf_atomic.h" +#include "cdf_lock.h" +#include "hif.h" + +#define CE_HTT_T2H_MSG 1 +#define CE_HTT_H2T_MSG 4 + +/** + * enum ce_id_type + * + * @ce_id_type: Copy engine ID + */ +enum ce_id_type { + CE_ID_0, + CE_ID_1, + CE_ID_2, + CE_ID_3, + CE_ID_4, + CE_ID_5, + CE_ID_6, + CE_ID_7, + CE_ID_8, + CE_ID_9, + CE_ID_10, + CE_ID_11, + CE_ID_MAX +}; +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; + cdf_dma_addr_t data; + unsigned int nbytes; + unsigned int transfer_id; + unsigned int flags; + uint32_t toeplitz_hash_result; +}; + +/* 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. */ + uint8_t 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; + cdf_size_t buf_sz; + cdf_spinlock_t recv_bufs_needed_lock; + + cdf_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 ce_tasklet_entry + * + * @intr_tq: intr_tq + * @ce_id: ce_id + * @inited: inited + * @hif_ce_state: hif_ce_state + * @from_irq: from_irq + */ +struct ce_tasklet_entry { + struct tasklet_struct intr_tq; + enum ce_id_type ce_id; + bool inited; + void *hif_ce_state; + bool from_irq; +}; + +struct HIF_CE_state { + struct ol_softc *scn; + bool started; + struct ce_tasklet_entry tasklets[CE_COUNT_MAX]; + cdf_spinlock_t keep_awake_lock; + unsigned int keep_awake_count; + bool verified_awake; + bool fake_sleep; + cdf_softirq_timer_t sleep_timer; + bool sleep_timer_init; + unsigned long sleep_ticks; + cdf_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; + cdf_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]; + /* to be activated after BMI_DONE */ + struct hif_msg_callbacks msg_callbacks_pending; + /* current msg callbacks in use */ + struct hif_msg_callbacks msg_callbacks_current; + + void *claimedContext; + + /* Target address used to signal a pending firmware event */ + uint32_t fw_indicator_address; + + /* Copy Engine used for Diagnostic Accesses */ + struct CE_handle *ce_diag; +}; +#endif /* __CE_H__ */ diff --git a/core/hif/src/ce/ce_reg.h b/core/hif/src/ce/ce_reg.h new file mode 100644 index 000000000000..cb7439421dbb --- /dev/null +++ b/core/hif/src/ce/ce_reg.h @@ -0,0 +1,478 @@ +/* + * 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 __CE_REG_H__ +#define __CE_REG_H__ + +#define DST_WR_INDEX_ADDRESS (scn->target_ce_def->d_DST_WR_INDEX_ADDRESS) +#define SRC_WATERMARK_ADDRESS (scn->target_ce_def->d_SRC_WATERMARK_ADDRESS) +#define SRC_WATERMARK_LOW_MASK (scn->target_ce_def->d_SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_HIGH_MASK (scn->target_ce_def->d_SRC_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_LOW_MASK (scn->target_ce_def->d_DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_HIGH_MASK (scn->target_ce_def->d_DST_WATERMARK_HIGH_MASK) +#define CURRENT_SRRI_ADDRESS (scn->target_ce_def->d_CURRENT_SRRI_ADDRESS) +#define CURRENT_DRRI_ADDRESS (scn->target_ce_def->d_CURRENT_DRRI_ADDRESS) + +#define SHADOW_VALUE0 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_0) +#define SHADOW_VALUE1 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_1) +#define SHADOW_VALUE2 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_2) +#define SHADOW_VALUE3 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_3) +#define SHADOW_VALUE4 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_4) +#define SHADOW_VALUE5 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_5) +#define SHADOW_VALUE6 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_6) +#define SHADOW_VALUE7 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_7) +#define SHADOW_VALUE8 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_8) +#define SHADOW_VALUE9 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_9) +#define SHADOW_VALUE10 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_10) +#define SHADOW_VALUE11 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_11) +#define SHADOW_VALUE12 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_12) +#define SHADOW_VALUE13 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_13) +#define SHADOW_VALUE14 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_14) +#define SHADOW_VALUE15 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_15) +#define SHADOW_VALUE16 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_16) +#define SHADOW_VALUE17 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_17) +#define SHADOW_VALUE18 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_18) +#define SHADOW_VALUE19 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_19) +#define SHADOW_VALUE20 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_20) +#define SHADOW_VALUE21 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_21) +#define SHADOW_VALUE22 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_22) +#define SHADOW_VALUE23 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_VALUE_23) +#define SHADOW_ADDRESS0 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_0) +#define SHADOW_ADDRESS1 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_1) +#define SHADOW_ADDRESS2 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_2) +#define SHADOW_ADDRESS3 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_3) +#define SHADOW_ADDRESS4 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_4) +#define SHADOW_ADDRESS5 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_5) +#define SHADOW_ADDRESS6 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_6) +#define SHADOW_ADDRESS7 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_7) +#define SHADOW_ADDRESS8 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_8) +#define SHADOW_ADDRESS9 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_9) +#define SHADOW_ADDRESS10 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_10) +#define SHADOW_ADDRESS11 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_11) +#define SHADOW_ADDRESS12 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_12) +#define SHADOW_ADDRESS13 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_13) +#define SHADOW_ADDRESS14 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_14) +#define SHADOW_ADDRESS15 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_15) +#define SHADOW_ADDRESS16 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_16) +#define SHADOW_ADDRESS17 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_17) +#define SHADOW_ADDRESS18 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_18) +#define SHADOW_ADDRESS19 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_19) +#define SHADOW_ADDRESS20 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_20) +#define SHADOW_ADDRESS21 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_21) +#define SHADOW_ADDRESS22 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_22) +#define SHADOW_ADDRESS23 (scn->host_shadow_regs->d_A_LOCAL_SHADOW_REG_ADDRESS_23) + +#define SHADOW_ADDRESS(i) (SHADOW_ADDRESS0 + i*(SHADOW_ADDRESS1-SHADOW_ADDRESS0)) + +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK \ + (scn->target_ce_def->d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK \ + (scn->target_ce_def->d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK) +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK \ + (scn->target_ce_def->d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK) +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK \ + (scn->target_ce_def->d_HOST_IS_DST_RING_LOW_WATERMARK_MASK) +#define MISC_IS_ADDRESS (scn->target_ce_def->d_MISC_IS_ADDRESS) +#define HOST_IS_COPY_COMPLETE_MASK \ + (scn->target_ce_def->d_HOST_IS_COPY_COMPLETE_MASK) +#define CE_WRAPPER_BASE_ADDRESS (scn->target_ce_def->d_CE_WRAPPER_BASE_ADDRESS) +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS \ + (scn->target_ce_def->d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS) +#define CE_WRAPPER_INDEX_BASE_LOW \ + (scn->target_ce_def->d_CE_WRAPPER_INDEX_BASE_LOW) +#define CE_WRAPPER_INDEX_BASE_HIGH \ + (scn->target_ce_def->d_CE_WRAPPER_INDEX_BASE_HIGH) +#define HOST_IE_COPY_COMPLETE_MASK \ + (scn->target_ce_def->d_HOST_IE_COPY_COMPLETE_MASK) +#define SR_BA_ADDRESS (scn->target_ce_def->d_SR_BA_ADDRESS) +#define SR_BA_ADDRESS_HIGH (scn->target_ce_def->d_SR_BA_ADDRESS_HIGH) +#define SR_SIZE_ADDRESS (scn->target_ce_def->d_SR_SIZE_ADDRESS) +#define CE_CTRL1_ADDRESS (scn->target_ce_def->d_CE_CTRL1_ADDRESS) +#define CE_CTRL1_DMAX_LENGTH_MASK \ + (scn->target_ce_def->d_CE_CTRL1_DMAX_LENGTH_MASK) +#define DR_BA_ADDRESS (scn->target_ce_def->d_DR_BA_ADDRESS) +#define DR_BA_ADDRESS_HIGH (scn->target_ce_def->d_DR_BA_ADDRESS_HIGH) +#define DR_SIZE_ADDRESS (scn->target_ce_def->d_DR_SIZE_ADDRESS) +#define CE_CMD_REGISTER (scn->target_ce_def->d_CE_CMD_REGISTER) +#define CE_MSI_ADDRESS (scn->target_ce_def->d_CE_MSI_ADDRESS) +#define CE_MSI_ADDRESS_HIGH (scn->target_ce_def->d_CE_MSI_ADDRESS_HIGH) +#define CE_MSI_DATA (scn->target_ce_def->d_CE_MSI_DATA) +#define CE_MSI_ENABLE_BIT (scn->target_ce_def->d_CE_MSI_ENABLE_BIT) +#define MISC_IE_ADDRESS (scn->target_ce_def->d_MISC_IE_ADDRESS) +#define MISC_IS_AXI_ERR_MASK (scn->target_ce_def->d_MISC_IS_AXI_ERR_MASK) +#define MISC_IS_DST_ADDR_ERR_MASK \ + (scn->target_ce_def->d_MISC_IS_DST_ADDR_ERR_MASK) +#define MISC_IS_SRC_LEN_ERR_MASK \ + (scn->target_ce_def->d_MISC_IS_SRC_LEN_ERR_MASK) +#define MISC_IS_DST_MAX_LEN_VIO_MASK \ + (scn->target_ce_def->d_MISC_IS_DST_MAX_LEN_VIO_MASK) +#define MISC_IS_DST_RING_OVERFLOW_MASK \ + (scn->target_ce_def->d_MISC_IS_DST_RING_OVERFLOW_MASK) +#define MISC_IS_SRC_RING_OVERFLOW_MASK \ + (scn->target_ce_def->d_MISC_IS_SRC_RING_OVERFLOW_MASK) +#define SRC_WATERMARK_LOW_LSB (scn->target_ce_def->d_SRC_WATERMARK_LOW_LSB) +#define SRC_WATERMARK_HIGH_LSB (scn->target_ce_def->d_SRC_WATERMARK_HIGH_LSB) +#define DST_WATERMARK_LOW_LSB (scn->target_ce_def->d_DST_WATERMARK_LOW_LSB) +#define DST_WATERMARK_HIGH_LSB (scn->target_ce_def->d_DST_WATERMARK_HIGH_LSB) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK \ + (scn->target_ce_def->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ + (scn->target_ce_def->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_CTRL1_DMAX_LENGTH_LSB (scn->target_ce_def->d_CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK \ + (scn->target_ce_def->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK \ + (scn->target_ce_def->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB \ + (scn->target_ce_def->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB \ + (scn->target_ce_def->d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) +#define WLAN_DEBUG_INPUT_SEL_OFFSET \ + (scn->targetdef->d_WLAN_DEBUG_INPUT_SEL_OFFSET) +#define WLAN_DEBUG_INPUT_SEL_SRC_MSB \ + (scn->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_LSB \ + (scn->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_LSB) +#define WLAN_DEBUG_INPUT_SEL_SRC_MASK \ + (scn->targetdef->d_WLAN_DEBUG_INPUT_SEL_SRC_MASK) +#define WLAN_DEBUG_CONTROL_OFFSET (scn->targetdef->d_WLAN_DEBUG_CONTROL_OFFSET) +#define WLAN_DEBUG_CONTROL_ENABLE_MSB \ + (scn->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MSB) +#define WLAN_DEBUG_CONTROL_ENABLE_LSB \ + (scn->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_LSB) +#define WLAN_DEBUG_CONTROL_ENABLE_MASK \ + (scn->targetdef->d_WLAN_DEBUG_CONTROL_ENABLE_MASK) +#define WLAN_DEBUG_OUT_OFFSET (scn->targetdef->d_WLAN_DEBUG_OUT_OFFSET) +#define WLAN_DEBUG_OUT_DATA_MSB (scn->targetdef->d_WLAN_DEBUG_OUT_DATA_MSB) +#define WLAN_DEBUG_OUT_DATA_LSB (scn->targetdef->d_WLAN_DEBUG_OUT_DATA_LSB) +#define WLAN_DEBUG_OUT_DATA_MASK (scn->targetdef->d_WLAN_DEBUG_OUT_DATA_MASK) +#define AMBA_DEBUG_BUS_OFFSET (scn->targetdef->d_AMBA_DEBUG_BUS_OFFSET) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB \ + (scn->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB \ + (scn->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB) +#define AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK \ + (scn->targetdef->d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK) +#define AMBA_DEBUG_BUS_SEL_MSB (scn->targetdef->d_AMBA_DEBUG_BUS_SEL_MSB) +#define AMBA_DEBUG_BUS_SEL_LSB (scn->targetdef->d_AMBA_DEBUG_BUS_SEL_LSB) +#define AMBA_DEBUG_BUS_SEL_MASK (scn->targetdef->d_AMBA_DEBUG_BUS_SEL_MASK) +#define CE_WRAPPER_DEBUG_OFFSET (scn->target_ce_def->d_CE_WRAPPER_DEBUG_OFFSET) +#define CE_WRAPPER_DEBUG_SEL_MSB (scn->target_ce_def->d_CE_WRAPPER_DEBUG_SEL_MSB) +#define CE_WRAPPER_DEBUG_SEL_LSB (scn->target_ce_def->d_CE_WRAPPER_DEBUG_SEL_LSB) +#define CE_WRAPPER_DEBUG_SEL_MASK (scn->target_ce_def->d_CE_WRAPPER_DEBUG_SEL_MASK) +#define CE_DEBUG_OFFSET (scn->target_ce_def->d_CE_DEBUG_OFFSET) +#define CE_DEBUG_SEL_MSB (scn->target_ce_def->d_CE_DEBUG_SEL_MSB) +#define CE_DEBUG_SEL_LSB (scn->target_ce_def->d_CE_DEBUG_SEL_LSB) +#define CE_DEBUG_SEL_MASK (scn->target_ce_def->d_CE_DEBUG_SEL_MASK) +#define HOST_IE_ADDRESS (scn->target_ce_def->d_HOST_IE_ADDRESS) +#define HOST_IS_ADDRESS (scn->target_ce_def->d_HOST_IS_ADDRESS) + +#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) + +#define CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_SRRI_ADDRESS) + +#define CE_SRC_RING_BASE_ADDR_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_BA_ADDRESS, (addr)) + +#define CE_SRC_RING_BASE_ADDR_HIGH_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_BA_ADDRESS_HIGH, (addr)) + +#define CE_SRC_RING_BASE_ADDR_HIGH_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + SR_BA_ADDRESS_HIGH) + +#define CE_SRC_RING_SZ_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_SIZE_ADDRESS, (n)) + +#define CE_SRC_RING_DMAX_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS, \ + (A_TARGET_READ(scn, (CE_ctrl_addr) + \ + CE_CTRL1_ADDRESS) & ~CE_CTRL1_DMAX_LENGTH_MASK) | \ + CE_CTRL1_DMAX_LENGTH_SET(n)) + +#define CE_CMD_REGISTER_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + CE_CMD_REGISTER) + +#define CE_CMD_REGISTER_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CMD_REGISTER, n) + +#define CE_MSI_ADDR_LOW_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_MSI_ADDRESS, (addr)) + +#define CE_MSI_ADDR_HIGH_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_MSI_ADDRESS_HIGH, (addr)) + +#define CE_MSI_DATA_SET(scn, CE_ctrl_addr, data) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_MSI_DATA, (data)) + +#define CE_CTRL_REGISTER1_SET(scn, CE_ctrl_addr, val) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS, val) + +#define CE_CTRL_REGISTER1_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS) + +#define CE_SRC_RING_BYTE_SWAP_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (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(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (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_READ_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS) + +#define CE_DEST_RING_BASE_ADDR_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DR_BA_ADDRESS, (addr)) + +#define CE_DEST_RING_BASE_ADDR_HIGH_SET(scn, CE_ctrl_addr, addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DR_BA_ADDRESS_HIGH, (addr)) + +#define CE_DEST_RING_BASE_ADDR_HIGH_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + DR_BA_ADDRESS_HIGH) + +#define CE_DEST_RING_SZ_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DR_SIZE_ADDRESS, (n)) + +#define CE_SRC_RING_HIGHMARK_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SRC_WATERMARK_ADDRESS, \ + (A_TARGET_READ(scn, \ + (CE_ctrl_addr) + SRC_WATERMARK_ADDRESS) \ + & ~SRC_WATERMARK_HIGH_MASK) | \ + SRC_WATERMARK_HIGH_SET(n)) + +#define CE_SRC_RING_LOWMARK_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SRC_WATERMARK_ADDRESS, \ + (A_TARGET_READ(scn, \ + (CE_ctrl_addr) + SRC_WATERMARK_ADDRESS) \ + & ~SRC_WATERMARK_LOW_MASK) | \ + SRC_WATERMARK_LOW_SET(n)) + +#define CE_DEST_RING_HIGHMARK_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DST_WATERMARK_ADDRESS, \ + (A_TARGET_READ(scn, \ + (CE_ctrl_addr) + DST_WATERMARK_ADDRESS) \ + & ~DST_WATERMARK_HIGH_MASK) | \ + DST_WATERMARK_HIGH_SET(n)) + +#define CE_DEST_RING_LOWMARK_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DST_WATERMARK_ADDRESS, \ + (A_TARGET_READ(scn, \ + (CE_ctrl_addr) + DST_WATERMARK_ADDRESS) \ + & ~DST_WATERMARK_LOW_MASK) | \ + DST_WATERMARK_LOW_SET(n)) + +#define CE_COPY_COMPLETE_INTR_ENABLE(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IE_ADDRESS, \ + A_TARGET_READ(scn, \ + (CE_ctrl_addr) + HOST_IE_ADDRESS) | \ + HOST_IE_COPY_COMPLETE_MASK) + +#define CE_COPY_COMPLETE_INTR_DISABLE(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IE_ADDRESS, \ + A_TARGET_READ(scn, \ + (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(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IE_ADDRESS, \ + A_TARGET_READ(scn, \ + (CE_ctrl_addr) + HOST_IE_ADDRESS) | \ + CE_WATERMARK_MASK) + +#define CE_WATERMARK_INTR_DISABLE(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IE_ADDRESS, \ + A_TARGET_READ(scn, \ + (CE_ctrl_addr) + HOST_IE_ADDRESS) \ + & ~CE_WATERMARK_MASK) + +#define CE_ERROR_INTR_ENABLE(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + MISC_IE_ADDRESS, \ + A_TARGET_READ(scn, \ + (CE_ctrl_addr) + MISC_IE_ADDRESS) | CE_ERROR_MASK) + +#define CE_MISC_INT_STATUS_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + MISC_IS_ADDRESS) + +#define CE_ENGINE_INT_STATUS_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + HOST_IS_ADDRESS) + +#define CE_ENGINE_INT_STATUS_CLEAR(scn, CE_ctrl_addr, mask) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IS_ADDRESS, (mask)) + +#define CE_WRAPPER_INDEX_BASE_LOW_SET(scn, n) \ + A_TARGET_WRITE(scn, \ + CE_WRAPPER_INDEX_BASE_LOW + CE_WRAPPER_BASE_ADDRESS, n) + +#define CE_WRAPPER_INDEX_BASE_HIGH_SET(scn, n) \ + A_TARGET_WRITE(scn, \ + CE_WRAPPER_INDEX_BASE_HIGH + CE_WRAPPER_BASE_ADDRESS, n) + +#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_RING_IDX_ADD(nentries_mask, idx, num) \ + (((idx) + (num)) & (nentries_mask)) + +#define CE_INTERRUPT_SUMMARY(scn) \ + CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ + A_TARGET_READ(scn, CE_WRAPPER_BASE_ADDRESS + \ + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) + +/*Macro to increment CE packet errors*/ +#define OL_ATH_CE_PKT_ERROR_COUNT_INCR(_scn, _ce_ecode) \ + do { if (_ce_ecode == CE_RING_DELTA_FAIL) \ + (_scn->pkt_stats.ce_ring_delta_fail_count) \ + += 1; } while (0) + +/* 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) +#define CE0_BASE_ADDRESS (scn->target_ce_def->d_CE0_BASE_ADDRESS) +#define CE1_BASE_ADDRESS (scn->target_ce_def->d_CE1_BASE_ADDRESS) + +#ifdef ADRASTEA_SHADOW_REGISTERS + +#define NUM_SHADOW_REGISTERS 24 + +#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \ + - CE0_BASE_ADDRESS)/(CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) + +u32 shadow_sr_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr); +u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr); +#define CE_SRC_RING_WRITE_IDX_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, shadow_sr_wr_ind_addr(scn, CE_ctrl_addr), n) + +#define CE_SRC_RING_WRITE_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, shadow_sr_wr_ind_addr(scn, CE_ctrl_addr)) + +#define CE_DEST_RING_WRITE_IDX_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, shadow_dst_wr_ind_addr(scn, CE_ctrl_addr), n) + +#define CE_DEST_RING_WRITE_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, shadow_dst_wr_ind_addr(scn, CE_ctrl_addr)) + +#else + +#define CE_SRC_RING_WRITE_IDX_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_WR_INDEX_ADDRESS, (n)) + +#define CE_SRC_RING_WRITE_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + SR_WR_INDEX_ADDRESS) + +#define CE_DEST_RING_WRITE_IDX_SET(scn, CE_ctrl_addr, n) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + DST_WR_INDEX_ADDRESS, (n)) + +#define CE_DEST_RING_WRITE_IDX_GET(scn, CE_ctrl_addr) \ + A_TARGET_READ(scn, (CE_ctrl_addr) + DST_WR_INDEX_ADDRESS) + +#endif + +#endif /* __CE_REG_H__ */ diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c new file mode 100644 index 000000000000..d27ca6b1a848 --- /dev/null +++ b/core/hif/src/ce/ce_service.c @@ -0,0 +1,1678 @@ +/* + * 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 "a_types.h" +#include +#include "osapi_linux.h" +#include "hif.h" +#include "hif_io32.h" +#include "ce_api.h" +#include "ce_main.h" +#include "ce_internal.h" +#include "ce_reg.h" +#include "cdf_lock.h" +#include "regtable.h" +#include +#include "epping_main.h" +#include "hif_main.h" +#include "hif_debug.h" + +#ifdef IPA_OFFLOAD +#ifdef QCA_WIFI_3_0 +#define CE_IPA_RING_INIT(ce_desc) \ + do { \ + ce_desc->gather = 0; \ + ce_desc->enable_11h = 0; \ + ce_desc->meta_data_low = 0; \ + ce_desc->packet_result_offset = 64; \ + ce_desc->toeplitz_hash_enable = 0; \ + ce_desc->addr_y_search_disable = 0; \ + ce_desc->addr_x_search_disable = 0; \ + ce_desc->misc_int_disable = 0; \ + ce_desc->target_int_disable = 0; \ + ce_desc->host_int_disable = 0; \ + ce_desc->dest_byte_swap = 0; \ + ce_desc->byte_swap = 0; \ + ce_desc->type = 2; \ + ce_desc->tx_classify = 1; \ + ce_desc->buffer_addr_hi = 0; \ + ce_desc->meta_data = 0; \ + ce_desc->nbytes = 128; \ + } while (0) +#else +#define CE_IPA_RING_INIT(ce_desc) \ + do { \ + ce_desc->byte_swap = 0; \ + ce_desc->nbytes = 60; \ + ce_desc->gather = 0; \ + } while (0) +#endif /* QCA_WIFI_3_0 */ +#endif /* IPA_OFFLOAD */ + +static int war1_allow_sleep; +/* io32 write workaround */ +static int hif_ce_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. + * Target TX harsh result toeplitz_hash_result + */ + +/* + * 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, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, unsigned int *hw_idx, + uint32_t *toeplitz_hash_result); + +void war_ce_src_ring_write_idx_set(struct ol_softc *scn, + u32 ctrl_addr, unsigned int write_index) +{ + if (hif_ce_war1) { + void __iomem *indicator_addr; + + indicator_addr = scn->mem + ctrl_addr + DST_WATERMARK_ADDRESS; + + if (!war1_allow_sleep + && ctrl_addr == CE_BASE_ADDRESS(CDC_WAR_DATA_CE)) { + hif_write32_mb(indicator_addr, + (CDC_WAR_MAGIC_STR | write_index)); + } else { + unsigned long irq_flags; + local_irq_save(irq_flags); + hif_write32_mb(indicator_addr, 1); + + /* + * PCIE write waits for ACK in IPQ8K, there is no + * need to read back value. + */ + (void)hif_read32_mb(indicator_addr); + (void)hif_read32_mb(indicator_addr); /* conservative */ + + CE_SRC_RING_WRITE_IDX_SET(scn, + ctrl_addr, write_index); + + hif_write32_mb(indicator_addr, 0); + local_irq_restore(irq_flags); + } + } else + CE_SRC_RING_WRITE_IDX_SET(scn, ctrl_addr, write_index); +} + +int +ce_send_nolock(struct CE_handle *copyeng, + void *per_transfer_context, + cdf_dma_addr_t buffer, + uint32_t nbytes, + uint32_t transfer_id, + uint32_t flags, + uint32_t user_flags) +{ + int status; + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *src_ring = CE_state->src_ring; + uint32_t ctrl_addr = CE_state->ctrl_addr; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int write_index = src_ring->write_index; + uint64_t dma_addr = buffer; + struct ol_softc *scn = CE_state->scn; + + A_TARGET_ACCESS_BEGIN_RET(scn); + if (unlikely(CE_RING_DELTA(nentries_mask, + write_index, sw_index - 1) <= 0)) { + OL_ATH_CE_PKT_ERROR_COUNT_INCR(scn, CE_RING_DELTA_FAIL); + status = CDF_STATUS_E_FAILURE; + A_TARGET_ACCESS_END_RET(scn); + 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 low 32 bits source descriptor address */ + shadow_src_desc->buffer_addr = + (uint32_t)(dma_addr & 0xFFFFFFFF); +#ifdef QCA_WIFI_3_0 + shadow_src_desc->buffer_addr_hi = + (uint32_t)((dma_addr >> 32) & 0x1F); + user_flags |= shadow_src_desc->buffer_addr_hi; + memcpy(&(((uint32_t *)shadow_src_desc)[1]), &user_flags, + sizeof(uint32_t)); +#endif + 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(scn, ctrl_addr, + write_index); + } + + src_ring->write_index = write_index; + status = CDF_STATUS_SUCCESS; + } + A_TARGET_ACCESS_END_RET(scn); + + return status; +} + +int +ce_send(struct CE_handle *copyeng, + void *per_transfer_context, + cdf_dma_addr_t buffer, + uint32_t nbytes, + uint32_t transfer_id, + uint32_t flags, + uint32_t user_flag) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + int status; + + cdf_spin_lock_bh(&CE_state->scn->target_lock); + status = ce_send_nolock(copyeng, per_transfer_context, buffer, nbytes, + transfer_id, flags, user_flag); + cdf_spin_unlock_bh(&CE_state->scn->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, + cdf_dma_addr_t buffer, + uint32_t nbytes, + uint32_t flags, + uint32_t user_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) { + CDF_ASSERT(num_items < CE_SENDLIST_ITEMS_MAX); + return CDF_STATUS_E_RESOURCES; + } + + item = &sl->item[num_items]; + item->send_type = CE_SIMPLE_BUFFER_TYPE; + item->data = buffer; + item->u.nbytes = nbytes; + item->flags = flags; + item->user_flags = user_flags; + sl->num_items = num_items + 1; + return CDF_STATUS_SUCCESS; +} + +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; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int num_items = sl->num_items; + unsigned int sw_index; + unsigned int write_index; + + CDF_ASSERT((num_items > 0) && (num_items < src_ring->nentries)); + + cdf_spin_lock_bh(&CE_state->scn->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? */ + CDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); + status = ce_send_nolock(copyeng, CE_SENDLIST_ITEM_CTXT, + (cdf_dma_addr_t) item->data, + item->u.nbytes, transfer_id, + item->flags | CE_SEND_FLAG_GATHER, + item->user_flags); + CDF_ASSERT(status == CDF_STATUS_SUCCESS); + } + /* provide valid context pointer for final item */ + item = &sl->item[i]; + /* TBDXXX: Support extensible sendlist_types? */ + CDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE); + status = ce_send_nolock(copyeng, per_transfer_context, + (cdf_dma_addr_t) item->data, + item->u.nbytes, + transfer_id, item->flags, + item->user_flags); + CDF_ASSERT(status == CDF_STATUS_SUCCESS); + NBUF_UPDATE_TX_PKT_COUNT((cdf_nbuf_t)per_transfer_context, + NBUF_TX_PKT_CE); + DPTRACE(cdf_dp_trace((cdf_nbuf_t)per_transfer_context, + CDF_DP_TRACE_CE_PACKET_PTR_RECORD, + (uint8_t *)(((cdf_nbuf_t)per_transfer_context)->data), + sizeof(((cdf_nbuf_t)per_transfer_context)->data))); + } 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. + */ + } + cdf_spin_unlock_bh(&CE_state->scn->target_lock); + + return status; +} + +#ifdef WLAN_FEATURE_FASTPATH +#ifdef QCA_WIFI_3_0 +static inline void +ce_buffer_addr_hi_set(struct CE_src_desc *shadow_src_desc, + uint64_t dma_addr, + uint32_t user_flags) +{ + shadow_src_desc->buffer_addr_hi = + (uint32_t)((dma_addr >> 32) & 0x1F); + user_flags |= shadow_src_desc->buffer_addr_hi; + memcpy(&(((uint32_t *)shadow_src_desc)[1]), &user_flags, + sizeof(uint32_t)); +} +#else +static inline void +ce_buffer_addr_hi_set(struct CE_src_desc *shadow_src_desc, + uint64_t dma_addr, + uint32_t user_flags) +{ +} +#endif + +/** + * ce_send_fast() CE layer Tx buffer posting function + * @copyeng: copy engine handle + * @msdus: iarray of msdu to be sent + * @num_msdus: number of msdus in an array + * @transfer_id: transfer_id + * + * Assumption : Called with an array of MSDU's + * Function: + * For each msdu in the array + * 1. Check no. of available entries + * 2. Create src ring entries (allocated in consistent memory + * 3. Write index to h/w + * + * Return: No. of packets that could be sent + */ + +int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, + unsigned int num_msdus, unsigned int transfer_id) +{ + struct CE_state *ce_state = (struct CE_state *)copyeng; + struct ol_softc *scn = ce_state->scn; + struct CE_ring_state *src_ring = ce_state->src_ring; + u_int32_t ctrl_addr = ce_state->ctrl_addr; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int write_index; + unsigned int sw_index; + unsigned int frag_len; + cdf_nbuf_t msdu; + int i; + uint64_t dma_addr; + uint32_t user_flags = 0; + + /* + * This lock could be more fine-grained, one per CE, + * TODO : Add this lock now. + * That is the next step of optimization. + */ + cdf_spin_lock_bh(&scn->target_lock); + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + + /* 2 msdus per packet */ + for (i = 0; i < num_msdus; i++) { + 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); + + msdu = msdus[i]; + + /* + * First fill out the ring descriptor for the HTC HTT frame + * header. These are uncached writes. Should we use a local + * structure instead? + */ + /* HTT/HTC header can be passed as a argument */ + dma_addr = cdf_nbuf_get_frag_paddr_lo(msdu, 0); + shadow_src_desc->buffer_addr = (uint32_t)(dma_addr & + 0xFFFFFFFF); + user_flags = cdf_nbuf_data_attr_get(msdu) & DESC_DATA_FLAG_MASK; + ce_buffer_addr_hi_set(shadow_src_desc, dma_addr, user_flags); + + shadow_src_desc->meta_data = transfer_id; + shadow_src_desc->nbytes = cdf_nbuf_get_frag_len(msdu, 0); + + /* + * HTC HTT header is a word stream, so byte swap if CE byte + * swap enabled + */ + shadow_src_desc->byte_swap = ((ce_state->attr_flags & + CE_ATTR_BYTE_SWAP_DATA) != 0); + /* For the first one, it still does not need to write */ + shadow_src_desc->gather = 1; + *src_desc = *shadow_src_desc; + + /* By default we could initialize the transfer context to this + * value + */ + src_ring->per_transfer_context[write_index] = + CE_SENDLIST_ITEM_CTXT; + + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + + src_desc = CE_SRC_RING_TO_DESC(src_ring_base, write_index); + shadow_src_desc = CE_SRC_RING_TO_DESC(shadow_base, write_index); + /* + * Now fill out the ring descriptor for the actual data + * packet + */ + dma_addr = cdf_nbuf_get_frag_paddr_lo(msdu, 1); + shadow_src_desc->buffer_addr = (uint32_t)(dma_addr & + 0xFFFFFFFF); + /* + * Clear packet offset for all but the first CE desc. + */ + user_flags &= ~CDF_CE_TX_PKT_OFFSET_BIT_M; + ce_buffer_addr_hi_set(shadow_src_desc, dma_addr, user_flags); + shadow_src_desc->meta_data = transfer_id; + + /* get actual packet length */ + frag_len = cdf_nbuf_get_frag_len(msdu, 1); + shadow_src_desc->nbytes = frag_len > ce_state->download_len ? + ce_state->download_len : frag_len; + + /* Data packet is a byte stream, so disable byte swap */ + shadow_src_desc->byte_swap = 0; + /* For the last one, gather is not set */ + shadow_src_desc->gather = 0; + *src_desc = *shadow_src_desc; + src_ring->per_transfer_context[write_index] = msdu; + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + } + + /* Write the final index to h/w one-shot */ + if (i) { + src_ring->write_index = write_index; + /* Don't call WAR_XXX from here + * Just call XXX instead, that has the reqd. intel + */ + war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index); + } + + cdf_spin_unlock_bh(&scn->target_lock); + + /* + * If all packets in the array are transmitted, + * i = num_msdus + * Temporarily add an ASSERT + */ + ASSERT(i == num_msdus); + return i; +} +#endif /* WLAN_FEATURE_FASTPATH */ + +int +ce_recv_buf_enqueue(struct CE_handle *copyeng, + void *per_recv_context, cdf_dma_addr_t buffer) +{ + int status; + struct CE_state *CE_state = (struct CE_state *)copyeng; + struct CE_ring_state *dest_ring = CE_state->dest_ring; + uint32_t ctrl_addr = CE_state->ctrl_addr; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int write_index; + unsigned int sw_index; + int val = 0; + uint64_t dma_addr = buffer; + struct ol_softc *scn = CE_state->scn; + + cdf_spin_lock_bh(&scn->target_lock); + write_index = dest_ring->write_index; + sw_index = dest_ring->sw_index; + + A_TARGET_ACCESS_BEGIN_RET_EXT(scn, val); + if (val == -1) { + cdf_spin_unlock_bh(&scn->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 low 32 bit destination descriptor */ + dest_desc->buffer_addr = (uint32_t)(dma_addr & 0xFFFFFFFF); +#ifdef QCA_WIFI_3_0 + dest_desc->buffer_addr_hi = + (uint32_t)((dma_addr >> 32) & 0x1F); +#endif + dest_desc->nbytes = 0; + + 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(scn, ctrl_addr, write_index); + dest_ring->write_index = write_index; + status = CDF_STATUS_SUCCESS; + } else { + status = CDF_STATUS_E_FAILURE; + } + A_TARGET_ACCESS_END_RET_EXT(scn, val); + if (val == -1) { + cdf_spin_unlock_bh(&scn->target_lock); + return val; + } + + cdf_spin_unlock_bh(&scn->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; + uint32_t ctrl_addr = CE_state->ctrl_addr; + struct ol_softc *scn = CE_state->scn; + + cdf_spin_lock(&scn->target_lock); + CE_SRC_RING_LOWMARK_SET(scn, ctrl_addr, low_alert_nentries); + CE_SRC_RING_HIGHMARK_SET(scn, ctrl_addr, high_alert_nentries); + cdf_spin_unlock(&scn->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; + uint32_t ctrl_addr = CE_state->ctrl_addr; + struct ol_softc *scn = CE_state->scn; + + cdf_spin_lock(&scn->target_lock); + CE_DEST_RING_LOWMARK_SET(scn, ctrl_addr, + low_alert_nentries); + CE_DEST_RING_HIGHMARK_SET(scn, ctrl_addr, + high_alert_nentries); + cdf_spin_unlock(&scn->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; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index; + unsigned int write_index; + + cdf_spin_lock(&CE_state->scn->target_lock); + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + cdf_spin_unlock(&CE_state->scn->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; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int sw_index; + unsigned int write_index; + + cdf_spin_lock(&CE_state->scn->target_lock); + sw_index = dest_ring->sw_index; + write_index = dest_ring->write_index; + cdf_spin_unlock(&CE_state->scn->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 ol_softc *scn, + struct CE_state *CE_state) +{ + struct CE_ring_state *src_ring = CE_state->src_ring; + uint32_t ctrl_addr = CE_state->ctrl_addr; + 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(scn, 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; + unsigned int nentries; + + cdf_spin_lock(&CE_state->scn->target_lock); + nentries = ce_send_entries_done_nolock(CE_state->scn, CE_state); + cdf_spin_unlock(&CE_state->scn->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 ol_softc *scn, + struct CE_state *CE_state) +{ + struct CE_ring_state *dest_ring = CE_state->dest_ring; + uint32_t ctrl_addr = CE_state->ctrl_addr; + 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(scn, 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; + unsigned int nentries; + + cdf_spin_lock(&CE_state->scn->target_lock); + nentries = ce_recv_entries_done_nolock(CE_state->scn, CE_state); + cdf_spin_unlock(&CE_state->scn->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, + cdf_dma_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 CE_dest_desc 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; + 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 = CDF_STATUS_E_FAILURE; + goto done; + } + + dest_desc->nbytes = 0; + + /* Return data from completed destination descriptor */ + *bufferp = HIF_CE_DESC_ADDR_TO_DMA(&dest_desc_info); + *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 = CDF_STATUS_SUCCESS; + +done: + return status; +} + +int +ce_completed_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, unsigned int *flagsp) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + int status; + + cdf_spin_lock_bh(&CE_state->scn->target_lock); + status = + ce_completed_recv_next_nolock(CE_state, per_CE_contextp, + per_transfer_contextp, bufferp, + nbytesp, transfer_idp, flagsp); + cdf_spin_unlock_bh(&CE_state->scn->target_lock); + + return status; +} + +/* NB: Modeled after ce_completed_recv_next_nolock */ +CDF_STATUS +ce_revoke_recv_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, cdf_dma_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; + CDF_STATUS status; + struct ol_softc *scn; + + CE_state = (struct CE_state *)copyeng; + dest_ring = CE_state->dest_ring; + if (!dest_ring) { + return CDF_STATUS_E_FAILURE; + } + + scn = CE_state->scn; + cdf_spin_lock(&scn->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 = HIF_CE_DESC_ADDR_TO_DMA(dest_desc); + + 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 = CDF_STATUS_SUCCESS; + } else { + status = CDF_STATUS_E_FAILURE; + } + cdf_spin_unlock(&scn->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, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx, + uint32_t *toeplitz_hash_result) +{ + int status = CDF_STATUS_E_FAILURE; + struct CE_ring_state *src_ring = CE_state->src_ring; + uint32_t ctrl_addr = CE_state->ctrl_addr; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int read_index; + struct ol_softc *scn = CE_state->scn; + + 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(scn); + src_ring->hw_index = + CE_SRC_RING_READ_IDX_GET(scn, ctrl_addr); + A_TARGET_ACCESS_END_RET(scn); + } + 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); +#ifdef QCA_WIFI_3_0 + 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); +#endif + /* Return data from completed source descriptor */ + *bufferp = HIF_CE_DESC_ADDR_TO_DMA(shadow_src_desc); + *nbytesp = shadow_src_desc->nbytes; + *transfer_idp = shadow_src_desc->meta_data; +#ifdef QCA_WIFI_3_0 + *toeplitz_hash_result = src_desc->toeplitz_hash_result; +#else + *toeplitz_hash_result = 0; +#endif + 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 = CDF_STATUS_SUCCESS; + } + + return status; +} + +/* NB: Modeled after ce_completed_send_next */ +CDF_STATUS +ce_cancel_send_next(struct CE_handle *copyeng, + void **per_CE_contextp, + void **per_transfer_contextp, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + uint32_t *toeplitz_hash_result) +{ + struct CE_state *CE_state; + struct CE_ring_state *src_ring; + unsigned int nentries_mask; + unsigned int sw_index; + unsigned int write_index; + CDF_STATUS status; + struct ol_softc *scn; + + CE_state = (struct CE_state *)copyeng; + src_ring = CE_state->src_ring; + if (!src_ring) { + return CDF_STATUS_E_FAILURE; + } + + scn = CE_state->scn; + cdf_spin_lock(&CE_state->scn->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 = HIF_CE_DESC_ADDR_TO_DMA(src_desc); + *nbytesp = src_desc->nbytes; + *transfer_idp = src_desc->meta_data; +#ifdef QCA_WIFI_3_0 + *toeplitz_hash_result = src_desc->toeplitz_hash_result; +#else + *toeplitz_hash_result = 0; +#endif + + 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 = CDF_STATUS_SUCCESS; + } else { + status = CDF_STATUS_E_FAILURE; + } + cdf_spin_unlock(&CE_state->scn->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, + cdf_dma_addr_t *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *sw_idx, + unsigned int *hw_idx, + unsigned int *toeplitz_hash_result) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + int status; + + cdf_spin_lock_bh(&CE_state->scn->target_lock); + status = + ce_completed_send_next_nolock(CE_state, per_CE_contextp, + per_transfer_contextp, bufferp, + nbytesp, transfer_idp, sw_idx, + hw_idx, toeplitz_hash_result); + cdf_spin_unlock_bh(&CE_state->scn->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 + * hif_send_complete_check so should not countain recieve functionality + * within it . + */ + +void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) +{ + void *CE_context; + void *transfer_context; + cdf_dma_addr_t buf; + unsigned int nbytes; + unsigned int id; + unsigned int sw_idx, hw_idx; + uint32_t toeplitz_hash_result; + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + + A_TARGET_ACCESS_BEGIN(scn); + + /* 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 occured + * 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. + */ + + cdf_spin_lock_bh(&scn->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, + &toeplitz_hash_result) == + CDF_STATUS_SUCCESS) { + if (CE_id != CE_HTT_H2T_MSG) { + cdf_spin_unlock_bh(&scn->target_lock); + CE_state-> + send_cb((struct CE_handle *) + CE_state, CE_context, + transfer_context, buf, + nbytes, id, sw_idx, hw_idx, + toeplitz_hash_result); + cdf_spin_lock_bh(&scn->target_lock); + } else { + struct HIF_CE_pipe_info *pipe_info = + (struct HIF_CE_pipe_info *) + CE_context; + + cdf_spin_lock_bh(&pipe_info-> + completion_freeq_lock); + pipe_info->num_sends_allowed++; + cdf_spin_unlock_bh(&pipe_info-> + completion_freeq_lock); + } + } + } + } + + cdf_spin_unlock_bh(&scn->target_lock); + A_TARGET_ACCESS_END(scn); +} + +#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. + * + * Returns: number of messages processed + */ + +int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id) +{ + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + uint32_t ctrl_addr = CE_state->ctrl_addr; + void *CE_context; + void *transfer_context; + cdf_dma_addr_t buf; + unsigned int nbytes; + unsigned int id; + unsigned int flags; + uint32_t CE_int_status; + unsigned int more_comp_cnt = 0; + unsigned int more_snd_comp_cnt = 0; + unsigned int sw_idx, hw_idx; + uint32_t toeplitz_hash_result; + + if (Q_TARGET_ACCESS_BEGIN(scn) < 0) { + HIF_ERROR("[premature rc=0]\n"); + return 0; /* no work done */ + } + + cdf_spin_lock(&scn->target_lock); + + /* Clear force_break flag and re-initialize receive_count to 0 */ + + /* NAPI: scn variables- thread/multi-processing safety? */ + scn->receive_count = 0; + scn->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) == + CDF_STATUS_SUCCESS) { + cdf_spin_unlock(&scn->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 (cdf_unlikely(scn->force_break)) { + cdf_atomic_set(&CE_state->rx_pending, 1); + CE_ENGINE_INT_STATUS_CLEAR(scn, ctrl_addr, + HOST_IS_COPY_COMPLETE_MASK); + if (Q_TARGET_ACCESS_END(scn) < 0) + HIF_ERROR("<--[premature rc=%d]\n", + scn->receive_count); + return scn->receive_count; + } + cdf_spin_lock(&scn->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, + &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { + + if (CE_id != CE_HTT_H2T_MSG || + WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + cdf_spin_unlock(&scn->target_lock); + CE_state->send_cb((struct CE_handle *)CE_state, + CE_context, transfer_context, + buf, nbytes, id, sw_idx, + hw_idx, toeplitz_hash_result); + cdf_spin_lock(&scn->target_lock); + } else { + struct HIF_CE_pipe_info *pipe_info = + (struct HIF_CE_pipe_info *)CE_context; + + cdf_spin_lock(&pipe_info-> + completion_freeq_lock); + pipe_info->num_sends_allowed++; + cdf_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, + &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { + cdf_spin_unlock(&scn->target_lock); + CE_state->send_cb((struct CE_handle *)CE_state, + CE_context, transfer_context, buf, + nbytes, id, sw_idx, hw_idx, + toeplitz_hash_result); + cdf_spin_lock(&scn->target_lock); + } +#endif /*ATH_11AC_TXCOMPACT */ + } + +more_watermarks: + if (CE_state->misc_cbs) { + CE_int_status = CE_ENGINE_INT_STATUS_GET(scn, ctrl_addr); + if (CE_int_status & CE_WATERMARK_MASK) { + if (CE_state->watermark_cb) { + + cdf_spin_unlock(&scn->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); + cdf_spin_lock(&scn->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(scn, 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(scn, CE_state)) { + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam()) || + more_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { + goto more_completions; + } else { + HIF_ERROR( + "%s:Potential infinite loop detected during Rx processing nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", + __func__, CE_state->dest_ring->nentries_mask, + CE_state->dest_ring->sw_index, + CE_DEST_RING_READ_IDX_GET(scn, + CE_state->ctrl_addr)); + } + } + + if (CE_state->send_cb && ce_send_entries_done_nolock(scn, CE_state)) { + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam()) || + more_snd_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { + goto more_completions; + } else { + HIF_ERROR( + "%s:Potential infinite loop detected during send completion nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", + __func__, CE_state->src_ring->nentries_mask, + CE_state->src_ring->sw_index, + CE_SRC_RING_READ_IDX_GET(scn, + CE_state->ctrl_addr)); + } + } + + if (CE_state->misc_cbs) { + CE_int_status = CE_ENGINE_INT_STATUS_GET(scn, ctrl_addr); + if (CE_int_status & CE_WATERMARK_MASK) { + if (CE_state->watermark_cb) { + goto more_watermarks; + } + } + } + + cdf_spin_unlock(&scn->target_lock); + cdf_atomic_set(&CE_state->rx_pending, 0); + + if (Q_TARGET_ACCESS_END(scn) < 0) + HIF_ERROR("<--[premature rc=%d]\n", scn->receive_count); + return scn->receive_count; +} + +/* + * 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, struct ol_softc *scn) +{ + int CE_id; + uint32_t intr_summary; + + A_TARGET_ACCESS_BEGIN(scn); + if (!cdf_atomic_read(&scn->tasklet_from_intr)) { + for (CE_id = 0; CE_id < scn->ce_count; CE_id++) { + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + if (cdf_atomic_read(&CE_state->rx_pending)) { + cdf_atomic_set(&CE_state->rx_pending, 0); + ce_per_engine_service(scn, CE_id); + } + } + + A_TARGET_ACCESS_END(scn); + return; + } + + intr_summary = CE_INTERRUPT_SUMMARY(scn); + + for (CE_id = 0; intr_summary && (CE_id < scn->ce_count); CE_id++) { + if (intr_summary & (1 << CE_id)) { + intr_summary &= ~(1 << CE_id); + } else { + continue; /* no intr pending on this CE */ + } + + ce_per_engine_service(scn, CE_id); + } + + A_TARGET_ACCESS_END(scn); +} + +/* + * Adjust interrupts for the copy complete handler. + * If it's needed for either send or recv, then unmask + * this interrupt; otherwise, mask it. + * + * Called with target_lock held. + */ +static void +ce_per_engine_handler_adjust(struct CE_state *CE_state, + int disable_copy_compl_intr) +{ + uint32_t ctrl_addr = CE_state->ctrl_addr; + struct ol_softc *scn = CE_state->scn; + + CE_state->disable_copy_compl_intr = disable_copy_compl_intr; + A_TARGET_ACCESS_BEGIN(scn); + if ((!disable_copy_compl_intr) && + (CE_state->send_cb || CE_state->recv_cb)) { + CE_COPY_COMPLETE_INTR_ENABLE(scn, ctrl_addr); + } else { + CE_COPY_COMPLETE_INTR_DISABLE(scn, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_ENABLE(scn, ctrl_addr); + } else { + CE_WATERMARK_INTR_DISABLE(scn, ctrl_addr); + } + A_TARGET_ACCESS_END(scn); + +} + +/*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 ol_softc *scn) +{ + int CE_id; + + A_TARGET_ACCESS_BEGIN(scn); + for (CE_id = 0; CE_id < scn->ce_count; CE_id++) { + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + uint32_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(scn, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_DISABLE(scn, ctrl_addr); + } + } + A_TARGET_ACCESS_END(scn); +} + +void ce_enable_any_copy_compl_intr_nolock(struct ol_softc *scn) +{ + int CE_id; + + A_TARGET_ACCESS_BEGIN(scn); + for (CE_id = 0; CE_id < scn->ce_count; CE_id++) { + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + uint32_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(scn, ctrl_addr); + } + + if (CE_state->watermark_cb) { + CE_WATERMARK_INTR_ENABLE(scn, ctrl_addr); + } + } + A_TARGET_ACCESS_END(scn); +} + +void ce_disable_any_copy_compl_intr(struct ol_softc *scn) +{ + cdf_spin_lock(&scn->target_lock); + ce_disable_any_copy_compl_intr_nolock(scn); + cdf_spin_unlock(&scn->target_lock); +} + +/*Re-enable the copy compl interrupt if it has not been disabled before.*/ +void ce_enable_any_copy_compl_intr(struct ol_softc *scn) +{ + cdf_spin_lock(&scn->target_lock); + ce_enable_any_copy_compl_intr_nolock(scn); + cdf_spin_unlock(&scn->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; + + cdf_spin_lock(&CE_state->scn->target_lock); + CE_state->send_cb = fn_ptr; + CE_state->send_context = ce_send_context; + ce_per_engine_handler_adjust(CE_state, disable_interrupts); + cdf_spin_unlock(&CE_state->scn->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; + + cdf_spin_lock(&CE_state->scn->target_lock); + CE_state->recv_cb = fn_ptr; + CE_state->recv_context = CE_recv_context; + ce_per_engine_handler_adjust(CE_state, disable_interrupts); + cdf_spin_unlock(&CE_state->scn->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; + + cdf_spin_lock(&CE_state->scn->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; + } + cdf_spin_unlock(&CE_state->scn->target_lock); +} + +#ifdef WLAN_FEATURE_FASTPATH +/** + * ce_pkt_dl_len_set() set the HTT packet download length + * @hif_sc: HIF context + * @pkt_download_len: download length + * + * Return: None + */ +void ce_pkt_dl_len_set(void *hif_sc, u_int32_t pkt_download_len) +{ + struct ol_softc *sc = (struct ol_softc *)(hif_sc); + struct CE_state *ce_state = sc->ce_id_to_state[CE_HTT_H2T_MSG]; + + cdf_assert_always(ce_state); + + cdf_spin_lock_bh(&sc->target_lock); + ce_state->download_len = pkt_download_len; + cdf_spin_unlock_bh(&sc->target_lock); + + cdf_print("%s CE %d Pkt download length %d\n", __func__, + ce_state->id, ce_state->download_len); +} +#else +void ce_pkt_dl_len_set(void *hif_sc, u_int32_t pkt_download_len) +{ +} +#endif /* WLAN_FEATURE_FASTPATH */ + +bool ce_get_rx_pending(struct ol_softc *scn) +{ + int CE_id; + + for (CE_id = 0; CE_id < scn->ce_count; CE_id++) { + struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + if (cdf_atomic_read(&CE_state->rx_pending)) + return true; + } + + return false; +} + +/** + * ce_check_rx_pending() - ce_check_rx_pending + * @scn: ol_softc + * @ce_id: ce_id + * + * Return: bool + */ +bool ce_check_rx_pending(struct ol_softc *scn, int ce_id) +{ + struct CE_state *CE_state = scn->ce_id_to_state[ce_id]; + if (cdf_atomic_read(&CE_state->rx_pending)) + return true; + else + return false; +} +void ce_enable_msi(struct ol_softc *scn, unsigned int CE_id, + uint32_t msi_addr_lo, uint32_t msi_addr_hi, + uint32_t msi_data) +{ +#ifdef WLAN_ENABLE_QCA6180 + struct CE_state *CE_state; + A_target_id_t targid; + u_int32_t ctrl_addr; + uint32_t tmp; + + adf_os_spin_lock(&scn->target_lock); + CE_state = scn->ce_id_to_state[CE_id]; + if (!CE_state) { + HIF_ERROR("%s: error - CE_state = NULL", __func__); + adf_os_spin_unlock(&scn->target_lock); + return; + } + targid = TARGID(sc); + ctrl_addr = CE_state->ctrl_addr; + CE_MSI_ADDR_LOW_SET(scn, ctrl_addr, msi_addr_lo); + CE_MSI_ADDR_HIGH_SET(scn, ctrl_addr, msi_addr_hi); + CE_MSI_DATA_SET(scn, ctrl_addr, msi_data); + tmp = CE_CTRL_REGISTER1_GET(scn, ctrl_addr); + tmp |= (1 << CE_MSI_ENABLE_BIT); + CE_CTRL_REGISTER1_SET(scn, ctrl_addr, tmp); + adf_os_spin_unlock(&scn->target_lock); +#endif +} + +#ifdef IPA_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_ipa_get_resource(struct CE_handle *ce, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr) +{ + struct CE_state *CE_state = (struct CE_state *)ce; + uint32_t ring_loop; + struct CE_src_desc *ce_desc; + cdf_dma_addr_t phy_mem_base; + struct ol_softc *scn = CE_state->scn; + + 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))); + CE_IPA_RING_INIT(ce_desc); + } + + /* Get BAR address */ + hif_read_phy_mem_base(CE_state->scn, &phy_mem_base); + + *ce_sr_base_paddr = (uint32_t) CE_state->src_ring->base_addr_CE_space; + *ce_sr_ring_size = (uint32_t) CE_state->src_ring->nentries; + *ce_reg_paddr = phy_mem_base + CE_BASE_ADDRESS(CE_state->id) + + SR_WR_INDEX_ADDRESS; + return; +} +#endif /* IPA_OFFLOAD */ + diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c new file mode 100644 index 000000000000..6bb550e3c8c9 --- /dev/null +++ b/core/hif/src/ce/ce_tasklet.c @@ -0,0 +1,404 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include "a_types.h" +#include "athdefs.h" +#include "cdf_lock.h" +#include "cdf_types.h" +#include "cdf_status.h" +#include "cds_api.h" +#include "regtable.h" +#include "hif.h" +#include "hif_io32.h" +#include "ce_main.h" +#include "ce_api.h" +#include "ce_reg.h" +#include "ce_internal.h" +#ifdef CONFIG_CNSS +#include +#ifdef HIF_PCI +#include "icnss_stub.h" +#else +#include +#endif /* HIF_PCI */ +#endif +#include "hif_debug.h" +#include "hif_napi.h" + + +/** + * ce_irq_status() - read CE IRQ status + * @scn: struct ol_softc + * @ce_id: ce_id + * @host_status: host_status + * + * Return: IRQ status + */ +static inline void ce_irq_status(struct ol_softc *scn, + int ce_id, uint32_t *host_status) +{ + uint32_t offset = HOST_IS_ADDRESS + CE_BASE_ADDRESS(ce_id); + + *host_status = hif_read32_mb(scn->mem + offset); +} + +/** + * reschedule_ce_tasklet_work_handler() - reschedule work + * @ce_id: ce_id + * + * Return: N/A + */ +static void reschedule_ce_tasklet_work_handler(int ce_id) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct HIF_CE_state *hif_ce_state; + + if (NULL == scn) { + HIF_ERROR("%s: tasklet scn is null", __func__); + return; + } + hif_ce_state = (struct HIF_CE_state *)scn->hif_hdl; + + if (scn->hif_init_done == false) { + HIF_ERROR("%s: wlan driver is unloaded", __func__); + return; + } + tasklet_schedule(&hif_ce_state->tasklets[ce_id].intr_tq); + return; +} + +/** + * struct tasklet_work + * + * @id: ce_id + * @work: work + */ +struct tasklet_work { + enum ce_id_type id; + struct work_struct work; +}; + +static struct tasklet_work tasklet_workers[CE_ID_MAX]; +static bool work_initialized; + +/** + * work_handler() - work_handler + * @work: struct work_struct + * + * Return: N/A + */ +static void work_handler(struct work_struct *work) +{ + struct tasklet_work *tmp; + + tmp = container_of(work, struct tasklet_work, work); + reschedule_ce_tasklet_work_handler(tmp->id); +} + +/** + * init_tasklet_work() - init_tasklet_work + * @work: struct work_struct + * @work_handler: work_handler + * + * Return: N/A + */ +#ifdef CONFIG_CNSS +static void init_tasklet_work(struct work_struct *work, + work_func_t work_handler) +{ + cnss_init_work(work, work_handler); +} +#else +static void init_tasklet_work(struct work_struct *work, + work_func_t work_handler) +{ + INIT_WORK(work, work_handler); +} +#endif + +/** + * init_tasklet_workers() - init_tasklet_workers + * + * Return: N/A + */ +void init_tasklet_workers(void) +{ + uint32_t id; + + for (id = 0; id < CE_ID_MAX; id++) { + tasklet_workers[id].id = id; + init_tasklet_work(&tasklet_workers[id].work, work_handler); + } + work_initialized = true; +} + +#ifdef CONFIG_SLUB_DEBUG_ON +/** + * ce_schedule_tasklet() - schedule ce tasklet + * @tasklet_entry: struct ce_tasklet_entry + * + * Return: N/A + */ +static inline void ce_schedule_tasklet(struct ce_tasklet_entry *tasklet_entry) +{ + if (work_initialized && (tasklet_entry->ce_id <= CE_ID_MAX)) + schedule_work(&tasklet_workers[tasklet_entry->ce_id].work); + else + HIF_ERROR("%s: work_initialized = %d, ce_id = %d", + __func__, work_initialized, tasklet_entry->ce_id); +} +#else +/** + * ce_schedule_tasklet() - schedule ce tasklet + * @tasklet_entry: struct ce_tasklet_entry + * + * Return: N/A + */ +static inline void ce_schedule_tasklet(struct ce_tasklet_entry *tasklet_entry) +{ + tasklet_schedule(&tasklet_entry->intr_tq); +} +#endif + +/** + * ce_tasklet() - ce_tasklet + * @data: data + * + * Return: N/A + */ +static void ce_tasklet(unsigned long data) +{ + struct ce_tasklet_entry *tasklet_entry = + (struct ce_tasklet_entry *)data; + struct HIF_CE_state *hif_ce_state = tasklet_entry->hif_ce_state; + struct ol_softc *scn = hif_ce_state->scn; + struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id]; + + if (tasklet_entry->from_irq) + tasklet_entry->from_irq = false; + + if (cdf_atomic_read(&scn->link_suspended)) { + HIF_ERROR("%s: ce %d tasklet fired after link suspend.", + __func__, tasklet_entry->ce_id); + CDF_BUG(0); + } + + ce_per_engine_service(scn, tasklet_entry->ce_id); + + if (tasklet_entry->ce_id == CE_HTT_T2H_MSG && + CE_state->lro_flush_cb != NULL) { + CE_state->lro_flush_cb(CE_state->lro_data); + } + + if (ce_check_rx_pending(scn, tasklet_entry->ce_id)) { + /* + * 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. + */ + ce_schedule_tasklet(tasklet_entry); + return; + } + + if (scn->target_status != OL_TRGET_STATUS_RESET) + ce_irq_enable(scn, tasklet_entry->ce_id); + + cdf_atomic_dec(&scn->active_tasklet_cnt); +} +/** + * ce_tasklet_init() - ce_tasklet_init + * @hif_ce_state: hif_ce_state + * @mask: mask + * + * Return: N/A + */ +void ce_tasklet_init(struct HIF_CE_state *hif_ce_state, uint32_t mask) +{ + int i; + + for (i = 0; i < CE_COUNT_MAX; i++) { + if (mask & (1 << i)) { + hif_ce_state->tasklets[i].ce_id = i; + hif_ce_state->tasklets[i].inited = true; + hif_ce_state->tasklets[i].hif_ce_state = hif_ce_state; + tasklet_init(&hif_ce_state->tasklets[i].intr_tq, + ce_tasklet, + (unsigned long)&hif_ce_state->tasklets[i]); + } + } +} +/** + * ce_tasklet_kill() - ce_tasklet_kill + * @hif_ce_state: hif_ce_state + * + * Return: N/A + */ +void ce_tasklet_kill(struct HIF_CE_state *hif_ce_state) +{ + int i; + struct ol_softc *scn = hif_ce_state->scn; + + for (i = 0; i < CE_COUNT_MAX; i++) + if (hif_ce_state->tasklets[i].inited) { + tasklet_kill(&hif_ce_state->tasklets[i].intr_tq); + hif_ce_state->tasklets[i].inited = false; + } + cdf_atomic_set(&scn->active_tasklet_cnt, 0); +} +/** + * ce_irq_handler() - ce_irq_handler + * @ce_id: ce_id + * @context: context + * + * Return: N/A + */ +static irqreturn_t ce_irq_handler(int irq, void *context) +{ + struct ce_tasklet_entry *tasklet_entry = context; + struct HIF_CE_state *hif_ce_state = tasklet_entry->hif_ce_state; + struct ol_softc *scn = hif_ce_state->scn; + int ce_id = icnss_get_ce_id(irq); + uint32_t host_status; + + + if (tasklet_entry->ce_id != ce_id) { + HIF_ERROR("%s: ce_id (expect %d, received %d) does not match", + __func__, tasklet_entry->ce_id, ce_id); + return IRQ_NONE; + } + +#ifndef HIF_PCI + disable_irq_nosync(irq); +#endif + ce_irq_disable(scn, ce_id); + ce_irq_status(scn, ce_id, &host_status); + cdf_atomic_inc(&scn->active_tasklet_cnt); + if (hif_napi_enabled(scn, ce_id)) + hif_napi_schedule(scn, ce_id); + else { + tasklet_entry->from_irq = true; + tasklet_schedule(&tasklet_entry->intr_tq); + } + return IRQ_HANDLED; +} + +/** + * const char *ce_name + * + * @ce_name: ce_name + */ +const char *ce_name[ICNSS_MAX_IRQ_REGISTRATIONS] = { + "WLAN_CE_0", + "WLAN_CE_1", + "WLAN_CE_2", + "WLAN_CE_3", + "WLAN_CE_4", + "WLAN_CE_5", + "WLAN_CE_6", + "WLAN_CE_7", + "WLAN_CE_8", + "WLAN_CE_9", + "WLAN_CE_10", + "WLAN_CE_11", +}; +/** + * ce_unregister_irq() - ce_unregister_irq + * @hif_ce_state: hif_ce_state copy engine device handle + * @mask: which coppy engines to unregister for. + * + * Unregisters copy engine irqs matching mask. If a 1 is set at bit x, + * unregister for copy engine x. + * + * Return: CDF_STATUS + */ +CDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask) +{ + int id; + int ret; + + if (hif_ce_state == NULL) { + HIF_WARN("%s: hif_ce_state = NULL", __func__); + return CDF_STATUS_SUCCESS; + } + for (id = 0; id < CE_COUNT_MAX; id++) { + if ((mask & (1 << id)) && hif_ce_state->tasklets[id].inited) { + ret = icnss_ce_free_irq(id, + &hif_ce_state->tasklets[id]); + if (ret < 0) + HIF_ERROR( + "%s: icnss_unregister_irq error - ce_id = %d, ret = %d", + __func__, id, ret); + } + } + return CDF_STATUS_SUCCESS; +} +/** + * ce_register_irq() - ce_register_irq + * @hif_ce_state: hif_ce_state + * @mask: which coppy engines to unregister for. + * + * Registers copy engine irqs matching mask. If a 1 is set at bit x, + * Register for copy engine x. + * + * Return: CDF_STATUS + */ +CDF_STATUS ce_register_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask) +{ + int id; + int ret; + unsigned long irqflags = IRQF_TRIGGER_RISING; + uint32_t done_mask = 0; + + for (id = 0; id < CE_COUNT_MAX; id++) { + if ((mask & (1 << id)) && hif_ce_state->tasklets[id].inited) { + ret = icnss_ce_request_irq(id, ce_irq_handler, + irqflags, ce_name[id], + &hif_ce_state->tasklets[id]); + if (ret) { + HIF_ERROR( + "%s: cannot register CE %d irq handler, ret = %d", + __func__, id, ret); + ce_unregister_irq(hif_ce_state, done_mask); + return CDF_STATUS_E_FAULT; + } else { + done_mask |= 1 << id; + } + } + } + +#ifndef HIF_PCI + /* move to hif_configure_irq */ + ce_enable_irq_in_group_reg(hif_ce_state->scn, done_mask); +#endif + + return CDF_STATUS_SUCCESS; +} diff --git a/core/hif/src/ce/ce_tasklet.h b/core/hif/src/ce/ce_tasklet.h new file mode 100644 index 000000000000..c4147709c8cb --- /dev/null +++ b/core/hif/src/ce/ce_tasklet.h @@ -0,0 +1,35 @@ +/* + * 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 __CE_TASKLET_H__ +#define __CE_TASKLET_H__ +void init_tasklet_workers(void); +void ce_tasklet_init(struct HIF_CE_state *hif_ce_state, uint32_t mask); +void ce_tasklet_kill(struct HIF_CE_state *hif_ce_state); +CDF_STATUS ce_register_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask); +CDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask); +#endif /* __CE_TASKLET_H__ */ diff --git a/core/hif/src/hif_debug.h b/core/hif/src/hif_debug.h new file mode 100644 index 000000000000..4ab7d1f8e05f --- /dev/null +++ b/core/hif/src/hif_debug.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef __HIF_DEBUG_H__ +#define __HIF_DEBUG_H__ +#include "cdf_trace.h" + +#define HIF_ERROR(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_ERROR, ## args) +#define HIF_WARN(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_WARN, ## args) +#define HIF_INFO(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_INFO, ## args) +#define HIF_INFO_HI(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_INFO_HIGH, ## args) +#define HIF_INFO_MED(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_INFO_MED, ## args) +#define HIF_INFO_LO(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_INFO_LOW, ## args) +#define HIF_TRACE(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_ERROR, ## args) +#define HIF_DBG(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_DEBUG, ## args) +#endif /* __HIF_DEBUG_H__ */ diff --git a/core/hif/src/hif_hw_version.h b/core/hif/src/hif_hw_version.h new file mode 100644 index 000000000000..d5d76dc05942 --- /dev/null +++ b/core/hif/src/hif_hw_version.h @@ -0,0 +1,93 @@ +/* + * 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 HIF_HW_VERSION_H +#define HIF_HW_VERSION_H + +#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 AR6320_REV3_2_VERSION 0x5030000 + +struct qwlan_hw { + u32 id; + u32 subid; + const char *name; +}; + +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 = "AR6320_REV3_2_VERSION", + } +}; + +#endif /* HIF_HW_VERSION_H */ diff --git a/core/hif/src/hif_io32.h b/core/hif/src/hif_io32.h new file mode 100644 index 000000000000..d711ff719f02 --- /dev/null +++ b/core/hif/src/hif_io32.h @@ -0,0 +1,39 @@ +/* + * 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 __HIF_IO32_H__ +#define __HIF_IO32_H__ + +#include +#include "ol_if_athvar.h" +#include "hif.h" +#ifdef HIF_PCI +#include "hif_io32_pci.h" +#else +#include "hif_io32_snoc.h" +#endif /* HIF_PCI */ +#endif /* __HIF_IO32_H__ */ diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c new file mode 100644 index 000000000000..bbfde23c236b --- /dev/null +++ b/core/hif/src/hif_main.c @@ -0,0 +1,894 @@ +/* + * 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. + */ + +#include +#include "a_types.h" +#include "athdefs.h" +#include "osapi_linux.h" +#include "targcfg.h" +#include "cdf_lock.h" +#include "cdf_status.h" +#include /* cdf_atomic_read */ +#include +#include +#include "hif_io32.h" +#include +#include +#include "regtable.h" +#define ATH_MODULE_NAME hif +#include +#include "hif_main.h" +#include "hif_hw_version.h" +#include "ce_api.h" +#include "ce_tasklet.h" +#include "cdf_trace.h" +#include "cdf_status.h" +#include "cds_api.h" +#ifdef CONFIG_CNSS +#include +#endif +#include +#include "epping_main.h" +#include "hif_debug.h" +#include "mp_dev.h" +#ifdef HIF_PCI +#include "icnss_stub.h" +#else +#include +#endif + +#ifndef REMOVE_PKT_LOG +#include "pktlog_ac.h" +#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 + +void hif_dump(struct ol_softc *scn, uint8_t cmd_id, bool start) +{ + switch (cmd_id) { + case AGC_DUMP: + if (start) + priv_start_agc(scn); + else + priv_dump_agc(scn); + break; + + case CHANINFO_DUMP: + if (start) + priv_start_cap_chaninfo(scn); + else + priv_dump_chaninfo(scn); + break; + + case BB_WATCHDOG_DUMP: + priv_dump_bbwatchdog(scn); + break; + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + case PCIE_ACCESS_DUMP: + hif_target_dump_access_log(); + break; +#endif + default: + HIF_ERROR("%s: Invalid htc dump command", __func__); + break; + } +} + +/** + * hif_shut_down_device() - hif_shut_down_device + * + * SThis fucntion shuts down the device + * + * @scn: ol_softc + * + * Return: void + */ +void hif_shut_down_device(struct ol_softc *scn) +{ + if (scn && scn->hif_hdl) { + struct HIF_CE_state *hif_state = + (struct HIF_CE_state *)scn->hif_hdl; + + hif_stop(scn); + cdf_mem_free(hif_state); + scn->hif_hdl = NULL; + } + +} + + + +/** + * hif_cancel_deferred_target_sleep() - cancel deferred target sleep + * + * This function cancels the defered target sleep + * + * @scn: ol_softc + * + * Return: void + */ +void hif_cancel_deferred_target_sleep(struct ol_softc *scn) +{ + hif_pci_cancel_deferred_target_sleep(scn); +} + +/** + * hif_get_target_id(): hif_get_target_id + * + * Return the virtual memory base address to the caller + * + * @scn: ol_softc + * + * Return: A_target_id_t + */ +A_target_id_t hif_get_target_id(struct ol_softc *scn) +{ + return scn->mem; +} + +/** + * hif_set_target_sleep(): hif_set_target_sleep + * @scn: scn + * @sleep_ok: sleep_ok + * @wait_for_it: wait + * + * Return: void + */ +void hif_set_target_sleep(struct ol_softc *scn, + bool sleep_ok, bool wait_for_it) +{ + hif_target_sleep_state_adjust(scn, + sleep_ok, wait_for_it); +} + +/** + * hif_target_forced_awake(): hif_target_forced_awake + * @scn: scn + * + * Return: bool + */ +bool hif_target_forced_awake(struct ol_softc *scn) +{ + A_target_id_t addr = scn->mem; + bool awake; + bool forced_awake; + + awake = hif_targ_is_awake(scn, addr); + + forced_awake = + !!(hif_read32_mb + (addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS) & PCIE_SOC_WAKE_V_MASK); + + return awake && forced_awake; +} + +/** + * hif_fw_interrupt_handler(): FW interrupt handler + * + * This function is the FW interrupt handlder + * + * @irq: irq number + * @arg: the user pointer + * + * Return: bool + */ +#ifndef QCA_WIFI_3_0 +irqreturn_t hif_fw_interrupt_handler(int irq, void *arg) +{ + struct ol_softc *scn = arg; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + uint32_t fw_indicator_address, fw_indicator; + + A_TARGET_ACCESS_BEGIN_RET(scn); + + fw_indicator_address = hif_state->fw_indicator_address; + /* For sudden unplug this will return ~0 */ + fw_indicator = A_TARGET_READ(scn, fw_indicator_address); + + if ((fw_indicator != ~0) && (fw_indicator & FW_IND_EVENT_PENDING)) { + /* ACK: clear Target-side pending event */ + A_TARGET_WRITE(scn, fw_indicator_address, + fw_indicator & ~FW_IND_EVENT_PENDING); + A_TARGET_ACCESS_END_RET(scn); + + 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, + ("%s: Early firmware event indicated\n", + __func__)); + } + } else { + A_TARGET_ACCESS_END_RET(scn); + } + + return ATH_ISR_SCHED; +} +#else +irqreturn_t hif_fw_interrupt_handler(int irq, void *arg) +{ + return ATH_ISR_SCHED; +} +#endif /* #ifdef QCA_WIFI_3_0 */ + +/** + * hif_get_targetdef(): hif_get_targetdef + * @scn: scn + * + * Return: void * + */ +void *hif_get_targetdef(struct ol_softc *scn) +{ + return scn->targetdef; +} + +/** + * hif_vote_link_down(): unvote for link up + * + * Call hif_vote_link_down to release a previous request made using + * hif_vote_link_up. A hif_vote_link_down call should only be made + * after a corresponding hif_vote_link_up, otherwise you could be + * negating a vote from another source. When no votes are present + * hif will not guarantee the linkstate after hif_bus_suspend. + * + * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread + * and initialization deinitialization sequencences. + * + * Return: n/a + */ +void hif_vote_link_down(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + CDF_BUG(scn); + + scn->linkstate_vote--; + if (scn->linkstate_vote == 0) + hif_bus_prevent_linkdown(false); +} + +/** + * hif_vote_link_up(): vote to prevent bus from suspending + * + * Makes hif guarantee that fw can message the host normally + * durring suspend. + * + * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread + * and initialization deinitialization sequencences. + * + * Return: n/a + */ +void hif_vote_link_up(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + CDF_BUG(scn); + + scn->linkstate_vote++; + if (scn->linkstate_vote == 1) + hif_bus_prevent_linkdown(true); +} + +/** + * hif_can_suspend_link(): query if hif is permitted to suspend the link + * + * Hif will ensure that the link won't be suspended if the upperlayers + * don't want it to. + * + * SYNCHRONIZATION: MC thread is stopped before bus suspend thus + * we don't need extra locking to ensure votes dont change while + * we are in the process of suspending or resuming. + * + * Return: false if hif will guarantee link up durring suspend. + */ +bool hif_can_suspend_link(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + CDF_BUG(scn); + + return scn->linkstate_vote == 0; +} + +/** + * hif_hia_item_address(): hif_hia_item_address + * @target_type: target_type + * @item_offset: item_offset + * + * Return: n/a + */ +uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset) +{ + switch (target_type) { + 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; + case TARGET_TYPE_QCA6180: + return QCA6180_HOST_INTEREST_ADDRESS + item_offset; + case TARGET_TYPE_ADRASTEA: + /* ADRASTEA doesn't have a host interest address */ + ASSERT(0); + return 0; + default: + ASSERT(0); + return 0; + } +} + +/** + * hif_max_num_receives_reached() - check max receive is reached + * @count: unsigned int. + * + * Output check status as bool + * + * Return: bool + */ +bool hif_max_num_receives_reached(unsigned int count) +{ + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + return count > 120; + else + return count > MAX_NUM_OF_RECEIVES; +} + +/** + * init_buffer_count() - initial buffer count + * @maxSize: cdf_size_t + * + * routine to modify the initial buffer count to be allocated on an os + * platform basis. Platform owner will need to modify this as needed + * + * Return: cdf_size_t + */ +cdf_size_t init_buffer_count(cdf_size_t maxSize) +{ + return maxSize; +} + +/** + * hif_init_cdf_ctx(): hif_init_cdf_ctx + * @hif_ctx: hif_ctx + * + * Return: int + */ +int hif_init_cdf_ctx(void *hif_ctx) +{ + cdf_device_t cdf_ctx; + struct ol_softc *scn = (struct ol_softc *)hif_ctx; + + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + if (!cdf_ctx) { + HIF_ERROR("%s: CDF is NULL", __func__); + return -ENOMEM; + } + + cdf_ctx->drv = &scn->aps_osdev; + cdf_ctx->drv_hdl = scn->aps_osdev.bdev; + cdf_ctx->dev = scn->aps_osdev.device; + scn->cdf_dev = cdf_ctx; + return 0; +} + +/** + * hif_deinit_cdf_ctx(): hif_deinit_cdf_ctx + * @hif_ctx: hif_ctx + * + * Return: void + */ +void hif_deinit_cdf_ctx(void *hif_ctx) +{ + struct ol_softc *scn = (struct ol_softc *)hif_ctx; + + if (scn == NULL || !scn->cdf_dev) + return; + scn->cdf_dev = NULL; +} + +/** + * hif_save_htc_htt_config_endpoint(): + * hif_save_htc_htt_config_endpoint + * @htc_endpoint: htc_endpoint + * + * Return: void + */ +void hif_save_htc_htt_config_endpoint(int htc_endpoint) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + + if (!scn) { + HIF_ERROR("%s: error: scn or scn->hif_sc is NULL!", + __func__); + return; + } + + scn->htc_endpoint = htc_endpoint; +} + +/** + * hif_get_hw_name(): get a human readable name for the hardware + * + * Return: human readible name for the underlying wifi hardware. + */ +const char *hif_get_hw_name(struct ol_softc *scn) +{ + int i; + for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) { + if (scn->target_version == qwlan_hw_list[i].id && + scn->target_revision == qwlan_hw_list[i].subid) { + return qwlan_hw_list[i].name; + } + } + + return "Unknown Device"; +} + +/** + * hif_get_hw_info(): hif_get_hw_info + * @scn: scn + * @version: version + * @revision: revision + * + * Return: n/a + */ +void hif_get_hw_info(void *scn, u32 *version, u32 *revision, + const char **target_name) +{ + *version = ((struct ol_softc *)scn)->target_version; + *revision = ((struct ol_softc *)scn)->target_revision; + *target_name = hif_get_hw_name((struct ol_softc *)scn); +} + +/** + * hif_set_fw_info(): set the target_fw_version + * @scn: scn + * @target_fw_version: target_fw_version + * + * Return: n/a + */ +void hif_set_fw_info(void *scn, uint32_t target_fw_version) +{ + ((struct ol_softc *)scn)->target_fw_version = target_fw_version; +} + +/** + * hif_open(): hif_open + * + * Return: scn + */ +CDF_STATUS hif_open(void) +{ + struct ol_softc *scn; + v_CONTEXT_t cds_context; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + cds_context = cds_get_global_context(); + status = cds_alloc_context(cds_context, CDF_MODULE_ID_HIF, + (void **)&scn, sizeof(*scn)); + if (status != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: cannot alloc ol_sc", __func__); + return status; + } + + cdf_mem_zero(scn, sizeof(*scn)); + scn->enableuartprint = 0; + scn->enablefwlog = 0; + scn->max_no_of_peers = 1; + scn->pkt_log_init = false; + cdf_atomic_init(&scn->wow_done); + cdf_atomic_init(&scn->active_tasklet_cnt); + cdf_atomic_init(&scn->link_suspended); + cdf_atomic_init(&scn->tasklet_from_intr); + init_waitqueue_head(&scn->aps_osdev.event_queue); + cdf_spinlock_init(&scn->target_lock); + scn->linkstate_vote = 0; + return status; +} + +/** + * hif_close(): hif_close + * @hif_ctx: hif_ctx + * + * Return: n/a + */ +void hif_close(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + + if (scn == NULL) { + HIF_ERROR("%s: ol_softc is NULL", __func__); + return; + } + + if (scn->athdiag_procfs_inited) { + athdiag_procfs_remove(); + scn->athdiag_procfs_inited = false; + } + + if (scn->hif_hdl) { + cdf_mem_free(scn->hif_hdl); + scn->hif_hdl = NULL; + } + hif_bus_close(scn); + cds_free_context(cds_get_global_context(), + CDF_MODULE_ID_HIF, hif_ctx); +} + +/** + * hif_enable(): hif_enable + * @hif_ctx: hif_ctx + * @dev: dev + * @bdev: bus dev + * @bid: bus ID + * @bus_type: bus type + * @type: enable type + * + * Return: CDF_STATUS + */ +CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, + void *bdev, const hif_bus_id *bid, + enum ath_hal_bus_type bus_type, + enum hif_enable_type type) +{ + CDF_STATUS status; + struct ol_softc *scn = hif_ctx; + + if (scn == NULL) { + HIF_ERROR("%s: hif_ctx = NULL", __func__); + return CDF_STATUS_E_NULL_VALUE; + } + + status = hif_bus_open(scn, bus_type); + if (status != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d", + __func__, status, bus_type); + return status; + } + + status = hif_enable_bus(scn, dev, bdev, bid, type); + if (status != CDF_STATUS_SUCCESS) { + hif_bus_close(scn); + HIF_ERROR("%s: hif_enable_bus error = %d", + __func__, status); + return status; + } + + if (ADRASTEA_BU) + hif_vote_link_up(); + + if (hif_config_ce(scn)) { + HIF_ERROR("%s: Target probe failed.", __func__); + hif_disable_bus(scn->aps_osdev.bdev); + hif_bus_close(scn); + status = CDF_STATUS_E_FAILURE; + return status; + } + /* + * 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. + */ + +#ifdef HIF_PCI + status = hif_configure_irq(scn->hif_sc); + if (status < 0) { + HIF_ERROR("%s: ERROR - configure_IRQ_and_CE failed, status = %d", + __func__, status); + return CDF_STATUS_E_FAILURE; + } +#endif + + scn->hif_init_done = true; + + HIF_TRACE("%s: X OK", __func__); + + return CDF_STATUS_SUCCESS; +} + +/** + * hif_pktlogmod_exit(): hif_pktlogmod_exit + * @scn: scn + * + * Return: n/a + */ +#ifndef REMOVE_PKT_LOG +void hif_pktlogmod_exit(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + + if (scn && cds_get_conparam() != CDF_FTM_MODE && + !WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && scn->pkt_log_init) { + pktlogmod_exit(scn); + scn->pkt_log_init = false; + } +} +#else +void hif_pktlogmod_exit(void *hif_ctx) +{ +} +#endif + +#if ((!defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA)) || defined(CONFIG_ICNSS)) +static inline void cnss_pcie_notify_q6(void) +{ + return; +} +#endif + +/** + * hif_wlan_disable(): call the platform driver to disable wlan + * + * This function passes the con_mode to platform driver to disable + * wlan. + * + * Return: void + */ +void hif_wlan_disable(void) +{ + enum icnss_driver_mode mode; + uint32_t con_mode = cds_get_conparam(); + + switch (con_mode) { + case CDF_FTM_MODE: + mode = ICNSS_FTM; + break; + case CDF_EPPING_MODE: + mode = ICNSS_EPPING; + break; + default: + mode = ICNSS_MISSION; + break; + } + + icnss_wlan_disable(mode); +} + +void hif_disable(void *hif_ctx, enum hif_disable_type type) +{ + struct ol_softc *scn = hif_ctx; + + if (!scn) + return; + + hif_nointrs(scn); + if (scn->hif_init_done == false) + hif_shut_down_device(scn); + else + hif_stop(scn); + + if (ADRASTEA_BU) + hif_vote_link_down(); + + if (scn->aps_osdev.bdev) + hif_disable_bus(scn->aps_osdev.bdev); + + if (IHELIUM_BU) { + cnss_pcie_notify_q6(); + HIF_TRACE("%s: cnss_pcie_notify_q6 done, notice_send= %d", + __func__, scn->notice_send); + } + + hif_wlan_disable(); + + scn->notice_send = false; + + HIF_INFO("%s: X", __func__); +} + + +/** + * hif_crash_shutdown_dump_ce_register(): + * hif_crash_shutdown_dump_ce_register + * @hif_ctx: hif_ctx + * + * Return: n/a + */ +#if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \ +&& defined(HIF_PCI) && defined(DEBUG) + +static void hif_crash_shutdown_dump_ce_register(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + + if (hif_check_soc_status(scn) + || dump_ce_register(scn)) { + return; + } + + dump_ce_debug_register(scn); +} + +/** + * hif_crash_shutdown(): hif_crash_shutdown + * + * This function is called by the platform driver to dump CE registers + * + * @hif_ctx: hif_ctx + * + * Return: n/a + */ +void hif_crash_shutdown(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + struct HIF_CE_state *hif_state; + + if (!scn) + return; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + if (!hif_state) + return; + + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + HIF_INFO_MED("%s: Target is already asserted, ignore!", + __func__); + return; + } + + if (cds_is_load_unload_in_progress()) { + HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__); + return; + } + + cdf_spin_lock_irqsave(&scn->target_lock); + + hif_crash_shutdown_dump_ce_register(hif_ctx); + + if (ol_copy_ramdump(scn)) + goto out; + + HIF_INFO_MED("%s: RAM dump collecting completed!", __func__); + +out: + cdf_spin_unlock_irqrestore(&scn->target_lock); + return; +} +#else +void hif_crash_shutdown(void *hif_ctx) +{ + HIF_INFO_MED("%s: Collecting target RAM dump disabled", + __func__); + return; +} +#endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */ + +#ifdef QCA_WIFI_3_0 +/** + * hif_check_fw_reg(): hif_check_fw_reg + * @scn: scn + * @state: + * + * Return: int + */ +int hif_check_fw_reg(struct ol_softc *scn) +{ + return 0; +} +#endif + +#ifdef IPA_OFFLOAD +/** + * hif_read_phy_mem_base(): hif_read_phy_mem_base + * @scn: scn + * @phy_mem_base: physical mem base + * + * Return: n/a + */ +void hif_read_phy_mem_base(struct ol_softc *scn, cdf_dma_addr_t *phy_mem_base) +{ + *phy_mem_base = scn->mem_pa; +} +#endif /* IPA_OFFLOAD */ + +/** + * hif_get_device_type(): hif_get_device_type + * @device_id: device_id + * @revision_id: revision_id + * @hif_type: returned hif_type + * @target_type: returned target_type + * + * Return: int + */ +int hif_get_device_type(uint32_t device_id, + uint32_t revision_id, + uint32_t *hif_type, uint32_t *target_type) +{ + int ret = 0; + + switch (device_id) { +#ifdef QCA_WIFI_3_0_ADRASTEA + case ADRASTEA_DEVICE_ID: + case ADRASTEA_DEVICE_ID_P2_E12: + + *hif_type = HIF_TYPE_ADRASTEA; + *target_type = TARGET_TYPE_ADRASTEA; + break; +#else + case QCA6180_DEVICE_ID: + *hif_type = HIF_TYPE_QCA6180; + *target_type = TARGET_TYPE_QCA6180; + break; +#endif + + 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: + HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x", + __func__, device_id, revision_id); + ret = -ENODEV; + goto end; + } + break; + + default: + HIF_ERROR("%s: Unsupported device ID!", __func__); + ret = -ENODEV; + break; + } +end: + return ret; +} diff --git a/core/hif/src/hif_main.h b/core/hif/src/hif_main.h new file mode 100644 index 000000000000..5a9c81ca1afa --- /dev/null +++ b/core/hif/src/hif_main.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#ifndef __HIF_MAIN_H__ +#define __HIF_MAIN_H__ + +#include /* cdf_atomic_read */ +#include "cdf_lock.h" +#include "cepci.h" +#include "hif.h" + +#define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 +#define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 + +/* + * 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))) + +A_target_id_t hif_get_target_id(struct ol_softc *scn); +bool hif_target_forced_awake(struct ol_softc *scn); + +#ifdef QCA_WIFI_3_0 +#define DISABLE_L1SS_STATES 1 +#endif +#ifdef CONFIG_SLUB_DEBUG_ON +#define MAX_NUM_OF_RECEIVES 100 /* Maximum number of Rx buf to process before* + * break out in SLUB debug builds */ +#elif defined(FEATURE_NAPI) +#define MAX_NUM_OF_RECEIVES HIF_NAPI_MAX_RECEIVES +#else /* no SLUBS, no NAPI */ +/* Maximum number of Rx buf to process before break out */ +#define MAX_NUM_OF_RECEIVES 1000 +#endif /* SLUB_DEBUG_ON / FEATURE_NAPI */ + +#ifdef QCA_WIFI_3_0_IHELIUM +#define IHELIUM_BU 1 +#else +#define IHELIUM_BU 0 +#endif + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define ADRASTEA_BU 1 +#else +#define ADRASTEA_BU 0 +#endif + +#ifdef QCA_WIFI_3_0 +#define HAS_FW_INDICATOR 0 +#else +#define HAS_FW_INDICATOR 1 +#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) +#define ADRASTEA_DEVICE_ID (0xabcd) +#define ADRASTEA_DEVICE_ID_P2_E12 (0x7021) +#if (defined(QVIT) || defined (QCA_WIFI_3_0_IHELIUM)) +#define QCA6180_DEVICE_ID (0xabcd) +#else +#define QCA6180_DEVICE_ID (0x041) +#endif + +A_target_id_t hif_get_target_id(struct ol_softc *scn); +void hif_dump_pipe_debug_count(struct ol_softc *scn); + +bool hif_max_num_receives_reached(unsigned int count); +int hif_config_ce(hif_handle_t hif_hdl); +int athdiag_procfs_init(void *scn); +void athdiag_procfs_remove(void); +/* routine to modify the initial buffer count to be allocated on an os + * platform basis. Platform owner will need to modify this as needed + */ +cdf_size_t init_buffer_count(cdf_size_t maxSize); + +irqreturn_t hif_fw_interrupt_handler(int irq, void *arg); +int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, + void *bdev, const hif_bus_id *bid, uint32_t *hif_type, + uint32_t *target_type); +int hif_get_device_type(uint32_t device_id, + uint32_t revision_id, + uint32_t *hif_type, uint32_t *target_type); +/*These functions are exposed to HDD*/ +int hif_init_cdf_ctx(void *ol_sc); +void hif_deinit_cdf_ctx(void *ol_sc); +bool hif_targ_is_awake(struct ol_softc *scn, void *__iomem *mem); +void hif_nointrs(struct ol_softc *scn); +void hif_bus_close(struct ol_softc *ol_sc); +CDF_STATUS hif_bus_open(struct ol_softc *ol_sc, + enum ath_hal_bus_type bus_type); +CDF_STATUS hif_enable_bus(struct ol_softc *ol_sc, struct device *dev, + void *bdev, const hif_bus_id *bid, enum hif_enable_type type); +void hif_disable_bus(void *bdev); +void hif_bus_prevent_linkdown(bool flag); + +#endif /* __HIF_MAIN_H__ */ diff --git a/core/hif/src/hif_napi.c b/core/hif/src/hif_napi.c new file mode 100644 index 000000000000..f33fb8747bc3 --- /dev/null +++ b/core/hif/src/hif_napi.c @@ -0,0 +1,444 @@ +/* + * 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: hif_napi.c + * + * HIF NAPI interface implementation + */ + +#include /* memset */ + +#include +#include +#include +#include +#include + +enum napi_decision_vector { + HIF_NAPI_NOEVENT = 0, + HIF_NAPI_INITED = 1, + HIF_NAPI_CONF_UP = 2 +}; +#define ENABLE_NAPI_MASK (HIF_NAPI_INITED | HIF_NAPI_CONF_UP) + +/** + * hif_napi_create() - creates the NAPI structures for a given CE + * @hif : pointer to hif context + * @pipe_id: the CE id on which the instance will be created + * @poll : poll function to be used for this NAPI instance + * @budget : budget to be registered with the NAPI instance + * @scale : scale factor on the weight (to scaler budget to 1000) + * + * Description: + * Creates NAPI instances. This function is called + * unconditionally during initialization. It creates + * napi structures through the proper HTC/HIF calls. + * The structures are disabled on creation. + * Note that for each NAPI instance a separate dummy netdev is used + * + * Return: + * < 0: error + * = 0: + * > 0: id of the created object (for multi-NAPI, number of objects created) + */ +int hif_napi_create(struct ol_softc *hif, + uint8_t pipe_id, + int (*poll)(struct napi_struct *, int), + int budget, + int scale) +{ + struct qca_napi_data *napid; + struct qca_napi_info *napii; + + NAPI_DEBUG("-->(pipe=%d, budget=%d, scale=%d)\n", + pipe_id, budget, scale); + NAPI_DEBUG("hif->napi_data.state = 0x%08x\n", + hif->napi_data.state); + NAPI_DEBUG("hif->napi_data.ce_map = 0x%08x\n", + hif->napi_data.ce_map); + + napid = &(hif->napi_data); + if (0 == (napid->state & HIF_NAPI_INITED)) { + memset(napid, 0, sizeof(struct qca_napi_data)); + mutex_init(&(napid->mutex)); + + init_dummy_netdev(&(napid->netdev)); + + napid->state |= HIF_NAPI_INITED; + HIF_INFO("%s: NAPI structures initialized\n", __func__); + + NAPI_DEBUG("NAPI structures initialized\n"); + } + napii = &(napid->napis[pipe_id]); + memset(napii, 0, sizeof(struct qca_napi_info)); + napii->scale = scale; + napii->id = NAPI_PIPE2ID(pipe_id); + + NAPI_DEBUG("adding napi=%p to netdev=%p (poll=%p, bdgt=%d)\n", + &(napii->napi), &(napid->netdev), poll, budget); + netif_napi_add(&(napid->netdev), &(napii->napi), poll, budget); + + NAPI_DEBUG("after napi_add\n"); + NAPI_DEBUG("napi=0x%p, netdev=0x%p\n", + &(napii->napi), &(napid->netdev)); + NAPI_DEBUG("napi.dev_list.prev=0x%p, next=0x%p\n", + napii->napi.dev_list.prev, napii->napi.dev_list.next); + NAPI_DEBUG("dev.napi_list.prev=0x%p, next=0x%p\n", + napid->netdev.napi_list.prev, napid->netdev.napi_list.next); + + /* It is OK to change the state variable below without protection + as there should be no-one around yet */ + napid->ce_map |= (0x01 << pipe_id); + HIF_INFO("%s: NAPI id %d created for pipe %d\n", __func__, + napii->id, pipe_id); + + NAPI_DEBUG("NAPI id %d created for pipe %d\n", napii->id, pipe_id); + NAPI_DEBUG("<--napi_id=%d]\n", napii->id); + return napii->id; +} + +/** + * + * hif_napi_destroy() - destroys the NAPI structures for a given instance + * @hif : pointer to hif context + * @ce_id : the CE id whose napi instance will be destroyed + * @force : if set, will destroy even if entry is active (de-activates) + * + * Description: + * Destroy a given NAPI instance. This function is called + * unconditionally during cleanup. + * Refuses to destroy an entry of it is still enabled (unless force=1) + * Marks the whole napi_data invalid if all instances are destroyed. + * + * Return: + * -EINVAL: specific entry has not been created + * -EPERM : specific entry is still active + * 0 < : error + * 0 = : success + */ +int hif_napi_destroy(struct ol_softc *hif, + uint8_t id, + int force) +{ + uint8_t ce = NAPI_ID2PIPE(id); + int rc = 0; + + NAPI_DEBUG("-->(id=%d, force=%d)\n", id, force); + + if (0 == (hif->napi_data.state & HIF_NAPI_INITED)) { + HIF_ERROR("%s: NAPI not initialized or entry %d not created\n", + __func__, id); + rc = -EINVAL; + } else if (0 == (hif->napi_data.ce_map & (0x01 << ce))) { + HIF_ERROR("%s: NAPI instance %d (pipe %d) not created\n", + __func__, id, ce); + rc = -EINVAL; + } else { + struct qca_napi_data *napid; + struct qca_napi_info *napii; + napid = &(hif->napi_data); + napii = &(napid->napis[ce]); + + if (hif->napi_data.state == HIF_NAPI_CONF_UP) { + if (force) { + napi_disable(&(napii->napi)); + HIF_INFO("%s: NAPI entry %d force disabled\n", + __func__, id); + NAPI_DEBUG("NAPI %d force disabled\n", id); + } else { + HIF_ERROR("%s: Cannot destroy active NAPI %d\n", + __func__, id); + rc = -EPERM; + } + } + if (0 == rc) { + NAPI_DEBUG("before napi_del\n"); + NAPI_DEBUG("napi.dlist.prv=0x%p, next=0x%p\n", + napii->napi.dev_list.prev, + napii->napi.dev_list.next); + NAPI_DEBUG("dev.napi_l.prv=0x%p, next=0x%p\n", + napid->netdev.napi_list.prev, + napid->netdev.napi_list.next); + + netif_napi_del(&(napii->napi)); + + napid->ce_map &= ~(0x01 << ce); + napii->scale = 0; + HIF_INFO("%s: NAPI %d destroyed\n", __func__, id); + + /* if there are no active instances and + if they are all destroyed, + set the whole structure to uninitialized state */ + if (napid->ce_map == 0) { + /* hif->napi_data.state = 0; */ + memset(napid, + 0, sizeof(struct qca_napi_data)); + HIF_INFO("%s: no NAPI instances. Zapped.\n", + __func__); + } + } + } + + return rc; +} + +/** + * + * hif_napi_get_all() - returns the address of the whole HIF NAPI structure + * @hif: pointer to hif context + * + * Description: + * Returns the address of the whole structure + * + * Return: + * : address of the whole HIF NAPI structure + */ +inline struct qca_napi_data *hif_napi_get_all(struct ol_softc *hif) +{ + return &(hif->napi_data); +} + +/** + * + * hif_napi_event() - Decision-maker to enable/disable NAPI. + * @hif : pointer to hif context + * @evnt: event that has been detected + * @data: more data regarding the event + * + * Description: + * This function decides whether or not NAPI should be enabled. + * NAPI will be enabled, if all the following is satisfied. + * 1- has been enabled administratively: + * the .ini file has the enabled setting and it has not been disabled + * by an vendor command override later + * + * Return: + * < 0: some error + * = 0: NAPI is now disabled + * = 1: NAPI is now enabled + */ +int hif_napi_event(struct ol_softc *hif, enum qca_napi_event event, void *data) +{ + int rc; + uint32_t prev_state; + int i; + struct napi_struct *napi; + + NAPI_DEBUG("-->(event=%d, aux=%p)\n", event, data); + + mutex_lock(&(hif->napi_data.mutex)); + prev_state = hif->napi_data.state; + switch (event) { + case NAPI_EVT_INI_FILE: + case NAPI_EVT_CMD_STATE: { + int on = (data != ((void *)0)); + HIF_INFO("%s: received evnt: CONF %s; v = %d (state=0x%0x)\n", + __func__, + (event == NAPI_EVT_INI_FILE)?".ini file":"cmd", + on, prev_state); + if (on) + if (prev_state & HIF_NAPI_CONF_UP) { + HIF_INFO("%s: duplicate NAPI conf ON msg\n", + __func__); + } else { + HIF_INFO("%s: setting configuration to ON\n", + __func__); + hif->napi_data.state |= HIF_NAPI_CONF_UP; + } + else /* off request */ + if (prev_state & HIF_NAPI_CONF_UP) { + HIF_INFO("%s: setting configuration to OFF\n", + __func__); + hif->napi_data.state &= ~HIF_NAPI_CONF_UP; + } else { + HIF_INFO("%s: duplicate NAPI conf OFF msg\n", + __func__); + } + break; + } + /* case NAPI_INIT_FILE/CMD_STATE */ + default: { + HIF_ERROR("%s: unknown event: %d (data=0x%0lx)\n", + __func__, event, (unsigned long) data); + break; + } /* default */ + }; /* switch */ + + + mutex_unlock(&(hif->napi_data.mutex)); + + if (prev_state != hif->napi_data.state) { + if (hif->napi_data.state == ENABLE_NAPI_MASK) { + rc = 1; + for (i = 0; i < CE_COUNT_MAX; i++) + if ((hif->napi_data.ce_map & (0x01 << i))) { + napi = &(hif->napi_data.napis[i].napi); + NAPI_DEBUG("enabling NAPI %d\n", i); + napi_enable(napi); + } + } else { + rc = 0; + for (i = 0; i < CE_COUNT_MAX; i++) + if (hif->napi_data.ce_map & (0x01 << i)) { + napi = &(hif->napi_data.napis[i].napi); + NAPI_DEBUG("disabling NAPI %d\n", i); + napi_disable(napi); + } + } + } else { + HIF_INFO("%s: no change in hif napi state (still %d)\n", + __func__, prev_state); + rc = (hif->napi_data.state == ENABLE_NAPI_MASK); + } + + NAPI_DEBUG("<--[rc=%d]\n", rc); + return rc; +} + +/** + * hif_napi_enabled() - checks whether NAPI is enabled for given ce or not + * @hif: hif context + * @ce : CE instance (or -1, to check if any CEs are enabled) + * + * Return: bool + */ +inline int hif_napi_enabled(struct ol_softc *hif, int ce) +{ + int rc; + if (-1 == ce) + rc = ((hif->napi_data.state == ENABLE_NAPI_MASK)); + else + rc = ((hif->napi_data.state == ENABLE_NAPI_MASK) && + (hif->napi_data.ce_map & (0x01 << ce))); + return rc; +}; + +/** + * hif_napi_enable_irq() - enables bus interrupts after napi_complete + * + * @hif: hif context + * @id : id of NAPI instance calling this (used to determine the CE) + * + * Return: void + */ +inline void hif_napi_enable_irq(struct ol_softc *hif, int id) +{ + ce_irq_enable(hif, NAPI_ID2PIPE(id)); + return; +} + + +/** + * hif_napi_schedule() - schedules napi, updates stats + * @scn: hif context + * @ce_id: index of napi instance + * + * Return: void + */ +int hif_napi_schedule(struct ol_softc *scn, int ce_id) +{ + int cpu = smp_processor_id(); + + scn->napi_data.napis[ce_id].stats[cpu].napi_schedules++; + NAPI_DEBUG("scheduling napi %d (ce:%d)\n", + scn->napi_data.napis[ce_id].id, ce_id); + napi_schedule(&(scn->napi_data.napis[ce_id].napi)); + + return true; +} + +/** + * hif_napi_poll() - NAPI poll routine + * @napi : pointer to NAPI struct as kernel holds it + * @budget: + * + * This is the body of the poll function. + * The poll function is called by kernel. So, there is a wrapper + * function in HDD, which in turn calls this function. + * Two main reasons why the whole thing is not implemented in HDD: + * a) references to things like ce_service that HDD is not aware of + * b) proximity to the implementation of ce_tasklet, which the body + * of this function should be very close to. + * + * NOTE TO THE MAINTAINER: + * Consider this function and ce_tasklet very tightly coupled pairs. + * Any changes to ce_tasklet or this function may likely need to be + * reflected in the counterpart. + * + * Returns: + * int: the amount of work done in this poll ( <= budget) + */ +int hif_napi_poll(struct napi_struct *napi, int budget) +{ + int rc, normalized, bucket; + int cpu = smp_processor_id(); + struct ol_softc *hif; + struct qca_napi_info *napi_info; + + NAPI_DEBUG("%s -->(.., budget=%d)\n", budget); + + napi_info = (struct qca_napi_info *) + container_of(napi, struct qca_napi_info, napi); + napi_info->stats[cpu].napi_polls++; + + hif = (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + CDF_ASSERT(hif != NULL); + rc = ce_per_engine_service(hif, NAPI_ID2PIPE(napi_info->id)); + HIF_INFO_HI("%s: ce_per_engine_service reports %d msgs processed", + __func__, rc); + napi_info->stats[cpu].napi_workdone += rc; + normalized = (rc / napi_info->scale); + /* do not return 0, if there was some work done, + even if it is below the scale */ + if (rc) + normalized++; + bucket = (normalized / QCA_NAPI_DEF_SCALE); + napi_info->stats[cpu].napi_budget_uses[bucket]++; + + /* if ce_per engine reports 0, then we should make sure + poll is terminated */ + if (0 == rc) + NAPI_DEBUG("%s:%d: nothing processed by CE. Completing NAPI\n", + __func__, __LINE__); + + if (rc <= HIF_NAPI_MAX_RECEIVES) { + napi_info->stats[cpu].napi_completes++; + /* enable interrupts */ + napi_complete(napi); + hif_napi_enable_irq(hif, napi_info->id); + + /* support suspend/resume */ + cdf_atomic_dec(&(hif->active_tasklet_cnt)); + + NAPI_DEBUG("%s:%d: napi_complete + enabling the interrupts\n", + __func__, __LINE__); + } + + NAPI_DEBUG("%s <--[normalized=%d]\n", _func__, normalized); + return normalized; +} diff --git a/core/hif/src/icnss_stub/icnss_stub.c b/core/hif/src/icnss_stub/icnss_stub.c new file mode 100644 index 000000000000..956b4569406d --- /dev/null +++ b/core/hif/src/icnss_stub/icnss_stub.c @@ -0,0 +1,342 @@ +/* + * 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. + */ + +#ifdef HIF_PCI + +#include "icnss_stub.h" +#include "hif_io32.h" +#include +#include "regtable.h" +#include "hif_debug.h" +#include "cds_api.h" +#include "cdf_status.h" +#include "qwlan_version.h" +#include + +static int icnss_get_irq_num(int ce_id); + +/** + * struct icnss_stub_entry + * + * @irq_handler: irq_handler + * @data: data + * @name: name + * @ce_id: ce_id + */ +struct icnss_stub_entry { + irqreturn_t (*irq_handler)(int, void *); + void *data; + const char *name; + int ce_id; +}; + +/** + * struct icnss_stub_context + * + * @stub: icnss_stub_entry + * @regged_irq: regged_irq + */ +struct icnss_stub_context { + struct icnss_stub_entry stub[ICNSS_MAX_IRQ_REGISTRATIONS]; + uint32_t regged_irq; +}; + +static struct icnss_stub_context cnss_stub; + +#ifndef QCA_WIFI_3_0_ADRASTEA +/** + * icnss_wlan_enable() - icnss_wlan_enable + * @config: ce configuration information + * @mode: driver_mode + * @host_version: version string to send to the fw + * + * Return: int + */ +int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config, + enum icnss_driver_mode mode, const char *host_version) +{ + return 0; +} + +/** + * icnss_wlan_disable() - icnss_wlan_disable + * @mode: driver_mode + * + * Return: int + */ +int icnss_wlan_disable(enum icnss_driver_mode mode) +{ + return 0; +} + +#else + +/** + * icnss_wlan_enable(): call the platform driver to enable wlan + * @config: ce configuration information + * @mode: driver_mode + * @host_version: version string to send to the fw + * + * This function passes the con_mode and CE configuration to + * platform driver to enable wlan. + * cnss_wlan_enable has been hacked to do a qmi handshake with fw. + * this is not needed for rome. + * + * Return: 0 on success, error number otherwise. + */ +int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config, + enum icnss_driver_mode mode, const char *host_version) +{ + struct cnss_wlan_enable_cfg cfg; + enum cnss_driver_mode cnss_mode; + + cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg; + cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *) + config->ce_tgt_cfg; + cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg; + cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *) + config->ce_svc_cfg; + + cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg; + cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *) + config->shadow_reg_cfg; + + switch (mode) { + case ICNSS_FTM: + cnss_mode = CNSS_FTM; + break; + case ICNSS_EPPING: + cnss_mode = CNSS_EPPING; + break; + default: + cnss_mode = CNSS_MISSION; + break; + } + return cnss_wlan_enable(&cfg, cnss_mode, host_version); +} + +/** + * icnss_wlan_disable(): call the platform driver to disable wlan + * + * This function passes the con_mode to platform driver to disable wlan. + * cnss_wlan_disable has been hacked to do a qmi handshake with fw. + * this is not needed for rome. + * + * Return: void + */ +int icnss_wlan_disable(enum icnss_driver_mode con_mode) +{ + enum cnss_driver_mode mode; + + switch (con_mode) { + case ICNSS_FTM: + mode = CNSS_FTM; + break; + case ICNSS_EPPING: + mode = CNSS_EPPING; + break; + default: + mode = CNSS_MISSION; + break; + } + + cnss_wlan_disable(mode); + return 0; +} +#endif + +/** + * icnss_ce_request_irq() - register an irq handler + * @ce_id: ce_id + * @handler: handler + * @flags: flags to pass to the kernel api + * @name: name + * @context: context to pass to the irq handler + * + * Return: integer status + */ +int icnss_ce_request_irq(int ce_id, + irqreturn_t (*handler)(int, void *), + unsigned long flags, const char *name, + void *context) +{ + if (ce_id >= ICNSS_MAX_IRQ_REGISTRATIONS) { + HIF_ERROR("%s: invalid ce_id = %d", __func__, ce_id); + return -EINVAL; + } + + cnss_stub.stub[ce_id].irq_handler = handler; + cnss_stub.stub[ce_id].ce_id = ce_id; + cnss_stub.stub[ce_id].data = context; + cnss_stub.stub[ce_id].name = name; + cnss_stub.regged_irq |= (1 << ce_id); + return 0; +} + +/** + * icnss_ce_free_irq() - icnss_unregister_irq + * @ce_id: the ce_id that the irq belongs to + * @context: context with witch the irq was requested. + * Return: integer status + */ +int icnss_ce_free_irq(int ce_id, void *context) +{ + if (ce_id >= ICNSS_MAX_IRQ_REGISTRATIONS) { + HIF_ERROR("%s: invalid ce_id = %d", __func__, ce_id); + return -EINVAL; + } + + if (cnss_stub.stub[ce_id].data != context) { + HIF_ERROR("%s: context match failure for ce_id %d", + __func__, ce_id); + return -EINVAL; + } + + if (cnss_stub.regged_irq & (1 << ce_id)) { + cnss_stub.stub[ce_id].irq_handler = NULL; + cnss_stub.stub[ce_id].ce_id = 0; + cnss_stub.stub[ce_id].data = 0; + cnss_stub.stub[ce_id].name = NULL; + cnss_stub.regged_irq &= ~(1 << ce_id); + } + return 0; +} + +/** + * icnss_dispatch_one_ce_irq() - icnss_dispatch_one_ce_irq + * @ce_id: ce_id + * + * Return: irqreturn_t + */ +static irqreturn_t icnss_dispatch_one_ce_irq(int ce_id) +{ + irqreturn_t ret = IRQ_NONE; + + if (cnss_stub.stub[ce_id].irq_handler) + ret = cnss_stub.stub[ce_id].irq_handler( + icnss_get_irq_num(ce_id), + (void *)cnss_stub.stub[ce_id].data); + else + HIF_ERROR( + "%sd: error - ce_id = %d, no IRQ handler", + __func__, ce_id); + + return ret; +} + +/** + * icnss_dispatch_ce_irq() - icnss_dispatch_ce_irq + * @scn: scn + * + * Return: N/A + */ +void icnss_dispatch_ce_irq(struct ol_softc *scn) +{ + uint32_t intr_summary; + int id; + irqreturn_t ret; + + if (scn->hif_init_done != true) + return; + + A_TARGET_ACCESS_BEGIN(scn); + intr_summary = CE_INTERRUPT_SUMMARY(scn); + + if (intr_summary == 0) { + if ((scn->target_status != OL_TRGET_STATUS_RESET) && + (!cdf_atomic_read(&scn->link_suspended))) { + + hif_write32_mb(scn->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + HOST_GROUP0_MASK); + + hif_read32_mb(scn->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + } + A_TARGET_ACCESS_END(scn); + return; + } else { + A_TARGET_ACCESS_END(scn); + } + + scn->ce_irq_summary = intr_summary; + for (id = 0; intr_summary && (id < scn->ce_count); id++) { + if (intr_summary & (1 << id)) { + intr_summary &= ~(1 << id); + ret = icnss_dispatch_one_ce_irq(id); + } + } +} + +/** + * icnss_get_soc_info() - get soc info + * + * This function query the soc information from the platform + * driver + * + * @info: struct icnss_soc_info + * + * Return: 0 for success + */ +int icnss_get_soc_info(struct icnss_soc_info *info) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + + if (!scn) { + HIF_ERROR("%s: SCN = NULL", __func__); + return -EINVAL; + } + info->v_addr = scn->mem; + info->p_addr = scn->mem_pa; + info->version = 0; + return 0; +} + + +/* icnss_get_irq_num() - generate a number to represent an irq number +*/ +static int icnss_get_irq_num(int ce_id) +{ + if (ce_id <= ICNSS_MAX_IRQ_REGISTRATIONS && ce_id >= 0) + return ce_id + 100; + + pr_err("icnss: No irq registered for CE id %d\n", ce_id); + return -EINVAL; +} + +int icnss_get_ce_id(int irq) +{ + int ce_id = irq - 100; + if (ce_id <= ICNSS_MAX_IRQ_REGISTRATIONS && ce_id >= 0) + return ce_id; + + pr_err("icnss: No matching CE id for irq %d\n", irq); + return -EINVAL; +} +#endif /* HIF_PCI */ diff --git a/core/hif/src/icnss_stub/icnss_stub.h b/core/hif/src/icnss_stub/icnss_stub.h new file mode 100644 index 000000000000..bce229a2dbdf --- /dev/null +++ b/core/hif/src/icnss_stub/icnss_stub.h @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#ifdef HIF_PCI +#ifndef _ICNSS_WLAN_H_ +#define _ICNSS_WLAN_H_ + +#include +#include +#include + +#define ICNSS_MAX_IRQ_REGISTRATIONS 12 + +/** + * struct ce_tgt_pipe_cfg + * + * @pipenum: pipe_num + * @pipedir: pipe_dir + * @nentries: nentries + * @nbytes_max: nbytes_max + * @flags: flags + * @reserved: reserved + */ +struct ce_tgt_pipe_cfg { + uint32_t pipe_num; + uint32_t pipe_dir; + uint32_t nentries; + uint32_t nbytes_max; + uint32_t flags; + uint32_t reserved; +}; + +/** + * struct ce_svc_pipe_cfg + * + * @service_id: service_id + * @pipedir: pipedir + * @pipenum: pipenum + */ +struct ce_svc_pipe_cfg { + uint32_t service_id; + uint32_t pipedir; + uint32_t pipenum; +}; + +/** + * struct icnss_shadow_reg_cfg + * + * @ce_id: Copy engine id + * @reg_offset: Register offset + */ +struct icnss_shadow_reg_cfg { + u16 ce_id; + u16 reg_offset; +}; +/** + * struct icnss_wlan_enable_cfg + * + * @num_ce_tgt_cfg: num_ce_tgt_cfg + * @ce_tgt_cfg: ce_tgt_cfg + * @num_ce_svc_pipe_cfg: num_ce_svc_pipe_cfg + * @ce_svc_cfg: ce_svc_cfg + */ +struct icnss_wlan_enable_cfg { + uint32_t num_ce_tgt_cfg; + struct ce_tgt_pipe_cfg *ce_tgt_cfg; + uint32_t num_ce_svc_pipe_cfg; + struct ce_svc_pipe_cfg *ce_svc_cfg; + u32 num_shadow_reg_cfg; + struct icnss_shadow_reg_cfg *shadow_reg_cfg; +}; + +/** + * enum driver_mode + * + * @driver_mode: driver_mode + */ +enum icnss_driver_mode { + ICNSS_MISSION, + ICNSS_FTM, + ICNSS_EPPING, +}; + +/** + * struct icnss_soc_info + * + * @v_addr: virtual address + * @p_addr: physical address + * @ver: version + */ +struct icnss_soc_info { + void __iomem *v_addr; + phys_addr_t p_addr; + uint32_t version; +}; + +int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config, + enum icnss_driver_mode mode, const char *host_version); +int icnss_wlan_disable(enum icnss_driver_mode mode); +int icnss_ce_request_irq(int ce_id, + irqreturn_t (*handler)(int ce_id, void *arg), + unsigned long flags, const char *name, void *context); +int icnss_ce_free_irq(int irq, void *context); +void icnss_enable_irq(unsigned int ce_id); +void icnss_disable_irq(unsigned int ce_id); +int icnss_get_soc_info(struct icnss_soc_info *info); +int icnss_get_ce_id(int irq); +#endif /* _ICNSS_WLAN_H_ */ +#endif /* HIF_PCI */ + diff --git a/core/hif/src/mp_dev.c b/core/hif/src/mp_dev.c new file mode 100644 index 000000000000..276e60ae1ab1 --- /dev/null +++ b/core/hif/src/mp_dev.c @@ -0,0 +1,310 @@ +/* + * 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 "hif_io32.h" +#include "hif_debug.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 + +struct priv_ctrl_ctx { + uint32_t chaninfo_ctrl_orig; + uint32_t gain_min_offsets_orig; + uint32_t anyreg_start; + uint32_t anyreg_len; +}; + +static struct priv_ctrl_ctx g_priv_dump_ctx; + +static INLINE void set_target_reg_bits(void __iomem *mem, uint32_t reg, + uint32_t bitmask, uint32_t val) +{ + uint32_t value = hif_read32_mb(mem + (reg)); + uint32_t shift = 0; + value &= ~(bitmask); + while (!((bitmask >> shift) & 0x01)) + shift++; + + value |= (((val) << shift) & (bitmask)); + hif_write32_mb(mem + (reg), value); +} + +static INLINE uint32_t get_target_reg_bits(void __iomem *mem, + uint32_t reg, uint32_t bitmask) +{ + uint32_t value = hif_read32_mb(mem + (reg)); + uint32_t shift = 0; + while (!((bitmask >> shift) & 0x01)) + shift++; + + return (value >> shift) & bitmask; +} + +void priv_start_cap_chaninfo(struct ol_softc *scn) +{ + set_target_reg_bits(scn->mem, BB_chaninfo_ctrl, + CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK, 1); +} + +void priv_start_agc(struct ol_softc *scn) +{ + g_priv_dump_ctx.gain_min_offsets_orig = + hif_read32_mb(scn->mem + BB_gains_min_offsets); + set_target_reg_bits(scn->mem, BB_gains_min_offsets, + AGC_HISTORY_DUMP_MASK, + 0x0f); +} + +void priv_stop_agc(struct ol_softc *scn) +{ + set_target_reg_bits(scn->mem, BB_gains_min_offsets, + AGC_HISTORY_DUMP_MASK, + 0); +} + +void priv_dump_chaninfo(struct ol_softc *scn) +{ + uint32_t bw, val; + uint32_t len, i, tmp; + uint32_t chain_mask; + uint32_t chain0, chain1; + + chain_mask = + get_target_reg_bits(scn->mem, BB_multichain_enable, + MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK); + chain0 = chain_mask & 1; + chain1 = chain_mask & 2; + + HIF_TRACE("%s: E", __func__); + bw = get_target_reg_bits(scn->mem, 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) { + hif_write32_mb(scn->mem + BB_chn_tables_intf_addr, + 0x80003200); + } + if (chain1) { + hif_write32_mb(scn->mem + BB_chn1_tables_intf_addr, + 0x80003200); + } + + set_target_reg_bits(scn->mem, BB_chaninfo_ctrl, + CHANINFOMEM_S2_READ_MASK, 0); + + if (chain0) { + if (bw < 2) { + len = (bw == 0) ? 53 : 57; + for (i = 0; i < len; i++) { + val = + hif_read32_mb(scn->mem + + BB_chn_tables_intf_data) & + 0x0000ffff; + cdf_print("0x%x\t", val); + if (i % 4 == 0) + cdf_print("\n"); + } + } else { + len = (bw == 2) ? 59 : 60; + for (i = 0; i < len; i++) { + tmp = + hif_read32_mb(scn->mem + + BB_chn_tables_intf_data); + cdf_print("0x%x\t", ((tmp >> 16) & 0x0000ffff)); + cdf_print("0x%x\t", (tmp & 0x0000ffff)); + if (i % 2 == 0) + cdf_print("\n"); + } + if (bw > 2) { + /* bw == 3 for vht80 */ + hif_write32_mb(scn->mem + + BB_chn_tables_intf_addr, + 0x80003300); + len = 61; + for (i = 0; i < len; i++) { + tmp = + hif_read32_mb(scn->mem + + BB_chn_tables_intf_data); + cdf_print("0x%x\t", + ((tmp >> 16) & 0x0000ffff)); + cdf_print("0x%x\t", (tmp & 0x0000ffff)); + if (i % 2 == 0) + cdf_print("\n"); + } + } + } + } + if (chain1) { + if (bw < 2) { + len = (bw == 0) ? 53 : 57; + for (i = 0; i < len; i++) { + val = + hif_read32_mb(scn->mem + + BB_chn1_tables_intf_data) & + 0x0000ffff; + cdf_print("0x%x\t", val); + if (i % 4 == 0) + cdf_print("\n"); + } + } else { + len = (bw == 2) ? 59 : 60; + for (i = 0; i < len; i++) { + tmp = + hif_read32_mb(scn->mem + + BB_chn1_tables_intf_data); + cdf_print("0x%x\n", (tmp >> 16) & 0x0000ffff); + cdf_print("0x%x\n", tmp & 0x0000ffff); + if (i % 2 == 0) + cdf_print("\n"); + } + if (bw > 2) { + /* bw == 3 for vht80 */ + hif_write32_mb(scn->mem + + BB_chn1_tables_intf_addr, + 0x80003300); + len = 61; + for (i = 0; i < len; i++) { + tmp = + hif_read32_mb(scn->mem + + BB_chn1_tables_intf_data); + cdf_print("0x%x\t", + ((tmp >> 16) & 0x0000ffff)); + cdf_print("0x%x\t", (tmp & 0x0000ffff)); + if (i % 2 == 0) + cdf_print("\n"); + } + } + } + } + HIF_TRACE("%s: X", __func__); +} + +void priv_dump_agc(struct ol_softc *scn) +{ + int i, len = 30; /* check this value for Rome and Peregrine */ + uint32_t chain0, chain1, chain_mask, val; + + chain_mask = + get_target_reg_bits(scn->mem, 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(scn); + + set_target_reg_bits(scn->mem, BB_chaninfo_ctrl, + CHANINFOMEM_S2_READ_MASK, 0); + + HIF_TRACE("%s: AGC history buffer dump: E", __func__); + if (chain0) { + for (i = 0; i < len; i++) { + val = + hif_read32_mb(scn->mem + BB_chaninfo_tab_b0 + + i * 4); + cdf_print("0x%x\t", val); + if (i % 4 == 0) + cdf_print("\n"); + } + } + if (chain1) { + for (i = 0; i < len; i++) { + val = + hif_read32_mb(scn->mem + BB_chaninfo_tab_b1 + + i * 4); + cdf_print("0x%x\t", val); + if (i % 4 == 0) + cdf_print("\n"); + } + } + HIF_TRACE("%s: AGC history buffer dump X", __func__); + /* restore original value */ + hif_write32_mb(scn->mem + BB_gains_min_offsets, + g_priv_dump_ctx.gain_min_offsets_orig); + return; +} + +void priv_dump_bbwatchdog(struct ol_softc *scn) +{ + uint32_t val; + + HIF_TRACE("%s: BB watchdog dump E", __func__); + val = hif_read32_mb(scn->mem + BB_watchdog_status); + cdf_print("0x%x\t", val); + val = hif_read32_mb(scn->mem + BB_watchdog_ctrl_1); + cdf_print("0x%x\t", val); + val = hif_read32_mb(scn->mem + BB_watchdog_ctrl_2); + cdf_print("0x%x\t", val); + val = hif_read32_mb(scn->mem + BB_watchdog_status_B); + cdf_print("0x%x", val); + HIF_TRACE("%s: BB watchdog dump X", __func__); +} diff --git a/core/hif/src/mp_dev.h b/core/hif/src/mp_dev.h new file mode 100644 index 000000000000..cb7e3d06ec18 --- /dev/null +++ b/core/hif/src/mp_dev.h @@ -0,0 +1,36 @@ +/* + * 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 __MP_DEV_H__ +#define __MP_DEV_H__ +void priv_start_agc(struct ol_softc *scn); +void priv_dump_agc(struct ol_softc *scn); +void priv_start_cap_chaninfo(struct ol_softc *scn); +void priv_dump_chaninfo(struct ol_softc *scn); +void priv_dump_bbwatchdog(struct ol_softc *scn); +void hif_shut_down_device(struct ol_softc *scn); +#endif /* __MP_DEV_H__ */ diff --git a/core/hif/src/pcie/cnss_stub.h b/core/hif/src/pcie/cnss_stub.h new file mode 100644 index 000000000000..64ab19e535e3 --- /dev/null +++ b/core/hif/src/pcie/cnss_stub.h @@ -0,0 +1,40 @@ +/* + * 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 __CNSS_STUB_H__ +#define __CNSS_STUB_H__ + +#ifndef CONFIG_CNSS +inline void cnss_wlan_pci_link_down(void) {} + +inline int cnss_pcie_shadow_control(struct pci_dev *dev, bool enable) +{ + return 0; +} + +#endif +#endif /* __CNSS_STUB_H__ */ diff --git a/core/hif/src/pcie/hif_io32_pci.h b/core/hif/src/pcie/hif_io32_pci.h new file mode 100644 index 000000000000..3ffa30da0325 --- /dev/null +++ b/core/hif/src/pcie/hif_io32_pci.h @@ -0,0 +1,306 @@ +/* + * 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 __HIF_IO32_PCI_H__ +#define __HIF_IO32_PCI_H__ + +#ifdef HIF_PCI + +#include "hif.h" +#include "regtable.h" +#include "ce_reg.h" +#include "cdf_atomic.h" +#include "if_pci.h" +/* + * 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 + +/* + * 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 + +#define hif_read32_mb(addr) ioread32((void __iomem *)addr) +#define hif_write32_mb(addr, value) \ + iowrite32((u32)(value), (void __iomem *)(addr)) + +extern int hif_target_sleep_state_adjust(struct ol_softc *scn, + bool sleep_ok, + bool wait_for_it); + +#if CONFIG_ATH_PCIE_MAX_PERF +#define A_TARGET_ACCESS_BEGIN(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_END(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_OK(scn) 1 + +#define A_TARGET_ACCESS_LIKELY(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_UNLIKELY(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_READ(scn, offset) \ + hif_read32_mb(scn->mem + (offset)) + +void war_pci_write32(char *addr, u32 offset, u32 value); +#define A_TARGET_WRITE(scn, offset, value) \ + war_pci_write32(scn->mem, (offset), (value)) + +#define A_TARGET_ACCESS_BEGIN_RET(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_BEGIN_RET_EXT(scn, val) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_BEGIN_RET_PTR(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_END_RET(scn) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_END_RET_EXT(scn, val) \ + do {struct ol_softc *unused = scn; \ + unused = unused; } while (0) + +#define A_TARGET_ACCESS_END_RET_PTR(scn) \ + do {struct ol_softc *unused = scn; \ + 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(scn, val) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_BEGIN(scn) < 0) \ + val = -1; \ +} while (0) + +#define A_TARGET_ACCESS_BEGIN_RET(scn) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_BEGIN(scn) < 0) \ + return ATH_ISR_NOSCHED; \ +} while (0) + +#define A_TARGET_ACCESS_BEGIN_RET_PTR(scn) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_BEGIN(scn) < 0) \ + return NULL; \ +} while (0) + +#define A_TARGET_ACCESS_BEGIN(scn) \ +do { \ + if (Q_TARGET_ACCESS_BEGIN(scn) < 0) \ + return; \ +} while (0) + +#define Q_TARGET_ACCESS_BEGIN(scn) \ + hif_target_sleep_state_adjust(scn, false, true) + +#define A_TARGET_ACCESS_END_RET(scn) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_END(scn) < 0) \ + return ATH_ISR_NOSCHED; \ +} while (0) + +#define A_TARGET_ACCESS_END_RET_EXT(scn, val) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_END(scn) < 0) \ + val = -1; \ +} while (0) + +#define A_TARGET_ACCESS_END_RET_PTR(scn) \ +do { \ + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && \ + Q_TARGET_ACCESS_END(scn) < 0) \ + return NULL; \ +} while (0) +#define A_TARGET_ACCESS_END(scn) \ +do { \ + if (Q_TARGET_ACCESS_END(scn) < 0) \ + return; \ +} while (0) + +#define Q_TARGET_ACCESS_END(scn) \ + hif_target_sleep_state_adjust(scn, true, false) + +#define A_TARGET_ACCESS_OK(scn) hif_target_forced_awake(scn) + +#if CONFIG_ATH_PCIE_ACCESS_LIKELY +#define A_TARGET_ACCESS_LIKELY(scn) \ + hif_target_sleep_state_adjust(scn, false, false) +#define A_TARGET_ACCESS_UNLIKELY(scn) \ + hif_target_sleep_state_adjust(scn, true, false) +#else /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ +#define A_TARGET_ACCESS_LIKELY(scn) \ + do { \ + unsigned long unused = (unsigned long)(scn); \ + unused = unused; \ + } while (0) + +#define A_TARGET_ACCESS_UNLIKELY(scn) \ + do { \ + unsigned long unused = (unsigned long)(scn); \ + unused = unused; \ + } while (0) +#endif /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +extern uint32_t hif_target_read_checked(struct ol_softc *scn, + uint32_t offset); +extern void hif_target_write_checked(struct ol_softc *scn, uint32_t offset, + uint32_t value); +#define A_TARGET_READ(scn, offset) \ + hif_target_read_checked(scn, (offset)) +#define A_TARGET_WRITE(scn, offset, value) \ + hif_target_write_checked(scn, (offset), (value)) +#else /* CONFIG_ATH_PCIE_ACCESS_DEBUG */ +#define A_TARGET_READ(scn, offset) \ + hif_read32_mb(scn->mem + (offset)) +#define A_TARGET_WRITE(scn, offset, value) \ + war_pci_write32(scn->mem, (offset), (value)) +#endif +#endif /* CONFIG_ATH_PCIE_MAX_PERF */ + +/** + * ce_irq_enable() - ce_irq_enable + * @scn: ol_softc + * @ce_id: ce_id + * + * Return: void + */ +static inline void ce_irq_enable(struct ol_softc *scn, int ce_id) +{ + uint32_t tmp = 1 << ce_id; + struct hif_pci_softc *sc = scn->hif_sc; + + cdf_spin_lock_irqsave(&scn->irq_lock); + scn->ce_irq_summary &= ~tmp; + if (scn->ce_irq_summary == 0) { + /* Enable Legacy PCI line interrupts */ + if (LEGACY_INTERRUPTS(sc) && + (scn->target_status != OL_TRGET_STATUS_RESET) && + (!cdf_atomic_read(&scn->link_suspended))) { + + hif_write32_mb(scn->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + HOST_GROUP0_MASK); + + hif_read32_mb(scn->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + } + } + if (scn->hif_init_done == true) + A_TARGET_ACCESS_END(scn); + cdf_spin_unlock_irqrestore(&scn->irq_lock); +} +/** + * ce_irq_disable() - ce_irq_disable + * @scn: ol_softc + * @ce_id: ce_id + * + * Return: void + */ +static inline void ce_irq_disable(struct ol_softc *scn, int ce_id) +{ + /* For Rome only need to wake up target */ + A_TARGET_ACCESS_BEGIN(scn); +} +/** + * soc_wake_reset() - soc_wake_reset + * @scn: ol_softc + * + * Return: void + */ +static inline void soc_wake_reset(struct ol_softc *scn) +{ + hif_write32_mb(scn->mem + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); +} +#endif /* HIF_PCI */ +#endif /* __HIF_IO32_PCI_H__ */ diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c new file mode 100644 index 000000000000..6efb418ee8d9 --- /dev/null +++ b/core/hif/src/pcie/if_pci.c @@ -0,0 +1,2239 @@ +/* + * 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 +#ifdef CONFIG_PCI_MSM +#include +#endif +#include "hif_io32.h" +#include "if_pci.h" +#include "hif.h" +#include "hif_main.h" +#include "ce_api.h" +#include "ce_internal.h" +#include "ce_reg.h" +#include "bmi_msg.h" /* TARGET_TYPE_ */ +#include "regtable.h" +#include "ol_fw.h" +#include +#include "cds_api.h" +#include "cdf_status.h" +#include "cds_sched.h" +#include "wma_api.h" +#include "cdf_atomic.h" +#include "wlan_hdd_power.h" +#include "wlan_hdd_main.h" +#ifdef CONFIG_CNSS +#include +#else +#include "cnss_stub.h" +#endif +#include "epping_main.h" +#include "mp_dev.h" +#include "hif_debug.h" + +#ifndef REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "pktlog_ac_api.h" +#include "pktlog_ac.h" +#endif +#include "if_pci_internal.h" +#include "icnss_stub.h" +#include "ce_tasklet.h" + +/* Maximum ms timeout for host to wake up target */ +#define PCIE_WAKE_TIMEOUT 1000 +#define RAMDUMP_EVENT_TIMEOUT 2500 + +unsigned int msienable = 0; +module_param(msienable, int, 0644); + +int hif_pci_war1 = 0; +static DEFINE_SPINLOCK(pciwar_lock); + +#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. + */ +struct ce_irq_reg_table { + uint32_t irq_enable; + uint32_t irq_status; +}; + +#if !defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA) +static inline void cnss_intr_notify_q6(void) +{ +} +#endif + +#if !defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA) +static inline void *cnss_get_target_smem(void) +{ + return NULL; +} +#endif + +void hif_pci_route_target_interrupt(struct hif_pci_softc *sc) +{ + uint32_t target_cause0, target_cause1, target_cause2; + uint32_t *target_smem; + struct ol_softc *scn = sc->ol_sc; + + target_smem = (uint32_t *)cnss_get_target_smem(); + if (!target_smem) + return; + + /* disable interrupts */ + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_0_ADDRESS, 0); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_1_ADDRESS, 0); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_2_ADDRESS, 0); + /* read cause */ + target_cause0 = hif_read32_mb(sc->mem + + A_SOC_CORE_SCRATCH_3_ADDRESS); + target_cause1 = hif_read32_mb(sc->mem + + A_SOC_CORE_SCRATCH_4_ADDRESS); + target_cause2 = hif_read32_mb(sc->mem + + A_SOC_CORE_SCRATCH_5_ADDRESS); + /* clear cause registers */ + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_3_ADDRESS, 0xffffffff); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_4_ADDRESS, 0xffffffff); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_5_ADDRESS, 0xffffffff); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_3_ADDRESS, 0); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_4_ADDRESS, 0); + hif_write32_mb(sc->mem + + A_SOC_CORE_SCRATCH_5_ADDRESS, 0); + /* copy cause value to Q6 */ + *target_smem = target_cause0; + *(target_smem + 1) = target_cause1; + *(target_smem + 2) = target_cause2; + if (scn->notice_send) + cnss_intr_notify_q6(); +} + +#ifndef QCA_WIFI_3_0_ADRASTEA +static inline void hif_pci_route_adrastea_interrupt(struct hif_pci_softc *sc) +{ + return; +} +#else +void hif_pci_route_adrastea_interrupt(struct hif_pci_softc *sc) +{ + struct ol_softc *scn = sc->ol_sc; + unsigned int target_enable0, target_enable1; + unsigned int target_cause0, target_cause1; + + target_enable0 = hif_read32_mb(sc->mem + Q6_ENABLE_REGISTER_0); + target_enable1 = hif_read32_mb(sc->mem + Q6_ENABLE_REGISTER_1); + target_cause0 = hif_read32_mb(sc->mem + Q6_CAUSE_REGISTER_0); + target_cause1 = hif_read32_mb(sc->mem + Q6_CAUSE_REGISTER_1); + + if ((target_enable0 & target_cause0) || + (target_enable1 & target_cause1)) { + hif_write32_mb(sc->mem + Q6_ENABLE_REGISTER_0, 0); + hif_write32_mb(sc->mem + Q6_ENABLE_REGISTER_1, 0); + + if (scn->notice_send) + cnss_intr_notify_q6(); + } +} +#endif + +static irqreturn_t hif_pci_interrupt_handler(int irq, void *arg) +{ + struct hif_pci_softc *sc = (struct hif_pci_softc *)arg; + struct ol_softc *scn = sc->ol_sc; + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + volatile int tmp; + uint16_t val; + uint32_t bar0; + uint32_t fw_indicator_address, fw_indicator; + bool ssr_irq = false; + unsigned int host_cause, host_enable; + + if (LEGACY_INTERRUPTS(sc)) { + if (Q_TARGET_ACCESS_BEGIN(scn) < 0) + return IRQ_HANDLED; + + if (ADRASTEA_BU) { + host_enable = hif_read32_mb(sc->mem + + PCIE_INTR_ENABLE_ADDRESS); + host_cause = hif_read32_mb(sc->mem + + PCIE_INTR_CAUSE_ADDRESS); + if (!(host_enable & host_cause)) { + hif_pci_route_adrastea_interrupt(sc); + return IRQ_HANDLED; + } + } + + /* 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 */ + hif_write32_mb(sc->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), 0); + if (IHELIUM_BU) { + if (!hif_read32_mb(sc->mem + PCIE_INTR_CAUSE_ADDRESS)) { + hif_pci_route_target_interrupt(sc); + + hif_write32_mb(sc->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + HOST_GROUP0_MASK); + + return IRQ_HANDLED; + } + } + + hif_write32_mb(sc->mem + + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_CLR_ADDRESS), + ADRASTEA_BU ? + (host_enable & host_cause) : + HOST_GROUP0_MASK); + + if (ADRASTEA_BU) + hif_write32_mb(sc->mem + 0x2f100c , (host_cause >> 1)); + + /* IMPORTANT: this extra read transaction is required to + * flush the posted write buffer */ + if (!ADRASTEA_BU) { + tmp = + hif_read32_mb(sc->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + + if (tmp == 0xdeadbeef) { + HIF_ERROR("BUG(%s): SoC returns 0xdeadbeef!!", + __func__); + + pci_read_config_word(sc->pdev, PCI_VENDOR_ID, &val); + HIF_ERROR("%s: PCI Vendor ID = 0x%04x", + __func__, val); + + pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &val); + HIF_ERROR("%s: PCI Device ID = 0x%04x", + __func__, val); + + pci_read_config_word(sc->pdev, PCI_COMMAND, &val); + HIF_ERROR("%s: PCI Command = 0x%04x", __func__, + val); + + pci_read_config_word(sc->pdev, PCI_STATUS, &val); + HIF_ERROR("%s: PCI Status = 0x%04x", __func__, + val); + + pci_read_config_dword(sc->pdev, PCI_BASE_ADDRESS_0, + &bar0); + HIF_ERROR("%s: PCI BAR0 = 0x%08x", __func__, + bar0); + + HIF_ERROR("%s: RTC_STATE_ADDRESS = 0x%08x", + __func__, + hif_read32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS)); + HIF_ERROR("%s: PCIE_SOC_WAKE_ADDRESS = 0x%08x", + __func__, + hif_read32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + HIF_ERROR("%s: 0x80008 = 0x%08x, 0x8000c = 0x%08x", + __func__, + hif_read32_mb(sc->mem + 0x80008), + hif_read32_mb(sc->mem + 0x8000c)); + HIF_ERROR("%s: 0x80010 = 0x%08x, 0x80014 = 0x%08x", + __func__, + hif_read32_mb(sc->mem + 0x80010), + hif_read32_mb(sc->mem + 0x80014)); + HIF_ERROR("%s: 0x80018 = 0x%08x, 0x8001c = 0x%08x", + __func__, + hif_read32_mb(sc->mem + 0x80018), + hif_read32_mb(sc->mem + 0x8001c)); + CDF_BUG(0); + } + + PCI_CLR_CAUSE0_REGISTER(sc); + } + + if (HAS_FW_INDICATOR) { + fw_indicator_address = hif_state->fw_indicator_address; + fw_indicator = A_TARGET_READ(scn, fw_indicator_address); + if ((fw_indicator != ~0) && + (fw_indicator & FW_IND_EVENT_PENDING)) + ssr_irq = true; + } + + if (Q_TARGET_ACCESS_END(scn) < 0) + return IRQ_HANDLED; + } + /* TBDXXX: Add support for WMAC */ + + if (ssr_irq) { + sc->irq_event = irq; + cdf_atomic_set(&scn->tasklet_from_intr, 1); + + cdf_atomic_inc(&scn->active_tasklet_cnt); + tasklet_schedule(&sc->intr_tq); + } else { + icnss_dispatch_ce_irq(scn); + } + + 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->ol_sc); + + return IRQ_HANDLED; +} + +bool hif_targ_is_awake(struct ol_softc *scn, void *__iomem *mem) +{ + HIF_PCI_TARG_IS_AWAKE(scn, mem); +} + +bool hif_pci_targ_is_present(struct ol_softc *scn, void *__iomem *mem) +{ + return 1; /* FIX THIS */ +} + +/** + * hif_pci_cancel_deferred_target_sleep() - cancels the defered target sleep + * @scn: ol_softc + * + * Return: void + */ +#if CONFIG_ATH_PCIE_MAX_PERF == 0 +void hif_pci_cancel_deferred_target_sleep(struct ol_softc *scn) +{ + struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + A_target_id_t pci_addr = scn->mem; + + cdf_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) { + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + if (hif_state->verified_awake == false) { + hif_write32_mb(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); + } + hif_state->fake_sleep = false; + } + cdf_spin_unlock_irqrestore(&hif_state->keep_awake_lock); +} +#else +inline void hif_pci_cancel_deferred_target_sleep(struct ol_softc *scn) +{ + return; +} +#endif + +#define A_PCIE_LOCAL_REG_READ(mem, addr) \ + hif_read32_mb((char *)(mem) + \ + PCIE_LOCAL_BASE_ADDRESS + (uint32_t)(addr)) + +#define A_PCIE_LOCAL_REG_WRITE(mem, addr, val) \ + hif_write32_mb(((char *)(mem) + \ + PCIE_LOCAL_BASE_ADDRESS + (uint32_t)(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; + uint32_t val; + struct ol_softc *scn = sc->ol_sc; + + if (!scn->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; + } + + HIF_ERROR("%s: Reset Device", __func__); + + /* + * 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; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (hif_targ_is_awake(scn, mem)) + break; + + cdf_mdelay(1); + } + + /* Put Target, including PCIe, into RESET. */ + val = A_PCIE_LOCAL_REG_READ(mem, SOC_GLOBAL_RESET_ADDRESS); + val |= 1; + A_PCIE_LOCAL_REG_WRITE(mem, SOC_GLOBAL_RESET_ADDRESS, val); + for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (A_PCIE_LOCAL_REG_READ(mem, RTC_STATE_ADDRESS) & + RTC_STATE_COLD_RESET_MASK) + break; + + cdf_mdelay(1); + } + + /* Pull Target, including PCIe, out of RESET. */ + val &= ~1; + A_PCIE_LOCAL_REG_WRITE(mem, SOC_GLOBAL_RESET_ADDRESS, val); + for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (! + (A_PCIE_LOCAL_REG_READ(mem, RTC_STATE_ADDRESS) & + RTC_STATE_COLD_RESET_MASK)) + break; + + cdf_mdelay(1); + } + + A_PCIE_LOCAL_REG_WRITE(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); +} + +/* CPU warm reset function + * Steps: + * 1. Disable all pending interrupts - so no pending interrupts on WARM reset + * 2. Clear the FW_INDICATOR_ADDRESS -so Traget CPU intializes FW + * correctly on WARM reset + * 3. Clear TARGET CPU LF timer interrupt + * 4. Reset all CEs to clear any pending CE tarnsactions + * 5. Warm reset CPU + */ +void hif_pci_device_warm_reset(struct hif_pci_softc *sc) +{ + void __iomem *mem = sc->mem; + int i; + uint32_t val; + uint32_t fw_indicator; + struct ol_softc *scn = sc->ol_sc; + + /* NB: Don't check resetok here. This form of reset is + * integral to correct operation. */ + + if (!mem) { + return; + } + + HIF_INFO_MED("%s: Target Warm Reset", __func__); + + /* + * 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; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (hif_targ_is_awake(scn, mem)) + break; + cdf_mdelay(1); + } + + /* + * Disable Pending interrupts + */ + val = + hif_read32_mb(mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_CAUSE_ADDRESS)); + HIF_INFO_MED("%s: Host Intr Cause reg 0x%x : value : 0x%x", __func__, + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_CAUSE_ADDRESS), val); + /* Target CPU Intr Cause */ + val = hif_read32_mb(mem + (SOC_CORE_BASE_ADDRESS | CPU_INTR_ADDRESS)); + HIF_INFO_MED("%s: Target CPU Intr Cause 0x%x", __func__, val); + + val = + hif_read32_mb(mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + hif_write32_mb((mem + + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)), 0); + hif_write32_mb((mem + (SOC_CORE_BASE_ADDRESS + PCIE_INTR_CLR_ADDRESS)), + HOST_GROUP0_MASK); + + cdf_mdelay(100); + + /* Clear FW_INDICATOR_ADDRESS */ + if (HAS_FW_INDICATOR) { + fw_indicator = hif_read32_mb(mem + FW_INDICATOR_ADDRESS); + hif_write32_mb(mem + FW_INDICATOR_ADDRESS, 0); + } + + /* Clear Target LF Timer interrupts */ + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS + + SOC_LF_TIMER_CONTROL0_ADDRESS)); + HIF_INFO_MED("%s: addr 0x%x : 0x%x", __func__, + (RTC_SOC_BASE_ADDRESS + SOC_LF_TIMER_CONTROL0_ADDRESS), val); + val &= ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK; + hif_write32_mb(mem + + (RTC_SOC_BASE_ADDRESS + SOC_LF_TIMER_CONTROL0_ADDRESS), + val); + + /* Reset CE */ + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS | + SOC_RESET_CONTROL_ADDRESS)); + val |= SOC_RESET_CONTROL_CE_RST_MASK; + hif_write32_mb((mem + + (RTC_SOC_BASE_ADDRESS | SOC_RESET_CONTROL_ADDRESS)), + val); + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS | + SOC_RESET_CONTROL_ADDRESS)); + cdf_mdelay(10); + + /* CE unreset */ + val &= ~SOC_RESET_CONTROL_CE_RST_MASK; + hif_write32_mb(mem + (RTC_SOC_BASE_ADDRESS | SOC_RESET_CONTROL_ADDRESS), + val); + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS | + SOC_RESET_CONTROL_ADDRESS)); + cdf_mdelay(10); + + /* Read Target CPU Intr Cause */ + val = hif_read32_mb(mem + (SOC_CORE_BASE_ADDRESS | CPU_INTR_ADDRESS)); + HIF_INFO_MED("%s: Target CPU Intr Cause after CE reset 0x%x", + __func__, val); + + /* CPU warm RESET */ + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS | + SOC_RESET_CONTROL_ADDRESS)); + val |= SOC_RESET_CONTROL_CPU_WARM_RST_MASK; + hif_write32_mb(mem + (RTC_SOC_BASE_ADDRESS | SOC_RESET_CONTROL_ADDRESS), + val); + val = + hif_read32_mb(mem + + (RTC_SOC_BASE_ADDRESS | + SOC_RESET_CONTROL_ADDRESS)); + HIF_INFO_MED("%s: RESET_CONTROL after cpu warm reset 0x%x", + __func__, val); + + cdf_mdelay(100); + HIF_INFO_MED("%s: Target Warm reset complete", __func__); + +} + +#ifndef QCA_WIFI_3_0 +int hif_check_fw_reg(struct ol_softc *scn) +{ + struct hif_pci_softc *sc = scn->hif_sc; + void __iomem *mem = sc->mem; + uint32_t val; + + A_TARGET_ACCESS_BEGIN_RET(scn); + val = hif_read32_mb(mem + FW_INDICATOR_ADDRESS); + A_TARGET_ACCESS_END_RET(scn); + + HIF_INFO_MED("%s: FW_INDICATOR register is 0x%x", __func__, val); + + if (val & FW_IND_HELPER) + return 0; + + return 1; +} +#endif + +int hif_check_soc_status(struct ol_softc *scn) +{ + uint16_t device_id; + uint32_t val; + uint16_t timeout_count = 0; + struct hif_pci_softc *sc = scn->hif_sc; + + /* 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) { + HIF_ERROR("%s: device ID does match (read 0x%x, expect 0x%x)", + __func__, device_id, sc->devid); + return -EACCES; + } + + /* Check PCIe local register for bar/memory access */ + val = hif_read32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS); + HIF_INFO_MED("%s: RTC_STATE_ADDRESS is %08x", __func__, val); + + /* Try to wake up taget if it sleeps */ + hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + HIF_INFO_MED("%s: PCIE_SOC_WAKE_ADDRESS is %08x", __func__, + hif_read32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + + /* Check if taget can be woken up */ + while (!hif_targ_is_awake(scn, sc->mem)) { + if (timeout_count >= PCIE_WAKE_TIMEOUT) { + HIF_ERROR("%s: wake up timeout, %08x, %08x", + __func__, + hif_read32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS), + hif_read32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + return -EACCES; + } + + hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + + cdf_mdelay(100); + timeout_count += 100; + } + + /* Check Power register for SoC internal bus issues */ + val = + hif_read32_mb(sc->mem + RTC_SOC_BASE_ADDRESS + + SOC_POWER_REG_OFFSET); + HIF_INFO_MED("%s: Power register is %08x", __func__, val); + + return 0; +} + +void dump_ce_debug_register(struct ol_softc *scn) +{ + struct hif_pci_softc *sc = scn->hif_sc; + void __iomem *mem = sc->mem; + uint32_t val, i, j; + uint32_t wrapper_idx[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + uint32_t ce_base; + + A_TARGET_ACCESS_BEGIN(scn); + + /* DEBUG_INPUT_SEL_SRC = 0x6 */ + val = + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_INPUT_SEL_OFFSET); + val &= ~WLAN_DEBUG_INPUT_SEL_SRC_MASK; + val |= WLAN_DEBUG_INPUT_SEL_SRC_SET(0x6); + hif_write32_mb(mem + GPIO_BASE_ADDRESS + WLAN_DEBUG_INPUT_SEL_OFFSET, + val); + + /* DEBUG_CONTROL_ENABLE = 0x1 */ + val = hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_CONTROL_OFFSET); + val &= ~WLAN_DEBUG_CONTROL_ENABLE_MASK; + val |= WLAN_DEBUG_CONTROL_ENABLE_SET(0x1); + hif_write32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_CONTROL_OFFSET, val); + + HIF_INFO_MED("%s: Debug: inputsel: %x dbgctrl: %x", __func__, + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_INPUT_SEL_OFFSET), + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_CONTROL_OFFSET)); + + HIF_INFO_MED("%s: Debug CE", __func__); + /* Loop CE debug output */ + /* AMBA_DEBUG_BUS_SEL = 0xc */ + val = hif_read32_mb(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET); + val &= ~AMBA_DEBUG_BUS_SEL_MASK; + val |= AMBA_DEBUG_BUS_SEL_SET(0xc); + hif_write32_mb(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET, val); + + for (i = 0; i < sizeof(wrapper_idx) / sizeof(uint32_t); i++) { + /* For (i=1,2,3,4,8,9) write CE_WRAPPER_DEBUG_SEL = i */ + val = hif_read32_mb(mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_DEBUG_OFFSET); + val &= ~CE_WRAPPER_DEBUG_SEL_MASK; + val |= CE_WRAPPER_DEBUG_SEL_SET(wrapper_idx[i]); + hif_write32_mb(mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_DEBUG_OFFSET, val); + + HIF_INFO_MED("%s: ce wrapper: %d amdbg: %x cewdbg: %x", + __func__, wrapper_idx[i], + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + AMBA_DEBUG_BUS_OFFSET), + hif_read32_mb(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 = + hif_read32_mb(mem + ce_base + + CE_DEBUG_OFFSET); + val &= ~CE_DEBUG_SEL_MASK; + val |= CE_DEBUG_SEL_SET(j); + hif_write32_mb(mem + ce_base + CE_DEBUG_OFFSET, + val); + + /* read (@gpio_athr_wlan_reg) + * WLAN_DEBUG_OUT_DATA */ + val = hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + HIF_INFO_MED("%s: module%d: cedbg: %x out: %x", + __func__, j, + hif_read32_mb(mem + ce_base + + CE_DEBUG_OFFSET), val); + } + } else { + /* read (@gpio_athr_wlan_reg) WLAN_DEBUG_OUT_DATA */ + val = + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + HIF_INFO_MED("%s: out: %x", __func__, val); + } + } + + HIF_INFO_MED("%s: Debug PCIe:", __func__); + /* Loop PCIe debug output */ + /* Write AMBA_DEBUG_BUS_SEL = 0x1c */ + val = hif_read32_mb(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET); + val &= ~AMBA_DEBUG_BUS_SEL_MASK; + val |= AMBA_DEBUG_BUS_SEL_SET(0x1c); + hif_write32_mb(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 = + hif_read32_mb(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); + hif_write32_mb(mem + GPIO_BASE_ADDRESS + AMBA_DEBUG_BUS_OFFSET, + val); + + /* read (@gpio_athr_wlan_reg) WLAN_DEBUG_OUT_DATA */ + val = + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET); + val = WLAN_DEBUG_OUT_DATA_GET(val); + + HIF_INFO_MED("%s: amdbg: %x out: %x %x", __func__, + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET), val, + hif_read32_mb(mem + GPIO_BASE_ADDRESS + + WLAN_DEBUG_OUT_OFFSET)); + } + + A_TARGET_ACCESS_END(scn); +} + +/* + * 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->ol_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) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct hif_pci_softc *sc; + + if (NULL == scn) { + HIF_ERROR("%s: tasklet scn is null", __func__); + return; + } + + sc = scn->hif_sc; + + if (scn->hif_init_done == false) { + HIF_ERROR("%s: wlan driver is unloaded", __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 ol_softc *scn = sc->ol_sc; + + if (scn->hif_init_done == false) + goto end; + + if (cdf_atomic_read(&scn->link_suspended)) + goto end; + + if (!IHELIUM_BU && !ADRASTEA_BU) { + (irqreturn_t) hif_fw_interrupt_handler(sc->irq_event, scn); + if (sc->ol_sc->target_status == OL_TRGET_STATUS_RESET) + goto end; + } + +end: + cdf_atomic_set(&scn->tasklet_from_intr, 0); + cdf_atomic_dec(&scn->active_tasklet_cnt); +} + +#define ATH_PCI_PROBE_RETRY_MAX 3 +/** + * hif_bus_open(): hif_bus_open + * @scn: scn + * @bus_type: bus type + * + * Return: n/a + */ +CDF_STATUS hif_bus_open(struct ol_softc *ol_sc, enum ath_hal_bus_type bus_type) +{ + struct hif_pci_softc *sc; + + sc = cdf_mem_malloc(sizeof(*sc)); + if (!sc) { + HIF_ERROR("%s: no mem", __func__); + return CDF_STATUS_E_NOMEM; + } + ol_sc->hif_sc = (void *)sc; + sc->ol_sc = ol_sc; + ol_sc->bus_type = bus_type; + + return CDF_STATUS_SUCCESS; +} + +/** + * hif_bus_close(): hif_bus_close + * + * Return: n/a + */ +void hif_bus_close(struct ol_softc *ol_sc) +{ + struct hif_pci_softc *sc; + + if (ol_sc == NULL) { + HIF_ERROR("%s: ol_softc is NULL", __func__); + return; + } + sc = ol_sc->hif_sc; + if (sc == NULL) + return; + cdf_mem_free(sc); + ol_sc->hif_sc = NULL; +} + +#define BAR_NUM 0 + +int hif_enable_pci(struct hif_pci_softc *sc, + struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem *mem; + int ret = 0; + uint16_t device_id; + struct ol_softc *ol_sc = sc->ol_sc; + + pci_read_config_word(pdev,PCI_DEVICE_ID,&device_id); + if(device_id != id->device) { + HIF_ERROR( + "%s: dev id mismatch, config id = 0x%x, probing id = 0x%x", + __func__, device_id, id->device); + /* 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)) { + HIF_ERROR("%s: pci_assign_resource error", __func__); + return -EIO; + } +#endif + + if (pci_enable_device(pdev)) { + HIF_ERROR("%s: pci_enable_device error", + __func__); + return -EIO; + } + + /* Request MMIO resources */ + ret = pci_request_region(pdev, BAR_NUM, "ath"); + if (ret) { + HIF_ERROR("%s: PCI MMIO reservation error", __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) { + HIF_ERROR("%s: Cannot enable 64-bit pci DMA", __func__); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) { + HIF_ERROR("%s: Cannot enable 64-bit DMA", __func__); + goto err_dma; + } +#else + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + HIF_ERROR("%s: Cannot enable 32-bit pci DMA", __func__); + goto err_dma; + } + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + HIF_ERROR("%s: Cannot enable 32-bit consistent DMA!", + __func__); + goto err_dma; + } +#endif + + PCI_CFG_TO_DISABLE_L1SS_STATES(pdev, 0x188); + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + + /* Arrange for access to Target SoC registers. */ + mem = pci_iomap(pdev, BAR_NUM, 0); + if (!mem) { + HIF_ERROR("%s: PCI iomap error", __func__); + ret = -EIO; + goto err_iomap; + } + sc->mem = mem; + sc->pdev = pdev; + sc->dev = &pdev->dev; + ol_sc->aps_osdev.bdev = pdev; + ol_sc->aps_osdev.device = &pdev->dev; + ol_sc->aps_osdev.bc.bc_handle = (void *)mem; + ol_sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_PCI; + sc->devid = id->device; + sc->cacheline_sz = dma_get_cache_alignment(); + /* Get RAM dump memory address and size */ + GET_VIRT_RAMDUMP_MEM(ol_sc); + ol_sc->mem = mem; + sc->pci_enabled = true; + return ret; + +err_iomap: + pci_clear_master(pdev); +err_dma: + pci_release_region(pdev, BAR_NUM); +err_region: + pci_disable_device(pdev); + return ret; +} + +void hif_disable_pci(struct hif_pci_softc *sc) +{ + struct ol_softc *ol_sc; + + if (!sc) + return; + + ol_sc = sc->ol_sc; + if (ol_sc == NULL) { + HIF_ERROR("%s: ol_sc = NULL", __func__); + return; + } + pci_set_drvdata(sc->pdev, NULL); + hif_pci_device_reset(sc); + pci_iounmap(sc->pdev, sc->mem); + sc->mem = NULL; + ol_sc->mem = NULL; + pci_clear_master(sc->pdev); + pci_release_region(sc->pdev, BAR_NUM); + pci_disable_device(sc->pdev); +} + +int hif_pci_probe_tgt_wakeup(struct hif_pci_softc *sc) +{ + int ret = 0; + int targ_awake_limit = 500; +#ifndef QCA_WIFI_3_0 + uint32_t fw_indicator; +#endif + struct ol_softc *scn = sc->ol_sc; + /* + * 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. + */ + hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_V_MASK); + while (!hif_targ_is_awake(scn, sc->mem)) { + if (0 == targ_awake_limit) { + HIF_ERROR("%s: target awake timeout", __func__); + ret = -EAGAIN; + goto end; + } + cdf_mdelay(1); + targ_awake_limit--; + } + +#if PCIE_BAR0_READY_CHECKING + { + int wait_limit = 200; + /* Synchronization point: wait the BAR0 is configured */ + while (wait_limit-- && + !(hif_read32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_RDY_STATUS_ADDRESS) \ + & PCIE_SOC_RDY_STATUS_BAR_MASK)) { + cdf_mdelay(10); + } + if (wait_limit < 0) { + /* AR6320v1 doesn't support checking of BAR0 configuration, + takes one sec to wait BAR0 ready */ + HIF_INFO_MED("%s: AR6320v1 waits two sec for BAR0", + __func__); + } + } +#endif + +#ifndef QCA_WIFI_3_0 + fw_indicator = hif_read32_mb(sc->mem + FW_INDICATOR_ADDRESS); + hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); + + if (fw_indicator & FW_IND_INITIALIZED) { + HIF_ERROR("%s: Target is in an unknown state. EAGAIN", + __func__); + ret = -EAGAIN; + goto end; + } +#endif + +end: + return ret; +} + +static void wlan_tasklet_msi(unsigned long data) +{ + struct hif_tasklet_entry *entry = (struct hif_tasklet_entry *)data; + struct hif_pci_softc *sc = (struct hif_pci_softc *) entry->hif_handler; + struct ol_softc *scn = sc->ol_sc; + + if (sc->ol_sc->hif_init_done == false) + goto irq_handled; + + if (cdf_atomic_read(&sc->ol_sc->link_suspended)) + goto irq_handled; + + cdf_atomic_inc(&scn->active_tasklet_cnt); + + if (entry->id == HIF_MAX_TASKLET_NUM) { + /* the last tasklet is for fw IRQ */ + (irqreturn_t)hif_fw_interrupt_handler(sc->irq_event, sc->ol_sc); + if (sc->ol_sc->target_status == OL_TRGET_STATUS_RESET) + goto irq_handled; + } else if (entry->id < sc->ol_sc->ce_count) { + ce_per_engine_service(sc->ol_sc, entry->id); + } else { + HIF_ERROR("%s: ERROR - invalid CE_id = %d", + __func__, entry->id); + } + return; + +irq_handled: + cdf_atomic_dec(&scn->active_tasklet_cnt); + +} + +int hif_configure_msi(struct hif_pci_softc *sc) +{ + int ret = 0; + int num_msi_desired; + int rv = -1; + struct ol_softc *scn = sc->ol_sc; + + HIF_TRACE("%s: E", __func__); + + num_msi_desired = MSI_NUM_REQUEST; /* Multiple MSI */ + if (num_msi_desired < 1) { + HIF_ERROR("%s: MSI is not configured", __func__); + return -EINVAL; + } + + if (num_msi_desired > 1) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + rv = pci_enable_msi_range(sc->pdev, num_msi_desired, + num_msi_desired); +#else + rv = pci_enable_msi_block(sc->pdev, num_msi_desired); +#endif + } + HIF_TRACE("%s: num_msi_desired = %d, available_msi = %d", + __func__, num_msi_desired, rv); + + if (rv == 0 || rv >= HIF_MAX_TASKLET_NUM) { + int i; + + sc->num_msi_intrs = HIF_MAX_TASKLET_NUM; + sc->tasklet_entries[HIF_MAX_TASKLET_NUM -1].hif_handler = + (void *)sc; + sc->tasklet_entries[HIF_MAX_TASKLET_NUM -1].id = + HIF_MAX_TASKLET_NUM; + tasklet_init(&sc->intr_tq, wlan_tasklet_msi, + (unsigned long)&sc->tasklet_entries[ + HIF_MAX_TASKLET_NUM -1]); + ret = request_irq(sc->pdev->irq + MSI_ASSIGN_FW, + hif_pci_msi_fw_handler, + IRQF_SHARED, "wlan_pci", sc); + if(ret) { + HIF_ERROR("%s: request_irq failed", __func__); + goto err_intr; + } + for (i = 0; i <= scn->ce_count; i++) { + sc->tasklet_entries[i].hif_handler = (void *)sc; + sc->tasklet_entries[i].id = i; + tasklet_init(&sc->intr_tq, wlan_tasklet_msi, + (unsigned long)&sc->tasklet_entries[i]); + ret = request_irq((sc->pdev->irq + + i + MSI_ASSIGN_CE_INITIAL), + ce_per_engine_handler, IRQF_SHARED, + "wlan_pci", sc); + if(ret) { + HIF_ERROR("%s: request_irq failed", __func__); + goto err_intr; + } + } + } else if (rv > 0) { + HIF_TRACE("%s: use single msi", __func__); + + if ((ret = pci_enable_msi(sc->pdev)) < 0) { + HIF_ERROR("%s: single MSI allocation failed", + __func__); + /* Try for legacy PCI line interrupts */ + sc->num_msi_intrs = 0; + } else { + sc->num_msi_intrs = 1; + tasklet_init(&sc->intr_tq, + wlan_tasklet, (unsigned long)sc); + ret = request_irq(sc->pdev->irq, + hif_pci_interrupt_handler, + IRQF_SHARED, "wlan_pci", sc); + if(ret) { + HIF_ERROR("%s: request_irq failed", __func__); + goto err_intr; + } + } + } else { + sc->num_msi_intrs = 0; + ret = -EIO; + HIF_ERROR("%s: do not support MSI, rv = %d", __func__, rv); + } + if ((ret = pci_enable_msi(sc->pdev)) < 0) { + HIF_ERROR("%s: single MSI interrupt allocation failed", + __func__); + /* Try for legacy PCI line interrupts */ + sc->num_msi_intrs = 0; + } else { + sc->num_msi_intrs = 1; + tasklet_init(&sc->intr_tq, wlan_tasklet, (unsigned long)sc); + ret = request_irq(sc->pdev->irq, + hif_pci_interrupt_handler, IRQF_SHARED, + "wlan_pci", sc); + if(ret) { + HIF_ERROR("%s: request_irq failed", __func__); + goto err_intr; + } + } + + if (ret == 0) { + hif_write32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + HOST_GROUP0_MASK); + hif_write32_mb(sc->mem + + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); + } + HIF_TRACE("%s: X, ret = %d", __func__, ret); + + return ret; + +err_intr: +if (sc->num_msi_intrs >= 1) + pci_disable_msi(sc->pdev); + return ret; +} + +static int hif_pci_configure_legacy_irq(struct hif_pci_softc *sc) +{ + int ret = 0; + struct ol_softc *scn = sc->ol_sc; + + HIF_TRACE("%s: E", __func__); + + /* do notn support MSI or MSI IRQ failed */ + tasklet_init(&sc->intr_tq, wlan_tasklet, (unsigned long)sc); + ret = request_irq(sc->pdev->irq, + hif_pci_interrupt_handler, IRQF_SHARED, + "wlan_pci", sc); + if(ret) { + HIF_ERROR("%s: request_irq failed, ret = %d", __func__, ret); + goto end; + } + /* Use Legacy PCI Interrupts */ + hif_write32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + HOST_GROUP0_MASK); + hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_RESET); +end: + CDF_TRACE(CDF_MODULE_ID_HIF, CDF_TRACE_LEVEL_ERROR, + "%s: X, ret = %d", __func__, ret); + return ret; +} + +/** + * hif_nointrs(): disable IRQ + * + * This function stops interrupt(s) + * + * @scn: struct ol_softc + * + * Return: none + */ +void hif_nointrs(struct ol_softc *scn) +{ + int i; + struct hif_pci_softc *sc = scn->hif_sc; + + if (scn->request_irq_done == false) + 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); + } + ce_unregister_irq(scn->hif_hdl, 0xfff); + scn->request_irq_done = false; +} + +/** + * hif_disable_bus(): hif_disable_bus + * + * This function disables the bus + * + * @bdev: bus dev + * + * Return: none + */ +void hif_disable_bus(void *bdev) +{ + struct pci_dev *pdev = bdev; + 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; + + if (ADRASTEA_BU) { + hif_write32_mb(sc->mem + PCIE_INTR_ENABLE_ADDRESS, 0); + hif_write32_mb(sc->mem + PCIE_INTR_CLR_ADDRESS, + HOST_GROUP0_MASK); + } + + mem = (void __iomem *)sc->mem; + if (mem) { + pci_disable_msi(pdev); + hif_dump_pipe_debug_count(scn); + hif_deinit_cdf_ctx(scn); + if (scn->athdiag_procfs_inited) { + athdiag_procfs_remove(); + scn->athdiag_procfs_inited = false; + } + pci_set_drvdata(pdev, NULL); + pci_iounmap(pdev, mem); + scn->mem = NULL; + pci_release_region(pdev, BAR_NUM); + pci_clear_master(pdev); + pci_disable_device(pdev); + } + HIF_INFO("%s: X", __func__); +} + +#define OL_ATH_PCI_PM_CONTROL 0x44 + +#ifdef CONFIG_CNSS +/** + * hif_bus_prevent_linkdown(): allow or permit linkdown + * @flag: true prevents linkdown, false allows + * + * Calls into the platform driver to vote against taking down the + * pcie link. + * + * Return: n/a + */ +void hif_bus_prevent_linkdown(bool flag) +{ + HIF_ERROR("wlan: %s pcie power collapse", + (flag ? "disable" : "enable")); + cnss_wlan_pm_control(flag); +} +#endif + +/** + * hif_drain_tasklets(): wait untill no tasklet is pending + * @scn: hif context + * + * Let running tasklets clear pending trafic. + * + * Return: 0 if no bottom half is in progress when it returns. + * -EFAULT if it times out. + */ +static inline int hif_drain_tasklets(struct ol_softc *scn) +{ + uint32_t ce_drain_wait_cnt = 0; + + while (cdf_atomic_read(&scn->active_tasklet_cnt)) { + if (++ce_drain_wait_cnt > HIF_CE_DRAIN_WAIT_CNT) { + HIF_ERROR("%s: CE still not done with access", + __func__); + + return -EFAULT; + } + HIF_INFO("%s: Waiting for CE to finish access", __func__); + msleep(10); + } + return 0; +} + +/** + * hif_bus_suspend_link_up() - suspend the bus + * + * Configures the pci irq line as a wakeup source. + * + * Return: 0 for success and non-zero for failure + */ +static int hif_bus_suspend_link_up(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct pci_dev *pdev; + int status; + + if (!scn) + return -EFAULT; + + pdev = scn->aps_osdev.bdev; + + status = hif_drain_tasklets(scn); + if (status != 0) + return status; + + if (unlikely(enable_irq_wake(pdev->irq))) { + HIF_ERROR("%s: Fail to enable wake IRQ!", __func__); + return -EINVAL; + } + + return 0; +} + +/** + * hif_bus_resume_link_up() - hif bus resume API + * + * This function disables the wakeup source. + * + * Return: 0 for success and non-zero for failure + */ +static int hif_bus_resume_link_up(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct pci_dev *pdev; + + if (!scn) + return -EFAULT; + + pdev = scn->aps_osdev.bdev; + if (!pdev) { + HIF_ERROR("%s: pci_dev is null", __func__); + return -EFAULT; + } + + if (unlikely(disable_irq_wake(pdev->irq))) { + HIF_ERROR("%s: Fail to disable wake IRQ!", __func__); + return -EFAULT; + } + + return 0; +} + +/** + * hif_bus_suspend_link_down() - suspend the bus + * + * Suspends the hif layer taking care of draining recieve queues and + * shutting down copy engines if needed. Ensures opy engine interrupts + * are disabled when it returns. Prevents register access after it + * returns. + * + * Return: 0 for success and non-zero for failure + */ +static int hif_bus_suspend_link_down(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct pci_dev *pdev; + struct HIF_CE_state *hif_state; + int status = 0; + + if (!scn) + return -EFAULT; + + pdev = scn->aps_osdev.bdev; + + hif_state = (struct HIF_CE_state *)scn->hif_hdl; + if (!hif_state) { + HIF_ERROR("%s: hif_state is null", __func__); + return -EFAULT; + } + + disable_irq(pdev->irq); + + status = hif_drain_tasklets(scn); + if (status != 0) { + enable_irq(pdev->irq); + return status; + } + + /* Stop the HIF Sleep Timer */ + hif_cancel_deferred_target_sleep(scn); + + cdf_atomic_set(&scn->link_suspended, 1); + + return 0; +} + +/** + * hif_bus_resume_link_down() - hif bus resume API + * + * This function resumes the bus reenabling interupts. + * + * Return: 0 for success and non-zero for failure + */ +static int hif_bus_resume_link_down(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct pci_dev *pdev; + + if (!scn) + return -EFAULT; + + pdev = scn->aps_osdev.bdev; + if (!pdev) { + HIF_ERROR("%s: pci_dev is null", __func__); + return -EFAULT; + } + + cdf_atomic_set(&scn->link_suspended, 0); + + enable_irq(pdev->irq); + + return 0; +} + +/** + * hif_bus_suspend(): prepare hif for suspend + * chose suspend type based on link suspend voting. + * + * Return: linux status + */ +int hif_bus_suspend(void) +{ + if (hif_can_suspend_link()) + return hif_bus_suspend_link_down(); + else + return hif_bus_suspend_link_up(); +} + +/** + * hif_bus_suspend(): prepare hif for suspend + * chose suspend type based on link suspend voting. + * + * Return: linux status + */ +int hif_bus_resume(void) +{ + if (hif_can_suspend_link()) + return hif_bus_resume_link_down(); + else + return hif_bus_resume_link_up(); +} + +void hif_disable_isr(void *ol_sc) +{ + struct ol_softc *scn = (struct ol_softc *)ol_sc; + struct hif_pci_softc *sc = scn->hif_sc; + + hif_nointrs(ol_sc); +#if CONFIG_PCIE_64BIT_MSI + OS_FREE_CONSISTENT(&scn->aps_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 */ + ce_tasklet_kill(scn->hif_hdl); + tasklet_kill(&sc->intr_tq); + cdf_atomic_set(&scn->active_tasklet_cnt, 0); +} + +/* 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) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct hif_pci_softc *sc; + + if (NULL == scn) { + HIF_ERROR("%s: Could not disable ASPM scn is null", + __func__); + return; + } + + sc = scn->hif_sc; + + /* Disable ASPM when pkt log is enabled */ + pci_read_config_dword(sc->pdev, 0x80, &scn->lcr_val); + pci_write_config_dword(sc->pdev, 0x80, (scn->lcr_val & 0xffffff00)); +} + +/** + * hif_enable_power_gating(): enable HW power gating + * + * This function enables HW gating + * + * Return: none + */ +void hif_enable_power_gating(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + struct hif_pci_softc *sc; + + if (NULL == scn) { + HIF_ERROR("%s: Could not disable ASPM scn is null", + __func__); + return; + } + sc = scn->hif_sc; + + /* Re-enable ASPM after firmware/OTP download is complete */ + pci_write_config_dword(sc->pdev, 0x80, scn->lcr_val); + if (scn->pkt_log_init == false) { + PKT_LOG_MOD_INIT(scn); + scn->pkt_log_init = true; + } +} + +#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). + */ +/** + * hif_target_sleep_state_adjust() - on-demand sleep/wake + * @scn: ol_softc pointer. + * @sleep_ok: bool + * @wait_for_it: bool + * + * Output the pipe error counts of each pipe to log file + * + * Return: int + */ +#if ((CONFIG_ATH_PCIE_MAX_PERF == 0) && CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD) +int +hif_target_sleep_state_adjust(struct ol_softc *scn, + bool sleep_ok, bool wait_for_it) +{ + struct HIF_CE_state *hif_state = scn->hif_hdl; + A_target_id_t pci_addr = scn->mem; + static int max_delay; + struct hif_pci_softc *sc = scn->hif_sc; + static int debug; + + if (scn->recovery) + return -EACCES; + + if (cdf_atomic_read(&scn->link_suspended)) { + HIF_ERROR("%s:invalid access, PCIe link is down", __func__); + debug = true; + CDF_ASSERT(0); + return -EACCES; + } + + if (debug) { + wait_for_it = true; + HIF_ERROR("%s: doing debug for invalid access, PCIe link is suspended", + __func__); + CDF_ASSERT(0); + } + + if (sleep_ok) { + cdf_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 = cdf_system_ticks(); + } + if (hif_state->fake_sleep == false) { + /* Set the Fake Sleep */ + hif_state->fake_sleep = true; + + /* Start the Sleep Timer */ + cdf_softirq_timer_cancel(&hif_state->sleep_timer); + cdf_softirq_timer_start(&hif_state->sleep_timer, + HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } + cdf_spin_unlock_irqrestore(&hif_state->keep_awake_lock); + } else { + cdf_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 */ + hif_write32_mb(pci_addr + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + } + } + hif_state->keep_awake_count++; + cdf_spin_unlock_irqrestore(&hif_state->keep_awake_lock); + + if (wait_for_it && !hif_state->verified_awake) { +#define PCIE_SLEEP_ADJUST_TIMEOUT 8000 /* 8Ms */ + int tot_delay = 0; + int curr_delay = 5; + + for (;; ) { + if (hif_targ_is_awake(scn, pci_addr)) { + hif_state->verified_awake = true; + break; + } else + if (!hif_pci_targ_is_present + (scn, pci_addr)) { + break; + } + if (tot_delay > PCIE_SLEEP_ADJUST_TIMEOUT) { + uint16_t val; + uint32_t bar; + + HIF_ERROR("%s: keep_awake_count = %d", + __func__, + hif_state->keep_awake_count); + + pci_read_config_word(sc->pdev, + PCI_VENDOR_ID, + &val); + HIF_ERROR("%s: PCI Vendor ID = 0x%04x", + __func__, val); + + pci_read_config_word(sc->pdev, + PCI_DEVICE_ID, + &val); + HIF_ERROR("%s: PCI Device ID = 0x%04x", + __func__, val); + + pci_read_config_word(sc->pdev, + PCI_COMMAND, &val); + HIF_ERROR("%s: PCI Command = 0x%04x", + __func__, val); + + pci_read_config_word(sc->pdev, + PCI_STATUS, &val); + HIF_ERROR("%s: PCI Status = 0x%04x", + __func__, val); + + pci_read_config_dword(sc->pdev, + PCI_BASE_ADDRESS_0, &bar); + HIF_ERROR("%s: PCI BAR 0 = 0x%08x", + __func__, bar); + + HIF_ERROR("%s: SOC_WAKE_ADDR 0%08x", + __func__, + hif_read32_mb(pci_addr + + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS)); + HIF_ERROR("%s: RTC_STATE_ADDR 0x%08x", + __func__, + hif_read32_mb(pci_addr + + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS)); + + HIF_ERROR("%s:error, wakeup target", + __func__); + hif_msm_pcie_debug_info(sc); + if (!sc->ol_sc->enable_self_recovery) + CDF_BUG(0); + scn->recovery = true; + cds_set_logp_in_progress(true); + cnss_wlan_pci_link_down(); + 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; + HIF_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__, + hif_read32_mb(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_ENABLE_ADDRESS), + hif_read32_mb(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CAUSE_ADDRESS), + hif_read32_mb(sc->mem + SOC_CORE_BASE_ADDRESS + + CPU_INTR_ADDRESS), + hif_read32_mb(sc->mem + SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CLR_ADDRESS), + hif_read32_mb(sc->mem + CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); + } + + return 0; +} +#else +inline int +hif_target_sleep_state_adjust(struct ol_softc *scn, + bool sleep_ok, bool wait_for_it) +{ + return 0; +} +#endif + +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG +uint32_t hif_target_read_checked(struct ol_softc *scn, uint32_t offset) +{ + uint32_t value; + void *addr; + + if (!A_TARGET_ACCESS_OK(scn)) + hi_fdebug(); + + addr = scn->mem + 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 +hif_target_write_checked(struct ol_softc *scn, uint32_t offset, uint32_t value) +{ + void *addr; + + if (!A_TARGET_ACCESS_OK(scn)) + hi_fdebug(); + + addr = scn->mem + (offset); + hif_write32_mb(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); + } +} + +/** + * hi_fdebug() - not needed in PCI + * + * + * Return: n/a + */ +void hi_fdebug(void) +{ + /* BUG_ON(1); */ +} + +/** + * hif_target_dump_access_log() - dump access log + * + * dump access log + * + * Return: n/a + */ +void hif_target_dump_access_log(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; + HIF_ERROR("%s: idx:%d sn:%u wr:%d addr:%p val:%u.", + __func__, 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 + +/** + * war_pci_write32() - PCIe io32 write workaround + * @addr: addr + * @offset: offset + * @value: value + * + * iowrite32 + * + * Return: int + */ +void war_pci_write32(char *addr, uint32_t offset, uint32_t value) +{ + if (hif_pci_war1) { + unsigned long irq_flags; + + spin_lock_irqsave(&pciwar_lock, irq_flags); + + (void)ioread32((void __iomem *)(addr + offset + 4)); + (void)ioread32((void __iomem *)(addr + offset + 4)); + (void)ioread32((void __iomem *)(addr + offset + 4)); + iowrite32((uint32_t) (value), (void __iomem *)(addr + offset)); + + spin_unlock_irqrestore(&pciwar_lock, irq_flags); + } else { + iowrite32((uint32_t) (value), (void __iomem *)(addr + offset)); + } +} + +/** + * hif_configure_irq(): configure interrupt + * + * This function configures interrupt(s) + * + * @sc: PCIe control struct + * @hif_hdl: struct HIF_CE_state + * + * Return: 0 - for success + */ +int hif_configure_irq(struct hif_pci_softc *sc) +{ + int ret = 0; + struct ol_softc *scn = sc->ol_sc; + + HIF_TRACE("%s: E", __func__); + + if (ENABLE_MSI) { + ret = hif_configure_msi(sc); + if (ret == 0) + goto end; + } + /* MSI failed. Try legacy irq */ + ret = hif_pci_configure_legacy_irq(sc); + if (ret < 0) { + HIF_ERROR("%s: hif_pci_configure_legacy_irq error = %d", + __func__, ret); + return ret; + } +end: + scn->request_irq_done = true; + return 0; +} + +/** + * hif_target_sync() : ensure the target is ready + * @scn: hif controll structure + * + * Informs fw that we plan to use legacy interupts so that + * it can begin booting. Ensures that the fw finishes booting + * before continuing. Should be called before trying to write + * to the targets other registers for the first time. + * + * Return: none + */ +void hif_target_sync(struct ol_softc *scn) +{ + hif_write32_mb(scn->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK); + + hif_write32_mb(scn->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + while (!hif_targ_is_awake(scn, scn->mem)) + ; + + if (HAS_FW_INDICATOR) { + int wait_limit = 500; + int fw_ind = 0; + HIF_TRACE("%s: Loop checking FW signal", __func__); + while (1) { + fw_ind = hif_read32_mb(scn->hif_sc->mem + + FW_INDICATOR_ADDRESS); + if (fw_ind & FW_IND_INITIALIZED) + break; + if (wait_limit-- < 0) + break; + hif_write32_mb(scn->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS), + PCIE_INTR_FIRMWARE_MASK); + + cdf_mdelay(10); + } + if (wait_limit < 0) + HIF_TRACE("%s: FW signal timed out", + __func__); + else + HIF_TRACE("%s: Got FW signal, retries = %x", + __func__, 500-wait_limit); + } + hif_write32_mb(scn->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); +} + +/** + * hif_enable_bus(): enable bus + * + * This function enables the bus + * + * @ol_sc: soft_sc struct + * @dev: device pointer + * @bdev: bus dev pointer + * bid: bus id pointer + * type: enum hif_enable_type such as HIF_ENABLE_TYPE_PROBE + * Return: CDF_STATUS + */ +CDF_STATUS hif_enable_bus(struct ol_softc *ol_sc, + struct device *dev, void *bdev, + const hif_bus_id *bid, + enum hif_enable_type type) +{ + int ret = 0; + uint32_t hif_type, target_type; + struct hif_pci_softc *sc; + uint16_t revision_id; + uint32_t lcr_val; + int probe_again = 0; + struct pci_dev *pdev = bdev; + const struct pci_device_id *id = bid; + + HIF_TRACE("%s: con_mode = 0x%x, device_id = 0x%x", + __func__, cds_get_conparam(), id->device); + + ol_sc = cds_get_context(CDF_MODULE_ID_HIF); + if (!ol_sc) { + HIF_ERROR("%s: hif_ctx is NULL", __func__); + return CDF_STATUS_E_NOMEM; + } + sc = ol_sc->hif_sc; + ol_sc->aps_osdev.bdev = pdev; + + sc->pdev = pdev; + sc->dev = &pdev->dev; + ol_sc->aps_osdev.bdev = pdev; + ol_sc->aps_osdev.device = &pdev->dev; + ol_sc->aps_osdev.bc.bc_handle = (void *)ol_sc->mem; + ol_sc->aps_osdev.bc.bc_bustype = type; + sc->devid = id->device; + sc->cacheline_sz = dma_get_cache_alignment(); +again: + ret = hif_enable_pci(sc, pdev, id); + if (ret < 0) { + HIF_ERROR("%s: ERROR - hif_enable_pci error = %d", + __func__, ret); + goto err_enable_pci; + } + HIF_TRACE("%s: hif_enable_pci done", __func__); + + /* 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)); + + device_disable_async_suspend(&pdev->dev); + pci_read_config_word(pdev, 0x08, &revision_id); + + ret = hif_get_device_type(id->device, revision_id, + &hif_type, &target_type); + if (ret < 0) { + HIF_ERROR("%s: invalid device id/revision_id", __func__); + goto err_tgtstate; + } + HIF_TRACE("%s: hif_type = 0x%x, target_type = 0x%x", + __func__, hif_type, target_type); + + hif_register_tbl_attach(sc->ol_sc, hif_type); + target_register_tbl_attach(sc->ol_sc, target_type); + + ret = hif_pci_probe_tgt_wakeup(sc); + if (ret < 0) { + HIF_ERROR("%s: ERROR - hif_pci_prob_wakeup error = %d", + __func__, ret); + if (ret == -EAGAIN) + probe_again++; + goto err_tgtstate; + } + HIF_TRACE("%s: hif_pci_probe_tgt_wakeup done", __func__); + + ol_sc->target_type = target_type; + sc->soc_pcie_bar0 = pci_resource_start(pdev, BAR_NUM); + if (!sc->soc_pcie_bar0) { + HIF_ERROR("%s: ERROR - cannot get CE BAR0", __func__); + ret = -EIO; + goto err_tgtstate; + } + ol_sc->mem_pa = sc->soc_pcie_bar0; + + BUG_ON(pci_get_drvdata(sc->pdev) != NULL); + pci_set_drvdata(sc->pdev, sc); + + ret = hif_init_cdf_ctx(ol_sc); + if (ret != 0) { + HIF_ERROR("%s: cannot init CDF", __func__); + goto err_tgtstate; + } + + hif_target_sync(ol_sc); + return 0; + +err_tgtstate: + hif_deinit_cdf_ctx(ol_sc); + hif_disable_pci(sc); + sc->pci_enabled = false; + HIF_ERROR("%s: error, hif_disable_pci done", __func__); + return CDF_STATUS_E_ABORTED; + +err_enable_pci: + if (probe_again && (probe_again <= ATH_PCI_PROBE_RETRY_MAX)) { + int delay_time; + + HIF_INFO("%s: pci reprobe", __func__); + /* 10, 40, 90, 100, 100, ... */ + delay_time = max(100, 10 * (probe_again * probe_again)); + cdf_mdelay(delay_time); + goto again; + } + return ret; +} + +/** + * hif_get_target_type(): Get the target type + * + * This function is used to query the target type. + * + * @ol_sc: ol_softc struct pointer + * @dev: device pointer + * @bdev: bus dev pointer + * @bid: bus id pointer + * @hif_type: HIF type such as HIF_TYPE_QCA6180 + * @target_type: target type such as TARGET_TYPE_QCA6180 + * + * Return: 0 for success + */ +int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, + void *bdev, const hif_bus_id *bid, uint32_t *hif_type, + uint32_t *target_type) +{ + uint16_t revision_id; + struct pci_dev *pdev = bdev; + const struct pci_device_id *id = bid; + + pci_read_config_word(pdev, 0x08, &revision_id); + return hif_get_device_type(id->device, revision_id, + hif_type, target_type); +} diff --git a/core/hif/src/pcie/if_pci.h b/core/hif/src/pcie/if_pci.h new file mode 100644 index 000000000000..b2f5bd6c20a2 --- /dev/null +++ b/core/hif/src/pcie/if_pci.h @@ -0,0 +1,115 @@ +/* + * 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 ATH_DBG_DEFAULT 0 +#include +#include +#include +#include "osapi_linux.h" +#include "hif.h" +#include "cepci.h" + +struct CE_state; +struct ol_softc; + +/* An address (e.g. of a buffer) in Copy Engine space. */ + +#define HIF_MAX_TASKLET_NUM 11 +struct hif_tasklet_entry { + uint8_t id; /* 0 - 9: maps to CE, 10: fw */ + void *hif_handler; /* struct hif_pci_softc */ +}; +struct hif_pci_softc { + void __iomem *mem; /* PCI address. */ + /* For efficiency, should be first in struct */ + + struct device *dev; + struct pci_dev *pdev; + 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; + u16 devid; + cdf_dma_addr_t soc_pcie_bar0; + struct hif_tasklet_entry tasklet_entries[HIF_MAX_TASKLET_NUM]; + bool pci_enabled; +}; + +bool hif_pci_targ_is_present(struct ol_softc *scn, void *__iomem *mem); +void icnss_dispatch_ce_irq(struct ol_softc *scn); +int hif_configure_irq(struct hif_pci_softc *sc); +void hif_pci_cancel_deferred_target_sleep(struct ol_softc *scn); + +/* + * 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() + */ +#ifndef QCA_WIFI_3_0_EMU +#define OL_ATH_TX_DRAIN_WAIT_CNT 10 +#else +#define OL_ATH_TX_DRAIN_WAIT_CNT 60 +#endif + +#define HIF_CE_DRAIN_WAIT_CNT 20 +#endif /* __ATH_PCI_H__ */ diff --git a/core/hif/src/pcie/if_pci_internal.h b/core/hif/src/pcie/if_pci_internal.h new file mode 100644 index 000000000000..e5f28d2b2774 --- /dev/null +++ b/core/hif/src/pcie/if_pci_internal.h @@ -0,0 +1,110 @@ +/* + * 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 __IF_PCI_INTERNAL_H__ +#define __IF_PCI_INTERNAL_H__ +#ifdef CONFIG_CNSS +#define HIF_REGISTER_DRIVER(wlan_drv_id) \ + cnss_wlan_register_driver(wlan_drv_id) +#define HIF_UNREGISTER_DRIVER(wlan_drv_id) \ + cnss_wlan_unregister_driver(wlan_drv_id) +#else +#define HIF_REGISTER_DRIVER(wlan_drv_id) \ + pci_register_driver(wlan_drv_id) +#define HIF_UNREGISTER_DRIVER(wlan_drv_id) \ + pci_unregister_driver(wlan_drv_id) +#endif + +#ifdef DISABLE_L1SS_STATES +#define PCI_CFG_TO_DISABLE_L1SS_STATES(pdev, addr) \ +{ \ + uint32_t lcr_val; \ + pci_read_config_dword(pdev, addr, &lcr_val); \ + pci_write_config_dword(pdev, addr, (lcr_val & ~0x0000000f)); \ +} +#else +#define PCI_CFG_TO_DISABLE_L1SS_STATES(pdev, addr) +#endif + +#if defined(CONFIG_CNSS) && !defined(QCA_WIFI_3_0) +#define GET_VIRT_RAMDUMP_MEM(ol_sc) \ +{ \ + ol_sc->ramdump_base = cnss_get_virt_ramdump_mem(&ol_sc->ramdump_size); \ + if (ol_sc->ramdump_base == NULL || !ol_sc->ramdump_size) \ + HIF_ERROR("%s: Failed to get RAM dump memory addr or size!", \ + __func__); \ +} +#else +#define GET_VIRT_RAMDUMP_MEM(ol_sc) +#endif + +#ifdef QCA_WIFI_3_0 +#define PCI_CLR_CAUSE0_REGISTER(sc) \ +{ \ + uint32_t tmp_cause0; \ + tmp_cause0 = hif_read32_mb(sc->mem + PCIE_INTR_CAUSE_ADDRESS); \ + hif_write32_mb(sc->mem + PCIE_INTR_CLR_ADDRESS, \ + PCIE_INTR_FIRMWARE_MASK | tmp_cause0); \ + hif_read32_mb(sc->mem + PCIE_INTR_CLR_ADDRESS); \ + hif_write32_mb(sc->mem + PCIE_INTR_CLR_ADDRESS, 0); \ + hif_read32_mb(sc->mem + PCIE_INTR_CLR_ADDRESS); \ +} + +#define HIF_PCI_TARG_IS_AWAKE(scn, mem) \ +{ \ + return 1; \ +} +#else +#define PCI_CLR_CAUSE0_REGISTER(sc) + +#define HIF_PCI_TARG_IS_AWAKE(scn, mem) \ +{ \ + uint32_t val; \ + if (scn->recovery) \ + return false; \ + val = hif_read32_mb(mem + PCIE_LOCAL_BASE_ADDRESS \ + + RTC_STATE_ADDRESS); \ + return RTC_STATE_V_GET(val) == RTC_STATE_V_ON; \ +} +#endif + +#if !defined(REMOVE_PKT_LOG) && !defined(QVIT) +#define PKT_LOG_MOD_INIT(ol_sc) \ +{ \ + ol_txrx_pdev_handle pdev_txrx_handle; \ + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); \ + if (cds_get_conparam() != CDF_FTM_MODE && \ + !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { \ + ol_pl_sethandle(&pdev_txrx_handle->pl_dev, ol_sc); \ + if (pktlogmod_init(ol_sc)) \ + HIF_ERROR("%s: pktlogmod_init failed", __func__); \ + } \ +} +#else +#define PKT_LOG_MOD_INIT(ol_sc) +#endif +#endif /* __IF_PCI_INTERNAL_H__ */ diff --git a/core/hif/src/qca6180def.h b/core/hif/src/qca6180def.h new file mode 100644 index 000000000000..cdfc2a325665 --- /dev/null +++ b/core/hif/src/qca6180def.h @@ -0,0 +1,1008 @@ +/* + * 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 _QCA6180DEF_H_ +#define _QCA6180DEF_H_ + +#define MISSING 0 +#define _PCIE_LOCAL_REG_BASE_ADDRESS 0x1E8000 +#define _WIFI_RTC_REG_BASE_ADDRESS 0x45000 +#define _RTC_SOC_REG_BASE_ADDRESS 0x113000 +#define _GPIO_ATHR_WLAN_REG_BASE_ADDRESS 0x85000 +#define _SI_REG_BASE_ADDRESS 0x84000 +#define _SOC_CORE_REG_BASE_ADDRESS 0x113000 +#define _CE_REG_CSR_BASE_ADDRESS 0x240000 +#define _CE0_CE_REG_CSR_BASE_ADDRESS 0 +#define _CE_WRAPPER_REG_CSR_BASE_ADDRESS 0xC000 +#define _MAC_WIFICMN_REG_BASE_ADDRESS MISSING + +/* Base Addresses */ +#define QCA6180_RTC_SOC_BASE_ADDRESS 0x00000000 +#define QCA6180_RTC_WMAC_BASE_ADDRESS 0x00000000 +#define QCA6180_MAC_COEX_BASE_ADDRESS 0x0000f000 +#define QCA6180_BT_COEX_BASE_ADDRESS 0x00002000 +#define QCA6180_SOC_PCIE_BASE_ADDRESS 0x00130000 +#define QCA6180_SOC_CORE_BASE_ADDRESS 0x00000000 +#define QCA6180_WLAN_UART_BASE_ADDRESS 0x00111000 +#define QCA6180_WLAN_SI_BASE_ADDRESS 0x00010000 +#define QCA6180_WLAN_GPIO_BASE_ADDRESS 0x00000000 +#define QCA6180_WLAN_ANALOG_INTF_BASE_ADDRESS 0x00000000 +#define QCA6180_WLAN_MAC_BASE_ADDRESS 0x00000000 +#define QCA6180_EFUSE_BASE_ADDRESS 0x00024000 +#define QCA6180_FPGA_REG_BASE_ADDRESS 0x00039000 +#define QCA6180_WLAN_UART2_BASE_ADDRESS 0x00054c00 +#define QCA6180_CE_WRAPPER_BASE_ADDRESS 0x24C000 +#define QCA6180_CE0_BASE_ADDRESS 0x240000 +#define QCA6180_CE1_BASE_ADDRESS 0x241000 +#define QCA6180_CE2_BASE_ADDRESS 0x242000 +#define QCA6180_CE3_BASE_ADDRESS 0x243000 +#define QCA6180_CE4_BASE_ADDRESS 0x244000 +#define QCA6180_CE5_BASE_ADDRESS 0x245000 +#define QCA6180_CE6_BASE_ADDRESS 0x246000 +#define QCA6180_CE7_BASE_ADDRESS 0x247000 +#define QCA6180_CE8_BASE_ADDRESS 0x248000 +#define QCA6180_CE9_BASE_ADDRESS 0x249000 +#define QCA6180_CE10_BASE_ADDRESS 0x24A000 +#define QCA6180_CE11_BASE_ADDRESS 0x24B000 +#define QCA6180_A_SOC_PCIE_SOC_PCIE_REG 0x130000 +#define QCA6180_DBI_BASE_ADDRESS 0x0003c000 +#define QCA6180_WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x00007800 +#define QCA6180_WIFICMN_BASE_ADDRESS 0x00000000 +#define QCA6180_BOARD_DATA_SZ MISSING +#define QCA6180_BOARD_EXT_DATA_SZ MISSING +#define QCA6180_A_SOC_PCIE_PCIE_BAR0_START \ + (0x030 + QCA6180_A_SOC_PCIE_SOC_PCIE_REG) +#define QCA6180_A_SOC_CORE_SCRATCH_0_ADDRESS 0x00114000 +#define QCA6180_A_SOC_CORE_SCRATCH_1_ADDRESS 0x00114004 +#define QCA6180_A_SOC_CORE_SCRATCH_2_ADDRESS 0x00114008 +#define QCA6180_A_SOC_CORE_SCRATCH_3_ADDRESS 0x0011400c +#define QCA6180_A_SOC_CORE_SCRATCH_4_ADDRESS 0x00114010 +#define QCA6180_A_SOC_CORE_SCRATCH_5_ADDRESS 0x00114014 +#define QCA6180_A_SOC_CORE_SCRATCH_6_ADDRESS 0x00114018 +#define QCA6180_A_SOC_CORE_SCRATCH_7_ADDRESS 0x0011401c +#define QCA6180_A_SOC_CORE_SPARE_0_REGISTER 0x00113180 +#define QCA6180_PCIE_INTR_FIRMWARE_ROUTE_MASK 0xff +#define QCA6180_SCRATCH_3_ADDRESS 0x00113020 +#define QCA6180_TARG_DRAM_START 0x00400000 +#define QCA6180_SOC_SYSTEM_SLEEP_OFFSET 0x000000c0 +#define QCA6180_SOC_RESET_CONTROL_OFFSET \ + (0x00000000 + _RTC_SOC_REG_BASE_ADDRESS) +#define QCA6180_SOC_CLOCK_CONTROL_OFFSET \ + (0x00000028 + _RTC_SOC_REG_BASE_ADDRESS) +#define QCA6180_SOC_CLOCK_CONTROL_SI0_CLK_MASK 0x00000001 +#define QCA6180_SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 +#define QCA6180_WLAN_GPIO_PIN0_ADDRESS \ + (0x50 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN1_ADDRESS \ + (0x54 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800 +#define QCA6180_WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800 +#define QCA6180_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define QCA6180_SOC_LPO_CAL_OFFSET \ + (0xe0 + _RTC_SOC_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN10_ADDRESS \ + (0x78 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN11_ADDRESS \ + (0x7c + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN12_ADDRESS \ + (0x80 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_WLAN_GPIO_PIN13_ADDRESS \ + (0x84 + _GPIO_ATHR_WLAN_REG_BASE_ADDRESS) +#define QCA6180_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define QCA6180_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +#define QCA6180_SOC_LPO_CAL_ENABLE_LSB 20 +#define QCA6180_SOC_LPO_CAL_ENABLE_MASK 0x00100000 + +#define QCA6180_WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 +#define QCA6180_WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001 +#define QCA6180_WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000002 +#define QCA6180_WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000001 +#define QCA6180_SI_CONFIG_BIDIR_OD_DATA_LSB 18 +#define QCA6180_SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000 +#define QCA6180_SI_CONFIG_I2C_LSB 16 +#define QCA6180_SI_CONFIG_I2C_MASK 0x00010000 +#define QCA6180_SI_CONFIG_POS_SAMPLE_LSB 7 +#define QCA6180_SI_CONFIG_POS_SAMPLE_MASK 0x00000080 +#define QCA6180_SI_CONFIG_INACTIVE_CLK_LSB 4 +#define QCA6180_SI_CONFIG_INACTIVE_CLK_MASK 0x00000010 +#define QCA6180_SI_CONFIG_INACTIVE_DATA_LSB 5 +#define QCA6180_SI_CONFIG_INACTIVE_DATA_MASK 0x00000020 +#define QCA6180_SI_CONFIG_DIVIDER_LSB 0 +#define QCA6180_SI_CONFIG_DIVIDER_MASK 0x0000000f +#define QCA6180_SI_CONFIG_OFFSET (0x00000000 + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_TX_DATA0_OFFSET (0x00000008 + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_TX_DATA1_OFFSET (0x0000000c + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_RX_DATA0_OFFSET (0x00000010 + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_RX_DATA1_OFFSET (0x00000014 + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_CS_OFFSET (0x00000004 + _SI_REG_BASE_ADDRESS) +#define QCA6180_SI_CS_DONE_ERR_MASK 0x00000400 +#define QCA6180_SI_CS_DONE_INT_MASK 0x00000200 +#define QCA6180_SI_CS_START_LSB 8 +#define QCA6180_SI_CS_START_MASK 0x00000100 +#define QCA6180_SI_CS_RX_CNT_LSB 4 +#define QCA6180_SI_CS_RX_CNT_MASK 0x000000f0 +#define QCA6180_SI_CS_TX_CNT_LSB 0 +#define QCA6180_SI_CS_TX_CNT_MASK 0x0000000f +#define QCA6180_CE_COUNT 8 +#define QCA6180_SR_WR_INDEX_ADDRESS (0x003C + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_DST_WATERMARK_ADDRESS (0x0050 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_RX_MSDU_END_4_FIRST_MSDU_LSB 14 +#define QCA6180_RX_MSDU_END_4_FIRST_MSDU_MASK 0x00004000 +#define QCA6180_RX_MPDU_START_0_SEQ_NUM_LSB 16 +#define QCA6180_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 +#define QCA6180_RX_MPDU_START_2_PN_47_32_LSB 0 +#define QCA6180_RX_MPDU_START_2_PN_47_32_MASK 0x0000ffff +#define QCA6180_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB 16 +#define QCA6180_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK 0xffff0000 +#define QCA6180_RX_MSDU_END_4_LAST_MSDU_LSB 15 +#define QCA6180_RX_MSDU_END_4_LAST_MSDU_MASK 0x00008000 +#define QCA6180_RX_ATTENTION_0_MCAST_BCAST_LSB 2 +#define QCA6180_RX_ATTENTION_0_MCAST_BCAST_MASK 0x00000004 +#define QCA6180_RX_ATTENTION_0_FRAGMENT_LSB 13 +#define QCA6180_RX_ATTENTION_0_FRAGMENT_MASK 0x00002000 +#define QCA6180_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK 0x08000000 +#define QCA6180_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB 16 +#define QCA6180_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK 0x00ff0000 +#define QCA6180_RX_MSDU_START_0_MSDU_LENGTH_LSB 0 +#define QCA6180_RX_MSDU_START_0_MSDU_LENGTH_MASK 0x00003fff + +#define QCA6180_RX_MSDU_START_2_DECAP_FORMAT_OFFSET 0x00000008 +#define QCA6180_RX_MSDU_START_2_DECAP_FORMAT_LSB 8 +#define QCA6180_RX_MSDU_START_2_DECAP_FORMAT_MASK 0x00000300 +#define QCA6180_RX_MPDU_START_0_ENCRYPTED_LSB 13 +#define QCA6180_RX_MPDU_START_0_ENCRYPTED_MASK 0x00002000 +#define QCA6180_RX_ATTENTION_0_MORE_DATA_MASK 0x00000400 +#define QCA6180_RX_ATTENTION_0_MSDU_DONE_MASK 0x80000000 +#define QCA6180_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK 0x00040000 +#define QCA6180_DST_WR_INDEX_ADDRESS (0x0040 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_SRC_WATERMARK_ADDRESS (0x004c + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_SRC_WATERMARK_LOW_MASK 0xffff0000 +#define QCA6180_SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define QCA6180_DST_WATERMARK_LOW_MASK 0xffff0000 +#define QCA6180_DST_WATERMARK_HIGH_MASK 0x0000ffff +#define QCA6180_CURRENT_SRRI_ADDRESS (0x0044 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CURRENT_DRRI_ADDRESS (0x0048 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define QCA6180_HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define QCA6180_HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define QCA6180_HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define QCA6180_HOST_IS_ADDRESS (0x0030 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_MISC_IS_ADDRESS (0x0038 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 +#define QCA6180_CE_WRAPPER_INDEX_BASE_LOW 0x0004 +#define QCA6180_CE_WRAPPER_INDEX_BASE_HIGH 0x0008 +#define QCA6180_HOST_IE_ADDRESS (0x002C + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define QCA6180_SR_BA_ADDRESS (0x0000 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_SR_BA_ADDRESS_HIGH (0x0004 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_SR_SIZE_ADDRESS (0x0008 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_CTRL1_ADDRESS (0x0018 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define QCA6180_DR_BA_ADDRESS (0x000C + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_DR_BA_ADDRESS_HIGH (0x000C + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_DR_SIZE_ADDRESS (0x0014 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_CMD_REGISTER (0x0020 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_MSI_ADDRESS (0x0058 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_MSI_ADDRESS_HIGH (0x005C + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_MSI_DATA (0x0060 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_CE_MSI_ENABLE_BIT 16 +#define QCA6180_MISC_IE_ADDRESS (0x0034 + _CE0_CE_REG_CSR_BASE_ADDRESS) +#define QCA6180_MISC_IS_AXI_ERR_MASK 0x00000100 +#define QCA6180_MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define QCA6180_MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define QCA6180_MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define QCA6180_MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define QCA6180_MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 +#define QCA6180_WRAPPER_INTERRUPT_SUMMARY_ADDR 0x0024D000 +#define QCA6180_SRC_WATERMARK_LOW_LSB 16 +#define QCA6180_SRC_WATERMARK_HIGH_LSB 0 +#define QCA6180_DST_WATERMARK_LOW_LSB 16 +#define QCA6180_DST_WATERMARK_HIGH_LSB 0 +#define QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0xfff000 +#define QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 12 +#define QCA6180_CE_CTRL1_DMAX_LENGTH_LSB 0 +#define QCA6180_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define QCA6180_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00040000 +#define QCA6180_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 17 +#define QCA6180_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 18 +#define QCA6180_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK 0x0000004 +#define QCA6180_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB 2 +#define QCA6180_SOC_GLOBAL_RESET_ADDRESS \ + (0x0008 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_RTC_STATE_ADDRESS \ + (0x0000 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_RTC_STATE_COLD_RESET_MASK 0x400 + +#define QCA6180_PCIE_SOC_WAKE_RESET 0x00000000 +#define QCA6180_PCIE_SOC_WAKE_ADDRESS (0x0004 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_PCIE_SOC_WAKE_V_MASK 0x00000001 + +#define QCA6180_RTC_STATE_V_MASK 0x00000007 +#define QCA6180_RTC_STATE_V_LSB 0 +#define QCA6180_RTC_STATE_V_ON 5 +#define QCA6180_PCIE_LOCAL_BASE_ADDRESS 0x0 +#define QCA6180_FW_IND_EVENT_PENDING 1 +#define QCA6180_FW_IND_INITIALIZED 2 +#define QCA6180_FW_IND_HELPER 4 + +#define QCA6180_PCIE_INTR_ENABLE_ADDRESS (0x000c + _SOC_CORE_REG_BASE_ADDRESS) +#define QCA6180_PCIE_INTR_CLR_ADDRESS (0x001c + _SOC_CORE_REG_BASE_ADDRESS) +#define QCA6180_PCIE_INTR_FIRMWARE_MASK 0x00100000 +#define QCA6180_PCIE_INTR_CE0_MASK 0x00000100 +#define QCA6180_PCIE_INTR_CE_MASK_ALL 0x0000ff00 +#define QCA6180_PCIE_INTR_CAUSE_ADDRESS (0x0014 + _SOC_CORE_REG_BASE_ADDRESS) + +#define QCA6180_CPU_INTR_ADDRESS 0xffffffff +#define QCA6180_SOC_LF_TIMER_CONTROL0_ADDRESS 0xffffffff +#define QCA6180_SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0xffffffff +#define QCA6180_SOC_RESET_CONTROL_ADDRESS \ + (0x00000000 + _RTC_SOC_REG_BASE_ADDRESS) +#define QCA6180_SOC_RESET_CONTROL_CE_RST_MASK 0x0100 +#define QCA6180_SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 +#define QCA6180_CORE_CTRL_ADDRESS (0x0000 + _SOC_CORE_REG_BASE_ADDRESS) +#define QCA6180_CORE_CTRL_CPU_INTR_MASK 0x00002000 +#define QCA6180_LOCAL_SCRATCH_OFFSET 0x00000018 +#define QCA6180_CLOCK_GPIO_OFFSET 0xffffffff +#define QCA6180_CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0 +#define QCA6180_CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0 +#define QCA6180_SOC_CHIP_ID_ADDRESS 0x000000f0 +#define QCA6180_SOC_CHIP_ID_VERSION_MASK 0xfffc0000 +#define QCA6180_SOC_CHIP_ID_VERSION_LSB 18 +#define QCA6180_SOC_CHIP_ID_REVISION_MASK 0x00000f00 +#define QCA6180_SOC_CHIP_ID_REVISION_LSB 8 +#define QCA6180_SOC_POWER_REG_OFFSET 0x0000010c + +/* Copy Engine Debug */ +#define QCA6180_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c +#define QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_MSB 3 +#define QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_LSB 0 +#define QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_MASK 0x0000000f +#define QCA6180_WLAN_DEBUG_CONTROL_OFFSET 0x00000108 +#define QCA6180_WLAN_DEBUG_CONTROL_ENABLE_MSB 0 +#define QCA6180_WLAN_DEBUG_CONTROL_ENABLE_LSB 0 +#define QCA6180_WLAN_DEBUG_CONTROL_ENABLE_MASK 0x00000001 +#define QCA6180_WLAN_DEBUG_OUT_OFFSET 0x00000110 +#define QCA6180_WLAN_DEBUG_OUT_DATA_MSB 19 +#define QCA6180_WLAN_DEBUG_OUT_DATA_LSB 0 +#define QCA6180_WLAN_DEBUG_OUT_DATA_MASK 0x000fffff +#define QCA6180_AMBA_DEBUG_BUS_OFFSET 0x0000011c +#define QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB 13 +#define QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB 8 +#define QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK 0x00003f00 +#define QCA6180_AMBA_DEBUG_BUS_SEL_MSB 4 +#define QCA6180_AMBA_DEBUG_BUS_SEL_LSB 0 +#define QCA6180_AMBA_DEBUG_BUS_SEL_MASK 0x0000001f +#define QCA6180_CE_WRAPPER_DEBUG_OFFSET 0x0008 +#define QCA6180_CE_WRAPPER_DEBUG_SEL_MSB 4 +#define QCA6180_CE_WRAPPER_DEBUG_SEL_LSB 0 +#define QCA6180_CE_WRAPPER_DEBUG_SEL_MASK 0x0000001f +#define QCA6180_CE_DEBUG_OFFSET 0x0054 +#define QCA6180_CE_DEBUG_SEL_MSB 5 +#define QCA6180_CE_DEBUG_SEL_LSB 0 +#define QCA6180_CE_DEBUG_SEL_MASK 0x0000003f +/* End */ + +/* PLL start */ +#define QCA6180_EFUSE_OFFSET 0x0000032c +#define QCA6180_EFUSE_XTAL_SEL_MSB 10 +#define QCA6180_EFUSE_XTAL_SEL_LSB 8 +#define QCA6180_EFUSE_XTAL_SEL_MASK 0x00000700 +#define QCA6180_BB_PLL_CONFIG_OFFSET 0x000002f4 +#define QCA6180_BB_PLL_CONFIG_OUTDIV_MSB 20 +#define QCA6180_BB_PLL_CONFIG_OUTDIV_LSB 18 +#define QCA6180_BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000 +#define QCA6180_BB_PLL_CONFIG_FRAC_MSB 17 +#define QCA6180_BB_PLL_CONFIG_FRAC_LSB 0 +#define QCA6180_BB_PLL_CONFIG_FRAC_MASK 0x0003ffff +#define QCA6180_WLAN_PLL_SETTLE_TIME_MSB 10 +#define QCA6180_WLAN_PLL_SETTLE_TIME_LSB 0 +#define QCA6180_WLAN_PLL_SETTLE_TIME_MASK 0x000007ff +#define QCA6180_WLAN_PLL_SETTLE_OFFSET 0x0018 +#define QCA6180_WLAN_PLL_SETTLE_SW_MASK 0x000007ff +#define QCA6180_WLAN_PLL_SETTLE_RSTMASK 0xffffffff +#define QCA6180_WLAN_PLL_SETTLE_RESET 0x00000400 +#define QCA6180_WLAN_PLL_CONTROL_NOPWD_MSB 18 +#define QCA6180_WLAN_PLL_CONTROL_NOPWD_LSB 18 +#define QCA6180_WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000 +#define QCA6180_WLAN_PLL_CONTROL_BYPASS_MSB 16 +#define QCA6180_WLAN_PLL_CONTROL_BYPASS_LSB 16 +#define QCA6180_WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000 +#define QCA6180_WLAN_PLL_CONTROL_BYPASS_RESET 0x1 +#define QCA6180_WLAN_PLL_CONTROL_CLK_SEL_MSB 15 +#define QCA6180_WLAN_PLL_CONTROL_CLK_SEL_LSB 14 +#define QCA6180_WLAN_PLL_CONTROL_CLK_SEL_MASK 0x0000c000 +#define QCA6180_WLAN_PLL_CONTROL_CLK_SEL_RESET 0x0 +#define QCA6180_WLAN_PLL_CONTROL_REFDIV_MSB 13 +#define QCA6180_WLAN_PLL_CONTROL_REFDIV_LSB 10 +#define QCA6180_WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00 +#define QCA6180_WLAN_PLL_CONTROL_REFDIV_RESET 0x0 +#define QCA6180_WLAN_PLL_CONTROL_DIV_MSB 9 +#define QCA6180_WLAN_PLL_CONTROL_DIV_LSB 0 +#define QCA6180_WLAN_PLL_CONTROL_DIV_MASK 0x000003ff +#define QCA6180_WLAN_PLL_CONTROL_DIV_RESET 0x11 +#define QCA6180_WLAN_PLL_CONTROL_OFFSET 0x0014 +#define QCA6180_WLAN_PLL_CONTROL_SW_MASK 0x001fffff +#define QCA6180_WLAN_PLL_CONTROL_RSTMASK 0xffffffff +#define QCA6180_WLAN_PLL_CONTROL_RESET 0x00010011 +#define QCA6180_SOC_CORE_CLK_CTRL_OFFSET 0x00000114 +#define QCA6180_SOC_CORE_CLK_CTRL_DIV_MSB 2 +#define QCA6180_SOC_CORE_CLK_CTRL_DIV_LSB 0 +#define QCA6180_SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007 +#define QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_MSB 5 +#define QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_LSB 5 +#define QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020 +#define QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_RESET 0x0 +#define QCA6180_RTC_SYNC_STATUS_OFFSET 0x0244 +#define QCA6180_SOC_CPU_CLOCK_OFFSET 0x00000020 +#define QCA6180_SOC_CPU_CLOCK_STANDARD_MSB 1 +#define QCA6180_SOC_CPU_CLOCK_STANDARD_LSB 0 +#define QCA6180_SOC_CPU_CLOCK_STANDARD_MASK 0x00000003 +/* PLL end */ + +#define QCA6180_PCIE_INTR_CE_MASK(n) (QCA6180_PCIE_INTR_CE0_MASK << (n)) +#define QCA6180_DRAM_BASE_ADDRESS QCA6180_TARG_DRAM_START +#define QCA6180_FW_INDICATOR_ADDRESS \ + (QCA6180_WIFICMN_BASE_ADDRESS + QCA6180_SCRATCH_3_ADDRESS) +#define QCA6180_SYSTEM_SLEEP_OFFSET QCA6180_SOC_SYSTEM_SLEEP_OFFSET +#define QCA6180_WLAN_SYSTEM_SLEEP_OFFSET (0x002c + _WIFI_RTC_REG_BASE_ADDRESS) +#define QCA6180_WLAN_RESET_CONTROL_OFFSET (0x0000 + _WIFI_RTC_REG_BASE_ADDRESS) +#define QCA6180_CLOCK_CONTROL_OFFSET QCA6180_SOC_CLOCK_CONTROL_OFFSET +#define QCA6180_CLOCK_CONTROL_SI0_CLK_MASK \ + QCA6180_SOC_CLOCK_CONTROL_SI0_CLK_MASK +#define QCA6180_RESET_CONTROL_MBOX_RST_MASK 0x00000004 +#define QCA6180_RESET_CONTROL_SI0_RST_MASK \ + QCA6180_SOC_RESET_CONTROL_SI0_RST_MASK +#define QCA6180_GPIO_BASE_ADDRESS QCA6180_WLAN_GPIO_BASE_ADDRESS +#define QCA6180_GPIO_PIN0_OFFSET QCA6180_WLAN_GPIO_PIN0_ADDRESS +#define QCA6180_GPIO_PIN1_OFFSET QCA6180_WLAN_GPIO_PIN1_ADDRESS +#define QCA6180_GPIO_PIN0_CONFIG_MASK QCA6180_WLAN_GPIO_PIN0_CONFIG_MASK +#define QCA6180_GPIO_PIN1_CONFIG_MASK QCA6180_WLAN_GPIO_PIN1_CONFIG_MASK +#define QCA6180_SI_BASE_ADDRESS 0x00000000 +#define QCA6180_CPU_CLOCK_OFFSET (0x20 + _RTC_SOC_REG_BASE_ADDRESS) +#define QCA6180_LPO_CAL_OFFSET QCA6180_SOC_LPO_CAL_OFFSET +#define QCA6180_GPIO_PIN10_OFFSET QCA6180_WLAN_GPIO_PIN10_ADDRESS +#define QCA6180_GPIO_PIN11_OFFSET QCA6180_WLAN_GPIO_PIN11_ADDRESS +#define QCA6180_GPIO_PIN12_OFFSET QCA6180_WLAN_GPIO_PIN12_ADDRESS +#define QCA6180_GPIO_PIN13_OFFSET QCA6180_WLAN_GPIO_PIN13_ADDRESS +#define QCA6180_CPU_CLOCK_STANDARD_LSB 0 +#define QCA6180_CPU_CLOCK_STANDARD_MASK 0x1 +#define QCA6180_LPO_CAL_ENABLE_LSB QCA6180_SOC_LPO_CAL_ENABLE_LSB +#define QCA6180_LPO_CAL_ENABLE_MASK QCA6180_SOC_LPO_CAL_ENABLE_MASK +#define QCA6180_ANALOG_INTF_BASE_ADDRESS QCA6180_WLAN_ANALOG_INTF_BASE_ADDRESS +#define QCA6180_MBOX_BASE_ADDRESS 0x00008000 +#define QCA6180_INT_STATUS_ENABLE_ERROR_LSB MISSING +#define QCA6180_INT_STATUS_ENABLE_ERROR_MASK MISSING +#define QCA6180_INT_STATUS_ENABLE_CPU_LSB MISSING +#define QCA6180_INT_STATUS_ENABLE_CPU_MASK MISSING +#define QCA6180_INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define QCA6180_INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define QCA6180_INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define QCA6180_INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define QCA6180_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define QCA6180_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define QCA6180_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define QCA6180_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define QCA6180_COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define QCA6180_COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define QCA6180_INT_STATUS_ENABLE_ADDRESS MISSING +#define QCA6180_CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define QCA6180_CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define QCA6180_HOST_INT_STATUS_ADDRESS MISSING +#define QCA6180_CPU_INT_STATUS_ADDRESS MISSING +#define QCA6180_ERROR_INT_STATUS_ADDRESS MISSING +#define QCA6180_ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define QCA6180_ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define QCA6180_ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define QCA6180_ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define QCA6180_ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define QCA6180_ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define QCA6180_COUNT_DEC_ADDRESS MISSING +#define QCA6180_HOST_INT_STATUS_CPU_MASK MISSING +#define QCA6180_HOST_INT_STATUS_CPU_LSB MISSING +#define QCA6180_HOST_INT_STATUS_ERROR_MASK MISSING +#define QCA6180_HOST_INT_STATUS_ERROR_LSB MISSING +#define QCA6180_HOST_INT_STATUS_COUNTER_MASK MISSING +#define QCA6180_HOST_INT_STATUS_COUNTER_LSB MISSING +#define QCA6180_RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define QCA6180_WINDOW_DATA_ADDRESS MISSING +#define QCA6180_WINDOW_READ_ADDR_ADDRESS MISSING +#define QCA6180_WINDOW_WRITE_ADDR_ADDRESS MISSING +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_0 \ + (0x0024 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_1 \ + (0x0028 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_2 \ + (0x002C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_3 \ + (0x0030 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_4 \ + (0x0034 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_5 \ + (0x0038 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_6 \ + (0x003C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_7 \ + (0x0040 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_8 \ + (0x0044 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_9 \ + (0x0048 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_10 \ + (0x004C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_11 \ + (0x0050 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_12 \ + (0x0054 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_13 \ + (0x0058 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_14 \ + (0x005C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_15 \ + (0x0060 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_16 \ + (0x0064 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_17 \ + (0x0068 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_18 \ + (0x006C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_19 \ + (0x0070 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_20 \ + (0x0074 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_21 \ + (0x0078 + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_22 \ + (0x007C + _PCIE_LOCAL_REG_BASE_ADDRESS) +#define QCA6180_A_LOCAL_SHADOW_REG_VALUE_23 \ + (0x0080 + _PCIE_LOCAL_REG_BASE_ADDRESS) + + +/* Q6 iHelium emulation registers */ +#define QCA6180_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 0x00113018 +#define QCA6180_A_SOC_CORE_SPARE_1_REGISTER 0x00113184 +#define QCA6180_A_SOC_CORE_PCIE_INTR_CLR_GRP1 0x00113020 +#define QCA6180_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 0x00113010 +#define QCA6180_A_SOC_PCIE_PCIE_SCRATCH_0 0x00130040 +#define QCA6180_A_SOC_PCIE_PCIE_SCRATCH_1 0x00130044 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE0_TARGET_IE 0x00240024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE0_TARGET_IS 0x00240028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE1_TARGET_IE 0x00241024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE1_TARGET_IS 0x00241028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE2_TARGET_IE 0x00242024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE2_TARGET_IS 0x00242028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE3_TARGET_IE 0x00243024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE3_TARGET_IS 0x00243028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE4_TARGET_IE 0x00244024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE4_TARGET_IS 0x00244028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE5_TARGET_IE 0x00245024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE5_TARGET_IS 0x00245028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE6_TARGET_IE 0x00246024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE6_TARGET_IS 0x00246028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE7_TARGET_IE 0x00247024 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE7_TARGET_IS 0x00247028 +#define QCA6180_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA 0x08 +#define QCA6180_A_SOC_PCIE_PCIE_SCRATCH_2 0x0013005C +#define QCA6180_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK 0x0 +/* end: Q6 iHelium emulation registers */ + +struct targetdef_s qca6180_targetdef = { + .d_RTC_SOC_BASE_ADDRESS = QCA6180_RTC_SOC_BASE_ADDRESS, + .d_RTC_WMAC_BASE_ADDRESS = QCA6180_RTC_WMAC_BASE_ADDRESS, + .d_SYSTEM_SLEEP_OFFSET = QCA6180_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_OFFSET = QCA6180_WLAN_SYSTEM_SLEEP_OFFSET, + .d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = + QCA6180_WLAN_SYSTEM_SLEEP_DISABLE_LSB, + .d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = + QCA6180_WLAN_SYSTEM_SLEEP_DISABLE_MASK, + .d_CLOCK_CONTROL_OFFSET = QCA6180_CLOCK_CONTROL_OFFSET, + .d_CLOCK_CONTROL_SI0_CLK_MASK = QCA6180_CLOCK_CONTROL_SI0_CLK_MASK, + .d_RESET_CONTROL_OFFSET = QCA6180_SOC_RESET_CONTROL_OFFSET, + .d_RESET_CONTROL_MBOX_RST_MASK = QCA6180_RESET_CONTROL_MBOX_RST_MASK, + .d_RESET_CONTROL_SI0_RST_MASK = QCA6180_RESET_CONTROL_SI0_RST_MASK, + .d_WLAN_RESET_CONTROL_OFFSET = QCA6180_WLAN_RESET_CONTROL_OFFSET, + .d_WLAN_RESET_CONTROL_COLD_RST_MASK = + QCA6180_WLAN_RESET_CONTROL_COLD_RST_MASK, + .d_WLAN_RESET_CONTROL_WARM_RST_MASK = + QCA6180_WLAN_RESET_CONTROL_WARM_RST_MASK, + .d_GPIO_BASE_ADDRESS = QCA6180_GPIO_BASE_ADDRESS, + .d_GPIO_PIN0_OFFSET = QCA6180_GPIO_PIN0_OFFSET, + .d_GPIO_PIN1_OFFSET = QCA6180_GPIO_PIN1_OFFSET, + .d_GPIO_PIN0_CONFIG_MASK = QCA6180_GPIO_PIN0_CONFIG_MASK, + .d_GPIO_PIN1_CONFIG_MASK = QCA6180_GPIO_PIN1_CONFIG_MASK, + .d_SI_CONFIG_BIDIR_OD_DATA_LSB = QCA6180_SI_CONFIG_BIDIR_OD_DATA_LSB, + .d_SI_CONFIG_BIDIR_OD_DATA_MASK = QCA6180_SI_CONFIG_BIDIR_OD_DATA_MASK, + .d_SI_CONFIG_I2C_LSB = QCA6180_SI_CONFIG_I2C_LSB, + .d_SI_CONFIG_I2C_MASK = QCA6180_SI_CONFIG_I2C_MASK, + .d_SI_CONFIG_POS_SAMPLE_LSB = QCA6180_SI_CONFIG_POS_SAMPLE_LSB, + .d_SI_CONFIG_POS_SAMPLE_MASK = QCA6180_SI_CONFIG_POS_SAMPLE_MASK, + .d_SI_CONFIG_INACTIVE_CLK_LSB = QCA6180_SI_CONFIG_INACTIVE_CLK_LSB, + .d_SI_CONFIG_INACTIVE_CLK_MASK = QCA6180_SI_CONFIG_INACTIVE_CLK_MASK, + .d_SI_CONFIG_INACTIVE_DATA_LSB = QCA6180_SI_CONFIG_INACTIVE_DATA_LSB, + .d_SI_CONFIG_INACTIVE_DATA_MASK = QCA6180_SI_CONFIG_INACTIVE_DATA_MASK, + .d_SI_CONFIG_DIVIDER_LSB = QCA6180_SI_CONFIG_DIVIDER_LSB, + .d_SI_CONFIG_DIVIDER_MASK = QCA6180_SI_CONFIG_DIVIDER_MASK, + .d_SI_BASE_ADDRESS = QCA6180_SI_BASE_ADDRESS, + .d_SI_CONFIG_OFFSET = QCA6180_SI_CONFIG_OFFSET, + .d_SI_TX_DATA0_OFFSET = QCA6180_SI_TX_DATA0_OFFSET, + .d_SI_TX_DATA1_OFFSET = QCA6180_SI_TX_DATA1_OFFSET, + .d_SI_RX_DATA0_OFFSET = QCA6180_SI_RX_DATA0_OFFSET, + .d_SI_RX_DATA1_OFFSET = QCA6180_SI_RX_DATA1_OFFSET, + .d_SI_CS_OFFSET = QCA6180_SI_CS_OFFSET, + .d_SI_CS_DONE_ERR_MASK = QCA6180_SI_CS_DONE_ERR_MASK, + .d_SI_CS_DONE_INT_MASK = QCA6180_SI_CS_DONE_INT_MASK, + .d_SI_CS_START_LSB = QCA6180_SI_CS_START_LSB, + .d_SI_CS_START_MASK = QCA6180_SI_CS_START_MASK, + .d_SI_CS_RX_CNT_LSB = QCA6180_SI_CS_RX_CNT_LSB, + .d_SI_CS_RX_CNT_MASK = QCA6180_SI_CS_RX_CNT_MASK, + .d_SI_CS_TX_CNT_LSB = QCA6180_SI_CS_TX_CNT_LSB, + .d_SI_CS_TX_CNT_MASK = QCA6180_SI_CS_TX_CNT_MASK, + .d_BOARD_DATA_SZ = QCA6180_BOARD_DATA_SZ, + .d_BOARD_EXT_DATA_SZ = QCA6180_BOARD_EXT_DATA_SZ, + .d_MBOX_BASE_ADDRESS = QCA6180_MBOX_BASE_ADDRESS, + .d_LOCAL_SCRATCH_OFFSET = QCA6180_LOCAL_SCRATCH_OFFSET, + .d_CPU_CLOCK_OFFSET = QCA6180_CPU_CLOCK_OFFSET, + .d_LPO_CAL_OFFSET = QCA6180_LPO_CAL_OFFSET, + .d_GPIO_PIN10_OFFSET = QCA6180_GPIO_PIN10_OFFSET, + .d_GPIO_PIN11_OFFSET = QCA6180_GPIO_PIN11_OFFSET, + .d_GPIO_PIN12_OFFSET = QCA6180_GPIO_PIN12_OFFSET, + .d_GPIO_PIN13_OFFSET = QCA6180_GPIO_PIN13_OFFSET, + .d_CLOCK_GPIO_OFFSET = QCA6180_CLOCK_GPIO_OFFSET, + .d_CPU_CLOCK_STANDARD_LSB = QCA6180_CPU_CLOCK_STANDARD_LSB, + .d_CPU_CLOCK_STANDARD_MASK = QCA6180_CPU_CLOCK_STANDARD_MASK, + .d_LPO_CAL_ENABLE_LSB = QCA6180_LPO_CAL_ENABLE_LSB, + .d_LPO_CAL_ENABLE_MASK = QCA6180_LPO_CAL_ENABLE_MASK, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = QCA6180_CLOCK_GPIO_BT_CLK_OUT_EN_LSB, + .d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = + QCA6180_CLOCK_GPIO_BT_CLK_OUT_EN_MASK, + .d_ANALOG_INTF_BASE_ADDRESS = QCA6180_ANALOG_INTF_BASE_ADDRESS, + .d_WLAN_MAC_BASE_ADDRESS = QCA6180_WLAN_MAC_BASE_ADDRESS, + .d_FW_INDICATOR_ADDRESS = QCA6180_FW_INDICATOR_ADDRESS, + .d_DRAM_BASE_ADDRESS = QCA6180_DRAM_BASE_ADDRESS, + .d_SOC_CORE_BASE_ADDRESS = QCA6180_SOC_CORE_BASE_ADDRESS, + .d_CORE_CTRL_ADDRESS = QCA6180_CORE_CTRL_ADDRESS, + .d_CE_COUNT = QCA6180_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 = QCA6180_PCIE_INTR_ENABLE_ADDRESS, + .d_PCIE_INTR_CLR_ADDRESS = QCA6180_PCIE_INTR_CLR_ADDRESS, + .d_PCIE_INTR_FIRMWARE_MASK = QCA6180_PCIE_INTR_FIRMWARE_MASK, + .d_PCIE_INTR_CE_MASK_ALL = QCA6180_PCIE_INTR_CE_MASK_ALL, + .d_CORE_CTRL_CPU_INTR_MASK = QCA6180_CORE_CTRL_CPU_INTR_MASK, + .d_SR_WR_INDEX_ADDRESS = QCA6180_SR_WR_INDEX_ADDRESS, + .d_DST_WATERMARK_ADDRESS = QCA6180_DST_WATERMARK_ADDRESS, + /* htt_rx.c */ + .d_RX_MSDU_END_4_FIRST_MSDU_MASK = + QCA6180_RX_MSDU_END_4_FIRST_MSDU_MASK, + .d_RX_MSDU_END_4_FIRST_MSDU_LSB = QCA6180_RX_MSDU_END_4_FIRST_MSDU_LSB, + .d_RX_MPDU_START_0_SEQ_NUM_MASK = QCA6180_RX_MPDU_START_0_SEQ_NUM_MASK, + .d_RX_MPDU_START_0_SEQ_NUM_LSB = QCA6180_RX_MPDU_START_0_SEQ_NUM_LSB, + .d_RX_MPDU_START_2_PN_47_32_LSB = QCA6180_RX_MPDU_START_2_PN_47_32_LSB, + .d_RX_MPDU_START_2_PN_47_32_MASK = + QCA6180_RX_MPDU_START_2_PN_47_32_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK = + QCA6180_RX_MSDU_END_1_EXT_WAPI_PN_63_48_MASK, + .d_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB = + QCA6180_RX_MSDU_END_1_EXT_WAPI_PN_63_48_LSB, + .d_RX_MSDU_END_4_LAST_MSDU_MASK = QCA6180_RX_MSDU_END_4_LAST_MSDU_MASK, + .d_RX_MSDU_END_4_LAST_MSDU_LSB = QCA6180_RX_MSDU_END_4_LAST_MSDU_LSB, + .d_RX_ATTENTION_0_MCAST_BCAST_MASK = + QCA6180_RX_ATTENTION_0_MCAST_BCAST_MASK, + .d_RX_ATTENTION_0_MCAST_BCAST_LSB = + QCA6180_RX_ATTENTION_0_MCAST_BCAST_LSB, + .d_RX_ATTENTION_0_FRAGMENT_MASK = QCA6180_RX_ATTENTION_0_FRAGMENT_MASK, + .d_RX_ATTENTION_0_FRAGMENT_LSB = QCA6180_RX_ATTENTION_0_FRAGMENT_LSB, + .d_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK = + QCA6180_RX_ATTENTION_0_MPDU_LENGTH_ERR_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK = + QCA6180_RX_FRAG_INFO_0_RING2_MORE_COUNT_MASK, + .d_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB = + QCA6180_RX_FRAG_INFO_0_RING2_MORE_COUNT_LSB, + .d_RX_MSDU_START_0_MSDU_LENGTH_MASK = + QCA6180_RX_MSDU_START_0_MSDU_LENGTH_MASK, + .d_RX_MSDU_START_0_MSDU_LENGTH_LSB = + QCA6180_RX_MSDU_START_0_MSDU_LENGTH_LSB, + .d_RX_MSDU_START_2_DECAP_FORMAT_OFFSET = + QCA6180_RX_MSDU_START_2_DECAP_FORMAT_OFFSET, + .d_RX_MSDU_START_2_DECAP_FORMAT_MASK = + QCA6180_RX_MSDU_START_2_DECAP_FORMAT_MASK, + .d_RX_MSDU_START_2_DECAP_FORMAT_LSB = + QCA6180_RX_MSDU_START_2_DECAP_FORMAT_LSB, + .d_RX_MPDU_START_0_ENCRYPTED_MASK = + QCA6180_RX_MPDU_START_0_ENCRYPTED_MASK, + .d_RX_MPDU_START_0_ENCRYPTED_LSB = + QCA6180_RX_MPDU_START_0_ENCRYPTED_LSB, + .d_RX_ATTENTION_0_MORE_DATA_MASK = + QCA6180_RX_ATTENTION_0_MORE_DATA_MASK, + .d_RX_ATTENTION_0_MSDU_DONE_MASK = + QCA6180_RX_ATTENTION_0_MSDU_DONE_MASK, + .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = + QCA6180_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, + + /* PLL start */ + .d_EFUSE_OFFSET = QCA6180_EFUSE_OFFSET, + .d_EFUSE_XTAL_SEL_MSB = QCA6180_EFUSE_XTAL_SEL_MSB, + .d_EFUSE_XTAL_SEL_LSB = QCA6180_EFUSE_XTAL_SEL_LSB, + .d_EFUSE_XTAL_SEL_MASK = QCA6180_EFUSE_XTAL_SEL_MASK, + .d_BB_PLL_CONFIG_OFFSET = QCA6180_BB_PLL_CONFIG_OFFSET, + .d_BB_PLL_CONFIG_OUTDIV_MSB = QCA6180_BB_PLL_CONFIG_OUTDIV_MSB, + .d_BB_PLL_CONFIG_OUTDIV_LSB = QCA6180_BB_PLL_CONFIG_OUTDIV_LSB, + .d_BB_PLL_CONFIG_OUTDIV_MASK = QCA6180_BB_PLL_CONFIG_OUTDIV_MASK, + .d_BB_PLL_CONFIG_FRAC_MSB = QCA6180_BB_PLL_CONFIG_FRAC_MSB, + .d_BB_PLL_CONFIG_FRAC_LSB = QCA6180_BB_PLL_CONFIG_FRAC_LSB, + .d_BB_PLL_CONFIG_FRAC_MASK = QCA6180_BB_PLL_CONFIG_FRAC_MASK, + .d_WLAN_PLL_SETTLE_TIME_MSB = QCA6180_WLAN_PLL_SETTLE_TIME_MSB, + .d_WLAN_PLL_SETTLE_TIME_LSB = QCA6180_WLAN_PLL_SETTLE_TIME_LSB, + .d_WLAN_PLL_SETTLE_TIME_MASK = QCA6180_WLAN_PLL_SETTLE_TIME_MASK, + .d_WLAN_PLL_SETTLE_OFFSET = QCA6180_WLAN_PLL_SETTLE_OFFSET, + .d_WLAN_PLL_SETTLE_SW_MASK = QCA6180_WLAN_PLL_SETTLE_SW_MASK, + .d_WLAN_PLL_SETTLE_RSTMASK = QCA6180_WLAN_PLL_SETTLE_RSTMASK, + .d_WLAN_PLL_SETTLE_RESET = QCA6180_WLAN_PLL_SETTLE_RESET, + .d_WLAN_PLL_CONTROL_NOPWD_MSB = QCA6180_WLAN_PLL_CONTROL_NOPWD_MSB, + .d_WLAN_PLL_CONTROL_NOPWD_LSB = QCA6180_WLAN_PLL_CONTROL_NOPWD_LSB, + .d_WLAN_PLL_CONTROL_NOPWD_MASK = QCA6180_WLAN_PLL_CONTROL_NOPWD_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_MSB = QCA6180_WLAN_PLL_CONTROL_BYPASS_MSB, + .d_WLAN_PLL_CONTROL_BYPASS_LSB = QCA6180_WLAN_PLL_CONTROL_BYPASS_LSB, + .d_WLAN_PLL_CONTROL_BYPASS_MASK = QCA6180_WLAN_PLL_CONTROL_BYPASS_MASK, + .d_WLAN_PLL_CONTROL_BYPASS_RESET = + QCA6180_WLAN_PLL_CONTROL_BYPASS_RESET, + .d_WLAN_PLL_CONTROL_CLK_SEL_MSB = QCA6180_WLAN_PLL_CONTROL_CLK_SEL_MSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_LSB = QCA6180_WLAN_PLL_CONTROL_CLK_SEL_LSB, + .d_WLAN_PLL_CONTROL_CLK_SEL_MASK = + QCA6180_WLAN_PLL_CONTROL_CLK_SEL_MASK, + .d_WLAN_PLL_CONTROL_CLK_SEL_RESET = + QCA6180_WLAN_PLL_CONTROL_CLK_SEL_RESET, + .d_WLAN_PLL_CONTROL_REFDIV_MSB = QCA6180_WLAN_PLL_CONTROL_REFDIV_MSB, + .d_WLAN_PLL_CONTROL_REFDIV_LSB = QCA6180_WLAN_PLL_CONTROL_REFDIV_LSB, + .d_WLAN_PLL_CONTROL_REFDIV_MASK = QCA6180_WLAN_PLL_CONTROL_REFDIV_MASK, + .d_WLAN_PLL_CONTROL_REFDIV_RESET = + QCA6180_WLAN_PLL_CONTROL_REFDIV_RESET, + .d_WLAN_PLL_CONTROL_DIV_MSB = QCA6180_WLAN_PLL_CONTROL_DIV_MSB, + .d_WLAN_PLL_CONTROL_DIV_LSB = QCA6180_WLAN_PLL_CONTROL_DIV_LSB, + .d_WLAN_PLL_CONTROL_DIV_MASK = QCA6180_WLAN_PLL_CONTROL_DIV_MASK, + .d_WLAN_PLL_CONTROL_DIV_RESET = QCA6180_WLAN_PLL_CONTROL_DIV_RESET, + .d_WLAN_PLL_CONTROL_OFFSET = QCA6180_WLAN_PLL_CONTROL_OFFSET, + .d_WLAN_PLL_CONTROL_SW_MASK = QCA6180_WLAN_PLL_CONTROL_SW_MASK, + .d_WLAN_PLL_CONTROL_RSTMASK = QCA6180_WLAN_PLL_CONTROL_RSTMASK, + .d_WLAN_PLL_CONTROL_RESET = QCA6180_WLAN_PLL_CONTROL_RESET, + .d_SOC_CORE_CLK_CTRL_OFFSET = QCA6180_SOC_CORE_CLK_CTRL_OFFSET, + .d_SOC_CORE_CLK_CTRL_DIV_MSB = QCA6180_SOC_CORE_CLK_CTRL_DIV_MSB, + .d_SOC_CORE_CLK_CTRL_DIV_LSB = QCA6180_SOC_CORE_CLK_CTRL_DIV_LSB, + .d_SOC_CORE_CLK_CTRL_DIV_MASK = QCA6180_SOC_CORE_CLK_CTRL_DIV_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MSB = + QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_MSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_LSB = + QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_LSB, + .d_RTC_SYNC_STATUS_PLL_CHANGING_MASK = + QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_MASK, + .d_RTC_SYNC_STATUS_PLL_CHANGING_RESET = + QCA6180_RTC_SYNC_STATUS_PLL_CHANGING_RESET, + .d_RTC_SYNC_STATUS_OFFSET = QCA6180_RTC_SYNC_STATUS_OFFSET, + .d_SOC_CPU_CLOCK_OFFSET = QCA6180_SOC_CPU_CLOCK_OFFSET, + .d_SOC_CPU_CLOCK_STANDARD_MSB = QCA6180_SOC_CPU_CLOCK_STANDARD_MSB, + .d_SOC_CPU_CLOCK_STANDARD_LSB = QCA6180_SOC_CPU_CLOCK_STANDARD_LSB, + .d_SOC_CPU_CLOCK_STANDARD_MASK = QCA6180_SOC_CPU_CLOCK_STANDARD_MASK, + /* PLL end */ + .d_SOC_POWER_REG_OFFSET = QCA6180_SOC_POWER_REG_OFFSET, + .d_PCIE_INTR_CAUSE_ADDRESS = QCA6180_PCIE_INTR_CAUSE_ADDRESS, + .d_SOC_RESET_CONTROL_ADDRESS = QCA6180_SOC_RESET_CONTROL_ADDRESS, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK = + QCA6180_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK, + .d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB = + QCA6180_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB, + .d_SOC_RESET_CONTROL_CE_RST_MASK = + QCA6180_SOC_RESET_CONTROL_CE_RST_MASK, + .d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK = + QCA6180_SOC_RESET_CONTROL_CPU_WARM_RST_MASK, + .d_CPU_INTR_ADDRESS = QCA6180_CPU_INTR_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ADDRESS = + QCA6180_SOC_LF_TIMER_CONTROL0_ADDRESS, + .d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK = + QCA6180_SOC_LF_TIMER_CONTROL0_ENABLE_MASK, + /* chip id start */ + .d_SOC_CHIP_ID_ADDRESS = QCA6180_SOC_CHIP_ID_ADDRESS, + .d_SOC_CHIP_ID_VERSION_MASK = QCA6180_SOC_CHIP_ID_VERSION_MASK, + .d_SOC_CHIP_ID_VERSION_LSB = QCA6180_SOC_CHIP_ID_VERSION_LSB, + .d_SOC_CHIP_ID_REVISION_MASK = QCA6180_SOC_CHIP_ID_REVISION_MASK, + .d_SOC_CHIP_ID_REVISION_LSB = QCA6180_SOC_CHIP_ID_REVISION_LSB, + /* chip id end */ + .d_A_SOC_CORE_SCRATCH_0_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_0_ADDRESS, + .d_A_SOC_CORE_SCRATCH_1_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_1_ADDRESS, + .d_A_SOC_CORE_SCRATCH_2_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_2_ADDRESS, + .d_A_SOC_CORE_SCRATCH_3_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_3_ADDRESS, + .d_A_SOC_CORE_SCRATCH_4_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_4_ADDRESS, + .d_A_SOC_CORE_SCRATCH_5_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_5_ADDRESS, + .d_A_SOC_CORE_SCRATCH_6_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_6_ADDRESS, + .d_A_SOC_CORE_SCRATCH_7_ADDRESS = QCA6180_A_SOC_CORE_SCRATCH_7_ADDRESS, + .d_A_SOC_CORE_SPARE_0_REGISTER = QCA6180_A_SOC_CORE_SPARE_0_REGISTER, + .d_PCIE_INTR_FIRMWARE_ROUTE_MASK = + QCA6180_PCIE_INTR_FIRMWARE_ROUTE_MASK, + .d_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 = + QCA6180_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1, + .d_A_SOC_CORE_SPARE_1_REGISTER = + QCA6180_A_SOC_CORE_SPARE_1_REGISTER, + .d_A_SOC_CORE_PCIE_INTR_CLR_GRP1 = + QCA6180_A_SOC_CORE_PCIE_INTR_CLR_GRP1, + .d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 = + QCA6180_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1, + .d_A_SOC_PCIE_PCIE_SCRATCH_0 = + QCA6180_A_SOC_PCIE_PCIE_SCRATCH_0, + .d_A_SOC_PCIE_PCIE_SCRATCH_1 = + QCA6180_A_SOC_PCIE_PCIE_SCRATCH_1, + .d_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA = + QCA6180_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA, + .d_A_SOC_PCIE_PCIE_SCRATCH_2 = QCA6180_A_SOC_PCIE_PCIE_SCRATCH_2, + .d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK = + QCA6180_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK, + + .d_WLAN_DEBUG_INPUT_SEL_OFFSET = QCA6180_WLAN_DEBUG_INPUT_SEL_OFFSET, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MSB = QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_MSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_LSB = QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_LSB, + .d_WLAN_DEBUG_INPUT_SEL_SRC_MASK = + QCA6180_WLAN_DEBUG_INPUT_SEL_SRC_MASK, + .d_WLAN_DEBUG_CONTROL_OFFSET = QCA6180_WLAN_DEBUG_CONTROL_OFFSET, + .d_WLAN_DEBUG_CONTROL_ENABLE_MSB = + QCA6180_WLAN_DEBUG_CONTROL_ENABLE_MSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_LSB = + QCA6180_WLAN_DEBUG_CONTROL_ENABLE_LSB, + .d_WLAN_DEBUG_CONTROL_ENABLE_MASK = + QCA6180_WLAN_DEBUG_CONTROL_ENABLE_MASK, + .d_WLAN_DEBUG_OUT_OFFSET = QCA6180_WLAN_DEBUG_OUT_OFFSET, + .d_WLAN_DEBUG_OUT_DATA_MSB = QCA6180_WLAN_DEBUG_OUT_DATA_MSB, + .d_WLAN_DEBUG_OUT_DATA_LSB = QCA6180_WLAN_DEBUG_OUT_DATA_LSB, + .d_WLAN_DEBUG_OUT_DATA_MASK = QCA6180_WLAN_DEBUG_OUT_DATA_MASK, + .d_AMBA_DEBUG_BUS_OFFSET = QCA6180_AMBA_DEBUG_BUS_OFFSET, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB = + QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB = + QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_LSB, + .d_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK = + QCA6180_AMBA_DEBUG_BUS_PCIE_DEBUG_SEL_MASK, + .d_AMBA_DEBUG_BUS_SEL_MSB = QCA6180_AMBA_DEBUG_BUS_SEL_MSB, + .d_AMBA_DEBUG_BUS_SEL_LSB = QCA6180_AMBA_DEBUG_BUS_SEL_LSB, + .d_AMBA_DEBUG_BUS_SEL_MASK = QCA6180_AMBA_DEBUG_BUS_SEL_MASK, +}; + +struct hostdef_s qca6180_hostdef = { + .d_INT_STATUS_ENABLE_ERROR_LSB = QCA6180_INT_STATUS_ENABLE_ERROR_LSB, + .d_INT_STATUS_ENABLE_ERROR_MASK = QCA6180_INT_STATUS_ENABLE_ERROR_MASK, + .d_INT_STATUS_ENABLE_CPU_LSB = QCA6180_INT_STATUS_ENABLE_CPU_LSB, + .d_INT_STATUS_ENABLE_CPU_MASK = QCA6180_INT_STATUS_ENABLE_CPU_MASK, + .d_INT_STATUS_ENABLE_COUNTER_LSB = + QCA6180_INT_STATUS_ENABLE_COUNTER_LSB, + .d_INT_STATUS_ENABLE_COUNTER_MASK = + QCA6180_INT_STATUS_ENABLE_COUNTER_MASK, + .d_INT_STATUS_ENABLE_MBOX_DATA_LSB = + QCA6180_INT_STATUS_ENABLE_MBOX_DATA_LSB, + .d_INT_STATUS_ENABLE_MBOX_DATA_MASK = + QCA6180_INT_STATUS_ENABLE_MBOX_DATA_MASK, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = + QCA6180_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = + QCA6180_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = + QCA6180_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB, + .d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = + QCA6180_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK, + .d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = + QCA6180_COUNTER_INT_STATUS_ENABLE_BIT_LSB, + .d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = + QCA6180_COUNTER_INT_STATUS_ENABLE_BIT_MASK, + .d_INT_STATUS_ENABLE_ADDRESS = QCA6180_INT_STATUS_ENABLE_ADDRESS, + .d_CPU_INT_STATUS_ENABLE_BIT_LSB = + QCA6180_CPU_INT_STATUS_ENABLE_BIT_LSB, + .d_CPU_INT_STATUS_ENABLE_BIT_MASK = + QCA6180_CPU_INT_STATUS_ENABLE_BIT_MASK, + .d_HOST_INT_STATUS_ADDRESS = QCA6180_HOST_INT_STATUS_ADDRESS, + .d_CPU_INT_STATUS_ADDRESS = QCA6180_CPU_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_ADDRESS = QCA6180_ERROR_INT_STATUS_ADDRESS, + .d_ERROR_INT_STATUS_WAKEUP_MASK = QCA6180_ERROR_INT_STATUS_WAKEUP_MASK, + .d_ERROR_INT_STATUS_WAKEUP_LSB = QCA6180_ERROR_INT_STATUS_WAKEUP_LSB, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = + QCA6180_ERROR_INT_STATUS_RX_UNDERFLOW_MASK, + .d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = + QCA6180_ERROR_INT_STATUS_RX_UNDERFLOW_LSB, + .d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = + QCA6180_ERROR_INT_STATUS_TX_OVERFLOW_MASK, + .d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = + QCA6180_ERROR_INT_STATUS_TX_OVERFLOW_LSB, + .d_COUNT_DEC_ADDRESS = QCA6180_COUNT_DEC_ADDRESS, + .d_HOST_INT_STATUS_CPU_MASK = QCA6180_HOST_INT_STATUS_CPU_MASK, + .d_HOST_INT_STATUS_CPU_LSB = QCA6180_HOST_INT_STATUS_CPU_LSB, + .d_HOST_INT_STATUS_ERROR_MASK = QCA6180_HOST_INT_STATUS_ERROR_MASK, + .d_HOST_INT_STATUS_ERROR_LSB = QCA6180_HOST_INT_STATUS_ERROR_LSB, + .d_HOST_INT_STATUS_COUNTER_MASK = QCA6180_HOST_INT_STATUS_COUNTER_MASK, + .d_HOST_INT_STATUS_COUNTER_LSB = QCA6180_HOST_INT_STATUS_COUNTER_LSB, + .d_RX_LOOKAHEAD_VALID_ADDRESS = QCA6180_RX_LOOKAHEAD_VALID_ADDRESS, + .d_WINDOW_DATA_ADDRESS = QCA6180_WINDOW_DATA_ADDRESS, + .d_WINDOW_READ_ADDR_ADDRESS = QCA6180_WINDOW_READ_ADDR_ADDRESS, + .d_WINDOW_WRITE_ADDR_ADDRESS = QCA6180_WINDOW_WRITE_ADDR_ADDRESS, + .d_SOC_GLOBAL_RESET_ADDRESS = QCA6180_SOC_GLOBAL_RESET_ADDRESS, + .d_RTC_STATE_ADDRESS = QCA6180_RTC_STATE_ADDRESS, + .d_RTC_STATE_COLD_RESET_MASK = QCA6180_RTC_STATE_COLD_RESET_MASK, + .d_PCIE_LOCAL_BASE_ADDRESS = QCA6180_PCIE_LOCAL_BASE_ADDRESS, + .d_PCIE_SOC_WAKE_RESET = QCA6180_PCIE_SOC_WAKE_RESET, + .d_PCIE_SOC_WAKE_ADDRESS = QCA6180_PCIE_SOC_WAKE_ADDRESS, + .d_PCIE_SOC_WAKE_V_MASK = QCA6180_PCIE_SOC_WAKE_V_MASK, + .d_RTC_STATE_V_MASK = QCA6180_RTC_STATE_V_MASK, + .d_RTC_STATE_V_LSB = QCA6180_RTC_STATE_V_LSB, + .d_FW_IND_EVENT_PENDING = QCA6180_FW_IND_EVENT_PENDING, + .d_FW_IND_INITIALIZED = QCA6180_FW_IND_INITIALIZED, + .d_FW_IND_HELPER = QCA6180_FW_IND_HELPER, + .d_RTC_STATE_V_ON = QCA6180_RTC_STATE_V_ON, +#if defined(SDIO_3_0) + .d_HOST_INT_STATUS_MBOX_DATA_MASK = + QCA6180_HOST_INT_STATUS_MBOX_DATA_MASK, + .d_HOST_INT_STATUS_MBOX_DATA_LSB = + QCA6180_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, + .d_HOST_CE_COUNT = 8, + .d_ENABLE_MSI = 0, + .d_MUX_ID_MASK = 0xf000, + .d_TRANSACTION_ID_MASK = 0x0fff, + .d_DESC_DATA_FLAG_MASK = 0x1FFFE3E0, + .d_A_SOC_PCIE_PCIE_BAR0_START = QCA6180_A_SOC_PCIE_PCIE_BAR0_START, +}; + + +struct ce_reg_def qca6180_ce_targetdef = { + /* copy_engine.c */ + .d_DST_WR_INDEX_ADDRESS = QCA6180_DST_WR_INDEX_ADDRESS, + .d_SRC_WATERMARK_ADDRESS = QCA6180_SRC_WATERMARK_ADDRESS, + .d_SRC_WATERMARK_LOW_MASK = QCA6180_SRC_WATERMARK_LOW_MASK, + .d_SRC_WATERMARK_HIGH_MASK = QCA6180_SRC_WATERMARK_HIGH_MASK, + .d_DST_WATERMARK_LOW_MASK = QCA6180_DST_WATERMARK_LOW_MASK, + .d_DST_WATERMARK_HIGH_MASK = QCA6180_DST_WATERMARK_HIGH_MASK, + .d_CURRENT_SRRI_ADDRESS = QCA6180_CURRENT_SRRI_ADDRESS, + .d_CURRENT_DRRI_ADDRESS = QCA6180_CURRENT_DRRI_ADDRESS, + .d_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK = + QCA6180_HOST_IS_SRC_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_SRC_RING_LOW_WATERMARK_MASK = + QCA6180_HOST_IS_SRC_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_DST_RING_HIGH_WATERMARK_MASK = + QCA6180_HOST_IS_DST_RING_HIGH_WATERMARK_MASK, + .d_HOST_IS_DST_RING_LOW_WATERMARK_MASK = + QCA6180_HOST_IS_DST_RING_LOW_WATERMARK_MASK, + .d_HOST_IS_ADDRESS = QCA6180_HOST_IS_ADDRESS, + .d_MISC_IS_ADDRESS = QCA6180_MISC_IS_ADDRESS, + .d_HOST_IS_COPY_COMPLETE_MASK = QCA6180_HOST_IS_COPY_COMPLETE_MASK, + .d_CE_WRAPPER_BASE_ADDRESS = QCA6180_CE_WRAPPER_BASE_ADDRESS, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = + QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, + .d_CE_WRAPPER_INDEX_BASE_LOW = QCA6180_CE_WRAPPER_INDEX_BASE_LOW, + .d_CE_WRAPPER_INDEX_BASE_HIGH = QCA6180_CE_WRAPPER_INDEX_BASE_HIGH, + .d_HOST_IE_ADDRESS = QCA6180_HOST_IE_ADDRESS, + .d_HOST_IE_COPY_COMPLETE_MASK = QCA6180_HOST_IE_COPY_COMPLETE_MASK, + .d_SR_BA_ADDRESS = QCA6180_SR_BA_ADDRESS, + .d_SR_SIZE_ADDRESS = QCA6180_SR_SIZE_ADDRESS, + .d_CE_CTRL1_ADDRESS = QCA6180_CE_CTRL1_ADDRESS, + .d_CE_CTRL1_DMAX_LENGTH_MASK = QCA6180_CE_CTRL1_DMAX_LENGTH_MASK, + .d_DR_BA_ADDRESS = QCA6180_DR_BA_ADDRESS, + .d_DR_SIZE_ADDRESS = QCA6180_DR_SIZE_ADDRESS, + .d_CE_CMD_REGISTER = QCA6180_CE_CMD_REGISTER, + .d_CE_MSI_ADDRESS = QCA6180_CE_MSI_ADDRESS, + .d_CE_MSI_ADDRESS_HIGH = QCA6180_CE_MSI_ADDRESS_HIGH, + .d_CE_MSI_DATA = QCA6180_CE_MSI_DATA, + .d_CE_MSI_ENABLE_BIT = QCA6180_CE_MSI_ENABLE_BIT, + .d_MISC_IE_ADDRESS = QCA6180_MISC_IE_ADDRESS, + .d_MISC_IS_AXI_ERR_MASK = QCA6180_MISC_IS_AXI_ERR_MASK, + .d_MISC_IS_DST_ADDR_ERR_MASK = QCA6180_MISC_IS_DST_ADDR_ERR_MASK, + .d_MISC_IS_SRC_LEN_ERR_MASK = QCA6180_MISC_IS_SRC_LEN_ERR_MASK, + .d_MISC_IS_DST_MAX_LEN_VIO_MASK = QCA6180_MISC_IS_DST_MAX_LEN_VIO_MASK, + .d_MISC_IS_DST_RING_OVERFLOW_MASK = + QCA6180_MISC_IS_DST_RING_OVERFLOW_MASK, + .d_MISC_IS_SRC_RING_OVERFLOW_MASK = + QCA6180_MISC_IS_SRC_RING_OVERFLOW_MASK, + .d_SRC_WATERMARK_LOW_LSB = QCA6180_SRC_WATERMARK_LOW_LSB, + .d_SRC_WATERMARK_HIGH_LSB = QCA6180_SRC_WATERMARK_HIGH_LSB, + .d_DST_WATERMARK_LOW_LSB = QCA6180_DST_WATERMARK_LOW_LSB, + .d_DST_WATERMARK_HIGH_LSB = QCA6180_DST_WATERMARK_HIGH_LSB, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK = + QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK, + .d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB = + QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB, + .d_CE_CTRL1_DMAX_LENGTH_LSB = QCA6180_CE_CTRL1_DMAX_LENGTH_LSB, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK = + QCA6180_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK = + QCA6180_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK, + .d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB = + QCA6180_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = + QCA6180_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_CE_WRAPPER_DEBUG_OFFSET = QCA6180_CE_WRAPPER_DEBUG_OFFSET, + .d_CE_WRAPPER_DEBUG_SEL_MSB = QCA6180_CE_WRAPPER_DEBUG_SEL_MSB, + .d_CE_WRAPPER_DEBUG_SEL_LSB = QCA6180_CE_WRAPPER_DEBUG_SEL_LSB, + .d_CE_WRAPPER_DEBUG_SEL_MASK = QCA6180_CE_WRAPPER_DEBUG_SEL_MASK, + .d_CE_DEBUG_OFFSET = QCA6180_CE_DEBUG_OFFSET, + .d_CE_DEBUG_SEL_MSB = QCA6180_CE_DEBUG_SEL_MSB, + .d_CE_DEBUG_SEL_LSB = QCA6180_CE_DEBUG_SEL_LSB, + .d_CE_DEBUG_SEL_MASK = QCA6180_CE_DEBUG_SEL_MASK, + .d_CE0_BASE_ADDRESS = QCA6180_CE0_BASE_ADDRESS, + .d_CE1_BASE_ADDRESS = QCA6180_CE1_BASE_ADDRESS, +}; + + +struct host_shadow_regs_s qca6180_host_shadow_regs = { + .d_A_LOCAL_SHADOW_REG_VALUE_0 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_0, + .d_A_LOCAL_SHADOW_REG_VALUE_1 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_1, + .d_A_LOCAL_SHADOW_REG_VALUE_2 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_2, + .d_A_LOCAL_SHADOW_REG_VALUE_3 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_3, + .d_A_LOCAL_SHADOW_REG_VALUE_4 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_4, + .d_A_LOCAL_SHADOW_REG_VALUE_5 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_5, + .d_A_LOCAL_SHADOW_REG_VALUE_6 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_6, + .d_A_LOCAL_SHADOW_REG_VALUE_7 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_7, + .d_A_LOCAL_SHADOW_REG_VALUE_8 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_8, + .d_A_LOCAL_SHADOW_REG_VALUE_9 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_9, + .d_A_LOCAL_SHADOW_REG_VALUE_10 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_10, + .d_A_LOCAL_SHADOW_REG_VALUE_11 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_11, + .d_A_LOCAL_SHADOW_REG_VALUE_12 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_12, + .d_A_LOCAL_SHADOW_REG_VALUE_13 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_13, + .d_A_LOCAL_SHADOW_REG_VALUE_14 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_14, + .d_A_LOCAL_SHADOW_REG_VALUE_15 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_15, + .d_A_LOCAL_SHADOW_REG_VALUE_16 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_16, + .d_A_LOCAL_SHADOW_REG_VALUE_17 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_17, + .d_A_LOCAL_SHADOW_REG_VALUE_18 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_18, + .d_A_LOCAL_SHADOW_REG_VALUE_19 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_19, + .d_A_LOCAL_SHADOW_REG_VALUE_20 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_20, + .d_A_LOCAL_SHADOW_REG_VALUE_21 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_21, + .d_A_LOCAL_SHADOW_REG_VALUE_22 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_22, + .d_A_LOCAL_SHADOW_REG_VALUE_23 = + QCA6180_A_LOCAL_SHADOW_REG_VALUE_23, + +}; + +#endif /* _QCA6180DEF_H_ */ diff --git a/core/hif/src/regtable.c b/core/hif/src/regtable.c new file mode 100644 index 000000000000..90d8f8ef910d --- /dev/null +++ b/core/hif/src/regtable.c @@ -0,0 +1,91 @@ +/* + * 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 "bmi_msg.h" +#include "targaddrs.h" +#include "cepci.h" +#include "regtable.h" +#include "ar9888def.h" +#include "ar6320def.h" +#include "ar6320v2def.h" +#include "qca6180def.h" +#include "ol_if_athvar.h" +#include "hif.h" +#include "adrastea_reg_def.h" + +void target_register_tbl_attach(struct ol_softc *scn, u32 target_type) +{ + switch (target_type) { + case TARGET_TYPE_AR9888: + scn->targetdef = &ar9888_targetdef; + scn->target_ce_def = &ar9888_ce_targetdef; + break; + case TARGET_TYPE_AR6320: + scn->targetdef = &ar6320_targetdef; + scn->target_ce_def = &ar6320_ce_targetdef; + break; + case TARGET_TYPE_AR6320V2: + scn->targetdef = &ar6320v2_targetdef; + scn->target_ce_def = &ar6320v2_ce_targetdef; + break; + case TARGET_TYPE_QCA6180: + scn->targetdef = &qca6180_targetdef; + scn->target_ce_def = &qca6180_ce_targetdef; + break; + case TARGET_TYPE_ADRASTEA: + scn->targetdef = &adrastea_targetdef; + scn->target_ce_def = &adrastea_ce_targetdef; + break; + default: + break; + } +} + +void hif_register_tbl_attach(struct ol_softc *scn, u32 hif_type) +{ + switch (hif_type) { + case HIF_TYPE_AR9888: + scn->hostdef = &ar9888_hostdef; + break; + case HIF_TYPE_AR6320: + scn->hostdef = &ar6320_hostdef; + break; + case HIF_TYPE_AR6320V2: + scn->hostdef = &ar6320v2_hostdef; + break; + case HIF_TYPE_QCA6180: + scn->hostdef = &qca6180_hostdef; + scn->host_shadow_regs = &qca6180_host_shadow_regs; + break; + case HIF_TYPE_ADRASTEA: + scn->hostdef = &adrastea_hostdef; + scn->host_shadow_regs = &adrastea_host_shadow_regs; + break; + default: + break; + } +} diff --git a/core/hif/src/snoc/hif_io32_snoc.h b/core/hif/src/snoc/hif_io32_snoc.h new file mode 100644 index 000000000000..8507c4b98d67 --- /dev/null +++ b/core/hif/src/snoc/hif_io32_snoc.h @@ -0,0 +1,236 @@ +/* + * 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: hif_io32_snoc.h + * + * snoc specific implementations and configurations + */ + +#ifndef __HIF_IO32_SNOC_H__ +#define __HIF_IO32_SNOC_H__ + +#ifdef HIF_PCI +#error snoc and pci cannot be supported in parrallel at this time +#endif + +#include "hif.h" +#include "regtable.h" +#include "ce_reg.h" +#include "cdf_atomic.h" +#include +#include "hif_main.h" +#include "hif_debug.h" + +/** + * Following features are not supported for snoc bus + * Force 0 and consider moving corresponding code into + * pci specific files + */ +#define CONFIG_ATH_PCIE_MAX_PERF 0 +#define CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD 0 +#define CONFIG_ATH_PCIE_ACCESS_LIKELY 0 +#define CONFIG_PCIE_ENABLE_L1_CLOCK_GATE 0 + +#define A_TARGET_ACCESS_LIKELY(scn) +#define A_TARGET_ACCESS_UNLIKELY(scn) +#define A_TARGET_ACCESS_BEGIN_RET_PTR(scn) +#define A_TARGET_ACCESS_END_RET_PTR(scn) +#define A_TARGET_ACCESS_BEGIN(scn) +#define A_TARGET_ACCESS_END(scn) +#define A_TARGET_ACCESS_BEGIN_RET(scn) +#define A_TARGET_ACCESS_END_RET(scn) +#define A_TARGET_ACCESS_BEGIN_RET_EXT(scn, val) +#define A_TARGET_ACCESS_END_RET_EXT(scn, val) + +#define Q_TARGET_ACCESS_BEGIN(scn) 0 +#define Q_TARGET_ACCESS_END(scn) 0 + +static inline void hif_pci_cancel_deferred_target_sleep(struct ol_softc *scn) +{ + return; +} + +static inline void hif_target_sleep_state_adjust(struct ol_softc *scn, + bool sleep_ok, bool wait_for_it) +{ + return; +} + +/** + * soc_wake_reset() - soc_wake_reset + * @scn: ol_softc + * + * Return: void + */ +static inline void soc_wake_reset(struct ol_softc *scn) +{ +} + +/** + * hif_write32_mb - SNOC write 32 + * @addr: physical address + * @value: value + * + * Return: N/A + */ +static inline void hif_write32_mb(void __iomem *addr, uint32_t value) +{ + wmb(); /* write memory barrier */ + writel_relaxed((value), (addr)); + wmb(); /* write memory barrier */ +} + +/** + * hif_read32_mb - SNOC read 32 + * @addr: physical address + * + * Return: N/A + */ +static inline uint32_t hif_read32_mb(void __iomem *addr) +{ + uint32_t tmp; + rmb(); /* read memory barrier */ + tmp = readl_relaxed(addr); + rmb(); /* read memory barrier */ + return tmp; +} + +#define A_TARGET_READ(scn, offset) \ + hif_read32_mb(scn->mem + (offset)) +#define A_TARGET_WRITE(scn, offset, value) \ + hif_write32_mb((scn->mem + offset), (value)) + +#define ADRASTEA_CE_INTR_ENABLES 0x002F00A8 +#define ADRASTEA_CE_INTR_ENABLES_SET "COMING IN REGISTER SET36" +#define ADRASTEA_CE_INTR_ENABLES_CLEAR "COMING IN REGISTER SET36" + +#define ADRASTEA_CE_INTR_STATUS 0x002F00AC + +static inline void ce_enable_irq_in_individual_register(struct ol_softc *scn, + int ce_id) +{ + uint32_t offset; + offset = HOST_IE_ADDRESS + CE_BASE_ADDRESS(ce_id); + hif_write32_mb(scn->mem + offset, 1); + hif_read32_mb(scn->mem + offset); +} + +static inline void ce_disable_irq_in_individual_register(struct ol_softc *scn, + int ce_id) +{ + uint32_t offset; + offset = HOST_IE_ADDRESS + CE_BASE_ADDRESS(ce_id); + hif_write32_mb(scn->mem + offset, 0); + hif_read32_mb(scn->mem + offset); +} + +static inline void ce_read_irq_group_status(struct ol_softc *scn) +{ + uint32_t group_status = 0; + group_status = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_STATUS); +} + +static inline void ce_clear_irq_group_status(struct ol_softc *scn, int mask) +{ + uint32_t group_status = 0; + group_status = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_STATUS); + + hif_write32_mb(scn->mem + + ADRASTEA_CE_INTR_STATUS, mask); + + group_status = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_STATUS); +} + +/* this will need to be changed when we move to reg set 36 + * because we will have set & clear registers provided + */ +static inline void ce_enable_irq_in_group_reg(struct ol_softc *scn, + int mask) +{ + int new_mask = 0; + new_mask = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES); + + new_mask |= mask; + + hif_write32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES, new_mask); + mask = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES); +} + +/* this will need to be changed when we move to reg set 36 + * because we will have set & clear registers provided + */ +static inline void ce_disable_irq_in_group_reg(struct ol_softc *scn, + int mask) +{ + int new_mask = 0; + new_mask = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES); + + new_mask &= ~mask; + + hif_write32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES, new_mask); + mask = hif_read32_mb(scn->mem + + ADRASTEA_CE_INTR_ENABLES); +} + +/** + * ce_irq_enable() - enable copy engine IRQ + * @scn: struct ol_softc + * @ce_id: ce_id + * + * Return: N/A + */ +static inline void ce_irq_enable(struct ol_softc *scn, + int ce_id) +{ + icnss_enable_irq(ce_id); + ce_enable_irq_in_individual_register(scn, ce_id); + ce_enable_irq_in_group_reg(scn, 1<hif_hdl); + cdf_atomic_set(&scn->active_tasklet_cnt, 0); +} + +/** + * dump_ce_debug_register(): dump CE debug registers + * + * This function dumps CE debug registers + * + * @scn: struct ol_softc + * + * Return: void + */ +void dump_ce_debug_register(struct ol_softc *scn) +{ + return; +} + +/** + * hif_bus_suspend() - suspend the bus + * + * This function suspends the bus, but snoc doesn't need to suspend. + * Therefore do nothing. + * + * Return: 0 for success and non-zero for failure + */ +int hif_bus_suspend(void) +{ + return 0; +} + +/** + * hif_bus_resume() - hif resume API + * + * This function resumes the bus. but snoc doesn't need to resume. + * Therefore do nothing. + * + * Return: 0 for success and non-zero for failure + */ +int hif_bus_resume(void) +{ + return 0; +} + +/** + * hif_enable_power_gating(): enable HW power gating + * + * Return: n/a + */ +void hif_enable_power_gating(void *hif_ctx) +{ +} + +/** + * hif_disable_aspm(): hif_disable_aspm + * + * Return: n/a + */ +void hif_disable_aspm(void) +{ +} + +/** + * hif_bus_close(): hif_bus_close + * + * Return: n/a + */ +void hif_bus_close(struct ol_softc *scn) +{ +} + +/** + * hif_bus_open(): hif_bus_open + * @scn: scn + * @bus_type: bus type + * + * Return: n/a + */ +CDF_STATUS hif_bus_open(struct ol_softc *scn, enum ath_hal_bus_type bus_type) +{ + return CDF_STATUS_SUCCESS; +} + +/** + * hif_get_target_type(): Get the target type + * + * This function is used to query the target type. + * + * @ol_sc: ol_softc struct pointer + * @dev: device pointer + * @bdev: bus dev pointer + * @bid: bus id pointer + * @hif_type: HIF type such as HIF_TYPE_QCA6180 + * @target_type: target type such as TARGET_TYPE_QCA6180 + * + * Return: 0 for success + */ +int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, + void *bdev, const hif_bus_id *bid, uint32_t *hif_type, + uint32_t *target_type) +{ + /* TODO: need to use CNSS's HW version. Hard code for now */ +#ifdef QCA_WIFI_3_0_ADRASTEA + *hif_type = HIF_TYPE_ADRASTEA; + *target_type = TARGET_TYPE_ADRASTEA; +#else + *hif_type = 0; + *target_type = 0; +#endif + return 0; +} + +/** + * hif_enable_bus(): hif_enable_bus + * @dev: dev + * @bdev: bus dev + * @bid: bus id + * @type: bus type + * + * Return: CDF_STATUS + */ +CDF_STATUS hif_enable_bus(struct ol_softc *ol_sc, + struct device *dev, void *bdev, + const hif_bus_id *bid, + enum hif_enable_type type) +{ + int ret; + int hif_type; + int target_type; + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) { + HIF_ERROR("%s: failed to set dma mask error = %d", + __func__, ret); + return ret; + } + + if (!ol_sc) { + HIF_ERROR("%s: hif_ctx is NULL", __func__); + return CDF_STATUS_E_NOMEM; + } + + ol_sc->aps_osdev.device = dev; + ol_sc->aps_osdev.bc.bc_handle = (void *)ol_sc->mem; + ol_sc->aps_osdev.bc.bc_bustype = type; + + ret = hif_get_target_type(ol_sc, dev, bdev, bid, + &hif_type, &target_type); + if (ret < 0) { + HIF_ERROR("%s: invalid device id/revision_id", __func__); + return CDF_STATUS_E_FAILURE; + } + + hif_register_tbl_attach(ol_sc, hif_type); + target_register_tbl_attach(ol_sc, target_type); + + HIF_TRACE("%s: X - hif_type = 0x%x, target_type = 0x%x", + __func__, hif_type, target_type); + + ret = hif_init_cdf_ctx(ol_sc); + if (ret != 0) { + HIF_ERROR("%s: cannot init CDF", __func__); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * hif_disable_bus(): hif_disable_bus + * + * This function disables the bus + * + * @bdev: bus dev + * + * Return: none + */ +void hif_disable_bus(void *bdev) +{ +} + +/** + * hif_nointrs(): disable IRQ + * + * This function stops interrupt(s) + * + * @scn: struct ol_softc + * + * Return: none + */ +void hif_nointrs(struct ol_softc *scn) +{ + if (scn->request_irq_done) { + ce_unregister_irq(scn->hif_hdl, 0xfff); + scn->request_irq_done = false; + } +} diff --git a/core/htc/dl_list.h b/core/htc/dl_list.h new file mode 100644 index 000000000000..1b5d72f780e2 --- /dev/null +++ b/core/htc/dl_list.h @@ -0,0 +1,208 @@ +/* + * 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. + */ + +/* ============================================================================== */ +/* 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_list_is_entry_in_list(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_list_is_entry_in_list(pStart, pTemp) +#define ITERATE_RESET(pStart) pTemp=(pStart)->pNext + +#define ITERATE_END }} + +/* + * dl_list_insert_tail - insert pAdd to the end of the list + */ +static __inline PDL_LIST dl_list_insert_tail(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_list_insert_head - insert pAdd into the head of the list + */ +static __inline PDL_LIST dl_list_insert_head(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_list_insert_head((pList),(pItem)) +/* + * dl_list_remove - remove pDel from list + */ +static __inline PDL_LIST dl_list_remove(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_list_remove_item_from_head - get a list item from the head + */ +static __inline PDL_LIST dl_list_remove_item_from_head(PDL_LIST pList) +{ + PDL_LIST pItem = NULL; + if (pList->pNext != pList) { + pItem = pList->pNext; + /* remove the first item from head */ + dl_list_remove(pItem); + } + return pItem; +} + +static __inline PDL_LIST dl_list_remove_item_from_tail(PDL_LIST pList) +{ + PDL_LIST pItem = NULL; + if (pList->pPrev != pList) { + pItem = pList->pPrev; + /* remove the item from tail */ + dl_list_remove(pItem); + } + return pItem; +} + +/* transfer src list items to the tail of the destination list */ +static __inline void dl_list_transfer_items_to_tail(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_list_transfer_items_to_head(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/core/htc/htc.c b/core/htc/htc.c new file mode 100644 index 000000000000..bbabee1f2575 --- /dev/null +++ b/core/htc/htc.c @@ -0,0 +1,816 @@ +/* + * 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 "ol_if_athvar.h" +#include "htc_debug.h" +#include "htc_internal.h" +#include /* cdf_nbuf_t */ +#include /* cdf_print */ +#include +#include +#include "epping_main.h" +#include "hif_io32.h" + +#ifdef DEBUG +static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = { + {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_htc_debug_description), + g_htc_debug_description); + +#endif + +extern unsigned int htc_credit_flow; + +static void reset_endpoint_states(HTC_TARGET *target); + +static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket) +{ + cdf_nbuf_t netbuf; + netbuf = (cdf_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) { + cdf_nbuf_free(netbuf); + } + + cdf_mem_free(pPacket); +} + +static HTC_PACKET *build_htc_tx_ctrl_packet(cdf_device_t osdev) +{ + HTC_PACKET *pPacket = NULL; + cdf_nbuf_t netbuf; + + do { + pPacket = (HTC_PACKET *) cdf_mem_malloc(sizeof(HTC_PACKET)); + if (NULL == pPacket) { + break; + } + A_MEMZERO(pPacket, sizeof(HTC_PACKET)); + netbuf = + cdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE, 20, 4, true); + if (NULL == netbuf) { + cdf_mem_free(pPacket); + pPacket = NULL; + cdf_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 htc_free_control_tx_packet(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 + destroy_htc_tx_ctrl_packet(pPacket); +#endif + +} + +HTC_PACKET *htc_alloc_control_tx_packet(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 build_htc_tx_ctrl_packet(target->osdev); +#endif +} + +/* Set the target failure handling callback */ +void htc_set_target_failure_callback(HTC_HANDLE HTCHandle, + HTC_TARGET_FAILURE Callback) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + target->HTCInitInfo.TargetFailure = Callback; +} + +void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + hif_dump(target->hif_dev, CmdId, start); +} + +/* cleanup the HTC instance */ +static void htc_cleanup(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + /* cdf_nbuf_t netbuf; */ + + if (target->hif_dev != NULL) { + hif_detach_htc(target->hif_dev); + target->hif_dev = NULL; + } + + while (true) { + pPacket = allocate_htc_packet_container(target); + if (NULL == pPacket) { + break; + } + cdf_mem_free(pPacket); + } + + pPacket = target->pBundleFreeList; + while (pPacket) { + HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext; + cdf_mem_free(pPacket); + pPacket = pPacketTmp; + } +#ifdef TODO_FIXME + while (true) { + pPacket = htc_alloc_control_tx_packet(target); + if (NULL == pPacket) { + break; + } + netbuf = (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + if (netbuf != NULL) { + cdf_nbuf_free(netbuf); + } + + cdf_mem_free(pPacket); + } +#endif + + cdf_spinlock_destroy(&target->HTCLock); + cdf_spinlock_destroy(&target->HTCRxLock); + cdf_spinlock_destroy(&target->HTCTxLock); + cdf_spinlock_destroy(&target->HTCCreditLock); + + /* free our instance */ + cdf_mem_free(target); +} + +/* registered target arrival callback from the HIF layer */ +HTC_HANDLE htc_create(void *ol_sc, HTC_INIT_INFO *pInfo, cdf_device_t osdev) +{ + struct hif_msg_callbacks htcCallbacks; + HTC_ENDPOINT *pEndpoint = NULL; + HTC_TARGET *target = NULL; + int i; + + if (ol_sc == NULL) { + HTC_ERROR("%s: ol_sc = NULL", __func__); + return NULL; + } + HTC_TRACE("+htc_create .. HIF :%p", ol_sc); + + A_REGISTER_MODULE_DEBUG_INFO(htc); + + target = (HTC_TARGET *) cdf_mem_malloc(sizeof(HTC_TARGET)); + if (target == NULL) { + HTC_ERROR("%s: Unable to allocate memory", __func__); + return NULL; + } + + A_MEMZERO(target, sizeof(HTC_TARGET)); + + cdf_spinlock_init(&target->HTCLock); + cdf_spinlock_init(&target->HTCRxLock); + cdf_spinlock_init(&target->HTCTxLock); + cdf_spinlock_init(&target->HTCCreditLock); + + do { + A_MEMCPY(&target->HTCInitInfo, pInfo, sizeof(HTC_INIT_INFO)); + target->host_handle = pInfo->pContext; + target->osdev = osdev; + + reset_endpoint_states(target); + + INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); + + for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) { + HTC_PACKET *pPacket = + (HTC_PACKET *) cdf_mem_malloc(sizeof(HTC_PACKET)); + if (pPacket != NULL) { + A_MEMZERO(pPacket, sizeof(HTC_PACKET)); + free_htc_packet_container(target, pPacket); + } + } + +#ifdef TODO_FIXME + for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) { + pPacket = build_htc_tx_ctrl_packet(); + if (NULL == pPacket) { + break; + } + htc_free_control_tx_packet(target, pPacket); + } +#endif + + /* setup HIF layer callbacks */ + cdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks)); + htcCallbacks.Context = target; + htcCallbacks.rxCompletionHandler = htc_rx_completion_handler; + htcCallbacks.txCompletionHandler = htc_tx_completion_handler; + htcCallbacks.txResourceAvailHandler = htc_tx_resource_avail_handler; + htcCallbacks.fwEventHandler = htc_fw_event_handler; + target->hif_dev = ol_sc; + + /* Get HIF default pipe for HTC message exchange */ + pEndpoint = &target->EndPoint[ENDPOINT_0]; + + hif_post_init(target->hif_dev, target, &htcCallbacks); + hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID, + &pEndpoint->DL_PipeID); + + } while (false); + + htc_recv_init(target); + + HTC_TRACE("-htc_create: (0x%p)", target); + + return (HTC_HANDLE) target; +} + +void htc_destroy(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("+htc_destroy .. Destroying :0x%p\n", target)); + if (target) + htc_cleanup(target); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n")); +} + +/* get the low level HIF device for the caller , the caller may wish to do low level + * HIF requests */ +void *htc_get_hif_device(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + return target->hif_dev; +} + +void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket) +{ + HTC_TARGET *target = (HTC_TARGET *) Context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("+-htc_control_tx_complete 0x%p (l:%d) \n", pPacket, + pPacket->ActualLength)); + htc_free_control_tx_packet(target, pPacket); +} + +/* TODO, this is just a temporary max packet size */ +#define MAX_MESSAGE_SIZE 1536 + +/** + * htc_setup_target_buffer_assignments() - setup target buffer assignments + * @target: HTC Target Pointer + * + * Return: A_STATUS + */ +A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) +{ + HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry; + A_STATUS status; + int credits; + int creditsPerMaxMsg; + + 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]; + + /* + * Allocate all credists/HTC buffers to WMI. + * no buffers are used/required for data. data always + * remains on host. + */ + status = A_OK; + pEntry++; + pEntry->ServiceID = WMI_CONTROL_SVC; + pEntry->CreditAllocation = credits; + + if (WLAN_IS_EPPING_ENABLED(cds_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, CDF, 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. + */ + pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->CreditAllocation = (credits >> 1); + + pEntry++; + pEntry->ServiceID = WMI_DATA_BK_SVC; + pEntry->CreditAllocation = (credits >> 1); + } + + 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 htc_get_credit_allocation(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 htc_wait_target(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, + ("htc_wait_target - Enter (target:0x%p) \n", HTCHandle)); + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n")); + + do { + + status = hif_start(target->hif_dev); + if (A_FAILED(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("hif_start failed\n")); + break; + } + + status = htc_wait_recv_ctrl_message(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) pReadyMsg->MaxMsgsPerHTCBundle; + /* 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; + + htc_setup_target_buffer_assignments(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 = htc_control_tx_complete; + connect.EpCallbacks.EpRecv = htc_control_rx_complete; + connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS; + connect.ServiceID = HTC_CTRL_RSVD_SVC; + + /* connect fake service */ + status = htc_connect_service((HTC_HANDLE) target, + &connect, &resp); + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - 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 htc_config_target_hif_pipe(HTC_TARGET *target) +{ + + return A_OK; +} + +static void reset_endpoint_states(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; + cdf_atomic_init(&pEndpoint->TxProcessCount); + } +} + +A_STATUS htc_start(HTC_HANDLE HTCHandle) +{ + cdf_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, ("htc_start Enter\n")); + + do { + + htc_config_target_hif_pipe(target); + + /* allocate a buffer to send */ + pSendPacket = htc_alloc_control_tx_packet(target); + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(false); + cdf_print("%s: allocControlTxPacket failed\n", + __func__); + status = A_NO_MEMORY; + break; + } + + netbuf = + (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); + /* assemble setup complete message */ + cdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); + pSetupComp = + (HTC_SETUP_COMPLETE_EX_MSG *) cdf_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")); + } + +#ifdef HIF_SDIO +#if ENABLE_BUNDLE_RX + if (HTC_ENABLE_BUNDLE(target)) + pSetupComp->SetupFlags |= + HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; +#endif /* ENABLE_BUNDLE_RX */ +#endif /* HIF_SDIO */ + + SET_HTC_PACKET_INFO_TX(pSendPacket, + NULL, + (A_UINT8 *) pSetupComp, + sizeof(HTC_SETUP_COMPLETE_EX_MSG), + ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); + + status = htc_send_pkt((HTC_HANDLE) target, pSendPacket); + if (A_FAILED(status)) { + break; + } + + } while (false); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n")); + return status; +} + +/*flush all queued buffers for surpriseremove case*/ +void htc_flush_surprise_remove(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + HTC_ENDPOINT *pEndpoint; +#ifdef RX_SG_SUPPORT + cdf_nbuf_t netbuf; + cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove \n")); + + /* cleanup endpoints */ + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + htc_flush_rx_hold_queue(target, pEndpoint); + htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); + } + + hif_flush_surprise_remove(target->hif_dev); + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + cdf_nbuf_free(netbuf); + } + RESET_RX_SG_CONFIG(target); + UNLOCK_HTC_RX(target); +#endif + + reset_endpoint_states(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove \n")); +} + +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ +void htc_stop(HTC_HANDLE HTCHandle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + int i; + HTC_ENDPOINT *pEndpoint; +#ifdef RX_SG_SUPPORT + cdf_nbuf_t netbuf; + cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop \n")); + + /* cleanup endpoints */ + for (i = 0; i < ENDPOINT_MAX; i++) { + pEndpoint = &target->EndPoint[i]; + htc_flush_rx_hold_queue(target, pEndpoint); + htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); + if (pEndpoint->ul_is_polled) { + cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer); + cdf_softirq_timer_free(&pEndpoint->ul_poll_timer); + } + } + + /* Note: htc_flush_endpoint_tx for all endpoints should be called before + * hif_stop - otherwise htc_tx_completion_handler 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 + */ + + hif_stop(target->hif_dev); + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + cdf_nbuf_free(netbuf); + } + RESET_RX_SG_CONFIG(target); + UNLOCK_HTC_RX(target); +#endif + + reset_endpoint_states(target); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n")); +} + +void htc_dump_credit_states(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")); + } +} + +A_BOOL htc_get_endpoint_statistics(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); +} + +/** + * htc_set_target_to_sleep() - set target to sleep + * @context: ol_softc context + * + * Return: none + */ +void htc_set_target_to_sleep(void *context) +{ + struct ol_softc *scn = (struct ol_softc *)context; + + hif_set_target_sleep(scn, true, false); +} + +/** + * htc_cancel_deferred_target_sleep() - cancel deferred target sleep + * @context: ol_softc context + * + * Return: none + */ +void htc_cancel_deferred_target_sleep(void *context) +{ + struct ol_softc *scn = (struct ol_softc *)context; + hif_cancel_deferred_target_sleep(scn); +} + +#ifdef IPA_OFFLOAD +void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + if (target->hif_dev != NULL) { + hif_ipa_get_ce_resource(target->hif_dev, + ce_sr_base_paddr, + ce_sr_ring_size, ce_reg_paddr); + } +} +#endif /* IPA_OFFLOAD */ diff --git a/core/htc/htc_api.h b/core/htc/htc_api.h new file mode 100644 index 000000000000..937d326ba7f6 --- /dev/null +++ b/core/htc/htc_api.h @@ -0,0 +1,712 @@ +/* + * 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 _HTC_API_H_ +#define _HTC_API_H_ + +#include +#include "osapi_linux.h" +#include "htc_packet.h" +#include +#include +#include /* cdf_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, CDF_STATUS Status); + +typedef struct _HTC_INIT_INFO { + void *pContext; /* context for target notifications */ + void (*TargetFailure)(void *Instance, CDF_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; +}; + +/* 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_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 */ +} HTC_ENDPOINT_STATS; + +/* ------ Function Prototypes ------ */ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Create an instance of HTC over the underlying HIF device + @function name: htc_create + @input: HifDevice - hif device handle, + pInfo - initialization information + @output: + @return: HTC_HANDLE on success, NULL on failure + @notes: + @example: + @see also: htc_destroy + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +HTC_HANDLE htc_create(void *HifDevice, + HTC_INIT_INFO *pInfo, cdf_device_t osdev); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the underlying HIF device handle + @function name: htc_get_hif_device + @input: HTCHandle - handle passed into the AddInstance callback + @output: + @return: opaque HIF device handle usable in HIF API calls. + @notes: + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void *htc_get_hif_device(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set credit distribution parameters + @function name: htc_set_credit_distribution + @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 htc_set_credit_distribution(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: htc_wait_target + @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: htc_connect_service + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS htc_wait_target(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Start target service communications + @function name: htc_start + @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: htc_connect_service + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS htc_start(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add receive packet to HTC + @function name: htc_add_receive_pkt + @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 htc_add_receive_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Connect to an HTC service + @function name: htc_connect_service + @input: HTCHandle - HTC handle + pReq - connection details + @output: pResp - connection response + @return: + @notes: Service connections must be performed before htc_start. User provides callback handlers + for various endpoint events. + @example: + @see also: htc_start + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, + HTC_SERVICE_CONNECT_REQ *pReq, + HTC_SERVICE_CONNECT_RESP *pResp); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: HTC register log dump + @function name: htc_dump + @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 htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet + @function name: htc_send_pkt + @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: htc_flush_endpoint + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS htc_send_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Send an HTC packet containing a tx descriptor and data + @function name: htc_send_data_pkt + @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, htc_send_data_pkt will + call the registered Endpoint EpDataTxComplete callback to cleanup + the packet. + @example: + @see also: htc_send_pkt + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#ifdef ATH_11AC_TXCOMPACT +A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, cdf_nbuf_t netbuf, + int Epid, int ActualLength); +#else /*ATH_11AC_TXCOMPACT */ +A_STATUS htc_send_data_pkt(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: htc_flush_surprise_remove + @input: HTCHandle - HTC handle + @output: + @return: + @notes: All receive and pending TX packets will + be flushed. + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_flush_surprise_remove(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Stop HTC service communications + @function name: htc_stop + @input: HTCHandle - HTC handle + @output: + @return: + @notes: HTC communications is halted. All receive and pending TX packets will + be flushed. + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_stop(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Destory HTC service + @function name: htc_destroy + @input: HTCHandle + @output: + @return: + @notes: This cleans up all resources allocated by htc_create(). + @example: + @see also: htc_create + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_destroy(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Flush pending TX packets + @function name: htc_flush_endpoint + @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: htc_send_pkt + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, + HTC_TX_TAG Tag); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Dump credit distribution state + @function name: htc_dump_credit_states + @input: HTCHandle - HTC handle + @output: + @return: + @notes: This dumps all credit distribution information to the debugger + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_dump_credit_states(HTC_HANDLE HTCHandle); +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Indicate a traffic activity change on an endpoint + @function name: htc_indicate_activity_change + @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 htc_indicate_activity_change(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, A_BOOL Active); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get endpoint statistics + @function name: htc_get_endpoint_statistics + @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 htc_get_endpoint_statistics(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, + HTC_ENDPOINT_STAT_ACTION Action, + HTC_ENDPOINT_STATS *pStats); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Unblock HTC message reception + @function name: htc_unblock_recv + @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 htc_unblock_recv(HTC_HANDLE HTCHandle); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: send a series of HTC packets + @function name: htc_send_pkts_multiple + @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, htc_send_pkts will + call the registered Endpoint callback to cleanup the packet. + @example: + @see also: htc_flush_endpoint + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +A_STATUS htc_send_pkts_multiple(HTC_HANDLE HTCHandle, + HTC_PACKET_QUEUE *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Add multiple receive packets to HTC + @function name: htc_add_receive_pkt_multiple + @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 htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle, + HTC_PACKET_QUEUE *pPktQueue); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Check if an endpoint is marked active + @function name: htc_is_endpoint_active + @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 htc_is_endpoint_active(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Get the number of recv buffers currently queued into an HTC endpoint + @function name: htc_get_num_recv_buffers + @input: HTCHandle - HTC handle + Endpoint - endpoint to check + @output: + @return: returns number of buffers in queue + @notes: + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint); + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @desc: Set the target failure handling callback in HTC layer + @function name: htc_set_target_failure_callback + @input: HTCHandle - HTC handle + Callback - target failure handling callback + @output: + @return: + @notes: + @example: + @see also: + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +void htc_set_target_failure_callback(HTC_HANDLE HTCHandle, + HTC_TARGET_FAILURE Callback); + +/* internally used functions for testing... */ +void htc_enable_recv(HTC_HANDLE HTCHandle); +void htc_disable_recv(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) { \ + cdf_mem_free(p); \ + } +#else +#define HTCReturnReceivePkt(target,p,osbuf) htc_add_receive_pkt(target,p) +#endif + +#ifdef WLAN_FEATURE_FASTPATH +#define HTC_TX_DESC_FILL(_htc_tx_desc, _download_len, _ep_id, _seq_no) \ +do { \ + HTC_WRITE32((_htc_tx_desc), \ + SM((_download_len), HTC_FRAME_HDR_PAYLOADLEN) | \ + SM((_ep_id), HTC_FRAME_HDR_ENDPOINTID)); \ + \ + HTC_WRITE32((A_UINT32 *)(_htc_tx_desc) + 1, \ + SM((_seq_no), HTC_FRAME_HDR_CONTROLBYTES1));\ +} while (0) +#endif /* WLAN_FEATURE_FASTPATH */ + +#ifdef __cplusplus +} +#endif +void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle, int *credit); +void htc_dump_counter_info(HTC_HANDLE HTCHandle); +void *htc_get_targetdef(HTC_HANDLE htc_handle); +void htc_set_target_to_sleep(void *context); +void htc_cancel_deferred_target_sleep(void *context); + +/* Disable ASPM : Disable PCIe low power */ +void htc_disable_aspm(void); + +#ifdef IPA_OFFLOAD +void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, + uint32_t *ce_sr_base_paddr, + uint32_t *ce_sr_ring_size, + cdf_dma_addr_t *ce_reg_paddr); +#else +#define htc_ipa_get_ce_resource(htc_handle, \ + ce_sr_base_paddr, \ + ce_sr_ring_size, \ + ce_reg_paddr) /* NO-OP */ +#endif /* IPA_OFFLOAD */ +#endif /* _HTC_API_H_ */ diff --git a/core/htc/htc_debug.h b/core/htc/htc_debug.h new file mode 100644 index 000000000000..fe0c8496f813 --- /dev/null +++ b/core/htc/htc_debug.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 HTC_DEBUG_H_ +#define HTC_DEBUG_H_ + +#define ATH_MODULE_NAME htc +#include "a_debug.h" +#include "cdf_trace.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) +#define HTC_ERROR(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HTC, CDF_TRACE_LEVEL_ERROR, ## args) +#define HTC_WARN(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HTC, CDF_TRACE_LEVEL_WARN, ## args) +#define HTC_INFO(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HTC, CDF_TRACE_LEVEL_INFO, ## args) +#define HTC_TRACE(args ...) \ + CDF_TRACE(CDF_MODULE_ID_HTC, CDF_TRACE_LEVEL_DEBUG, ## args) +#endif /*HTC_DEBUG_H_ */ diff --git a/core/htc/htc_internal.h b/core/htc/htc_internal.h new file mode 100644 index 000000000000..2e48b790d4c2 --- /dev/null +++ b/core/htc/htc_internal.h @@ -0,0 +1,310 @@ +/* + * 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 */ + +#include +#include "a_types.h" +#include "osapi_linux.h" +#include +#include +#include +#include +#include +#include "hif.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 9 +#else +#define HTC_MAX_MSG_PER_BUNDLE 16 +#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; + uint64_t time; + uint32_t tx_credit; + uint32_t 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 */ + uint8_t UL_PipeID; + uint8_t DL_PipeID; + int ul_is_polled; /* Need to call HIF to get tx completion callbacks? */ + cdf_softirq_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 */ + cdf_softirq_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 */ + cdf_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 { + struct ol_softc *hif_dev; + HTC_ENDPOINT EndPoint[ENDPOINT_MAX]; + cdf_spinlock_t HTCLock; + cdf_spinlock_t HTCRxLock; + cdf_spinlock_t HTCTxLock; + cdf_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; + cdf_semaphore_t CtrlResponseValid; + A_BOOL CtrlResponseProcessing; + int TotalTransmitCredits; + HTC_SERVICE_TX_CREDIT_ALLOCATION + ServiceTxAllocTable[HTC_MAX_SERVICE_ALLOC_ENTRIES]; + int TargetCreditSize; +#ifdef RX_SG_SUPPORT + cdf_nbuf_queue_t RxSgQueue; + A_BOOL IsRxSgInprogress; + A_UINT32 CurRxSgTotalLen; /* current total length */ + A_UINT32 ExpRxSgTotalLen; /* expected total length */ +#endif + cdf_device_t osdev; + struct ol_ath_htc_stats htc_pkt_stats; + HTC_PACKET *pBundleFreeList; + A_UINT32 ce_send_cnt; + A_UINT32 TX_comp_cnt; + A_UINT8 MaxMsgsPerHTCBundle; +} 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) cdf_spin_lock_bh(&(t)->HTCLock); +#define UNLOCK_HTC(t) cdf_spin_unlock_bh(&(t)->HTCLock); +#define LOCK_HTC_RX(t) cdf_spin_lock_bh(&(t)->HTCRxLock); +#define UNLOCK_HTC_RX(t) cdf_spin_unlock_bh(&(t)->HTCRxLock); +#define LOCK_HTC_TX(t) cdf_spin_lock_bh(&(t)->HTCTxLock); +#define UNLOCK_HTC_TX(t) cdf_spin_unlock_bh(&(t)->HTCTxLock); +#define LOCK_HTC_CREDIT(t) cdf_spin_lock_bh(&(t)->HTCCreditLock); +#define UNLOCK_HTC_CREDIT(t) cdf_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 */ + +CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, + uint8_t pipeID); +CDF_STATUS htc_tx_completion_handler(void *Context, cdf_nbuf_t netbuf, + unsigned int transferID, uint32_t toeplitz_hash_result); + +HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target); +void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket); + +HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target); +void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket); +void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint); +void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, + HTC_TX_TAG Tag); +void htc_recv_init(HTC_TARGET *target); +A_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target); +void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket); +HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target); +A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID); +void htc_tx_resource_avail_handler(void *context, A_UINT8 pipeID); +void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket); +void htc_process_credit_rpt(HTC_TARGET *target, + HTC_CREDIT_REPORT *pRpt, + int NumEntries, HTC_ENDPOINT_ID FromEndpoint); +void htc_fw_event_handler(void *context, CDF_STATUS status); +void htc_send_complete_check_cleanup(void *context); + +void htc_credit_record(htc_credit_exchange_type type, uint32_t tx_credit, + uint32_t htc_tx_queue_depth); + +static inline void htc_send_complete_poll_timer_stop(HTC_ENDPOINT * + pEndpoint) { + LOCK_HTC_TX(pEndpoint->target); + if (pEndpoint->ul_poll_timer_active) { + /* cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer); */ + pEndpoint->ul_poll_timer_active = 0; + } + UNLOCK_HTC_TX(pEndpoint->target); +} + +static inline void htc_send_complete_poll_timer_start(HTC_ENDPOINT * + pEndpoint) { + LOCK_HTC_TX(pEndpoint->target); + if (pEndpoint->ul_outstanding_cnt + && !pEndpoint->ul_poll_timer_active) { + /* + cdf_softirq_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 +htc_send_complete_check(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. + */ + htc_send_complete_poll_timer_stop(pEndpoint); + /* + * Check whether HIF has any prior sends that have finished, + * have not had the post-processing done. + */ + hif_send_complete_check(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. + */ + htc_send_complete_poll_timer_start(pEndpoint); +} + +#ifdef __cplusplus +} +#endif + +#ifndef DEBUG_BUNDLE +#define DEBUG_BUNDLE 0 +#endif + +#ifdef HIF_SDIO +#ifndef ENABLE_BUNDLE_TX +#define ENABLE_BUNDLE_TX 1 +#endif + +#ifndef ENABLE_BUNDLE_RX +#define ENABLE_BUNDLE_RX 1 +#endif +#endif /* HIF_SDIO */ +#endif /* !_HTC_HOST_INTERNAL_H_ */ diff --git a/core/htc/htc_packet.h b/core/htc/htc_packet.h new file mode 100644 index 000000000000..c30d5114434b --- /dev/null +++ b/core/htc/htc_packet.h @@ -0,0 +1,266 @@ +/* + * 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 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_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; \ + } + +#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_list_insert_tail(& (pQ)->QueueHead,& (p)->ListLink); \ + (pQ)->Depth ++; \ + } + +/* enqueue HTC packet to the tail of the queue */ +#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \ + { dl_list_insert_head(& (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_list_remove(& (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_list_remove_item_from_head(&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_list_remove_item_from_tail(&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_list_transfer_items_to_tail(&(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_list_transfer_items_to_head(&(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/core/htc/htc_recv.c b/core/htc/htc_recv.c new file mode 100644 index 000000000000..dd8719e2649e --- /dev/null +++ b/core/htc/htc_recv.c @@ -0,0 +1,743 @@ +/* + * 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 "cds_api.h" +#include /* cdf_nbuf_t */ +#include +#include "epping_main.h" + +#ifdef DEBUG +void debug_dump_bytes(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 debug_dump_bytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) +{ +} +#endif + +static A_STATUS htc_process_trailer(HTC_TARGET *target, + A_UINT8 *pBuffer, + int Length, HTC_ENDPOINT_ID FromEndpoint); + +static void do_recv_completion(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 recv_packet_completion(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, + HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE container; + INIT_HTC_PACKET_QUEUE_AND_ADD(&container, pPacket); + /* do completion */ + do_recv_completion(pEndpoint, &container); +} + +void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket) +{ + /* TODO, can't really receive HTC control messages yet.... */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid call to htc_control_rx_complete\n")); +} + +void htc_unblock_recv(HTC_HANDLE HTCHandle) +{ + /* TODO find the Need in new model */ +} + +void htc_enable_recv(HTC_HANDLE HTCHandle) +{ + + /* TODO find the Need in new model */ +} + +void htc_disable_recv(HTC_HANDLE HTCHandle) +{ + + /* TODO find the Need in new model */ +} + +int htc_get_num_recv_buffers(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 *allocate_htc_packet_container(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 free_htc_packet_container(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 +cdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target) +{ + cdf_nbuf_t skb; + uint8_t *anbdata; + uint8_t *anbdata_new; + uint32_t anblen; + cdf_nbuf_t new_skb = NULL; + uint32_t sg_queue_len; + cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; + + sg_queue_len = cdf_nbuf_queue_len(rx_sg_queue); + + if (sg_queue_len <= 1) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("rx_sg_to_single_netbuf: invalid sg queue len %u\n")); + goto _failed; + } + + new_skb = cdf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, false); + if (new_skb == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("rx_sg_to_single_netbuf: can't allocate %u size netbuf\n", + target->ExpRxSgTotalLen)); + goto _failed; + } + + cdf_nbuf_peek_header(new_skb, &anbdata_new, &anblen); + + skb = cdf_nbuf_queue_remove(rx_sg_queue); + do { + cdf_nbuf_peek_header(skb, &anbdata, &anblen); + cdf_mem_copy(anbdata_new, anbdata, cdf_nbuf_len(skb)); + cdf_nbuf_put_tail(new_skb, cdf_nbuf_len(skb)); + anbdata_new += cdf_nbuf_len(skb); + cdf_nbuf_free(skb); + skb = cdf_nbuf_queue_remove(rx_sg_queue); + } while (skb != NULL); + + RESET_RX_SG_CONFIG(target); + return new_skb; + +_failed: + + while ((skb = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) { + cdf_nbuf_free(skb); + } + + RESET_RX_SG_CONFIG(target); + return NULL; +} +#endif + +CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, + uint8_t pipeID) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + HTC_FRAME_HDR *HtcHdr; + HTC_TARGET *target = (HTC_TARGET *) Context; + uint8_t *netdata; + uint32_t netlen; + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; + A_UINT16 payloadLen; + uint32_t trailerlen = 0; + A_UINT8 htc_ep_id; + +#ifdef RX_SG_SUPPORT + LOCK_HTC_RX(target); + if (target->IsRxSgInprogress) { + target->CurRxSgTotalLen += cdf_nbuf_len(netbuf); + cdf_nbuf_queue_add(&target->RxSgQueue, netbuf); + if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) { + netbuf = rx_sg_to_single_netbuf(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 = cdf_nbuf_data(netbuf); + netlen = cdf_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)); + debug_dump_bytes((A_UINT8 *) HtcHdr, + sizeof(HTC_FRAME_HDR), "BAD HTC Header"); + status = CDF_STATUS_E_FAILURE; + CDF_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) { + htc_send_complete_check(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; + cdf_nbuf_queue_init(&target->RxSgQueue); + cdf_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)); + debug_dump_bytes((A_UINT8 *) HtcHdr, + sizeof(HTC_FRAME_HDR), + "BAD RX packet length"); + status = CDF_STATUS_E_FAILURE; + CDF_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; + A_STATUS temp_status; + /* 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, + ("htc_rx_completion_handler, invalid header (payloadlength should be :%d, CB[0] is:%d)\n", + payloadLen, temp)); + status = CDF_STATUS_E_INVAL; + break; + } + + trailerlen = temp; + /* process trailer data that follows HDR + application payload */ + temp_status = htc_process_trailer(target, + ((A_UINT8 *) HtcHdr + + HTC_HDR_LENGTH + + payloadLen - temp), + temp, htc_ep_id); + if (A_FAILED(temp_status)) { + status = CDF_STATUS_E_FAILURE; + 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 */ + cdf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH); + netdata = cdf_nbuf_data(netbuf); + netlen = cdf_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 = CDF_STATUS_E_FAILURE; + break; + } + + LOCK_HTC_RX(target); + target->CtrlResponseLength = + min((int)netlen, + HTC_MAX_CONTROL_MESSAGE_LENGTH); + A_MEMCPY(target->CtrlResponseBuffer, netdata, + target->CtrlResponseLength); + UNLOCK_HTC_RX(target); + + cdf_semaphore_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); + break; + case HTC_MSG_NACK_SUSPEND: + wow_nack = 1; + 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); + break; + } + + cdf_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 = allocate_htc_packet_container(target); + if (NULL == pPacket) { + status = CDF_STATUS_E_RESOURCES; + break; + } + pPacket->Status = CDF_STATUS_SUCCESS; + pPacket->Endpoint = htc_ep_id; + pPacket->pPktContext = netbuf; + pPacket->pBuffer = cdf_nbuf_data(netbuf) + HTC_HDR_LENGTH; + pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen; + + cdf_nbuf_pull_head(netbuf, HTC_HEADER_LEN); + cdf_nbuf_set_pktlen(netbuf, pPacket->ActualLength); + + recv_packet_completion(target, pEndpoint, pPacket); + /* recover the packet container */ + free_htc_packet_container(target, pPacket); + netbuf = NULL; + + } while (false); + +#ifdef RX_SG_SUPPORT +_out: +#endif + + if (netbuf != NULL) { + cdf_nbuf_free(netbuf); + } + + return status; + +} + +A_STATUS htc_add_receive_pkt_multiple(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, + ("+- htc_add_receive_pkt_multiple : 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; + + do_recv_completion(pEndpoint, pPktQueue); + } + + return status; +} + +A_STATUS htc_add_receive_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE queue; + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue, pPacket); + return htc_add_receive_pkt_multiple(HTCHandle, &queue); +} + +void htc_flush_rx_hold_queue(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 */ + do_recv_completion(pEndpoint, &container); + LOCK_HTC_RX(target); + } + + UNLOCK_HTC_RX(target); +} + +void htc_recv_init(HTC_TARGET *target) +{ + /* Initialize CtrlResponseValid to block */ + cdf_semaphore_init(&target->CtrlResponseValid); + cdf_semaphore_acquire(target->osdev, &target->CtrlResponseValid); +} + +/* polling routine to wait for a control packet to be received */ +A_STATUS htc_wait_recv_ctrl_message(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 (cdf_semaphore_acquire(target->osdev, &target->CtrlResponseValid)) { + } + + LOCK_HTC_RX(target); + /* caller will clear this flag */ + target->CtrlResponseProcessing = true; + + UNLOCK_HTC_RX(target); + +#if 0 + while (count > 0) { + + LOCK_HTC_RX(target); + + if (target->CtrlResponseValid) { + target->CtrlResponseValid = false; + /* caller will clear this flag */ + target->CtrlResponseProcessing = true; + UNLOCK_HTC_RX(target); + break; + } + + UNLOCK_HTC_RX(target); + + count--; + A_MSLEEP(HTC_TARGET_RESPONSE_POLL_MS); + } + + if (count <= 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("-HTCWaitCtrlMessageRecv: Timeout!\n")); + return A_ECOMM; + } +#endif + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCWaitCtrlMessageRecv success\n")); + return A_OK; +} + +static A_STATUS htc_process_trailer(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, + ("+htc_process_trailer (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)); + htc_process_credit_rpt(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)) { + debug_dump_bytes(pOrigBuffer, origLength, "BAD Recv Trailer"); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer \n")); + return status; + +} diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c new file mode 100644 index 000000000000..e011538de1a9 --- /dev/null +++ b/core/htc/htc_send.c @@ -0,0 +1,1850 @@ +/* + * 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 /* cdf_nbuf_t */ +#include /* cdf_mem_malloc */ +#include +#include "epping_main.h" + +/* #define USB_HIF_SINGLE_PIPE_DATA_SCHED */ +/* #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED */ +#define DATA_EP_SIZE 4 +/* #endif */ +#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]; + +/** + * htc_credit_record() - records tx que state & credit transactions + * @type: type of echange can be HTC_REQUEST_CREDIT + * or HTC_PROCESS_CREDIT_REPORT + * @tx_credits: current number of tx_credits + * @htc_tx_queue_depth: current hct tx queue depth + * + * This function records the credits and pending commands whenever a command is + * sent or credits are returned. Call this after the credits have been updated + * according to the transaction. Call this before dequeing commands. + * + * Consider making this function accept an HTC_ENDPOINT and find the current + * credits and queue depth itself. + * + * Consider moving the LOCK_HTC_CREDIT(target); logic into this function as well. + */ +void htc_credit_record(htc_credit_exchange_type type, uint32_t tx_credit, + uint32_t 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 = + cdf_get_log_timestamp(); + 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++; + +#ifdef QCA_WIFI_3_0_EMU + if (type == HTC_REQUEST_CREDIT) + printk("\nrequest_credits-> current_credit %d, pending commands %d\n", + tx_credit, htc_tx_queue_depth); + + else if (type == HTC_PROCESS_CREDIT_REPORT) + printk("\ncredit_report<- current_credit %d, pending commands %d\n", + tx_credit, htc_tx_queue_depth); +#endif +} + +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 htc_get_control_endpoint_tx_host_credits(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 restore_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) { + cdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + cdf_nbuf_unmap(target->osdev, netbuf, CDF_DMA_TO_DEVICE); + cdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); + pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF; + } + +} + +static void do_send_completion(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 send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint]; + HTC_PACKET_QUEUE container; + + restore_tx_packet(target, pPacket); + INIT_HTC_PACKET_QUEUE_AND_ADD(&container, pPacket); + + /* do completion */ + do_send_completion(pEndpoint, &container); +} + +void htc_send_complete_check_cleanup(void *context) +{ + HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context; + htc_send_complete_check(pEndpoint, 1); +} + +HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target) +{ + HTC_PACKET *pPacket; + HTC_PACKET_QUEUE *pQueueSave; + cdf_nbuf_t netbuf; + LOCK_HTC_TX(target); + if (NULL == target->pBundleFreeList) { + UNLOCK_HTC_TX(target); + netbuf = cdf_nbuf_alloc(NULL, + target->MaxMsgsPerHTCBundle * + target->TargetCreditSize, 0, 4, false); + AR_DEBUG_ASSERT(netbuf); + if (!netbuf) { + return NULL; + } + pPacket = cdf_mem_malloc(sizeof(HTC_PACKET)); + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) { + cdf_nbuf_free(netbuf); + return NULL; + } + pQueueSave = cdf_mem_malloc(sizeof(HTC_PACKET_QUEUE)); + AR_DEBUG_ASSERT(pQueueSave); + if (!pQueueSave) { + cdf_nbuf_free(netbuf); + cdf_mem_free(pPacket); + return NULL; + } + INIT_HTC_PACKET_QUEUE(pQueueSave); + pPacket->pContext = pQueueSave; + SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); + pPacket->pBuffer = cdf_nbuf_data(netbuf); + pPacket->BufferLength = cdf_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 = cdf_nbuf_headroom(netbuf); + return pPacket; + } + /* already done malloc - restore from free list */ + pPacket = target->pBundleFreeList; + AR_DEBUG_ASSERT(pPacket); + if (!pPacket) { + UNLOCK_HTC_TX(target); + return NULL; + } + target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext; + UNLOCK_HTC_TX(target); + pPacket->ListLink.pNext = NULL; + + return pPacket; +} + +void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket) +{ + A_UINT32 curentHeadRoom; + cdf_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 = cdf_nbuf_headroom(netbuf); + cdf_nbuf_pull_head(netbuf, + pPacket->netbufOrigHeadRoom - curentHeadRoom); + cdf_nbuf_trim_tail(netbuf, cdf_nbuf_len(netbuf)); + + /* restore the pBuffer pointer. HIF changes this */ + pPacket->pBuffer = cdf_nbuf_data(netbuf); + pPacket->BufferLength = cdf_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->pBundleFreeList == NULL) { + target->pBundleFreeList = pPacket; + pPacket->ListLink.pNext = NULL; + } else { + pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList; + target->pBundleFreeList = pPacket; + } + UNLOCK_HTC_TX(target); +} + +#if defined(HIF_USB) || defined(HIF_SDIO) +#ifdef ENABLE_BUNDLE_TX +static A_STATUS htc_send_bundled_netbuf(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + unsigned char *pBundleBuffer, + HTC_PACKET *pPacketTx) +{ + cdf_size_t data_len; + A_STATUS status; + cdf_nbuf_t bundleBuf; + uint32_t data_attr = 0; + + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + data_len = pBundleBuffer - cdf_nbuf_data(bundleBuf); + cdf_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 + cdf_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 + status = hif_send_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, data_len, bundleBuf, data_attr); + if (status != A_OK) { + cdf_print("%s:hif_send_head failed(len=%d).\n", __FUNCTION__, + data_len); + } + return status; +} + +static void htc_issue_packets_bundle(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pPktQueue) +{ + int i, frag_count, nbytes; + cdf_nbuf_t netbuf, bundleBuf; + unsigned char *pBundleBuffer = NULL; + HTC_PACKET *pPacket = NULL, *pPacketTx = NULL; + HTC_FRAME_HDR *pHtcHdr; + int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining = + 0; + HTC_PACKET_QUEUE *pQueueSave = NULL; + + bundlesSpaceRemaining = + target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize; + pPacketTx = allocate_htc_bundle_packet(target); + if (!pPacketTx) { + /* good time to panic */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("allocate_htc_bundle_packet failed \n")); + AR_DEBUG_ASSERT(false); + return; + } + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + pBundleBuffer = cdf_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 */ + htc_send_bundled_netbuf(target, pEndpoint, pBundleBuffer, + pPacketTx); + if (HTC_PACKET_QUEUE_DEPTH(pPktQueue) < + HTC_MIN_MSG_PER_BUNDLE) { + return; + } + bundlesSpaceRemaining = + target->MaxMsgsPerHTCBundle * + pEndpoint->TxCreditSize; + pPacketTx = allocate_htc_bundle_packet(target); + if (!pPacketTx) { + /* good time to panic */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("allocate_htc_bundle_packet failed \n")); + AR_DEBUG_ASSERT(false); + return; + } + bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); + pBundleBuffer = cdf_nbuf_data(bundleBuf); + pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext; + } + + bundlesSpaceRemaining -= transferLength; + netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + pHtcHdr = (HTC_FRAME_HDR *) cdf_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; + frag_count = cdf_nbuf_get_num_frags(netbuf); + nbytes = pPacket->ActualLength + HTC_HDR_LENGTH; + for (i = 0; i < frag_count && nbytes > 0; i++) { + int frag_len = cdf_nbuf_get_frag_len(netbuf, i); + unsigned char *frag_addr = + cdf_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; + } + if (pBundleBuffer != cdf_nbuf_data(bundleBuf)) { + /* send out remaining buffer */ + htc_send_bundled_netbuf(target, pEndpoint, pBundleBuffer, + pPacketTx); + } else { + free_htc_bundle_packet(target, pPacketTx); + } +} +#endif /* ENABLE_BUNDLE_TX */ +#endif + +static A_STATUS htc_issue_packets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pPktQueue) +{ + A_STATUS status = A_OK; + cdf_nbuf_t netbuf; + HTC_PACKET *pPacket = NULL; + uint16_t payloadLen; + HTC_FRAME_HDR *pHtcHdr; + uint32_t data_attr = 0; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+htc_issue_packets: 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 (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint) && + HTC_ENABLE_BUNDLE(target) && + HTC_PACKET_QUEUE_DEPTH(pPktQueue) >= + HTC_MIN_MSG_PER_BUNDLE) { + htc_issue_packets_bundle(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 *) cdf_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) { + cdf_nbuf_map(target->osdev, + GET_HTC_PACKET_NET_BUF_CONTEXT + (pPacket), CDF_DMA_TO_DEVICE); + } + } + 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 = hif_send_head(target->hif_dev, + pEndpoint->UL_PipeID, pEndpoint->Id, + HTC_HDR_LENGTH + pPacket->ActualLength, + netbuf, data_attr); +#if DEBUG_BUNDLE + cdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n", + pEndpoint->Id, + pEndpoint->TxCreditSize, + HTC_HDR_LENGTH + pPacket->ActualLength); +#endif + + target->ce_send_cnt++; + + if (cdf_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, + ("hif_send 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 */ +#if defined(HIF_USB) + if (pEndpoint->Id >= ENDPOINT_2 + && pEndpoint->Id <= ENDPOINT_5) + target->avail_tx_credits += + pPacket->PktInfo.AsTx.CreditsUsed; + else + pEndpoint->TxCredits += + pPacket->PktInfo.AsTx.CreditsUsed; +#else + pEndpoint->TxCredits += + pPacket->PktInfo.AsTx.CreditsUsed; +#endif + /* put it back into the callers queue */ + HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket); + UNLOCK_HTC_TX(target); + break; + } + + } + if (cdf_unlikely(A_FAILED(status))) { +#if defined(HIF_USB) + if (pEndpoint->Id >= ENDPOINT_2 && pEndpoint->Id <= ENDPOINT_5) + target->avail_tx_credits += + pPacket->PktInfo.AsTx.CreditsUsed; + else + pEndpoint->TxCredits += + pPacket->PktInfo.AsTx.CreditsUsed; +#endif + while (!HTC_QUEUE_EMPTY(pPktQueue)) { + if (status != A_NO_RESOURCE) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("htc_issue_packets, failed pkt:0x%p status:%d \n", + pPacket, status)); + } + pPacket = htc_packet_dequeue(pPktQueue); + if (pPacket) { + pPacket->Status = status; + send_packet_completion(target, pPacket); + } + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets \n")); + + return status; +} + +/* get HTC send packets from the TX queue on an endpoint, based on available credits */ +void get_htc_send_packets_credit_based(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue) +{ + int creditsRequired; + int remainder; + A_UINT8 sendFlags; + HTC_PACKET *pPacket; + unsigned int transferLength; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+get_htc_send_packets_credit_based \n")); + + /* loop until we can grab as many packets out of the queue as we can */ + while (true) { + + sendFlags = 0; + /* get packet at head, but don't remove it */ + pPacket = htc_get_pkt_at_head(&pEndpoint->TxQueue); + if (pPacket == NULL) { + break; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Got head packet:%p , Queue Depth: %d\n", + pPacket, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + + 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; +#if defined(HIF_USB) + } else if (pEndpoint->Id >= ENDPOINT_2 + && pEndpoint->Id <= ENDPOINT_5) { + if (target->avail_tx_credits < creditsRequired) + break; + + target->avail_tx_credits -= creditsRequired; + + if (target->avail_tx_credits < 9) { + /* tell the target we need credits ASAP! */ + sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; + INC_HTC_EP_STAT(pEndpoint, + TxCreditLowIndications, 1); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Host Needs Credits \n")); + } +#endif + } 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 + 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(&pEndpoint->TxQueue); + 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); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets_credit_based \n")); + +} + +void get_htc_send_packets(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + HTC_PACKET_QUEUE *pQueue, int Resources) +{ + + HTC_PACKET *pPacket; + + /****** NOTE : the TX lock is held when this function is called *****************/ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+get_htc_send_packets %d resources\n", Resources)); + + /* loop until we can grab as many packets out of the queue as we can */ + while (Resources > 0) { + int num_frags; + + pPacket = htc_packet_dequeue(&pEndpoint->TxQueue); + if (pPacket == NULL) { + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + (" Got packet:%p , New Queue Depth: %d\n", + pPacket, + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); + /* 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 cdf_nbuf_get_num_frags before calling + * cdf_nbuf_map, because the MacOS version of cdf_nbuf_t doesn't + * support cdf_nbuf_get_num_frags until after cdf_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 */ : + cdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT + (pPacket)); + Resources -= num_frags; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets \n")); + +} + +static HTC_SEND_QUEUE_RESULT htc_try_send(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, ("+htc_try_send (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. + */ + restore_tx_packet(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 */ + cdf_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, ("-htc_try_send: \n")); + return result; + } + + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + tx_resources = + hif_get_free_queue_number(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 */ + cdf_atomic_inc(&pEndpoint->TxProcessCount); + if (cdf_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 */ + cdf_atomic_dec(&pEndpoint->TxProcessCount); + UNLOCK_HTC_TX(target); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (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 */ + get_htc_send_packets_credit_based(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 { + /* get all the packets for this endpoint that we can for this pass */ + get_htc_send_packets(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 */ + htc_issue_packets(target, pEndpoint, &sendQueue); + + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + tx_resources = + hif_get_free_queue_number(target->hif_dev, + pEndpoint->UL_PipeID); + } + + LOCK_HTC_TX(target); + + } + + UNLOCK_HTC_TX(target); + /* done with this endpoint, we can clear the count */ + cdf_atomic_init(&pEndpoint->TxProcessCount); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: \n")); + + return HTC_SEND_QUEUE_OK; +} + +#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED +static A_UINT16 htc_send_pkts_sched_check(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID id) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_ENDPOINT_ID eid; + HTC_PACKET_QUEUE *pTxQueue; + A_UINT16 resources; + A_UINT16 acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 }; + + if (id < ENDPOINT_2 || id > ENDPOINT_5) { + return 1; + } + + for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) { + pEndpoint = &target->EndPoint[eid]; + pTxQueue = &pEndpoint->TxQueue; + + if (HTC_QUEUE_EMPTY(pTxQueue)) { + acQueueStatus[eid - 2] = 1; + } + } + + switch (id) { + case ENDPOINT_2: /* BE */ + return (acQueueStatus[0] && acQueueStatus[2] + && acQueueStatus[3]); + case ENDPOINT_3: /* BK */ + return (acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2] + && acQueueStatus[3]); + case ENDPOINT_4: /* VI */ + return (acQueueStatus[2] && acQueueStatus[3]); + case ENDPOINT_5: /* VO */ + return (acQueueStatus[3]); + default: + return 0; + } + +} + +static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target, + HTC_PACKET_QUEUE *pPktQueue, + HTC_ENDPOINT_ID eid) +{ + HTC_ENDPOINT *pEndpoint; + HTC_PACKET_QUEUE *pTxQueue; + HTC_PACKET *pPacket; + int goodPkts; + + pEndpoint = &target->EndPoint[eid]; + pTxQueue = &pEndpoint->TxQueue; + + LOCK_HTC_TX(target); + + goodPkts = + pEndpoint->MaxTxQueueDepth - + HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); + + if (goodPkts > 0) { + while (!HTC_QUEUE_EMPTY(pPktQueue)) { + pPacket = htc_packet_dequeue(pPktQueue); + HTC_PACKET_ENQUEUE(pTxQueue, pPacket); + goodPkts--; + + if (goodPkts <= 0) { + break; + } + } + } + + if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) { + ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket, + HTC_PACKET, ListLink) { + + if (pEndpoint->EpCallBacks. + EpSendFull(pEndpoint->EpCallBacks.pContext, + pPacket) == HTC_SEND_FULL_DROP) { + INC_HTC_EP_STAT(pEndpoint, TxDropped, 1); + } else { + HTC_PACKET_REMOVE(pPktQueue, pPacket); + HTC_PACKET_ENQUEUE(pTxQueue, pPacket); + } + } + ITERATE_END; + } + + UNLOCK_HTC_TX(target); + + return A_OK; +} + +#endif + +A_STATUS htc_send_pkts_multiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; + cdf_nbuf_t netbuf; + HTC_FRAME_HDR *pHtcHdr; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+htc_send_pkts_multiple: 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, ("-htc_send_pkts_multiple \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); + + cdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); + /* setup HTC frame header */ + pHtcHdr = (HTC_FRAME_HDR *) cdf_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. + */ + cdf_nbuf_map(target->osdev, + GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), + CDF_DMA_TO_DEVICE); + + pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF; + } + HTC_PACKET_QUEUE_ITERATE_END; + +#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED + if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id)) { + htc_send_pkts_sched_queue(HTCHandle, pPktQueue, pEndpoint->Id); + } else { + htc_try_send(target, pEndpoint, pPktQueue); + } +#else + htc_try_send(target, pEndpoint, pPktQueue); +#endif + + /* 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 */ + restore_tx_packet(target, pPacket); + + if (HTC_STOPPING(target)) { + pPacket->Status = A_ECANCELED; + } else { + pPacket->Status = A_NO_RESOURCE; + } + } + HTC_PACKET_QUEUE_ITERATE_END; + + do_send_completion(pEndpoint, pPktQueue); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_send_pkts_multiple \n")); + + return A_OK; +} + +/* HTC API - htc_send_pkt */ +A_STATUS htc_send_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) +{ + HTC_PACKET_QUEUE queue; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("+-htc_send_pkt: Enter endPointId: %d, buffer: %p, length: %d \n", + pPacket->Endpoint, pPacket->pBuffer, + pPacket->ActualLength)); + INIT_HTC_PACKET_QUEUE_AND_ADD(&queue, pPacket); + return htc_send_pkts_multiple(HTCHandle, &queue); +} + +#ifdef ATH_11AC_TXCOMPACT + +A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, cdf_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; + uint32_t data_attr = 0; + + pEndpoint = &target->EndPoint[Epid]; + + tx_resources = + hif_get_free_queue_number(target->hif_dev, pEndpoint->UL_PipeID); + + if (tx_resources < HTC_DATA_RESOURCE_THRS) { + if (pEndpoint->ul_is_polled) { + hif_send_complete_check(pEndpoint->target->hif_dev, + pEndpoint->UL_PipeID, 1); + tx_resources = + hif_get_free_queue_number(target->hif_dev, + pEndpoint->UL_PipeID); + } + if (tx_resources < HTC_DATA_MINDESC_PERPACKET) { + return A_ERROR; + } + } + + pHtcHdr = (HTC_FRAME_HDR *) cdf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + + data_attr = cdf_nbuf_data_attr_get(netbuf); + + 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 htc_tx_completion_handler, + * which can take the HTC tx lock, make the hif_send_complete_check + * call before acquiring the HTC tx lock. + * Call hif_send_complete_check directly, rather than calling + * htc_send_complete_check, and call the PollTimerStart separately + * after calling hif_send_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++; + + NBUF_UPDATE_TX_PKT_COUNT(netbuf, NBUF_TX_PKT_HTC); + DPTRACE(cdf_dp_trace(netbuf, CDF_DP_TRACE_HTC_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(netbuf)), + sizeof(cdf_nbuf_data(netbuf)))); + status = hif_send_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, ActualLength, netbuf, data_attr); + + UNLOCK_HTC_TX(target); + return status; +} +#else /*ATH_11AC_TXCOMPACT */ + +A_STATUS htc_send_data_pkt(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; + cdf_nbuf_t netbuf; + int tx_resources; + A_STATUS status = A_OK; + uint32_t data_attr = 0; + + 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 *) cdf_nbuf_get_frag_vaddr(netbuf, 0); + AR_DEBUG_ASSERT(pHtcHdr); + + 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 htc_tx_completion_handler, + * which can take the HTC tx lock, make the hif_send_complete_check + * call before acquiring the HTC tx lock. + * Call hif_send_complete_check directly, rather than calling + * htc_send_complete_check, and call the PollTimerStart separately + * after calling hif_send_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) { + htc_send_complete_poll_timer_stop(pEndpoint); + hif_send_complete_check(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 */ + cdf_atomic_inc(&pEndpoint->TxProcessCount); + if (cdf_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. + */ + cdf_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 + get_htc_send_packets_credit_based(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)) { + /* Dequeue max packets from endpoint tx queue */ + get_htc_send_packets(target, pEndpoint, &sendQueue, + HTC_MAX_TX_BUNDLE_SEND_LIMIT); + UNLOCK_HTC_TX(target); + } +#endif + else { + /* + * Now drain the endpoint TX queue for transmission as long as we have + * enough transmit resources + */ + tx_resources = + hif_get_free_queue_number(target->hif_dev, + pEndpoint->UL_PipeID); + get_htc_send_packets(target, pEndpoint, &sendQueue, tx_resources); + UNLOCK_HTC_TX(target); + } + NBUF_UPDATE_TX_PKT_COUNT(netbuf, NBUF_TX_PKT_HTC); + DPTRACE(cdf_dp_trace(netbuf, CDF_DP_TRACE_HTC_PACKET_PTR_RECORD, + (uint8_t *)(cdf_nbuf_data(netbuf)), + sizeof(cdf_nbuf_data(netbuf)))); + + /* 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) { + htc_issue_packets_bundle(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 = hif_send_head(target->hif_dev, + pEndpoint->UL_PipeID, + pEndpoint->Id, + HTC_HDR_LENGTH + pPacket->ActualLength, + netbuf, data_attr); +#if DEBUG_BUNDLE + cdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.\n", + pEndpoint->Id, + pEndpoint->TxCreditSize, + HTC_HDR_LENGTH + pPacket->ActualLength); +#endif + + if (cdf_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 */ + cdf_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. + */ + htc_send_complete_poll_timer_start(pEndpoint); + } + + return status; +} +#endif /*ATH_11AC_TXCOMPACT */ + +/* + * In the adapted HIF layer, cdf_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 *htc_lookup_tx_packet(HTC_TARGET *target, + HTC_ENDPOINT *pEndpoint, + cdf_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 (cdf_unlikely(!pPacket)) { + UNLOCK_HTC_TX(target); + return NULL; + } + if (netbuf == (cdf_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 == + (cdf_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; +} + +CDF_STATUS htc_tx_completion_handler(void *Context, + cdf_nbuf_t netbuf, unsigned int EpID, + uint32_t toeplitz_hash_result) +{ + HTC_TARGET *target = (HTC_TARGET *) Context; + HTC_ENDPOINT *pEndpoint; + HTC_PACKET *pPacket; +#ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED + HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = + { ENDPOINT_5, ENDPOINT_4, ENDPOINT_2, ENDPOINT_3 }; + int epidIdx; + A_UINT16 resourcesThresh[DATA_EP_SIZE]; /* urb resources */ + A_UINT16 resources; + A_UINT16 resourcesMax; +#endif + + pEndpoint = &target->EndPoint[EpID]; + target->TX_comp_cnt++; + + do { + pPacket = htc_lookup_tx_packet(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; + } + 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; + send_packet_completion(target, pPacketTemp); + } + HTC_PACKET_QUEUE_ITERATE_END; + free_htc_bundle_packet(target, pPacket); + return CDF_STATUS_SUCCESS; + } + /* will be giving this buffer back to upper layers */ + netbuf = NULL; + pPacket->Status = CDF_STATUS_SUCCESS; + send_packet_completion(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 */ + htc_try_send(target, pEndpoint, NULL); + } + + return CDF_STATUS_SUCCESS; +} + +/* callback when TX resources become available */ +void htc_tx_resource_avail_handler(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)); + + htc_try_send(target, pEndpoint, NULL); +} + +/* flush endpoint TX queue */ +void htc_flush_endpoint_tx(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; + send_packet_completion(target, pPacket); + } + } + UNLOCK_HTC_TX(target); +} + +/* HTC API to flush an endpoint's TX queue*/ +void htc_flush_endpoint(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; + } + + htc_flush_endpoint_tx(target, pEndpoint, Tag); +} + +/* HTC API to indicate activity to the credit distribution function */ +void htc_indicate_activity_change(HTC_HANDLE HTCHandle, + HTC_ENDPOINT_ID Endpoint, A_BOOL Active) +{ + /* TODO */ +} + +A_BOOL htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) +{ + return true; +} + +/* process credit reports and call distribution function */ +void htc_process_credit_rpt(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, + ("+htc_process_credit_rpt, 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 +#if defined(HIF_USB) + if (pEndpoint->Id >= ENDPOINT_2 && pEndpoint->Id <= ENDPOINT_5) { + HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = + { ENDPOINT_5, ENDPOINT_4, ENDPOINT_2, ENDPOINT_3 }; + int epid_idx; + + target->avail_tx_credits += rpt_credits; + + for (epid_idx = 0; epid_idx < DATA_EP_SIZE; epid_idx++) { + pEndpoint = &target->EndPoint[eid[epid_idx]]; + if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { + break; + } + + } + UNLOCK_HTC_TX(target); + htc_try_send(target, pEndpoint, NULL); + LOCK_HTC_TX(target); + } else { + pEndpoint->TxCredits += rpt_credits; + + if (pEndpoint->TxCredits + && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { + UNLOCK_HTC_TX(target); + htc_try_send(target, pEndpoint, NULL); + LOCK_HTC_TX(target); + } + } +#else + 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 + htc_try_send(target, pEndpoint, NULL); +#else + if (pEndpoint->ServiceID == HTT_DATA_MSG_SVC) { + htc_send_data_pkt(target, NULL, 0); + } else { + htc_try_send(target, pEndpoint, NULL); + } +#endif + LOCK_HTC_TX(target); + } +#endif + 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, ("-htc_process_credit_rpt \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/core/htc/htc_services.c b/core/htc/htc_services.c new file mode 100644 index 000000000000..40067f733649 --- /dev/null +++ b/core/htc/htc_services.c @@ -0,0 +1,368 @@ +/* + * 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 /* cdf_nbuf_t */ +#include "hif.h" + +/* use credit flow control over HTC */ +unsigned int htc_credit_flow = 1; +#ifndef DEBUG_CREDIT +#define DEBUG_CREDIT 0 +#endif + +A_STATUS htc_connect_service(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; + cdf_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, + ("+htc_connect_service, 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 = + htc_get_credit_allocation(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 = htc_alloc_control_tx_packet(target); + + if (NULL == pSendPacket) { + AR_DEBUG_ASSERT(false); + status = A_NO_MEMORY; + break; + } + + netbuf = + (cdf_nbuf_t) + GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); + length = + sizeof(HTC_CONNECT_SERVICE_MSG) + + pConnectReq->MetaDataLength; + + /* assemble connect service message */ + cdf_nbuf_put_tail(netbuf, length); + pConnectMsg = + (HTC_CONNECT_SERVICE_MSG *) cdf_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 = htc_send_pkt((HTC_HANDLE) target, pSendPacket); + /* we don't own it anymore */ + pSendPacket = NULL; + if (A_FAILED(status)) { + break; + } + + /* wait for response */ + status = htc_wait_recv_ctrl_message(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, + ("htc_connect_service, 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 + cdf_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 = hif_map_service_to_pipe(target->hif_dev, + pEndpoint->ServiceID, + &pEndpoint->UL_PipeID, + &pEndpoint->DL_PipeID, + &pEndpoint->ul_is_polled, + &pEndpoint->dl_is_polled); + if (A_FAILED(status)) { + break; + } + + cdf_assert(!pEndpoint->dl_is_polled); /* not currently supported */ + + if (pEndpoint->ul_is_polled) { + cdf_softirq_timer_init(target->osdev, + &pEndpoint->ul_poll_timer, + htc_send_complete_check_cleanup, + pEndpoint, + CDF_TIMER_TYPE_SW); + } + + 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, ("-htc_connect_service \n")); + + return status; +} + +void htc_set_credit_distribution(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 htc_fw_event_handler(void *context, CDF_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) +{ + hif_disable_aspm(); +} diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h new file mode 100644 index 000000000000..f3bee2ad088e --- /dev/null +++ b/core/mac/inc/ani_global.h @@ -0,0 +1,1064 @@ +/* + * 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 _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 "cdf_types.h" +#include "sir_common.h" +#include "ani_system_defs.h" +#include "sys_def.h" +#include "dph_global.h" +#include "lim_global.h" +#include "sch_global.h" +#include "sys_global.h" +#include "cfg_global.h" +#include "utils_global.h" +#include "sir_api.h" + +#include "csr_api.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "sme_ft_api.h" +#endif +#include "csr_support.h" +#include "sme_internal.h" +#include "sap_api.h" +#include "csr_internal.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oem_data_internal.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "sme_rrm_internal.h" +#include "rrm_global.h" +#endif +#include "p2p_api.h" + +#if defined WLAN_FEATURE_VOWIFI_11R +#include +#endif + +/* 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 + +/* 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) + +/** + * enum log_event_type - Type of event initiating bug report + * @WLAN_LOG_TYPE_NON_FATAL: Non fatal event + * @WLAN_LOG_TYPE_FATAL: Fatal event + * + * Enum indicating the type of event that is initiating the bug report + */ +enum log_event_type { + WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_TYPE_FATAL, +}; + +/** + * enum log_event_indicator - Module triggering bug report + * @WLAN_LOG_INDICATOR_UNUSED: Unused + * @WLAN_LOG_INDICATOR_FRAMEWORK: Framework triggers bug report + * @WLAN_LOG_INDICATOR_HOST_DRIVER: Host driver triggers bug report + * @WLAN_LOG_INDICATOR_FIRMWARE: FW initiates bug report + * + * Enum indicating the module that triggered the bug report + */ +enum log_event_indicator { + WLAN_LOG_INDICATOR_UNUSED, + WLAN_LOG_INDICATOR_FRAMEWORK, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_INDICATOR_FIRMWARE, +}; + +/** + * enum log_event_host_reason_code - Reason code for bug report + * @WLAN_LOG_REASON_CODE_UNUSED: Unused + * @WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL: Command response status from FW + * is error + * @WLAN_LOG_REASON_ROAM_FAIL: Driver initiated roam has failed + * @WLAN_LOG_REASON_THREAD_STUCK: Monitor Health of host threads and report + * fatal event if some thread is stuck + * @WLAN_LOG_REASON_DATA_STALL: Unable to send/receive data due to low resource + * scenario for a prolonged period + * @WLAN_LOG_REASON_SME_COMMAND_STUCK: SME command is stuck in SME active queue + * @WLAN_LOG_REASON_ZERO_SCAN_RESULTS: Full scan resulted in zero scan results + * @WLAN_LOG_REASON_QUEUE_FULL: Defer queue becomes full for a prolonged period + * @WLAN_LOG_REASON_POWER_COLLAPSE_FAIL: Unable to allow apps power collapse + * for a prolonged period + * @WLAN_LOG_REASON_SSR_FAIL: Unable to gracefully complete SSR + * @WLAN_LOG_REASON_DISCONNECT_FAIL: Disconnect from Supplicant is not + * successful + * @WLAN_LOG_REASON_CLEAN_UP_FAIL: Clean up of TDLS or Pre-Auth Sessions + * not successful + * @WLAN_LOG_REASON_MALLOC_FAIL: Memory allocation Fails + * @WLAN_LOG_REASON_VOS_MSG_UNDER_RUN: VOS Core runs out of message wrapper + * @WLAN_LOG_REASON_MSG_POST_FAIL: Unable to post msg + * + * This enum contains the different reason codes for bug report + */ +enum log_event_host_reason_code { + WLAN_LOG_REASON_CODE_UNUSED, + WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL, + WLAN_LOG_REASON_ROAM_FAIL, + WLAN_LOG_REASON_THREAD_STUCK, + WLAN_LOG_REASON_DATA_STALL, + WLAN_LOG_REASON_SME_COMMAND_STUCK, + WLAN_LOG_REASON_ZERO_SCAN_RESULTS, + WLAN_LOG_REASON_QUEUE_FULL, + WLAN_LOG_REASON_POWER_COLLAPSE_FAIL, + WLAN_LOG_REASON_SSR_FAIL, + WLAN_LOG_REASON_DISCONNECT_FAIL, + WLAN_LOG_REASON_CLEAN_UP_FAIL, + WLAN_LOG_REASON_MALLOC_FAIL, + WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, + WLAN_LOG_REASON_MSG_POST_FAIL, +}; + +/** + * enum userspace_log_level - Log level at userspace + * @LOG_LEVEL_NO_COLLECTION: verbose_level 0 corresponds to no collection + * @LOG_LEVEL_NORMAL_COLLECT: verbose_level 1 correspond to normal log level, + * with minimal user impact. this is the default value + * @LOG_LEVEL_ISSUE_REPRO: verbose_level 2 are enabled when user is lazily + * trying to reproduce a problem, wifi performances and power can be impacted + * but device should not otherwise be significantly impacted + * @LOG_LEVEL_ACTIVE: verbose_level 3+ are used when trying to + * actively debug a problem + * + * Various log levels defined in the userspace for logging applications + */ +enum userspace_log_level { + LOG_LEVEL_NO_COLLECTION, + LOG_LEVEL_NORMAL_COLLECT, + LOG_LEVEL_ISSUE_REPRO, + LOG_LEVEL_ACTIVE, +}; + +/** + * enum wifi_driver_log_level - Log level defined in the driver for logging + * @WLAN_LOG_LEVEL_OFF: No logging + * @WLAN_LOG_LEVEL_NORMAL: Default logging + * @WLAN_LOG_LEVEL_REPRO: Normal debug level + * @WLAN_LOG_LEVEL_ACTIVE: Active debug level + * + * Log levels defined for logging by the wifi driver + */ +enum wifi_driver_log_level { + WLAN_LOG_LEVEL_OFF, + WLAN_LOG_LEVEL_NORMAL, + WLAN_LOG_LEVEL_REPRO, + WLAN_LOG_LEVEL_ACTIVE, +}; + +/** + * enum wifi_logging_ring_id - Ring id of logging entities + * @RING_ID_WAKELOCK: Power events ring id + * @RING_ID_CONNECTIVITY: Connectivity event ring id + * @RING_ID_PER_PACKET_STATS: Per packet statistic ring id + * @RIND_ID_DRIVER_DEBUG: Driver debug messages ring id + * @RING_ID_FIRMWARE_DEBUG: Firmware debug messages ring id + * + * This enum has the ring id values of logging rings + */ +enum wifi_logging_ring_id { + RING_ID_WAKELOCK, + RING_ID_CONNECTIVITY, + RING_ID_PER_PACKET_STATS, + RIND_ID_DRIVER_DEBUG, + RING_ID_FIRMWARE_DEBUG, +}; + +/* ------------------------------------------------------------------- */ +/* Change channel generic scheme */ +typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, + tpPESession psessionEntry); + +/* / LIM global definitions */ +typedef struct sAniSirLimIbss { + void *pHdr; + void *pBeacon; +} tAniSirLimIbss; + +typedef struct sDialogueToken { + /* bytes 0-3 */ + uint16_t assocId; + uint8_t token; + uint8_t rsvd1; + /* Bytes 4-7 */ + uint16_t tid; + uint8_t rsvd2[2]; + + struct sDialogueToken *next; +} tDialogueToken, *tpDialogueToken; + +typedef struct sLimTimers { + /* TIMERS IN LIM ARE NOT SUPPOSED TO BE ZEROED OUT DURING RESET. */ + /* DURING lim_initialize DONOT ZERO THEM OUT. */ + +/* STA SPECIFIC TIMERS */ + + TX_TIMER gLimPreAuthClnupTimer; + + /* Association related timers */ + TX_TIMER gLimAssocFailureTimer; + TX_TIMER gLimReassocFailureTimer; + + /* / 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; + + 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; + /* 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 lim_initialize */ +/* **************************************************************************************** */ + +} 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 */ + uint32_t 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. + */ + uint32_t gLimUseScanModeForLearnMode; + + /** + * This is useful for modules other than LIM + * to see if system is in scan/learn mode or not + */ + uint32_t gLimSystemInScanLearnMode; + + /* Scan related globals on STA */ + uint8_t gLimReturnAfterFirstMatch; + uint8_t gLim24Band11dScanDone; + uint8_t gLim50Band11dScanDone; + uint8_t gLimReturnUniqueResults; + + /* / Place holder for current channel ID */ + /* / being scanned */ + uint32_t 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 + */ + uint16_t gDeferMsgTypeForNOA; + uint32_t *gpDefdSmeMsgForNOA; + + tLimMlmScanReq *gpLimMlmScanReq; + + + /* Used to store the list of legacy bss sta detected during scan on one channel */ + uint16_t gLimRestoreCBNumScanInterval; + uint16_t gLimRestoreCBCount; + tSirMacAddr gLimLegacyBssidList[MAX_NUM_LEGACY_BSSID_PER_CHANNEL]; + + /* abort scan is used to abort an on-going scan */ + uint8_t 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 */ + + uint8_t gLimCurrentBssUapsd; + + /* This is used for testing sta legacy bss detect feature */ + uint8_t gLimForceNoPropIE; + + /* */ + /* Store the BSS Index returned by HAL during */ + /* WMA_ADD_BSS_RSP here. */ + /* */ + + /* For now: */ + /* This will be used during WMA_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; + + /* //////////////////////////////////////// BSS RELATED END /////////////////////////////////////////// */ + + /* //////////////////////////////////////// IBSS RELATED START /////////////////////////////////////////// */ + /* This indicates whether this STA coalesced and adapter to peer's capabilities or not. */ + uint8_t gLimIbssCoalescingHappened; + + /* / Definition for storing IBSS peers BSS description */ + tLimIbssPeerNode *gLimIbssPeerList; + uint32_t gLimNumIbssPeers; + uint32_t ibss_retry_cnt; + + /* ibss info - params for which ibss to join while coalescing */ + tAniSirLimIbss ibssInfo; + + /* //////////////////////////////////////// IBSS RELATED END /////////////////////////////////////////// */ + + /* //////////////////////////////////////// STATS/COUNTER RELATED START /////////////////////////////////////////// */ + + uint16_t maxStation; + uint16_t maxBssId; + + uint32_t gLimNumBeaconsRcvd; + uint32_t gLimNumBeaconsIgnored; + + uint32_t gLimNumDeferredMsgs; + + /* / Variable to keep track of number of currently associated STAs */ + uint16_t gLimNumOfAniSTAs; /* count of ANI peers */ + uint16_t gLimAssocStaLimit; + + /* Heart-Beat interval value */ + uint32_t gLimHeartBeatCount; + tSirMacAddr gLimHeartBeatApMac[2]; + uint8_t gLimHeartBeatApMacIndex; + + /* Statistics to keep track of no. beacons rcvd in heart beat interval */ + uint16_t + gLimHeartBeatBeaconStats[MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL]; + +#ifdef WLAN_DEBUG + /* Debug counters */ + uint32_t numTot, numBbt, numProtErr, numLearn, numLearnIgnore; + uint32_t numSme, numMAC[4][16]; + + /* Debug counter to track number of Assoc Req frame drops */ + /* when received in pStaDs->mlmState other than LINK_ESTABLISED */ + uint32_t gLimNumAssocReqDropInvldState; + /* counters to track rejection of Assoc Req due to Admission Control */ + uint32_t gLimNumAssocReqDropACRejectTS; + uint32_t gLimNumAssocReqDropACRejectSta; + /* Debug counter to track number of Reassoc Req frame drops */ + /* when received in pStaDs->mlmState other than LINK_ESTABLISED */ + uint32_t gLimNumReassocReqDropInvldState; + /* Debug counter to track number of Hash Miss event that */ + /* will not cause a sending of de-auth/de-associate frame */ + uint32_t gLimNumHashMissIgnored; + + /* Debug counter to track number of Beacon frames */ + /* received in unexpected state */ + uint32_t gLimUnexpBcnCnt; + + /* Debug counter to track number of Beacon frames */ + /* received in wt-join-state that do have SSID mismatch */ + uint32_t gLimBcnSSIDMismatchCnt; + + /* Debug counter to track number of Link establishments on STA/BP */ + uint32_t gLimNumLinkEsts; + + /* Debug counter to track number of Rx cleanup */ + uint32_t gLimNumRxCleanup; + + /* Debug counter to track different parse problem */ + uint32_t gLim11bStaAssocRejectCount; + +#endif + + /* Time stamp of the last beacon received from the BSS to which STA is connected. */ + uint64_t gLastBeaconTimeStamp; + /* RX Beacon count for the current BSS to which STA is connected. */ + uint32_t gCurrentBssBeaconCnt; + uint8_t gLastBeaconDtimCount; + uint8_t gLastBeaconDtimPeriod; + + /* //////////////////////////////////////// STATS/COUNTER RELATED END /////////////////////////////////////////// */ + + /* //////////////////////////////////////// STATES RELATED START /////////////////////////////////////////// */ + /* Counts Heartbeat failures */ + uint8_t gLimHBfailureCntInLinkEstState; + uint8_t gLimProbeFailureAfterHBfailedCnt; + uint8_t 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 + */ + uint8_t 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; + uint32_t *gpLimSuspendData; + SUSPEND_RESUME_LINK_CALLBACK gpLimResumeCallback; + uint32_t *gpLimResumeData; +/* end WLAN_SUSPEND_LINK Related */ + /* 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 */ + uint16_t gResumeChannel; + ePhyChanBondState gResumePhyCbState; + + /* Change channel generic scheme */ + CHANGE_CHANNEL_CALLBACK gpchangeChannelCallback; + uint32_t *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) */ + uint32_t gLimPhyMode; + uint32_t propRateAdjustPeriod; + uint32_t scanStartTime; /* used to measure scan time */ + + uint8_t gLimMyMacAddr[6]; + uint8_t ackPolicy; + + uint8_t gLimQosEnabled:1; /* 11E */ + uint8_t gLimWmeEnabled:1; /* WME */ + uint8_t gLimWsmEnabled:1; /* WSM */ + uint8_t gLimHcfEnabled:1; + uint8_t gLim11dEnabled:1; + uint8_t gLimProbeRespDisableFlag:1; /* control over probe response */ + /* ---------------- DPH ----------------------- */ + + /* //////////////////////////////////////// STATES RELATED END /////////////////////////////////////////// */ + + /* //////////////////////////////////////// MISC RELATED START /////////////////////////////////////////// */ + + /* Deferred Queue Parameters */ + tLimDeferredMsgQParams gLimDeferredMsgQ; + + /* addts request if any - only one can be outstanding at any time */ + tSirAddtsReq gLimAddtsReq; + uint8_t gLimAddtsSent; + uint8_t gLimAddtsRspTimerCount; + + /* protection related config cache */ + tCfgProtection cfgProtection; + + uint8_t gLimProtectionControl; + /* 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. */ + uint8_t gLimProcessDefdMsgs; + + /* UAPSD flag used on AP */ + uint8_t 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. + */ + uint8_t gUapsdPerAcBitmask; + + /* 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 + */ + uint8_t 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; + cdf_mutex_t lkPeGlobalLock; + uint8_t disableLDPCWithTxbfAP; +#ifdef FEATURE_WLAN_TDLS + uint8_t gLimTDLSBufStaEnabled; + uint8_t gLimTDLSUapsdMask; + uint8_t gLimTDLSOffChannelEnabled; + uint8_t 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 */ + /* WMA_CHNL_SWITCH_REQ message to HAL */ + uint32_t channelChangeReasonCode; + + /* / MAC level Pre-authentication related globals */ + tSirMacChanNum gLimPreAuthChannelNumber; + tAniAuthType gLimPreAuthType; + tSirMacAddr gLimPreAuthPeerAddr; + uint32_t gLimNumPreAuthContexts; + tLimPreAuthTable gLimPreAuthTimerTable; + + /* Placed holder to deauth reason */ + uint16_t gLimDeauthReasonCode; + + /* Place holder for Pre-authentication node list */ + struct tLimPreAuthNode *pLimPreAuthList; + + /* Send Disassociate frame threshold parameters */ + uint16_t gLimDisassocFrameThreshold; + uint16_t 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 */ + uint8_t htCapabilityPresentInBeacon; + + /* 802.11 HT capability: Enabled or Disabled */ + uint8_t htCapability; + + uint8_t gHTGreenfield; + + uint8_t gHTShortGI40Mhz; + uint8_t gHTShortGI20Mhz; + + /* Set to 0 for 3839 octets */ + /* Set to 1 for 7935 octets */ + uint8_t gHTMaxAmsduLength; + + /* DSSS/CCK at 40 MHz: Enabled 1 or Disabled */ + uint8_t gHTDsssCckRate40MHzSupport; + + /* PSMP Support: Enabled 1 or Disabled 0 */ + uint8_t gHTPSMPSupport; + + /* L-SIG TXOP Protection used only if peer support available */ + uint8_t gHTLsigTXOPProtection; + + /* MIMO Power Save */ + tSirMacHTMIMOPowerSaveState gHTMIMOPSState; + + /* Scan In Power Save */ + uint8_t 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 */ + /* */ + uint8_t gHTAMpduDensity; + + bool gMaxAmsduSizeEnabled; + /* Maximum Tx/Rx A-MPDU factor */ + uint8_t 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 */ + /* */ + uint8_t gHTServiceIntervalGranularity; + + /* Indicates whether an AP wants to associate PSMP enabled Stations */ + uint8_t gHTControlledAccessOnly; + + /* RIFS Mode. Set if no APSD legacy devices associated */ + uint8_t gHTRifsMode; + /* OBss Mode . set when we have Non HT STA is associated or with in overlap bss */ + uint8_t gHTObssMode; + + /* Identifies the current Operating Mode */ + tSirMacHTOperatingMode gHTOperMode; + + /* Indicates if PCO is activated in the BSS */ + uint8_t gHTPCOActive; + + /* */ + /* If PCO is active, indicates which PCO phase to use */ + /* 0 - switch to 20 MHz phase */ + /* 1 - switch to 40 MHz phase */ + /* */ + uint8_t gHTPCOPhase; + + /* */ + /* Used only in beacons. For PR, this is set to 0 */ + /* 0 - Primary beacon */ + /* 1 - Secondary beacon */ + /* */ + uint8_t gHTSecondaryBeacon; + + /* */ + /* Dual CTS Protection */ + /* 0 - Use RTS/CTS */ + /* 1 - Dual CTS Protection is used */ + /* */ + uint8_t gHTDualCTSProtection; + + /* */ + /* Identifies a single STBC MCS that shall ne used for */ + /* STBC control frames and STBC beacons */ + /* */ + uint8_t gHTSTBCBasicMCS; + + uint8_t gHTNonGFDevicesPresent; + + /* ////////////////////////////// HT RELATED ////////////////////////////////////////// */ + +#ifdef FEATURE_WLAN_TDLS + uint8_t gLimAddStaTdls; + uint8_t 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. + **/ + uint8_t gSmeSessionId; + uint16_t gTransactionId; + +#ifdef FEATURE_OEM_DATA_SUPPORT + tLimMlmOemDataReq *gpLimMlmOemDataReq; + tLimMlmOemDataRsp *gpLimMlmOemDataRsp; +#endif + + tSirRemainOnChnReq *gpLimRemainOnChanReq; /* hold remain on chan request in this buf */ + cdf_mutex_t lim_frame_register_lock; + cdf_list_t gLimMgmtFrameRegistratinQueue; + uint32_t mgmtFrameSessionId; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + tpPESession pSessionEntry; + uint8_t reAssocRetryAttempt; +#endif + tLimDisassocDeauthCnfReq limDisassocDeauthCnfReq; + uint8_t deferredMsgCnt; + tSirDFSChannelList dfschannelList; + uint8_t deauthMsgCnt; + uint8_t gLimIbssStaLimit; + + /* Number of channel switch IEs sent so far */ + uint8_t gLimDfsChanSwTxCount; + uint8_t gLimDfsTargetChanNum; + uint8_t probeCounter; + uint8_t maxProbe; + CDF_STATUS(*add_bssdescr_callback) + (tpAniSirGlobal pMac, tpSirBssDescription buf, + uint32_t scan_id, uint32_t flags); + uint8_t retry_packet_cnt; + uint8_t scan_disabled; +} tAniSirLim, *tpAniSirLim; + +struct mgmt_frm_reg_info { + cdf_list_node_t node; /* MUST be first element */ + uint16_t frameType; + uint16_t matchLen; + uint16_t sessionId; + uint8_t matchData[1]; +}; + +#if defined WLAN_FEATURE_VOWIFI +typedef struct sRrmContext { + tRrmSMEContext rrmSmeContext; + tRrmPEContext rrmPEContext; +} tRrmContext, *tpRrmContext; +#endif + +/** + * enum tDriverType - Indicate the driver type to the mac, and based on this + * do appropriate initialization. + * + * @eDRIVER_TYPE_PRODUCTION: + * @eDRIVER_TYPE_MFG: + * + */ +typedef enum { + eDRIVER_TYPE_PRODUCTION = 0, + eDRIVER_TYPE_MFG = 1, +} tDriverType; + +/** ------------------------------------------------------------------------- * + + \typedef tMacOpenParameters + + \brief Parameters needed for Enumeration of all status codes returned by the higher level + interface functions. + + -------------------------------------------------------------------------- */ + +typedef struct sMacOpenParameters { + uint16_t maxStation; + uint16_t maxBssId; + uint32_t frameTransRequired; + uint8_t powersaveOffloadEnabled; + /* Powersave Parameters */ + uint8_t staMaxLIModDtim; + uint8_t staModDtim; + uint8_t staDynamicDtim; + tDriverType driverType; + uint8_t maxWoWFilters; + uint8_t 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 + */ + uint8_t olIniInfo; + bool ssdp; + /* + * DFS Phyerror Filtering offload status from ini + * 0 indicates offload disabled + * 1 indicates offload enabled + */ + uint8_t dfsPhyerrFilterOffload; +/* pass intra-bss-fwd info to txrx module */ + uint8_t apDisableIntraBssFwd; + + /* max offload peer */ + uint8_t apMaxOffloadPeers; + + /* max offload reorder buffs */ + uint8_t apMaxOffloadReorderBuffs; + +#ifdef FEATURE_WLAN_RA_FILTERING + uint16_t RArateLimitInterval; + bool IsRArateLimitEnabled; +#endif + /* is RX re-ordering offloaded to the fw */ + uint8_t reorderOffload; + + /* dfs radar pri multiplier */ + int32_t dfsRadarPriMultiplier; + + /* IPA Micro controller data path offload enable flag */ + uint8_t ucOffloadEnabled; + /* IPA Micro controller data path offload TX buffer count */ + uint32_t ucTxBufCount; + /* IPA Micro controller data path offload TX buffer size */ + uint32_t ucTxBufSize; + /* IPA Micro controller data path offload RX indication ring count */ + uint32_t ucRxIndRingCount; + /* IPA Micro controller data path offload TX partition base */ + uint32_t ucTxPartitionBase; + bool enable_rxthread; + bool ip_tcp_udp_checksum_offload; + + /* CE based classification enabled */ + bool ce_classify_enabled; + + /* Maximum number of parallel scans */ + uint8_t max_scan; + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 + /* Threshold to stop queue in percentage */ + uint32_t tx_flow_stop_queue_th; + /* Start queue offset in percentage */ + uint32_t tx_flow_start_queue_offset; +#endif +#ifdef WLAN_FEATURE_LPSS + bool is_lpass_enabled; +#endif +#ifdef WLAN_FEATURE_NAN + bool is_nan_enabled; +#endif + bool tx_chain_mask_cck; + uint16_t self_gen_frm_pwr; +} tMacOpenParameters; + +typedef struct sHalMacStartParameters { + /* parametes for the Firmware */ + tDriverType driverType; + +} tHalMacStartParameters; + +/* ------------------------------------------------------------------- */ +/* / MAC Sirius parameter structure */ +typedef struct sAniSirGlobal { + tDriverType gDriverType; + + tAniSirCfg cfg; + tAniSirLim lim; + 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 +#if defined WLAN_FEATURE_VOWIFI + tRrmContext rrm; +#endif +#ifdef WLAN_FEATURE_CONCURRENT_P2P + tp2pContext p2pContext[MAX_NO_OF_P2P_SESSIONS]; +#else + tp2pContext p2pContext; +#endif + +#ifdef FEATURE_WLAN_TDLS + bool is_tdls_power_save_prohibited; +#endif + + uint8_t isCoalesingInIBSSAllowed; + + bool imps_enabled; + + /* PNO offload */ + bool pnoOffload; + + csr_readyToSuspendCallback readyToSuspendCallback; + void *readyToSuspendContext; + uint8_t lteCoexAntShare; + uint8_t beacon_offload; + uint32_t fEnableDebugLog; + uint16_t mgmtSeqNum; + bool enable5gEBT; + /* Miracast session 0-Disabled, 1-Source, 2-sink */ + uint8_t fMiracastSessionPresent; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + csr_readyToExtWoWCallback readyToExtWoWCallback; + void *readyToExtWoWContext; +#endif + uint32_t f_sta_miracast_mcc_rest_time_val; + uint8_t f_prefer_non_dfs_on_radar; + hdd_ftm_msg_processor ftm_msg_processor_callback; + bool policy_manager_enabled; + uint32_t fine_time_meas_cap; + + /* 802.11p enable */ + bool enable_dot11p; + + uint32_t dual_mac_feature_disable; + + bool first_scan_done; +} 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) ((uint16_t) (((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/core/mac/inc/ani_system_defs.h b/core/mac/inc/ani_system_defs.h new file mode 100644 index 000000000000..578d0b833911 --- /dev/null +++ b/core/mac/inc/ani_system_defs.h @@ -0,0 +1,216 @@ +/* + * 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 ani_system_defs.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 "sir_types.h" +#include "sir_mac_prot_def.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 { + uint8_t length; + uint8_t ssId[SIR_MAC_MAX_SSID_LENGTH]; +} tAniSSID, *tpAniSSID; + +typedef struct sAniApName { + uint8_t length; + uint8_t name[SIR_MAC_MAX_SSID_LENGTH]; +} tAniApName, *tpAniApName; + +/* / RSN IE information */ +typedef struct sSirRSNie { + uint16_t length; + uint8_t rsnIEdata[SIR_MAC_MAX_IE_LENGTH + 2]; +} tSirRSNie, *tpSirRSNie; + +typedef struct sSirWAPIie { + uint16_t length; + uint8_t 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 { + uint16_t length; + uint8_t 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 { + uint16_t length; + uint8_t cckmIEdata[SIR_MAC_MAX_IE_LENGTH + 2]; +} tSirCCKMie, *tpSirCCKMie; + +#endif + +/* / Definition for Encryption Keys */ +typedef struct sSirKeys { + uint8_t keyId; + uint8_t unicast; /* 0 for multicast */ + tAniKeyDirection keyDirection; + uint8_t keyRsc[WLAN_MAX_KEY_RSC_LEN]; /* Usage is unknown */ + uint8_t paeRole; /* =1 for authenticator, */ + /* =0 for supplicant */ + uint16_t keyLength; + uint8_t key[SIR_MAC_MAX_KEY_LENGTH]; +} tSirKeys, *tpSirKeys; + +/* / Definition for Keying material */ +typedef struct sSirKeyMaterial { + uint16_t length; /* This is the length of all */ + /* data that follows */ + tAniEdType edType; /* Encryption/Decryption type */ + uint8_t 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; + uint8_t IV1; /* first byte of IV */ + uint8_t keyId; /* second byte of IV */ + uint8_t TSC[SIR_CIPHER_SEQ_CTR_SIZE]; /* sequence number */ + tSirMacAddr rxMacAddr; /* receive address */ + +} tSirMicFailureInfo, *tpSirMicFailureInfo; + +typedef struct sTrafStrmMetrics { + uint16_t UplinkPktQueueDly; + uint16_t UplinkPktQueueDlyHist[4]; + uint32_t UplinkPktTxDly; + uint16_t UplinkPktLoss; + uint16_t UplinkPktCount; + uint8_t RoamingCount; + uint16_t RoamingDly; +} cdf_packed tTrafStrmMetrics, *tpTrafStrmMetrics; + +typedef struct sBcnReportFields { + uint8_t ChanNum; + uint8_t Spare; + uint16_t MeasDuration; + uint8_t PhyType; + uint8_t RecvSigPower; + tSirMacAddr Bssid; + uint32_t ParentTsf; + uint32_t TargetTsf[2]; + uint16_t BcnInterval; + uint16_t CapabilityInfo; +} cdf_packed tBcnReportFields, *tpBcnReportFields; + +#endif /* __ANI_SYSTEM_DEFS_H */ diff --git a/core/mac/inc/mac_init_api.h b/core/mac/inc/mac_init_api.h new file mode 100644 index 000000000000..195f9e83db86 --- /dev/null +++ b/core/mac/inc/mac_init_api.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* + * + * mac_init_api.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 "ani_global.h" +#include "sir_types.h" + +tSirRetStatus mac_start(tHalHandle hHal, void *pHalMacStartParams); +tSirRetStatus mac_stop(tHalHandle hHal, tHalStopType stopType); +tSirRetStatus mac_open(tHalHandle *pHalHandle, tHddHandle hHdd, + tMacOpenParameters *pMacOpenParms); +tSirRetStatus mac_close(tHalHandle hHal); + +#endif /* __MAC_INIT_API_H */ diff --git a/core/mac/inc/mac_trace.h b/core/mac/inc/mac_trace.h new file mode 100644 index 000000000000..dbe01b1f3f24 --- /dev/null +++ b/core/mac/inc/mac_trace.h @@ -0,0 +1,72 @@ +/* + * 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 mac_trace.h + + * \brief definition for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#ifndef __MAC_TRACE_H +#define __MAC_TRACE_H + +#include "ani_global.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 mac_trace(tpAniSirGlobal pMac, uint8_t code, uint16_t session, + uint32_t data); +void mac_trace_new(tpAniSirGlobal pMac, uint8_t module, uint8_t code, + uint16_t session, uint32_t data); +uint8_t *mac_trace_get_cfg_msg_string(uint16_t cfgMsg); +uint8_t *mac_trace_get_lim_msg_string(uint16_t limMsg); +uint8_t *mac_trace_get_wma_msg_string(uint16_t wmaMsg); +uint8_t *mac_trace_get_sme_msg_string(uint16_t smeMsg); +uint8_t *mac_trace_get_info_log_string(uint16_t infoLog); +CDF_STATUS pe_acquire_global_lock(tAniSirLim *psPe); +CDF_STATUS pe_release_global_lock(tAniSirLim *psPe); + +uint8_t *mac_trace_get_neighbour_roam_state(uint16_t neighbourRoamState); +uint8_t *mac_trace_getcsr_roam_state(uint16_t csr_roamState); +uint8_t *mac_trace_getcsr_roam_sub_state(uint16_t csr_roamSubState); +uint8_t *mac_trace_get_lim_sme_state(uint16_t limState); +uint8_t *mac_trace_get_lim_mlm_state(uint16_t mlmState); +uint8_t *mac_trace_get_tl_state(uint16_t tlState); + +#endif + +#endif diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h new file mode 100644 index 000000000000..1fa77d28e8d1 --- /dev/null +++ b/core/mac/inc/qwlan_version.h @@ -0,0 +1,49 @@ +/* + * 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 automaticly updated by build scripts. + + ===========================================================================*/ + +#define QWLAN_VERSION_MAJOR 5 +#define QWLAN_VERSION_MINOR 0 +#define QWLAN_VERSION_PATCH 0 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 139 + +#define QWLAN_VERSIONSTR "5.0.0.139" + +#endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h new file mode 100644 index 000000000000..4be197e1b629 --- /dev/null +++ b/core/mac/inc/sir_api.h @@ -0,0 +1,5350 @@ +/* + * 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 sir_api.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 "sir_types.h" +#include "sir_mac_prot_def.h" +#include "ani_system_defs.h" +#include "sir_params.h" + +#define OFFSET_OF(structType, fldName) (&((structType *)0)->fldName) + +/* / Max supported channel list */ +#define SIR_MAX_SUPPORTED_CHANNEL_LIST 96 + +#define SIR_MDIE_ELEMENT_ID 54 +#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 uint8_t tSirIpv4Addr[SIR_IPV4_ADDR_LEN]; + +#define SIR_VERSION_STRING_LEN 64 +typedef uint8_t 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 + +#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 + +/* This should not be greater than MAX_NUMBER_OF_CONC_CONNECTIONS */ +#define MAX_VDEV_SUPPORTED 4 + +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 + +/** + * 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, +}; + +#define SIR_WMA_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_SMS_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_LOGP_EXCEPTION, + eSIR_SME_INVALID_PARAMETERS = 500, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, + eSIR_SME_RESOURCES_UNAVAILABLE, + /* Unable to find a BssDescription */ + eSIR_SME_SCAN_FAILED, + /* 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, + /* Recvd Deauth while join/pre-auth */ + eSIR_SME_DEAUTH_WHILE_JOIN, + eSIR_SME_STA_NOT_AUTHENTICATED, + eSIR_SME_STA_NOT_ASSOCIATED, + eSIR_SME_ALREADY_JOINED_A_BSS, + /* Given in SME_SCAN_RSP msg */ + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW, + /* that more SME_SCAN_RSP */ + /* messages are following. */ + /* SME_SCAN_RSP message with */ + /* eSIR_SME_SUCCESS status */ + /* code is the last one. */ + /* Sent in SME_JOIN/REASSOC_RSP */ + eSIR_SME_INVALID_ASSOC_RSP_RXED, + /* messages upon receiving */ + /* invalid Re/Assoc Rsp frame. */ + /* STOP BSS triggered by MIC failures: MAC software to + * disassoc all stations + */ + eSIR_SME_MIC_COUNTER_MEASURES, + /* with MIC_FAILURE reason code and perform the stop bss operation */ + /* didn't get rsp from peer within timeout interval */ + eSIR_SME_ADDTS_RSP_TIMEOUT, + /* didn't get success rsp from HAL */ + eSIR_SME_ADDTS_RSP_FAILED, + /* failed to send ch switch act frm */ + eSIR_SME_CHANNEL_SWITCH_FAIL, + eSIR_SME_INVALID_STATE, + /* SIR_HAL_SIR_HAL_INIT_SCAN_RSP returned failed status */ + eSIR_SME_HAL_SCAN_INIT_FAILED, + /* SIR_HAL_END_SCAN_RSP returned failed status */ + eSIR_SME_HAL_SCAN_END_FAILED, + /* SIR_HAL_FINISH_SCAN_RSP returned failed status */ + eSIR_SME_HAL_SCAN_FINISH_FAILED, + /* Failed to send a message to HAL */ + eSIR_SME_HAL_SEND_MESSAGE_FAIL, + /* Failed to stop the bss */ + eSIR_SME_STOP_BSS_FAILURE, + 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, + eSIR_SME_DEAUTH_STATUS, + eSIR_PNO_SCAN_SUCCESS, + eSIR_DONOT_USE_RESULT_CODE = SIR_MAX_ENUM_SIZE +} tSirResultCodes; + +/* each station added has a rate mode which specifies the sta attributes */ +typedef enum eStaRateMode { + eSTA_TAURUS = 0, + eSTA_TITAN, + eSTA_POLARIS, + 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) + +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 + */ + uint16_t llbRates[SIR_NUM_11B_RATES]; + uint16_t llaRates[SIR_NUM_11A_RATES]; + /* + * 0-76 bits used, remaining reserved + * bits 0-15 and 32 should be set. + */ + uint8_t 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. + */ + uint16_t rxHighestDataRate; + +#ifdef WLAN_FEATURE_11AC + /*Indicates the Maximum MCS that can be received for each number + of spacial streams */ + uint16_t vhtRxMCSMap; + /*Indicate the highest VHT data rate that the STA is able to receive */ + uint16_t vhtRxHighestDataRate; + /*Indicates the Maximum MCS that can be transmitted for each number + of spacial streams */ + uint16_t vhtTxMCSMap; + /*Indicate the highest VHT data rate that the STA is able to transmit */ + uint16_t vhtTxHighestDataRate; +#endif +} tSirSupportedRates, *tpSirSupportedRates; + +typedef enum eSirRFBand { + SIR_BAND_UNKNOWN, + SIR_BAND_2_4_GHZ, + SIR_BAND_5_GHZ, +} tSirRFBand; + +typedef struct sSirRemainOnChnReq { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; + tSirMacAddr selfMacAddr; + uint8_t chnNum; + uint8_t phyMode; + uint32_t duration; + uint8_t isProbeRequestAllowed; + uint32_t scan_id; + uint8_t probeRspIe[1]; +} tSirRemainOnChnReq, *tpSirRemainOnChnReq; + +/** + * struct sir_roc_rsp - Structure to store the remain on channel response + * @message_type: Message Type + * @length: Message Length + * @session_id: SME session Id + * @scan_id : scan identifier + * @status: result status + */ +struct sir_roc_rsp { + uint16_t message_type; + uint16_t length; + uint8_t session_id; + uint32_t scan_id; + tSirResultCodes status; +}; + +typedef struct sSirRegisterMgmtFrame { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; + bool registerFrame; + uint16_t frameType; + uint16_t matchLen; + uint8_t matchData[1]; +} tSirRegisterMgmtFrame, *tpSirRegisterMgmtFrame; + +/* / Generic type for sending a response message */ +/* / with result code to host software */ +typedef struct sSirSmeRsp { + uint16_t messageType; /* eWNI_SME_*_RSP */ + uint16_t length; + uint8_t sessionId; /* To support BT-AMP */ + uint16_t transactionId; /* To support BT-AMP */ + tSirResultCodes statusCode; +} tSirSmeRsp, *tpSirSmeRsp; + +/* / Definition for indicating all modules ready on STA */ +typedef struct sSirSmeReadyReq { + uint16_t messageType; /* eWNI_SME_SYS_READY_IND */ + uint16_t length; + uint16_t transactionId; + void *add_bssdescr_cb; +} tSirSmeReadyReq, *tpSirSmeReadyReq; + +/** + * struct sir_hw_mode - Format of set HW mode + * @hw_mode_index: Index of HW mode to be set + * @set_hw_mode_cb: HDD set HW mode callback + */ +struct sir_hw_mode { + uint32_t hw_mode_index; + void *set_hw_mode_cb; +}; + +/** + * struct s_sir_set_hw_mode - Set HW mode request + * @messageType: Message type + * @length: Length of the message + * @set_hw: Params containing the HW mode index and callback + */ +struct s_sir_set_hw_mode { + uint16_t messageType; + uint16_t length; + struct sir_hw_mode set_hw; +}; + +/** + * struct sir_dual_mac_config - Dual MAC configuration + * @scan_config: Scan configuration + * @fw_mode_config: FW mode configuration + * @set_dual_mac_cb: Callback function to be executed on response to the command + */ +struct sir_dual_mac_config { + uint32_t scan_config; + uint32_t fw_mode_config; + void *set_dual_mac_cb; +}; + +/** + * struct sir_set_dual_mac_cfg - Set Dual mac config request + * @message_type: Message type + * @length: Length of the message + * @set_dual_mac: Params containing the dual mac config and callback + */ +struct sir_set_dual_mac_cfg { + uint16_t message_type; + uint16_t length; + struct sir_dual_mac_config set_dual_mac; +}; + +/* / 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 { + uint8_t minTxPower; + uint8_t maxTxPower; +} tSirMacPowerCapInfo, *tpSirMacPowerCapInfo; + +/* / Supported Channel info used in 11H */ +typedef struct sSirSupChnl { + uint8_t numChnl; + uint8_t 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; + uint16_t aid; +} tSirNewIbssPeerInfo, *tpSirNewIbssPeerInfo; + +/* HT configuration values */ +typedef struct sSirHtConfig { + /* Enable/Disable receiving LDPC coded packets */ + uint32_t ht_rx_ldpc:1; + /* Enable/Disable TX STBC */ + uint32_t ht_tx_stbc:1; + /* Enable/Disable RX STBC */ + uint32_t ht_rx_stbc:2; + /* Enable/Disable SGI */ + uint32_t ht_sgi:1; + uint32_t unused:27; +} cdf_packed tSirHTConfig, *tpSirHTConfig; + +typedef struct sSirAddIeParams { + uint16_t probeRespDataLen; + uint8_t *probeRespData_buff; + uint16_t assocRespDataLen; + uint8_t *assocRespData_buff; + uint16_t probeRespBCNDataLen; + uint8_t *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 { + uint16_t messageType; /* eWNI_SME_START_BSS_REQ */ + uint16_t length; + uint8_t sessionId; /* Added for BT-AMP Support */ + uint16_t transactionId; /* Added for BT-AMP Support */ + tSirMacAddr bssId; /* Added for BT-AMP Support */ + tSirMacAddr selfMacAddr; /* Added for BT-AMP Support */ + uint16_t beaconInterval; /* Added for BT-AMP Support */ + uint8_t dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + tSirBssType bssType; + tSirMacSSid ssId; + uint8_t channelId; + ePhyChanBondState cbMode; + uint8_t vht_channel_width; + uint8_t center_freq_seg0; + uint8_t center_freq_seg1; + uint8_t sec_ch_offset; + + uint8_t privacy; + uint8_t apUapsdEnable; + uint8_t ssidHidden; + bool fwdWPSPBCProbeReq; + bool protEnabled; + bool obssProtEnabled; + uint16_t ht_capab; + tAniAuthType authType; + uint32_t dtimPeriod; + uint8_t wps_state; + uint8_t isCoalesingInIBSSAllowed; /* Coalesing on/off knob */ + tCDF_CON_MODE bssPersona; + + uint8_t 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 + bool pmfCapable; + bool pmfRequired; +#endif + + tSirAddIeParams addIeParams; + + bool 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. */ + uint16_t length; + tSirMacAddr bssId; + v_TIME_t scanSysTimeMsec; + uint32_t timeStamp[2]; + uint16_t beaconInterval; + uint16_t capabilityInfo; + tSirNwType nwType; /* Indicates 11a/b/g */ + uint8_t reserved_padding0; + int8_t rssi; + int8_t sinr; + /* channelId what peer sent in beacon/probersp. */ + uint8_t channelId; + /* channelId on which we are parked at. */ + /* used only in scan case. */ + uint8_t channelIdSelf; + uint8_t sSirBssDescriptionRsvd[3]; + /* base on a tick count. It is a time stamp, not a relative time. */ + uint32_t nReceivedTime; +#if defined WLAN_FEATURE_VOWIFI + uint32_t parentTSF; + uint32_t startTSF[2]; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + uint8_t mdiePresent; + /* MDIE for 11r, picked from the beacons */ + uint8_t mdie[SIR_MDIE_SIZE]; +#endif +#ifdef FEATURE_WLAN_ESE + uint16_t QBSSLoad_present; + uint16_t QBSSLoad_avail; + /* To achieve 8-byte alignment with ESE enabled */ + uint32_t reservedPadding5; +#endif + /* Please keep the structure 4 bytes aligned above the ieFields */ + + /* whether it is from a probe rsp */ + uint8_t fProbeRsp; + uint8_t reservedPadding1; + uint8_t reservedPadding2; + uint8_t reservedPadding3; + uint32_t WscIeLen; + uint8_t WscIeProbeRsp[WSCIE_PROBE_RSP_LEN]; + uint8_t reservedPadding4; + uint32_t tsf_delta; + + uint32_t ieFields[1]; +} tSirBssDescription, *tpSirBssDescription; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef struct sSirSmeHTProfile { + uint8_t dot11mode; + uint8_t htCapability; + uint8_t htSupportedChannelWidthSet; + uint8_t htRecommendedTxWidthSet; + ePhyChanBondState htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + uint8_t vhtCapability; + uint8_t vhtTxChannelWidthSet; + uint8_t apCenterChan; + uint8_t apChanWidth; +#endif +} tSirSmeHTProfile; +#endif +/* / Definition for response message to previously */ +/* / issued start BSS request */ +/* / MAC ---> */ +typedef struct sSirSmeStartBssRsp { + uint16_t messageType; /* eWNI_SME_START_BSS_RSP */ + uint16_t length; + uint8_t sessionId; + uint16_t transactionId; /* transaction ID for cmd */ + tSirResultCodes statusCode; + tSirBssType bssType; /* Add new type for WDS mode */ + uint16_t beaconInterval; /* Beacon Interval for both type */ + uint32_t staId; /* Staion ID for Self */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile HTProfile; +#endif + tSirBssDescription bssDescription; /* Peer BSS description */ +} tSirSmeStartBssRsp, *tpSirSmeStartBssRsp; + +typedef struct sSirChannelList { + uint8_t numChannels; + uint8_t channelNumber[SIR_ESE_MAX_MEAS_IE_REQS]; +} tSirChannelList, *tpSirChannelList; + +typedef struct sSirDFSChannelList { + uint32_t timeStamp[SIR_MAX_24G_5G_CHANNEL_RANGE]; + +} tSirDFSChannelList, *tpSirDFSChannelList; + +#ifdef FEATURE_WLAN_ESE +typedef struct sTspecInfo { + uint8_t valid; + tSirMacTspecIE tspec; +} tTspecInfo; + +#define SIR_ESE_MAX_TSPEC_IES 4 +typedef struct sESETspecTspecInfo { + uint8_t numTspecs; + tTspecInfo tspec[SIR_ESE_MAX_TSPEC_IES]; +} tESETspecInfo; +#endif + +/* / Two Background Scan mode */ +typedef enum eSirBackgroundScanMode { + 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 { + uint16_t messageType; /* eWNI_SME_SCAN_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + tSirMacAddr selfMacAddr; /* Added For BT-AMP Support */ + tSirBssType bssType; + uint8_t dot11mode; + tSirScanType scanType; + uint32_t scan_id; + /** + * minChannelTime. Not used if scanType is passive. + * 0x0 - Dont Use min channel timer. Only max channel timeout will used. + * 11k measurements set this to 0 to user only single duration for scan. + * - Timeout value used for min channel timeout. + */ + uint32_t minChannelTime; + /** + * maxChannelTime. + * 0x0 - Invalid. In case of active scan. + * In case of passive scan, MAX( maxChannelTime, + * WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME) is used. + */ + uint32_t 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. + */ + /* in units of milliseconds, ignored when not connected */ + uint32_t restTime; + uint8_t 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. + */ + uint8_t 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. + */ + uint8_t returnFreshResults; + + /* backgroundScanMode can take following values: + * 0x0 - agressive scan + * 0x1 - normal scan where HAL will check for link traffic + * prior to proceeding with the scan + */ + tSirBackgroundScanMode backgroundScanMode; + + uint8_t hiddenSsid; + + /* Number of SSIDs to scan */ + uint8_t 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 + */ + + bool p2pSearch; + uint16_t uIEFieldLen; + uint16_t 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 { + uint16_t type; + uint16_t msgLen; + uint8_t sessionId; + uint32_t scan_id; +} tSirSmeScanAbortReq, *tpSirSmeScanAbortReq; + +typedef struct sSirSmeScanChanReq { + uint16_t type; + uint16_t msgLen; + uint8_t sessionId; + uint16_t 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 { + uint16_t messageType; /* eWNI_SME_OEM_DATA_REQ */ + uint16_t messageLen; + tSirMacAddr selfMacAddr; + uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; +} tSirOemDataReq, *tpSirOemDataReq; + +typedef struct sSirOemDataRsp { + uint16_t messageType; + uint16_t length; + uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; +} tSirOemDataRsp, *tpSirOemDataRsp; + +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +/* / Definition for response message to previously issued scan request */ +typedef struct sSirSmeScanRsp { + uint16_t messageType; /* eWNI_SME_SCAN_RSP */ + uint16_t length; + uint8_t sessionId; + tSirResultCodes statusCode; + uint16_t transcationId; + uint32_t scan_id; +} tSirSmeScanRsp, *tpSirSmeScanRsp; + +/* / 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 { + uint16_t messageType; /* eWNI_SME_JOIN_REQ */ + uint16_t length; + uint8_t sessionId; + uint16_t transactionId; + tSirMacSSid ssId; + tSirMacAddr selfMacAddr; /* self Mac address */ + tSirBssType bsstype; /* add new type for BT-AMP STA and AP Modules */ + uint8_t dot11mode; /* to support BT-AMP */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + tCDF_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 + */ + uint8_t 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 + /* CCMK IE to be included as handler for join and reassoc is */ + tSirCCKMie cckmIE; + /* 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 + + uint8_t txLdpcIniFeatureEnabled; + tSirHTConfig htConfig; +#ifdef WLAN_FEATURE_11AC + uint8_t txBFIniFeatureEnabled; + uint8_t txBFCsnValue; + uint8_t txMuBformee; + uint8_t enableVhtpAid; + uint8_t enableVhtGid; +#endif + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmps; + + uint8_t isAmsduSupportInAMPDU; + tAniBool isWMEenabled; + tAniBool isQosEnabled; + tAniBool isOSENConnection; + tAniBool spectrumMgtIndicator; + tSirMacPowerCapInfo powerCap; + tSirSupChnl supportedChannels; + tSirBssDescription bssDescription; + +} tSirSmeJoinReq, *tpSirSmeJoinReq; + +/* / Definition for reponse message to previously issued join request */ +/* / MAC ---> */ +typedef struct sSirSmeJoinRsp { + uint16_t messageType; /* eWNI_SME_JOIN_RSP */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirResultCodes statusCode; + tAniAuthType authType; + uint32_t vht_channel_width; + /* It holds reasonCode when join fails due to deauth/disassoc frame. + * Otherwise it holds status code. + */ + uint16_t protStatusCode; + uint16_t aid; + uint32_t beaconLength; + uint32_t assocReqLength; + uint32_t assocRspLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + uint32_t parsedRicRspLen; +#endif +#ifdef FEATURE_WLAN_ESE + uint32_t tspecIeLen; +#endif + uint32_t 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 + */ + uint8_t ucastSig; + + /*Broadcast DPU signature */ + uint8_t bcastSig; + + /*Timing measurement capability */ + uint8_t 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 +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile HTProfile; +#endif + uint8_t frames[1]; +} tSirSmeJoinRsp, *tpSirSmeJoinRsp; + +/* / probereq from peer, when wsc is enabled */ +typedef struct sSirSmeProbereq { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; + tSirMacAddr peerMacAddr; + uint16_t devicePasswdId; +} tSirSmeProbeReq, *tpSirSmeProbeReq; + +typedef struct sSirSmeChanInfo { + uint8_t chan_id; + uint32_t mhz; + uint32_t band_center_freq1; + uint32_t band_center_freq2; + uint32_t info; + uint32_t reg_info_1; + uint32_t reg_info_2; +} tSirSmeChanInfo, *tpSirSmeChanInfo; +/* / Definition for Association indication from peer */ +/* / MAC ---> */ +typedef struct sSirSmeAssocInd { + uint16_t messageType; /* eWNI_SME_ASSOC_IND */ + uint16_t length; + uint8_t sessionId; + tSirMacAddr peerMacAddr; + uint16_t aid; + tSirMacAddr bssId; /* Self BSSID */ + uint16_t staId; /* Station ID for peer */ + uint8_t uniSig; /* DPU signature for unicast packets */ + uint8_t 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 */ + /* Additional IE received from peer, which possibly include + * WSC IE and/or P2P IE + */ + tSirAddie addIE; + + /* 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 */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; + + /* Timing measurement capability */ + uint8_t timingMeasCap; + tSirSmeChanInfo chan_info; +} tSirSmeAssocInd, *tpSirSmeAssocInd; + +/* / Definition for Association confirm */ +/* / ---> MAC */ +typedef struct sSirSmeAssocCnf { + uint16_t messageType; /* eWNI_SME_ASSOC_CNF */ + uint16_t length; + tSirResultCodes statusCode; + tSirMacAddr bssId; /* Self BSSID */ + tSirMacAddr peerMacAddr; + uint16_t aid; + tSirMacAddr alternateBssId; + uint8_t alternateChannelId; +} tSirSmeAssocCnf, *tpSirSmeAssocCnf; + +/* / 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, +} tSirSmeStatusChangeCode; + +typedef struct sSirSmeNewBssInfo { + tSirMacAddr bssId; + uint8_t channelNumber; + uint8_t reserved; + tSirMacSSid ssId; +} tSirSmeNewBssInfo, *tpSirSmeNewBssInfo; + +typedef struct sSirSmeApNewCaps { + uint16_t capabilityInfo; + tSirMacAddr bssId; + uint8_t channelId; + uint8_t 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. + */ + +/* / Definition for Wireless medium status change notification */ +typedef struct sSirSmeWmStatusChangeNtf { + uint16_t messageType; /* eWNI_SME_WM_STATUS_CHANGE_NTF */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + tSirSmeStatusChangeCode statusChangeCode; + tSirMacAddr bssId; /* Self BSSID */ + union { + uint16_t deAuthReasonCode; /* eSIR_SME_DEAUTH_FROM_PEER */ + /* eSIR_SME_DISASSOC_FROM_PEER */ + uint16_t disassocReasonCode; + /* none for eSIR_SME_LOST_LINK_WITH_PEER */ + uint8_t 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 */ + /* eSIR_SME_IBSS_NEW_PEER */ + tSirNewIbssPeerInfo newIbssPeerInfo; + tSirSmeApNewCaps apNewCaps; /* eSIR_SME_AP_CAPS_CHANGED */ + } statusChangeInfo; +} tSirSmeWmStatusChangeNtf, *tpSirSmeWmStatusChangeNtf; + +/* Definition for Disassociation request */ +typedef struct sSirSmeDisassocReq { + uint16_t messageType; /* eWNI_SME_DISASSOC_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; /* Peer BSSID */ + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + /* 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 */ + uint8_t doNotSendOverTheAir; +} cdf_packed tSirSmeDisassocReq, *tpSirSmeDisassocReq; + +/* / Definition for Tkip countermeasures request */ +typedef struct sSirSmeTkipCntrMeasReq { + uint16_t messageType; /* eWNI_SME_DISASSOC_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; /* Peer BSSID */ + bool bEnable; /* Start/stop countermeasures */ +} cdf_packed tSirSmeTkipCntrMeasReq, *tpSirSmeTkipCntrMeasReq; + +typedef struct sAni64BitCounters { + uint32_t Hi; + uint32_t Lo; +} tAni64BitCounters, *tpAni64BitCounters; + +typedef struct sAniSecurityStat { + tAni64BitCounters txBlks; + tAni64BitCounters rxBlks; + tAni64BitCounters formatErrorCnt; + tAni64BitCounters decryptErr; + tAni64BitCounters protExclCnt; + tAni64BitCounters unDecryptableCnt; + tAni64BitCounters decryptOkCnt; + +} tAniSecurityStat, *tpAniSecurityStat; + +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. + */ + uint32_t sentAesBlksUcastHi; + uint32_t sentAesBlksUcastLo; + uint32_t recvAesBlksUcastHi; + uint32_t recvAesBlksUcastLo; + uint32_t aesFormatErrorUcastCnts; + uint32_t aesReplaysUcast; + uint32_t aesDecryptErrUcast; + uint32_t singleRetryPkts; + uint32_t failedTxPkts; + uint32_t ackTimeouts; + uint32_t multiRetryPkts; + uint32_t fragTxCntsHi; + uint32_t fragTxCntsLo; + uint32_t transmittedPktsHi; + uint32_t transmittedPktsLo; + uint32_t phyStatHi; /* These are used to fill in the phystats. */ + uint32_t phyStatLo; /* This is only for private use. */ + + uint32_t uplinkRssi; + uint32_t uplinkSinr; + uint32_t uplinkRate; + uint32_t downlinkRssi; + uint32_t downlinkSinr; + uint32_t downlinkRate; + uint32_t nRcvBytes; + uint32_t 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; + + uint32_t currentTxRate; + uint32_t currentRxRate; /* Rate in 100Kbps */ + + uint32_t maxTxRate; + uint32_t maxRxRate; + + int8_t rssi[SIR_MAX_RX_CHAINS]; + + tAniSecStats securityStats; + + uint8_t currentRxRateIdx; /* This the softmac rate Index. */ + uint8_t currentTxRateIdx; + +} tAniStaStatStruct, *tpAniStaStatStruct; + +typedef enum sPacketType { + ePACKET_TYPE_UNKNOWN, + ePACKET_TYPE_11A, + ePACKET_TYPE_11G, + ePACKET_TYPE_11B, + ePACKET_TYPE_11N +} tPacketType, *tpPacketType; + +/* / Definition for Disassociation response */ +typedef struct sSirSmeDisassocRsp { + uint16_t messageType; /* eWNI_SME_DISASSOC_RSP */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; + tAniStaStatStruct perStaStats; /* STA stats */ + uint16_t staId; +} cdf_packed tSirSmeDisassocRsp, *tpSirSmeDisassocRsp; + +/* / Definition for Disassociation indication from peer */ +typedef struct sSirSmeDisassocInd { + uint16_t messageType; /* eWNI_SME_DISASSOC_IND */ + uint16_t length; + uint8_t sessionId; /* Session Identifier */ + uint16_t transactionId; /* Transaction Identifier with PE */ + tSirResultCodes statusCode; + tSirMacAddr bssId; + tSirMacAddr peerMacAddr; + tAniStaStatStruct perStaStats; /* STA stats */ + uint16_t staId; + uint32_t reasonCode; +} tSirSmeDisassocInd, *tpSirSmeDisassocInd; + +/* / Definition for Disassociation confirm */ +/* / MAC ---> */ +typedef struct sSirSmeDisassocCnf { + uint16_t messageType; /* eWNI_SME_DISASSOC_CNF */ + uint16_t length; + tSirResultCodes statusCode; + tSirMacAddr bssId; + tSirMacAddr peerMacAddr; +} tSirSmeDisassocCnf, *tpSirSmeDisassocCnf, + tSirSmeDeauthCnf, *tpSirSmeDeauthCnf; + +/* / Definition for Deauthetication request */ +typedef struct sSirSmeDeauthReq { + uint16_t messageType; /* eWNI_SME_DEAUTH_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; /* AP BSSID */ + tSirMacAddr peerMacAddr; + uint16_t reasonCode; +} tSirSmeDeauthReq, *tpSirSmeDeauthReq; + +/* / Definition for Deauthetication response */ +typedef struct sSirSmeDeauthRsp { + uint16_t messageType; /* eWNI_SME_DEAUTH_RSP */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirSmeDeauthRsp, *tpSirSmeDeauthRsp; + +/* / Definition for Deauthetication indication from peer */ +typedef struct sSirSmeDeauthInd { + uint16_t messageType; /* eWNI_SME_DEAUTH_IND */ + uint16_t length; + uint8_t sessionId; /* Added for BT-AMP */ + uint16_t transactionId; /* Added for BT-AMP */ + tSirResultCodes statusCode; + tSirMacAddr bssId; /* AP BSSID */ + tSirMacAddr peerMacAddr; + + uint16_t staId; + uint32_t reasonCode; +} tSirSmeDeauthInd, *tpSirSmeDeauthInd; + +/* / Definition for stop BSS request message */ +typedef struct sSirSmeStopBssReq { + uint16_t messageType; /* eWNI_SME_STOP_BSS_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* tranSaction ID for cmd */ + tSirResultCodes reasonCode; + tSirMacAddr bssId; /* Self BSSID */ +} tSirSmeStopBssReq, *tpSirSmeStopBssReq; + +/* / Definition for stop BSS response message */ +typedef struct sSirSmeStopBssRsp { + uint16_t messageType; /* eWNI_SME_STOP_BSS_RSP */ + uint16_t length; + tSirResultCodes statusCode; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ +} tSirSmeStopBssRsp, *tpSirSmeStopBssRsp; + +/* / Definition for Channel Switch indication for station */ +/* / MAC ---> */ +typedef struct sSirSmeSwitchChannelInd { + uint16_t messageType; /* eWNI_SME_SWITCH_CHL_IND */ + uint16_t length; + uint8_t sessionId; + uint16_t newChannelId; + tSirMacAddr bssId; /* BSSID */ +} tSirSmeSwitchChannelInd, *tpSirSmeSwitchChannelInd; + +/* / Definition for Neighbor BSS indication */ +/* / MAC ---> */ +/* / MAC reports this each time a new I/BSS is detected */ +typedef struct sSirSmeNeighborBssInd { + uint16_t messageType; /* eWNI_SME_NEIGHBOR_BSS_IND */ + uint16_t length; + uint8_t sessionId; + tSirBssDescription bssDescription[1]; +} tSirSmeNeighborBssInd, *tpSirSmeNeighborBssInd; + +/* / Definition for MIC failure indication */ +/* / MAC ---> */ +/* / MAC reports this each time a MIC failure occures on Rx TKIP packet */ +typedef struct sSirSmeMicFailureInd { + uint16_t messageType; /* eWNI_SME_MIC_FAILURE_IND */ + uint16_t length; + uint8_t sessionId; + tSirMacAddr bssId; /* BSSID */ + tSirMicFailureInfo info; +} tSirSmeMicFailureInd, *tpSirSmeMicFailureInd; + +typedef struct sSirSmeMissedBeaconInd { + uint16_t messageType; /* eWNI_SME_MISSED_BEACON_IND */ + uint16_t length; + uint8_t bssIdx; +} tSirSmeMissedBeaconInd, *tpSirSmeMissedBeaconInd; + +/* / Definition for Set Context request */ +/* / ---> MAC */ +typedef struct sSirSmeSetContextReq { + uint16_t messageType; /* eWNI_SME_SET_CONTEXT_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr peerMacAddr; + tSirMacAddr bssId; /* BSSID */ + tSirKeyMaterial keyMaterial; +} tSirSmeSetContextReq, *tpSirSmeSetContextReq; + +/* / Definition for Set Context response */ +/* / MAC ---> */ +typedef struct sSirSmeSetContextRsp { + uint16_t messageType; /* eWNI_SME_SET_CONTEXT_RSP */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirResultCodes statusCode; + tSirMacAddr peerMacAddr; +} tSirSmeSetContextRsp, *tpSirSmeSetContextRsp; + +/* / 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 stats of the radio interface */ + eANI_CLEAR_TX_STATS, /* Clears TX stats 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 param 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 */ + uint32_t tx1Mbps; + uint32_t tx2Mbps; + uint32_t tx5_5Mbps; + uint32_t tx6Mbps; + uint32_t tx9Mbps; + uint32_t tx11Mbps; + uint32_t tx12Mbps; + uint32_t tx18Mbps; + uint32_t tx24Mbps; + uint32_t tx36Mbps; + uint32_t tx48Mbps; + uint32_t tx54Mbps; + uint32_t tx72Mbps; + uint32_t tx96Mbps; + uint32_t tx108Mbps; + + /* tx path radio counts */ + uint32_t txFragHi; + uint32_t txFragLo; + uint32_t txFrameHi; + uint32_t txFrameLo; + uint32_t txMulticastFrameHi; + uint32_t txMulticastFrameLo; + uint32_t txFailedHi; + uint32_t txFailedLo; + uint32_t multipleRetryHi; + uint32_t multipleRetryLo; + uint32_t singleRetryHi; + uint32_t singleRetryLo; + uint32_t ackFailureHi; + uint32_t ackFailureLo; + uint32_t xmitBeacons; +} tAniTxCtrs, *tpAniTxCtrs; + +typedef struct sAniRxCtrs { + /* receive frame rate counters */ + uint32_t rx1Mbps; + uint32_t rx2Mbps; + uint32_t rx5_5Mbps; + uint32_t rx6Mbps; + uint32_t rx9Mbps; + uint32_t rx11Mbps; + uint32_t rx12Mbps; + uint32_t rx18Mbps; + uint32_t rx24Mbps; + uint32_t rx36Mbps; + uint32_t rx48Mbps; + uint32_t rx54Mbps; + uint32_t rx72Mbps; + uint32_t rx96Mbps; + uint32_t rx108Mbps; + + /* receive size counters; 'Lte' = Less than or equal to */ + uint32_t rxLte64; + uint32_t rxLte128Gt64; + uint32_t rxLte256Gt128; + uint32_t rxLte512Gt256; + uint32_t rxLte1kGt512; + uint32_t rxLte1518Gt1k; + uint32_t rxLte2kGt1518; + uint32_t rxLte4kGt2k; + + /* rx radio stats */ + uint32_t rxFrag; + uint32_t rxFrame; + uint32_t fcsError; + uint32_t rxMulticast; + uint32_t duplicate; + uint32_t rtsSuccess; + uint32_t rtsFailed; + uint32_t wepUndecryptables; + uint32_t drops; + uint32_t aesFormatErrorUcastCnts; + uint32_t aesReplaysUcast; + uint32_t aesDecryptErrUcast; +} tAniRxCtrs, *tpAniRxCtrs; + +/* 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 */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; + tSirMacAddr bssId; /* BSSID */ + /* only used for clear stats and per sta stats clear */ + tAniStatSubTypes stat; /* Clears the stats of the described types. */ + uint32_t staId; /* Per STA stats request must contain valid */ + /* values */ + tSirMacAddr macAddr; +} tAniGetStatsReq, *tpAniGetStatsReq; + +/* *************************************************************** */ + +/*******************PE Statistics*************************/ + +/* + * 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 */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint32_t staId; /* Per STA stats request must contain valid */ + /* categories of stats requested. look at ePEStatsMask */ + uint32_t statsMask; + uint8_t 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 */ + uint16_t msgType; /* message type is same as the request type */ + /* length of the entire request, includes the pStatsBuf length too */ + uint16_t msgLen; + uint8_t sessionId; + uint32_t rc; /* success/failure */ + uint32_t staId; /* Per STA stats request must contain valid */ + /* categories of stats requested. look at ePEStatsMask */ + uint32_t statsMask; + /* 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 */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t sessionId; + uint8_t staId; + int8_t lastRSSI; /* in case of error, return last RSSI */ + void *rssiCallback; + void *pDevContext; /* device context */ + void *p_cds_context; /* cds context */ + +} tAniGetRssiReq, *tpAniGetRssiReq; + +typedef struct sAniGetSnrReq { + /* Common for all types are requests */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t sessionId; + uint8_t staId; + void *snrCallback; + void *pDevContext; /* device context */ + int8_t snr; +} tAniGetSnrReq, *tpAniGetSnrReq; + +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct sSirTsmIE { + uint8_t tsid; + uint8_t state; + uint16_t msmt_interval; +} tSirTsmIE, *tpSirTsmIE; +typedef struct sSirSmeTsmIEInd { + tSirTsmIE tsmIe; + uint8_t sessionId; +} tSirSmeTsmIEInd, *tpSirSmeTsmIEInd; +typedef struct sAniTrafStrmMetrics { + uint16_t UplinkPktQueueDly; + uint16_t UplinkPktQueueDlyHist[4]; + uint32_t UplinkPktTxDly; + uint16_t UplinkPktLoss; + uint16_t UplinkPktCount; + uint8_t RoamingCount; + uint16_t RoamingDly; +} tAniTrafStrmMetrics, *tpAniTrafStrmMetrics; +typedef struct sAniGetTsmStatsReq { + /* Common for all types are requests */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t staId; + uint8_t tid; /* traffic id */ + tSirMacAddr bssId; + void *tsmStatsCallback; + void *pDevContext; /* device context */ + void *p_cds_context; /* cds context */ +} tAniGetTsmStatsReq, *tpAniGetTsmStatsReq; +typedef struct sAniGetTsmStatsRsp { + /* Common for all types are responses */ + uint16_t msgType; /* + * message type is same as + * the request type + */ + uint16_t msgLen; /* + * length of the entire request, + * includes the pStatsBuf length too + */ + uint8_t sessionId; + uint32_t rc; /* success/failure */ + uint32_t staId; /* + * Per STA stats request must + * contain valid + */ + tAniTrafStrmMetrics tsmMetrics; + void *tsmStatsReq; /* tsm stats request backup */ +} tAniGetTsmStatsRsp, *tpAniGetTsmStatsRsp; + +typedef struct sSirEseBcnReportBssInfo { + tBcnReportFields bcnReportFields; + uint8_t ieLen; + uint8_t *pBuf; +} tSirEseBcnReportBssInfo, *tpSirEseBcnReportBssInfo; + +typedef struct sSirEseBcnReportRsp { + uint16_t measurementToken; + uint8_t flag; /* Flag to report measurement done and more data */ + uint8_t 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 */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t 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 *p_cds_context; /* cds context */ + +} tAniChangeCountryCodeReq, *tpAniChangeCountryCodeReq; + +/** + * struct ani_scan_req - Scan request + * @msg_type: Message type + * @msg_len: Message Length + * @session_id: SME session Id + * @scan_param: scan request parameter + * @callback: call back function for scan result + * @ctx: Global context + * + * Scan request message structure + */ +struct ani_scan_req { + /* message type is same as the request type */ + uint16_t msg_type; + /* length of the entire request */ + uint16_t msg_len; + uint16_t session_id; + void *scan_param; + void *callback; + void *ctx; +}; + +/** + * struct ani_roc_req - Remain on channel request + * @msg_type: Message type + * @msg_len: Message Length + * @session_id: SME session Id + * @channel: channel number + * @callback: call back function for scan result + * @duration: Roc duration + * @is_p2pprobe_allowed : flag for p2p probe request + * @ctx: Global context + * @scan_id: Scan Identifier + * + * Remain on channel request message structure + */ +struct ani_roc_req { + /* message type is same as the request type */ + uint16_t msg_type; + /* length of the entire request */ + uint16_t msg_len; + uint16_t session_id; + uint8_t channel; + uint32_t duration; + uint8_t is_p2pprobe_allowed; + void *callback; + void *ctx; + uint32_t scan_id; +}; + +/* generic country code change request MSG structure */ +typedef struct sAniGenericChangeCountryCodeReq { + /* Common for all types are requests */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; /* 3 char country code */ + uint16_t domain_index; +} tAniGenericChangeCountryCodeReq, *tpAniGenericChangeCountryCodeReq; + +typedef struct sAniDHCPStopInd { + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t 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 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; + +/**********************PE Statistics end*************************/ + +typedef struct sSirP2PNoaStart { + uint32_t status; + uint32_t bssIdx; +} tSirP2PNoaStart, *tpSirP2PNoaStart; + +typedef struct sSirTdlsInd { + uint16_t status; + uint16_t assocId; + uint16_t staIdx; + uint16_t reasonCode; +} tSirTdlsInd, *tpSirTdlsInd; + +typedef struct sSirP2PNoaAttr { +#ifdef ANI_BIG_BYTE_ENDIAN + uint32_t index:8; + uint32_t oppPsFlag:1; + uint32_t ctWin:7; + uint32_t rsvd1:16; +#else + uint32_t rsvd1:16; + uint32_t ctWin:7; + uint32_t oppPsFlag:1; + uint32_t index:8; +#endif + +#ifdef ANI_BIG_BYTE_ENDIAN + uint32_t uNoa1IntervalCnt:8; + uint32_t rsvd2:24; +#else + uint32_t rsvd2:24; + uint32_t uNoa1IntervalCnt:8; +#endif + uint32_t uNoa1Duration; + uint32_t uNoa1Interval; + uint32_t uNoa1StartTime; + +#ifdef ANI_BIG_BYTE_ENDIAN + uint32_t uNoa2IntervalCnt:8; + uint32_t rsvd3:24; +#else + uint32_t rsvd3:24; + uint32_t uNoa2IntervalCnt:8; +#endif + uint32_t uNoa2Duration; + uint32_t uNoa2Interval; + uint32_t uNoa2StartTime; +} tSirP2PNoaAttr, *tpSirP2PNoaAttr; + +typedef struct sSirTclasInfo { + tSirMacTclasIE tclas; + uint8_t version; /* applies only for classifier type ip */ + union { + tSirMacTclasParamEthernet eth; + tSirMacTclasParamIPv4 ipv4; + tSirMacTclasParamIPv6 ipv6; + tSirMacTclasParam8021dq t8021dq; + } cdf_packed tclasParams; +} cdf_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 { + uint8_t tsid; + uint8_t rates[8]; +} tSirMacESETSRSIE; +typedef struct sSirMacESETSMIE { + uint8_t tsid; + uint8_t state; + uint16_t msmt_interval; +} tSirMacESETSMIE; +typedef struct sTSMStats { + uint8_t tid; + tSirMacAddr bssId; + tTrafStrmMetrics tsmMetrics; +} tTSMStats, *tpTSMStats; +typedef struct sEseTSMContext { + uint8_t tid; + tSirMacESETSMIE tsmInfo; + tTrafStrmMetrics tsmMetrics; +} tEseTSMContext, *tpEseTSMContext; +typedef struct sEsePEContext { + tEseTSMContext tsm; +} tEsePEContext, *tpEsePEContext; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +typedef struct sSirAddtsReqInfo { + uint8_t dialogToken; + tSirMacTspecIE tspec; + + uint8_t numTclas; /* number of Tclas elements */ + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + uint8_t tclasProc; +#if defined(FEATURE_WLAN_ESE) + tSirMacESETSRSIE tsrsIE; + uint8_t tsrsPresent:1; +#endif + uint8_t wmeTspecPresent:1; + uint8_t wsmTspecPresent:1; + uint8_t lleTspecPresent:1; + uint8_t tclasProcPresent:1; +} tSirAddtsReqInfo, *tpSirAddtsReqInfo; + +typedef struct sSirAddtsRspInfo { + uint8_t dialogToken; + tSirMacStatusCodes status; + tSirMacTsDelayIE delay; + + tSirMacTspecIE tspec; + uint8_t numTclas; /* number of Tclas elements */ + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + uint8_t tclasProc; + tSirMacScheduleIE schedule; +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + tSirMacESETSMIE tsmIE; + uint8_t tsmPresent:1; +#endif + uint8_t wmeTspecPresent:1; + uint8_t wsmTspecPresent:1; + uint8_t lleTspecPresent:1; + uint8_t tclasProcPresent:1; + uint8_t schedulePresent:1; +} tSirAddtsRspInfo, *tpSirAddtsRspInfo; + +typedef struct sSirDeltsReqInfo { + tSirMacTSInfo tsinfo; + tSirMacTspecIE tspec; + uint8_t wmeTspecPresent:1; + uint8_t wsmTspecPresent:1; + uint8_t lleTspecPresent:1; +} tSirDeltsReqInfo, *tpSirDeltsReqInfo; + +/* / Add a tspec as defined */ +typedef struct sSirAddtsReq { + uint16_t messageType; /* eWNI_SME_ADDTS_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; + tSirMacAddr bssId; /* BSSID */ + uint32_t timeout; /* in ms */ + uint8_t rspReqd; + tSirAddtsReqInfo req; +} tSirAddtsReq, *tpSirAddtsReq; + +typedef struct sSirAddtsRsp { + uint16_t messageType; /* eWNI_SME_ADDTS_RSP */ + uint16_t length; + uint8_t sessionId; /* sme sessionId Added for BT-AMP support */ + uint16_t transactionId; /* sme transaction Id - for BT-AMP Support */ + uint32_t rc; /* return code */ + tSirAddtsRspInfo rsp; +} tSirAddtsRsp, *tpSirAddtsRsp; + +typedef struct sSirDeltsReq { + uint16_t messageType; /* eWNI_SME_DELTS_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; + tSirMacAddr bssId; /* BSSID */ + uint16_t aid; /* use 0 if macAddr is being specified */ + tSirMacAddr macAddr; /* only on AP to specify the STA */ + uint8_t rspReqd; + tSirDeltsReqInfo req; +} tSirDeltsReq, *tpSirDeltsReq; + +typedef struct sSirDeltsRsp { + uint16_t messageType; /* eWNI_SME_DELTS_RSP */ + uint16_t length; + uint8_t sessionId; /* sme sessionId Added for BT-AMP support */ + uint16_t transactionId; /* sme transaction Id - for BT-AMP Support */ + uint32_t rc; + uint16_t aid; /* use 0 if macAddr is being specified */ + tSirMacAddr macAddr; /* only on AP to specify the STA */ + tSirDeltsReqInfo rsp; +} tSirDeltsRsp, *tpSirDeltsRsp; + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct sSirPlmReq { + uint16_t diag_token; /* Dialog token */ + uint16_t meas_token; /* measurement token */ + uint16_t numBursts; /* total number of bursts */ + uint16_t burstInt; /* burst interval in seconds */ + uint16_t measDuration; /* in TU's,STA goes off-ch */ + /* no of times the STA should cycle through PLM ch list */ + uint8_t burstLen; + tPowerdBm desiredTxPwr; /* desired tx power */ + tSirMacAddr macAddr; /* MC dest addr */ + /* no of channels */ + uint8_t plmNumCh; + /* channel numbers */ + uint8_t plmChList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint8_t sessionId; + bool 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 { + uint16_t tspecIdx; + tSirAddtsReqInfo aggrAddTsInfo[SIR_QOS_NUM_AC_MAX]; +} tSirAggrQosReqInfo, *tpSirAggrQosReqInfo; + +typedef struct sSirAggrQosReq { + uint16_t messageType; /* eWNI_SME_ADDTS_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; + tSirMacAddr bssId; /* BSSID */ + uint32_t timeout; /* in ms */ + uint8_t rspReqd; + tSirAggrQosReqInfo aggrInfo; +} tSirAggrQosReq, *tpSirAggrQosReq; + +typedef struct sSirAggrQosRspInfo { + uint16_t tspecIdx; + tSirAddtsRspInfo aggrRsp[SIR_QOS_NUM_AC_MAX]; +} tSirAggrQosRspInfo, *tpSirAggrQosRspInfo; + +typedef struct sSirAggrQosRsp { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; + tSirAggrQosRspInfo aggrInfo; +} tSirAggrQosRsp, *tpSirAggrQosRsp; + +#endif /*WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE */ + +typedef struct sSirQosMapSet { + uint8_t present; + uint8_t num_dscp_exceptions; + uint8_t dscp_exceptions[21][2]; + uint8_t dscp_range[8][2]; +} tSirQosMapSet, *tpSirQosMapSet; + +typedef struct sSmeIbssPeerInd { + uint16_t mesgType; + uint16_t mesgLen; + uint8_t sessionId; + + tSirMacAddr peerAddr; + uint16_t 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 */ + uint8_t ucastSig; + + /*Broadcast DPU signature */ + uint8_t bcastSig; + + /* Beacon will be appended for new Peer indication. */ +} tSmeIbssPeerInd, *tpSmeIbssPeerInd; + +typedef struct sSirIbssPeerInactivityInd { + uint8_t bssIdx; + uint8_t staIdx; + tSirMacAddr peerAddr; +} tSirIbssPeerInactivityInd, *tpSirIbssPeerInactivityInd; + +typedef struct sLimScanChn { + uint16_t numTimeScan; /* how many time this channel is scan */ + uint8_t channelId; +} tLimScanChn; + +typedef struct sSmeGetScanChnRsp { + /* Message Type */ + uint16_t mesgType; + /* Message Length */ + uint16_t mesgLen; + uint8_t sessionId; + uint8_t numChn; + tLimScanChn scanChn[1]; +} tSmeGetScanChnRsp, *tpSmeGetScanChnRsp; + +typedef struct sLimScanChnInfo { + uint8_t numChnInfo; /* number of channels in scanChn */ + tLimScanChn scanChn[SIR_MAX_SUPPORTED_CHANNEL_LIST]; +} tLimScanChnInfo; + +typedef struct sSirSmeGetAssocSTAsReq { + uint16_t messageType; /* eWNI_SME_GET_ASSOC_STAS_REQ */ + uint16_t length; + tSirMacAddr bssId; /* BSSID */ + uint16_t modId; + void *pUsrContext; + void *pSapEventCallback; + /* Pointer to allocated mem passed in wlansap_get_assoc_stations API */ + void *pAssocStasArray; +} tSirSmeGetAssocSTAsReq, *tpSirSmeGetAssocSTAsReq; + +typedef struct sSmeMaxAssocInd { + uint16_t mesgType; /* eWNI_SME_MAX_ASSOC_EXCEEDED */ + uint16_t mesgLen; + uint8_t sessionId; + /* the new peer that got rejected max assoc limit reached */ + tSirMacAddr peerMac; +} tSmeMaxAssocInd, *tpSmeMaxAssocInd; + +typedef struct sSmeCsaOffloadInd { + uint16_t mesgType; /* eWNI_SME_CSA_OFFLOAD_EVENT */ + uint16_t mesgLen; + tSirMacAddr bssId; /* BSSID */ +} tSmeCsaOffloadInd, *tpSmeCsaOffloadInd; + +/* WOW related structures */ +#define SIR_WOWL_BCAST_PATTERN_MAX_SIZE 146 + +/** + * struct wow_add_pattern - wow pattern add structure + * @pattern_id: pattern id + * @pattern_byte_offset: pattern byte offset from beginning of the 802.11 + * packet to start of the wake-up pattern + * @pattern_size: pattern size + * @pattern: pattern byte stream + * @pattern_mask_size: pattern mask size + * @pattern_mask: pattern mask + * @session_id: session id + */ +struct wow_add_pattern { + uint8_t pattern_id; + uint8_t pattern_byte_offset; + uint8_t pattern_size; + uint8_t pattern[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; + uint8_t pattern_mask_size; + uint8_t pattern_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; + uint8_t session_id; +}; + +/** + * struct wow_delete_patern - wow pattern delete structure + * @pattern_id: pattern id of wake up pattern to be deleted + * @session_id: session id + */ +struct wow_delete_pattern { + uint8_t pattern_id; + uint8_t session_id; +}; + +/* SME->PE: Enter WOWLAN parameters */ +typedef struct sSirSmeWowlEnterParams { + uint8_t sessionId; + + /* Enables/disables magic packet filtering */ + uint8_t ucMagicPktEnable; + + /* Magic pattern */ + tSirMacAddr magicPtrn; + + /* Enables/disables packet pattern filtering */ + uint8_t ucPatternFilteringEnable; + +#ifdef WLAN_WAKEUP_EVENTS + /* + * This configuration directs the WoW packet filtering to look at EAP-ID + * requests embedded in EAPOL frames and use this as a wake source. + */ + uint8_t ucWoWEAPIDRequestEnable; + + /* + * This configuration directs the WoW packet filtering to look for + * EAPOL-4WAY requests and use this as a wake source. + */ + uint8_t ucWoWEAPOL4WayEnable; + + /* + * This configuration allows a host wakeup on an network scan + * offload match. + */ + uint8_t ucWowNetScanOffloadMatch; + + /* This configuration allows a host wakeup on any GTK rekeying error. + */ + uint8_t ucWowGTKRekeyError; + + /* This configuration allows a host wakeup on BSS connection loss. + */ + uint8_t ucWoWBSSConnLoss; +#endif /* WLAN_WAKEUP_EVENTS */ + + tSirMacAddr bssId; +} tSirSmeWowlEnterParams, *tpSirSmeWowlEnterParams; + +/* PE<->HAL: Enter WOWLAN parameters */ +typedef struct sSirHalWowlEnterParams { + uint8_t sessionId; + + /* Enables/disables magic packet filtering */ + uint8_t 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 + */ + uint8_t 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 + */ + uint8_t ucUcastPatternFilteringEnable; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Channel Switch Action Frame. + */ + uint8_t ucWowChnlSwitchRcv; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Deauthentication Frame. + */ + uint8_t ucWowDeauthRcv; + + /* This configuration is valid only when magicPktEnable=1. + * It requests hardware to wake up when it receives the + * Disassociation Frame. + */ + uint8_t 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). + */ + uint8_t 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. + */ + uint8_t ucWowMaxSleepUsec; + +#ifdef WLAN_WAKEUP_EVENTS + /* This config directs the WoW pkt filtering to look for EAP-ID + * requests embedded in EAPOL frames and use this as a wake source. + */ + uint8_t ucWoWEAPIDRequestEnable; + + /* This config directs the WoW pkt filtering to look for EAPOL-4WAY + * requests and use this as a wake source. + */ + uint8_t ucWoWEAPOL4WayEnable; + + /* This config allows a host wakeup on an network scan offload match. + */ + uint8_t ucWowNetScanOffloadMatch; + + /* This configuration allows a host wakeup on any GTK rekeying error. + */ + uint8_t ucWowGTKRekeyError; + + /* This configuration allows a host wakeup on BSS connection loss. + */ + uint8_t ucWoWBSSConnLoss; +#endif /* WLAN_WAKEUP_EVENTS */ + + /* Status code to be filled by HAL when it sends + * SIR_HAL_WOWL_ENTER_RSP to PE. + */ + CDF_STATUS status; + + /*BSSID to find the current session + */ + uint8_t bssIdx; +} tSirHalWowlEnterParams, *tpSirHalWowlEnterParams; + +/* SME->PE: Exit WOWLAN parameters */ +typedef struct sSirSmeWowlExitParams { + uint8_t sessionId; + +} tSirSmeWowlExitParams, *tpSirSmeWowlExitParams; + +/* PE<->HAL: Exit WOWLAN parameters */ +typedef struct sSirHalWowlExitParams { + uint8_t sessionId; + + /* Status code to be filled by HAL when it sends + * SIR_HAL_WOWL_EXIT_RSP to PE. + */ + CDF_STATUS status; + + /*BSSIDX to find the current session + */ + uint8_t bssIdx; +} tSirHalWowlExitParams, *tpSirHalWowlExitParams; + +#define SIR_MAX_NAME_SIZE 64 +#define SIR_MAX_TEXT_SIZE 32 + +typedef struct sSirName { + uint8_t num_name; + uint8_t name[SIR_MAX_NAME_SIZE]; +} tSirName; + +typedef struct sSirText { + uint8_t num_text; + uint8_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 { + uint32_t FieldPresent; + uint32_t Version; /* Version. 0x10 = version 1.0, 0x11 = etc. */ + uint32_t wpsState; /* 1 = unconfigured, 2 = configured. */ + bool APSetupLocked; /* Must be included if value is true */ + /* + * BOOL: indicates if the user has recently activated a Registrar to + * add an Enrollee. + */ + bool SelectedRegistra; + uint16_t DevicePasswordID; /* Device Password ID */ + /* Selected Registrar config method */ + uint16_t SelectedRegistraCfgMethod; + uint8_t ResponseType; /* Response type */ + uint8_t UUID_E[16]; /* Unique identifier of the AP. */ + tSirName Manufacture; + tSirText ModelName; + tSirText ModelNumber; + tSirText SerialNumber; + /* Device Category ID: 1Computer, 2Input Device, ... */ + uint32_t PrimaryDeviceCategory; + /* Vendor specific OUI for Device Sub Category */ + uint8_t PrimaryDeviceOUI[4]; + /* + Device Sub Category ID: 1-PC, 2-Server if Device Category ID + * is computer + */ + uint32_t DeviceSubCategory; + tSirText DeviceName; + uint16_t ConfigMethod; /* Configuaration method */ + uint8_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 { + uint32_t FieldPresent; + uint32_t Version; /* Version. 0x10 = version 1.0, 0x11 = etc. */ + uint32_t wpsState; /* 1 = unconfigured, 2 = configured. */ + bool APSetupLocked; /* Must be included if value is true */ + /* + * BOOL: indicates if the user has recently activated a Registrar to + * add an Enrollee. + */ + bool SelectedRegistra; + uint16_t DevicePasswordID; /* Device Password ID */ + /* Selected Registrar config method */ + uint16_t SelectedRegistraCfgMethod; + uint8_t UUID_E[SIR_WPS_UUID_LEN]; /* Unique identifier of the AP. */ + uint8_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 { + uint32_t FieldPresent; + uint32_t Version; + uint8_t ResposeType; +} tSirWPSAssocRspIE; + +typedef struct sSirAPWPSIEs { + tSirWPSProbeRspIE SirWPSProbeRspIE; /*WPS Set Probe Respose IE */ + tSirWPSBeaconIE SirWPSBeaconIE; /*WPS Set Beacon IE */ + tSirWPSAssocRspIE SirWPSAssocRspIE; /*WPS Set Assoc Response IE */ +} tSirAPWPSIEs, *tpSiriAPWPSIEs; + +typedef struct sSirUpdateAPWPSIEsReq { + uint16_t messageType; /* eWNI_SME_UPDATE_APWPSIE_REQ */ + uint16_t length; + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; /* BSSID */ + uint8_t sessionId; /* Session ID */ + tSirAPWPSIEs APWPSIEs; +} tSirUpdateAPWPSIEsReq, *tpSirUpdateAPWPSIEsReq; + +typedef struct sSirUpdateParams { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint8_t ssidHidden; /* Hide SSID */ +} tSirUpdateParams, *tpSirUpdateParams; + +/* Beacon Interval */ +typedef struct sSirChangeBIParams { + uint16_t messageType; + uint16_t length; + uint16_t beaconInterval; /* Beacon Interval */ + tSirMacAddr bssId; + uint8_t sessionId; /* Session ID */ +} tSirChangeBIParams, *tpSirChangeBIParams; + +#ifdef QCA_HT_2040_COEX +typedef struct sSirSetHT2040Mode { + uint16_t messageType; + uint16_t length; + uint8_t cbMode; + bool obssEnabled; + tSirMacAddr bssId; + uint8_t sessionId; /* Session ID */ +} tSirSetHT2040Mode, *tpSirSetHT2040Mode; +#endif + +#define SIR_WPS_PBC_WALK_TIME 120 /* 120 Second */ + +typedef struct sSirWPSPBCSession { + struct sSirWPSPBCSession *next; + tSirMacAddr addr; + uint8_t uuid_e[SIR_WPS_UUID_LEN]; + uint32_t timestamp; +} tSirWPSPBCSession; + +typedef struct sSirSmeGetWPSPBCSessionsReq { + uint16_t messageType; /* eWNI_SME_GET_WPSPBC_SESSION_REQ */ + uint16_t length; + void *pUsrContext; + void *pSapEventCallback; + tSirMacAddr bssId; /* BSSID */ + /* MAC Address of STA in WPS Session to be removed */ + tSirMacAddr pRemoveMac; +} tSirSmeGetWPSPBCSessionsReq, *tpSirSmeGetWPSPBCSessionsReq; + +typedef struct sSirWPSPBCProbeReq { + tSirMacAddr peerMacAddr; + uint16_t probeReqIELen; + uint8_t probeReqIE[512]; +} tSirWPSPBCProbeReq, *tpSirWPSPBCProbeReq; + +/* probereq from peer, when wsc is enabled */ +typedef struct sSirSmeProbeReqInd { + uint16_t messageType; /* eWNI_SME_WPS_PBC_PROBE_REQ_IND */ + uint16_t length; + uint8_t sessionId; + tSirMacAddr bssId; + tSirWPSPBCProbeReq WPSPBCProbeReq; +} tSirSmeProbeReqInd, *tpSirSmeProbeReqInd; + +typedef struct sSirUpdateAPWPARSNIEsReq { + uint16_t messageType; /* eWNI_SME_SET_APWPARSNIEs_REQ */ + uint16_t length; + uint16_t transactionId; /* Transaction ID for cmd */ + tSirMacAddr bssId; /* BSSID */ + uint8_t sessionId; /* Session ID */ + tSirRSNie APWPARSNIEs; +} tSirUpdateAPWPARSNIEsReq, *tpSirUpdateAPWPARSNIEsReq; + +#define SIR_ROAM_MAX_CHANNELS 80 +#define SIR_ROAM_SCAN_MAX_PB_REQ_SIZE 450 +/* Occupied channel list remains static */ +#define CHANNEL_LIST_STATIC 1 +/* Occupied channel list can be learnt after init */ +#define CHANNEL_LIST_DYNAMIC_INIT 2 +/* Occupied channel list can be learnt after flush */ +#define CHANNEL_LIST_DYNAMIC_FLUSH 3 +/* Occupied channel list can be learnt after update */ +#define CHANNEL_LIST_DYNAMIC_UPDATE 4 +#define SIR_ROAM_SCAN_24G_DEFAULT_CH 1 +#define SIR_ROAM_SCAN_5G_DEFAULT_CH 36 +#define SIR_ROAM_SCAN_RESERVED_BYTES 61 + +#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 { + uint8_t srcIPv6Addr[16]; + uint8_t selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; + uint8_t targetIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; + tSirMacAddr selfMacAddr; + uint8_t srcIPv6AddrValid; + uint8_t targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + uint8_t slotIdx; +} tSirNsOffloadReq, *tpSirNsOffloadReq; +#endif /* WLAN_NS_OFFLOAD */ + +typedef struct sSirHostOffloadReq { + uint8_t offloadType; + uint8_t enableOrDisable; + uint32_t num_ns_offload_count; + union { + uint8_t hostIpv4Addr[4]; + uint8_t 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 { + uint8_t packetType; + uint32_t timePeriod; + tSirIpv4Addr hostIpv4Addr; + tSirIpv4Addr destIpv4Addr; + tSirMacAddr destMacAddr; + tSirMacAddr bssId; + uint8_t sessionId; +} tSirKeepAliveReq, *tpSirKeepAliveReq; + +typedef struct sSirSmeMgmtFrameInd { + uint16_t mesgType; + uint16_t mesgLen; + uint32_t rxChan; + uint8_t sessionId; + uint8_t frameType; + int8_t rxRssi; + uint8_t frameBuf[1]; /* variable */ +} tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; + +#ifdef WLAN_FEATURE_11W +typedef struct sSirSmeUnprotMgmtFrameInd { + uint8_t sessionId; + uint8_t frameType; + uint8_t frameLen; + uint8_t 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))) +#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 { + uint8_t ctWindow:7; + uint8_t OppPS:1; + uint8_t count; + uint32_t duration; + uint32_t interval; + uint32_t singleNoADuration; + uint8_t psSelection; +} tSirNoAParam, *tpSirNoAParam; + +typedef struct sSirWlanSuspendParam { + uint8_t configuredMcstBcstFilterSetting; + uint8_t sessionId; + uint8_t connectedState; +} tSirWlanSuspendParam, *tpSirWlanSuspendParam; + +typedef struct sSirWlanResumeParam { + uint8_t 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 { + uint8_t vdev_id; + EXT_WOW_TYPE type; + uint32_t wakeup_pin_num; +} tSirExtWoWParams, *tpSirExtWoWParams; + +typedef struct { + uint8_t vdev_id; + tSirMacAddr wakee_mac_addr; + uint8_t identification_id[8]; + uint8_t password[16]; + uint32_t id_length; + uint32_t pass_length; +} tSirAppType1Params, *tpSirAppType1Params; + +typedef struct { + uint8_t vdev_id; + + uint8_t rc4_key[16]; + uint32_t rc4_key_len; + + /** ip header parameter */ + uint32_t ip_id; /* NC id */ + uint32_t ip_device_ip; /* NC IP address */ + uint32_t ip_server_ip; /* Push server IP address */ + + /** tcp header parameter */ + uint16_t tcp_src_port; /* NC TCP port */ + uint16_t tcp_dst_port; /* Push server TCP port */ + uint32_t tcp_seq; + uint32_t tcp_ack_seq; + + uint32_t keepalive_init; /* Initial ping interval */ + uint32_t keepalive_min; /* Minimum ping interval */ + uint32_t keepalive_max; /* Maximum ping interval */ + uint32_t keepalive_inc; /* Increment of ping interval */ + + tSirMacAddr gateway_mac; + uint32_t tcp_tx_timeout_val; + uint32_t tcp_rx_timeout_val; +} tSirAppType2Params, *tpSirAppType2Params; +#endif + +typedef struct sSirWlanSetRxpFilters { + uint8_t configuredMcstBcstFilterSetting; + uint8_t setMcstBcstFilter; +} tSirWlanSetRxpFilters, *tpSirWlanSetRxpFilters; + + +#define ANI_MAX_IBSS_ROUTE_TABLE_ENTRY 100 + +typedef struct sAniDestIpNextHopMacPair { + uint8_t destIpv4Addr[CDF_IPV4_ADDR_SIZE]; + uint8_t nextHopMacAddr[CDF_MAC_ADDR_SIZE]; +} tAniDestIpNextHopMacPair; + +typedef struct sAniIbssRouteTable { + uint8_t sessionId; + uint16_t numEntries; + tAniDestIpNextHopMacPair destIpNextHopPair[1]; +} tAniIbssRouteTable; + +#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 +#define SIR_PNO_MAX_SCAN_TIMERS 10 + +/* + * 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; + uint32_t authentication; + uint32_t encryption; + uint32_t bcastNetwType; + uint8_t ucChannelCount; + uint8_t aChannels[SIR_PNO_MAX_NETW_CHANNELS_EX]; + int32_t rssiThreshold; +} tSirNetworkType; + +typedef struct { + uint32_t uTimerValue; + uint32_t uTimerRepeat; +} tSirScanTimer; + +typedef struct { + uint8_t ucScanTimersCount; + tSirScanTimer aTimerValues[SIR_PNO_MAX_SCAN_TIMERS]; +} tSirScanTimersType; + +typedef struct sSirPNOScanReq { + uint8_t enable; + eSirPNOMode modePNO; + uint8_t ucNetworksCount; + tSirNetworkType aNetworks[SIR_PNO_MAX_SUPP_NETWORKS]; + tSirScanTimersType scanTimers; + uint8_t sessionId; + + 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; + +/* Preferred Network Found Indication */ +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + /* Network that was found with the highest RSSI */ + tSirMacSSid ssId; + /* Indicates the RSSI */ + uint8_t rssi; + /* Length of the beacon or probe response + * corresponding to the candidate found by PNO */ + uint32_t frameLength; + uint8_t sessionId; + /* Index to memory location where the contents of + * beacon or probe response frame will be copied */ + uint8_t data[1]; +} tSirPrefNetworkFoundInd, *tpSirPrefNetworkFoundInd; +#endif /* FEATURE_WLAN_SCAN_PNO */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +typedef struct { + uint8_t acvo_uapsd:1; + uint8_t acvi_uapsd:1; + uint8_t acbk_uapsd:1; + uint8_t acbe_uapsd:1; + uint8_t reserved:4; +} tSirAcUapsd, *tpSirAcUapsd; +#endif + +typedef struct { + tSirMacSSid ssId; + uint8_t currAPbssid[CDF_MAC_ADDR_SIZE]; + uint32_t authentication; + uint8_t encryption; + uint8_t mcencryption; + uint8_t ChannelCount; + uint8_t ChannelCache[SIR_ROAM_MAX_CHANNELS]; +#ifdef WLAN_FEATURE_11W + bool mfp_enabled; +#endif + +} tSirRoamNetworkType; + +typedef struct SirMobilityDomainInfo { + uint8_t mdiePresent; + uint16_t 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 - Structure holding roaming parameters + * @num_bssid_avoid_list: The number of BSSID's that we should + * avoid connecting to. It is like a + * blacklist of BSSID's. + * @num_ssid_allowed_list: The number of SSID profiles that are + * in the Whitelist. When roaming, we + * consider the BSSID's with this SSID + * also for roaming apart from the connected one's + * @num_bssid_favored: Number of BSSID's which have a preference over + * others + * @ssid_allowed_list: Whitelist SSID's + * @bssid_avoid_list: Blacklist SSID's + * @bssid_favored: Favorable BSSID's + * @bssid_favored_factor: RSSI to be added to this BSSID to prefer it + * @raise_rssi_thresh_5g: The RSSI threshold below which the + * raise_factor_5g (boost factor) should be + * applied. + * @drop_rssi_thresh_5g: The RSSI threshold beyond which the + * drop_factor_5g (penalty factor) should be + * applied + * @raise_rssi_type_5g: Algorithm to apply the boost factor + * @raise_factor_5g: Boost factor + * @drop_rssi_type_5g: Algorithm to apply the penalty factor + * @drop_factor_5g: Penalty factor + * @max_raise_rssi_5g: Maximum amount of Boost that can added + * @max_drop_rssi_5g: Maximum amount of penalty that can be subtracted + * @good_rssi_threshold: The Lookup UP threshold beyond which roaming + * scan should be performed. + * @rssi_diff: RSSI difference for the AP to be better over the + * current AP to avoid ping pong effects + * @good_rssi_roam: Lazy Roam + * @is_5g_pref_enabled: 5GHz BSSID preference feature enable/disable. + * + * This structure holds all the key parameters related to + * initial connection and also roaming connections. + * */ +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 { + bool RoamScanOffloadEnabled; + bool MAWCEnabled; + int8_t LookupThreshold; + uint8_t delay_before_vdev_stop; + uint8_t OpportunisticScanThresholdDiff; + uint8_t RoamRescanRssiDiff; + uint8_t RoamRssiDiff; + uint8_t ChannelCacheType; + uint8_t Command; + uint8_t reason; + uint16_t NeighborScanTimerPeriod; + uint16_t NeighborRoamScanRefreshPeriod; + uint16_t NeighborScanChannelMinTime; + uint16_t NeighborScanChannelMaxTime; + uint16_t EmptyRefreshScanPeriod; + uint8_t ValidChannelCount; + uint8_t ValidChannelList[SIR_ROAM_MAX_CHANNELS]; + bool IsESEAssoc; + uint16_t us24GProbeTemplateLen; + uint8_t p24GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; + uint16_t us5GProbeTemplateLen; + uint8_t p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; + uint8_t 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. */ + uint8_t nProbes; + uint16_t HomeAwayTime; + tSirRoamNetworkType ConnectedNetwork; + tSirMobilityDomainInfo MDID; + uint8_t sessionId; + uint8_t RoamBmissFirstBcnt; + uint8_t RoamBmissFinalBcnt; + uint8_t RoamBeaconRssiWeight; + eSirDFSRoamScanMode allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t RoamOffloadEnabled; + uint8_t PSK_PMK[SIR_ROAM_SCAN_PSK_SIZE]; + uint32_t pmk_len; + uint8_t Prefer5GHz; + uint8_t RoamRssiCatGap; + uint8_t Select5GHzMargin; + uint8_t KRK[SIR_KRK_KEY_LEN]; + uint8_t BTK[SIR_BTK_KEY_LEN]; + uint32_t ReassocFailureTimeout; + tSirAcUapsd AcUapsd; + uint8_t R0KH_ID[SIR_ROAM_R0KH_ID_MAX_LEN]; + uint32_t R0KH_ID_Length; + uint8_t RoamKeyMgmtOffloadEnabled; +#endif + struct roam_ext_params roam_params; + uint8_t middle_of_roaming; + 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; +} tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; + +typedef struct sSirRoamOffloadScanRsp { + uint8_t sessionId; + uint32_t reason; +} tSirRoamOffloadScanRsp, *tpSirRoamOffloadScanRsp; + + +#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 */ + uint16_t dataLength; + /* from start of the respective frame header */ + uint8_t dataOffset; + /* Reserved field */ + uint8_t reserved; + /* Data to compare */ + uint8_t compareData[SIR_MAX_FILTER_TEST_DATA_LEN]; + /* Mask to be applied on the received packet data before compare */ + uint8_t dataMask[SIR_MAX_FILTER_TEST_DATA_LEN]; +} tSirRcvPktFilterFieldParams, *tpSirRcvPktFilterFieldParams; + +typedef struct sSirRcvPktFilterCfg { + uint8_t filterId; + eSirReceivePacketFilterType filterType; + uint32_t numFieldParams; + uint32_t 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 { + uint8_t filterId; + uint32_t matchCnt; +} tSirRcvFltPktMatchCnt, tpSirRcvFltPktMatchCnt; + +typedef struct sSirRcvFltPktMatchRsp { + uint16_t mesgType; + uint16_t mesgLen; + + /* Success or Failure */ + uint32_t status; + tSirRcvFltPktMatchCnt filterMatchCnt[SIR_MAX_NUM_FILTERS]; + tSirMacAddr bssId; +} tSirRcvFltPktMatchRsp, *tpSirRcvFltPktMatchRsp; + +/* */ +/* Receive Filter Clear Parameters */ +/* */ +typedef struct sSirRcvFltPktClearParam { + uint32_t status; /* only valid for response message */ + uint8_t filterId; + tSirMacAddr selfMacAddr; + tSirMacAddr bssId; +} tSirRcvFltPktClearParam, *tpSirRcvFltPktClearParam; + +/* */ +/* Multicast Address List Parameters */ +/* */ +typedef struct sSirRcvFltMcAddrList { + uint32_t ulMulticastAddrCnt; + tSirMacAddr multicastAddr[SIR_MAX_NUM_MULTICAST_ADDRESS]; + tSirMacAddr selfMacAddr; + tSirMacAddr bssId; + uint8_t action; +} tSirRcvFltMcAddrList, *tpSirRcvFltMcAddrList; +#endif /* WLAN_FEATURE_PACKET_FILTERING */ + +/* */ +/* Generic version information */ +/* */ +typedef struct { + uint8_t revision; + uint8_t version; + uint8_t minor; + uint8_t major; +} tSirVersionType; + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/*--------------------------------------------------------------------------- +* WMA_GTK_OFFLOAD_REQ +*--------------------------------------------------------------------------*/ +typedef struct { + uint32_t ulFlags; /* optional flags */ + uint8_t aKCK[16]; /* Key confirmation key */ + uint8_t aKEK[16]; /* key encryption key */ + uint64_t 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; +}; + +/** + * enum hw_mode_ss_config - Possible spatial stream configuration + * @SS_0x0: Unused Tx and Rx of MAC + * @SS_1x1: 1 Tx SS and 1 Rx SS + * @SS_2x2: 2 Tx SS and 2 Rx SS + * @SS_3x3: 3 Tx SS and 3 Rx SS + * @SS_4x4: 4 Tx SS and 4 Rx SS + * + * Note: Right now only 1x1 and 2x2 are being supported. Other modes should + * be added when supported. Asymmetric configuration like 1x2, 2x1 are also + * not supported now. But, they are still valid. Right now, Tx/Rx SS support is + * 4 bits long. So, we can go upto 15x15 + */ +enum hw_mode_ss_config { + HW_MODE_SS_0x0, + HW_MODE_SS_1x1, + HW_MODE_SS_2x2, + HW_MODE_SS_3x3, + HW_MODE_SS_4x4, +}; + +/** + * enum hw_mode_bandwidth - bandwidth of wifi channel. + * + * @HW_MODE_5_MHZ: 5 Mhz bandwidth + * @HW_MODE_10_MHZ: 10 Mhz bandwidth + * @HW_MODE_20_MHZ: 20 Mhz bandwidth + * @HW_MODE_40_MHZ: 40 Mhz bandwidth + * @HW_MODE_80_MHZ: 80 Mhz bandwidth + * @HW_MODE_80_PLUS_80_MHZ: 80 Mhz plus 80 Mhz bandwidth + * @HW_MODE_160_MHZ: 160 Mhz bandwidth + * @HW_MODE_MAX_BANDWIDTH: Max place holder + * + * These are generic IDs that identify the various roles + * in the software system + */ +enum hw_mode_bandwidth { + HW_MODE_BW_NONE, + HW_MODE_5_MHZ, + HW_MODE_10_MHZ, + HW_MODE_20_MHZ, + HW_MODE_40_MHZ, + HW_MODE_80_MHZ, + HW_MODE_80_PLUS_80_MHZ, + HW_MODE_160_MHZ, + HW_MODE_MAX_BANDWIDTH +}; + +/** + * enum hw_mode_dbs_capab - DBS HW mode capability + * @HW_MODE_DBS_NONE: Non DBS capable + * @HW_MODE_DBS: DFS capable + */ +enum hw_mode_dbs_capab { + HW_MODE_DBS_NONE, + HW_MODE_DBS, +}; + +/** + * enum hw_mode_agile_dfs_capab - Agile DFS HW mode capability + * @HW_MODE_AGILE_DFS_NONE: Non Agile DFS capable + * @HW_MODE_AGILE_DFS: Agile DFS capable + */ +enum hw_mode_agile_dfs_capab { + HW_MODE_AGILE_DFS_NONE, + HW_MODE_AGILE_DFS, +}; + +/** + * enum set_hw_mode_status - Status of set HW mode command + * @SET_HW_MODE_STATUS_OK: command successful + * @SET_HW_MODE_STATUS_EINVAL: Requested invalid hw_mode + * @SET_HW_MODE_STATUS_ECANCELED: HW mode change cancelled + * @SET_HW_MODE_STATUS_ENOTSUP: HW mode not supported + * @SET_HW_MODE_STATUS_EHARDWARE: HW mode change prevented by hardware + * @SET_HW_MODE_STATUS_EPENDING: HW mode change is pending + * @SET_HW_MODE_STATUS_ECOEX: HW mode change conflict with Coex + */ +enum set_hw_mode_status { + SET_HW_MODE_STATUS_OK, + SET_HW_MODE_STATUS_EINVAL, + SET_HW_MODE_STATUS_ECANCELED, + SET_HW_MODE_STATUS_ENOTSUP, + SET_HW_MODE_STATUS_EHARDWARE, + SET_HW_MODE_STATUS_EPENDING, + SET_HW_MODE_STATUS_ECOEX, +}; + +/** + * struct sir_pcl_list - Format of PCL + * @pcl_list: List of preferred channels + * @pcl_len: Number of channels in the PCL + */ +struct sir_pcl_list { + uint8_t pcl_list[128]; + uint32_t pcl_len; +}; + +/** + * struct sir_hw_mode_params - HW mode params + * @mac0_tx_ss: MAC0 Tx spatial stream + * @mac0_rx_ss: MAC0 Rx spatial stream + * @mac1_tx_ss: MAC1 Tx spatial stream + * @mac1_rx_ss: MAC1 Rx spatial stream + * @mac0_bw: MAC0 bandwidth + * @mac1_bw: MAC1 bandwidth + * @dbs_cap: DBS capabality + * @agile_dfs_cap: Agile DFS capabality + */ +struct sir_hw_mode_params { + uint8_t mac0_tx_ss; + uint8_t mac0_rx_ss; + uint8_t mac1_tx_ss; + uint8_t mac1_rx_ss; + uint8_t mac0_bw; + uint8_t mac1_bw; + uint8_t dbs_cap; + uint8_t agile_dfs_cap; +}; + +/** + * struct sir_vdev_mac_map - vdev id-mac id map + * @vdev_id: VDEV id + * @mac_id: MAC id + */ +struct sir_vdev_mac_map { + uint32_t vdev_id; + uint32_t mac_id; +}; + +/** + * struct sir_set_hw_mode_resp - HW mode response + * @status: Status + * @cfgd_hw_mode_index: Configured HW mode index + * @num_vdev_mac_entries: Number of vdev-mac id entries + * @vdev_mac_map: vdev id-mac id map + */ +struct sir_set_hw_mode_resp { + uint32_t status; + uint32_t cfgd_hw_mode_index; + uint32_t num_vdev_mac_entries; + struct sir_vdev_mac_map vdev_mac_map[MAX_VDEV_SUPPORTED]; +}; + +/** + * struct sir_hw_mode_trans_ind - HW mode transition indication + * @old_hw_mode_index: Index of old HW mode + * @new_hw_mode_index: Index of new HW mode + * @num_vdev_mac_entries: Number of vdev-mac id entries + * @vdev_mac_map: vdev id-mac id map + */ +struct sir_hw_mode_trans_ind { + uint32_t old_hw_mode_index; + uint32_t new_hw_mode_index; + uint32_t num_vdev_mac_entries; + struct sir_vdev_mac_map vdev_mac_map[MAX_VDEV_SUPPORTED]; +}; + +/** + * struct sir_dual_mac_config_resp - Dual MAC config response + * @status: Status of setting the dual mac configuration + */ +struct sir_dual_mac_config_resp { + uint32_t status; +}; + +/*--------------------------------------------------------------------------- +* WMA_GTK_OFFLOAD_GETINFO_REQ +*--------------------------------------------------------------------------*/ +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + + uint32_t ulStatus; /* success or failure */ + uint64_t ullKeyReplayCounter; /* current replay counter value */ + uint32_t ulTotalRekeyCount; /* total rekey attempts */ + uint32_t ulGTKRekeyCount; /* successful GTK rekeys */ + uint32_t ulIGTKRekeyCount; /* successful iGTK rekeys */ + tSirMacAddr bssId; +} tSirGtkOffloadGetInfoRspParams, *tpSirGtkOffloadGetInfoRspParams; +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + +#ifdef WLAN_WAKEUP_EVENTS +/*--------------------------------------------------------------------------- + tSirWakeReasonInd + ---------------------------------------------------------------------------*/ +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + uint32_t ulReason; /* see tWakeReasonType */ + uint32_t ulReasonArg; /* argument specific to the reason type */ + /* 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 + */ + uint32_t ulStoredDataLen; + uint32_t ulActualDataLen; /* actual length of data */ + /* variable length start of data (length == storedDataLen) + * see specific wake type + */ + uint8_t aDataStart[1]; +} tSirWakeReasonInd, *tpSirWakeReasonInd; +#endif /* WLAN_WAKEUP_EVENTS */ + +/*--------------------------------------------------------------------------- + sAniSetTmLevelReq + ---------------------------------------------------------------------------*/ +typedef struct sAniSetTmLevelReq { + uint16_t tmMode; + uint16_t newTmLevel; +} tAniSetTmLevelReq, *tpAniSetTmLevelReq; + +#ifdef FEATURE_WLAN_TDLS +/* TDLS Request struct SME-->PE */ +typedef struct sSirTdlsSendMgmtReq { + uint16_t messageType; /* eWNI_SME_TDLS_DISCOVERY_START_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + uint8_t reqType; + uint8_t dialog; + uint16_t statusCode; + uint8_t responder; + uint32_t peerCapability; + /* For multi-session, for PE to locate peSession ID */ + tSirMacAddr bssid; + tSirMacAddr peerMac; + /* Variable lenght. Dont add any field after this. */ + uint8_t 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 { + uint16_t messageType; /* eWNI_SME_TDLS_DISCOVERY_START_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + /* For multi-session, for PE to locate peSession ID */ + tSirMacAddr bssid; + eTdlsAddOper tdlsAddOper; + tSirMacAddr peerMac; + uint16_t capability; + uint8_t extn_capability[SIR_MAC_MAX_EXTN_CAP]; + uint8_t supported_rates_length; + uint8_t supported_rates[SIR_MAC_MAX_SUPP_RATES]; + uint8_t htcap_present; + tSirHTCap htCap; + uint8_t vhtcap_present; + tSirVHTCap vhtCap; + uint8_t uapsd_queues; + uint8_t max_sp; +} tSirTdlsAddStaReq, *tpSirSmeTdlsAddStaReq; + +/* TDLS Response struct PE-->SME */ +typedef struct sSirTdlsAddStaRsp { + uint16_t messageType; + uint16_t length; + tSirResultCodes statusCode; + tSirMacAddr peerMac; + uint8_t sessionId; /* Session ID */ + uint16_t staId; + uint16_t staType; + uint8_t ucastSig; + uint8_t bcastSig; + eTdlsAddOper tdlsAddOper; +} tSirTdlsAddStaRsp; + +/* TDLS Request struct SME-->PE */ +typedef struct { + uint16_t messageType; /* eWNI_SME_TDLS_LINK_ESTABLISH_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + uint8_t uapsdQueues; /* Peer's uapsd Queues Information */ + uint8_t maxSp; /* Peer's Supported Maximum Service Period */ + uint8_t isBufSta; /* Does Peer Support as Buffer Station. */ + /* Does Peer Support as TDLS Off Channel. */ + uint8_t isOffChannelSupported; + uint8_t isResponder; /* Is Peer a responder. */ + /* For multi-session, for PE to locate peSession ID */ + tSirMacAddr bssid; + tSirMacAddr peerMac; + uint8_t supportedChannelsLen; + uint8_t supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + uint8_t supportedOperClassesLen; + uint8_t supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} tSirTdlsLinkEstablishReq, *tpSirTdlsLinkEstablishReq; + +/* TDLS Request struct SME-->PE */ +typedef struct { + uint16_t messageType; /* eWNI_SME_TDLS_LINK_ESTABLISH_RSP */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + tSirResultCodes statusCode; + tSirMacAddr peerMac; +} tSirTdlsLinkEstablishReqRsp, *tpSirTdlsLinkEstablishReqRsp; + +/* TDLS Request struct SME-->PE */ +typedef struct sSirTdlsDelStaReq { + uint16_t messageType; /* eWNI_SME_TDLS_DISCOVERY_START_REQ */ + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t transactionId; /* Transaction ID for cmd */ + /* For multi-session, for PE to locate peSession ID */ + tSirMacAddr bssid; + tSirMacAddr peerMac; +} tSirTdlsDelStaReq, *tpSirSmeTdlsDelStaReq; +/* TDLS Response struct PE-->SME */ +typedef struct sSirTdlsDelStaRsp { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ + tSirResultCodes statusCode; + tSirMacAddr peerMac; + uint16_t staId; +} tSirTdlsDelStaRsp, *tpSirTdlsDelStaRsp; +/* TDLS Delete Indication struct PE-->SME */ +typedef struct sSirTdlsDelStaInd { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ + tSirMacAddr peerMac; + uint16_t staId; + uint16_t reasonCode; +} tSirTdlsDelStaInd, *tpSirTdlsDelStaInd; +typedef struct sSirTdlsDelAllPeerInd { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ +} tSirTdlsDelAllPeerInd, *tpSirTdlsDelAllPeerInd; +#ifdef FEATURE_WLAN_TDLS_DISAPPEAR_AP +typedef struct sSirTdlsDisappearAPInd { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint16_t staId; + tSirMacAddr staAddr; +} tSirTdlsDisappearAPInd, *tpSirTdlsDisappearAPInd; +#endif +typedef struct sSirMgmtTxCompletionInd { + uint16_t messageType; + uint16_t length; + uint8_t sessionId; /* Session ID */ + uint32_t txCompleteStatus; +} tSirMgmtTxCompletionInd, *tpSirMgmtTxCompletionInd; + +typedef struct sSirTdlsEventnotify { + uint8_t sessionId; + tSirMacAddr peerMac; + uint16_t messageType; + uint32_t peer_reason; +} tSirTdlsEventnotify; +#endif /* FEATURE_WLAN_TDLS */ + +typedef struct sSirActiveModeSetBcnFilterReq { + uint16_t messageType; + uint16_t length; + uint8_t seesionId; +} tSirSetActiveModeSetBncFilterReq, *tpSirSetActiveModeSetBncFilterReq; + +/* Reset AP Caps Changed */ +typedef struct sSirResetAPCapsChange { + uint16_t messageType; + uint16_t length; + tSirMacAddr bssId; +} tSirResetAPCapsChange, *tpSirResetAPCapsChange; + +/* / Definition for Candidate found indication from FW */ +typedef struct sSirSmeCandidateFoundInd { + uint16_t messageType; /* eWNI_SME_CANDIDATE_FOUND_IND */ + uint16_t length; + uint8_t sessionId; /* Session Identifier */ +} tSirSmeCandidateFoundInd, *tpSirSmeCandidateFoundInd; + +#ifdef WLAN_FEATURE_11W +typedef struct sSirWlanExcludeUnencryptParam { + bool 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 */ + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t sessionId; + uint8_t bssid[CDF_MAC_ADDR_SIZE]; + uint8_t channel; + uint8_t handoff_src; +} tAniHandoffReq, *tpAniHandoffReq; + +typedef struct sSirScanOffloadReq { + uint8_t sessionId; + tSirMacAddr bssId; + uint8_t numSsid; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + uint8_t hiddenSsid; + tSirMacAddr selfMacAddr; + tSirBssType bssType; + uint8_t dot11mode; + tSirScanType scanType; + uint32_t minChannelTime; + uint32_t maxChannelTime; + uint32_t scan_id; + /* in units of milliseconds, ignored when not connected */ + uint32_t restTime; + tSirP2pScanType p2pScanType; + uint16_t uIEFieldLen; + uint16_t 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 ch */ + SCAN_EVENT_FOREIGN_CHANNEL = 0x8, /* FW going to move to FORIEGN ch */ + SCAN_EVENT_DEQUEUED = 0x10, /* scan request got dequeued */ + SCAN_EVENT_PREEMPTED = 0x20, /* preempted by 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; + uint32_t chanFreq; + uint32_t requestor; + uint32_t scanId; + tSirP2pScanType p2pScanType; + uint8_t sessionId; +} tSirScanOffloadEvent, *tpSirScanOffloadEvent; + +/** + * struct sSirUpdateChanParam - channel parameters + * @chanId: ID of the channel + * @pwr: power level + * @dfsSet: is dfs supported or not + * @half_rate: is the channel operating at 10MHz + * @quarter_rate: is the channel operating at 5MHz + */ +typedef struct sSirUpdateChanParam { + uint8_t chanId; + uint8_t pwr; + bool dfsSet; + bool half_rate; + bool quarter_rate; +} tSirUpdateChanParam, *tpSirUpdateChanParam; + +typedef struct sSirUpdateChan { + uint8_t numChan; + 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 { + uint8_t enable; + uint8_t item; + uint8_t session; +} tSirLPHBEnableStruct; + +typedef struct sSirLPHBTcpParamStruct { + uint32_t srv_ip; + uint32_t dev_ip; + uint16_t src_port; + uint16_t dst_port; + uint16_t timeout; + uint8_t session; + tSirMacAddr gateway_mac; + uint16_t timePeriodSec; /* in seconds */ + uint32_t tcpSn; +} tSirLPHBTcpParamStruct; + +typedef struct sSirLPHBTcpFilterStruct { + uint16_t length; + uint8_t offset; + uint8_t session; + uint8_t filter[SIR_LPHB_FILTER_LEN]; +} tSirLPHBTcpFilterStruct; + +typedef struct sSirLPHBUdpParamStruct { + uint32_t srv_ip; + uint32_t dev_ip; + uint16_t src_port; + uint16_t dst_port; + uint16_t interval; + uint16_t timeout; + uint8_t session; + tSirMacAddr gateway_mac; +} tSirLPHBUdpParamStruct; + +typedef struct sSirLPHBUdpFilterStruct { + uint16_t length; + uint8_t offset; + uint8_t session; + uint8_t filter[SIR_LPHB_FILTER_LEN]; +} tSirLPHBUdpFilterStruct; + +typedef struct sSirLPHBReq { + uint16_t cmd; + uint16_t dummy; + union { + tSirLPHBEnableStruct lphbEnableReq; + tSirLPHBTcpParamStruct lphbTcpParamReq; + tSirLPHBTcpFilterStruct lphbTcpFilterReq; + tSirLPHBUdpParamStruct lphbUdpParamReq; + tSirLPHBUdpFilterStruct lphbUdpFilterReq; + } params; +} tSirLPHBReq; + +typedef struct sSirLPHBInd { + uint8_t sessionIdx; + uint8_t protocolType; /*TCP or UDP */ + uint8_t eventReason; +} tSirLPHBInd; +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_CH_AVOID +typedef struct sSirChAvoidUpdateReq { + uint32_t reserved_param; +} tSirChAvoidUpdateReq; +#endif /* FEATURE_WLAN_CH_AVOID */ + +typedef struct sSirLinkSpeedInfo { + /* MAC Address for the peer */ + tSirMacAddr peer_macaddr; + uint32_t estLinkSpeed; /* Linkspeed from firmware */ +} tSirLinkSpeedInfo, *tpSirLinkSpeedInfo; + +typedef struct sSirAddPeriodicTxPtrn { + /* MAC Address for the adapter */ + tSirMacAddr macAddress; + uint8_t ucPtrnId; /* Pattern ID */ + uint16_t ucPtrnSize; /* Pattern size */ + uint32_t usPtrnIntervalMs; /* In msec */ + uint8_t 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 */ + uint32_t ucPatternIdBitmap; + uint8_t ucPtrnId; /* Pattern ID */ +} tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn; + +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + bool suspended; +} tSirReadyToSuspendInd, *tpSirReadyToSuspendInd; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + bool status; +} tSirReadyToExtWoWInd, *tpSirReadyToExtWoWInd; +#endif +typedef struct sSirRateUpdateInd { + uint8_t nss; /* 0: 1x1, 1: 2x2 */ + tSirMacAddr bssid; + tCDF_CON_MODE dev_mode; + int32_t bcastDataRate; /* bcast rate unit Mbpsx10, -1:not used */ + /* + * 0 implies RA, positive value implies fixed rate, -1 implies ignore + * this param. + */ + int32_t 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 + */ + int32_t 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 + */ + uint32_t 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 + */ + uint32_t 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 { + uint32_t start_freq; + uint32_t end_freq; +} tSirChAvoidFreqType; + +typedef struct sSirChAvoidIndType { + uint32_t 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 { + uint32_t nchannels; + /* Ch num including bonded channels on which the RADAR is present */ + uint8_t channels[SIR_DFS_MAX_20M_SUB_CH]; +} tSirSmeDfsChannelList, *tpSirSmeDfsChannelList; + +typedef struct sSirSmeDfsEventInd { + uint32_t sessionId; + tSirSmeDfsChannelList chan_list; + uint32_t dfs_radar_status; + int use_nol; +} tSirSmeDfsEventInd, *tpSirSmeDfsEventInd; + +typedef struct sSirChanChangeRequest { + uint16_t messageType; + uint16_t messageLen; + uint8_t targetChannel; + uint8_t cbMode; + uint8_t channel_width; + uint8_t center_freq_seg_0; + uint8_t center_freq_seg_1; + uint8_t bssid[CDF_MAC_ADDR_SIZE]; + uint32_t dot11mode; + tSirMacRateSet operational_rateset; + tSirMacRateSet extended_rateset; +} tSirChanChangeRequest, *tpSirChanChangeRequest; + +typedef struct sSirChanChangeResponse { + uint8_t sessionId; + uint8_t newChannelNumber; + uint8_t channelChangeStatus; + ePhyChanBondState secondaryChannelOffset; +} tSirChanChangeResponse, *tpSirChanChangeResponse; + +typedef struct sSirStartBeaconIndication { + uint16_t messageType; + uint16_t messageLen; + uint8_t beaconStartStatus; + uint8_t bssid[CDF_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 prob resp Bcn */ +typedef struct sSirModifyIE { + tSirMacAddr bssid; + uint16_t smeSessionId; + bool notify; + uint8_t ieID; + uint8_t ieIDLen; /*ie length as per spec */ + uint16_t ieBufferlength; + uint8_t *pIEBuffer; + +} tSirModifyIE, *tpSirModifyIE; + +/* Message format for Update IE message sent to PE */ +typedef struct sSirModifyIEsInd { + uint16_t msgType; + uint16_t msgLen; + tSirModifyIE modifyIE; + eUpdateIEsType updateType; +} tSirModifyIEsInd, *tpSirModifyIEsInd; + +/* Message format for Update IE message sent to PE */ +typedef struct sSirUpdateIE { + tSirMacAddr bssid; + uint16_t smeSessionId; + bool append; + bool notify; + uint16_t ieBufferlength; + uint8_t *pAdditionIEBuffer; +} tSirUpdateIE, *tpSirUpdateIE; + +/* Message format for Update IE message sent to PE */ +typedef struct sSirUpdateIEsInd { + uint16_t msgType; + uint16_t msgLen; + tSirUpdateIE updateIE; + eUpdateIEsType updateType; +} tSirUpdateIEsInd, *tpSirUpdateIEsInd; + +/* Message format for requesting channel switch announcement to lower layers */ +typedef struct sSirDfsCsaIeRequest { + uint16_t msgType; + uint16_t msgLen; + uint8_t targetChannel; + uint8_t csaIeRequired; + uint8_t bssid[CDF_MAC_ADDR_SIZE]; + uint8_t ch_bandwidth; +} tSirDfsCsaIeRequest, *tpSirDfsCsaIeRequest; + +/* Indication from lower layer indicating the completion of first beacon send + * after the beacon template update + */ +typedef struct sSirFirstBeaconTxCompleteInd { + uint16_t messageType; /* eWNI_SME_MISSED_BEACON_IND */ + uint16_t length; + uint8_t bssIdx; +} tSirFirstBeaconTxCompleteInd, *tpSirFirstBeaconTxCompleteInd; + +typedef struct sSirSmeCSAIeTxCompleteRsp { + uint8_t sessionId; + uint8_t chanSwIeTxStatus; +} tSirSmeCSAIeTxCompleteRsp, *tpSirSmeCSAIeTxCompleteRsp; + +/* Thermal Mitigation*/ + +typedef struct { + uint16_t minTempThreshold; + uint16_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]; + uint8_t thermalCurrLevel; + uint8_t thermalMgmtEnabled; + uint32_t throttlePeriod; +} t_thermal_mgmt, *tp_thermal_mgmt; + +typedef struct sSirTxPowerLimit { + /* Thermal limits for 2g and 5g */ + uint32_t txPower2g; + uint32_t txPower5g; +} tSirTxPowerLimit; + +/* notify MODEM power state to FW */ +typedef struct { + uint32_t param; +} tSirModemPowerStateInd, *tpSirModemPowerStateInd; + +#ifdef WLAN_FEATURE_STATS_EXT +typedef struct { + uint32_t vdev_id; + uint32_t event_data_len; + uint8_t event_data[]; +} tSirStatsExtEvent, *tpSirStatsExtEvent; +#endif + +#ifdef WLAN_FEATURE_NAN +typedef struct { + uint32_t event_data_len; + uint8_t event_data[]; +} tSirNanEvent, *tpSirNanEvent; +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +typedef struct sSirSmeRoamOffloadSynchInd { + uint16_t messageType; /*eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */ + uint16_t length; + uint16_t beaconProbeRespOffset; + uint16_t beaconProbeRespLength; + uint16_t reassocRespOffset; + uint16_t reassocRespLength; + uint8_t isBeacon; + uint8_t roamedVdevId; + tSirMacAddr bssId; + int8_t txMgmtPower; + uint32_t authStatus; + uint8_t rssi; + uint8_t roamReason; + uint32_t chan_freq; + uint8_t kck[SIR_KCK_KEY_LEN]; + uint8_t kek[SIR_KEK_KEY_LEN]; + uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; + tpSirBssDescription bss_desc_ptr; +} roam_offload_synch_ind; + +typedef struct sSirSmeRoamOffloadSynchCnf { + uint8_t sessionId; +} tSirSmeRoamOffloadSynchCnf, *tpSirSmeRoamOffloadSynchCnf; + +typedef struct sSirSmeHOFailureInd { + uint8_t sessionId; +} tSirSmeHOFailureInd, *tpSirSmeHOFailureInd; + +struct roam_offload_synch_fail { + uint8_t session_id; +}; + +#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 { + struct cdf_mac_addr bssid; + + /* Low threshold */ + int32_t low; + + /* High threshold */ + int32_t high; +} tSirAPThresholdParam, *tpSirAPThresholdParam; + +typedef struct { + uint32_t requestId; + uint8_t sessionId; +} tSirGetExtScanCapabilitiesReqParams, *tpSirGetExtScanCapabilitiesReqParams; + +/** + * struct ext_scan_capabilities_response - extscan capabilities response data + * @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 { + uint32_t requestId; + uint8_t sessionId; + + /* + * 1 - return cached results and flush it + * 0 - return cached results and do not flush + */ + bool flush; +} tSirExtScanGetCachedResultsReqParams, *tpSirExtScanGetCachedResultsReqParams; + +typedef struct { + uint32_t requestId; + uint32_t status; +} tSirExtScanGetCachedResultsRspParams, *tpSirExtScanGetCachedResultsRspParams; + +typedef struct { + /* Time of discovery */ + uint64_t ts; + + /* Null terminated SSID */ + uint8_t ssid[SIR_MAC_MAX_SSID_LENGTH + 1]; + + struct cdf_mac_addr bssid; + + /* Frequency in MHz */ + uint32_t channel; + + /* RSSI in dBm */ + int32_t rssi; + + /* RTT in nanoseconds */ + uint32_t rtt; + + /* Standard deviation in rtt */ + uint32_t rtt_sd; + + /* Period advertised in the beacon */ + uint16_t beaconPeriod; + + /* Capabilities advertised in the beacon */ + uint16_t capability; + + uint16_t ieLength; + + uint8_t 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 */ + uint32_t channel; + + uint32_t dwellTimeMs; + + /* 0 => active + 1 => passive scan; ignored for DFS */ + bool passive; + + uint8_t 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 - wifi scan command request params + * @basePeriod: base timer period + * @maxAPperScan: max ap per scan + * @report_threshold_percent: report threshold + * in %, when buffer is this much full, wake up host + * @report_threshold_num_scans: report threshold number of scans + * in number of scans, wake up host after these many scans + * @requestId: request id + * @sessionId: session id + * @numBuckets: number of 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 + * @configuration_flags: configuration flags + * @buckets: buckets array + */ +typedef struct { + uint32_t basePeriod; + uint32_t maxAPperScan; + + uint32_t report_threshold_percent; + uint32_t report_threshold_num_scans; + + uint32_t requestId; + uint8_t sessionId; + uint32_t 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; + uint32_t status; +}; + +typedef struct { + uint32_t requestId; + uint8_t 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 { + uint32_t requestId; + uint8_t 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 { + uint32_t requestId; + uint8_t sessionId; + + /* Number of samples for averaging RSSI */ + uint32_t rssiSampleSize; + + /* Number of missed samples to confirm AP loss */ + uint32_t lostApSampleSize; + + /* Number of APs breaching threshold required for firmware + * to generate event + */ + uint32_t minBreaching; + + uint32_t numAp; + tSirAPThresholdParam ap[WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS]; +} tSirExtScanSetSigChangeReqParams, *tpSirExtScanSetSigChangeReqParams; + +typedef struct { + struct cdf_mac_addr bssid; + uint32_t channel; + uint32_t numOfRssi; + + /* Rssi history in db */ + int32_t rssi[]; +} tSirWifiSignificantChange, *tpSirWifiSignificantChange; + +typedef struct { + uint32_t requestId; + + bool moreData; + uint32_t numResults; + tSirWifiSignificantChange ap[]; +} tSirWifiSignificantChangeEvent, *tpSirWifiSignificantChangeEvent; + +typedef struct { + uint32_t requestId; + uint8_t sessionId; +} tSirExtScanResetSignificantChangeReqParams, +*tpSirExtScanResetSignificantChangeReqParams; + +typedef struct { + uint32_t requestId; + uint32_t numResultsAvailable; +} tSirExtScanResultsAvailableIndParams, *tpSirExtScanResultsAvailableIndParams; + +typedef struct { + uint32_t requestId; + uint32_t status; + uint8_t 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 { + uint32_t timer_val; +} tSirAutoShutdownCmdParams; + +typedef struct { + uint32_t shutdown_reason; +} tSirAutoShutdownEvtParams; +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +typedef struct { + uint32_t reqId; + uint8_t staId; + uint32_t mpduSizeThreshold; + uint32_t aggressiveStatisticsGathering; +} tSirLLStatsSetReq, *tpSirLLStatsSetReq; + +typedef struct { + uint32_t reqId; + uint8_t staId; + uint32_t paramIdMask; +} tSirLLStatsGetReq, *tpSirLLStatsGetReq; + +typedef struct { + uint32_t reqId; + uint8_t staId; + uint32_t statsClearReqMask; + uint8_t stopReq; +} tSirLLStatsClearReq, *tpSirLLStatsClearReq; + +typedef struct { + uint8_t 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; +}; + +/*--------------------------------------------------------------------------- + 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 assoc (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 */ + uint8_t mode; + /* interface mac address (self) */ + struct cdf_mac_addr macAddr; + /* tSirWifiConnectionState */ + /* connection state (valid for STA, CLI only) */ + uint8_t state; + /* tSirWifiRoamState */ + /* roaming state */ + uint32_t roaming; + /* WIFI_CAPABILITY_XXX (self) */ + uint32_t capabilities; + /* null terminated SSID */ + uint8_t ssid[33]; + /* bssid */ + struct cdf_mac_addr bssid; + /* country string advertised by AP */ + uint8_t apCountryStr[WNI_CFG_COUNTRY_CODE_LEN]; + /* country string for this association */ + uint8_t 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 */ + uint32_t preamble:3; + /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + uint32_t nss:2; + /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ + uint32_t bw:3; + /* OFDM/CCK rate code would be as per ieee std in units of 0.5mbps */ + /* HT/VHT it would be mcs index */ + uint32_t rateMcsIdx:8; + /* reserved */ + uint32_t reserved:16; + /* units of 100 Kbps */ + uint32_t bitrate; +} tSirWifiRate, *tpSirWifiRate; + +/* channel statistics */ +typedef struct { + /* channel */ + tSirWifiChannelInfo channel; + /* msecs the radio is awake (32 bits number accruing over time) */ + uint32_t onTime; + /* msecs the CCA register is busy (32 bits number accruing over time) */ + uint32_t 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) */ + uint32_t onTime; + /* msecs the radio is transmitting + * (32 bits number accruing over time) + */ + uint32_t txTime; + /* msecs the radio is in active receive + *(32 bits number accruing over time) + */ + uint32_t rxTime; + /* msecs the radio is awake due to all scan + * (32 bits number accruing over time) + */ + uint32_t onTimeScan; + /* msecs the radio is awake due to NAN + * (32 bits number accruing over time) + */ + uint32_t onTimeNbd; + /* msecs the radio is awake due to Gscan + * (32 bits number accruing over time) + */ + uint32_t onTimeGscan; + /* msecs the radio is awake due to roam?scan + * (32 bits number accruing over time) + */ + uint32_t onTimeRoamScan; + /* msecs the radio is awake due to PNO scan + * (32 bits number accruing over time) + */ + uint32_t onTimePnoScan; + /* msecs the radio is awake due to HS2.0 scans and GAS exchange + * (32 bits number accruing over time) + */ + uint32_t onTimeHs20; + /* number of channels */ + uint32_t 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) */ + uint32_t txMpdu; + /* number of received data pkts */ + uint32_t rxMpdu; + /* number of data packet losses (no ACK) */ + uint32_t mpduLost; + /* total number of data pkt retries * */ + uint32_t retries; + /* number of short data pkt retries */ + uint32_t retriesShort; + /* number of long data pkt retries */ + uint32_t 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 */ + struct cdf_mac_addr peerMacAddress; + /* peer WIFI_CAPABILITY_XXX */ + uint32_t capabilities; + /* number of rates */ + uint32_t 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) */ + uint32_t ac; + /* number of successfully transmitted unicast data pkts (ACK rcvd) */ + uint32_t txMpdu; + /* number of received unicast mpdus */ + uint32_t rxMpdu; + /* number of succesfully transmitted multicast data packets */ + /* STA case: implies ACK received from AP for the unicast */ + /* packet in which mcast pkt was sent */ + uint32_t txMcast; + /* number of received multicast data packets */ + uint32_t rxMcast; + /* number of received unicast a-mpdus */ + uint32_t rxAmpdu; + /* number of transmitted unicast a-mpdus */ + uint32_t txAmpdu; + /* number of data pkt losses (no ACK) */ + uint32_t mpduLost; + /* total number of data pkt retries */ + uint32_t retries; + /* number of short data pkt retries */ + uint32_t retriesShort; + /* number of long data pkt retries */ + uint32_t retriesLong; + /* data pkt min contention time (usecs) */ + uint32_t contentionTimeMin; + /* data pkt max contention time (usecs) */ + uint32_t contentionTimeMax; + /* data pkt avg contention time (usecs) */ + uint32_t contentionTimeAvg; + /* num of data pkts used for contention statistics */ + uint32_t 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 */ + uint32_t beaconRx; + /* access point mgmt frames received count from */ + /* connected AP (including Beacon) */ + uint32_t mgmtRx; + /* action frames received count */ + uint32_t mgmtActionRx; + /* action frames transmit count */ + uint32_t mgmtActionTx; + /* access Point Beacon and Management frames RSSI (averaged) */ + uint32_t rssiMgmt; + /* access Point Data Frames RSSI (averaged) from connected AP */ + uint32_t rssiData; + /* access Point ACK RSSI (averaged) from connected AP */ + uint32_t rssiAck; + /* number of peers */ + uint32_t num_peers; + /* + * Indicates how many peer_stats events will be sent depending on the + * num_peers. + */ + uint32_t num_peer_events; + /* number of ac */ + uint32_t num_ac; + /* Roaming Stat */ + uint32_t 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 + */ + uint32_t avg_bcn_spread_offset_high; + /* Lower 32 bits of averaged 64 bit beacon spread offset */ + uint32_t avg_bcn_spread_offset_low; + /* + * Takes value of 1 if AP leaks packets after sending an ACK for PM=1 + * otherwise 0 + */ + uint32_t is_leaky_ap; + /* + * Average number of frames received from AP after receiving the ACK + * for a frame with PM = 1 + */ + uint32_t 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. + */ + uint32_t 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 */ + uint32_t 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 { + uint32_t paramId; + uint8_t ifaceId; + uint32_t rspId; + uint32_t moreResultToFollow; + union { + uint32_t num_peers; + uint32_t num_radio; + }; + + uint32_t peer_event_number; + /* Variable length field - Do not add anything after this */ + uint8_t results[0]; +} tSirLLStatsResults, *tpSirLLStatsResults; + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +typedef struct sAniGetLinkStatus { + uint16_t msgType; /* message type is same as the request type */ + uint16_t msgLen; /* length of the entire request */ + uint8_t linkStatus; + uint8_t sessionId; +} tAniGetLinkStatus, *tpAniGetLinkStatus; + +#ifdef DHCP_SERVER_OFFLOAD +typedef struct { + uint32_t vdev_id; + uint32_t dhcpSrvOffloadEnabled; + uint32_t dhcpClientNum; + uint32_t dhcpSrvIP; +} tSirDhcpSrvOffloadInfo, *tpSirDhcpSrvOffloadInfo; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +typedef struct { + uint32_t reqId; + /* pattern identifier. 0: disconnected 1: connected */ + uint32_t pattern_id; + uint32_t led_x0; /* led flashing parameter0 */ + uint32_t led_x1; /* led flashing parameter1 */ +} tSirLedFlashingReq, *tpSirLedFlashingReq; +#endif +/* 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 + +/** + * 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) + +/* + * 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; + struct cdf_mac_addr curr_bssid; +}; + +#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_id - 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 send_extcap_ie - used to pass send_extcap_ie msg from SME to PE + * @type - MSG type + * @length - length of the message + * @seesion_id - session_id for which the message is intended for + * + * This structure is used to pass send_extcap_ie msg from SME to PE + */ +struct send_extcap_ie { + uint16_t msg_type; /* eWNI_SME_SET_IE_REQ */ + uint16_t length; + uint8_t session_id; +}; + +typedef void (*hw_mode_cb)(uint32_t status, uint32_t cfgd_hw_mode_index, + uint32_t num_vdev_mac_entries, + struct sir_vdev_mac_map *vdev_mac_map); +typedef void (*hw_mode_transition_cb)(uint32_t old_hw_mode_index, + uint32_t new_hw_mode_index, + uint32_t num_vdev_mac_entries, + struct sir_vdev_mac_map *vdev_mac_map); +typedef void (*dual_mac_cb)(uint32_t status, uint32_t scan_config, + uint32_t fw_mode_config); + +/** + * struct sir_nss_update_request + * @msgType: nss update msg type + * @msgLen: length of the msg + * @new_nss: new spatial stream value + * @vdev_id: session id + */ +struct sir_nss_update_request { + uint16_t msgType; + uint16_t msgLen; + uint8_t new_nss; + uint32_t vdev_id; +}; + +/** + * struct sir_beacon_tx_complete_rsp + * + * @session_id: session for which beacon update happened + * @tx_status: status of the beacon tx from FW + */ +struct sir_beacon_tx_complete_rsp { + uint8_t session_id; + uint8_t tx_status; +}; + +typedef void (*nss_update_cb)(void *context, uint8_t tx_status, uint8_t vdev_id, + uint8_t next_action); + +/** + * OCB structures + */ + +#define NUM_AC (4) +#define OCB_CHANNEL_MAX (5) + +struct sir_qos_params { + uint8_t aifsn; + uint8_t cwmin; + uint8_t cwmax; +}; + +/** + * 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; + struct sir_qos_params 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; +}; + +/** + * 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 +}; + +#endif /* __SIR_API_H */ diff --git a/core/mac/inc/sir_mac_prop_exts.h b/core/mac/inc/sir_mac_prop_exts.h new file mode 100644 index 000000000000..dd24a87904f4 --- /dev/null +++ b/core/mac/inc/sir_mac_prop_exts.h @@ -0,0 +1,119 @@ +/* + * 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 sir_mac_prop_exts.h contains the MAC protocol + * extensions to support ANI feature set. + * Author: Chandra Modumudi + * Date: 11/27/02 + */ +#ifndef __MAC_PROP_EXTS_H +#define __MAC_PROP_EXTS_H + +#include "sir_types.h" +#include "sir_api.h" +#include "ani_system_defs.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 { + uint8_t elementID; /* SIR_MAC_ANI_PROP_IE_EID */ + uint8_t length; + uint8_t oui[3]; /* ANI_OUI for Airgo products */ + uint8_t info[1]; +} tSirMacPropIE, *tpSirMacPropIE; + +typedef struct sSirMacPropRateSet { + uint8_t numPropRates; + uint8_t propRate[8]; +} tSirMacPropRateSet, *tpSirMacPropRateSet; + +#define SIR_PROP_VERSION_STR_MAX 20 +typedef struct sSirMacPropVersion { + uint32_t chip_rev; /* board, chipset info */ + uint8_t card_type; /* Type of Card */ + /* build version string */ + uint8_t build_version[SIR_PROP_VERSION_STR_MAX]; +} tSirMacPropVersion, *tpSirMacPropVersion; + +/* Default value for gLimRestoreCBNumScanInterval */ +#define LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT 2 + +/* generic proprietary IE structure definition */ +typedef struct sSirPropIEStruct { + uint8_t propRatesPresent:1; + uint8_t apNamePresent:1; + uint8_t loadBalanceInfoPresent:1; + uint8_t versionPresent:1; + uint8_t edcaParamPresent:1; + uint8_t capabilityPresent:1; + uint8_t propChannelSwitchPresent:1; + uint8_t triggerStaScanPresent:1; + uint8_t rsvd:8; + + tSirMacPropRateSet propRates; + tAniApName apName; /* used in beacon/probe only */ + uint16_t capability; /* capability bit map */ + tSirMacPropVersion version; + tSirMacEdcaParamSetIE edca; + uint8_t triggerStaScanEnable; + +} tSirPropIEStruct, *tpSirPropIEStruct; + +#endif /* __MAC_PROP_EXTS_H */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h new file mode 100644 index 000000000000..ccc2dcefbfad --- /dev/null +++ b/core/mac/inc/sir_mac_prot_def.h @@ -0,0 +1,2192 @@ +/* + * 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 sir_mac_prot_def.h contains the MAC/PHY protocol + * definitions used across various projects. + */ + +#ifndef __MAC_PROT_DEFS_H +#define __MAC_PROT_DEFS_H + +#include + +#include "cds_api.h" +#include "sir_types.h" +#include "wni_cfg.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_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_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 + +#ifdef ANI_SUPPORT_11H +#define SIR_MAC_ACTION_MEASURE_REQUEST_ID 0 +#define SIR_MAC_ACTION_MEASURE_REPORT_ID 1 +#define SIR_MAC_ACTION_TPC_REQUEST_ID 2 +#define SIR_MAC_ACTION_TPC_REPORT_ID 3 +#endif /* ANI_SUPPORT_11H */ +#define SIR_MAC_ACTION_CHANNEL_SWITCH_ID 4 + +#ifdef ANI_SUPPORT_11H +#define SIR_MAC_BASIC_MEASUREMENT_TYPE 0 +#define SIR_MAC_CCA_MEASUREMENT_TYPE 1 +#define SIR_MAC_RPI_MEASUREMENT_TYPE 2 +#endif /* ANI_SUPPORT_11H */ + +/* 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 + +#define NUM_OF_SOUNDING_DIMENSIONS 1 /*Nss - 1, (Nss = 2 for 2x2)*/ +/* 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_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 + +#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 /* TBD temp - change backto 18 */ +#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 +/* 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 + +#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(uint8_t) + 2 * sizeof(uint16_t) + sizeof(uint32_t) +\ + 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) (((uint8_t) x) | 2) +#define SIR_MAC_SET_MEAS_REQ_REQUEST(x) (((uint8_t) x) | 4) +#define SIR_MAC_SET_MEAS_REQ_REPORT(x) (((uint8_t) x) | 8) + +#define SIR_MAC_SET_MEAS_REPORT_LATE(x) (((uint8_t) x) | 1) +#define SIR_MAC_SET_MEAS_REPORT_INCAPABLE(x) (((uint8_t) x) | 2) +#define SIR_MAC_SET_MEAS_REPORT_REFUSE(x) (((uint8_t) 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_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) ((((uint16_t) x) & 0x0300) >> 8) +#define SIR_MAC_GET_FRAME_TYPE(x) ((((uint16_t) x) & 0x0C00) >> 8) +#define SIR_MAC_GET_FRAME_SUB_TYPE(x) ((((uint16_t) x) & 0xF000) >> 12) +#define SIR_MAC_GET_WEP_BIT_IN_FC(x) (((uint16_t) x) & 0x0040) +#define SIR_MAC_SET_PROT_VERSION(x) ((uint16_t) x) +#define SIR_MAC_SET_FRAME_TYPE(x) (((uint16_t) x) << 2) +#define SIR_MAC_SET_FRAME_SUB_TYPE(x) (((uint16_t) x) << 4) +#define SIR_MAC_SET_WEP_BIT_IN_FC(x) (((uint16_t) x) << 14) + +/* / Macro definitions for get/set on capabilityInfo bits */ +#define SIR_MAC_GET_ESS(x) (((uint16_t) x) & 0x0001) +#define SIR_MAC_GET_IBSS(x) ((((uint16_t) x) & 0x0002) >> 1) +#define SIR_MAC_GET_CF_POLLABLE(x) ((((uint16_t) x) & 0x0004) >> 2) +#define SIR_MAC_GET_CF_POLL_REQ(x) ((((uint16_t) x) & 0x0008) >> 3) +#define SIR_MAC_GET_PRIVACY(x) ((((uint16_t) x) & 0x0010) >> 4) +#define SIR_MAC_GET_SHORT_PREAMBLE(x) ((((uint16_t) x) & 0x0020) >> 5) +#define SIR_MAC_GET_SPECTRUM_MGMT(x) ((((uint16_t) x) & 0x0100) >> 8) +#define SIR_MAC_GET_QOS(x) ((((uint16_t) x) & 0x0200) >> 9) +#define SIR_MAC_GET_SHORT_SLOT_TIME(x) ((((uint16_t) x) & 0x0400) >> 10) +#define SIR_MAC_GET_APSD(x) ((((uint16_t) x) & 0x0800) >> 11) +#if defined WLAN_FEATURE_VOWIFI +#define SIR_MAC_GET_RRM(x) ((((uint16_t) x) & 0x1000) >> 12) +#endif +#define SIR_MAC_GET_BLOCK_ACK(x) ((((uint16_t) x) & 0xc000) >> CAPABILITY_INFO_DELAYED_BA_BIT) +#define SIR_MAC_SET_ESS(x) (((uint16_t) x) | 0x0001) +#define SIR_MAC_SET_IBSS(x) (((uint16_t) x) | 0x0002) +#define SIR_MAC_SET_CF_POLLABLE(x) (((uint16_t) x) | 0x0004) +#define SIR_MAC_SET_CF_POLL_REQ(x) (((uint16_t) x) | 0x0008) +#define SIR_MAC_SET_PRIVACY(x) (((uint16_t) x) | 0x0010) +#define SIR_MAC_SET_SHORT_PREAMBLE(x) (((uint16_t) x) | 0x0020) +#define SIR_MAC_SET_SPECTRUM_MGMT(x) (((uint16_t) x) | 0x0100) +#define SIR_MAC_SET_QOS(x) (((uint16_t) x) | 0x0200) +#define SIR_MAC_SET_SHORT_SLOT_TIME(x) (((uint16_t) x) | 0x0400) +#define SIR_MAC_SET_APSD(x) (((uint16_t) x) | 0x0800) +#if defined WLAN_FEATURE_VOWIFI +#define SIR_MAC_SET_RRM(x) (((uint16_t) x) | 0x1000) +#endif +#define SIR_MAC_SET_GROUP_ACK(x) (((uint16_t) x) | 0x4000) + +#ifdef WLAN_FEATURE_11AC +#define SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(x) ((((uint32_t) 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 */ + eSIR_MAC_TS_NOT_CREATED_STATUS = 47, /* 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_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 */ + eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON = 6, /* Class 2 frame received from nonauthenticated station */ + eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON = 7, /* Class 3 frame received from nonassociated station */ + 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 + eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE = 25, /* TDLS direct link teardown due to TDLS peer STA unreachable via the TDLS direct link */ + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON = 26, /* TDLS direct link teardown for unspecified reason */ +#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 struct sSirMacFrameCtl { + +#ifndef ANI_LITTLE_BIT_ENDIAN + + uint8_t subType:4; + uint8_t type:2; + uint8_t protVer:2; + + uint8_t order:1; + uint8_t wep:1; + uint8_t moreData:1; + uint8_t powerMgmt:1; + uint8_t retry:1; + uint8_t moreFrag:1; + uint8_t fromDS:1; + uint8_t toDS:1; + +#else + + uint8_t protVer:2; + uint8_t type:2; + uint8_t subType:4; + + uint8_t toDS:1; + uint8_t fromDS:1; + uint8_t moreFrag:1; + uint8_t retry:1; + uint8_t powerMgmt:1; + uint8_t moreData:1; + uint8_t wep:1; + uint8_t order:1; + +#endif + +} cdf_packed tSirMacFrameCtl, *tpSirMacFrameCtl; + +/* / Sequence control field */ +typedef struct sSirMacSeqCtl { + +#ifndef ANI_LITTLE_BIT_ENDIAN + + uint8_t seqNumLo:4; + uint8_t fragNum:4; + + uint8_t seqNumHi:8; + +#else + + uint8_t fragNum:4; + uint8_t seqNumLo:4; + uint8_t seqNumHi:8; + +#endif +} cdf_packed tSirMacSeqCtl, *tpSirMacSeqCtl; + +/* / QoS control field */ +typedef struct sSirMacQosCtl { + +#ifndef ANI_LITTLE_BIT_ENDIAN + + uint8_t rsvd:1; + uint8_t ackPolicy:2; + uint8_t esop_txopUnit:1; + uint8_t tid:4; + + uint8_t txop:8; + +#else + + uint8_t tid:4; + uint8_t esop_txopUnit:1; + uint8_t ackPolicy:2; + uint8_t rsvd:1; + + uint8_t txop:8; + +#endif +} cdf_packed tSirMacQosCtl, *tpSirMacQosCtl; + +/* / Length (in bytes) of MAC header in 3 address format */ +#define SIR_MAC_HDR_LEN_3A 24 + +typedef uint8_t tSirMacAddr[ETH_ALEN]; + +/* / 3 address MAC data header format (24/26 bytes) */ +typedef struct sSirMacDot3Hdr { + tSirMacAddr da; + tSirMacAddr sa; + uint16_t length; +} cdf_packed tSirMacDot3Hdr, *tpSirMacDot3Hdr; + +/* / 3 address MAC data header format (24/26 bytes) */ +typedef struct sSirMacDataHdr3a { + tSirMacFrameCtl fc; + uint8_t durationLo; + uint8_t durationHi; + tSirMacAddr addr1; + tSirMacAddr addr2; + tSirMacAddr addr3; + tSirMacSeqCtl seqControl; + tSirMacQosCtl qosControl; +} cdf_packed tSirMacDataHdr3a, *tpSirMacDataHdr3a; + +/* / Management header format */ +typedef struct sSirMacMgmtHdr { + tSirMacFrameCtl fc; + uint8_t durationLo; + uint8_t durationHi; + tSirMacAddr da; + tSirMacAddr sa; + tSirMacAddr bssId; + tSirMacSeqCtl seqControl; +} cdf_packed tSirMacMgmtHdr, *tpSirMacMgmtHdr; + +/* / ERP information field */ +typedef struct sSirMacErpInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t reserved:5; + uint8_t barkerPreambleMode:1; + uint8_t useProtection:1; + uint8_t nonErpPresent:1; +#else + uint8_t nonErpPresent:1; + uint8_t useProtection:1; + uint8_t barkerPreambleMode:1; + uint8_t reserved:5; +#endif +} cdf_packed tSirMacErpInfo, *tpSirMacErpInfo; + +/* / Capability information field */ +typedef struct sSirMacCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t immediateBA:1; + uint16_t delayedBA:1; + uint16_t dsssOfdm:1; + uint16_t rrm:1; + uint16_t apsd:1; + uint16_t shortSlotTime:1; + uint16_t qos:1; + uint16_t spectrumMgt:1; + uint16_t channelAgility:1; + uint16_t pbcc:1; + uint16_t shortPreamble:1; + uint16_t privacy:1; + uint16_t cfPollReq:1; + uint16_t cfPollable:1; + uint16_t ibss:1; + uint16_t ess:1; +#else + uint16_t ess:1; + uint16_t ibss:1; + uint16_t cfPollable:1; + uint16_t cfPollReq:1; + uint16_t privacy:1; + uint16_t shortPreamble:1; + uint16_t pbcc:1; + uint16_t channelAgility:1; + uint16_t spectrumMgt:1; + uint16_t qos:1; + uint16_t shortSlotTime:1; + uint16_t apsd:1; + uint16_t rrm:1; + uint16_t dsssOfdm:1; + uint16_t delayedBA:1; + uint16_t immediateBA:1; +#endif +} cdf_packed tSirMacCapabilityInfo, *tpSirMacCapabilityInfo; + +typedef struct sSirMacCfParamSet { + uint8_t cfpCount; + uint8_t cfpPeriod; + uint16_t cfpMaxDuration; + uint16_t cfpDurRemaining; +} cdf_packed tSirMacCfParamSet; + +typedef struct sSirMacTim { + uint8_t dtimCount; + uint8_t dtimPeriod; + uint8_t bitmapControl; + uint8_t bitmapLength; + uint8_t bitmap[251]; +} cdf_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 struct sSirMacRateSet { + uint8_t numRates; + uint8_t rate[SIR_MAC_RATESET_EID_MAX]; +} cdf_packed tSirMacRateSet; + +typedef struct sSirMacSSid { + uint8_t length; + uint8_t ssId[SIR_MAC_MAX_SSID_LENGTH]; +} cdf_packed tSirMacSSid; + +typedef struct sSirMacWpaInfo { + uint8_t length; + uint8_t info[SIR_MAC_MAX_IE_LENGTH]; +} cdf_packed tSirMacWpaInfo, *tpSirMacWpaInfo, +tSirMacRsnInfo, *tpSirMacRsnInfo; +typedef struct sSirMacWapiInfo { + uint8_t length; + uint8_t info[SIR_MAC_MAX_IE_LENGTH]; +} cdf_packed tSirMacWapiInfo, *tpSirMacWapiInfo, +tSirMacWapiInfo, *tpSirMacWapiInfo; + +typedef struct sSirMacFHParamSet { + uint16_t dwellTime; + uint8_t hopSet; + uint8_t hopPattern; + uint8_t hopIndex; +} tSirMacFHParamSet, *tpSirMacFHParamSet; + +typedef struct sSirMacIBSSParams { + uint16_t atim; +} tSirMacIBSSParams, *tpSirMacIBSSParams; + +typedef struct sSirMacRRMEnabledCap { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t reserved:6; + uint8_t AntennaInformation:1; + uint8_t BSSAvailAdmission:1; + uint8_t BssAvgAccessDelay:1; + uint8_t RSNIMeasurement:1; + uint8_t RCPIMeasurement:1; + uint8_t NeighborTSFOffset:1; + uint8_t MeasurementPilotEnabled:1; + uint8_t MeasurementPilot:3; + uint8_t nonOperatinChanMax:3; + uint8_t operatingChanMax:3; + uint8_t RRMMIBEnabled:1; + uint8_t APChanReport:1; + uint8_t triggeredTCM:1; + uint8_t TCMCapability:1; + uint8_t LCIAzimuth:1; + uint8_t LCIMeasurement:1; + uint8_t statistics:1; + uint8_t NoiseHistogram:1; + uint8_t ChannelLoad:1; + uint8_t FrameMeasurement:1; + uint8_t BeaconRepCond:1; + uint8_t BeaconTable:1; + uint8_t BeaconActive:1; + uint8_t BeaconPassive:1; + uint8_t repeated:1; + uint8_t parallel:1; + uint8_t NeighborRpt:1; + uint8_t LinkMeasurement:1; + uint8_t present; +#else + uint8_t present; + uint8_t LinkMeasurement:1; + uint8_t NeighborRpt:1; + uint8_t parallel:1; + uint8_t repeated:1; + uint8_t BeaconPassive:1; + uint8_t BeaconActive:1; + uint8_t BeaconTable:1; + uint8_t BeaconRepCond:1; + uint8_t FrameMeasurement:1; + uint8_t ChannelLoad:1; + uint8_t NoiseHistogram:1; + uint8_t statistics:1; + uint8_t LCIMeasurement:1; + uint8_t LCIAzimuth:1; + uint8_t TCMCapability:1; + uint8_t triggeredTCM:1; + uint8_t APChanReport:1; + uint8_t RRMMIBEnabled:1; + uint8_t operatingChanMax:3; + uint8_t nonOperatinChanMax:3; + uint8_t MeasurementPilot:3; + uint8_t MeasurementPilotEnabled:1; + uint8_t NeighborTSFOffset:1; + uint8_t RCPIMeasurement:1; + uint8_t RSNIMeasurement:1; + uint8_t BssAvgAccessDelay:1; + uint8_t BSSAvailAdmission:1; + uint8_t AntennaInformation:1; + uint8_t 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 struct sSirMacAciAifsn { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t rsvd:1; + uint8_t aci:2; + uint8_t acm:1; + uint8_t aifsn:4; +#else + uint8_t aifsn:4; + uint8_t acm:1; + uint8_t aci:2; + uint8_t rsvd:1; +#endif +} cdf_packed tSirMacAciAifsn; + +/* contention window size */ +typedef struct sSirMacCW { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t max:4; + uint8_t min:4; +#else + uint8_t min:4; + uint8_t max:4; +#endif +} cdf_packed tSirMacCW; + +typedef struct sSirMacEdcaParamRecord { + tSirMacAciAifsn aci; + tSirMacCW cw; + uint16_t txoplimit; +} cdf_packed tSirMacEdcaParamRecord; + +typedef struct sSirMacQosInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t uapsd:1; + uint8_t txopreq:1; + uint8_t qreq:1; + uint8_t qack:1; + uint8_t count:4; +#else + uint8_t count:4; + uint8_t qack:1; + uint8_t qreq:1; + uint8_t txopreq:1; + uint8_t uapsd:1; +#endif +} cdf_packed tSirMacQosInfo; + +typedef struct sSirMacQosInfoStation { +#ifdef ANI_LITTLE_BIT_ENDIAN + uint8_t acvo_uapsd:1; + uint8_t acvi_uapsd:1; + uint8_t acbk_uapsd:1; + uint8_t acbe_uapsd:1; + uint8_t qack:1; + uint8_t maxSpLen:2; + uint8_t moreDataAck:1; +#else + uint8_t moreDataAck:1; + uint8_t maxSpLen:2; + uint8_t qack:1; + uint8_t acbe_uapsd:1; + uint8_t acbk_uapsd:1; + uint8_t acvi_uapsd:1; + uint8_t acvo_uapsd:1; +#endif +} cdf_packed tSirMacQosInfoStation, *tpSirMacQosInfoStation; + +typedef struct sSirMacEdcaParamSetIE { + uint8_t type; + uint8_t length; + tSirMacQosInfo qosInfo; + uint8_t rsvd; + tSirMacEdcaParamRecord acbe; /* best effort */ + tSirMacEdcaParamRecord acbk; /* background */ + tSirMacEdcaParamRecord acvi; /* video */ + tSirMacEdcaParamRecord acvo; /* voice */ +} cdf_packed tSirMacEdcaParamSetIE; + +typedef struct sSirMacQoSParams { + uint8_t count; + uint16_t limit; + uint8_t CWmin[8]; + uint8_t AIFS[8]; +} cdf_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 struct sSirMacTSInfoTfc { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t burstSizeDefn:1; + uint8_t reserved:7; +#else + uint8_t reserved:7; + uint8_t burstSizeDefn:1; +#endif + +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t ackPolicy:2; + uint16_t userPrio:3; + uint16_t psb:1; + uint16_t aggregation:1; + uint16_t accessPolicy:2; + uint16_t direction:2; + uint16_t tsid:4; + uint16_t trafficType:1; +#else + uint16_t trafficType:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t accessPolicy:2; + uint16_t aggregation:1; + uint16_t psb:1; + uint16_t userPrio:3; + uint16_t ackPolicy:2; +#endif +} cdf_packed tSirMacTSInfoTfc; + +typedef struct sSirMacTSInfoSch { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t rsvd:7; + uint8_t schedule:1; +#else + uint8_t schedule:1; + uint8_t rsvd:7; +#endif +} cdf_packed tSirMacTSInfoSch; + +typedef struct sSirMacTSInfo { + tSirMacTSInfoTfc traffic; + tSirMacTSInfoSch schedule; +} cdf_packed tSirMacTSInfo; + +typedef struct sSirMacTspecIE { + uint8_t type; + uint8_t length; + tSirMacTSInfo tsinfo; + uint16_t nomMsduSz; + uint16_t maxMsduSz; + uint32_t minSvcInterval; + uint32_t maxSvcInterval; + uint32_t inactInterval; + uint32_t suspendInterval; + uint32_t svcStartTime; + uint32_t minDataRate; + uint32_t meanDataRate; + uint32_t peakDataRate; + uint32_t maxBurstSz; + uint32_t delayBound; + uint32_t minPhyRate; + uint16_t surplusBw; + uint16_t mediumTime; +} cdf_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 struct sSirMacTclasParamEthernet { + tSirMacAddr srcAddr; + tSirMacAddr dstAddr; + uint16_t type; +} cdf_packed tSirMacTclasParamEthernet; + +typedef struct sSirMacTclasParamIPv4 { + uint8_t version; + uint8_t srcIpAddr[4]; + uint8_t dstIpAddr[4]; + uint16_t srcPort; + uint16_t dstPort; + uint8_t dscp; + uint8_t protocol; + uint8_t rsvd; +} cdf_packed tSirMacTclasParamIPv4; + +#define SIR_MAC_TCLAS_IPV4 4 +#define SIR_MAC_TCLAS_IPV6 6 + +typedef struct sSirMacTclasParamIPv6 { + uint8_t version; + uint8_t srcIpAddr[16]; + uint8_t dstIpAddr[16]; + uint16_t srcPort; + uint16_t dstPort; + uint8_t flowLabel[3]; +} cdf_packed tSirMacTclasParamIPv6; + +typedef struct sSirMacTclasParam8021dq { + uint16_t tag; +} cdf_packed tSirMacTclasParam8021dq; + +typedef struct sSirMacTclasIE { + uint8_t type; + uint8_t length; + uint8_t userPrio; + uint8_t classifierType; + uint8_t classifierMask; +} cdf_packed tSirMacTclasIE; + +typedef struct sSirMacTsDelayIE { + uint8_t type; + uint8_t length; + uint32_t delay; +} cdf_packed tSirMacTsDelayIE; + +typedef struct sSirMacScheduleInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t rsvd:9; + uint16_t direction:2; + uint16_t tsid:4; + uint16_t aggregation:1; +#else + uint16_t aggregation:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t rsvd:9; +#endif +} cdf_packed tSirMacScheduleInfo; + +typedef struct sSirMacScheduleIE { + uint8_t type; + uint8_t length; + tSirMacScheduleInfo info; + uint32_t svcStartTime; + uint32_t svcInterval; + uint16_t maxSvcDuration; + uint16_t specInterval; +} cdf_packed tSirMacScheduleIE; + +typedef struct sSirMacQosCapabilityIE { + uint8_t type; + uint8_t length; + tSirMacQosInfo qosInfo; +} cdf_packed tSirMacQosCapabilityIE; + +typedef struct sSirMacQosCapabilityStaIE { + uint8_t type; + uint8_t length; + tSirMacQosInfoStation qosInfo; +} cdf_packed tSirMacQosCapabilityStaIE; + +typedef uint32_t tSirMacTimeStamp[2]; + +typedef uint16_t tSirMacBeaconInterval; + +typedef uint16_t tSirMacListenInterval; + +typedef uint8_t tSirMacChanNum; + +/* IE definitions */ +typedef struct sSirMacSSidIE { + uint8_t type; + tSirMacSSid ssId; +} cdf_packed tSirMacSSidIE; + +typedef struct sSirMacRateSetIE { + uint8_t type; + tSirMacRateSet supportedRateSet; +} cdf_packed tSirMacRateSetIE; + +typedef struct sSirMacDsParamSetIE { + uint8_t type; + uint8_t length; + tSirMacChanNum channelNumber; +} cdf_packed tSirMacDsParamSetIE; + +typedef struct sSirMacCfParamSetIE { + uint8_t type; + uint8_t length; + tSirMacCfParamSet cfParams; +} cdf_packed tSirMacCfParamSetIE; + +typedef struct sSirMacChanInfo { + tSirMacChanNum firstChanNum; + uint8_t numChannels; + int8_t maxTxPower; +} cdf_packed tSirMacChanInfo; + +typedef struct sSirMacNonErpPresentIE { + uint8_t type; + uint8_t length; + uint8_t erp; +} cdf_packed tSirMacNonErpPresentIE; + +typedef struct sSirMacPowerCapabilityIE { + uint8_t type; + uint8_t length; + uint8_t minTxPower; + uint8_t maxTxPower; +} tSirMacPowerCapabilityIE; + +typedef struct sSirMacSupportedChannelIE { + uint8_t type; + uint8_t length; + uint8_t supportedChannels[96]; +} tSirMacSupportedChannelIE; + +typedef struct sSirMacMeasReqField { + uint8_t channelNumber; + uint8_t measStartTime[8]; + uint16_t measDuration; +} tSirMacMeasReqField, *tpSirMacMeasReqField; + +typedef struct sSirMacMeasReqIE { + uint8_t type; + uint8_t length; + uint8_t measToken; + uint8_t measReqMode; + uint8_t 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 struct sSirMacVHTCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint32_t reserved1:2; + uint32_t txAntPattern:1; + uint32_t rxAntPattern:1; + uint32_t vhtLinkAdaptCap:2; + uint32_t maxAMPDULenExp:3; + uint32_t htcVHTCap:1; + uint32_t vhtTXOPPS:1; + uint32_t muBeamformeeCap:1; + uint32_t muBeamformerCap:1; + uint32_t numSoundingDim:3; + uint32_t csnofBeamformerAntSup:3; + uint32_t suBeamformeeCap:1; + uint32_t suBeamFormerCap:1; + uint32_t rxSTBC:3; + uint32_t txSTBC:1; + uint32_t shortGI160and80plus80MHz:1; + uint32_t shortGI80MHz:1; + uint32_t ldpcCodingCap:1; + uint32_t supportedChannelWidthSet:2; + uint32_t maxMPDULen:2; +#else + uint32_t maxMPDULen:2; + uint32_t supportedChannelWidthSet:2; + uint32_t ldpcCodingCap:1; + uint32_t shortGI80MHz:1; + uint32_t shortGI160and80plus80MHz:1; + uint32_t txSTBC:1; + uint32_t rxSTBC:3; + uint32_t suBeamFormerCap:1; + uint32_t suBeamformeeCap:1; + uint32_t csnofBeamformerAntSup:3; + uint32_t numSoundingDim:3; + uint32_t muBeamformerCap:1; + uint32_t muBeamformeeCap:1; + uint32_t vhtTXOPPS:1; + uint32_t htcVHTCap:1; + uint32_t maxAMPDULenExp:3; + uint32_t vhtLinkAdaptCap:2; + uint32_t rxAntPattern:1; + uint32_t txAntPattern:1; + uint32_t reserved1:2; +#endif +} cdf_packed tSirMacVHTCapabilityInfo; + +typedef struct sSirMacVHTTxSupDataRateInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved:3; + uint16_t txSupDataRate:13; +#else + uint16_t txSupDataRate:13; + uint16_t reserved:3; +#endif +} cdf_packed tSirMacVHTTxSupDataRateInfo; + +typedef struct sSirMacVHTRxSupDataRateInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved:3; + uint16_t rxSupDataRate:13; +#else + uint16_t rxSupDataRate:13; + uint16_t reserved:3; +#endif +} cdf_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 { + uint16_t rxMcsMap; + uint16_t rxHighest; + uint16_t txMcsMap; + uint16_t 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 { + uint32_t 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 { + uint16_t capInfo; + uint8_t ampduParamsInfo; + uint8_t suppMcsSet[16]; + uint16_t extendedHtCapInfo; + uint32_t txBFCapInfo; + uint8_t 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 /* Protetion 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, + eHT_CHANNEL_WIDTH_80MHZ = 2, + eHT_CHANNEL_WIDTH_160MHZ = 3, + eHT_CHANNEL_WIDTH_80P80MHZ = 4, + 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 struct sHtCaps { + uint16_t advCodingCap:1; + uint16_t supportedChannelWidthSet:1; + uint16_t mimoPowerSave:2; + uint16_t greenField:1; + uint16_t shortGI20MHz:1; + uint16_t shortGI40MHz:1; + uint16_t txSTBC:1; + uint16_t rxSTBC:2; + uint16_t delayedBA:1; + uint16_t maximalAMSDUsize:1; + uint16_t dsssCckMode40MHz:1; + uint16_t psmp:1; + uint16_t stbcControlFrame:1; + uint16_t lsigTXOPProtection:1; + uint8_t maxRxAMPDUFactor:2; + uint8_t mpduDensity:3; + uint8_t reserved1:3; + uint8_t supportedMCSSet[16]; + uint16_t pco:1; + uint16_t transitionTime:2; + uint16_t reserved2:5; + uint16_t mcsFeedback:2; + uint16_t reserved3:6; + uint32_t txBF:1; + uint32_t rxStaggeredSounding:1; + uint32_t txStaggeredSounding:1; + uint32_t rxZLF:1; + uint32_t txZLF:1; + uint32_t implicitTxBF:1; + uint32_t calibration:2; + uint32_t explicitCSITxBF:1; + uint32_t explicitUncompressedSteeringMatrix:1; + uint32_t explicitBFCSIFeedback:3; + uint32_t explicitUncompressedSteeringMatrixFeedback:3; + uint32_t explicitCompressedSteeringMatrixFeedback:3; + uint32_t csiNumBFAntennae:2; + uint32_t uncompressedSteeringMatrixBFAntennae:2; + uint32_t compressedSteeringMatrixBFAntennae:2; + uint32_t reserved4:7; + uint8_t antennaSelection:1; + uint8_t explicitCSIFeedbackTx:1; + uint8_t antennaIndicesFeedbackTx:1; + uint8_t explicitCSIFeedback:1; + uint8_t antennaIndicesFeedback:1; + uint8_t rxAS:1; + uint8_t txSoundingPPDUs:1; + uint8_t reserved5:1; + +} cdf_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 struct _BarControl { + +#ifndef ANI_BIG_BYTE_ENDIAN + + uint16_t barAckPolicy:1; + uint16_t multiTID:1; + uint16_t bitMap:1; + uint16_t rsvd:9; + uint16_t numTID:4; + +#else + uint16_t numTID:4; + uint16_t rsvd:9; + uint16_t bitMap:1; + uint16_t multiTID:1; + uint16_t barAckPolicy:1; + +#endif + +} cdf_packed barCtrlType; + +typedef struct _BARFrmStruct { + tSirMacFrameCtl fc; + uint16_t duration; + tSirMacAddr rxAddr; + tSirMacAddr txAddr; + barCtrlType barControl; + tSirMacSeqCtl ssnCtrl; +} cdf_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 +#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_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 struct sSirMacHTCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t lsigTXOPProtection:1; /* Dynamic state */ + uint16_t stbcControlFrame:1; /* Static via CFG */ + uint16_t psmp:1; /* Static via CFG */ + uint16_t dsssCckMode40MHz:1; /* Static via CFG */ + uint16_t maximalAMSDUsize:1; /* Static via CFG */ + uint16_t delayedBA:1; /* Static via CFG */ + uint16_t rxSTBC:2; /* Static via CFG */ + uint16_t txSTBC:1; /* Static via CFG */ + uint16_t shortGI40MHz:1; /* Static via CFG */ + uint16_t shortGI20MHz:1; /* Static via CFG */ + uint16_t greenField:1; /* Static via CFG */ + uint16_t mimoPowerSave:2; /* Dynamic state */ + uint16_t supportedChannelWidthSet:1; /* Static via CFG */ + uint16_t advCodingCap:1; /* Static via CFG */ +#else + uint16_t advCodingCap:1; + uint16_t supportedChannelWidthSet:1; + uint16_t mimoPowerSave:2; + uint16_t greenField:1; + uint16_t shortGI20MHz:1; + uint16_t shortGI40MHz:1; + uint16_t txSTBC:1; + uint16_t rxSTBC:2; + uint16_t delayedBA:1; + uint16_t maximalAMSDUsize:1; + uint16_t dsssCckMode40MHz:1; + uint16_t psmp:1; + uint16_t stbcControlFrame:1; + uint16_t lsigTXOPProtection:1; +#endif +} cdf_packed tSirMacHTCapabilityInfo; + +/* HT Parameters Info */ +typedef struct sSirMacHTParametersInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t reserved:3; + uint8_t mpduDensity:3; /* Dynamic state */ + uint8_t maxRxAMPDUFactor:2; /* Dynamic state */ +#else + uint8_t maxRxAMPDUFactor:2; + uint8_t mpduDensity:3; + uint8_t reserved:3; +#endif +} cdf_packed tSirMacHTParametersInfo; + +/* Extended HT Capabilities Info */ +typedef struct sSirMacExtendedHTCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved2:6; + uint16_t mcsFeedback:2; /* Static via CFG */ + uint16_t reserved1:5; + uint16_t transitionTime:2; /* Static via CFG */ + uint16_t pco:1; /* Static via CFG */ +#else + uint16_t pco:1; + uint16_t transitionTime:2; + uint16_t reserved1:5; + uint16_t mcsFeedback:2; + uint16_t reserved2:6; +#endif +} cdf_packed tSirMacExtendedHTCapabilityInfo; + +/* IEEE 802.11n/D7.0 - 7.3.2.57.4 */ +/* Part of the "supported MCS set field" */ +typedef struct sSirMacRxHighestSupportRate { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved:6; + uint16_t rate:10; +#else + uint16_t rate:10; + uint16_t reserved:6; +#endif +} cdf_packed tSirMacRxHighestSupportRate, *tpSirMacRxHighestSupportRate; + +/* Transmit Beam Forming Capabilities Info */ +typedef struct sSirMacTxBFCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint32_t reserved:7; + uint32_t compressedSteeringMatrixBFAntennae:2; /* Static via CFG */ + /* Static via CFG */ + uint32_t uncompressedSteeringMatrixBFAntennae:2; + uint32_t csiNumBFAntennae:2; /* Static via CFG */ + /* Static via CFG */ + uint32_t explicitCompressedSteeringMatrixFeedback:3; + /* Static via CFG */ + uint32_t explicitUncompressedSteeringMatrixFeedback:3; + uint32_t explicitBFCSIFeedback:3; /* Static via CFG */ + uint32_t explicitUncompressedSteeringMatrix:1; /* Static via CFG */ + uint32_t explicitCSITxBF:1; /* Static via CFG */ + uint32_t calibration:2; /* Static via CFG */ + uint32_t implicitTxBF:1; /* Static via CFG */ + uint32_t txZLF:1; /* Static via CFG */ + uint32_t rxZLF:1; /* Static via CFG */ + uint32_t txStaggeredSounding:1; /* Static via CFG */ + uint32_t rxStaggeredSounding:1; /* Static via CFG */ + uint32_t txBF:1; /* Static via CFG */ +#else + uint32_t txBF:1; + uint32_t rxStaggeredSounding:1; + uint32_t txStaggeredSounding:1; + uint32_t rxZLF:1; + uint32_t txZLF:1; + uint32_t implicitTxBF:1; + uint32_t calibration:2; + uint32_t explicitCSITxBF:1; + uint32_t explicitUncompressedSteeringMatrix:1; + uint32_t explicitBFCSIFeedback:3; + uint32_t explicitUncompressedSteeringMatrixFeedback:3; + uint32_t explicitCompressedSteeringMatrixFeedback:3; + uint32_t csiNumBFAntennae:2; + uint32_t uncompressedSteeringMatrixBFAntennae:2; + uint32_t compressedSteeringMatrixBFAntennae:2; + uint32_t reserved:7; +#endif +} cdf_packed tSirMacTxBFCapabilityInfo; + +/* Antenna Selection Capability Info */ +typedef struct sSirMacASCapabilityInfo { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t reserved2:1; + uint8_t txSoundingPPDUs:1; /* Static via CFG */ + uint8_t rxAS:1; /* Static via CFG */ + uint8_t antennaIndicesFeedback:1; /* Static via CFG */ + uint8_t explicitCSIFeedback:1; /* Static via CFG */ + uint8_t antennaIndicesFeedbackTx:1; /* Static via CFG */ + uint8_t explicitCSIFeedbackTx:1; /* Static via CFG */ + uint8_t antennaSelection:1; /* Static via CFG */ +#else + uint8_t antennaSelection:1; + uint8_t explicitCSIFeedbackTx:1; + uint8_t antennaIndicesFeedbackTx:1; + uint8_t explicitCSIFeedback:1; + uint8_t antennaIndicesFeedback:1; + uint8_t rxAS:1; + uint8_t txSoundingPPDUs:1; + uint8_t reserved2:1; +#endif +} cdf_packed tSirMacASCapabilityInfo; + +/* Additional HT IE Field1 */ +typedef struct sSirMacHTInfoField1 { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint8_t serviceIntervalGranularity:3; /* Dynamic state */ + uint8_t controlledAccessOnly:1; /* Static via CFG */ + uint8_t rifsMode:1; /* Dynamic state */ + uint8_t recommendedTxWidthSet:1; /* Dynamic state */ + uint8_t secondaryChannelOffset:2; /* Dynamic state */ +#else + uint8_t secondaryChannelOffset:2; + uint8_t recommendedTxWidthSet:1; + uint8_t rifsMode:1; + uint8_t controlledAccessOnly:1; + uint8_t serviceIntervalGranularity:3; +#endif +} cdf_packed tSirMacHTInfoField1; + +/* Additional HT IE Field2 */ +typedef struct sSirMacHTInfoField2 { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved:11; + uint16_t obssNonHTStaPresent:1; /*added for Obss */ + uint16_t transmitBurstLimit:1; + uint16_t nonGFDevicesPresent:1; + uint16_t opMode:2; /* Dynamic state */ +#else + uint16_t opMode:2; + uint16_t nonGFDevicesPresent:1; + uint16_t transmitBurstLimit:1; + uint16_t obssNonHTStaPresent:1; /*added for Obss */ + uint16_t reserved:11; +#endif +} cdf_packed tSirMacHTInfoField2; + +/* Additional HT IE Field3 */ +typedef struct sSirMacHTInfoField3 { +#ifndef ANI_LITTLE_BIT_ENDIAN + uint16_t reserved:4; + uint16_t pcoPhase:1; /* Dynamic state */ + uint16_t pcoActive:1; /* Dynamic state */ + uint16_t lsigTXOPProtectionFullSupport:1; /* Dynamic state */ + uint16_t secondaryBeacon:1; /* Dynamic state */ + uint16_t dualCTSProtection:1; /* Dynamic state */ + uint16_t basicSTBCMCS:7; /* Dynamic state */ +#else + uint16_t basicSTBCMCS:7; + uint16_t dualCTSProtection:1; + uint16_t secondaryBeacon:1; + uint16_t lsigTXOPProtectionFullSupport:1; + uint16_t pcoActive:1; + uint16_t pcoPhase:1; + uint16_t reserved:4; +#endif +} cdf_packed tSirMacHTInfoField3; + +typedef struct sSirMacProbeReqFrame { + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; +} cdf_packed tSirMacProbeReqFrame, *tpSirMacProbeReqFrame; + +typedef struct sSirMacProbeRspFrame { + tSirMacTimeStamp ts; + tSirMacBeaconInterval beaconInterval; + tSirMacCapabilityInfo capabilityInfo; + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; + tSirMacNonErpPresentIE nonErpPresent; + tSirMacDsParamSetIE dsParamsIE; + tSirMacCfParamSetIE cfParamsIE; +} cdf_packed tSirMacProbeRspFrame, *tpSirMacProbeRspFrame; + +typedef struct sSirMacAuthFrameBody { + uint16_t authAlgoNumber; + uint16_t authTransactionSeqNumber; + uint16_t authStatusCode; + uint8_t type; /* = SIR_MAC_CHALLENGE_TEXT_EID */ + uint8_t length; /* = SIR_MAC_AUTH_CHALLENGE_LENGTH */ + uint8_t challengeText[SIR_MAC_AUTH_CHALLENGE_LENGTH]; +} cdf_packed tSirMacAuthFrameBody, *tpSirMacAuthFrameBody; + +typedef struct sSirMacAuthenticationFrame { + tSirMacAuthFrameBody authFrameBody; +} cdf_packed tSirMacAuthFrame, *tpSirMacAuthFrame; + +typedef struct sSirMacAssocReqFrame { + tSirMacCapabilityInfo capabilityInfo; + uint16_t listenInterval; + tSirMacSSidIE ssIdIE; + tSirMacRateSetIE rateSetIE; + tSirMacRateSetIE extendedRateSetIE; +} cdf_packed tSirMacAssocReqFrame, *tpSirMacAssocReqFrame; + +typedef struct sSirMacAssocRspFrame { + tSirMacCapabilityInfo capabilityInfo; + uint16_t statusCode; + uint16_t aid; + tSirMacRateSetIE supportedRates; + tSirMacRateSetIE extendedRateSetIE; +} cdf_packed tSirMacAssocRspFrame, *tpSirMacAssocRspFrame; + +typedef struct sSirMacDisassocFrame { + uint16_t reasonCode; +} cdf_packed tSirMacDisassocFrame, *tpSirMacDisassocFrame; + +typedef struct sDSirMacDeauthFrame { + uint16_t reasonCode; +} cdf_packed tSirMacDeauthFrame, *tpSirMacDeauthFrame; + +/* / Common header for all action frames */ +typedef struct sSirMacActionFrameHdr { + uint8_t category; + uint8_t actionID; +} cdf_packed tSirMacActionFrameHdr, *tpSirMacActionFrameHdr; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +typedef struct sSirMacVendorSpecificFrameHdr { + uint8_t category; + uint8_t Oui[4]; +} cdf_packed tSirMacVendorSpecificFrameHdr, +*tpSirMacVendorSpecificFrameHdr; +#endif + +typedef struct sSirMacVendorSpecificPublicActionFrameHdr { + uint8_t category; + uint8_t actionID; + uint8_t Oui[4]; + uint8_t OuiSubType; + uint8_t dialogToken; +} cdf_packed tSirMacVendorSpecificPublicActionFrameHdr, +*tpSirMacVendorSpecificPublicActionFrameHdr; + +typedef struct sSirMacP2PActionFrameHdr { + uint8_t category; + uint8_t Oui[4]; + uint8_t OuiSubType; + uint8_t dialogToken; +} cdf_packed tSirMacP2PActionFrameHdr, *tpSirMacP2PActionFrameHdr; + +typedef struct sSirMacMeasActionFrameHdr { + uint8_t category; + uint8_t actionID; + uint8_t dialogToken; +} tSirMacMeasActionFrameHdr, *tpSirMacMeasActionFrameHdr; + +#ifdef ANI_SUPPORT_11H +typedef struct sSirMacTpcReqActionFrame { + tSirMacMeasActionFrameHdr actionHeader; + uint8_t type; + uint8_t length; +} tSirMacTpcReqActionFrame, *tpSirMacTpcReqActionFrame; +typedef struct sSirMacMeasReqActionFrame { + tSirMacMeasActionFrameHdr actionHeader; + tSirMacMeasReqIE measReqIE; +} tSirMacMeasReqActionFrame, *tpSirMacMeasReqActionFrame; +#endif + +#if defined WLAN_FEATURE_VOWIFI + +typedef struct sSirMacNeighborReportReq { + uint8_t dialogToken; + uint8_t ssid_present; + tSirMacSSid ssid; +} tSirMacNeighborReportReq, *tpSirMacNeighborReportReq; + +typedef struct sSirMacLinkReport { + uint8_t dialogToken; + uint8_t txPower; + uint8_t rxAntenna; + uint8_t txAntenna; + uint8_t rcpi; + uint8_t rsni; +} tSirMacLinkReport, *tpSirMacLinkReport; + +#define BEACON_REPORT_MAX_IES 224 /* Refer IEEE 802.11k-2008, Table 7-31d */ +typedef struct sSirMacBeaconReport { + uint8_t regClass; + uint8_t channel; + uint8_t measStartTime[8]; + uint8_t measDuration; + uint8_t phyType; + uint8_t bcnProbeRsp; + uint8_t rsni; + uint8_t rcpi; + tSirMacAddr bssid; + uint8_t antennaId; + uint32_t parentTSF; + uint8_t numIes; + uint8_t Ies[BEACON_REPORT_MAX_IES]; + +} tSirMacBeaconReport, *tpSirMacBeaconReport; + +#define RADIO_REPORTS_MAX_IN_A_FRAME 4 +typedef struct sSirMacRadioMeasureReport { + uint8_t token; + uint8_t refused; + uint8_t incapable; + uint8_t 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) ((((uint8_t)x) == SIR_MAC_RATE_6) || \ + (((uint8_t)x) == SIR_MAC_RATE_9) || \ + (((uint8_t)x) == SIR_MAC_RATE_12) || \ + (((uint8_t)x) == SIR_MAC_RATE_18) || \ + (((uint8_t)x) == SIR_MAC_RATE_24) || \ + (((uint8_t)x) == SIR_MAC_RATE_36) || \ + (((uint8_t)x) == SIR_MAC_RATE_48) || \ + (((uint8_t)x) == SIR_MAC_RATE_54)) + +#define sirIsBrate(x) ((((uint8_t)x) == SIR_MAC_RATE_1) || \ + (((uint8_t)x) == SIR_MAC_RATE_2) || \ + (((uint8_t)x) == SIR_MAC_RATE_5_5) || \ + (((uint8_t)x) == SIR_MAC_RATE_11)) + +#define sirIsGrate(x) ((((uint8_t)x) == SIR_MAC_RATE_1) || \ + (((uint8_t)x) == SIR_MAC_RATE_2) || \ + (((uint8_t)x) == SIR_MAC_RATE_5_5) || \ + (((uint8_t)x) == SIR_MAC_RATE_11) || \ + (((uint8_t)x) == SIR_MAC_RATE_6) || \ + (((uint8_t)x) == SIR_MAC_RATE_9) || \ + (((uint8_t)x) == SIR_MAC_RATE_12) || \ + (((uint8_t)x) == SIR_MAC_RATE_18) || \ + (((uint8_t)x) == SIR_MAC_RATE_24) || \ + (((uint8_t)x) == SIR_MAC_RATE_36) || \ + (((uint8_t)x) == SIR_MAC_RATE_48) || \ + (((uint8_t)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/core/mac/inc/sir_types.h b/core/mac/inc/sir_types.h new file mode 100644 index 000000000000..84032abae6e1 --- /dev/null +++ b/core/mac/inc/sir_types.h @@ -0,0 +1,236 @@ +/* + * 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 sir_types.h contains the common types + * + * Author: V. K. Kandarpa + * Date: 04/12/2002 + */ + +#ifndef __SIR_TYPES_H +#define __SIR_TYPES_H + +#include "cdf_types.h" + + +/** ------------------------------------------------------------------------ * + + \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; + +/** ------------------------------------------------------------------------ * + + \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; + +/* ********************************************** * +* * +* 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; + +#define IS_SIR_STATUS_SUCCESS(status) (eSIR_SUCCESS == status) +typedef enum { + HAL_STOP_TYPE_SYS_RESET, + HAL_STOP_TYPE_SYS_DEEP_SLEEP, + HAL_STOP_TYPE_RF_KILL, +} tHalStopType; + +#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 + +/* 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 + +#define STACFG_MAX_TC 8 + +#endif /* __SIR_TYPES_H */ diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h new file mode 100644 index 000000000000..9c279eada39e --- /dev/null +++ b/core/mac/inc/wni_api.h @@ -0,0 +1,539 @@ +/* + * 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 wni_api.h contains message definitions exported by + * Sirius software modules. + * NOTE: See projects/sirius/include/sir_api.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 + +/* / 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_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_ASSOC_IND, + eWNI_SME_ASSOC_CNF, + eWNI_SME_SWITCH_CHL_IND, + eWNI_SME_STOP_BSS_REQ, + eWNI_SME_STOP_BSS_RSP, + eWNI_SME_NEIGHBOR_BSS_IND, + eWNI_SME_DEAUTH_CNF, + eWNI_SME_MIC_FAILURE_IND, + eWNI_SME_ADDTS_REQ, + eWNI_SME_ADDTS_RSP, + eWNI_SME_DELTS_REQ, + eWNI_SME_DELTS_RSP, + eWNI_SME_DELTS_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_RSP, + eWNI_SME_MGMT_FRM_IND, + eWNI_SME_REMAIN_ON_CHN_RDY_IND, + eWNI_SME_SEND_ACTION_FRAME_IND, + eWNI_SME_ACTION_FRAME_SEND_CNF, + eWNI_SME_ABORT_REMAIN_ON_CHAN_IND, + eWNI_SME_UPDATE_NOA, + eWNI_SME_CLEAR_DFS_CHANNEL_LIST, + eWNI_SME_GET_SNR_REQ, + /* General Power Save Messages */ + eWNI_PMC_MSG_TYPES_BEGIN, + + /* WOWL Messages */ + eWNI_PMC_SMPS_STATE_IND, + +#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_RSP, + 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, +#ifdef FEATURE_WLAN_SCAN_PNO + eWNI_SME_PREF_NETWORK_FOUND_IND, +#endif /* FEATURE_WLAN_SCAN_PNO */ + + eWNI_SME_CHANGE_COUNTRY_CODE, + eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE, + eWNI_SME_MAX_ASSOC_EXCEEDED, +#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 mesages, please make sure that */ + /* SIR_LIM_ITC_MSG_TYPES_BEGIN is moved appropriately. It is set as */ + /* SIR_LIM_MSG_TYPES_BEGIN+0xB0 = 12B0 (which means max of 176 messages and */ + /* eWNI_SME_TDLS_DEL_STA_RSP = 175. */ + /* Should fix above issue to enable TDLS_INTERNAL */ + eWNI_SME_SET_BCN_FILTER_REQ, + eWNI_SME_RESET_AP_CAPS_CHANGED, +#ifdef WLAN_FEATURE_11W + eWNI_SME_UNPROT_MGMT_FRM_IND, +#endif +#ifdef WLAN_FEATURE_GTK_OFFLOAD + eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + eWNI_SME_CANDIDATE_FOUND_IND, /*ROAM candidate indication from FW */ + eWNI_SME_HANDOFF_REQ, /*upper layer requested handoff to driver in STA mode */ + eWNI_SME_ROAM_SCAN_OFFLOAD_RSP, /*Fwd the LFR scan offload rsp from FW to SME */ +#ifdef FEATURE_WLAN_LPHB + eWNI_SME_LPHB_IND, +#endif /* FEATURE_WLAN_LPHB */ + + eWNI_SME_GET_TSM_STATS_REQ, + eWNI_SME_GET_TSM_STATS_RSP, + eWNI_SME_TSM_IE_IND, + + eWNI_SME_READY_TO_SUSPEND_IND, +#ifdef FEATURE_WLAN_CH_AVOID + eWNI_SME_CH_AVOID_IND, +#endif /* FEATURE_WLAN_CH_AVOID */ + /* DFS EVENTS */ + eWNI_SME_DFS_RADAR_FOUND, /* RADAR found indication from DFS */ + eWNI_SME_CHANNEL_CHANGE_REQ, /* Channel Change Request from SAP */ + eWNI_SME_CHANNEL_CHANGE_RSP, /* Channel Change Response from WMA */ + eWNI_SME_START_BEACON_REQ, /* Start Beacon Transmission. */ + eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ, /* Transmit CSA IE in beacons */ + eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND, /* To indicate completion of CSA IE */ + /* update in beacons/probe rsp */ + eWNI_SME_STATS_EXT_EVENT, + eWNI_SME_LINK_SPEED_IND, /* Indicate linkspeed 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_DUMP_IND, + eWNI_SME_SET_HW_MODE_REQ, + eWNI_SME_SET_HW_MODE_RESP, + eWNI_SME_HW_MODE_TRANS_IND, + eWNI_SME_NSS_UPDATE_REQ, + eWNI_SME_NSS_UPDATE_RSP, + eWNI_SME_SCAN_CMD, + 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_SET_DUAL_MAC_CFG_REQ, + eWNI_SME_SET_DUAL_MAC_CFG_RESP, + eWNI_SME_ROC_CMD, + eWNI_SME_SET_THERMAL_LEVEL_IND, + eWNI_SME_SET_IE_REQ, + 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 paramter 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 paramter 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 + +/*---------------------------------------------------------------------*/ +/* 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/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h new file mode 100644 index 000000000000..76583d0d3ab7 --- /dev/null +++ b/core/mac/inc/wni_cfg.h @@ -0,0 +1,1572 @@ +/* + * 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 __WNICFG_H +#define __WNICFG_H + +/* + * Configuration Parameter ID for STA + */ + +enum { + WNI_CFG_STA_ID, + WNI_CFG_CF_POLLABLE, + WNI_CFG_CFP_PERIOD, + WNI_CFG_CFP_MAX_DURATION, + WNI_CFG_SSID, + WNI_CFG_BEACON_INTERVAL, + WNI_CFG_DTIM_PERIOD, + WNI_CFG_WEP_KEY_LENGTH, + WNI_CFG_WEP_DEFAULT_KEY_1, + WNI_CFG_WEP_DEFAULT_KEY_2, + WNI_CFG_WEP_DEFAULT_KEY_3, + WNI_CFG_WEP_DEFAULT_KEY_4, + WNI_CFG_WEP_DEFAULT_KEYID, + WNI_CFG_EXCLUDE_UNENCRYPTED, + WNI_CFG_RTS_THRESHOLD, + WNI_CFG_SHORT_RETRY_LIMIT, + WNI_CFG_LONG_RETRY_LIMIT, + WNI_CFG_FRAGMENTATION_THRESHOLD, + WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + WNI_CFG_JOIN_FAILURE_TIMEOUT, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, + WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + WNI_CFG_RA_PERIODICITY_TIMEOUT_IN_PS, + WNI_CFG_PS_ENABLE_BCN_FILTER, + WNI_CFG_PS_ENABLE_HEART_BEAT, + WNI_CFG_PS_ENABLE_RSSI_MONITOR, + WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + WNI_CFG_RF_SETTLING_TIME_CLK, + WNI_CFG_SUPPORTED_RATES_11B, + WNI_CFG_SUPPORTED_RATES_11A, + WNI_CFG_PHY_MODE, + WNI_CFG_DOT11_MODE, + WNI_CFG_OPERATIONAL_RATE_SET, + WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET, + WNI_CFG_LISTEN_INTERVAL, + WNI_CFG_VALID_CHANNEL_LIST, + WNI_CFG_CURRENT_CHANNEL, + WNI_CFG_DEFAULT_RATE_INDEX_5GHZ, + WNI_CFG_DEFAULT_RATE_INDEX_24GHZ, + WNI_CFG_RATE_ADAPTATION_TYPE, + WNI_CFG_FIXED_RATE, + WNI_CFG_FIXED_RATE_MULTICAST_24GHZ, + WNI_CFG_FIXED_RATE_MULTICAST_5GHZ, + WNI_CFG_RETRYRATE_POLICY, + WNI_CFG_RETRYRATE_SECONDARY, + WNI_CFG_RETRYRATE_TERTIARY, + WNI_CFG_APSD_ENABLED, + WNI_CFG_SHARED_KEY_AUTH_ENABLE, + WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE, + WNI_CFG_AUTHENTICATION_TYPE, + WNI_CFG_CF_POLL_REQUEST, + WNI_CFG_PRIVACY_ENABLED, + WNI_CFG_SHORT_PREAMBLE, + WNI_CFG_SHORT_SLOT_TIME, + WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY, + WNI_CFG_QOS_ENABLED, + WNI_CFG_HCF_ENABLED, + WNI_CFG_RSN_ENABLED, + WNI_CFG_MAX_NUM_PRE_AUTH, + WNI_CFG_PREAUTH_CLNUP_TIMEOUT, + WNI_CFG_RELEASE_AID_TIMEOUT, + WNI_CFG_HEART_BEAT_THRESHOLD, + WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + WNI_CFG_MANUFACTURER_OUI, + WNI_CFG_MANUFACTURER_NAME, + WNI_CFG_MODEL_NUMBER, + WNI_CFG_MODEL_NAME, + WNI_CFG_MANUFACTURER_PRODUCT_NAME, + WNI_CFG_MANUFACTURER_PRODUCT_VERSION, + WNI_CFG_11D_ENABLED, + WNI_CFG_MAX_TX_POWER_2_4, + WNI_CFG_MAX_TX_POWER_5, + WNI_CFG_NETWORK_DENSITY, + WNI_CFG_ADAPTIVE_THRESHOLD_ALGORITHM, + WNI_CFG_CURRENT_TX_ANTENNA, + WNI_CFG_CURRENT_RX_ANTENNA, + WNI_CFG_CURRENT_TX_POWER_LEVEL, + WNI_CFG_NEW_BSS_FOUND_IND, + WNI_CFG_PROPRIETARY_RATES_ENABLED, + WNI_CFG_AP_NODE_NAME, + WNI_CFG_COUNTRY_CODE, + WNI_CFG_11H_ENABLED, + WNI_CFG_WT_CNF_TIMEOUT, + WNI_CFG_PROXIMITY, + WNI_CFG_LOG_LEVEL, + WNI_CFG_OLBC_DETECT_TIMEOUT, + WNI_CFG_PROTECTION_ENABLED, + WNI_CFG_11G_PROTECTION_ALWAYS, + WNI_CFG_FORCE_POLICY_PROTECTION, + WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, + WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + WNI_CFG_11G_ONLY_POLICY, + WNI_CFG_PACKET_CLASSIFICATION, + WNI_CFG_WME_ENABLED, + WNI_CFG_ADDTS_RSP_TIMEOUT, + WNI_CFG_MAX_SP_LENGTH, + WNI_CFG_KEEP_ALIVE_STA_LIMIT_THRESHOLD, + WNI_CFG_SEND_SINGLE_SSID_ALWAYS, + WNI_CFG_WSM_ENABLED, + WNI_CFG_EDCA_PROFILE, + WNI_CFG_EDCA_ANI_ACBK_LOCAL, + WNI_CFG_EDCA_ANI_ACBE_LOCAL, + WNI_CFG_EDCA_ANI_ACVI_LOCAL, + WNI_CFG_EDCA_ANI_ACVO_LOCAL, + WNI_CFG_EDCA_ANI_ACBK, + WNI_CFG_EDCA_ANI_ACBE, + WNI_CFG_EDCA_ANI_ACVI, + WNI_CFG_EDCA_ANI_ACVO, + WNI_CFG_EDCA_WME_ACBK_LOCAL, + WNI_CFG_EDCA_WME_ACBE_LOCAL, + WNI_CFG_EDCA_WME_ACVI_LOCAL, + WNI_CFG_EDCA_WME_ACVO_LOCAL, + WNI_CFG_EDCA_WME_ACBK, + WNI_CFG_EDCA_WME_ACBE, + WNI_CFG_EDCA_WME_ACVI, + WNI_CFG_EDCA_WME_ACVO, + WNI_CFG_RDET_FLAG, + WNI_CFG_RADAR_CHANNEL_LIST, + WNI_CFG_LOCAL_POWER_CONSTRAINT, + WNI_CFG_ADMIT_POLICY, + WNI_CFG_ADMIT_BWFACTOR, + WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE, + WNI_CFG_CHANNEL_BONDING_MODE, + WNI_CFG_CB_SECONDARY_CHANNEL_STATE, + WNI_CFG_DYNAMIC_THRESHOLD_ZERO, + WNI_CFG_DYNAMIC_THRESHOLD_ONE, + WNI_CFG_DYNAMIC_THRESHOLD_TWO, + WNI_CFG_TRIG_STA_BK_SCAN, + WNI_CFG_DYNAMIC_PROFILE_SWITCHING, + WNI_CFG_SCAN_CONTROL_LIST, + WNI_CFG_MIMO_ENABLED, + WNI_CFG_BLOCK_ACK_ENABLED, + WNI_CFG_HT_RX_STBC, + WNI_CFG_HT_CAP_INFO, + WNI_CFG_HT_AMPDU_PARAMS, + WNI_CFG_SUPPORTED_MCS_SET, + WNI_CFG_EXT_HT_CAP_INFO, + WNI_CFG_TX_BF_CAP, + WNI_CFG_AS_CAP, + WNI_CFG_HT_INFO_FIELD1, + WNI_CFG_HT_INFO_FIELD2, + WNI_CFG_HT_INFO_FIELD3, + WNI_CFG_BASIC_MCS_SET, + WNI_CFG_CURRENT_MCS_SET, + WNI_CFG_GREENFIELD_CAPABILITY, + WNI_CFG_VHT_MAX_MPDU_LENGTH, + WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, + WNI_CFG_VHT_LDPC_CODING_CAP, + WNI_CFG_VHT_SHORT_GI_80MHZ, + WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, + WNI_CFG_VHT_TXSTBC, + WNI_CFG_VHT_RXSTBC, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, + WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS, + WNI_CFG_VHT_MU_BEAMFORMER_CAP, + WNI_CFG_VHT_MU_BEAMFORMEE_CAP, + WNI_CFG_VHT_TXOP_PS, + WNI_CFG_VHT_HTC_VHTC_CAP, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT, + WNI_CFG_VHT_LINK_ADAPTATION_CAP, + WNI_CFG_VHT_RX_ANT_PATTERN, + WNI_CFG_VHT_TX_ANT_PATTERN, + WNI_CFG_VHT_RX_MCS_MAP, + WNI_CFG_VHT_TX_MCS_MAP, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, + WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT2, + WNI_CFG_VHT_BASIC_MCS_SET, + WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT, + WNI_CFG_VHT_SS_UNDER_UTIL, + WNI_CFG_VHT_40MHZ_UTILIZATION, + WNI_CFG_VHT_80MHZ_UTILIZATION, + WNI_CFG_VHT_160MHZ_UTILIZATION, + WNI_CFG_MAX_AMSDU_LENGTH, + WNI_CFG_MPDU_DENSITY, + WNI_CFG_MAX_RX_AMPDU_FACTOR, + WNI_CFG_SHORT_GI_20MHZ, + WNI_CFG_SHORT_GI_40MHZ, + WNI_CFG_RIFS_ENABLED, + WNI_CFG_MAX_PS_POLL, + WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, + WNI_CFG_RSSI_FILTER_PERIOD, + WNI_CFG_MIN_RSSI_THRESHOLD, + WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE, + WNI_CFG_SCAN_IN_POWERSAVE, + WNI_CFG_IGNORE_DTIM, + WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE, + WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE, + WNI_CFG_WOWLAN_DEAUTH_ENABLE, + WNI_CFG_WOWLAN_DISASSOC_ENABLE, + WNI_CFG_WOWLAN_MAX_MISSED_BEACON, + WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD, + WNI_CFG_BG_SCAN_CHANNEL_LIST, + WNI_CFG_MAX_MEDIUM_TIME, + WNI_CFG_MAX_MPDUS_IN_AMPDU, + WNI_CFG_IBSS_AUTO_BSSID, + WNI_CFG_PROBE_REQ_ADDNIE_FLAG, + WNI_CFG_PROBE_REQ_ADDNIE_DATA, + WNI_CFG_PROBE_RSP_ADDNIE_FLAG, + WNI_CFG_PROBE_RSP_ADDNIE_DATA1, + WNI_CFG_PROBE_RSP_ADDNIE_DATA2, + WNI_CFG_PROBE_RSP_ADDNIE_DATA3, + WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, + WNI_CFG_ASSOC_RSP_ADDNIE_DATA, + WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG, + WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, + WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, + WNI_CFG_WPS_ENABLE, + WNI_CFG_WPS_STATE, + WNI_CFG_WPS_PROBE_REQ_FLAG, + WNI_CFG_WPS_VERSION, + WNI_CFG_WPS_REQUEST_TYPE, + WNI_CFG_WPS_CFG_METHOD, + WNI_CFG_WPS_UUID, + WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY, + WNI_CFG_WPS_PIMARY_DEVICE_OUI, + WNI_CFG_WPS_DEVICE_SUB_CATEGORY, + WNI_CFG_WPS_ASSOCIATION_STATE, + WNI_CFG_WPS_CONFIGURATION_ERROR, + WNI_CFG_WPS_DEVICE_PASSWORD_ID, + WNI_CFG_WPS_ASSOC_METHOD, + WNI_CFG_LOW_GAIN_OVERRIDE, + WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE, + WNI_CFG_RPE_POLLING_THRESHOLD, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG, + WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG, + WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS, + WNI_CFG_SINGLE_TID_RC, + WNI_CFG_RRM_ENABLED, + WNI_CFG_RRM_OPERATING_CHAN_MAX, + WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, + WNI_CFG_TX_PWR_CTRL_ENABLE, + WNI_CFG_MCAST_BCAST_FILTER_SETTING, + WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK, + WNI_CFG_DYNAMIC_PS_POLL_VALUE, + WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT, + WNI_CFG_TELE_BCN_WAKEUP_EN, + WNI_CFG_TELE_BCN_TRANS_LI, + WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS, + WNI_CFG_TELE_BCN_MAX_LI, + WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS, + WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS, + WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD, + WNI_CFG_ASSOC_STA_LIMIT, + WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL, + WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, + WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, + WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, + WNI_CFG_ENABLE_CLOSE_LOOP, + WNI_CFG_ENABLE_LTE_COEX, + WNI_CFG_AP_KEEP_ALIVE_TIMEOUT, + WNI_CFG_GO_KEEP_ALIVE_TIMEOUT, + WNI_CFG_ENABLE_MC_ADDR_LIST, + WNI_CFG_ENABLE_UC_FILTER, + WNI_CFG_ENABLE_LPWR_IMG_TRANSITION, + WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, + WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, + WNI_CFG_AP_LINK_MONITOR_TIMEOUT, + WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + WNI_CFG_TDLS_BUF_STA_ENABLED, + WNI_CFG_TDLS_PUAPSD_INACT_TIME, + WNI_CFG_TDLS_RX_FRAME_THRESHOLD, + WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + WNI_CFG_ENABLE_ADAPT_RX_DRAIN, + WNI_CFG_FLEX_CONNECT_POWER_FACTOR, + WNI_CFG_ANTENNA_DIVESITY, + WNI_CFG_GO_LINK_MONITOR_TIMEOUT, + WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, + WNI_CFG_CURRENT_RSSI, + WNI_CFG_RTT3_ENABLE, + WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL, + WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + WNI_CFG_IBSS_ATIM_WIN_SIZE, + WNI_CFG_DFS_MASTER_ENABLED, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + WNI_CFG_TDLS_WMM_MODE_ENABLED +}; +/* + * 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_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_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_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 2 +#define WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET_STADEF 2 + +#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 1 + +#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 0 + +#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 0 + +#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_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_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_RRM_ENABLED_STAMIN 0 +#define WNI_CFG_RRM_ENABLED_STAMAX 1 +#define WNI_CFG_RRM_ENABLED_STADEF 0 + +#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMIN 0 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMAX 8 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STADEF 0 + +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMIN 0 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMAX 8 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STADEF 0 + +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMIN 0 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STAMAX 1 +#define WNI_CFG_TX_PWR_CTRL_ENABLE_STADEF 1 + +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMIN 0 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STAMAX 3 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING_STADEF 0 + +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMIN 0 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STAMAX 255 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK_STADEF 0 + +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMIN 0 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STAMAX 255 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE_STADEF 0 + +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMIN 0 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STAMAX 80 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT_STADEF 0 + +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMIN 0 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STAMAX 1 +#define WNI_CFG_TELE_BCN_WAKEUP_EN_STADEF 0 + +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_TRANS_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_TRANS_LI_STADEF 3 + +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS_STADEF 10 + +#define WNI_CFG_TELE_BCN_MAX_LI_STAMIN 0 +#define WNI_CFG_TELE_BCN_MAX_LI_STAMAX 7 +#define WNI_CFG_TELE_BCN_MAX_LI_STADEF 5 + +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMIN 5 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STAMAX 255 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS_STADEF 15 + +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMIN 0 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STAMAX 255 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS_STADEF 7 + +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMIN 0 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX 1000 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STADEF 0 + +#define WNI_CFG_ASSOC_STA_LIMIT_STAMIN 1 +#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX 32 +#define WNI_CFG_ASSOC_STA_LIMIT_STADEF 10 + +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STADEF 1 + +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMIN 1 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STAMAX 252 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL_STADEF 11 + +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMIN 0 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STAMAX 5 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND_STADEF 0 + +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMIN 0 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STAMAX 65535 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD_STADEF 5 + +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMIN 0 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STAMAX 1 +#define WNI_CFG_ENABLE_CLOSE_LOOP_STADEF 0 + +#define WNI_CFG_ENABLE_LTE_COEX_STAMIN 0 +#define WNI_CFG_ENABLE_LTE_COEX_STAMAX 1 +#define WNI_CFG_ENABLE_LTE_COEX_STADEF 0 + +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMIN 1 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STAMAX 65535 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT_STADEF 20 + +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMIN 0 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STAMAX 1 +#define WNI_CFG_ENABLE_MC_ADDR_LIST_STADEF 0 + +#define WNI_CFG_ENABLE_UC_FILTER_STAMIN 0 +#define WNI_CFG_ENABLE_UC_FILTER_STAMAX 1 +#define WNI_CFG_ENABLE_UC_FILTER_STADEF 0 + +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMIN 0 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STAMAX 1 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION_STADEF 0 + +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMIN 0 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STAMAX 1 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED_STADEF 0 + +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMIN 0 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STAMAX 1 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP_STADEF 0 + +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMIN 1 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX 255 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF 3 + +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMIN 0 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STAMAX 15 +#define WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK_STADEF 0 + +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_BUF_STA_ENABLED_STADEF 0 + +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMIN 0 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STAMAX 10 +#define WNI_CFG_TDLS_PUAPSD_INACT_TIME_STADEF 0 + +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMIN 10 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STAMAX 20 +#define WNI_CFG_TDLS_RX_FRAME_THRESHOLD_STADEF 10 + +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMIN 0 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STAMAX 20 +#define WNI_CFG_PMF_SA_QUERY_MAX_RETRIES_STADEF 5 + +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN 10 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMAX 2000 +#define WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF 200 + +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMIN 0 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STAMAX 1 +#define WNI_CFG_ENABLE_ADAPT_RX_DRAIN_STADEF 1 + +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMIN 0 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STAMAX 9 +#define WNI_CFG_FLEX_CONNECT_POWER_FACTOR_STADEF 0 + +#define WNI_CFG_ANTENNA_DIVESITY_STAMIN 0 +#define WNI_CFG_ANTENNA_DIVESITY_STAMAX 3 +#define WNI_CFG_ANTENNA_DIVESITY_STADEF 0 + +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMIN 3 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX 50 +#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF 10 + +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN 100 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX 1000 +#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF 300 + +#define WNI_CFG_CURRENT_RSSI_STAMIN 0 +#define WNI_CFG_CURRENT_RSSI_STAMAX 127 +#define WNI_CFG_CURRENT_RSSI_STADEF 0 + +#define WNI_CFG_RTT3_ENABLE_STAMIN 0 +#define WNI_CFG_RTT3_ENABLE_STAMAX 1 +#define WNI_CFG_RTT3_ENABLE_STADEF 1 + +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMIN 0 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STAMAX 1 +#define WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL_STADEF 0 + +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_OFF_CHANNEL_ENABLED_STADEF 0 + +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMIN 0 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STAMAX 100 +#define WNI_CFG_IBSS_ATIM_WIN_SIZE_STADEF 0 + +#define WNI_CFG_DFS_MASTER_ENABLED_STAMIN 0 +#define WNI_CFG_DFS_MASTER_ENABLED_STAMAX 1 +#define WNI_CFG_DFS_MASTER_ENABLED_STADEF 0 + +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMIN 0 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STAMAX 1 +#define WNI_CFG_VHT_ENABLE_TXBF_20MHZ_STADEF 0 + +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMIN 0 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX 1 +#define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 + +#define CFG_PARAM_MAX_NUM 289 +#define CFG_STA_IBUF_MAX_SIZE 237 +#define CFG_STA_SBUF_MAX_SIZE 3199 + +#define CFG_STA_MAGIC_DWORD 0xbeefbeef + +#endif diff --git a/core/mac/src/cfg/cfgUtil/cfg.txt b/core/mac/src/cfg/cfgUtil/cfg.txt new file mode 100644 index 000000000000..85071b968781 --- /dev/null +++ b/core/mac/src/cfg/cfgUtil/cfg.txt @@ -0,0 +1,4474 @@ +* 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. + +* +* 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 65 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 33 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 33 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 33 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 33 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 + +* +* 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 + +* +* Calibration periodicity (minutes) +* + +WNI_CFG_CAL_PERIOD I 4 12 +V RW NP +HAL +2 10 5 +V RW NP +HAL +2 10 5 + +* +* Statistics collection periodicity (seconds) +* + +WNI_CFG_STATS_PERIOD I 4 12 +V RW NP +HAL +1 10 10 +V RW NP +HAL +1 10 10 + +* +* Calibration on/off control +* + +WNI_CFG_CAL_CONTROL I 4 12 +V RW NP +HAL +0 1 0 +V RW NP +HAL +0 1 0 + +#ENUM CAL_ON 0 +#ENUM CAL_OFF 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 0 +V RW NP +LIM +0 1 0 + +* +* 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 + +* +* 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 + +* +* RRM Enabled +* + +WNI_CFG_RRM_ENABLED I 4 8 +V RW NP +NONE +0 1 0 +V RW NP +NONE +0 1 0 + +* +* RRM measurement max duration. Section 11.10.3 802.11k-2008. +* Max Duration represented as maxDuration inTUs = 2^(*WNI_CFG_RRM_IN_CHAN_MAX - 4) * bcnIntvl +* Operating channel max measurement duration. +* + +WNI_CFG_RRM_OPERATING_CHAN_MAX I 4 8 +V RW NP +NONE +0 8 0 +V RW NP +NONE +0 8 0 + +* +* Non-Operating channel max measurement duration. +* + +WNI_CFG_RRM_NON_OPERATING_CHAN_MAX I 4 8 +V RW NP +NONE +0 8 0 +V RW NP +NONE +0 8 0 + +* +* 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/core/mac/src/cfg/cfgUtil/dot11f.frms b/core/mac/src/cfg/cfgUtil/dot11f.frms new file mode 100644 index 000000000000..04165e7907e4 --- /dev/null +++ b/core/mac/src/cfg/cfgUtil/dot11f.frms @@ -0,0 +1,3611 @@ +/* + * 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 uint8_t // 8, +%16-bit-type uint16_t // 16, +%32-bit-type uint32_t // & 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 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 VhtMembershipStatusArray(8) // 8.4.1.51 +{ + membershipStatusArray[8]; +} + +FF VhtUserPositionArray(16) // 8.4.1.52 +{ + userPositionArray[16]; +} + + +///////////////////////////////////////////////////////////////////////////// +// 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 Listen Channel Attribute + */ + +TLV ListenChannel ( TLV_LISTEN_CHANNEL ) ( 1 : 2 ) LSB +{ + countryString[3]; + regulatoryClass, 1; + channel, 1; +} + +/** + * \brief Extended Listen Attribute + */ + +TLV ExtendedListenTiming ( TLV_EXTENDED_LISTEN_TIMING ) ( 1 : 2 ) LSB +{ + availibilityPeriod, 2; + availibilityInterval, 2; +} + + +/** + * \brief P2P Manageability Attribute + */ + +TLV P2PManageability ( TLV_P2P_MANAGEABILITY ) ( 1 : 2 ) LSB +{ + manageability, 1; +} + + +/** + * \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 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 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 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 ht2040_bss_coexistence (EID_20_40_BSS_COEXISTENCE) +{ + // 20/40 BSS Coexistence Information + { + info_request: 1; + forty_mhz_intolerant: 1; + twenty_mhz_bsswidth_req: 1; + obss_scan_exemption_req: 1; + obss_scan_exemption_grant: 1; + unused: 3; + } +} + +IE ht2040_bss_intolerant_report (EID_20_40_BSS_INTOLERANT_REPORT) +{ + operating_class, 1; + channel_list[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 P2PDeAuth ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV MinorReasonCode; +} + + +MULTIIE P2PDisAssoc ( EID_VENDOR_SPECIFIC ) OUI( 0x50, 0x6F, 0x9A, 0x09 ) +{ + MANDATORYTLV MinorReasonCode; +} + +IE vendor2_ie (EID_VENDOR_SPECIFIC) OUI (0x00, 0x90, 0x4c) +{ + type, 1; + sub_type, 1; + OPTIE IE VHTCaps; + OPTIE IE VHTOperation; +} + +///////////////////////////////////////////////////////////////////////////// +// 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 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 vendor2_ie; + 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 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 vendor2_ie; + 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 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 vendor2_ie; + 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; + OPTIE vendor2_ie; +} // 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; + OPTIE vendor2_ie; +} // 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; + OPTIE vendor2_ie; +} // 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; + OPTIE vendor2_ie; +} // 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 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 vendor2_ie; + 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 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 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 ht2040_bss_coexistence; + 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 ht2040_bss_coexistence; + 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 ht2040_bss_coexistence; + 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 ht2040_bss_coexistence_mgmt_action_frame +{ + FF Category; + FF Action; + MANDIE ht2040_bss_coexistence; + MANDIE ht2040_bss_intolerant_report; +} + +FRAME TimingAdvertisementFrame // 8.3.3.15 +{ + FF TimeStamp; + FF Capabilities; + OPTIE Country; + OPTIE PowerConstraints; + OPTIE TimeAdvertisement; + OPTIE ExtCap; + OPTIE Vendor1IE; + OPTIE Vendor3IE; +} + +// 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/core/mac/src/cfg/cfg_api.c b/core/mac/src/cfg/cfg_api.c new file mode 100644 index 000000000000..3a0d689e29ee --- /dev/null +++ b/core/mac/src/cfg/cfg_api.c @@ -0,0 +1,948 @@ +/* + * 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 "cds_api.h" +#include "cfg_priv.h" +#include "cfg_debug.h" +#include "wma_types.h" +#include "cfg_api.h" + +/* --------------------------------------------------------------------- */ +/* Static Variables */ +/* ---------------------------------------------------------------------- */ +static tCfgCtl __g_cfg_entry[CFG_PARAM_MAX_NUM]; +static uint32_t __g_cfg_i_buf_min[CFG_STA_IBUF_MAX_SIZE]; +static uint32_t __g_cfg_i_buf_max[CFG_STA_IBUF_MAX_SIZE]; +static uint32_t __g_cfg_i_buf[CFG_STA_IBUF_MAX_SIZE]; +static uint8_t __g_cfg_s_buf[CFG_STA_SBUF_MAX_SIZE]; +static uint8_t __g_s_buffer[CFG_MAX_STR_LEN]; +static uint32_t __g_param_list[WNI_CFG_MAX_PARAM_NUM + + WNI_CFG_GET_PER_STA_STAT_RSP_NUM]; + +static void notify(tpAniSirGlobal, uint16_t, uint32_t); + +typedef enum { + eRF_BAND_UNKNOWN = 0, + eRF_BAND_2_4_GHZ = 1, + eRF_BAND_5_GHZ = 2 +} eRfBandMode; + +extern cfgstatic_string cfg_static_string[CFG_MAX_STATIC_STRING]; +extern cgstatic cfg_static[CFG_PARAM_MAX_NUM] ; + +/* --------------------------------------------------------------------- */ +uint32_t cfg_need_restart(tpAniSirGlobal pMac, uint16_t cfgId) +{ + if (!pMac->cfg.gCfgEntry) { + PELOGE(cfg_log(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } + return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RESTART); +} + +void cfg_get_strindex(tpAniSirGlobal pMac, uint16_t cfgId) +{ + uint16_t i = 0; + + for (i = 0; i < CFG_MAX_STATIC_STRING; i++) { + if (cfgId == cfg_static_string[i].cfgId) + break; + } + if (i == CFG_MAX_STATIC_STRING) { + PELOGE(cfg_log(pMac, LOGE, FL("Entry not found for cfg id :%d"), cfgId);) + cfg_static[cfgId].pStrData = NULL; + return; + } + cfg_static[cfgId].pStrData = &cfg_static_string[i]; +} +/* --------------------------------------------------------------------- */ +uint32_t cfg_need_reload(tpAniSirGlobal pMac, uint16_t cfgId) +{ + if (!pMac->cfg.gCfgEntry) { + PELOGE(cfg_log(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } + return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RELOAD); +} + +/* --------------------------------------------------------------------- */ +tSirRetStatus cfg_init(tpAniSirGlobal pMac) +{ + uint16_t i = 0; + pMac->cfg.gCfgIBufMin = __g_cfg_i_buf_min; + pMac->cfg.gCfgIBufMax = __g_cfg_i_buf_max; + pMac->cfg.gCfgIBuf = __g_cfg_i_buf; + pMac->cfg.gCfgSBuf = __g_cfg_s_buf; + pMac->cfg.gSBuffer = __g_s_buffer; + pMac->cfg.gCfgEntry = __g_cfg_entry; + pMac->cfg.gParamList = __g_param_list; + + for (i = 0; i < CFG_PARAM_MAX_NUM; i++) { + if (!(cfg_static[i].control & CFG_CTL_INT)) { + cfg_get_strindex(pMac, i); + } else { + cfg_static[i].pStrData = NULL; + } + } + return (eSIR_SUCCESS); +} + +/* ---------------------------------------------------------------------- */ +void cfg_de_init(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; + pMac->cfg.gParamList = NULL; +} + +/* --------------------------------------------------------------------- */ +/** + * cfg_check_valid() + * + * 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 cfg_check_valid(tpAniSirGlobal pMac, uint16_t cfgId, + uint32_t *index) +{ + uint32_t control; + + if (cfgId >= CFG_PARAM_MAX_NUM) { + PELOGE(cfg_log(pMac, LOG3, FL("Invalid cfg id %d"), cfgId);) + return eSIR_CFG_INVALID_ID; + } + if (!pMac->cfg.gCfgEntry) { + PELOGE(cfg_log(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) { + PELOGE(cfg_log(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) + return eSIR_CFG_INVALID_ID; + } + + *index = control & CFG_BUF_INDX_MASK; + + if (*index >= CFG_STA_SBUF_MAX_SIZE) { + PELOGE(cfg_log(pMac, LOGE, FL("cfg index out of bounds %d"), + *index);) + return eSIR_CFG_INVALID_ID; + } + + return eSIR_SUCCESS; + +} /*** end cfg_check_valid() ***/ + +/* --------------------------------------------------------------------- */ +/** + * cfg_set_int() + * + * 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 + * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID + */ + +tSirRetStatus cfg_set_int(tpAniSirGlobal pMac, uint16_t cfgId, uint32_t value) +{ + uint32_t index; + uint32_t control; + uint32_t mask; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + if ((pMac->cfg.gCfgIBufMin[index] > value) || + (pMac->cfg.gCfgIBufMax[index] < value)) { + PELOGE(cfg_log (pMac, LOGE, FL( + "Value %d out of range [%d,%d] cfg id %d"), value, + pMac->cfg.gCfgIBufMin[index], + pMac->cfg.gCfgIBufMax[index], cfgId);) + return eSIR_CFG_INVALID_ID; + } else { + /* Write integer value */ + pMac->cfg.gCfgIBuf[index] = value; + + control = pMac->cfg.gCfgEntry[cfgId].control; + /* Update hardware if necessary */ + mask = control & CFG_CTL_NTF_MASK; + if ((mask & CFG_CTL_NTF_HW) != 0) + PELOGE(cfg_log(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 status; +} /*** end cfg_set_int ***/ + +/* --------------------------------------------------------------------- */ +/** + * wlan_cfg_get_int() + * + * 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_cfg_get_int(tpAniSirGlobal pMac, uint16_t cfgId, + uint32_t *pValue) +{ + uint32_t index; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + /* Get integer value */ + *pValue = pMac->cfg.gCfgIBuf[index]; + + return eSIR_SUCCESS; +} /*** end wlan_cfg_get_int() ***/ + +/* --------------------------------------------------------------------- */ +/** + * cfg_set_str() + * + * FUNCTION: + * This function is called to set a string parameter. + * + * LOGIC: + * This function invokes the cfg_set_str_notify function passing the notify + * bool 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 cfg_set_str_notify is invoked with the bool 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 CFG parameter length + * + */ + +tSirRetStatus cfg_set_str(tpAniSirGlobal pMac, uint16_t cfgId, uint8_t *pStr, + uint32_t length) +{ + return cfg_set_str_notify(pMac, cfgId, pStr, length, true); +} + +/* --------------------------------------------------------------------- */ +/** + * cfg_set_str_notify() + * + * 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 CFG parameter length + * + */ + +tSirRetStatus cfg_set_str_notify(tpAniSirGlobal pMac, uint16_t cfgId, + uint8_t *pStr, uint32_t length, + int notifyMod) +{ + uint8_t *pDst, *pDstEnd; + uint32_t index, paramLen, mask; + uint32_t control; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + pDst = &pMac->cfg.gCfgSBuf[index]; + paramLen = *pDst++; + control = pMac->cfg.gCfgEntry[cfgId].control; + if (length > paramLen) { + PELOGE(cfg_log(pMac, LOGE, FL( + "Invalid length %d (>%d) cfg id %d"), + length, paramLen, cfgId);) + return eSIR_CFG_INVALID_LEN; + } else { + *pDst++ = (uint8_t) 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(cfg_log(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 eSIR_SUCCESS; +} /*** end cfg_set_str_notify() ***/ + +/* --------------------------------------------------------------------- */ +/** + * wlan_cfg_get_str() + * + * 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 CFG parameter length + * + */ + +tSirRetStatus wlan_cfg_get_str(tpAniSirGlobal pMac, uint16_t cfgId, + uint8_t *pBuf, uint32_t *pLength) +{ + uint8_t *pSrc, *pSrcEnd; + uint32_t index; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + /* Get string */ + pSrc = &pMac->cfg.gCfgSBuf[index]; + pSrc++; /* skip over max length */ + if (*pLength < *pSrc) { + PELOGE(cfg_log(pMac, LOGE, FL( + "Invalid length %d (<%d) cfg id %d"), + *pLength, *pSrc, cfgId);) + return eSIR_CFG_INVALID_LEN; + } else { + *pLength = *pSrc++; /* save parameter length */ + pSrcEnd = pSrc + *pLength; + while (pSrc < pSrcEnd) + *pBuf++ = *pSrc++; + } + return eSIR_SUCCESS; +} /*** end wlan_cfg_get_str() ***/ + +/* --------------------------------------------------------------------- */ +/** + * wlan_cfg_get_str_max_len() + * + * 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_cfg_get_str_max_len(tpAniSirGlobal pMac, uint16_t cfgId, + uint32_t *pLength) +{ + uint32_t index; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + *pLength = pMac->cfg.gCfgSBuf[index]; + + return status; +} /*** end wlan_cfg_get_str_max_len() ***/ + +/* --------------------------------------------------------------------- */ +/** + * wlan_cfg_get_str_len() + * + * 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_cfg_get_str_len(tpAniSirGlobal pMac, uint16_t cfgId, + uint32_t *pLength) +{ + uint32_t index; + tSirRetStatus status; + + status = cfg_check_valid(pMac, cfgId, &index); + + if (eSIR_SUCCESS != status) + return status; + + *pLength = pMac->cfg.gCfgSBuf[index + 1]; + + return status; + +} /*** end wlan_cfg_get_str_len() ***/ + +/*------------------------------------------------------------- + \fn cfg_get_dot11d_transmit_power + \brief This function returns the regulatory max transmit power + \param pMac + \return tPowerdBm - Power + \-------------------------------------------------------------*/ +static tPowerdBm +cfg_get_dot11d_transmit_power(tpAniSirGlobal pMac, uint16_t cfgId, + uint32_t cfgLength, uint8_t channel) +{ + uint8_t *pCountryInfo = NULL; + uint8_t count = 0; + tPowerdBm maxTxPwr = WMA_MAX_TXPOWER_INVALID; + + /* At least one element is present */ + if (cfgLength < sizeof(tSirMacChanInfo)) { + PELOGE(cfg_log + (pMac, LOGE, + FL("Invalid CFGLENGTH %d while getting 11d txpower"), + cfgLength); + ) + goto error; + } + + pCountryInfo = cdf_mem_malloc(cfgLength); + if (NULL == pCountryInfo) { + cfg_log(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_cfg_get_str(pMac, cfgId, pCountryInfo, &cfgLength) != + eSIR_SUCCESS) { + cdf_mem_free(pCountryInfo); + pCountryInfo = NULL; + + cfg_log(pMac, LOGP, + FL + ("Failed to retrieve 11d configuration parameters while retrieving 11d tuples")); + goto error; + } + /* Identify the channel and maxtxpower */ + while (count <= (cfgLength - (sizeof(tSirMacChanInfo)))) { + uint8_t firstChannel, maxChannels; + + firstChannel = pCountryInfo[count++]; + maxChannels = pCountryInfo[count++]; + maxTxPwr = pCountryInfo[count++]; + + if ((channel >= firstChannel) && + (channel < (firstChannel + maxChannels))) { + break; + } + } + +error: + if (NULL != pCountryInfo) + cdf_mem_free(pCountryInfo); + + return maxTxPwr; +} + +/**---------------------------------------------------------------------- + \fn cfg_get_regulatory_max_transmit_power + + \brief Gets regulatory tx power on the current channel. + + \param pMac + \param channel + \param rfBand + -----------------------------------------------------------------------*/ +tPowerdBm cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, uint8_t channel) +{ + uint32_t cfgLength = 0; + uint16_t 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(cfg_log + (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(cfg_log + (pMac, LOG2, + FL + ("HAL: Reading CFG for 5.0 GHz channels to get regulatory max tx power")); + ) + break; + + case eRF_BAND_UNKNOWN: + default: + PELOG2(cfg_log + (pMac, LOG2, + FL("HAL: Invalid current working band for the device")); + ) + return WMA_MAX_TXPOWER_INVALID; /* Its return, not break. */ + } + + maxTxPwr = cfg_get_dot11d_transmit_power(pMac, cfgId, cfgLength, channel); + + return (maxTxPwr); +} + +/* --------------------------------------------------------------------- */ +/** + * cfg_get_capability_info + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +tSirRetStatus cfg_get_capability_info(tpAniSirGlobal pMac, uint16_t *pCap, + tpPESession sessionEntry) +{ + uint32_t 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 + cfg_log(pMac, LOGP, + FL("can't get capability, role is UNKNOWN!!")); + + if (LIM_IS_AP_ROLE(sessionEntry)) { + val = sessionEntry->privacy; + } else { + /* PRIVACY bit */ + if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != + eSIR_SUCCESS) { + cfg_log(pMac, LOGP, + FL("cfg get WNI_CFG_PRIVACY_ENABLED failed")); + return eSIR_FAILURE; + } + } + if (val) + pCapInfo->privacy = 1; + + /* Short preamble bit */ + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) { + cfg_log(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_cfg_get_int + (pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) + != eSIR_SUCCESS) { + cfg_log(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_cfg_get_int(pMac, WNI_CFG_11H_ENABLED, &val) != + eSIR_SUCCESS) { + cfg_log(pMac, LOGP, + FL("cfg get WNI_CFG_11H_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->spectrumMgt = 1; + } + /* QoS bit */ + if (wlan_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) { + cfg_log(pMac, LOGP, FL("cfg get WNI_CFG_QOS_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->qos = 1; + + /* APSD bit */ + if (wlan_cfg_get_int(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) { + cfg_log(pMac, LOGP, FL("cfg get WNI_CFG_APSD_ENABLED failed")); + return eSIR_FAILURE; + } + if (val) + pCapInfo->apsd = 1; + +#if defined WLAN_FEATURE_VOWIFI + if (LIM_IS_STA_ROLE(sessionEntry)) { + if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != + eSIR_SUCCESS) { + cfg_log(pMac, LOGP, + FL("cfg get WNI_CFG_RRM_ENABLED failed")); + return eSIR_FAILURE; + } +#if defined WLAN_VOWIFI_DEBUG + PELOGE(cfg_log(pMac, LOGE, "RRM = %d", val);) +#endif + if (val) + pCapInfo->rrm = 1; + } +#endif + /* DSSS-OFDM */ + /* FIXME : no config defined yet. */ + + /* Block ack bit */ + if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != + eSIR_SUCCESS) { + cfg_log(pMac, LOGP, + FL("cfg get WNI_CFG_BLOCK_ACK_ENABLED failed")); + return eSIR_FAILURE; + } + pCapInfo->delayedBA = + (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); + pCapInfo->immediateBA = + (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); + + return eSIR_SUCCESS; +} + +/* -------------------------------------------------------------------- */ +/** + * cfg_set_capability_info + * + * 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 cfg_set_capability_info(tpAniSirGlobal pMac, uint16_t caps) +{ +} + +/* --------------------------------------------------------------------- */ +/** + * cfg_cleanup() + * + * FUNCTION: + * CFG cleanup function. + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * This function must be called during system shutdown. + * + * @param None + * + * @return None. + * + */ + +void cfg_cleanup(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, uint16_t cfgId, uint32_t ntfMask) +{ + + tSirMsgQ mmhMsg; + + mmhMsg.type = SIR_CFG_PARAM_UPDATE_IND; + mmhMsg.bodyval = (uint32_t) cfgId; + mmhMsg.bodyptr = NULL; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + + if ((ntfMask & CFG_CTL_NTF_SCH) != 0) + sch_post_message(pMac, &mmhMsg); + + if ((ntfMask & CFG_CTL_NTF_LIM) != 0) + lim_post_msg_api(pMac, &mmhMsg); + + if ((ntfMask & CFG_CTL_NTF_HAL) != 0) + wma_post_ctrl_msg(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) { + cfg_log(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/core/mac/src/cfg/cfg_debug.c b/core/mac/src/cfg/cfg_debug.c new file mode 100644 index 000000000000..7d09c91763d1 --- /dev/null +++ b/core/mac/src/cfg/cfg_debug.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 cfg_debug.c + + \brief implementation for log Debug related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#include "cfg_debug.h" + +void cfg_log(tpAniSirGlobal pMac, uint32_t 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. */ + + log_debug(pMac, SIR_CFG_MODULE_ID, loglevel, pString, marker); + + va_end(marker); /* Reset variable arguments. */ + } +#endif +} diff --git a/core/mac/src/cfg/cfg_debug.h b/core/mac/src/cfg/cfg_debug.h new file mode 100644 index 000000000000..424152e6e9e0 --- /dev/null +++ b/core/mac/src/cfg/cfg_debug.h @@ -0,0 +1,51 @@ +/* + * 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 __CFG_DEBUG_H__ +#define __CFG_DEBUG_H__ + +#include "sir_debug.h" +#include "utils_api.h" +#include "lim_trace.h" + +#if !defined(__printf) +#define __printf(a, b) +#endif + +void __printf(3, 4) cfg_log(tpAniSirGlobal pMac, uint32_t loglevel, + const char *pString, ...); + +#endif diff --git a/core/mac/src/cfg/cfg_def.h b/core/mac/src/cfg/cfg_def.h new file mode 100644 index 000000000000..6239538ebcec --- /dev/null +++ b/core/mac/src/cfg/cfg_def.h @@ -0,0 +1,72 @@ +/* + * 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 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 + +#endif /* __CFGDEF_H */ diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c new file mode 100644 index 000000000000..00be55d6492e --- /dev/null +++ b/core/mac/src/cfg/cfg_param_name.c @@ -0,0 +1,326 @@ +/* + * 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. + */ + +/* + * DO NOT EDIT - This file is generated automatically + */ + +/* + * IMPORTANT: This file is for system that supports STA mode ONLY. + */ +#include "cfg_priv.h" + +unsigned char *g_cfg_param_name[] = { + (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 *)"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_THRESHOLD_HIGH", + (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 *)"RRM_ENABLED", + (unsigned char *)"RRM_OPERATING_CHAN_MAX", + (unsigned char *)"RRM_NON_OPERATING_CHAN_MAX", + (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/core/mac/src/cfg/cfg_priv.h b/core/mac/src/cfg/cfg_priv.h new file mode 100644 index 000000000000..78769f59c229 --- /dev/null +++ b/core/mac/src/cfg/cfg_priv.h @@ -0,0 +1,90 @@ +/* + * 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 "cfg_def.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 { + uint32_t hdrInfo; + uint32_t controlSize; + uint32_t iBufSize; + uint32_t sBufSize; +} tCfgBinHdr, *tpCfgBinHdr; + +/*--------------------------------------------------------------------*/ +/* Polaris HW counter access structure */ +/*--------------------------------------------------------------------*/ + +#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 cfg_send_host_msg(tpAniSirGlobal, uint16_t, uint32_t, uint32_t, + uint32_t *, uint32_t, uint32_t *); + +#endif /* __CFGPRIV_H */ diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c new file mode 100644 index 000000000000..0a477d0b805e --- /dev/null +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -0,0 +1,2607 @@ +/* + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/* + * This file contains CFG functions for processing host messages. + */ +#include "cds_api.h" +#include "ani_global.h" +#include "cfg_priv.h" +#include "cfg_debug.h" +#include "wma_types.h" + +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_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_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_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_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_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_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_RRM_ENABLED, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_RRM_ENABLED_STAMIN, + WNI_CFG_RRM_ENABLED_STAMAX, + WNI_CFG_RRM_ENABLED_STADEF}, + {WNI_CFG_RRM_OPERATING_CHAN_MAX, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMIN, + WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMAX, + WNI_CFG_RRM_OPERATING_CHAN_MAX_STADEF}, + {WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMIN, + WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMAX, + WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_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} +}; + + +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 proc_dnld_rsp(tpAniSirGlobal, uint16_t, uint32_t *); +static void proc_get_req(tpAniSirGlobal, uint16_t, uint32_t *); +static void proc_set_req(tpAniSirGlobal, uint16_t, uint32_t *); +static void proc_set_req_no_rsp(tpAniSirGlobal, uint16_t, uint32_t *); + +static uint8_t check_param(tpAniSirGlobal, uint16_t, uint32_t, uint32_t, + uint32_t *); +static void get_str_value(uint8_t *, uint8_t *, uint32_t); + +/*--------------------------------------------------------------------*/ +/* Module global variables */ +/*--------------------------------------------------------------------*/ + +/* CFG function table */ +void (*g_cfg_func[])(tpAniSirGlobal, uint16_t, uint32_t *) = { + proc_dnld_rsp, proc_get_req, proc_set_req, proc_set_req_no_rsp +}; + +/**--------------------------------------------------------------------- + * cfg_process_mb_msg() + * + ***FUNCTION: + * CFG mailbox message processing function. + * + ***LOGIC: + * + ***ASSUMPTIONS: + * None. + * + ***NOTE: + * + * @param pMsg Message pointer + * + * @return None. + * + */ +void cfg_process_mb_msg(tpAniSirGlobal pMac, tSirMbMsg *pMsg) +{ + uint16_t index; + uint16_t len; + uint32_t *pParam; + + /* Use type[7:0] as index to function table */ + index = CFG_GET_FUNC_INDX(pMsg->type); + + if (index >= CDF_ARRAY_SIZE(g_cfg_func)) { + cdf_mem_free(pMsg); + return; + } + len = pMsg->msgLen - WNI_CFG_MB_HDR_LEN; + pParam = ((uint32_t *) pMsg) + 1; + + /* Call processing function */ + g_cfg_func[index] (pMac, len, pParam); + + /* Free up buffer */ + cdf_mem_free(pMsg); + +} /*** end cfg_process_mb_msg() ***/ + +/**--------------------------------------------------------------------- + * proc_dnld_rsp() + * + * 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 proc_dnld_rsp(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam) +{ + int32_t i; + + uint32_t expLen, retVal, bufStart, bufEnd; + uint32_t *pSrc, *pDst, *pDstEnd; + uint32_t strSize, j; + uint8_t pStr[CFG_MAX_STR_LEN]; + tpCfgBinHdr pHdr; + uint32_t logLevel; + tSirMsgQ mmhMsg; + + /* First Dword must contain the AP or STA magic dword */ + PELOGW(cfg_log(pMac, LOGW, FL("CFG size %d bytes MAGIC dword is 0x%x"), + length, sir_read_u32_n((uint8_t *) pParam)); + ) + /* if the string is not correct, return failure */ + if (*pParam == CFG_STA_MAGIC_DWORD) { + } + + else { + PELOGE(cfg_log + (pMac, LOGE, FL("Invalid magic dword 0x%x"), + sir_read_u32_n((uint8_t *) 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(cfg_log + (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(cfg_log + (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(cfg_log + (pMac, LOGE, FL(" Total parameter count mismatch")); + ) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + + if (pHdr->iBufSize != pMac->cfg.gCfgMaxIBufSize) { + PELOGE(cfg_log + (pMac, LOGE, + FL(" Integer parameter count mismatch")); + ) + retVal = WNI_CFG_INVALID_LEN; + goto end; + } + /* Copy control array */ + pDst = (uint32_t *) 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; i < pMac->cfg.gCfgMaxIBufSize; i++) + if (pMac->cfg.gCfgIBuf[i] < pMac->cfg.gCfgIBufMin[i] || + pMac->cfg.gCfgIBuf[i] > pMac->cfg.gCfgIBufMax[i]) { + PELOGE(cfg_log + (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] = + (uint8_t) (bufEnd - bufStart - 2); + + PELOG1(cfg_log + (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) { + uint32_t paramId, paramLen, paramLenCeil4; + + if (strSize < 4) { + PELOGE(cfg_log + (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(cfg_log + (pMac, LOGE, + FL("Error parsing str defaults, rem %d bytes"), + strSize); + ) + PELOGE(cfg_log + (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] = (uint8_t) (*pSrc >> 24) & 0xff; + pStr[4 * j + 1] = (uint8_t) (*pSrc >> 16) & 0xff; + pStr[4 * j + 2] = (uint8_t) (*pSrc >> 8) & 0xff; + pStr[4 * j + 3] = (uint8_t) (*pSrc) & 0xff; + + pSrc++; + strSize -= 4; + } + + PELOG1(cfg_log + (pMac, LOG1, FL("set str id %d len %d"), paramId, + paramLen); + ) + + if (cfg_set_str(pMac, (uint16_t) paramId, pStr, paramLen) != + eSIR_SUCCESS) { + PELOGE(cfg_log + (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_cfg_get_int(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(cfg_log(pMac, LOG1, " Completed successfully");) + +end : + + if (retVal != WNI_CFG_SUCCESS) + pMac->cfg.gCfgStatus = CFG_FAILURE; + + /* Send response message to host */ + pMac->cfg.gParamList[WNI_CFG_DNLD_CNF_RES] = retVal; + cfg_send_host_msg(pMac, WNI_CFG_DNLD_CNF, WNI_CFG_DNLD_CNF_LEN, + WNI_CFG_DNLD_CNF_NUM, pMac->cfg.gParamList, 0, 0); + + /* notify WMA that the config has downloaded */ + mmhMsg.type = SIR_CFG_DOWNLOAD_COMPLETE_IND; + mmhMsg.bodyptr = NULL; + mmhMsg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + if (wma_post_ctrl_msg(pMac, &mmhMsg) != eSIR_SUCCESS) { + PELOGE(cfg_log(pMac, LOGE, FL("WMAPostMsgApi failed!"));) + } + +} /*** end procDnldRsp() ***/ + +/**--------------------------------------------------------------------- + * proc_get_req() + * + * 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 proc_get_req(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam) +{ + uint16_t cfgId, i; + uint32_t value, valueLen, result; + uint32_t *pValue; + + PELOG1(cfg_log(pMac, LOG1, FL("Rcvd cfg get request %d bytes"), length);) + for (i = 0; i < length / 4; i++) + PELOG2(cfg_log(pMac, LOG2, FL("[%2d] 0x%08x"), i, pParam[i]);) + + if (!pMac->cfg.gCfgStatus) { + cfgId = (uint16_t) sir_read_u32_n((uint8_t *) pParam); + PELOGE(cfg_log(pMac, LOGE, FL("CFG not ready, param %d"), cfgId);) + pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES] = + WNI_CFG_NOT_READY; + pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID] = cfgId; + pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN] = 0; + cfg_send_host_msg(pMac, WNI_CFG_GET_RSP, + WNI_CFG_GET_RSP_PARTIAL_LEN, WNI_CFG_GET_RSP_NUM, + pMac->cfg.gParamList, 0, 0); + } else { + /* Process all parameter ID's on the list */ + while (length >= sizeof(uint32_t)) { + cfgId = (uint16_t) *pParam++; + pValue = 0; + valueLen = 0; + + PELOG1(cfg_log + (pMac, LOG1, FL("Cfg get param %d"), cfgId); + ) + /* Check for valid parameter ID, etc... */ + if (check_param + (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_cfg_get_int(pMac, cfgId, &value) + == + eSIR_SUCCESS ? WNI_CFG_SUCCESS : + WNI_CFG_OTHER_ERROR); + pValue = &value; + valueLen = sizeof(uint32_t); + } else { + /* Get string parameter */ + valueLen = sizeof(pMac->cfg.gSBuffer); + result = + (wlan_cfg_get_str + (pMac, cfgId, pMac->cfg.gSBuffer, + &valueLen) + == eSIR_SUCCESS ? WNI_CFG_SUCCESS : + WNI_CFG_OTHER_ERROR); + pValue = + (uint32_t *) pMac->cfg.gSBuffer; + } + } else { + PELOGE(cfg_log + (pMac, LOGE, + FL("Check param failed, param %d"), + cfgId); + ) + result = WNI_CFG_INVALID_LEN; + } + + /* Send response message to host */ + pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES] = result; + pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID] = cfgId; + pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN] = valueLen; + + /* We need to round up buffer length to word-increment */ + valueLen = (((valueLen + 3) >> 2) << 2); + cfg_send_host_msg(pMac, WNI_CFG_GET_RSP, + WNI_CFG_GET_RSP_PARTIAL_LEN + valueLen, + WNI_CFG_GET_RSP_NUM, + pMac->cfg.gParamList, valueLen, pValue); + + /* Decrement length */ + length -= sizeof(uint32_t); + } + } + +} /*** end procGetReq() ***/ + +/**--------------------------------------------------------------------- + * proc_set_req_internal() + * + * 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 +proc_set_req_internal(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam, + bool fRsp) +{ + uint16_t cfgId, valueLen, valueLenRoundedUp4; + uint32_t value, result; + + PELOG1(cfg_log(pMac, LOGl, FL("Rcvd cfg set request %d bytes"), length);) + + if (!pMac->cfg.gCfgStatus) { + cfgId = (uint16_t) sir_read_u32_n((uint8_t *) pParam); + PELOG1(cfg_log(pMac, LOGW, FL("CFG not ready, param %d"), cfgId);) + pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES] = + WNI_CFG_NOT_READY; + pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID] = cfgId; + if (fRsp) { + cfg_send_host_msg(pMac, WNI_CFG_SET_CNF, + WNI_CFG_SET_CNF_LEN, WNI_CFG_SET_CNF_NUM, + pMac->cfg.gParamList, 0, 0); + } + } else { + /* Process all TLVs in buffer */ + while (length >= (sizeof(uint32_t) * 2)) { + cfgId = (uint16_t) *pParam++; + valueLen = (uint16_t) *pParam++; + length -= (sizeof(uint32_t) * 2); + /* value length rounded up to a 4 byte multiple */ + valueLenRoundedUp4 = (((valueLen + 3) >> 2) << 2); + + /* Check for valid request before proceeding */ + if (check_param + (pMac, cfgId, CFG_CTL_WE, WNI_CFG_RO_PARAM, + &result)) { + PELOG1(cfg_log + (pMac, LOGW, + (char *)g_cfg_param_name[cfgId]); + ) + /* Process integer parameter */ + if ((pMac->cfg.gCfgEntry[cfgId]. + control & CFG_CTL_INT) != 0) { + /* Set VALUE */ + if (valueLen != sizeof(uint32_t)) { + PELOGE(cfg_log + (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(cfg_log + (pMac, LOGW, + FL + ("Cfg set int %d len %d(%d) val %d"), + cfgId, valueLen, + valueLenRoundedUp4, + value); + ) + result = + (cfg_set_int + (pMac, cfgId, + value) == + eSIR_SUCCESS ? + WNI_CFG_SUCCESS : + WNI_CFG_OTHER_ERROR); + if (result == WNI_CFG_SUCCESS) { + if (cfg_need_restart + (pMac, cfgId)) { + result = + WNI_CFG_NEED_RESTART; + } else + if (cfg_need_reload + (pMac, cfgId)) { + result = + WNI_CFG_NEED_RELOAD; + } + } + } + } + /* Process string parameter */ + else { + if (valueLenRoundedUp4 > length) { + PELOGE(cfg_log + (pMac, LOGE, + FL + ("Invalid string length %d" + "in set param %d (tot %d)"), + valueLen, cfgId, + length); + ) + result = + WNI_CFG_INVALID_LEN; + } else { + get_str_value((uint8_t *) pParam, + pMac->cfg.gSBuffer, + valueLen); + PELOG1(cfg_log + (pMac, LOGW, + FL + ("Cfg set str %d len %d(%d) bytes"), + cfgId, valueLen, + valueLenRoundedUp4); + ) + result = + (cfg_set_str + (pMac, cfgId, + pMac->cfg.gSBuffer, + valueLen) == + eSIR_SUCCESS ? + WNI_CFG_SUCCESS : + WNI_CFG_OTHER_ERROR); + if (result == WNI_CFG_SUCCESS) { + if (cfg_need_restart + (pMac, cfgId)) { + result = + WNI_CFG_NEED_RESTART; + } else + if (cfg_need_reload + (pMac, cfgId)) { + result = + WNI_CFG_NEED_RELOAD; + } + } + } + } + } else { + PELOGE(cfg_log + (pMac, LOGE, + FL("Check param failed, param %d"), + cfgId); + ) + result = WNI_CFG_INVALID_LEN; + } + + /* Send confirm message to host */ + pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES] = result; + pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID] = cfgId; + if (fRsp) { + cfg_send_host_msg(pMac, WNI_CFG_SET_CNF, + WNI_CFG_SET_CNF_LEN, + WNI_CFG_SET_CNF_NUM, + pMac->cfg.gParamList, 0, 0); + } else { + PELOGW(cfg_log + (pMac, LOG2, " CFGID %d no rsp", cfgId); + ) + } + + if (valueLenRoundedUp4 > length) + length = 0; + else { + length -= valueLenRoundedUp4; + pParam += (valueLenRoundedUp4 >> 2); + } + } + } +} + +static void proc_set_req(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam) +{ + proc_set_req_internal(pMac, length, pParam, true); +} + +static void +proc_set_req_no_rsp(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam) +{ + proc_set_req_internal(pMac, length, pParam, false); +} + +/**--------------------------------------------------------------------- + * check_param() + * + * 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 uint8_t +check_param(tpAniSirGlobal pMac, uint16_t cfgId, uint32_t flag, + uint32_t failedResult, uint32_t *pResult) +{ + /* Check if parameter ID is out of bound */ + if (cfgId >= CFG_PARAM_MAX_NUM) { + PELOGE(cfg_log(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(cfg_log + (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(cfg_log + (pMac, LOGE, + FL("Param id %d wrong permissions %x"), + cfgId, + pMac->cfg.gCfgEntry[cfgId].control); + ) + * pResult = failedResult; + } else + return true; + } + } + return false; + +} /*** cfgParamCheck() ***/ + +/**--------------------------------------------------------------------- + * get_str_value() + * + * 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 get_str_value(uint8_t *pBuf, uint8_t *pValue, uint32_t length) +{ + uint8_t *pEnd; + + pEnd = pValue + length; + while (pValue < pEnd) + *pValue++ = *pBuf++; +} /*** end get_str_value() ***/ + +/**--------------------------------------------------------------------- + * process_cfg_download_req() + * + * FUNCTION: This function does the Cfg Download and is invoked + * only in the case of Prima or the Integrated SOC + * solutions. Not applicable to Volans or Libra + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMac: Pointer to Mac Structure + * + * @return None + * + */ + +void +process_cfg_download_req(tpAniSirGlobal pMac) +{ + int32_t i; + uint32_t index; + uint8_t *pDstTest, *pSrcTest; + uint8_t len; + cfgstatic_string *pStrCfg; + uint32_t bufStart, bufEnd; + uint32_t logLevel, retVal; + 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)) { + pStrCfg = (cfgstatic_string *)cfg_static[i]. + pStrData; + if (pStrCfg == NULL) { + PELOGE(cfg_log(pMac, LOGE, + FL("pStrCfg is NULL for CfigID : %d"), + i);) + continue; + } + index = sCount & CFG_BUF_INDX_MASK; + sCount += pStrCfg->maxLen + 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*/ + 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] = (uint8_t)(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; + } + + 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].cfgIMin; + pMac->cfg.gCfgIBufMax[index] = cfg_static[i].cfgIMax; + pMac->cfg.gCfgIBuf[index] = cfg_static[i].cfgIVal; + } else { + uint8_t maxSavedLen; + if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0) + continue; + if (index >= CFG_STA_SBUF_MAX_SIZE) + continue; + + pDstTest = &pMac->cfg.gCfgSBuf[index]; + pStrCfg = (cfgstatic_string *)cfg_static[i].pStrData; + pSrcTest = pStrCfg->data; + if ((pDstTest == NULL) || (pStrCfg == NULL) || + (pSrcTest == NULL)) + continue; + maxSavedLen = *pDstTest; + len = pStrCfg->length; + if (len > maxSavedLen) + continue; + *pDstTest++ = pStrCfg->maxLen; + *pDstTest++ = len; + while (len) { + *pDstTest++ = *pSrcTest++; + len--; + } + } + } + + /* Set the default log level based on config */ + wlan_cfg_get_int(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(cfg_log(pMac, LOG1, " Completed successfully");) + + pMac->cfg.gParamList[WNI_CFG_DNLD_CNF_RES] = retVal; + +} /*** end ProcessDownloadReq() ***/ diff --git a/core/mac/src/cfg/cfg_send_msg.c b/core/mac/src/cfg/cfg_send_msg.c new file mode 100644 index 000000000000..ebad7c739f7b --- /dev/null +++ b/core/mac/src/cfg/cfg_send_msg.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 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. + */ + +/* + * 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 "cds_api.h" +#include "cfg_priv.h" +#include "lim_trace.h" +#include "cfg_debug.h" + +/*--------------------------------------------------------------------*/ +/* ATTENTION: The functions contained in this module are to be used */ +/* by CFG module ONLY. */ +/*--------------------------------------------------------------------*/ + +/**--------------------------------------------------------------------- + * cfg_send_host_msg() + * + * 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 +cfg_send_host_msg(tpAniSirGlobal pMac, uint16_t msgType, uint32_t msgLen, + uint32_t paramNum, uint32_t *pParamList, uint32_t dataLen, + uint32_t *pData) +{ + uint32_t *pMsg, *pEnd; + tSirMsgQ mmhMsg; + + /* sanity */ + if ((paramNum > 0) && (NULL == pParamList)) { + PELOGE(cfg_log(pMac, LOGE, + FL + ("pParamList NULL when paramNum greater than 0!")); + ) + return; + } + if ((dataLen > 0) && (NULL == pData)) { + PELOGE(cfg_log(pMac, LOGE, + FL("pData NULL when dataLen greater than 0!")); + ) + return; + } + /* Allocate message buffer */ + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) { + PELOGE(cfg_log(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 = (uint16_t) 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(cfg_log(pMac, LOGE, FL("Unknown msg %d!"), (int)msgType);) + cdf_mem_free(pMsg); + return; + } + + /* Ship it */ + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + sys_process_mmh_msg(pMac, &mmhMsg); + +} /*** end cfg_send_host_msg() ***/ diff --git a/core/mac/src/dph/dph_hash_table.c b/core/mac/src/dph/dph_hash_table.c new file mode 100644 index 000000000000..e1bbe39f63ce --- /dev/null +++ b/core/mac/src/dph/dph_hash_table.c @@ -0,0 +1,459 @@ +/* + * 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 dph_hash_table.cc implements the member functions of + * DPH hash table class. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "cds_api.h" +#include "cfg_api.h" +#include "sch_api.h" +#include "dph_global.h" +#include "lim_debug.h" + +#include "wma_if.h" + +/* --------------------------------------------------------------------- */ +/** + * dphHashTableClass() + * + * FUNCTION: + * Constructor function + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void dph_hash_table_class_init(tpAniSirGlobal pMac, + dphHashTableClass *pDphHashTable) +{ + uint16_t i; + + for (i = 0; i < pDphHashTable->size; i++) { + pDphHashTable->pHashTable[i] = 0; + } + + for (i = 0; i < pDphHashTable->size; i++) { + pDphHashTable->pDphNodeArray[i].valid = 0; + pDphHashTable->pDphNodeArray[i].added = 0; + pDphHashTable->pDphNodeArray[i].assocId = i; + } + +} + +/* --------------------------------------------------------------------- */ +/** + * hash_function + * + * FUNCTION: + * Hashing function + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param staAddr MAC address of the station + * @return None + */ + +uint16_t hash_function(tpAniSirGlobal pMac, uint8_t staAddr[], uint16_t numSta) +{ + int i; + uint16_t sum = 0; + + for (i = 0; i < 6; i++) + sum += staAddr[i]; + + return (sum % numSta); +} + +/* --------------------------------------------------------------------- */ +/** + * dph_lookup_hash_entry + * + * 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 dph_lookup_hash_entry(tpAniSirGlobal pMac, uint8_t staAddr[], + uint16_t *pAssocId, + dphHashTableClass *pDphHashTable) +{ + tpDphHashNode ptr = NULL; + uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size); + + for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) { + if (dph_compare_mac_addr(staAddr, ptr->staAddr)) { + *pAssocId = ptr->assocId; + break; + } + } + return ptr; +} + +/* --------------------------------------------------------------------- */ +/** + * dph_get_hash_entry + * + * 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 dph_get_hash_entry(tpAniSirGlobal pMac, uint16_t 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 get_node(tpAniSirGlobal pMac, uint8_t assocId, + dphHashTableClass *pDphHashTable) +{ + return &pDphHashTable->pDphNodeArray[assocId]; +} + +/* --------------------------------------------------------------------- */ +/** + * dph_lookup_assoc_id + * + * 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 dph_lookup_assoc_id(tpAniSirGlobal pMac, uint16_t staIdx, + uint16_t *assocId, + dphHashTableClass *pDphHashTable) +{ + uint8_t i; + + for (i = 0; i < pDphHashTable->size; 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 dph_init_sta_state + \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 uint16_t assocId + \param uint8_t 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 dph_init_sta_state(tpAniSirGlobal pMac, tSirMacAddr staAddr, + uint16_t assocId, uint8_t validStaIdx, + dphHashTableClass *pDphHashTable) +{ + uint32_t val; + + tpDphHashNode pStaDs; + uint16_t staIdx = STA_INVALID_IDX; + + if (assocId >= pDphHashTable->size) { + PELOGE(lim_log(pMac, LOGE, FL("Invalid Assoc Id %d"), assocId);) + return NULL; + } + + pStaDs = get_node(pMac, (uint8_t) assocId, pDphHashTable); + staIdx = pStaDs->staIndex; + + PELOG1(lim_log + (pMac, LOG1, FL("Assoc Id %d, Addr %08X"), assocId, pStaDs); + ) + /* Clear the STA node except for the next pointer (last 4 bytes) */ + cdf_mem_set((uint8_t *) pStaDs, + sizeof(tDphHashNode) - sizeof(tpDphHashNode), 0); + + /* Initialize the assocId */ + pStaDs->assocId = assocId; + if (true == validStaIdx) + pStaDs->staIndex = staIdx; + else + pStaDs->staIndex = STA_INVALID_IDX; + + /* Initialize STA mac address */ + cdf_mem_copy(pStaDs->staAddr, staAddr, sizeof(tSirMacAddr)); + + /* Initialize fragmentation threshold */ + if (wlan_cfg_get_int(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, &val) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, + FL("could not retrieve fragmentation threshold")); + else + pStaDs->fragSize = (uint16_t) val; + + pStaDs->added = 1; + pStaDs->encPolicy = ENC_POLICY_NULL; + pStaDs->is_disassoc_deauth_in_progress = 0; +#ifdef WLAN_FEATURE_11W + pStaDs->last_assoc_received_time = 0; +#endif + pStaDs->valid = 1; + return pStaDs; +} + +/* --------------------------------------------------------------------- */ +/** + * dph_add_hash_entry + * + * 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 dph_add_hash_entry(tpAniSirGlobal pMac, tSirMacAddr staAddr, + uint16_t assocId, + dphHashTableClass *pDphHashTable) +{ + tpDphHashNode ptr, node; + uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size); + + PELOG1(lim_log(pMac, LOG1, FL("assocId %d index %d STA addr"), + assocId, index); dph_print_mac_addr(pMac, staAddr, LOG1); + ) + + if (assocId >= pDphHashTable->size) { + PELOGE(lim_log(pMac, LOGE, FL("invalid STA id %d"), assocId);) + return NULL; + } + + if (pDphHashTable->pDphNodeArray[assocId].added) { + PELOGE(lim_log(pMac, LOGE, FL("already added STA %d"), assocId);) + return NULL; + } + + for (ptr = pDphHashTable->pHashTable[index]; ptr; ptr = ptr->next) { + if (ptr == ptr->next) { + PELOGE(lim_log(pMac, LOGE, FL("Infinite Loop"));) + return NULL; + } + + if (dph_compare_mac_addr(staAddr, ptr->staAddr) + || ptr->assocId == assocId) + break; + } + + if (ptr) { + /* Duplicate entry */ + lim_log(pMac, LOGE, FL("assocId %d hashIndex %d entry exists"), + assocId, index); + return NULL; + } else { + if (dph_init_sta_state + (pMac, staAddr, assocId, false, pDphHashTable) == NULL) { + PELOGE(lim_log + (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; + } +} + +/* --------------------------------------------------------------------- */ +/** + * dph_delete_hash_entry + * + * 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 dph_delete_hash_entry(tpAniSirGlobal pMac, tSirMacAddr staAddr, + uint16_t assocId, + dphHashTableClass *pDphHashTable) +{ + tpDphHashNode ptr, prev; + uint16_t index = hash_function(pMac, staAddr, pDphHashTable->size); + + PELOG1(lim_log(pMac, LOG1, FL("assocId %d index %d STA addr"), + assocId, index); dph_print_mac_addr(pMac, staAddr, LOG1); + ) + + if (assocId >= pDphHashTable->size) { + PELOGE(lim_log(pMac, LOGE, FL("invalid STA id %d"), assocId);) + return eSIR_FAILURE; + } + + if (pDphHashTable->pDphNodeArray[assocId].added == 0) { + PELOGE(lim_log(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 (dph_compare_mac_addr(staAddr, ptr->staAddr)) + break; + if (prev == ptr) { + PELOGE(lim_log(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->is_disassoc_deauth_in_progress = 0; +#ifdef WLAN_FEATURE_11W + ptr->last_assoc_received_time = 0; +#endif + ptr->next = 0; + } else { + /* / Entry not present */ + PELOGE(lim_log(pMac, LOGE, FL("Entry not present STA addr")); + dph_print_mac_addr(pMac, staAddr, LOGE); + ) + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/** + * dph_print_mac_addr + * + * FUNCTION: + * Print a MAC address + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param addr MAC address + * @return None + */ + +void dph_print_mac_addr(tpAniSirGlobal pMac, uint8_t addr[], uint32_t level) +{ + lim_log(pMac, (uint16_t) level, FL("MAC ADDR = %d:%d:%d:%d:%d:%d"), + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +/* --------------------------------------------------------------------- */ + + diff --git a/core/mac/src/dph/dph_hash_table.h b/core/mac/src/dph/dph_hash_table.h new file mode 100644 index 000000000000..1a55f586a838 --- /dev/null +++ b/core/mac/src/dph/dph_hash_table.h @@ -0,0 +1,102 @@ +/* + * 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 dph_hash_table.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 "ani_global.h" +/* Compare MAC addresses, return true if same */ +static inline uint8_t dph_compare_mac_addr(uint8_t addr1[], uint8_t 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; + uint16_t size; +} dphHashTableClass; + +/* The hash table object */ +extern dphHashTableClass dphHashTable; + +/* Print MAC addresse */ +extern void dph_print_mac_addr(struct sAniSirGlobal *pMac, uint8_t addr[], + uint32_t); + +tpDphHashNode dph_lookup_hash_entry(tpAniSirGlobal pMac, uint8_t staAddr[], + uint16_t *pStaId, + dphHashTableClass *pDphHashTable); +tpDphHashNode dph_lookup_assoc_id(tpAniSirGlobal pMac, uint16_t staIdx, + uint16_t *assocId, + dphHashTableClass *pDphHashTable); + +/* Get a pointer to the hash node */ +extern tpDphHashNode dph_get_hash_entry(tpAniSirGlobal pMac, uint16_t staId, + dphHashTableClass *pDphHashTable); + +/* Add an entry to the hash table */ +extern tpDphHashNode dph_add_hash_entry(tpAniSirGlobal pMac, + tSirMacAddr staAddr, + uint16_t staId, + dphHashTableClass *pDphHashTable); + +/* Delete an entry from the hash table */ +extern tSirRetStatus dph_delete_hash_entry(tpAniSirGlobal pMac, + tSirMacAddr staAddr, uint16_t staId, + dphHashTableClass *pDphHashTable); + +void dph_hash_table_class_init(tpAniSirGlobal pMac, + dphHashTableClass *pDphHashTable); +/* Initialize STA state */ +extern tpDphHashNode dph_init_sta_state(tpAniSirGlobal pMac, + tSirMacAddr staAddr, + uint16_t staId, uint8_t validStaIdx, + dphHashTableClass *pDphHashTable); + +#endif diff --git a/core/mac/src/include/cfg_api.h b/core/mac/src/include/cfg_api.h new file mode 100644 index 000000000000..e165d5a3622d --- /dev/null +++ b/core/mac/src/include/cfg_api.h @@ -0,0 +1,131 @@ +/* + * 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. + */ + +/* + * + * 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 { + uint8_t keyMappingAddr[CDF_MAC_ADDR_SIZE]; + uint32_t wepOn; + uint8_t key[SIR_MAC_KEY_LENGTH]; + uint32_t status; +} tCfgWepKeyEntry; + +/*---------------------------------------------------------------------*/ +/* CFG function prototypes */ +/*---------------------------------------------------------------------*/ + +uint32_t cfg_need_restart(tpAniSirGlobal pMac, uint16_t cfgId); +uint32_t cfg_need_reload(tpAniSirGlobal pMac, uint16_t cfgId); + +/* / Process host message */ +void cfg_process_mb_msg(tpAniSirGlobal, tSirMbMsg *); + +/* / Set integer parameter value */ +tSirRetStatus cfg_set_int(tpAniSirGlobal, uint16_t, uint32_t); + +/* / Check if the parameter is valid */ +tSirRetStatus cfg_check_valid(tpAniSirGlobal, uint16_t, uint32_t *); + +/* / Get integer parameter value */ +tSirRetStatus wlan_cfg_get_int(tpAniSirGlobal, uint16_t, uint32_t *); + +/* / Set string parameter value */ +tSirRetStatus cfg_set_str(tpAniSirGlobal, uint16_t, uint8_t *, uint32_t); + +tSirRetStatus cfg_set_str_notify(tpAniSirGlobal, uint16_t, uint8_t *, uint32_t, + int); + +/* Cfg Download function for Prima or Integrated solutions. */ +void process_cfg_download_req(tpAniSirGlobal); + +/* / Get string parameter value */ +tSirRetStatus wlan_cfg_get_str(tpAniSirGlobal, uint16_t, uint8_t *, uint32_t *); + +/* / Get string parameter maximum length */ +tSirRetStatus wlan_cfg_get_str_max_len(tpAniSirGlobal, uint16_t, uint32_t *); + +/* / Get string parameter maximum length */ +tSirRetStatus wlan_cfg_get_str_len(tpAniSirGlobal, uint16_t, uint32_t *); + +/* / Get the regulatory tx power on given channel */ +tPowerdBm cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, + uint8_t channel); + +/* / Dump CFG data to memory */ +void cfgDump(uint32_t *); + +/* / Save parameters with P flag set */ +void cfgSave(void); + +/* / Get capability info */ +extern tSirRetStatus cfg_get_capability_info(tpAniSirGlobal pMac, uint16_t *pCap, + tpPESession psessionEntry); + +/* / Set capability info */ +extern void cfg_set_capability_info(tpAniSirGlobal, uint16_t); + +/* / Cleanup CFG module */ +void cfg_cleanup(tpAniSirGlobal pMac); + +extern uint8_t *g_cfg_param_name[]; + +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/core/mac/src/include/cfg_global.h b/core/mac/src/include/cfg_global.h new file mode 100644 index 000000000000..8678f27daf4e --- /dev/null +++ b/core/mac/src/include/cfg_global.h @@ -0,0 +1,95 @@ +/* + * 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/09/03 + * History:- + * 04/09/02 Created. + * -------------------------------------------------------------------- + * + */ + +#ifndef __CFGGLOBAL_H +#define __CFGGLOBAL_H + +#include "sir_common.h" +#include "sir_types.h" +#include "wni_cfg.h" + +#define CFG_MAX_NUM_STA SIR_MAX_NUM_STA_IN_IBSS + +#define CFG_MAX_STATIC_STRING 70 +/* as the number of channels grows, 128 is not big enough */ +#define CFG_MAX_STR_LEN 256 + +/*--------------------------------------------------------------------*/ +/* Configuration Control Structure */ +/*--------------------------------------------------------------------*/ +typedef struct { + uint32_t control; +} tCfgCtl; + + +typedef struct sAniSirCfgStaticString { + uint16_t cfgId; + uint8_t maxLen; + uint8_t length; + uint8_t data[255]; +} cfgstatic_string; + +typedef struct sAniSirCfgStatic { + uint16_t cfgId; + uint32_t control; + uint32_t cfgIMin; + uint32_t cfgIMax; + uint32_t cfgIVal; + void *pStrData; +} cgstatic; + +typedef struct sAniSirCfg { + /* CFG module status */ + uint8_t gCfgStatus; + + tCfgCtl *gCfgEntry; + uint32_t *gCfgIBufMin; + uint32_t *gCfgIBufMax; + uint32_t *gCfgIBuf; + uint8_t *gCfgSBuf; + + uint16_t gCfgMaxIBufSize; + uint16_t gCfgMaxSBufSize; + + /* Static buffer for string parameter (must be word-aligned) */ + uint8_t *gSBuffer; + + /* Message param list buffer (enough for largest possible response) */ + uint32_t *gParamList; +} tAniSirCfg, *tpAniSirCfg; + +#endif diff --git a/core/mac/src/include/dot11f.h b/core/mac/src/include/dot11f.h new file mode 100644 index 000000000000..0258abdf8f06 --- /dev/null +++ b/core/mac/src/include/dot11f.h @@ -0,0 +1,8920 @@ +/* + * 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' + * Wed Oct 14 10:14:42 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 uint32_t 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 { + uint16_t associd; +} tDot11fFfAID; + +#define DOT11F_FF_AID_LEN (2) + +void dot11f_unpack_ff_AID(tpAniSirGlobal, uint8_t *, tDot11fFfAID *); + +void dot11f_pack_ff_aid(tpAniSirGlobal, tDot11fFfAID *, uint8_t *); + +typedef struct sDot11fFfAction { + uint8_t action; +} tDot11fFfAction; + +#define DOT11F_FF_ACTION_LEN (1) + +void dot11f_unpack_ff_action(tpAniSirGlobal, uint8_t *, tDot11fFfAction *); + +void dot11f_pack_ff_action(tpAniSirGlobal, tDot11fFfAction *, uint8_t *); + +typedef struct sDot11fFfAuthAlgo { + uint16_t algo; +} tDot11fFfAuthAlgo; + +#define DOT11F_FF_AUTHALGO_LEN (2) + +void dot11f_unpack_ff_AuthAlgo(tpAniSirGlobal, uint8_t *, + tDot11fFfAuthAlgo *); + +void dot11f_pack_ff_auth_algo(tpAniSirGlobal, tDot11fFfAuthAlgo *, uint8_t *); + +typedef struct sDot11fFfAuthSeqNo { + uint16_t no; +} tDot11fFfAuthSeqNo; + +#define DOT11F_FF_AUTHSEQNO_LEN (2) + +void dot11f_unpack_ff_AuthSeqNo(tpAniSirGlobal, uint8_t *, + tDot11fFfAuthSeqNo *); + +void dot11f_pack_ff_auth_seq_no(tpAniSirGlobal, tDot11fFfAuthSeqNo *, + uint8_t *); + +typedef struct sDot11fFfBeaconInterval { + uint16_t interval; +} tDot11fFfBeaconInterval; + +#define DOT11F_FF_BEACONINTERVAL_LEN (2) + +void dot11f_unpack_ff_BeaconInterval(tpAniSirGlobal, uint8_t *, + tDot11fFfBeaconInterval *); + +void dot11f_pack_ff_beacon_interval(tpAniSirGlobal, tDot11fFfBeaconInterval *, + uint8_t *); + +typedef struct sDot11fFfCapabilities { + uint16_t ess:1; + uint16_t ibss:1; + uint16_t cfPollable:1; + uint16_t cfPollReq:1; + uint16_t privacy:1; + uint16_t shortPreamble:1; + uint16_t pbcc:1; + uint16_t channelAgility:1; + uint16_t spectrumMgt:1; + uint16_t qos:1; + uint16_t shortSlotTime:1; + uint16_t apsd:1; + uint16_t rrm:1; + uint16_t dsssOfdm:1; + uint16_t delayedBA:1; + uint16_t immediateBA:1; +} tDot11fFfCapabilities; + +#define DOT11F_FF_CAPABILITIES_LEN (2) + +void dot11f_unpack_ff_capabilities(tpAniSirGlobal, uint8_t *, + tDot11fFfCapabilities *); + +void dot11f_pack_ff_capabilities(tpAniSirGlobal, tDot11fFfCapabilities *, + uint8_t *); + +#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 { + uint8_t category; +} tDot11fFfCategory; + +#define DOT11F_FF_CATEGORY_LEN (1) + +void dot11f_unpack_ff_category(tpAniSirGlobal, uint8_t *, + tDot11fFfCategory *); + +void dot11f_pack_ff_category(tpAniSirGlobal, tDot11fFfCategory *, uint8_t *); + +typedef struct sDot11fFfCurrentAPAddress { + uint8_t mac[6]; +} tDot11fFfCurrentAPAddress; + +#define DOT11F_FF_CURRENTAPADDRESS_LEN (6) + +void dot11f_unpack_ff_current_ap_address(tpAniSirGlobal, uint8_t *, + tDot11fFfCurrentAPAddress *); + +void dot11f_pack_ff_current_ap_address(tpAniSirGlobal, + tDot11fFfCurrentAPAddress *, + uint8_t *); + + +typedef struct sDot11fFfDialogToken { + uint8_t token; +} tDot11fFfDialogToken; + +#define DOT11F_FF_DIALOGTOKEN_LEN (1) + +void dot11f_unpack_ff_dialog_token(tpAniSirGlobal, uint8_t *, + tDot11fFfDialogToken *); + +void dot11f_pack_ff_dialog_token(tpAniSirGlobal, tDot11fFfDialogToken *, + uint8_t *); + +typedef struct sDot11fFfLinkMargin { + uint8_t linkMargin; +} tDot11fFfLinkMargin; + +#define DOT11F_FF_LINKMARGIN_LEN (1) + +void dot11f_unpack_ff_link_margin(tpAniSirGlobal, uint8_t *, + tDot11fFfLinkMargin *); + +void dot11f_pack_ff_link_margin(tpAniSirGlobal, tDot11fFfLinkMargin *, + uint8_t *); + +typedef struct sDot11fFfListenInterval { + uint16_t interval; +} tDot11fFfListenInterval; + +#define DOT11F_FF_LISTENINTERVAL_LEN (2) + +void dot11f_unpack_ff_ListenInterval(tpAniSirGlobal, uint8_t *, + tDot11fFfListenInterval *); + +void dot11f_pack_ff_listen_interval(tpAniSirGlobal, tDot11fFfListenInterval *, + uint8_t *); + +typedef struct sDot11fFfMaxTxPower { + uint8_t maxTxPower; +} tDot11fFfMaxTxPower; + +#define DOT11F_FF_MAXTXPOWER_LEN (1) + +void dot11f_unpack_ff_max_tx_power(tpAniSirGlobal, uint8_t *, + tDot11fFfMaxTxPower *); + +void dot11f_pack_ff_max_tx_power(tpAniSirGlobal, tDot11fFfMaxTxPower *, + uint8_t *); + +typedef struct sDot11fFfNumOfRepetitions { + uint16_t repetitions; +} tDot11fFfNumOfRepetitions; + +#define DOT11F_FF_NUMOFREPETITIONS_LEN (2) + +void dot11f_unpack_ff_num_of_repetitions(tpAniSirGlobal, uint8_t *, + tDot11fFfNumOfRepetitions *); + +void dot11f_pack_ff_num_of_repetitions(tpAniSirGlobal, + tDot11fFfNumOfRepetitions *, + uint8_t *); + + +typedef struct sDot11fFfOperatingMode { + uint8_t chanWidth:2; + uint8_t reserved:2; + uint8_t rxNSS:3; + uint8_t rxNSSType:1; +} tDot11fFfOperatingMode; + +#define DOT11F_FF_OPERATINGMODE_LEN (1) + +void dot11f_unpack_ff_operating_mode(tpAniSirGlobal, uint8_t *, + tDot11fFfOperatingMode *); + +void dot11f_pack_ff_operating_mode(tpAniSirGlobal, tDot11fFfOperatingMode *, + uint8_t *); + +#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 sDot11fFfRCPI { + uint8_t rcpi; +} tDot11fFfRCPI; + +#define DOT11F_FF_RCPI_LEN (1) + +void dot11f_unpack_ff_rcpi(tpAniSirGlobal, uint8_t *, tDot11fFfRCPI *); + +void dot11f_pack_ff_rcpi(tpAniSirGlobal, tDot11fFfRCPI *, uint8_t *); + +typedef struct sDot11fFfRSNI { + uint8_t rsni; +} tDot11fFfRSNI; + +#define DOT11F_FF_RSNI_LEN (1) + +void dot11f_unpack_ff_rsni(tpAniSirGlobal, uint8_t *, tDot11fFfRSNI *); + +void dot11f_pack_ff_rsni(tpAniSirGlobal, tDot11fFfRSNI *, uint8_t *); + +typedef struct sDot11fFfReason { + uint16_t code; +} tDot11fFfReason; + +#define DOT11F_FF_REASON_LEN (2) + +void dot11f_unpack_ff_Reason(tpAniSirGlobal, uint8_t *, tDot11fFfReason *); + +void dot11f_pack_ff_reason(tpAniSirGlobal, tDot11fFfReason *, uint8_t *); + +typedef struct sDot11fFfRxAntennaId { + uint8_t antennaId; +} tDot11fFfRxAntennaId; + +#define DOT11F_FF_RXANTENNAID_LEN (1) + +void dot11f_unpack_ff_rx_antenna_id(tpAniSirGlobal, uint8_t *, + tDot11fFfRxAntennaId *); + +void dot11f_pack_ff_rx_antenna_id(tpAniSirGlobal, tDot11fFfRxAntennaId *, + uint8_t *); + +typedef struct sDot11fFfSMPowerModeSet { + uint8_t PowerSave_En:1; + uint8_t Mode:1; + uint8_t reserved:6; +} tDot11fFfSMPowerModeSet; + +#define DOT11F_FF_SMPOWERMODESET_LEN (1) + +void dot11f_unpack_ff_sm_power_mode_set(tpAniSirGlobal, uint8_t *, + tDot11fFfSMPowerModeSet *); + +void dot11f_pack_ff_sm_power_mode_set(tpAniSirGlobal, tDot11fFfSMPowerModeSet *, + uint8_t *); + +#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 { + uint16_t status; +} tDot11fFfStatus; + +#define DOT11F_FF_STATUS_LEN (2) + +void dot11f_unpack_ff_Status(tpAniSirGlobal, uint8_t *, tDot11fFfStatus *); + +void dot11f_pack_ff_status(tpAniSirGlobal, tDot11fFfStatus *, uint8_t *); + +typedef struct sDot11fFfStatusCode { + uint8_t statusCode; +} tDot11fFfStatusCode; + +#define DOT11F_FF_STATUSCODE_LEN (1) + +void dot11f_unpack_ff_status_code(tpAniSirGlobal, uint8_t *, + tDot11fFfStatusCode *); + +void dot11f_pack_ff_status_code(tpAniSirGlobal, tDot11fFfStatusCode *, + uint8_t *); + +typedef struct sDot11fFfTPCEleID { + uint8_t TPCId; +} tDot11fFfTPCEleID; + +#define DOT11F_FF_TPCELEID_LEN (1) + +void dot11f_unpack_ff_tpc_ele_id(tpAniSirGlobal, uint8_t *, + tDot11fFfTPCEleID *); + +void dot11f_pack_ff_tpc_ele_id(tpAniSirGlobal, tDot11fFfTPCEleID *, uint8_t *); + +typedef struct sDot11fFfTPCEleLen { + uint8_t TPCLen; +} tDot11fFfTPCEleLen; + +#define DOT11F_FF_TPCELELEN_LEN (1) + +void dot11f_unpack_ff_tpc_ele_len(tpAniSirGlobal, uint8_t *, + tDot11fFfTPCEleLen *); + +void dot11f_pack_ff_tpc_ele_len(tpAniSirGlobal, tDot11fFfTPCEleLen *, + uint8_t *); + +typedef struct sDot11fFfTSInfo { + uint32_t traffic_type:1; + uint32_t tsid:4; + uint32_t direction:2; + uint32_t access_policy:2; + uint32_t aggregation:1; + uint32_t psb:1; + uint32_t user_priority:3; + uint32_t tsinfo_ack_pol:2; + uint32_t schedule:1; + uint32_t unused:15; +} tDot11fFfTSInfo; + +#define DOT11F_FF_TSINFO_LEN (3) + +void dot11f_unpack_ff_ts_info(tpAniSirGlobal, uint8_t *, tDot11fFfTSInfo *); + +void dot11f_pack_ff_ts_info(tpAniSirGlobal, tDot11fFfTSInfo *, uint8_t *); + +#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 dot11f_unpack_ff_time_stamp(tpAniSirGlobal, uint8_t *, + tDot11fFfTimeStamp *); + +void dot11f_pack_ff_time_stamp(tpAniSirGlobal, tDot11fFfTimeStamp *, + uint8_t *); + +typedef struct sDot11fFfTransactionId { + uint8_t transId[2]; +} tDot11fFfTransactionId; + +#define DOT11F_FF_TRANSACTIONID_LEN (2) + +void dot11f_unpack_ff_transaction_id(tpAniSirGlobal, uint8_t *, + tDot11fFfTransactionId *); + +void dot11f_pack_ff_transaction_id(tpAniSirGlobal, tDot11fFfTransactionId *, + uint8_t *); + +typedef struct sDot11fFfTxAntennaId { + uint8_t antennaId; +} tDot11fFfTxAntennaId; + +#define DOT11F_FF_TXANTENNAID_LEN (1) + +void dot11f_unpack_ff_tx_antenna_id(tpAniSirGlobal, uint8_t *, + tDot11fFfTxAntennaId *); + +void dot11f_pack_ff_tx_antenna_id(tpAniSirGlobal, tDot11fFfTxAntennaId *, + uint8_t *); + +typedef struct sDot11fFfTxPower { + uint8_t txPower; +} tDot11fFfTxPower; + +#define DOT11F_FF_TXPOWER_LEN (1) + +void dot11f_unpack_ff_tx_power(tpAniSirGlobal, uint8_t *, + tDot11fFfTxPower *); + +void dot11f_pack_ff_tx_power(tpAniSirGlobal, tDot11fFfTxPower *, uint8_t *); + +typedef struct sDot11fFfVhtMembershipStatusArray { + uint8_t membershipStatusArray[8]; +} tDot11fFfVhtMembershipStatusArray; + +#define DOT11F_FF_VHTMEMBERSHIPSTATUSARRAY_LEN (8) + +void dot11f_unpack_ff_vht_membership_status_array(tpAniSirGlobal, uint8_t *, + tDot11fFfVhtMembershipStatusArray *); + +void dot11f_pack_ff_vht_membership_status_array(tpAniSirGlobal, + tDot11fFfVhtMembershipStatusArray *, + uint8_t *); + + +typedef struct sDot11fFfVhtUserPositionArray { + uint8_t userPositionArray[16]; +} tDot11fFfVhtUserPositionArray; + +#define DOT11F_FF_VHTUSERPOSITIONARRAY_LEN (16) + +void dot11f_unpack_ff_vht_user_position_array(tpAniSirGlobal, uint8_t *, + tDot11fFfVhtUserPositionArray *); + +void dot11f_pack_ff_vht_user_position_array(tpAniSirGlobal, + tDot11fFfVhtUserPositionArray *, + uint8_t *); + + +/********************************************************************* + * TLVs * + ********************************************************************/ + + +/* ID 1 (0x0001) */ +typedef struct sDot11fTLVAuthorizedMACs { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_authorized_ma_cs( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVAuthorizedMACs*); + +uint32_t dot11f_pack_tlv_authorized_ma_cs( + tpAniSirGlobal, + tDot11fTLVAuthorizedMACs *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_AuthorizedMACs( + tpAniSirGlobal, + tDot11fTLVAuthorizedMACs *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 3 (0x0003) */ +typedef struct sDot11fTLVRequestToEnroll { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_RequestToEnroll( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVRequestToEnroll*); + +uint32_t dot11f_pack_tlv_request_to_enroll( + tpAniSirGlobal, + tDot11fTLVRequestToEnroll *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_RequestToEnroll( + tpAniSirGlobal, + tDot11fTLVRequestToEnroll *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 0 (0x0000) */ +typedef struct sDot11fTLVVersion2 { + uint8_t present; + uint8_t minor:4; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_version2( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVVersion2*); + +uint32_t dot11f_pack_tlv_version2( + tpAniSirGlobal, + tDot11fTLVVersion2 *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_Version2( + tpAniSirGlobal, + tDot11fTLVVersion2 *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4183 (0x1057) */ +typedef struct sDot11fTLVAPSetupLocked { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_APSetupLocked( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVAPSetupLocked*); + +uint32_t dot11f_pack_tlv_ap_setup_locked( + tpAniSirGlobal, + tDot11fTLVAPSetupLocked *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_APSetupLocked( + tpAniSirGlobal, + tDot11fTLVAPSetupLocked *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4098 (0x1002) */ +typedef struct sDot11fTLVAssociationState { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_AssociationState( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVAssociationState*); + +uint32_t dot11f_pack_tlv_association_state( + tpAniSirGlobal, + tDot11fTLVAssociationState *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_AssociationState( + tpAniSirGlobal, + tDot11fTLVAssociationState *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4104 (0x1008) */ +typedef struct sDot11fTLVConfigMethods { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_ConfigMethods( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVConfigMethods*); + +uint32_t dot11f_pack_tlv_config_methods( + tpAniSirGlobal, + tDot11fTLVConfigMethods *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ConfigMethods( + tpAniSirGlobal, + tDot11fTLVConfigMethods *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4105 (0x1009) */ +typedef struct sDot11fTLVConfigurationError { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_ConfigurationError( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVConfigurationError*); + +uint32_t dot11f_pack_tlv_configuration_error( + tpAniSirGlobal, + tDot11fTLVConfigurationError *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ConfigurationError( + tpAniSirGlobal, + tDot11fTLVConfigurationError *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4113 (0x1011) */ +typedef struct sDot11fTLVDeviceName { + uint8_t present; + uint8_t num_text; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_device_name( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVDeviceName*); + +uint32_t dot11f_pack_tlv_device_name( + tpAniSirGlobal, + tDot11fTLVDeviceName *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_DeviceName( + tpAniSirGlobal, + tDot11fTLVDeviceName *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4114 (0x1012) */ +typedef struct sDot11fTLVDevicePasswordID { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_DevicePasswordID( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVDevicePasswordID*); + +uint32_t dot11f_pack_tlv_device_password_id( + tpAniSirGlobal, + tDot11fTLVDevicePasswordID *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_DevicePasswordID( + tpAniSirGlobal, + tDot11fTLVDevicePasswordID *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 8 (0x0008) */ +typedef struct sDot11fTLVExtendedListenTiming { + uint8_t present; + uint16_t availibilityPeriod; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_extended_listen_timing( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVExtendedListenTiming*); + +uint32_t dot11f_pack_tlv_extended_listen_timing( + tpAniSirGlobal, + tDot11fTLVExtendedListenTiming *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ExtendedListenTiming( + tpAniSirGlobal, + tDot11fTLVExtendedListenTiming *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 6 (0x0006) */ +typedef struct sDot11fTLVListenChannel { + uint8_t present; + uint8_t countryString[3]; + uint8_t regulatoryClass; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_listen_channel( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVListenChannel*); + +uint32_t dot11f_pack_tlv_listen_channel( + tpAniSirGlobal, + tDot11fTLVListenChannel *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ListenChannel( + tpAniSirGlobal, + tDot11fTLVListenChannel *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4129 (0x1021) */ +typedef struct sDot11fTLVManufacturer { + uint8_t present; + uint8_t num_name; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_manufacturer( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVManufacturer*); + +uint32_t dot11f_pack_tlv_manufacturer( + tpAniSirGlobal, + tDot11fTLVManufacturer *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_Manufacturer( + tpAniSirGlobal, + tDot11fTLVManufacturer *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 1 (0x0001) */ +typedef struct sDot11fTLVMinorReasonCode { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_MinorReasonCode( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVMinorReasonCode*); + +uint32_t dot11f_pack_tlv_minor_reason_code( + tpAniSirGlobal, + tDot11fTLVMinorReasonCode *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_MinorReasonCode( + tpAniSirGlobal, + tDot11fTLVMinorReasonCode *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4131 (0x1023) */ +typedef struct sDot11fTLVModelName { + uint8_t present; + uint8_t num_text; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_model_name( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVModelName*); + +uint32_t dot11f_pack_tlv_model_name( + tpAniSirGlobal, + tDot11fTLVModelName *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ModelName( + tpAniSirGlobal, + tDot11fTLVModelName *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4132 (0x1024) */ +typedef struct sDot11fTLVModelNumber { + uint8_t present; + uint8_t num_text; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_model_number( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVModelNumber*); + +uint32_t dot11f_pack_tlv_model_number( + tpAniSirGlobal, + tDot11fTLVModelNumber *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ModelNumber( + tpAniSirGlobal, + tDot11fTLVModelNumber *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 12 (0x000c) */ +typedef struct sDot11fTLVNoticeOfAbsence { + uint8_t present; + uint8_t index; + uint8_t CTSWindowOppPS; + uint8_t num_NoADesc; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_notice_of_absence( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVNoticeOfAbsence*); + +uint32_t dot11f_pack_tlv_notice_of_absence( + tpAniSirGlobal, + tDot11fTLVNoticeOfAbsence *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_NoticeOfAbsence( + tpAniSirGlobal, + tDot11fTLVNoticeOfAbsence *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 17 (0x0011) */ +typedef struct sDot11fTLVOperatingChannel { + uint8_t present; + uint8_t countryString[3]; + uint8_t regulatoryClass; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_operating_channel( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVOperatingChannel*); + +uint32_t dot11f_pack_tlv_operating_channel( + tpAniSirGlobal, + tDot11fTLVOperatingChannel *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_OperatingChannel( + tpAniSirGlobal, + tDot11fTLVOperatingChannel *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 2 (0x0002) */ +typedef struct sDot11fTLVP2PCapability { + uint8_t present; + uint8_t deviceCapability; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_p2_p_capability( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PCapability*); + +uint32_t dot11f_pack_tlv_p2_p_capability( + tpAniSirGlobal, + tDot11fTLVP2PCapability *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PCapability( + tpAniSirGlobal, + tDot11fTLVP2PCapability *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 3 (0x0003) */ +typedef struct sDot11fTLVP2PDeviceId { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_p2_p_device_id( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PDeviceId*); + +uint32_t dot11f_pack_tlv_p2_p_device_id( + tpAniSirGlobal, + tDot11fTLVP2PDeviceId *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PDeviceId( + tpAniSirGlobal, + tDot11fTLVP2PDeviceId *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 13 (0x000d) */ +typedef struct sDot11fTLVP2PDeviceInfo { + uint8_t present; + uint8_t P2PDeviceAddress[6]; + uint16_t configMethod; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_p2_p_device_info( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PDeviceInfo*); + +uint32_t dot11f_pack_tlv_p2_p_device_info( + tpAniSirGlobal, + tDot11fTLVP2PDeviceInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PDeviceInfo( + tpAniSirGlobal, + tDot11fTLVP2PDeviceInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 14 (0x000e) */ +typedef struct sDot11fTLVP2PGroupInfo { + uint8_t present; + uint8_t num_P2PClientInfoDesc; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_p2_p_group_info( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PGroupInfo*); + +uint32_t dot11f_pack_tlv_p2_p_group_info( + tpAniSirGlobal, + tDot11fTLVP2PGroupInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PGroupInfo( + tpAniSirGlobal, + tDot11fTLVP2PGroupInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 0 (0x0000) */ +typedef struct sDot11fTLVP2PStatus { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_P2PStatus( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PStatus*); + +uint32_t dot11f_pack_tlv_p2_p_status( + tpAniSirGlobal, + tDot11fTLVP2PStatus *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PStatus( + tpAniSirGlobal, + tDot11fTLVP2PStatus *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4180 (0x1054) */ +typedef struct sDot11fTLVPrimaryDeviceType { + uint8_t present; + uint16_t primary_category; + uint8_t oui[4]; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_primary_device_type( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVPrimaryDeviceType*); + +uint32_t dot11f_pack_tlv_primary_device_type( + tpAniSirGlobal, + tDot11fTLVPrimaryDeviceType *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_PrimaryDeviceType( + tpAniSirGlobal, + tDot11fTLVPrimaryDeviceType *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4156 (0x103c) */ +typedef struct sDot11fTLVRFBands { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_RFBands( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVRFBands*); + +uint32_t dot11f_pack_tlv_rf_bands( + tpAniSirGlobal, + tDot11fTLVRFBands *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_RFBands( + tpAniSirGlobal, + tDot11fTLVRFBands *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4202 (0x106a) */ +typedef struct sDot11fTLVRequestDeviceType { + uint8_t present; + uint16_t primary_category; + uint8_t oui[4]; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_request_device_type( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVRequestDeviceType*); + +uint32_t dot11f_pack_tlv_request_device_type( + tpAniSirGlobal, + tDot11fTLVRequestDeviceType *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_RequestDeviceType( + tpAniSirGlobal, + tDot11fTLVRequestDeviceType *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4154 (0x103a) */ +typedef struct sDot11fTLVRequestType { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_RequestType( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVRequestType*); + +uint32_t dot11f_pack_tlv_request_type( + tpAniSirGlobal, + tDot11fTLVRequestType *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_RequestType( + tpAniSirGlobal, + tDot11fTLVRequestType *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4155 (0x103b) */ +typedef struct sDot11fTLVResponseType { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_ResponseType( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVResponseType*); + +uint32_t dot11f_pack_tlv_response_type( + tpAniSirGlobal, + tDot11fTLVResponseType *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_ResponseType( + tpAniSirGlobal, + tDot11fTLVResponseType *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4161 (0x1041) */ +typedef struct sDot11fTLVSelectedRegistrar { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_SelectedRegistrar( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVSelectedRegistrar*); + +uint32_t dot11f_pack_tlv_selected_registrar( + tpAniSirGlobal, + tDot11fTLVSelectedRegistrar *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_SelectedRegistrar( + tpAniSirGlobal, + tDot11fTLVSelectedRegistrar *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4179 (0x1053) */ +typedef struct sDot11fTLVSelectedRegistrarConfigMethods { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_tlv_SelectedRegistrarConfigMethods( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVSelectedRegistrarConfigMethods*); + +uint32_t dot11f_pack_tlv_selected_registrar_config_methods( + tpAniSirGlobal, + tDot11fTLVSelectedRegistrarConfigMethods *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_SelectedRegistrarConfigMethods( + tpAniSirGlobal, + tDot11fTLVSelectedRegistrarConfigMethods *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4162 (0x1042) */ +typedef struct sDot11fTLVSerialNumber { + uint8_t present; + uint8_t num_text; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_serial_number( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVSerialNumber*); + +uint32_t dot11f_pack_tlv_serial_number( + tpAniSirGlobal, + tDot11fTLVSerialNumber *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_SerialNumber( + tpAniSirGlobal, + tDot11fTLVSerialNumber *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4167 (0x1047) */ +typedef struct sDot11fTLVUUID_E { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_uuid_e( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVUUID_E*); + +uint32_t dot11f_pack_tlv_uuid_e( + tpAniSirGlobal, + tDot11fTLVUUID_E *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_UUID_E( + tpAniSirGlobal, + tDot11fTLVUUID_E *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4168 (0x1048) */ +typedef struct sDot11fTLVUUID_R { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_uuid_r( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVUUID_R*); + +uint32_t dot11f_pack_tlv_uuid_r( + tpAniSirGlobal, + tDot11fTLVUUID_R *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_UUID_R( + tpAniSirGlobal, + tDot11fTLVUUID_R *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4169 (0x1049) */ +typedef struct sDot11fTLVVendorExtension { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_vendor_extension( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVVendorExtension*); + +uint32_t dot11f_pack_tlv_vendor_extension( + tpAniSirGlobal, + tDot11fTLVVendorExtension *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_VendorExtension( + tpAniSirGlobal, + tDot11fTLVVendorExtension *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4170 (0x104a) */ +typedef struct sDot11fTLVVersion { + uint8_t present; + uint8_t minor:4; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_version( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVVersion*); + +uint32_t dot11f_pack_tlv_version( + tpAniSirGlobal, + tDot11fTLVVersion *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_Version( + tpAniSirGlobal, + tDot11fTLVVersion *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 4164 (0x1044) */ +typedef struct sDot11fTLVWPSState { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_WPSState( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVWPSState*); + +uint32_t dot11f_pack_tlv_wps_state( + tpAniSirGlobal, + tDot11fTLVWPSState *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_WPSState( + tpAniSirGlobal, + tDot11fTLVWPSState *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 16 (0x0010) */ +typedef struct sDot11fTLVP2PInterface { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_p2_p_interface( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PInterface*); + +uint32_t dot11f_pack_tlv_p2_p_interface( + tpAniSirGlobal, + tDot11fTLVP2PInterface *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PInterface( + tpAniSirGlobal, + tDot11fTLVP2PInterface *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* ID 10 (0x000a) */ +typedef struct sDot11fTLVP2PManageability { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_tlv_P2PManageability( + tpAniSirGlobal, + uint8_t *, + uint16_t, + tDot11fTLVP2PManageability*); + +uint32_t dot11f_pack_tlv_p2_p_manageability( + tpAniSirGlobal, + tDot11fTLVP2PManageability *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_tlv_P2PManageability( + tpAniSirGlobal, + tDot11fTLVP2PManageability *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +/********************************************************************* + * Information Elements * + ********************************************************************/ + + +/* EID 2 (0x02) */ +typedef struct sDot11fIECondensedCountryStr { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_condensed_country_str( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIECondensedCountryStr*); + +uint32_t dot11f_pack_ie_condensed_country_str( + tpAniSirGlobal, + tDot11fIECondensedCountryStr *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_CondensedCountryStr( + tpAniSirGlobal, + tDot11fIECondensedCountryStr *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 2 (0x02) */ +typedef struct sDot11fIEGTK { + uint8_t present; + uint16_t keyId:2; + uint16_t reserved:14; + uint8_t keyLength; + uint8_t RSC[8]; + uint8_t num_key; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_gtk( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEGTK*); + +uint32_t dot11f_pack_ie_gtk( + tpAniSirGlobal, + tDot11fIEGTK *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_GTK( + tpAniSirGlobal, + tDot11fIEGTK *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 4 (0x04) */ +typedef struct sDot11fIEIGTK { + uint8_t present; + uint8_t keyID[2]; + uint8_t IPN[6]; + uint8_t keyLength; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_igtk( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEIGTK*); + +uint32_t dot11f_pack_ie_igtk( + tpAniSirGlobal, + tDot11fIEIGTK *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_IGTK( + tpAniSirGlobal, + tDot11fIEIGTK *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 3 (0x03) */ +typedef struct sDot11fIER0KH_ID { + uint8_t present; + uint8_t num_PMK_R0_ID; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_r0_kh_id( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIER0KH_ID*); + +uint32_t dot11f_pack_ie_r0_kh_id( + tpAniSirGlobal, + tDot11fIER0KH_ID *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_R0KH_ID( + tpAniSirGlobal, + tDot11fIER0KH_ID *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 1 (0x01) */ +typedef struct sDot11fIER1KH_ID { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_r1_kh_id( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIER1KH_ID*); + +uint32_t dot11f_pack_ie_r1_kh_id( + tpAniSirGlobal, + tDot11fIER1KH_ID *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_R1KH_ID( + tpAniSirGlobal, + tDot11fIER1KH_ID *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 1 (0x01) */ +typedef struct sDot11fIETSFInfo { + uint8_t present; + uint16_t TsfOffset; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_tsf_info( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETSFInfo*); + +uint32_t dot11f_pack_ie_tsf_info( + tpAniSirGlobal, + tDot11fIETSFInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TSFInfo( + tpAniSirGlobal, + tDot11fIETSFInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 51 (0x33) */ +typedef struct sDot11fIEAPChannelReport { + uint8_t present; + uint8_t regulatoryClass; + uint8_t num_channelList; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ap_channel_report( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEAPChannelReport*); + +uint32_t dot11f_pack_ie_ap_channel_report( + tpAniSirGlobal, + tDot11fIEAPChannelReport *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_APChannelReport( + tpAniSirGlobal, + tDot11fIEAPChannelReport *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 2 (0x02) */ +typedef struct sDot11fIEBcnReportingDetail { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_bcn_reporting_detail( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEBcnReportingDetail*); + +uint32_t dot11f_pack_ie_bcn_reporting_detail( + tpAniSirGlobal, + tDot11fIEBcnReportingDetail *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_BcnReportingDetail( + tpAniSirGlobal, + tDot11fIEBcnReportingDetail *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 1 (0x01) */ +typedef struct sDot11fIEBeaconReportFrmBody { + uint8_t present; + uint8_t num_reportedFields; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_beacon_report_frm_body( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEBeaconReportFrmBody*); + +uint32_t dot11f_pack_ie_beacon_report_frm_body( + tpAniSirGlobal, + tDot11fIEBeaconReportFrmBody *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_BeaconReportFrmBody( + tpAniSirGlobal, + tDot11fIEBeaconReportFrmBody *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 1 (0x01) */ +typedef struct sDot11fIEBeaconReporting { + uint8_t present; + uint8_t reportingCondition; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_beacon_reporting( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEBeaconReporting*); + +uint32_t dot11f_pack_ie_beacon_reporting( + tpAniSirGlobal, + tDot11fIEBeaconReporting *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_BeaconReporting( + tpAniSirGlobal, + tDot11fIEBeaconReporting *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 66 (0x42) */ +typedef struct sDot11fIEMeasurementPilot { + uint8_t present; + uint8_t measurementPilot; + uint8_t num_vendorSpecific; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_measurement_pilot( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEMeasurementPilot*); + +uint32_t dot11f_pack_ie_measurement_pilot( + tpAniSirGlobal, + tDot11fIEMeasurementPilot *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_MeasurementPilot( + tpAniSirGlobal, + tDot11fIEMeasurementPilot *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 71 (0x47) */ +typedef struct sDot11fIEMultiBssid { + uint8_t present; + uint8_t maxBSSIDIndicator; + uint8_t num_vendorSpecific; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_multi_bssid( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEMultiBssid*); + +uint32_t dot11f_pack_ie_multi_bssid( + tpAniSirGlobal, + tDot11fIEMultiBssid *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_MultiBssid( + tpAniSirGlobal, + tDot11fIEMultiBssid *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 57 (0x39) */ +typedef struct sDot11fIERICData { + uint8_t present; + uint8_t Identifier; + uint8_t resourceDescCount; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_ric_data( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERICData*); + +uint32_t dot11f_pack_ie_ric_data( + tpAniSirGlobal, + tDot11fIERICData *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_RICData( + tpAniSirGlobal, + tDot11fIERICData *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 75 (0x4b) */ +typedef struct sDot11fIERICDescriptor { + uint8_t present; + uint8_t resourceType; + uint8_t num_variableData; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ric_descriptor( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERICDescriptor*); + +uint32_t dot11f_pack_ie_ric_descriptor( + tpAniSirGlobal, + tDot11fIERICDescriptor *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_RICDescriptor( + tpAniSirGlobal, + tDot11fIERICDescriptor *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 70 (0x46) */ +typedef struct sDot11fIERRMEnabledCap { + uint8_t present; + uint8_t LinkMeasurement:1; + uint8_t NeighborRpt:1; + uint8_t parallel:1; + uint8_t repeated:1; + uint8_t BeaconPassive:1; + uint8_t BeaconActive:1; + uint8_t BeaconTable:1; + uint8_t BeaconRepCond:1; + uint8_t FrameMeasurement:1; + uint8_t ChannelLoad:1; + uint8_t NoiseHistogram:1; + uint8_t statistics:1; + uint8_t LCIMeasurement:1; + uint8_t LCIAzimuth:1; + uint8_t TCMCapability:1; + uint8_t triggeredTCM:1; + uint8_t APChanReport:1; + uint8_t RRMMIBEnabled:1; + uint8_t operatingChanMax:3; + uint8_t nonOperatinChanMax:3; + uint8_t MeasurementPilot:3; + uint8_t MeasurementPilotEnabled:1; + uint8_t NeighborTSFOffset:1; + uint8_t RCPIMeasurement:1; + uint8_t RSNIMeasurement:1; + uint8_t BssAvgAccessDelay:1; + uint8_t BSSAvailAdmission:1; + uint8_t AntennaInformation:1; + uint8_t fine_time_meas_rpt:1; + uint8_t lci_capability:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_rrm_enabled_cap( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERRMEnabledCap*); + +uint32_t dot11f_pack_ie_rrm_enabled_cap( + tpAniSirGlobal, + tDot11fIERRMEnabledCap *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_RRMEnabledCap( + tpAniSirGlobal, + tDot11fIERRMEnabledCap *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 10 (0x0a) */ +typedef struct sDot11fIERequestedInfo { + uint8_t present; + uint8_t num_requested_eids; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_requested_info( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERequestedInfo*); + +uint32_t dot11f_pack_ie_requested_info( + tpAniSirGlobal, + tDot11fIERequestedInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_RequestedInfo( + tpAniSirGlobal, + tDot11fIERequestedInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 0 (0x00) */ +typedef struct sDot11fIESSID { + uint8_t present; + uint8_t num_ssid; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ssid( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIESSID*); + +uint32_t dot11f_pack_ie_ssid( + tpAniSirGlobal, + tDot11fIESSID *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_SSID( + tpAniSirGlobal, + tDot11fIESSID *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 15 (0x0f) */ +typedef struct sDot11fIESchedule { + uint8_t present; + uint16_t aggregation:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t reserved:9; + uint32_t service_start_time; + uint32_t service_interval; + uint16_t max_service_dur; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_schedule( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIESchedule*); + +uint32_t dot11f_pack_ie_schedule( + tpAniSirGlobal, + tDot11fIESchedule *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_Schedule( + tpAniSirGlobal, + tDot11fIESchedule *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 14 (0x0e) */ +typedef struct sDot11fIETCLAS { + uint8_t present; + uint8_t user_priority; + uint8_t classifier_type; + uint8_t classifier_mask; + union { + struct { + uint8_t source[6]; + uint8_t dest[6]; + uint16_t type; + } EthParams; /* classifier_type = 0 */ + struct { + uint8_t version; + union { + struct { + uint8_t source[4]; + uint8_t dest[4]; + uint16_t src_port; + uint16_t dest_port; + uint8_t DSCP; + uint8_t proto; + uint8_t reserved; + } IpV4Params; /* version = 4 */ + struct { + uint8_t source[16]; + uint8_t dest[16]; + uint16_t src_port; + uint16_t dest_port; + uint8_t flow_label[3]; + } IpV6Params; /* version = 6 */ + } params; + } IpParams; /* classifier_type = 1 */ + struct { + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_tclas( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETCLAS*); + +uint32_t dot11f_pack_ie_tclas( + tpAniSirGlobal, + tDot11fIETCLAS *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ietclas( + tpAniSirGlobal, + tDot11fIETCLAS *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 44 (0x2c) */ +typedef struct sDot11fIETCLASSPROC { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_tclasSPROC( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETCLASSPROC*); + +uint32_t dot11f_pack_ie_tclassproc( + tpAniSirGlobal, + tDot11fIETCLASSPROC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ietclasSPROC( + tpAniSirGlobal, + tDot11fIETCLASSPROC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 43 (0x2b) */ +typedef struct sDot11fIETSDelay { + uint8_t present; + uint32_t 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++ */ +uint32_t dot11f_unpack_ie_ts_delay( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETSDelay*); + +uint32_t dot11f_pack_ie_ts_delay( + tpAniSirGlobal, + tDot11fIETSDelay *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TSDelay( + tpAniSirGlobal, + tDot11fIETSDelay *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 13 (0x0d) */ +typedef struct sDot11fIETSPEC { + uint8_t present; + uint16_t traffic_type:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t access_policy:2; + uint16_t aggregation:1; + uint16_t psb:1; + uint16_t user_priority:3; + uint16_t tsinfo_ack_pol:2; + uint8_t schedule:1; + uint8_t unused:7; + uint16_t size:15; + uint16_t fixed:1; + uint16_t max_msdu_size; + uint32_t min_service_int; + uint32_t max_service_int; + uint32_t inactivity_int; + uint32_t suspension_int; + uint32_t service_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw_allowance; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_tspec( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETSPEC*); + +uint32_t dot11f_pack_ie_tspec( + tpAniSirGlobal, + tDot11fIETSPEC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TSPEC( + tpAniSirGlobal, + tDot11fIETSPEC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 191 (0xbf) */ +typedef struct sDot11fIEVHTCaps { + uint8_t present; + uint32_t maxMPDULen:2; + uint32_t supportedChannelWidthSet:2; + uint32_t ldpcCodingCap:1; + uint32_t shortGI80MHz:1; + uint32_t shortGI160and80plus80MHz:1; + uint32_t txSTBC:1; + uint32_t rxSTBC:3; + uint32_t suBeamFormerCap:1; + uint32_t suBeamformeeCap:1; + uint32_t csnofBeamformerAntSup:3; + uint32_t numSoundingDim:3; + uint32_t muBeamformerCap:1; + uint32_t muBeamformeeCap:1; + uint32_t vhtTXOPPS:1; + uint32_t htcVHTCap:1; + uint32_t maxAMPDULenExp:3; + uint32_t vhtLinkAdaptCap:2; + uint32_t rxAntPattern:1; + uint32_t txAntPattern:1; + uint32_t reserved1:2; + uint16_t rxMCSMap; + uint16_t rxHighSupDataRate:13; + uint16_t reserved2:3; + uint16_t txMCSMap; + uint16_t txSupDataRate:13; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_vht_caps( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEVHTCaps*); + +uint32_t dot11f_pack_ie_vht_caps( + tpAniSirGlobal, + tDot11fIEVHTCaps *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_VHTCaps( + tpAniSirGlobal, + tDot11fIEVHTCaps *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 192 (0xc0) */ +typedef struct sDot11fIEVHTOperation { + uint8_t present; + uint8_t chanWidth; + uint8_t chanCenterFreqSeg1; + uint8_t chanCenterFreqSeg2; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_vht_operation( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEVHTOperation*); + +uint32_t dot11f_pack_ie_vht_operation( + tpAniSirGlobal, + tDot11fIEVHTOperation *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_VHTOperation( + tpAniSirGlobal, + tDot11fIEVHTOperation *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x09} */ +typedef struct sDot11fIEWMMSchedule { + uint8_t present; + uint8_t version /* Must be 1! */; + uint16_t aggregation:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t reserved:9; + uint32_t service_start_time; + uint32_t service_interval; + uint16_t max_service_dur; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_wmm_schedule( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMSchedule*); + +uint32_t dot11f_pack_ie_wmm_schedule( + tpAniSirGlobal, + tDot11fIEWMMSchedule *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMSchedule( + tpAniSirGlobal, + tDot11fIEWMMSchedule *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x06} */ +typedef struct sDot11fIEWMMTCLAS { + uint8_t present; + uint8_t version /* Must be 1! */; + uint8_t user_priority; + uint8_t classifier_type; + uint8_t classifier_mask; + union { + struct { + uint8_t source[6]; + uint8_t dest[6]; + uint16_t type; + } EthParams; /* classifier_type = 0 */ + struct { + uint8_t version; + union { + struct { + uint8_t source[4]; + uint8_t dest[4]; + uint16_t src_port; + uint16_t dest_port; + uint8_t DSCP; + uint8_t proto; + uint8_t reserved; + } IpV4Params; /* version = 4 */ + struct { + uint8_t source[16]; + uint8_t dest[16]; + uint16_t src_port; + uint16_t dest_port; + uint8_t flow_label[3]; + } IpV6Params; /* version = 6 */ + } params; + } IpParams; /* classifier_type = 1 */ + struct { + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_wmmtclas( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMTCLAS*); + +uint32_t dot11f_pack_ie_wmmtclas( + tpAniSirGlobal, + tDot11fIEWMMTCLAS *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewmmtclas( + tpAniSirGlobal, + tDot11fIEWMMTCLAS *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x07} */ +typedef struct sDot11fIEWMMTCLASPROC { + uint8_t present; + uint8_t version /* Must be 1! */; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wmmtclasproc( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMTCLASPROC*); + +uint32_t dot11f_pack_ie_wmmtclasproc( + tpAniSirGlobal, + tDot11fIEWMMTCLASPROC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewmmtclasPROC( + tpAniSirGlobal, + tDot11fIEWMMTCLASPROC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x08} */ +typedef struct sDot11fIEWMMTSDelay { + uint8_t present; + uint8_t version /* Must be 1! */; + uint32_t 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++ */ +uint32_t dot11f_unpack_ie_wmmts_delay( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMTSDelay*); + +uint32_t dot11f_pack_ie_wmmts_delay( + tpAniSirGlobal, + tDot11fIEWMMTSDelay *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMTSDelay( + tpAniSirGlobal, + tDot11fIEWMMTSDelay *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x02} */ +typedef struct sDot11fIEWMMTSPEC { + uint8_t present; + uint8_t version /* Must be 1! */; + uint16_t traffic_type:1; + uint16_t tsid:4; + uint16_t direction:2; + uint16_t access_policy:2; + uint16_t aggregation:1; + uint16_t psb:1; + uint16_t user_priority:3; + uint16_t tsinfo_ack_pol:2; + uint8_t tsinfo_rsvd:7; + uint8_t burst_size_defn:1; + uint16_t size:15; + uint16_t fixed:1; + uint16_t max_msdu_size; + uint32_t min_service_int; + uint32_t max_service_int; + uint32_t inactivity_int; + uint32_t suspension_int; + uint32_t service_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw_allowance; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_wmmtspec( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMTSPEC*); + +uint32_t dot11f_pack_ie_wmmtspec( + tpAniSirGlobal, + tDot11fIEWMMTSPEC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMTSPEC( + tpAniSirGlobal, + tDot11fIEWMMTSPEC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 194 (0xc2) */ +typedef struct sDot11fIEWiderBWChanSwitchAnn { + uint8_t present; + uint8_t newChanWidth; + uint8_t newCenterChanFreq0; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wider_bw_chan_switch_ann( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWiderBWChanSwitchAnn*); + +uint32_t dot11f_pack_ie_wider_bw_chan_switch_ann( + tpAniSirGlobal, + tDot11fIEWiderBWChanSwitchAnn *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WiderBWChanSwitchAnn( + tpAniSirGlobal, + tDot11fIEWiderBWChanSwitchAnn *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 197 (0xc5) */ +typedef struct sDot11fIEAID { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_aid( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEAID*); + +uint32_t dot11f_pack_ie_aid( + tpAniSirGlobal, + tDot11fIEAID *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_AID( + tpAniSirGlobal, + tDot11fIEAID *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 4 (0x04) */ +typedef struct sDot11fIECFParams { + uint8_t present; + uint8_t cfp_count; + uint8_t cfp_period; + uint16_t cfp_maxduration; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_cf_params( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIECFParams*); + +uint32_t dot11f_pack_ie_cf_params( + tpAniSirGlobal, + tDot11fIECFParams *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_CFParams( + tpAniSirGlobal, + tDot11fIECFParams *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 16 (0x10) */ +typedef struct sDot11fIEChallengeText { + uint8_t present; + uint8_t num_text; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_challenge_text( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEChallengeText*); + +uint32_t dot11f_pack_ie_challenge_text( + tpAniSirGlobal, + tDot11fIEChallengeText *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ChallengeText( + tpAniSirGlobal, + tDot11fIEChallengeText *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 37 (0x25) */ +typedef struct sDot11fIEChanSwitchAnn { + uint8_t present; + uint8_t switchMode; + uint8_t newChannel; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_chan_switch_ann( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEChanSwitchAnn*); + +uint32_t dot11f_pack_ie_chan_switch_ann( + tpAniSirGlobal, + tDot11fIEChanSwitchAnn *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ChanSwitchAnn( + tpAniSirGlobal, + tDot11fIEChanSwitchAnn *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 196 (0xc4) */ +typedef struct sDot11fIEChannelSwitchWrapper { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_channel_switch_wrapper( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEChannelSwitchWrapper*); + +uint32_t dot11f_pack_ie_channel_switch_wrapper( + tpAniSirGlobal, + tDot11fIEChannelSwitchWrapper *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_channel_switch_wrapper( + tpAniSirGlobal, + tDot11fIEChannelSwitchWrapper *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 7 (0x07) */ +typedef struct sDot11fIECountry { + uint8_t present; + uint8_t country[3]; + uint8_t num_triplets; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_country( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIECountry*); + +uint32_t dot11f_pack_ie_country( + tpAniSirGlobal, + tDot11fIECountry *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_country( + tpAniSirGlobal, + tDot11fIECountry *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 3 (0x03) */ +typedef struct sDot11fIEDSParams { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_DSParams( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEDSParams*); + +uint32_t dot11f_pack_ie_ds_params( + tpAniSirGlobal, + tDot11fIEDSParams *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_DSParams( + tpAniSirGlobal, + tDot11fIEDSParams *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 12 (0x0c) */ +typedef struct sDot11fIEEDCAParamSet { + uint8_t present; + uint8_t qos; + uint8_t reserved; + uint8_t acbe_aifsn:4; + uint8_t acbe_acm:1; + uint8_t acbe_aci:2; + uint8_t unused1:1; + uint8_t acbe_acwmin:4; + uint8_t acbe_acwmax:4; + uint16_t acbe_txoplimit; + uint8_t acbk_aifsn:4; + uint8_t acbk_acm:1; + uint8_t acbk_aci:2; + uint8_t unused2:1; + uint8_t acbk_acwmin:4; + uint8_t acbk_acwmax:4; + uint16_t acbk_txoplimit; + uint8_t acvi_aifsn:4; + uint8_t acvi_acm:1; + uint8_t acvi_aci:2; + uint8_t unused3:1; + uint8_t acvi_acwmin:4; + uint8_t acvi_acwmax:4; + uint16_t acvi_txoplimit; + uint8_t acvo_aifsn:4; + uint8_t acvo_acm:1; + uint8_t acvo_aci:2; + uint8_t unused4:1; + uint8_t acvo_acwmin:4; + uint8_t acvo_acwmax:4; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_edca_param_set( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEEDCAParamSet*); + +uint32_t dot11f_pack_ie_edca_param_set( + tpAniSirGlobal, + tDot11fIEEDCAParamSet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_EDCAParamSet( + tpAniSirGlobal, + tDot11fIEEDCAParamSet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 42 (0x2a) */ +typedef struct sDot11fIEERPInfo { + uint8_t present; + uint8_t non_erp_present:1; + uint8_t use_prot:1; + uint8_t barker_preamble:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_erp_info( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEERPInfo*); + +uint32_t dot11f_pack_ie_erp_info( + tpAniSirGlobal, + tDot11fIEERPInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ERPInfo( + tpAniSirGlobal, + tDot11fIEERPInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 156 (0x9c) {OUI 0x00, 0x40, 0x96, 0x00} */ +typedef struct sDot11fIEESECckmOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ese_cckm_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESECckmOpaque*); + +uint32_t dot11f_pack_ie_ese_cckm_opaque( + tpAniSirGlobal, + tDot11fIEESECckmOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESECckmOpaque( + tpAniSirGlobal, + tDot11fIEESECckmOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x01} */ +typedef struct sDot11fIEESERadMgmtCap { + uint8_t present; + uint8_t mgmt_state; + uint8_t mbssid_mask:3; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ese_rad_mgmt_cap( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESERadMgmtCap*); + +uint32_t dot11f_pack_ie_ese_rad_mgmt_cap( + tpAniSirGlobal, + tDot11fIEESERadMgmtCap *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESERadMgmtCap( + tpAniSirGlobal, + tDot11fIEESERadMgmtCap *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x07} */ +typedef struct sDot11fIEESETrafStrmMet { + uint8_t present; + uint8_t tsid; + uint8_t state; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_ese_traf_strm_met( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESETrafStrmMet*); + +uint32_t dot11f_pack_ie_ese_traf_strm_met( + tpAniSirGlobal, + tDot11fIEESETrafStrmMet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESETrafStrmMet( + tpAniSirGlobal, + tDot11fIEESETrafStrmMet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x08} */ +typedef struct sDot11fIEESETrafStrmRateSet { + uint8_t present; + uint8_t tsid; + uint8_t num_tsrates; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ese_traf_strm_rate_set( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESETrafStrmRateSet*); + +uint32_t dot11f_pack_ie_ese_traf_strm_rate_set( + tpAniSirGlobal, + tDot11fIEESETrafStrmRateSet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESETrafStrmRateSet( + tpAniSirGlobal, + tDot11fIEESETrafStrmRateSet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 150 (0x96) {OUI 0x00, 0x40, 0x96, 0x00} */ +typedef struct sDot11fIEESETxmitPower { + uint8_t present; + uint8_t power_limit; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ese_txmit_power( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESETxmitPower*); + +uint32_t dot11f_pack_ie_ese_txmit_power( + tpAniSirGlobal, + tDot11fIEESETxmitPower *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESETxmitPower( + tpAniSirGlobal, + tDot11fIEESETxmitPower *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x40, 0x96, 0x03} */ +typedef struct sDot11fIEESEVersion { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ese_version( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEESEVersion*); + +uint32_t dot11f_pack_ie_ese_version( + tpAniSirGlobal, + tDot11fIEESEVersion *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ESEVersion( + tpAniSirGlobal, + tDot11fIEESEVersion *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 127 (0x7f) */ +typedef struct sDot11fIEExtCap { + uint8_t present; + uint8_t num_bytes; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ext_cap( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEExtCap*); + +uint32_t dot11f_pack_ie_ext_cap( + tpAniSirGlobal, + tDot11fIEExtCap *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ExtCap( + tpAniSirGlobal, + tDot11fIEExtCap *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 50 (0x32) */ +typedef struct sDot11fIEExtSuppRates { + uint8_t present; + uint8_t num_rates; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ext_supp_rates( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEExtSuppRates*); + +uint32_t dot11f_pack_ie_ext_supp_rates( + tpAniSirGlobal, + tDot11fIEExtSuppRates *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ExtSuppRates( + tpAniSirGlobal, + tDot11fIEExtSuppRates *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 2 (0x02) */ +typedef struct sDot11fIEFHParamSet { + uint8_t present; + uint16_t dwell_time; + uint8_t hop_set; + uint8_t hop_pattern; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_fh_param_set( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEFHParamSet*); + +uint32_t dot11f_pack_ie_fh_param_set( + tpAniSirGlobal, + tDot11fIEFHParamSet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_FHParamSet( + tpAniSirGlobal, + tDot11fIEFHParamSet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 8 (0x08) */ +typedef struct sDot11fIEFHParams { + uint8_t present; + uint8_t radix; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_fh_params( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEFHParams*); + +uint32_t dot11f_pack_ie_fh_params( + tpAniSirGlobal, + tDot11fIEFHParams *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_FHParams( + tpAniSirGlobal, + tDot11fIEFHParams *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 9 (0x09) */ +typedef struct sDot11fIEFHPattTable { + uint8_t present; + uint8_t flag; + uint8_t nsets; + uint8_t modulus; + uint8_t offset; + uint8_t num_randtable; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_fh_patt_table( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEFHPattTable*); + +uint32_t dot11f_pack_ie_fh_patt_table( + tpAniSirGlobal, + tDot11fIEFHPattTable *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_FHPattTable( + tpAniSirGlobal, + tDot11fIEFHPattTable *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 55 (0x37) */ +typedef struct sDot11fIEFTInfo { + uint8_t present; + uint16_t reserved:8; + uint16_t IECount:8; + uint8_t MIC[16]; + uint8_t Anonce[32]; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ft_info( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEFTInfo*); + +uint32_t dot11f_pack_ie_ft_info( + tpAniSirGlobal, + tDot11fIEFTInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ieft_info( + tpAniSirGlobal, + tDot11fIEFTInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 45 (0x2d) */ +typedef struct sDot11fIEHTCaps { + uint8_t present; + uint16_t advCodingCap:1; + uint16_t supportedChannelWidthSet:1; + uint16_t mimoPowerSave:2; + uint16_t greenField:1; + uint16_t shortGI20MHz:1; + uint16_t shortGI40MHz:1; + uint16_t txSTBC:1; + uint16_t rxSTBC:2; + uint16_t delayedBA:1; + uint16_t maximalAMSDUsize:1; + uint16_t dsssCckMode40MHz:1; + uint16_t psmp:1; + uint16_t stbcControlFrame:1; + uint16_t lsigTXOPProtection:1; + uint8_t maxRxAMPDUFactor:2; + uint8_t mpduDensity:3; + uint8_t reserved1:3; + uint8_t supportedMCSSet[16]; + uint16_t pco:1; + uint16_t transitionTime:2; + uint16_t reserved2:5; + uint16_t mcsFeedback:2; + uint16_t reserved3:6; + uint32_t txBF:1; + uint32_t rxStaggeredSounding:1; + uint32_t txStaggeredSounding:1; + uint32_t rxZLF:1; + uint32_t txZLF:1; + uint32_t implicitTxBF:1; + uint32_t calibration:2; + uint32_t explicitCSITxBF:1; + uint32_t explicitUncompressedSteeringMatrix:1; + uint32_t explicitBFCSIFeedback:3; + uint32_t explicitUncompressedSteeringMatrixFeedback:3; + uint32_t explicitCompressedSteeringMatrixFeedback:3; + uint32_t csiNumBFAntennae:2; + uint32_t uncompressedSteeringMatrixBFAntennae:2; + uint32_t compressedSteeringMatrixBFAntennae:2; + uint32_t reserved4:7; + uint8_t antennaSelection:1; + uint8_t explicitCSIFeedbackTx:1; + uint8_t antennaIndicesFeedbackTx:1; + uint8_t explicitCSIFeedback:1; + uint8_t antennaIndicesFeedback:1; + uint8_t rxAS:1; + uint8_t txSoundingPPDUs:1; + uint8_t reserved5:1; + uint8_t num_rsvd; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ht_caps( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEHTCaps*); + +uint32_t dot11f_pack_ie_ht_caps( + tpAniSirGlobal, + tDot11fIEHTCaps *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_HTCaps( + tpAniSirGlobal, + tDot11fIEHTCaps *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 61 (0x3d) */ +typedef struct sDot11fIEHTInfo { + uint8_t present; + uint8_t primaryChannel; + uint8_t secondaryChannelOffset:2; + uint8_t recommendedTxWidthSet:1; + uint8_t rifsMode:1; + uint8_t controlledAccessOnly:1; + uint8_t serviceIntervalGranularity:3; + uint16_t opMode:2; + uint16_t nonGFDevicesPresent:1; + uint16_t transmitBurstLimit:1; + uint16_t obssNonHTStaPresent:1; + uint16_t reserved:11; + uint16_t basicSTBCMCS:7; + uint16_t dualCTSProtection:1; + uint16_t secondaryBeacon:1; + uint16_t lsigTXOPProtectionFullSupport:1; + uint16_t pcoActive:1; + uint16_t pcoPhase:1; + uint16_t reserved2:4; + uint8_t basicMCSSet[16]; + uint8_t num_rsvd; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ht_info( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEHTInfo*); + +uint32_t dot11f_pack_ie_ht_info( + tpAniSirGlobal, + tDot11fIEHTInfo *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_HTInfo( + tpAniSirGlobal, + tDot11fIEHTInfo *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 6 (0x06) */ +typedef struct sDot11fIEIBSSParams { + uint8_t present; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_ibss_params( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEIBSSParams*); + +uint32_t dot11f_pack_ie_ibss_params( + tpAniSirGlobal, + tDot11fIEIBSSParams *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_IBSSParams( + tpAniSirGlobal, + tDot11fIEIBSSParams *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 101 (0x65) */ +typedef struct sDot11fIELinkIdentifier { + uint8_t present; + uint8_t bssid[6]; + uint8_t InitStaAddr[6]; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_link_identifier( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIELinkIdentifier*); + +uint32_t dot11f_pack_ie_link_identifier( + tpAniSirGlobal, + tDot11fIELinkIdentifier *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_LinkIdentifier( + tpAniSirGlobal, + tDot11fIELinkIdentifier *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 39 (0x27) */ +typedef struct sDot11fIEMeasurementReport { + uint8_t present; + uint8_t token; + uint8_t late:1; + uint8_t incapable:1; + uint8_t refused:1; + uint8_t unused:5; + uint8_t type; + union { + struct { + uint8_t channel; + tDOT11F_U64 meas_start_time; + uint16_t meas_duration; + uint8_t bss:1; + uint8_t ofdm_preamble:1; + uint8_t unid_signal:1; + uint8_t rader:1; + uint8_t unmeasured:1; + uint8_t unused:3; + } Basic; /* type = 0 */ + struct { + uint8_t channel; + tDOT11F_U64 meas_start_time; + uint16_t meas_duration; + uint8_t cca_busy_fraction; + } CCA; /* type = 1 */ + struct { + uint8_t channel; + tDOT11F_U64 meas_start_time; + uint16_t meas_duration; + uint8_t rpi0_density; + uint8_t rpi1_density; + uint8_t rpi2_density; + uint8_t rpi3_density; + uint8_t rpi4_density; + uint8_t rpi5_density; + uint8_t rpi6_density; + uint8_t rpi7_density; + } RPIHistogram; /* type = 2 */ + struct { + uint8_t regClass; + uint8_t channel; + tDOT11F_U64 meas_start_time; + uint16_t meas_duration; + uint8_t condensed_PHY:7; + uint8_t reported_frame_type:1; + uint8_t RCPI; + uint8_t RSNI; + uint8_t BSSID[6]; + uint8_t antenna_id; + uint32_t 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++ */ +uint32_t dot11f_unpack_ie_measurement_report( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEMeasurementReport*); + +uint32_t dot11f_pack_ie_measurement_report( + tpAniSirGlobal, + tDot11fIEMeasurementReport *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_measurement_report( + tpAniSirGlobal, + tDot11fIEMeasurementReport *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 38 (0x26) */ +typedef struct sDot11fIEMeasurementRequest { + uint8_t present; + uint8_t measurement_token; + uint8_t parallel:1; + uint8_t enable:1; + uint8_t request:1; + uint8_t report:1; + uint8_t durationMandatory:1; + uint8_t unused:3; + uint8_t measurement_type; + union { + struct { + uint8_t channel_no; + uint8_t meas_start_time[8]; + uint16_t meas_duration; + } Basic; /* measurement_type = 0 */ + struct { + uint8_t channel_no; + uint8_t meas_start_time[8]; + uint16_t meas_duration; + } CCA; /* measurement_type = 1 */ + struct { + uint8_t channel_no; + uint8_t meas_start_time[8]; + uint16_t meas_duration; + } RPIHistogram; /* measurement_type = 2 */ + struct { + uint8_t regClass; + uint8_t channel; + uint16_t randomization; + uint16_t meas_duration; + uint8_t meas_mode; + uint8_t BSSID[6]; + tDot11fIESSID SSID; + tDot11fIEBeaconReporting BeaconReporting; + tDot11fIEBcnReportingDetail BcnReportingDetail; + tDot11fIERequestedInfo RequestedInfo; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_measurement_request( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEMeasurementRequest*); + +uint32_t dot11f_pack_ie_measurement_request( + tpAniSirGlobal, + tDot11fIEMeasurementRequest *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_measurement_request( + tpAniSirGlobal, + tDot11fIEMeasurementRequest *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 54 (0x36) */ +typedef struct sDot11fIEMobilityDomain { + uint8_t present; + uint16_t MDID; + uint8_t overDSCap:1; + uint8_t resourceReqCap:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_mobility_domain( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEMobilityDomain*); + +uint32_t dot11f_pack_ie_mobility_domain( + tpAniSirGlobal, + tDot11fIEMobilityDomain *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_MobilityDomain( + tpAniSirGlobal, + tDot11fIEMobilityDomain *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 52 (0x34) */ +typedef struct sDot11fIENeighborReport { + uint8_t present; + uint8_t bssid[6]; + uint8_t APReachability:2; + uint8_t Security:1; + uint8_t KeyScope:1; + uint8_t SpecMgmtCap:1; + uint8_t QosCap:1; + uint8_t apsd:1; + uint8_t rrm:1; + uint8_t DelayedBA:1; + uint8_t ImmBA:1; + uint8_t MobilityDomain:1; + uint8_t reserved:5; + uint16_t reserved1; + uint8_t regulatoryClass; + uint8_t channel; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_neighbor_report( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIENeighborReport*); + +uint32_t dot11f_pack_ie_neighbor_report( + tpAniSirGlobal, + tDot11fIENeighborReport *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_neighbor_report( + tpAniSirGlobal, + tDot11fIENeighborReport *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 74 (0x4a) */ +typedef struct sDot11fIEOBSSScanParameters { + uint8_t present; + uint16_t obssScanPassiveDwell; + uint16_t obssScanActiveDwell; + uint16_t bssChannelWidthTriggerScanInterval; + uint16_t obssScanPassiveTotalPerChannel; + uint16_t obssScanActiveTotalPerChannel; + uint16_t bssWidthChannelTransitionDelayFactor; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_obss_scan_parameters( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEOBSSScanParameters*); + +uint32_t dot11f_pack_ie_obss_scan_parameters( + tpAniSirGlobal, + tDot11fIEOBSSScanParameters *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_OBSSScanParameters( + tpAniSirGlobal, + tDot11fIEOBSSScanParameters *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 199 (0xc7) */ +typedef struct sDot11fIEOperatingMode { + uint8_t present; + uint8_t chanWidth:2; + uint8_t reserved:2; + uint8_t rxNSS:3; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_operating_mode( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEOperatingMode*); + +uint32_t dot11f_pack_ie_operating_mode( + tpAniSirGlobal, + tDot11fIEOperatingMode *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_OperatingMode( + tpAniSirGlobal, + tDot11fIEOperatingMode *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PAssocReq { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_assoc_req( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PAssocReq*); + +uint32_t dot11f_pack_ie_p2_p_assoc_req( + tpAniSirGlobal, + tDot11fIEP2PAssocReq *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_assoc_req( + tpAniSirGlobal, + tDot11fIEP2PAssocReq *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PAssocRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_assoc_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PAssocRes*); + +uint32_t dot11f_pack_ie_p2_p_assoc_res( + tpAniSirGlobal, + tDot11fIEP2PAssocRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_assoc_res( + tpAniSirGlobal, + tDot11fIEP2PAssocRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PBeacon { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_beacon( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PBeacon*); + +uint32_t dot11f_pack_ie_p2_p_beacon( + tpAniSirGlobal, + tDot11fIEP2PBeacon *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_beacon( + tpAniSirGlobal, + tDot11fIEP2PBeacon *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PBeaconProbeRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_beacon_probe_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PBeaconProbeRes*); + +uint32_t dot11f_pack_ie_p2_p_beacon_probe_res( + tpAniSirGlobal, + tDot11fIEP2PBeaconProbeRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_beacon_probe_res( + tpAniSirGlobal, + tDot11fIEP2PBeaconProbeRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PDeAuth { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_de_auth( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PDeAuth*); + +uint32_t dot11f_pack_ie_p2_p_de_auth( + tpAniSirGlobal, + tDot11fIEP2PDeAuth *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_de_auth( + tpAniSirGlobal, + tDot11fIEP2PDeAuth *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PDisAssoc { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_dis_assoc( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PDisAssoc*); + +uint32_t dot11f_pack_ie_p2_p_dis_assoc( + tpAniSirGlobal, + tDot11fIEP2PDisAssoc *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_dis_assoc( + tpAniSirGlobal, + tDot11fIEP2PDisAssoc *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} */ +typedef struct sDot11fIEP2PIEOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_pie_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PIEOpaque*); + +uint32_t dot11f_pack_ie_p2_pie_opaque( + tpAniSirGlobal, + tDot11fIEP2PIEOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_P2PIEOpaque( + tpAniSirGlobal, + tDot11fIEP2PIEOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PProbeReq { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_probe_req( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PProbeReq*); + +uint32_t dot11f_pack_ie_p2_p_probe_req( + tpAniSirGlobal, + tDot11fIEP2PProbeReq *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_probe_req( + tpAniSirGlobal, + tDot11fIEP2PProbeReq *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x09} (Multi-IE) */ +typedef struct sDot11fIEP2PProbeRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_p2_p_probe_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEP2PProbeRes*); + +uint32_t dot11f_pack_ie_p2_p_probe_res( + tpAniSirGlobal, + tDot11fIEP2PProbeRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iep2_p_probe_res( + tpAniSirGlobal, + tDot11fIEP2PProbeRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 105 (0x69) */ +typedef struct sDot11fIEPTIControl { + uint8_t present; + uint8_t tid; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_pti_control( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEPTIControl*); + +uint32_t dot11f_pack_ie_pti_control( + tpAniSirGlobal, + tDot11fIEPTIControl *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_PTIControl( + tpAniSirGlobal, + tDot11fIEPTIControl *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 106 (0x6a) */ +typedef struct sDot11fIEPUBufferStatus { + uint8_t present; + uint8_t ac_bk_traffic_aval:1; + uint8_t ac_be_traffic_aval:1; + uint8_t ac_vi_traffic_aval:1; + uint8_t ac_vo_traffic_aval:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_pu_buffer_status( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEPUBufferStatus*); + +uint32_t dot11f_pack_ie_pu_buffer_status( + tpAniSirGlobal, + tDot11fIEPUBufferStatus *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_PUBufferStatus( + tpAniSirGlobal, + tDot11fIEPUBufferStatus *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 33 (0x21) */ +typedef struct sDot11fIEPowerCaps { + uint8_t present; + uint8_t minTxPower; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_power_caps( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEPowerCaps*); + +uint32_t dot11f_pack_ie_power_caps( + tpAniSirGlobal, + tDot11fIEPowerCaps *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_PowerCaps( + tpAniSirGlobal, + tDot11fIEPowerCaps *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 32 (0x20) */ +typedef struct sDot11fIEPowerConstraints { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_power_constraints( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEPowerConstraints*); + +uint32_t dot11f_pack_ie_power_constraints( + tpAniSirGlobal, + tDot11fIEPowerConstraints *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_PowerConstraints( + tpAniSirGlobal, + tDot11fIEPowerConstraints *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 11 (0x0b) */ +typedef struct sDot11fIEQBSSLoad { + uint8_t present; + uint16_t stacount; + uint8_t chautil; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_qbss_load( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQBSSLoad*); + +uint32_t dot11f_pack_ie_qbss_load( + tpAniSirGlobal, + tDot11fIEQBSSLoad *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_QBSSLoad( + tpAniSirGlobal, + tDot11fIEQBSSLoad *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0xa0, 0xc6} */ +typedef struct sDot11fIEQComVendorIE { + uint8_t present; + uint8_t type; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_QComVendorIE( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQComVendorIE*); + +uint32_t dot11f_pack_ie_QComVendorIE( + tpAniSirGlobal, + tDot11fIEQComVendorIE *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_QComVendorIE( + tpAniSirGlobal, + tDot11fIEQComVendorIE *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 46 (0x2e) */ +typedef struct sDot11fIEQOSCapsAp { + uint8_t present; + uint8_t count:4; + uint8_t qack:1; + uint8_t qreq:1; + uint8_t txopreq:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_qos_caps_ap( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQOSCapsAp*); + +uint32_t dot11f_pack_ie_qos_caps_ap( + tpAniSirGlobal, + tDot11fIEQOSCapsAp *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_QOSCapsAp( + tpAniSirGlobal, + tDot11fIEQOSCapsAp *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 46 (0x2e) */ +typedef struct sDot11fIEQOSCapsStation { + uint8_t present; + uint8_t acvo_uapsd:1; + uint8_t acvi_uapsd:1; + uint8_t acbk_uapsd:1; + uint8_t acbe_uapsd:1; + uint8_t qack:1; + uint8_t max_sp_length:2; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_qos_caps_station( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQOSCapsStation*); + +uint32_t dot11f_pack_ie_qos_caps_station( + tpAniSirGlobal, + tDot11fIEQOSCapsStation *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_QOSCapsStation( + tpAniSirGlobal, + tDot11fIEQOSCapsStation *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 110 (0x6e) */ +typedef struct sDot11fIEQosMapSet { + uint8_t present; + uint8_t num_dscp_exceptions; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_qos_map_set( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQosMapSet*); + +uint32_t dot11f_pack_ie_qos_map_set( + tpAniSirGlobal, + tDot11fIEQosMapSet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_QosMapSet( + tpAniSirGlobal, + tDot11fIEQosMapSet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 40 (0x28) */ +typedef struct sDot11fIEQuiet { + uint8_t present; + uint8_t count; + uint8_t period; + uint16_t duration; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_quiet( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEQuiet*); + +uint32_t dot11f_pack_ie_quiet( + tpAniSirGlobal, + tDot11fIEQuiet *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_Quiet( + tpAniSirGlobal, + tDot11fIEQuiet *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 53 (0x35) */ +typedef struct sDot11fIERCPIIE { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_rcpiie( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERCPIIE*); + +uint32_t dot11f_pack_ie_rcpiie( + tpAniSirGlobal, + tDot11fIERCPIIE *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_RCPIIE( + tpAniSirGlobal, + tDot11fIERCPIIE *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 57 (0x39) */ +typedef struct sDot11fIERICDataDesc { + uint8_t present; + tDot11fIERICData RICData; + tDot11fIERICDescriptor RICDescriptor; + tDot11fIETSPEC TSPEC; + uint16_t num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIETSDelay TSDelay; + tDot11fIESchedule Schedule; + tDot11fIEWMMTSPEC WMMTSPEC; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_ric_data_desc( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERICDataDesc*); + +uint32_t dot11f_pack_ie_ric_data_desc( + tpAniSirGlobal, + tDot11fIERICDataDesc *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ieric_data_desc( + tpAniSirGlobal, + tDot11fIERICDataDesc *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 48 (0x30) */ +typedef struct sDot11fIERSN { + uint8_t present; + uint16_t version /* Must be 1! */; + uint8_t gp_cipher_suite[4]; + uint16_t pwise_cipher_suite_count; + uint8_t pwise_cipher_suites[4][4]; + uint16_t akm_suite_count; + uint8_t akm_suites[4][4]; + uint8_t RSN_Cap[2]; + uint16_t pmkid_count; + uint8_t pmkid[4][16]; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_rsn( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERSN*); + +uint32_t dot11f_pack_ie_rsn( + tpAniSirGlobal, + tDot11fIERSN *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iersn( + tpAniSirGlobal, + tDot11fIERSN *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 65 (0x41) */ +typedef struct sDot11fIERSNIIE { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_rsniie( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERSNIIE*); + +uint32_t dot11f_pack_ie_rsniie( + tpAniSirGlobal, + tDot11fIERSNIIE *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iersnIIE( + tpAniSirGlobal, + tDot11fIERSNIIE *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 48 (0x30) */ +typedef struct sDot11fIERSNOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_rsn_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIERSNOpaque*); + +uint32_t dot11f_pack_ie_rsn_opaque( + tpAniSirGlobal, + tDot11fIERSNOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iersnOpaque( + tpAniSirGlobal, + tDot11fIERSNOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 36 (0x24) */ +typedef struct sDot11fIESuppChannels { + uint8_t present; + uint8_t num_bands; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_supp_channels( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIESuppChannels*); + +uint32_t dot11f_pack_ie_supp_channels( + tpAniSirGlobal, + tDot11fIESuppChannels *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_SuppChannels( + tpAniSirGlobal, + tDot11fIESuppChannels *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 59 (0x3b) */ +typedef struct sDot11fIESuppOperatingClasses { + uint8_t present; + uint8_t num_classes; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_supp_operating_classes( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIESuppOperatingClasses*); + +uint32_t dot11f_pack_ie_supp_operating_classes( + tpAniSirGlobal, + tDot11fIESuppOperatingClasses *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_SuppOperatingClasses( + tpAniSirGlobal, + tDot11fIESuppOperatingClasses *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 1 (0x01) */ +typedef struct sDot11fIESuppRates { + uint8_t present; + uint8_t num_rates; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_supp_rates( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIESuppRates*); + +uint32_t dot11f_pack_ie_supp_rates( + tpAniSirGlobal, + tDot11fIESuppRates *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_SuppRates( + tpAniSirGlobal, + tDot11fIESuppRates *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 5 (0x05) */ +typedef struct sDot11fIETIM { + uint8_t present; + uint8_t dtim_count; + uint8_t dtim_period; + uint8_t bmpctl; + uint8_t num_vbmp; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_tim( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETIM*); + +uint32_t dot11f_pack_ie_tim( + tpAniSirGlobal, + tDot11fIETIM *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TIM( + tpAniSirGlobal, + tDot11fIETIM *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 35 (0x23) */ +typedef struct sDot11fIETPCReport { + uint8_t present; + uint8_t tx_power; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_tpc_report( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETPCReport*); + +uint32_t dot11f_pack_ie_tpc_report( + tpAniSirGlobal, + tDot11fIETPCReport *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TPCReport( + tpAniSirGlobal, + tDot11fIETPCReport *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 34 (0x22) */ +typedef struct sDot11fIETPCRequest { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_tpc_request( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETPCRequest*); + +uint32_t dot11f_pack_ie_tpc_request( + tpAniSirGlobal, + tDot11fIETPCRequest *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TPCRequest( + tpAniSirGlobal, + tDot11fIETPCRequest *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 69 (0x45) */ +typedef struct sDot11fIETimeAdvertisement { + uint8_t present; + uint8_t timing_capabilities; + uint8_t time_value[10]; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_time_advertisement( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETimeAdvertisement*); + +uint32_t dot11f_pack_ie_time_advertisement( + tpAniSirGlobal, + tDot11fIETimeAdvertisement *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_time_advertisement( + tpAniSirGlobal, + tDot11fIETimeAdvertisement *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 56 (0x38) */ +typedef struct sDot11fIETimeoutInterval { + uint8_t present; + uint8_t timeoutType; + uint32_t 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++ */ +uint32_t dot11f_unpack_ie_timeout_interval( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIETimeoutInterval*); + +uint32_t dot11f_pack_ie_timeout_interval( + tpAniSirGlobal, + tDot11fIETimeoutInterval *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_TimeoutInterval( + tpAniSirGlobal, + tDot11fIETimeoutInterval *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 193 (0xc1) */ +typedef struct sDot11fIEVHTExtBssLoad { + uint8_t present; + uint8_t muMIMOCapStaCount; + uint8_t ssUnderUtil; + uint8_t FortyMHzUtil; + uint8_t EightyMHzUtil; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_vht_ext_bss_load( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEVHTExtBssLoad*); + +uint32_t dot11f_pack_ie_vht_ext_bss_load( + tpAniSirGlobal, + tDot11fIEVHTExtBssLoad *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_VHTExtBssLoad( + tpAniSirGlobal, + tDot11fIEVHTExtBssLoad *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x10, 0x18} */ +typedef struct sDot11fIEVendor1IE { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_vendor1_ie( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEVendor1IE*); + +uint32_t dot11f_pack_ie_vendor1_ie( + tpAniSirGlobal, + tDot11fIEVendor1IE *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_Vendor1IE( + tpAniSirGlobal, + tDot11fIEVendor1IE *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x16, 0x32} */ +typedef struct sDot11fIEVendor3IE { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_vendor3_ie( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEVendor3IE*); + +uint32_t dot11f_pack_ie_vendor3_ie( + tpAniSirGlobal, + tDot11fIEVendor3IE *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_Vendor3IE( + tpAniSirGlobal, + tDot11fIEVendor3IE *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 68 (0x44) */ +typedef struct sDot11fIEWAPI { + uint8_t present; + uint16_t version /* Must be 1! */; + uint16_t akm_suite_count; + uint8_t akm_suites[4][4]; + uint16_t unicast_cipher_suite_count; + uint8_t unicast_cipher_suites[4][4]; + uint8_t multicast_cipher_suite[4]; + uint16_t preauth:1; + uint16_t reserved:15; + uint16_t bkid_count; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wapi( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWAPI*); + +uint32_t dot11f_pack_ie_wapi( + tpAniSirGlobal, + tDot11fIEWAPI *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewapi( + tpAniSirGlobal, + tDot11fIEWAPI *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 68 (0x44) */ +typedef struct sDot11fIEWAPIOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wapi_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWAPIOpaque*); + +uint32_t dot11f_pack_ie_wapi_opaque( + tpAniSirGlobal, + tDot11fIEWAPIOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewapiOpaque( + tpAniSirGlobal, + tDot11fIEWAPIOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x08, 0x00} */ +typedef struct sDot11fIEWFATPC { + uint8_t present; + uint8_t txPower; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wfatpc( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWFATPC*); + +uint32_t dot11f_pack_ie_wfatpc( + tpAniSirGlobal, + tDot11fIEWFATPC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WFATPC( + tpAniSirGlobal, + tDot11fIEWFATPC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x0a} */ +typedef struct sDot11fIEWFDIEOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wfdie_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWFDIEOpaque*); + +uint32_t dot11f_pack_ie_wfdie_opaque( + tpAniSirGlobal, + tDot11fIEWFDIEOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WFDIEOpaque( + tpAniSirGlobal, + tDot11fIEWFDIEOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x05} */ +typedef struct sDot11fIEWMMCaps { + uint8_t present; + uint8_t version /* Must be 1! */; + uint8_t reserved:4; + uint8_t qack:1; + uint8_t queue_request:1; + uint8_t txop_request:1; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wmm_caps( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMCaps*); + +uint32_t dot11f_pack_ie_wmm_caps( + tpAniSirGlobal, + tDot11fIEWMMCaps *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMCaps( + tpAniSirGlobal, + tDot11fIEWMMCaps *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x00} */ +typedef struct sDot11fIEWMMInfoAp { + uint8_t present; + uint8_t version; + uint8_t param_set_count:4; + uint8_t reserved:3; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wmm_info_ap( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMInfoAp*); + +uint32_t dot11f_pack_ie_wmm_info_ap( + tpAniSirGlobal, + tDot11fIEWMMInfoAp *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMInfoAp( + tpAniSirGlobal, + tDot11fIEWMMInfoAp *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x00} */ +typedef struct sDot11fIEWMMInfoStation { + uint8_t present; + uint8_t version; + uint8_t acvo_uapsd:1; + uint8_t acvi_uapsd:1; + uint8_t acbk_uapsd:1; + uint8_t acbe_uapsd:1; + uint8_t reserved1:1; + uint8_t max_sp_length:2; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wmm_info_station( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMInfoStation*); + +uint32_t dot11f_pack_ie_wmm_info_station( + tpAniSirGlobal, + tDot11fIEWMMInfoStation *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMInfoStation( + tpAniSirGlobal, + tDot11fIEWMMInfoStation *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x02, 0x01} */ +typedef struct sDot11fIEWMMParams { + uint8_t present; + uint8_t version /* Must be 1! */; + uint8_t qosInfo; + uint8_t reserved2; + uint8_t acbe_aifsn:4; + uint8_t acbe_acm:1; + uint8_t acbe_aci:2; + uint8_t unused1:1; + uint8_t acbe_acwmin:4; + uint8_t acbe_acwmax:4; + uint16_t acbe_txoplimit; + uint8_t acbk_aifsn:4; + uint8_t acbk_acm:1; + uint8_t acbk_aci:2; + uint8_t unused2:1; + uint8_t acbk_acwmin:4; + uint8_t acbk_acwmax:4; + uint16_t acbk_txoplimit; + uint8_t acvi_aifsn:4; + uint8_t acvi_acm:1; + uint8_t acvi_aci:2; + uint8_t unused3:1; + uint8_t acvi_acwmin:4; + uint8_t acvi_acwmax:4; + uint16_t acvi_txoplimit; + uint8_t acvo_aifsn:4; + uint8_t acvo_acm:1; + uint8_t acvo_aci:2; + uint8_t unused4:1; + uint8_t acvo_acwmin:4; + uint8_t acvo_acwmax:4; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_wmm_params( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWMMParams*); + +uint32_t dot11f_pack_ie_wmm_params( + tpAniSirGlobal, + tDot11fIEWMMParams *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WMMParams( + tpAniSirGlobal, + tDot11fIEWMMParams *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x01} */ +typedef struct sDot11fIEWPA { + uint8_t present; + uint16_t version /* Must be 1! */; + /* field added to fix the bug in dot11fPackIEWPA */ + uint8_t multicast_cipher_present; + uint8_t multicast_cipher[4]; + uint16_t unicast_cipher_count; + uint8_t unicast_ciphers[4][4]; + uint16_t auth_suite_count; + uint8_t auth_suites[4][4]; + uint16_t 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++ */ +uint32_t dot11f_unpack_ie_wpa( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWPA*); + +uint32_t dot11f_pack_ie_wpa( + tpAniSirGlobal, + tDot11fIEWPA *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewpa( + tpAniSirGlobal, + tDot11fIEWPA *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x01} */ +typedef struct sDot11fIEWPAOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wpa_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWPAOpaque*); + +uint32_t dot11f_pack_ie_wpa_opaque( + tpAniSirGlobal, + tDot11fIEWPAOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewpaOpaque( + tpAniSirGlobal, + tDot11fIEWPAOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWSC { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWSC*); + +uint32_t dot11f_pack_ie_wsc( + tpAniSirGlobal, + tDot11fIEWSC *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_iewsc( + tpAniSirGlobal, + tDot11fIEWSC *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscAssocReq { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_assoc_req( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscAssocReq*); + +uint32_t dot11f_pack_ie_wsc_assoc_req( + tpAniSirGlobal, + tDot11fIEWscAssocReq *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_assoc_req( + tpAniSirGlobal, + tDot11fIEWscAssocReq *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscAssocRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_assoc_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscAssocRes*); + +uint32_t dot11f_pack_ie_wsc_assoc_res( + tpAniSirGlobal, + tDot11fIEWscAssocRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_assoc_res( + tpAniSirGlobal, + tDot11fIEWscAssocRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscBeacon { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_beacon( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscBeacon*); + +uint32_t dot11f_pack_ie_wsc_beacon( + tpAniSirGlobal, + tDot11fIEWscBeacon *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_beacon( + tpAniSirGlobal, + tDot11fIEWscBeacon *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscBeaconProbeRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_beacon_probe_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscBeaconProbeRes*); + +uint32_t dot11f_pack_ie_wsc_beacon_probe_res( + tpAniSirGlobal, + tDot11fIEWscBeaconProbeRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_beacon_probe_res( + tpAniSirGlobal, + tDot11fIEWscBeaconProbeRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} */ +typedef struct sDot11fIEWscIEOpaque { + uint8_t present; + uint8_t num_data; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_ie_opaque( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscIEOpaque*); + +uint32_t dot11f_pack_ie_wsc_ie_opaque( + tpAniSirGlobal, + tDot11fIEWscIEOpaque *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_WscIEOpaque( + tpAniSirGlobal, + tDot11fIEWscIEOpaque *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscProbeReq { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_probe_req( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscProbeReq*); + +uint32_t dot11f_pack_ie_wsc_probe_req( + tpAniSirGlobal, + tDot11fIEWscProbeReq *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_probe_req( + tpAniSirGlobal, + tDot11fIEWscProbeReq *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscProbeRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_probe_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscProbeRes*); + +uint32_t dot11f_pack_ie_wsc_probe_res( + tpAniSirGlobal, + tDot11fIEWscProbeRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_probe_res( + tpAniSirGlobal, + tDot11fIEWscProbeRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x50, 0xf2, 0x04} (Multi-IE) */ +typedef struct sDot11fIEWscReassocRes { + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_wsc_reassoc_res( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEWscReassocRes*); + +uint32_t dot11f_pack_ie_wsc_reassoc_res( + tpAniSirGlobal, + tDot11fIEWscReassocRes *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_wsc_reassoc_res( + tpAniSirGlobal, + tDot11fIEWscReassocRes *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 60 (0x3c) */ +typedef struct sDot11fIEext_chan_switch_ann { + uint8_t present; + uint8_t switch_mode; + uint8_t new_reg_class; + uint8_t new_channel; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_ext_chan_switch_ann( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEext_chan_switch_ann*); + +uint32_t dot11f_pack_ie_ext_chan_switch_ann( + tpAniSirGlobal, + tDot11fIEext_chan_switch_ann *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ext_chan_switch_ann( + tpAniSirGlobal, + tDot11fIEext_chan_switch_ann *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 72 (0x48) */ +typedef struct sDot11fIEht2040_bss_coexistence { + uint8_t present; + uint8_t info_request:1; + uint8_t forty_mhz_intolerant:1; + uint8_t twenty_mhz_bsswidth_req:1; + uint8_t obss_scan_exemption_req:1; + uint8_t obss_scan_exemption_grant:1; + uint8_t unused:3; +} tDot11fIEht2040_bss_coexistence; + +#define DOT11F_EID_HT2040_BSS_COEXISTENCE (72) + +/* N.B. These #defines do *not* include the EID & length */ +#define DOT11F_IE_HT2040_BSS_COEXISTENCE_MIN_LEN (1) + +#define DOT11F_IE_HT2040_BSS_COEXISTENCE_MAX_LEN (1) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +uint32_t dot11f_unpack_ie_ht2040_bss_coexistence( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEht2040_bss_coexistence*); + +uint32_t dot11f_pack_ie_ht2040_bss_coexistence( + tpAniSirGlobal, + tDot11fIEht2040_bss_coexistence *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ht2040_bss_coexistence( + tpAniSirGlobal, + tDot11fIEht2040_bss_coexistence *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 73 (0x49) */ +typedef struct sDot11fIEht2040_bss_intolerant_report { + uint8_t present; + uint8_t operating_class; + uint8_t num_channel_list; + uint8_t channel_list[50]; +} tDot11fIEht2040_bss_intolerant_report; + +#define DOT11F_EID_HT2040_BSS_INTOLERANT_REPORT (73) + +/* N.B. These #defines do *not* include the EID & length */ +#define DOT11F_IE_HT2040_BSS_INTOLERANT_REPORT_MIN_LEN (1) + +#define DOT11F_IE_HT2040_BSS_INTOLERANT_REPORT_MAX_LEN (51) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +uint32_t dot11f_unpack_ie_ht2040_bss_intolerant_report( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEht2040_bss_intolerant_report*); + +uint32_t dot11f_pack_ie_ht2040_bss_intolerant_report( + tpAniSirGlobal, + tDot11fIEht2040_bss_intolerant_report *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_ht2040_bss_intolerant_report( + tpAniSirGlobal, + tDot11fIEht2040_bss_intolerant_report *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 62 (0x3e) */ +typedef struct sDot11fIEsec_chan_offset_ele { + uint8_t present; + uint8_t 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++ */ +uint32_t dot11f_unpack_ie_sec_chan_offset_ele( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEsec_chan_offset_ele*); + +uint32_t dot11f_pack_ie_sec_chan_offset_ele( + tpAniSirGlobal, + tDot11fIEsec_chan_offset_ele *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_sec_chan_offset_ele( + tpAniSirGlobal, + tDot11fIEsec_chan_offset_ele *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ + +/* EID 221 (0xdd) {OUI 0x00, 0x90, 0x4c} */ +typedef struct sDot11fIEvendor2_ie { + uint8_t present; + uint8_t type; + uint8_t sub_type; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; +} tDot11fIEvendor2_ie; + +#define DOT11F_EID_VENDOR2_IE (221) + +/* N.B. These #defines do *not* include the EID & length */ +#define DOT11F_IE_VENDOR2_IE_MIN_LEN (5) + +#define DOT11F_IE_VENDOR2_IE_MAX_LEN (26) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +uint32_t dot11f_unpack_ie_vendor2_ie( + tpAniSirGlobal, + uint8_t *, + uint8_t, + tDot11fIEvendor2_ie*); + +uint32_t dot11f_pack_ie_vendor2_ie( + tpAniSirGlobal, + tDot11fIEvendor2_ie *, + uint8_t *, + uint32_t, + uint32_t*); + +uint32_t dot11f_get_packed_ie_vendor2_ie( + tpAniSirGlobal, + tDot11fIEvendor2_ie *, + uint32_t*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +/************************************************************************ + * Frames + **********************************************************************/ + +typedef struct sDot11fAddTSRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETSPEC TSPEC; + uint16_t num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIEWMMTSPEC WMMTSPEC; + uint16_t num_WMMTCLAS; + tDot11fIEWMMTCLAS WMMTCLAS[2]; + tDot11fIEWMMTCLASPROC WMMTCLASPROC; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; +} tDot11fAddTSRequest; + +#define DOT11F_ADDTSREQUEST (1) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_add_ts_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAddTSRequest * pFrm); +uint32_t dot11f_pack_add_ts_request(tpAniSirGlobal pCtx, + tDot11fAddTSRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_add_ts_request_size(tpAniSirGlobal pCtx, + tDot11fAddTSRequest *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fAddTSResponse{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfStatus Status; + tDot11fIETSDelay TSDelay; + tDot11fIETSPEC TSPEC; + uint16_t num_TCLAS; + tDot11fIETCLAS TCLAS[2]; + tDot11fIETCLASSPROC TCLASSPROC; + tDot11fIESchedule Schedule; + tDot11fIEWMMTSDelay WMMTSDelay; + tDot11fIEWMMSchedule WMMSchedule; + tDot11fIEWMMTSPEC WMMTSPEC; + uint16_t num_WMMTCLAS; + tDot11fIEWMMTCLAS WMMTCLAS[2]; + tDot11fIEWMMTCLASPROC WMMTCLASPROC; + tDot11fIEESETrafStrmMet ESETrafStrmMet; +} tDot11fAddTSResponse; + +#define DOT11F_ADDTSRESPONSE (2) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_add_ts_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAddTSResponse * pFrm); +uint32_t dot11f_pack_add_ts_response(tpAniSirGlobal pCtx, + tDot11fAddTSResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_add_ts_response_size(tpAniSirGlobal pCtx, + tDot11fAddTSResponse *pFrm, + uint32_t *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; + tDot11fIEvendor2_ie vendor2_ie; +} tDot11fAssocRequest; + +#define DOT11F_ASSOCREQUEST (3) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_assoc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAssocRequest * pFrm); +uint32_t dot11f_pack_assoc_request(tpAniSirGlobal pCtx, + tDot11fAssocRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_assoc_request_size(tpAniSirGlobal pCtx, + tDot11fAssocRequest *pFrm, + uint32_t *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; + uint16_t num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; + tDot11fIEWPA WPA; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEWMMParams WMMParams; + tDot11fIEWMMCaps WMMCaps; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + uint16_t num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEWscAssocRes WscAssocRes; + tDot11fIEP2PAssocRes P2PAssocRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEExtCap ExtCap; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEQosMapSet QosMapSet; + tDot11fIEvendor2_ie vendor2_ie; +} tDot11fAssocResponse; + +#define DOT11F_ASSOCRESPONSE (4) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_assoc_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAssocResponse * pFrm); +uint32_t dot11f_pack_assoc_response(tpAniSirGlobal pCtx, + tDot11fAssocResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_assoc_response_size(tpAniSirGlobal pCtx, + tDot11fAssocResponse *pFrm, + uint32_t *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; + uint16_t num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; +} tDot11fAuthentication; + +#define DOT11F_AUTHENTICATION (5) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_authentication(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAuthentication * pFrm); +uint32_t dot11f_pack_authentication(tpAniSirGlobal pCtx, + tDot11fAuthentication *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_authentication_size(tpAniSirGlobal pCtx, + tDot11fAuthentication *pFrm, + uint32_t *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; + 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; + tDot11fIEvendor2_ie vendor2_ie; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fBeacon; + +#define DOT11F_BEACON (6) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_beacon(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon * pFrm); +uint32_t dot11f_pack_beacon(tpAniSirGlobal pCtx, + tDot11fBeacon *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_beacon_size(tpAniSirGlobal pCtx, + tDot11fBeacon *pFrm, + uint32_t *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 (7) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_beacon1(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon1 * pFrm); +uint32_t dot11f_pack_beacon1(tpAniSirGlobal pCtx, + tDot11fBeacon1 *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_beacon1_size(tpAniSirGlobal pCtx, + tDot11fBeacon1 *pFrm, + uint32_t *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; + 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; + tDot11fIEvendor2_ie vendor2_ie; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fBeacon2; + +#define DOT11F_BEACON2 (8) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_beacon2(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon2 * pFrm); +uint32_t dot11f_pack_beacon2(tpAniSirGlobal pCtx, + tDot11fBeacon2 *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_beacon2_size(tpAniSirGlobal pCtx, + tDot11fBeacon2 *pFrm, + uint32_t *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; + 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; + tDot11fIEvendor2_ie vendor2_ie; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; +} tDot11fBeaconIEs; + +#define DOT11F_BEACONIES (9) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_beacon_i_es(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeaconIEs * pFrm); +uint32_t dot11f_pack_beacon_i_es(tpAniSirGlobal pCtx, + tDot11fBeaconIEs *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_beacon_i_es_size(tpAniSirGlobal pCtx, + tDot11fBeaconIEs *pFrm, + uint32_t *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 (10) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_channel_switch(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fChannelSwitch * pFrm); +uint32_t dot11f_pack_channel_switch(tpAniSirGlobal pCtx, + tDot11fChannelSwitch *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_channel_switch_size(tpAniSirGlobal pCtx, + tDot11fChannelSwitch *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDeAuth{ + tDot11fFfReason Reason; + tDot11fIEP2PDeAuth P2PDeAuth; +} tDot11fDeAuth; + +#define DOT11F_DEAUTH (11) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_de_auth(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDeAuth * pFrm); +uint32_t dot11f_pack_de_auth(tpAniSirGlobal pCtx, + tDot11fDeAuth *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_de_auth_size(tpAniSirGlobal pCtx, + tDot11fDeAuth *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDelTS{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTSInfo TSInfo; + tDot11fFfReason Reason; +} tDot11fDelTS; + +#define DOT11F_DELTS (12) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_del_ts(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDelTS * pFrm); +uint32_t dot11f_pack_del_ts(tpAniSirGlobal pCtx, + tDot11fDelTS *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_del_ts_size(tpAniSirGlobal pCtx, + tDot11fDelTS *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fDisassociation{ + tDot11fFfReason Reason; + tDot11fIEP2PDisAssoc P2PDisAssoc; +} tDot11fDisassociation; + +#define DOT11F_DISASSOCIATION (13) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_disassociation(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDisassociation * pFrm); +uint32_t dot11f_pack_disassociation(tpAniSirGlobal pCtx, + tDot11fDisassociation *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_disassociation_size(tpAniSirGlobal pCtx, + tDot11fDisassociation *pFrm, + uint32_t *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 (14) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_link_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fLinkMeasurementReport * pFrm); +uint32_t dot11f_pack_link_measurement_report(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementReport *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_link_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementReport *pFrm, + uint32_t *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 (15) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_link_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fLinkMeasurementRequest * pFrm); +uint32_t dot11f_pack_link_measurement_request(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_link_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementRequest *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fMeasurementReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIEMeasurementReport MeasurementReport; +} tDot11fMeasurementReport; + +#define DOT11F_MEASUREMENTREPORT (16) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fMeasurementReport * pFrm); +uint32_t dot11f_pack_measurement_report(tpAniSirGlobal pCtx, + tDot11fMeasurementReport *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fMeasurementReport *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fMeasurementRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + uint16_t num_MeasurementRequest; + tDot11fIEMeasurementRequest MeasurementRequest[4]; +} tDot11fMeasurementRequest; + +#define DOT11F_MEASUREMENTREQUEST (17) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fMeasurementRequest * pFrm); +uint32_t dot11f_pack_measurement_request(tpAniSirGlobal pCtx, + tDot11fMeasurementRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fMeasurementRequest *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fNeighborReportRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIESSID SSID; +} tDot11fNeighborReportRequest; + +#define DOT11F_NEIGHBORREPORTREQUEST (18) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_neighbor_report_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fNeighborReportRequest * pFrm); +uint32_t dot11f_pack_neighbor_report_request(tpAniSirGlobal pCtx, + tDot11fNeighborReportRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_neighbor_report_request_size(tpAniSirGlobal pCtx, + tDot11fNeighborReportRequest *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fNeighborReportResponse{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + uint16_t num_NeighborReport; + tDot11fIENeighborReport NeighborReport[15]; +} tDot11fNeighborReportResponse; + +#define DOT11F_NEIGHBORREPORTRESPONSE (19) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_neighbor_report_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fNeighborReportResponse * pFrm); +uint32_t dot11f_pack_neighbor_report_response(tpAniSirGlobal pCtx, + tDot11fNeighborReportResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_neighbor_report_response_size(tpAniSirGlobal pCtx, + tDot11fNeighborReportResponse *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fOperatingMode{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfOperatingMode OperatingMode; +} tDot11fOperatingMode; + +#define DOT11F_OPERATINGMODE (20) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_operating_mode(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fOperatingMode * pFrm); +uint32_t dot11f_pack_operating_mode(tpAniSirGlobal pCtx, + tDot11fOperatingMode *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_operating_mode_size(tpAniSirGlobal pCtx, + tDot11fOperatingMode *pFrm, + uint32_t *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 (21) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_probe_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fProbeRequest * pFrm); +uint32_t dot11f_pack_probe_request(tpAniSirGlobal pCtx, + tDot11fProbeRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_probe_request_size(tpAniSirGlobal pCtx, + tDot11fProbeRequest *pFrm, + uint32_t *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; + 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; + tDot11fIEvendor2_ie vendor2_ie; + tDot11fIEVendor3IE Vendor3IE; + tDot11fIEChannelSwitchWrapper ChannelSwitchWrapper; + tDot11fIEQComVendorIE QComVendorIE; + tDot11fIEESEVersion ESEVersion; +} tDot11fProbeResponse; + +#define DOT11F_PROBERESPONSE (22) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_probe_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fProbeResponse * pFrm); +uint32_t dot11f_pack_probe_response(tpAniSirGlobal pCtx, + tDot11fProbeResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_probe_response_size(tpAniSirGlobal pCtx, + tDot11fProbeResponse *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fQosMapConfigure{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fIEQosMapSet QosMapSet; +} tDot11fQosMapConfigure; + +#define DOT11F_QOSMAPCONFIGURE (23) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_qos_map_configure(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fQosMapConfigure * pFrm); +uint32_t dot11f_pack_qos_map_configure(tpAniSirGlobal pCtx, + tDot11fQosMapConfigure *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_qos_map_configure_size(tpAniSirGlobal pCtx, + tDot11fQosMapConfigure *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fRadioMeasurementReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + uint16_t num_MeasurementReport; + tDot11fIEMeasurementReport MeasurementReport[4]; +} tDot11fRadioMeasurementReport; + +#define DOT11F_RADIOMEASUREMENTREPORT (24) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_radio_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fRadioMeasurementReport * pFrm); +uint32_t dot11f_pack_radio_measurement_report(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementReport *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_radio_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementReport *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fRadioMeasurementRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fFfNumOfRepetitions NumOfRepetitions; + uint16_t num_MeasurementRequest; + tDot11fIEMeasurementRequest MeasurementRequest[2]; +} tDot11fRadioMeasurementRequest; + +#define DOT11F_RADIOMEASUREMENTREQUEST (25) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_radio_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fRadioMeasurementRequest * pFrm); +uint32_t dot11f_pack_radio_measurement_request(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_radio_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementRequest *pFrm, + uint32_t *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; + uint16_t 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; + uint16_t num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; + tDot11fIEP2PIEOpaque P2PIEOpaque; + tDot11fIEWFDIEOpaque WFDIEOpaque; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEExtCap ExtCap; + tDot11fIEOperatingMode OperatingMode; + tDot11fIEQosMapSet QosMapSet; + tDot11fIEvendor2_ie vendor2_ie; +} tDot11fReAssocRequest; + +#define DOT11F_REASSOCREQUEST (26) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_re_assoc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fReAssocRequest * pFrm); +uint32_t dot11f_pack_re_assoc_request(tpAniSirGlobal pCtx, + tDot11fReAssocRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_re_assoc_request_size(tpAniSirGlobal pCtx, + tDot11fReAssocRequest *pFrm, + uint32_t *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; + uint16_t num_RICDataDesc; + tDot11fIERICDataDesc RICDataDesc[2]; + tDot11fIEWPA WPA; + tDot11fIETimeoutInterval TimeoutInterval; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEWMMParams WMMParams; + tDot11fIEESERadMgmtCap ESERadMgmtCap; + tDot11fIEESETrafStrmMet ESETrafStrmMet; + tDot11fIEESETxmitPower ESETxmitPower; + uint16_t num_WMMTSPEC; + tDot11fIEWMMTSPEC WMMTSPEC[4]; + tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet; + tDot11fIEWscReassocRes WscReassocRes; + tDot11fIEP2PAssocRes P2PAssocRes; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEExtCap ExtCap; + tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEQosMapSet QosMapSet; + tDot11fIEvendor2_ie vendor2_ie; +} tDot11fReAssocResponse; + +#define DOT11F_REASSOCRESPONSE (27) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_re_assoc_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fReAssocResponse * pFrm); +uint32_t dot11f_pack_re_assoc_response(tpAniSirGlobal pCtx, + tDot11fReAssocResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_re_assoc_response_size(tpAniSirGlobal pCtx, + tDot11fReAssocResponse *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSMPowerSave{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfSMPowerModeSet SMPowerModeSet; +} tDot11fSMPowerSave; + +#define DOT11F_SMPOWERSAVE (28) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_sm_power_save(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSMPowerSave * pFrm); +uint32_t dot11f_pack_sm_power_save(tpAniSirGlobal pCtx, + tDot11fSMPowerSave *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_sm_power_save_size(tpAniSirGlobal pCtx, + tDot11fSMPowerSave *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSaQueryReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTransactionId TransactionId; +} tDot11fSaQueryReq; + +#define DOT11F_SAQUERYREQ (29) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_sa_query_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSaQueryReq * pFrm); +uint32_t dot11f_pack_sa_query_req(tpAniSirGlobal pCtx, + tDot11fSaQueryReq *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_sa_query_req_size(tpAniSirGlobal pCtx, + tDot11fSaQueryReq *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fSaQueryRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfTransactionId TransactionId; +} tDot11fSaQueryRsp; + +#define DOT11F_SAQUERYRSP (30) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_sa_query_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSaQueryRsp * pFrm); +uint32_t dot11f_pack_sa_query_rsp(tpAniSirGlobal pCtx, + tDot11fSaQueryRsp *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_sa_query_rsp_size(tpAniSirGlobal pCtx, + tDot11fSaQueryRsp *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSDisReq{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIELinkIdentifier LinkIdentifier; +} tDot11fTDLSDisReq; + +#define DOT11F_TDLSDISREQ (31) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_dis_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSDisReq * pFrm); +uint32_t dot11f_pack_tdls_dis_req(tpAniSirGlobal pCtx, + tDot11fTDLSDisReq *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_dis_req_size(tpAniSirGlobal pCtx, + tDot11fTDLSDisReq *pFrm, + uint32_t *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; + tDot11fIEht2040_bss_coexistence ht2040_bss_coexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEVHTCaps VHTCaps; +} tDot11fTDLSDisRsp; + +#define DOT11F_TDLSDISRSP (32) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_dis_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSDisRsp * pFrm); +uint32_t dot11f_pack_tdls_dis_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSDisRsp *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_dis_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSDisRsp *pFrm, + uint32_t *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 (33) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_peer_traffic_ind(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSPeerTrafficInd * pFrm); +uint32_t dot11f_pack_tdls_peer_traffic_ind(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficInd *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_peer_traffic_ind_size(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficInd *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTDLSPeerTrafficRsp{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIELinkIdentifier LinkIdentifier; +} tDot11fTDLSPeerTrafficRsp; + +#define DOT11F_TDLSPEERTRAFFICRSP (34) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_peer_traffic_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSPeerTrafficRsp * pFrm); +uint32_t dot11f_pack_tdls_peer_traffic_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficRsp *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_peer_traffic_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficRsp *pFrm, + uint32_t *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 (35) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_setup_cnf(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupCnf * pFrm); +uint32_t dot11f_pack_tdls_setup_cnf(tpAniSirGlobal pCtx, + tDot11fTDLSSetupCnf *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_setup_cnf_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupCnf *pFrm, + uint32_t *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; + tDot11fIEht2040_bss_coexistence ht2040_bss_coexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEAID AID; + tDot11fIEVHTCaps VHTCaps; +} tDot11fTDLSSetupReq; + +#define DOT11F_TDLSSETUPREQ (36) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_setup_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupReq * pFrm); +uint32_t dot11f_pack_tdls_setup_req(tpAniSirGlobal pCtx, + tDot11fTDLSSetupReq *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_setup_req_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupReq *pFrm, + uint32_t *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; + tDot11fIEht2040_bss_coexistence ht2040_bss_coexistence; + tDot11fIELinkIdentifier LinkIdentifier; + tDot11fIEWMMInfoStation WMMInfoStation; + tDot11fIEAID AID; + tDot11fIEVHTCaps VHTCaps; + tDot11fIEOperatingMode OperatingMode; +} tDot11fTDLSSetupRsp; + +#define DOT11F_TDLSSETUPRSP (37) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_setup_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupRsp * pFrm); +uint32_t dot11f_pack_tdls_setup_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSSetupRsp *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_setup_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupRsp *pFrm, + uint32_t *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 (38) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tdls_teardown(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSTeardown * pFrm); +uint32_t dot11f_pack_tdls_teardown(tpAniSirGlobal pCtx, + tDot11fTDLSTeardown *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tdls_teardown_size(tpAniSirGlobal pCtx, + tDot11fTDLSTeardown *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTPCReport{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETPCReport TPCReport; +} tDot11fTPCReport; + +#define DOT11F_TPCREPORT (39) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tpc_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTPCReport * pFrm); +uint32_t dot11f_pack_tpc_report(tpAniSirGlobal pCtx, + tDot11fTPCReport *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tpc_report_size(tpAniSirGlobal pCtx, + tDot11fTPCReport *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fTPCRequest{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfDialogToken DialogToken; + tDot11fIETPCRequest TPCRequest; +} tDot11fTPCRequest; + +#define DOT11F_TPCREQUEST (40) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_tpc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTPCRequest * pFrm); +uint32_t dot11f_pack_tpc_request(tpAniSirGlobal pCtx, + tDot11fTPCRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_tpc_request_size(tpAniSirGlobal pCtx, + tDot11fTPCRequest *pFrm, + uint32_t *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; + tDot11fIEVendor3IE Vendor3IE; +} tDot11fTimingAdvertisementFrame; + +#define DOT11F_TIMINGADVERTISEMENTFRAME (41) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_timing_advertisement_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTimingAdvertisementFrame * pFrm); +uint32_t dot11f_pack_timing_advertisement_frame(tpAniSirGlobal pCtx, + tDot11fTimingAdvertisementFrame *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_timing_advertisement_frame_size(tpAniSirGlobal pCtx, + tDot11fTimingAdvertisementFrame *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fVHTGidManagementActionFrame{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fFfVhtMembershipStatusArray VhtMembershipStatusArray; + tDot11fFfVhtUserPositionArray VhtUserPositionArray; +} tDot11fVHTGidManagementActionFrame; + +#define DOT11F_VHTGIDMANAGEMENTACTIONFRAME (42) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_vht_gid_management_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fVHTGidManagementActionFrame * pFrm); +uint32_t dot11f_pack_vht_gid_management_action_frame(tpAniSirGlobal pCtx, + tDot11fVHTGidManagementActionFrame *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_vht_gid_management_action_frame_size(tpAniSirGlobal pCtx, + tDot11fVHTGidManagementActionFrame *pFrm, + uint32_t *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 (43) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_wmm_add_ts_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMAddTSRequest * pFrm); +uint32_t dot11f_pack_wmm_add_ts_request(tpAniSirGlobal pCtx, + tDot11fWMMAddTSRequest *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_wmm_add_ts_request_size(tpAniSirGlobal pCtx, + tDot11fWMMAddTSRequest *pFrm, + uint32_t *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 (44) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_wmm_add_ts_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMAddTSResponse * pFrm); +uint32_t dot11f_pack_wmm_add_ts_response(tpAniSirGlobal pCtx, + tDot11fWMMAddTSResponse *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_wmm_add_ts_response_size(tpAniSirGlobal pCtx, + tDot11fWMMAddTSResponse *pFrm, + uint32_t *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 (45) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_wmm_del_ts(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMDelTS * pFrm); +uint32_t dot11f_pack_wmm_del_ts(tpAniSirGlobal pCtx, + tDot11fWMMDelTS *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_wmm_del_ts_size(tpAniSirGlobal pCtx, + tDot11fWMMDelTS *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +typedef struct sDot11fht2040_bss_coexistence_mgmt_action_frame{ + tDot11fFfCategory Category; + tDot11fFfAction Action; + tDot11fIEht2040_bss_coexistence ht2040_bss_coexistence; + tDot11fIEht2040_bss_intolerant_report ht2040_bss_intolerant_report; +} tDot11fht2040_bss_coexistence_mgmt_action_frame; + +#define DOT11F_HT2040_BSS_COEXISTENCE_MGMT_ACTION_FRAME (46) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_ht2040_bss_coexistence_mgmt_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fht2040_bss_coexistence_mgmt_action_frame * pFrm); +uint32_t dot11f_pack_ht2040_bss_coexistence_mgmt_action_frame(tpAniSirGlobal pCtx, + tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_ht2040_bss_coexistence_mgmt_action_frameSize(tpAniSirGlobal pCtx, + tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + +#endif /* DOT11F_H */ diff --git a/core/mac/src/include/dph_global.h b/core/mac/src/include/dph_global.h new file mode 100644 index 000000000000..ae590db66603 --- /dev/null +++ b/core/mac/src/include/dph_global.h @@ -0,0 +1,258 @@ +/* + * 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 __DPH_GLOBAL_H__ +#define __DPH_GLOBAL_H__ + +#include "lim_global.h" +#include "sir_mac_prot_def.h" +#include "sir_mac_prop_exts.h" +#include "sir_api.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 { + uint32_t hi; + uint32_t lo; +} tDphRateBasedCtr; + +typedef struct sDphPhyRates { + uint8_t dataRateX2; + uint8_t ackRateX2; + uint8_t rtsRateX2; +} tDphPhyRates; + +typedef struct sDphIFSValues { + uint8_t sifs; + uint8_t pifs; + uint8_t difs; + uint8_t preamble; +} tDphIFSValues; + +typedef struct sDphQosParams { + uint8_t addtsPresent; + tSirAddtsReqInfo addts; + tSirMacQosCapabilityStaIE capability; +} tDphQosParams; + +/* Queue attribute structure */ +typedef struct sDphQueueAttr { + uint16_t valid:1; + uint16_t seqNum:12; + uint16_t ackPolicy:2; + uint16_t rsvd:1; +} tDphQueueAttr, *tpDphQueueAttr; + +/* STA state node */ +typedef struct sDphHashNode { + /* + * BYTE 0 + * HASH ENTRY FIELDS NOT NEEDED IN HAL. + * This STA valid or not + */ + uint8_t valid:1; + uint8_t encPolicy:3; + uint8_t defaultKey:1; + uint8_t defaultKeyId:2; + uint8_t qosMode:1; + /* BYTE 1 */ + uint8_t erpEnabled:1; + /* This has been added to the dph hash table */ + uint8_t added:1; + uint8_t linkTestOn:1; + uint8_t shortPreambleEnabled:1; + uint8_t shortSlotTimeEnabled:1; + uint8_t stopTx:1; + /* set if both ap and sta are wme capable */ + uint8_t wmeEnabled:1; + /* set if both ap and sta are 11e capable */ + uint8_t lleEnabled:1; + /* BYTE 2 */ + /* set if both ap and sta are wsm capable */ + uint8_t wsmEnabled:1; + /* station gave version info */ + uint8_t versionPresent:1; + /* allow bursting regardless of qosMode */ + uint8_t burstEnableForce:1; + uint8_t staAuthenticated:1; + uint8_t fAniCount:1; + uint8_t rmfEnabled:1; + /* Fragmentation size */ + uint16_t fragSize; + /* LIM state */ + tLimMlmStaContext mlmStaContext; + /* Number of Tim to wait if the STA doesn't respond / fetch data */ + uint8_t timWaitCount; + /* Number of Successful MPDU's being sent */ + uint32_t curTxMpduCnt; + /* number of consecutive TIMs sent without response */ + uint8_t numTimSent; + /* qos parameter info */ + tDphQosParams qos; + /* station version info - valid only if versionPresent is set */ + tSirMacPropVersion version; +#ifdef PLM_WDS + uint8_t wdsIndex; + uint8_t wdsPeerBeaconSeen; +#endif + /* Taurus capabilities */ + uint16_t baPolicyFlag; /* BA Policy for each TID. */ + /* + * All the legacy and airgo supported rates. + */ + tSirSupportedRates supportedRates; + uint8_t htGreenfield:1; + uint8_t htShortGI40Mhz:1; + uint8_t htShortGI20Mhz:1; + /* DSSS/CCK at 40 MHz: Enabled 1 or Disabled */ + uint8_t htDsssCckRate40MHzSupport:1; + /* L-SIG TXOP Protection used only if peer support available */ + uint8_t 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 + */ + uint8_t htAMpduDensity:3; + /* Set to 0 for 3839 octets */ + /* Set to 1 for 7935 octets */ + uint8_t htMaxAmsduLength; + /* MIMO Power Save */ + tSirMacHTMIMOPowerSaveState htMIMOPSState; + /* */ + /* Maximum Rx A-MPDU factor */ + uint8_t htMaxRxAMpduFactor:3; + /* + * Recommended Tx Width Set + * 0 - use 20 MHz channel (control channel) + * 1 - use 40 Mhz channel + */ + uint8_t htSupportedChannelWidthSet:1; + uint8_t htSecondaryChannelOffset:2; + uint8_t rsvd1:2; + /* DPH HASH ENTRY FIELDS NEEDED IN HAL ONLY */ + uint8_t dpuSig:4; /* DPU signiture */ + uint8_t staSig:4; /* STA signature */ + uint8_t staType; + uint16_t bssId; /* BSSID */ + uint16_t assocId; /* Association ID */ + /* This is the real sta index generated by HAL */ + uint16_t staIndex; + uint8_t 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 */ + uint8_t ucUcastSig; + /*Broadcast DPU signature */ + uint8_t ucBcastSig; + + uint8_t vhtSupportedChannelWidthSet; + uint8_t vhtSupportedRxNss; + uint8_t vhtBeamFormerCapable; + uint8_t vht_su_bfee_capable; +#ifdef WLAN_FEATURE_11W + uint8_t pmfSaQueryState; + uint8_t pmfSaQueryRetryCount; + uint16_t pmfSaQueryCurrentTransId; + uint16_t pmfSaQueryStartTransId; + TX_TIMER pmfSaQueryTimer; + v_TIME_t last_unprot_deauth_disassoc; + uint8_t proct_deauh_disassoc_cnt; + v_TIME_t last_assoc_received_time; +#endif + uint8_t htLdpcCapable; + uint8_t vhtLdpcCapable; +#ifdef FEATURE_WLAN_TDLS + uint16_t ht_caps; + uint32_t vht_caps; +#endif + uint8_t timingMeasCap; + /* key installed for this STA or not in the firmware */ + uint8_t is_key_installed; + uint8_t is_disassoc_deauth_in_progress; + /* + * 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. + */ + struct sDphHashNode *next; +} tDphHashNode, *tpDphHashNode; + +#include "dph_hash_table.h" + +/* ------------------------------------------------------------------- */ +typedef struct sAniSirDph { + /* The hash table object */ + dphHashTableClass dphHashTable; +} tAniSirDph, *tpAniSirDph; + +#endif diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h new file mode 100644 index 000000000000..afbfd5e339e6 --- /dev/null +++ b/core/mac/src/include/parser_api.h @@ -0,0 +1,965 @@ +/* + * 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 parser_api.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 "sir_mac_prop_exts.h" +#include "dot11f.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.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 */ + +typedef struct sSirCountryInformation { + uint8_t countryString[COUNTRY_STRING_LENGTH]; + uint8_t numIntervals; /* number of channel intervals */ + struct channelPowerLim { + uint8_t channelNumber; + uint8_t numChannel; + uint8_t maxTransmitPower; + } channelTransmitPower[COUNTRY_INFO_MAX_CHANNEL]; +} tSirCountryInformation, *tpSirCountryInformation; + +/* Structure common to Beacons & Probe Responses */ +typedef struct sSirProbeRespBeacon { + tSirMacTimeStamp timeStamp; + uint16_t 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; + tSirMacAddr bssid; + tDot11fIEQuiet quietIE; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; + tDot11fIEP2PProbeRes P2PProbeRes; +#ifdef WLAN_FEATURE_VOWIFI_11R + uint8_t mdie[SIR_MDIE_SIZE]; +#endif +#ifdef FEATURE_WLAN_ESE + tDot11fIEESETxmitPower eseTxPwr; + tDot11fIEQBSSLoad QBSSLoad; +#endif + uint8_t ssidPresent; + uint8_t suppRatesPresent; + uint8_t extendedRatesPresent; + uint8_t cfPresent; + uint8_t dsParamsPresent; + uint8_t timPresent; + + uint8_t edcaPresent; + uint8_t qosCapabilityPresent; + uint8_t wmeEdcaPresent; + uint8_t wmeInfoPresent; + uint8_t wsmCapablePresent; + + uint8_t countryInfoPresent; + uint8_t wpaPresent; + uint8_t rsnPresent; + uint8_t erpPresent; + uint8_t channelSwitchPresent; + uint8_t sec_chan_offset_present; + uint8_t ext_chan_switch_present; + uint8_t quietIEPresent; + uint8_t tpcReportPresent; + uint8_t powerConstraintPresent; + +#ifdef WLAN_FEATURE_VOWIFI_11R + uint8_t mdiePresent; +#endif + +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; + tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEOperatingMode OperatingMode; + uint8_t WiderBWChanSwitchAnnPresent; + tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; +#endif + uint8_t Vendor1IEPresent; + tDot11fIEvendor2_ie vendor2_ie; + uint8_t 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; + uint8_t ssidPresent; + uint8_t suppRatesPresent; + uint8_t extendedRatesPresent; + uint8_t wscIePresent; + uint8_t 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; + uint16_t 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: */ + uint8_t reassocRequest; + uint8_t ssidPresent; + uint8_t suppRatesPresent; + uint8_t extendedRatesPresent; + + uint8_t wmeInfoPresent; + uint8_t qosCapabilityPresent; + uint8_t addtsPresent; + uint8_t wsmCapablePresent; + + uint8_t wapiPresent; + uint8_t wpaPresent; + uint8_t rsnPresent; + uint8_t addIEPresent; + + uint8_t powerCapabilityPresent; + uint8_t supportedChannelsPresent; + /* keeping copy of association request received, this is + required for indicating the frame to upper layers */ + uint32_t assocReqFrameLength; + uint8_t *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; + uint16_t aid; + uint16_t statusCode; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tSirPropIEStruct propIEinfo; + tSirMacEdcaParamSetIE edca; + tSirAddtsRspInfo addtsRsp; + tDot11fIEHTCaps HTCaps; + tDot11fIEHTInfo HTInfo; +#if defined WLAN_FEATURE_VOWIFI_11R + tDot11fIEFTInfo FTInfo; + uint8_t mdie[SIR_MDIE_SIZE]; + uint8_t num_RICData; + tDot11fIERICDataDesc RICData[2]; +#endif + +#ifdef FEATURE_WLAN_ESE + uint8_t num_tspecs; + tDot11fIEWMMTSPEC TSPECInfo[SIR_ESE_MAX_TSPEC_IES]; + tSirMacESETSMIE tsmIE; +#endif + + uint8_t suppRatesPresent; + uint8_t extendedRatesPresent; + + uint8_t edcaPresent; + uint8_t wmeEdcaPresent; + uint8_t addtsPresent; + uint8_t wsmCapablePresent; +#if defined WLAN_FEATURE_VOWIFI_11R + uint8_t ftinfoPresent; + uint8_t mdiePresent; + uint8_t ricPresent; +#endif +#ifdef FEATURE_WLAN_ESE + uint8_t tspecPresent; + uint8_t tsmPresent; +#endif +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + tDot11fIEVHTOperation VHTOperation; +#endif + tDot11fIEExtCap ExtCap; + tSirQosMapSet QosMapSet; +#ifdef WLAN_FEATURE_11W + tDot11fIETimeoutInterval TimeoutInterval; +#endif + tDot11fIEvendor2_ie vendor2_ie; +} 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; + + uint8_t ssidPresent; + uint8_t suppRatesPresent; + uint8_t fhParamPresent; + uint8_t dsParamsPresent; + uint8_t cfPresent; + uint8_t ibssParamPresent; + uint8_t timPresent; + uint8_t rrmPresent; +} tSirEseBcnReportMandatoryIe, *tpSirEseBcnReportMandatoryIe; +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +/** + * struct s_ext_cap - holds bitfields of extended capability IE + * + * s_ext_cap holds bitfields of extended capability IE. In dot11f files + * extended capability IE information is stored as an array of bytes. + * This structure is used to encode/decode the byte array present in + * dot11f IE structure. + */ + +struct s_ext_cap { + uint8_t bss_coexist_mgmt_support:1; + uint8_t reserved1:1; + uint8_t ext_chan_switch:1; + uint8_t reserved2:1; + uint8_t psmp_cap:1; + uint8_t reserved3:1; + uint8_t spsmp_cap:1; + uint8_t event:1; + uint8_t diagnostics:1; + uint8_t multi_diagnostics:1; + uint8_t loc_tracking:1; + uint8_t fms:1; + uint8_t proxy_arp_service:1; + uint8_t co_loc_intf_reporting:1; + uint8_t civic_loc:1; + uint8_t geospatial_loc:1; + uint8_t tfs:1; + uint8_t wnm_sleep_mode:1; + uint8_t tim_broadcast:1; + uint8_t bss_transition:1; + uint8_t qos_traffic_cap:1; + uint8_t ac_sta_cnt:1; + uint8_t multi_bssid:1; + uint8_t timing_meas:1; + uint8_t chan_usage:1; + uint8_t ssid_list:1; + uint8_t dms:1; + uint8_t utctsf_offset:1; + uint8_t tdls_peer_uapsd_buffer_sta:1; + uint8_t tdls_peer_psm_supp:1; + uint8_t tdls_channel_switching:1; + uint8_t interworking_service:1; + uint8_t qos_map:1; + uint8_t ebr:1; + uint8_t sspn_interface:1; + uint8_t reserved4:1; + uint8_t msg_cf_cap:1; + uint8_t tdls_support:1; + uint8_t tdls_prohibited:1; + uint8_t tdls_chan_swit_prohibited:1; + uint8_t reject_unadmitted_traffic:1; + uint8_t service_interval_granularity:3; + uint8_t identifier_loc:1; + uint8_t uapsd_coexistence:1; + uint8_t wnm_notification:1; + uint8_t qa_bcapbility:1; + uint8_t utf8_ssid:1; + uint8_t qmf_activated:1; + uint8_t qm_frecon_act:1; + uint8_t robust_av_streaming:1; + uint8_t advanced_gcr:1; + uint8_t mesh_gcr:1; + uint8_t scs:1; + uint8_t q_load_report:1; + uint8_t alternate_edca:1; + uint8_t unprot_txo_pneg:1; + uint8_t prot_txo_pneg:1; + uint8_t reserved6:1; + uint8_t prot_q_load_report:1; + uint8_t tdls_wider_bw:1; + uint8_t oper_mode_notification:1; + uint8_t max_num_of_msdu_bit1:1; + uint8_t max_num_of_msdu_bit2:1; + uint8_t chan_sch_mgmt:1; + uint8_t geo_db_inband_en_signal:1; + uint8_t nw_chan_control:1; + uint8_t white_space_map:1; + uint8_t chan_avail_query:1; + uint8_t fine_time_meas_responder:1; + uint8_t fine_time_meas_initiator:1; +}; + +uint8_t sirIsPropCapabilityEnabled(struct sAniSirGlobal *pMac, uint32_t bitnum); + +void dot11f_log(tpAniSirGlobal pMac, int nSev, const char *lpszFormat, ...); + +#define CFG_GET_INT(nStatus, pMac, nItem, cfg) do { \ + (nStatus) = wlan_cfg_get_int((pMac), (nItem), &(cfg)); \ + if (eSIR_SUCCESS != (nStatus)) { \ + dot11f_log((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_cfg_get_int((pMac), (nItem), &(cfg)); \ + if (eSIR_SUCCESS != (nStatus)) { \ + dot11f_log((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_cfg_get_str((pMac), (nItem), (cfg), &(nCfg)); \ + if (eSIR_SUCCESS != (nStatus)) { \ + dot11f_log((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_cfg_get_str((pMac), (nItem), (cfg), &(nCfg)); \ + if (eSIR_SUCCESS != (nStatus)) { \ + dot11f_log((pMac), LOGP, FL("Failed to retrieve nItem from CFG (%d)."), (nStatus)); \ + return; \ + } \ +} while (0) + +void swap_bit_field16(uint16_t in, uint16_t *out); + +/* Currently implemented as "shims" between callers & the new framesc- */ +/* generated code: */ + +tSirRetStatus +sir_convert_probe_req_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tpSirProbeReq probe); + +tSirRetStatus +sir_convert_probe_frame2_struct(struct sAniSirGlobal *pMac, uint8_t *frame, + uint32_t len, tpSirProbeRespBeacon probe); + +tSirRetStatus +sir_convert_assoc_req_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tpSirAssocReq assoc); + +tSirRetStatus +sir_convert_assoc_resp_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tpSirAssocRsp assoc); + +tSirRetStatus +sir_convert_reassoc_req_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tpSirAssocReq assoc); + +tSirRetStatus +sir_parse_beacon_ie(struct sAniSirGlobal *pMac, + tpSirProbeRespBeacon pBeaconStruct, + uint8_t *pPayload, uint32_t payloadLength); + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +tSirRetStatus +sir_beacon_ie_ese_bcn_report(tpAniSirGlobal pMac, + uint8_t *pPayload, const uint32_t payloadLength, + uint8_t **outIeBuf, uint32_t *pOutIeLen); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +tSirRetStatus +sir_convert_beacon_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *pBeaconFrame, + tpSirProbeRespBeacon pBeaconStruct); + +tSirRetStatus +sir_convert_auth_frame2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tpSirMacAuthFrameBody auth); + +tSirRetStatus +sir_convert_addts_req2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tSirAddtsReqInfo *addTs); + +tSirRetStatus +sir_convert_addts_rsp2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tSirAddtsRspInfo *addts); + +tSirRetStatus +sir_convert_delts_req2_struct(struct sAniSirGlobal *pMac, + uint8_t *frame, uint32_t len, + tSirDeltsReqInfo *delTs); +tSirRetStatus +sir_convert_qos_map_configure_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, uint32_t nFrame, + tSirQosMapSet *pQosMapSet); + +#ifdef ANI_SUPPORT_11H +tSirRetStatus +sir_convert_tpc_req_frame2_struct(struct sAniSirGlobal *, uint8_t *, + tpSirMacTpcReqActionFrame, uint32_t); + +tSirRetStatus +sir_convert_meas_req_frame2_struct(struct sAniSirGlobal *, uint8_t *, + tpSirMacMeasReqActionFrame, uint32_t); +#endif + +/** + * \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 +populate_dot11f_capabilities(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 +populate_dot11f_capabilities2(tpAniSirGlobal pMac, + tDot11fFfCapabilities *pDot11f, + struct sDphHashNode *pSta, + tpPESession psessionEntry); + +/* / Populate a tDot11fIEChanSwitchAnn */ +void +populate_dot11f_chan_switch_ann(tpAniSirGlobal pMac, + tDot11fIEChanSwitchAnn *pDot11f, + tpPESession psessionEntry); + +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 +populate_dot11f_chan_switch_wrapper(tpAniSirGlobal pMac, + tDot11fIEChannelSwitchWrapper *pDot11f, + tpPESession psessionEntry); + +/* / Populate a tDot11fIECountry */ +tSirRetStatus +populate_dot11f_country(tpAniSirGlobal pMac, + tDot11fIECountry *pDot11f, tpPESession psessionEntry); + +/* Populated a populate_dot11f_ds_params */ +tSirRetStatus +populate_dot11f_ds_params(tpAniSirGlobal pMac, + tDot11fIEDSParams *pDot11f, uint8_t channel); + +/* / Populated a tDot11fIEEDCAParamSet */ +void +populate_dot11f_edca_param_set(tpAniSirGlobal pMac, + tDot11fIEEDCAParamSet *pDot11f, + tpPESession psessionEntry); + +tSirRetStatus +populate_dot11f_erp_info(tpAniSirGlobal pMac, + tDot11fIEERPInfo *pDot11f, tpPESession psessionEntry); + +tSirRetStatus +populate_dot11f_ext_supp_rates(tpAniSirGlobal pMac, + uint8_t nChannelNum, tDot11fIEExtSuppRates *pDot11f, + tpPESession psessionEntry); + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus +populate_dot11f_beacon_report(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 +populate_dot11f_ext_supp_rates1(tpAniSirGlobal pMac, + uint8_t nChannelNum, + tDot11fIEExtSuppRates *pDot11f); + +tSirRetStatus +populate_dot11f_ht_caps(tpAniSirGlobal pMac, + tpPESession psessionEntry, tDot11fIEHTCaps *pDot11f); + +tSirRetStatus +populate_dot11f_ht_info(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pDot11f, tpPESession psessionEntry); + +void populate_dot11f_ibss_params(tpAniSirGlobal pMac, + tDot11fIEIBSSParams *pDot11f, + tpPESession psessionEntry); + +#ifdef ANI_SUPPORT_11H +tSirRetStatus +populate_dot11f_measurement_report0(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f); + +/* / Populate a tDot11fIEMeasurementReport when the report type is CCA */ +tSirRetStatus +populate_dot11f_measurement_report1(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f); + +/* / Populate a tDot11fIEMeasurementReport when the report type is RPI Hist */ +tSirRetStatus +populate_dot11f_measurement_report2(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f); +#endif /* ANI_SUPPORT_11H */ + +/* / Populate a tDot11fIEPowerCaps */ +void +populate_dot11f_power_caps(tpAniSirGlobal pMac, + tDot11fIEPowerCaps *pCaps, + uint8_t nAssocType, tpPESession psessionEntry); + +/* / Populate a tDot11fIEPowerConstraints */ +tSirRetStatus +populate_dot11f_power_constraints(tpAniSirGlobal pMac, + tDot11fIEPowerConstraints *pDot11f); + +void +populate_dot11f_qos_caps_ap(tpAniSirGlobal pMac, + tDot11fIEQOSCapsAp *pDot11f, + tpPESession psessionEntry); + +void +populate_dot11f_qos_caps_station(tpAniSirGlobal pMac, + tDot11fIEQOSCapsStation *pDot11f); + +tSirRetStatus +populate_dot11f_rsn(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIERSN *pDot11f); + +tSirRetStatus +populate_dot11f_rsn_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIERSNOpaque *pDot11f); + +#if defined(FEATURE_WLAN_WAPI) + +tSirRetStatus +populate_dot11f_wapi(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIEWAPI *pDot11f); + +tSirRetStatus populate_dot11f_wapi_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPIOpaque *pDot11f); + +#endif /* defined(FEATURE_WLAN_WAPI) */ + +/* / Populate a tDot11fIESSID given a tSirMacSSid */ +void +populate_dot11f_ssid(tpAniSirGlobal pMac, + tSirMacSSid *pInternal, tDot11fIESSID *pDot11f); + +/* / Populate a tDot11fIESSID from CFG */ +tSirRetStatus populate_dot11f_ssid2(tpAniSirGlobal pMac, + tDot11fIESSID *pDot11f); + +/** + * \brief Populate a tDot11fIESchedule + * + * \sa populate_dot11f_wmm_schedule + * + * + * \param pSchedule Address of a tSirMacScheduleIE struct + * + * \param pDot11f Address of a tDot11fIESchedule to be filled in + * + * + */ + +void +populate_dot11f_schedule(tSirMacScheduleIE *pSchedule, + tDot11fIESchedule *pDot11f); + +void +populate_dot11f_supp_channels(tpAniSirGlobal pMac, + tDot11fIESuppChannels *pDot11f, + uint8_t 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 +populate_dot11f_supp_rates(tpAniSirGlobal pMac, + uint8_t nChannelNum, + tDot11fIESuppRates *pDot11f, tpPESession); + +tSirRetStatus +populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, + tDot11fIESuppRates *p_supp_rates, + tDot11fIEExtSuppRates *p_ext_supp_rates); + +tSirRetStatus populate_dot11f_tpc_report(tpAniSirGlobal pMac, + tDot11fIETPCReport *pDot11f, + tpPESession psessionEntry); + +/* / Populate a tDot11FfTSInfo */ +void populate_dot11f_ts_info(tSirMacTSInfo *pInfo, tDot11fFfTSInfo *pDot11f); + +void populate_dot11f_wmm(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tDot11fIEWMMParams *pParams, + tDot11fIEWMMCaps *pCaps, tpPESession psessionEntry); + +void populate_dot11f_wmm_caps(tDot11fIEWMMCaps *pCaps); + +#if defined(FEATURE_WLAN_ESE) +/* Fill the ESE version IE */ +void populate_dot11f_ese_version(tDot11fIEESEVersion *pESEVersion); +/* Fill the Radio Management Capability */ +void populate_dot11f_ese_rad_mgmt_cap(tDot11fIEESERadMgmtCap *pESERadMgmtCap); +/* Fill the CCKM IE */ +tSirRetStatus populate_dot11f_ese_cckm_opaque(tpAniSirGlobal pMac, + tpSirCCKMie pCCKMie, + tDot11fIEESECckmOpaque *pDot11f); + +void populate_dot11_tsrsie(tpAniSirGlobal pMac, + tSirMacESETSRSIE *pOld, + tDot11fIEESETrafStrmRateSet *pDot11f, + uint8_t rate_length); +void populate_dot11f_re_assoc_tspec(tpAniSirGlobal pMac, + tDot11fReAssocRequest *pReassoc, + tpPESession psessionEntry); +#endif + +void populate_dot11f_wmm_info_ap(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tpPESession psessionEntry); + +void populate_dot11f_wmm_info_station_per_session(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEWMMInfoStation *pInfo); + +void populate_dot11f_wmm_params(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 +populate_dot11f_wmm_schedule(tSirMacScheduleIE *pSchedule, + tDot11fIEWMMSchedule *pDot11f); + +tSirRetStatus +populate_dot11f_wpa(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIEWPA *pDot11f); + +tSirRetStatus +populate_dot11f_wpa_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIEWPAOpaque *pDot11f); + +void populate_dot11f_tspec(tSirMacTspecIE *pOld, tDot11fIETSPEC *pDot11f); + +void populate_dot11f_wmmtspec(tSirMacTspecIE *pOld, tDot11fIEWMMTSPEC *pDot11f); + +tSirRetStatus +populate_dot11f_tclas(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, tDot11fIETCLAS *pDot11f); + +tSirRetStatus +populate_dot11f_wmmtclas(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, tDot11fIEWMMTCLAS *pDot11f); + +tSirRetStatus populate_dot11f_wsc(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus populate_dot11f_wsc_registrar_info(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus de_populate_dot11f_wsc_registrar_info(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f); + +tSirRetStatus populate_dot11f_probe_res_wpsi_es(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f, + tpPESession psessionEntry); +tSirRetStatus populate_dot11f_assoc_res_wpsi_es(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f, + tpPESession psessionEntry); +tSirRetStatus populate_dot11f_beacon_wpsi_es(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f, + tpPESession psessionEntry); + +tSirRetStatus populate_dot11f_wsc_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + +tSirRetStatus +populate_dot11f_wsc_registrar_info_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + +tSirRetStatus +de_populate_dot11f_wsc_registrar_info_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f); + +tSirRetStatus populate_dot11f_assoc_res_wsc_ie(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq); + +tSirRetStatus populate_dot11_assoc_res_p2p_ie(tpAniSirGlobal pMac, + tDot11fIEP2PAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq); + +tSirRetStatus populate_dot11f_wscInAssocRes(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f); + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus populate_dot11f_wfatpc(tpAniSirGlobal pMac, + tDot11fIEWFATPC *pDot11f, uint8_t txPower, + uint8_t linkMargin); + +tSirRetStatus populate_dot11f_rrm_ie(tpAniSirGlobal pMac, + tDot11fIERRMEnabledCap *pDot11f, + tpPESession psessionEntry); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +void populate_mdie(tpAniSirGlobal pMac, + tDot11fIEMobilityDomain * pDot11f, uint8_t mdie[]); +void populate_ft_info(tpAniSirGlobal pMac, tDot11fIEFTInfo *pDot11f); +#endif + +void populate_dot11f_assoc_rsp_rates(tpAniSirGlobal pMac, + tDot11fIESuppRates *pSupp, + tDot11fIEExtSuppRates *pExt, + uint16_t *_11bRates, uint16_t *_11aRates); + +int find_ie_location(tpAniSirGlobal pMac, tpSirRSNie pRsnIe, uint8_t EID); + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +populate_dot11f_vht_caps(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIEVHTCaps *pDot11f); + +tSirRetStatus +populate_dot11f_vht_operation(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEVHTOperation *pDot11f); + +tSirRetStatus +populate_dot11f_vht_ext_bss_load(tpAniSirGlobal pMac, + tDot11fIEVHTExtBssLoad *pDot11f); + +tSirRetStatus +populate_dot11f_ext_cap(tpAniSirGlobal pMac, bool isVHTEnabled, + tDot11fIEExtCap *pDot11f, tpPESession psessionEntry); + +tSirRetStatus +populate_dot11f_operating_mode(tpAniSirGlobal pMac, + tDot11fIEOperatingMode *pDot11f, + tpPESession psessionEntry); + +void +populate_dot11f_wider_bw_chan_switch_ann(tpAniSirGlobal pMac, + tDot11fIEWiderBWChanSwitchAnn *pDot11f, + tpPESession psessionEntry); +#endif + +void populate_dot11f_timeout_interval(tpAniSirGlobal pMac, + tDot11fIETimeoutInterval *pDot11f, + uint8_t type, uint32_t value); + +#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 */ + +tSirRetStatus populate_dot11f_timing_advert_frame(tpAniSirGlobal pMac, + tDot11fTimingAdvertisementFrame *frame); + +#endif /* __PARSE_H__ */ diff --git a/core/mac/src/include/sir_common.h b/core/mac/src/include/sir_common.h new file mode 100644 index 000000000000..f6997725d52e --- /dev/null +++ b/core/mac/src/include/sir_common.h @@ -0,0 +1,55 @@ +/* + * 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 sir_common.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 "sir_api.h" +#include "sir_params.h" +#include "sys_wrapper.h" + +/* ********************************************* * +* * +* SIRIUS SYSTEM EXTERNAL GLOBALS * +* * +* ********************************************* */ + +/* All the following are resource definitions */ + +#endif /* __SIRCOMMON_H */ diff --git a/core/mac/src/include/sir_debug.h b/core/mac/src/include/sir_debug.h new file mode 100644 index 000000000000..674855d0567b --- /dev/null +++ b/core/mac/src/include/sir_debug.h @@ -0,0 +1,109 @@ +/* + * 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: Sandesh Goel + * Date: 02/25/02 + */ + +#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/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h new file mode 100644 index 000000000000..78513a3ac805 --- /dev/null +++ b/core/mac/src/include/sir_params.h @@ -0,0 +1,758 @@ +/* + * 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 sir_params.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 "sir_types.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 + +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, + WLAN_ROAM_SCAN_OFFLOAD = 23, + 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 { + uint16_t type; + /* + * This field can be used as sequence number/dialog token for matching + * requests and responses. + */ + uint16_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; + uint32_t 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 { + uint16_t 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. + */ + uint16_t 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. + */ + uint32_t data[1]; +} tSirMbMsg, *tpSirMbMsg; + +/* / Mailbox Message Structure for P2P */ +typedef struct sSirMbMsgP2p { + uint16_t 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. + */ + uint16_t msgLen; + + uint8_t sessionId; + uint8_t noack; + uint16_t wait; + uint16_t channel_freq; + uint32_t scan_id; + + /** + * 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. + */ + uint32_t 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 wni_api.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 + +/* + * New Taurus related messages + */ +#define SIR_HAL_ADD_STA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 1) +#define SIR_HAL_ADD_STA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 2) +#define SIR_HAL_DELETE_STA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 3) +#define SIR_HAL_DELETE_STA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 4) +#define SIR_HAL_ADD_BSS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 5) +#define SIR_HAL_ADD_BSS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 6) +#define SIR_HAL_DELETE_BSS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 7) +#define SIR_HAL_DELETE_BSS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 8) +#define SIR_HAL_INIT_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 9) +#define SIR_HAL_INIT_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 10) +#define SIR_HAL_START_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 11) +#define SIR_HAL_START_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 12) +#define SIR_HAL_END_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 13) +#define SIR_HAL_END_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 14) +#define SIR_HAL_FINISH_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 15) +#define SIR_HAL_FINISH_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 16) +#define SIR_HAL_SEND_BEACON_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 17) + +#define SIR_HAL_SET_BSSKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 18) +#define SIR_HAL_SET_BSSKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 19) +#define SIR_HAL_SET_STAKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 20) +#define SIR_HAL_SET_STAKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 21) +#define SIR_HAL_UPDATE_EDCA_PROFILE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 22) + +#define SIR_HAL_UPDATE_BEACON_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 23) +#define SIR_HAL_UPDATE_CF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 24) +#define SIR_HAL_CHNL_SWITCH_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 25) +#define SIR_HAL_ADD_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 26) +#define SIR_HAL_DEL_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 27) + +#define SIR_HAL_MISSED_BEACON_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 34) + +#define SIR_HAL_SWITCH_CHANNEL_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 35) +#define SIR_HAL_PWR_SAVE_CFG (SIR_HAL_ITC_MSG_TYPES_BEGIN + 36) + +#define SIR_HAL_REGISTER_PE_CALLBACK (SIR_HAL_ITC_MSG_TYPES_BEGIN + 37) + +#define SIR_HAL_IBSS_STA_ADD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 43) +#define SIR_HAL_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 44) +#define SIR_HAL_SET_LINK_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 45) + +/* + * (SIR_HAL_ITC_MSG_TYPES_BEGIN + 46) to + * (SIR_HAL_ITC_MSG_TYPES_BEGIN + 57) are unused + */ + +#define SIR_HAL_SET_STA_BCASTKEY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 58) +#define SIR_HAL_SET_STA_BCASTKEY_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 59) +#define SIR_HAL_ADD_TS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 60) +#define SIR_HAL_DPU_MIC_ERROR (SIR_HAL_ITC_MSG_TYPES_BEGIN + 61) +#define SIR_HAL_TIMER_CHIP_MONITOR_TIMEOUT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 63) +#define SIR_HAL_TIMER_TRAFFIC_ACTIVITY_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 64) +#define SIR_HAL_TIMER_ADC_RSSI_STATS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 65) +/* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 66) is unused */ +#define SIR_HAL_SET_MIMOPS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 67) +#define SIR_HAL_SET_MIMOPS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 68) +#define SIR_HAL_SYS_READY_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 69) +#define SIR_HAL_SET_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 70) +#define SIR_HAL_SET_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 71) +#define SIR_HAL_GET_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 72) +#define SIR_HAL_GET_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 73) +#define SIR_HAL_GET_NOISE_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 74) + +/* Messages to support transmit_halt and transmit_resume */ +#define SIR_HAL_TRANSMISSION_CONTROL_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 75) + +#define SIR_HAL_LOW_RSSI_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 80) +#define SIR_HAL_BEACON_FILTER_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 81) +/* / PE <-> HAL WOWL messages */ +#define SIR_HAL_WOW_ADD_PTRN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 82) +#define SIR_HAL_WOW_DEL_PTRN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 83) +#define SIR_HAL_WOWL_ENTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 84) +#define SIR_HAL_WOWL_ENTER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 85) +#define SIR_HAL_WOWL_EXIT_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 86) +#define SIR_HAL_WOWL_EXIT_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 87) +/* / PE <-> HAL statistics messages */ +#define SIR_HAL_GET_STATISTICS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 88) +#define SIR_HAL_GET_STATISTICS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 89) +#define SIR_HAL_SET_KEY_DONE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 90) + +/* / PE <-> HAL BTC messages */ +#define SIR_HAL_BTC_SET_CFG (SIR_HAL_ITC_MSG_TYPES_BEGIN + 91) +/* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 92) is unused */ +#define SIR_HAL_HANDLE_FW_MBOX_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 93) +#define SIR_HAL_SEND_PROBE_RSP_TMPL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 94) + +/* PE <-> HAL addr2 mismatch message */ +#define SIR_LIM_ADDR2_MISS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 95) +#ifdef FEATURE_OEM_DATA_SUPPORT +/* PE <-> HAL OEM_DATA RELATED MESSAGES */ +#define SIR_HAL_START_OEM_DATA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 96) +#define SIR_HAL_START_OEM_DATA_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 97) +#endif + +#define SIR_HAL_SET_MAX_TX_POWER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 98) +#define SIR_HAL_SET_MAX_TX_POWER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 99) + +/* / PE <-> HAL Host Offload message */ +#define SIR_HAL_SET_HOST_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 100) + +#define SIR_HAL_ADD_STA_SELF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 101) +#define SIR_HAL_ADD_STA_SELF_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 102) +#define SIR_HAL_DEL_STA_SELF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 103) +#define SIR_HAL_DEL_STA_SELF_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 104) + +#define SIR_HAL_CFG_RXP_FILTER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 106) + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define SIR_HAL_AGGR_ADD_TS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 107) +#define SIR_HAL_AGGR_ADD_TS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 108) +#define SIR_HAL_AGGR_QOS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 109) +#define SIR_HAL_AGGR_QOS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 110) +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* P2P <-> HAL P2P msg */ +#define SIR_HAL_SET_P2P_GO_NOA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 111) +#define SIR_HAL_P2P_NOA_ATTR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 112) +#define SIR_HAL_P2P_NOA_START_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 113) + +#define SIR_HAL_SET_LINK_STATE_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 114) + +#define SIR_HAL_WLAN_SUSPEND_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 115) +#define SIR_HAL_WLAN_RESUME_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 116) + +/* / PE <-> HAL Keep Alive message */ +#define SIR_HAL_SET_KEEP_ALIVE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 117) + +#ifdef WLAN_NS_OFFLOAD +#define SIR_HAL_SET_NS_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 118) +#endif /* WLAN_NS_OFFLOAD */ + +#ifdef FEATURE_WLAN_SCAN_PNO +#define SIR_HAL_SET_PNO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 119) +/* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 120) is unused */ +#endif /* FEATURE_WLAN_SCAN_PNO */ + +/* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 122) is unused */ + +#ifdef WLAN_FEATURE_PACKET_FILTERING +#define SIR_HAL_8023_MULTICAST_LIST_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 123) +#define SIR_HAL_RECEIVE_FILTER_SET_FILTER_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 124) +#define SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 125) +#define SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 126) +#define SIR_HAL_RECEIVE_FILTER_CLEAR_FILTER_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 127) +#endif /* WLAN_FEATURE_PACKET_FILTERING */ + +/* (SIR_HAL_ITC_MSG_TYPES_BEGIN + 128) is unused */ + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define SIR_HAL_GTK_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 129) +#define SIR_HAL_GTK_OFFLOAD_GETINFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 130) +#define SIR_HAL_GTK_OFFLOAD_GETINFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 131) +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + +#ifdef FEATURE_WLAN_ESE +#define SIR_HAL_TSM_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 132) +#define SIR_HAL_TSM_STATS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 133) +#endif + +#define SIR_HAL_SET_TM_LEVEL_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 134) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_OP_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 135) +#endif + +#ifdef FEATURE_WLAN_TDLS +/* / PE <-> HAL TDLS messages */ +#define SIR_HAL_TDLS_LINK_ESTABLISH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 136) +#define SIR_HAL_TDLS_LINK_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 137) +#endif +#define SIR_HAL_ROAM_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 138) + +#define SIR_HAL_TRAFFIC_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 141) + +#ifdef WLAN_FEATURE_11W +#define SIR_HAL_EXCLUDE_UNENCRYPTED_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 142) +#endif +#ifdef FEATURE_WLAN_TDLS +/* / PE <-> HAL TDLS messages */ +#define SIR_HAL_TDLS_LINK_ESTABLISH_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 143) +#define SIR_HAL_TDLS_LINK_ESTABLISH_REQ_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 144) +#define SIR_HAL_TDLS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 145) +#endif + +#define SIR_HAL_STOP_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 146) +#define SIR_HAL_RX_SCAN_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 147) +#define SIR_HAL_DHCP_START_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 148) +#define SIR_HAL_DHCP_STOP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 149) +#define SIR_HAL_IBSS_PEER_INACTIVITY_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 150) + +#define SIR_HAL_LPHB_CONF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 151) + +#define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 152) +#define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 153) + +/* Messages between 156 to 157 are not used */ +#define SIR_HAL_SOC_DUAL_MAC_CFG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 154) +#define SIR_HAL_SOC_DUAL_MAC_CFG_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 155) + +#define SIR_HAL_RATE_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 159) + +#define SIR_HAL_FLUSH_LOG_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 160) + +#define SIR_HAL_SOC_SET_PCL_TO_FW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161) + +/* 162 unused */ + +#define SIR_HAL_CLI_SET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 163) +#ifndef REMOVE_PKT_LOG +#define SIR_HAL_PKTLOG_ENABLE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 164) +#endif +#ifdef FEATURE_WLAN_SCAN_PNO +#define SIR_HAL_SME_SCAN_CACHE_UPDATED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 165) +#endif +#define SIR_HAL_START_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 166) +#define SIR_HAL_UPDATE_CHAN_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 167) +#define SIR_CSA_OFFLOAD_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 169) + +#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 170) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_MEMBERSHIP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 172) +#define SIR_HAL_UPDATE_USERPOS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 173) +#endif + +#ifdef FEATURE_WLAN_TDLS +#define SIR_HAL_UPDATE_FW_TDLS_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 174) +#define SIR_HAL_UPDATE_TDLS_PEER_STATE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 175) +#define SIR_HAL_TDLS_SHOULD_DISCOVER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 176) +#define SIR_HAL_TDLS_SHOULD_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 177) +#define SIR_HAL_TDLS_PEER_DISCONNECTED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 178) +#endif + +/* Handling of beacon tx indication from FW */ +#define SIR_HAL_BEACON_TX_SUCCESS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 179) +#define SIR_HAL_DFS_RADAR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 180) + +#define SIR_HAL_INIT_THERMAL_INFO_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 185) +#define SIR_HAL_SET_THERMAL_LEVEL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 186) + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define SIR_HAL_SET_PLM_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 187) +#endif + +#define SIR_HAL_SET_TX_POWER_LIMIT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 188) +#define SIR_HAL_SET_SAP_INTRABSS_DIS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 189) + +#define SIR_HAL_MODEM_POWER_STATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190) + +#define SIR_HAL_DISASSOC_TX_COMP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 191) +#define SIR_HAL_DEAUTH_TX_COMP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 192) + +#ifdef WLAN_FEATURE_11AC +#define SIR_HAL_UPDATE_RX_NSS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 193) +#endif + +#ifdef WLAN_FEATURE_STATS_EXT +#define SIR_HAL_STATS_EXT_REQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 194) +#define SIR_HAL_STATS_EXT_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 195) +#endif /* WLAN_FEATURE_STATS_EXT */ + +#define SIR_HAL_HIDE_SSID_VDEV_RESTART (SIR_HAL_ITC_MSG_TYPES_BEGIN + 196) + +#define SIR_HAL_GET_LINK_SPEED (SIR_HAL_ITC_MSG_TYPES_BEGIN + 197) + +#ifdef FEATURE_WLAN_EXTSCAN +#define SIR_HAL_EXTSCAN_GET_CAPABILITIES_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 198) +#define SIR_HAL_EXTSCAN_START_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 199) +#define SIR_HAL_EXTSCAN_STOP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 200) +#define SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 201) +#define SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 202) +#define SIR_HAL_EXTSCAN_SET_SIGNF_CHANGE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 203) +#define SIR_HAL_EXTSCAN_RESET_SIGNF_CHANGE_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 204) +#define SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_REQ \ + (SIR_HAL_ITC_MSG_TYPES_BEGIN + 205) +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef FEATURE_WLAN_CH_AVOID +#define SIR_HAL_CH_AVOID_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206) +#endif + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +#define SIR_HAL_LL_STATS_CLEAR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207) +#define SIR_HAL_LL_STATS_SET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208) +#define SIR_HAL_LL_STATS_GET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209) +#define SIR_HAL_LL_STATS_RESULTS_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210) +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_CNF (SIR_HAL_ITC_MSG_TYPES_BEGIN + 211) +#endif +#ifdef WLAN_FEATURE_NAN +#define SIR_HAL_NAN_REQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 212) +#endif /* WLAN_FEATURE_NAN */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define SIR_HAL_SET_AUTO_SHUTDOWN_TIMER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 213) +#endif + +#define SIR_HAL_SET_BASE_MACADDR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 214) + +#define SIR_HAL_UNIT_TEST_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 215) + +#define SIR_HAL_LINK_STATUS_GET_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 216) + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define SIR_HAL_CONFIG_EXT_WOW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 217) +#define SIR_HAL_CONFIG_APP_TYPE1_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 218) +#define SIR_HAL_CONFIG_APP_TYPE2_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 219) +#endif + +#define SIR_HAL_GET_TEMPERATURE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 220) +#define SIR_HAL_SET_SCAN_MAC_OUI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 221) +#ifdef DHCP_SERVER_OFFLOAD +#define SIR_HAL_SET_DHCP_SERVER_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 222) +#endif /* DHCP_SERVER_OFFLOAD */ +#define SIR_HAL_LED_FLASHING_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 223) +#define SIR_HAL_PROCESS_FW_EVENT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 224) + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 225) +#define SIR_HAL_ROAM_OFFLOAD_SYNCH_FAIL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 226) +#define SIR_HAL_ROAM_INVOKE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 227) +#endif + +#ifdef FEATURE_WLAN_TDLS +#define SIR_HAL_TDLS_SET_OFFCHAN_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 228) +#endif + +#define SIR_HAL_SET_MAS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 229) +#define SIR_HAL_SET_MIRACAST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 230) +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define SIR_HAL_UPDATE_Q2Q_IE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 231) +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +#define SIR_HAL_CONFIG_STATS_FACTOR (SIR_HAL_ITC_MSG_TYPES_BEGIN + 232) +#define SIR_HAL_CONFIG_GUARD_TIME (SIR_HAL_ITC_MSG_TYPES_BEGIN + 233) +#define SIR_HAL_IPA_OFFLOAD_ENABLE_DISABLE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 234) + +#define SIR_HAL_ENTER_PS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 235) +#define SIR_HAL_EXIT_PS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 236) +#define SIR_HAL_ENABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237) +#define SIR_HAL_DISABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238) + +#define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313) +#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_SOC_SET_HW_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 329) +#define SIR_HAL_SOC_SET_HW_MODE_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 330) +#define SIR_HAL_SOC_HW_MODE_TRANS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 331) + +#define SIR_HAL_SET_RSSI_MONITOR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 333) +#define SIR_HAL_SET_IE_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 334) + +#define SIR_HAL_LRO_CONFIG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 335) + +#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) +/* 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_UPDATE_BEACON (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0x13) + +/* LIM Timeout messages */ +#define SIR_LIM_TIMEOUT_MSG_START ((SIR_LIM_MODULE_ID << 8) + 0xD0) +#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_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) +/* currently unused (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_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_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) + +/* PTT message types */ +#define SIR_PTT_MSG_TYPES_BEGIN 0x3000 +#define SIR_PTT_MSG_TYPES_END 0x3300 + +/* ****************************************** * +* * +* EVENT TYPE Defintions * +* * +* ****************************************** */ + +/* MMH Events that are used in other modules to post events to MMH */ +#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/core/mac/src/include/sys_global.h b/core/mac/src/include/sys_global.h new file mode 100644 index 000000000000..2f76ddf5e615 --- /dev/null +++ b/core/mac/src/include/sys_global.h @@ -0,0 +1,52 @@ +/* + * 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 __SYS_GLOBAL_H__ +#define __SYS_GLOBAL_H__ + +typedef struct sAniSirSys { + + uint32_t gSysFrameCount[4][16]; + uint32_t gSysBbtReceived; + uint32_t gSysBbtPostedToLim; + uint32_t gSysBbtPostedToSch; + uint32_t gSysBbtPostedToPmm; + uint32_t gSysBbtPostedToHal; + uint32_t gSysBbtDropped; + uint32_t gSysBbtNonLearnFrameInv; + uint32_t gSysBbtLearnFrameInv; + uint32_t gSysBbtCrcFail; + uint32_t gSysBbtDuplicates; + uint32_t gSysReleaseCount; + uint32_t probeError, probeBadSsid, probeIgnore, probeRespond; + + uint32_t gSysEnableLearnMode; + uint32_t gSysEnableScanMode; + uint32_t gSysEnableLinkMonitorMode; +} tAniSirSys, *tpAniSirSys; + +#endif diff --git a/core/mac/src/include/utils_api.h b/core/mac/src/include/utils_api.h new file mode 100644 index 000000000000..6a344befe9f2 --- /dev/null +++ b/core/mac/src/include/utils_api.h @@ -0,0 +1,669 @@ +/* + * 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 __UTILSAPI_H +#define __UTILSAPI_H + +#include +#include +#include "ani_global.h" +#include "utils_global.h" +#include "sys_wrapper.h" + +/* / 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; + +#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 log_debug(tpAniSirGlobal pMac, uint8_t modId, uint32_t debugLevel, + const char *pStr, va_list marker); + +extern void log_dbg(tpAniSirGlobal pMac, uint8_t modId, uint32_t debugLevel, + const char *pStr, ...); + +extern uint32_t gPktAllocCnt, gPktFreeCnt; + +extern CDF_TRACE_LEVEL get_vos_debug_level(uint32_t debugLevel); + +/* / Log initialization */ +extern tSirRetStatus log_init(tpAniSirGlobal); + +extern void log_deinit(tpAniSirGlobal); + +extern tSirRetStatus cfg_init(tpAniSirGlobal); +extern void cfg_de_init(tpAniSirGlobal); + +void sir_dump_buf(tpAniSirGlobal pMac, uint8_t modId, uint32_t level, + uint8_t *buf, uint32_t size); + +/** + * sir_swap_u16() + * + * FUNCTION: + * This function is called to swap two U8s of an uint16_t value + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val uint16_t value to be uint8_t swapped + * @return Swapped uint16_t value + */ + +static inline uint16_t sir_swap_u16(uint16_t val) +{ + return ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8); +} /*** end sir_swap_u16() ***/ + +/** + * sir_swap_u16if_needed() + * + * FUNCTION: + * This function is called to swap two U8s of an uint16_t value depending + * on endiannes of the target processor/compiler the software is + * running on + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val uint16_t value to be uint8_t swapped + * @return Swapped uint16_t value + */ + +static inline uint16_t sir_swap_u16if_needed(uint16_t val) +{ +#ifndef ANI_LITTLE_BYTE_ENDIAN + return sir_swap_u16(val); +#else + return val; +#endif +} /*** end sir_swap_u16if_needed() ***/ + +/** + * sir_swap_u32() + * + * FUNCTION: + * This function is called to swap four U8s of an uint32_t value + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val uint32_t value to be uint8_t swapped + * @return Swapped uint32_t value + */ + +static inline uint32_t sir_swap_u32(uint32_t val) +{ + return (val << 24) | + (val >> 24) | + ((val & 0x0000FF00) << 8) | ((val & 0x00FF0000) >> 8); +} /*** end sir_swap_u32() ***/ + +/** + * sir_swap_u32if_needed() + * + * FUNCTION: + * This function is called to swap U8s of an uint32_t value depending + * on endiannes of the target processor/compiler the software is + * running on + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param val uint32_t value to be uint8_t swapped + * @return Swapped uint32_t value + */ + +static inline uint32_t sir_swap_u32if_needed(uint32_t val) +{ +#ifndef ANI_LITTLE_BYTE_ENDIAN + return sir_swap_u32(val); +#else + return val; +#endif +} /*** end sir_swap_u32if_needed() ***/ + +/** + * sir_swap_u32_buf + * + * FUNCTION: + * It swaps N dwords into the same buffer + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of uint32_t array + * @return void + * + */ + +static inline void sir_swap_u32_buf(uint32_t *ptr, uint32_t nWords) +{ + uint32_t i; + + for (i = 0; i < nWords; i++) + ptr[i] = sir_swap_u32(ptr[i]); +} + +/** + * sir_swap_u32_buf_if_needed() + * + * FUNCTION: + * This function is called to swap U8s of U32s in the buffer depending + * on endiannes 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 sir_swap_u32_buf_if_needed(uint32_t *pBuf, uint32_t nWords) +{ +#ifdef ANI_LITTLE_BYTE_ENDIAN + sir_swap_u32_buf(pBuf, nWords); +#endif +} /*** end sir_swap_u32if_needed() ***/ + +/** + * sir_swap_bd_if_needed + * + * 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 sir_swap_bd_if_needed(uint32_t *pBd) +{ + sir_swap_u32_buf_if_needed(pBd, 6); + sir_swap_u32_buf_if_needed(pBd + 18, 14); +} + +/** + * sir_store_u16_n + * + * 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 sir_store_u16_n(uint8_t *ptr, uint16_t val) +{ + *ptr++ = (val >> 8) & 0xff; + *ptr = val & 0xff; +} + +/** + * sir_store_u32_n + * + * 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 sir_store_u32_n(uint8_t *ptr, uint32_t val) +{ + *ptr++ = (uint8_t) (val >> 24) & 0xff; + *ptr++ = (uint8_t) (val >> 16) & 0xff; + *ptr++ = (uint8_t) (val >> 8) & 0xff; + *ptr = (uint8_t) (val) & 0xff; +} + +/** + * sir_store_u16 + * + * 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 sir_store_u16(uint8_t *ptr, uint16_t val) +{ + *ptr++ = val & 0xff; + *ptr = (val >> 8) & 0xff; +} + +/** + * sir_store_u32 + * + * 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 sir_store_u32(uint8_t *ptr, uint32_t val) +{ + *ptr++ = (uint8_t) val & 0xff; + *ptr++ = (uint8_t) (val >> 8) & 0xff; + *ptr++ = (uint8_t) (val >> 16) & 0xff; + *ptr = (uint8_t) (val >> 24) & 0xff; +} + +/** + * sir_store_u32BufN + * + * 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 uint32_t data type fields. + * + * NOTE: + * Must be used if all the fields in the buffer must be of uint32_t 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 +sir_store_buf_n(uint8_t *pDst, uint32_t *pSrc, uint32_t length) +{ + while (length) { + sir_store_u32_n(pDst, *pSrc); + pDst += 4; + pSrc++; + length--; + } +} + +/** + * sir_read_u16_n + * + * 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 uint16_t sir_read_u16_n(uint8_t *ptr) +{ + return ((*ptr) << 8) | (*(ptr + 1)); +} + +/** + * sir_swap_u32_buf + * + * FUNCTION: + * It swaps N dwords into the same buffer + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param ptr address of uint32_t array + * @return void + * + */ + +static inline void +sir_swap_n_store(uint32_t *src, uint32_t *dst, uint32_t nWords) +{ + uint32_t i; + + for (i = 0; i < nWords; i++) + dst[i] = sir_swap_u32(src[i]); +} + +/** + * sir_read_u32_n + * + * 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 uint32_t sir_read_u32_n(uint8_t *ptr) +{ + return (*(ptr) << 24) | + (*(ptr + 1) << 16) | (*(ptr + 2) << 8) | (*(ptr + 3)); +} + +/** + * sir_read_u16 + * + * 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 uint16_t sir_read_u16(uint8_t *ptr) +{ + return (*ptr) | (*(ptr + 1) << 8); +} + +/** + * sir_read_u32 + * + * 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 uint32_t sir_read_u32(uint8_t *ptr) +{ + return (*(ptr)) | + (*(ptr + 1) << 8) | (*(ptr + 2) << 16) | (*(ptr + 3) << 24); +} + +/* / Copy a MAC address from 'from' to 'to' */ +static inline void sir_copy_mac_addr(uint8_t to[], uint8_t from[]) +{ +#if defined(_X86_) + uint32_t align = (0x3 & ((uint32_t) to | (uint32_t) from)); + if (align == 0) { + *((uint16_t *) &(to[4])) = *((uint16_t *) &(from[4])); + *((uint32_t *) to) = *((uint32_t *) from); + } else if (align == 2) { + *((uint16_t *) &to[4]) = *((uint16_t *) &from[4]); + *((uint16_t *) &to[2]) = *((uint16_t *) &from[2]); + *((uint16_t *) &to[0]) = *((uint16_t *) &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 uint8_t sir_compare_mac_addr(uint8_t addr1[], uint8_t addr2[]) +{ +#if defined(_X86_) + uint32_t align = (0x3 & ((uint32_t) addr1 | (uint32_t) addr2)); + + if (align == 0) { + return (*((uint16_t *) &(addr1[4])) == + *((uint16_t *) &(addr2[4]))) + && (*((uint32_t *) addr1) == *((uint32_t *) addr2)); + } else if (align == 2) { + return (*((uint16_t *) &addr1[4]) == + *((uint16_t *) &addr2[4])) + && (*((uint16_t *) &addr1[2]) == + *((uint16_t *) &addr2[2])) + && (*((uint16_t *) &addr1[0]) == + *((uint16_t *) &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 uint16_t CW value to 4 bit value to be inserted in IE + */ +static inline uint8_t convert_cw(uint16_t cw) +{ + uint8_t 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, uint8_t *pPayload, + uint16_t payloadLength, int16_t lastType, + uint8_t *pType, uint8_t *pLength); + +/* / Check if the given channel is 11b channel */ +#define SIR_IS_CHANNEL_11B(chId) (chId <= 14) + +/** + * hal_round_s32 + * + * 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 int32_t input + * @return rounded number + */ +static inline int32_t hal_round_s32(int32_t p) +{ + int32_t 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 endianess conversion */ +#ifdef ANI_LITTLE_BYTE_ENDIAN +#define ani_cpu_to_be16(x) sir_swap_u16((x)) +#define ani_cpu_to_le16(x) (x) +#define ani_cpu_to_be32(x) sir_swap_u32((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) sir_swap_u16((x)) +#define ani_cpu_to_be32(x) (x) +#define ani_cpu_to_le32(x) sir_swap_u32((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 convertto_big_endian(void *ptr, uint16_t size); +void create_scan_cts_frame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, + tSirMacAddr selfMac); +void create_scan_data_null_frame(tpAniSirGlobal pMac, + tSirMacMgmtHdr *macMgmtHdr, uint8_t pwrMgmt, tSirMacAddr bssid, + tSirMacAddr selfMacAddr); +void create_init_scan_raw_frame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, + tBssSystemRole role); +void create_finish_scan_raw_frame(tpAniSirGlobal pMac, + tSirMacMgmtHdr *macMgmtHdr, tBssSystemRole role); + +#endif /* __UTILSAPI_H */ diff --git a/core/mac/src/include/utils_global.h b/core/mac/src/include/utils_global.h new file mode 100644 index 000000000000..db2f8547dcac --- /dev/null +++ b/core/mac/src/include/utils_global.h @@ -0,0 +1,56 @@ +/* + * 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 __UTILS_GLOBAL_H__ +#define __UTILS_GLOBAL_H__ + +#include "sir_params.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 { + uint32_t gLogEvtLevel[LOG_ENTRY_NUM]; + uint32_t gLogDbgLevel[LOG_ENTRY_NUM]; + +} tAniSirUtils, *tpAniSirUtils; + +#endif diff --git a/core/mac/src/pe/include/lim_admit_control.h b/core/mac/src/pe/include/lim_admit_control.h new file mode 100644 index 000000000000..90eae86ee5f8 --- /dev/null +++ b/core/mac/src/pe/include/lim_admit_control.h @@ -0,0 +1,106 @@ +/* + * 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: Dinesh Upadhyay + * Date: 10/24/06 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#ifndef __LIM_ADMIT_CONTROL_H__ +#define __LIM_ADMIT_CONTROL_H__ + +#include "sir_common.h" +#include "sir_mac_prot_def.h" + +#include "ani_global.h" + +tSirRetStatus +lim_tspec_find_by_assoc_id(tpAniSirGlobal, uint16_t, tSirMacTspecIE *, + tpLimTspecInfo, tpLimTspecInfo *); + +/* Add TSPEC in lim local table */ +tSirRetStatus lim_tspec_add(tpAniSirGlobal pMac, + uint8_t *pAddr, + uint16_t assocId, + tSirMacTspecIE *pTspec, + uint32_t interval, tpLimTspecInfo *ppInfo); + +/* admit control interface */ +extern tSirRetStatus lim_admit_control_add_ts(tpAniSirGlobal pMac, + uint8_t *pAddr, tSirAddtsReqInfo *addts, + tSirMacQosCapabilityStaIE *qos, + uint16_t assocId, uint8_t alloc, + tSirMacScheduleIE *pSch, + /* index to the lim tspec table. */ + uint8_t *pTspecIdx, + tpPESession psessionEntry); + +static inline tSirRetStatus +lim_admit_control_add_sta(tpAniSirGlobal pMac, uint8_t *staAddr, uint8_t alloc) +{ + return eSIR_SUCCESS; +} + +extern tSirRetStatus +lim_admit_control_delete_sta(tpAniSirGlobal pMac, uint16_t assocId); + +extern tSirRetStatus +lim_admit_control_delete_ts(tpAniSirGlobal pMac, + uint16_t assocId, + tSirMacTSInfo *tsinfo, + uint8_t *tsStatus, uint8_t *tspecIdx); + +extern tSirRetStatus lim_update_admit_policy(tpAniSirGlobal pMac); + +tSirRetStatus lim_admit_control_init(tpAniSirGlobal pMac); +#ifdef FEATURE_WLAN_ESE +tSirRetStatus lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, + tSirMacTspecIE tspecIE, + uint8_t sessionId, uint16_t tsm_interval); +#else +tSirRetStatus lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, + tSirMacTspecIE tspecIE, + uint8_t sessionId); +#endif + +tSirRetStatus lim_send_hal_msg_del_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, + tSirDeltsReqInfo delts, + uint8_t sessionId, uint8_t *bssId); +void lim_process_hal_add_ts_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg); + +#endif diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h new file mode 100644 index 000000000000..99e2fc7376cc --- /dev/null +++ b/core/mac/src/pe/include/lim_api.h @@ -0,0 +1,251 @@ +/* + * 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 lim_api.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 "wni_api.h" +#include "sir_api.h" +#include "ani_global.h" +#include "sir_mac_prot_def.h" +#include "sir_common.h" +#include "sir_debug.h" +#include "sch_global.h" +#include "utils_api.h" +#include "lim_global.h" +#include "wma_if.h" +#include "wma_types.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_AP_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_AP_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_UNKNOWN_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_UNKNOWN_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_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 lim_initialize(tpAniSirGlobal); +tSirRetStatus pe_open(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam); +tSirRetStatus pe_close(tpAniSirGlobal pMac); +void pe_register_tl_handle(tpAniSirGlobal pMac); +tSirRetStatus lim_start(tpAniSirGlobal pMac); +tSirRetStatus pe_start(tpAniSirGlobal pMac); +void pe_stop(tpAniSirGlobal pMac); +tSirRetStatus pe_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg); +tSirRetStatus peProcessMsg(tpAniSirGlobal pMac, tSirMsgQ *limMsg); +/** + * Function to cleanup LIM state. + * This called upon reset/persona change etc + */ +extern void lim_cleanup(tpAniSirGlobal); +/* / Function to post messages to LIM thread */ +extern uint32_t lim_post_msg_api(tpAniSirGlobal, tSirMsgQ *); +/** + * Function to process messages posted to LIM thread + * and dispatch to various sub modules within LIM module. + */ +extern void lim_message_processor(tpAniSirGlobal, tpSirMsgQ); +extern void lim_process_messages(tpAniSirGlobal, tpSirMsgQ); /* DT test alt deferred 2 */ +/** + * Function to check the LIM state if system is in Scan/Learn state. + */ +extern uint8_t lim_is_system_in_scan_state(tpAniSirGlobal); +/** + * Function to handle IBSS coalescing. + * Beacon Processing module to call this. + */ +extern tSirRetStatus lim_handle_ibss_coalescing(tpAniSirGlobal, + tpSchBeaconStruct, + uint8_t *, tpPESession); +/* / Function used by other Sirius modules to read global SME state */ +static inline tLimSmeStates lim_get_sme_state(tpAniSirGlobal pMac) +{ + return pMac->lim.gLimSmeState; +} + +extern void lim_received_hb_handler(tpAniSirGlobal, uint8_t, tpPESession); +extern void limCheckAndQuietBSS(tpAniSirGlobal); +/* / Function that triggers STA context deletion */ +extern void lim_trigger_sta_deletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry); + +#ifdef FEATURE_WLAN_TDLS +/* Function that sends TDLS Del Sta indication to SME */ +extern void lim_send_sme_tdls_del_sta_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry, + uint16_t reasonCode); +#endif + +/* / Function that checks for change in AP's capabilties on STA */ +extern void lim_detect_change_in_ap_capabilities(tpAniSirGlobal, + tpSirProbeRespBeacon, tpPESession); +tSirRetStatus lim_update_short_slot(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeacon, + tpUpdateBeaconParams pBeaconParams, + tpPESession); + +void lim_ps_offload_handle_missed_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void lim_send_heart_beat_timeout_ind(tpAniSirGlobal pMac, tpPESession psessionEntry); +tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + uint32_t 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 +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +#endif +#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 lim_get_phy_mode(tpAniSirGlobal pMac, uint32_t *phyMode, + tpPESession psessionEntry) +{ + *phyMode = + psessionEntry ? psessionEntry->gLimPhyMode : pMac->lim.gLimPhyMode; +} + +/* ----------------------------------------------------------------------- */ +static inline void lim_get_rf_band_new(tpAniSirGlobal pMac, tSirRFBand *band, + tpPESession psessionEntry) +{ + *band = psessionEntry ? psessionEntry->limRFBand : SIR_BAND_UNKNOWN; +} + +/*-------------------------------------------------------------------------- + + \brief pe_process_messages() - 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 uint32_t - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ +tSirRetStatus pe_process_messages(tpAniSirGlobal pMac, tSirMsgQ *pMsg); +/** ------------------------------------------------------------- + \fn pe_free_msg + \brief Called by CDS scheduler (function cds_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 + -----------------------------------------------------------------*/ +void pe_free_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +/*-------------------------------------------------------------------------- + + \brief lim_remain_on_chn_rsp() - 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 lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data); + +/*-------------------------------------------------------------------------- + + \brief lim_process_abort_scan_ind() - 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 lim_process_abort_scan_ind(tpAniSirGlobal pMac, uint8_t sessionId, + uint32_t scan_id); + +void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal, uint32_t, uint32_t *); + +/************************************************************/ +#endif /* __LIM_API_H */ diff --git a/core/mac/src/pe/include/lim_ft.h b/core/mac/src/pe/include/lim_ft.h new file mode 100644 index 000000000000..a0be848165d0 --- /dev/null +++ b/core/mac/src/pe/include/lim_ft.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. + */ + +#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 lim_ft_open(tpAniSirGlobal pMac, tpPESession psessionEntry); +void lim_ft_cleanup(tpAniSirGlobal pMac, tpPESession psessionEntry); +void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, tpPESession psessionEntry); +int lim_process_ft_pre_auth_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry); +void limPerformPostFTPreAuth(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry); +void limFTResumeLinkCb(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data); +void lim_post_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, + uint8_t *auth_rsp, uint16_t auth_rsp_length, + tpPESession psessionEntry); +void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, + uint8_t *auth_rsp, uint16_t auth_rsp_len, + tpPESession psessionEntry); +void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf, + tpPESession psessionEntry); +void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal pMac); + +bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf); +tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf); +void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void lim_ft_cleanup_all_ft_sessions(tpAniSirGlobal pMac); +void lim_fill_ft_session(tpAniSirGlobal pMac, + tpSirBssDescription pbssDescription, + tpPESession pftSessionEntry, + tpPESession psessionEntry); +tSirRetStatus lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac, + uint8_t updateEntry, + tpPESession pftSessionEntry, + tpSirBssDescription bssDescription); +#endif /* __LIMFT_H__ */ + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/core/mac/src/pe/include/lim_ft_defs.h b/core/mac/src/pe/include/lim_ft_defs.h new file mode 100644 index 000000000000..da4f11f7a27c --- /dev/null +++ b/core/mac/src/pe/include/lim_ft_defs.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. + */ + +#if defined WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + Macros and Function prototypes FT and 802.11R purposes + + ========================================================================*/ + +#ifndef __LIMFTDEFS_H__ +#define __LIMFTDEFS_H__ + +#include +#include "wma_if.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 { + uint16_t messageType; /* eWNI_SME_FT_PRE_AUTH_REQ */ + uint16_t length; + /* + * Track if response is processed for this request + * We expect only one response per request. + */ + bool bPreAuthRspProcessed; + uint8_t preAuthchannelNum; + /* BSSID currently associated to suspend the link */ + tSirMacAddr currbssId; + tSirMacAddr preAuthbssId; /* BSSID to preauth to */ + uint16_t ft_ies_length; + uint8_t ft_ies[MAX_FTIE_SIZE]; + tpSirBssDescription pbssDescription; +} tSirFTPreAuthReq, *tpSirFTPreAuthReq; + +/*------------------------------------------------------------------------- + FT Pre Auth Rsp PE<->SME + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthRsp { + uint16_t messageType; /* eWNI_SME_FT_PRE_AUTH_RSP */ + uint16_t length; + uint8_t smeSessionId; + tSirMacAddr preAuthbssId; /* BSSID to preauth to */ + tSirRetStatus status; + uint16_t ft_ies_length; + uint8_t ft_ies[MAX_FTIE_SIZE]; + uint16_t ric_ies_length; + uint8_t ric_ies[MAX_FTIE_SIZE]; +} tSirFTPreAuthRsp, *tpSirFTPreAuthRsp; + +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTUpdateKeyInfo { + uint16_t messageType; + uint16_t length; + uint32_t smeSessionId; + tSirMacAddr bssId; + tSirKeyMaterial keyMaterial; +} tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo; + +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthKeyInfo { + uint8_t extSetStaKeyParamValid; /* Ext Bss Config Msg if set */ + /* SetStaKeyParams for ext bss msg */ + tLimMlmSetKeysReq extSetStaKeyParam; +} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo; + +/*------------------------------------------------------------------------- + Global FT Information + ------------------------------------------------------------------------*/ +typedef struct sFTPEContext { + tpSirFTPreAuthReq pFTPreAuthReq; /* Saved FT Pre Auth Req */ + tSirRetStatus ftPreAuthStatus; + uint16_t saved_auth_rsp_length; + uint8_t 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 */ + uint32_t peSessionId; + uint32_t 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 + */ + bool ftPreAuthSession; +} tftPEContext, *tpftPEContext; + +#endif /* __LIMFTDEFS_H__ */ + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h new file mode 100644 index 000000000000..5ddb01c6320c --- /dev/null +++ b/core/mac/src/pe/include/lim_global.h @@ -0,0 +1,670 @@ +/* + * 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 lim_global.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 "wni_api.h" +#include "sir_api.h" +#include "sir_mac_prot_def.h" +#include "sir_mac_prop_exts.h" +#include "sir_common.h" +#include "sir_debug.h" +#include "wni_cfg.h" +#include "csr_api.h" +#include "sap_api.h" +#include "dot11f.h" +#include "wma_if.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_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, + CDF_STATUS status, + uint32_t *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; + +/* MLM Req/Cnf structure definitions */ +typedef struct sLimMlmAuthReq { + tSirMacAddr peerMacAddr; + tAniAuthType authType; + uint32_t authFailureTimeout; + uint8_t sessionId; +} tLimMlmAuthReq, *tpLimMlmAuthReq; + +typedef struct sLimMlmJoinReq { + uint32_t joinFailureTimeout; + tSirMacRateSet operationalRateSet; + uint8_t sessionId; + tSirBssDescription bssDescription; +} tLimMlmJoinReq, *tpLimMlmJoinReq; + +typedef struct sLimMlmScanReq { + tSirBssType bssType; + tSirMacAddr bssId; + tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; + tSirScanType scanType; + uint32_t minChannelTime; + uint32_t maxChannelTime; + uint32_t dot11mode; + /* Number of SSIDs to scan(send Probe request) */ + uint8_t numSsid; + + bool p2pSearch; + uint16_t uIEFieldLen; + uint16_t uIEFieldOffset; + + uint8_t 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 oemDataReq[OEM_DATA_REQ_SIZE]; +} tLimMlmOemDataReq, *tpLimMlmOemDataReq; + +typedef struct sLimMlmOemDataRsp { + uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; +} tLimMlmOemDataRsp, *tpLimMlmOemDataRsp; +#endif + +/* Pre-authentication structure definition */ +typedef struct tLimPreAuthNode { + struct tLimPreAuthNode *next; + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tLimMlmStates mlmState; + uint8_t authNodeIdx; + uint8_t challengeText[SIR_MAC_AUTH_CHALLENGE_LENGTH]; + uint8_t fTimerStarted:1; + uint8_t fSeen:1; + uint8_t fFree:1; + uint8_t rsvd:5; + TX_TIMER timer; + uint16_t seq_num; + v_TIME_t timestamp; +} tLimPreAuthNode, *tpLimPreAuthNode; + +/* Pre-authentication table definition */ +typedef struct tLimPreAuthTable { + uint32_t numEntry; + tpLimPreAuthNode pTable; +} tLimPreAuthTable, *tpLimPreAuthTable; + +/* / Per STA context structure definition */ +typedef struct sLimMlmStaContext { + tLimMlmStates mlmState; + tAniAuthType authType; + uint16_t listenInterval; + tSirMacCapabilityInfo capabilityInfo; + tSirMacPropRateSet propRateSet; + tSirMacReasonCodes disassocReason; + uint16_t cleanupTrigger; + + tSirResultCodes resultCode; + uint16_t protStatusCode; + + uint8_t subType:1; /* Indicates ASSOC (0) or REASSOC (1) */ + uint8_t updateContext:1; + uint8_t schClean:1; + /* 802.11n HT Capability in Station: Enabled 1 or DIsabled 0 */ + uint8_t htCapability:1; +#ifdef WLAN_FEATURE_11AC + uint8_t vhtCapability:1; +#endif +} tLimMlmStaContext, *tpLimMlmStaContext; + +/* Structure definition to hold deferred messages queue parameters */ +typedef struct sLimDeferredMsgQParams { + tSirMsgQ deferredQueue[MAX_DEFERRED_QUEUE_LEN]; + uint16_t size; + uint16_t read; + uint16_t write; +} tLimDeferredMsgQParams, *tpLimDeferredMsgQParams; + +typedef struct sCfgProtection { + uint32_t overlapFromlla:1; + uint32_t overlapFromllb:1; + uint32_t overlapFromllg:1; + uint32_t overlapHt20:1; + uint32_t overlapNonGf:1; + uint32_t overlapLsigTxop:1; + uint32_t overlapRifs:1; + uint32_t overlapOBSS:1; /* added for obss */ + uint32_t fromlla:1; + uint32_t fromllb:1; + uint32_t fromllg:1; + uint32_t ht20:1; + uint32_t nonGf:1; + uint32_t lsigTxop:1; + uint32_t rifs:1; + uint32_t 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 { + uint8_t 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 { + uint8_t numSta; + uint8_t protectionEnabled; +} tLimProtStaParams, *tpLimProtStaParams; + +typedef struct sLimNoShortParams { + uint8_t numNonShortPreambleSta; + tCacheParams staNoShortCache[LIM_PROT_STA_CACHE_SIZE]; +} tLimNoShortParams, *tpLimNoShortParams; + +typedef struct sLimNoShortSlotParams { + uint8_t numNonShortSlotSta; + tCacheParams staNoShortSlotCache[LIM_PROT_STA_CACHE_SIZE]; +} tLimNoShortSlotParams, *tpLimNoShortSlotParams; + +typedef struct tLimIbssPeerNode tLimIbssPeerNode; +struct tLimIbssPeerNode { + tLimIbssPeerNode *next; + tSirMacAddr peerMacAddr; + uint8_t extendedRatesPresent:1; + uint8_t edcaPresent:1; + uint8_t wmeEdcaPresent:1; + uint8_t wmeInfoPresent:1; + uint8_t htCapable:1; + uint8_t vhtCapable:1; + uint8_t rsvd:2; + uint8_t htSecondaryChannelOffset; + tSirMacCapabilityInfo capabilityInfo; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + uint8_t supportedMCSSet[SIZE_OF_SUPPORTED_MCS_SET]; + tSirMacEdcaParamSetIE edcaParams; + uint8_t erpIePresent; + + /* HT Capabilities of IBSS Peer */ + uint8_t htGreenfield; + uint8_t htShortGI40Mhz; + uint8_t htShortGI20Mhz; + + /* DSSS/CCK at 40 MHz: Enabled 1 or Disabled */ + uint8_t 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 */ + /* */ + uint8_t htAMpduDensity; + + /* Maximum Rx A-MPDU factor */ + uint8_t htMaxRxAMpduFactor; + + /* Set to 0 for 3839 octets */ + /* Set to 1 for 7935 octets */ + uint8_t htMaxAmsduLength; + + /* */ + /* Recommended Tx Width Set */ + /* 0 - use 20 MHz channel (control channel) */ + /* 1 - use 40 Mhz channel */ + /* */ + uint8_t htSupportedChannelWidthSet; + + uint8_t htLdpcCapable; + + uint8_t beaconHBCount; + uint8_t heartbeatFailure; + + uint8_t *beacon; /* Hold beacon to be sent to HDD/CSR */ + uint16_t beaconLen; + +#ifdef WLAN_FEATURE_11AC + tDot11fIEVHTCaps VHTCaps; + uint8_t vhtSupportedChannelWidthSet; + uint8_t vhtBeamFormerCapable; +#endif + /* + * Peer Atim Info + */ + uint8_t atimIePresent; + uint32_t peerAtimWindowLength; +}; + +/* Enums used for channel switching. */ +typedef enum eLimChannelSwitchState { + eLIM_CHANNEL_SWITCH_IDLE, + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY, + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY +} tLimChannelSwitchState; + +/* Channel Switch Info */ +typedef struct sLimChannelSwitchInfo { + tLimChannelSwitchState state; + uint8_t primaryChannel; + uint8_t ch_center_freq_seg0; + uint8_t ch_center_freq_seg1; + phy_ch_width ch_width; + int8_t switchCount; + uint32_t switchTimeoutValue; + uint8_t switchMode; +} tLimChannelSwitchInfo, *tpLimChannelSwitchInfo; + +#ifdef WLAN_FEATURE_11AC +typedef struct sLimOperatingModeInfo { + uint8_t present; + uint8_t chanWidth:2; + uint8_t reserved:2; + uint8_t rxNSS:3; + uint8_t rxNSSType:1; +} tLimOperatingModeInfo, *tpLimOperatingModeInfo; +#endif + +typedef struct sLimWiderBWChannelSwitch { + uint8_t newChanWidth; + uint8_t newCenterChanFreq0; + uint8_t newCenterChanFreq1; +} tLimWiderBWChannelSwitchInfo, *tpLimWiderBWChannelSwitchInfo; + +/* Enums used when stopping the Tx. */ +typedef enum eLimQuietTxMode { + /* Stop/resume transmission of all stations,Uses the global flag */ + eLIM_TX_ALL = 0, + /* + * Stops/resumes the transmission of specific stations identified + * by staId. + */ + eLIM_TX_STA, + /* Stops/resumes the transmission of all the packets in BSS */ + eLIM_TX_BSS, + /* + * 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 + */ + eLIM_TX_BSS_BUT_BEACON +} tLimQuietTxMode; + +typedef enum eLimControlTx { + eLIM_RESUME_TX = 0, + eLIM_STOP_TX +} tLimControlTx; + +/* -------------------------------------------------------------------- */ + +typedef struct sLimTspecInfo { + /* 0==free, else used */ + uint8_t inuse; + /* index in list */ + uint8_t idx; + tSirMacAddr staAddr; + uint16_t assocId; + tSirMacTspecIE tspec; + /* number of Tclas elements */ + uint8_t numTclas; + tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM]; + uint8_t tclasProc; + /* tclassProc is valid only if this is set to 1. */ + uint8_t tclasProcPresent:1; +} cdf_packed tLimTspecInfo, *tpLimTspecInfo; + +typedef struct sLimAdmitPolicyInfo { + /* admit control policy type */ + uint8_t type; + /* oversubscription factor : 0 means nothing is allowed */ + uint8_t bw_factor; + /* 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 { + bool apSetupLocked; + bool selectedRegistrar; + uint16_t selectedRegistrarConfigMethods; + tLimWscEnrollState wscEnrollmentState; + tLimWscEnrollState probeRespWscEnrollmentState; + uint8_t reqType; + uint8_t 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; + uint32_t quietCount; + /* This is in units of system TICKS */ + uint32_t quietDuration; + /* This is in units of TU, for over the air transmission */ + uint32_t quietDuration_TU; + /* After this timeout, actual quiet starts */ + uint32_t quietTimeoutValue; + /* Used on AP, if quiet is enabled during learning */ + bool fQuietEnabled; + tLimDot11hChanSwStates dot11hChanSwState; + /* Radar detected in cur oper chan on AP */ + bool fRadarDetCurOperChan; + /* Whether radar interrupt has been configured */ + bool fRadarIntrConfigured; +} tLimSpecMgmtInfo, *tpLimSpecMgmtInfo; + +#ifdef FEATURE_WLAN_TDLS +/* + * Peer info needed for TDLS setup.. + */ +typedef struct tLimTDLSPeerSta { + struct tLimTDLSPeerSta *next; + uint8_t dialog; + tSirMacAddr peerMac; + tSirMacCapabilityInfo capabilityInfo; + tSirMacRateSet supportedRates; + tSirMacRateSet extendedRates; + tSirMacQosCapabilityStaIE qosCaps; + tSirMacEdcaParamSetIE edcaParams; + uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; + uint8_t tdls_bIsResponder; + /* HT Capabilties */ + tDot11fIEHTCaps tdlsPeerHTCaps; + tDot11fIEExtCap tdlsPeerExtCaps; + uint8_t tdls_flags; + uint8_t tdls_link_state; + uint8_t tdls_prev_link_state; + uint8_t tdls_sessionId; + uint8_t ExtRatesPresent; + TX_TIMER gLimTdlsLinkSetupRspTimeoutTimer; + TX_TIMER gLimTdlsLinkSetupCnfTimeoutTimer; +} tLimTdlsLinkSetupPeer, *tpLimTdlsLinkSetupPeer; + +typedef struct tLimTdlsLinkSetupInfo { + tLimTdlsLinkSetupPeer *tdlsLinkSetupList; + uint8_t num_tdls_peers; + uint8_t tdls_flags; + uint8_t tdls_state; + uint8_t 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/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h new file mode 100644 index 000000000000..f027fa01a69e --- /dev/null +++ b/core/mac/src/pe/include/lim_session.h @@ -0,0 +1,612 @@ +/* + * 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(__LIM_SESSION_H) +#define __LIM_SESSION_H + +/**========================================================================= + + \file lim_session.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; + uint8_t bcnmiss; +} tPowersaveoffloadInfo, tpPowersaveoffloadInfo; + +#ifdef WLAN_FEATURE_11W +typedef struct tagComebackTimerInfo { + tpAniSirGlobal pMac; + uint8_t 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; + uint8_t fShortPreamble; + uint8_t llaCoexist; + uint8_t llbCoexist; + uint8_t llgCoexist; + uint8_t ht20Coexist; + uint8_t llnNonGFCoexist; + uint8_t fRIFSMode; + uint8_t fLsigTXOPProtectionFullSupport; + uint8_t gHTObssMode; +} tBeaconParams, *tpBeaconParams; + +typedef struct sPESession /* Added to Support BT-AMP */ +{ + /* To check session table is in use or free */ + uint8_t available; + uint16_t peSessionId; + uint8_t smeSessionId; + uint16_t transactionId; + + /* In AP role: BSSID and selfMacAddr will be the same. */ + /* In STA role: they will be different */ + tSirMacAddr bssId; + tSirMacAddr selfMacAddr; + tSirMacSSid ssId; + uint8_t bssIdx; + uint8_t valid; + tLimMlmStates limMlmState; /* MLM State */ + tLimMlmStates limPrevMlmState; /* Previous MLM State */ + tLimSmeStates limSmeState; /* SME State */ + tLimSmeStates limPrevSmeState; /* Previous SME State */ + tLimSystemRole limSystemRole; + tSirBssType bssType; + uint8_t 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 */ + uint16_t channelChangeReasonCode; + uint8_t dot11mode; + uint8_t htCapability; + /* Supported Channel Width Set: 0-20MHz 1 - 40MHz */ + uint8_t htSupportedChannelWidthSet; + /* Recommended Tx Width Set + * 0 - use 20 MHz channel (control channel) + * 1 - use channel width enabled under Supported Channel Width Set + */ + uint8_t htRecommendedTxWidthSet; + /* Identifies the 40 MHz extension channel */ + ePhyChanBondState htSecondaryChannelOffset; + tSirRFBand limRFBand; + uint8_t limIbssActive; /* TO SUPPORT CONCURRENCY */ + + /* These global varibales moved to session Table to support BT-AMP : Oct 9th review */ + tAniAuthType limCurrentAuthType; + uint16_t limCurrentBssCaps; + uint8_t limCurrentBssQosCaps; + uint16_t limCurrentBssPropCap; + uint8_t limSentCapsChangeNtf; + uint16_t limAID; + + /* Parameters For Reassociation */ + tSirMacAddr limReAssocbssId; + tSirMacChanNum limReassocChannelId; + /* CB paramaters required/duplicated for Reassoc since re-assoc mantains its own params in lim */ + uint8_t reAssocHtSupportedChannelWidthSet; + uint8_t reAssocHtRecommendedTxWidthSet; + ePhyChanBondState reAssocHtSecondaryChannelOffset; + tSirMacSSid limReassocSSID; + uint16_t limReassocBssCaps; + uint8_t limReassocBssQosCaps; + uint16_t 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. + */ + uint16_t staId; + uint16_t statypeForBss; /* to know session is for PEER or SELF */ + uint8_t shortSlotTimeSupported; + uint8_t dtimPeriod; + tSirMacRateSet rateSet; + tSirMacRateSet extRateSet; + tSirMacHTOperatingMode htOperMode; + uint8_t currentOperChannel; + uint8_t currentReqChannel; + uint8_t LimRxedBeaconCntDuringHB; + + /* Time stamp of the last beacon received from the BSS to which STA is connected. */ + uint64_t lastBeaconTimeStamp; + /* RX Beacon count for the current BSS to which STA is connected. */ + uint32_t currentBssBeaconCnt; + uint8_t lastBeaconDtimCount; + uint8_t lastBeaconDtimPeriod; + + uint32_t bcnLen; + uint8_t *beacon; /* Used to store last beacon / probe response before assoc. */ + + uint32_t assocReqLen; + uint8_t *assocReq; /* Used to store association request frame sent out while associating. */ + + uint32_t assocRspLen; + uint8_t *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 + uint32_t RICDataLen; /* Used to store the Ric data received in the assoc response */ + uint8_t *ricData; +#endif +#ifdef FEATURE_WLAN_ESE + uint32_t tspecLen; /* Used to store the TSPEC IEs received in the assoc response */ + uint8_t *tspecIes; +#endif + uint32_t encryptType; + + bool bTkipCntrMeasActive; /* Used to keep record of TKIP counter measures start/stop */ + + uint8_t gLimProtectionControl; /* used for 11n protection */ + + uint8_t 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]; + + uint8_t privacy; + tAniAuthType authType; + tSirKeyMaterial WEPKeyMaterial[NUM_WEP_KEYS]; + + tDot11fIERSN gStartBssRSNIe; + tDot11fIEWPA gStartBssWPAIe; + tSirAPWPSIEs APWPSIEs; + uint8_t apUapsdEnable; + tSirWPSPBCSession *pAPWPSPBCSession; + uint32_t DefProbeRspIeBitmap[8]; + uint32_t proxyProbeRspEn; + tDot11fProbeResponse probeRespFrame; + uint8_t ssidHidden; + bool fwdWPSPBCProbeReq; + uint8_t wps_state; + + uint8_t limQosEnabled:1; /* 11E */ + uint8_t limWmeEnabled:1; /* WME */ + uint8_t limWsmEnabled:1; /* WSM */ + uint8_t limHcfEnabled:1; + uint8_t lim11dEnabled:1; +#ifdef WLAN_FEATURE_11W + uint8_t limRmfEnabled:1; /* 11W */ +#endif + uint32_t lim11hEnable; + + tPowerdBm maxTxPower; /* MIN (Regulatory and local power constraint) */ + tCDF_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; + uint32_t 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]; + + uint8_t gLimEdcaParamSetCount; + + tBeaconParams beaconParams; + uint8_t vhtCapability; + uint8_t vhtTxChannelWidthSet; + tLimOperatingModeInfo gLimOperatingMode; + uint8_t vhtCapabilityPresentInBeacon; + uint8_t ch_center_freq_seg0; + phy_ch_width ch_width; + uint8_t ch_center_freq_seg1; + uint8_t txBFIniFeatureEnabled; + uint8_t txMuBformee; + uint8_t enableVhtpAid; + uint8_t enableVhtGid; + uint8_t enable_su_tx_bformer; + tLimWiderBWChannelSwitchInfo gLimWiderBWChannelSwitch; + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmpsvalue; + uint8_t 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 */ + bool LimHBFailureStatus; + uint32_t gLimPhyMode; + uint8_t amsduSupportedInBA; + uint8_t txLdpcIniFeatureEnabled; + /** + * Following is the place holder for free peer index pool. + * A non-zero value indicates that peer index is available + * for assignment. + */ + uint8_t *gpLimPeerIdxpool; + uint8_t freePeerIdxHead; + uint8_t freePeerIdxTail; + uint16_t gLimNumOfCurrentSTAs; +#ifdef FEATURE_WLAN_TDLS + uint32_t peerAIDBitmap[2]; + bool tdls_prohibited; + bool tdls_chan_swit_prohibited; +#endif + bool fWaitForProbeRsp; + bool fIgnoreCapsChange; + bool fDeauthReceived; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + int8_t rssi; +#endif + uint8_t isAmsduSupportInAMPDU; + uint8_t isCoalesingInIBSSAllowed; + + tSirHTConfig htConfig; + + /* + * Place holder for StartBssReq message + * received by SME state machine + */ + uint8_t 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. + */ + uint8_t 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. + */ + uint8_t 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. + */ + uint8_t gUapsdPerAcDeliveryEnableMask; + + /* Flag to skip CSA IE processing when CSA + * offload is enabled. + */ + uint8_t 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 + */ + uint8_t gAcAdmitMask[SIR_MAC_DIRECTION_DIRECT]; + + /* Power Save Off load Parameters */ + tPowersaveoffloadInfo pmmOffloadInfo; + /* SMPS mode */ + uint8_t smpsMode; + + uint8_t chainMask; + + /* Flag to indicate Chan Sw announcement is required */ + uint8_t dfsIncludeChanSwIe; + + /* Flag to indicate Chan Wrapper Element is required */ + uint8_t dfsIncludeChanWrapperIe; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + + bool isCiscoVendorAP; + + tSirAddIeParams addIeParams; + + uint8_t *pSchProbeRspTemplate; + /* Beginning portion of the beacon frame to be written to TFP */ + uint8_t *pSchBeaconFrameBegin; + /* Trailing portion of the beacon frame to be written to TFP */ + uint8_t *pSchBeaconFrameEnd; + /* Size of the beginning portion */ + uint16_t schBeaconOffsetBegin; + /* Size of the trailing portion */ + uint16_t schBeaconOffsetEnd; + bool isOSENConnection; + /* DSCP to UP mapping for HS 2.0 */ + tSirQosMapSet QosMapSet; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + bool bRoamSynchInProgress; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + /* Fast Transition (FT) */ + tftPEContext ftPEContext; +#endif + bool isNonRoamReassoc; +#ifdef WLAN_FEATURE_11W + cdf_mc_timer_t pmfComebackTimer; + tComebackTimerInfo pmfComebackTimerInfo; +#endif /* WLAN_FEATURE_11W */ + uint8_t is_key_installed; + /* timer for reseting protection fileds at regular intervals */ + cdf_mc_timer_t protection_fields_reset_timer; + void *mac_ctx; + /* + * variable to store state of various protection struct like + * gLimOlbcParams, gLimOverlap11gParams, gLimOverlapHt20Params etc + */ + uint16_t 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 */ +#ifdef FEATURE_WLAN_ESE + uint8_t is_ese_version_ie_present; +#endif + uint8_t sap_dot11mc; + bool is_vendor_specific_vhtcaps; + uint8_t vendor_specific_vht_ie_type; + uint8_t vendor_specific_vht_ie_sub_type; + /* flag to indicate country code in beacon */ + uint8_t country_info_present; + uint8_t nss; +} tPESession, *tpPESession; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +/** + * pe_create_session() - creates a new PE session given the BSSID + * + * @pMac: pointer to global adapter context + * @bssid: BSSID of the new session + * @sessionId: session ID is returned here, if session is created. + * @numSta: number of stations + * @bssType: bss type of new session to do conditional memory allocation. + * + * 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. + * + * Return: ptr to the session context or NULL if session can not be created. + */ +tpPESession pe_create_session(tpAniSirGlobal pMac, + uint8_t *bssid, + uint8_t *sessionId, + uint16_t numSta, tSirBssType bssType); + +/** + * pe_find_session_by_bssid() - looks up the PE session given the BSSID. + * + * @pMac: pointer to global adapter context + * @bssid: BSSID of the new session + * @sessionId: session ID is returned here, if session is created. + * + * 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. + * + * Return: pointer to the session context or NULL if session is not found. + */ +tpPESession pe_find_session_by_bssid(tpAniSirGlobal pMac, uint8_t *bssid, + uint8_t *sessionId); + +/** + * pe_find_session_by_bss_idx() - looks up the PE session given the bssIdx. + * + * @pMac: pointer to global adapter context + * @bssIdx: bss index of the session + * + * This function returns the session context if the session + * corresponding to the given bssIdx is found in the PE session table. + * + * Return: pointer to the session context or NULL if session is not found. + */ +tpPESession pe_find_session_by_bss_idx(tpAniSirGlobal pMac, uint8_t bssIdx); + +/** + * pe_find_session_by_peer_sta() - looks up the PE session given the Peer + * Station Address. + * + * @pMac: pointer to global adapter context + * @sa: Peer STA Address of the session + * @sessionId: session ID is returned here, if session is found. + * + * 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. + * + * Return: pointer to the session context or NULL if session is not found. + */ +tpPESession pe_find_session_by_peer_sta(tpAniSirGlobal pMac, uint8_t *sa, + uint8_t *sessionId); + +/** + * pe_find_session_by_session_id() - looks up the PE session given the session + * ID. + * + * @pMac: pointer to global adapter context + * @sessionId: session ID for which session context needs to be looked up. + * + * This function returns the session context if the session corresponding to + * the given session ID is found in the PE session table. + * + * Return: pointer to the session context or NULL if session is not found. + */ +tpPESession pe_find_session_by_session_id(tpAniSirGlobal pMac, + uint8_t sessionId); + +/** + * pe_find_session_by_bssid() - looks up the PE session given staid. + * + * @pMac: pointer to global adapter context + * @staid: StaId of the session + * @sessionId: session ID is returned here, if session is found. + * + * 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. + * + * Return: pointer to the session context or NULL if session is not found. + */ +tpPESession pe_find_session_by_sta_id(tpAniSirGlobal pMac, uint8_t staid, + uint8_t *sessionId); + +/** + * pe_delete_session() - deletes the PE session given the session ID. + * + * @pMac: pointer to global adapter context + * @sessionId: session ID to delete. + * + * Return: void + */ +void pe_delete_session(tpAniSirGlobal pMac, tpPESession psessionEntry); + + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * 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); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx); +#endif /* #if !defined( __LIM_SESSION_H ) */ diff --git a/core/mac/src/pe/include/lim_trace.h b/core/mac/src/pe/include/lim_trace.h new file mode 100644 index 000000000000..494edc8703b5 --- /dev/null +++ b/core/mac/src/pe/include/lim_trace.h @@ -0,0 +1,99 @@ +/* + * 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 lim_trace.h + + * \brief definition for trace related APIs + + * \author Sunit Bhatia + + ========================================================================*/ + +#ifndef __LIM_TRACE_H +#define __LIM_TRACE_H + +#include "lim_global.h" +#include "mac_trace.h" +#include "cdf_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_WMA_MSG, + TRACE_CODE_RX_WMA_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 lim_trace_init(tpAniSirGlobal pMac); +void limTraceReset(tpAniSirGlobal pMac); +void limTraceUpdateMgmtStat(tpAniSirGlobal pMac, uint8_t subtype); +void lim_trace_dumpMgmtStat(tpAniSirGlobal pMac, uint8_t subtype); +uint8_t *lim_trace_get_mlm_state_string(uint32_t mlmState); +uint8_t *lim_trace_get_sme_state_string(uint32_t smeState); +void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, + uint16_t recIndex); +void mac_trace_msg_tx(tpAniSirGlobal pMac, uint8_t session, uint32_t data); +void mac_trace_msg_rx(tpAniSirGlobal pMac, uint8_t session, uint32_t data); + +void mac_trace_msg_rx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session, + uint32_t data); +void mac_trace_msg_tx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session, + uint32_t data); +#endif /* endof LIM_TRACE_RECORD MACRO */ + +#endif diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h new file mode 100644 index 000000000000..05466c00423c --- /dev/null +++ b/core/mac/src/pe/include/rrm_api.h @@ -0,0 +1,104 @@ +/* + * 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 rrm_api.h + + \brief RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +#ifndef __RRM_API_H__ +#define __RRM_API_H__ + +#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 + +uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, tPowerdBm regMax, + tPowerdBm apTxPower); + +extern tSirRetStatus rrm_initialize(tpAniSirGlobal pMac); + +extern tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac); + +extern tSirRetStatus rrm_process_link_measurement_request(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + tDot11fLinkMeasurementRequest + *pLinkReq, + tpPESession + pSessionEntry); + +extern tSirRetStatus rrm_process_radio_measurement_request(tpAniSirGlobal pMac, + tSirMacAddr peer, + tDot11fRadioMeasurementRequest + *pRRMReq, + tpPESession + pSessionEntry); + +extern tSirRetStatus rrm_process_neighbor_report_response(tpAniSirGlobal pMac, + tDot11fNeighborReportResponse + *pNeighborRep, + tpPESession + pSessionEntry); + +extern void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg); + +extern tSirRetStatus rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, + tPowerdBm txPower, + tpPESession pSessionEntry); + +extern tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, + tpPESession pSessionEntry); + +extern void rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, + tPowerdBm txPower, tpPESession pSessionEntry); + +extern tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, + tpPESession pSessionEntry); + +extern void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry); + +extern void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF); + +extern void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2]); + +extern tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ); + +extern tSirRetStatus +rrm_process_neighbor_report_req(tpAniSirGlobal pMac, + tpSirNeighborReportReqInd pNeighborReq); +extern tSirRetStatus +rrm_process_beacon_report_xmit(tpAniSirGlobal pMac, + tpSirBeaconReportXmitInd pBcnReport); +#endif diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h new file mode 100644 index 000000000000..053848d1f0c5 --- /dev/null +++ b/core/mac/src/pe/include/rrm_global.h @@ -0,0 +1,228 @@ +/* + * 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 rrm_global.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 { + uint8_t regulatoryClass; + uint8_t channelNum; +} tSirChannelInfo, *tpSirChannelInfo; + +typedef struct sSirBeaconReportReqInd { + uint16_t messageType; /* eWNI_SME_BEACON_REPORT_REQ_IND */ + uint16_t length; + tSirMacAddr bssId; + uint16_t measurementDuration[SIR_ESE_MAX_MEAS_IE_REQS]; /* ms */ + uint16_t randomizationInterval; /* ms */ + tSirChannelInfo channelInfo; + /* 0: wildcard */ + tSirMacAddr macaddrBssid; + /* 0:Passive, 1: Active, 2: table mode */ + uint8_t fMeasurementtype[SIR_ESE_MAX_MEAS_IE_REQS]; + tAniSSID ssId; /* May be wilcard. */ + uint16_t uDialogToken; + tSirChannelList channelList; /* From AP channel report. */ + tRrmMsgReqSource msgSource; +} tSirBeaconReportReqInd, *tpSirBeaconReportReqInd; + +typedef struct sSirBeaconReportXmitInd { + uint16_t messageType; /* eWNI_SME_BEACON_REPORT_RESP_XMIT_IND */ + uint16_t length; + tSirMacAddr bssId; + uint16_t uDialogToken; + uint8_t fMeasureDone; + uint16_t duration; + uint8_t regClass; + uint8_t numBssDesc; + tpSirBssDescription pBssDescription[SIR_BCN_REPORT_MAX_BSS_DESC]; +} tSirBeaconReportXmitInd, *tpSirBeaconReportXmitInd; + +typedef struct sSirNeighborReportReqInd { + /* eWNI_SME_NEIGHBOR_REPORT_REQ_IND */ + uint16_t messageType; + uint16_t length; + /* For the session. */ + tSirMacAddr bssId; + /* true - dont include SSID in the request. */ + uint16_t noSSID; + /* false include the SSID. It may be null (wildcard) */ + tSirMacSSid ucSSID; +} tSirNeighborReportReqInd, *tpSirNeighborReportReqInd; + +typedef struct sSirNeighborBssDescription { + uint16_t length; + tSirMacAddr bssId; + uint8_t regClass; + uint8_t channel; + uint8_t phyType; + union sSirNeighborBssidInfo { + struct _rrmInfo { + /* see IEEE 802.11k Table 7-43a */ + uint32_t fApPreauthReachable:2; + uint32_t fSameSecurityMode:1; + uint32_t fSameAuthenticator:1; + /* see IEEE 802.11k Table 7-95d */ + uint32_t fCapSpectrumMeasurement:1; + uint32_t fCapQos:1; + uint32_t fCapApsd:1; + uint32_t fCapRadioMeasurement:1; + uint32_t fCapDelayedBlockAck:1; + uint32_t fCapImmediateBlockAck:1; + uint32_t fMobilityDomain:1; + uint32_t reserved:21; + } rrmInfo; + struct _eseInfo { + uint32_t channelBand:8; + uint32_t minRecvSigPower:8; + uint32_t apTxPower:8; + uint32_t roamHysteresis:8; + uint32_t adaptScanThres:8; + + uint32_t transitionTime:8; + uint32_t tsfOffset:16; + + uint32_t beaconInterval:16; + uint32_t reserved:16; + } eseInfo; + } bssidInfo; + + /* Optional sub IEs....ignoring for now. */ +} tSirNeighborBssDescription, *tpSirNeighborBssDescripton; + +typedef struct sSirNeighborReportInd { + uint16_t messageType; /* eWNI_SME_NEIGHBOR_REPORT_IND */ + uint16_t length; + uint8_t sessionId; + uint16_t numNeighborReports; + tSirMacAddr bssId; /* For the session. */ + tSirNeighborBssDescription sNeighborBssDescription[1]; +} tSirNeighborReportInd, *tpSirNeighborReportInd; + +typedef struct sRRMBeaconReportRequestedIes { + uint8_t num; + uint8_t *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 { + uint8_t dialog_token; /* In action frame; */ + uint8_t token; /* Within individual request; */ + uint8_t type; + union { + struct { + uint8_t reportingDetail; + tRRMBeaconReportRequestedIes reqIes; + } Beacon; + } request; + uint8_t sendEmptyBcnRpt; +} tRRMReq, *tpRRMReq; + +typedef struct sRRMCaps { + uint8_t LinkMeasurement:1; + uint8_t NeighborRpt:1; + uint8_t parallel:1; + uint8_t repeated:1; + uint8_t BeaconPassive:1; + uint8_t BeaconActive:1; + uint8_t BeaconTable:1; + uint8_t BeaconRepCond:1; + uint8_t FrameMeasurement:1; + uint8_t ChannelLoad:1; + uint8_t NoiseHistogram:1; + uint8_t statistics:1; + uint8_t LCIMeasurement:1; + uint8_t LCIAzimuth:1; + uint8_t TCMCapability:1; + uint8_t triggeredTCM:1; + uint8_t APChanReport:1; + uint8_t RRMMIBEnabled:1; + uint8_t operatingChanMax:3; + uint8_t nonOperatingChanMax:3; + uint8_t MeasurementPilot:3; + uint8_t MeasurementPilotEnabled:1; + uint8_t NeighborTSFOffset:1; + uint8_t RCPIMeasurement:1; + uint8_t RSNIMeasurement:1; + uint8_t BssAvgAccessDelay:1; + uint8_t BSSAvailAdmission:1; + uint8_t AntennaInformation:1; + uint8_t fine_time_meas_rpt:1; + uint8_t lci_capability:1; + uint8_t reserved:4; +} tRRMCaps, *tpRRMCaps; + +typedef struct sRrmPEContext { + uint8_t rrmEnable; + /* + * Used during scan/measurement to store the start TSF. + * this is not used directly in beacon reports. + */ + uint32_t startTSF[2]; + /* + * This value is stored into bssdescription and beacon report + * gets it from bss decsription. + */ + tRRMCaps rrmEnabledCaps; + tPowerdBm txMgmtPower; + /* Dialog token for the request initiated from station. */ + uint8_t DialogToken; + 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) + +#endif /* #if defined __RRMGLOBAL_H */ diff --git a/core/mac/src/pe/include/sch_api.h b/core/mac/src/pe/include/sch_api.h new file mode 100644 index 000000000000..04db805e19f8 --- /dev/null +++ b/core/mac/src/pe/include/sch_api.h @@ -0,0 +1,112 @@ +/* + * 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 __SCH_API_H__ +#define __SCH_API_H__ + +#include "sir_common.h" +#include "sir_mac_prot_def.h" + +#include "ani_global.h" + +/* / Send start scan response message */ +extern void sch_send_start_scan_rsp(tpAniSirGlobal pMac); + +/* update only the broadcast qos params */ +extern void sch_qos_update_broadcast(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +/* fill in the default local edca parameter into gLimEdcaParams[] */ +extern void sch_set_default_edca_params(tpAniSirGlobal pMac, tpPESession psessionE); + +/* update only local qos params */ +extern void sch_qos_update_local(tpAniSirGlobal pMac, tpPESession psessionEntry); + +/* update the edca profile parameters */ +extern void sch_edca_profile_update(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +/* / Set the fixed fields in a beacon frame */ +extern tSirRetStatus sch_set_fixed_beacon_fields(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +/* / Initialize globals */ +extern void sch_init_globals(tpAniSirGlobal pMac); + +/* / Initialize CF Poll template */ +extern void sch_initializeCfPollTemplate(tpAniSirGlobal pMac); + +/* / Initialize CF End template */ +extern void sch_initializeCfEndTemplate(tpAniSirGlobal pMac); + +/* / Process the scheduler messages */ +extern void sch_process_message(tpAniSirGlobal pMac, tpSirMsgQ pSchMsg); + +/* / The beacon Indication handler function */ +extern void sch_process_pre_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg); + +/* / Post a message to the scheduler message queue */ +extern tSirRetStatus sch_post_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg); + +extern void sch_beacon_process(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry); +extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *edca, + tpPESession psessionEntry); + +void sch_generate_tim(tpAniSirGlobal, uint8_t **, uint16_t *, uint8_t); +#define SCH_RR_TIMEOUT (SCH_RR_TIMEOUT_MS / SYS_TICK_DUR_MS) + +void sch_set_beacon_interval(tpAniSirGlobal pMac, tpPESession psessionEntry); + +tSirRetStatus sch_send_beacon_req(tpAniSirGlobal, uint8_t *, uint16_t, + tpPESession psessionEntry); + +tSirRetStatus lim_update_probe_rsp_template_ie_bitmap_beacon1(tpAniSirGlobal, + tDot11fBeacon1 *, + tpPESession + psessionEntry); +void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal, tDot11fBeacon2 *, + uint32_t *, + tDot11fProbeResponse *); +void set_probe_rsp_ie_bitmap(uint32_t *, uint32_t); +uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal, tpPESession, uint32_t *); + +int sch_gen_timing_advert_frame(tpAniSirGlobal pMac, tSirMacAddr self_addr, + uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset); + +#endif diff --git a/core/mac/src/pe/include/sch_global.h b/core/mac/src/pe/include/sch_global.h new file mode 100644 index 000000000000..baebe98f96de --- /dev/null +++ b/core/mac/src/pe/include/sch_global.h @@ -0,0 +1,176 @@ +/* + * 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 "sir_mac_prop_exts.h" +#include "lim_global.h" + +#include "parser_api.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 { + uint16_t gSchBeaconInterval; + + /* / Current CFP count */ + uint8_t gSchCFPCount; + + /* / CFP Duration remaining */ + uint8_t gSchCFPDurRemaining; + + /* / CFP Maximum Duration */ + uint8_t gSchCFPMaxDuration; + + /* / Current DTIM count */ + uint8_t gSchDTIMCount; + + /* / Whether we have initiated a CFP or not */ + uint8_t gSchCFPInitiated; + + /* / Whether we have initiated a CFB or not */ + uint8_t gSchCFBInitiated; + + /* / CFP is enabled and AP is configured as HCF */ + uint8_t gSchCFPEnabled; + + /* / CFB is enabled and AP is configured as HCF */ + uint8_t gSchCFBEnabled; + + /* --------- STA ONLY state ----------- */ + + /* / Indicates whether RR timer is running or not */ + uint8_t rrTimer[8]; + + /* / Indicates the remaining RR timeout value if the RR timer is running */ + uint16_t rrTimeout[8]; + + /* / Number of RRs transmitted */ + uint16_t numRR[8]; + uint16_t numRRtimeouts[8]; + + /* / flag to indicate that beacon template has been updated */ + uint8_t fBeaconChanged; + + uint16_t p2pIeOffset; + +}; + +/* ****************** MISC defs ********************************* */ + +typedef struct schStaWaitList { + uint16_t staId; + uint16_t count; +} tStaWaitList, *tpStaWaitList; + +/* / Global SCH structure */ +typedef struct sAniSirSch { + /* / The scheduler object */ + struct schMisc schObject; + + /* schQoSClass unsolicited; */ + + /* / Whether HCF is enabled or not */ + uint8_t gSchHcfEnabled; + + /* / Whether scan is requested by LIM or not */ + uint8_t gSchScanRequested; + + /* / Whether scan request is received by SCH or not */ + uint8_t gSchScanReqRcvd; + + /* / Debug flag to disable beacon generation */ + uint32_t gSchGenBeacon; + +#define SCH_MAX_ARR 100 + uint32_t gSchBeaconsWritten; + uint32_t gSchBeaconsSent; + uint32_t gSchBBXportRcvCnt; + uint32_t gSchRRRcvCnt, qosNullCnt; + uint32_t gSchBcnRcvCnt; + uint32_t gSchUnknownRcvCnt; + + uint32_t gSchBcnParseErrorCnt; + uint32_t gSchBcnIgnored; + + uint32_t numPoll, numData, numCorrupt; + uint32_t numBogusInt, numTxAct0; + +#define SCH_MAX_NUM_SCH 21 + uint32_t lastBeaconLength; + uint16_t rrTimeout; + uint32_t pollPeriod; + uint32_t multipleSched; + uint32_t pollFeedbackHist[8]; + uint32_t dataFeedbackHist[8]; + uint32_t maxPollTimeouts; + uint32_t checkCfbFlagStuck; + + /* / Sta Wait list */ + tpStaWaitList pStaWaitList; + + /* / Pointer to next available entry in sta wait list */ + uint16_t staWaitListIn; + /* / Pointer to first waiting sta in sta wait list */ + uint16_t staWaitListOut; + /* / Total number of waiting STAs in sta wait list */ + uint16_t staWaitListCount; + /* / Total number of schedules to be waited */ + uint16_t staWaitListTotalWait; + + /* / Number of entries in DPH activity queue that were ignored */ + uint32_t ignoreDph; + +} tAniSirSch, *tpAniSirSch; + +#endif diff --git a/core/mac/src/pe/include/wmm_apsd.h b/core/mac/src/pe/include/wmm_apsd.h new file mode 100644 index 000000000000..9b5d5d4affd8 --- /dev/null +++ b/core/mac/src/pe/include/wmm_apsd.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 "ani_global.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/core/mac/src/pe/lim/lim_admit_control.c b/core/mac/src/pe/lim/lim_admit_control.c new file mode 100644 index 000000000000..b217c402ee96 --- /dev/null +++ b/core/mac/src/pe/lim/lim_admit_control.c @@ -0,0 +1,1140 @@ +/* + * 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 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 "lim_debug.h" +#include "sys_def.h" +#include "lim_api.h" +#include "cfg_api.h" /* wlan_cfg_get_int() */ +#include "lim_trace.h" +#include "lim_send_sme_rsp_messages.h" +#include "lim_types.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 +lim_calculate_svc_int(tpAniSirGlobal, tSirMacTspecIE *, uint32_t *); +static tSirRetStatus +lim_validate_tspec_edca(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); +static tSirRetStatus +lim_validate_tspec(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); +static void +lim_compute_mean_bw_used(tpAniSirGlobal, uint32_t *, uint32_t, tpLimTspecInfo, + tpPESession); +static void lim_get_available_bw(tpAniSirGlobal, uint32_t *, uint32_t *, uint32_t, + uint32_t); +static tSirRetStatus lim_admit_policy_oversubscription(tpAniSirGlobal, + tSirMacTspecIE *, + tpLimAdmitPolicyInfo, + tpLimTspecInfo, + tpPESession); +static tSirRetStatus lim_tspec_find_by_sta_addr(tpAniSirGlobal, uint8_t *, + tSirMacTspecIE *, tpLimTspecInfo, + tpLimTspecInfo *); +static tSirRetStatus lim_validate_access_policy(tpAniSirGlobal, uint8_t, uint16_t, + tpPESession); + +/** ------------------------------------------------------------- + \fn lim_calculate_svc_int + \brief TSPEC validation and servcie interval determination + \param tpAniSirGlobal pMac + \param tSirMacTspecIE *pTspec + \param uint32_t *pSvcInt + \return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +static tSirRetStatus +lim_calculate_svc_int(tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, uint32_t *pSvcInt) +{ + uint32_t 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(lim_log(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(lim_log(pMac, LOGE, FL("DataRate not specified"));) + return eSIR_FAILURE; + } + + *pSvcInt = + LIM_CONVERT_SIZE_BITS(msduSz) / LIM_CONVERT_RATE_MBPS(dataRate); + return eSIR_FAILURE; +} + +/** + * lim_validate_tspec_edca() - Validate the parameters + * @mac_ctx: Global MAC context + * @tspec: Pointer to the TSPEC + * @session_entry: Session Entry + * + * validate the parameters in the edca tspec + * mandatory fields are derived from 11e Annex I (Table I.1) + * + * Return: Status + **/ +static tSirRetStatus +lim_validate_tspec_edca(tpAniSirGlobal mac_ctx, + tSirMacTspecIE *tspec, tpPESession session_entry) +{ + uint32_t max_phy_rate, min_phy_rate; + uint32_t phy_mode; + tSirRetStatus retval = eSIR_SUCCESS; + + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + lim_get_available_bw(mac_ctx, &max_phy_rate, &min_phy_rate, phy_mode, + 1 /* bandwidth mult factor */); + /* mandatory fields are derived from 11e Annex I (Table I.1) */ + if ((tspec->nomMsduSz == 0) || + (tspec->meanDataRate == 0) || + (tspec->surplusBw == 0) || + (tspec->minPhyRate == 0) || + (tspec->minPhyRate > max_phy_rate)) { + lim_log(mac_ctx, LOGW, + FL + ("Invalid EDCA Tspec: NomMsdu %d, meanDataRate %d, surplusBw %d, min_phy_rate %d"), + tspec->nomMsduSz, tspec->meanDataRate, + tspec->surplusBw, tspec->minPhyRate); + retval = eSIR_FAILURE; + } + + lim_log(mac_ctx, ADMIT_CONTROL_LOGLEVEL, + FL("return status %d"), retval); + return retval; +} + +/** ------------------------------------------------------------- + \fn lim_validate_tspec + \brief validate the offered tspec + \param tpAniSirGlobal pMac + \param tSirMacTspecIE *pTspec + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +static tSirRetStatus +lim_validate_tspec(tpAniSirGlobal pMac, + tSirMacTspecIE *pTspec, tpPESession psessionEntry) +{ + tSirRetStatus retval = eSIR_SUCCESS; + switch (pTspec->tsinfo.traffic.accessPolicy) { + case SIR_MAC_ACCESSPOLICY_EDCA: + retval = lim_validate_tspec_edca(pMac, pTspec, psessionEntry); + if (retval != eSIR_SUCCESS) + PELOGW(lim_log(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: + lim_log(pMac, LOGW, FL("AccessType %d not supported"), + pTspec->tsinfo.traffic.accessPolicy); + retval = eSIR_FAILURE; + break; + } + return retval; +} + +/* ----------------------------------------------------------------------------- */ +/* Admit Control Policy */ + +/** ------------------------------------------------------------- + \fn lim_compute_mean_bw_used + \brief determime the used/allocated bandwidth + \param tpAniSirGlobal pMac + \param uint32_t *pBw + \param uint32_t phyMode + \param tpLimTspecInfo pTspecInfo + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +static void +lim_compute_mean_bw_used(tpAniSirGlobal pMac, + uint32_t *pBw, + uint32_t phyMode, + tpLimTspecInfo pTspecInfo, tpPESession psessionEntry) +{ + uint32_t ctspec; + *pBw = 0; + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) { + if (pTspecInfo->inuse) { + tpDphHashNode pSta = + dph_get_hash_entry(pMac, pTspecInfo->assocId, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) { + /* maybe we should delete the tspec?? */ + lim_log(pMac, LOGE, + FL + ("Tspec %d (assocId %d): dphNode not found"), + ctspec, pTspecInfo->assocId); + continue; + } + *pBw += pTspecInfo->tspec.meanDataRate; + } + } +} + +/** ------------------------------------------------------------- + \fn lim_get_available_bw + \brief based on the phy mode and the bw_factor, determine the total bandwidth that + can be supported + \param tpAniSirGlobal pMac + \param uint32_t *pMaxBw + \param uint32_t *pMinBw + \param uint32_t phyMode + \param uint32_t bw_factor + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +static void +lim_get_available_bw(tpAniSirGlobal pMac, + uint32_t *pMaxBw, + uint32_t *pMinBw, uint32_t phyMode, uint32_t 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; +} + +/** + * lim_admit_policy_oversubscription() - Admission control policy + * @mac_ctx: Global MAC Context + * @tspec: Pointer to the tspec + * @admit_policy: Admission policy + * @tspec_info: TSPEC information + * @session_entry: Session Entry + * + * 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. + * + * Return: Status + **/ +static tSirRetStatus +lim_admit_policy_oversubscription(tpAniSirGlobal mac_ctx, + tSirMacTspecIE *tspec, + tpLimAdmitPolicyInfo admit_policy, + tpLimTspecInfo tspec_info, + tpPESession session_entry) +{ + uint32_t totalbw, minbw, usedbw; + uint32_t phy_mode; + + /* determine total bandwidth used so far */ + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + lim_compute_mean_bw_used(mac_ctx, &usedbw, phy_mode, + tspec_info, session_entry); + + /* determine how much bw is available based on the current phy mode */ + lim_get_available_bw(mac_ctx, &totalbw, &minbw, phy_mode, + admit_policy->bw_factor); + + if (usedbw > totalbw) /* this can't possibly happen */ + return eSIR_FAILURE; + + if ((totalbw - usedbw) < tspec->meanDataRate) { + lim_log(mac_ctx, ADMIT_CONTROL_POLICY_LOGLEVEL, + FL + ("Total BW %d, Used %d, Tspec request %d not possible"), + totalbw, usedbw, tspec->meanDataRate); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_admit_policy + \brief determine the current admit control policy and apply it for the offered tspec + \param tpAniSirGlobal pMac + \param tSirMacTspecIE *pTspec + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus lim_admit_policy(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 = lim_admit_policy_oversubscription(pMac, pTspec, + &pMac->lim. + admitPolicyInfo, + &pMac->lim.tspecInfo[0], + psessionEntry); + if (retval != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, FL("rejected by BWFactor policy")); + ) + break; + + case WNI_CFG_ADMIT_POLICY_REJECT_ALL: + retval = eSIR_FAILURE; + break; + + default: + retval = eSIR_SUCCESS; + lim_log(pMac, LOGE, + FL("Admit Policy %d unknown, admitting all traffic"), + pAdmitPolicy->type); + break; + } + return retval; +} + +/** ------------------------------------------------------------- + \fn lim_tspec_delete + \brief delete the specified tspec + \param tpAniSirGlobal pMac + \param tpLimTspecInfo pInfo + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +/* ----------------------------------------------------------------------------- */ +/* delete the specified tspec */ +void lim_tspec_delete(tpAniSirGlobal pMac, tpLimTspecInfo pInfo) +{ + if (pInfo == NULL) + return; + /* pierre */ + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tspec entry = %d"), + pInfo->idx); + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("delete tspec %p"), pInfo); + pInfo->inuse = 0; + + return; +} + +/** ------------------------------------------------------------- + \fn lim_tspec_find_by_sta_addr + \brief Send halMsg_AddTs to HAL + \param tpAniSirGlobal pMac + \param \param uint8_t *pAddr + \param tSirMacTspecIE *pTspecIE + \param tpLimTspecInfo pTspecList + \param tpLimTspecInfo *ppInfo + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +/* find the specified tspec in the list */ +static tSirRetStatus +lim_tspec_find_by_sta_addr(tpAniSirGlobal pMac, + uint8_t *pAddr, + tSirMacTspecIE *pTspecIE, + tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) { + if ((pTspecList->inuse) + && + (cdf_mem_compare + (pAddr, pTspecList->staAddr, sizeof(pTspecList->staAddr))) + && + (cdf_mem_compare + ((uint8_t *) pTspecIE, (uint8_t *) &pTspecList->tspec, + sizeof(tSirMacTspecIE)))) { + *ppInfo = pTspecList; + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- + \fn lim_tspec_find_by_assoc_id + \brief find tspec with matchin staid and Tspec + \param tpAniSirGlobal pMac + \param uint32_t staid + \param tSirMacTspecIE *pTspecIE + \param tpLimTspecInfo pTspecList + \param tpLimTspecInfo *ppInfo + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +lim_tspec_find_by_assoc_id(tpAniSirGlobal pMac, + uint16_t assocId, + tSirMacTspecIE *pTspecIE, + tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, + FL("Trying to find tspec entry for assocId = %d"), assocId); + lim_log(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) + && + (cdf_mem_compare + ((uint8_t *) pTspecIE, (uint8_t *) &pTspecList->tspec, + sizeof(tSirMacTspecIE)))) { + *ppInfo = pTspecList; + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- + \fn lim_find_tspec + \brief finding a TSPEC entry with assocId, tsinfo.direction and tsinfo.tsid + \param uint16_t assocId + \param tpAniSirGlobal pMac + \param tSirMacTSInfo *pTsInfo + \param tpLimTspecInfo pTspecList + \param tpLimTspecInfo *ppInfo + \return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +tSirRetStatus +lim_find_tspec(tpAniSirGlobal pMac, + uint16_t assocId, + tSirMacTSInfo *pTsInfo, + tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo) +{ + int ctspec; + + *ppInfo = NULL; + + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, + FL("Trying to find tspec entry for assocId = %d"), assocId); + lim_log(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 lim_tspec_add + \brief add or update the specified tspec to the tspec list + \param tpAniSirGlobal pMac + \param uint8_t *pAddr + \param uint16_t assocId + \param tSirMacTspecIE *pTspec + \param uint32_t interval + \param tpLimTspecInfo *ppInfo + + \return eSirRetStatus - status of the comparison + -------------------------------------------------------------*/ + +tSirRetStatus lim_tspec_add(tpAniSirGlobal pMac, + uint8_t *pAddr, + uint16_t assocId, + tSirMacTspecIE *pTspec, + uint32_t interval, tpLimTspecInfo *ppInfo) +{ + tpLimTspecInfo pTspecList = &pMac->lim.tspecInfo[0]; + *ppInfo = NULL; + + /* validate the assocId */ + if (assocId >= pMac->lim.maxStation) { + PELOGE(lim_log(pMac, LOGE, FL("Invalid assocId 0x%x"), assocId);) + return eSIR_FAILURE; + } + /* decide whether to add/update */ + { + *ppInfo = NULL; + + if (eSIR_SUCCESS == + lim_find_tspec(pMac, assocId, &pTspec->tsinfo, pTspecList, + ppInfo)) { + /* update this entry. */ + lim_log(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 + */ + uint8_t ctspec = 0; + for (ctspec = 0, pTspecList = &pMac->lim.tspecInfo[0]; + ctspec < LIM_NUM_TSPEC_MAX; + ctspec++, pTspecList++) { + if (!pTspecList->inuse) { + lim_log(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; + cdf_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; + lim_log(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; + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, + FL("added entry for HCCA AccessPolicy")); + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_validate_access_policy + \brief Validates Access policy + \param tpAniSirGlobal pMac + \param uint8_t accessPolicy + \param uint16_t assocId + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +static tSirRetStatus +lim_validate_access_policy(tpAniSirGlobal pMac, + uint8_t accessPolicy, + uint16_t assocId, tpPESession psessionEntry) +{ + tSirRetStatus retval = eSIR_FAILURE; + tpDphHashNode pSta = + dph_get_hash_entry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if ((pSta == NULL) || (!pSta->valid)) { + PELOGE(lim_log(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(lim_log + (pMac, LOGE, FL("Invalid accessPolicy %d"), + accessPolicy); + ) + break; + } + + if (retval != eSIR_SUCCESS) + lim_log(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; +} + +/** + * lim_admit_control_add_ts() - Check if STA can be admitted + * @pMac: Global MAC context + * @pAddr: Address + * @pAddts: ADD TS + * @pQos: QOS fields + * @assocId: Association ID + * @alloc: Allocate bandwidth for this tspec + * @pSch: Schedule IE + * @pTspecIdx: TSPEC index + * @psessionEntry: PE Session Entry + * + * Determine if STA with the specified TSPEC can be admitted. If it can, + * a schedule element is provided + * + * Return: status + **/ +tSirRetStatus lim_admit_control_add_ts(tpAniSirGlobal pMac, uint8_t *pAddr, + tSirAddtsReqInfo *pAddts, tSirMacQosCapabilityStaIE *pQos, + uint16_t assocId, uint8_t alloc, tSirMacScheduleIE *pSch, + uint8_t *pTspecIdx, tpPESession psessionEntry) +{ + tpLimTspecInfo pTspecInfo; + tSirRetStatus retval; + uint32_t 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. */ + + lim_log(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) + ? lim_tspec_find_by_assoc_id(pMac, assocId, &pAddts->tspec, + &pMac->lim.tspecInfo[0], &pTspecInfo) + : lim_tspec_find_by_sta_addr(pMac, pAddr, &pAddts->tspec, + &pMac->lim.tspecInfo[0], &pTspecInfo); + + if (retval == eSIR_SUCCESS) { + lim_log(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 (lim_validate_tspec(pMac, &pAddts->tspec, psessionEntry) != + eSIR_SUCCESS) { + PELOGW(lim_log(pMac, LOGW, FL("tspec validation failed"));) + return eSIR_FAILURE; + } + /* determine a service interval for the tspec */ + if (lim_calculate_svc_int(pMac, &pAddts->tspec, &svcInterval) != + eSIR_SUCCESS) { + PELOGW(lim_log(pMac, LOGW, FL("SvcInt calculate failed"));) + return eSIR_FAILURE; + } + /* determine if the tspec can be admitted or not based on current policy */ + if (lim_admit_policy(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) { + PELOGW(lim_log + (pMac, LOGW, + FL("tspec rejected by admit control policy")); + ) + return eSIR_FAILURE; + } + /* fill in a schedule if requested */ + if (pSch != NULL) { + cdf_mem_set((uint8_t *) pSch, sizeof(*pSch), 0); + pSch->svcStartTime = pAddts->tspec.svcStartTime; + pSch->svcInterval = svcInterval; + pSch->maxSvcDuration = (uint16_t) 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 (lim_validate_access_policy + (pMac, (uint8_t) pAddts->tspec.tsinfo.traffic.accessPolicy, assocId, + psessionEntry) != eSIR_SUCCESS) { + lim_log(pMac, LOGW, + FL("AccessPolicy %d is not valid in current mode"), + pAddts->tspec.tsinfo.traffic.accessPolicy); + return eSIR_FAILURE; + } + /* add tspec to list */ + if (lim_tspec_add + (pMac, pAddr, assocId, &pAddts->tspec, svcInterval, &pTspecInfo) + != eSIR_SUCCESS) { + PELOGE(lim_log(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 lim_admit_control_delete_ts + \brief Delete the specified Tspec for the specified STA + \param tpAniSirGlobal pMac + \param uint16_t assocId + \param tSirMacTSInfo *pTsInfo + \param uint8_t *pTsStatus + \param uint8_t *ptspecIdx + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +lim_admit_control_delete_ts(tpAniSirGlobal pMac, + uint16_t assocId, + tSirMacTSInfo *pTsInfo, + uint8_t *pTsStatus, uint8_t *ptspecIdx) +{ + tpLimTspecInfo pTspecInfo = NULL; + + if (pTsStatus != NULL) + *pTsStatus = 0; + + if (lim_find_tspec + (pMac, assocId, pTsInfo, &pMac->lim.tspecInfo[0], + &pTspecInfo) == eSIR_SUCCESS) { + if (pTspecInfo != NULL) { + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, + FL("Tspec entry %d found"), pTspecInfo->idx); + + *ptspecIdx = pTspecInfo->idx; + lim_tspec_delete(pMac, pTspecInfo); + return eSIR_SUCCESS; + } + } + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- + \fn lim_admit_control_delete_sta + \brief Delete all TSPEC for the specified STA + \param tpAniSirGlobal pMac + \param uint16_t assocId + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus lim_admit_control_delete_sta(tpAniSirGlobal pMac, uint16_t assocId) +{ + tpLimTspecInfo pTspecInfo = &pMac->lim.tspecInfo[0]; + int ctspec; + + for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) { + if (assocId == pTspecInfo->assocId) { + lim_tspec_delete(pMac, pTspecInfo); + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, + FL("Deleting TSPEC %d for assocId %d"), ctspec, + assocId); + } + } + lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("assocId %d done"), assocId); + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_admit_control_init + \brief init tspec table + \param tpAniSirGlobal pMac + \return eSirRetStatus - status + -------------------------------------------------------------*/ +tSirRetStatus lim_admit_control_init(tpAniSirGlobal pMac) +{ + cdf_mem_set(pMac->lim.tspecInfo, + LIM_NUM_TSPEC_MAX * sizeof(tLimTspecInfo), 0); + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_update_admit_policy + \brief Set the admit control policy based on CFG parameters + \param tpAniSirGlobal pMac + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus lim_update_admit_policy(tpAniSirGlobal pMac) +{ + uint32_t val; + if (wlan_cfg_get_int(pMac, WNI_CFG_ADMIT_POLICY, &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("Unable to get CFG_ADMIT_POLICY")); + return eSIR_FAILURE; + } + pMac->lim.admitPolicyInfo.type = (uint8_t) val; + if (wlan_cfg_get_int(pMac, WNI_CFG_ADMIT_BWFACTOR, &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("Unable to get CFG_ADMIT_BWFACTOR")); + return eSIR_FAILURE; + } + pMac->lim.admitPolicyInfo.bw_factor = (uint8_t) val; + + PELOG1(lim_log(pMac, LOG1, FL("LIM: AdmitPolicy %d, bw_factor %d"), + pMac->lim.admitPolicyInfo.type, + pMac->lim.admitPolicyInfo.bw_factor); + ) + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_send_hal_msg_add_ts + \brief Send halMsg_AddTs to HAL + \param tpAniSirGlobal pMac + \param uint16_t staIdx + \param uint8_t tspecIdx + \param tSirMacTspecIE tspecIE + \param tSirTclasInfo *tclasInfo + \param uint8_t tclasProc + \param uint16_t tsm_interval + \return eSirRetStatus - status + -------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_ESE +tSirRetStatus +lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, + tSirMacTspecIE tspecIE, + uint8_t sessionId, uint16_t tsm_interval) +#else +tSirRetStatus +lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, tSirMacTspecIE tspecIE, uint8_t sessionId) +#endif +{ + tSirMsgQ msg; + tpAddTsParams pAddTsParam; + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tpPESession psessionEntry = pe_find_session_by_session_id(pMac, sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGP, + FL("Unable to get Session for session Id %d"), + sessionId); + return eSIR_FAILURE; + } +#endif + pAddTsParam = cdf_mem_malloc(sizeof(tAddTsParams)); + if (NULL == pAddTsParam) { + PELOGW(lim_log(pMac, LOGW, FL("AllocateMemory() failed"));) + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) pAddTsParam, sizeof(tAddTsParams), 0); + pAddTsParam->staIdx = staIdx; + pAddTsParam->tspecIdx = tspecIdx; + cdf_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 = WMA_ADD_TS_REQ; + msg.bodyptr = pAddTsParam; + msg.bodyval = 0; + + /* We need to defer any incoming messages until we get a + * WMA_ADD_TS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(mac_trace_msg_tx(pMac, sessionId, msg.type)); + + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + lim_log(pMac, LOGW, FL("wma_post_ctrl_msg() failed")); + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + cdf_mem_free(pAddTsParam); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_send_hal_msg_del_ts + \brief Send halMsg_AddTs to HAL + \param tpAniSirGlobal pMac + \param uint16_t staIdx + \param uint8_t tspecIdx + \param tSirAddtsReqInfo addts + \return eSirRetStatus - status + -------------------------------------------------------------*/ + +tSirRetStatus +lim_send_hal_msg_del_ts(tpAniSirGlobal pMac, + uint16_t staIdx, + uint8_t tspecIdx, + tSirDeltsReqInfo delts, uint8_t sessionId, uint8_t *bssId) +{ + tSirMsgQ msg; + tpDelTsParams pDelTsParam; + tpPESession psessionEntry = NULL; + + pDelTsParam = cdf_mem_malloc(sizeof(tDelTsParams)); + if (NULL == pDelTsParam) { + lim_log(pMac, LOGP, FL("AllocateMemory() failed")); + return eSIR_MEM_ALLOC_FAILED; + } + + msg.type = WMA_DEL_TS_REQ; + msg.bodyptr = pDelTsParam; + msg.bodyval = 0; + cdf_mem_set((uint8_t *) pDelTsParam, sizeof(tDelTsParams), 0); + + /* filling message parameters. */ + pDelTsParam->staIdx = staIdx; + pDelTsParam->tspecIdx = tspecIdx; + cdf_mem_copy(&pDelTsParam->bssId, bssId, sizeof(tSirMacAddr)); + + psessionEntry = pe_find_session_by_session_id(pMac, sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log(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) { + cdf_mem_copy(&pDelTsParam->delTsInfo, &delts, + sizeof(tSirDeltsReqInfo)); + pDelTsParam->setRICparams = 1; + } +#endif + + lim_log(pMac, LOGW, FL("calling wma_post_ctrl_msg()")); + MTRACE(mac_trace_msg_tx(pMac, sessionId, msg.type)); + + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + lim_log(pMac, LOGW, FL("wma_post_ctrl_msg() failed")); + goto err; + } + return eSIR_SUCCESS; + +err: + cdf_mem_free(pDelTsParam); + return eSIR_FAILURE; +} + +/** ------------------------------------------------------------- + \fn lim_process_hal_add_ts_rsp + \brief This function process the WMA_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 lim_process_hal_add_ts_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpAddTsParams pAddTsRspMsg = NULL; + tpDphHashNode pSta = NULL; + uint16_t assocId = 0; + tSirMacAddr peerMacAddr; + uint8_t rspReqd = 1; + tpPESession psessionEntry = NULL; + + /* Need to process all the deferred messages enqueued + * since sending the WMA_ADD_TS_REQ. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + if (NULL == limMsg->bodyptr) { + lim_log(pMac, LOGP, FL("Received WMA_ADD_TS_RSP with NULL ")); + goto end; + } + + pAddTsRspMsg = (tpAddTsParams) (limMsg->bodyptr); + + /* 090803: Use pe_find_session_by_session_id() to obtain the PE session context */ + /* from the sessionId in the Rsp Msg from HAL */ + psessionEntry = pe_find_session_by_session_id(pMac, pAddTsRspMsg->sessionId); + + if (psessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("Session does Not exist with given sessionId :%d "), + pAddTsRspMsg->sessionId); + ) + lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, + psessionEntry, pAddTsRspMsg->tspec, + pMac->lim.gLimAddtsReq.sessionId, + pMac->lim.gLimAddtsReq.transactionId); + goto end; + } + + if (pAddTsRspMsg->status == CDF_STATUS_SUCCESS) { + PELOG1(lim_log + (pMac, LOG1, + FL("Received successful ADDTS response from HAL ")); + ) + /* Use the smesessionId and smetransactionId from the PE session context */ + lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_SUCCESS, + psessionEntry, pAddTsRspMsg->tspec, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + goto end; + } else { + PELOG1(lim_log + (pMac, LOG1, + FL("Received failure ADDTS response from HAL ")); + ) + /* Send DELTS action frame to AP */ + /* 090803: Get peer MAC addr from session */ + sir_copy_mac_addr(peerMacAddr, psessionEntry->bssId); + + /* 090803: Add the SME Session ID */ + lim_send_delts_req_action_frame(pMac, peerMacAddr, rspReqd, + &pAddTsRspMsg->tspec.tsinfo, + &pAddTsRspMsg->tspec, psessionEntry); + + /* Delete TSPEC */ + /* 090803: Pull the hash table from the session */ + pSta = dph_lookup_assoc_id(pMac, pAddTsRspMsg->staIdx, &assocId, + &psessionEntry->dph.dphHashTable); + if (pSta != NULL) + lim_admit_control_delete_ts(pMac, assocId, + &pAddTsRspMsg->tspec.tsinfo, + NULL, + (uint8_t *) &pAddTsRspMsg-> + tspecIdx); + + /* Send SME_ADDTS_RSP */ + /* 090803: Use the smesessionId and smetransactionId from the PE session context */ + lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, + psessionEntry, pAddTsRspMsg->tspec, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + goto end; + } + +end: + if (pAddTsRspMsg != NULL) + cdf_mem_free(pAddTsRspMsg); + return; +} diff --git a/core/mac/src/pe/lim/lim_aid_mgmt.c b/core/mac/src/pe/lim/lim_aid_mgmt.c new file mode 100644 index 000000000000..253543d86b02 --- /dev/null +++ b/core/mac/src/pe/lim/lim_aid_mgmt.c @@ -0,0 +1,194 @@ +/* + * 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 lim_aid_mgmt.c 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 "cds_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" +#include "sir_params.h" +#include "lim_utils.h" +#include "lim_timer_utils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_session_utils.h" + +#define LIM_START_PEER_IDX 1 + +/** + * lim_init_peer_idxpool() + * + ***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 lim_init_peer_idxpool(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + uint8_t i; + uint8_t 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; i < maxAssocSta; i++) { + pSessionEntry->gpLimPeerIdxpool[i] = i + 1; + } + pSessionEntry->gpLimPeerIdxpool[i] = 0; + + pSessionEntry->freePeerIdxTail = i; + +} + +/** + * lim_assign_peer_idx() + * + ***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 + */ + +uint16_t lim_assign_peer_idx(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + uint16_t 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 (pe_get_current_stas_count(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 */ +} + +/** + * lim_release_peer_idx() + * + ***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 +lim_release_peer_idx(tpAniSirGlobal pMac, uint16_t peerIdx, + tpPESession pSessionEntry) +{ + pSessionEntry->gLimNumOfCurrentSTAs--; + + /* insert at tail of free list */ + if (pSessionEntry->freePeerIdxTail) { + pSessionEntry->gpLimPeerIdxpool[pSessionEntry-> + freePeerIdxTail] = + (uint8_t) peerIdx; + pSessionEntry->freePeerIdxTail = (uint8_t) peerIdx; + } else { + pSessionEntry->freePeerIdxTail = + pSessionEntry->freePeerIdxHead = (uint8_t) peerIdx; + } + pSessionEntry->gpLimPeerIdxpool[(uint8_t) peerIdx] = 0; +} diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c new file mode 100644 index 000000000000..1d0dc07bfc65 --- /dev/null +++ b/core/mac/src/pe/lim/lim_api.c @@ -0,0 +1,2202 @@ +/* + * 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 lim_api.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 "cds_api.h" +#include "wni_cfg.h" +#include "wni_api.h" +#include "sir_common.h" +#include "sir_debug.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_api.h" +#include "lim_global.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_ibss_peer_mgmt.h" +#include "lim_admit_control.h" +#include "lim_send_sme_rsp_messages.h" +#include "wmm_apsd.h" +#include "lim_trace.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "wma_types.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +#include +#include "cdf_types.h" +#include "cds_packet.h" +#include "cds_utils.h" +#include "sys_startup.h" + +static void __lim_init_scan_vars(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; + + pMac->lim.gLimCurrentScanChannelId = 0; + pMac->lim.gpLimMlmScanReq = NULL; + pMac->lim.gDeferMsgTypeForNOA = 0; + pMac->lim.gpDefdSmeMsgForNOA = NULL; + + pMac->lim.gLimRestoreCBNumScanInterval = + LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT; + pMac->lim.gLimRestoreCBCount = 0; + cdf_mem_set(pMac->lim.gLimLegacyBssidList, + sizeof(pMac->lim.gLimLegacyBssidList), 0); + + /* Fill in default values */ + + /* abort scan is used to abort an on-going scan */ + pMac->lim.abortScan = 0; + cdf_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0); + cdf_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 __lim_init_bss_vars(tpAniSirGlobal pMac) +{ + cdf_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; +} + +static void __lim_init_stats_vars(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; + + cdf_mem_zero(pMac->lim.gLimHeartBeatApMac[0], + sizeof(tSirMacAddr)); + cdf_mem_zero(pMac->lim.gLimHeartBeatApMac[1], + sizeof(tSirMacAddr)); + pMac->lim.gLimHeartBeatApMacIndex = 0; + + /* Statistics to keep track of no. beacons rcvd in heart beat interval */ + cdf_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; + cdf_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 __lim_init_states(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(mac_trace + (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. + */ + + cdf_mem_set(&pMac->lim.gLimOverlap11gParams, sizeof(tLimProtStaParams), + 0); + cdf_mem_set(&pMac->lim.gLimOverlap11aParams, sizeof(tLimProtStaParams), + 0); + cdf_mem_set(&pMac->lim.gLimOverlapHt20Params, sizeof(tLimProtStaParams), + 0); + cdf_mem_set(&pMac->lim.gLimOverlapNonGfParams, + sizeof(tLimProtStaParams), 0); + cdf_mem_set(&pMac->lim.gLimNoShortParams, sizeof(tLimNoShortParams), 0); + cdf_mem_set(&pMac->lim.gLimNoShortSlotParams, + sizeof(tLimNoShortSlotParams), 0); + + pMac->lim.gLimPhyMode = 0; + pMac->lim.scanStartTime = 0; /* used to measure scan time */ + + cdf_mem_set(pMac->lim.gLimMyMacAddr, sizeof(pMac->lim.gLimMyMacAddr), + 0); + pMac->lim.ackPolicy = 0; + + pMac->lim.gLimProbeRespDisableFlag = 0; /* control over probe resp */ +} + +static void __lim_init_vars(tpAniSirGlobal pMac) +{ + /* Place holder for Measurement Req/Rsp/Ind related info */ + + + /* Deferred Queue Paramters */ + cdf_mem_set(&pMac->lim.gLimDeferredMsgQ, sizeof(tSirAddtsReq), 0); + + /* addts request if any - only one can be outstanding at any time */ + cdf_mem_set(&pMac->lim.gLimAddtsReq, sizeof(tSirAddtsReq), 0); + pMac->lim.gLimAddtsSent = 0; + pMac->lim.gLimAddtsRspTimerCount = 0; + + /* protection related config cache */ + cdf_mem_set(&pMac->lim.cfgProtection, sizeof(tCfgProtection), 0); + pMac->lim.gLimProtectionControl = 0; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + /* WMM Related Flag */ + pMac->lim.gUapsdEnable = 0; + pMac->lim.gUapsdPerAcBitmask = 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; + + cdf_mem_set(&pMac->lim.tspecInfo, + sizeof(tLimTspecInfo) * LIM_NUM_TSPEC_MAX, 0); + + /* admission control policy information */ + cdf_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; +} + +static void __lim_init_assoc_vars(tpAniSirGlobal pMac) +{ + uint32_t val; + if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) + != eSIR_SUCCESS) + lim_log(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; + cdf_mem_set(&pMac->lim.gLimPreAuthPeerAddr, sizeof(tSirMacAddr), 0); + pMac->lim.gLimNumPreAuthContexts = 0; + cdf_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. */ + cdf_mem_set(pMac->lim.protStaOverlapCache, + sizeof(tCacheParams) * LIM_PROT_STA_OVERLAP_CACHE_SIZE, 0); + cdf_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 __lim_init_ht_vars(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; +} + +static tSirRetStatus __lim_init_config(tpAniSirGlobal pMac) +{ + uint32_t val1, val2, val3; + uint16_t val16; + uint8_t val8; + tSirMacHTCapabilityInfo *pHTCapabilityInfo; + tSirMacHTInfoField1 *pHTInfoField1; + tSirMacHTParametersInfo *pAmpduParamInfo; + + /* Read all the CFGs here that were updated before pe_start 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_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + return eSIR_FAILURE; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_CHANNEL_BONDING_MODE, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve Channel Bonding CFG")); + ) + return eSIR_FAILURE; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + + /* channel bonding mode could be set to anything from 0 to 4(Titan had these */ + /* modes But for Taurus we have only two modes: enable(>0) or disable(=0) */ + pHTCapabilityInfo->supportedChannelWidthSet = val2 ? + WNI_CFG_CHANNEL_BONDING_MODE_ENABLE : + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, *(uint16_t *) pHTCapabilityInfo) + != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("could not update HT Cap Info CFG")); + ) + return eSIR_FAILURE; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD1, &val1) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT INFO Field1 CFG")); + ) + return eSIR_FAILURE; + } + + val8 = (uint8_t) val1; + pHTInfoField1 = (tSirMacHTInfoField1 *) &val8; + pHTInfoField1->recommendedTxWidthSet = + (uint8_t) pHTCapabilityInfo->supportedChannelWidthSet; + if (cfg_set_int(pMac, WNI_CFG_HT_INFO_FIELD1, *(uint8_t *) pHTInfoField1) + != eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("could not update HT Info Field"));) + return eSIR_FAILURE; + } + + /* WNI_CFG_HEART_BEAT_THRESHOLD */ + + if (wlan_cfg_get_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG")); + ) + return eSIR_FAILURE; + } + if (!val1) { + 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_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) + return eSIR_FAILURE; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG")); + ) + return eSIR_FAILURE; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val3) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG")); + ) + return eSIR_FAILURE; + } + + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->shortGI20MHz = (uint16_t) val2; + pHTCapabilityInfo->shortGI40MHz = (uint16_t) val3; + + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("could not update HT Cap Info CFG")); + ) + return eSIR_FAILURE; + } + + /* WNI_CFG_MAX_RX_AMPDU_FACTOR */ + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT AMPDU Param CFG")); + ) + return eSIR_FAILURE; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("could not retrieve AMPDU Factor CFG")); + ) + return eSIR_FAILURE; + } + val16 = (uint16_t) val1; + pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16; + pAmpduParamInfo->maxRxAMPDUFactor = (uint8_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_AMPDU_PARAMS, + *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("cfg get short preamble failed")); + return eSIR_FAILURE; + } + + /* WNI_CFG_SHORT_PREAMBLE - this one is not updated in + lim_handle_cf_gparam_update do we want to update this? */ + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val1) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("cfg get short preamble failed")); + return eSIR_FAILURE; + } + + /* 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 */ + handle_ht_capabilityand_ht_info(pMac, NULL); + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, + (uint32_t *) &pMac->lim.disableLDPCWithTxbfAP)) { + lim_log(pMac, LOGP, FL("cfg get disableLDPCWithTxbfAP failed")); + return eSIR_FAILURE; + } +#ifdef FEATURE_WLAN_TDLS + if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_TDLS_BUF_STA_ENABLED, + (uint32_t *) &pMac->lim. + gLimTDLSBufStaEnabled)) { + lim_log(pMac, LOGP, FL("cfg get LimTDLSBufStaEnabled failed")); + return eSIR_FAILURE; + } + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, + (uint32_t *) &pMac->lim.gLimTDLSUapsdMask)) { + lim_log(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); + return eSIR_FAILURE; + } + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, + (uint32_t *) &pMac->lim. + gLimTDLSOffChannelEnabled)) { + lim_log(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); + return eSIR_FAILURE; + } + + if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_TDLS_WMM_MODE_ENABLED, + (uint32_t *) &pMac->lim. + gLimTDLSWmmMode)) { + lim_log(pMac, LOGP, FL("cfg get LimTDLSWmmMode failed")); + return eSIR_FAILURE; + } +#endif + return eSIR_SUCCESS; +} + +/* + lim_start + This function is to replace the __lim_process_sme_start_req since there is no + eWNI_SME_START_REQ post to PE. + */ +tSirRetStatus lim_start(tpAniSirGlobal pMac) +{ + tSirResultCodes retCode = eSIR_SUCCESS; + + PELOG1(lim_log(pMac, LOG1, FL(" enter"));) + + if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) { + pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE; + + MTRACE(mac_trace + (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 */ + lim_init_mlm(pMac); + + /* By default return unique scan results */ + pMac->lim.gLimReturnUniqueResults = true; + } else { + /** + * Should not have received eWNI_SME_START_REQ in states + * other than OFFLINE. Return response to host and + * log error + */ + lim_log(pMac, LOGE, FL("Invalid SME state %X"), + pMac->lim.gLimSmeState); + retCode = eSIR_FAILURE; + } + + return retCode; +} + +/** + * lim_initialize() + * + ***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 lim_initialize(tpAniSirGlobal pMac) +{ + tSirRetStatus status = eSIR_SUCCESS; + + __lim_init_assoc_vars(pMac); + __lim_init_vars(pMac); + __lim_init_states(pMac); + __lim_init_stats_vars(pMac); + __lim_init_bss_vars(pMac); + __lim_init_scan_vars(pMac); + __lim_init_ht_vars(pMac); + + status = lim_start(pMac); + if (eSIR_SUCCESS != status) { + return status; + } + /* Initializations for maintaining peers in IBSS */ + lim_ibss_init(pMac); + +#if defined WLAN_FEATURE_VOWIFI + rrm_initialize(pMac); +#endif + + cdf_mutex_init(&pMac->lim.lim_frame_register_lock); + cdf_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue, 0); + + /* Initialize the configurations needed by PE */ + if (eSIR_FAILURE == __lim_init_config(pMac)) { + /* We need to undo everything in lim_start */ + lim_cleanup_mlm(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 */ + lim_admit_control_init(pMac); + lim_register_hal_ind_call_back(pMac); + + return status; + +} /*** end lim_initialize() ***/ + +/** + * lim_cleanup() + * + ***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 lim_cleanup(tpAniSirGlobal pMac) +{ + void *p_cds_gctx; + CDF_STATUS retStatus; + + /*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 + */ + + struct mgmt_frm_reg_info *pLimMgmtRegistration = NULL; + + if (CDF_FTM_MODE != cds_get_conparam()) { + cdf_mutex_acquire(&pMac->lim.lim_frame_register_lock); + while (cdf_list_remove_front( + &pMac->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t **) &pLimMgmtRegistration) == + CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Fixing leak! Deallocating pLimMgmtRegistration node")); + cdf_mem_free(pLimMgmtRegistration); + } + cdf_mutex_release(&pMac->lim.lim_frame_register_lock); + cdf_list_destroy(&pMac->lim.gLimMgmtFrameRegistratinQueue); + } + + lim_cleanup_mlm(pMac); + lim_cleanup_lmm(pMac); + + /* free up preAuth table */ + if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL) { + cdf_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable); + pMac->lim.gLimPreAuthTimerTable.pTable = NULL; + pMac->lim.gLimPreAuthTimerTable.numEntry = 0; + } + + if (NULL != pMac->lim.pDialogueTokenHead) { + lim_delete_dialogue_token_list(pMac); + } + + if (NULL != pMac->lim.pDialogueTokenTail) { + cdf_mem_free(pMac->lim.pDialogueTokenTail); + pMac->lim.pDialogueTokenTail = NULL; + } + + if (pMac->lim.gpLimMlmSetKeysReq != NULL) { + cdf_mem_free(pMac->lim.gpLimMlmSetKeysReq); + pMac->lim.gpLimMlmSetKeysReq = NULL; + } + + if (pMac->lim.gpLimMlmAuthReq != NULL) { + cdf_mem_free(pMac->lim.gpLimMlmAuthReq); + pMac->lim.gpLimMlmAuthReq = NULL; + } + + if (pMac->lim.gpDefdSmeMsgForNOA != NULL) { + cdf_mem_free(pMac->lim.gpDefdSmeMsgForNOA); + pMac->lim.gpDefdSmeMsgForNOA = NULL; + } + + if (pMac->lim.gpLimMlmScanReq != NULL) { + cdf_mem_free(pMac->lim.gpLimMlmScanReq); + pMac->lim.gpLimMlmScanReq = NULL; + } + /* Now, finally reset the deferred message queue pointers */ + lim_reset_deferred_msg_q(pMac); + + p_cds_gctx = cds_get_global_context(); + retStatus = wma_de_register_mgmt_frm_client(p_cds_gctx); + + if (retStatus != CDF_STATUS_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL + ("DeRegistering the PE Handle with wma has failed bailing out...")); + ) +#if defined WLAN_FEATURE_VOWIFI + rrm_cleanup(pMac); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + lim_ft_cleanup_all_ft_sessions(pMac); +#endif + +} /*** end lim_cleanup() ***/ + +/** ------------------------------------------------------------- + \fn pe_open + \brief will be called in Open sequence from mac_open + \param tpAniSirGlobal pMac + \param tHalOpenParameters *pHalOpenParam + \return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus pe_open(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(lim_log(pMac, LOGE, + FL("max number of Bssid or Stations cannot be zero!"));) + return eSIR_FAILURE; + } + + pMac->lim.limTimers.gpLimCnfWaitTimer = + cdf_mem_malloc(sizeof(TX_TIMER) * (pMac->lim.maxStation + 1)); + if (NULL == pMac->lim.limTimers.gpLimCnfWaitTimer) { + PELOGE(lim_log(pMac, LOGE, + FL("gpLimCnfWaitTimer memory allocate failed!"));) + return eSIR_MEM_ALLOC_FAILED; + } + + pMac->lim.gpSession = + cdf_mem_malloc(sizeof(tPESession) * pMac->lim.maxBssId); + if (NULL == pMac->lim.gpSession) { + lim_log(pMac, LOGE, + FL("gpSession memory allocate failed!")); + status = eSIR_MEM_ALLOC_FAILED; + goto pe_open_psession_fail; + } + + cdf_mem_set(pMac->lim.gpSession, + sizeof(tPESession) * pMac->lim.maxBssId, 0); + + pMac->lim.mgmtFrameSessionId = 0xff; + pMac->lim.deferredMsgCnt = 0; + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init(&pMac->lim.lkPeGlobalLock))) { + PELOGE(lim_log(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.ibss_retry_cnt = 0; + + /* + * pe_open 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(lim_trace_init(pMac)); +#endif + return status; /* status here will be eSIR_SUCCESS */ + +pe_open_lock_fail: + cdf_mem_free(pMac->lim.gpSession); + pMac->lim.gpSession = NULL; +pe_open_psession_fail: + cdf_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); + pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; + + return status; +} + +/** ------------------------------------------------------------- + \fn pe_close + \brief will be called in close sequence from mac_close + \param tpAniSirGlobal pMac + \return tSirRetStatus + -------------------------------------------------------------*/ + +tSirRetStatus pe_close(tpAniSirGlobal pMac) +{ + uint8_t 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) { + pe_delete_session(pMac, &pMac->lim.gpSession[i]); + } + } + cdf_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); + pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; + + if (pMac->lim.gpLimMlmOemDataReq) { + cdf_mem_free(pMac->lim.gpLimMlmOemDataReq); + pMac->lim.gpLimMlmOemDataReq = NULL; + } + + cdf_mem_free(pMac->lim.gpSession); + pMac->lim.gpSession = NULL; + if (!CDF_IS_STATUS_SUCCESS + (cdf_mutex_destroy(&pMac->lim.lkPeGlobalLock))) { + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn pe_start + \brief will be called in start sequence from mac_start + \param tpAniSirGlobal pMac + \return none + -------------------------------------------------------------*/ + +tSirRetStatus pe_start(tpAniSirGlobal pMac) +{ + tSirRetStatus status = eSIR_SUCCESS; + + status = lim_initialize(pMac); + return status; +} + +/** ------------------------------------------------------------- + \fn pe_stop + \brief will be called in stop sequence from mac_stop + \param tpAniSirGlobal pMac + \return none + -------------------------------------------------------------*/ + +void pe_stop(tpAniSirGlobal pMac) +{ + lim_cleanup(pMac); + SET_LIM_MLM_STATE(pMac, eLIM_MLM_OFFLINE_STATE); + return; +} + +/** ------------------------------------------------------------- + \fn pe_free_msg + \brief Called by CDS scheduler (function cds_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 + -----------------------------------------------------------------*/ +void pe_free_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + if (pMsg != NULL) { + if (NULL != pMsg->bodyptr) { + if (SIR_BB_XPORT_MGMT_MSG == pMsg->type) { + cds_pkt_return_packet((cds_pkt_t *) pMsg-> + bodyptr); + } else { + cdf_mem_free((void *)pMsg->bodyptr); + } + } + pMsg->bodyptr = 0; + pMsg->bodyval = 0; + pMsg->type = 0; + } + return; +} + +/** + * lim_post_msg_api() + * + ***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 + */ + +uint32_t lim_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + return cds_mq_post_message(CDS_MQ_ID_PE, (cds_msg_t *) pMsg); + +} /*** end lim_post_msg_api() ***/ + +/*-------------------------------------------------------------------------- + + \brief pe_post_msg_api() - A wrapper function to post message to Voss msg queues + + This function can be called by legacy code to post message to cds queues OR + legacy code may keep on invoking 'lim_post_msg_api' to post the message to cds queue + for dispatching it later. + + \param pMac - Pointer to Global MAC structure + \param pMsg - Pointer to the message structure + + \return uint32_t - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ + +tSirRetStatus pe_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + return (tSirRetStatus) lim_post_msg_api(pMac, pMsg); +} + +/*-------------------------------------------------------------------------- + + \brief pe_process_messages() - 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 uint32_t - TX_SUCCESS for success. + + --------------------------------------------------------------------------*/ + +tSirRetStatus pe_process_messages(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)) + cfg_process_mb_msg(pMac, (tSirMbMsg *) pMsg->bodyptr); + else + lim_message_processor(pMac, pMsg); + return eSIR_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ +/** + * pe_handle_mgmt_frame + * + * FUNCTION: + * Process the Management frames from TL + * + * LOGIC: + * + * ASSUMPTIONS: TL sends the packet along with the CDS GlobalContext + * + * NOTE: + * + * @param p_cds_gctx Global Vos Context + * @param cds_buff Packet + * @return None + */ + +CDF_STATUS pe_handle_mgmt_frame(void *p_cds_gctx, void *cds_buff) +{ + tpAniSirGlobal pMac; + tpSirMacMgmtHdr mHdr; + tSirMsgQ msg; + cds_pkt_t *pVosPkt; + CDF_STATUS cdf_status; + uint8_t *pRxPacketInfo; + + pVosPkt = (cds_pkt_t *) cds_buff; + if (NULL == pVosPkt) { + return CDF_STATUS_E_FAILURE; + } + + pMac = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == pMac) { + /* cannot log a failure without a valid pMac */ + cds_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + return CDF_STATUS_E_FAILURE; + } + + cdf_status = + wma_ds_peek_rx_packet_info(pVosPkt, (void *)&pRxPacketInfo, false); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cds_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + return CDF_STATUS_E_FAILURE; + } + + /* + * The MPDU header is now present at a certain "offset" in + * the BD and is specified in the BD itself + */ + + mHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + if (mHdr->fc.type == SIR_MAC_MGMT_FRAME) { + lim_log(pMac, LOG1, FL + ("RxBd=%p mHdr=%p Type: %d Subtype: %d Sizes:FC%zu Mgmt%zu"), + pRxPacketInfo, mHdr, mHdr->fc.type, mHdr->fc.subType, + sizeof(tSirMacFrameCtl), sizeof(tSirMacMgmtHdr)); + + lim_log(pMac, LOG1, FL("mpdu_len:%d hdr_len:%d data_len:%d"), + WMA_GET_RX_MPDU_LEN(pRxPacketInfo), + WMA_GET_RX_MPDU_HEADER_LEN(pRxPacketInfo), + WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)); + + MTRACE(mac_trace(pMac, TRACE_CODE_RX_MGMT, + WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo), + LIM_TRACE_MAKE_RXMGMT(mHdr->fc.subType, + (uint16_t) (((uint16_t) + (mHdr->seqControl.seqNumHi << 4)) | + mHdr->seqControl.seqNumLo)));) + + if (WMA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + lim_log(pMac, LOG1, FL("roamCandidateInd %d"), + WMA_GET_ROAMCANDIDATEIND(pRxPacketInfo)); + + if (WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + lim_log(pMac, LOG1, FL("offloadScanLearn %d"), + WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo)); + } + + /* Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG */ + msg.type = SIR_BB_XPORT_MGMT_MSG; + msg.bodyptr = cds_buff; + msg.bodyval = 0; + + if (eSIR_SUCCESS != sys_bbt_process_message_core(pMac, + &msg, + mHdr->fc.type, + mHdr->fc.subType)) { + cds_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + lim_log(pMac, LOGW, + FL + ("sys_bbt_process_message_core failed to process SIR_BB_XPORT_MGMT_MSG")); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * pe_register_wma_handle() - register management frame handler to WMA + * @pMac: mac global ctx + * + * Return: None + */ +void pe_register_wma_handle(tpAniSirGlobal pMac) +{ + void *p_cds_gctx; + CDF_STATUS retStatus; + + p_cds_gctx = cds_get_global_context(); + + retStatus = wma_register_mgmt_frm_client(p_cds_gctx, + pe_handle_mgmt_frame); + if (retStatus != CDF_STATUS_SUCCESS) + lim_log(pMac, LOGP, + FL("Registering the PE Handle with WMA has failed")); + +} + +/** + * lim_is_system_in_scan_state() + * + ***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 + */ + +uint8_t lim_is_system_in_scan_state(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 lim_is_system_in_scan_state() ***/ + +#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 = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + session_entry = pe_find_session_by_bssid(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 = dph_lookup_hash_entry(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 && + ((cdf_mc_timer_get_system_ticks() - + sta_ds->last_assoc_received_time) < 1000)) + return true; + + sta_ds->last_assoc_received_time = cdf_mc_timer_get_system_ticks(); + 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 = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + session_entry = pe_find_session_by_bssid(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 = dph_lookup_hash_entry(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 ((WMA_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 ((cdf_mc_timer_get_system_ticks() - + sta_ds->last_unprot_deauth_disassoc) < 1000) + return true; + + sta_ds->last_unprot_deauth_disassoc = + cdf_mc_timer_get_system_ticks(); + } 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->is_disassoc_deauth_in_progress) + return true; + else + sta_ds->is_disassoc_deauth_in_progress++; + } + + return false; +} + +/** + *\brief lim_received_hb_handler() + * + * This function is called by sch_beacon_process() 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 +lim_received_hb_handler(tpAniSirGlobal pMac, uint8_t channelId, + tpPESession psessionEntry) +{ + if ((channelId == 0) + || (channelId == psessionEntry->currentOperChannel)) + psessionEntry->LimRxedBeaconCntDuringHB++; + + psessionEntry->pmmOffloadInfo.bcnmiss = false; +} /*** lim_init_wds_info_params() ***/ + +/** ------------------------------------------------------------- + \fn lim_update_overlap_sta_param + \brief Updates overlap cache and param data structure + \param tpAniSirGlobal pMac + \param tSirMacAddr bssId + \param tpLimProtStaParams pStaParams + \return None + -------------------------------------------------------------*/ +void +lim_update_overlap_sta_param(tpAniSirGlobal pMac, tSirMacAddr bssId, + tpLimProtStaParams pStaParams) +{ + int i; + if (!pStaParams->numSta) { + cdf_mem_copy(pMac->lim.protStaOverlapCache[0].addr, + bssId, sizeof(tSirMacAddr)); + pMac->lim.protStaOverlapCache[0].active = true; + + pStaParams->numSta = 1; + + return; + } + + for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) { + if (pMac->lim.protStaOverlapCache[i].active) { + if (cdf_mem_compare + (pMac->lim.protStaOverlapCache[i].addr, bssId, + sizeof(tSirMacAddr))) { + return; + } + } else + break; + } + + if (i == LIM_PROT_STA_OVERLAP_CACHE_SIZE) { + PELOG1(lim_log(pMac, LOGW, FL("Overlap cache is full"));) + } else { + cdf_mem_copy(pMac->lim.protStaOverlapCache[i].addr, + bssId, sizeof(tSirMacAddr)); + pMac->lim.protStaOverlapCache[i].active = true; + + pStaParams->numSta++; + } +} + +/** + * lim_ibss_enc_type_matched + * + ***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 lim_ibss_enc_type_matched(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; +} + +/** + * lim_handle_ibs_scoalescing() + * + ***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 +lim_handle_ibss_coalescing(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon, + uint8_t *pRxPacketInfo, tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tSirRetStatus retCode; + + pHdr = WMA_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) || + (lim_cmp_s_sid(pMac, &pBeacon->ssId, psessionEntry) != true) || + (psessionEntry->currentOperChannel != pBeacon->channelNumber)) + retCode = eSIR_LIM_IGNORE_BEACON; + else if (lim_ibss_enc_type_matched(pBeacon, psessionEntry) != eSIR_TRUE) { + PELOG3(lim_log(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 { + uint32_t ieLen; + uint16_t tsfLater; + uint8_t *pIEs; + ieLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + tsfLater = WMA_GET_RX_TSF_LATER(pRxPacketInfo); + pIEs = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + PELOG3(lim_log + (pMac, LOG3, FL("BEFORE Coalescing tsfLater val :%d"), + tsfLater); + ) + retCode = + lim_ibss_coalesce(pMac, pHdr, pBeacon, pIEs, ieLen, tsfLater, + psessionEntry); + } + return retCode; +} /*** end lim_handle_ibs_scoalescing() ***/ + +/** + * 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; + + lim_log(mac_ctx, LOG1, + FL("Beacon/Probe:: Privacy :%d WPA Present:%d RSN Present: %d"), + bcn->capabilityInfo.privacy, bcn->wpaPresent, bcn->rsnPresent); + lim_log(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)) { + lim_log(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; +} + +/** + * lim_detect_change_in_ap_capabilities() + * + ***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 +lim_detect_change_in_ap_capabilities(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeacon, + tpPESession psessionEntry) +{ + uint8_t len; + tSirSmeApNewCaps apNewCaps; + uint8_t newChannel; + tSirRetStatus status = eSIR_SUCCESS; + bool security_caps_matched = true; + + apNewCaps.capabilityInfo = + lim_get_u16((uint8_t *) &pBeacon->capabilityInfo); + newChannel = (uint8_t) pBeacon->channelNumber; + + security_caps_matched = lim_enc_type_matched(pMac, pBeacon, + psessionEntry); + if ((false == psessionEntry->limSentCapsChangeNtf) && + (((!lim_is_null_ssid(&pBeacon->ssId)) && + (false == lim_cmp_s_sid(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)) || + (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) { + lim_log(pMac, LOGW, + FL + ("Ignoring the Capability change as it is false alarm")); + return; + } + psessionEntry->fWaitForProbeRsp = true; + lim_log(pMac, LOGW, + FL("AP capabilities are not matching," + "sending directed probe request.. ")); + status = + lim_send_probe_req_mgmt_frame(pMac, &psessionEntry->ssId, + psessionEntry->bssId, + psessionEntry-> + currentOperChannel, + psessionEntry->selfMacAddr, + psessionEntry->dot11mode, + 0, NULL); + + if (eSIR_SUCCESS != status) { + lim_log(pMac, LOGE, FL("send ProbeReq failed")); + psessionEntry->fWaitForProbeRsp = false; + } + return; + } + /** + * BSS capabilities have changed. + * Inform Roaming. + */ + len = sizeof(tSirMacCapabilityInfo) + sizeof(tSirMacAddr) + sizeof(uint8_t) + 3 * sizeof(uint8_t) + /* reserved fields */ + pBeacon->ssId.length + 1; + + cdf_mem_copy(apNewCaps.bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + if (newChannel != psessionEntry->currentOperChannel) { + PELOGE(lim_log + (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(lim_log + (pMac, LOGE, + FL("BSS Caps (Privacy) bit 0 in beacon," + " but WPA or RSN IE present, Ignore Beacon!")); + ) + return; + } else + apNewCaps.channelId = psessionEntry->currentOperChannel; + cdf_mem_copy((uint8_t *) &apNewCaps.ssId, + (uint8_t *) &pBeacon->ssId, + pBeacon->ssId.length + 1); + + psessionEntry->fIgnoreCapsChange = false; + psessionEntry->fWaitForProbeRsp = false; + psessionEntry->limSentCapsChangeNtf = true; + lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_AP_CAPS_CHANGED, + (uint32_t *) &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*/ + + lim_log(pMac, LOG1, FL("capabilities in probe response are" + "matching with the current setting," + "Ignoring subsequent capability" + "mismatch")); + psessionEntry->fIgnoreCapsChange = true; + psessionEntry->fWaitForProbeRsp = false; + } + +} /*** lim_detect_change_in_ap_capabilities() ***/ + +/* --------------------------------------------------------------------- */ +/** + * lim_update_short_slot + * + * FUNCTION: + * Enable/Disable short slot + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param enable Flag to enable/disable short slot + * @return None + */ + +tSirRetStatus lim_update_short_slot(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeacon, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + + tSirSmeApNewCaps apNewCaps; + uint32_t nShortSlot; + uint32_t val = 0; + uint32_t phyMode; + + /* Check Admin mode first. If it is disabled just return */ + if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) + != eSIR_SUCCESS) { + lim_log(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 */ + lim_get_phy_mode(pMac, &phyMode, psessionEntry); + if ((phyMode == WNI_CFG_PHY_MODE_11A) + || (phyMode == WNI_CFG_PHY_MODE_11B)) + return eSIR_SUCCESS; + + apNewCaps.capabilityInfo = + lim_get_u16((uint8_t *) &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(lim_log + (pMac, LOG1, + FL("Shortslot capability of AP changed: %d"), + nShortSlot); + ) + ((tpSirMacCapabilityInfo) & psessionEntry-> + limCurrentBssCaps)->shortSlotTime = (uint16_t) nShortSlot; + psessionEntry->shortSlotTimeSupported = nShortSlot; + pBeaconParams->fShortSlotTime = (uint8_t) nShortSlot; + pBeaconParams->paramChangeBitmap |= + PARAM_SHORT_SLOT_TIME_CHANGED; + } + return eSIR_SUCCESS; +} + + +void lim_send_heart_beat_timeout_ind(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t statusCode; + tSirMsgQ msg; + + /* Prepare and post message to LIM Message Queue */ + msg.type = (uint16_t) SIR_LIM_HEART_BEAT_TIMEOUT; + msg.bodyptr = psessionEntry; + msg.bodyval = 0; + lim_log(pMac, LOGE, FL("Heartbeat failure from Fw")); + + statusCode = lim_post_msg_api(pMac, &msg); + + if (statusCode != eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("posting message %X to LIM failed, reason=%d"), + msg.type, statusCode); + } +} + +/** + * lim_ps_offload_handle_missed_beacon_ind(): handles missed beacon indication + * @pMac : global mac context + * @pMsg: message + * + * This function process the SIR_HAL_MISSED_BEACON_IND + * message from HAL, to do active AP probing. + * + * Return: void + */ +void lim_ps_offload_handle_missed_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpSirSmeMissedBeaconInd pSirMissedBeaconInd = + (tpSirSmeMissedBeaconInd) pMsg->bodyptr; + tpPESession psessionEntry = + pe_find_session_by_bss_idx(pMac, pSirMissedBeaconInd->bssIdx); + + if (!psessionEntry) { + lim_log(pMac, LOGE, + FL("session does not exist for given BSSId")); + return; + } + + /* Set Beacon Miss in Powersave Offload */ + psessionEntry->pmmOffloadInfo.bcnmiss = true; + PELOGE(lim_log(pMac, LOGE, + FL("Received Heart Beat Failure"));) + + /* Do AP probing immediately */ + lim_send_heart_beat_timeout_ind(pMac, psessionEntry); + return; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac, + roam_offload_synch_ind *roam_offload_synch_ind_ptr) +{ + uint32_t ie_len = 0; + tpSirProbeRespBeacon parsed_frm_ptr; + tpSirMacMgmtHdr mac_hdr; + uint8_t *bcn_proberesp_ptr; + tSirBssDescription *bss_desc_ptr = NULL; + + bcn_proberesp_ptr = (uint8_t *)roam_offload_synch_ind_ptr + + roam_offload_synch_ind_ptr->beaconProbeRespOffset; + mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr; + parsed_frm_ptr = + (tpSirProbeRespBeacon) cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == parsed_frm_ptr) { + lim_log(pMac, LOGE, "fail to allocate memory for frame"); + return CDF_STATUS_E_NOMEM; + } + + if (roam_offload_synch_ind_ptr->beaconProbeRespLength <= + SIR_MAC_HDR_LEN_3A) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, "%s: very" + "few bytes in synchInd beacon / probe resp frame! length=%d", + __func__, roam_offload_synch_ind_ptr->beaconProbeRespLength); + cdf_mem_free(parsed_frm_ptr); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + "LFR3: Beacon/Prb Rsp:"); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + bcn_proberesp_ptr, roam_offload_synch_ind_ptr->beaconProbeRespLength); + if (roam_offload_synch_ind_ptr->isBeacon) { + if (sir_parse_beacon_ie(pMac, parsed_frm_ptr, + &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + + SIR_MAC_B_PR_SSID_OFFSET], + roam_offload_synch_ind_ptr->beaconProbeRespLength - + SIR_MAC_HDR_LEN_3A) != eSIR_SUCCESS || + !parsed_frm_ptr->ssidPresent) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "Parse error Beacon, length=%d", + roam_offload_synch_ind_ptr->beaconProbeRespLength); + cdf_mem_free(parsed_frm_ptr); + return CDF_STATUS_E_FAILURE; + } + } else { + if (sir_convert_probe_frame2_struct(pMac, + &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A], + roam_offload_synch_ind_ptr->beaconProbeRespLength - + SIR_MAC_HDR_LEN_3A, parsed_frm_ptr) != eSIR_SUCCESS || + !parsed_frm_ptr->ssidPresent) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "Parse error ProbeResponse, length=%d", + roam_offload_synch_ind_ptr->beaconProbeRespLength); + cdf_mem_free(parsed_frm_ptr); + return CDF_STATUS_E_FAILURE; + } + } + /* 24 byte MAC header and 12 byte to ssid IE */ + if (roam_offload_synch_ind_ptr->beaconProbeRespLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) { + ie_len = roam_offload_synch_ind_ptr->beaconProbeRespLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } + /* + * Memory allocated below is freed up in csrProcessRoamOffloadSynchInd + */ + roam_offload_synch_ind_ptr->bss_desc_ptr = + cdf_mem_malloc(sizeof (tSirBssDescription) + ie_len); + bss_desc_ptr = roam_offload_synch_ind_ptr->bss_desc_ptr; + if (NULL == bss_desc_ptr) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3:Failed to allocate memory"); + CDF_ASSERT(bss_desc_ptr != NULL); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(bss_desc_ptr, 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 + */ + bss_desc_ptr->length = (uint16_t) (offsetof(tSirBssDescription, + ieFields[0]) - + sizeof(bss_desc_ptr->length) + ie_len); + + if (parsed_frm_ptr->dsParamsPresent) { + bss_desc_ptr->channelId = parsed_frm_ptr->channelNumber; + } else if (parsed_frm_ptr->HTInfo.present) { + bss_desc_ptr->channelId = parsed_frm_ptr->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.*/ + bss_desc_ptr->channelId = + cds_freq_to_chan(roam_offload_synch_ind_ptr->chan_freq); + } + bss_desc_ptr->channelIdSelf = bss_desc_ptr->channelId; + + if ((bss_desc_ptr->channelId > 0) && (bss_desc_ptr->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 < parsed_frm_ptr->supportedRates.numRates; i++) { + if (sirIsArate(parsed_frm_ptr->supportedRates.rate[i] & + 0x7f)) { + bss_desc_ptr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (parsed_frm_ptr->extendedRatesPresent) { + bss_desc_ptr->nwType = eSIR_11G_NW_TYPE; + } + } else { + /* 11a packet */ + bss_desc_ptr->nwType = eSIR_11A_NW_TYPE; + } + + bss_desc_ptr->sinr = 0; + bss_desc_ptr->beaconInterval = parsed_frm_ptr->beaconInterval; + bss_desc_ptr->timeStamp[0] = parsed_frm_ptr->timeStamp[0]; + bss_desc_ptr->timeStamp[1] = parsed_frm_ptr->timeStamp[1]; + cdf_mem_copy(&bss_desc_ptr->capabilityInfo, + &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2); + cdf_mem_copy((uint8_t *) &bss_desc_ptr->bssId, + (uint8_t *) mac_hdr->bssId, + sizeof(tSirMacAddr)); + bss_desc_ptr->nReceivedTime = + (uint32_t)cdf_mc_timer_get_system_ticks(); + if (parsed_frm_ptr->mdiePresent) { + bss_desc_ptr->mdiePresent = parsed_frm_ptr->mdiePresent; + cdf_mem_copy((uint8_t *)bss_desc_ptr->mdie, + (uint8_t *)parsed_frm_ptr->mdie, + SIR_MDIE_SIZE); + } + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:%s:BssDescr Info:", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + bss_desc_ptr->bssId, sizeof(tSirMacAddr)); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "chan=%d, rssi=%d", bss_desc_ptr->channelId, + bss_desc_ptr->rssi); + if (ie_len) { + cdf_mem_copy(&bss_desc_ptr->ieFields, + bcn_proberesp_ptr + + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), + ie_len); + } + cdf_mem_free(parsed_frm_ptr); + return CDF_STATUS_SUCCESS; +} + +/**----------------------------------------------------------------- + * brief lim_roam_offload_synch_ind() - Handles Roam Synch Indication + * param pMac - global mac structure + * return - none + *----------------------------------------------------------------- + **/ +void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + tpPESession session_ptr; + tpPESession ft_session_ptr; + uint8_t session_id; + tSirMsgQ mmh_msg; + tSirBssDescription *bss_desc_ptr = NULL; + roam_offload_synch_ind *roam_sync_ind_ptr = + (roam_offload_synch_ind *)pMsg->bodyptr; + + if (!roam_sync_ind_ptr) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3:%s:roam_sync_ind_ptr is NULL", __func__); + return; + } + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3: Received WMA_ROAM_OFFLOAD_SYNCH_IND"); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:%s:authStatus=%d, vdevId=%d", __func__, + roam_sync_ind_ptr->authStatus, + roam_sync_ind_ptr->roamedVdevId); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + roam_sync_ind_ptr->bssId, 6); + session_ptr = pe_find_session_by_bss_idx(pMac, + roam_sync_ind_ptr->roamedVdevId); + if (session_ptr == NULL) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "%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(session_ptr)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "session is not in STA mode"); + return; + } + if (!CDF_IS_STATUS_SUCCESS(lim_roam_fill_bss_descr(pMac, + roam_sync_ind_ptr))) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3:%s:Failed to fill Bss Descr", __func__); + return; + } + bss_desc_ptr = roam_sync_ind_ptr->bss_desc_ptr; + ft_session_ptr = pe_create_session(pMac, bss_desc_ptr->bssId, + &session_id, pMac->lim.maxStation, + eSIR_INFRASTRUCTURE_MODE); + if (ft_session_ptr == NULL) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3: Session Can't be created for new AP during Roam Synch"); + lim_print_mac_addr(pMac, bss_desc_ptr->bssId, LOGE); + return; + } + ft_session_ptr->peSessionId = session_id; + sir_copy_mac_addr(ft_session_ptr->selfMacAddr, session_ptr->selfMacAddr); + sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc_ptr->bssId); + ft_session_ptr->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 + **/ + ft_session_ptr->bRoamSynchInProgress = true; + + if (ft_session_ptr->bssType == eSIR_INFRASTRUCTURE_MODE) { + ft_session_ptr->limSystemRole = eLIM_STA_ROLE; + } else { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3:Invalid bss type"); + return; + } + ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState; + ft_session_ptr->limSmeState = eLIM_SME_WT_REASSOC_STATE; + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:%s:created session (%p) with id = %d", + __func__, ft_session_ptr, ft_session_ptr->peSessionId); + /* Update the ReAssoc BSSID of the current session */ + sir_copy_mac_addr(session_ptr->limReAssocbssId, bss_desc_ptr->bssId); + lim_print_mac_addr(pMac, session_ptr->limReAssocbssId, LOG2); + + /* Prepare the session right now with as much as possible */ + lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr); + lim_ft_prepare_add_bss_req(pMac, false, ft_session_ptr, bss_desc_ptr); + mmh_msg.type = + roam_sync_ind_ptr->messageType; + /* eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */ + mmh_msg.bodyptr = roam_sync_ind_ptr; + mmh_msg.bodyval = 0; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:%s:sending eWNI_SME_ROAM_OFFLOAD_SYNCH_IND", __func__); + lim_sys_process_mmh_msg_api(pMac, &mmh_msg, ePROT); +} +#endif + +uint8_t lim_is_beacon_miss_scenario(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo) +{ + tpSirMacMgmtHdr pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + uint8_t sessionId; + tpPESession psessionEntry = + pe_find_session_by_bssid(pMac, pHdr->bssId, &sessionId); + + if (psessionEntry && psessionEntry->pmmOffloadInfo.bcnmiss) + return true; + return false; +} + +/** ----------------------------------------------------------------- + \brief lim_is_pkt_candidate_for_drop() - 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 lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + uint32_t subType) +{ + uint32_t framelen; + uint8_t *pBody; + tSirMacCapabilityInfo capabilityInfo; + tpSirMacMgmtHdr pHdr = NULL; + tpPESession psessionEntry = NULL; + uint8_t 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 (lim_is_beacon_miss_scenario(pMac, pRxPacketInfo)) { + MTRACE(mac_trace + (pMac, TRACE_CODE_INFO_LOG, 0, + eLOG_NODROP_MISSED_BEACON_SCENARIO)); + return eMGMT_DROP_NO_DROP; + } + if (lim_is_system_in_scan_state(pMac)) { + return eMGMT_DROP_NO_DROP; + } else if (WMA_IS_RX_IN_SCAN(pRxPacketInfo)) { + return eMGMT_DROP_SCAN_MODE_FRAME; + } else { + /* Beacons and probe responses can come in any time + * because of parallel scans. Don't drop them. + */ + return eMGMT_DROP_NO_DROP; + } + } + + 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 + + framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + + /* 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; + + *((uint16_t *) &capabilityInfo) = + sir_read_u16(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) && + (!WMA_GET_RX_BEACON_SENT(pRxPacketInfo))) { + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + psessionEntry = + pe_find_session_by_bssid(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; +} + +CDF_STATUS pe_acquire_global_lock(tAniSirLim *psPe) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + + if (psPe) { + if (CDF_IS_STATUS_SUCCESS + (cdf_mutex_acquire(&psPe->lkPeGlobalLock))) { + status = CDF_STATUS_SUCCESS; + } + } + return status; +} + +CDF_STATUS pe_release_global_lock(tAniSirLim *psPe) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + if (psPe) { + if (CDF_IS_STATUS_SUCCESS + (cdf_mutex_release(&psPe->lkPeGlobalLock))) { + status = CDF_STATUS_SUCCESS; + } + } + return status; +} + diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c new file mode 100644 index 000000000000..a1680d6bab13 --- /dev/null +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -0,0 +1,5132 @@ +/* + * 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 lim_assoc_utils.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 "cds_api.h" +#include "ani_global.h" +#include "wni_api.h" +#include "sir_common.h" + +#include "wni_cfg.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_sta_hash_api.h" +#include "lim_admit_control.h" +#include "lim_send_messages.h" +#include "lim_ibss_peer_mgmt.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" + +#include "cdf_types.h" +#include "wma_types.h" +#include "lim_types.h" + +/* + * fill up the rate info properly based on what is actually supported by the peer + * TBD TBD TBD + */ +void +lim_fill_supported_rates_info(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 = + lim_get_sta_rate_mode((uint8_t) psessionEntry->dot11mode); + else + pRates->opRateMode = + lim_get_sta_peer_type(pMac, pSta, psessionEntry); + +} + +/** + * lim_cmp_s_sid() + * + ***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. + */ + +uint8_t +lim_cmp_s_sid(tpAniSirGlobal pMac, tSirMacSSid *prxSSid, + tpPESession psessionEntry) +{ + + if (cdf_mem_compare + ((uint8_t *) prxSSid, (uint8_t *) &psessionEntry->ssId, + (uint8_t) (psessionEntry->ssId.length + 1))) + return true; + else + return false; + +} /****** end lim_cmp_s_sid() ******/ + +/** + * lim_compare_capabilities() + * + ***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. + */ + +uint8_t +lim_compare_capabilities(tpAniSirGlobal pMac, + tSirAssocReq *pAssocReq, + tSirMacCapabilityInfo *pLocalCapabs, + tpPESession psessionEntry) +{ + uint32_t val; + + if ((LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && + (pAssocReq->capabilityInfo.ibss)) { + /* Requesting STA asserting IBSS capability. */ + lim_log(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 */ + lim_log(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 */ + } + + lim_log(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 */ + lim_log(pMac, LOG1, + FL + ("Received unmatched QOS but cfg to suppress - continuing")); + } + + /* + * 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_cfg_get_int + (pMac, WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY, + &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("error getting WNI_CFG_FORCE_SHORT_SLOT_ASSOC_ONLY ")); + return false; + } + if (val) { + if (pAssocReq->capabilityInfo.shortSlotTime != + pLocalCapabs->shortSlotTime) { + lim_log(pMac, LOGE, + FL + ("AP rejects association as station doesnt support shortslot time")); + return false; + } + return false; + } + } + + return true; +} /****** end lim_compare_capabilities() ******/ + +/** + * lim_check_rx_basic_rates() + * + ***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. + */ + +uint8_t +lim_check_rx_basic_rates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet, + tpPESession psessionEntry) +{ + tSirMacRateSet *pRateSet, basicRate; + uint8_t i, j, k, match; + + pRateSet = cdf_mem_malloc(sizeof(tSirMacRateSet)); + if (NULL == pRateSet) { + lim_log(pMac, LOGP, + FL("call to AllocateMemory failed for RATESET")); + + return false; + } + + /* Copy operational rate set from session Entry */ + cdf_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 */ + cdf_mem_free((uint8_t *) pRateSet); + + return false; + } + } + + /* Free up memory allocated for rateset */ + cdf_mem_free((uint8_t *) pRateSet); + + return true; +} /****** end lim_check_rx_basic_rates() ******/ + +/** + * lim_check_mcs_set() + * + ***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. + */ + +uint8_t lim_check_mcs_set(tpAniSirGlobal pMac, uint8_t *supportedMCSSet) +{ + uint8_t basicMCSSet[SIZE_OF_BASIC_MCS_SET] = { 0 }; + uint32_t cfgLen = 0; + uint8_t i; + uint8_t validBytes; + uint8_t lastByteMCSMask = 0x1f; + + cfgLen = WNI_CFG_BASIC_MCS_SET_LEN; + if (wlan_cfg_get_str(pMac, WNI_CFG_BASIC_MCS_SET, + (uint8_t *) basicMCSSet, + (uint32_t *) &cfgLen) != eSIR_SUCCESS) { + /* / Could not get Basic MCS rateset from CFG. Log error. */ + lim_log(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; i < validBytes; i++) { + if ((basicMCSSet[i] & supportedMCSSet[i]) != basicMCSSet[i]) { + /* Log is avaiable in calling function in file lim_process_assoc_req_frame.c */ + lim_log(pMac, LOGW, + FL + ("One of Basic MCS Set Rates is not supported by the Station.")); + return false; + } + } + + /* check the last 5 bits of the valid MCS bitmap */ + if (((basicMCSSet[i] & lastByteMCSMask) & + (supportedMCSSet[i] & lastByteMCSMask)) != + (basicMCSSet[i] & lastByteMCSMask)) { + lim_log(pMac, LOGW, + FL + ("One of Basic MCS Set Rates is not supported by the Station.")); + return false; + } + + return true; +} + +#define SECURITY_SUITE_TYPE_MASK 0xFF +#define SECURITY_SUITE_TYPE_WEP40 0x1 +#define SECURITY_SUITE_TYPE_TKIP 0x2 +#define SECURITY_SUITE_TYPE_CCMP 0x4 +#define SECURITY_SUITE_TYPE_WEP104 0x4 + +/** + * lim_check_rx_rsn_ie_match()- validate received rsn ie with supported cipher + * suites. + * @mac_ctx: pointer to global mac structure + * @rx_rsn_ie: received rsn IE + * @session_entry: pe session entry + * @sta_is_ht: peer station HT capability + * @pmf_connection: set to true if this is pmf connection + * + * 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. + * + * Return: eSIR_SUCCESS if ALL BSS basic rates are present in the + * received rateset else failure status. + */ + +uint8_t +lim_check_rx_rsn_ie_match(tpAniSirGlobal mac_ctx, tDot11fIERSN rx_rsn_ie, + tpPESession session_entry, uint8_t sta_is_ht, + bool *pmf_connection) +{ + tDot11fIERSN *rsn_ie; + uint8_t i, j, match, only_non_ht_cipher = 1; +#ifdef WLAN_FEATURE_11W + bool we_are_pmf_capable; + bool we_require_pmf; + bool they_are_pmf_capable; + bool they_require_pmf; +#endif + + /* RSN IE should be received from PE */ + rsn_ie = &session_entry->gStartBssRSNIe; + + /* Check groupwise cipher suite */ + for (i = 0; i < sizeof(rx_rsn_ie.gp_cipher_suite); i++) + if (rsn_ie->gp_cipher_suite[i] != + rx_rsn_ie.gp_cipher_suite[i]) { + lim_log(mac_ctx, 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 < rx_rsn_ie.pwise_cipher_suite_count; i++) { + for (j = 0; j < rsn_ie->pwise_cipher_suite_count; j++) { + if (cdf_mem_compare(&rx_rsn_ie.pwise_cipher_suites[i], + &rsn_ie->pwise_cipher_suites[j], + sizeof(rsn_ie->pwise_cipher_suites[j]))) { + match = 1; + break; + } + } + + if ((sta_is_ht) +#ifdef ANI_LITTLE_BYTE_ENDIAN + && + ((rx_rsn_ie.pwise_cipher_suites[i][3] & + SECURITY_SUITE_TYPE_MASK) == + SECURITY_SUITE_TYPE_CCMP)) +#else + && + ((rx_rsn_ie.pwise_cipher_suites[i][0] & + SECURITY_SUITE_TYPE_MASK) == + SECURITY_SUITE_TYPE_CCMP)) +#endif + only_non_ht_cipher = 0; + + } + + if ((!match) || ((sta_is_ht) && only_non_ht_cipher)) { + lim_log(mac_ctx, LOG1, FL("Invalid pairwise cipher suite")); + return eSIR_MAC_INVALID_PAIRWISE_CIPHER_STATUS; + } + /* + * Check RSN capabilities + * Bit 0 of First Byte - PreAuthentication Capability + */ + if (((rx_rsn_ie.RSN_Cap[0] >> 0) & 0x1) == true) { + /* this is supported by AP only */ + lim_log(mac_ctx, LOG1, + FL("Invalid RSN information element capabilities")); + return eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS; + } + + *pmf_connection = false; + +#ifdef WLAN_FEATURE_11W + we_are_pmf_capable = session_entry->pLimStartBssReq->pmfCapable; + we_require_pmf = session_entry->pLimStartBssReq->pmfRequired; + they_are_pmf_capable = (rx_rsn_ie.RSN_Cap[0] >> 7) & 0x1; + they_require_pmf = (rx_rsn_ie.RSN_Cap[0] >> 6) & 0x1; + + if ((they_require_pmf && they_are_pmf_capable && !we_are_pmf_capable) || + (we_require_pmf && !they_are_pmf_capable)) { + lim_log(mac_ctx, LOG1, + FL("Association fail, robust management frames policy" + " violation they_require_pmf =%d" + " theyArePMFCapable %d weArePMFCapable %d" + " weRequirePMF %d theyArePMFCapable %d"), + they_require_pmf, they_are_pmf_capable, + we_are_pmf_capable, we_require_pmf, + they_are_pmf_capable); + return eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION; + } + + if (they_are_pmf_capable && we_are_pmf_capable) + *pmf_connection = true; + + lim_log(mac_ctx, LOG1, + FL("weAreCapable %d, weRequire %d, theyAreCapable %d," + " theyRequire %d, PMFconnection %d"), + we_are_pmf_capable, we_require_pmf, they_are_pmf_capable, + they_require_pmf, *pmf_connection); +#endif + + return eSIR_SUCCESS; +} + +/** + * lim_check_rx_wpa_ie_match() - to check supported cipher suites + * + * @mac: pointer to global mac structure + * @rx_wpaie: Received WPA IE in (Re)Assco req + * @session_entry: pointer to PE session + * @sta_is_ht: peer station is HT + * + * 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. + * + * Return: Success if ALL BSS basic rates are present in the + * received rateset else failure status. + */ + +uint8_t +lim_check_rx_wpa_ie_match(tpAniSirGlobal mac, tDot11fIEWPA rx_wpaie, + tpPESession session_entry, uint8_t sta_is_ht) +{ + tDot11fIEWPA *wpa_ie; + uint8_t i, j, match, only_non_ht_cipher = 1; + + /* WPA IE should be received from PE */ + wpa_ie = &session_entry->gStartBssWPAIe; + + /* Check groupwise cipher suite */ + for (i = 0; i < 4; i++) { + if (wpa_ie->multicast_cipher[i] != rx_wpaie.multicast_cipher[i]) { + lim_log(mac, 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 < rx_wpaie.unicast_cipher_count; i++) { + for (j = 0; j < wpa_ie->unicast_cipher_count; j++) { + if (cdf_mem_compare(rx_wpaie.unicast_ciphers[i], + wpa_ie->unicast_ciphers[j], 4)) { + match = 1; + break; + } + } + + if ((sta_is_ht) +#ifdef ANI_LITTLE_BYTE_ENDIAN + && + ((rx_wpaie. + unicast_ciphers[i][3] & SECURITY_SUITE_TYPE_MASK) == + SECURITY_SUITE_TYPE_CCMP)) +#else + && + ((rx_wpaie. + unicast_ciphers[i][0] & SECURITY_SUITE_TYPE_MASK) == + SECURITY_SUITE_TYPE_CCMP)) +#endif + { + only_non_ht_cipher = 0; + } + + } + + if ((!match) || ((sta_is_ht) && only_non_ht_cipher)) { + lim_log(mac, LOG1, FL("Invalid pairwise cipher suite")); + return eSIR_MAC_CIPHER_SUITE_REJECTED_STATUS; + } + + return eSIR_SUCCESS; +} + +/** + * lim_cleanup_rx_path() + * + ***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 +lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + + lim_log(pMac, LOG1, FL("Cleanup Rx Path for AID : %d" + "psessionEntry->limSmeState : %d, mlmState : %d"), + pStaDs->assocId, psessionEntry->limSmeState, + pStaDs->mlmStaContext.mlmState); + + psessionEntry->isCiscoVendorAP = false; + + if (pMac->lim.gLimAddtsSent) { + MTRACE(mac_trace + (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) { + lim_deactivate_and_change_per_sta_id_timer(pMac, eLIM_CNF_WAIT_TIMER, + pStaDs->assocId); + + if (!pStaDs->mlmStaContext.updateContext) { + /** + * There is no context at Polaris to delete. + * Release our assigned AID back to the free pool + */ + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + lim_release_peer_idx(pMac, pStaDs->assocId, + psessionEntry); + } + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, + pStaDs->assocId, psessionEntry); + + return retCode; + } + } + /* delete all tspecs associated with this sta. */ + lim_admit_control_delete_sta(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(mac_trace + (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 */ + lim_deactivate_and_change_timer(pMac, eLIM_PROBE_AFTER_HB_TIMER); + lim_deactivate_and_change_timer(pMac, eLIM_JOIN_FAIL_TIMER); + pMac->lim.gLastBeaconDtimCount = 0; + pMac->lim.gLastBeaconDtimPeriod = 0; + +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); +#else + lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + + } +#ifdef WLAN_DEBUG + /* increment a debug count */ + pMac->lim.gLimNumRxCleanup++; +#endif + + if (psessionEntry->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) { + retCode = + lim_del_bss(pMac, pStaDs, psessionEntry->bssIdx, + psessionEntry); + } else + retCode = lim_del_sta(pMac, pStaDs, true, psessionEntry); + + return retCode; + +} /*** end lim_cleanup_rx_path() ***/ + +/** + * lim_send_del_sta_cnf() + * + ***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 uint16_t staDsAssocId, + * @param tLimMlmStaContext mlmStaContext, + * @param tSirResultCodes statusCode + * + * @return None + */ + +void +lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, + uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext, + tSirResultCodes statusCode, tpPESession psessionEntry) +{ + + tLimMlmDisassocCnf mlmDisassocCnf; + tLimMlmDeauthCnf mlmDeauthCnf; + tLimMlmPurgeStaInd mlmPurgeStaInd; + + lim_log(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 }; + + sir_copy_mac_addr(nullAddr, psessionEntry->bssId); + + /* Free up buffer allocated for JoinReq held by */ + /* MLM state machine */ + if (psessionEntry->pLimMlmJoinReq) { + cdf_mem_free(psessionEntry->pLimMlmJoinReq); + psessionEntry->pLimMlmJoinReq = NULL; + } + + psessionEntry->limAID = 0; + + } + + if ((mlmStaContext.cleanupTrigger == + eLIM_HOST_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_LINK_MONITORING_DISASSOC) || + (mlmStaContext.cleanupTrigger == eLIM_PROMISCUOUS_MODE_DISASSOC)) { + /** + * Host or LMM driven Disassociation. + * Issue Disassoc Confirm to SME. + */ + lim_log(pMac, LOGW, + FL("Lim Posting DISASSOC_CNF to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger); + + cdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr, + (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + mlmDisassocCnf.resultCode = statusCode; + mlmDisassocCnf.disassocTrigger = mlmStaContext.cleanupTrigger; + /* Update PE session Id */ + mlmDisassocCnf.sessionId = psessionEntry->peSessionId; + + lim_post_sme_message(pMac, + LIM_MLM_DISASSOC_CNF, + (uint32_t *) &mlmDisassocCnf); + } else if ((mlmStaContext.cleanupTrigger == + eLIM_HOST_DEAUTH) || + (mlmStaContext.cleanupTrigger == + eLIM_LINK_MONITORING_DEAUTH)) { + /** + * Host or LMM driven Deauthentication. + * Issue Deauth Confirm to SME. + */ + lim_log(pMac, LOGW, + FL("Lim Posting DEAUTH_CNF to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger); + cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr, + (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + mlmDeauthCnf.resultCode = statusCode; + mlmDeauthCnf.deauthTrigger = mlmStaContext.cleanupTrigger; + /* PE session Id */ + mlmDeauthCnf.sessionId = psessionEntry->peSessionId; + + lim_post_sme_message(pMac, + LIM_MLM_DEAUTH_CNF, + (uint32_t *) &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. + */ + lim_log(pMac, LOGW, + FL("Lim Posting PURGE_STA_IND to Sme. Trigger: %d"), + mlmStaContext.cleanupTrigger); + cdf_mem_copy((uint8_t *) &mlmPurgeStaInd.peerMacAddr, + (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + mlmPurgeStaInd.reasonCode = + (uint8_t) mlmStaContext.disassocReason; + mlmPurgeStaInd.aid = staDsAssocId; + mlmPurgeStaInd.purgeTrigger = mlmStaContext.cleanupTrigger; + mlmPurgeStaInd.sessionId = psessionEntry->peSessionId; + + lim_post_sme_message(pMac, + LIM_MLM_PURGE_STA_IND, + (uint32_t *) &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. */ + uint8_t smesessionId; + uint16_t smetransactionId; + + smesessionId = psessionEntry->smeSessionId; + smetransactionId = psessionEntry->transactionId; + + psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + psessionEntry->limSmeState)); + + /* if it is a reassoc failure to join new AP */ + if ((mlmStaContext.resultCode == + eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE) + || (mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_FAILURE) + || (mlmStaContext.resultCode == + eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE)) { + lim_log(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) { + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + } + + lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP, + mlmStaContext.resultCode, + mlmStaContext.protStatusCode, + psessionEntry, smesessionId, + smetransactionId); + } else { + cdf_mem_free(psessionEntry->pLimJoinReq); + psessionEntry->pLimJoinReq = NULL; + + lim_log(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) { + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + } + + lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_JOIN_RSP, + mlmStaContext.resultCode, + mlmStaContext.protStatusCode, + psessionEntry, smesessionId, + smetransactionId); + } + + } + + if (NULL != psessionEntry && !LIM_IS_AP_ROLE(psessionEntry)) { + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + } +} + +/** + * lim_reject_association() - function to reject Re/Association Request + * + * @mac_ctx: pointer to global mac structure + * @peer_addr: mac address of the peer + * @sub_type: Indicates whether it is Association Request (=0) or + * Reassociation Request (=1) frame + * @add_pre_auth_context:Indicates whether pre-auth context + * to be added for this STA + * @auth_type: Indicates auth type to be added + * @sta_id: Indicates staId of the STA being rejected + * association + * @delete_sta: Indicates whether to delete STA context + * at Polaris + * @result_code: Indicates what reasonCode to be sent in + * Re/Assoc response to STA + * @session_entry: pointer to PE session + * + * 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 at Polaris or reject by applications. + * 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 + * + * Return: none + */ + +void +lim_reject_association(tpAniSirGlobal mac_ctx, tSirMacAddr peer_addr, + uint8_t sub_type, uint8_t add_pre_auth_context, + tAniAuthType auth_type, uint16_t sta_id, + uint8_t delete_sta, tSirResultCodes result_code, + tpPESession session_entry) +{ + tpDphHashNode sta_ds; + + lim_log(mac_ctx, LOG1, + FL("Sessionid: %d auth_type: %d sub_type: %d add_pre_auth_context: %d sta_id: %d delete_sta: %d result_code : %d peer_addr: " MAC_ADDRESS_STR), + session_entry->peSessionId, auth_type, sub_type, + add_pre_auth_context, sta_id, delete_sta, result_code, + MAC_ADDR_ARRAY(peer_addr)); + + if (add_pre_auth_context) { + /* Create entry for this STA in pre-auth list */ + struct tLimPreAuthNode *auth_node; + + auth_node = lim_acquire_free_pre_auth_node(mac_ctx, + &mac_ctx->lim.gLimPreAuthTimerTable); + + if (auth_node) { + cdf_mem_copy((uint8_t *) auth_node->peerMacAddr, + peer_addr, sizeof(tSirMacAddr)); + auth_node->fTimerStarted = 0; + auth_node->mlmState = eLIM_MLM_AUTHENTICATED_STATE; + auth_node->authType = (tAniAuthType) auth_type; + auth_node->timestamp = cdf_mc_timer_get_system_ticks(); + lim_add_pre_auth_node(mac_ctx, auth_node); + } + } + + if (delete_sta == false) { + lim_send_assoc_rsp_mgmt_frame(mac_ctx, + eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS, + 1, peer_addr, sub_type, 0, session_entry); + /* Log error */ + lim_log(mac_ctx, LOGW, + FL("received Re/Assoc req when max associated STAs reached from ")); + lim_print_mac_addr(mac_ctx, peer_addr, LOGW); + lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, peer_addr, + session_entry->smeSessionId); + return; + } + + sta_ds = dph_get_hash_entry(mac_ctx, sta_id, + &session_entry->dph.dphHashTable); + + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGW, + FL("No STA context, yet rejecting Association")); + return; + } + + /* + * Polaris has state for this STA. + * Trigger cleanup. + */ + sta_ds->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT; + + /* Receive path cleanup */ + lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + + /* + * Send Re/Association Response with + * status code to requesting STA. + */ + lim_send_assoc_rsp_mgmt_frame(mac_ctx, result_code, 0, peer_addr, + sub_type, 0, session_entry); + + if (session_entry->parsedAssocReq[sta_ds->assocId] != NULL) { + uint8_t *assoc_req_frame; + + assoc_req_frame = (uint8_t *)((tpSirAssocReq) (session_entry-> + parsedAssocReq[sta_ds->assocId]))->assocReqFrame; + /* + *Assoction confirmation is complete, + *free the copy of association request frame. + */ + if (assoc_req_frame) { + cdf_mem_free(assoc_req_frame); + assoc_req_frame = NULL; + } + + cdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]); + session_entry->parsedAssocReq[sta_ds->assocId] = NULL; + } +} + +/** + * lim_decide_ap_protection_on_ht20_delete() - function to update protection + * parameters. + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @beacon_params: ap beacon parameters + * @session_entry: pe session entry + * + * protection related function while HT20 station is getting deleted. + * + * Return: none + */ +static void +lim_decide_ap_protection_on_ht20_delete(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpUpdateBeaconParams beacon_params, + tpPESession session_entry) +{ + uint32_t i = 0; + + lim_log(mac_ctx, LOG1, + FL("(%d) A HT 20 STA is disassociated. Addr is %pM"), + session_entry->gLimHt20Params.numSta, sta_ds->staAddr); + + if (session_entry->gLimHt20Params.numSta > 0) { + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (!session_entry->protStaCache[i].active) + continue; + + if (cdf_mem_compare(session_entry->protStaCache[i].addr, + sta_ds->staAddr, sizeof(tSirMacAddr))) { + session_entry->gLimHt20Params.numSta--; + session_entry->protStaCache[i].active = + false; + break; + } + } + } + + if (session_entry->gLimHt20Params.numSta == 0) { + /* disable protection */ + lim_log(mac_ctx, LOG1, FL("No 11B STA exists, PESessionID %d"), + session_entry->peSessionId); + lim_enable_ht20_protection(mac_ctx, false, false, beacon_params, + session_entry); + } +} + +/** + * lim_decide_ap_protection_on_delete() - update SAP protection on station + * deletion. + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @beacon_params: ap beacon parameters + * @session_entry: pe session entry + * + * Decides about protection related settings when a station is getting deleted. + * + * Return: none + */ +void +lim_decide_ap_protection_on_delete(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpUpdateBeaconParams beacon_params, + tpPESession session_entry) +{ + uint32_t phy_mode; + tHalBitVal erp_enabled = eHAL_CLEAR; + tSirRFBand rf_band = SIR_BAND_UNKNOWN; + uint32_t i; + + if (NULL == sta_ds) + return; + + lim_get_rf_band_new(mac_ctx, &rf_band, session_entry); + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + erp_enabled = sta_ds->erpEnabled; + + if ((SIR_BAND_5_GHZ == rf_band) && + (true == session_entry->htCapability) && + (session_entry->beaconParams.llaCoexist) && + (false == sta_ds->mlmStaContext.htCapability)) { + /* + * we are HT. if we are 11A, then protection is not required or + * we are HT and 11A station is leaving. + * protection consideration required. + * HT station leaving ==> this case is commonly handled + * between both the bands below. + */ + lim_log(mac_ctx, LOG1, + FL("(%d) A 11A STA is disassociated. Addr is %pM"), + session_entry->gLim11aParams.numSta, sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->protStaCache[i].active && + cdf_mem_compare( + session_entry->protStaCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->protStaCache[i].active = false; + break; + } + } + + if (session_entry->gLim11aParams.numSta == 0) { + /* disable protection */ + lim_update_11a_protection(mac_ctx, false, false, + beacon_params, session_entry); + } + } + + /* we are HT or 11G and 11B station is getting deleted */ + if ((SIR_BAND_2_4_GHZ == rf_band) && + (phy_mode == WNI_CFG_PHY_MODE_11G || + session_entry->htCapability) && + (erp_enabled == eHAL_CLEAR)) { + lim_log(mac_ctx, LOG1, + FL("(%d) A legacy STA is disassociated. Addr is %pM"), + session_entry->gLim11bParams.numSta, sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->protStaCache[i].active && + cdf_mem_compare( + session_entry->protStaCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->gLim11bParams.numSta--; + session_entry->protStaCache[i].active = + false; + break; + } + } + + if (session_entry->gLim11bParams.numSta == 0) { + /* disable protection */ + lim_enable11g_protection(mac_ctx, false, false, + beacon_params, session_entry); + } + } + + /* + * we are HT AP and non-11B station is leaving. + * 11g station is leaving + */ + if ((SIR_BAND_2_4_GHZ == rf_band) && + session_entry->htCapability && + !sta_ds->mlmStaContext.htCapability) { + lim_log(mac_ctx, LOG1, + FL("(%d) A 11g STA is disassociated. Addr is %pM"), + session_entry->gLim11bParams.numSta, sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->protStaCache[i].active && + cdf_mem_compare( + session_entry->protStaCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->gLim11gParams.numSta--; + session_entry->protStaCache[i].active = false; + break; + } + } + + if (session_entry->gLim11gParams.numSta == 0) { + /* disable protection */ + lim_enable_ht_protection_from11g(mac_ctx, false, false, + beacon_params, + session_entry); + } + } + + if (!((true == session_entry->htCapability) && + (true == sta_ds->mlmStaContext.htCapability))) + return; + + /* + * Applies to 2.4 as well as 5 GHZ. + * HT non-GF leaving + */ + if (!sta_ds->htGreenfield) { + lim_log(mac_ctx, LOG1, + FL("(%d) A non-GF STA is disassociated. Addr is %pM"), + session_entry->gLimNonGfParams.numSta, sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->protStaCache[i].active && + cdf_mem_compare( + session_entry->protStaCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->protStaCache[i].active = false; + break; + } + } + + if (session_entry->gLimNonGfParams.numSta == 0) { + /* disable protection */ + lim_enable_ht_non_gf_protection(mac_ctx, false, false, + beacon_params, session_entry); + } + } + + /* + * Applies to 2.4 as well as 5 GHZ. + * HT 20Mhz station leaving + */ + if (session_entry->beaconParams.ht20Coexist && + (eHT_CHANNEL_WIDTH_20MHZ == + sta_ds->htSupportedChannelWidthSet)) { + lim_decide_ap_protection_on_ht20_delete(mac_ctx, sta_ds, + beacon_params, session_entry); + } + + /* + * Applies to 2.4 as well as 5 GHZ. + * LSIG TXOP not supporting staiton leaving + */ + if ((false == session_entry->beaconParams. + fLsigTXOPProtectionFullSupport) && + (false == sta_ds->htLsigTXOPProtection)) { + lim_log(mac_ctx, LOG1, + FL("(%d) A HT LSIG not supporting STA is disassociated. Addr is %pM"), + session_entry->gLimLsigTxopParams.numSta, + sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->protStaCache[i].active && + cdf_mem_compare( + session_entry->protStaCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->protStaCache[i].active = false; + break; + } + } + + if (session_entry->gLimLsigTxopParams.numSta == 0) { + /* disable protection */ + lim_enable_ht_lsig_txop_protection(mac_ctx, true, + false, beacon_params, session_entry); + } + } +} + +/** + * lim_decide_short_preamble() - update short preamble parameters + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @beacon_params: ap beacon parameters + * @session_entry: pe session entry + * + * Decides about any short preamble related change because of new station + * joining. + * + * Return: None + */ +void lim_decide_short_preamble(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpUpdateBeaconParams beacon_params, + tpPESession session_entry) +{ + uint32_t i; + + if (sta_ds->shortPreambleEnabled == eHAL_CLEAR) { + lim_log(mac_ctx, LOG1, + FL("(%d) A non-short preamble STA is disassociated. Addr is %pM"), + session_entry->gLimNoShortParams.numNonShortPreambleSta, + sta_ds->staAddr); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->gLimNoShortParams. + staNoShortCache[i].active && + cdf_mem_compare(session_entry-> + gLimNoShortParams. + staNoShortCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + session_entry->gLimNoShortParams. + numNonShortPreambleSta--; + session_entry->gLimNoShortParams. + staNoShortCache[i].active = false; + break; + } + } + + if (session_entry->gLimNoShortParams.numNonShortPreambleSta) + return; + + /* + * enable short preamble + * reset the cache + */ + cdf_mem_set((uint8_t *) &session_entry->gLimNoShortParams, + sizeof(tLimNoShortParams), 0); + if (lim_enable_short_preamble(mac_ctx, true, + beacon_params, session_entry) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("Cannot enable short preamble")); + } + } +} + +/** + * lim_decide_short_slot() - update short slot time related parameters + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @beacon_params: ap beacon parameters + * @session_entry: pe session entry + * + * Decides about any short slot time related change because of station leaving + * the BSS. + * Return: None + */ +void +lim_decide_short_slot(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, + tpUpdateBeaconParams beacon_params, + tpPESession session_entry) +{ + uint32_t i, val, non_short_slot_sta_count; + + if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR) + return; + + lim_log(mac_ctx, LOG1, + FL("(%d) A non-short slottime STA is disassociated. Addr is %pM"), + mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta, + sta_ds->staAddr); + + wlan_cfg_get_int(mac_ctx, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + &val); + + if (LIM_IS_AP_ROLE(session_entry)) { + non_short_slot_sta_count = + session_entry->gLimNoShortSlotParams.numNonShortSlotSta; + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].active && + cdf_mem_compare(session_entry-> + gLimNoShortSlotParams. + staNoShortSlotCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + non_short_slot_sta_count--; + session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].active = false; + break; + } + } + + if (non_short_slot_sta_count == 0 && val) { + /* + * enable short slot time + * reset the cache + */ + cdf_mem_set((uint8_t *) &session_entry-> + gLimNoShortSlotParams, + sizeof(tLimNoShortSlotParams), 0); + beacon_params->fShortSlotTime = true; + beacon_params->paramChangeBitmap |= + PARAM_SHORT_SLOT_TIME_CHANGED; + session_entry->shortSlotTimeSupported = true; + } + session_entry->gLimNoShortSlotParams.numNonShortSlotSta = + non_short_slot_sta_count; + } else { + non_short_slot_sta_count = + mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta; + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].active && + cdf_mem_compare( + mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].addr, + sta_ds->staAddr, + sizeof(tSirMacAddr))) { + non_short_slot_sta_count--; + mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].active = false; + break; + } + } + + if (val && !non_short_slot_sta_count) { + /* + * enable short slot time + * reset the cache + */ + cdf_mem_set( + (uint8_t *) &mac_ctx->lim.gLimNoShortSlotParams, + sizeof(tLimNoShortSlotParams), 0); + /*in case of AP set SHORT_SLOT_TIME to enable*/ + if (LIM_IS_AP_ROLE(session_entry)) { + beacon_params->fShortSlotTime = true; + beacon_params->paramChangeBitmap |= + PARAM_SHORT_SLOT_TIME_CHANGED; + session_entry->shortSlotTimeSupported = true; + } + } + mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta = + non_short_slot_sta_count; + } +} + +void +lim_post_reassoc_failure(tpAniSirGlobal pMac, + tSirResultCodes resultCode, + uint16_t protStatusCode, tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; + + psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + eLIM_MLM_LINK_ESTABLISHED_STATE)); + + /* 'Change' timer for future activations */ + lim_deactivate_and_change_timer(pMac, eLIM_REASSOC_FAIL_TIMER); + + mlmReassocCnf.resultCode = resultCode; + mlmReassocCnf.protStatusCode = protStatusCode; + /* Update PE session Id */ + mlmReassocCnf.sessionId = psessionEntry->peSessionId; + lim_post_sme_message(pMac, + LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf); +} /*** end lim_post_reassoc_failure() ***/ + +/** + * lim_restore_pre_reassoc_state() + * + ***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 both at Polaris & software + * + ***ASSUMPTIONS: + * + ***NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @param resultCode - Result code that specifies why Reassociation + * attemp failed + * + * @return None + */ + +void +lim_restore_pre_reassoc_state(tpAniSirGlobal pMac, + tSirResultCodes resultCode, + uint16_t protStatusCode, tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; + + lim_log(pMac, LOG1, + FL("sessionid: %d protStatusCode: %d resultCode: %d"), + psessionEntry->smeSessionId, protStatusCode, resultCode); + + psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + eLIM_MLM_LINK_ESTABLISHED_STATE)); + + /* 'Change' timer for future activations */ + lim_deactivate_and_change_timer(pMac, eLIM_REASSOC_FAIL_TIMER); + + lim_set_channel(pMac, psessionEntry->currentOperChannel, + psessionEntry->ch_center_freq_seg0, + psessionEntry->ch_center_freq_seg1, + psessionEntry->ch_width, + 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; + lim_post_sme_message(pMac, + LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf); +} /*** end lim_restore_pre_reassoc_state() ***/ + +/** + * lim_is_reassoc_in_progress() + * + ***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 true When STA is waiting for Reassoc response from AP \n + * else false + */ + +bool lim_is_reassoc_in_progress(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (psessionEntry == NULL) { + return 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 true; + + return false; +} /*** end lim_is_reassoc_in_progress() ***/ + +#ifdef WLAN_FEATURE_11AC +/** + * lim_populate_vht_mcs_set - function to populate vht mcs rate set + * @mac_ctx: pointer to global mac structure + * @rates: pointer to supported rate set + * @peer_vht_caps: pointer to peer vht capabilities + * @session_entry: pe session entry + * + * Populates vht mcs rate set based on peer and self capabilities + * + * Return: eSIR_SUCCESS on success else eSIR_FAILURE + */ +tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal mac_ctx, + tpSirSupportedRates rates, + tDot11fIEVHTCaps *peer_vht_caps, + tpPESession session_entry) +{ + uint32_t val; + uint32_t self_sta_dot11mode = 0; + uint16_t mcs_map_mask = MCSMAPMASK1x1; + uint16_t mcs_map_mask2x2 = 0; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_sta_dot11mode); + + if (!IS_DOT11_MODE_VHT(self_sta_dot11mode)) + return eSIR_SUCCESS; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_VHT_RX_MCS_MAP, &val) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, FL("could not retrieve VHT RX MCS MAP")); + goto error; + } + rates->vhtRxMCSMap = (uint16_t) val; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_VHT_TX_MCS_MAP, &val) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, FL("could not retrieve VHT TX MCS MAP")); + goto error; + } + rates->vhtTxMCSMap = (uint16_t) val; + + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, + &val) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("couldn't retrieve VHT RX Supported data rate MAP")); + goto error; + } + rates->vhtRxHighestDataRate = (uint16_t) val; + + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + &val) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("couldn't retrieve VHT RX Supported data rate MAP")); + goto error; + } + rates->vhtTxHighestDataRate = (uint16_t) val; + + if (peer_vht_caps == NULL) + return eSIR_SUCCESS; + + rates->vhtTxHighestDataRate = + CDF_MIN(rates->vhtTxHighestDataRate, + peer_vht_caps->txSupDataRate); + rates->vhtRxHighestDataRate = + CDF_MIN(rates->vhtRxHighestDataRate, + peer_vht_caps->rxHighSupDataRate); + + if (mac_ctx->roam.configParam.enable2x2) { + if (session_entry && mac_ctx->lteCoexAntShare && + IS_24G_CH(session_entry->currentOperChannel)) { + if (IS_2X2_CHAIN(session_entry->chainMask)) + mcs_map_mask2x2 = MCSMAPMASK2x2; + else + lim_log(mac_ctx, LOGE, FL("2x2 not enabled %d"), + session_entry->chainMask); + } else { + mcs_map_mask2x2 = MCSMAPMASK2x2; + } + } + + if ((peer_vht_caps->txMCSMap & mcs_map_mask) < + (rates->vhtRxMCSMap & mcs_map_mask)) { + rates->vhtRxMCSMap &= ~(mcs_map_mask); + rates->vhtRxMCSMap |= + (peer_vht_caps->txMCSMap & mcs_map_mask); + } + if ((peer_vht_caps->rxMCSMap & mcs_map_mask) < + (rates->vhtTxMCSMap & mcs_map_mask)) { + rates->vhtTxMCSMap &= ~(mcs_map_mask); + rates->vhtTxMCSMap |= + (peer_vht_caps->rxMCSMap & mcs_map_mask); + } + + if (mcs_map_mask2x2) { + + uint16_t peer_mcs_map, self_mcs_map; + + peer_mcs_map = + peer_vht_caps->txMCSMap & mcs_map_mask2x2; + self_mcs_map = + rates->vhtRxMCSMap & mcs_map_mask2x2; + + if ((self_mcs_map != mcs_map_mask2x2) && + ((peer_mcs_map == mcs_map_mask2x2) || + (peer_mcs_map < self_mcs_map))) { + rates->vhtRxMCSMap &= ~mcs_map_mask2x2; + rates->vhtRxMCSMap |= peer_mcs_map; + } + + peer_mcs_map = + (peer_vht_caps->rxMCSMap & mcs_map_mask2x2); + self_mcs_map = + (rates->vhtTxMCSMap & mcs_map_mask2x2); + + if ((self_mcs_map != mcs_map_mask2x2) && + ((peer_mcs_map == mcs_map_mask2x2) || + (peer_mcs_map < self_mcs_map))) { + rates->vhtTxMCSMap &= ~mcs_map_mask2x2; + rates->vhtTxMCSMap |= peer_mcs_map; + } + } + + lim_log(mac_ctx, LOG1, + FL("enable2x2 - %d vhtRxMCSMap - %x vhtTxMCSMap - %x\n"), + mac_ctx->roam.configParam.enable2x2, + rates->vhtRxMCSMap, rates->vhtTxMCSMap); + + return eSIR_SUCCESS; +error: + + return eSIR_FAILURE; +} +#endif + +/** + * lim_populate_own_rate_set() - comprises the basic and extended rates read + * from CFG + * @mac_ctx: pointer to global mac structure + * @rates: pointer to supported rates + * @supported_mcs_set: pointer to supported mcs rates + * @basic_only: update only basic rates if set true + * @session_entry: pe session entry + * @vht_caps: pointer to vht capability + * + * This function is called by limProcessAssocRsp() or + * lim_add_staInIBSS() + * - 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 + * 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 + * + * Return: eSIR_SUCCESS or eSIR_FAILURE. + */ +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +lim_populate_own_rate_set(tpAniSirGlobal mac_ctx, + tpSirSupportedRates rates, uint8_t *supported_mcs_set, + uint8_t basic_only, tpPESession session_entry, + tDot11fIEVHTCaps *vht_caps) +#else +tSirRetStatus +lim_populate_own_rate_set(tpAniSirGlobal mac_ctx, + tpSirSupportedRates rates, + uint8_t *supported_mcs_set, + uint8_t basic_only, tpPESession session_entry) +#endif +{ + tSirMacRateSet temp_rate_set; + tSirMacRateSet temp_rate_set2; + uint32_t i, j, val, min, is_arate; + uint32_t phy_mode = 0; + uint32_t self_sta_dot11mode = 0; + uint8_t a_rate_index = 0; + uint8_t b_rate_index = 0; + + + is_arate = 0; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_sta_dot11mode); + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + /* + * Include 11b rates only when the device configured in + * auto, 11a/b/g or 11b_only + */ + if ((self_sta_dot11mode == WNI_CFG_DOT11_MODE_ALL) || + (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11A) || + (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11AC) || + (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11N) || + (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11G) || + (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11B)) { + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_RATES_11B, + (uint8_t *) &temp_rate_set.rate, &val); + temp_rate_set.numRates = (uint8_t) val; + } else { + temp_rate_set.numRates = 0; + } + + /* Include 11a rates when the device configured in non-11b mode */ + if (!IS_DOT11_MODE_11B(self_sta_dot11mode)) { + val = WNI_CFG_SUPPORTED_RATES_11A_LEN; + wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_RATES_11A, + (uint8_t *) &temp_rate_set2.rate, &val); + temp_rate_set2.numRates = (uint8_t) val; + } else { + temp_rate_set2.numRates = 0; + } + + if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) { + /* we are in big trouble */ + lim_log(mac_ctx, LOGP, FL("more than 12 rates in CFG")); + /* panic */ + goto error; + } + /* copy all rates in temp_rate_set, there are 12 rates max */ + for (i = 0; i < temp_rate_set2.numRates; i++) + temp_rate_set.rate[i + temp_rate_set.numRates] = + temp_rate_set2.rate[i]; + + temp_rate_set.numRates += temp_rate_set2.numRates; + + /** + * Sort rates in temp_rate_set (they are likely to be already sorted) + * put the result in pSupportedRates + */ + + cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0); + for (i = 0; i < temp_rate_set.numRates; i++) { + min = 0; + val = 0xff; + is_arate = 0; + + for (j = 0; (j < temp_rate_set.numRates) && + (j < SIR_MAC_RATESET_EID_MAX); j++) { + if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < + val) { + val = temp_rate_set.rate[j] & 0x7f; + min = j; + } + } + + if (sirIsArate(temp_rate_set.rate[min] & 0x7f)) + is_arate = 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 (basic_only && temp_rate_set.rate[min] & 0x80) { + if (is_arate) + rates->llaRates[a_rate_index++] = + temp_rate_set.rate[min]; + else + rates->llbRates[b_rate_index++] = + temp_rate_set.rate[min]; + } else { + if (is_arate) + rates->llaRates[a_rate_index++] = + temp_rate_set.rate[min]; + else + rates->llbRates[b_rate_index++] = + temp_rate_set.rate[min]; + } + temp_rate_set.rate[min] = 0xff; + } + + if (IS_DOT11_MODE_HT(self_sta_dot11mode)) { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET, + rates->supportedMCSSet, + &val) != eSIR_SUCCESS) { + /* Could not get rateset from CFG. Log error. */ + lim_log(mac_ctx, LOGE, + FL("could not retrieve supportedMCSSet")); + goto error; + } + + /* + * if supported MCS Set of the peer is passed in, + * then do the intersection + * else use the MCS set from local CFG. + */ + + if (supported_mcs_set != NULL) { + for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) + rates->supportedMCSSet[i] &= + supported_mcs_set[i]; + } + + lim_log(mac_ctx, LOG2, FL("MCS Rate Set Bitmap: ")); + for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) + PELOG2(lim_log(mac_ctx, LOG2, FL("%x "), + rates->supportedMCSSet[i]);) + } +#ifdef WLAN_FEATURE_11AC + lim_populate_vht_mcs_set(mac_ctx, rates, vht_caps, session_entry); +#endif + + return eSIR_SUCCESS; +error: + return eSIR_FAILURE; +} + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +lim_populate_peer_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, + tpPESession psessionEntry, tDot11fIEVHTCaps *pVHTCaps) +#else +tSirRetStatus +lim_populate_peer_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, tpPESession psessionEntry) +#endif +{ + tSirMacRateSet tempRateSet; + tSirMacRateSet tempRateSet2; + uint32_t i, j, val, min, isArate; + isArate = 0; + + /* copy operational rate set from psessionEntry */ + if (psessionEntry->rateSet.numRates <= SIR_MAC_RATESET_EID_MAX) { + cdf_mem_copy((uint8_t *) tempRateSet.rate, + (uint8_t *) (psessionEntry->rateSet.rate), + psessionEntry->rateSet.numRates); + tempRateSet.numRates = psessionEntry->rateSet.numRates; + } else { + lim_log(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) { + cdf_mem_copy((uint8_t *) tempRateSet2.rate, + (uint8_t *) (psessionEntry->extRateSet. + rate), + psessionEntry->extRateSet.numRates); + tempRateSet2.numRates = + psessionEntry->extRateSet.numRates; + } else { + lim_log(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 */ + lim_log(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 + */ + { + uint8_t aRateIndex = 0; + uint8_t bRateIndex = 0; + cdf_mem_set((uint8_t *) 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 ((uint32_t) (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_cfg_get_str(pMac, WNI_CFG_SUPPORTED_MCS_SET, + pRates->supportedMCSSet, + &val) != eSIR_SUCCESS) { + /* / Could not get rateset from CFG. Log error. */ + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve supportedMCSSet")); + ) + goto error; + } + /* 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; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) + pRates->supportedMCSSet[i] &= + pSupportedMCSSet[i]; + } + PELOG2(lim_log(pMac, LOG2, FL("MCS Rate Set Bitmap: "));) + for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) + PELOG2(lim_log + (pMac, LOG2, FL("%x "), + pRates->supportedMCSSet[i]); + ) + } +#ifdef WLAN_FEATURE_11AC + lim_populate_vht_mcs_set(pMac, pRates, pVHTCaps, psessionEntry); +#endif + return eSIR_SUCCESS; +error: + return eSIR_FAILURE; +} /*** lim_populate_peer_rate_set() ***/ + +/** + * lim_populate_matching_rate_set() -process the CFG rate sets and + * the rate sets received in the Assoc request on AP. + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @oper_rate_set: pointer to operating rate set + * @ext_rate_set: pointer to extended rate set + * @supported_mcs_set: pointer to supported rate set + * @session_entry: pointer to pe session entry + * @vht_caps: pointer to vht capabilities + * + * 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. + * + * 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 + * + * The parser has already ensured unicity of the rates in the + * association request structure + * + * Return: eSIR_SUCCESS on success else eSIR_FAILURE + */ +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +lim_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, + tSirMacRateSet *oper_rate_set, tSirMacRateSet *ext_rate_set, + uint8_t *supported_mcs_set, tpPESession session_entry, + tDot11fIEVHTCaps * vht_caps) +#else +tSirRetStatus +lim_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, + tSirMacRateSet *oper_rate_set, tSirMacRateSet *ext_rate_set, + uint8_t *supported_mcs_set, tpPESession session_entry) +#endif +{ + tSirMacRateSet temp_rate_set; + tSirMacRateSet temp_rate_set2; + uint32_t i, j, val, min, is_arate; + uint32_t phy_mode; + uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET]; + tpSirSupportedRates rates; + uint8_t a_rate_index = 0; + uint8_t b_rate_index = 0; + + is_arate = 0; + + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + /* copy operational rate set from session_entry */ + cdf_mem_copy((temp_rate_set.rate), (session_entry->rateSet.rate), + session_entry->rateSet.numRates); + temp_rate_set.numRates = (uint8_t) session_entry->rateSet.numRates; + + if (phy_mode == WNI_CFG_PHY_MODE_11G) { + cdf_mem_copy((temp_rate_set2.rate), + (session_entry->extRateSet.rate), + session_entry->extRateSet.numRates); + temp_rate_set2.numRates = + (uint8_t) session_entry->extRateSet.numRates; + } else { + temp_rate_set2.numRates = 0; + } + + if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) { + lim_log(mac_ctx, 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 temp_rate_set, there are 12 rates max */ + for (i = 0; i < temp_rate_set2.numRates; i++) + temp_rate_set.rate[i + temp_rate_set.numRates] = + temp_rate_set2.rate[i]; + + temp_rate_set.numRates += temp_rate_set2.numRates; + + /* + * Sort rates in temp_rate_set (they are likely to be already sorted) + * put the result in temp_rate_set2 + */ + temp_rate_set2.numRates = 0; + + for (i = 0; i < temp_rate_set.numRates; i++) { + min = 0; + val = 0xff; + + for (j = 0; j < temp_rate_set.numRates; j++) + if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) { + val = temp_rate_set.rate[j] & 0x7f; + min = j; + } + + temp_rate_set2.rate[temp_rate_set2.numRates++] = + temp_rate_set.rate[min]; + temp_rate_set.rate[min] = 0xff; + } + + /* + * Copy received rates in temp_rate_set, the parser has ensured + * unicity of the rates so there cannot be more than 12 + */ + for (i = 0; (i < oper_rate_set->numRates && + i < SIR_MAC_RATESET_EID_MAX); i++) + temp_rate_set.rate[i] = oper_rate_set->rate[i]; + + temp_rate_set.numRates = oper_rate_set->numRates; + + lim_log(mac_ctx, LOG2, + "Sum of SUPPORTED and EXTENDED Rate Set (%1d)", + temp_rate_set.numRates + ext_rate_set->numRates); + + if (ext_rate_set->numRates && + ((temp_rate_set.numRates + ext_rate_set->numRates) > 12) && + temp_rate_set.numRates < 12) { + int found = 0; + int tail = temp_rate_set.numRates; + + for (i = 0; (i < ext_rate_set->numRates && + i < SIR_MAC_RATESET_EID_MAX); i++) { + found = 0; + for (j = 0; j < (uint32_t) tail; j++) { + if ((temp_rate_set.rate[j] & 0x7F) == + (ext_rate_set->rate[i] & 0x7F)) { + found = 1; + break; + } + } + + if (!found) { + temp_rate_set.rate[temp_rate_set.numRates++] = + ext_rate_set->rate[i]; + if (temp_rate_set.numRates >= 12) + break; + } + } + } else if (ext_rate_set->numRates && + ((temp_rate_set.numRates + ext_rate_set->numRates) <= 12)) { + for (j = 0; ((j < ext_rate_set->numRates) && + (j < SIR_MAC_RATESET_EID_MAX) && + ((i + j) < SIR_MAC_RATESET_EID_MAX)); j++) + temp_rate_set.rate[i + j] = ext_rate_set->rate[j]; + + temp_rate_set.numRates += ext_rate_set->numRates; + } else if (ext_rate_set->numRates) { + lim_log(mac_ctx, LOG2, + "Relying only on the SUPPORTED Rate Set IE..."); + } + + + rates = &sta_ds->supportedRates; + cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0); + for (i = 0; (i < temp_rate_set2.numRates && + i < SIR_MAC_RATESET_EID_MAX); i++) { + for (j = 0; (j < temp_rate_set.numRates && + j < SIR_MAC_RATESET_EID_MAX); j++) { + if ((temp_rate_set2.rate[i] & 0x7F) != + (temp_rate_set.rate[j] & 0x7F)) + continue; + + if (sirIsArate(temp_rate_set2.rate[i] & 0x7f) && + a_rate_index < SIR_NUM_11A_RATES) { + is_arate = 1; + rates->llaRates[a_rate_index++] = + temp_rate_set2.rate[i]; + } else if ((b_rate_index < SIR_NUM_11B_RATES) && + !(sirIsArate(temp_rate_set2.rate[i] & 0x7f))) { + rates->llbRates[b_rate_index++] = + temp_rate_set2.rate[i]; + } + break; + } + } + + /* + * Now add the Polaris rates only when Proprietary rates are enabled. + * compute the matching MCS rate set, if peer is 11n capable and self + * mode is 11n + */ +#ifdef FEATURE_WLAN_TDLS + if (sta_ds->mlmStaContext.htCapability) +#else + if (IS_DOT11_MODE_HT(session_entry->dot11mode) && + (sta_ds->mlmStaContext.htCapability)) +#endif + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET, + mcs_set, &val) != eSIR_SUCCESS) { + /* Could not get rateset from CFG. Log error. */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve supportedMCSet")); + goto error; + } + + for (i = 0; i < val; i++) + sta_ds->supportedRates.supportedMCSSet[i] = + mcs_set[i] & supported_mcs_set[i]; + + lim_log(mac_ctx, LOG2, + FL("lim_populate_matching_rate_set: MCS Rate Set Bitmap" + " from CFG and DPH : ")); + for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) { + lim_log(mac_ctx, LOG2, FL("%x %x "), mcs_set[i], + sta_ds->supportedRates.supportedMCSSet[i]); + } + } +#ifdef WLAN_FEATURE_11AC + lim_populate_vht_mcs_set(mac_ctx, &sta_ds->supportedRates, vht_caps, + session_entry); +#endif + /* + * Set the erpEnabled bit if the phy is in G mode and at least + * one A rate is supported + */ + if ((phy_mode == WNI_CFG_PHY_MODE_11G) && is_arate) + sta_ds->erpEnabled = eHAL_SET; + + return eSIR_SUCCESS; + +error: + + return eSIR_FAILURE; +} + +/** + * lim_populate_vht_caps() - populates vht capabilities based on input + * capabilities + * @input_caps: input capabilities based on which we format the vht + * capabilities + * + * function to populate the supported vht capabilities. + * + * Return: vht capabilities derived based on input parameters. + */ +static uint32_t lim_populate_vht_caps(tDot11fIEVHTCaps input_caps) +{ + uint32_t vht_caps; + + vht_caps = ((input_caps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | + (input_caps.supportedChannelWidthSet << + SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | + (input_caps.ldpcCodingCap << + SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | + (input_caps.shortGI80MHz << + SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | + (input_caps.shortGI160and80plus80MHz << + SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | + (input_caps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | + (input_caps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | + (input_caps.suBeamFormerCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | + (input_caps.suBeamformeeCap << + SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | + (input_caps.csnofBeamformerAntSup << + SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | + (input_caps.numSoundingDim << + SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | + (input_caps.muBeamformerCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) | + (input_caps.muBeamformeeCap << + SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | + (input_caps.vhtTXOPPS << + SIR_MAC_VHT_CAP_TXOPPS) | + (input_caps.htcVHTCap << + SIR_MAC_VHT_CAP_HTC_CAP) | + (input_caps.maxAMPDULenExp << + SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | + (input_caps.vhtLinkAdaptCap << + SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | + (input_caps.rxAntPattern << + SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | + (input_caps.txAntPattern << + SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | + (input_caps.reserved1 << + SIR_MAC_VHT_CAP_RESERVED2)); + + return vht_caps; +} +/** + * lim_add_sta()- called to add an STA context at hardware + * @mac_ctx: pointer to global mac structure + * @sta_ds: station node + * @update_entry: set to true for updating the entry + * @session_entry: pe session entry + * + * This function is called to add an STA context at hardware + * whenever a STA is (Re) Associated. + * + * Return: eSIR_SUCCESS on success else eSirRetStatus failure codes + */ + +tSirRetStatus +lim_add_sta(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, uint8_t update_entry, tpPESession session_entry) +{ + tpAddStaParams add_sta_params = NULL; + tSirMsgQ msg_q; + tSirRetStatus ret_code = eSIR_SUCCESS; + tSirMacAddr sta_mac, *sta_Addr; + uint8_t i, nw_type_11b = 0; + tpSirAssocReq assoc_req; + tLimIbssPeerNode *peer_node; /* for IBSS mode */ + uint8_t *p2p_ie = NULL; + + sir_copy_mac_addr(sta_mac, session_entry->selfMacAddr); + + lim_log(mac_ctx, LOG1, + FL("sessionid: %d update_entry = %d limsystemrole = %d "), + session_entry->smeSessionId, update_entry, + GET_LIM_SYSTEM_ROLE(session_entry)); + + add_sta_params = cdf_mem_malloc(sizeof(tAddStaParams)); + if (NULL == add_sta_params) { + lim_log(mac_ctx, LOGP, + FL("Unable to allocate memory during ADD_STA")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set((uint8_t *) add_sta_params, sizeof(tAddStaParams), 0); + + if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_IBSS_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) + sta_Addr = &sta_ds->staAddr; +#ifdef FEATURE_WLAN_TDLS + /* SystemRole shouldn't be matter if staType is TDLS peer */ + else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) + sta_Addr = &sta_ds->staAddr; +#endif + else + sta_Addr = &sta_mac; + + lim_log(mac_ctx, LOG1, + FL(MAC_ADDRESS_STR ": Subtype(Assoc/Reassoc): %d"), + MAC_ADDR_ARRAY(*sta_Addr), sta_ds->mlmStaContext.subType); + + cdf_mem_copy((uint8_t *) add_sta_params->staMac, + (uint8_t *) *sta_Addr, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) add_sta_params->bssId, + session_entry->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(&add_sta_params->capab_info, + &sta_ds->mlmStaContext.capabilityInfo, + sizeof(add_sta_params->capab_info)); + + lim_fill_supported_rates_info(mac_ctx, sta_ds, &sta_ds->supportedRates, + session_entry); + + /* Copy legacy rates */ + cdf_mem_copy((uint8_t *) &add_sta_params->supportedRates, + (uint8_t *) &sta_ds->supportedRates, + sizeof(tSirSupportedRates)); + + add_sta_params->assocId = sta_ds->assocId; + + add_sta_params->wmmEnabled = sta_ds->qosMode; + add_sta_params->listenInterval = sta_ds->mlmStaContext.listenInterval; + add_sta_params->shortPreambleSupported = sta_ds->shortPreambleEnabled; + if (LIM_IS_AP_ROLE(session_entry) && + (sta_ds->mlmStaContext.subType == LIM_REASSOC)) { + /* + * TBD - need to remove this REASSOC check + * after fixinf rmmod issue + */ + add_sta_params->updateSta = sta_ds->mlmStaContext.updateContext; + } + sta_ds->valid = 0; + sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + + lim_log(mac_ctx, LOG2, + FL(" Assoc ID: %d wmmEnabled = %d listenInterval = %d" + " shortPreambleSupported: %d "), add_sta_params->assocId, + add_sta_params->wmmEnabled, add_sta_params->listenInterval, + add_sta_params->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 == sta_ds->staType) && (true == update_entry)) + add_sta_params->staIdx = sta_ds->staIndex; + else +#endif + add_sta_params->staIdx = STA_INVALID_IDX; + add_sta_params->staType = sta_ds->staType; + + add_sta_params->updateSta = update_entry; + + add_sta_params->status = CDF_STATUS_SUCCESS; + add_sta_params->respReqd = 1; + /* Update HT Capability */ + + if (LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry) || + LIM_IS_IBSS_ROLE(session_entry)) { + add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability; +#ifdef WLAN_FEATURE_11AC + add_sta_params->vhtCapable = + sta_ds->mlmStaContext.vhtCapability; +#endif + } +#ifdef FEATURE_WLAN_TDLS + /* SystemRole shouldn't be matter if staType is TDLS peer */ + else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { + add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability; +#ifdef WLAN_FEATURE_11AC + add_sta_params->vhtCapable = + sta_ds->mlmStaContext.vhtCapability; +#endif + } +#endif + else { + add_sta_params->htCapable = session_entry->htCapability; +#ifdef WLAN_FEATURE_11AC + add_sta_params->vhtCapable = session_entry->vhtCapability; +#endif + + } +#ifdef WLAN_FEATURE_11AC + lim_log(mac_ctx, LOG2, FL("vhtCapable: %d "), + add_sta_params->vhtCapable); +#endif + lim_log(mac_ctx, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "), + add_sta_params->staIdx, add_sta_params->updateSta, + add_sta_params->htCapable); + + add_sta_params->greenFieldCapable = sta_ds->htGreenfield; + add_sta_params->maxAmpduDensity = sta_ds->htAMpduDensity; + add_sta_params->maxAmpduSize = sta_ds->htMaxRxAMpduFactor; + add_sta_params->fDsssCckMode40Mhz = sta_ds->htDsssCckRate40MHzSupport; + add_sta_params->fShortGI20Mhz = sta_ds->htShortGI20Mhz; + add_sta_params->fShortGI40Mhz = sta_ds->htShortGI40Mhz; + add_sta_params->lsigTxopProtection = sta_ds->htLsigTXOPProtection; + add_sta_params->maxAmsduSize = sta_ds->htMaxAmsduLength; + add_sta_params->ch_width = sta_ds->htSupportedChannelWidthSet; + add_sta_params->mimoPS = sta_ds->htMIMOPSState; + + lim_log(mac_ctx, LOG2, + FL("greenFieldCapable: %d maxAmpduDensity = %d maxAmpduDensity = %d"), + add_sta_params->greenFieldCapable, + add_sta_params->maxAmpduDensity, add_sta_params->maxAmpduSize); + + lim_log(mac_ctx, LOG2, + FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d fShortGI40Mhz: %d"), + add_sta_params->fDsssCckMode40Mhz, + add_sta_params->fShortGI20Mhz, add_sta_params->fShortGI40Mhz); + + lim_log(mac_ctx, LOG2, + FL("lsigTxopProtection: %d maxAmsduSize: %d txChannelWidth: %d mimoPS: %d "), + add_sta_params->lsigTxopProtection, + add_sta_params->maxAmsduSize, add_sta_params->ch_width, + add_sta_params->mimoPS); + + if (add_sta_params->vhtCapable) { + if (sta_ds->vhtSupportedChannelWidthSet) + add_sta_params->ch_width = + sta_ds->vhtSupportedChannelWidthSet + 1; + + add_sta_params->vhtSupportedRxNss = sta_ds->vhtSupportedRxNss; + add_sta_params->vhtTxBFCapable = +#ifdef FEATURE_WLAN_TDLS + ((STA_ENTRY_PEER == sta_ds->staType) + || (STA_ENTRY_TDLS_PEER == sta_ds->staType)) ? + sta_ds->vhtBeamFormerCapable : + session_entry->txBFIniFeatureEnabled; +#else + (STA_ENTRY_PEER == sta_ds->staType) ? + sta_ds->vhtBeamFormerCapable : + session_entry->txBFIniFeatureEnabled; +#endif + add_sta_params->enable_su_tx_bformer = + sta_ds->vht_su_bfee_capable; + } + + lim_log(mac_ctx, LOGE, FL("TxChWidth %d vhtTxBFCap %d, su_bfer %d"), + add_sta_params->ch_width, add_sta_params->vhtTxBFCapable, + add_sta_params->enable_su_tx_bformer); +#ifdef FEATURE_WLAN_TDLS + if ((STA_ENTRY_PEER == sta_ds->staType) || + (STA_ENTRY_TDLS_PEER == sta_ds->staType)) +#else + if (STA_ENTRY_PEER == sta_ds->staType) +#endif + { + /* + * peer STA get the LDPC capability from sta_ds, + * which populated from + * HT/VHT capability + */ + if (add_sta_params->vhtTxBFCapable + && mac_ctx->lim.disableLDPCWithTxbfAP) { + add_sta_params->htLdpcCapable = 0; + add_sta_params->vhtLdpcCapable = 0; + } else { + add_sta_params->htLdpcCapable = sta_ds->htLdpcCapable; + add_sta_params->vhtLdpcCapable = sta_ds->vhtLdpcCapable; + } + } else if (STA_ENTRY_SELF == sta_ds->staType) { + /* For Self STA get the LDPC capability from config.ini */ + add_sta_params->htLdpcCapable = + (session_entry->txLdpcIniFeatureEnabled & 0x01); + add_sta_params->vhtLdpcCapable = + ((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01); + } + + /* Update PE session ID */ + add_sta_params->sessionId = session_entry->peSessionId; + + /* Update SME session ID */ + add_sta_params->smesessionId = session_entry->smeSessionId; + + add_sta_params->maxTxPower = session_entry->maxTxPower; + + if (session_entry->parsedAssocReq != NULL) { + uint16_t aid = sta_ds->assocId; + /* Get a copy of the already parsed Assoc Request */ + assoc_req = + (tpSirAssocReq) session_entry->parsedAssocReq[aid]; + if (assoc_req && assoc_req->addIEPresent + && assoc_req->addIE.length) { + p2p_ie = limGetP2pIEPtr(mac_ctx, + assoc_req->addIE.addIEdata, + assoc_req->addIE.length); + } + + add_sta_params->p2pCapableSta = (p2p_ie != NULL); + if (assoc_req && add_sta_params->htCapable) { + cdf_mem_copy(&add_sta_params->ht_caps, + ((uint8_t *) &assoc_req->HTCaps) + 1, + sizeof(add_sta_params->ht_caps)); + } + + if (assoc_req && add_sta_params->vhtCapable) + add_sta_params->vht_caps = + lim_populate_vht_caps(assoc_req->VHTCaps); + } else if (LIM_IS_IBSS_ROLE(session_entry)) { + + /* + * in IBSS mode, use peer node as the source of ht_caps + * and vht_caps + */ + peer_node = lim_ibss_peer_find(mac_ctx, *sta_Addr); + if (!peer_node) { + lim_log(mac_ctx, LOGP, + FL("Can't find IBSS peer node for ADD_STA")); + return eSIR_HAL_STA_DOES_NOT_EXIST; + } + + if (peer_node->atimIePresent) { + add_sta_params->atimIePresent = + peer_node->atimIePresent; + add_sta_params->peerAtimWindowLength = + peer_node->peerAtimWindowLength; + } + + add_sta_params->ht_caps = + (peer_node->htSupportedChannelWidthSet << + SIR_MAC_HT_CAP_CHWIDTH40_S) | + (peer_node->htGreenfield << + SIR_MAC_HT_CAP_GREENFIELD_S) | + (peer_node->htShortGI20Mhz << + SIR_MAC_HT_CAP_SHORTGI20MHZ_S) | + (peer_node->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) | + (peer_node->htMaxAmsduLength << + SIR_MAC_HT_CAP_MAXAMSDUSIZE_S) | + (peer_node->htDsssCckRate40MHzSupport << + SIR_MAC_HT_CAP_DSSSCCK40_S); + + add_sta_params->vht_caps = + lim_populate_vht_caps(peer_node->VHTCaps); + } +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { + add_sta_params->ht_caps = sta_ds->ht_caps; + add_sta_params->vht_caps = sta_ds->vht_caps; + + lim_log(mac_ctx, LOG1, + FL("Sta type is TDLS_PEER, ht_caps: 0x%x, vht_caps: 0x%x"), + add_sta_params->ht_caps, + add_sta_params->vht_caps); + } +#endif + +#ifdef FEATURE_WLAN_TDLS + if (sta_ds->wmeEnabled && + (LIM_IS_AP_ROLE(session_entry) || + (STA_ENTRY_TDLS_PEER == sta_ds->staType))) +#else + if (sta_ds->wmeEnabled && LIM_IS_AP_ROLE(session_entry)) +#endif + { + add_sta_params->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 + */ + add_sta_params->uAPSD |= + sta_ds->qos.capability.qosInfo.acvo_uapsd; + add_sta_params->uAPSD |= + (sta_ds->qos.capability.qosInfo.acvi_uapsd << 1); + add_sta_params->uAPSD |= + (sta_ds->qos.capability.qosInfo.acbk_uapsd << 2); + add_sta_params->uAPSD |= + (sta_ds->qos.capability.qosInfo.acbe_uapsd << 3); + /* + * making delivery enabled and + * trigger enabled setting the same. + */ + add_sta_params->uAPSD |= add_sta_params->uAPSD << 4; + + add_sta_params->maxSPLen = + sta_ds->qos.capability.qosInfo.maxSpLen; + lim_log(mac_ctx, LOG1, FL("uAPSD = 0x%x, maxSpLen = %d"), + add_sta_params->uAPSD, add_sta_params->maxSPLen); + } +#ifdef WLAN_FEATURE_11W + add_sta_params->rmfEnabled = sta_ds->rmfEnabled; + lim_log(mac_ctx, LOG1, FL("PMF enabled %d"), + add_sta_params->rmfEnabled); +#endif + + lim_log(mac_ctx, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d " + "p2pCapableSta: %d"), + add_sta_params->htLdpcCapable, add_sta_params->vhtLdpcCapable, + add_sta_params->p2pCapableSta); + + /* + * we need to defer the message until we get the + * response back from HAL. + */ + if (add_sta_params->respReqd) + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false); + + for (i = 0; i < SIR_NUM_11A_RATES; i++) { + if (sirIsArate(sta_ds->supportedRates.llaRates[i] & 0x7F)) { + nw_type_11b = 0; + break; + } else { + nw_type_11b = 1; + } + } + if (nw_type_11b) + add_sta_params->nwType = eSIR_11B_NW_TYPE; + else + add_sta_params->nwType = session_entry->nwType; + + msg_q.type = WMA_ADD_STA_REQ; + + msg_q.reserved = 0; + msg_q.bodyptr = add_sta_params; + msg_q.bodyval = 0; + + lim_log(mac_ctx, LOG1, FL("Sending WMA_ADD_STA_REQ for assocId %d"), + sta_ds->assocId); + MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId, + msg_q.type)); + + ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q); + if (eSIR_SUCCESS != ret_code) { + if (add_sta_params->respReqd) + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + lim_log(mac_ctx, LOGE, + FL("ADD_STA_REQ for aId %d failed (reason %X)"), + sta_ds->assocId, ret_code); + cdf_mem_free(add_sta_params); + } + + return ret_code; +} + +/** + * lim_del_sta() + * + ***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 +lim_del_sta(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, bool fRespReqd, tpPESession psessionEntry) +{ + tpDeleteStaParams pDelStaParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + pDelStaParams = cdf_mem_malloc(sizeof(tDeleteStaParams)); + if (NULL == pDelStaParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_STA")); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) 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 lim_del_sta 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(mac_trace + (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(mac_trace + (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; + cdf_mem_copy((uint8_t *) pDelStaParams->staMac, + (uint8_t *) pStaDs->staAddr, sizeof(tSirMacAddr)); + + pDelStaParams->status = CDF_STATUS_SUCCESS; + msgQ.type = WMA_DELETE_STA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDelStaParams; + msgQ.bodyval = 0; + + lim_log(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(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + if (fRespReqd) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + lim_log(pMac, LOGE, + FL("Posting DELETE_STA_REQ to HAL failed, reason=%X"), + retCode); + cdf_mem_free(pDelStaParams); + } + + return retCode; +} + +#if defined WLAN_FEATURE_VOWIFI_11R +/** + * lim_add_ft_sta_self()- function to add STA once we have connected with a + * new AP + * @mac_ctx: pointer to global mac structure + * @assoc_id: association id for the station connection + * @session_entry: pe session entr + * + * 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. + * + * Return: eSIR_SUCCESS on success else eSirRetStatus failure codes + */ +tSirRetStatus lim_add_ft_sta_self(tpAniSirGlobal mac_ctx, uint16_t assoc_id, + tpPESession session_entry) +{ + tpAddStaParams add_sta_params = NULL; + tSirRetStatus ret_code = eSIR_SUCCESS; + tSirMsgQ msg_q; + + add_sta_params = session_entry->ftPEContext.pAddStaReq; + add_sta_params->assocId = assoc_id; + add_sta_params->smesessionId = session_entry->smeSessionId; + + msg_q.type = WMA_ADD_STA_REQ; + msg_q.reserved = 0; + msg_q.bodyptr = add_sta_params; + msg_q.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "Sending WMA_ADD_STA_REQ (aid %d)", + add_sta_params->assocId); +#endif + MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId, + msg_q.type)); + + session_entry->limPrevMlmState = session_entry->limMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_WT_ADD_STA_RSP_STATE)); + session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q); + if (eSIR_SUCCESS != ret_code) { + lim_log(mac_ctx, LOGE, + FL("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X"), + ret_code); + cdf_mem_free(add_sta_params); + } + + session_entry->ftPEContext.pAddStaReq = NULL; + return ret_code; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/** + * lim_add_sta_self() + * + ***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 +lim_add_sta_self(tpAniSirGlobal pMac, uint16_t staIdx, uint8_t updateSta, + tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMacAddr staMac; + uint32_t listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; + uint32_t shortGi20MhzSupport; + uint32_t shortGi40MhzSupport; + uint32_t ampduLenExponent = 0; + /*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.*/ + uint32_t selfStaDot11Mode = 0, selfTxWidth = 0; + uint32_t val; + wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + lim_log(pMac, LOG1, FL("cfgDot11Mode %d"), (int)selfStaDot11Mode); + wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO_SUPPORTED_CHAN_WIDTH_SET, + &selfTxWidth); + lim_log(pMac, LOG1, FL("SGI 20 %d"), (int)selfTxWidth); + lim_log(pMac, LOG1, FL("Roam Channel Bonding Mode %d"), + (int)pMac->roam.configParam.uCfgDot11Mode); + + sir_copy_mac_addr(staMac, psessionEntry->selfMacAddr); + lim_log(pMac, LOG1, FL(MAC_ADDRESS_STR ": "), MAC_ADDR_ARRAY(staMac)); + pAddStaParams = cdf_mem_malloc(sizeof(tAddStaParams)); + if (NULL == pAddStaParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_STA")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set((uint8_t *) pAddStaParams, sizeof(tAddStaParams), 0); + + /* / Add STA context at MAC HW (BMU, RHP & TFP) */ + cdf_mem_copy((uint8_t *) pAddStaParams->staMac, + (uint8_t *) staMac, sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) pAddStaParams->bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + + pAddStaParams->assocId = psessionEntry->limAID; + pAddStaParams->staType = STA_ENTRY_SELF; + pAddStaParams->status = CDF_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_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL( + "Couldn't get SHORT_PREAMBLE, set default")); + pAddStaParams->shortPreambleSupported = 1; + } else { + pAddStaParams->shortPreambleSupported = val; + } + +#ifdef WLAN_FEATURE_11AC + lim_populate_own_rate_set(pMac, &pAddStaParams->supportedRates, NULL, false, + psessionEntry, NULL); +#else + lim_populate_own_rate_set(pMac, &pAddStaParams->supportedRates, NULL, false, + psessionEntry); +#endif + if (IS_DOT11_MODE_HT(selfStaDot11Mode)) { + pAddStaParams->htCapable = true; +#ifdef DISABLE_GF_FOR_INTEROP + if ((psessionEntry->pLimJoinReq != NULL) + && (!psessionEntry->pLimJoinReq->bssDescription. + aniIndicator)) { + lim_log(pMac, LOGE, + FL + (" Turning off Greenfield, when adding self entry")); + pAddStaParams->greenFieldCapable = + WNI_CFG_GREENFIELD_CAPABILITY_DISABLE; + } else +#endif + { + pAddStaParams->greenFieldCapable = + lim_get_ht_capability(pMac, eHT_GREENFIELD, + psessionEntry); + pAddStaParams->ch_width = + pMac->roam.configParam.channelBondingMode5GHz; + pAddStaParams->mimoPS = + lim_get_ht_capability(pMac, eHT_MIMO_POWER_SAVE, + psessionEntry); + pAddStaParams->rifsMode = + lim_get_ht_capability(pMac, eHT_RIFS_MODE, + psessionEntry); + pAddStaParams->lsigTxopProtection = + lim_get_ht_capability(pMac, eHT_LSIG_TXOP_PROTECTION, + psessionEntry); + pAddStaParams->maxAmpduDensity = + lim_get_ht_capability(pMac, eHT_MPDU_DENSITY, + psessionEntry); + pAddStaParams->maxAmpduSize = + lim_get_ht_capability(pMac, eHT_MAX_RX_AMPDU_FACTOR, + psessionEntry); + pAddStaParams->maxAmsduSize = + lim_get_ht_capability(pMac, eHT_MAX_AMSDU_LENGTH, + psessionEntry); + pAddStaParams->fDsssCckMode40Mhz = + lim_get_ht_capability(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 (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) { + if (true == shortGi20MhzSupport) { + pAddStaParams->fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STAMAX; + } else { + pAddStaParams->fShortGI20Mhz = false; + } + } else { + PELOGE(lim_log + (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 (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) { + if (true == shortGi40MhzSupport) { + pAddStaParams->fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STAMAX; + } else { + pAddStaParams->fShortGI40Mhz = false; + } + } else { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve shortGI 40Mhz" + "CFG,setting value to default")); + ) + pAddStaParams->fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + lim_log(pMac, LOG2, + FL(" greenFieldCapable: %d maxAmpduDensity = %d " + "maxAmpduSize = %d"), + pAddStaParams->greenFieldCapable, + pAddStaParams->maxAmpduDensity, + pAddStaParams->maxAmpduSize); + + lim_log(pMac, LOG2, + FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d " + "fShortGI40Mhz: %d lsigTxopProtection: %d"), + pAddStaParams->fDsssCckMode40Mhz, + pAddStaParams->fShortGI20Mhz, + pAddStaParams->fShortGI40Mhz, + pAddStaParams->lsigTxopProtection); + + lim_log(pMac, LOG2, + FL("maxAmsduSize: %d txChannelWidth: %d mimoPS: %d rifsMode %d"), + pAddStaParams->maxAmsduSize, + pAddStaParams->ch_width, + pAddStaParams->mimoPS, pAddStaParams->rifsMode); + } + } +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = IS_DOT11_MODE_VHT(selfStaDot11Mode); + if (pAddStaParams->vhtCapable) { + pAddStaParams->ch_width = + psessionEntry->ch_width; + lim_log(pMac, LOG1, FL("VHT WIDTH SET %d"), + pAddStaParams->ch_width); + } + pAddStaParams->vhtTxBFCapable = psessionEntry->txBFIniFeatureEnabled; + pAddStaParams->enable_su_tx_bformer = + psessionEntry->enable_su_tx_bformer; + lim_log(pMac, LOG2, FL("vhtCapable: %d vhtTxBFCapable %d, su_bfer %d"), + pAddStaParams->vhtCapable, pAddStaParams->vhtTxBFCapable, + pAddStaParams->enable_su_tx_bformer); + + /* In 11ac mode, the hardware is capable of supporting 128K AMPDU size */ + if (IS_DOT11_MODE_VHT(selfStaDot11Mode)) { + if (wlan_cfg_get_int + (pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &duLenExponent) + != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT")); + } + pAddStaParams->maxAmpduSize = (uint8_t) ampduLenExponent; + } + pAddStaParams->vhtTxMUBformeeCapable = psessionEntry->txMuBformee; + pAddStaParams->enableVhtpAid = psessionEntry->enableVhtpAid; +#endif + pAddStaParams->enableAmpduPs = psessionEntry->enableAmpduPs; + pAddStaParams->enableHtSmps = psessionEntry->enableHtSmps; + 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_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + pAddStaParams->listenInterval = (uint16_t) listenInterval; + + if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona) { + pAddStaParams->p2pCapableSta = 1; + } + + pAddStaParams->supportedRates.opRateMode = + lim_get_sta_rate_mode((uint8_t) selfStaDot11Mode); + + lim_log(pMac, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "), + pAddStaParams->staIdx, pAddStaParams->updateSta, + pAddStaParams->htCapable); + + lim_log(pMac, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d " + "p2pCapableSta: %d"), + pAddStaParams->htLdpcCapable, pAddStaParams->vhtLdpcCapable, + pAddStaParams->p2pCapableSta); + + if (psessionEntry->isNonRoamReassoc) { + pAddStaParams->nonRoamReassoc = 1; + psessionEntry->isNonRoamReassoc = 0; + } + lim_log(pMac, LOG2, FL("sessionid: %d Assoc ID: %d listenInterval = %d " + "shortPreambleSupported: %d"), + psessionEntry->smeSessionId, pAddStaParams->assocId, + pAddStaParams->listenInterval, + pAddStaParams->shortPreambleSupported); + + msgQ.type = WMA_ADD_STA_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pAddStaParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG1, FL(MAC_ADDRESS_STR ":Sessionid %d : " + "Sending WMA_ADD_STA_REQ. (aid %d)"), + MAC_ADDR_ARRAY(pAddStaParams->staMac), + pAddStaParams->sessionId, pAddStaParams->assocId); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + lim_log(pMac, LOGE, + FL("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X"), + retCode); + cdf_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 lim_teardown_infra_bss(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMacAddr bcAddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + /** + * Send Broadcast Disassociate frame with + * 'leaving BSS' reason. + */ + lim_send_disassoc_mgmt_frame(pMac, + eSIR_MAC_DISASSOC_LEAVING_BSS_REASON, + bcAddr, psessionEntry, false); +} /*** end lim_teardown_infra_bss() ***/ + +/** + * lim_handle_cnf_wait_timeout() + * + ***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 lim_handle_cnf_wait_timeout(tpAniSirGlobal pMac, uint16_t staId) +{ + tpDphHashNode pStaDs; + tpPESession psessionEntry = NULL; + + psessionEntry = pe_find_session_by_session_id(pMac, + pMac->lim.limTimers.gpLimCnfWaitTimer[staId].sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } + pStaDs = dph_get_hash_entry(pMac, staId, &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) { + PELOGW(lim_log + (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(lim_log + (pMac, LOGW, + FL + ("Did not receive Assoc Cnf in eLIM_MLM_WT_ASSOC_CNF_STATE sta Assoc id %d"), + pStaDs->assocId); + ) + lim_print_mac_addr(pMac, pStaDs->staAddr, LOGW); + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + lim_reject_association(pMac, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, + pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + (tSirResultCodes) + eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } + break; + + default: + lim_log(pMac, LOGW, FL("Received CNF_WAIT_TIMEOUT in state %d"), + pStaDs->mlmStaContext.mlmState); + } +} + +/** + * lim_delete_dph_hash_entry()- function to delete dph hash entry + * @mac_ctx: pointer to global mac structure + * @sta_addr: peer station address + * @sta_id: id assigned to peer station + * @session_entry: pe session entry + * + * This function is called whenever we need to delete + * the dph hash entry + * + * Return: none + */ + +void +lim_delete_dph_hash_entry(tpAniSirGlobal mac_ctx, tSirMacAddr sta_addr, + uint16_t sta_id, tpPESession session_entry) +{ + uint16_t aid; + tpDphHashNode sta_ds; + tUpdateBeaconParams beacon_params; + + cdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); + beacon_params.paramChangeBitmap = 0; + lim_deactivate_and_change_per_sta_id_timer(mac_ctx, eLIM_CNF_WAIT_TIMER, + sta_id); + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, FL("NULL session_entry")); + return; + } + + beacon_params.bssIdx = session_entry->bssIdx; + sta_ds = dph_lookup_hash_entry(mac_ctx, sta_addr, &aid, + &session_entry->dph.dphHashTable); + + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, FL("sta_ds is NULL")); + return; + } + + lim_log(mac_ctx, LOGW, FL("Deleting DPH Hash entry for STAID: %X"), + sta_id); + /* + * update the station count and perform associated actions + * do this before deleting the dph hash entry + */ + lim_util_count_sta_del(mac_ctx, sta_ds, session_entry); + + if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_IBSS_ROLE(session_entry)) { + if (LIM_IS_AP_ROLE(session_entry)) { + if (session_entry->gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_ap_protection_on_delete(mac_ctx, + sta_ds, &beacon_params, session_entry); + } + + if (LIM_IS_IBSS_ROLE(session_entry)) + lim_ibss_decide_protection_on_delete(mac_ctx, sta_ds, + &beacon_params, session_entry); + + lim_decide_short_preamble(mac_ctx, sta_ds, &beacon_params, + session_entry); + lim_decide_short_slot(mac_ctx, sta_ds, &beacon_params, + session_entry); + + /* Send message to HAL about beacon parameter change. */ + lim_log(mac_ctx, LOGW, FL("param bitmap = %d "), + beacon_params.paramChangeBitmap); + if (beacon_params.paramChangeBitmap && + (false == + mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + sch_set_fixed_beacon_fields(mac_ctx, session_entry); + lim_send_beacon_params(mac_ctx, &beacon_params, + session_entry); + } +#ifdef WLAN_FEATURE_11W + tx_timer_delete(&sta_ds->pmfSaQueryTimer); +#endif + } + + if (dph_delete_hash_entry(mac_ctx, sta_addr, sta_id, + &session_entry->dph.dphHashTable) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, FL("error deleting hash entry")); +} + +/** + * lim_check_and_announce_join_success()- function to check if the received + * Beacon/Probe Response is from the BSS that we're attempting to join. + * @mac: pointer to global mac structure + * @beacon_probe_rsp: pointer to reveived beacon/probe response frame + * @header: pointer to received management frame header + * @session_entry: pe session entry + * + * 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. + * If the Beacon/Probe Response is indeed from the BSS we're + * attempting to join, join success is sent to SME. + * + * Return: none + */ + +void +lim_check_and_announce_join_success(tpAniSirGlobal mac_ctx, + tSirProbeRespBeacon *beacon_probe_rsp, tpSirMacMgmtHdr header, + tpPESession session_entry) +{ + tSirMacSSid current_ssid; + tLimMlmJoinCnf mlm_join_cnf; + uint32_t val = 0; + uint32_t *noa_duration_from_beacon = NULL; + uint32_t *noa2_duration_from_beacon = NULL; + uint32_t noa; + uint32_t total_num_noa_desc = 0; + + cdf_mem_copy(current_ssid.ssId, + session_entry->ssId.ssId, session_entry->ssId.length); + + current_ssid.length = (uint8_t) session_entry->ssId.length; + + /* + * Check for SSID only in probe response. Beacons may not carry + * SSID information in hidden SSID case + */ + if (((SIR_MAC_MGMT_FRAME == header->fc.type) && + (SIR_MAC_MGMT_PROBE_RSP == header->fc.subType)) && + current_ssid.length && + (!cdf_mem_compare((uint8_t *) &beacon_probe_rsp->ssId, + (uint8_t *) ¤t_ssid, + (uint8_t) (1 + current_ssid.length)))) { + /* + * Received SSID does not match with the one we've. + * Ignore received Beacon frame + */ + lim_log(mac_ctx, LOG1, + FL("SSID received in Beacon does not match")); +#ifdef WLAN_DEBUG + mac_ctx->lim.gLimBcnSSIDMismatchCnt++; +#endif + return; + } + + if (!(LIM_IS_BT_AMP_STA_ROLE(session_entry) || + LIM_IS_STA_ROLE(session_entry))) + return; + + lim_log(mac_ctx, LOG1, + FL("Received Beacon/PR with matching BSSID:%pM PESessionID %d"), + session_entry->bssId, session_entry->peSessionId); + + /* Deactivate Join Failure timer */ + lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER); + /* Deactivate Periodic Join timer */ + lim_deactivate_and_change_timer(mac_ctx, + eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + + if (CDF_P2P_CLIENT_MODE == session_entry->pePersona && + beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.present) { + + noa_duration_from_beacon = (uint32_t *) + (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + 1); + + if (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.num_NoADesc) + total_num_noa_desc = + beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence. + num_NoADesc / SIZE_OF_NOA_DESCRIPTOR; + + noa = *noa_duration_from_beacon; + + if (total_num_noa_desc > 1) { + noa2_duration_from_beacon = (uint32_t *) + (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + + SIZE_OF_NOA_DESCRIPTOR + 1); + noa += *noa2_duration_from_beacon; + } + + /* + * 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_cfg_get_int(mac_ctx, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, &val) == + eSIR_SUCCESS) { + session_entry->defaultAuthFailureTimeout = val; + cfg_set_int(mac_ctx, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + val + noa); + } + } else { + session_entry->defaultAuthFailureTimeout = 0; + } + + /* Update Beacon Interval at CFG database */ + + if (beacon_probe_rsp->HTCaps.present) + lim_update_sta_run_time_ht_capability(mac_ctx, + &beacon_probe_rsp->HTCaps); + if (beacon_probe_rsp->HTInfo.present) + lim_update_sta_run_time_ht_info(mac_ctx, + &beacon_probe_rsp->HTInfo, session_entry); + session_entry->limMlmState = eLIM_MLM_JOINED_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_JOINED_STATE)); + + /* + * update the capability info based on recently received beacon/probe + * response frame + */ + session_entry->limCurrentBssCaps = + lim_get_u16((uint8_t *)&beacon_probe_rsp->capabilityInfo); + + /* + * Announce join success by sending + * Join confirm to SME. + */ + mlm_join_cnf.resultCode = eSIR_SME_SUCCESS; + mlm_join_cnf.protStatusCode = eSIR_MAC_SUCCESS_STATUS; + /* Update PE sessionId */ + mlm_join_cnf.sessionId = session_entry->peSessionId; + lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, + (uint32_t *) &mlm_join_cnf); + + if (beacon_probe_rsp->vendor2_ie.VHTCaps.present) { + session_entry->is_vendor_specific_vhtcaps = true; + session_entry->vendor_specific_vht_ie_type = + beacon_probe_rsp->vendor2_ie.type; + session_entry->vendor_specific_vht_ie_sub_type = + beacon_probe_rsp->vendor2_ie.sub_type; + lim_log(mac_ctx, LOG1, FL( + "VHT caps are present in vendor specific IE")); + } +} + +/** + * lim_extract_ap_capabilities() + * + ***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 lim_extract_ap_capability() 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 lim_extract_ap_capabilities(tpAniSirGlobal pMac, + uint8_t *pIE, + uint16_t ieLen, + tpSirProbeRespBeacon beaconStruct) +{ + cdf_mem_set((uint8_t *) beaconStruct, sizeof(tSirProbeRespBeacon), 0); + + PELOG3(lim_log(pMac, LOG3, + FL + ("In lim_extract_ap_capabilities: The IE's being received are:")); + sir_dump_buf(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 != + sir_parse_beacon_ie(pMac, beaconStruct, pIE, + (uint32_t) ieLen)) { + lim_log(pMac, LOGE, + FL("APCapExtract: Beacon parsing error!")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; +} + +/** + * lim_del_bss() + * + ***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 +lim_del_bss(tpAniSirGlobal pMac, tpDphHashNode pStaDs, uint16_t bssIdx, + tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBssParams = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + pDelBssParams = cdf_mem_malloc(sizeof(tDeleteBssParams)); + if (NULL == pDelBssParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_BSS")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set((uint8_t *) 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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + eLIM_MLM_WT_DEL_BSS_RSP_STATE)); + + if ((psessionEntry->peSessionId == + pMac->lim.limTimers.gLimJoinFailureTimer.sessionId) + && (true == + tx_timer_running(&pMac->lim.limTimers.gLimJoinFailureTimer))) { + lim_deactivate_and_change_timer(pMac, eLIM_JOIN_FAIL_TIMER); + } + + pDelBssParams->status = CDF_STATUS_SUCCESS; + pDelBssParams->respReqd = 1; + cdf_mem_copy(pDelBssParams->bssid, psessionEntry->bssId, + sizeof(tSirMacAddr)); + pDelBssParams->smesessionId = psessionEntry->smeSessionId; + PELOGW(lim_log + (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 = WMA_DELETE_BSS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pDelBssParams; + msgQ.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + lim_log(pMac, LOGE, + FL("Posting DELETE_BSS_REQ to HAL failed, reason=%X"), + retCode); + cdf_mem_free(pDelBssParams); + } + + return retCode; +} + +/** + * lim_update_vhtcaps_assoc_resp : Update VHT caps in assoc response. + * @mac_ctx Pointer to Global MAC structure + * @pAddBssParams: parameters required for add bss params. + * @vht_caps: VHT capabilities. + * @psessionEntry : session entry. + * + * Return : void + */ +void lim_update_vhtcaps_assoc_resp(tpAniSirGlobal mac_ctx, + tpAddBssParams pAddBssParams, + tDot11fIEVHTCaps *vht_caps, tpPESession psessionEntry) +{ + pAddBssParams->staContext.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)); + + pAddBssParams->staContext.maxAmpduSize = + SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( + pAddBssParams->staContext.vht_caps); + + lim_log(mac_ctx, LOG1, + FL("Updating VHT caps in assoc Response")); +} + +/** + * lim_update_vht_oper_assoc_resp : Update VHT Operations in assoc response. + * @mac_ctx Pointer to Global MAC structure + * @pAddBssParams: parameters required for add bss params. + * @vht_oper: VHT Operations to update. + * @psessionEntry : session entry. + * + * Return : void + */ +void lim_update_vht_oper_assoc_resp(tpAniSirGlobal mac_ctx, + tpAddBssParams pAddBssParams, + tDot11fIEVHTOperation *vht_oper, tpPESession psessionEntry) +{ + if (vht_oper->chanWidth && + psessionEntry->ch_width) { + pAddBssParams->ch_width = vht_oper->chanWidth + 1; + + pAddBssParams->ch_center_freq_seg0 = + vht_oper->chanCenterFreqSeg1; + + pAddBssParams->ch_center_freq_seg1 = + vht_oper->chanCenterFreqSeg2; + } + lim_log(mac_ctx, LOG1, + FL("Updating VHT Operation in assoc Response")); +} + + +/** + * 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 lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, + tpSchBeaconStruct pBeaconStruct, + tpSirBssDescription bssDescription, + uint8_t updateEntry, tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpAddBssParams pAddBssParams = NULL; + uint32_t retCode; + tpDphHashNode pStaDs = NULL; + uint8_t chanWidthSupp = 0; + uint32_t shortGi20MhzSupport; + uint32_t shortGi40MhzSupport; + uint32_t enableTxBF20MHz; + tDot11fIEVHTCaps *vht_caps = NULL; + tDot11fIEVHTOperation *vht_oper = NULL; + tAddStaParams *sta_context; + + /* Package SIR_HAL_ADD_BSS_REQ message parameters */ + pAddBssParams = cdf_mem_malloc(sizeof(tAddBssParams)); + if (NULL == pAddBssParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_BSS")); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } else + cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams), + 0); + + cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, + sizeof(tSirMacAddr)); + /* Fill in tAddBssParams selfMacAddr */ + cdf_mem_copy(pAddBssParams->selfMacAddr, + psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + + lim_log(pMac, LOG1, + FL("sessionid: %d updateEntry = %d limsystemrole = %d "), + psessionEntry->smeSessionId, updateEntry, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + lim_log(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; + cdf_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 = + (uint8_t) pAssocRsp->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = + (uint8_t) psessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = + (uint8_t) psessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = + (uint8_t) psessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = + (uint8_t) psessionEntry->beaconParams.ht20Coexist; + + lim_log(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d " + "cfpCount: %d"), pAddBssParams->bssType, + pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod, + pAddBssParams->cfParamSet.cfpCount); + + lim_log(pMac, LOG2, + FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:" + " %d numRates: %d "), pAddBssParams->cfParamSet.cfpPeriod, + pAddBssParams->cfParamSet.cfpMaxDuration, + pAddBssParams->cfParamSet.cfpDurRemaining, + pAddBssParams->rateSet.numRates); + + lim_log(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; + lim_log(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; + lim_log(pMac, LOG2, FL("htCapable: %d"), + pAddBssParams->htCapable); + if (pBeaconStruct->HTInfo.present) { + pAddBssParams->htOperMode = + (tSirMacHTOperatingMode) pAssocRsp->HTInfo.opMode; + pAddBssParams->dualCTSProtection = + (uint8_t) pAssocRsp->HTInfo.dualCTSProtection; + chanWidthSupp = + lim_get_ht_capability(pMac, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, + psessionEntry); + if ((pAssocRsp->HTCaps.supportedChannelWidthSet) + && (chanWidthSupp)) { + pAddBssParams->ch_width = (uint8_t) + pAssocRsp->HTInfo.recommendedTxWidthSet; + if (pAssocRsp->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId + 2; + else if (pAssocRsp->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId - 2; + } else { + pAddBssParams->ch_width = CH_WIDTH_20MHZ; + pAddBssParams->ch_center_freq_seg0 = 0; + } + pAddBssParams->llnNonGFCoexist = + (uint8_t) pAssocRsp->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = + (uint8_t) pAssocRsp->HTInfo. + lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = pAssocRsp->HTInfo.rifsMode; + + lim_log(pMac, LOGE, + FL("htOperMode: %d dualCTSProtection: %d txChannelWidth: %d center_freq_0: %d "), + pAddBssParams->htOperMode, + pAddBssParams->dualCTSProtection, + pAddBssParams->ch_width, + pAddBssParams->ch_center_freq_seg0); + + lim_log(pMac, LOG2, FL("llnNonGFCoexist: %d " + "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"), + pAddBssParams->llnNonGFCoexist, + pAddBssParams->fLsigTXOPProtectionFullSupport, + pAddBssParams->fRIFSMode); + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + lim_log(pMac, LOGE, FL("currentOperChannel %d"), + pAddBssParams->currentOperChannel); + if (psessionEntry->vhtCapability && (pAssocRsp->VHTCaps.present)) { + pAddBssParams->vhtCapable = pAssocRsp->VHTCaps.present; + vht_caps = &pAssocRsp->VHTCaps; + vht_oper = &pAssocRsp->VHTOperation; + } else if (psessionEntry->vhtCapability && + pAssocRsp->vendor2_ie.VHTCaps.present){ + pAddBssParams->vhtCapable = + pAssocRsp->vendor2_ie.VHTCaps.present; + lim_log(pMac, LOG1, + FL("VHT Caps and Operation are present in vendor Specfic IE")); + vht_caps = &pAssocRsp->vendor2_ie.VHTCaps; + vht_oper = &pAssocRsp->vendor2_ie.VHTOperation; + } else { + pAddBssParams->vhtCapable = 0; + } + if (pAddBssParams->vhtCapable) { + if (vht_oper != NULL) + lim_update_vht_oper_assoc_resp(pMac, pAddBssParams, + vht_oper, psessionEntry); + if (vht_caps != NULL) + lim_update_vhtcaps_assoc_resp(pMac, pAddBssParams, + vht_caps, psessionEntry); + } + + lim_log(pMac, LOGE, FL("vhtCapable %d TxChannelWidth %d center_freq_0 %d center_freq_1 %d"), + pAddBssParams->vhtCapable, pAddBssParams->ch_width, + pAddBssParams->ch_center_freq_seg0, + pAddBssParams->ch_center_freq_seg1); + + /* + * Populate the STA-related parameters here + * Note that the STA here refers to the AP + * staType = PEER + */ + sta_context = &pAddBssParams->staContext; + /* Identifying AP as an STA */ + pAddBssParams->staContext.staType = STA_ENTRY_OTHER; + + cdf_mem_copy(pAddBssParams->staContext.bssId, + bssDescription->bssId, sizeof(tSirMacAddr)); + pAddBssParams->staContext.listenInterval = + bssDescription->beaconInterval; + + /* Fill Assoc id from the dph table */ + pStaDs = dph_lookup_hash_entry(pMac, pAddBssParams->staContext.bssId, + &pAddBssParams->staContext.assocId, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + lim_log(pMac, LOGE, FL( + "Couldn't get assoc id for " "MAC ADDR: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY( + pAddBssParams->staContext.staMac)); + return eSIR_FAILURE; + } + + pAddBssParams->staContext.uAPSD = + psessionEntry->gUapsdPerAcBitmask; + + pAddBssParams->staContext.maxSPLen = 0; + pAddBssParams->staContext.shortPreambleSupported = + (uint8_t) pAssocRsp->capabilityInfo.shortPreamble; + pAddBssParams->staContext.updateSta = updateEntry; + + lim_log(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 = + (uint8_t) pAssocRsp->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = + (uint8_t) pAssocRsp->HTCaps.lsigTXOPProtection; + lim_log(pMac, LOG2, FL( + "StaCtx: htCap %d GFcap %d lsigTxopProtn %d"), + pAddBssParams->staContext.htCapable, + pAddBssParams->staContext.greenFieldCapable, + pAddBssParams->staContext.lsigTxopProtection); + if (psessionEntry->vhtCapability && + (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || + IS_BSS_VHT_CAPABLE( + pBeaconStruct->vendor2_ie.VHTCaps))) { + pAddBssParams->staContext.vhtCapable = 1; + pAddBssParams->staContext.vhtSupportedRxNss = + pStaDs->vhtSupportedRxNss; + if (pAssocRsp->VHTCaps.present) + vht_caps = &pAssocRsp->VHTCaps; + else if (pAssocRsp->vendor2_ie.VHTCaps.present) { + vht_caps = &pAssocRsp->vendor2_ie.VHTCaps; + lim_log(pMac, LOG1, FL( + "VHT Caps are in vendor Specfic IE")); + } + + if ((vht_caps != NULL) && (vht_caps->suBeamFormerCap || + vht_caps->muBeamformerCap) && + psessionEntry->txBFIniFeatureEnabled) + sta_context->vhtTxBFCapable = 1; + + if ((vht_caps != NULL) && vht_caps->muBeamformerCap && + psessionEntry->txMuBformee) + sta_context->vhtTxMUBformeeCapable = 1; + if ((vht_caps != NULL) && vht_caps->suBeamformeeCap && + psessionEntry->enable_su_tx_bformer) + sta_context->enable_su_tx_bformer = 1; + } + + if ((pAssocRsp->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + pAddBssParams->staContext.ch_width = (uint8_t) + pAssocRsp->HTInfo.recommendedTxWidthSet; + if (pAssocRsp->VHTCaps.present) + vht_oper = &pAssocRsp->VHTOperation; + else if (pAssocRsp->vendor2_ie.VHTCaps.present) { + vht_oper = &pAssocRsp->vendor2_ie.VHTOperation; + lim_log(pMac, LOG1, FL( + "VHT Op IE is in vendor Specfic IE")); + } + if ((vht_oper != NULL) && + pAddBssParams->staContext.vhtCapable && + vht_oper->chanWidth) + pAddBssParams->staContext.ch_width = + vht_oper->chanWidth + 1; + + lim_log(pMac, LOGE, FL( + "StaCtx: vhtCap %d ChBW %d TxBF %d"), + pAddBssParams->staContext.vhtCapable, + pAddBssParams->staContext.ch_width, + sta_context->vhtTxBFCapable); + lim_log(pMac, LOGE, FL("StaContext su_tx_bfer %d"), + sta_context->enable_su_tx_bformer); + } else { + sta_context->ch_width = CH_WIDTH_20MHZ; + if ((IS_SIR_STATUS_SUCCESS( + wlan_cfg_get_int(pMac, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + &enableTxBF20MHz))) && + (false == enableTxBF20MHz)) + sta_context->vhtTxBFCapable = 0; + } + pAddBssParams->staContext.mimoPS = + (tSirMacHTMIMOPowerSaveState) + pAssocRsp->HTCaps.mimoPowerSave; + pAddBssParams->staContext.maxAmsduSize = + (uint8_t) pAssocRsp->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = + pAssocRsp->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = + (uint8_t) 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 (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) { + if (true == shortGi20MhzSupport) { + pAddBssParams->staContext. + fShortGI20Mhz = + (uint8_t) pAssocRsp->HTCaps. + shortGI20MHz; + } else { + pAddBssParams->staContext. + fShortGI20Mhz = false; + } + } else { + lim_log(pMac, LOGE, FL( + "failed to get shortGI 20Mhz, set default")); + pAddBssParams->staContext.fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) { + if (true == shortGi40MhzSupport) { + pAddBssParams->staContext. + fShortGI40Mhz = + (uint8_t) pAssocRsp->HTCaps. + shortGI40MHz; + } else { + pAddBssParams->staContext. + fShortGI40Mhz = false; + } + } else { + lim_log(pMac, LOGE, FL( + "failed to get shortGI 40Mhz, set default")); + pAddBssParams->staContext.fShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STADEF; + } + + if (!pAddBssParams->staContext.vhtCapable) + /* Use max ampd factor advertised in + * HTCAP for non-vht connection */ + { + 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 { + pAddBssParams->staContext.htLdpcCapable = + (uint8_t) pAssocRsp->HTCaps.advCodingCap; + if (pAssocRsp->VHTCaps.present) + vht_caps = &pAssocRsp->VHTCaps; + else if (pAssocRsp->vendor2_ie.VHTCaps.present) { + vht_caps = &pAssocRsp->vendor2_ie.VHTCaps; + lim_log(pMac, LOG1, FL( + "VHT Caps is in vendor Specfic IE")); + } + if (vht_caps != NULL) + pAddBssParams->staContext.vhtLdpcCapable = + (uint8_t) vht_caps->ldpcCodingCap; + } + + if (pBeaconStruct->HTInfo.present) + pAddBssParams->staContext.rifsMode = + pAssocRsp->HTInfo.rifsMode; + + lim_log(pMac, LOGE, FL( + "StaCtx: ChBW %d mimoPS %d maxAmsduSize %d"), + pAddBssParams->staContext.ch_width, + pAddBssParams->staContext.mimoPS, + pAddBssParams->staContext.maxAmsduSize); + + lim_log(pMac, LOG2, FL( + "maxAmpduDens %d CckMode40Mhz %d SGI20Mhz %d"), + pAddBssParams->staContext.maxAmpduDensity, + pAddBssParams->staContext.fDsssCckMode40Mhz, + pAddBssParams->staContext.fShortGI20Mhz); + + lim_log(pMac, LOG2, FL( + "SGI40M %d maxAmpdu %d htLdpc %d vhtLdpc %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; + cdf_mem_copy(&pAddBssParams->staContext.capab_info, + &pAssocRsp->capabilityInfo, + sizeof(pAddBssParams->staContext.capab_info)); + cdf_mem_copy(&pAddBssParams->staContext.ht_caps, + (uint8_t *) &pAssocRsp->HTCaps + sizeof(uint8_t), + 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 = dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) { + lim_fill_supported_rates_info(pMac, pStaDs, + &pStaDs->supportedRates, + psessionEntry); + cdf_mem_copy((uint8_t *) &pAddBssParams->staContext. + supportedRates, + (uint8_t *) &pStaDs->supportedRates, + sizeof(tSirSupportedRates)); + } else + lim_log(pMac, LOGE, FL( + "could not Update the supported rates")); + pAddBssParams->staContext.encryptType = psessionEntry->encryptType; + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = psessionEntry->maxTxPower; + lim_log(pMac, LOG2, FL("maxTxPower: %d"), pAddBssParams->maxTxPower); +#endif + /* FIXME_GEN4 - Any other value that can be used for initialization? */ + pAddBssParams->status = CDF_STATUS_SUCCESS; + pAddBssParams->respReqd = true; + /* update persona */ + pAddBssParams->halPersona = (uint8_t) psessionEntry->pePersona; + + if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona) + pAddBssParams->staContext.p2pCapableSta = 1; + + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; + +#if defined WLAN_FEATURE_VOWIFI_11R + pAddBssParams->extSetStaKeyParamValid = 0; + lim_log(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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + psessionEntry->limMlmState)); + + lim_log(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d " + "p2pCapableSta: %d"), + pAddBssParams->staContext.wmmEnabled, + pAddBssParams->staContext.encryptType, + pAddBssParams->staContext.p2pCapableSta); + + lim_log(pMac, LOG2, FL("bSpectrumMgtEnabled: %d halPersona: %d setting " + "LimMlm state to %d"), + pAddBssParams->bSpectrumMgtEnabled, pAddBssParams->halPersona, + psessionEntry->limMlmState); + if (psessionEntry->isNonRoamReassoc) + pAddBssParams->nonRoamReassoc = 1; + pAddBssParams->nss = psessionEntry->nss; + lim_log(pMac, LOG2, FL("nss value: %d"), pAddBssParams->nss); + + /* we need to defer the message until we get the response back from HAL. */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = WMA_ADD_BSS_REQ; + /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/ + msgQ.reserved = 0; + msgQ.bodyptr = pAddBssParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG1, FL("SessionId:%d Sending WMA_ADD_BSS_REQ"), + psessionEntry->peSessionId); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + cdf_mem_free(pAddBssParams); + lim_log(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 lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t updateEntry, + tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpAddBssParams pAddBssParams = NULL; + uint32_t retCode; + tSchBeaconStruct *pBeaconStruct; + uint8_t chanWidthSupp = 0; + uint32_t shortGi20MhzSupport; + uint32_t shortGi40MhzSupport; + tDot11fIEVHTOperation *vht_oper = NULL; + tDot11fIEVHTCaps *vht_caps = NULL; + + tpSirBssDescription bssDescription = + &psessionEntry->pLimJoinReq->bssDescription; + + pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { + lim_log(pMac, LOGE, + FL("Unable to allocate memory during ADD_BSS")); + return eSIR_MEM_ALLOC_FAILED; + } + + /* Package SIR_HAL_ADD_BSS_REQ message parameters */ + pAddBssParams = cdf_mem_malloc(sizeof(tAddBssParams)); + if (NULL == pAddBssParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_BSS")); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + + cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams), 0); + + lim_extract_ap_capabilities(pMac, (uint8_t *) bssDescription->ieFields, + lim_get_ielen_from_bss_description(bssDescription), + pBeaconStruct); + + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection_on_assoc(pMac, pBeaconStruct, + psessionEntry); + cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, + sizeof(tSirMacAddr)); + + /* Fill in tAddBssParams selfMacAddr */ + cdf_mem_copy(pAddBssParams->selfMacAddr, + psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + lim_log(pMac, LOG1, + FL("sessionid: %d updateEntry = %d limsystemrole = %d "), + psessionEntry->smeSessionId, updateEntry, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + + lim_log(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; + cdf_mem_copy(pAddBssParams->rateSet.rate, + pBeaconStruct->supportedRates.rate, + pBeaconStruct->supportedRates.numRates); + + pAddBssParams->nwType = bssDescription->nwType; + + pAddBssParams->shortSlotTimeSupported = + (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = + (uint8_t) psessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = + (uint8_t) psessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = + (uint8_t) psessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = + (uint8_t) psessionEntry->beaconParams.ht20Coexist; + + lim_log(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d " + "cfpCount: %d"), pAddBssParams->bssType, + pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod, + pAddBssParams->cfParamSet.cfpCount); + + lim_log(pMac, LOG2, + FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:" + " %d numRates: %d "), pAddBssParams->cfParamSet.cfpPeriod, + pAddBssParams->cfParamSet.cfpMaxDuration, + pAddBssParams->cfParamSet.cfpDurRemaining, + pAddBssParams->rateSet.numRates); + + lim_log(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; + lim_log(pMac, LOG2, FL("htCapable: %d"), + pAddBssParams->htCapable); + if (pBeaconStruct->HTInfo.present) { + pAddBssParams->htOperMode = + (tSirMacHTOperatingMode) pBeaconStruct->HTInfo. + opMode; + pAddBssParams->dualCTSProtection = + (uint8_t) pBeaconStruct->HTInfo.dualCTSProtection; + + chanWidthSupp = + lim_get_ht_capability(pMac, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, + psessionEntry); + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) + && (chanWidthSupp)) { + pAddBssParams->ch_width = + (uint8_t) pBeaconStruct->HTInfo. + recommendedTxWidthSet; + if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId + 2; + + if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId - 2; + } else { + pAddBssParams->ch_width = CH_WIDTH_20MHZ; + pAddBssParams->ch_center_freq_seg0 = 0; + } + pAddBssParams->llnNonGFCoexist = + (uint8_t) pBeaconStruct->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = + (uint8_t) pBeaconStruct->HTInfo. + lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = + pBeaconStruct->HTInfo.rifsMode; + + lim_log(pMac, LOG2, + FL("htOperMode: %d dualCTSProtection: %d txChannelWidthSet: %d center_freq_seg0: %d "), + pAddBssParams->htOperMode, + pAddBssParams->dualCTSProtection, + pAddBssParams->txChannelWidthSet, + pAddBssParams->ch_center_freq_seg0); + + lim_log(pMac, LOG2, FL("llnNonGFCoexist: %d " + "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"), + pAddBssParams->llnNonGFCoexist, + pAddBssParams->fLsigTXOPProtectionFullSupport, + pAddBssParams->fRIFSMode); + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + lim_log(pMac, LOG2, FL("currentOperChannel %d"), + pAddBssParams->currentOperChannel); +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && + (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || + IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor2_ie.VHTCaps))) { + + pAddBssParams->vhtCapable = 1; + if (pBeaconStruct->VHTOperation.present) + vht_oper = &pBeaconStruct->VHTOperation; + else if (pBeaconStruct->vendor2_ie.VHTOperation.present) { + vht_oper = &pBeaconStruct->vendor2_ie.VHTOperation; + lim_log(pMac, LOG1, + FL("VHT Operation is present in vendor Specfic IE")); + } + + + if ((vht_oper != NULL) && + vht_oper->chanWidth && + chanWidthSupp) { + pAddBssParams->ch_width = + vht_oper->chanWidth + 1; + pAddBssParams->ch_center_freq_seg0 = + vht_oper->chanCenterFreqSeg1; + pAddBssParams->ch_center_freq_seg1 = + vht_oper->chanCenterFreqSeg2; + } + pAddBssParams->staContext.maxAmpduSize = + SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( + pAddBssParams->staContext.vht_caps); + } else { + pAddBssParams->vhtCapable = 0; + } + lim_log(pMac, LOGE, FL("vhtCapable %d vhtTxChannelWidthSet %d center_freq_seg0 - %d, center_freq_seg1 - %d"), + pAddBssParams->vhtCapable, pAddBssParams->ch_width, + pAddBssParams->ch_center_freq_seg0, + pAddBssParams->ch_center_freq_seg1); +#endif + + /* + * Populate the STA-related parameters here + * Note that the STA here refers to the AP + */ + /* Identifying AP as an STA */ + pAddBssParams->staContext.staType = STA_ENTRY_OTHER; + + cdf_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 = + (uint8_t) pBeaconStruct->capabilityInfo.shortPreamble; + pAddBssParams->staContext.updateSta = updateEntry; + + lim_log(pMac, LOG2, FL( + "StaCtx: " MAC_ADDRESS_STR " shortPreamble: %d"), + MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac), + pAddBssParams->staContext.shortPreambleSupported); + + pAddBssParams->dot11_mode = psessionEntry->dot11mode; + lim_log(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 = + (uint8_t) pBeaconStruct->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = + (uint8_t) pBeaconStruct->HTCaps.lsigTXOPProtection; + lim_log(pMac, LOG2, FL( + "StaCtx: htCap %d GFCap %d lsigTxopProtn %d"), + pAddBssParams->staContext.htCapable, + pAddBssParams->staContext.greenFieldCapable, + pAddBssParams->staContext.lsigTxopProtection); + if (psessionEntry->vhtCapability && + (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || + IS_BSS_VHT_CAPABLE( + pBeaconStruct->vendor2_ie.VHTCaps))) { + pAddBssParams->staContext.vhtCapable = 1; + if (pBeaconStruct->VHTCaps.present) + vht_caps = &pBeaconStruct->VHTCaps; + else if (pBeaconStruct->vendor2_ie.VHTCaps.present) + vht_caps = &pBeaconStruct->vendor2_ie.VHTCaps; + + if ((vht_caps != NULL) && (vht_caps->suBeamFormerCap || + vht_caps->muBeamformerCap) && + psessionEntry->txBFIniFeatureEnabled) + pAddBssParams->staContext.vhtTxBFCapable = 1; + + if ((vht_caps != NULL) && vht_caps->muBeamformerCap && + psessionEntry->txMuBformee) + pAddBssParams->staContext.vhtTxMUBformeeCapable + = 1; + if ((vht_caps != NULL) && vht_caps->suBeamformeeCap && + psessionEntry->enable_su_tx_bformer) + pAddBssParams->staContext.enable_su_tx_bformer + = 1; + lim_log(pMac, LOG2, FL("StaContext: su_tx_bfer %d"), + pAddBssParams->staContext.enable_su_tx_bformer); + } + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + pAddBssParams->staContext.ch_width = + (uint8_t) pBeaconStruct->HTInfo. + recommendedTxWidthSet; + if ((vht_oper != NULL) && + pAddBssParams->staContext.vhtCapable && + vht_oper->chanWidth) + pAddBssParams->staContext.ch_width = + vht_oper->chanWidth + 1; + lim_log(pMac, LOG2, FL( + "StaCtx: vhtCap %d ch_bw %d TxBF %d"), + pAddBssParams->staContext.vhtCapable, + pAddBssParams->staContext.ch_width, + pAddBssParams->staContext. + vhtTxBFCapable); + } else { + pAddBssParams->staContext.ch_width = + CH_WIDTH_20MHZ; + } + pAddBssParams->staContext.mimoPS = + (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps. + mimoPowerSave; + pAddBssParams->staContext.maxAmsduSize = + (uint8_t) pBeaconStruct->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = + pBeaconStruct->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = + (uint8_t) 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 (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_20MHZ, + &shortGi20MhzSupport))) { + if (true == shortGi20MhzSupport) + pAddBssParams->staContext.fShortGI20Mhz = + (uint8_t)pBeaconStruct->HTCaps.shortGI20MHz; + else + pAddBssParams->staContext.fShortGI20Mhz = + false; + } else { + lim_log(pMac, LOGE, FL( + "get shortGI 20Mhz failed, set default")); + pAddBssParams->staContext.fShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int + (pMac, WNI_CFG_SHORT_GI_40MHZ, + &shortGi40MhzSupport))) { + if (true == shortGi40MhzSupport) { + pAddBssParams->staContext. + fShortGI40Mhz = + (uint8_t) pBeaconStruct->HTCaps. + shortGI40MHz; + } else { + pAddBssParams->staContext. + fShortGI40Mhz = false; + } + } else { + lim_log(pMac, LOGE, FL( + "get shortGI 40Mhz failed, set 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 { + pAddBssParams->staContext.htLdpcCapable = + (uint8_t) pBeaconStruct->HTCaps. + advCodingCap; + if (pBeaconStruct->VHTCaps.present) + vht_caps = &pBeaconStruct->VHTCaps; + else if (pBeaconStruct->vendor2_ie.VHTCaps.present) { + vht_caps = + &pBeaconStruct->vendor2_ie.VHTCaps; + lim_log(pMac, LOG1, FL( + "VHT Caps are in vendor Specfic IE")); + } + if (vht_caps != NULL) + pAddBssParams->staContext.vhtLdpcCapable = + (uint8_t) vht_caps->ldpcCodingCap; + } + + if (pBeaconStruct->HTInfo.present) + pAddBssParams->staContext.rifsMode = + pBeaconStruct->HTInfo.rifsMode; + lim_log(pMac, LOG2, + FL("StaContext ChannelWidth: %d mimoPS: %d maxAmsduSize: %d"), + pAddBssParams->staContext.ch_width, + pAddBssParams->staContext.mimoPS, + pAddBssParams->staContext.maxAmsduSize); + + lim_log(pMac, LOG2, FL( + "maxAmpduDensity %d Cck40Mhz %d SGI20Mhz %d"), + pAddBssParams->staContext.maxAmpduDensity, + pAddBssParams->staContext.fDsssCckMode40Mhz, + pAddBssParams->staContext.fShortGI20Mhz); + + lim_log(pMac, LOG2, FL( + "SGI40M %d maxAmpdu %d htLdpc %d vhtLdpc %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 + lim_populate_peer_rate_set(pMac, + &pAddBssParams->staContext. + supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, + false, psessionEntry, + &pBeaconStruct->VHTCaps); +#else + lim_populate_peer_rate_set(pMac, + &pAddBssParams->staContext. + supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, + false, psessionEntry); +#endif + lim_fill_supported_rates_info(pMac, NULL, + &pAddBssParams->staContext. + supportedRates, psessionEntry); + + + pAddBssParams->staContext.encryptType = psessionEntry->encryptType; + +#if defined WLAN_FEATURE_VOWIFI + pAddBssParams->maxTxPower = psessionEntry->maxTxPower; + lim_log(pMac, LOG2, FL("maxTxPower: %d"), pAddBssParams->maxTxPower); +#endif + + pAddBssParams->status = CDF_STATUS_SUCCESS; + pAddBssParams->respReqd = true; + + pAddBssParams->staContext.smesessionId = psessionEntry->smeSessionId; + pAddBssParams->staContext.sessionId = psessionEntry->peSessionId; + pAddBssParams->sessionId = psessionEntry->peSessionId; + + pAddBssParams->halPersona = (uint8_t) psessionEntry->pePersona; /* update persona */ + + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; + +#if defined WLAN_FEATURE_VOWIFI_11R + pAddBssParams->extSetStaKeyParamValid = 0; + lim_log(pMac, LOG2, FL("extSetStaKeyParamValid: %d"), + pAddBssParams->extSetStaKeyParamValid); +#endif + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) { + pAddBssParams->rmfEnabled = 1; + pAddBssParams->staContext.rmfEnabled = 1; + } +#endif + + pAddBssParams->nss = psessionEntry->nss; + lim_log(pMac, LOG2, FL("nss value: %d"), pAddBssParams->nss); + + /* Set a new state for MLME */ + psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; + + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + psessionEntry->limMlmState)); + + lim_log(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d " + "p2pCapableSta: %d"), + pAddBssParams->staContext.wmmEnabled, + pAddBssParams->staContext.encryptType, + pAddBssParams->staContext.p2pCapableSta); + + lim_log(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 = WMA_ADD_BSS_REQ; + /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/ + msgQ.reserved = 0; + msgQ.bodyptr = pAddBssParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG1, FL("SessionId:%d Sending WMA_ADD_BSS_REQ"), + psessionEntry->peSessionId); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + cdf_mem_free(pAddBssParams); + lim_log(pMac, LOGE, + FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), + retCode); + goto returnFailure; + + } else { + cdf_mem_free(pBeaconStruct); + return retCode; + } + +returnFailure: + /* Clean-up will be done by the caller... */ + cdf_mem_free(pBeaconStruct); + return retCode; +} + +/** + * lim_prepare_and_send_del_sta_cnf() - prepares and send del sta cnf + * + * @pMac: mac global context + * @pStaDs: sta dph node + * @statusCode: status code + * @psessionEntry: session context + * + * deletes DPH entry, changes the MLM mode for station, calls + * lim_send_del_sta_cnf + * + * Return: void + */ +void +lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tSirResultCodes statusCode, + tpPESession psessionEntry) +{ + uint16_t staDsAssocId = 0; + tSirMacAddr staDsAddr; + tLimMlmStaContext mlmStaContext; + + if (pStaDs == NULL) { + PELOGW(lim_log(pMac, LOGW, FL("pStaDs is NULL"));) + return; + } + staDsAssocId = pStaDs->assocId; + cdf_mem_copy((uint8_t *) staDsAddr, + pStaDs->staAddr, sizeof(tSirMacAddr)); + + mlmStaContext = pStaDs->mlmStaContext; + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry); + } + lim_delete_dph_hash_entry(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(mac_trace(pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + psessionEntry->limMlmState)); + } + lim_send_del_sta_cnf(pMac, staDsAddr, staDsAssocId, mlmStaContext, + statusCode, psessionEntry); +} + +/** ------------------------------------------------------------- + \fn lim_get_sta_rate_mode + \brief Gets the Station Rate Mode. + \param uint8_t dot11Mode + \return none + -------------------------------------------------------------*/ +tStaRateMode lim_get_sta_rate_mode(uint8_t 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 lim_init_pre_auth_timer_table + \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 lim_init_pre_auth_timer_table(tpAniSirGlobal pMac, + tpLimPreAuthTable pPreAuthTimerTable) +{ + uint32_t cfgValue; + uint32_t authNodeIdx; + tpLimPreAuthNode pAuthNode = pPreAuthTimerTable->pTable; + + /* Get AUTH_RSP Timers value */ + + if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) { + /* + ** Could not get AUTH_RSP timeout value + ** from CFG. Log error. + **/ + lim_log(pMac, LOGP, + FL("could not retrieve AUTH_RSP timeout value")); + return; + } + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + for (authNodeIdx = 0; authNodeIdx < pPreAuthTimerTable->numEntry; + authNodeIdx++, pAuthNode++) { + if (tx_timer_create + (&pAuthNode->timer, "AUTH RESPONSE TIMEOUT", + lim_auth_response_timer_handler, authNodeIdx, cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) { + /* Cannot create timer. Log error. */ + lim_log(pMac, LOGP, + FL("Cannot create Auth Rsp timer of Index :%d."), + authNodeIdx); + return; + } + pAuthNode->authNodeIdx = (uint8_t) authNodeIdx; + pAuthNode->fFree = 1; + } + +} + +/** ------------------------------------------------------------- + \fn lim_acquire_free_pre_auth_node + \brief Retrives a free Pre Auth node from Pre Auth Table. + \param tpAniSirGlobal pMac + \param tpLimPreAuthTable pPreAuthTimerTable + \return none + -------------------------------------------------------------*/ +tLimPreAuthNode *lim_acquire_free_pre_auth_node(tpAniSirGlobal pMac, + tpLimPreAuthTable pPreAuthTimerTable) +{ + uint32_t i; + tLimPreAuthNode *pTempNode = pPreAuthTimerTable->pTable; + for (i = 0; i < pPreAuthTimerTable->numEntry; i++, pTempNode++) { + if (pTempNode->fFree == 1) { + pTempNode->fFree = 0; + return pTempNode; + } + } + + return NULL; +} + +/** ------------------------------------------------------------- + \fn lim_get_pre_auth_node_from_index + \brief Depending on the Index this retrives the pre auth node. + \param tpAniSirGlobal pMac + \param tpLimPreAuthTable pAuthTable + \param uint32_t authNodeIdx + \return none + -------------------------------------------------------------*/ +tLimPreAuthNode *lim_get_pre_auth_node_from_index(tpAniSirGlobal pMac, + tpLimPreAuthTable pAuthTable, + uint32_t authNodeIdx) +{ + if ((authNodeIdx >= pAuthTable->numEntry) + || (pAuthTable->pTable == NULL)) { + lim_log(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 lim_is_dot11h_supported_channels_valid(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 lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac, + tSirAssocReq *assoc, + tpPESession psessionEntry) +{ + tPowerdBm localMaxTxPower; + uint32_t localPwrConstraint; + + localMaxTxPower = + cfg_get_regulatory_max_transmit_power(pMac, + psessionEntry->currentOperChannel); + + if (wlan_cfg_get_int + (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, + &localPwrConstraint) != eSIR_SUCCESS) { + lim_log(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) { + lim_log(pMac, LOGW, + FL("minTxPower (STA) = %d, localMaxTxPower (AP) = %d"), + assoc->powerCapability.minTxPower, localMaxTxPower); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_fill_rx_highest_supported_rate + \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 uint8_t* pSupportedMCSSet + \return none + -------------------------------------------------------------*/ +void lim_fill_rx_highest_supported_rate(tpAniSirGlobal pMac, + uint16_t *rxHighestRate, + uint8_t *pSupportedMCSSet) +{ + tSirMacRxHighestSupportRate *pRxHighestRate; + uint8_t *pBuf; + uint16_t rate = 0; + + pBuf = pSupportedMCSSet + MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET; + rate = lim_get_u16(pBuf); + + pRxHighestRate = (tSirMacRxHighestSupportRate *) &rate; + *rxHighestRate = pRxHighestRate->rate; + + return; +} + +#ifdef WLAN_FEATURE_11W +/** ------------------------------------------------------------- + \fn lim_send_sme_unprotected_mgmt_frame_ind + \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 lim_send_sme_unprotected_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, + uint8_t *frame, uint32_t frameLen, + uint16_t sessionId, + tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeUnprotMgmtFrameInd *pSirSmeMgmtFrame = NULL; + uint16_t length; + + length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen; + + pSirSmeMgmtFrame = cdf_mem_malloc(length); + if (NULL == pSirSmeMgmtFrame) { + lim_log(pMac, LOGP, + FL + ("AllocateMemory failed for tSirSmeUnprotectedMgmtFrameInd")); + return; + } + cdf_mem_set((void *)pSirSmeMgmtFrame, length, 0); + + pSirSmeMgmtFrame->sessionId = sessionId; + pSirSmeMgmtFrame->frameType = frameType; + + cdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); + pSirSmeMgmtFrame->frameLen = frameLen; + + mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND; + mmhMsg.bodyptr = pSirSmeMgmtFrame; + mmhMsg.bodyval = 0; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** ------------------------------------------------------------- + \fn lim_send_sme_tsm_ie_ind + \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 lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t tid, uint8_t state, uint16_t measInterval) +{ + tSirMsgQ mmhMsg; + tpSirSmeTsmIEInd pSirSmeTsmIeInd = NULL; + + if (!pMac || !psessionEntry) + return; + + pSirSmeTsmIeInd = cdf_mem_malloc(sizeof(tSirSmeTsmIEInd)); + if (NULL == pSirSmeTsmIeInd) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for tSirSmeTsmIEInd")); + return; + } + cdf_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; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h new file mode 100644 index 000000000000..b9efbff3c842 --- /dev/null +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -0,0 +1,212 @@ +/* + * 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 lim_assoc_utils.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 "sir_api.h" +#include "sir_debug.h" +#include "cfg_api.h" + +#include "lim_types.h" + +uint8_t lim_cmp_s_sid(tpAniSirGlobal, tSirMacSSid *, tpPESession); +uint8_t lim_compare_capabilities(tpAniSirGlobal, + tSirAssocReq *, + tSirMacCapabilityInfo *, tpPESession); +uint8_t lim_check_rx_basic_rates(tpAniSirGlobal, tSirMacRateSet, tpPESession); +uint8_t lim_check_rx_rsn_ie_match(tpAniSirGlobal, tDot11fIERSN, tpPESession, uint8_t, + bool *); +uint8_t lim_check_rx_wpa_ie_match(tpAniSirGlobal, tDot11fIEWPA, tpPESession, + uint8_t); +uint8_t lim_check_mcs_set(tpAniSirGlobal pMac, uint8_t *supportedMCSSet); +void limPostDummyToTmRing(tpAniSirGlobal, tpDphHashNode); +void limPostPacketToTdRing(tpAniSirGlobal, tpDphHashNode, uint8_t); +tSirRetStatus lim_cleanup_rx_path(tpAniSirGlobal, tpDphHashNode, tpPESession); +void lim_reject_association(tpAniSirGlobal, tSirMacAddr, uint8_t, + uint8_t, tAniAuthType, + uint16_t, uint8_t, tSirResultCodes, tpPESession); + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus lim_populate_peer_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); +#else +tSirRetStatus lim_populate_peer_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, + tpPESession psessionEntry); +#endif + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus lim_populate_own_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); + +#else +tSirRetStatus lim_populate_own_rate_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + uint8_t *pSupportedMCSSet, + uint8_t basicOnly, + tpPESession psessionEntry); +#endif + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +lim_populate_matching_rate_set(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tSirMacRateSet *pOperRateSet, + tSirMacRateSet *pExtRateSet, + uint8_t *pSupportedMCSSet, + tpPESession psessionEntry, + tDot11fIEVHTCaps *pVHTCaps); +#else +tSirRetStatus lim_populate_matching_rate_set(tpAniSirGlobal, + tpDphHashNode, + tSirMacRateSet *, + tSirMacRateSet *, + uint8_t *pSupportedMCSSet, + tpPESession); + +#endif + +#ifdef WLAN_FEATURE_11AC +#define MCSMAPMASK1x1 0x3 +#define MCSMAPMASK2x2 0xC +#endif + +tSirRetStatus lim_add_sta(tpAniSirGlobal, tpDphHashNode, uint8_t, tpPESession); +tSirRetStatus lim_del_bss(tpAniSirGlobal, tpDphHashNode, uint16_t, tpPESession); +tSirRetStatus lim_del_sta(tpAniSirGlobal, tpDphHashNode, bool, tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +tSirRetStatus lim_add_ft_sta_self(tpAniSirGlobal pMac, uint16_t assocId, + tpPESession psessionEntry); +#endif /* WLAN_FEATURE_VOWIFI_11R */ +tSirRetStatus lim_add_sta_self(tpAniSirGlobal, uint16_t, uint8_t, tpPESession); +tStaRateMode lim_get_sta_rate_mode(uint8_t dot11Mode); + +void lim_teardown_infra_bss(tpAniSirGlobal, tpPESession); +void lim_restore_pre_reassoc_state(tpAniSirGlobal, + tSirResultCodes, uint16_t, tpPESession); +void lim_post_reassoc_failure(tpAniSirGlobal, + tSirResultCodes, uint16_t, tpPESession); +bool lim_is_reassoc_in_progress(tpAniSirGlobal, tpPESession); +void +lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, + uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext, + tSirResultCodes statusCode, tpPESession psessionEntry); + +void lim_handle_cnf_wait_timeout(tpAniSirGlobal pMac, uint16_t staId); +void lim_delete_dph_hash_entry(tpAniSirGlobal, tSirMacAddr, uint16_t, tpPESession); +void lim_check_and_announce_join_success(tpAniSirGlobal, + tSirProbeRespBeacon *, + tpSirMacMgmtHdr, tpPESession); +void lim_update_re_assoc_globals(tpAniSirGlobal pMac, + tpSirAssocRsp pAssocRsp, + tpPESession psessionEntry); + +void lim_update_assoc_sta_datas(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, tpSirAssocRsp pAssocRsp, + tpPESession psessionEntry); +void lim_fill_supported_rates_info(tpAniSirGlobal pMac, tpDphHashNode pSta, + tpSirSupportedRates pRates, + tpPESession psessionEntry); + +tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, + tpSchBeaconStruct pBeaconStruct, + tpSirBssDescription bssDescription, + uint8_t updateEntry, tpPESession psessionEntry); +tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t updateEntry, + tpPESession psessionEntry); + +void lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tSirResultCodes statusCode, tpPESession); +tSirRetStatus lim_extract_ap_capabilities(tpAniSirGlobal pMac, uint8_t *pIE, + uint16_t ieLen, + tpSirProbeRespBeacon beaconStruct); +void lim_init_pre_auth_timer_table(tpAniSirGlobal pMac, + tpLimPreAuthTable pPreAuthTimerTable); +tpLimPreAuthNode lim_acquire_free_pre_auth_node(tpAniSirGlobal pMac, + tpLimPreAuthTable + pPreAuthTimerTable); +tpLimPreAuthNode lim_get_pre_auth_node_from_index(tpAniSirGlobal pMac, + tpLimPreAuthTable pAuthTable, + uint32_t authNodeIdx); + +/* Util API to check if the channels supported by STA is within range */ +tSirRetStatus lim_is_dot11h_supported_channels_valid(tpAniSirGlobal pMac, + tSirAssocReq *assoc); + +/* Util API to check if the txpower supported by STA is within range */ +tSirRetStatus lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac, + tSirAssocReq *assoc, + tpPESession); + +/* API to re-add the same BSS during re-association */ +void lim_handle_add_bss_in_re_assoc_context(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry); + +/* API to fill in RX Highest Supported data Rate */ +void lim_fill_rx_highest_supported_rate(tpAniSirGlobal pMac, + uint16_t *rxHighestRate, + uint8_t *pSupportedMCSSet); +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) +void lim_send_retry_reassoc_req_frame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq, + tpPESession psessionEntry); +#endif +#ifdef WLAN_FEATURE_11W +void lim_send_sme_unprotected_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, + uint8_t *frame, uint32_t frameLen, + uint16_t sessionId, + tpPESession psessionEntry); +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +void lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t tid, uint8_t state, uint16_t measInterval); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +#endif /* __LIM_ASSOC_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_debug.c b/core/mac/src/pe/lim/lim_debug.c new file mode 100644 index 000000000000..51620d78bf9d --- /dev/null +++ b/core/mac/src/pe/lim/lim_debug.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 lim_debug.c + + \brief implementation for log Debug related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +#include "lim_debug.h" + +void lim_log(tpAniSirGlobal pMac, uint32_t 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. */ + + log_debug(pMac, SIR_LIM_MODULE_ID, loglevel, pString, marker); + + va_end(marker); /* Reset variable arguments. */ + } +#endif +} diff --git a/core/mac/src/pe/lim/lim_debug.h b/core/mac/src/pe/lim/lim_debug.h new file mode 100644 index 000000000000..e0ab7f6251f1 --- /dev/null +++ b/core/mac/src/pe/lim/lim_debug.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/* + * This file lim_debug.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 "utils_api.h" +#include "sir_debug.h" + +#if !defined(__printf) +#define __printf(a, b) +#endif + +void __printf(3, 4) lim_log(tpAniSirGlobal pMac, uint32_t 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/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c new file mode 100644 index 000000000000..c96327c12d67 --- /dev/null +++ b/core/mac/src/pe/lim/lim_ft.c @@ -0,0 +1,2027 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef WLAN_FEATURE_VOWIFI_11R +/**========================================================================= + + \brief implementation for PE 11r VoWiFi FT Protocol + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wmm_apsd.h" + +extern void lim_send_set_sta_key_req(tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + uint16_t staIdx, + uint8_t defWEPIdx, + tpPESession sessionEntry, bool sendRsp); + +/*-------------------------------------------------------------------------- + Initialize the FT variables. + ------------------------------------------------------------------------*/ +void lim_ft_open(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (psessionEntry) + cdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), + 0); +} + +/*-------------------------------------------------------------------------- + Cleanup FT variables. + ------------------------------------------------------------------------*/ +void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tpPESession pReAssocSessionEntry = NULL; + uint8_t sessionId = 0; + + if (!psessionEntry) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log + (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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + pReAssocSessionEntry = + pe_find_session_by_bssid(pMac, + psessionEntry->ftPEContext. + pFTPreAuthReq->preAuthbssId, + &sessionId); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq); + ) +#endif + if (psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription) { + cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription = NULL; + } + cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddBssReq) { + cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); + psessionEntry->ftPEContext.pAddBssReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddStaReq) { + cdf_mem_free(psessionEntry->ftPEContext.pAddStaReq); + psessionEntry->ftPEContext.pAddStaReq = NULL; + } + + /* The session is being deleted, cleanup the contents */ + cdf_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) { + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_DEBUG, + FL("Deleting Preauth session(%d)"), + pReAssocSessionEntry->peSessionId); + pe_delete_session(pMac, pReAssocSessionEntry); + } + } +} + +void lim_ft_cleanup_all_ft_sessions(tpAniSirGlobal pMac) +{ + /* Wrapper function to cleanup all FT sessions */ + int i; + + for (i = 0; i < pMac->lim.maxBssId; i++) { + if (true == pMac->lim.gpSession[i].valid) { + /* The session is valid, may have FT data */ + lim_ft_cleanup(pMac, &pMac->lim.gpSession[i]); + } + } +} + +void lim_ft_cleanup(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (NULL == psessionEntry) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log(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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return; + } + + if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq); + ) +#endif + if (NULL != + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription) { + cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription = NULL; + } + cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddBssReq) { + cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); + psessionEntry->ftPEContext.pAddBssReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddStaReq) { + cdf_mem_free(psessionEntry->ftPEContext.pAddStaReq); + psessionEntry->ftPEContext.pAddStaReq = NULL; + } + + /* The session is being deleted, cleanup the contents */ + cdf_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 +lim_ft_pre_auth_suspend_link_handler(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data) +{ + tpPESession psessionEntry = (tpPESession) data; + + /* The link is suspended of not */ + if (NULL == psessionEntry || + NULL == psessionEntry->ftPEContext.pFTPreAuthReq || + status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, + FL("preAuth error, status = %d"), status); + ) + lim_post_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0, + psessionEntry); + return; + } + + /* Suspended, now move to a different channel. + * Perform some sanity check before proceeding + */ + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + lim_change_channel_with_callback(pMac, + psessionEntry->ftPEContext. + pFTPreAuthReq->preAuthchannelNum, + lim_perform_ft_pre_auth, NULL, + psessionEntry); + return; + } +} + +/* + * lim_process_ft_pre_auth_req() - process ft pre auth req + * + * @mac_ctx: global mac ctx + * @msg: pointer to message + * + * 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 + * + * Return: value to indicate if buffer was consumed + */ +int lim_process_ft_pre_auth_req(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + int buf_consumed = false; + tpPESession session; + uint8_t session_id; + tpSirFTPreAuthReq ft_pre_auth_req = (tSirFTPreAuthReq *) msg->bodyptr; + + if (NULL == ft_pre_auth_req) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log(mac_ctx, LOGE, FL("tSirFTPreAuthReq is NULL"));) +#endif + return buf_consumed; + } + + /* Get the current session entry */ + session = pe_find_session_by_bssid(mac_ctx, + ft_pre_auth_req->currbssId, + &session_id); + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("Unable to find session for the bssid" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(ft_pre_auth_req->currbssId)); + /* Post the FT Pre Auth Response to SME */ + lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, + session); + /* + * return FALSE, since the Pre-Auth Req will be freed in + * limPostFTPreAuthRsp on failure + */ + return buf_consumed; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(session)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); +#endif + buf_consumed = true; + return buf_consumed; + } + + /* Can set it only after sending auth */ + session->ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + session->ftPEContext.ftPreAuthSession = true; + + /* Indicate that this is the session on which preauth is being done */ + if (session->ftPEContext.pFTPreAuthReq) { + if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { + cdf_mem_free( + session->ftPEContext.pFTPreAuthReq->pbssDescription); + session->ftPEContext.pFTPreAuthReq->pbssDescription = + NULL; + } + cdf_mem_free(session->ftPEContext.pFTPreAuthReq); + session->ftPEContext.pFTPreAuthReq = NULL; + } + + /* We need information from the Pre-Auth Req. Lets save that */ + session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"), + session->ftPEContext.pFTPreAuthReq->ft_ies[0], + session->ftPEContext.pFTPreAuthReq->ft_ies[1], + session->ftPEContext.pFTPreAuthReq->ft_ies[2]); +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, + session, 0, 0); +#endif + + /* Dont need to suspend if APs are in same channel */ + if (session->currentOperChannel != + session->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to suspend link only if the channels are different */ + lim_log(mac_ctx, LOG2, + FL("Performing pre-auth on diff channel(session %p)"), + session); + lim_ft_pre_auth_suspend_link_handler(mac_ctx, CDF_STATUS_SUCCESS, + (uint32_t *)session); + } else { + lim_log(mac_ctx, LOG2, + FL("Performing pre-auth on same channel (session %p)"), + session); + /* We are in the same channel. Perform pre-auth */ + lim_perform_ft_pre_auth(mac_ctx, CDF_STATUS_SUCCESS, NULL, + session); + } + + return buf_consumed; +} + +/*------------------------------------------------------------------ + * Send the Auth1 + * Receive back Auth2 + *------------------------------------------------------------------*/ +void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry) +{ + tSirMacAuthFrameBody authFrame; + + if (NULL == psessionEntry) { + PELOGE(lim_log(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(lim_log(pMac, LOGE, + "%s: FTIEs for Auth Req Seq 1 is absent", + __func__); + ) + goto preauth_fail; + } + } + + if (status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log(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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return; + } +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG2(lim_log(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(lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed"));) +#endif + } + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, + eLIM_FT_PREAUTH_RSP_TIMER)); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started"));) +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, + pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + + lim_send_auth_mgmt_frame(pMac, &authFrame, + psessionEntry->ftPEContext.pFTPreAuthReq-> + preAuthbssId, LIM_NO_WEP_IN_FC, psessionEntry); + + return; + +preauth_fail: + lim_handle_ft_pre_auth_rsp(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 lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac, + uint8_t updateEntry, + tpPESession pftSessionEntry, + tpSirBssDescription bssDescription) +{ + tpAddBssParams pAddBssParams = NULL; + tAddStaParams *sta_ctx; + uint8_t 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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return eSIR_FAILURE; + } + + pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { + lim_log(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 = cdf_mem_malloc(sizeof(tAddBssParams)); + if (NULL == pAddBssParams) { + cdf_mem_free(pBeaconStruct); + lim_log(pMac, LOGP, + FL("Unable to allocate memory for creating ADD_BSS")); + return (eSIR_MEM_ALLOC_FAILED); + } + + cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams), 0); + + lim_extract_ap_capabilities(pMac, (uint8_t *) bssDescription->ieFields, + lim_get_ielen_from_bss_description(bssDescription), + pBeaconStruct); + + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection_on_assoc(pMac, pBeaconStruct, + pftSessionEntry); + + cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, + sizeof(tSirMacAddr)); + + /* Fill in tAddBssParams selfMacAddr */ + cdf_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; + cdf_mem_copy(pAddBssParams->rateSet.rate, + pBeaconStruct->supportedRates.rate, + pBeaconStruct->supportedRates.numRates); + + pAddBssParams->nwType = bssDescription->nwType; + + pAddBssParams->shortSlotTimeSupported = + (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime; + pAddBssParams->llaCoexist = + (uint8_t) pftSessionEntry->beaconParams.llaCoexist; + pAddBssParams->llbCoexist = + (uint8_t) pftSessionEntry->beaconParams.llbCoexist; + pAddBssParams->llgCoexist = + (uint8_t) pftSessionEntry->beaconParams.llgCoexist; + pAddBssParams->ht20Coexist = + (uint8_t) 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; + cdf_mem_copy(&pAddBssParams->staContext.capab_info, + &pBeaconStruct->capabilityInfo, + sizeof(pAddBssParams->staContext.capab_info)); + cdf_mem_copy(&pAddBssParams->staContext.ht_caps, + (uint8_t *) &pBeaconStruct->HTCaps + + sizeof(uint8_t), + sizeof(pAddBssParams->staContext.ht_caps)); + + if (pBeaconStruct->HTInfo.present) { + pAddBssParams->htOperMode = + (tSirMacHTOperatingMode) pBeaconStruct->HTInfo. + opMode; + pAddBssParams->dualCTSProtection = + (uint8_t) pBeaconStruct->HTInfo.dualCTSProtection; + + chanWidthSupp = lim_get_ht_capability(pMac, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, + pftSessionEntry); + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + pAddBssParams->ch_width = (uint8_t) + pBeaconStruct->HTInfo.recommendedTxWidthSet; + if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId + 2; + else if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + pAddBssParams->ch_center_freq_seg0 = + bssDescription->channelId - 2; + } else { + pAddBssParams->ch_width = CH_WIDTH_20MHZ; + pAddBssParams->ch_center_freq_seg0 = 0; + } + pAddBssParams->llnNonGFCoexist = + (uint8_t) pBeaconStruct->HTInfo.nonGFDevicesPresent; + pAddBssParams->fLsigTXOPProtectionFullSupport = + (uint8_t) pBeaconStruct->HTInfo. + lsigTXOPProtectionFullSupport; + pAddBssParams->fRIFSMode = + pBeaconStruct->HTInfo.rifsMode; + } + } + + pAddBssParams->currentOperChannel = bssDescription->channelId; + pftSessionEntry->htSecondaryChannelOffset = + pBeaconStruct->HTInfo.secondaryChannelOffset; + sta_ctx = &pAddBssParams->staContext; + +#ifdef WLAN_FEATURE_11AC + if (pftSessionEntry->vhtCapability && + pftSessionEntry->vhtCapabilityPresentInBeacon) { + pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present; + if (pBeaconStruct->VHTOperation.chanWidth && chanWidthSupp) { + pAddBssParams->ch_width = + pBeaconStruct->VHTOperation.chanWidth + 1; + pAddBssParams->ch_center_freq_seg0 = + pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + pAddBssParams->ch_center_freq_seg1 = + pBeaconStruct->VHTOperation.chanCenterFreqSeg2; + } + 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 + lim_log(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; + + cdf_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 = + (uint8_t) 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 = + (uint8_t) pBeaconStruct->HTCaps.greenField; + pAddBssParams->staContext.lsigTxopProtection = + (uint8_t) pBeaconStruct->HTCaps.lsigTXOPProtection; + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + pAddBssParams->staContext.ch_width = (uint8_t) + pBeaconStruct->HTInfo.recommendedTxWidthSet; + } else { + pAddBssParams->staContext.ch_width = + CH_WIDTH_20MHZ; + } + if (pftSessionEntry->vhtCapability && + IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) { + pAddBssParams->staContext.vhtCapable = 1; + if ((pBeaconStruct->VHTCaps.suBeamFormerCap || + pBeaconStruct->VHTCaps.muBeamformerCap) && + pftSessionEntry->txBFIniFeatureEnabled) + sta_ctx->vhtTxBFCapable + = 1; + if (pBeaconStruct->VHTCaps.suBeamformeeCap && + pftSessionEntry->enable_su_tx_bformer) + sta_ctx->enable_su_tx_bformer = 1; + } + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && + (chanWidthSupp)) { + sta_ctx->ch_width = (uint8_t) + pBeaconStruct->HTInfo.recommendedTxWidthSet; + if (pAddBssParams->staContext.vhtCapable && + pBeaconStruct->VHTOperation.chanWidth) + sta_ctx->ch_width = + pBeaconStruct->VHTOperation.chanWidth + + 1; + } else { + pAddBssParams->staContext.ch_width = + CH_WIDTH_20MHZ; + } + pAddBssParams->staContext.mimoPS = + (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps. + mimoPowerSave; + pAddBssParams->staContext.maxAmsduSize = + (uint8_t) pBeaconStruct->HTCaps.maximalAMSDUsize; + pAddBssParams->staContext.maxAmpduDensity = + pBeaconStruct->HTCaps.mpduDensity; + pAddBssParams->staContext.fDsssCckMode40Mhz = + (uint8_t) pBeaconStruct->HTCaps.dsssCckMode40MHz; + pAddBssParams->staContext.fShortGI20Mhz = + (uint8_t) pBeaconStruct->HTCaps.shortGI20MHz; + pAddBssParams->staContext.fShortGI40Mhz = + (uint8_t) 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 + lim_populate_peer_rate_set(pMac, + &pAddBssParams->staContext. + supportedRates, + pBeaconStruct->HTCaps.supportedMCSSet, + false, pftSessionEntry, + &pBeaconStruct->VHTCaps); +#else + lim_populate_peer_rate_set(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; + } + } + } + +#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 = CDF_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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, pftSessionEntry->peSessionId, + eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE)); + pAddBssParams->halPersona = (uint8_t) pftSessionEntry->pePersona; + + pftSessionEntry->ftPEContext.pAddBssReq = pAddBssParams; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOG1, FL("Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap...")); +#endif + + cdf_mem_free(pBeaconStruct); + return 0; +} + +/*------------------------------------------------------------------ + * + * Setup the new session for the pre-auth AP. + * Return the newly created session entry. + * + *------------------------------------------------------------------*/ +void lim_fill_ft_session(tpAniSirGlobal pMac, + tpSirBssDescription pbssDescription, + tpPESession pftSessionEntry, tpPESession psessionEntry) +{ + uint8_t currentBssUapsd; + tPowerdBm localPowerConstraint; + tPowerdBm regMax; + tSchBeaconStruct *pBeaconStruct; + uint32_t selfDot11Mode; + ePhyChanBondState cbEnabledMode; + + pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOGE, + FL + ("Unable to allocate memory for creating lim_fill_ft_session")); +#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) + lim_print_mac_addr(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; + + lim_extract_ap_capabilities(pMac, (uint8_t *) pbssDescription->ieFields, + lim_get_ielen_from_bss_description(pbssDescription), + pBeaconStruct); + + pftSessionEntry->rateSet.numRates = + pBeaconStruct->supportedRates.numRates; + cdf_mem_copy(pftSessionEntry->rateSet.rate, + pBeaconStruct->supportedRates.rate, + pBeaconStruct->supportedRates.numRates); + + pftSessionEntry->extRateSet.numRates = + pBeaconStruct->extendedRates.numRates; + cdf_mem_copy(pftSessionEntry->extRateSet.rate, + pBeaconStruct->extendedRates.rate, + pftSessionEntry->extRateSet.numRates); + + pftSessionEntry->ssId.length = pBeaconStruct->ssId.length; + cdf_mem_copy(pftSessionEntry->ssId.ssId, pBeaconStruct->ssId.ssId, + pftSessionEntry->ssId.length); + + wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode); + lim_log(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); + + /* Copy The channel Id to the session Table */ + pftSessionEntry->limReassocChannelId = pbssDescription->channelId; + pftSessionEntry->currentOperChannel = pbssDescription->channelId; + + pftSessionEntry->limRFBand = lim_get_rf_band( + pftSessionEntry->currentOperChannel); + + 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; + + +#ifdef WLAN_FEATURE_11AC + if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && + pBeaconStruct->VHTOperation.present && + pftSessionEntry->vhtCapability) { + pftSessionEntry->vhtCapabilityPresentInBeacon = 1; + } else { + pftSessionEntry->vhtCapabilityPresentInBeacon = 0; + } +#endif + if (pftSessionEntry->htRecommendedTxWidthSet) { + pftSessionEntry->ch_width = CH_WIDTH_40MHZ; + if (pftSessionEntry->vhtCapabilityPresentInBeacon && + pBeaconStruct->VHTOperation.chanWidth) { + pftSessionEntry->ch_width = + pBeaconStruct->VHTOperation.chanWidth + 1; + pftSessionEntry->ch_center_freq_seg0 = + pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + pftSessionEntry->ch_center_freq_seg1 = + pBeaconStruct->VHTOperation.chanCenterFreqSeg2; + } else { + if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + pftSessionEntry->ch_center_freq_seg0 = + pbssDescription->channelId + 2; + else if (pBeaconStruct->HTInfo.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + pftSessionEntry->ch_center_freq_seg0 = + pbssDescription->channelId - 2; + else + lim_log(pMac, LOGE, FL("Invalid sec ch offset")); + } + } else { + pftSessionEntry->ch_width = CH_WIDTH_20MHZ; + pftSessionEntry->ch_center_freq_seg0 = 0; + pftSessionEntry->ch_center_freq_seg1 = 0; + } + + sir_copy_mac_addr(pftSessionEntry->selfMacAddr, + psessionEntry->selfMacAddr); + sir_copy_mac_addr(pftSessionEntry->limReAssocbssId, + pbssDescription->bssId); + sir_copy_mac_addr(pftSessionEntry->prev_ap_bssid, psessionEntry->bssId); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + lim_print_mac_addr(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; + + + 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. */ + lim_log(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 = cfg_get_regulatory_max_transmit_power(pMac, + pftSessionEntry-> + currentOperChannel); + localPowerConstraint = regMax; + lim_extract_ap_capability(pMac, (uint8_t *) pbssDescription->ieFields, + lim_get_ielen_from_bss_description(pbssDescription), + &pftSessionEntry->limCurrentBssQosCaps, + &pftSessionEntry->limCurrentBssPropCap, ¤tBssUapsd, + &localPowerConstraint, pftSessionEntry); + + 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 = + lim_get_max_tx_power(regMax, localPowerConstraint, + pMac->roam.configParam.nTxPowerCap); +#else + pftSessionEntry->maxTxPower = CDF_MIN(regMax, (localPowerConstraint)); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(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->limPrevSmeState = pftSessionEntry->limSmeState; + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_SME_STATE, pftSessionEntry->peSessionId, + pftSessionEntry->limSmeState)); + + pftSessionEntry->encryptType = psessionEntry->encryptType; +#ifdef WLAN_FEATURE_11W + pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled; +#endif + + cdf_mem_free(pBeaconStruct); +} + +/*------------------------------------------------------------------ + * + * Setup the session and the add bss req for the pre-auth AP. + * + *------------------------------------------------------------------*/ +tSirRetStatus lim_ft_setup_auth_session(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + uint8_t sessionId = 0; + + pftSessionEntry = + pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId, + &sessionId); + if (pftSessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, + FL + ("Unable to find session for the following bssid")); + ) + lim_print_mac_addr(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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return eSIR_FAILURE; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq && + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + lim_fill_ft_session(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription, pftSessionEntry, + psessionEntry); + + lim_ft_prepare_add_bss_req(pMac, false, pftSessionEntry, + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription); + } + + return eSIR_SUCCESS; +} + +/*------------------------------------------------------------------ + * Resume Link Call Back + *------------------------------------------------------------------*/ +void lim_ft_process_pre_auth_result(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return; + } + + if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + psessionEntry->ftPEContext.ftPreAuthStatus = + lim_ft_setup_auth_session(pMac, psessionEntry); + } + /* Post the FT Pre Auth Response to SME */ + lim_post_ft_pre_auth_rsp(pMac, psessionEntry->ftPEContext.ftPreAuthStatus, + psessionEntry->ftPEContext.saved_auth_rsp, + psessionEntry->ftPEContext.saved_auth_rsp_length, + psessionEntry); +} + +/*------------------------------------------------------------------ + * Resume Link Call Back + *------------------------------------------------------------------*/ +void lim_perform_post_ft_pre_auth_and_channel_change(tpAniSirGlobal pMac, + CDF_STATUS status, + uint32_t *data, + tpPESession psessionEntry) +{ + /* Set the resume channel to Any valid channel (invalid) + * This will instruct HAL to set it to any previous valid channel. + */ + pe_set_resume_channel(pMac, 0, 0); + lim_ft_process_pre_auth_result(pMac, CDF_STATUS_SUCCESS, + (uint32_t *) psessionEntry); +} + +/* + * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME. + * + * @mac_ctx: global mac ctx + * @status: status code to post in auth rsp + * @auth_rsp: pointer to auth rsp FT ie + * @auth_rsp_length: len of the IE field + * @session: pe session + * + * post pre auth response to SME. + * + * Return: void + */ +void lim_post_ft_pre_auth_rsp(tpAniSirGlobal mac_ctx, + tSirRetStatus status, + uint8_t *auth_rsp, + uint16_t auth_rsp_length, + tpPESession session) +{ + tpSirFTPreAuthRsp ft_pre_auth_rsp; + tSirMsgQ mmh_msg; + uint16_t rsp_len = sizeof(tSirFTPreAuthRsp); + + ft_pre_auth_rsp = (tpSirFTPreAuthRsp) cdf_mem_malloc(rsp_len); + if (NULL == ft_pre_auth_rsp) { + lim_log(mac_ctx, LOGE, "Failed to allocate memory"); + CDF_ASSERT(ft_pre_auth_rsp != NULL); + return; + } + cdf_mem_zero(ft_pre_auth_rsp, rsp_len); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("Auth Rsp = %p"), ft_pre_auth_rsp); +#endif + if (session) { + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(session)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOGE, + FL("session is not in STA mode")); +#endif + cdf_mem_free(ft_pre_auth_rsp); + return; + } + ft_pre_auth_rsp->smeSessionId = session->smeSessionId; + /* The bssid of the AP we are sending Auth1 to. */ + if (session->ftPEContext.pFTPreAuthReq) + sir_copy_mac_addr(ft_pre_auth_rsp->preAuthbssId, + session->ftPEContext.pFTPreAuthReq->preAuthbssId); + } + + ft_pre_auth_rsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP; + ft_pre_auth_rsp->length = (uint16_t) rsp_len; + ft_pre_auth_rsp->status = status; + + /* Attach the auth response now back to SME */ + ft_pre_auth_rsp->ft_ies_length = 0; + if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { + /* Only 11r assoc has FT IEs */ + cdf_mem_copy(ft_pre_auth_rsp->ft_ies, + auth_rsp, auth_rsp_length); + ft_pre_auth_rsp->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. + */ + lim_log(mac_ctx, LOG1, "Pre-Auth Failed, Cleanup!"); + lim_ft_cleanup(mac_ctx, session); + } + + mmh_msg.type = ft_pre_auth_rsp->messageType; + mmh_msg.bodyptr = ft_pre_auth_rsp; + mmh_msg.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("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) + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE, + session, status, 0); +#endif + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, 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 lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, + uint8_t *auth_rsp, uint16_t auth_rsp_length, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + uint8_t sessionId = 0; + tpSirBssDescription pbssDescription = NULL; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, + psessionEntry, (uint16_t) 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(lim_log + (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)) { + cdf_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) { + lim_log(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; + lim_print_mac_addr(pMac, pbssDescription->bssId, LOG1); + if ((pftSessionEntry = + pe_create_session(pMac, pbssDescription->bssId, + &sessionId, pMac->lim.maxStation, + psessionEntry->bssType)) == NULL) { + lim_log(pMac, LOGE, FL( + "Session not created for pre-auth 11R AP")); + status = eSIR_FAILURE; + psessionEntry->ftPEContext.ftPreAuthStatus = status; + goto send_rsp; + } + pftSessionEntry->peSessionId = sessionId; + pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; + sir_copy_mac_addr(pftSessionEntry->selfMacAddr, + psessionEntry->selfMacAddr); + sir_copy_mac_addr(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 { + lim_log(pMac, LOGE, FL("Invalid bss type")); + } + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + cdf_mem_copy(&(pftSessionEntry->htConfig), + &(psessionEntry->htConfig), + sizeof(psessionEntry->htConfig)); + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + + PELOGE(lim_log + (pMac, LOG1, "%s:created session (%p) with id = %d", + __func__, pftSessionEntry, + pftSessionEntry->peSessionId); + ) + + /* Update the ReAssoc BSSID of the current session */ + sir_copy_mac_addr(psessionEntry->limReAssocbssId, + pbssDescription->bssId); + lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOG1); + } +send_rsp: + if (psessionEntry->currentOperChannel != + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to move to the original AP channel */ + lim_change_channel_with_callback(pMac, + psessionEntry->currentOperChannel, + lim_perform_post_ft_pre_auth_and_channel_change, + NULL, psessionEntry); + } else { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log(pMac, LOG1, + "Pre auth on same channel as connected AP channel %d", + psessionEntry->ftPEContext.pFTPreAuthReq-> + preAuthchannelNum); + ) +#endif + lim_ft_process_pre_auth_result(pMac, status, + (uint32_t *) psessionEntry); + } +} + +/*------------------------------------------------------------------ + * + * This function handles the 11R Reassoc Req from SME + * + *------------------------------------------------------------------*/ +void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf, + tpPESession psessionEntry) +{ + uint8_t smeSessionId = 0; + uint16_t transactionId = 0; + uint8_t chanNum = 0; + tLimMlmReassocReq *pMlmReassocReq; + uint16_t caps; + uint32_t val; + tSirMsgQ msgQ; + tSirRetStatus retCode; + uint32_t teleBcnEn = 0; + + chanNum = psessionEntry->currentOperChannel; + lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smeSessionId, + &transactionId); + psessionEntry->smeSessionId = smeSessionId; + psessionEntry->transactionId = transactionId; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return; + } + + if (NULL == psessionEntry->ftPEContext.pAddBssReq) { + lim_log(pMac, LOGE, FL("pAddBssReq is NULL")); + return; + } + pMlmReassocReq = cdf_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == pMlmReassocReq) { + lim_log(pMac, LOGE, + FL("call to AllocateMemory failed for mlmReassocReq")); + return; + } + + cdf_mem_copy(pMlmReassocReq->peerMacAddr, + psessionEntry->bssId, sizeof(tSirMacAddr)); + + if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (uint32_t *) &pMlmReassocReq->reassocFailureTimeout) + != eSIR_SUCCESS) { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve ReassocFailureTimeout value")); + cdf_mem_free(pMlmReassocReq); + return; + } + + if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { + /** + * Could not get Capabilities value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, FL("could not retrieve Capabilities value")); + cdf_mem_free(pMlmReassocReq); + return; + } + 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_cfg_get_int(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + cdf_mem_free(pMlmReassocReq); + return; + } + + if (teleBcnEn) { + if (wlan_cfg_get_int(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != + eSIR_SUCCESS) { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve ListenInterval")); + cdf_mem_free(pMlmReassocReq); + return; + } + } else { + if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != + eSIR_SUCCESS) { + /** + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve ListenInterval")); + cdf_mem_free(pMlmReassocReq); + return; + } + } + if (lim_set_link_state + (pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { + cdf_mem_free(pMlmReassocReq); + return; + } + + pMlmReassocReq->listenInterval = (uint16_t) val; + psessionEntry->pLimMlmReassocReq = pMlmReassocReq; + + /* we need to defer the message until we get the response back from HAL */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + + msgQ.type = SIR_HAL_ADD_BSS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = psessionEntry->ftPEContext.pAddBssReq; + msgQ.bodyval = 0; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ...")); +#endif + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); + lim_log(pMac, LOGE, + FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), + retCode); + } + + psessionEntry->ftPEContext.pAddBssReq = NULL; + return; +} + +/* + * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout + * + * @mac_ctx: global mac ctx + * + * This function is called if preauth response is not received from the AP + * within this timeout while FT in progress + * + * Return: void + */ +void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal mac_ctx) +{ + tpPESession session; + + /* + * We have failed pre auth. We need to resume link and get back on + * home channel + */ + lim_log(mac_ctx, LOGE, FL("FT Pre-Auth Time Out!!!!")); + session = pe_find_session_by_session_id(mac_ctx, + mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); + if (NULL == session) { + lim_log(mac_ctx, 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(session)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); +#endif + return; + } + + /* Reset the flag to indicate preauth request session */ + session->ftPEContext.ftPreAuthSession = false; + + if (NULL == session->ftPEContext.pFTPreAuthReq) { + lim_log(mac_ctx, LOGE, + FL("pFTPreAuthReq is NULL. Auth Rsp might already be posted to SME and ftcleanup done! sessionId:%d"), + mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); + return; + } + + /* + * To handle the race condition where we recieve preauth rsp after + * timer has expired. + */ + if (true == + session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { + lim_log(mac_ctx, LOGE, + FL("Auth rsp already posted to SME (session %p)"), + session); + 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 + * lim_process_auth_frame_no_session. + */ + lim_log(mac_ctx, LOG1, + FL("Auth rsp not yet posted to SME (session %p)"), + session); + session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true; + } + + /* + * Attempted at Pre-Auth and failed. If we are off channel. We need + * to get back to home channel + */ + lim_handle_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, session); +} + +/*------------------------------------------------------------------ + * + * This function is called to process the update key request from SME + * + *------------------------------------------------------------------*/ +bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tAddBssParams *pAddBssParams; + tSirFTUpdateKeyInfo *pKeyInfo; + uint32_t val = 0; + tpPESession psessionEntry; + uint8_t sessionId; + + /* Sanity Check */ + if (pMac == NULL || pMsgBuf == NULL) { + return false; + } + + pKeyInfo = (tSirFTUpdateKeyInfo *) pMsgBuf; + + psessionEntry = pe_find_session_by_bssid(pMac, pKeyInfo->bssId, &sessionId); + if (NULL == psessionEntry) { + PELOGE(lim_log(pMac, LOGE, + "%s: Unable to find session for the following bssid", + __func__); + ) + lim_print_mac_addr(pMac, pKeyInfo->bssId, LOGE); + return 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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + return false; + } + + if (NULL == psessionEntry->ftPEContext.pAddBssReq) { + /* AddBss Req is NULL, save the keys to configure them later. */ + tpLimMlmSetKeysReq pMlmSetKeysReq = + &psessionEntry->ftPEContext.PreAuthKeyInfo. + extSetStaKeyParam; + + cdf_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq)); + cdf_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; + cdf_mem_copy((uint8_t *) &pMlmSetKeysReq->key, + (uint8_t *) &pKeyInfo->keyMaterial.key, + sizeof(tSirKeys)); + + psessionEntry->ftPEContext.PreAuthKeyInfo. + extSetStaKeyParamValid = true; + + lim_log(pMac, LOGE, FL("pAddBssReq is NULL")); + + if (psessionEntry->ftPEContext.pAddStaReq == NULL) { + lim_log(pMac, LOGE, FL("pAddStaReq is NULL")); + lim_send_set_sta_key_req(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; + cdf_mem_copy((uint8_t *) &pAddBssParams->extSetStaKeyParam.key, + (uint8_t *) &pKeyInfo->keyMaterial.key, + sizeof(tSirKeys)); + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { + lim_log(pMac, LOGP, + FL("Unable to read WNI_CFG_SINGLE_TID_RC")); + } + + pAddBssParams->extSetStaKeyParam.singleTidRc = val; + PELOG1(lim_log(pMac, LOG1, FL("Key valid %d"), + pAddBssParams->extSetStaKeyParamValid, + pAddBssParams->extSetStaKeyParam.key[0]. + keyLength); + ) + + pAddBssParams->extSetStaKeyParam.staIdx = 0; + + PELOG1(lim_log(pMac, LOG1, + FL("BSSID = " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pKeyInfo->bssId)); + ) + + sir_copy_mac_addr(pAddBssParams->extSetStaKeyParam.peerMacAddr, + pKeyInfo->bssId); + + pAddBssParams->extSetStaKeyParam.sendRsp = false; + + if (pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16) { + PELOG1(lim_log(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 +lim_ft_send_aggr_qos_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, + tpAggrAddTsParams aggrQosRsp, uint8_t smesessionId) +{ + tpSirAggrQosRsp rsp; + int i = 0; + if (!rspReqd) { + return; + } + rsp = cdf_mem_malloc(sizeof(tSirAggrQosRsp)); + if (NULL == rsp) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for tSirAggrQosRsp")); + return; + } + cdf_mem_set((uint8_t *) 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]; + } + } + lim_send_sme_aggr_qos_rsp(pMac, rsp, smesessionId); + return; +} +void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpAggrAddTsParams pAggrQosRspMsg = NULL; + tAddTsParams addTsParam = { 0 }; + tpDphHashNode pSta = NULL; + uint16_t assocId = 0; + tSirMacAddr peerMacAddr; + uint8_t rspReqd = 1; + tpPESession psessionEntry = NULL; + int i = 0; + PELOG1(lim_log(pMac, LOG1, FL(" Received AGGR_QOS_RSP from HAL"));) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + pAggrQosRspMsg = (tpAggrAddTsParams) (limMsg->bodyptr); + if (NULL == pAggrQosRspMsg) { + PELOGE(lim_log(pMac, LOGE, FL("NULL pAggrQosRspMsg"));) + return; + } + psessionEntry = + pe_find_session_by_session_id(pMac, pAggrQosRspMsg->sessionId); + if (NULL == psessionEntry) { + PELOGE(lim_log(pMac, LOGE, + FL("Cant find session entry for %s"), __func__); + ) + if (pAggrQosRspMsg != NULL) { + cdf_mem_free(pAggrQosRspMsg); + } + return; + } + if (!LIM_IS_STA_ROLE(psessionEntry)) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log + (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] != CDF_STATUS_SUCCESS)) { + sir_copy_mac_addr(peerMacAddr, psessionEntry->bssId); + addTsParam.staIdx = pAggrQosRspMsg->staIdx; + addTsParam.sessionId = pAggrQosRspMsg->sessionId; + addTsParam.tspec = pAggrQosRspMsg->tspec[i]; + addTsParam.tspecIdx = pAggrQosRspMsg->tspecIdx; + lim_send_delts_req_action_frame(pMac, peerMacAddr, rspReqd, + &addTsParam.tspec.tsinfo, + &addTsParam.tspec, + psessionEntry); + pSta = + dph_lookup_assoc_id(pMac, addTsParam.staIdx, &assocId, + &psessionEntry->dph.dphHashTable); + if (pSta != NULL) { + lim_admit_control_delete_ts(pMac, assocId, + &addTsParam.tspec. + tsinfo, NULL, + (uint8_t *) & + addTsParam.tspecIdx); + } + } + } + lim_ft_send_aggr_qos_rsp(pMac, rspReqd, pAggrQosRspMsg, + psessionEntry->smeSessionId); + if (pAggrQosRspMsg != NULL) { + cdf_mem_free(pAggrQosRspMsg); + } + return; +} +tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirMsgQ msg; + tSirAggrQosReq *aggrQosReq = (tSirAggrQosReq *) pMsgBuf; + tpAggrAddTsParams pAggrAddTsParam; + tpPESession psessionEntry = NULL; + tpLimTspecInfo tspecInfo; + uint8_t ac; + tpDphHashNode pSta; + uint16_t aid; + uint8_t sessionId; + int i; + + pAggrAddTsParam = cdf_mem_malloc(sizeof(tAggrAddTsParams)); + if (NULL == pAggrAddTsParam) { + PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));) + return eSIR_MEM_ALLOC_FAILED; + } + + psessionEntry = + pe_find_session_by_bssid(pMac, aggrQosReq->bssId, &sessionId); + + if (psessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("psession Entry Null for sessionId = %d"), + aggrQosReq->sessionId); + ) + cdf_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(lim_log + (pMac, LOGE, FL("psessionEntry is not in STA mode")); + ) +#endif + cdf_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + pSta = dph_lookup_hash_entry(pMac, aggrQosReq->bssId, &aid, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) { + PELOGE(lim_log(pMac, LOGE, + FL + ("Station context not found - ignoring AddTsRsp")); + ) + cdf_mem_free(pAggrAddTsParam); + return eSIR_FAILURE; + } + + cdf_mem_set((uint8_t *) 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 << i)) { + tSirMacTspecIE *pTspec = + &aggrQosReq->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 (pTspec->tsinfo.traffic.psb == 1) { + lim_set_tspec_uapsd_mask_per_session(pMac, + psessionEntry, + &pTspec-> + tsinfo, + SET_UAPSD_MASK); + } else { + lim_set_tspec_uapsd_mask_per_session(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); + } + lim_set_active_edca_params(pMac, + psessionEntry->gLimEdcaParams, + psessionEntry); + + lim_send_edca_params(pMac, + psessionEntry->gLimEdcaParamsActive, + pSta->bssId); + + if (eSIR_SUCCESS != + lim_tspec_add(pMac, pSta->staAddr, pSta->assocId, + pTspec, 0, &tspecInfo)) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("Adding entry in lim Tspec Table failed ")); + ) + pMac->lim.gLimAddtsSent = false; + cdf_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 = WMA_AGGR_QOS_REQ; + msg.bodyptr = pAggrAddTsParam; + msg.bodyval = 0; + + /* We need to defer any incoming messages until we get a + * WMA_AGGR_QOS_RSP from HAL. + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msg.type)); + + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + PELOGW(lim_log + (pMac, LOGW, FL("wma_post_ctrl_msg() failed")); + ) + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + cdf_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 */ + lim_ft_send_aggr_qos_rsp(pMac, true, pAggrAddTsParam, + psessionEntry->smeSessionId); + if (pAggrAddTsParam != NULL) { + cdf_mem_free(pAggrAddTsParam); + } + } +#endif + + return eSIR_SUCCESS; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c new file mode 100644 index 000000000000..c2c3dba5353a --- /dev/null +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c @@ -0,0 +1,1833 @@ +/* + * 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 "cds_api.h" +#include "ani_global.h" +#include "sir_common.h" +#include "wni_cfg.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_sta_hash_api.h" +#include "sch_api.h" /* sch_set_fixed_beacon_fields for IBSS coalesce */ +#include "lim_security_utils.h" +#include "lim_send_messages.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_ibss_peer_mgmt.h" +#include "lim_types.h" + +/** + * ibss_peer_find + * + ***FUNCTION: + * This function is called while adding a context at + * DPH & Polaris for a peer in IBSS. + * If peer is found in the list, capabilities from the + * returned BSS description are used at DPH node & Polaris. + * + ***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 (cdf_mem_compare((uint8_t *) macAddr, + (uint8_t *) &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 + uint32_t 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) { + cdf_mem_free(pTemp->beacon); + } + + cdf_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) +{ + cdf_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; + cdf_mem_copy((uint8_t *) pPeer->supportedMCSSet, + (uint8_t *) pBeacon->HTCaps.supportedMCSSet, + sizeof(pPeer->supportedMCSSet)); + pPeer->htGreenfield = (uint8_t) pBeacon->HTCaps.greenField; + pPeer->htSupportedChannelWidthSet = + (uint8_t) pBeacon->HTCaps.supportedChannelWidthSet; + pPeer->htMIMOPSState = + (tSirMacHTMIMOPowerSaveState) pBeacon->HTCaps.mimoPowerSave; + pPeer->htMaxAmsduLength = + (uint8_t) pBeacon->HTCaps.maximalAMSDUsize; + pPeer->htAMpduDensity = pBeacon->HTCaps.mpduDensity; + pPeer->htDsssCckRate40MHzSupport = + (uint8_t) pBeacon->HTCaps.dsssCckMode40MHz; + pPeer->htShortGI20Mhz = (uint8_t) pBeacon->HTCaps.shortGI20MHz; + pPeer->htShortGI40Mhz = (uint8_t) pBeacon->HTCaps.shortGI40MHz; + pPeer->htMaxRxAMpduFactor = pBeacon->HTCaps.maxRxAMPDUFactor; + pPeer->htSecondaryChannelOffset = + pBeacon->HTInfo.secondaryChannelOffset; + pPeer->htLdpcCapable = (uint8_t) 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 */ + cdf_mem_copy((uint8_t *) &pPeer->VHTCaps, + (uint8_t *) &pBeacon->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } +#endif + pPeer->erpIePresent = pBeacon->erpPresent; + + cdf_mem_copy((uint8_t *) &pPeer->supportedRates, + (uint8_t *) &pBeacon->supportedRates, + pBeacon->supportedRates.numRates + 1); + if (pPeer->extendedRatesPresent) + cdf_mem_copy((uint8_t *) &pPeer->extendedRates, + (uint8_t *) &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) +{ + uint16_t peerIdx; + tpDphHashNode pStaDs; + + pPeerNode->beaconHBCount++; /* Update beacon count. */ + + /* if the peer node exists, update its qos capabilities */ + pStaDs = dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx, + &psessionEntry->dph.dphHashTable); + if (pStaDs == 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->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 = + (uint8_t) 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 + lim_populate_matching_rate_set(pMac, pStaDs, &pPeer->supportedRates, + &pPeer->extendedRates, + pPeer->supportedMCSSet, psessionEntry, + &pPeer->VHTCaps); +#else + /* Populate supported rateset */ + lim_populate_matching_rate_set(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 both SW & Polaris 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) + cdf_mem_free(pMac->lim.ibssInfo.pHdr); + if (pMac->lim.ibssInfo.pBeacon != NULL) + cdf_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 = cdf_mem_malloc(sizeof(*pHdr)); + if (NULL == pMac->lim.ibssInfo.pHdr) { + PELOGE(lim_log(pMac, LOGE, FL("ibbs-save: Failed malloc pHdr"));) + return; + } + pMac->lim.ibssInfo.pBeacon = cdf_mem_malloc(sizeof(*pBeacon)); + if (NULL == pMac->lim.ibssInfo.pBeacon) { + PELOGE(lim_log + (pMac, LOGE, FL("ibbs-save: Failed malloc pBeacon")); + ) + ibss_coalesce_free(pMac); + return; + } + + cdf_mem_copy(pMac->lim.ibssInfo.pHdr, pHdr, sizeof(*pHdr)); + cdf_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) +{ + uint16_t peerIdx; + tpDphHashNode pStaDs; + + *ppSta = NULL; + + pStaDs = + dph_lookup_hash_entry(pMac, peerAddr, &peerIdx, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) { + /* Trying to add context for already existing STA in IBSS */ + PELOGE(lim_log(pMac, LOGE, FL("STA exists already "));) + lim_print_mac_addr(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 = lim_assign_peer_idx(pMac, psessionEntry); + + pStaDs = + dph_get_hash_entry(pMac, peerIdx, &psessionEntry->dph.dphHashTable); + if (pStaDs) { + (void)lim_del_sta(pMac, pStaDs, false /*asynchronous */, + psessionEntry); + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, peerIdx, + psessionEntry); + } + + pStaDs = + dph_add_hash_entry(pMac, peerAddr, peerIdx, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + /* Could not add hash table entry */ + PELOGE(lim_log + (pMac, LOGE, + FL + ("could not add hash entry at DPH for peerIdx/aid=%d MACaddr:"), + peerIdx); + ) + lim_print_mac_addr(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, + uint16_t staIndex, + uint8_t ucastSig, + uint8_t bcastSig, uint16_t status, uint8_t sessionId) +{ + + tLimIbssPeerNode *peerNode; + uint8_t *beacon = NULL; + uint16_t 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; + } + + lim_send_sme_ibss_peer_ind(pMac, peerAddr, staIndex, ucastSig, bcastSig, + beacon, bcnLen, status, sessionId); + + if (beacon != NULL) { + cdf_mem_free(beacon); + } +} + +static void ibss_bss_add(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tLimMlmStartReq mlmStartReq; + uint32_t cfg; + tpSirMacMgmtHdr pHdr = (tpSirMacMgmtHdr) pMac->lim.ibssInfo.pHdr; + tpSchBeaconStruct pBeacon = + (tpSchBeaconStruct) pMac->lim.ibssInfo.pBeacon; + uint8_t numExtRates = 0; + + if ((pHdr == NULL) || (pBeacon == NULL)) { + PELOGE(lim_log + (pMac, LOGE, + FL("Unable to add BSS (no cached BSS info)")); + ) + return; + } + + cdf_mem_copy(psessionEntry->bssId, pHdr->bssId, sizeof(tSirMacAddr)); + + sir_copy_mac_addr(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 lim_apply_configuration() + * 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; + } + cdf_mem_copy((uint8_t *) &psessionEntry->pLimStartBssReq-> + operationalRateSet, (uint8_t *) &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 (cfg_set_str(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + (uint8_t *) &pBeacon->extendedRates.rate, + numExtRates) != eSIR_SUCCESS) { + lim_log(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. + */ + cdf_mem_set((void *)&mlmStartReq, sizeof(mlmStartReq), 0); + + cdf_mem_copy(mlmStartReq.bssId, pHdr->bssId, sizeof(tSirMacAddr)); + mlmStartReq.rateSet.numRates = + psessionEntry->pLimStartBssReq->operationalRateSet.numRates; + cdf_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. */ + cdf_mem_copy((uint8_t *) &mlmStartReq.ssId, + (uint8_t *) &psessionEntry->pLimStartBssReq->ssId, + psessionEntry->pLimStartBssReq->ssId.length + 1); + + PELOG1(lim_log + (pMac, LOG1, FL("invoking ADD_BSS as part of coalescing!")); + ) + if (lim_mlm_add_bss(pMac, &mlmStartReq, psessionEntry) != + eSIR_SME_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("AddBss failure"));) + return; + } + /* Update fields in Beacon */ + if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS) { + PELOGE(lim_log + (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(lim_log(pMac, LOGW, FL("Initiating IBSS Delete BSS"));) + if (psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) { + lim_log(pMac, LOGW, + FL("Incorrect LIM MLM state for delBss (%d)"), + psessionEntry->limMlmState); + return; + } + status = lim_del_bss(pMac, NULL, psessionEntry->bssIdx, psessionEntry); + if (status != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, FL("delBss failed for bss %d"), + psessionEntry->bssIdx); + ) +} + +/** + * lim_ibss_init + * + ***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 lim_ibss_init(tpAniSirGlobal pMac) +{ + pMac->lim.gLimIbssCoalescingHappened = 0; + pMac->lim.gLimIbssPeerList = NULL; + pMac->lim.gLimNumIbssPeers = 0; + + /* ibss info - params for which ibss to join while coalescing */ + cdf_mem_set(&pMac->lim.ibssInfo, sizeof(tAniSirLimIbss), 0); +} /*** end lim_ibss_init() ***/ + +/** + * lim_ibss_delete_all_peers + * + ***FUNCTION: + * This function is called to delete all peers. + * + ***LOGIC: + * + ***ASSUMPTIONS: + * + ***NOTE: + * + * @param pMac - Pointer to Global MAC structure + * @return None + */ + +void lim_ibss_delete_all_peers(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tLimIbssPeerNode *pCurrNode, *pTempNode; + tpDphHashNode pStaDs; + uint16_t peerIdx; + + pCurrNode = pTempNode = pMac->lim.gLimIbssPeerList; + + while (pCurrNode != NULL) { + if (!pMac->lim.gLimNumIbssPeers) { + lim_log(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 lim_delete_dph_hash_entry + */ + pStaDs = + dph_lookup_hash_entry(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); + lim_release_peer_idx(pMac, peerIdx, psessionEntry); + dph_delete_hash_entry(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) { + cdf_mem_free(pCurrNode->beacon); + } + cdf_mem_free(pCurrNode); + if (pMac->lim.gLimNumIbssPeers > 0) /* be paranoid */ + pMac->lim.gLimNumIbssPeers--; + pCurrNode = pTempNode; + } + + if (pMac->lim.gLimNumIbssPeers) + lim_log(pMac, LOGP, + FL("Number of peers[%d] in the list is non-zero"), + pMac->lim.gLimNumIbssPeers); + + pMac->lim.gLimNumIbssPeers = 0; + pMac->lim.gLimIbssPeerList = NULL; + +} + +/** + * lim_ibss_delete() - This function is called while tearing down an IBSS + * + * @pMac: Pointer to Global MAC structure + * @psessionEntry: Pointer to session entry + * + * Return: none + */ + +void lim_ibss_delete(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + lim_ibss_delete_all_peers(pMac, psessionEntry); + ibss_coalesce_free(pMac); +} + +/** ------------------------------------------------------------- + \fn lim_ibss_set_protection + \brief Decides all the protection related information. + \ + \param tpAniSirGlobal pMac + \param tSirMacAddr peerMacAddr + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +static void +lim_ibss_set_protection(tpAniSirGlobal pMac, uint8_t enable, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + + if (!pMac->lim.cfgProtection.fromllb) { + PELOG1(lim_log + (pMac, LOG1, FL("protection from 11b is disabled")); + ) + return; + } + + if (enable) { + psessionEntry->gLim11bParams.protectionEnabled = true; + if (false == + psessionEntry->beaconParams. + llbCoexist /*pMac->lim.llbCoexist */) { + PELOGE(lim_log + (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(lim_log(pMac, LOGE, FL("===> IBSS: Disable protection "));) + pBeaconParams->llbCoexist = + psessionEntry->beaconParams.llbCoexist = false; + pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; + } + return; +} + +/** ------------------------------------------------------------- + \fn lim_ibss_update_protection_params + \brief Decides all the protection related information. + \ + \param tpAniSirGlobal pMac + \param tSirMacAddr peerMacAddr + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +static void +lim_ibss_update_protection_params(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tLimProtStaCacheType protStaCacheType, + tpPESession psessionEntry) +{ + uint32_t i; + + PELOG1(lim_log(pMac, LOG1, FL("A STA is associated:")); + lim_log(pMac, LOG1, FL("Addr : ")); + lim_print_mac_addr(pMac, peerMacAddr, LOG1); + ) + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (pMac->lim.protStaCache[i].active) { + PELOG1(lim_log(pMac, LOG1, FL("Addr: "));) + PELOG1(lim_print_mac_addr + (pMac, pMac->lim.protStaCache[i].addr, LOG1); + ) + + if (cdf_mem_compare(pMac->lim.protStaCache[i].addr, + peerMacAddr, + sizeof(tSirMacAddr))) { + PELOG1(lim_log + (pMac, LOG1, + FL + ("matching cache entry at %d already active."), + i); + ) + return; + } + } + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (!pMac->lim.protStaCache[i].active) + break; + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + PELOGE(lim_log(pMac, LOGE, FL("No space in ProtStaCache"));) + return; + } + + cdf_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 lim_ibss_decide_protection + \brief Decides all the protection related information. + \ + \param tpAniSirGlobal pMac + \param tSirMacAddr peerMacAddr + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +static void +lim_ibss_decide_protection(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + uint32_t phyMode; + tLimProtStaCacheType protStaCacheType = + eLIM_PROT_STA_CACHE_TYPE_INVALID; + + pBeaconParams->paramChangeBitmap = 0; + + if (NULL == pStaDs) { + PELOGE(lim_log(pMac, LOGE, FL("pStaDs is NULL"));) + return; + } + + lim_get_rf_band_new(pMac, &rfBand, psessionEntry); + if (SIR_BAND_2_4_GHZ == rfBand) { + lim_get_phy_mode(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(lim_log + (pMac, LOGE, + FL("Enable protection from 11B")); + ) + lim_ibss_set_protection(pMac, true, + pBeaconParams, + psessionEntry); + } + } + } + lim_ibss_update_protection_params(pMac, pStaDs->staAddr, protStaCacheType, + psessionEntry); + return; +} + +/** + * lim_ibss_peer_find() + * + ***FUNCTION: + * This function is called while adding a context at + * DPH & Polaris for a peer in IBSS. + * If peer is found in the list, capabilities from the + * returned BSS description are used at DPH node & Polaris. + * + ***LOGIC: + * + ***ASSUMPTIONS: + * + ***NOTE: + * + * @param macAddr - MAC address of the peer + * + * @return Pointer to peer node if found, else NULL + */ +tLimIbssPeerNode *lim_ibss_peer_find(tpAniSirGlobal pMac, tSirMacAddr macAddr) +{ + return ibss_peer_find(pMac, macAddr); +} + +/** + * lim_ibss_sta_add() + * + ***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 +lim_ibss_sta_add(tpAniSirGlobal pMac, void *pBody, tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tpDphHashNode pStaDs; + tLimIbssPeerNode *pPeerNode; + tLimMlmStates prevState; + tSirMacAddr *pPeerAddr = (tSirMacAddr *) pBody; + tUpdateBeaconParams beaconParams; + + cdf_mem_set((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams), 0); + + if (pBody == 0) { + PELOGE(lim_log(pMac, LOGE, FL("Invalid IBSS AddSta"));) + return eSIR_FAILURE; + } + + PELOGE(lim_log(pMac, LOGE, FL("Rx Add-Ibss-Sta for MAC:"));) + lim_print_mac_addr(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(lim_log + (pMac, LOGW, + FL("initiating ADD STA for the IBSS peer.")); + ) + retCode = + lim_add_sta(pMac, pStaDs, false, psessionEntry); + if (retCode != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("ibss-sta-add failed (reason %x)"), + retCode); + ) + lim_print_mac_addr(pMac, *pPeerAddr, LOGE); + pStaDs->mlmStaContext.mlmState = prevState; + dph_delete_hash_entry(pMac, pStaDs->staAddr, + pStaDs->assocId, + &psessionEntry->dph. + dphHashTable); + } else { + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_ibss_decide_protection(pMac, pStaDs, + &beaconParams, + psessionEntry); + + if (beaconParams.paramChangeBitmap) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("---> Update Beacon Params ")); + ) + sch_set_fixed_beacon_fields(pMac, + psessionEntry); + beaconParams.bssIdx = + psessionEntry->bssIdx; + lim_send_beacon_params(pMac, &beaconParams, + psessionEntry); + } + } + } else { + PELOGE(lim_log + (pMac, LOGE, FL("hashTblAdd failed (reason %x)"), + retCode); + ) + lim_print_mac_addr(pMac, *pPeerAddr, LOGE); + } + } else { + retCode = eSIR_FAILURE; + } + + return retCode; +} + +/* handle the response from HAL for an ADD STA request */ +tSirRetStatus +lim_ibss_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession psessionEntry) +{ + tpDphHashNode pStaDs; + uint16_t peerIdx; + tpAddStaParams pAddStaParams = (tpAddStaParams) msg; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + if (pAddStaParams == NULL) { + PELOGE(lim_log + (pMac, LOGE, FL("IBSS: ADD_STA_RSP with no body!")); + ) + return eSIR_FAILURE; + } + + pStaDs = + dph_lookup_hash_entry(pMac, pAddStaParams->staMac, &peerIdx, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("IBSS: ADD_STA_RSP for unknown MAC addr ")); + ) + lim_print_mac_addr(pMac, pAddStaParams->staMac, LOGE); + cdf_mem_free(pAddStaParams); + return eSIR_FAILURE; + } + + if (pAddStaParams->status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("IBSS: ADD_STA_RSP error (%x) "), + pAddStaParams->status); + ) + lim_print_mac_addr(pMac, pAddStaParams->staMac, LOGE); + cdf_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(lim_log + (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); + + cdf_mem_free(pAddStaParams); + + return eSIR_SUCCESS; +} + +void lim_ibss_del_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg, + tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBss = (tpDeleteBssParams) msg; + + PELOGW(lim_log + (pMac, LOGW, FL("IBSS: DEL_BSS_RSP Rcvd during coalescing!")); + ) + + if (pDelBss == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("IBSS: DEL_BSS_RSP(coalesce) with no body!")); + ) + goto end; + } + + if (pDelBss->status != CDF_STATUS_SUCCESS) { + lim_log(pMac, LOGE, + FL("IBSS: DEL_BSS_RSP(coalesce) error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx); + goto end; + } + /* Delete peer entries. */ + lim_ibss_delete_all_peers(pMac, psessionEntry); + + /* add the new bss */ + ibss_bss_add(pMac, psessionEntry); + +end: + if (pDelBss != NULL) + cdf_mem_free(pDelBss); +} + +void lim_ibss_add_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg, + tpPESession pSessionEntry) +{ + uint8_t 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(lim_log + (pMac, LOGE, + FL + ("Unable to handle AddBssRspWhenCoalescing (no cached BSS info)")); + ) + goto end; + } + /* Inform Host of IBSS coalescing */ + infoLen = sizeof(tSirMacAddr) + sizeof(tSirMacChanNum) + + sizeof(uint8_t) + pBeacon->ssId.length + 1; + + cdf_mem_set((void *)&newBssInfo, sizeof(newBssInfo), 0); + cdf_mem_copy(newBssInfo.bssId, pHdr->bssId, sizeof(tSirMacAddr)); + newBssInfo.channelNumber = (tSirMacChanNum) pAddBss->currentOperChannel; + cdf_mem_copy((uint8_t *) &newBssInfo.ssId, + (uint8_t *) &pBeacon->ssId, pBeacon->ssId.length + 1); + + PELOGW(lim_log + (pMac, LOGW, FL("Sending JOINED_NEW_BSS notification to SME.")); + ) + + lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_JOINED_NEW_BSS, + (uint32_t *) &newBssInfo, + infoLen, pSessionEntry->smeSessionId); + { + /* Configure beacon and send beacons to HAL */ + lim_send_beacon_ind(pMac, pSessionEntry); + } + +end: + ibss_coalesce_free(pMac); +} + +void lim_ibss_del_bss_rsp(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(lim_log + (pMac, LOGE, FL("IBSS: DEL_BSS_RSP with no body!")); + ) + rc = eSIR_SME_REFUSED; + goto end; + } + + psessionEntry = pe_find_session_by_session_id(pMac, pDelBss->sessionId); + if (psessionEntry == NULL) { + lim_log(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) { + + lim_ibss_del_bss_rsp_when_coalescing(pMac, msg, psessionEntry); + return; + } + + if (pDelBss->status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("IBSS: DEL_BSS_RSP error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx); + ) + rc = eSIR_SME_STOP_BSS_FAILURE; + goto end; + } + + if (lim_set_link_state(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + psessionEntry->selfMacAddr, NULL, + NULL) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("IBSS: DEL_BSS_RSP setLinkState failed")); + ) + rc = eSIR_SME_REFUSED; + goto end; + } + + lim_ibss_delete(pMac, psessionEntry); + + dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable); + lim_delete_pre_auth_list(pMac); + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + + MTRACE(mac_trace + (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 lim_apply_configuration + */ + psessionEntry->shortSlotTimeSupported = WNI_CFG_SHORT_SLOT_TIME_STADEF; + +end: + if (pDelBss != NULL) + cdf_mem_free(pDelBss); + /* Delete PE session once BSS is deleted */ + if (NULL != psessionEntry) { + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, rc, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + } +} + +static void +__lim_ibss_search_and_delete_peer(tpAniSirGlobal pMac, + tpPESession psessionEntry, tSirMacAddr macAddr) +{ + tLimIbssPeerNode *pTempNode, *pPrevNode; + tLimIbssPeerNode *pTempNextNode = NULL; + tpDphHashNode pStaDs = NULL; + uint16_t peerIdx = 0; + uint16_t staIndex = 0; + uint8_t ucUcastSig; + uint8_t ucBcastSig; + + pPrevNode = pTempNode = pMac->lim.gLimIbssPeerList; + + lim_log(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 (cdf_mem_compare((uint8_t *) macAddr, + (uint8_t *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr))) { + pStaDs = dph_lookup_hash_entry(pMac, macAddr, + &peerIdx, + &psessionEntry->dph. + dphHashTable); + if (pStaDs) { + staIndex = pStaDs->staIndex; + ucUcastSig = pStaDs->ucUcastSig; + ucBcastSig = pStaDs->ucBcastSig; + + (void)lim_del_sta(pMac, pStaDs, + false /*asynchronous */, + psessionEntry); + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, + peerIdx, psessionEntry); + lim_release_peer_idx(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; + + cdf_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) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + "Last STA from IBSS walked out"); + psessionEntry->limIbssActive = false; + } +} + +/** + * lim_ibss_coalesce() + * + ***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 +lim_ibss_coalesce(tpAniSirGlobal pMac, + tpSirMacMgmtHdr pHdr, + tpSchBeaconStruct pBeacon, + uint8_t *pIEs, + uint32_t ieLen, uint16_t fTsfLater, tpPESession psessionEntry) +{ + uint16_t peerIdx; + tSirMacAddr currentBssId; + tLimIbssPeerNode *pPeerNode; + tpDphHashNode pStaDs; + tUpdateBeaconParams beaconParams; + + cdf_mem_set((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams), 0); + + sir_copy_mac_addr(currentBssId, psessionEntry->bssId); + + lim_log(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 (!cdf_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) { + __lim_ibss_search_and_delete_peer(pMac, psessionEntry, + pHdr->sa); + PELOGW(lim_log + (pMac, LOGW, + FL + ("** Peer attempting to reconnect before HB timeout, deleted **")); + ) + return eSIR_LIM_IGNORE_BEACON; + } + + if (!fTsfLater) { /* No Coalescing happened. */ + PELOGW(lim_log(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(lim_log(pMac, LOGW, FL("IBSS Coalescing happened"));) + ibss_coalesce_save(pMac, pHdr, pBeacon); + lim_log(pMac, LOGW, FL("Delete BSSID :" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(currentBssId)); + ibss_bss_delete(pMac, psessionEntry); + return eSIR_SUCCESS; + } else { + if (!cdf_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 */ + uint32_t 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.ibss_retry_cnt % 100 == 0) { + PELOGE(lim_log(pMac, LOG1, + FL("**** MAX STA LIMIT HAS REACHED ****"));) + } + pMac->lim.ibss_retry_cnt++; + return eSIR_LIM_MAX_STA_REACHED_ERROR; + } + PELOGW(lim_log + (pMac, LOGW, + FL("IBSS Peer node does not exist, adding it***")); + ) + frameLen = + sizeof(tLimIbssPeerNode) + ieLen - sizeof(uint32_t); + + pPeerNode = cdf_mem_malloc((uint16_t) frameLen); + if (NULL == pPeerNode) { + lim_log(pMac, LOGP, + FL + ("alloc fail (%d bytes) storing IBSS peer info"), + frameLen); + return eSIR_MEM_ALLOC_FAILED; + } + + pPeerNode->beacon = NULL; + pPeerNode->beaconLen = 0; + + ibss_peer_collect(pMac, pBeacon, pHdr, pPeerNode, + psessionEntry); + pPeerNode->beacon = cdf_mem_malloc(ieLen); + if (NULL == pPeerNode->beacon) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("Unable to allocate memory to store beacon")); + ) + } else { + cdf_mem_copy(pPeerNode->beacon, pIEs, ieLen); + pPeerNode->beaconLen = (uint16_t) ieLen; + } + ibss_peer_add(pMac, pPeerNode); + + pStaDs = + dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) { + /* / DPH node already exists for the peer */ + PELOGW(lim_log + (pMac, LOGW, + FL("DPH Node present for just learned peer")); + ) + PELOG1(lim_print_mac_addr + (pMac, pPeerNode->peerMacAddr, LOG1); + ) + ibss_sta_info_update(pMac, pStaDs, pPeerNode, + psessionEntry); + return eSIR_SUCCESS; + } + retCode = + lim_ibss_sta_add(pMac, pPeerNode->peerMacAddr, psessionEntry); + if (retCode != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("lim-ibss-sta-add failed (reason %x)"), + retCode); + ) + lim_print_mac_addr(pMac, pPeerNode->peerMacAddr, LOGE); + return retCode; + } + /* Decide protection mode */ + pStaDs = + dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx, + &psessionEntry->dph.dphHashTable); + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_ibss_decide_protection(pMac, pStaDs, &beaconParams, + psessionEntry); + + if (beaconParams.paramChangeBitmap) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("beaconParams.paramChangeBitmap=1 ---> Update Beacon Params ")); + ) + sch_set_fixed_beacon_fields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; + lim_send_beacon_params(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(lim_log + (pMac, LOGW, + FL + ("Partner joined our IBSS, Sending IBSS_ACTIVE Notification to SME")); + ) + psessionEntry->limIbssActive = true; + lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_IBSS_ACTIVE, NULL, 0, + psessionEntry->smeSessionId); + } + + return eSIR_SUCCESS; +} /*** end lim_handle_ibs_scoalescing() ***/ + +/** + * lim_ibss_heart_beat_handle() - handle IBSS hearbeat failure + * + * @mac_ctx: global mac context + * @session: PE session entry + * + * Hanlde IBSS hearbeat failure. + * + * Return: None. + */ +void lim_ibss_heart_beat_handle(tpAniSirGlobal mac_ctx, tpPESession session) +{ + tLimIbssPeerNode *tempnode, *prevnode; + tLimIbssPeerNode *temp_next = NULL; + uint16_t peer_idx = 0; + tpDphHashNode stads = 0; + uint32_t threshold = 0; + uint16_t sta_idx = 0; + uint8_t ucast_sig = 0; + uint8_t bcast_sig = 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 (session->limMlmState != eLIM_MLM_BSS_STARTED_STATE) + return; + + /* If LinkMonitor is Disabled */ + if (!mac_ctx->sys.gSysEnableLinkMonitorMode) + return; + + prevnode = tempnode = mac_ctx->lim.gLimIbssPeerList; + threshold = (mac_ctx->lim.gLimNumIbssPeers / 4) + 1; + + /* Monitor the HeartBeat with the Individual PEERS in the IBSS */ + while (tempnode != NULL) { + temp_next = tempnode->next; + if (tempnode->beaconHBCount) { + /* There was a beacon for this peer during heart beat */ + tempnode->beaconHBCount = 0; + tempnode->heartbeatFailure = 0; + prevnode = tempnode; + tempnode = temp_next; + continue; + } + + /* There wasnt any beacon received during heartbeat timer. */ + tempnode->heartbeatFailure++; + lim_log(mac_ctx, LOGE, FL("Heartbeat fail = %d thres = %d"), + tempnode->heartbeatFailure, mac_ctx->lim.gLimNumIbssPeers); + if (tempnode->heartbeatFailure >= threshold) { + /* Remove this entry from the list. */ + stads = dph_lookup_hash_entry(mac_ctx, + tempnode->peerMacAddr, &peer_idx, + &session->dph.dphHashTable); + if (stads) { + sta_idx = stads->staIndex; + ucast_sig = stads->ucUcastSig; + bcast_sig = stads->ucBcastSig; + + (void)lim_del_sta(mac_ctx, stads, false, + session); + lim_delete_dph_hash_entry(mac_ctx, + stads->staAddr, peer_idx, session); + lim_release_peer_idx(mac_ctx, peer_idx, + session); + /* Send indication. */ + ibss_status_chg_notify(mac_ctx, + tempnode->peerMacAddr, sta_idx, + ucast_sig, bcast_sig, + eWNI_SME_IBSS_PEER_DEPARTED_IND, + session->smeSessionId); + } + if (tempnode == mac_ctx->lim.gLimIbssPeerList) { + mac_ctx->lim.gLimIbssPeerList = tempnode->next; + prevnode = mac_ctx->lim.gLimIbssPeerList; + } else { + prevnode->next = tempnode->next; + } + + cdf_mem_free(tempnode); + mac_ctx->lim.gLimNumIbssPeers--; + + /* we deleted current node, so prevNode remains same. */ + tempnode = temp_next; + continue; + } + prevnode = tempnode; + tempnode = temp_next; + } + + /* + * General IBSS Activity Monitor, + * check if in IBSS Mode we are received any Beacons + */ + if (mac_ctx->lim.gLimNumIbssPeers) { + if (session->LimRxedBeaconCntDuringHB < + MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) + mac_ctx->lim.gLimHeartBeatBeaconStats[ + session->LimRxedBeaconCntDuringHB]++; + else + mac_ctx->lim.gLimHeartBeatBeaconStats[0]++; + + /* Reset number of beacons received */ + limResetHBPktCount(session); + return; + } else { + lim_log(mac_ctx, LOGW, FL("Heartbeat Failure")); + mac_ctx->lim.gLimHBfailureCntInLinkEstState++; + + if (session->limIbssActive == true) { + /* + * We don't receive Beacon frames from any + * other STA in IBSS. Announce IBSS inactive + * to Roaming algorithm + */ + lim_log(mac_ctx, LOGW, FL("Alone in IBSS")); + session->limIbssActive = false; + + lim_send_sme_wm_status_change_ntf(mac_ctx, + eSIR_SME_IBSS_INACTIVE, NULL, 0, + session->smeSessionId); + } + } +} + +/** + * lim_ibss_decide_protection_on_delete() - decides protection related info. + * + * @mac_ctx: global mac context + * @stads: station hash node + * @bcn_param: beacon parameters + * @session: PE session entry + * + * Decides all the protection related information. + * + * Return: None + */ +void lim_ibss_decide_protection_on_delete(tpAniSirGlobal mac_ctx, + tpDphHashNode stads, + tpUpdateBeaconParams bcn_param, + tpPESession session) +{ + uint32_t phymode; + tHalBitVal erpenabled = eHAL_CLEAR; + tSirRFBand rfband = SIR_BAND_UNKNOWN; + uint32_t i; + + if (NULL == stads) + return; + + lim_get_rf_band_new(mac_ctx, &rfband, session); + if (SIR_BAND_2_4_GHZ != rfband) + return; + + lim_get_phy_mode(mac_ctx, &phymode, session); + erpenabled = stads->erpEnabled; + /* we are HT or 11G and 11B station is getting deleted. */ + if (((phymode == WNI_CFG_PHY_MODE_11G) || + session->htCapability) && (erpenabled == eHAL_CLEAR)) { + lim_log(mac_ctx, LOGE, + FL("(%d) A legacy STA is disassociated. Addr is "), + session->gLim11bParams.numSta); + lim_print_mac_addr(mac_ctx, stads->staAddr, LOGE); + if (session->gLim11bParams.numSta == 0) { + lim_log(mac_ctx, LOGE, + FL("No 11B STA exists. Disable protection.")); + lim_ibss_set_protection(mac_ctx, false, + bcn_param, session); + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (!mac_ctx->lim.protStaCache[i].active) + continue; + if (cdf_mem_compare(mac_ctx->lim.protStaCache[i].addr, + stads->staAddr, sizeof(tSirMacAddr))) { + session->gLim11bParams.numSta--; + mac_ctx->lim.protStaCache[i].active = false; + break; + } + } + + } +} + +/** ----------------------------------------------------------------- + \fn __lim_ibss_peer_inactivity_handler + \brief Internal function. Deletes FW indicated peer which is inactive + \ + \param tpAniSirGlobal pMac + \param tpPESession psessionEntry + \param tpSirIbssPeerInactivityInd peerInactivityInd + \return None + -----------------------------------------------------------------*/ +static void +__lim_ibss_peer_inactivity_handler(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSirIbssPeerInactivityInd peerInactivityInd) +{ + if (psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) { + return; + } + + /* delete the peer for which heartbeat is observed */ + __lim_ibss_search_and_delete_peer(pMac, psessionEntry, + peerInactivityInd->peerAddr); + +} + +/** ------------------------------------------------------------- + \fn lim_process_ibss_peer_inactivity + \brief Peer inactivity message handler + \ + \param tpAniSirGlobal pMac + \param void* buf + \return None + -------------------------------------------------------------*/ +void lim_process_ibss_peer_inactivity(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 + */ + uint8_t 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 (true == pMac->lim.gpSession[i].valid && + eSIR_IBSS_MODE == pMac->lim.gpSession[i].bssType) { + __lim_ibss_peer_inactivity_handler(pMac, + &pMac->lim.gpSession[i], + peerInactivityInd); + break; + } + } +} diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h new file mode 100644 index 000000000000..0c97919c3d9f --- /dev/null +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.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 lim_ibss_peer_mgmt.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 "sir_common.h" +#include "lim_utils.h" + +#define IBSS_STATIONS_USED_DURING_INIT 4 /* (broadcast + self + p2p + softap) */ + +void lim_ibss_init(tpAniSirGlobal); +void lim_ibss_delete(tpAniSirGlobal, tpPESession psessionEntry); +tSirRetStatus lim_ibss_coalesce(tpAniSirGlobal, tpSirMacMgmtHdr, + tpSchBeaconStruct, uint8_t *, uint32_t, uint16_t, + tpPESession); +tSirRetStatus lim_ibss_sta_add(tpAniSirGlobal, void *, tpPESession); +tSirRetStatus lim_ibss_add_sta_rsp(tpAniSirGlobal, void *, tpPESession); +tLimIbssPeerNode *lim_ibss_peer_find(tpAniSirGlobal pMac, tSirMacAddr macAddr); +void lim_ibss_del_bss_rsp(tpAniSirGlobal, void *, tpPESession); +void lim_ibss_del_bss_rsp_when_coalescing(tpAniSirGlobal, void *, tpPESession); +void lim_ibss_add_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg, + tpPESession pSessionEntry); +void lim_ibss_decide_protection_on_delete(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpUpdateBeaconParams pBeaconParams, + tpPESession pSessionEntry); +void lim_ibss_heart_beat_handle(tpAniSirGlobal pMac, tpPESession psessionEntry); +void lim_process_ibss_peer_inactivity(tpAniSirGlobal pMac, void *buf); diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c new file mode 100644 index 000000000000..2ce55b062a11 --- /dev/null +++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -0,0 +1,561 @@ +/* + * 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 lim_link_monitoring_algo.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 "ani_global.h" +#include "wni_cfg.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_assoc_utils.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_prop_exts_utils.h" + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ +#include "host_diag_core_log.h" +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_ser_des_utils.h" + +/** + * lim_delete_sta_util - utility function for deleting station context + * + * @mac_ctx: global MAC context + * @msg: pointer to delte station context + * @session_entry: PE session entry + * + * utility function called to clear up station context. + * + * Return: None. + */ +static void lim_delete_sta_util(tpAniSirGlobal mac_ctx, tpDeleteStaContext msg, + tpPESession session_entry) +{ + tpDphHashNode stads; + + lim_log(mac_ctx, LOGE, + FL("Deleting station: staId = %d, reasonCode = %d"), + msg->staId, msg->reasonCode); + + if (LIM_IS_IBSS_ROLE(session_entry)) { + cdf_mem_free(msg); + return; + } + + stads = dph_lookup_assoc_id(mac_ctx, msg->staId, &msg->assocId, + &session_entry->dph.dphHashTable); + + if (!stads) { + lim_log(mac_ctx, LOGE, + FL("Invalid STA limSystemRole=%d"), + GET_LIM_SYSTEM_ROLE(session_entry)); + cdf_mem_free(msg); + 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 (stads->staIndex != msg->staId) { + lim_log(mac_ctx, LOGE, FL("staid mismatch: %d vs %d "), + stads->staIndex, msg->staId); + cdf_mem_free(msg); + return; + } + + if (LIM_IS_BT_AMP_AP_ROLE(session_entry) || + LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOG1, + FL("Delete Station staId: %d, assocId: %d"), + msg->staId, msg->assocId); + /* + * 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 ((stads && + ((stads->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (stads->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE) && + (stads->mlmStaContext.mlmState != + eLIM_MLM_ASSOCIATED_STATE)))) { + lim_log(mac_ctx, LOGE, + FL("Inv Del STA staId:%d, assocId:%d"), + msg->staId, msg->assocId); + cdf_mem_free(msg); + return; + } else { + lim_trigger_sta_deletion(mac_ctx, stads, session_entry); + } + } else { +#ifdef FEATURE_WLAN_TDLS + if (LIM_IS_STA_ROLE(session_entry) && + STA_ENTRY_TDLS_PEER == stads->staType) { + /* + * TeardownLink with PEER reason code + * HAL_DEL_STA_REASON_CODE_KEEP_ALIVE means + * eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE + */ + lim_send_sme_tdls_del_sta_ind(mac_ctx, stads, + session_entry, + eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE); + } else { +#endif + /* TearDownLink with AP */ + tLimMlmDeauthInd mlm_deauth_ind; + lim_log(mac_ctx, LOGW, + FL("Delete Station (staId: %d, assocId: %d) "), + msg->staId, msg->assocId); + + if ((stads && + ((stads->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (stads->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE) && + (stads->mlmStaContext.mlmState != + eLIM_MLM_ASSOCIATED_STATE)))) { + + /* + * Received SIR_LIM_DELETE_STA_CONTEXT_IND for STA that + * does not have context or in some transit state. + * Log error + */ + lim_log(mac_ctx, LOGE, + FL("Received SIR_LIM_DELETE_STA_CONTEXT_IND for " + "STA that either has no context or " + "in some transit state, Addr = " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(msg->bssId)); + cdf_mem_free(msg); + return; + } + + stads->mlmStaContext.disassocReason = + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + stads->mlmStaContext.cleanupTrigger = + eLIM_LINK_MONITORING_DEAUTH; + + /* Issue Deauth Indication to SME. */ + cdf_mem_copy((uint8_t *) &mlm_deauth_ind.peerMacAddr, + stads->staAddr, sizeof(tSirMacAddr)); + mlm_deauth_ind.reasonCode = + (uint8_t) stads->mlmStaContext.disassocReason; + mlm_deauth_ind.deauthTrigger = + stads->mlmStaContext.cleanupTrigger; + +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS */ + lim_delete_tdls_peers(mac_ctx, session_entry); +#endif + lim_post_sme_message(mac_ctx, LIM_MLM_DEAUTH_IND, + (uint32_t *) &mlm_deauth_ind); + + lim_send_sme_deauth_ind(mac_ctx, stads, session_entry); +#ifdef FEATURE_WLAN_TDLS + } +#endif + } +} + +/** + * lim_delete_sta_context() - delete sta context. + * + * @mac_ctx: global mac_ctx context + * @lim_msg: lim message. + * + * This function handles the message from HAL: WMA_DELETE_STA_CONTEXT_IND. + * This function validates that the given station id exist, and if so, + * deletes the station by calling lim_trigger_sta_deletion. + * + * Return: none + */ +void lim_delete_sta_context(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg) +{ + tpDeleteStaContext msg = (tpDeleteStaContext) lim_msg->bodyptr; + tpPESession session_entry; + uint8_t session_id; + + if (NULL == msg) { + lim_log(mac_ctx, LOGE, FL("Invalid body pointer in message")); + return; + } + session_entry = pe_find_session_by_bssid(mac_ctx, msg->bssId, + &session_id); + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, FL("session does not exist")); + cdf_mem_free(msg); + return; + } + + switch (msg->reasonCode) { + case HAL_DEL_STA_REASON_CODE_KEEP_ALIVE: + case HAL_DEL_STA_REASON_CODE_TIM_BASED: + lim_delete_sta_util(mac_ctx, msg, session_entry); + break; + + case HAL_DEL_STA_REASON_CODE_UNKNOWN_A2: + lim_log(mac_ctx, LOGE, FL("Deleting Unknown station ")); + lim_print_mac_addr(mac_ctx, msg->addr2, LOGE); + lim_send_deauth_mgmt_frame(mac_ctx, + eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON, + msg->addr2, session_entry, false); + break; + + default: + lim_log(mac_ctx, LOGE, FL(" Unknown reason code ")); + break; + } + cdf_mem_free(msg); + return; +} + +/** + * lim_trigger_sta_deletion() + * + ***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 +lim_trigger_sta_deletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry) +{ + tSirSmeDeauthReq *pSmeDeauthReq; + uint8_t *pBuf; + uint8_t *pLen; + uint16_t msgLength = 0; + + if (!pStaDs) { + PELOGW(lim_log + (pMac, LOGW, FL("Skip STA deletion (invalid STA)")); + ) + return; + } + /** + * MAC based Authentication was used. Trigger + * Deauthentication frame to peer since it will + * take care of disassociation as well. + */ + + pSmeDeauthReq = cdf_mem_malloc(sizeof(tSirSmeDeauthReq)); + if (NULL == pSmeDeauthReq) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for eWNI_SME_DEAUTH_REQ ")); + return; + } + + pBuf = (uint8_t *) &pSmeDeauthReq->messageType; + + /* messageType */ + lim_copy_u16((uint8_t *) pBuf, eWNI_SME_DISASSOC_REQ); + pBuf += sizeof(uint16_t); + msgLength += sizeof(uint16_t); + + /* length */ + pLen = pBuf; + pBuf += sizeof(uint16_t); + msgLength += sizeof(uint16_t); + + /* sessionId */ + *pBuf = psessionEntry->smeSessionId; + pBuf++; + msgLength++; + + /* transactionId */ + lim_copy_u16((uint8_t *) pBuf, psessionEntry->transactionId); + pBuf += sizeof(uint16_t); + msgLength += sizeof(uint16_t); + + /* bssId */ + cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + msgLength += sizeof(tSirMacAddr); + + /* peerMacAddr */ + cdf_mem_copy(pBuf, pStaDs->staAddr, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + msgLength += sizeof(tSirMacAddr); + + /* reasonCode */ + lim_copy_u16((uint8_t *) pBuf, (uint16_t) eLIM_LINK_MONITORING_DISASSOC); + pBuf += sizeof(uint16_t); + msgLength += sizeof(uint16_t); + + /* Do not send disassoc OTA */ + /* pBuf[0] = 1 means do not send the disassoc frame over the air */ + /* pBuf[0] = 0 means send the disassoc frame over the air */ + pBuf[0] = 0; + pBuf += sizeof(uint8_t); + msgLength += sizeof(uint8_t); + + /* Fill in length */ + lim_copy_u16((uint8_t *) pLen, msgLength); + + lim_post_sme_message(pMac, eWNI_SME_DISASSOC_REQ, + (uint32_t *) pSmeDeauthReq); + cdf_mem_free(pSmeDeauthReq); + +} /*** end lim_trigger_st_adeletion() ***/ + +/** + * lim_tear_down_link_with_ap() + * + ***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 +lim_tear_down_link_with_ap(tpAniSirGlobal pMac, uint8_t sessionId, + tSirMacReasonCodes reasonCode) +{ + tpDphHashNode pStaDs = NULL; + + /* tear down the following sessionEntry */ + tpPESession psessionEntry; + + if ((psessionEntry = pe_find_session_by_session_id(pMac, sessionId)) == NULL) { + lim_log(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. + */ + psessionEntry->pmmOffloadInfo.bcnmiss = false; + + lim_log(pMac, LOGW, + FL("No ProbeRsp from AP after HB failure. Tearing down link")); + + /* Announce loss of link to Roaming algorithm */ + /* and cleanup by sending SME_DISASSOC_REQ to SME */ + + pStaDs = + dph_get_hash_entry(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 */ + lim_delete_tdls_peers(pMac, psessionEntry); +#endif + + pStaDs->mlmStaContext.disassocReason = reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = + eLIM_LINK_MONITORING_DEAUTH; + + /* + * 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 + * Tx inactivity timer by FWR. 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; + + /* / Issue Deauth Indication to SME. */ + cdf_mem_copy((uint8_t *) &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; + + lim_log(pMac, LOGE, FL("HB Failure on MAC " + MAC_ADDRESS_STR" Store it on Index %d"), + MAC_ADDR_ARRAY(pStaDs->staAddr),apCount); + + sir_copy_mac_addr(pMac->lim.gLimHeartBeatApMac[apCount], + pStaDs->staAddr); + } + + mlmDeauthInd.reasonCode = + (uint8_t) pStaDs->mlmStaContext.disassocReason; + mlmDeauthInd.deauthTrigger = + pStaDs->mlmStaContext.cleanupTrigger; + + lim_post_sme_message(pMac, LIM_MLM_DEAUTH_IND, + (uint32_t *) &mlmDeauthInd); + + lim_send_sme_deauth_ind(pMac, pStaDs, psessionEntry); + } +} /*** lim_tear_down_link_with_ap() ***/ + +/** + * lim_handle_heart_beat_failure() - handle hear beat failure in STA + * + * @mac_ctx: global MAC context + * @session: PE session entry + * + * This function is called when heartbeat (beacon reception) + * fails on STA + * + * Return: None + */ + +void lim_handle_heart_beat_failure(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + uint8_t curr_chan; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + host_log_beacon_update_pkt_type *log_ptr = NULL; +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_beacon_update_pkt_type, + LOG_WLAN_BEACON_UPDATE_C); + if (log_ptr) + log_ptr->bcn_rx_cnt = session->LimRxedBeaconCntDuringHB; + WLAN_HOST_DIAG_LOG_REPORT(log_ptr); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + /* Ensure HB Status for the session has been reseted */ + session->LimHBFailureStatus = false; + + if ((LIM_IS_STA_ROLE(session) || + LIM_IS_BT_AMP_STA_ROLE(session)) && + (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) && + (session->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && + (session->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) { + if (!mac_ctx->sys.gSysEnableLinkMonitorMode) + return; + + /* Beacon frame not received within heartbeat timeout. */ + lim_log(mac_ctx, LOGW, FL("Heartbeat Failure")); + mac_ctx->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 + */ + curr_chan = session->currentOperChannel; + if (!lim_isconnected_on_dfs_channel(curr_chan)) { + /* Detected continuous Beacon Misses */ + session->LimHBFailureStatus = true; + + /*Reset the HB packet count before sending probe*/ + limResetHBPktCount(session); + /** + * Send Probe Request frame to AP to see if + * it is still around. Wait until certain + * timeout for Probe Response from AP. + */ + lim_log(mac_ctx, LOGW, + FL("HB missed from AP. Sending Probe Req")); + /* for searching AP, we don't include any more IE */ + lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId, + session->bssId, curr_chan, session->selfMacAddr, + session->dot11mode, 0, NULL); + } else { + lim_log(mac_ctx, LOGW, + FL("HB missed from AP on DFS chanel moving to passive")); + if (curr_chan < SIR_MAX_24G_5G_CHANNEL_RANGE) { + lim_covert_channel_scan_type(mac_ctx, curr_chan, + false); + mac_ctx->lim.dfschannelList.timeStamp[curr_chan] + = 0; + } + /* + * Connected on DFS channel so should not send the + * probe request tear down the link directly + */ + lim_tear_down_link_with_ap(mac_ctx, + session->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. + */ + lim_log(mac_ctx, LOG1, + FL("received heartbeat timeout in state %X"), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOG1, session->limMlmState); + mac_ctx->lim.gLimHBfailureCntInOtherStates++; + } +} diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c new file mode 100644 index 000000000000..7f29157ddfcd --- /dev/null +++ b/core/mac/src/pe/lim/lim_p2p.c @@ -0,0 +1,794 @@ +/* + * 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. + */ + +/*=========================================================================== + 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 "lim_utils.h" +#include "lim_session_utils.h" +#include "wma_types.h" +#include "lim_types.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 lim_exit_remain_on_channel(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry); +extern tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state, + tSirMacAddr bssId, tSirMacAddr selfMacAddr, + tpSetLinkStateCallback callback, + void *callbackArg); + +CDF_STATUS lim_p2p_action_cnf(tpAniSirGlobal pMac, uint32_t txCompleteSuccess); + +/*------------------------------------------------------------------ + * + * Below function is called if hdd requests a remain on channel. + * + *------------------------------------------------------------------*/ +static CDF_STATUS lim_send_hal_req_remain_on_chan_offload(tpAniSirGlobal pMac, + tSirRemainOnChnReq * + pRemOnChnReq) +{ + tSirScanOffloadReq *pScanOffloadReq; + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + uint8_t bssid[CDF_MAC_ADDR_SIZE] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + pScanOffloadReq = cdf_mem_malloc(sizeof(tSirScanOffloadReq)); + if (NULL == pScanOffloadReq) { + lim_log(pMac, LOGE, + FL("Memory allocation failed for pScanOffloadReq")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(pScanOffloadReq, sizeof(tSirScanOffloadReq)); + + msg.type = WMA_START_SCAN_OFFLOAD_REQ; + msg.bodyptr = pScanOffloadReq; + msg.bodyval = 0; + + cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr, + (uint8_t *) pRemOnChnReq->selfMacAddr, + sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId, + (uint8_t *) 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; + pScanOffloadReq->scan_id = pRemOnChnReq->scan_id; + + lim_log(pMac, LOG1, + FL("Req-rem-on-channel: duration %u, session %hu, chan %hu"), + pRemOnChnReq->duration, pRemOnChnReq->sessionId, + pRemOnChnReq->chnNum); + + rc = wma_post_ctrl_msg(pMac, &msg); + if (rc != eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure %u"), + rc); + cdf_mem_free(pScanOffloadReq); + return CDF_STATUS_E_FAILURE; + } + + return CDF_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 lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg) +{ + tSirRemainOnChnReq *msgbuff = (tSirRemainOnChnReq *) pMsg; + CDF_STATUS status; + + pMac->lim.gpLimRemainOnChanReq = msgbuff; + status = lim_send_hal_req_remain_on_chan_offload(pMac, msgbuff); + if (status != CDF_STATUS_SUCCESS) { + /* Post the meessage to Sme */ + lim_send_sme_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, + status, msgbuff->sessionId, msgbuff->scan_id); + cdf_mem_free(pMac->lim.gpLimRemainOnChanReq); + pMac->lim.gpLimRemainOnChanReq = NULL; + } + return false; +} + +/*------------------------------------------------------------------ + * + * lim Insert NOA timer timeout callback - when timer fires, deactivate it and send + * scan rsp to csr/hdd + * + *------------------------------------------------------------------*/ +void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac) +{ + /* timeout means start NOA did not arrive; we need to deactivate and change the timer for + * future activations + */ + lim_deactivate_and_change_timer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); + + /* Even if insert NOA timedout, go ahead and process/send stored SME request */ + lim_process_regd_defd_sme_req_after_noa_start(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 lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac) +{ + uint32_t currentTime; + uint32_t lastTime = 0; + uint32_t timeDiff; + uint8_t i; + currentTime = cdf_mc_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) { + lim_covert_channel_scan_type(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) { + lim_log(pMac, LOGE, + FL + ("Could not activate Active to Passive Channel timer")); + } + } + + return; + +} + +/** + * lim_process_remain_on_chn_timeout() - ROC timeout handler + * + * @mac_ctx: MAC context + * + * limchannelchange callback, on success channel change, set the + * link_state to LISTEN + * + * Return: NULL + */ +void lim_process_remain_on_chn_timeout(tpAniSirGlobal mac_ctx) +{ + tpPESession session; + tSirMacAddr null_bssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + TX_TIMER *roc_timer; + + roc_timer = &mac_ctx->lim.limTimers.gLimRemainOnChannelTimer; + /* + * Timer might get extended while Sending Action Frame + * In that case don't process Channel Timeout + */ + if (tx_timer_running(roc_timer)) { + lim_log(mac_ctx, LOGE, + FL("already timer is running and not processing ")); + return; + } + + lim_deactivate_and_change_timer(mac_ctx, eLIM_REMAIN_CHN_TIMER); + if (NULL == mac_ctx->lim.gpLimRemainOnChanReq) { + lim_log(mac_ctx, LOGE, FL("No Remain on channel pending")); + return; + } + + /* get the previous valid LINK state */ + if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE, null_bssid, + mac_ctx->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS) + { + lim_log(mac_ctx, LOGE, FL("Unable to change link state")); + return; + } + + if (mac_ctx->lim.gLimMlmState != eLIM_MLM_P2P_LISTEN_STATE) { + lim_remain_on_chn_rsp(mac_ctx, CDF_STATUS_SUCCESS, NULL); + } else { + session = pe_find_session_by_session_id(mac_ctx, + roc_timer->sessionId); + /* get the session */ + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("Session Does not exist sessionID %d"), + roc_timer->sessionId); + goto error; + } + + lim_exit_remain_on_channel(mac_ctx, CDF_STATUS_SUCCESS, NULL, + session); + return; +error: + lim_remain_on_chn_rsp(mac_ctx, CDF_STATUS_E_FAILURE, NULL); + } + return; +} + +/*------------------------------------------------------------------ + * + * limchannelchange callback, on success channel change, set the link_state + * to LISTEN + * + *------------------------------------------------------------------*/ + +void lim_exit_remain_on_channel(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry) +{ + + if (status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log(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. */ + pe_set_resume_channel(pMac, 0, 0); + lim_remain_on_chn_rsp(pMac, CDF_STATUS_SUCCESS, NULL); + return; +error: + lim_remain_on_chn_rsp(pMac, CDF_STATUS_E_FAILURE, NULL); + return; +} + +/*------------------------------------------------------------------ + * + * Send remain on channel respone: Success/ Failure + * + *------------------------------------------------------------------*/ +void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data) +{ + tpPESession psessionEntry; + uint8_t sessionId; + tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq; + tSirMacAddr nullBssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + if (NULL == MsgRemainonChannel) { + PELOGE(lim_log(pMac, LOGP, + "%s: No Pointer for Remain on Channel Req", + __func__); + ) + return; + } + /* Incase of the Remain on Channel Failure Case */ + /* Cleanup Everything */ + if (CDF_STATUS_E_FAILURE == status) { + /* Deactivate Remain on Channel Timer */ + lim_deactivate_and_change_timer(pMac, eLIM_REMAIN_CHN_TIMER); + + /* Set the Link State to Idle */ + /* get the previous valid LINK state */ + if (lim_set_link_state(pMac, eSIR_LINK_IDLE_STATE, nullBssid, + pMac->lim.gSelfMacAddr, NULL, + NULL) != eSIR_SUCCESS) { + lim_log(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 = pe_find_session_by_bssid(pMac, + MsgRemainonChannel-> + selfMacAddr, + &sessionId)) != NULL) { + if (LIM_IS_P2P_DEVICE_ROLE(psessionEntry)) { + pe_delete_session(pMac, psessionEntry); + } + } + + /* Post the meessage to Sme */ + lim_send_sme_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, + status, + MsgRemainonChannel->sessionId, 0); + + cdf_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) { + lim_p2p_action_cnf(pMac, 0); + } + + return; +} + +/*------------------------------------------------------------------ + * + * Indicate the Mgmt Frame received to SME to HDD callback + * handle Probe_req/Action frame currently + * + *------------------------------------------------------------------*/ +void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, + uint8_t *frame, uint32_t frameLen, + uint16_t sessionId, uint32_t rxChannel, + tpPESession psessionEntry, int8_t rxRssi) +{ + tSirMsgQ mmhMsg; + tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL; + uint16_t length; + + length = sizeof(tSirSmeMgmtFrameInd) + frameLen; + + pSirSmeMgmtFrame = cdf_mem_malloc(length); + if (NULL == pSirSmeMgmtFrame) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for eWNI_SME_LISTEN_RSP")); + return; + } + cdf_mem_set((void *)pSirSmeMgmtFrame, length, 0); + + pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND; + pSirSmeMgmtFrame->mesgLen = length; + pSirSmeMgmtFrame->sessionId = sessionId; + pSirSmeMgmtFrame->frameType = frameType; + pSirSmeMgmtFrame->rxRssi = rxRssi; + pSirSmeMgmtFrame->rxChan = rxChannel; + + cdf_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen); + cdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); + + mmhMsg.type = eWNI_SME_MGMT_FRM_IND; + mmhMsg.bodyptr = pSirSmeMgmtFrame; + mmhMsg.bodyval = 0; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} + +CDF_STATUS lim_p2p_action_cnf(tpAniSirGlobal pMac, uint32_t txCompleteSuccess) +{ + if (pMac->lim.mgmtFrameSessionId != 0xff) { + /* The session entry might be invalid(0xff) action confirmation received after + * remain on channel timer expired */ + lim_send_sme_rsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, + (txCompleteSuccess ? eSIR_SME_SUCCESS : + eSIR_SME_SEND_ACTION_FAIL), + pMac->lim.mgmtFrameSessionId, 0); + pMac->lim.mgmtFrameSessionId = 0xff; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * lim_tx_action_frame() - Handles action frame transmission request + * @mac_ctx: Pointer to mac context + * @mb_msg: message sent from SME + * @msg_len: Message length + * @packet: network buffer for TX + * @frame: frame buffer + * + * This function processes the action frame transmission request and + * posts message to WMA. + * + * Return: NULL + */ +static void lim_tx_action_frame(tpAniSirGlobal mac_ctx, + tSirMbMsgP2p *mb_msg, uint32_t msg_len, void *packet, uint8_t *frame) +{ + uint8_t tx_flag = 0; + tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data; + CDF_STATUS cdf_status; + uint8_t sme_session_id = 0; + uint16_t channel_freq; + + sme_session_id = mb_msg->sessionId; + channel_freq = mb_msg->channel_freq; + /* + * 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. + */ + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + if ((SIR_MAC_MGMT_PROBE_RSP == fc->subType) || + (mb_msg->noack)) { + cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) msg_len, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, 7, lim_tx_complete, + frame, tx_flag, sme_session_id, + channel_freq); + + if (!mb_msg->noack) + lim_send_sme_rsp(mac_ctx, + eWNI_SME_ACTION_FRAME_SEND_CNF, + cdf_status, mb_msg->sessionId, 0); + mac_ctx->lim.mgmtFrameSessionId = 0xff; + } else { + mac_ctx->lim.mgmtFrameSessionId = mb_msg->sessionId; + cdf_status = + wma_tx_frameWithTxComplete(mac_ctx, packet, + (uint16_t) msg_len, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, 7, lim_tx_complete, + frame, lim_p2p_action_cnf, tx_flag, + sme_session_id, false, + channel_freq); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("couldn't send action frame")); + lim_send_sme_rsp(mac_ctx, + eWNI_SME_ACTION_FRAME_SEND_CNF, + cdf_status, mb_msg->sessionId, 0); + mac_ctx->lim.mgmtFrameSessionId = 0xff; + } else { + mac_ctx->lim.mgmtFrameSessionId = mb_msg->sessionId; + lim_log(mac_ctx, LOG2, + FL("lim.actionFrameSessionId = %u"), + mac_ctx->lim.mgmtFrameSessionId); + } + } + + return; +} + +/** + * lim_send_p2p_action_frame() - Process action frame request + * @mac_ctx: Pointer to mac context + * @msg: message sent from SME + * + * This function processes the action frame request sent from the + * SME and generates the ACTION frame. + * + * Return: NULL + */ +void lim_send_p2p_action_frame(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + tSirMbMsgP2p *mb_msg = (tSirMbMsgP2p *) msg->bodyptr; + uint32_t msg_len; + uint8_t *frame; + void *packet; + CDF_STATUS cdf_status; + tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data; + uint8_t noa_len = 0; + uint8_t noa_stream[SIR_MAX_NOA_ATTR_LEN + (2 * SIR_P2P_IE_HEADER_LEN)]; + uint8_t orig_len = 0; + uint8_t session_id = 0; + uint8_t *p2p_ie = NULL; + tpPESession session_entry = NULL; + uint8_t *presence_noa_attr = NULL; + uint8_t *tmp_p2p_ie = NULL; + uint16_t remain_len = 0; + uint8_t sme_session_id = 0; +#ifdef WLAN_FEATURE_11W + tpSirMacMgmtHdr mac_hdr; + tpSirMacActionFrameHdr action_hdr; +#endif + + msg_len = mb_msg->msgLen - sizeof(tSirMbMsgP2p); + lim_log(mac_ctx, LOG1, FL("sending fc->type=%d fc->subType=%d"), + fc->type, fc->subType); + + if ((!mac_ctx->lim.gpLimRemainOnChanReq) && (0 != mb_msg->wait)) { + lim_log(mac_ctx, LOGE, + FL("RemainOnChannel is not running\n")); + lim_send_sme_rsp(mac_ctx, eWNI_SME_ACTION_FRAME_SEND_CNF, + CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0); + return; + } + sme_session_id = mb_msg->sessionId; + + if ((SIR_MAC_MGMT_FRAME == fc->type) && + (SIR_MAC_MGMT_PROBE_RSP == fc->subType)) { + /* get proper offset for Probe RSP */ + p2p_ie = limGetP2pIEPtr(mac_ctx, + (uint8_t *) mb_msg->data + + PROBE_RSP_IE_OFFSET, + msg_len - PROBE_RSP_IE_OFFSET); + while ((NULL != p2p_ie) + && (SIR_MAC_MAX_IE_LENGTH == p2p_ie[1])) { + remain_len = + msg_len - (p2p_ie - + (uint8_t *) mb_msg->data); + if (remain_len > 2) { + tmp_p2p_ie = limGetP2pIEPtr(mac_ctx, + p2p_ie + SIR_MAC_MAX_IE_LENGTH + 2, + remain_len); + } + if (tmp_p2p_ie) { + p2p_ie = tmp_p2p_ie; + tmp_p2p_ie = NULL; + } else { + break; + } + } /* end of while */ + } else if ((SIR_MAC_MGMT_FRAME == fc->type) && + (SIR_MAC_MGMT_ACTION == fc->subType) && + (SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY == + *((uint8_t *) mb_msg->data + ACTION_OFFSET))) { + tpSirMacP2PActionFrameHdr action_hdr = + (tpSirMacP2PActionFrameHdr) ((uint8_t *) + mb_msg->data + ACTION_OFFSET); + if (cdf_mem_compare(action_hdr->Oui, SIR_MAC_P2P_OUI, + SIR_MAC_P2P_OUI_SIZE) && + (SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP == + action_hdr->OuiSubType)) { + + /* In case of Presence RSP response */ + p2p_ie = limGetP2pIEPtr(mac_ctx, + (uint8_t *)mb_msg->data + + ACTION_OFFSET + + sizeof(tSirMacP2PActionFrameHdr), + (msg_len - ACTION_OFFSET + - sizeof(tSirMacP2PActionFrameHdr))); + if (NULL != p2p_ie) { + /* extract the presence of NoA attribute inside + * P2P IE */ + presence_noa_attr = lim_get_ie_ptr_new(mac_ctx, + p2p_ie + SIR_P2P_IE_HEADER_LEN, + p2p_ie[1], SIR_P2P_NOA_ATTR, TWO_BYTE); + } + } + } + + if ((SIR_MAC_MGMT_FRAME == fc->type) && + (SIR_MAC_MGMT_PROBE_RSP == fc->subType || + SIR_MAC_MGMT_ACTION == fc->subType) && p2p_ie != NULL) { + /* get NoA attribute stream P2P IE */ + noa_len = + lim_get_noa_attr_stream(mac_ctx, noa_stream, + session_entry); + /* need to append NoA attribute in P2P IE */ + if (noa_len > 0) { + orig_len = p2p_ie[1]; + /* if Presence Rsp has NoAttr */ + if (presence_noa_attr) { + uint16_t noa_len = + presence_noa_attr[1] | + (presence_noa_attr[2] << 8); + /*One byte for attribute, 2bytes for length */ + orig_len -= (noa_len + 1 + 2); + /* remove those bytes to copy */ + msg_len -= (noa_len + 1 + 2); + /* remove NoA from original Len */ + p2p_ie[1] = orig_len; + } + if ((p2p_ie[1] + (uint16_t) noa_len) > + SIR_MAC_MAX_IE_LENGTH) { + /* + * Form the new NoA Byte array in multiple + * P2P IEs + */ + noa_len = + lim_get_noa_attr_stream_in_mult_p2p_ies + (mac_ctx, noa_stream, noa_len, + ((p2p_ie[1] + (uint16_t)noa_len) + - SIR_MAC_MAX_IE_LENGTH)); + p2p_ie[1] = SIR_MAC_MAX_IE_LENGTH; + } else { + /* increment the length of P2P IE */ + p2p_ie[1] += noa_len; + } + msg_len += noa_len; + lim_log(mac_ctx, LOGE, + FL("noa_len=%d orig_len=%d p2p_ie=%p" + " msg_len=%d nBytesToCopy=%zu "), + noa_len, orig_len, p2p_ie, msg_len, + ((p2p_ie + orig_len + 2) - + (uint8_t *) mb_msg->data)); + } + } + + if ((SIR_MAC_MGMT_PROBE_RSP == fc->subType || + SIR_MAC_MGMT_ACTION == fc->subType)) + lim_set_ht_caps(mac_ctx, session_entry, + (uint8_t *) mb_msg->data + PROBE_RSP_IE_OFFSET, + msg_len - PROBE_RSP_IE_OFFSET); + + /* Ok-- try to allocate some memory: */ + cdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame, + (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to allocate %d bytes for a Probe Request."), + msg_len); + return; + } + /* Paranoia: */ + cdf_mem_set(frame, msg_len, 0); + + /* + * Add sequence number to action frames + * Frames are handed over in .11 format by supplicant already + */ + lim_populate_p2p_mac_header(mac_ctx, (uint8_t *) mb_msg->data); + + if ((noa_len > 0) + && (noa_len < (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN))) { + /* Add 2 bytes for length and Arribute field */ + uint32_t nBytesToCopy = ((p2p_ie + orig_len + 2) - + (uint8_t *) mb_msg->data); + cdf_mem_copy(frame, mb_msg->data, nBytesToCopy); + cdf_mem_copy((frame + nBytesToCopy), noa_stream, noa_len); + cdf_mem_copy((frame + nBytesToCopy + noa_len), + mb_msg->data + nBytesToCopy, + msg_len - nBytesToCopy - noa_len); + + } else { + cdf_mem_copy(frame, mb_msg->data, msg_len); + } + +#ifdef WLAN_FEATURE_11W + action_hdr = (tpSirMacActionFrameHdr) (frame + sizeof(tSirMacMgmtHdr)); + + /* + * Setting Protected bit for SA_QUERY Action Frame + * This has to be based on the current Connection with the + * station lim_set_protected_bit API will set the protected bit + * if PMF + */ + if ((SIR_MAC_MGMT_ACTION == fc->subType) && + (SIR_MAC_ACTION_SA_QUERY == action_hdr->category)) { + mac_hdr = (tpSirMacMgmtHdr) frame; + session_entry = pe_find_session_by_bssid(mac_ctx, + (uint8_t *) mb_msg->data + BSSID_OFFSET, + &session_id); + + /* + * Check for session corresponding to ADDR2 ss supplicant + * is filling ADDR2 with BSSID + */ + if (NULL == session_entry) { + session_entry = pe_find_session_by_bssid(mac_ctx, + (uint8_t *) mb_msg->data + ADDR2_OFFSET, + &session_id); + } + + if (NULL != session_entry) { + lim_set_protected_bit(mac_ctx, session_entry, + mac_hdr->da, mac_hdr); + } else { + lim_log(mac_ctx, LOGE, + FL("Dropping SA Query - PE Session not found")); + lim_send_sme_rsp(mac_ctx, + eWNI_SME_ACTION_FRAME_SEND_CNF, + CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0); + cds_packet_free((void *)packet); + return; + } + + /* + * If wep bit is not set in MAC header then we are trying to + * send SA Query via non PMF connection. Drop the packet. + */ + if (0 == mac_hdr->fc.wep) { + lim_log(mac_ctx, LOGE, + FL("Dropping SA Query due to non PMF conne.")); + lim_send_sme_rsp(mac_ctx, + eWNI_SME_ACTION_FRAME_SEND_CNF, + CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0); + cds_packet_free((void *)packet); + return; + } + } +#endif + lim_tx_action_frame(mac_ctx, mb_msg, msg_len, packet, frame); + return; +} + +void lim_abort_remain_on_chan(tpAniSirGlobal pMac, uint8_t sessionId, + uint32_t scan_id) +{ + lim_process_abort_scan_ind(pMac, sessionId, scan_id); +} + +/* Power Save Related Functions */ +tSirRetStatus __lim_process_sme_no_a_update(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpP2pPsConfig pNoA; + tpP2pPsParams pMsgNoA; + tSirMsgQ msg; + + pNoA = (tpP2pPsConfig) pMsgBuf; + + pMsgNoA = cdf_mem_malloc(sizeof(tP2pPsConfig)); + if (NULL == pMsgNoA) { + lim_log(pMac, LOGE, + FL("Unable to allocate memory during NoA Update")); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) 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 = WMA_SET_P2P_GO_NOA_REQ; + msg.reserved = 0; + msg.bodyptr = pMsgNoA; + msg.bodyval = 0; + + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + lim_log(pMac, LOGE, FL("halPostMsgApi failed")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /*** end __limProcessSmeGoNegReq() ***/ diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c new file mode 100644 index 000000000000..c77ae536ae93 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -0,0 +1,2093 @@ +/* + * 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 lim_process_action_frame.cc contains the code + * for processing Action Frame. + * Author: Michael Lui + * Date: 05/23/03 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "cds_api.h" +#include "wni_api.h" +#include "sir_api.h" +#include "ani_global.h" +#include "wni_cfg.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_send_sme_rsp_messages.h" +#include "parser_api.h" +#include "lim_admit_control.h" +#include "wmm_apsd.h" +#include "lim_send_messages.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif +#include "lim_session_utils.h" + +#include "wma_types.h" + + +#define BA_DEFAULT_TX_BUFFER_SIZE 64 + +/* 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 lim_stop_tx_and_switch_channel + \brief Stops the transmission if channel switch mode is silent and + starts the channel switch timer. + + \param pMac + \return NONE + -----------------------------------------------------------------*/ +void lim_stop_tx_and_switch_channel(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tpPESession psessionEntry; + + psessionEntry = pe_find_session_by_session_id(pMac, sessionId); + + if (NULL == psessionEntry) { + lim_log(pMac, LOGE, FL("Session %d not active"), sessionId); + return; + } + + PELOG1(lim_log(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 */ + lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_STOP_TX); + + } else { + /* Resume the transmission */ + lim_frame_transmission_control(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 + */ + if (psessionEntry->gLimChannelSwitch.switchCount == 0) { + lim_process_channel_switch_timeout(pMac); + return; + } + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, + eLIM_CHANNEL_SWITCH_TIMER)); + + if (tx_timer_activate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != + TX_SUCCESS) { + lim_log(pMac, LOGP, FL("tx_timer_activate failed")); + } + return; +} + +/**------------------------------------------------------------ + \fn lim_start_channel_switch + \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 lim_start_channel_switch(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + PELOG1(lim_log(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 ((lim_is_chan_switch_running(pMac) && + psessionEntry->gLimSpecMgmt.dot11hChanSwState != + eLIM_11H_CHANSW_RUNNING) || psessionEntry->csaOffloadEnable) { + lim_log(pMac, LOGW, FL("Ignoring channel switch on session %d"), + psessionEntry->peSessionId); + return eSIR_SUCCESS; + } + + /* Deactivate and change reconfigure the timeout value */ + /* lim_deactivate_and_change_timer(pMac, eLIM_CHANNEL_SWITCH_TIMER); */ + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, + eLIM_CHANNEL_SWITCH_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("tx_timer_deactivate failed!")); + return eSIR_FAILURE; + } + + if (tx_timer_change(&pMac->lim.limTimers.gLimChannelSwitchTimer, + psessionEntry->gLimChannelSwitch.switchTimeoutValue, + 0) != TX_SUCCESS) { + lim_log(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(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, + psessionEntry->peSessionId, eLIM_QUIET_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != + TX_SUCCESS) { + lim_log(pMac, LOGP, FL("tx_timer_deactivate failed")); + return eSIR_FAILURE; + } + } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) { + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, + psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) + != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("tx_timer_deactivate failed")); + return eSIR_FAILURE; + } + } + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + + /* Prepare for 11h channel switch */ + lim_prepare_for11h_channel_switch(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; +} + +/** + * __lim_process_channel_switch_action_frame() - to process channel switch + * @mac_ctx: Pointer to Global MAC structure + * @rx_pkt_info: A pointer to packet info structure + * + * This routine will be called to process channel switch action frame + * + * Return: None + */ + +static void __lim_process_channel_switch_action_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + tpSirMacMgmtHdr mac_hdr; + uint8_t *body_ptr; + tDot11fChannelSwitch *chnl_switch_frame; + uint16_t bcn_period; + uint32_t val, frame_len, status; + tLimChannelSwitchInfo *ch_switch_params; + struct sDot11fIEWiderBWChanSwitchAnn *wbw_chnlswitch_ie = NULL; + struct sLimWiderBWChannelSwitch *lim_wbw_chnlswitch_info = NULL; + struct sDot11fIEsec_chan_offset_ele *sec_chnl_offset = NULL; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + PELOG3(lim_log(mac_ctx, LOG3, + FL("Received Channel switch action frame"));) + if (!session->lim11hEnable) + return; + + chnl_switch_frame = cdf_mem_malloc(sizeof(*chnl_switch_frame)); + if (NULL == chnl_switch_frame) { + lim_log(mac_ctx, LOGE, FL("AllocateMemory failed")); + return; + } + + /* Unpack channel switch frame */ + status = dot11f_unpack_channel_switch(mac_ctx, body_ptr, frame_len, + chnl_switch_frame); + + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to unpack and parse (0x%08x, %d bytes)"), + status, frame_len); + cdf_mem_free(chnl_switch_frame); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("warning: unpack 11h-CHANSW Req(0x%08x, %d bytes)"), + status, frame_len); + } + + if (!(cdf_mem_compare((uint8_t *) &session->bssId, + (uint8_t *) &mac_hdr->sa, sizeof(tSirMacAddr)))) { + lim_log(mac_ctx, LOG1, + FL("Rcvd action frame not from our BSS, dropping...")); + cdf_mem_free(chnl_switch_frame); + return; + } + /* copy the beacon interval from session */ + val = session->beaconParams.beaconInterval; + ch_switch_params = &session->gLimChannelSwitch; + bcn_period = (uint16_t)val; + ch_switch_params->primaryChannel = + chnl_switch_frame->ChanSwitchAnn.newChannel; + ch_switch_params->switchCount = + chnl_switch_frame->ChanSwitchAnn.switchCount; + ch_switch_params->switchTimeoutValue = + SYS_MS_TO_TICKS(bcn_period) * + session->gLimChannelSwitch.switchCount; + ch_switch_params->switchMode = + chnl_switch_frame->ChanSwitchAnn.switchMode; + + /* Only primary channel switch element is present */ + ch_switch_params->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + ch_switch_params->ch_width = CH_WIDTH_20MHZ; + + if (chnl_switch_frame->WiderBWChanSwitchAnn.present + && session->vhtCapability) { + wbw_chnlswitch_ie = &chnl_switch_frame->WiderBWChanSwitchAnn; + session->gLimWiderBWChannelSwitch.newChanWidth = + wbw_chnlswitch_ie->newChanWidth; + session->gLimWiderBWChannelSwitch.newCenterChanFreq0 = + wbw_chnlswitch_ie->newCenterChanFreq0; + session->gLimWiderBWChannelSwitch.newCenterChanFreq1 = + wbw_chnlswitch_ie->newCenterChanFreq1; + } + lim_log(mac_ctx, LOG3, + FL("Rcv Chnl Swtch Frame: Timeout in %d ticks"), + session->gLimChannelSwitch.switchTimeoutValue); + if (session->htSupportedChannelWidthSet) { + sec_chnl_offset = &chnl_switch_frame->sec_chan_offset_ele; + if (sec_chnl_offset->secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + ch_switch_params->state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + ch_switch_params->ch_width = CH_WIDTH_40MHZ; + ch_switch_params->ch_center_freq_seg0 = + ch_switch_params->primaryChannel + 2; + } else if (sec_chnl_offset->secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) { + ch_switch_params->state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + ch_switch_params->ch_width = CH_WIDTH_40MHZ; + ch_switch_params->ch_center_freq_seg0 = + ch_switch_params->primaryChannel - 2; + + } + if (session->vhtCapability && + chnl_switch_frame->WiderBWChanSwitchAnn.present) { + wbw_chnlswitch_ie = + &chnl_switch_frame->WiderBWChanSwitchAnn; + ch_switch_params->ch_width = + wbw_chnlswitch_ie->newChanWidth + 1; + lim_wbw_chnlswitch_info = + &session->gLimWiderBWChannelSwitch; + ch_switch_params->ch_center_freq_seg0 = + lim_wbw_chnlswitch_info->newCenterChanFreq0; + ch_switch_params->ch_center_freq_seg1 = + lim_wbw_chnlswitch_info->newCenterChanFreq1; + + } + } + + if (CH_WIDTH_20MHZ == ch_switch_params->ch_width) { + session->htSupportedChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + session->htRecommendedTxWidthSet = + session->htSupportedChannelWidthSet; + } + + if (eSIR_SUCCESS != lim_start_channel_switch(mac_ctx, session)) + lim_log(mac_ctx, LOG1, + FL("Could not start channel switch")); + + cdf_mem_free(chnl_switch_frame); + return; +} + +#ifdef WLAN_FEATURE_11AC +/** + * __lim_process_operating_mode_action_frame() - To process op mode frames + * @mac_ctx: pointer to mac context + * @rx_pkt_info: pointer to received packet info + * @session: pointer to session + * + * This routine is called to process operating mode action frames + * + * Return: None + */ +static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + + tpSirMacMgmtHdr mac_hdr; + uint8_t *body_ptr; + tDot11fOperatingMode *operating_mode_frm; + uint32_t frame_len; + uint32_t status; + tpDphHashNode sta_ptr; + uint16_t aid; + uint8_t oper_mode; + uint8_t cb_mode; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_log(mac_ctx, LOG1, + FL("Received Operating Mode action frame")); + if (RF_CHAN_14 >= session->currentOperChannel) + cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz; + else + cb_mode = mac_ctx->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 == cb_mode) { + lim_log(mac_ctx, LOGW, FL("channel bonding disabled")); + return; + } + operating_mode_frm = cdf_mem_malloc(sizeof(*operating_mode_frm)); + if (NULL == operating_mode_frm) { + lim_log(mac_ctx, LOGE, FL("AllocateMemory failed")); + return; + } + /* Unpack channel switch frame */ + status = dot11f_unpack_operating_mode(mac_ctx, body_ptr, frame_len, + operating_mode_frm); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to unpack and parse (0x%08x, %d bytes)"), + status, frame_len); + cdf_mem_free(operating_mode_frm); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("warnings while unpacking (0x%08x, %d bytes):"), + status, frame_len); + } + sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid, + &session->dph.dphHashTable); + if (sta_ptr->htSupportedChannelWidthSet) { + if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ < + sta_ptr->vhtSupportedChannelWidthSet) + oper_mode = eHT_CHANNEL_WIDTH_160MHZ; + else + oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1; + } else { + oper_mode = eHT_CHANNEL_WIDTH_20MHZ; + } + if (oper_mode != operating_mode_frm->OperatingMode.chanWidth) { + lim_log(mac_ctx, LOGE, + FL(" received Chanwidth %d, staIdx = %d"), + (operating_mode_frm->OperatingMode.chanWidth), + sta_ptr->staIndex); + + lim_log(mac_ctx, LOGE, + FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2], + mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]); + + if (operating_mode_frm->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_160MHZ) { + sta_ptr->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + sta_ptr->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (operating_mode_frm->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_80MHZ) { + sta_ptr->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + sta_ptr->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (operating_mode_frm->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_40MHZ) { + sta_ptr->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + sta_ptr->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (operating_mode_frm->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_20MHZ) { + sta_ptr->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + sta_ptr->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + } + lim_check_vht_op_mode_change(mac_ctx, session, + operating_mode_frm->OperatingMode.chanWidth, + sta_ptr->staIndex, mac_hdr->sa); + } + + if (sta_ptr->vhtSupportedRxNss != + (operating_mode_frm->OperatingMode.rxNSS + 1)) { + sta_ptr->vhtSupportedRxNss = + operating_mode_frm->OperatingMode.rxNSS + 1; + lim_set_nss_change(mac_ctx, session, sta_ptr->vhtSupportedRxNss, + sta_ptr->staIndex, mac_hdr->sa); + } + cdf_mem_free(operating_mode_frm); + return; +} + +/** + * __lim_process_gid_management_action_frame() - To process group-id mgmt frames + * @mac_ctx: Pointer to mac context + * @rx_pkt_info: Rx packet info + * @session: pointer to session + * + * This routine will be called to process group id management frames + * + * Return: none + */ +static void __lim_process_gid_management_action_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + + uint8_t *body_ptr; + uint16_t aid; + uint32_t frame_len, status, membership = 0, usr_position = 0; + uint32_t *mem_lower, *mem_upper, *mem_cur; + tpSirMacMgmtHdr mac_hdr; + tDot11fVHTGidManagementActionFrame *gid_mgmt_frame; + tpDphHashNode sta_ptr; + struct sDot11fFfVhtMembershipStatusArray *vht_member_status = NULL; + struct sDot11fFfVhtUserPositionArray *vht_user_position = NULL; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_log(mac_ctx, LOG3, FL("Received GID Management action frame")); + gid_mgmt_frame = cdf_mem_malloc(sizeof(*gid_mgmt_frame)); + if (NULL == gid_mgmt_frame) { + lim_log(mac_ctx, LOGE, FL("AllocateMemory failed")); + return; + } + + /* Unpack Gid Mangement Action frame */ + status = dot11f_unpack_vht_gid_management_action_frame(mac_ctx, + body_ptr, frame_len, gid_mgmt_frame); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Fail to parse an Grp id frame (0x%08x, %d bytes):"), + status, frame_len); + cdf_mem_free(gid_mgmt_frame); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("warnings while unpacking Grp id frm (0x%08x, %d bytes):"), + status, frame_len); + } + sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid, + &session->dph.dphHashTable); + lim_log(mac_ctx, LOGE, + FL("received Gid Management Action Frame , staIdx = %d"), + sta_ptr->staIndex); + + lim_log(mac_ctx, LOGE, + FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), + mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2], + mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]); + vht_member_status = &gid_mgmt_frame->VhtMembershipStatusArray; + mem_lower = (uint32_t *) vht_member_status->membershipStatusArray; + mem_upper = (uint32_t *) &vht_member_status->membershipStatusArray[4]; + + if (*mem_lower && *mem_upper) { + lim_log(mac_ctx, LOGE, + FL("rcved frame with mult group ID set, staIdx = %d"), + sta_ptr->staIndex); + goto out; + } + if (*mem_lower) { + mem_cur = mem_lower; + } else if (*mem_upper) { + mem_cur = mem_upper; + membership += sizeof(uint32_t); + } else { + lim_log(mac_ctx, LOGE, + FL("rcved Gid frame with no group ID set, staIdx = %d"), + sta_ptr->staIndex); + goto out; + } + while (!(*mem_cur & 1)) { + *mem_cur >>= 1; + ++membership; + } + if (*mem_cur) { + lim_log(mac_ctx, LOGE, + FL("rcved frame with mult group ID set, staIdx = %d"), + sta_ptr->staIndex); + goto out; + } + + /*Just read the last two bits */ + vht_user_position = &gid_mgmt_frame->VhtUserPositionArray; + usr_position = vht_user_position->userPositionArray[membership] & 0x3; + lim_check_membership_user_position(mac_ctx, session, membership, + usr_position, sta_ptr->staIndex); +out: + cdf_mem_free(gid_mgmt_frame); + return; +} + +#endif + +static void +__lim_process_add_ts_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ +} + +/** + * __lim_process_add_ts_rsp() - To process add ts response frame + * @mac_ctx: pointer to mac context + * @rx_pkt_info: Received packet info + * @session: pointer to session + * + * This routine is to handle add ts response frame + * + * Return: none + */ +static void __lim_process_add_ts_rsp(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + tSirAddtsRspInfo addts; + tSirRetStatus retval; + tpSirMacMgmtHdr mac_hdr; + tpDphHashNode sta_ptr; + uint16_t aid; + uint32_t frameLen; + uint8_t *body_ptr; + tpLimTspecInfo tspec_info; + uint8_t ac; + tpDphHashNode sta_ds_ptr = NULL; + uint8_t rsp_reqd = 1; + uint32_t cfg_len; + tSirMacAddr peer_macaddr; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frameLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_log(mac_ctx, LOGW, "Recv AddTs Response"); + if (LIM_IS_AP_ROLE(session) || + LIM_IS_BT_AMP_AP_ROLE(session)) { + lim_log(mac_ctx, LOGW, + FL("AddTsRsp recvd at AP: ignoring")); + return; + } + + sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid, + &session->dph.dphHashTable); + if (sta_ptr == NULL) { + lim_log(mac_ctx, LOGE, + FL("Station context not found - ignoring AddTsRsp")); + return; + } + + retval = sir_convert_addts_rsp2_struct(mac_ctx, body_ptr, + frameLen, &addts); + if (retval != eSIR_SUCCESS) { + lim_log(mac_ctx, 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 (!mac_ctx->lim.gLimAddtsSent) { + /* we never sent an addts request! */ + lim_log(mac_ctx, LOGW, + FL("rx AddTsRsp but no req was ever sent-ignoring")); + return; + } + + if (mac_ctx->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken) { + lim_log(mac_ctx, LOGW, + FL("token mismatch (got %d, exp %d) - ignoring"), + addts.dialogToken, + mac_ctx->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 */ + lim_log(mac_ctx, LOGE, + FL("Sta %d: Too many Tclas (%d), 1 supported"), + aid, addts.numTclas); + return; + } else if (addts.numTclas == 1) { + lim_log(mac_ctx, LOGW, + FL("Response from STA %d: tsid %d, UP %d, OK!"), + aid, addts.tspec.tsinfo.traffic.tsid, + addts.tspec.tsinfo.traffic.userPrio); + } + } + lim_log(mac_ctx, LOGW, FL("Recv AddTsRsp: tsid %d, UP %d, status %d "), + addts.tspec.tsinfo.traffic.tsid, + addts.tspec.tsinfo.traffic.userPrio, addts.status); + + /* deactivate the response timer */ + lim_deactivate_and_change_timer(mac_ctx, eLIM_ADDTS_RSP_TIMER); + + if (addts.status != eSIR_MAC_SUCCESS_STATUS) { + lim_log(mac_ctx, LOGW, + FL("Recv AddTsRsp: tsid %d, UP %d, status %d "), + addts.tspec.tsinfo.traffic.tsid, + addts.tspec.tsinfo.traffic.userPrio, addts.status); + lim_send_sme_addts_rsp(mac_ctx, true, addts.status, session, + addts.tspec, session->smeSessionId, + session->transactionId); + + /* clear the addts flag */ + mac_ctx->lim.gLimAddtsSent = false; + + return; + } +#ifdef FEATURE_WLAN_ESE + if (addts.tsmPresent) { + lim_log(mac_ctx, LOGW, "TSM IE Present"); + session->eseContext.tsm.tid = + addts.tspec.tsinfo.traffic.userPrio; + cdf_mem_copy(&session->eseContext.tsm.tsmInfo, + &addts.tsmIE, sizeof(tSirMacESETSMIE)); +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_tsm_ie_ind(mac_ctx, session, addts.tsmIE.tsid, + addts.tsmIE.state, + addts.tsmIE.msmt_interval); +#else + limActivateTSMStatsTimer(mac_ctx, session); +#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 (addts.tspec.tsinfo.traffic.psb == 1) + lim_set_tspec_uapsd_mask_per_session(mac_ctx, session, + &addts.tspec.tsinfo, + SET_UAPSD_MASK); + else + lim_set_tspec_uapsd_mask_per_session(mac_ctx, session, + &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) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + } else if (addts.tspec.tsinfo.traffic.direction == + SIR_MAC_DIRECTION_DNLINK) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } else if (addts.tspec.tsinfo.traffic.direction == + SIR_MAC_DIRECTION_BIDIR) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams, + session); + sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session->dph.dphHashTable); + if (sta_ds_ptr != NULL) + lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive, + sta_ds_ptr->bssId); + else + lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table ")); + sir_copy_mac_addr(peer_macaddr, session->bssId); + /* if schedule is not present then add TSPEC with svcInterval as 0. */ + if (!addts.schedulePresent) + addts.schedule.svcInterval = 0; + if (eSIR_SUCCESS != + lim_tspec_add(mac_ctx, sta_ptr->staAddr, sta_ptr->assocId, + &addts.tspec, addts.schedule.svcInterval, &tspec_info)) { + lim_log(mac_ctx, LOGE, + FL("Adding entry in lim Tspec Table failed ")); + lim_send_delts_req_action_frame(mac_ctx, peer_macaddr, rsp_reqd, + &addts.tspec.tsinfo, + &addts.tspec, session); + mac_ctx->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 = lim_send_hal_msg_add_ts(mac_ctx, + sta_ptr->staIndex, tspec_info->idx, + addts.tspec, session->peSessionId, + addts.tsmIE.msmt_interval); +#else + retval = lim_send_hal_msg_add_ts(mac_ctx, + sta_ptr->staIndex, tspec_info->idx, + addts.tspec, session->peSessionId); +#endif + if (eSIR_SUCCESS != retval) { + lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId, + &addts.tspec.tsinfo, NULL, &tspec_info->idx); + + /* Send DELTS action frame to AP */ + cfg_len = sizeof(tSirMacAddr); + lim_send_delts_req_action_frame(mac_ctx, peer_macaddr, + rsp_reqd, &addts.tspec.tsinfo, + &addts.tspec, session); + lim_send_sme_addts_rsp(mac_ctx, true, retval, + session, addts.tspec, + session->smeSessionId, + session->transactionId); + mac_ctx->lim.gLimAddtsSent = false; + return; + } + lim_log(mac_ctx, LOGW, + FL("AddTsRsp received successfully(UP %d, TSID %d)"), + addts.tspec.tsinfo.traffic.userPrio, + addts.tspec.tsinfo.traffic.tsid); + } else { + lim_log(mac_ctx, LOGW, + FL("AddTsRsp received successfully(UP %d, TSID %d)"), + addts.tspec.tsinfo.traffic.userPrio, + addts.tspec.tsinfo.traffic.tsid); + lim_log(mac_ctx, LOGW, + FL("no ACM: Bypass sending WMA_ADD_TS_REQ to HAL ")); + /* + * Use the smesessionId and smetransactionId from the PE + * session context + */ + lim_send_sme_addts_rsp(mac_ctx, true, eSIR_SME_SUCCESS, + session, addts.tspec, session->smeSessionId, + session->transactionId); + } + /* clear the addts flag */ + mac_ctx->lim.gLimAddtsSent = false; + return; +} + +/** + * __lim_process_del_ts_req() - To process del ts response frame + * @mac_ctx: pointer to mac context + * @rx_pkt_info: Received packet info + * @session: pointer to session + * + * This routine is to handle del ts request frame + * + * Return: none + */ +static void __lim_process_del_ts_req(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + tSirRetStatus retval; + tSirDeltsReqInfo delts; + tpSirMacMgmtHdr mac_hdr; + tpDphHashNode sta_ptr; + uint32_t frame_len; + uint16_t aid; + uint8_t *body_ptr; + uint8_t ts_status; + tSirMacTSInfo *tsinfo; + uint8_t tspec_idx; + uint8_t ac; + tpDphHashNode sta_ds_ptr = NULL; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid, + &session->dph.dphHashTable); + if (sta_ptr == NULL) { + lim_log(mac_ctx, LOGE, + FL("Station context not found - ignoring DelTs")); + return; + } + /* parse the delts request */ + retval = sir_convert_delts_req2_struct(mac_ctx, body_ptr, + frame_len, &delts); + if (retval != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGW, + FL("DelTs parsing failed (error %d)"), retval); + return; + } + + if (delts.wmeTspecPresent) { + if ((!session->limWmeEnabled) || (!sta_ptr->wmeEnabled)) { + lim_log(mac_ctx, LOGW, + FL("Ignore delts req: wme not enabled")); + return; + } + lim_log(mac_ctx, LOG2, FL("WME Delts received")); + } else if ((session->limQosEnabled) && sta_ptr->lleEnabled) { + lim_log(mac_ctx, LOG2, FL("11e QoS Delts received")); + } else if ((session->limWsmEnabled) && sta_ptr->wsmEnabled) { + lim_log(mac_ctx, LOG2, FL("WSM Delts received")); + } else { + lim_log(mac_ctx, 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) { + lim_log(mac_ctx, LOGW, + FL("DelTs with UP %d has no AC - ignoring req"), + tsinfo->traffic.userPrio); + return; + } + } + + if (!LIM_IS_AP_ROLE(session) && + !LIM_IS_BT_AMP_AP_ROLE(session)) + lim_send_sme_delts_ind(mac_ctx, &delts, aid, session); + + /* try to delete the TS */ + if (eSIR_SUCCESS != + lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId, tsinfo, + &ts_status, &tspec_idx)) { + lim_log(mac_ctx, LOGW, FL("Unable to Delete TS")); + return; + } else if (!((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) + || (tsinfo->traffic.accessPolicy == + SIR_MAC_ACCESSPOLICY_BOTH))){ + /* send message to HAL to delete TS */ + if (eSIR_SUCCESS != lim_send_hal_msg_del_ts(mac_ctx, + sta_ptr->staIndex, tspec_idx, + delts, session->peSessionId, + session->bssId)) { + lim_log(mac_ctx, LOGW, + FL("DelTs with UP %d failed 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. + */ + lim_set_tspec_uapsd_mask_per_session(mac_ctx, session, + 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) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= + ~(1 << ac); + } else if (tsinfo->traffic.direction == + SIR_MAC_DIRECTION_DNLINK) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= + ~(1 << ac); + } else if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) { + session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= + ~(1 << ac); + session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= + ~(1 << ac); + } + lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams, + session); + sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session->dph.dphHashTable); + if (sta_ds_ptr != NULL) + lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive, + sta_ds_ptr->bssId); + else + lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table ")); + + lim_log(mac_ctx, LOG1, FL("DeleteTS succeeded")); +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_tsm_ie_ind(mac_ctx, session, 0, 0, 0); +#else + lim_deactivate_and_change_timer(mac_ctx, eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif +} + +/** + * __lim_process_qos_map_configure_frame() - to process QoS map configure frame + * @mac_ctx: pointer to mac context + * @rx_pkt_info: pointer to received packet info + * @session: pointer to session + * + * This routine will called to process qos map configure frame + * + * Return: none + */ +static void __lim_process_qos_map_configure_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + tpSirMacMgmtHdr mac_hdr; + uint32_t frame_len; + uint8_t *body_ptr; + tSirRetStatus retval; + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + retval = sir_convert_qos_map_configure_frame2_struct(mac_ctx, + body_ptr, frame_len, &session->QosMapSet); + if (retval != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("QosMapConfigure frame parsing fail(error %d)"), + retval); + return; + } + lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(rx_pkt_info), session, 0); +} + +#ifdef ANI_SUPPORT_11H +static void +__lim_process_basic_meas_req(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pMeasReqFrame, + tSirMacAddr peerMacAddr, tpPESession psessionEntry) +{ + if (lim_send_meas_report_frame(pMac, + pMeasReqFrame, + peerMacAddr, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(lim_log + (pMac, LOGE, FL("fail to send Basic Meas report ")); + ) + return; + } +} +static void +__lim_process_cca_meas_req(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pMeasReqFrame, + tSirMacAddr peerMacAddr, tpPESession psessionEntry) +{ + if (lim_send_meas_report_frame(pMac, + pMeasReqFrame, + peerMacAddr, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(lim_log(pMac, LOGE, FL("fail to send CCA Meas report "));) + return; + } +} +static void +__lim_process_rpi_meas_req(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pMeasReqFrame, + tSirMacAddr peerMacAddr, tpPESession psessionEntry) +{ + if (lim_send_meas_report_frame(pMac, + pMeasReqFrame, + peerMacAddr, psessionEntry) != eSIR_SUCCESS) + { + PELOGE(lim_log(pMac, LOGE, FL("fail to send RPI Meas report "));) + return; + } +} +static void +__lim_process_measurement_request_frame(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + uint8_t *pBody; + tpSirMacMeasReqActionFrame pMeasReqFrame; + uint32_t frameLen; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + pMeasReqFrame = cdf_mem_malloc(sizeof(tSirMacMeasReqActionFrame)); + if (NULL == pMeasReqFrame) { + lim_log(pMac, LOGE, + FL + ("limProcessMeasurementRequestFrame: AllocateMemory failed ")); + return; + } + + if (sir_convert_meas_req_frame2_struct(pMac, pBody, pMeasReqFrame, frameLen) + != eSIR_SUCCESS) { + PELOGW(lim_log + (pMac, LOGW, + FL("Rcv invalid Measurement Request Action Frame ")); + ) + return; + } + switch (pMeasReqFrame->measReqIE.measType) { + case SIR_MAC_BASIC_MEASUREMENT_TYPE: + __lim_process_basic_meas_req(pMac, pMeasReqFrame, pHdr->sa, + psessionEntry); + break; + case SIR_MAC_CCA_MEASUREMENT_TYPE: + __lim_process_cca_meas_req(pMac, pMeasReqFrame, pHdr->sa, + psessionEntry); + break; + case SIR_MAC_RPI_MEASUREMENT_TYPE: + __lim_process_rpi_meas_req(pMac, pMeasReqFrame, pHdr->sa, + psessionEntry); + break; + default: + PELOG1(lim_log(pMac, LOG1, FL("Unknown Measurement Type %d "), + pMeasReqFrame->measReqIE.measType); + ) + break; + } +} /*** end limProcessMeasurementRequestFrame ***/ +static void +__lim_process_tpc_request_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + uint8_t *pBody; + tpSirMacTpcReqActionFrame pTpcReqFrame; + uint32_t frameLen; + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + PELOG1(lim_log + (pMac, LOG1, + FL("****LIM: Processing TPC Request from peer ****")); + ) + pTpcReqFrame = cdf_mem_malloc(sizeof(tSirMacTpcReqActionFrame)); + if (NULL == pTpcReqFrame) { + PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory failed "));) + return; + } + if (sir_convert_tpc_req_frame2_struct(pMac, pBody, pTpcReqFrame, frameLen) != + eSIR_SUCCESS) { + PELOGW(lim_log + (pMac, LOGW, FL("Rcv invalid TPC Req Action Frame ")); + ) + return; + } + if (lim_send_tpc_report_frame(pMac, + pTpcReqFrame, + pHdr->sa, psessionEntry) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("fail to send TPC Report Frame. ")); + ) + return; + } +} +#endif + +static void +__lim_process_sm_power_save_update(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + + tpSirMacMgmtHdr pHdr; + tDot11fSMPowerSave frmSMPower; + tSirMacHTMIMOPowerSaveState state; + tpDphHashNode pSta; + uint16_t aid; + uint32_t frameLen, nStatus; + uint8_t *pBody; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + pSta = + dph_lookup_hash_entry(pMac, pHdr->sa, &aid, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) { + lim_log(pMac, LOGE, + FL + ("STA context not found - ignoring UpdateSM PSave Mode from ")); + lim_print_mac_addr(pMac, pHdr->sa, LOGW); + return; + } + + /**Unpack the received frame */ + nStatus = dot11f_unpack_sm_power_save(pMac, pBody, frameLen, &frmSMPower); + + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL + ("Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + return; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + } + + lim_log(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(lim_log + (pMac, LOGW, + FL + ("Received SM Power save Mode update Frame with invalid mode")); + ) + return; + } + + if (state == pSta->htMIMOPSState) { + PELOGE(lim_log + (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; + lim_post_sm_state_update(pMac, pSta->staIndex, pSta->htMIMOPSState, + pSta->staAddr, psessionEntry->smeSessionId); +} + +#if defined WLAN_FEATURE_VOWIFI + +static void +__lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tDot11fRadioMeasurementRequest frm; + uint32_t frameLen, nStatus; + uint8_t *pBody; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (psessionEntry == NULL) { + return; + } + + lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *)pHdr, + frameLen + sizeof(tSirMacMgmtHdr), 0, + WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, 0); + + /**Unpack the received frame */ + nStatus = + dot11f_unpack_radio_measurement_request(pMac, pBody, frameLen, &frm); + + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL + ("Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + return; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Radio Measure request (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + } + /* Call rrm function to handle the request. */ + + rrm_process_radio_measurement_request(pMac, pHdr->sa, &frm, psessionEntry); +} + +static void +__lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tDot11fLinkMeasurementRequest frm; + uint32_t frameLen, nStatus; + uint8_t *pBody; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (psessionEntry == NULL) { + return; + } + + /**Unpack the received frame */ + nStatus = + dot11f_unpack_link_measurement_request(pMac, pBody, frameLen, &frm); + + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL + ("Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + return; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + } + /* Call rrm function to handle the request. */ + + rrm_process_link_measurement_request(pMac, pRxPacketInfo, &frm, + psessionEntry); + +} + +static void +__lim_process_neighbor_report(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + tDot11fNeighborReportResponse *pFrm; + uint32_t frameLen, nStatus; + uint8_t *pBody; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + pFrm = cdf_mem_malloc(sizeof(tDot11fNeighborReportResponse)); + if (NULL == pFrm) { + lim_log(pMac, LOGE, + FL + ("Unable to allocate memory in __lim_process_neighbor_report")); + return; + } + + if (psessionEntry == NULL) { + cdf_mem_free(pFrm); + return; + } + + /**Unpack the received frame */ + nStatus = + dot11f_unpack_neighbor_report_response(pMac, pBody, frameLen, pFrm); + + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL + ("Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + cdf_mem_free(pFrm); + return; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):"), + nStatus, frameLen); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); + ) + } + /* Call rrm function to handle the request. */ + rrm_process_neighbor_report_response(pMac, pFrm, psessionEntry); + + cdf_mem_free(pFrm); +} + +#endif + +#ifdef WLAN_FEATURE_11W +/** + * limProcessSAQueryRequestActionFrame + * + ***FUNCTION: + * This function is called by lim_process_action_frame() 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 __lim_process_sa_query_request_action_frame(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + uint8_t *pBody; + uint8_t transId[2]; + + /* Prima --- Below Macro not available in prima + pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd); + pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */ + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_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 */ + cdf_mem_copy(&transId[0], &pBody[2], 2); + + /* Send 11w SA query response action frame */ + if (lim_send_sa_query_response_frame(pMac, + transId, + pHdr->sa, + psessionEntry) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("fail to send SA query response action frame.")); + ) + return; + } +} + +/** + * __lim_process_sa_query_response_action_frame + * + ***FUNCTION: + * This function is called by lim_process_action_frame() 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 __lim_process_sa_query_response_action_frame(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + uint32_t frameLen; + uint8_t *pBody; + tpDphHashNode pSta; + uint16_t aid; + uint16_t transId; + uint8_t retryNum; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_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)) { + lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *) pHdr, + frameLen + sizeof(tSirMacMgmtHdr), 0, + WMA_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 = + dph_lookup_hash_entry(pMac, pHdr->sa, &aid, + &psessionEntry->dph.dphHashTable); + if (NULL == pSta) + return; + + lim_log(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]); + lim_log(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 */ + cdf_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) { + lim_log(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 +/** + * lim_drop_unprotected_action_frame + * + ***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 bool +lim_drop_unprotected_action_frame(tpAniSirGlobal pMac, tpPESession psessionEntry, + tpSirMacMgmtHdr pHdr, uint8_t category) +{ + uint16_t aid; + tpDphHashNode pStaDs; + bool rmfConnection = false; + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + pStaDs = + dph_lookup_hash_entry(pMac, pHdr->sa, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) + if (pStaDs->rmfEnabled) + rmfConnection = true; + } else if (psessionEntry->limRmfEnabled) + rmfConnection = true; + + if (rmfConnection && (pHdr->fc.wep == 0)) { + PELOGE(lim_log + (pMac, LOGE, + FL("Dropping unprotected Action category %d frame " + "since RMF is enabled."), category); + ) + return true; + } else + return false; +} +#endif + +/** + * lim_process_action_frame() - to process action frames + * @mac_ctx: Pointer to Global MAC structure + * @rx_pkt_info: A pointer to packet info structure + * + * This function is called by limProcessMessageQueue() upon + * Action frame reception. + * + * Return: none + */ + +void lim_process_action_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, tpPESession session) +{ + uint8_t *body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) body_ptr; +#ifdef WLAN_FEATURE_11W + tpSirMacMgmtHdr mac_hdr_11w = WMA_GET_RX_MAC_HEADER(rx_pkt_info); +#endif + tpSirMacMgmtHdr mac_hdr = NULL; + int8_t rssi; + uint32_t frame_len; + tpSirMacVendorSpecificFrameHdr vendor_specific; + uint8_t oui[] = { 0x00, 0x00, 0xf0 }; + tpSirMacVendorSpecificPublicActionFrameHdr pub_action; + uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x09 }; + + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + switch (action_hdr->category) { + case SIR_MAC_ACTION_QOS_MGMT: +#ifdef WLAN_FEATURE_11W + if (lim_drop_unprotected_action_frame(mac_ctx, session, + mac_hdr_11w, action_hdr->category)) + break; +#endif + if ((session->limQosEnabled) || + (action_hdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE)) { + switch (action_hdr->actionID) { + case SIR_MAC_QOS_ADD_TS_REQ: + __lim_process_add_ts_req(mac_ctx, + (uint8_t *) rx_pkt_info, + session); + break; + + case SIR_MAC_QOS_ADD_TS_RSP: + __lim_process_add_ts_rsp(mac_ctx, + (uint8_t *) rx_pkt_info, + session); + break; + + case SIR_MAC_QOS_DEL_TS_REQ: + __lim_process_del_ts_req(mac_ctx, + (uint8_t *) rx_pkt_info, + session); + break; + + case SIR_MAC_QOS_MAP_CONFIGURE: + __lim_process_qos_map_configure_frame(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + default: + lim_log(mac_ctx, LOGE, + FL("Qos action %d not handled"), + action_hdr->actionID); + break; + } + break; + } + break; + + case SIR_MAC_ACTION_SPECTRUM_MGMT: +#ifdef WLAN_FEATURE_11W + if (lim_drop_unprotected_action_frame(mac_ctx, session, + mac_hdr_11w, action_hdr->category)) + break; +#endif + switch (action_hdr->actionID) { +#ifdef ANI_SUPPORT_11H + case SIR_MAC_ACTION_MEASURE_REQUEST_ID: + if (session->lim11hEnable) + __lim_process_measurement_request_frame(mac_ctx, + rx_pkt_info, + session); + break; + case SIR_MAC_ACTION_TPC_REQUEST_ID: + if ((LIM_IS_STA_ROLE(session) || + LIM_IS_AP_ROLE(session)) && + session->lim11hEnable) + __lim_process_tpc_request_frame(mac_ctx, + rx_pkt_info, session); + break; +#endif + case SIR_MAC_ACTION_CHANNEL_SWITCH_ID: + if (LIM_IS_STA_ROLE(session)) + __lim_process_channel_switch_action_frame( + mac_ctx, rx_pkt_info, session); + break; + default: + lim_log(mac_ctx, LOGE, + FL("Spectrum mgmt action id %d not handled"), + action_hdr->actionID); + break; + } + break; + + case SIR_MAC_ACTION_WME: + if (!session->limWmeEnabled) { + lim_log(mac_ctx, LOGW, + FL("WME mode disabled - dropping frame %d"), + action_hdr->actionID); + break; + } + switch (action_hdr->actionID) { + case SIR_MAC_QOS_ADD_TS_REQ: + __lim_process_add_ts_req(mac_ctx, + (uint8_t *) rx_pkt_info, session); + break; + + case SIR_MAC_QOS_ADD_TS_RSP: + __lim_process_add_ts_rsp(mac_ctx, + (uint8_t *) rx_pkt_info, session); + break; + + case SIR_MAC_QOS_DEL_TS_REQ: + __lim_process_del_ts_req(mac_ctx, + (uint8_t *) rx_pkt_info, session); + break; + + case SIR_MAC_QOS_MAP_CONFIGURE: + __lim_process_qos_map_configure_frame(mac_ctx, + (uint8_t *)rx_pkt_info, session); + break; + + default: + lim_log(mac_ctx, LOGE, + FL("WME action %d not handled"), + action_hdr->actionID); + break; + } + break; + + case SIR_MAC_ACTION_HT: + /** Type of HT Action to be performed*/ + switch (action_hdr->actionID) { + case SIR_MAC_SM_POWER_SAVE: + if (LIM_IS_AP_ROLE(session)) + __lim_process_sm_power_save_update(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + default: + lim_log(mac_ctx, LOGE, + FL("Action ID %d not handled in HT category"), + action_hdr->actionID); + break; + } + break; + + case SIR_MAC_ACTION_WNM: +#ifdef WLAN_FEATURE_11W + if ((session->limRmfEnabled) && (mac_hdr_11w->fc.wep == 0)) { + lim_log(mac_ctx, LOGE, + FL("Dropping unprot action %d frm (PMF on)"), + action_hdr->category); + break; + } +#endif + lim_log(mac_ctx, LOG1, + FL("WNM Action category %d action %d."), + action_hdr->category, action_hdr->actionID); + switch (action_hdr->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: + rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + /* Forward to the SME to HDD to wpa_supplicant */ + lim_send_sme_mgmt_frame_ind(mac_ctx, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), + session, rssi); + break; + default: + lim_log(mac_ctx, LOGE, + FL("Action ID %d not handled in WNM category"), + action_hdr->actionID); + break; + } + break; + +#if defined WLAN_FEATURE_VOWIFI + case SIR_MAC_ACTION_RRM: +#ifdef WLAN_FEATURE_11W + if (lim_drop_unprotected_action_frame(mac_ctx, session, + mac_hdr_11w, action_hdr->category)) + break; +#endif + if (mac_ctx->rrm.rrmPEContext.rrmEnable) { + switch (action_hdr->actionID) { + case SIR_MAC_RRM_RADIO_MEASURE_REQ: + __lim_process_radio_measure_request(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + case SIR_MAC_RRM_LINK_MEASUREMENT_REQ: + __lim_process_link_measurement_req(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + case SIR_MAC_RRM_NEIGHBOR_RPT: + __lim_process_neighbor_report(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + default: + lim_log(mac_ctx, LOGE, + FL("Action ID %d not handled in RRM"), + action_hdr->actionID); + break; + + } + } else { + /* Else we will just ignore the RRM messages. */ + lim_log(mac_ctx, LOGE, + FL("RRM frm ignored, it 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: + vendor_specific = (tpSirMacVendorSpecificFrameHdr) action_hdr; + mac_hdr = NULL; + frame_len = 0; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + /* Check if it is a vendor specific action frame. */ + if (LIM_IS_STA_ROLE(session) && + (true == cdf_mem_compare(session->selfMacAddr, + &mac_hdr->da[0], sizeof(tSirMacAddr))) + && IS_WES_MODE_ENABLED(mac_ctx) + && cdf_mem_compare(vendor_specific->Oui, oui, 3)) { + lim_log(mac_ctx, LOGW, + FL("Rcvd Vendor specific frame, OUI %x %x %x"), + vendor_specific->Oui[0], + vendor_specific->Oui[1], + vendor_specific->Oui[2]); + /* + * Forward to the SME to HDD to wpa_supplicant + * type is ACTION + */ + lim_send_sme_mgmt_frame_ind(mac_ctx, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), + session, 0); + } else { + lim_log(mac_ctx, LOGE, + FL("Dropping the vendor specific action frame" + "beacause of (WES Mode not enabled " + "(WESMODE = %d) or OUI mismatch " + "(%02x %02x %02x) or not received with" + "SelfSta address) system role = %d"), + IS_WES_MODE_ENABLED(mac_ctx), + vendor_specific->Oui[0], + vendor_specific->Oui[1], + vendor_specific->Oui[2], + GET_LIM_SYSTEM_ROLE(session)); + } + break; +#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || + FEATURE_WLAN_LFR */ + case SIR_MAC_ACTION_PUBLIC_USAGE: + switch (action_hdr->actionID) { + case SIR_MAC_ACTION_VENDOR_SPECIFIC: + pub_action = + (tpSirMacVendorSpecificPublicActionFrameHdr) + action_hdr; + mac_hdr = NULL; + frame_len = 0; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + /* Check if it is a P2P public action frame. */ + if (cdf_mem_compare(pub_action->Oui, p2p_oui, 4)) { + /* + * Forward to the SME to HDD to wpa_supplicant + * type is ACTION + */ + lim_send_sme_mgmt_frame_ind(mac_ctx, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), + session, 0); + } else { + lim_log(mac_ctx, LOGE, + FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"), + pub_action->Oui[0], pub_action->Oui[1], + pub_action->Oui[2], pub_action->Oui[3]); + } + break; + + case SIR_MAC_ACTION_2040_BSS_COEXISTENCE: + mac_hdr = NULL; + frame_len = 0; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_send_sme_mgmt_frame_ind(mac_ctx, + mac_hdr->fc.subType, + (uint8_t *) mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), session, 0); + break; +#ifdef FEATURE_WLAN_TDLS + case SIR_MAC_TDLS_DIS_RSP: + mac_hdr = NULL; + frame_len = 0; + rssi = 0; + + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + ("Public Action TDLS Discovery RSP ..")); + lim_send_sme_mgmt_frame_ind(mac_ctx, + mac_hdr->fc.subType, (uint8_t *) mac_hdr, + frame_len + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), session, rssi); + break; +#endif + + default: + lim_log(mac_ctx, LOGE, + FL("Unhandled public action frame -- %x "), + action_hdr->actionID); + break; + } + break; + +#ifdef WLAN_FEATURE_11W + case SIR_MAC_ACTION_SA_QUERY: + lim_log(mac_ctx, LOG1, + FL("SA Query Action category %d action %d."), + action_hdr->category, action_hdr->actionID); + if (lim_drop_unprotected_action_frame(mac_ctx, session, + mac_hdr_11w, action_hdr->category)) + break; + switch (action_hdr->actionID) { + case SIR_MAC_SA_QUERY_REQ: + /**11w SA query request action frame received**/ + /* Respond directly to the incoming request in LIM */ + __lim_process_sa_query_request_action_frame(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + case SIR_MAC_SA_QUERY_RSP: + /**11w SA query response action frame received**/ + /* Handle based on the current SA Query state */ + __lim_process_sa_query_response_action_frame(mac_ctx, + (uint8_t *)rx_pkt_info, + session); + break; + default: + break; + } + break; +#endif +#ifdef WLAN_FEATURE_11AC + case SIR_MAC_ACTION_VHT: + if (!session->vhtCapability) + break; + switch (action_hdr->actionID) { + case SIR_MAC_VHT_OPMODE_NOTIFICATION: + __lim_process_operating_mode_action_frame(mac_ctx, + rx_pkt_info, session); + break; + case SIR_MAC_VHT_GID_NOTIFICATION: + /* Only if ini supports it */ + if (session->enableVhtGid) + __lim_process_gid_management_action_frame( + mac_ctx, rx_pkt_info, session); + break; + default: + break; + } + break; +#endif + default: + lim_log(mac_ctx, LOGE, + FL("Action category %d not handled"), + action_hdr->category); + break; + } +} + +/** + * lim_process_action_frame_no_session + * + ***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 lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) +{ + uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd); + tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr = + (tpSirMacVendorSpecificPublicActionFrameHdr) pBody; + + lim_log(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; + uint32_t frameLen; + uint8_t P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 }; + + pHdr = WMA_GET_RX_MAC_HEADER(pBd); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd); + + /* Check if it is a P2P public action frame. */ + if (cdf_mem_compare(pActionHdr->Oui, P2POui, 4)) { + /* Forward to the SME to HDD to wpa_supplicant */ + /* type is ACTION */ + lim_send_sme_mgmt_frame_ind(pMac, + pHdr->fc.subType, + (uint8_t *) pHdr, + frameLen + + sizeof + (tSirMacMgmtHdr), + 0, + WMA_GET_RX_CH + (pBd), NULL, 0); + } else { + lim_log(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(lim_log + (pMac, LOGE, + FL("Unhandled public action frame -- %x "), + pActionHdr->actionID); + ) + break; + } + break; + default: + PELOGE(lim_log + (pMac, LOG1, + FL("Unhandled action frame without session -- %x "), + pActionHdr->category); + ) + break; + + } +} diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c new file mode 100644 index 000000000000..1972461f0350 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -0,0 +1,1921 @@ +/* + * 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 lim_process_assoc_req_frame.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 "cds_api.h" +#include "ani_global.h" +#include "wni_cfg.h" +#include "sir_api.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_sta_hash_api.h" +#include "lim_admit_control.h" +#include "cds_packet.h" +#include "lim_session_utils.h" + +#include "cdf_types.h" +#include "cds_utils.h" + +/** + * lim_convert_supported_channels - Parses channel support IE + * + * @mac_ctx - A pointer to Global MAC structure + * @assoc_ind - A pointer to SME ASSOC/REASSOC IND + * @assoc_req - A pointer to ASSOC/REASSOC Request frame + * + * This function is called by lim_process_assoc_req_frame() to + * parse the channel support IE in the Assoc/Reassoc Request + * frame, and send relevant information in the SME_ASSOC_IND + * + * return None + */ +static void +lim_convert_supported_channels(tpAniSirGlobal mac_ctx, + tpLimMlmAssocInd assoc_ind, tSirAssocReq *assoc_req) +{ + uint16_t i, j, index = 0; + uint8_t first_chn_no; + uint8_t chn_count; + uint8_t next_chn_no; + uint8_t channel_offset = 0; + + if (assoc_req->supportedChannels.length >= + SIR_MAX_SUPPORTED_CHANNEL_LIST) { + lim_log(mac_ctx, LOG1, + FL("Number of supported channels:%d is more than MAX"), + assoc_req->supportedChannels.length); + assoc_ind->supportedChannels.numChnl = 0; + return; + } + + for (i = 0; i < (assoc_req->supportedChannels.length); i++) { + /* Get First Channel Number */ + first_chn_no = + assoc_req->supportedChannels.supportedChannels[i]; + assoc_ind->supportedChannels.channelList[index] = + first_chn_no; + i++; + index++; + + /* Get Number of Channels in a Subband */ + chn_count = + assoc_req->supportedChannels.supportedChannels[i]; + PELOG2(lim_log(mac_ctx, LOG2, + FL("Rcv assoc_req: chnl=%d, numOfChnl=%d "), + first_chn_no, chn_count);) + if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) { + PELOG2(lim_log(mac_ctx, LOGW, + FL("Channel count is more than max supported =%d "), + chn_count);) + assoc_ind->supportedChannels.numChnl = 0; + return; + } + if (chn_count <= 1) + continue; + next_chn_no = first_chn_no; + if (SIR_BAND_5_GHZ == lim_get_rf_band(first_chn_no)) + channel_offset = SIR_11A_FREQUENCY_OFFSET; + else if (SIR_BAND_2_4_GHZ == lim_get_rf_band(first_chn_no)) + channel_offset = SIR_11B_FREQUENCY_OFFSET; + else + continue; + + for (j = 1; j < chn_count; j++) { + next_chn_no += channel_offset; + assoc_ind->supportedChannels.channelList[index] + = next_chn_no; + index++; + if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) { + PELOG2(lim_log(mac_ctx, LOGW, + FL("Channel count is more than supported =%d "), + chn_count);) + assoc_ind->supportedChannels.numChnl = 0; + return; + } + } + } + + assoc_ind->supportedChannels.numChnl = (uint8_t) index; + PELOG2(lim_log(mac_ctx, LOG2, + FL("Send AssocInd to WSM: minPwr %d, maxPwr %d, numChnl %d"), + assoc_ind->powerCap.minTxPower, + assoc_ind->powerCap.maxTxPower, + assoc_ind->supportedChannels.numChnl);) +} + +/**--------------------------------------------------------------- + \fn lim_check_sta_in_pe_entries + \brief This function is called by lim_process_assoc_req_frame() + \ 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) +{ + uint8_t i; + uint16_t 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 == CDF_SAP_MODE)) { + + psessionEntry = &pMac->lim.gpSession[i]; + pStaDs = dph_lookup_hash_entry(pMac, pHdr->sa, &assocId, + &psessionEntry->dph. + dphHashTable); + if (pStaDs +#ifdef WLAN_FEATURE_11W + && !pStaDs->rmfEnabled +#endif + ) { + lim_log(pMac, LOGE, + FL + ("Sending Deauth and Deleting existing STA entry: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(psessionEntry-> + selfMacAddr)); + lim_send_deauth_mgmt_frame(pMac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + (uint8_t *) pHdr->sa, + psessionEntry, false); + lim_trigger_sta_deletion(pMac, pStaDs, + psessionEntry); + break; + } + } + } +} + +/**--------------------------------------------------------------- + \fn lim_process_assoc_req_frame + \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 +lim_process_assoc_req_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + uint8_t subType, tpPESession psessionEntry) +{ + uint8_t updateContext; + uint8_t *pBody; + uint16_t peerIdx, temp; + uint32_t val; + int32_t framelen; + tSirRetStatus status; + tpSirMacMgmtHdr pHdr; + struct tLimPreAuthNode *pStaPreAuthContext; + tAniAuthType authType; + tSirMacCapabilityInfo localCapabilities; + tpDphHashNode pStaDs = NULL; + tpSirAssocReq pAssocReq, pTempAssocReq; + tLimMlmStates mlmPrevState; + tDot11fIERSN Dot11fIERSN; + tDot11fIEWPA Dot11fIEWPA; + uint32_t phyMode; + tHalBitVal qosMode; + tHalBitVal wsmMode, wmeMode; + uint8_t *wpsIe = NULL; + uint8_t *ht_cap_ie = NULL; + tSirMacRateSet basicRates; + uint8_t i = 0, j = 0; + bool pmfConnection = false; +#ifdef WLAN_FEATURE_11W + tPmfSaQueryTimerId timerId; + uint32_t retryInterval; +#endif + uint16_t assoc_id = 0; + bool assoc_req_copied = false; + + lim_get_phy_mode(pMac, &phyMode, psessionEntry); + + limGetQosMode(psessionEntry, &qosMode); + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + lim_log(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)) { + lim_log(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)); + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG3, + WMA_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 = dph_lookup_hash_entry(pMac, pHdr->sa, &assoc_id, + &psessionEntry->dph.dphHashTable); + if ((NULL != pStaDs) && (pHdr->fc.retry > 0)) { + lim_log(pMac, LOGE, + FL("STA is initiating Assoc Req after ACK lost. Do not process" + " 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)); + return; + } + + lim_check_sta_in_pe_entries(pMac, pHdr); + + /* Get pointer to Re/Association Request frame body */ + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (lim_is_group_addr(pHdr->sa)) { + /* Received Re/Assoc Req frame from a BC/MC address */ + /* Log error and ignore it */ + lim_log(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; + } + + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG2, (uint8_t *) pBody, framelen); + + if (cdf_mem_compare((uint8_t *) pHdr->sa, (uint8_t *) pHdr->da, + (uint8_t) (sizeof(tSirMacAddr)))) { + lim_log(pMac, LOGE, + FL("Rejected Assoc Req frame Since same mac as" + " SAP/GO")); + lim_send_assoc_rsp_mgmt_frame(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)) { + lim_log(pMac, LOGE, FL("TKIP counter measure is active")); + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_MIC_FAILURE_REASON, + 1, pHdr->sa, subType, + 0, psessionEntry); + return; + } + /* Allocate memory for the Assoc Request frame */ + pAssocReq = cdf_mem_malloc(sizeof(*pAssocReq)); + if (NULL == pAssocReq) { + lim_log(pMac, LOGP, FL("Allocate Memory failed in assoc_req")); + return; + } + cdf_mem_set((void *)pAssocReq, sizeof(*pAssocReq), 0); + + /* Parse Assoc Request frame */ + if (subType == LIM_ASSOC) + status = + sir_convert_assoc_req_frame2_struct(pMac, pBody, framelen, + pAssocReq); + else + status = + sir_convert_reassoc_req_frame2_struct(pMac, pBody, framelen, + pAssocReq); + + if (status != eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("Parse error AssocRequest, length=%d from " + MAC_ADDRESS_STR), framelen, MAC_ADDR_ARRAY(pHdr->sa)); + lim_send_assoc_rsp_mgmt_frame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, + 1, pHdr->sa, subType, 0, + psessionEntry); + goto error; + } + + pAssocReq->assocReqFrame = cdf_mem_malloc(framelen); + if (NULL == pAssocReq->assocReqFrame) { + lim_log(pMac, LOGE, + FL("Unable to allocate memory for the assoc req, " + "length=%d from "), framelen); + goto error; + } + + cdf_mem_copy((uint8_t *) pAssocReq->assocReqFrame, + (uint8_t *) pBody, framelen); + pAssocReq->assocReqFrameLength = framelen; + + if (cfg_get_capability_info(pMac, &temp, psessionEntry) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("could not retrieve Capabilities")); + goto error; + } + lim_copy_u16((uint8_t *) &localCapabilities, temp); + + if (lim_compare_capabilities(pMac, + pAssocReq, + &localCapabilities, psessionEntry) == false) + { + lim_log(pMac, LOGE, FL("local caps mismatch received caps")); + lim_log(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. + */ + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, + 1, + pHdr->sa, subType, 0, psessionEntry); + + goto error; + } + + updateContext = false; + + if (lim_cmp_s_sid(pMac, &pAssocReq->ssId, psessionEntry) == false) { + lim_log(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. + */ + lim_send_assoc_rsp_mgmt_frame(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 (lim_check_rx_basic_rates(pMac, basicRates, psessionEntry) == false) { + lim_log(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. + */ + lim_send_assoc_rsp_mgmt_frame(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)) + { + lim_log(pMac, LOGE, + FL("SOFTAP was in 11G only mode, rejecting legacy " + "STA : " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa)); + lim_send_assoc_rsp_mgmt_frame(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)) { + lim_log(pMac, LOGE, + FL("SOFTAP was in 11N only mode, rejecting legacy " + "STA : " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa)); + lim_send_assoc_rsp_mgmt_frame(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)) { + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, + 1, pHdr->sa, subType, 0, + psessionEntry); + lim_log(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) { + lim_log(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) { + lim_log(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 = + lim_is_dot11h_power_capabilities_in_range(pMac, + pAssocReq, + psessionEntry); + if (eSIR_SUCCESS != status) { + lim_log(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 = + lim_is_dot11h_supported_channels_valid(pMac, + pAssocReq); + if (eSIR_SUCCESS != status) { + lim_log(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) + && (lim_check_mcs_set(pMac, pAssocReq->HTCaps.supportedMCSSet) == + false)) { + lim_log(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. + */ + lim_send_assoc_rsp_mgmt_frame(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_cfg_get_int(pMac, WNI_CFG_11G_ONLY_POLICY, &val) != + eSIR_SUCCESS) { + lim_log(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. + */ + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS, + 1, + pHdr->sa, + subType, 0, psessionEntry); + + lim_log(pMac, LOGE, + FL("Rejecting Re/Assoc req from 11b STA: ")); + lim_print_mac_addr(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... */ + + lim_log(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 */ + cdf_mem_set((uint8_t *) &Dot11fIERSN, sizeof(Dot11fIERSN), 0); + cdf_mem_set((uint8_t *) &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 { + lim_log(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) { + lim_log(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 */ + dot11f_unpack_ie_rsn(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 = + lim_check_rx_rsn_ie_match(pMac, + Dot11fIERSN, + psessionEntry, + pAssocReq-> + HTCaps. + present, + &pmfConnection))) + { + lim_log(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 */ + lim_send_assoc_rsp_mgmt_frame + (pMac, status, 1, + pHdr->sa, subType, + 0, psessionEntry); + + goto error; + + } + } else { + lim_log(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 */ + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS, + 1, + pHdr-> + sa, + subType, + 0, + psessionEntry); + goto error; + + } + } else { + lim_log(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 */ + lim_send_assoc_rsp_mgmt_frame(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) { + dot11f_unpack_ie_wpa(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 = + lim_check_rx_wpa_ie_match(pMac, + Dot11fIEWPA, + psessionEntry, + pAssocReq-> + HTCaps. + present))) { + lim_log(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 */ + lim_send_assoc_rsp_mgmt_frame(pMac, + status, + 1, + pHdr-> + sa, + subType, + 0, + psessionEntry); + goto error; + + } + } else { + lim_log(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 */ + lim_send_assoc_rsp_mgmt_frame(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 { + lim_log(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 = + dph_lookup_hash_entry(pMac, pHdr->sa, &peerIdx, + &psessionEntry->dph.dphHashTable); + + /* / Extract pre-auth context for the STA, if any. */ + pStaPreAuthContext = lim_search_pre_auth_list(pMac, pHdr->sa); + + if (pStaDs == NULL) { + /* / Requesting STA is not currently associated */ + if (pe_get_current_stas_count(pMac) == + pMac->lim.gLimAssocStaLimit) { + /** + * Maximum number of STAs that AP can handle reached. + * Send Association response to peer MAC entity + */ + lim_log(pMac, LOGE, FL("Max Sta count reached : %d"), + pMac->lim.maxStation); + lim_reject_association(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. + */ + lim_send_deauth_mgmt_frame(pMac, eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, /* =9 */ + pHdr->sa, psessionEntry, false); + + lim_log(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; + lim_delete_pre_auth_node(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 + lim_log(pMac, LOGE, + FL("received Assoc req in state " + "%X from "), + pStaDs->mlmStaContext.mlmState); + } else { +#ifdef WLAN_DEBUG + pMac->lim.gLimNumReassocReqDropInvldState++; +#endif + lim_log(pMac, LOGE, + FL("received ReAssoc req in state %X" + " from "), + pStaDs->mlmStaContext.mlmState); + } + lim_print_mac_addr(pMac, pHdr->sa, LOG1); + lim_print_mlm_state(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 + lim_log(pMac, LOG1, + FL + ("Re/Assoc request from station that is already associated")); + lim_log(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; + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_TRY_AGAIN_LATER, + 1, pHdr->sa, subType, + pStaDs, psessionEntry); + lim_send_sa_query_request_frame(pMac, + (uint8_t *) & + (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) { + lim_log(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: + lim_send_assoc_rsp_mgmt_frame(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 ((true == + cdf_mem_compare(&pStaDs->mlmStaContext.capabilityInfo, + &pAssocReq->capabilityInfo, + sizeof(tSirMacCapabilityInfo))) + && (subType == LIM_ASSOC)) { + lim_log(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 + */ + lim_log(pMac, LOG1, + FL("Recved 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; + lim_delete_pre_auth_node(pMac, pHdr->sa); + } else + authType = pStaDs->mlmStaContext.authType; + + updateContext = true; + if (dph_init_sta_state + (pMac, pHdr->sa, peerIdx, true, + &psessionEntry->dph.dphHashTable) + == NULL) { + lim_log(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) { + uint8_t tspecIdx = 0; /* index in the sch tspec table. */ + if (lim_admit_control_add_ts + (pMac, pHdr->sa, &(pAssocReq->addtsReq), + &(pAssocReq->qosCapability), 0, false, NULL, + &tspecIdx, psessionEntry) != eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("AdmitControl: TSPEC rejected")); + lim_send_assoc_rsp_mgmt_frame(pMac, + eSIR_MAC_QAP_NO_BANDWIDTH_REASON, + 1, pHdr->sa, subType, + 0, psessionEntry); +#ifdef WLAN_DEBUG + pMac->lim.gLimNumAssocReqDropACRejectTS++; +#endif + goto error; + } + } else if (lim_admit_control_add_sta(pMac, pHdr->sa, false) + != eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("AdmitControl: Sta rejected")); + lim_send_assoc_rsp_mgmt_frame(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 */ + lim_log(pMac, LOG1, FL("AdmitControl: Sta OK!")); + } + + /** + * STA is Associated ! + */ + lim_log(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: lim_assign_peer_idx() assigns AID values ranging + * between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT) + */ + + peerIdx = lim_assign_peer_idx(pMac, psessionEntry); + + if (!peerIdx) { + /* Could not assign AID */ + /* Reject association */ + lim_log(pMac, LOGE, + FL("PeerIdx not avaialble. Reject associaton")); + lim_reject_association(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 = + dph_add_hash_entry(pMac, pHdr->sa, peerIdx, + &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) { + /* Could not add hash table entry at DPH */ + lim_log(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 */ + lim_release_peer_idx(pMac, peerIdx, psessionEntry); + + lim_reject_association(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 assoc_req and free it before + * assigning this new pAssocReq + */ + if (psessionEntry->parsedAssocReq != NULL) { + pTempAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId]; + if (pTempAssocReq != NULL) { + if (pTempAssocReq->assocReqFrame) { + cdf_mem_free(pTempAssocReq->assocReqFrame); + pTempAssocReq->assocReqFrame = NULL; + pTempAssocReq->assocReqFrameLength = 0; + } + cdf_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 = + (uint8_t) pAssocReq->capabilityInfo.shortPreamble; + pStaDs->shortSlotTimeEnabled = + (uint8_t) 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 = + (uint8_t) 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 = (uint8_t) pAssocReq->HTCaps.greenField; + pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity; + pStaDs->htDsssCckRate40MHzSupport = + (uint8_t) pAssocReq->HTCaps.dsssCckMode40MHz; + pStaDs->htLsigTXOPProtection = + (uint8_t) pAssocReq->HTCaps.lsigTXOPProtection; + pStaDs->htMaxAmsduLength = + (uint8_t) pAssocReq->HTCaps.maximalAMSDUsize; + pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor; + pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave; + + /* pAssocReq will be copied to psessionEntry->parsedAssocReq + * later + */ + ht_cap_ie = ((uint8_t *) &pAssocReq->HTCaps) + 1; + + /* check whether AP is enabled with shortGI */ + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) != + eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, + FL("could not retrieve shortGI 20Mhz CFG"));) + goto error; + } + if (val) { + pStaDs->htShortGI20Mhz = + (uint8_t)pAssocReq->HTCaps.shortGI20MHz; + } else { + /* Unset htShortGI20Mhz in ht_caps*/ + *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI20MHZ_S); + pStaDs->htShortGI20Mhz = 0; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) != + eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, + FL("could not retrieve shortGI 40Mhz CFG"));) + goto error; + } + if (val) { + pStaDs->htShortGI40Mhz = + (uint8_t)pAssocReq->HTCaps.shortGI40MHz; + } else { + /* Unset htShortGI40Mhz in ht_caps */ + *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI40MHZ_S); + pStaDs->htShortGI40Mhz = 0; + } + + pStaDs->htSupportedChannelWidthSet = + (uint8_t) 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 = + (uint8_t) ((pAssocReq->operMode.chanWidth == + eHT_CHANNEL_WIDTH_80MHZ) ? + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ); + pStaDs->htSupportedChannelWidthSet = + (uint8_t) (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 = + (uint8_t) ((pStaDs->htSupportedChannelWidthSet == + eHT_CHANNEL_WIDTH_20MHZ) ? + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ : + psessionEntry->ch_width - 1); + 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 = + (uint8_t) pAssocReq->HTCaps.advCodingCap; + } + + if (pAssocReq->VHTCaps.present && pAssocReq->wmeInfoPresent) { + pStaDs->vhtLdpcCapable = + (uint8_t) pAssocReq->VHTCaps.ldpcCodingCap; + } + + if (!pAssocReq->wmeInfoPresent) { + pStaDs->mlmStaContext.htCapability = 0; + pStaDs->mlmStaContext.vhtCapability = 0; + } + if (pStaDs->mlmStaContext.vhtCapability) { + if (psessionEntry->txBFIniFeatureEnabled && + pAssocReq->VHTCaps.suBeamFormerCap) + pStaDs->vhtBeamFormerCapable = 1; + else + pStaDs->vhtBeamFormerCapable = 0; + if (psessionEntry->enable_su_tx_bformer && + pAssocReq->VHTCaps.suBeamformeeCap) + pStaDs->vht_su_bfee_capable = 1; + else + pStaDs->vht_su_bfee_capable = 0; + } +#ifdef WLAN_FEATURE_11AC + if (lim_populate_matching_rate_set(pMac, + pStaDs, + &(pAssocReq->supportedRates), + &(pAssocReq->extendedRates), + pAssocReq->HTCaps.supportedMCSSet, + psessionEntry, &pAssocReq->VHTCaps) + != eSIR_SUCCESS) +#else + + if (lim_populate_matching_rate_set(pMac, + pStaDs, + &(pAssocReq->supportedRates), + &(pAssocReq->extendedRates), + pAssocReq->HTCaps.supportedMCSSet, + psessionEntry) != eSIR_SUCCESS) +#endif + { + /* Could not update hash table entry at DPH with rateset */ + lim_log(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 */ + lim_release_peer_idx(pMac, peerIdx, psessionEntry); + + lim_reject_association(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 = false; + pStaDs->lleEnabled = false; + if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET)) { + pStaDs->lleEnabled = true; + pStaDs->qosMode = true; + } + + pStaDs->wmeEnabled = false; + pStaDs->wsmEnabled = false; + limGetWmeMode(psessionEntry, &wmeMode); + if ((!pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent + && (wmeMode == eHAL_SET)) { + pStaDs->wmeEnabled = true; + pStaDs->qosMode = 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. + */ + lim_log(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 = 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_cfg_get_int(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retryInterval) != eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL + ("Could not retrieve PMF SA Query retry interval value")); + lim_reject_association(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_STAMIN > retryInterval) { + retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF; + } + if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer", + lim_pmf_sa_query_timer_handler, timerId.value, + SYS_MS_TO_TICKS((retryInterval * 1024) / 1000), + 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGE, FL("could not create PMF SA Query timer")); + lim_reject_association(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, pMac); + } else { + pStaDs->timingMeasCap = 0; + PELOG1(lim_log(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 lim_del_sta() 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 WMA_ADD_STA_REQ to HAL */ + if (lim_add_sta(pMac, pStaDs, false, psessionEntry) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("could not Add STA with assocId=%d"), + pStaDs->assocId); + lim_reject_association(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 lim_del_sta */ + if (subType != LIM_REASSOC) { + /* we need to set the mlmState here in order differentiate in lim_del_sta. */ + pStaDs->mlmStaContext.mlmState = + eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE; + if (lim_del_sta(pMac, pStaDs, true, psessionEntry) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL + ("could not DEL STA with assocId=%d staId %d"), + pStaDs->assocId, pStaDs->staIndex); + lim_reject_association(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 lim_add_sta context */ + /* use the same AID, already allocated */ + if (lim_add_sta(pMac, pStaDs, false, psessionEntry) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("Could not AddSta with assocId= %d" + "staId %d"), + pStaDs->assocId, pStaDs->staIndex); + lim_reject_association(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 */ + lim_post_sm_state_update(pMac, pStaDs->staIndex, + pStaDs->htMIMOPSState, + pStaDs->staAddr, + psessionEntry->smeSessionId); + } + + return; + +error: + if (pAssocReq != NULL) { + if (pAssocReq->assocReqFrame) { + cdf_mem_free(pAssocReq->assocReqFrame); + pAssocReq->assocReqFrame = NULL; + pAssocReq->assocReqFrameLength = 0; + } + + cdf_mem_free(pAssocReq); + /* to avoid double free */ + if (assoc_req_copied && psessionEntry->parsedAssocReq) + psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; + } + + /* If it is not duplicate Assoc request then only make to Null */ + 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) { + cdf_mem_free(pTempAssocReq-> + assocReqFrame); + pTempAssocReq->assocReqFrame = NULL; + pTempAssocReq->assocReqFrameLength = 0; + } + cdf_mem_free(pTempAssocReq); + psessionEntry-> + parsedAssocReq[pStaDs->assocId] = NULL; + } + } + } + + return; + +} /*** end lim_process_assoc_req_frame() ***/ + +#ifdef FEATURE_WLAN_WAPI +/** + * lim_fill_assoc_ind_wapi_info()- Updates WAPI data in assoc indication + * @mac_ctx: Global Mac context + * @assoc_req: pointer to association request + * @assoc_ind: Pointer to association indication + * @wpsie: WPS IE + * + * This function updates WAPI meta data in association indication message + * sent to SME. + * + * Return: None + */ +static void lim_fill_assoc_ind_wapi_info(tpAniSirGlobal mac_ctx, + tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind, + uint8_t *wpsie) +{ + if (assoc_req->wapiPresent && (NULL == wpsie)) { + lim_log(mac_ctx, LOG2, + FL("Received WAPI IE length in Assoc Req is %d"), + assoc_req->wapi.length); + assoc_ind->wapiIE.wapiIEdata[0] = SIR_MAC_WAPI_EID; + assoc_ind->wapiIE.wapiIEdata[1] = assoc_req->wapi.length; + cdf_mem_copy(&assoc_ind->wapiIE.wapiIEdata[2], + assoc_req->wapi.info, assoc_req->wapi.length); + assoc_ind->wapiIE.length = + 2 + assoc_req->wapi.length; + } + return; +} +#endif + +/** + * lim_fill_assoc_ind_vht_info() - Updates VHT information in assoc indication + * @mac_ctx: Global Mac context + * @assoc_req: pointer to association request + * @session_entry: PE session entry + * @assoc_ind: Pointer to association indication + * + * This function updates VHT information in association indication message + * sent to SME. + * + * Return: None + */ +static void lim_fill_assoc_ind_vht_info(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tpSirAssocReq assoc_req, + tpLimMlmAssocInd assoc_ind) +{ + uint8_t chan; + + if (session_entry->limRFBand == SIR_BAND_2_4_GHZ) { + if (session_entry->vhtCapability + && assoc_req->VHTCaps.present) + assoc_ind->chan_info.info = MODE_11AC_VHT20; + else if (session_entry->htCapability + && assoc_req->HTCaps.present) + assoc_ind->chan_info.info = MODE_11NG_HT20; + else + assoc_ind->chan_info.info = MODE_11G; + } else { + if (session_entry->vhtCapability + && assoc_req->VHTCaps.present) { + if ((session_entry->ch_width > CH_WIDTH_40MHZ) + && assoc_req->HTCaps.supportedChannelWidthSet) { + chan = session_entry->ch_center_freq_seg0; + assoc_ind->chan_info.band_center_freq1 = + cds_chan_to_freq(chan); + assoc_ind->chan_info.info = MODE_11AC_VHT80; + } else if ((session_entry->ch_width == CH_WIDTH_40MHZ) + && assoc_req->HTCaps.supportedChannelWidthSet) { + assoc_ind->chan_info.info = MODE_11AC_VHT40; + if (session_entry->htSecondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + assoc_ind->chan_info.band_center_freq1 + += 10; + else + assoc_ind->chan_info.band_center_freq1 + -= 10; + } else { + assoc_ind->chan_info.info = MODE_11AC_VHT20; + } + } else if (session_entry->htCapability + && assoc_req->HTCaps.present) { + if ((session_entry->ch_width == CH_WIDTH_40MHZ) + && assoc_req->HTCaps.supportedChannelWidthSet) { + assoc_ind->chan_info.info = MODE_11NA_HT40; + if (session_entry->htSecondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + assoc_ind->chan_info.band_center_freq1 + += 10; + else + assoc_ind->chan_info.band_center_freq1 + -= 10; + } else { + assoc_ind->chan_info.info = MODE_11NA_HT20; + } + } else { + assoc_ind->chan_info.info = MODE_11A; + } + } + return; +} + +/** + * lim_send_mlm_assoc_ind() - Sends assoc indication to SME + * @mac_ctx: Global Mac context + * @sta_ds: Station DPH hash entry + * @session_entry: PE session entry + * + * This function sends either LIM_MLM_ASSOC_IND + * or LIM_MLM_REASSOC_IND to SME. + * + * Return: None + */ +void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, tpPESession session_entry) +{ + tpLimMlmAssocInd assoc_ind = NULL; + tpSirAssocReq assoc_req; + uint16_t temp, rsn_len; + uint32_t phy_mode; + uint8_t sub_type; + uint8_t *wpsie = NULL; + uint32_t tmp; + + /* Get a copy of the already parsed Assoc Request */ + assoc_req = + (tpSirAssocReq) session_entry->parsedAssocReq[sta_ds->assocId]; + + /* Get the phy_mode */ + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + /* Determine if its Assoc or ReAssoc Request */ + if (assoc_req->reassocRequest == 1) + sub_type = LIM_REASSOC; + else + sub_type = LIM_ASSOC; + + lim_log(mac_ctx, LOG1, + FL("Sessionid %d ssid %s sub_type %d Associd %d staAddr " + MAC_ADDRESS_STR), session_entry->peSessionId, + assoc_req->ssId.ssId, sub_type, sta_ds->assocId, + MAC_ADDR_ARRAY(sta_ds->staAddr)); + + if (sub_type == LIM_ASSOC || sub_type == LIM_REASSOC) { + temp = sizeof(tLimMlmAssocInd); + + assoc_ind = cdf_mem_malloc(temp); + if (NULL == assoc_ind) { + lim_release_peer_idx(mac_ctx, sta_ds->assocId, + session_entry); + lim_log(mac_ctx, LOGP, + FL("AllocateMemory failed for assoc_ind")); + return; + } + cdf_mem_set(assoc_ind, temp, 0); + cdf_mem_copy((uint8_t *) assoc_ind->peerMacAddr, + (uint8_t *) sta_ds->staAddr, sizeof(tSirMacAddr)); + assoc_ind->aid = sta_ds->assocId; + cdf_mem_copy((uint8_t *) &assoc_ind->ssId, + (uint8_t *) &(assoc_req->ssId), + assoc_req->ssId.length + 1); + assoc_ind->sessionId = session_entry->peSessionId; + assoc_ind->authType = sta_ds->mlmStaContext.authType; + assoc_ind->capabilityInfo = assoc_req->capabilityInfo; + + /* Fill in RSN IE information */ + assoc_ind->rsnIE.length = 0; + /* if WPS IE is present, ignore RSN IE */ + if (assoc_req->addIEPresent && assoc_req->addIE.length) { + wpsie = limGetWscIEPtr(mac_ctx, + assoc_req->addIE.addIEdata, + assoc_req->addIE.length); + } + if (assoc_req->rsnPresent && (NULL == wpsie)) { + lim_log(mac_ctx, LOG2, FL("Assoc Req RSN IE len = %d"), + assoc_req->rsn.length); + assoc_ind->rsnIE.length = 2 + assoc_req->rsn.length; + assoc_ind->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID; + assoc_ind->rsnIE.rsnIEdata[1] = + assoc_req->rsn.length; + cdf_mem_copy(&assoc_ind->rsnIE.rsnIEdata[2], + assoc_req->rsn.info, + assoc_req->rsn.length); + } + /* Fill in 802.11h related info */ + if (assoc_req->powerCapabilityPresent + && assoc_req->supportedChannelsPresent) { + assoc_ind->spectrumMgtIndicator = eSIR_TRUE; + assoc_ind->powerCap.minTxPower = + assoc_req->powerCapability.minTxPower; + assoc_ind->powerCap.maxTxPower = + assoc_req->powerCapability.maxTxPower; + lim_convert_supported_channels(mac_ctx, assoc_ind, + assoc_req); + } else { + assoc_ind->spectrumMgtIndicator = eSIR_FALSE; + } + + /* This check is to avoid extra Sec IEs present incase of WPS */ + if (assoc_req->wpaPresent && (NULL == wpsie)) { + rsn_len = assoc_ind->rsnIE.length; + if ((rsn_len + assoc_req->wpa.length) + >= SIR_MAC_MAX_IE_LENGTH) { + lim_log(mac_ctx, LOGE, + FL("rsnIEdata index out of bounds %d"), + rsn_len); + cdf_mem_free(assoc_ind); + return; + } + assoc_ind->rsnIE.rsnIEdata[rsn_len] = + SIR_MAC_WPA_EID; + assoc_ind->rsnIE.rsnIEdata[rsn_len + 1] + = assoc_req->wpa.length; + cdf_mem_copy( + &assoc_ind->rsnIE.rsnIEdata[rsn_len + 2], + assoc_req->wpa.info, assoc_req->wpa.length); + assoc_ind->rsnIE.length += 2 + assoc_req->wpa.length; + } +#ifdef FEATURE_WLAN_WAPI + lim_fill_assoc_ind_wapi_info(mac_ctx, assoc_req, assoc_ind, + wpsie); +#endif + + assoc_ind->addIE.length = 0; + if (assoc_req->addIEPresent) { + cdf_mem_copy(&assoc_ind->addIE.addIEdata, + assoc_req->addIE.addIEdata, + assoc_req->addIE.length); + assoc_ind->addIE.length = assoc_req->addIE.length; + } + /* + * Add HT Capabilities into addIE for OBSS + * processing in hostapd + */ + if (assoc_req->HTCaps.present) { + rsn_len = assoc_ind->addIE.length; + if (assoc_ind->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN + + 2 < SIR_MAC_MAX_IE_LENGTH) { + assoc_ind->addIE.addIEdata[rsn_len] = + SIR_MAC_HT_CAPABILITIES_EID; + assoc_ind->addIE.addIEdata[rsn_len + 1] = + DOT11F_IE_HTCAPS_MIN_LEN; + cdf_mem_copy( + &assoc_ind->addIE.addIEdata[rsn_len+2], + ((uint8_t *)&assoc_req->HTCaps) + 1, + DOT11F_IE_HTCAPS_MIN_LEN); + assoc_ind->addIE.length += + 2 + DOT11F_IE_HTCAPS_MIN_LEN; + } else { + lim_log(mac_ctx, LOGP, + FL("Fail:HT capabilities IE to addIE")); + } + } + + if (assoc_req->wmeInfoPresent) { + if (wlan_cfg_get_int (mac_ctx, + (uint16_t) WNI_CFG_WME_ENABLED, &tmp) + != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("wlan_cfg_get_int failed for id %d"), + WNI_CFG_WME_ENABLED); + + /* check whether AP is enabled with WMM */ + if (tmp) + assoc_ind->WmmStaInfoPresent = 1; + else + assoc_ind->WmmStaInfoPresent = 0; + /* + * Note: we are not rejecting association here + * because IOT will fail + */ + } + /* Required for indicating the frames to upper layer */ + assoc_ind->assocReqLength = assoc_req->assocReqFrameLength; + assoc_ind->assocReqPtr = assoc_req->assocReqFrame; + + assoc_ind->beaconPtr = session_entry->beacon; + assoc_ind->beaconLength = session_entry->bcnLen; + + assoc_ind->chan_info.chan_id = + session_entry->currentOperChannel; + assoc_ind->chan_info.mhz = + cds_chan_to_freq(session_entry->currentOperChannel); + assoc_ind->chan_info.band_center_freq1 = + cds_chan_to_freq(session_entry->currentOperChannel); + assoc_ind->chan_info.band_center_freq2 = 0; + assoc_ind->chan_info.reg_info_1 = + (session_entry->maxTxPower << 16); + assoc_ind->chan_info.reg_info_2 = + (session_entry->maxTxPower << 8); + /* updates VHT information in assoc indication */ + lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req, + assoc_ind); + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND, + (uint32_t *) assoc_ind); + cdf_mem_free(assoc_ind); + } + return; +} diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c new file mode 100644 index 000000000000..e4c672be0e35 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -0,0 +1,1109 @@ +/* + * 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 lim_process_assoc_rsp_frame.cc contains the code + * for processing Re/Association Response Frame. + * Author: Chandra Modumudi + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wni_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" +#include "sch_api.h" + +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_sta_hash_api.h" +#include "lim_send_messages.h" + + +extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry); + +/** + * lim_update_stads_htcap() - Updates station Descriptor HT capability + * @mac_ctx: Pointer to Global MAC structure + * @sta_ds: Station Descriptor in DPH + * @assoc_rsp: Pointer to Association Response Structure + * + * This function is called to Update the HT capabilities in + * Station Descriptor (dph) Details from + * Association / ReAssociation Response Frame + * + * Return: None + */ +static void lim_update_stads_htcap(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp) +{ + uint16_t highest_rxrate = 0; + tDot11fIEHTCaps *ht_caps; + + ht_caps = &assoc_rsp->HTCaps; + sta_ds->mlmStaContext.htCapability = assoc_rsp->HTCaps.present; + if (assoc_rsp->HTCaps.present) { + sta_ds->htGreenfield = + (uint8_t) ht_caps->greenField; + sta_ds->htSupportedChannelWidthSet = + (uint8_t) (ht_caps->supportedChannelWidthSet ? + assoc_rsp->HTInfo.recommendedTxWidthSet : + ht_caps->supportedChannelWidthSet); + sta_ds->htLsigTXOPProtection = + (uint8_t) ht_caps->lsigTXOPProtection; + sta_ds->htMIMOPSState = + (tSirMacHTMIMOPowerSaveState)ht_caps->mimoPowerSave; + sta_ds->htMaxAmsduLength = + (uint8_t) ht_caps->maximalAMSDUsize; + sta_ds->htAMpduDensity = ht_caps->mpduDensity; + sta_ds->htDsssCckRate40MHzSupport = + (uint8_t) ht_caps->dsssCckMode40MHz; + sta_ds->htShortGI20Mhz = + (uint8_t) ht_caps->shortGI20MHz; + sta_ds->htShortGI40Mhz = + (uint8_t) ht_caps->shortGI40MHz; + sta_ds->htMaxRxAMpduFactor = + ht_caps->maxRxAMPDUFactor; + lim_fill_rx_highest_supported_rate(mac_ctx, &highest_rxrate, + ht_caps->supportedMCSSet); + sta_ds->supportedRates.rxHighestDataRate = + highest_rxrate; + /* + * This is for AP as peer STA and we are INFRA STA + *.We will put APs offset in dph node which is peer STA + */ + sta_ds->htSecondaryChannelOffset = + (uint8_t) assoc_rsp->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 + */ + sta_ds->baPolicyFlag = 0xFF; + } +} + +/** + * lim_update_assoc_sta_datas() - Updates station Descriptor + * mac_ctx: Pointer to Global MAC structure + * sta_ds: Station Descriptor in DPH + * assoc_rsp: Pointer to Association Response Structure + * session_entry : PE session Entry + * + * This function is called to Update the Station Descriptor (dph) Details from + * Association / ReAssociation Response Frame + * + * Return: None + */ +void lim_update_assoc_sta_datas(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, + tpPESession session_entry) +{ + uint32_t phy_mode; + bool qos_mode; + tDot11fIEVHTCaps *vht_caps = NULL; + + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + sta_ds->staType = STA_ENTRY_SELF; + limGetQosMode(session_entry, &qos_mode); + sta_ds->mlmStaContext.authType = session_entry->limCurrentAuthType; + + /* Add capabilities information, rates and AID */ + sta_ds->mlmStaContext.capabilityInfo = assoc_rsp->capabilityInfo; + sta_ds->shortPreambleEnabled = + (uint8_t) assoc_rsp->capabilityInfo.shortPreamble; + + /* Update HT Capabilites only when the self mode supports HT */ + if (IS_DOT11_MODE_HT(session_entry->dot11mode)) + lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp); + +#ifdef WLAN_FEATURE_11AC + if (assoc_rsp->VHTCaps.present) + vht_caps = &assoc_rsp->VHTCaps; + else if (assoc_rsp->vendor2_ie.VHTCaps.present) + vht_caps = &assoc_rsp->vendor2_ie.VHTCaps; + + if (IS_DOT11_MODE_VHT(session_entry->dot11mode)) { + if ((vht_caps != NULL) && vht_caps->present) { + sta_ds->mlmStaContext.vhtCapability = + vht_caps->present; + /* + * If 11ac is supported and if the peer is + * sending VHT capabilities, + * then htMaxRxAMpduFactor should be + * overloaded with VHT maxAMPDULenExp + */ + sta_ds->htMaxRxAMpduFactor = vht_caps->maxAMPDULenExp; + if (session_entry->htSupportedChannelWidthSet) { + if (assoc_rsp->VHTOperation.present) + sta_ds->vhtSupportedChannelWidthSet = + assoc_rsp->VHTOperation.chanWidth; + else + sta_ds->vhtSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } + } + } + if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates, + assoc_rsp->HTCaps.supportedMCSSet, + false, session_entry, + vht_caps) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("could not get rateset and extended rate set")); + return; + } +#else + if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates, + assoc_rsp->HTCaps.supportedMCSSet, + false, session_entry) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("could not get rateset and extended rate set")); + return; + } +#endif +#ifdef WLAN_FEATURE_11AC + sta_ds->vhtSupportedRxNss = + ((sta_ds->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2) + == MCSMAPMASK2x2) ? 1 : 2; +#endif + /* If one of the rates is 11g rates, set the ERP mode. */ + if ((phy_mode == WNI_CFG_PHY_MODE_11G) && + sirIsArate(sta_ds->supportedRates.llaRates[0] & 0x7f)) + sta_ds->erpEnabled = eHAL_SET; + + /* Could not get prop rateset from CFG. Log error. */ + sta_ds->qosMode = 0; + sta_ds->lleEnabled = 0; + + /* update TSID to UP mapping */ + if (qos_mode) { + if (assoc_rsp->edcaPresent) { + tSirRetStatus status; + status = + sch_beacon_edca_process(mac_ctx, + &assoc_rsp->edca, session_entry); + lim_log(mac_ctx, LOG2, + "Edca set update based on AssocRsp: status %d", + status); + if (status != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("Edca error in AssocResp ")); + } else { + /* update default tidmap based on ACM */ + sta_ds->qosMode = 1; + sta_ds->lleEnabled = 1; + } + } + } + + sta_ds->wmeEnabled = 0; + sta_ds->wsmEnabled = 0; + if (session_entry->limWmeEnabled && assoc_rsp->wmeEdcaPresent) { + tSirRetStatus status; + status = sch_beacon_edca_process(mac_ctx, &assoc_rsp->edca, + session_entry); + lim_log(mac_ctx, LOGW, + "WME Edca set update based on AssocRsp: status %d", + status); + + if (status != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("WME Edca error in AssocResp - ignoring")); + + else { + /* update default tidmap based on HashACM */ + sta_ds->qosMode = 1; + sta_ds->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 + * lim_process_sta_mlm_add_bss_rsp(). + */ + sch_set_default_edca_params(mac_ctx, session_entry); + } + + if (qos_mode && (!sta_ds->qosMode) && + sta_ds->mlmStaContext.htCapability) { + /* + * Enable QOS for all HT AP's even though WMM + * or 802.11E IE is not present + */ + sta_ds->qosMode = 1; + sta_ds->wmeEnabled = 1; + } +#ifdef WLAN_FEATURE_11W + if (session_entry->limRmfEnabled) + sta_ds->rmfEnabled = 1; +#endif +} + +/** + * @function : lim_update_re_assoc_globals + * + * @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 lim_update_re_assoc_globals(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, + tpPESession psessionEntry) +{ + /* Update the current Bss Information */ + cdf_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; + + cdf_mem_copy((uint8_t *) &psessionEntry->ssId, + (uint8_t *) &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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + psessionEntry->limMlmState)); + +} +#ifdef WLAN_FEATURE_VOWIFI_11R +/** + * lim_update_ric_data() - update session with ric data + * @mac_ctx: Pointer to Global MAC structure + * @session_entry: PE session handle + * @assoc_rsp: pointer to assoc response + * + * This function is called by lim_process_assoc_rsp_frame() to + * update PE session context with RIC data. + * + * Return: None + */ +static void lim_update_ric_data(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tpSirAssocRsp assoc_rsp) +{ + if (session_entry->ricData != NULL) { + cdf_mem_free(session_entry->ricData); + session_entry->ricData = NULL; + } + if (assoc_rsp->ricPresent) { + session_entry->RICDataLen = + assoc_rsp->num_RICData * sizeof(tDot11fIERICDataDesc); + session_entry->ricData = + cdf_mem_malloc(session_entry->RICDataLen); + if (NULL == session_entry->ricData) { + lim_log(mac_ctx, LOGE, + FL("Assoc res/RIC: Unable to allocate memory")); + session_entry->RICDataLen = 0; + } else { + cdf_mem_copy(session_entry->ricData, + &assoc_rsp->RICData[0], + session_entry->RICDataLen); + } + } else { + lim_log(mac_ctx, LOG1, + FL("Ric is not present,Set RICDataLen & RicData to 0")); + session_entry->RICDataLen = 0; + session_entry->ricData = NULL; + } + return; +} +#endif + +#ifdef FEATURE_WLAN_ESE + +/** + * lim_update_ese_tspec() - update session with Tspec info. + * @mac_ctx: Pointer to Global MAC structure + * @session_entry: PE session handle + * @assoc_rsp: pointer to assoc response + * + * This function is called by lim_process_assoc_rsp_frame() to + * update PE session context with Tspec data. + * + * Return: None + */ +static void lim_update_ese_tspec(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tpSirAssocRsp assoc_rsp) +{ + if (session_entry->tspecIes != NULL) { + cdf_mem_free(session_entry->tspecIes); + session_entry->tspecIes = NULL; + } + if (assoc_rsp->tspecPresent) { + session_entry->tspecLen = + assoc_rsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC); + session_entry->tspecIes = + cdf_mem_malloc(session_entry->tspecLen); + if (NULL == session_entry->tspecIes) { + lim_log(mac_ctx, LOGE, + FL("Assoc Rsp/Tspec:Fail to allocate memory")); + session_entry->tspecLen = 0; + } else { + cdf_mem_copy(session_entry->tspecIes, + &assoc_rsp->TSPECInfo[0], + session_entry->tspecLen); + } + lim_log(mac_ctx, LOG1, FL(" Tspec EID present in assoc rsp ")); + } else { + session_entry->tspecLen = 0; + session_entry->tspecIes = NULL; + lim_log(mac_ctx, LOG1, + FL(" Tspec EID *NOT* present in assoc rsp ")); + } + return; +} + +/** + * lim_update_ese_tsm() - update session with TSM info. + * @mac_ctx: Pointer to Global MAC structure + * @session_entry: PE session handle + * @assoc_rsp: pointer to assoc response + * + * This function is called by lim_process_assoc_rsp_frame() to + * update PE session context with TSM IE data and send + * eWNI_TSM_IE_IND to SME. + * + * Return: None + */ +static void lim_update_ese_tsm(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tpSirAssocRsp assoc_rsp) +{ + uint8_t cnt = 0; + tpEseTSMContext tsm_ctx; + + lim_log(mac_ctx, LOG1, + FL("TSM IE Present in Reassoc Rsp")); + /* + * Start the TSM timer only if the TSPEC + * Ie is present in the reassoc rsp + */ + if (!assoc_rsp->tspecPresent) { + lim_log(mac_ctx, LOGE, + FL("TSM present but TSPEC IE not present")); + return; + } + tsm_ctx = &session_entry->eseContext.tsm; + /* Find the TSPEC IE with VO user priority */ + for (cnt = 0; cnt < assoc_rsp->num_tspecs; cnt++) { + if (upToAc(assoc_rsp->TSPECInfo[cnt].user_priority) == + EDCA_AC_VO) { + tsm_ctx->tid = + assoc_rsp->TSPECInfo[cnt].user_priority; + cdf_mem_copy(&tsm_ctx->tsmInfo, + &assoc_rsp->tsmIE, sizeof(tSirMacESETSMIE)); +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_tsm_ie_ind(mac_ctx, + session_entry, assoc_rsp->tsmIE.tsid, + assoc_rsp->tsmIE.state, + assoc_rsp->tsmIE.msmt_interval); +#else + limActivateTSMStatsTimer(mac_ctx, session_entry); +#endif + if (tsm_ctx->tsmInfo.state) + tsm_ctx->tsmMetrics.RoamingCount++; + break; + } + } +} +#endif + +/** + * lim_update_stads_ext_cap() - update sta ds with ext cap + * @mac_ctx: Pointer to Global MAC structure + * @session_entry: PE session handle + * @assoc_rsp: pointer to assoc response + * + * This function is called by lim_process_assoc_rsp_frame() to + * update STA DS with ext capablities. + * + * Return: None + */ +static void lim_update_stads_ext_cap(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tpSirAssocRsp assoc_rsp, + tpDphHashNode sta_ds) +{ + struct s_ext_cap *ext_cap; + if (!assoc_rsp->ExtCap.present) { + sta_ds->timingMeasCap = 0; +#ifdef FEATURE_WLAN_TDLS + session_entry->tdls_prohibited = false; + session_entry->tdls_chan_swit_prohibited = false; +#endif + lim_log(mac_ctx, LOG1, FL("ExtCap not present")); + return; + } + + ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes; + lim_set_stads_rtt_cap(sta_ds, ext_cap, mac_ctx); +#ifdef FEATURE_WLAN_TDLS + session_entry->tdls_prohibited = ext_cap->tdls_prohibited; + session_entry->tdls_chan_swit_prohibited = + ext_cap->tdls_chan_swit_prohibited; + lim_log(mac_ctx, LOG1, + FL("ExtCap: tdls_prohibited:%d, tdls_chan_swit_prohibited: %d"), + ext_cap->tdls_prohibited, + ext_cap->tdls_chan_swit_prohibited); +#endif +} + +/** + * lim_process_assoc_rsp_frame() - Processes assoc response + * @mac_ctx: Pointer to Global MAC structure + * @rx_packet_info - A pointer to Rx packet info structure + * @sub_type - Indicates whether it is Association Response (=0) or + * Reassociation Response (=1) frame + * + * This function is called by limProcessMessageQueue() upon + * Re/Association Response frame reception. + * + * Return: None + */ + +void +lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, + uint8_t *rx_pkt_info, uint8_t subtype, tpPESession session_entry) +{ + uint8_t *body; + uint16_t caps, ie_len; + uint32_t frame_len; + tSirMacAddr current_bssid; + tpSirMacMgmtHdr hdr = NULL; + tSirMacCapabilityInfo mac_capab; + tpDphHashNode sta_ds; + tpSirAssocRsp assoc_rsp; + tLimMlmAssocCnf assoc_cnf; + tSchBeaconStruct *beacon; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t sme_sessionid = 0; +#endif + tCsrRoamSession *roam_session; + + /* Initialize status code to success. */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session_entry->bRoamSynchInProgress) + hdr = (tpSirMacMgmtHdr) mac_ctx->roam.pReassocResp; + else +#endif + hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + sme_sessionid = session_entry->smeSessionId; +#endif + assoc_cnf.resultCode = eSIR_SME_SUCCESS; + /* Update PE session Id */ + assoc_cnf.sessionId = session_entry->peSessionId; + if (hdr == NULL) { + lim_log(mac_ctx, LOGE, + FL("LFR3: Reassoc response packet header is NULL")); + return; + } else if (hdr->sa == NULL) { + lim_log(mac_ctx, LOGE, + FL("LFR3: Reassoc resp packet source address is NULL")); + return; + } + + lim_log(mac_ctx, LOG1, + FL("received Re/Assoc(%d) resp on sessionid: %d systemrole: %d" + "and mlmstate: %d RSSI %d from " MAC_ADDRESS_STR), subtype, + session_entry->peSessionId, GET_LIM_SYSTEM_ROLE(session_entry), + session_entry->limMlmState, + (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(rx_pkt_info)), + MAC_ADDR_ARRAY(hdr->sa)); + + beacon = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == beacon) { + lim_log(mac_ctx, LOGE, FL("Unable to allocate memory")); + return; + } + + if (LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + /* + * Should not have received Re/Association + * Response frame on AP. Log error + */ + lim_log(mac_ctx, LOGE, + FL("Should not recieved Re/Assoc Response in role %d "), + GET_LIM_SYSTEM_ROLE(session_entry)); + cdf_mem_free(beacon); + return; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session_entry->bRoamSynchInProgress) { + hdr = (tpSirMacMgmtHdr) mac_ctx->roam.pReassocResp; + frame_len = mac_ctx->roam.reassocRespLen - SIR_MAC_HDR_LEN_3A; + } else { +#endif + hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +} +#endif + if (((subtype == LIM_ASSOC) && + (session_entry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) || + ((subtype == LIM_REASSOC) && + ((session_entry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + && (session_entry->limMlmState != + eLIM_MLM_WT_FT_REASSOC_RSP_STATE) +#endif + ))) { + /* Received unexpected Re/Association Response frame */ + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, + FL("Recieved Re/Assoc rsp in unexpected " + "state %d on session=%d"), + session_entry->limMlmState, session_entry->peSessionId); +#endif + if (!hdr->fc.retry) { + if (!(mac_ctx->lim.retry_packet_cnt & 0xf)) { + lim_log(mac_ctx, LOGE, + FL("recvd Re/Assoc rsp:not a retry frame")); + lim_print_mlm_state(mac_ctx, LOGE, + session_entry->limMlmState); + } else { + mac_ctx->lim.retry_packet_cnt++; + } + } + cdf_mem_free(beacon); + return; + } + sir_copy_mac_addr(current_bssid, session_entry->bssId); + if (subtype == LIM_ASSOC) { + if (!cdf_mem_compare + (hdr->sa, current_bssid, sizeof(tSirMacAddr))) { + /* + * Received Association Response frame from an entity + * other than one to which request was initiated. + * Ignore this and wait until Assoc Failure Timeout + */ + lim_log(mac_ctx, LOGW, + FL("received AssocRsp from unexpected peer " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(hdr->sa)); + cdf_mem_free(beacon); + return; + } + } else { + if (!cdf_mem_compare + (hdr->sa, session_entry->limReAssocbssId, + sizeof(tSirMacAddr))) { + /* + * Received Reassociation Response frame from an entity + * other than one to which request was initiated. + * Ignore this and wait until Reassoc Failure Timeout. + */ + lim_log(mac_ctx, LOGW, + FL("received ReassocRsp from unexpected peer " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(hdr->sa)); + cdf_mem_free(beacon); + return; + } + } + + assoc_rsp = cdf_mem_malloc(sizeof(*assoc_rsp)); + if (NULL == assoc_rsp) { + lim_log(mac_ctx, LOGP, + FL("Allocate Memory failed in AssocRsp")); + cdf_mem_free(beacon); + return; + } + /* Get pointer to Re/Association Response frame body */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session_entry->bRoamSynchInProgress) + body = mac_ctx->roam.pReassocResp + SIR_MAC_HDR_LEN_3A; + else +#endif + body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + /* parse Re/Association Response frame. */ + if (sir_convert_assoc_resp_frame2_struct(mac_ctx, body, + frame_len, assoc_rsp) == eSIR_FAILURE) { + cdf_mem_free(assoc_rsp); + lim_log(mac_ctx, LOGE, + FL("Parse error Assoc resp subtype %d," "length=%d"), + frame_len, subtype); + cdf_mem_free(beacon); + return; + } + + if (!assoc_rsp->suppRatesPresent) { + lim_log(mac_ctx, LOGE, + FL("assoc response does not have supported rate set")); + cdf_mem_copy(&assoc_rsp->supportedRates, + &session_entry->rateSet, + sizeof(tSirMacRateSet)); + } + + assoc_cnf.protStatusCode = assoc_rsp->statusCode; + if (session_entry->assocRsp != NULL) { + lim_log(mac_ctx, LOGW, + FL("session_entry->assocRsp is not NULL freeing it " + "and setting NULL")); + cdf_mem_free(session_entry->assocRsp); + session_entry->assocRsp = NULL; + } + + session_entry->assocRsp = cdf_mem_malloc(frame_len); + if (NULL == session_entry->assocRsp) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory for assoc res,len=%d"), + frame_len); + } else { + /* + * Store the Assoc response. This is sent + * to csr/hdd in join cnf response. + */ + cdf_mem_copy(session_entry->assocRsp, body, frame_len); + session_entry->assocRspLen = frame_len; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + lim_update_ric_data(mac_ctx, session_entry, assoc_rsp); +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + roam_session = + &mac_ctx->roam.roamSession[sme_sessionid]; + if (assoc_rsp->FTInfo.R0KH_ID.present) { + roam_session->ftSmeContext.r0kh_id_len = + assoc_rsp->FTInfo.R0KH_ID.num_PMK_R0_ID; + cdf_mem_copy(roam_session->ftSmeContext.r0kh_id, + assoc_rsp->FTInfo.R0KH_ID.PMK_R0_ID, + roam_session->ftSmeContext.r0kh_id_len); + } else { + roam_session->ftSmeContext.r0kh_id_len = 0; + cdf_mem_zero(roam_session->ftSmeContext.r0kh_id, + SIR_ROAM_R0KH_ID_MAX_LEN); + } +#endif + +#ifdef FEATURE_WLAN_ESE + lim_update_ese_tspec(mac_ctx, session_entry, assoc_rsp); +#endif + + if (assoc_rsp->capabilityInfo.ibss) { + /* + * Received Re/Association Response from peer + * with IBSS capability set. + * Ignore the frame and wait until Re/assoc + * failure timeout. + */ + lim_log(mac_ctx, LOGE, + FL("received Re/AssocRsp frame with IBSS capability")); + cdf_mem_free(assoc_rsp); + cdf_mem_free(beacon); + return; + } + + if (cfg_get_capability_info(mac_ctx, &caps, session_entry) + != eSIR_SUCCESS) { + cdf_mem_free(assoc_rsp); + cdf_mem_free(beacon); + lim_log(mac_ctx, LOGP, FL("could not retrieve Capabilities ")); + return; + } + lim_copy_u16((uint8_t *) &mac_capab, caps); + + /* Stop Association failure timer */ + if (subtype == LIM_ASSOC) + lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER); + else + { + /* Stop Reassociation failure timer */ +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + mac_ctx->lim.reAssocRetryAttempt = 0; + if ((NULL != mac_ctx->lim.pSessionEntry) + && (NULL != + mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq)) { + cdf_mem_free( + mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq); + mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq = + NULL; + } +#endif + lim_deactivate_and_change_timer(mac_ctx, + eLIM_REASSOC_FAIL_TIMER); + } + + if (assoc_rsp->statusCode != eSIR_MAC_SUCCESS_STATUS +#ifdef WLAN_FEATURE_11W + && assoc_rsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER +#endif + ) { + /* + *Re/Association response was received + * either with failure code. + */ + lim_log(mac_ctx, LOGE, + FL("received Re/AssocRsp frame failure code %d"), + assoc_rsp->statusCode); + /* + * Need to update 'association failure' error counter + * along with STATUS CODE + * Return Assoc confirm to SME with received failure code + */ + assoc_cnf.resultCode = eSIR_SME_ASSOC_REFUSED; + /* Delete Pre-auth context for the associated BSS */ + if (lim_search_pre_auth_list(mac_ctx, hdr->sa)) + lim_delete_pre_auth_node(mac_ctx, hdr->sa); + goto assocReject; + } else if ((assoc_rsp->aid & 0x3FFF) > 2007) { + /* + * Re/Association response was received + * with invalid AID value + */ + lim_log(mac_ctx, LOGE, FL("received Re/AssocRsp frame with" + "invalid aid %X"), assoc_rsp->aid); + assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED; + assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Send advisory Disassociation frame to AP */ + lim_send_disassoc_mgmt_frame(mac_ctx, + eSIR_MAC_UNSPEC_FAILURE_REASON, + hdr->sa, session_entry, 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 + * lim_process_mlm_assoc_req + */ +#ifdef WLAN_FEATURE_11W + if (assoc_rsp->statusCode == eSIR_MAC_TRY_AGAIN_LATER) { + if (assoc_rsp->TimeoutInterval.present && + (assoc_rsp->TimeoutInterval.timeoutType == + SIR_MAC_TI_TYPE_ASSOC_COMEBACK)) { + uint16_t timeout_value = + assoc_rsp->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; + } + lim_log(mac_ctx, LOG1, + FL("ASSOC res with eSIR_MAC_TRY_AGAIN_LATER " + " recvd.Starting timer to wait timeout=%d."), + timeout_value); + if (CDF_STATUS_SUCCESS != + cdf_mc_timer_start( + &session_entry->pmfComebackTimer, + timeout_value)) { + lim_log(mac_ctx, LOGE, + FL("Failed to start comeback timer.")); + } + } else { + lim_log(mac_ctx, LOGW, + FL("ASSOC resp with try again event recvd. " + "But try again time interval IE is wrong.")); + } + cdf_mem_free(beacon); + cdf_mem_free(assoc_rsp); + return; + } +#endif + if (!((session_entry->bssType == eSIR_BTAMP_STA_MODE) || + ((session_entry->bssType == eSIR_BTAMP_AP_MODE) && + LIM_IS_BT_AMP_STA_ROLE(session_entry)))) { + if (lim_set_link_state + (mac_ctx, eSIR_LINK_POSTASSOC_STATE, + session_entry->bssId, + session_entry->selfMacAddr, NULL, + NULL) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("Set link state to POSTASSOC failed")); + cdf_mem_free(beacon); + cdf_mem_free(assoc_rsp); + return; + } + } + if (subtype == LIM_REASSOC) { + lim_log + (mac_ctx, LOG1, FL("Successfully Reassociated with BSS")); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT, + session_entry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif +#ifdef FEATURE_WLAN_ESE + if (assoc_rsp->tsmPresent) + lim_update_ese_tsm(mac_ctx, session_entry, assoc_rsp); +#endif + if (session_entry->pLimMlmJoinReq) { + cdf_mem_free(session_entry->pLimMlmJoinReq); + session_entry->pLimMlmJoinReq = NULL; + } + + session_entry->limAssocResponseData = (void *)assoc_rsp; + /* + * Store the ReAssocRsp Frame in DphTable + * to be used during processing DelSta and + * DelBss to send AddBss again + */ + sta_ds = + dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + + if (!sta_ds) { + lim_log(mac_ctx, LOGE, + FL("could not get hash entry at DPH for")); + lim_print_mac_addr(mac_ctx, hdr->sa, LOGE); + assoc_cnf.resultCode = + eSIR_SME_INVALID_ASSOC_RSP_RXED; + assoc_cnf.protStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + + /* Send advisory Disassociation frame to AP */ + lim_send_disassoc_mgmt_frame(mac_ctx, + eSIR_MAC_UNSPEC_FAILURE_REASON, hdr->sa, + session_entry, false); + goto assocReject; + } +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (session_entry->limMlmState == + eLIM_MLM_WT_FT_REASSOC_RSP_STATE) { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("Sending self sta")); +#endif + lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp, + session_entry); + /* Store assigned AID for TIM processing */ + session_entry->limAID = assoc_rsp->aid & 0x3FFF; + /* Downgrade the EDCA parameters if needed */ + lim_set_active_edca_params(mac_ctx, + session_entry->gLimEdcaParams, + session_entry); + /* Send the active EDCA parameters to HAL */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (!session_entry->bRoamSynchInProgress) { +#endif + lim_send_edca_params(mac_ctx, + session_entry->gLimEdcaParamsActive, + sta_ds->bssId); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } +#endif + lim_add_ft_sta_self(mac_ctx, (assoc_rsp->aid & 0x3FFF), + session_entry); + cdf_mem_free(beacon); + 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 (sir_compare_mac_addr(session_entry->bssId, + session_entry->limReAssocbssId)) + lim_handle_add_bss_in_re_assoc_context(mac_ctx, sta_ds, + session_entry); + else { + /* + * reset the uapsd mask settings since + * we're re-associating to new AP + */ + session_entry->gUapsdPerAcDeliveryEnableMask = 0; + session_entry->gUapsdPerAcTriggerEnableMask = 0; + + if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry) + != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("Could not cleanup the rx path")); + goto assocReject; + } + } + cdf_mem_free(beacon); + return; + } + lim_log(mac_ctx, LOG1, + FL("Successfully Associated with BSS " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(hdr->sa)); +#ifdef FEATURE_WLAN_ESE + if (session_entry->eseContext.tsm.tsmInfo.state) + session_entry->eseContext.tsm.tsmMetrics.RoamingCount = 0; +#endif + /* Store assigned AID for TIM processing */ + session_entry->limAID = assoc_rsp->aid & 0x3FFF; + + /* STA entry was created during pre-assoc state. */ + sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + /* Could not add hash table entry */ + lim_log(mac_ctx, LOGE, FL("could not get hash entry at DPH ")); + lim_print_mac_addr(mac_ctx, hdr->sa, LOGE); + assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + assoc_cnf.protStatusCode = eSIR_SME_SUCCESS; + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF, + (uint32_t *) &assoc_cnf); + cdf_mem_free(assoc_rsp); + cdf_mem_free(beacon); + return; + } + /* Delete Pre-auth context for the associated BSS */ + if (lim_search_pre_auth_list(mac_ctx, hdr->sa)) + lim_delete_pre_auth_node(mac_ctx, hdr->sa); + + lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp, session_entry); + /* + * Extract the AP capabilities from the beacon that + * was received earlier + */ + ie_len = lim_get_ielen_from_bss_description( + &session_entry->pLimJoinReq->bssDescription); + lim_extract_ap_capabilities(mac_ctx, + (uint8_t *) session_entry->pLimJoinReq->bssDescription.ieFields, + ie_len, + beacon); + + if (mac_ctx->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection_on_assoc(mac_ctx, beacon, + session_entry); + + if (beacon->erpPresent) { + if (beacon->erpIEInfo.barkerPreambleMode) + session_entry->beaconParams.fShortPreamble = false; + else + session_entry->beaconParams.fShortPreamble = true; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_CONNECTED, session_entry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + if (assoc_rsp->QosMapSet.present) + cdf_mem_copy(&session_entry->QosMapSet, + &assoc_rsp->QosMapSet, sizeof(tSirQosMapSet)); + else + cdf_mem_zero(&session_entry->QosMapSet, sizeof(tSirQosMapSet)); + + lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds); + /* Update the BSS Entry, this entry was added during preassoc. */ + if (eSIR_SUCCESS == lim_sta_send_add_bss(mac_ctx, assoc_rsp, + beacon, + &session_entry->pLimJoinReq->bssDescription, true, + session_entry)) { + cdf_mem_free(assoc_rsp); + cdf_mem_free(beacon); + return; + } else { + lim_log(mac_ctx, LOGE, FL("could not update the bss entry")); + assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + } + +assocReject: + if ((subtype == LIM_ASSOC) +#ifdef WLAN_FEATURE_VOWIFI_11R + || ((subtype == LIM_REASSOC) + && (session_entry->limMlmState == + eLIM_MLM_WT_FT_REASSOC_RSP_STATE)) +#endif + ) { + lim_log(mac_ctx, LOGE, FL("Assoc Rejected by the peer. " + "mlmestate: %d sessionid %d Reason: %d MACADDR:" + MAC_ADDRESS_STR), + session_entry->limMlmState, + session_entry->peSessionId, + assoc_cnf.resultCode, MAC_ADDR_ARRAY(hdr->sa)); + session_entry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + session_entry->limMlmState)); + if (session_entry->pLimMlmJoinReq) { + cdf_mem_free(session_entry->pLimMlmJoinReq); + session_entry->pLimMlmJoinReq = NULL; + } + if (subtype == LIM_ASSOC) { + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF, + (uint32_t *) &assoc_cnf); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + else { + assoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; + lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF, + (uint32_t *)&assoc_cnf); + } +#endif + } else { + lim_restore_pre_reassoc_state(mac_ctx, + eSIR_SME_REASSOC_REFUSED, + assoc_cnf.protStatusCode, + session_entry); + } + + cdf_mem_free(beacon); + cdf_mem_free(assoc_rsp); + return; +} diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c new file mode 100644 index 000000000000..9871cff47c9b --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -0,0 +1,1929 @@ +/* + * 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 lim_process_auth_frame.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 "wni_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" + +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft.h" +#endif +#include "cds_utils.h" + +/** + * is_auth_valid + * + ***FUNCTION: + * This function is called by lim_process_auth_frame() 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 is_auth_valid(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; +} + +/** + * lim_process_auth_frame + * + ***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 +lim_process_auth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + uint8_t *pBody, keyId, cfgPrivacyOptImp, + defaultKey[SIR_MAC_KEY_LENGTH], + encrAuthFrame[LIM_ENCR_AUTH_BODY_LEN], plainBody[256]; + uint16_t frameLen; + uint32_t maxNumPreAuth, val; + tSirMacAuthFrameBody *pRxAuthFrameBody, rxAuthFrame, authFrame; + tpSirMacMgmtHdr pHdr; + struct tLimPreAuthNode *pAuthNode; + uint8_t decryptResult; + uint8_t *pChallenge; + uint32_t key_length = 8; + uint8_t challengeTextArray[SIR_MAC_AUTH_CHALLENGE_LENGTH]; + tpDphHashNode pStaDs = NULL; + uint16_t assocId = 0; + uint16_t curr_seq_num = 0; + + /* Get pointer to Authentication frame header and body */ + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (!frameLen) { + /* Log error */ + lim_log(pMac, LOGE, + FL("received Authentication frame with no body from ")); + lim_print_mac_addr(pMac, pHdr->sa, LOGE); + + return; + } + + if (lim_is_group_addr(pHdr->sa)) { + /* Received Auth frame from a BC/MC address */ + /* Log error and ignore it */ + lim_log(pMac, LOGE, FL ( + "received Auth frame from a BC/MC addr - ")); + PELOGE(lim_print_mac_addr(pMac, pHdr->sa, LOGE);) + + return; + } + curr_seq_num = (pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo); + + lim_log(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((int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo))); + + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + + /* Restore default failure timeout */ + if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona + && psessionEntry->defaultAuthFailureTimeout) { + lim_log(pMac, LOG1, FL("Restore default failure timeout")); + cfg_set_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + psessionEntry->defaultAuthFailureTimeout); + } + /* / 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(lim_log + (pMac, LOGE, + FL + ("Tkip counter measures Enabled, sending Deauth frame to")); + ) + lim_print_mac_addr(pMac, pHdr->sa, LOGE); + + lim_send_deauth_mgmt_frame(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(lim_log(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)); + ) + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } + + if (frameLen < LIM_ENCR_AUTH_BODY_LEN) { + /* Log error */ + lim_log(pMac, LOGE, + FL + ("Not enough size [%d] to decrypt received Auth frame"), + frameLen); + lim_print_mac_addr(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_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + lim_log(pMac, LOGP, + FL("could not retrieve Privacy option")); + } + + cfgPrivacyOptImp = (uint8_t) 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 = lim_search_pre_auth_list(pMac, pHdr->sa); + + if (pAuthNode == NULL) { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } else { + /* / Change the auth-response timeout */ + lim_deactivate_and_change_per_sta_id_timer(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(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } + } + + val = SIR_MAC_KEY_LENGTH; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + tpSirKeys pKey; + pKey = + &psessionEntry-> + WEPKeyMaterial[keyId].key[0]; + cdf_mem_copy(defaultKey, pKey->key, + pKey->keyLength); + val = pKey->keyLength; + } else if (wlan_cfg_get_str(pMac, + (uint16_t) (WNI_CFG_WEP_DEFAULT_KEY_1 + + keyId), defaultKey, + &val) != eSIR_SUCCESS) { + /* / Could not get Default key from CFG. */ + /* Log error. */ + lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + + return; + } + + key_length = val; + + decryptResult = lim_decrypt_auth_frame(pMac, defaultKey, + pBody, plainBody, key_length, + (uint16_t) (frameLen - + SIR_MAC_WEP_IV_LENGTH)); + if (decryptResult == LIM_DECRYPT_ICV_FAIL) { + /* Log error */ + PELOGE(lim_log(pMac, LOGE, + FL + ("received Authentication frame from peer that failed decryption: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + ) + /* / ICV failure */ + lim_delete_pre_auth_node(pMac, + pHdr->sa); + authFrame.authAlgoNumber = + eSIR_SHARED_KEY; + authFrame.authTransactionSeqNumber = + SIR_MAC_AUTH_FRAME_4; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } + if ((sir_convert_auth_frame2_struct + (pMac, plainBody, frameLen - 8, + &rxAuthFrame) != eSIR_SUCCESS) || + (!is_auth_valid + (pMac, &rxAuthFrame, psessionEntry))) { + lim_log(pMac, LOGE, + FL + ("failed to convert Auth Frame to structure or Auth is not valid ")); + return; + } + } else { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, psessionEntry); + return; + } /* else if (wlan_cfg_get_int(CFG_PRIVACY_OPTION_IMPLEMENTED)) */ + } /* if (fc.wep) */ + else { + if ((sir_convert_auth_frame2_struct(pMac, pBody, + frameLen, + &rxAuthFrame) != eSIR_SUCCESS) + || (!is_auth_valid(pMac, &rxAuthFrame, psessionEntry))) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("failed to convert Auth Frame to structure or Auth is not valid ")); + ) + return; + } + } + + pRxAuthFrameBody = &rxAuthFrame; + + PELOGW(lim_log(pMac, LOGW, + FL + ("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), + (uint32_t) pRxAuthFrameBody->authAlgoNumber, + (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber, + (uint32_t) pRxAuthFrameBody->authStatusCode, + (uint32_t) pMac->lim.gLimNumPreAuthContexts); + ) + + switch (pRxAuthFrameBody->authTransactionSeqNumber) { + case SIR_MAC_AUTH_FRAME_1: + /* AuthFrame 1 */ + + pStaDs = dph_lookup_hash_entry(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 + && + (cdf_mem_compare + ((uint8_t *) pHdr->sa, + (uint8_t *) &pMlmDisassocReq->peerMacAddr, + sizeof(tSirMacAddr)))) { + PELOGE(lim_log + (pMac, LOGE, + FL("TODO:Ack for disassoc " + "frame is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDisassocReq-> + peerMacAddr)); + ) + lim_process_disassoc_ack_timeout(pMac); + isConnected = eSIR_FALSE; + } + pMlmDeauthReq = + pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (pMlmDeauthReq + && + (cdf_mem_compare + ((uint8_t *) pHdr->sa, + (uint8_t *) &pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)))) { + PELOGE(lim_log + (pMac, LOGE, + FL("TODO:Ack for deauth frame " + "is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDeauthReq-> + peerMacAddr)); + ) + lim_process_deauth_ack_timeout(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 + ) { + lim_log(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); + lim_send_deauth_mgmt_frame(pMac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + (uint8_t *) pHdr->sa, + psessionEntry, false); + lim_trigger_sta_deletion(pMac, pStaDs, + psessionEntry); + return; + } + } + /* / Check if there exists pre-auth context for this STA */ + pAuthNode = lim_search_pre_auth_list(pMac, pHdr->sa); + if (pAuthNode) { + /* / Pre-auth context exists for the STA */ + if (pHdr->fc.retry == 0 || + pAuthNode->seq_num != curr_seq_num) { + /** + * 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) { + lim_deactivate_and_change_per_sta_id_timer + (pMac, eLIM_AUTH_RSP_TIMER, + pAuthNode->authNodeIdx); + } + PELOGE(lim_log + (pMac, LOGE, + FL + ("STA is initiating brand-new Authentication ...")); + ) + lim_delete_pre_auth_node(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 = + dph_get_hash_entry(pMac, assocId, + &psessionEntry->dph. + dphHashTable); + + if (NULL == pStaDs) + continue; + + if (pStaDs->valid) { + if (cdf_mem_compare + ((uint8_t *) &pStaDs-> + staAddr, + (uint8_t *) &(pHdr->sa), + (uint8_t) (sizeof + (tSirMacAddr)))) + break; + } + + pStaDs = NULL; + } + + if (NULL != pStaDs +#ifdef WLAN_FEATURE_11W + && !pStaDs->rmfEnabled +#endif + ) { + PELOGE(lim_log(pMac, LOGE, + FL + ("lim Delete Station Context (staId: %d, assocId: %d) "), + pStaDs->staIndex, + assocId); + ) + lim_send_deauth_mgmt_frame(pMac, + eSIR_MAC_UNSPEC_FAILURE_REASON, + (uint8_t *) + pAuthNode-> + peerMacAddr, + psessionEntry, + false); + lim_trigger_sta_deletion(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(lim_log + (pMac, LOGE, + FL + ("STA is initiating Authentication after ACK lost...")); + ) + return; + } + } + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, + (uint32_t *) &maxNumPreAuth) != + eSIR_SUCCESS) { + /** + * Could not get MaxNumPreAuth + * from CFG. Log error. + */ + lim_log(pMac, LOGP, + FL("could not retrieve MaxNumPreAuth")); + } + if (pMac->lim.gLimNumPreAuthContexts == maxNumPreAuth && + !lim_delete_open_auth_pre_auth_node(pMac)) { + PELOGE(lim_log + (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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, psessionEntry); + + return; + } + /* / No Pre-auth context exists for the STA. */ + if (lim_is_auth_algo_supported(pMac, (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber, + psessionEntry)) { + switch (pRxAuthFrameBody->authAlgoNumber) { + case eSIR_OPEN_SYSTEM: + PELOGW(lim_log + (pMac, LOGW, + FL("=======> eSIR_OPEN_SYSTEM ...")); + ) + /* / Create entry for this STA in pre-auth list */ + pAuthNode = + lim_acquire_free_pre_auth_node(pMac, + &pMac->lim. + gLimPreAuthTimerTable); + if (pAuthNode == NULL) { + /* Log error */ + lim_log(pMac, LOGW, + FL + ("Max pre-auth nodes reached ")); + lim_print_mac_addr(pMac, pHdr->sa, LOGW); + + return; + } + + PELOG1(lim_log + (pMac, LOG1, + FL("Alloc new data: %x peer "), + pAuthNode); + lim_print_mac_addr(pMac, pHdr->sa, LOG1); + ) + + cdf_mem_copy((uint8_t *) pAuthNode-> + peerMacAddr, pHdr->sa, + sizeof(tSirMacAddr)); + + pAuthNode->mlmState = + eLIM_MLM_AUTHENTICATED_STATE; + pAuthNode->authType = (tAniAuthType) + pRxAuthFrameBody->authAlgoNumber; + pAuthNode->fSeen = 0; + pAuthNode->fTimerStarted = 0; + pAuthNode->seq_num = + ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = + cdf_mc_timer_get_system_ticks(); + lim_add_pre_auth_node(pMac, pAuthNode); + + /** + * Send Authenticaton frame with Success + * status code. + */ + + authFrame.authAlgoNumber = + pRxAuthFrameBody->authAlgoNumber; + authFrame.authTransactionSeqNumber = + pRxAuthFrameBody->authTransactionSeqNumber + + 1; + authFrame.authStatusCode = + eSIR_MAC_SUCCESS_STATUS; + lim_send_auth_mgmt_frame(pMac, &authFrame, pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + break; + + case eSIR_SHARED_KEY: + PELOGW(lim_log + (pMac, LOGW, + FL("=======> eSIR_SHARED_KEY ...")); + ) + if (LIM_IS_AP_ROLE(psessionEntry)) { + val = psessionEntry->privacy; + } else + if (wlan_cfg_get_int + (pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + lim_log(pMac, LOGP, + FL + ("could not retrieve Privacy option")); + } + cfgPrivacyOptImp = (uint8_t) val; + if (!cfgPrivacyOptImp) { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } else { + /* Create entry for this STA */ + /* in pre-auth list */ + pAuthNode = + lim_acquire_free_pre_auth_node(pMac, + &pMac-> + lim. + gLimPreAuthTimerTable); + if (pAuthNode == NULL) { + /* Log error */ + lim_log(pMac, LOGW, + FL + ("Max pre-auth nodes reached ")); + lim_print_mac_addr(pMac, pHdr->sa, + LOGW); + + return; + } + + cdf_mem_copy((uint8_t *) 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->seq_num = + ((pHdr->seqControl.seqNumHi << + 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = + cdf_mc_timer_get_system_ticks(); + lim_add_pre_auth_node(pMac, pAuthNode); + + PELOG1(lim_log + (pMac, LOG1, + FL + ("Alloc new data: %x id %d peer "), + pAuthNode, + pAuthNode->authNodeIdx); + ) + PELOG1(lim_print_mac_addr + (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 */ + lim_log(pMac, LOGP, + FL + ("Unable to chg context auth response timer for peer ")); + lim_print_mac_addr(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; + + lim_send_auth_mgmt_frame(pMac, + &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + + lim_delete_pre_auth_node(pMac, + pHdr->sa); + return; + } + + lim_activate_auth_rsp_timer(pMac, + pAuthNode); + + pAuthNode->fTimerStarted = 1; + + /* get random bytes and use as */ + /* challenge text. If it fails we already have random stack bytes. */ + if (!CDF_IS_STATUS_SUCCESS + (cds_rand_get_bytes + (0, (uint8_t *) challengeTextArray, + SIR_MAC_AUTH_CHALLENGE_LENGTH))) { + lim_log(pMac, LOGE, + FL + ("Challenge text preparation failed in lim_process_auth_frame")); + } + + pChallenge = pAuthNode->challengeText; + + cdf_mem_copy(pChallenge, + (uint8_t *) + 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; + cdf_mem_copy(authFrame.challengeText, + pAuthNode->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH); + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + } /* if (wlan_cfg_get_int(CFG_PRIVACY_OPTION_IMPLEMENTED)) */ + + break; + + default: + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } /* end switch(pRxAuthFrameBody->authAlgoNumber) */ + } /* if (lim_is_auth_algo_supported(pRxAuthFrameBody->authAlgoNumber)) */ + else { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, psessionEntry); + return; + } /* end if (lim_is_auth_algo_supported(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) + && + (cdf_mem_compare + (psessionEntry->ftPEContext.pFTPreAuthReq-> + preAuthbssId, pHdr->sa, sizeof(tSirMacAddr)))) { + /* Update the FTIEs in the saved auth response */ + PELOGW(lim_log + (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)) { + cdf_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(lim_log(pMac, LOG1, + FL + ("received Auth frame2 from peer in state %d, addr "), + psessionEntry->limMlmState); + ) + PELOG1(lim_print_mac_addr + (pMac, pHdr->sa, LOG1); + ) + } + + return; + + } + + if (!cdf_mem_compare((uint8_t *) pHdr->sa, + (uint8_t *) &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(lim_log(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(lim_log(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 = + lim_acquire_free_pre_auth_node(pMac, + &pMac->lim. + gLimPreAuthTimerTable); + + if (pAuthNode == NULL) { + /* Log error */ + lim_log(pMac, LOGW, + FL + ("Max pre-auth nodes reached ")); + lim_print_mac_addr(pMac, pHdr->sa, LOGW); + + return; + } + + PELOG1(lim_log + (pMac, LOG1, + FL("Alloc new data: %x peer "), + pAuthNode); + ) + PELOG1(lim_print_mac_addr + (pMac, pHdr->sa, LOG1); + ) + + cdf_mem_copy((uint8_t *) pAuthNode-> + peerMacAddr, + pMac->lim.gpLimMlmAuthReq-> + peerMacAddr, + sizeof(tSirMacAddr)); + pAuthNode->fTimerStarted = 0; + pAuthNode->authType = + pMac->lim.gpLimMlmAuthReq->authType; + pAuthNode->seq_num = + ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = + cdf_mc_timer_get_system_ticks(); + lim_add_pre_auth_node(pMac, pAuthNode); + + lim_restore_from_auth_state(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_cfg_get_int + (pMac, WNI_CFG_PRIVACY_ENABLED, + &val) != eSIR_SUCCESS) { + /** + * Could not get Privacy option + * from CFG. Log error. + */ + lim_log(pMac, LOGP, + FL + ("could not retrieve Privacy option")); + } + cfgPrivacyOptImp = (uint8_t) 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(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } else { + + if (pRxAuthFrameBody->type != + SIR_MAC_CHALLENGE_TEXT_EID) { + /* Log error */ + PELOGE(lim_log(pMac, LOGE, + FL + ("received Auth frame with invalid challenge text IE")); + ) + + return; + } + + if (wlan_cfg_get_int + (pMac, + WNI_CFG_WEP_DEFAULT_KEYID, + &val) != eSIR_SUCCESS) { + /** + * Could not get Default keyId + * from CFG. Log error. + */ + lim_log(pMac, LOGP, + FL + ("could not retrieve Default keyId")); + } + keyId = (uint8_t) val; + + val = SIR_MAC_KEY_LENGTH; + + if (LIM_IS_AP_ROLE(psessionEntry)) { + tpSirKeys pKey; + pKey = + &psessionEntry-> + WEPKeyMaterial + [keyId].key[0]; + cdf_mem_copy(defaultKey, + pKey->key, + pKey-> + keyLength); + } else + if (wlan_cfg_get_str + (pMac, + (uint16_t) + (WNI_CFG_WEP_DEFAULT_KEY_1 + + keyId), defaultKey, + &val) + != eSIR_SUCCESS) { + /* / Could not get Default key from CFG. */ + /* Log error. */ + lim_log(pMac, LOGP, + FL + ("could not retrieve Default key")); + + authFrame.authAlgoNumber = + pRxAuthFrameBody-> + authAlgoNumber; + authFrame. + authTransactionSeqNumber = + pRxAuthFrameBody-> + authTransactionSeqNumber + + 1; + authFrame.authStatusCode = + eSIR_MAC_CHALLENGE_FAILURE_STATUS; + + lim_send_auth_mgmt_frame + (pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + + lim_restore_from_auth_state + (pMac, + eSIR_SME_INVALID_WEP_DEFAULT_KEY, + eSIR_MAC_UNSPEC_FAILURE_REASON, + psessionEntry); + + break; + } + key_length = val; + ((tpSirMacAuthFrameBody) + plainBody)->authAlgoNumber = + sir_swap_u16if_needed(pRxAuthFrameBody-> + authAlgoNumber); + ((tpSirMacAuthFrameBody) + plainBody)-> + authTransactionSeqNumber = + sir_swap_u16if_needed((uint16_t) + (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; + cdf_mem_copy((uint8_t*) ((tpSirMacAuthFrameBody) plainBody)->challengeText, + pRxAuthFrameBody->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH); + + lim_encrypt_auth_frame(pMac, keyId, + defaultKey, + plainBody, + encrAuthFrame, + key_length); + + psessionEntry->limMlmState = + eLIM_MLM_WT_AUTH_FRAME4_STATE; + MTRACE(mac_trace + (pMac, + TRACE_CODE_MLM_STATE, + psessionEntry-> + peSessionId, + psessionEntry-> + limMlmState)); + + lim_send_auth_mgmt_frame(pMac, + (tpSirMacAuthFrameBody) + encrAuthFrame, + pHdr->sa, + LIM_WEP_IN_FC, + psessionEntry); + + break; + } /* end if (!wlan_cfg_get_int(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(lim_log(pMac, LOGE, + FL + ("received Auth frame from peer with failure code %d " + MAC_ADDRESS_STR), + pRxAuthFrameBody->authStatusCode, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + + lim_restore_from_auth_state(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(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, psessionEntry); + 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(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } + + pAuthNode = lim_search_pre_auth_list(pMac, pHdr->sa); + if (pAuthNode == NULL) { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + return; + } + + if (pAuthNode->mlmState == + eLIM_MLM_AUTH_RSP_TIMEOUT_STATE) { + /* Log error */ + lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + + /* / Delete pre-auth context of STA */ + lim_delete_pre_auth_node(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(lim_log(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 (cdf_mem_compare(pRxAuthFrameBody->challengeText, + pAuthNode->challengeText, + SIR_MAC_AUTH_CHALLENGE_LENGTH)) { + /* / Challenge match. STA is autheticated ! */ + + /* / Delete Authentication response timer if running */ + lim_deactivate_and_change_per_sta_id_timer(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + break; + } else { + /* Log error */ + PELOGE(lim_log(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; + + lim_send_auth_mgmt_frame(pMac, &authFrame, + pHdr->sa, + LIM_NO_WEP_IN_FC, + psessionEntry); + 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(lim_log(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(lim_log(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 (!cdf_mem_compare((uint8_t *) pHdr->sa, + (uint8_t *) &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(lim_log(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(lim_log(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 = + lim_acquire_free_pre_auth_node(pMac, + &pMac->lim. + gLimPreAuthTimerTable); + if (pAuthNode == NULL) { + /* Log error */ + lim_log(pMac, LOGW, + FL("Max pre-auth nodes reached ")); + lim_print_mac_addr(pMac, pHdr->sa, LOGW); + + return; + } + PELOG1(lim_log + (pMac, LOG1, FL("Alloc new data: %x peer "), + pAuthNode); + lim_print_mac_addr(pMac, pHdr->sa, LOG1); + ) + + cdf_mem_copy((uint8_t *) pAuthNode->peerMacAddr, + pMac->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + pAuthNode->fTimerStarted = 0; + pAuthNode->authType = + pMac->lim.gpLimMlmAuthReq->authType; + pAuthNode->seq_num = + ((pHdr->seqControl.seqNumHi << 4) | + (pHdr->seqControl.seqNumLo)); + pAuthNode->timestamp = cdf_mc_timer_get_system_ticks(); + lim_add_pre_auth_node(pMac, pAuthNode); + + lim_restore_from_auth_state(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(lim_log + (pMac, LOGE, + FL("Authentication failure from peer " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa)); + ) + + lim_restore_from_auth_state(pMac, eSIR_SME_AUTH_REFUSED, + pRxAuthFrameBody-> + authStatusCode, + psessionEntry); + } /* end if (pRxAuthFrameBody->Status == 0) */ + + break; + + default: + /* / Invalid Authentication Frame received. Ignore it. */ + + /* Log error */ + PELOGE(lim_log(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 lim_process_auth_frame() ***/ + +#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 lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd, + void *body) +{ + tpSirMacMgmtHdr pHdr; + tpPESession psessionEntry = NULL; + uint8_t *pBody; + uint16_t frameLen; + tSirMacAuthFrameBody rxAuthFrame; + tSirMacAuthFrameBody *pRxAuthFrameBody = NULL; + tSirRetStatus ret_status = eSIR_FAILURE; + int i; + + pHdr = WMA_GET_RX_MAC_HEADER(pBd); + pBody = WMA_GET_RX_MPDU_DATA(pBd); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd); + + lim_log(pMac, LOG1, + FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(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 == + true) { + /* Found the session */ + psessionEntry = &pMac->lim.gpSession[i]; + pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession = + false; + } + } + + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL + ("Error: Unable to find session id while in pre-auth phase for FT")); + return eSIR_FAILURE; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) { + lim_log(pMac, LOGE, FL("Error: No FT")); + /* No FT in progress. */ + return eSIR_FAILURE; + } + + if (frameLen == 0) { + lim_log(pMac, LOGE, FL("Error: Frame len = 0")); + return eSIR_FAILURE; + } +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_print_mac_addr(pMac, pHdr->bssId, LOG2); + lim_print_mac_addr(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + LOG2); + lim_log(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 (!cdf_mem_compare + (psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + pHdr->bssId, sizeof(tSirMacAddr))) { + lim_log(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 (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(lim_log(pMac, LOG1, "Auth rsp already posted to SME" + " (session %p, FT session %p)", psessionEntry, + psessionEntry); + ); + return eSIR_SUCCESS; + } else { + PELOGE(lim_log(pMac, LOGW, "Auth rsp not yet posted to SME" + " (session %p, FT session %p)", psessionEntry, + psessionEntry); + ); + psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = + true; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOG1, FL("Pre-Auth response received from neighbor")); + lim_log(pMac, LOG1, FL("Pre-Auth done state")); +#endif + /* Stopping timer now, that we have our unicast from the AP */ + /* of our choice. */ + lim_deactivate_and_change_timer(pMac, eLIM_FT_PREAUTH_RSP_TIMER); + + /* Save off the auth resp. */ + if ((sir_convert_auth_frame2_struct(pMac, pBody, frameLen, &rxAuthFrame) != + eSIR_SUCCESS)) { + lim_log(pMac, LOGE, + FL("failed to convert Auth frame to struct")); + lim_handle_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0, + psessionEntry); + return eSIR_FAILURE; + } + pRxAuthFrameBody = &rxAuthFrame; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log(pMac, LOG1, + FL + ("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), + (uint32_t) pRxAuthFrameBody->authAlgoNumber, + (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber, + (uint32_t) pRxAuthFrameBody->authStatusCode, + (uint32_t) 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(lim_log + (pMac, LOGE, "Auth status code received is %d", + (uint32_t) 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(lim_log + (pMac, LOGE, "Seq. no incorrect expected 2 received %d", + (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber); + ) +#endif + break; + } + + /* Send the Auth response to SME */ + lim_handle_ft_pre_auth_rsp(pMac, ret_status, pBody, frameLen, psessionEntry); + + return ret_status; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/core/mac/src/pe/lim/lim_process_beacon_frame.c b/core/mac/src/pe/lim/lim_process_beacon_frame.c new file mode 100644 index 000000000000..3a72a69ba418 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_beacon_frame.c @@ -0,0 +1,250 @@ +/* + * 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 lim_process_beacon_frame.cc contains the code + * for processing Received Beacon Frame. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_ser_des_utils.h" + +/** + * lim_process_beacon_frame() - to process beacon frames + * @mac_ctx: Pointer to Global MAC structure + * @rx_pkt_info: A pointer to RX packet info structure + * @session: A pointer to session + * + * This function is called by limProcessMessageQueue() upon Beacon + * frame reception. + * Note: + * 1. Beacons received in 'normal' state in IBSS are handled by + * Beacon Processing module. + * + * Return: none + */ + +void +lim_process_beacon_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpPESession session) +{ + tpSirMacMgmtHdr mac_hdr; + tSchBeaconStruct *bcn_ptr; + + mac_ctx->lim.gLimNumBeaconsRcvd++; + + /* + * here is it required to increment session specific heartBeat + * beacon counter + */ + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + lim_log(mac_ctx, LOG2, + FL("Received Beacon frame with length=%d from "), + WMA_GET_RX_MPDU_LEN(rx_pkt_info)); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG2); + + /* Expect Beacon in any state as Scan is independent of LIM state */ + bcn_ptr = cdf_mem_malloc(sizeof(*bcn_ptr)); + if (NULL == bcn_ptr) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory")); + return; + } + /* Parse received Beacon */ + if (sir_convert_beacon_frame2_struct(mac_ctx, + rx_pkt_info, bcn_ptr) != + eSIR_SUCCESS) { + /* + * Received wrongly formatted/invalid Beacon. + * Ignore it and move on. + */ + lim_log(mac_ctx, LOGW, + FL("Received invalid Beacon in state %X"), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOGW, + session->limMlmState); + cdf_mem_free(bcn_ptr); + 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 ((!session->lastBeaconDtimPeriod) && + (sir_compare_mac_addr(session->bssId, + bcn_ptr->bssid))) { + cdf_mem_copy((uint8_t *)&session->lastBeaconTimeStamp, + (uint8_t *) bcn_ptr->timeStamp, + sizeof(uint64_t)); + session->lastBeaconDtimCount = + bcn_ptr->tim.dtimCount; + session->lastBeaconDtimPeriod = + bcn_ptr->tim.dtimPeriod; + session->currentBssBeaconCnt++; + } + MTRACE(mac_trace(mac_ctx, + TRACE_CODE_RX_MGMT_TSF, 0, bcn_ptr->timeStamp[0]);) + MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 0, + bcn_ptr->timeStamp[1]);) + lim_check_and_add_bss_description(mac_ctx, bcn_ptr, + rx_pkt_info, false, true); + + if ((mac_ctx->lim.gLimMlmState == + eLIM_MLM_WT_PROBE_RESP_STATE) || + (mac_ctx->lim.gLimMlmState == + eLIM_MLM_PASSIVE_SCAN_STATE)) { + lim_check_and_add_bss_description(mac_ctx, bcn_ptr, + rx_pkt_info, + ((mac_ctx->lim.gLimHalScanState == + eLIM_HAL_SCANNING_STATE) ? true : false), + false); + /* + * Calling dfsChannelList which will convert DFS channel + * to active channel for x secs if this channel is DFS + */ + lim_set_dfs_channel_list(mac_ctx, + bcn_ptr->channelNumber, + &mac_ctx->lim.dfschannelList); + } else if (session->limMlmState == + eLIM_MLM_WT_JOIN_BEACON_STATE) { + if (session->beacon != NULL) { + cdf_mem_free(session->beacon); + session->beacon = NULL; + } + session->bcnLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + session->beacon = cdf_mem_malloc(session->bcnLen); + if (NULL == session->beacon) { + lim_log(mac_ctx, LOGE, + FL("fail to alloc mem to store bcn")); + } else { + /* + * Store the Beacon/ProbeRsp. This is sent to + * csr/hdd in join cnf response. + */ + cdf_mem_copy(session->beacon, + WMA_GET_RX_MPDU_DATA(rx_pkt_info), + session->bcnLen); + } + lim_check_and_announce_join_success(mac_ctx, bcn_ptr, + mac_hdr, session); + } + cdf_mem_free(bcn_ptr); + return; +} + +/**--------------------------------------------------------------- + \fn lim_process_beacon_frame_no_session + \brief This function is called by limProcessMessageQueue() + \ upon Beacon reception. + \ + \param pMac + \param *pRxPacketInfo - A pointer to Rx packet info structure + \return None + ------------------------------------------------------------------*/ +void +lim_process_beacon_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo) +{ + tpSirMacMgmtHdr pHdr; + tSchBeaconStruct *pBeacon; + + pMac->lim.gLimNumBeaconsRcvd++; + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + + lim_log(pMac, LOG2, FL("Received Beacon frame with length=%d from "), + WMA_GET_RX_MPDU_LEN(pRxPacketInfo)); + lim_print_mac_addr(pMac, pHdr->sa, LOG2); + + + /** + * 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 = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeacon) { + lim_log(pMac, LOGE, + FL + ("Unable to allocate memory in lim_process_beacon_frame_no_session")); + return; + } + + if (sir_convert_beacon_frame2_struct + (pMac, (uint8_t *) pRxPacketInfo, + pBeacon) != eSIR_SUCCESS) { + /* Received wrongly formatted/invalid Beacon. Ignore and move on. */ + lim_log(pMac, LOGW, + FL + ("Received invalid Beacon in global MLM state %X"), + pMac->lim.gLimMlmState); + lim_print_mlm_state(pMac, LOGW, pMac->lim.gLimMlmState); + cdf_mem_free(pBeacon); + return; + } + + if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || + (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) { + lim_check_and_add_bss_description(pMac, pBeacon, + pRxPacketInfo, true, + false); + /* Calling dfsChannelList which will convert DFS channel + * to Active channel for x secs if this channel is DFS channel */ + lim_set_dfs_channel_list(pMac, pBeacon->channelNumber, + &pMac->lim.dfschannelList); + } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { + } /* end of eLIM_MLM_LEARN_STATE) */ + cdf_mem_free(pBeacon); + } /* end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) */ + else { + lim_log(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d"), + pMac->lim.gLimMlmState); + lim_print_mlm_state(pMac, LOG1, pMac->lim.gLimMlmState); +#ifdef WLAN_DEBUG + pMac->lim.gLimUnexpBcnCnt++; +#endif + } + + return; +} /*** end lim_process_beacon_frame_no_session() ***/ diff --git a/core/mac/src/pe/lim/lim_process_cfg_updates.c b/core/mac/src/pe/lim/lim_process_cfg_updates.c new file mode 100644 index 000000000000..e1a645e1ac8c --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_cfg_updates.c @@ -0,0 +1,648 @@ +/* + * 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 lim_process_cfg_updates.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 "ani_global.h" + +#include "wni_cfg.h" +#include "sir_mac_prot_def.h" +#include "cfg_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_prop_exts_utils.h" +#include "sch_api.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +static void lim_update_config(tpAniSirGlobal pMac, tpPESession psessionEntry); + +static void lim_set_default_key_id_and_keys(tpAniSirGlobal pMac) +{ +#ifdef FIXME_GEN6 + uint32_t val; + uint32_t dkCfgId; + PELOG1(lim_log(pMac, LOG1, FL("Setting default keys at SP"));) + if (wlan_cfg_get_int(pMac, WNI_CFG_WEP_DEFAULT_KEYID, + &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to retrieve defaultKeyId from CFG")); + } + dkCfgId = limGetCfgIdOfDefaultKeyid(val); +#endif + +} /*** end lim_set_default_key_id_and_keys() ***/ +/** ------------------------------------------------------------- + \fn lim_set_cfg_protection + \brief sets lim global cfg cache from the config. + \param tpAniSirGlobal pMac + \return None + -------------------------------------------------------------*/ +void lim_set_cfg_protection(tpAniSirGlobal pMac, tpPESession pesessionEntry) +{ + uint32_t val = 0; + + if (pesessionEntry != NULL && LIM_IS_AP_ROLE(pesessionEntry)) { + if (pesessionEntry->gLimProtectionControl == + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + cdf_mem_set((void *)&pesessionEntry->cfgProtection, + sizeof(tCfgProtection), 0); + else { + lim_log(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_cfg_get_int(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, &val) + != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed")); + return; + } else + pMac->lim.gLimProtectionControl = (uint8_t) val; + + if (wlan_cfg_get_int(pMac, WNI_CFG_PROTECTION_ENABLED, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("reading protection cfg failed")); + return; + } + + if (pMac->lim.gLimProtectionControl == + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + cdf_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; + + } + } +} + +/** + * lim_handle_param_update() + * + ***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 lim_handle_param_update(tpAniSirGlobal pMac, eUpdateIEsType cfgId) +{ + tSirMsgQ msg = { 0 }; + uint32_t status; + + PELOG3(lim_log + (pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId); + ) + switch (cfgId) { + case eUPDATE_IE_PROBE_BCN: + { + msg.type = SIR_LIM_UPDATE_BEACON; + status = lim_post_msg_api(pMac, &msg); + + if (status != TX_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("Failed lim_post_msg_api %u"), status); + ) + break; + } + default: + break; + } +} + +/** + * lim_handle_cf_gparam_update() + * + ***FUNCTION: + * This function is called by lim_process_messages() 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 lim_handle_cf_gparam_update(tpAniSirGlobal pMac, uint32_t cfgId) +{ + uint32_t val1, val2; + uint16_t val16; + tSirMacHTCapabilityInfo *pHTCapabilityInfo; + tSirMacHTParametersInfo *pAmpduParamInfo; + + PELOG3(lim_log + (pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId); + ) + switch (cfgId) { + case WNI_CFG_WEP_DEFAULT_KEYID: + + /* !!LAC - when the default KeyID is changed, force all of the */ + /* keys and the keyID to be reprogrammed. this allows the */ + /* keys to change after the initial setting of the keys when the CFG was */ + /* applied at association time through CFG changes of the keys. */ + lim_set_default_key_id_and_keys(pMac); + + break; + + case WNI_CFG_EXCLUDE_UNENCRYPTED: + if (wlan_cfg_get_int(pMac, WNI_CFG_EXCLUDE_UNENCRYPTED, + &val1) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to retrieve excludeUnencr from CFG")); + } + lim_log(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 */ + lim_deactivate_and_change_timer(pMac, + eLIM_ASSOC_FAIL_TIMER); + } + + break; + + case WNI_CFG_PROTECTION_ENABLED: + lim_set_cfg_protection(pMac, NULL); + break; + case WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG: + { + tSirMsgQ msg = { 0 }; + uint32_t status; + + msg.type = SIR_LIM_UPDATE_BEACON; + + status = lim_post_msg_api(pMac, &msg); + + if (status != TX_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("Failed lim_post_msg_api %u"), status); + ) + break; + } + case WNI_CFG_GREENFIELD_CAPABILITY: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT Cap Info CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_GREENFIELD_CAPABILITY, &val2) + != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve GreenField CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->greenField = (uint16_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT Cap Info CFG")); + ) + break; + + case WNI_CFG_HT_RX_STBC: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve WNI_CFG_HT_CAP_INFO ")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_RX_STBC, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve WNI_CFG_HT_RX_STBC")); + ) + break; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->rxSTBC = (uint16_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT Cap Info CFG")); + ) + break; + + case WNI_CFG_MAX_AMSDU_LENGTH: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT Cap Info CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_AMSDU_LENGTH, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve Max AMSDU Length CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->maximalAMSDUsize = (uint16_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT Cap Info CFG")); + ) + break; + + case WNI_CFG_SHORT_GI_20MHZ: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT Cap CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve shortGI 20Mhz CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->shortGI20MHz = (uint16_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT Cap Info CFG")); + ) + break; + case WNI_CFG_SHORT_GI_40MHZ: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT Cap CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve shortGI 40Mhz CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16; + pHTCapabilityInfo->shortGI40MHz = (uint16_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_CAP_INFO, + *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT Cap Info CFG")); + ) + break; + case WNI_CFG_MPDU_DENSITY: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT AMPDU Param CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_MPDU_DENSITY, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve MPDU Density CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16; + pAmpduParamInfo->mpduDensity = (uint8_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_AMPDU_PARAMS, + *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT AMPDU Param CFG")); + ) + + break; + case WNI_CFG_MAX_RX_AMPDU_FACTOR: + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve HT AMPDU Param CFG")); + ) + break; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve AMPDU Factor CFG")); + ) + break; + } + val16 = (uint16_t) val1; + pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16; + pAmpduParamInfo->maxRxAMPDUFactor = (uint8_t) val2; + if (cfg_set_int + (pMac, WNI_CFG_HT_AMPDU_PARAMS, + *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, + FL("could not update HT AMPDU Param CFG")); + ) + break; + + case WNI_CFG_DOT11_MODE: + if (wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &val1) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve Dot11 Mode CFG")); + ) + break; + } + break; + + case WNI_CFG_SCAN_IN_POWERSAVE: + if (wlan_cfg_get_int(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val1) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("Unable to get WNI_CFG_SCAN_IN_POWERSAVE ")); + break; + } + pMac->lim.gScanInPowersave = (uint8_t) val1; + break; + + case WNI_CFG_ASSOC_STA_LIMIT: + if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val1) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("Unable to get WNI_CFG_ASSOC_STA_LIMIT")); + break; + } + pMac->lim.gLimAssocStaLimit = (uint16_t) val1; + break; + default: + break; + } +} /*** end lim_handle_cf_gparam_update() ***/ + +/** + * lim_apply_configuration() + * + ***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 lim_apply_configuration(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t val = 0, phyMode; + + PELOG2(lim_log(pMac, LOG2, FL("Applying config"));) + + psessionEntry->limSentCapsChangeNtf = false; + + lim_get_phy_mode(pMac, &phyMode, psessionEntry); + + /* Set default keyId and keys */ + lim_set_default_key_id_and_keys(pMac); + + lim_update_config(pMac, psessionEntry); + + lim_get_short_slot_from_phy_mode(pMac, psessionEntry, phyMode, + &psessionEntry->shortSlotTimeSupported); + + lim_set_cfg_protection(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(lim_log + (pMac, LOG1, + FL("Initializing BT-AMP beacon generation")); + ) + sch_set_beacon_interval(pMac, psessionEntry); + sch_set_fixed_beacon_fields(pMac, psessionEntry); + } + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE")); + return; + } + + PELOG1(lim_log(pMac, LOG1, FL("pMac->lim.gScanInPowersave = %hu"), + pMac->lim.gScanInPowersave); + ) + pMac->lim.gScanInPowersave = (uint8_t) val; + +} /*** end lim_apply_configuration() ***/ + +/** + * lim_update_config + * + * FUNCTION: + * Update the local state from CFG database + * (This used to be dphUpdateConfig) + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +static void lim_update_config(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t val; + + sir_copy_mac_addr(pMac->lim.gLimMyMacAddr, psessionEntry->selfMacAddr); + + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) + lim_log(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_cfg_get_int(pMac, WNI_CFG_WME_ENABLED, &val) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("cfg get wme enabled failed")); + psessionEntry->limWmeEnabled = (val) ? 1 : 0; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_WSM_ENABLED, &val) != eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("cfg get wsm enabled failed")); + psessionEntry->limWsmEnabled = (val) ? 1 : 0; + + if ((!psessionEntry->limWmeEnabled) && (psessionEntry->limWsmEnabled)) { + PELOGE(lim_log(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_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("cfg get qos enabled failed")); + psessionEntry->limQosEnabled = (val) ? 1 : 0; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_HCF_ENABLED, &val) != eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("cfg get hcf enabled failed")); + psessionEntry->limHcfEnabled = (val) ? 1 : 0; + + /* 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_cfg_get_int(pMac, WNI_CFG_11D_ENABLED, &val) != eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("cfg get 11d enabled failed")); + psessionEntry->lim11dEnabled = (val) ? 1 : 0; + + if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("cfg get assoc sta limit failed")); + } + pMac->lim.gLimAssocStaLimit = (uint16_t) val; + +#if defined WLAN_FEATURE_VOWIFI + rrm_update_config(pMac, psessionEntry); +#endif + PELOG1(lim_log(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));) +} diff --git a/core/mac/src/pe/lim/lim_process_deauth_frame.c b/core/mac/src/pe/lim/lim_process_deauth_frame.c new file mode 100644 index 000000000000..e64058d28342 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_deauth_frame.c @@ -0,0 +1,596 @@ +/* + * 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 lim_process_deauth_frame.cc contains the code + * for processing Deauthentication Frame. + * Author: Chandra Modumudi + * Date: 03/24/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "cds_api.h" +#include "ani_global.h" + +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "sch_api.h" +#include "lim_send_messages.h" + +/** + * lim_process_deauth_frame + * + ***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 +lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + uint8_t *pBody; + uint16_t aid, reasonCode; + tpSirMacMgmtHdr pHdr; + tLimMlmAssocCnf mlmAssocCnf; + tLimMlmDeauthInd mlmDeauthInd; + tpDphHashNode pStaDs; + tpPESession pRoamSessionEntry = NULL; + uint8_t roamSessionId; +#ifdef WLAN_FEATURE_11W + uint32_t frameLen; +#endif + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + + pBody = WMA_GET_RX_MPDU_DATA(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(lim_log(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 (lim_is_group_addr(pHdr->sa)) { + /* Received Deauth frame from a BC/MC address */ + /* Log error and ignore it */ + PELOGE(lim_log(pMac, LOGE, + FL("received Deauth frame from a BC/MC address")); + ) + + return; + } + + if (lim_is_group_addr(pHdr->da) && !lim_is_addr_bc(pHdr->da)) { + /* Received Deauth frame for a MC address */ + /* Log error and ignore it */ + PELOGE(lim_log(pMac, LOGE, + FL("received Deauth frame for a MC address")); + ) + + return; + } + if (!lim_validate_received_frame_a1_addr(pMac, + pHdr->da, psessionEntry)) { + lim_log(pMac, LOGE, + FL("rx frame doesn't have valid a1 address, drop it")); + return; + } +#ifdef WLAN_FEATURE_11W + /* PMF: If this session is a PMF session, then ensure that this frame was protected */ + if (psessionEntry->limRmfEnabled + && (WMA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & + DPU_FEEDBACK_UNPROTECTED_ERROR)) { + PELOGE(lim_log + (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 = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + /* send the unprotected frame indication to SME */ + lim_send_sme_unprotected_mgmt_frame_ind(pMac, pHdr->fc.subType, + (uint8_t *) pHdr, + (frameLen + + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, + psessionEntry); + return; + } +#endif + + /* Get reasonCode from Deauthentication frame body */ + reasonCode = sir_read_u16(pBody); + + PELOGE(lim_log(pMac, LOGE, + FL("Received Deauth frame for Addr: " MAC_ADDRESS_STR + " (mlm state = %s," + " sme state = %d systemrole = %d) with reason code %d [%s] from " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->da), + lim_mlm_state_str(psessionEntry->limMlmState), + psessionEntry->limSmeState, + GET_LIM_SYSTEM_ROLE(psessionEntry), + reasonCode, lim_dot11_reason_str(reasonCode), + MAC_ADDR_ARRAY(pHdr->sa)); + ) + + if (lim_check_disassoc_deauth_ack_pending(pMac, (uint8_t *) pHdr->sa)) { + PELOGE(lim_log(pMac, LOGE, + FL + ("Ignore the Deauth received, while waiting for ack of " + "disassoc/deauth")); + ) + lim_clean_up_disassoc_deauth_req(pMac, (uint8_t *) 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(lim_log(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(lim_log(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 */ + lim_log(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 = + pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId, + &roamSessionId); + } + if (lim_is_reassoc_in_progress(pMac, psessionEntry) + || lim_is_reassoc_in_progress(pMac, pRoamSessionEntry)) { + if (!IS_REASSOC_BSSID(pMac, pHdr->sa, psessionEntry)) { + PELOGE(lim_log + (pMac, LOGE, + FL("Rcv Deauth from unknown/different " + "AP while ReAssoc. Ignore " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + ) + PELOGE(lim_log + (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(lim_log + (pMac, LOGE, + FL("received DeAuth from the New AP to " + "which ReAssoc is sent " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->sa)); + ) + PELOGE(lim_log + (pMac, LOGE, + FL(" psessionEntry->bssId: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(psessionEntry->bssId)); + ) + lim_restore_pre_reassoc_state(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(lim_log + (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 (lim_search_pre_auth_list(pMac, pHdr->sa)) { + PELOG1(lim_log + (pMac, LOG1, + FL("Preauth entry exist. " + "Deleting... ")); + ) + lim_delete_pre_auth_node(pMac, pHdr->sa); + } + return; + } + } + + pStaDs = + dph_lookup_hash_entry(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(lim_log(pMac, LOG1, + FL + ("received Deauth frame state %X with failure " + "code %d from " MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + + lim_restore_from_auth_state(pMac, + eSIR_SME_DEAUTH_WHILE_JOIN, + reasonCode, psessionEntry); + + return; + + case eLIM_MLM_AUTHENTICATED_STATE: + lim_log(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. */ + cdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr, + pHdr->sa, sizeof(tSirMacAddr)); + mlmDeauthInd.reasonCode = reasonCode; + + psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + psessionEntry->limMlmState)); + + lim_post_sme_message(pMac, + LIM_MLM_DEAUTH_IND, + (uint32_t *) &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. + */ + lim_log(pMac, LOG1, + FL("received Deauth frame state %X with " + "reasonCode=%d from " MAC_ADDRESS_STR), + psessionEntry->limMlmState, reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + if (lim_search_pre_auth_list(pMac, pHdr->sa)) + lim_delete_pre_auth_node(pMac, pHdr->sa); + + if (psessionEntry->pLimMlmJoinReq) { + cdf_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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + psessionEntry->limMlmState)); + + /* Deactive Association response timeout */ + lim_deactivate_and_change_timer(pMac, + eLIM_ASSOC_FAIL_TIMER); + + lim_post_sme_message(pMac, + LIM_MLM_ASSOC_CNF, + (uint32_t *) &mlmAssocCnf); + + return; + + case eLIM_MLM_WT_ADD_STA_RSP_STATE: + psessionEntry->fDeauthReceived = true; + PELOGW(lim_log(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(lim_log + (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)); + ) + lim_send_sme_tdls_del_sta_ind(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)) + lim_delete_tdls_peers(pMac, psessionEntry); +#endif + /** + * This could be Deauthentication frame from + * a BSS with which pre-authentication was + * performed. Delete Pre-auth entry if found. + */ + if (lim_search_pre_auth_list(pMac, pHdr->sa)) + lim_delete_pre_auth_node(pMac, pHdr->sa); +#ifdef FEATURE_WLAN_TDLS + } +#endif + break; + + case eLIM_MLM_WT_REASSOC_RSP_STATE: + lim_log(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(lim_log(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(lim_log(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) { + lim_log(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(lim_log(pMac, LOGE, + FL + ("received Deauth frame from peer that is in state %X, addr " + MAC_ADDRESS_STR), pStaDs->mlmStaContext.mlmState, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + return; + } + pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode; + pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH; + + /* / Issue Deauth Indication to SME. */ + cdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr, + pStaDs->staAddr, sizeof(tSirMacAddr)); + mlmDeauthInd.reasonCode = + (uint8_t) 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 (lim_is_reassoc_in_progress(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 (lim_search_pre_auth_list(pMac, pHdr->sa)) + lim_delete_pre_auth_node(pMac, pHdr->sa); + + if (psessionEntry->limAssocResponseData) { + cdf_mem_free(psessionEntry->limAssocResponseData); + psessionEntry->limAssocResponseData = NULL; + } + + PELOGE(lim_log(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". + */ + lim_post_reassoc_failure(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)) + wma_tx_abort(psessionEntry->smeSessionId); + + /* / Deauthentication from peer MAC entity */ + lim_post_sme_message(pMac, LIM_MLM_DEAUTH_IND, + (uint32_t *) &mlmDeauthInd); + + /* send eWNI_SME_DEAUTH_IND to SME */ + lim_send_sme_deauth_ind(pMac, pStaDs, psessionEntry); + return; + +} /*** end lim_process_deauth_frame() ***/ diff --git a/core/mac/src/pe/lim/lim_process_disassoc_frame.c b/core/mac/src/pe/lim/lim_process_disassoc_frame.c new file mode 100644 index 000000000000..33a1c089d232 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_disassoc_frame.c @@ -0,0 +1,390 @@ +/* + * 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 lim_process_disassoc_frame.cc contains the code + * for processing Disassocation Frame. + * Author: Chandra Modumudi + * Date: 03/24/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ +#include "cds_api.h" +#include "wni_api.h" +#include "sir_api.h" +#include "ani_global.h" +#include "wni_cfg.h" + +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_send_messages.h" +#include "sch_api.h" + +/** + * lim_process_disassoc_frame + * + ***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 +lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, + tpPESession psessionEntry) +{ + uint8_t *pBody; + uint16_t aid, reasonCode; + tpSirMacMgmtHdr pHdr; + tpDphHashNode pStaDs; + tLimMlmDisassocInd mlmDisassocInd; +#ifdef WLAN_FEATURE_11W + uint32_t frameLen; +#endif + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (lim_is_group_addr(pHdr->sa)) { + /* Received Disassoc frame from a BC/MC address */ + /* Log error and ignore it */ + PELOGE(lim_log(pMac, LOGE, + FL + ("received Disassoc frame from a BC/MC address")); + ) + + return; + } + + if (lim_is_group_addr(pHdr->da) && !lim_is_addr_bc(pHdr->da)) { + /* Received Disassoc frame for a MC address */ + /* Log error and ignore it */ + PELOGE(lim_log(pMac, LOGE, + FL("received Disassoc frame for a MC address")); + ) + + return; + } + if (!lim_validate_received_frame_a1_addr(pMac, + pHdr->da, psessionEntry)) { + lim_log(pMac, LOGE, + FL("rx frame doesn't have valid a1 address, drop 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 + */ + lim_log(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 + && (WMA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & + DPU_FEEDBACK_UNPROTECTED_ERROR)) { + PELOGE(lim_log + (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 = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + /* send the unprotected frame indication to SME */ + lim_send_sme_unprotected_mgmt_frame_ind(pMac, pHdr->fc.subType, + (uint8_t *) pHdr, + (frameLen + + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, + psessionEntry); + return; + } +#endif + + /* Get reasonCode from Disassociation frame body */ + reasonCode = sir_read_u16(pBody); + + PELOG2(lim_log(pMac, LOGE, + FL("Received Disassoc frame for Addr: " MAC_ADDRESS_STR + "(mlm state=%s, sme state=%d)," + "with reason code %d [%s] from " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pHdr->da), + lim_mlm_state_str(psessionEntry->limMlmState), + psessionEntry->limSmeState, reasonCode, + lim_dot11_reason_str(reasonCode), MAC_ADDR_ARRAY(pHdr->sa)); + ) + + /** + * Extract 'associated' context for STA, if any. + * This is maintained by DPH and created by LIM. + */ + pStaDs = + dph_lookup_hash_entry(pMac, pHdr->sa, &aid, + &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) { + /** + * Disassociating STA is not associated. + * Log error. + */ + PELOGE(lim_log(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 (lim_check_disassoc_deauth_ack_pending(pMac, (uint8_t *) pHdr->sa)) { + PELOGE(lim_log(pMac, LOGE, + FL("Ignore the DisAssoc received, while waiting " + "for ack of disassoc/deauth")); + ) + lim_clean_up_disassoc_deauth_req(pMac, (uint8_t *) pHdr->sa, 1); + return; + } + + /** If we are in the Wait for ReAssoc Rsp state */ + if (lim_is_reassoc_in_progress(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(lim_log + (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(lim_log + (pMac, LOGW, + FL + ("received Disassoc from the New AP to which ReAssoc is sent ")); + ) + lim_restore_pre_reassoc_state(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(lim_log(pMac, LOGE, + FL + ("received Disassoc frame with invalid reasonCode " + "%d from " MAC_ADDRESS_STR), reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + break; + } + } else if ((LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && + ((psessionEntry->limSmeState != eLIM_SME_WT_JOIN_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_AUTH_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE) && + (psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE))) { + switch (reasonCode) { + case eSIR_MAC_UNSPEC_FAILURE_REASON: + case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON: + case eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON: + case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON: + case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON: + case eSIR_MAC_MIC_FAILURE_REASON: + case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON: + case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON: + case eSIR_MAC_RSN_IE_MISMATCH_REASON: + case eSIR_MAC_1X_AUTH_FAILURE_REASON: + case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: + /* Valid reasonCode in received Disassociation frame */ + break; + + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: + case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON: + /* Valid reasonCode in received Disassociation frame */ + /* as long as we're not about to channel switch */ + if (psessionEntry->gLimChannelSwitch.state != + eLIM_CHANNEL_SWITCH_IDLE) { + lim_log(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(lim_log(pMac, LOGE, + FL + ("received Disassoc frame with invalid reasonCode " + "%d from " MAC_ADDRESS_STR), reasonCode, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + return; + } + } else { + /* Received Disassociation frame in either IBSS */ + /* or un-known role. Log and ignore it */ + lim_log(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(lim_log(pMac, LOGE, + FL("received Disassoc frame in state %d from " + MAC_ADDRESS_STR), + pStaDs->mlmStaContext.mlmState, + MAC_ADDR_ARRAY(pHdr->sa)); + ) + + 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(lim_log(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. */ + cdf_mem_copy((uint8_t *) &mlmDisassocInd.peerMacAddr, + (uint8_t *) pStaDs->staAddr, sizeof(tSirMacAddr)); + mlmDisassocInd.reasonCode = + (uint8_t) pStaDs->mlmStaContext.disassocReason; + mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC; + + /* Update PE session Id */ + mlmDisassocInd.sessionId = psessionEntry->peSessionId; + + if (lim_is_reassoc_in_progress(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(lim_log + (pMac, LOGE, + FL("received Disassoc from AP while waiting " + "for Reassoc Rsp")); + ) + + if (psessionEntry->limAssocResponseData) { + cdf_mem_free(psessionEntry->limAssocResponseData); + psessionEntry->limAssocResponseData = NULL; + } + + lim_restore_pre_reassoc_state(pMac, eSIR_SME_REASSOC_REFUSED, + reasonCode, psessionEntry); + return; + } + + lim_post_sme_message(pMac, LIM_MLM_DISASSOC_IND, + (uint32_t *) &mlmDisassocInd); + + /* send eWNI_SME_DISASSOC_IND to SME */ + lim_send_sme_disassoc_ind(pMac, pStaDs, psessionEntry); + + return; +} /*** end lim_process_disassoc_frame() ***/ diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c new file mode 100644 index 000000000000..25e7ed1a5c06 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -0,0 +1,2098 @@ +/* + * 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 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 "cds_api.h" +#include "wni_api.h" +#include "wma_types.h" + +#include "wni_cfg.h" +#include "cfg_api.h" +#include "sir_common.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" + +#include "lim_admit_control.h" +#include "lim_ibss_peer_mgmt.h" +#include "sch_api.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_send_messages.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +#include "lim_ft.h" +#endif + +#include "cdf_types.h" +#include "cds_packet.h" +#include "cdf_memory.h" + +void lim_log_session_states(tpAniSirGlobal pMac); +static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, + struct sSirMsgQ *msg, uint8_t rsp_reqd); + +/** + * lim_process_dual_mac_cfg_resp() - Process set dual mac config response + * @mac: Global MAC pointer + * @body: Set dual mac config response in sir_dual_mac_config_resp format + * + * Process the set dual mac config response and post the message + * to SME to process this further and release the active + * command list + * + * Return: None + */ +static void lim_process_dual_mac_cfg_resp(tpAniSirGlobal mac, void *body) +{ + struct sir_dual_mac_config_resp *resp, *param; + uint32_t len, fail_resp = 0; + tSirMsgQ msg; + + resp = (struct sir_dual_mac_config_resp *)body; + if (!resp) { + lim_log(mac, LOGE, FL("Set dual mac cfg param is NULL")); + fail_resp = 1; + /* Not returning here. If possible, let us proceed + * and send fail response to SME + */ + } + + len = sizeof(*param); + + param = cdf_mem_malloc(len); + if (!param) { + lim_log(mac, LOGE, FL("Fail to allocate memory")); + /* Memory allocation for param failed. + * Cannot send fail status back to SME + */ + return; + } + + if (fail_resp) { + lim_log(mac, LOGE, FL("Send fail status to SME")); + param->status = SET_HW_MODE_STATUS_ECANCELED; + } else { + param->status = resp->status; + /* + * TODO: Update this HW mode info in any UMAC params, if needed + */ + } + + msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP; + msg.bodyptr = param; + msg.bodyval = 0; + lim_log(mac, LOG1, FL("Send eWNI_SME_SET_DUAL_MAC_CFG_RESP to SME")); + lim_sys_process_mmh_msg_api(mac, &msg, ePROT); + return; +} + +/** + * lim_process_set_hw_mode_resp() - Process set HW mode response + * @mac: Global MAC pointer + * @body: Set HW mode response in sir_set_hw_mode_resp format + * + * Process the set HW mode response and post the message + * to SME to process this further and release the active + * command list + * + * Return: None + */ +static void lim_process_set_hw_mode_resp(tpAniSirGlobal mac, void *body) +{ + struct sir_set_hw_mode_resp *resp, *param; + uint32_t len, i, fail_resp = 0; + tSirMsgQ msg; + + resp = (struct sir_set_hw_mode_resp *)body; + if (!resp) { + lim_log(mac, LOGE, FL("Set HW mode param is NULL")); + fail_resp = 1; + /* Not returning here. If possible, let us proceed + * and send fail response to SME */ + } + + len = sizeof(*param); + + param = cdf_mem_malloc(len); + if (!param) { + lim_log(mac, LOGE, FL("Fail to allocate memory")); + /* Memory allocation for param failed. + * Cannot send fail status back to SME + */ + return; + } + + if (fail_resp) { + lim_log(mac, LOGE, FL("Send fail status to SME")); + param->status = SET_HW_MODE_STATUS_ECANCELED; + param->cfgd_hw_mode_index = 0; + param->num_vdev_mac_entries = 0; + } else { + param->status = resp->status; + param->cfgd_hw_mode_index = resp->cfgd_hw_mode_index; + param->num_vdev_mac_entries = resp->num_vdev_mac_entries; + + for (i = 0; i < resp->num_vdev_mac_entries; i++) { + param->vdev_mac_map[i].vdev_id = + resp->vdev_mac_map[i].vdev_id; + param->vdev_mac_map[i].mac_id = + resp->vdev_mac_map[i].mac_id; + } + /* + * TODO: Update this HW mode info in any UMAC params, if needed + */ + } + + msg.type = eWNI_SME_SET_HW_MODE_RESP; + msg.bodyptr = param; + msg.bodyval = 0; + lim_log(mac, LOGE, FL("Send eWNI_SME_SET_HW_MODE_RESP to SME")); + lim_sys_process_mmh_msg_api(mac, &msg, ePROT); + return; +} + +/** + * lim_process_hw_mode_trans_ind() - Process set HW mode transition indication + * @mac: Global MAC pointer + * @body: Set HW mode response in sir_hw_mode_trans_ind format + * + * Process the set HW mode transition indication and post the message + * to SME to invoke the HDD callback + * command list + * + * Return: None + */ +static void lim_process_hw_mode_trans_ind(tpAniSirGlobal mac, void *body) +{ + struct sir_hw_mode_trans_ind *ind, *param; + uint32_t len, i; + tSirMsgQ msg; + + ind = (struct sir_hw_mode_trans_ind *)body; + if (!ind) { + lim_log(mac, LOGE, FL("Set HW mode trans ind param is NULL")); + return; + } + + len = sizeof(*param); + + param = cdf_mem_malloc(len); + if (!param) { + lim_log(mac, LOGE, FL("Fail to allocate memory")); + return; + } + + param->old_hw_mode_index = ind->old_hw_mode_index; + param->new_hw_mode_index = ind->new_hw_mode_index; + param->num_vdev_mac_entries = ind->num_vdev_mac_entries; + + for (i = 0; i < ind->num_vdev_mac_entries; i++) { + param->vdev_mac_map[i].vdev_id = + ind->vdev_mac_map[i].vdev_id; + param->vdev_mac_map[i].mac_id = + ind->vdev_mac_map[i].mac_id; + } + + /* TODO: Update this HW mode info in any UMAC params, if needed */ + + msg.type = eWNI_SME_HW_MODE_TRANS_IND; + msg.bodyptr = param; + msg.bodyval = 0; + lim_log(mac, LOGE, FL("Send eWNI_SME_HW_MODE_TRANS_IND to SME")); + lim_sys_process_mmh_msg_api(mac, &msg, ePROT); + return; +} + +/** ------------------------------------------------------------- + \fn def_msg_decision + \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 + -------------------------------------------------------------*/ + +uint8_t static def_msg_decision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + +/* this function should not changed */ + if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) { + /* Defer processsing this message */ + if (lim_defer_msg(pMac, limMsg) != TX_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_PE, LOGE, + FL("Unable to Defer Msg")); + lim_log_session_states(pMac); + lim_handle_defer_msg_error(pMac, limMsg); + } + return true; + } + /* When defer is requested then defer all the messages except HAL responses. */ + if ((!lim_is_system_in_scan_state(pMac)) + && (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) + && !pMac->lim.gLimSystemInScanLearnMode) { + if ((limMsg->type != WMA_ADD_BSS_RSP) + && (limMsg->type != WMA_DELETE_BSS_RSP) + && (limMsg->type != WMA_ADD_STA_RSP) + && (limMsg->type != WMA_DELETE_STA_RSP) + && (limMsg->type != WMA_SET_BSSKEY_RSP) + && (limMsg->type != WMA_SET_STAKEY_RSP) + && (limMsg->type != WMA_SET_STA_BCASTKEY_RSP) + && (limMsg->type != WMA_AGGR_QOS_RSP) + && (limMsg->type != WMA_SET_MIMOPS_RSP) + && (limMsg->type != WMA_SWITCH_CHANNEL_RSP) + && (limMsg->type != WMA_P2P_NOA_ATTR_IND) + && (limMsg->type != WMA_P2P_NOA_START_IND) && +#ifdef FEATURE_OEM_DATA_SUPPORT + (limMsg->type != WMA_START_OEM_DATA_RSP) && +#endif + (limMsg->type != WMA_ADD_TS_RSP)) { + PELOG1(lim_log + (pMac, LOG1, + FL + ("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode"), + lim_msg_str(limMsg->type)); + ) + /* Defer processsing this message */ + if (lim_defer_msg(pMac, limMsg) != TX_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_PE, LOGE, + FL("Unable to Defer Msg")); + lim_log_session_states(pMac); + lim_handle_defer_msg_error(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 = cdf_mem_malloc(len); + if (NULL == result) { + lim_log(pmac, LOGE, FL("Memory allocation failed")); + return; + } + hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + cdf_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 = cdf_mc_timer_get_system_time(); + result->ap[i].beaconPeriod = frame->beaconInterval; + result->ap[i].capability = + lim_get_u16((uint8_t *) &frame->capabilityInfo); + result->ap[i].channel = WMA_GET_RX_CH(rx_pkt_info); + result->ap[i].rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + result->ap[i].rtt = 0; + result->ap[i].rtt_sd = 0; + result->ap[i].ieLength = ie_len; + cdf_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'; + cdf_mem_copy((uint8_t *) &result->ap[i].bssid, + (uint8_t *) hdr->bssId, + sizeof(tSirMacAddr)); + /* Copy IE fields */ + cdf_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; + lim_sys_process_mmh_msg_api(pmac, &mmh_msg, ePROT); +} + + +static void +__lim_ext_scan_forward_bcn_probe_rsp(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 = cdf_mem_malloc(sizeof(*result) + ie_len); + if (NULL == result) { + lim_log(pmac, LOGE, FL("Memory allocation failed")); + return; + } + hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + cdf_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 = cdf_mc_timer_get_system_time(); + result->ap.beaconPeriod = frame->beaconInterval; + result->ap.capability = + lim_get_u16((uint8_t *) &frame->capabilityInfo); + result->ap.channel = WMA_GET_RX_CH(rx_pkt_info); + result->ap.rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + result->ap.rtt = 0; + result->ap.rtt_sd = 0; + result->ap.ieLength = ie_len; + + cdf_mem_copy((uint8_t *) &result->ap.ssid[0], + (uint8_t *) frame->ssId.ssId, frame->ssId.length); + result->ap.ssid[frame->ssId.length] = '\0'; + cdf_mem_copy((uint8_t *) &result->ap.bssid.bytes, + (uint8_t *) hdr->bssId, + CDF_MAC_ADDR_SIZE); + /* Copy IE fields */ + cdf_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; + lim_sys_process_mmh_msg_api(pmac, &mmh_msg, ePROT); +} + +static void +__lim_process_ext_scan_beacon_probe_rsp(tpAniSirGlobal pmac, + uint8_t *rx_pkt_info, + uint8_t sub_type) +{ + tSirProbeRespBeacon *frame; + uint8_t *body; + uint32_t frm_len; + tSirRetStatus status; + + frm_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + if (frm_len <= SIR_MAC_B_PR_SSID_OFFSET) { + lim_log(pmac, LOGP, + FL("RX packet has invalid length %d"), frm_len); + return; + } + + frame = cdf_mem_malloc(sizeof(*frame)); + if (NULL == frame) { + lim_log(pmac, LOGE, FL("Memory allocation failed")); + return; + } + + if (sub_type == SIR_MAC_MGMT_BEACON) { + lim_log(pmac, LOG2, FL("Beacon due to ExtScan/epno")); + status = sir_convert_beacon_frame2_struct(pmac, + (uint8_t *)rx_pkt_info, + frame); + } else if (sub_type == SIR_MAC_MGMT_PROBE_RSP) { + lim_log(pmac, LOG2, FL("Probe Rsp due to ExtScan/epno")); + body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + status = sir_convert_probe_frame2_struct(pmac, body, + frm_len, frame); + } else { + cdf_mem_free(frame); + return; + } + + if (status != eSIR_SUCCESS) { + lim_log(pmac, LOGE, FL("Frame parsing failed")); + cdf_mem_free(frame); + return; + } + + if (WMA_IS_EXTSCAN_SCAN_SRC(rx_pkt_info)) + __lim_ext_scan_forward_bcn_probe_rsp(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); + + cdf_mem_free(frame); +} +#endif + +/* + * Beacon Handling Cases: + * during scanning, when no session is active: + * handled by lim_handle_frames_in_scan_state before __lim_handle_beacon 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 lim_handle_frames_in_scan_state before __lim_handle_beacon 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 lim_handle_frames_in_scan_state before __lim_handle_beacon call is invoked. + * Not scanning, no session: + * there should not be any beacon coming, if coming, should be dropped. + * Not Scanning, + */ +static void +__lim_handle_beacon(tpAniSirGlobal pMac, tpSirMsgQ pMsg, + tpPESession psessionEntry) +{ + /* checking for global SME state... */ + uint8_t *pRxPacketInfo; + lim_get_b_dfrom_rx_packet(pMac, pMsg->bodyptr, + (uint32_t * *) &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) { + sch_beacon_process(pMac, pRxPacketInfo, NULL); + } else if ((psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE) || + (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE)) { + sch_beacon_process(pMac, pRxPacketInfo, psessionEntry); + } else + lim_process_beacon_frame(pMac, pRxPacketInfo, psessionEntry); + + return; +} + +/** + * lim_defer_msg() + * + ***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 + */ + +uint32_t lim_defer_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + uint32_t retCode = TX_SUCCESS; + + retCode = lim_write_deferred_msg_q(pMac, pMsg); + + if (retCode == TX_SUCCESS) { + MTRACE(mac_trace_msg_rx + (pMac, NO_SESSION, + LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DEFERRED)); + ) + } else { + lim_log(pMac, LOGE, FL("Dropped lim message (0x%X)"), + pMsg->type); + MTRACE(mac_trace_msg_rx + (pMac, NO_SESSION, + LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DROPPED)); + ) + } + + return retCode; +} /*** end lim_defer_msg() ***/ + +/** + * lim_handle_unknown_a2_index_frames() - This function handles Unknown Unicast + * (A2 Index) packets + * @mac_ctx: Pointer to the Global Mac Context. + * @rx_pkt_buffer: Pointer to the packet Buffer descriptor. + * @session_entry: Pointer to the PE Session Entry. + * + * This routine will handle public action frames. + * + * Return: None. + */ +static void lim_handle_unknown_a2_index_frames(tpAniSirGlobal mac_ctx, + void *rx_pkt_buffer, tpPESession session_entry) +{ +#ifdef FEATURE_WLAN_TDLS + tpSirMacDataHdr3a mac_hdr; +#endif + if (LIM_IS_P2P_DEVICE_ROLE(session_entry)) + lim_process_action_frame_no_session(mac_ctx, + (uint8_t *) rx_pkt_buffer); +#ifdef FEATURE_WLAN_TDLS + mac_hdr = WMA_GET_RX_MPDUHEADER3A(rx_pkt_buffer); + + if (lim_is_group_addr(mac_hdr->addr2)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Ignoring A2 Invalid Packet received for MC/BC:")); + lim_print_mac_addr(mac_ctx, mac_hdr->addr2, LOG2); + return; + } + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("type=0x%x, subtype=0x%x"), + mac_hdr->fc.type, mac_hdr->fc.subType); + /* Currently only following type and subtype are handled. + * If there are more combinations, then add switch-case + * statements. + */ + if (LIM_IS_STA_ROLE(session_entry) && + (mac_hdr->fc.type == SIR_MAC_MGMT_FRAME) && + (mac_hdr->fc.subType == SIR_MAC_MGMT_ACTION)) + lim_process_action_frame(mac_ctx, rx_pkt_buffer, session_entry); +#endif + return; +} + +/** + * lim_check_mgmt_registered_frames() - This function handles registered + * management frames. + * + * @mac_ctx: Pointer to the Global Mac Context. + * @buff_desc: Pointer to the packet Buffer descriptor. + * @session_entry: Pointer to the PE Session Entry. + * + * 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. + * + * Return: True or False for Match or Mismatch respectively. + */ +static bool +lim_check_mgmt_registered_frames(tpAniSirGlobal mac_ctx, uint8_t *buff_desc, + tpPESession session_entry) +{ + tSirMacFrameCtl fc; + tpSirMacMgmtHdr hdr; + uint8_t *body; + struct mgmt_frm_reg_info *mgmt_frame = NULL; + struct mgmt_frm_reg_info *next_frm = NULL; + uint16_t frm_type; + uint16_t frm_len; + uint8_t type, sub_type; + bool match = false; + CDF_STATUS cdf_status; + + hdr = WMA_GET_RX_MAC_HEADER(buff_desc); + fc = hdr->fc; + frm_type = (fc.type << 2) | (fc.subType << 4); + body = WMA_GET_RX_MPDU_DATA(buff_desc); + frm_len = WMA_GET_RX_PAYLOAD_LEN(buff_desc); + + cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); + cdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t **) &mgmt_frame); + cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); + + while (mgmt_frame != NULL) { + type = (mgmt_frame->frameType >> 2) & 0x03; + sub_type = (mgmt_frame->frameType >> 4) & 0x0f; + if ((type == SIR_MAC_MGMT_FRAME) + && (fc.type == SIR_MAC_MGMT_FRAME) + && (sub_type == SIR_MAC_MGMT_RESERVED15)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_HIGH, + FL + ("rcvd frm match for SIR_MAC_MGMT_RESERVED15")); + match = true; + break; + } + if (mgmt_frame->frameType == frm_type) { + if (mgmt_frame->matchLen <= 0) { + match = true; + break; + } + if (mgmt_frame->matchLen <= frm_len && + cdf_mem_compare(mgmt_frame->matchData, body, + mgmt_frame->matchLen)) { + /* found match! */ + match = true; + break; + } + } + + cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); + cdf_status = + cdf_list_peek_next( + &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t *) mgmt_frame, + (cdf_list_node_t **) &next_frm); + cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); + mgmt_frame = next_frm; + next_frm = NULL; + } + + if (match) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("rcvd frame match with registered frame params")); + /* Indicate this to SME */ + lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType, + (uint8_t *) hdr, + WMA_GET_RX_PAYLOAD_LEN(buff_desc) + + sizeof(tSirMacMgmtHdr), mgmt_frame->sessionId, + WMA_GET_RX_CH(buff_desc), session_entry, 0); + + if ((type == SIR_MAC_MGMT_FRAME) + && (fc.type == SIR_MAC_MGMT_FRAME) + && (sub_type == 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 = false; + } + + return match; +} + +/** + * lim_handle80211_frames() + * + ***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 +lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg) +{ + uint8_t *pRxPacketInfo = NULL; + tSirMacFrameCtl fc; + tpSirMacMgmtHdr pHdr = NULL; + tpPESession psessionEntry = NULL; + uint8_t sessionId; + tAniBool isFrmFt = false; + + *pDeferMsg = false; + lim_get_b_dfrom_rx_packet(pMac, limMsg->bodyptr, + (uint32_t * *) &pRxPacketInfo); + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + isFrmFt = WMA_GET_RX_FT_DONE(pRxPacketInfo); + fc = pHdr->fc; + +#ifdef WLAN_DUMP_MGMTFRAMES + lim_log(pMac, LOGE, + FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), + fc.protVer, fc.type, fc.subType, + WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, pHdr, + WMA_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)) { + lim_log(pMac, LOGE, + FL("RX MGMT - Type %hu, SubType %hu, seq num[%d]"), + fc.type, + fc.subType, + ((pHdr->seqControl.seqNumHi << + HIGH_SEQ_NUM_OFFSET) | + pHdr->seqControl.seqNumLo)); + } + } +#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) { + __lim_process_ext_scan_beacon_probe_rsp(pMac, + pRxPacketInfo, + fc.subType); + } else { + lim_log(pMac, LOGE, + FL("Wrong frameType %d, Subtype %d for %d"), + fc.type, fc.subType, + WMA_GET_SCAN_SRC(pRxPacketInfo)); + } + goto end; + } +#endif + if (WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) { + if (fc.subType == SIR_MAC_MGMT_BEACON) { + lim_log(pMac, LOG2, FL("Learning scan beacon")); + __lim_handle_beacon(pMac, limMsg, NULL); + } else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP) { + lim_log(pMac, LOG2, FL("Learning scan probe rsp")); + lim_process_probe_rsp_frame_no_session(pMac, pRxPacketInfo); + } else { + lim_log(pMac, LOGE, + FL("Wrong frame Type %d, Subtype %d for LFR"), + fc.type, fc.subType); + } + goto end; + } + /* Added For BT-AMP Support */ + if ((psessionEntry = + pe_find_session_by_bssid(pMac, pHdr->bssId, + &sessionId)) == NULL) { +#ifdef WLAN_FEATURE_VOWIFI_11R + if (fc.subType == SIR_MAC_MGMT_AUTH) { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOG1, + FL + ("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), + fc.protVer, fc.type, fc.subType, + WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); + lim_print_mac_addr(pMac, pHdr->bssId, LOG1); +#endif + if (lim_process_auth_frame_no_session + (pMac, pRxPacketInfo, + limMsg->bodyptr) == eSIR_SUCCESS) { + lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, + pRxPacketInfo, limMsg->bodyptr); + return; + } + } +#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 = + pe_find_session_by_peer_sta(pMac, pHdr->sa, + &sessionId)) == NULL) { + lim_log(pMac, LOG1, + FL + ("session does not exist for given bssId")); + lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, + pRxPacketInfo, limMsg->bodyptr); + return; + } else + lim_log(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 = + pe_find_session_by_bssid(pMac, pHdr->da, &sessionId); + } + } + + /* Check if frame is registered by HDD */ + if (lim_check_mgmt_registered_frames(pMac, pRxPacketInfo, psessionEntry)) { + lim_log(pMac, LOG1, FL("Received frame is passed to SME")); + lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, + limMsg->bodyptr); + return; + } + + if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { /* Received Frame with non-zero Protocol Version */ + lim_log(pMac, LOGE, + FL("Unexpected frame with protVersion %d received"), + fc.protVer); + lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, + (void *)limMsg->bodyptr); +#ifdef WLAN_DEBUG + pMac->lim.numProtErr++; +#endif + 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)) + lim_process_assoc_req_frame(pMac, + pRxPacketInfo, + LIM_ASSOC, + psessionEntry); + else { + /* Unwanted messages - Log error */ + lim_log(pMac, LOGE, + FL + ("unexpected message received %X"), + limMsg->type); + lim_print_msg_name(pMac, LOGE, + limMsg->type); + } + break; + + case SIR_MAC_MGMT_ASSOC_RSP: + lim_process_assoc_rsp_frame(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)) { + lim_process_assoc_req_frame(pMac, + pRxPacketInfo, + LIM_REASSOC, + psessionEntry); + } else { + /* Unwanted messages - Log error */ + lim_log(pMac, LOGE, + FL + ("unexpected message received %X"), + limMsg->type); + lim_print_msg_name(pMac, LOGE, + limMsg->type); + } + break; + + case SIR_MAC_MGMT_REASSOC_RSP: + lim_process_assoc_rsp_frame(pMac, pRxPacketInfo, + LIM_REASSOC, + psessionEntry); + break; + + case SIR_MAC_MGMT_PROBE_REQ: + lim_process_probe_req_frame_multiple_bss(pMac, + pRxPacketInfo, + psessionEntry); + break; + + case SIR_MAC_MGMT_PROBE_RSP: + if (psessionEntry == NULL) + lim_process_probe_rsp_frame_no_session(pMac, + pRxPacketInfo); + else + lim_process_probe_rsp_frame(pMac, + pRxPacketInfo, + psessionEntry); + break; + + case SIR_MAC_MGMT_BEACON: + __lim_handle_beacon(pMac, limMsg, psessionEntry); + break; + + case SIR_MAC_MGMT_DISASSOC: + lim_process_disassoc_frame(pMac, pRxPacketInfo, + psessionEntry); + break; + + case SIR_MAC_MGMT_AUTH: + lim_process_auth_frame(pMac, pRxPacketInfo, + psessionEntry); + break; + + case SIR_MAC_MGMT_DEAUTH: + lim_process_deauth_frame(pMac, pRxPacketInfo, + psessionEntry); + break; + + case SIR_MAC_MGMT_ACTION: + if (psessionEntry == NULL) + lim_process_action_frame_no_session(pMac, + pRxPacketInfo); + else { + if (WMA_GET_RX_UNKNOWN_UCAST + (pRxPacketInfo)) + lim_handle_unknown_a2_index_frames + (pMac, pRxPacketInfo, + psessionEntry); + else + lim_process_action_frame(pMac, + pRxPacketInfo, + psessionEntry); + } + break; + default: + /* Received Management frame of 'reserved' subtype */ + break; + } /* switch (fc.subType) */ + + } + break; + case SIR_MAC_DATA_FRAME: + { + } + break; + default: + /* Received frame of type 'reserved' */ + break; + + } /* switch (fc.type) */ + +end: + lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, + (void *)limMsg->bodyptr); + return; +} /*** end lim_handle80211_frames() ***/ + +/** + * lim_send_stop_scan_offload_req() + * + ***FUNCTION: + * This function will be called to abort the ongoing offloaded scan + * request. + * + * + ***NOTE: + * + * @param pMac Pointer to Global MAC structure + * @return CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE + */ +CDF_STATUS lim_send_stop_scan_offload_req(tpAniSirGlobal pMac, + uint8_t SessionId, uint32_t scan_id) +{ + tSirMsgQ msg; + tSirRetStatus rc = eSIR_SUCCESS; + tAbortScanParams *pAbortScanParams; + + pAbortScanParams = cdf_mem_malloc(sizeof(tAbortScanParams)); + if (NULL == pAbortScanParams) { + lim_log(pMac, LOGP, + FL("Memory allocation failed for AbortScanParams")); + return CDF_STATUS_E_NOMEM; + } + + pAbortScanParams->SessionId = SessionId; + pAbortScanParams->scan_id = scan_id; + msg.type = WMA_STOP_SCAN_OFFLOAD_REQ; + msg.bodyptr = pAbortScanParams; + msg.bodyval = 0; + + rc = wma_post_ctrl_msg(pMac, &msg); + if (rc != eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure")); + cdf_mem_free(pAbortScanParams); + return CDF_STATUS_E_FAILURE; + } + + lim_log(pMac, LOG1, FL("Abort ongoing offload scan.")); + return CDF_STATUS_SUCCESS; + +} + +/** + * lim_process_abort_scan_ind() + * + ***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 lim_process_abort_scan_ind(tpAniSirGlobal mac_ctx, + uint8_t session_id, uint32_t scan_id) +{ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT, NULL, 0, 0); +#endif + + lim_log(mac_ctx, LOG2, FL("Processing AbortScan Ind scan_id %d"), + scan_id); + + /* send stop scan cmd to fw if scan offload is enabled. */ + lim_send_stop_scan_offload_req(mac_ctx, session_id, scan_id); + return; +} + +/** + * lim_message_processor() - Process messages from LIM. + * + * @mac_ctx: Pointer to the Global Mac Context. + * @msg: Received LIM message. + * + * Wrapper function for lim_process_messages when handling messages received by + * LIM.Could either defer messages or process them. + * + * Return: None. + */ +void lim_message_processor(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + if (eLIM_MLM_OFFLINE_STATE == mac_ctx->lim.gLimMlmState) { + pe_free_msg(mac_ctx, msg); + return; + } + + if (!def_msg_decision(mac_ctx, msg)) { + lim_process_messages(mac_ctx, msg); + /* process deferred message queue if allowed */ + if ((!(mac_ctx->lim.gLimAddtsSent)) && + (!(lim_is_system_in_scan_state(mac_ctx))) && + (true == GET_LIM_PROCESS_DEFD_MESGS(mac_ctx))) + lim_process_deferred_message_queue(mac_ctx); + } +} + +#ifdef FEATURE_OEM_DATA_SUPPORT + +void lim_oem_data_rsp_handle_resume_link_rsp(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *mlmOemDataRsp) +{ + if (status != CDF_STATUS_SUCCESS) { + lim_log(pMac, LOGE, + FL + ("OEM Data Rsp failed to get the response for resume link")); + } + + if (NULL != pMac->lim.gpLimMlmOemDataReq) { + cdf_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 */ + lim_post_sme_message(pMac, LIM_MLM_OEM_DATA_CNF, + (uint32_t *) (mlmOemDataRsp)); + + return; +} + +void lim_process_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *body) +{ + tpLimMlmOemDataRsp mlmOemDataRsp = NULL; + + /* Process all the messages for the lim queue */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + + mlmOemDataRsp = (tpLimMlmOemDataRsp) body; + + PELOG1(lim_log + (pMac, LOG1, FL("%s: sending oem data response msg to sme"), + __func__); + ) + lim_post_sme_message(pMac, LIM_MLM_OEM_DATA_CNF, + (uint32_t *) (mlmOemDataRsp)); + + return; +} + +#endif + +/** + * lim_process_messages() - Process messages from upper layers. + * + * @mac_ctx: Pointer to the Global Mac Context. + * @msg: Received message. + * + * Return: None. + */ +void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + uint8_t vdev_id = 0; + tUpdateBeaconParams beacon_params; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + uint8_t i; + uint8_t p2p_go_exists = 0; + tpPESession session_entry = NULL; + uint8_t defer_msg = false; + tLinkStateParams *link_state_param; + uint16_t pkt_len = 0; + cds_pkt_t *body_ptr = NULL; + CDF_STATUS cdf_status; + tSirMsgQ new_msg; + tSirSmeScanAbortReq *req_msg = NULL; + uint8_t session_id; + uint32_t scan_id; + +#ifdef FEATURE_WLAN_TDLS + tSirTdlsInd *tdls_ind = NULL; + tpDphHashNode sta_ds = NULL; + tTdlsLinkEstablishParams *tdls_link_params = NULL; +#endif + tSirMbMsgP2p *p2p_msg = NULL; + if (ANI_DRIVER_TYPE(mac_ctx) == eDRIVER_TYPE_MFG) { + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + return; + } + if (msg == NULL) { + lim_log(mac_ctx, LOGE, FL("Message pointer is Null")); + CDF_ASSERT(0); + return; + } +#ifdef WLAN_DEBUG + mac_ctx->lim.numTot++; +#endif + MTRACE(mac_trace_msg_rx(mac_ctx, NO_SESSION, + LIM_TRACE_MAKE_RXMSG(msg->type, LIM_MSG_PROCESSED));) + + switch (msg->type) { + + case SIR_LIM_UPDATE_BEACON: + lim_update_beacon(mac_ctx); + break; + case SIR_CFG_PARAM_UPDATE_IND: + if (!lim_is_system_in_scan_state(mac_ctx)) { + lim_handle_cf_gparam_update(mac_ctx, msg->bodyval); + break; + } + /* System is in DFS (Learn) mode. + * Defer processsing this message + */ + if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { + if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) + CDF_TRACE(CDF_MODULE_ID_PE, LOGE, + FL("Unable to Defer Msg")); + lim_log_session_states(mac_ctx); + lim_print_msg_name(mac_ctx, LOGE, msg->type); + } + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case WMA_START_OEM_DATA_RSP: + lim_process_oem_data_rsp(mac_ctx, msg->bodyptr); + msg->bodyptr = NULL; + break; +#endif + case WMA_SWITCH_CHANNEL_RSP: + lim_process_switch_channel_rsp(mac_ctx, msg->bodyptr); + msg->bodyptr = NULL; + break; +#ifdef ANI_SIR_IBSS_PEER_CACHING + case WMA_IBSS_STA_ADD: + lim_ibss_sta_add(mac_ctx, msg->bodyptr); + break; +#endif + case SIR_BB_XPORT_MGMT_MSG: + /* These messages are from Peer MAC entity. */ +#ifdef WLAN_DEBUG + mac_ctx->lim.numBbt++; +#endif + /* The original msg which we were deferring have the + * bodyPointer point to 'BD' instead of 'cds pkt'. If we + * don't make a copy of msg, then overwrite the + * msg->bodyPointer and next time when we try to + * process the msg, we will try to use 'BD' as + * 'cds Pkt' which will cause a crash + */ + if (msg->bodyptr == NULL) { + lim_log(mac_ctx, LOGE, FL("Message bodyptr is Null")); + CDF_ASSERT(0); + break; + } + cdf_mem_copy((uint8_t *) &new_msg, + (uint8_t *) msg, sizeof(tSirMsgQ)); + body_ptr = (cds_pkt_t *) new_msg.bodyptr; + cds_pkt_get_packet_length(body_ptr, &pkt_len); + + cdf_status = wma_ds_peek_rx_packet_info(body_ptr, + (void **) &new_msg.bodyptr, false); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cds_pkt_return_packet(body_ptr); + break; + } + + if (WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr)) + lim_log(mac_ctx, LOG1, FL("roamCandidateInd %d"), + WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr)); + + if (WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr)) + lim_log(mac_ctx, LOG1, FL("offloadScanLearn %d"), + WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr)); + + lim_handle80211_frames(mac_ctx, &new_msg, &defer_msg); + + if (defer_msg == true) { + CDF_TRACE(CDF_MODULE_ID_PE, LOG1, + FL("Defer Msg type=%x"), msg->type); + if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_PE, LOGE, + FL("Unable to Defer Msg")); + lim_log_session_states(mac_ctx); + cds_pkt_return_packet(body_ptr); + } + } else + /* PE is not deferring this 802.11 frame so we need to + * call cds_pkt_return. Asumption here is when Rx mgmt + * frame processing is done, cds packet could be + * freed here. + */ + cds_pkt_return_packet(body_ptr); + break; + case eWNI_SME_SCAN_REQ: + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + case eWNI_SME_DISASSOC_REQ: + case eWNI_SME_DEAUTH_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: + case eWNI_SME_SET_HW_MODE_REQ: + case eWNI_SME_SET_DUAL_MAC_CFG_REQ: + /* These messages are from HDD. Need to respond to HDD */ + lim_process_normal_hdd_msg(mac_ctx, msg, true); + break; + + case eWNI_SME_SCAN_ABORT_IND: + req_msg = msg->bodyptr; + if (req_msg) { + session_id = req_msg->sessionId; + scan_id = req_msg->scan_id; + lim_process_abort_scan_ind(mac_ctx, session_id, + scan_id); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + } + break; + 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_IND: + case eWNI_SME_SETCONTEXT_REQ: + case eWNI_SME_DISASSOC_CNF: + case eWNI_SME_DEAUTH_CNF: + case eWNI_SME_ASSOC_CNF: + case eWNI_SME_ADDTS_REQ: + case eWNI_SME_DELTS_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_REGISTER_MGMT_FRAME_REQ: + case eWNI_SME_UPDATE_NOA: + case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: + 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 */ + /* These messages are from HDD.No need to respond to HDD */ + lim_process_normal_hdd_msg(mac_ctx, msg, false); + break; + + case eWNI_PMC_SMPS_STATE_IND: + if (msg->bodyptr) { + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + } + break; + case eWNI_SME_SEND_ACTION_FRAME_IND: + lim_send_p2p_action_frame(mac_ctx, msg); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_ABORT_REMAIN_ON_CHAN_IND: + p2p_msg = (tSirMbMsgP2p *) msg->bodyptr; + lim_abort_remain_on_chan(mac_ctx, p2p_msg->sessionId, + p2p_msg->scan_id); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; + case SIR_HAL_P2P_NOA_START_IND: + session_entry = &mac_ctx->lim.gpSession[0]; + lim_log(mac_ctx, LOG1, "LIM received NOA start %x", msg->type); + + /* Since insert NOA is done and NOA start msg received, + * we should deactivate the Insert NOA timer + */ + lim_deactivate_and_change_timer(mac_ctx, + eLIM_INSERT_SINGLESHOT_NOA_TIMER); + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + session_entry = &mac_ctx->lim.gpSession[i]; + if ((session_entry != NULL) && (session_entry->valid) && + (session_entry->pePersona == CDF_P2P_GO_MODE)) { + /* Save P2P NOA start attribute for Go persona*/ + p2p_go_exists = 1; + cdf_mem_copy(&session_entry->p2pGoPsNoaStartInd, + msg->bodyptr, sizeof(tSirP2PNoaStart)); + cdf_status = + session_entry->p2pGoPsNoaStartInd.status; + if (cdf_status != CDF_STATUS_SUCCESS) + CDF_TRACE(CDF_MODULE_ID_PE, LOGW, + FL( + "GO NOA start status %d by FW"), + cdf_status); + break; + } + } + + if (p2p_go_exists == 0) + CDF_TRACE(CDF_MODULE_ID_PE, LOGW, + FL( + "GO is removed by the time NOA start recvd")); + + /* We received the NOA start indication. Now we can send down + * the SME request which requires off-channel operation */ + lim_process_regd_defd_sme_req_after_noa_start(mac_ctx); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; +#ifdef FEATURE_WLAN_TDLS + case SIR_HAL_TDLS_IND: + tdls_ind = (tpSirTdlsInd) msg->bodyptr; + session_entry = pe_find_session_by_sta_id(mac_ctx, + tdls_ind->staIdx, &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOG1, + FL("No session exist for given bssId")); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + return; + } + sta_ds = dph_get_hash_entry(mac_ctx, tdls_ind->assocId, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOG1, + FL("No sta_ds exist for given staId")); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + return; + } + + if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { + lim_log(mac_ctx, LOGE, + FL("rcvd TDLS IND from FW with RC %d "), + tdls_ind->reasonCode); + lim_send_sme_tdls_del_sta_ind(mac_ctx, sta_ds, + session_entry, tdls_ind->reasonCode); + } + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; +#endif + case SIR_HAL_P2P_NOA_ATTR_IND: + session_entry = &mac_ctx->lim.gpSession[0]; + lim_log(mac_ctx, LOG1, FL("Received message Noa_ATTR %x"), + msg->type); + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + session_entry = &mac_ctx->lim.gpSession[i]; + if ((session_entry != NULL) && (session_entry->valid) + && (session_entry->pePersona == + CDF_P2P_GO_MODE)) { /* Save P2P attr for Go */ + cdf_mem_copy( + &session_entry->p2pGoPsUpdate, + msg->bodyptr, + sizeof(tSirP2PNoaAttr)); + lim_log(mac_ctx, LOG2, + FL("bssId" + MAC_ADDRESS_STR + " ctWin=%d oppPsFlag=%d"), + MAC_ADDR_ARRAY( + session_entry->bssId), + session_entry->p2pGoPsUpdate.ctWin, + session_entry->p2pGoPsUpdate.oppPsFlag); + lim_log(mac_ctx, LOG2, + FL + (" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d"), + session_entry->p2pGoPsUpdate.uNoa1IntervalCnt, + session_entry->p2pGoPsUpdate.uNoa1Duration, + session_entry->p2pGoPsUpdate.uNoa1Interval, + session_entry->p2pGoPsUpdate.uNoa1StartTime); + break; + } + } + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; + case WMA_MISSED_BEACON_IND: + lim_ps_offload_handle_missed_beacon_ind(mac_ctx, msg); + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WMA_ROAM_OFFLOAD_SYNCH_IND: + lim_roam_offload_synch_ind(mac_ctx, msg); + /* bodyPtr is freed after handling + * eWNI_SME_ROAM_OFFLOAD_SYNCH_IND in sme_ProcessMsg */ + break; +#endif + case SIR_LIM_ADDTS_RSP_TIMEOUT: + lim_process_sme_req_messages(mac_ctx, msg); + break; +#ifdef FEATURE_WLAN_ESE + case SIR_LIM_ESE_TSM_TIMEOUT: +#ifndef FEATURE_WLAN_ESE_UPLOAD + limProcessTsmTimeoutHandler(mac_ctx, msg); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + break; + case WMA_TSM_STATS_RSP: +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_pe_ese_tsm_rsp(mac_ctx, + (tAniGetTsmStatsRsp *) msg->bodyptr); +#else + limProcessHalEseTsmRsp(mac_ctx, msg); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + break; +#endif + case WMA_ADD_TS_RSP: + lim_process_hal_add_ts_rsp(mac_ctx, msg); + break; + case SIR_LIM_DEL_TS_IND: + lim_process_del_ts_ind(mac_ctx, msg); + break; + case SIR_LIM_BEACON_GEN_IND: + if (mac_ctx->lim.gLimSystemRole != eLIM_AP_ROLE) + sch_process_pre_beacon_ind(mac_ctx, msg); + break; + case SIR_LIM_DELETE_STA_CONTEXT_IND: + lim_delete_sta_context(mac_ctx, msg); + break; + 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: + /* These timeout messages are handled by MLM sub module */ + lim_process_mlm_req_messages(mac_ctx, msg); + 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 (NULL == msg->bodyptr) + lim_log(mac_ctx, LOGE, + FL("Can't Process HB TO - bodyptr is Null")); + else { + session_entry = (tpPESession) msg->bodyptr; + lim_log(mac_ctx, LOGE, + FL + ("SIR_LIM_HEART_BEAT_TIMEOUT, Session %d"), + ((tpPESession) msg->bodyptr)->peSessionId); + limResetHBPktCount(session_entry); + lim_handle_heart_beat_timeout_for_session(mac_ctx, + session_entry); + } + break; + case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT: + lim_handle_heart_beat_failure_timeout(mac_ctx); + break; + case SIR_LIM_HASH_MISS_THRES_TIMEOUT: + mac_ctx->lim.gLimDisassocFrameCredit = 0; + break; + case SIR_LIM_CNF_WAIT_TIMEOUT: + /* Does not receive CNF or dummy packet */ + lim_handle_cnf_wait_timeout(mac_ctx, (uint16_t) msg->bodyval); + 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: + lim_process_channel_switch_timeout(mac_ctx); + break; + case SIR_LIM_QUIET_TIMEOUT: + lim_process_quiet_timeout(mac_ctx); + break; + case SIR_LIM_QUIET_BSS_TIMEOUT: + lim_process_quiet_bss_timeout(mac_ctx); + break; + case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: + lim_handle_update_olbc_cache(mac_ctx); + break; +#ifdef FEATURE_WLAN_TDLS + case SIR_HAL_TDLS_SHOULD_DISCOVER: + case SIR_HAL_TDLS_SHOULD_TEARDOWN: + case SIR_HAL_TDLS_PEER_DISCONNECTED: + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + ("%s received tdls event: 0x%x"), __func__, msg->type); + lim_send_sme_tdls_event_notify(mac_ctx, msg->type, + (void *)msg->bodyptr); + break; +#endif + case WMA_ADD_BSS_RSP: + lim_process_mlm_add_bss_rsp(mac_ctx, msg); + break; + case WMA_ADD_STA_RSP: + lim_process_add_sta_rsp(mac_ctx, msg); + break; + case WMA_DELETE_STA_RSP: + lim_process_mlm_del_sta_rsp(mac_ctx, msg); + break; + case WMA_DELETE_BSS_RSP: + lim_handle_delete_bss_rsp(mac_ctx, msg); + break; + case WMA_CSA_OFFLOAD_EVENT: + lim_handle_csa_offload_msg(mac_ctx, msg); + break; + case WMA_SET_BSSKEY_RSP: + case WMA_SET_STA_BCASTKEY_RSP: + lim_process_mlm_set_bss_key_rsp(mac_ctx, msg); + break; + case WMA_SET_STAKEY_RSP: + lim_process_mlm_set_sta_key_rsp(mac_ctx, msg); + break; + case WMA_GET_STATISTICS_RSP: + lim_send_sme_pe_statistics_rsp(mac_ctx, msg->type, + (void *)msg->bodyptr); + break; + case WMA_SET_MIMOPS_RSP: + case WMA_SET_TX_POWER_RSP: + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case WMA_SET_MAX_TX_POWER_RSP: +#if defined WLAN_FEATURE_VOWIFI + rrm_set_max_tx_power_rsp(mac_ctx, msg); +#endif + if (msg->bodyptr != NULL) { + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + } + break; + case SIR_LIM_ADDR2_MISS_IND: + lim_log(mac_ctx, LOGE, + FL("Addr2 mismatch interrupt received %X"), msg->type); + /* message from HAL indicating addr2 mismatch interrupt occurred + * msg->bodyptr contains only pointer to 48-bit addr2 field + */ + cdf_mem_free((void *)(msg->bodyptr)); + msg->bodyptr = NULL; + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case WMA_AGGR_QOS_RSP: + lim_process_ft_aggr_qo_s_rsp(mac_ctx, msg); + break; +#endif + case WMA_SET_LINK_STATE_RSP: + link_state_param = (tLinkStateParams *) msg->bodyptr; +#if defined WLAN_FEATURE_VOWIFI_11R + session_entry = link_state_param->session; + if (link_state_param->ft +#if defined WLAN_FEATURE_ROAM_OFFLOAD + && !session_entry->bRoamSynchInProgress +#endif + ) + lim_send_reassoc_req_with_ft_ies_mgmt_frame(mac_ctx, + session_entry->pLimMlmReassocReq, + session_entry); +#endif + if (link_state_param->callback) + link_state_param->callback(mac_ctx, + link_state_param->callbackArg, + link_state_param->status); + cdf_mem_free((void *)(msg->bodyptr)); + msg->bodyptr = NULL; + break; + case eWNI_SME_SET_BCN_FILTER_REQ: + session_id = (uint8_t) msg->bodyval; + session_entry = &mac_ctx->lim.gpSession[session_id]; + if ((session_entry != NULL) && + (lim_send_beacon_filter_info(mac_ctx, session_entry) != + eSIR_SUCCESS)) + lim_log(mac_ctx, LOGE, + FL("Failied to send Beacon Filter Info ")); + cdf_mem_free((void *)(msg->bodyptr)); + msg->bodyptr = NULL; + break; +#ifdef FEATURE_WLAN_TDLS + case WMA_SET_TDLS_LINK_ESTABLISH_REQ_RSP: + tdls_link_params = (tTdlsLinkEstablishParams *) msg->bodyptr; + session_entry = pe_find_session_by_sta_id(mac_ctx, + tdls_link_params->staIdx, &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session %u does not exist"), session_id); + /* 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 + */ + lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, 0, + NULL, NULL, eSIR_FAILURE); + } else { + lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, + session_entry->smeSessionId, NULL, NULL, + tdls_link_params->status); + } + cdf_mem_free((void *)(msg->bodyptr)); + msg->bodyptr = NULL; + break; +#endif + case WMA_RX_SCAN_EVENT: + lim_process_rx_scan_event(mac_ctx, msg->bodyptr); + break; + case WMA_IBSS_PEER_INACTIVITY_IND: + lim_process_ibss_peer_inactivity(mac_ctx, msg->bodyptr); + cdf_mem_free((void *)(msg->bodyptr)); + msg->bodyptr = NULL; + break; + case WMA_DFS_RADAR_IND: + lim_send_sme_dfs_event_notify(mac_ctx, msg->type, + (void *)msg->bodyptr); + /* msg->bodyptr will be freed up by SME/CSR */ + break; + case WMA_DFS_BEACON_TX_SUCCESS_IND: + lim_process_beacon_tx_success_ind(mac_ctx, msg->type, + (void *)msg->bodyptr); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case WMA_DISASSOC_TX_COMP: + lim_disassoc_tx_complete_cnf(mac_ctx, msg->bodyval); + break; + case WMA_DEAUTH_TX_COMP: + lim_deauth_tx_complete_cnf(mac_ctx, msg->bodyval); + break; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + case WMA_UPDATE_Q2Q_IE_IND: + cdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); + beacon_params.paramChangeBitmap = 0; + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + vdev_id = ((uint8_t *)msg->bodyptr)[i]; + session_entry = pe_find_session_by_sme_session_id( + mac_ctx, vdev_id); + if (session_entry == NULL) + continue; + session_entry->sap_advertise_avoid_ch_ie = + (uint8_t)msg->bodyval; + /* + * if message comes for DFS channel, no need to update: + * 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 (cds_get_channel_state( + session_entry->currentOperChannel) + != CHANNEL_STATE_DFS) { + beacon_params.bssIdx = session_entry->bssIdx; + beacon_params.beaconInterval = + session_entry->beaconParams.beaconInterval; + beacon_params.paramChangeBitmap |= + PARAM_BCN_INTERVAL_CHANGED; + sch_set_fixed_beacon_fields(mac_ctx, + session_entry); + lim_send_beacon_params(mac_ctx, &beacon_params, + session_entry); + } + } + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + case eWNI_SME_NSS_UPDATE_REQ: + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_CHANNEL_CHANGE_REQ: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_START_BEACON_REQ: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_UPDATE_ADDITIONAL_IES: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_MODIFY_ADDITIONAL_IES: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; +#ifdef QCA_HT_2040_COEX + case eWNI_SME_SET_HT_2040_MODE: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; +#endif + case SIR_HAL_SOC_SET_HW_MODE_RESP: + lim_process_set_hw_mode_resp(mac_ctx, msg->bodyptr); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case SIR_HAL_SOC_HW_MODE_TRANS_IND: + lim_process_hw_mode_trans_ind(mac_ctx, msg->bodyptr); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case SIR_HAL_SOC_DUAL_MAC_CFG_RESP: + lim_process_dual_mac_cfg_resp(mac_ctx, msg->bodyptr); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + case eWNI_SME_SET_IE_REQ: + lim_process_sme_req_messages(mac_ctx, msg); + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; + default: + cdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + /* Unwanted messages */ + /* Log error */ + lim_log(mac_ctx, LOGE, + FL("Discarding unexpected message received %X"), + msg->type); + lim_print_msg_name(mac_ctx, LOGE, msg->type); + break; + + } /* switch (msg->type) */ +} /*** end lim_process_messages() ***/ + +/** + * lim_process_deferred_message_queue + * + ***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 lim_process_deferred_message_queue(tpAniSirGlobal pMac) +{ + tSirMsgQ limMsg = { 0, 0, 0 }; + + tSirMsgQ *readMsg; + uint16_t size; + + /* + ** check any deferred messages need to be processed + **/ + size = pMac->lim.gLimDeferredMsgQ.size; + if (size > 0) { + while ((readMsg = lim_read_deferred_msg_q(pMac)) != NULL) { + cdf_mem_copy((uint8_t *) &limMsg, + (uint8_t *) readMsg, sizeof(tSirMsgQ)); + size--; + lim_process_messages(pMac, &limMsg); + + if ((lim_is_system_in_scan_state(pMac)) + || (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) + || (pMac->lim.gLimSystemInScanLearnMode)) + break; + } + } +} /*** end lim_process_deferred_message_queue() ***/ + +/** + * lim_process_normal_hdd_msg() - Process the message and defer if needed + * @mac_ctx : Pointer to Global MAC structure + * @msg : The message need to be processed + * @rsp_reqd: whether return result to hdd + * + * This function checks the current lim state and decide whether the message + * passed will be deferred or not. + * + * Return: None + */ +static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, tSirMsgQ *msg, + uint8_t rsp_reqd) +{ + bool defer_msg = true; + + /* Added For BT-AMP Support */ + if ((mac_ctx->lim.gLimSystemRole == eLIM_AP_ROLE) + || (mac_ctx->lim.gLimSystemRole == eLIM_BT_AMP_AP_ROLE) + || (mac_ctx->lim.gLimSystemRole == eLIM_BT_AMP_STA_ROLE) + || (mac_ctx->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 defer_msg. Possibly + * you might end up in an infinite loop. + */ + if ((msg->type == eWNI_SME_START_BSS_REQ) || + (msg->type == eWNI_SME_STOP_BSS_REQ) || + (msg->type == eWNI_SME_SWITCH_CHL_IND)) + defer_msg = false; + } + + if (((mac_ctx->lim.gLimAddtsSent) || + (lim_is_system_in_scan_state(mac_ctx))) && defer_msg) { + /* + * System is in DFS (Learn) mode or awaiting addts response or + * if radar is detected, Defer processsing this message + */ + if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { +#ifdef WLAN_DEBUG + mac_ctx->lim.numSme++; +#endif + lim_log_session_states(mac_ctx); + /* Release body */ + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + } + } else { + /* + * These messages are from HDD.Since these requests may also be + * generated internally within LIM module, need to distinquish + * and send response to host + */ + if (rsp_reqd) + mac_ctx->lim.gLimRspReqd = true; +#ifdef WLAN_DEBUG + mac_ctx->lim.numSme++; +#endif + if (lim_process_sme_req_messages(mac_ctx, msg)) { + /* + * Release body. limProcessSmeReqMessage consumed the + * buffer. We can free it. + */ + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + } + } +} + +void +handle_ht_capabilityand_ht_info(struct sAniSirGlobal *pMac, + tpPESession psessionEntry) +{ + tSirMacHTCapabilityInfo macHTCapabilityInfo; + tSirMacHTParametersInfo macHTParametersInfo; + tSirMacHTInfoField1 macHTInfoField1; + tSirMacHTInfoField2 macHTInfoField2; + tSirMacHTInfoField3 macHTInfoField3; + uint32_t cfgValue; + uint8_t *ptr; + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &cfgValue) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value")); + return; + } + ptr = (uint8_t *) &macHTCapabilityInfo; + *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); + pMac->lim.gHTLsigTXOPProtection = + (uint8_t) macHTCapabilityInfo.lsigTXOPProtection; + pMac->lim.gHTMIMOPSState = + (tSirMacHTMIMOPowerSaveState) macHTCapabilityInfo.mimoPowerSave; + pMac->lim.gHTGreenfield = (uint8_t) macHTCapabilityInfo.greenField; + pMac->lim.gHTMaxAmsduLength = + (uint8_t) macHTCapabilityInfo.maximalAMSDUsize; + pMac->lim.gHTShortGI20Mhz = (uint8_t) macHTCapabilityInfo.shortGI20MHz; + pMac->lim.gHTShortGI40Mhz = (uint8_t) macHTCapabilityInfo.shortGI40MHz; + pMac->lim.gHTPSMPSupport = (uint8_t) macHTCapabilityInfo.psmp; + pMac->lim.gHTDsssCckRate40MHzSupport = + (uint8_t) macHTCapabilityInfo.dsssCckMode40MHz; + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &cfgValue) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value")); + return; + } + ptr = (uint8_t *) &macHTParametersInfo; + *ptr = (uint8_t) (cfgValue & 0xff); + pMac->lim.gHTAMpduDensity = (uint8_t) macHTParametersInfo.mpduDensity; + pMac->lim.gHTMaxRxAMpduFactor = + (uint8_t) macHTParametersInfo.maxRxAMPDUFactor; + + /* Get HT IE Info */ + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD1, &cfgValue) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value")); + return; + } + ptr = (uint8_t *) &macHTInfoField1; + *((uint8_t *) ptr) = (uint8_t) (cfgValue & 0xff); + pMac->lim.gHTServiceIntervalGranularity = + (uint8_t) macHTInfoField1.serviceIntervalGranularity; + pMac->lim.gHTControlledAccessOnly = + (uint8_t) macHTInfoField1.controlledAccessOnly; + pMac->lim.gHTRifsMode = (uint8_t) macHTInfoField1.rifsMode; + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD2, &cfgValue) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value")); + return; + } + ptr = (uint8_t *) &macHTInfoField2; + *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); + pMac->lim.gHTOperMode = (tSirMacHTOperatingMode) macHTInfoField2.opMode; + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD3, &cfgValue) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value")); + return; + } + ptr = (uint8_t *) &macHTInfoField3; + *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); + pMac->lim.gHTPCOActive = (uint8_t) macHTInfoField3.pcoActive; + pMac->lim.gHTPCOPhase = (uint8_t) macHTInfoField3.pcoPhase; + pMac->lim.gHTSecondaryBeacon = + (uint8_t) macHTInfoField3.secondaryBeacon; + pMac->lim.gHTDualCTSProtection = + (uint8_t) macHTInfoField3.dualCTSProtection; + pMac->lim.gHTSTBCBasicMCS = (uint8_t) 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 = + (uint8_t) macHTInfoField3.lsigTXOPProtectionFullSupport; + } +} + +void lim_log_session_states(tpAniSirGlobal mac_ctx) +{ +#ifdef WLAN_DEBUG + int i; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + if (mac_ctx->lim.gpSession[i].valid) { + CDF_TRACE(CDF_MODULE_ID_PE, LOG1, + FL("sysRole(%d) Session (%d)"), + mac_ctx->lim.gLimSystemRole, i); + CDF_TRACE(CDF_MODULE_ID_PE, LOG1, + FL("SME: Curr %s,Prev %s,MLM: Curr %s,Prev %s"), + lim_sme_state_str( + mac_ctx->lim.gpSession[i].limSmeState), + lim_sme_state_str( + mac_ctx->lim.gpSession[i].limPrevSmeState), + lim_mlm_state_str( + mac_ctx->lim.gpSession[i].limMlmState), + lim_mlm_state_str( + mac_ctx->lim.gpSession[i].limPrevMlmState)); + } + } +#endif +} diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c new file mode 100644 index 000000000000..73f4bf0294ea --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -0,0 +1,2868 @@ +/* + * 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 "cds_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "sir_api.h" +#include "sir_params.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_security_utils.h" +#include "lim_send_messages.h" +#include "lim_send_messages.h" +#include "lim_session_utils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM +#include "host_diag_core_log.h" +#endif +#include "wma_if.h" + +static void lim_process_mlm_start_req(tpAniSirGlobal, uint32_t *); +#ifdef FEATURE_OEM_DATA_SUPPORT +static void lim_process_mlm_oem_data_req(tpAniSirGlobal, uint32_t *); +#endif +static void lim_process_mlm_join_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_auth_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_assoc_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_reassoc_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_disassoc_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_deauth_req(tpAniSirGlobal, uint32_t *); +static void lim_process_mlm_set_keys_req(tpAniSirGlobal, uint32_t *); + +/* MLM Timeout event handler templates */ +static void lim_process_periodic_probe_req_timer(tpAniSirGlobal mac_ctx); +static void lim_process_join_failure_timeout(tpAniSirGlobal); +static void lim_process_auth_failure_timeout(tpAniSirGlobal); +static void lim_process_auth_rsp_timeout(tpAniSirGlobal, uint32_t); +static void lim_process_assoc_failure_timeout(tpAniSirGlobal, uint32_t); +static void lim_process_periodic_join_probe_req_timer(tpAniSirGlobal); + +/** + * lim_process_mlm_req_messages() - process mlm request messages + * @mac_ctx: global MAC context + * @msg: mlm request message + * + * This function is called by lim_post_mlm_message(). This + * function handles MLM primitives invoked by SME. + * 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. + * + * Return: None + */ +void lim_process_mlm_req_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + MTRACE(mac_trace_msg_rx(mac_ctx, NO_SESSION, msg->type)); + switch (msg->type) { + case LIM_MLM_START_REQ: + lim_process_mlm_start_req(mac_ctx, msg->bodyptr); + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case LIM_MLM_OEM_DATA_REQ: + lim_process_mlm_oem_data_req(mac_ctx, msg->bodyptr); + break; +#endif + case LIM_MLM_JOIN_REQ: + lim_process_mlm_join_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_AUTH_REQ: + lim_process_mlm_auth_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_ASSOC_REQ: + lim_process_mlm_assoc_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_REASSOC_REQ: + lim_process_mlm_reassoc_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_DISASSOC_REQ: + lim_process_mlm_disassoc_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_DEAUTH_REQ: + lim_process_mlm_deauth_req(mac_ctx, msg->bodyptr); + break; + case LIM_MLM_SETKEYS_REQ: + lim_process_mlm_set_keys_req(mac_ctx, msg->bodyptr); + break; + case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT: + lim_process_periodic_probe_req_timer(mac_ctx); + break; + case SIR_LIM_JOIN_FAIL_TIMEOUT: + lim_process_join_failure_timeout(mac_ctx); + break; + case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: + lim_process_periodic_join_probe_req_timer(mac_ctx); + break; + case SIR_LIM_AUTH_FAIL_TIMEOUT: + lim_process_auth_failure_timeout(mac_ctx); + break; + case SIR_LIM_AUTH_RSP_TIMEOUT: + lim_process_auth_rsp_timeout(mac_ctx, msg->bodyval); + break; + case SIR_LIM_ASSOC_FAIL_TIMEOUT: + lim_process_assoc_failure_timeout(mac_ctx, msg->bodyval); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: + lim_process_ft_preauth_rsp_timeout(mac_ctx); + break; +#endif + case SIR_LIM_REMAIN_CHN_TIMEOUT: + lim_process_remain_on_chn_timeout(mac_ctx); + break; + case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT: + lim_process_insert_single_shot_noa_timeout(mac_ctx); + break; + case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: + lim_convert_active_channel_to_passive_channel(mac_ctx); + break; + case SIR_LIM_DISASSOC_ACK_TIMEOUT: + lim_process_disassoc_ack_timeout(mac_ctx); + break; + case SIR_LIM_DEAUTH_ACK_TIMEOUT: + lim_process_deauth_ack_timeout(mac_ctx); + break; + case LIM_MLM_TSPEC_REQ: + default: + break; + } /* switch (msg->type) */ +} + +/* WLAN_SUSPEND_LINK Related */ + +/** + * lim_is_link_suspended()- check if link is suspended + * @mac_ctx: global MAC context + * + * This function returns is link is suspended or not. + * Since Suspend link uses init scan, it just returns + * gLimSystemInScanLearnMode flag. + * + * Return: uint8_t(gLimSystemInScanLearnMode flag) + */ +uint8_t lim_is_link_suspended(tpAniSirGlobal mac_ctx) +{ + return mac_ctx->lim.gLimSystemInScanLearnMode; +} + +/** + * lim_change_channel_with_callback() - change channel and register callback + * @mac_ctx: global MAC context + * @new_chan: new channel to switch + * @callback: Callback function + * @cbdata: callback data + * @session_entry: PE session pointer + * + * 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. + * + * Return: None + */ +void +lim_change_channel_with_callback(tpAniSirGlobal mac_ctx, uint8_t new_chan, + CHANGE_CHANNEL_CALLBACK callback, + uint32_t *cbdata, tpPESession session_entry) +{ + /* Sanity checks for the current and new channel */ +#if defined WLAN_VOWIFI_DEBUG + lim_log(mac_ctx, LOGE, FL("Switching channel to %d"), new_chan); +#endif + session_entry->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_OPERATION; + + mac_ctx->lim.gpchangeChannelCallback = callback; + mac_ctx->lim.gpchangeChannelData = cbdata; + + lim_send_switch_chnl_params(mac_ctx, new_chan, 0, 0, + CH_WIDTH_20MHZ, session_entry->maxTxPower, + session_entry->peSessionId, false); + + return; +} + +/** + * lim_covert_channel_scan_type() - switch between ACTIVE and PASSIVE scan type + * @mac_ctx: global MAC context + * @chan_num: channel number to change the scan type + * @passive_to_active: flag to indicate if switch allowed + * + * This function is called to get the list, + * change the channel type and set again. + * 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 + * + * Return: None + */ + +void lim_covert_channel_scan_type(tpAniSirGlobal mac_ctx, uint8_t chan_num, + bool passive_to_active) +{ + + uint32_t i; + uint8_t chan_pair[WNI_CFG_SCAN_CONTROL_LIST_LEN]; + uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + tSirRetStatus status; + + status = wlan_cfg_get_str(mac_ctx, WNI_CFG_SCAN_CONTROL_LIST, + chan_pair, &len); + if (eSIR_SUCCESS != status) { + lim_log(mac_ctx, LOGE, FL("Unable to get scan control list")); + return; + } + if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) { + lim_log(mac_ctx, LOGE, + FL("Invalid scan control list length:%d"), len); + return; + } + for (i = 0; (i + 1) < len; i += 2) { + if (chan_pair[i] != chan_num) /* skip this channel */ + continue; + if ((eSIR_PASSIVE_SCAN == chan_pair[i + 1]) && + true == passive_to_active) { + lim_log(mac_ctx, LOG1, FL + ("Channel %d changed from Passive to Active"), + chan_num); + chan_pair[i + 1] = eSIR_ACTIVE_SCAN; + break; + } + if ((eSIR_ACTIVE_SCAN == chan_pair[i + 1]) && + false == passive_to_active) { + lim_log(mac_ctx, LOG1, FL + ("Channel %d changed from Active to Passive"), + chan_num); + chan_pair[i + 1] = eSIR_PASSIVE_SCAN; + break; + } + } + + cfg_set_str_notify(mac_ctx, WNI_CFG_SCAN_CONTROL_LIST, + (uint8_t *) chan_pair, len, false); + return; +} + +/** + * lim_set_dfs_channel_list() - convert dfs channel list to active channel list + * @mac_ctx: global MAC context. + * @chan_num: channel number + * @dfs_ch_list: list of DFS channels + * + * 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. + * + * NOTE: If a channel is ACTIVE, it won't store any time + * If a channel is PAssive, it will store time as timestamp + * + * Return: None + */ +void lim_set_dfs_channel_list(tpAniSirGlobal mac_ctx, uint8_t chan_num, + tSirDFSChannelList *dfs_ch_list) +{ + bool pass_to_active = true; + + if (!((1 <= chan_num) && (165 >= chan_num))) { + lim_log(mac_ctx, LOGE, FL("Invalid Channel: %d"), chan_num); + return; + } + + if (true == lim_isconnected_on_dfs_channel(chan_num)) { + if (dfs_ch_list->timeStamp[chan_num] == 0) { + /* + * Received first beacon; + * Convert DFS channel to Active channel. + */ + lim_log(mac_ctx, LOG1, + FL("Received first beacon on DFS channel: %d"), + chan_num); + lim_covert_channel_scan_type(mac_ctx, chan_num, + pass_to_active); + } + dfs_ch_list->timeStamp[chan_num] = + cdf_mc_timer_get_system_time(); + } else { + lim_log(mac_ctx, LOG1, FL("Channel %d is Active"), chan_num); + return; + } + + if (!tx_timer_running + (&mac_ctx->lim.limTimers.gLimActiveToPassiveChannelTimer)) { + tx_timer_activate( + &mac_ctx->lim.limTimers.gLimActiveToPassiveChannelTimer); + } + + return; +} + +/** + * lim_restore_pre_scan_state() - restore HW state prior to scan + * + * @mac_ctx: global MAC context + * + * This function is called by lim_continue_channel_scan() + * to restore HW state prior to entering 'scan state' + * + * Return: None + */ +void lim_restore_pre_scan_state(tpAniSirGlobal mac_ctx) +{ + /* Deactivate MIN/MAX channel timers if running */ + lim_deactivate_and_change_timer(mac_ctx, eLIM_MIN_CHANNEL_TIMER); + lim_deactivate_and_change_timer(mac_ctx, eLIM_MAX_CHANNEL_TIMER); + + mac_ctx->lim.gLimSystemInScanLearnMode = 0; + lim_log(mac_ctx, LOG1, FL("Scan ended, took %llu tu"), + (tx_time_get() - mac_ctx->lim.scanStartTime)); +} + +#ifdef FEATURE_OEM_DATA_SUPPORT +/** + * lim_send_hal_oem_data_req() - send oem data request + * @mac_ctx: global MAC context + * + * This function is used to send OEM data request to HAL. + * + * Return: None + */ +void lim_send_hal_oem_data_req(tpAniSirGlobal mac_ctx) +{ + tSirMsgQ msg; + tpStartOemDataReq start_oem_data_req = NULL; + tSirRetStatus rc = eSIR_SUCCESS; + tpLimMlmOemDataRsp mlm_oem_data_rsp; + uint32_t reqlen = 0; + + if (NULL == mac_ctx->lim.gpLimMlmOemDataReq) { + lim_log(mac_ctx, LOGE, FL("Null pointer")); + goto error; + } + + reqlen = sizeof(tStartOemDataReq); + + start_oem_data_req = cdf_mem_malloc(reqlen); + if (NULL == start_oem_data_req) { + lim_log(mac_ctx, LOGE, FL + ("Could not allocate memory for start_oem_data_req")); + goto error; + } + + cdf_mem_set((uint8_t *) (start_oem_data_req), reqlen, 0); + + /* Now copy over the information to the OEM DATA REQ to HAL */ + cdf_mem_copy(start_oem_data_req->selfMacAddr, + mac_ctx->lim.gpLimMlmOemDataReq->selfMacAddr, + sizeof(tSirMacAddr)); + + cdf_mem_copy(start_oem_data_req->oemDataReq, + mac_ctx->lim.gpLimMlmOemDataReq->oemDataReq, + OEM_DATA_REQ_SIZE); + + /* Create the message to be passed to HAL */ + msg.type = WMA_START_OEM_DATA_REQ; + msg.bodyptr = start_oem_data_req; + msg.bodyval = 0; + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false); + MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type)); + + rc = wma_post_ctrl_msg(mac_ctx, &msg); + if (rc == eSIR_SUCCESS) + return; + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + cdf_mem_free(start_oem_data_req); + lim_log(mac_ctx, LOGE, + FL("OEM_DATA: posting WMA_START_OEM_DATA_REQ to HAL failed")); + +error: + mac_ctx->lim.gLimMlmState = mac_ctx->lim.gLimPrevMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, NO_SESSION, + mac_ctx->lim.gLimMlmState)); + + mlm_oem_data_rsp = cdf_mem_malloc(sizeof(tLimMlmOemDataRsp)); + if (NULL == mlm_oem_data_rsp) { + lim_log(mac_ctx->hHdd, LOGP, FL + ("memory allocation for mlm_oem_data_rsp")); + return; + } + + if (NULL != mac_ctx->lim.gpLimMlmOemDataReq) { + cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq); + mac_ctx->lim.gpLimMlmOemDataReq = NULL; + } + + lim_post_sme_message(mac_ctx, LIM_MLM_OEM_DATA_CNF, + (uint32_t *) mlm_oem_data_rsp); + + return; +} +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +/** + * mlm_add_sta() - MLM add sta + * @mac_ctx: global MAC context + * @sta_param: Add sta params + * @bssid: BSSID + * @ht_capable: HT capability + * @session_entry: PE session entry + * + * This function is called to update station parameters + * + * Return: None + */ +static void mlm_add_sta(tpAniSirGlobal mac_ctx, tpAddStaParams sta_param, + uint8_t *bssid, uint8_t ht_capable, tpPESession session_entry) +{ + uint32_t val; + uint32_t self_dot11mode = 0; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_dot11mode); + sta_param->staType = STA_ENTRY_SELF; /* Identifying self */ + + cdf_mem_copy(sta_param->bssId, bssid, sizeof(tSirMacAddr)); + cdf_mem_copy(sta_param->staMac, session_entry->selfMacAddr, + sizeof(tSirMacAddr)); + + /* Configuration related parameters to be changed to support BT-AMP */ + + if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL, + &val)) + lim_log(mac_ctx, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + sta_param->listenInterval = (uint16_t) val; + + if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx, WNI_CFG_SHORT_PREAMBLE, + &val)) + lim_log(mac_ctx, LOGP, FL("Couldn't get SHORT_PREAMBLE")); + sta_param->shortPreambleSupported = (uint8_t) val; + + sta_param->assocId = 0; /* Is SMAC OK with this? */ + sta_param->wmmEnabled = 0; + sta_param->uAPSD = 0; + sta_param->maxSPLen = 0; + sta_param->us32MaxAmpduDuration = 0; + sta_param->maxAmpduSize = 0; /* 0: 8k, 1: 16k,2: 32k,3: 64k, 4:128k */ + + /* For Self STA get the LDPC capability from config.ini */ + sta_param->htLdpcCapable = + (session_entry->txLdpcIniFeatureEnabled & 0x01); + sta_param->vhtLdpcCapable = + ((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01); + + if (IS_DOT11_MODE_HT(session_entry->dot11mode)) { + sta_param->htCapable = ht_capable; + sta_param->greenFieldCapable = + lim_get_ht_capability(mac_ctx, eHT_GREENFIELD, + session_entry); + sta_param->ch_width = + lim_get_ht_capability(mac_ctx, + eHT_SUPPORTED_CHANNEL_WIDTH_SET, session_entry); + sta_param->mimoPS = + (tSirMacHTMIMOPowerSaveState)lim_get_ht_capability( + mac_ctx, eHT_MIMO_POWER_SAVE, session_entry); + sta_param->rifsMode = + lim_get_ht_capability(mac_ctx, eHT_RIFS_MODE, + session_entry); + sta_param->lsigTxopProtection = + lim_get_ht_capability(mac_ctx, eHT_LSIG_TXOP_PROTECTION, + session_entry); + sta_param->maxAmpduDensity = + lim_get_ht_capability(mac_ctx, eHT_MPDU_DENSITY, + session_entry); + sta_param->maxAmsduSize = + lim_get_ht_capability(mac_ctx, eHT_MAX_AMSDU_LENGTH, + session_entry); + sta_param->fDsssCckMode40Mhz = + lim_get_ht_capability(mac_ctx, eHT_DSSS_CCK_MODE_40MHZ, + session_entry); + sta_param->fShortGI20Mhz = + lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_20MHZ, + session_entry); + sta_param->fShortGI40Mhz = + lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_40MHZ, + session_entry); + } + if (session_entry->vhtCapability) { + sta_param->vhtCapable = true; + sta_param->vhtTxBFCapable = + session_entry->txBFIniFeatureEnabled; + sta_param->vhtTxMUBformeeCapable = session_entry->txMuBformee; + sta_param->enable_su_tx_bformer = + session_entry->enable_su_tx_bformer; + } + /* + * Since this is Self-STA, need to populate Self MAX_AMPDU_SIZE + * capabilities + */ + if (IS_DOT11_MODE_VHT(self_dot11mode)) { + val = 0; /* Default 8K AMPDU size */ + if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &val)) + lim_log(mac_ctx, LOGE, FL + ("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT")); + sta_param->maxAmpduSize = (uint8_t) val; + } + sta_param->enableVhtpAid = session_entry->enableVhtpAid; + sta_param->enableAmpduPs = session_entry->enableAmpduPs; + sta_param->enableHtSmps = session_entry->enableHtSmps; + sta_param->htSmpsconfig = session_entry->htSmpsvalue; + +#ifdef WLAN_FEATURE_11AC + lim_populate_own_rate_set(mac_ctx, &sta_param->supportedRates, NULL, + false, session_entry, NULL); +#else + lim_populate_own_rate_set(mac_ctx, &sta_param->supportedRates, NULL, + false, session_entry); +#endif + lim_fill_supported_rates_info(mac_ctx, NULL, &sta_param->supportedRates, + session_entry); + + lim_log(mac_ctx, LOGE, FL( + "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d," + " SGI20: %d, SGI40%d"), sta_param->greenFieldCapable, + sta_param->ch_width, sta_param->mimoPS, + sta_param->lsigTxopProtection, sta_param->fDsssCckMode40Mhz, + sta_param->fShortGI20Mhz, sta_param->fShortGI40Mhz); + + if (CDF_P2P_GO_MODE == session_entry->pePersona) + sta_param->p2pCapableSta = 1; +} + +/** + * lim_mlm_add_bss() - HAL interface for WMA_ADD_BSS_REQ + * @mac_ctx: global MAC context + * @mlm_start_req: MLM start request + * @session: PE session entry + * + * Package WMA_ADD_BSS_REQ to HAL, in order to start a BSS + * + * Return: eSIR_SME_SUCCESS on success, other error codes otherwise + */ +tSirResultCodes +lim_mlm_add_bss(tpAniSirGlobal mac_ctx, + tLimMlmStartReq *mlm_start_req, tpPESession session) +{ + tSirMsgQ msg_buf; + tpAddBssParams addbss_param = NULL; + uint32_t retcode; + + /* Package WMA_ADD_BSS_REQ message parameters */ + addbss_param = cdf_mem_malloc(sizeof(tAddBssParams)); + if (NULL == addbss_param) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory during ADD_BSS")); + /* Respond to SME with LIM_MLM_START_CNF */ + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set(addbss_param, sizeof(tAddBssParams), 0); + /* Fill in tAddBssParams members */ + cdf_mem_copy(addbss_param->bssId, mlm_start_req->bssId, + sizeof(tSirMacAddr)); + + /* Fill in tAddBssParams selfMacAddr */ + cdf_mem_copy(addbss_param->selfMacAddr, + session->selfMacAddr, sizeof(tSirMacAddr)); + + addbss_param->bssType = mlm_start_req->bssType; + if ((mlm_start_req->bssType == eSIR_IBSS_MODE) || + (mlm_start_req->bssType == eSIR_BTAMP_AP_MODE) || + (mlm_start_req->bssType == eSIR_BTAMP_STA_MODE)) { + addbss_param->operMode = BSS_OPERATIONAL_MODE_STA; + } else if (mlm_start_req->bssType == eSIR_INFRA_AP_MODE) { + addbss_param->operMode = BSS_OPERATIONAL_MODE_AP; + } + + addbss_param->shortSlotTimeSupported = session->shortSlotTimeSupported; + addbss_param->beaconInterval = mlm_start_req->beaconPeriod; + addbss_param->dtimPeriod = mlm_start_req->dtimPeriod; + addbss_param->wps_state = mlm_start_req->wps_state; + addbss_param->cfParamSet.cfpCount = mlm_start_req->cfParamSet.cfpCount; + addbss_param->cfParamSet.cfpPeriod = + mlm_start_req->cfParamSet.cfpPeriod; + addbss_param->cfParamSet.cfpMaxDuration = + mlm_start_req->cfParamSet.cfpMaxDuration; + addbss_param->cfParamSet.cfpDurRemaining = + mlm_start_req->cfParamSet.cfpDurRemaining; + + addbss_param->rateSet.numRates = mlm_start_req->rateSet.numRates; + cdf_mem_copy(addbss_param->rateSet.rate, mlm_start_req->rateSet.rate, + mlm_start_req->rateSet.numRates); + + addbss_param->nwType = mlm_start_req->nwType; + addbss_param->htCapable = mlm_start_req->htCapable; + addbss_param->vhtCapable = session->vhtCapability; + addbss_param->ch_width = session->ch_width; + addbss_param->ch_center_freq_seg0 = + session->ch_center_freq_seg0; + addbss_param->ch_center_freq_seg1 = + session->ch_center_freq_seg1; + addbss_param->htOperMode = mlm_start_req->htOperMode; + addbss_param->dualCTSProtection = mlm_start_req->dualCTSProtection; + addbss_param->txChannelWidthSet = mlm_start_req->txChannelWidthSet; + + addbss_param->currentOperChannel = mlm_start_req->channelNumber; +#ifdef WLAN_FEATURE_11W + addbss_param->rmfEnabled = session->limRmfEnabled; +#endif + + /* Update PE sessionId */ + addbss_param->sessionId = mlm_start_req->sessionId; + + /* Send the SSID to HAL to enable SSID matching for IBSS */ + cdf_mem_copy(&(addbss_param->ssId.ssId), + mlm_start_req->ssId.ssId, mlm_start_req->ssId.length); + addbss_param->ssId.length = mlm_start_req->ssId.length; + addbss_param->bHiddenSSIDEn = mlm_start_req->ssidHidden; + lim_log(mac_ctx, LOGE, FL("TRYING TO HIDE SSID %d"), + addbss_param->bHiddenSSIDEn); + /* CR309183. Disable Proxy Probe Rsp. Host handles Probe Requests. Until FW fixed. */ + addbss_param->bProxyProbeRespEn = 0; + addbss_param->obssProtEnabled = mlm_start_req->obssProtEnabled; + +#if defined WLAN_FEATURE_VOWIFI + addbss_param->maxTxPower = session->maxTxPower; +#endif + mlm_add_sta(mac_ctx, &addbss_param->staContext, + addbss_param->bssId, addbss_param->htCapable, + session); + + addbss_param->status = CDF_STATUS_SUCCESS; + addbss_param->respReqd = 1; + + /* Set a new state for MLME */ + session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId, + session->limMlmState)); + + /* pass on the session persona to hal */ + addbss_param->halPersona = session->pePersona; + + addbss_param->bSpectrumMgtEnabled = session->spectrumMgtEnabled || + lim_isconnected_on_dfs_channel(mlm_start_req->channelNumber); +#if defined WLAN_FEATURE_VOWIFI_11R + addbss_param->extSetStaKeyParamValid = 0; +#endif + + addbss_param->dot11_mode = session->dot11mode; + addbss_param->nss = session->nss; + lim_log(mac_ctx, LOG2, FL("dot11_mode:%d nss value:%d"), + addbss_param->dot11_mode, addbss_param->nss); + + msg_buf.type = WMA_ADD_BSS_REQ; + msg_buf.reserved = 0; + msg_buf.bodyptr = addbss_param; + msg_buf.bodyval = 0; + MTRACE(mac_trace_msg_tx(mac_ctx, session->peSessionId, msg_buf.type)); + + lim_log(mac_ctx, LOGW, FL("Sending WMA_ADD_BSS_REQ...")); + retcode = wma_post_ctrl_msg(mac_ctx, &msg_buf); + if (eSIR_SUCCESS != retcode) { + lim_log(mac_ctx, LOGE, + FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), + retcode); + cdf_mem_free(addbss_param); + return eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + + return eSIR_SME_SUCCESS; +} + +/** + * lim_process_mlm_start_req() - process MLM_START_REQ message + * + * @mac_ctx: global MAC context + * @msg_buf: Pointer to MLM message buffer + * + * This function is called to process MLM_START_REQ message + * from SME + * 1) MLME receives LIM_MLM_START_REQ from LIM + * 2) MLME sends WMA_ADD_BSS_REQ to HAL + * 3) MLME changes state to eLIM_MLM_WT_ADD_BSS_RSP_STATE + * MLME now waits for HAL to send WMA_ADD_BSS_RSP + * + * Return: None + */ +static void lim_process_mlm_start_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tLimMlmStartReq *mlm_start_req; + tLimMlmStartCnf mlm_start_cnf; + tpPESession session = NULL; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + mlm_start_req = (tLimMlmStartReq *) msg_buf; + session = pe_find_session_by_session_id(mac_ctx, + mlm_start_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGP, + FL("Session Does not exist for given sessionID")); + mlm_start_cnf.resultCode = eSIR_SME_REFUSED; + goto end; + } + + if (session->limMlmState != eLIM_MLM_IDLE_STATE) { + /* + * Should not have received Start req in states other than idle. + * Return Start confirm with failure code. + */ + lim_log(mac_ctx, LOGE, + FL("received unexpected MLM_START_REQ in state %X"), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState); + mlm_start_cnf.resultCode = + eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + goto end; + } + + mlm_start_cnf.resultCode = + lim_mlm_add_bss(mac_ctx, mlm_start_req, session); + +end: + /* Update PE session Id */ + mlm_start_cnf.sessionId = mlm_start_req->sessionId; + + /* Free up buffer allocated for LimMlmScanReq */ + cdf_mem_free(msg_buf); + + /* + * Respond immediately to LIM, only if MLME has not been + * successfully able to send WMA_ADD_BSS_REQ to HAL. + * Else, LIM_MLM_START_CNF will be sent after receiving + * WMA_ADD_BSS_RSP from HAL + */ + if (eSIR_SME_SUCCESS != mlm_start_cnf.resultCode) + lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF, + (uint32_t *) &mlm_start_cnf); +} + +#ifdef FEATURE_OEM_DATA_SUPPORT +/** + * lim_process_mlm_oem_data_req() - process MLM OEM_DATA_REQ message + * @mac_ctx: global MAC context + * @msg_buf: MLM message buffer + * + * This function process MLM OEM_DATA_REQ message. + * + * Return: None + */ +static void lim_process_mlm_oem_data_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tLimMlmOemDataRsp *mlm_oem_data_rsp; + + if (((mac_ctx->lim.gLimMlmState == eLIM_MLM_IDLE_STATE) || + (mac_ctx->lim.gLimMlmState == eLIM_MLM_JOINED_STATE) || + (mac_ctx->lim.gLimMlmState == eLIM_MLM_AUTHENTICATED_STATE) || + (mac_ctx->lim.gLimMlmState == eLIM_MLM_BSS_STARTED_STATE) || + (mac_ctx->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 (mac_ctx->lim.gpLimMlmOemDataReq) { + cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq); + mac_ctx->lim.gpLimMlmOemDataReq = NULL; + } + + mac_ctx->lim.gpLimMlmOemDataReq = (tLimMlmOemDataReq *) msg_buf; + mac_ctx->lim.gLimPrevMlmState = mac_ctx->lim.gLimMlmState; + + lim_log(mac_ctx, LOG2, FL("Calling lim_send_hal_oem_data_req")); + lim_send_hal_oem_data_req(mac_ctx); + } else { + /* Should not have received oem data req in other states */ + lim_log(mac_ctx, LOGW, FL + ("unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X"), + mac_ctx->lim.gLimMlmState); + lim_print_mlm_state(mac_ctx, LOGW, mac_ctx->lim.gLimMlmState); + + /* Free up buffer allocated */ + cdf_mem_free(msg_buf); + + /* Return Meas confirm with INVALID_PARAMETERS */ + mlm_oem_data_rsp = cdf_mem_malloc(sizeof(tLimMlmOemDataRsp)); + if (mlm_oem_data_rsp != NULL) { + lim_post_sme_message(mac_ctx, LIM_MLM_OEM_DATA_CNF, + (uint32_t *) mlm_oem_data_rsp); + cdf_mem_free(mlm_oem_data_rsp); + } else { + lim_log(mac_ctx, LOGP, FL + ("Could not allocate memory for mlm_oem_data_rsp")); + 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; + + lim_log(mac, LOG1, FL("Sessionid %d set link state(%d) cb status:%d"), + session_entry->peSessionId, session_entry->limMlmState, + status); + + if (!status) { + lim_log(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 session_entry 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 + lim_log(mac, LOGE, + FL("[lim_process_mlm_join_req]: suspend link success(%d) " + "on sessionid: %d setting channel to: %d with ch_width :%d " + "and maxtxPower: %d"), status, session_entry->peSessionId, + session_entry->currentOperChannel, + session_entry->ch_width, + session_entry->maxTxPower); + lim_set_channel(mac, session_entry->currentOperChannel, + session_entry->ch_center_freq_seg0, + session_entry->ch_center_freq_seg1, + session_entry->ch_width, + session_entry->maxTxPower, + session_entry->peSessionId); + return; + +failure: + MTRACE(mac_trace(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; + lim_post_sme_message(mac, LIM_MLM_JOIN_CNF, (uint32_t *) &mlm_join_cnf); +} + +/** + * lim_process_mlm_post_join_suspend_link() - This function is called after the + * suspend link while joining off channel. + * + * @mac_ctx: Pointer to Global MAC structure + * @status: status of suspend link. + * @ctx: passed while calling suspend link(session) + * + * This function does following: + * 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. + * + * @Return None + */ +static void +lim_process_mlm_post_join_suspend_link(tpAniSirGlobal mac_ctx, + CDF_STATUS status, + uint32_t *ctx) +{ + tLimMlmJoinCnf mlm_join_cnf; + tpPESession session = (tpPESession) ctx; + tSirLinkState lnk_state; + + if (CDF_STATUS_SUCCESS != status) { + lim_log(mac_ctx, LOGE, + FL("Sessionid %d Suspend link(NOTIFY_BSS) failed. Still proceeding with join"), + session->peSessionId); + } + lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER); + + /* assign appropriate sessionId to the timer object */ + mac_ctx->lim.limTimers.gLimJoinFailureTimer.sessionId = + session->peSessionId; + + lnk_state = (LIM_IS_BT_AMP_STA_ROLE(session) ? + eSIR_LINK_BTAMP_PREASSOC_STATE : eSIR_LINK_PREASSOC_STATE); + lim_log(mac_ctx, LOG1, FL("[lim_process_mlm_join_req]: lnk_state:%d"), + lnk_state); + + if (lim_set_link_state(mac_ctx, lnk_state, + session->pLimMlmJoinReq->bssDescription.bssId, + session->selfMacAddr, + lim_post_join_set_link_state_callback, + session) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("SessionId:%d lim_set_link_state to eSIR_LINK_PREASSOC_STATE Failed!!"), + session->peSessionId); + lim_print_mac_addr(mac_ctx, + session->pLimMlmJoinReq->bssDescription.bssId, LOGE); + mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + session->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, session->limMlmState)); + goto error; + } + + return; +error: + mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlm_join_cnf.sessionId = session->peSessionId; + mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, + (uint32_t *) &mlm_join_cnf); +} + +/** + * lim_process_mlm_join_req() - process mlm join request. + * + * @mac_ctx: Pointer to Global MAC structure + * @msg: Pointer to the MLM message buffer + * + * This function is called to process MLM_JOIN_REQ message + * from SME. It does following: + * 1) Initialize LIM, HAL, DPH + * 2) Configure the BSS for which the JOIN REQ was received + * a) Send WMA_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 WMA_ADD_BSS_RSP + * c) Send WMA_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 + * + * @Return: None + */ +static void lim_process_mlm_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg) +{ + tLimMlmJoinCnf mlmjoin_cnf; + uint8_t sessionid; + tpPESession session; + + sessionid = ((tpLimMlmJoinReq) msg)->sessionId; + + session = pe_find_session_by_session_id(mac_ctx, sessionid); + if (NULL == session) { + lim_log(mac_ctx, LOGE, FL("SessionId:%d does not exist"), + sessionid); + goto error; + } + + if ((!LIM_IS_AP_ROLE(session) && + !LIM_IS_BT_AMP_AP_ROLE(session)) && + ((session->limMlmState == eLIM_MLM_IDLE_STATE) || + (session->limMlmState == eLIM_MLM_JOINED_STATE)) && + (SIR_MAC_GET_ESS + (((tpLimMlmJoinReq) msg)->bssDescription.capabilityInfo) != + SIR_MAC_GET_IBSS(((tpLimMlmJoinReq) msg)->bssDescription. + capabilityInfo))) { + /* Hold onto Join request parameters */ + + session->pLimMlmJoinReq = (tpLimMlmJoinReq) msg; + if (is_lim_session_off_channel(mac_ctx, sessionid)) { + lim_log(mac_ctx, LOG1, + "SessionId:%d LimSession is on OffChannel", + sessionid); + /* suspend link */ + lim_log(mac_ctx, LOG1, + FL("Suspend link, sessionid %d is off channel"), + sessionid); + if (lim_is_link_suspended(mac_ctx)) { + lim_log(mac_ctx, LOGE, FL( + "link is already suspended, session %d" + ), sessionid); + goto error; + } + lim_process_mlm_post_join_suspend_link(mac_ctx, + CDF_STATUS_SUCCESS, (uint32_t *)session); + } else { + lim_log(mac_ctx, LOG1, FL("No need to Suspend link")); + /* + * No need to Suspend link as LimSession is not + * off channel, calling + * lim_process_mlm_post_join_suspend_link with + * status as SUCCESS. + */ + lim_log(mac_ctx, LOG1, + FL("SessionId:%d Join req on current chan"), + sessionid); + lim_process_mlm_post_join_suspend_link(mac_ctx, + CDF_STATUS_SUCCESS, (uint32_t *)session); + } + return; + } else { + /** + * Should not have received JOIN req in states other than + * Idle state or on AP. + * Return join confirm with invalid parameters code. + */ + lim_log(mac_ctx, LOGE, + FL("Session:%d Unexpected Join req, role %d state %X"), + session->peSessionId, GET_LIM_SYSTEM_ROLE(session), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState); + } + +error: + cdf_mem_free(msg); + if (session != NULL) + session->pLimMlmJoinReq = NULL; + mlmjoin_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + mlmjoin_cnf.sessionId = sessionid; + mlmjoin_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, + (uint32_t *)&mlmjoin_cnf); + +} + +/** + * lim_is_auth_req_expected() - check if auth request is expected + * + * @mac_ctx: global MAC context + * @session: PE session entry + * + * This function is called by lim_process_mlm_auth_req to check + * if auth request is expected. + * + * Return: true if expected and false otherwise + */ +static bool lim_is_auth_req_expected(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + bool flag = false; + + /* + * 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 + * address and requested authentication algorithm is + * supported. + */ + + flag = ((((LIM_IS_STA_ROLE(session) || + LIM_IS_BT_AMP_STA_ROLE(session)) && + ((session->limMlmState == eLIM_MLM_JOINED_STATE) || + (session->limMlmState == + eLIM_MLM_LINK_ESTABLISHED_STATE))) || + (LIM_IS_IBSS_ROLE(session) && + (session->limMlmState == + eLIM_MLM_BSS_STARTED_STATE))) && + (!lim_is_group_addr(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr)) + && lim_is_auth_algo_supported(mac_ctx, + mac_ctx->lim.gpLimMlmAuthReq->authType, session)); + + return flag; +} + +/** + * lim_is_preauth_ctx_exisits() - check if preauth context exists + * + * @mac_ctx: global MAC context + * @session: PE session entry + * @preauth_node_ptr: pointer to preauth node pointer + * + * This function is called by lim_process_mlm_auth_req to check + * if preauth context already exists + * + * Return: true if exists and false otherwise + */ +static bool lim_is_preauth_ctx_exists(tpAniSirGlobal mac_ctx, + tpPESession session, + struct tLimPreAuthNode **preauth_node_ptr) +{ + bool fl = false; + struct tLimPreAuthNode *preauth_node; + tpDphHashNode stads; + tSirMacAddr curr_bssid; + + preauth_node = *preauth_node_ptr; + sir_copy_mac_addr(curr_bssid, session->bssId); + stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session->dph.dphHashTable); + preauth_node = lim_search_pre_auth_list(mac_ctx, + mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr); + + fl = (((LIM_IS_STA_ROLE(session) || LIM_IS_BT_AMP_STA_ROLE(session)) && + (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) && + ((stads != NULL) && + (mac_ctx->lim.gpLimMlmAuthReq->authType == + stads->mlmStaContext.authType)) && + (cdf_mem_compare(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr, + curr_bssid, sizeof(tSirMacAddr)))) || + ((preauth_node != NULL) && + (preauth_node->authType == + mac_ctx->lim.gpLimMlmAuthReq->authType))); + + return fl; +} + +/** + * lim_process_mlm_auth_req() - process lim auth request + * + * @mac_ctx: global MAC context + * @msg: MLM auth request message + * + * This function is called to process MLM_AUTH_REQ message from SME + * + * @Return: None + */ +static void lim_process_mlm_auth_req(tpAniSirGlobal mac_ctx, uint32_t *msg) +{ + uint32_t num_preauth_ctx; + tSirMacAddr curr_bssid; + tSirMacAuthFrameBody auth_frame_body; + tLimMlmAuthCnf mlm_auth_cnf; + struct tLimPreAuthNode *preauth_node = NULL; + uint8_t session_id; + tpPESession session; + + if (msg == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + mac_ctx->lim.gpLimMlmAuthReq = (tLimMlmAuthReq *) msg; + session_id = mac_ctx->lim.gpLimMlmAuthReq->sessionId; + session = pe_find_session_by_session_id(mac_ctx, session_id); + if (NULL == session) { + lim_log(mac_ctx, LOGP, FL("SessionId:%d does not exist"), + session_id); + return; + } + + lim_log(mac_ctx, LOG1, FL("Process Auth Req sessionID %d Systemrole %d" + "mlmstate %d from: " MAC_ADDRESS_STR + " with authtype %d"), session_id, + GET_LIM_SYSTEM_ROLE(session), session->limMlmState, + MAC_ADDR_ARRAY(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr), + mac_ctx->lim.gpLimMlmAuthReq->authType); + + sir_copy_mac_addr(curr_bssid, session->bssId); + + if (!lim_is_auth_req_expected(mac_ctx, session)) { + /* + * Unexpected auth request. + * Return Auth confirm with Invalid parameters code. + */ + mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + /* + * 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_preauth_ctx_exists(mac_ctx, session, &preauth_node)) { + lim_log(mac_ctx, LOG2, + FL("Already have pre-auth context with peer: " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr)); + mlm_auth_cnf.resultCode = (tSirResultCodes) + eSIR_MAC_SUCCESS_STATUS; + goto end; + } else { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_MAX_NUM_PRE_AUTH, + (uint32_t *) &num_preauth_ctx) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Could not retrieve NumPreAuthLimit from CFG")); + + if (mac_ctx->lim.gLimNumPreAuthContexts == num_preauth_ctx) { + lim_log(mac_ctx, LOGW, + FL("Number of pre-auth reached max limit")); + /* Return Auth confirm with reject code */ + mlm_auth_cnf.resultCode = + eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED; + goto end; + } + } + + /* Delete pre-auth node if exists */ + if (preauth_node) + lim_delete_pre_auth_node(mac_ctx, + mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr); + + session->limPrevMlmState = session->limMlmState; + session->limMlmState = eLIM_MLM_WT_AUTH_FRAME2_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId, + session->limMlmState)); + + /* Prepare & send Authentication frame */ + auth_frame_body.authAlgoNumber = + (uint8_t) mac_ctx->lim.gpLimMlmAuthReq->authType; + auth_frame_body.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + auth_frame_body.authStatusCode = 0; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_START_EVENT, session, + eSIR_SUCCESS, auth_frame_body.authStatusCode); +#endif + + lim_send_auth_mgmt_frame(mac_ctx, + &auth_frame_body, mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr, + LIM_NO_WEP_IN_FC, session); + + /* assign appropriate session_id to the timer object */ + mac_ctx->lim.limTimers.gLimAuthFailureTimer.sessionId = session_id; + + /* Activate Auth failure timer */ + MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, + session->peSessionId, eLIM_AUTH_FAIL_TIMER)); + if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimAuthFailureTimer) + != TX_SUCCESS) { + /* Could not start Auth failure timer. */ + lim_log(mac_ctx, LOGP, + FL("could not start Auth failure timer")); + /* Cleanup as if auth timer expired */ + lim_process_auth_failure_timeout(mac_ctx); + } + return; +end: + cdf_mem_copy((uint8_t *) &mlm_auth_cnf.peerMacAddr, + (uint8_t *) &mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr, + sizeof(tSirMacAddr)); + + mlm_auth_cnf.authType = mac_ctx->lim.gpLimMlmAuthReq->authType; + mlm_auth_cnf.sessionId = session_id; + + cdf_mem_free(mac_ctx->lim.gpLimMlmAuthReq); + mac_ctx->lim.gpLimMlmAuthReq = NULL; + lim_log(mac_ctx, LOG1, "SessionId:%d LimPostSme LIM_MLM_AUTH_CNF ", + session_id); + lim_post_sme_message(mac_ctx, LIM_MLM_AUTH_CNF, + (uint32_t *) &mlm_auth_cnf); +} + +/** + * lim_process_mlm_assoc_req() - This function is called to process + * MLM_ASSOC_REQ message from SME + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the MLM message buffer + * + * This function is called to process MLM_ASSOC_REQ message from SME + * + * @Return None + */ + +static void lim_process_mlm_assoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tSirMacAddr curr_bssId; + tLimMlmAssocReq *mlm_assoc_req; + tLimMlmAssocCnf mlm_assoc_cnf; + tpPESession session_entry; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + mlm_assoc_req = (tLimMlmAssocReq *) msg_buf; + session_entry = pe_find_session_by_session_id(mac_ctx, + mlm_assoc_req->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGP, + FL("SessionId:%d Session Does not exist"), + mlm_assoc_req->sessionId); + cdf_mem_free(mlm_assoc_req); + return; + } + + sir_copy_mac_addr(curr_bssId, session_entry->bssId); + + if (!((!LIM_IS_AP_ROLE(session_entry) && + !LIM_IS_BT_AMP_AP_ROLE(session_entry)) && + (session_entry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE || + session_entry->limMlmState == eLIM_MLM_JOINED_STATE) && + (cdf_mem_compare(mlm_assoc_req->peerMacAddr, + curr_bssId, sizeof(tSirMacAddr))))) { + /* + * 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. + */ + lim_log(mac_ctx, LOGW, + FL("received unexpected MLM_ASSOC_CNF in state %X for role=%d, MAC addr= " + MAC_ADDRESS_STR), session_entry->limMlmState, + GET_LIM_SYSTEM_ROLE(session_entry), + MAC_ADDR_ARRAY(mlm_assoc_req->peerMacAddr)); + lim_print_mlm_state(mac_ctx, LOGW, session_entry->limMlmState); + mlm_assoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + goto end; + } + + /* map the session entry pointer to the AssocFailureTimer */ + mac_ctx->lim.limTimers.gLimAssocFailureTimer.sessionId = + mlm_assoc_req->sessionId; +#ifdef WLAN_FEATURE_11W + /* + * Store current MLM state in case ASSOC response returns with + * TRY_AGAIN_LATER return code. + */ + if (session_entry->limRmfEnabled) { + session_entry->pmfComebackTimerInfo.limPrevMlmState = + session_entry->limPrevMlmState; + session_entry->pmfComebackTimerInfo.limMlmState = + session_entry->limMlmState; + } +#endif /* WLAN_FEATURE_11W */ + + session_entry->limPrevMlmState = session_entry->limMlmState; + session_entry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + session_entry->limMlmState)); + lim_log(mac_ctx, LOG1, FL("SessionId:%d Sending Assoc_Req Frame"), + session_entry->peSessionId); + + /* Prepare and send Association request frame */ + lim_send_assoc_req_mgmt_frame(mac_ctx, mlm_assoc_req, session_entry); + + /* + * Set the link state to postAssoc, so HW can start receiving frames + * from AP. + */ + if ((session_entry->bssType == eSIR_BTAMP_STA_MODE) || + ((session_entry->bssType == eSIR_BTAMP_AP_MODE) + && LIM_IS_BT_AMP_STA_ROLE(session_entry))) { + if (lim_set_link_state(mac_ctx, eSIR_LINK_BTAMP_POSTASSOC_STATE, + curr_bssId, session_entry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("Failed to set the LinkState")); + } + /* Start association failure timer */ + MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, + session_entry->peSessionId, eLIM_ASSOC_FAIL_TIMER)); + if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimAssocFailureTimer) + != TX_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("SessionId:%d couldn't start Assoc failure timer"), + session_entry->peSessionId); + /* Cleanup as if assoc timer expired */ + lim_process_assoc_failure_timeout(mac_ctx, LIM_ASSOC); + } + + return; +end: + /* Update PE session Id */ + mlm_assoc_cnf.sessionId = mlm_assoc_req->sessionId; + /* Free up buffer allocated for assocReq */ + cdf_mem_free(mlm_assoc_req); + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF, + (uint32_t *) &mlm_assoc_cnf); +} + +/** + * lim_process_mlm_reassoc_req() - process mlm reassoc request. + * + * @mac_ctx: pointer to Global MAC structure + * @msg: pointer to the MLM message buffer + * + * This function is called to process MLM_REASSOC_REQ message + * from SME + * + * Return: None + */ +static void lim_process_mlm_reassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg) +{ + uint8_t channel, sec_ch_offset; + struct tLimPreAuthNode *auth_node; + tLimMlmReassocReq *reassoc_req; + tLimMlmReassocCnf reassoc_cnf; + tpPESession session; + + if (msg == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + reassoc_req = (tLimMlmReassocReq *) msg; + session = pe_find_session_by_session_id(mac_ctx, + reassoc_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("Session Does not exist for given sessionId %d"), + reassoc_req->sessionId); + cdf_mem_free(reassoc_req); + return; + } + + lim_log(mac_ctx, LOG1, + FL("Process ReAssoc Req on sessionID %d Systemrole %d mlmstate %d from: " MAC_ADDRESS_STR), + reassoc_req->sessionId, GET_LIM_SYSTEM_ROLE(session), + session->limMlmState, MAC_ADDR_ARRAY(reassoc_req->peerMacAddr)); + + if ((LIM_IS_AP_ROLE(session) || + LIM_IS_BT_AMP_AP_ROLE(session)) || + (session->limMlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE)) { + /* + * Received Reassoc request in invalid state or + * in AP role.Return Reassoc confirm with Invalid + * parameters code. + */ + + lim_log(mac_ctx, LOGW, + FL("received unexpected MLM_REASSOC_CNF in state %X for role=%d, MAC addr= " MAC_ADDRESS_STR), + session->limMlmState, GET_LIM_SYSTEM_ROLE(session), + MAC_ADDR_ARRAY(reassoc_req->peerMacAddr)); + lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState); + reassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + goto end; + } + + if (session->pLimMlmReassocReq) + cdf_mem_free(session->pLimMlmReassocReq); + + /* + * Hold Re-Assoc request as part of Session, knock-out mac_ctx + * Hold onto Reassoc request parameters + */ + session->pLimMlmReassocReq = reassoc_req; + + /* See if we have pre-auth context with new AP */ + auth_node = lim_search_pre_auth_list(mac_ctx, session->limReAssocbssId); + + if (!auth_node && (!cdf_mem_compare(reassoc_req->peerMacAddr, + session->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 + */ + reassoc_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED; + reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + + goto end; + } + /* assign the sessionId to the timer object */ + mac_ctx->lim.limTimers.gLimReassocFailureTimer.sessionId = + reassoc_req->sessionId; + session->limPrevMlmState = session->limMlmState; + session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId, + session->limMlmState)); + + /* Derive channel from BSS description and store it at CFG. */ + channel = session->limReassocChannelId; + sec_ch_offset = session->reAssocHtSecondaryChannelOffset; + + /* Apply previously set configuration at HW */ + lim_apply_configuration(mac_ctx, session); + + /* store the channel switch sessionEntry in the lim global var */ + session->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_REASSOC; + + /* Switch channel to the new Operating channel for Reassoc */ + lim_set_channel(mac_ctx, channel, + session->ch_center_freq_seg0, + session->ch_center_freq_seg1, + session->ch_width, + session->maxTxPower, + session->peSessionId); + + return; +end: + reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE sessio Id */ + reassoc_cnf.sessionId = reassoc_req->sessionId; + /* Free up buffer allocated for reassocReq */ + cdf_mem_free(reassoc_req); + session->pLimReAssocReq = NULL; + lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF, + (uint32_t *) &reassoc_cnf); +} + +/** + * lim_process_mlm_disassoc_req_ntf() - process disassoc request notification + * + * @mac_ctx: global MAC context + * @suspend_status: suspend status + * @msg: mlm message buffer + * + * This function is used to process MLM disassoc notification + * + * Return: None + */ +static void +lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, + CDF_STATUS suspend_status, uint32_t *msg) +{ + uint16_t aid; + tSirMacAddr curr_bssid; + tpDphHashNode stads; + tLimMlmDisassocReq *mlm_disassocreq; + tLimMlmDisassocCnf mlm_disassoccnf; + tpPESession session; + extern bool send_disassoc_frame; + tLimMlmStates mlm_state; + + if (CDF_STATUS_SUCCESS != suspend_status) + lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"), + suspend_status); + + mlm_disassocreq = (tLimMlmDisassocReq *) msg; + + session = pe_find_session_by_session_id(mac_ctx, + mlm_disassocreq->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId %d"), + mlm_disassocreq->sessionId); + mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + lim_log(mac_ctx, LOG1, + FL("Process DisAssoc Req on sessionID %d Systemrole %d" + "mlmstate %d from: " MAC_ADDRESS_STR), + mlm_disassocreq->sessionId, GET_LIM_SYSTEM_ROLE(session), + session->limMlmState, + MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + + sir_copy_mac_addr(curr_bssid, session->bssId); + + switch (GET_LIM_SYSTEM_ROLE(session)) { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + if (!cdf_mem_compare(mlm_disassocreq->peerMacAddr, + curr_bssid, sizeof(tSirMacAddr))) { + lim_log(mac_ctx, LOGW, + FL("received MLM_DISASSOC_REQ with invalid BSS id")); + lim_print_mac_addr(mac_ctx, + mlm_disassocreq->peerMacAddr, LOGW); + + /* Prepare and Send LIM_MLM_DISASSOC_CNF */ + mlm_disassoccnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } + break; + case eLIM_STA_IN_IBSS_ROLE: + break; + case eLIM_AP_ROLE: + case eLIM_P2P_DEVICE_GO: + if (true == + mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) { + lim_log(mac_ctx, LOGE, + FL("CAC timer is running, drop disassoc from going out")); + mlm_disassoccnf.resultCode = eSIR_SME_SUCCESS; + goto end; + } + break; + default: + break; + } /* end switch (GET_LIM_SYSTEM_ROLE(session)) */ + + /* + * Check if there exists a context for the peer entity + * to be disassociated with. + */ + stads = dph_lookup_hash_entry(mac_ctx, mlm_disassocreq->peerMacAddr, + &aid, &session->dph.dphHashTable); + if (stads) + mlm_state = stads->mlmStaContext.mlmState; + + if ((stads == NULL) || + (stads && + ((mlm_state != eLIM_MLM_LINK_ESTABLISHED_STATE) && + (mlm_state != eLIM_MLM_WT_ASSOC_CNF_STATE) && + (mlm_state != eLIM_MLM_ASSOCIATED_STATE)))) { + /* + * Received LIM_MLM_DISASSOC_REQ for STA that does not + * have context or in some transit state. + */ + lim_log(mac_ctx, LOGW, + FL("Invalid MLM_DISASSOC_REQ, Addr= " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + if (stads != NULL) + lim_log(mac_ctx, LOGE, FL("Sta MlmState : %d"), + stads->mlmStaContext.mlmState); + + /* Prepare and Send LIM_MLM_DISASSOC_CNF */ + mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + stads->mlmStaContext.disassocReason = (tSirMacReasonCodes) + mlm_disassocreq->reasonCode; + stads->mlmStaContext.cleanupTrigger = mlm_disassocreq->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 + */ + + stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + + /* Send Disassociate frame to peer entity */ + if (send_disassoc_frame && (mlm_disassocreq->reasonCode != + eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = + mlm_disassocreq; + /* + * 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 + */ + stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + + /* + * If the reason for disassociation is inactivity of STA, then + * dont wait for acknowledgement + */ + if ((mlm_disassocreq->reasonCode == + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON) && + LIM_IS_AP_ROLE(session)) { + lim_send_disassoc_mgmt_frame(mac_ctx, + mlm_disassocreq->reasonCode, + mlm_disassocreq->peerMacAddr, session, false); + + /* Send Disassoc CNF and receive path cleanup */ + lim_send_disassoc_cnf(mac_ctx); + } else { + lim_send_disassoc_mgmt_frame(mac_ctx, + mlm_disassocreq->reasonCode, + mlm_disassocreq->peerMacAddr, session, true); + /* + * Abort Tx so that data frames won't be sent to the AP + * after sending Disassoc. + */ + if (LIM_IS_STA_ROLE(session)) + wma_tx_abort(session->smeSessionId); + } + } else { + /* Disassoc frame is not sent OTA */ + send_disassoc_frame = 1; + /* Receive path cleanup with dummy packet */ + if (eSIR_SUCCESS != + lim_cleanup_rx_path(mac_ctx, stads, session)) { + mlm_disassoccnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + /* Free up buffer allocated for mlmDisassocReq */ + cdf_mem_free(mlm_disassocreq); + } + + return; + +end: + cdf_mem_copy((uint8_t *) &mlm_disassoccnf.peerMacAddr, + (uint8_t *) mlm_disassocreq->peerMacAddr, + sizeof(tSirMacAddr)); + mlm_disassoccnf.aid = mlm_disassocreq->aid; + mlm_disassoccnf.disassocTrigger = mlm_disassocreq->disassocTrigger; + + /* Update PE session ID */ + mlm_disassoccnf.sessionId = mlm_disassocreq->sessionId; + + /* Free up buffer allocated for mlmDisassocReq */ + cdf_mem_free(mlm_disassocreq); + + lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF, + (uint32_t *) &mlm_disassoccnf); +} + +/** + * lim_check_disassoc_deauth_ack_pending() - check if deauth is pending + * + * @mac_ctx - global MAC context + * @sta_mac - station MAC + * + * This function checks if diassociation or deauthentication is pending for + * given station MAC address. + * + * Return: true if pending and false otherwise. + */ +bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal mac_ctx, + uint8_t *sta_mac) +{ + tLimMlmDisassocReq *disassoc_req; + tLimMlmDeauthReq *deauth_req; + + disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if ((disassoc_req && (cdf_mem_compare((uint8_t *) sta_mac, + (uint8_t *) &disassoc_req->peerMacAddr, + sizeof(tSirMacAddr)))) || + (deauth_req && (cdf_mem_compare((uint8_t *) sta_mac, + (uint8_t *) &deauth_req->peerMacAddr, + sizeof(tSirMacAddr))))) { + PELOG1(lim_log(mac_ctx, LOG1, + FL("Disassoc/Deauth ack pending"));) + return true; + } else { + PELOG1(lim_log(mac_ctx, LOG1, + FL("Disassoc/Deauth Ack not pending"));) + return false; + } +} + +/* + * lim_clean_up_disassoc_deauth_req() - cleans up pending disassoc or deauth req + * + * @mac_ctx: mac_ctx + * @sta_mac: sta mac address + * @clean_rx_path: flag to indicate whether to cleanup rx path or not + * + * This function cleans up pending disassoc or deauth req + * + * Return: void + */ +void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal mac_ctx, + uint8_t *sta_mac, bool clean_rx_path) +{ + tLimMlmDisassocReq *mlm_disassoc_req; + tLimMlmDeauthReq *mlm_deauth_req; + mlm_disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + if (mlm_disassoc_req && + (cdf_mem_compare((uint8_t *) sta_mac, + (uint8_t *) &mlm_disassoc_req->peerMacAddr, + sizeof(tSirMacAddr)))) { + if (clean_rx_path) { + lim_process_disassoc_ack_timeout(mac_ctx); + } else { + if (tx_timer_running( + &mac_ctx->lim.limTimers.gLimDisassocAckTimer)) { + lim_deactivate_and_change_timer(mac_ctx, + eLIM_DISASSOC_ACK_TIMER); + } + cdf_mem_free(mlm_disassoc_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = + NULL; + } + } + + mlm_deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (mlm_deauth_req && + (cdf_mem_compare((uint8_t *) sta_mac, + (uint8_t *) &mlm_deauth_req->peerMacAddr, + sizeof(tSirMacAddr)))) { + if (clean_rx_path) { + lim_process_deauth_ack_timeout(mac_ctx); + } else { + if (tx_timer_running( + &mac_ctx->lim.limTimers.gLimDeauthAckTimer)) { + lim_deactivate_and_change_timer(mac_ctx, + eLIM_DEAUTH_ACK_TIMER); + } + cdf_mem_free(mlm_deauth_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = + NULL; + } + } +} + +/* + * lim_process_disassoc_ack_timeout() - wrapper function around + * lim_send_disassoc_cnf + * + * @mac_ctx: mac_ctx + * + * wrapper function around lim_send_disassoc_cnf + * + * Return: void + */ +void lim_process_disassoc_ack_timeout(tpAniSirGlobal mac_ctx) +{ + lim_log(mac_ctx, LOG1, FL("")); + lim_send_disassoc_cnf(mac_ctx); +} + +/** + * lim_process_mlm_disassoc_req() - This function is called to process + * MLM_DISASSOC_REQ message from SME + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the MLM message buffer + * + * This function is called to process MLM_DISASSOC_REQ message from SME + * + * @Return: None + */ +static void +lim_process_mlm_disassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tLimMlmDisassocReq *mlm_disassoc_req; + tpPESession session; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, + FL("Buffer is Pointing to NULL")); + return; + } + + mlm_disassoc_req = (tLimMlmDisassocReq *) msg_buf; + lim_log(mac_ctx, LOG1, + FL("Process disassoc req, sessionID %d from: "MAC_ADDRESS_STR), + mlm_disassoc_req->sessionId, + MAC_ADDR_ARRAY(mlm_disassoc_req->peerMacAddr)); + + session = pe_find_session_by_session_id(mac_ctx, + mlm_disassoc_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId %d"), + mlm_disassoc_req->sessionId); + return; + } + + lim_process_mlm_disassoc_req_ntf(mac_ctx, CDF_STATUS_SUCCESS, + (uint32_t *) msg_buf); +} + +/** + * lim_process_mlm_deauth_req_ntf() - This function is process mlm deauth req + * notification + * + * @mac_ctx: Pointer to Global MAC structure + * @suspend_status: suspend status + * @msg_buf: A pointer to the MLM message buffer + * + * This function is process mlm deauth req notification + * + * @Return: None + */ +static void +lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, + CDF_STATUS suspend_status, uint32_t *msg_buf) +{ + uint16_t aid; + tSirMacAddr curr_bssId; + tpDphHashNode sta_ds; + struct tLimPreAuthNode *auth_node; + tLimMlmDeauthReq *mlm_deauth_req; + tLimMlmDeauthCnf mlm_deauth_cnf; + tpPESession session; + + if (CDF_STATUS_SUCCESS != suspend_status) + lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"), + suspend_status); + + mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf; + session = pe_find_session_by_session_id(mac_ctx, + mlm_deauth_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId %d"), + mlm_deauth_req->sessionId); + cdf_mem_free(mlm_deauth_req); + return; + } + lim_log(mac_ctx, LOG1, FL("Process Deauth Req on sessionID %d Systemrole %d" + "mlmstate %d from: " MAC_ADDRESS_STR), + mlm_deauth_req->sessionId, + GET_LIM_SYSTEM_ROLE(session), + session->limMlmState, + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + sir_copy_mac_addr(curr_bssId, session->bssId); + + switch (GET_LIM_SYSTEM_ROLE(session)) { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + switch (session->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 (!cdf_mem_compare(mlm_deauth_req->peerMacAddr, + curr_bssId, sizeof(tSirMacAddr))) { + lim_log(mac_ctx, LOGE, + FL("received MLM_DEAUTH_REQ with invalid BSS id " + "Peer MAC: "MAC_ADDRESS_STR + " CFG BSSID Addr : "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY( + mlm_deauth_req->peerMacAddr), + MAC_ADDR_ARRAY(curr_bssId)); + /* Prepare and Send LIM_MLM_DEAUTH_CNF */ + mlm_deauth_cnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + if ((session->limMlmState == + eLIM_MLM_AUTHENTICATED_STATE) || + (session->limMlmState == + eLIM_MLM_WT_ASSOC_RSP_STATE)) { + /* Send deauth frame to peer entity */ + lim_send_deauth_mgmt_frame(mac_ctx, + mlm_deauth_req->reasonCode, + mlm_deauth_req->peerMacAddr, + session, false); + /* Prepare and Send LIM_MLM_DEAUTH_CNF */ + mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; + session->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, + session->limMlmState)); + goto end; + } + break; + default: + lim_log(mac_ctx, LOGW, + FL("received MLM_DEAUTH_REQ with in state %d for peer " + MAC_ADDRESS_STR), + session->limMlmState, + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + lim_print_mlm_state(mac_ctx, LOGW, + session->limMlmState); + /* Prepare and Send LIM_MLM_DEAUTH_CNF */ + mlm_deauth_cnf.resultCode = + eSIR_SME_STA_NOT_AUTHENTICATED; + + goto end; + } + break; + case eLIM_STA_IN_IBSS_ROLE: + lim_log(mac_ctx, LOGE, FL("received MLM_DEAUTH_REQ IBSS Mode")); + mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + case eLIM_AP_ROLE: + case eLIM_P2P_DEVICE_GO: + if (true == + mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) { + lim_log(mac_ctx, LOGE, + FL("CAC timer is running, drop disassoc from going out")); + mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; + goto end; + } + break; + + default: + break; + } /* end switch (GET_LIM_SYSTEM_ROLE(session)) */ + + /* + * Check if there exists a context for the peer entity + * to be deauthenticated with. + */ + sta_ds = dph_lookup_hash_entry(mac_ctx, mlm_deauth_req->peerMacAddr, + &aid, &session->dph.dphHashTable); + + if (sta_ds == NULL) { + /* Check if there exists pre-auth context for this STA */ + auth_node = lim_search_pre_auth_list(mac_ctx, + mlm_deauth_req->peerMacAddr); + if (auth_node == NULL) { + /* + * Received DEAUTH REQ for a STA that is neither + * Associated nor Pre-authenticated. Log error, + * Prepare and Send LIM_MLM_DEAUTH_CNF + */ + lim_log(mac_ctx, LOGW, + FL("received MLM_DEAUTH_REQ in mlme state %d for STA that " + "does not have context, Addr=" + MAC_ADDRESS_STR), + session->limMlmState, + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + mlm_deauth_cnf.resultCode = + eSIR_SME_STA_NOT_AUTHENTICATED; + } else { + mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; + /* Delete STA from pre-auth STA list */ + lim_delete_pre_auth_node(mac_ctx, + mlm_deauth_req->peerMacAddr); + /* Send Deauthentication frame to peer entity */ + lim_send_deauth_mgmt_frame(mac_ctx, + mlm_deauth_req->reasonCode, + mlm_deauth_req->peerMacAddr, + session, false); + } + goto end; + } else if ((sta_ds->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (sta_ds->mlmStaContext.mlmState != + eLIM_MLM_WT_ASSOC_CNF_STATE)) { + /* + * received MLM_DEAUTH_REQ for STA that either has no context or + * in some transit state + */ + lim_log(mac_ctx, LOGW, + FL("Invalid MLM_DEAUTH_REQ, Addr="MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + /* Prepare and Send LIM_MLM_DEAUTH_CNF */ + mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + /* sta_ds->mlmStaContext.rxPurgeReq = 1; */ + sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes) + mlm_deauth_req->reasonCode; + sta_ds->mlmStaContext.cleanupTrigger = mlm_deauth_req->deauthTrigger; + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req; + /* + * 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. + */ + sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + /* Send Deauthentication frame to peer entity */ + lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode, + mlm_deauth_req->peerMacAddr, session, true); + return; +end: + cdf_mem_copy((uint8_t *) &mlm_deauth_cnf.peerMacAddr, + (uint8_t *) mlm_deauth_req->peerMacAddr, + sizeof(tSirMacAddr)); + mlm_deauth_cnf.deauthTrigger = mlm_deauth_req->deauthTrigger; + mlm_deauth_cnf.aid = mlm_deauth_req->aid; + mlm_deauth_cnf.sessionId = mlm_deauth_req->sessionId; + + /* Free up buffer allocated for mlmDeauthReq */ + cdf_mem_free(mlm_deauth_req); + lim_post_sme_message(mac_ctx, + LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlm_deauth_cnf); +} + +/* + * lim_process_deauth_ack_timeout() - wrapper function around + * lim_send_deauth_cnf + * + * @mac_ctx: mac_ctx + * + * wrapper function around lim_send_deauth_cnf + * + * Return: void + */ +void lim_process_deauth_ack_timeout(tpAniSirGlobal mac_ctx) +{ + lim_log(mac_ctx, LOG1, FL("")); + lim_send_deauth_cnf(mac_ctx); +} + +/* + * lim_process_mlm_deauth_req() - This function is called to process + * MLM_DEAUTH_REQ message from SME + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the MLM message buffer + * + * This function is called to process MLM_DEAUTH_REQ message from SME + * + * @Return: None + */ +static void +lim_process_mlm_deauth_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tLimMlmDeauthReq *mlm_deauth_req; + tpPESession session; + + if (msg_buf == NULL) { + PELOGE(lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + + mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf; + lim_log(mac_ctx, LOG1, + FL("Process Deauth Req on sessionID %d from: " + MAC_ADDRESS_STR), + mlm_deauth_req->sessionId, + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + + session = pe_find_session_by_session_id(mac_ctx, + mlm_deauth_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId %d"), + mlm_deauth_req->sessionId); + return; + } + lim_process_mlm_deauth_req_ntf(mac_ctx, CDF_STATUS_SUCCESS, + (uint32_t *) msg_buf); +} + +/** + * lim_process_mlm_set_keys_req() - This function is called to process + * MLM_SETKEYS_REQ message from SME + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the MLM message buffer + * + * This function is called to process MLM_SETKEYS_REQ message from SME + * + * @Return: None + */ +static void +lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + uint16_t aid; + uint16_t sta_idx = 0; + uint32_t default_key_id = 0; + tSirMacAddr curr_bssid; + tpDphHashNode sta_ds; + tLimMlmSetKeysReq *mlm_set_keys_req; + tLimMlmSetKeysCnf mlm_set_keys_cnf; + tpPESession session; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + mlm_set_keys_req = (tLimMlmSetKeysReq *) msg_buf; + /* Hold onto the SetKeys request parameters */ + mac_ctx->lim.gpLimMlmSetKeysReq = (void *)mlm_set_keys_req; + session = pe_find_session_by_session_id(mac_ctx, + mlm_set_keys_req->sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId")); + return; + } + + lim_log(mac_ctx, LOGW, + FL("Received MLM_SETKEYS_REQ with parameters:" + "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "), + mlm_set_keys_req->aid, mlm_set_keys_req->edType, + mlm_set_keys_req->numKeys); + lim_print_mac_addr(mac_ctx, mlm_set_keys_req->peerMacAddr, LOGW); + sir_copy_mac_addr(curr_bssid, session->bssId); + + switch (GET_LIM_SYSTEM_ROLE(session)) { + 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 ((!lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) && + (!cdf_mem_compare(mlm_set_keys_req->peerMacAddr, + curr_bssid, sizeof(tSirMacAddr)))) { + lim_log(mac_ctx, LOGW, + FL("Received MLM_SETKEYS_REQ with invalid BSSID" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr)); + /* + * Prepare and Send LIM_MLM_SETKEYS_CNF with error code + */ + mlm_set_keys_cnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } +#endif + break; + case eLIM_STA_IN_IBSS_ROLE: + /* + * update the IBSS PE session encrption type based on the + * key type + */ + session->encryptType = mlm_set_keys_req->edType; + break; + default: + break; + } + + /* + * Use the "unicast" parameter to determine if the "Group Keys" + * are being set. + * mlm_set_keys_req->key.unicast = 0 -> Multicast/broadcast + * mlm_set_keys_req->key.unicast - 1 -> Unicast keys are being set + */ + if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) { + lim_log(mac_ctx, LOG1, FL("Trying to set Group Keys...%d "), + mlm_set_keys_req->sessionId); + /* + * When trying to set Group Keys for any security mode other + * than WEP, use the STA Index corresponding to the AP... + */ + switch (mlm_set_keys_req->edType) { + case eSIR_ED_CCMP: +#ifdef WLAN_FEATURE_11W + case eSIR_ED_AES_128_CMAC: +#endif + sta_idx = session->staId; + break; + default: + break; + } + } else { + lim_log(mac_ctx, LOG1, FL("Trying to set Unicast Keys...")); + /* + * Check if there exists a context for the + * peer entity for which keys need to be set. + */ + sta_ds = dph_lookup_hash_entry(mac_ctx, + mlm_set_keys_req->peerMacAddr, &aid, + &session->dph.dphHashTable); + if ((sta_ds == NULL) || + ((sta_ds->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && + !LIM_IS_AP_ROLE(session))) { + /* + * Received LIM_MLM_SETKEYS_REQ for STA that does not + * have context or in some transit state. + */ + lim_log(mac_ctx, LOG1, + FL("Invalid MLM_SETKEYS_REQ, Addr = " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr)); + /* Prepare and Send LIM_MLM_SETKEYS_CNF */ + mlm_set_keys_cnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } else { + sta_idx = sta_ds->staIndex; + } + } + + if ((mlm_set_keys_req->numKeys == 0) + && (mlm_set_keys_req->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 + */ + default_key_id = 0xff; + } else if (mlm_set_keys_req->key[0].keyId && + ((mlm_set_keys_req->edType == eSIR_ED_WEP40) || + (mlm_set_keys_req->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 + */ + default_key_id = mlm_set_keys_req->key[0].keyId; + } else { + default_key_id = 0; + } + lim_log(mac_ctx, LOG1, + FL("Trying to set keys for STA Index [%d], using default_key_id [%d]"), + sta_idx, default_key_id); + + if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) { + session->limPrevMlmState = session->limMlmState; + session->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, session->limMlmState)); + lim_log(mac_ctx, LOG1, FL("Trying to set Group Keys...%d "), + session->peSessionId); + /* Package WMA_SET_BSSKEY_REQ message parameters */ + lim_send_set_bss_key_req(mac_ctx, mlm_set_keys_req, session); + return; + } else { + /* + * Package WMA_SET_STAKEY_REQ / WMA_SET_STA_BCASTKEY_REQ message + * parameters + */ + lim_send_set_sta_key_req(mac_ctx, mlm_set_keys_req, sta_idx, + (uint8_t) default_key_id, session, + true); + return; + } +end: + mlm_set_keys_cnf.sessionId = mlm_set_keys_req->sessionId; + lim_post_sme_set_keys_cnf(mac_ctx, mlm_set_keys_req, &mlm_set_keys_cnf); +} + +/** + * lim_process_periodic_probe_req_timer() - This function is called to process + * periodic probe request to send during scan. + * + * @mac_ctx: Pointer to Global MAC structure + * + * This function is called to process periodic probe request to send during scan + * + * @Return None + */ +static void lim_process_periodic_probe_req_timer(tpAniSirGlobal mac_ctx) +{ + uint8_t channel_num; + uint8_t i = 0; + tLimMlmScanReq *mlm_scan_req; + tSirRetStatus status = eSIR_SUCCESS; + TX_TIMER *probe_req_timer = + &mac_ctx->lim.limTimers.gLimPeriodicProbeReqTimer; + + if (cdf_mc_timer_get_current_state(&probe_req_timer->cdf_timer) + != CDF_TIMER_STATE_STOPPED) { + lim_log(mac_ctx, LOG1, FL("Invalid state of timer")); + return; + } + + if (!((mac_ctx->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) + && (probe_req_timer->sessionId != 0xff) + && (mac_ctx->lim.probeCounter < mac_ctx->lim.maxProbe))) { + lim_log(mac_ctx, LOG1, + FL("received unexpected Periodic scan timeout in state %X"), + mac_ctx->lim.gLimMlmState); + return; + } + + mlm_scan_req = mac_ctx->lim.gpLimMlmScanReq; + lim_log(mac_ctx, LOG1, FL("Scanning : Periodic scanning")); + mac_ctx->lim.probeCounter++; + /* Periodic channel timer timed out to send probe request. */ + channel_num = lim_get_current_scan_channel(mac_ctx); + do { + /* + * Prepare and send Probe Request frame for all the SSIDs + * present in the saved MLM + */ + status = lim_send_probe_req_mgmt_frame(mac_ctx, + &mlm_scan_req->ssId[i], mlm_scan_req->bssId, + channel_num, mac_ctx->lim.gSelfMacAddr, + mlm_scan_req->dot11mode, + mlm_scan_req->uIEFieldLen, + (uint8_t *) (mlm_scan_req) + + mlm_scan_req->uIEFieldOffset); + if (status != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("send ProbeReq failed for SSID %s on channel: %d"), + mlm_scan_req->ssId[i].ssId, channel_num); + return; + } + i++; + } while (i < mlm_scan_req->numSsid); + /* Activate timer again */ + MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, + probe_req_timer->sessionId, + eLIM_PERIODIC_PROBE_REQ_TIMER)); + if (tx_timer_activate(probe_req_timer) != TX_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("could not start periodic probe req timer")); + return; + } +} + +/** + * lim_process_join_failure_timeout() - This function is called to process + * JoinFailureTimeout + * + * @mac_ctx: Pointer to Global MAC structure + * + * This function is called to process JoinFailureTimeout + * + * @Return None + */ +static void lim_process_join_failure_timeout(tpAniSirGlobal mac_ctx) +{ + tLimMlmJoinCnf mlm_join_cnf; + uint32_t len; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + host_log_rssi_pkt_type *rssi_log = NULL; +#endif + tpPESession session; + + session = pe_find_session_by_session_id(mac_ctx, + mac_ctx->lim.limTimers.gLimJoinFailureTimer.sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("Session Does not exist for given sessionID")); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, + host_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C); + if (rssi_log) + rssi_log->rssi = session->rssi; + WLAN_HOST_DIAG_LOG_REPORT(rssi_log); +#endif + + if (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) { + len = sizeof(tSirMacAddr); + /* Change timer for future activations */ + lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER); + /* Change Periodic probe req timer for future activation */ + lim_deactivate_and_change_timer(mac_ctx, + eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + /* Issue MLM join confirm with timeout reason code */ + lim_log(mac_ctx, LOGE, + FL("In state eLIM_MLM_WT_JOIN_BEACON_STATE.")); + lim_log(mac_ctx, LOGE, + FL("Join Failure Timeout occurred for session %d with BSS " + MAC_ADDRESS_STR), + session->peSessionId, MAC_ADDR_ARRAY(session->bssId)); + + mlm_join_cnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE; + mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + session->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, session->limMlmState)); + if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE, + session->bssId, session->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + ("Failed to set the LinkState")); + /* Update PE session Id */ + mlm_join_cnf.sessionId = session->peSessionId; + /* Freeup buffer allocated to join request */ + if (session->pLimMlmJoinReq) { + cdf_mem_free(session->pLimMlmJoinReq); + session->pLimMlmJoinReq = NULL; + } + lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, + (uint32_t *) &mlm_join_cnf); + return; + } else { + lim_log(mac_ctx, LOGW, + FL("received unexpected JOIN failure timeout in state %X"), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState); + } +} + +/** + * lim_process_periodic_join_probe_req_timer() - This function is called to + * process periodic probe request send during joining process. + * + * @mac_ctx: Pointer to Global MAC structure + * + * This function is called to process periodic probe request send during + * joining process. + * + * @Return None + */ +static void lim_process_periodic_join_probe_req_timer(tpAniSirGlobal mac_ctx) +{ + tpPESession session; + tSirMacSSid ssid; + + session = pe_find_session_by_session_id(mac_ctx, + mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given SessionId : %d"), + mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer. + sessionId); + return; + } + + if ((true == + tx_timer_running(&mac_ctx->lim.limTimers.gLimJoinFailureTimer)) + && (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE)) { + cdf_mem_copy(ssid.ssId, session->ssId.ssId, + session->ssId.length); + ssid.length = session->ssId.length; + lim_send_probe_req_mgmt_frame(mac_ctx, &ssid, + session->pLimMlmJoinReq->bssDescription.bssId, + session->currentOperChannel /*chanNum */, + session->selfMacAddr, session->dot11mode, + session->pLimJoinReq->addIEScan.length, + session->pLimJoinReq->addIEScan.addIEdata); + lim_deactivate_and_change_timer(mac_ctx, + eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + /* Activate Join Periodic Probe Req timer */ + if (tx_timer_activate( + &mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != + TX_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("could not activate Periodic Join req failure timer")); + return; + } + } +} + +/** + * lim_process_auth_failure_timeout() - This function is called to process Min + * Channel Timeout during channel scan. + * + * @mac_ctx: Pointer to Global MAC structure + * + * This function is called to process Min Channel Timeout during channel scan. + * + * @Return: None + */ +static void lim_process_auth_failure_timeout(tpAniSirGlobal mac_ctx) +{ + /* fetch the sessionEntry based on the sessionId */ + tpPESession session; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + host_log_rssi_pkt_type *rssi_log = NULL; +#endif + + session = pe_find_session_by_session_id(mac_ctx, + mac_ctx->lim.limTimers.gLimAuthFailureTimer.sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } + + lim_log(mac_ctx, LOGE, + FL("received AUTH failure timeout in sessionid %d " + "limMlmstate %X limSmeState %X"), + session->peSessionId, session->limMlmState, + session->limSmeState); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, host_log_rssi_pkt_type, + LOG_WLAN_RSSI_UPDATE_C); + if (rssi_log) + rssi_log->rssi = session->rssi; + WLAN_HOST_DIAG_LOG_REPORT(rssi_log); +#endif + + switch (session->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 (CDF_P2P_CLIENT_MODE == session->pePersona + && session->defaultAuthFailureTimeout) + cfg_set_int(mac_ctx, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + session->defaultAuthFailureTimeout); + lim_restore_from_auth_state(mac_ctx, + eSIR_SME_AUTH_TIMEOUT_RESULT_CODE, + eSIR_MAC_UNSPEC_FAILURE_REASON, session); + break; + default: + /* + * Auth failure timer should not have timed out + * in states other than wt_auth_frame2/4 + */ + lim_log(mac_ctx, LOGE, + FL("received unexpected AUTH failure timeout in state %X"), + session->limMlmState); + lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState); + break; + } +} + +/** + * lim_process_auth_rsp_timeout() - This function is called to process Min + * Channel Timeout during channel scan. + * + * @mac_ctx: Pointer to Global MAC structure + * + * This function is called to process Min Channel Timeout during channel scan. + * + * @Return: None + */ +static void +lim_process_auth_rsp_timeout(tpAniSirGlobal mac_ctx, uint32_t auth_idx) +{ + struct tLimPreAuthNode *auth_node; + tpPESession session; + uint8_t session_id; + + auth_node = lim_get_pre_auth_node_from_index(mac_ctx, + &mac_ctx->lim.gLimPreAuthTimerTable, auth_idx); + if (NULL == auth_node) { + lim_log(mac_ctx, LOGW, FL("Invalid auth node")); + return; + } + + session = pe_find_session_by_bssid(mac_ctx, auth_node->peerMacAddr, + &session_id); + if (NULL == session) { + lim_log(mac_ctx, LOGW, + FL("session does not exist for given BSSID ")); + return; + } + + if (LIM_IS_AP_ROLE(session) || LIM_IS_IBSS_ROLE(session)) { + if (auth_node->mlmState != eLIM_MLM_WT_AUTH_FRAME3_STATE) { + lim_log(mac_ctx, LOGE, + FL("received AUTH rsp timeout in unexpected " + "state for MAC address: " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(auth_node->peerMacAddr)); + } else { + auth_node->mlmState = eLIM_MLM_AUTH_RSP_TIMEOUT_STATE; + auth_node->fTimerStarted = 0; + lim_log(mac_ctx, LOG1, + FL("AUTH rsp timedout for MAC address " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(auth_node->peerMacAddr)); + /* Change timer to reactivate it in future */ + lim_deactivate_and_change_per_sta_id_timer(mac_ctx, + eLIM_AUTH_RSP_TIMER, auth_node->authNodeIdx); + lim_delete_pre_auth_node(mac_ctx, + auth_node->peerMacAddr); + } + } +} + +/** + * lim_process_assoc_failure_timeout() - This function is called to process Min + * Channel Timeout during channel scan. + * + * @mac_ctx Pointer to Global MAC structure + * + * This function is called to process Min Channel Timeout during channel scan. + * + * @Return: None + */ +static void +lim_process_assoc_failure_timeout(tpAniSirGlobal mac_ctx, uint32_t msg_type) +{ + + tLimMlmAssocCnf mlm_assoc_cnf; + tpPESession session; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + host_log_rssi_pkt_type *rssi_log = NULL; +#endif + /* + * to fetch the lim/mlm state based on the session_id, use the + * below sessionEntry + */ + uint8_t session_id; + + if (msg_type == LIM_ASSOC) + session_id = + mac_ctx->lim.limTimers.gLimAssocFailureTimer.sessionId; + else + session_id = + mac_ctx->lim.limTimers.gLimReassocFailureTimer.sessionId; + + session = pe_find_session_by_session_id(mac_ctx, session_id); + if (NULL == session) { + lim_log(mac_ctx, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, + host_log_rssi_pkt_type, + LOG_WLAN_RSSI_UPDATE_C); + if (rssi_log) + rssi_log->rssi = session->rssi; + WLAN_HOST_DIAG_LOG_REPORT(rssi_log); +#endif + + lim_log(mac_ctx, LOG1, + FL("Re/Association Response not received before timeout ")); + + if ((LIM_IS_AP_ROLE(session) || LIM_IS_BT_AMP_AP_ROLE(session)) || + ((session->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) && + (session->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) && + (session->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. + */ + lim_log(mac_ctx, LOGW, + FL("received unexpected REASSOC failure timeout in state %X for role %d"), + session->limMlmState, + GET_LIM_SYSTEM_ROLE(session)); + lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState); + return; + } + + if ((msg_type == LIM_ASSOC) || ((msg_type == LIM_REASSOC) + && (session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) { + lim_log(mac_ctx, LOGE, + FL("(Re)Assoc Failure Timeout occurred.")); + session->limMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, session->limMlmState)); + /* Change timer for future activations */ + lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER); + /* + * Free up buffer allocated for JoinReq held by + * MLM state machine + */ + if (session->pLimMlmJoinReq) { + cdf_mem_free(session->pLimMlmJoinReq); + session->pLimMlmJoinReq = NULL; + } + /* To remove the preauth node in case of fail to associate */ + if (lim_search_pre_auth_list(mac_ctx, session->bssId)) { + lim_log(mac_ctx, LOG1, + FL(" delete pre auth node for "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(session->bssId)); + lim_delete_pre_auth_node(mac_ctx, + session->bssId); + } + + mlm_assoc_cnf.resultCode = eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE; + mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + /* Update PE session Id */ + mlm_assoc_cnf.sessionId = session->peSessionId; + if (msg_type == LIM_ASSOC) { + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF, + (uint32_t *) &mlm_assoc_cnf); + } else { + /* + * Will come here only in case of 11r, Ese FT + * when reassoc rsp is not received and we + * receive a reassoc - timesout + */ + mlm_assoc_cnf.resultCode = + eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE; + lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlm_assoc_cnf); + } + } else { + /* + * Restore pre-reassoc req state. + * Set BSSID to currently associated AP address. + */ + session->limMlmState = session->limPrevMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session->peSessionId, session->limMlmState)); + lim_restore_pre_reassoc_state(mac_ctx, + eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE, + eSIR_MAC_UNSPEC_FAILURE_STATUS, session); + } +} + +/** + * lim_complete_mlm_scan() - This function is called to send MLM_SCAN_CNF + * message to SME state machine. + * + * @mac_ctx: Pointer to Global MAC structure + * @ret_code: Result code to be sent + * + * This function is called to send MLM_SCAN_CNF message to SME state machine. + * + * @Return: None + */ + +void lim_complete_mlm_scan(tpAniSirGlobal mac_ctx, tSirResultCodes ret_code) +{ + tLimMlmScanCnf mlm_scan_cnf; + + /* Restore previous MLM state */ + mac_ctx->lim.gLimMlmState = mac_ctx->lim.gLimPrevMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, NO_SESSION, + mac_ctx->lim.gLimMlmState)); + lim_restore_pre_scan_state(mac_ctx); + /* Free up mac_ctx->lim.gLimMlmScanReq */ + if (NULL != mac_ctx->lim.gpLimMlmScanReq) { + cdf_mem_free(mac_ctx->lim.gpLimMlmScanReq); + mac_ctx->lim.gpLimMlmScanReq = NULL; + } + + mlm_scan_cnf.resultCode = ret_code; + lim_post_sme_message(mac_ctx, LIM_MLM_SCAN_CNF, + (uint32_t *) &mlm_scan_cnf); +} + +/** + * lim_set_channel() - set channel api for lim + * + * @mac_ctx: Pointer to Global MAC structure + * @channel: power save state + * @ch_center_freq_seg0: center freq seq 0 + * @ch_center_freq_seg1: center freq seq 1 + * @ch_width: channel width + * @max_tx_power: max tx power + * @pe_session_id: pe session id + * + * set channel api for lim + * + * @Return: None + */ +void lim_set_channel(tpAniSirGlobal mac_ctx, uint8_t channel, + uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, tPowerdBm max_tx_power, + uint8_t pe_session_id) +{ +#if !defined WLAN_FEATURE_VOWIFI + uint32_t localPwrConstraint; +#endif + tpPESession pe_session; + pe_session = pe_find_session_by_session_id(mac_ctx, pe_session_id); + + if (NULL == pe_session) { + lim_log(mac_ctx, LOGP, FL("Invalid PE session = %d"), + pe_session_id); + return; + } +#if defined WLAN_FEATURE_VOWIFI + lim_send_switch_chnl_params(mac_ctx, channel, ch_center_freq_seg0, + ch_center_freq_seg1, ch_width, + max_tx_power, pe_session_id, false); +#else + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LOCAL_POWER_CONSTRAINT, + &localPwrConstraint) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("couldn't read CFG_LOCAL_POWER_CONSTRAINT")); + return; + } + /* Send WMA_CHNL_SWITCH_IND to HAL */ + lim_send_switch_chnl_params(mac_ctx, channel, ch_center_freq_seg0, + ch_center_freq_seg1, ch_width, + (tPowerdBm) localPwrConstraint, + pe_session_id, false); +#endif +} diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c new file mode 100644 index 000000000000..4450acd6992a --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -0,0 +1,4200 @@ +/* + * 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 "wni_api.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "sir_api.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_timer_utils.h" +#include "lim_send_messages.h" +#include "lim_admit_control.h" +#include "lim_send_messages.h" +#include "lim_ibss_peer_mgmt.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft.h" +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_session_utils.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif +#include "wma_types.h" +#include "cds_utils.h" +#include "lim_types.h" + +#define MAX_SUPPORTED_PEERS_WEP 16 + +static void lim_handle_sme_join_result(tpAniSirGlobal, tSirResultCodes, uint16_t, + tpPESession); +static void lim_handle_sme_reaasoc_result(tpAniSirGlobal, tSirResultCodes, uint16_t, + tpPESession); + +#ifdef FEATURE_OEM_DATA_SUPPORT +void lim_process_mlm_oem_data_req_cnf(tpAniSirGlobal, uint32_t *); +#endif +void lim_process_mlm_join_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_auth_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_start_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_assoc_ind(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_assoc_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_reassoc_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_reassoc_ind(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_set_keys_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_disassoc_ind(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_disassoc_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_deauth_ind(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_deauth_cnf(tpAniSirGlobal, uint32_t *); +void lim_process_mlm_purge_sta_ind(tpAniSirGlobal, uint32_t *); +static void lim_handle_del_bss_in_re_assoc_context(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tpPESession psessionEntry); +void lim_get_session_info(tpAniSirGlobal pMac, uint8_t *, uint8_t *, uint16_t *); +static void +lim_process_btamp_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry); +/** + * lim_process_mlm_rsp_messages() + * + ***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 +lim_process_mlm_rsp_messages(tpAniSirGlobal pMac, uint32_t msgType, + uint32_t *pMsgBuf) +{ + + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + MTRACE(mac_trace(pMac, TRACE_CODE_TX_LIM_MSG, 0, msgType)); + switch (msgType) { + +#ifdef FEATURE_OEM_DATA_SUPPORT + case LIM_MLM_OEM_DATA_CNF: + lim_process_mlm_oem_data_req_cnf(pMac, pMsgBuf); + pMsgBuf = NULL; + break; +#endif + + case LIM_MLM_AUTH_CNF: + lim_process_mlm_auth_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_ASSOC_CNF: + lim_process_mlm_assoc_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_START_CNF: + lim_process_mlm_start_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_JOIN_CNF: + lim_process_mlm_join_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_ASSOC_IND: + lim_process_mlm_assoc_ind(pMac, pMsgBuf); + break; + case LIM_MLM_REASSOC_CNF: + lim_process_mlm_reassoc_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_DISASSOC_CNF: + lim_process_mlm_disassoc_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_DISASSOC_IND: + lim_process_mlm_disassoc_ind(pMac, pMsgBuf); + break; + case LIM_MLM_PURGE_STA_IND: + lim_process_mlm_purge_sta_ind(pMac, pMsgBuf); + break; + case LIM_MLM_DEAUTH_CNF: + lim_process_mlm_deauth_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_DEAUTH_IND: + lim_process_mlm_deauth_ind(pMac, pMsgBuf); + break; + case LIM_MLM_SETKEYS_CNF: + lim_process_mlm_set_keys_cnf(pMac, pMsgBuf); + break; + case LIM_MLM_TSPEC_CNF: + break; + default: + break; + } /* switch (msgType) */ + return; +} /*** end lim_process_mlm_rsp_messages() ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * lim_process_mlm_oem_data_req_cnf() + * + ***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 lim_process_mlm_oem_data_req_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tLimMlmOemDataRsp *measRsp; + + tSirResultCodes resultCode = eSIR_SME_SUCCESS; + + measRsp = (tLimMlmOemDataRsp *) (pMsgBuf); + + /* Now send the meas confirm message to the sme */ + lim_send_sme_oem_data_rsp(pMac, (uint32_t *) measRsp, resultCode); + + /* Dont free the memory here. It will be freed up by the callee */ + + return; +} +#endif + +/** + * lim_process_mlm_start_cnf() + * + ***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 lim_process_mlm_start_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpPESession psessionEntry = NULL; + tLimMlmStartCnf *pLimMlmStartCnf; + uint8_t smesessionId; + uint16_t smetransactionId; + uint8_t channelId; + + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + pLimMlmStartCnf = (tLimMlmStartCnf *) pMsgBuf; + psessionEntry = pe_find_session_by_session_id(pMac, + pLimMlmStartCnf->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log(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(lim_log(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(mac_trace + (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + psessionEntry->limSmeState)); + if (psessionEntry->bssType == eSIR_BTAMP_STA_MODE) { + lim_log(pMac, LOG1, + FL("*** Started BSS in BT_AMP STA SIDE***")); + } else if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { + lim_log(pMac, LOG1, + FL("*** Started BSS in BT_AMP AP SIDE***")); + } else if (psessionEntry->bssType == eSIR_INFRA_AP_MODE) { + lim_log(pMac, LOG1, + FL("*** Started BSS in INFRA AP SIDE***")); + } else + PELOG1(lim_log(pMac, LOG1, FL("*** Started BSS ***"));) + } else { + /* Start BSS is a failure */ + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + PELOGE(lim_log(pMac, LOGE, FL("Start BSS Failed "));) + } + /* Send response to Host */ + lim_send_sme_start_bss_rsp(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) && + (cds_get_channel_state(channelId) != + CHANNEL_STATE_DFS))) { + /* Configure beacon and send beacons to HAL */ + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Start Beacon with ssid %s Ch %d"), + psessionEntry->ssId.ssId, + psessionEntry->currentOperChannel); + lim_send_beacon_ind(pMac, psessionEntry); + } + } +} + +/*** end lim_process_mlm_start_cnf() ***/ + +/** + * lim_process_mlm_join_cnf() - Processes join confirmation + * @mac_ctx: Pointer to Global MAC structure + * @msg: A pointer to the MLM message buffer + * + * This Function handles the join confirmation message + * LIM_MLM_JOIN_CNF. + * + * Return: None + */ +void lim_process_mlm_join_cnf(tpAniSirGlobal mac_ctx, + uint32_t *msg) +{ + tSirResultCodes result_code; + tLimMlmJoinCnf *join_cnf; + tpPESession session_entry; + + join_cnf = (tLimMlmJoinCnf *) msg; + session_entry = pe_find_session_by_session_id(mac_ctx, + join_cnf->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL("SessionId:%d does not exist"), + join_cnf->sessionId); + return; + } + + if (session_entry->limSmeState != eLIM_SME_WT_JOIN_STATE) { + lim_log(mac_ctx, LOGE, + FL("received unexpected MLM_JOIN_CNF in state %X"), + session_entry->limSmeState); + return; + } + + result_code = ((tLimMlmJoinCnf *) msg)->resultCode; + /* Process Join confirm from MLM */ + if (result_code == eSIR_SME_SUCCESS) { + lim_log(mac_ctx, LOG1, FL("***SessionId:%d Joined ESS ***"), + join_cnf->sessionId); + /* Setup hardware upfront */ + if (lim_sta_send_add_bss_pre_assoc(mac_ctx, false, + session_entry) == eSIR_SUCCESS) + return; + else + result_code = eSIR_SME_REFUSED; + } + + /* Join failure */ + session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + /* Send Join response to Host */ + lim_handle_sme_join_result(mac_ctx, result_code, + ((tLimMlmJoinCnf *) msg)->protStatusCode, session_entry); + return; +} + +/** + * lim_send_mlm_assoc_req() - Association request will be processed + * mac_ctx: Pointer to Global MAC structure + * session_entry: Pointer to session etnry + * + * 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. + * 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. + * + * Return: None + */ + +void lim_send_mlm_assoc_req(tpAniSirGlobal mac_ctx, + tpPESession session_entry) +{ + tLimMlmAssocReq *assoc_req; + uint32_t val; + uint16_t caps; + uint32_t tele_bcn = 0; + tpSirMacCapabilityInfo cap_info; + + /* Successful MAC based authentication. Trigger Association with BSS */ + lim_log(mac_ctx, LOG1, FL("SessionId:%d Authenticated with BSS"), + session_entry->peSessionId); + + if (NULL == session_entry->pLimJoinReq) { + lim_log(mac_ctx, LOGE, FL("Join Request is NULL.")); + /* No need to Assert. JOIN timeout will handle this error */ + return; + } + + assoc_req = cdf_mem_malloc(sizeof(tLimMlmAssocReq)); + if (NULL == assoc_req) { + lim_log(mac_ctx, LOGP, + FL("call to AllocateMemory failed for mlmAssocReq")); + return; + } + val = sizeof(tSirMacAddr); + sir_copy_mac_addr(assoc_req->peerMacAddr, session_entry->bssId); + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + (uint32_t *) &assoc_req->assocFailureTimeout) + != eSIR_SUCCESS) { + /* Could not get AssocFailureTimeout value from CFG.*/ + lim_log(mac_ctx, LOGP, + FL("could not retrieve AssocFailureTimeout value")); + } + + if (cfg_get_capability_info(mac_ctx, &caps, session_entry) + != eSIR_SUCCESS) + /* Could not get Capabilities value from CFG.*/ + lim_log(mac_ctx, LOGP, + FL("could not retrieve Capabilities value")); + + /* Clear spectrum management bit if AP doesn't support it */ + if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo & + LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) + /* + * AP doesn't support spectrum management + * clear spectrum management bit + */ + caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK); + + /* Clear rrm bit if AP doesn't support it */ + if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo + & LIM_RRM_BIT_MASK)) + caps &= (~LIM_RRM_BIT_MASK); + + /* Clear short preamble bit if AP does not support it */ + if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo & + (LIM_SHORT_PREAMBLE_BIT_MASK))) { + caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK); + lim_log(mac_ctx, LOG1, + FL("Clearing short preamble:no AP support")); + } + + /* Clear immediate block ack bit if AP does not support it */ + if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo & + (LIM_IMMEDIATE_BLOCK_ACK_MASK))) { + caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK); + lim_log(mac_ctx, LOG1, + FL("Clearing Immed Blk Ack:no AP support")); + } + + assoc_req->capabilityInfo = caps; + cap_info = ((tpSirMacCapabilityInfo) &assoc_req->capabilityInfo); + lim_log(mac_ctx, LOG3, FL("Capabilities to be used in AssocReq=0x%X," + "privacy bit=%x shortSlotTime %x"), caps, + cap_info->privacy, + cap_info->shortSlotTime); + + /* + * If telescopic beaconing is enabled, set listen interval to + * WNI_CFG_TELE_BCN_MAX_LI + */ + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_WAKEUP_EN, &tele_bcn) + != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + + val = WNI_CFG_LISTEN_INTERVAL_STADEF; + if (tele_bcn) { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_MAX_LI, &val) != + eSIR_SUCCESS) + /* + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve ListenInterval")); + } else { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL, + &val) != eSIR_SUCCESS) + /* + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve ListenInterval")); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_REQ_EVENT, + session_entry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + assoc_req->listenInterval = (uint16_t) val; + /* Update PE session ID */ + assoc_req->sessionId = session_entry->peSessionId; + session_entry->limPrevSmeState = session_entry->limSmeState; + session_entry->limSmeState = eLIM_SME_WT_ASSOC_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, session_entry->limSmeState)); + lim_post_mlm_message(mac_ctx, LIM_MLM_ASSOC_REQ, + (uint32_t *) assoc_req); +} + +#ifdef WLAN_FEATURE_11W +/** + * lim_pmf_comeback_timer_callback() -PMF callback handler + * @context: Timer context + * + * This function is called to processes the PMF comeback + * callback + * + * Return: None + */ +void lim_pmf_comeback_timer_callback(void *context) +{ + tComebackTimerInfo *info = (tComebackTimerInfo *) context; + tpAniSirGlobal mac_ctx = info->pMac; + tpPESession psessionEntry = &mac_ctx->lim.gpSession[info->sessionID]; + + lim_log(mac_ctx, LOGE, + FL("comeback later timer expired. sending MLM ASSOC req")); + /* set MLM state such that ASSOC REQ packet will be sent out */ + psessionEntry->limPrevMlmState = info->limPrevMlmState; + psessionEntry->limMlmState = info->limMlmState; + lim_send_mlm_assoc_req(mac_ctx, psessionEntry); +} +#endif /* WLAN_FEATURE_11W */ + +/** + * lim_process_mlm_auth_cnf()-Process Auth confirmation + * @mac_ctx: Pointer to Global MAC structure + * @msg: A pointer to the MLM message buffer + * + * This function is called to processes MLM_AUTH_CNF + * message from MLM State machine. + * + * Return: None + */ +void lim_process_mlm_auth_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg) +{ + tAniAuthType auth_type, auth_mode; + tLimMlmAuthReq *auth_req; + tLimMlmAuthCnf *auth_cnf; + tpPESession session_entry; + + if (msg == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + auth_cnf = (tLimMlmAuthCnf *) msg; + session_entry = pe_find_session_by_session_id(mac_ctx, + auth_cnf->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL("SessionId:%d session doesn't exist"), + auth_cnf->sessionId); + return; + } + + if ((session_entry->limSmeState != eLIM_SME_WT_AUTH_STATE && + session_entry->limSmeState != eLIM_SME_WT_PRE_AUTH_STATE) || + LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + /** + * Should not have received AUTH confirm + * from MLM in other states or on AP. + * Log error + */ + lim_log(mac_ctx, LOGE, + FL("SessionId:%d received MLM_AUTH_CNF in state %X"), + session_entry->peSessionId, session_entry->limSmeState); + return; + } + + if (((tLimMlmAuthCnf *) msg)->resultCode == eSIR_SME_SUCCESS) { + if (session_entry->limSmeState == eLIM_SME_WT_AUTH_STATE) { + lim_send_mlm_assoc_req(mac_ctx, session_entry); + } else { + /* + * Successful Pre-authentication. Send + * Pre-auth response to host + */ + session_entry->limSmeState = + session_entry->limPrevSmeState; + MTRACE(mac_trace + (mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + } + /* Return for success case */ + return; + } + /* + * Failure case handle: + * Process AUTH confirm from MLM + */ + if (session_entry->limSmeState == eLIM_SME_WT_AUTH_STATE) { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_AUTHENTICATION_TYPE, + (uint32_t *) &auth_type) != eSIR_SUCCESS) { + /* + * Could not get AuthType value from CFG. + * Log error. + */ + lim_log(mac_ctx, LOGP, + FL("Fail to retrieve AuthType value")); + } + } else { + auth_type = mac_ctx->lim.gLimPreAuthType; + } + + if ((auth_type == eSIR_AUTO_SWITCH) && + (((tLimMlmAuthCnf *) msg)->authType == eSIR_OPEN_SYSTEM) + && (eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS == + ((tLimMlmAuthCnf *) msg)->protStatusCode)) { + /* + * When Open authentication fails with reason + * code "13" and authType set to 'auto switch', + * Try with Shared Authentication + */ + auth_mode = eSIR_SHARED_KEY; + /* Trigger MAC based Authentication */ + auth_req = cdf_mem_malloc(sizeof(tLimMlmAuthReq)); + if (NULL == auth_req) { + /* Log error */ + lim_log(mac_ctx, LOGP, + FL("mlmAuthReq :Memory alloc failed ")); + return; + } + cdf_mem_set((uint8_t *) auth_req, + sizeof(tLimMlmAuthReq), 0); + if (session_entry->limSmeState == + eLIM_SME_WT_AUTH_STATE) { + sir_copy_mac_addr(auth_req->peerMacAddr, + session_entry->bssId); + } else { + cdf_mem_copy((uint8_t *)&auth_req->peerMacAddr, + (uint8_t *)&mac_ctx->lim.gLimPreAuthPeerAddr, + sizeof(tSirMacAddr)); + } + auth_req->authType = auth_mode; + /* Update PE session Id */ + auth_req->sessionId = auth_cnf->sessionId; + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + (uint32_t *) &auth_req->authFailureTimeout) + != eSIR_SUCCESS) { + /* + * Could not get AuthFailureTimeout value from CFG. + * Log error. + */ + lim_log(mac_ctx, LOGP, + FL("Fail:retrieve AuthFailureTimeout ")); + } + lim_post_mlm_message(mac_ctx, LIM_MLM_AUTH_REQ, + (uint32_t *) auth_req); + return; + } else { + /* MAC based authentication failure */ + if (session_entry->limSmeState == + eLIM_SME_WT_AUTH_STATE) { + lim_log(mac_ctx, LOGE, + FL("Auth Failure occurred.")); + session_entry->limSmeState = + eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + session_entry->limMlmState = + eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + session_entry->limMlmState)); + /* + * Need to send Join response with + * auth failure to Host. + */ + lim_handle_sme_join_result(mac_ctx, + ((tLimMlmAuthCnf *)msg)->resultCode, + ((tLimMlmAuthCnf *)msg)->protStatusCode, + session_entry); + } else { + /* + * Pre-authentication failure. + * Send Pre-auth failure response to host + */ + session_entry->limSmeState = + session_entry->limPrevSmeState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + } + } +} + +/** + * lim_process_mlm_assoc_cnf() - Process association confirmation + * @mac_ctx: Pointer to Global MAC structure + * @msg: A pointer to the MLM message buffer + * + * This function is called to processes MLM_ASSOC_CNF + * message from MLM State machine. + * + * Return: None + */ +void lim_process_mlm_assoc_cnf(tpAniSirGlobal mac_ctx, + uint32_t *msg) +{ + tpPESession session_entry; + tLimMlmAssocCnf *assoc_cnf; + + if (msg == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + assoc_cnf = (tLimMlmAssocCnf *) msg; + session_entry = pe_find_session_by_session_id(mac_ctx, + assoc_cnf->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("SessionId:%d Session does not exist"), + assoc_cnf->sessionId); + return; + } + if (session_entry->limSmeState != eLIM_SME_WT_ASSOC_STATE || + LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + /* + * Should not have received Assocication confirm + * from MLM in other states OR on AP. + * Log error + */ + lim_log(mac_ctx, LOGE, + FL("SessionId:%d Received MLM_ASSOC_CNF in state %X"), + session_entry->peSessionId, session_entry->limSmeState); + return; + } + if (((tLimMlmAssocCnf *) msg)->resultCode != eSIR_SME_SUCCESS) { + /* Association failure */ + lim_log(mac_ctx, LOG1, FL("SessionId:%d Association failure"), + session_entry->peSessionId); + session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, mac_ctx->lim.gLimSmeState)); + /* + * Need to send Join response with + * Association failure to Host. + */ + lim_handle_sme_join_result(mac_ctx, + ((tLimMlmAssocCnf *) msg)->resultCode, + ((tLimMlmAssocCnf *) msg)->protStatusCode, + session_entry); + } else { + /* Successful Association */ + lim_log(mac_ctx, LOG1, FL("SessionId:%d Associated with BSS"), + session_entry->peSessionId); + session_entry->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + /** + * Need to send Join response with + * Association success to Host. + */ + lim_handle_sme_join_result(mac_ctx, + ((tLimMlmAssocCnf *) msg)->resultCode, + ((tLimMlmAssocCnf *) msg)->protStatusCode, + session_entry); + } +} + +/** + * lim_process_mlm_reassoc_cnf() - process mlm reassoc cnf msg + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the MLM message buffer + * + * This function is called to process MLM_REASSOC_CNF message from MLM State + * machine. + * + * @Return: void + */ +void lim_process_mlm_reassoc_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tpPESession session; + tLimMlmReassocCnf *lim_mlm_reassoc_cnf; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + lim_mlm_reassoc_cnf = (tLimMlmReassocCnf *) msg_buf; + session = pe_find_session_by_session_id(mac_ctx, + lim_mlm_reassoc_cnf->sessionId); + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("session Does not exist for given session Id")); + return; + } + if ((session->limSmeState != eLIM_SME_WT_REASSOC_STATE) || + LIM_IS_AP_ROLE(session) || LIM_IS_BT_AMP_AP_ROLE(session)) { + /* + * Should not have received Reassocication confirm + * from MLM in other states OR on AP. + */ + lim_log(mac_ctx, LOGE, + FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X"), + GET_LIM_SYSTEM_ROLE(session), session->limSmeState); + return; + } + if (session->pLimReAssocReq) { + cdf_mem_free(session->pLimReAssocReq); + session->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 (session->ftPEContext.pFTPreAuthReq) { + lim_log(mac_ctx, LOG1, FL("Freeing pFTPreAuthReq= %p"), + session->ftPEContext.pFTPreAuthReq); + if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { + cdf_mem_free( + session->ftPEContext.pFTPreAuthReq->pbssDescription); + session->ftPEContext.pFTPreAuthReq->pbssDescription = + NULL; + } + cdf_mem_free(session->ftPEContext.pFTPreAuthReq); + session->ftPEContext.pFTPreAuthReq = NULL; + session->ftPEContext.ftPreAuthSession = false; + } + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session->bRoamSynchInProgress) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Re-set the LIM Ctxt Roam Synch In Progress")); + session->bRoamSynchInProgress = false; + } +#endif + + lim_log(mac_ctx, LOG1, FL("Rcv MLM_REASSOC_CNF with result code %d"), + lim_mlm_reassoc_cnf->resultCode); + if (lim_mlm_reassoc_cnf->resultCode == eSIR_SME_SUCCESS) { + /* Successful Reassociation */ + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + FL("*** Reassociated with new BSS ***")); + + session->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session->peSessionId, session->limSmeState)); + + /* Need to send Reassoc rsp with Reassoc success to Host. */ + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, + lim_mlm_reassoc_cnf->resultCode, + lim_mlm_reassoc_cnf->protStatusCode, + session, session->smeSessionId, + session->transactionId); + } else if (lim_mlm_reassoc_cnf->resultCode + == eSIR_SME_REASSOC_REFUSED) { + /* + * Reassociation failure With the New AP but we still have the + * link with the Older AP + */ + session->limSmeState = eLIM_SME_LINK_EST_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session->peSessionId, session->limSmeState)); + + /* Need to send Reassoc rsp with Assoc failure to Host. */ + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, + lim_mlm_reassoc_cnf->resultCode, + lim_mlm_reassoc_cnf->protStatusCode, + session, session->smeSessionId, + session->transactionId); + } else { + /* Reassociation failure */ + session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session->peSessionId, session->limSmeState)); + /* Need to send Reassoc rsp with Assoc failure to Host. */ + lim_handle_sme_reaasoc_result(mac_ctx, + lim_mlm_reassoc_cnf->resultCode, + lim_mlm_reassoc_cnf->protStatusCode, + session); + } +} + +/** + * lim_fill_assoc_ind_params() - Initialize association indication + * mac_ctx: Pointer to Global MAC structure + * assoc_ind: PE association indication structure + * sme_assoc_ind: SME association indication + * session_entry: PE session entry + * + * This function is called to initialzie the association + * indication strucutre to process association indication. + * + * Return: None + */ + +void +lim_fill_assoc_ind_params(tpAniSirGlobal mac_ctx, + tpLimMlmAssocInd assoc_ind, tSirSmeAssocInd *sme_assoc_ind, + tpPESession session_entry) +{ + sme_assoc_ind->length = sizeof(tSirSmeAssocInd); + sme_assoc_ind->sessionId = session_entry->smeSessionId; + + /* Required for indicating the frames to upper layer */ + sme_assoc_ind->assocReqLength = assoc_ind->assocReqLength; + sme_assoc_ind->assocReqPtr = assoc_ind->assocReqPtr; + + sme_assoc_ind->beaconPtr = session_entry->beacon; + sme_assoc_ind->beaconLength = session_entry->bcnLen; + + /* Fill in peerMacAddr */ + cdf_mem_copy(sme_assoc_ind->peerMacAddr, assoc_ind->peerMacAddr, + sizeof(tSirMacAddr)); + + /* Fill in aid */ + sme_assoc_ind->aid = assoc_ind->aid; + /* Fill in bssId */ + cdf_mem_copy(sme_assoc_ind->bssId, session_entry->bssId, + sizeof(tSirMacAddr)); + /* Fill in authType */ + sme_assoc_ind->authType = assoc_ind->authType; + /* Fill in ssId */ + cdf_mem_copy((uint8_t *) &sme_assoc_ind->ssId, + (uint8_t *) &(assoc_ind->ssId), assoc_ind->ssId.length + 1); + sme_assoc_ind->rsnIE.length = assoc_ind->rsnIE.length; + cdf_mem_copy((uint8_t *) &sme_assoc_ind->rsnIE.rsnIEdata, + (uint8_t *) &(assoc_ind->rsnIE.rsnIEdata), + assoc_ind->rsnIE.length); + +#ifdef FEATURE_WLAN_WAPI + sme_assoc_ind->wapiIE.length = assoc_ind->wapiIE.length; + cdf_mem_copy((uint8_t *) &sme_assoc_ind->wapiIE.wapiIEdata, + (uint8_t *) &(assoc_ind->wapiIE.wapiIEdata), + assoc_ind->wapiIE.length); +#endif + sme_assoc_ind->addIE.length = assoc_ind->addIE.length; + cdf_mem_copy((uint8_t *) &sme_assoc_ind->addIE.addIEdata, + (uint8_t *) &(assoc_ind->addIE.addIEdata), + assoc_ind->addIE.length); + + /* Copy the new TITAN capabilities */ + sme_assoc_ind->spectrumMgtIndicator = assoc_ind->spectrumMgtIndicator; + if (assoc_ind->spectrumMgtIndicator == eSIR_TRUE) { + sme_assoc_ind->powerCap.minTxPower = + assoc_ind->powerCap.minTxPower; + sme_assoc_ind->powerCap.maxTxPower = + assoc_ind->powerCap.maxTxPower; + sme_assoc_ind->supportedChannels.numChnl = + assoc_ind->supportedChannels.numChnl; + cdf_mem_copy((uint8_t *) &sme_assoc_ind->supportedChannels. + channelList, + (uint8_t *) &(assoc_ind->supportedChannels.channelList), + assoc_ind->supportedChannels.numChnl); + } + cdf_mem_copy(&sme_assoc_ind->chan_info, &assoc_ind->chan_info, + sizeof(tSirSmeChanInfo)); + /* Fill in WmmInfo */ + sme_assoc_ind->wmmEnabledSta = assoc_ind->WmmStaInfoPresent; +} + +/** + * lim_process_mlm_assoc_ind() + * + ***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 lim_process_mlm_assoc_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + uint32_t len; + tSirMsgQ msgQ; + tSirSmeAssocInd *pSirSmeAssocInd; + tpDphHashNode pStaDs = 0; + tpPESession psessionEntry; + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + psessionEntry = pe_find_session_by_session_id(pMac, + ((tpLimMlmAssocInd) pMsgBuf)-> + sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session Does not exist for given sessionId")); + return; + } + /* / Inform Host of STA association */ + len = sizeof(tSirSmeAssocInd); + pSirSmeAssocInd = cdf_mem_malloc(len); + if (NULL == pSirSmeAssocInd) { + /* Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_ASSOC_IND")); + return; + } + + pSirSmeAssocInd->messageType = eWNI_SME_ASSOC_IND; + lim_fill_assoc_ind_params(pMac, (tpLimMlmAssocInd) pMsgBuf, pSirSmeAssocInd, + psessionEntry); + msgQ.type = eWNI_SME_ASSOC_IND; + msgQ.bodyptr = pSirSmeAssocInd; + msgQ.bodyval = 0; + pStaDs = dph_get_hash_entry(pMac, + ((tpLimMlmAssocInd) pMsgBuf)->aid, + &psessionEntry->dph.dphHashTable); + if (!pStaDs) { /* good time to panic... */ + lim_log(pMac, LOGE, + FL + ("MLM AssocInd: Station context no longer valid (aid %d)"), + ((tpLimMlmAssocInd) pMsgBuf)->aid); + cdf_mem_free(pSirSmeAssocInd); + + return; + } + pSirSmeAssocInd->staId = pStaDs->staIndex; + pSirSmeAssocInd->reassocReq = pStaDs->mlmStaContext.subType; + pSirSmeAssocInd->timingMeasCap = pStaDs->timingMeasCap; + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_ASSOC_IND_EVENT, psessionEntry, 0, + 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT); + + PELOG1(lim_log(pMac, LOG1, + FL + ("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND")); + ) + /* + ** turn on a timer to detect the loss of ASSOC CNF + **/ + lim_activate_cnf_timer(pMac, + (uint16_t) ((tpLimMlmAssocInd) pMsgBuf)->aid, + psessionEntry); + +} /*** end lim_process_mlm_assoc_ind() ***/ + +/** + * lim_process_mlm_disassoc_ind() + * + ***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 lim_process_mlm_disassoc_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tLimMlmDisassocInd *pMlmDisassocInd; + tpPESession psessionEntry; + pMlmDisassocInd = (tLimMlmDisassocInd *) pMsgBuf; + psessionEntry = pe_find_session_by_session_id(pMac, + pMlmDisassocInd->sessionId); + if (psessionEntry == NULL) { + lim_log(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(mac_trace + (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + psessionEntry->limSmeState)); + break; + default: /* eLIM_AP_ROLE //eLIM_BT_AMP_AP_ROLE */ + PELOG1(lim_log(pMac, LOG1, + FL("*** Peer staId=%d Disassociated ***"), + pMlmDisassocInd->aid); + ) + /* Send SME_DISASOC_IND after Polaris cleanup */ + /* (after receiving LIM_MLM_PURGE_STA_IND) */ + break; + } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */ +} /*** end lim_process_mlm_disassoc_ind() ***/ + +/** + * lim_process_mlm_disassoc_cnf() - Processes disassociation + * @mac_ctx: Pointer to Global MAC structure + * @msg: A pointer to the MLM message buffer + * + * This function is called to processes MLM_DISASSOC_CNF + * message from MLM State machine. + * + * Return: None + */ +void lim_process_mlm_disassoc_cnf(tpAniSirGlobal mac_ctx, + uint32_t *msg) +{ + tSirResultCodes result_code; + tLimMlmDisassocCnf *disassoc_cnf; + tpPESession session_entry; + disassoc_cnf = (tLimMlmDisassocCnf *) msg; + + session_entry = + pe_find_session_by_session_id(mac_ctx, disassoc_cnf->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session Does not exist for given session Id")); + return; + } + result_code = (tSirResultCodes)(disassoc_cnf->disassocTrigger == + eLIM_LINK_MONITORING_DISASSOC) ? + eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE : + disassoc_cnf->resultCode; + if (LIM_IS_STA_ROLE(session_entry) || + LIM_IS_BT_AMP_STA_ROLE(session_entry)) { + /* Disassociate Confirm from MLM */ + if ((session_entry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) + && (session_entry->limSmeState != + eLIM_SME_WT_DEAUTH_STATE)) { + /* + * Should not have received + * Disassocate confirm + * from MLM in other states.Log error + */ + lim_log(mac_ctx, LOGE, + FL("received MLM_DISASSOC_CNF in state %X"), + session_entry->limSmeState); + return; + } + if (mac_ctx->lim.gLimRspReqd) + mac_ctx->lim.gLimRspReqd = false; + if (disassoc_cnf->disassocTrigger == + eLIM_PROMISCUOUS_MODE_DISASSOC) { + if (disassoc_cnf->resultCode != eSIR_SME_SUCCESS) + session_entry->limSmeState = + session_entry->limPrevSmeState; + else + session_entry->limSmeState = + eLIM_SME_OFFLINE_STATE; + MTRACE(mac_trace + (mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + } else { + if (disassoc_cnf->resultCode != eSIR_SME_SUCCESS) + session_entry->limSmeState = + session_entry->limPrevSmeState; + else + session_entry->limSmeState = + eLIM_SME_IDLE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + lim_send_sme_disassoc_ntf(mac_ctx, + disassoc_cnf->peerMacAddr, result_code, + disassoc_cnf->disassocTrigger, + disassoc_cnf->aid, session_entry->smeSessionId, + session_entry->transactionId, session_entry); + } + } else if (LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + lim_send_sme_disassoc_ntf(mac_ctx, disassoc_cnf->peerMacAddr, + result_code, disassoc_cnf->disassocTrigger, + disassoc_cnf->aid, session_entry->smeSessionId, + session_entry->transactionId, session_entry); + } +} + +/** + * lim_process_mlm_deauth_ind() + * + ***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 lim_process_mlm_deauth_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tLimMlmDeauthInd *pMlmDeauthInd; + tpPESession psessionEntry; + uint8_t sessionId; + pMlmDeauthInd = (tLimMlmDeauthInd *) pMsgBuf; + psessionEntry = pe_find_session_by_bssid(pMac, + pMlmDeauthInd->peerMacAddr, &sessionId); + if (psessionEntry == NULL) { + lim_log(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(mac_trace + (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + psessionEntry->limSmeState)); + + default: /* eLIM_AP_ROLE */ + { + PELOG1(lim_log(pMac, LOG1, + FL + ("*** Received Deauthentication from staId=%d ***"), + pMlmDeauthInd->aid); + ) + } + /* Send SME_DEAUTH_IND after Polaris cleanup */ + /* (after receiving LIM_MLM_PURGE_STA_IND) */ + break; + } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */ +} /*** end lim_process_mlm_deauth_ind() ***/ + +/** + * lim_process_mlm_deauth_cnf() + * + ***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 lim_process_mlm_deauth_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + uint16_t aid; + tSirResultCodes resultCode; + tLimMlmDeauthCnf *pMlmDeauthCnf; + tpPESession psessionEntry; + + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + pMlmDeauthCnf = (tLimMlmDeauthCnf *) pMsgBuf; + psessionEntry = pe_find_session_by_session_id(pMac, + pMlmDeauthCnf->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log + (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_DEAUTH_STATE) { + /** + * Should not have received Deauth confirm + * from MLM in other states. + * Log error + */ + PELOGE(lim_log(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(lim_log(pMac, LOG1, + FL("*** Deauthenticated with BSS ***"));) + } else + psessionEntry->limSmeState = + psessionEntry->limPrevSmeState; + MTRACE(mac_trace + (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 */ + lim_send_sme_deauth_ntf(pMac, pMlmDeauthCnf->peerMacAddr, + resultCode, + pMlmDeauthCnf->deauthTrigger, + aid, psessionEntry->smeSessionId, + psessionEntry->transactionId); +} /*** end lim_process_mlm_deauth_cnf() ***/ + +/** + * lim_process_mlm_purge_sta_ind() + * + ***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 lim_process_mlm_purge_sta_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirResultCodes resultCode; + tpLimMlmPurgeStaInd pMlmPurgeStaInd; + tpPESession psessionEntry; + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + pMlmPurgeStaInd = (tpLimMlmPurgeStaInd) pMsgBuf; + psessionEntry = pe_find_session_by_session_id(pMac, + pMlmPurgeStaInd->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log + (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(lim_log(pMac, LOGE, + FL + ("received unexpected MLM_PURGE_STA_IND in state %X"), + psessionEntry->limSmeState); + ) + break; + } + PELOG1(lim_log(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(mac_trace + (pMac, TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); + + } + if (pMlmPurgeStaInd->purgeTrigger == eLIM_PEER_ENTITY_DEAUTH) { + lim_send_sme_deauth_ntf(pMac, + pMlmPurgeStaInd->peerMacAddr, + resultCode, + pMlmPurgeStaInd->purgeTrigger, + pMlmPurgeStaInd->aid, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + } else + lim_send_sme_disassoc_ntf(pMac, + pMlmPurgeStaInd->peerMacAddr, + resultCode, + pMlmPurgeStaInd->purgeTrigger, + pMlmPurgeStaInd->aid, + psessionEntry->smeSessionId, + psessionEntry->transactionId, + psessionEntry); + } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */ +} /*** end lim_process_mlm_purge_sta_ind() ***/ + +/** + * lim_process_mlm_set_keys_cnf() + * + ***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 lim_process_mlm_set_keys_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + /* Prepare and send SME_SETCONTEXT_RSP message */ + tLimMlmSetKeysCnf *pMlmSetKeysCnf; + tpPESession psessionEntry; + uint16_t aid; + tpDphHashNode sta_ds; + + if (pMsgBuf == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));) + return; + } + pMlmSetKeysCnf = (tLimMlmSetKeysCnf *) pMsgBuf; + psessionEntry = pe_find_session_by_session_id(pMac, + pMlmSetKeysCnf->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("session does not exist for given sessionId ")); + ) + return; + } + psessionEntry->is_key_installed = 0; + lim_log(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->is_key_installed = 1; + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + sta_ds = dph_lookup_hash_entry(pMac, + pMlmSetKeysCnf->peerMacAddr, + &aid, &psessionEntry->dph.dphHashTable); + if (sta_ds != NULL) + sta_ds->is_key_installed = 1; + } + } + lim_send_sme_set_context_rsp(pMac, + pMlmSetKeysCnf->peerMacAddr, + 1, + (tSirResultCodes) pMlmSetKeysCnf->resultCode, + psessionEntry, psessionEntry->smeSessionId, + psessionEntry->transactionId); +} /*** end lim_process_mlm_set_keys_cnf() ***/ + +/** + * lim_handle_sme_join_result() - Handles sme join result + * @mac_ctx: Pointer to Global MAC structure + * @result_code: Failure code to be sent + * @prot_status_code : Protocol status code + * @session_entry: PE session handle + * + * 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. + * + * Return: None + */ +static void +lim_handle_sme_join_result(tpAniSirGlobal mac_ctx, + tSirResultCodes result_code, uint16_t prot_status_code, + tpPESession session_entry) +{ + tpDphHashNode sta_ds = NULL; + uint8_t sme_session_id; + uint16_t sme_trans_id; + + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL("psessionEntry is NULL ")); + return; + } + sme_session_id = session_entry->smeSessionId; + sme_trans_id = session_entry->transactionId; + /* + * When associations is failed , delete the session created + * and pass NULL to limsendsmeJoinReassocRsp() + */ + if (result_code != eSIR_SME_SUCCESS) { + sta_ds = + dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (sta_ds != NULL) { + sta_ds->mlmStaContext.disassocReason = + eSIR_MAC_UNSPEC_FAILURE_REASON; + sta_ds->mlmStaContext.cleanupTrigger = + eLIM_JOIN_FAILURE; + sta_ds->mlmStaContext.resultCode = result_code; + sta_ds->mlmStaContext.protStatusCode = prot_status_code; + /* + * FIX_ME: at the end of lim_cleanup_rx_path, + * make sure PE is sending eWNI_SME_JOIN_RSP + * to SME + */ + lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + cdf_mem_free(session_entry->pLimJoinReq); + session_entry->pLimJoinReq = NULL; + return; + } + } + + cdf_mem_free(session_entry->pLimJoinReq); + session_entry->pLimJoinReq = NULL; + /* Delete teh session if JOIN failure occurred. */ + if (result_code != eSIR_SME_SUCCESS) { + if (lim_set_link_state(mac_ctx, eSIR_LINK_DOWN_STATE, + session_entry->bssId, + session_entry->selfMacAddr, NULL, NULL) + != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("Failed to set the DownState.")); + if (lim_set_link_state + (mac_ctx, eSIR_LINK_IDLE_STATE, + session_entry->bssId, + session_entry->selfMacAddr, NULL, + NULL) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("Failed to set the LinkState.")); + pe_delete_session(mac_ctx, session_entry); + session_entry = NULL; + } + + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, result_code, + prot_status_code, session_entry, sme_session_id, sme_trans_id); +} + +/** + * lim_handle_sme_reaasoc_result() + * + ***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 +lim_handle_sme_reaasoc_result(tpAniSirGlobal pMac, tSirResultCodes resultCode, + uint16_t protStatusCode, tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL; + uint8_t smesessionId; + uint16_t smetransactionId; + + if (psessionEntry == NULL) { + PELOGE(lim_log(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 = + dph_get_hash_entry(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; + lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); + return; + } + } + /* Delete teh session if REASSOC failure occurred. */ + if (resultCode != eSIR_SME_SUCCESS) { + if (NULL != psessionEntry) { + pe_delete_session(pMac, psessionEntry); + psessionEntry = NULL; + } + } + lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP, resultCode, + protStatusCode, psessionEntry, smesessionId, + smetransactionId); +} /*** end limHandleSmeReassocResult() ***/ + +/** + * lim_process_mlm_add_sta_rsp() + * + ***FUNCTION: + * This function is called to process a WMA_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 lim_process_mlm_add_sta_rsp(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)) { + lim_process_ap_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry); + return; + } + lim_process_sta_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry); +} + +/** + * lim_process_sta_mlm_add_sta_rsp () - Process add sta response + * @mac_ctx: Pointer to mac context + * @msg: tpSirMsgQan Message structure + * @session_entry: PE session entry + * + * Process ADD STA response sent from WMA and posts results + * to SME. + * + * Return: Null + */ + +void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg, tpPESession session_entry) +{ + tLimMlmAssocCnf mlm_assoc_cnf; + tpDphHashNode sta_ds; + uint32_t msg_type = LIM_MLM_ASSOC_CNF; + tpAddStaParams add_sta_params = (tpAddStaParams) msg->bodyptr; + tpPESession ft_session = NULL; + uint8_t ft_session_id; + + if (NULL == add_sta_params) { + lim_log(mac_ctx, LOGE, FL("Encountered NULL Pointer")); + return; + } + + if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + msg_type = LIM_MLM_REASSOC_CNF; + + if (true == session_entry->fDeauthReceived) { + lim_log(mac_ctx, LOGE, + FL("Received Deauth frame in ADD_STA_RESP state")); + if (CDF_STATUS_SUCCESS == add_sta_params->status) { + lim_log(mac_ctx, LOGE, + FL("ADD_STA success, send update result code with eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA staIdx: %d limMlmState: %d"), + add_sta_params->staIdx, + session_entry->limMlmState); + + if (session_entry->limSmeState == + eLIM_SME_WT_REASSOC_STATE) + msg_type = 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. + */ + mlm_assoc_cnf.resultCode = + eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA; + session_entry->staId = add_sta_params->staIdx; + goto end; + } + } + + if (CDF_STATUS_SUCCESS == add_sta_params->status) { + if (eLIM_MLM_WT_ADD_STA_RSP_STATE != + session_entry->limMlmState) { + lim_log(mac_ctx, LOGE, + FL("Received WMA_ADD_STA_RSP in state %X"), + session_entry->limMlmState); + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_REFUSED; + goto end; + } + if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) { +#ifdef WLAN_FEATURE_VOWIFI_11R + /* check if we have keys(PTK)to install in case of 11r */ + tpftPEContext ft_ctx = &session_entry->ftPEContext; + ft_session = pe_find_session_by_bssid(mac_ctx, + session_entry->limReAssocbssId, &ft_session_id); + if (ft_session != NULL && + ft_ctx->PreAuthKeyInfo.extSetStaKeyParamValid + == true) { + tpLimMlmSetKeysReq pMlmStaKeys = + &ft_ctx->PreAuthKeyInfo.extSetStaKeyParam; + lim_send_set_sta_key_req(mac_ctx, pMlmStaKeys, + 0, 0, ft_session, false); + ft_ctx->PreAuthKeyInfo.extSetStaKeyParamValid = + false; + } +#endif + } + /* + * Update the DPH Hash Entry for this STA + * with proper state info + */ + sta_ds = + dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (NULL != sta_ds) + sta_ds->mlmStaContext.mlmState = + eLIM_MLM_LINK_ESTABLISHED_STATE; + else + lim_log(mac_ctx, LOGW, + FL("Fail to get DPH Hash Entry for AID - %d"), + DPH_STA_HASH_INDEX_PEER); + session_entry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + session_entry->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 + */ + session_entry->staId = add_sta_params->staIdx; + +#ifdef WLAN_DEBUG + mac_ctx->lim.gLimNumLinkEsts++; +#endif +#ifdef FEATURE_WLAN_TDLS + /* initialize TDLS peer related data */ + lim_init_tdls_data(mac_ctx, session_entry); +#endif + /* + * Return Assoc confirm to SME with success + * FIXME - Need the correct ASSOC RSP code to + * be passed in here + */ + mlm_assoc_cnf.resultCode = (tSirResultCodes) eSIR_SME_SUCCESS; + } else { + lim_log(mac_ctx, LOGE, FL("ADD_STA failed!")); + if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_FT_REASSOC_FAILURE; + else + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_REFUSED; + } +end: + if (NULL != msg->bodyptr) { + cdf_mem_free(add_sta_params); + msg->bodyptr = NULL; + } + /* Updating PE session Id */ + mlm_assoc_cnf.sessionId = session_entry->peSessionId; + lim_post_sme_message(mac_ctx, msg_type, (uint32_t *) &mlm_assoc_cnf); + if (true == session_entry->fDeauthReceived) + session_entry->fDeauthReceived = false; + return; +} + +void lim_process_mlm_del_bss_rsp(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)) { + lim_process_bt_amp_ap_mlm_del_bss_rsp(pMac, limMsgQ, psessionEntry); + return; + } + lim_process_sta_mlm_del_bss_rsp(pMac, limMsgQ, psessionEntry); + +#ifdef WLAN_FEATURE_11W + if (psessionEntry->limRmfEnabled) { + if (eSIR_SUCCESS != + lim_send_exclude_unencrypt_ind(pMac, true, psessionEntry)) { + lim_log(pMac, LOGE, + FL + ("Could not send down Exclude Unencrypted Indication!")); + } + } +#endif +} + +void lim_process_sta_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tpDeleteBssParams pDelBssParams = (tpDeleteBssParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = + dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + + if (NULL == pDelBssParams) { + lim_log(pMac, LOGE, FL("Invalid body pointer in message")); + goto end; + } + if (CDF_STATUS_SUCCESS == pDelBssParams->status) { + PELOGW(lim_log(pMac, LOGW, + FL("STA received the DEL_BSS_RSP for BSSID: %X."), + pDelBssParams->bssIdx); + ) + if (lim_set_link_state + (pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, + psessionEntry->selfMacAddr, NULL, + NULL) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("Failure in setting link state to IDLE")); + ) + statusCode = eSIR_SME_REFUSED; + goto end; + } + if (pStaDs == NULL) { + lim_log(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(lim_log + (pMac, LOGE, + FL + ("Received unexpected WMA_DEL_BSS_RSP in state %X"), + pStaDs->mlmStaContext.mlmState); + ) + statusCode = eSIR_SME_REFUSED; + goto end; + } + PELOG1(lim_log + (pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId); + lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1); + ) + } else { + lim_log(pMac, LOGE, FL("DEL BSS failed!")); + statusCode = eSIR_SME_STOP_BSS_FAILURE; + } +end: + if (0 != limMsgQ->bodyptr) { + cdf_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. + */ + lim_handle_del_bss_in_re_assoc_context(pMac, pStaDs, psessionEntry); + return; + } + lim_prepare_and_send_del_sta_cnf(pMac, pStaDs, statusCode, psessionEntry); + return; +} + +void lim_process_bt_amp_ap_mlm_del_bss_rsp(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) { + lim_log(pMac, LOGE, FL("Session entry passed is NULL")); + if (pDelBss != NULL) { + cdf_mem_free(pDelBss); + limMsgQ->bodyptr = NULL; + } + return; + } + + if (pDelBss == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!"));) + rc = eSIR_SME_REFUSED; + goto end; + } + pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, NO_SESSION, + pMac->lim.gLimMlmState)); + + if (eLIM_MLM_WT_DEL_BSS_RSP_STATE != psessionEntry->limMlmState) { + lim_log(pMac, LOGE, + FL("Received unexpected WMA_DEL_BSS_RSP in state %X"), + psessionEntry->limMlmState); + rc = eSIR_SME_REFUSED; + goto end; + } + if (pDelBss->status != CDF_STATUS_SUCCESS) { + lim_log(pMac, LOGE, FL("BSS: DEL_BSS_RSP error (%x) Bss %d "), + pDelBss->status, pDelBss->bssIdx); + rc = eSIR_SME_STOP_BSS_FAILURE; + goto end; + } + status = lim_set_link_state(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. + */ + dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable); + lim_delete_pre_auth_list(pMac); + /* Initialize number of associated stations during cleanup */ + psessionEntry->gLimNumOfCurrentSTAs = 0; +end: + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, rc, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + pe_delete_session(pMac, psessionEntry); + + if (pDelBss != NULL) { + cdf_mem_free(pDelBss); + limMsgQ->bodyptr = NULL; + } +} + +/** + * lim_process_mlm_del_sta_rsp() - Process DEL STA response + * @mac_ctx: Pointer to Global MAC structure + * @msg: The MsgQ header, which contains the response buffer + * + * This function is called to process a WMA_DEL_STA_RSP from + * WMA Upon receipt of this message from FW. + * + * Return: None + */ +void lim_process_mlm_del_sta_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + /* + * 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 session_entry; + tpDeleteStaParams del_sta_params; + del_sta_params = (tpDeleteStaParams) msg->bodyptr; + if (NULL == del_sta_params) { + lim_log(mac_ctx, LOGE, + FL("null pointer del_sta_params msg")); + return; + } + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + + session_entry = pe_find_session_by_session_id(mac_ctx, + del_sta_params->sessionId); + if (NULL == session_entry) { + lim_log(mac_ctx, LOGP, + FL("Session Doesn't exist")); + cdf_mem_free(del_sta_params); + msg->bodyptr = NULL; + return; + } + + if (LIM_IS_BT_AMP_AP_ROLE(session_entry) || + LIM_IS_AP_ROLE(session_entry)) { + lim_process_bt_amp_ap_mlm_del_sta_rsp(mac_ctx, msg, + session_entry); + return; + } + lim_process_sta_mlm_del_sta_rsp(mac_ctx, msg, session_entry); +} + +void lim_process_bt_amp_ap_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs; + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + if (limMsgQ->bodyptr == NULL) { + lim_log(pMac, LOGE, FL("limMsgQ->bodyptry NULL")); + return; + } + + pStaDs = + dph_get_hash_entry(pMac, pDelStaParams->assocId, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + lim_log(pMac, LOGE, + FL("DPH Entry for STA %X missing."), + pDelStaParams->assocId); + statusCode = eSIR_SME_REFUSED; + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + + return; + } + lim_log(pMac, LOG1, FL("Received del Sta Rsp in StaD MlmState : %d"), + pStaDs->mlmStaContext.mlmState); + if (CDF_STATUS_SUCCESS == pDelStaParams->status) { + lim_log(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)) { + lim_log(pMac, LOGE, + FL + ("Received unexpected WMA_DEL_STA_RSP in state %s for staId %d assocId %d "), + lim_mlm_state_str(pStaDs->mlmStaContext.mlmState), + pStaDs->staIndex, pStaDs->assocId); + statusCode = eSIR_SME_REFUSED; + goto end; + } + + lim_log(pMac, LOG1, + FL("Deleted STA AssocID %d staId %d MAC "), + pStaDs->assocId, pStaDs->staIndex); + lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1); + if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE == + pStaDs->mlmStaContext.mlmState) { + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + if (lim_add_sta(pMac, pStaDs, false, psessionEntry) != + eSIR_SUCCESS) { + PELOGE(lim_log + (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 == + lim_tspec_find_by_assoc_id(pMac, + pStaDs->assocId, + &pStaDs->qos.addts.tspec, + &pMac->lim.tspecInfo[0], + &pTspecInfo)) { + lim_admit_control_delete_ts(pMac, + pStaDs-> + assocId, + &pStaDs-> + qos. + addts. + tspec. + tsinfo, + NULL, + &pTspecInfo-> + idx); + } + } + lim_reject_association(pMac, + pStaDs->staAddr, + pStaDs->mlmStaContext. + subType, true, + pStaDs->mlmStaContext. + authType, pStaDs->assocId, + true, + (tSirResultCodes) + eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } + return; + } + } else { + lim_log(pMac, LOGW, FL("DEL STA failed!")); + statusCode = eSIR_SME_REFUSED; + } +end: + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != + pStaDs->mlmStaContext.mlmState) { + lim_prepare_and_send_del_sta_cnf(pMac, pStaDs, statusCode, + psessionEntry); + } + return; +} + +void lim_process_sta_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tSirResultCodes statusCode = eSIR_SME_SUCCESS; + tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = NULL; + if (NULL == pDelStaParams) { + lim_log(pMac, LOGE, FL("Encountered NULL Pointer")); + goto end; + } + if (CDF_STATUS_SUCCESS == pDelStaParams->status) { + pStaDs = + dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + /* TODO: any response to be sent out here ? */ + lim_log(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) { + /* TODO: any response to be sent out here ? */ + lim_log(pMac, LOGE, + FL + ("Received unexpected WMA_DELETE_STA_RSP in state %s"), + lim_mlm_state_str(psessionEntry->limMlmState)); + statusCode = eSIR_SME_REFUSED; + goto end; + } + PELOG1(lim_log + (pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId); + lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1); + ) + lim_log(pMac, LOGW, + FL("DEL_STA_RSP received for assocID: %X"), + pDelStaParams->assocId); + /* we must complete all cleanup related to delSta before calling limDelBSS. */ + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + } + statusCode = + (tSirResultCodes) lim_del_bss(pMac, pStaDs, 0, psessionEntry); + return; + } else { + lim_log(pMac, LOGE, FL("DEL_STA failed for sta Id %d"), + pDelStaParams->staIdx); + statusCode = eSIR_SME_REFUSED; + } +end: + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; + } + return; +} + +void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tpAddStaParams pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr; + tpDphHashNode pStaDs = NULL; + + if (NULL == pAddStaParams) { + lim_log(pMac, LOGE, FL("Invalid body pointer in message")); + goto end; + } + + pStaDs = + dph_get_hash_entry(pMac, pAddStaParams->assocId, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + /* TODO: any response to be sent out here ? */ + lim_log(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 ? */ + lim_log(pMac, LOGE, + FL("Received unexpected WMA_ADD_STA_RSP in state %X"), + pStaDs->mlmStaContext.mlmState); + goto end; + } + if (CDF_STATUS_SUCCESS != pAddStaParams->status) { + PELOGE(lim_log + (pMac, LOGE, + FL("Error! rcvd delSta rsp from HAL with status %d"), + pAddStaParams->status); + ) + lim_reject_association(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; + /* 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; + lim_log(pMac, LOG1, + FL("AddStaRsp Success.STA AssocID %d staId %d MAC "), + pStaDs->assocId, pStaDs->staIndex); + lim_print_mac_addr(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 + */ + lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry); + /* fall though to reclaim the original Add STA Response message */ +end: + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pAddStaParams); + limMsgQ->bodyptr = NULL; + } + return; +} + +/** + * lim_process_ap_mlm_add_bss_rsp() + * + ***FUNCTION: + * This function is called to process a WMA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WMA_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 WMA_ADD_BSS_REQ to HAL + * HAL responds with WMA_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 lim_process_mlm_start_req + * 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 lim_process_ap_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) +{ + tLimMlmStartCnf mlmStartCnf; + tpPESession psessionEntry; + uint8_t isWepEnabled = false; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + if (NULL == pAddBssParams) { + lim_log(pMac, LOGE, FL("Encountered NULL Pointer")); + goto end; + } + /* TBD: free the memory before returning, do it for all places where lookup fails. */ + psessionEntry = pe_find_session_by_session_id(pMac, + pAddBssParams->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("session does not exist for given sessionId")); + ) + if (NULL != pAddBssParams) { + cdf_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } + return; + } + /* Update PE session Id */ + mlmStartCnf.sessionId = pAddBssParams->sessionId; + if (CDF_STATUS_SUCCESS == pAddBssParams->status) { + PELOG2(lim_log + (pMac, LOG2, + FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS")); + ) + if (lim_set_link_state + (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(mac_trace + (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); + } + psessionEntry->bssIdx = (uint8_t) 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; + sch_edca_profile_update(pMac, psessionEntry); + lim_init_pre_auth_list(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)) + lim_log(pMac, LOG1, + FL("WPA/WPA2 SAP configuration\n")); + else { + if (pMac->lim.gLimAssocStaLimit > + MAX_SUPPORTED_PEERS_WEP) { + lim_log(pMac, LOG1, + FL("WEP SAP Configuration\n")); + pMac->lim.gLimAssocStaLimit = + MAX_SUPPORTED_PEERS_WEP; + isWepEnabled = true; + } + } + } + lim_init_peer_idxpool(pMac, psessionEntry); + + /* Start OLBC timer */ + if (tx_timer_activate + (&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != + TX_SUCCESS) { + lim_log(pMac, LOGE, FL("tx_timer_activate failed")); + } + + /* Apply previously set configuration at HW */ + lim_apply_configuration(pMac, psessionEntry); + + /* In lim_apply_configuration 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 { + lim_log(pMac, LOGE, FL("WMA_ADD_BSS_REQ failed with status %d"), + pAddBssParams->status); + mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf); +end: + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + +/** + * lim_process_ibss_mlm_add_bss_rsp() + * + ***FUNCTION: + * This function is called to process a WMA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WMA_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 WMA_ADD_BSS_REQ to HAL + * HAL responds with WMA_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 lim_process_mlm_start_req + * 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 +lim_process_ibss_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tLimMlmStartCnf mlmStartCnf; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + + if (NULL == pAddBssParams) { + lim_log(pMac, LOGE, FL("Invalid body pointer in message")); + goto end; + } + if (CDF_STATUS_SUCCESS == pAddBssParams->status) { + PELOG1(lim_log + (pMac, LOG1, + FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS")); + ) + if (lim_set_link_state + (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(mac_trace + (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); + psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx; + psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + psessionEntry->statypeForBss = STA_ENTRY_SELF; + sch_edca_profile_update(pMac, psessionEntry); + if (0 == psessionEntry->freePeerIdxHead) + lim_init_peer_idxpool(pMac, psessionEntry); + + /* Apply previously set configuration at HW */ + lim_apply_configuration(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) { + lim_ibss_add_bss_rsp_when_coalescing(pMac, limMsgQ->bodyptr, + psessionEntry); + goto end; + } + } else { + lim_log(pMac, LOGE, FL("WMA_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; + lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf); +end: + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + +/** + * csr_neighbor_roam_handoff_req_hdlr - Processes handoff request + * @mac_ctx: Pointer to mac context + * @msg: message sent to HDD + * @session_entry: PE session handle + * + * This function is called to process a WMA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL if the state is pre assoc. + * + * Return: Null + */ +static void +lim_process_sta_add_bss_rsp_pre_assoc(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg, tpPESession session_entry) +{ + tpAddBssParams pAddBssParams = (tpAddBssParams) msg->bodyptr; + tAniAuthType cfgAuthType, authMode; + tLimMlmAuthReq *pMlmAuthReq; + tpDphHashNode pStaDs = NULL; + + if (NULL == pAddBssParams) { + lim_log(mac_ctx, LOGE, FL("Invalid body pointer in message")); + goto joinFailure; + } + if (CDF_STATUS_SUCCESS == pAddBssParams->status) { + pStaDs = dph_add_hash_entry(mac_ctx, + pAddBssParams->staContext.staMac, + DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (pStaDs == NULL) { + /* Could not add hash table entry */ + lim_log(mac_ctx, LOGE, + FL("could not add hash entry at DPH for ")); + lim_print_mac_addr(mac_ctx, + pAddBssParams->staContext.staMac, LOGE); + goto joinFailure; + } + session_entry->bssIdx = (uint8_t) 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_cfg_get_int(mac_ctx, WNI_CFG_AUTHENTICATION_TYPE, + (uint32_t *) &cfgAuthType) != eSIR_SUCCESS) { + /* + * Could not get AuthType from CFG. + * Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve AuthType")); + } + /* Try Open Authentication first */ + if (cfgAuthType == eSIR_AUTO_SWITCH) + authMode = eSIR_OPEN_SYSTEM; + else + authMode = cfgAuthType; + + /* Trigger MAC based Authentication */ + pMlmAuthReq = cdf_mem_malloc(sizeof(tLimMlmAuthReq)); + if (NULL == pMlmAuthReq) { + lim_log(mac_ctx, LOGP, + FL("Allocate Memory failed for mlmAuthReq")); + return; + } + sir_copy_mac_addr(pMlmAuthReq->peerMacAddr, + session_entry->bssId); + + pMlmAuthReq->authType = authMode; + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + (uint32_t *) &pMlmAuthReq->authFailureTimeout) + != eSIR_SUCCESS) { + /* + * Could not get AuthFailureTimeout + * value from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("Fail: retrieve AuthFailureTimeout value")); + } + session_entry->limMlmState = eLIM_MLM_JOINED_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_JOINED_STATE)); + pMlmAuthReq->sessionId = session_entry->peSessionId; + session_entry->limPrevSmeState = session_entry->limSmeState; + session_entry->limSmeState = eLIM_SME_WT_AUTH_STATE; + /* remember staId in case of assoc timeout/failure handling */ + session_entry->staId = pAddBssParams->staContext.staIdx; + + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + lim_log(mac_ctx, LOG1, + FL("SessionId:%d lim_post_mlm_message " + "LIM_MLM_AUTH_REQ with limSmeState:%d"), + session_entry->peSessionId, session_entry->limSmeState); + lim_post_mlm_message(mac_ctx, LIM_MLM_AUTH_REQ, + (uint32_t *) pMlmAuthReq); + return; + } + +joinFailure: + { + session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + + /* Send Join response to Host */ + lim_handle_sme_join_result(mac_ctx, eSIR_SME_REFUSED, + eSIR_MAC_UNSPEC_FAILURE_STATUS, session_entry); + } + +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/*------------------------------------------------------------------------------------------ + * + * Function to handle WMA_ADD_BSS_RSP, in FT reassoc state. + * Function to Send ReAssociation Request. + * + * + ***------------------------------------------------------------------------------------------ + */ +static inline void +lim_process_sta_mlm_add_bss_rsp_ft(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; /* keep sme */ + tpDphHashNode pStaDs = NULL; + tpAddStaParams pAddStaParams = NULL; + uint32_t listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + uint32_t selfStaDot11Mode = 0; + + /* Sanity Checks */ + + if (pAddBssParams == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));) + goto end; + } + if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE != + psessionEntry->limMlmState) { + goto end; + } + + pStaDs = dph_add_hash_entry(pMac, pAddBssParams->bssId, + DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + /* Could not add hash table entry */ + PELOGE(lim_log + (pMac, LOGE, FL("could not add hash entry at DPH for ")); + ) + lim_print_mac_addr(pMac, pAddBssParams->staContext.staMac, + LOGE); + goto end; + } + /* Prepare and send Reassociation request frame */ + /* start reassoc timer. */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress != true) { +#endif + pMac->lim.limTimers.gLimReassocFailureTimer.sessionId = + psessionEntry->peSessionId; + /* / Start reassociation failure timer */ + MTRACE(mac_trace + (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 */ + lim_log(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 = + cdf_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == + pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) + goto end; + cdf_mem_set(pMac->lim.pSessionEntry-> + pLimMlmReassocRetryReq, + sizeof(tLimMlmReassocReq), 0); + cdf_mem_copy(pMac->lim.pSessionEntry-> + pLimMlmReassocRetryReq, + psessionEntry->pLimMlmReassocReq, + sizeof(tLimMlmReassocReq)); + } + pMac->lim.reAssocRetryAttempt = 0; +#endif + lim_send_reassoc_req_with_ft_ies_mgmt_frame(pMac, + psessionEntry-> + pLimMlmReassocReq, + psessionEntry); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +} else { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_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(mac_trace + (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, + eLIM_MLM_WT_FT_REASSOC_RSP_STATE)); + PELOGE(lim_log + (pMac, LOG1, FL("Set the mlm state to %d session=%d"), + psessionEntry->limMlmState, psessionEntry->peSessionId); + ) + + psessionEntry->bssIdx = (uint8_t) 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 + rrm_cache_mgmt_tx_power(pMac, pAddBssParams->txMgmtPower, psessionEntry); +#endif + + pAddStaParams = cdf_mem_malloc(sizeof(tAddStaParams)); + if (NULL == pAddStaParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during ADD_STA")); + goto end; + } + cdf_mem_set((uint8_t *) pAddStaParams, sizeof(tAddStaParams), 0); + + /* / Add STA context at MAC HW (BMU, RHP & TFP) */ + cdf_mem_copy((uint8_t *) pAddStaParams->staMac, + (uint8_t *) psessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) pAddStaParams->bssId, + psessionEntry->bssId, sizeof(tSirMacAddr)); + + pAddStaParams->staType = STA_ENTRY_SELF; + pAddStaParams->status = CDF_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 != true) +#endif + pAddStaParams->staIdx = STA_INVALID_IDX; + pAddStaParams->updateSta = false; + + pAddStaParams->shortPreambleSupported = + (uint8_t) psessionEntry->beaconParams.fShortPreamble; +#ifdef WLAN_FEATURE_11AC + lim_populate_peer_rate_set(pMac, &pAddStaParams->supportedRates, NULL, + false, psessionEntry, NULL); +#else + lim_populate_peer_rate_set(pMac, &pAddStaParams->supportedRates, NULL, + false, psessionEntry); +#endif + + if (psessionEntry->htCapability) { + pAddStaParams->htCapable = psessionEntry->htCapability; +#ifdef WLAN_FEATURE_11AC + pAddStaParams->vhtCapable = psessionEntry->vhtCapability; + pAddStaParams->ch_width = psessionEntry->ch_width; +#endif + + pAddStaParams->greenFieldCapable = + lim_get_ht_capability(pMac, eHT_GREENFIELD, + psessionEntry); + pAddStaParams->mimoPS = + lim_get_ht_capability(pMac, eHT_MIMO_POWER_SAVE, + psessionEntry); + pAddStaParams->rifsMode = + lim_get_ht_capability(pMac, eHT_RIFS_MODE, psessionEntry); + pAddStaParams->lsigTxopProtection = + lim_get_ht_capability(pMac, eHT_LSIG_TXOP_PROTECTION, + psessionEntry); + pAddStaParams->maxAmpduDensity = + lim_get_ht_capability(pMac, eHT_MPDU_DENSITY, psessionEntry); + pAddStaParams->maxAmpduSize = + lim_get_ht_capability(pMac, eHT_MAX_RX_AMPDU_FACTOR, + psessionEntry); + pAddStaParams->maxAmsduSize = + lim_get_ht_capability(pMac, eHT_MAX_AMSDU_LENGTH, + psessionEntry); + pAddStaParams->fDsssCckMode40Mhz = + lim_get_ht_capability(pMac, eHT_DSSS_CCK_MODE_40MHZ, + psessionEntry); + pAddStaParams->fShortGI20Mhz = + lim_get_ht_capability(pMac, eHT_SHORT_GI_20MHZ, psessionEntry); + pAddStaParams->fShortGI40Mhz = + lim_get_ht_capability(pMac, eHT_SHORT_GI_40MHZ, psessionEntry); + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); + pAddStaParams->listenInterval = (uint16_t) listenInterval; + + wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + pAddStaParams->supportedRates.opRateMode = + lim_get_sta_rate_mode((uint8_t) 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) { + cdf_mem_free(pAddBssParams); + pAddBssParams = NULL; + limMsgQ->bodyptr = NULL; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (psessionEntry->bRoamSynchInProgress) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:Prepare and save pAddStaReq in pMac for post-assoc-rsp"); + lim_process_assoc_rsp_frame(pMac, pMac->roam.pReassocResp, + LIM_REASSOC, psessionEntry); + } +#endif + return; + +end: + /* Free up buffer allocated for reassocReq */ + if (psessionEntry != NULL) + if (psessionEntry->pLimMlmReassocReq != NULL) { + cdf_mem_free(psessionEntry->pLimMlmReassocReq); + psessionEntry->pLimMlmReassocReq = NULL; + } + + if (pAddBssParams != NULL) { + cdf_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; + + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ +/** + * lim_process_sta_mlm_add_bss_rsp() - Process ADD BSS response + * @mac_ctx: Pointer to Global MAC structure + * @msg: The MsgQ header, which contains the response buffer + * + * This function is called to process a WMA_ADD_BSS_RSP from HAL. + * Upon receipt of this message from HAL, MLME - + * > Validates the result of WMA_ADD_BSS_REQ + * > Now, send an ADD_STA to HAL and ADD the "local" STA itself + * + * MLME had sent WMA_ADD_BSS_REQ to HAL + * HAL responded with WMA_ADD_BSS_RSP to MLME + * MLME now sends WMA_ADD_STA_REQ to HAL + * ASSUMPTIONS: + * tSirMsgQ.body is allocated by MLME during lim_process_mlm_join_req + * tSirMsgQ.body will now be freed by this routine + * + * Return: None + */ +static void +lim_process_sta_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg, tpPESession session_entry) +{ + tpAddBssParams add_bss_params = (tpAddBssParams) msg->bodyptr; + tLimMlmAssocCnf mlm_assoc_cnf; + uint32_t msg_type = LIM_MLM_ASSOC_CNF; + uint32_t sub_type = LIM_ASSOC; + tpDphHashNode sta_ds = NULL; + uint16_t sta_idx = STA_INVALID_IDX; + uint8_t update_sta = false; + mlm_assoc_cnf.resultCode = eSIR_SME_SUCCESS; + + if (eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE == + session_entry->limMlmState) { + lim_log(mac_ctx, LOG1, + "SessionId:%d lim_process_sta_add_bss_rsp_pre_assoc", + session_entry->peSessionId); + lim_process_sta_add_bss_rsp_pre_assoc(mac_ctx, msg, + session_entry); + goto end; + } + if (eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE == session_entry->limMlmState +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + || (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == + session_entry->limMlmState) +#endif + ) { + msg_type = LIM_MLM_REASSOC_CNF; + sub_type = 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 (sir_compare_mac_addr(session_entry->bssId, + session_entry->limReAssocbssId)) { + sta_idx = session_entry->staId; + update_sta = true; + } + } + + if (add_bss_params == 0) + goto end; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session_entry->bRoamSynchInProgress) + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "LFR3:lim_process_sta_mlm_add_bss_rsp"); +#endif + + if (CDF_STATUS_SUCCESS == add_bss_params->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 == + session_entry->limMlmState) { +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("Mlm=%d %d"), + session_entry->limMlmState, + eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE); +#endif + lim_process_sta_mlm_add_bss_rsp_ft(mac_ctx, msg, + session_entry); + goto end; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + /* Set MLME state */ + session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + session_entry->limMlmState)); + /* to know the session started for self or for peer */ + session_entry->statypeForBss = STA_ENTRY_PEER; + /* Now, send WMA_ADD_STA_REQ */ + lim_log(mac_ctx, LOGW, + FL("SessionId:%d On STA: ADD_BSS was successful"), + session_entry->peSessionId); + sta_ds = + dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, + FL("Session:%d Fail to add Self Entry for STA"), + session_entry->peSessionId); + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_REFUSED; + } else { + session_entry->bssIdx = + (uint8_t) add_bss_params->bssIdx; + /* Success, handle below */ + sta_ds->bssId = add_bss_params->bssIdx; + /* + * STA Index(genr by HAL) for the BSS + * entry is stored here + */ + sta_ds->staIndex = add_bss_params->staContext.staIdx; + sta_ds->ucUcastSig = + add_bss_params->staContext.ucUcastSig; + sta_ds->ucBcastSig = + add_bss_params->staContext.ucBcastSig; + /* Downgrade the EDCA parameters if needed */ + lim_set_active_edca_params(mac_ctx, + session_entry->gLimEdcaParams, session_entry); + lim_send_edca_params(mac_ctx, + session_entry->gLimEdcaParamsActive, + sta_ds->bssId); +#if defined WLAN_FEATURE_VOWIFI + rrm_cache_mgmt_tx_power(mac_ctx, + add_bss_params->txMgmtPower, session_entry); +#endif + if (lim_add_sta_self(mac_ctx, sta_idx, update_sta, + session_entry) != eSIR_SUCCESS) { + /* Add STA context at HW */ + lim_log(mac_ctx, LOGE, + FL("Session:%d could not Add Self" + "Entry for the station"), + session_entry->peSessionId); + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_REFUSED; + } + } + } else { + lim_log(mac_ctx, LOGP, FL("SessionId:%d ADD_BSS failed!"), + session_entry->peSessionId); + /* Return Assoc confirm to SME with failure */ + if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == + session_entry->limMlmState) + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_FT_REASSOC_FAILURE; + else + mlm_assoc_cnf.resultCode = + (tSirResultCodes) eSIR_SME_REFUSED; + } + + if (mlm_assoc_cnf.resultCode != eSIR_SME_SUCCESS) { + session_entry->limMlmState = eLIM_MLM_IDLE_STATE; + if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE, + session_entry->bssId, + session_entry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, FL("Failed to set the LinkState")); + /* Update PE session Id */ + mlm_assoc_cnf.sessionId = session_entry->peSessionId; + lim_post_sme_message(mac_ctx, msg_type, + (uint32_t *) &mlm_assoc_cnf); + } +end: + if (0 != msg->bodyptr) { + cdf_mem_free(add_bss_params); + msg->bodyptr = NULL; + } +} + +/** + * lim_process_mlm_add_bss_rsp() - Processes ADD BSS Response + * + * @mac_ctx - Pointer to Global MAC structure + * @msg - The MsgQ header, which contains the response buffer + * + * This function is called to process a WMA_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: + * WMA_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 + * + * Return None + */ +void lim_process_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + tLimMlmStartCnf mlm_start_cnf; + tpPESession session_entry; + tpAddBssParams add_bss_param = (tpAddBssParams) (msg->bodyptr); + tSirBssType bss_type; + + if (NULL == add_bss_param) { + lim_log(mac_ctx, LOGE, FL("Encountered NULL Pointer")); + return; + } + + /* + * 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(mac_ctx, true); + /* Validate SME/LIM/MLME state */ + session_entry = pe_find_session_by_session_id(mac_ctx, + add_bss_param->sessionId); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL("SessionId:%d Session Doesn't exist"), + add_bss_param->sessionId); + if (NULL != add_bss_param) { + cdf_mem_free(add_bss_param); + msg->bodyptr = NULL; + } + return; + } + + session_entry->nss = add_bss_param->nss; + bss_type = session_entry->bssType; + /* update PE session Id */ + mlm_start_cnf.sessionId = session_entry->peSessionId; + if (eSIR_IBSS_MODE == bss_type) { + lim_process_ibss_mlm_add_bss_rsp(mac_ctx, msg, session_entry); + } else { + if (eLIM_SME_WT_START_BSS_STATE == session_entry->limSmeState) { + if (eLIM_MLM_WT_ADD_BSS_RSP_STATE != + session_entry->limMlmState) { + /* Mesg received from HAL in Invalid state! */ + lim_log(mac_ctx, LOGE, + FL("SessionId:%d Received " + " WMA_ADD_BSS_RSP in state %X"), + session_entry->peSessionId, + session_entry->limMlmState); + mlm_start_cnf.resultCode = + eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + if (0 != msg->bodyptr) { + cdf_mem_free(add_bss_param); + msg->bodyptr = NULL; + } + lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF, + (uint32_t *) &mlm_start_cnf); + } else if ((bss_type == eSIR_BTAMP_AP_MODE) || + (bss_type == eSIR_BTAMP_STA_MODE)) { + lim_process_btamp_add_bss_rsp(mac_ctx, msg, + session_entry); + } else + lim_process_ap_mlm_add_bss_rsp(mac_ctx, msg); + } else { + /* Called while processing assoc response */ + lim_process_sta_mlm_add_bss_rsp(mac_ctx, msg, + session_entry); + } + } + +#ifdef WLAN_FEATURE_11W + if (session_entry->limRmfEnabled) { + if (eSIR_SUCCESS != + lim_send_exclude_unencrypt_ind(mac_ctx, false, + session_entry)) { + lim_log(mac_ctx, LOGE, + FL("Failed to send Exclude Unencrypted Ind.")); + } + } +#endif +} + +/** + * lim_process_mlm_set_sta_key_rsp() - Process STA key response + * + * @mac_ctx: Pointer to Global MAC structure + * @msg: The MsgQ header, which contains the response buffer + * + * This function is called to process the following two + * messages from HAL: + * 1) WMA_SET_BSSKEY_RSP + * 2) WMA_SET_STAKEY_RSP + * 3) WMA_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: + * WMA_SET_BSSKEY_RSP/WMA_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 + * Assumption: + * 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 + * + * Return: None + */ +void lim_process_mlm_set_sta_key_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + uint8_t resp_reqd = 1; + tLimMlmSetKeysCnf mlm_set_key_cnf; + uint8_t session_id = 0; + tpPESession session_entry; + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + cdf_mem_set((void *)&mlm_set_key_cnf, sizeof(tLimMlmSetKeysCnf), 0); + if (NULL == msg->bodyptr) { + PELOGE(lim_log(mac_ctx, LOGE, FL("msg bodyptr is NULL"));) + return; + } + session_id = ((tpSetStaKeyParams) msg->bodyptr)->sessionId; + session_entry = pe_find_session_by_session_id(mac_ctx, session_id); + if (session_entry == NULL) { + PELOGE(lim_log(mac_ctx, LOGE, + FL("session does not exist for given session_id"));) + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + return; + } + if (eLIM_MLM_WT_SET_STA_KEY_STATE != session_entry->limMlmState) { + /* Mesg received from HAL in Invalid state! */ + lim_log(mac_ctx, LOGE, + FL("Received unexpected [Mesg Id - %d] in state %X"), + msg->type, session_entry->limMlmState); + /* There's not much that MLME can do at this stage... */ + resp_reqd = 0; + } else { + mlm_set_key_cnf.resultCode = + (uint16_t)(((tpSetStaKeyParams) msg->bodyptr)->status); + } + + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + /* Restore MLME state */ + session_entry->limMlmState = session_entry->limPrevMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, session_entry->limMlmState)); + if (resp_reqd) { + tpLimMlmSetKeysReq lpLimMlmSetKeysReq = + (tpLimMlmSetKeysReq) mac_ctx->lim.gpLimMlmSetKeysReq; + /* Prepare and Send LIM_MLM_SETKEYS_CNF */ + if (NULL != lpLimMlmSetKeysReq) { + cdf_mem_copy((uint8_t *) &mlm_set_key_cnf.peerMacAddr, + (uint8_t *) lpLimMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + /* + * Free the buffer cached for the global + * mac_ctx->lim.gpLimMlmSetKeysReq + */ + cdf_mem_free(mac_ctx->lim.gpLimMlmSetKeysReq); + mac_ctx->lim.gpLimMlmSetKeysReq = NULL; + } + mlm_set_key_cnf.sessionId = session_id; + lim_post_sme_message(mac_ctx, LIM_MLM_SETKEYS_CNF, + (uint32_t *) &mlm_set_key_cnf); + } +} + +/** + * lim_process_mlm_set_bss_key_rsp() - handles BSS key + * + * @mac_ctx: A pointer to Global MAC structure + * @msg: Message from SME + * + * This function processes BSS key response and updates + * PE status accordingly. + * + * Return: NULL + */ +void lim_process_mlm_set_bss_key_rsp(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + tLimMlmSetKeysCnf set_key_cnf; + uint16_t result_status; + uint8_t session_id = 0; + tpPESession session_entry; + tpLimMlmSetKeysReq set_key_req; + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + cdf_mem_set((void *)&set_key_cnf, sizeof(tLimMlmSetKeysCnf), 0); + if (NULL == msg->bodyptr) { + PELOGE(lim_log(mac_ctx, LOGE, FL("msg bodyptr is null"));) + return; + } + session_id = ((tpSetBssKeyParams) msg->bodyptr)->sessionId; + session_entry = pe_find_session_by_session_id(mac_ctx, session_id); + if (session_entry == NULL) { + PELOGE(lim_log(mac_ctx, LOGE, + FL("session does not exist for given sessionId [%d]"), + session_id);) + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + return; + } + if (eLIM_MLM_WT_SET_BSS_KEY_STATE == session_entry->limMlmState) + result_status = + (uint16_t)(((tpSetBssKeyParams)msg->bodyptr)->status); + else + /* + * BCAST key also uses tpSetStaKeyParams. + * Done this way for readabilty. + */ + result_status = + (uint16_t)(((tpSetStaKeyParams)msg->bodyptr)->status); + + /* Validate MLME state */ + if (eLIM_MLM_WT_SET_BSS_KEY_STATE != session_entry->limMlmState && + eLIM_MLM_WT_SET_STA_BCASTKEY_STATE != + session_entry->limMlmState) { + /* Msg received from HAL in Invalid state! */ + lim_log(mac_ctx, LOGE, + FL("Received unexpected [Mesg Id - %d] in state %X"), + msg->type, session_entry->limMlmState); + } else { + set_key_cnf.resultCode = result_status; + } + + cdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + /* Restore MLME state */ + session_entry->limMlmState = session_entry->limPrevMlmState; + + MTRACE(mac_trace + (mac_ctx, TRACE_CODE_MLM_STATE, session_entry->peSessionId, + session_entry->limMlmState)); + set_key_req = + (tpLimMlmSetKeysReq) mac_ctx->lim.gpLimMlmSetKeysReq; + set_key_cnf.sessionId = session_id; + + /* Prepare and Send LIM_MLM_SETKEYS_CNF */ + if (NULL != set_key_req) { + cdf_mem_copy((uint8_t *) &set_key_cnf.peerMacAddr, + (uint8_t *) set_key_req->peerMacAddr, + sizeof(tSirMacAddr)); + /* + * Free the buffer cached for the + * global mac_ctx->lim.gpLimMlmSetKeysReq + */ + cdf_mem_free(mac_ctx->lim.gpLimMlmSetKeysReq); + mac_ctx->lim.gpLimMlmSetKeysReq = NULL; + } + lim_post_sme_message(mac_ctx, LIM_MLM_SETKEYS_CNF, + (uint32_t *) &set_key_cnf); +} + +/** + * lim_process_switch_channel_re_assoc_req() + * + ***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 lim_process_switch_channel_re_assoc_req(tpAniSirGlobal pMac, + tpPESession psessionEntry, + CDF_STATUS status) +{ + tLimMlmReassocCnf mlmReassocCnf; + tLimMlmReassocReq *pMlmReassocReq; + pMlmReassocReq = + (tLimMlmReassocReq *) (psessionEntry->pLimMlmReassocReq); + if (pMlmReassocReq == NULL) { + lim_log(pMac, LOGP, + FL + ("pLimMlmReassocReq does not exist for given switchChanSession")); + mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + if (status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("Change channel failed!!"));) + mlmReassocCnf.resultCode = eSIR_SME_CHANNEL_SWITCH_FAIL; + goto end; + } + /* / Start reassociation failure timer */ + MTRACE(mac_trace + (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 */ + lim_log(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 */ + lim_send_reassoc_req_mgmt_frame(pMac, pMlmReassocReq, psessionEntry); + return; +end: + /* Free up buffer allocated for reassocReq */ + if (pMlmReassocReq != NULL) { + /* Update PE session Id */ + mlmReassocCnf.sessionId = pMlmReassocReq->sessionId; + cdf_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; + + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); +} + + +/** + * lim_process_switch_channel_join_req() -Initiates probe request + * + * @mac_ctx - A pointer to Global MAC structure + * @sessionEntry - session related information. + * @status - channel switch success/failure + * + * This function is called to send the probe req mgmt frame + * after the switchChannelRsp message is received from HAL. + * + * Return None + */ +static void lim_process_switch_channel_join_req( + tpAniSirGlobal mac_ctx, tpPESession session_entry, + CDF_STATUS status) +{ + tSirMacSSid ssId; + tLimMlmJoinCnf join_cnf; + if (status != CDF_STATUS_SUCCESS) { + PELOGE(lim_log(mac_ctx, LOGE, FL("Change channel failed!!"));) + goto error; + } + + if ((NULL == session_entry) || (NULL == session_entry->pLimMlmJoinReq) + || (NULL == session_entry->pLimJoinReq)) { + PELOGE(lim_log(mac_ctx, 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 (session_entry->bssType == eSIR_BTAMP_AP_MODE) { + if (lim_set_link_state + (mac_ctx, eSIR_LINK_BTAMP_PREASSOC_STATE, + session_entry->bssId, session_entry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) { + PELOGE(lim_log + (mac_ctx, LOGE, + FL("Sessionid: %d Set link state " + "failed!! BSSID:" MAC_ADDRESS_STR), + session_entry->peSessionId, + MAC_ADDR_ARRAY(session_entry->bssId));) + goto error; + } + } + + session_entry->limPrevMlmState = session_entry->limMlmState; + session_entry->limMlmState = eLIM_MLM_WT_JOIN_BEACON_STATE; + lim_log(mac_ctx, LOG1, + FL("Sessionid %d prev lim state %d new lim state %d " + "systemrole = %d"), session_entry->peSessionId, + session_entry->limPrevMlmState, + session_entry->limMlmState, GET_LIM_SYSTEM_ROLE(session_entry)); + + /* Apply previously set configuration at HW */ + lim_apply_configuration(mac_ctx, session_entry); + + /* + * If sendDeauthBeforeCon is enabled, Send Deauth first to AP if last + * disconnection was caused by HB failure. + */ + if(mac_ctx->roam.configParam.sendDeauthBeforeCon) { + int apCount; + + for(apCount = 0; apCount < 2; apCount++) { + + if (cdf_mem_compare(session_entry->pLimMlmJoinReq->bssDescription.bssId, + mac_ctx->lim.gLimHeartBeatApMac[apCount], sizeof(tSirMacAddr))) { + + lim_log(mac_ctx, LOGE, FL("Index %d Sessionid: %d Send deauth on " + "channel %d to BSSID: "MAC_ADDRESS_STR ), apCount, + session_entry->peSessionId, session_entry->currentOperChannel, + MAC_ADDR_ARRAY(session_entry->pLimMlmJoinReq->bssDescription. + bssId)); + + lim_send_deauth_mgmt_frame(mac_ctx, eSIR_MAC_UNSPEC_FAILURE_REASON, + session_entry->pLimMlmJoinReq->bssDescription.bssId, + session_entry, false ); + + cdf_mem_zero(mac_ctx->lim.gLimHeartBeatApMac[apCount], + sizeof(tSirMacAddr)); + break; + } + } + } + + /* Wait for Beacon to announce join success */ + cdf_mem_copy(ssId.ssId, + session_entry->ssId.ssId, session_entry->ssId.length); + ssId.length = session_entry->ssId.length; + + lim_deactivate_and_change_timer(mac_ctx, + eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); + + /* assign appropriate sessionId to the timer object */ + mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId = + session_entry->peSessionId; + lim_log(mac_ctx, LOG1, + FL("Sessionid: %d Send Probe req on channel %d ssid:%.*s " + "BSSID: " MAC_ADDRESS_STR), session_entry->peSessionId, + session_entry->currentOperChannel, ssId.length, ssId.ssId, + MAC_ADDR_ARRAY( + session_entry->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(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, + session_entry->peSessionId, eLIM_JOIN_FAIL_TIMER)); + if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimJoinFailureTimer) != + TX_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("couldn't activate Join failure timer")); + session_entry->limMlmState = session_entry->limPrevMlmState; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, + mac_ctx->lim.gLimMlmState)); + session_entry->pLimMlmJoinReq = NULL; + goto error; + } + /* include additional IE if there is */ + lim_send_probe_req_mgmt_frame(mac_ctx, &ssId, + session_entry->pLimMlmJoinReq->bssDescription.bssId, + session_entry->currentOperChannel, session_entry->selfMacAddr, + session_entry->dot11mode, + session_entry->pLimJoinReq->addIEScan.length, + session_entry->pLimJoinReq->addIEScan.addIEdata); + + if (session_entry->pePersona == CDF_P2P_CLIENT_MODE) { + /* Activate Join Periodic Probe Req timer */ + if (tx_timer_activate + (&mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer) + != TX_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("Periodic JoinReq timer activate failed")); + goto error; + } + } + return; +error: + if (NULL != session_entry) { + if (session_entry->pLimMlmJoinReq) { + cdf_mem_free(session_entry->pLimMlmJoinReq); + session_entry->pLimMlmJoinReq = NULL; + } + if (session_entry->pLimJoinReq) { + cdf_mem_free(session_entry->pLimJoinReq); + session_entry->pLimJoinReq = NULL; + } + join_cnf.sessionId = session_entry->peSessionId; + } else { + join_cnf.sessionId = 0; + } + join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, (uint32_t *)&join_cnf); +} + +/** + * lim_process_switch_channel_rsp() + * + ***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 lim_process_switch_channel_rsp(tpAniSirGlobal pMac, void *body) +{ + tpSwitchChannelParams pChnlParams = NULL; + CDF_STATUS status; + uint16_t channelChangeReasonCode; + uint8_t 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; + + psessionEntry = pe_find_session_by_session_id(pMac, peSessionId); + if (psessionEntry == NULL) { + lim_log(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. */ + rrm_cache_mgmt_tx_power(pMac, pChnlParams->txMgmtPower, psessionEntry); +#endif + channelChangeReasonCode = psessionEntry->channelChangeReasonCode; + /* initialize it back to invalid id */ + psessionEntry->chainMask = pChnlParams->chainMask; + psessionEntry->nss = pChnlParams->nss; + psessionEntry->smpsMode = pChnlParams->smpsMode; + psessionEntry->channelChangeReasonCode = 0xBAD; + lim_log(pMac, LOG1, FL("channelChangeReasonCode %d"), + channelChangeReasonCode); + switch (channelChangeReasonCode) { + case LIM_SWITCH_CHANNEL_REASSOC: + lim_process_switch_channel_re_assoc_req(pMac, psessionEntry, status); + break; + case LIM_SWITCH_CHANNEL_JOIN: + lim_process_switch_channel_join_req(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(lim_log + (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. + */ + lim_send_sme_ap_channel_switch_resp(pMac, psessionEntry, + pChnlParams); + } + break; + default: + break; + } + cdf_mem_free(body); +} + +/** + * @function : lim_handle_del_bss_in_re_assoc_context + * @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 +lim_handle_del_bss_in_re_assoc_context(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 beacon_struct; + beacon_struct = cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == beacon_struct) { + lim_log(pMac, LOGE, FL("beaconStruct alloc failed")); + mlmReassocCnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + lim_delete_dph_hash_entry(pMac, psessionEntry->bssId, + DPH_STA_HASH_INDEX_PEER, psessionEntry); + goto error; + } + /* Delete the older STA Table entry */ + lim_delete_dph_hash_entry(pMac, psessionEntry->bssId, + DPH_STA_HASH_INDEX_PEER, psessionEntry); + /* + * Add an entry for AP to hash table + * maintained by DPH module + */ + pStaDs = dph_add_hash_entry(pMac, + psessionEntry->limReAssocbssId, + DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + /* Could not add hash table entry */ + lim_log(pMac, LOGE, + FL("could not add hash entry at DPH for ")); + lim_print_mac_addr(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; + lim_update_assoc_sta_datas(pMac, pStaDs, assocRsp, + psessionEntry); + lim_update_re_assoc_globals(pMac, assocRsp, psessionEntry); + lim_extract_ap_capabilities(pMac, + (uint8_t *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, + lim_get_ielen_from_bss_description( + &psessionEntry->pLimReAssocReq->bssDescription), + beacon_struct); + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection_on_assoc(pMac, + beacon_struct, + psessionEntry); + if (beacon_struct->erpPresent) { + if (beacon_struct->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 != + lim_sta_send_add_bss(pMac, assocRsp, beacon_struct, + &psessionEntry->pLimReAssocReq->bssDescription, + false, psessionEntry)) { + lim_log(pMac, LOGE, + FL("Posting ADDBSS in the ReAssocCtx has Failed ")); + retStatus = eSIR_FAILURE; + } + if (retStatus != eSIR_SUCCESS) { + mlmReassocCnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; + cdf_mem_free(assocRsp); + pMac->lim.gLimAssocResponseData = NULL; + cdf_mem_free(beacon_struct); + goto error; + } + cdf_mem_free(assocRsp); + cdf_mem_free(beacon_struct); + 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; + lim_delete_dph_hash_entry(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; + } + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); + } + break; + default: + lim_log(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: + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); +} + +/* Added For BT -AMP Support */ +static void +lim_process_btamp_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry) +{ + tLimMlmStartCnf mlmStartCnf; + tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; + + if (NULL == pAddBssParams) { + lim_log(pMac, LOGE, FL("Invalid body pointer in message")); + goto end; + } + if (CDF_STATUS_SUCCESS == pAddBssParams->status) { + lim_log(pMac, LOG2, + FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS")); + if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { + if (lim_set_link_state + (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 (lim_set_link_state + (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 = (uint8_t) pAddBssParams->bssIdx; + sch_edca_profile_update(pMac, psessionEntry); + lim_init_peer_idxpool(pMac, psessionEntry); + + /* Apply previously set configuration at HW */ + lim_apply_configuration(pMac, psessionEntry); + psessionEntry->staId = pAddBssParams->staContext.staIdx; + mlmStartCnf.resultCode = eSIR_SME_SUCCESS; + } else { + lim_log(pMac, LOGE, FL("WMA_ADD_BSS_REQ failed with status %d"), + pAddBssParams->status); + mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; + } + mlmStartCnf.sessionId = psessionEntry->peSessionId; + lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf); +end: + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pAddBssParams); + limMsgQ->bodyptr = NULL; + } +} + +/** + * @function : lim_handle_add_bss_in_re_assoc_context + * @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 +lim_handle_add_bss_in_re_assoc_context(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(mac_trace + (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 = + cdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (NULL == pBeaconStruct) { + lim_log(pMac, LOGE, + FL + ("Unable to allocate memory in lim_handle_add_bss_in_re_assoc_context")); + mlmReassocCnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + goto Error; + } + /* Get the AP entry from DPH hash table */ + pStaDs = + dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("Fail to get STA PEER entry from hash")); + ) + mlmReassocCnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; + cdf_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; + lim_update_assoc_sta_datas(pMac, pStaDs, assocRsp, + psessionEntry); + lim_update_re_assoc_globals(pMac, assocRsp, psessionEntry); + lim_extract_ap_capabilities(pMac, + (uint8_t *) psessionEntry-> + pLimReAssocReq->bssDescription. + ieFields, + lim_get_ielen_from_bss_description + (&psessionEntry-> + pLimReAssocReq-> + bssDescription), + pBeaconStruct); + if (pMac->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection_on_assoc(pMac, + pBeaconStruct, + psessionEntry); + + if (pBeaconStruct->erpPresent) { + if (pBeaconStruct->erpIEInfo.barkerPreambleMode) + psessionEntry->beaconParams. + fShortPreamble = 0; + else + psessionEntry->beaconParams. + fShortPreamble = 1; + } + + psessionEntry->isNonRoamReassoc = 1; + if (eSIR_SUCCESS != + lim_sta_send_add_bss(pMac, assocRsp, pBeaconStruct, + &psessionEntry->pLimReAssocReq-> + bssDescription, true, + psessionEntry)) { + lim_log(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; + cdf_mem_free(assocRsp); + pMac->lim.gLimAssocResponseData = NULL; + cdf_mem_free(pBeaconStruct); + goto Error; + } + cdf_mem_free(assocRsp); + psessionEntry->limAssocResponseData = NULL; + cdf_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; + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, + pStaDs->assocId, psessionEntry); + if (LIM_IS_STA_ROLE(psessionEntry)) { + psessionEntry->limMlmState = + eLIM_MLM_IDLE_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + psessionEntry->limMlmState)); + } + + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); + } + break; + default: + PELOGE(lim_log + (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: + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); +} + +void lim_send_beacon_ind(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(lim_log(pMac, LOGE, + FL("Error:Unable to get the PESessionEntry")); + ) + return; + } + pBeaconGenParams = cdf_mem_malloc(sizeof(*pBeaconGenParams)); + if (NULL == pBeaconGenParams) { + PELOGE(lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during sending beaconPreMessage")); + ) + return; + } + cdf_mem_set(pBeaconGenParams, sizeof(*pBeaconGenParams), 0); + cdf_mem_copy((void *)pBeaconGenParams->bssId, + (void *)psessionEntry->bssId, CDF_MAC_ADDR_SIZE); + limMsg.bodyptr = pBeaconGenParams; + sch_process_pre_beacon_ind(pMac, &limMsg); + return; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +/** + * lim_send_sme_scan_cache_updated_ind() + * + ***FUNCTION: + * This function is used to post WMA_SME_SCAN_CACHE_UPDATED message to WMA. + * This message is the indication to WMA 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 lim_send_sme_scan_cache_updated_ind(uint8_t sessionId) +{ + cds_msg_t msg; + + msg.type = WMA_SME_SCAN_CACHE_UPDATED; + msg.reserved = 0; + msg.bodyptr = NULL; + msg.bodyval = sessionId; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_SME_SCAN_CACHE_UPDATED message to WMA", + __func__); +} +#endif + +void lim_send_scan_offload_complete(tpAniSirGlobal pMac, + tSirScanOffloadEvent *pScanEvent) +{ + + pMac->lim.gLimRspReqd = false; + lim_send_sme_scan_rsp(pMac, pScanEvent->reasonCode, + pScanEvent->sessionId, 0, pScanEvent->scanId); +#ifdef FEATURE_WLAN_SCAN_PNO + lim_send_sme_scan_cache_updated_ind(pScanEvent->sessionId); +#endif +} + +void lim_process_rx_scan_event(tpAniSirGlobal pMac, void *buf) +{ + tSirScanOffloadEvent *pScanEvent = (tSirScanOffloadEvent *) buf; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_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: + if (P2P_SCAN_TYPE_LISTEN == pScanEvent->p2pScanType) { + lim_send_sme_roc_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, + CDF_STATUS_SUCCESS, + pScanEvent->sessionId, + pScanEvent->scanId); + cdf_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) { + lim_send_sme_rsp(pMac, + eWNI_SME_ACTION_FRAME_SEND_CNF, + eSIR_SME_SEND_ACTION_FAIL, + pMac->lim.mgmtFrameSessionId, 0); + pMac->lim.mgmtFrameSessionId = 0xff; + } + } else { + lim_send_scan_offload_complete(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) { + lim_send_sme_roc_rsp(pMac, + eWNI_SME_REMAIN_ON_CHN_RDY_IND, + CDF_STATUS_SUCCESS, + pScanEvent->sessionId, + pScanEvent->scanId); + } else { + lim_log(pMac, LOGE, + FL("gpLimRemainOnChanReq is NULL")); + } + } + break; + case SCAN_EVENT_BSS_CHANNEL: + case SCAN_EVENT_DEQUEUED: + case SCAN_EVENT_PREEMPTED: + default: + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + "Received unhandled scan event %u", + pScanEvent->event); + } + cdf_mem_free(buf); +} diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c new file mode 100644 index 000000000000..ccc87123e169 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -0,0 +1,693 @@ +/* + * 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 lim_process_probe_req_frame.cc contains the code + * for processing Probe Request Frame. + * Author: Chandra Modumudi + * Date: 02/28/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" + +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_ser_des_utils.h" +#include "parser_api.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" + +void + +lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + uint8_t *pProbeReqIE, + uint32_t ProbeReqIELen, tpPESession psessionEntry); + +/** + * lim_get_wpspbc_sessions() - to get wps pbs sessions + * @mac_ctx: Pointer to Global MAC structure + * @addr: A pointer to probe request source MAC addresss + * @uuid_e: A pointer to UUIDE element of WPS IE in WPS PBC probe request + * @session: A pointer to station PE session + * + * This function is called to query the WPS PBC overlap. This function + * check WPS PBC probe request link list for PBC overlap + * + * @return None + */ + +void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, + uint8_t *uuid_e, eWPSPBCOverlap *overlap, + tpPESession session) +{ + int count = 0; + tSirWPSPBCSession *pbc; + uint32_t cur_time; + + cur_time = (uint32_t) (cdf_mc_timer_get_system_ticks() / + CDF_TICKS_PER_SECOND); + cdf_mem_set((uint8_t *) addr, sizeof(tSirMacAddr), 0); + cdf_mem_set((uint8_t *) uuid_e, SIR_WPS_UUID_LEN, 0); + for (pbc = session->pAPWPSPBCSession; pbc; pbc = pbc->next) { + if (cur_time > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) + break; + count++; + if (count > 1) + break; + cdf_mem_copy((uint8_t *) addr, (uint8_t *) pbc->addr, + sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) uuid_e, (uint8_t *) pbc->uuid_e, + SIR_WPS_UUID_LEN); + } + if (count > 1) + /* Overlap */ + *overlap = eSAP_WPSPBC_OVERLAP_IN120S; + else if (count == 0) + /* no WPS probe request in 120 second */ + *overlap = eSAP_WPSPBC_NO_WPSPBC_PROBE_REQ_IN120S; + else + /* One WPS probe request in 120 second */ + *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S; + + lim_log(mac_ctx, LOGE, FL("overlap = %d"), *overlap); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, addr, + sizeof(tSirMacAddr)); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, uuid_e, + SIR_WPS_UUID_LEN); + return; +} + +/** + * lim_remove_timeout_pb_csessions + * + ***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 lim_remove_timeout_pb_csessions(tpAniSirGlobal pMac, + tSirWPSPBCSession *pbc) +{ + tSirWPSPBCSession *prev; + + while (pbc) { + prev = pbc; + pbc = pbc->next; + + PELOG4(lim_log(pMac, LOG4, FL("WPS PBC sessions remove"));) + PELOG4(sir_dump_buf + (pMac, SIR_LIM_MODULE_ID, LOG4, prev->addr, + sizeof(tSirMacAddr)); + ) + PELOG4(sir_dump_buf + (pMac, SIR_LIM_MODULE_ID, LOG4, prev->uuid_e, + SIR_WPS_UUID_LEN); + ) + + cdf_mem_free(prev); + } +} + +void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac, + tpPESession psessionEntry) +{ + tSirWPSPBCSession *pbc, *prev = NULL; + prev = pbc = psessionEntry->pAPWPSPBCSession; + + while (pbc) { + if (cdf_mem_compare((uint8_t *) pbc->addr, + (uint8_t *) pRemoveMac, + sizeof(tSirMacAddr))) { + prev->next = pbc->next; + if (pbc == psessionEntry->pAPWPSPBCSession) + psessionEntry->pAPWPSPBCSession = pbc->next; + cdf_mem_free(pbc); + return; + } + prev = pbc; + pbc = pbc->next; + } + +} + +/** + * lim_update_pbc_session_entry + * + ***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 lim_update_pbc_session_entry(tpAniSirGlobal pMac, + uint8_t *addr, uint8_t *uuid_e, + tpPESession psessionEntry) +{ + tSirWPSPBCSession *pbc, *prev = NULL; + + uint32_t curTime; + + curTime = + (uint32_t) (cdf_mc_timer_get_system_ticks() / + CDF_TICKS_PER_SECOND); + + PELOG4(lim_log + (pMac, LOG4, FL("Receive WPS probe reques curTime=%d"), curTime); + ) + PELOG4(sir_dump_buf + (pMac, SIR_LIM_MODULE_ID, LOG4, addr, sizeof(tSirMacAddr)); + ) + PELOG4(sir_dump_buf + (pMac, SIR_LIM_MODULE_ID, LOG4, uuid_e, SIR_WPS_UUID_LEN); + ) + + pbc = psessionEntry->pAPWPSPBCSession; + + while (pbc) { + if (cdf_mem_compare + ((uint8_t *) pbc->addr, (uint8_t *) addr, + sizeof(tSirMacAddr)) + && cdf_mem_compare((uint8_t *) pbc->uuid_e, + (uint8_t *) 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 = cdf_mem_malloc(sizeof(tSirWPSPBCSession)); + if (NULL == pbc) { + PELOGE(lim_log + (pMac, LOGE, FL("memory allocate failed!")); + ) + return; + } + cdf_mem_copy((uint8_t *) pbc->addr, (uint8_t *) addr, + sizeof(tSirMacAddr)); + + if (uuid_e) + cdf_mem_copy((uint8_t *) pbc->uuid_e, + (uint8_t *) 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; + lim_remove_timeout_pb_csessions(pMac, pbc); + break; + } + prev = pbc; + pbc = pbc->next; + } +} + +/** + * lim_wpspbc_close + * + ***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 lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + lim_remove_timeout_pb_csessions(pMac, psessionEntry->pAPWPSPBCSession); + +} + +/** + * lim_check11b_rates + * + ***FUNCTION: + * This function is called by lim_process_probe_req_frame() upon + * Probe Request frame reception. + * + ***LOGIC: + * This function check 11b rates in supportedRates and extendedRates rates + * + ***NOTE: + * + * @param rate + * + * @return BOOLEAN + */ + +bool lim_check11b_rates(uint8_t rate) +{ + if ((0x02 == (rate)) + || (0x04 == (rate)) + || (0x0b == (rate)) + || (0x16 == (rate)) + ) { + return true; + } + return false; +} + +/** + * lim_process_probe_req_frame: to process probe req frame + * @mac_ctx: Pointer to Global MAC structure + * @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs + * @session: a ponter to session entry + * + * This function is called by limProcessMessageQueue() upon + * Probe Request frame reception. 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. + * + * + * Return: none + */ + +void +lim_process_probe_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpPESession session) +{ + uint8_t *body_ptr; + tpSirMacMgmtHdr mac_hdr; + uint32_t frame_len; + tSirProbeReq probe_req; + tAniSSID ssid; + + /* Don't send probe responses if disabled */ + if (mac_ctx->lim.gLimProbeRespDisableFlag) + return; + + /* + * Don't send probe response if P2P go is scanning till scan + * come to idle state. + */ + if ((session->pePersona == CDF_P2P_GO_MODE) && + ((mac_ctx->lim.gpLimRemainOnChanReq) || + (mac_ctx->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE))) { + lim_log(mac_ctx, LOG3, + FL("GO is scanning, don't send probersp on diff chnl")); + return; + } + mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + if (LIM_IS_AP_ROLE(session) || + LIM_IS_BT_AMP_AP_ROLE(session) || + LIM_IS_BT_AMP_STA_ROLE(session) || + (LIM_IS_IBSS_ROLE(session) && + (WMA_GET_RX_BEACON_SENT(rx_pkt_info)))) { + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_log(mac_ctx, LOG3, + FL("Received Probe Request %d bytes from "), + frame_len); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3); + /* Get pointer to Probe Request frame body */ + body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + + /* Parse Probe Request frame */ + if (sir_convert_probe_req_frame2_struct(mac_ctx, body_ptr, + frame_len, &probe_req) == eSIR_FAILURE) { + lim_log(mac_ctx, LOGE, + FL("Parse error ProbeReq, length=%d, SA is: " + MAC_ADDRESS_STR), frame_len, + MAC_ADDR_ARRAY(mac_hdr->sa)); + mac_ctx->sys.probeError++; + return; + } + if (session->pePersona == CDF_P2P_GO_MODE) { + uint8_t i = 0, rate_11b = 0, other_rates = 0; + /* Check 11b rates in supported rates */ + for (i = 0; i < probe_req.supportedRates.numRates; + i++) { + if (lim_check11b_rates( + probe_req.supportedRates.rate[i] & + 0x7f)) + rate_11b++; + else + other_rates++; + } + + /* Check 11b rates in extended rates */ + for (i = 0; i < probe_req.extendedRates.numRates; i++) { + if (lim_check11b_rates( + probe_req.extendedRates.rate[i] & 0x7f)) + rate_11b++; + else + other_rates++; + } + + if ((rate_11b > 0) && (other_rates == 0)) { + lim_log(mac_ctx, LOG3, + FL("Received a probe req frame with only 11b rates, SA is: ")); + lim_print_mac_addr(mac_ctx, + mac_hdr->sa, LOG3); + return; + } + } + if (LIM_IS_AP_ROLE(session) && + ((session->APWPSIEs.SirWPSProbeRspIE.FieldPresent + & SIR_WPS_PROBRSP_VER_PRESENT) + && (probe_req.wscIePresent == 1) + && (probe_req.probeReqWscIeInfo.DevicePasswordID.id == + WSC_PASSWD_ID_PUSH_BUTTON) + && (probe_req.probeReqWscIeInfo.UUID_E.present == 1))) { + if (session->fwdWPSPBCProbeReq) { + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, + LOG4, mac_hdr->sa, sizeof(tSirMacAddr)); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, + LOG4, body_ptr, frame_len); + lim_send_sme_probe_req_ind(mac_ctx, mac_hdr->sa, + body_ptr, frame_len, session); + } else { + lim_update_pbc_session_entry(mac_ctx, + mac_hdr->sa, + probe_req.probeReqWscIeInfo.UUID_E.uuid, + session); + } + } + ssid.length = session->ssId.length; + /* Copy the SSID from sessio entry to local variable */ + cdf_mem_copy(ssid.ssId, session->ssId.ssId, + session->ssId.length); + + /* + * Compare received SSID with current SSID. If they match, + * reply with Probe Response + */ + if (probe_req.ssId.length) { + if (!ssid.length) + goto multipleSSIDcheck; + + if (cdf_mem_compare((uint8_t *) &ssid, + (uint8_t *) &(probe_req.ssId), + (uint8_t) (ssid.length + 1))) { + lim_send_probe_rsp_mgmt_frame(mac_ctx, + mac_hdr->sa, &ssid, + DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, + session, + probe_req.p2pIePresent); + return; + } else if (session->pePersona == + CDF_P2P_GO_MODE) { + uint8_t direct_ssid[7] = "DIRECT-"; + uint8_t direct_ssid_len = 7; + if (cdf_mem_compare((uint8_t *) &direct_ssid, + (uint8_t *) &(probe_req.ssId.ssId), + (uint8_t) (direct_ssid_len))) { + lim_send_probe_rsp_mgmt_frame(mac_ctx, + mac_hdr->sa, + &ssid, + DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, + session, + probe_req.p2pIePresent); + return; + } + } else { + lim_log(mac_ctx, LOG3, + FL("Ignore ProbeReq frm with unmatch SSID received from ")); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, + LOG3); + mac_ctx->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 (session->ssidHidden) + /* + * We are returning from here as probe request + * contains the broadcast SSID. So no need to + * send the probe resp + */ + return; + lim_send_probe_rsp_mgmt_frame(mac_ctx, mac_hdr->sa, + &ssid, + DPH_USE_MGMT_STAID, + DPH_NON_KEEPALIVE_FRAME, + session, + probe_req.p2pIePresent); + return; + } +multipleSSIDcheck: + lim_log(mac_ctx, LOG3, + FL("Ignore ProbeReq frm with unmatch SSID rcved from")); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3); + mac_ctx->sys.probeBadSsid++; + } else { + /* Ignore received Probe Request frame */ + lim_log(mac_ctx, LOG3, + FL("Ignoring Probe Request frame received from ")); + lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3); + mac_ctx->sys.probeIgnore++; + } + return; +} + +/** + * lim_indicate_probe_req_to_hdd + * + ***FUNCTION: + * This function is called by lim_process_probe_req_frame_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 +lim_indicate_probe_req_to_hdd(tpAniSirGlobal pMac, uint8_t *pBd, + tpPESession psessionEntry) +{ + tpSirMacMgmtHdr pHdr; + uint32_t frameLen; + + lim_log(pMac, LOG1, "Received a probe request frame"); + + pHdr = WMA_GET_RX_MAC_HEADER(pBd); + frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd); + + /* send the probe req to SME. */ + lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, + (uint8_t *) pHdr, + (frameLen + sizeof(tSirMacMgmtHdr)), + psessionEntry->smeSessionId, WMA_GET_RX_CH(pBd), + psessionEntry, 0); +} /*** end lim_indicate_probe_req_to_hdd() ***/ + +/** + * lim_process_probe_req_frame_multiple_bss() - to process probe req + * @mac_ctx: Pointer to Global MAC structure + * @buf_descr: A pointer to Buffer descriptor + associated PDUs + * @session: A pointer to PE session + * + * This function is called by limProcessMessageQueue() upon + * Probe Request frame reception. This function call + * lim_indicate_probe_req_to_hdd function to indicate + * Probe Request frame to HDD. It also call lim_process_probe_req_frame + * function which process received Probe Request frame and responds + * with Probe Response. + * + * @return None + */ +void +lim_process_probe_req_frame_multiple_bss(tpAniSirGlobal mac_ctx, + uint8_t *buf_descr, tpPESession session) +{ + uint8_t i; + + if (session != NULL) { + if (LIM_IS_AP_ROLE(session)) { + lim_indicate_probe_req_to_hdd(mac_ctx, + buf_descr, session); + } + lim_process_probe_req_frame(mac_ctx, buf_descr, session); + return; + } + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + session = pe_find_session_by_session_id(mac_ctx, i); + if (session == NULL) + continue; + if (LIM_IS_AP_ROLE(session)) + lim_indicate_probe_req_to_hdd(mac_ctx, + buf_descr, session); + if (LIM_IS_AP_ROLE(session) || + LIM_IS_IBSS_ROLE(session) || + LIM_IS_BT_AMP_AP_ROLE(session) || + LIM_IS_BT_AMP_STA_ROLE(session)) + lim_process_probe_req_frame(mac_ctx, + buf_descr, session); + } +} + +/** + * lim_send_sme_probe_req_ind() + * + ***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 +lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + uint8_t *pProbeReqIE, + uint32_t ProbeReqIELen, tpPESession psessionEntry) +{ + tSirSmeProbeReqInd *pSirSmeProbeReqInd; + tSirMsgQ msgQ; + + pSirSmeProbeReqInd = cdf_mem_malloc(sizeof(tSirSmeProbeReqInd)); + if (NULL == pSirSmeProbeReqInd) { + /* Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_PROBE_REQ_IND")); + 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; + + cdf_mem_copy(pSirSmeProbeReqInd->bssId, psessionEntry->bssId, + sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peerMacAddr, + peerMacAddr, sizeof(tSirMacAddr)); + + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIELen = + (uint16_t) ProbeReqIELen; + cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE, pProbeReqIE, + ProbeReqIELen); + + if (lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("couldnt send the probe req to hdd")); + ) + } + +} /*** end lim_send_sme_probe_req_ind() ***/ diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c new file mode 100644 index 000000000000..d3df1d31eba3 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c @@ -0,0 +1,362 @@ +/* + * 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 lim_process_probe_rsp_frame.cc contains the code + * for processing Probe Response Frame. + * Author: Chandra Modumudi + * Date: 03/01/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "wni_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_send_messages.h" + +#include "parser_api.h" + +tSirRetStatus lim_validate_ie_information_in_probe_rsp_frame(uint8_t *pRxPacketInfo) +{ + tSirRetStatus status = eSIR_SUCCESS; + + if (WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) < + (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) { + status = eSIR_FAILURE; + } + + return status; +} + +/** + * lim_process_probe_rsp_frame() - processes received Probe Response frame + * @mac_ctx: Pointer to Global MAC structure + * @rx_Packet_info: A pointer to Buffer descriptor + associated PDUs + * @session_entry: Handle to the session. + * + * This function processes received Probe Response frame. + * Frames with out-of-order IEs are dropped. + * 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. + * + * Return: None + */ +void +lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info, + tpPESession session_entry) +{ + uint8_t *body; + uint32_t frame_len = 0; + tSirMacAddr current_bssid; + tpSirMacMgmtHdr header; + tSirProbeRespBeacon *probe_rsp; + uint8_t qos_enabled = false; + uint8_t wme_enabled = false; + + if (!session_entry) { + lim_log(mac_ctx, LOGE, FL("session_entry is NULL")); + return; + } + lim_log(mac_ctx, LOG1, "SessionId:%d ProbeRsp Frame is received", + session_entry->peSessionId); + + probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == probe_rsp) { + lim_log(mac_ctx, LOGE, + FL + ("Unable to allocate memory ")); + return; + } + + probe_rsp->ssId.length = 0; + probe_rsp->wpa.length = 0; + + header = WMA_GET_RX_MAC_HEADER(rx_Packet_info); + + lim_log(mac_ctx, LOG2, + FL("Rx Probe Response with length = %d from "MAC_ADDRESS_STR), + WMA_GET_RX_MPDU_LEN(rx_Packet_info), + MAC_ADDR_ARRAY(header->sa)); + + /* Validate IE information before processing Probe Response Frame */ + if (lim_validate_ie_information_in_probe_rsp_frame(rx_Packet_info) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOG1, + FL("Parse error ProbeResponse, length=%d"), frame_len); + cdf_mem_free(probe_rsp); + return; + } + + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " + MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(header->bssId), + (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_Packet_info))); + /* Get pointer to Probe Response frame body */ + body = WMA_GET_RX_MPDU_DATA(rx_Packet_info); + /* Enforce Mandatory IEs */ + if ((sir_convert_probe_frame2_struct(mac_ctx, + body, frame_len, probe_rsp) == eSIR_FAILURE) || + !probe_rsp->ssidPresent) { + lim_log(mac_ctx, LOG1, + FL("Parse error ProbeResponse, length=%d"), frame_len); + cdf_mem_free(probe_rsp); + return; + } + lim_check_and_add_bss_description(mac_ctx, probe_rsp, + rx_Packet_info, false, true); + /* To Support BT-AMP */ + if ((mac_ctx->lim.gLimMlmState == + eLIM_MLM_WT_PROBE_RESP_STATE) || + (mac_ctx->lim.gLimMlmState == + eLIM_MLM_PASSIVE_SCAN_STATE)) { + lim_check_and_add_bss_description(mac_ctx, probe_rsp, + rx_Packet_info, ((mac_ctx->lim. + gLimHalScanState == eLIM_HAL_SCANNING_STATE) + ? true : false), true); + } else if (session_entry->limMlmState == + eLIM_MLM_WT_JOIN_BEACON_STATE) { + /* + * Either Beacon/probe response is required. + * Hence store it in same buffer. + */ + if (session_entry->beacon != NULL) { + cdf_mem_free(session_entry->beacon); + session_entry->beacon = NULL; + } + session_entry->bcnLen = + WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info); + session_entry->beacon = + cdf_mem_malloc(session_entry->bcnLen); + if (NULL == session_entry->beacon) { + lim_log(mac_ctx, LOGE, + FL("No Memory to store beacon")); + } else { + /* + * Store the Beacon/ProbeRsp. + * This is sent to csr/hdd in join cnf response. + */ + cdf_mem_copy(session_entry->beacon, + WMA_GET_RX_MPDU_DATA + (rx_Packet_info), + session_entry->bcnLen); + } + /* STA in WT_JOIN_BEACON_STATE */ + lim_check_and_announce_join_success(mac_ctx, probe_rsp, + header, + session_entry); + } else if (session_entry->limMlmState == + eLIM_MLM_LINK_ESTABLISHED_STATE) { + tpDphHashNode sta_ds = NULL; + /* + * Check if this Probe Response is for + * our Probe Request sent upon reaching + * heart beat threshold + */ + sir_copy_mac_addr(current_bssid, session_entry->bssId); + if (!cdf_mem_compare(current_bssid, header->bssId, + sizeof(tSirMacAddr))) { + cdf_mem_free(probe_rsp); + return; + } + if (!LIM_IS_CONNECTION_ACTIVE(session_entry)) { + lim_log(mac_ctx, LOGW, + FL("Recved Probe Resp from AP,AP-alive")); + if (probe_rsp->HTInfo.present) + lim_received_hb_handler(mac_ctx, + probe_rsp->HTInfo.primaryChannel, + session_entry); + else + lim_received_hb_handler(mac_ctx, + (uint8_t)probe_rsp->channelNumber, + session_entry); + } + if (LIM_IS_STA_ROLE(session_entry)) { + if (probe_rsp->channelSwitchPresent) { + lim_update_channel_switch(mac_ctx, + probe_rsp, + session_entry); + } else if (session_entry->gLimSpecMgmt.dot11hChanSwState + == eLIM_11H_CHANSW_RUNNING) { + lim_cancel_dot11h_channel_switch( + mac_ctx, session_entry); + } + } + /* + * 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. + */ + sta_ds = dph_get_hash_entry(mac_ctx, + DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + limGetQosMode(session_entry, &qos_enabled); + limGetWmeMode(session_entry, &wme_enabled); + lim_log(mac_ctx, LOG2, + FL("wmeEdcaPresent: %d wme_enabled: %d"), + probe_rsp->wmeEdcaPresent, wme_enabled); + lim_log(mac_ctx, LOG2, + FL("edcaPresent: %d, qos_enabled: %d"), + probe_rsp->edcaPresent, qos_enabled); + lim_log(mac_ctx, LOG2, + FL("edcaParams.qosInfo.count: %d"), + probe_rsp->edcaParams.qosInfo.count); + lim_log(mac_ctx, LOG2, + FL("schObject.gLimEdcaParamSetCount: %d"), + session_entry->gLimEdcaParamSetCount); + if (((probe_rsp->wmeEdcaPresent && wme_enabled) || + (probe_rsp->edcaPresent && qos_enabled)) && + (probe_rsp->edcaParams.qosInfo.count != + session_entry->gLimEdcaParamSetCount)) { + if (sch_beacon_edca_process(mac_ctx, + &probe_rsp->edcaParams, + session_entry) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("EDCA param process error")); + } else if (sta_ds != NULL) { + /* + * If needed, downgrade the + * EDCA parameters + */ + lim_set_active_edca_params(mac_ctx, + session_entry-> + gLimEdcaParams, + session_entry); + lim_send_edca_params(mac_ctx, + session_entry-> + gLimEdcaParamsActive, + sta_ds->bssId); + } else { + lim_log(mac_ctx, LOGE, + FL("SelfEntry missing in Hash")); + } + } + if (session_entry->fWaitForProbeRsp == true) { + lim_log(mac_ctx, LOGW, + FL("Check probe resp for caps change")); + lim_detect_change_in_ap_capabilities( + mac_ctx, probe_rsp, session_entry); + } + } else { + if (LIM_IS_IBSS_ROLE(session_entry) && + (session_entry->limMlmState == + eLIM_MLM_BSS_STARTED_STATE)) + lim_handle_ibss_coalescing(mac_ctx, probe_rsp, + rx_Packet_info, session_entry); + } + cdf_mem_free(probe_rsp); + + /* Ignore Probe Response frame in all other states */ + return; +} + +/** + * lim_process_probe_rsp_frame_no_session() - process Probe Response frame + * @mac_ctx: Pointer to Global MAC structure + * @rx_packet_info: A pointer to Buffer descriptor + associated PDUs + * + * This function processes received Probe Response frame with no session. + * + * Return: None + */ +void +lim_process_probe_rsp_frame_no_session(tpAniSirGlobal mac_ctx, + uint8_t *rx_packet_info) +{ + uint8_t *body; + uint32_t frame_len = 0; + tpSirMacMgmtHdr header; + tSirProbeRespBeacon *probe_rsp; + + probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == probe_rsp) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory")); + return; + } + + probe_rsp->ssId.length = 0; + probe_rsp->wpa.length = 0; + + header = WMA_GET_RX_MAC_HEADER(rx_packet_info); + + lim_log(mac_ctx, LOG2, + FL("Received Probe Response frame with length=%d from "), + WMA_GET_RX_MPDU_LEN(rx_packet_info)); + lim_print_mac_addr(mac_ctx, header->sa, LOG2); + + /* Validate IE information before processing Probe Response Frame */ + if (lim_validate_ie_information_in_probe_rsp_frame(rx_packet_info) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOG1, + FL("Parse error ProbeResponse, length=%d"), frame_len); + cdf_mem_free(probe_rsp); + return; + } + + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " + MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(header->bssId), + (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_packet_info))); + /* + * Get pointer to Probe Response frame body + */ + body = WMA_GET_RX_MPDU_DATA(rx_packet_info); + if (sir_convert_probe_frame2_struct(mac_ctx, body, frame_len, + probe_rsp) == eSIR_FAILURE) { + lim_log(mac_ctx, LOG1, + FL("Parse error ProbeResponse, length=%d\n"), + frame_len); + cdf_mem_free(probe_rsp); + return; + } + lim_log(mac_ctx, LOG2, FL("Save this probe rsp in LFR cache")); + lim_check_and_add_bss_description(mac_ctx, probe_rsp, + rx_packet_info, false, true); + cdf_mem_free(probe_rsp); + return; +} diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c new file mode 100644 index 000000000000..0db6d07bfc33 --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -0,0 +1,5690 @@ +/* + * 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 lim_process_sme_req_messages.cc contains the code + * for processing SME request messages. + * Author: Chandra Modumudi + * Date: 02/11/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "cds_api.h" +#include "wni_api.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "sir_api.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_sme_req_utils.h" +#include "lim_ibss_peer_mgmt.h" +#include "lim_admit_control.h" +#include "dph_hash_table.h" +#include "lim_send_messages.h" +#include "lim_api.h" +#include "wmm_apsd.h" +#include "sir_mac_prot_def.h" + +#include "sap_api.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.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 bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal, uint32_t *); +static bool __lim_process_sme_start_bss_req(tpAniSirGlobal, tpSirMsgQ pMsg); +static void __lim_process_sme_scan_req(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_join_req(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_reassoc_req(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_disassoc_req(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_deauth_req(tpAniSirGlobal, uint32_t *); +static void __lim_process_sme_set_context_req(tpAniSirGlobal, uint32_t *); +static bool __lim_process_sme_stop_bss_req(tpAniSirGlobal, tpSirMsgQ pMsg); +static void lim_process_sme_channel_change_request(tpAniSirGlobal pMac, + uint32_t *pMsg); +static void lim_process_sme_start_beacon_req(tpAniSirGlobal pMac, uint32_t *pMsg); +static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal pMac, uint32_t *pMsg); +static void lim_process_nss_update_request(tpAniSirGlobal pMac, uint32_t *pMsg); +static void lim_process_set_ie_req(tpAniSirGlobal pMac, uint32_t *pMsg); + +static void lim_start_bss_update_add_ie_buffer(tpAniSirGlobal pMac, + uint8_t **pDstData_buff, + uint16_t *pDstDataLen, + uint8_t *pSrcData_buff, + uint16_t srcDataLen); + +static void lim_update_add_ie_buffer(tpAniSirGlobal pMac, + uint8_t **pDstData_buff, + uint16_t *pDstDataLen, + uint8_t *pSrcData_buff, uint16_t srcDataLen); + +static void lim_process_modify_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg); + +static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg); + +extern void pe_register_wma_handle(tpAniSirGlobal pMac); + +/** + * lim_process_set_hw_mode() - Send set HW mode command to WMA + * @mac: Globacl MAC pointer + * @msg: Message containing the hw mode index + * + * Send the set HW mode command to WMA + * + * Return: CDF_STATUS_SUCCESS if message posting is successful + */ +static CDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t cds_message; + struct sir_hw_mode *req_msg; + uint32_t len; + struct s_sir_set_hw_mode *buf; + tSirMsgQ resp_msg; + struct sir_set_hw_mode_resp *param; + + buf = (struct s_sir_set_hw_mode *) msg; + if (!buf) { + lim_log(mac, LOGE, FL("Set HW mode param is NULL")); + /* To free the active command list */ + goto fail; + } + + len = sizeof(*req_msg); + + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + lim_log(mac, LOGE, FL("cdf_mem_malloc failed")); + /* Free the active command list + * Probably the malloc is going to fail there as well?! + */ + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(req_msg, len); + + req_msg->hw_mode_index = buf->set_hw.hw_mode_index; + /* Other parameters are not needed for WMA */ + + cds_message.bodyptr = req_msg; + cds_message.type = SIR_HAL_SOC_SET_HW_MODE; + + lim_log(mac, LOG1, FL("Posting SIR_HAL_SOC_SET_HW_MOD to WMA")); + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + lim_log(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + goto fail; + } + return status; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + lim_log(mac, LOGE, FL("HW mode resp failed")); + return CDF_STATUS_E_FAILURE; + } + param->status = SET_HW_MODE_STATUS_ECANCELED; + param->cfgd_hw_mode_index = 0; + param->num_vdev_mac_entries = 0; + resp_msg.type = eWNI_SME_SET_HW_MODE_RESP; + resp_msg.bodyptr = param; + resp_msg.bodyval = 0; + lim_sys_process_mmh_msg_api(mac, &resp_msg, ePROT); + return CDF_STATUS_SUCCESS; +} + +/** + * lim_process_set_dual_mac_cfg_req() - Set dual mac config command to WMA + * @mac: Global MAC pointer + * @msg: Message containing the dual mac config parameter + * + * Send the set dual mac config command to WMA + * + * Return: CDF_STATUS_SUCCESS if message posting is successful + */ +static CDF_STATUS lim_process_set_dual_mac_cfg_req(tpAniSirGlobal mac, + uint32_t *msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t cds_message; + struct sir_dual_mac_config *req_msg; + uint32_t len; + struct sir_set_dual_mac_cfg *buf; + tSirMsgQ resp_msg; + struct sir_dual_mac_config_resp *param; + + buf = (struct sir_set_dual_mac_cfg *) msg; + if (!buf) { + lim_log(mac, LOGE, FL("Set Dual mac config is NULL")); + /* To free the active command list */ + goto fail; + } + + len = sizeof(*req_msg); + + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + lim_log(mac, LOGE, FL("vos_mem_malloc failed")); + /* Free the active command list + * Probably the malloc is going to fail there as well?! + */ + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(req_msg, len); + + req_msg->scan_config = buf->set_dual_mac.scan_config; + req_msg->fw_mode_config = buf->set_dual_mac.fw_mode_config; + /* Other parameters are not needed for WMA */ + + cds_message.bodyptr = req_msg; + cds_message.type = SIR_HAL_SOC_DUAL_MAC_CFG_REQ; + + lim_log(mac, LOG1, + FL("Post SIR_HAL_SOC_DUAL_MAC_CFG_REQ to WMA: %x %x"), + req_msg->scan_config, req_msg->fw_mode_config); + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + lim_log(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + goto fail; + } + return status; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + lim_log(mac, LOGE, FL("Dual mac config resp failed")); + return CDF_STATUS_E_FAILURE; + } + param->status = SET_HW_MODE_STATUS_ECANCELED; + resp_msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP; + resp_msg.bodyptr = param; + resp_msg.bodyval = 0; + lim_sys_process_mmh_msg_api(mac, &resp_msg, ePROT); + return CDF_STATUS_SUCCESS; +} + +/** + * __lim_fresh_scan_reqd() - determine if a fresh scan request must be issued. + * @mac_ctx: Pointer to Global MAC structure + * @return_fresh_results: Trigger fresh scan. + * + * 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. + * + * Return: true for fresh scan results, false if in invalid state. + */ +static uint8_t +__lim_fresh_scan_reqd(tpAniSirGlobal mac_ctx, uint8_t return_fresh_results) +{ + uint8_t valid_state = true; + int i; + + lim_log(mac_ctx, LOG1, FL("gLimSmeState: %d, returnFreshResults 0x%x"), + mac_ctx->lim.gLimSmeState, return_fresh_results); + + if (mac_ctx->lim.gLimSmeState != eLIM_SME_IDLE_STATE) { + lim_log(mac_ctx, LOG1, FL("return FALSE")); + return false; + } + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + lim_log(mac_ctx, LOG1, + FL("session %d, bsstype %d, limSystemRole %d, limSmeState %d"), + i, mac_ctx->lim.gpSession[i].bssType, + mac_ctx->lim.gpSession[i].limSystemRole, + mac_ctx->lim.gpSession[i].limSmeState); + if (mac_ctx->lim.gpSession[i].valid == true) { + if (!((((mac_ctx->lim.gpSession[i].bssType == + eSIR_INFRASTRUCTURE_MODE) || + (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_BT_AMP_STA_ROLE)) && + (mac_ctx->lim.gpSession[i].limSmeState == + eLIM_SME_LINK_EST_STATE)) || + (((mac_ctx->lim.gpSession[i].bssType == + eSIR_IBSS_MODE) || + (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_BT_AMP_AP_ROLE) || + (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_BT_AMP_STA_ROLE)) && + (mac_ctx->lim.gpSession[i].limSmeState == + eLIM_SME_NORMAL_STATE)) || + ((((mac_ctx->lim.gpSession[i].bssType == + eSIR_INFRA_AP_MODE) && + (mac_ctx->lim.gpSession[i].pePersona == + CDF_P2P_GO_MODE)) || + (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_AP_ROLE)) && + (mac_ctx->lim.gpSession[i].limSmeState == + eLIM_SME_NORMAL_STATE)))) { + valid_state = false; + break; + } + } + } + + lim_log(mac_ctx, LOG1, FL("valid_state: %d"), valid_state); + + if ((valid_state) && + (return_fresh_results & SIR_BG_SCAN_RETURN_FRESH_RESULTS)) + return true; + else + return false; +} + +/** + * __lim_is_sme_assoc_cnf_valid() + * + ***FUNCTION: + * This function is called by __lim_process_sme_assoc_cnf_new() 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 + */ + +static inline uint8_t __lim_is_sme_assoc_cnf_valid(tpSirSmeAssocCnf pAssocCnf) +{ + if (lim_is_group_addr(pAssocCnf->peerMacAddr)) + return false; + else + return true; +} /*** end __lim_is_sme_assoc_cnf_valid() ***/ + +/** + * __lim_get_sme_join_req_size_for_alloc() + * + ***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 uint16_t __lim_get_sme_join_req_size_for_alloc(uint8_t *pBuf) +{ + uint16_t len = 0; + + if (!pBuf) + return len; + + pBuf += sizeof(uint16_t); + len = lim_get_u16(pBuf); + return len + sizeof(uint16_t); +} + +/** + * __lim_is_defered_msg_for_learn() - message handling in SME learn state + * @pMac: Global MAC context + * @pMsg: Pointer to message posted from SME to LIM. + * + * 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. + * + * Return: true - If defered false - Otherwise + */ + +static bool __lim_is_defered_msg_for_learn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (lim_is_system_in_scan_state(pMac)) { + if (lim_defer_msg(pMac, pMsg) != TX_SUCCESS) { + lim_log(pMac, LOGE, FL("Could not defer Msg = %d"), + pMsg->type); + return false; + } + lim_log(pMac, LOG1, + FL("Defer the message, in learn mode type = %d"), + pMsg->type); + return true; + } + return false; +} + +/** + * __lim_is_defered_msg_for_radar() - Defers the message if radar is detected + * @mac_ctx: Pointer to Global MAC structure + * @message: Pointer to message posted from SME to LIM. + * + * Has role only if 11h is enabled. Not used on STA side. + * Defers the message if radar is detected. + * + * Return: true, if defered otherwise return false. + */ +static bool +__lim_is_defered_msg_for_radar(tpAniSirGlobal mac_ctx, tpSirMsgQ message) +{ + /* + * 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(mac_ctx)) + */ + if (0) { + if (lim_defer_msg(mac_ctx, message) != TX_SUCCESS) { + lim_log(mac_ctx, LOGE, FL("Could not defer Msg = %d"), + message->type); + return false; + } + lim_log(mac_ctx, LOG1, + FL("Defer the message, in learn mode type = %d"), + message->type); + return true; + } + return false; +} + +/** + * __lim_process_sme_sys_ready_ind () - Process ready indication from WMA + * @pMac: Global MAC context + * @pMsgBuf: Message from WMA + * + * handles the notification from HDD. PE just forwards this message to HAL. + * + * Return: true-Posting to HAL failed, so PE will consume the buffer. + * false-Posting to HAL successful, so HAL will consume the buffer. + */ + +static bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirMsgQ msg; + tSirSmeReadyReq *ready_req = (tSirSmeReadyReq *) pMsgBuf; + + msg.type = WMA_SYS_READY_IND; + msg.reserved = 0; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + + if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { + pe_register_wma_handle(pMac); + pMac->lim.add_bssdescr_callback = ready_req->add_bssdescr_cb; + } + PELOGW(lim_log(pMac, LOGW, FL("sending WMA_SYS_READY_IND msg to HAL"));) + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type)); + + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + lim_log(pMac, LOGP, FL("wma_post_ctrl_msg failed")); + return true; + } + return false; +} + +#ifdef WLAN_FEATURE_11AC + +uint32_t lim_get_center_channel(tpAniSirGlobal pMac, uint8_t primarychanNum, + ePhyChanBondState secondaryChanOffset, + uint8_t 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 + +/** + *lim_configure_ap_start_bss_session() - Configure the AP Start BSS in session. + *@mac_ctx: Pointer to Global MAC structure + *@session: A pointer to session entry + *@sme_start_bss_req: Start BSS Request from upper layers. + * + * This function is used to configure the start bss parameters + * in to the session. + * + * Return: None. + */ +static void +lim_configure_ap_start_bss_session(tpAniSirGlobal mac_ctx, tpPESession session, + tpSirSmeStartBssReq sme_start_bss_req) +{ + session->limSystemRole = eLIM_AP_ROLE; + session->privacy = sme_start_bss_req->privacy; + session->fwdWPSPBCProbeReq = sme_start_bss_req->fwdWPSPBCProbeReq; + session->authType = sme_start_bss_req->authType; + /* Store the DTIM period */ + session->dtimPeriod = (uint8_t) sme_start_bss_req->dtimPeriod; + /* Enable/disable UAPSD */ + session->apUapsdEnable = sme_start_bss_req->apUapsdEnable; + if (session->pePersona == CDF_P2P_GO_MODE) { + session->proxyProbeRspEn = 0; + } else { + /* + * To detect PBC overlap in SAP WPS mode, + * Host handles Probe Requests. + */ + if (SAP_WPS_DISABLED == sme_start_bss_req->wps_state) + session->proxyProbeRspEn = 1; + else + session->proxyProbeRspEn = 0; + } + session->ssidHidden = sme_start_bss_req->ssidHidden; + session->wps_state = sme_start_bss_req->wps_state; + session->sap_dot11mc = sme_start_bss_req->sap_dot11mc; + lim_get_short_slot_from_phy_mode(mac_ctx, session, session->gLimPhyMode, + &session->shortSlotTimeSupported); + session->isCoalesingInIBSSAllowed = + sme_start_bss_req->isCoalesingInIBSSAllowed; + +} + +/** + * __lim_handle_sme_start_bss_request() - process SME_START_BSS_REQ message + *@mac_ctx: Pointer to Global MAC structure + *@msg_buf: A pointer to the SME message buffer + * + * This function is called to process SME_START_BSS_REQ message + * from HDD or upper layer application. + * + * Return: None + */ +static void +__lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + uint16_t size; + uint32_t val = 0; + tSirRetStatus ret_status; + tSirMacChanNum channel_number; + tLimMlmStartReq *mlm_start_req = NULL; + tpSirSmeStartBssReq sme_start_bss_req = NULL; + tSirResultCodes ret_code = eSIR_SME_SUCCESS; + /* Flag Used in case of IBSS to Auto generate BSSID. */ + uint32_t auto_gen_bssid = false; + uint8_t session_id; + tpPESession session = NULL; + uint8_t sme_session_id = 0; + uint16_t sme_transaction_id = 0; + uint32_t chanwidth; + tSirRetStatus cfg_get_wmi_dfs_master_param = eSIR_SUCCESS; + +/* FEATURE_WLAN_DIAG_SUPPORT */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + /* + * Since the session is not created yet, sending NULL. + * The response should have the correct state. + */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_START_BSS_REQ_EVENT, + NULL, 0, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_log(mac_ctx, LOG1, FL("Received START_BSS_REQ")); + + /* + * Global Sme state and mlm states are not defined yet, + * for BT-AMP Suppoprt . TO BE DONE + */ + if ((mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || + (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) { + size = sizeof(tSirSmeStartBssReq); + + sme_start_bss_req = cdf_mem_malloc(size); + if (NULL == sme_start_bss_req) { + lim_log(mac_ctx, LOGE, + FL("Allocate Memory fail for LimStartBssReq")); + /* Send failure response to host */ + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + cdf_mem_set((void *)sme_start_bss_req, size, 0); + cdf_mem_copy(sme_start_bss_req, msg_buf, + sizeof(tSirSmeStartBssReq)); + if (!lim_is_sme_start_bss_req_valid(mac_ctx, + sme_start_bss_req)) { + lim_log(mac_ctx, LOGW, + FL("Received invalid eWNI_SME_START_BSS_REQ")); + ret_code = 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 + */ + session = pe_find_session_by_bssid(mac_ctx, + sme_start_bss_req->bssId, &session_id); + if (session != NULL) { + lim_log(mac_ctx, LOGW, + FL("Session Already exists for given BSSID")); + ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + session = NULL; + goto free; + } else { + session = pe_create_session(mac_ctx, + sme_start_bss_req->bssId, + &session_id, mac_ctx->lim.maxStation, + sme_start_bss_req->bssType); + if (session == NULL) { + lim_log(mac_ctx, LOGW, + FL("Session Can not be created ")); + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + } + + /* Probe resp add ie */ + lim_start_bss_update_add_ie_buffer(mac_ctx, + &session->addIeParams.probeRespData_buff, + &session->addIeParams.probeRespDataLen, + sme_start_bss_req->addIeParams.probeRespData_buff, + sme_start_bss_req->addIeParams.probeRespDataLen); + + /* Probe Beacon add ie */ + lim_start_bss_update_add_ie_buffer(mac_ctx, + &session->addIeParams.probeRespBCNData_buff, + &session->addIeParams.probeRespBCNDataLen, + sme_start_bss_req->addIeParams.probeRespBCNData_buff, + sme_start_bss_req->addIeParams.probeRespBCNDataLen); + + /* Assoc resp IE */ + lim_start_bss_update_add_ie_buffer(mac_ctx, + &session->addIeParams.assocRespData_buff, + &session->addIeParams.assocRespDataLen, + sme_start_bss_req->addIeParams.assocRespData_buff, + sme_start_bss_req->addIeParams.assocRespDataLen); + + /* Store the session related params in newly created session */ + session->pLimStartBssReq = sme_start_bss_req; + + /* Store PE session_id in session Table */ + session->peSessionId = session_id; + + /* Store SME session Id in sessionTable */ + session->smeSessionId = sme_start_bss_req->sessionId; + + session->transactionId = sme_start_bss_req->transactionId; + + cdf_mem_copy(&(session->htConfig), + &(sme_start_bss_req->htConfig), + sizeof(session->htConfig)); + + sir_copy_mac_addr(session->selfMacAddr, + sme_start_bss_req->selfMacAddr); + + /* Copy SSID to session table */ + cdf_mem_copy((uint8_t *) &session->ssId, + (uint8_t *) &sme_start_bss_req->ssId, + (sme_start_bss_req->ssId.length + 1)); + + session->bssType = sme_start_bss_req->bssType; + + session->nwType = sme_start_bss_req->nwType; + + session->beaconParams.beaconInterval = + sme_start_bss_req->beaconInterval; + + /* Store the channel number in session Table */ + session->currentOperChannel = + sme_start_bss_req->channelId; + + /* Store Persona */ + session->pePersona = sme_start_bss_req->bssPersona; + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("PE PERSONA=%d"), session->pePersona); + + /* Update the phymode */ + session->gLimPhyMode = sme_start_bss_req->nwType; + + session->maxTxPower = + cfg_get_regulatory_max_transmit_power(mac_ctx, + session->currentOperChannel); + /* Store the dot 11 mode in to the session Table */ + session->dot11mode = sme_start_bss_req->dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + session->cc_switch_mode = + sme_start_bss_req->cc_switch_mode; +#endif + session->htCapability = + IS_DOT11_MODE_HT(session->dot11mode); + session->vhtCapability = + IS_DOT11_MODE_VHT(session->dot11mode); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("*****session->vhtCapability = %d"), + session->vhtCapability); + session->txLdpcIniFeatureEnabled = + sme_start_bss_req->txLdpcIniFeatureEnabled; + + if (mac_ctx->roam.configParam.enable2x2) + session->nss = 2; + else + session->nss = 1; +#ifdef WLAN_FEATURE_11W + session->limRmfEnabled = + sme_start_bss_req->pmfCapable ? 1 : 0; + lim_log(mac_ctx, LOG1, FL("Session RMF enabled: %d"), + session->limRmfEnabled); +#endif + + cdf_mem_copy((void *)&session->rateSet, + (void *)&sme_start_bss_req->operationalRateSet, + sizeof(tSirMacRateSet)); + cdf_mem_copy((void *)&session->extRateSet, + (void *)&sme_start_bss_req->extendedRateSet, + sizeof(tSirMacRateSet)); + + switch (sme_start_bss_req->bssType) { + case eSIR_INFRA_AP_MODE: + lim_configure_ap_start_bss_session(mac_ctx, session, + sme_start_bss_req); + break; + case eSIR_IBSS_MODE: + session->limSystemRole = eLIM_STA_IN_IBSS_ROLE; + lim_get_short_slot_from_phy_mode(mac_ctx, session, + session->gLimPhyMode, + &session->shortSlotTimeSupported); + + /* + * initialize to "OPEN". + * will be updated upon key installation + */ + session->encryptType = eSIR_ED_NONE; + + break; + + case eSIR_BTAMP_AP_MODE: + session->limSystemRole = eLIM_BT_AMP_AP_ROLE; + break; + + case eSIR_BTAMP_STA_MODE: + session->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; + } + + /* + * BT-AMP: Allocate memory for the array of + * parsed (Re)Assoc request structure + */ + if ((sme_start_bss_req->bssType == eSIR_BTAMP_AP_MODE) || + (sme_start_bss_req->bssType == eSIR_INFRA_AP_MODE)) { + session->parsedAssocReq = + cdf_mem_malloc(session->dph.dphHashTable. + size * sizeof(tpSirAssocReq)); + if (NULL == session->parsedAssocReq) { + lim_log(mac_ctx, LOGW, + FL("AllocateMemory() failed")); + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + cdf_mem_set(session->parsedAssocReq, + (session->dph.dphHashTable.size * + sizeof(tpSirAssocReq)), 0); + } + + if (!sme_start_bss_req->channelId) { + lim_log(mac_ctx, LOGE, + FL("Received invalid eWNI_SME_START_BSS_REQ")); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto free; + } + channel_number = sme_start_bss_req->channelId; +#ifdef QCA_HT_2040_COEX + if (sme_start_bss_req->obssEnabled) + session->htSupportedChannelWidthSet = + session->htCapability; + else +#endif + session->htSupportedChannelWidthSet = + (sme_start_bss_req->sec_ch_offset) ? 1 : 0; + session->htSecondaryChannelOffset = + sme_start_bss_req->sec_ch_offset; + session->htRecommendedTxWidthSet = + (session->htSecondaryChannelOffset) ? 1 : 0; + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("cbMode %u"), sme_start_bss_req->cbMode); + if (session->vhtCapability || session->htCapability) { + chanwidth = sme_start_bss_req->vht_channel_width; + lim_log(mac_ctx, LOG1, FL("vht_channel_width %u"), + sme_start_bss_req->vht_channel_width); + if (channel_number <= RF_CHAN_14 && + chanwidth != eHT_CHANNEL_WIDTH_20MHZ) { + chanwidth = CH_WIDTH_20MHZ; + session->htSupportedChannelWidthSet = 0; + lim_log(mac_ctx, LOG1, + FL("Set chanwidth to 20Mhz, chan %d"), + channel_number); + } + session->ch_width = chanwidth; + if (session->htSupportedChannelWidthSet) { + session->ch_center_freq_seg0 = + sme_start_bss_req->center_freq_seg0; + session->ch_center_freq_seg1 = + sme_start_bss_req->center_freq_seg1; + } else { + session->ch_center_freq_seg0 = 0; + session->ch_center_freq_seg1 = 0; + } + } + + if (session->vhtCapability && + (CH_WIDTH_160MHZ > session->ch_width)) { + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, FL( + "cfg get vht su bformer failed")); + + session->enable_su_tx_bformer = val; + } else { + session->nss = 1; + } + lim_log(mac_ctx, LOG1, FL("vht su tx bformer %d"), val); + + /* Delete pre-auth list if any */ + lim_delete_pre_auth_list(mac_ctx); + + /* + * keep the RSN/WPA IE information in PE Session Entry + * later will be using this to check when received (Re)Assoc req + */ + lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(mac_ctx, + &sme_start_bss_req->rsnIE, session); + + if (LIM_IS_AP_ROLE(session) || LIM_IS_IBSS_ROLE(session)) { + session->gLimProtectionControl = + sme_start_bss_req->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 + */ + cdf_mem_copy((void *)&session->cfgProtection, + (void *)&sme_start_bss_req->ht_capab, + sizeof(uint16_t)); + /* Initialize WPS PBC session link list */ + session->pAPWPSPBCSession = NULL; + } + /* Prepare and Issue LIM_MLM_START_REQ to MLM */ + mlm_start_req = cdf_mem_malloc(sizeof(tLimMlmStartReq)); + if (NULL == mlm_start_req) { + lim_log(mac_ctx, LOGP, + FL("Allocate Memory failed for mlmStartReq")); + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + + cdf_mem_set((void *)mlm_start_req, sizeof(tLimMlmStartReq), 0); + + /* Copy SSID to the MLM start structure */ + cdf_mem_copy((uint8_t *) &mlm_start_req->ssId, + (uint8_t *) &sme_start_bss_req->ssId, + sme_start_bss_req->ssId.length + 1); + mlm_start_req->ssidHidden = sme_start_bss_req->ssidHidden; + mlm_start_req->obssProtEnabled = + sme_start_bss_req->obssProtEnabled; + + mlm_start_req->bssType = session->bssType; + + /* Fill PE session Id from the session Table */ + mlm_start_req->sessionId = session->peSessionId; + + if ((mlm_start_req->bssType == eSIR_BTAMP_STA_MODE) || + (mlm_start_req->bssType == eSIR_BTAMP_AP_MODE) || + (mlm_start_req->bssType == eSIR_INFRA_AP_MODE)) { + /* + * Copy the BSSId from sessionTable to + * mlmStartReq struct + */ + sir_copy_mac_addr(mlm_start_req->bssId, session->bssId); + } else { + /* ibss mode */ + mac_ctx->lim.gLimIbssCoalescingHappened = false; + + ret_status = wlan_cfg_get_int(mac_ctx, + WNI_CFG_IBSS_AUTO_BSSID, + &auto_gen_bssid); + if (ret_status != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("Get Auto Gen BSSID fail,Status=%d"), + ret_status); + ret_code = eSIR_LOGP_EXCEPTION; + goto free; + } + + if (!auto_gen_bssid) { + /* + * We're not auto generating BSSID. + * Instead, get it from session entry + */ + sir_copy_mac_addr(mlm_start_req->bssId, + session->bssId); + /* + * Start IBSS group BSSID + * Auto Generating BSSID. + */ + auto_gen_bssid = ((mlm_start_req->bssId[0] & + 0x01) ? true : false); + } + + if (auto_gen_bssid) { + /* + * if BSSID is not any uc id. + * then use locally generated BSSID. + * Autogenerate the BSSID + */ + lim_get_random_bssid(mac_ctx, + mlm_start_req->bssId); + mlm_start_req->bssId[0] = 0x02; + + /* + * Copy randomly generated BSSID + * to the session Table + */ + sir_copy_mac_addr(session->bssId, + mlm_start_req->bssId); + } + } + /* store the channel num in mlmstart req structure */ + mlm_start_req->channelNumber = session->currentOperChannel; + mlm_start_req->cbMode = sme_start_bss_req->cbMode; + mlm_start_req->beaconPeriod = + session->beaconParams.beaconInterval; + + if (LIM_IS_AP_ROLE(session)) { + mlm_start_req->dtimPeriod = session->dtimPeriod; + mlm_start_req->wps_state = session->wps_state; + + } else { + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("could not retrieve DTIM Period")); + mlm_start_req->dtimPeriod = (uint8_t) val; + } + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_CFP_PERIOD, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("could not retrieve Beacon interval")); + mlm_start_req->cfParamSet.cfpPeriod = (uint8_t) val; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_CFP_MAX_DURATION, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("could not retrieve CFPMaxDuration")); + mlm_start_req->cfParamSet.cfpMaxDuration = (uint16_t) val; + + /* + * this may not be needed anymore now, + * as rateSet is now included in the + * session entry and MLM has session context. + */ + cdf_mem_copy((void *)&mlm_start_req->rateSet, + (void *)&session->rateSet, + sizeof(tSirMacRateSet)); + + /* Now populate the 11n related parameters */ + mlm_start_req->nwType = session->nwType; + mlm_start_req->htCapable = session->htCapability; + + mlm_start_req->htOperMode = mac_ctx->lim.gHTOperMode; + /* Unused */ + mlm_start_req->dualCTSProtection = + mac_ctx->lim.gHTDualCTSProtection; + mlm_start_req->txChannelWidthSet = + session->htRecommendedTxWidthSet; + + session->limRFBand = lim_get_rf_band(channel_number); + + /* Initialize 11h Enable Flag */ + session->lim11hEnable = 0; + if ((mlm_start_req->bssType != eSIR_IBSS_MODE) && + (SIR_BAND_5_GHZ == session->limRFBand)) { + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Fail to get WNI_CFG_11H_ENABLED ")); + else + session->lim11hEnable = val; + + if (session->lim11hEnable && + (eSIR_INFRA_AP_MODE == + mlm_start_req->bssType)) { + cfg_get_wmi_dfs_master_param = + wlan_cfg_get_int(mac_ctx, + WNI_CFG_DFS_MASTER_ENABLED, + &val); + session->lim11hEnable = val; + } + if (cfg_get_wmi_dfs_master_param != eSIR_SUCCESS) + /* Failed get CFG WNI_CFG_DFS_MASTER_ENABLED */ + lim_log(mac_ctx, LOGE, + FL("Get Fail, CFG DFS ENABLE")); + } + + if (!session->lim11hEnable) { + if (cfg_set_int(mac_ctx, + WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) != + eSIR_SUCCESS) + /* + * Failed to set the CFG param + * WNI_CFG_LOCAL_POWER_CONSTRAINT + */ + lim_log(mac_ctx, LOGE, + FL("Set LOCAL_POWER_CONSTRAINT failed")); + } + + session->limPrevSmeState = session->limSmeState; + session->limSmeState = eLIM_SME_WT_START_BSS_STATE; + MTRACE(mac_trace + (mac_ctx, TRACE_CODE_SME_STATE, + session->peSessionId, + session->limSmeState)); + + lim_post_mlm_message(mac_ctx, LIM_MLM_START_REQ, + (uint32_t *) mlm_start_req); + return; + } else { + + lim_log(mac_ctx, LOGE, + FL("Received unexpected START_BSS_REQ, in state %X"), + mac_ctx->lim.gLimSmeState); + ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; + goto end; + } /* if (mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) */ + +free: + if ((session != NULL) && + (session->pLimStartBssReq == sme_start_bss_req)) { + session->pLimStartBssReq = NULL; + } + cdf_mem_free(sme_start_bss_req); + cdf_mem_free(mlm_start_req); + +end: + if (sme_start_bss_req != NULL) { + sme_session_id = sme_start_bss_req->sessionId; + sme_transaction_id = sme_start_bss_req->transactionId; + } + if (NULL != session) { + pe_delete_session(mac_ctx, session); + session = NULL; + } + lim_send_sme_start_bss_rsp(mac_ctx, eWNI_SME_START_BSS_RSP, ret_code, + session, sme_session_id, sme_transaction_id); +} + +/** + * __lim_process_sme_start_bss_req() - Call handler to start BSS + * + * @pMac: Global MAC context + * @pMsg: Message pointer + * + * Wrapper for the function __lim_handle_sme_start_bss_request + * This message will be defered until softmac come out of + * scan mode or if we have detected radar on the current + * operating channel. + * + * return true - If we consumed the buffer + * false - If have defered the message. + */ +static bool __lim_process_sme_start_bss_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (__lim_is_defered_msg_for_learn(pMac, pMsg) || + __lim_is_defered_msg_for_radar(pMac, pMsg)) { + /** + * If message defered, buffer is not consumed yet. + * So return false + */ + return false; + } + + __lim_handle_sme_start_bss_request(pMac, (uint32_t *) pMsg->bodyptr); + return true; +} + +/** + * lim_get_random_bssid() + * + * 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 lim_get_random_bssid(tpAniSirGlobal pMac, uint8_t *data) +{ + uint32_t random[2]; + random[0] = tx_time_get(); + random[0] |= (random[0] << 15); + random[1] = random[0] >> 1; + cdf_mem_copy(data, (uint8_t *) random, sizeof(tSirMacAddr)); +} + +static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, + tpSirSmeScanReq pScanReq) +{ + tSirScanOffloadReq *pScanOffloadReq; + uint8_t *p; + uint8_t *ht_cap_ie; + tSirMsgQ msg; + uint16_t i, len; + uint16_t ht_cap_len = 0, addn_ie_len = 0; +#ifdef WLAN_FEATURE_11AC + uint8_t *vht_cap_ie; + uint16_t vht_cap_len = 0; +#endif /* WLAN_FEATURE_11AC */ + tSirRetStatus status, rc = eSIR_SUCCESS; + tDot11fIEExtCap extracted_extcap = {0}; + bool extcap_present = true; + + 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; + lim_log(pMac, LOG1, + FL("Unable to Strip ExtCap IE from Scan Req")); + } + + if (extcap_present) { + lim_log(pMac, LOG1, + FL("Extcap was part of SCAN IE - Updating FW")); + lim_send_ext_cap_ie(pMac, pScanReq->sessionId, + &extracted_extcap, true); + } + } else { + lim_log(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 (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { + lim_log(pMac, LOG1, + FL("Adding HT Caps IE since dot11mode=%d"), + pScanReq->dot11mode); + /* 2 bytes for EID and Length */ + ht_cap_len = 2 + sizeof(tHtCaps); + len += ht_cap_len; + addn_ie_len += ht_cap_len; + } + +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) { + lim_log(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 = cdf_mem_malloc(len); + if (NULL == pScanOffloadReq) { + lim_log(pMac, LOGE, + FL("AllocateMemory failed for pScanOffloadReq")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set((uint8_t *) pScanOffloadReq, len, 0); + + msg.type = WMA_START_SCAN_OFFLOAD_REQ; + msg.bodyptr = pScanOffloadReq; + msg.bodyval = 0; + + cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId, + (uint8_t *) pScanReq->bssId, sizeof(tSirMacAddr)); + + if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) { + lim_log(pMac, LOGE, + FL("Invalid value (%d) for numSsid"), + SIR_SCAN_MAX_NUM_SSID); + cdf_mem_free(pScanOffloadReq); + return CDF_STATUS_E_FAILURE; + } + + pScanOffloadReq->numSsid = pScanReq->numSsid; + for (i = 0; i < pScanOffloadReq->numSsid; i++) { + pScanOffloadReq->ssId[i].length = pScanReq->ssId[i].length; + cdf_mem_copy((uint8_t *) pScanOffloadReq->ssId[i].ssId, + (uint8_t *) pScanReq->ssId[i].ssId, + pScanOffloadReq->ssId[i].length); + } + + pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid; + cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr, + (uint8_t *) 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; + + /* for normal scan, the value for p2pScanType should be 0 + always */ + if (pScanReq->p2pSearch) + pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_SEARCH; + + pScanOffloadReq->sessionId = pScanReq->sessionId; + pScanOffloadReq->scan_id = pScanReq->scan_id; + + if (pScanOffloadReq->sessionId >= pMac->lim.maxBssId) + lim_log(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; + cdf_mem_copy((uint8_t *) pScanOffloadReq + + pScanOffloadReq->uIEFieldOffset, + (uint8_t *) pScanReq + pScanReq->uIEFieldOffset, + pScanReq->uIEFieldLen); + + /* Copy HT Capability info if dot11mode is HT */ + if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { + /* Populate EID and Length field here */ + ht_cap_ie = (uint8_t *) pScanOffloadReq + + pScanOffloadReq->uIEFieldOffset + + pScanOffloadReq->uIEFieldLen; + cdf_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 = (uint8_t *) pScanOffloadReq + + pScanOffloadReq->uIEFieldOffset + + pScanOffloadReq->uIEFieldLen; + cdf_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 = wma_post_ctrl_msg(pMac, &msg); + if (rc != eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure")); + cdf_mem_free(pScanOffloadReq); + return CDF_STATUS_E_FAILURE; + } + + lim_log(pMac, LOG1, FL("Processed Offload Scan Request Successfully")); + + return CDF_STATUS_SUCCESS; +} + +/** + * __lim_process_sme_scan_req() - Process the SME Scan Request + * @mac_ctx: Global MAC Context + * @msg_buf: Buffer which contains the request and pertinent parameters + * + * This function is called to process SME_SCAN_REQ message + * from HDD or upper layer application. + * + * Return: None + */ + +static void __lim_process_sme_scan_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tpSirSmeScanReq scan_req; + uint8_t valid_req = 0; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SCAN_REQ_EVENT, NULL, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + + scan_req = (tpSirSmeScanReq) msg_buf; + lim_log(mac_ctx, LOG1, + FL("SME SCAN REQ id %d numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d rsp %d"), + scan_req->scan_id, scan_req->channelList.numChannels, + scan_req->minChannelTime, scan_req->maxChannelTime, + scan_req->uIEFieldLen, scan_req->returnAfterFirstMatch, + scan_req->returnFreshResults, scan_req->returnUniqueResults, + scan_req->scanType, mac_ctx->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. + */ + mac_ctx->lim.gLimRspReqd = true; + + /* + * copy the Self MAC address from SmeReq to the globalplace, + * used for sending probe req + */ + sir_copy_mac_addr(mac_ctx->lim.gSelfMacAddr, scan_req->selfMacAddr); + valid_req = lim_is_sme_scan_req_valid(mac_ctx, scan_req); + + if (!valid_req || mac_ctx->lim.scan_disabled) { + lim_log(mac_ctx, LOGE, + FL("Scan disabled %d, Valid Scan Req %d"), + mac_ctx->lim.scan_disabled, valid_req); + + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + + lim_send_sme_scan_rsp(mac_ctx, + eSIR_SME_INVALID_PARAMETERS, + scan_req->sessionId, + scan_req->transactionId, + scan_req->scan_id); + } + return; + } + + /* + * 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 (__lim_fresh_scan_reqd(mac_ctx, scan_req->returnFreshResults)) { + + mac_ctx->lim.gLim24Band11dScanDone = 0; + mac_ctx->lim.gLim50Band11dScanDone = 0; + mac_ctx->lim.gLimReturnAfterFirstMatch = + scan_req->returnAfterFirstMatch; + mac_ctx->lim.gLimReturnUniqueResults = + ((scan_req->returnUniqueResults) > 0 ? true : false); + + if (CDF_STATUS_SUCCESS != + lim_send_hal_start_scan_offload_req(mac_ctx, + scan_req)) { + lim_log(mac_ctx, LOGE, FL( + "Couldn't send Offload scan request")); + lim_send_sme_scan_rsp(mac_ctx, + eSIR_SME_INVALID_PARAMETERS, + scan_req->sessionId, + scan_req->transactionId, + scan_req->scan_id); + return; + } + } + else { + /* In all other cases return 'cached' scan results */ + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + lim_send_sme_scan_rsp(mac_ctx, eSIR_SME_SUCCESS, + scan_req->sessionId, + scan_req->transactionId, scan_req->scan_id); + } + } +} + +#ifdef FEATURE_OEM_DATA_SUPPORT + +static void __lim_process_sme_oem_data_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirOemDataReq pOemDataReq; + tLimMlmOemDataReq *pMlmOemDataReq; + + pOemDataReq = (tpSirOemDataReq) pMsgBuf; + + /* post the lim mlm message now */ + pMlmOemDataReq = cdf_mem_malloc(sizeof(tLimMlmOemDataReq)); + if (NULL == pMlmOemDataReq) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for mlmOemDataReq")); + return; + } + /* Initialize this buffer */ + cdf_mem_set(pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0); + + cdf_mem_copy(pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq, + OEM_DATA_REQ_SIZE); + + /* Issue LIM_MLM_OEM_DATA_REQ to MLM */ + lim_post_mlm_message(pMac, LIM_MLM_OEM_DATA_REQ, + (uint32_t *) pMlmOemDataReq); + + return; + +} /*** end __lim_process_sme_oem_data_req() ***/ + +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +/** + * __lim_process_clear_dfs_channel_list() + * + ***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 __lim_process_clear_dfs_channel_list(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + cdf_mem_set(&pMac->lim.dfschannelList, sizeof(tSirDFSChannelList), 0); +} + +/** + * __lim_process_sme_join_req() - process SME_JOIN_REQ message + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: A pointer to the SME message buffer + * + * This function is called to process SME_JOIN_REQ message + * from HDD or upper layer application. + * + * Return: None + */ +static void +__lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tpSirSmeJoinReq sme_join_req = NULL; + tLimMlmJoinReq *mlm_join_req; + tSirResultCodes ret_code = eSIR_SME_SUCCESS; + uint32_t val = 0; + uint16_t n_size; + uint8_t session_id; + tpPESession session = NULL; + uint8_t sme_session_id; + uint16_t sme_transaction_id; + tPowerdBm local_power_constraint = 0, reg_max = 0; + uint16_t ie_len; + uint8_t *vendor_ie; + tSirBssDescription bss_desc; + +/* FEATURE_WLAN_DIAG_SUPPORT */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + /* + * Not sending any session, since it is not created yet. + * The response whould have correct state. + */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_log(mac_ctx, LOG1, FL("Received SME_JOIN_REQ")); +#ifdef WLAN_FEATURE_VOWIFI + /* + * Need to read the CFG here itself as this is + * used in limExtractAPCapability() below. + * This CFG is actually read in rrm_update_config() + * which is called later. Because this is not + * read, RRM related path before calling rrm_update_config() + * is not getting executed causing issues + * like not honoring power constraint on 1st association + * after driver loading. + */ + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RRM_ENABLED, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, FL("cfg get rrm enabled failed")); + mac_ctx->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; + val = 0; +#endif /* WLAN_FEATURE_VOWIFI */ + + /* + * 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 (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE) { + n_size = __lim_get_sme_join_req_size_for_alloc((uint8_t *) + msg_buf); + + sme_join_req = cdf_mem_malloc(n_size); + if (NULL == sme_join_req) { + lim_log(mac_ctx, LOGP, + FL("AllocateMemory failed for sme_join_req")); + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + return; + } + (void)cdf_mem_set((void *)sme_join_req, n_size, 0); + (void)cdf_mem_copy((void *)sme_join_req, (void *)msg_buf, + n_size); + + if (!lim_is_sme_join_req_valid(mac_ctx, sme_join_req)) { + /* Received invalid eWNI_SME_JOIN_REQ */ + /* Log the event */ + lim_log(mac_ctx, LOGW, + FL("SessionId:%d JOIN REQ with invalid data"), + sme_join_req->sessionId); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + bss_desc = sme_join_req->bssDescription; + /* check for the existence of start BSS session */ + + session = pe_find_session_by_bssid(mac_ctx, bss_desc.bssId, + &session_id); + + if (session != NULL) { + lim_log(mac_ctx, LOGE, + FL("Session(%d) Already exists for BSSID: " + MAC_ADDRESS_STR " in limSmeState = %X"), + session_id, + MAC_ADDR_ARRAY(bss_desc.bssId), + session->limSmeState); + + if (session->limSmeState == eLIM_SME_LINK_EST_STATE && + session->smeSessionId == sme_join_req->sessionId) { + /* + * Received eWNI_SME_JOIN_REQ for same + * BSS as currently associated. + * Log the event and send success + */ + lim_log(mac_ctx, LOGW, + FL("SessionId: %d"), session_id); + lim_log(mac_ctx, LOGW, + FL("JOIN_REQ for current joined BSS")); + /* Send Join success response to host */ + ret_code = eSIR_SME_ALREADY_JOINED_A_BSS; + session = NULL; + goto end; + } else { + lim_log(mac_ctx, LOGE, + FL("JOIN_REQ not for current joined BSS")); + ret_code = eSIR_SME_REFUSED; + session = NULL; + goto end; + } + } else { + /* + * Session Entry does not exist for given BSSId + * Try to Create a new session + */ + session = pe_create_session(mac_ctx, bss_desc.bssId, + &session_id, mac_ctx->lim.maxStation, + eSIR_INFRASTRUCTURE_MODE); + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("Session Can not be created ")); + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } else + lim_log(mac_ctx, LOG1, + FL("SessionId:%d New session created"), + session_id); + } + session->isAmsduSupportInAMPDU = + sme_join_req->isAmsduSupportInAMPDU; + + /* + * Store Session related parameters + * Store PE session Id in session Table + */ + session->peSessionId = session_id; + + /* store the smejoin req handle in session table */ + session->pLimJoinReq = sme_join_req; + + /* Store SME session Id in sessionTable */ + session->smeSessionId = sme_join_req->sessionId; + + /* Store SME transaction Id in session Table */ + session->transactionId = sme_join_req->transactionId; + + /* Store beaconInterval */ + session->beaconParams.beaconInterval = + bss_desc.beaconInterval; + + cdf_mem_copy(&(session->htConfig), &(sme_join_req->htConfig), + sizeof(session->htConfig)); + + /* Copying of bssId is already done, while creating session */ + sir_copy_mac_addr(session->selfMacAddr, + sme_join_req->selfMacAddr); + session->bssType = sme_join_req->bsstype; + + session->statypeForBss = STA_ENTRY_PEER; + session->limWmeEnabled = sme_join_req->isWMEenabled; + session->limQosEnabled = sme_join_req->isQosEnabled; + + /* Store vendor specfic IE for CISCO AP */ + ie_len = (bss_desc.length + sizeof(bss_desc.length) - + GET_FIELD_OFFSET(tSirBssDescription, ieFields)); + + vendor_ie = cfg_get_vendor_ie_ptr_from_oui(mac_ctx, + SIR_MAC_CISCO_OUI, SIR_MAC_CISCO_OUI_SIZE, + ((uint8_t *)&bss_desc.ieFields), ie_len); + + if (NULL != vendor_ie) { + lim_log(mac_ctx, LOGE, + FL("DUT is trying to connect to Cisco AP")); + session->isCiscoVendorAP = true; + } else { + session->isCiscoVendorAP = false; + } + + /* Copy the dot 11 mode in to the session table */ + + session->dot11mode = sme_join_req->dot11mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + session->cc_switch_mode = sme_join_req->cc_switch_mode; +#endif + session->nwType = bss_desc.nwType; + session->enableAmpduPs = sme_join_req->enableAmpduPs; + session->enableHtSmps = sme_join_req->enableHtSmps; + session->htSmpsvalue = sme_join_req->htSmps; + + /*Store Persona */ + session->pePersona = sme_join_req->staPersona; + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("PE PERSONA=%d cbMode %u"), + session->pePersona, sme_join_req->cbMode); + if (mac_ctx->roam.configParam.enable2x2) + session->nss = 2; + else + session->nss = 1; +#ifdef WLAN_FEATURE_11AC + session->vhtCapability = + IS_DOT11_MODE_VHT(session->dot11mode); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, + "***__lim_process_sme_join_req: vhtCapability=%d****", + session->vhtCapability); + if (session->vhtCapability) { + if (session->pePersona == CDF_STA_MODE) { + session->txBFIniFeatureEnabled = + sme_join_req->txBFIniFeatureEnabled; + } else { + session->txBFIniFeatureEnabled = 0; + } + session->txMuBformee = sme_join_req->txMuBformee; + session->enableVhtpAid = + sme_join_req->enableVhtpAid; + session->enableVhtGid = + sme_join_req->enableVhtGid; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, + FL("***txBFIniFeatureEnabled=%d***"), + session->txBFIniFeatureEnabled); + if (wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_SU_BEAMFORMER_CAP, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, FL( + "cfg get vht su bformer failed")); + + session->enable_su_tx_bformer = val; + lim_log(mac_ctx, LOGE, FL("vht su tx bformer %d"), val); + } + if (session->vhtCapability && session->txBFIniFeatureEnabled) { + if (cfg_set_int(mac_ctx, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + session->txBFIniFeatureEnabled) != + eSIR_SUCCESS) { + /* + * Set failed for + * CFG_VHT_SU_BEAMFORMEE_CAP + */ + lim_log(mac_ctx, LOGP, + FL("Failed CFG_VHT_SU_BEAMFORMEE_CAP")); + ret_code = eSIR_LOGP_EXCEPTION; + goto end; + } + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, + "%s: txBFCsnValue=%d", __func__, + sme_join_req->txBFCsnValue); + if (cfg_set_int(mac_ctx, + WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, + sme_join_req->txBFCsnValue) != eSIR_SUCCESS) { + /* + * Set Failed for CFG + * CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED + */ + lim_log(mac_ctx, LOGP, FL("Set Fail CFG")); + ret_code = eSIR_LOGP_EXCEPTION; + goto end; + } + } +#endif + + /*Phy mode */ + session->gLimPhyMode = bss_desc.nwType; + handle_ht_capabilityand_ht_info(mac_ctx, session); + /* Copy The channel Id to the session Table */ + session->currentOperChannel = bss_desc.channelId; + /* cbMode is already merged value of peer and self - + * done by csr in csr_get_cb_mode_from_ies */ + session->htSupportedChannelWidthSet = + (sme_join_req->cbMode) ? 1 : 0; + session->htRecommendedTxWidthSet = + session->htSupportedChannelWidthSet; + session->htSecondaryChannelOffset = sme_join_req->cbMode; + + if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == sme_join_req->cbMode) { + session->ch_center_freq_seg0 = + session->currentOperChannel - 2; + session->ch_width = CH_WIDTH_40MHZ; + } else if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY == + sme_join_req->cbMode) { + session->ch_center_freq_seg0 = + session->currentOperChannel + 2; + session->ch_width = CH_WIDTH_40MHZ; + } else { + session->ch_center_freq_seg0 = 0; + session->ch_width = CH_WIDTH_20MHZ; + } + + /* Record if management frames need to be protected */ +#ifdef WLAN_FEATURE_11W + if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) { + CDF_STATUS cdf_status; + session->limRmfEnabled = 1; + session->pmfComebackTimerInfo.pMac = mac_ctx; + session->pmfComebackTimerInfo.sessionID = + session_id; + cdf_status = cdf_mc_timer_init( + &session->pmfComebackTimer, + CDF_TIMER_TYPE_SW, + lim_pmf_comeback_timer_callback, + (void *)&session->pmfComebackTimerInfo); + if (CDF_STATUS_SUCCESS != cdf_status) { + lim_log(mac_ctx, LOGP, + FL("cannot init pmf comeback timer.")); + ret_code = eSIR_LOGP_EXCEPTION; + goto end; + } + } else { + session->limRmfEnabled = 0; + } +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + session->rssi = bss_desc.rssi; +#endif + + /* Copy the SSID from smejoinreq to session entry */ + session->ssId.length = sme_join_req->ssId.length; + cdf_mem_copy(session->ssId.ssId, sme_join_req->ssId.ssId, + session->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 + session->is11Rconnection = sme_join_req->is11Rconnection; +#endif +#ifdef FEATURE_WLAN_ESE + session->isESEconnection = sme_join_req->isESEconnection; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + session->isFastTransitionEnabled = + sme_join_req->isFastTransitionEnabled; +#endif + +#ifdef FEATURE_WLAN_LFR + session->isFastRoamIniFeatureEnabled = + sme_join_req->isFastRoamIniFeatureEnabled; +#endif + session->txLdpcIniFeatureEnabled = + sme_join_req->txLdpcIniFeatureEnabled; + + if (session->bssType == eSIR_INFRASTRUCTURE_MODE) { + session->limSystemRole = eLIM_STA_ROLE; + } else if (session->bssType == eSIR_BTAMP_AP_MODE) { + session->limSystemRole = eLIM_BT_AMP_STA_ROLE; + } else { + /* + * Throw an error and return and make + * sure to delete the session. + */ + lim_log(mac_ctx, LOGE, + FL("recvd JOIN_REQ with invalid bss type %d"), + session->bssType); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + if (sme_join_req->addIEScan.length) + cdf_mem_copy(&session->pLimJoinReq->addIEScan, + &sme_join_req->addIEScan, sizeof(tSirAddie)); + + if (sme_join_req->addIEAssoc.length) + cdf_mem_copy(&session->pLimJoinReq->addIEAssoc, + &sme_join_req->addIEAssoc, sizeof(tSirAddie)); + + val = sizeof(tLimMlmJoinReq) + + session->pLimJoinReq->bssDescription.length + 2; + mlm_join_req = cdf_mem_malloc(val); + if (NULL == mlm_join_req) { + lim_log(mac_ctx, LOGP, + FL("AllocateMemory failed for mlmJoinReq")); + return; + } + (void)cdf_mem_set((void *)mlm_join_req, val, 0); + + /* PE SessionId is stored as a part of JoinReq */ + mlm_join_req->sessionId = session->peSessionId; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_JOIN_FAILURE_TIMEOUT, + (uint32_t *) &mlm_join_req->joinFailureTimeout) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("couldn't retrieve JoinFailureTimer value" + " setting to default value")); + mlm_join_req->joinFailureTimeout = + WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF; + } + + /* copy operational rate from session */ + cdf_mem_copy((void *)&session->rateSet, + (void *)&sme_join_req->operationalRateSet, + sizeof(tSirMacRateSet)); + cdf_mem_copy((void *)&session->extRateSet, + (void *)&sme_join_req->extendedRateSet, + sizeof(tSirMacRateSet)); + /* + * this may not be needed anymore now, as rateSet is now + * included in the session entry and MLM has session context. + */ + cdf_mem_copy((void *)&mlm_join_req->operationalRateSet, + (void *)&session->rateSet, + sizeof(tSirMacRateSet)); + + session->encryptType = sme_join_req->UCEncryptionType; + + mlm_join_req->bssDescription.length = + session->pLimJoinReq->bssDescription.length; + + cdf_mem_copy((uint8_t *) &mlm_join_req->bssDescription.bssId, + (uint8_t *) + &session->pLimJoinReq->bssDescription.bssId, + session->pLimJoinReq->bssDescription.length + 2); + + session->limCurrentBssCaps = + session->pLimJoinReq->bssDescription.capabilityInfo; + + reg_max = cfg_get_regulatory_max_transmit_power(mac_ctx, + session->currentOperChannel); + local_power_constraint = reg_max; + + lim_extract_ap_capability(mac_ctx, + (uint8_t *) + session->pLimJoinReq->bssDescription.ieFields, + lim_get_ielen_from_bss_description( + &session->pLimJoinReq->bssDescription), + &session->limCurrentBssQosCaps, + &session->limCurrentBssPropCap, + &session->gLimCurrentBssUapsd, + &local_power_constraint, session); + +#ifdef FEATURE_WLAN_ESE + session->maxTxPower = lim_get_max_tx_power(reg_max, + local_power_constraint, + mac_ctx->roam.configParam.nTxPowerCap); +#else + session->maxTxPower = + CDF_MIN(reg_max, (local_power_constraint)); +#endif +#if defined WLAN_VOWIFI_DEBUG + lim_log(mac_ctx, LOGE, + "Regulatory max = %d, local power constraint = %d" + reg_max, local_power_constraint); + lim_log(mac_ctx, LOGE, FL(" max tx = %d"), + session->maxTxPower); +#endif + + if (session->gLimCurrentBssUapsd) { + session->gUapsdPerAcBitmask = + session->pLimJoinReq->uapsdPerAcBitmask; + lim_log(mac_ctx, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + session->gUapsdPerAcBitmask); + + /* resetting the dynamic uapsd mask */ + session->gUapsdPerAcDeliveryEnableMask = 0; + session->gUapsdPerAcTriggerEnableMask = 0; + } + + session->limRFBand = + lim_get_rf_band(session->currentOperChannel); + + /* Initialize 11h Enable Flag */ + if (SIR_BAND_5_GHZ == session->limRFBand) { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_11H_ENABLED, + &val) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("Fail to get WNI_CFG_11H_ENABLED ")); + session->lim11hEnable = + WNI_CFG_11H_ENABLED_STADEF; + } else { + session->lim11hEnable = val; + } + } else { + session->lim11hEnable = 0; + } + + /* + * To care of the scenario when STA transitions from + * IBSS to Infrastructure mode. + */ + mac_ctx->lim.gLimIbssCoalescingHappened = false; + + session->limPrevSmeState = session->limSmeState; + session->limSmeState = eLIM_SME_WT_JOIN_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session->peSessionId, + session->limSmeState)); + + lim_log(mac_ctx, LOG1, + FL("SME JoinReq:Sessionid %d SSID len %d SSID : %s Channel %d, BSSID " MAC_ADDRESS_STR), + mlm_join_req->sessionId, session->ssId.length, + session->ssId.ssId, session->currentOperChannel, + MAC_ADDR_ARRAY(session->bssId)); + + /* Indicate whether spectrum management is enabled */ + session->spectrumMgtEnabled = + sme_join_req->spectrumMgtIndicator; + + /* Enable the spectrum management if this is a DFS channel */ + if (session->country_info_present && + lim_isconnected_on_dfs_channel( + session->currentOperChannel)) + session->spectrumMgtEnabled = true; + + session->isOSENConnection = sme_join_req->isOSENConnection; + + lim_log(mac_ctx, LOG1, + FL("SessionId:%d MLM_JOIN_REQ is posted to MLM SM"), + mlm_join_req->sessionId); + /* Issue LIM_MLM_JOIN_REQ to MLM */ + lim_post_mlm_message(mac_ctx, LIM_MLM_JOIN_REQ, + (uint32_t *) mlm_join_req); + return; + + } else { + /* Received eWNI_SME_JOIN_REQ un expected state */ + lim_log(mac_ctx, LOGE, + FL("received unexpected SME_JOIN_REQ in state %X"), + mac_ctx->lim.gLimSmeState); + lim_print_sme_state(mac_ctx, LOGE, mac_ctx->lim.gLimSmeState); + ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + session = NULL; + goto end; + } + +end: + sme_session_id = sme_join_req->sessionId; + sme_transaction_id = sme_join_req->transactionId; + + if (sme_join_req) { + cdf_mem_free(sme_join_req); + sme_join_req = NULL; + if (NULL != session) + session->pLimJoinReq = NULL; + } + if (ret_code != eSIR_SME_SUCCESS) { + if (NULL != session) { + pe_delete_session(mac_ctx, session); + session = NULL; + } + } + lim_log(mac_ctx, LOG1, + FL("Send failure status on sessionid: %d with ret_code = %d"), + sme_session_id, ret_code); + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, ret_code, + eSIR_MAC_UNSPEC_FAILURE_STATUS, session, sme_session_id, + sme_transaction_id); +} + +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI +uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower, + uint8_t iniTxPower) +{ + uint8_t maxTxPower = 0; + uint8_t txPower = CDF_MIN(regMax, (apTxPower)); + txPower = CDF_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 + +/** + * __lim_process_sme_reassoc_req() - process reassoc req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process SME_REASSOC_REQ message + * from HDD or upper layer application. + * + * Return: None + */ + +static void __lim_process_sme_reassoc_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + uint16_t caps; + uint32_t val; + tpSirSmeJoinReq reassoc_req = NULL; + tLimMlmReassocReq *mlm_reassoc_req; + tSirResultCodes ret_code = eSIR_SME_SUCCESS; + tpPESession session_entry = NULL; + uint8_t session_id; + uint8_t sme_session_id; + uint16_t transaction_id; + tPowerdBm local_pwr_constraint = 0, reg_max = 0; + uint32_t tele_bcn_en = 0; + uint16_t size; + + lim_log(mac_ctx, LOG3, FL("Received REASSOC_REQ")); + + size = __lim_get_sme_join_req_size_for_alloc((uint8_t *)msg_buf); + reassoc_req = cdf_mem_malloc(size); + if (NULL == reassoc_req) { + lim_log(mac_ctx, LOGP, + FL("call to AllocateMemory failed for reassoc_req")); + + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + (void)cdf_mem_set((void *)reassoc_req, size, 0); + (void)cdf_mem_copy((void *)reassoc_req, (void *)msg_buf, size); + + if (!lim_is_sme_join_req_valid(mac_ctx, + (tpSirSmeJoinReq)reassoc_req)) { + /* + * Received invalid eWNI_SME_REASSOC_REQ + */ + lim_log(mac_ctx, LOGW, + FL("received SME_REASSOC_REQ with invalid data")); + + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + session_entry = pe_find_session_by_bssid(mac_ctx, + reassoc_req->bssDescription.bssId, + &session_id); + if (session_entry == NULL) { + lim_print_mac_addr(mac_ctx, reassoc_req->bssDescription.bssId, + LOGE); + lim_log(mac_ctx, LOGE, + FL("Session does not exist for given bssId")); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_REQ_EVENT, + session_entry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + /* mac_ctx->lim.gpLimReassocReq = reassoc_req;//TO SUPPORT BT-AMP */ + + /* Store the reassoc handle in the session Table */ + session_entry->pLimReAssocReq = reassoc_req; + + session_entry->dot11mode = reassoc_req->dot11mode; + session_entry->vhtCapability = + IS_DOT11_MODE_VHT(reassoc_req->dot11mode); + /* + * Reassociate request is expected + * in link established state only. + */ + + if (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE) { +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) { + /* + * May be from 11r FT pre-auth. So lets check it + * before we bail out + */ + lim_log(mac_ctx, LOG1, FL( + "Session in reassoc state is %d"), + session_entry->peSessionId); + + /* Make sure its our preauth bssid */ + if (!cdf_mem_compare(reassoc_req->bssDescription.bssId, + session_entry->limReAssocbssId, + 6)) { + lim_print_mac_addr(mac_ctx, + reassoc_req->bssDescription. + bssId, LOGE); + lim_log(mac_ctx, LOGP, + FL("Unknown bssId in reassoc state")); + ret_code = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + lim_process_mlm_ft_reassoc_req(mac_ctx, msg_buf, + session_entry); + return; + } +#endif + /* + * Should not have received eWNI_SME_REASSOC_REQ + */ + lim_log(mac_ctx, LOGE, + FL("received unexpected SME_REASSOC_REQ in state %X"), + session_entry->limSmeState); + lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState); + + ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; + goto end; + } + + cdf_mem_copy(session_entry->limReAssocbssId, + session_entry->pLimReAssocReq->bssDescription.bssId, + sizeof(tSirMacAddr)); + + session_entry->limReassocChannelId = + session_entry->pLimReAssocReq->bssDescription.channelId; + + session_entry->reAssocHtSupportedChannelWidthSet = + (session_entry->pLimReAssocReq->cbMode) ? 1 : 0; + session_entry->reAssocHtRecommendedTxWidthSet = + session_entry->reAssocHtSupportedChannelWidthSet; + session_entry->reAssocHtSecondaryChannelOffset = + session_entry->pLimReAssocReq->cbMode; + + session_entry->limReassocBssCaps = + session_entry->pLimReAssocReq->bssDescription.capabilityInfo; + reg_max = cfg_get_regulatory_max_transmit_power(mac_ctx, + session_entry->currentOperChannel); + local_pwr_constraint = reg_max; + + lim_extract_ap_capability(mac_ctx, + (uint8_t *)session_entry->pLimReAssocReq->bssDescription.ieFields, + lim_get_ielen_from_bss_description( + &session_entry->pLimReAssocReq->bssDescription), + &session_entry->limReassocBssQosCaps, + &session_entry->limReassocBssPropCap, + &session_entry->gLimCurrentBssUapsd, + &local_pwr_constraint, session_entry); + session_entry->maxTxPower = CDF_MIN(reg_max, (local_pwr_constraint)); +#if defined WLAN_VOWIFI_DEBUG + lim_log(mac_ctx, LOGE, + "Regulatory max = %d, local pwr constraint = %d, max tx = %d", + reg_max, local_pwr_constraint, + session_entry->maxTxPower); +#endif + /* Copy the SSID from session entry to local variable */ + session_entry->limReassocSSID.length = reassoc_req->ssId.length; + cdf_mem_copy(session_entry->limReassocSSID.ssId, + reassoc_req->ssId.ssId, + session_entry->limReassocSSID.length); + if (session_entry->gLimCurrentBssUapsd) { + session_entry->gUapsdPerAcBitmask = + session_entry->pLimReAssocReq->uapsdPerAcBitmask; + lim_log(mac_ctx, LOG1, + FL("UAPSD flag for all AC - 0x%2x"), + session_entry->gUapsdPerAcBitmask); + } + + mlm_reassoc_req = cdf_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == mlm_reassoc_req) { + lim_log(mac_ctx, LOGP, + FL("call to AllocateMemory failed for mlmReassocReq")); + + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto end; + } + + cdf_mem_copy(mlm_reassoc_req->peerMacAddr, + session_entry->limReAssocbssId, sizeof(tSirMacAddr)); + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (uint32_t *)&mlm_reassoc_req->reassocFailureTimeout) != + eSIR_SUCCESS) { + /* + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve ReassocFailureTimeout value")); + } + + if (cfg_get_capability_info(mac_ctx, &caps, session_entry) != + eSIR_SUCCESS) { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, FL( + "could not retrieve Capabilities value")); + } + mlm_reassoc_req->capabilityInfo = caps; + + /* Update PE session_id */ + mlm_reassoc_req->sessionId = session_id; + + /* + * If telescopic beaconing is enabled, set listen interval to + * WNI_CFG_TELE_BCN_MAX_LI + */ + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_WAKEUP_EN, + &tele_bcn_en) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + + val = WNI_CFG_LISTEN_INTERVAL_STADEF; + + if (tele_bcn_en) { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_MAX_LI, &val) != + eSIR_SUCCESS) + /* + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve ListenInterval")); + } else { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL, &val) != + eSIR_SUCCESS) + /* + * Could not get ListenInterval value + * from CFG. Log error. + */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve ListenInterval")); + } + + mlm_reassoc_req->listenInterval = (uint16_t) val; + + /* Indicate whether spectrum management is enabled */ + session_entry->spectrumMgtEnabled = reassoc_req->spectrumMgtIndicator; + + /* Enable the spectrum management if this is a DFS channel */ + if (session_entry->country_info_present && + lim_isconnected_on_dfs_channel( + session_entry->currentOperChannel)) + session_entry->spectrumMgtEnabled = true; + + session_entry->limPrevSmeState = session_entry->limSmeState; + session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->limSmeState)); + + lim_post_mlm_message(mac_ctx, + LIM_MLM_REASSOC_REQ, (uint32_t *)mlm_reassoc_req); + return; +end: + if (reassoc_req) { + cdf_mem_free(reassoc_req); + if (session_entry) + session_entry->pLimReAssocReq = NULL; + } + + if (session_entry) { + /* + * error occurred after we determined the session so extract + * session and transaction info from there + */ + sme_session_id = session_entry->smeSessionId; + transaction_id = session_entry->transactionId; + } else + /* + * error occurred before or during the time we determined + * the session so extract the session and transaction info + * from the message + */ + lim_get_session_info(mac_ctx, (uint8_t *) msg_buf, + &sme_session_id, &transaction_id); + + /* + * Send Reassoc failure response to host + * (note session_entry may be NULL, but that's OK) + */ + lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, + ret_code, eSIR_MAC_UNSPEC_FAILURE_STATUS, + session_entry, sme_session_id, + transaction_id); +} + +bool send_disassoc_frame = 1; +/** + * __lim_process_sme_disassoc_req() + * + ***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 __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + uint16_t disassocTrigger, reasonCode; + tLimMlmDisassocReq *pMlmDisassocReq; + tSirResultCodes retCode = eSIR_SME_SUCCESS; + tSirSmeDisassocReq smeDisassocReq; + tpPESession psessionEntry = NULL; + uint8_t sessionId; + uint8_t smesessionId; + uint16_t smetransactionId; + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + cdf_mem_copy(&smeDisassocReq, pMsgBuf, sizeof(tSirSmeDisassocReq)); + smesessionId = smeDisassocReq.sessionId; + smetransactionId = smeDisassocReq.transactionId; + if (!lim_is_sme_disassoc_req_valid(pMac, + &smeDisassocReq, + psessionEntry)) { + PELOGE(lim_log(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; + } + + psessionEntry = pe_find_session_by_bssid(pMac, + smeDisassocReq.bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(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; + } + lim_log(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 */ + lim_diag_event_report(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: + psessionEntry->limPrevSmeState = + psessionEntry->limSmeState; + psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE; +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS */ + lim_delete_tdls_peers(pMac, psessionEntry); +#endif + MTRACE(mac_trace + (pMac, TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); + lim_log(pMac, LOG1, + FL("Rcvd SME_DISASSOC_REQ while in limSmeState: %d "), + 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(mac_trace + (pMac, TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); + lim_log(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. + */ + lim_log(pMac, LOG1, + FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. ")); + break; + + case eLIM_SME_JOIN_FAILURE_STATE: { + /* Already in Disconnected State, return success */ + lim_log(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 + */ + lim_log(pMac, LOGE, + FL("received unexpected SME_DISASSOC_REQ in state %X"), + psessionEntry->limSmeState); + lim_print_sme_state(pMac, LOGE, + 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 */ + lim_log(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) */ + + if (smeDisassocReq.reasonCode == eLIM_LINK_MONITORING_DISASSOC) { + /* / Disassociation is triggered by Link Monitoring */ + lim_log(pMac, LOG1, + FL("Sending Disasscoc with reason Link Monitoring")); + disassocTrigger = eLIM_LINK_MONITORING_DISASSOC; + reasonCode = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + } else { + disassocTrigger = eLIM_HOST_DISASSOC; + reasonCode = smeDisassocReq.reasonCode; + } + + if (smeDisassocReq.doNotSendOverTheAir) { + lim_log(pMac, LOG1, FL("do not send dissoc over the air")); + send_disassoc_frame = 0; + } + /* Trigger Disassociation frame to peer MAC entity */ + lim_log(pMac, LOG1, FL("Sending Disasscoc with disassoc Trigger" + " : %d, reasonCode : %d"), + disassocTrigger, reasonCode); + + pMlmDisassocReq = cdf_mem_malloc(sizeof(tLimMlmDisassocReq)); + if (NULL == pMlmDisassocReq) { + /* Log error */ + lim_log(pMac, LOGP, + FL("call to AllocateMemory failed for mlmDisassocReq")); + + return; + } + + cdf_mem_copy((uint8_t *) &pMlmDisassocReq->peerMacAddr, + (uint8_t *) &smeDisassocReq.peerMacAddr, + sizeof(tSirMacAddr)); + + pMlmDisassocReq->reasonCode = reasonCode; + pMlmDisassocReq->disassocTrigger = disassocTrigger; + + /* Update PE session ID */ + pMlmDisassocReq->sessionId = sessionId; + + lim_post_mlm_message(pMac, + LIM_MLM_DISASSOC_REQ, (uint32_t *) pMlmDisassocReq); + return; + +sendDisassoc: + if (psessionEntry) + lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr, + retCode, + disassocTrigger, + 1, smesessionId, smetransactionId, + psessionEntry); + else + lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr, + retCode, + disassocTrigger, + 1, smesessionId, smetransactionId, NULL); + +} /*** end __lim_process_sme_disassoc_req() ***/ + +/** ----------------------------------------------------------------- + \brief __lim_process_sme_disassoc_cnf() - 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 __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirSmeDisassocCnf smeDisassocCnf; + uint16_t aid; + tpDphHashNode pStaDs; + tpPESession psessionEntry; + uint8_t sessionId; + + PELOG1(lim_log(pMac, LOG1, FL("received DISASSOC_CNF message"));) + + cdf_mem_copy(&smeDisassocCnf, pMsgBuf, + sizeof(struct sSirSmeDisassocCnf)); + + psessionEntry = pe_find_session_by_bssid(pMac, + smeDisassocCnf.bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("session does not exist for given bssId")); + return; + } + + if (!lim_is_sme_disassoc_cnf_valid(pMac, &smeDisassocCnf, psessionEntry)) { + lim_log(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) + lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT, + psessionEntry, + (uint16_t) smeDisassocCnf.statusCode, 0); + else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF) + lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT, + psessionEntry, + (uint16_t) 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)) { + lim_log(pMac, LOGE, + FL + ("received unexp SME_DISASSOC_CNF in state %X"), + psessionEntry->limSmeState); + lim_print_sme_state(pMac, LOGE, + psessionEntry->limSmeState); + return; + } + break; + + case eLIM_AP_ROLE: + /* Fall through */ + break; + + case eLIM_STA_IN_IBSS_ROLE: + default: /* eLIM_UNKNOWN_ROLE */ + lim_log(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 = dph_lookup_hash_entry(pMac, + smeDisassocCnf.peerMacAddr, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + lim_log(pMac, LOGE, + FL("DISASSOC_CNF for a STA with no context, addr= " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr)); + return; + } +#if defined WLAN_FEATURE_VOWIFI_11R + /* Delete FT session if there exists one */ + lim_ft_cleanup_pre_auth_info(pMac, psessionEntry); +#endif + lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); + + lim_clean_up_disassoc_deauth_req(pMac, + (char *)&smeDisassocCnf.peerMacAddr, + 0); + } + + return; +} + +/** + * __lim_process_sme_deauth_req() - process sme deauth req + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process SME_DEAUTH_REQ message + * from HDD or upper layer application. + * + * Return: None + */ + +static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + uint16_t deauth_trigger, reason_code; + tLimMlmDeauthReq *mlm_deauth_req; + tSirSmeDeauthReq sme_deauth_req; + tSirResultCodes ret_code = eSIR_SME_SUCCESS; + tpPESession session_entry; + uint8_t session_id; /* PE sessionId */ + uint8_t sme_session_id; + uint16_t sme_transaction_id; + + lim_log(mac_ctx, LOG1, FL("received DEAUTH_REQ message")); + + cdf_mem_copy(&sme_deauth_req, msg_buf, sizeof(tSirSmeDeauthReq)); + sme_session_id = sme_deauth_req.sessionId; + sme_transaction_id = sme_deauth_req.transactionId; + + /* + * We need to get a session first but we don't even know + * if the message is correct. + */ + session_entry = pe_find_session_by_bssid(mac_ctx, sme_deauth_req.bssId, + &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given bssId")); + ret_code = eSIR_SME_INVALID_PARAMETERS; + deauth_trigger = eLIM_HOST_DEAUTH; + goto send_deauth; + } + + if (!lim_is_sme_deauth_req_valid(mac_ctx, &sme_deauth_req, + session_entry)) { + lim_log(mac_ctx, LOGE, + FL("received invalid SME_DEAUTH_REQ message")); + mac_ctx->lim.gLimRspReqd = false; + + ret_code = eSIR_SME_INVALID_PARAMETERS; + deauth_trigger = eLIM_HOST_DEAUTH; + goto send_deauth; + } + lim_log(mac_ctx, LOG1, + FL("received DEAUTH_REQ sessionid %d Systemrole %d reasoncode %u limSmestate %d from " + MAC_ADDRESS_STR), sme_session_id, + GET_LIM_SYSTEM_ROLE(session_entry), sme_deauth_req.reasonCode, + session_entry->limSmeState, + MAC_ADDR_ARRAY(sme_deauth_req.peerMacAddr)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, + session_entry, 0, sme_deauth_req.reasonCode); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + /* Update SME session ID and Transaction ID */ + session_entry->smeSessionId = sme_session_id; + session_entry->transactionId = sme_transaction_id; + + switch (GET_LIM_SYSTEM_ROLE(session_entry)) { + case eLIM_STA_ROLE: + case eLIM_BT_AMP_STA_ROLE: + + switch (session_entry->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: + session_entry->limPrevSmeState = + session_entry->limSmeState; + session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; + MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, + session_entry->peSessionId, + session_entry->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 get + * 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. + */ + session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; + lim_log(mac_ctx, 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. + */ + lim_log(mac_ctx, LOGE, FL( + "received unexp SME_DEAUTH_REQ in state %X"), + session_entry->limSmeState); + lim_print_sme_state(mac_ctx, LOGE, + session_entry->limSmeState); + + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + + ret_code = eSIR_SME_STA_NOT_AUTHENTICATED; + deauth_trigger = 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 ifwe 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 (session_entry->limSmeState == + eLIM_SME_WT_DEAUTH_STATE && + session_entry->limMlmState != + eLIM_MLM_IDLE_STATE && + session_entry->limMlmState != + eLIM_MLM_WT_DEL_STA_RSP_STATE) + ret_code = eSIR_SME_DEAUTH_STATUS; + goto send_deauth; + } + return; + } + break; + + case eLIM_STA_IN_IBSS_ROLE: + lim_log(mac_ctx, LOGE, FL("Deauth not allowed in IBSS")); + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + ret_code = eSIR_SME_INVALID_PARAMETERS; + deauth_trigger = eLIM_HOST_DEAUTH; + goto send_deauth; + } + return; + case eLIM_AP_ROLE: + break; + default: + lim_log(mac_ctx, LOGE, + FL("received unexpected SME_DEAUTH_REQ for role %X"), + GET_LIM_SYSTEM_ROLE(session_entry)); + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + ret_code = eSIR_SME_INVALID_PARAMETERS; + deauth_trigger = eLIM_HOST_DEAUTH; + goto send_deauth; + } + return; + } /* end switch (mac_ctx->lim.gLimSystemRole) */ + + if (sme_deauth_req.reasonCode == eLIM_LINK_MONITORING_DEAUTH) { + /* Deauthentication is triggered by Link Monitoring */ + lim_log(mac_ctx, LOG1, FL("** Lost link with AP **")); + deauth_trigger = eLIM_LINK_MONITORING_DEAUTH; + reason_code = eSIR_MAC_UNSPEC_FAILURE_REASON; + } else { + deauth_trigger = eLIM_HOST_DEAUTH; + reason_code = sme_deauth_req.reasonCode; + } + + /* Trigger Deauthentication frame to peer MAC entity */ + mlm_deauth_req = cdf_mem_malloc(sizeof(tLimMlmDeauthReq)); + if (NULL == mlm_deauth_req) { + lim_log(mac_ctx, LOGP, + FL("call to AllocateMemory failed for mlmDeauthReq")); + if (mac_ctx->lim.gLimRspReqd) { + mac_ctx->lim.gLimRspReqd = false; + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + deauth_trigger = eLIM_HOST_DEAUTH; + goto send_deauth; + } + return; + } + + cdf_mem_copy((uint8_t *) &mlm_deauth_req->peerMacAddr, + (uint8_t *) &sme_deauth_req.peerMacAddr, + sizeof(tSirMacAddr)); + + mlm_deauth_req->reasonCode = reason_code; + mlm_deauth_req->deauthTrigger = deauth_trigger; + + /* Update PE session Id */ + mlm_deauth_req->sessionId = session_id; + + lim_post_mlm_message(mac_ctx, LIM_MLM_DEAUTH_REQ, + (uint32_t *)mlm_deauth_req); + return; + +send_deauth: + lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peerMacAddr, ret_code, + deauth_trigger, 1, sme_session_id, sme_transaction_id); +} + +/** + * __lim_process_sme_set_context_req() + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process SME_SETCONTEXT_REQ message + * from HDD or upper layer application. + * + * Return: None + */ + +static void +__lim_process_sme_set_context_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + tpSirSmeSetContextReq set_context_req; + tLimMlmSetKeysReq *mlm_set_key_req; + tpPESession session_entry; + uint8_t session_id; /* PE sessionID */ + uint8_t sme_session_id; + uint16_t sme_transaction_id; + + lim_log(mac_ctx, LOG1, FL("received SETCONTEXT_REQ message")); + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + set_context_req = cdf_mem_malloc(sizeof(struct sSirSmeSetContextReq)); + if (NULL == set_context_req) { + lim_log(mac_ctx, LOGP, FL( + "call to AllocateMemory failed for set_context_req")); + return; + } + cdf_mem_copy(set_context_req, msg_buf, + sizeof(struct sSirSmeSetContextReq)); + sme_session_id = set_context_req->sessionId; + sme_transaction_id = set_context_req->transactionId; + + if ((!lim_is_sme_set_context_req_valid(mac_ctx, set_context_req))) { + lim_log(mac_ctx, LOGW, + FL("received invalid SME_SETCONTEXT_REQ message")); + goto end; + } + + if (set_context_req->keyMaterial.numKeys > + SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { + lim_log(mac_ctx, LOGE, FL( + "numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), + set_context_req->keyMaterial.numKeys); + lim_send_sme_set_context_rsp(mac_ctx, + set_context_req->peerMacAddr, 1, + eSIR_SME_INVALID_PARAMETERS, NULL, + sme_session_id, sme_transaction_id); + goto end; + } + + session_entry = pe_find_session_by_bssid(mac_ctx, + set_context_req->bssId, &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGW, + FL("Session does not exist for given BSSID")); + lim_send_sme_set_context_rsp(mac_ctx, + set_context_req->peerMacAddr, 1, + eSIR_SME_INVALID_PARAMETERS, NULL, + sme_session_id, sme_transaction_id); + goto end; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT, + session_entry, 0, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + if (((LIM_IS_STA_ROLE(session_entry) || + LIM_IS_BT_AMP_STA_ROLE(session_entry)) && + (session_entry->limSmeState == eLIM_SME_LINK_EST_STATE)) || + ((LIM_IS_IBSS_ROLE(session_entry) || + LIM_IS_AP_ROLE(session_entry) || + LIM_IS_BT_AMP_AP_ROLE(session_entry)) && + (session_entry->limSmeState == eLIM_SME_NORMAL_STATE))) { + /* Trigger MLM_SETKEYS_REQ */ + mlm_set_key_req = cdf_mem_malloc(sizeof(tLimMlmSetKeysReq)); + if (NULL == mlm_set_key_req) { + lim_log(mac_ctx, LOGP, FL( + "mem alloc failed for mlmSetKeysReq")); + goto end; + } + mlm_set_key_req->edType = set_context_req->keyMaterial.edType; + mlm_set_key_req->numKeys = + set_context_req->keyMaterial.numKeys; + if (mlm_set_key_req->numKeys > + SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { + lim_log(mac_ctx, LOGP, FL( + "no.of keys exceeded max num of default keys limit")); + goto end; + } + cdf_mem_copy((uint8_t *) &mlm_set_key_req->peerMacAddr, + (uint8_t *) &set_context_req->peerMacAddr, + sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) &mlm_set_key_req->key, + (uint8_t *) &set_context_req->keyMaterial.key, + sizeof(tSirKeys) * + (mlm_set_key_req->numKeys ? mlm_set_key_req-> + numKeys : 1)); + + mlm_set_key_req->sessionId = session_id; + mlm_set_key_req->smesessionId = sme_session_id; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL( + "received SETCONTEXT_REQ message sessionId=%d"), + mlm_set_key_req->sessionId); +#endif + + if (((set_context_req->keyMaterial.edType == eSIR_ED_WEP40) || + (set_context_req->keyMaterial.edType == eSIR_ED_WEP104)) && + LIM_IS_AP_ROLE(session_entry)) { + if (set_context_req->keyMaterial.key[0].keyLength) { + uint8_t key_id; + key_id = + set_context_req->keyMaterial.key[0].keyId; + cdf_mem_copy((uint8_t *) + &session_entry->WEPKeyMaterial[key_id], + (uint8_t *) &set_context_req->keyMaterial, + sizeof(tSirKeyMaterial)); + } else { + uint32_t i; + for (i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + i++) { + cdf_mem_copy((uint8_t *) + &mlm_set_key_req->key[i], + (uint8_t *)session_entry->WEPKeyMaterial[i].key, + sizeof(tSirKeys)); + } + } + } + lim_post_mlm_message(mac_ctx, LIM_MLM_SETKEYS_REQ, + (uint32_t *) mlm_set_key_req); + } else { + lim_log(mac_ctx, LOGE, FL( + "rcvd unexpected SME_SETCONTEXT_REQ for role %d, state=%X"), + GET_LIM_SYSTEM_ROLE(session_entry), + session_entry->limSmeState); + lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState); + + lim_send_sme_set_context_rsp(mac_ctx, + set_context_req->peerMacAddr, 1, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, + session_entry, sme_session_id, + sme_transaction_id); + } +end: + cdf_mem_free(set_context_req); + return; +} + +/** + * lim_process_sme_get_assoc_sta_info() - process sme assoc sta req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process SME_GET_ASSOC_STAS_REQ message + * from HDD or upper layer application. + * + * Return: None + */ + +void lim_process_sme_get_assoc_sta_info(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tSirSmeGetAssocSTAsReq get_assoc_stas_req; + tpDphHashNode sta_ds = NULL; + tpPESession session_entry = NULL; + tSap_Event sap_event; + tpWLAN_SAPEventCB sap_event_cb = NULL; + tpSap_AssocMacAddr assoc_sta_tmp = NULL; + uint8_t session_id = CSR_SESSION_ID_INVALID; + uint8_t assoc_id = 0; + uint8_t sta_cnt = 0; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + cdf_mem_copy(&get_assoc_stas_req, msg_buf, + sizeof(struct sSirSmeGetAssocSTAsReq)); + /* + * Get Associated stations from PE. + * Find PE session Entry + */ + session_entry = pe_find_session_by_bssid(mac_ctx, + get_assoc_stas_req.bssId, + &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given bssId")); + goto lim_assoc_sta_end; + } + + if (!LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOGE, FL( + "Received unexpected message in state %X, in role %X"), + session_entry->limSmeState, + GET_LIM_SYSTEM_ROLE(session_entry)); + goto lim_assoc_sta_end; + } + /* Retrieve values obtained in the request message */ + sap_event_cb = (tpWLAN_SAPEventCB)get_assoc_stas_req.pSapEventCallback; + assoc_sta_tmp = (tpSap_AssocMacAddr)get_assoc_stas_req.pAssocStasArray; + + if (NULL == assoc_sta_tmp) + goto lim_assoc_sta_end; + for (assoc_id = 0; assoc_id < session_entry->dph.dphHashTable.size; + assoc_id++) { + sta_ds = dph_get_hash_entry(mac_ctx, assoc_id, + &session_entry->dph.dphHashTable); + if (NULL == sta_ds) + continue; + if (sta_ds->valid) { + cdf_mem_copy((uint8_t *) &assoc_sta_tmp->staMac, + (uint8_t *) &sta_ds->staAddr, + CDF_MAC_ADDR_SIZE); + assoc_sta_tmp->assocId = (uint8_t) sta_ds->assocId; + assoc_sta_tmp->staId = (uint8_t) sta_ds->staIndex; + + cdf_mem_copy((uint8_t *)&assoc_sta_tmp->supportedRates, + (uint8_t *)&sta_ds->supportedRates, + sizeof(tSirSupportedRates)); + assoc_sta_tmp->ShortGI40Mhz = sta_ds->htShortGI40Mhz; + assoc_sta_tmp->ShortGI20Mhz = sta_ds->htShortGI20Mhz; + assoc_sta_tmp->Support40Mhz = + sta_ds->htDsssCckRate40MHzSupport; + + lim_log(mac_ctx, LOG1, FL("dph Station Number = %d"), + sta_cnt + 1); + lim_log(mac_ctx, LOG1, FL("MAC = " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(sta_ds->staAddr)); + lim_log(mac_ctx, LOG1, FL("Association Id = %d"), + sta_ds->assocId); + lim_log(mac_ctx, LOG1, FL("Station Index = %d"), + sta_ds->staIndex); + assoc_sta_tmp++; + sta_cnt++; + } + } +lim_assoc_sta_end: + /* + * Call hdd callback with sap event to send the list of + * associated stations from PE + */ + if (sap_event_cb != NULL) { + sap_event.sapHddEventCode = eSAP_ASSOC_STA_CALLBACK_EVENT; + sap_event.sapevt.sapAssocStaListEvent.module = + CDF_MODULE_ID_PE; + sap_event.sapevt.sapAssocStaListEvent.noOfAssocSta = sta_cnt; + sap_event.sapevt.sapAssocStaListEvent.pAssocStas = + (tpSap_AssocMacAddr)get_assoc_stas_req.pAssocStasArray; + sap_event_cb(&sap_event, get_assoc_stas_req.pUsrContext); + } +} + +/** + * lim_process_sme_get_wpspbc_sessions - process sme get wpspbc req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to WPS PBC overlap query message + * + * This function parses get WPS PBC overlap information + * message and call callback to pass WPS PBC overlap + * information back to hdd. + * + * Return: None + */ +void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tSirSmeGetWPSPBCSessionsReq get_wps_pbc_sessions_req; + tpPESession session_entry = NULL; + tSap_Event sap_event; + tpWLAN_SAPEventCB sap_event_cb = NULL; + uint8_t session_id = CSR_SESSION_ID_INVALID; + tSirMacAddr zero_mac = { 0, 0, 0, 0, 0, 0 }; + tSap_GetWPSPBCSessionEvent *sap_get_wpspbc_event; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + sap_get_wpspbc_event = &sap_event.sapevt.sapGetWPSPBCSessionEvent; + sap_get_wpspbc_event->status = CDF_STATUS_E_FAULT; + + cdf_mem_copy(&get_wps_pbc_sessions_req, msg_buf, + sizeof(struct sSirSmeGetWPSPBCSessionsReq)); + /* + * Get Associated stations from PE + * Find PE session Entry + */ + session_entry = pe_find_session_by_bssid(mac_ctx, + get_wps_pbc_sessions_req.bssId, &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given bssId")); + goto lim_get_wpspbc_sessions_end; + } + + if (!LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOGE, + FL("Received unexpected message in role %X"), + GET_LIM_SYSTEM_ROLE(session_entry)); + goto lim_get_wpspbc_sessions_end; + } + /* + * Call hdd callback with sap event to send the + * WPS PBC overlap information + */ + sap_event.sapHddEventCode = eSAP_GET_WPSPBC_SESSION_EVENT; + sap_get_wpspbc_event->module = CDF_MODULE_ID_PE; + + if (cdf_mem_compare(zero_mac, get_wps_pbc_sessions_req.pRemoveMac, + sizeof(tSirMacAddr))) { + lim_get_wpspbc_sessions(mac_ctx, + sap_get_wpspbc_event->addr.bytes, + sap_get_wpspbc_event->UUID_E, + &sap_get_wpspbc_event->wpsPBCOverlap, + session_entry); + } else { + lim_remove_pbc_sessions(mac_ctx, + get_wps_pbc_sessions_req.pRemoveMac, + session_entry); + /* don't have to inform the HDD/Host */ + return; + } + + lim_log(mac_ctx, LOGE, FL("wpsPBCOverlap %d"), + sap_get_wpspbc_event->wpsPBCOverlap); + lim_print_mac_addr(mac_ctx, + sap_get_wpspbc_event->addr.bytes, LOG4); + + sap_get_wpspbc_event->status = CDF_STATUS_SUCCESS; + +lim_get_wpspbc_sessions_end: + sap_event_cb = + (tpWLAN_SAPEventCB)get_wps_pbc_sessions_req.pSapEventCallback; + if (NULL != sap_event_cb) + sap_event_cb(&sap_event, get_wps_pbc_sessions_req.pUsrContext); +} + +/** + * __lim_counter_measures() + * + * 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 __lim_counter_measures(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)) + lim_send_disassoc_mgmt_frame(pMac, eSIR_MAC_MIC_FAILURE_REASON, + mac, psessionEntry, false); +}; + +void lim_process_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirSmeTkipCntrMeasReq tkipCntrMeasReq; + tpPESession psessionEntry; + uint8_t sessionId; /* PE sessionId */ + + cdf_mem_copy(&tkipCntrMeasReq, pMsgBuf, + sizeof(struct sSirSmeTkipCntrMeasReq)); + + psessionEntry = pe_find_session_by_bssid(pMac, + tkipCntrMeasReq.bssId, + &sessionId); + if (NULL == psessionEntry) { + lim_log(pMac, LOGE, + FL("session does not exist for given BSSID ")); + return; + } + + if (tkipCntrMeasReq.bEnable) + __lim_counter_measures(pMac, psessionEntry); + + psessionEntry->bTkipCntrMeasActive = tkipCntrMeasReq.bEnable; +} + +static void +__lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirSmeStopBssReq stopBssReq; + tSirRetStatus status; + tLimSmeStates prevState; + tpPESession psessionEntry; + uint8_t smesessionId; + uint8_t sessionId; + uint16_t smetransactionId; + uint8_t i = 0; + tpDphHashNode pStaDs = NULL; + + cdf_mem_copy(&stopBssReq, pMsgBuf, sizeof(tSirSmeStopBssReq)); + smesessionId = stopBssReq.sessionId; + smetransactionId = stopBssReq.transactionId; + + if (!lim_is_sme_stop_bss_req_valid(pMsgBuf)) { + PELOGW(lim_log(pMac, LOGW, + FL("received invalid SME_STOP_BSS_REQ message"));) + /* Send Stop BSS response to host */ + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, + eSIR_SME_INVALID_PARAMETERS, smesessionId, + smetransactionId); + return; + } + + psessionEntry = pe_find_session_by_bssid(pMac, + stopBssReq.bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGW, + FL("session does not exist for given BSSID ")); + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, + eSIR_SME_INVALID_PARAMETERS, smesessionId, + smetransactionId); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(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. + */ + lim_log(pMac, LOGE, + FL + ("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"), + psessionEntry->limSmeState, + GET_LIM_SYSTEM_ROLE(psessionEntry)); + lim_print_sme_state(pMac, LOGE, psessionEntry->limSmeState); + /* / Send Stop BSS response to host */ + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, + eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, smesessionId, + smetransactionId); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry)) + lim_wpspbc_close(pMac, psessionEntry); + + lim_log(pMac, LOGW, + FL("RECEIVED STOP_BSS_REQ with reason code=%d"), + stopBssReq.reasonCode); + + prevState = psessionEntry->limSmeState; + + psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; + MTRACE(mac_trace + (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 */ + __lim_counter_measures(pMac, psessionEntry); + else + lim_send_disassoc_mgmt_frame(pMac, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + bcAddr, psessionEntry, false); + } + + /* Free the buffer allocated in START_BSS_REQ */ + cdf_mem_free(psessionEntry->addIeParams.probeRespData_buff); + psessionEntry->addIeParams.probeRespDataLen = 0; + psessionEntry->addIeParams.probeRespData_buff = NULL; + + cdf_mem_free(psessionEntry->addIeParams.assocRespData_buff); + psessionEntry->addIeParams.assocRespDataLen = 0; + psessionEntry->addIeParams.assocRespData_buff = NULL; + + cdf_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); + psessionEntry->addIeParams.probeRespBCNDataLen = 0; + psessionEntry->addIeParams.probeRespBCNData_buff = NULL; + + /* lim_del_bss 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 = + dph_get_hash_entry(pMac, i, &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + continue; + status = lim_del_sta(pMac, pStaDs, false, psessionEntry); + if (eSIR_SUCCESS == status) { + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, + pStaDs->assocId, psessionEntry); + lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry); + } else { + lim_log(pMac, LOGE, + FL("lim_del_sta failed with Status : %d"), status); + CDF_ASSERT(0); + } + } + /* send a delBss to HAL and wait for a response */ + status = lim_del_bss(pMac, NULL, psessionEntry->bssIdx, psessionEntry); + + if (status != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("delBss failed for bss %d"), + psessionEntry->bssIdx); + ) + psessionEntry->limSmeState = prevState; + + MTRACE(mac_trace + (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, + psessionEntry->limSmeState)); + + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, + eSIR_SME_STOP_BSS_FAILURE, smesessionId, + smetransactionId); + } +} + +/** + * __lim_process_sme_stop_bss_req() - Process STOP_BSS from SME + * @pMac: Global MAC context + * @pMsg: Message from SME + * + * Wrapper for the function __lim_handle_sme_stop_bss_request + * 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. + * + * Return: true - If we consumed the buffer + * false - If have defered the message. + */ + +static bool __lim_process_sme_stop_bss_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + if (__lim_is_defered_msg_for_learn(pMac, pMsg)) { + /** + * If message defered, buffer is not consumed yet. + * So return false + */ + return false; + } + __lim_handle_sme_stop_bss_request(pMac, (uint32_t *) pMsg->bodyptr); + return true; +} /*** end __lim_process_sme_stop_bss_req() ***/ + +void lim_process_sme_del_bss_rsp(tpAniSirGlobal pMac, + uint32_t body, tpPESession psessionEntry) +{ + + (void)body; + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + lim_ibss_delete(pMac, psessionEntry); + dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable); + lim_delete_pre_auth_list(pMac); + lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_SUCCESS, + psessionEntry->smeSessionId, + psessionEntry->transactionId); + return; +} + +/** + * __lim_process_sme_assoc_cnf_new() - process sme assoc/reassoc cnf + * + * @mac_ctx: pointer to mac context + * @msg_type: message type + * @msg_buf: pointer to the SME message buffer + * + * This function handles SME_ASSOC_CNF/SME_REASSOC_CNF + * in BTAMP AP. + * + * Return: None + */ + +void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, + uint32_t *msg_buf) +{ + tSirSmeAssocCnf assoc_cnf; + tpDphHashNode sta_ds = NULL; + tpPESession session_entry = NULL; + uint8_t session_id; + tpSirAssocReq assoc_req; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("msg_buf is NULL ")); + goto end; + } + + cdf_mem_copy(&assoc_cnf, msg_buf, sizeof(struct sSirSmeAssocCnf)); + if (!__lim_is_sme_assoc_cnf_valid(&assoc_cnf)) { + lim_log(mac_ctx, LOGE, + FL("Received invalid SME_RE(ASSOC)_CNF message ")); + goto end; + } + + session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssId, + &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("session does not exist for given bssId")); + goto end; + } + + if ((!LIM_IS_AP_ROLE(session_entry) && + !LIM_IS_BT_AMP_AP_ROLE(session_entry)) || + ((session_entry->limSmeState != eLIM_SME_NORMAL_STATE) && + (session_entry->limSmeState != + eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { + lim_log(mac_ctx, LOGE, FL( + "Rcvd unexpected msg %X in state %X, in role %X"), + msg_type, session_entry->limSmeState, + GET_LIM_SYSTEM_ROLE(session_entry)); + goto end; + } + sta_ds = dph_get_hash_entry(mac_ctx, assoc_cnf.aid, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, FL( + "Rcvd invalid msg %X due to no STA ctx, aid %d, peer "), + msg_type, assoc_cnf.aid); + lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + + /* + * send a DISASSOC_IND message to WSM to make sure + * the state in WSM and LIM is the same + */ + lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peerMacAddr, + eSIR_SME_STA_NOT_ASSOCIATED, + eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid, + session_entry->smeSessionId, + session_entry->transactionId, + session_entry); + goto end; + } + if (!cdf_mem_compare((uint8_t *)sta_ds->staAddr, + (uint8_t *) assoc_cnf.peerMacAddr, + sizeof(tSirMacAddr))) { + lim_log(mac_ctx, LOG1, FL( + "peerMacAddr mismatched for aid %d, peer "), + assoc_cnf.aid); + lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + goto end; + } + + if ((sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) || + ((sta_ds->mlmStaContext.subType == LIM_ASSOC) && + (msg_type != eWNI_SME_ASSOC_CNF)) || + ((sta_ds->mlmStaContext.subType == LIM_REASSOC) && + (msg_type != eWNI_SME_ASSOC_CNF))) { + lim_log(mac_ctx, LOG1, FL( + "not in MLM_WT_ASSOC_CNF_STATE, for aid %d, peer" + "StaD mlmState : %d"), + assoc_cnf.aid, sta_ds->mlmStaContext.mlmState); + lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + goto end; + } + /* + * Deactivate/delet CNF_WAIT timer since ASSOC_CNF + * has been received + */ + lim_log(mac_ctx, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); + lim_deactivate_and_change_per_sta_id_timer(mac_ctx, + eLIM_CNF_WAIT_TIMER, sta_ds->assocId); + + if (assoc_cnf.statusCode == eSIR_SME_SUCCESS) { + /* + * In BTAMP-AP, PE already finished the WMA_ADD_STA sequence + * when it had received Assoc Request frame. Now, PE just needs + * to send association rsp frame to the requesting BTAMP-STA. + */ + sta_ds->mlmStaContext.mlmState = + eLIM_MLM_LINK_ESTABLISHED_STATE; + lim_log(mac_ctx, LOG1, + FL("sending Assoc Rsp frame to STA (assoc id=%d) "), + sta_ds->assocId); + lim_send_assoc_rsp_mgmt_frame(mac_ctx, eSIR_SUCCESS, + sta_ds->assocId, sta_ds->staAddr, + sta_ds->mlmStaContext.subType, sta_ds, + session_entry); + goto end; + } 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 (!sta_ds->mlmStaContext.updateContext) + sta_ds->mlmStaContext.updateContext = 1; + lim_log(mac_ctx, LOG1, + FL("Recv Assoc Cnf, status Code : %d(assoc id=%d) "), + assoc_cnf.statusCode, sta_ds->assocId); + lim_reject_association(mac_ctx, sta_ds->staAddr, + sta_ds->mlmStaContext.subType, + true, sta_ds->mlmStaContext.authType, + sta_ds->assocId, true, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + session_entry); + } +end: + if (((session_entry != NULL) && (sta_ds != NULL)) && + (session_entry->parsedAssocReq[sta_ds->assocId] != NULL)) { + assoc_req = (tpSirAssocReq) + session_entry->parsedAssocReq[sta_ds->assocId]; + if (assoc_req->assocReqFrame) { + cdf_mem_free(assoc_req->assocReqFrame); + assoc_req->assocReqFrame = NULL; + } + cdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]); + session_entry->parsedAssocReq[sta_ds->assocId] = NULL; + } +} + +static void __lim_process_sme_addts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpDphHashNode pStaDs; + tSirMacAddr peerMac; + tpSirAddtsReq pSirAddts; + uint32_t timeout; + tpPESession psessionEntry; + uint8_t sessionId; /* PE sessionId */ + uint8_t smesessionId; + uint16_t smetransactionId; + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smesessionId, + &smetransactionId); + + pSirAddts = (tpSirAddtsReq) pMsgBuf; + + psessionEntry = pe_find_session_by_bssid(pMac, + pSirAddts->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, "Session Does not exist for given bssId"); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(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(lim_log(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(lim_log(pMac, LOGE, "AddTs received on AP - ignoring");) + lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, + psessionEntry, pSirAddts->req.tspec, + smesessionId, smetransactionId); + return; + } + /* Ignore the request if STA is in 11B mode. */ + if (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) { + PELOGE(lim_log + (pMac, LOGE, + "AddTS received while Dot11Mode is 11B - ignoring"); + ) + lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, + psessionEntry, pSirAddts->req.tspec, + smesessionId, smetransactionId); + return; + } + + pStaDs = + dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + + if (pStaDs == NULL) { + PELOGE(lim_log + (pMac, LOGE, "Cannot find AP context for addts req"); + ) + lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, + psessionEntry, pSirAddts->req.tspec, + smesessionId, smetransactionId); + return; + } + + if ((!pStaDs->valid) || (pStaDs->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE)) { + lim_log(pMac, LOGE, "AddTs received in invalid MLM state"); + lim_send_sme_addts_rsp(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(lim_log + (pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled")); + ) + lim_send_sme_addts_rsp(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)) { + lim_log(pMac, LOGE, + "AddTs received in invalid LIMsme state (%d)", + psessionEntry->limSmeState); + lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, + psessionEntry, pSirAddts->req.tspec, + smesessionId, smetransactionId); + return; + } + + if (pMac->lim.gLimAddtsSent) { + lim_log(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); + lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, + psessionEntry, pSirAddts->req.tspec, + smesessionId, smetransactionId); + return; + } + + sir_copy_mac_addr(peerMac, psessionEntry->bssId); + + /* save the addts request */ + pMac->lim.gLimAddtsSent = true; + cdf_mem_copy((uint8_t *) &pMac->lim.gLimAddtsReq, + (uint8_t *) pSirAddts, sizeof(tSirAddtsReq)); + + /* ship out the message now */ + lim_send_addts_req_action_frame(pMac, peerMac, &pSirAddts->req, + psessionEntry); + PELOG1(lim_log(pMac, LOG1, "Sent ADDTS request");) + /* start a timer to wait for the response */ + if (pSirAddts->timeout) + timeout = pSirAddts->timeout; + else if (wlan_cfg_get_int(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) != + eSIR_SUCCESS) { + lim_log(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) { + lim_log(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) { + lim_log(pMac, LOGP, FL("AddtsRsp timer change failed!")); + return; + } + MTRACE(mac_trace + (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) { + lim_log(pMac, LOGP, FL("AddtsRsp timer activation failed!")); + return; + } + return; +} + +static void __lim_process_sme_delts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirMacAddr peerMacAddr; + uint8_t ac; + tSirMacTSInfo *pTsinfo; + tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) pMsgBuf; + tpDphHashNode pStaDs = NULL; + tpPESession psessionEntry; + uint8_t sessionId; + uint32_t status = eSIR_SUCCESS; + uint8_t smesessionId; + uint16_t smetransactionId; + + lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smesessionId, + &smetransactionId); + + psessionEntry = pe_find_session_by_bssid(pMac, + pDeltsReq->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, "Session Does not exist for given bssId"); + status = eSIR_FAILURE; + goto end; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_REQ_EVENT, psessionEntry, 0, + 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + if (eSIR_SUCCESS != + lim_validate_delts_req(pMac, pDeltsReq, peerMacAddr, psessionEntry)) { + PELOGE(lim_log(pMac, LOGE, FL("lim_validate_delts_req failed"));) + status = eSIR_FAILURE; + lim_send_sme_delts_rsp(pMac, pDeltsReq, eSIR_FAILURE, psessionEntry, + smesessionId, smetransactionId); + return; + } + + lim_log(pMac, LOG1, + FL("Sent DELTS request to station with assocId = %d MacAddr = " + MAC_ADDRESS_STR), + pDeltsReq->aid, MAC_ADDR_ARRAY(peerMacAddr)); + + lim_send_delts_req_action_frame(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 + */ + lim_set_tspec_uapsd_mask_per_session(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); + } + + lim_set_active_edca_params(pMac, psessionEntry->gLimEdcaParams, + psessionEntry); + + pStaDs = + dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs != NULL) { + lim_send_edca_params(pMac, psessionEntry->gLimEdcaParamsActive, + pStaDs->bssId); + status = eSIR_SUCCESS; + } else { + lim_log(pMac, LOGE, FL("Self entry missing in Hash Table ")); + status = eSIR_FAILURE; + } +#ifdef FEATURE_WLAN_ESE +#ifdef FEATURE_WLAN_ESE_UPLOAD + lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); +#else + lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + + /* send an sme response back */ +end: + lim_send_sme_delts_rsp(pMac, pDeltsReq, eSIR_SUCCESS, psessionEntry, + smesessionId, smetransactionId); +} + +void lim_process_sme_addts_rsp_timeout(tpAniSirGlobal pMac, uint32_t param) +{ + /* fetch the sessionEntry based on the sessionId */ + tpPESession psessionEntry; + psessionEntry = pe_find_session_by_session_id(pMac, + pMac->lim.limTimers.gLimAddtsRspTimer. + sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } + + if (!LIM_IS_STA_ROLE(psessionEntry) && + !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + pMac->lim.gLimAddtsSent = false; + return; + } + + if (!pMac->lim.gLimAddtsSent) { + lim_log(pMac, LOGW, "AddtsRspTimeout but no AddtsSent"); + return; + } + + if (param != pMac->lim.gLimAddtsRspTimerCount) { + lim_log(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++; + + lim_send_sme_addts_rsp(pMac, true, eSIR_SME_ADDTS_RSP_TIMEOUT, + psessionEntry, pMac->lim.gLimAddtsReq.req.tspec, + psessionEntry->smeSessionId, + psessionEntry->transactionId); +} + +/** + * __lim_process_sme_get_statistics_request() + * + ***FUNCTION: + * + * + ***NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__lim_process_sme_get_statistics_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpAniGetPEStatsReq pPEStatsReq; + tSirMsgQ msgQ; + + pPEStatsReq = (tpAniGetPEStatsReq) pMsgBuf; + + msgQ.type = WMA_GET_STATISTICS_REQ; + + msgQ.reserved = 0; + msgQ.bodyptr = pMsgBuf; + msgQ.bodyval = 0; + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + + if (eSIR_SUCCESS != (wma_post_ctrl_msg(pMac, &msgQ))) { + cdf_mem_free(pMsgBuf); + pMsgBuf = NULL; + lim_log(pMac, LOGP, "Unable to forward request"); + return; + } + + return; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + *FUNCTION: __lim_process_sme_get_tsm_stats_request() + * + ***NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param *pMsgBuf A pointer to the SME message buffer + * @return None + */ +static void +__lim_process_sme_get_tsm_stats_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tSirMsgQ msgQ; + + msgQ.type = WMA_TSM_STATS_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pMsgBuf; + msgQ.bodyval = 0; + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + + if (eSIR_SUCCESS != (wma_post_ctrl_msg(pMac, &msgQ))) { + cdf_mem_free(pMsgBuf); + pMsgBuf = NULL; + lim_log(pMac, LOGP, "Unable to forward request"); + return; + } +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +static void +__lim_process_sme_update_apwpsi_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq; + tpPESession psessionEntry; + uint8_t sessionId; /* PE sessionID */ + + PELOG1(lim_log(pMac, LOG1, FL("received UPDATE_APWPSIEs_REQ message"));); + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateAPWPSIEsReq = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if (NULL == pUpdateAPWPSIEsReq) { + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for pUpdateAPWPSIEsReq")); + return; + } + cdf_mem_copy(pUpdateAPWPSIEsReq, pMsgBuf, + sizeof(struct sSirUpdateAPWPSIEsReq)); + + psessionEntry = pe_find_session_by_bssid(pMac, + pUpdateAPWPSIEsReq->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGW, + FL("Session does not exist for given BSSID")); + goto end; + } + + cdf_mem_copy(&psessionEntry->APWPSIEs, &pUpdateAPWPSIEsReq->APWPSIEs, + sizeof(tSirAPWPSIEs)); + + sch_set_fixed_beacon_fields(pMac, psessionEntry); + lim_send_beacon_ind(pMac, psessionEntry); + +end: + cdf_mem_free(pUpdateAPWPSIEsReq); + return; +} + +void +lim_send_vdev_restart(tpAniSirGlobal pMac, + tpPESession psessionEntry, uint8_t sessionId) +{ + tpHalHiddenSsidVdevRestart pHalHiddenSsidVdevRestart = NULL; + tSirMsgQ msgQ; + tSirRetStatus retCode = eSIR_SUCCESS; + + if (psessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, "%s:%d: Invalid parameters", __func__, + __LINE__); + ) + return; + } + + pHalHiddenSsidVdevRestart = + cdf_mem_malloc(sizeof(tHalHiddenSsidVdevRestart)); + if (NULL == pHalHiddenSsidVdevRestart) { + PELOGE(lim_log + (pMac, LOGE, "%s:%d: Unable to allocate memory", + __func__, __LINE__); + ) + return; + } + + pHalHiddenSsidVdevRestart->ssidHidden = psessionEntry->ssidHidden; + pHalHiddenSsidVdevRestart->sessionId = sessionId; + + msgQ.type = WMA_HIDDEN_SSID_VDEV_RESTART; + msgQ.bodyptr = pHalHiddenSsidVdevRestart; + msgQ.bodyval = 0; + + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + PELOGE(lim_log + (pMac, LOGE, "%s:%d: wma_post_ctrl_msg() failed", __func__, + __LINE__); + ) + cdf_mem_free(pHalHiddenSsidVdevRestart); + } +} + +static void __lim_process_sme_hide_ssid(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirUpdateParams pUpdateParams; + tpPESession psessionEntry; + + PELOG1(lim_log(pMac, LOG1, FL("received HIDE_SSID message"));); + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateParams = (tpSirUpdateParams) pMsgBuf; + + psessionEntry = pe_find_session_by_session_id(pMac, + pUpdateParams->sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGW, + "Session does not exist for given sessionId %d", + pUpdateParams->sessionId); + return; + } + + /* Update the session entry */ + psessionEntry->ssidHidden = pUpdateParams->ssidHidden; + + /* Send vdev restart */ + lim_send_vdev_restart(pMac, psessionEntry, pUpdateParams->sessionId); + + /* Update beacon */ + sch_set_fixed_beacon_fields(pMac, psessionEntry); + lim_send_beacon_ind(pMac, psessionEntry); + + return; +} /*** end __lim_process_sme_hide_ssid(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/ + +static void __lim_process_sme_set_wparsni_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq; + tpPESession psessionEntry; + uint8_t sessionId; /* PE sessionID */ + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pUpdateAPWPARSNIEsReq = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if (NULL == pUpdateAPWPARSNIEsReq) { + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for pUpdateAPWPARSNIEsReq")); + return; + } + cdf_mem_copy(pUpdateAPWPARSNIEsReq, pMsgBuf, + sizeof(struct sSirUpdateAPWPARSNIEsReq)); + + psessionEntry = pe_find_session_by_bssid(pMac, + pUpdateAPWPARSNIEsReq->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGW, + FL("Session does not exist for given BSSID")); + goto end; + } + + cdf_mem_copy(&psessionEntry->pLimStartBssReq->rsnIE, + &pUpdateAPWPARSNIEsReq->APWPARSNIEs, sizeof(tSirRSNie)); + + lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(pMac, + &psessionEntry-> + pLimStartBssReq->rsnIE, + psessionEntry); + + psessionEntry->pLimStartBssReq->privacy = 1; + psessionEntry->privacy = 1; + + sch_set_fixed_beacon_fields(pMac, psessionEntry); + lim_send_beacon_ind(pMac, psessionEntry); + +end: + cdf_mem_free(pUpdateAPWPARSNIEsReq); + return; +} /*** end __lim_process_sme_set_wparsni_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/ + +/* + Update the beacon Interval dynamically if beaconInterval is different in MCC + */ +static void __lim_process_sme_change_bi(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirChangeBIParams pChangeBIParams; + tpPESession psessionEntry; + uint8_t sessionId = 0; + tUpdateBeaconParams beaconParams; + + PELOG1(lim_log(pMac, LOG1, + FL("received Update Beacon Interval message")); + ); + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + cdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + pChangeBIParams = (tpSirChangeBIParams) pMsgBuf; + + psessionEntry = pe_find_session_by_bssid(pMac, + pChangeBIParams->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(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(lim_log(pMac, LOG1, + FL + ("LIM send update BeaconInterval Indication : %d"), + pChangeBIParams->beaconInterval); + ); + + if (false == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { + /* Update beacon */ + sch_set_fixed_beacon_fields(pMac, psessionEntry); + + beaconParams.bssIdx = psessionEntry->bssIdx; + /* Set change in beacon Interval */ + beaconParams.beaconInterval = + pChangeBIParams->beaconInterval; + beaconParams.paramChangeBitmap = + PARAM_BCN_INTERVAL_CHANGED; + lim_send_beacon_params(pMac, &beaconParams, psessionEntry); + } + } + + return; +} /*** end __lim_process_sme_change_bi(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/ + +#ifdef QCA_HT_2040_COEX +static void __lim_process_sme_set_ht2040_mode(tpAniSirGlobal pMac, + uint32_t *pMsgBuf) +{ + tpSirSetHT2040Mode pSetHT2040Mode; + tpPESession psessionEntry; + uint8_t sessionId = 0; + cds_msg_t msg; + tUpdateVHTOpMode *pHtOpMode = NULL; + uint16_t staId = 0; + tpDphHashNode pStaDs = NULL; + + PELOG1(lim_log(pMac, LOG1, FL("received Set HT 20/40 mode message"));); + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pSetHT2040Mode = (tpSirSetHT2040Mode) pMsgBuf; + + psessionEntry = pe_find_session_by_bssid(pMac, + pSetHT2040Mode->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOG1, + FL("Session does not exist for given BSSID ")); + lim_print_mac_addr(pMac, pSetHT2040Mode->bssId, LOG1); + return; + } + + lim_log(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: + lim_log(pMac, LOGE, FL("Invalid cbMode")); + return; + } + + /* Update beacon */ + sch_set_fixed_beacon_fields(pMac, psessionEntry); + lim_send_beacon_ind(pMac, psessionEntry); + + /* update OP Mode for each associated peer */ + for (staId = 0; staId < psessionEntry->dph.dphHashTable.size; staId++) { + pStaDs = dph_get_hash_entry(pMac, staId, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) + continue; + + if (pStaDs->valid && pStaDs->htSupportedChannelWidthSet) { + pHtOpMode = cdf_mem_malloc(sizeof(tUpdateVHTOpMode)); + if (NULL == pHtOpMode) { + lim_log(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; + cdf_mem_copy(pHtOpMode->peer_mac, &pStaDs->staAddr, + sizeof(tSirMacAddr)); + pHtOpMode->smesessionId = sessionId; + + msg.type = WMA_UPDATE_OP_MODE; + msg.reserved = 0; + msg.bodyptr = pHtOpMode; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + lim_log(pMac, LOGE, + FL + ("%s: Not able to post WMA_UPDATE_OP_MODE message to WMA"), + __func__); + cdf_mem_free(pHtOpMode); + return; + } + lim_log(pMac, LOG1, + FL + ("%s: Notifed FW about OP mode: %d for staId=%d"), + __func__, pHtOpMode->opMode, staId); + + } else + lim_log(pMac, LOG1, + FL("%s: station %d does not support HT40\n"), + __func__, staId); + } + + return; +} +#endif + +/* -------------------------------------------------------------------- */ +/** + * __lim_process_report_message + * + * FUNCTION: Processes the next received Radio Resource Management message + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void __lim_process_report_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ +#ifdef WLAN_FEATURE_VOWIFI + switch (pMsg->type) { + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + rrm_process_neighbor_report_req(pMac, pMsg->bodyptr); + break; + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + { + rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr); + } + break; + } +#endif +} + +#if defined(FEATURE_WLAN_ESE) || defined(WLAN_FEATURE_VOWIFI) +/* -------------------------------------------------------------------- */ +/** + * lim_send_set_max_tx_power_req + * + * 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 +lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, + tpPESession pSessionEntry) +{ + tpMaxTxPowerParams pMaxTxParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if (pSessionEntry == NULL) { + PELOGE(lim_log + (pMac, LOGE, "%s:%d: Inavalid parameters", __func__, + __LINE__); + ) + return eSIR_FAILURE; + } + + pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams)); + if (NULL == pMaxTxParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory for pMaxTxParams ")); + return eSIR_MEM_ALLOC_FAILED; + + } +#if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_ESE) + lim_log(pMac, LOG1, + FL("pMaxTxParams allocated...will be freed in other module")); +#endif + if (pMaxTxParams == NULL) { + lim_log(pMac, LOGE, FL("pMaxTxParams is NULL")); + return eSIR_FAILURE; + } + pMaxTxParams->power = txPower; + cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + + msgQ.type = WMA_SET_MAX_TX_POWER_REQ; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + PELOG1(lim_log + (pMac, LOG1, FL("Posting WMA_SET_MAX_TX_POWER_REQ to WMA")); + ) + MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() failed")); + cdf_mem_free(pMaxTxParams); + } + return retCode; +} +#endif + +/** + * __lim_process_sme_register_mgmt_frame_req() - process sme reg mgmt frame req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message + * from SME. It Register this information within PE. + * + * Return: None + */ +static void __lim_process_sme_register_mgmt_frame_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + CDF_STATUS cdf_status; + tpSirRegisterMgmtFrame sme_req = (tpSirRegisterMgmtFrame)msg_buf; + struct mgmt_frm_reg_info *lim_mgmt_regn = NULL; + struct mgmt_frm_reg_info *next = NULL; + bool match = false; + + lim_log(mac_ctx, LOG1, FL( + "registerFrame %d, frameType %d, matchLen %d"), + sme_req->registerFrame, sme_req->frameType, + sme_req->matchLen); + /* First check whether entry exists already */ + cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); + cdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t **) &lim_mgmt_regn); + cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); + + while (lim_mgmt_regn != NULL) { + if (lim_mgmt_regn->frameType != sme_req->frameType) + goto skip_match; + if (sme_req->matchLen) { + if ((lim_mgmt_regn->matchLen == sme_req->matchLen) && + (cdf_mem_compare(lim_mgmt_regn->matchData, + sme_req->matchData, + lim_mgmt_regn->matchLen))) { + /* found match! */ + match = true; + break; + } + } else { + /* found match! */ + match = true; + break; + } +skip_match: + cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); + cdf_status = cdf_list_peek_next( + &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t *)lim_mgmt_regn, + (cdf_list_node_t **)&next); + cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); + lim_mgmt_regn = next; + next = NULL; + } + if (match) { + cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); + cdf_list_remove_node( + &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, + (cdf_list_node_t *)lim_mgmt_regn); + cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); + cdf_mem_free(lim_mgmt_regn); + } + + if (sme_req->registerFrame) { + lim_mgmt_regn = + cdf_mem_malloc(sizeof(struct mgmt_frm_reg_info) + + sme_req->matchLen); + if (lim_mgmt_regn != NULL) { + cdf_mem_set((void *)lim_mgmt_regn, + sizeof(struct mgmt_frm_reg_info) + + sme_req->matchLen, 0); + lim_mgmt_regn->frameType = sme_req->frameType; + lim_mgmt_regn->matchLen = sme_req->matchLen; + lim_mgmt_regn->sessionId = sme_req->sessionId; + if (sme_req->matchLen) { + cdf_mem_copy(lim_mgmt_regn->matchData, + sme_req->matchData, + sme_req->matchLen); + } + cdf_mutex_acquire( + &mac_ctx->lim.lim_frame_register_lock); + cdf_list_insert_front(&mac_ctx->lim. + gLimMgmtFrameRegistratinQueue, + &lim_mgmt_regn->node); + cdf_mutex_release( + &mac_ctx->lim.lim_frame_register_lock); + } + } + return; +} + +static void __lim_deregister_deferred_sme_req_after_noa_start(tpAniSirGlobal pMac) +{ + lim_log(pMac, LOG1, FL("Dereg msgType %d"), + pMac->lim.gDeferMsgTypeForNOA); + pMac->lim.gDeferMsgTypeForNOA = 0; + if (pMac->lim.gpDefdSmeMsgForNOA != NULL) { + /* __lim_process_sme_scan_req consumed the buffer. We can free it. */ + cdf_mem_free(pMac->lim.gpDefdSmeMsgForNOA); + pMac->lim.gpDefdSmeMsgForNOA = NULL; + } +} + +/** + * lim_process_regd_defd_sme_req_after_noa_start() + * + * mac_ctx: Pointer to Global MAC structure + * + * This function is called to process deferred sme req message + * after noa start. + * + * Return: None + */ +void lim_process_regd_defd_sme_req_after_noa_start(tpAniSirGlobal mac_ctx) +{ + bool buf_consumed = true; + + lim_log(mac_ctx, LOG1, FL("Process defd sme req %d"), + mac_ctx->lim.gDeferMsgTypeForNOA); + + if ((mac_ctx->lim.gDeferMsgTypeForNOA == 0) || + (mac_ctx->lim.gpDefdSmeMsgForNOA == NULL)) { + lim_log(mac_ctx, LOGW, + FL("start rcvd from FW when no sme deferred msg pending. Do nothing. ")); + lim_log(mac_ctx, LOGW, + FL("It may happen when NOA start ind and timeout happen at the same time")); + return; + } + switch (mac_ctx->lim.gDeferMsgTypeForNOA) { + case eWNI_SME_SCAN_REQ: + __lim_process_sme_scan_req(mac_ctx, + mac_ctx->lim.gpDefdSmeMsgForNOA); + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + __lim_process_sme_oem_data_req(mac_ctx, + mac_ctx->lim.gpDefdSmeMsgForNOA); + break; +#endif + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + buf_consumed = lim_process_remain_on_chnl_req(mac_ctx, + mac_ctx->lim.gpDefdSmeMsgForNOA); + /* + * lim_process_remain_on_chnl_req doesnt want us to free + * the buffer since it is freed in lim_remain_on_chn_rsp. + * this change is to avoid "double free" + */ + if (false == buf_consumed) + mac_ctx->lim.gpDefdSmeMsgForNOA = NULL; + break; + case eWNI_SME_JOIN_REQ: + __lim_process_sme_join_req(mac_ctx, + mac_ctx->lim.gpDefdSmeMsgForNOA); + break; + default: + lim_log(mac_ctx, LOGE, FL("Unknown deferred msg type %d"), + mac_ctx->lim.gDeferMsgTypeForNOA); + break; + } + __lim_deregister_deferred_sme_req_after_noa_start(mac_ctx); +} + +static void +__lim_process_sme_reset_ap_caps_change(tpAniSirGlobal pMac, uint32_t *pMsgBuf) +{ + tpSirResetAPCapsChange pResetCapsChange; + tpPESession psessionEntry; + uint8_t sessionId = 0; + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pResetCapsChange = (tpSirResetAPCapsChange) pMsgBuf; + psessionEntry = + pe_find_session_by_bssid(pMac, pResetCapsChange->bssId, &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session does not exist for given BSSID")); + return; + } + + psessionEntry->limSentCapsChangeNtf = false; + return; +} + +/** + * lim_process_sme_req_messages() + * + ***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. + */ + +bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + bool bufConsumed = true; /* Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. */ + uint32_t *pMsgBuf = pMsg->bodyptr; + tpSirSmeScanReq pScanReq; + PELOG1(lim_log + (pMac, LOG1, + FL + ("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)"), + lim_msg_str(pMsg->type), pMsg->type, + lim_sme_state_str(pMac->lim.gLimSmeState), pMac->lim.gLimSmeState, + lim_mlm_state_str(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState); + ) + + pScanReq = (tpSirSmeScanReq) pMsgBuf; + /* If no insert NOA required then execute the code below */ + + switch (pMsg->type) { + case eWNI_SME_SYS_READY_IND: + bufConsumed = __lim_process_sme_sys_ready_ind(pMac, pMsgBuf); + break; + + case eWNI_SME_START_BSS_REQ: + bufConsumed = __lim_process_sme_start_bss_req(pMac, pMsg); + break; + + case eWNI_SME_SCAN_REQ: + __lim_process_sme_scan_req(pMac, pMsgBuf); + break; + +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + __lim_process_sme_oem_data_req(pMac, pMsgBuf); + break; +#endif + case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + bufConsumed = lim_process_remain_on_chnl_req(pMac, pMsgBuf); + break; + + case eWNI_SME_UPDATE_NOA: + __lim_process_sme_no_a_update(pMac, pMsgBuf); + break; + case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: + __lim_process_clear_dfs_channel_list(pMac, pMsg); + break; + case eWNI_SME_JOIN_REQ: + __lim_process_sme_join_req(pMac, pMsgBuf); + break; + + case eWNI_SME_REASSOC_REQ: + __lim_process_sme_reassoc_req(pMac, pMsgBuf); + break; + + case eWNI_SME_DISASSOC_REQ: + __lim_process_sme_disassoc_req(pMac, pMsgBuf); + break; + + case eWNI_SME_DISASSOC_CNF: + case eWNI_SME_DEAUTH_CNF: + __lim_process_sme_disassoc_cnf(pMac, pMsgBuf); + break; + + case eWNI_SME_DEAUTH_REQ: + __lim_process_sme_deauth_req(pMac, pMsgBuf); + break; + + case eWNI_SME_SETCONTEXT_REQ: + __lim_process_sme_set_context_req(pMac, pMsgBuf); + break; + + case eWNI_SME_STOP_BSS_REQ: + bufConsumed = __lim_process_sme_stop_bss_req(pMac, pMsg); + break; + + case eWNI_SME_ASSOC_CNF: + if (pMsg->type == eWNI_SME_ASSOC_CNF) + PELOG1(lim_log(pMac, + LOG1, FL("Received ASSOC_CNF message"));) + __lim_process_sme_assoc_cnf_new(pMac, pMsg->type, + pMsgBuf); + break; + + case eWNI_SME_ADDTS_REQ: + PELOG1(lim_log(pMac, LOG1, FL("Received ADDTS_REQ message"));) + __lim_process_sme_addts_req(pMac, pMsgBuf); + break; + + case eWNI_SME_DELTS_REQ: + PELOG1(lim_log(pMac, LOG1, FL("Received DELTS_REQ message"));) + __lim_process_sme_delts_req(pMac, pMsgBuf); + break; + + case SIR_LIM_ADDTS_RSP_TIMEOUT: + PELOG1(lim_log + (pMac, LOG1, + FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message ")); + ) + lim_process_sme_addts_rsp_timeout(pMac, pMsg->bodyval); + break; + + case eWNI_SME_GET_STATISTICS_REQ: + __lim_process_sme_get_statistics_request(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: + __lim_process_sme_get_tsm_stats_request(pMac, pMsgBuf); + bufConsumed = false; + break; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_GET_ASSOC_STAS_REQ: + lim_process_sme_get_assoc_sta_info(pMac, pMsgBuf); + break; + case eWNI_SME_TKIP_CNTR_MEAS_REQ: + lim_process_tkip_counter_measures(pMac, pMsgBuf); + break; + + case eWNI_SME_HIDE_SSID_REQ: + __lim_process_sme_hide_ssid(pMac, pMsgBuf); + break; + case eWNI_SME_UPDATE_APWPSIE_REQ: + __lim_process_sme_update_apwpsi_es(pMac, pMsgBuf); + break; + case eWNI_SME_GET_WPSPBC_SESSION_REQ: + lim_process_sme_get_wpspbc_sessions(pMac, pMsgBuf); + break; + + case eWNI_SME_SET_APWPARSNIEs_REQ: + __lim_process_sme_set_wparsni_es(pMac, pMsgBuf); + break; + + case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: + /* Update the beaconInterval */ + __lim_process_sme_change_bi(pMac, pMsgBuf); + break; + +#ifdef QCA_HT_2040_COEX + case eWNI_SME_SET_HT_2040_MODE: + __lim_process_sme_set_ht2040_mode(pMac, pMsgBuf); + break; +#endif + +#if defined WLAN_FEATURE_VOWIFI + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + __lim_process_report_message(pMac, pMsg); + break; +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_PRE_AUTH_REQ: + bufConsumed = (bool) lim_process_ft_pre_auth_req(pMac, pMsg); + break; + case eWNI_SME_FT_UPDATE_KEY: + lim_process_ft_update_key(pMac, pMsgBuf); + break; + + case eWNI_SME_FT_AGGR_QOS_REQ: + lim_process_ft_aggr_qos_req(pMac, pMsgBuf); + break; +#endif + + case eWNI_SME_REGISTER_MGMT_FRAME_REQ: + __lim_process_sme_register_mgmt_frame_req(pMac, pMsgBuf); + break; +#ifdef FEATURE_WLAN_TDLS + case eWNI_SME_TDLS_SEND_MGMT_REQ: + lim_process_sme_tdls_mgmt_send_req(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_ADD_STA_REQ: + lim_process_sme_tdls_add_sta_req(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_DEL_STA_REQ: + lim_process_sme_tdls_del_sta_req(pMac, pMsgBuf); + break; + case eWNI_SME_TDLS_LINK_ESTABLISH_REQ: + lim_process_sme_tdls_link_establish_req(pMac, pMsgBuf); + break; +#endif + case eWNI_SME_RESET_AP_CAPS_CHANGED: + __lim_process_sme_reset_ap_caps_change(pMac, pMsgBuf); + break; + + case eWNI_SME_CHANNEL_CHANGE_REQ: + lim_process_sme_channel_change_request(pMac, pMsgBuf); + break; + + case eWNI_SME_START_BEACON_REQ: + lim_process_sme_start_beacon_req(pMac, pMsgBuf); + break; + + case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: + lim_process_sme_dfs_csa_ie_request(pMac, pMsgBuf); + break; + + case eWNI_SME_UPDATE_ADDITIONAL_IES: + lim_process_update_add_ies(pMac, pMsgBuf); + break; + + case eWNI_SME_MODIFY_ADDITIONAL_IES: + lim_process_modify_add_ies(pMac, pMsgBuf); + break; + case eWNI_SME_SET_HW_MODE_REQ: + lim_process_set_hw_mode(pMac, pMsgBuf); + break; + case eWNI_SME_NSS_UPDATE_REQ: + lim_process_nss_update_request(pMac, pMsgBuf); + break; + case eWNI_SME_SET_DUAL_MAC_CFG_REQ: + lim_process_set_dual_mac_cfg_req(pMac, pMsgBuf); + break; + case eWNI_SME_SET_IE_REQ: + lim_process_set_ie_req(pMac, pMsgBuf); + break; + default: + cdf_mem_free((void *)pMsg->bodyptr); + pMsg->bodyptr = NULL; + break; + } /* switch (msgType) */ + + return bufConsumed; +} /*** end lim_process_sme_req_messages() ***/ + +/** + * lim_process_sme_start_beacon_req() + * + ***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 lim_process_sme_start_beacon_req(tpAniSirGlobal pMac, uint32_t *pMsg) +{ + tpSirStartBeaconIndication pBeaconStartInd; + tpPESession psessionEntry; + uint8_t sessionId; /* PE sessionID */ + + if (pMsg == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + pBeaconStartInd = (tpSirStartBeaconIndication) pMsg; + psessionEntry = pe_find_session_by_bssid(pMac, + pBeaconStartInd->bssid, + &sessionId); + if (psessionEntry == NULL) { + lim_print_mac_addr(pMac, pBeaconStartInd->bssid, LOGE); + lim_log(pMac, LOGE, + FL("Session does not exist for given bssId")); + return; + } + + if (pBeaconStartInd->beaconStartStatus == 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 WMA_ADD_BSS_RSP. + */ + lim_apply_configuration(pMac, psessionEntry); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Start Beacon with ssid %s Ch %d"), + psessionEntry->ssId.ssId, + psessionEntry->currentOperChannel); + lim_send_beacon_ind(pMac, psessionEntry); + } else { + lim_log(pMac, LOGE, FL("Invalid Beacon Start Indication")); + return; + } +} + +/** + * lim_process_sme_channel_change_request() - process sme ch change req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function is called to process SME_CHANNEL_CHANGE_REQ message + * + * Return: None + */ +static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tpSirChanChangeRequest ch_change_req; + tpPESession session_entry; + uint8_t session_id; /* PE session_id */ + tPowerdBm max_tx_pwr; + uint32_t val = 0; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("msg_buf is NULL")); + return; + } + ch_change_req = (tpSirChanChangeRequest)msg_buf; + + max_tx_pwr = cfg_get_regulatory_max_transmit_power(mac_ctx, + ch_change_req->targetChannel); + + if ((ch_change_req->messageType != eWNI_SME_CHANNEL_CHANGE_REQ) || + (max_tx_pwr == WMA_MAX_TXPOWER_INVALID)) { + lim_log(mac_ctx, LOGE, FL("Invalid Request/max_tx_pwr")); + return; + } + + session_entry = pe_find_session_by_bssid(mac_ctx, + ch_change_req->bssid, &session_id); + if (session_entry == NULL) { + lim_print_mac_addr(mac_ctx, ch_change_req->bssid, LOGE); + lim_log(mac_ctx, LOGE, FL( + "Session does not exist for given bssId")); + return; + } + + if (session_entry->currentOperChannel == + ch_change_req->targetChannel) { + lim_log(mac_ctx, LOGE, FL("target CH is same as current CH")); + return; + } + + if (LIM_IS_AP_ROLE(session_entry)) + session_entry->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_SAP_DFS; + else + session_entry->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_OPERATION; + + lim_log(mac_ctx, LOGW, FL( + "switch old chnl %d to new chnl %d, ch_bw %d"), + session_entry->currentOperChannel, + ch_change_req->targetChannel, + ch_change_req->channel_width); + + /* Store the New Channel Params in session_entry */ + session_entry->ch_width = ch_change_req->channel_width; + session_entry->ch_center_freq_seg0 = + ch_change_req->center_freq_seg_0; + session_entry->ch_center_freq_seg1 = + ch_change_req->center_freq_seg_1; + session_entry->htSecondaryChannelOffset = ch_change_req->cbMode; + session_entry->htSupportedChannelWidthSet = + (ch_change_req->channel_width ? 1 : 0); + session_entry->htRecommendedTxWidthSet = + session_entry->htSupportedChannelWidthSet; + session_entry->currentOperChannel = + ch_change_req->targetChannel; + session_entry->limRFBand = + lim_get_rf_band(session_entry->currentOperChannel); + /* Initialize 11h Enable Flag */ + if (SIR_BAND_5_GHZ == session_entry->limRFBand) { + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_11H_ENABLED, &val) != + eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Fail to get WNI_CFG_11H_ENABLED")); + } + + session_entry->lim11hEnable = val; + session_entry->dot11mode = ch_change_req->dot11mode; + cdf_mem_copy(&session_entry->rateSet, + &ch_change_req->operational_rateset, + sizeof(session_entry->rateSet)); + cdf_mem_copy(&session_entry->extRateSet, + &ch_change_req->extended_rateset, + sizeof(session_entry->extRateSet)); + lim_set_channel(mac_ctx, ch_change_req->targetChannel, + session_entry->ch_center_freq_seg0, + session_entry->ch_center_freq_seg1, + session_entry->ch_width, + max_tx_pwr, session_entry->peSessionId); +} + +/****************************************************************************** +* lim_start_bss_update_add_ie_buffer() +* +***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 uint8_t dst buffer +* @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length +* @param *pSrcData_buff A pointer of uint8_t src buffer +* @param srcDataLen src buffer length +******************************************************************************/ + +static void +lim_start_bss_update_add_ie_buffer(tpAniSirGlobal pMac, + uint8_t **pDstData_buff, + uint16_t *pDstDataLen, + uint8_t *pSrcData_buff, uint16_t srcDataLen) +{ + + if (srcDataLen > 0 && pSrcData_buff != NULL) { + *pDstDataLen = srcDataLen; + + *pDstData_buff = cdf_mem_malloc(*pDstDataLen); + + if (NULL == *pDstData_buff) { + lim_log(pMac, LOGE, + FL("AllocateMemory failed for pDstData_buff")); + return; + } + cdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); + } else { + *pDstData_buff = NULL; + *pDstDataLen = 0; + } +} + +/****************************************************************************** +* lim_update_add_ie_buffer() +* +***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 uint8_t dst buffer +* @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length +* @param *pSrcData_buff A pointer of uint8_t src buffer +* @param srcDataLen src buffer length +******************************************************************************/ + +static void +lim_update_add_ie_buffer(tpAniSirGlobal pMac, + uint8_t **pDstData_buff, + uint16_t *pDstDataLen, + uint8_t *pSrcData_buff, uint16_t srcDataLen) +{ + + if (NULL == pSrcData_buff) { + lim_log(pMac, LOGE, FL("src buffer is null.")); + return; + } + + if (srcDataLen > *pDstDataLen) { + *pDstDataLen = srcDataLen; + /* free old buffer */ + cdf_mem_free(*pDstData_buff); + /* allocate a new */ + *pDstData_buff = cdf_mem_malloc(*pDstDataLen); + + if (NULL == *pDstData_buff) { + lim_log(pMac, LOGE, FL("Memory allocation failed.")); + *pDstDataLen = 0; + return; + } + } + + /* copy the content of buffer into dst buffer + */ + *pDstDataLen = srcDataLen; + cdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); + +} + +/* +* lim_process_modify_add_ies() - process modify additional IE req. +* +* @mac_ctx: Pointer to Global MAC structure +* @msg_buf: pointer to the SME message buffer +* +* This function update the PE buffers for additional IEs. +* +* Return: None +*/ +static void lim_process_modify_add_ies(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tpSirModifyIEsInd modify_add_ies; + tpPESession session_entry; + uint8_t session_id; + bool ret = false; + tSirAddIeParams *add_ie_params; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("msg_buf is NULL")); + return; + } + + modify_add_ies = (tpSirModifyIEsInd)msg_buf; + /* Incoming message has smeSession, use BSSID to find PE session */ + session_entry = pe_find_session_by_bssid(mac_ctx, + modify_add_ies->modifyIE.bssid, &session_id); + + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(modify_add_ies->modifyIE.bssid)); + goto end; + } + if ((0 == modify_add_ies->modifyIE.ieBufferlength) || + (0 == modify_add_ies->modifyIE.ieIDLen) || + (NULL == modify_add_ies->modifyIE.pIEBuffer)) { + lim_log(mac_ctx, LOGE, + FL("Invalid request pIEBuffer %p ieBufferlength %d ieIDLen %d ieID %d. update Type %d"), + modify_add_ies->modifyIE.pIEBuffer, + modify_add_ies->modifyIE.ieBufferlength, + modify_add_ies->modifyIE.ieID, + modify_add_ies->modifyIE.ieIDLen, + modify_add_ies->updateType); + goto end; + } + add_ie_params = &session_entry->addIeParams; + switch (modify_add_ies->updateType) { + case eUPDATE_IE_PROBE_RESP: + /* Probe resp */ + break; + case eUPDATE_IE_ASSOC_RESP: + /* assoc resp IE */ + if (add_ie_params->assocRespDataLen == 0) { + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_ERROR, FL( + "assoc resp add ie not present %d"), + add_ie_params->assocRespDataLen); + } + /* search through the buffer and modify the IE */ + break; + case eUPDATE_IE_PROBE_BCN: + /*probe beacon IE */ + if (ret == true && modify_add_ies->modifyIE.notify) { + lim_handle_param_update(mac_ctx, + modify_add_ies->updateType); + } + break; + default: + lim_log(mac_ctx, LOGE, FL("unhandled buffer type %d"), + modify_add_ies->updateType); + break; + } +end: + cdf_mem_free(modify_add_ies->modifyIE.pIEBuffer); + modify_add_ies->modifyIE.pIEBuffer = NULL; +} + +/* +* lim_process_update_add_ies() - process additional IE update req +* +* @mac_ctx: Pointer to Global MAC structure +* @msg_buf: pointer to the SME message buffer +* +* This function update the PE buffers for additional IEs. +* +* Return: None +*/ +static void lim_process_update_add_ies(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tpSirUpdateIEsInd update_add_ies = (tpSirUpdateIEsInd)msg_buf; + uint8_t session_id; + tpPESession session_entry; + tSirAddIeParams *addn_ie; + uint16_t new_length = 0; + uint8_t *new_ptr = NULL; + tSirUpdateIE *update_ie; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("msg_buf is NULL")); + return; + } + update_ie = &update_add_ies->updateIE; + /* incoming message has smeSession, use BSSID to find PE session */ + session_entry = pe_find_session_by_bssid(mac_ctx, + update_ie->bssid, &session_id); + + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(update_ie->bssid)); + goto end; + } + addn_ie = &session_entry->addIeParams; + /* if len is 0, upper layer requested freeing of buffer */ + if (0 == update_ie->ieBufferlength) { + switch (update_add_ies->updateType) { + case eUPDATE_IE_PROBE_RESP: + cdf_mem_free(addn_ie->probeRespData_buff); + addn_ie->probeRespData_buff = NULL; + addn_ie->probeRespDataLen = 0; + break; + case eUPDATE_IE_ASSOC_RESP: + cdf_mem_free(addn_ie->assocRespData_buff); + addn_ie->assocRespData_buff = NULL; + addn_ie->assocRespDataLen = 0; + break; + case eUPDATE_IE_PROBE_BCN: + cdf_mem_free(addn_ie->probeRespBCNData_buff); + addn_ie->probeRespBCNData_buff = NULL; + addn_ie->probeRespBCNDataLen = 0; + + if (update_ie->notify) + lim_handle_param_update(mac_ctx, + update_add_ies->updateType); + break; + default: + break; + } + return; + } + switch (update_add_ies->updateType) { + case eUPDATE_IE_PROBE_RESP: + if (update_ie->append) { + /* + * In case of append, allocate new memory + * with combined length + */ + new_length = update_ie->ieBufferlength + + addn_ie->probeRespDataLen; + new_ptr = cdf_mem_malloc(new_length); + if (NULL == new_ptr) { + lim_log(mac_ctx, LOGE, FL( + "Memory allocation failed.")); + goto end; + } + /* append buffer to end of local buffers */ + cdf_mem_copy(new_ptr, addn_ie->probeRespData_buff, + addn_ie->probeRespDataLen); + cdf_mem_copy(&new_ptr[addn_ie->probeRespDataLen], + update_ie->pAdditionIEBuffer, + update_ie->ieBufferlength); + /* free old memory */ + cdf_mem_free(addn_ie->probeRespData_buff); + /* adjust length accordingly */ + addn_ie->probeRespDataLen = new_length; + /* save refernece of local buffer in PE session */ + addn_ie->probeRespData_buff = new_ptr; + goto end; + } + lim_update_add_ie_buffer(mac_ctx, &addn_ie->probeRespData_buff, + &addn_ie->probeRespDataLen, + update_ie->pAdditionIEBuffer, + update_ie->ieBufferlength); + break; + case eUPDATE_IE_ASSOC_RESP: + /* assoc resp IE */ + lim_update_add_ie_buffer(mac_ctx, &addn_ie->assocRespData_buff, + &addn_ie->assocRespDataLen, + update_ie->pAdditionIEBuffer, + update_ie->ieBufferlength); + break; + case eUPDATE_IE_PROBE_BCN: + /* probe resp Bcn IE */ + lim_update_add_ie_buffer(mac_ctx, + &addn_ie->probeRespBCNData_buff, + &addn_ie->probeRespBCNDataLen, + update_ie->pAdditionIEBuffer, + update_ie->ieBufferlength); + if (update_ie->notify) + lim_handle_param_update(mac_ctx, + update_add_ies->updateType); + break; + default: + lim_log(mac_ctx, LOGE, FL("unhandled buffer type %d."), + update_add_ies->updateType); + break; + } +end: + cdf_mem_free(update_ie->pAdditionIEBuffer); + update_ie->pAdditionIEBuffer = NULL; +} + +/** + * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function processes SME request messages from HDD or upper layer + * application. + * + * Return: None + */ +static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + tpSirDfsCsaIeRequest dfs_csa_ie_req; + tpPESession session_entry = NULL; + uint32_t ch_width = 0; + uint8_t session_id; + tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + dfs_csa_ie_req = (tSirDfsCsaIeRequest *)msg_buf; + session_entry = pe_find_session_by_bssid(mac_ctx, + dfs_csa_ie_req->bssid, &session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL( + "Session not found for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(dfs_csa_ie_req->bssid)); + return; + } + + if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOGE, FL("Invalid SystemRole %d"), + GET_LIM_SYSTEM_ROLE(session_entry)); + return; + } + + /* target channel */ + session_entry->gLimChannelSwitch.primaryChannel = + dfs_csa_ie_req->targetChannel; + + /* Channel switch announcement needs to be included in beacon */ + session_entry->dfsIncludeChanSwIe = true; + session_entry->gLimChannelSwitch.switchCount = LIM_MAX_CSA_IE_UPDATES; + session_entry->gLimChannelSwitch.ch_width = + dfs_csa_ie_req->ch_bandwidth; + if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) + session_entry->gLimChannelSwitch.switchMode = 1; + + /* + * Validate if SAP is operating HT or VHT mode and set the Channel + * Switch Wrapper element with the Wide Band Switch subelement. + */ + if (true != session_entry->vhtCapability) + goto skip_vht; + + if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == + session_entry->vhtTxChannelWidthSet) + ch_width = eHT_CHANNEL_WIDTH_80MHZ; + else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == + session_entry->vhtTxChannelWidthSet) + ch_width = session_entry->htSupportedChannelWidthSet; + /* Now encode the Wider Ch BW element depending on the ch width */ + wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch; + switch (ch_width) { + 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. + */ + session_entry->dfsIncludeChanWrapperIe = false; + wider_bw_ch_switch->newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + break; + case eHT_CHANNEL_WIDTH_40MHZ: + session_entry->dfsIncludeChanWrapperIe = true; + wider_bw_ch_switch->newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + break; + case eHT_CHANNEL_WIDTH_80MHZ: + session_entry->dfsIncludeChanWrapperIe = true; + wider_bw_ch_switch->newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + break; + case eHT_CHANNEL_WIDTH_160MHZ: + session_entry->dfsIncludeChanWrapperIe = true; + wider_bw_ch_switch->newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + break; + default: + session_entry->dfsIncludeChanWrapperIe = false; + /* + * Need to handle 80+80 Mhz Scenario. When 80+80 is supported + * set the gLimWiderBWChannelSwitch.newChanWidth to 3 + */ + lim_log(mac_ctx, LOGE, FL("Invalid Channel Width")); + break; + } + /* Fetch the center channel based on the channel width */ + wider_bw_ch_switch->newCenterChanFreq0 = + lim_get_center_channel(mac_ctx, dfs_csa_ie_req->targetChannel, + session_entry->htSecondaryChannelOffset, + wider_bw_ch_switch->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. + */ + wider_bw_ch_switch->newCenterChanFreq1 = 0; +skip_vht: + /* Send CSA IE request from here */ + if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != + eSIR_SUCCESS) { + lim_log(mac_ctx, 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 + */ + lim_send_beacon_ind(mac_ctx, session_entry); + lim_log(mac_ctx, LOG1, FL("Updated CSA IE, IE COUNT = %d"), + session_entry->gLimChannelSwitch.switchCount); + session_entry->gLimChannelSwitch.switchCount--; +} + +/** + * lim_process_nss_update_request() - process sme nss update req + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function processes SME request messages from HDD or upper layer + * application. + * + * Return: None + */ +static void lim_process_nss_update_request(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + struct sir_nss_update_request *nss_update_req_ptr; + tpPESession session_entry = NULL; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + nss_update_req_ptr = (struct sir_nss_update_request *)msg_buf; + session_entry = pe_find_session_by_session_id(mac_ctx, + nss_update_req_ptr->vdev_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL( + "Session not found for given session_id %d"), + nss_update_req_ptr->vdev_id); + return; + } + + if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOGE, FL("Invalid SystemRole %d"), + GET_LIM_SYSTEM_ROLE(session_entry)); + return; + } + + /* populate nss field in the beacon */ + session_entry->gLimOperatingMode.present = 1; + session_entry->gLimOperatingMode.rxNSS = nss_update_req_ptr->new_nss; + /* Send nss update request from here */ + if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != + eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("Unable to set op mode IE in beacon")); + return; + } + + lim_send_beacon_ind(mac_ctx, session_entry); +} + +/** + * lim_process_set_ie_req() - process sme set IE request + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to the SME message buffer + * + * This function processes SME request messages from HDD or upper layer + * application. + * + * Return: None + */ +static void lim_process_set_ie_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) +{ + struct send_extcap_ie *msg; + CDF_STATUS status; + + if (msg_buf == NULL) { + lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + msg = (struct send_extcap_ie *)msg_buf; + status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, NULL, false); + if (CDF_STATUS_SUCCESS != status) + lim_log(mac_ctx, LOGE, FL("Unable to send ExtCap to FW")); + +} diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c new file mode 100644 index 000000000000..fa5a0ab3010c --- /dev/null +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -0,0 +1,3267 @@ +/* + * 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. + */ + +/*=========================================================================== + * lim_process_tdls.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 lim_process_tdls.c + * + * \brief Code for preparing,processing and sending 802.11z action frames + * + */ + +#ifdef FEATURE_WLAN_TDLS + +#include "sir_api.h" +#include "ani_global.h" +#include "sir_mac_prot_def.h" +#include "cfg_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_security_utils.h" +#include "dot11f.h" +#include "lim_sta_hash_api.h" +#include "sch_api.h" +#include "lim_send_messages.h" +#include "utils_parser.h" +#include "lim_assoc_utils.h" +#include "dph_hash_table.h" +#include "wma_types.h" +#include "cds_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 lim_tdls_setup_add_sta(tpAniSirGlobal pMac, + tSirTdlsAddStaReq * pAddStaReq, tpPESession psessionEntry); +void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIELinkIdentifier *linkIden, + tSirMacAddr peerMac, uint8_t reqType); +void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEExtCap *extCapability); + +void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIESuppChannels *suppChannels, + tDot11fIESuppOperatingClasses * + suppOperClasses); +void lim_log_vht_cap(tpAniSirGlobal pMac, tDot11fIEVHTCaps *pDot11f); +tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal pMac, + tpSirSupportedRates pRates, + tDot11fIEVHTCaps *pPeerVHTCaps, + tpPESession psessionEntry); +ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode); + +/* + * TDLS data frames will go out/come in as non-qos data. + * so, eth_890d_header will be aligned access.. + */ +static const uint8_t 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 +} e_tdls_link; + +/* + * node status in node searching + */ +enum tdlsLinkNodeStatus { + TDLS_NODE_NOT_FOUND, + TDLS_NODE_FOUND +} e_tdls_link_node_status; + +enum tdlsReqType { + TDLS_INITIATOR, + TDLS_RESPONDER +} e_tdls_req_type; + +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 +} e_tdls_peer_capability; + +/* 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) \ + do { \ + if ((aid) < (sizeof(uint32_t) << 3)) \ + SET_BIT(peer_bitmap[0], (aid)); \ + else if ((aid) < (sizeof(uint32_t) << 4)) \ + SET_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\ + } while (0); + +#define CLEAR_PEER_AID_BITMAP(peer_bitmap, aid) \ + do { \ + if ((aid) < (sizeof(uint32_t) << 3)) \ + CLEAR_BIT(peer_bitmap[0], (aid)); \ + else if ((aid) < (sizeof(uint32_t) << 4)) \ + CLEAR_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\ + } while (0); + +#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 uint8_t *lim_trace_tdls_action_string(uint8_t 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 uint8_t *)"UNKNOWN"; +} +#endif +/* + * initialize TDLS setup list and related data structures. + */ +void lim_init_tdls_data(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + lim_init_peer_idxpool(pMac, pSessionEntry); + + return; +} + +/* + * prepare TDLS frame header, it includes + * | | | | + * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD + * | | | | + */ +static uint32_t lim_prepare_tdls_frame_header(tpAniSirGlobal pMac, uint8_t *pFrame, + tDot11fIELinkIdentifier *link_iden, + uint8_t tdlsLinkType, uint8_t reqType, + uint8_t tid, + tpPESession psessionEntry) +{ + tpSirMacDataHdr3a pMacHdr; + uint32_t header_offset = 0; + uint8_t *addr1 = NULL; + uint8_t *addr3 = NULL; + uint8_t toDs = (tdlsLinkType == TDLS_LINK_AP) + ? ANI_TXDIR_TODS : ANI_TXDIR_IBSS; + uint8_t *peerMac = (reqType == TDLS_INITIATOR) + ? link_iden->RespStaAddr : link_iden->InitStaAddr; + uint8_t *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; + pMacHdr->fc.subType = + IS_QOS_ENABLED(psessionEntry) ? 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; + + cdf_mem_copy((uint8_t *) pMacHdr->addr1, + (uint8_t *) addr1, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pMacHdr->addr2, + (uint8_t *) staMac, sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) pMacHdr->addr3, + (uint8_t *) (addr3), sizeof(tSirMacAddr)); + + lim_log(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 (IS_QOS_ENABLED(psessionEntry)) { + pMacHdr->qosControl.tid = tid; + header_offset += sizeof(tSirMacDataHdr3a); + } else + header_offset += sizeof(tSirMacMgmtHdr); + + /* + * Now form RFC1042 header + */ + cdf_mem_copy((uint8_t *) (pFrame + header_offset), + (uint8_t *) eth_890d_header, sizeof(eth_890d_header)); + + header_offset += sizeof(eth_890d_header); + + /* add payload type as TDLS */ + *(pFrame + header_offset) = PAYLOAD_TYPE_TDLS; + header_offset += PAYLOAD_TYPE_TDLS_SIZE; + return header_offset; +} + +/* + * TX Complete for Management frames + */ +CDF_STATUS lim_mgmt_tx_complete(tpAniSirGlobal pMac, uint32_t txCompleteSuccess) +{ + tpPESession psessionEntry = NULL; + + if (0xff != pMac->lim.mgmtFrameSessionId) { + psessionEntry = + pe_find_session_by_session_id(pMac, + pMac->lim.mgmtFrameSessionId); + if (NULL == psessionEntry) { + lim_log(pMac, LOGE, FL("sessionID %d is not found"), + pMac->lim.mgmtFrameSessionId); + return CDF_STATUS_E_FAILURE; + } + lim_send_sme_mgmt_tx_completion(pMac, psessionEntry, + txCompleteSuccess); + pMac->lim.mgmtFrameSessionId = 0xff; + } + return CDF_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 lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, + uint8_t dialog, tpPESession psessionEntry) +{ + tDot11fTDLSDisReq tdlsDisReq; + uint32_t status = 0; + uint32_t nPayload = 0; + uint32_t size = 0; + uint32_t nBytes = 0; + uint32_t header_offset = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + uint32_t padLen = 0; +#endif + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + lim_log(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 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + cdf_mem_set((uint8_t *) &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); + + populate_dot11f_link_iden(pMac, psessionEntry, &tdlsDisReq.LinkIdentifier, + peer_mac, TDLS_INITIATOR); + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11f_get_packed_tdls_dis_req_size(pMac, &tdlsDisReq, &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGP, + 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)) { + lim_log(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 */ + + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL( + "Failed to allocate %d bytes for a TDLS Discovery Request." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET + (tdlsDisReq), TDLS_LINK_AP, + TDLS_INITIATOR, TID_AC_VI, + psessionEntry); + + status = dot11f_pack_tdls_dis_req(pMac, &tdlsDisReq, pFrame + + header_offset, nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to pack a TDLS discovery req (0x%08x)."), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(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 }; */ + uint8_t *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; + + lim_log(pMac, LOGW, + FL("Padding Vendor Specific Ie Len = %d"), padLen); + + /* padding zero if more than 5 bytes are required */ + if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE) + cdf_mem_set(pFrame + header_offset + nPayload + + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_DIS_REQ, + lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_REQ), + MAC_ADDR_ARRAY(peer_mac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false, 0); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(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 lim_send_tdls_dis_rsp_frame, + * lim_send_tdls_link_setup_req_frame and lim_send_tdls_setup_rsp_frame + */ +static void populate_dot11f_tdls_ht_vht_cap(tpAniSirGlobal pMac, + uint32_t selfDot11Mode, + tDot11fIEHTCaps *htCap, + tDot11fIEVHTCaps *vhtCap, + tpPESession psessionEntry) +{ + if (IS_DOT11_MODE_HT(selfDot11Mode)) { + /* Include HT Capability IE */ + populate_dot11f_ht_caps(pMac, NULL, htCap); + /* + * Advertise 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; + } + lim_log(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 */ + populate_dot11f_vht_caps(pMac, psessionEntry, vhtCap); + vhtCap->suBeamformeeCap = 0; + vhtCap->suBeamFormerCap = 0; + vhtCap->muBeamformeeCap = 0; + vhtCap->muBeamformerCap = 0; + } else { + vhtCap->present = 0; + } + } else { + /* Vht Disable from ini in 2.4 GHz */ + vhtCap->present = 0; + } + lim_log(pMac, LOG1, FL("VHT present = %hu, Chan Width = %hu"), + vhtCap->present, vhtCap->supportedChannelWidthSet); +#endif +} + +/* + * Send TDLS discovery response frame on direct link. + */ + +static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, uint8_t dialog, + tpPESession psessionEntry, + uint8_t *addIe, uint16_t addIeLen) +{ + tDot11fTDLSDisRsp tdlsDisRsp; + uint16_t caps = 0; + uint32_t status = 0; + uint32_t nPayload = 0; + uint32_t nBytes = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; + uint32_t 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_t tdlsChannelBondingMode; */ + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + lim_log(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 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + cdf_mem_set((uint8_t *) &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; + + populate_dot11f_link_iden(pMac, psessionEntry, + &tdlsDisRsp.LinkIdentifier, + peerMac, TDLS_RESPONDER); + + if (cfg_get_capability_info(pMac, &caps, psessionEntry) + != eSIR_SUCCESS) { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve Capabilities value")); + } + swap_bit_field16(caps, (uint16_t *) &tdlsDisRsp.Capabilities); + + /* populate supported rate and ext supported rate IE */ + if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac, + &tdlsDisRsp.SuppRates, + &tdlsDisRsp.ExtSuppRates)) + lim_log(pMac, LOGE, + FL("could not populate supported data rates")); + + /* populate extended capability IE */ + populate_dot11f_tdls_ext_capability(pMac, + psessionEntry, + &tdlsDisRsp.ExtCap); + + wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + populate_dot11f_tdls_ht_vht_cap(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)) { + populate_dot11f_tdls_offchannel_params(pMac, psessionEntry, + &tdlsDisRsp.SuppChannels, + &tdlsDisRsp. + SuppOperatingClasses); + if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) { + tdlsDisRsp.ht2040_bss_coexistence.present = 1; + tdlsDisRsp.ht2040_bss_coexistence.info_request = 1; + } + } else { + lim_log(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 = dot11f_get_packed_tdls_dis_rsp_size(pMac, &tdlsDisRsp, &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(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)) { + lim_log(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 */ + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL( + "Failed to allocate %d bytes for a TDLS Discovery Request." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * response frame + */ + + /* Make public Action Frame */ + + lim_populate_mac_header(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; + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + } + + status = dot11f_pack_tdls_dis_rsp(pMac, &tdlsDisRsp, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL( + "Failed to pack a TDLS discovery response (0x%08x)." + ), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL( + "There were warnings while packing TDLS Discovery Response (0x%08x)." + ), + status); + } + if (0 != addIeLen) { + lim_log(pMac, LOG1, + FL("Copy Additional Ie Len = %d"), addIeLen); + cdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, addIe, + addIeLen); + } + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -DIRECT-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_DIS_RSP, + lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_RSP), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + /* + * Transmit Discovery response and watch if this is delivered to + * peer STA. + */ + /* In CLD 2.0, pass Discovery Response as mgmt frame so that + * wma does not do header conversion to 802.3 before calling tx/rx + * routine and subsequenly target also sends frame as is OTA + */ + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_IBSS, + 0, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_SELF_STA_REQUESTED_MASK, + smeSessionId, false, 0); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(pMac, LOGE, + FL("could not send TDLS Discovery Response frame!")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} + +/* + * This static function is currently used by lim_send_tdls_link_setup_req_frame and + * lim_send_tdls_setup_rsp_frame to populate the AID if device is 11ac capable. + */ +static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t 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)) { + + uint16_t aid; + tpDphHashNode pStaDs; + + pStaDs = + dph_lookup_hash_entry(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; + lim_log(pMac, LOGE, + FL("pStaDs is NULL for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(peerMac)); + } + } + } else { + Aid->present = 0; + lim_log(pMac, LOGW, FL("Vht not enable from ini for 2.4GHz.")); + } +} + +/* + * TDLS setup Request frame on AP link + */ + +tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, uint8_t dialog, + tpPESession psessionEntry, + uint8_t *addIe, uint16_t addIeLen) +{ + tDot11fTDLSSetupReq tdlsSetupReq; + uint16_t caps = 0; + uint32_t status = 0; + uint32_t nPayload = 0; + uint32_t nBytes = 0; + uint32_t header_offset = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; + uint32_t selfDot11Mode; + uint8_t 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_t tdlsChannelBondingMode; */ + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &tdlsSetupReq, sizeof(tDot11fTDLSSetupReq), 0); + tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS; + tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ; + tdlsSetupReq.DialogToken.token = dialog; + + populate_dot11f_link_iden(pMac, psessionEntry, + &tdlsSetupReq.LinkIdentifier, peerMac, + TDLS_INITIATOR); + + if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve Capabilities value")); + } + swap_bit_field16(caps, (uint16_t *) &tdlsSetupReq.Capabilities); + + /* populate supported rate and ext supported rate IE */ + if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac, + &tdlsSetupReq.SuppRates, + &tdlsSetupReq.ExtSuppRates)) + lim_log(pMac, LOGE, + FL("could not populate supported data rates")); + + /* Populate extended capability IE */ + populate_dot11f_tdls_ext_capability(pMac, + psessionEntry, + &tdlsSetupReq.ExtCap); + + if (1 == pMac->lim.gLimTDLSWmmMode) { + uint32_t val = 0; + + lim_log(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_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != + eSIR_SUCCESS) + lim_log(pMac, LOGE, + FL("could not retrieve Max SP Length")); + + tdlsSetupReq.WMMInfoStation.max_sp_length = (uint8_t) 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, since populate_dot11f_qos_caps_station() + * depends on AP's capability, and TDLS doesn't want to depend + * on AP's capability + */ + + lim_log(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_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupReq.HTCaps, + &tdlsSetupReq.VHTCaps, psessionEntry); + + /* Populate AID */ + populate_dotf_tdls_vht_aid(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)) { + populate_dot11f_tdls_offchannel_params(pMac, psessionEntry, + &tdlsSetupReq.SuppChannels, + &tdlsSetupReq. + SuppOperatingClasses); + if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) { + tdlsSetupReq.ht2040_bss_coexistence.present = 1; + tdlsSetupReq.ht2040_bss_coexistence.info_request = 1; + } + } else { + lim_log(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 = dot11f_get_packed_tdls_setup_req_size(pMac, &tdlsSetupReq, + &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(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)) { + lim_log(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 */ + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL( + "Failed to allocate %d bytes for a TDLS Setup Request." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET + (tdlsSetupReq), TDLS_LINK_AP, + TDLS_INITIATOR, TID_AC_BK, + psessionEntry); + + lim_log(pMac, LOGW, + FL( + "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x" + ), + tdlsSetupReq.VHTCaps.supportedChannelWidthSet, + tdlsSetupReq.VHTCaps.rxMCSMap, + tdlsSetupReq.VHTCaps.txMCSMap, + tdlsSetupReq.VHTCaps.txSupDataRate); + + status = dot11f_pack_tdls_setup_req(pMac, &tdlsSetupReq, pFrame + + header_offset, nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to pack a TDLS Setup request (0x%08x)."), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(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) { + lim_log(pMac, LOG1, FL("Copy Additional Ie Len = %d"), + addIeLen); + cdf_mem_copy(pFrame + header_offset + nPayload, addIe, + addIeLen); + } + + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_REQ, + lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_REQ), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_BK, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false, 0); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(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 lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, uint16_t reason, + uint8_t responder, + tpPESession psessionEntry, + uint8_t *addIe, uint16_t addIeLen) +{ + tDot11fTDLSTeardown teardown; + uint32_t status = 0; + uint32_t nPayload = 0; + uint32_t nBytes = 0; + uint32_t header_offset = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + uint32_t padLen = 0; +#endif + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + lim_log(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 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + cdf_mem_set((uint8_t *) &teardown, sizeof(tDot11fTDLSTeardown), 0); + teardown.Category.category = SIR_MAC_ACTION_TDLS; + teardown.Action.action = SIR_MAC_TDLS_TEARDOWN; + teardown.Reason.code = reason; + + populate_dot11f_link_iden(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 = dot11f_get_packed_tdls_teardown_size(pMac, &teardown, &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(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(tDot11fProbeRequest); + } else if (DOT11F_WARNED(status)) { + lim_log(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 + 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 */ + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL( + "Failed to allocate %d bytes for a TDLS Teardown Frame." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + lim_log(pMac, LOGE, FL("Reason of TDLS Teardown: %d"), reason); + header_offset = lim_prepare_tdls_frame_header(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 = dot11f_pack_tdls_teardown(pMac, &teardown, pFrame + + header_offset, nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to pack a TDLS Teardown frame (0x%08x)."), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL( + "There were warnings while packing TDLS Teardown frame (0x%08x)." + ), + status); + } + + if (addIeLen != 0) { + lim_log(pMac, LOGW, + FL("Copy Additional Ie Len = %d"), addIeLen); + cdf_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 }; */ + uint8_t *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; + + lim_log(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) + cdf_mem_set(pFrame + header_offset + nPayload + + addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -%s-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_TEARDOWN, + lim_trace_tdls_action_string(SIR_MAC_TDLS_TEARDOWN), + ((reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? "AP" : + "DIRECT"), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false, 0); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(pMac, LOGE, + FL("could not send TDLS Teardown frame")); + return eSIR_FAILURE; + + } + return eSIR_SUCCESS; + +} + +/* + * Send Setup RSP frame on AP link. + */ +static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, + uint8_t dialog, + tpPESession psessionEntry, + etdlsLinkSetupStatus setupStatus, + uint8_t *addIe, + uint16_t addIeLen) +{ + tDot11fTDLSSetupRsp tdlsSetupRsp; + uint32_t status = 0; + uint16_t caps = 0; + uint32_t nPayload = 0; + uint32_t header_offset = 0; + uint32_t nBytes = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; + uint32_t 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_t tdlsChannelBondingMode; */ + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + lim_log(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 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + cdf_mem_set((uint8_t *) &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; + + populate_dot11f_link_iden(pMac, psessionEntry, + &tdlsSetupRsp.LinkIdentifier, peerMac, + TDLS_RESPONDER); + + if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { + /* + * Could not get Capabilities value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve Capabilities value")); + } + swap_bit_field16(caps, (uint16_t *) &tdlsSetupRsp.Capabilities); + + /* populate supported rate and ext supported rate IE */ + if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac, + &tdlsSetupRsp.SuppRates, + &tdlsSetupRsp.ExtSuppRates)) + lim_log(pMac, LOGE, + FL("could not populate supported data rates")); + + /* Populate extended capability IE */ + populate_dot11f_tdls_ext_capability(pMac, + psessionEntry, + &tdlsSetupRsp.ExtCap); + + if (1 == pMac->lim.gLimTDLSWmmMode) { + uint32_t val = 0; + + lim_log(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_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != + eSIR_SUCCESS) + lim_log(pMac, LOGE, + FL("could not retrieve Max SP Length")); + tdlsSetupRsp.WMMInfoStation.max_sp_length = (uint8_t) 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 + * populate_dot11f_qos_caps_station() depends on AP's + * capability, and TDLS doesn't want to depend on AP's + * capability + */ + lim_log(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_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode); + + /* Populate HT/VHT Capabilities */ + populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupRsp.HTCaps, + &tdlsSetupRsp.VHTCaps, psessionEntry); + + /* Populate AID */ + populate_dotf_tdls_vht_aid(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)) { + populate_dot11f_tdls_offchannel_params(pMac, psessionEntry, + &tdlsSetupRsp.SuppChannels, + &tdlsSetupRsp. + SuppOperatingClasses); + if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) { + tdlsSetupRsp.ht2040_bss_coexistence.present = 1; + tdlsSetupRsp.ht2040_bss_coexistence.info_request = 1; + } + } else { + lim_log(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 = dot11f_get_packed_tdls_setup_rsp_size(pMac, &tdlsSetupRsp, + &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(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)) { + lim_log(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 */ + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL( + "Failed to allocate %d bytes for a TDLS Setup Response." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET + (tdlsSetupRsp), TDLS_LINK_AP, + TDLS_RESPONDER, TID_AC_BK, + psessionEntry); + + lim_log(pMac, LOG1, + FL( + "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x" + ), + tdlsSetupRsp.VHTCaps.supportedChannelWidthSet, + tdlsSetupRsp.VHTCaps.rxMCSMap, + tdlsSetupRsp.VHTCaps.txMCSMap, + tdlsSetupRsp.VHTCaps.txSupDataRate); + status = dot11f_pack_tdls_setup_rsp(pMac, &tdlsSetupRsp, + pFrame + header_offset, + nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to pack a TDLS Setup Response (0x%08x)."), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(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) { + cdf_mem_copy(pFrame + header_offset + nPayload, addIe, + addIeLen); + } + + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_RSP, + lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_RSP), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_BK, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false, 0); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(pMac, LOGE, + FL("could not send TDLS Dis Request frame!")); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} + +/* + * Send TDLS setup CNF frame on AP link + */ + +tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, + uint8_t dialog, + uint32_t peerCapability, + tpPESession psessionEntry, + uint8_t *addIe, uint16_t addIeLen) +{ + tDot11fTDLSSetupCnf tdlsSetupCnf; + uint32_t status = 0; + uint32_t nPayload = 0; + uint32_t nBytes = 0; + uint32_t header_offset = 0; + uint8_t *pFrame; + void *pPacket; + CDF_STATUS cdf_status; +#ifndef NO_PAD_TDLS_MIN_8023_SIZE + uint32_t padLen = 0; +#endif + uint8_t smeSessionId = 0; + + /* + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &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; + + populate_dot11f_link_iden(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))) { + lim_log(pMac, LOG1, FL("populate WMM praram in Setup Confirm")); + populate_dot11f_wmm_params(pMac, &tdlsSetupCnf.WMMParams, + psessionEntry); + } + + /* Check peer is VHT capable */ + if (CHECK_BIT(peerCapability, TDLS_PEER_VHT_CAP)) { + populate_dot11f_vht_operation(pMac, + psessionEntry, + &tdlsSetupCnf.VHTOperation); + populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry); + } else if (CHECK_BIT(peerCapability, TDLS_PEER_HT_CAP)) { /* Check peer is HT capable */ + populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry); + } + + /* + * now we pack it. First, how much space are we going to need? + */ + status = dot11f_get_packed_tdls_setup_cnf_size(pMac, &tdlsSetupCnf, + &nPayload); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL( + "Failed to calculate the packed size for a Setup Confirm (0x%08x)." + ), + status); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof(tDot11fProbeRequest); + } else if (DOT11F_WARNED(status)) { + lim_log(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 */ + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL( + "Failed to allocate %d bytes for a TDLS Setup Confirm." + ), + nBytes); + return eSIR_MEM_ALLOC_FAILED; + } + + /* zero out the memory */ + cdf_mem_set(pFrame, nBytes, 0); + + /* + * IE formation, memory allocation is completed, Now form TDLS discovery + * request frame + */ + + /* fill out the buffer descriptor */ + + header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, + LINK_IDEN_ADDR_OFFSET + (tdlsSetupCnf), TDLS_LINK_AP, + TDLS_INITIATOR, TID_AC_VI, + psessionEntry); + + status = dot11f_pack_tdls_setup_cnf(pMac, &tdlsSetupCnf, pFrame + + header_offset, nPayload, &nPayload); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to pack a TDLS discovery req (0x%08x)."), + status); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL( + "There were warnings while packing TDLS Discovery 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) { + cdf_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 }; */ + uint8_t *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; + + lim_log(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) + cdf_mem_set(pFrame + header_offset + nPayload + + addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE, + padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0); + } +#endif + + lim_log(pMac, LOG1, + FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), + SIR_MAC_TDLS_SETUP_CNF, + lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_CNF), + MAC_ADDR_ARRAY(peerMac)); + + pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; + + cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_DATA, + ANI_TXDIR_TODS, + TID_AC_VI, + lim_tx_complete, pFrame, + lim_mgmt_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false, 0); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->lim.mgmtFrameSessionId = 0xff; + lim_log(pMac, LOGE, + FL("could not send TDLS Setup Confirm frame")); + return eSIR_FAILURE; + + } + + return eSIR_SUCCESS; +} + +/* This Function is similar to populate_dot11f_ht_caps, except that the HT Capabilities + * are considered from the AddStaReq rather from the cfg.dat as in populate_dot11f_ht_caps + */ +static tSirRetStatus lim_tdls_populate_dot11f_ht_caps(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirTdlsAddStaReq * + pTdlsAddStaReq, + tDot11fIEHTCaps *pDot11f) +{ + uint32_t nCfgValue; + uint8_t nCfgValue8; + tSirMacHTParametersInfo *pHTParametersInfo; + union { + uint16_t 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 + * Only in case of NO session + */ + if (psessionEntry == NULL) { + 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; + } + + lim_log(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 = (uint8_t) nCfgValue; + pHTParametersInfo = (tSirMacHTParametersInfo *) &nCfgValue8; + + pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor; + pDot11f->mpduDensity = pHTParametersInfo->mpduDensity; + pDot11f->reserved1 = pHTParametersInfo->reserved; + + lim_log(pMac, LOG1, FL("AMPDU Param: %x"), nCfgValue); + + cdf_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 = (uint8_t) 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 +lim_tdls_populate_dot11f_vht_caps(tpAniSirGlobal pMac, + tSirTdlsAddStaReq *pTdlsAddStaReq, + tDot11fIEVHTCaps *pDot11f) +{ + uint32_t nCfgValue = 0; + union { + uint32_t nCfgValue32; + tSirMacVHTCapabilityInfo vhtCapInfo; + } uVHTCapabilityInfo; + union { + uint16_t 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; + + lim_log_vht_cap(pMac, pDot11f); + + return eSIR_SUCCESS; + +} + +/** + * lim_tdls_populate_matching_rate_set() - populate matching rate set + * + * @mac_ctx - global MAC context + * @stads - station hash entry + * @supp_rate_set - pointer to supported rate set + * @supp_rates_len - length of the supported rates + * @supp_mcs_set - pointer to supported MSC set + * @session_entry - pointer to PE session entry + * @vht_caps - pointer to VHT capability + * + * + * This function gets set of available rates from the config and compare them + * against the set of received supported rates. After the comparison station + * entry's rates is populated with 11A rates and 11B rates. + * + * Return: eSIR_SUCCESS on success, eSIR_FAILURE on failure. + */ +static tSirRetStatus +lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads, + uint8_t *supp_rate_set, + uint8_t supp_rates_len, + uint8_t *supp_mcs_set, + tpPESession session_entry, + tDot11fIEVHTCaps *vht_caps) +{ + tSirMacRateSet temp_rate_set; + uint32_t i, j, val, min, is_a_rate; + tSirMacRateSet temp_rate_set2; + uint32_t phymode; + uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET]; + tpSirSupportedRates rates; + uint8_t a_rateindex = 0; + uint8_t b_rateindex = 0; + is_a_rate = 0; + temp_rate_set2.numRates = 0; + + lim_get_phy_mode(mac_ctx, &phymode, NULL); + + /* get own rate set */ + val = WNI_CFG_OPERATIONAL_RATE_SET_LEN; + if (wlan_cfg_get_str(mac_ctx, WNI_CFG_OPERATIONAL_RATE_SET, + (uint8_t *) &temp_rate_set.rate, + &val) != eSIR_SUCCESS) { + /* Could not get rateset from CFG. Log error. */ + lim_log(mac_ctx, LOGE, FL("could not retrieve rateset")); + val = 0; + } + temp_rate_set.numRates = val; + + if (phymode == WNI_CFG_PHY_MODE_11G) { + /* get own extended rate set */ + val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN; + if (wlan_cfg_get_str(mac_ctx, + WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + (uint8_t *) &temp_rate_set2.rate, + &val) != eSIR_SUCCESS) + temp_rate_set2.numRates = val; + } + + if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) { + lim_log(mac_ctx, 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 temp_rate_set, there are 12 rates max */ + for (i = 0; i < temp_rate_set2.numRates; i++) + temp_rate_set.rate[i + temp_rate_set.numRates] = + temp_rate_set2.rate[i]; + + temp_rate_set.numRates += temp_rate_set2.numRates; + + /** + * Sort rates in temp_rate_set (they are likely to be already sorted) + * put the result in temp_rate_set2 + */ + temp_rate_set2.numRates = 0; + + for (i = 0; i < temp_rate_set.numRates; i++) { + min = 0; + val = 0xff; + + for (j = 0; j < temp_rate_set.numRates; j++) + if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) { + val = temp_rate_set.rate[j] & 0x7f; + min = j; + } + + temp_rate_set2.rate[temp_rate_set2.numRates++] = + temp_rate_set.rate[min]; + temp_rate_set.rate[min] = 0xff; + } + + /** + * Copy received rates in temp_rate_set, the parser has ensured + * unicity of the rates so there cannot be more than 12 . + */ + if (supp_rates_len > SIR_MAC_RATESET_EID_MAX) { + lim_log(mac_ctx, LOGW, + FL( + "Supported rates length %d more than the Max limit, reset to Max" + ), + supp_rates_len); + supp_rates_len = SIR_MAC_RATESET_EID_MAX; + } + + for (i = 0; i < supp_rates_len; i++) + temp_rate_set.rate[i] = supp_rate_set[i]; + + temp_rate_set.numRates = supp_rates_len; + + rates = &stads->supportedRates; + cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0); + + for (i = 0; i < temp_rate_set2.numRates; i++) { + for (j = 0; j < temp_rate_set.numRates; j++) { + if ((temp_rate_set2.rate[i] & 0x7F) != + (temp_rate_set.rate[j] & 0x7F)) + continue; + +#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC + if ((b_rateindex > HAL_NUM_11B_RATES) || + (a_rateindex > HAL_NUM_11A_RATES)) { + lim_log(mac_ctx, LOGE, + FL("Invalid number of rates (11b->%d, 11a->%d)"), + b_rateindex, a_rateindex); + return eSIR_FAILURE; + } +#endif + if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) { + is_a_rate = 1; + if (a_rateindex < SIR_NUM_11A_RATES) + rates->llaRates[a_rateindex++] = temp_rate_set2.rate[i]; + } else { + if (b_rateindex < SIR_NUM_11B_RATES) + rates->llbRates[b_rateindex++] = temp_rate_set2.rate[i]; + } + break; + } + } + + /* compute the matching MCS rate set, if peer is 11n capable and self mode is 11n */ +#ifdef FEATURE_WLAN_TDLS + if (stads->mlmStaContext.htCapability) +#else + if (IS_DOT11_MODE_HT(session_entry->dot11mode) && + (stads->mlmStaContext.htCapability)) +#endif + { + val = SIZE_OF_SUPPORTED_MCS_SET; + if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET, + mcsSet, &val) != eSIR_SUCCESS) { + /* Could not get rateset from CFG. Log error. */ + lim_log(mac_ctx, LOGP, + FL("could not retrieve supportedMCSSet")); + goto error; + } + + for (i = 0; i < val; i++) + stads->supportedRates.supportedMCSSet[i] = + mcsSet[i] & supp_mcs_set[i]; + + lim_log(mac_ctx, LOG1, + FL("MCS Rate Set Bitmap from CFG and DPH")); + for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) { + lim_log(mac_ctx, LOG1, FL("%x %x"), mcsSet[i], + stads->supportedRates.supportedMCSSet[i]); + } + } +#ifdef WLAN_FEATURE_11AC + lim_populate_vht_mcs_set(mac_ctx, &stads->supportedRates, vht_caps, + session_entry); +#endif + /** + * Set the erpEnabled bit if the phy is in G mode and at least + * one A rate is supported + */ + if ((phymode == WNI_CFG_PHY_MODE_11G) && is_a_rate) + stads->erpEnabled = eHAL_SET; + + return eSIR_SUCCESS; + +error: + return eSIR_FAILURE; +} + +/* + * update HASH node entry info + */ +static void lim_tdls_update_hash_node_info(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; + uint8_t cbMode; +#endif + tpDphHashNode pSessStaDs = NULL; + uint16_t aid; + + if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_ADD) { + populate_dot11f_ht_caps(pMac, psessionEntry, &htCap); + } else if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE) { + lim_tdls_populate_dot11f_ht_caps(pMac, NULL, pTdlsAddStaReq, &htCap); + } + htCaps = &htCap; + if (htCaps->present) { + pStaDs->mlmStaContext.htCapability = 1; + pStaDs->htGreenfield = htCaps->greenField; + pStaDs->htSupportedChannelWidthSet = + htCaps->supportedChannelWidthSet; + 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; + lim_fill_rx_highest_supported_rate(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 + lim_tdls_populate_dot11f_vht_caps(pMac, pTdlsAddStaReq, &vhtCap); + pVhtCaps = &vhtCap; + if (pVhtCaps->present) { + pStaDs->mlmStaContext.vhtCapability = 1; + + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) { + /* + * if the channel is 2G then update the min channel + * widthset in pStaDs. These values are used when + * sending a AddSta request to firmware + * 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. + */ + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + lim_log(pMac, LOG1, FL("vhtSupportedChannelWidthSet = %hu, htSupportedChannelWidthSet %hu"), + pStaDs->htSupportedChannelWidthSet, + pStaDs->htSupportedChannelWidthSet); + } else { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } + + 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 = lim_select_cb_mode(pStaDs, psessionEntry, + psessionEntry->currentOperChannel, + pStaDs->vhtSupportedChannelWidthSet); + + pStaDs->htSecondaryChannelOffset = cbMode; + +#ifdef WLAN_FEATURE_11AC + if (pStaDs->mlmStaContext.vhtCapability) { + pStaDs->htSecondaryChannelOffset = lim_get_htcb_state(cbMode); + } +#endif + + pSessStaDs = dph_lookup_hash_entry(pMac, psessionEntry->bssId, &aid, + &psessionEntry->dph.dphHashTable); + + /* Lets enable QOS parameter */ + pStaDs->qosMode = 1; + 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 ?? + */ + lim_tdls_populate_matching_rate_set(pMac, pStaDs, + pTdlsAddStaReq->supported_rates, + pTdlsAddStaReq->supported_rates_length, + (uint8_t *) 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 lim_tdls_setup_add_sta(tpAniSirGlobal pMac, + tSirTdlsAddStaReq *pAddStaReq, + tpPESession psessionEntry) +{ + tpDphHashNode pStaDs = NULL; + tSirRetStatus status = eSIR_SUCCESS; + uint16_t aid = 0; + + pStaDs = dph_lookup_hash_entry(pMac, pAddStaReq->peerMac, &aid, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) { + aid = lim_assign_peer_idx(pMac, psessionEntry); + + if (!aid) { + lim_log(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); + + lim_log(pMac, LOG1, FL("Aid = %d, for peer =" MAC_ADDRESS_STR), + aid, MAC_ADDR_ARRAY(pAddStaReq->peerMac)); + pStaDs = + dph_get_hash_entry(pMac, aid, + &psessionEntry->dph.dphHashTable); + + if (pStaDs) { + (void)lim_del_sta(pMac, pStaDs, false /*asynchronous */, + psessionEntry); + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, aid, + psessionEntry); + } + + pStaDs = dph_add_hash_entry(pMac, pAddStaReq->peerMac, aid, + &psessionEntry->dph.dphHashTable); + + if (NULL == pStaDs) { + lim_log(pMac, LOGE, FL("add hash entry failed")); + CDF_ASSERT(0); + return eSIR_FAILURE; + } + } + + lim_tdls_update_hash_node_info(pMac, pStaDs, pAddStaReq, psessionEntry); + + pStaDs->staType = STA_ENTRY_TDLS_PEER; + + status = + lim_add_sta(pMac, pStaDs, + (pAddStaReq->tdlsAddOper == + TDLS_OPER_UPDATE) ? true : false, psessionEntry); + + if (eSIR_SUCCESS != status) { + /* should not fail */ + CDF_ASSERT(0); + } + return status; +} + +/* + * Del STA, after Link is teardown or discovery response sent on direct link + */ +static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac, tSirMacAddr peerMac, + tpPESession psessionEntry) +{ + tSirRetStatus status = eSIR_SUCCESS; + uint16_t peerIdx = 0; + tpDphHashNode pStaDs = NULL; + + pStaDs = dph_lookup_hash_entry(pMac, peerMac, &peerIdx, + &psessionEntry->dph.dphHashTable); + + if (pStaDs) { + + lim_log(pMac, LOG1, FL("DEL STA peer MAC: "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pStaDs->staAddr)); + + lim_log(pMac, LOG1, FL("STA type = %x, sta idx = %x"), + pStaDs->staType, + pStaDs->staIndex); + + status = lim_del_sta(pMac, pStaDs, false, psessionEntry); + } + + return pStaDs; +} + +/* + * Once Link is setup with PEER, send Add STA ind to SME + */ +static CDF_STATUS lim_send_sme_tdls_add_sta_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirMacAddr peerMac, + uint8_t updateSta, + tDphHashNode *pStaDs, uint8_t status) +{ + tSirMsgQ mmhMsg = { 0 }; + tSirTdlsAddStaRsp *addStaRsp = NULL; + mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP; + + addStaRsp = cdf_mem_malloc(sizeof(tSirTdlsAddStaRsp)); + if (NULL == addStaRsp) { + lim_log(pMac, LOGE, FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + + addStaRsp->sessionId = sessionId; + addStaRsp->statusCode = status; + if (pStaDs) { + addStaRsp->staId = pStaDs->staIndex; + addStaRsp->ucastSig = pStaDs->ucUcastSig; + addStaRsp->bcastSig = pStaDs->ucBcastSig; + } + if (peerMac) { + cdf_mem_copy(addStaRsp->peerMac, + (uint8_t *) 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; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return CDF_STATUS_SUCCESS; + +} + +/* + * STA RSP received from HAL + */ +CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, + tpPESession psessionEntry) +{ + tAddStaParams *pAddStaParams = (tAddStaParams *) msg; + uint8_t status = eSIR_SUCCESS; + tDphHashNode *pStaDs = NULL; + uint16_t aid = 0; + + SET_LIM_PROCESS_DEFD_MESGS(pMac, true); + lim_log(pMac, LOG1, FL("staIdx=%d, staMac="MAC_ADDRESS_STR), + pAddStaParams->staIdx, + MAC_ADDR_ARRAY(pAddStaParams->staMac)); + + if (pAddStaParams->status != CDF_STATUS_SUCCESS) { + CDF_ASSERT(0); + lim_log(pMac, LOGE, FL("Add sta failed ")); + status = eSIR_FAILURE; + goto add_sta_error; + } + + pStaDs = dph_lookup_hash_entry(pMac, pAddStaParams->staMac, &aid, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) { + lim_log(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 = lim_send_sme_tdls_add_sta_rsp(pMac, psessionEntry->smeSessionId, + pAddStaParams->staMac, + pAddStaParams->updateSta, pStaDs, + status); + cdf_mem_free(pAddStaParams); + return status; +} + +void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIESuppChannels *suppChannels, + tDot11fIESuppOperatingClasses * + suppOperClasses) +{ + uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; + uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint8_t i; + uint8_t valid_count = 0; + uint8_t chanOffset; + uint8_t op_class; + uint8_t numClasses; + uint8_t classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; + if (wlan_cfg_get_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, + validChan, &numChans) != eSIR_SUCCESS) { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve Valid channel list")); + return; + } + + /* validating the channel list for DFS channels */ + for (i = 0U; i < numChans; i++) { + if (CHANNEL_STATE_DFS == + cds_get_channel_state(validChan[i])) { + lim_log(pMac, LOG1, + FL( + "skipping DFS channel %d from the valid channel list" + ), + validChan[i]); + continue; + } + + if (valid_count >= ARRAY_SIZE(suppChannels->bands)) + 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 = cds_regdm_get_opclass_from_channel( + pMac->scan.countryCodeCurrent, + psessionEntry->currentOperChannel, + chanOffset); + + if (op_class == 0) { + lim_log(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 { + lim_log(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; + + cds_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 populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry, + tDot11fIELinkIdentifier *linkIden, + tSirMacAddr peerMac, uint8_t reqType) +{ + uint8_t *initStaAddr = NULL; + uint8_t *respStaAddr = NULL; + + (reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr), + (respStaAddr = linkIden->RespStaAddr)) + : ((respStaAddr = linkIden->InitStaAddr), + (initStaAddr = linkIden->RespStaAddr)); + cdf_mem_copy((uint8_t *) linkIden->bssid, + (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) initStaAddr, + psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) respStaAddr, (uint8_t *) peerMac, + sizeof(tSirMacAddr)); + + linkIden->present = 1; + return; + +} + +void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEExtCap *extCapability) +{ + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes; + + p_ext_cap->tdls_peer_psm_supp = PEER_PSM_SUPPORT; + p_ext_cap->tdls_peer_uapsd_buffer_sta = 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->tdls_channel_switching = 1; + p_ext_cap->tdls_chan_swit_prohibited = 0; + } else { + p_ext_cap->tdls_channel_switching = 0; + p_ext_cap->tdls_chan_swit_prohibited = TDLS_CH_SWITCH_PROHIBITED; + } + p_ext_cap->tdls_support = TDLS_SUPPORT; + p_ext_cap->tdls_prohibited = TDLS_PROHIBITED; + + extCapability->present = 1; + /* For STA cases we alwasy support 11mc - Allow MAX length */ + extCapability->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + + return; +} + +/** + * lim_process_sme_tdls_mgmt_send_req() - send out tdls management frames + * + * @mac_ctx - global mac context + * @msg - message buffer received from SME. + * + * Process Send Mgmt Request from SME and transmit to AP. + * + * Return: eSIR_SUCCESS on success, error code otherwise + */ +tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, + uint32_t *msg) +{ + /* get all discovery request parameters */ + tSirTdlsSendMgmtReq *send_req = (tSirTdlsSendMgmtReq *) msg; + tpPESession session_entry; + uint8_t session_id; + tSirResultCodes result_code = eSIR_SME_INVALID_PARAMETERS; + + lim_log(mac_ctx, LOG1, FL("Send Mgmt Recieved")); + session_entry = pe_find_session_by_bssid(mac_ctx, + send_req->bssid, &session_id); + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, + FL("PE Session does not exist for given sme session_id %d"), + send_req->sessionId); + goto lim_tdls_send_mgmt_error; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(session_entry)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("send mgmt received in wrong system Role %d"), + GET_LIM_SYSTEM_ROLE(session_entry)); + 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 ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) { + lim_log(mac_ctx, LOGE, + FL("send mgmt received in invalid LIMsme state (%d)"), + session_entry->limSmeState); + goto lim_tdls_send_mgmt_error; + } + + switch (send_req->reqType) { + case SIR_MAC_TDLS_DIS_REQ: + lim_log(mac_ctx, LOG1, FL("Transmit Discovery Request Frame")); + /* format TDLS discovery request frame and transmit it */ + lim_send_tdls_dis_req_frame(mac_ctx, send_req->peerMac, + send_req->dialog, session_entry); + result_code = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_DIS_RSP: + lim_log(mac_ctx, LOG1, FL("Transmit Discovery Response Frame")); + /* Send a response mgmt action frame */ + lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peerMac, + send_req->dialog, session_entry, &send_req->addIe[0], + (send_req->length - sizeof(tSirTdlsSendMgmtReq))); + result_code = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_SETUP_REQ: + lim_log(mac_ctx, LOG1, FL("Transmit Setup Request Frame")); + lim_send_tdls_link_setup_req_frame(mac_ctx, + send_req->peerMac, send_req->dialog, session_entry, + &send_req->addIe[0], + (send_req->length - sizeof(tSirTdlsSendMgmtReq))); + result_code = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_SETUP_RSP: + lim_log(mac_ctx, LOG1, FL("Transmit Setup Response Frame")); + lim_send_tdls_setup_rsp_frame(mac_ctx, + send_req->peerMac, send_req->dialog, session_entry, + send_req->statusCode, &send_req->addIe[0], + (send_req->length - sizeof(tSirTdlsSendMgmtReq))); + result_code = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_SETUP_CNF: + lim_log(mac_ctx, LOG1, FL("Transmit Setup Confirm Frame")); + lim_send_tdls_link_setup_cnf_frame(mac_ctx, + send_req->peerMac, send_req->dialog, + send_req->peerCapability, session_entry, + &send_req->addIe[0], + (send_req->length - sizeof(tSirTdlsSendMgmtReq))); + result_code = eSIR_SME_SUCCESS; + break; + case SIR_MAC_TDLS_TEARDOWN: + lim_log(mac_ctx, LOG1, FL("Transmit Teardown Frame")); + lim_send_tdls_teardown_frame(mac_ctx, + send_req->peerMac, send_req->statusCode, + send_req->responder, session_entry, + &send_req->addIe[0], + (send_req->length - sizeof(tSirTdlsSendMgmtReq))); + result_code = 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: + lim_send_sme_rsp(mac_ctx, eWNI_SME_TDLS_SEND_MGMT_RSP, + result_code, send_req->sessionId, + send_req->transactionId); + + return eSIR_SUCCESS; +} + +/* + * Send Response to Link Establish Request to SME + */ +void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, tSirMacAddr peerMac, + tDphHashNode *pStaDs, uint8_t status) +{ + tSirMsgQ mmhMsg = { 0 }; + + tSirTdlsLinkEstablishReqRsp *pTdlsLinkEstablishReqRsp = NULL; + + pTdlsLinkEstablishReqRsp = + cdf_mem_malloc(sizeof(tSirTdlsLinkEstablishReqRsp)); + if (NULL == pTdlsLinkEstablishReqRsp) { + lim_log(pMac, LOGE, FL("Failed to allocate memory")); + return; + } + pTdlsLinkEstablishReqRsp->statusCode = status; + if (peerMac) { + cdf_mem_copy(pTdlsLinkEstablishReqRsp->peerMac, peerMac, + sizeof(tSirMacAddr)); + } + pTdlsLinkEstablishReqRsp->sessionId = sessionId; + mmhMsg.type = eWNI_SME_TDLS_LINK_ESTABLISH_RSP; + mmhMsg.bodyptr = pTdlsLinkEstablishReqRsp; + mmhMsg.bodyval = 0; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; + +} + +/* + * Once link is teardown, send Del Peer Ind to SME + */ +static CDF_STATUS lim_send_sme_tdls_del_sta_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirMacAddr peerMac, + tDphHashNode *pStaDs, uint8_t status) +{ + tSirMsgQ mmhMsg = { 0 }; + tSirTdlsDelStaRsp *pDelSta = NULL; + mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP; + + pDelSta = cdf_mem_malloc(sizeof(tSirTdlsDelStaRsp)); + if (NULL == pDelSta) { + lim_log(pMac, LOGE, FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + + pDelSta->sessionId = sessionId; + pDelSta->statusCode = status; + if (pStaDs) { + pDelSta->staId = pStaDs->staIndex; + } else + pDelSta->staId = STA_INVALID_IDX; + + if (peerMac) { + cdf_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; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return CDF_STATUS_SUCCESS; + +} + +/* + * Process Send Mgmt Request from SME and transmit to AP. + */ +tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf) +{ + /* get all discovery request parameters */ + tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq *) pMsgBuf; + tpPESession psessionEntry; + uint8_t sessionId; + + lim_log(pMac, LOG1, FL("TDLS Add STA Request Recieved")); + psessionEntry = + pe_find_session_by_bssid(pMac, pAddStaReq->bssid, &sessionId); + if (psessionEntry == NULL) { + lim_log(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)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_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)) { + + lim_log(pMac, LOGE, + FL("send mgmt 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 == lim_tdls_setup_add_sta(pMac, pAddStaReq, psessionEntry)) { + lim_log(pMac, LOGE, + FL("Add TDLS Station request failed")); + goto lim_tdls_add_sta_error; + } + return eSIR_SUCCESS; +lim_tdls_add_sta_error: + lim_send_sme_tdls_add_sta_rsp(pMac, + pAddStaReq->sessionId, pAddStaReq->peerMac, + (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE), + NULL, eSIR_FAILURE); + + return eSIR_SUCCESS; +} + +/* + * Process Del Sta Request from SME . + */ +tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf) +{ + /* get all discovery request parameters */ + tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq *) pMsgBuf; + tpPESession psessionEntry; + uint8_t sessionId; + tpDphHashNode pStaDs = NULL; + + lim_log(pMac, LOG1, FL("TDLS Delete STA Request Recieved")); + psessionEntry = + pe_find_session_by_bssid(pMac, pDelStaReq->bssid, &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL( + "PE Session does not exist for given sme sessionId %d" + ), + pDelStaReq->sessionId); + lim_send_sme_tdls_del_sta_rsp(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)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_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)) { + + lim_log(pMac, LOGE, + FL("Del Sta received in invalid LIMsme state (%d)"), + psessionEntry->limSmeState); + goto lim_tdls_del_sta_error; + } + + pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peerMac, psessionEntry); + + /* now send indication to SME-->HDD->TL to remove STA from TL */ + + if (pStaDs) { + lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId, + pDelStaReq->peerMac, pStaDs, + eSIR_SUCCESS); + lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry); + + /* Clear the aid in peerAIDBitmap as this aid is now in freepool */ + CLEAR_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, + pStaDs->assocId); + lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, pStaDs->assocId, + psessionEntry); + + return eSIR_SUCCESS; + + } + +lim_tdls_del_sta_error: + lim_send_sme_tdls_del_sta_rsp(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 uint8_t suffices */ +static void lim_tdls_get_intersection(uint8_t *input_array1, + uint8_t input1_length, + uint8_t *input_array2, + uint8_t input2_length, + uint8_t *output_array, + uint8_t *output_length) +{ + uint8_t i, j, k = 0, flag = 0; + for (i = 0; i < input1_length; i++) { + flag = 0; + for (j = 0; j < input2_length; j++) { + if (input_array1[i] == input_array2[j]) { + flag = 1; + break; + } + } + if (flag == 1) { + output_array[k] = input_array1[i]; + k++; + } + } + *output_length = k; +} + +/** + * lim_process_sme_tdls_link_establish_req() - process tdls link establishment + * request + * + * @mac_ctx - global MAC context + * @msg_buf - message buffer from SME + * + * Process Link Establishment Request from SME + * + * Return: eSIR_SUCCESS on success, failure code otherwise. + */ +tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + /* get all discovery request parameters */ + tSirTdlsLinkEstablishReq *tdls_req = + (tSirTdlsLinkEstablishReq *) msg_buf; + tpPESession session_entry; + uint8_t session_id; + tpTdlsLinkEstablishParams tdls_req_params; + tSirMsgQ msg; + uint16_t peer_idx = 0; + tpDphHashNode stads = NULL; + uint32_t self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN; + uint8_t self_supp_chan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("Send Mgmt Recieved")); + + session_entry = pe_find_session_by_bssid(mac_ctx, tdls_req->bssid, + &session_id); + if (NULL == session_entry) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("PE Session does not exist for sme session_id %d"), + tdls_req->sessionId); + lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, + tdls_req->sessionId, tdls_req->peerMac, NULL, + eSIR_FAILURE); + return eSIR_FAILURE; + } + + /* check if we are in proper state to work as TDLS client */ + if (!LIM_IS_STA_ROLE(session_entry)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("TDLS Link Establish Request received in wrong system Role %d"), + GET_LIM_SYSTEM_ROLE(session_entry)); + 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 ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && + (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) { + lim_log(mac_ctx, LOGE, + FL("TDLS Link Establish Request received in invalid LIMsme state (%d)"), + session_entry->limSmeState); + goto lim_tdls_link_establish_error; + } + + stads = dph_lookup_hash_entry(mac_ctx, tdls_req->peerMac, &peer_idx, + &session_entry->dph.dphHashTable); + if (NULL == stads) { + lim_log(mac_ctx, LOGE, FL("stads is NULL")); + goto lim_tdls_link_establish_error; + } + tdls_req_params = cdf_mem_malloc(sizeof(tTdlsLinkEstablishParams)); + if (NULL == tdls_req_params) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory TDLS Link Establish Request")); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) tdls_req_params, + sizeof(tTdlsLinkEstablishParams), 0); + + tdls_req_params->staIdx = stads->staIndex; + tdls_req_params->isResponder = tdls_req->isResponder; + tdls_req_params->uapsdQueues = tdls_req->uapsdQueues; + tdls_req_params->maxSp = tdls_req->maxSp; + tdls_req_params->isBufsta = tdls_req->isBufSta; + tdls_req_params->isOffChannelSupported = + tdls_req->isOffChannelSupported; + + if (0 == tdls_req->supportedChannelsLen) + goto send_tdls_establish_request; + + if (wlan_cfg_get_str(mac_ctx, WNI_CFG_VALID_CHANNEL_LIST, + self_supp_chan, + &self_num_chan) != eSIR_SUCCESS) { + /** + * Could not get Valid channel list from CFG. + * Log error. + */ + lim_log(mac_ctx, LOGE, + FL("could not retrieve Valid channel list")); + } + + if (self_num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + lim_log(mac_ctx, LOGE, + FL("Channel List more than Valid Channel list")); + self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + + if (tdls_req->supportedChannelsLen > SIR_MAC_MAX_SUPP_CHANNELS) { + lim_log(mac_ctx, LOGE, + FL("Channel List is more than the supported Channel list")); + tdls_req->supportedChannelsLen = SIR_MAC_MAX_SUPP_CHANNELS; + } + + lim_tdls_get_intersection(self_supp_chan, self_num_chan, + tdls_req->supportedChannels, tdls_req->supportedChannelsLen, + tdls_req_params->validChannels, + &tdls_req_params->validChannelsLen); + +send_tdls_establish_request: + cdf_mem_copy(tdls_req_params->validOperClasses, + tdls_req->supportedOperClasses, + tdls_req->supportedOperClassesLen); + tdls_req_params->validOperClassesLen = + tdls_req->supportedOperClassesLen; + + msg.type = WMA_SET_TDLS_LINK_ESTABLISH_REQ; + msg.reserved = 0; + msg.bodyptr = tdls_req_params; + msg.bodyval = 0; + if (eSIR_SUCCESS != wma_post_ctrl_msg(mac_ctx, &msg)) { + lim_log(mac_ctx, LOGE, FL("halPostMsgApi failed")); + goto lim_tdls_link_establish_error; + } + return eSIR_SUCCESS; + +lim_tdls_link_establish_error: + lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, + session_entry->smeSessionId, tdls_req->peerMac, NULL, + eSIR_FAILURE); + + return eSIR_SUCCESS; +} + +/** + * lim_delete_tdls_peers() - delete tdls peers + * + * @mac_ctx - global MAC context + * @session_entry - PE session entry + * + * Delete all the TDLS peer connected before leaving the BSS + * + * Return: eSIR_SUCCESS on success, error code otherwise + */ +tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, + tpPESession session_entry) +{ + tpDphHashNode stads = NULL; + int i, aid; + size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap); + + if (NULL == session_entry) { + lim_log(mac_ctx, LOGE, FL("NULL session_entry")); + return eSIR_FAILURE; + } + + /* + * Check all the set bit in peerAIDBitmap and delete the peer + * (with that aid) entry from the hash table and add the aid + * in free pool + */ + for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) { + for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) { + if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid)) + continue; + stads = dph_get_hash_entry(mac_ctx, + (aid + i * (sizeof(uint32_t) << 3)), + &session_entry->dph.dphHashTable); + + if (NULL != stads) { + lim_log(mac_ctx, LOGE, + FL("Deleting "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(stads->staAddr)); + + lim_send_deauth_mgmt_frame(mac_ctx, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, + stads->staAddr, session_entry, false); + dph_delete_hash_entry(mac_ctx, + stads->staAddr, stads->assocId, + &session_entry->dph.dphHashTable); + } + lim_release_peer_idx(mac_ctx, + (aid + i * (sizeof(uint32_t) << 3)), + session_entry); + CLEAR_BIT(session_entry->peerAIDBitmap[i], aid); + } + } + lim_send_sme_tdls_delete_all_peer_ind(mac_ctx, session_entry); + + return eSIR_SUCCESS; +} + +#endif diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c new file mode 100644 index 000000000000..d5349059edc6 --- /dev/null +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -0,0 +1,296 @@ +/* + * 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 lim_prop_exts_utils.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 "ani_global.h" +#include "wni_cfg.h" +#include "sir_common.h" +#include "sir_debug.h" +#include "utils_api.h" +#include "cfg_api.h" +#include "lim_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_trace.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#define LIM_GET_NOISE_MAX_TRY 5 +/** + * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability + * @mac_ctx: Pointer to Global MAC structure + * @p_ie: Pointer to starting IE in Beacon/Probe Response + * @ie_len: Length of all IEs combined + * @qos_cap: Bits are set according to capabilities + * @prop_cap: Pointer to prop info IE. + * @uapsd: pointer to uapsd + * @local_constraint: Pointer to local power constraint. + * @session: A pointer to session entry. + * + * This function is called to extract AP's HCF/WME/WSM capability + * from the IEs received from it in Beacon/Probe Response frames + * + * Return: None + */ +void +lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, + uint16_t ie_len, uint8_t *qos_cap, uint16_t *prop_cap, uint8_t *uapsd, + tPowerdBm *local_constraint, tpPESession session) +{ + tSirProbeRespBeacon *beacon_struct; +#if !defined WLAN_FEATURE_VOWIFI + uint32_t local_power_constraints = 0; +#endif + uint32_t enable_txbf_20mhz; + tSirRetStatus cfg_set_status = eSIR_FAILURE; + tSirRetStatus cfg_get_status = eSIR_FAILURE; + + beacon_struct = cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == beacon_struct) { + lim_log(mac_ctx, LOGE, FL("Unable to allocate memory")); + return; + } + + cdf_mem_set((uint8_t *) beacon_struct, sizeof(tSirProbeRespBeacon), 0); + *qos_cap = 0; + *prop_cap = 0; + *uapsd = 0; + lim_log(mac_ctx, LOG3, + FL("In lim_extract_ap_capability: The IE's being received:")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG3, p_ie, ie_len); + if (sir_parse_beacon_ie(mac_ctx, beacon_struct, p_ie, + (uint32_t) ie_len) == eSIR_SUCCESS) { + if (beacon_struct->wmeInfoPresent + || beacon_struct->wmeEdcaPresent) + LIM_BSS_CAPS_SET(WME, *qos_cap); + if (LIM_BSS_CAPS_GET(WME, *qos_cap) + && beacon_struct->wsmCapablePresent) + LIM_BSS_CAPS_SET(WSM, *qos_cap); + if (beacon_struct->propIEinfo.capabilityPresent) + *prop_cap = beacon_struct->propIEinfo.capability; + if (beacon_struct->HTCaps.present) + mac_ctx->lim.htCapabilityPresentInBeacon = 1; + else + mac_ctx->lim.htCapabilityPresentInBeacon = 0; + +#ifdef WLAN_FEATURE_11AC + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, + "beacon.VHTCaps.present = %d BSS_VHT_Capable:%d", + beacon_struct->VHTCaps.present, + IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps)); + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, + "***beacon.SU Beamformer Capable*****=%d", + beacon_struct->VHTCaps.suBeamFormerCap); + + if (IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps) && + beacon_struct->VHTOperation.present && + session->vhtCapability) { + session->vhtCapabilityPresentInBeacon = 1; + if (((beacon_struct->Vendor1IEPresent && + beacon_struct->vendor2_ie.present && + beacon_struct->Vendor3IEPresent)) && + (((beacon_struct->VHTCaps.txMCSMap & + VHT_MCS_3x3_MASK) == VHT_MCS_3x3_MASK) && + ((beacon_struct->VHTCaps.txMCSMap & + VHT_MCS_2x2_MASK) != VHT_MCS_2x2_MASK))) { + session->txBFIniFeatureEnabled = 0; + } + } else { + session->vhtCapabilityPresentInBeacon = 0; + } + if (session->vhtCapabilityPresentInBeacon == 1 && + session->txBFIniFeatureEnabled == 0) { + cfg_set_status = cfg_set_int(mac_ctx, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + 0); + if (cfg_set_status != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Set VHT_SU_BEAMFORMEE_CAP Fail")); + } + if (session->vhtCapabilityPresentInBeacon == 1 && + !session->htSupportedChannelWidthSet) { + cfg_get_status = wlan_cfg_get_int(mac_ctx, + WNI_CFG_VHT_ENABLE_TXBF_20MHZ, + &enable_txbf_20mhz); + if ((IS_SIR_STATUS_SUCCESS(cfg_get_status)) && + (false == enable_txbf_20mhz)) + session->txBFIniFeatureEnabled = 0; + } else if (session->vhtCapabilityPresentInBeacon == 1 && + beacon_struct->VHTOperation.chanWidth) { + session->ch_center_freq_seg0 = + beacon_struct->VHTOperation.chanCenterFreqSeg1; + session->ch_center_freq_seg1 = + beacon_struct->VHTOperation.chanCenterFreqSeg2; + session->ch_width = + beacon_struct->VHTOperation.chanWidth + 1; + if (CH_WIDTH_80MHZ < session->ch_width) { + session->enable_su_tx_bformer = 0; + session->nss = 1; + } + } + if (session->vhtCapabilityPresentInBeacon == 1 && + !session->htSupportedChannelWidthSet && + session->txBFIniFeatureEnabled == 0) { + cfg_set_status = cfg_set_int(mac_ctx, + WNI_CFG_VHT_SU_BEAMFORMEE_CAP, + 0); + if (cfg_set_status != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Set VHT_SU_BEAMFORMEE_CAP Fail")); + } +#endif + /* Extract the UAPSD flag from WMM Parameter element */ + if (beacon_struct->wmeEdcaPresent) + *uapsd = beacon_struct->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 (beacon_struct->eseTxPwr.present) + *local_constraint = beacon_struct->eseTxPwr.power_limit; + session->is_ese_version_ie_present = + beacon_struct->is_ese_ver_ie_present; +#endif + if (beacon_struct->powerConstraintPresent) { +#if defined WLAN_FEATURE_VOWIFI + *local_constraint -= + beacon_struct->localPowerConstraint. + localPowerConstraints; +#else + local_power_constraints = + (uint32_t) beacon_struct->localPowerConstraint. + localPowerConstraints; +#endif + } +#if !defined WLAN_FEATURE_VOWIFI + if (cfg_set_int + (mac_ctx, WNI_CFG_LOCAL_POWER_CONSTRAINT, + local_power_constraints) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL + ("Could not update local power constraint to cfg.")); + } +#endif + session->country_info_present = false; + /* Initializing before first use */ + if (beacon_struct->countryInfoPresent) + session->country_info_present = true; + } + cdf_mem_free(beacon_struct); + return; +} /****** end lim_extract_ap_capability() ******/ + +/** + * lim_get_htcb_state + * + ***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 lim_get_htcb_state(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; + } +} + +/* + * lim_get_sta_peer_type + * + ***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 lim_get_sta_peer_type(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/core/mac/src/pe/lim/lim_prop_exts_utils.h b/core/mac/src/pe/lim/lim_prop_exts_utils.h new file mode 100644 index 000000000000..a648a78ddbfd --- /dev/null +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.h @@ -0,0 +1,64 @@ +/* + * 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 lim_prop_exts_utils.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, uint32_t); +void lim_cleanupMeasData(tpAniSirGlobal); +void limDeleteMeasTimers(tpAniSirGlobal); +void limStopMeasTimers(tpAniSirGlobal pMac); +void lim_cleanupMeasResources(tpAniSirGlobal); +void limRestorePreLearnState(tpAniSirGlobal); +void limCollectMeasurementData(tpAniSirGlobal, uint32_t *, tpSchBeaconStruct); +void limCollectRSSI(tpAniSirGlobal); +void limDeleteCurrentBssWdsNode(tpAniSirGlobal); +uint32_t limComputeAvg(tpAniSirGlobal, uint32_t, uint32_t); + +/* / Function to extract AP's HCF capability from IE fields */ +void lim_extract_ap_capability(tpAniSirGlobal, uint8_t *, uint16_t, uint8_t *, + uint16_t *, uint8_t *, tPowerdBm *, tpPESession); + +tStaRateMode lim_get_sta_peer_type(tpAniSirGlobal, tpDphHashNode, tpPESession); +#ifdef WLAN_FEATURE_11AC +ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode); +#endif + +#endif /* __LIM_PROP_EXTS_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.c b/core/mac/src/pe/lim/lim_scan_result_utils.c new file mode 100644 index 000000000000..387152e92fee --- /dev/null +++ b/core/mac/src/pe/lim/lim_scan_result_utils.c @@ -0,0 +1,421 @@ +/* + * 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 lim_scan_result_utils.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 "lim_types.h" +#include "lim_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_api.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif +#include "cds_utils.h" + + +/** + * lim_collect_bss_description() + * + ***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 +CDF_STATUS +lim_collect_bss_description(tpAniSirGlobal pMac, + tSirBssDescription *pBssDescr, + tpSirProbeRespBeacon pBPR, + uint8_t *pRxPacketInfo, uint8_t fScanning) +#else +CDF_STATUS +lim_collect_bss_description(tpAniSirGlobal pMac, + tSirBssDescription *pBssDescr, + tpSirProbeRespBeacon pBPR, uint8_t *pRxPacketInfo) +#endif +{ + uint8_t *pBody; + uint32_t ieLen = 0; + tpSirMacMgmtHdr pHdr; + uint8_t channelNum; + uint8_t rxChannel; + uint8_t rfBand = 0; + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + + if (SIR_MAC_B_PR_SSID_OFFSET > WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)) { + CDF_ASSERT(WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) >= + SIR_MAC_B_PR_SSID_OFFSET); + return CDF_STATUS_E_FAILURE; + } + ieLen = + WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) - SIR_MAC_B_PR_SSID_OFFSET; + rxChannel = WMA_GET_RX_CH(pRxPacketInfo); + pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); + rfBand = WMA_GET_RX_RFBAND(pRxPacketInfo); + + /** + * 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 = (uint16_t)(offsetof(tSirBssDescription, ieFields[0]) + - sizeof(pBssDescr->length) + ieLen); + + /* Copy BSS Id */ + cdf_mem_copy((uint8_t *) &pBssDescr->bssId, + (uint8_t *) pHdr->bssId, sizeof(tSirMacAddr)); + + /* Copy Timestamp, Beacon Interval and Capability Info */ + pBssDescr->scanSysTimeMsec = cdf_mc_timer_get_system_time(); + + pBssDescr->timeStamp[0] = pBPR->timeStamp[0]; + pBssDescr->timeStamp[1] = pBPR->timeStamp[1]; + pBssDescr->beaconInterval = pBPR->beaconInterval; + pBssDescr->capabilityInfo = + lim_get_u16((uint8_t *) &pBPR->capabilityInfo); + + if (!pBssDescr->beaconInterval) { + lim_log(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 = lim_get_channel_from_beacon(pMac, pBPR); + + if (pBssDescr->channelId == 0) { + /* If the channel Id is not retrieved from Beacon, extract the channel from BD */ + 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 = + lim_get_nw_type(pMac, channelNum, SIR_MAC_MGMT_FRAME, pBPR); + + /* Copy RSSI & SINR from BD */ + + lim_log(pMac, LOG4, "*********BSS Description for BSSID:********* "); + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, pBssDescr->bssId, 6); + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, + (uint8_t *) pRxPacketInfo, 36); + + pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo); + + /* SINR no longer reported by HW */ + pBssDescr->sinr = 0; + + pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks(); + pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo); + + lim_log(pMac, LOG1, FL("BSSID: "MAC_ADDRESS_STR " tsf_delta = %u"), + MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->tsf_delta); + +#if defined WLAN_FEATURE_VOWIFI + if (fScanning) { + rrm_get_start_tsf(pMac, pBssDescr->startTSF); + pBssDescr->parentTSF = WMA_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 */ + cdf_mem_copy((uint8_t *) &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; + + lim_log(pMac, LOG3, + FL("Collected BSS Description for Channel(%1d), length(%u), IE Fields(%u)"), + pBssDescr->channelId, pBssDescr->length, ieLen); + + return CDF_STATUS_SUCCESS; +} /*** end lim_collect_bss_description() ***/ + +/** + * lim_is_scan_requested_ssid() + * + ***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 bool - true if SSID is present in requested list, false otherwise + */ + +bool lim_is_scan_requested_ssid(tpAniSirGlobal pMac, tSirMacSSid *ssId) +{ + uint8_t i = 0; + + for (i = 0; i < pMac->lim.gpLimMlmScanReq->numSsid; i++) { + if (true == cdf_mem_compare((uint8_t *) ssId, + (uint8_t *) &pMac->lim. + gpLimMlmScanReq->ssId[i], + (uint8_t) (pMac->lim. + gpLimMlmScanReq->ssId[i]. + length + 1))) { + return true; + } + } + return false; +} + +/** + * lim_check_and_add_bss_description() + * @mac_ctx: Pointer to Global MAC structure + * @bpr: Pointer to parsed Beacon/Probe Response structure + * @rx_packet_info: Pointer to Received frame's BD + * @scanning: bool to indicate whether the BSS is from current scan + * or just happens to receive a beacon + * + * 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. + * + * Return: None + */ + +void +lim_check_and_add_bss_description(tpAniSirGlobal mac_ctx, + tpSirProbeRespBeacon bpr, uint8_t *rx_packet_info, + bool scanning, uint8_t fProbeRsp) +{ + tSirBssDescription *bssdescr = NULL; + uint32_t frame_len, ie_len = 0; + uint8_t rx_chan_in_beacon = 0; + CDF_STATUS status; + uint8_t dont_update_all = 0; + uint8_t rf_band = 0; + uint8_t rx_chan_bd = 0; + + tSirMacAddr bssid_zero = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + tpSirMacDataHdr3a hdr; + + hdr = WMA_GET_RX_MPDUHEADER3A((uint8_t *) rx_packet_info); + + /* Check For Null BSSID and Skip in case of P2P */ + if (cdf_mem_compare(bssid_zero, &hdr->addr3, 6)) + return; + + /* + * SSID/BSSID policy: + * Accept beacons/probe responses with any SSID or BSSID because + * multiple scan requests may be running at the same time and + * firmware may forward results to CLD from scans requested through a + * different path. + * + * CSA Policy: + * 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 (bpr->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 ((bpr->dsParamsPresent) || (bpr->HTInfo.present)) { + /* This means that we are in 2.4GHz mode or 5GHz 11n mode */ + rx_chan_in_beacon = lim_get_channel_from_beacon(mac_ctx, bpr); + rf_band = WMA_GET_RX_RFBAND(rx_packet_info); + rx_chan_bd = WMA_GET_RX_CH(rx_packet_info); + + if (rx_chan_bd != rx_chan_in_beacon) { + /* BCAST Frame, if CH do not match, Drop */ + if (WMA_IS_RX_BCAST(rx_packet_info)) { + lim_log(mac_ctx, LOG3, + FL("Beacon/Probe Rsp dropped. Channel in BD %d. Channel in beacon %d"), + WMA_GET_RX_CH(rx_packet_info), + lim_get_channel_from_beacon(mac_ctx, + bpr)); + return; + } + /* Unit cast frame, Probe RSP, do not drop */ + else { + dont_update_all = 1; + lim_log(mac_ctx, LOG3, + FL("SSID %s, CH in ProbeRsp %d, CH in BD %d, mismatch, Do Not Drop"), + bpr->ssId.ssId, rx_chan_in_beacon, + WMA_GET_RX_CH(rx_packet_info)); + WMA_GET_RX_CH(rx_packet_info) = + rx_chan_in_beacon; + } + } + } + + /* + * Allocate buffer to hold BSS description from + * received Beacon frame. + * Include size of fixed fields and IEs length + */ + + ie_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info); + if (ie_len <= SIR_MAC_B_PR_SSID_OFFSET) { + lim_log(mac_ctx, LOGP, + FL("RX packet has invalid length %d"), ie_len); + return; + } + + ie_len -= SIR_MAC_B_PR_SSID_OFFSET; + + /* IEs will be overlap ieFields field. Adjust the length accordingly */ + frame_len = sizeof(*bssdescr) + ie_len - sizeof(bssdescr->ieFields[1]); + bssdescr = (tSirBssDescription *) cdf_mem_malloc(frame_len); + + if (NULL == bssdescr) { + /* Log error */ + lim_log(mac_ctx, LOGE, + FL("cdf_mem_malloc(length=%d) failed"), frame_len); + return; + } + /* In scan state, store scan result. */ +#if defined WLAN_FEATURE_VOWIFI + status = lim_collect_bss_description(mac_ctx, bssdescr, + bpr, rx_packet_info, scanning); + if (CDF_STATUS_SUCCESS != status) + goto last; +#else + status = lim_collect_bss_description(mac_ctx, bssdescr, + bpr, rx_packet_info); + if (CDF_STATUS_SUCCESS != status) + goto last; +#endif + bssdescr->fProbeRsp = fProbeRsp; + + /* + * Send the beacon to CSR with registered callback routine. + * scan_id and flags parameters are currently unused and set to 0. + */ + if (mac_ctx->lim.add_bssdescr_callback) { + (mac_ctx->lim.add_bssdescr_callback) (mac_ctx, bssdescr, 0, 0); + } else { + lim_log(mac_ctx, LOGE, + FL("No CSR callback routine to send beacons")); + status = CDF_STATUS_E_INVAL; + } +last: + cdf_mem_free(bssdescr); + return; +} + diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.h b/core/mac/src/pe/lim/lim_scan_result_utils.h new file mode 100644 index 000000000000..c622dc2c8a36 --- /dev/null +++ b/core/mac/src/pe/lim/lim_scan_result_utils.h @@ -0,0 +1,59 @@ +/* + * 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 lim_scan_result_utils.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 "parser_api.h" +#include "lim_types.h" + +/* Scan result hash related functions */ +uint8_t lim_scan_hash_function(tSirMacAddr); +void lim_restore_pre_scan_state(tpAniSirGlobal); +void lim_copy_scan_result(tpAniSirGlobal, uint8_t *); +void lim_check_and_add_bss_description(tpAniSirGlobal, tpSirProbeRespBeacon, + uint8_t *, bool, uint8_t); +#if defined WLAN_FEATURE_VOWIFI +CDF_STATUS lim_collect_bss_description(tpAniSirGlobal, + tSirBssDescription *, + tpSirProbeRespBeacon, uint8_t *, uint8_t); +#else +CDF_STATUS lim_collect_bss_description(tpAniSirGlobal, + tSirBssDescription *, + tpSirProbeRespBeacon, uint8_t *); +#endif + +#endif /* __LIM_SCAN_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_security_utils.c b/core/mac/src/pe/lim/lim_security_utils.c new file mode 100644 index 000000000000..ae0a42224d06 --- /dev/null +++ b/core/mac/src/pe/lim/lim_security_utils.c @@ -0,0 +1,1075 @@ +/* + * 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 lim_utils.cc contains the utility functions + * LIM uses. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "ani_global.h" +#include "wni_api.h" + +#include "sir_common.h" +#include "wni_cfg.h" +#include "cfg_api.h" + +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_security_utils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" + +#define LIM_SEED_LENGTH 16 +/* + * preauth node timeout value in interval of 10msec + */ +#define LIM_OPENAUTH_TIMEOUT 500 + +/** + * lim_is_auth_algo_supported() + * + ***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 + */ +uint8_t +lim_is_auth_algo_supported(tpAniSirGlobal pMac, tAniAuthType authType, + tpPESession psessionEntry) +{ + uint32_t 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_cfg_get_int(pMac, WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE, + &algoEnable) != eSIR_SUCCESS) { + /** + * Could not get AuthAlgo1 Enable value + * from CFG. Log error. + */ + lim_log(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_cfg_get_int + (pMac, WNI_CFG_SHARED_KEY_AUTH_ENABLE, + &algoEnable) != eSIR_SUCCESS) { + /** + * Could not get AuthAlgo2 Enable value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL("could not retrieve AuthAlgo2 Enable value")); + + return false; + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + privacyOptImp = psessionEntry->privacy; + } else + + if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, + &privacyOptImp) != eSIR_SUCCESS) + { + /** + * Could not get PrivacyOptionImplemented value + * from CFG. Log error. + */ + lim_log(pMac, LOGE, + FL + ("could not retrieve PrivacyOptImplemented value")); + + return false; + } + return (algoEnable && privacyOptImp); + } +} /****** end lim_is_auth_algo_supported() ******/ + +/** + * lim_init_pre_auth_list + * + ***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 lim_init_pre_auth_list(tpAniSirGlobal pMac) +{ + pMac->lim.pLimPreAuthList = NULL; + +} /*** end lim_init_pre_auth_list() ***/ + +/** + * lim_delete_pre_auth_list + * + ***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 lim_delete_pre_auth_list(tpAniSirGlobal pMac) +{ + struct tLimPreAuthNode *pCurrNode, *pTempNode; + + pCurrNode = pTempNode = pMac->lim.pLimPreAuthList; + while (pCurrNode != NULL) { + pTempNode = pCurrNode->next; + + PELOG1(lim_log(pMac, LOG1, FL("=====> lim_delete_pre_auth_list "));) + lim_release_pre_auth_node(pMac, pCurrNode); + + pCurrNode = pTempNode; + } + pMac->lim.pLimPreAuthList = NULL; +} /*** end lim_delete_pre_auth_list() ***/ + +/** + * lim_search_pre_auth_list + * + ***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 *lim_search_pre_auth_list(tpAniSirGlobal pMac, + tSirMacAddr macAddr) +{ + struct tLimPreAuthNode *pTempNode = pMac->lim.pLimPreAuthList; + + while (pTempNode != NULL) { + if (cdf_mem_compare((uint8_t *) macAddr, + (uint8_t *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr))) + break; + + pTempNode = pTempNode->next; + } + + return pTempNode; +} /*** end lim_search_pre_auth_list() ***/ + +/** + * lim_delete_open_auth_pre_auth_node() - delete any stale preauth nodes + * @mac_ctx: 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 + */ +uint8_t +lim_delete_open_auth_pre_auth_node(tpAniSirGlobal mac_ctx) +{ + struct tLimPreAuthNode *prev_node, *temp_node, *found_node; + uint8_t auth_node_freed = false; + + temp_node = prev_node = mac_ctx->lim.pLimPreAuthList; + + if (temp_node == NULL) + return auth_node_freed; + + while (temp_node != NULL) { + if (temp_node->mlmState == eLIM_MLM_AUTHENTICATED_STATE && + temp_node->authType == eSIR_OPEN_SYSTEM && + (cdf_mc_timer_get_system_ticks() > + (LIM_OPENAUTH_TIMEOUT + temp_node->timestamp) || + cdf_mc_timer_get_system_ticks() < temp_node->timestamp)) { + /* Found node to be deleted */ + auth_node_freed = true; + found_node = temp_node; + if (mac_ctx->lim.pLimPreAuthList == temp_node) { + prev_node = mac_ctx->lim.pLimPreAuthList = + temp_node = found_node->next; + } else { + prev_node->next = temp_node->next; + temp_node = prev_node->next; + } + + lim_release_pre_auth_node(mac_ctx, found_node); + } else { + prev_node = temp_node; + temp_node = prev_node->next; + } + } + + return auth_node_freed; +} + +/** + * lim_add_pre_auth_node + * + ***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 lim_add_pre_auth_node(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNode) +{ + pMac->lim.gLimNumPreAuthContexts++; + + pAuthNode->next = pMac->lim.pLimPreAuthList; + + pMac->lim.pLimPreAuthList = pAuthNode; +} /*** end lim_add_pre_auth_node() ***/ + +/** + * lim_release_pre_auth_node + * + ***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 lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode) +{ + pAuthNode->fFree = 1; + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, + eLIM_PRE_AUTH_CLEANUP_TIMER)); + tx_timer_deactivate(&pAuthNode->timer); + pMac->lim.gLimNumPreAuthContexts--; +} /*** end lim_release_pre_auth_node() ***/ + +/** + * lim_delete_pre_auth_node + * + ***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 lim_delete_pre_auth_node(tpAniSirGlobal pMac, tSirMacAddr macAddr) +{ + struct tLimPreAuthNode *pPrevNode, *pTempNode; + + pTempNode = pPrevNode = pMac->lim.pLimPreAuthList; + + if (pTempNode == NULL) + return; + + if (cdf_mem_compare((uint8_t *) macAddr, + (uint8_t *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr))) { + /* First node to be deleted */ + + pMac->lim.pLimPreAuthList = pTempNode->next; + + PELOG1(lim_log + (pMac, LOG1, + FL + ("=====> lim_delete_pre_auth_node : first node to delete")); + ) + PELOG1(lim_log + (pMac, LOG1, + FL("Release data entry: %x id %d peer "), pTempNode, + pTempNode->authNodeIdx); + lim_print_mac_addr(pMac, macAddr, LOG1); + ) + lim_release_pre_auth_node(pMac, pTempNode); + + return; + } + + pTempNode = pTempNode->next; + + while (pTempNode != NULL) { + if (cdf_mem_compare((uint8_t *) macAddr, + (uint8_t *) &pTempNode->peerMacAddr, + sizeof(tSirMacAddr))) { + /* Found node to be deleted */ + + pPrevNode->next = pTempNode->next; + + PELOG1(lim_log + (pMac, LOG1, + FL + ("=====> lim_delete_pre_auth_node : subsequent node to delete")); + lim_log(pMac, LOG1, + FL("Release data entry: %x id %d peer "), + pTempNode, pTempNode->authNodeIdx); + lim_print_mac_addr(pMac, macAddr, LOG1); + ) + lim_release_pre_auth_node(pMac, pTempNode); + + return; + } + + pPrevNode = pTempNode; + pTempNode = pTempNode->next; + } + + /* Should not be here */ + /* Log error */ + lim_log(pMac, LOGP, FL("peer not found in pre-auth list, addr= ")); + lim_print_mac_addr(pMac, macAddr, LOGP); + +} /*** end lim_delete_pre_auth_node() ***/ + +/** + * 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 +lim_restore_from_auth_state(tpAniSirGlobal pMac, tSirResultCodes resultCode, + uint16_t protStatusCode, tpPESession sessionEntry) +{ + tSirMacAddr currentBssId; + tLimMlmAuthCnf mlmAuthCnf; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_AUTH_COMP_EVENT, sessionEntry, + resultCode, protStatusCode); +#endif + + cdf_mem_copy((uint8_t *) &mlmAuthCnf.peerMacAddr, + (uint8_t *) &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 */ + cdf_mem_free(pMac->lim.gpLimMlmAuthReq); + pMac->lim.gpLimMlmAuthReq = NULL; + + sessionEntry->limMlmState = sessionEntry->limPrevMlmState; + + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, + sessionEntry->limMlmState)); + + /* 'Change' timer for future activations */ + lim_deactivate_and_change_timer(pMac, eLIM_AUTH_FAIL_TIMER); + + sir_copy_mac_addr(currentBssId, sessionEntry->bssId); + + if (sessionEntry->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE) { + pMac->lim.gLimPreAuthChannelNumber = 0; + } + + lim_post_sme_message(pMac, LIM_MLM_AUTH_CNF, (uint32_t *) &mlmAuthCnf); +} /*** end lim_restore_from_auth_state() ***/ + +/** + * lim_encrypt_auth_frame() + * + ***FUNCTION: + * This function is called in lim_process_auth_frame() 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 +lim_encrypt_auth_frame(tpAniSirGlobal pMac, uint8_t keyId, uint8_t *pKey, + uint8_t *pPlainText, uint8_t *pEncrBody, + uint32_t keyLength) +{ + uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH]; + + keyLength += 3; + + /* Bytes 3-7 of seed is key */ + cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3); + + /* Compute CRC-32 and place them in last 4 bytes of plain text */ + lim_compute_crc32(icv, pPlainText, sizeof(tSirMacAuthFrameBody)); + + cdf_mem_copy(pPlainText + sizeof(tSirMacAuthFrameBody), + icv, SIR_MAC_WEP_ICV_LENGTH); + + /* Run RC4 on plain text with the seed */ + lim_rc4(pEncrBody + SIR_MAC_WEP_IV_LENGTH, + (uint8_t *) 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 lim_encrypt_auth_frame() ******/ + +/** + * lim_compute_crc32() + * + ***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 lim_compute_crc32(uint8_t *pDest, uint8_t *pSrc, uint8_t len) +{ + uint32_t crc; + int i; + + crc = 0; + crc = ~crc; + + while (len-- > 0) + crc = lim_crc_update(crc, *pSrc++); + + crc = ~crc; + + for (i = 0; i < SIR_MAC_WEP_IV_LENGTH; i++) { + pDest[i] = (uint8_t) crc; + crc >>= 8; + } +} /****** end lim_compute_crc32() ******/ + +/** + * lim_rc4() + * + ***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 +lim_rc4(uint8_t *pDest, uint8_t *pSrc, uint8_t *seed, uint32_t keyLength, + uint16_t frameLen) +{ + typedef struct { + uint8_t i, j; + uint8_t sbox[256]; + } tRC4Context; + + tRC4Context ctx; + + { + uint16_t i, j, k; + + /* */ + /* Initialize sbox using seed */ + /* */ + + ctx.i = ctx.j = 0; + for (i = 0; i < 256; i++) + ctx.sbox[i] = (uint8_t) i; + + j = 0; + k = 0; + for (i = 0; i < 256; i++) { + uint8_t temp; + if (k < LIM_SEED_LENGTH) + j = (uint8_t) (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; + } + } + + { + uint8_t i = ctx.i; + uint8_t j = ctx.j; + uint8_t len = (uint8_t) frameLen; + + while (len-- > 0) { + uint8_t temp1, temp2; + + i = (uint8_t) (i + 1); + temp1 = ctx.sbox[i]; + j = (uint8_t) (j + temp1); + + ctx.sbox[i] = temp2 = ctx.sbox[j]; + ctx.sbox[j] = temp1; + + temp1 = (uint8_t) (temp1 + temp2); + temp1 = ctx.sbox[temp1]; + temp2 = (uint8_t) (pSrc ? *pSrc++ : 0); + + *pDest++ = (uint8_t) (temp1 ^ temp2); + } + + ctx.i = i; + ctx.j = j; + } +} /****** end lim_rc4() ******/ + +/** + * lim_decrypt_auth_frame() + * + ***FUNCTION: + * This function is called in lim_process_auth_frame() 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. + */ + +uint8_t +lim_decrypt_auth_frame(tpAniSirGlobal pMac, uint8_t *pKey, uint8_t *pEncrBody, + uint8_t *pPlainBody, uint32_t keyLength, uint16_t frameLen) +{ + uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH]; + int i; + keyLength += 3; + + /* Bytes 0-2 of seed is received IV */ + cdf_mem_copy((uint8_t *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1); + + /* Bytes 3-7 of seed is key */ + cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3); + + /* Run RC4 on encrypted text with the seed */ + lim_rc4(pPlainBody, + pEncrBody + SIR_MAC_WEP_IV_LENGTH, seed, keyLength, frameLen); + + PELOG4(lim_log(pMac, LOG4, FL("plainbody is ")); + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen); + ) + /* Compute CRC-32 and place them in last 4 bytes of encrypted body */ + lim_compute_crc32(icv, + (uint8_t *) pPlainBody, + (uint8_t) (frameLen - SIR_MAC_WEP_ICV_LENGTH)); + + /* Compare RX_ICV with computed ICV */ + for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) { + PELOG4(lim_log + (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 lim_decrypt_auth_frame() ******/ + +/** + * lim_post_sme_set_keys_cnf + * + * A utility API to send MLM_SETKEYS_CNF to SME + */ +void lim_post_sme_set_keys_cnf(tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tLimMlmSetKeysCnf *mlmSetKeysCnf) +{ + /* Prepare and Send LIM_MLM_SETKEYS_CNF */ + cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr, + (uint8_t *) pMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + + cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr, + (uint8_t *) pMlmSetKeysReq->peerMacAddr, + sizeof(tSirMacAddr)); + + /* / Free up buffer allocated for mlmSetKeysReq */ + cdf_mem_free(pMlmSetKeysReq); + pMac->lim.gpLimMlmSetKeysReq = NULL; + + lim_post_sme_message(pMac, + LIM_MLM_SETKEYS_CNF, (uint32_t *) mlmSetKeysCnf); +} + +/** + * lim_send_set_bss_key_req() + * + ***FUNCTION: + * This function is called from lim_process_mlm_set_keys_req(), + * 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 lim_send_set_bss_key_req(tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpSetBssKeyParams pSetBssKeyParams = NULL; + tLimMlmSetKeysCnf mlmSetKeysCnf; + tSirRetStatus retCode; + uint32_t val = 0; + + if (pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { + lim_log(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 WMA_SET_BSSKEY_REQ message parameters */ + + pSetBssKeyParams = cdf_mem_malloc(sizeof(tSetBssKeyParams)); + if (NULL == pSetBssKeyParams) { + lim_log(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 + cdf_mem_set((void *)pSetBssKeyParams, + sizeof(tSetBssKeyParams), 0); + + /* Update the WMA_SET_BSSKEY_REQ parameters */ + pSetBssKeyParams->bssIdx = psessionEntry->bssIdx; + pSetBssKeyParams->encType = pMlmSetKeysReq->edType; + + if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { + lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC")); + } + + pSetBssKeyParams->singleTidRc = (uint8_t) 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; + cdf_mem_copy((uint8_t *) &pSetBssKeyParams-> + key[pMlmSetKeysReq->key[0].keyId], + (uint8_t *) &pMlmSetKeysReq->key[0], + sizeof(pMlmSetKeysReq->key[0])); + + } else { + pSetBssKeyParams->numKeys = pMlmSetKeysReq->numKeys; + cdf_mem_copy((uint8_t *) &pSetBssKeyParams->key, + (uint8_t *) &pMlmSetKeysReq->key, + sizeof(tSirKeys) * pMlmSetKeysReq->numKeys); + } + + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + msgQ.type = WMA_SET_BSSKEY_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pSetBssKeyParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOGW, FL("Sending WMA_SET_BSSKEY_REQ...")); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) { + lim_log(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 WMA_SET_BSSKEY_RSP... */ + +end: + lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf); + +} + +/** + * @function : lim_send_set_sta_key_req() + * + * @brief : This function is called from lim_process_mlm_set_keys_req(), + * 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 lim_send_set_sta_key_req(tpAniSirGlobal pMac, + tLimMlmSetKeysReq *pMlmSetKeysReq, + uint16_t staIdx, + uint8_t defWEPIdx, + tpPESession sessionEntry, bool sendRsp) +{ + tSirMsgQ msgQ; + tpSetStaKeyParams pSetStaKeyParams = NULL; + tLimMlmSetKeysCnf mlmSetKeysCnf; + tSirRetStatus retCode; + uint32_t val = 0; + + /* Package WMA_SET_STAKEY_REQ message parameters */ + pSetStaKeyParams = cdf_mem_malloc(sizeof(tSetStaKeyParams)); + if (NULL == pSetStaKeyParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during SET_BSSKEY")); + return; + } else + cdf_mem_set((void *)pSetStaKeyParams, sizeof(tSetStaKeyParams), + 0); + + /* Update the WMA_SET_STAKEY_REQ parameters */ + pSetStaKeyParams->staIdx = staIdx; + pSetStaKeyParams->encType = pMlmSetKeysReq->edType; + + if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { + lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC")); + } + + pSetStaKeyParams->singleTidRc = (uint8_t) 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; + cdf_mem_copy(pSetStaKeyParams->peerMacAddr, + pMlmSetKeysReq->peerMacAddr, sizeof(tSirMacAddr)); + + if (sendRsp == 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 == true) + sessionEntry->limMlmState = + eLIM_MLM_WT_SET_STA_BCASTKEY_STATE; + msgQ.type = WMA_SET_STA_BCASTKEY_REQ; + } else { + if (sendRsp == true) + sessionEntry->limMlmState = + eLIM_MLM_WT_SET_STA_KEY_STATE; + msgQ.type = WMA_SET_STAKEY_REQ; + } + MTRACE(mac_trace + (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) { + uint32_t i; + + for (i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) { + cdf_mem_copy((uint8_t *) &pSetStaKeyParams-> + key[i], + (uint8_t *) &pMlmSetKeysReq-> + key[i], sizeof(tSirKeys)); + } + pSetStaKeyParams->wepType = eSIR_WEP_STATIC; + sessionEntry->limMlmState = + eLIM_MLM_WT_SET_STA_KEY_STATE; + MTRACE(mac_trace + (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) { + cdf_mem_copy((uint8_t *) &pSetStaKeyParams-> + key[defWEPIdx], + (uint8_t *) &pMlmSetKeysReq-> + key[0], + sizeof(pMlmSetKeysReq->key[0])); + pMlmSetKeysReq->numKeys = + SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + } else { + lim_log(pMac, LOGE, FL("Wrong Key Index %d"), + defWEPIdx); + cdf_mem_free(pSetStaKeyParams); + return; + } + } + break; + case eSIR_ED_TKIP: + case eSIR_ED_CCMP: +#ifdef FEATURE_WLAN_WAPI + case eSIR_ED_WPI: +#endif + { + cdf_mem_copy((uint8_t *) &pSetStaKeyParams->key, + (uint8_t *) &pMlmSetKeysReq->key[0], + sizeof(tSirKeys)); + } + break; + default: + break; + } + + pSetStaKeyParams->sendRsp = sendRsp; + + msgQ.reserved = 0; + msgQ.bodyptr = pSetStaKeyParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG1, FL("Sending WMA_SET_STAKEY_REQ...")); + MTRACE(mac_trace_msg_tx(pMac, sessionEntry->peSessionId, msgQ.type)); + if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) { + lim_log(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 WMA_SET_STAKEY_RSP... */ + + if (sendRsp == true) + lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf); +} diff --git a/core/mac/src/pe/lim/lim_security_utils.h b/core/mac/src/pe/lim/lim_security_utils.h new file mode 100644 index 000000000000..c5b30bab509a --- /dev/null +++ b/core/mac/src/pe/lim/lim_security_utils.h @@ -0,0 +1,95 @@ +/* + * 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 lim_security_utils.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 "sir_mac_prot_def.h" /* for tSirMacAuthFrameBody */ + +#define LIM_ENCR_AUTH_BODY_LEN (sizeof(tSirMacAuthFrameBody) + \ + SIR_MAC_WEP_IV_LENGTH + \ + SIR_MAC_WEP_ICV_LENGTH) +struct tLimPreAuthNode; + +uint8_t lim_is_auth_algo_supported(tpAniSirGlobal, tAniAuthType, tpPESession); + +/* MAC based authentication related functions */ +void lim_init_pre_auth_list(tpAniSirGlobal); +void lim_delete_pre_auth_list(tpAniSirGlobal); +struct tLimPreAuthNode *lim_search_pre_auth_list(tpAniSirGlobal, tSirMacAddr); +void lim_add_pre_auth_node(tpAniSirGlobal, struct tLimPreAuthNode *); +void lim_delete_pre_auth_node(tpAniSirGlobal, tSirMacAddr); +void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode); +void lim_restore_from_auth_state(tpAniSirGlobal, + tSirResultCodes, uint16_t, tpPESession); +uint8_t lim_delete_open_auth_pre_auth_node(tpAniSirGlobal mac_ctx); + +/* Encryption/Decryption related functions */ +void lim_compute_crc32(uint8_t *, uint8_t *, uint8_t); +void lim_rc4(uint8_t *, uint8_t *, uint8_t *, uint32_t, uint16_t); +void lim_encrypt_auth_frame(tpAniSirGlobal, uint8_t, uint8_t *, uint8_t *, + uint8_t *, uint32_t); +uint8_t lim_decrypt_auth_frame(tpAniSirGlobal, uint8_t *, uint8_t *, uint8_t *, + uint32_t, uint16_t); + +void lim_send_set_bss_key_req(tpAniSirGlobal, tLimMlmSetKeysReq *, tpPESession); +void lim_send_set_sta_key_req(tpAniSirGlobal, tLimMlmSetKeysReq *, uint16_t, uint8_t, + tpPESession, bool sendRsp); +void lim_post_sme_set_keys_cnf(tpAniSirGlobal, tLimMlmSetKeysReq *, + tLimMlmSetKeysCnf *); + +#define PTAPS 0xedb88320 + +static inline uint32_t lim_crc_update(uint32_t crc, uint8_t x) +{ + + /* Update CRC computation for 8 bits contained in x */ + /* */ + uint32_t z; + uint32_t 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/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c new file mode 100644 index 000000000000..c7f422052b87 --- /dev/null +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -0,0 +1,5130 @@ +/* + * 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 lim_send_management_frames.c + * + * \brief Code for preparing and sending 802.11 Management frames + * + * + */ + +#include "sir_api.h" +#include "ani_global.h" +#include "sir_mac_prot_def.h" +#include "cfg_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_security_utils.h" +#include "lim_prop_exts_utils.h" +#include "dot11f.h" +#include "lim_sta_hash_api.h" +#include "sch_api.h" +#include "lim_send_messages.h" +#include "lim_assoc_utils.h" +#include "lim_ft.h" +#ifdef WLAN_FEATURE_11W +#include "wni_cfg.h" +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cds_utils.h" +#include "sme_trace.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +#include "wma_types.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 lim_add_mgmt_seq_num(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 lim_populate_p2p_mac_header(tpAniSirGlobal pMac, uint8_t *pBD) +{ + tpSirMacMgmtHdr pMacHdr; + + /* / Prepare MAC management header */ + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + /* Prepare sequence number */ + lim_add_mgmt_seq_num(pMac, pMacHdr); + lim_log(pMac, LOG1, "seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d", + pMacHdr->seqControl.seqNumLo, + pMacHdr->seqControl.seqNumHi, pMac->mgmtSeqNum); +} + +/** + * lim_populate_mac_header() - Fill in 802.11 header of frame + * + * @mac_ctx: Pointer to Global MAC structure + * @buf: Pointer to the frame buffer that needs to be populate + * @type: 802.11 Type of the frame + * @sub_type: 802.11 Subtype of the frame + * @peer_addr: dst address + * @self_mac_addr: local mac address + * + * This function is called by various LIM modules to prepare the + * 802.11 frame MAC header + * + * The buf 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 + * + * Return: None + */ + +void lim_populate_mac_header(tpAniSirGlobal mac_ctx, uint8_t *buf, + uint8_t type, uint8_t sub_type, tSirMacAddr peer_addr, + tSirMacAddr self_mac_addr) +{ + tpSirMacMgmtHdr mac_hdr; + + /* Prepare MAC management header */ + mac_hdr = (tpSirMacMgmtHdr) (buf); + + /* Prepare FC */ + mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + mac_hdr->fc.type = type; + mac_hdr->fc.subType = sub_type; + + /* Prepare Address 1 */ + cdf_mem_copy((uint8_t *) mac_hdr->da, + (uint8_t *) peer_addr, sizeof(tSirMacAddr)); + + /* Prepare Address 2 */ + sir_copy_mac_addr(mac_hdr->sa, self_mac_addr); + + /* Prepare Address 3 */ + cdf_mem_copy((uint8_t *) mac_hdr->bssId, + (uint8_t *) peer_addr, sizeof(tSirMacAddr)); + + /* Prepare sequence number */ + lim_add_mgmt_seq_num(mac_ctx, mac_hdr); + lim_log(mac_ctx, LOG1, "seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d", + mac_hdr->seqControl.seqNumLo, + mac_hdr->seqControl.seqNumHi, mac_ctx->mgmtSeqNum); +} + +/** + * lim_send_probe_req_mgmt_frame() - send probe request management frame + * @mac_ctx: Pointer to Global MAC structure + * @ssid: SSID to be sent in Probe Request frame + * @bssid: BSSID to be sent in Probe Request frame + * @channel: Channel # on which the Probe Request is going out + * @self_macaddr: self MAC address + * @dot11mode: self dotllmode + * @additional_ielen: if non-zero, include additional_ie in the Probe Request + * frame + * @additional_ie: if additional_ielen 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 + * --sch_beacon_processing: to get EDCA parameters: session needed + * + * Return: tSirRetStatus (eSIR_SUCCESS on success and error codes otherwise) + */ +tSirRetStatus +lim_send_probe_req_mgmt_frame(tpAniSirGlobal mac_ctx, + tSirMacSSid *ssid, + tSirMacAddr bssid, + uint8_t channel, + tSirMacAddr self_macaddr, + uint32_t dot11mode, + uint32_t additional_ielen, uint8_t *additional_ie) +{ + tDot11fProbeRequest pr; + uint32_t status, bytes, payload; + uint8_t *frame; + void *packet; + CDF_STATUS cdf_status, extcap_status; + tpPESession pesession; + uint8_t sessionid; + uint8_t *p2pie = NULL; + uint8_t txflag = 0; + uint8_t sme_sessionid = 0; + bool is_vht_enabled = false; + uint8_t txPower; + uint16_t addn_ielen = additional_ielen; + + /* 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 (channel <= SIR_11B_CHANNEL_END && + (false == mac_ctx->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 + * --sch_beacon_processing: 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 + */ + pesession = pe_find_session_by_bssid(mac_ctx, bssid, &sessionid); + + if (pesession != NULL) + sme_sessionid = pesession->smeSessionId; + + /* The scheme here is to fill out a 'tDot11fProbeRequest' structure */ + /* and then hand it off to 'dot11f_pack_probe_request' (for */ + /* serialization). We start by zero-initializing the structure: */ + cdf_mem_set((uint8_t *) &pr, sizeof(pr), 0); + + /* & delegating to assorted helpers: */ + populate_dot11f_ssid(mac_ctx, ssid, &pr.SSID); + + if (addn_ielen && additional_ie) + p2pie = limGetP2pIEPtr(mac_ctx, additional_ie, addn_ielen); + + /* + * Don't include 11b rate if it is a P2P serach or probe request is + * sent by P2P Client + */ + if ((WNI_CFG_DOT11_MODE_11B != dot11mode) && (p2pie != NULL) && + (((mac_ctx->lim.gpLimMlmScanReq != NULL) && + mac_ctx->lim.gpLimMlmScanReq->p2pSearch) || + ((pesession != NULL) && + (CDF_P2P_CLIENT_MODE == pesession->pePersona)) + ) + ) { + /* + * In the below API pass channel number > 14, do that it fills + * only 11a rates in supported rates + */ + populate_dot11f_supp_rates(mac_ctx, 15, &pr.SuppRates, + pesession); + } else { + populate_dot11f_supp_rates(mac_ctx, channel, + &pr.SuppRates, pesession); + + if (WNI_CFG_DOT11_MODE_11B != dot11mode) { + populate_dot11f_ext_supp_rates1(mac_ctx, channel, + &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. + */ + populate_dot11f_ds_params(mac_ctx, &pr.DSParams, channel); + /* Call RRM module to get the tx power for management used. */ + txPower = (uint8_t) rrm_get_mgmt_tx_power(mac_ctx, pesession); + populate_dot11f_wfatpc(mac_ctx, &pr.WFATPC, txPower, 0); + +#endif + + if (pesession != NULL) { + pesession->htCapability = IS_DOT11_MODE_HT(dot11mode); + /* Include HT Capability IE */ + if (pesession->htCapability) + populate_dot11f_ht_caps(mac_ctx, pesession, &pr.HTCaps); + } else { /* pesession == NULL */ + if (IS_DOT11_MODE_HT(dot11mode)) + populate_dot11f_ht_caps(mac_ctx, NULL, &pr.HTCaps); + } + + /* + * Set channelbonding information as "disabled" when tunned to a + * 2.4 GHz channel + */ + if (channel <= SIR_11B_CHANNEL_END) { + if (mac_ctx->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 (pesession != NULL) { + pesession->vhtCapability = IS_DOT11_MODE_VHT(dot11mode); + /* Include VHT Capability IE */ + if (pesession->vhtCapability) { + populate_dot11f_vht_caps(mac_ctx, pesession, + &pr.VHTCaps); + is_vht_enabled = true; + } + } else { + if (IS_DOT11_MODE_VHT(dot11mode)) { + populate_dot11f_vht_caps(mac_ctx, pesession, + &pr.VHTCaps); + is_vht_enabled = true; + } + } +#endif + if (pesession != NULL) + populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &pr.ExtCap, + pesession); + + /* That's it-- now we pack it. First, how much space are we going to */ + status = dot11f_get_packed_probe_request_size(mac_ctx, &pr, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGP, FL("Failed to calculate the packed size for a Probe Request (0x%08x)."), status); + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fProbeRequest); + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("There were warnings while calculating the packed size for a Probe Request (0x%08x)."), status); + } + + /* Strip extended capability IE (if present). FW will add that IE */ + if (addn_ielen) { + extcap_status = lim_strip_extcap_ie(mac_ctx, additional_ie, + &addn_ielen, NULL); + if (CDF_STATUS_SUCCESS != extcap_status) + lim_log(mac_ctx, LOGE, + FL("Error:%d stripping extcap IE"), extcap_status); + } + + bytes = payload + sizeof(tSirMacMgmtHdr) + addn_ielen; + + /* Ok-- try to allocate some memory: */ + cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, + (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, FL("Failed to allocate %d bytes for a Probe Request."), bytes); + return eSIR_MEM_ALLOC_FAILED; + } + /* Paranoia: */ + cdf_mem_set(frame, bytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssid, self_macaddr); + + /* That done, pack the Probe Request: */ + status = dot11f_pack_probe_request(mac_ctx, &pr, frame + + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to pack a Probe Request (0x%08x)."), status); + cds_packet_free((void *)packet); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, FL("There were warnings while packing a Probe Request (0x%08x)."), status); + } + /* Append any AddIE if present. */ + if (addn_ielen) { + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + additional_ie, addn_ielen); + payload += 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 == lim_get_rf_band(channel)) + || ((mac_ctx->lim.gpLimMlmScanReq != NULL) && + mac_ctx->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 + */ + || ((pesession != NULL) && + (CDF_P2P_CLIENT_MODE == pesession->pePersona)) + ) { + txflag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + cdf_status = + wma_tx_frame(mac_ctx, packet, + (uint16_t) sizeof(tSirMacMgmtHdr) + payload, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, frame, txflag, sme_sessionid, + 0); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("could not send Probe Request frame!")); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} /* End lim_send_probe_req_mgmt_frame. */ + +tSirRetStatus lim_get_addn_ie_for_probe_resp(tpAniSirGlobal pMac, + uint8_t *addIE, uint16_t *addnIELen, + uint8_t probeReqP2pIe) +{ + /* If Probe request doesn't have P2P IE, then take out P2P IE + from additional IE */ + if (!probeReqP2pIe) { + uint8_t *tempbuf = NULL; + uint16_t tempLen = 0; + int left = *addnIELen; + uint8_t *ptr = addIE; + uint8_t elem_id, elem_len; + + if (NULL == addIE) { + PELOGE(lim_log(pMac, LOGE, FL(" NULL addIE pointer"));) + return eSIR_FAILURE; + } + + tempbuf = cdf_mem_malloc(left); + if (NULL == tempbuf) { + PELOGE(lim_log(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) { + lim_log(pMac, LOGE, + FL + ("****Invalid IEs eid = %d elem_len=%d left=%d*****"), + elem_id, elem_len, left); + cdf_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))) { + cdf_mem_copy(tempbuf + tempLen, &ptr[0], + elem_len + 2); + tempLen += (elem_len + 2); + } + left -= elem_len; + ptr += (elem_len + 2); + } + cdf_mem_copy(addIE, tempbuf, tempLen); + *addnIELen = tempLen; + cdf_mem_free(tempbuf); + } + return eSIR_SUCCESS; +} + +/** + * lim_send_probe_rsp_mgmt_frame() - Send probe response + * + * @mac_ctx: Handle for mac context + * @peer_macaddr: Mac address of requesting peer + * @ssid: SSID for response + * @n_staid: Station ID, currently unused. + * @pe_session: PE session id + * @keepalive: Keep alive flag. Currently unused. + * @preq_p2pie: P2P IE in incoming probe request + * + * Builds and sends probe response frame to the requesting peer + * + * Return: void + */ + +void +lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, + tSirMacAddr peer_macaddr, + tpAniSSID ssid, + short n_staid, + uint8_t keepalive, + tpPESession pe_session, uint8_t preq_p2pie) +{ + tDot11fProbeResponse *frm; + tSirRetStatus sir_status; + uint32_t cfg, payload, bytes, status; + tpSirMacMgmtHdr mac_hdr; + uint8_t *frame; + void *packet; + CDF_STATUS cdf_status; + uint32_t addn_ie_present = false; + + uint16_t addn_ie_len = 0; + uint32_t wps_ap = 0, tmp; + uint8_t tx_flag = 0; + uint8_t *add_ie = NULL; + uint8_t *p2p_ie = NULL; + uint8_t noalen = 0; + uint8_t total_noalen = 0; + uint8_t noa_stream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + uint8_t noa_ie[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + uint8_t sme_sessionid = 0; + bool is_vht_enabled = false; + tDot11fIEExtCap extracted_ext_cap; + bool extracted_ext_cap_flag = true; + + /* We don't answer requests in this case*/ + if (ANI_DRIVER_TYPE(mac_ctx) == eDRIVER_TYPE_MFG) + return; + + if (NULL == pe_session) + 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 (((pe_session->pePersona == CDF_SAP_MODE) || + (pe_session->pePersona == CDF_P2P_GO_MODE)) && + (true == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("CAC timer is running, probe response dropped")); + return; + } + sme_sessionid = pe_session->smeSessionId; + frm = cdf_mem_malloc(sizeof(tDot11fProbeResponse)); + if (NULL == frm) { + lim_log(mac_ctx, LOGE, + FL("Unable to allocate memory")); + return; + } + + cdf_mem_zero(&extracted_ext_cap, sizeof(extracted_ext_cap)); + + /* + * Fill out 'frm', after which we'll just hand the struct off to + * 'dot11f_pack_probe_response'. + */ + cdf_mem_set((uint8_t *) frm, sizeof(tDot11fProbeResponse), 0); + + /* + * Timestamp to be updated by TFP, below. + * + * Beacon Interval: + */ + if (LIM_IS_AP_ROLE(pe_session)) { + frm->BeaconInterval.interval = + mac_ctx->sch.schObject.gSchBeaconInterval; + } else { + sir_status = wlan_cfg_get_int(mac_ctx, + WNI_CFG_BEACON_INTERVAL, &cfg); + if (eSIR_SUCCESS != sir_status) { + lim_log(mac_ctx, LOGP, + FL("Failed to get WNI_CFG_BEACON_INTERVAL (%d)."), + sir_status); + goto err_ret; + } + frm->BeaconInterval.interval = (uint16_t) cfg; + } + + populate_dot11f_capabilities(mac_ctx, &frm->Capabilities, pe_session); + populate_dot11f_ssid(mac_ctx, (tSirMacSSid *) ssid, &frm->SSID); + populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm->SuppRates, pe_session); + + populate_dot11f_ds_params(mac_ctx, &frm->DSParams, + pe_session->currentOperChannel); + populate_dot11f_ibss_params(mac_ctx, &frm->IBSSParams, pe_session); + + if (LIM_IS_AP_ROLE(pe_session)) { + if (pe_session->wps_state != SAP_WPS_DISABLED) + populate_dot11f_probe_res_wpsi_es(mac_ctx, + &frm->WscProbeRes, + pe_session); + } else { + if (wlan_cfg_get_int(mac_ctx, (uint16_t) WNI_CFG_WPS_ENABLE, + &tmp) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, "Failed to cfg get id %d", + WNI_CFG_WPS_ENABLE); + + wps_ap = tmp & WNI_CFG_WPS_ENABLE_AP; + + if (wps_ap) + populate_dot11f_wsc_in_probe_res(mac_ctx, + &frm->WscProbeRes); + + if (mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState == + eLIM_WSC_ENROLL_BEGIN) { + populate_dot11f_wsc_registrar_info_in_probe_res(mac_ctx, + &frm->WscProbeRes); + mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState = + eLIM_WSC_ENROLL_IN_PROGRESS; + } + + if (mac_ctx->lim.wscIeInfo.wscEnrollmentState == + eLIM_WSC_ENROLL_END) { + de_populate_dot11f_wsc_registrar_info_in_probe_res( + mac_ctx, &frm->WscProbeRes); + mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState = + eLIM_WSC_ENROLL_NOOP; + } + } + + populate_dot11f_country(mac_ctx, &frm->Country, pe_session); + populate_dot11f_edca_param_set(mac_ctx, &frm->EDCAParamSet, pe_session); + + if (pe_session->dot11mode != WNI_CFG_DOT11_MODE_11B) + populate_dot11f_erp_info(mac_ctx, &frm->ERPInfo, pe_session); + + populate_dot11f_ext_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, + &frm->ExtSuppRates, pe_session); + + /* Populate HT IEs, when operating in 11n */ + if (pe_session->htCapability) { + populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps); + populate_dot11f_ht_info(mac_ctx, &frm->HTInfo, pe_session); + } +#ifdef WLAN_FEATURE_11AC + if (pe_session->vhtCapability) { + lim_log(mac_ctx, LOG1, FL("Populate VHT IE in Probe Response")); + populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps); + populate_dot11f_vht_operation(mac_ctx, pe_session, + &frm->VHTOperation); + /* + * we do not support multi users yet. + * populate_dot11f_vht_ext_bss_load( mac_ctx, + * &frm.VHTExtBssLoad ); + */ + is_vht_enabled = true; + } +#endif + + populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &frm->ExtCap, + pe_session); + + if (pe_session->pLimStartBssReq) { + populate_dot11f_wpa(mac_ctx, + &(pe_session->pLimStartBssReq->rsnIE), + &frm->WPA); + populate_dot11f_rsn_opaque(mac_ctx, + &(pe_session->pLimStartBssReq->rsnIE), + &frm->RSNOpaque); + } + + populate_dot11f_wmm(mac_ctx, &frm->WMMInfoAp, &frm->WMMParams, + &frm->WMMCaps, pe_session); + +#if defined(FEATURE_WLAN_WAPI) + if (pe_session->pLimStartBssReq) + populate_dot11f_wapi(mac_ctx, + &(pe_session->pLimStartBssReq->rsnIE), + &frm->WAPI); +#endif /* defined(FEATURE_WLAN_WAPI) */ + + status = dot11f_get_packed_probe_response_size(mac_ctx, frm, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGP, + FL("Probe Response size error (0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fProbeResponse); + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Probe Response size warning (0x%08x)."), + status); + } + + bytes = payload + sizeof(tSirMacMgmtHdr); + + if (mac_ctx->lim.gpLimRemainOnChanReq) + bytes += (mac_ctx->lim.gpLimRemainOnChanReq->length - + sizeof(tSirRemainOnChnReq)); + else + /* + * 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. + */ + addn_ie_present = + (pe_session->addIeParams.probeRespDataLen != 0); + + if (addn_ie_present) { + + add_ie = cdf_mem_malloc( + pe_session->addIeParams.probeRespDataLen); + if (NULL == add_ie) { + lim_log(mac_ctx, LOGE, + FL("add_ie allocation failed")); + goto err_ret; + } + + cdf_mem_copy(add_ie, + pe_session->addIeParams.probeRespData_buff, + pe_session->addIeParams.probeRespDataLen); + addn_ie_len = pe_session->addIeParams.probeRespDataLen; + + if (eSIR_SUCCESS != lim_get_addn_ie_for_probe_resp(mac_ctx, + add_ie, &addn_ie_len, preq_p2pie)) { + lim_log(mac_ctx, LOGP, + FL("Unable to get addn_ie")); + goto err_ret; + } + + sir_status = lim_strip_extcap_update_struct(mac_ctx, + add_ie, &addn_ie_len, + &extracted_ext_cap); + if (eSIR_SUCCESS != sir_status) { + extracted_ext_cap_flag = false; + lim_log(mac_ctx, LOG1, + FL("Unable to strip off ExtCap IE")); + } + + bytes = bytes + addn_ie_len; + + if (preq_p2pie) + p2p_ie = limGetP2pIEPtr(mac_ctx, &add_ie[0], + addn_ie_len); + + if (p2p_ie != NULL) { + /* get NoA attribute stream P2P IE */ + noalen = lim_get_noa_attr_stream(mac_ctx, + noa_stream, pe_session); + if (noalen != 0) { + total_noalen = + lim_build_p2p_ie(mac_ctx, &noa_ie[0], + &noa_stream[0], noalen); + bytes = bytes + total_noalen; + } + } + } + + cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, + (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, FL("Probe Response allocation failed")); + goto err_ret; + } + /* Paranoia: */ + cdf_mem_set(frame, bytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_RSP, peer_macaddr, + pe_session->selfMacAddr); + + mac_hdr = (tpSirMacMgmtHdr) frame; + + sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId); + + /* merge ExtCap IE */ + if (extracted_ext_cap_flag) + lim_merge_extcap_struct(&frm->ExtCap, &extracted_ext_cap); + + /* That done, pack the Probe Response: */ + status = + dot11f_pack_probe_response(mac_ctx, frm, + frame + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Probe Response pack failure (0x%08x)."), + status); + goto err_ret; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Probe Response pack warning (0x%08x)."), + status); + } + + lim_log(mac_ctx, LOG3, FL("Sending Probe Response frame to ")); + lim_print_mac_addr(mac_ctx, peer_macaddr, LOG3); + + mac_ctx->sys.probeRespond++; + + if (mac_ctx->lim.gpLimRemainOnChanReq) + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + mac_ctx->lim.gpLimRemainOnChanReq->probeRspIe, + (mac_ctx->lim.gpLimRemainOnChanReq->length - + sizeof(tSirRemainOnChnReq))); + + if (addn_ie_present) + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + &add_ie[0], addn_ie_len); + + if (noalen != 0) { + if (total_noalen > + (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)) { + lim_log(mac_ctx, LOGE, + FL("Not able to insert NoA, total len=%d"), + total_noalen); + goto err_ret; + } else { + cdf_mem_copy(&frame[bytes - (total_noalen)], + &noa_ie[0], total_noalen); + } + } + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(pe_session->currentOperChannel)) + || (pe_session->pePersona == CDF_P2P_CLIENT_MODE) || + (pe_session->pePersona == CDF_P2P_GO_MODE) + ) + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + /* Queue Probe Response frame in high priority WQ */ + cdf_status = wma_tx_frame((tHalHandle) mac_ctx, packet, + (uint16_t) bytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, frame, tx_flag, + sme_sessionid, 0); + + /* Pkt will be freed up by the callback */ + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + lim_log(mac_ctx, LOGE, FL("Could not send Probe Response.")); + + if (add_ie != NULL) + cdf_mem_free(add_ie); + + cdf_mem_free(frm); + return; + +err_ret: + if (add_ie != NULL) + cdf_mem_free(add_ie); + if (frm != NULL) + cdf_mem_free(frm); + if (packet != NULL) + cds_packet_free((void *)packet); + return; + +} /* End lim_send_probe_rsp_mgmt_frame. */ + +void +lim_send_addts_req_action_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirAddtsReqInfo *pAddTS, tpPESession psessionEntry) +{ + uint16_t i; + uint8_t *pFrame; + tDot11fAddTSRequest AddTSReq; + tDot11fWMMAddTSRequest WMMAddTSReq; + uint32_t nPayload, nBytes, nStatus; + tpSirMacMgmtHdr pMacHdr; + void *pPacket; +#ifdef FEATURE_WLAN_ESE + uint32_t phyMode; +#endif + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + if (!pAddTS->wmeTspecPresent) { + cdf_mem_set((uint8_t *) &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) { + populate_dot11f_tspec(&pAddTS->tspec, &AddTSReq.TSPEC); + } else { + populate_dot11f_wmmtspec(&pAddTS->tspec, + &AddTSReq.WMMTSPEC); + } + + if (pAddTS->lleTspecPresent) { + AddTSReq.num_WMMTCLAS = 0; + AddTSReq.num_TCLAS = pAddTS->numTclas; + for (i = 0; i < pAddTS->numTclas; ++i) { + populate_dot11f_tclas(pMac, &pAddTS->tclasInfo[i], + &AddTSReq.TCLAS[i]); + } + } else { + AddTSReq.num_TCLAS = 0; + AddTSReq.num_WMMTCLAS = pAddTS->numTclas; + for (i = 0; i < pAddTS->numTclas; ++i) { + populate_dot11f_wmmtclas(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 = + dot11f_get_packed_add_ts_request_size(pMac, &AddTSReq, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL("There were warnings while calculating" + "the packed size for an Add TS Request" + " (0x%08x)."), nStatus); + } + } else { + cdf_mem_set((uint8_t *) &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; + + populate_dot11f_wmmtspec(&pAddTS->tspec, &WMMAddTSReq.WMMTSPEC); +#ifdef FEATURE_WLAN_ESE + lim_get_phy_mode(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; + } + populate_dot11_tsrsie(pMac, &pAddTS->tsrsIE, + &WMMAddTSReq.ESETrafStrmRateSet, + sizeof(uint8_t)); +#endif + /* fillWmeTspecIE */ + + nStatus = + dot11f_get_packed_wmm_add_ts_request_size(pMac, &WMMAddTSReq, + &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(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); + + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" + "d TS Request."), nBytes); + return; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peerMacAddr, psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peerMacAddr, pMacHdr); +#endif + + /* That done, pack the struct: */ + if (!pAddTS->wmeTspecPresent) { + nStatus = dot11f_pack_add_ts_request(pMac, &AddTSReq, + pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack an Add TS Request " + "(0x%08x)."), nStatus); + cds_packet_free((void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing " + "an Add TS Request (0x%08x)."), nStatus); + } + } else { + nStatus = dot11f_pack_wmm_add_ts_request(pMac, &WMMAddTSReq, + pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a WMM Add TS Reque" + "st (0x%08x)."), nStatus); + cds_packet_free((void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing " + "a WMM Add TS Request (0x%08x)."), nStatus); + } + } + + PELOG3(lim_log(pMac, LOG3, FL("Sending an Add TS Request frame to ")); + lim_print_mac_addr(pMac, peerMacAddr, LOG3); + ) + + if ((SIR_BAND_5_GHZ == + lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) + || (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + + /* Queue Addts Response frame in high priority WQ */ + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, FL("*** Could not send an Add TS Request" + " (%X) ***"), cdf_status); + /* Pkt will be freed up by the callback */ + } + +} /* End lim_send_addts_req_action_frame. */ + +/** + * lim_send_assoc_rsp_mgmt_frame() - Send assoc response + * @mac_ctx: Handle for mac context + * @status_code: Status code for assoc response frame + * @aid: Association ID + * @peer_addr: Mac address of requesting peer + * @subtype: Assoc/Reassoc + * @sta: Pointer to station node + * @pe_session: PE session id. + * + * Builds and sends association response frame to the requesting peer. + * + * Return: void + */ + +void +lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, + uint16_t status_code, uint16_t aid, tSirMacAddr peer_addr, + uint8_t subtype, tpDphHashNode sta, tpPESession pe_session) +{ + static tDot11fAssocResponse frm; + uint8_t *frame; + tpSirMacMgmtHdr mac_hdr; + tSirRetStatus sir_status; + uint8_t lle_mode = 0, addts; + tHalBitVal qos_mode, wme_mode; + uint32_t payload, bytes, status; + void *packet; + CDF_STATUS cdf_status; + tUpdateBeaconParams beacon_params; + uint8_t tx_flag = 0; + uint32_t addn_ie_len = 0; + uint8_t add_ie[WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN]; + tpSirAssocReq assoc_req = NULL; + uint8_t sme_session = 0; + bool is_vht = false; + uint16_t stripoff_len = 0; + tDot11fIEExtCap extracted_ext_cap; + bool extracted_flag = false; +#ifdef WLAN_FEATURE_11W + uint32_t retry_int; + uint32_t max_retries; +#endif + + if (NULL == pe_session) { + lim_log(mac_ctx, LOGE, FL("pe_session is NULL")); + return; + } + + sme_session = pe_session->smeSessionId; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + limGetQosMode(pe_session, &qos_mode); + limGetWmeMode(pe_session, &wme_mode); + + /* + * An Add TS IE is added only if the AP supports it and + * the requesting STA sent a traffic spec. + */ + addts = (qos_mode && sta && sta->qos.addtsPresent) ? 1 : 0; + + frm.Status.status = status_code; + + frm.AID.associd = aid | LIM_AID_MASK; + + if (NULL == sta) { + populate_dot11f_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.SuppRates, pe_session); + populate_dot11f_ext_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.ExtSuppRates, pe_session); + } else { + populate_dot11f_assoc_rsp_rates(mac_ctx, &frm.SuppRates, + &frm.ExtSuppRates, + sta->supportedRates.llbRates, + sta->supportedRates.llaRates); + } + + if (LIM_IS_AP_ROLE(pe_session) && sta != NULL && + eSIR_SUCCESS == status_code) { + assoc_req = (tpSirAssocReq) + pe_session->parsedAssocReq[sta->assocId]; + /* + * populate P2P IE in AssocRsp when assocReq from the peer + * includes P2P IE + */ + if (assoc_req != NULL && assoc_req->addIEPresent) + populate_dot11_assoc_res_p2p_ie(mac_ctx, + &frm.P2PAssocRes, + assoc_req); + } + + if (NULL != sta) { + if (eHAL_SET == qos_mode) { + if (sta->lleEnabled) { + lle_mode = 1; + populate_dot11f_edca_param_set(mac_ctx, + &frm.EDCAParamSet, pe_session); + } + } + + if ((!lle_mode) && (eHAL_SET == wme_mode) && sta->wmeEnabled) { + populate_dot11f_wmm_params(mac_ctx, &frm.WMMParams, + pe_session); + + if (sta->wsmEnabled) + populate_dot11f_wmm_caps(&frm.WMMCaps); + } + + if (sta->mlmStaContext.htCapability && + pe_session->htCapability) { + lim_log(mac_ctx, LOG1, + FL("Populate HT IEs in Assoc Response")); + populate_dot11f_ht_caps(mac_ctx, pe_session, + &frm.HTCaps); + populate_dot11f_ht_info(mac_ctx, &frm.HTInfo, + pe_session); + } +#ifdef WLAN_FEATURE_11AC + if (sta->mlmStaContext.vhtCapability && + pe_session->vhtCapability) { + lim_log(mac_ctx, LOG1, + FL("Populate VHT IEs in Assoc Response")); + populate_dot11f_vht_caps(mac_ctx, pe_session, + &frm.VHTCaps); + populate_dot11f_vht_operation(mac_ctx, pe_session, + &frm.VHTOperation); + is_vht = true; + } +#endif + + populate_dot11f_ext_cap(mac_ctx, is_vht, &frm.ExtCap, + pe_session); + +#ifdef WLAN_FEATURE_11W + if (eSIR_MAC_TRY_AGAIN_LATER == status_code) { + if (wlan_cfg_get_int + (mac_ctx, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &max_retries) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("get WNI_CFG_PMF_SA_QUERY_MAX_RETRIES failure")); + else if (wlan_cfg_get_int + (mac_ctx, + WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retry_int) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, + FL("get WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL failure")); + else + populate_dot11f_timeout_interval(mac_ctx, + &frm.TimeoutInterval, + SIR_MAC_TI_TYPE_ASSOC_COMEBACK, + (max_retries - + sta->pmfSaQueryRetryCount) + * retry_int); + } +#endif + } + + cdf_mem_set((uint8_t *) &beacon_params, sizeof(beacon_params), 0); + + if (LIM_IS_AP_ROLE(pe_session) && + (pe_session->gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)) + lim_decide_ap_protection(mac_ctx, peer_addr, + &beacon_params, pe_session); + + lim_update_short_preamble(mac_ctx, peer_addr, &beacon_params, + pe_session); + lim_update_short_slot_time(mac_ctx, peer_addr, &beacon_params, + pe_session); + + /* + * Populate Do11capabilities after updating session with + * Assos req details + */ + populate_dot11f_capabilities(mac_ctx, &frm.Capabilities, pe_session); + + beacon_params.bssIdx = pe_session->bssIdx; + + /* Send message to HAL about beacon parameter change. */ + if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beacon_params.paramChangeBitmap) { + sch_set_fixed_beacon_fields(mac_ctx, pe_session); + lim_send_beacon_params(mac_ctx, &beacon_params, pe_session); + } + /* Allocate a buffer for this frame: */ + status = dot11f_get_packed_assoc_response_size(mac_ctx, &frm, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("get Association Response size failure (0x%08x)."), + status); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("get Association Response size warning (0x%08x)."), + status); + } + + bytes = sizeof(tSirMacMgmtHdr) + payload; + + if (assoc_req != NULL) { + addn_ie_len = (pe_session->addIeParams.assocRespDataLen != 0); + + /* Nonzero length indicates Assoc rsp IE available */ + if (addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN + && (bytes + addn_ie_len) <= SIR_MAX_PACKET_SIZE) { + cdf_mem_copy(add_ie, + pe_session->addIeParams.assocRespData_buff, + pe_session->addIeParams.assocRespDataLen); + + cdf_mem_set((uint8_t *) &extracted_ext_cap, + sizeof(extracted_ext_cap), 0); + + stripoff_len = addn_ie_len; + sir_status = + lim_strip_extcap_update_struct + (mac_ctx, &add_ie[0], &stripoff_len, + &extracted_ext_cap); + if (eSIR_SUCCESS != sir_status) { + lim_log(mac_ctx, LOG1, + FL("strip off extcap IE failed")); + } else { + addn_ie_len = stripoff_len; + extracted_flag = true; + } + bytes = bytes + addn_ie_len; + } + lim_log(mac_ctx, LOG1, + FL("addn_ie_len = %d for Assoc Resp : %d"), + addn_ie_len, assoc_req->addIEPresent); + } + cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, + (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, FL("cds_packet_alloc failed.")); + return; + } + /* Paranoia: */ + cdf_mem_set(frame, bytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + (LIM_ASSOC == subtype) ? + SIR_MAC_MGMT_ASSOC_RSP : SIR_MAC_MGMT_REASSOC_RSP, + peer_addr, + pe_session->selfMacAddr); + mac_hdr = (tpSirMacMgmtHdr) frame; + + sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId); + + /* merge the ExtCap struct */ + if (extracted_flag) + lim_merge_extcap_struct(&(frm.ExtCap), &extracted_ext_cap); + status = dot11f_pack_assoc_response(mac_ctx, &frm, + frame + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Association Response pack failure(0x%08x)."), + status); + cds_packet_free((void *)packet); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Association Response pack warning (0x%08x)."), + status); + } + + if (subtype == LIM_ASSOC) + lim_log(mac_ctx, LOG1, + FL("*** Sending Assoc Resp status %d aid %d to "), + status_code, aid); + else + lim_log(mac_ctx, LOG1, + FL("*** Sending ReAssoc Resp status %d aid %d to "), + status_code, aid); + + lim_print_mac_addr(mac_ctx, mac_hdr->da, LOG1); + + if (addn_ie_len && addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN) + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + &add_ie[0], addn_ie_len); + + if ((SIR_BAND_5_GHZ == + lim_get_rf_band(pe_session->currentOperChannel)) || + (pe_session->pePersona == CDF_P2P_CLIENT_MODE) || + (pe_session->pePersona == CDF_P2P_GO_MODE)) + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + pe_session->peSessionId, mac_hdr->fc.subType)); + /* Queue Association Response frame in high priority WQ */ + cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) bytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, frame, tx_flag, + sme_session, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + pe_session->peSessionId, cdf_status)); + + /* Pkt will be freed up by the callback */ + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + lim_log(mac_ctx, LOGE, + FL("*** Could not Send Re/AssocRsp, retCode=%X ***"), + cdf_status); + + /* + * update the ANI peer station count. + * FIXME_PROTECTION : take care of different type of station + * counter inside this function. + */ + lim_util_count_sta_add(mac_ctx, sta, pe_session); + +} + +void +lim_send_delts_req_action_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, + uint8_t wmmTspecPresent, + tSirMacTSInfo *pTsinfo, + tSirMacTspecIE *pTspecIe, tpPESession psessionEntry) +{ + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + tDot11fDelTS DelTS; + tDot11fWMMDelTS WMMDelTS; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + if (NULL == psessionEntry) { + return; + } + + smeSessionId = psessionEntry->smeSessionId; + + if (!wmmTspecPresent) { + cdf_mem_set((uint8_t *) &DelTS, sizeof(DelTS), 0); + + DelTS.Category.category = SIR_MAC_ACTION_QOS_MGMT; + DelTS.Action.action = SIR_MAC_QOS_DEL_TS_REQ; + populate_dot11f_ts_info(pTsinfo, &DelTS.TSInfo); + + nStatus = dot11f_get_packed_del_ts_size(pMac, &DelTS, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL("There were warnings while calcula" + "ting the packed size for a Del TS" + " (0x%08x)."), nStatus); + } + } else { + cdf_mem_set((uint8_t *) &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; + populate_dot11f_wmmtspec(pTspecIe, &WMMDelTS.WMMTSPEC); + nStatus = + dot11f_get_packed_wmm_del_ts_size(pMac, &WMMDelTS, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(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); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" + "d TS Response."), nBytes); + return; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + /* That done, pack the struct: */ + if (!wmmTspecPresent) { + nStatus = dot11f_pack_del_ts(pMac, &DelTS, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Del TS frame (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing " + "a Del TS frame (0x%08x)."), nStatus); + } + } else { + nStatus = dot11f_pack_wmm_del_ts(pMac, &WMMDelTS, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL + ("Failed to pack a WMM Del TS frame (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing " + "a WMM Del TS frame (0x%08x)."), nStatus); + } + } + + PELOG1(lim_log + (pMac, LOG1, FL("Sending DELTS REQ (size %d) to "), nBytes); + lim_print_mac_addr(pMac, pMacHdr->da, LOG1); + ) + + if ((SIR_BAND_5_GHZ == + lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) + || (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + /* Pkt will be freed up by the callback */ + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + lim_log(pMac, LOGE, FL("Failed to send Del TS (%X)!"), + cdf_status); + +} /* End lim_send_delts_req_action_frame. */ + +/** + * lim_send_assoc_req_mgmt_frame() - Send association request + * @mac_ctx: Handle to MAC context + * @mlm_assoc_req: Association request information + * @pe_session: PE session information + * + * Builds and transmits association request frame to AP. + * + * Return: Void + */ + +void +lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, + tLimMlmAssocReq *mlm_assoc_req, + tpPESession pe_session) +{ + tDot11fAssocRequest *frm; + uint16_t caps; + uint8_t *frame; + tSirRetStatus sir_status; + tLimMlmAssocCnf assoc_cnf; + uint32_t bytes, payload, status; + uint8_t qos_enabled, wme_enabled, wsm_enabled; + void *packet; + CDF_STATUS cdf_status; + uint16_t add_ie_len; + uint8_t *add_ie; + uint8_t *wps_ie = NULL; +#if defined WLAN_FEATURE_VOWIFI + uint8_t power_caps = false; +#endif + uint8_t tx_flag = 0; + uint8_t sme_sessionid = 0; + bool vht_enabled = false; + tDot11fIEExtCap extr_ext_cap; + bool extr_ext_flag = true; + tpSirMacMgmtHdr mac_hdr; + + if (NULL == pe_session) { + lim_log(mac_ctx, LOGE, FL("pe_session is NULL")); + return; + } + + sme_sessionid = pe_session->smeSessionId; + + /* check this early to avoid unncessary operation */ + if (NULL == pe_session->pLimJoinReq) { + lim_log(mac_ctx, LOGE, FL("pe_session->pLimJoinReq is NULL")); + return; + } + add_ie_len = pe_session->pLimJoinReq->addIEAssoc.length; + add_ie = pe_session->pLimJoinReq->addIEAssoc.addIEdata; + + frm = cdf_mem_malloc(sizeof(tDot11fAssocRequest)); + if (NULL == frm) { + lim_log(mac_ctx, LOGE, FL("Unable to allocate memory")); + return; + } + + cdf_mem_set((uint8_t *) frm, sizeof(tDot11fAssocRequest), 0); + + if (add_ie_len) { + cdf_mem_set((uint8_t *) &extr_ext_cap, sizeof(tDot11fIEExtCap), + 0); + sir_status = lim_strip_extcap_update_struct(mac_ctx, + add_ie, &add_ie_len, &extr_ext_cap); + if (eSIR_SUCCESS != sir_status) { + extr_ext_flag = false; + lim_log(mac_ctx, LOG1, + FL("Unable to Stripoff ExtCap IE from Assoc Req")); + } else { + struct s_ext_cap *p_ext_cap = (struct s_ext_cap *) + extr_ext_cap.bytes; + + if (p_ext_cap->interworking_service) + p_ext_cap->qos_map = 1; + else { + /* + * No need to merge the EXT Cap from Supplicant + * if interworkingService is not set, as currently + * driver is only interested in interworkingService + * capability from supplicant. if in future any other + * EXT Cap info is required from supplicant + * it needs to be handled here. + */ + extr_ext_flag = false; + } + } + } else { + lim_log(mac_ctx, LOG1, FL("No additional IE for Assoc Req")); + extr_ext_flag = false; + } + + caps = mlm_assoc_req->capabilityInfo; +#if defined(FEATURE_WLAN_WAPI) + /* + * 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 (pe_session->encryptType == eSIR_ED_WPI) + ((tSirMacCapabilityInfo *) &caps)->privacy = 0; +#endif + swap_bit_field16(caps, (uint16_t *) &frm->Capabilities); + + frm->ListenInterval.interval = mlm_assoc_req->listenInterval; + populate_dot11f_ssid2(mac_ctx, &frm->SSID); + populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm->SuppRates, pe_session); + + qos_enabled = (pe_session->limQosEnabled) && + SIR_MAC_GET_QOS(pe_session->limCurrentBssCaps); + + wme_enabled = (pe_session->limWmeEnabled) && + LIM_BSS_CAPS_GET(WME, pe_session->limCurrentBssQosCaps); + + /* We prefer .11e asociations: */ + if (qos_enabled) + wme_enabled = false; + + wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled && + LIM_BSS_CAPS_GET(WSM, pe_session->limCurrentBssQosCaps); + + if (pe_session->lim11hEnable && + pe_session->pLimJoinReq->spectrumMgtIndicator == eSIR_TRUE) { +#if defined WLAN_FEATURE_VOWIFI + power_caps = true; + + populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps, + LIM_ASSOC, pe_session); +#endif + populate_dot11f_supp_channels(mac_ctx, &frm->SuppChannels, + LIM_ASSOC, pe_session); + + } +#if defined WLAN_FEATURE_VOWIFI + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) { + if (power_caps == false) { + power_caps = true; + populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps, + LIM_ASSOC, pe_session); + } + } +#endif + + if (qos_enabled) + populate_dot11f_qos_caps_station(mac_ctx, &frm->QOSCapsStation); + + populate_dot11f_ext_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, &frm->ExtSuppRates, + pe_session); + +#if defined WLAN_FEATURE_VOWIFI + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) + populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap, + pe_session); +#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 + * { + * uint16_t length; + * uint8_t 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 (add_ie_len && add_ie) + wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len); + + if (NULL == wps_ie) { + populate_dot11f_rsn_opaque(mac_ctx, + &(pe_session->pLimJoinReq->rsnIE), + &frm->RSNOpaque); + populate_dot11f_wpa_opaque(mac_ctx, + &(pe_session->pLimJoinReq->rsnIE), + &frm->WPAOpaque); +#if defined(FEATURE_WLAN_WAPI) + populate_dot11f_wapi_opaque(mac_ctx, + &(pe_session->pLimJoinReq->rsnIE), + &frm->WAPIOpaque); +#endif /* defined(FEATURE_WLAN_WAPI) */ + } + /* include WME EDCA IE as well */ + if (wme_enabled) { + populate_dot11f_wmm_info_station_per_session(mac_ctx, + pe_session, &frm->WMMInfoStation); + + if (wsm_enabled) + populate_dot11f_wmm_caps(&frm->WMMCaps); + } + + /* + * Populate HT IEs, when operating in 11n and + * when AP is also operating in 11n mode + */ + if (pe_session->htCapability && + mac_ctx->lim.htCapabilityPresentInBeacon) { + lim_log(mac_ctx, LOG1, FL("Populate HT Caps in Assoc Request")); + populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps); + } +#ifdef WLAN_FEATURE_11AC + if (pe_session->vhtCapability && + pe_session->vhtCapabilityPresentInBeacon) { + lim_log(mac_ctx, LOG1, FL("Populate VHT IEs in Assoc Request")); + populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps); + vht_enabled = true; + } + if (!vht_enabled && + pe_session->is_vendor_specific_vhtcaps) { + lim_log(mac_ctx, LOG1, + FL("Populate Vendor VHT IEs in Assoc Request")); + frm->vendor2_ie.present = 1; + frm->vendor2_ie.type = + pe_session->vendor_specific_vht_ie_type; + frm->vendor2_ie.sub_type = + pe_session->vendor_specific_vht_ie_sub_type; + + frm->vendor2_ie.VHTCaps.present = 1; + populate_dot11f_vht_caps(mac_ctx, pe_session, + &frm->vendor2_ie.VHTCaps); + vht_enabled = true; + } + +#endif + + populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm->ExtCap, pe_session); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (pe_session->pLimJoinReq->is11Rconnection) { +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + tSirBssDescription *bssdescr; + + bssdescr = &pe_session->pLimJoinReq->bssDescription; + lim_log(mac_ctx, LOG1, FL("mdie = %02x %02x %02x"), + (unsigned int) bssdescr->mdie[0], + (unsigned int) bssdescr->mdie[1], + (unsigned int) bssdescr->mdie[2]); +#endif + populate_mdie(mac_ctx, &frm->MobilityDomain, + pe_session->pLimJoinReq->bssDescription.mdie); + } else { + /* No 11r IEs dont send any MDIE */ + lim_log(mac_ctx, 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 (pe_session->is_ese_version_ie_present && + mac_ctx->roam.configParam.isEseIniFeatureEnabled) + populate_dot11f_ese_version(&frm->ESEVersion); + /* For ESE Associations fill the ESE IEs */ + if (pe_session->isESEconnection && + pe_session->pLimJoinReq->isESEFeatureIniEnabled) { +#ifndef FEATURE_DISABLE_RM + populate_dot11f_ese_rad_mgmt_cap(&frm->ESERadMgmtCap); +#endif + } +#endif + + status = dot11f_get_packed_assoc_request_size(mac_ctx, frm, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGP, + FL("Association Request packet size failure(0x%08x)."), + status); + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fAssocRequest); + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Association request packet size warning (0x%08x)."), + status); + } + + bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len; + + cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, + (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, FL("Failed to allocate %d bytes."), + bytes); + + pe_session->limMlmState = pe_session->limPrevMlmState; + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + pe_session->peSessionId, + pe_session->limMlmState)); + + /* Update PE session id */ + assoc_cnf.sessionId = pe_session->peSessionId; + + assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + + cds_packet_free((void *)packet); + + lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF, + (uint32_t *) &assoc_cnf); + + cdf_mem_free(frm); + return; + } + /* Paranoia: */ + cdf_mem_set(frame, bytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ASSOC_REQ, pe_session->bssId, + pe_session->selfMacAddr); + /* merge the ExtCap struct */ + if (extr_ext_flag) + lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap); + /* That done, pack the Assoc Request: */ + status = dot11f_pack_assoc_request(mac_ctx, frm, + frame + sizeof(tSirMacMgmtHdr), payload, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Assoc request pack failure (0x%08x)"), status); + cds_packet_free((void *)packet); + cdf_mem_free(frm); + return; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Assoc request pack warning (0x%08x)"), status); + } + + lim_log(mac_ctx, LOG1, + FL("*** Sending Association Request length %d to "), bytes); + if (pe_session->assocReq != NULL) { + cdf_mem_free(pe_session->assocReq); + pe_session->assocReq = NULL; + } + + if (add_ie_len) { + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + add_ie, add_ie_len); + payload += add_ie_len; + } + + pe_session->assocReq = cdf_mem_malloc(payload); + if (NULL == pe_session->assocReq) { + lim_log(mac_ctx, LOGE, FL("Unable to allocate memory")); + } else { + /* + * Store the Assoc request. This is sent to csr/hdd in + * join cnf response. + */ + cdf_mem_copy(pe_session->assocReq, + frame + sizeof(tSirMacMgmtHdr), payload); + pe_session->assocReqLen = payload; + } + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(pe_session->currentOperChannel)) + || (pe_session->pePersona == CDF_P2P_CLIENT_MODE) + || (pe_session->pePersona == CDF_P2P_GO_MODE) + ) + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + if (pe_session->pePersona == CDF_P2P_CLIENT_MODE) + tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_START_EVENT, + pe_session, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + mac_hdr = (tpSirMacMgmtHdr) frame; + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + pe_session->peSessionId, mac_hdr->fc.subType)); + cdf_status = + wma_tx_frame(mac_ctx, packet, + (uint16_t) (sizeof(tSirMacMgmtHdr) + payload), + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, frame, tx_flag, sme_sessionid, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + pe_session->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to send Association Request (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + cdf_mem_free(frm); + return; + } + /* Free up buffer allocated for mlm_assoc_req */ + cdf_mem_free(mlm_assoc_req); + mlm_assoc_req = NULL; + cdf_mem_free(frm); + return; +} + +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) +/** + * lim_send_reassoc_req_with_ft_ies_mgmt_frame() - Send Reassoc Req with FTIEs. + * + * @mac_ctx: Handle to mac context + * @mlm_reassoc_req: Original reassoc request + * @pe_session: PE session information + * + * It builds a reassoc request with FT IEs and sends it to AP through WMA. + * Then it creates assoc request and stores it for sending after join + * confirmation. + * + * Return: void + */ + +void +lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, + tLimMlmReassocReq *mlm_reassoc_req, + tpPESession pe_session) +{ + static tDot11fReAssocRequest frm; + uint16_t caps; + uint8_t *frame; + uint32_t bytes, payload, status; + uint8_t qos_enabled, wme_enabled, wsm_enabled; + void *packet; + CDF_STATUS cdf_status; +#if defined WLAN_FEATURE_VOWIFI + uint8_t power_caps_populated = false; +#endif + uint16_t ft_ies_length = 0; + uint8_t *body; + uint16_t add_ie_len; + uint8_t *add_ie; +#if defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + uint8_t *wps_ie = NULL; +#endif + uint8_t tx_flag = 0; + uint8_t sme_sessionid = 0; + bool vht_enabled = false; + tpSirMacMgmtHdr mac_hdr; + tftSMEContext *ft_sme_context; + + if (NULL == pe_session) + return; + + sme_sessionid = pe_session->smeSessionId; + + /* check this early to avoid unncessary operation */ + if (NULL == pe_session->pLimReAssocReq) + return; + + add_ie_len = pe_session->pLimReAssocReq->addIEAssoc.length; + add_ie = pe_session->pLimReAssocReq->addIEAssoc.addIEdata; + lim_log(mac_ctx, LOG1, + FL("called in state (%d)."), pe_session->limMlmState); + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + caps = mlm_reassoc_req->capabilityInfo; +#if defined(FEATURE_WLAN_WAPI) + /* + * 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 (pe_session->encryptType == eSIR_ED_WPI) + ((tSirMacCapabilityInfo *) &caps)->privacy = 0; +#endif + swap_bit_field16(caps, (uint16_t *) &frm.Capabilities); + + frm.ListenInterval.interval = mlm_reassoc_req->listenInterval; + + /* + * Get the old bssid of the older AP. + * The previous ap bssid is stored in the FT Session + * while creating the PE FT Session for reassociation. + */ + cdf_mem_copy((uint8_t *)frm.CurrentAPAddress.mac, + pe_session->prev_ap_bssid, sizeof(tSirMacAddr)); + + populate_dot11f_ssid2(mac_ctx, &frm.SSID); + populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.SuppRates, pe_session); + + qos_enabled = (pe_session->limQosEnabled) && + SIR_MAC_GET_QOS(pe_session->limReassocBssCaps); + + wme_enabled = (pe_session->limWmeEnabled) && + LIM_BSS_CAPS_GET(WME, pe_session->limReassocBssQosCaps); + + wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled && + LIM_BSS_CAPS_GET(WSM, pe_session->limReassocBssQosCaps); + + if (pe_session->lim11hEnable && + pe_session->pLimReAssocReq->spectrumMgtIndicator == eSIR_TRUE) { +#if defined WLAN_FEATURE_VOWIFI + power_caps_populated = true; + + populate_dot11f_power_caps(mac_ctx, &frm.PowerCaps, + LIM_REASSOC, pe_session); + populate_dot11f_supp_channels(mac_ctx, &frm.SuppChannels, + LIM_REASSOC, pe_session); +#endif + } +#if defined WLAN_FEATURE_VOWIFI + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) { + if (power_caps_populated == false) { + power_caps_populated = true; + populate_dot11f_power_caps(mac_ctx, &frm.PowerCaps, + LIM_REASSOC, pe_session); + } + } +#endif + + if (qos_enabled) + populate_dot11f_qos_caps_station(mac_ctx, &frm.QOSCapsStation); + + populate_dot11f_ext_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, &frm.ExtSuppRates, + pe_session); + +#if defined WLAN_FEATURE_VOWIFI + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limReassocBssCaps)) { + populate_dot11f_rrm_ie(mac_ctx, &frm.RRMEnabledCap, pe_session); + } +#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 + * { + * uint16_t length; + * uint8_t 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 (!pe_session->is11Rconnection) { + if (add_ie_len && add_ie) + wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len); + if (NULL == wps_ie) { + populate_dot11f_rsn_opaque(mac_ctx, + &(pe_session->pLimReAssocReq->rsnIE), + &frm.RSNOpaque); + populate_dot11f_wpa_opaque(mac_ctx, + &(pe_session->pLimReAssocReq->rsnIE), + &frm.WPAOpaque); + } +#ifdef FEATURE_WLAN_ESE + if (pe_session->pLimReAssocReq->cckmIE.length) { + populate_dot11f_ese_cckm_opaque(mac_ctx, + &(pe_session->pLimReAssocReq->cckmIE), + &frm.ESECckmOpaque); + } +#endif + } +#ifdef FEATURE_WLAN_ESE + /* + * ESE Version IE will be included in re-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 (pe_session->is_ese_version_ie_present && + mac_ctx->roam.configParam.isEseIniFeatureEnabled) + populate_dot11f_ese_version(&frm.ESEVersion); + /* For ESE Associations fill the ESE IEs */ + if (pe_session->isESEconnection && + pe_session->pLimReAssocReq->isESEFeatureIniEnabled) { +#ifndef FEATURE_DISABLE_RM + populate_dot11f_ese_rad_mgmt_cap(&frm.ESERadMgmtCap); +#endif + } +#endif /* FEATURE_WLAN_ESE */ +#endif /* FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ + + /* include WME EDCA IE as well */ + if (wme_enabled) { + populate_dot11f_wmm_info_station_per_session(mac_ctx, + pe_session, &frm.WMMInfoStation); + if (wsm_enabled) + populate_dot11f_wmm_caps(&frm.WMMCaps); +#ifdef FEATURE_WLAN_ESE + if (pe_session->isESEconnection) { + uint32_t phymode; + uint8_t rate; + + populate_dot11f_re_assoc_tspec(mac_ctx, &frm, + pe_session); + + /* + * Populate the TSRS IE if TSPEC is included in + * the reassoc request + */ + lim_get_phy_mode(mac_ctx, &phymode, pe_session); + if (phymode == WNI_CFG_PHY_MODE_11G || + phymode == WNI_CFG_PHY_MODE_11A) + rate = TSRS_11AG_RATE_6MBPS; + else + rate = TSRS_11B_RATE_5_5MBPS; + + if (pe_session->pLimReAssocReq->eseTspecInfo. + numTspecs) { + tSirMacESETSRSIE tsrs_ie; + + tsrs_ie.tsid = 0; + tsrs_ie.rates[0] = rate; + populate_dot11_tsrsie(mac_ctx, &tsrs_ie, + &frm.ESETrafStrmRateSet, + sizeof(uint8_t)); + } + } +#endif + } + + ft_sme_context = &mac_ctx->roam.roamSession[sme_sessionid].ftSmeContext; + if (pe_session->htCapability && + mac_ctx->lim.htCapabilityPresentInBeacon) { + populate_dot11f_ht_caps(mac_ctx, pe_session, &frm.HTCaps); + } +#if defined WLAN_FEATURE_VOWIFI_11R + if (pe_session->pLimReAssocReq->bssDescription.mdiePresent && + (ft_sme_context->addMDIE == true) +#if defined FEATURE_WLAN_ESE + && !pe_session->isESEconnection +#endif + ) { + populate_mdie(mac_ctx, &frm.MobilityDomain, + pe_session->pLimReAssocReq->bssDescription.mdie); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if (pe_session->vhtCapability && + pe_session->vhtCapabilityPresentInBeacon) { + lim_log(mac_ctx, LOG1, + FL("Populate VHT IEs in Re-Assoc Request")); + populate_dot11f_vht_caps(mac_ctx, pe_session, &frm.VHTCaps); + vht_enabled = true; + populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm.ExtCap, + pe_session); + } + if (!vht_enabled && + pe_session->is_vendor_specific_vhtcaps) { + lim_log(mac_ctx, LOG1, + FL("Populate Vendor VHT IEs in Re-Assoc Request")); + frm.vendor2_ie.present = 1; + frm.vendor2_ie.type = + pe_session->vendor_specific_vht_ie_type; + frm.vendor2_ie.sub_type = + pe_session->vendor_specific_vht_ie_sub_type; + frm.vendor2_ie.VHTCaps.present = 1; + populate_dot11f_vht_caps(mac_ctx, pe_session, + &frm.vendor2_ie.VHTCaps); + vht_enabled = true; + } +#endif + + status = dot11f_get_packed_re_assoc_request_size(mac_ctx, &frm, + &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGP, + FL("Failure in size calculation (0x%08x)."), status); + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fReAssocRequest); + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("Warnings in size calculation(0x%08x)."), status); + } + + bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("FT IE Reassoc Req (%d)."), + ft_sme_context->reassoc_ft_ies_length); +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R + if (pe_session->is11Rconnection) + ft_ies_length = ft_sme_context->reassoc_ft_ies_length; +#endif + + cdf_status = cds_packet_alloc((uint16_t) bytes + ft_ies_length, + (void **)&frame, (void **)&packet); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pe_session->limMlmState = pe_session->limPrevMlmState; + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + pe_session->peSessionId, + pe_session->limMlmState)); + lim_log(mac_ctx, LOGP, FL("Failed to alloc memory %d"), bytes); + goto end; + } + /* Paranoia: */ + cdf_mem_set(frame, bytes + ft_ies_length, 0); + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + lim_print_mac_addr(mac_ctx, pe_session->limReAssocbssId, LOG1); +#endif + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_REASSOC_REQ, pe_session->limReAssocbssId, + pe_session->selfMacAddr); + mac_hdr = (tpSirMacMgmtHdr) frame; + /* That done, pack the ReAssoc Request: */ + status = dot11f_pack_re_assoc_request(mac_ctx, &frm, frame + + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, FL("Failure in pack (0x%08x)."), status); + cds_packet_free((void *)packet); + goto end; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, FL("Warnings in pack (0x%08x)."), + status); + } + + lim_log(mac_ctx, LOG3, + FL("*** Sending Re-Assoc Request length %d %d to "), + bytes, payload); + + if (pe_session->assocReq != NULL) { + cdf_mem_free(pe_session->assocReq); + pe_session->assocReq = NULL; + } + + if (add_ie_len) { + cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload, + add_ie, add_ie_len); + payload += add_ie_len; + } + + pe_session->assocReq = cdf_mem_malloc(payload); + if (NULL == pe_session->assocReq) { + lim_log(mac_ctx, LOGE, FL("Failed to alloc memory")); + } else { + /* + * Store the Assoc request. This is sent to csr/hdd in + * join cnf response. + */ + cdf_mem_copy(pe_session->assocReq, + frame + sizeof(tSirMacMgmtHdr), payload); + pe_session->assocReqLen = payload; + } + + if (pe_session->is11Rconnection && ft_sme_context->reassoc_ft_ies) { + int i = 0; + + body = frame + bytes; + for (i = 0; i < ft_ies_length; i++) { + *body = ft_sme_context->reassoc_ft_ies[i]; + body++; + } + } +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOGE(lim_log(mac_ctx, LOG1, FL("Re-assoc Req Frame is: ")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG1, + (uint8_t *) frame, (bytes + ft_ies_length)); + ) +#endif + if ((SIR_BAND_5_GHZ == + lim_get_rf_band(pe_session->currentOperChannel)) || + (pe_session->pePersona == CDF_P2P_CLIENT_MODE) || + (pe_session->pePersona == CDF_P2P_GO_MODE)) { + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if (NULL != pe_session->assocReq) { + cdf_mem_free(pe_session->assocReq); + pe_session->assocReq = NULL; + } + + pe_session->assocReq = cdf_mem_malloc(ft_ies_length); + if (NULL == pe_session->assocReq) { + lim_log(mac_ctx, LOGE, FL("Failed to alloc memory")); + pe_session->assocReqLen = 0; + } else { + /* + * Store the Assoc request. This is sent to csr/hdd in + * join cnf response. + */ + cdf_mem_copy(pe_session->assocReq, + ft_sme_context->reassoc_ft_ies, (ft_ies_length)); + pe_session->assocReqLen = (ft_ies_length); + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_START_EVENT, + pe_session, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + pe_session->peSessionId, mac_hdr->fc.subType)); + cdf_status = wma_tx_frame(mac_ctx, packet, + (uint16_t) (bytes + ft_ies_length), + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, frame, tx_flag, sme_sessionid, + 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + pe_session->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to send Re-Assoc Request (%X)!"), + cdf_status); + } + +end: + /* Free up buffer allocated for mlmAssocReq */ + cdf_mem_free(mlm_reassoc_req); + pe_session->pLimMlmReassocReq = NULL; + +} + +void lim_send_retry_reassoc_req_frame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq, + tpPESession psessionEntry) +{ + tLimMlmReassocCnf mlmReassocCnf; /* keep sme */ + tLimMlmReassocReq *pTmpMlmReassocReq = NULL; + if (NULL == pTmpMlmReassocReq) { + pTmpMlmReassocReq = cdf_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == pTmpMlmReassocReq) + goto end; + cdf_mem_set(pTmpMlmReassocReq, sizeof(tLimMlmReassocReq), 0); + cdf_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(cdf_trace(CDF_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 */ + lim_log(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; + } + + lim_send_reassoc_req_with_ft_ies_mgmt_frame(pMac, pTmpMlmReassocReq, + psessionEntry); + return; + +end: + /* Free up buffer allocated for reassocReq */ + if (pMlmReassocReq != NULL) { + cdf_mem_free(pMlmReassocReq); + pMlmReassocReq = NULL; + } + if (pTmpMlmReassocReq != NULL) { + cdf_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; + + lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, + (uint32_t *) &mlmReassocCnf); +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +void +lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq, + tpPESession psessionEntry) +{ + static tDot11fReAssocRequest frm; + uint16_t caps; + uint8_t *pFrame; + uint32_t nBytes, nPayload, nStatus; + uint8_t fQosEnabled, fWmeEnabled, fWsmEnabled; + void *pPacket; + CDF_STATUS cdf_status; + uint16_t nAddIELen; + uint8_t *pAddIE; + uint8_t *wpsIe = NULL; + uint8_t txFlag = 0; +#if defined WLAN_FEATURE_VOWIFI + uint8_t PowerCapsPopulated = false; +#endif + uint8_t smeSessionId = 0; + bool isVHTEnabled = 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; + + cdf_mem_set((uint8_t *) &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 + swap_bit_field16(caps, (uint16_t *) &frm.Capabilities); + + frm.ListenInterval.interval = pMlmReassocReq->listenInterval; + + cdf_mem_copy((uint8_t *) frm.CurrentAPAddress.mac, + (uint8_t *) psessionEntry->bssId, 6); + + populate_dot11f_ssid2(pMac, &frm.SSID); + populate_dot11f_supp_rates(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; + populate_dot11f_power_caps(pMac, &frm.PowerCaps, LIM_REASSOC, + psessionEntry); + populate_dot11f_supp_channels(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; + populate_dot11f_power_caps(pMac, &frm.PowerCaps, + LIM_REASSOC, psessionEntry); + } + } +#endif + + if (fQosEnabled) + populate_dot11f_qos_caps_station(pMac, &frm.QOSCapsStation); + + populate_dot11f_ext_supp_rates(pMac, POPULATE_DOT11F_RATES_OPERATIONAL, + &frm.ExtSuppRates, psessionEntry); + +#if defined WLAN_FEATURE_VOWIFI + if (pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(psessionEntry->limReassocBssCaps)) { + populate_dot11f_rrm_ie(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 */ + /* { */ + /* uint16_t length; */ + /* uint8_t 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) { + populate_dot11f_rsn_opaque(pMac, + &(psessionEntry->pLimReAssocReq->rsnIE), + &frm.RSNOpaque); + populate_dot11f_wpa_opaque(pMac, + &(psessionEntry->pLimReAssocReq->rsnIE), + &frm.WPAOpaque); +#if defined(FEATURE_WLAN_WAPI) + populate_dot11f_wapi_opaque(pMac, + &(psessionEntry->pLimReAssocReq-> + rsnIE), &frm.WAPIOpaque); +#endif /* defined(FEATURE_WLAN_WAPI) */ + } + /* include WME EDCA IE as well */ + if (fWmeEnabled) { + populate_dot11f_wmm_info_station_per_session(pMac, + psessionEntry, + &frm.WMMInfoStation); + + if (fWsmEnabled) + populate_dot11f_wmm_caps(&frm.WMMCaps); + } + + if (psessionEntry->htCapability && + pMac->lim.htCapabilityPresentInBeacon) { + populate_dot11f_ht_caps(pMac, psessionEntry, &frm.HTCaps); + } +#ifdef WLAN_FEATURE_11AC + if (psessionEntry->vhtCapability && + psessionEntry->vhtCapabilityPresentInBeacon) { + lim_log(pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request")); + populate_dot11f_vht_caps(pMac, psessionEntry, &frm.VHTCaps); + isVHTEnabled = true; + } +#endif + + populate_dot11f_ext_cap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + + nStatus = dot11f_get_packed_re_assoc_request_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(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; + + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + psessionEntry->limMlmState = psessionEntry->limPrevMlmState; + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE, + psessionEntry->peSessionId, + psessionEntry->limMlmState)); + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a Re-As" + "sociation Request."), nBytes); + goto end; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_REASSOC_REQ, psessionEntry->limReAssocbssId, + psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + /* That done, pack the Probe Request: */ + nStatus = dot11f_pack_re_assoc_request(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, FL("Failed to pack a Re-Association Reque" + "st (0x%08x)."), nStatus); + cds_packet_free((void *)pPacket); + goto end; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a R" + "e-Association Request (0x%08x)."), + nStatus); + } + + PELOG1(lim_log + (pMac, LOG1, + FL("*** Sending Re-Association Request length %d" "to "), + nBytes); + ) + + if (psessionEntry->assocReq != NULL) { + cdf_mem_free(psessionEntry->assocReq); + psessionEntry->assocReq = NULL; + } + + if (nAddIELen) { + cdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, + pAddIE, nAddIELen); + nPayload += nAddIELen; + } + + psessionEntry->assocReq = cdf_mem_malloc(nPayload); + if (NULL == psessionEntry->assocReq) { + PELOGE(lim_log + (pMac, LOGE, + FL("Unable to allocate memory to store assoc request")); + ) + } else { + /* Store the Assoc request. This is sent to csr/hdd in join cnf response. */ + cdf_mem_copy(psessionEntry->assocReq, + pFrame + sizeof(tSirMacMgmtHdr), nPayload); + psessionEntry->assocReqLen = nPayload; + } + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_REASSOC_START_EVENT, + psessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = + wma_tx_frame(pMac, pPacket, + (uint16_t) (sizeof(tSirMacMgmtHdr) + nPayload), + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, pFrame, txFlag, smeSessionId, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send Re-Association Request (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + } + +end: + /* Free up buffer allocated for mlmAssocReq */ + cdf_mem_free(pMlmReassocReq); + psessionEntry->pLimMlmReassocReq = NULL; + +} /* lim_send_reassoc_req_mgmt_frame */ + +/** + * lim_send_auth_mgmt_frame() - Send an Authentication frame + * + * @mac_ctx: Pointer to Global MAC structure + * @auth_frame: Pointer to Authentication frame structure + * @peer_addr: MAC address of destination peer + * @wep_bit: wep bit in frame control for Authentication frame3 + * @session: PE session information + * + * This function is called by lim_process_mlm_messages(). Authentication frame + * is formatted and sent when this function is called. + * + * Return: void + */ + +void +lim_send_auth_mgmt_frame(tpAniSirGlobal mac_ctx, + tpSirMacAuthFrameBody auth_frame, + tSirMacAddr peer_addr, + uint8_t wep_bit, tpPESession session) +{ + uint8_t *frame, *body; + uint32_t frame_len = 0, body_len = 0; + tpSirMacMgmtHdr mac_hdr; + void *packet; + CDF_STATUS cdf_status; + uint8_t tx_flag = 0; + uint8_t sme_sessionid = 0; + uint16_t ft_ies_length = 0; + + if (NULL == session) { + lim_log(mac_ctx, LOGE, FL("Error: psession Entry is NULL")); + return; + } + + sme_sessionid = session->smeSessionId; + + lim_log(mac_ctx, LOG1, + FL("Sending Auth seq# %d status %d (%d) to " MAC_ADDRESS_STR), + auth_frame->authTransactionSeqNumber, + auth_frame->authStatusCode, + (auth_frame->authStatusCode == eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(peer_addr)); + + switch (auth_frame->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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET; + +#if defined WLAN_FEATURE_VOWIFI_11R + if (auth_frame->authAlgoNumber == eSIR_FT_AUTH) { + if (NULL != session->ftPEContext.pFTPreAuthReq && + 0 != session->ftPEContext.pFTPreAuthReq-> + ft_ies_length) { + ft_ies_length = session->ftPEContext. + pFTPreAuthReq->ft_ies_length; + frame_len += ft_ies_length; + lim_log(mac_ctx, LOG3, + FL("Auth frame, FTIES length added=%d"), + ft_ies_length); + } else { + lim_log(mac_ctx, LOG3, + FL("Auth frame, Does not contain FTIES!!!")); + frame_len += (2 + SIR_MDIE_SIZE); + } + } +#endif + break; + + case SIR_MAC_AUTH_FRAME_2: + if ((auth_frame->authAlgoNumber == eSIR_OPEN_SYSTEM) || + ((auth_frame->authAlgoNumber == eSIR_SHARED_KEY) && + (auth_frame->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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + body_len = 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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + sizeof(tSirMacAuthFrame); + body_len = sizeof(tSirMacAuthFrameBody); + } + break; + + case SIR_MAC_AUTH_FRAME_3: + if (wep_bit == 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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + LIM_ENCR_AUTH_BODY_LEN; + body_len = LIM_ENCR_AUTH_BODY_LEN; + } else { + + /* + * 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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + body_len = 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. + */ + + frame_len = sizeof(tSirMacMgmtHdr) + + SIR_MAC_AUTH_CHALLENGE_OFFSET; + body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET; + + break; + } /* switch (auth_frame->authTransactionSeqNumber) */ + + cdf_status = cds_packet_alloc((uint16_t) frame_len, (void **)&frame, + (void **)&packet); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, + FL("call to bufAlloc failed for AUTH frame")); + return; + } + + cdf_mem_zero(frame, frame_len); + + /* Prepare BD */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_AUTH, peer_addr, session->selfMacAddr); + mac_hdr = (tpSirMacMgmtHdr) frame; + mac_hdr->fc.wep = wep_bit; + + /* Prepare BSSId */ + if (LIM_IS_AP_ROLE(session) || + LIM_IS_BT_AMP_AP_ROLE(session)) + cdf_mem_copy((uint8_t *) mac_hdr->bssId, + (uint8_t *) session->bssId, + sizeof(tSirMacAddr)); + + /* Prepare Authentication frame body */ + body = frame + sizeof(tSirMacMgmtHdr); + + if (wep_bit == LIM_WEP_IN_FC) { + cdf_mem_copy(body, (uint8_t *) auth_frame, body_len); + + lim_log(mac_ctx, LOG1, + FL("*** Sending Auth seq# 3 status %d (%d) to" + MAC_ADDRESS_STR), + auth_frame->authStatusCode, + (auth_frame->authStatusCode == eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(mac_hdr->da)); + + } else { + *((uint16_t *) (body)) = + sir_swap_u16if_needed(auth_frame->authAlgoNumber); + body += sizeof(uint16_t); + body_len -= sizeof(uint16_t); + + *((uint16_t *) (body)) = + sir_swap_u16if_needed( + auth_frame->authTransactionSeqNumber); + body += sizeof(uint16_t); + body_len -= sizeof(uint16_t); + + *((uint16_t *) (body)) = + sir_swap_u16if_needed(auth_frame->authStatusCode); + body += sizeof(uint16_t); + body_len -= sizeof(uint16_t); + if (body_len <= (sizeof(auth_frame->type) + + sizeof(auth_frame->length) + + sizeof(auth_frame->challengeText))) + cdf_mem_copy(body, (uint8_t *) &auth_frame->type, + body_len); + +#if defined WLAN_FEATURE_VOWIFI_11R + if ((auth_frame->authAlgoNumber == eSIR_FT_AUTH) && + (auth_frame->authTransactionSeqNumber == + SIR_MAC_AUTH_FRAME_1) && + (session->ftPEContext.pFTPreAuthReq != NULL)) { + + if (ft_ies_length > 0) { + cdf_mem_copy(body, + session->ftPEContext. + pFTPreAuthReq->ft_ies, + ft_ies_length); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG2, + FL("Auth1 Frame FTIE is: ")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, + (uint8_t *) body, + ft_ies_length); +#endif + } else if (NULL != session->ftPEContext. + pFTPreAuthReq->pbssDescription) { + /* MDID attr is 54 */ + *body = SIR_MDIE_ELEMENT_ID; + body++; + *body = SIR_MDIE_SIZE; + body++; + cdf_mem_copy(body, + &session->ftPEContext.pFTPreAuthReq-> + pbssDescription->mdie[0], + SIR_MDIE_SIZE); + } + } +#endif + + lim_log(mac_ctx, LOG1, + FL("*** Sending Auth seq# %d status %d (%d) to " + MAC_ADDRESS_STR), + auth_frame->authTransactionSeqNumber, + auth_frame->authStatusCode, + (auth_frame->authStatusCode == + eSIR_MAC_SUCCESS_STATUS), + MAC_ADDR_ARRAY(mac_hdr->da)); + } + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, frame, frame_len); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(session->currentOperChannel)) + || (session->pePersona == CDF_P2P_CLIENT_MODE) + || (session->pePersona == CDF_P2P_GO_MODE) +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + || ((NULL != session->ftPEContext.pFTPreAuthReq) && + (SIR_BAND_5_GHZ == + lim_get_rf_band(session->ftPEContext.pFTPreAuthReq-> + preAuthchannelNum))) +#endif + ) + tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + + + if (session->pePersona == CDF_P2P_CLIENT_MODE) + tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK; + + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + session->peSessionId, mac_hdr->fc.subType)); + /* Queue Authentication frame in high priority WQ */ + cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) frame_len, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, 7, lim_tx_complete, + frame, tx_flag, sme_sessionid, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + session->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + lim_log(mac_ctx, LOGE, + FL("*** Could not send Auth frame, retCode=%X ***"), + cdf_status); + + return; +} + +CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac) +{ + uint16_t aid; + tpDphHashNode pStaDs; + tLimMlmDeauthReq *pMlmDeauthReq; + tLimMlmDeauthCnf mlmDeauthCnf; + tpPESession psessionEntry; + + pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (pMlmDeauthReq) { + if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer)) { + lim_deactivate_and_change_timer(pMac, + eLIM_DEAUTH_ACK_TIMER); + } + + psessionEntry = pe_find_session_by_session_id(pMac, + pMlmDeauthReq->sessionId); + if (psessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, + FL + ("session does not exist for given sessionId")); + ) + mlmDeauthCnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + pStaDs = + dph_lookup_hash_entry(pMac, pMlmDeauthReq->peerMacAddr, &aid, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + /* / Receive path cleanup with dummy packet */ + lim_ft_cleanup_pre_auth_info(pMac, psessionEntry); + lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); + /* / Free up buffer allocated for mlmDeauthReq */ + cdf_mem_free(pMlmDeauthReq); + pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; + } + return CDF_STATUS_SUCCESS; +end: + cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr, + (uint8_t *) pMlmDeauthReq->peerMacAddr, + sizeof(tSirMacAddr)); + mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger; + mlmDeauthCnf.aid = pMlmDeauthReq->aid; + mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId; + + /* Free up buffer allocated */ + /* for mlmDeauthReq */ + cdf_mem_free(pMlmDeauthReq); + + lim_post_sme_message(pMac, + LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlmDeauthCnf); + return CDF_STATUS_SUCCESS; +} + +/** + * lim_send_disassoc_cnf() - Send disassoc confirmation to SME + * + * @mac_ctx: Handle to MAC context + * + * Sends disassoc confirmation to SME. Removes disassoc request stored + * in lim. + * + * Return: CDF_STATUS_SUCCESS + */ + +CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx) +{ + uint16_t aid; + tpDphHashNode sta_ds; + tLimMlmDisassocCnf disassoc_cnf; + tpPESession pe_session; + tLimMlmDisassocReq *disassoc_req; + + disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; + if (disassoc_req) { + if (tx_timer_running( + &mac_ctx->lim.limTimers.gLimDisassocAckTimer)) + lim_deactivate_and_change_timer(mac_ctx, + eLIM_DISASSOC_ACK_TIMER); + + pe_session = pe_find_session_by_session_id( + mac_ctx, disassoc_req->sessionId); + if (pe_session == NULL) { + lim_log(mac_ctx, LOGE, + FL("No session for given sessionId")); + disassoc_cnf.resultCode = + eSIR_SME_INVALID_PARAMETERS; + goto end; + } + + sta_ds = dph_lookup_hash_entry(mac_ctx, + disassoc_req->peerMacAddr, &aid, + &pe_session->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, FL("StaDs Null")); + disassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + goto end; + } + /* Receive path cleanup with dummy packet */ + if (eSIR_SUCCESS != + lim_cleanup_rx_path(mac_ctx, sta_ds, pe_session)) { + disassoc_cnf.resultCode = + eSIR_SME_RESOURCES_UNAVAILABLE; + lim_log(mac_ctx, LOGE, FL("cleanup_rx_path error")); + goto end; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (LIM_IS_STA_ROLE(pe_session) && ( +#ifdef FEATURE_WLAN_ESE + (pe_session->isESEconnection) || +#endif +#ifdef FEATURE_WLAN_LFR + (pe_session->isFastRoamIniFeatureEnabled) || +#endif + (pe_session->is11Rconnection)) && + (disassoc_req->reasonCode != + eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { + lim_log(mac_ctx, LOGE, + FL("FT Preauth Session (%p,%d) Clean up"), + pe_session, pe_session->peSessionId); + +#if defined WLAN_FEATURE_VOWIFI_11R + /* Delete FT session if there exists one */ + lim_ft_cleanup_pre_auth_info(mac_ctx, pe_session); +#endif + } else { + lim_log(mac_ctx, 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(pe_session), +#ifdef FEATURE_WLAN_ESE + pe_session->isESEconnection, +#endif +#ifdef FEATURE_WLAN_LFR + pe_session->isFastRoamIniFeatureEnabled, +#endif + pe_session->is11Rconnection, + disassoc_req->reasonCode); + } +#endif + /* Free up buffer allocated for mlmDisassocReq */ + cdf_mem_free(disassoc_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL; + return CDF_STATUS_SUCCESS; + } else { + return CDF_STATUS_SUCCESS; + } +end: + cdf_mem_copy((uint8_t *) &disassoc_cnf.peerMacAddr, + (uint8_t *) disassoc_req->peerMacAddr, + sizeof(tSirMacAddr)); + disassoc_cnf.aid = disassoc_req->aid; + disassoc_cnf.disassocTrigger = disassoc_req->disassocTrigger; + + /* Update PE session ID */ + disassoc_cnf.sessionId = disassoc_req->sessionId; + + if (disassoc_req != NULL) { + /* / Free up buffer allocated for mlmDisassocReq */ + cdf_mem_free(disassoc_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL; + } + + lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF, + (uint32_t *) &disassoc_cnf); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS lim_disassoc_tx_complete_cnf(tpAniSirGlobal pMac, + uint32_t txCompleteSuccess) +{ + return lim_send_disassoc_cnf(pMac); +} + +CDF_STATUS lim_deauth_tx_complete_cnf(tpAniSirGlobal pMac, + uint32_t txCompleteSuccess) +{ + return lim_send_deauth_cnf(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 +lim_send_disassoc_mgmt_frame(tpAniSirGlobal pMac, + uint16_t nReason, + tSirMacAddr peer, + tpPESession psessionEntry, bool waitForAck) +{ + tDot11fDisassociation frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint32_t val = 0; + uint8_t 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 == CDF_SAP_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) && + (true == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL + ("CAC timer is running, drop disassoc from going out")); + return; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + frm.Reason.code = nReason; + + nStatus = dot11f_get_packed_disassociation_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Disassociation " + "(0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a Dis" + "association."), nBytes); + return; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_DISASSOC, peer, psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + /* Prepare the BSSID */ + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_disassociation(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Disassociation (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a D" + "isassociation (0x%08x)."), nStatus); + } + + lim_log(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 == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } + + if (waitForAck) { + MTRACE(cdf_trace(CDF_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 */ + cdf_status = + wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, 7, lim_tx_complete, + pFrame, lim_disassoc_tx_complete_cnf, + txFlag, smeSessionId, false, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + + val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT); + + if (tx_timer_change + (&pMac->lim.limTimers.gLimDisassocAckTimer, val, 0) + != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to change Disassoc ack Timer val")); + return; + } else if (TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers. + gLimDisassocAckTimer)) { + lim_log(pMac, LOGP, + FL("Unable to activate Disassoc ack Timer")); + lim_deactivate_and_change_timer(pMac, + eLIM_DISASSOC_ACK_TIMER); + return; + } + } else { + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, + pMacHdr->fc.subType)); + /* Queue Disassociation frame in high priority WQ */ + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send Disassociation (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + } + } +} /* End lim_send_disassoc_mgmt_frame. */ + +/** + * \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 +lim_send_deauth_mgmt_frame(tpAniSirGlobal pMac, + uint16_t nReason, + tSirMacAddr peer, + tpPESession psessionEntry, bool waitForAck) +{ + tDot11fDeAuth frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint32_t val = 0; +#ifdef FEATURE_WLAN_TDLS + uint16_t aid; + tpDphHashNode pStaDs; +#endif + uint8_t 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 == CDF_SAP_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) && + (true == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL + ("CAC timer is running, drop the deauth from going out")); + return; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + frm.Reason.code = nReason; + + nStatus = dot11f_get_packed_de_auth_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a De-Authentication " + "(0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a De-" + "Authentication."), nBytes); + return; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_DEAUTH, peer, psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + /* Prepare the BSSID */ + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_de_auth(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a DeAuthentication (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a D" + "e-Authentication (0x%08x)."), nStatus); + } + lim_log(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 == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; + } +#ifdef FEATURE_WLAN_TDLS + pStaDs = + dph_lookup_hash_entry(pMac, peer, &aid, + &psessionEntry->dph.dphHashTable); +#endif + + if (waitForAck) { + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, + pMacHdr->fc.subType)); + /* Queue Disassociation frame in high priority WQ */ + cdf_status = + wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, 7, lim_tx_complete, + pFrame, lim_deauth_tx_complete_cnf, + txFlag, smeSessionId, false, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + /* Pkt will be freed up by the callback lim_tx_complete */ + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send De-Authentication (%X)!"), + cdf_status); + + /* Call lim_process_deauth_ack_timeout which will send + * DeauthCnf for this frame + */ + lim_process_deauth_ack_timeout(pMac); + return; + } + + val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT); + + if (tx_timer_change + (&pMac->lim.limTimers.gLimDeauthAckTimer, val, 0) + != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to change Deauth ack Timer val")); + return; + } else if (TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers. + gLimDeauthAckTimer)) { + lim_log(pMac, LOGP, + FL("Unable to activate Deauth ack Timer")); + lim_deactivate_and_change_timer(pMac, + eLIM_DEAUTH_ACK_TIMER); + return; + } + } else { + MTRACE(cdf_trace(CDF_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 */ + cdf_status = + wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_IBSS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + } else { +#endif + /* Queue Disassociation frame in high priority WQ */ + cdf_status = + wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); +#ifdef FEATURE_WLAN_TDLS + } +#endif + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send De-Authentication (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + } + } + +} /* End lim_send_deauth_mgmt_frame. */ + +#ifdef ANI_SUPPORT_11H +/** + * \brief Send a Measurement Report Action frame + * + * + * \param pMac Pointer to the global MAC structure + * + * \param pMeasReqFrame Address of a tSirMacMeasReqActionFrame + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +lim_send_meas_report_frame(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pMeasReqFrame, + tSirMacAddr peer, tpPESession psessionEntry) +{ + tDot11fMeasurementReport frm; + uint8_t *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT; + frm.Action.action = SIR_MAC_ACTION_MEASURE_REPORT_ID; + frm.DialogToken.token = pMeasReqFrame->actionHeader.dialogToken; + + switch (pMeasReqFrame->measReqIE.measType) { + case SIR_MAC_BASIC_MEASUREMENT_TYPE: + nSirStatus = + populate_dot11f_measurement_report0(pMac, pMeasReqFrame, + &frm.MeasurementReport); + break; + case SIR_MAC_CCA_MEASUREMENT_TYPE: + nSirStatus = + populate_dot11f_measurement_report1(pMac, pMeasReqFrame, + &frm.MeasurementReport); + break; + case SIR_MAC_RPI_MEASUREMENT_TYPE: + nSirStatus = + populate_dot11f_measurement_report2(pMac, pMeasReqFrame, + &frm.MeasurementReport); + break; + default: + lim_log(pMac, LOGE, FL("Unknown measurement type %d in limSen" + "dMeasReportFrame."), + pMeasReqFrame->measReqIE.measType); + return eSIR_FAILURE; + } + + if (eSIR_SUCCESS != nSirStatus) + return eSIR_FAILURE; + + nStatus = dot11f_get_packed_measurement_report_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGP, FL("Failed to calculate the packed size f" + "or a Measurement Report (0x%08x)."), + nStatus); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof(tDot11fMeasurementReport); + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Measurement Rep" + "ort (0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a De-" + "Authentication."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_measurement_report(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Measurement Report (0x%08x)."), + nStatus); + cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (void *)pFrame, (void *)pPacket); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a M" + "easurement Report (0x%08x)."), nStatus); + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + ((psessionEntry) ? psessionEntry-> + peSessionId : NO_SESSION), pMacHdr->fc.subType)); + cdf_status = + wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, pFrame, 0, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION), + cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a Measurement Report (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; /* just allocated... */ + } + + return eSIR_SUCCESS; + +} /* End lim_send_meas_report_frame. */ + +/** + * \brief Send a TPC Request Action frame + * + * + * \param pMac Pointer to the global MAC datastructure + * + * \param peer MAC address to which the frame should be sent + * + * + */ + +void +lim_send_tpc_request_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, tpPESession psessionEntry) +{ + tDot11fTPCRequest frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT; + frm.Action.action = SIR_MAC_ACTION_TPC_REQUEST_ID; + frm.DialogToken.token = 1; + frm.TPCRequest.present = 1; + + nStatus = dot11f_get_packed_tpc_request_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGP, FL("Failed to calculate the packed size f" + "or a TPC Request (0x%08x)."), nStatus); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof(tDot11fTPCRequest); + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a TPC Request (0x" + "%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Request."), nBytes); + return; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_tpc_request(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x)."), + nStatus); + cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (void *)pFrame, (void *)pPacket); + return; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a T" + "PC Request (0x%08x)."), nStatus); + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + ((psessionEntry) ? psessionEntry-> + peSessionId : NO_SESSION), pMacHdr->fc.subType)); + cdf_status = + wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, pFrame, 0, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION), + cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a TPC Request (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + } + +} /* End lim_send_tpc_request_frame. */ + +/** + * \brief Send a TPC Report Action frame + * + * + * \param pMac Pointer to the global MAC datastructure + * + * \param pTpcReqFrame Pointer to the received TPC Request + * + * \return eSIR_SUCCESS on success, eSIR_FAILURE else + * + * + */ + +tSirRetStatus +lim_send_tpc_report_frame(tpAniSirGlobal pMac, + tpSirMacTpcReqActionFrame pTpcReqFrame, + tSirMacAddr peer, tpPESession psessionEntry) +{ + tDot11fTPCReport frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + + cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0); + + frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT; + frm.Action.action = SIR_MAC_ACTION_TPC_REPORT_ID; + frm.DialogToken.token = pTpcReqFrame->actionHeader.dialogToken; + + frm.TPCReport.tx_power = 0; + frm.TPCReport.link_margin = 0; + frm.TPCReport.present = 1; + + nStatus = dot11f_get_packed_tpc_report_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGP, FL("Failed to calculate the packed size f" + "or a TPC Report (0x%08x)."), nStatus); + /* We'll fall back on the worst case scenario: */ + nPayload = sizeof(tDot11fTPCReport); + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a TPC Report (0x" + "%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Report."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer); + + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_tpc_report(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x)."), + nStatus); + cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT, + (void *)pFrame, (void *)pPacket); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a T" + "PC Report (0x%08x)."), nStatus); + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + ((psessionEntry) ? psessionEntry-> + peSessionId : NO_SESSION), pMacHdr->fc.subType)); + cdf_status = + wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, + lim_tx_complete, pFrame, 0, 0); + MTRACE(cdf_trace + (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION), + cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a TPC Report (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; /* just allocated... */ + } + + return eSIR_SUCCESS; + +} /* End lim_send_tpc_report_frame. */ +#endif /* ANI_SUPPORT_11H */ + +/** + * \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 +lim_send_channel_switch_mgmt_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, + uint8_t nMode, + uint8_t nNewChannel, + uint8_t nCount, tpPESession psessionEntry) +{ + tDot11fChannelSwitch frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; /* , nCfg; */ + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + + uint8_t smeSessionId = 0; + + if (psessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &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 = dot11f_get_packed_channel_switch_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Channel Switch (0x" + "%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Report."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, + psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + cdf_mem_copy((uint8_t *) pMacHdr->bssId, + (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + nStatus = dot11f_pack_channel_switch(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Channel Switch (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a C" + "hannel Switch (0x%08x)."), nStatus); + } + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a Channel Switch (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} /* End lim_send_channel_switch_mgmt_frame. */ + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus +lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, + uint8_t nMode, tpPESession psessionEntry) +{ + tDot11fOperatingMode frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload = 0, nStatus; /* , nCfg; */ + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + + uint8_t smeSessionId = 0; + + if (psessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &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 = dot11f_get_packed_operating_mode_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Operating Mode (0x" + "%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a Operating Mode" + " Report."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + if (psessionEntry->pePersona == CDF_SAP_MODE) + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, + psessionEntry->selfMacAddr); + else + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, psessionEntry->bssId, + psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + cdf_mem_copy((uint8_t *) pMacHdr->bssId, + (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); + nStatus = dot11f_pack_operating_mode(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Operating Mode (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing a Operating Mode" + " (0x%08x)."), nStatus); + } + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a Channel Switch (%X)!"), + cdf_status); + /* 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 +lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, + uint8_t nChanWidth, + uint8_t nNewChannel, + uint8_t ncbMode, tpPESession psessionEntry) +{ + tDot11fChannelSwitch frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; /* , nCfg; */ + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + + uint8_t smeSessionId = 0; + + if (psessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));) + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &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 = + lim_get_htcb_state(ncbMode); + frm.sec_chan_offset_ele.present = 1; + frm.WiderBWChanSwitchAnn.newChanWidth = nChanWidth; + frm.WiderBWChanSwitchAnn.newCenterChanFreq0 = + lim_get_center_channel(pMac, nNewChannel, ncbMode, nChanWidth); + frm.WiderBWChanSwitchAnn.newCenterChanFreq1 = 0; + frm.ChanSwitchAnn.present = 1; + frm.WiderBWChanSwitchAnn.present = 1; + + nStatus = dot11f_get_packed_channel_switch_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Channel Switch (0x" + "%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" + " Report."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + pMacHdr = (tpSirMacMgmtHdr) pFrame; + cdf_mem_copy((uint8_t *) pMacHdr->bssId, + (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); + nStatus = dot11f_pack_channel_switch(pMac, &frm, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(pMac, LOGE, + FL("Failed to pack a Channel Switch (0x%08x)."), + nStatus); + cds_packet_free((void *)pPacket); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while packing a C" + "hannel Switch (0x%08x)."), nStatus); + } + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGE, + FL("Failed to send a Channel Switch (%X)!"), + cdf_status); + /* Pkt will be freed up by the callback */ + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} /* End lim_send_vht_channel_switch_mgmt_frame. */ + +#endif + +#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 +lim_send_neighbor_report_request_frame(tpAniSirGlobal pMac, + tpSirMacNeighborReportReq pNeighborReq, + tSirMacAddr peer, tpPESession psessionEntry) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tDot11fNeighborReportRequest frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL + ("(psession == NULL) in Request to send Neighbor Report request action frame")); + return eSIR_FAILURE; + } + smeSessionId = psessionEntry->smeSessionId; + cdf_mem_set((uint8_t *) &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) { + populate_dot11f_ssid(pMac, &pNeighborReq->ssid, &frm.SSID); + } + + nStatus = + dot11f_get_packed_neighbor_report_request_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Neighbor Rep" + "ort Request(0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a Neighbor " + "Report Request."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Copy necessary info to BD */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + + /* Update A3 with the BSSID */ + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + /* Now, we're ready to "pack" the frames */ + nStatus = dot11f_pack_neighbor_report_request(pMac, + &frm, + pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing Neighbor Report " + "Request (0x%08x)."), nStatus); + } + + lim_log(pMac, LOGW, FL("Sending a Neighbor Report Request to ")); + lim_print_mac_addr(pMac, peer, LOGW); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, + pPacket, + (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (CDF_STATUS_SUCCESS != cdf_status) { + PELOGE(lim_log + (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"), + cdf_status); + ) + statusCode = eSIR_FAILURE; + /* Pkt will be freed up by the callback */ + return statusCode; + } else + return eSIR_SUCCESS; + +returnAfterError: + cds_packet_free((void *)pPacket); + + return statusCode; +} /* End lim_send_neighbor_report_request_frame. */ + +/** + * \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 +lim_send_link_report_action_frame(tpAniSirGlobal pMac, + tpSirMacLinkReport pLinkReport, + tSirMacAddr peer, tpPESession psessionEntry) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tDot11fLinkMeasurementReport frm; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL + ("(psession == NULL) in Request to send Link Report action frame")); + return eSIR_FAILURE; + } + + cdf_mem_set((uint8_t *) &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 = + dot11f_get_packed_link_measurement_report_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Link Rep" + "ort (0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a Link " + "Report."), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Copy necessary info to BD */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + + /* Update A3 with the BSSID */ + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + /* Now, we're ready to "pack" the frames */ + nStatus = dot11f_pack_link_measurement_report(pMac, + &frm, + pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while packing Link Report (0x%08x)."), + nStatus); + } + + lim_log(pMac, LOGW, FL("Sending a Link Report to ")); + lim_print_mac_addr(pMac, peer, LOGW); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, + pPacket, + (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (CDF_STATUS_SUCCESS != cdf_status) { + PELOGE(lim_log + (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"), + cdf_status); + ) + statusCode = eSIR_FAILURE; + /* Pkt will be freed up by the callback */ + return statusCode; + } else + return eSIR_SUCCESS; + +returnAfterError: + cds_packet_free((void *)pPacket); + + return statusCode; +} /* End lim_send_link_report_action_frame. */ + +/** + * \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 +lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac, + uint8_t dialog_token, + uint8_t num_report, + tpSirMacRadioMeasureReport pRRMReport, + tSirMacAddr peer, + tpPESession psessionEntry) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + uint8_t *pFrame; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t i; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + tDot11fRadioMeasurementReport *frm = + cdf_mem_malloc(sizeof(tDot11fRadioMeasurementReport)); + if (!frm) { + lim_log(pMac, LOGE, + FL + ("Not enough memory to allocate tDot11fRadioMeasurementReport")); + return eSIR_MEM_ALLOC_FAILED; + } + + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL + ("(psession == NULL) in Request to send Beacon Report action frame")); + cdf_mem_free(frm); + return eSIR_FAILURE; + } + cdf_mem_set((uint8_t *) 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: + populate_dot11f_beacon_report(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 = + dot11f_get_packed_radio_measurement_report_size(pMac, frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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); + cdf_mem_free(frm); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(nStatus)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for a Radio Measure Rep" + "ort (0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + + cdf_status = + cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, + (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a Radio Measure " + "Report."), nBytes); + cdf_mem_free(frm); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Copy necessary info to BD */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + + /* Update A3 with the BSSID */ + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + +#ifdef WLAN_FEATURE_11W + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); +#endif + + /* Now, we're ready to "pack" the frames */ + nStatus = dot11f_pack_radio_measurement_report(pMac, + frm, + pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL("There were warnings while packing Radio " + "Measure Report (0x%08x)."), nStatus); + } + + lim_log(pMac, LOGW, FL("Sending a Radio Measure Report to ")); + lim_print_mac_addr(pMac, peer, LOGW); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, + pPacket, + (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (CDF_STATUS_SUCCESS != cdf_status) { + PELOGE(lim_log + (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"), + cdf_status); + ) + statusCode = eSIR_FAILURE; + /* Pkt will be freed up by the callback */ + cdf_mem_free(frm); + return statusCode; + } else { + cdf_mem_free(frm); + return eSIR_SUCCESS; + } + +returnAfterError: + cdf_mem_free(frm); + cds_packet_free((void *)pPacket); + return statusCode; +} + +#endif + +#ifdef WLAN_FEATURE_11W +/** + * \brief Send SA query request action frame to peer + * + * \sa lim_send_sa_query_request_frame + * + * + * \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 lim_send_sa_query_request_frame(tpAniSirGlobal pMac, uint8_t *transId, + tSirMacAddr peer, + tpPESession psessionEntry) +{ + + tDot11fSaQueryReq frm; /* SA query request action frame */ + uint8_t *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + cdf_mem_set((uint8_t *) &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 */ + cdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2); + + nStatus = dot11f_get_packed_sa_query_req_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an SA Query Request" + " (0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + cdf_status = + cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a SA Query Request " + "action frame"), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Copy necessary info to BD */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + + /* Update A3 with the BSSID */ + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + + /* Since this is a SA Query Request, set the "protect" (aka WEP) bit */ + /* in the FC */ + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); + + /* Pack 11w SA Query Request frame */ + nStatus = dot11f_pack_sa_query_req(pMac, + &frm, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while packing SA Query Request (0x%08x)."), + nStatus); + } + + lim_log(pMac, LOG1, FL("Sending an SA Query Request to ")); + lim_print_mac_addr(pMac, peer, LOG1); + lim_log(pMac, LOG1, FL("Sending an SA Query Request from ")); + lim_print_mac_addr(pMac, psessionEntry->selfMacAddr, LOG1); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) +#ifdef WLAN_FEATURE_P2P + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) +#endif + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + smeSessionId = psessionEntry->smeSessionId; + + cdf_status = wma_tx_frame(pMac, + pPacket, + (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + if (CDF_STATUS_SUCCESS != cdf_status) { + PELOGE(lim_log + (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"), + cdf_status); + ) + nSirStatus = eSIR_FAILURE; + /* Pkt will be freed up by the callback */ + return nSirStatus; + } else { + return eSIR_SUCCESS; + } + +returnAfterError: + cds_packet_free((void *)pPacket); + return nSirStatus; +} /* End lim_send_sa_query_request_frame */ + +/** + * \brief Send SA query response action frame to peer + * + * \sa lim_send_sa_query_response_frame + * + * + * \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 lim_send_sa_query_response_frame(tpAniSirGlobal pMac, + uint8_t *transId, tSirMacAddr peer, + tpPESession psessionEntry) +{ + + tDot11fSaQueryRsp frm; /* SA query reponse action frame */ + uint8_t *pFrame; + tSirRetStatus nSirStatus; + tpSirMacMgmtHdr pMacHdr; + uint32_t nBytes, nPayload, nStatus; + void *pPacket; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t smeSessionId = 0; + + smeSessionId = psessionEntry->smeSessionId; + + cdf_mem_set((uint8_t *) &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 */ + cdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2); + + nStatus = dot11f_get_packed_sa_query_rsp_size(pMac, &frm, &nPayload); + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, FL("There were warnings while calculating " + "the packed size for an SA Query Response" + " (0x%08x)."), nStatus); + } + + nBytes = nPayload + sizeof(tSirMacMgmtHdr); + cdf_status = + cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(pMac, LOGP, + FL("Failed to allocate %d bytes for a SA query response" + " action frame"), nBytes); + return eSIR_FAILURE; + } + /* Paranoia: */ + cdf_mem_set(pFrame, nBytes, 0); + + /* Copy necessary info to BD */ + lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); + + /* Update A3 with the BSSID */ + pMacHdr = (tpSirMacMgmtHdr) pFrame; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + + /* Since this is a SA Query Response, set the "protect" (aka WEP) bit */ + /* in the FC */ + lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr); + + /* Pack 11w SA query response frame */ + nStatus = dot11f_pack_sa_query_rsp(pMac, + &frm, + pFrame + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + lim_log(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)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while packing SA Query Response (0x%08x)."), + nStatus); + } + + lim_log(pMac, LOG1, FL("Sending a SA Query Response to ")); + lim_print_mac_addr(pMac, peer, LOGW); + + if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) +#ifdef WLAN_FEATURE_P2P + || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE) +#endif + ) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + psessionEntry->peSessionId, pMacHdr->fc.subType)); + cdf_status = wma_tx_frame(pMac, + pPacket, + (uint16_t) nBytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, lim_tx_complete, pFrame, txFlag, + smeSessionId, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + psessionEntry->peSessionId, cdf_status)); + if (CDF_STATUS_SUCCESS != cdf_status) { + PELOGE(lim_log + (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"), + cdf_status); + ) + nSirStatus = eSIR_FAILURE; + /* Pkt will be freed up by the callback */ + return nSirStatus; + } else { + return eSIR_SUCCESS; + } + +returnAfterError: + cds_packet_free((void *)pPacket); + return nSirStatus; +} /* End lim_send_sa_query_response_frame */ +#endif diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c new file mode 100644 index 000000000000..e47bf2fbc3a7 --- /dev/null +++ b/core/mac/src/pe/lim/lim_send_messages.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. + */ + +/* + * + * lim_send_messages.c: Provides functions to send messages or Indications to HAL. + * Author: Sunit Bhatia + * Date: 09/21/2006 + * History:- + * Date Modified by Modification Information + * + * -------------------------------------------------------------------------- + * + */ +#include "lim_send_messages.h" +#include "cfg_api.h" +#include "lim_trace.h" +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ +#include "host_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 beacon_filter_table[] = { + {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 +}; + +/** + * lim_send_cf_params() + * + ***FUNCTION: + * This function is called to send CFP Parameters to WMA, 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 lim_send_cf_params(tpAniSirGlobal pMac, uint8_t bssIdx, + uint8_t cfpCount, uint8_t cfpPeriod) +{ + tpUpdateCFParams pCFParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pCFParams = cdf_mem_malloc(sizeof(tUpdateCFParams)); + if (NULL == pCFParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update CF Params")); + retCode = eSIR_MEM_ALLOC_FAILED; + goto returnFailure; + } + cdf_mem_set((uint8_t *) pCFParams, sizeof(tUpdateCFParams), 0); + pCFParams->cfpCount = cfpCount; + pCFParams->cfpPeriod = cfpPeriod; + pCFParams->bssIdx = bssIdx; + + msgQ.type = WMA_UPDATE_CF_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pCFParams; + msgQ.bodyval = 0; + lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_CF_IND...")); + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pCFParams); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_CF_IND failed, reason=%X"), + retCode); + } +returnFailure: + return retCode; +} + +/** + * lim_send_beacon_params() - updates bcn params to WMA + * + * @pMac : pointer to Global Mac structure. + * @tpUpdateBeaconParams : pointer to the structure, which contains the beacon + * parameters which are changed. + * + * This function is called to send beacon interval, short preamble or other + * parameters to WMA, which are changed and indication is received in beacon. + * + * @return success if message send is ok, else false. + */ +tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, + tpUpdateBeaconParams pUpdatedBcnParams, + tpPESession psessionEntry) +{ + tpUpdateBeaconParams pBcnParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pBcnParams = cdf_mem_malloc(sizeof(*pBcnParams)); + if (NULL == pBcnParams) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update Beacon Params")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_copy((uint8_t *) pBcnParams, pUpdatedBcnParams, + sizeof(*pBcnParams)); + msgQ.type = WMA_UPDATE_BEACON_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pBcnParams; + msgQ.bodyval = 0; + PELOG3(lim_log(pMac, LOG3, + FL("Sending WMA_UPDATE_BEACON_IND, paramChangeBitmap in hex = %x"), + pUpdatedBcnParams->paramChangeBitmap);) + if (NULL == psessionEntry) { + cdf_mem_free(pBcnParams); + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + return eSIR_FAILURE; + } else { + MTRACE(mac_trace_msg_tx(pMac, + psessionEntry->peSessionId, + msgQ.type)); + } + pBcnParams->smeSessionId = psessionEntry->smeSessionId; + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pBcnParams); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_BEACON_IND, reason=%X"), + retCode); + } + lim_send_beacon_ind(pMac, psessionEntry); + return retCode; +} + +/** + * lim_send_switch_chnl_params() + * + ***FUNCTION: + * This function is called to send Channel Switch Indication to WMA + * + ***LOGIC: + * + ***ASSUMPTIONS: + * NA + * + ***NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param chnlNumber New Channel Number to be switched to. + * @param ch_width an enum for channel width. + * @param localPowerConstraint 11h local power constraint value + * + * @return success if message send is ok, else false. + */ +#if !defined WLAN_FEATURE_VOWIFI +tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, + uint8_t chnlNumber, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, + uint8_t localPwrConstraint, + uint8_t peSessionId, + uint8_t is_restart) +#else +tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, + uint8_t chnlNumber, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, + tPowerdBm maxTxPower, + uint8_t peSessionId, + uint8_t is_restart) +#endif +{ + tpSwitchChannelParams pChnlParams = NULL; + tSirMsgQ msgQ; + tpPESession pSessionEntry; + pSessionEntry = pe_find_session_by_session_id(pMac, peSessionId); + if (pSessionEntry == NULL) { + lim_log(pMac, LOGP, FL( + "Unable to get Session for session Id %d"), + peSessionId); + return eSIR_FAILURE; + } + pChnlParams = cdf_mem_malloc(sizeof(tSwitchChannelParams)); + if (NULL == pChnlParams) { + lim_log(pMac, LOGP, FL( + "Unable to allocate memory for Switch Ch Params")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set((uint8_t *) pChnlParams, sizeof(tSwitchChannelParams), 0); + pChnlParams->channelNumber = chnlNumber; + pChnlParams->ch_center_freq_seg0 = ch_center_freq_seg0; + pChnlParams->ch_center_freq_seg1 = ch_center_freq_seg1; + pChnlParams->ch_width = ch_width; + cdf_mem_copy(pChnlParams->selfStaMacAddr, pSessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); +#if defined WLAN_FEATURE_VOWIFI + pChnlParams->maxTxPower = maxTxPower; +#else + pChnlParams->localPowerConstraint = localPwrConstraint; +#endif + cdf_mem_copy(pChnlParams->bssId, pSessionEntry->bssId, + sizeof(tSirMacAddr)); + pChnlParams->peSessionId = peSessionId; + pChnlParams->vhtCapable = pSessionEntry->vhtCapability; + pChnlParams->dot11_mode = pSessionEntry->dot11mode; + pChnlParams->nss = pSessionEntry->nss; + lim_log(pMac, LOG2, FL("nss value: %d"), pChnlParams->nss); + + /*Set DFS flag for DFS channel */ + if (cds_get_channel_state(chnlNumber) == CHANNEL_STATE_DFS) + pChnlParams->isDfsChannel = true; + else + pChnlParams->isDfsChannel = false; + + pChnlParams->restart_on_chan_switch = is_restart; + + /* we need to defer the message until we + * get the response back from WMA + */ + SET_LIM_PROCESS_DEFD_MESGS(pMac, false); + msgQ.type = WMA_CHNL_SWITCH_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pChnlParams; + msgQ.bodyval = 0; +#if defined WLAN_FEATURE_VOWIFI + PELOG3(lim_log(pMac, LOG3, FL( + "Sending CH_SWITCH_REQ, ch_width %d, ch_num %d, maxTxPower %d"), + pChnlParams->ch_width, + pChnlParams->channelNumber, pChnlParams->maxTxPower);) +#else + PELOG3(lim_log(pMac, LOG3, FL( + "Sending CH_SWITCH_REQ, ch_width %d, ch_num %d, local_pwr_constraint %d"), + pChnlParams->ch_width, + pChnlParams->channelNumber, + pChnlParams->localPowerConstraint);) +#endif + MTRACE(mac_trace_msg_tx(pMac, peSessionId, msgQ.type)); + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msgQ)) { + cdf_mem_free(pChnlParams); + lim_log(pMac, LOGP, FL( + "Posting CH_SWITCH_REQ to WMA failed")); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** + * lim_send_edca_params() + * + ***FUNCTION: + * This function is called to send dynamically changing EDCA Parameters to WMA. + * + ***LOGIC: + * + ***ASSUMPTIONS: + * NA + * + ***NOTE: + * NA + * + * @param pMac pointer to Global Mac structure. + * @param tpUpdatedEdcaParams pointer to the structure which contains + * dynamically changing EDCA parameters. + * @param highPerformance If the peer is Airgo (taurus) then switch to highPerformance is true. + * + * @return success if message send is ok, else false. + */ +tSirRetStatus lim_send_edca_params(tpAniSirGlobal pMac, + tSirMacEdcaParamRecord *pUpdatedEdcaParams, + uint16_t bssIdx) +{ + tEdcaParams *pEdcaParams = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + uint8_t i; + + pEdcaParams = cdf_mem_malloc(sizeof(tEdcaParams)); + if (NULL == pEdcaParams) { + lim_log(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 = WMA_UPDATE_EDCA_PROFILE_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pEdcaParams; + msgQ.bodyval = 0; + PELOG1(lim_log(pMac, LOG1, + FL("Sending WMA_UPDATE_EDCA_PROFILE_IND, EDCA Parameters:"));) + for (i = 0; i < MAX_NUM_AC; i++) { + PELOG1(lim_log(pMac, LOG1, + FL("AC[%d]: AIFSN %d, ACM %d, CWmin %d, CWmax %d, TxOp %d "), + i, pUpdatedEdcaParams[i].aci.aifsn, + pUpdatedEdcaParams[i].aci.acm, + pUpdatedEdcaParams[i].cw.min, + pUpdatedEdcaParams[i].cw.max, + pUpdatedEdcaParams[i].txoplimit);) + } + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pEdcaParams); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_EDCA_PROFILE_IND failed, reason=%X"), + retCode); + } + return retCode; +} + +/** + * lim_set_active_edca_params() - Choose best EDCA parameters + * + * @mac_ctx: pointer to Global Mac structure. + * @edca_params: pointer to the local EDCA parameters + * @pe_session: point to the session entry + * + * This function is called to set the most up-to-date EDCA parameters + * given the default local EDCA parameters. The rules are as following: + * - If ACM bit is set for all ACs, then downgrade everything to Best Effort. + * - If ACM is not set for any AC, then PE will use the default EDCA + * parameters as advertised by AP. + * - If ACM is set in any of the ACs, PE will use the EDCA parameters + * from the next best AC for which ACM is not enabled. + * + * Return: none + */ + +void lim_set_active_edca_params(tpAniSirGlobal mac_ctx, + tSirMacEdcaParamRecord *edca_params, + tpPESession pe_session) +{ + uint8_t ac, new_ac, i; + uint8_t ac_admitted; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + host_log_qos_edca_pkt_type *log_ptr = NULL; +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + /* Initialize gLimEdcaParamsActive[] to be same as localEdcaParams */ + pe_session->gLimEdcaParamsActive[EDCA_AC_BE] = edca_params[EDCA_AC_BE]; + pe_session->gLimEdcaParamsActive[EDCA_AC_BK] = edca_params[EDCA_AC_BK]; + pe_session->gLimEdcaParamsActive[EDCA_AC_VI] = edca_params[EDCA_AC_VI]; + pe_session->gLimEdcaParamsActive[EDCA_AC_VO] = edca_params[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. + */ + lim_log(mac_ctx, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "), + pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK]); + lim_log(mac_ctx, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "), + pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK]); + for (ac = EDCA_AC_BK; ac <= EDCA_AC_VO; ac++) { + ac_admitted = + ((pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & + (1 << ac)) >> ac); + + lim_log(mac_ctx, LOG1, + FL("For AC[%d]: acm=%d, ac_admitted=%d "), + ac, edca_params[ac].aci.acm, ac_admitted); + if ((edca_params[ac].aci.acm == 1) && (ac_admitted == 0)) { + lim_log(mac_ctx, LOG1, + FL("We need to downgrade AC %d!! "), ac); + /* Loop backwards through AC values until it finds + * acm == 0 or reaches EDCA_AC_BE. + * Note that for block has no executable statements. + */ + for (i = ac - 1; + (i > EDCA_AC_BE && + (edca_params[i].aci.acm != 0)); + i--) + ; + new_ac = i; + lim_log(mac_ctx, LOGW, + FL("Downgrading AC %d ---> AC %d "), + ac, new_ac); + pe_session->gLimEdcaParamsActive[ac] = + edca_params[new_ac]; + } + } +/* log: LOG_WLAN_QOS_EDCA_C */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type, + LOG_WLAN_QOS_EDCA_C); + if (log_ptr) { + tSirMacEdcaParamRecord *rec; + + rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_BE]; + log_ptr->aci_be = rec->aci.aci; + log_ptr->cw_be = rec->cw.max << 4 | rec->cw.min; + log_ptr->txoplimit_be = rec->txoplimit; + + rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_BK]; + log_ptr->aci_bk = rec->aci.aci; + log_ptr->cw_bk = rec->cw.max << 4 | rec->cw.min; + log_ptr->txoplimit_bk = rec->txoplimit; + + rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_VI]; + log_ptr->aci_vi = rec->aci.aci; + log_ptr->cw_vi = rec->cw.max << 4 | rec->cw.min; + log_ptr->txoplimit_vi = rec->txoplimit; + + rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_VO]; + log_ptr->aci_vo = rec->aci.aci; + log_ptr->cw_vo = rec->cw.max << 4 | rec->cw.min; + log_ptr->txoplimit_vo = rec->txoplimit; + } + WLAN_HOST_DIAG_LOG_REPORT(log_ptr); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + return; +} + +/** --------------------------------------------------------- + \fn lim_set_link_state + \brief LIM sends a message to WMA to set the link state + \param tpAniSirGlobal pMac + \param tSirLinkState state + \return None + -----------------------------------------------------------*/ +tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state, + tSirMacAddr bssId, tSirMacAddr selfMacAddr, + tpSetLinkStateCallback callback, + void *callbackArg) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode; + tpLinkStateParams pLinkStateParams = NULL; + /* Allocate memory. */ + pLinkStateParams = cdf_mem_malloc(sizeof(tLinkStateParams)); + if (NULL == pLinkStateParams) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory while sending Set Link State")); + retCode = eSIR_MEM_ALLOC_FAILED; + return retCode; + } + cdf_mem_set((uint8_t *) pLinkStateParams, sizeof(tLinkStateParams), 0); + pLinkStateParams->state = state; + pLinkStateParams->callback = callback; + pLinkStateParams->callbackArg = callbackArg; + + /* Copy Mac address */ + sir_copy_mac_addr(pLinkStateParams->bssid, bssId); + sir_copy_mac_addr(pLinkStateParams->selfMacAddr, selfMacAddr); + + msgQ.type = WMA_SET_LINK_STATE; + msgQ.reserved = 0; + msgQ.bodyptr = pLinkStateParams; + msgQ.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + + retCode = (uint32_t) wma_post_ctrl_msg(pMac, &msgQ); + if (retCode != eSIR_SUCCESS) { + cdf_mem_free(pLinkStateParams); + lim_log(pMac, LOGP, + FL("Posting link state %d failed, reason = %x "), state, + retCode); + } + return retCode; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +extern tSirRetStatus lim_set_link_state_ft(tpAniSirGlobal pMac, tSirLinkState + state, tSirMacAddr bssId, + tSirMacAddr selfMacAddr, int ft, + tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tSirRetStatus retCode; + tpLinkStateParams pLinkStateParams = NULL; + /* Allocate memory. */ + pLinkStateParams = cdf_mem_malloc(sizeof(tLinkStateParams)); + if (NULL == pLinkStateParams) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory while sending Set Link State")); + retCode = eSIR_MEM_ALLOC_FAILED; + return retCode; + } + cdf_mem_set((uint8_t *) pLinkStateParams, sizeof(tLinkStateParams), 0); + pLinkStateParams->state = state; + /* Copy Mac address */ + sir_copy_mac_addr(pLinkStateParams->bssid, bssId); + sir_copy_mac_addr(pLinkStateParams->selfMacAddr, selfMacAddr); + pLinkStateParams->ft = 1; + pLinkStateParams->session = psessionEntry; + + msgQ.type = WMA_SET_LINK_STATE; + msgQ.reserved = 0; + msgQ.bodyptr = pLinkStateParams; + msgQ.bodyval = 0; + if (NULL == psessionEntry) { + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + } else { + MTRACE(mac_trace_msg_tx + (pMac, psessionEntry->peSessionId, msgQ.type)); + } + + retCode = (uint32_t) wma_post_ctrl_msg(pMac, &msgQ); + if (retCode != eSIR_SUCCESS) { + cdf_mem_free(pLinkStateParams); + lim_log(pMac, LOGP, + FL("Posting link state %d failed, reason = %x "), state, + retCode); + } + return retCode; +} +#endif + +/** --------------------------------------------------------- + \fn lim_send_beacon_filter_info + \brief LIM sends beacon filtering info to WMA + \param tpAniSirGlobal pMac + \return None + -----------------------------------------------------------*/ +tSirRetStatus lim_send_beacon_filter_info(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tpBeaconFilterMsg pBeaconFilterMsg = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + uint8_t *ptr; + uint32_t i; + uint32_t msgSize; + tpBeaconFilterIe pIe; + + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, FL("Fail to find the right session ")); + retCode = eSIR_FAILURE; + return retCode; + } + msgSize = sizeof(tBeaconFilterMsg) + sizeof(beacon_filter_table); + pBeaconFilterMsg = cdf_mem_malloc(msgSize); + if (NULL == pBeaconFilterMsg) { + lim_log(pMac, LOGP, + FL("Fail to allocate memory for beaconFiilterMsg ")); + retCode = eSIR_MEM_ALLOC_FAILED; + return retCode; + } + cdf_mem_set((uint8_t *) 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 = + (uint16_t) psessionEntry->beaconParams.beaconInterval; + /* Fill in number of IEs in beacon_filter_table */ + pBeaconFilterMsg->ieNum = + (uint16_t) (sizeof(beacon_filter_table) / sizeof(tBeaconFilterIe)); + /* Fill the BSSIDX */ + pBeaconFilterMsg->bssIdx = psessionEntry->bssIdx; + + /* Fill message with info contained in the beacon_filter_table */ + ptr = (uint8_t *) pBeaconFilterMsg + sizeof(tBeaconFilterMsg); + for (i = 0; i < (pBeaconFilterMsg->ieNum); i++) { + pIe = (tpBeaconFilterIe) ptr; + pIe->elementId = beacon_filter_table[i].elementId; + pIe->checkIePresence = beacon_filter_table[i].checkIePresence; + pIe->byte.offset = beacon_filter_table[i].byte.offset; + pIe->byte.value = beacon_filter_table[i].byte.value; + pIe->byte.bitMask = beacon_filter_table[i].byte.bitMask; + pIe->byte.ref = beacon_filter_table[i].byte.ref; + ptr += sizeof(tBeaconFilterIe); + } + msgQ.type = WMA_BEACON_FILTER_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pBeaconFilterMsg; + msgQ.bodyval = 0; + lim_log(pMac, LOG3, FL("Sending WMA_BEACON_FILTER_IND...")); + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pBeaconFilterMsg); + lim_log(pMac, LOGP, + FL("Posting WMA_BEACON_FILTER_IND failed, reason=%X"), + retCode); + return retCode; + } + return retCode; +} + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus lim_send_mode_update(tpAniSirGlobal pMac, + tUpdateVHTOpMode *pTempParam, + tpPESession psessionEntry) +{ + tUpdateVHTOpMode *pVhtOpMode = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pVhtOpMode = cdf_mem_malloc(sizeof(tUpdateVHTOpMode)); + if (NULL == pVhtOpMode) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update Op Mode")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_copy((uint8_t *) pVhtOpMode, pTempParam, + sizeof(tUpdateVHTOpMode)); + msgQ.type = WMA_UPDATE_OP_MODE; + msgQ.reserved = 0; + msgQ.bodyptr = pVhtOpMode; + msgQ.bodyval = 0; + lim_log(pMac, LOG3, FL( + "Sending WMA_UPDATE_OP_MODE, op_mode %d, sta_id %d"), + pVhtOpMode->opMode, pVhtOpMode->staId); + if (NULL == psessionEntry) + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + else + MTRACE(mac_trace_msg_tx(pMac, + psessionEntry->peSessionId, + msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pVhtOpMode); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_OP_MODE failed, reason=%X"), + retCode); + } + + return retCode; +} + +tSirRetStatus lim_send_rx_nss_update(tpAniSirGlobal pMac, + tUpdateRxNss *pTempParam, + tpPESession psessionEntry) +{ + tUpdateRxNss *pRxNss = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pRxNss = cdf_mem_malloc(sizeof(tUpdateRxNss)); + if (NULL == pRxNss) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update Rx Nss")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_copy((uint8_t *) pRxNss, pTempParam, sizeof(tUpdateRxNss)); + msgQ.type = WMA_UPDATE_RX_NSS; + msgQ.reserved = 0; + msgQ.bodyptr = pRxNss; + msgQ.bodyval = 0; + PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_RX_NSS"));) + if (NULL == psessionEntry) + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + else + MTRACE(mac_trace_msg_tx(pMac, + psessionEntry->peSessionId, + msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pRxNss); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_RX_NSS failed, reason=%X"), + retCode); + } + + return retCode; +} + +tSirRetStatus lim_set_membership(tpAniSirGlobal pMac, + tUpdateMembership *pTempParam, + tpPESession psessionEntry) +{ + tUpdateMembership *pMembership = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pMembership = cdf_mem_malloc(sizeof(tUpdateMembership)); + if (NULL == pMembership) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update Membership Mode")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_copy((uint8_t *) pMembership, pTempParam, + sizeof(tUpdateMembership)); + + msgQ.type = WMA_UPDATE_MEMBERSHIP; + msgQ.reserved = 0; + msgQ.bodyptr = pMembership; + msgQ.bodyval = 0; + PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_MEMBERSHIP"));) + if (NULL == psessionEntry) + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + else + MTRACE(mac_trace_msg_tx(pMac, + psessionEntry->peSessionId, + msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pMembership); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_MEMBERSHIP failed, reason=%X"), + retCode); + } + + return retCode; +} + +tSirRetStatus lim_set_user_pos(tpAniSirGlobal pMac, + tUpdateUserPos *pTempParam, + tpPESession psessionEntry) +{ + tUpdateUserPos *pUserPos = NULL; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + pUserPos = cdf_mem_malloc(sizeof(tUpdateUserPos)); + if (NULL == pUserPos) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during Update User Position")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_copy((uint8_t *) pUserPos, pTempParam, sizeof(tUpdateUserPos)); + + msgQ.type = WMA_UPDATE_USERPOS; + msgQ.reserved = 0; + msgQ.bodyptr = pUserPos; + msgQ.bodyval = 0; + PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_USERPOS"));) + if (NULL == psessionEntry) + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + else + MTRACE(mac_trace_msg_tx(pMac, + psessionEntry->peSessionId, + msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pUserPos); + lim_log(pMac, LOGP, + FL("Posting WMA_UPDATE_USERPOS failed, reason=%X"), + retCode); + } + + return retCode; +} + +#endif + +#ifdef WLAN_FEATURE_11W +/** + * lim_send_exclude_unencrypt_ind() - sends WMA_EXCLUDE_UNENCRYPTED_IND to HAL + * @pMac: mac global context + * @excludeUnenc: true: ignore, false: indicate + * @psessionEntry: session context + * + * LIM sends a message to HAL to indicate whether to ignore or indicate the + * unprotected packet error. + * + * Return: status of operation + */ +tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac, + bool excludeUnenc, + tpPESession psessionEntry) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tSirWlanExcludeUnencryptParam *pExcludeUnencryptParam; + + pExcludeUnencryptParam = + cdf_mem_malloc(sizeof(tSirWlanExcludeUnencryptParam)); + if (NULL == pExcludeUnencryptParam) { + lim_log(pMac, LOGP, + FL("Unable to allocate memory during lim_send_exclude_unencrypt_ind")); + return eSIR_MEM_ALLOC_FAILED; + } + + pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc; + sir_copy_mac_addr(pExcludeUnencryptParam->bssId, psessionEntry->bssId); + + msgQ.type = WMA_EXCLUDE_UNENCRYPTED_IND; + msgQ.reserved = 0; + msgQ.bodyptr = pExcludeUnencryptParam; + msgQ.bodyval = 0; + PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_EXCLUDE_UNENCRYPTED_IND"));) + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + cdf_mem_free(pExcludeUnencryptParam); + lim_log(pMac, LOGP, + FL("Posting WMA_EXCLUDE_UNENCRYPTED_IND failed, reason=%X"), + retCode); + } + + return retCode; +} +#endif diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h new file mode 100644 index 000000000000..d884de757253 --- /dev/null +++ b/core/mac/src/pe/lim/lim_send_messages.h @@ -0,0 +1,126 @@ +/* + * 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. + */ + +/* + * + * lim_send_messages.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 "ani_global.h" +#include "lim_types.h" +#include "wma_if.h" +#include "sir_params.h" +tSirRetStatus lim_send_cf_params(tpAniSirGlobal pMac, uint8_t bssIdx, + uint8_t cfpCount, uint8_t cfpPeriod); +tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, + tpUpdateBeaconParams pUpdatedBcnParams, + tpPESession psessionEntry); +/* tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, tpUpdateBeaconParams pUpdatedBcnParams); */ +#ifdef WLAN_FEATURE_11AC +tSirRetStatus lim_send_mode_update(tpAniSirGlobal pMac, + tUpdateVHTOpMode *tempParam, + tpPESession psessionEntry); +tSirRetStatus lim_send_rx_nss_update(tpAniSirGlobal pMac, + tUpdateRxNss *tempParam, + tpPESession psessionEntry); + +uint32_t lim_get_center_channel(tpAniSirGlobal pMac, + uint8_t primarychanNum, + ePhyChanBondState secondaryChanOffset, + uint8_t chanWidth); + +tSirRetStatus lim_set_membership(tpAniSirGlobal pMac, + tUpdateMembership *pTempParam, + tpPESession psessionEntry); + +tSirRetStatus lim_set_user_pos(tpAniSirGlobal pMac, + tUpdateUserPos *pTempParam, + tpPESession psessionEntry); +#endif +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, + uint8_t chnlNumber, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, + tPowerdBm maxTxPower, + uint8_t peSessionId, + uint8_t is_restart); +#else +tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, + uint8_t chnlNumber, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, + uint8_t localPwrConstraint, + uint8_t peSessionId, + uint8_t is_restart); +#endif +tSirRetStatus lim_send_edca_params(tpAniSirGlobal pMac, + tSirMacEdcaParamRecord *pUpdatedEdcaParams, + uint16_t bssIdx); +tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state, + tSirMacAddr bssId, tSirMacAddr selfMac, + tpSetLinkStateCallback callback, + void *callbackArg); +#ifdef WLAN_FEATURE_VOWIFI_11R +extern tSirRetStatus lim_set_link_state_ft(tpAniSirGlobal pMac, tSirLinkState + state, tSirMacAddr bssId, + tSirMacAddr selfMacAddr, int ft, + tpPESession psessionEntry); +#endif +void lim_set_active_edca_params(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 lim_send_beacon_filter_info(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +#ifdef WLAN_FEATURE_11W +tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac, + bool excludeUnenc, + tpPESession psessionEntry); +#endif +#endif diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c new file mode 100644 index 000000000000..e27113cd52da --- /dev/null +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -0,0 +1,2370 @@ +/* + * 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 lim_send_sme_rspMessages.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 "cdf_types.h" +#include "wni_api.h" +#include "sir_common.h" +#include "ani_global.h" + +#include "wni_cfg.h" +#include "sys_def.h" +#include "cfg_api.h" + +#include "sch_api.h" +#include "utils_api.h" +#include "lim_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" +#include "lim_send_sme_rsp_messages.h" +#include "lim_ibss_peer_mgmt.h" +#include "lim_session_utils.h" +#include "lim_types.h" +#include "sir_api.h" + +static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tSirResultCodes result_code, + tpSirSmeJoinRsp sme_join_rsp); + +/** + * lim_send_sme_rsp() - Send Response to upper layers + * @mac_ctx: Pointer to Global MAC structure + * @msg_type: Indicates message type + * @result_code: Indicates the result of previously issued + * eWNI_SME_msg_type_REQ message + * + * This function is called by lim_process_sme_req_messages() to send + * eWNI_SME_START_RSP, eWNI_SME_STOP_BSS_RSP + * or eWNI_SME_SWITCH_CHL_RSP messages to applications above MAC + * Software. + * + * Return: None + */ + +void +lim_send_sme_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, + tSirResultCodes result_code, uint8_t sme_session_id, + uint16_t sme_transaction_id) +{ + tSirMsgQ msg; + tSirSmeRsp *sme_rsp; + + lim_log(mac_ctx, LOG1, FL("Sending message %s with reasonCode %s"), + lim_msg_str(msg_type), lim_result_code_str(result_code)); + + sme_rsp = cdf_mem_malloc(sizeof(tSirSmeRsp)); + if (NULL == sme_rsp) { + /* Buffer not available. Log error */ + CDF_TRACE(CDF_MODULE_ID_PE, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_*_RSP")); + return; + } + + sme_rsp->messageType = msg_type; + sme_rsp->length = sizeof(tSirSmeRsp); + sme_rsp->statusCode = result_code; + + sme_rsp->sessionId = sme_session_id; + sme_rsp->transactionId = sme_transaction_id; + + msg.type = msg_type; + msg.bodyptr = sme_rsp; + msg.bodyval = 0; + MTRACE(mac_trace_msg_tx(mac_ctx, sme_session_id, msg.type)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + switch (msg_type) { + case eWNI_SME_STOP_BSS_RSP: + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_STOP_BSS_RSP_EVENT, + NULL, (uint16_t) result_code, 0); + break; + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT); +} + + + +/** + * lim_send_sme_roc_rsp() - Send Response to SME + * @mac_ctx: Pointer to Global MAC structure + * @status: Resume link status + * @result_code: Result of the ROC request + * @sme_session_id: SME sesson Id + * @scan_id: Scan Identifier + * + * This function is called to send ROC rsp + * message to SME. + * + * Return: None + */ +void +lim_send_sme_roc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, + tSirResultCodes result_code, uint8_t sme_session_id, + uint32_t scan_id) +{ + tSirMsgQ msg; + struct sir_roc_rsp *sme_rsp; + + lim_log(mac_ctx, LOG1, + FL("Sending message %s with reasonCode %s scanId %d"), + lim_msg_str(msg_type), lim_result_code_str(result_code), + scan_id); + + sme_rsp = cdf_mem_malloc(sizeof(struct sir_roc_rsp)); + if (NULL == sme_rsp) { + CDF_TRACE(CDF_MODULE_ID_PE, LOGP, + FL("call to AllocateMemory failed for eWNI_SME_*_RSP")); + return; + } + + sme_rsp->message_type = msg_type; + sme_rsp->length = sizeof(struct sir_roc_rsp); + sme_rsp->status = result_code; + + sme_rsp->session_id = sme_session_id; + sme_rsp->scan_id = scan_id; + + msg.type = msg_type; + msg.bodyptr = sme_rsp; + msg.bodyval = 0; + MTRACE(mac_trace_msg_tx(mac_ctx, sme_session_id, msg.type)); + lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT); +} + + +/** + * lim_send_sme_join_reassoc_rsp_after_resume() - Send Response to SME + * @mac_ctx Pointer to Global MAC structure + * @status Resume link status + * @ctx context passed while calling resmune link. + * (join response to be sent) + * + * This function is called to send Join/Reassoc rsp + * message to SME after the resume link. + * + * Return: None + */ +static void lim_send_sme_join_reassoc_rsp_after_resume(tpAniSirGlobal mac_ctx, + CDF_STATUS status, uint32_t *ctx) +{ + tSirMsgQ msg; + tpSirSmeJoinRsp sme_join_rsp = (tpSirSmeJoinRsp) ctx; + + msg.type = sme_join_rsp->messageType; + msg.bodyptr = sme_join_rsp; + msg.bodyval = 0; + MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type)); + lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT); +} + +/** + * lim_handle_join_rsp_status() - Handle the response. + * @mac_ctx: Pointer to Global MAC structure + * @session_entry: PE Session Info + * @result_code: Indicates the result of previously issued + * eWNI_SME_msgType_REQ message + * @sme_join_rsp The received response. + * + * This function will handle both the success and failure status + * of the received response. + * + * Return: None + */ +static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, + tpPESession session_entry, tSirResultCodes result_code, + tpSirSmeJoinRsp sme_join_rsp) +{ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile *ht_profile; +#endif + if (result_code == eSIR_SME_SUCCESS) { + if (session_entry->beacon != NULL) { + sme_join_rsp->beaconLength = session_entry->bcnLen; + cdf_mem_copy(sme_join_rsp->frames, + session_entry->beacon, + sme_join_rsp->beaconLength); + cdf_mem_free(session_entry->beacon); + session_entry->beacon = NULL; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("Beacon=%d"), + session_entry->bcnLen); +#endif + } + if (session_entry->assocReq != NULL) { + sme_join_rsp->assocReqLength = + session_entry->assocReqLen; + cdf_mem_copy(sme_join_rsp->frames + + session_entry->bcnLen, session_entry->assocReq, + sme_join_rsp->assocReqLength); + cdf_mem_free(session_entry->assocReq); + session_entry->assocReq = NULL; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, + LOG1, FL("AssocReq=%d"), + session_entry->assocReqLen); +#endif + } + if (session_entry->assocRsp != NULL) { + sme_join_rsp->assocRspLength = + session_entry->assocRspLen; + cdf_mem_copy(sme_join_rsp->frames + + session_entry->bcnLen + + session_entry->assocReqLen, + session_entry->assocRsp, + sme_join_rsp->assocRspLength); + cdf_mem_free(session_entry->assocRsp); + session_entry->assocRsp = NULL; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (session_entry->ricData != NULL) { + sme_join_rsp->parsedRicRspLen = + session_entry->RICDataLen; + cdf_mem_copy(sme_join_rsp->frames + + session_entry->bcnLen + + session_entry->assocReqLen + + session_entry->assocRspLen, + session_entry->ricData, + sme_join_rsp->parsedRicRspLen); + cdf_mem_free(session_entry->ricData); + session_entry->ricData = NULL; + lim_log(mac_ctx, LOG1, FL("RicLength=%d"), + sme_join_rsp->parsedRicRspLen); + } +#endif +#ifdef FEATURE_WLAN_ESE + if (session_entry->tspecIes != NULL) { + sme_join_rsp->tspecIeLen = + session_entry->tspecLen; + cdf_mem_copy(sme_join_rsp->frames + + session_entry->bcnLen + + session_entry->assocReqLen + + session_entry->assocRspLen + + session_entry->RICDataLen, + session_entry->tspecIes, + sme_join_rsp->tspecIeLen); + cdf_mem_free(session_entry->tspecIes); + session_entry->tspecIes = NULL; + lim_log(mac_ctx, LOG1, FL("ESE-TspecLen=%d"), + session_entry->tspecLen); + } +#endif + sme_join_rsp->aid = session_entry->limAID; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(mac_ctx, LOG1, FL("AssocRsp=%d"), + session_entry->assocRspLen); +#endif + sme_join_rsp->vht_channel_width = + session_entry->ch_width; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (session_entry->cc_switch_mode != + CDF_MCC_TO_SCC_SWITCH_DISABLE) { + ht_profile = &sme_join_rsp->HTProfile; + ht_profile->htSupportedChannelWidthSet = + session_entry->htSupportedChannelWidthSet; + ht_profile->htRecommendedTxWidthSet = + session_entry->htRecommendedTxWidthSet; + ht_profile->htSecondaryChannelOffset = + session_entry->htSecondaryChannelOffset; + ht_profile->dot11mode = session_entry->dot11mode; + ht_profile->htCapability = session_entry->htCapability; +#ifdef WLAN_FEATURE_11AC + ht_profile->vhtCapability = + session_entry->vhtCapability; + ht_profile->vhtTxChannelWidthSet = + session_entry->vhtTxChannelWidthSet; + ht_profile->apCenterChan = session_entry->ch_center_freq_seg0; + ht_profile->apChanWidth = session_entry->ch_width; +#endif + } +#endif + } else { + if (session_entry->beacon != NULL) { + cdf_mem_free(session_entry->beacon); + session_entry->beacon = NULL; + } + if (session_entry->assocReq != NULL) { + cdf_mem_free(session_entry->assocReq); + session_entry->assocReq = NULL; + } + if (session_entry->assocRsp != NULL) { + cdf_mem_free(session_entry->assocRsp); + session_entry->assocRsp = NULL; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (session_entry->ricData != NULL) { + cdf_mem_free(session_entry->ricData); + session_entry->ricData = NULL; + } +#endif +#ifdef FEATURE_WLAN_ESE + if (session_entry->tspecIes != NULL) { + cdf_mem_free(session_entry->tspecIes); + session_entry->tspecIes = NULL; + } +#endif + } +} +/** + * lim_send_sme_join_reassoc_rsp() - Send Response to Upper Layers + * @mac_ctx: Pointer to Global MAC structure + * @msg_type: Indicates message type + * @result_code: Indicates the result of previously issued + * eWNI_SME_msgType_REQ message + * @prot_status_code: Protocol Status Code + * @session_entry: PE Session Info + * @sme_session_id: SME Session ID + * @sme_transaction_id: SME Transaction ID + * + * This function is called by lim_process_sme_req_messages() to send + * eWNI_SME_JOIN_RSP or eWNI_SME_REASSOC_RSP messages to applications + * above MAC Software. + * + * Return: None + */ + +void +lim_send_sme_join_reassoc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, + tSirResultCodes result_code, uint16_t prot_status_code, + tpPESession session_entry, uint8_t sme_session_id, + uint16_t sme_transaction_id) +{ + tpSirSmeJoinRsp sme_join_rsp; + uint32_t rsp_len; + tpDphHashNode sta_ds = NULL; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + if (msg_type == eWNI_SME_REASSOC_RSP) + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_RSP_EVENT, + session_entry, (uint16_t) result_code, 0); + else + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_RSP_EVENT, + session_entry, (uint16_t) result_code, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_log(mac_ctx, LOG1, FL("Sending message %s with reasonCode %s"), + lim_msg_str(msg_type), lim_result_code_str(result_code)); + + if (session_entry == NULL) { + rsp_len = sizeof(tSirSmeJoinRsp); + sme_join_rsp = cdf_mem_malloc(rsp_len); + if (NULL == sme_join_rsp) { + lim_log(mac_ctx, LOGP, + FL("Mem Alloc fail - JOIN/REASSOC_RSP")); + return; + } + + cdf_mem_set((uint8_t *) sme_join_rsp, rsp_len, 0); + sme_join_rsp->beaconLength = 0; + sme_join_rsp->assocReqLength = 0; + sme_join_rsp->assocRspLength = 0; + } else { + rsp_len = session_entry->assocReqLen + + session_entry->assocRspLen + session_entry->bcnLen + +#ifdef WLAN_FEATURE_VOWIFI_11R + session_entry->RICDataLen + +#endif +#ifdef FEATURE_WLAN_ESE + session_entry->tspecLen + +#endif + sizeof(tSirSmeJoinRsp) - sizeof(uint8_t); + sme_join_rsp = cdf_mem_malloc(rsp_len); + if (NULL == sme_join_rsp) { + lim_log(mac_ctx, LOGP, + FL("MemAlloc fail - JOIN/REASSOC_RSP")); + return; + } + cdf_mem_set((uint8_t *) sme_join_rsp, rsp_len, 0); + if (result_code == eSIR_SME_SUCCESS) { + sta_ds = dph_get_hash_entry(mac_ctx, + DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, + FL("Get Self Sta Entry fail")); + } else { + /* Pass the peer's staId */ + sme_join_rsp->staId = sta_ds->staIndex; + sme_join_rsp->ucastSig = + sta_ds->ucUcastSig; + sme_join_rsp->bcastSig = + sta_ds->ucBcastSig; + sme_join_rsp->timingMeasCap = + sta_ds->timingMeasCap; +#ifdef FEATURE_WLAN_TDLS + sme_join_rsp->tdls_prohibited = + session_entry->tdls_prohibited; + sme_join_rsp->tdls_chan_swit_prohibited = + session_entry->tdls_chan_swit_prohibited; +#endif + } + } + sme_join_rsp->beaconLength = 0; + sme_join_rsp->assocReqLength = 0; + sme_join_rsp->assocRspLength = 0; +#ifdef WLAN_FEATURE_VOWIFI_11R + sme_join_rsp->parsedRicRspLen = 0; +#endif +#ifdef FEATURE_WLAN_ESE + sme_join_rsp->tspecIeLen = 0; +#endif + + lim_handle_join_rsp_status(mac_ctx, session_entry, result_code, + sme_join_rsp); + } + + sme_join_rsp->messageType = msg_type; + sme_join_rsp->length = (uint16_t) rsp_len; + sme_join_rsp->statusCode = result_code; + sme_join_rsp->protStatusCode = prot_status_code; + + sme_join_rsp->sessionId = sme_session_id; + sme_join_rsp->transactionId = sme_transaction_id; + + lim_send_sme_join_reassoc_rsp_after_resume(mac_ctx, CDF_STATUS_SUCCESS, + (uint32_t *)sme_join_rsp); +} + +/** + * lim_send_sme_start_bss_rsp() + * + ***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 +lim_send_sme_start_bss_rsp(tpAniSirGlobal pMac, + uint16_t msgType, tSirResultCodes resultCode, + tpPESession psessionEntry, uint8_t smesessionId, + uint16_t smetransactionId) +{ + + uint16_t size = 0; + tSirMsgQ mmhMsg; + tSirSmeStartBssRsp *pSirSmeRsp; + uint16_t ieLen; + uint16_t ieOffset, curLen; + + PELOG1(lim_log(pMac, LOG1, FL("Sending message %s with reasonCode %s"), + lim_msg_str(msgType), lim_result_code_str(resultCode)); + ) + + size = sizeof(tSirSmeStartBssRsp); + + if (psessionEntry == NULL) { + pSirSmeRsp = cdf_mem_malloc(size); + if (NULL == pSirSmeRsp) { + /* / Buffer not available. Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP")); + return; + } + cdf_mem_set((uint8_t *) 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 = cdf_mem_malloc(size); + if (NULL == pSirSmeRsp) { + /* / Buffer not available. Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP")); + + return; + } + cdf_mem_set((uint8_t *) pSirSmeRsp, size, 0); + size = sizeof(tSirSmeStartBssRsp); + if (resultCode == eSIR_SME_SUCCESS) { + + sir_copy_mac_addr(pSirSmeRsp->bssDescription.bssId, + psessionEntry->bssId); + + /* Read beacon interval from session */ + pSirSmeRsp->bssDescription.beaconInterval = + (uint16_t) psessionEntry->beaconParams. + beaconInterval; + pSirSmeRsp->bssType = psessionEntry->bssType; + + if (cfg_get_capability_info + (pMac, &pSirSmeRsp->bssDescription.capabilityInfo, + psessionEntry) + != eSIR_SUCCESS) + lim_log(pMac, LOGP, + FL + ("could not retrieve Capabilities value")); + + lim_get_phy_mode(pMac, + (uint32_t *) &pSirSmeRsp->bssDescription. + nwType, psessionEntry); + + pSirSmeRsp->bssDescription.channelId = + psessionEntry->currentOperChannel; + + curLen = psessionEntry->schBeaconOffsetBegin - ieOffset; + cdf_mem_copy((uint8_t *) &pSirSmeRsp->bssDescription. + ieFields, + psessionEntry->pSchBeaconFrameBegin + + ieOffset, (uint32_t) curLen); + + cdf_mem_copy(((uint8_t *) &pSirSmeRsp->bssDescription. + ieFields) + curLen, + psessionEntry->pSchBeaconFrameEnd, + (uint32_t) psessionEntry-> + schBeaconOffsetEnd); + + /* subtracting size of length indicator itself and size of pointer to ieFields */ + pSirSmeRsp->bssDescription.length = + sizeof(tSirBssDescription) - sizeof(uint16_t) - + sizeof(uint32_t) + ieLen; + /* This is the size of the message, subtracting the size of the pointer to ieFields */ + size += ieLen - sizeof(uint32_t); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (psessionEntry->cc_switch_mode + != CDF_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->ch_center_freq_seg0; + pSirSmeRsp->HTProfile.apChanWidth = + psessionEntry->ch_width; +#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(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + } else { + MTRACE(mac_trace_msg_tx + (pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_START_BSS_RSP_EVENT, + psessionEntry, (uint16_t) resultCode, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} /*** end lim_send_sme_start_bss_rsp() ***/ + +#define LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED 20 +#define LIM_SIZE_OF_EACH_BSS 400 /* this is a rough estimate */ + +/** + * lim_send_sme_scan_rsp() - Send scan response to SME + * @pMac: Pointer to Global MAC structure + * @length: Indicates length of message + * @resultCode: Indicates the result of previously issued + * eWNI_SME_SCAN_REQ message + * @scan_id: scan identifier + * + * This function is called by lim_process_sme_req_messages() to send + * eWNI_SME_SCAN_RSP message to applications above MAC + * + * return: None + */ + +void +lim_send_sme_scan_rsp(tpAniSirGlobal pMac, tSirResultCodes resultCode, + uint8_t smesessionId, uint16_t smetranscationId, + uint32_t scan_id) +{ + lim_log(pMac, LOG1, + FL("Sending message SME_SCAN_RSP reasonCode %s scanId %d"), + lim_result_code_str(resultCode), scan_id); + lim_post_sme_scan_rsp_message(pMac, resultCode, smesessionId, + smetranscationId, scan_id); +} + +/** + * lim_post_sme_scan_rsp_message() + * + ***FUNCTION: + * This function is called by lim_send_sme_scan_rsp() 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 +lim_post_sme_scan_rsp_message(tpAniSirGlobal pMac, + tSirResultCodes resultCode, uint8_t smesessionId, + uint16_t smetransactionId, + uint32_t scan_id) +{ + tpSirSmeScanRsp pSirSmeScanRsp; + tSirMsgQ mmhMsg; + + lim_log(pMac, LOG1, FL("send SME_SCAN_RSP (reasonCode %s)."), + lim_result_code_str(resultCode)); + + pSirSmeScanRsp = cdf_mem_malloc(sizeof(tSirSmeScanRsp)); + if (NULL == pSirSmeScanRsp) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for eWNI_SME_SCAN_RSP")); + return; + } + cdf_mem_set((void *)pSirSmeScanRsp, sizeof(tSirSmeScanRsp), 0); + + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->statusCode = resultCode; + + /*Update SME session Id and transaction Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetransactionId; + pSirSmeScanRsp->scan_id = scan_id; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_SCAN_RSP_EVENT, NULL, + (uint16_t) resultCode, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; + +} /*** lim_post_sme_scan_rsp_message ***/ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * lim_send_sme_oem_data_rsp() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 lim_send_sme_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *pMsgBuf, + tSirResultCodes resultCode) +{ + tSirMsgQ mmhMsg; + tSirOemDataRsp *pSirSmeOemDataRsp = NULL; + tLimMlmOemDataRsp *pMlmOemDataRsp = NULL; + uint16_t msgLength; + + /* get the pointer to the mlm message */ + pMlmOemDataRsp = (tLimMlmOemDataRsp *) (pMsgBuf); + + msgLength = sizeof(tSirOemDataRsp); + + /* now allocate memory for the char buffer */ + pSirSmeOemDataRsp = cdf_mem_malloc(msgLength); + if (NULL == pSirSmeOemDataRsp) { + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for pSirSmeOemDataRsp")); + return; + } +#if defined (ANI_LITTLE_BYTE_ENDIAN) + sir_store_u16_n((uint8_t *) &pSirSmeOemDataRsp->length, msgLength); + sir_store_u16_n((uint8_t *) &pSirSmeOemDataRsp->messageType, + eWNI_SME_OEM_DATA_RSP); +#else + pSirSmeOemDataRsp->length = msgLength; + pSirSmeOemDataRsp->messageType = eWNI_SME_OEM_DATA_RSP; +#endif + + cdf_mem_copy(pSirSmeOemDataRsp->oemDataRsp, pMlmOemDataRsp->oemDataRsp, + OEM_DATA_RSP_SIZE); + + /* Now free the memory from MLM Rsp Message */ + cdf_mem_free(pMlmOemDataRsp); + + mmhMsg.type = eWNI_SME_OEM_DATA_RSP; + mmhMsg.bodyptr = pSirSmeOemDataRsp; + mmhMsg.bodyval = 0; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return; +} /*** lim_send_sme_oem_data_rsp ***/ + +#endif + +void lim_send_sme_disassoc_deauth_ntf(tpAniSirGlobal pMac, + CDF_STATUS status, uint32_t *pCtx) +{ + tSirMsgQ mmhMsg; + tSirMsgQ *pMsg = (tSirMsgQ *) pCtx; + + mmhMsg.type = pMsg->type; + mmhMsg.bodyptr = pMsg; + mmhMsg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} + +/** + * lim_send_sme_disassoc_ntf() + * + ***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 +lim_send_sme_disassoc_ntf(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tSirResultCodes reasonCode, + uint16_t disassocTrigger, + uint16_t aid, + uint8_t smesessionId, + uint16_t smetransactionId, tpPESession psessionEntry) +{ + + uint8_t *pBuf; + tSirSmeDisassocRsp *pSirSmeDisassocRsp; + tSirSmeDisassocInd *pSirSmeDisassocInd; + uint32_t *pMsg; + bool failure = false; + + lim_log(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 = cdf_mem_malloc(sizeof(tSirSmeDisassocRsp)); + if (NULL == pSirSmeDisassocRsp) { + /* Log error */ + lim_log(pMac, LOGP, FL("Memory allocation failed")); + failure = true; + goto error; + } + lim_log(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 = (uint8_t *) &pSirSmeDisassocRsp->sessionId; + *pBuf = smesessionId; + pBuf++; + + /* transactionId */ + lim_copy_u16(pBuf, smetransactionId); + pBuf += sizeof(uint16_t); + + /* statusCode */ + lim_copy_u32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + /* peerMacAddr */ + cdf_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 */ + + lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_RSP_EVENT, + psessionEntry, (uint16_t) reasonCode, 0); +#endif + pMsg = (uint32_t *) pSirSmeDisassocRsp; + break; + + default: + /** + * Disassociation indication due to Disassociation + * frame reception from peer entity or due to + * loss of link with peer entity. + */ + pSirSmeDisassocInd = cdf_mem_malloc(sizeof(tSirSmeDisassocInd)); + if (NULL == pSirSmeDisassocInd) { + /* Log error */ + lim_log(pMac, LOGP, FL("Memory allocation failed")); + failure = true; + goto error; + } + lim_log(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 = (uint8_t *) &pSirSmeDisassocInd->statusCode; + + lim_copy_u32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, + psessionEntry, (uint16_t) reasonCode, 0); +#endif + pMsg = (uint32_t *) pSirSmeDisassocInd; + + break; + } + +error: + /* Delete the PE session Created */ + if ((psessionEntry != NULL) && + (LIM_IS_STA_ROLE(psessionEntry) || + LIM_IS_BT_AMP_STA_ROLE(psessionEntry))) { + pe_delete_session(pMac, psessionEntry); + } + + if (false == failure) + lim_send_sme_disassoc_deauth_ntf(pMac, CDF_STATUS_SUCCESS, + (uint32_t *) pMsg); +} /*** end lim_send_sme_disassoc_ntf() ***/ + +/** ----------------------------------------------------------------- + \brief lim_send_sme_disassoc_ind() - 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 +lim_send_sme_disassoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeDisassocInd *pSirSmeDisassocInd; + + pSirSmeDisassocInd = cdf_mem_malloc(sizeof(tSirSmeDisassocInd)); + if (NULL == pSirSmeDisassocInd) { + lim_log(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; + + cdf_mem_copy(pSirSmeDisassocInd->bssId, psessionEntry->bssId, + sizeof(tSirMacAddr)); + + cdf_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(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, psessionEntry, + 0, (uint16_t) pStaDs->mlmStaContext.disassocReason); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + +} /*** end lim_send_sme_disassoc_ind() ***/ + +/** ----------------------------------------------------------------- + \brief lim_send_sme_deauth_ind() - 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 +lim_send_sme_deauth_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirSmeDeauthInd *pSirSmeDeauthInd; + + pSirSmeDeauthInd = cdf_mem_malloc(sizeof(tSirSmeDeauthInd)); + if (NULL == pSirSmeDeauthInd) { + lim_log(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 */ + cdf_mem_copy(pSirSmeDeauthInd->bssId, psessionEntry->bssId, + sizeof(tSirMacAddr)); + /* peerMacAddr */ + cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, pStaDs->staAddr, + sizeof(tSirMacAddr)); + pSirSmeDeauthInd->reasonCode = pStaDs->mlmStaContext.disassocReason; + + pSirSmeDeauthInd->staId = pStaDs->staIndex; + + mmhMsg.type = eWNI_SME_DEAUTH_IND; + mmhMsg.bodyptr = pSirSmeDeauthInd; + mmhMsg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, psessionEntry, + 0, pStaDs->mlmStaContext.cleanupTrigger); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} /*** end lim_send_sme_deauth_ind() ***/ + +#ifdef FEATURE_WLAN_TDLS +/** + * lim_send_sme_tdls_del_sta_ind() + * + ***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 +lim_send_sme_tdls_del_sta_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry, uint16_t reasonCode) +{ + tSirMsgQ mmhMsg; + tSirTdlsDelStaInd *pSirTdlsDelStaInd; + + pSirTdlsDelStaInd = cdf_mem_malloc(sizeof(tSirTdlsDelStaInd)); + if (NULL == pSirTdlsDelStaInd) { + lim_log(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 */ + cdf_mem_copy(pSirTdlsDelStaInd->peerMac, pStaDs->staAddr, + sizeof(tSirMacAddr)); + + /* staId */ + lim_copy_u16((uint8_t *) (&pSirTdlsDelStaInd->staId), + (uint16_t) pStaDs->staIndex); + + /* reasonCode */ + lim_copy_u16((uint8_t *) (&pSirTdlsDelStaInd->reasonCode), reasonCode); + + mmhMsg.type = eWNI_SME_TDLS_DEL_STA_IND; + mmhMsg.bodyptr = pSirTdlsDelStaInd; + mmhMsg.bodyval = 0; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} /*** end lim_send_sme_tdls_del_sta_ind() ***/ + +/** + * lim_send_sme_tdls_delete_all_peer_ind() + * + ***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 +lim_send_sme_tdls_delete_all_peer_ind(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg; + tSirTdlsDelAllPeerInd *pSirTdlsDelAllPeerInd; + + pSirTdlsDelAllPeerInd = cdf_mem_malloc(sizeof(tSirTdlsDelAllPeerInd)); + if (NULL == pSirTdlsDelAllPeerInd) { + lim_log(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; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/ + +/** + * lim_send_sme_mgmt_tx_completion() + * + ***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 +lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac, + tpPESession psessionEntry, uint32_t txCompleteStatus) +{ + tSirMsgQ mmhMsg; + tSirMgmtTxCompletionInd *pSirMgmtTxCompletionInd; + + pSirMgmtTxCompletionInd = + cdf_mem_malloc(sizeof(tSirMgmtTxCompletionInd)); + if (NULL == pSirMgmtTxCompletionInd) { + lim_log(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; + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/ + +void lim_send_sme_tdls_event_notify(tpAniSirGlobal pMac, uint16_t 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; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} +#endif /* FEATURE_WLAN_TDLS */ + +/** + * lim_send_sme_deauth_ntf() + * + ***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 +lim_send_sme_deauth_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tSirResultCodes reasonCode, uint16_t deauthTrigger, + uint16_t aid, uint8_t smesessionId, + uint16_t smetransactionId) +{ + uint8_t *pBuf; + tSirSmeDeauthRsp *pSirSmeDeauthRsp; + tSirSmeDeauthInd *pSirSmeDeauthInd; + tpPESession psessionEntry; + uint8_t sessionId; + uint32_t *pMsg; + + psessionEntry = pe_find_session_by_bssid(pMac, peerMacAddr, &sessionId); + switch (deauthTrigger) { + case eLIM_PEER_ENTITY_DEAUTH: + return; + + case eLIM_HOST_DEAUTH: + /** + * Deauthentication response to host triggered + * deauthentication. + */ + pSirSmeDeauthRsp = cdf_mem_malloc(sizeof(tSirSmeDeauthRsp)); + if (NULL == pSirSmeDeauthRsp) { + /* Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_DEAUTH_RSP")); + + return; + } + lim_log(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 = (uint8_t *) pSirSmeDeauthRsp->peerMacAddr; + cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_RSP_EVENT, + psessionEntry, 0, (uint16_t) reasonCode); +#endif + pMsg = (uint32_t *) pSirSmeDeauthRsp; + + break; + + default: + /** + * Deauthentication indication due to Deauthentication + * frame reception from peer entity or due to + * loss of link with peer entity. + */ + pSirSmeDeauthInd = cdf_mem_malloc(sizeof(tSirSmeDeauthInd)); + if (NULL == pSirSmeDeauthInd) { + /* Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_DEAUTH_Ind")); + + return; + } + lim_log(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 = (uint8_t *) &pSirSmeDeauthInd->sessionId; + *pBuf++ = smesessionId; + + /* transaction ID */ + lim_copy_u16(pBuf, smetransactionId); + pBuf += sizeof(uint16_t); + + /* status code */ + lim_copy_u32(pBuf, reasonCode); + pBuf += sizeof(tSirResultCodes); + + /* bssId */ + cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + + /* peerMacAddr */ + cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, peerMacAddr, + sizeof(tSirMacAddr)); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, + psessionEntry, 0, (uint16_t) reasonCode); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + pMsg = (uint32_t *) pSirSmeDeauthInd; + + break; + } + + /*Delete the PE session created */ + if (psessionEntry != NULL) { + pe_delete_session(pMac, psessionEntry); + } + + lim_send_sme_disassoc_deauth_ntf(pMac, CDF_STATUS_SUCCESS, + (uint32_t *) pMsg); + +} /*** end lim_send_sme_deauth_ntf() ***/ + +/** + * lim_send_sme_wm_status_change_ntf() - Send Notification + * @mac_ctx: Global MAC Context + * @status_change_code: Indicates the change in the wireless medium. + * @status_change_info: Indicates the information associated with + * change in the wireless medium. + * @info_len: Indicates the length of status change information + * being sent. + * @session_id SessionID + * + * This function is called by limProcessSmeMessages() to send + * eWNI_SME_WM_STATUS_CHANGE_NTF message to host. + * + * Return: None + */ +void +lim_send_sme_wm_status_change_ntf(tpAniSirGlobal mac_ctx, + tSirSmeStatusChangeCode status_change_code, + uint32_t *status_change_info, uint16_t info_len, uint8_t session_id) +{ + tSirMsgQ msg; + tSirSmeWmStatusChangeNtf *wm_status_change_ntf; + + wm_status_change_ntf = cdf_mem_malloc(sizeof(tSirSmeWmStatusChangeNtf)); + if (NULL == wm_status_change_ntf) { + lim_log(mac_ctx, LOGE, + FL("Mem Alloc failed - eWNI_SME_WM_STATUS_CHANGE_NTF")); + return; + } + + msg.type = eWNI_SME_WM_STATUS_CHANGE_NTF; + msg.bodyval = 0; + msg.bodyptr = wm_status_change_ntf; + + switch (status_change_code) { + case eSIR_SME_RADAR_DETECTED: + break; + default: + wm_status_change_ntf->messageType = + eWNI_SME_WM_STATUS_CHANGE_NTF; + wm_status_change_ntf->statusChangeCode = status_change_code; + wm_status_change_ntf->length = sizeof(tSirSmeWmStatusChangeNtf); + wm_status_change_ntf->sessionId = session_id; + if (sizeof(wm_status_change_ntf->statusChangeInfo) >= + info_len) { + cdf_mem_copy( + (uint8_t *) &wm_status_change_ntf->statusChangeInfo, + (uint8_t *) status_change_info, info_len); + } + lim_log(mac_ctx, LOGE, + FL("**---** StatusChg: code 0x%x, length %d **---**"), + status_change_code, info_len); + break; + } + + MTRACE(mac_trace_msg_tx(mac_ctx, session_id, msg.type)); + if (eSIR_SUCCESS != lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT)) { + cdf_mem_free(wm_status_change_ntf); + lim_log(mac_ctx, LOGP, + FL("lim_sys_process_mmh_msg_api failed")); + } + +} /*** end lim_send_sme_wm_status_change_ntf() ***/ + +/** + * lim_send_sme_set_context_rsp() + * + ***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 +lim_send_sme_set_context_rsp(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, uint16_t aid, + tSirResultCodes resultCode, + tpPESession psessionEntry, uint8_t smesessionId, + uint16_t smetransactionId) +{ + + uint8_t *pBuf; + tSirMsgQ mmhMsg; + tSirSmeSetContextRsp *pSirSmeSetContextRsp; + + pSirSmeSetContextRsp = cdf_mem_malloc(sizeof(tSirSmeSetContextRsp)); + if (NULL == pSirSmeSetContextRsp) { + /* Log error */ + lim_log(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; + + cdf_mem_copy(pBuf, (uint8_t *) 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(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + } else { + MTRACE(mac_trace_msg_tx + (pMac, psessionEntry->peSessionId, mmhMsg.type)); + } + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT, + psessionEntry, (uint16_t) resultCode, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} /*** end lim_send_sme_set_context_rsp() ***/ + +/** + * lim_send_sme_neighbor_bss_ind() + * + ***FUNCTION: + * This function is called by lim_lookup_nadd_hash_entry() 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 +lim_send_sme_neighbor_bss_ind(tpAniSirGlobal pMac, tLimScanResultNode *pBssDescr) +{ + tSirMsgQ msgQ; + uint32_t 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_cfg_get_int(pMac, WNI_CFG_NEW_BSS_FOUND_IND, &val) != + eSIR_SUCCESS) { + lim_log(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(uint16_t) + + sizeof(uint32_t) + sizeof(uint8_t); + pNewBssInd = cdf_mem_malloc(val); + if (NULL == pNewBssInd) { + /* Log error */ + lim_log(pMac, LOGP, + FL + ("call to AllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND")); + + return; + } + + pNewBssInd->messageType = eWNI_SME_NEIGHBOR_BSS_IND; + pNewBssInd->length = (uint16_t) val; + pNewBssInd->sessionId = 0; + + cdf_mem_copy((uint8_t *) pNewBssInd->bssDescription, + (uint8_t *) &pBssDescr->bssDescription, + pBssDescr->bssDescription.length + sizeof(uint16_t)); + + msgQ.type = eWNI_SME_NEIGHBOR_BSS_IND; + msgQ.bodyptr = pNewBssInd; + msgQ.bodyval = 0; + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT); +} /*** end lim_send_sme_neighbor_bss_ind() ***/ + +/** ----------------------------------------------------------------- + \brief lim_send_sme_addts_rsp() - 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 +lim_send_sme_addts_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, uint32_t status, + tpPESession psessionEntry, tSirMacTspecIE tspec, + uint8_t smesessionId, uint16_t smetransactionId) +{ + tpSirAddtsRsp rsp; + tSirMsgQ mmhMsg; + + if (!rspReqd) + return; + + rsp = cdf_mem_malloc(sizeof(tSirAddtsRsp)); + if (NULL == rsp) { + lim_log(pMac, LOGP, FL("AllocateMemory failed for ADDTS_RSP")); + return; + } + + cdf_mem_set((uint8_t *) 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(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + } else { + MTRACE(mac_trace_msg_tx + (pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_ADDTS_RSP_EVENT, psessionEntry, 0, + 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} + +void +lim_send_sme_delts_rsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, uint32_t status, + tpPESession psessionEntry, uint8_t smesessionId, + uint16_t smetransactionId) +{ + tpSirDeltsRsp rsp; + tSirMsgQ mmhMsg; + + lim_log(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 = cdf_mem_malloc(sizeof(tSirDeltsRsp)); + if (NULL == rsp) { + /* Log error */ + lim_log(pMac, LOGP, FL("AllocateMemory failed for DELTS_RSP")); + return; + } + cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0); + + if (psessionEntry != NULL) { + + rsp->aid = delts->aid; + cdf_mem_copy((uint8_t *) &rsp->macAddr[0], + (uint8_t *) &delts->macAddr[0], 6); + cdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) &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(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + } else { + MTRACE(mac_trace_msg_tx + (pMac, psessionEntry->peSessionId, mmhMsg.type)); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_RSP_EVENT, psessionEntry, + (uint16_t) status, 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} + +void +lim_send_sme_delts_ind(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, uint16_t aid, + tpPESession psessionEntry) +{ + tpSirDeltsRsp rsp; + tSirMsgQ mmhMsg; + + lim_log(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)", + aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio); + + rsp = cdf_mem_malloc(sizeof(tSirDeltsRsp)); + if (NULL == rsp) { + /* Log error */ + lim_log(pMac, LOGP, FL("AllocateMemory failed for DELTS_IND")); + return; + } + cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0); + + rsp->messageType = eWNI_SME_DELTS_IND; + rsp->rc = eSIR_SUCCESS; + rsp->aid = aid; + cdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) 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(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_IND_EVENT, psessionEntry, 0, + 0); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} + +/** + * lim_send_sme_pe_statistics_rsp() + * + ***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 +lim_send_sme_pe_statistics_rsp(tpAniSirGlobal pMac, uint16_t msgType, void *stats) +{ + tSirMsgQ mmhMsg; + uint8_t sessionId; + tAniGetPEStatsRsp *pPeStats = (tAniGetPEStatsRsp *) stats; + tpPESession pPeSessionEntry; + + /* Get the Session Id based on Sta Id */ + pPeSessionEntry = + pe_find_session_by_sta_id(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 WMA_GET_STATISTICS_RSP */ + mmhMsg.type = eWNI_SME_GET_STATISTICS_RSP; + + mmhMsg.bodyptr = stats; + mmhMsg.bodyval = 0; + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type)); + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return; + +} /*** end lim_send_sme_pe_statistics_rsp() ***/ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * lim_send_sme_pe_ese_tsm_rsp() + * + ***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 lim_send_sme_pe_ese_tsm_rsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats) +{ + tSirMsgQ mmhMsg; + uint8_t sessionId; + tAniGetTsmStatsRsp *pPeStats = (tAniGetTsmStatsRsp *) pStats; + tpPESession pPeSessionEntry = NULL; + + /* Get the Session Id based on Sta Id */ + pPeSessionEntry = + pe_find_session_by_sta_id(pMac, pPeStats->staId, &sessionId); + + /* Fill the Session Id */ + if (NULL != pPeSessionEntry) { + /* Fill the Session Id */ + pPeStats->sessionId = pPeSessionEntry->smeSessionId; + } else { + PELOGE(lim_log + (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(mac_trace_msg_tx(pMac, sessionId, mmhMsg.type)); + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return; +} /*** end lim_send_sme_pe_ese_tsm_rsp() ***/ + +#endif /* FEATURE_WLAN_ESE) && FEATURE_WLAN_ESE_UPLOAD */ + +void +lim_send_sme_ibss_peer_ind(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + uint16_t staIndex, + uint8_t ucastIdx, + uint8_t bcastIdx, + uint8_t *beacon, + uint16_t beaconLen, uint16_t msgType, uint8_t sessionId) +{ + tSirMsgQ mmhMsg; + tSmeIbssPeerInd *pNewPeerInd; + + pNewPeerInd = cdf_mem_malloc(sizeof(tSmeIbssPeerInd) + beaconLen); + if (NULL == pNewPeerInd) { + PELOGE(lim_log(pMac, LOGE, FL("Failed to allocate memory"));) + return; + } + + cdf_mem_set((void *)pNewPeerInd, (sizeof(tSmeIbssPeerInd) + beaconLen), + 0); + + cdf_mem_copy((uint8_t *) 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) { + cdf_mem_copy((void *)((uint8_t *) pNewPeerInd + + sizeof(tSmeIbssPeerInd)), (void *)beacon, + beaconLen); + } + + mmhMsg.type = msgType; + mmhMsg.bodyptr = pNewPeerInd; + MTRACE(mac_trace_msg_tx(pMac, sessionId, mmhMsg.type)); + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + +} + +/** + * lim_handle_csa_offload_msg() - Handle CSA offload message + * @mac_ctx: pointer to global adapter context + * @msg: Message pointer. + * + * Return: None + */ +void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + tpPESession session_entry; + tSirMsgQ mmh_msg; + tpCSAOffloadParams csa_params = (tpCSAOffloadParams) (msg->bodyptr); + tpSmeCsaOffloadInd csa_offload_ind; + tpDphHashNode sta_ds = NULL; + uint8_t session_id; + uint16_t aid = 0; + tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL; + + if (!csa_params) { + lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL")); + return; + } + + session_entry = + pe_find_session_by_bssid(mac_ctx, + csa_params->bssId, &session_id); + if (!session_entry) { + lim_log(mac_ctx, LOGE, + FL("Session does not exist")); + goto err; + } + + sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid, + &session_entry->dph.dphHashTable); + + if (!sta_ds) { + lim_log(mac_ctx, LOGE, + FL("sta_ds does not exist")); + goto err; + } + + if (LIM_IS_STA_ROLE(session_entry)) { + session_entry->gLimChannelSwitch.switchMode = + csa_params->switchmode; + /* timer already started by firmware, switch immediately */ + session_entry->gLimChannelSwitch.switchCount = 0; + session_entry->gLimChannelSwitch.primaryChannel = + csa_params->channel; + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ; + + if (session_entry->vhtCapability && + session_entry->htSupportedChannelWidthSet) { + chnl_switch_info = + &session_entry->gLimWiderBWChannelSwitch; + if (csa_params->ies_present_flag & lim_wbw_ie_present) { + chnl_switch_info->newChanWidth = + csa_params->new_ch_width; + chnl_switch_info->newCenterChanFreq0 = + csa_params->new_ch_freq_seg1; + chnl_switch_info->newCenterChanFreq1 = + csa_params->new_ch_freq_seg2; + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + session_entry->gLimChannelSwitch.ch_width = + csa_params->new_ch_width + 1; + } + } else if (session_entry->htSupportedChannelWidthSet) { + if (csa_params->sec_chan_offset) { + session_entry->gLimChannelSwitch.ch_width = + CH_WIDTH_40MHZ; + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + } else { + session_entry->htSupportedChannelWidthSet = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + session_entry->htRecommendedTxWidthSet = + session_entry->htSupportedChannelWidthSet; + } + } + lim_log(mac_ctx, LOG1, FL("new ch width = %d"), + session_entry->gLimChannelSwitch.ch_width); + + lim_prepare_for11h_channel_switch(mac_ctx, session_entry); + csa_offload_ind = cdf_mem_malloc(sizeof(tSmeCsaOffloadInd)); + if (NULL == csa_offload_ind) { + lim_log(mac_ctx, LOGE, + FL("memalloc fail eWNI_SME_CSA_OFFLOAD_EVENT")); + goto err; + } + + cdf_mem_set(csa_offload_ind, sizeof(tSmeCsaOffloadInd), 0); + csa_offload_ind->mesgType = eWNI_SME_CSA_OFFLOAD_EVENT; + csa_offload_ind->mesgLen = sizeof(tSmeCsaOffloadInd); + cdf_mem_copy(csa_offload_ind->bssId, session_entry->bssId, + sizeof(tSirMacAddr)); + mmh_msg.type = eWNI_SME_CSA_OFFLOAD_EVENT; + mmh_msg.bodyptr = csa_offload_ind; + mmh_msg.bodyval = 0; + lim_log(mac_ctx, LOG1, + FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME. ")); + MTRACE(mac_trace_msg_tx + (mac_ctx, session_entry->peSessionId, mmh_msg.type)); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(mac_ctx, + WLAN_PE_DIAG_SWITCH_CHL_IND_EVENT, session_entry, + eSIR_SUCCESS, eSIR_SUCCESS); +#endif + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); + } + +err: + cdf_mem_free(csa_params); +} + +/*-------------------------------------------------------------------------- + \brief pe_delete_session() - Handle the Delete BSS Response from HAL. + + \param pMac - pointer to global adapter context + \param sessionId - Message pointer. + + \sa + --------------------------------------------------------------------------*/ + +void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ) +{ + tpPESession psessionEntry; + tpDeleteBssParams pDelBss = (tpDeleteBssParams) (MsgQ->bodyptr); + + psessionEntry = + pe_find_session_by_session_id(pMac, pDelBss->sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session Does not exist for given sessionID %d"), + pDelBss->sessionId); + return; + } + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + lim_ibss_del_bss_rsp(pMac, MsgQ->bodyptr, psessionEntry); + } else if (LIM_IS_UNKNOWN_ROLE(psessionEntry)) { + lim_process_sme_del_bss_rsp(pMac, MsgQ->bodyval, psessionEntry); + } + + else + lim_process_mlm_del_bss_rsp(pMac, MsgQ, psessionEntry); + +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/** ----------------------------------------------------------------- + \brief lim_send_sme_aggr_qos_rsp() - 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 +lim_send_sme_aggr_qos_rsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp, + uint8_t smesessionId) +{ + tSirMsgQ mmhMsg; + + mmhMsg.type = eWNI_SME_FT_AGGR_QOS_RSP; + mmhMsg.bodyptr = aggrQosRsp; + mmhMsg.bodyval = 0; + MTRACE(mac_trace_msg_tx(pMac, smesessionId, mmhMsg.type)); + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return; +} +#endif + +void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + uint8_t smesessionId) +{ + tSirMsgQ mmhMsg; + tSmeMaxAssocInd *pSmeMaxAssocInd; + + pSmeMaxAssocInd = cdf_mem_malloc(sizeof(tSmeMaxAssocInd)); + if (NULL == pSmeMaxAssocInd) { + PELOGE(lim_log(pMac, LOGE, FL("Failed to allocate memory"));) + return; + } + cdf_mem_set((void *)pSmeMaxAssocInd, sizeof(tSmeMaxAssocInd), 0); + cdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peerMac, + (uint8_t *) 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(lim_log(pMac, LOG1, FL("msgType %s peerMacAddr " MAC_ADDRESS_STR + " sme session id %d"), + "eWNI_SME_MAX_ASSOC_EXCEEDED", + MAC_ADDR_ARRAY(peerMacAddr)); + ) + MTRACE(mac_trace_msg_tx(pMac, smesessionId, mmhMsg.type)); + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return; +} + +/** ----------------------------------------------------------------- + \brief lim_send_sme_dfs_event_notify() - 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 +lim_send_sme_dfs_event_notify(tpAniSirGlobal pMac, uint16_t msgType, void *event) +{ + tSirMsgQ mmhMsg; + mmhMsg.type = eWNI_SME_DFS_RADAR_FOUND; + mmhMsg.bodyptr = event; + mmhMsg.bodyval = 0; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + return; +} + +/*-------------------------------------------------------------------------- + \brief lim_send_dfs_chan_sw_ie_update() + 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 +lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + /* Update the beacon template and send to FW */ + if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) + return; + } + + /* Send update beacon template message */ + lim_send_beacon_ind(pMac, psessionEntry); + PELOG1(lim_log(pMac, LOG1, + FL(" Updated CSA IE, IE COUNT = %d"), + psessionEntry->gLimChannelSwitch.switchCount); + ) + + return; +} + +/** ----------------------------------------------------------------- + \brief lim_send_sme_ap_channel_switch_resp() - sends + eWNI_SME_CHANNEL_CHANGE_RSP + After receiving WMA_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 +lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams) +{ + tSirMsgQ mmhMsg; + tpSwitchChannelParams pSmeSwithChnlParams; + uint8_t channelId; + + pSmeSwithChnlParams = (tSwitchChannelParams *) + cdf_mem_malloc(sizeof(tSwitchChannelParams)); + if (NULL == pSmeSwithChnlParams) { + lim_log(pMac, LOGP, + FL("AllocateMemory failed for pSmeSwithChnlParams\n")); + return; + } + + cdf_mem_set((void *)pSmeSwithChnlParams, + sizeof(tSwitchChannelParams), 0); + + cdf_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; + lim_sys_process_mmh_msg_api(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 (CHANNEL_STATE_DFS != cds_get_channel_state(channelId)) { + if (channelId == psessionEntry->currentOperChannel) { + lim_apply_configuration(pMac, psessionEntry); + lim_send_beacon_ind(pMac, psessionEntry); + } else { + PELOG1(lim_log(pMac, LOG1, + FL + ("Failed to Transmit Beacons on channel = %d" + "after AP channel change response"), + psessionEntry->bcnLen); + ) + } + } + return; +} + +/** ----------------------------------------------------------------- + \brief lim_process_beacon_tx_success_ind() - 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 +lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t 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; + struct sir_beacon_tx_complete_rsp *beacon_tx_comp_rsp_ptr; + uint8_t length = sizeof(tSirSmeCSAIeTxCompleteRsp); + tpSirFirstBeaconTxCompleteInd pBcnTxInd = + (tSirFirstBeaconTxCompleteInd *) event; + + psessionEntry = pe_find_session_by_bss_idx(pMac, pBcnTxInd->bssIdx); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session Does not exist for given sessionID")); + return; + } + + if (LIM_IS_AP_ROLE(psessionEntry) && + 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 + */ + lim_send_dfs_chan_sw_ie_update(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 == false) + psessionEntry->gLimChannelSwitch.switchMode = 0; + psessionEntry->dfsIncludeChanSwIe = false; + psessionEntry->dfsIncludeChanWrapperIe = false; + + pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *) + cdf_mem_malloc(length); + + if (NULL == pChanSwTxResponse) { + lim_log(pMac, LOGP, + FL + ("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp")); + return; + } + + cdf_mem_set((void *)pChanSwTxResponse, length, 0); + pChanSwTxResponse->sessionId = + psessionEntry->smeSessionId; + pChanSwTxResponse->chanSwIeTxStatus = + CDF_STATUS_SUCCESS; + + mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; + mmhMsg.bodyptr = pChanSwTxResponse; + mmhMsg.bodyval = 0; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + } + } + + if (LIM_IS_AP_ROLE(psessionEntry) && + psessionEntry->gLimOperatingMode.present) { + /* Done with nss update, send response back to SME */ + psessionEntry->gLimOperatingMode.present = 0; + beacon_tx_comp_rsp_ptr = (struct sir_beacon_tx_complete_rsp *) + cdf_mem_malloc(sizeof(*beacon_tx_comp_rsp_ptr)); + if (NULL == beacon_tx_comp_rsp_ptr) { + lim_log(pMac, LOGP, + FL + ("AllocateMemory failed for beacon_tx_comp_rsp_ptr")); + return; + } + cdf_mem_set((void *)beacon_tx_comp_rsp_ptr, + sizeof(*beacon_tx_comp_rsp_ptr), 0); + beacon_tx_comp_rsp_ptr->session_id = + psessionEntry->smeSessionId; + beacon_tx_comp_rsp_ptr->tx_status = CDF_STATUS_SUCCESS; + mmhMsg.type = eWNI_SME_NSS_UPDATE_RSP; + mmhMsg.bodyptr = beacon_tx_comp_rsp_ptr; + mmhMsg.bodyval = 0; + lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + } + return; +} diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h new file mode 100644 index 000000000000..e707481ad6c3 --- /dev/null +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h @@ -0,0 +1,134 @@ +/* + * 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 lim_send_sme_rsp_messages.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 "sir_common.h" +#include "sir_api.h" +#include "sir_mac_prot_def.h" + +/* Functions for sending responses to Host */ +void lim_send_sme_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes, uint8_t, + uint16_t); +void lim_send_sme_roc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, + tSirResultCodes result_code, uint8_t sme_session_id, + uint32_t scan_id); +void lim_send_sme_start_bss_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes, + tpPESession, uint8_t, uint16_t); +void lim_send_sme_scan_rsp(tpAniSirGlobal, tSirResultCodes, uint8_t, + uint16_t, uint32_t scan_id); +void lim_post_sme_scan_rsp_message(tpAniSirGlobal, tSirResultCodes, + uint8_t, uint16_t, uint32_t scan_id); + +void lim_send_sme_join_reassoc_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes, + uint16_t, tpPESession, uint8_t, uint16_t); +void lim_send_sme_disassoc_ntf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, + uint16_t, uint16_t, uint8_t, uint16_t, tpPESession); +void lim_send_sme_deauth_ntf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, uint16_t, + uint16_t, uint8_t, uint16_t); +void lim_send_sme_disassoc_ind(tpAniSirGlobal, tpDphHashNode, tpPESession); +void lim_send_sme_deauth_ind(tpAniSirGlobal, tpDphHashNode, + tpPESession psessionEntry); +void lim_send_sme_wm_status_change_ntf(tpAniSirGlobal, tSirSmeStatusChangeCode, + uint32_t *, uint16_t, uint8_t); +void lim_send_sme_set_context_rsp(tpAniSirGlobal, tSirMacAddr, uint16_t, + tSirResultCodes, tpPESession, uint8_t, uint16_t); +void lim_send_sme_neighbor_bss_ind(tpAniSirGlobal, tLimScanResultNode *); +void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ); +void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg); + +#ifdef WLAN_FEATURE_VOWIFI_11R +void +lim_send_sme_aggr_qos_rsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp, + uint8_t smesessionId); +#endif /*WLAN_FEATURE_VOWIFI_11R */ + +void lim_send_sme_addts_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, uint32_t status, + tpPESession psessionEntry, tSirMacTspecIE tspec, + uint8_t smesessionId, uint16_t smetransactionId); +void lim_send_sme_delts_rsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, + uint32_t status, tpPESession psessionEntry, + uint8_t smessionId, uint16_t smetransactionId); +void lim_send_sme_delts_ind(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, + uint16_t aid, tpPESession); +void lim_send_sme_stats_rsp(tpAniSirGlobal pMac, uint16_t msgtype, void *stats); + +void lim_send_sme_pe_statistics_rsp(tpAniSirGlobal pMac, uint16_t msgtype, + void *stats); +#ifdef FEATURE_WLAN_ESE_UPLOAD +void lim_send_sme_pe_ese_tsm_rsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats); +#endif + +void lim_send_sme_ibss_peer_ind(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + uint16_t staIndex, uint8_t ucastIdx, + uint8_t bcastIdx, uint8_t *beacon, + uint16_t beaconLen, uint16_t msgType, + uint8_t sessionId); +#ifdef FEATURE_OEM_DATA_SUPPORT +void lim_send_sme_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *pMsgBuf, + tSirResultCodes resultCode); +#endif + +void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + uint8_t smesessionId); +#ifdef FEATURE_WLAN_TDLS +void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, uint8_t sessionId, + tSirMacAddr peerMac, + tDphHashNode *pStaDs, uint8_t status); +void lim_send_sme_tdls_event_notify(tpAniSirGlobal pMac, uint16_t msgType, + void *events); +#endif + +void lim_send_sme_dfs_event_notify(tpAniSirGlobal pMac, uint16_t msgType, + void *event); +void lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tpSwitchChannelParams pChnlParams); +void +lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t 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/core/mac/src/pe/lim/lim_ser_des_utils.c b/core/mac/src/pe/lim/lim_ser_des_utils.c new file mode 100644 index 000000000000..bd778f55cc90 --- /dev/null +++ b/core/mac/src/pe/lim/lim_ser_des_utils.c @@ -0,0 +1,78 @@ +/* + * 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 lim_ser_des_utils.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 "ani_system_defs.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_ser_des_utils.h" + +/**--------------------------------------------------------------- + \fn lim_get_session_info + \brief This function returns the sessionId and transactionId + \ of a message. This assumes that the message structure + \ is of format: + \ uint16_t messageType + \ uint16_t messageLength + \ uint8_t sessionId + \ uint16_t 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 +lim_get_session_info(tpAniSirGlobal pMac, uint8_t *pBuf, uint8_t *sessionId, + uint16_t *transactionId) +{ + if (!pBuf) { + lim_log(pMac, LOGE, FL("NULL ptr received. ")); + return; + } + + pBuf += sizeof(uint16_t); /* skip message type */ + pBuf += sizeof(uint16_t); /* skip message length */ + + *sessionId = *pBuf; /* get sessionId */ + pBuf++; + *transactionId = lim_get_u16(pBuf); /* get transactionId */ + + return; +} diff --git a/core/mac/src/pe/lim/lim_ser_des_utils.h b/core/mac/src/pe/lim/lim_ser_des_utils.h new file mode 100644 index 000000000000..f05f4ddd0a9e --- /dev/null +++ b/core/mac/src/pe/lim/lim_ser_des_utils.h @@ -0,0 +1,98 @@ +/* + * 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 lim_ser_des_utils.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 "sir_api.h" +#include "ani_system_defs.h" +#include "sir_mac_prot_def.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_prop_exts_utils.h" + +void lim_get_session_info(tpAniSirGlobal pMac, uint8_t *, + uint8_t *, uint16_t *); + +/* Byte String <--> uint16_t/uint32_t copy functions */ +static inline void lim_copy_u16(uint8_t *ptr, uint16_t u16Val) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + *ptr++ = (uint8_t) (u16Val & 0xff); + *ptr = (uint8_t) ((u16Val >> 8) & 0xff); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline uint16_t lim_get_u16(uint8_t *ptr) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + return ((uint16_t) (*(ptr + 1) << 8)) | ((uint16_t) (*ptr)); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline void lim_copy_u32(uint8_t *ptr, uint32_t u32Val) +{ +#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \ + (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN))) + *ptr++ = (uint8_t) (u32Val & 0xff); + *ptr++ = (uint8_t) ((u32Val >> 8) & 0xff); + *ptr++ = (uint8_t) ((u32Val >> 16) & 0xff); + *ptr = (uint8_t) ((u32Val >> 24) & 0xff); +#else +#error "Unknown combination of OS Type and endianess" +#endif +} + +static inline uint32_t lim_get_u32(uint8_t *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/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c new file mode 100644 index 000000000000..6c73b4ce2b2f --- /dev/null +++ b/core/mac/src/pe/lim/lim_session.c @@ -0,0 +1,767 @@ +/* + * 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 lim_session.c + + \brief implementation for lim Session related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "ani_global.h" +#include "lim_debug.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#include "lim_ft.h" +#endif +#include "lim_session.h" +#include "lim_utils.h" + +#include "sch_api.h" +#include "lim_send_messages.h" + +/*-------------------------------------------------------------------------- + + \brief pe_init_beacon_params() - Initialize the beaconParams structure + + \param tpPESession - pointer to the session context or NULL if session can not be created. + \return void + \sa + + --------------------------------------------------------------------------*/ + +void pe_init_beacon_params(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 */ + cdf_mem_set((void *)&psessionEntry->gLim11bParams, + sizeof(tLimProtStaParams), 0); + cdf_mem_set((void *)&psessionEntry->gLim11aParams, + sizeof(tLimProtStaParams), 0); + cdf_mem_set((void *)&psessionEntry->gLim11gParams, + sizeof(tLimProtStaParams), 0); + cdf_mem_set((void *)&psessionEntry->gLimNonGfParams, + sizeof(tLimProtStaParams), 0); + cdf_mem_set((void *)&psessionEntry->gLimHt20Params, + sizeof(tLimProtStaParams), 0); + cdf_mem_set((void *)&psessionEntry->gLimLsigTxopParams, + sizeof(tLimProtStaParams), 0); + cdf_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; + uint16_t current_protection_state = 0; + tpDphHashNode station_hash_node = NULL; + tSirMacHTOperatingMode old_op_mode; + bool bcn_prms_changed = false; + + if (pe_session_entry->valid == false) { + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_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; + + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_INFO, + FL("old protection state: 0x%04X, new protection state: 0x%04X\n"), + pe_session_entry->old_protection_state, + current_protection_state); + + cdf_mem_zero(&pe_session_entry->gLimOverlap11gParams, + sizeof(pe_session_entry->gLimOverlap11gParams)); + cdf_mem_zero(&pe_session_entry->gLimOverlap11aParams, + sizeof(pe_session_entry->gLimOverlap11aParams)); + cdf_mem_zero(&pe_session_entry->gLimOverlapHt20Params, + sizeof(pe_session_entry->gLimOverlapHt20Params)); + cdf_mem_zero(&pe_session_entry->gLimOverlapNonGfParams, + sizeof(pe_session_entry->gLimOverlapNonGfParams)); + + cdf_mem_zero(&pe_session_entry->gLimOlbcParams, + sizeof(pe_session_entry->gLimOlbcParams)); + + cdf_mem_zero(&pe_session_entry->beaconParams, + sizeof(pe_session_entry->beaconParams)); + + cdf_mem_zero(&mac_ctx->lim.gLimOverlap11gParams, + sizeof(mac_ctx->lim.gLimOverlap11gParams)); + cdf_mem_zero(&mac_ctx->lim.gLimOverlap11aParams, + sizeof(mac_ctx->lim.gLimOverlap11aParams)); + cdf_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params, + sizeof(mac_ctx->lim.gLimOverlapHt20Params)); + cdf_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; + + cdf_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 = dph_get_hash_entry(mac_ctx, i, + &pe_session_entry->dph.dphHashTable); + if (NULL == station_hash_node) + continue; + lim_decide_ap_protection(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) && + (false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) { + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_ERROR, + FL("protection changed, update beacon template\n")); + /* update beacon fix params and send update to FW */ + cdf_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) { + sch_set_fixed_beacon_fields(mac_ctx, pe_session_entry); + lim_send_beacon_params(mac_ctx, &beacon_params, pe_session_entry); + } + + pe_session_entry->old_protection_state = current_protection_state; + if (cdf_mc_timer_start(&pe_session_entry-> + protection_fields_reset_timer, + SCH_PROTECTION_RESET_TIME) + != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_ERROR, + FL("cannot create or start protectionFieldsResetTimer\n")); + } +} + +/** + * pe_create_session() creates a new PE session given the BSSID + * @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 + * + * 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. + * + * Return: tpPESession: pointer to the session context or NULL if session + * can not be created. + */ + +tpPESession +pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, + uint16_t numSta, tSirBssType bssType) +{ + CDF_STATUS status; + uint8_t i; + tpPESession session_ptr; + for (i = 0; i < pMac->lim.maxBssId; i++) { + /* Find first free room in session table */ + if (pMac->lim.gpSession[i].valid == true) + continue; + break; + } + + if (i == pMac->lim.maxBssId) { + lim_log(pMac, LOGE, + FL("Session can't be created. Reached max sessions\n")); + return NULL; + } + + session_ptr = &pMac->lim.gpSession[i]; + cdf_mem_set((void *)session_ptr, sizeof(tPESession), 0); + /* Allocate space for Station Table for this session. */ + session_ptr->dph.dphHashTable.pHashTable = + cdf_mem_malloc(sizeof(tpDphHashNode) * (numSta + 1)); + if (NULL == session_ptr->dph.dphHashTable.pHashTable) { + lim_log(pMac, LOGE, FL("memory allocate failed!")); + return NULL; + } + + session_ptr->dph.dphHashTable.pDphNodeArray = + cdf_mem_malloc(sizeof(tDphHashNode) * (numSta + 1)); + if (NULL == session_ptr->dph.dphHashTable.pDphNodeArray) { + lim_log(pMac, LOGE, FL("memory allocate failed!")); + cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable); + session_ptr->dph.dphHashTable. + pHashTable = NULL; + return NULL; + } + + session_ptr->dph.dphHashTable.size = numSta + 1; + dph_hash_table_class_init(pMac, &session_ptr->dph.dphHashTable); + session_ptr->gpLimPeerIdxpool = cdf_mem_malloc( + sizeof(*(session_ptr->gpLimPeerIdxpool)) * (numSta + 1)); + if (NULL == session_ptr->gpLimPeerIdxpool) { + lim_log(pMac, LOGE, FL("memory allocate failed!")); + cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable); + cdf_mem_free(session_ptr->dph.dphHashTable.pDphNodeArray); + session_ptr->dph.dphHashTable.pHashTable = NULL; + session_ptr->dph.dphHashTable.pDphNodeArray = NULL; + return NULL; + } + cdf_mem_set(session_ptr->gpLimPeerIdxpool, + sizeof(*session_ptr->gpLimPeerIdxpool) * (numSta + 1), + 0); + session_ptr->freePeerIdxHead = 0; + session_ptr->freePeerIdxTail = 0; + session_ptr->gLimNumOfCurrentSTAs = 0; + /* Copy the BSSID to the session table */ + sir_copy_mac_addr(session_ptr->bssId, bssid); + session_ptr->valid = true; + /* Intialize the SME and MLM states to IDLE */ + session_ptr->limMlmState = eLIM_MLM_IDLE_STATE; + session_ptr->limSmeState = eLIM_SME_IDLE_STATE; + session_ptr->limCurrentAuthType = eSIR_OPEN_SYSTEM; + pe_init_beacon_params(pMac, &pMac->lim.gpSession[i]); +#ifdef WLAN_FEATURE_VOWIFI_11R + session_ptr->is11Rconnection = false; +#endif +#ifdef FEATURE_WLAN_ESE + session_ptr->isESEconnection = false; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + session_ptr->isFastTransitionEnabled = false; +#endif +#ifdef FEATURE_WLAN_LFR + session_ptr->isFastRoamIniFeatureEnabled = false; +#endif + *sessionId = i; + session_ptr->gLimPhyMode = WNI_CFG_PHY_MODE_11G; + /* Initialize CB mode variables when session is created */ + session_ptr->htSupportedChannelWidthSet = 0; + session_ptr->htRecommendedTxWidthSet = 0; + session_ptr->htSecondaryChannelOffset = 0; +#ifdef FEATURE_WLAN_TDLS + cdf_mem_set(session_ptr->peerAIDBitmap, + sizeof(session_ptr->peerAIDBitmap), 0); + session_ptr->tdls_prohibited = false; + session_ptr->tdls_chan_swit_prohibited = false; +#endif + session_ptr->fWaitForProbeRsp = 0; + session_ptr->fIgnoreCapsChange = 0; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + FL("Create a new PE session(%d), BSSID: "MAC_ADDRESS_STR" Max No. of STA %d"), + session_ptr->peSessionId, MAC_ADDR_ARRAY(bssid), numSta); + + if (eSIR_INFRA_AP_MODE == bssType + || eSIR_IBSS_MODE == bssType + || eSIR_BTAMP_AP_MODE == bssType) { + session_ptr->pSchProbeRspTemplate = + cdf_mem_malloc(SCH_MAX_PROBE_RESP_SIZE); + session_ptr->pSchBeaconFrameBegin = + cdf_mem_malloc(SCH_MAX_BEACON_SIZE); + session_ptr->pSchBeaconFrameEnd = + cdf_mem_malloc(SCH_MAX_BEACON_SIZE); + if ((NULL == session_ptr->pSchProbeRspTemplate) + || (NULL == session_ptr->pSchBeaconFrameBegin) + || (NULL == session_ptr->pSchBeaconFrameEnd)) { + lim_log(pMac, LOGE, FL("memory allocate failed!")); + cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable); + cdf_mem_free(session_ptr->dph.dphHashTable.pDphNodeArray); + cdf_mem_free(session_ptr->gpLimPeerIdxpool); + cdf_mem_free(session_ptr->pSchProbeRspTemplate); + cdf_mem_free(session_ptr->pSchBeaconFrameBegin); + cdf_mem_free(session_ptr->pSchBeaconFrameEnd); + + session_ptr->dph.dphHashTable.pHashTable = NULL; + session_ptr->dph.dphHashTable.pDphNodeArray = NULL; + session_ptr->gpLimPeerIdxpool = NULL; + session_ptr->pSchProbeRspTemplate = NULL; + session_ptr->pSchBeaconFrameBegin = NULL; + session_ptr->pSchBeaconFrameEnd = NULL; + return NULL; + } + } +#if defined WLAN_FEATURE_VOWIFI_11R + if (eSIR_INFRASTRUCTURE_MODE == bssType) + lim_ft_open(pMac, &pMac->lim.gpSession[i]); +#endif + if (eSIR_INFRA_AP_MODE == bssType) { + session_ptr->old_protection_state = 0; + session_ptr->mac_ctx = (void *)pMac; + status = cdf_mc_timer_init( + &session_ptr->protection_fields_reset_timer, + CDF_TIMER_TYPE_SW, pe_reset_protection_callback, + (void *)&pMac->lim.gpSession[i]); + if (status == CDF_STATUS_SUCCESS) { + status = cdf_mc_timer_start( + &session_ptr->protection_fields_reset_timer, + SCH_PROTECTION_RESET_TIME); + } + if (status != CDF_STATUS_SUCCESS) + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("cannot create or start protectionFieldsResetTimer\n")); + } + return &pMac->lim.gpSession[i]; +} + +/*-------------------------------------------------------------------------- + \brief pe_find_session_by_bssid() - 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 pe_find_session_by_bssid(tpAniSirGlobal pMac, uint8_t *bssid, + uint8_t *sessionId) +{ + uint8_t i; + + for (i = 0; i < pMac->lim.maxBssId; i++) { + /* If BSSID matches return corresponding tables address */ + if ((pMac->lim.gpSession[i].valid) + && (sir_compare_mac_addr(pMac->lim.gpSession[i].bssId, bssid))) + { + *sessionId = i; + return (&pMac->lim.gpSession[i]); + } + } + + lim_log(pMac, LOG4, FL("Session lookup fails for BSSID: \n ")); + lim_print_mac_addr(pMac, bssid, LOG4); + return (NULL); + +} + +/*-------------------------------------------------------------------------- + \brief pe_find_session_by_bss_idx() - 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 pe_find_session_by_bss_idx(tpAniSirGlobal pMac, uint8_t bssIdx) +{ + uint8_t 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]; + } + } + lim_log(pMac, LOG4, FL("Session lookup fails for bssIdx: %d"), bssIdx); + return NULL; +} + +/*-------------------------------------------------------------------------- + \brief pe_find_session_by_session_id() - 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 pe_find_session_by_session_id(tpAniSirGlobal pMac, uint8_t sessionId) +{ + if (sessionId >= pMac->lim.maxBssId) { + lim_log(pMac, LOGE, FL("Invalid sessionId: %d \n "), sessionId); + return (NULL); + } + if ((pMac->lim.gpSession[sessionId].valid == true)) { + return (&pMac->lim.gpSession[sessionId]); + } + return (NULL); + +} + +/** + * pe_find_session_by_sta_id() - looks up the PE session given staid. + * @mac_ctx: pointer to global adapter context + * @staid: StaId of the session + * @session_id: session ID is returned here, if session is found. + * + * 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. + * + * Return: session pointer + */ +tpPESession +pe_find_session_by_sta_id(tpAniSirGlobal mac_ctx, + uint8_t staid, + uint8_t *session_id) +{ + uint8_t i, j; + tpPESession session_ptr; + dphHashTableClass *dph_ptr; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + if (!mac_ctx->lim.gpSession[i].valid) + continue; + session_ptr = &mac_ctx->lim.gpSession[i]; + dph_ptr = &session_ptr->dph.dphHashTable; + for (j = 0; j < dph_ptr->size; j++) { + if (dph_ptr->pDphNodeArray[j].valid + && dph_ptr->pDphNodeArray[j].added + && staid == dph_ptr->pDphNodeArray[j].staIndex) { + *session_id = i; + return session_ptr; + } + } + } + + lim_log(mac_ctx, LOG4, + FL("Session lookup fails for StaId: %d\n "), staid); + return NULL; +} + +/** + * pe_delete_session() - deletes the PE session given the session ID. + * @mac_ctx: pointer to global adapter context + * @session: session to be deleted. + * + * Deletes the given PE session + * + * Return: void + */ +void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) +{ + uint16_t i = 0; + uint16_t n; + TX_TIMER *timer_ptr; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + FL("Trying to delete PE session %d Opmode %d BssIdx %d BSSID: "MAC_ADDRESS_STR), + session->peSessionId, session->operMode, + session->bssIdx, + MAC_ADDR_ARRAY(session->bssId)); + for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) { + timer_ptr = &mac_ctx->lim.limTimers.gpLimCnfWaitTimer[n]; + if (session->peSessionId == timer_ptr->sessionId) + if (true == tx_timer_running(timer_ptr)) + tx_timer_deactivate(timer_ptr); + } + +#if defined (WLAN_FEATURE_VOWIFI_11R) + /* Delete FT related information */ + lim_ft_cleanup(mac_ctx, session); +#endif + if (session->pLimStartBssReq != NULL) { + cdf_mem_free(session->pLimStartBssReq); + session->pLimStartBssReq = NULL; + } + + if (session->pLimJoinReq != NULL) { + cdf_mem_free(session->pLimJoinReq); + session->pLimJoinReq = NULL; + } + + if (session->pLimReAssocReq != NULL) { + cdf_mem_free(session->pLimReAssocReq); + session->pLimReAssocReq = NULL; + } + + if (session->pLimMlmJoinReq != NULL) { + cdf_mem_free(session->pLimMlmJoinReq); + session->pLimMlmJoinReq = NULL; + } + + if (session->dph.dphHashTable.pHashTable != NULL) { + cdf_mem_free(session->dph.dphHashTable.pHashTable); + session->dph.dphHashTable.pHashTable = NULL; + } + + if (session->dph.dphHashTable.pDphNodeArray != NULL) { + cdf_mem_free(session->dph.dphHashTable.pDphNodeArray); + session->dph.dphHashTable.pDphNodeArray = NULL; + } + + if (session->gpLimPeerIdxpool != NULL) { + cdf_mem_free(session->gpLimPeerIdxpool); + session->gpLimPeerIdxpool = NULL; + } + + if (session->beacon != NULL) { + cdf_mem_free(session->beacon); + session->beacon = NULL; + } + + if (session->assocReq != NULL) { + cdf_mem_free(session->assocReq); + session->assocReq = NULL; + } + + if (session->assocRsp != NULL) { + cdf_mem_free(session->assocRsp); + session->assocRsp = NULL; + } + + if (session->parsedAssocReq != NULL) { + tpSirAssocReq tmp_ptr = NULL; + /* Cleanup the individual allocation first */ + for (i = 0; i < session->dph.dphHashTable.size; i++) { + if (session->parsedAssocReq[i] == NULL) + continue; + tmp_ptr = ((tpSirAssocReq) + (session->parsedAssocReq[i])); + if (tmp_ptr->assocReqFrame) { + cdf_mem_free(tmp_ptr->assocReqFrame); + tmp_ptr->assocReqFrame = NULL; + tmp_ptr->assocReqFrameLength = 0; + } + cdf_mem_free(session->parsedAssocReq[i]); + session->parsedAssocReq[i] = NULL; + } + /* Cleanup the whole block */ + cdf_mem_free(session->parsedAssocReq); + session->parsedAssocReq = NULL; + } + if (NULL != session->limAssocResponseData) { + cdf_mem_free(session->limAssocResponseData); + session->limAssocResponseData = NULL; + } +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (NULL != session->pLimMlmReassocRetryReq) { + cdf_mem_free(session->pLimMlmReassocRetryReq); + session->pLimMlmReassocRetryReq = NULL; + } +#endif + if (NULL != session->pLimMlmReassocReq) { + cdf_mem_free(session->pLimMlmReassocReq); + session->pLimMlmReassocReq = NULL; + } + + if (NULL != session->pSchProbeRspTemplate) { + cdf_mem_free(session->pSchProbeRspTemplate); + session->pSchProbeRspTemplate = NULL; + } + + if (NULL != session->pSchBeaconFrameBegin) { + cdf_mem_free(session->pSchBeaconFrameBegin); + session->pSchBeaconFrameBegin = NULL; + } + + if (NULL != session->pSchBeaconFrameEnd) { + cdf_mem_free(session->pSchBeaconFrameEnd); + session->pSchBeaconFrameEnd = NULL; + } + + /* Must free the buffer before peSession invalid */ + if (NULL != session->addIeParams.probeRespData_buff) { + cdf_mem_free(session->addIeParams.probeRespData_buff); + session->addIeParams.probeRespData_buff = NULL; + session->addIeParams.probeRespDataLen = 0; + } + if (NULL != session->addIeParams.assocRespData_buff) { + cdf_mem_free(session->addIeParams.assocRespData_buff); + session->addIeParams.assocRespData_buff = NULL; + session->addIeParams.assocRespDataLen = 0; + } + if (NULL != session->addIeParams.probeRespBCNData_buff) { + cdf_mem_free(session->addIeParams.probeRespBCNData_buff); + session->addIeParams.probeRespBCNData_buff = NULL; + session->addIeParams.probeRespBCNDataLen = 0; + } +#ifdef WLAN_FEATURE_11W + /* if PMF connection */ + if (session->limRmfEnabled) + cdf_mc_timer_destroy(&session->pmfComebackTimer); +#endif + + if (LIM_IS_AP_ROLE(session)) { + cdf_mc_timer_stop(&session->protection_fields_reset_timer); + cdf_mc_timer_destroy(&session->protection_fields_reset_timer); + } + + session->valid = false; + + if (LIM_IS_AP_ROLE(session)) + lim_check_and_reset_protection_params(mac_ctx); + + return; +} + +/*-------------------------------------------------------------------------- + \brief pe_find_session_by_peer_sta() - 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 pe_find_session_by_peer_sta(tpAniSirGlobal pMac, uint8_t *sa, + uint8_t *sessionId) +{ + uint8_t i; + tpDphHashNode pSta; + uint16_t aid; + + for (i = 0; i < pMac->lim.maxBssId; i++) { + if ((pMac->lim.gpSession[i].valid)) { + pSta = + dph_lookup_hash_entry(pMac, sa, &aid, + &pMac->lim.gpSession[i].dph. + dphHashTable); + if (pSta != NULL) { + *sessionId = i; + return &pMac->lim.gpSession[i]; + } + } + } + + lim_log(pMac, LOG1, FL("Session lookup fails for Peer StaId: \n ")); + lim_print_mac_addr(pMac, sa, LOG1); + 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, + uint8_t 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]; + } + } + lim_log(mac_ctx, LOG4, + FL("Session lookup fails for smeSessionID: %d"), + sme_session_id); + 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 + */ +uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx) +{ + uint8_t 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/core/mac/src/pe/lim/lim_session_utils.c b/core/mac/src/pe/lim/lim_session_utils.c new file mode 100644 index 000000000000..49b37a12b8d4 --- /dev/null +++ b/core/mac/src/pe/lim/lim_session_utils.c @@ -0,0 +1,145 @@ +/* + * 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 lim_session_utils.c + \brief implementation for lim Session Utility APIs + \author Sunit Bhatia + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "ani_global.h" +#include "lim_debug.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "lim_session_utils.h" +#include "lim_utils.h" + +/** + * is_lim_session_off_channel() - checks if any other off channel session exists + * @mac_ctx: Global MAC context. + * @sessionId: PE session ID. + * + * Return: This function returns true if the session Id passed needs to be on + * a different channel than atleast one session already active. + **/ +uint8_t is_lim_session_off_channel(tpAniSirGlobal mac_ctx, uint8_t session_id) +{ + uint8_t i; + + if (session_id >= mac_ctx->lim.maxBssId) { + lim_log(mac_ctx, LOGE, FL("Invalid session_id:%d"), session_id); + return false; + } + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + /* Skip the session_id that is to be joined. */ + if (i == session_id) + continue; + /* + * if another session is valid and it is on different channel + * then it is an off channel operation. + */ + if ((mac_ctx->lim.gpSession[i].valid) && + (mac_ctx->lim.gpSession[i].currentOperChannel != + mac_ctx->lim.gpSession[session_id].currentOperChannel)) + return true; + } + return false; + +} + +/** + * lim_is_chan_switch_running() - check if channel switch is happening + * @mac_ctx: Global MAC context. + * + * Return: 1 - if channel switch is happening on any session. + * 0 - if channel switch is not happening. + **/ +uint8_t lim_is_chan_switch_running(tpAniSirGlobal mac_ctx) +{ + uint8_t i; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) + if (mac_ctx->lim.gpSession[i].valid && + mac_ctx->lim.gpSession[i].gLimSpecMgmt.dot11hChanSwState + == eLIM_11H_CHANSW_RUNNING) + return 1; + return 0; +} + +/** + * lim_is_in_mcc() - check if device is in MCC + * @mac_ctx: Global MAC context. + * + * Return: true - if in MCC. + * false - Not in MCC + **/ +uint8_t lim_is_in_mcc(tpAniSirGlobal mac_ctx) +{ + uint8_t i; + uint8_t chan = 0; + uint8_t curr_oper_channel = 0; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + /* + * if another session is valid and it is on different channel + * it is an off channel operation. + */ + if ((mac_ctx->lim.gpSession[i].valid)) { + curr_oper_channel = + mac_ctx->lim.gpSession[i].currentOperChannel; + if (chan == 0) + chan = curr_oper_channel; + else if (chan != curr_oper_channel) + return true; + } + } + return false; +} + +/** + * pe_get_current_stas_count() - Total stations associated on all sessions. + * @mac_ctx: Global MAC context. + * + * Return: true - Number of stations active on all sessions. + **/ +uint8_t pe_get_current_stas_count(tpAniSirGlobal mac_ctx) +{ + uint8_t i; + uint8_t stacount = 0; + for (i = 0; i < mac_ctx->lim.maxBssId; i++) + if (mac_ctx->lim.gpSession[i].valid == true) + stacount += + mac_ctx->lim.gpSession[i].gLimNumOfCurrentSTAs; + return stacount; +} diff --git a/core/mac/src/pe/lim/lim_session_utils.h b/core/mac/src/pe/lim/lim_session_utils.h new file mode 100644 index 000000000000..d1dd7d1c0370 --- /dev/null +++ b/core/mac/src/pe/lim/lim_session_utils.h @@ -0,0 +1,36 @@ +/* + * 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(__LIM_SESSION_UTILS_H) +#define __LIM_SESSION_UTILS_H + +uint8_t is_lim_session_off_channel(tpAniSirGlobal pMac, uint8_t sessionId); +uint8_t lim_is_chan_switch_running(tpAniSirGlobal pMac); +uint8_t lim_is_in_mcc(tpAniSirGlobal pMac); +uint8_t pe_get_current_stas_count(tpAniSirGlobal pMac); + +#endif /* #if !defined( __LIM_SESSION_UTILS_H ) */ diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c new file mode 100644 index 000000000000..550231ff03da --- /dev/null +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -0,0 +1,925 @@ +/* + * 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 lim_sme_req_utils.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 "wni_api.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "sir_api.h" +#include "sch_api.h" +#include "utils_api.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" +#include "lim_ser_des_utils.h" + +/** + * lim_is_rs_nie_valid_in_sme_req_message() + * + * @mac_ctx Pointer to Global MAC structure + * @rsn_ie Pointer to received RSN IE + * + * This function is called to verify if the RSN IE received in various SME_REQ + * messages is valid or not + * + * Return: true when RSN IE is valid, false otherwise + * + */ + +static uint8_t +lim_is_rsn_ie_valid_in_sme_req_message(tpAniSirGlobal mac_ctx, tpSirRSNie rsn_ie) +{ + uint8_t start = 0; + uint32_t privacy, val; + int len; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_PRIVACY_ENABLED, + &privacy) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, FL("Unable to retrieve POI from CFG")); + } + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RSN_ENABLED, &val) + != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGP, + FL("Unable to retrieve RSN_ENABLED from CFG")); + } + + if (rsn_ie->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(lim_log(mac_ctx, LOG1, + FL("RSN ie len %d PRIVACY %d RSN %d"), + rsn_ie->length, privacy, val);) + } + + if (!rsn_ie->length) + return true; + + if ((rsn_ie->rsnIEdata[0] != DOT11F_EID_RSN) +#ifdef FEATURE_WLAN_WAPI + && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WAPI) +#endif + && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WPA)) { + lim_log(mac_ctx, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]"), + rsn_ie->rsnIEdata[0], DOT11F_EID_RSN, + DOT11F_EID_WPA); + return false; + } + + len = rsn_ie->length; + start = 0; + while (len > 0) { + switch (rsn_ie->rsnIEdata[start]) { + case DOT11F_EID_RSN: + /* Check validity of RSN IE */ + if ((rsn_ie->rsnIEdata[start + 1] > + DOT11F_IE_RSN_MAX_LEN) + || (rsn_ie->rsnIEdata[start + 1] < + DOT11F_IE_RSN_MIN_LEN)) { + lim_log(mac_ctx, LOGE, + FL("RSN IE len %d not [%d,%d]"), + rsn_ie->rsnIEdata[start + 1], + DOT11F_IE_RSN_MIN_LEN, + DOT11F_IE_RSN_MAX_LEN); + return false; + } + break; + case DOT11F_EID_WPA: + /* Check validity of WPA IE */ + if (SIR_MAC_MAX_IE_LENGTH <= start) + break; + + if (start <= (SIR_MAC_MAX_IE_LENGTH - sizeof(uint32_t))) + val = sir_read_u32((uint8_t *) & + rsn_ie->rsnIEdata[start + 2]); + + if ((rsn_ie->rsnIEdata[start + 1] < + DOT11F_IE_WPA_MIN_LEN) + || (rsn_ie->rsnIEdata[start + 1] > + DOT11F_IE_WPA_MAX_LEN) + || (SIR_MAC_WPA_OUI != val)) { + lim_log(mac_ctx, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + rsn_ie->rsnIEdata[start + 1], + DOT11F_IE_WPA_MIN_LEN, + DOT11F_IE_WPA_MAX_LEN, + val, SIR_MAC_WPA_OUI); + return false; + } + break; +#ifdef FEATURE_WLAN_WAPI + case DOT11F_EID_WAPI: + if ((rsn_ie->rsnIEdata[start + 1] > + DOT11F_IE_WAPI_MAX_LEN) + || (rsn_ie->rsnIEdata[start + 1] < + DOT11F_IE_WAPI_MIN_LEN)) { + lim_log(mac_ctx, LOGE, + FL("WAPI IE len %d not [%d,%d]"), + rsn_ie->rsnIEdata[start + 1], + DOT11F_IE_WAPI_MIN_LEN, + DOT11F_IE_WAPI_MAX_LEN); + return false; + } + break; +#endif + default: + /* we will never be here, simply for completeness */ + return false; + } /* end of switch */ + /* EID + length field + length */ + start += 2 + rsn_ie->rsnIEdata[start + 1]; + len -= start; + } /* end while loop */ + return true; +} /*** end lim_is_rs_nie_valid_in_sme_req_message() ***/ + +/** + * lim_is_addie_valid_in_sme_req_message() + * + ***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 uint8_t +lim_is_addie_valid_in_sme_req_message(tpAniSirGlobal pMac, tpSirAddie pAddie) +{ + int left = pAddie->length; + uint8_t *ptr = pAddie->addIEdata; + uint8_t 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) { + lim_log(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 lim_is_addie_valid_in_sme_req_message() ***/ + +/** + * lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message() - to set rsnie/wpaie + * + * @mac_ctx : Pointer to Global MAC structure + * @rsn_ie : Pointer to received RSN IE + * @session : Pointer to pe session + * + * This function is called to verify if the RSN IE received in various + * SME_REQ messages is valid or not. RSN IE validity checks are performed in + * this function + * + * Return: true when RSN IE is valid, false otherwise + */ +uint8_t +lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(tpAniSirGlobal mac_ctx, + tpSirRSNie rsn_ie, + tpPESession session) +{ + uint8_t wpa_idx = 0; + uint32_t privacy, val; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_PRIVACY_ENABLED, + &privacy) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, FL("Unable to retrieve POI from CFG")); + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RSN_ENABLED, + &val) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Unable to retrieve RSN_ENABLED from CFG")); + + if (rsn_ie->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 + */ + lim_log(mac_ctx, LOG1, + FL("RSN ie len %d but PRIVACY %d RSN %d"), + rsn_ie->length, privacy, val); + } + + if (!rsn_ie->length) + return true; + + if ((rsn_ie->rsnIEdata[0] != SIR_MAC_RSN_EID) && + (rsn_ie->rsnIEdata[0] != SIR_MAC_WPA_EID)) { + lim_log(mac_ctx, LOGE, FL("RSN/WPA EID %d not [%d || %d]"), + rsn_ie->rsnIEdata[0], SIR_MAC_RSN_EID, + SIR_MAC_WPA_EID); + return false; + } + /* Check validity of RSN IE */ + if ((rsn_ie->rsnIEdata[0] == SIR_MAC_RSN_EID) && + (rsn_ie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) { + lim_log(mac_ctx, LOGE, FL("RSN IE len %d not [%d,%d]"), + rsn_ie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, + SIR_MAC_RSN_IE_MAX_LENGTH); + return false; + } + + if (rsn_ie->length > rsn_ie->rsnIEdata[1] + 2) { + if (rsn_ie->rsnIEdata[0] != SIR_MAC_RSN_EID) { + lim_log(mac_ctx, LOGE, + FL("First byte[%d] in rsnIEdata isn't RSN_EID"), + rsn_ie->rsnIEdata[1]); + return false; + } + lim_log(mac_ctx, LOG1, + FL("WPA IE is present along with WPA2 IE")); + wpa_idx = 2 + rsn_ie->rsnIEdata[1]; + } else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2) && + (rsn_ie->rsnIEdata[0] == SIR_MAC_RSN_EID)) { + lim_log(mac_ctx, LOG1, FL("Only RSN IE is present")); + dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2], + (uint8_t) rsn_ie->length, + &session->gStartBssRSNIe); + } else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2) + && (rsn_ie->rsnIEdata[0] == SIR_MAC_WPA_EID)) { + lim_log(mac_ctx, LOG1, FL("Only WPA IE is present")); + dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[6], + (uint8_t) rsn_ie->length - 4, + &session->gStartBssWPAIe); + } + /* Check validity of WPA IE */ + if (wpa_idx + 6 >= SIR_MAC_MAX_IE_LENGTH) + return false; + + val = sir_read_u32((uint8_t *)&rsn_ie->rsnIEdata[wpa_idx + 2]); + if ((rsn_ie->rsnIEdata[wpa_idx] == SIR_MAC_WPA_EID) + && ((rsn_ie->rsnIEdata[wpa_idx + 1] < SIR_MAC_WPA_IE_MIN_LENGTH) + || (SIR_MAC_WPA_OUI != val))) { + lim_log(mac_ctx, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + rsn_ie->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 */ + dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2], + (uint8_t) rsn_ie->length, + &session->gStartBssRSNIe); + dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[wpa_idx + 6], + rsn_ie->rsnIEdata[wpa_idx + 1] - 4, + &session->gStartBssWPAIe); + } + return true; +} + +/** + * lim_is_bss_descr_valid_in_sme_req_message() + * + ***FUNCTION: + * This function is called to verify if the BSS Descr + * received in various SME_REQ messages is valid or not + * + ***LOGIC: + * BSS Descritipion validity checks are performed in this function + * + ***ASSUMPTIONS: + * + ***NOTE: + * + * @param pMac Pointer to Global MAC structure + * @param pBssDescr Pointer to received Bss Descritipion + * @return true when BSS description is valid, false otherwise + */ + +static uint8_t +lim_is_bss_descr_valid_in_sme_req_message(tpAniSirGlobal pMac, + tpSirBssDescription pBssDescr) +{ + uint8_t valid = true; + + if (lim_is_addr_bc(pBssDescr->bssId) || !pBssDescr->channelId) { + valid = false; + goto end; + } + +end: + return valid; +} /*** end lim_is_bss_descr_valid_in_sme_req_message() ***/ + +/** + * lim_is_sme_start_bss_req_valid() - To validate sme start bss request + * + * @mac_ctx: Pointer to Global MAC structure + * @start_bss_req: Pointer to received SME_START_BSS_REQ message + * + * This function is called by lim_process_sme_req_messages() upon + * receiving SME_START_BSS_REQ message from application. + * + * Return: true when received SME_START_BSS_REQ is formatted correctly false + * otherwise + */ + +uint8_t +lim_is_sme_start_bss_req_valid(tpAniSirGlobal mac_ctx, + tpSirSmeStartBssReq start_bss_req) +{ + uint8_t i = 0; + tSirMacRateSet *opr_rates = &start_bss_req->operationalRateSet; + + PELOG1(lim_log(mac_ctx, LOG1, + FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), + start_bss_req->bssType, start_bss_req->channelId, + start_bss_req->ssId.length, start_bss_req->rsnIE.length, + start_bss_req->nwType, opr_rates->numRates);) + + switch (start_bss_req->bssType) { + case eSIR_INFRASTRUCTURE_MODE: + /** + * Should not have received start BSS req with bssType + * Infrastructure on STA. + */ + lim_log(mac_ctx, LOGE, + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), + start_bss_req->bssType); + return false; + break; + case eSIR_IBSS_MODE: + break; + case eSIR_BTAMP_STA_MODE: + break; + case eSIR_BTAMP_AP_MODE: + break; + case eSIR_INFRA_AP_MODE: + break; + default: + /** + * Should not have received start BSS req with bssType + * other than Infrastructure/IBSS. + */ + lim_log(mac_ctx, LOGW, + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), + start_bss_req->bssType); + return false; + } + + if (start_bss_req->bssType == eSIR_IBSS_MODE + && (!start_bss_req->ssId.length + || start_bss_req->ssId.length > SIR_MAC_MAX_SSID_LENGTH)) { + lim_log(mac_ctx, LOGW, + FL("Invalid SSID length in eWNI_SME_START_BSS_REQ")); + return false; + } + + if (!lim_is_rsn_ie_valid_in_sme_req_message(mac_ctx, + &start_bss_req->rsnIE)) + return false; + + if (start_bss_req->nwType != eSIR_11A_NW_TYPE + && start_bss_req->nwType != eSIR_11B_NW_TYPE + && start_bss_req->nwType != eSIR_11G_NW_TYPE) + return false; + + if (start_bss_req->nwType == eSIR_11A_NW_TYPE) { + for (i = 0; i < opr_rates->numRates; i++) { + if (sirIsArate(opr_rates->rate[i] & 0x7F)) + continue; + + lim_log(mac_ctx, LOGW, + FL("Invalid operational 11A rates")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, + opr_rates->rate, opr_rates->numRates); + return false; + } + return true; + } + /* check if all the rates in the opr rate set are legal 11G rates */ + if (start_bss_req->nwType == eSIR_11G_NW_TYPE) { + for (i = 0; i < opr_rates->numRates; i++) { + if (sirIsGrate(opr_rates->rate[i] & 0x7F)) + continue; + + lim_log(mac_ctx, LOGW, + FL("Invalid operational 11G rates")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, + opr_rates->rate, opr_rates->numRates); + return false; + } + return true; + } + + for (i = 0; i < opr_rates->numRates; i++) { + if (sirIsBrate(opr_rates->rate[i] & 0x7F)) + continue; + + lim_log(mac_ctx, LOGW, + FL("Invalid operational 11B rates")); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, + opr_rates->rate, opr_rates->numRates); + return false; + } + return true; +} + +/** + * lim_is_sme_join_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t lim_is_sme_join_req_valid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) +{ + uint8_t valid = true; + + if (!lim_is_rsn_ie_valid_in_sme_req_message(pMac, &pJoinReq->rsnIE)) { + lim_log(pMac, LOGE, + FL("received SME_JOIN_REQ with invalid RSNIE")); + valid = false; + goto end; + } + + if (!lim_is_addie_valid_in_sme_req_message(pMac, &pJoinReq->addIEScan)) { + lim_log(pMac, LOGE, + FL + ("received SME_JOIN_REQ with invalid additional IE for scan")); + valid = false; + goto end; + } + + if (!lim_is_addie_valid_in_sme_req_message(pMac, &pJoinReq->addIEAssoc)) { + lim_log(pMac, LOGE, + FL + ("received SME_JOIN_REQ with invalid additional IE for assoc")); + valid = false; + goto end; + } + + if (!lim_is_bss_descr_valid_in_sme_req_message(pMac, &pJoinReq->bssDescription)) { + /* / Received eWNI_SME_JOIN_REQ with invalid BSS Info */ + /* Log the event */ + lim_log(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 (cdf_mem_compare((uint8_t *) pJoinReq->selfMacAddr, + (uint8_t *) pJoinReq->bssDescription.bssId, + (uint8_t) (sizeof(tSirMacAddr)))) { + /* Log the event */ + lim_log(pMac, LOGE, + FL + ("received SME_JOIN_REQ with Self Mac and BSSID Same")); + + valid = false; + goto end; + } + +end: + return valid; +} /*** end lim_is_sme_join_req_valid() ***/ + +/** + * lim_is_sme_disassoc_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t +lim_is_sme_disassoc_req_valid(tpAniSirGlobal pMac, + tpSirSmeDisassocReq pDisassocReq, + tpPESession psessionEntry) +{ + if (lim_is_group_addr(pDisassocReq->peerMacAddr) && + !lim_is_addr_bc(pDisassocReq->peerMacAddr)) + return false; + + return true; +} /*** end lim_is_sme_disassoc_req_valid() ***/ + +/** + * lim_is_sme_disassoc_cnf_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t +lim_is_sme_disassoc_cnf_valid(tpAniSirGlobal pMac, + tpSirSmeDisassocCnf pDisassocCnf, + tpPESession psessionEntry) +{ + if (lim_is_group_addr(pDisassocCnf->peerMacAddr)) + return false; + + return true; +} /*** end lim_is_sme_disassoc_cnf_valid() ***/ + +/** + * lim_is_sme_deauth_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t +lim_is_sme_deauth_req_valid(tpAniSirGlobal pMac, tpSirSmeDeauthReq pDeauthReq, + tpPESession psessionEntry) +{ + if (lim_is_group_addr(pDeauthReq->peerMacAddr) && + !lim_is_addr_bc(pDeauthReq->peerMacAddr)) + return false; + + return true; +} /*** end lim_is_sme_deauth_req_valid() ***/ + +/** + * lim_is_sme_scan_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t lim_is_sme_scan_req_valid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq) +{ + uint8_t valid = true; + uint8_t i = 0; + + if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) { + valid = false; + lim_log(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) { + lim_log(pMac, LOGE, + FL + ("Requested SSID length > SIR_MAC_MAX_SSID_LENGTH")); + valid = false; + goto end; + } + } + if ((pScanReq->bssType < 0) || (pScanReq->bssType > eSIR_AUTO_MODE)) { + lim_log(pMac, LOGE, FL("Invalid BSS Type")); + valid = false; + } + if (lim_is_group_addr(pScanReq->bssId) && !lim_is_addr_bc(pScanReq->bssId)) { + valid = false; + lim_log(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; + lim_log(pMac, LOGE, FL("Invalid Scan Type")); + } + if (pScanReq->channelList.numChannels > SIR_MAX_NUM_CHANNELS) { + valid = false; + lim_log(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)) { + lim_log(pMac, LOGE, + FL("Max Channel Time < Min Channel Time")); + valid = false; + goto end; + } + } + +end: + return valid; +} /*** end lim_is_sme_scan_req_valid() ***/ + +/** + * lim_is_sme_set_context_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t +lim_is_sme_set_context_req_valid(tpAniSirGlobal pMac, + tpSirSmeSetContextReq pSetContextReq) +{ + uint8_t i = 0; + uint8_t 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. + */ + lim_log(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. + */ + lim_log(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. + */ + lim_log(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) { + uint32_t poi; + + if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, + &poi) != eSIR_SUCCESS) { + lim_log(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(lim_log(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. + */ + lim_log(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 lim_is_sme_set_context_req_valid() ***/ + +/** + * lim_is_sme_stop_bss_req_valid() + * + ***FUNCTION: + * This function is called by lim_process_sme_req_messages() 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 + */ + +uint8_t lim_is_sme_stop_bss_req_valid(uint32_t *pMsg) +{ + uint8_t valid = true; + + return valid; +} /*** end lim_is_sme_stop_bss_req_valid() ***/ + +/** + * lim_get_bss_id_from_sme_join_req_msg() + * + ***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 + */ + +uint8_t *lim_get_bss_id_from_sme_join_req_msg(uint8_t *pBuf) +{ + if (!pBuf) + return NULL; + + pBuf += sizeof(uint32_t); /* skip message header */ + + pBuf += lim_get_u16(pBuf) + sizeof(uint16_t); /* skip RSN IE */ + + pBuf += sizeof(uint16_t); /* skip length of BSS description */ + + return (pBuf); +} /*** end lim_get_bss_id_from_sme_join_req_msg() ***/ diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.h b/core/mac/src/pe/lim/lim_sme_req_utils.h new file mode 100644 index 000000000000..7e89373ad2e1 --- /dev/null +++ b/core/mac/src/pe/lim/lim_sme_req_utils.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/* + * + * This file lim_sme_req_utils.h contains the utility definitions + * LIM uses while processing SME request messsages. + * 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 "sir_api.h" +#include "lim_types.h" + +/* LIM SME request messages related utility functions */ +uint8_t lim_is_sme_start_bss_req_valid(tpAniSirGlobal, tpSirSmeStartBssReq); +uint8_t lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(tpAniSirGlobal, + tpSirRSNie, tpPESession); +uint8_t lim_is_sme_scan_req_valid(tpAniSirGlobal, tpSirSmeScanReq); +uint8_t lim_is_sme_join_req_valid(tpAniSirGlobal, tpSirSmeJoinReq); +uint8_t lim_is_sme_disassoc_req_valid(tpAniSirGlobal, tpSirSmeDisassocReq, + tpPESession); +uint8_t lim_is_sme_deauth_req_valid(tpAniSirGlobal, tpSirSmeDeauthReq, tpPESession); +uint8_t lim_is_sme_set_context_req_valid(tpAniSirGlobal, tpSirSmeSetContextReq); +uint8_t lim_is_sme_stop_bss_req_valid(uint32_t *); +uint8_t *lim_get_bss_id_from_sme_join_req_msg(uint8_t *); +uint8_t lim_is_sme_disassoc_cnf_valid(tpAniSirGlobal, tpSirSmeDisassocCnf, + tpPESession); + +#endif /* __LIM_SME_REQ_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_sta_hash_api.c b/core/mac/src/pe/lim/lim_sta_hash_api.c new file mode 100644 index 000000000000..794ebaad073e --- /dev/null +++ b/core/mac/src/pe/lim/lim_sta_hash_api.c @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/* + * + * lim_sta_hash_api.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 "lim_sta_hash_api.h" + +/** + * lim_get_sta_hash_bssidx() + * + ***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 lim_get_sta_hash_bssidx(tpAniSirGlobal pMac, uint16_t assocId, + uint8_t *bssidx, tpPESession psessionEntry) +{ + tpDphHashNode pSta = + dph_get_hash_entry(pMac, assocId, &psessionEntry->dph.dphHashTable); + + if (pSta == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("invalid STA %d"), assocId);) + return eSIR_LIM_INVALID_STA; + } + + *bssidx = (uint8_t) pSta->bssId; + return eSIR_SUCCESS; +} diff --git a/core/mac/src/pe/lim/lim_sta_hash_api.h b/core/mac/src/pe/lim/lim_sta_hash_api.h new file mode 100644 index 000000000000..9a34091ad39d --- /dev/null +++ b/core/mac/src/pe/lim/lim_sta_hash_api.h @@ -0,0 +1,50 @@ +/* + * 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 lim_sta_hash_api.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 "ani_global.h" +#include "lim_types.h" + +tSirRetStatus lim_get_sta_hash_bssidx(tpAniSirGlobal pMac, uint16_t assocId, + uint8_t *bssidx, tpPESession psessionEntry); + +#endif diff --git a/core/mac/src/pe/lim/lim_timer_utils.c b/core/mac/src/pe/lim/lim_timer_utils.c new file mode 100644 index 000000000000..f68f7b08bbf6 --- /dev/null +++ b/core/mac/src/pe/lim/lim_timer_utils.c @@ -0,0 +1,1357 @@ +/* + * 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 lim_timer_utils.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 "lim_types.h" +#include "lim_utils.h" +#include "lim_assoc_utils.h" +#include "lim_security_utils.h" + +/* 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 + +/* 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 + +static bool +lim_create_non_ap_timers(tpAniSirGlobal pMac) +{ + uint32_t cfgValue; + /* Create Channel Switch Timer */ + if (tx_timer_create(&pMac->lim.limTimers.gLimChannelSwitchTimer, + "CHANNEL SWITCH TIMER", + lim_channel_switch_timer_handler, 0, + LIM_CHANNEL_SWITCH_TIMER_TICKS, + 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("failed to create Ch Switch timer")); + return false; + } + /* 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", lim_quiet_timer_handler, + SIR_LIM_QUIET_TIMEOUT, LIM_QUIET_TIMER_TICKS, + 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("failed to create Quiet Begin Timer")); + return false; + } + /* 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", lim_quiet_bss_timer_handler, + SIR_LIM_QUIET_BSS_TIMEOUT, LIM_QUIET_BSS_TIMER_TICK, + 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("failed to create Quiet Bss Timer")); + return false; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", + lim_timer_handler, SIR_LIM_JOIN_FAIL_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) { + /* / Could not create Join failure timer. */ + /* Log error */ + lim_log(pMac, LOGP, + FL("could not create Join failure timer")); + return false; + } + /* Send unicast probe req frame every 200 ms */ + if (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, + "Periodic Join Probe Request Timer", + lim_timer_handler, + SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT, + SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS), 0, + TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not create Periodic Join Probe Request tmr")); + return false; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", + lim_assoc_failure_timer_handler, LIM_ASSOC, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not create Association failure timer")); + return false; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", lim_assoc_failure_timer_handler, + LIM_REASSOC, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not create Reassociation failure timer")); + return false; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &cfgValue) + != eSIR_SUCCESS) + lim_log(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", + lim_addts_response_timer_handler, + SIR_LIM_ADDTS_RSP_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not create Addts response timer")); + return false; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", + lim_timer_handler, + SIR_LIM_AUTH_FAIL_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("could not create Auth failure timer")); + return false; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", + lim_timer_handler, + SIR_LIM_PROBE_HB_FAILURE_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("unable to create ProbeAfterHBTimer")); + return false; + } + + return true; +} +/** + * lim_create_timers() + * + * @pMac : Pointer to Global MAC structure + * + * 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 + * + * @return : status of operation + */ + +uint32_t lim_create_timers(tpAniSirGlobal pMac) +{ + uint32_t cfgValue, i = 0; + uint32_t cfgValue1; + + PELOG1(lim_log(pMac, LOG1, + FL("Creating Timers used by LIM module in Role %d"), + pMac->lim.gLimSystemRole);) + + if (wlan_cfg_get_int(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + &cfgValue) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not retrieve MinChannelTimeout value")); + } + cfgValue = SYS_MS_TO_TICKS(cfgValue); + /* 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; + /* Create periodic probe request timer and activate them later */ + if (cfgValue1 >= 1 + && (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, + "Periodic Probe Request Timer", lim_timer_handler, + SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT, cfgValue1, 0, + TX_NO_ACTIVATE) != TX_SUCCESS)) { + lim_log(pMac, LOGP, + FL("could not create periodic probe timer")); + goto err_timer; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + &cfgValue) != eSIR_SUCCESS) + lim_log(pMac, LOGP, + FL("could not retrieve MAXChannelTimeout value")); + + cfgValue = SYS_MS_TO_TICKS(cfgValue); + /* Limiting max numm of probe req for each channel scan */ + pMac->lim.maxProbe = (cfgValue / cfgValue1); + + if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE) + if (false == lim_create_non_ap_timers(pMac)) + goto err_timer; + + cfgValue = SYS_MS_TO_TICKS(LIM_HASH_MISS_TIMER_MS); + + if (tx_timer_create( + &pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer, + "Disassoc throttle TIMEOUT", + lim_send_disassoc_frame_threshold_handler, + SIR_LIM_HASH_MISS_THRES_TIMEOUT, cfgValue, cfgValue, + TX_AUTO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("create Disassociate throttle timer failed")); + goto err_timer; + } + PELOG1(lim_log(pMac, LOG1, FL("Created Disassociate throttle timer "));) + + /* Create all CNF_WAIT Timers upfront */ + if (wlan_cfg_get_int(pMac, WNI_CFG_WT_CNF_TIMEOUT, &cfgValue) + != eSIR_SUCCESS) { + lim_log(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", + lim_cnf_wait_tmer_handler, + (uint32_t) i, cfgValue, + 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("Cannot create CNF wait timer")); + goto err_timer; + } + } + + /* Alloc and init table for the preAuth timer list */ + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, + &cfgValue) != eSIR_SUCCESS) + lim_log(pMac, LOGP, FL("could not retrieve mac preauth value")); + pMac->lim.gLimPreAuthTimerTable.numEntry = cfgValue; + pMac->lim.gLimPreAuthTimerTable.pTable = + cdf_mem_malloc(cfgValue * sizeof(tLimPreAuthNode)); + + if (pMac->lim.gLimPreAuthTimerTable.pTable == NULL) { + lim_log(pMac, LOGP, FL("AllocateMemory failed!")); + goto err_timer; + } + + lim_init_pre_auth_timer_table(pMac, &pMac->lim.gLimPreAuthTimerTable); + PELOG1(lim_log(pMac, LOG1, + FL("alloc and init table for preAuth timers"));) + + if (wlan_cfg_get_int(pMac, WNI_CFG_OLBC_DETECT_TIMEOUT, + &cfgValue) != eSIR_SUCCESS) + lim_log(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", + lim_update_olbc_cache_timer_handler, + SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT, cfgValue, + cfgValue, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("Cannot create update OLBC cache tmr")); + 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", + lim_timer_handler, SIR_LIM_FT_PREAUTH_RSP_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, FL("could not create Join failure timer")); + goto err_timer; + } +#endif + cfgValue = 1000; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create(&pMac->lim.limTimers.gLimRemainOnChannelTimer, + "FT PREAUTH RSP TIMEOUT", + lim_timer_handler, SIR_LIM_REMAIN_CHN_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(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", + lim_timer_handler, SIR_LIM_DISASSOC_ACK_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(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", + lim_timer_handler, SIR_LIM_DEAUTH_ACK_TIMEOUT, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("could not create DEAUTH ACK TIMEOUT timer")); + goto err_timer; + } + + /* (> 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 = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + if (tx_timer_create( + &pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer, + "Single Shot NOA Insert timeout", lim_timer_handler, + SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT, cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(pMac, LOGP, + FL("Can't create Single Shot NOA Insert Timeout tmr")); + 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", lim_timer_handler, + SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) { + lim_log(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); + tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer); + while (((int32_t)-- i) >= 0) { + tx_timer_delete(&pMac->lim.limTimers.gpLimCnfWaitTimer[i]); + } + tx_timer_delete(&pMac->lim.limTimers. + gLimSendDisassocFrameThresholdTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimProbeAfterHBTimer); + 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.gLimQuietBssTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimQuietTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimChannelSwitchTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer); + tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + + if (NULL != pMac->lim.gLimPreAuthTimerTable.pTable) { + cdf_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable); + pMac->lim.gLimPreAuthTimerTable.pTable = NULL; + } + return TX_TIMER_ERROR; +} /****** end lim_create_timers() ******/ + +/** + * lim_timer_handler() + * + ***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 cleanup and Link monitoring timer + * expiration on AP + * + ***LOGIC: + * + ***ASSUMPTIONS: + * NA + * + ***NOTE: + * NA + * + * @param param - Message corresponding to the timer that expired + * + * @return None + */ + +void lim_timer_handler(void *pMacGlobal, uint32_t param) +{ + uint32_t statusCode; + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + /* Prepare and post message to LIM Message Queue */ + + msg.type = (uint16_t) param; + msg.bodyptr = NULL; + msg.bodyval = 0; + + if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS) + lim_log(pMac, LOGE, + FL("posting message %X to LIM failed, reason=%d"), + msg.type, statusCode); +} /****** end lim_timer_handler() ******/ + +/** + * lim_addts_response_timer_handler() + * + ***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 lim_addts_response_timer_handler(void *pMacGlobal, uint32_t 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; + + lim_post_msg_api(pMac, &msg); +} /****** end lim_auth_response_timer_handler() ******/ + +/** + * lim_auth_response_timer_handler() + * + ***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 lim_auth_response_timer_handler(void *pMacGlobal, uint32_t 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 = (uint32_t) param; + + lim_post_msg_api(pMac, &msg); +} /****** end lim_auth_response_timer_handler() ******/ + +/** + * lim_assoc_failure_timer_handler() + * + * @mac_global : Pointer to Global MAC structure + * @param : Indicates whether this is assoc or reassoc failure timeout + * + * This function is called upon Re/Assoc failure timer expiration on STA. + * Message SIR_LIM_ASSOC_FAIL_TIMEOUT is posted to gSirLimMsgQ when this + * function is executed. + * + * Return void + */ +void lim_assoc_failure_timer_handler(void *mac_global, uint32_t param) +{ + tSirMsgQ msg; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal) mac_global; + tpPESession session = NULL; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + session = mac_ctx->lim.pSessionEntry; + if (LIM_REASSOC == param && NULL != session + && session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE) { + lim_log(mac_ctx, LOGE, FL("Reassoc timeout happened")); + if (mac_ctx->lim.reAssocRetryAttempt < + LIM_MAX_REASSOC_RETRY_LIMIT) { + lim_send_retry_reassoc_req_frame(mac_ctx, + session->pLimMlmReassocRetryReq, session); + mac_ctx->lim.reAssocRetryAttempt++; + lim_log(mac_ctx, LOGW, + FL("Reassoc request retry is sent %d times"), + mac_ctx->lim.reAssocRetryAttempt); + return; + } else { + lim_log(mac_ctx, LOGW, + FL("Reassoc request retry MAX(%d) reached"), + LIM_MAX_REASSOC_RETRY_LIMIT); + if (NULL != session->pLimMlmReassocRetryReq) { + cdf_mem_free(session->pLimMlmReassocRetryReq); + session->pLimMlmReassocRetryReq = NULL; + } + } + } +#endif + /* Prepare and post message to LIM Message Queue */ + msg.type = SIR_LIM_ASSOC_FAIL_TIMEOUT; + msg.bodyval = (uint32_t) param; + msg.bodyptr = NULL; + lim_post_msg_api(mac_ctx, &msg); +} /****** end lim_assoc_failure_timer_handler() ******/ + +/** + * lim_update_olbc_cache_timer_handler() + * + ***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 lim_update_olbc_cache_timer_handler(void *pMacGlobal, uint32_t 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; + + lim_post_msg_api(pMac, &msg); +} /****** end lim_update_olbc_cache_timer_handler() ******/ + +/** + * lim_deactivate_and_change_timer() + * + ***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 lim_utils.h file + * + * @return None + */ + +void lim_deactivate_and_change_timer(tpAniSirGlobal pMac, uint32_t timerId) +{ + uint32_t val = 0; + + MTRACE(mac_trace + (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 */ + lim_log(pMac, LOGP, + FL("Unable to deactivate AddtsRsp 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 */ + lim_log(pMac, LOGP, + FL("Unable to deactivate periodic timer")); + } + + val = + SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime) / + 2; + if (tx_timer_change + (&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, val, + 0) != TX_SUCCESS) { + /* Could not change min channel timer. */ + /* Log error */ + lim_log(pMac, LOGP, + FL("Unable to change periodic 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. + */ + lim_log(pMac, LOGP, + FL("Unable to deactivate Join Failure timer")); + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get JoinFailureTimeout value + * from CFG. Log error. + */ + lim_log(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. + */ + lim_log(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. */ + lim_log(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 */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL("Unable to deactivate auth failure timer")); + } + /* Change timer to reactivate it in future */ + if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get AuthFailureTimeout value + * from CFG. Log error. + */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL("unable to change Auth failure 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 */ + lim_log(pMac, LOGP, + FL + ("unable to deactivate Association failure timer")); + } + /* Change timer to reactivate it in future */ + if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get AssocFailureTimeout value + * from CFG. Log error. + */ + lim_log(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 */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL + ("unable to deactivate Reassoc failure timer")); + } + /* Change timer to reactivate it in future */ + if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get ReassocFailureTimeout value + * from CFG. Log error. + */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL + ("unable to change Reassociation failure timer")); + } + + break; + + case eLIM_PROBE_AFTER_HB_TIMER: + if (tx_timer_deactivate + (&pMac->lim.limTimers.gLimProbeAfterHBTimer) != + TX_SUCCESS) { + /* Could not deactivate Heartbeat timer. */ + /* Log error */ + lim_log(pMac, LOGP, + FL("unable to deactivate probeAfterHBTimer")); + } else { + lim_log(pMac, LOG1, + FL("Deactivated probe after hb timer")); + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get PROBE_AFTER_HB_FAILURE + * value from CFG. Log error. + */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL("unable to change ProbeAfterHBTimer")); + } else { + lim_log(pMac, LOGW, + FL("Probe after HB timer value is changed = %u"), + val); + } + + 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. + **/ + lim_log(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. + */ + lim_log(pMac, LOGP, + FL("Unable to change Join Failure timer")); + return; + } + break; +#endif + case eLIM_REMAIN_CHN_TIMER: + if (tx_timer_deactivate + (&pMac->lim.limTimers.gLimRemainOnChannelTimer) != + TX_SUCCESS) { + /** + ** Could not deactivate Join Failure + ** timer. Log error. + **/ + lim_log(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. + */ + lim_log(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. + **/ + lim_log(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. + */ + lim_log(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. + **/ + lim_log(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. + */ + lim_log(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. + **/ + lim_log(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. + */ + lim_log(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. + **/ + lim_log(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. + */ + lim_log(pMac, LOGP, FL("Unable to change timer")); + return; + } + break; + + default: + /* Invalid timerId. Log error */ + break; + } +} /****** end lim_deactivate_and_change_timer() ******/ + +/** + * lim_deactivate_and_change_per_sta_id_timer() + * + * + * @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 lim_utils.h file + * @param staId - staId + * + * @return None + */ + +void +lim_deactivate_and_change_per_sta_id_timer(tpAniSirGlobal pMac, uint32_t timerId, + uint16_t staId) +{ + uint32_t val; + MTRACE(mac_trace + (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) { + lim_log(pMac, LOGP, + FL("unable to deactivate CNF wait timer")); + + } + /* Change timer to reactivate it in future */ + + if (wlan_cfg_get_int(pMac, WNI_CFG_WT_CNF_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get cnf timeout value + * from CFG. Log error. + */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL("unable to change cnf wait timer")); + } + + break; + + case eLIM_AUTH_RSP_TIMER: + { + tLimPreAuthNode *pAuthNode; + + pAuthNode = + lim_get_pre_auth_node_from_index(pMac, + &pMac->lim. + gLimPreAuthTimerTable, + staId); + + if (pAuthNode == NULL) { + lim_log(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 */ + lim_log(pMac, LOGP, + FL + ("unable to deactivate auth response timer")); + } + /* Change timer to reactivate it in future */ + + if (wlan_cfg_get_int + (pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT, + &val) != eSIR_SUCCESS) { + /** + * Could not get auth rsp timeout value + * from CFG. Log error. + */ + lim_log(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 */ + lim_log(pMac, LOGP, + FL("unable to change auth rsp timer")); + } + } + break; + + default: + /* Invalid timerId. Log error */ + break; + + } +} + +/** + * lim_activate_cnf_timer() + * + ***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 lim_activate_cnf_timer(tpAniSirGlobal pMac, uint16_t staId, + tpPESession psessionEntry) +{ + MTRACE(mac_trace + (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) { + lim_log(pMac, LOGP, FL("could not activate cnf wait timer")); + } +} + +/** + * lim_activate_auth_rsp_timer() + * + ***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 lim_activate_auth_rsp_timer(tpAniSirGlobal pMac, tLimPreAuthNode *pAuthNode) +{ + MTRACE(mac_trace + (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 */ + lim_log(pMac, LOGP, FL("could not activate auth rsp timer")); + } +} + +/** + * lim_send_disassoc_frame_threshold_handler() + * + ***FUNCTION: + * This function reloads the credit to the send disassociate frame bucket + * + ***LOGIC: + * + ***ASSUMPTIONS: + * + ***NOTE: + * NA + * + * @param + * + * @return None + */ + +void lim_send_disassoc_frame_threshold_handler(void *pMacGlobal, uint32_t param) +{ + tSirMsgQ msg; + uint32_t statusCode; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + msg.type = SIR_LIM_HASH_MISS_THRES_TIMEOUT; + msg.bodyval = 0; + msg.bodyptr = NULL; + + if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS) + lim_log(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 lim_cnf_wait_tmer_handler(void *pMacGlobal, uint32_t param) +{ + tSirMsgQ msg; + uint32_t statusCode; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + msg.type = SIR_LIM_CNF_WAIT_TIMEOUT; + msg.bodyval = (uint32_t) param; + msg.bodyptr = NULL; + + if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS) + lim_log(pMac, LOGE, + FL("posting to LIM failed, reason=%d"), statusCode); + +} + +void lim_channel_switch_timer_handler(void *pMacGlobal, uint32_t param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + PELOG1(lim_log(pMac, LOG1, + FL("ChannelSwitch Timer expired. Posting msg to LIM ")); + ) + + msg.type = SIR_LIM_CHANNEL_SWITCH_TIMEOUT; + msg.bodyval = (uint32_t) param; + msg.bodyptr = NULL; + + lim_post_msg_api(pMac, &msg); +} + +void lim_quiet_timer_handler(void *pMacGlobal, uint32_t param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + msg.type = SIR_LIM_QUIET_TIMEOUT; + msg.bodyval = (uint32_t) param; + msg.bodyptr = NULL; + + PELOG1(lim_log(pMac, LOG1, FL("Post SIR_LIM_QUIET_TIMEOUT msg. "));) + lim_post_msg_api(pMac, &msg); +} + +void lim_quiet_bss_timer_handler(void *pMacGlobal, uint32_t param) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + + msg.type = SIR_LIM_QUIET_BSS_TIMEOUT; + msg.bodyval = (uint32_t) param; + msg.bodyptr = NULL; + PELOG1(lim_log(pMac, LOG1, FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. "));) + lim_post_msg_api(pMac, &msg); +} + diff --git a/core/mac/src/pe/lim/lim_timer_utils.h b/core/mac/src/pe/lim/lim_timer_utils.h new file mode 100644 index 000000000000..b133d712f9e0 --- /dev/null +++ b/core/mac/src/pe/lim/lim_timer_utils.h @@ -0,0 +1,102 @@ +/* + * 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 lim_timer_utils.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 "lim_types.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_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 +}; + +#define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT 500 +#define LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE 500 + +/* Timer Handler functions */ +uint32_t lim_create_timers(tpAniSirGlobal); +void lim_timer_handler(void *, uint32_t); +void lim_auth_response_timer_handler(void *, uint32_t); +void lim_assoc_failure_timer_handler(void *, uint32_t); +void limReassocFailureTimerHandler(void *, uint32_t); + +void lim_deactivate_and_change_timer(tpAniSirGlobal, uint32_t); +void limDummyPktExpTimerHandler(void *, uint32_t); +void lim_send_disassoc_frame_threshold_handler(void *, uint32_t); +void lim_cnf_wait_tmer_handler(void *, uint32_t); +void lim_deactivate_and_change_per_sta_id_timer(tpAniSirGlobal, uint32_t, uint16_t); +void lim_activate_cnf_timer(tpAniSirGlobal, uint16_t, tpPESession); +void lim_activate_auth_rsp_timer(tpAniSirGlobal, tLimPreAuthNode *); +void lim_update_olbc_cache_timer_handler(void *, uint32_t); +void lim_addts_response_timer_handler(void *, uint32_t); +void lim_channel_switch_timer_handler(void *, uint32_t); +void lim_quiet_timer_handler(void *, uint32_t); +void lim_quiet_bss_timer_handler(void *, uint32_t); +void limCBScanIntervalTimerHandler(void *, uint32_t); +void limCBScanDurationTimerHandler(void *, uint32_t); +#endif /* __LIM_TIMER_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_trace.c b/core/mac/src/pe/lim/lim_trace.c new file mode 100644 index 000000000000..3847127120e5 --- /dev/null +++ b/core/mac/src/pe/lim/lim_trace.c @@ -0,0 +1,483 @@ +/* + * 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 lim_trace.c + + \brief implementation for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "ani_global.h" /* for tpAniSirGlobal */ + +#include "lim_trace.h" +#include "lim_timer_utils.h" +#include "cdf_trace.h" + +#ifdef LIM_TRACE_RECORD +uint32_t g_mgmt_frame_stats[14]; + +#define LIM_TRACE_MAX_SUBTYPES 14 + +static uint8_t *__lim_trace_get_timer_string(uint16_t 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_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); + default: + return ("UNKNOWN"); + break; + } +} + +static uint8_t *__lim_trace_get_mgmt_drop_reason_string(uint16_t 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 lim_trace_init(tpAniSirGlobal pMac) +{ + cdf_trace_register(CDF_MODULE_ID_PE, (tp_cdf_trace_cb) & lim_trace_dump); +} + +void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, + uint16_t 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: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "MLM State:", + lim_trace_get_mlm_state_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_SME_STATE: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "SME State:", + lim_trace_get_sme_state_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_TX_MGMT: + lim_log(pMac, LOGE, + "%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)) { + lim_log(pMac, LOGE, "Wrong Subtype - %d", + LIM_TRACE_GET_SUBTYPE(pRecord->data)); + } else { + lim_log(pMac, LOGE, + "%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: + lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(%d) ", + recIndex, pRecord->time, pRecord->session, + "Drop RX Mgmt:", + __lim_trace_get_mgmt_drop_reason_string((uint16_t) pRecord-> + data), pRecord->data); + break; + + case TRACE_CODE_RX_MGMT_TSF: + lim_log(pMac, LOGE, + "%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: + lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %d ", recIndex, + pRecord->time, pRecord->session, "TX Complete", + pRecord->data); + break; + + case TRACE_CODE_TX_SME_MSG: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "TX SME Msg:", + mac_trace_get_sme_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_RX_SME_MSG: + lim_log(pMac, LOGE, + "%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:", + mac_trace_get_sme_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + + case TRACE_CODE_TX_WMA_MSG: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "TX WMA Msg:", + mac_trace_get_wma_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + + case TRACE_CODE_RX_WMA_MSG: + lim_log(pMac, LOGE, + "%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 WMA Msg:", + mac_trace_get_wma_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + + case TRACE_CODE_TX_LIM_MSG: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "TX LIM Msg:", + mac_trace_get_lim_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_RX_LIM_MSG: + lim_log(pMac, LOGE, + "%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", + mac_trace_get_lim_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_TX_CFG_MSG: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "TX CFG Msg:", + mac_trace_get_cfg_msg_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_RX_CFG_MSG: + lim_log(pMac, LOGE, + "%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:", + mac_trace_get_cfg_msg_string((uint16_t) + MAC_TRACE_GET_MSG_ID(pRecord-> + data)), + pRecord->data); + break; + + case TRACE_CODE_TIMER_ACTIVATE: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "Timer Actvtd", + __lim_trace_get_timer_string((uint16_t) pRecord->data), + pRecord->data); + break; + case TRACE_CODE_TIMER_DEACTIVATE: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + pRecord->time, pRecord->session, "Timer DeActvtd", + __lim_trace_get_timer_string((uint16_t) pRecord->data), + pRecord->data); + break; + + case TRACE_CODE_INFO_LOG: + lim_log(pMac, LOGE, + "%04d %012llu S%d %-14s %-30s(0x%x) \n", + recIndex, pRecord->time, pRecord->session, + "INFORMATION_LOG", + mac_trace_get_info_log_string((uint16_t) pRecord->data), + pRecord->data); + break; + default: + lim_log(pMac, LOGE, "%04d %012llu S%d %-14s(%d) (0x%x) ", + recIndex, pRecord->time, pRecord->session, + "Unknown Code", pRecord->code, pRecord->data); + break; + } +} + +void mac_trace_msg_tx(tpAniSirGlobal pMac, uint8_t session, uint32_t data) +{ + + uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data); + uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data); + + switch (moduleId) { + case SIR_LIM_MODULE_ID: + if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + mac_trace(pMac, TRACE_CODE_TX_LIM_MSG, session, data); + else + mac_trace(pMac, TRACE_CODE_TX_SME_MSG, session, data); + break; + case SIR_WMA_MODULE_ID: + mac_trace(pMac, TRACE_CODE_TX_WMA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + mac_trace(pMac, TRACE_CODE_TX_CFG_MSG, session, data); + break; + default: + mac_trace(pMac, moduleId, session, data); + break; + } +} + +void mac_trace_msg_tx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session, + uint32_t data) +{ + uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data); + uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data); + + switch (moduleId) { + case SIR_LIM_MODULE_ID: + if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + mac_trace_new(pMac, module, TRACE_CODE_TX_LIM_MSG, + session, data); + else + mac_trace_new(pMac, module, TRACE_CODE_TX_SME_MSG, + session, data); + break; + case SIR_WMA_MODULE_ID: + mac_trace_new(pMac, module, TRACE_CODE_TX_WMA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + mac_trace_new(pMac, module, TRACE_CODE_TX_CFG_MSG, session, data); + break; + default: + mac_trace(pMac, moduleId, session, data); + break; + } +} + +/* + * bit31: Rx message defferred or not + * bit 0-15: message ID: + */ +void mac_trace_msg_rx(tpAniSirGlobal pMac, uint8_t session, uint32_t data) +{ + uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data); + uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data); + + switch (moduleId) { + case SIR_LIM_MODULE_ID: + if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + mac_trace(pMac, TRACE_CODE_RX_LIM_MSG, session, data); + else + mac_trace(pMac, TRACE_CODE_RX_SME_MSG, session, data); + break; + case SIR_WMA_MODULE_ID: + mac_trace(pMac, TRACE_CODE_RX_WMA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + mac_trace(pMac, TRACE_CODE_RX_CFG_MSG, session, data); + break; + default: + mac_trace(pMac, moduleId, session, data); + break; + } +} + +/* + * bit31: Rx message defferred or not + * bit 0-15: message ID: + */ +void mac_trace_msg_rx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session, + uint32_t data) +{ + uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data); + uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data); + + switch (moduleId) { + case SIR_LIM_MODULE_ID: + if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN) + mac_trace_new(pMac, module, TRACE_CODE_RX_LIM_MSG, + session, data); + else + mac_trace_new(pMac, module, TRACE_CODE_RX_SME_MSG, + session, data); + break; + case SIR_WMA_MODULE_ID: + mac_trace_new(pMac, module, TRACE_CODE_RX_WMA_MSG, session, data); + break; + case SIR_CFG_MODULE_ID: + mac_trace_new(pMac, module, TRACE_CODE_RX_CFG_MSG, session, data); + break; + default: + mac_trace(pMac, moduleId, session, data); + break; + } +} + +uint8_t *lim_trace_get_mlm_state_string(uint32_t 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_SET_MIMOPS_STATE); + default: + return ("UNKNOWN"); + break; + } +} + +uint8_t *lim_trace_get_sme_state_string(uint32_t 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/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h new file mode 100644 index 000000000000..715e7751e7ae --- /dev/null +++ b/core/mac/src/pe/lim/lim_types.h @@ -0,0 +1,867 @@ +/* + * 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 lim_types.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 "wni_api.h" +#include "sir_api.h" +#include "sir_common.h" +#include "sir_mac_prot_def.h" +#include "utils_api.h" + +#include "lim_api.h" +#include "lim_debug.h" +#include "lim_send_sme_rsp_messages.h" +#include "sys_global.h" +#include "dph_global.h" +#include "parser_api.h" +#include "wma_if.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) +/* + * Values (LIM_MLM_MSG_START + 32) through + * (LIM_MLM_MSG_START + 40) are unused. + */ +#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 distinquish between Association/Reassociaton */ +#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) (cdf_mem_compare(addr, \ + psessionEntry->bssId, \ + sizeof(psessionEntry->bssId))) +/* / Verifies whether given addr matches the REASSOC Bssid */ +#define IS_REASSOC_BSSID(pMac, addr, psessionEntry) (cdf_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 + + +#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 + + +/* 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 + * WMA_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; + uint8_t dtimPeriod; + tSirMacCfParamSet cfParamSet; + tSirMacChanNum channelNumber; + ePhyChanBondState cbMode; + uint16_t atimWindow; + tSirMacRateSet rateSet; + uint8_t sessionId; /* Added For BT-AMP Support */ + + /* Parameters reqd for new HAL (message) interface */ + tSirNwType nwType; + uint8_t htCapable; + tSirMacHTOperatingMode htOperMode; + uint8_t dualCTSProtection; + uint8_t txChannelWidthSet; + uint8_t ssidHidden; + uint8_t wps_state; + uint8_t obssProtEnabled; +} tLimMlmStartReq, *tpLimMlmStartReq; + +typedef struct sLimMlmStartCnf { + tSirResultCodes resultCode; + uint8_t sessionId; +} tLimMlmStartCnf, *tpLimMlmStartCnf; + +typedef struct sLimMlmScanCnf { + tSirResultCodes resultCode; + uint16_t scanResultLength; + tSirBssDescription bssDescription[1]; + uint8_t sessionId; +} tLimMlmScanCnf, *tpLimMlmScanCnf; + +typedef struct sLimScanResult { + uint16_t numBssDescriptions; + tSirBssDescription bssDescription[1]; +} tLimScanResult; + +typedef struct sLimMlmJoinCnf { + tSirResultCodes resultCode; + uint16_t protStatusCode; + uint8_t sessionId; +} tLimMlmJoinCnf, *tpLimMlmJoinCnf; + +typedef struct sLimMlmAssocReq { + tSirMacAddr peerMacAddr; + uint32_t assocFailureTimeout; + uint16_t capabilityInfo; + tSirMacListenInterval listenInterval; + uint8_t sessionId; +} tLimMlmAssocReq, *tpLimMlmAssocReq; + +typedef struct sLimMlmAssocCnf { + tSirResultCodes resultCode; /* Internal status code. */ + uint16_t protStatusCode; /* Protocol Status code. */ + uint8_t sessionId; +} tLimMlmAssocCnf, *tpLimMlmAssocCnf; + +typedef struct sLimMlmAssocInd { + tSirMacAddr peerMacAddr; + uint16_t 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; + uint8_t sessionId; + + tAniBool WmmStaInfoPresent; + + /* Required for indicating the frames to upper layer */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; + tSirSmeChanInfo chan_info; +} tLimMlmAssocInd, *tpLimMlmAssocInd; + +typedef struct sLimMlmReassocReq { + tSirMacAddr peerMacAddr; + uint32_t reassocFailureTimeout; + uint16_t capabilityInfo; + tSirMacListenInterval listenInterval; + uint8_t sessionId; +} tLimMlmReassocReq, *tpLimMlmReassocReq; + +typedef struct sLimMlmReassocCnf { + tSirResultCodes resultCode; + uint16_t protStatusCode; /* Protocol Status code. */ + uint8_t sessionId; +} tLimMlmReassocCnf, *tpLimMlmReassocCnf; + +typedef struct sLimMlmReassocInd { + tSirMacAddr peerMacAddr; + tSirMacAddr currentApAddr; + uint16_t 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 */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; +} tLimMlmReassocInd, *tpLimMlmReassocInd; + +typedef struct sLimMlmAuthCnf { + tSirMacAddr peerMacAddr; + tAniAuthType authType; + tSirResultCodes resultCode; + uint16_t protStatusCode; + uint8_t sessionId; +} tLimMlmAuthCnf, *tpLimMlmAuthCnf; + +typedef struct sLimMlmDeauthReq { + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + uint16_t deauthTrigger; + uint16_t aid; + uint8_t sessionId; /* Added for BT-AMP SUPPORT */ + +} tLimMlmDeauthReq, *tpLimMlmDeauthReq; + +typedef struct sLimMlmDeauthCnf { + tSirMacAddr peerMacAddr; + tSirResultCodes resultCode; + uint16_t deauthTrigger; + uint16_t aid; + uint8_t sessionId; +} tLimMlmDeauthCnf, *tpLimMLmDeauthCnf; + +typedef struct sLimMlmDeauthInd { + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + uint16_t deauthTrigger; + uint16_t aid; +} tLimMlmDeauthInd, *tpLimMlmDeauthInd; + +typedef struct sLimMlmDisassocReq { + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + uint16_t disassocTrigger; + uint16_t aid; + uint8_t sessionId; +} tLimMlmDisassocReq, *tpLimMlmDisassocReq; + +typedef struct sLimMlmDisassocCnf { + tSirMacAddr peerMacAddr; + tSirResultCodes resultCode; + uint16_t disassocTrigger; + uint16_t aid; + uint8_t sessionId; +} tLimMlmDisassocCnf, *tpLimMlmDisassocCnf; + +typedef struct sLimMlmDisassocInd { + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + uint16_t disassocTrigger; + uint16_t aid; + uint8_t sessionId; +} tLimMlmDisassocInd, *tpLimMlmDisassocInd; + +typedef struct sLimMlmPurgeStaReq { + tSirMacAddr peerMacAddr; + uint16_t aid; + uint8_t sessionId; /* Added For BT-AMP Support */ +} tLimMlmPurgeStaReq, *tpLimMlmPurgeStaReq; + +typedef struct sLimMlmPurgeStaInd { + tSirMacAddr peerMacAddr; + uint16_t reasonCode; + uint16_t purgeTrigger; + uint16_t aid; + uint8_t sessionId; +} tLimMlmPurgeStaInd, *tpLimMlmPurgeStaInd; + +typedef struct sLimMlmSetKeysCnf { + tSirMacAddr peerMacAddr; + uint16_t resultCode; + uint16_t aid; + uint8_t sessionId; +} tLimMlmSetKeysCnf, *tpLimMlmSetKeysCnf; + +typedef struct sLimMlmResetReq { + tSirMacAddr macAddr; + uint8_t performCleanup; + uint8_t sessionId; +} tLimMlmResetReq, *tpLimMlmResetReq; + +typedef struct sLimMlmResetCnf { + tSirMacAddr macAddr; + tSirResultCodes resultCode; + uint8_t sessionId; +} tLimMlmResetCnf, *tpLimMlmResetCnf; + +typedef struct sLimMlmLinkTestStopReq { + tSirMacAddr peerMacAddr; + uint8_t sessionId; +} tLimMlmLinkTestStopReq, *tpLimMlmLinkTestStopReq; + +/* Function templates */ + +bool lim_process_sme_req_messages(tpAniSirGlobal, tpSirMsgQ); +void lim_process_mlm_req_messages(tpAniSirGlobal, tpSirMsgQ); +void lim_process_mlm_rsp_messages(tpAniSirGlobal, uint32_t, uint32_t *); +void lim_process_sme_del_bss_rsp(tpAniSirGlobal, uint32_t, tpPESession); + +void lim_get_random_bssid(tpAniSirGlobal pMac, uint8_t *data); + +/* Function to handle HT and HT IE CFG parameter intializations */ +void handle_ht_capabilityand_ht_info(struct sAniSirGlobal *pMac, + tpPESession psessionEntry); + +/* Function to handle CFG parameter updates */ +void lim_handle_cf_gparam_update(tpAniSirGlobal, uint32_t); + +void lim_handle_param_update(tpAniSirGlobal pMac, eUpdateIEsType cfgId); + +/* Function to apply CFG parameters before join/reassoc/start BSS */ +void lim_apply_configuration(tpAniSirGlobal, tpPESession); + +void lim_set_cfg_protection(tpAniSirGlobal pMac, tpPESession pesessionEntry); + +/* Function to Initialize MLM state machine on STA */ +void lim_init_mlm(tpAniSirGlobal); + +/* Function to cleanup MLM state machine */ +void lim_cleanup_mlm(tpAniSirGlobal); + +/* Function to cleanup LMM state machine */ +void lim_cleanup_lmm(tpAniSirGlobal); + +/* Management frame handling functions */ +void lim_process_beacon_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_beacon_frame_no_session(tpAniSirGlobal, uint8_t *); +void lim_process_probe_req_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_probe_rsp_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_probe_rsp_frame_no_session(tpAniSirGlobal, uint8_t *); +void lim_process_probe_req_frame_multiple_bss(tpAniSirGlobal, uint8_t *, + tpPESession); + +/* Process Auth frame when we have a session in progress. */ +void lim_process_auth_frame(tpAniSirGlobal, uint8_t *, tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *, + void *body); +#endif + +void lim_process_assoc_req_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); +void lim_send_mlm_assoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, + tpPESession psessionEntry); + +void lim_process_assoc_rsp_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); +void lim_process_disassoc_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_deauth_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_action_frame(tpAniSirGlobal, uint8_t *, tpPESession); +void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxMetaInfo); + +void lim_populate_p2p_mac_header(tpAniSirGlobal, uint8_t *); +void lim_populate_mac_header(tpAniSirGlobal, uint8_t *, uint8_t, uint8_t, + tSirMacAddr, tSirMacAddr); +tSirRetStatus lim_send_probe_req_mgmt_frame(tpAniSirGlobal, tSirMacSSid *, + tSirMacAddr, uint8_t, tSirMacAddr, + uint32_t, uint32_t, uint8_t *); +void lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal, tSirMacAddr, tpAniSSID, short, + uint8_t, tpPESession, uint8_t); +void lim_send_auth_mgmt_frame(tpAniSirGlobal, tSirMacAuthFrameBody *, tSirMacAddr, + uint8_t, tpPESession); +void lim_send_assoc_req_mgmt_frame(tpAniSirGlobal, tLimMlmAssocReq *, tpPESession); +void lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal, tLimMlmReassocReq *, + tpPESession); +#ifdef WLAN_FEATURE_VOWIFI_11R +void lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal pMac, + tLimMlmReassocReq *pMlmReassocReq, + tpPESession psessionEntry); +#endif +void lim_send_delts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peer, + uint8_t wmmTspecPresent, + tSirMacTSInfo *pTsinfo, + tSirMacTspecIE *pTspecIe, + tpPESession psessionEntry); +void lim_send_addts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tSirAddtsReqInfo *addts, tpPESession); +void lim_send_addts_rsp_action_frame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + uint16_t statusCode, tSirAddtsReqInfo *addts, + tSirMacScheduleIE *pSchedule, tpPESession); + +void lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal, uint16_t, uint16_t, tSirMacAddr, + uint8_t, tpDphHashNode pSta, tpPESession); + +void lim_send_disassoc_mgmt_frame(tpAniSirGlobal, uint16_t, tSirMacAddr, + tpPESession, bool waitForAck); +void lim_send_deauth_mgmt_frame(tpAniSirGlobal, uint16_t, tSirMacAddr, tpPESession, + bool waitForAck); + +tSirResultCodes lim_mlm_add_bss(tpAniSirGlobal, tLimMlmStartReq *, + tpPESession psessionEntry); + +tSirRetStatus lim_send_channel_switch_mgmt_frame(tpAniSirGlobal, tSirMacAddr, + uint8_t, uint8_t, uint8_t, + tpPESession); + +#ifdef WLAN_FEATURE_11AC +tSirRetStatus lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, uint8_t nMode, + tpPESession psessionEntry); +tSirRetStatus lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac, + tSirMacAddr peer, + uint8_t nChanWidth, + uint8_t nNewChannel, + uint8_t ncbMode, + tpPESession psessionEntry); +#endif + +#if defined WLAN_FEATURE_VOWIFI +tSirRetStatus lim_send_neighbor_report_request_frame(tpAniSirGlobal, + tpSirMacNeighborReportReq, + tSirMacAddr, tpPESession); +tSirRetStatus lim_send_link_report_action_frame(tpAniSirGlobal, tpSirMacLinkReport, + tSirMacAddr, tpPESession); +tSirRetStatus lim_send_radio_measure_report_action_frame(tpAniSirGlobal, uint8_t, + uint8_t, + tpSirMacRadioMeasureReport, + tSirMacAddr, tpPESession); +#endif + + +#ifdef FEATURE_WLAN_TDLS +void lim_init_tdls_data(tpAniSirGlobal, tpPESession); +tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf); +tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf); +tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf); +tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, + uint32_t *pMsgBuf); +void lim_send_sme_tdls_delete_all_peer_ind(tpAniSirGlobal pMac, + tpPESession psessionEntry); +void lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint32_t txCompleteStatus); +tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal pMac, + tpPESession psessionEntry); +CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession); +tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, + tSirMacAddr peerMac, uint16_t reason, + uint8_t responder, + tpPESession psessionEntry, + uint8_t *addIe, uint16_t addIeLen); +#endif + +/* Algorithms & Link Monitoring related functions */ +/* / Function that handles heartbeat failure */ +void lim_handle_heart_beat_failure(tpAniSirGlobal, tpPESession); + +/* / Function that triggers link tear down with AP upon HB failure */ +void lim_tear_down_link_with_ap(tpAniSirGlobal, uint8_t, tSirMacReasonCodes); + +/* / Function that processes Max retries interrupt from TFP */ +void limHandleMaxRetriesInterrupt(uint32_t); + +/* / Function that processes messages deferred during Learn mode */ +void lim_process_deferred_message_queue(tpAniSirGlobal); + +/* / Function that defers the messages received */ +uint32_t lim_defer_msg(tpAniSirGlobal, tSirMsgQ *); + +/* / Function that Switches the Channel and sets the CB Mode */ +void lim_set_channel(tpAniSirGlobal pMac, uint8_t channel, + uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, + phy_ch_width ch_width, tPowerdBm maxTxPower, + uint8_t peSessionId); + + +/* / Function that completes channel scan */ +void lim_complete_mlm_scan(tpAniSirGlobal, tSirResultCodes); + +#ifdef ANI_SUPPORT_11H +/* / Function that sends Measurement Report action frame */ +tSirRetStatus lim_send_meas_report_frame(tpAniSirGlobal, tpSirMacMeasReqActionFrame, + tSirMacAddr, tpPESession psessionEntry); + +/* / Function that sends TPC Report action frame */ +tSirRetStatus lim_send_tpc_report_frame(tpAniSirGlobal, tpSirMacTpcReqActionFrame, + tSirMacAddr, tpPESession psessionEntry); +#endif + +/* / Function that sends TPC Request action frame */ +void lim_send_tpc_request_frame(tpAniSirGlobal, tSirMacAddr, + tpPESession psessionEntry); + +/* Function(s) to handle responses received from HAL */ +void lim_process_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ); +void lim_process_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQt, + tpPESession psessionEntry); +void lim_process_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ); +void lim_process_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession); +void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry); +void lim_process_sta_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry); +void lim_process_sta_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry); +void lim_process_mlm_set_sta_key_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ); +void lim_process_mlm_set_bss_key_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ); + +/* Function to process WMA_SWITCH_CHANNEL_RSP message */ +void lim_process_switch_channel_rsp(tpAniSirGlobal pMac, void *); + +void lim_covert_channel_scan_type(tpAniSirGlobal pMac, uint8_t channelNum, + bool passiveToActive); +void lim_set_dfs_channel_list(tpAniSirGlobal pMac, uint8_t channelNum, + tSirDFSChannelList *dfsChannelList); +void limContinueChannelLearn(tpAniSirGlobal); +/* WLAN_SUSPEND_LINK Related */ +uint8_t lim_is_link_suspended(tpAniSirGlobal pMac); +/* end WLAN_SUSPEND_LINK Related */ + +#ifdef WLAN_FEATURE_11W +/* 11w send SA query request action frame */ +tSirRetStatus lim_send_sa_query_request_frame(tpAniSirGlobal pMac, uint8_t *transId, + tSirMacAddr peer, + tpPESession psessionEntry); +/* 11w SA query request action frame handler */ +tSirRetStatus lim_send_sa_query_response_frame(tpAniSirGlobal pMac, + uint8_t *transId, tSirMacAddr peer, + tpPESession psessionEntry); +#endif + +/* Inline functions */ + +/** + * lim_post_sme_message() + * + ***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 +lim_post_sme_message(tpAniSirGlobal pMac, uint32_t msgType, uint32_t *pMsgBuf) +{ + tSirMsgQ msg; + + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + + msg.type = (uint16_t) msgType; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + if (msgType > eWNI_SME_MSG_TYPES_BEGIN) + lim_process_sme_req_messages(pMac, &msg); + else + lim_process_mlm_rsp_messages(pMac, msgType, pMsgBuf); +} /*** end lim_post_sme_message() ***/ + +/** + * lim_post_mlm_message() + * + ***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 +lim_post_mlm_message(tpAniSirGlobal pMac, uint32_t msgType, uint32_t *pMsgBuf) +{ + + tSirMsgQ msg; + if (pMsgBuf == NULL) { + lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL")); + return; + } + msg.type = (uint16_t) msgType; + msg.bodyptr = pMsgBuf; + msg.bodyval = 0; + lim_process_mlm_req_messages(pMac, &msg); +} /*** end lim_post_mlm_message() ***/ + +/** + * lim_get_current_scan_channel() + * + ***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 uint8_t lim_get_current_scan_channel(tpAniSirGlobal pMac) +{ + uint8_t *pChanNum = + pMac->lim.gpLimMlmScanReq->channelList.channelNumber; + + return *(pChanNum + pMac->lim.gLimCurrentScanChannelId); +} /*** end lim_get_current_scan_channel() ***/ + +/** + * lim_get_ielen_from_bss_description() + * + ***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 uint16_t +lim_get_ielen_from_bss_description(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 = (uint16_t)(pBssDescr->length + sizeof(pBssDescr->length) - + GET_FIELD_OFFSET(tSirBssDescription, ieFields)); + + return ielen; +} /*** end lim_get_ielen_from_bss_description() ***/ + +/** + * lim_send_beacon_ind() + * + ***FUNCTION: + * This function is called to send the beacon indication + * number being scanned. + * + ***PARAMS: + * + ***LOGIC: + * + ***ASSUMPTIONS: + */ + +void lim_send_beacon_ind(tpAniSirGlobal pMac, tpPESession psessionEntry); + +void +lim_send_vdev_restart(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t sessionId); + +void lim_get_wpspbc_sessions(tpAniSirGlobal pMac, uint8_t *addr, uint8_t *uuid_e, + eWPSPBCOverlap *overlap, tpPESession psessionEntry); +void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry); +void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry); +void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac, + tpPESession psessionEntry); + +#define LIM_WPS_OVERLAP_TIMER_MS 10000 +void +lim_change_channel_with_callback(tpAniSirGlobal pMac, uint8_t newChannel, + CHANGE_CHANNEL_CALLBACK callback, + uint32_t *cbdata, tpPESession psessionEntry); + +void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, + uint8_t *frame, uint32_t frameLen, + uint16_t sessionId, uint32_t rxChan, + tpPESession psessionEntry, int8_t rxRssi); +void lim_process_remain_on_chn_timeout(tpAniSirGlobal pMac); +void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac); +void lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac); +void lim_send_p2p_action_frame(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +void lim_abort_remain_on_chan(tpAniSirGlobal pMac, uint8_t sessionId, + uint32_t scan_id); +tSirRetStatus __lim_process_sme_no_a_update(tpAniSirGlobal pMac, uint32_t *pMsgBuf); +void lim_process_regd_defd_sme_req_after_noa_start(tpAniSirGlobal pMac); + +void lim_process_disassoc_ack_timeout(tpAniSirGlobal pMac); +void lim_process_deauth_ack_timeout(tpAniSirGlobal pMac); +CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal pMac); +CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac); +CDF_STATUS lim_disassoc_tx_complete_cnf(tpAniSirGlobal pMac, + uint32_t txCompleteSuccess); +CDF_STATUS lim_deauth_tx_complete_cnf(tpAniSirGlobal pMac, + uint32_t txCompleteSuccess); + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct sSetLinkCbackParams { + void *cbackDataPtr; +} tSetLinkCbackParams; +#endif + +void lim_process_rx_scan_event(tpAniSirGlobal mac, void *buf); + +int lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg); +void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data); + +/* / Bit value data structure */ +typedef enum sHalBitVal /* For Bit operations */ +{ + eHAL_CLEAR, + eHAL_SET +} tHalBitVal; + +enum { + eHI_PRI, + ePROT, + eDBG +}; + +#endif /* __LIM_TYPES_H */ diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c new file mode 100644 index 000000000000..d34c2a30d0af --- /dev/null +++ b/core/mac/src/pe/lim/lim_utils.c @@ -0,0 +1,7145 @@ +/* + * 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 lim_utils.cc contains the utility functions + * LIM uses. + * Author: Chandra Modumudi + * Date: 02/13/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + */ + +#include "sch_api.h" +#include "lim_utils.h" +#include "lim_types.h" +#include "lim_security_utils.h" +#include "lim_prop_exts_utils.h" +#include "lim_send_messages.h" +#include "lim_ser_des_utils.h" +#include "lim_admit_control.h" +#include "lim_sta_hash_api.h" +#include "dot11f.h" +#include "dot11fdefs.h" +#include "wmm_apsd.h" +#include "lim_trace.h" +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "host_diag_core_event.h" +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#include "lim_ibss_peer_mgmt.h" +#include "lim_session_utils.h" +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "lim_ft_defs.h" +#endif +#include "lim_session.h" +#include "cds_reg_service.h" + +#ifdef WLAN_FEATURE_11W +#include "wni_cfg.h" +#endif +#define ASCII_SPACE_CHARACTER 0x20 + +#define SUCCESS 1 + +#define MAX_BA_WINDOW_SIZE_FOR_CISCO 25 + +/** ------------------------------------------------------------- + \fn lim_delete_dialogue_token_list + \brief deletes the complete lim dialogue token linked list. + \param tpAniSirGlobal pMac + \return None + -------------------------------------------------------------*/ +void lim_delete_dialogue_token_list(tpAniSirGlobal pMac) +{ + tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead; + + while (NULL != pMac->lim.pDialogueTokenHead) { + pCurrNode = pMac->lim.pDialogueTokenHead; + pMac->lim.pDialogueTokenHead = + pMac->lim.pDialogueTokenHead->next; + cdf_mem_free(pCurrNode); + pCurrNode = NULL; + } + pMac->lim.pDialogueTokenTail = NULL; +} + +char *lim_dot11_reason_str(uint16_t 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 *lim_mlm_state_str(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 +lim_print_mlm_state(tpAniSirGlobal pMac, uint16_t logLevel, tLimMlmStates state) +{ + lim_log(pMac, logLevel, lim_mlm_state_str(state)); +} + +char *lim_sme_state_str(tLimSmeStates state) +{ + switch (state) { + case eLIM_SME_OFFLINE_STATE: + return "eLIM_SME_OFFLINE_STATE"; + case eLIM_SME_IDLE_STATE: + return "eLIM_SME_OFFLINE_STATE"; + case eLIM_SME_SUSPEND_STATE: + return "eLIM_SME_SUSPEND_STATE"; + case eLIM_SME_WT_SCAN_STATE: + return "eLIM_SME_WT_SCAN_STATE"; + case eLIM_SME_WT_JOIN_STATE: + return "eLIM_SME_WT_JOIN_STATE"; + case eLIM_SME_WT_AUTH_STATE: + return "eLIM_SME_WT_AUTH_STATE"; + case eLIM_SME_WT_ASSOC_STATE: + return "eLIM_SME_WT_ASSOC_STATE"; + case eLIM_SME_WT_REASSOC_STATE: + return "eLIM_SME_WT_REASSOC_STATE"; + case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: + return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE"; + case eLIM_SME_JOIN_FAILURE_STATE: + return "eLIM_SME_JOIN_FAILURE_STATE"; + case eLIM_SME_ASSOCIATED_STATE: + return "eLIM_SME_ASSOCIATED_STATE"; + case eLIM_SME_REASSOCIATED_STATE: + return "eLIM_SME_REASSOCIATED_STATE"; + case eLIM_SME_LINK_EST_STATE: + return "eLIM_SME_LINK_EST_STATE"; + case eLIM_SME_LINK_EST_WT_SCAN_STATE: + return "eLIM_SME_LINK_EST_WT_SCAN_STATE"; + case eLIM_SME_WT_PRE_AUTH_STATE: + return "eLIM_SME_WT_PRE_AUTH_STATE"; + case eLIM_SME_WT_DISASSOC_STATE: + return "eLIM_SME_WT_DISASSOC_STATE"; + case eLIM_SME_WT_DEAUTH_STATE: + return "eLIM_SME_WT_DEAUTH_STATE"; + case eLIM_SME_WT_START_BSS_STATE: + return "eLIM_SME_WT_START_BSS_STATE"; + case eLIM_SME_WT_STOP_BSS_STATE: + return "eLIM_SME_WT_STOP_BSS_STATE"; + case eLIM_SME_NORMAL_STATE: + return "eLIM_SME_NORMAL_STATE"; + case eLIM_SME_CHANNEL_SCAN_STATE: + return "eLIM_SME_CHANNEL_SCAN_STATE"; + case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: + return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE"; + default: + return "INVALID SME STATE"; + } +} + +void +lim_print_sme_state(tpAniSirGlobal pMac, uint16_t logLevel, tLimSmeStates state) +{ + lim_log(pMac, logLevel, lim_sme_state_str(state)); +} + +char *lim_msg_str(uint32_t msgType) +{ +#ifdef FIXME_GEN6 + switch (msgType) { + case eWNI_SME_SYS_READY_IND: + return "eWNI_SME_SYS_READY_IND"; + case eWNI_SME_SCAN_REQ: + return "eWNI_SME_SCAN_REQ"; +#ifdef FEATURE_OEM_DATA_SUPPORT + case eWNI_SME_OEM_DATA_REQ: + return "eWNI_SME_OEM_DATA_REQ"; + case eWNI_SME_OEM_DATA_RSP: + return "eWNI_SME_OEM_DATA_RSP"; +#endif + case eWNI_SME_SCAN_RSP: + return "eWNI_SME_SCAN_RSP"; + case eWNI_SME_JOIN_REQ: + return "eWNI_SME_JOIN_REQ"; + case eWNI_SME_JOIN_RSP: + return "eWNI_SME_JOIN_RSP"; + case eWNI_SME_SETCONTEXT_REQ: + return "eWNI_SME_SETCONTEXT_REQ"; + case eWNI_SME_SETCONTEXT_RSP: + return "eWNI_SME_SETCONTEXT_RSP"; + case eWNI_SME_REASSOC_REQ: + return "eWNI_SME_REASSOC_REQ"; + case eWNI_SME_REASSOC_RSP: + return "eWNI_SME_REASSOC_RSP"; + case eWNI_SME_DISASSOC_REQ: + return "eWNI_SME_DISASSOC_REQ"; + case eWNI_SME_DISASSOC_RSP: + return "eWNI_SME_DISASSOC_RSP"; + case eWNI_SME_DISASSOC_IND: + return "eWNI_SME_DISASSOC_IND"; + case eWNI_SME_DISASSOC_CNF: + return "eWNI_SME_DISASSOC_CNF"; + case eWNI_SME_DEAUTH_REQ: + return "eWNI_SME_DEAUTH_REQ"; + case eWNI_SME_DEAUTH_RSP: + return "eWNI_SME_DEAUTH_RSP"; + case eWNI_SME_DEAUTH_IND: + return "eWNI_SME_DEAUTH_IND"; + case eWNI_SME_WM_STATUS_CHANGE_NTF: + return "eWNI_SME_WM_STATUS_CHANGE_NTF"; + case eWNI_SME_START_BSS_REQ: + return "eWNI_SME_START_BSS_REQ"; + case eWNI_SME_START_BSS_RSP: + return "eWNI_SME_START_BSS_RSP"; + case eWNI_SME_ASSOC_IND: + return "eWNI_SME_ASSOC_IND"; + case eWNI_SME_ASSOC_CNF: + return "eWNI_SME_ASSOC_CNF"; + case eWNI_SME_SWITCH_CHL_IND: + return "eWNI_SME_SWITCH_CHL_IND"; + case eWNI_SME_STOP_BSS_REQ: + return "eWNI_SME_STOP_BSS_REQ"; + case eWNI_SME_STOP_BSS_RSP: + return "eWNI_SME_STOP_BSS_RSP"; + case eWNI_SME_NEIGHBOR_BSS_IND: + return "eWNI_SME_NEIGHBOR_BSS_IND"; + case eWNI_SME_DEAUTH_CNF: + return "eWNI_SME_DEAUTH_CNF"; + case eWNI_SME_ADDTS_REQ: + return "eWNI_SME_ADDTS_REQ"; + case eWNI_SME_ADDTS_RSP: + return "eWNI_SME_ADDTS_RSP"; + case eWNI_SME_DELTS_REQ: + return "eWNI_SME_DELTS_REQ"; + case eWNI_SME_DELTS_RSP: + return "eWNI_SME_DELTS_RSP"; + case eWNI_SME_DELTS_IND: + return "eWNI_SME_DELTS_IND"; + case WMA_SUSPEND_ACTIVITY_RSP: + return "WMA_SUSPEND_ACTIVITY_RSP"; + case SIR_LIM_RETRY_INTERRUPT_MSG: + return "SIR_LIM_RETRY_INTERRUPT_MSG"; + case SIR_BB_XPORT_MGMT_MSG: + return "SIR_BB_XPORT_MGMT_MSG"; + case SIR_LIM_INV_KEY_INTERRUPT_MSG: + return "SIR_LIM_INV_KEY_INTERRUPT_MSG"; + case SIR_LIM_KEY_ID_INTERRUPT_MSG: + return "SIR_LIM_KEY_ID_INTERRUPT_MSG"; + case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG: + return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG"; + case SIR_LIM_JOIN_FAIL_TIMEOUT: + return "SIR_LIM_JOIN_FAIL_TIMEOUT"; + case SIR_LIM_AUTH_FAIL_TIMEOUT: + return "SIR_LIM_AUTH_FAIL_TIMEOUT"; + case SIR_LIM_AUTH_RSP_TIMEOUT: + return "SIR_LIM_AUTH_RSP_TIMEOUT"; + case SIR_LIM_ASSOC_FAIL_TIMEOUT: + return "SIR_LIM_ASSOC_FAIL_TIMEOUT"; + case SIR_LIM_REASSOC_FAIL_TIMEOUT: + return "SIR_LIM_REASSOC_FAIL_TIMEOUT"; + case SIR_LIM_HEART_BEAT_TIMEOUT: + return "SIR_LIM_HEART_BEAT_TIMEOUT"; + case SIR_LIM_ADDTS_RSP_TIMEOUT: + return "SIR_LIM_ADDTS_RSP_TIMEOUT"; + case SIR_LIM_LINK_TEST_DURATION_TIMEOUT: + return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT"; + case SIR_LIM_HASH_MISS_THRES_TIMEOUT: + return "SIR_LIM_HASH_MISS_THRES_TIMEOUT"; + case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: + return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT"; + case SIR_LIM_CNF_WAIT_TIMEOUT: + return "SIR_LIM_CNF_WAIT_TIMEOUT"; + case SIR_LIM_RADAR_DETECT_IND: + return "SIR_LIM_RADAR_DETECT_IND"; +#ifdef WLAN_FEATURE_VOWIFI_11R + case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: + return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT"; +#endif + + case WNI_CFG_PARAM_UPDATE_IND: + return "WNI_CFG_PARAM_UPDATE_IND"; + case WNI_CFG_DNLD_REQ: + return "WNI_CFG_DNLD_REQ"; + case WNI_CFG_DNLD_CNF: + return "WNI_CFG_DNLD_CNF"; + case WNI_CFG_GET_RSP: + return "WNI_CFG_GET_RSP"; + case WNI_CFG_SET_CNF: + return "WNI_CFG_SET_CNF"; + case WNI_CFG_GET_ATTRIB_RSP: + return "WNI_CFG_GET_ATTRIB_RSP"; + case WNI_CFG_ADD_GRP_ADDR_CNF: + return "WNI_CFG_ADD_GRP_ADDR_CNF"; + case WNI_CFG_DEL_GRP_ADDR_CNF: + return "WNI_CFG_DEL_GRP_ADDR_CNF"; + case ANI_CFG_GET_RADIO_STAT_RSP: + return "ANI_CFG_GET_RADIO_STAT_RSP"; + case ANI_CFG_GET_PER_STA_STAT_RSP: + return "ANI_CFG_GET_PER_STA_STAT_RSP"; + case ANI_CFG_GET_AGG_STA_STAT_RSP: + return "ANI_CFG_GET_AGG_STA_STAT_RSP"; + case ANI_CFG_CLEAR_STAT_RSP: + return "ANI_CFG_CLEAR_STAT_RSP"; + case WNI_CFG_DNLD_RSP: + return "WNI_CFG_DNLD_RSP"; + case WNI_CFG_GET_REQ: + return "WNI_CFG_GET_REQ"; + case WNI_CFG_SET_REQ: + return "WNI_CFG_SET_REQ"; + case WNI_CFG_SET_REQ_NO_RSP: + return "WNI_CFG_SET_REQ_NO_RSP"; + case eWNI_PMC_ENTER_IMPS_RSP: + return "eWNI_PMC_ENTER_IMPS_RSP"; + case eWNI_PMC_EXIT_IMPS_RSP: + return "eWNI_PMC_EXIT_IMPS_RSP"; + case eWNI_PMC_ENTER_BMPS_RSP: + return "eWNI_PMC_ENTER_BMPS_RSP"; + case eWNI_PMC_EXIT_BMPS_RSP: + return "eWNI_PMC_EXIT_BMPS_RSP"; + case eWNI_PMC_EXIT_BMPS_IND: + return "eWNI_PMC_EXIT_BMPS_IND"; + case eWNI_SME_SET_BCN_FILTER_REQ: + return "eWNI_SME_SET_BCN_FILTER_REQ"; +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_GET_TSM_STATS_REQ: + return "eWNI_SME_GET_TSM_STATS_REQ"; + case eWNI_SME_GET_TSM_STATS_RSP: + return "eWNI_SME_GET_TSM_STATS_RSP"; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_CSA_OFFLOAD_EVENT: + return "eWNI_SME_CSA_OFFLOAD_EVENT"; + case eWNI_SME_SET_HW_MODE_REQ: + return "eWNI_SME_SET_HW_MODE_REQ"; + case eWNI_SME_SET_HW_MODE_RESP: + return "eWNI_SME_SET_HW_MODE_RESP"; + case eWNI_SME_HW_MODE_TRANS_IND: + return "eWNI_SME_HW_MODE_TRANS_IND"; + default: + return "INVALID SME message"; + } +#endif + return ""; +} + +char *lim_result_code_str(tSirResultCodes resultCode) +{ + switch (resultCode) { + case eSIR_SME_SUCCESS: + return "eSIR_SME_SUCCESS"; + case eSIR_LOGP_EXCEPTION: + return "eSIR_LOGP_EXCEPTION"; + 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_ALREADY_JOINED_A_BSS: + return "eSIR_SME_ALREADY_JOINED_A_BSS"; + 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_CHANNEL_SWITCH_FAIL: + return "eSIR_SME_CHANNEL_SWITCH_FAIL"; + case eSIR_SME_HAL_SCAN_INIT_FAILED: + return "eSIR_SME_HAL_SCAN_INIT_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"; + } +} + +void lim_print_msg_name(tpAniSirGlobal pMac, uint16_t logLevel, uint32_t msgType) +{ + lim_log(pMac, logLevel, lim_msg_str(msgType)); +} + +/** + * lim_init_mlm() + * + ***FUNCTION: + * This function is called by limProcessSmeMessages() to + * initialize MLM state machine on STA + * + ***PARAMS: + * + ***LOGIC: + * + ***ASSUMPTIONS: + * NA + * + ***NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @return None + */ +void lim_init_mlm(tpAniSirGlobal pMac) +{ + uint32_t retVal; + + pMac->lim.gLimTimersCreated = 0; + + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, NO_SESSION, + pMac->lim.gLimMlmState)); + + + /* / Initialize number of pre-auth contexts */ + pMac->lim.gLimNumPreAuthContexts = 0; + + /* / Initialize MAC based Authentication STA list */ + lim_init_pre_auth_list(pMac); + + /* Create timers used by LIM */ + retVal = lim_create_timers(pMac); + if (retVal == TX_SUCCESS) { + pMac->lim.gLimTimersCreated = 1; + } else { + lim_log(pMac, LOGP, + FL(" lim_create_timers Failed to create lim timers ")); + } +} /*** end lim_init_mlm() ***/ + +/** + * lim_deactivate_del_sta() - This function deactivate/delete associates STA + * @mac_ctx: pointer to Global Mac Structure + * @bss_entry: index for bss_entry + * @psession_entry: pointer to session entry + * @sta_ds: pointer to tpDphHashNode + * + * Function deactivate/delete associates STA + * + * Return: none + */ +static void lim_deactivate_del_sta(tpAniSirGlobal mac_ctx, uint32_t bss_entry, + tpPESession psession_entry, tpDphHashNode sta_ds) +{ + uint32_t sta_entry; + + for (sta_entry = 1; sta_entry < mac_ctx->lim.gLimAssocStaLimit; + sta_entry++) { + psession_entry = &mac_ctx->lim.gpSession[bss_entry]; + sta_ds = dph_get_hash_entry(mac_ctx, sta_entry, + &psession_entry->dph.dphHashTable); + if (NULL == sta_ds) + continue; + + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("Deleting pmfSaQueryTimer for staid[%d]"), + sta_ds->staIndex); + tx_timer_deactivate(&sta_ds->pmfSaQueryTimer); + tx_timer_delete(&sta_ds->pmfSaQueryTimer); + } +} + +/** + * lim_cleanup_mlm() - This function is called to cleanup + * @mac_ctx: Pointer to Global MAC structure + * + * Function is called to cleanup any resources allocated by the MLM + * state machine. + * + * Return: none + */ +void lim_cleanup_mlm(tpAniSirGlobal mac_ctx) +{ + uint32_t n; + tLimPreAuthNode *pAuthNode; +#ifdef WLAN_FEATURE_11W + uint32_t bss_entry; + tpDphHashNode sta_ds = NULL; + tpPESession psession_entry = NULL; +#endif + tLimTimers *lim_timer = NULL; + + if (mac_ctx->lim.gLimTimersCreated == 1) { + lim_timer = &mac_ctx->lim.limTimers; + + /* Deactivate and delete Periodic Probe channel timers. */ + tx_timer_deactivate(&lim_timer->gLimPeriodicProbeReqTimer); + tx_timer_delete(&lim_timer->gLimPeriodicProbeReqTimer); + + /* Deactivate and delete channel switch timer. */ + tx_timer_deactivate(&lim_timer->gLimChannelSwitchTimer); + tx_timer_delete(&lim_timer->gLimChannelSwitchTimer); + + /* Deactivate and delete addts response timer. */ + tx_timer_deactivate(&lim_timer->gLimAddtsRspTimer); + tx_timer_delete(&lim_timer->gLimAddtsRspTimer); + + /* Deactivate and delete Join failure timer. */ + tx_timer_deactivate(&lim_timer->gLimJoinFailureTimer); + tx_timer_delete(&lim_timer->gLimJoinFailureTimer); + + /* Deactivate and delete Periodic Join Probe Request timer. */ + tx_timer_deactivate(&lim_timer->gLimPeriodicJoinProbeReqTimer); + tx_timer_delete(&lim_timer->gLimPeriodicJoinProbeReqTimer); + + /* Deactivate and delete Association failure timer. */ + tx_timer_deactivate(&lim_timer->gLimAssocFailureTimer); + tx_timer_delete(&lim_timer->gLimAssocFailureTimer); + + /* Deactivate and delete Reassociation failure timer. */ + tx_timer_deactivate(&lim_timer->gLimReassocFailureTimer); + tx_timer_delete(&lim_timer->gLimReassocFailureTimer); + + /* Deactivate and delete Authentication failure timer. */ + tx_timer_deactivate(&lim_timer->gLimAuthFailureTimer); + tx_timer_delete(&lim_timer->gLimAuthFailureTimer); + + /* Deactivate and delete wait-for-probe-after-Heartbeat timer. */ + tx_timer_deactivate(&lim_timer->gLimProbeAfterHBTimer); + tx_timer_delete(&lim_timer->gLimProbeAfterHBTimer); + + /* Deactivate and delete Quiet timer. */ + tx_timer_deactivate(&lim_timer->gLimQuietTimer); + tx_timer_delete(&lim_timer->gLimQuietTimer); + + /* Deactivate and delete Quiet BSS timer. */ + tx_timer_deactivate(&lim_timer->gLimQuietBssTimer); + tx_timer_delete(&lim_timer->gLimQuietBssTimer); + + /* Deactivate and delete cnf wait timer */ + for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) { + tx_timer_deactivate(&lim_timer->gpLimCnfWaitTimer[n]); + tx_timer_delete(&lim_timer->gpLimCnfWaitTimer[n]); + } + + pAuthNode = mac_ctx->lim.gLimPreAuthTimerTable.pTable; + + /* Deactivate any Authentication response timers */ + lim_delete_pre_auth_list(mac_ctx); + + for (n = 0; n < mac_ctx->lim.gLimPreAuthTimerTable.numEntry; + n++, pAuthNode++) { + /* + * Delete any Authentication response + * timers, which might have been started. + */ + tx_timer_delete(&pAuthNode->timer); + } + + /* Deactivate and delete Hash Miss throttle timer */ + tx_timer_deactivate(&lim_timer-> + gLimSendDisassocFrameThresholdTimer); + tx_timer_delete(&lim_timer-> + gLimSendDisassocFrameThresholdTimer); + + tx_timer_deactivate(&lim_timer->gLimUpdateOlbcCacheTimer); + tx_timer_delete(&lim_timer->gLimUpdateOlbcCacheTimer); + tx_timer_deactivate(&lim_timer->gLimPreAuthClnupTimer); + tx_timer_delete(&lim_timer->gLimPreAuthClnupTimer); + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Deactivate and delete FT Preauth response timer */ + tx_timer_deactivate(&lim_timer->gLimFTPreAuthRspTimer); + tx_timer_delete(&lim_timer->gLimFTPreAuthRspTimer); +#endif + + /* Deactivate and delete remain on channel timer */ + tx_timer_deactivate(&lim_timer->gLimRemainOnChannelTimer); + tx_timer_delete(&lim_timer->gLimRemainOnChannelTimer); + + + tx_timer_deactivate(&lim_timer->gLimDisassocAckTimer); + tx_timer_delete(&lim_timer->gLimDisassocAckTimer); + + tx_timer_deactivate(&lim_timer->gLimDeauthAckTimer); + tx_timer_delete(&lim_timer->gLimDeauthAckTimer); + + tx_timer_deactivate(&lim_timer-> + gLimP2pSingleShotNoaInsertTimer); + tx_timer_delete(&lim_timer-> + gLimP2pSingleShotNoaInsertTimer); + + tx_timer_deactivate(&lim_timer-> + gLimActiveToPassiveChannelTimer); + tx_timer_delete(&lim_timer-> + gLimActiveToPassiveChannelTimer); + + mac_ctx->lim.gLimTimersCreated = 0; + } +#ifdef WLAN_FEATURE_11W + /* + * When SSR is triggered, we need to loop through + * each STA associated per BSSId and deactivate/delete + * the pmfSaQueryTimer for it + */ + if (cds_is_logp_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + FL("SSR is detected, proceed to clean up pmfSaQueryTimer")); + for (bss_entry = 0; bss_entry < mac_ctx->lim.maxBssId; + bss_entry++) { + if (!mac_ctx->lim.gpSession[bss_entry].valid) + continue; + lim_deactivate_del_sta(mac_ctx, bss_entry, + psession_entry, sta_ds); + } + } +#endif + +} /*** end lim_cleanup_mlm() ***/ + +/** + * lim_cleanup_lmm() + * + ***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 lim_cleanup_lmm(tpAniSirGlobal pMac) +{ +} /*** end lim_cleanup_lmm() ***/ + +/** + * lim_is_addr_bc() + * + ***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 + */ + +uint8_t lim_is_addr_bc(tSirMacAddr macAddr) +{ + int i; + for (i = 0; i < 6; i++) { + if ((macAddr[i] & 0xFF) != 0xFF) + return false; + } + + return true; +} /****** end lim_is_addr_bc() ******/ + +/** + * lim_is_group_addr() + * + ***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 + */ + +uint8_t lim_is_group_addr(tSirMacAddr macAddr) +{ + if ((macAddr[0] & 0x01) == 0x01) + return true; + else + return false; +} /****** end lim_is_group_addr() ******/ + +/** + * lim_print_mac_addr() + * + ***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 lim_print_mac_addr(tpAniSirGlobal pMac, tSirMacAddr macAddr, uint8_t logLevel) +{ + lim_log(pMac, logLevel, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(macAddr)); +} /****** end lim_print_mac_addr() ******/ + +/* + * lim_reset_deferred_msg_q() + * + ***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 lim_reset_deferred_msg_q(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) + +/** + * lim_write_deferred_msg_q() - This function queues up a deferred message + * + * @mac_ctx: Pointer to Global MAC structure + * @lim_msg: a LIM message + * + * Function queues up a deferred message for later processing on the + * STA side. + * + * Return: none + */ + +uint8_t lim_write_deferred_msg_q(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg) +{ + lim_log(mac_ctx, LOG1, + FL("Queue a deferred message (size %d, write %d) - type 0x%x "), + mac_ctx->lim.gLimDeferredMsgQ.size, + mac_ctx->lim.gLimDeferredMsgQ.write, + lim_msg->type); + + /* check if the deferred message queue is full */ + if (mac_ctx->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN) { + if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) { + lim_log(mac_ctx, LOGE, + FL("queue->MsgQ full Msg:%d Msgs Failed:%d"), + lim_msg->type, + ++mac_ctx->lim.deferredMsgCnt); + } else { + mac_ctx->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 (mac_ctx->lim.gLimDeferredMsgQ.size > 0) + lim_log(mac_ctx, LOGW, + FL("%d Deferred Msg (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"), + mac_ctx->lim.gLimDeferredMsgQ.size, + lim_msg->type, + lim_is_system_in_scan_state(mac_ctx), + mac_ctx->lim.gLimSmeState, + mac_ctx->lim.gLimMlmState, + mac_ctx->lim.gLimAddtsSent); + + /* + * To prevent the deferred Q is full of management frames, only give + * them certain space + */ + if ((SIR_BB_XPORT_MGMT_MSG == lim_msg->type) && + (LIM_DEFERRED_Q_CHECK_THRESHOLD < + mac_ctx->lim.gLimDeferredMsgQ.size)) { + uint16_t idx, count = 0; + for (idx = 0; idx < mac_ctx->lim.gLimDeferredMsgQ.size; + idx++) { + if (SIR_BB_XPORT_MGMT_MSG == + mac_ctx->lim.gLimDeferredMsgQ. + deferredQueue[idx].type) { + count++; + } + } + if (LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count) { + /* + * We reach the quota for management frames, + * drop this one + */ + lim_log(mac_ctx, LOGW, + FL("Too many queue->MsgQ Msg: %d (count=%d)"), + lim_msg->type, count); + /* Return error, caller knows what to do */ + return TX_QUEUE_FULL; + } + } + + ++mac_ctx->lim.gLimDeferredMsgQ.size; + + /* reset the count here since we are able to defer the message */ + if (mac_ctx->lim.deferredMsgCnt != 0) + mac_ctx->lim.deferredMsgCnt = 0; + + /* if the write pointer hits the end of the queue, rewind it */ + if (mac_ctx->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN) + mac_ctx->lim.gLimDeferredMsgQ.write = 0; + + /* save the message to the queue and advanced the write pointer */ + cdf_mem_copy((uint8_t *) &mac_ctx->lim.gLimDeferredMsgQ. + deferredQueue[mac_ctx->lim.gLimDeferredMsgQ.write++], + (uint8_t *) lim_msg, sizeof(tSirMsgQ)); + return TX_SUCCESS; + +} + +/* + * lim_read_deferred_msg_q() + * + ***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 *lim_read_deferred_msg_q(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(lim_log(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(lim_log + (pMac, LOG1, + FL + ("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"), + lim_is_system_in_scan_state(pMac), pMac->lim.gLimSmeState, + pMac->lim.gLimMlmState, pMac->lim.gLimAddtsSent); + ) + + return msg; +} + +tSirRetStatus +lim_sys_process_mmh_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg, uint8_t qType) +{ + /* FIXME */ + sys_process_mmh_msg(pMac, pMsg); + return eSIR_SUCCESS; +} + +/* + * lim_handle_update_olbc_cache() - This function update olbc cache + * + * @mac_ctx: Pointer to Global MAC structure + * + * Function updates olbc cache + * + * Return: none + */ +void lim_handle_update_olbc_cache(tpAniSirGlobal mac_ctx) +{ + int i; + static int enable; + tUpdateBeaconParams beaconParams; + + tpPESession psessionEntry = lim_is_ap_session_active(mac_ctx); + + if (psessionEntry == NULL) { + lim_log(mac_ctx, LOGE, FL(" Session not found")); + return; + } + + cdf_mem_set((uint8_t *) &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) { + lim_log(mac_ctx, 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++) + mac_ctx->lim.protStaOverlapCache[i].active = false; + + enable = 1; + } else { + if ((!psessionEntry->gLimOlbcParams.numSta) && + (psessionEntry->gLimOlbcParams.protectionEnabled) && + (!psessionEntry->gLim11bParams.protectionEnabled)) { + lim_log(mac_ctx, LOG1, + FL("Overlap cache clear and no 11B STA set")); + lim_enable11g_protection(mac_ctx, false, true, + &beaconParams, + psessionEntry); + } + + if ((!psessionEntry->gLimOverlap11gParams.numSta) && + (psessionEntry->gLimOverlap11gParams.protectionEnabled) + && (!psessionEntry->gLim11gParams.protectionEnabled)) { + lim_log(mac_ctx, LOG1, + FL("Overlap cache clear and no 11G STA set")); + lim_enable_ht_protection_from11g(mac_ctx, false, true, + &beaconParams, + psessionEntry); + } + + if ((!psessionEntry->gLimOverlapHt20Params.numSta) && + (psessionEntry->gLimOverlapHt20Params.protectionEnabled) + && (!psessionEntry->gLimHt20Params.protectionEnabled)) { + lim_log(mac_ctx, LOG1, + FL("Overlap cache clear and no HT20 STA set")); + lim_enable11g_protection(mac_ctx, false, true, + &beaconParams, + psessionEntry); + } + + enable = 0; + } + + if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) { + sch_set_fixed_beacon_fields(mac_ctx, psessionEntry); + lim_send_beacon_params(mac_ctx, &beaconParams, psessionEntry); + } + /* Start OLBC timer */ + if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimUpdateOlbcCacheTimer) + != TX_SUCCESS) + lim_log(mac_ctx, LOGE, FL("tx_timer_activate failed")); +} + +/** + * lim_is_null_ssid() - This function checks if ssid supplied is Null SSID + * @ssid: pointer to tSirMacSSid + * + * Function checks if ssid supplied is Null SSID + * + * Return: none + */ + +uint8_t lim_is_null_ssid(tSirMacSSid *ssid) +{ + uint8_t fnull_ssid = false; + uint32_t ssid_len; + uint8_t *ssid_str; + + if (0 == ssid->length) { + fnull_ssid = true; + return fnull_ssid; + } + /* If the first charactes is space, then check if all + * characters in SSID are spaces to consider it as NULL SSID + */ + if ((ASCII_SPACE_CHARACTER == ssid->ssId[0]) && + (ssid->length == 1)){ + fnull_ssid = true; + return fnull_ssid; + } else { + /* check if all the charactes in SSID are NULL */ + ssid_len = ssid->length; + ssid_str = ssid->ssId; + + while (ssid_len) { + if (*ssid_str) + return fnull_ssid; + + ssid_str++; + ssid_len--; + } + + if (0 == ssid_len) { + fnull_ssid = true; + return fnull_ssid; + } + } + + return fnull_ssid; +} + +/** ------------------------------------------------------------- + \fn lim_update_prot_sta_params + \brief updates protection related counters. + \param tpAniSirGlobal pMac + \param tSirMacAddr peerMacAddr + \param tLimProtStaCacheType protStaCacheType + \param tHalBitVal gfSupported + \param tHalBitVal lsigTxopSupported + \return None + -------------------------------------------------------------*/ +void +lim_update_prot_sta_params(tpAniSirGlobal pMac, + tSirMacAddr peerMacAddr, + tLimProtStaCacheType protStaCacheType, + tHalBitVal gfSupported, tHalBitVal lsigTxopSupported, + tpPESession psessionEntry) +{ + uint32_t i; + + PELOG1(lim_log(pMac, LOG1, FL("A STA is associated:")); + lim_log(pMac, LOG1, FL("Addr : ")); + lim_print_mac_addr(pMac, peerMacAddr, LOG1); + ) + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (psessionEntry->protStaCache[i].active) { + PELOG1(lim_log(pMac, LOG1, FL("Addr: "));) + PELOG1(lim_print_mac_addr + (pMac, psessionEntry->protStaCache[i].addr, + LOG1); + ) + + if (cdf_mem_compare + (psessionEntry->protStaCache[i].addr, + peerMacAddr, sizeof(tSirMacAddr))) { + PELOG1(lim_log + (pMac, LOG1, + FL + ("matching cache entry at %d already active."), + i); + ) + return; + } + } + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (!psessionEntry->protStaCache[i].active) + break; + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + PELOGE(lim_log(pMac, LOGE, FL("No space in ProtStaCache"));) + return; + } + + cdf_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++; + lim_log(pMac, LOG1, FL("11B, ")); + } else if (eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) { + psessionEntry->gLim11gParams.numSta++; + lim_log(pMac, LOG1, FL("11G, ")); + } else if (eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType) { + psessionEntry->gLimHt20Params.numSta++; + lim_log(pMac, LOG1, FL("HT20, ")); + } + + if (!gfSupported) { + psessionEntry->gLimNonGfParams.numSta++; + lim_log(pMac, LOG1, FL("NonGf, ")); + } + if (!lsigTxopSupported) { + psessionEntry->gLimLsigTxopParams.numSta++; + lim_log(pMac, LOG1, FL("!lsigTxopSupported")); + } +} /* --------------------------------------------------------------------- */ + +/** ------------------------------------------------------------- + \fn lim_decide_ap_protection + \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 +lim_decide_ap_protection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + uint16_t tmpAid; + tpDphHashNode pStaDs; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + uint32_t 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 = + dph_lookup_hash_entry(pMac, peerMacAddr, &tmpAid, + &psessionEntry->dph.dphHashTable); + if (NULL == pStaDs) { + PELOG1(lim_log(pMac, LOG1, FL("pStaDs is NULL"));) + return; + } + lim_get_rf_band_new(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) { + lim_update_11a_protection(pMac, true, false, + pBeaconParams, + psessionEntry); + return; + } + } + } else if (SIR_BAND_2_4_GHZ == rfBand) { + lim_get_phy_mode(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(lim_log + (pMac, LOG3, + FL("Enabling protection from 11B")); + ) + lim_enable11g_protection(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(lim_log + (pMac, LOG3, + FL("Enabling protection from 11B")); + ) + lim_enable11g_protection(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 */ + lim_enable_ht_protection_from11g(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) { + lim_enable_ht_non_gf_protection(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; + lim_enable_ht20_protection(pMac, true, false, + pBeaconParams, psessionEntry); + } + /* Station joining does not support LSIG TXOP Protection */ + if (!pStaDs->htLsigTXOPProtection) { + lim_enable_ht_lsig_txop_protection(pMac, false, false, + pBeaconParams, + psessionEntry); + lsigTxopSupported = eHAL_CLEAR; + } + } + + lim_update_prot_sta_params(pMac, peerMacAddr, protStaCacheType, + gfSupported, lsigTxopSupported, psessionEntry); + + return; +} + +/** ------------------------------------------------------------- + \fn lim_enable_overlap11g_protection + \brief wrapper function for setting overlap 11g protection. + \param tpAniSirGlobal pMac + \param tpUpdateBeaconParams pBeaconParams + \param tpSirMacMgmtHdr pMh + \return None + -------------------------------------------------------------*/ +void +lim_enable_overlap11g_protection(tpAniSirGlobal pMac, + tpUpdateBeaconParams pBeaconParams, + tpSirMacMgmtHdr pMh, tpPESession psessionEntry) +{ + lim_update_overlap_sta_param(pMac, pMh->bssId, + &(psessionEntry->gLimOlbcParams)); + + if (psessionEntry->gLimOlbcParams.numSta && + !psessionEntry->gLimOlbcParams.protectionEnabled) { + /* enable protection */ + PELOG1(lim_log(pMac, LOG1, FL("OLBC happens!!!"));) + lim_enable11g_protection(pMac, true, true, pBeaconParams, + psessionEntry); + } +} + +/** + * lim_update_short_preamble() - This function Updates short preamble + * @mac_ctx: pointer to Global MAC structure + * @peer_mac_addr: pointer to tSirMacAddr + * @pbeaconparams: pointer to tpUpdateBeaconParams + * @psession_entry: pointer to tpPESession + * + * Function Updates short preamble if needed when a new station joins + * + * Return: none + */ +void +lim_update_short_preamble(tpAniSirGlobal mac_ctx, tSirMacAddr peer_mac_addr, + tpUpdateBeaconParams beaconparams, + tpPESession psession_entry) +{ + uint16_t aid; + tpDphHashNode sta_ds; + uint32_t phy_mode; + uint16_t i; + + /* check whether to enable protection or not */ + sta_ds = + dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid, + &psession_entry->dph.dphHashTable); + + lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry); + + if (sta_ds == NULL || phy_mode != WNI_CFG_PHY_MODE_11G) + return; + + if (sta_ds->shortPreambleEnabled != eHAL_CLEAR) + return; + + lim_log(mac_ctx, LOG1, + FL("Short Preamble is not enabled in Assoc Req from ")); + + lim_print_mac_addr(mac_ctx, peer_mac_addr, LOG1); + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(psession_entry) && + (psession_entry->gLimNoShortParams. + staNoShortCache[i].active) && + (cdf_mem_compare + (psession_entry->gLimNoShortParams. + staNoShortCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr)))) + return; + else if (!LIM_IS_AP_ROLE(psession_entry) && + (mac_ctx->lim.gLimNoShortParams. + staNoShortCache[i].active) && + (cdf_mem_compare(mac_ctx->lim.gLimNoShortParams. + staNoShortCache[i].addr, + peer_mac_addr, + sizeof(tSirMacAddr)))) + return; + } + + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(psession_entry) && + !psession_entry->gLimNoShortParams. + staNoShortCache[i].active) + break; + else if (!mac_ctx->lim.gLimNoShortParams. + staNoShortCache[i].active) + break; + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + tLimNoShortParams *lim_params = + &psession_entry->gLimNoShortParams; + if (LIM_IS_AP_ROLE(psession_entry)) { + lim_log(mac_ctx, LOGE, + FL("No space in Short cache (#active %d, #sta %d) for sta "), + i, + lim_params->numNonShortPreambleSta); + lim_print_mac_addr(mac_ctx, peer_mac_addr, LOGE); + return; + } else { + lim_log(mac_ctx, LOGE, + FL("No space in Short cache (#active %d, #sta %d) for sta "), + i, + lim_params->numNonShortPreambleSta); + lim_print_mac_addr(mac_ctx, peer_mac_addr, LOGE); + return; + } + + } + + if (LIM_IS_AP_ROLE(psession_entry)) { + cdf_mem_copy(psession_entry->gLimNoShortParams. + staNoShortCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr)); + psession_entry->gLimNoShortParams.staNoShortCache[i]. + active = true; + psession_entry->gLimNoShortParams.numNonShortPreambleSta++; + } else { + cdf_mem_copy(mac_ctx->lim.gLimNoShortParams. + staNoShortCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr)); + mac_ctx->lim.gLimNoShortParams.staNoShortCache[i].active = true; + mac_ctx->lim.gLimNoShortParams.numNonShortPreambleSta++; + } + + /* enable long preamble */ + lim_log(mac_ctx, LOG1, FL("Disabling short preamble")); + + if (lim_enable_short_preamble(mac_ctx, false, beaconparams, + psession_entry) != eSIR_SUCCESS) + lim_log(mac_ctx, LOGE, FL("Cannot enable long preamble")); +} + +/** + * lim_update_short_slot_time() - This function Updates short slot time + * @mac_ctx: pointer to Global MAC structure + * @peer_mac_addr: pointer to tSirMacAddr + * @beaconparams: pointer to tpUpdateBeaconParams + * @psession_entry: pointer to tpPESession + * + * Function Updates short slot time if needed when a new station joins + * + * Return: None + */ +void +lim_update_short_slot_time(tpAniSirGlobal mac_ctx, tSirMacAddr peer_mac_addr, + tpUpdateBeaconParams beaconparams, + tpPESession session_entry) +{ + uint16_t aid; + tpDphHashNode sta_ds; + uint32_t phy_mode; + uint32_t val; + uint16_t i; + + /* check whether to enable protection or not */ + sta_ds = + dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid, + &session_entry->dph.dphHashTable); + lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); + + if (sta_ds == NULL || phy_mode != WNI_CFG_PHY_MODE_11G) + return; + + /* + * 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. + * 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 lim_decide_short_slot + */ + if (sta_ds->shortSlotTimeEnabled == eHAL_CLEAR) { + lim_log(mac_ctx, LOG1, + FL("Short Slot Time is not enabled in Assoc Req from ")); + lim_print_mac_addr(mac_ctx, peer_mac_addr, LOG1); + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(session_entry) && + session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].active) { + if (cdf_mem_compare( + session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr))) + return; + } else if (!LIM_IS_AP_ROLE(session_entry)) { + if (mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].active) { + if (cdf_mem_compare(mac_ctx->lim. + gLimNoShortSlotParams. + staNoShortSlotCache[i]. + addr, peer_mac_addr, + sizeof(tSirMacAddr))) + return; + } + } + } + for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { + if (LIM_IS_AP_ROLE(session_entry) && + !session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].active) + break; + else { + if (!mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].active) + break; + } + } + + if (i >= LIM_PROT_STA_CACHE_SIZE) { + if (LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOGE, + FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "), + i, + session_entry->gLimNoShortSlotParams. + numNonShortSlotSta); + lim_print_mac_addr(mac_ctx, peer_mac_addr, + LOGE); + return; + } else { + lim_log(mac_ctx, LOGE, + FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "), + i, + mac_ctx->lim.gLimNoShortSlotParams. + numNonShortSlotSta); + lim_print_mac_addr(mac_ctx, peer_mac_addr, + LOGE); + return; + } + } + + if (LIM_IS_AP_ROLE(session_entry)) { + cdf_mem_copy(session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr)); + session_entry->gLimNoShortSlotParams. + staNoShortSlotCache[i].active = true; + session_entry->gLimNoShortSlotParams. + numNonShortSlotSta++; + } else { + cdf_mem_copy(mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].addr, + peer_mac_addr, sizeof(tSirMacAddr)); + mac_ctx->lim.gLimNoShortSlotParams. + staNoShortSlotCache[i].active = true; + mac_ctx->lim.gLimNoShortSlotParams. + numNonShortSlotSta++; + } + wlan_cfg_get_int(mac_ctx, + 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(session_entry)) && (val && + session_entry->gLimNoShortSlotParams.numNonShortSlotSta + && session_entry->shortSlotTimeSupported)) { + /* enable long slot time */ + beaconparams->fShortSlotTime = false; + beaconparams->paramChangeBitmap |= + PARAM_SHORT_SLOT_TIME_CHANGED; + lim_log(mac_ctx, LOG1, + FL("Disable short slot time. Enable long slot time.")); + session_entry->shortSlotTimeSupported = false; + } else if (!LIM_IS_AP_ROLE(session_entry) && + (val && mac_ctx->lim.gLimNoShortSlotParams. + numNonShortSlotSta && + session_entry->shortSlotTimeSupported)) { + /* enable long slot time */ + beaconparams->fShortSlotTime = false; + beaconparams->paramChangeBitmap |= + PARAM_SHORT_SLOT_TIME_CHANGED; + lim_log(mac_ctx, LOG1, + FL("Disable short slot time. Enable long slot time.")); + session_entry->shortSlotTimeSupported = + false; + } + } +} + +/** ------------------------------------------------------------- + \fn lim_decide_sta_protection_on_assoc + \brief Decide protection related settings on Sta while association. + \param tpAniSirGlobal pMac + \param tpSchBeaconStruct pBeaconStruct + \return None + -------------------------------------------------------------*/ +void +lim_decide_sta_protection_on_assoc(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeaconStruct, + tpPESession psessionEntry) +{ + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + uint32_t phyMode = WNI_CFG_PHY_MODE_NONE; + + lim_get_rf_band_new(pMac, &rfBand, psessionEntry); + lim_get_phy_mode(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 = + (uint8_t) 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 = + (uint8_t) htInfo.rifsMode; + psessionEntry->beaconParams.llnNonGFCoexist = + (uint8_t) htInfo.nonGFDevicesPresent; + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = + (uint8_t) htInfo.lsigTXOPProtectionFullSupport; + } +} + + +/** + * lim_decide_sta_11bg_protection() - decides protection related settings on sta + * @mac_ctx: pointer to global mac structure + * @beacon_struct: pointer to tpschbeaconstruct + * @beaconparams: pointer to tpupdatebeaconparams + * @psession_entry: pointer to tppesession + * @phy_mode: phy mode index + * + * decides 11bg protection related settings on sta while processing beacon + * + * Return: none + */ +static void +lim_decide_sta_11bg_protection(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct beacon_struct, + tpUpdateBeaconParams beaconparams, + tpPESession psession_entry, + uint32_t phy_mode) +{ + + tDot11fIEHTInfo htInfo; + + /* + * 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 (phy_mode != WNI_CFG_PHY_MODE_11B) { + if (beacon_struct->erpPresent && + (beacon_struct->erpIEInfo.useProtection || + beacon_struct->erpIEInfo.nonErpPresent)) { + lim_enable11g_protection(mac_ctx, true, false, + beaconparams, + psession_entry); + } + /* AP has no 11b station associated. */ + else { + /* disable protection from 11b station */ + lim_enable11g_protection(mac_ctx, false, false, + beaconparams, + psession_entry); + } + } + + if (!(psession_entry->htCapability) || + !(beacon_struct->HTInfo.present)) + return; + + /* following code is only for HT station. */ + + htInfo = beacon_struct->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)) && + (!psession_entry->beaconParams.llbCoexist)) { + lim_enable_ht_protection_from11g(mac_ctx, true, false, + beaconparams, psession_entry); + + } + /* + * 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. Hence this + * check is being done after mixed/legacy mode + * check. + */ + if (mac_ctx->lim.gHTOperMode != + (tSirMacHTOperatingMode)htInfo.opMode) { + mac_ctx->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. */ + lim_enable_ht_protection_from11g(mac_ctx, false, + false, beaconparams, + psession_entry); + + lim_enable_ht20_protection(mac_ctx, true, false, + beaconparams, + psession_entry); + } + /* + * 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) { + lim_enable_ht_protection_from11g(mac_ctx, false, + false, beaconparams, + psession_entry); + + lim_enable_ht20_protection(mac_ctx, false, + false, beaconparams, + psession_entry); + + } + } + +} + +/** + * lim_decide_sta_protection() - decides protection related settings on sta + * @mac_ctx: pointer to global mac structure + * @beacon_struct: pointer to tpschbeaconstruct + * @beaconparams: pointer to tpupdatebeaconparams + * @psession_entry: pointer to tppesession + * + * decides protection related settings on sta while processing beacon + * + * Return: none + */ +void +lim_decide_sta_protection(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct beacon_struct, + tpUpdateBeaconParams beaconparams, + tpPESession psession_entry) +{ + + tSirRFBand rfband = SIR_BAND_UNKNOWN; + uint32_t phy_mode = WNI_CFG_PHY_MODE_NONE; + + lim_get_rf_band_new(mac_ctx, &rfband, psession_entry); + lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry); + + if ((SIR_BAND_5_GHZ == rfband) && + /* we are HT capable. */ + (true == psession_entry->htCapability) && + (beacon_struct->HTInfo.present)) { + /* + * we are HT capable, AP's HT OPMode is + * mixed / overlap legacy ==> need protection + * from 11A. + */ + if ((eSIR_HT_OP_MODE_MIXED == + beacon_struct->HTInfo.opMode) || + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + beacon_struct->HTInfo.opMode)) { + lim_update_11a_protection(mac_ctx, true, false, + beaconparams, psession_entry); + } + /* + * we are HT capable, AP's HT OPMode is + * HT20 ==> disable protection from 11A if + * enabled. + */ + /* protection from HT20 if needed. */ + else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == + beacon_struct->HTInfo.opMode) { + lim_update_11a_protection(mac_ctx, false, false, + beaconparams, psession_entry); + lim_enable_ht20_protection(mac_ctx, true, false, + beaconparams, psession_entry); + } else if (eSIR_HT_OP_MODE_PURE == + beacon_struct->HTInfo.opMode) { + lim_update_11a_protection(mac_ctx, false, false, + beaconparams, psession_entry); + lim_enable_ht20_protection(mac_ctx, false, + false, beaconparams, + psession_entry); + } + } else if (SIR_BAND_2_4_GHZ == rfband) { + lim_decide_sta_11bg_protection(mac_ctx, beacon_struct, + beaconparams, psession_entry, phy_mode); + } + /* + * following code block is only for HT station. + * (2.4 GHZ as well as 5 GHZ) + */ + if ((psession_entry->htCapability) && (beacon_struct->HTInfo.present)) { + tDot11fIEHTInfo htInfo = beacon_struct->HTInfo; + /* + * Check for changes in protection related factors other + * than HT operating mode. + */ + /* + * Check for changes in RIFS mode, nonGFDevicesPresent, + * lsigTXOPProtectionFullSupport. + */ + if (psession_entry->beaconParams.fRIFSMode != + (uint8_t) htInfo.rifsMode) { + beaconparams->fRIFSMode = + psession_entry->beaconParams.fRIFSMode = + (uint8_t) htInfo.rifsMode; + beaconparams->paramChangeBitmap |= + PARAM_RIFS_MODE_CHANGED; + } + + if (psession_entry->beaconParams.llnNonGFCoexist != + htInfo.nonGFDevicesPresent) { + beaconparams->llnNonGFCoexist = + psession_entry->beaconParams.llnNonGFCoexist = + (uint8_t) htInfo.nonGFDevicesPresent; + beaconparams->paramChangeBitmap |= + PARAM_NON_GF_DEVICES_PRESENT_CHANGED; + } + + if (psession_entry->beaconParams. + fLsigTXOPProtectionFullSupport != + (uint8_t) htInfo.lsigTXOPProtectionFullSupport) { + beaconparams->fLsigTXOPProtectionFullSupport = + psession_entry->beaconParams. + fLsigTXOPProtectionFullSupport = + (uint8_t) htInfo. + lsigTXOPProtectionFullSupport; + beaconparams->paramChangeBitmap |= + PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; + } + /* + * For Station just update the global lim variable, + * no need to send message to HAL since Station already + * taking care of HT OPR Mode=01, + * meaning AP is seeing legacy + */ + /* stations in overlapping BSS. */ + if (psession_entry->beaconParams.gHTObssMode != + (uint8_t) htInfo.obssNonHTStaPresent) + psession_entry->beaconParams.gHTObssMode = + (uint8_t) htInfo.obssNonHTStaPresent; + + } +} + +/** + * lim_process_channel_switch_timeout() + * + ***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 lim_process_channel_switch_timeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry = NULL; + uint8_t channel; /* This is received and stored from channelSwitch Action frame */ + + psessionEntry = pe_find_session_by_session_id(pMac, + pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } + + if (!LIM_IS_STA_ROLE(psessionEntry)) { + PELOGW(lim_log + (pMac, LOGW, + "Channel switch can be done only in STA role, Current Role = %d", + GET_LIM_SYSTEM_ROLE(psessionEntry)); + ) + return; + } + + channel = psessionEntry->gLimChannelSwitch.primaryChannel; + /* 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; + + /* 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 (!lim_is_channel_valid_for_channel_switch(pMac, channel)) { + /* We need to restore pre-channelSwitch state on the STA */ + if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) != + eSIR_SUCCESS) { + lim_log(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 !!! + */ + lim_tear_down_link_with_ap(pMac, + pMac->lim.limTimers. + gLimChannelSwitchTimer.sessionId, + eSIR_MAC_UNSPEC_FAILURE_REASON); + return; + } + lim_covert_channel_scan_type(pMac, psessionEntry->currentOperChannel, + false); + pMac->lim.dfschannelList.timeStamp[psessionEntry->currentOperChannel] = + 0; + switch (psessionEntry->gLimChannelSwitch.state) { + case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY: + PELOGW(lim_log(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));) + lim_switch_primary_channel(pMac, + psessionEntry->gLimChannelSwitch. + primaryChannel, psessionEntry); + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_IDLE; + break; + case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: + PELOGW(lim_log + (pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY")); + ) + lim_switch_primary_secondary_channel(pMac, psessionEntry, + psessionEntry->gLimChannelSwitch.primaryChannel, + psessionEntry->gLimChannelSwitch.ch_center_freq_seg0, + psessionEntry->gLimChannelSwitch.ch_center_freq_seg1, + psessionEntry->gLimChannelSwitch.ch_width); + psessionEntry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_IDLE; + break; + + case eLIM_CHANNEL_SWITCH_IDLE: + default: + PELOGE(lim_log(pMac, LOGE, FL("incorrect state "));) + if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("Could not restore pre-channelSwitch (11h) state, resetting the system")); + } + return; /* Please note, this is 'return' and not 'break' */ + } +} + +/** + * lim_update_channel_switch() - This Function updates channel switch + * @mac_ctx: pointer to Global MAC structure + * @beacon: pointer to tpSirProbeRespBeacon + * @psessionentry: pointer to tpPESession + * + * This function is invoked whenever Station receives + * either 802.11h channel switch IE or airgo proprietary + * channel switch IE. + * + * Return: none + */ +void +lim_update_channel_switch(struct sAniSirGlobal *mac_ctx, + tpSirProbeRespBeacon beacon, + tpPESession psession_entry) +{ + uint16_t beacon_period; + tDot11fIEChanSwitchAnn *chnl_switch; + tLimChannelSwitchInfo *ch_switch_params; +#ifdef WLAN_FEATURE_11AC + tDot11fIEWiderBWChanSwitchAnn *widerchnl_switch; +#endif + + beacon_period = psession_entry->beaconParams.beaconInterval; + + /* 802.11h standard channel switch IE */ + chnl_switch = &(beacon->channelSwitchIE); + ch_switch_params = &psession_entry->gLimChannelSwitch; + ch_switch_params->primaryChannel = + chnl_switch->newChannel; + ch_switch_params->switchCount = chnl_switch->switchCount; + ch_switch_params->switchTimeoutValue = + SYS_MS_TO_TICKS(beacon_period) * (chnl_switch->switchCount); + ch_switch_params->switchMode = chnl_switch->switchMode; +#ifdef WLAN_FEATURE_11AC + widerchnl_switch = &(beacon->WiderBWChanSwitchAnn); + if (beacon->WiderBWChanSwitchAnnPresent) { + psession_entry->gLimWiderBWChannelSwitch.newChanWidth = + widerchnl_switch->newChanWidth; + psession_entry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = + widerchnl_switch->newCenterChanFreq0; + psession_entry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = + widerchnl_switch->newCenterChanFreq1; + } +#endif + + /* Only primary channel switch element is present */ + ch_switch_params->state = + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + ch_switch_params->ch_width = CH_WIDTH_20MHZ; + + /* + * Do not bother to look and operate on extended channel switch element + * if our own channel-bonding state is not enabled + */ + if (psession_entry->htSupportedChannelWidthSet && + beacon->sec_chan_offset_present) { + if (beacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + ch_switch_params->state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + ch_switch_params->ch_width = CH_WIDTH_40MHZ; + ch_switch_params->ch_center_freq_seg0 = + ch_switch_params->primaryChannel + 2; + } else if (beacon->sec_chan_offset.secondaryChannelOffset == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) { + ch_switch_params->state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + ch_switch_params->ch_width = CH_WIDTH_40MHZ; + ch_switch_params->ch_center_freq_seg0 = + ch_switch_params->primaryChannel - 2; + } +#ifdef WLAN_FEATURE_11AC + if (psession_entry->vhtCapability && + beacon->WiderBWChanSwitchAnnPresent) { + ch_switch_params->ch_width = + widerchnl_switch->newChanWidth + 1; + ch_switch_params->ch_center_freq_seg0 = + psession_entry->gLimWiderBWChannelSwitch. + newCenterChanFreq0; + ch_switch_params->ch_center_freq_seg1 = + psession_entry->gLimWiderBWChannelSwitch. + newCenterChanFreq1; +#endif + } + } + if (eSIR_SUCCESS != lim_start_channel_switch(mac_ctx, psession_entry)) + lim_log(mac_ctx, LOGW, FL("Could not start Channel Switch")); + + lim_log(mac_ctx, LOGW, + FL("session %d primary chl %d, ch_width %d, count %d (%d ticks)"), + psession_entry->peSessionId, + psession_entry->gLimChannelSwitch.primaryChannel, + psession_entry->gLimChannelSwitch.ch_width, + psession_entry->gLimChannelSwitch.switchCount, + psession_entry->gLimChannelSwitch.switchTimeoutValue); + return; +} + +/** + * lim_cancel_dot11h_channel_switch + * + ***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 lim_cancel_dot11h_channel_switch(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + PELOGW(lim_log + (pMac, LOGW, FL("Received a beacon without channel switch IE")); + ) + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, + psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER)); + + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != + eSIR_SUCCESS) { + PELOGE(lim_log(pMac, LOGE, FL("tx_timer_deactivate failed!"));) + } + + /* We need to restore pre-channelSwitch state on the STA */ + if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) != + eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL + ("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system")); + ) + + } +} + +/** + * lim_cancel_dot11h_quiet() + * + * @mac_ctx: pointer to global mac structure + * @psession_entry: pointer to tppesession + * + * Cancel the quieting on Station if latest beacon + * doesn't contain quiet IE in it. + * + * Return: none + */ +void lim_cancel_dot11h_quiet(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (!LIM_IS_STA_ROLE(psessionEntry)) + return; + + if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) { + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, + psessionEntry->peSessionId, eLIM_QUIET_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != + TX_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("tx_timer_deactivate failed")); + ) + } + } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) { + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_DEACTIVATE, + psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) + != TX_SUCCESS) { + PELOGE(lim_log + (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))) { + lim_frame_transmission_control(pMac, eLIM_TX_ALL, + eLIM_RESUME_TX); + lim_restore_pre_quiet_state(pMac, psessionEntry); + } + } + psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; +} + +/** + * lim_process_quiet_timeout + * + * 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 lim_process_quiet_timeout(tpAniSirGlobal pMac) +{ + tpPESession psessionEntry; + + psessionEntry = pe_find_session_by_session_id(pMac, + pMac->lim.limTimers.gLimQuietTimer.sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session Does not exist for given sessionID")); + return; + } + + PELOG1(lim_log + (pMac, LOG1, FL("quietState = %d"), + psessionEntry->gLimSpecMgmt.quietState); + ) + switch (psessionEntry->gLimSpecMgmt.quietState) { + case eLIM_QUIET_BEGIN: + /* Time to Stop data traffic for quietDuration */ + /* lim_deactivate_and_change_timer(pMac, eLIM_QUIET_BSS_TIMER); */ + if (TX_SUCCESS != tx_timer_deactivate( + &pMac->lim.limTimers.gLimQuietBssTimer)) { + lim_log(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)) { + lim_log(pMac, LOGE, + FL + ("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); + } + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_ACTIVATE, + pMac->lim.limTimers.gLimQuietTimer.sessionId, + eLIM_QUIET_BSS_TIMER)); + if (TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers.gLimQuietBssTimer)) { + lim_log(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; + /* Shut-off Tx/Rx for gLimSpecMgmt.quietDuration */ + /* freeze the transmission */ + lim_frame_transmission_control(pMac, eLIM_TX_ALL, + eLIM_STOP_TX); + + lim_log(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; + } +} + +/** + * lim_process_quiet_bss_timeout() - Handles SIR_LIM_QUIET_BSS_TIMEOUT + * @mac_ctx: pointer to Globale Mac Structure + * + * This function is active on the AP and STA. + * Handles SIR_LIM_QUIET_BSS_TIMEOUT + * + * 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. This will be understood by all the + * TITAN STA's + * 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 + * + * + * Return: none + */ +void lim_process_quiet_bss_timeout(tpAniSirGlobal mac_ctx) +{ + tpPESession psession_entry = NULL; + tLimTimers *lim_timer = &mac_ctx->lim.limTimers; + + psession_entry = pe_find_session_by_session_id(mac_ctx, + lim_timer->gLimQuietBssTimer.sessionId); + + if (psession_entry == NULL) { + lim_log(mac_ctx, LOGP, + FL("Session Does not exist for given sessionID")); + return; + } + + lim_log(mac_ctx, LOG1, FL("quietState = %d"), + psession_entry->gLimSpecMgmt.quietState); + + if (LIM_IS_AP_ROLE(psession_entry)) + return; + + /* eLIM_STA_ROLE */ + switch (psession_entry->gLimSpecMgmt.quietState) { + case eLIM_QUIET_RUNNING: + /* Transition to eLIM_QUIET_INIT */ + psession_entry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + + /* + * Resume data traffic only if channel switch is + * not running in silent mode. + */ + if (!((psession_entry->gLimSpecMgmt.dot11hChanSwState == + eLIM_11H_CHANSW_RUNNING) && + (psession_entry->gLimChannelSwitch.switchMode == + eSIR_CHANSW_MODE_SILENT))) { + lim_frame_transmission_control(mac_ctx, eLIM_TX_ALL, + eLIM_RESUME_TX); + lim_restore_pre_quiet_state(mac_ctx, psession_entry); + } + lim_log(mac_ctx, LOG2, FL("Quiet BSS: Resuming traffic...")); + break; + + case eLIM_QUIET_INIT: + case eLIM_QUIET_BEGIN: + case eLIM_QUIET_END: + lim_log(mac_ctx, LOG2, FL("Quiet state not in RUNNING")); + /* + * If the quiet period has ended, then resume the + * frame transmission + */ + lim_frame_transmission_control(mac_ctx, eLIM_TX_ALL, + eLIM_RESUME_TX); + lim_restore_pre_quiet_state(mac_ctx, psession_entry); + psession_entry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; + break; + + default: + /* As of now, nothing to be done */ + break; + } +} + +/**---------------------------------------------- + \fn lim_start_quiet_timer + \brief Starts the quiet timer. + + \param pMac + \return NONE + -----------------------------------------------*/ +void lim_start_quiet_timer(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tpPESession psessionEntry; + psessionEntry = pe_find_session_by_session_id(pMac, sessionId); + + if (psessionEntry == NULL) { + lim_log(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 */ + lim_cancel_dot11h_quiet(pMac, psessionEntry); + + MTRACE(mac_trace + (pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_QUIET_TIMER)); + if (TX_SUCCESS != + tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) { + lim_log(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)) { + lim_log(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)) { + lim_log(pMac, LOGE, + FL + ("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!")); + lim_restore_pre_quiet_state(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 notfiy SCH + */ +void +lim_util_count_sta_add(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 */ + sch_edca_profile_update(pMac, psessionEntry); +} + +void +lim_util_count_sta_del(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) { + lim_log(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 */ + sch_edca_profile_update(pMac, psessionEntry); +} + +/** + * lim_switch_channel_cback() + * + ***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 lim_switch_channel_cback(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry) +{ + tSirMsgQ mmhMsg = { 0 }; + tSirSmeSwitchChannelInd *pSirSmeSwitchChInd; + + psessionEntry->currentOperChannel = psessionEntry->currentReqChannel; + + /* We need to restore pre-channelSwitch state on the STA */ + if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("Could not restore pre-channelSwitch (11h) state, resetting the system")); + return; + } + + mmhMsg.type = eWNI_SME_SWITCH_CHL_IND; + pSirSmeSwitchChInd = cdf_mem_malloc(sizeof(tSirSmeSwitchChannelInd)); + if (NULL == pSirSmeSwitchChInd) { + lim_log(pMac, LOGP, + FL("Failed to allocate buffer for buffer descriptor")); + return; + } + + pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_IND; + pSirSmeSwitchChInd->length = sizeof(tSirSmeSwitchChannelInd); + pSirSmeSwitchChInd->newChannelId = + psessionEntry->gLimChannelSwitch.primaryChannel; + pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId; + cdf_mem_copy(pSirSmeSwitchChInd->bssId, psessionEntry->bssId, + sizeof(tSirMacAddr)); + mmhMsg.bodyptr = pSirSmeSwitchChInd; + mmhMsg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type)); + + sys_process_mmh_msg(pMac, &mmhMsg); +} + +/** + * lim_switch_primary_channel() + * + ***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 chnannel ID + * @return NONE + */ +void lim_switch_primary_channel(tpAniSirGlobal pMac, uint8_t newChannel, + tpPESession psessionEntry) +{ +#if !defined WLAN_FEATURE_VOWIFI + uint32_t localPwrConstraint; +#endif + + PELOG3(lim_log + (pMac, LOG3, + FL("lim_switch_primary_channel: old chnl %d --> new chnl %d "), + psessionEntry->currentOperChannel, newChannel); + ) + psessionEntry->currentReqChannel = newChannel; + psessionEntry->limRFBand = lim_get_rf_band(newChannel); + + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; + + pMac->lim.gpchangeChannelCallback = lim_switch_channel_cback; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + lim_send_switch_chnl_params(pMac, newChannel, 0, 0, CH_WIDTH_20MHZ, + psessionEntry->maxTxPower, + psessionEntry->peSessionId, false); +#else + if (wlan_cfg_get_int + (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, + &localPwrConstraint) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to read Local Power Constraint from cfg")); + return; + } + lim_send_switch_chnl_params(pMac, newChannel, 0, 0, CH_WIDTH_20MHZ, + (tPowerdBm) localPwrConstraint, + psessionEntry->peSessionId, false); +#endif + return; +} + +/** + * lim_switch_primary_secondary_channel() + * + ***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 chnannel 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 lim_switch_primary_secondary_channel(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint8_t newChannel, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width) +{ +#if !defined WLAN_FEATURE_VOWIFI + uint32_t localPwrConstraint; +#endif + uint8_t subband = 0; +#if !defined WLAN_FEATURE_VOWIFI + if (wlan_cfg_get_int + (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, + &localPwrConstraint) != eSIR_SUCCESS) { + lim_log(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 = lim_get_rf_band(newChannel); + psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; + pMac->lim.gpchangeChannelCallback = lim_switch_channel_cback; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + lim_send_switch_chnl_params(pMac, newChannel, ch_center_freq_seg0, + ch_center_freq_seg1, ch_width, + psessionEntry->maxTxPower, + psessionEntry->peSessionId, + false); +#else + lim_send_switch_chnl_params(pMac, newChannel, ch_center_freq_seg0, + ch_center_freq_seg1, ch_width, + psessionEntry->peSessionId, + false); +#endif + + /* Store the new primary and secondary channel in session entries if different */ + if (psessionEntry->currentOperChannel != newChannel) { + lim_log(pMac, LOGW, + FL("switch old chnl %d --> new chnl %d "), + psessionEntry->currentOperChannel, newChannel); + psessionEntry->currentOperChannel = newChannel; + } + if (psessionEntry->htSecondaryChannelOffset != subband) { + lim_log(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; +} + +/** + * lim_active_scan_allowed() + * + ***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 + */ + +uint8_t lim_active_scan_allowed(tpAniSirGlobal pMac, uint8_t channelNum) +{ + uint32_t i; + uint8_t channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN]; + uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + if (wlan_cfg_get_str(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len) + != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, FL("Unable to get scan control list")); + ) + return false; + } + + if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) { + lim_log(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; +} + +/** + * lim_get_ht_capability() + * + ***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 uint8_t The current state of the requested HT capability is returned in a + * uint8_t variable + */ + +uint8_t lim_get_ht_capability(tpAniSirGlobal pMac, + uint32_t htCap, tpPESession psessionEntry) +{ + uint8_t retVal = 0; + uint8_t *ptr; + uint32_t 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 Seletion HT Capabilities */ + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_AS_CAP, &cfgValue)) + cfgValue = 0; + ptr = (uint8_t *) &macASCapabilityInfo; + *((uint8_t *) ptr) = (uint8_t) (cfgValue & 0xff); + } else { + if (htCap >= eHT_TX_BEAMFORMING && + htCap < eHT_ANTENNA_SELECTION) { + /* Get Transmit Beam Forming HT Capabilities */ + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_TX_BF_CAP, &cfgValue)) + cfgValue = 0; + ptr = (uint8_t *) &macTxBFCapabilityInfo; + *((uint32_t *) ptr) = (uint32_t) (cfgValue); + } else { + if (htCap >= eHT_PCO && htCap < eHT_TX_BEAMFORMING) { + /* Get Extended HT Capabilities */ + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, + WNI_CFG_EXT_HT_CAP_INFO, + &cfgValue)) + cfgValue = 0; + ptr = (uint8_t *) &macExtHTCapabilityInfo; + *((uint16_t *) ptr) = + (uint16_t) (cfgValue & 0xffff); + } else { + if (htCap < eHT_MAX_RX_AMPDU_FACTOR) { + /* Get HT Capabilities */ + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, + WNI_CFG_HT_CAP_INFO, + &cfgValue)) + cfgValue = 0; + ptr = (uint8_t *) &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 = (uint8_t) 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 = (uint8_t) macHTCapabilityInfo.maximalAMSDUsize; + break; + + case eHT_RX_STBC: + retVal = (uint8_t) psessionEntry->htConfig.ht_rx_stbc; + break; + + case eHT_TX_STBC: + retVal = (uint8_t) psessionEntry->htConfig.ht_tx_stbc; + break; + + case eHT_SHORT_GI_40MHZ: + retVal = (uint8_t) + (psessionEntry->htConfig.ht_sgi) ? macHTCapabilityInfo. + shortGI40MHz : 0; + break; + + case eHT_SHORT_GI_20MHZ: + retVal = (uint8_t) + (psessionEntry->htConfig.ht_sgi) ? macHTCapabilityInfo. + shortGI20MHz : 0; + break; + + case eHT_GREENFIELD: + retVal = (uint8_t) macHTCapabilityInfo.greenField; + break; + + case eHT_MIMO_POWER_SAVE: + retVal = (uint8_t) pMac->lim.gHTMIMOPSState; + break; + + case eHT_SUPPORTED_CHANNEL_WIDTH_SET: + retVal = (uint8_t) psessionEntry->htSupportedChannelWidthSet; + break; + + case eHT_ADVANCED_CODING: + retVal = (uint8_t) 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 = (uint8_t) macExtHTCapabilityInfo.pco; + break; + + case eHT_TRANSITION_TIME: + retVal = (uint8_t) macExtHTCapabilityInfo.transitionTime; + break; + + case eHT_MCS_FEEDBACK: + retVal = (uint8_t) macExtHTCapabilityInfo.mcsFeedback; + break; + + case eHT_TX_BEAMFORMING: + retVal = (uint8_t) macTxBFCapabilityInfo.txBF; + break; + + case eHT_ANTENNA_SELECTION: + retVal = (uint8_t) 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; +} + +/** + * lim_enable_11a_protection() - updates protection params for enable 11a + * protection request + * @mac_ctx: pointer to Global MAC structure + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @bcn_prms: beacon parameters + * @pe_session: pe session entry + * + * This fucntion updates protection params for enable 11a protection request + * + * @Return: void + */ +static void +lim_enable_11a_protection(tpAniSirGlobal mac_ctx, + uint8_t overlap, + tpUpdateBeaconParams bcn_prms, + tpPESession pe_session) +{ + /* + * If we are AP and HT capable, we need to set the HT OP mode + * appropriately. + */ + if ((LIM_IS_AP_ROLE(pe_session) || LIM_IS_BT_AMP_AP_ROLE(pe_session)) + && (true == pe_session->htCapability)) { + if (overlap) { + mac_ctx->lim.gLimOverlap11aParams.protectionEnabled = + true; + if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != + mac_ctx->lim.gHTOperMode) + && (eSIR_HT_OP_MODE_MIXED != + mac_ctx->lim.gHTOperMode)) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + pe_session->htOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, bcn_prms, pe_session); + lim_enable_ht_obss_protection(mac_ctx, true, + overlap, bcn_prms, pe_session); + } + } else { + pe_session->gLim11aParams.protectionEnabled = true; + if (eSIR_HT_OP_MODE_MIXED != pe_session->htOperMode) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_MIXED; + pe_session->htOperMode = eSIR_HT_OP_MODE_MIXED; + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, bcn_prms, pe_session); + lim_enable_ht_obss_protection(mac_ctx, true, + overlap, bcn_prms, pe_session); + } + } + } + /* This part is common for station as well. */ + if (false == pe_session->beaconParams.llaCoexist) { + lim_log(mac_ctx, LOGW, + FL(" => protection from 11A Enabled")); + bcn_prms->llaCoexist = true; + pe_session->beaconParams.llaCoexist = true; + bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + } +} + +/** + * lim_disable_11a_protection() - updates protection params for disable 11a + * protection request + * @mac_ctx: pointer to Global MAC structure + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @bcn_prms: beacon parameters + * @pe_session: pe session entry + * + * This fucntion updates protection params for disable 11a protection request + * + * @Return: void + */ +static void +lim_disable_11a_protection(tpAniSirGlobal mac_ctx, + uint8_t overlap, + tpUpdateBeaconParams bcn_prms, + tpPESession pe_session) +{ + if (false == pe_session->beaconParams.llaCoexist) + return; + + /* for station role */ + if (!LIM_IS_AP_ROLE(pe_session)) { + lim_log(mac_ctx, LOGW, + FL("===> Protection from 11A Disabled")); + bcn_prms->llaCoexist = false; + pe_session->beaconParams.llaCoexist = false; + bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + return; + } + /* + * for AP role. + * we need to take care of HT OP mode change if needed. + * We need to take care of Overlap cases. + */ + if (overlap) { + /* Overlap Legacy protection disabled. */ + mac_ctx->lim.gLimOverlap11aParams.protectionEnabled = false; + + /* + * We need to take care of HT OP mode iff we are HT AP. + * OR no HT op-mode change is needed if any of the overlap + * protection enabled. + */ + if (!pe_session->htCapability || + (mac_ctx->lim.gLimOverlap11aParams.protectionEnabled + || mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled + || mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled)) + goto disable_11a_end; + + /* Check if there is a need to change HT OP mode. */ + if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + mac_ctx->lim.gHTOperMode) { + lim_enable_ht_rifs_protection(mac_ctx, false, overlap, + bcn_prms, pe_session); + lim_enable_ht_obss_protection(mac_ctx, false, overlap, + bcn_prms, pe_session); + + if (pe_session->gLimHt20Params.protectionEnabled) + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + else + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } else { + /* Disable protection from 11A stations. */ + pe_session->gLim11aParams.protectionEnabled = false; + lim_enable_ht_obss_protection(mac_ctx, false, overlap, + bcn_prms, pe_session); + + /* + * 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 (mac_ctx->lim.gLimOverlap11aParams.protectionEnabled + || mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled + || mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + pe_session->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_enable_ht_rifs_protection(mac_ctx, true, overlap, + bcn_prms, pe_session); + } else if (pe_session->gLimHt20Params.protectionEnabled) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + pe_session->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, false, overlap, + bcn_prms, pe_session); + } else { + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + pe_session->htOperMode = eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(mac_ctx, false, overlap, + bcn_prms, pe_session); + } + } + +disable_11a_end: + if (!mac_ctx->lim.gLimOverlap11aParams.protectionEnabled && + !pe_session->gLim11aParams.protectionEnabled) { + lim_log(mac_ctx, LOGW, + FL("===> Protection from 11A Disabled")); + bcn_prms->llaCoexist = false; + pe_session->beaconParams.llaCoexist = false; + bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; + } +} + +/** + * lim_update_11a_protection() - based on config setting enables\disables 11a + * protection. + * @mac_ctx: pointer to Global MAC structure + * @enable: 1=> enable protection, 0=> disable protection. + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @bcn_prms: beacon parameters + * @session: pe session entry + * + * This based on config setting enables\disables 11a protection. + * + * @Return: success of failure of operation + */ +tSirRetStatus +lim_update_11a_protection(tpAniSirGlobal mac_ctx, uint8_t enable, + uint8_t overlap, tpUpdateBeaconParams bcn_prms, + tpPESession session) +{ + if (NULL == session) { + lim_log(mac_ctx, LOGW, FL("session is NULL")); + return eSIR_FAILURE; + } + /* overlapping protection configuration check. */ + if (!overlap) { + /* normal protection config check */ + if ((LIM_IS_AP_ROLE(session)) && + (!session->cfgProtection.fromlla)) { + /* protection disabled. */ + lim_log(mac_ctx, LOGW, + FL("protection from 11a is disabled")); + return eSIR_SUCCESS; + } + } + + if (enable) + lim_enable_11a_protection(mac_ctx, overlap, bcn_prms, session); + else + lim_disable_11a_protection(mac_ctx, overlap, bcn_prms, session); + + return eSIR_SUCCESS; +} + +/** + * lim_handle_enable11g_protection_enabled() - handle 11g protection enabled + * @mac_ctx: pointer to Globale Mac structure + * @beaconparams: pointer to tpUpdateBeaconParams + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @session_entry: pointer to tpPESession + * + * Function handles 11g protection enaled case + * + * Return: none + */ +static void +lim_handle_enable11g_protection_enabled(tpAniSirGlobal mac_ctx, + tpUpdateBeaconParams beaconparams, + uint8_t overlap, tpPESession session_entry) +{ + /* + * If we are AP and HT capable, we need to set the HT OP mode + * appropriately. + */ + if (LIM_IS_AP_ROLE(session_entry) && overlap) { + session_entry->gLimOlbcParams.protectionEnabled = true; + + lim_log(mac_ctx, LOG1, FL("protection from olbc is enabled")); + + if (true == session_entry->htCapability) { + if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != + session_entry->htOperMode) && + (eSIR_HT_OP_MODE_MIXED != + session_entry->htOperMode)) { + session_entry->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 + */ + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + /* + * 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 + */ + lim_enable_ht_obss_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + } + } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { + session_entry->gLim11bParams.protectionEnabled = true; + lim_log(mac_ctx, LOG1, FL("protection from 11b is enabled")); + if (true == session_entry->htCapability) { + if (eSIR_HT_OP_MODE_MIXED != + session_entry->htOperMode) { + session_entry->htOperMode = + eSIR_HT_OP_MODE_MIXED; + lim_enable_ht_rifs_protection(mac_ctx, + true, overlap, beaconparams, + session_entry); + lim_enable_ht_obss_protection(mac_ctx, + true, overlap, beaconparams, + session_entry); + } + } + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && + (true == session_entry->htCapability) && overlap) { + session_entry->gLimOlbcParams.protectionEnabled = true; + if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != + mac_ctx->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != + mac_ctx->lim.gHTOperMode)) { + mac_ctx->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 + */ + lim_enable_ht_rifs_protection(mac_ctx, true, overlap, + beaconparams, session_entry); + /* + * 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 + */ + lim_enable_ht_obss_protection(mac_ctx, true, overlap, + beaconparams, session_entry); + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && + (true == session_entry->htCapability) && !overlap) { + session_entry->gLim11bParams.protectionEnabled = true; + if (eSIR_HT_OP_MODE_MIXED != + mac_ctx->lim.gHTOperMode) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_MIXED; + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + } + } + /* This part is common for staiton as well. */ + if (false == session_entry->beaconParams.llbCoexist) { + lim_log(mac_ctx, LOG1, FL("=> 11G Protection Enabled")); + beaconparams->llbCoexist = + session_entry->beaconParams.llbCoexist = true; + beaconparams->paramChangeBitmap |= + PARAM_llBCOEXIST_CHANGED; + } +} + +/** + * lim_handle_11g_protection_for_11bcoexist() - 11g protection for 11b co-ex + * @mac_ctx: pointer to Globale Mac structure + * @beaconparams: pointer to tpUpdateBeaconParams + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @session_entry: pointer to tpPESession + * + * Function handles 11g protection for 11b co-exist + * + * Return: none + */ +static void +lim_handle_11g_protection_for_11bcoexist(tpAniSirGlobal mac_ctx, + tpUpdateBeaconParams beaconparams, + uint8_t overlap, tpPESession session_entry) +{ + /* + * 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(session_entry) && overlap) { + /* Overlap Legacy protection disabled. */ + session_entry->gLimOlbcParams.protectionEnabled = false; + + /* We need to take care of HT OP mode if we are HT AP. */ + if (session_entry->htCapability) { + /* + * no HT op mode change if any of the overlap + * protection enabled. + */ + if (!(session_entry->gLimOverlap11gParams. + protectionEnabled || + session_entry->gLimOverlapHt20Params. + protectionEnabled || + session_entry->gLimOverlapNonGfParams. + protectionEnabled) && + /* + * Check if there is a need to change HT + * OP mode. + */ + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + session_entry->htOperMode)) { + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + if (session_entry->gLimHt20Params. + protectionEnabled) { + if(eHT_CHANNEL_WIDTH_20MHZ == + session_entry->htSupportedChannelWidthSet) + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + } else + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + } + } + } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { + /* Disable protection from 11B stations. */ + session_entry->gLim11bParams.protectionEnabled = false; + lim_log(mac_ctx, LOG1, FL("===> 11B Protection Disabled")); + /* Check if any other non-HT protection enabled. */ + if (!session_entry->gLim11gParams.protectionEnabled) { + /* Right now we are in HT OP Mixed mode. */ + /* Change HT op mode appropriately. */ + lim_enable_ht_obss_protection(mac_ctx, false, overlap, + beaconparams, session_entry); + /* + * Change HT OP mode to 01 if any overlap protection + * enabled + */ + if (session_entry->gLimOlbcParams.protectionEnabled || + session_entry->gLimOverlap11gParams. + protectionEnabled || + session_entry->gLimOverlapHt20Params. + protectionEnabled || + session_entry->gLimOverlapNonGfParams. + protectionEnabled) { + session_entry->htOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_log(mac_ctx, LOG1, + FL("===> 11G Protection Disabled")); + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, beaconparams, + session_entry); + } else if (session_entry->gLimHt20Params. + protectionEnabled) { + /* Commenting because of CR 258588 WFA cert */ + /* session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */ + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + lim_log(mac_ctx, LOG1, + FL("===> 11G Protection Disabled")); + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, + session_entry); + } else { + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, + session_entry); + } + } + } + if (LIM_IS_AP_ROLE(session_entry)) { + if (!session_entry->gLimOlbcParams.protectionEnabled && + !session_entry->gLim11bParams.protectionEnabled) { + lim_log(mac_ctx, LOG1, + FL("===> 11G Protection Disabled")); + beaconparams->llbCoexist = + session_entry->beaconParams.llbCoexist = + false; + beaconparams->paramChangeBitmap |= + PARAM_llBCOEXIST_CHANGED; + } + } + if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) { + /* Overlap Legacy protection disabled. */ + session_entry->gLimOlbcParams.protectionEnabled = false; + + /* We need to take care of HT OP mode iff we are HT AP. */ + if (session_entry->htCapability) { + /* + * no HT op mode change if any of the overlap protection + * enabled. + */ + if (!(mac_ctx->lim.gLimOverlap11gParams. + protectionEnabled || + mac_ctx->lim.gLimOverlapHt20Params. + protectionEnabled || + mac_ctx->lim.gLimOverlapNonGfParams. + protectionEnabled) && + /* + * Check if there is a need to change HT + * OP mode. + */ + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + mac_ctx->lim.gHTOperMode)) { + lim_enable_ht_rifs_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + lim_enable_ht_obss_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + if (session_entry->gLimHt20Params. + protectionEnabled) + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + else + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_PURE; + } + } + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) { + /* Disable protection from 11B stations. */ + session_entry->gLim11bParams.protectionEnabled = false; + /* Check if any other non-HT protection enabled. */ + if (!session_entry->gLim11gParams.protectionEnabled) { + /* Right now we are in HT OP Mixed mode. */ + /* Change HT op mode appropriately. */ + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + /* + * Change HT OP mode to 01 if any overlap protection + * enabled + */ + if (session_entry->gLimOlbcParams.protectionEnabled || + mac_ctx->lim.gLimOverlap11gParams. + protectionEnabled || + mac_ctx->lim.gLimOverlapHt20Params. + protectionEnabled || + mac_ctx->lim.gLimOverlapNonGfParams. + protectionEnabled) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_enable_ht_rifs_protection(mac_ctx, + true, overlap, beaconparams, + session_entry); + } else if (session_entry->gLimHt20Params. + protectionEnabled) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + } else { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + } + } + } + if (LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + if (!session_entry->gLimOlbcParams.protectionEnabled && + !session_entry->gLim11bParams.protectionEnabled) { + lim_log(mac_ctx, LOG1, + FL("===> 11G Protection Disabled")); + beaconparams->llbCoexist = + session_entry->beaconParams.llbCoexist = + false; + beaconparams->paramChangeBitmap |= + PARAM_llBCOEXIST_CHANGED; + } + } + /* For station role */ + if (!LIM_IS_AP_ROLE(session_entry) && + !LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOG1, FL("===> 11G Protection Disabled")); + beaconparams->llbCoexist = + session_entry->beaconParams.llbCoexist = false; + beaconparams->paramChangeBitmap |= + PARAM_llBCOEXIST_CHANGED; + } +} + +/** + * lim_enable11g_protection() - Function to enable 11g protection + * @mac_ctx: pointer to Global Mac structure + * @enable: 1=> enable protection, 0=> disable protection. + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @beaconparams: pointer to tpUpdateBeaconParams + * @session_entry: pointer to tpPESession + * + * based on config setting enables\disables 11g protection. + * + * Return: Success - eSIR_SUCCESS - Success, Error number - Failure + */ +tSirRetStatus +lim_enable11g_protection(tpAniSirGlobal mac_ctx, uint8_t enable, + uint8_t overlap, tpUpdateBeaconParams beaconparams, + tpPESession session_entry) +{ + + /* overlapping protection configuration check. */ + if (!overlap) { + /* normal protection config check */ + if ((LIM_IS_AP_ROLE(session_entry)) && + !session_entry->cfgProtection.fromllb) { + /* protection disabled. */ + lim_log(mac_ctx, LOG1, + FL("protection from 11b is disabled")); + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(session_entry)) { + if (!mac_ctx->lim.cfgProtection.fromllb) { + /* protection disabled. */ + lim_log(mac_ctx, LOG1, + FL("protection from 11b is disabled")); + return eSIR_SUCCESS; + } + } + } + + if (enable) { + lim_handle_enable11g_protection_enabled(mac_ctx, beaconparams, + overlap, session_entry); + } else if (true == session_entry->beaconParams.llbCoexist) { + lim_handle_11g_protection_for_11bcoexist(mac_ctx, beaconparams, + overlap, session_entry); + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_enable_ht_protection_from11g + \brief based on cofig enables\disables protection from 11g. + \param uint8_t enable : 1=> enable protection, 0=> disable protection. + \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +tSirRetStatus +lim_enable_ht_protection_from11g(tpAniSirGlobal pMac, uint8_t enable, + uint8_t 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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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; + } + lim_enable_ht_rifs_protection(pMac, true, overlap, + pBeaconParams, + psessionEntry); + lim_enable_ht_obss_protection(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; + lim_enable_ht_rifs_protection(pMac, true, + overlap, + pBeaconParams, + psessionEntry); + lim_enable_ht_obss_protection(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; + lim_enable_ht_rifs_protection(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; + lim_enable_ht_rifs_protection(pMac, true, + overlap, + pBeaconParams, + psessionEntry); + lim_enable_ht_obss_protection(pMac, true, + overlap, + pBeaconParams, + psessionEntry); + } + } + } + /* This part is common for staiton 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) { + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + lim_enable_ht_obss_protection(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. */ + lim_enable_ht_obss_protection(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; + lim_enable_ht_rifs_protection(pMac, + true, + overlap, + pBeaconParams, + psessionEntry); + } else if (psessionEntry-> + gLimHt20Params. + protectionEnabled) { + /* Commenting because of CR 258588 WFA cert */ + /* psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */ + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + } else { + psessionEntry->htOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + } + } + } + if (!psessionEntry->gLimOverlap11gParams. + protectionEnabled + && !psessionEntry->gLim11gParams. + protectionEnabled) { + PELOG1(lim_log + (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) { + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + lim_enable_ht_obss_protection(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. */ + lim_enable_ht_obss_protection(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; + lim_enable_ht_rifs_protection(pMac, + true, + overlap, + pBeaconParams, + psessionEntry); + } else if (psessionEntry-> + gLimHt20Params. + protectionEnabled) { + pMac->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + } else { + pMac->lim.gHTOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(pMac, + false, + overlap, + pBeaconParams, + psessionEntry); + } + } + } + if (!pMac->lim.gLimOverlap11gParams.protectionEnabled && + !psessionEntry->gLim11gParams.protectionEnabled) { + PELOG1(lim_log + (pMac, LOG1, + FL + ("===> Protection from 11G Disabled")); + ) + pBeaconParams->llgCoexist = + psessionEntry->beaconParams.llgCoexist = + false; + pBeaconParams->paramChangeBitmap |= + PARAM_llGCOEXIST_CHANGED; + } + } + /* for station role */ + else { + PELOG1(lim_log + (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 uint8_t enable : 1=> enable protection, 0=> disable protection. + \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +tSirRetStatus +lim_enable_ht_obss_protection(tpAniSirGlobal pMac, uint8_t enable, + uint8_t 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(lim_log + (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(lim_log + (pMac, LOG1, + FL("protection from Obss is disabled")); + ) + return eSIR_SUCCESS; + } + } + } + + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((enable) + && (false == psessionEntry->beaconParams.gHTObssMode)) { + PELOG1(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (pMac, LOG1, + FL("===> obss Protection disabled")); + ) + psessionEntry->beaconParams.gHTObssMode = false; + pBeaconParams->paramChangeBitmap |= + PARAM_OBSS_MODE_CHANGED; + + } + } + return eSIR_SUCCESS; +} + +/** + * lim_handle_ht20protection_enabled() - Handle ht20 protection enabled + * @mac_ctx: pointer to Gloal Mac Structure + * @overlap: variable for overlap detection + * @beaconparams: pointer to tpUpdateBeaconParams + * @session_entry: pointer to tpPESession + * + * Function handles ht20 protection enabled + * + * Return: none + */ +static void lim_handle_ht20protection_enabled(tpAniSirGlobal mac_ctx, + uint8_t overlap, tpUpdateBeaconParams beaconparams, + tpPESession session_entry) +{ + /* + * If we are AP and HT capable, we need to set the HT OP mode + * appropriately. + */ + if (LIM_IS_AP_ROLE(session_entry) && overlap) { + session_entry->gLimOverlapHt20Params.protectionEnabled = true; + if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != + session_entry->htOperMode) && + (eSIR_HT_OP_MODE_MIXED != + session_entry->htOperMode)) { + session_entry->htOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + } + } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { + session_entry->gLimHt20Params.protectionEnabled = true; + if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) { + if (session_entry->htSupportedChannelWidthSet != + eHT_CHANNEL_WIDTH_20MHZ) + session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + } + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) { + mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled = + true; + if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != + mac_ctx->lim.gHTOperMode) && + (eSIR_HT_OP_MODE_MIXED != + mac_ctx->lim.gHTOperMode)) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_OVERLAP_LEGACY; + lim_enable_ht_rifs_protection(mac_ctx, true, + overlap, beaconparams, session_entry); + } + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) { + session_entry->gLimHt20Params.protectionEnabled = true; + if (eSIR_HT_OP_MODE_PURE == mac_ctx->lim.gHTOperMode) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + } + } + /* This part is common for staiton as well. */ + if (false == session_entry->beaconParams.ht20Coexist) { + lim_log(mac_ctx, LOG1, + FL("=> Protection from HT20 Enabled")); + beaconparams->ht20MhzCoexist = + session_entry->beaconParams.ht20Coexist = true; + beaconparams->paramChangeBitmap |= + PARAM_HT20MHZCOEXIST_CHANGED; + } +} + +/** + * lim_handle_ht20coexist_ht20protection() - ht20 protection for ht20 coexist + * @mac_ctx: pointer to Gloal Mac Structure + * @beaconparams: pointer to tpUpdateBeaconParams + * @session_entry: pointer to tpPESession + * @overlap: variable for overlap detection + * + * Function handles ht20 protection for ht20 coexist + * + * Return: none + */ +static void lim_handle_ht20coexist_ht20protection(tpAniSirGlobal mac_ctx, + tpUpdateBeaconParams beaconparams, + tpPESession session_entry, uint8_t overlap) +{ + /* + * 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(session_entry) && overlap) { + /* Overlap Legacy protection disabled. */ + session_entry->gLimOverlapHt20Params.protectionEnabled = + false; + /* + * no HT op mode change if any of the overlap + * protection enabled. + */ + if (!(session_entry->gLimOlbcParams.protectionEnabled || + session_entry->gLimOverlap11gParams.protectionEnabled || + session_entry->gLimOverlapHt20Params.protectionEnabled + || session_entry->gLimOverlapNonGfParams. + protectionEnabled) && + /* + * Check if there is a need to change HT + * OP mode. + */ + (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + session_entry->htOperMode)) { + if (session_entry->gLimHt20Params. + protectionEnabled) { + if(eHT_CHANNEL_WIDTH_20MHZ == + session_entry->htSupportedChannelWidthSet) + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + else + session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + + lim_enable_ht_rifs_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + lim_enable_ht_obss_protection(mac_ctx, + false, overlap, beaconparams, + session_entry); + } else { + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + } + } + } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { + /* Disable protection from 11G stations. */ + session_entry->gLimHt20Params.protectionEnabled = false; + /* Change HT op mode appropriately. */ + if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == + session_entry->htOperMode) { + session_entry->htOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + } + } + if (LIM_IS_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOG1, + FL("===> Protection from HT 20 Disabled")); + beaconparams->ht20MhzCoexist = + session_entry->beaconParams.ht20Coexist = false; + beaconparams->paramChangeBitmap |= + PARAM_HT20MHZCOEXIST_CHANGED; + } + if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) { + /* Overlap Legacy protection disabled. */ + mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled = false; + /* + * no HT op mode change if any of the overlap + * protection enabled. + */ + if (!(session_entry->gLimOlbcParams.protectionEnabled || + mac_ctx->lim.gLimOverlap11gParams.protectionEnabled || + mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled || + mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled) + /* + * Check if there is a need to change + * HT OP mode. + */ + && (eSIR_HT_OP_MODE_OVERLAP_LEGACY == + mac_ctx->lim.gHTOperMode)) { + if (session_entry->gLimHt20Params.protectionEnabled) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + } else { + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } + } + } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) { + /* Disable protection from 11G stations. */ + session_entry->gLimHt20Params.protectionEnabled = false; + + /* Change HT op mode appropriately. */ + if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == + mac_ctx->lim.gHTOperMode) { + mac_ctx->lim.gHTOperMode = + eSIR_HT_OP_MODE_PURE; + lim_enable_ht_rifs_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + lim_enable_ht_obss_protection(mac_ctx, false, + overlap, beaconparams, session_entry); + } + } + if (LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + lim_log(mac_ctx, LOG1, + FL("===> Protection from HT 20 Disabled")); + beaconparams->ht20MhzCoexist = + session_entry->beaconParams.ht20Coexist = false; + beaconparams->paramChangeBitmap |= + PARAM_HT20MHZCOEXIST_CHANGED; + } + + if (!LIM_IS_AP_ROLE(session_entry) && + !LIM_IS_BT_AMP_AP_ROLE(session_entry)) { + /* For station role */ + lim_log(mac_ctx, LOG1, + FL("===> Protection from HT20 Disabled")); + beaconparams->ht20MhzCoexist = + session_entry->beaconParams.ht20Coexist = false; + beaconparams->paramChangeBitmap |= + PARAM_HT20MHZCOEXIST_CHANGED; + } +} + +/** + * lim_enable_ht20_protection() - Function to enable ht20 protection + * @mac_ctx: pointer to Global Mac structure + * @enable: 1=> enable protection, 0=> disable protection. + * @overlap: 1=> called from overlap context, 0 => called from assoc context. + * @beaconparams: pointer to tpUpdateBeaconParams + * @session_entry: pointer to tpPESession + * + * based on cofig enables\disables protection from Ht20 + * + * Return: 0 - success + */ +tSirRetStatus lim_enable_ht20_protection(tpAniSirGlobal mac_ctx, uint8_t enable, + uint8_t overlap, tpUpdateBeaconParams beaconparams, + tpPESession session_entry) +{ + /* This protection is only for HT stations. */ + if (!session_entry->htCapability) + return eSIR_SUCCESS; + + /* overlapping protection configuration check. */ + if (!overlap) { + /* normal protection config check */ + if ((LIM_IS_AP_ROLE(session_entry)) && + !session_entry->cfgProtection.ht20) { + /* protection disabled. */ + lim_log(mac_ctx, LOG3, + FL("protection from HT20 is disabled")); + return eSIR_SUCCESS; + } else if (!LIM_IS_AP_ROLE(session_entry)) { + if (!mac_ctx->lim.cfgProtection.ht20) { + /* protection disabled. */ + lim_log(mac_ctx, LOG3, + FL("protection from HT20 is disabled")); + return eSIR_SUCCESS; + } + } + } + + if (enable) + lim_handle_ht20protection_enabled(mac_ctx, overlap, + beaconparams, session_entry); + else if (true == session_entry->beaconParams.ht20Coexist) + lim_handle_ht20coexist_ht20protection(mac_ctx, beaconparams, + session_entry, overlap); + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_enable_ht_non_gf_protection + \brief based on cofig enables\disables protection from NonGf. + \param uint8_t enable : 1=> enable protection, 0=> disable protection. + \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +tSirRetStatus +lim_enable_ht_non_gf_protection(tpAniSirGlobal pMac, uint8_t enable, + uint8_t 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(lim_log + (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(lim_log + (pMac, LOG3, + FL + ("protection from NonGf is disabled")); + ) + return eSIR_SUCCESS; + } + } + } + if (LIM_IS_AP_ROLE(psessionEntry)) { + if ((enable) + && (false == psessionEntry->beaconParams.llnNonGFCoexist)) { + PELOG1(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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 lim_enable_ht_lsig_txop_protection + \brief based on cofig enables\disables LsigTxop protection. + \param uint8_t enable : 1=> enable protection, 0=> disable protection. + \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +tSirRetStatus +lim_enable_ht_lsig_txop_protection(tpAniSirGlobal pMac, uint8_t enable, + uint8_t 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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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 lim_enable_ht_rifs_protection + \brief based on cofig enables\disables Rifs protection. + \param uint8_t enable : 1=> enable protection, 0=> disable protection. + \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. + \param tpUpdateBeaconParams pBeaconParams + \return None + -------------------------------------------------------------*/ +tSirRetStatus +lim_enable_ht_rifs_protection(tpAniSirGlobal pMac, uint8_t enable, + uint8_t 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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (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(lim_log + (pMac, LOG1, FL("===> Rifs Protection Enabled")); + ) + pBeaconParams->fRIFSMode = + psessionEntry->beaconParams.fRIFSMode = false; + pBeaconParams->paramChangeBitmap |= + PARAM_RIFS_MODE_CHANGED; + } + } + return eSIR_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/** + * lim_enable_short_preamble + * + * FUNCTION: + * Enable/Disable short preamble + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param enable Flag to enable/disable short preamble + * @return None + */ + +tSirRetStatus +lim_enable_short_preamble(tpAniSirGlobal pMac, uint8_t enable, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry) +{ + uint32_t val; + + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) { + /* Could not get short preamble enabled flag from CFG. Log error. */ + lim_log(pMac, LOGP, + FL("could not retrieve short preamble flag")); + return eSIR_FAILURE; + } + + if (!val) + return eSIR_SUCCESS; + + if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) != + eSIR_SUCCESS) { + lim_log(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(lim_log + (pMac, LOG1, FL("===> Short Preamble Enabled")); + ) + psessionEntry->beaconParams.fShortPreamble = true; + pBeaconParams->fShortPreamble = + (uint8_t) psessionEntry->beaconParams. + fShortPreamble; + pBeaconParams->paramChangeBitmap |= + PARAM_SHORT_PREAMBLE_CHANGED; + } else if (!enable + && (psessionEntry->beaconParams.fShortPreamble == + 1)) { + PELOG1(lim_log + (pMac, LOG1, FL("===> Short Preamble Disabled")); + ) + psessionEntry->beaconParams.fShortPreamble = false; + pBeaconParams->fShortPreamble = + (uint8_t) psessionEntry->beaconParams. + fShortPreamble; + pBeaconParams->paramChangeBitmap |= + PARAM_SHORT_PREAMBLE_CHANGED; + } + } + + return eSIR_SUCCESS; +} + +/** + * lim_tx_complete + * + * 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 cds_packet_alloc( ..., **pData, **pPacket ) + * LIM transmits the MGMT frame using the API: + * wma_tx_frame( ... pPacket, ..., (void *) lim_tx_complete, pData ) + * HDD, via wma_tx_frame/DXE, "transfers" the packet over to BMU + * HDD, if it determines that a TX completion routine (in this case + * lim_tx_complete) 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 cds_packet_free( ... 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 cds_packet_free() 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 lim_tx_complete(tHalHandle hHal, void *data, bool free) +{ + if (free) + cds_packet_free((void *)data); +} + +/** + * \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 Swtich 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 lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pHTInfo, + uint8_t bssIdx, + tpPESession psessionEntry) +{ + uint8_t center_freq = 0; +#if !defined WLAN_FEATURE_VOWIFI + uint32_t localPwrConstraint; +#endif + + /* If self capability is set to '20Mhz only', then do not change the CB mode. */ + if (!lim_get_ht_capability + (pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry)) + return; + +#if !defined WLAN_FEATURE_VOWIFI + if (wlan_cfg_get_int + (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, + &localPwrConstraint) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("Unable to get Local Power Constraint from cfg")); + return; + } +#endif + + if (psessionEntry->ftPEContext.ftPreAuthSession) { + lim_log(pMac, LOGE, + FL("FT PREAUTH channel change is in progress")); + return; + } + + if (psessionEntry->htSecondaryChannelOffset != + (uint8_t) pHTInfo->secondaryChannelOffset + || psessionEntry->htRecommendedTxWidthSet != + (uint8_t) pHTInfo->recommendedTxWidthSet) { + psessionEntry->htSecondaryChannelOffset = + (ePhyChanBondState) pHTInfo->secondaryChannelOffset; + psessionEntry->htRecommendedTxWidthSet = + (uint8_t) pHTInfo->recommendedTxWidthSet; + if (eHT_CHANNEL_WIDTH_40MHZ == + psessionEntry->htRecommendedTxWidthSet) { + if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY == + pHTInfo->secondaryChannelOffset) + center_freq = pHTInfo->primaryChannel + 2; + else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == + pHTInfo->secondaryChannelOffset) + center_freq = pHTInfo->primaryChannel - 2; + } + + /* notify HAL */ + lim_log(pMac, LOGW, FL("Channel Information in HT IE change" + "d; sending notification to HAL.")); + lim_log(pMac, LOGW, FL("Primary Channel: %d, Secondary Chan" + "nel Offset: %d, Channel Width: %d"), + pHTInfo->primaryChannel, center_freq, + psessionEntry->htRecommendedTxWidthSet); + psessionEntry->channelChangeReasonCode = + LIM_SWITCH_CHANNEL_OPERATION; + pMac->lim.gpchangeChannelCallback = NULL; + pMac->lim.gpchangeChannelData = NULL; + +#if defined WLAN_FEATURE_VOWIFI + lim_send_switch_chnl_params(pMac, (uint8_t) pHTInfo->primaryChannel, + center_freq, 0, + psessionEntry->htRecommendedTxWidthSet, + psessionEntry->maxTxPower, + psessionEntry->peSessionId, + true); +#else + lim_send_switch_chnl_params(pMac, (uint8_t) pHTInfo->primaryChannel, + center_freq, 0, + psessionEntry->htRecommendedTxWidthSet, + (tPowerdBm) localPwrConstraint, + psessionEntry->peSessionId, + true); +#endif + + /* In case of IBSS, if STA should update HT Info IE in its beacons. */ + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + sch_set_fixed_beacon_fields(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 lim_update_sta_run_time_ht_capability(tpAniSirGlobal pMac, + tDot11fIEHTCaps *pHTCaps) +{ + + if (pMac->lim.gHTLsigTXOPProtection != + (uint8_t) pHTCaps->lsigTXOPProtection) { + pMac->lim.gHTLsigTXOPProtection = + (uint8_t) pHTCaps->lsigTXOPProtection; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTAMpduDensity != (uint8_t) pHTCaps->mpduDensity) { + pMac->lim.gHTAMpduDensity = (uint8_t) pHTCaps->mpduDensity; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTMaxRxAMpduFactor != + (uint8_t) pHTCaps->maxRxAMPDUFactor) { + pMac->lim.gHTMaxRxAMpduFactor = + (uint8_t) pHTCaps->maxRxAMPDUFactor; + /* Send change notification to HAL */ + } + +} /* End lim_update_sta_run_time_ht_capability. */ + +/** + * \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 lim_update_sta_run_time_ht_info(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pHTInfo, + tpPESession psessionEntry) +{ + if (psessionEntry->htRecommendedTxWidthSet != + (uint8_t) pHTInfo->recommendedTxWidthSet) { + psessionEntry->htRecommendedTxWidthSet = + (uint8_t) pHTInfo->recommendedTxWidthSet; + /* Send change notification to HAL */ + } + + if (psessionEntry->beaconParams.fRIFSMode != + (uint8_t) pHTInfo->rifsMode) { + psessionEntry->beaconParams.fRIFSMode = + (uint8_t) pHTInfo->rifsMode; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTServiceIntervalGranularity != + (uint8_t) pHTInfo->serviceIntervalGranularity) { + pMac->lim.gHTServiceIntervalGranularity = + (uint8_t) 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 = + (uint8_t) pHTInfo->nonGFDevicesPresent; + } + + if (pMac->lim.gHTSTBCBasicMCS != (uint8_t) pHTInfo->basicSTBCMCS) { + pMac->lim.gHTSTBCBasicMCS = (uint8_t) pHTInfo->basicSTBCMCS; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTDualCTSProtection != + (uint8_t) pHTInfo->dualCTSProtection) { + pMac->lim.gHTDualCTSProtection = + (uint8_t) pHTInfo->dualCTSProtection; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTSecondaryBeacon != (uint8_t) pHTInfo->secondaryBeacon) { + pMac->lim.gHTSecondaryBeacon = + (uint8_t) pHTInfo->secondaryBeacon; + /* Send change notification to HAL */ + } + + if (psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport != + (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport) { + psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = + (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTPCOActive != (uint8_t) pHTInfo->pcoActive) { + pMac->lim.gHTPCOActive = (uint8_t) pHTInfo->pcoActive; + /* Send change notification to HAL */ + } + + if (pMac->lim.gHTPCOPhase != (uint8_t) pHTInfo->pcoPhase) { + pMac->lim.gHTPCOPhase = (uint8_t) pHTInfo->pcoPhase; + /* Send change notification to HAL */ + } + +} /* End lim_update_sta_run_time_ht_info. */ + +/** ------------------------------------------------------------- + \fn lim_process_hal_ind_messages + \brief callback function for HAL indication + \param tpAniSirGlobal pMac + \param uint32_t mesgId + \param void *mesgParam + \return tSirRetStatu - status + -------------------------------------------------------------*/ + +tSirRetStatus lim_process_hal_ind_messages(tpAniSirGlobal pMac, uint32_t 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_DELETE_STA_CONTEXT_IND: + case SIR_LIM_BEACON_GEN_IND: + msg.type = (uint16_t) msgId; + msg.bodyptr = msgParam; + msg.bodyval = 0; + break; + + default: + cdf_mem_free(msgParam); + lim_log(pMac, LOGP, FL("invalid message id = %d received"), + msgId); + return eSIR_FAILURE; + } + + if (lim_post_msg_api(pMac, &msg) != eSIR_SUCCESS) { + cdf_mem_free(msgParam); + lim_log(pMac, LOGP, FL("lim_post_msg_api failed for msgid = %d"), + msg.type); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} + +/** + * lim_validate_delts_req() - This function validates DelTs req + * @mac_ctx: pointer to Global Mac structure + * @delts_req: pointer to delete traffic stream structure + * @peer_mac_addr: variable for peer mac address + * + * Function validates DelTs req originated by SME or by HAL and also + * sends halMsg_DelTs to HAL + * + * Return: eSIR_SUCCESS - Success, eSIR_FAILURE - Failure + */ + +tSirRetStatus +lim_validate_delts_req(tpAniSirGlobal mac_ctx, tpSirDeltsReq delts_req, + tSirMacAddr peer_mac_addr, tpPESession psession_entry) +{ + tpDphHashNode sta; + uint8_t ts_status; + tSirMacTSInfo *tsinfo; + uint32_t i; + uint8_t tspec_idx; + + /* + * if sta + * - verify assoc state + * - del tspec locally + * if ap + * - verify sta is in assoc state + * - del sta tspec locally + */ + if (delts_req == NULL) { + lim_log(mac_ctx, LOGE, + FL("Delete TS request pointer is NULL")); + return eSIR_FAILURE; + } + + if (LIM_IS_STA_ROLE(psession_entry) || + LIM_IS_BT_AMP_STA_ROLE(psession_entry)) { + uint32_t val; + + /* station always talks to the AP */ + sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &psession_entry->dph.dphHashTable); + + val = sizeof(tSirMacAddr); + sir_copy_mac_addr(peer_mac_addr, psession_entry->bssId); + + } else { + uint16_t associd; + uint8_t *macaddr = (uint8_t *) peer_mac_addr; + + associd = delts_req->aid; + if (associd != 0) + sta = dph_get_hash_entry(mac_ctx, associd, + &psession_entry->dph.dphHashTable); + else + sta = dph_lookup_hash_entry(mac_ctx, + delts_req->macAddr, + &associd, + &psession_entry->dph. + dphHashTable); + + if (sta != NULL) + /* TBD: check sta assoc state as well */ + for (i = 0; i < sizeof(tSirMacAddr); i++) + macaddr[i] = sta->staAddr[i]; + } + + if (sta == NULL) { + lim_log(mac_ctx, LOGE, + FL("Cannot find station context for delts req")); + return eSIR_FAILURE; + } + + if ((!sta->valid) || + (sta->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE)) { + lim_log(mac_ctx, LOGE, + FL("Invalid Sta (or state) for DelTsReq")); + return eSIR_FAILURE; + } + + delts_req->req.wsmTspecPresent = 0; + delts_req->req.wmeTspecPresent = 0; + delts_req->req.lleTspecPresent = 0; + + if ((sta->wsmEnabled) && + (delts_req->req.tspec.tsinfo.traffic.accessPolicy != + SIR_MAC_ACCESSPOLICY_EDCA)) + delts_req->req.wsmTspecPresent = 1; + else if (sta->wmeEnabled) + delts_req->req.wmeTspecPresent = 1; + else if (sta->lleEnabled) + delts_req->req.lleTspecPresent = 1; + else { + lim_log(mac_ctx, LOGW, + FL("DELTS_REQ ignore - qos is disabled")); + return eSIR_FAILURE; + } + + tsinfo = delts_req->req.wmeTspecPresent ? &delts_req->req.tspec.tsinfo + : &delts_req->req.tsinfo; + lim_log(mac_ctx, LOG1, + FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"), + delts_req->req.wmeTspecPresent, + delts_req->req.lleTspecPresent, + delts_req->req.wsmTspecPresent, tsinfo->traffic.tsid, + tsinfo->traffic.userPrio, tsinfo->traffic.direction); + + /* if no Access Control, ignore the request */ + if (lim_admit_control_delete_ts(mac_ctx, sta->assocId, tsinfo, + &ts_status, &tspec_idx) != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("ERROR DELTS request for sta assocId %d (tsid %d, up %d)"), + sta->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 != + lim_send_hal_msg_del_ts(mac_ctx, sta->staIndex, + tspec_idx, delts_req->req, + psession_entry->peSessionId, + psession_entry->bssId)) { + lim_log(mac_ctx, LOGW, + FL("DelTs with UP %d failed in lim_send_hal_msg_del_ts - ignoring request"), + tsinfo->traffic.userPrio); + return eSIR_FAILURE; + } + } + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn lim_register_hal_ind_call_back + \brief registers callback function to HAL for any indication. + \param tpAniSirGlobal pMac + \return none. + -------------------------------------------------------------*/ +void lim_register_hal_ind_call_back(tpAniSirGlobal pMac) +{ + tSirMsgQ msg; + tpHalIndCB pHalCB; + + pHalCB = cdf_mem_malloc(sizeof(tHalIndCB)); + if (NULL == pHalCB) { + lim_log(pMac, LOGP, FL("AllocateMemory() failed")); + return; + } + + pHalCB->pHalIndCB = lim_process_hal_ind_messages; + + msg.type = WMA_REGISTER_PE_CALLBACK; + msg.bodyptr = pHalCB; + msg.bodyval = 0; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type)); + if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) { + cdf_mem_free(pHalCB); + lim_log(pMac, LOGP, FL("wma_post_ctrl_msg() failed")); + } + + return; +} + +/** + * lim_process_del_ts_ind() - handle del_ts_ind from HAL + * + * @mac_ctx: pointer to Global Mac Structure + * @lim_msg: pointer to msg buff + * + * 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 indicatoin to HDD. + * + * Return: none + */ +void lim_process_del_ts_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpDphHashNode pSta; + tpDelTsParams pDelTsParam = (tpDelTsParams) (limMsg->bodyptr); + tpSirDeltsReq pDelTsReq = NULL; + tSirMacAddr peerMacAddr; + tpSirDeltsReqInfo pDelTsReqInfo; + tpLimTspecInfo pTspecInfo; + tpPESession psessionEntry; + uint8_t sessionId; + + psessionEntry = pe_find_session_by_bssid(pMac, pDelTsParam->bssId, + &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("session does not exist for given BssId")); + cdf_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; + } + + pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]); + if (pTspecInfo->inuse == false) { + PELOGE(lim_log + (pMac, LOGE, + FL("tspec entry with index %d is not in use"), + pDelTsParam->tspecIdx); + ) + goto error1; + } + + pSta = + dph_get_hash_entry(pMac, pTspecInfo->assocId, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) { + lim_log(pMac, LOGE, + FL("Could not find entry in DPH table for assocId = %d"), + pTspecInfo->assocId); + goto error1; + } + + pDelTsReq = cdf_mem_malloc(sizeof(tSirDeltsReq)); + if (NULL == pDelTsReq) { + PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));) + goto error1; + } + + cdf_mem_set((uint8_t *) pDelTsReq, sizeof(tSirDeltsReq), 0); + + if (pSta->wmeEnabled) + cdf_mem_copy(&(pDelTsReq->req.tspec), &(pTspecInfo->tspec), + sizeof(tSirMacTspecIE)); + else + cdf_mem_copy(&(pDelTsReq->req.tsinfo), + &(pTspecInfo->tspec.tsinfo), + sizeof(tSirMacTSInfo)); + + /* validate the req */ + if (eSIR_SUCCESS != + lim_validate_delts_req(pMac, pDelTsReq, peerMacAddr, psessionEntry)) { + PELOGE(lim_log(pMac, LOGE, FL("lim_validate_delts_req failed"));) + goto error2; + } + PELOG1(lim_log(pMac, LOG1, "Sent DELTS request to station with " + "assocId = %d MacAddr = " MAC_ADDRESS_STR, + pDelTsReq->aid, MAC_ADDR_ARRAY(peerMacAddr)); + ) + + lim_send_delts_req_action_frame(pMac, peerMacAddr, + pDelTsReq->req.wmeTspecPresent, + &pDelTsReq->req.tsinfo, + &pDelTsReq->req.tspec, psessionEntry); + + /* prepare and send an sme indication to HDD */ + pDelTsReqInfo = cdf_mem_malloc(sizeof(tSirDeltsReqInfo)); + if (NULL == pDelTsReqInfo) { + PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));) + goto error3; + } + cdf_mem_set((uint8_t *) pDelTsReqInfo, sizeof(tSirDeltsReqInfo), 0); + + if (pSta->wmeEnabled) + cdf_mem_copy(&(pDelTsReqInfo->tspec), &(pTspecInfo->tspec), + sizeof(tSirMacTspecIE)); + else + cdf_mem_copy(&(pDelTsReqInfo->tsinfo), + &(pTspecInfo->tspec.tsinfo), + sizeof(tSirMacTSInfo)); + + lim_send_sme_delts_ind(pMac, pDelTsReqInfo, pDelTsReq->aid, psessionEntry); + +error3: + cdf_mem_free(pDelTsReqInfo); +error2: + cdf_mem_free(pDelTsReq); +error1: + cdf_mem_free(limMsg->bodyptr); + limMsg->bodyptr = NULL; + return; +} + +/** + * @function : lim_post_sm_state_update() + * + * @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 +lim_post_sm_state_update(tpAniSirGlobal pMac, + uint16_t staIdx, tSirMacHTMIMOPowerSaveState state, + uint8_t *pPeerStaMac, uint8_t sessionId) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + tpSetMIMOPS pMIMO_PSParams; + + msgQ.reserved = 0; + msgQ.type = WMA_SET_MIMOPS_REQ; + + /* Allocate for WMA_SET_MIMOPS_REQ */ + pMIMO_PSParams = cdf_mem_malloc(sizeof(tSetMIMOPS)); + if (NULL == pMIMO_PSParams) { + lim_log(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; + cdf_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac, sizeof(tSirMacAddr)); + + msgQ.bodyptr = pMIMO_PSParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG2, FL("Sending WMA_SET_MIMOPS_REQ...")); + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + retCode = wma_post_ctrl_msg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) { + lim_log(pMac, LOGP, + FL + ("Posting WMA_SET_MIMOPS_REQ to HAL failed! Reason = %d"), + retCode); + cdf_mem_free(pMIMO_PSParams); + return retCode; + } + + return retCode; +} + +void lim_pkt_free(tpAniSirGlobal pMac, + eFrameType frmType, uint8_t *pRxPacketInfo, void *pBody) +{ + (void)pMac; + (void)frmType; + (void)pRxPacketInfo; + (void)pBody; +} + +/** + * lim_get_b_dfrom_rx_packet() + * + ***FUNCTION: + * This function is called to get pointer to Polaris + * 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 +lim_get_b_dfrom_rx_packet(tpAniSirGlobal pMac, void *body, uint32_t **pRxPacketInfo) +{ + *pRxPacketInfo = (uint32_t *) body; +} /*** end lim_get_b_dfrom_rx_packet() ***/ + +void lim_resset_scan_channel_info(tpAniSirGlobal pMac) +{ + cdf_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0); +} + +/** + * @function : lim_is_channel_valid_for_channel_switch() + * + * @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 lim_is_channel_valid_for_channel_switch(tpAniSirGlobal pMac, uint8_t channel) +{ + uint8_t index; + uint32_t validChannelListLen = WNI_CFG_VALID_CHANNEL_LIST_LEN; + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + + if (wlan_cfg_get_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, + (uint8_t *) validChannelList, + (uint32_t *) &validChannelListLen) != + eSIR_SUCCESS) { + PELOGE(lim_log + (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 __lim_fill_tx_control_params + \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 CDF_STATUS +__lim_fill_tx_control_params(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg, + tLimQuietTxMode type, tLimControlTx mode) +{ + + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + + if (mode == eLIM_STOP_TX) + pTxCtrlMsg->stopTx = true; + else + pTxCtrlMsg->stopTx = 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(lim_log(pMac, LOGW, FL("Invalid case: Not Handled"));) + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * @function : lim_frame_transmission_control() + * + * @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 lim_frame_transmission_control(tpAniSirGlobal pMac, tLimQuietTxMode type, + tLimControlTx mode) +{ + + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpTxControlParams pTxCtrlMsg; + tSirMsgQ msgQ; + uint8_t 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 = (uint8_t) HALMSG_NUMBYTES_STATION_BITMAP(pMac->lim.maxStation); + + pTxCtrlMsg = cdf_mem_malloc(sizeof(*pTxCtrlMsg) + nBytes); + if (NULL == pTxCtrlMsg) { + lim_log(pMac, LOGP, FL("AllocateMemory() failed")); + return; + } + + cdf_mem_set((void *)pTxCtrlMsg, (sizeof(*pTxCtrlMsg) + nBytes), 0); + status = __lim_fill_tx_control_params(pMac, pTxCtrlMsg, type, mode); + if (status != CDF_STATUS_SUCCESS) { + cdf_mem_free(pTxCtrlMsg); + lim_log(pMac, LOGP, + FL("__lim_fill_tx_control_params failed, status = %d"), + status); + return; + } + + msgQ.bodyptr = (void *)pTxCtrlMsg; + msgQ.bodyval = 0; + msgQ.reserved = 0; + msgQ.type = WMA_TRANSMISSION_CONTROL_IND; + + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type)); + if (wma_post_ctrl_msg(pMac, &msgQ) != eSIR_SUCCESS) { + cdf_mem_free(pTxCtrlMsg); + lim_log(pMac, LOGP, FL("Posting Message to HAL failed")); + return; + } + + if (mode == eLIM_STOP_TX) { + PELOG1(lim_log + (pMac, LOG1, + FL + ("Stopping the transmission of all packets, indicated softmac")); + ) + } else { + PELOG1(lim_log + (pMac, LOG1, + FL + ("Resuming the transmission of all packets, indicated softmac")); + ) + } + return; +} + +/** + * @function : lim_restore_pre_channel_switch_state() + * + * @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 +lim_restore_pre_channel_switch_state(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + tSirRetStatus retCode = eSIR_SUCCESS; + + 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. */ + lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + + return retCode; +} + +/**-------------------------------------------- + \fn lim_restore_pre_quiet_state + \brief Restore the pre quiet state + + \param pMac + \return NONE + ---------------------------------------------*/ +tSirRetStatus lim_restore_pre_quiet_state(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + + tSirRetStatus retCode = eSIR_SUCCESS; + + 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) + lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); + + return retCode; +} + +/** + * @function: lim_prepare_for11h_channel_switch() + * + * @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 +lim_prepare_for11h_channel_switch(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; + + if (pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE || + pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE) { + PELOGE(lim_log + (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. */ + pe_set_resume_channel(pMac, 0, 0); + } else { + lim_restore_pre_channel_switch_state(pMac, psessionEntry); + } + return; + } else { + PELOGE(lim_log + (pMac, LOG1, + FL("Not in scan state, start channel switch timer")); + ) + /** We are safe to switch channel at this point */ + lim_stop_tx_and_switch_channel(pMac, psessionEntry->peSessionId); + } +} + +/**---------------------------------------------------- + \fn lim_get_nw_type + + \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 lim_get_nw_type(tpAniSirGlobal pMac, uint8_t channelNum, uint32_t 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 iff 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(lim_log + (pMac, LOG3, FL("Beacon, nwtype=G")); + ) + nwType = eSIR_11G_NW_TYPE; + } + } else { + /* 11a packet */ + PELOG3(lim_log(pMac, LOG3, FL("Beacon, nwtype=A"));) + nwType = eSIR_11A_NW_TYPE; + } + } + return nwType; +} + +/**--------------------------------------------------------- + \fn lim_get_channel_from_beacon + \brief To extract channel number from beacon + + \param pMac + \param pBeacon - Pointer to beacon or probe rsp + \return channel number + -----------------------------------------------------------*/ +uint8_t lim_get_channel_from_beacon(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon) +{ + uint8_t channelNum = 0; + + if (pBeacon->dsParamsPresent) + channelNum = pBeacon->channelNumber; + else if (pBeacon->HTInfo.present) + channelNum = pBeacon->HTInfo.primaryChannel; + else + channelNum = pBeacon->channelNumber; + + return channelNum; +} + +void lim_set_tspec_uapsd_mask_per_session(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacTSInfo *pTsInfo, uint32_t action) +{ + uint8_t userPrio = (uint8_t) pTsInfo->traffic.userPrio; + uint16_t direction = pTsInfo->traffic.direction; + uint8_t ac = upToAc(userPrio); + + PELOG1(lim_log + (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); + } + } + + lim_log(pMac, LOG1, + FL("New psessionEntry->gUapsdPerAcTriggerEnableMask = 0x%x "), + psessionEntry->gUapsdPerAcTriggerEnableMask); + lim_log(pMac, LOG1, + FL("New psessionEntry->gUapsdPerAcDeliveryEnableMask = 0x%x "), + psessionEntry->gUapsdPerAcDeliveryEnableMask); + + return; +} + +/** + * lim_handle_heart_beat_timeout_for_session() - Handle heart beat time out + * @mac_ctx: pointer to Global Mac Structure + * @psession_entry: pointer to tpPESession + * + * Function handles heart beat time out for session + * + * Return: none + */ +void lim_handle_heart_beat_timeout_for_session(tpAniSirGlobal mac_ctx, + tpPESession psession_entry) +{ + if (psession_entry->valid == true) { + if (psession_entry->bssType == eSIR_IBSS_MODE) + lim_ibss_heart_beat_handle(mac_ctx, psession_entry); + + if ((psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) && + (LIM_IS_STA_ROLE(psession_entry))) + lim_handle_heart_beat_failure(mac_ctx, psession_entry); + } + /* + * In the function lim_handle_heart_beat_failure things can change + * so check for the session entry valid and the other things + * again + */ + if ((psession_entry->valid == true) && + (psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) && + (LIM_IS_STA_ROLE(psession_entry)) && + (psession_entry->LimHBFailureStatus == true)) { + tLimTimers *lim_timer = &mac_ctx->lim.limTimers; + /* + * Activate Probe After HeartBeat Timer incase HB + * Failure detected + */ + PELOGW(lim_log(mac_ctx, LOGW, + FL("Sending Probe for Session: %d"), + psession_entry->bssIdx);) + lim_deactivate_and_change_timer(mac_ctx, + eLIM_PROBE_AFTER_HB_TIMER); + MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, 0, + eLIM_PROBE_AFTER_HB_TIMER)); + if (tx_timer_activate(&lim_timer->gLimProbeAfterHBTimer) + != TX_SUCCESS) + lim_log(mac_ctx, LOGP, + FL("Fail to re-activate Probe-after-hb timer")); + } +} + +uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac) +{ + uint8_t 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 lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) +{ + tpPESession psessionEntry; + tpAddStaParams pAddStaParams; + + pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr; + + psessionEntry = pe_find_session_by_session_id(pMac, + pAddStaParams->sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGP, + FL("Session Does not exist for given sessionID")); + cdf_mem_free(pAddStaParams); + return; + } + psessionEntry->csaOffloadEnable = pAddStaParams->csaOffloadEnable; + if (LIM_IS_IBSS_ROLE(psessionEntry)) + (void)lim_ibss_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry); +#ifdef FEATURE_WLAN_TDLS + else if (pMac->lim.gLimAddStaTdls) { + lim_process_tdls_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry); + pMac->lim.gLimAddStaTdls = false; + } +#endif + else + lim_process_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry); + +} + +/** + * lim_update_beacon() - This function updates beacon + * @mac_ctx: pointer to Global Mac Structure + * + * This Function is invoked to update the beacon + * + * Return: none + */ +void lim_update_beacon(tpAniSirGlobal mac_ctx) +{ + uint8_t i; + + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + if (mac_ctx->lim.gpSession[i].valid != true) + continue; + if (((mac_ctx->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) + || (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_STA_IN_IBSS_ROLE)) + && (eLIM_SME_NORMAL_STATE == + mac_ctx->lim.gpSession[i].limSmeState)) { + + sch_set_fixed_beacon_fields(mac_ctx, + &mac_ctx->lim.gpSession[i]); + + if (false == mac_ctx->sap.SapDfsInfo. + is_dfs_cac_timer_running) + lim_send_beacon_ind(mac_ctx, + &mac_ctx->lim.gpSession[i]); + } else if (((mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_BT_AMP_AP_ROLE) || + (mac_ctx->lim.gpSession[i].limSystemRole == + eLIM_BT_AMP_STA_ROLE)) && + (mac_ctx->lim.gpSession[i].statypeForBss == + STA_ENTRY_SELF)){ + sch_set_fixed_beacon_fields(mac_ctx, + &mac_ctx->lim.gpSession[i]); + } + } +} + +/** + * lim_handle_heart_beat_failure_timeout - handle heart beat failure + * @mac_ctx: pointer to Global Mac Structure + * + * Function handle heart beat failure timeout + * + * Return: none + */ +void lim_handle_heart_beat_failure_timeout(tpAniSirGlobal mac_ctx) +{ + uint8_t i; + tpPESession psession_entry; + /* + * Probe response is not received after HB failure. + * This is handled by LMM sub module. + */ + for (i = 0; i < mac_ctx->lim.maxBssId; i++) { + if (mac_ctx->lim.gpSession[i].valid != true) + continue; + psession_entry = &mac_ctx->lim.gpSession[i]; + if (psession_entry->LimHBFailureStatus != true) + continue; + lim_log(mac_ctx, LOGE, FL("SME %d, MLME %d, HB-Count %d"), + psession_entry->limSmeState, + psession_entry->limMlmState, + psession_entry->LimRxedBeaconCntDuringHB); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_HB_FAILURE_TIMEOUT, + psession_entry, 0, 0); +#endif + if ((psession_entry->limMlmState == + eLIM_MLM_LINK_ESTABLISHED_STATE) && + (psession_entry->limSmeState != + eLIM_SME_WT_DISASSOC_STATE) && + (psession_entry->limSmeState != + eLIM_SME_WT_DEAUTH_STATE) && + ((!LIM_IS_CONNECTION_ACTIVE(psession_entry)) || + /* + * Disconnect even if we have not received a single + * beacon after connection. + */ + (psession_entry->currentBssBeaconCnt == 0))) { + lim_log(mac_ctx, LOGE, FL("for session:%d "), + psession_entry->peSessionId); + /* + * AP did not respond to Probe Request. + * Tear down link with it. + */ + lim_tear_down_link_with_ap(mac_ctx, + psession_entry->peSessionId, + eSIR_BEACON_MISSED); + mac_ctx->lim.gLimProbeFailureAfterHBfailedCnt++; + } else { + lim_log(mac_ctx, LOGE, + FL("Unexpected wt-probe-timeout in state ")); + lim_print_mlm_state(mac_ctx, LOGE, + psession_entry->limMlmState); + } + } + /* + * Deactivate Timer ProbeAfterHB Timer -> As its a oneshot timer, + * need not deactivate the timer + * tx_timer_deactivate(&pMac->lim.limTimers.gLimProbeAfterHBTimer); + */ +} + +/* + * This function assumes there will not be more than one IBSS session active at any time. + */ +tpPESession lim_is_ibss_session_active(tpAniSirGlobal pMac) +{ + uint8_t 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 lim_is_ap_session_active(tpAniSirGlobal pMac) +{ + uint8_t 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 lim_handle_defer_msg_error + \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 lim_handle_defer_msg_error(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg) +{ + if (SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) { + cds_pkt_return_packet((cds_pkt_t *) pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } else if (pLimMsg->bodyptr != NULL) { + cdf_mem_free(pLimMsg->bodyptr); + pLimMsg->bodyptr = NULL; + } + +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/**--------------------------------------------------------- + \fn lim_diag_event_report + \brief This function reports Diag event + \param pMac + \param eventType + \param bssid + \param status + \param reasonCode + \return void + -----------------------------------------------------------*/ +void lim_diag_event_report(tpAniSirGlobal pMac, uint16_t eventType, + tpPESession pSessionEntry, uint16_t status, + uint16_t reasonCode) +{ + tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 }; + WLAN_HOST_DIAG_EVENT_DEF(peEvent, host_event_wlan_pe_payload_type); + + cdf_mem_set(&peEvent, sizeof(host_event_wlan_pe_payload_type), 0); + + if (NULL == pSessionEntry) { + cdf_mem_copy(peEvent.bssid, nullBssid, sizeof(tSirMacAddr)); + peEvent.sme_state = (uint16_t) pMac->lim.gLimSmeState; + peEvent.mlm_state = (uint16_t) pMac->lim.gLimMlmState; + + } else { + cdf_mem_copy(peEvent.bssid, pSessionEntry->bssId, + sizeof(tSirMacAddr)); + peEvent.sme_state = (uint16_t) pSessionEntry->limSmeState; + peEvent.mlm_state = (uint16_t) pSessionEntry->limMlmState; + } + peEvent.event_type = eventType; + peEvent.status = status; + peEvent.reason_code = reasonCode; + + WLAN_HOST_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE); + return; +} + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +uint8_t *lim_get_ie_ptr_new(tpAniSirGlobal pMac, uint8_t *pIes, int length, + uint8_t eid, eSizeOfLenField size_of_len_field) +{ + int left = length; + uint8_t *ptr = pIes; + uint8_t elem_id; + uint16_t elem_len; + + while (left >= (size_of_len_field + 1)) { + elem_id = ptr[0]; + if (size_of_len_field == TWO_BYTE) { + elem_len = ((uint16_t) ptr[1]) | (ptr[2] << 8); + } else { + elem_len = ptr[1]; + } + + left -= (size_of_len_field + 1); + if (elem_len > left) { + lim_log(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 */ + +uint8_t lim_build_p2p_ie(tpAniSirGlobal pMac, uint8_t *ie, uint8_t *data, + uint8_t ie_len) +{ + int length = 0; + uint8_t *ptr = ie; + + ptr[length++] = SIR_MAC_EID_VENDOR; + ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE; + cdf_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + cdf_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 */ + +uint8_t lim_get_noa_attr_stream_in_mult_p2p_ies(tpAniSirGlobal pMac, + uint8_t *noaStream, uint8_t noaLen, + uint8_t overFlowLen) +{ + uint8_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)) { + cdf_mem_copy(overFlowP2pStream, + noaStream + noaLen - overFlowLen, overFlowLen); + noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; + noaStream[noaLen - overFlowLen + 1] = + overFlowLen + SIR_MAC_P2P_OUI_SIZE; + cdf_mem_copy(noaStream + noaLen - overFlowLen + 2, + SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + cdf_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 */ +uint8_t lim_get_noa_attr_stream(tpAniSirGlobal pMac, uint8_t *pNoaStream, + tpPESession psessionEntry) +{ + uint8_t len = 0; + + uint8_t *pBody = pNoaStream; + + if ((psessionEntry != NULL) && (psessionEntry->valid) && + (psessionEntry->pePersona == CDF_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; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa1Duration); + pBody += sizeof(uint32_t); + len += 4; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa1Interval); + pBody += sizeof(uint32_t); + len += 4; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa1StartTime); + pBody += sizeof(uint32_t); + len += 4; + + } + + if (psessionEntry->p2pGoPsUpdate.uNoa2Duration) { + *pBody = psessionEntry->p2pGoPsUpdate.uNoa2IntervalCnt; + pBody += 1; + len += 1; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa2Duration); + pBody += sizeof(uint32_t); + len += 4; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa2Interval); + pBody += sizeof(uint32_t); + len += 4; + + *((uint32_t *) (pBody)) = + sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate. + uNoa2StartTime); + pBody += sizeof(uint32_t); + len += 4; + + } + + pBody = pNoaStream + 1; + *((uint16_t *) (pBody)) = sir_swap_u16if_needed(len - 3); /*one byte for Attr and 2 bytes for length */ + + return len; + + } + return 0; + +} + +void pe_set_resume_channel(tpAniSirGlobal pMac, uint16_t channel, + ePhyChanBondState phyCbState) +{ + + pMac->lim.gResumeChannel = channel; + pMac->lim.gResumePhyCbState = phyCbState; +} + +bool lim_is_noa_insert_reqd(tpAniSirGlobal pMac) +{ + uint8_t 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) + && (CDF_P2P_GO_MODE == + pMac->lim.gpSession[i].pePersona) + ) { + return true; + } + } + } + return false; +} + +bool lim_isconnected_on_dfs_channel(uint8_t currentChannel) +{ + if (CHANNEL_STATE_DFS == + cds_get_channel_state(currentChannel)) { + return true; + } else { + return false; + } +} + +#ifdef WLAN_FEATURE_11W +void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal; + tPmfSaQueryTimerId timerId; + tpPESession psessionEntry; + tpDphHashNode pSta; + uint32_t maxRetries; + + lim_log(pMac, LOG1, FL("SA Query timer fires")); + timerId.value = param; + + /* Check that SA Query is in progress */ + psessionEntry = pe_find_session_by_session_id(pMac, + timerId.fields.sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOGE, + FL("Session does not exist for given session ID %d"), + timerId.fields.sessionId); + return; + } + pSta = dph_get_hash_entry(pMac, timerId.fields.peerIdx, + &psessionEntry->dph.dphHashTable); + if (pSta == NULL) { + lim_log(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_cfg_get_int(pMac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &maxRetries) != eSIR_SUCCESS) { + lim_log(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) { + lim_log(pMac, LOGE, FL("SA Query timed out,Deleting STA")); + lim_print_mac_addr(pMac, pSta->staAddr, LOGE); + lim_send_disassoc_mgmt_frame(pMac, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + pSta->staAddr, psessionEntry, false); + lim_trigger_sta_deletion(pMac, pSta, psessionEntry); + pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT; + return; + } + /* Retry SA Query */ + lim_send_sa_query_request_frame(pMac, + (uint8_t *) &(pSta-> + pmfSaQueryCurrentTransId), + pSta->staAddr, psessionEntry); + pSta->pmfSaQueryCurrentTransId++; + lim_log(pMac, LOGE, FL("Starting SA Query retry %d"), + pSta->pmfSaQueryRetryCount); + if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS) { + lim_log(pMac, LOGE, FL("PMF SA Query timer activation failed!")); + pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; + } +} +#endif + +#ifdef WLAN_FEATURE_11AC +bool lim_check_vht_op_mode_change(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t chanWidth, uint8_t staId, + uint8_t *peerMac) +{ + tUpdateVHTOpMode tempParam; + + tempParam.opMode = chanWidth; + tempParam.staId = staId; + tempParam.smesessionId = psessionEntry->smeSessionId; + cdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr)); + + lim_send_mode_update(pMac, &tempParam, psessionEntry); + + return true; +} + +bool lim_set_nss_change(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t rxNss, uint8_t staId, uint8_t *peerMac) +{ + tUpdateRxNss tempParam; + + tempParam.rxNss = rxNss; + tempParam.staId = staId; + tempParam.smesessionId = psessionEntry->smeSessionId; + cdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr)); + + lim_send_rx_nss_update(pMac, &tempParam, psessionEntry); + + return true; +} + +bool lim_check_membership_user_position(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint32_t membership, uint32_t userPosition, + uint8_t staId) +{ + tUpdateMembership tempParamMembership; + tUpdateUserPos tempParamUserPosition; + + tempParamMembership.membership = membership; + tempParamMembership.staId = staId; + tempParamMembership.smesessionId = psessionEntry->smeSessionId; + cdf_mem_copy(tempParamMembership.peer_mac, psessionEntry->bssId, + sizeof(tSirMacAddr)); + + lim_set_membership(pMac, &tempParamMembership, psessionEntry); + + tempParamUserPosition.userPos = userPosition; + tempParamUserPosition.staId = staId; + tempParamUserPosition.smesessionId = psessionEntry->smeSessionId; + cdf_mem_copy(tempParamUserPosition.peer_mac, psessionEntry->bssId, + sizeof(tSirMacAddr)); + + lim_set_user_pos(pMac, &tempParamUserPosition, psessionEntry); + + return true; +} +#endif + +void lim_get_short_slot_from_phy_mode(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint32_t phyMode, uint8_t *pShortSlotEnabled) +{ + uint8_t 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 == CDF_SAP_MODE) || + (psessionEntry->pePersona == CDF_IBSS_MODE) || + (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { + val = true; + } + /* Program Polaris based on AP capability */ + 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; + } + + lim_log(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode, + val); + *pShortSlotEnabled = val; +} + +#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 +lim_set_protected_bit(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr) +{ + uint16_t aid; + tpDphHashNode pStaDs; + + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { + + pStaDs = dph_lookup_hash_entry(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->is_key_installed) + pMacHdr->fc.wep = 1; + } + } else if (psessionEntry->limRmfEnabled && + psessionEntry->is_key_installed) { + pMacHdr->fc.wep = 1; + } +} /*** end lim_set_protected_bit() ***/ +#endif + +void lim_set_ht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry, + uint8_t *p_ie_start, uint32_t num_bytes) +{ + uint8_t *p_ie = NULL; + tDot11fIEHTCaps dot11_ht_cap = {0,}; + + populate_dot11f_ht_caps(p_mac, p_session_entry, &dot11_ht_cap); + p_ie = lim_get_ie_ptr_new(p_mac, p_ie_start, num_bytes, + DOT11F_EID_HTCAPS, ONE_BYTE); + lim_log(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; + cdf_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, + uint8_t *p_ie_start, uint32_t num_bytes) +{ + uint8_t *p_ie = NULL; + tDot11fIEVHTCaps dot11_vht_cap; + + populate_dot11f_vht_caps(p_mac, p_session_entry, &dot11_vht_cap); + p_ie = lim_get_ie_ptr_new(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 { + uint16_t 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 */ + +/** + * 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) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + "mac or session context is null"); + /* let main routine handle it */ + return true; + } + if (lim_is_group_addr(a1) || lim_is_addr_bc(a1)) { + /* just for fail safe, don't handle MC/BC a1 in this routine */ + return true; + } + if (!cdf_mem_compare(a1, session->selfMacAddr, 6)) { + lim_log(mac_ctx, LOGE, + FL("Invalid A1 address in received frame")); + return false; + } + return true; +} + +/** + * 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)) { + cdf_mem_zero(&mac_ctx->lim.gLimOverlap11gParams, + sizeof(mac_ctx->lim.gLimOverlap11gParams)); + cdf_mem_zero(&mac_ctx->lim.gLimOverlap11aParams, + sizeof(mac_ctx->lim.gLimOverlap11aParams)); + cdf_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params, + sizeof(mac_ctx->lim.gLimOverlapHt20Params)); + cdf_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams, + sizeof(mac_ctx->lim.gLimOverlapNonGfParams)); + + mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; + } +} + +/** + * lim_set_stads_rtt_cap() - update station node RTT capability + * @sta_ds: Station hash node + * @ext_cap: Pointer to extended capability + * @mac_ctx: global MAC context + * + * 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, + tpAniSirGlobal mac_ctx) +{ + sta_ds->timingMeasCap = 0; + sta_ds->timingMeasCap |= (ext_cap->timing_meas) ? + 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; + + lim_log(mac_ctx, LOG1, + FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"), + ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, + ext_cap->fine_time_meas_responder); +} + +/** + * 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: CDF_STATUS + */ +CDF_STATUS 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; + cds_msg_t msg = {0}; + tSirRetStatus status; + uint8_t *temp, i; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &dot11mode); + if (IS_DOT11_MODE_VHT(dot11mode)) + vht_enabled = true; + + status = populate_dot11f_ext_cap(mac_ctx, vht_enabled, &ext_cap_data, + NULL); + if (eSIR_SUCCESS != status) { + lim_log(mac_ctx, LOGE, FL("Failed to populate ext cap IE")); + return CDF_STATUS_E_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 = cdf_mem_malloc(sizeof(*vdev_ie) + num_bytes); + if (!vdev_ie) { + lim_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + + vdev_ie->vdev_id = session_id; + vdev_ie->ie_id = DOT11F_EID_EXTCAP; + vdev_ie->length = num_bytes; + + lim_log(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++) + lim_log(mac_ctx, LOG1, FL("%d byte is %02x"), i+1, *temp); + + vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie); + cdf_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes); + + msg.type = WMA_SET_IE_INFO; + msg.bodyptr = vdev_ie; + msg.reserved = 0; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + lim_log(mac_ctx, LOGE, + FL("Not able to post WMA_SET_IE_INFO to WDA")); + cdf_mem_free(vdev_ie); + return CDF_STATUS_E_FAILURE; + } + + return CDF_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) { + lim_log(mac_ctx, LOG1, FL("NULL addn_ie pointer")); + return eSIR_IGNORE_IE; + } + + tempbuf = cdf_mem_malloc(left); + if (NULL == tempbuf) { + lim_log(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) { + lim_log(mac_ctx, LOGE, + FL("Invalid IEs eid = %d elem_len=%d left=%d"), + elem_id, elem_len, left); + cdf_mem_free(tempbuf); + return eSIR_FAILURE; + } + if (!(DOT11F_EID_EXTCAP == elem_id)) { + cdf_mem_copy(tempbuf + templen, &ptr[0], elem_len + 2); + templen += (elem_len + 2); + } else { + if (NULL != extracted_ie) { + cdf_mem_set(extracted_ie, + DOT11F_IE_EXTCAP_MAX_LEN + 2, 0); + if (elem_len <= DOT11F_IE_EXTCAP_MAX_LEN) + cdf_mem_copy(extracted_ie, &ptr[0], + elem_len + 2); + } + } + left -= elem_len; + ptr += (elem_len + 2); + } + cdf_mem_copy(addn_ie, tempbuf, templen); + + *addn_ielen = templen; + cdf_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) { + lim_log(mac_ctx, LOGE, FL("Invalid Buffer Address")); + return; + } + + if (NULL == dst) { + lim_log(mac_ctx, LOGE, FL("NULL dst pointer")); + return; + } + + if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) { + lim_log(mac_ctx, LOG1, FL("Invalid IEs eid = %d elem_len=%d "), + buf[0], buf[1]); + return; + } + + cdf_mem_set((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN, 0); + cdf_mem_copy(&out[0], &buf[2], DOT11F_IE_EXTCAP_MAX_LEN); + + if (DOT11F_PARSE_SUCCESS != dot11f_unpack_ie_ext_cap(mac_ctx, &out[0], + DOT11F_IE_EXTCAP_MAX_LEN, dst)) + lim_log(mac_ctx, LOGE, FL("dot11f_unpack 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; + + cdf_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) { + lim_log(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++; + } +} + diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h new file mode 100644 index 000000000000..76b000cdd342 --- /dev/null +++ b/core/mac/src/pe/lim/lim_utils.h @@ -0,0 +1,591 @@ +/* + * 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 lim_utils.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 "sir_api.h" +#include "sir_debug.h" +#include "cfg_api.h" + +#include "lim_types.h" +#include "lim_scan_result_utils.h" +#include "lim_timer_utils.h" +#include "lim_trace.h" +typedef enum { + ONE_BYTE = 1, + TWO_BYTE = 2 +} eSizeOfLenField; + +#define MIN_TX_PWR_CAP 8 +#define MAX_TX_PWR_CAP 22 + +#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 VHT_MCS_3x3_MASK 0x30 +#define VHT_MCS_2x2_MASK 0x0C + +#ifdef WLAN_FEATURE_11W +typedef union uPmfSaQueryTimerId { + struct { + uint8_t sessionId; + uint16_t peerIdx; + } fields; + uint32_t value; +} tPmfSaQueryTimerId, *tpPmfSaQueryTimerId; +#endif + +/* LIM utility functions */ +void limGetBssidFromPkt(tpAniSirGlobal, uint8_t *, uint8_t *, uint32_t *); +char *lim_dot11_reason_str(uint16_t reasonCode); +char *lim_mlm_state_str(tLimMlmStates state); +char *lim_sme_state_str(tLimSmeStates state); +char *lim_msg_str(uint32_t msgType); +char *lim_result_code_str(tSirResultCodes resultCode); +char *lim_dot11_mode_str(tpAniSirGlobal pMac, uint8_t dot11Mode); +void lim_print_mlm_state(tpAniSirGlobal pMac, uint16_t logLevel, + tLimMlmStates state); +void lim_print_sme_state(tpAniSirGlobal pMac, uint16_t logLevel, + tLimSmeStates state); +void lim_print_msg_name(tpAniSirGlobal pMac, uint16_t logLevel, uint32_t msgType); + +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI +extern tSirRetStatus lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, + tPowerdBm txPower, + tpPESession pSessionEntry); +extern uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower, + uint8_t iniTxPower); +#endif +uint8_t lim_is_addr_bc(tSirMacAddr); +uint8_t lim_is_group_addr(tSirMacAddr); + +/* check for type of scan allowed */ +uint8_t lim_active_scan_allowed(tpAniSirGlobal, uint8_t); + +/* AID pool management functions */ +void lim_init_peer_idxpool(tpAniSirGlobal, tpPESession); +uint16_t lim_assign_peer_idx(tpAniSirGlobal, tpPESession); + +void lim_enable_overlap11g_protection(tpAniSirGlobal pMac, + tpUpdateBeaconParams pBeaconParams, + tpSirMacMgmtHdr pMh, + tpPESession psessionEntry); +void lim_update_overlap_sta_param(tpAniSirGlobal pMac, tSirMacAddr bssId, + tpLimProtStaParams pStaParams); +void lim_update_short_preamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); +void lim_update_short_slot_time(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); + +/* + * The below 'product' check tobe removed if 'Association' is + * allowed in IBSS. + */ +void lim_release_peer_idx(tpAniSirGlobal, uint16_t, tpPESession); + +void lim_decide_ap_protection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, + tpUpdateBeaconParams pBeaconParams, tpPESession); +void lim_decide_ap_protection_on_delete(tpAniSirGlobal pMac, + tpDphHashNode pStaDs, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); + +extern tSirRetStatus lim_update_11a_protection(tpAniSirGlobal pMac, + uint8_t enable, + uint8_t overlap, + tpUpdateBeaconParams pBeaconParams, + tpPESession); +extern tSirRetStatus lim_enable11g_protection(tpAniSirGlobal pMac, + uint8_t enable, + uint8_t overlap, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); +extern tSirRetStatus lim_enable_ht_protection_from11g(tpAniSirGlobal pMac, + uint8_t enable, + uint8_t overlap, + tpUpdateBeaconParams + pBeaconParams, + tpPESession psessionEntry); +extern tSirRetStatus lim_enable_ht20_protection(tpAniSirGlobal pMac, + uint8_t enable, uint8_t overlap, + tpUpdateBeaconParams pBeaconParams, + tpPESession sessionEntry); +extern tSirRetStatus lim_enable_ht_non_gf_protection(tpAniSirGlobal pMac, + uint8_t enable, uint8_t overlap, + tpUpdateBeaconParams + pBeaconParams, tpPESession); +extern tSirRetStatus lim_enable_ht_rifs_protection(tpAniSirGlobal pMac, + uint8_t enable, uint8_t overlap, + tpUpdateBeaconParams + pBeaconParams, + tpPESession psessionEntry); +extern tSirRetStatus lim_enable_ht_lsig_txop_protection(tpAniSirGlobal pMac, + uint8_t enable, + uint8_t overlap, + tpUpdateBeaconParams + pBeaconParams, tpPESession); +extern tSirRetStatus lim_enable_short_preamble(tpAniSirGlobal pMac, + uint8_t enable, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); +extern tSirRetStatus lim_enable_ht_obss_protection(tpAniSirGlobal pMac, + uint8_t enable, uint8_t overlap, + tpUpdateBeaconParams + pBeaconParams, tpPESession); +void lim_decide_sta_protection(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeaconStruct, + tpUpdateBeaconParams pBeaconParams, + tpPESession psessionEntry); +void lim_decide_sta_protection_on_assoc(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeaconStruct, + tpPESession psessionEntry); +void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pHTInfo, + uint8_t bssIdx, + tpPESession psessionEntry); +/* Print MAC address utility function */ +void lim_print_mac_addr(tpAniSirGlobal, tSirMacAddr, uint8_t); + +/* Deferred Message Queue read/write */ +uint8_t lim_write_deferred_msg_q(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirMsgQ *lim_read_deferred_msg_q(tpAniSirGlobal pMac); +void lim_handle_defer_msg_error(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg); + +/* Deferred Message Queue Reset */ +void lim_reset_deferred_msg_q(tpAniSirGlobal pMac); + +tSirRetStatus lim_sys_process_mmh_msg_api(tpAniSirGlobal, tSirMsgQ *, uint8_t); + +void lim_handle_update_olbc_cache(tpAniSirGlobal pMac); + +uint8_t lim_is_null_ssid(tSirMacSSid *pSsid); + +/* 11h Support */ +void lim_stop_tx_and_switch_channel(tpAniSirGlobal pMac, uint8_t sessionId); +void lim_process_channel_switch_timeout(tpAniSirGlobal); +tSirRetStatus lim_start_channel_switch(tpAniSirGlobal pMac, + tpPESession psessionEntry); +void lim_update_channel_switch(tpAniSirGlobal, tpSirProbeRespBeacon, + tpPESession psessionEntry); +void lim_process_quiet_timeout(tpAniSirGlobal); +void lim_process_quiet_bss_timeout(tpAniSirGlobal); + +void lim_start_quiet_timer(tpAniSirGlobal pMac, uint8_t sessionId); +void lim_switch_primary_channel(tpAniSirGlobal, uint8_t, tpPESession); +void lim_switch_primary_secondary_channel(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint8_t newChannel, + uint8_t ch_center_freq_seg0, + uint8_t ch_center_freq_seg1, + phy_ch_width ch_width); +void limUpdateStaRunTimeHTSwtichChnlParams(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pRcvdHTInfo, + uint8_t bssIdx); +void lim_update_sta_run_time_ht_capability(tpAniSirGlobal pMac, + tDot11fIEHTCaps *pHTCaps); +void lim_update_sta_run_time_ht_info(struct sAniSirGlobal *pMac, + tDot11fIEHTInfo *pRcvdHTInfo, + tpPESession psessionEntry); +void lim_cancel_dot11h_channel_switch(tpAniSirGlobal pMac, + tpPESession psessionEntry); +void lim_cancel_dot11h_quiet(tpAniSirGlobal pMac, tpPESession psessionEntry); +tAniBool lim_is_channel_valid_for_channel_switch(tpAniSirGlobal pMac, + uint8_t channel); +void lim_frame_transmission_control(tpAniSirGlobal pMac, tLimQuietTxMode type, + tLimControlTx mode); +tSirRetStatus lim_restore_pre_channel_switch_state(tpAniSirGlobal pMac, + tpPESession psessionEntry); +tSirRetStatus lim_restore_pre_quiet_state(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +void lim_prepare_for11h_channel_switch(tpAniSirGlobal pMac, + tpPESession psessionEntry); +void lim_switch_channel_cback(tpAniSirGlobal pMac, CDF_STATUS status, + uint32_t *data, tpPESession psessionEntry); + +static inline tSirRFBand lim_get_rf_band(uint8_t 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 +lim_get_mgmt_staid(tpAniSirGlobal pMac, uint16_t *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 uint8_t lim_is_system_in_set_mimops_state(tpAniSirGlobal pMac) +{ + if (pMac->lim.gLimMlmState == eLIM_MLM_WT_SET_MIMOPS_STATE) + return true; + return false; +} + +static inline uint8_t +is_entering_mimo_ps(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 lim_select_cb_mode(tDphHashNode *pStaDs, + tpPESession psessionEntry, uint8_t channel, + uint8_t 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 lim_util_count_sta_add(tpAniSirGlobal pMac, tpDphHashNode pSta, + tpPESession psessionEntry); +void lim_util_count_sta_del(tpAniSirGlobal pMac, tpDphHashNode pSta, + tpPESession psessionEntry); + +uint8_t lim_get_ht_capability(tpAniSirGlobal, uint32_t, tpPESession); +void lim_tx_complete(tHalHandle hHal, void *pData, bool free); + +/** + * This function will be registered with HAL for callback when TSPEC inactivity + * timer fires. + */ + +void lim_process_del_ts_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +tSirRetStatus lim_process_hal_ind_messages(tpAniSirGlobal pMac, uint32_t mesgId, + void *mesgParam); +tSirRetStatus lim_validate_delts_req(tpAniSirGlobal pMac, + tpSirDeltsReq pDeltsReq, + tSirMacAddr peerMacAddr, + tpPESession psessionEntry); + +/* callback function registration to HAL for any indication. */ +void lim_register_hal_ind_call_back(tpAniSirGlobal pMac); +void lim_pkt_free(tpAniSirGlobal pMac, + eFrameType frmType, uint8_t *pBD, void *body); + +void lim_get_b_dfrom_rx_packet(tpAniSirGlobal pMac, void *body, uint32_t **pBD); + +/** + * utils_power_xy() - calc result of base raised to power + * @base: Base value + * @power: Base raised to this Power value + * + * Given a base(X) and power(Y), this API will return + * the result of base raised to power - (X ^ Y) + * + * Return: Result of X^Y + * + */ +static inline uint32_t utils_power_xy(uint16_t base, uint16_t power) +{ + uint32_t result = 1, i; + + for (i = 0; i < power; i++) + result *= base; + + return result; +} + +tSirRetStatus lim_post_sm_state_update(tpAniSirGlobal pMac, + uint16_t StaIdx, + tSirMacHTMIMOPowerSaveState MIMOPSState, + uint8_t *pPeerStaMac, uint8_t sessionId); + +void lim_delete_sta_context(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void lim_delete_dialogue_token_list(tpAniSirGlobal pMac); +void lim_resset_scan_channel_info(tpAniSirGlobal pMac); +uint8_t lim_get_channel_from_beacon(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon); +tSirNwType lim_get_nw_type(tpAniSirGlobal pMac, uint8_t channelNum, + uint32_t type, tpSchBeaconStruct pBeacon); + +void lim_set_tspec_uapsd_mask_per_session(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacTSInfo *pTsInfo, uint32_t action); + +void lim_handle_heart_beat_timeout_for_session(tpAniSirGlobal pMac, + tpPESession psessionEntry); + +void lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ pMsgQ); + +void lim_update_beacon(tpAniSirGlobal pMac); + +void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, + tpPESession psessionEntry); +void lim_process_bt_amp_ap_mlm_del_bss_rsp(tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ, + tpPESession psessionEntry); + +void lim_process_bt_amp_ap_mlm_del_sta_rsp(tpAniSirGlobal pMac, + tpSirMsgQ limMsgQ, + tpPESession psessionEntry); + +tpPESession lim_is_ibss_session_active(tpAniSirGlobal pMac); +tpPESession lim_is_ap_session_active(tpAniSirGlobal pMac); +void lim_handle_heart_beat_failure_timeout(tpAniSirGlobal pMac); + +uint8_t *lim_get_ie_ptr_new(tpAniSirGlobal pMac, uint8_t *pIes, int length, + uint8_t eid, eSizeOfLenField size_of_len_field); + +#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) + +uint8_t lim_get_noa_attr_stream_in_mult_p2p_ies(tpAniSirGlobal pMac, + uint8_t *noaStream, uint8_t noaLen, + uint8_t overFlowLen); +uint8_t lim_get_noa_attr_stream(tpAniSirGlobal pMac, uint8_t *pNoaStream, + tpPESession psessionEntry); + +uint8_t lim_build_p2p_ie(tpAniSirGlobal pMac, uint8_t *ie, uint8_t *data, + uint8_t ie_len); +bool lim_is_noa_insert_reqd(tpAniSirGlobal pMac); +bool lim_isconnected_on_dfs_channel(uint8_t currentChannel); +uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac); + +#ifdef WLAN_FEATURE_11AC +bool lim_check_vht_op_mode_change(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint8_t chanWidth, uint8_t staId, + uint8_t *peerMac); +bool lim_set_nss_change(tpAniSirGlobal pMac, tpPESession psessionEntry, + uint8_t rxNss, uint8_t staId, uint8_t *peerMac); +bool lim_check_membership_user_position(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint32_t membership, uint32_t userPosition, + uint8_t 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_IND_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, + WLAN_PE_DIAG_DELTS_REQ_EVENT = 30, + 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_UAPSD_REQ_EVENT, + WLAN_PE_DIAG_ENTER_UAPSD_RSP_EVENT, + WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT = 40, + 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, + WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT, + WLAN_PE_DIAG_EXIT_WOWL_RSP_EVENT, + WLAN_PE_DIAG_HB_FAILURE_TIMEOUT, + WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, + WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT = 50, + WLAN_PE_DIAG_PREAUTH_DONE, + WLAN_PE_DIAG_REASSOCIATING, + 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 = 60, + WLAN_PE_DIAG_ROAM_AUTH_COMP_EVENT, + WLAN_PE_DIAG_ROAM_ASSOC_START_EVENT, + WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT, + RESERVED1, /* = 64 for SCAN_COMPLETE */ + RESERVED2, /* = 65 for SCAN_RES_FOUND */ +} WLAN_PE_DIAG_EVENT_TYPE; + +void lim_diag_event_report(tpAniSirGlobal pMac, uint16_t eventType, + tpPESession pSessionEntry, uint16_t status, + uint16_t reasonCode); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +void pe_set_resume_channel(tpAniSirGlobal pMac, uint16_t channel, + ePhyChanBondState cbState); + +void lim_get_short_slot_from_phy_mode(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint32_t phyMode, uint8_t *pShortSlotEnable); + +void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal pMac, uint8_t *staMac, + bool cleanRxPath); + +bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal pMac, + uint8_t *staMac); + +#ifdef WLAN_FEATURE_11W +void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param); +#endif + +void lim_set_protected_bit(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr); + +#ifdef WLAN_FEATURE_11W +void lim_pmf_comeback_timer_callback(void *context); +#endif /* WLAN_FEATURE_11W */ + +void lim_set_ht_caps(tpAniSirGlobal p_mac, + tpPESession p_session_ntry, + uint8_t *p_ie_start, + uint32_t num_bytes); + +#ifdef WLAN_FEATURE_11AC +void lim_set_vht_caps(tpAniSirGlobal p_mac, + tpPESession p_session_entry, + uint8_t *p_ie_start, + uint32_t num_bytes); +#endif /* WLAN_FEATURE_11AC */ +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, + tpAniSirGlobal mac_ctx); + +void lim_check_and_reset_protection_params(tpAniSirGlobal mac_ctx); + +CDF_STATUS 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); + +#endif /* __LIM_UTILS_H */ diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c new file mode 100644 index 000000000000..5b85bf9a73c8 --- /dev/null +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -0,0 +1,1495 @@ +/* + * 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 rrm_api.c + + \brief implementation for PE RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +#if defined WLAN_FEATURE_VOWIFI + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cds_api.h" +#include "wni_api.h" +#include "sir_api.h" +#include "ani_global.h" +#include "wni_cfg.h" +#include "lim_types.h" +#include "lim_utils.h" +#include "lim_send_sme_rsp_messages.h" +#include "parser_api.h" +#include "lim_send_messages.h" +#include "rrm_global.h" +#include "rrm_api.h" + +uint8_t +rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, + tPowerdBm regMax, tPowerdBm apTxPower) +{ + uint8_t maxTxPower = 0; + uint8_t txPower = CDF_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; + + lim_log(pMac, LOG3, + "%s: regulatoryMax = %d, apTxPwr = %d, maxTxpwr = %d", + __func__, regMax, apTxPower, maxTxPower); + return maxTxPower; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_cache_mgmt_tx_power + ** + * FUNCTION: Store Tx power for management frames. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry session entry. + * @return None + */ +void +rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, tPowerdBm txPower, + tpPESession pSessionEntry) +{ + lim_log(pMac, LOG3, "Cache Mgmt Tx Power = %d", txPower); + + if (pSessionEntry == NULL) { + lim_log(pMac, LOG3, "%s: pSessionEntry is NULL", __func__); + pMac->rrm.rrmPEContext.txMgmtPower = txPower; + } else + pSessionEntry->txMgmtPower = txPower; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_get_mgmt_tx_power + * + * FUNCTION: Get the Tx power for management frames. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry session entry. + * @return txPower + */ +tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + lim_log(pMac, LOG3, "RrmGetMgmtTxPower called"); + + if (pSessionEntry == NULL) { + lim_log(pMac, LOG3, "%s: txpower from rrmPEContext: %d", + __func__, pMac->rrm.rrmPEContext.txMgmtPower); + return pMac->rrm.rrmPEContext.txMgmtPower; + } + + return pSessionEntry->txMgmtPower; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_send_set_max_tx_power_req + * + * FUNCTION: Send WMA_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 +rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, + tpPESession pSessionEntry) +{ + tpMaxTxPowerParams pMaxTxParams; + tSirRetStatus retCode = eSIR_SUCCESS; + tSirMsgQ msgQ; + + if (pSessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));) + return eSIR_FAILURE; + } + pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams)); + if (NULL == pMaxTxParams) { + lim_log(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; + cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, + sizeof(tSirMacAddr)); + + msgQ.type = WMA_SET_MAX_TX_POWER_REQ; + msgQ.reserved = 0; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + + lim_log(pMac, LOG3, + FL("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL"), + txPower); + + MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type)); + if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) { + lim_log(pMac, LOGP, + FL + ("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X"), + retCode); + cdf_mem_free(pMaxTxParams); + return retCode; + } + return retCode; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_set_max_tx_power_rsp + * + * FUNCTION: Process WMA_SET_MAX_TX_POWER_RSP message. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param txPower txPower to be set. + * @param pSessionEntry session entry. + * @return None + */ +tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) +{ + tSirRetStatus retCode = eSIR_SUCCESS; + tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; + tpPESession pSessionEntry; + uint8_t sessionId, i; + tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + if (cdf_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]; + rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power, + pSessionEntry); + } + } + } else { + if ((pSessionEntry = + pe_find_session_by_bssid(pMac, pMaxTxParams->bssId, + &sessionId)) == NULL) { + PELOGE(lim_log + (pMac, LOGE, FL("Unable to find session:")); + ) + retCode = eSIR_FAILURE; + } else { + rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power, + pSessionEntry); + } + } + + cdf_mem_free(limMsgQ->bodyptr); + limMsgQ->bodyptr = NULL; + return retCode; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_link_measurement_request + * + * 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 +rrm_process_link_measurement_request(tpAniSirGlobal pMac, + uint8_t *pRxPacketInfo, + tDot11fLinkMeasurementRequest *pLinkReq, + tpPESession pSessionEntry) +{ + tSirMacLinkReport LinkReport; + tpSirMacMgmtHdr pHdr; + int8_t currentRSSI = 0; + + lim_log(pMac, LOG3, "Received Link measurement request"); + + if (pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, + "%s Invalid parameters - Ignoring the request", + __func__); + ) + return eSIR_FAILURE; + } + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + + LinkReport.txPower = lim_get_max_tx_power(pLinkReq->MaxTxPower.maxTxPower, + pLinkReq->MaxTxPower.maxTxPower, + pMac->roam.configParam. + nTxPowerCap); + + if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) && + (eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac, + (tPowerdBm) (LinkReport. + txPower), + pSessionEntry))) { + PELOGW(lim_log + (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 = WMA_GET_RX_RSSI_DB(pRxPacketInfo); + + lim_log(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 = WMA_GET_RX_SNR(pRxPacketInfo); + + lim_log(pMac, LOG3, "Sending Link report frame"); + + return lim_send_link_report_action_frame(pMac, &LinkReport, pHdr->sa, + pSessionEntry); +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_neighbor_report_response + * + * 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 +rrm_process_neighbor_report_response(tpAniSirGlobal pMac, + tDot11fNeighborReportResponse *pNeighborRep, + tpPESession pSessionEntry) +{ + tSirRetStatus status = eSIR_FAILURE; + tpSirNeighborReportInd pSmeNeighborRpt = NULL; + uint16_t length; + uint8_t i; + tSirMsgQ mmhMsg; + + if (pNeighborRep == NULL || pSessionEntry == NULL) { + PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));) + return status; + } + + lim_log(pMac, LOG3, FL("Neighbor report response received ")); + + /* Dialog token */ + if (pMac->rrm.rrmPEContext.DialogToken != + pNeighborRep->DialogToken.token) { + PELOGE(lim_log + (pMac, LOGE, + "Dialog token mismatch in the received Neighbor report"); + ) + return eSIR_FAILURE; + } + if (pNeighborRep->num_NeighborReport == 0) { + PELOGE(lim_log + (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 = cdf_mem_malloc(length); + if (NULL == pSmeNeighborRpt) { + PELOGE(lim_log(pMac, LOGP, FL("Unable to allocate memory"));) + return eSIR_MEM_ALLOC_FAILED; + + } + cdf_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 */ + cdf_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; + cdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId, + sizeof(tSirMacAddr)); + + /* Send request to SME. */ + mmhMsg.type = pSmeNeighborRpt->messageType; + mmhMsg.bodyptr = pSmeNeighborRpt; + MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type)); + status = lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + + return status; + +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_neighbor_report_req + * + * FUNCTION: + * + * LOGIC: Create a Neighbor report request and send it to peer. + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pNeighborReq Neighbor report request params . + * @return None + */ +tSirRetStatus +rrm_process_neighbor_report_req(tpAniSirGlobal pMac, + tpSirNeighborReportReqInd pNeighborReq) +{ + tSirRetStatus status = eSIR_SUCCESS; + tSirMacNeighborReportReq NeighborReportReq; + tpPESession pSessionEntry; + uint8_t sessionId; + + if (pNeighborReq == NULL) { + PELOGE(lim_log(pMac, LOGE, "NeighborReq is NULL");) + return eSIR_FAILURE; + } + if ((pSessionEntry = + pe_find_session_by_bssid(pMac, pNeighborReq->bssId, + &sessionId)) == NULL) { + PELOGE(lim_log + (pMac, LOGE, + FL("session does not exist for given bssId")); + ) + return eSIR_FAILURE; + } + + lim_log(pMac, LOG1, FL("SSID present = %d "), pNeighborReq->noSSID); + + cdf_mem_set(&NeighborReportReq, sizeof(tSirMacNeighborReportReq), 0); + + NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken; + NeighborReportReq.ssid_present = !pNeighborReq->noSSID; + if (NeighborReportReq.ssid_present) { + cdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID, + sizeof(tSirMacSSid)); + PELOGE(sir_dump_buf + (pMac, SIR_LIM_MODULE_ID, LOGE, + (uint8_t *) NeighborReportReq.ssid.ssId, + NeighborReportReq.ssid.length); + ) + } + + status = + lim_send_neighbor_report_request_frame(pMac, &NeighborReportReq, + pNeighborReq->bssId, + pSessionEntry); + + return status; +} + +#define ABS(x) ((x < 0) ? -x : x) +/* -------------------------------------------------------------------- */ +/** + * rrm_process_beacon_report_req + * + * FUNCTION: Processes the Beacon report request from the peer AP. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pCurrentReq pointer to the current Req comtext. + * @param pBeaconReq pointer to the beacon report request IE from the peer. + * @param pSessionEntry session entry. + * @return None + */ +static tRrmRetStatus +rrm_process_beacon_report_req(tpAniSirGlobal pMac, + tpRRMReq pCurrentReq, + tDot11fIEMeasurementRequest *pBeaconReq, + tpPESession pSessionEntry) +{ + tSirMsgQ mmhMsg; + tpSirBeaconReportReqInd pSmeBcnReportReq; + uint8_t num_channels = 0, num_APChanReport; + uint16_t measDuration, maxMeasduration; + int8_t maxDuration; + uint8_t 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 repetitons is zero. */ + /* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */ + + PELOGE(lim_log + (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; + + lim_log(pMac, LOG3, + "maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d", + maxDuration, sign, maxMeasduration, measDuration); + + if (maxMeasduration < measDuration) { + if (pBeaconReq->durationMandatory) { + PELOGE(lim_log + (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 = + cdf_mem_malloc(sizeof(uint8_t) * + pBeaconReq->measurement_request.Beacon. + RequestedInfo.num_requested_eids); + if (NULL == pCurrentReq->request.Beacon.reqIes.pElementIds) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory for request IEs buffer")); + return eRRM_FAILURE; + } + lim_log(pMac, LOG3, FL(" Allocated memory for pElementIds")); + + pCurrentReq->request.Beacon.reqIes.num = + pBeaconReq->measurement_request.Beacon.RequestedInfo. + num_requested_eids; + cdf_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 = cdf_mem_malloc(sizeof(tSirBeaconReportReqInd)); + if (NULL == pSmeBcnReportReq) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during Beacon Report Req Ind to SME")); + + return eRRM_FAILURE; + + } + + cdf_mem_set(pSmeBcnReportReq, sizeof(tSirBeaconReportReqInd), 0); + + /* Allocated memory for pSmeBcnReportReq....will be freed by other modulea */ + cdf_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; + cdf_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; + cdf_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) { + uint8_t *pChanList = + pSmeBcnReportReq->channelList.channelNumber; + for (num_APChanReport = 0; + num_APChanReport < + pBeaconReq->measurement_request.Beacon.num_APChannelReport; + num_APChanReport++) { + cdf_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(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type)); + return lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_fill_beacon_ies + * + * FUNCTION: + * + * LOGIC: Fills Fixed fields and Ies in bss description to an array of uint8_t. + * + * 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 +rrm_fill_beacon_ies(tpAniSirGlobal pMac, + uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize, + uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc) +{ + uint8_t len, *pBcnIes, count = 0, i; + uint8_t BcnNumIes; + + if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) { + PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));) + return; + } + /* Make sure that if eid is null, numEids is set to zero. */ + numEids = (eids == NULL) ? 0 : numEids; + + pBcnIes = (uint8_t *) &pBssDesc->ieFields[0]; + BcnNumIes = (uint8_t) GET_IE_LEN_IN_BSS(pBssDesc->length); + + *pNumIes = 0; + + *((uint32_t *) pIes) = pBssDesc->timeStamp[0]; + *pNumIes += sizeof(uint32_t); + pIes += sizeof(uint32_t); + *((uint32_t *) pIes) = pBssDesc->timeStamp[1]; + *pNumIes += sizeof(uint32_t); + pIes += sizeof(uint32_t); + *((uint16_t *) pIes) = pBssDesc->beaconInterval; + *pNumIes += sizeof(uint16_t); + pIes += sizeof(uint16_t); + *((uint16_t *) pIes) = pBssDesc->capabilityInfo; + *pNumIes += sizeof(uint16_t); + pIes += sizeof(uint16_t); + + while (BcnNumIes > 0) { + len = *(pBcnIes + 1) + 2; /* element id + length. */ + lim_log(pMac, LOG3, "EID = %d, len = %d total = %d", + *pBcnIes, *(pBcnIes + 1), len); + + i = 0; + do { + if (((eids == NULL) || (*pBcnIes == eids[i])) && + ((*pNumIes) + len) < pIesMaxSize) { + lim_log(pMac, LOG3, "Adding Eid %d, len=%d", + *pBcnIes, len); + + cdf_mem_copy(pIes, pBcnIes, len); + pIes += len; + *pNumIes += len; + count++; + break; + } + i++; + } while (i < numEids); + + pBcnIes += len; + BcnNumIes -= len; + } + lim_log(pMac, LOG1, "Total length of Ies added = %d", *pNumIes); +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_beacon_report_xmit + * + * 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 +rrm_process_beacon_report_xmit(tpAniSirGlobal pMac, + tpSirBeaconReportXmitInd pBcnReport) +{ + tSirRetStatus status = eSIR_SUCCESS; + tSirMacRadioMeasureReport *pReport = NULL; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + tpPESession pSessionEntry; + uint8_t sessionId; + uint8_t flagBSSPresent = false, bssDescCnt = 0; + + lim_log(pMac, LOG1, "Received beacon report xmit indication"); + + if (NULL == pBcnReport) { + PELOGE(lim_log(pMac, LOGE, "Received pBcnReport is NULL in PE");) + return eSIR_FAILURE; + } + + if (NULL == pCurrentReq) { + PELOGE(lim_log(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 = pe_find_session_by_bssid(pMac, + pBcnReport-> + bssId, + &sessionId))) + { + PELOGE(lim_log + (pMac, LOGE, + FL("session does not exist for given bssId")); + ) + return eSIR_FAILURE; + } + + pReport = cdf_mem_malloc(pBcnReport->numBssDesc * + sizeof(tSirMacRadioMeasureReport)); + + if (NULL == pReport) { + PELOGE(lim_log + (pMac, LOGE, + FL("RRM Report is NULL, allocation failed")); + ) + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_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; + cdf_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; + cdf_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. */ + lim_log(pMac, LOG3, + "No reporting detail requested"); + break; + case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE: + /* 1: Include all FFs and Requested Ies. */ + lim_log(pMac, LOG3, + "Only requested IEs in reporting detail requested"); + + if (flagBSSPresent) { + rrm_fill_beacon_ies(pMac, + (uint8_t *) & + pReport + [bssDescCnt]. + report. + beaconReport. + Ies[0], + (uint8_t *) & + 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: + lim_log(pMac, LOG3, + "Default all IEs and FFs"); + if (flagBSSPresent) { + rrm_fill_beacon_ies(pMac, + (uint8_t *) & + pReport + [bssDescCnt]. + report. + beaconReport. + Ies[0], + (uint8_t *) & + pReport + [bssDescCnt]. + report. + beaconReport. + numIes, + BEACON_REPORT_MAX_IES, + NULL, 0, + pBcnReport-> + pBssDescription + [bssDescCnt]); + } + break; + } + } + } + + lim_log(pMac, LOG1, "Sending Action frame with %d bss info", + bssDescCnt); + lim_send_radio_measure_report_action_frame(pMac, + pCurrentReq->dialog_token, + bssDescCnt, pReport, + pBcnReport->bssId, + pSessionEntry); + + pCurrentReq->sendEmptyBcnRpt = false; + } + + if (pBcnReport->fMeasureDone) { + lim_log(pMac, LOG3, "Measurement done....cleanup the context"); + + rrm_cleanup(pMac); + } + + if (NULL != pReport) + cdf_mem_free(pReport); + + return status; +} + +void rrm_process_beacon_request_failure(tpAniSirGlobal pMac, + tpPESession pSessionEntry, tSirMacAddr peer, + tRrmRetStatus status) +{ + tpSirMacRadioMeasureReport pReport = NULL; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + + pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); + if (NULL == pReport) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + return; + } + cdf_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(lim_log(pMac, LOGE, + FL + (" Beacon request processing failed no report sent with status %d "), + status); + ); + cdf_mem_free(pReport); + return; + } + + lim_send_radio_measure_report_action_frame(pMac, pCurrentReq->dialog_token, 1, + pReport, peer, pSessionEntry); + + cdf_mem_free(pReport); + lim_log(pMac, LOG3, FL(" Free memory for pReport")); + return; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_radio_measurement_request + * + * 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 +rrm_process_radio_measurement_request(tpAniSirGlobal pMac, + tSirMacAddr peer, + tDot11fRadioMeasurementRequest *pRRMReq, + tpPESession pSessionEntry) +{ + uint8_t i; + tSirRetStatus status = eSIR_SUCCESS; + tpSirMacRadioMeasureReport pReport = NULL; + uint8_t num_report = 0; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + tRrmRetStatus rrmStatus = eRRM_SUCCESS; + + if (!pRRMReq->num_MeasurementRequest) { + /* No measurement requests.... */ + /* */ + pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); + if (NULL == pReport) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0); + PELOGE(lim_log(pMac, LOGE, + FL + ("No requestIes in the measurement request, sending incapable report")); + ) + pReport->incapable = 1; + num_report = 1; + lim_send_radio_measure_report_action_frame(pMac, + pRRMReq->DialogToken.token, + num_report, pReport, peer, + pSessionEntry); + cdf_mem_free(pReport); + return eSIR_FAILURE; + } + /* PF Fix */ + if (pRRMReq->NumOfRepetitions.repetitions > 0) { + lim_log(pMac, LOG1, + FL(" number of repetitions %d"), + pRRMReq->NumOfRepetitions.repetitions); + + /* Send a report with incapable bit set. Not supporting repetitions. */ + pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); + if (NULL == pReport) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0); + PELOGE(lim_log(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 = + cdf_mem_malloc(sizeof + (tSirMacRadioMeasureReport) + * + (pRRMReq-> + num_MeasurementRequest + - i)); + if (NULL == pReport) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set(pReport, + sizeof + (tSirMacRadioMeasureReport) + * + (pRRMReq-> + num_MeasurementRequest - + i), 0); + lim_log(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 = + cdf_mem_malloc(sizeof(*pCurrentReq)); + if (NULL == pCurrentReq) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + cdf_mem_free(pReport); + return eSIR_MEM_ALLOC_FAILED; + } + lim_log(pMac, LOG3, + FL(" Processing Beacon Report request")); + cdf_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 = + rrm_process_beacon_report_req(pMac, pCurrentReq, + &pRRMReq-> + MeasurementRequest + [i], + pSessionEntry); + if (eRRM_SUCCESS != rrmStatus) { + rrm_process_beacon_request_failure(pMac, + pSessionEntry, + peer, + rrmStatus); + rrm_cleanup(pMac); + } + } + break; + case SIR_MAC_RRM_LCI_TYPE: + case SIR_MAC_RRM_LOCATION_CIVIC_TYPE: + case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE: + lim_log(pMac, LOG1, + FL("RRM with type: %d sent to userspace"), + pRRMReq->MeasurementRequest[i].measurement_type); + break; + default: + /* Send a report with incapabale bit set. */ + if (pReport == NULL) /* Allocate memory to send reports for any subsequent requests. */ + { + pReport = + cdf_mem_malloc(sizeof + (tSirMacRadioMeasureReport) + * + (pRRMReq-> + num_MeasurementRequest - + i)); + if (NULL == pReport) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory during RRM Req processing")); + return eSIR_MEM_ALLOC_FAILED; + } + cdf_mem_set(pReport, + sizeof(tSirMacRadioMeasureReport) + * (pRRMReq->num_MeasurementRequest - + i), 0); + lim_log(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) { + lim_send_radio_measure_report_action_frame(pMac, + pRRMReq->DialogToken.token, + num_report, pReport, peer, + pSessionEntry); + + cdf_mem_free(pReport); + lim_log(pMac, LOG3, FL(" Free memory for pReport")); + } + return status; + +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_update_start_tsf + ** + * FUNCTION: Store start TSF of measurement. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param startTSF - TSF value at the start of measurement. + * @return None + */ +void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2]) +{ + pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0]; + pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1]; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_get_start_tsf + * + * FUNCTION: Get the Start TSF. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param startTSF - store star TSF in this buffer. + * @return txPower + */ +void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF) +{ + pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0]; + pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1]; + +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_get_capabilities + * + * FUNCTION: + * Returns a pointer to tpRRMCaps with all the caps enabled in RRM + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry + * @return pointer to tRRMCaps + */ +tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + return &pMac->rrm.rrmPEContext.rrmEnabledCaps; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_update_config + * + * FUNCTION: + * Update the configuration. This is called from lim_update_config. + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pSessionEntry + * @return pointer to tRRMCaps + */ +void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry) +{ + uint32_t val; + tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; + + if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("cfg get rrm enabled failed")); + return; + } + pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; + + if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_OPERATING_CHAN_MAX, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("cfg get rrm operating channel max measurement duration failed")); + return; + } + pRRMCaps->operatingChanMax = (uint8_t) val; + + if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL + ("cfg get rrm non-operating channel max measurement duration failed")); + return; + } + pRRMCaps->nonOperatingChanMax = (uint8_t) val; + + lim_log(pMac, LOG1, + "RRM enabled = %d OperatingChanMax = %d NonOperatingMax = %d", + pMac->rrm.rrmPEContext.rrmEnable, + pRRMCaps->operatingChanMax, pRRMCaps->nonOperatingChanMax); +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_initialize + * + * FUNCTION: + * Initialize RRM module + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @return None + */ + +tSirRetStatus rrm_initialize(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; + + cdf_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; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_cleanup + * + * FUNCTION: + * cleanup RRM module + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param mode + * @param rate + * @return None + */ + +tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac) +{ + if (pMac->rrm.rrmPEContext.pCurrentReq) { + if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes. + pElementIds) { + cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq-> + request.Beacon.reqIes.pElementIds); + lim_log(pMac, LOG4, FL(" Free memory for pElementIds")); + } + + cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq); + lim_log(pMac, LOG4, FL(" Free memory for pCurrentReq")); + } + + pMac->rrm.rrmPEContext.pCurrentReq = NULL; + return eSIR_SUCCESS; +} + +/* -------------------------------------------------------------------- */ +/** + * rrm_process_message + * + * FUNCTION: Processes the next received Radio Resource Management message + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + switch (pMsg->type) { + case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: + rrm_process_neighbor_report_req(pMac, pMsg->bodyptr); + break; + case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: + rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr); + break; + } + +} + +#endif diff --git a/core/mac/src/pe/sch/sch_api.c b/core/mac/src/pe/sch/sch_api.c new file mode 100644 index 000000000000..1a11104162bf --- /dev/null +++ b/core/mac/src/pe/sch/sch_api.c @@ -0,0 +1,625 @@ +/* + * 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 sch_api.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 "cds_api.h" +#include "ani_global.h" +#include "wni_cfg.h" + +#include "sir_mac_prot_def.h" +#include "sir_mac_prop_exts.h" +#include "sir_common.h" + +#include "cfg_api.h" + +#include "lim_api.h" + +#include "sch_api.h" +#include "sch_debug.h" + +#include "sch_sys_params.h" +#include "lim_trace.h" +#include "lim_types.h" + +#include "wma_types.h" + +/* -------------------------------------------------------------------- */ +/* */ +/* Static Variables */ +/* */ +/* ------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------- */ +/** + * sch_get_cfp_count + * + * FUNCTION: + * Function used by other Sirius modules to read CFPcount + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +uint8_t sch_get_cfp_count(tpAniSirGlobal pMac) +{ + return pMac->sch.schObject.gSchCFPCount; +} + +/* -------------------------------------------------------------------- */ +/** + * sch_get_cfp_dur_remaining + * + * FUNCTION: + * Function used by other Sirius modules to read CFPDuration remaining + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +uint16_t sch_get_cfp_dur_remaining(tpAniSirGlobal pMac) +{ + return pMac->sch.schObject.gSchCFPDurRemaining; +} + +/* -------------------------------------------------------------------- */ +/** + * sch_init_globals + * + * FUNCTION: + * Initialize globals + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void sch_init_globals(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.multipleSched = 1; + pMac->sch.maxPollTimeouts = 20; + pMac->sch.checkCfbFlagStuck = 0; +} + +/* -------------------------------------------------------------------- */ +/** + * sch_post_message + * + * FUNCTION: + * Post the beacon message to the scheduler message queue + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param pMsg pointer to message + * @return None + */ + +tSirRetStatus sch_post_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +{ + sch_process_message(pMac, pMsg); + + return eSIR_SUCCESS; +} + +/* --------------------------------------------------------------------------- */ +/** + * sch_send_start_scan_rsp + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void sch_send_start_scan_rsp(tpAniSirGlobal pMac) +{ + tSirMsgQ msgQ; + uint32_t retCode; + + PELOG1(sch_log(pMac, LOG1, FL("Sending LIM message to go into scan"));) + msgQ.type = SIR_SCH_START_SCAN_RSP; + if ((retCode = lim_post_msg_api(pMac, &msgQ)) != eSIR_SUCCESS) + sch_log(pMac, LOGE, + FL("Posting START_SCAN_RSP to LIM failed, reason=%X"), + retCode); +} + +/** + * sch_send_beacon_req + * + * FUNCTION: + * + * LOGIC: + * 1) SCH received SIR_SCH_BEACON_GEN_IND + * 2) SCH updates TIM IE and other beacon related IE's + * 3) SCH sends WMA_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 CDF_STATUS + */ +tSirRetStatus sch_send_beacon_req(tpAniSirGlobal pMac, uint8_t *beaconPayload, + uint16_t size, tpPESession psessionEntry) +{ + tSirMsgQ msgQ; + tpSendbeaconParams beaconParams = NULL; + tSirRetStatus retCode; + + sch_log(pMac, LOG2, + FL + ("Indicating HAL to copy the beacon template [%d bytes] to memory"), + size); + + beaconParams = cdf_mem_malloc(sizeof(tSendbeaconParams)); + if (NULL == beaconParams) + return eSIR_MEM_ALLOC_FAILED; + + msgQ.type = WMA_SEND_BEACON_REQ; + + /* No Dialog Token reqd, as a response is not solicited */ + msgQ.reserved = 0; + + /* Fill in tSendbeaconParams members */ + cdf_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 atleast greater than timIeOffset */ + if ((pMac->sch.schObject.p2pIeOffset != 0) && + (pMac->sch.schObject.p2pIeOffset < + psessionEntry->schBeaconOffsetBegin)) { + sch_log(pMac, LOGE, FL("Invalid p2pIeOffset:[%d]"), + pMac->sch.schObject.p2pIeOffset); + CDF_ASSERT(0); + cdf_mem_free(beaconParams); + return eSIR_FAILURE; + } + beaconParams->p2pIeOffset = pMac->sch.schObject.p2pIeOffset; +#ifdef WLAN_SOFTAP_FW_BEACON_TX_PRNT_LOG + sch_log(pMac, LOGE, FL("TimIeOffset:[%d]"), beaconParams->TimIeOffset); +#endif + + beaconParams->beacon = beaconPayload; + beaconParams->beaconLength = (uint32_t) size; + msgQ.bodyptr = beaconParams; + msgQ.bodyval = 0; + + /* Keep a copy of recent beacon frame sent */ + + /* free previous copy of the beacon */ + if (psessionEntry->beacon) { + cdf_mem_free(psessionEntry->beacon); + } + + psessionEntry->bcnLen = 0; + psessionEntry->beacon = NULL; + + psessionEntry->beacon = cdf_mem_malloc(size); + if (psessionEntry->beacon != NULL) { + cdf_mem_copy(psessionEntry->beacon, beaconPayload, size); + psessionEntry->bcnLen = size; + } + + MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); + if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) { + sch_log(pMac, LOGE, + FL("Posting SEND_BEACON_REQ to HAL failed, reason=%X"), + retCode); + } else { + sch_log(pMac, LOG2, + FL("Successfully posted WMA_SEND_BEACON_REQ to HAL")); + + if (LIM_IS_AP_ROLE(psessionEntry) && + (pMac->sch.schObject.fBeaconChanged)) { + if (eSIR_SUCCESS != + (retCode = + lim_send_probe_rsp_template_to_hal(pMac, psessionEntry, + &psessionEntry-> + DefProbeRspIeBitmap + [0]))) { + /* check whether we have to free any memory */ + sch_log(pMac, LOGE, + FL + ("FAILED to send probe response template with retCode %d"), + retCode); + } + } + } + + return retCode; +} + +uint32_t lim_remove_p2p_ie_from_add_ie(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint8_t *addIeWoP2pIe, + uint32_t *addnIELenWoP2pIe) +{ + uint32_t left = psessionEntry->addIeParams.probeRespDataLen; + uint8_t *ptr = psessionEntry->addIeParams.probeRespData_buff; + uint8_t elem_id,elem_len; + uint32_t offset = 0; + uint8_t eid = 0xDD; + + cdf_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) { + sch_log(pMac, LOGE, FL("Invalid IEs")); + return eSIR_FAILURE; + } + if ((elem_id == eid) && + (cdf_mem_compare(&ptr[2], + "\x50\x6f\x9a\x09", 4))) { + left -= elem_len; + ptr += (elem_len + 2); + cdf_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; +} + +uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal pMac, + tpPESession psessionEntry, + uint32_t *IeBitmap) +{ + tSirMsgQ msgQ; + uint8_t *pFrame2Hal = psessionEntry->pSchProbeRspTemplate; + tpSendProbeRespParams pprobeRespParams = NULL; + uint32_t retCode = eSIR_FAILURE; + uint32_t nPayload, nBytes, nStatus; + tpSirMacMgmtHdr pMacHdr; + uint32_t addnIEPresent = false; + uint32_t addnIELen = 0; + uint8_t *addIE = NULL; + uint8_t *addIeWoP2pIe = NULL; + uint32_t addnIELenWoP2pIe = 0; + uint32_t retStatus; + + nStatus = + dot11f_get_packed_probe_response_size(pMac, + &psessionEntry->probeRespFrame, + &nPayload); + if (DOT11F_FAILED(nStatus)) { + sch_log(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)) { + sch_log(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 = cdf_mem_malloc(psessionEntry->addIeParams. + probeRespDataLen); + if (NULL == addIeWoP2pIe) { + sch_log(pMac, LOGE, + FL("FAILED to alloc memory when removing P2P IE")); + return eSIR_MEM_ALLOC_FAILED; + } + + retStatus = lim_remove_p2p_ie_from_add_ie(pMac, psessionEntry, + addIeWoP2pIe, &addnIELenWoP2pIe); + if (retStatus != eSIR_SUCCESS) { + cdf_mem_free(addIeWoP2pIe); + return eSIR_FAILURE; + } + + /* Probe rsp IE available */ + /*need to check the data length */ + addIE = + cdf_mem_malloc(addnIELenWoP2pIe); + if (NULL == addIE) { + sch_log(pMac, LOGE, + FL + ("Unable to get WNI_CFG_PROBE_RSP_ADDNIE_DATA1 length")); + cdf_mem_free(addIeWoP2pIe); + return eSIR_MEM_ALLOC_FAILED; + } + addnIELen = addnIELenWoP2pIe; + + if (addnIELen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIELen + && (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) { + + cdf_mem_copy(addIE, + addIeWoP2pIe, + addnIELenWoP2pIe); + } + cdf_mem_free(addIeWoP2pIe); + } + + if (addnIEPresent) { + if ((nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) + nBytes += addnIELen; + else + addnIEPresent = false; /* Dont include the IE. */ + } + /* Paranoia: */ + cdf_mem_set(pFrame2Hal, nBytes, 0); + + /* Next, we fill out the buffer descriptor: */ + lim_populate_mac_header(pMac, pFrame2Hal, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_RSP, + psessionEntry->selfMacAddr, + psessionEntry->selfMacAddr); + + pMacHdr = (tpSirMacMgmtHdr) pFrame2Hal; + + sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId); + + /* That done, pack the Probe Response: */ + nStatus = + dot11f_pack_probe_response(pMac, &psessionEntry->probeRespFrame, + pFrame2Hal + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + + if (DOT11F_FAILED(nStatus)) { + sch_log(pMac, LOGE, + FL("Failed to pack a Probe Response (0x%08x)."), + nStatus); + + cdf_mem_free(addIE); + return retCode; /* allocated! */ + } else if (DOT11F_WARNED(nStatus)) { + sch_log(pMac, LOGE, FL("There were warnings while packing a P" + "robe Response (0x%08x)."), nStatus); + } + + if (addnIEPresent) { + cdf_mem_copy(&pFrame2Hal[nBytes - addnIELen], + &addIE[0], addnIELen); + } + + /* free the allocated Memory */ + cdf_mem_free(addIE); + + pprobeRespParams = cdf_mem_malloc(sizeof(tSendProbeRespParams)); + if (NULL == pprobeRespParams) { + sch_log(pMac, LOGE, + FL + ("lim_send_probe_rsp_template_to_hal: HAL probe response params malloc failed for bytes %d"), + nBytes); + } else { + sir_copy_mac_addr(pprobeRespParams->bssId, psessionEntry->bssId); + pprobeRespParams->pProbeRespTemplate = pFrame2Hal; + pprobeRespParams->probeRespTemplateLen = nBytes; + cdf_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap, + IeBitmap, (sizeof(uint32_t) * 8)); + msgQ.type = WMA_SEND_PROBE_RSP_TMPL; + msgQ.reserved = 0; + msgQ.bodyptr = pprobeRespParams; + msgQ.bodyval = 0; + + if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) { + /* free the allocated Memory */ + sch_log(pMac, LOGE, + FL + ("lim_send_probe_rsp_template_to_hal: FAIL bytes %d retcode[%X]"), + nBytes, retCode); + cdf_mem_free(pprobeRespParams); + } else { + sch_log(pMac, LOG1, + FL + ("lim_send_probe_rsp_template_to_hal: Probe response template msg posted to HAL of bytes %d"), + nBytes); + } + } + + return retCode; +} + +/** + * sch_gen_timing_advert_frame() - 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 sch_gen_timing_advert_frame(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; + struct cdf_mac_addr wildcard_bssid = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }; + + cdf_mem_zero((uint8_t *)&frame, sizeof(tDot11fTimingAdvertisementFrame)); + + /* Populate the TA fields */ + status = populate_dot11f_timing_advert_frame(mac_ctx, &frame); + if (status) { + sch_log(mac_ctx, LOGE, FL("Error populating TA frame %x"), + status); + return status; + } + + status = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx, + &frame, &payload_size); + if (DOT11F_FAILED(status)) { + sch_log(mac_ctx, LOGE, FL("Error getting packed frame size %x"), + status); + return status; + } else if (DOT11F_WARNED(status)) { + sch_log(mac_ctx, LOGW, FL("Warning getting packed frame size")); + } + + buf_size = sizeof(tSirMacMgmtHdr) + payload_size; + *buf = cdf_mem_malloc(buf_size); + if (*buf == NULL) { + sch_log(mac_ctx, LOGE, FL("Cannot allocate memory")); + return eSIR_FAILURE; + } + cdf_mem_zero(*buf, buf_size); + + payload_size = 0; + status = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame, + *buf + sizeof(tSirMacMgmtHdr), buf_size - + sizeof(tSirMacMgmtHdr), &payload_size); + sch_log(mac_ctx, LOGE, FL("TA payload size2 = %d"), payload_size); + if (DOT11F_FAILED(status)) { + sch_log(mac_ctx, LOGE, FL("Error packing frame %x"), status); + goto fail; + } else if (DOT11F_WARNED(status)) { + sch_log(mac_ctx, LOGE, FL("Warning packing frame")); + } + + lim_populate_mac_header(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 */ + dot11f_get_packed_ie_country(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) + cdf_mem_free(*buf); + return status; +} diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c new file mode 100644 index 000000000000..365b3492fa01 --- /dev/null +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -0,0 +1,930 @@ +/* + * 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 sch_beacon_gen.cc contains beacon generation related + * functions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "cds_api.h" +#include "wni_cfg.h" +#include "ani_global.h" +#include "sir_mac_prot_def.h" + +#include "lim_utils.h" +#include "lim_api.h" + +#include "wma_if.h" +#include "cfg_api.h" +#include "sch_api.h" + +#include "parser_api.h" + +#include "sch_debug.h" + +/* */ +/* March 15, 2006 */ +/* Temporarily (maybe for all of Alpha-1), assuming TIM = 0 */ +/* */ + +const uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x9 }; + +tSirRetStatus sch_get_p2p_ie_offset(uint8_t *pExtraIe, uint32_t extraIeLen, + uint16_t *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 (cdf_mem_compare + ((void *)(pExtraIe + 2), &p2p_oui, sizeof(p2p_oui))) { + status = eSIR_SUCCESS; + break; + } + } + + (*pP2pIeOffset)++; + pExtraIe++; + } while (--extraIeLen > 0); + + return status; +} + +/** + * sch_append_addn_ie() - adds additional IEs to frame + * @mac_ctx: mac global context + * @session: pe session pointer + * @frm: frame where additional IE is to be added + * @max_bcn_size: max beacon size + * @num_bytes: final size + * + * Return: status of operation + */ +tSirRetStatus +sch_append_addn_ie(tpAniSirGlobal mac_ctx, tpPESession session, + uint8_t *frm, uint32_t max_bcn_size, uint32_t *num_bytes) +{ + tSirRetStatus status = eSIR_FAILURE; + uint32_t present, len; + uint8_t add_ie[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; + uint8_t *p2p_ie = NULL; + uint8_t noa_len = 0; + uint8_t noa_strm[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + + present = (session->addIeParams.probeRespBCNDataLen != 0); + if (!present) + return status; + + len = session->addIeParams.probeRespBCNDataLen; + if (!(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len && + ((len + *num_bytes) <= max_bcn_size))) + return status; + + cdf_mem_copy(&add_ie[0], session->addIeParams.probeRespBCNData_buff, + len); + + p2p_ie = limGetP2pIEPtr(mac_ctx, &add_ie[0], len); + if ((p2p_ie != NULL) && !mac_ctx->beacon_offload) { + /* get NoA attribute stream P2P IE */ + noa_len = lim_get_noa_attr_stream(mac_ctx, noa_strm, session); + if (noa_len) { + if ((noa_len + len) <= + WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { + cdf_mem_copy(&add_ie[len], noa_strm, noa_len); + len += noa_len; + p2p_ie[1] += noa_len; + } else { + sch_log(mac_ctx, LOGE, + FL("Not able to insert NoA because of length constraint")); + } + } + } + if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) { + cdf_mem_copy(frm, &add_ie[0], len); + *num_bytes = *num_bytes + len; + } else { + sch_log(mac_ctx, LOGW, + FL("Not able to insert because of len constraint %d"), + len); + } + return status; +} + +/** + * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame + * @mac_ctx: mac global context + * @session: pe session entry + * @band: out param, band caclculated + * @opr_ch: operating channels + * + * Return: status of operation + */ + +tSirRetStatus +sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session) +{ + tpAniBeaconStruct bcn_struct = (tpAniBeaconStruct) + session->pSchBeaconFrameBegin; + tpSirMacMgmtHdr mac; + uint16_t offset; + uint8_t *ptr; + tDot11fBeacon1 *bcn_1; + tDot11fBeacon2 *bcn_2; + uint32_t i, n_status, n_bytes; + uint32_t wps_ap_enable = 0, tmp; + tDot11fIEWscProbeRes *wsc_prb_res; + uint8_t *extra_ie = NULL; + uint32_t extra_ie_len = 0; + uint16_t extra_ie_offset = 0; + uint16_t p2p_ie_offset = 0; + tSirRetStatus status = eSIR_SUCCESS; + bool is_vht_enabled = false; + + bcn_1 = cdf_mem_malloc(sizeof(tDot11fBeacon1)); + if (NULL == bcn_1) { + sch_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + return eSIR_MEM_ALLOC_FAILED; + } + + bcn_2 = cdf_mem_malloc(sizeof(tDot11fBeacon2)); + if (NULL == bcn_2) { + sch_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + cdf_mem_free(bcn_1); + return eSIR_MEM_ALLOC_FAILED; + } + + wsc_prb_res = cdf_mem_malloc(sizeof(tDot11fIEWscProbeRes)); + if (NULL == wsc_prb_res) { + sch_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + cdf_mem_free(bcn_1); + cdf_mem_free(bcn_2); + return eSIR_MEM_ALLOC_FAILED; + } + + sch_log(mac_ctx, LOG1, FL("Setting fixed beacon fields")); + + /* + * First set the fixed fields: + * set the TFP headers, set the mac header + */ + cdf_mem_set((uint8_t *) &bcn_struct->macHdr, sizeof(tSirMacMgmtHdr), 0); + mac = (tpSirMacMgmtHdr) &bcn_struct->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; + + cdf_mem_copy(mac->sa, session->selfMacAddr, + sizeof(session->selfMacAddr)); + cdf_mem_copy(mac->bssId, session->bssId, sizeof(session->bssId)); + + mac->fc.fromDS = 0; + mac->fc.toDS = 0; + + /* Now set the beacon body */ + cdf_mem_set((uint8_t *) bcn_1, sizeof(tDot11fBeacon1), 0); + + /* Skip over the timestamp (it'll be updated later). */ + bcn_1->BeaconInterval.interval = + mac_ctx->sch.schObject.gSchBeaconInterval; + populate_dot11f_capabilities(mac_ctx, &bcn_1->Capabilities, session); + if (session->ssidHidden) { + bcn_1->SSID.present = 1; + /* rest of the fileds are 0 for hidden ssid */ + if ((session->ssId.length) && + (session->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS)) + bcn_1->SSID.num_ssid = session->ssId.length; + } else { + populate_dot11f_ssid(mac_ctx, &session->ssId, &bcn_1->SSID); + } + + populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL, + &bcn_1->SuppRates, session); + populate_dot11f_ds_params(mac_ctx, &bcn_1->DSParams, + session->currentOperChannel); + populate_dot11f_ibss_params(mac_ctx, &bcn_1->IBSSParams, session); + + offset = sizeof(tAniBeaconStruct); + ptr = session->pSchBeaconFrameBegin + offset; + + if (LIM_IS_AP_ROLE(session)) { + /* Initialize the default IE bitmap to zero */ + cdf_mem_set((uint8_t *) &(session->DefProbeRspIeBitmap), + (sizeof(uint32_t) * 8), 0); + + /* Initialize the default IE bitmap to zero */ + cdf_mem_set((uint8_t *) &(session->probeRespFrame), + sizeof(session->probeRespFrame), 0); + + /* + * Can be efficiently updated whenever new IE added in Probe + * response in future + */ + if (lim_update_probe_rsp_template_ie_bitmap_beacon1(mac_ctx, + bcn_1, session) != eSIR_SUCCESS) + sch_log(mac_ctx, LOGE, + FL("Failed to build ProbeRsp template")); + } + + n_status = dot11f_pack_beacon1(mac_ctx, bcn_1, ptr, + SCH_MAX_BEACON_SIZE - offset, &n_bytes); + if (DOT11F_FAILED(n_status)) { + sch_log(mac_ctx, LOGE, + FL("Failed to packed a tDot11fBeacon1 (0x%08x.)."), + n_status); + cdf_mem_free(bcn_1); + cdf_mem_free(bcn_2); + cdf_mem_free(wsc_prb_res); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(n_status)) { + sch_log(mac_ctx, LOGE, + FL("Warnings while packing a tDot11fBeacon1(0x%08x.)."), + n_status); + } + /*changed to correct beacon corruption */ + cdf_mem_set((uint8_t *) bcn_2, sizeof(tDot11fBeacon2), 0); + session->schBeaconOffsetBegin = offset + (uint16_t) n_bytes; + sch_log(mac_ctx, LOG1, FL("Initialized beacon begin, offset %d"), + offset); + + /* Initialize the 'new' fields at the end of the beacon */ + + if ((session->limSystemRole == eLIM_AP_ROLE) && + session->dfsIncludeChanSwIe == true) + populate_dot_11_f_ext_chann_switch_ann(mac_ctx, + &bcn_2->ext_chan_switch_ann, + session); + + populate_dot11f_country(mac_ctx, &bcn_2->Country, session); + if (bcn_1->Capabilities.qos) + populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet, + session); + + if (session->lim11hEnable) { + populate_dot11f_power_constraints(mac_ctx, + &bcn_2->PowerConstraints); + populate_dot11f_tpc_report(mac_ctx, &bcn_2->TPCReport, session); + /* Need to insert channel switch announcement here */ + if ((LIM_IS_AP_ROLE(session) + || LIM_IS_P2P_DEVICE_GO(session)) + && session->dfsIncludeChanSwIe == true) { + /* + * Channel switch announcement only if radar is detected + * and SAP has instructed to announce channel switch IEs + * in beacon and probe responses + */ + populate_dot11f_chan_switch_ann(mac_ctx, + &bcn_2->ChanSwitchAnn, session); + + /* + * TODO: depending the CB mode, extended channel switch + * announcement need to be called + */ + /* + populate_dot11f_ext_chan_switch_ann(mac_ctx, + &bcn_2->ExtChanSwitchAnn, session); + */ +#ifdef WLAN_FEATURE_11AC + /* + * TODO: If in 11AC mode, wider bw channel switch + * announcement needs to be called + */ + /* + populate_dot11f_wider_bw_chan_switch_ann(mac_ctx, + &bcn_2->WiderBWChanSwitchAnn, session); + */ +#endif + /* + * Populate the Channel Switch Wrapper Element if + * SAP operates in 40/80 Mhz Channel Width. + */ + if (true == session->dfsIncludeChanWrapperIe) + populate_dot11f_chan_switch_wrapper(mac_ctx, + &bcn_2->ChannelSwitchWrapper, session); + } + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* populate proprietary IE for MDM device operating in AP-MCC */ + populate_dot11f_avoid_channel_ie(mac_ctx, &bcn_2->QComVendorIE, + session); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + if (session->dot11mode != WNI_CFG_DOT11_MODE_11B) + populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session); + + if (session->htCapability) { + populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps); + populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session); + } +#ifdef WLAN_FEATURE_11AC + if (session->vhtCapability) { + sch_log(mac_ctx, LOGW, FL("Populate VHT IEs in Beacon")); + populate_dot11f_vht_caps(mac_ctx, session, &bcn_2->VHTCaps); + populate_dot11f_vht_operation(mac_ctx, session, + &bcn_2->VHTOperation); + is_vht_enabled = true; + /* following is for MU MIMO: we do not support it yet */ + /* + populate_dot11f_vht_ext_bss_load( mac_ctx, &bcn2.VHTExtBssLoad); + */ + if (session->gLimOperatingMode.present) + populate_dot11f_operating_mode(mac_ctx, + &bcn_2->OperatingMode, session); + } +#endif + populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap, + session); + populate_dot11f_ext_supp_rates(mac_ctx, + POPULATE_DOT11F_RATES_OPERATIONAL, + &bcn_2->ExtSuppRates, session); + + if (session->pLimStartBssReq != NULL) { + populate_dot11f_wpa(mac_ctx, &session->pLimStartBssReq->rsnIE, + &bcn_2->WPA); + populate_dot11f_rsn_opaque(mac_ctx, + &session->pLimStartBssReq->rsnIE, + &bcn_2->RSNOpaque); + } + + if (session->limWmeEnabled) + populate_dot11f_wmm(mac_ctx, &bcn_2->WMMInfoAp, + &bcn_2->WMMParams, &bcn_2->WMMCaps, session); + if (LIM_IS_AP_ROLE(session)) { + if (session->wps_state != SAP_WPS_DISABLED) { + populate_dot11f_beacon_wpsi_es(mac_ctx, + &bcn_2->WscBeacon, session); + } + } else { + if (wlan_cfg_get_int(mac_ctx, + (uint16_t) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) + sch_log(mac_ctx, LOGP, FL("Failed to cfg get id %d"), + WNI_CFG_WPS_ENABLE); + + wps_ap_enable = tmp & WNI_CFG_WPS_ENABLE_AP; + + if (wps_ap_enable) + populate_dot11f_wsc(mac_ctx, &bcn_2->WscBeacon); + + if (mac_ctx->lim.wscIeInfo.wscEnrollmentState == + eLIM_WSC_ENROLL_BEGIN) { + populate_dot11f_wsc_registrar_info(mac_ctx, + &bcn_2->WscBeacon); + mac_ctx->lim.wscIeInfo.wscEnrollmentState = + eLIM_WSC_ENROLL_IN_PROGRESS; + } + + if (mac_ctx->lim.wscIeInfo.wscEnrollmentState == + eLIM_WSC_ENROLL_END) { + de_populate_dot11f_wsc_registrar_info(mac_ctx, + &bcn_2->WscBeacon); + mac_ctx->lim.wscIeInfo.wscEnrollmentState = + eLIM_WSC_ENROLL_NOOP; + } + } + + if ((LIM_IS_AP_ROLE(session))) { + /* + * Can be efficiently updated whenever new IE added in Probe + * response in future + */ + lim_update_probe_rsp_template_ie_bitmap_beacon2(mac_ctx, bcn_2, + &session->DefProbeRspIeBitmap[0], + &session->probeRespFrame); + + /* update probe response WPS IE instead of beacon WPS IE */ + if (session->wps_state != SAP_WPS_DISABLED) { + if (session->APWPSIEs.SirWPSProbeRspIE.FieldPresent) + populate_dot11f_probe_res_wpsi_es(mac_ctx, + wsc_prb_res, session); + else + wsc_prb_res->present = 0; + if (wsc_prb_res->present) { + set_probe_rsp_ie_bitmap( + &session->DefProbeRspIeBitmap[0], + SIR_MAC_WPA_EID); + cdf_mem_copy((void *) + &session->probeRespFrame.WscProbeRes, + (void *)wsc_prb_res, + sizeof(tDot11fIEWscProbeRes)); + } + } + + } + + n_status = dot11f_pack_beacon2(mac_ctx, bcn_2, + session->pSchBeaconFrameEnd, + SCH_MAX_BEACON_SIZE, &n_bytes); + if (DOT11F_FAILED(n_status)) { + sch_log(mac_ctx, LOGE, + FL("Failed to packed a tDot11fBeacon2 (0x%08x.)."), + n_status); + cdf_mem_free(bcn_1); + cdf_mem_free(bcn_2); + cdf_mem_free(wsc_prb_res); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(n_status)) { + sch_log(mac_ctx, LOGE, + FL("Warnings while packing a tDot11fBeacon2(0x%08x.)."), + n_status); + } + + extra_ie = session->pSchBeaconFrameEnd + n_bytes; + extra_ie_offset = n_bytes; + /* TODO: Append additional IE here. */ + sch_append_addn_ie(mac_ctx, session, + session->pSchBeaconFrameEnd + n_bytes, + SCH_MAX_BEACON_SIZE, &n_bytes); + session->schBeaconOffsetEnd = (uint16_t) n_bytes; + extra_ie_len = n_bytes - extra_ie_offset; + /* Get the p2p Ie Offset */ + status = sch_get_p2p_ie_offset(extra_ie, extra_ie_len, &p2p_ie_offset); + if (eSIR_SUCCESS == status) + /* Update the P2P Ie Offset */ + mac_ctx->sch.schObject.p2pIeOffset = + session->schBeaconOffsetBegin + TIM_IE_SIZE + + extra_ie_offset + p2p_ie_offset; + else + mac_ctx->sch.schObject.p2pIeOffset = 0; + + sch_log(mac_ctx, LOG1, FL("Initialized beacon end, offset %d"), + session->schBeaconOffsetEnd); + mac_ctx->sch.schObject.fBeaconChanged = 1; + cdf_mem_free(bcn_1); + cdf_mem_free(bcn_2); + cdf_mem_free(wsc_prb_res); + return eSIR_SUCCESS; +} + +tSirRetStatus lim_update_probe_rsp_template_ie_bitmap_beacon1(tpAniSirGlobal pMac, + tDot11fBeacon1 *beacon1, + tpPESession + psessionEntry) +{ + uint32_t *DefProbeRspIeBitmap; + tDot11fProbeResponse *prb_rsp; + if (!psessionEntry) { + sch_log(pMac, LOGE, FL("PESession is null!")); + return eSIR_FAILURE; + } + DefProbeRspIeBitmap = &psessionEntry->DefProbeRspIeBitmap[0]; + prb_rsp = &psessionEntry->probeRespFrame; + prb_rsp->BeaconInterval = beacon1->BeaconInterval; + cdf_mem_copy((void *)&prb_rsp->Capabilities, + (void *)&beacon1->Capabilities, + sizeof(beacon1->Capabilities)); + + /* SSID */ + if (beacon1->SSID.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_SSID_EID); + /* populating it, because probe response has to go with SSID even in hidden case */ + populate_dot11f_ssid(pMac, &psessionEntry->ssId, &prb_rsp->SSID); + } + /* supported rates */ + if (beacon1->SuppRates.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RATESET_EID); + cdf_mem_copy((void *)&prb_rsp->SuppRates, + (void *)&beacon1->SuppRates, + sizeof(beacon1->SuppRates)); + + } + /* DS Parameter set */ + if (beacon1->DSParams.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_DS_PARAM_SET_EID); + cdf_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 lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac, + tDot11fBeacon2 *beacon2, + uint32_t *DefProbeRspIeBitmap, + tDot11fProbeResponse *prb_rsp) +{ + /* IBSS parameter set - will not be present in probe response tx by AP */ + /* country */ + if (beacon2->Country.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_COUNTRY_EID); + cdf_mem_copy((void *)&prb_rsp->Country, + (void *)&beacon2->Country, + sizeof(beacon2->Country)); + + } + /* Power constraint */ + if (beacon2->PowerConstraints.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_PWR_CONSTRAINT_EID); + cdf_mem_copy((void *)&prb_rsp->PowerConstraints, + (void *)&beacon2->PowerConstraints, + sizeof(beacon2->PowerConstraints)); + + } + /* Channel Switch Annoouncement SIR_MAC_CHNL_SWITCH_ANN_EID */ + if (beacon2->ChanSwitchAnn.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_CHNL_SWITCH_ANN_EID); + cdf_mem_copy((void *)&prb_rsp->ChanSwitchAnn, + (void *)&beacon2->ChanSwitchAnn, + sizeof(beacon2->ChanSwitchAnn)); + + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (beacon2->QComVendorIE.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_QCOM_VENDOR_EID); + cdf_mem_copy((void *)&prb_rsp->QComVendorIE, + (void *)&beacon2->QComVendorIE, + sizeof(beacon2->QComVendorIE)); + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + /* ERP information */ + if (beacon2->ERPInfo.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_ERP_INFO_EID); + cdf_mem_copy((void *)&prb_rsp->ERPInfo, + (void *)&beacon2->ERPInfo, + sizeof(beacon2->ERPInfo)); + + } + /* Extended supported rates */ + if (beacon2->ExtSuppRates.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_EXTENDED_RATE_EID); + cdf_mem_copy((void *)&prb_rsp->ExtSuppRates, + (void *)&beacon2->ExtSuppRates, + sizeof(beacon2->ExtSuppRates)); + + } + + /* WPA */ + if (beacon2->WPA.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID); + cdf_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA, + sizeof(beacon2->WPA)); + + } + + /* RSN */ + if (beacon2->RSNOpaque.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RSN_EID); + cdf_mem_copy((void *)&prb_rsp->RSNOpaque, + (void *)&beacon2->RSNOpaque, + sizeof(beacon2->RSNOpaque)); + } + + /* EDCA Parameter set */ + if (beacon2->EDCAParamSet.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_EDCA_PARAM_SET_EID); + cdf_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) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_HT_CAPABILITIES_EID); + cdf_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps, + sizeof(beacon2->HTCaps)); + } + /* HT Info IE */ + if (beacon2->HTInfo.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_HT_INFO_EID); + cdf_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo, + sizeof(beacon2->HTInfo)); + } +#ifdef WLAN_FEATURE_11AC + if (beacon2->VHTCaps.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_VHT_CAPABILITIES_EID); + cdf_mem_copy((void *)&prb_rsp->VHTCaps, + (void *)&beacon2->VHTCaps, + sizeof(beacon2->VHTCaps)); + } + if (beacon2->VHTOperation.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_VHT_OPERATION_EID); + cdf_mem_copy((void *)&prb_rsp->VHTOperation, + (void *)&beacon2->VHTOperation, + sizeof(beacon2->VHTOperation)); + } + if (beacon2->VHTExtBssLoad.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_VHT_EXT_BSS_LOAD_EID); + cdf_mem_copy((void *)&prb_rsp->VHTExtBssLoad, + (void *)&beacon2->VHTExtBssLoad, + sizeof(beacon2->VHTExtBssLoad)); + } +#endif + + /* WMM IE */ + if (beacon2->WMMParams.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID); + cdf_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) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID); + cdf_mem_copy((void *)&prb_rsp->WMMCaps, + (void *)&beacon2->WMMCaps, + sizeof(beacon2->WMMCaps)); + } + + /* Extended Capability */ + if (beacon2->ExtCap.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP); + cdf_mem_copy((void *)&prb_rsp->ExtCap, + (void *)&beacon2->ExtCap, + sizeof(beacon2->ExtCap)); + } + +} + +void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos) +{ + uint32_t index, temp; + + index = pos >> 5; + if (index >= 8) { + return; + } + temp = IeBitmap[index]; + + temp |= 1 << (pos & 0x1F); + + IeBitmap[index] = temp; +} + +/* -------------------------------------------------------------------- */ +/** + * write_beacon_to_memory + * + * 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 write_beacon_to_memory(tpAniSirGlobal pMac, uint16_t size, uint16_t length, + tpPESession psessionEntry) +{ + uint16_t 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 = (uint32_t) size - sizeof(uint32_t); + + /* write size bytes from pSchBeaconFrameBegin */ + PELOG2(sch_log(pMac, LOG2, FL("Beacon size - %d bytes"), size);) + PELOG2(sir_dump_buf + (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 != + sch_send_beacon_req(pMac, psessionEntry->pSchBeaconFrameBegin, + size, psessionEntry)) + PELOGE(sch_log + (pMac, LOGE, + FL + ("sch_send_beacon_req() returned an error (zsize %d)"), + size); + ) + else { + pMac->sch.gSchBeaconsWritten++; + } + } + pMac->sch.schObject.fBeaconChanged = 0; +} + +/** + * sch_generate_tim + * + * 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 sch_generate_tim(tpAniSirGlobal pMac, uint8_t **pPtr, uint16_t *timLength, + uint8_t dtimPeriod) +{ + uint8_t *ptr = *pPtr; + uint32_t val = 0; + uint32_t minAid = 1; /* Always start with AID 1 as minimum */ + uint32_t maxAid = HAL_NUM_STA; + + /* Generate partial virtual bitmap */ + uint8_t N1 = minAid / 8; + uint8_t N2 = maxAid / 8; + if (N1 & 1) + N1--; + + *timLength = N2 - N1 + 4; + val = dtimPeriod; + + /* + * 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++ = (uint8_t) (*timLength); + /* location for dtimCount. will be filled in by FW. */ + *ptr++ = 0xFF; + *ptr++ = (uint8_t) val; + /* location for bitmap control. will be filled in by FW. */ + *ptr++ = 0xFF; + ptr += (N2 - N1 + 1); + + PELOG2(sir_dump_buf + (pMac, SIR_SCH_MODULE_ID, LOG2, *pPtr, (*timLength) + 2); + ) + * pPtr = ptr; +} +/* -------------------------------------------------------------------- */ +/** + * @function: SchProcessPreBeaconInd + * + * @brief : Process the PreBeacon Indication from the Lim + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param : pMac - tpAniSirGlobal + * + * @return None + */ + +void sch_process_pre_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg) +{ + tpBeaconGenParams pMsg = (tpBeaconGenParams) limMsg->bodyptr; + uint32_t beaconSize; + tpPESession psessionEntry; + uint8_t sessionId; + + if ((psessionEntry = + pe_find_session_by_bssid(pMac, pMsg->bssId, &sessionId)) == NULL) { + PELOGE(sch_log(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(sch_log + (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) + write_beacon_to_memory(pMac, (uint16_t) beaconSize, + (uint16_t) beaconSize, + psessionEntry); + else + PELOGE(sch_log + (pMac, LOGE, + FL + ("can not send beacon for PEER session entry")); + ) + break; + + case eLIM_AP_ROLE: { + uint8_t *ptr = + &psessionEntry->pSchBeaconFrameBegin[psessionEntry-> + schBeaconOffsetBegin]; + uint16_t timLength = 0; + if (psessionEntry->statypeForBss == STA_ENTRY_SELF) { + sch_generate_tim(pMac, &ptr, &timLength, + psessionEntry->dtimPeriod); + beaconSize += 2 + timLength; + write_beacon_to_memory(pMac, (uint16_t) beaconSize, + (uint16_t) beaconSize, + psessionEntry); + } else + PELOGE(sch_log + (pMac, LOGE, + FL + ("can not send beacon for PEER session entry")); + ) + } + break; + + default: + PELOGE(sch_log + (pMac, LOGE, + FL + ("Error-PE has Receive PreBeconGenIndication when System is in %d role"), + GET_LIM_SYSTEM_ROLE(psessionEntry)); + ) + } + +end: + cdf_mem_free(pMsg); + + } diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c new file mode 100644 index 000000000000..a8f2a468b90b --- /dev/null +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -0,0 +1,1011 @@ +/* + * 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 sch_beacon_process.cc contains beacon processing related + * functions + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "cds_api.h" +#include "wni_cfg.h" + +#include "cfg_api.h" +#include "lim_api.h" +#include "utils_api.h" +#include "sch_debug.h" +#include "sch_api.h" + +#include "lim_utils.h" +#include "lim_send_messages.h" +#include "lim_sta_hash_api.h" + +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "host_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_5_ghz(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpSchBeaconStruct bcn_struct, + tpUpdateBeaconParams bcn_prm, tpPESession session, + uint32_t phy_mode) +{ + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + if (!session->htCapability) + return; + + if (bcn_struct->channelNumber != session->currentOperChannel) + return; + + /* 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 (!bcn_struct->HTInfo.present + || (eSIR_HT_OP_MODE_MIXED == bcn_struct->HTInfo.opMode) + || (eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode)) { + lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, + &(mac_ctx->lim.gLimOverlap11aParams)); + + if (mac_ctx->lim.gLimOverlap11aParams.numSta + && !mac_ctx->lim.gLimOverlap11aParams.protectionEnabled) { + lim_update_11a_protection(mac_ctx, true, true, + bcn_prm, session); + } + return; + } + /* HT AP with HT20 op mode overlaps. */ + if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT != bcn_struct->HTInfo.opMode) + return; + + lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, + &(mac_ctx->lim.gLimOverlapHt20Params)); + + if (mac_ctx->lim.gLimOverlapHt20Params.numSta + && !mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled) + lim_enable_ht20_protection(mac_ctx, true, true, + bcn_prm, session); +} + +static void +ap_beacon_process_24_ghz(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpSchBeaconStruct bcn_struct, + tpUpdateBeaconParams bcn_prm, tpPESession session, + uint32_t phy_mode) +{ + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + bool tmp_exp = false; + /* We are 11G AP. */ + if ((phy_mode == WNI_CFG_PHY_MODE_11G) && + (false == session->htCapability)) { + if (bcn_struct->channelNumber != session->currentOperChannel) + return; + + tmp_exp = (!bcn_struct->erpPresent + && !bcn_struct->HTInfo.present) + /* if erp not present then 11B AP overlapping */ + || (!mac_ctx->roam.configParam.ignore_peer_erp_info && + bcn_struct->erpPresent && + (bcn_struct->erpIEInfo.useProtection + || bcn_struct->erpIEInfo.nonErpPresent)); + if (!tmp_exp) + return; +#ifdef FEATURE_WLAN_ESE + if (session->isESEconnection) + CDF_TRACE(CDF_MODULE_ID_PE, + CDF_TRACE_LEVEL_INFO, + FL("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d"), + bcn_struct->erpPresent, + bcn_struct->erpIEInfo.useProtection, + bcn_struct->erpIEInfo.nonErpPresent); +#endif + lim_enable_overlap11g_protection(mac_ctx, bcn_prm, + mac_hdr, session); + return; + } + /* handling the case when HT AP has overlapping legacy BSS. */ + if (!session->htCapability) + return; + + if (bcn_struct->channelNumber != session->currentOperChannel) + return; + + tmp_exp = (!bcn_struct->erpPresent && !bcn_struct->HTInfo.present) + /* if erp not present then 11B AP overlapping */ + || (!mac_ctx->roam.configParam.ignore_peer_erp_info && + bcn_struct->erpPresent && + (bcn_struct->erpIEInfo.useProtection + || bcn_struct->erpIEInfo.nonErpPresent)); + if (tmp_exp) { +#ifdef FEATURE_WLAN_ESE + if (session->isESEconnection) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, + FL("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d"), + bcn_struct->erpPresent, + bcn_struct->erpIEInfo.useProtection, + bcn_struct->erpIEInfo.nonErpPresent); + } +#endif + lim_enable_overlap11g_protection(mac_ctx, bcn_prm, + mac_hdr, session); + } + /* 11g device overlaps */ + tmp_exp = bcn_struct->erpPresent + && !(bcn_struct->erpIEInfo.useProtection + || bcn_struct->erpIEInfo.nonErpPresent) + && !(bcn_struct->HTInfo.present); + if (tmp_exp) { + lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, + &(session->gLimOverlap11gParams)); + + if (session->gLimOverlap11gParams.numSta + && !session->gLimOverlap11gParams.protectionEnabled) + lim_enable_ht_protection_from11g(mac_ctx, true, true, + bcn_prm, session); + } + /* 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 (!bcn_struct->HTInfo.present) + return; + + /* + * 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 == bcn_struct->HTInfo.opMode) { + if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == mac_ctx->lim.gHTOperMode + || eSIR_HT_OP_MODE_MIXED == mac_ctx->lim.gHTOperMode) + return; + lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, + &(session->gLimOverlap11gParams)); + if (session->gLimOverlap11gParams.numSta + && !session->gLimOverlap11gParams.protectionEnabled) + lim_enable_ht_protection_from11g(mac_ctx, true, true, + bcn_prm, session); + return; + } + + if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == bcn_struct->HTInfo.opMode) { + lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, + &(session->gLimOverlapHt20Params)); + if (session->gLimOverlapHt20Params.numSta + && !session->gLimOverlapHt20Params.protectionEnabled) + lim_enable_ht20_protection(mac_ctx, true, true, + bcn_prm, session); + } +} + +/** + * ap_beacon_process() - processes incoming beacons + * + * @mac_ctx: mac global context + * @rx_pkt_info: incoming beacon packet + * @bcn_struct: beacon struct + * @bcn_prm: beacon params + * @session: pe session entry + * + * Return: void + */ +static void +ap_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpSchBeaconStruct bcn_struct, + tpUpdateBeaconParams bcn_prm, tpPESession session) +{ + uint32_t phy_mode; + tSirRFBand rf_band = SIR_BAND_UNKNOWN; + /* Get RF band from session */ + rf_band = session->limRFBand; + + lim_get_phy_mode(mac_ctx, &phy_mode, session); + + if (SIR_BAND_5_GHZ == rf_band) + ap_beacon_process_5_ghz(mac_ctx, rx_pkt_info, bcn_struct, + bcn_prm, session, phy_mode); + else if (SIR_BAND_2_4_GHZ == rf_band) + ap_beacon_process_24_ghz(mac_ctx, rx_pkt_info, bcn_struct, + bcn_prm, session, phy_mode); + mac_ctx->sch.gSchBcnIgnored++; +} + +/* -------------------------------------------------------------------- */ + +/** + * __sch_beacon_process_no_session + * + * 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 lim_handle_ibs_scoalescing 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 __sch_beacon_process_no_session(tpAniSirGlobal pMac, + tpSchBeaconStruct pBeacon, + uint8_t *pRxPacketInfo) +{ + tpPESession psessionEntry = NULL; + + if ((psessionEntry = lim_is_ibss_session_active(pMac)) != NULL) { + lim_handle_ibss_coalescing(pMac, pBeacon, pRxPacketInfo, + psessionEntry); + } + /* If station(STA/BT-STA/BT-AP/IBSS) mode, Always save the beacon in the scan results, if atleast one session is active */ + /* sch_beacon_processNoSession will be called only when there is atleast one session active, so not checking */ + /* it again here. */ + lim_check_and_add_bss_description(pMac, pBeacon, pRxPacketInfo, false, + false); + return; +} + +/** + * get_operating_channel_width() - Get operating channel width + * @pStaDs - station entry. + * + * This function returns the oeprating channgl width based on + * the supported channel width entry. + * + * Return: tSirMacHTChannelWidth on success + */ +tSirMacHTChannelWidth get_operating_channel_width(tpDphHashNode stads) +{ + tSirMacHTChannelWidth ch_width = eHT_CHANNEL_WIDTH_20MHZ; + + if (stads->vhtSupportedChannelWidthSet == + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) + ch_width = eHT_CHANNEL_WIDTH_160MHZ; + else if (stads->vhtSupportedChannelWidthSet == + WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) + ch_width = eHT_CHANNEL_WIDTH_160MHZ; + else if (stads->vhtSupportedChannelWidthSet == + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) + ch_width = eHT_CHANNEL_WIDTH_80MHZ; + else if (stads->htSupportedChannelWidthSet) + ch_width = eHT_CHANNEL_WIDTH_40MHZ; + else + ch_width = eHT_CHANNEL_WIDTH_20MHZ; + + return ch_width; +} + +/* + * sch_bcn_process_sta_bt_amp_sta() - Process the received beacon frame for sta, + * bt_amp_sta + * + * @mac_ctx: mac_ctx + * @bcn: beacon struct + * @rx_pkt_info: received packet info + * @session: pe session pointer + * @bssIdx: bss index + * @beaconParams: update beacon params + * @sendProbeReq: out flag to indicate if probe rsp is to be sent + * @pMh: mac header + * + * Process the received beacon frame for sta, bt_amp_sta + * + * Return: success of failure of operation + */ +static bool +sch_bcn_process_sta_bt_amp_sta(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct bcn, + uint8_t *rx_pkt_info, + tpPESession session, uint8_t *bssIdx, + tUpdateBeaconParams *beaconParams, + uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh) +{ + uint32_t bi; + tpDphHashNode pStaDs = NULL; + /* + * This handles two cases: + * -- Infra STA receving beacons from AP + * -- BTAMP_STA receving beacons from BTAMP_AP + */ + /* Always save the beacon into LIM's cached scan results */ + lim_check_and_add_bss_description(mac_ctx, bcn, rx_pkt_info, + false, 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 ((uint8_t) bcn->channelNumber != session->currentOperChannel) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Channel Change from %d --> %d - Ignoring beacon!"), + session->currentOperChannel, + bcn->channelNumber);) + return false; + } + lim_detect_change_in_ap_capabilities(mac_ctx, bcn, session); + if (lim_get_sta_hash_bssidx(mac_ctx, DPH_STA_HASH_INDEX_PEER, bssIdx, + session) != eSIR_SUCCESS) + return false; + + beaconParams->bssIdx = *bssIdx; + cdf_mem_copy((uint8_t *) &session->lastBeaconTimeStamp, + (uint8_t *) bcn->timeStamp, sizeof(uint64_t)); + session->lastBeaconDtimCount = bcn->tim.dtimCount; + session->lastBeaconDtimPeriod = bcn->tim.dtimPeriod; + session->currentBssBeaconCnt++; + + MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, + session->peSessionId, bcn->timeStamp[0]);) + MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, + session->peSessionId, bcn->timeStamp[1]);) + + /* Read beacon interval session Entry */ + bi = session->beaconParams.beaconInterval; + if (bi != bcn->beaconInterval) { + PELOG1(sch_log(mac_ctx, LOG1, + FL("Beacon interval changed from %d to %d"), + bcn->beaconInterval, bi);) + + bi = bcn->beaconInterval; + session->beaconParams.beaconInterval = (uint16_t) bi; + beaconParams->paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; + beaconParams->beaconInterval = (uint16_t) bi; + } + + if (bcn->cfPresent) { + cfg_set_int(mac_ctx, WNI_CFG_CFP_PERIOD, + bcn->cfParamSet.cfpPeriod); + lim_send_cf_params(mac_ctx, *bssIdx, + bcn->cfParamSet.cfpCount, + bcn->cfParamSet.cfpPeriod); + } + + /* No need to send DTIM Period and Count to HAL/SMAC */ + /* SMAC already parses TIM bit. */ + if (bcn->timPresent) + cfg_set_int(mac_ctx, WNI_CFG_DTIM_PERIOD, bcn->tim.dtimPeriod); + + if (mac_ctx->lim.gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + lim_decide_sta_protection(mac_ctx, bcn, beaconParams, session); + + if (bcn->erpPresent) { + if (bcn->erpIEInfo.barkerPreambleMode) + lim_enable_short_preamble(mac_ctx, false, + beaconParams, session); + else + lim_enable_short_preamble(mac_ctx, true, + beaconParams, session); + } + lim_update_short_slot(mac_ctx, bcn, beaconParams, session); + + pStaDs = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, + &session->dph.dphHashTable); + if ((bcn->wmeEdcaPresent && (session->limWmeEnabled)) + || (bcn->edcaPresent && (session->limQosEnabled))) { + if (bcn->edcaParams.qosInfo.count != + session->gLimEdcaParamSetCount) { + if (sch_beacon_edca_process(mac_ctx, &bcn->edcaParams, + session) != eSIR_SUCCESS) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("EDCA parameter processing error"));) + } else if (pStaDs != NULL) { + /* If needed, downgrade the EDCA parameters */ + lim_set_active_edca_params(mac_ctx, + session->gLimEdcaParams, session); + lim_send_edca_params(mac_ctx, + session->gLimEdcaParamsActive, + pStaDs->bssId); + } else { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Self Entry missing in Hash Table"));) + } + } + return true; + } + + if ((bcn->qosCapabilityPresent && session->limQosEnabled) + && (bcn->qosCapability.qosInfo.count != + session->gLimEdcaParamSetCount)) + *sendProbeReq = true; + + return true; +} + +/** + * update_nss() - Function to update NSS + * @mac_ctx: pointer to Global Mac structure + * @sta_ds: pointer to tpDphHashNode + * @beacon: pointer to tpSchBeaconStruct + * @session_entry: pointer to tpPESession + * @mgmt_hdr: pointer to tpSirMacMgmtHdr + * + * function to update NSS + * + * Return: none + */ +void update_nss(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, + tpSchBeaconStruct beacon, tpPESession session_entry, + tpSirMacMgmtHdr mgmt_hdr) +{ + if (sta_ds->vhtSupportedRxNss != (beacon->OperatingMode.rxNSS + 1)) { + sta_ds->vhtSupportedRxNss = + beacon->OperatingMode.rxNSS + 1; + lim_set_nss_change(mac_ctx, session_entry, + sta_ds->vhtSupportedRxNss, sta_ds->staIndex, + mgmt_hdr->sa); + } +} + +/* + * sch_bcn_process_sta_bt_amp_sta_ibss() - Process the received beacon frame + * for sta, bt_amp_sta and ibss + * + * @mac_ctx: mac_ctx + * @bcn: beacon struct + * @rx_pkt_info: received packet info + * @session: pe session pointer + * @bssIdx: bss index + * @beaconParams: update beacon params + * @sendProbeReq: out flag to indicate if probe rsp is to be sent + * @pMh: mac header + * + * Process the received beacon frame for sta, bt_amp_sta and ibss + * + * Return: void + */ +static void +sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct bcn, + uint8_t *rx_pkt_info, + tpPESession session, uint8_t *bssIdx, + tUpdateBeaconParams *beaconParams, + uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh) +{ + tpDphHashNode pStaDs = NULL; + uint16_t aid; + uint8_t operMode; + uint8_t chWidth = 0; + uint8_t cb_mode; + + if (RF_CHAN_14 >= session->currentOperChannel) + cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz; + else + cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz; + /* check for VHT capability */ + pStaDs = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid, + &session->dph.dphHashTable); + if ((NULL == pStaDs) || + (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode)) + return; + + if (session->vhtCapability && bcn->OperatingMode.present) { + operMode = get_operating_channel_width(pStaDs); + if (operMode == bcn->OperatingMode.chanWidth) + return; + + PELOGE(sch_log(mac_ctx, LOGE, + FL("received OpMode Chanwidth %d, staIdx = %d"), + bcn->OperatingMode.chanWidth, pStaDs->staIndex);) + PELOGE(sch_log(mac_ctx, LOGE, + 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 (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_160MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 160MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_80MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 80MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_40MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 40MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + } else if (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_20MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 20MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + } + lim_check_vht_op_mode_change(mac_ctx, session, + bcn->OperatingMode.chanWidth, + pStaDs->staIndex, pMh->sa); + update_nss(mac_ctx, pStaDs, bcn, session, pMh); + return; + } + + if (!(session->vhtCapability && bcn->VHTOperation.present)) + return; + + operMode = pStaDs->vhtSupportedChannelWidthSet; + if (operMode == bcn->VHTOperation.chanWidth) + return; + + PELOGE(sch_log(mac_ctx, LOGE, + FL("received VHTOP CHWidth %d staIdx = %d"), + bcn->VHTOperation.chanWidth, pStaDs->staIndex);) + PELOGE(sch_log(mac_ctx, LOGE, + 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 (bcn->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 160MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + } else if (bcn->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 160MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; + pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + } else if (bcn->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + 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 (bcn->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + if (bcn->HTCaps.supportedChannelWidthSet) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 40MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_40MHZ; + } else { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 20MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + chWidth = eHT_CHANNEL_WIDTH_20MHZ; + } + } + lim_check_vht_op_mode_change(mac_ctx, session, chWidth, + pStaDs->staIndex, pMh->sa); + return; +} + +/* + * __sch_beacon_process_for_session() - Process the received beacon frame when + * station is not scanning and corresponding session is found + * + * + * @mac_ctx: mac_ctx + * @bcn: beacon struct + * @rx_pkt_info: received packet info + * @session: pe session pointer + * + * Following scenarios exist when Session exists + * IBSS STA receving beacons from IBSS Peers, who are part of IBSS. + * - call lim_handle_ibs_scoalescing with that session context. + * Infra STA receving beacons from AP to which it is connected + * - call sch_beacon_processFromAP with that session's context. + * BTAMP STA receving beacons from BTAMP AP + * - call sch_beacon_processFromAP 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 lim_handle_ibs_scoalescing with that session context. + * Infra/IBSS both active and receives Infra beacon: + * - call sch_beacon_processFromAP 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 + * + * Return: void + */ +static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, + tpSchBeaconStruct bcn, + uint8_t *rx_pkt_info, + tpPESession session) +{ + tPowerdBm localRRMConstraint = 0; + uint8_t bssIdx = 0; + tUpdateBeaconParams beaconParams; + uint8_t sendProbeReq = false; +#ifdef WLAN_FEATURE_11AC + tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info); +#endif +#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI + tPowerdBm regMax = 0, maxTxPower = 0; +#endif + cdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); + beaconParams.paramChangeBitmap = 0; + + if (LIM_IS_IBSS_ROLE(session)) { + lim_handle_ibss_coalescing(mac_ctx, bcn, rx_pkt_info, session); + } else if (LIM_IS_STA_ROLE(session) + || LIM_IS_BT_AMP_STA_ROLE(session)) { + if (false == sch_bcn_process_sta_bt_amp_sta(mac_ctx, bcn, + rx_pkt_info, session, &bssIdx, + &beaconParams, &sendProbeReq, pMh)) + return; + } + + if (session->htCapability && bcn->HTInfo.present) + lim_update_sta_run_time_ht_switch_chnl_params(mac_ctx, + &bcn->HTInfo, bssIdx, session); + + if (LIM_IS_STA_ROLE(session) + || LIM_IS_BT_AMP_STA_ROLE(session) + || LIM_IS_IBSS_ROLE(session)) { + /* Channel Switch information element updated */ + if (bcn->channelSwitchPresent) { + lim_update_channel_switch(mac_ctx, bcn, session); + } else if (session->gLimSpecMgmt.dot11hChanSwState == + eLIM_11H_CHANSW_RUNNING) { + lim_cancel_dot11h_channel_switch(mac_ctx, session); + } + } +#ifdef WLAN_FEATURE_11AC + if (LIM_IS_STA_ROLE(session) + || LIM_IS_BT_AMP_STA_ROLE(session) + || LIM_IS_IBSS_ROLE(session)) + sch_bcn_process_sta_bt_amp_sta_ibss(mac_ctx, bcn, + rx_pkt_info, session, &bssIdx, + &beaconParams, &sendProbeReq, pMh); +#endif + +#if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI) + /* Obtain the Max Tx power for the current regulatory */ + regMax = cfg_get_regulatory_max_transmit_power(mac_ctx, + session->currentOperChannel); +#endif + +#if defined WLAN_FEATURE_VOWIFI + if (mac_ctx->rrm.rrmPEContext.rrmEnable + && bcn->powerConstraintPresent) + localRRMConstraint = + bcn->localPowerConstraint.localPowerConstraints; + else + localRRMConstraint = 0; + maxTxPower = lim_get_max_tx_power(regMax, regMax - localRRMConstraint, + mac_ctx->roam.configParam.nTxPowerCap); +#elif defined FEATURE_WLAN_ESE + maxTxPower = regMax; +#endif + +#if defined FEATURE_WLAN_ESE + if (session->isESEconnection) { + tPowerdBm localESEConstraint = 0; + if (bcn->eseTxPwr.present) { + localESEConstraint = bcn->eseTxPwr.power_limit; + maxTxPower = lim_get_max_tx_power(maxTxPower, + localESEConstraint, + mac_ctx->roam.configParam.nTxPowerCap); + } + sch_log(mac_ctx, LOG1, + FL("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 != session->maxTxPower) { + sch_log(mac_ctx, LOG1, + FL("Local power constraint change..updating new maxTx power %d to HAL"), + maxTxPower); + if (lim_send_set_max_tx_power_req(mac_ctx, maxTxPower, session) + == eSIR_SUCCESS) + session->maxTxPower = maxTxPower; + } +#endif + + /* Indicate to LIM that Beacon is received */ + if (bcn->HTInfo.present) + lim_received_hb_handler(mac_ctx, + (uint8_t) bcn->HTInfo.primaryChannel, session); + else + lim_received_hb_handler(mac_ctx, (uint8_t) bcn->channelNumber, + session); + + /* + * I don't know if any additional IE is required here. Currently, not + * include addIE. + */ + if (sendProbeReq) + lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId, + session->bssId, session->currentOperChannel, + session->selfMacAddr, session->dot11mode, 0, NULL); + + if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) + && beaconParams.paramChangeBitmap) { + PELOGW(sch_log(mac_ctx, LOGW, + FL("Beacon for session[%d] got changed."), + session->peSessionId);) + PELOGW(sch_log(mac_ctx, LOGW, + FL("sending beacon param change bitmap: 0x%x "), + beaconParams.paramChangeBitmap);) + lim_send_beacon_params(mac_ctx, &beaconParams, session); + } +} + +/** + * sch_beacon_process() - process the beacon frame + * + * @mac_ctx: mac global context + * @rx_pkt_info: pointer to buffer descriptor + * + * @return None + */ +void +sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, + tpPESession session) +{ + static tSchBeaconStruct bcn; + tUpdateBeaconParams bcn_prm; + tpPESession ap_session = NULL; +#ifdef WLAN_FEATURE_MBSSID + uint8_t i; +#endif + + cdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams)); + bcn_prm.paramChangeBitmap = 0; + mac_ctx->sch.gSchBcnRcvCnt++; + /* Convert the beacon frame into a structure */ + if (sir_convert_beacon_frame2_struct(mac_ctx, (uint8_t *) rx_pkt_info, + &bcn) != eSIR_SUCCESS) { + PELOGE(sch_log(mac_ctx, LOGE, FL("beacon parsing failed"));) + mac_ctx->sch.gSchBcnParseErrorCnt++; + return; + } + + if (bcn.ssidPresent) + bcn.ssId.ssId[bcn.ssId.length] = 0; + /* + * First process the beacon in the context of any existing AP or BTAP + * session. This takes cares of following two scenarios: + * - session = NULL: + * e.g. beacon received from a neighboring BSS, you want to apply the + * protection settings to BTAP/InfraAP beacons + * - session 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 < mac_ctx->lim.maxBssId; i++) { + ap_session = pe_find_session_by_session_id(mac_ctx, i); + if (!((ap_session != NULL) && + (!(WMA_GET_OFFLOADSCANLEARN(rx_pkt_info))))) + continue; + + if (!LIM_IS_AP_ROLE(ap_session)) + continue; + + bcn_prm.bssIdx = ap_session->bssIdx; + if (ap_session->gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + ap_beacon_process(mac_ctx, rx_pkt_info, + &bcn, &bcn_prm, ap_session); + + if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) + && bcn_prm.paramChangeBitmap) { + /* Update the bcn and apply the new settings to HAL */ + sch_set_fixed_beacon_fields(mac_ctx, ap_session); + PELOG1(sch_log(mac_ctx, LOG1, + FL("Beacon for PE session[%d] got changed."), + ap_session->peSessionId);) + PELOG1(sch_log(mac_ctx, LOG1, + FL("sending beacon param change bitmap: 0x%x"), + bcn_prm.paramChangeBitmap);) + lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); + } + } +#else + ap_session = lim_is_ap_session_active(mac_ctx); + if ((ap_session != NULL) + && (!(WMA_GET_OFFLOADSCANLEARN(rx_pkt_info)))) { + bcn_prm.bssIdx = ap_session->bssIdx; + if (ap_session->gLimProtectionControl != + WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) + ap_beacon_process(mac_ctx, rx_pkt_info, &bcn, + &bcn_prm, ap_session); + + if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) + && bcn_prm.paramChangeBitmap) { + /* Update the bcn and apply the new settings to HAL */ + sch_set_fixed_beacon_fields(mac_ctx, ap_session); + PELOG1(sch_log(mac_ctx, LOG1, + FL("Beacon for PE session[%d] got changed."), + ap_session->peSessionId);) + PELOG1(sch_log(mac_ctx, LOG1, + FL("sending beacon param change bitmap: 0x%x "), + bcn_prm.paramChangeBitmap);) + lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); + } + } +#endif + /* + * Now process the beacon in the context of the BSS which is + * transmitting the beacons, if one is found + */ + if (session == NULL) + __sch_beacon_process_no_session(mac_ctx, &bcn, rx_pkt_info); + else + __sch_beacon_process_for_session(mac_ctx, &bcn, rx_pkt_info, + session); +} + +/** + * sch_beacon_edca_process(): Process the EDCA parameter set in the received + * beacon frame + * + * @mac_ctx: mac global context + * @edca: reference to edca parameters in beacon struct + * @session : pesession entry + * + * @return status of operation + */ +tSirRetStatus +sch_beacon_edca_process(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, + tpPESession session) +{ + uint8_t i; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + host_log_qos_edca_pkt_type *log_ptr = NULL; +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + PELOG1(sch_log(pMac, LOG1, + FL("Updating parameter set count: Old %d ---> new %d"), + session->gLimEdcaParamSetCount, edca->qosInfo.count);) + + session->gLimEdcaParamSetCount = edca->qosInfo.count; + session->gLimEdcaParams[EDCA_AC_BE] = edca->acbe; + session->gLimEdcaParams[EDCA_AC_BK] = edca->acbk; + session->gLimEdcaParams[EDCA_AC_VI] = edca->acvi; + session->gLimEdcaParams[EDCA_AC_VO] = edca->acvo; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type, + LOG_WLAN_QOS_EDCA_C); + if (log_ptr) { + log_ptr->aci_be = session->gLimEdcaParams[EDCA_AC_BE].aci.aci; + log_ptr->cw_be = + session->gLimEdcaParams[EDCA_AC_BE].cw.max << 4 + | session->gLimEdcaParams[EDCA_AC_BE].cw.min; + log_ptr->txoplimit_be = + session->gLimEdcaParams[EDCA_AC_BE].txoplimit; + log_ptr->aci_bk = + session->gLimEdcaParams[EDCA_AC_BK].aci.aci; + log_ptr->cw_bk = + session->gLimEdcaParams[EDCA_AC_BK].cw.max << 4 + | session->gLimEdcaParams[EDCA_AC_BK].cw.min; + log_ptr->txoplimit_bk = + session->gLimEdcaParams[EDCA_AC_BK].txoplimit; + log_ptr->aci_vi = + session->gLimEdcaParams[EDCA_AC_VI].aci.aci; + log_ptr->cw_vi = + session->gLimEdcaParams[EDCA_AC_VI].cw.max << 4 + | session->gLimEdcaParams[EDCA_AC_VI].cw.min; + log_ptr->txoplimit_vi = + session->gLimEdcaParams[EDCA_AC_VI].txoplimit; + log_ptr->aci_vo = + session->gLimEdcaParams[EDCA_AC_VO].aci.aci; + log_ptr->cw_vo = + session->gLimEdcaParams[EDCA_AC_VO].cw.max << 4 + | session->gLimEdcaParams[EDCA_AC_VO].cw.min; + log_ptr->txoplimit_vo = + session->gLimEdcaParams[EDCA_AC_VO].txoplimit; + } + WLAN_HOST_DIAG_LOG_REPORT(log_ptr); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + PELOG1(sch_log(pMac, LOGE, + FL("Updating Local EDCA Params(gLimEdcaParams) to: "));) + for (i = 0; i < MAX_NUM_AC; i++) { + PELOG1(sch_log(pMac, LOG1, + FL("AC[%d]: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"), + i, session->gLimEdcaParams[i].aci.aifsn, + session->gLimEdcaParams[i].aci.acm, + session->gLimEdcaParams[i].cw.min, + session->gLimEdcaParams[i].cw.max, + session->gLimEdcaParams[i].txoplimit);) + } + return eSIR_SUCCESS; +} diff --git a/core/mac/src/pe/sch/sch_debug.c b/core/mac/src/pe/sch/sch_debug.c new file mode 100644 index 000000000000..47c0714a83db --- /dev/null +++ b/core/mac/src/pe/sch/sch_debug.c @@ -0,0 +1,61 @@ +/* + * 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 sch_debug.cc contains some debug functions. + * + * Author: Sandesh Goel + * Date: 02/25/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "cdf_trace.h" +#include "sch_debug.h" +#define LOG_SIZE 256 + +void sch_log(tpAniSirGlobal pMac, uint32_t loglevel, const char *pString, ...) +{ + + CDF_TRACE_LEVEL cdf_debug_level; + char logBuffer[LOG_SIZE]; + va_list marker; + + /* getting proper Debug level */ + cdf_debug_level = get_vos_debug_level(loglevel); + + /* extracting arguments from pstring */ + va_start(marker, pString); + vsnprintf(logBuffer, LOG_SIZE, pString, marker); + CDF_TRACE(CDF_MODULE_ID_PE, cdf_debug_level, "%s", logBuffer); + va_end(marker); +} + +/* -------------------------------------------------------------------- */ diff --git a/core/mac/src/pe/sch/sch_debug.h b/core/mac/src/pe/sch/sch_debug.h new file mode 100644 index 000000000000..d27f72733dfe --- /dev/null +++ b/core/mac/src/pe/sch/sch_debug.h @@ -0,0 +1,53 @@ +/* + * 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 sch_debug.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 "utils_api.h" +#include "sir_debug.h" + +#if !defined(__printf) +#define __printf(a, b) +#endif + +void __printf(3, 4) sch_log(tpAniSirGlobal pMac, uint32_t loglevel, + const char *pString, ...); + +#endif diff --git a/core/mac/src/pe/sch/sch_message.c b/core/mac/src/pe/sch/sch_message.c new file mode 100644 index 000000000000..e746f8b742ea --- /dev/null +++ b/core/mac/src/pe/sch/sch_message.c @@ -0,0 +1,574 @@ +/* + * 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 "cds_api.h" +#include "sir_common.h" + +#include "wni_cfg.h" +#include "ani_global.h" +#include "cfg_api.h" +#include "lim_api.h" +#include "lim_send_messages.h" + +#include "sch_api.h" +#include "sch_debug.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 uint16_t */ +#define GET_CW(pCw) ((uint16_t) ((*(pCw) << 8) + *((pCw) + 1))) + +/* local functions */ +static tSirRetStatus get_wmm_local_params(tpAniSirGlobal pMac, + uint32_t + params[] + [WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]); +static void set_sch_edca_params(tpAniSirGlobal pMac, + uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], + tpPESession psessionEntry); + +/* -------------------------------------------------------------------- */ +/** + * sch_set_beacon_interval + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void sch_set_beacon_interval(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t bi; + + bi = psessionEntry->beaconParams.beaconInterval; + + if (bi < SCH_BEACON_INTERVAL_MIN || bi > SCH_BEACON_INTERVAL_MAX) { + sch_log(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 = (uint16_t) bi; +} + +/* -------------------------------------------------------------------- */ +/** + * sch_process_message + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param None + * @return None + */ + +void sch_process_message(tpAniSirGlobal pMac, tpSirMsgQ pSchMsg) +{ + uint32_t val; + + tpPESession psessionEntry = &pMac->lim.gpSession[0]; + PELOG3(sch_log(pMac, LOG3, FL("Received message (%x) "), pSchMsg->type);) + + switch (pSchMsg->type) { + + case SIR_SCH_CHANNEL_SWITCH_REQUEST: + sch_log(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(sch_log(pMac, LOG1, + FL + ("Waiting for TFP to halt before sending " + "start scan response")); + ) + } else + sch_send_start_scan_rsp(pMac); + } else { + /* In eDCF mode, send the response right away */ + sch_send_start_scan_rsp(pMac); + } + break; + + case SIR_SCH_END_SCAN_NTF: + PELOG3(sch_log(pMac, LOG3, + FL("Received STOP_SCAN_NTF from LIM")); + ) + pMac->sch.gSchScanReqRcvd = false; + break; + + case SIR_CFG_PARAM_UPDATE_IND: + + if (wlan_cfg_get_int(pMac, (uint16_t) pSchMsg->bodyval, &val) != + eSIR_SUCCESS) + sch_log(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)) + sch_set_beacon_interval(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: + sch_edca_profile_update(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)) + sch_qos_update_local(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++; + sch_qos_update_broadcast(pMac, psessionEntry); + } + break; + + default: + sch_log(pMac, LOGE, + FL("Cfg param %d indication not handled"), + pSchMsg->bodyval); + } + break; + + default: + sch_log(pMac, LOGE, FL("Unknown message in schMsgQ type %d"), + pSchMsg->type); + } + +} + +/* get the local or broadcast parameters based on the profile sepcified in the config */ +/* params are delivered in this order: BK, BE, VI, VO */ +tSirRetStatus +sch_get_params(tpAniSirGlobal pMac, + uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], uint8_t local) +{ + uint32_t val; + uint32_t i, idx; + uint32_t *prf; + + uint32_t 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}; + uint32_t 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}; + uint32_t ani_b[] = { WNI_CFG_EDCA_ANI_ACBE, WNI_CFG_EDCA_ANI_ACBK, + WNI_CFG_EDCA_ANI_ACVI, WNI_CFG_EDCA_ANI_ACVO}; + uint32_t wme_b[] = { WNI_CFG_EDCA_WME_ACBE, WNI_CFG_EDCA_WME_ACBK, + WNI_CFG_EDCA_WME_ACVI, WNI_CFG_EDCA_WME_ACVO}; + + if (wlan_cfg_get_int(pMac, WNI_CFG_EDCA_PROFILE, &val) != eSIR_SUCCESS) { + sch_log(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) { + sch_log(pMac, LOGE, + FL("Invalid EDCA_PROFILE %d, using %d instead"), val, + WNI_CFG_EDCA_PROFILE_ANI); + val = WNI_CFG_EDCA_PROFILE_ANI; + } + + sch_log(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++) { + uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN]; + uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN; + if (wlan_cfg_get_str + (pMac, (uint16_t) prf[i], (uint8_t *) &data[0], + &len) != eSIR_SUCCESS) { + sch_log(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]); + return eSIR_FAILURE; + } + if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) { + sch_log(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] = (uint32_t) data[idx]; + } + PELOG1(sch_log + (pMac, LOG1, FL("GetParams: local=%d, profile = %d Done"), local, + val); + ) + return eSIR_SUCCESS; +} + +/** + * broadcast_wmm_of_concurrent_sta_session() - broadcasts wmm info + * @mac_ctx: mac global context + * @session: pesession entry + * + * Return: void + */ +static void +broadcast_wmm_of_concurrent_sta_session(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + uint8_t i, j; + tpPESession concurrent_session = NULL; + + for (i = 0; i < mac_ctx->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 (!((mac_ctx->lim.gpSession[i].valid == true) && + (mac_ctx->lim.gpSession[i].peSessionId != + session->peSessionId) + && (mac_ctx->lim.gpSession[i].currentOperChannel == + session->currentOperChannel) + && (mac_ctx->lim.gpSession[i].limSystemRole + == eLIM_STA_ROLE))) + continue; + + concurrent_session = &(mac_ctx->lim.gpSession[i]); + break; + } + + if (concurrent_session == NULL) + return; + /* + * Once atleast one concurrent session on same channel is found and WMM + * broadcast params for current SoftAP/GO session updated, return + */ + for (j = 0; j < MAX_NUM_AC; j++) { + session->gLimEdcaParamsBC[j].aci.acm = + concurrent_session->gLimEdcaParams[j].aci.acm; + session->gLimEdcaParamsBC[j].aci.aifsn = + concurrent_session->gLimEdcaParams[j].aci.aifsn; + session->gLimEdcaParamsBC[j].cw.min = + concurrent_session->gLimEdcaParams[j].cw.min; + session->gLimEdcaParamsBC[j].cw.max = + concurrent_session->gLimEdcaParams[j].cw.max; + session->gLimEdcaParamsBC[j].txoplimit = + concurrent_session->gLimEdcaParams[j].txoplimit; + PELOG1(sch_log(mac_ctx, LOG1, + FL("QoSUpdateBCast changed again due to concurrent INFRA STA session: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"), + j, session->gLimEdcaParamsBC[j].aci.aifsn, + session->gLimEdcaParamsBC[j].aci.acm, + session->gLimEdcaParamsBC[j].cw.min, + session->gLimEdcaParamsBC[j].cw.max, + session->gLimEdcaParamsBC[j].txoplimit);) + } +} + +void sch_qos_update_broadcast(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + uint32_t cwminidx, cwmaxidx, txopidx; + uint32_t phyMode; + uint8_t i; + + if (sch_get_params(pMac, params, false) != eSIR_SUCCESS) { + PELOGE(sch_log(pMac, LOGE, FL("QosUpdateBroadcast: failed"));) + return; + } + lim_get_phy_mode(pMac, &phyMode, psessionEntry); + + PELOG1(sch_log(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; i < MAX_NUM_AC; i++) { + psessionEntry->gLimEdcaParamsBC[i].aci.acm = + (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX]; + psessionEntry->gLimEdcaParamsBC[i].aci.aifsn = + (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX]; + psessionEntry->gLimEdcaParamsBC[i].cw.min = + convert_cw(GET_CW(¶ms[i][cwminidx])); + psessionEntry->gLimEdcaParamsBC[i].cw.max = + convert_cw(GET_CW(¶ms[i][cwmaxidx])); + psessionEntry->gLimEdcaParamsBC[i].txoplimit = + (uint16_t) params[i][txopidx]; + + PELOG1(sch_log + (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 */ + broadcast_wmm_of_concurrent_sta_session(pMac, psessionEntry); + + if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS) + PELOGE(sch_log(pMac, LOGE, "Unable to set beacon fields!");) +} + +void sch_qos_update_local(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + + uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + + if (sch_get_params(pMac, params, true /*local */) != eSIR_SUCCESS) { + PELOGE(sch_log(pMac, LOGE, FL("sch_get_params(local) failed"));) + return; + } + + set_sch_edca_params(pMac, params, psessionEntry); + + /* For AP, the bssID is stored in LIM Global context. */ + lim_send_edca_params(pMac, psessionEntry->gLimEdcaParams, + psessionEntry->bssIdx); +} + +/** ---------------------------------------------------------- + \fn sch_set_default_edca_params + \brief This function sets the gLimEdcaParams to the default + \ local wmm profile. + \param tpAniSirGlobal pMac + \return none + \ ------------------------------------------------------------ */ +void sch_set_default_edca_params(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]; + + if (get_wmm_local_params(pMac, params) != eSIR_SUCCESS) { + PELOGE(sch_log(pMac, LOGE, FL("get_wmm_local_params() failed"));) + return; + } + + set_sch_edca_params(pMac, params, psessionEntry); + return; +} + +/** ---------------------------------------------------------- + \fn set_sch_edca_params + \brief This function fills in the gLimEdcaParams structure + \ with the given edca params. + \param tpAniSirGlobal pMac + \return none + \ ------------------------------------------------------------ */ +static void +set_sch_edca_params(tpAniSirGlobal pMac, + uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], + tpPESession psessionEntry) +{ + uint32_t i; + uint32_t cwminidx, cwmaxidx, txopidx; + uint32_t phyMode; + + lim_get_phy_mode(pMac, &phyMode, psessionEntry); + + PELOG1(sch_log(pMac, LOG1, FL("lim_get_phy_mode() = %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; i < MAX_NUM_AC; i++) { + psessionEntry->gLimEdcaParams[i].aci.acm = + (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX]; + psessionEntry->gLimEdcaParams[i].aci.aifsn = + (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX]; + psessionEntry->gLimEdcaParams[i].cw.min = + convert_cw(GET_CW(¶ms[i][cwminidx])); + psessionEntry->gLimEdcaParams[i].cw.max = + convert_cw(GET_CW(¶ms[i][cwmaxidx])); + psessionEntry->gLimEdcaParams[i].txoplimit = + (uint16_t) params[i][txopidx]; + + PELOG1(sch_log + (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 get_wmm_local_params + \brief This function gets the WMM local edca parameters. + \param tpAniSirGlobal pMac + \param uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN] + \return none + \ ------------------------------------------------------------ */ +static tSirRetStatus +get_wmm_local_params(tpAniSirGlobal pMac, + uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]) +{ + uint32_t i, idx; + uint32_t *prf; + uint32_t 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++) { + uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN]; + uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN; + if (wlan_cfg_get_str + (pMac, (uint16_t) prf[i], (uint8_t *) &data[0], + &len) != eSIR_SUCCESS) { + sch_log(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]); + return eSIR_FAILURE; + } + if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) { + sch_log(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] = (uint32_t) data[idx]; + } + return eSIR_SUCCESS; +} + +/** ---------------------------------------------------------- + \fn sch_edca_profile_update + \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 sch_edca_profile_update(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + if (LIM_IS_AP_ROLE(psessionEntry) || + LIM_IS_IBSS_ROLE(psessionEntry)) { + sch_qos_update_local(pMac, psessionEntry); + psessionEntry->gLimEdcaParamSetCount++; + sch_qos_update_broadcast(pMac, psessionEntry); + } +} + +/* -------------------------------------------------------------------- */ diff --git a/core/mac/src/pe/sch/sch_sys_params.h b/core/mac/src/pe/sch/sch_sys_params.h new file mode 100644 index 000000000000..adf5c198277f --- /dev/null +++ b/core/mac/src/pe/sch/sch_sys_params.h @@ -0,0 +1,107 @@ +/* + * 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 sch_sys_params.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/core/mac/src/sys/common/inc/wlan_qct_sys.h b/core/mac/src/sys/common/inc/wlan_qct_sys.h new file mode 100644 index 000000000000..c80b641a2035 --- /dev/null +++ b/core/mac/src/sys/common/inc/wlan_qct_sys.h @@ -0,0 +1,194 @@ +/* + * 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_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 void (*sysResponseCback)(void *pUserData); + +typedef enum { + SYS_MSG_ID_MC_START, + SYS_MSG_ID_MC_THR_PROBE, + SYS_MSG_ID_MC_TIMER, + SYS_MSG_ID_MC_STOP, + SYS_MSG_ID_FTM_RSP, + +} SYS_MSG_ID; + +/*--------------------------------------------------------------------------- + Preprocessor definitions and constants + -------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Function declarations and documenation + -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + + \brief sys_build_message_header() - 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 + + --------------------------------------------------------------------------*/ +CDF_STATUS sys_build_message_header(SYS_MSG_ID sysMsgId, cds_msg_t *pMsg); + +/*---------------------------------------------------------------------------- + + \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 p_cds_context - pointer to the CDS 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 CDF_STATUS_SUCCESS - + + \todo: We have not 'status' on the callback. How do we notify the + callback that there is a failure ? + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sysMcStart(v_CONTEXT_t p_cds_context, sysResponseCback userCallback, + void *pUserData); + +/*---------------------------------------------------------------------------- + + \brief sys_stop() - Stop the SYS module. + + This function stops the SYS module. + + \todo: What else do we need to do on sys_stop()? + + \param p_cds_context - pointer to the CDS Context + + \return CDF_STATUS_SUCCESS - the SYS module is stopped. + + CDF_STATUS_E_FAILURE - the SYS module open failed to stop. + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sys_stop(v_CONTEXT_t p_cds_context); + +/*---------------------------------------------------------------------------- + + \brief sys_mc_process_msg() - 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 p_cds_context - pointer to the CDS Context + + \param pMsg - pointer to the message to be processed. + + \return - CDF_STATUS_SUCCESS - the message was processed successfully. + + CDF_STATUS_E_BADMSG - a bad (unknown type) message was received + and subsequently not processed. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sys_mc_process_msg(v_CONTEXT_t p_cds_context, cds_msg_t *pMsg); + +void wlan_sys_probe(void); + +#endif /* WLAN_QCT_SYS_H__ */ diff --git a/core/mac/src/sys/common/src/wlan_qct_sys.c b/core/mac/src/sys/common/src/wlan_qct_sys.c new file mode 100644 index 000000000000..c2c39d1d97ca --- /dev/null +++ b/core/mac/src/sys/common/src/wlan_qct_sys.c @@ -0,0 +1,371 @@ +/* + * 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 +#include +#include /* needed for tSirRetStatus */ +#include /* needed for tSirMbMsg */ +#include /* needed for SIR_... message types */ +#include /* needed for WNI_... message types */ +#include "ani_global.h" +#include "wma_types.h" +#include "sme_api.h" +#include "mac_init_api.h" + +/* 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 SYS_MSG_COOKIE 0xFACE + +/* SYS stop timeout 30 seconds */ +#define SYS_STOP_TIMEOUT (30000) + +static cdf_event_t g_stop_evt; + +CDF_STATUS sys_build_message_header(SYS_MSG_ID sysMsgId, cds_msg_t *pMsg) +{ + pMsg->type = sysMsgId; + pMsg->reserved = SYS_MSG_COOKIE; + + return (CDF_STATUS_SUCCESS); +} + +void sys_stop_complete_cb(void *pUserData) { + cdf_event_t *pStopEvt = (cdf_event_t *) pUserData; + CDF_STATUS cdf_status; +/*-------------------------------------------------------------------------*/ + + cdf_status = cdf_event_set(pStopEvt); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + +} /* cds_sys_stop_complete_cback() */ + +CDF_STATUS sys_stop(v_CONTEXT_t p_cds_context) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_msg_t sysMsg; + + /* Initialize the stop event */ + cdf_status = cdf_event_init(&g_stop_evt); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + return cdf_status; + } + + /* post a message to SYS module in MC to stop SME and MAC */ + sys_build_message_header(SYS_MSG_ID_MC_STOP, &sysMsg); + + /* Save the user callback and user data */ + /* finished. */ + sysMsg.callback = sys_stop_complete_cb; + sysMsg.bodyptr = (void *)&g_stop_evt; + + /* post the message.. */ + cdf_status = cds_mq_post_message(CDS_MQ_ID_SYS, &sysMsg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_status = CDF_STATUS_E_BADMSG; + } + + cdf_status = cdf_wait_single_event(&g_stop_evt, SYS_STOP_TIMEOUT); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + + cdf_status = cdf_event_destroy(&g_stop_evt); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + + return (cdf_status); +} + +CDF_STATUS sys_mc_process_msg(v_CONTEXT_t p_cds_context, cds_msg_t *pMsg) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + void *hHal; + + if (NULL == pMsg) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "%s: NULL pointer to cds_msg_t", __func__); + return CDF_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 CDF_ASSERT*/ + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + " Received SYS_MSG_ID_MC_START message msgType= %d [0x%08x]", + pMsg->type, pMsg->type); + CDF_ASSERT(0); + break; + } + + case SYS_MSG_ID_MC_STOP: + { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_INFO, + "Processing SYS MC STOP"); + + /* get the HAL context... */ + hHal = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal", __func__); + } else { + cdf_status = + sme_stop(hHal, + HAL_STOP_TYPE_SYS_DEEP_SLEEP); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS + (cdf_status)); + + cdf_status = + mac_stop(hHal, + HAL_STOP_TYPE_SYS_DEEP_SLEEP); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS + (cdf_status)); + + ((sysResponseCback) pMsg-> + callback)((void *)pMsg->bodyptr); + + cdf_status = CDF_STATUS_SUCCESS; + } + break; + } + + /* Process MC thread probe. Just callback to the */ + /* function that is in the message. */ + case SYS_MSG_ID_MC_THR_PROBE: + { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_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: + { + cdf_mc_timer_callback_t timerCB = + pMsg->callback; + + if (NULL != timerCB) { + timerCB(pMsg->bodyptr); + } + break; + } + case SYS_MSG_ID_FTM_RSP: + { + tpAniSirGlobal mac_ctx = NULL; + hHal = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + FL("Invalid hal")); + cdf_mem_free(pMsg->bodyptr); + break; + } + mac_ctx = PMAC_STRUCT(hHal); + if (NULL == mac_ctx) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + FL("Invalid mac context")); + cdf_mem_free(pMsg->bodyptr); + break; + } + if (NULL == mac_ctx->ftm_msg_processor_callback) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + FL("callback pointer is NULL")); + cdf_mem_free(pMsg->bodyptr); + break; + } + mac_ctx->ftm_msg_processor_callback( + (void *)pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; + } + + default: + { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + "Unknown message type in sys_mc_process_msg() 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: + { + CDF_ASSERT(0); + + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + "Received SYS message cookie with unidentified " + "MC message type= %d [0x%08X]", + pMsg->type, pMsg->type); + + cdf_status = CDF_STATUS_E_BADMSG; + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + break; + } + } /* end switch on pMsg->type */ + } /* end else */ + + return (cdf_status); +} + + +void sys_process_mmh_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) { + CDS_MQ_ID targetMQ = CDS_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) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "NULL Message Pointer"); + CDF_ASSERT(0); + return; + } + + switch (pMsg->type) { + /* + ** Following messages are routed to SYS + */ + case WNI_CFG_DNLD_REQ: + case WNI_CFG_DNLD_CNF: + { + /* Forward this message to the SYS module */ + targetMQ = CDS_MQ_ID_SYS; + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Handling for the Message ID %d is removed in SYS\r\n", + pMsg->type); + + CDF_ASSERT(0); + break; + } + + /* + ** Following messages are routed to HAL + */ + case WNI_CFG_DNLD_RSP: + { + /* Forward this message to the HAL module */ + targetMQ = CDS_MQ_ID_WMA; + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Handling for the Message ID %d is removed as there is no HAL \r\n", + pMsg->type); + + CDF_ASSERT(0); + break; + } + + 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 = CDS_MQ_ID_PE; + break; + } + + case WNI_CFG_GET_RSP: + case WNI_CFG_SET_CNF: + { + /* Forward this message to the SME module */ + targetMQ = CDS_MQ_ID_SME; + break; + } + + default: + { + + if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) + && (pMsg->type <= eWNI_SME_MSG_TYPES_END)) { + targetMQ = CDS_MQ_ID_SME; + break; + } + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Message of ID %d is not yet handled by SYS\r\n", + pMsg->type); + + CDF_ASSERT(0); + } + + } + + /* + ** Post now the message to the appropriate module for handling + */ + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(targetMQ, (cds_msg_t *) pMsg)) { + /* Caller doesn't allocate memory for the pMsg. It allocate memory for bodyptr */ + /* free the mem and return */ + if (pMsg->bodyptr) { + cdf_mem_free(pMsg->bodyptr); + } + } + +} /* sys_process_mmh_msg() */ + +void wlan_sys_probe(void) +{ + cds_msg_t cds_message; + + cds_message.reserved = SYS_MSG_COOKIE; + cds_message.type = SYS_MSG_ID_MC_THR_PROBE; + cds_message.bodyptr = NULL; + + cds_mq_post_message(CDS_MQ_ID_SYS, &cds_message); + + return; +} diff --git a/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h b/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h new file mode 100644 index 000000000000..6aeb635cd0a0 --- /dev/null +++ b/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h @@ -0,0 +1,149 @@ +/* + * 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 VossWrapper.h + * + * @brief This header file contains the various structure definitions and + * function prototypes for the RTOS abstraction layer, implemented for VOSS + */ + +#ifndef __VOSS_WRAPPER_H +#define __VOSS_WRAPPER_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/*--------------------------------------------------------------------------- + * Include Files + * ------------------------------------------------------------------------*/ + +#include "sir_types.h" +#include "sir_params.h" +#include "sys_def.h" +#include "cdf_mc_timer.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cdf_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((void *)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((void *)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 + uint64_t tmrSignature; + void (*pExpireFunc)(void *, uint32_t); + uint32_t expireInput; + uint64_t initScheduleTimeInMsecs; + uint64_t rescheduleTimeInMsecs; + cdf_mc_timer_t cdf_timer; + + /* Pointer to the MAC global structure, which stores the context for the NIC, */ + /* for which this timer is supposed to operate. */ + void *pMac; + uint8_t sessionId; + +} TX_TIMER; + +#define TX_TIMER_VALID(timer) (timer.pMac != 0) + +extern uint64_t tx_time_get(void); +extern uint32_t tx_timer_activate(TX_TIMER *); +extern uint32_t tx_timer_change(TX_TIMER *, uint64_t, uint64_t); +extern uint32_t tx_timer_change_context(TX_TIMER *, uint32_t); +#ifdef TIMER_MANAGER +extern uint32_t tx_timer_create_intern_debug(void *, TX_TIMER *, + char *, void (*)(void *, + uint32_t), + uint32_t, uint64_t, + uint64_t, uint64_t, + char *fileName, + uint32_t lineNum); +#else +extern uint32_t tx_timer_create_intern(void *, TX_TIMER *, char *, + void (*)(void *, uint32_t), + uint32_t, uint64_t, uint64_t, + uint64_t); +#endif +extern uint32_t tx_timer_deactivate(TX_TIMER *); +extern uint32_t tx_timer_delete(TX_TIMER *); +extern bool tx_timer_running(TX_TIMER *); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/core/mac/src/sys/legacy/src/platform/src/sys_wrapper.c b/core/mac/src/sys/legacy/src/platform/src/sys_wrapper.c new file mode 100644 index 000000000000..47499656cd41 --- /dev/null +++ b/core/mac/src/sys/legacy/src/platform/src/sys_wrapper.c @@ -0,0 +1,502 @@ +/* + * 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 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 cdf_timerIsActive 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 "sys_wrapper.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 + * + */ +uint64_t tx_time_get(void) +{ + return (cdf_mc_timer_get_system_ticks()); + +} /* * tx_time_get() */ + +/**--------------------------------------------------------------------- + * tx_timer_activate() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +uint32_t tx_timer_activate(TX_TIMER *timer_ptr) +{ + CDF_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) { + CDF_ASSERT(timer_ptr->tmrSignature == 0); + + return TX_TIMER_ERROR; + + } + /* Check for an uninitialized timer */ + CDF_ASSERT(0 != strlen(TIMER_NAME)); + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, + "Timer %s being activated\n", TIMER_NAME); + + status = cdf_mc_timer_start(&timer_ptr->cdf_timer, + timer_ptr->initScheduleTimeInMsecs); + + if (CDF_STATUS_SUCCESS == status) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, + "Timer %s now activated\n", TIMER_NAME); + return TX_SUCCESS; + } else if (CDF_STATUS_E_ALREADY == status) { + /* starting timer fails because timer is already started; this is okay */ + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, + "Timer %s is already running\n", TIMER_NAME); + return TX_SUCCESS; + } else { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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. + * + */ +uint32_t tx_timer_change(TX_TIMER *timer_ptr, + uint64_t initScheduleTimeInTicks, + uint64_t rescheduleTimeInTicks) +{ + /* Put a check for the free builds */ + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) { + CDF_ASSERT(timer_ptr->tmrSignature == 0); + + return TX_TIMER_ERROR; + } + /* changes cannot be applied until timer stops running */ + if (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&timer_ptr->cdf_timer)) { + 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. + * + */ +uint32_t tx_timer_change_context(TX_TIMER *timer_ptr, + uint32_t expiration_input) +{ + + /* Put a check for the free builds */ + if (TX_AIRGO_TMR_SIGNATURE != timer_ptr->tmrSignature) { + CDF_ASSERT(timer_ptr->tmrSignature == 0); + + return TX_TIMER_ERROR; + } + /* changes cannot be applied until timer stops running */ + if (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&timer_ptr->cdf_timer)) { + 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 void tx_main_timer_func(void *functionContext) +{ + TX_TIMER *timer_ptr = (TX_TIMER *) functionContext; + + if (NULL == timer_ptr) { + CDF_ASSERT(0); + return; + } + + if (NULL == timer_ptr->pExpireFunc) { + CDF_ASSERT(0); + return; + } + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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) { + CDF_STATUS status; + status = cdf_mc_timer_start(&timer_ptr->cdf_timer, + timer_ptr->rescheduleTimeInMsecs); + timer_ptr->rescheduleTimeInMsecs = 0; + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_WARN, + "Unable to reschedule timer %s; status=%d", + TIMER_NAME, status); + } + } +} /*** tx_timer_change() ***/ + +#ifdef TIMER_MANAGER +uint32_t tx_timer_create_intern_debug(void *pMacGlobal, + TX_TIMER *timer_ptr, char *name_ptr, + void (*expiration_function)(void *, + uint32_t), + uint32_t expiration_input, + uint64_t initScheduleTimeInTicks, + uint64_t rescheduleTimeInTicks, + uint64_t auto_activate, char *fileName, + uint32_t lineNum) +{ + CDF_STATUS status; + + if (NULL == expiration_function) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "NULL timer expiration"); + CDF_ASSERT(0); + return TX_TIMER_ERROR; + } + + if (NULL == name_ptr) { + + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "NULL name pointer for timer"); + CDF_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 = + cdf_mc_timer_init_debug(&timer_ptr->cdf_timer, CDF_TIMER_TYPE_SW, + tx_main_timer_func, (void *) timer_ptr, + fileName, lineNum); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Cannot create timer for %s\n", TIMER_NAME); + return TX_TIMER_ERROR; + } + + if (0 != rescheduleTimeInTicks) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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 +uint32_t tx_timer_create_intern(void *pMacGlobal, TX_TIMER *timer_ptr, + char *name_ptr, + void (*expiration_function)(void *, + uint32_t), + uint32_t expiration_input, + uint64_t initScheduleTimeInTicks, + uint64_t rescheduleTimeInTicks, + uint64_t auto_activate) +{ + CDF_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 = cdf_mc_timer_init(&timer_ptr->cdf_timer, CDF_TIMER_TYPE_SW, + tx_main_timer_func, (void *) timer_ptr); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Cannot create timer for %s\n", TIMER_NAME); + return TX_TIMER_ERROR; + } + + if (0 != rescheduleTimeInTicks) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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. + * + */ +uint32_t tx_timer_deactivate(TX_TIMER *timer_ptr) +{ + CDF_STATUS vStatus; + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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 = cdf_mc_timer_stop(&timer_ptr->cdf_timer); + if (CDF_STATUS_SUCCESS != vStatus) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO_HIGH, + "Unable to stop timer %s; status =%d\n", + TIMER_NAME, vStatus); + } + + return TX_SUCCESS; + +} /*** tx_timer_deactivate() ***/ + +uint32_t tx_timer_delete(TX_TIMER *timer_ptr) +{ + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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; + } + + cdf_mc_timer_destroy(&timer_ptr->cdf_timer); + return TX_SUCCESS; +} /*** tx_timer_delete() ***/ + +/**--------------------------------------------------------------------- + * tx_timer_running() + * + * FUNCTION: + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param + * + * @return TX_SUCCESS. + * + */ +bool tx_timer_running(TX_TIMER *timer_ptr) +{ + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_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 false; + + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&timer_ptr->cdf_timer)) { + return true; + } + return false; + +} /*** tx_timer_running() ***/ diff --git a/core/mac/src/sys/legacy/src/system/inc/sys_debug.h b/core/mac/src/sys/legacy/src/system/inc/sys_debug.h new file mode 100644 index 000000000000..4a2578885d21 --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/inc/sys_debug.h @@ -0,0 +1,47 @@ +/* + * 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 sys_global.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 "utils_api.h" +#include "sir_debug.h" +#include "sir_params.h" + +void sys_log(tpAniSirGlobal pMac, uint32_t loglevel, const char *pString, ...); + +#endif /* __SYS_DEBUG_H__ */ diff --git a/core/mac/src/sys/legacy/src/system/inc/sys_def.h b/core/mac/src/sys/legacy/src/system/inc/sys_def.h new file mode 100644 index 000000000000..abdae33dc19c --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/inc/sys_def.h @@ -0,0 +1,168 @@ +/* + * 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 sys_def.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 */ + +/* / 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 */ + +/* / 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/core/mac/src/sys/legacy/src/system/inc/sys_entry_func.h b/core/mac/src/sys/legacy/src/system/inc/sys_entry_func.h new file mode 100644 index 000000000000..41afc8bdfd3f --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/inc/sys_entry_func.h @@ -0,0 +1,53 @@ +/* + * 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 sys_entry_func.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 "ani_global.h" + +extern tSirRetStatus sys_init_globals(tpAniSirGlobal); +extern void sysBbtEntry(uint32_t dummy); +extern void sysSchEntry(uint32_t dummy); +extern void sysPmmEntry(uint32_t dummy); +extern void sysDphEntry(uint32_t dummy); +extern void sysLimEntry(uint32_t dummy); +extern void sysMmhEntry(uint32_t dummy); +extern void sysMntEntry(uint32_t dummy); +extern void sysHalEntry(uint32_t dummy); +extern void sysNimPttEntry(uint32_t dummy); + +#endif /* __SYS_ENTRY_FUNC_H */ diff --git a/core/mac/src/sys/legacy/src/system/inc/sys_startup.h b/core/mac/src/sys/legacy/src/system/inc/sys_startup.h new file mode 100644 index 000000000000..e56bd6193dba --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/inc/sys_startup.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/* + * + * sys_startup.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 "sir_params.h" + +/* Defines */ + +/* Function */ + +extern void sysMACCleanup(void *); +extern tSirRetStatus sys_bbt_process_message_core(struct sAniSirGlobal *, tpSirMsgQ, + uint32_t, uint32_t); + +#endif /* __SYSSTARTUP_H */ diff --git a/core/mac/src/sys/legacy/src/system/src/mac_init_api.c b/core/mac/src/sys/legacy/src/system/src/mac_init_api.c new file mode 100644 index 000000000000..5c0877a90647 --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/src/mac_init_api.c @@ -0,0 +1,194 @@ +/* + * 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. + */ + +/* + * + * mac_init_api.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 "cfg_api.h" /* cfg_cleanup */ +#include "lim_api.h" /* lim_cleanup */ +#include "sir_types.h" +#include "sys_debug.h" +#include "sys_entry_func.h" +#include "mac_init_api.h" + +#ifdef TRACE_RECORD +#include "mac_trace.h" +#endif + +extern tSirRetStatus halDoCfgInit(tpAniSirGlobal pMac); +extern tSirRetStatus halProcessStartEvent(tpAniSirGlobal pMac); + +tSirRetStatus mac_start(tHalHandle hHal, void *pHalMacStartParams) +{ + tSirRetStatus status = eSIR_SUCCESS; + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + + if (NULL == pMac) { + CDF_ASSERT(0); + status = eSIR_FAILURE; + return status; + } + + pMac->gDriverType = + ((tHalMacStartParameters *) pHalMacStartParams)->driverType; + + sys_log(pMac, LOG2, FL("called\n")); + + if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { + status = pe_start(pMac); + } + + return status; +} + +/** ------------------------------------------------------------- + \fn mac_stop + \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 mac_stop(tHalHandle hHal, tHalStopType stopType) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + pe_stop(pMac); + cfg_cleanup(pMac); + + return eSIR_SUCCESS; +} + +/** ------------------------------------------------------------- + \fn mac_open + \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 mac_open(tHalHandle *pHalHandle, tHddHandle hHdd, + tMacOpenParameters *pMacOpenParms) +{ + tpAniSirGlobal p_mac = NULL; + tSirRetStatus status = eSIR_SUCCESS; + + 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 = cdf_mem_malloc(sizeof(tAniSirGlobal)); + if (NULL == p_mac) + return eSIR_MEM_ALLOC_FAILED; + + /* Initialize the p_mac structure */ + cdf_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 != log_init(p_mac)) { + cdf_mem_free(p_mac); + return eSIR_FAILURE; + } + + /* Call routine to initialize CFG data structures */ + if (eSIR_SUCCESS != cfg_init(p_mac)) { + cdf_mem_free(p_mac); + return eSIR_FAILURE; + } + + sys_init_globals(p_mac); + } + + /* 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 = pe_open(p_mac, pMacOpenParms); + if (eSIR_SUCCESS != status) { + sys_log(p_mac, LOGE, FL("mac_open failure\n")); + cdf_mem_free(p_mac); + } + + return status; +} + +/** ------------------------------------------------------------- + \fn mac_close + \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 mac_close(tHalHandle hHal) +{ + + tpAniSirGlobal pMac = (tpAniSirGlobal) hHal; + + if (!pMac) + return eSIR_FAILURE; + + pe_close(pMac); + + /* Call routine to free-up all CFG data structures */ + cfg_de_init(pMac); + + log_deinit(pMac); + + /* Finally, de-allocate the global MAC datastructure: */ + cdf_mem_free(pMac); + + return eSIR_SUCCESS; +} diff --git a/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c new file mode 100644 index 000000000000..304ab3e8f7be --- /dev/null +++ b/core/mac/src/sys/legacy/src/system/src/sys_entry_func.c @@ -0,0 +1,247 @@ +/* + * 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. + */ + +/* + * sys_entry_func.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 "sir_common.h" +#include "ani_global.h" + +#include "lim_api.h" +#include "sch_api.h" +#include "utils_api.h" + +#include "sys_debug.h" +#include "sys_def.h" +#include "sys_entry_func.h" +#include "sys_startup.h" +#include "lim_trace.h" +#include "wma_types.h" + +tSirRetStatus postPTTMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +#include "cdf_types.h" +#include "cds_packet.h" + +#define MAX_DEAUTH_ALLOWED 5 +/* --------------------------------------------------------------------------- */ +/** + * sys_init_globals + * + * FUNCTION: + * Initializes system level global parameters + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param tpAniSirGlobal Sirius software parameter struct pointer + * @return None + */ + +tSirRetStatus sys_init_globals(tpAniSirGlobal pMac) +{ + + cdf_mem_set((uint8_t *) &pMac->sys, sizeof(pMac->sys), 0); + + pMac->sys.gSysEnableScanMode = 1; + pMac->sys.gSysEnableLinkMonitorMode = 0; + sch_init_globals(pMac); + + return eSIR_SUCCESS; +} + +/** + * sys_bbt_process_message_core() - to process BBT messages + * @mac_ctx: pointer to mac context + * @msg: message pointer + * @type: type of persona + * @subtype: subtype of persona + * + * This routine is to process some bbt messages + * + * Return: None + */ +tSirRetStatus +sys_bbt_process_message_core(tpAniSirGlobal mac_ctx, tpSirMsgQ msg, + uint32_t type, uint32_t subtype) +{ + uint32_t framecount; + tSirRetStatus ret; + void *bd_ptr; + tMgmtFrmDropReason dropreason; + cds_pkt_t *vos_pkt = (cds_pkt_t *) msg->bodyptr; + CDF_STATUS cdf_status = + wma_ds_peek_rx_packet_info(vos_pkt, &bd_ptr, false); + uint8_t sessionid; + tpPESession pe_session; + tpSirMacMgmtHdr mac_hdr; + + mac_ctx->sys.gSysBbtReceived++; + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + goto fail; + + sys_log(mac_ctx, LOG3, FL("Rx Mgmt Frame Subtype: %d\n"), subtype); + sir_dump_buf(mac_ctx, SIR_SYS_MODULE_ID, LOG3, + (uint8_t *) WMA_GET_RX_MAC_HEADER(bd_ptr), + WMA_GET_RX_MPDU_LEN(bd_ptr)); + sir_dump_buf(mac_ctx, SIR_SYS_MODULE_ID, LOG3, + WMA_GET_RX_MPDU_DATA(bd_ptr), + WMA_GET_RX_PAYLOAD_LEN(bd_ptr)); + + mac_ctx->sys.gSysFrameCount[type][subtype]++; + framecount = mac_ctx->sys.gSysFrameCount[type][subtype]; + + if (type == SIR_MAC_MGMT_FRAME) { + if (true == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) { + mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); + pe_session = pe_find_session_by_bssid(mac_ctx, + mac_hdr->bssId, + &sessionid); + if (pe_session && + (pe_session->pePersona == CDF_SAP_MODE)) { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_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) && + (!lim_is_system_in_scan_state(mac_ctx)) && + (GET_LIM_PROCESS_DEFD_MESGS(mac_ctx) != true) && + !mac_ctx->lim.gLimSystemInScanLearnMode) { + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO_HIGH, + FL("dropping received beacon in deffered state")); + goto fail; + } + + dropreason = lim_is_pkt_candidate_for_drop(mac_ctx, bd_ptr, + subtype); + if (eMGMT_DROP_NO_DROP != dropreason) { + sys_log(mac_ctx, LOG1, + FL("Mgmt Frame %d being dropped, reason: %d\n"), + subtype, dropreason); + MTRACE(mac_trace(mac_ctx, + TRACE_CODE_RX_MGMT_DROP, NO_SESSION, + dropreason);) + goto fail; + } + + if (subtype == SIR_MAC_MGMT_DEAUTH) { + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); + sys_log(mac_ctx, 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(mac_hdr->da), + MAC_ADDR_ARRAY(mac_hdr->sa), + MAC_ADDR_ARRAY(mac_hdr->bssId), + mac_ctx->sys.gSysFrameCount[type][subtype]); + } + if (subtype == SIR_MAC_MGMT_DISASSOC) { + tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd_ptr); + sys_log(mac_ctx, 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(mac_hdr->da), + MAC_ADDR_ARRAY(mac_hdr->sa), + MAC_ADDR_ARRAY(mac_hdr->bssId), + mac_ctx->sys.gSysFrameCount[type][subtype]); + } + + /* Post the message to PE Queue */ + ret = (tSirRetStatus) lim_post_msg_api(mac_ctx, msg); + if (ret != eSIR_SUCCESS) { + sys_log(mac_ctx, LOGE, + FL("posting to LIM2 failed, ret %d\n"), ret); + goto fail; + } + mac_ctx->sys.gSysBbtPostedToLim++; + } else if (type == SIR_MAC_DATA_FRAME) { +#ifdef FEATURE_WLAN_ESE + PELOGW(sys_log(mac_ctx, LOGW, FL("IAPP Frame...\n"));); + /* Post the message to PE Queue */ + ret = (tSirRetStatus) lim_post_msg_api(mac_ctx, msg); + if (ret != eSIR_SUCCESS) { + sys_log(mac_ctx, LOGE, + FL("posting to LIM2 failed, ret %d\n"), ret); + goto fail; + } + mac_ctx->sys.gSysBbtPostedToLim++; +#endif + } else { + sys_log(mac_ctx, LOG3, + "BBT received Invalid type %d subtype %d " + "LIM state %X. BD dump is:\n", type, subtype, + lim_get_sme_state(mac_ctx)); + goto fail; + } + return eSIR_SUCCESS; +fail: + mac_ctx->sys.gSysBbtDropped++; + return eSIR_FAILURE; +} + +void sys_log(tpAniSirGlobal pMac, uint32_t 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. */ + + log_debug(pMac, SIR_SYS_MODULE_ID, loglevel, pString, marker); + + va_end(marker); /* Reset variable arguments. */ + } +} diff --git a/core/mac/src/sys/legacy/src/utils/inc/dot11fdefs.h b/core/mac/src/sys/legacy/src/utils/inc/dot11fdefs.h new file mode 100644 index 000000000000..8cc4e9789910 --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/inc/dot11fdefs.h @@ -0,0 +1,99 @@ +/* + * 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. + */ + +#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 "parser_api.h" + +/* This controls how the "dot11f" code copies memory */ +#define DOT11F_MEMCPY(ctx, dst, src, len) \ + cdf_mem_copy((uint8_t *)(dst), (uint8_t *)(src), (len)) + +/* This controls how the "dot11f" code compares memory */ +#define DOT11F_MEMCMP(ctx, lhs, rhs, len) \ + (!cdf_mem_compare((uint8_t *)(lhs), (uint8_t *)(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) \ + dot11f_log((ctx), (sev), (fmt)); + +#define FRAMES_LOG1(ctx, sev, fmt, p1) \ + dot11f_log((ctx), (sev), (fmt), (p1)); + +#define FRAMES_LOG2(ctx, sev, fmt, p1, p2) \ + dot11f_log((ctx), (sev), (fmt), (p1), (p2)); + +#define FRAMES_LOG3(ctx, sev, fmt, p1, p2, p3) \ + dot11f_log((ctx), (sev), (fmt), (p1), (p2), (p3)); + +#define FRAMES_DUMP(ctx, sev, p, n) \ + sir_dump_buf((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/core/mac/src/sys/legacy/src/utils/inc/utils_parser.h b/core/mac/src/sys/legacy/src/utils/inc/utils_parser.h new file mode 100644 index 000000000000..3b63a0df737e --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/inc/utils_parser.h @@ -0,0 +1,98 @@ +/* + * 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 utils_parser.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 "sir_api.h" +#include "dot11f.h" +#include "utils_api.h" + +void convert_ssid(tpAniSirGlobal, tSirMacSSid *, tDot11fIESSID *); +void convert_supp_rates(tpAniSirGlobal, tSirMacRateSet *, tDot11fIESuppRates *); +void convert_fh_params(tpAniSirGlobal, tSirMacFHParamSet *, + tDot11fIEFHParamSet *); +void convert_ext_supp_rates(tpAniSirGlobal, tSirMacRateSet *, + tDot11fIEExtSuppRates *); +void convert_qos_caps(tpAniSirGlobal, tSirMacQosCapabilityIE *, + tDot11fIEQOSCapsAp *); +void convert_qos_caps_station(tpAniSirGlobal, tSirMacQosCapabilityStaIE *, + tDot11fIEQOSCapsStation *); +tSirRetStatus convert_wpa(tpAniSirGlobal, tSirMacWpaInfo *, tDot11fIEWPA *); +tSirRetStatus convert_wpa_opaque(tpAniSirGlobal, tSirMacWpaInfo *, + tDot11fIEWPAOpaque *); +tSirRetStatus convert_wapi_opaque(tpAniSirGlobal, tSirMacWapiInfo *, + tDot11fIEWAPIOpaque *); +tSirRetStatus convert_rsn(tpAniSirGlobal, tSirMacRsnInfo *, tDot11fIERSN *); +tSirRetStatus convert_rsn_opaque(tpAniSirGlobal, tSirMacRsnInfo *, + tDot11fIERSNOpaque *); +void convert_power_caps(tpAniSirGlobal, tSirMacPowerCapabilityIE *, + tDot11fIEPowerCaps *); +void convert_supp_channels(tpAniSirGlobal, tSirMacSupportedChannelIE *, + tDot11fIESuppChannels *); +void convert_cf_params(tpAniSirGlobal, tSirMacCfParamSet *, tDot11fIECFParams *); +void convert_tim(tpAniSirGlobal, tSirMacTim *, tDot11fIETIM *); +void convert_country(tpAniSirGlobal, tSirCountryInformation *, + tDot11fIECountry *); +void convert_wmm_params(tpAniSirGlobal, tSirMacEdcaParamSetIE *, + tDot11fIEWMMParams *); +void convert_erp_info(tpAniSirGlobal, tSirMacErpInfo *, tDot11fIEERPInfo *); +void convert_edca_param(tpAniSirGlobal, tSirMacEdcaParamSetIE *, + tDot11fIEEDCAParamSet *); +void convert_tspec(tpAniSirGlobal, tSirMacTspecIE *, tDot11fIETSPEC *); +tSirRetStatus convert_tclas(tpAniSirGlobal, tSirTclasInfo *, tDot11fIETCLAS *); +void convert_wmmtspec(tpAniSirGlobal, tSirMacTspecIE *, tDot11fIEWMMTSPEC *); +tSirRetStatus convert_wmmtclas(tpAniSirGlobal, tSirTclasInfo *, + tDot11fIEWMMTCLAS *); +void convert_ts_delay(tpAniSirGlobal, tSirMacTsDelayIE *, tDot11fIETSDelay *); +void convert_schedule(tpAniSirGlobal, tSirMacScheduleIE *, tDot11fIESchedule *); +void convert_wmm_schedule(tpAniSirGlobal, tSirMacScheduleIE *, + tDot11fIEWMMSchedule *); +tSirRetStatus convert_wsc_opaque(tpAniSirGlobal, tSirAddie *, + tDot11fIEWscIEOpaque *); +tSirRetStatus convert_p2p_opaque(tpAniSirGlobal, tSirAddie *, + tDot11fIEP2PIEOpaque *); +#ifdef WLAN_FEATURE_WFD +tSirRetStatus convert_wfd_opaque(tpAniSirGlobal, tSirAddie *, + tDot11fIEWFDIEOpaque *); +#endif +void convert_qos_mapset_frame(tpAniSirGlobal, tSirQosMapSet *, + tDot11fIEQosMapSet *); + +#endif diff --git a/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/core/mac/src/sys/legacy/src/utils/src/dot11f.c new file mode 100644 index 000000000000..6286a019287e --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -0,0 +1,21682 @@ +/* + * 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 dot11f.c + * + * \brief Structures, functions & definitions for + * working with 802.11 Frames + * + * + * This file was automatically generated by 'framesc' + * Wed Oct 14 10:14:42 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; + uint32_t offset; + uint16_t sig; + uint8_t size; +} tFFDefn; + +typedef struct sIEDefn { + uint32_t offset; + uint32_t presenceOffset; + uint32_t countOffset; + const char *name; + uint16_t arraybound; + uint16_t minSize; + uint16_t maxSize; + uint16_t sig; + unsigned char oui[5]; + unsigned char noui; + uint8_t 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 + +#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 + +#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))\ + eturn 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, + uint16_t *pOut, + uint8_t *pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +#if defined (DOT11F_LITTLE_ENDIAN_HOST) + if (!fMsb) + DOT11F_MEMCPY(pCtx, (uint16_t *)pOut, pIn, 2); + else + *pOut = (uint16_t)(*pIn << 8) | *(pIn + 1); +#else + if (!fMsb) + *pOut = (uint16_t)(*pIn | (*(pIn + 1) << 8)); + else + DOT11F_MEMCPY(pCtx, (uint16_t *)pOut, pIn, 2); +#endif +} + +static void framesntohl(tpAniSirGlobal pCtx, + uint32_t *pOut, + uint8_t *pIn, + tFRAMES_BOOL fMsb) +{ + (void)pCtx; +#if defined (DOT11F_LITTLE_ENDIAN_HOST) + if (!fMsb) + DOT11F_MEMCPY(pCtx, (uint32_t *)pOut, pIn, 4); + else + *pOut = (uint32_t)(*pIn << 24) | + (*(pIn + 1) << 16) | + (*(pIn + 2) << 8) | + (*(pIn + 3)); +#else + if (!fMsb) + *pOut = (uint32_t)(*(pIn + 3) << 24) | + (*(pIn + 2) << 16) | + (*(pIn + 1) << 8) | + (*(pIn)); +else + *pOut = *(uint32_t *)pIn; +#endif +} + +static void framesntohq(tpAniSirGlobal pCtx, + tDOT11F_U64 *pOut, + uint8_t *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, + uint8_t *pOut, + uint16_t 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, + uint8_t *pOut, + uint32_t 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, + uint8_t *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 *find_ie_defn(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t 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 > (uint32_t)(pIe->noui + 2)) && + (!DOT11F_MEMCMP(pCtx, pBuf + 2, pIe->oui, + pIe->noui))) + return pIe; + } + + ++pIe; + } + + return NULL; +} + +static uint32_t get_container_ies_len(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + uint8_t *pnConsumed, + const tIEDefn IEs[]) +{ + const tIEDefn *pIe, *pIeFirst; + uint8_t *pBufRemaining = pBuf; + uint8_t 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) { + pIe = find_ie_defn(pCtx, pBufRemaining, nBuf + len, IEs); + if (NULL == pIe) + break; + if (pIe->eid == pIeFirst->eid) + break; + len += *(pBufRemaining + 1) + 2; + pBufRemaining += *(pBufRemaining + 1) + 2; + } + + *pnConsumed = len; + return DOT11F_PARSE_SUCCESS; + +} + + +static uint32_t unpack_core(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + const tFFDefn FFs[], + const tIEDefn IEs[], + uint8_t *pFrm, + size_t nFrm); +static uint32_t pack_core(tpAniSirGlobal pCtx, + uint8_t *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed, + const tFFDefn FFs[], + const tIEDefn IEs[]); +static uint32_t get_packed_size_core(tpAniSirGlobal pCtx, + uint8_t *pFrm, + uint32_t *pnNeeded, + const tIEDefn IEs[]); + +uint32_t dot11f_unpack_tlv_common_func(tpAniSirGlobal pCtx, uint8_t *pBuf, + uint16_t tlvlen, uint8_t *pDstPresent, + uint8_t *pDstField) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)tlvlen; /* Shutup the compiler */ + + *pDstPresent = 1; + *pDstField = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_common_func. */ + +uint32_t dot11f_unpack_tlv_common_func2(tpAniSirGlobal pCtx, uint8_t *pBuf, + uint16_t tlvlen, uint8_t *pDstPresent, + uint16_t *pDstState) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)tlvlen; /* Shutup the compiler */ + + *pDstPresent = 1; + framesntohs(pCtx, pDstState, pBuf, 1); + (void)pCtx; + return status; + +} /* End dot11f_unpack_tlv_common_func2. */ + +void dot11f_unpack_ff_common_func(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint16_t *pDstField) +{ + framesntohs(pCtx, pDstField, pBuf, 0); + (void)pCtx; +} /* End dot11f_unpack_ff_common_func. */ + +uint32_t dot11f_unpack_ie_common_func(tpAniSirGlobal pCtx, uint8_t *pBuf, + uint8_t ielen, uint8_t *pDstPresent , + uint8_t *pDstField) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)ielen; + (void)pBuf; + if ((*pDstPresent)) + status = DOT11F_DUPLICATE_IE; + *pDstPresent = 1; + *pDstField = *pBuf; + (void)pCtx; + + return status; +} /* End dot11f_unpack_ie_common_func */ + +typedef struct sTLVDefn { + uint32_t offset; + uint32_t presenceOffset; + const char *name; + uint16_t sig; + uint32_t id; + uint32_t pec; + uint32_t minSize; + uint32_t maxSize; + uint8_t fMandatory; + uint8_t sType; + uint8_t sLen; + uint8_t fMsb; +} tTLVDefn; + +static const tTLVDefn *find_tlv_defn(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + const tTLVDefn TLVs[]) +{ + const tTLVDefn *pTlv; + uint32_t pec; + uint16_t 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 uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + const tTLVDefn TLVs[], + uint8_t *pFrm, + size_t nFrm); +static uint32_t pack_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed, + const tTLVDefn TLVs[], + uint32_t *pidx); +static uint32_t get_packed_size_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pFrm, + uint32_t *pnNeeded, + const tTLVDefn TLVs[]); + +#define SigFfAID (0x0001) + +void dot11f_unpack_ff_action(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfAction *pDst) +{ + pDst->action = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_action. */ + +#define SigFfAction (0x0002) + +#define SigFfAuthAlgo (0x0003) + +#define SigFfAuthSeqNo (0x0004) + +#define SigFfBeaconInterval (0x0005) + +void dot11f_unpack_ff_capabilities(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfCapabilities *pDst) +{ + uint16_t tmp0__; + framesntohs(pCtx, &tmp0__, pBuf, 0); + pDst->ess = tmp0__ >> 0 & 0x1; + pDst->ibss = tmp0__ >> 1 & 0x1; + pDst->cfPollable = tmp0__ >> 2 & 0x1; + pDst->cfPollReq = tmp0__ >> 3 & 0x1; + pDst->privacy = tmp0__ >> 4 & 0x1; + pDst->shortPreamble = tmp0__ >> 5 & 0x1; + pDst->pbcc = tmp0__ >> 6 & 0x1; + pDst->channelAgility = tmp0__ >> 7 & 0x1; + pDst->spectrumMgt = tmp0__ >> 8 & 0x1; + pDst->qos = tmp0__ >> 9 & 0x1; + pDst->shortSlotTime = tmp0__ >> 10 & 0x1; + pDst->apsd = tmp0__ >> 11 & 0x1; + pDst->rrm = tmp0__ >> 12 & 0x1; + pDst->dsssOfdm = tmp0__ >> 13 & 0x1; + pDst->delayedBA = tmp0__ >> 14 & 0x1; + pDst->immediateBA = tmp0__ >> 15 & 0x1; + (void)pCtx; +} /* End dot11f_unpack_ff_capabilities. */ + +#define SigFfCapabilities (0x0006) + +void dot11f_unpack_ff_category(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfCategory *pDst) +{ + pDst->category = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_category. */ + +#define SigFfCategory (0x0007) + +void dot11f_unpack_ff_current_ap_address(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfCurrentAPAddress *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->mac, pBuf, 6); + (void)pCtx; +} /* End dot11f_unpack_ff_current_ap_address. */ + +#define SigFfCurrentAPAddress (0x0008) + +void dot11f_unpack_ff_dialog_token(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfDialogToken *pDst) +{ + pDst->token = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_dialog_token. */ + +#define SigFfDialogToken (0x0009) + +void dot11f_unpack_ff_link_margin(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfLinkMargin *pDst) +{ + pDst->linkMargin = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_link_margin. */ + +#define SigFfLinkMargin (0x000a) + +#define SigFfListenInterval (0x000b) + +void dot11f_unpack_ff_max_tx_power(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfMaxTxPower *pDst) +{ + pDst->maxTxPower = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_max_tx_power. */ + +#define SigFfMaxTxPower (0x000c) + +void dot11f_unpack_ff_num_of_repetitions(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfNumOfRepetitions *pDst) +{ + framesntohs(pCtx, &pDst->repetitions, pBuf, 0); + (void)pCtx; +} /* End dot11f_unpack_ff_num_of_repetitions. */ + +#define SigFfNumOfRepetitions (0x000d) + +void dot11f_unpack_ff_operating_mode(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfOperatingMode *pDst) +{ + uint8_t tmp1__; + tmp1__ = *pBuf; + pDst->chanWidth = tmp1__ >> 0 & 0x3; + pDst->reserved = tmp1__ >> 2 & 0x3; + pDst->rxNSS = tmp1__ >> 4 & 0x7; + pDst->rxNSSType = tmp1__ >> 7 & 0x1; + (void)pCtx; +} /* End dot11f_unpack_ff_operating_mode. */ + +#define SigFfOperatingMode (0x000e) + +void dot11f_unpack_ff_rcpi(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfRCPI *pDst) +{ + pDst->rcpi = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_rcpi. */ + +#define SigFfRCPI (0x000f) + +void dot11f_unpack_ff_rsni(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfRSNI *pDst) +{ + pDst->rsni = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_rsni. */ + +#define SigFfRSNI (0x0010) + +#define SigFfReason (0x0011) + +void dot11f_unpack_ff_rx_antenna_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfRxAntennaId *pDst) +{ + pDst->antennaId = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_rx_antenna_id. */ + +#define SigFfRxAntennaId (0x0012) + +void dot11f_unpack_ff_sm_power_mode_set(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfSMPowerModeSet *pDst) +{ + uint8_t tmp2__; + tmp2__ = *pBuf; + pDst->PowerSave_En = tmp2__ >> 0 & 0x1; + pDst->Mode = tmp2__ >> 1 & 0x1; + pDst->reserved = tmp2__ >> 2 & 0x3f; + (void)pCtx; +} /* End dot11f_unpack_ff_sm_power_mode_set. */ + +#define SigFfSMPowerModeSet (0x0013) + +#define SigFfStatus (0x0014) + +void dot11f_unpack_ff_status_code(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfStatusCode *pDst) +{ + pDst->statusCode = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_status_code. */ + +#define SigFfStatusCode (0x0015) + +void dot11f_unpack_ff_tpc_ele_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTPCEleID *pDst) +{ + pDst->TPCId = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_tpc_ele_id. */ + +#define SigFfTPCEleID (0x0016) + +void dot11f_unpack_ff_tpc_ele_len(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTPCEleLen *pDst) +{ + pDst->TPCLen = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_tpc_ele_len. */ + +#define SigFfTPCEleLen (0x0017) + +void dot11f_unpack_ff_ts_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTSInfo *pDst) +{ + uint32_t tmp3__; + framesntohl(pCtx, &tmp3__, pBuf, 0); + pDst->traffic_type = tmp3__ >> 0 & 0x1; + pDst->tsid = tmp3__ >> 1 & 0xf; + pDst->direction = tmp3__ >> 5 & 0x3; + pDst->access_policy = tmp3__ >> 7 & 0x3; + pDst->aggregation = tmp3__ >> 9 & 0x1; + pDst->psb = tmp3__ >> 10 & 0x1; + pDst->user_priority = tmp3__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp3__ >> 14 & 0x3; + pDst->schedule = tmp3__ >> 16 & 0x1; + pDst->unused = tmp3__ >> 17 & 0x7fff; + (void)pCtx; +} /* End dot11f_unpack_ff_ts_info. */ + +#define SigFfTSInfo (0x0018) + +void dot11f_unpack_ff_time_stamp(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTimeStamp *pDst) +{ + framesntohq(pCtx, &pDst->timestamp, pBuf, 0); + (void)pCtx; +} /* End dot11f_unpack_ff_time_stamp. */ + +#define SigFfTimeStamp (0x0019) + +void dot11f_unpack_ff_transaction_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTransactionId *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->transId, pBuf, 2); + (void)pCtx; +} /* End dot11f_unpack_ff_transaction_id. */ + +#define SigFfTransactionId (0x001a) + +void dot11f_unpack_ff_tx_antenna_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTxAntennaId *pDst) +{ + pDst->antennaId = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_tx_antenna_id. */ + +#define SigFfTxAntennaId (0x001b) + +void dot11f_unpack_ff_tx_power(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfTxPower *pDst) +{ + pDst->txPower = *pBuf; + (void)pCtx; +} /* End dot11f_unpack_ff_tx_power. */ + +#define SigFfTxPower (0x001c) + +void dot11f_unpack_ff_vht_membership_status_array(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfVhtMembershipStatusArray *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->membershipStatusArray, pBuf, 8); + (void)pCtx; +} /* End dot11f_unpack_ff_vht_membership_status_array. */ + +#define SigFfVhtMembershipStatusArray (0x001d) + +void dot11f_unpack_ff_vht_user_position_array(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfVhtUserPositionArray *pDst) +{ + DOT11F_MEMCPY(pCtx, pDst->userPositionArray, pBuf, 16); + (void)pCtx; +} /* End dot11f_unpack_ff_vht_user_position_array. */ + +#define SigFfVhtUserPositionArray (0x001e) + +uint32_t dot11f_unpack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVAuthorizedMACs *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->mac, pBuf, 6); + pBuf += 6; + tlvlen -= (uint8_t)6; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_authorized_ma_cs. */ + +#define SigTlvAuthorizedMACs (0x0001) + + +#define SigTlvRequestToEnroll (0x0002) + + +uint32_t dot11f_unpack_tlv_version2(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVVersion2 *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp4__; + pDst->present = 1; + tmp4__ = *pBuf; + pBuf += 1; + tlvlen -= 1; + pDst->minor = tmp4__ >> 0 & 0xf; + pDst->major = tmp4__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_version2. */ + +#define SigTlvVersion2 (0x0003) + + +#define SigTlvAPSetupLocked (0x0004) + + +#define SigTlvAssociationState (0x0005) + + +#define SigTlvConfigMethods (0x0006) + + +#define SigTlvConfigurationError (0x0007) + + +uint32_t dot11f_unpack_tlv_device_name(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVDeviceName *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (uint8_t)(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 dot11f_unpack_tlv_device_name. */ + +#define SigTlvDeviceName (0x0008) + + +#define SigTlvDevicePasswordID (0x0009) + + +uint32_t dot11f_unpack_tlv_extended_listen_timing(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVExtendedListenTiming *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + framesntohs(pCtx, &pDst->availibilityPeriod, pBuf, 0); + pBuf += 2; + tlvlen -= (uint8_t)2; + framesntohs(pCtx, &pDst->availibilityInterval, pBuf, 0); + pBuf += 2; + tlvlen -= (uint8_t)2; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_extended_listen_timing. */ + +#define SigTlvExtendedListenTiming (0x000a) + + +uint32_t dot11f_unpack_tlv_listen_channel(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVListenChannel *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryString, pBuf, 3); + pBuf += 3; + tlvlen -= (uint8_t)3; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + pDst->channel = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_listen_channel. */ + +#define SigTlvListenChannel (0x000b) + + +uint32_t dot11f_unpack_tlv_manufacturer(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVManufacturer *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_name = (uint8_t)(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 dot11f_unpack_tlv_manufacturer. */ + +#define SigTlvManufacturer (0x000c) + + +#define SigTlvMinorReasonCode (0x000d) + + +uint32_t dot11f_unpack_tlv_model_name(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVModelName *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (uint8_t)(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 dot11f_unpack_tlv_model_name. */ + +#define SigTlvModelName (0x000e) + + +uint32_t dot11f_unpack_tlv_model_number(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVModelNumber *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (uint8_t)(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 dot11f_unpack_tlv_model_number. */ + +#define SigTlvModelNumber (0x000f) + + +uint32_t dot11f_unpack_tlv_notice_of_absence(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVNoticeOfAbsence *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->index = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + pDst->CTSWindowOppPS = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + pDst->num_NoADesc = (uint8_t)(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 dot11f_unpack_tlv_notice_of_absence. */ + +#define SigTlvNoticeOfAbsence (0x0010) + + +uint32_t dot11f_unpack_tlv_operating_channel(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVOperatingChannel *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->countryString, pBuf, 3); + pBuf += 3; + tlvlen -= (uint8_t)3; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + pDst->channel = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_operating_channel. */ + +#define SigTlvOperatingChannel (0x0011) + + +uint32_t dot11f_unpack_tlv_p2_p_capability(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVP2PCapability *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->deviceCapability = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + pDst->groupCapability = *pBuf; + pBuf += 1; + tlvlen -= (uint8_t)1; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_p2_p_capability. */ + +#define SigTlvP2PCapability (0x0012) + + +uint32_t dot11f_unpack_tlv_p2_p_device_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVP2PDeviceId *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (uint8_t)6; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_p2_p_device_id. */ + +#define SigTlvP2PDeviceId (0x0013) + + +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}, +}; + +uint32_t dot11f_unpack_tlv_p2_p_device_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVP2PDeviceInfo *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (uint8_t)6; + framesntohs(pCtx, &pDst->configMethod, pBuf, 0); + pBuf += 2; + tlvlen -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->primaryDeviceType, pBuf, 8); + pBuf += 8; + tlvlen -= (uint8_t)8; + (void)pCtx; + status |= unpack_tlv_core(pCtx, + pBuf, + tlvlen, + TLVS_P2PDeviceInfo, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_tlv_p2_p_device_info. */ + +#define SigTlvP2PDeviceInfo (0x0014) + + +uint32_t dot11f_unpack_tlv_p2_p_group_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVP2PGroupInfo *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_P2PClientInfoDesc = (uint8_t)(tlvlen); + DOT11F_MEMCPY(pCtx, pDst->P2PClientInfoDesc, pBuf, (tlvlen)); + pBuf += (tlvlen); + tlvlen -= (tlvlen); + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_p2_p_group_info. */ + +#define SigTlvP2PGroupInfo (0x0015) + + +#define SigTlvP2PStatus (0x0016) + + +uint32_t dot11f_unpack_tlv_primary_device_type(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVPrimaryDeviceType *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)tlvlen; /* Shutup the compiler */ + pDst->present = 1; + framesntohs(pCtx, &pDst->primary_category, pBuf, 1); + pBuf += 2; + tlvlen -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->oui, pBuf, 4); + pBuf += 4; + tlvlen -= (uint8_t)4; + framesntohs(pCtx, &pDst->sub_category, pBuf, 1); + pBuf += 2; + tlvlen -= (uint8_t)2; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_primary_device_type. */ + +#define SigTlvPrimaryDeviceType (0x0017) + + +#define SigTlvRFBands (0x0018) + + +uint32_t dot11f_unpack_tlv_request_device_type(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVRequestDeviceType *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + framesntohs(pCtx, &pDst->primary_category, pBuf, 1); + pBuf += 2; + tlvlen -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->oui, pBuf, 4); + pBuf += 4; + tlvlen -= (uint8_t)4; + framesntohs(pCtx, &pDst->sub_category, pBuf, 1); + pBuf += 2; + tlvlen -= (uint8_t)2; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_request_device_type. */ + +#define SigTlvRequestDeviceType (0x0019) + + +#define SigTlvRequestType (0x001a) + + +#define SigTlvResponseType (0x001b) + + +#define SigTlvSelectedRegistrar (0x001c) + + +#define SigTlvSelectedRegistrarConfigMethods (0x001d) + + +uint32_t dot11f_unpack_tlv_serial_number(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVSerialNumber *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + pDst->num_text = (uint8_t)(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 dot11f_unpack_tlv_serial_number. */ + +#define SigTlvSerialNumber (0x001e) + + +uint32_t dot11f_unpack_tlv_uuid_e(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVUUID_E *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->uuid, pBuf, 16); + pBuf += 16; + tlvlen -= (uint8_t)16; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_uuid_e. */ + +#define SigTlvUUID_E (0x001f) + + +uint32_t dot11f_unpack_tlv_uuid_r(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVUUID_R *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->uuid, pBuf, 16); + pBuf += 16; + tlvlen -= (uint8_t)16; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_uuid_r. */ + +#define SigTlvUUID_R (0x0020) + + +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}, +}; + +uint32_t dot11f_unpack_tlv_vendor_extension(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVVendorExtension *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->vendorId, pBuf, 3); + pBuf += 3; + tlvlen -= (uint8_t)3; + (void)pCtx; + status |= unpack_tlv_core(pCtx, + pBuf, + tlvlen, + TLVS_VendorExtension, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_tlv_vendor_extension. */ + +#define SigTlvVendorExtension (0x0021) + + +uint32_t dot11f_unpack_tlv_version(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVVersion *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp5__; + pDst->present = 1; + tmp5__ = *pBuf; + pBuf += 1; + tlvlen -= 1; + pDst->minor = tmp5__ >> 0 & 0xf; + pDst->major = tmp5__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_version. */ + +#define SigTlvVersion (0x0022) + + +#define SigTlvWPSState (0x0023) + + +uint32_t dot11f_unpack_tlv_p2_p_interface(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint16_t tlvlen, + tDot11fTLVP2PInterface *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->P2PDeviceAddress, pBuf, 6); + pBuf += 6; + tlvlen -= (uint8_t)6; + (void)pCtx; + return status; +} /* End dot11f_unpack_tlv_p2_p_interface. */ + +#define SigTlvP2PInterface (0x0024) + + +#define SigTlvP2PManageability (0x0025) + + +uint32_t dot11f_unpack_ie_condensed_country_str(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIECondensedCountryStr *pDst) +{ + uint32_t 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 dot11f_unpack_ie_condensed_country_str. */ + +#define SigIeCondensedCountryStr (0x0001) + + +uint32_t dot11f_unpack_ie_gtk(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEGTK *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp6__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp6__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->keyId = tmp6__ >> 0 & 0x3; + pDst->reserved = tmp6__ >> 2 & 0x3feb; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->RSC, pBuf, 8); + pBuf += 8; + ielen -= (uint8_t)8; + pDst->num_key = (uint8_t)(ielen); + if (ielen > 32) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_gtk. */ + +#define SigIeGTK (0x0002) + + +uint32_t dot11f_unpack_ie_igtk(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEIGTK *pDst) +{ + uint32_t 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 -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->IPN, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, 24); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_igtk. */ + +#define SigIeIGTK (0x0003) + + +uint32_t dot11f_unpack_ie_r0_kh_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIER0KH_ID *pDst) +{ + uint32_t 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 = (uint8_t)(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 dot11f_unpack_ie_r0_kh_id. */ + +#define SigIeR0KH_ID (0x0004) + + +uint32_t dot11f_unpack_ie_r1_kh_id(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIER1KH_ID *pDst) +{ + uint32_t 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 dot11f_unpack_ie_r1_kh_id. */ + +#define SigIeR1KH_ID (0x0005) + + +uint32_t dot11f_unpack_ie_tsf_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETSFInfo *pDst) +{ + uint32_t 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 -= (uint8_t)2; + framesntohs(pCtx, &pDst->BeaconIntvl, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_tsf_info. */ + +#define SigIeTSFInfo (0x0006) + + +uint32_t dot11f_unpack_ie_ap_channel_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEAPChannelReport *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->num_channelList = (uint8_t)(ielen); + if (ielen > 50) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->channelList, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ap_channel_report. */ + +#define SigIeAPChannelReport (0x0007) + + +uint32_t dot11f_unpack_ie_bcn_reporting_detail(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEBcnReportingDetail *pDst) +{ + uint32_t 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 dot11f_unpack_ie_bcn_reporting_detail. */ + +#define SigIeBcnReportingDetail (0x0008) + + +uint32_t dot11f_unpack_ie_beacon_report_frm_body(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEBeaconReportFrmBody *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_reportedFields = (uint8_t)(ielen); + if (ielen > 224) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->reportedFields, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_beacon_report_frm_body. */ + +#define SigIeBeaconReportFrmBody (0x0009) + + +uint32_t dot11f_unpack_ie_beacon_reporting(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEBeaconReporting *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->threshold = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_beacon_reporting. */ + +#define SigIeBeaconReporting (0x000a) + + +uint32_t dot11f_unpack_ie_measurement_pilot(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEMeasurementPilot *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->num_vendorSpecific = (uint8_t)(ielen); + DOT11F_MEMCPY(pCtx, pDst->vendorSpecific, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_measurement_pilot. */ + +#define SigIeMeasurementPilot (0x000b) + + +uint32_t dot11f_unpack_ie_multi_bssid(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEMultiBssid *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->num_vendorSpecific = (uint8_t)(ielen); + DOT11F_MEMCPY(pCtx, pDst->vendorSpecific, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_multi_bssid. */ + +#define SigIeMultiBssid (0x000c) + + +uint32_t dot11f_unpack_ie_ric_data(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERICData *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->resourceDescCount = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->statusCode, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ric_data. */ + +#define SigIeRICData (0x000d) + + +uint32_t dot11f_unpack_ie_ric_descriptor(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERICDescriptor *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->num_variableData = (uint8_t)(ielen); + DOT11F_MEMCPY(pCtx, pDst->variableData, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ric_descriptor. */ + +#define SigIeRICDescriptor (0x000e) + + +uint32_t dot11f_unpack_ie_rrm_enabled_cap(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERRMEnabledCap *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp7__; + uint8_t tmp8__; + uint8_t tmp9__; + uint8_t tmp10__; + uint8_t tmp11__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp7__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->LinkMeasurement = tmp7__ >> 0 & 0x1; + pDst->NeighborRpt = tmp7__ >> 1 & 0x1; + pDst->parallel = tmp7__ >> 2 & 0x1; + pDst->repeated = tmp7__ >> 3 & 0x1; + pDst->BeaconPassive = tmp7__ >> 4 & 0x1; + pDst->BeaconActive = tmp7__ >> 5 & 0x1; + pDst->BeaconTable = tmp7__ >> 6 & 0x1; + pDst->BeaconRepCond = tmp7__ >> 7 & 0x1; + tmp8__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->FrameMeasurement = tmp8__ >> 0 & 0x1; + pDst->ChannelLoad = tmp8__ >> 1 & 0x1; + pDst->NoiseHistogram = tmp8__ >> 2 & 0x1; + pDst->statistics = tmp8__ >> 3 & 0x1; + pDst->LCIMeasurement = tmp8__ >> 4 & 0x1; + pDst->LCIAzimuth = tmp8__ >> 5 & 0x1; + pDst->TCMCapability = tmp8__ >> 6 & 0x1; + pDst->triggeredTCM = tmp8__ >> 7 & 0x1; + tmp9__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->APChanReport = tmp9__ >> 0 & 0x1; + pDst->RRMMIBEnabled = tmp9__ >> 1 & 0x1; + pDst->operatingChanMax = tmp9__ >> 2 & 0x7; + pDst->nonOperatinChanMax = tmp9__ >> 5 & 0x7; + tmp10__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->MeasurementPilot = tmp10__ >> 0 & 0x7; + pDst->MeasurementPilotEnabled = tmp10__ >> 3 & 0x1; + pDst->NeighborTSFOffset = tmp10__ >> 4 & 0x1; + pDst->RCPIMeasurement = tmp10__ >> 5 & 0x1; + pDst->RSNIMeasurement = tmp10__ >> 6 & 0x1; + pDst->BssAvgAccessDelay = tmp10__ >> 7 & 0x1; + tmp11__ = *pBuf; + pDst->BSSAvailAdmission = tmp11__ >> 0 & 0x1; + pDst->AntennaInformation = tmp11__ >> 1 & 0x1; + pDst->fine_time_meas_rpt = tmp11__ >> 2 & 0x1; + pDst->lci_capability = tmp11__ >> 3 & 0x1; + pDst->reserved = tmp11__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_rrm_enabled_cap. */ + +#define SigIeRRMEnabledCap (0x000f) + + +uint32_t dot11f_unpack_ie_requested_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERequestedInfo *pDst) +{ + uint32_t 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 = (uint8_t)(ielen); + DOT11F_MEMCPY(pCtx, pDst->requested_eids, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_requested_info. */ + +#define SigIeRequestedInfo (0x0010) + + +uint32_t dot11f_unpack_ie_ssid(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIESSID *pDst) +{ + uint32_t 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 = (uint8_t)(ielen); + if (ielen > 32) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->ssid, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ssid. */ + +#define SigIeSSID (0x0011) + + +uint32_t dot11f_unpack_ie_schedule(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIESchedule *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp12__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp12__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->aggregation = tmp12__ >> 0 & 0x1; + pDst->tsid = tmp12__ >> 1 & 0xf; + pDst->direction = tmp12__ >> 5 & 0x3; + pDst->reserved = tmp12__ >> 7 & 0x1ff; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->service_interval, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->max_service_dur, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->spec_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_schedule. */ + +#define SigIeSchedule (0x0012) + + +uint32_t dot11f_unpack_ie_tclas(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETCLAS *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->classifier_type = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->classifier_mask = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + switch (pDst->classifier_type) { + case 0: + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.source, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.dest, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + framesntohs(pCtx, &pDst->info.EthParams.type, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + case 1: + pDst->info.IpParams.version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + switch (pDst->info.IpParams.version) { + case 4: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.source, pBuf, 4); + pBuf += 4; + ielen -= (uint8_t)4; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.dest, pBuf, 4); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->info.IpParams.params.IpV4Params.DSCP = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->info.IpParams.params.IpV4Params.proto = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->info.IpParams.params.IpV4Params.reserved = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + break; + case 6: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.source, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.dest, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.flow_label, pBuf, 3); + pBuf += 3; + ielen -= (uint8_t)3; + break; + } + break; + case 2: + framesntohs(pCtx, &pDst->info.Params8021dq.tag_type, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + } + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_tclas. */ + +#define SigIeTCLAS (0x0013) + + +#define SigIeTCLASSPROC (0x0014) + + +uint32_t dot11f_unpack_ie_ts_delay(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETSDelay *pDst) +{ + uint32_t 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 dot11f_unpack_ie_ts_delay. */ + +#define SigIeTSDelay (0x0015) + + +uint32_t dot11f_unpack_ie_tspec(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETSPEC *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp13__; + uint8_t tmp14__; + uint16_t tmp15__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp13__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->traffic_type = tmp13__ >> 0 & 0x1; + pDst->tsid = tmp13__ >> 1 & 0xf; + pDst->direction = tmp13__ >> 5 & 0x3; + pDst->access_policy = tmp13__ >> 7 & 0x3; + pDst->aggregation = tmp13__ >> 9 & 0x1; + pDst->psb = tmp13__ >> 10 & 0x1; + pDst->user_priority = tmp13__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp13__ >> 14 & 0x3; + tmp14__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->schedule = tmp14__ >> 0 & 0x1; + pDst->unused = tmp14__ >> 1 & 0x7f; + framesntohs(pCtx, &tmp15__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->size = tmp15__ >> 0 & 0x7fff; + pDst->fixed = tmp15__ >> 15 & 0x1; + framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohl(pCtx, &pDst->min_service_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->max_service_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->inactivity_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->suspension_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->min_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->mean_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->peak_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->burst_size, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->delay_bound, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->min_phy_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->surplus_bw_allowance, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->medium_time, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_tspec. */ + +#define SigIeTSPEC (0x0016) + + +uint32_t dot11f_unpack_ie_vht_caps(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEVHTCaps *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t tmp16__; + uint16_t tmp17__; + uint16_t tmp18__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohl(pCtx, &tmp16__, pBuf, 0); + pBuf += 4; + ielen -= 4; + pDst->maxMPDULen = tmp16__ >> 0 & 0x3; + pDst->supportedChannelWidthSet = tmp16__ >> 2 & 0x3; + pDst->ldpcCodingCap = tmp16__ >> 4 & 0x1; + pDst->shortGI80MHz = tmp16__ >> 5 & 0x1; + pDst->shortGI160and80plus80MHz = tmp16__ >> 6 & 0x1; + pDst->txSTBC = tmp16__ >> 7 & 0x1; + pDst->rxSTBC = tmp16__ >> 8 & 0x7; + pDst->suBeamFormerCap = tmp16__ >> 11 & 0x1; + pDst->suBeamformeeCap = tmp16__ >> 12 & 0x1; + pDst->csnofBeamformerAntSup = tmp16__ >> 13 & 0x7; + pDst->numSoundingDim = tmp16__ >> 16 & 0x7; + pDst->muBeamformerCap = tmp16__ >> 19 & 0x1; + pDst->muBeamformeeCap = tmp16__ >> 20 & 0x1; + pDst->vhtTXOPPS = tmp16__ >> 21 & 0x1; + pDst->htcVHTCap = tmp16__ >> 22 & 0x1; + pDst->maxAMPDULenExp = tmp16__ >> 23 & 0x7; + pDst->vhtLinkAdaptCap = tmp16__ >> 26 & 0x3; + pDst->rxAntPattern = tmp16__ >> 28 & 0x1; + pDst->txAntPattern = tmp16__ >> 29 & 0x1; + pDst->reserved1 = tmp16__ >> 30 & 0x3; + framesntohs(pCtx, &pDst->rxMCSMap, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &tmp17__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->rxHighSupDataRate = tmp17__ >> 0 & 0x1fff; + pDst->reserved2 = tmp17__ >> 13 & 0x7; + framesntohs(pCtx, &pDst->txMCSMap, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &tmp18__, pBuf, 0); + pDst->txSupDataRate = tmp18__ >> 0 & 0x1fff; + pDst->reserved3 = tmp18__ >> 13 & 0x7; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_vht_caps. */ + +#define SigIeVHTCaps (0x0017) + + +uint32_t dot11f_unpack_ie_vht_operation(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEVHTOperation *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->chanCenterFreqSeg1 = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->chanCenterFreqSeg2 = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->basicMCSSet, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_vht_operation. */ + +#define SigIeVHTOperation (0x0018) + + +uint32_t dot11f_unpack_ie_wmm_schedule(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMSchedule *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp19__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + framesntohs(pCtx, &tmp19__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->aggregation = tmp19__ >> 0 & 0x1; + pDst->tsid = tmp19__ >> 1 & 0xf; + pDst->direction = tmp19__ >> 5 & 0x3; + pDst->reserved = tmp19__ >> 7 & 0x1ff; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->service_interval, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->max_service_dur, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->spec_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmm_schedule. */ + +#define SigIeWMMSchedule (0x0019) + + +uint32_t dot11f_unpack_ie_wmmtclas(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMTCLAS *pDst) +{ + uint32_t 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 -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + pDst->user_priority = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->classifier_type = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->classifier_mask = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + switch (pDst->classifier_type) { + case 0: + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.source, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + DOT11F_MEMCPY(pCtx, pDst->info.EthParams.dest, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + framesntohs(pCtx, &pDst->info.EthParams.type, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + case 1: + pDst->info.IpParams.version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + switch (pDst->info.IpParams.version) { + case 4: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.source, pBuf, 4); + pBuf += 4; + ielen -= (uint8_t)4; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV4Params.dest, pBuf, 4); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV4Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->info.IpParams.params.IpV4Params.DSCP = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->info.IpParams.params.IpV4Params.proto = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->info.IpParams.params.IpV4Params.reserved = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + break; + case 6: + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.source, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.dest, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.src_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->info.IpParams.params.IpV6Params.dest_port, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + DOT11F_MEMCPY(pCtx, pDst->info.IpParams.params.IpV6Params.flow_label, pBuf, 3); + pBuf += 3; + ielen -= (uint8_t)3; + break; + } + break; + case 2: + framesntohs(pCtx, &pDst->info.Params8021dq.tag_type, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + } + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmmtclas. */ + +#define SigIeWMMTCLAS (0x001a) + + +uint32_t dot11f_unpack_ie_wmmtclasproc(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMTCLASPROC *pDst) +{ + uint32_t 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 -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + pDst->processing = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmmtclasproc. */ + +#define SigIeWMMTCLASPROC (0x001b) + + +uint32_t dot11f_unpack_ie_wmmts_delay(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMTSDelay *pDst) +{ + uint32_t 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 -= (uint8_t)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 dot11f_unpack_ie_wmmts_delay. */ + +#define SigIeWMMTSDelay (0x001c) + + +uint32_t dot11f_unpack_ie_wmmtspec(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMTSPEC *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp20__; + uint8_t tmp21__; + uint16_t tmp22__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + framesntohs(pCtx, &tmp20__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->traffic_type = tmp20__ >> 0 & 0x1; + pDst->tsid = tmp20__ >> 1 & 0xf; + pDst->direction = tmp20__ >> 5 & 0x3; + pDst->access_policy = tmp20__ >> 7 & 0x3; + pDst->aggregation = tmp20__ >> 9 & 0x1; + pDst->psb = tmp20__ >> 10 & 0x1; + pDst->user_priority = tmp20__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp20__ >> 14 & 0x3; + tmp21__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->tsinfo_rsvd = tmp21__ >> 0 & 0x7f; + pDst->burst_size_defn = tmp21__ >> 7 & 0x1; + framesntohs(pCtx, &tmp22__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->size = tmp22__ >> 0 & 0x7fff; + pDst->fixed = tmp22__ >> 15 & 0x1; + framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohl(pCtx, &pDst->min_service_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->max_service_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->inactivity_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->suspension_int, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->min_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->mean_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->peak_data_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->burst_size, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->delay_bound, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohl(pCtx, &pDst->min_phy_rate, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + framesntohs(pCtx, &pDst->surplus_bw_allowance, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->medium_time, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmmtspec. */ + +#define SigIeWMMTSPEC (0x001d) + + +uint32_t dot11f_unpack_ie_wider_bw_chan_switch_ann(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWiderBWChanSwitchAnn *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->newCenterChanFreq0 = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->newCenterChanFreq1 = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wider_bw_chan_switch_ann. */ + +#define SigIeWiderBWChanSwitchAnn (0x001e) + + +uint32_t dot11f_unpack_ie_aid(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEAID *pDst) +{ + uint32_t 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 dot11f_unpack_ie_aid. */ + +#define SigIeAID (0x001f) + + +uint32_t dot11f_unpack_ie_cf_params(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIECFParams *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->cfp_period = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->cfp_maxduration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->cfp_durremaining, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_cf_params. */ + +#define SigIeCFParams (0x0020) + + +uint32_t dot11f_unpack_ie_challenge_text(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEChallengeText *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_text = (uint8_t)(ielen); + if (ielen > 253) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->text, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_challenge_text. */ + +#define SigIeChallengeText (0x0021) + + +uint32_t dot11f_unpack_ie_chan_switch_ann(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEChanSwitchAnn *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->newChannel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->switchCount = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_chan_switch_ann. */ + +#define SigIeChanSwitchAnn (0x0022) + + +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, }, +}; + +uint32_t dot11f_unpack_ie_channel_switch_wrapper(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEChannelSwitchWrapper *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_ChannelSwitchWrapper, + IES_ChannelSwitchWrapper, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_channel_switch_wrapper. */ + +#define SigIeChannelSwitchWrapper (0x0023) + + +uint32_t dot11f_unpack_ie_country(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIECountry *pDst) +{ + uint32_t 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 -= (uint8_t)3; + if (!ielen) { + pDst->num_triplets = 0U; + return 0U; + } else { + pDst->num_triplets = (uint8_t)(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 dot11f_unpack_ie_country. */ + +#define SigIeCountry (0x0024) + + +#define SigIeDSParams (0x0025) + + +uint32_t dot11f_unpack_ie_edca_param_set(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEEDCAParamSet *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp23__; + uint8_t tmp24__; + uint8_t tmp25__; + uint8_t tmp26__; + uint8_t tmp27__; + uint8_t tmp28__; + uint8_t tmp29__; + uint8_t tmp30__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->qos = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->reserved = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp23__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_aifsn = tmp23__ >> 0 & 0xf; + pDst->acbe_acm = tmp23__ >> 4 & 0x1; + pDst->acbe_aci = tmp23__ >> 5 & 0x3; + pDst->unused1 = tmp23__ >> 7 & 0x1; + tmp24__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_acwmin = tmp24__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp24__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp25__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_aifsn = tmp25__ >> 0 & 0xf; + pDst->acbk_acm = tmp25__ >> 4 & 0x1; + pDst->acbk_aci = tmp25__ >> 5 & 0x3; + pDst->unused2 = tmp25__ >> 7 & 0x1; + tmp26__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_acwmin = tmp26__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp26__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp27__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_aifsn = tmp27__ >> 0 & 0xf; + pDst->acvi_acm = tmp27__ >> 4 & 0x1; + pDst->acvi_aci = tmp27__ >> 5 & 0x3; + pDst->unused3 = tmp27__ >> 7 & 0x1; + tmp28__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_acwmin = tmp28__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp28__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp29__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_aifsn = tmp29__ >> 0 & 0xf; + pDst->acvo_acm = tmp29__ >> 4 & 0x1; + pDst->acvo_aci = tmp29__ >> 5 & 0x3; + pDst->unused4 = tmp29__ >> 7 & 0x1; + tmp30__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_acwmin = tmp30__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp30__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_edca_param_set. */ + +#define SigIeEDCAParamSet (0x0026) + + +uint32_t dot11f_unpack_ie_erp_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEERPInfo *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp31__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp31__ = *pBuf; + pDst->non_erp_present = tmp31__ >> 0 & 0x1; + pDst->use_prot = tmp31__ >> 1 & 0x1; + pDst->barker_preamble = tmp31__ >> 2 & 0x1; + pDst->unused = tmp31__ >> 3 & 0x1f; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_erp_info. */ + +#define SigIeERPInfo (0x0027) + + +uint32_t dot11f_unpack_ie_ese_cckm_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESECckmOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 20) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ese_cckm_opaque. */ + +#define SigIeESECckmOpaque (0x0028) + + +uint32_t dot11f_unpack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESERadMgmtCap *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp32__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->mgmt_state = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp32__ = *pBuf; + pDst->mbssid_mask = tmp32__ >> 0 & 0x7; + pDst->reserved = tmp32__ >> 3 & 0x1f; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ese_rad_mgmt_cap. */ + +#define SigIeESERadMgmtCap (0x0029) + + +uint32_t dot11f_unpack_ie_ese_traf_strm_met(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESETrafStrmMet *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->state = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->msmt_interval, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ese_traf_strm_met. */ + +#define SigIeESETrafStrmMet (0x002a) + + +uint32_t dot11f_unpack_ie_ese_traf_strm_rate_set(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESETrafStrmRateSet *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->num_tsrates = (uint8_t)(ielen); + if (ielen > 8) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->tsrates, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ese_traf_strm_rate_set. */ + +#define SigIeESETrafStrmRateSet (0x002b) + + +uint32_t dot11f_unpack_ie_ese_txmit_power(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESETxmitPower *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->reserved = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ese_txmit_power. */ + +#define SigIeESETxmitPower (0x002c) + + +uint32_t dot11f_unpack_ie_ese_version(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEESEVersion *pDst) +{ + uint32_t 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 dot11f_unpack_ie_ese_version. */ + +#define SigIeESEVersion (0x002d) + + +uint32_t dot11f_unpack_ie_ext_cap(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEExtCap *pDst) +{ + uint32_t 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 = (uint8_t)(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 dot11f_unpack_ie_ext_cap. */ + +#define SigIeExtCap (0x002e) + + +uint32_t dot11f_unpack_ie_ext_supp_rates(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEExtSuppRates *pDst) +{ + uint8_t i; + uint8_t rate_indx = 0; + uint32_t 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 dot11f_unpack_ie_ext_supp_rates. */ + +#define SigIeExtSuppRates (0x002f) + + +uint32_t dot11f_unpack_ie_fh_param_set(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEFHParamSet *pDst) +{ + uint32_t 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 -= (uint8_t)2; + pDst->hop_set = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->hop_pattern = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->hop_index = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_fh_param_set. */ + +#define SigIeFHParamSet (0x0030) + + +uint32_t dot11f_unpack_ie_fh_params(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEFHParams *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->nchannels = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_fh_params. */ + +#define SigIeFHParams (0x0031) + + +uint32_t dot11f_unpack_ie_fh_patt_table(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEFHPattTable *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->nsets = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->modulus = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->offset = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->num_randtable = (uint8_t)(ielen); + if (ielen > 251) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->randtable, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_fh_patt_table. */ + +#define SigIeFHPattTable (0x0032) + + +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, }, +}; + +uint32_t dot11f_unpack_ie_ft_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEFTInfo *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp33__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + framesntohs(pCtx, &tmp33__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->reserved = tmp33__ >> 0 & 0xff; + pDst->IECount = tmp33__ >> 8 & 0xff; + DOT11F_MEMCPY(pCtx, pDst->MIC, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + DOT11F_MEMCPY(pCtx, pDst->Anonce, pBuf, 32); + pBuf += 32; + ielen -= (uint8_t)32; + DOT11F_MEMCPY(pCtx, pDst->Snonce, pBuf, 32); + pBuf += 32; + ielen -= (uint8_t)32; + (void)pCtx; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_FTInfo, + IES_FTInfo, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_ft_info. */ + +#define SigIeFTInfo (0x0033) + + +uint32_t dot11f_unpack_ie_ht_caps(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEHTCaps *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp34__; + uint8_t tmp35__; + uint16_t tmp36__; + uint32_t tmp37__; + uint8_t tmp38__; + (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->advCodingCap = tmp34__ >> 0 & 0x1; + pDst->supportedChannelWidthSet = tmp34__ >> 1 & 0x1; + pDst->mimoPowerSave = tmp34__ >> 2 & 0x3; + pDst->greenField = tmp34__ >> 4 & 0x1; + pDst->shortGI20MHz = tmp34__ >> 5 & 0x1; + pDst->shortGI40MHz = tmp34__ >> 6 & 0x1; + pDst->txSTBC = tmp34__ >> 7 & 0x1; + pDst->rxSTBC = tmp34__ >> 8 & 0x3; + pDst->delayedBA = tmp34__ >> 10 & 0x1; + pDst->maximalAMSDUsize = tmp34__ >> 11 & 0x1; + pDst->dsssCckMode40MHz = tmp34__ >> 12 & 0x1; + pDst->psmp = tmp34__ >> 13 & 0x1; + pDst->stbcControlFrame = tmp34__ >> 14 & 0x1; + pDst->lsigTXOPProtection = tmp34__ >> 15 & 0x1; + tmp35__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->maxRxAMPDUFactor = tmp35__ >> 0 & 0x3; + pDst->mpduDensity = tmp35__ >> 2 & 0x7; + pDst->reserved1 = tmp35__ >> 5 & 0x7; + DOT11F_MEMCPY(pCtx, pDst->supportedMCSSet, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + framesntohs(pCtx, &tmp36__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->pco = tmp36__ >> 0 & 0x1; + pDst->transitionTime = tmp36__ >> 1 & 0x3; + pDst->reserved2 = tmp36__ >> 3 & 0x1f; + pDst->mcsFeedback = tmp36__ >> 8 & 0x3; + pDst->reserved3 = tmp36__ >> 10 & 0x3f; + framesntohl(pCtx, &tmp37__, pBuf, 0); + pBuf += 4; + ielen -= 4; + pDst->txBF = tmp37__ >> 0 & 0x1; + pDst->rxStaggeredSounding = tmp37__ >> 1 & 0x1; + pDst->txStaggeredSounding = tmp37__ >> 2 & 0x1; + pDst->rxZLF = tmp37__ >> 3 & 0x1; + pDst->txZLF = tmp37__ >> 4 & 0x1; + pDst->implicitTxBF = tmp37__ >> 5 & 0x1; + pDst->calibration = tmp37__ >> 6 & 0x3; + pDst->explicitCSITxBF = tmp37__ >> 8 & 0x1; + pDst->explicitUncompressedSteeringMatrix = tmp37__ >> 9 & 0x1; + pDst->explicitBFCSIFeedback = tmp37__ >> 10 & 0x7; + pDst->explicitUncompressedSteeringMatrixFeedback = tmp37__ >> 13 & 0x7; + pDst->explicitCompressedSteeringMatrixFeedback = tmp37__ >> 16 & 0x7; + pDst->csiNumBFAntennae = tmp37__ >> 19 & 0x3; + pDst->uncompressedSteeringMatrixBFAntennae = tmp37__ >> 21 & 0x3; + pDst->compressedSteeringMatrixBFAntennae = tmp37__ >> 23 & 0x3; + pDst->reserved4 = tmp37__ >> 25 & 0x7f; + tmp38__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->antennaSelection = tmp38__ >> 0 & 0x1; + pDst->explicitCSIFeedbackTx = tmp38__ >> 1 & 0x1; + pDst->antennaIndicesFeedbackTx = tmp38__ >> 2 & 0x1; + pDst->explicitCSIFeedback = tmp38__ >> 3 & 0x1; + pDst->antennaIndicesFeedback = tmp38__ >> 4 & 0x1; + pDst->rxAS = tmp38__ >> 5 & 0x1; + pDst->txSoundingPPDUs = tmp38__ >> 6 & 0x1; + pDst->reserved5 = tmp38__ >> 7 & 0x1; + pDst->num_rsvd = (uint8_t)(ielen); + if (ielen > 32) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->rsvd, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ht_caps. */ + +#define SigIeHTCaps (0x0034) + + +uint32_t dot11f_unpack_ie_ht_info(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEHTInfo *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp39__; + uint16_t tmp40__; + uint16_t tmp41__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->primaryChannel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp39__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->secondaryChannelOffset = tmp39__ >> 0 & 0x3; + pDst->recommendedTxWidthSet = tmp39__ >> 2 & 0x1; + pDst->rifsMode = tmp39__ >> 3 & 0x1; + pDst->controlledAccessOnly = tmp39__ >> 4 & 0x1; + pDst->serviceIntervalGranularity = tmp39__ >> 5 & 0x7; + framesntohs(pCtx, &tmp40__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->opMode = tmp40__ >> 0 & 0x3; + pDst->nonGFDevicesPresent = tmp40__ >> 2 & 0x1; + pDst->transmitBurstLimit = tmp40__ >> 3 & 0x1; + pDst->obssNonHTStaPresent = tmp40__ >> 4 & 0x1; + pDst->reserved = tmp40__ >> 5 & 0x7ff; + framesntohs(pCtx, &tmp41__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->basicSTBCMCS = tmp41__ >> 0 & 0x7f; + pDst->dualCTSProtection = tmp41__ >> 7 & 0x1; + pDst->secondaryBeacon = tmp41__ >> 8 & 0x1; + pDst->lsigTXOPProtectionFullSupport = tmp41__ >> 9 & 0x1; + pDst->pcoActive = tmp41__ >> 10 & 0x1; + pDst->pcoPhase = tmp41__ >> 11 & 0x1; + pDst->reserved2 = tmp41__ >> 12 & 0xf; + DOT11F_MEMCPY(pCtx, pDst->basicMCSSet, pBuf, 16); + pBuf += 16; + ielen -= (uint8_t)16; + pDst->num_rsvd = (uint8_t)(ielen); + if (ielen > 32) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->rsvd, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ht_info. */ + +#define SigIeHTInfo (0x0035) + + +uint32_t dot11f_unpack_ie_ibss_params(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEIBSSParams *pDst) +{ + uint32_t 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 dot11f_unpack_ie_ibss_params. */ + +#define SigIeIBSSParams (0x0036) + + +uint32_t dot11f_unpack_ie_link_identifier(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIELinkIdentifier *pDst) +{ + uint32_t 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 -= (uint8_t)6; + DOT11F_MEMCPY(pCtx, pDst->InitStaAddr, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + DOT11F_MEMCPY(pCtx, pDst->RespStaAddr, pBuf, 6); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_link_identifier. */ + +#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, }, +}; + +uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEMeasurementReport *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp42__; + uint8_t tmp43__; + uint8_t tmp44__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->token = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp42__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->late = tmp42__ >> 0 & 0x1; + pDst->incapable = tmp42__ >> 1 & 0x1; + pDst->refused = tmp42__ >> 2 & 0x1; + pDst->unused = tmp42__ >> 3 & 0x1f; + pDst->type = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + if (!ielen) { + return 0U; + } else { + switch (pDst->type) { + case 0: + pDst->report.Basic.channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohq(pCtx, &pDst->report.Basic.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->report.Basic.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp43__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->report.Basic.bss = tmp43__ >> 0 & 0x1; + pDst->report.Basic.ofdm_preamble = tmp43__ >> 1 & 0x1; + pDst->report.Basic.unid_signal = tmp43__ >> 2 & 0x1; + pDst->report.Basic.rader = tmp43__ >> 3 & 0x1; + pDst->report.Basic.unmeasured = tmp43__ >> 4 & 0x1; + pDst->report.Basic.unused = tmp43__ >> 5 & 0x7; + break; + case 1: + pDst->report.CCA.channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohq(pCtx, &pDst->report.CCA.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->report.CCA.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->report.CCA.cca_busy_fraction = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + break; + case 2: + pDst->report.RPIHistogram.channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohq(pCtx, &pDst->report.RPIHistogram.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->report.RPIHistogram.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->report.RPIHistogram.rpi0_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi1_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi2_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi3_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi4_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi5_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi6_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.RPIHistogram.rpi7_density = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + break; + case 5: + pDst->report.Beacon.regClass = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.Beacon.channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohq(pCtx, &pDst->report.Beacon.meas_start_time, pBuf, 0); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->report.Beacon.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp44__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->report.Beacon.condensed_PHY = tmp44__ >> 0 & 0x7f; + pDst->report.Beacon.reported_frame_type = tmp44__ >> 7 & 0x1; + pDst->report.Beacon.RCPI = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->report.Beacon.RSNI = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->report.Beacon.BSSID, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + pDst->report.Beacon.antenna_id = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohl(pCtx, &pDst->report.Beacon.parent_TSF, pBuf, 0); + pBuf += 4; + ielen -= (uint8_t)4; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_reportBeacon, + IES_reportBeacon, + (uint8_t *)pDst, + sizeof(*pDst)); + break; + } + } + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_measurement_report. */ + +#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, }, +}; + +uint32_t dot11f_unpack_ie_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEMeasurementRequest *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp45__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->measurement_token = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp45__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->parallel = tmp45__ >> 0 & 0x1; + pDst->enable = tmp45__ >> 1 & 0x1; + pDst->request = tmp45__ >> 2 & 0x1; + pDst->report = tmp45__ >> 3 & 0x1; + pDst->durationMandatory = tmp45__ >> 4 & 0x1; + pDst->unused = tmp45__ >> 5 & 0x7; + pDst->measurement_type = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + switch (pDst->measurement_type) { + case 0: + pDst->measurement_request.Basic.channel_no = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.Basic.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->measurement_request.Basic.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + case 1: + pDst->measurement_request.CCA.channel_no = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.CCA.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->measurement_request.CCA.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + case 2: + pDst->measurement_request.RPIHistogram.channel_no = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.RPIHistogram.meas_start_time, pBuf, 8); + pBuf += 8; + ielen -= (uint8_t)8; + framesntohs(pCtx, &pDst->measurement_request.RPIHistogram.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + break; + case 5: + pDst->measurement_request.Beacon.regClass = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->measurement_request.Beacon.channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->measurement_request.Beacon.randomization, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->measurement_request.Beacon.meas_duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->measurement_request.Beacon.meas_mode = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->measurement_request.Beacon.BSSID, pBuf, 6); + pBuf += 6; + ielen -= (uint8_t)6; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_measurement_requestBeacon, + IES_measurement_requestBeacon, + (uint8_t *)pDst, + sizeof(*pDst)); + break; + } + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_measurement_request. */ + +#define SigIeMeasurementRequest (0x0039) + + +uint32_t dot11f_unpack_ie_mobility_domain(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEMobilityDomain *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp46__; + (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 -= (uint8_t)2; + tmp46__ = *pBuf; + pDst->overDSCap = tmp46__ >> 0 & 0x1; + pDst->resourceReqCap = tmp46__ >> 1 & 0x1; + pDst->reserved = tmp46__ >> 2 & 0x3f; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_mobility_domain. */ + +#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, }, +}; + +uint32_t dot11f_unpack_ie_neighbor_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIENeighborReport *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp47__; + uint8_t tmp48__; + (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 -= (uint8_t)6; + tmp47__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->APReachability = tmp47__ >> 0 & 0x3; + pDst->Security = tmp47__ >> 2 & 0x1; + pDst->KeyScope = tmp47__ >> 3 & 0x1; + pDst->SpecMgmtCap = tmp47__ >> 4 & 0x1; + pDst->QosCap = tmp47__ >> 5 & 0x1; + pDst->apsd = tmp47__ >> 6 & 0x1; + pDst->rrm = tmp47__ >> 7 & 0x1; + tmp48__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->DelayedBA = tmp48__ >> 0 & 0x1; + pDst->ImmBA = tmp48__ >> 1 & 0x1; + pDst->MobilityDomain = tmp48__ >> 2 & 0x1; + pDst->reserved = tmp48__ >> 3 & 0x1f; + framesntohs(pCtx, &pDst->reserved1, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + pDst->regulatoryClass = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->PhyType = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + (void)pCtx; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_NeighborReport, + IES_NeighborReport, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_neighbor_report. */ + +#define SigIeNeighborReport (0x003b) + + +uint32_t dot11f_unpack_ie_obss_scan_parameters(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEOBSSScanParameters *pDst) +{ + uint32_t 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 -= (uint8_t)2; + framesntohs(pCtx, &pDst->obssScanActiveDwell, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->bssChannelWidthTriggerScanInterval, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->obssScanPassiveTotalPerChannel, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->obssScanActiveTotalPerChannel, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->bssWidthChannelTransitionDelayFactor, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->obssScanActivityThreshold, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_obss_scan_parameters. */ + +#define SigIeOBSSScanParameters (0x003c) + + +uint32_t dot11f_unpack_ie_operating_mode(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEOperatingMode *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp49__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp49__ = *pBuf; + pDst->chanWidth = tmp49__ >> 0 & 0x3; + pDst->reserved = tmp49__ >> 2 & 0x3; + pDst->rxNSS = tmp49__ >> 4 & 0x7; + pDst->rxNSSType = tmp49__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_operating_mode. */ + +#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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_assoc_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PAssocReq *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PAssocReq, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_assoc_req. */ + +#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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_assoc_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PAssocRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PAssocRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_assoc_res. */ + +#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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_beacon(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PBeacon *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PBeacon, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_beacon. */ + +#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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_beacon_probe_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PBeaconProbeRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PBeaconProbeRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_beacon_probe_res. */ + +#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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_de_auth(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PDeAuth *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PDeAuth, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_de_auth. */ + +#define SigIeP2PDeAuth (0x0042) + + +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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_dis_assoc(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PDisAssoc *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PDisAssoc, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_dis_assoc. */ + +#define SigIeP2PDisAssoc (0x0043) + + +uint32_t dot11f_unpack_ie_p2_pie_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PIEOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 249) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_p2_pie_opaque. */ + +#define SigIeP2PIEOpaque (0x0044) + + +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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_probe_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PProbeReq *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PProbeReq, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_probe_req. */ + +#define SigIeP2PProbeReq (0x0045) + + +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}, +}; + +uint32_t dot11f_unpack_ie_p2_p_probe_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEP2PProbeRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_P2PProbeRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_p2_p_probe_res. */ + +#define SigIeP2PProbeRes (0x0046) + + +uint32_t dot11f_unpack_ie_pti_control(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEPTIControl *pDst) +{ + uint32_t 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 -= (uint8_t)1; + framesntohs(pCtx, &pDst->sequence_control, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_pti_control. */ + +#define SigIePTIControl (0x0047) + + +uint32_t dot11f_unpack_ie_pu_buffer_status(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEPUBufferStatus *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp50__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp50__ = *pBuf; + pDst->ac_bk_traffic_aval = tmp50__ >> 0 & 0x1; + pDst->ac_be_traffic_aval = tmp50__ >> 1 & 0x1; + pDst->ac_vi_traffic_aval = tmp50__ >> 2 & 0x1; + pDst->ac_vo_traffic_aval = tmp50__ >> 3 & 0x1; + pDst->reserved = tmp50__ >> 4 & 0xf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_pu_buffer_status. */ + +#define SigIePUBufferStatus (0x0048) + + +uint32_t dot11f_unpack_ie_power_caps(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEPowerCaps *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->maxTxPower = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_power_caps. */ + +#define SigIePowerCaps (0x0049) + + +uint32_t dot11f_unpack_ie_power_constraints(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEPowerConstraints *pDst) +{ + uint32_t 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 dot11f_unpack_ie_power_constraints. */ + +#define SigIePowerConstraints (0x004a) + + +uint32_t dot11f_unpack_ie_qbss_load(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQBSSLoad *pDst) +{ + uint32_t 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 -= (uint8_t)2; + pDst->chautil = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->avail, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_qbss_load. */ + +#define SigIeQBSSLoad (0x004b) + + +uint32_t dot11f_unpack_ie_QComVendorIE(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQComVendorIE *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->channel = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_QComVendorIE. */ + +#define SigIeQComVendorIE (0x004c) + + +uint32_t dot11f_unpack_ie_qos_caps_ap(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQOSCapsAp *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp51__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp51__ = *pBuf; + pDst->count = tmp51__ >> 0 & 0xf; + pDst->qack = tmp51__ >> 4 & 0x1; + pDst->qreq = tmp51__ >> 5 & 0x1; + pDst->txopreq = tmp51__ >> 6 & 0x1; + pDst->reserved = tmp51__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_qos_caps_ap. */ + +#define SigIeQOSCapsAp (0x004d) + + +uint32_t dot11f_unpack_ie_qos_caps_station(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQOSCapsStation *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp52__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp52__ = *pBuf; + pDst->acvo_uapsd = tmp52__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp52__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp52__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp52__ >> 3 & 0x1; + pDst->qack = tmp52__ >> 4 & 0x1; + pDst->max_sp_length = tmp52__ >> 5 & 0x3; + pDst->more_data_ack = tmp52__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_qos_caps_station. */ + +#define SigIeQOSCapsStation (0x004e) + + +uint32_t dot11f_unpack_ie_qos_map_set(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQosMapSet *pDst) +{ + uint32_t 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 = (uint8_t)(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 dot11f_unpack_ie_qos_map_set. */ + +#define SigIeQosMapSet (0x004f) + + +uint32_t dot11f_unpack_ie_quiet(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEQuiet *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->period = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + framesntohs(pCtx, &pDst->duration, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + framesntohs(pCtx, &pDst->offset, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_quiet. */ + +#define SigIeQuiet (0x0050) + + +uint32_t dot11f_unpack_ie_rcpiie(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERCPIIE *pDst) +{ + uint32_t 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 dot11f_unpack_ie_rcpiie. */ + +#define SigIeRCPIIE (0x0051) + + +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, }, +}; + +uint32_t dot11f_unpack_ie_ric_data_desc(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERICDataDesc *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + (void)pCtx; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_RICDataDesc, + IES_RICDataDesc, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_ric_data_desc. */ + +#define SigIeRICDataDesc (0x0052) + + +uint32_t dot11f_unpack_ie_rsn(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERSN *pDst) +{ + uint32_t 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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)2; + } + if (!ielen) { + pDst->pmkid_count = 0U; + return 0U; + } else { + framesntohs(pCtx, &pDst->pmkid_count, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)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 dot11f_unpack_ie_rsn. */ + +#define SigIeRSN (0x0053) + + +uint32_t dot11f_unpack_ie_rsniie(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERSNIIE *pDst) +{ + uint32_t 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 dot11f_unpack_ie_rsniie. */ + +#define SigIeRSNIIE (0x0054) + + +uint32_t dot11f_unpack_ie_rsn_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIERSNOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 253) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_rsn_opaque. */ + +#define SigIeRSNOpaque (0x0055) + + +uint32_t dot11f_unpack_ie_supp_channels(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIESuppChannels *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_bands = (uint8_t)(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 dot11f_unpack_ie_supp_channels. */ + +#define SigIeSuppChannels (0x0056) + + +uint32_t dot11f_unpack_ie_supp_operating_classes(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIESuppOperatingClasses *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_classes = (uint8_t)(ielen); + if (ielen > 32) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->classes, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_supp_operating_classes. */ + +#define SigIeSuppOperatingClasses (0x0057) + + +uint32_t dot11f_unpack_ie_supp_rates(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIESuppRates *pDst) +{ + uint8_t i; + uint8_t rate_indx = 0; + uint32_t 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 dot11f_unpack_ie_supp_rates. */ + +#define SigIeSuppRates (0x0058) + + +uint32_t dot11f_unpack_ie_tim(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETIM *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->dtim_period = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->bmpctl = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->num_vbmp = (uint8_t)(ielen); + if (ielen > 251) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->vbmp, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_tim. */ + +#define SigIeTIM (0x0059) + + +uint32_t dot11f_unpack_ie_tpc_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETPCReport *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->link_margin = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_tpc_report. */ + +#define SigIeTPCReport (0x005a) + + +uint32_t dot11f_unpack_ie_tpc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETPCRequest *pDst) +{ + uint32_t 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 dot11f_unpack_ie_tpc_request. */ + +#define SigIeTPCRequest (0x005b) + + +uint32_t dot11f_unpack_ie_time_advertisement(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETimeAdvertisement *pDst) +{ + uint32_t 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 -= (uint8_t)1; + DOT11F_MEMCPY(pCtx, pDst->time_value, pBuf, 10); + pBuf += 10; + ielen -= (uint8_t)10; + DOT11F_MEMCPY(pCtx, pDst->time_error, pBuf, 5); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_time_advertisement. */ + +#define SigIeTimeAdvertisement (0x005c) + + +uint32_t dot11f_unpack_ie_timeout_interval(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIETimeoutInterval *pDst) +{ + uint32_t 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 -= (uint8_t)1; + framesntohl(pCtx, &pDst->timeoutValue, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_timeout_interval. */ + +#define SigIeTimeoutInterval (0x005d) + + +uint32_t dot11f_unpack_ie_vht_ext_bss_load(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEVHTExtBssLoad *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->ssUnderUtil = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->FortyMHzUtil = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->EightyMHzUtil = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->OneSixtyMHzUtil = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_vht_ext_bss_load. */ + +#define SigIeVHTExtBssLoad (0x005e) + + +uint32_t dot11f_unpack_ie_vendor1_ie(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEVendor1IE *pDst) +{ + uint32_t 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 dot11f_unpack_ie_vendor1_ie. */ + +#define SigIeVendor1IE (0x005f) + + +uint32_t dot11f_unpack_ie_vendor3_ie(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEVendor3IE *pDst) +{ + uint32_t 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 dot11f_unpack_ie_vendor3_ie. */ + +#define SigIeVendor3IE (0x0060) + + +uint32_t dot11f_unpack_ie_wapi(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWAPI *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint16_t tmp53__; + (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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)4; + framesntohs(pCtx, &tmp53__, pBuf, 0); + pBuf += 2; + ielen -= 2; + pDst->preauth = tmp53__ >> 0 & 0x1; + pDst->reserved = tmp53__ >> 1 & 0x7fff; + if (!ielen) { + pDst->bkid_count = 0U; + return 0U; + } else { + framesntohs(pCtx, &pDst->bkid_count, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)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 dot11f_unpack_ie_wapi. */ + +#define SigIeWAPI (0x0061) + + +uint32_t dot11f_unpack_ie_wapi_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWAPIOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 253) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wapi_opaque. */ + +#define SigIeWAPIOpaque (0x0062) + + +uint32_t dot11f_unpack_ie_wfatpc(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWFATPC *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->linkMargin = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wfatpc. */ + +#define SigIeWFATPC (0x0063) + + +uint32_t dot11f_unpack_ie_wfdie_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWFDIEOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 249) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wfdie_opaque. */ + +#define SigIeWFDIEOpaque (0x0064) + + +uint32_t dot11f_unpack_ie_wmm_caps(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMCaps *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp54__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + tmp54__ = *pBuf; + pDst->reserved = tmp54__ >> 0 & 0xf; + pDst->qack = tmp54__ >> 4 & 0x1; + pDst->queue_request = tmp54__ >> 5 & 0x1; + pDst->txop_request = tmp54__ >> 6 & 0x1; + pDst->more_ack = tmp54__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmm_caps. */ + +#define SigIeWMMCaps (0x0065) + + +uint32_t dot11f_unpack_ie_wmm_info_ap(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMInfoAp *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp55__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp55__ = *pBuf; + pDst->param_set_count = tmp55__ >> 0 & 0xf; + pDst->reserved = tmp55__ >> 4 & 0x7; + pDst->uapsd = tmp55__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmm_info_ap. */ + +#define SigIeWMMInfoAp (0x0066) + + +uint32_t dot11f_unpack_ie_wmm_info_station(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMInfoStation *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp56__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp56__ = *pBuf; + pDst->acvo_uapsd = tmp56__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp56__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp56__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp56__ >> 3 & 0x1; + pDst->reserved1 = tmp56__ >> 4 & 0x1; + pDst->max_sp_length = tmp56__ >> 5 & 0x3; + pDst->reserved2 = tmp56__ >> 7 & 0x1; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmm_info_station. */ + +#define SigIeWMMInfoStation (0x0067) + + +uint32_t dot11f_unpack_ie_wmm_params(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWMMParams *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp57__; + uint8_t tmp58__; + uint8_t tmp59__; + uint8_t tmp60__; + uint8_t tmp61__; + uint8_t tmp62__; + uint8_t tmp63__; + uint8_t tmp64__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->version = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + if (pDst->version != 0x1) { + pDst->present = 0; + return status | DOT11F_BAD_FIXED_VALUE; + } + pDst->qosInfo = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->reserved2 = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + tmp57__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_aifsn = tmp57__ >> 0 & 0xf; + pDst->acbe_acm = tmp57__ >> 4 & 0x1; + pDst->acbe_aci = tmp57__ >> 5 & 0x3; + pDst->unused1 = tmp57__ >> 7 & 0x1; + tmp58__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbe_acwmin = tmp58__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp58__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp59__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_aifsn = tmp59__ >> 0 & 0xf; + pDst->acbk_acm = tmp59__ >> 4 & 0x1; + pDst->acbk_aci = tmp59__ >> 5 & 0x3; + pDst->unused2 = tmp59__ >> 7 & 0x1; + tmp60__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acbk_acwmin = tmp60__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp60__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp61__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_aifsn = tmp61__ >> 0 & 0xf; + pDst->acvi_acm = tmp61__ >> 4 & 0x1; + pDst->acvi_aci = tmp61__ >> 5 & 0x3; + pDst->unused3 = tmp61__ >> 7 & 0x1; + tmp62__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvi_acwmin = tmp62__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp62__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); + pBuf += 2; + ielen -= (uint8_t)2; + tmp63__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_aifsn = tmp63__ >> 0 & 0xf; + pDst->acvo_acm = tmp63__ >> 4 & 0x1; + pDst->acvo_aci = tmp63__ >> 5 & 0x3; + pDst->unused4 = tmp63__ >> 7 & 0x1; + tmp64__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->acvo_acwmin = tmp64__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp64__ >> 4 & 0xf; + framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wmm_params. */ + +#define SigIeWMMParams (0x0068) + + +uint32_t dot11f_unpack_ie_wpa(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWPA *pDst) +{ + uint32_t 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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)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 -= (uint8_t)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 dot11f_unpack_ie_wpa. */ + +#define SigIeWPA (0x0069) + + +uint32_t dot11f_unpack_ie_wpa_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWPAOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 249) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wpa_opaque. */ + +#define SigIeWPAOpaque (0x006a) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWSC *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WSC, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc. */ + +#define SigIeWSC (0x006b) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_assoc_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscAssocReq *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscAssocReq, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_assoc_req. */ + +#define SigIeWscAssocReq (0x006c) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_assoc_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscAssocRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscAssocRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_assoc_res. */ + +#define SigIeWscAssocRes (0x006d) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_beacon(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscBeacon *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscBeacon, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_beacon. */ + +#define SigIeWscBeacon (0x006e) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_beacon_probe_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscBeaconProbeRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscBeaconProbeRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_beacon_probe_res. */ + +#define SigIeWscBeaconProbeRes (0x006f) + + +uint32_t dot11f_unpack_ie_wsc_ie_opaque(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscIEOpaque *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_data = (uint8_t)(ielen); + if (ielen > 249) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->data, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_wsc_ie_opaque. */ + +#define SigIeWscIEOpaque (0x0070) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_probe_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscProbeReq *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscProbeReq, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_probe_req. */ + +#define SigIeWscProbeReq (0x0071) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_probe_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscProbeRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscProbeRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_probe_res. */ + +#define SigIeWscProbeRes (0x0072) + + +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}, +}; + +uint32_t dot11f_unpack_ie_wsc_reassoc_res(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEWscReassocRes *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pBuf; (void)ielen; /* Shutup the compiler */ + pDst->present = 1; + status = unpack_tlv_core(pCtx, pBuf, ielen, + TLVS_WscReassocRes, + (uint8_t *)pDst, sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_wsc_reassoc_res. */ + +#define SigIeWscReassocRes (0x0073) + + +uint32_t dot11f_unpack_ie_ext_chan_switch_ann(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEext_chan_switch_ann *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->new_reg_class = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->new_channel = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->switch_count = *pBuf; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ext_chan_switch_ann. */ + +#define SigIeext_chan_switch_ann (0x0074) + + +uint32_t dot11f_unpack_ie_ht2040_bss_coexistence(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEht2040_bss_coexistence *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + uint8_t tmp65__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp65__ = *pBuf; + pDst->info_request = tmp65__ >> 0 & 0x1; + pDst->forty_mhz_intolerant = tmp65__ >> 1 & 0x1; + pDst->twenty_mhz_bsswidth_req = tmp65__ >> 2 & 0x1; + pDst->obss_scan_exemption_req = tmp65__ >> 3 & 0x1; + pDst->obss_scan_exemption_grant = tmp65__ >> 4 & 0x1; + pDst->unused = tmp65__ >> 5 & 0x7; + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ht2040_bss_coexistence. */ + +#define SigIeht2040_bss_coexistence (0x0075) + + +uint32_t dot11f_unpack_ie_ht2040_bss_intolerant_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEht2040_bss_intolerant_report *pDst) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) + status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->operating_class = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + pDst->num_channel_list = (uint8_t)(ielen); + if (ielen > 50) { + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } + + DOT11F_MEMCPY(pCtx, pDst->channel_list, pBuf, (ielen)); + (void)pCtx; + return status; +} /* End dot11f_unpack_ie_ht2040_bss_intolerant_report. */ + +#define SigIeht2040_bss_intolerant_report (0x0076) + + +uint32_t dot11f_unpack_ie_sec_chan_offset_ele(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEsec_chan_offset_ele *pDst) +{ + uint32_t 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 dot11f_unpack_ie_sec_chan_offset_ele. */ + +#define SigIesec_chan_offset_ele (0x0077) + + +static const tFFDefn FFS_vendor2_ie[] = { + { NULL, 0, 0, 0,}, +}; + +static const tIEDefn IES_vendor2_ie[] = { + { offsetof(tDot11fIEvendor2_ie, VHTCaps), offsetof(tDot11fIEVHTCaps, + present), 0, "VHTCaps", 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, + 0, DOT11F_EID_VHTCAPS, 0, }, + { offsetof(tDot11fIEvendor2_ie, VHTOperation), + offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation", + 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, + 0, DOT11F_EID_VHTOPERATION, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, +}; + +uint32_t dot11f_unpack_ie_vendor2_ie(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint8_t ielen, + tDot11fIEvendor2_ie *pDst) +{ + uint32_t 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 -= (uint8_t)1; + pDst->sub_type = *pBuf; + pBuf += 1; + ielen -= (uint8_t)1; + (void)pCtx; + status |= unpack_core(pCtx, + pBuf, + ielen, + FFS_vendor2_ie, + IES_vendor2_ie, + (uint8_t *)pDst, + sizeof(*pDst)); + return status; +} /* End dot11f_unpack_ie_vendor2_ie. */ + +#define SigIevendor2_ie (0x0078) + + +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, },}; + +uint32_t dot11f_unpack_add_ts_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAddTSRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_AddTSRequest, IES_AddTSRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_add_ts_request. */ + +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, },}; + +uint32_t dot11f_unpack_add_ts_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAddTSResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_AddTSResponse, IES_AddTSResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_add_ts_response. */ + +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, }, + { offsetof(tDot11fAssocRequest, vendor2_ie), + offsetof(tDot11fIEvendor2_ie, present), 0, "vendor2_ie", + 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; + +uint32_t dot11f_unpack_assoc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAssocRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_AssocRequest, IES_AssocRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_assoc_request. */ + +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, }, + { offsetof(tDot11fAssocResponse, vendor2_ie), + offsetof(tDot11fIEvendor2_ie, present), 0, "vendor2_ie", + 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; + +uint32_t dot11f_unpack_assoc_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAssocResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_AssocResponse, IES_AssocResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_assoc_response. */ + +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, },}; + +uint32_t dot11f_unpack_authentication(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fAuthentication *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_Authentication, IES_Authentication, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_authentication. */ + +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, 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, vendor2_ie), offsetof(tDot11fIEvendor2_ie, + present), 0, "vendor2_ie", 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 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, },}; + +uint32_t dot11f_unpack_beacon(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_Beacon, IES_Beacon, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_beacon. */ + +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, },}; + +uint32_t dot11f_unpack_beacon1(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon1 *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_Beacon1, IES_Beacon1, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_beacon1. */ + +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, 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, vendor2_ie), offsetof(tDot11fIEvendor2_ie, + present), 0, "vendor2_ie", 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 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, },}; + +uint32_t dot11f_unpack_beacon2(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeacon2 *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_Beacon2, IES_Beacon2, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_beacon2. */ + +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, 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, vendor2_ie), offsetof(tDot11fIEvendor2_ie, + present), 0, "vendor2_ie", 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 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, },}; + +uint32_t dot11f_unpack_beacon_i_es(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fBeaconIEs *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_BeaconIEs, IES_BeaconIEs, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_beacon_i_es. */ + +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, },}; + +uint32_t dot11f_unpack_channel_switch(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fChannelSwitch *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ChannelSwitch, IES_ChannelSwitch, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_channel_switch. */ + +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, },}; + +uint32_t dot11f_unpack_de_auth(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDeAuth *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_DeAuth, IES_DeAuth, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_de_auth. */ + +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, },}; + +uint32_t dot11f_unpack_del_ts(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDelTS *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_DelTS, IES_DelTS, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_del_ts. */ + +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, },}; + +uint32_t dot11f_unpack_disassociation(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fDisassociation *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_Disassociation, IES_Disassociation, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_disassociation. */ + +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, },}; + +uint32_t dot11f_unpack_link_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fLinkMeasurementReport *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_LinkMeasurementReport, IES_LinkMeasurementReport, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_link_measurement_report. */ + +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, },}; + +uint32_t dot11f_unpack_link_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fLinkMeasurementRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_LinkMeasurementRequest, IES_LinkMeasurementRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_link_measurement_request. */ + +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, },}; + +uint32_t dot11f_unpack_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fMeasurementReport *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_MeasurementReport, IES_MeasurementReport, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_measurement_report. */ + +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, },}; + +uint32_t dot11f_unpack_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fMeasurementRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_MeasurementRequest, IES_MeasurementRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_measurement_request. */ + +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, },}; + +uint32_t dot11f_unpack_neighbor_report_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fNeighborReportRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_NeighborReportRequest, IES_NeighborReportRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_neighbor_report_request. */ + +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, },}; + +uint32_t dot11f_unpack_neighbor_report_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fNeighborReportResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_NeighborReportResponse, IES_NeighborReportResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_neighbor_report_response. */ + +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, },}; + +uint32_t dot11f_unpack_operating_mode(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fOperatingMode *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_OperatingMode, IES_OperatingMode, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_operating_mode. */ + +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, },}; + +uint32_t dot11f_unpack_probe_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fProbeRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ProbeRequest, IES_ProbeRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_probe_request. */ + +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, 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, vendor2_ie), + offsetof(tDot11fIEvendor2_ie, present), 0, "vendor2_ie", + 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 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, },}; + +uint32_t dot11f_unpack_probe_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fProbeResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ProbeResponse, IES_ProbeResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_probe_response. */ + +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, },}; + +uint32_t dot11f_unpack_qos_map_configure(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fQosMapConfigure *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_QosMapConfigure, IES_QosMapConfigure, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_qos_map_configure. */ + +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, },}; + +uint32_t dot11f_unpack_radio_measurement_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fRadioMeasurementReport *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_RadioMeasurementReport, IES_RadioMeasurementReport, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_radio_measurement_report. */ + +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, },}; + +uint32_t dot11f_unpack_radio_measurement_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fRadioMeasurementRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_RadioMeasurementRequest, IES_RadioMeasurementRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_radio_measurement_request. */ + +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, }, + { offsetof(tDot11fReAssocRequest, vendor2_ie), + offsetof(tDot11fIEvendor2_ie, present), 0, "vendor2_ie", + 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; + +uint32_t dot11f_unpack_re_assoc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fReAssocRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ReAssocRequest, IES_ReAssocRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_re_assoc_request. */ + +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, }, + { offsetof(tDot11fReAssocResponse, vendor2_ie), + offsetof(tDot11fIEvendor2_ie, present), 0, "vendor2_ie", + 0, 7, 28, SigIevendor2_ie, {0, 144, 76, 0, 0}, + 3, DOT11F_EID_VENDOR2_IE, 0, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; + +uint32_t dot11f_unpack_re_assoc_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fReAssocResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ReAssocResponse, IES_ReAssocResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_re_assoc_response. */ + +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, },}; + +uint32_t dot11f_unpack_sm_power_save(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSMPowerSave *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_SMPowerSave, IES_SMPowerSave, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_sm_power_save. */ + +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, },}; + +uint32_t dot11f_unpack_sa_query_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSaQueryReq *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_SaQueryReq, IES_SaQueryReq, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_sa_query_req. */ + +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, },}; + +uint32_t dot11f_unpack_sa_query_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fSaQueryRsp *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_SaQueryRsp, IES_SaQueryRsp, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_sa_query_rsp. */ + +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, },}; + +uint32_t dot11f_unpack_tdls_dis_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSDisReq *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSDisReq, IES_TDLSDisReq, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_dis_req. */ + +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, ht2040_bss_coexistence), + offsetof(tDot11fIEht2040_bss_coexistence, present), 0, + "ht2040_bss_coexistence", 0, 3, 3, SigIeht2040_bss_coexistence, + {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040_BSS_COEXISTENCE, 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, },}; + +uint32_t dot11f_unpack_tdls_dis_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSDisRsp *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSDisRsp, IES_TDLSDisRsp, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_dis_rsp. */ + +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, },}; + +uint32_t dot11f_unpack_tdls_peer_traffic_ind(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSPeerTrafficInd *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSPeerTrafficInd, IES_TDLSPeerTrafficInd, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_peer_traffic_ind. */ + +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, },}; + +uint32_t dot11f_unpack_tdls_peer_traffic_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSPeerTrafficRsp *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSPeerTrafficRsp, IES_TDLSPeerTrafficRsp, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_peer_traffic_rsp. */ + +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, },}; + +uint32_t dot11f_unpack_tdls_setup_cnf(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupCnf *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSSetupCnf, IES_TDLSSetupCnf, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_setup_cnf. */ + +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, ht2040_bss_coexistence), + offsetof(tDot11fIEht2040_bss_coexistence, present), 0, + "ht2040_bss_coexistence", 0, 3, 3, SigIeht2040_bss_coexistence, + {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040_BSS_COEXISTENCE, 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, },}; + +uint32_t dot11f_unpack_tdls_setup_req(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupReq *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSSetupReq, IES_TDLSSetupReq, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_setup_req. */ + +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, ht2040_bss_coexistence), + offsetof(tDot11fIEht2040_bss_coexistence, present), 0, + "ht2040_bss_coexistence", 0, 3, 3, SigIeht2040_bss_coexistence, + {0, 0, 0, 0, 0}, 0, DOT11F_EID_HT2040_BSS_COEXISTENCE, 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, },}; + +uint32_t dot11f_unpack_tdls_setup_rsp(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSSetupRsp *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSSetupRsp, IES_TDLSSetupRsp, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_setup_rsp. */ + +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, },}; + +uint32_t dot11f_unpack_tdls_teardown(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTDLSTeardown *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TDLSTeardown, IES_TDLSTeardown, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tdls_teardown. */ + +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, },}; + +uint32_t dot11f_unpack_tpc_report(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTPCReport *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TPCReport, IES_TPCReport, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tpc_report. */ + +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, },}; + +uint32_t dot11f_unpack_tpc_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTPCRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TPCRequest, IES_TPCRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_tpc_request. */ + +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, 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, },}; + +uint32_t dot11f_unpack_timing_advertisement_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fTimingAdvertisementFrame *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_TimingAdvertisementFrame, IES_TimingAdvertisementFrame, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_timing_advertisement_frame. */ + +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, },}; + +uint32_t dot11f_unpack_vht_gid_management_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fVHTGidManagementActionFrame *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_VHTGidManagementActionFrame, IES_VHTGidManagementActionFrame, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_vht_gid_management_action_frame. */ + +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, },}; + +uint32_t dot11f_unpack_wmm_add_ts_request(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMAddTSRequest *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_WMMAddTSRequest, IES_WMMAddTSRequest, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_wmm_add_ts_request. */ + +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, },}; + +uint32_t dot11f_unpack_wmm_add_ts_response(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMAddTSResponse *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_WMMAddTSResponse, IES_WMMAddTSResponse, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_wmm_add_ts_response. */ + +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, },}; + +uint32_t dot11f_unpack_wmm_del_ts(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fWMMDelTS *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_WMMDelTS, IES_WMMDelTS, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_wmm_del_ts. */ + +static const tFFDefn FFS_ht2040_bss_coexistence_mgmt_action_frame[] = { + { "Category", offsetof(tDot11fht2040_bss_coexistence_mgmt_action_frame, + Category), SigFfCategory, DOT11F_FF_CATEGORY_LEN, }, + { "Action", offsetof(tDot11fht2040_bss_coexistence_mgmt_action_frame, + Action), SigFfAction, DOT11F_FF_ACTION_LEN, }, + { NULL, 0, 0, 0,}, +}; + +static const tIEDefn IES_ht2040_bss_coexistence_mgmt_action_frame[] = { + { offsetof(tDot11fht2040_bss_coexistence_mgmt_action_frame, + ht2040_bss_coexistence), offsetof(tDot11fIEht2040_bss_coexistence, + present), 0, "ht2040_bss_coexistence", + 0, 3, 3, SigIeht2040_bss_coexistence, {0, 0, 0, 0, 0}, + 0, DOT11F_EID_HT2040_BSS_COEXISTENCE, 1, }, + { offsetof(tDot11fht2040_bss_coexistence_mgmt_action_frame, + ht2040_bss_intolerant_report), + offsetof(tDot11fIEht2040_bss_intolerant_report, present), 0, + "ht2040_bss_intolerant_report", + 0, 3, 53, SigIeht2040_bss_intolerant_report, {0, 0, 0, 0, 0}, + 0, DOT11F_EID_HT2040_BSS_INTOLERANT_REPORT, 1, }, + {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; + +uint32_t dot11f_unpack_ht2040_bss_coexistence_mgmt_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ht2040_bss_coexistence_mgmt_action_frame, IES_ht2040_bss_coexistence_mgmt_action_frame, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_ht2040_bss_coexistence_mgmt_action_frame. */ + +static uint32_t unpack_core(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + const tFFDefn FFs[], + const tIEDefn IEs[], + uint8_t *pFrm, + size_t nFrm) +{ + const tFFDefn *pFf; + const tIEDefn *pIe; + uint8_t *pBufRemaining; + uint32_t nBufRemaining, status; + uint8_t eid, len; + tFRAMES_BOOL *pfFound; + uint32_t 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) + *(uint16_t *)(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" + "bytes 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: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfAID *) + (pFrm + pFf->offset))->associd)); + break; + case SigFfAction: + dot11f_unpack_ff_action(pCtx, + pBufRemaining, (tDot11fFfAction *) + (pFrm + pFf->offset)); + break; + case SigFfAuthAlgo: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfAuthAlgo *) + (pFrm + pFf->offset))->algo)); + break; + case SigFfAuthSeqNo: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfAuthSeqNo *) + (pFrm + pFf->offset))->no)); + break; + case SigFfBeaconInterval: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfBeaconInterval *) + (pFrm + pFf->offset))->interval)); + break; + case SigFfCapabilities: + dot11f_unpack_ff_capabilities(pCtx, + pBufRemaining, (tDot11fFfCapabilities *) + (pFrm + pFf->offset)); + break; + case SigFfCategory: + dot11f_unpack_ff_category(pCtx, + pBufRemaining, (tDot11fFfCategory *) + (pFrm + pFf->offset)); + break; + case SigFfCurrentAPAddress: + dot11f_unpack_ff_current_ap_address(pCtx, + pBufRemaining, (tDot11fFfCurrentAPAddress *) + (pFrm + pFf->offset)); + break; + case SigFfDialogToken: + dot11f_unpack_ff_dialog_token(pCtx, + pBufRemaining, (tDot11fFfDialogToken *) + (pFrm + pFf->offset)); + break; + case SigFfLinkMargin: + dot11f_unpack_ff_link_margin(pCtx, + pBufRemaining, (tDot11fFfLinkMargin *) + (pFrm + pFf->offset)); + break; + case SigFfListenInterval: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfListenInterval *) + (pFrm + pFf->offset))->interval)); + break; + case SigFfMaxTxPower: + dot11f_unpack_ff_max_tx_power(pCtx, + pBufRemaining, (tDot11fFfMaxTxPower *) + (pFrm + pFf->offset)); + break; + case SigFfNumOfRepetitions: + dot11f_unpack_ff_num_of_repetitions(pCtx, + pBufRemaining, (tDot11fFfNumOfRepetitions *) + (pFrm + pFf->offset)); + break; + case SigFfOperatingMode: + dot11f_unpack_ff_operating_mode(pCtx, + pBufRemaining, (tDot11fFfOperatingMode *) + (pFrm + pFf->offset)); + break; + case SigFfRCPI: + dot11f_unpack_ff_rcpi(pCtx, + pBufRemaining, (tDot11fFfRCPI *) + (pFrm + pFf->offset)); + break; + case SigFfRSNI: + dot11f_unpack_ff_rsni(pCtx, + pBufRemaining, (tDot11fFfRSNI *) + (pFrm + pFf->offset)); + break; + case SigFfReason: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfReason *) + (pFrm + pFf->offset))->code)); + break; + case SigFfRxAntennaId: + dot11f_unpack_ff_rx_antenna_id(pCtx, + pBufRemaining, (tDot11fFfRxAntennaId *) + (pFrm + pFf->offset)); + break; + case SigFfSMPowerModeSet: + dot11f_unpack_ff_sm_power_mode_set(pCtx, + pBufRemaining, (tDot11fFfSMPowerModeSet *) + (pFrm + pFf->offset)); + break; + case SigFfStatus: + dot11f_unpack_ff_common_func(pCtx, + pBufRemaining, (uint16_t *)&(((tDot11fFfStatus *) + (pFrm + pFf->offset))->status)); + break; + case SigFfStatusCode: + dot11f_unpack_ff_status_code(pCtx, + pBufRemaining, (tDot11fFfStatusCode *) + (pFrm + pFf->offset)); + break; + case SigFfTPCEleID: + dot11f_unpack_ff_tpc_ele_id(pCtx, + pBufRemaining, (tDot11fFfTPCEleID *) + (pFrm + pFf->offset)); + break; + case SigFfTPCEleLen: + dot11f_unpack_ff_tpc_ele_len(pCtx, + pBufRemaining, (tDot11fFfTPCEleLen *) + (pFrm + pFf->offset)); + break; + case SigFfTSInfo: + dot11f_unpack_ff_ts_info(pCtx, + pBufRemaining, (tDot11fFfTSInfo *) + (pFrm + pFf->offset)); + break; + case SigFfTimeStamp: + dot11f_unpack_ff_time_stamp(pCtx, + pBufRemaining, (tDot11fFfTimeStamp *) + (pFrm + pFf->offset)); + break; + case SigFfTransactionId: + dot11f_unpack_ff_transaction_id(pCtx, + pBufRemaining, (tDot11fFfTransactionId *) + (pFrm + pFf->offset)); + break; + case SigFfTxAntennaId: + dot11f_unpack_ff_tx_antenna_id(pCtx, + pBufRemaining, (tDot11fFfTxAntennaId *) + (pFrm + pFf->offset)); + break; + case SigFfTxPower: + dot11f_unpack_ff_tx_power(pCtx, + pBufRemaining, (tDot11fFfTxPower *) + (pFrm + pFf->offset)); + break; + case SigFfVhtMembershipStatusArray: + dot11f_unpack_ff_vht_membership_status_array(pCtx, + pBufRemaining, (tDot11fFfVhtMembershipStatusArray *) + (pFrm + pFf->offset)); + break; + case SigFfVhtUserPositionArray: + dot11f_unpack_ff_vht_user_position_array(pCtx, + pBufRemaining, (tDot11fFfVhtUserPositionArray *) + (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 = find_ie_defn(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) * + (*(uint16_t *)(pFrm + pIe->countOffset))); + switch (pIe->sig) { + case SigIeCondensedCountryStr: + status |= + dot11f_unpack_ie_condensed_country_str( + pCtx, pBufRemaining, len, + (tDot11fIECondensedCountryStr *) + (pFrm + pIe->offset + + sizeof(tDot11fIECondensedCountryStr) * + countOffset)); + break; + case SigIeGTK: + status |= + dot11f_unpack_ie_gtk( + pCtx, pBufRemaining, len, + (tDot11fIEGTK *) + (pFrm + pIe->offset + + sizeof(tDot11fIEGTK) * + countOffset)); + break; + case SigIeIGTK: + status |= + dot11f_unpack_ie_igtk( + pCtx, pBufRemaining, len, + (tDot11fIEIGTK *) + (pFrm + pIe->offset + + sizeof(tDot11fIEIGTK) * + countOffset)); + break; + case SigIeR0KH_ID: + status |= + dot11f_unpack_ie_r0_kh_id( + pCtx, pBufRemaining, len, + (tDot11fIER0KH_ID *) + (pFrm + pIe->offset + + sizeof(tDot11fIER0KH_ID) * + countOffset)); + break; + case SigIeR1KH_ID: + status |= + dot11f_unpack_ie_r1_kh_id( + pCtx, pBufRemaining, len, + (tDot11fIER1KH_ID *) + (pFrm + pIe->offset + + sizeof(tDot11fIER1KH_ID) * + countOffset)); + break; + case SigIeTSFInfo: + status |= + dot11f_unpack_ie_tsf_info( + pCtx, pBufRemaining, len, + (tDot11fIETSFInfo *) + (pFrm + pIe->offset + + sizeof(tDot11fIETSFInfo) * + countOffset)); + break; + case SigIeAPChannelReport: + status |= + dot11f_unpack_ie_ap_channel_report( + pCtx, pBufRemaining, len, + (tDot11fIEAPChannelReport *) + (pFrm + pIe->offset + + sizeof(tDot11fIEAPChannelReport) * + countOffset)); + break; + case SigIeBcnReportingDetail: + status |= + dot11f_unpack_ie_bcn_reporting_detail( + pCtx, pBufRemaining, len, + (tDot11fIEBcnReportingDetail *) + (pFrm + pIe->offset + + sizeof(tDot11fIEBcnReportingDetail) * + countOffset)); + break; + case SigIeBeaconReportFrmBody: + status |= + dot11f_unpack_ie_beacon_report_frm_body( + pCtx, pBufRemaining, len, + (tDot11fIEBeaconReportFrmBody *) + (pFrm + pIe->offset + + sizeof(tDot11fIEBeaconReportFrmBody) * + countOffset)); + break; + case SigIeBeaconReporting: + status |= + dot11f_unpack_ie_beacon_reporting( + pCtx, pBufRemaining, len, + (tDot11fIEBeaconReporting *) + (pFrm + pIe->offset + + sizeof(tDot11fIEBeaconReporting) * + countOffset)); + break; + case SigIeMeasurementPilot: + status |= + dot11f_unpack_ie_measurement_pilot( + pCtx, pBufRemaining, len, + (tDot11fIEMeasurementPilot *) + (pFrm + pIe->offset + + sizeof(tDot11fIEMeasurementPilot) * + countOffset)); + break; + case SigIeMultiBssid: + status |= + dot11f_unpack_ie_multi_bssid( + pCtx, pBufRemaining, len, + (tDot11fIEMultiBssid *) + (pFrm + pIe->offset + + sizeof(tDot11fIEMultiBssid) * + countOffset)); + break; + case SigIeRICData: + status |= + dot11f_unpack_ie_ric_data( + pCtx, pBufRemaining, len, + (tDot11fIERICData *) + (pFrm + pIe->offset + + sizeof(tDot11fIERICData) * + countOffset)); + break; + case SigIeRICDescriptor: + status |= + dot11f_unpack_ie_ric_descriptor( + pCtx, pBufRemaining, len, + (tDot11fIERICDescriptor *) + (pFrm + pIe->offset + + sizeof(tDot11fIERICDescriptor) * + countOffset)); + break; + case SigIeRRMEnabledCap: + status |= + dot11f_unpack_ie_rrm_enabled_cap( + pCtx, pBufRemaining, len, + (tDot11fIERRMEnabledCap *) + (pFrm + pIe->offset + + sizeof(tDot11fIERRMEnabledCap) * + countOffset)); + break; + case SigIeRequestedInfo: + status |= + dot11f_unpack_ie_requested_info( + pCtx, pBufRemaining, len, + (tDot11fIERequestedInfo *) + (pFrm + pIe->offset + + sizeof(tDot11fIERequestedInfo) * + countOffset)); + break; + case SigIeSSID: + status |= + dot11f_unpack_ie_ssid( + pCtx, pBufRemaining, len, + (tDot11fIESSID *) + (pFrm + pIe->offset + + sizeof(tDot11fIESSID) * + countOffset)); + break; + case SigIeSchedule: + status |= + dot11f_unpack_ie_schedule( + pCtx, pBufRemaining, len, + (tDot11fIESchedule *) + (pFrm + pIe->offset + + sizeof(tDot11fIESchedule) * + countOffset)); + break; + case SigIeTCLAS: + status |= + dot11f_unpack_ie_tclas( + pCtx, pBufRemaining, len, + (tDot11fIETCLAS *) + (pFrm + pIe->offset + + sizeof(tDot11fIETCLAS) * + countOffset)); + break; + case SigIeTCLASSPROC: + status |= dot11f_unpack_ie_common_func(pCtx, pBufRemaining, len, + (uint8_t *) &(((tDot11fIETCLASSPROC *)(pFrm + pIe->offset + sizeof(tDot11fIETCLASSPROC)*countOffset))->present), + (uint8_t *) &(((tDot11fIETCLASSPROC *)(pFrm + pIe->offset + sizeof(tDot11fIETCLASSPROC)*countOffset))->processing)); + break; + case SigIeTSDelay: + status |= + dot11f_unpack_ie_ts_delay( + pCtx, pBufRemaining, len, + (tDot11fIETSDelay *) + (pFrm + pIe->offset + + sizeof(tDot11fIETSDelay) * + countOffset)); + break; + case SigIeTSPEC: + status |= + dot11f_unpack_ie_tspec( + pCtx, pBufRemaining, len, + (tDot11fIETSPEC *) + (pFrm + pIe->offset + + sizeof(tDot11fIETSPEC) * + countOffset)); + break; + case SigIeVHTCaps: + status |= + dot11f_unpack_ie_vht_caps( + pCtx, pBufRemaining, len, + (tDot11fIEVHTCaps *) + (pFrm + pIe->offset + + sizeof(tDot11fIEVHTCaps) * + countOffset)); + break; + case SigIeVHTOperation: + status |= + dot11f_unpack_ie_vht_operation( + pCtx, pBufRemaining, len, + (tDot11fIEVHTOperation *) + (pFrm + pIe->offset + + sizeof(tDot11fIEVHTOperation) * + countOffset)); + break; + case SigIeWMMSchedule: + status |= + dot11f_unpack_ie_wmm_schedule( + pCtx, pBufRemaining, len, + (tDot11fIEWMMSchedule *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMSchedule) * + countOffset)); + break; + case SigIeWMMTCLAS: + status |= + dot11f_unpack_ie_wmmtclas( + pCtx, pBufRemaining, len, + (tDot11fIEWMMTCLAS *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMTCLAS) * + countOffset)); + break; + case SigIeWMMTCLASPROC: + status |= + dot11f_unpack_ie_wmmtclasproc( + pCtx, pBufRemaining, len, + (tDot11fIEWMMTCLASPROC *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMTCLASPROC) * + countOffset)); + break; + case SigIeWMMTSDelay: + status |= + dot11f_unpack_ie_wmmts_delay( + pCtx, pBufRemaining, len, + (tDot11fIEWMMTSDelay *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMTSDelay) * + countOffset)); + break; + case SigIeWMMTSPEC: + status |= + dot11f_unpack_ie_wmmtspec( + pCtx, pBufRemaining, len, + (tDot11fIEWMMTSPEC *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMTSPEC) * + countOffset)); + break; + case SigIeWiderBWChanSwitchAnn: + status |= + dot11f_unpack_ie_wider_bw_chan_switch_ann( + pCtx, pBufRemaining, len, + (tDot11fIEWiderBWChanSwitchAnn *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWiderBWChanSwitchAnn) * + countOffset)); + break; + case SigIeAID: + status |= + dot11f_unpack_ie_aid( + pCtx, pBufRemaining, len, + (tDot11fIEAID *) + (pFrm + pIe->offset + + sizeof(tDot11fIEAID) * + countOffset)); + break; + case SigIeCFParams: + status |= + dot11f_unpack_ie_cf_params( + pCtx, pBufRemaining, len, + (tDot11fIECFParams *) + (pFrm + pIe->offset + + sizeof(tDot11fIECFParams) * + countOffset)); + break; + case SigIeChallengeText: + status |= + dot11f_unpack_ie_challenge_text( + pCtx, pBufRemaining, len, + (tDot11fIEChallengeText *) + (pFrm + pIe->offset + + sizeof(tDot11fIEChallengeText) * + countOffset)); + break; + case SigIeChanSwitchAnn: + status |= + dot11f_unpack_ie_chan_switch_ann( + pCtx, pBufRemaining, len, + (tDot11fIEChanSwitchAnn *) + (pFrm + pIe->offset + + sizeof(tDot11fIEChanSwitchAnn) * + countOffset)); + break; + case SigIeChannelSwitchWrapper: + status |= + dot11f_unpack_ie_channel_switch_wrapper( + pCtx, pBufRemaining, len, + (tDot11fIEChannelSwitchWrapper *) + (pFrm + pIe->offset + + sizeof(tDot11fIEChannelSwitchWrapper) * + countOffset)); + break; + case SigIeCountry: + status |= + dot11f_unpack_ie_country( + pCtx, pBufRemaining, len, + (tDot11fIECountry *) + (pFrm + pIe->offset + + sizeof(tDot11fIECountry) * + countOffset)); + break; + case SigIeDSParams: + status |= dot11f_unpack_ie_common_func(pCtx, pBufRemaining, len, + (uint8_t *) &(((tDot11fIEDSParams *)(pFrm + pIe->offset + sizeof(tDot11fIEDSParams)*countOffset))->present), + (uint8_t *) &(((tDot11fIEDSParams *)(pFrm + pIe->offset + sizeof(tDot11fIEDSParams)*countOffset))->curr_channel)); + break; + case SigIeEDCAParamSet: + status |= + dot11f_unpack_ie_edca_param_set( + pCtx, pBufRemaining, len, + (tDot11fIEEDCAParamSet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEEDCAParamSet) * + countOffset)); + break; + case SigIeERPInfo: + status |= + dot11f_unpack_ie_erp_info( + pCtx, pBufRemaining, len, + (tDot11fIEERPInfo *) + (pFrm + pIe->offset + + sizeof(tDot11fIEERPInfo) * + countOffset)); + break; + case SigIeESECckmOpaque: + status |= + dot11f_unpack_ie_ese_cckm_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEESECckmOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESECckmOpaque) * + countOffset)); + break; + case SigIeESERadMgmtCap: + status |= + dot11f_unpack_ie_ese_rad_mgmt_cap( + pCtx, pBufRemaining, len, + (tDot11fIEESERadMgmtCap *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESERadMgmtCap) * + countOffset)); + break; + case SigIeESETrafStrmMet: + status |= + dot11f_unpack_ie_ese_traf_strm_met( + pCtx, pBufRemaining, len, + (tDot11fIEESETrafStrmMet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESETrafStrmMet) * + countOffset)); + break; + case SigIeESETrafStrmRateSet: + status |= + dot11f_unpack_ie_ese_traf_strm_rate_set( + pCtx, pBufRemaining, len, + (tDot11fIEESETrafStrmRateSet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESETrafStrmRateSet) * + countOffset)); + break; + case SigIeESETxmitPower: + status |= + dot11f_unpack_ie_ese_txmit_power( + pCtx, pBufRemaining, len, + (tDot11fIEESETxmitPower *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESETxmitPower) * + countOffset)); + break; + case SigIeESEVersion: + status |= + dot11f_unpack_ie_ese_version( + pCtx, pBufRemaining, len, + (tDot11fIEESEVersion *) + (pFrm + pIe->offset + + sizeof(tDot11fIEESEVersion) * + countOffset)); + break; + case SigIeExtCap: + status |= + dot11f_unpack_ie_ext_cap( + pCtx, pBufRemaining, len, + (tDot11fIEExtCap *) + (pFrm + pIe->offset + + sizeof(tDot11fIEExtCap) * + countOffset)); + break; + case SigIeExtSuppRates: + status |= + dot11f_unpack_ie_ext_supp_rates( + pCtx, pBufRemaining, len, + (tDot11fIEExtSuppRates *) + (pFrm + pIe->offset + + sizeof(tDot11fIEExtSuppRates) * + countOffset)); + break; + case SigIeFHParamSet: + status |= + dot11f_unpack_ie_fh_param_set( + pCtx, pBufRemaining, len, + (tDot11fIEFHParamSet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEFHParamSet) * + countOffset)); + break; + case SigIeFHParams: + status |= + dot11f_unpack_ie_fh_params( + pCtx, pBufRemaining, len, + (tDot11fIEFHParams *) + (pFrm + pIe->offset + + sizeof(tDot11fIEFHParams) * + countOffset)); + break; + case SigIeFHPattTable: + status |= + dot11f_unpack_ie_fh_patt_table( + pCtx, pBufRemaining, len, + (tDot11fIEFHPattTable *) + (pFrm + pIe->offset + + sizeof(tDot11fIEFHPattTable) * + countOffset)); + break; + case SigIeFTInfo: + status |= + dot11f_unpack_ie_ft_info( + pCtx, pBufRemaining, len, + (tDot11fIEFTInfo *) + (pFrm + pIe->offset + + sizeof(tDot11fIEFTInfo) * + countOffset)); + break; + case SigIeHTCaps: + status |= + dot11f_unpack_ie_ht_caps( + pCtx, pBufRemaining, len, + (tDot11fIEHTCaps *) + (pFrm + pIe->offset + + sizeof(tDot11fIEHTCaps) * + countOffset)); + break; + case SigIeHTInfo: + status |= + dot11f_unpack_ie_ht_info( + pCtx, pBufRemaining, len, + (tDot11fIEHTInfo *) + (pFrm + pIe->offset + + sizeof(tDot11fIEHTInfo) * + countOffset)); + break; + case SigIeIBSSParams: + status |= + dot11f_unpack_ie_ibss_params( + pCtx, pBufRemaining, len, + (tDot11fIEIBSSParams *) + (pFrm + pIe->offset + + sizeof(tDot11fIEIBSSParams) * + countOffset)); + break; + case SigIeLinkIdentifier: + status |= + dot11f_unpack_ie_link_identifier( + pCtx, pBufRemaining, len, + (tDot11fIELinkIdentifier *) + (pFrm + pIe->offset + + sizeof(tDot11fIELinkIdentifier) * + countOffset)); + break; + case SigIeMeasurementReport: + status |= + dot11f_unpack_ie_measurement_report( + pCtx, pBufRemaining, len, + (tDot11fIEMeasurementReport *) + (pFrm + pIe->offset + + sizeof(tDot11fIEMeasurementReport) * + countOffset)); + break; + case SigIeMeasurementRequest: + status |= + dot11f_unpack_ie_measurement_request( + pCtx, pBufRemaining, len, + (tDot11fIEMeasurementRequest *) + (pFrm + pIe->offset + + sizeof(tDot11fIEMeasurementRequest) * + countOffset)); + break; + case SigIeMobilityDomain: + status |= + dot11f_unpack_ie_mobility_domain( + pCtx, pBufRemaining, len, + (tDot11fIEMobilityDomain *) + (pFrm + pIe->offset + + sizeof(tDot11fIEMobilityDomain) * + countOffset)); + break; + case SigIeNeighborReport: + if (countOffset < MAX_SUPPORTED_NEIGHBOR_RPT) { + status |= + dot11f_unpack_ie_neighbor_report( + pCtx, pBufRemaining, len, + (tDot11fIENeighborReport *) + (pFrm + pIe->offset + + sizeof(tDot11fIENeighborReport) * + countOffset)); + } else { + status |= DOT11F_BUFFER_OVERFLOW; + } + break; + case SigIeOBSSScanParameters: + status |= + dot11f_unpack_ie_obss_scan_parameters( + pCtx, pBufRemaining, len, + (tDot11fIEOBSSScanParameters *) + (pFrm + pIe->offset + + sizeof(tDot11fIEOBSSScanParameters) * + countOffset)); + break; + case SigIeOperatingMode: + status |= + dot11f_unpack_ie_operating_mode( + pCtx, pBufRemaining, len, + (tDot11fIEOperatingMode *) + (pFrm + pIe->offset + + sizeof(tDot11fIEOperatingMode) * + countOffset)); + break; + case SigIeP2PAssocReq: + status |= + dot11f_unpack_ie_p2_p_assoc_req( + pCtx, pBufRemaining, len, + (tDot11fIEP2PAssocReq *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PAssocReq) * + countOffset)); + break; + case SigIeP2PAssocRes: + status |= + dot11f_unpack_ie_p2_p_assoc_res( + pCtx, pBufRemaining, len, + (tDot11fIEP2PAssocRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PAssocRes) * + countOffset)); + break; + case SigIeP2PBeacon: + status |= + dot11f_unpack_ie_p2_p_beacon( + pCtx, pBufRemaining, len, + (tDot11fIEP2PBeacon *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PBeacon) * + countOffset)); + break; + case SigIeP2PBeaconProbeRes: + status |= + dot11f_unpack_ie_p2_p_beacon_probe_res( + pCtx, pBufRemaining, len, + (tDot11fIEP2PBeaconProbeRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PBeaconProbeRes) * + countOffset)); + break; + case SigIeP2PDeAuth: + status |= + dot11f_unpack_ie_p2_p_de_auth( + pCtx, pBufRemaining, len, + (tDot11fIEP2PDeAuth *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PDeAuth) * + countOffset)); + break; + case SigIeP2PDisAssoc: + status |= + dot11f_unpack_ie_p2_p_dis_assoc( + pCtx, pBufRemaining, len, + (tDot11fIEP2PDisAssoc *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PDisAssoc) * + countOffset)); + break; + case SigIeP2PIEOpaque: + status |= + dot11f_unpack_ie_p2_pie_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEP2PIEOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PIEOpaque) * + countOffset)); + break; + case SigIeP2PProbeReq: + status |= + dot11f_unpack_ie_p2_p_probe_req( + pCtx, pBufRemaining, len, + (tDot11fIEP2PProbeReq *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PProbeReq) * + countOffset)); + break; + case SigIeP2PProbeRes: + status |= + dot11f_unpack_ie_p2_p_probe_res( + pCtx, pBufRemaining, len, + (tDot11fIEP2PProbeRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEP2PProbeRes) * + countOffset)); + break; + case SigIePTIControl: + status |= + dot11f_unpack_ie_pti_control( + pCtx, pBufRemaining, len, + (tDot11fIEPTIControl *) + (pFrm + pIe->offset + + sizeof(tDot11fIEPTIControl) * + countOffset)); + break; + case SigIePUBufferStatus: + status |= + dot11f_unpack_ie_pu_buffer_status( + pCtx, pBufRemaining, len, + (tDot11fIEPUBufferStatus *) + (pFrm + pIe->offset + + sizeof(tDot11fIEPUBufferStatus) * + countOffset)); + break; + case SigIePowerCaps: + status |= + dot11f_unpack_ie_power_caps( + pCtx, pBufRemaining, len, + (tDot11fIEPowerCaps *) + (pFrm + pIe->offset + + sizeof(tDot11fIEPowerCaps) * + countOffset)); + break; + case SigIePowerConstraints: + status |= + dot11f_unpack_ie_power_constraints( + pCtx, pBufRemaining, len, + (tDot11fIEPowerConstraints *) + (pFrm + pIe->offset + + sizeof(tDot11fIEPowerConstraints) * + countOffset)); + break; + case SigIeQBSSLoad: + status |= + dot11f_unpack_ie_qbss_load( + pCtx, pBufRemaining, len, + (tDot11fIEQBSSLoad *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQBSSLoad) * + countOffset)); + break; + case SigIeQComVendorIE: + status |= + dot11f_unpack_ie_QComVendorIE( + pCtx, pBufRemaining, len, + (tDot11fIEQComVendorIE *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQComVendorIE) * + countOffset)); + break; + case SigIeQOSCapsAp: + status |= + dot11f_unpack_ie_qos_caps_ap( + pCtx, pBufRemaining, len, + (tDot11fIEQOSCapsAp *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQOSCapsAp) * + countOffset)); + break; + case SigIeQOSCapsStation: + status |= + dot11f_unpack_ie_qos_caps_station( + pCtx, pBufRemaining, len, + (tDot11fIEQOSCapsStation *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQOSCapsStation) * + countOffset)); + break; + case SigIeQosMapSet: + status |= + dot11f_unpack_ie_qos_map_set( + pCtx, pBufRemaining, len, + (tDot11fIEQosMapSet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQosMapSet) * + countOffset)); + break; + case SigIeQuiet: + status |= + dot11f_unpack_ie_quiet( + pCtx, pBufRemaining, len, + (tDot11fIEQuiet *) + (pFrm + pIe->offset + + sizeof(tDot11fIEQuiet) * + countOffset)); + break; + case SigIeRCPIIE: + status |= + dot11f_unpack_ie_rcpiie( + 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 |= get_container_ies_len(pCtx, pBufRemaining, nBufRemaining, &len, IES_RICDataDesc); + if (status != DOT11F_PARSE_SUCCESS && status != DOT11F_UNKNOWN_IES) + break; + status |= + dot11f_unpack_ie_ric_data_desc( + pCtx, pBufRemaining, len, + (tDot11fIERICDataDesc *) + (pFrm + pIe->offset + + sizeof(tDot11fIERICDataDesc) * + countOffset)); + break; + case SigIeRSN: + status |= + dot11f_unpack_ie_rsn( + pCtx, pBufRemaining, len, + (tDot11fIERSN *) + (pFrm + pIe->offset + + sizeof(tDot11fIERSN) * + countOffset)); + break; + case SigIeRSNIIE: + status |= + dot11f_unpack_ie_rsniie( + pCtx, pBufRemaining, len, + (tDot11fIERSNIIE *) + (pFrm + pIe->offset + + sizeof(tDot11fIERSNIIE) * + countOffset)); + break; + case SigIeRSNOpaque: + status |= + dot11f_unpack_ie_rsn_opaque( + pCtx, pBufRemaining, len, + (tDot11fIERSNOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIERSNOpaque) * + countOffset)); + break; + case SigIeSuppChannels: + status |= + dot11f_unpack_ie_supp_channels( + pCtx, pBufRemaining, len, + (tDot11fIESuppChannels *) + (pFrm + pIe->offset + + sizeof(tDot11fIESuppChannels) * + countOffset)); + break; + case SigIeSuppOperatingClasses: + status |= + dot11f_unpack_ie_supp_operating_classes( + pCtx, pBufRemaining, len, + (tDot11fIESuppOperatingClasses *) + (pFrm + pIe->offset + + sizeof(tDot11fIESuppOperatingClasses) * + countOffset)); + break; + case SigIeSuppRates: + status |= + dot11f_unpack_ie_supp_rates( + pCtx, pBufRemaining, len, + (tDot11fIESuppRates *) + (pFrm + pIe->offset + + sizeof(tDot11fIESuppRates) * + countOffset)); + break; + case SigIeTIM: + status |= + dot11f_unpack_ie_tim( + pCtx, pBufRemaining, len, + (tDot11fIETIM *) + (pFrm + pIe->offset + + sizeof(tDot11fIETIM) * + countOffset)); + break; + case SigIeTPCReport: + status |= + dot11f_unpack_ie_tpc_report( + pCtx, pBufRemaining, len, + (tDot11fIETPCReport *) + (pFrm + pIe->offset + + sizeof(tDot11fIETPCReport) * + countOffset)); + break; + case SigIeTPCRequest: + status |= + dot11f_unpack_ie_tpc_request( + pCtx, pBufRemaining, len, + (tDot11fIETPCRequest *) + (pFrm + pIe->offset + + sizeof(tDot11fIETPCRequest) * + countOffset)); + break; + case SigIeTimeAdvertisement: + status |= + dot11f_unpack_ie_time_advertisement( + pCtx, pBufRemaining, len, + (tDot11fIETimeAdvertisement *) + (pFrm + pIe->offset + + sizeof(tDot11fIETimeAdvertisement) * + countOffset)); + break; + case SigIeTimeoutInterval: + status |= + dot11f_unpack_ie_timeout_interval( + pCtx, pBufRemaining, len, + (tDot11fIETimeoutInterval *) + (pFrm + pIe->offset + + sizeof(tDot11fIETimeoutInterval) * + countOffset)); + break; + case SigIeVHTExtBssLoad: + status |= + dot11f_unpack_ie_vht_ext_bss_load( + pCtx, pBufRemaining, len, + (tDot11fIEVHTExtBssLoad *) + (pFrm + pIe->offset + + sizeof(tDot11fIEVHTExtBssLoad) * + countOffset)); + break; + case SigIeVendor1IE: + status |= + dot11f_unpack_ie_vendor1_ie( + pCtx, pBufRemaining, len, + (tDot11fIEVendor1IE *) + (pFrm + pIe->offset + + sizeof(tDot11fIEVendor1IE) * + countOffset)); + break; + case SigIeVendor3IE: + status |= + dot11f_unpack_ie_vendor3_ie( + pCtx, pBufRemaining, len, + (tDot11fIEVendor3IE *) + (pFrm + pIe->offset + + sizeof(tDot11fIEVendor3IE) * + countOffset)); + break; + case SigIeWAPI: + status |= + dot11f_unpack_ie_wapi( + pCtx, pBufRemaining, len, + (tDot11fIEWAPI *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWAPI) * + countOffset)); + break; + case SigIeWAPIOpaque: + status |= + dot11f_unpack_ie_wapi_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEWAPIOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWAPIOpaque) * + countOffset)); + break; + case SigIeWFATPC: + status |= + dot11f_unpack_ie_wfatpc( + pCtx, pBufRemaining, len, + (tDot11fIEWFATPC *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWFATPC) * + countOffset)); + break; + case SigIeWFDIEOpaque: + status |= + dot11f_unpack_ie_wfdie_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEWFDIEOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWFDIEOpaque) * + countOffset)); + break; + case SigIeWMMCaps: + status |= + dot11f_unpack_ie_wmm_caps( + pCtx, pBufRemaining, len, + (tDot11fIEWMMCaps *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMCaps) * + countOffset)); + break; + case SigIeWMMInfoAp: + status |= + dot11f_unpack_ie_wmm_info_ap( + pCtx, pBufRemaining, len, + (tDot11fIEWMMInfoAp *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMInfoAp) * + countOffset)); + break; + case SigIeWMMInfoStation: + status |= + dot11f_unpack_ie_wmm_info_station( + pCtx, pBufRemaining, len, + (tDot11fIEWMMInfoStation *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMInfoStation) * + countOffset)); + break; + case SigIeWMMParams: + status |= + dot11f_unpack_ie_wmm_params( + pCtx, pBufRemaining, len, + (tDot11fIEWMMParams *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWMMParams) * + countOffset)); + break; + case SigIeWPA: + status |= + dot11f_unpack_ie_wpa( + pCtx, pBufRemaining, len, + (tDot11fIEWPA *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWPA) * + countOffset)); + break; + case SigIeWPAOpaque: + status |= + dot11f_unpack_ie_wpa_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEWPAOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWPAOpaque) * + countOffset)); + break; + case SigIeWSC: + status |= + dot11f_unpack_ie_wsc( + pCtx, pBufRemaining, len, + (tDot11fIEWSC *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWSC) * + countOffset)); + break; + case SigIeWscAssocReq: + status |= + dot11f_unpack_ie_wsc_assoc_req( + pCtx, pBufRemaining, len, + (tDot11fIEWscAssocReq *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscAssocReq) * + countOffset)); + break; + case SigIeWscAssocRes: + status |= + dot11f_unpack_ie_wsc_assoc_res( + pCtx, pBufRemaining, len, + (tDot11fIEWscAssocRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscAssocRes) * + countOffset)); + break; + case SigIeWscBeacon: + status |= + dot11f_unpack_ie_wsc_beacon( + pCtx, pBufRemaining, len, + (tDot11fIEWscBeacon *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscBeacon) * + countOffset)); + break; + case SigIeWscBeaconProbeRes: + status |= + dot11f_unpack_ie_wsc_beacon_probe_res( + pCtx, pBufRemaining, len, + (tDot11fIEWscBeaconProbeRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscBeaconProbeRes) * + countOffset)); + break; + case SigIeWscIEOpaque: + status |= + dot11f_unpack_ie_wsc_ie_opaque( + pCtx, pBufRemaining, len, + (tDot11fIEWscIEOpaque *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscIEOpaque) * + countOffset)); + break; + case SigIeWscProbeReq: + status |= + dot11f_unpack_ie_wsc_probe_req( + pCtx, pBufRemaining, len, + (tDot11fIEWscProbeReq *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscProbeReq) * + countOffset)); + break; + case SigIeWscProbeRes: + status |= + dot11f_unpack_ie_wsc_probe_res( + pCtx, pBufRemaining, len, + (tDot11fIEWscProbeRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscProbeRes) * + countOffset)); + break; + case SigIeWscReassocRes: + status |= + dot11f_unpack_ie_wsc_reassoc_res( + pCtx, pBufRemaining, len, + (tDot11fIEWscReassocRes *) + (pFrm + pIe->offset + + sizeof(tDot11fIEWscReassocRes) * + countOffset)); + break; + case SigIeext_chan_switch_ann: + status |= + dot11f_unpack_ie_ext_chan_switch_ann( + pCtx, pBufRemaining, len, + (tDot11fIEext_chan_switch_ann *) + (pFrm + pIe->offset + + sizeof(tDot11fIEext_chan_switch_ann) * + countOffset)); + break; + case SigIeht2040_bss_coexistence: + status |= + dot11f_unpack_ie_ht2040_bss_coexistence( + pCtx, pBufRemaining, len, + (tDot11fIEht2040_bss_coexistence *) + (pFrm + pIe->offset + + sizeof(tDot11fIEht2040_bss_coexistence) * + countOffset)); + break; + case SigIeht2040_bss_intolerant_report: + status |= + dot11f_unpack_ie_ht2040_bss_intolerant_report( + pCtx, pBufRemaining, len, + (tDot11fIEht2040_bss_intolerant_report *) + (pFrm + pIe->offset + + sizeof(tDot11fIEht2040_bss_intolerant_report) * + countOffset)); + break; + case SigIesec_chan_offset_ele: + status |= + dot11f_unpack_ie_sec_chan_offset_ele( + pCtx, pBufRemaining, len, + (tDot11fIEsec_chan_offset_ele *) + (pFrm + pIe->offset + + sizeof(tDot11fIEsec_chan_offset_ele) * + countOffset)); + break; + case SigIevendor2_ie: + status |= + dot11f_unpack_ie_vendor2_ie( + pCtx, pBufRemaining, len, + (tDot11fIEvendor2_ie *) + (pFrm + pIe->offset + + sizeof(tDot11fIEvendor2_ie) * + 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) + (++(*(uint16_t *)(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 unpack_core. */ + +static uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pBuf, + uint32_t nBuf, + const tTLVDefn TLVs[], + uint8_t *pFrm, + size_t nFrm) +{ + const tTLVDefn *pTlv; + uint32_t nBufRemaining, status, npec; + uint16_t id, len; + uint8_t *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 = find_tlv_defn(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 |= + dot11f_unpack_tlv_authorized_ma_cs(pCtx, + pBufRemaining, len, + (tDot11fTLVAuthorizedMACs *) + (pFrm + pTlv->offset)); + break; + case SigTlvRequestToEnroll: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVRequestToEnroll *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVRequestToEnroll *) + (pFrm + pTlv->offset))->req)); + break; + case SigTlvVersion2: + status |= + dot11f_unpack_tlv_version2(pCtx, + pBufRemaining, len, + (tDot11fTLVVersion2 *) + (pFrm + pTlv->offset)); + break; + case SigTlvAPSetupLocked: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVAPSetupLocked *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVAPSetupLocked *) + (pFrm + pTlv->offset))->fLocked)); + break; + case SigTlvAssociationState: + status |= + dot11f_unpack_tlv_common_func2(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVAssociationState *) + (pFrm + pTlv->offset))->present), + (uint16_t *)&(((tDot11fTLVAssociationState *) + (pFrm + pTlv->offset))->state)); + break; + case SigTlvConfigMethods: + status |= + dot11f_unpack_tlv_common_func2(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVConfigMethods *) + (pFrm + pTlv->offset))->present), + (uint16_t *)&(((tDot11fTLVConfigMethods *) + (pFrm + pTlv->offset))->methods)); + break; + case SigTlvConfigurationError: + status |= + dot11f_unpack_tlv_common_func2(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVConfigurationError *) + (pFrm + pTlv->offset))->present), + (uint16_t *)&(((tDot11fTLVConfigurationError *) + (pFrm + pTlv->offset))->error)); + break; + case SigTlvDeviceName: + status |= + dot11f_unpack_tlv_device_name(pCtx, + pBufRemaining, len, + (tDot11fTLVDeviceName *) + (pFrm + pTlv->offset)); + break; + case SigTlvDevicePasswordID: + status |= + dot11f_unpack_tlv_common_func2(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVDevicePasswordID *) + (pFrm + pTlv->offset))->present), + (uint16_t *)&(((tDot11fTLVDevicePasswordID *) + (pFrm + pTlv->offset))->id)); + break; + case SigTlvExtendedListenTiming: + status |= + dot11f_unpack_tlv_extended_listen_timing(pCtx, + pBufRemaining, len, + (tDot11fTLVExtendedListenTiming *) + (pFrm + pTlv->offset)); + break; + case SigTlvListenChannel: + status |= + dot11f_unpack_tlv_listen_channel(pCtx, + pBufRemaining, len, + (tDot11fTLVListenChannel *) + (pFrm + pTlv->offset)); + break; + case SigTlvManufacturer: + status |= + dot11f_unpack_tlv_manufacturer(pCtx, + pBufRemaining, len, + (tDot11fTLVManufacturer *) + (pFrm + pTlv->offset)); + break; + case SigTlvMinorReasonCode: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVMinorReasonCode *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVMinorReasonCode *) + (pFrm + pTlv->offset))->minorReasonCode)); + break; + case SigTlvModelName: + status |= + dot11f_unpack_tlv_model_name(pCtx, + pBufRemaining, len, + (tDot11fTLVModelName *) + (pFrm + pTlv->offset)); + break; + case SigTlvModelNumber: + status |= + dot11f_unpack_tlv_model_number(pCtx, + pBufRemaining, len, + (tDot11fTLVModelNumber *) + (pFrm + pTlv->offset)); + break; + case SigTlvNoticeOfAbsence: + status |= + dot11f_unpack_tlv_notice_of_absence(pCtx, + pBufRemaining, len, + (tDot11fTLVNoticeOfAbsence *) + (pFrm + pTlv->offset)); + break; + case SigTlvOperatingChannel: + status |= + dot11f_unpack_tlv_operating_channel(pCtx, + pBufRemaining, len, + (tDot11fTLVOperatingChannel *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PCapability: + status |= + dot11f_unpack_tlv_p2_p_capability(pCtx, + pBufRemaining, len, + (tDot11fTLVP2PCapability *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PDeviceId: + status |= + dot11f_unpack_tlv_p2_p_device_id(pCtx, + pBufRemaining, len, + (tDot11fTLVP2PDeviceId *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PDeviceInfo: + status |= + dot11f_unpack_tlv_p2_p_device_info(pCtx, + pBufRemaining, len, + (tDot11fTLVP2PDeviceInfo *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PGroupInfo: + status |= + dot11f_unpack_tlv_p2_p_group_info(pCtx, + pBufRemaining, len, + (tDot11fTLVP2PGroupInfo *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PStatus: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVP2PStatus *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVP2PStatus *) + (pFrm + pTlv->offset))->status)); + break; + case SigTlvPrimaryDeviceType: + status |= + dot11f_unpack_tlv_primary_device_type(pCtx, + pBufRemaining, len, + (tDot11fTLVPrimaryDeviceType *) + (pFrm + pTlv->offset)); + break; + case SigTlvRFBands: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVRFBands *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVRFBands *) + (pFrm + pTlv->offset))->bands)); + break; + case SigTlvRequestDeviceType: + status |= + dot11f_unpack_tlv_request_device_type(pCtx, + pBufRemaining, len, + (tDot11fTLVRequestDeviceType *) + (pFrm + pTlv->offset)); + break; + case SigTlvRequestType: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVRequestType *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVRequestType *) + (pFrm + pTlv->offset))->reqType)); + break; + case SigTlvResponseType: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVResponseType *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVResponseType *) + (pFrm + pTlv->offset))->resType)); + break; + case SigTlvSelectedRegistrar: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVSelectedRegistrar *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVSelectedRegistrar *) + (pFrm + pTlv->offset))->selected)); + break; + case SigTlvSelectedRegistrarConfigMethods: + status |= + dot11f_unpack_tlv_common_func2(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVSelectedRegistrarConfigMethods *) + (pFrm + pTlv->offset))->present), + (uint16_t *)&(((tDot11fTLVSelectedRegistrarConfigMethods *) + (pFrm + pTlv->offset))->methods)); + break; + case SigTlvSerialNumber: + status |= + dot11f_unpack_tlv_serial_number(pCtx, + pBufRemaining, len, + (tDot11fTLVSerialNumber *) + (pFrm + pTlv->offset)); + break; + case SigTlvUUID_E: + status |= + dot11f_unpack_tlv_uuid_e(pCtx, + pBufRemaining, len, + (tDot11fTLVUUID_E *) + (pFrm + pTlv->offset)); + break; + case SigTlvUUID_R: + status |= + dot11f_unpack_tlv_uuid_r(pCtx, + pBufRemaining, len, + (tDot11fTLVUUID_R *) + (pFrm + pTlv->offset)); + break; + case SigTlvVendorExtension: + status |= + dot11f_unpack_tlv_vendor_extension(pCtx, + pBufRemaining, len, + (tDot11fTLVVendorExtension *) + (pFrm + pTlv->offset)); + break; + case SigTlvVersion: + status |= + dot11f_unpack_tlv_version(pCtx, + pBufRemaining, len, + (tDot11fTLVVersion *) + (pFrm + pTlv->offset)); + break; + case SigTlvWPSState: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVWPSState *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((tDot11fTLVWPSState *) + (pFrm + pTlv->offset))->state)); + break; + case SigTlvP2PInterface: + status |= + dot11f_unpack_tlv_p2_p_interface(pCtx, + pBufRemaining, len, + (tDot11fTLVP2PInterface *) + (pFrm + pTlv->offset)); + break; + case SigTlvP2PManageability: + status |= + dot11f_unpack_tlv_common_func(pCtx, + pBufRemaining, len, + (uint8_t *)&(((tDot11fTLVP2PManageability *) + (pFrm + pTlv->offset))->present), + (uint8_t *)&(((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 = (uint8_t *)(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. */ +uint32_t dot11f_get_packed_ietclas(tpAniSirGlobal pCtx, + tDot11fIETCLAS *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_ietclas. */ + +uint32_t dot11f_get_packed_iewmmtclas(tpAniSirGlobal pCtx, + tDot11fIEWMMTCLAS *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_iewmmtclas. */ + +uint32_t dot11f_get_packed_ie_channel_switch_wrapper(tpAniSirGlobal pCtx, + tDot11fIEChannelSwitchWrapper *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, + IES_ChannelSwitchWrapper); + break; + } + return status; +} /* End dot11f_get_packed_ie_channel_switch_wrapper. */ + +uint32_t dot11f_get_packed_ie_country(tpAniSirGlobal pCtx, + tDot11fIECountry *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_ie_country. */ + +uint32_t dot11f_get_packed_ieft_info(tpAniSirGlobal pCtx, + tDot11fIEFTInfo *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + *pnNeeded += 2; + *pnNeeded += 16; + *pnNeeded += 32; + *pnNeeded += 32; + status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, + IES_FTInfo); + break; + } + return status; +} /* End dot11f_get_packed_ieft_info. */ + +uint32_t dot11f_get_packed_ie_measurement_report(tpAniSirGlobal pCtx, + tDot11fIEMeasurementReport *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, IES_reportBeacon); + break; + } + } else { + break; + } + break; + } + return status; +} /* End dot11f_get_packed_ie_measurement_report. */ + +uint32_t dot11f_get_packed_ie_measurement_request(tpAniSirGlobal pCtx, + tDot11fIEMeasurementRequest *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, IES_measurement_requestBeacon); + break; + } + break; + } + return status; +} /* End dot11f_get_packed_ie_measurement_request. */ + +uint32_t dot11f_get_packed_ie_neighbor_report(tpAniSirGlobal pCtx, + tDot11fIENeighborReport *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + *pnNeeded += 6; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 2; + *pnNeeded += 1; + *pnNeeded += 1; + *pnNeeded += 1; + status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, + IES_NeighborReport); + break; + } + return status; +} /* End dot11f_get_packed_ie_neighbor_report. */ + +uint32_t dot11f_get_packed_iep2_p_assoc_req(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocReq *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PAssocReq); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_assoc_req. */ + +uint32_t dot11f_get_packed_iep2_p_assoc_res(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PAssocRes); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_assoc_res. */ + +uint32_t dot11f_get_packed_iep2_p_beacon(tpAniSirGlobal pCtx, + tDot11fIEP2PBeacon *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PBeacon); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_beacon. */ + +uint32_t dot11f_get_packed_iep2_p_beacon_probe_res(tpAniSirGlobal pCtx, + tDot11fIEP2PBeaconProbeRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PBeaconProbeRes); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_beacon_probe_res. */ + +uint32_t dot11f_get_packed_iep2_p_de_auth(tpAniSirGlobal pCtx, + tDot11fIEP2PDeAuth *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PDeAuth); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_de_auth. */ + +uint32_t dot11f_get_packed_iep2_p_dis_assoc(tpAniSirGlobal pCtx, + tDot11fIEP2PDisAssoc *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PDisAssoc); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_dis_assoc. */ + +uint32_t dot11f_get_packed_iep2_p_probe_req(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeReq *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PProbeReq); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_probe_req. */ + +uint32_t dot11f_get_packed_iep2_p_probe_res(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_P2PProbeRes); + break; + } + return status; +} /* End dot11f_get_packed_iep2_p_probe_res. */ + +uint32_t dot11f_get_packed_ieric_data_desc(tpAniSirGlobal pCtx, + tDot11fIERICDataDesc *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, + IES_RICDataDesc); + break; + } + return status; +} /* End dot11f_get_packed_ieric_data_desc. */ + +uint32_t dot11f_get_packed_iersn(tpAniSirGlobal pCtx, + tDot11fIERSN *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_iersn. */ + +uint32_t dot11f_get_packed_iewapi(tpAniSirGlobal pCtx, + tDot11fIEWAPI *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_iewapi. */ + +uint32_t dot11f_get_packed_iewpa(tpAniSirGlobal pCtx, + tDot11fIEWPA *pIe, uint32_t *pnNeeded) +{ + uint32_t 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 dot11f_get_packed_iewpa. */ + +uint32_t dot11f_get_packed_iewsc(tpAniSirGlobal pCtx, + tDot11fIEWSC *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WSC); + break; + } + return status; +} /* End dot11f_get_packed_iewsc. */ + +uint32_t dot11f_get_packed_ie_wsc_assoc_req(tpAniSirGlobal pCtx, + tDot11fIEWscAssocReq *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscAssocReq); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_assoc_req. */ + +uint32_t dot11f_get_packed_ie_wsc_assoc_res(tpAniSirGlobal pCtx, + tDot11fIEWscAssocRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscAssocRes); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_assoc_res. */ + +uint32_t dot11f_get_packed_ie_wsc_beacon(tpAniSirGlobal pCtx, + tDot11fIEWscBeacon *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscBeacon); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_beacon. */ + +uint32_t dot11f_get_packed_ie_wsc_beacon_probe_res(tpAniSirGlobal pCtx, + tDot11fIEWscBeaconProbeRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscBeaconProbeRes); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_beacon_probe_res. */ + +uint32_t dot11f_get_packed_ie_wsc_probe_req(tpAniSirGlobal pCtx, + tDot11fIEWscProbeReq *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscProbeReq); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_probe_req. */ + +uint32_t dot11f_get_packed_ie_wsc_probe_res(tpAniSirGlobal pCtx, + tDot11fIEWscProbeRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscProbeRes); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_probe_res. */ + +uint32_t dot11f_get_packed_ie_wsc_reassoc_res(tpAniSirGlobal pCtx, + tDot11fIEWscReassocRes *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + status = get_packed_size_tlv_core(pCtx, (uint8_t *)pIe, pnNeeded, + TLVS_WscReassocRes); + break; + } + return status; +} /* End dot11f_get_packed_ie_wsc_reassoc_res. */ + +uint32_t dot11f_get_packed_ie_vendor2_ie(tpAniSirGlobal pCtx, + tDot11fIEvendor2_ie *pIe, uint32_t *pnNeeded) +{ + uint32_t status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while (pIe->present) { + *pnNeeded += 1; + *pnNeeded += 1; + status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, + IES_vendor2_ie); + break; + } + return status; +} /* End dot11f_get_packed_ie_vendor2_ie. */ + +uint32_t dot11f_get_packed_add_ts_request_size(tpAniSirGlobal pCtx, + tDot11fAddTSRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_AddTSRequest); + return status; +} /* End dot11f_get_packed_add_ts_request_size. */ + +uint32_t dot11f_get_packed_add_ts_response_size(tpAniSirGlobal pCtx, + tDot11fAddTSResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_AddTSResponse); + return status; +} /* End dot11f_get_packed_add_ts_response_size. */ + +uint32_t dot11f_get_packed_assoc_request_size(tpAniSirGlobal pCtx, + tDot11fAssocRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_AssocRequest); + return status; +} /* End dot11f_get_packed_assoc_request_size. */ + +uint32_t dot11f_get_packed_assoc_response_size(tpAniSirGlobal pCtx, + tDot11fAssocResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 6; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_AssocResponse); + return status; +} /* End dot11f_get_packed_assoc_response_size. */ + +uint32_t dot11f_get_packed_authentication_size(tpAniSirGlobal pCtx, + tDot11fAuthentication *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 6; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_Authentication); + return status; +} /* End dot11f_get_packed_authentication_size. */ + +uint32_t dot11f_get_packed_beacon_size(tpAniSirGlobal pCtx, + tDot11fBeacon *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 12; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_Beacon); + return status; +} /* End dot11f_get_packed_beacon_size. */ + +uint32_t dot11f_get_packed_beacon1_size(tpAniSirGlobal pCtx, + tDot11fBeacon1 *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 12; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_Beacon1); + return status; +} /* End dot11f_get_packed_beacon1_size. */ + +uint32_t dot11f_get_packed_beacon2_size(tpAniSirGlobal pCtx, + tDot11fBeacon2 *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 0; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_Beacon2); + return status; +} /* End dot11f_get_packed_beacon2_size. */ + +uint32_t dot11f_get_packed_beacon_i_es_size(tpAniSirGlobal pCtx, + tDot11fBeaconIEs *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 0; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_BeaconIEs); + return status; +} /* End dot11f_get_packed_beacon_i_es_size. */ + +uint32_t dot11f_get_packed_channel_switch_size(tpAniSirGlobal pCtx, + tDot11fChannelSwitch *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 2; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ChannelSwitch); + return status; +} /* End dot11f_get_packed_channel_switch_size. */ + +uint32_t dot11f_get_packed_de_auth_size(tpAniSirGlobal pCtx, + tDot11fDeAuth *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 2; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_DeAuth); + return status; +} /* End dot11f_get_packed_de_auth_size. */ + +uint32_t dot11f_get_packed_del_ts_size(tpAniSirGlobal pCtx, + tDot11fDelTS *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 7; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_DelTS); + return status; +} /* End dot11f_get_packed_del_ts_size. */ + +uint32_t dot11f_get_packed_disassociation_size(tpAniSirGlobal pCtx, + tDot11fDisassociation *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 2; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_Disassociation); + return status; +} /* End dot11f_get_packed_disassociation_size. */ + +uint32_t dot11f_get_packed_link_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementReport *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 11; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_LinkMeasurementReport); + return status; +} /* End dot11f_get_packed_link_measurement_report_size. */ + +uint32_t dot11f_get_packed_link_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_LinkMeasurementRequest); + return status; +} /* End dot11f_get_packed_link_measurement_request_size. */ + +uint32_t dot11f_get_packed_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fMeasurementReport *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_MeasurementReport); + return status; +} /* End dot11f_get_packed_measurement_report_size. */ + +uint32_t dot11f_get_packed_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fMeasurementRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_MeasurementRequest); + return status; +} /* End dot11f_get_packed_measurement_request_size. */ + +uint32_t dot11f_get_packed_neighbor_report_request_size(tpAniSirGlobal pCtx, + tDot11fNeighborReportRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_NeighborReportRequest); + return status; +} /* End dot11f_get_packed_neighbor_report_request_size. */ + +uint32_t dot11f_get_packed_neighbor_report_response_size(tpAniSirGlobal pCtx, + tDot11fNeighborReportResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_NeighborReportResponse); + return status; +} /* End dot11f_get_packed_neighbor_report_response_size. */ + +uint32_t dot11f_get_packed_operating_mode_size(tpAniSirGlobal pCtx, + tDot11fOperatingMode *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_OperatingMode); + return status; +} /* End dot11f_get_packed_operating_mode_size. */ + +uint32_t dot11f_get_packed_probe_request_size(tpAniSirGlobal pCtx, + tDot11fProbeRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 0; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ProbeRequest); + return status; +} /* End dot11f_get_packed_probe_request_size. */ + +uint32_t dot11f_get_packed_probe_response_size(tpAniSirGlobal pCtx, + tDot11fProbeResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 12; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ProbeResponse); + return status; +} /* End dot11f_get_packed_probe_response_size. */ + +uint32_t dot11f_get_packed_qos_map_configure_size(tpAniSirGlobal pCtx, + tDot11fQosMapConfigure *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 2; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_QosMapConfigure); + return status; +} /* End dot11f_get_packed_qos_map_configure_size. */ + +uint32_t dot11f_get_packed_radio_measurement_report_size(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementReport *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_RadioMeasurementReport); + return status; +} /* End dot11f_get_packed_radio_measurement_report_size. */ + +uint32_t dot11f_get_packed_radio_measurement_request_size(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_RadioMeasurementRequest); + return status; +} /* End dot11f_get_packed_radio_measurement_request_size. */ + +uint32_t dot11f_get_packed_re_assoc_request_size(tpAniSirGlobal pCtx, + tDot11fReAssocRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 10; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ReAssocRequest); + return status; +} /* End dot11f_get_packed_re_assoc_request_size. */ + +uint32_t dot11f_get_packed_re_assoc_response_size(tpAniSirGlobal pCtx, + tDot11fReAssocResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 6; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ReAssocResponse); + return status; +} /* End dot11f_get_packed_re_assoc_response_size. */ + +uint32_t dot11f_get_packed_sm_power_save_size(tpAniSirGlobal pCtx, + tDot11fSMPowerSave *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_SMPowerSave); + return status; +} /* End dot11f_get_packed_sm_power_save_size. */ + +uint32_t dot11f_get_packed_sa_query_req_size(tpAniSirGlobal pCtx, + tDot11fSaQueryReq *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_SaQueryReq); + return status; +} /* End dot11f_get_packed_sa_query_req_size. */ + +uint32_t dot11f_get_packed_sa_query_rsp_size(tpAniSirGlobal pCtx, + tDot11fSaQueryRsp *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_SaQueryRsp); + return status; +} /* End dot11f_get_packed_sa_query_rsp_size. */ + +uint32_t dot11f_get_packed_tdls_dis_req_size(tpAniSirGlobal pCtx, + tDot11fTDLSDisReq *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSDisReq); + return status; +} /* End dot11f_get_packed_tdls_dis_req_size. */ + +uint32_t dot11f_get_packed_tdls_dis_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSDisRsp *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSDisRsp); + return status; +} /* End dot11f_get_packed_tdls_dis_rsp_size. */ + +uint32_t dot11f_get_packed_tdls_peer_traffic_ind_size(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficInd *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSPeerTrafficInd); + return status; +} /* End dot11f_get_packed_tdls_peer_traffic_ind_size. */ + +uint32_t dot11f_get_packed_tdls_peer_traffic_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficRsp *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSPeerTrafficRsp); + return status; +} /* End dot11f_get_packed_tdls_peer_traffic_rsp_size. */ + +uint32_t dot11f_get_packed_tdls_setup_cnf_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupCnf *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSSetupCnf); + return status; +} /* End dot11f_get_packed_tdls_setup_cnf_size. */ + +uint32_t dot11f_get_packed_tdls_setup_req_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupReq *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 5; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSSetupReq); + return status; +} /* End dot11f_get_packed_tdls_setup_req_size. */ + +uint32_t dot11f_get_packed_tdls_setup_rsp_size(tpAniSirGlobal pCtx, + tDot11fTDLSSetupRsp *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 7; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSSetupRsp); + return status; +} /* End dot11f_get_packed_tdls_setup_rsp_size. */ + +uint32_t dot11f_get_packed_tdls_teardown_size(tpAniSirGlobal pCtx, + tDot11fTDLSTeardown *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TDLSTeardown); + return status; +} /* End dot11f_get_packed_tdls_teardown_size. */ + +uint32_t dot11f_get_packed_tpc_report_size(tpAniSirGlobal pCtx, + tDot11fTPCReport *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TPCReport); + return status; +} /* End dot11f_get_packed_tpc_report_size. */ + +uint32_t dot11f_get_packed_tpc_request_size(tpAniSirGlobal pCtx, + tDot11fTPCRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 3; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TPCRequest); + return status; +} /* End dot11f_get_packed_tpc_request_size. */ + +uint32_t dot11f_get_packed_timing_advertisement_frame_size(tpAniSirGlobal pCtx, + tDot11fTimingAdvertisementFrame *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 10; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_TimingAdvertisementFrame); + return status; +} /* End dot11f_get_packed_timing_advertisement_frame_size. */ + +uint32_t dot11f_get_packed_vht_gid_management_action_frame_size(tpAniSirGlobal pCtx, + tDot11fVHTGidManagementActionFrame *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 26; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_VHTGidManagementActionFrame); + return status; +} /* End dot11f_get_packed_vht_gid_management_action_frame_size. */ + +uint32_t dot11f_get_packed_wmm_add_ts_request_size(tpAniSirGlobal pCtx, + tDot11fWMMAddTSRequest *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_WMMAddTSRequest); + return status; +} /* End dot11f_get_packed_wmm_add_ts_request_size. */ + +uint32_t dot11f_get_packed_wmm_add_ts_response_size(tpAniSirGlobal pCtx, + tDot11fWMMAddTSResponse *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_WMMAddTSResponse); + return status; +} /* End dot11f_get_packed_wmm_add_ts_response_size. */ + +uint32_t dot11f_get_packed_wmm_del_ts_size(tpAniSirGlobal pCtx, + tDot11fWMMDelTS *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 4; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_WMMDelTS); + return status; +} /* End dot11f_get_packed_wmm_del_ts_size. */ + +uint32_t dot11f_get_packed_ht2040_bss_coexistence_mgmt_action_frameSize(tpAniSirGlobal pCtx, + tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 2; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ht2040_bss_coexistence_mgmt_action_frame); + return status; +} /* End dot11f_get_packed_ht2040_bss_coexistence_mgmt_action_frameSize. */ + +static uint32_t get_packed_size_core(tpAniSirGlobal pCtx, + uint8_t *pFrm, + uint32_t *pnNeeded, + const tIEDefn IEs[]) +{ + const tIEDefn *pIe; + uint16_t i, n; + uint32_t status; + tFRAMES_BOOL *pfFound; + uint32_t countOffset = 0; + uint32_t byteCount = 0; + uint8_t pIePresent = 0; + uint32_t 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 : (*(uint16_t *)(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 + offset * 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 + offset * 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 + offset * 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 + offset * 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 + offset * i))-> + num_vendorSpecific + 1; + pIePresent = ((tDot11fIEMeasurementPilot *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeMultiBssid: + offset = sizeof(tDot11fIEMultiBssid); + byteCount = ((tDot11fIEMultiBssid *) + (pFrm + pIe->offset + offset * 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 + offset * 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 + offset * i))-> + num_requested_eids; + pIePresent = ((tDot11fIERequestedInfo *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeSSID: + offset = sizeof(tDot11fIESSID); + byteCount = ((tDot11fIESSID *) + (pFrm + pIe->offset + offset * 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 |= + dot11f_get_packed_ietclas( + 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 SigIeVHTCaps: + offset = sizeof(tDot11fIEVHTCaps); + byteCount = 12; + pIePresent = ((tDot11fIEVHTCaps *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeVHTOperation: + offset = sizeof(tDot11fIEVHTOperation); + byteCount = 5; + pIePresent = ((tDot11fIEVHTOperation *) + (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 |= + dot11f_get_packed_iewmmtclas( + 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 + offset * 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 |= + dot11f_get_packed_ie_channel_switch_wrapper( + pCtx, (tDot11fIEChannelSwitchWrapper *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeCountry: + offset = sizeof(tDot11fIECountry); + status |= + dot11f_get_packed_ie_country( + 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 + offset * 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 + offset * 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 + offset * i))-> + num_bytes; + pIePresent = ((tDot11fIEExtCap *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeExtSuppRates: + offset = sizeof(tDot11fIEExtSuppRates); + byteCount = ((tDot11fIEExtSuppRates *) + (pFrm + pIe->offset + offset * 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 + offset * i))-> + num_randtable + 4; + pIePresent = ((tDot11fIEFHPattTable *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeFTInfo: + offset = sizeof(tDot11fIEFTInfo); + status |= + dot11f_get_packed_ieft_info( + pCtx, (tDot11fIEFTInfo *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeHTCaps: + offset = sizeof(tDot11fIEHTCaps); + byteCount = ((tDot11fIEHTCaps *) + (pFrm + pIe->offset + offset * i))-> + num_rsvd + 26; + pIePresent = ((tDot11fIEHTCaps *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeHTInfo: + offset = sizeof(tDot11fIEHTInfo); + byteCount = ((tDot11fIEHTInfo *) + (pFrm + pIe->offset + offset * 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 |= + dot11f_get_packed_ie_measurement_report( + pCtx, (tDot11fIEMeasurementReport *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeMeasurementRequest: + offset = sizeof(tDot11fIEMeasurementRequest); + status |= + dot11f_get_packed_ie_measurement_request( + 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 |= + dot11f_get_packed_ie_neighbor_report( + 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 |= + dot11f_get_packed_iep2_p_assoc_req( + pCtx, (tDot11fIEP2PAssocReq *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PAssocRes: + offset = sizeof(tDot11fIEP2PAssocRes); + status |= + dot11f_get_packed_iep2_p_assoc_res( + pCtx, (tDot11fIEP2PAssocRes *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PBeacon: + offset = sizeof(tDot11fIEP2PBeacon); + status |= + dot11f_get_packed_iep2_p_beacon( + pCtx, (tDot11fIEP2PBeacon *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PBeaconProbeRes: + offset = sizeof(tDot11fIEP2PBeaconProbeRes); + status |= + dot11f_get_packed_iep2_p_beacon_probe_res( + pCtx, (tDot11fIEP2PBeaconProbeRes *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PDeAuth: + offset = sizeof(tDot11fIEP2PDeAuth); + status |= + dot11f_get_packed_iep2_p_de_auth( + pCtx, (tDot11fIEP2PDeAuth *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PDisAssoc: + offset = sizeof(tDot11fIEP2PDisAssoc); + status |= + dot11f_get_packed_iep2_p_dis_assoc( + pCtx, (tDot11fIEP2PDisAssoc *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PIEOpaque: + offset = sizeof(tDot11fIEP2PIEOpaque); + byteCount = ((tDot11fIEP2PIEOpaque *) + (pFrm + pIe->offset + offset * i))-> + num_data; + pIePresent = ((tDot11fIEP2PIEOpaque *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeP2PProbeReq: + offset = sizeof(tDot11fIEP2PProbeReq); + status |= + dot11f_get_packed_iep2_p_probe_req( + pCtx, (tDot11fIEP2PProbeReq *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeP2PProbeRes: + offset = sizeof(tDot11fIEP2PProbeRes); + status |= + dot11f_get_packed_iep2_p_probe_res( + pCtx, (tDot11fIEP2PProbeRes *) + (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 + offset * 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 |= + dot11f_get_packed_ieric_data_desc( + pCtx, (tDot11fIERICDataDesc *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeRSN: + offset = sizeof(tDot11fIERSN); + status |= + dot11f_get_packed_iersn( + 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 + offset * i))-> + num_data; + pIePresent = ((tDot11fIERSNOpaque *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeSuppChannels: + offset = sizeof(tDot11fIESuppChannels); + byteCount = ((tDot11fIESuppChannels *) + (pFrm + pIe->offset + offset * i))-> + num_bands * 2; + pIePresent = ((tDot11fIESuppChannels *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeSuppOperatingClasses: + offset = sizeof(tDot11fIESuppOperatingClasses); + byteCount = ((tDot11fIESuppOperatingClasses *) + (pFrm + pIe->offset + offset * i))-> + num_classes; + pIePresent = ((tDot11fIESuppOperatingClasses *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeSuppRates: + offset = sizeof(tDot11fIESuppRates); + byteCount = ((tDot11fIESuppRates *) + (pFrm + pIe->offset + offset * i))-> + num_rates; + pIePresent = ((tDot11fIESuppRates *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeTIM: + offset = sizeof(tDot11fIETIM); + byteCount = ((tDot11fIETIM *) + (pFrm + pIe->offset + offset * 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 SigIeVHTExtBssLoad: + offset = sizeof(tDot11fIEVHTExtBssLoad); + byteCount = 5; + pIePresent = ((tDot11fIEVHTExtBssLoad *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeVendor1IE: + offset = sizeof(tDot11fIEVendor1IE); + byteCount = 0; + pIePresent = ((tDot11fIEVendor1IE *) + (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 |= + dot11f_get_packed_iewapi( + pCtx, (tDot11fIEWAPI *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWAPIOpaque: + offset = sizeof(tDot11fIEWAPIOpaque); + byteCount = ((tDot11fIEWAPIOpaque *) + (pFrm + pIe->offset + offset * 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 + offset * 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 |= + dot11f_get_packed_iewpa( + pCtx, (tDot11fIEWPA *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWPAOpaque: + offset = sizeof(tDot11fIEWPAOpaque); + byteCount = ((tDot11fIEWPAOpaque *) + (pFrm + pIe->offset + offset * i))-> + num_data; + pIePresent = ((tDot11fIEWPAOpaque *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeWSC: + offset = sizeof(tDot11fIEWSC); + status |= + dot11f_get_packed_iewsc( + pCtx, (tDot11fIEWSC *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscAssocReq: + offset = sizeof(tDot11fIEWscAssocReq); + status |= + dot11f_get_packed_ie_wsc_assoc_req( + pCtx, (tDot11fIEWscAssocReq *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscAssocRes: + offset = sizeof(tDot11fIEWscAssocRes); + status |= + dot11f_get_packed_ie_wsc_assoc_res( + pCtx, (tDot11fIEWscAssocRes *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscBeacon: + offset = sizeof(tDot11fIEWscBeacon); + status |= + dot11f_get_packed_ie_wsc_beacon( + pCtx, (tDot11fIEWscBeacon *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscBeaconProbeRes: + offset = sizeof(tDot11fIEWscBeaconProbeRes); + status |= + dot11f_get_packed_ie_wsc_beacon_probe_res( + pCtx, (tDot11fIEWscBeaconProbeRes *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscIEOpaque: + offset = sizeof(tDot11fIEWscIEOpaque); + byteCount = ((tDot11fIEWscIEOpaque *) + (pFrm + pIe->offset + offset * i))-> + num_data; + pIePresent = ((tDot11fIEWscIEOpaque *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeWscProbeReq: + offset = sizeof(tDot11fIEWscProbeReq); + status |= + dot11f_get_packed_ie_wsc_probe_req( + pCtx, (tDot11fIEWscProbeReq *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscProbeRes: + offset = sizeof(tDot11fIEWscProbeRes); + status |= + dot11f_get_packed_ie_wsc_probe_res( + pCtx, (tDot11fIEWscProbeRes *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + case SigIeWscReassocRes: + offset = sizeof(tDot11fIEWscReassocRes); + status |= + dot11f_get_packed_ie_wsc_reassoc_res( + 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 SigIeht2040_bss_coexistence: + offset = sizeof(tDot11fIEht2040_bss_coexistence); + byteCount = 1; + pIePresent = ((tDot11fIEht2040_bss_coexistence *) + (pFrm + pIe->offset + offset * i))-> + present; + break; + case SigIeht2040_bss_intolerant_report: + offset = sizeof(tDot11fIEht2040_bss_intolerant_report); + byteCount = ((tDot11fIEht2040_bss_intolerant_report *) + (pFrm + pIe->offset + offset * i))-> + num_channel_list + 1; + pIePresent = ((tDot11fIEht2040_bss_intolerant_report *) + (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; + case SigIevendor2_ie: + offset = sizeof(tDot11fIEvendor2_ie); + status |= + dot11f_get_packed_ie_vendor2_ie( + pCtx, (tDot11fIEvendor2_ie *) + (pFrm + pIe->offset + offset * i), + pnNeeded); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" + "'t know about the IE signature %d; this is most l" + "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 uint32_t get_packed_size_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pFrm, + uint32_t *pnNeeded, + const tTLVDefn TLVs[]) +{ + const tTLVDefn *pTlv; + uint32_t status; + tFRAMES_BOOL *pfFound; + uint32_t byteCount = 0; + uint8_t 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 SigTlvConfigMethods: + byteCount = 2; + pTlvPresent = ((tDot11fTLVConfigMethods *) + (pFrm + pTlv->offset))->present; + break; + case SigTlvConfigurationError: + byteCount = 2; + pTlvPresent = ((tDot11fTLVConfigurationError *) + (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 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 = get_packed_size_tlv_core(pCtx, (uint8_t *)pFrm + pTlv->offset, pnNeeded, TLVS_P2PDeviceInfo); + byteCount = 16; + pTlvPresent = ((tDot11fTLVP2PDeviceInfo *) + (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 = get_packed_size_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ff_aid(tpAniSirGlobal pCtx, + tDot11fFfAID *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->associd, 0); + (void)pCtx; +} /* End dot11f_pack_ff_aid. */ + +void dot11f_pack_ff_action(tpAniSirGlobal pCtx, + tDot11fFfAction *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->action; + (void)pCtx; +} /* End dot11f_pack_ff_action. */ + +void dot11f_pack_ff_auth_algo(tpAniSirGlobal pCtx, + tDot11fFfAuthAlgo *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->algo, 0); + (void)pCtx; +} /* End dot11f_pack_ff_auth_algo. */ + +void dot11f_pack_ff_auth_seq_no(tpAniSirGlobal pCtx, + tDot11fFfAuthSeqNo *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->no, 0); + (void)pCtx; +} /* End dot11f_pack_ff_auth_seq_no. */ + +void dot11f_pack_ff_beacon_interval(tpAniSirGlobal pCtx, + tDot11fFfBeaconInterval *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->interval, 0); + (void)pCtx; +} /* End dot11f_pack_ff_beacon_interval. */ + +void dot11f_pack_ff_capabilities(tpAniSirGlobal pCtx, + tDot11fFfCapabilities *pSrc, + uint8_t *pBuf) +{ + uint16_t tmp66__; + tmp66__ = 0U; + tmp66__ |= (pSrc->ess << 0); + tmp66__ |= (pSrc->ibss << 1); + tmp66__ |= (pSrc->cfPollable << 2); + tmp66__ |= (pSrc->cfPollReq << 3); + tmp66__ |= (pSrc->privacy << 4); + tmp66__ |= (pSrc->shortPreamble << 5); + tmp66__ |= (pSrc->pbcc << 6); + tmp66__ |= (pSrc->channelAgility << 7); + tmp66__ |= (pSrc->spectrumMgt << 8); + tmp66__ |= (pSrc->qos << 9); + tmp66__ |= (pSrc->shortSlotTime << 10); + tmp66__ |= (pSrc->apsd << 11); + tmp66__ |= (pSrc->rrm << 12); + tmp66__ |= (pSrc->dsssOfdm << 13); + tmp66__ |= (pSrc->delayedBA << 14); + tmp66__ |= (pSrc->immediateBA << 15); + frameshtons(pCtx, pBuf, tmp66__, 0); + (void)pCtx; +} /* End dot11f_pack_ff_capabilities. */ + +void dot11f_pack_ff_category(tpAniSirGlobal pCtx, + tDot11fFfCategory *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->category; + (void)pCtx; +} /* End dot11f_pack_ff_category. */ + +void dot11f_pack_ff_current_ap_address(tpAniSirGlobal pCtx, + tDot11fFfCurrentAPAddress *pSrc, + uint8_t *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->mac, 6); + (void)pCtx; +} /* End dot11f_pack_ff_current_ap_address. */ + +void dot11f_pack_ff_dialog_token(tpAniSirGlobal pCtx, + tDot11fFfDialogToken *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->token; + (void)pCtx; +} /* End dot11f_pack_ff_dialog_token. */ + +void dot11f_pack_ff_link_margin(tpAniSirGlobal pCtx, + tDot11fFfLinkMargin *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->linkMargin; + (void)pCtx; +} /* End dot11f_pack_ff_link_margin. */ + +void dot11f_pack_ff_listen_interval(tpAniSirGlobal pCtx, + tDot11fFfListenInterval *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->interval, 0); + (void)pCtx; +} /* End dot11f_pack_ff_listen_interval. */ + +void dot11f_pack_ff_max_tx_power(tpAniSirGlobal pCtx, + tDot11fFfMaxTxPower *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->maxTxPower; + (void)pCtx; +} /* End dot11f_pack_ff_max_tx_power. */ + +void dot11f_pack_ff_num_of_repetitions(tpAniSirGlobal pCtx, + tDot11fFfNumOfRepetitions *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->repetitions, 0); + (void)pCtx; +} /* End dot11f_pack_ff_num_of_repetitions. */ + +void dot11f_pack_ff_operating_mode(tpAniSirGlobal pCtx, + tDot11fFfOperatingMode *pSrc, + uint8_t *pBuf) +{ + uint8_t tmp67__; + tmp67__ = 0U; + tmp67__ |= (pSrc->chanWidth << 0); + tmp67__ |= (pSrc->reserved << 2); + tmp67__ |= (pSrc->rxNSS << 4); + tmp67__ |= (pSrc->rxNSSType << 7); + *pBuf = tmp67__; + (void)pCtx; +} /* End dot11f_pack_ff_operating_mode. */ + +void dot11f_pack_ff_rcpi(tpAniSirGlobal pCtx, + tDot11fFfRCPI *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->rcpi; + (void)pCtx; +} /* End dot11f_pack_ff_rcpi. */ + +void dot11f_pack_ff_rsni(tpAniSirGlobal pCtx, + tDot11fFfRSNI *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->rsni; + (void)pCtx; +} /* End dot11f_pack_ff_rsni. */ + +void dot11f_pack_ff_reason(tpAniSirGlobal pCtx, + tDot11fFfReason *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->code, 0); + (void)pCtx; +} /* End dot11f_pack_ff_reason. */ + +void dot11f_pack_ff_rx_antenna_id(tpAniSirGlobal pCtx, + tDot11fFfRxAntennaId *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->antennaId; + (void)pCtx; +} /* End dot11f_pack_ff_rx_antenna_id. */ + +void dot11f_pack_ff_sm_power_mode_set(tpAniSirGlobal pCtx, + tDot11fFfSMPowerModeSet *pSrc, + uint8_t *pBuf) +{ + uint8_t tmp68__; + tmp68__ = 0U; + tmp68__ |= (pSrc->PowerSave_En << 0); + tmp68__ |= (pSrc->Mode << 1); + tmp68__ |= (pSrc->reserved << 2); + *pBuf = tmp68__; + (void)pCtx; +} /* End dot11f_pack_ff_sm_power_mode_set. */ + +void dot11f_pack_ff_status(tpAniSirGlobal pCtx, + tDot11fFfStatus *pSrc, + uint8_t *pBuf) +{ + frameshtons(pCtx, pBuf, pSrc->status, 0); + (void)pCtx; +} /* End dot11f_pack_ff_status. */ + +void dot11f_pack_ff_status_code(tpAniSirGlobal pCtx, + tDot11fFfStatusCode *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->statusCode; + (void)pCtx; +} /* End dot11f_pack_ff_status_code. */ + +void dot11f_pack_ff_tpc_ele_id(tpAniSirGlobal pCtx, + tDot11fFfTPCEleID *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->TPCId; + (void)pCtx; +} /* End dot11f_pack_ff_tpc_ele_id. */ + +void dot11f_pack_ff_tpc_ele_len(tpAniSirGlobal pCtx, + tDot11fFfTPCEleLen *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->TPCLen; + (void)pCtx; +} /* End dot11f_pack_ff_tpc_ele_len. */ + +void dot11f_pack_ff_ts_info(tpAniSirGlobal pCtx, + tDot11fFfTSInfo *pSrc, + uint8_t *pBuf) +{ + uint32_t tmp69__; + tmp69__ = 0U; + tmp69__ |= (pSrc->traffic_type << 0); + tmp69__ |= (pSrc->tsid << 1); + tmp69__ |= (pSrc->direction << 5); + tmp69__ |= (pSrc->access_policy << 7); + tmp69__ |= (pSrc->aggregation << 9); + tmp69__ |= (pSrc->psb << 10); + tmp69__ |= (pSrc->user_priority << 11); + tmp69__ |= (pSrc->tsinfo_ack_pol << 14); + tmp69__ |= (pSrc->schedule << 16); + tmp69__ |= (pSrc->unused << 17); + frameshtonl(pCtx, pBuf, tmp69__, 0); + (void)pCtx; +} /* End dot11f_pack_ff_ts_info. */ + +void dot11f_pack_ff_time_stamp(tpAniSirGlobal pCtx, + tDot11fFfTimeStamp *pSrc, + uint8_t *pBuf) +{ + frameshtonq(pCtx, pBuf, pSrc->timestamp, 0); + (void)pCtx; +} /* End dot11f_pack_ff_time_stamp. */ + +void dot11f_pack_ff_transaction_id(tpAniSirGlobal pCtx, + tDot11fFfTransactionId *pSrc, + uint8_t *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->transId, 2); + (void)pCtx; +} /* End dot11f_pack_ff_transaction_id. */ + +void dot11f_pack_ff_tx_antenna_id(tpAniSirGlobal pCtx, + tDot11fFfTxAntennaId *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->antennaId; + (void)pCtx; +} /* End dot11f_pack_ff_tx_antenna_id. */ + +void dot11f_pack_ff_tx_power(tpAniSirGlobal pCtx, + tDot11fFfTxPower *pSrc, + uint8_t *pBuf) +{ + *pBuf = pSrc->txPower; + (void)pCtx; +} /* End dot11f_pack_ff_tx_power. */ + +void dot11f_pack_ff_vht_membership_status_array(tpAniSirGlobal pCtx, + tDot11fFfVhtMembershipStatusArray *pSrc, + uint8_t *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->membershipStatusArray, 8); + (void)pCtx; +} /* End dot11f_pack_ff_vht_membership_status_array. */ + +void dot11f_pack_ff_vht_user_position_array(tpAniSirGlobal pCtx, + tDot11fFfVhtUserPositionArray *pSrc, + uint8_t *pBuf) +{ + DOT11F_MEMCPY(pCtx, pBuf, pSrc->userPositionArray, 16); + (void)pCtx; +} /* End dot11f_pack_ff_vht_user_position_array. */ + +uint32_t dot11f_pack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx, + tDot11fTLVAuthorizedMACs *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_authorized_ma_cs. */ + +uint32_t dot11f_pack_tlv_request_to_enroll(tpAniSirGlobal pCtx, + tDot11fTLVRequestToEnroll *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_request_to_enroll. */ + +uint32_t dot11f_pack_tlv_version2(tpAniSirGlobal pCtx, + tDot11fTLVVersion2 *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp70__; + nNeeded += 3; + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + while (pSrc->present) { + *pBuf = 0; + pBuf += 1; *pnConsumed += 1; + pTlvLen = pBuf; + pBuf += 1; *pnConsumed += 1; + tmp70__ = 0U; + tmp70__ |= (pSrc->minor << 0); + tmp70__ |= (pSrc->major << 4); + *pBuf = tmp70__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pTlvLen) { + *pTlvLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_tlv_version2. */ + +uint32_t dot11f_pack_tlv_ap_setup_locked(tpAniSirGlobal pCtx, + tDot11fTLVAPSetupLocked *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_ap_setup_locked. */ + +uint32_t dot11f_pack_tlv_association_state(tpAniSirGlobal pCtx, + tDot11fTLVAssociationState *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_association_state. */ + +uint32_t dot11f_pack_tlv_config_methods(tpAniSirGlobal pCtx, + tDot11fTLVConfigMethods *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_config_methods. */ + +uint32_t dot11f_pack_tlv_configuration_error(tpAniSirGlobal pCtx, + tDot11fTLVConfigurationError *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_configuration_error. */ + +uint32_t dot11f_pack_tlv_device_name(tpAniSirGlobal pCtx, + tDot11fTLVDeviceName *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_device_name. */ + +uint32_t dot11f_pack_tlv_device_password_id(tpAniSirGlobal pCtx, + tDot11fTLVDevicePasswordID *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_device_password_id. */ + +uint32_t dot11f_pack_tlv_extended_listen_timing(tpAniSirGlobal pCtx, + tDot11fTLVExtendedListenTiming *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_extended_listen_timing. */ + +uint32_t dot11f_pack_tlv_listen_channel(tpAniSirGlobal pCtx, + tDot11fTLVListenChannel *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_listen_channel. */ + +uint32_t dot11f_pack_tlv_manufacturer(tpAniSirGlobal pCtx, + tDot11fTLVManufacturer *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_manufacturer. */ + +uint32_t dot11f_pack_tlv_minor_reason_code(tpAniSirGlobal pCtx, + tDot11fTLVMinorReasonCode *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_minor_reason_code. */ + +uint32_t dot11f_pack_tlv_model_name(tpAniSirGlobal pCtx, + tDot11fTLVModelName *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_model_name. */ + +uint32_t dot11f_pack_tlv_model_number(tpAniSirGlobal pCtx, + tDot11fTLVModelNumber *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_model_number. */ + +uint32_t dot11f_pack_tlv_notice_of_absence(tpAniSirGlobal pCtx, + tDot11fTLVNoticeOfAbsence *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_notice_of_absence. */ + +uint32_t dot11f_pack_tlv_operating_channel(tpAniSirGlobal pCtx, + tDot11fTLVOperatingChannel *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_operating_channel. */ + +uint32_t dot11f_pack_tlv_p2_p_capability(tpAniSirGlobal pCtx, + tDot11fTLVP2PCapability *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_capability. */ + +uint32_t dot11f_pack_tlv_p2_p_device_id(tpAniSirGlobal pCtx, + tDot11fTLVP2PDeviceId *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_device_id. */ + +uint32_t dot11f_pack_tlv_p2_p_device_info(tpAniSirGlobal pCtx, + tDot11fTLVP2PDeviceInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + uint32_t 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 |= pack_tlv_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + TLVS_P2PDeviceInfo, &idx); + break; + } + (void)pCtx; + if (pTlvLen) { + frameshtons(pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 3, 0); + } + return status; +} /* End dot11f_pack_tlv_p2_p_device_info. */ + +uint32_t dot11f_pack_tlv_p2_p_group_info(tpAniSirGlobal pCtx, + tDot11fTLVP2PGroupInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_group_info. */ + +uint32_t dot11f_pack_tlv_p2_p_status(tpAniSirGlobal pCtx, + tDot11fTLVP2PStatus *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_status. */ + +uint32_t dot11f_pack_tlv_primary_device_type(tpAniSirGlobal pCtx, + tDot11fTLVPrimaryDeviceType *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_primary_device_type. */ + +uint32_t dot11f_pack_tlv_rf_bands(tpAniSirGlobal pCtx, + tDot11fTLVRFBands *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_rf_bands. */ + +uint32_t dot11f_pack_tlv_request_device_type(tpAniSirGlobal pCtx, + tDot11fTLVRequestDeviceType *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_request_device_type. */ + +uint32_t dot11f_pack_tlv_request_type(tpAniSirGlobal pCtx, + tDot11fTLVRequestType *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_request_type. */ + +uint32_t dot11f_pack_tlv_response_type(tpAniSirGlobal pCtx, + tDot11fTLVResponseType *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_response_type. */ + +uint32_t dot11f_pack_tlv_selected_registrar(tpAniSirGlobal pCtx, + tDot11fTLVSelectedRegistrar *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_selected_registrar. */ + +uint32_t dot11f_pack_tlv_selected_registrar_config_methods(tpAniSirGlobal pCtx, + tDot11fTLVSelectedRegistrarConfigMethods *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_selected_registrar_config_methods. */ + +uint32_t dot11f_pack_tlv_serial_number(tpAniSirGlobal pCtx, + tDot11fTLVSerialNumber *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_serial_number. */ + +uint32_t dot11f_pack_tlv_uuid_e(tpAniSirGlobal pCtx, + tDot11fTLVUUID_E *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_uuid_e. */ + +uint32_t dot11f_pack_tlv_uuid_r(tpAniSirGlobal pCtx, + tDot11fTLVUUID_R *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_uuid_r. */ + +uint32_t dot11f_pack_tlv_vendor_extension(tpAniSirGlobal pCtx, + tDot11fTLVVendorExtension *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + uint32_t 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 |= pack_tlv_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + TLVS_VendorExtension, &idx); + break; + } + (void)pCtx; + if (pTlvLen) { + frameshtons(pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return status; +} /* End dot11f_pack_tlv_vendor_extension. */ + +uint32_t dot11f_pack_tlv_version(tpAniSirGlobal pCtx, + tDot11fTLVVersion *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp71__; + 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; + tmp71__ = 0U; + tmp71__ |= (pSrc->minor << 0); + tmp71__ |= (pSrc->major << 4); + *pBuf = tmp71__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pTlvLen) { + frameshtons(pCtx, pTlvLen, *pnConsumed - nConsumedOnEntry - 4, 1); + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_tlv_version. */ + +uint32_t dot11f_pack_tlv_wps_state(tpAniSirGlobal pCtx, + tDot11fTLVWPSState *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_wps_state. */ + +uint32_t dot11f_pack_tlv_p2_p_interface(tpAniSirGlobal pCtx, + tDot11fTLVP2PInterface *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_interface. */ + +uint32_t dot11f_pack_tlv_p2_p_manageability(tpAniSirGlobal pCtx, + tDot11fTLVP2PManageability *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pTlvLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_tlv_p2_p_manageability. */ + +uint32_t dot11f_pack_ie_condensed_country_str(tpAniSirGlobal pCtx, + tDot11fIECondensedCountryStr *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_condensed_country_str. */ + +uint32_t dot11f_pack_ie_gtk(tpAniSirGlobal pCtx, + tDot11fIEGTK *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp72__; + nNeeded += (pSrc->num_key + 11); + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 2; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp72__ = 0U; + tmp72__ |= (pSrc->keyId << 0); + tmp72__ |= (pSrc->reserved << 2); + frameshtons(pCtx, pBuf, tmp72__, 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 dot11f_pack_ie_gtk. */ + +uint32_t dot11f_pack_ie_igtk(tpAniSirGlobal pCtx, + tDot11fIEIGTK *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_igtk. */ + +uint32_t dot11f_pack_ie_r0_kh_id(tpAniSirGlobal pCtx, + tDot11fIER0KH_ID *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_r0_kh_id. */ + +uint32_t dot11f_pack_ie_r1_kh_id(tpAniSirGlobal pCtx, + tDot11fIER1KH_ID *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_r1_kh_id. */ + +uint32_t dot11f_pack_ie_tsf_info(tpAniSirGlobal pCtx, + tDot11fIETSFInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_tsf_info. */ + +uint32_t dot11f_pack_ie_ap_channel_report(tpAniSirGlobal pCtx, + tDot11fIEAPChannelReport *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ap_channel_report. */ + +uint32_t dot11f_pack_ie_bcn_reporting_detail(tpAniSirGlobal pCtx, + tDot11fIEBcnReportingDetail *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_bcn_reporting_detail. */ + +uint32_t dot11f_pack_ie_beacon_report_frm_body(tpAniSirGlobal pCtx, + tDot11fIEBeaconReportFrmBody *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_beacon_report_frm_body. */ + +uint32_t dot11f_pack_ie_beacon_reporting(tpAniSirGlobal pCtx, + tDot11fIEBeaconReporting *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_beacon_reporting. */ + +uint32_t dot11f_pack_ie_measurement_pilot(tpAniSirGlobal pCtx, + tDot11fIEMeasurementPilot *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_measurement_pilot. */ + +uint32_t dot11f_pack_ie_multi_bssid(tpAniSirGlobal pCtx, + tDot11fIEMultiBssid *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_multi_bssid. */ + +uint32_t dot11f_pack_ie_ric_data(tpAniSirGlobal pCtx, + tDot11fIERICData *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ric_data. */ + +uint32_t dot11f_pack_ie_ric_descriptor(tpAniSirGlobal pCtx, + tDot11fIERICDescriptor *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ric_descriptor. */ + +uint32_t dot11f_pack_ie_rrm_enabled_cap(tpAniSirGlobal pCtx, + tDot11fIERRMEnabledCap *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp73__; + uint8_t tmp74__; + uint8_t tmp75__; + uint8_t tmp76__; + uint8_t tmp77__; + nNeeded += 5; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 70; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp73__ = 0U; + tmp73__ |= (pSrc->LinkMeasurement << 0); + tmp73__ |= (pSrc->NeighborRpt << 1); + tmp73__ |= (pSrc->parallel << 2); + tmp73__ |= (pSrc->repeated << 3); + tmp73__ |= (pSrc->BeaconPassive << 4); + tmp73__ |= (pSrc->BeaconActive << 5); + tmp73__ |= (pSrc->BeaconTable << 6); + tmp73__ |= (pSrc->BeaconRepCond << 7); + *pBuf = tmp73__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp74__ = 0U; + tmp74__ |= (pSrc->FrameMeasurement << 0); + tmp74__ |= (pSrc->ChannelLoad << 1); + tmp74__ |= (pSrc->NoiseHistogram << 2); + tmp74__ |= (pSrc->statistics << 3); + tmp74__ |= (pSrc->LCIMeasurement << 4); + tmp74__ |= (pSrc->LCIAzimuth << 5); + tmp74__ |= (pSrc->TCMCapability << 6); + tmp74__ |= (pSrc->triggeredTCM << 7); + *pBuf = tmp74__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp75__ = 0U; + tmp75__ |= (pSrc->APChanReport << 0); + tmp75__ |= (pSrc->RRMMIBEnabled << 1); + tmp75__ |= (pSrc->operatingChanMax << 2); + tmp75__ |= (pSrc->nonOperatinChanMax << 5); + *pBuf = tmp75__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp76__ = 0U; + tmp76__ |= (pSrc->MeasurementPilot << 0); + tmp76__ |= (pSrc->MeasurementPilotEnabled << 3); + tmp76__ |= (pSrc->NeighborTSFOffset << 4); + tmp76__ |= (pSrc->RCPIMeasurement << 5); + tmp76__ |= (pSrc->RSNIMeasurement << 6); + tmp76__ |= (pSrc->BssAvgAccessDelay << 7); + *pBuf = tmp76__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp77__ = 0U; + tmp77__ |= (pSrc->BSSAvailAdmission << 0); + tmp77__ |= (pSrc->AntennaInformation << 1); + tmp77__ |= (pSrc->fine_time_meas_rpt << 2); + tmp77__ |= (pSrc->lci_capability << 3); + tmp77__ |= (pSrc->reserved << 4); + *pBuf = tmp77__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_rrm_enabled_cap. */ + +uint32_t dot11f_pack_ie_requested_info(tpAniSirGlobal pCtx, + tDot11fIERequestedInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_requested_info. */ + +uint32_t dot11f_pack_ie_ssid(tpAniSirGlobal pCtx, + tDot11fIESSID *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ssid. */ + +uint32_t dot11f_pack_ie_schedule(tpAniSirGlobal pCtx, + tDot11fIESchedule *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp78__; + nNeeded += 14; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 15; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp78__ = 0U; + tmp78__ |= (pSrc->aggregation << 0); + tmp78__ |= (pSrc->tsid << 1); + tmp78__ |= (pSrc->direction << 5); + tmp78__ |= (pSrc->reserved << 7); + frameshtons(pCtx, pBuf, tmp78__, 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 dot11f_pack_ie_schedule. */ + +uint32_t dot11f_pack_ie_tclas(tpAniSirGlobal pCtx, + tDot11fIETCLAS *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ietclas(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 dot11f_pack_ie_tclas. */ + +uint32_t dot11f_pack_ie_tclassproc(tpAniSirGlobal pCtx, + tDot11fIETCLASSPROC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_tclassproc. */ + +uint32_t dot11f_pack_ie_ts_delay(tpAniSirGlobal pCtx, + tDot11fIETSDelay *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ts_delay. */ + +uint32_t dot11f_pack_ie_tspec(tpAniSirGlobal pCtx, + tDot11fIETSPEC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp79__; + uint8_t tmp80__; + uint16_t tmp81__; + nNeeded += 55; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 13; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp79__ = 0U; + tmp79__ |= (pSrc->traffic_type << 0); + tmp79__ |= (pSrc->tsid << 1); + tmp79__ |= (pSrc->direction << 5); + tmp79__ |= (pSrc->access_policy << 7); + tmp79__ |= (pSrc->aggregation << 9); + tmp79__ |= (pSrc->psb << 10); + tmp79__ |= (pSrc->user_priority << 11); + tmp79__ |= (pSrc->tsinfo_ack_pol << 14); + frameshtons(pCtx, pBuf, tmp79__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp80__ = 0U; + tmp80__ |= (pSrc->schedule << 0); + tmp80__ |= (pSrc->unused << 1); + *pBuf = tmp80__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp81__ = 0U; + tmp81__ |= (pSrc->size << 0); + tmp81__ |= (pSrc->fixed << 15); + frameshtons(pCtx, pBuf, tmp81__, 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 dot11f_pack_ie_tspec. */ + +uint32_t dot11f_pack_ie_vht_caps(tpAniSirGlobal pCtx, + tDot11fIEVHTCaps *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t tmp82__; + uint16_t tmp83__; + uint16_t tmp84__; + nNeeded += 12; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 191; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp82__ = 0U; + tmp82__ |= (pSrc->maxMPDULen << 0); + tmp82__ |= (pSrc->supportedChannelWidthSet << 2); + tmp82__ |= (pSrc->ldpcCodingCap << 4); + tmp82__ |= (pSrc->shortGI80MHz << 5); + tmp82__ |= (pSrc->shortGI160and80plus80MHz << 6); + tmp82__ |= (pSrc->txSTBC << 7); + tmp82__ |= (pSrc->rxSTBC << 8); + tmp82__ |= (pSrc->suBeamFormerCap << 11); + tmp82__ |= (pSrc->suBeamformeeCap << 12); + tmp82__ |= (pSrc->csnofBeamformerAntSup << 13); + tmp82__ |= (pSrc->numSoundingDim << 16); + tmp82__ |= (pSrc->muBeamformerCap << 19); + tmp82__ |= (pSrc->muBeamformeeCap << 20); + tmp82__ |= (pSrc->vhtTXOPPS << 21); + tmp82__ |= (pSrc->htcVHTCap << 22); + tmp82__ |= (pSrc->maxAMPDULenExp << 23); + tmp82__ |= (pSrc->vhtLinkAdaptCap << 26); + tmp82__ |= (pSrc->rxAntPattern << 28); + tmp82__ |= (pSrc->txAntPattern << 29); + tmp82__ |= (pSrc->reserved1 << 30); + frameshtonl(pCtx, pBuf, tmp82__, 0); + *pnConsumed += 4; + pBuf += 4; + nBuf -= 4 ; + frameshtons(pCtx, pBuf, pSrc->rxMCSMap, 0); + *pnConsumed += 2; + pBuf += 2; + tmp83__ = 0U; + tmp83__ |= (pSrc->rxHighSupDataRate << 0); + tmp83__ |= (pSrc->reserved2 << 13); + frameshtons(pCtx, pBuf, tmp83__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + frameshtons(pCtx, pBuf, pSrc->txMCSMap, 0); + *pnConsumed += 2; + pBuf += 2; + tmp84__ = 0U; + tmp84__ |= (pSrc->txSupDataRate << 0); + tmp84__ |= (pSrc->reserved3 << 13); + frameshtons(pCtx, pBuf, tmp84__, 0); + *pnConsumed += 2; + /* fieldsEndFlag = 1 */ + nBuf -= 2 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_vht_caps. */ + +uint32_t dot11f_pack_ie_vht_operation(tpAniSirGlobal pCtx, + tDot11fIEVHTOperation *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_vht_operation. */ + +uint32_t dot11f_pack_ie_wmm_schedule(tpAniSirGlobal pCtx, + tDot11fIEWMMSchedule *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp85__; + 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; + tmp85__ = 0U; + tmp85__ |= (pSrc->aggregation << 0); + tmp85__ |= (pSrc->tsid << 1); + tmp85__ |= (pSrc->direction << 5); + tmp85__ |= (pSrc->reserved << 7); + frameshtons(pCtx, pBuf, tmp85__, 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 dot11f_pack_ie_wmm_schedule. */ + +uint32_t dot11f_pack_ie_wmmtclas(tpAniSirGlobal pCtx, + tDot11fIEWMMTCLAS *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_iewmmtclas(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 dot11f_pack_ie_wmmtclas. */ + +uint32_t dot11f_pack_ie_wmmtclasproc(tpAniSirGlobal pCtx, + tDot11fIEWMMTCLASPROC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wmmtclasproc. */ + +uint32_t dot11f_pack_ie_wmmts_delay(tpAniSirGlobal pCtx, + tDot11fIEWMMTSDelay *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wmmts_delay. */ + +uint32_t dot11f_pack_ie_wmmtspec(tpAniSirGlobal pCtx, + tDot11fIEWMMTSPEC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp86__; + uint8_t tmp87__; + uint16_t tmp88__; + 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; + tmp86__ = 0U; + tmp86__ |= (pSrc->traffic_type << 0); + tmp86__ |= (pSrc->tsid << 1); + tmp86__ |= (pSrc->direction << 5); + tmp86__ |= (pSrc->access_policy << 7); + tmp86__ |= (pSrc->aggregation << 9); + tmp86__ |= (pSrc->psb << 10); + tmp86__ |= (pSrc->user_priority << 11); + tmp86__ |= (pSrc->tsinfo_ack_pol << 14); + frameshtons(pCtx, pBuf, tmp86__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp87__ = 0U; + tmp87__ |= (pSrc->tsinfo_rsvd << 0); + tmp87__ |= (pSrc->burst_size_defn << 7); + *pBuf = tmp87__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp88__ = 0U; + tmp88__ |= (pSrc->size << 0); + tmp88__ |= (pSrc->fixed << 15); + frameshtons(pCtx, pBuf, tmp88__, 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 dot11f_pack_ie_wmmtspec. */ + +uint32_t dot11f_pack_ie_wider_bw_chan_switch_ann(tpAniSirGlobal pCtx, + tDot11fIEWiderBWChanSwitchAnn *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wider_bw_chan_switch_ann. */ + +uint32_t dot11f_pack_ie_aid(tpAniSirGlobal pCtx, + tDot11fIEAID *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_aid. */ + +uint32_t dot11f_pack_ie_cf_params(tpAniSirGlobal pCtx, + tDot11fIECFParams *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_cf_params. */ + +uint32_t dot11f_pack_ie_challenge_text(tpAniSirGlobal pCtx, + tDot11fIEChallengeText *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_challenge_text. */ + +uint32_t dot11f_pack_ie_chan_switch_ann(tpAniSirGlobal pCtx, + tDot11fIEChanSwitchAnn *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_chan_switch_ann. */ + +uint32_t dot11f_pack_ie_channel_switch_wrapper(tpAniSirGlobal pCtx, + tDot11fIEChannelSwitchWrapper *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_channel_switch_wrapper(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 = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_ChannelSwitchWrapper, + IES_ChannelSwitchWrapper); + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_channel_switch_wrapper. */ + +uint32_t dot11f_pack_ie_country(tpAniSirGlobal pCtx, + tDot11fIECountry *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_country(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 dot11f_pack_ie_country. */ + +uint32_t dot11f_pack_ie_ds_params(tpAniSirGlobal pCtx, + tDot11fIEDSParams *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ds_params. */ + +uint32_t dot11f_pack_ie_edca_param_set(tpAniSirGlobal pCtx, + tDot11fIEEDCAParamSet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp89__; + uint8_t tmp90__; + uint8_t tmp91__; + uint8_t tmp92__; + uint8_t tmp93__; + uint8_t tmp94__; + uint8_t tmp95__; + uint8_t tmp96__; + 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; + tmp89__ = 0U; + tmp89__ |= (pSrc->acbe_aifsn << 0); + tmp89__ |= (pSrc->acbe_acm << 4); + tmp89__ |= (pSrc->acbe_aci << 5); + tmp89__ |= (pSrc->unused1 << 7); + *pBuf = tmp89__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp90__ = 0U; + tmp90__ |= (pSrc->acbe_acwmin << 0); + tmp90__ |= (pSrc->acbe_acwmax << 4); + *pBuf = tmp90__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp91__ = 0U; + tmp91__ |= (pSrc->acbk_aifsn << 0); + tmp91__ |= (pSrc->acbk_acm << 4); + tmp91__ |= (pSrc->acbk_aci << 5); + tmp91__ |= (pSrc->unused2 << 7); + *pBuf = tmp91__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp92__ = 0U; + tmp92__ |= (pSrc->acbk_acwmin << 0); + tmp92__ |= (pSrc->acbk_acwmax << 4); + *pBuf = tmp92__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp93__ = 0U; + tmp93__ |= (pSrc->acvi_aifsn << 0); + tmp93__ |= (pSrc->acvi_acm << 4); + tmp93__ |= (pSrc->acvi_aci << 5); + tmp93__ |= (pSrc->unused3 << 7); + *pBuf = tmp93__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp94__ = 0U; + tmp94__ |= (pSrc->acvi_acwmin << 0); + tmp94__ |= (pSrc->acvi_acwmax << 4); + *pBuf = tmp94__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp95__ = 0U; + tmp95__ |= (pSrc->acvo_aifsn << 0); + tmp95__ |= (pSrc->acvo_acm << 4); + tmp95__ |= (pSrc->acvo_aci << 5); + tmp95__ |= (pSrc->unused4 << 7); + *pBuf = tmp95__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp96__ = 0U; + tmp96__ |= (pSrc->acvo_acwmin << 0); + tmp96__ |= (pSrc->acvo_acwmax << 4); + *pBuf = tmp96__; + *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 dot11f_pack_ie_edca_param_set. */ + +uint32_t dot11f_pack_ie_erp_info(tpAniSirGlobal pCtx, + tDot11fIEERPInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp97__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 42; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp97__ = 0U; + tmp97__ |= (pSrc->non_erp_present << 0); + tmp97__ |= (pSrc->use_prot << 1); + tmp97__ |= (pSrc->barker_preamble << 2); + tmp97__ |= (pSrc->unused << 3); + *pBuf = tmp97__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_erp_info. */ + +uint32_t dot11f_pack_ie_ese_cckm_opaque(tpAniSirGlobal pCtx, + tDot11fIEESECckmOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ese_cckm_opaque. */ + +uint32_t dot11f_pack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, + tDot11fIEESERadMgmtCap *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp98__; + 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; + tmp98__ = 0U; + tmp98__ |= (pSrc->mbssid_mask << 0); + tmp98__ |= (pSrc->reserved << 3); + *pBuf = tmp98__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_ese_rad_mgmt_cap. */ + +uint32_t dot11f_pack_ie_ese_traf_strm_met(tpAniSirGlobal pCtx, + tDot11fIEESETrafStrmMet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ese_traf_strm_met. */ + +uint32_t dot11f_pack_ie_ese_traf_strm_rate_set(tpAniSirGlobal pCtx, + tDot11fIEESETrafStrmRateSet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ese_traf_strm_rate_set. */ + +uint32_t dot11f_pack_ie_ese_txmit_power(tpAniSirGlobal pCtx, + tDot11fIEESETxmitPower *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ese_txmit_power. */ + +uint32_t dot11f_pack_ie_ese_version(tpAniSirGlobal pCtx, + tDot11fIEESEVersion *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ese_version. */ + +uint32_t dot11f_pack_ie_ext_cap(tpAniSirGlobal pCtx, + tDot11fIEExtCap *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ext_cap. */ + +uint32_t dot11f_pack_ie_ext_supp_rates(tpAniSirGlobal pCtx, + tDot11fIEExtSuppRates *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ext_supp_rates. */ + +uint32_t dot11f_pack_ie_fh_param_set(tpAniSirGlobal pCtx, + tDot11fIEFHParamSet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_fh_param_set. */ + +uint32_t dot11f_pack_ie_fh_params(tpAniSirGlobal pCtx, + tDot11fIEFHParams *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_fh_params. */ + +uint32_t dot11f_pack_ie_fh_patt_table(tpAniSirGlobal pCtx, + tDot11fIEFHPattTable *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_fh_patt_table. */ + +uint32_t dot11f_pack_ie_ft_info(tpAniSirGlobal pCtx, + tDot11fIEFTInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp99__; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ieft_info(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); + tmp99__ = 0U; + tmp99__ |= (pSrc->reserved << 0); + tmp99__ |= (pSrc->IECount << 8); + frameshtons(pCtx, pBuf, tmp99__, 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 = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_FTInfo, + IES_FTInfo); + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_ft_info. */ + +uint32_t dot11f_pack_ie_ht_caps(tpAniSirGlobal pCtx, + tDot11fIEHTCaps *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp100__; + uint8_t tmp101__; + uint16_t tmp102__; + uint32_t tmp103__; + uint8_t tmp104__; + nNeeded += (pSrc->num_rsvd + 26); + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 45; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp100__ = 0U; + tmp100__ |= (pSrc->advCodingCap << 0); + tmp100__ |= (pSrc->supportedChannelWidthSet << 1); + tmp100__ |= (pSrc->mimoPowerSave << 2); + tmp100__ |= (pSrc->greenField << 4); + tmp100__ |= (pSrc->shortGI20MHz << 5); + tmp100__ |= (pSrc->shortGI40MHz << 6); + tmp100__ |= (pSrc->txSTBC << 7); + tmp100__ |= (pSrc->rxSTBC << 8); + tmp100__ |= (pSrc->delayedBA << 10); + tmp100__ |= (pSrc->maximalAMSDUsize << 11); + tmp100__ |= (pSrc->dsssCckMode40MHz << 12); + tmp100__ |= (pSrc->psmp << 13); + tmp100__ |= (pSrc->stbcControlFrame << 14); + tmp100__ |= (pSrc->lsigTXOPProtection << 15); + frameshtons(pCtx, pBuf, tmp100__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp101__ = 0U; + tmp101__ |= (pSrc->maxRxAMPDUFactor << 0); + tmp101__ |= (pSrc->mpduDensity << 2); + tmp101__ |= (pSrc->reserved1 << 5); + *pBuf = tmp101__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->supportedMCSSet, 16); + *pnConsumed += 16; + pBuf += 16; + tmp102__ = 0U; + tmp102__ |= (pSrc->pco << 0); + tmp102__ |= (pSrc->transitionTime << 1); + tmp102__ |= (pSrc->reserved2 << 3); + tmp102__ |= (pSrc->mcsFeedback << 8); + tmp102__ |= (pSrc->reserved3 << 10); + frameshtons(pCtx, pBuf, tmp102__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp103__ = 0U; + tmp103__ |= (pSrc->txBF << 0); + tmp103__ |= (pSrc->rxStaggeredSounding << 1); + tmp103__ |= (pSrc->txStaggeredSounding << 2); + tmp103__ |= (pSrc->rxZLF << 3); + tmp103__ |= (pSrc->txZLF << 4); + tmp103__ |= (pSrc->implicitTxBF << 5); + tmp103__ |= (pSrc->calibration << 6); + tmp103__ |= (pSrc->explicitCSITxBF << 8); + tmp103__ |= (pSrc->explicitUncompressedSteeringMatrix << 9); + tmp103__ |= (pSrc->explicitBFCSIFeedback << 10); + tmp103__ |= (pSrc->explicitUncompressedSteeringMatrixFeedback << 13); + tmp103__ |= (pSrc->explicitCompressedSteeringMatrixFeedback << 16); + tmp103__ |= (pSrc->csiNumBFAntennae << 19); + tmp103__ |= (pSrc->uncompressedSteeringMatrixBFAntennae << 21); + tmp103__ |= (pSrc->compressedSteeringMatrixBFAntennae << 23); + tmp103__ |= (pSrc->reserved4 << 25); + frameshtonl(pCtx, pBuf, tmp103__, 0); + *pnConsumed += 4; + pBuf += 4; + nBuf -= 4 ; + tmp104__ = 0U; + tmp104__ |= (pSrc->antennaSelection << 0); + tmp104__ |= (pSrc->explicitCSIFeedbackTx << 1); + tmp104__ |= (pSrc->antennaIndicesFeedbackTx << 2); + tmp104__ |= (pSrc->explicitCSIFeedback << 3); + tmp104__ |= (pSrc->antennaIndicesFeedback << 4); + tmp104__ |= (pSrc->rxAS << 5); + tmp104__ |= (pSrc->txSoundingPPDUs << 6); + tmp104__ |= (pSrc->reserved5 << 7); + *pBuf = tmp104__; + *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 dot11f_pack_ie_ht_caps. */ + +uint32_t dot11f_pack_ie_ht_info(tpAniSirGlobal pCtx, + tDot11fIEHTInfo *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp105__; + uint16_t tmp106__; + uint16_t tmp107__; + 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; + tmp105__ = 0U; + tmp105__ |= (pSrc->secondaryChannelOffset << 0); + tmp105__ |= (pSrc->recommendedTxWidthSet << 2); + tmp105__ |= (pSrc->rifsMode << 3); + tmp105__ |= (pSrc->controlledAccessOnly << 4); + tmp105__ |= (pSrc->serviceIntervalGranularity << 5); + *pBuf = tmp105__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp106__ = 0U; + tmp106__ |= (pSrc->opMode << 0); + tmp106__ |= (pSrc->nonGFDevicesPresent << 2); + tmp106__ |= (pSrc->transmitBurstLimit << 3); + tmp106__ |= (pSrc->obssNonHTStaPresent << 4); + tmp106__ |= (pSrc->reserved << 5); + frameshtons(pCtx, pBuf, tmp106__, 0); + *pnConsumed += 2; + pBuf += 2; + nBuf -= 2 ; + tmp107__ = 0U; + tmp107__ |= (pSrc->basicSTBCMCS << 0); + tmp107__ |= (pSrc->dualCTSProtection << 7); + tmp107__ |= (pSrc->secondaryBeacon << 8); + tmp107__ |= (pSrc->lsigTXOPProtectionFullSupport << 9); + tmp107__ |= (pSrc->pcoActive << 10); + tmp107__ |= (pSrc->pcoPhase << 11); + tmp107__ |= (pSrc->reserved2 << 12); + frameshtons(pCtx, pBuf, tmp107__, 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 dot11f_pack_ie_ht_info. */ + +uint32_t dot11f_pack_ie_ibss_params(tpAniSirGlobal pCtx, + tDot11fIEIBSSParams *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ibss_params. */ + +uint32_t dot11f_pack_ie_link_identifier(tpAniSirGlobal pCtx, + tDot11fIELinkIdentifier *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_link_identifier. */ + +uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx, + tDot11fIEMeasurementReport *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp108__; + uint8_t tmp109__; + uint8_t tmp110__; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_measurement_report(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; + tmp108__ = 0U; + tmp108__ |= (pSrc->late << 0); + tmp108__ |= (pSrc->incapable << 1); + tmp108__ |= (pSrc->refused << 2); + tmp108__ |= (pSrc->unused << 3); + *pBuf = tmp108__; + *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; + tmp109__ = 0U; + tmp109__ |= (pSrc->report.Basic.bss << 0); + tmp109__ |= (pSrc->report.Basic.ofdm_preamble << 1); + tmp109__ |= (pSrc->report.Basic.unid_signal << 2); + tmp109__ |= (pSrc->report.Basic.rader << 3); + tmp109__ |= (pSrc->report.Basic.unmeasured << 4); + tmp109__ |= (pSrc->report.Basic.unused << 5); + *pBuf = tmp109__; + *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; + tmp110__ = 0U; + tmp110__ |= (pSrc->report.Beacon.condensed_PHY << 0); + tmp110__ |= (pSrc->report.Beacon.reported_frame_type << 7); + *pBuf = tmp110__; + *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 = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_reportBeacon, + IES_reportBeacon); + break; + } + } else { + break; + } + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_measurement_report. */ + +uint32_t dot11f_pack_ie_measurement_request(tpAniSirGlobal pCtx, + tDot11fIEMeasurementRequest *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp111__; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_measurement_request(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; + tmp111__ = 0U; + tmp111__ |= (pSrc->parallel << 0); + tmp111__ |= (pSrc->enable << 1); + tmp111__ |= (pSrc->request << 2); + tmp111__ |= (pSrc->report << 3); + tmp111__ |= (pSrc->durationMandatory << 4); + tmp111__ |= (pSrc->unused << 5); + *pBuf = tmp111__; + *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 = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_measurement_requestBeacon, + IES_measurement_requestBeacon); + break; + } + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_measurement_request. */ + +uint32_t dot11f_pack_ie_mobility_domain(tpAniSirGlobal pCtx, + tDot11fIEMobilityDomain *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp112__; + 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; + tmp112__ = 0U; + tmp112__ |= (pSrc->overDSCap << 0); + tmp112__ |= (pSrc->resourceReqCap << 1); + tmp112__ |= (pSrc->reserved << 2); + *pBuf = tmp112__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_mobility_domain. */ + +uint32_t dot11f_pack_ie_neighbor_report(tpAniSirGlobal pCtx, + tDot11fIENeighborReport *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp113__; + uint8_t tmp114__; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_neighbor_report(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; + tmp113__ = 0U; + tmp113__ |= (pSrc->APReachability << 0); + tmp113__ |= (pSrc->Security << 2); + tmp113__ |= (pSrc->KeyScope << 3); + tmp113__ |= (pSrc->SpecMgmtCap << 4); + tmp113__ |= (pSrc->QosCap << 5); + tmp113__ |= (pSrc->apsd << 6); + tmp113__ |= (pSrc->rrm << 7); + *pBuf = tmp113__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp114__ = 0U; + tmp114__ |= (pSrc->DelayedBA << 0); + tmp114__ |= (pSrc->ImmBA << 1); + tmp114__ |= (pSrc->MobilityDomain << 2); + tmp114__ |= (pSrc->reserved << 3); + *pBuf = tmp114__; + *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 = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_NeighborReport, + IES_NeighborReport); + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_neighbor_report. */ + +uint32_t dot11f_pack_ie_obss_scan_parameters(tpAniSirGlobal pCtx, + tDot11fIEOBSSScanParameters *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_obss_scan_parameters. */ + +uint32_t dot11f_pack_ie_operating_mode(tpAniSirGlobal pCtx, + tDot11fIEOperatingMode *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp115__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 199; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp115__ = 0U; + tmp115__ |= (pSrc->chanWidth << 0); + tmp115__ |= (pSrc->reserved << 2); + tmp115__ |= (pSrc->rxNSS << 4); + tmp115__ |= (pSrc->rxNSSType << 7); + *pBuf = tmp115__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_operating_mode. */ + +uint32_t dot11f_pack_ie_p2_p_assoc_req(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocReq *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_assoc_req(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_assoc_req. */ + +uint32_t dot11f_pack_ie_p2_p_assoc_res(tpAniSirGlobal pCtx, + tDot11fIEP2PAssocRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_assoc_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_assoc_res. */ + +uint32_t dot11f_pack_ie_p2_p_beacon(tpAniSirGlobal pCtx, + tDot11fIEP2PBeacon *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_beacon(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_beacon. */ + +uint32_t dot11f_pack_ie_p2_p_beacon_probe_res(tpAniSirGlobal pCtx, + tDot11fIEP2PBeaconProbeRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_beacon_probe_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_beacon_probe_res. */ + +uint32_t dot11f_pack_ie_p2_p_de_auth(tpAniSirGlobal pCtx, + tDot11fIEP2PDeAuth *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_de_auth(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_de_auth. */ + +uint32_t dot11f_pack_ie_p2_p_dis_assoc(tpAniSirGlobal pCtx, + tDot11fIEP2PDisAssoc *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_dis_assoc(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_dis_assoc. */ + +uint32_t dot11f_pack_ie_p2_pie_opaque(tpAniSirGlobal pCtx, + tDot11fIEP2PIEOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_p2_pie_opaque. */ + +uint32_t dot11f_pack_ie_p2_p_probe_req(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeReq *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_probe_req(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_probe_req. */ + +uint32_t dot11f_pack_ie_p2_p_probe_res(tpAniSirGlobal pCtx, + tDot11fIEP2PProbeRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iep2_p_probe_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_p2_p_probe_res. */ + +uint32_t dot11f_pack_ie_pti_control(tpAniSirGlobal pCtx, + tDot11fIEPTIControl *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_pti_control. */ + +uint32_t dot11f_pack_ie_pu_buffer_status(tpAniSirGlobal pCtx, + tDot11fIEPUBufferStatus *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp116__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 106; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp116__ = 0U; + tmp116__ |= (pSrc->ac_bk_traffic_aval << 0); + tmp116__ |= (pSrc->ac_be_traffic_aval << 1); + tmp116__ |= (pSrc->ac_vi_traffic_aval << 2); + tmp116__ |= (pSrc->ac_vo_traffic_aval << 3); + tmp116__ |= (pSrc->reserved << 4); + *pBuf = tmp116__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_pu_buffer_status. */ + +uint32_t dot11f_pack_ie_power_caps(tpAniSirGlobal pCtx, + tDot11fIEPowerCaps *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_power_caps. */ + +uint32_t dot11f_pack_ie_power_constraints(tpAniSirGlobal pCtx, + tDot11fIEPowerConstraints *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_power_constraints. */ + +uint32_t dot11f_pack_ie_qbss_load(tpAniSirGlobal pCtx, + tDot11fIEQBSSLoad *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_qbss_load. */ + +uint32_t dot11f_pack_ie_QComVendorIE(tpAniSirGlobal pCtx, + tDot11fIEQComVendorIE *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_QComVendorIE. */ + +uint32_t dot11f_pack_ie_qos_caps_ap(tpAniSirGlobal pCtx, + tDot11fIEQOSCapsAp *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp117__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 46; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp117__ = 0U; + tmp117__ |= (pSrc->count << 0); + tmp117__ |= (pSrc->qack << 4); + tmp117__ |= (pSrc->qreq << 5); + tmp117__ |= (pSrc->txopreq << 6); + tmp117__ |= (pSrc->reserved << 7); + *pBuf = tmp117__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_qos_caps_ap. */ + +uint32_t dot11f_pack_ie_qos_caps_station(tpAniSirGlobal pCtx, + tDot11fIEQOSCapsStation *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp118__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 46; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp118__ = 0U; + tmp118__ |= (pSrc->acvo_uapsd << 0); + tmp118__ |= (pSrc->acvi_uapsd << 1); + tmp118__ |= (pSrc->acbk_uapsd << 2); + tmp118__ |= (pSrc->acbe_uapsd << 3); + tmp118__ |= (pSrc->qack << 4); + tmp118__ |= (pSrc->max_sp_length << 5); + tmp118__ |= (pSrc->more_data_ack << 7); + *pBuf = tmp118__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_qos_caps_station. */ + +uint32_t dot11f_pack_ie_qos_map_set(tpAniSirGlobal pCtx, + tDot11fIEQosMapSet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_qos_map_set. */ + +uint32_t dot11f_pack_ie_quiet(tpAniSirGlobal pCtx, + tDot11fIEQuiet *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_quiet. */ + +uint32_t dot11f_pack_ie_rcpiie(tpAniSirGlobal pCtx, + tDot11fIERCPIIE *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_rcpiie. */ + +uint32_t dot11f_pack_ie_ric_data_desc(tpAniSirGlobal pCtx, + tDot11fIERICDataDesc *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ieric_data_desc(pCtx, pSrc, &nNeeded); + if (!DOT11F_SUCCEEDED(status)) + return status; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + status = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_RICDataDesc, + IES_RICDataDesc); + break; + } + (void)pCtx; + return status; +} /* End dot11f_pack_ie_ric_data_desc. */ + +uint32_t dot11f_pack_ie_rsn(tpAniSirGlobal pCtx, + tDot11fIERSN *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_iersn(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 dot11f_pack_ie_rsn. */ + +uint32_t dot11f_pack_ie_rsniie(tpAniSirGlobal pCtx, + tDot11fIERSNIIE *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_rsniie. */ + +uint32_t dot11f_pack_ie_rsn_opaque(tpAniSirGlobal pCtx, + tDot11fIERSNOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_rsn_opaque. */ + +uint32_t dot11f_pack_ie_supp_channels(tpAniSirGlobal pCtx, + tDot11fIESuppChannels *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_supp_channels. */ + +uint32_t dot11f_pack_ie_supp_operating_classes(tpAniSirGlobal pCtx, + tDot11fIESuppOperatingClasses *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_supp_operating_classes. */ + +uint32_t dot11f_pack_ie_supp_rates(tpAniSirGlobal pCtx, + tDot11fIESuppRates *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_supp_rates. */ + +uint32_t dot11f_pack_ie_tim(tpAniSirGlobal pCtx, + tDot11fIETIM *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_tim. */ + +uint32_t dot11f_pack_ie_tpc_report(tpAniSirGlobal pCtx, + tDot11fIETPCReport *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_tpc_report. */ + +uint32_t dot11f_pack_ie_tpc_request(tpAniSirGlobal pCtx, + tDot11fIETPCRequest *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_tpc_request. */ + +uint32_t dot11f_pack_ie_time_advertisement(tpAniSirGlobal pCtx, + tDot11fIETimeAdvertisement *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_time_advertisement. */ + +uint32_t dot11f_pack_ie_timeout_interval(tpAniSirGlobal pCtx, + tDot11fIETimeoutInterval *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_timeout_interval. */ + +uint32_t dot11f_pack_ie_vht_ext_bss_load(tpAniSirGlobal pCtx, + tDot11fIEVHTExtBssLoad *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_vht_ext_bss_load. */ + +uint32_t dot11f_pack_ie_vendor1_ie(tpAniSirGlobal pCtx, + tDot11fIEVendor1IE *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_vendor1_ie. */ + +uint32_t dot11f_pack_ie_vendor3_ie(tpAniSirGlobal pCtx, + tDot11fIEVendor3IE *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_vendor3_ie. */ + +uint32_t dot11f_pack_ie_wapi(tpAniSirGlobal pCtx, + tDot11fIEWAPI *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint16_t tmp119__; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_iewapi(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; + tmp119__ = 0U; + tmp119__ |= (pSrc->preauth << 0); + tmp119__ |= (pSrc->reserved << 1); + frameshtons(pCtx, pBuf, tmp119__, 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 dot11f_pack_ie_wapi. */ + +uint32_t dot11f_pack_ie_wapi_opaque(tpAniSirGlobal pCtx, + tDot11fIEWAPIOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wapi_opaque. */ + +uint32_t dot11f_pack_ie_wfatpc(tpAniSirGlobal pCtx, + tDot11fIEWFATPC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wfatpc. */ + +uint32_t dot11f_pack_ie_wfdie_opaque(tpAniSirGlobal pCtx, + tDot11fIEWFDIEOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wfdie_opaque. */ + +uint32_t dot11f_pack_ie_wmm_caps(tpAniSirGlobal pCtx, + tDot11fIEWMMCaps *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp120__; + 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; + tmp120__ = 0U; + tmp120__ |= (pSrc->reserved << 0); + tmp120__ |= (pSrc->qack << 4); + tmp120__ |= (pSrc->queue_request << 5); + tmp120__ |= (pSrc->txop_request << 6); + tmp120__ |= (pSrc->more_ack << 7); + *pBuf = tmp120__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_wmm_caps. */ + +uint32_t dot11f_pack_ie_wmm_info_ap(tpAniSirGlobal pCtx, + tDot11fIEWMMInfoAp *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp121__; + 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; + tmp121__ = 0U; + tmp121__ |= (pSrc->param_set_count << 0); + tmp121__ |= (pSrc->reserved << 4); + tmp121__ |= (pSrc->uapsd << 7); + *pBuf = tmp121__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_wmm_info_ap. */ + +uint32_t dot11f_pack_ie_wmm_info_station(tpAniSirGlobal pCtx, + tDot11fIEWMMInfoStation *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp122__; + 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; + tmp122__ = 0U; + tmp122__ |= (pSrc->acvo_uapsd << 0); + tmp122__ |= (pSrc->acvi_uapsd << 1); + tmp122__ |= (pSrc->acbk_uapsd << 2); + tmp122__ |= (pSrc->acbe_uapsd << 3); + tmp122__ |= (pSrc->reserved1 << 4); + tmp122__ |= (pSrc->max_sp_length << 5); + tmp122__ |= (pSrc->reserved2 << 7); + *pBuf = tmp122__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_wmm_info_station. */ + +uint32_t dot11f_pack_ie_wmm_params(tpAniSirGlobal pCtx, + tDot11fIEWMMParams *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp123__; + uint8_t tmp124__; + uint8_t tmp125__; + uint8_t tmp126__; + uint8_t tmp127__; + uint8_t tmp128__; + uint8_t tmp129__; + uint8_t tmp130__; + 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; + tmp123__ = 0U; + tmp123__ |= (pSrc->acbe_aifsn << 0); + tmp123__ |= (pSrc->acbe_acm << 4); + tmp123__ |= (pSrc->acbe_aci << 5); + tmp123__ |= (pSrc->unused1 << 7); + *pBuf = tmp123__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp124__ = 0U; + tmp124__ |= (pSrc->acbe_acwmin << 0); + tmp124__ |= (pSrc->acbe_acwmax << 4); + *pBuf = tmp124__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp125__ = 0U; + tmp125__ |= (pSrc->acbk_aifsn << 0); + tmp125__ |= (pSrc->acbk_acm << 4); + tmp125__ |= (pSrc->acbk_aci << 5); + tmp125__ |= (pSrc->unused2 << 7); + *pBuf = tmp125__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp126__ = 0U; + tmp126__ |= (pSrc->acbk_acwmin << 0); + tmp126__ |= (pSrc->acbk_acwmax << 4); + *pBuf = tmp126__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp127__ = 0U; + tmp127__ |= (pSrc->acvi_aifsn << 0); + tmp127__ |= (pSrc->acvi_acm << 4); + tmp127__ |= (pSrc->acvi_aci << 5); + tmp127__ |= (pSrc->unused3 << 7); + *pBuf = tmp127__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp128__ = 0U; + tmp128__ |= (pSrc->acvi_acwmin << 0); + tmp128__ |= (pSrc->acvi_acwmax << 4); + *pBuf = tmp128__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp129__ = 0U; + tmp129__ |= (pSrc->acvo_aifsn << 0); + tmp129__ |= (pSrc->acvo_acm << 4); + tmp129__ |= (pSrc->acvo_aci << 5); + tmp129__ |= (pSrc->unused4 << 7); + *pBuf = tmp129__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp130__ = 0U; + tmp130__ |= (pSrc->acvo_acwmin << 0); + tmp130__ |= (pSrc->acvo_acwmax << 4); + *pBuf = tmp130__; + *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 dot11f_pack_ie_wmm_params. */ + +uint32_t dot11f_pack_ie_wpa(tpAniSirGlobal pCtx, + tDot11fIEWPA *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_iewpa(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 dot11f_pack_ie_wpa. */ + +uint32_t dot11f_pack_ie_wpa_opaque(tpAniSirGlobal pCtx, + tDot11fIEWPAOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wpa_opaque. */ + +uint32_t dot11f_pack_ie_wsc(tpAniSirGlobal pCtx, + tDot11fIEWSC *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_iewsc(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc. */ + +uint32_t dot11f_pack_ie_wsc_assoc_req(tpAniSirGlobal pCtx, + tDot11fIEWscAssocReq *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_assoc_req(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_assoc_req. */ + +uint32_t dot11f_pack_ie_wsc_assoc_res(tpAniSirGlobal pCtx, + tDot11fIEWscAssocRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_assoc_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_assoc_res. */ + +uint32_t dot11f_pack_ie_wsc_beacon(tpAniSirGlobal pCtx, + tDot11fIEWscBeacon *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_beacon(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_beacon. */ + +uint32_t dot11f_pack_ie_wsc_beacon_probe_res(tpAniSirGlobal pCtx, + tDot11fIEWscBeaconProbeRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_beacon_probe_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_beacon_probe_res. */ + +uint32_t dot11f_pack_ie_wsc_ie_opaque(tpAniSirGlobal pCtx, + tDot11fIEWscIEOpaque *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_wsc_ie_opaque. */ + +uint32_t dot11f_pack_ie_wsc_probe_req(tpAniSirGlobal pCtx, + tDot11fIEWscProbeReq *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_probe_req(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_probe_req. */ + +uint32_t dot11f_pack_ie_wsc_probe_res(tpAniSirGlobal pCtx, + tDot11fIEWscProbeRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_probe_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_probe_res. */ + +uint32_t dot11f_pack_ie_wsc_reassoc_res(tpAniSirGlobal pCtx, + tDot11fIEWscReassocRes *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t n, idx = 0, idxlast; + uint32_t nConsumedSoFar, nConsumedNow; + uint32_t status = DOT11F_PARSE_SUCCESS; + uint32_t nNeeded = 0U; + status = dot11f_get_packed_ie_wsc_reassoc_res(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 = pack_tlv_core(pCtx, (uint8_t *)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 dot11f_pack_ie_wsc_reassoc_res. */ + +uint32_t dot11f_pack_ie_ext_chan_switch_ann(tpAniSirGlobal pCtx, + tDot11fIEext_chan_switch_ann *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_ext_chan_switch_ann. */ + +uint32_t dot11f_pack_ie_ht2040_bss_coexistence(tpAniSirGlobal pCtx, + tDot11fIEht2040_bss_coexistence *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint8_t tmp131__; + nNeeded += 1; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 72; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + tmp131__ = 0U; + tmp131__ |= (pSrc->info_request << 0); + tmp131__ |= (pSrc->forty_mhz_intolerant << 1); + tmp131__ |= (pSrc->twenty_mhz_bsswidth_req << 2); + tmp131__ |= (pSrc->obss_scan_exemption_req << 3); + tmp131__ |= (pSrc->obss_scan_exemption_grant << 4); + tmp131__ |= (pSrc->unused << 5); + *pBuf = tmp131__; + *pnConsumed += 1; + /* fieldsEndFlag = 1 */ + nBuf -= 1 ; + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_ht2040_bss_coexistence. */ + +uint32_t dot11f_pack_ie_ht2040_bss_intolerant_report(tpAniSirGlobal pCtx, + tDot11fIEht2040_bss_intolerant_report *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + nNeeded += (pSrc->num_channel_list + 1); + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 73; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = pSrc->operating_class; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, &(pSrc->channel_list), pSrc->num_channel_list); + *pnConsumed += pSrc->num_channel_list; + /* fieldsEndFlag = 1 */ + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11f_pack_ie_ht2040_bss_intolerant_report. */ + +uint32_t dot11f_pack_ie_sec_chan_offset_ele(tpAniSirGlobal pCtx, + tDot11fIEsec_chan_offset_ele *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t 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 dot11f_pack_ie_sec_chan_offset_ele. */ + +uint32_t dot11f_pack_ie_vendor2_ie(tpAniSirGlobal pCtx, + tDot11fIEvendor2_ie *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed) +{ + uint8_t *pIeLen = 0; + uint32_t nConsumedOnEntry = *pnConsumed; + uint32_t nNeeded = 0U; + uint32_t status = DOT11F_PARSE_SUCCESS; + status = dot11f_get_packed_ie_vendor2_ie(pCtx, pSrc, &nNeeded); + if (!DOT11F_SUCCEEDED(status)) + return status; + while (pSrc->present) { + if (nNeeded > nBuf) + return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; --nBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x0; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x90; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = 0x4c; + ++pBuf; --nBuf; ++(*pnConsumed); + *pBuf = pSrc->type; + *pnConsumed += 1; + pBuf += 1; + *pBuf = pSrc->sub_type; + *pnConsumed += 1; + pBuf += 1; + status = pack_core(pCtx, + (uint8_t *)pSrc, + pBuf, + nBuf, + pnConsumed, + FFS_vendor2_ie, + IES_vendor2_ie); + break; + } + (void)pCtx; + if (pIeLen) { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11f_pack_ie_vendor2_ie. */ + +uint32_t dot11f_pack_add_ts_request(tpAniSirGlobal pCtx, + tDot11fAddTSRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_AddTSRequest, IES_AddTSRequest); + + return status; + +} /* End dot11f_unpack_add_ts_request. */ + +uint32_t dot11f_pack_add_ts_response(tpAniSirGlobal pCtx, + tDot11fAddTSResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_AddTSResponse, IES_AddTSResponse); + + return status; + +} /* End dot11f_unpack_add_ts_response. */ + +uint32_t dot11f_pack_assoc_request(tpAniSirGlobal pCtx, + tDot11fAssocRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_AssocRequest, IES_AssocRequest); + + return status; + +} /* End dot11f_unpack_assoc_request. */ + +uint32_t dot11f_pack_assoc_response(tpAniSirGlobal pCtx, + tDot11fAssocResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_AssocResponse, IES_AssocResponse); + + return status; + +} /* End dot11f_unpack_assoc_response. */ + +uint32_t dot11f_pack_authentication(tpAniSirGlobal pCtx, + tDot11fAuthentication *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_Authentication, IES_Authentication); + + return status; + +} /* End dot11f_unpack_authentication. */ + +uint32_t dot11f_pack_beacon(tpAniSirGlobal pCtx, + tDot11fBeacon *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_Beacon, IES_Beacon); + + return status; + +} /* End dot11f_unpack_beacon. */ + +uint32_t dot11f_pack_beacon1(tpAniSirGlobal pCtx, + tDot11fBeacon1 *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_Beacon1, IES_Beacon1); + + return status; + +} /* End dot11f_unpack_beacon1. */ + +uint32_t dot11f_pack_beacon2(tpAniSirGlobal pCtx, + tDot11fBeacon2 *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_Beacon2, IES_Beacon2); + + return status; + +} /* End dot11f_unpack_beacon2. */ + +uint32_t dot11f_pack_beacon_i_es(tpAniSirGlobal pCtx, + tDot11fBeaconIEs *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_BeaconIEs, IES_BeaconIEs); + + return status; + +} /* End dot11f_unpack_beacon_i_es. */ + +uint32_t dot11f_pack_channel_switch(tpAniSirGlobal pCtx, + tDot11fChannelSwitch *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ChannelSwitch, IES_ChannelSwitch); + + return status; + +} /* End dot11f_unpack_channel_switch. */ + +uint32_t dot11f_pack_de_auth(tpAniSirGlobal pCtx, + tDot11fDeAuth *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_DeAuth, IES_DeAuth); + + return status; + +} /* End dot11f_unpack_de_auth. */ + +uint32_t dot11f_pack_del_ts(tpAniSirGlobal pCtx, + tDot11fDelTS *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_DelTS, IES_DelTS); + + return status; + +} /* End dot11f_unpack_del_ts. */ + +uint32_t dot11f_pack_disassociation(tpAniSirGlobal pCtx, + tDot11fDisassociation *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_Disassociation, IES_Disassociation); + + return status; + +} /* End dot11f_unpack_disassociation. */ + +uint32_t dot11f_pack_link_measurement_report(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementReport *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_LinkMeasurementReport, IES_LinkMeasurementReport); + + return status; + +} /* End dot11f_unpack_link_measurement_report. */ + +uint32_t dot11f_pack_link_measurement_request(tpAniSirGlobal pCtx, + tDot11fLinkMeasurementRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_LinkMeasurementRequest, IES_LinkMeasurementRequest); + + return status; + +} /* End dot11f_unpack_link_measurement_request. */ + +uint32_t dot11f_pack_measurement_report(tpAniSirGlobal pCtx, + tDot11fMeasurementReport *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_MeasurementReport, IES_MeasurementReport); + + return status; + +} /* End dot11f_unpack_measurement_report. */ + +uint32_t dot11f_pack_measurement_request(tpAniSirGlobal pCtx, + tDot11fMeasurementRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_MeasurementRequest, IES_MeasurementRequest); + + return status; + +} /* End dot11f_unpack_measurement_request. */ + +uint32_t dot11f_pack_neighbor_report_request(tpAniSirGlobal pCtx, + tDot11fNeighborReportRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_NeighborReportRequest, IES_NeighborReportRequest); + + return status; + +} /* End dot11f_unpack_neighbor_report_request. */ + +uint32_t dot11f_pack_neighbor_report_response(tpAniSirGlobal pCtx, + tDot11fNeighborReportResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_NeighborReportResponse, IES_NeighborReportResponse); + + return status; + +} /* End dot11f_unpack_neighbor_report_response. */ + +uint32_t dot11f_pack_operating_mode(tpAniSirGlobal pCtx, + tDot11fOperatingMode *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_OperatingMode, IES_OperatingMode); + + return status; + +} /* End dot11f_unpack_operating_mode. */ + +uint32_t dot11f_pack_probe_request(tpAniSirGlobal pCtx, + tDot11fProbeRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ProbeRequest, IES_ProbeRequest); + + return status; + +} /* End dot11f_unpack_probe_request. */ + +uint32_t dot11f_pack_probe_response(tpAniSirGlobal pCtx, + tDot11fProbeResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ProbeResponse, IES_ProbeResponse); + + return status; + +} /* End dot11f_unpack_probe_response. */ + +uint32_t dot11f_pack_qos_map_configure(tpAniSirGlobal pCtx, + tDot11fQosMapConfigure *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_QosMapConfigure, IES_QosMapConfigure); + + return status; + +} /* End dot11f_unpack_qos_map_configure. */ + +uint32_t dot11f_pack_radio_measurement_report(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementReport *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_RadioMeasurementReport, IES_RadioMeasurementReport); + + return status; + +} /* End dot11f_unpack_radio_measurement_report. */ + +uint32_t dot11f_pack_radio_measurement_request(tpAniSirGlobal pCtx, + tDot11fRadioMeasurementRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_RadioMeasurementRequest, IES_RadioMeasurementRequest); + + return status; + +} /* End dot11f_unpack_radio_measurement_request. */ + +uint32_t dot11f_pack_re_assoc_request(tpAniSirGlobal pCtx, + tDot11fReAssocRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ReAssocRequest, IES_ReAssocRequest); + + return status; + +} /* End dot11f_unpack_re_assoc_request. */ + +uint32_t dot11f_pack_re_assoc_response(tpAniSirGlobal pCtx, + tDot11fReAssocResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ReAssocResponse, IES_ReAssocResponse); + + return status; + +} /* End dot11f_unpack_re_assoc_response. */ + +uint32_t dot11f_pack_sm_power_save(tpAniSirGlobal pCtx, + tDot11fSMPowerSave *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_SMPowerSave, IES_SMPowerSave); + + return status; + +} /* End dot11f_unpack_sm_power_save. */ + +uint32_t dot11f_pack_sa_query_req(tpAniSirGlobal pCtx, + tDot11fSaQueryReq *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_SaQueryReq, IES_SaQueryReq); + + return status; + +} /* End dot11f_unpack_sa_query_req. */ + +uint32_t dot11f_pack_sa_query_rsp(tpAniSirGlobal pCtx, + tDot11fSaQueryRsp *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_SaQueryRsp, IES_SaQueryRsp); + + return status; + +} /* End dot11f_unpack_sa_query_rsp. */ + +uint32_t dot11f_pack_tdls_dis_req(tpAniSirGlobal pCtx, + tDot11fTDLSDisReq *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSDisReq, IES_TDLSDisReq); + + return status; + +} /* End dot11f_unpack_tdls_dis_req. */ + +uint32_t dot11f_pack_tdls_dis_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSDisRsp *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSDisRsp, IES_TDLSDisRsp); + + return status; + +} /* End dot11f_unpack_tdls_dis_rsp. */ + +uint32_t dot11f_pack_tdls_peer_traffic_ind(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficInd *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSPeerTrafficInd, IES_TDLSPeerTrafficInd); + + return status; + +} /* End dot11f_unpack_tdls_peer_traffic_ind. */ + +uint32_t dot11f_pack_tdls_peer_traffic_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSPeerTrafficRsp *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSPeerTrafficRsp, IES_TDLSPeerTrafficRsp); + + return status; + +} /* End dot11f_unpack_tdls_peer_traffic_rsp. */ + +uint32_t dot11f_pack_tdls_setup_cnf(tpAniSirGlobal pCtx, + tDot11fTDLSSetupCnf *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSSetupCnf, IES_TDLSSetupCnf); + + return status; + +} /* End dot11f_unpack_tdls_setup_cnf. */ + +uint32_t dot11f_pack_tdls_setup_req(tpAniSirGlobal pCtx, + tDot11fTDLSSetupReq *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSSetupReq, IES_TDLSSetupReq); + + return status; + +} /* End dot11f_unpack_tdls_setup_req. */ + +uint32_t dot11f_pack_tdls_setup_rsp(tpAniSirGlobal pCtx, + tDot11fTDLSSetupRsp *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSSetupRsp, IES_TDLSSetupRsp); + + return status; + +} /* End dot11f_unpack_tdls_setup_rsp. */ + +uint32_t dot11f_pack_tdls_teardown(tpAniSirGlobal pCtx, + tDot11fTDLSTeardown *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TDLSTeardown, IES_TDLSTeardown); + + return status; + +} /* End dot11f_unpack_tdls_teardown. */ + +uint32_t dot11f_pack_tpc_report(tpAniSirGlobal pCtx, + tDot11fTPCReport *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TPCReport, IES_TPCReport); + + return status; + +} /* End dot11f_unpack_tpc_report. */ + +uint32_t dot11f_pack_tpc_request(tpAniSirGlobal pCtx, + tDot11fTPCRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TPCRequest, IES_TPCRequest); + + return status; + +} /* End dot11f_unpack_tpc_request. */ + +uint32_t dot11f_pack_timing_advertisement_frame(tpAniSirGlobal pCtx, + tDot11fTimingAdvertisementFrame *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_TimingAdvertisementFrame, IES_TimingAdvertisementFrame); + + return status; + +} /* End dot11f_unpack_timing_advertisement_frame. */ + +uint32_t dot11f_pack_vht_gid_management_action_frame(tpAniSirGlobal pCtx, + tDot11fVHTGidManagementActionFrame *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_VHTGidManagementActionFrame, IES_VHTGidManagementActionFrame); + + return status; + +} /* End dot11f_unpack_vht_gid_management_action_frame. */ + +uint32_t dot11f_pack_wmm_add_ts_request(tpAniSirGlobal pCtx, + tDot11fWMMAddTSRequest *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_WMMAddTSRequest, IES_WMMAddTSRequest); + + return status; + +} /* End dot11f_unpack_wmm_add_ts_request. */ + +uint32_t dot11f_pack_wmm_add_ts_response(tpAniSirGlobal pCtx, + tDot11fWMMAddTSResponse *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_WMMAddTSResponse, IES_WMMAddTSResponse); + + return status; + +} /* End dot11f_unpack_wmm_add_ts_response. */ + +uint32_t dot11f_pack_wmm_del_ts(tpAniSirGlobal pCtx, + tDot11fWMMDelTS *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_WMMDelTS, IES_WMMDelTS); + + return status; + +} /* End dot11f_unpack_wmm_del_ts. */ + +uint32_t dot11f_pack_ht2040_bss_coexistence_mgmt_action_frame(tpAniSirGlobal pCtx, + tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ht2040_bss_coexistence_mgmt_action_frame, IES_ht2040_bss_coexistence_mgmt_action_frame); + + return status; + +} /* End dot11f_unpack_ht2040_bss_coexistence_mgmt_action_frame. */ + +static uint32_t pack_core(tpAniSirGlobal pCtx, + uint8_t *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed, + const tFFDefn FFs[], + const tIEDefn IEs[]) +{ + const tFFDefn *pFf; + const tIEDefn *pIe; + tFRAMES_BOOL *pfFound; + uint8_t *pBufRemaining; + uint16_t i; + uint32_t nBufRemaining, status, len; + uint32_t 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: + dot11f_pack_ff_aid( + pCtx, (tDot11fFfAID *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAction: + dot11f_pack_ff_action( + pCtx, (tDot11fFfAction *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAuthAlgo: + dot11f_pack_ff_auth_algo( + pCtx, (tDot11fFfAuthAlgo *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfAuthSeqNo: + dot11f_pack_ff_auth_seq_no( + pCtx, (tDot11fFfAuthSeqNo *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfBeaconInterval: + dot11f_pack_ff_beacon_interval( + pCtx, (tDot11fFfBeaconInterval *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCapabilities: + dot11f_pack_ff_capabilities( + pCtx, (tDot11fFfCapabilities *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCategory: + dot11f_pack_ff_category( + pCtx, (tDot11fFfCategory *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfCurrentAPAddress: + dot11f_pack_ff_current_ap_address( + pCtx, (tDot11fFfCurrentAPAddress *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfDialogToken: + dot11f_pack_ff_dialog_token( + pCtx, (tDot11fFfDialogToken *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfLinkMargin: + dot11f_pack_ff_link_margin( + pCtx, (tDot11fFfLinkMargin *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfListenInterval: + dot11f_pack_ff_listen_interval( + pCtx, (tDot11fFfListenInterval *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfMaxTxPower: + dot11f_pack_ff_max_tx_power( + pCtx, (tDot11fFfMaxTxPower *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfNumOfRepetitions: + dot11f_pack_ff_num_of_repetitions( + pCtx, (tDot11fFfNumOfRepetitions *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfOperatingMode: + dot11f_pack_ff_operating_mode( + pCtx, (tDot11fFfOperatingMode *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRCPI: + dot11f_pack_ff_rcpi( + pCtx, (tDot11fFfRCPI *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRSNI: + dot11f_pack_ff_rsni( + pCtx, (tDot11fFfRSNI *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfReason: + dot11f_pack_ff_reason( + pCtx, (tDot11fFfReason *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfRxAntennaId: + dot11f_pack_ff_rx_antenna_id( + pCtx, (tDot11fFfRxAntennaId *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfSMPowerModeSet: + dot11f_pack_ff_sm_power_mode_set( + pCtx, (tDot11fFfSMPowerModeSet *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfStatus: + dot11f_pack_ff_status( + pCtx, (tDot11fFfStatus *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfStatusCode: + dot11f_pack_ff_status_code( + pCtx, (tDot11fFfStatusCode *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTPCEleID: + dot11f_pack_ff_tpc_ele_id( + pCtx, (tDot11fFfTPCEleID *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTPCEleLen: + dot11f_pack_ff_tpc_ele_len( + pCtx, (tDot11fFfTPCEleLen *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTSInfo: + dot11f_pack_ff_ts_info( + pCtx, (tDot11fFfTSInfo *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTimeStamp: + dot11f_pack_ff_time_stamp( + pCtx, (tDot11fFfTimeStamp *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTransactionId: + dot11f_pack_ff_transaction_id( + pCtx, (tDot11fFfTransactionId *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTxAntennaId: + dot11f_pack_ff_tx_antenna_id( + pCtx, (tDot11fFfTxAntennaId *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfTxPower: + dot11f_pack_ff_tx_power( + pCtx, (tDot11fFfTxPower *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfVhtMembershipStatusArray: + dot11f_pack_ff_vht_membership_status_array( + pCtx, (tDot11fFfVhtMembershipStatusArray *) + (pSrc + pFf->offset), pBufRemaining); + break; + case SigFfVhtUserPositionArray: + dot11f_pack_ff_vht_user_position_array( + pCtx, (tDot11fFfVhtUserPositionArray *) + (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 : *(uint16_t *)(pSrc + pIe->countOffset)); + for (i = 0; i < countOffset; ++i) { + len = 0U; + switch (pIe->sig) { + case SigIeCondensedCountryStr: + status |= + dot11f_pack_ie_condensed_country_str( + pCtx, (tDot11fIECondensedCountryStr *) + (pSrc + pIe->offset + + sizeof(tDot11fIECondensedCountryStr) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeGTK: + status |= + dot11f_pack_ie_gtk( + pCtx, (tDot11fIEGTK *) + (pSrc + pIe->offset + + sizeof(tDot11fIEGTK) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeIGTK: + status |= + dot11f_pack_ie_igtk( + pCtx, (tDot11fIEIGTK *) + (pSrc + pIe->offset + + sizeof(tDot11fIEIGTK) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeR0KH_ID: + status |= + dot11f_pack_ie_r0_kh_id( + pCtx, (tDot11fIER0KH_ID *) + (pSrc + pIe->offset + + sizeof(tDot11fIER0KH_ID) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeR1KH_ID: + status |= + dot11f_pack_ie_r1_kh_id( + pCtx, (tDot11fIER1KH_ID *) + (pSrc + pIe->offset + + sizeof(tDot11fIER1KH_ID) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSFInfo: + status |= + dot11f_pack_ie_tsf_info( + pCtx, (tDot11fIETSFInfo *) + (pSrc + pIe->offset + + sizeof(tDot11fIETSFInfo) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeAPChannelReport: + status |= + dot11f_pack_ie_ap_channel_report( + pCtx, (tDot11fIEAPChannelReport *) + (pSrc + pIe->offset + + sizeof(tDot11fIEAPChannelReport) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeBcnReportingDetail: + status |= + dot11f_pack_ie_bcn_reporting_detail( + pCtx, (tDot11fIEBcnReportingDetail *) + (pSrc + pIe->offset + + sizeof(tDot11fIEBcnReportingDetail) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeBeaconReportFrmBody: + status |= + dot11f_pack_ie_beacon_report_frm_body( + pCtx, (tDot11fIEBeaconReportFrmBody *) + (pSrc + pIe->offset + + sizeof(tDot11fIEBeaconReportFrmBody) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeBeaconReporting: + status |= + dot11f_pack_ie_beacon_reporting( + pCtx, (tDot11fIEBeaconReporting *) + (pSrc + pIe->offset + + sizeof(tDot11fIEBeaconReporting) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementPilot: + status |= + dot11f_pack_ie_measurement_pilot( + pCtx, (tDot11fIEMeasurementPilot *) + (pSrc + pIe->offset + + sizeof(tDot11fIEMeasurementPilot) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeMultiBssid: + status |= + dot11f_pack_ie_multi_bssid( + pCtx, (tDot11fIEMultiBssid *) + (pSrc + pIe->offset + + sizeof(tDot11fIEMultiBssid) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICData: + status |= + dot11f_pack_ie_ric_data( + pCtx, (tDot11fIERICData *) + (pSrc + pIe->offset + + sizeof(tDot11fIERICData) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICDescriptor: + status |= + dot11f_pack_ie_ric_descriptor( + pCtx, (tDot11fIERICDescriptor *) + (pSrc + pIe->offset + + sizeof(tDot11fIERICDescriptor) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRRMEnabledCap: + status |= + dot11f_pack_ie_rrm_enabled_cap( + pCtx, (tDot11fIERRMEnabledCap *) + (pSrc + pIe->offset + + sizeof(tDot11fIERRMEnabledCap) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRequestedInfo: + status |= + dot11f_pack_ie_requested_info( + pCtx, (tDot11fIERequestedInfo *) + (pSrc + pIe->offset + + sizeof(tDot11fIERequestedInfo) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeSSID: + status |= + dot11f_pack_ie_ssid( + pCtx, (tDot11fIESSID *) + (pSrc + pIe->offset + + sizeof(tDot11fIESSID) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeSchedule: + status |= + dot11f_pack_ie_schedule( + pCtx, (tDot11fIESchedule *) + (pSrc + pIe->offset + + sizeof(tDot11fIESchedule) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTCLAS: + status |= + dot11f_pack_ie_tclas( + pCtx, (tDot11fIETCLAS *) + (pSrc + pIe->offset + + sizeof(tDot11fIETCLAS) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTCLASSPROC: + status |= + dot11f_pack_ie_tclassproc( + pCtx, (tDot11fIETCLASSPROC *) + (pSrc + pIe->offset + + sizeof(tDot11fIETCLASSPROC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSDelay: + status |= + dot11f_pack_ie_ts_delay( + pCtx, (tDot11fIETSDelay *) + (pSrc + pIe->offset + + sizeof(tDot11fIETSDelay) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTSPEC: + status |= + dot11f_pack_ie_tspec( + pCtx, (tDot11fIETSPEC *) + (pSrc + pIe->offset + + sizeof(tDot11fIETSPEC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTCaps: + status |= + dot11f_pack_ie_vht_caps( + pCtx, (tDot11fIEVHTCaps *) + (pSrc + pIe->offset + + sizeof(tDot11fIEVHTCaps) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTOperation: + status |= + dot11f_pack_ie_vht_operation( + pCtx, (tDot11fIEVHTOperation *) + (pSrc + pIe->offset + + sizeof(tDot11fIEVHTOperation) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMSchedule: + status |= + dot11f_pack_ie_wmm_schedule( + pCtx, (tDot11fIEWMMSchedule *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMSchedule) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTCLAS: + status |= + dot11f_pack_ie_wmmtclas( + pCtx, (tDot11fIEWMMTCLAS *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMTCLAS) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTCLASPROC: + status |= + dot11f_pack_ie_wmmtclasproc( + pCtx, (tDot11fIEWMMTCLASPROC *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMTCLASPROC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTSDelay: + status |= + dot11f_pack_ie_wmmts_delay( + pCtx, (tDot11fIEWMMTSDelay *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMTSDelay) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMTSPEC: + status |= + dot11f_pack_ie_wmmtspec( + pCtx, (tDot11fIEWMMTSPEC *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMTSPEC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWiderBWChanSwitchAnn: + status |= + dot11f_pack_ie_wider_bw_chan_switch_ann( + pCtx, (tDot11fIEWiderBWChanSwitchAnn *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWiderBWChanSwitchAnn) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeAID: + status |= + dot11f_pack_ie_aid( + pCtx, (tDot11fIEAID *) + (pSrc + pIe->offset + + sizeof(tDot11fIEAID) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeCFParams: + status |= + dot11f_pack_ie_cf_params( + pCtx, (tDot11fIECFParams *) + (pSrc + pIe->offset + + sizeof(tDot11fIECFParams) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeChallengeText: + status |= + dot11f_pack_ie_challenge_text( + pCtx, (tDot11fIEChallengeText *) + (pSrc + pIe->offset + + sizeof(tDot11fIEChallengeText) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeChanSwitchAnn: + status |= + dot11f_pack_ie_chan_switch_ann( + pCtx, (tDot11fIEChanSwitchAnn *) + (pSrc + pIe->offset + + sizeof(tDot11fIEChanSwitchAnn) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeChannelSwitchWrapper: + status |= + dot11f_pack_ie_channel_switch_wrapper( + pCtx, (tDot11fIEChannelSwitchWrapper *) + (pSrc + pIe->offset + + sizeof(tDot11fIEChannelSwitchWrapper) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeCountry: + status |= + dot11f_pack_ie_country( + pCtx, (tDot11fIECountry *) + (pSrc + pIe->offset + + sizeof(tDot11fIECountry) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeDSParams: + status |= + dot11f_pack_ie_ds_params( + pCtx, (tDot11fIEDSParams *) + (pSrc + pIe->offset + + sizeof(tDot11fIEDSParams) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeEDCAParamSet: + status |= + dot11f_pack_ie_edca_param_set( + pCtx, (tDot11fIEEDCAParamSet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEEDCAParamSet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeERPInfo: + status |= + dot11f_pack_ie_erp_info( + pCtx, (tDot11fIEERPInfo *) + (pSrc + pIe->offset + + sizeof(tDot11fIEERPInfo) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESECckmOpaque: + status |= + dot11f_pack_ie_ese_cckm_opaque( + pCtx, (tDot11fIEESECckmOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESECckmOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESERadMgmtCap: + status |= + dot11f_pack_ie_ese_rad_mgmt_cap( + pCtx, (tDot11fIEESERadMgmtCap *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESERadMgmtCap) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETrafStrmMet: + status |= + dot11f_pack_ie_ese_traf_strm_met( + pCtx, (tDot11fIEESETrafStrmMet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESETrafStrmMet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETrafStrmRateSet: + status |= + dot11f_pack_ie_ese_traf_strm_rate_set( + pCtx, (tDot11fIEESETrafStrmRateSet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESETrafStrmRateSet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESETxmitPower: + status |= + dot11f_pack_ie_ese_txmit_power( + pCtx, (tDot11fIEESETxmitPower *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESETxmitPower) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeESEVersion: + status |= + dot11f_pack_ie_ese_version( + pCtx, (tDot11fIEESEVersion *) + (pSrc + pIe->offset + + sizeof(tDot11fIEESEVersion) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeExtCap: + status |= + dot11f_pack_ie_ext_cap( + pCtx, (tDot11fIEExtCap *) + (pSrc + pIe->offset + + sizeof(tDot11fIEExtCap) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeExtSuppRates: + status |= + dot11f_pack_ie_ext_supp_rates( + pCtx, (tDot11fIEExtSuppRates *) + (pSrc + pIe->offset + + sizeof(tDot11fIEExtSuppRates) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHParamSet: + status |= + dot11f_pack_ie_fh_param_set( + pCtx, (tDot11fIEFHParamSet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEFHParamSet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHParams: + status |= + dot11f_pack_ie_fh_params( + pCtx, (tDot11fIEFHParams *) + (pSrc + pIe->offset + + sizeof(tDot11fIEFHParams) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeFHPattTable: + status |= + dot11f_pack_ie_fh_patt_table( + pCtx, (tDot11fIEFHPattTable *) + (pSrc + pIe->offset + + sizeof(tDot11fIEFHPattTable) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeFTInfo: + status |= + dot11f_pack_ie_ft_info( + pCtx, (tDot11fIEFTInfo *) + (pSrc + pIe->offset + + sizeof(tDot11fIEFTInfo) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeHTCaps: + status |= + dot11f_pack_ie_ht_caps( + pCtx, (tDot11fIEHTCaps *) + (pSrc + pIe->offset + + sizeof(tDot11fIEHTCaps) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeHTInfo: + status |= + dot11f_pack_ie_ht_info( + pCtx, (tDot11fIEHTInfo *) + (pSrc + pIe->offset + + sizeof(tDot11fIEHTInfo) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeIBSSParams: + status |= + dot11f_pack_ie_ibss_params( + pCtx, (tDot11fIEIBSSParams *) + (pSrc + pIe->offset + + sizeof(tDot11fIEIBSSParams) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeLinkIdentifier: + status |= + dot11f_pack_ie_link_identifier( + pCtx, (tDot11fIELinkIdentifier *) + (pSrc + pIe->offset + + sizeof(tDot11fIELinkIdentifier) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementReport: + status |= + dot11f_pack_ie_measurement_report( + pCtx, (tDot11fIEMeasurementReport *) + (pSrc + pIe->offset + + sizeof(tDot11fIEMeasurementReport) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeMeasurementRequest: + status |= + dot11f_pack_ie_measurement_request( + pCtx, (tDot11fIEMeasurementRequest *) + (pSrc + pIe->offset + + sizeof(tDot11fIEMeasurementRequest) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeMobilityDomain: + status |= + dot11f_pack_ie_mobility_domain( + pCtx, (tDot11fIEMobilityDomain *) + (pSrc + pIe->offset + + sizeof(tDot11fIEMobilityDomain) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeNeighborReport: + status |= + dot11f_pack_ie_neighbor_report( + pCtx, (tDot11fIENeighborReport *) + (pSrc + pIe->offset + + sizeof(tDot11fIENeighborReport) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeOBSSScanParameters: + status |= + dot11f_pack_ie_obss_scan_parameters( + pCtx, (tDot11fIEOBSSScanParameters *) + (pSrc + pIe->offset + + sizeof(tDot11fIEOBSSScanParameters) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeOperatingMode: + status |= + dot11f_pack_ie_operating_mode( + pCtx, (tDot11fIEOperatingMode *) + (pSrc + pIe->offset + + sizeof(tDot11fIEOperatingMode) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PAssocReq: + status |= + dot11f_pack_ie_p2_p_assoc_req( + pCtx, (tDot11fIEP2PAssocReq *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PAssocReq) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PAssocRes: + status |= + dot11f_pack_ie_p2_p_assoc_res( + pCtx, (tDot11fIEP2PAssocRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PAssocRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PBeacon: + status |= + dot11f_pack_ie_p2_p_beacon( + pCtx, (tDot11fIEP2PBeacon *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PBeacon) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PBeaconProbeRes: + status |= + dot11f_pack_ie_p2_p_beacon_probe_res( + pCtx, (tDot11fIEP2PBeaconProbeRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PBeaconProbeRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDeAuth: + status |= + dot11f_pack_ie_p2_p_de_auth( + pCtx, (tDot11fIEP2PDeAuth *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PDeAuth) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PDisAssoc: + status |= + dot11f_pack_ie_p2_p_dis_assoc( + pCtx, (tDot11fIEP2PDisAssoc *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PDisAssoc) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PIEOpaque: + status |= + dot11f_pack_ie_p2_pie_opaque( + pCtx, (tDot11fIEP2PIEOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PIEOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PProbeReq: + status |= + dot11f_pack_ie_p2_p_probe_req( + pCtx, (tDot11fIEP2PProbeReq *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PProbeReq) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeP2PProbeRes: + status |= + dot11f_pack_ie_p2_p_probe_res( + pCtx, (tDot11fIEP2PProbeRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEP2PProbeRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIePTIControl: + status |= + dot11f_pack_ie_pti_control( + pCtx, (tDot11fIEPTIControl *) + (pSrc + pIe->offset + + sizeof(tDot11fIEPTIControl) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIePUBufferStatus: + status |= + dot11f_pack_ie_pu_buffer_status( + pCtx, (tDot11fIEPUBufferStatus *) + (pSrc + pIe->offset + + sizeof(tDot11fIEPUBufferStatus) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIePowerCaps: + status |= + dot11f_pack_ie_power_caps( + pCtx, (tDot11fIEPowerCaps *) + (pSrc + pIe->offset + + sizeof(tDot11fIEPowerCaps) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIePowerConstraints: + status |= + dot11f_pack_ie_power_constraints( + pCtx, (tDot11fIEPowerConstraints *) + (pSrc + pIe->offset + + sizeof(tDot11fIEPowerConstraints) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQBSSLoad: + status |= + dot11f_pack_ie_qbss_load( + pCtx, (tDot11fIEQBSSLoad *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQBSSLoad) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQComVendorIE: + status |= + dot11f_pack_ie_QComVendorIE( + pCtx, (tDot11fIEQComVendorIE *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQComVendorIE) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQOSCapsAp: + status |= + dot11f_pack_ie_qos_caps_ap( + pCtx, (tDot11fIEQOSCapsAp *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQOSCapsAp) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQOSCapsStation: + status |= + dot11f_pack_ie_qos_caps_station( + pCtx, (tDot11fIEQOSCapsStation *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQOSCapsStation) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQosMapSet: + status |= + dot11f_pack_ie_qos_map_set( + pCtx, (tDot11fIEQosMapSet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQosMapSet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeQuiet: + status |= + dot11f_pack_ie_quiet( + pCtx, (tDot11fIEQuiet *) + (pSrc + pIe->offset + + sizeof(tDot11fIEQuiet) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRCPIIE: + status |= + dot11f_pack_ie_rcpiie( + pCtx, (tDot11fIERCPIIE *) + (pSrc + pIe->offset + + sizeof(tDot11fIERCPIIE) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRICDataDesc: + status |= + dot11f_pack_ie_ric_data_desc( + pCtx, (tDot11fIERICDataDesc *) + (pSrc + pIe->offset + + sizeof(tDot11fIERICDataDesc) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSN: + status |= + dot11f_pack_ie_rsn( + pCtx, (tDot11fIERSN *) + (pSrc + pIe->offset + + sizeof(tDot11fIERSN) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSNIIE: + status |= + dot11f_pack_ie_rsniie( + pCtx, (tDot11fIERSNIIE *) + (pSrc + pIe->offset + + sizeof(tDot11fIERSNIIE) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeRSNOpaque: + status |= + dot11f_pack_ie_rsn_opaque( + pCtx, (tDot11fIERSNOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIERSNOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppChannels: + status |= + dot11f_pack_ie_supp_channels( + pCtx, (tDot11fIESuppChannels *) + (pSrc + pIe->offset + + sizeof(tDot11fIESuppChannels) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppOperatingClasses: + status |= + dot11f_pack_ie_supp_operating_classes( + pCtx, (tDot11fIESuppOperatingClasses *) + (pSrc + pIe->offset + + sizeof(tDot11fIESuppOperatingClasses) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeSuppRates: + status |= + dot11f_pack_ie_supp_rates( + pCtx, (tDot11fIESuppRates *) + (pSrc + pIe->offset + + sizeof(tDot11fIESuppRates) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTIM: + status |= + dot11f_pack_ie_tim( + pCtx, (tDot11fIETIM *) + (pSrc + pIe->offset + + sizeof(tDot11fIETIM) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTPCReport: + status |= + dot11f_pack_ie_tpc_report( + pCtx, (tDot11fIETPCReport *) + (pSrc + pIe->offset + + sizeof(tDot11fIETPCReport) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTPCRequest: + status |= + dot11f_pack_ie_tpc_request( + pCtx, (tDot11fIETPCRequest *) + (pSrc + pIe->offset + + sizeof(tDot11fIETPCRequest) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTimeAdvertisement: + status |= + dot11f_pack_ie_time_advertisement( + pCtx, (tDot11fIETimeAdvertisement *) + (pSrc + pIe->offset + + sizeof(tDot11fIETimeAdvertisement) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeTimeoutInterval: + status |= + dot11f_pack_ie_timeout_interval( + pCtx, (tDot11fIETimeoutInterval *) + (pSrc + pIe->offset + + sizeof(tDot11fIETimeoutInterval) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeVHTExtBssLoad: + status |= + dot11f_pack_ie_vht_ext_bss_load( + pCtx, (tDot11fIEVHTExtBssLoad *) + (pSrc + pIe->offset + + sizeof(tDot11fIEVHTExtBssLoad) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeVendor1IE: + status |= + dot11f_pack_ie_vendor1_ie( + pCtx, (tDot11fIEVendor1IE *) + (pSrc + pIe->offset + + sizeof(tDot11fIEVendor1IE) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeVendor3IE: + status |= + dot11f_pack_ie_vendor3_ie( + pCtx, (tDot11fIEVendor3IE *) + (pSrc + pIe->offset + + sizeof(tDot11fIEVendor3IE) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWAPI: + status |= + dot11f_pack_ie_wapi( + pCtx, (tDot11fIEWAPI *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWAPI) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWAPIOpaque: + status |= + dot11f_pack_ie_wapi_opaque( + pCtx, (tDot11fIEWAPIOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWAPIOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWFATPC: + status |= + dot11f_pack_ie_wfatpc( + pCtx, (tDot11fIEWFATPC *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWFATPC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWFDIEOpaque: + status |= + dot11f_pack_ie_wfdie_opaque( + pCtx, (tDot11fIEWFDIEOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWFDIEOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMCaps: + status |= + dot11f_pack_ie_wmm_caps( + pCtx, (tDot11fIEWMMCaps *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMCaps) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMInfoAp: + status |= + dot11f_pack_ie_wmm_info_ap( + pCtx, (tDot11fIEWMMInfoAp *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMInfoAp) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMInfoStation: + status |= + dot11f_pack_ie_wmm_info_station( + pCtx, (tDot11fIEWMMInfoStation *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMInfoStation) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWMMParams: + status |= + dot11f_pack_ie_wmm_params( + pCtx, (tDot11fIEWMMParams *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWMMParams) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWPA: + status |= + dot11f_pack_ie_wpa( + pCtx, (tDot11fIEWPA *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWPA) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWPAOpaque: + status |= + dot11f_pack_ie_wpa_opaque( + pCtx, (tDot11fIEWPAOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWPAOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWSC: + status |= + dot11f_pack_ie_wsc( + pCtx, (tDot11fIEWSC *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWSC) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscAssocReq: + status |= + dot11f_pack_ie_wsc_assoc_req( + pCtx, (tDot11fIEWscAssocReq *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscAssocReq) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscAssocRes: + status |= + dot11f_pack_ie_wsc_assoc_res( + pCtx, (tDot11fIEWscAssocRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscAssocRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscBeacon: + status |= + dot11f_pack_ie_wsc_beacon( + pCtx, (tDot11fIEWscBeacon *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscBeacon) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscBeaconProbeRes: + status |= + dot11f_pack_ie_wsc_beacon_probe_res( + pCtx, (tDot11fIEWscBeaconProbeRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscBeaconProbeRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscIEOpaque: + status |= + dot11f_pack_ie_wsc_ie_opaque( + pCtx, (tDot11fIEWscIEOpaque *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscIEOpaque) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscProbeReq: + status |= + dot11f_pack_ie_wsc_probe_req( + pCtx, (tDot11fIEWscProbeReq *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscProbeReq) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscProbeRes: + status |= + dot11f_pack_ie_wsc_probe_res( + pCtx, (tDot11fIEWscProbeRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscProbeRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeWscReassocRes: + status |= + dot11f_pack_ie_wsc_reassoc_res( + pCtx, (tDot11fIEWscReassocRes *) + (pSrc + pIe->offset + + sizeof(tDot11fIEWscReassocRes) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeext_chan_switch_ann: + status |= + dot11f_pack_ie_ext_chan_switch_ann( + pCtx, (tDot11fIEext_chan_switch_ann *) + (pSrc + pIe->offset + + sizeof(tDot11fIEext_chan_switch_ann) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeht2040_bss_coexistence: + status |= + dot11f_pack_ie_ht2040_bss_coexistence( + pCtx, (tDot11fIEht2040_bss_coexistence *) + (pSrc + pIe->offset + + sizeof(tDot11fIEht2040_bss_coexistence) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIeht2040_bss_intolerant_report: + status |= + dot11f_pack_ie_ht2040_bss_intolerant_report( + pCtx, (tDot11fIEht2040_bss_intolerant_report *) + (pSrc + pIe->offset + + sizeof(tDot11fIEht2040_bss_intolerant_report) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIesec_chan_offset_ele: + status |= + dot11f_pack_ie_sec_chan_offset_ele( + pCtx, (tDot11fIEsec_chan_offset_ele *) + (pSrc + pIe->offset + + sizeof(tDot11fIEsec_chan_offset_ele) * i), + pBufRemaining, nBufRemaining, &len); + break; + case SigIevendor2_ie: + status |= + dot11f_pack_ie_vendor2_ie( + pCtx, (tDot11fIEvendor2_ie *) + (pSrc + pIe->offset + + sizeof(tDot11fIEvendor2_ie) * i), + pBufRemaining, nBufRemaining, &len); + break; + default: + FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" + "'t know about the IE %d; this is most likely a b" + "ug in 'framesc'.\n"), pFf->sig); + return DOT11F_INTERNAL_ERROR; + } + + pBufRemaining += len; + nBufRemaining -= len; + *pnConsumed += len; + } + + ++pIe; + + } + + return status; + +} + +static uint32_t pack_tlv_core(tpAniSirGlobal pCtx, + uint8_t *pSrc, + uint8_t *pBuf, + uint32_t nBuf, + uint32_t *pnConsumed, + const tTLVDefn TLVs[], + uint32_t *pidx) +{ + const tTLVDefn *pTlv; + tFRAMES_BOOL *pfFound; + uint8_t *pBufRemaining; + uint32_t 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 |= + dot11f_pack_tlv_authorized_ma_cs( + pCtx, (tDot11fTLVAuthorizedMACs *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvRequestToEnroll: + status |= + dot11f_pack_tlv_request_to_enroll( + pCtx, (tDot11fTLVRequestToEnroll *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvVersion2: + status |= + dot11f_pack_tlv_version2( + pCtx, (tDot11fTLVVersion2 *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvAPSetupLocked: + status |= + dot11f_pack_tlv_ap_setup_locked( + pCtx, (tDot11fTLVAPSetupLocked *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvAssociationState: + status |= + dot11f_pack_tlv_association_state( + pCtx, (tDot11fTLVAssociationState *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvConfigMethods: + status |= + dot11f_pack_tlv_config_methods( + pCtx, (tDot11fTLVConfigMethods *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvConfigurationError: + status |= + dot11f_pack_tlv_configuration_error( + pCtx, (tDot11fTLVConfigurationError *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvDeviceName: + status |= + dot11f_pack_tlv_device_name( + pCtx, (tDot11fTLVDeviceName *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvDevicePasswordID: + status |= + dot11f_pack_tlv_device_password_id( + pCtx, (tDot11fTLVDevicePasswordID *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvExtendedListenTiming: + status |= + dot11f_pack_tlv_extended_listen_timing( + pCtx, (tDot11fTLVExtendedListenTiming *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvListenChannel: + status |= + dot11f_pack_tlv_listen_channel( + pCtx, (tDot11fTLVListenChannel *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvManufacturer: + status |= + dot11f_pack_tlv_manufacturer( + pCtx, (tDot11fTLVManufacturer *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvMinorReasonCode: + status |= + dot11f_pack_tlv_minor_reason_code( + pCtx, (tDot11fTLVMinorReasonCode *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvModelName: + status |= + dot11f_pack_tlv_model_name( + pCtx, (tDot11fTLVModelName *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvModelNumber: + status |= + dot11f_pack_tlv_model_number( + pCtx, (tDot11fTLVModelNumber *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvNoticeOfAbsence: + status |= + dot11f_pack_tlv_notice_of_absence( + pCtx, (tDot11fTLVNoticeOfAbsence *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvOperatingChannel: + status |= + dot11f_pack_tlv_operating_channel( + pCtx, (tDot11fTLVOperatingChannel *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PCapability: + status |= + dot11f_pack_tlv_p2_p_capability( + pCtx, (tDot11fTLVP2PCapability *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PDeviceId: + status |= + dot11f_pack_tlv_p2_p_device_id( + pCtx, (tDot11fTLVP2PDeviceId *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PDeviceInfo: + status |= + dot11f_pack_tlv_p2_p_device_info( + pCtx, (tDot11fTLVP2PDeviceInfo *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PGroupInfo: + status |= + dot11f_pack_tlv_p2_p_group_info( + pCtx, (tDot11fTLVP2PGroupInfo *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PStatus: + status |= + dot11f_pack_tlv_p2_p_status( + pCtx, (tDot11fTLVP2PStatus *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvPrimaryDeviceType: + status |= + dot11f_pack_tlv_primary_device_type( + pCtx, (tDot11fTLVPrimaryDeviceType *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvRFBands: + status |= + dot11f_pack_tlv_rf_bands( + pCtx, (tDot11fTLVRFBands *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvRequestDeviceType: + status |= + dot11f_pack_tlv_request_device_type( + pCtx, (tDot11fTLVRequestDeviceType *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvRequestType: + status |= + dot11f_pack_tlv_request_type( + pCtx, (tDot11fTLVRequestType *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvResponseType: + status |= + dot11f_pack_tlv_response_type( + pCtx, (tDot11fTLVResponseType *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvSelectedRegistrar: + status |= + dot11f_pack_tlv_selected_registrar( + pCtx, (tDot11fTLVSelectedRegistrar *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvSelectedRegistrarConfigMethods: + status |= + dot11f_pack_tlv_selected_registrar_config_methods( + pCtx, (tDot11fTLVSelectedRegistrarConfigMethods *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvSerialNumber: + status |= + dot11f_pack_tlv_serial_number( + pCtx, (tDot11fTLVSerialNumber *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvUUID_E: + status |= + dot11f_pack_tlv_uuid_e( + pCtx, (tDot11fTLVUUID_E *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvUUID_R: + status |= + dot11f_pack_tlv_uuid_r( + pCtx, (tDot11fTLVUUID_R *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvVendorExtension: + status |= + dot11f_pack_tlv_vendor_extension( + pCtx, (tDot11fTLVVendorExtension *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvVersion: + status |= + dot11f_pack_tlv_version( + pCtx, (tDot11fTLVVersion *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvWPSState: + status |= + dot11f_pack_tlv_wps_state( + pCtx, (tDot11fTLVWPSState *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PInterface: + status |= + dot11f_pack_tlv_p2_p_interface( + pCtx, (tDot11fTLVP2PInterface *) + (pSrc + pTlv->offset), pBufRemaining, + nBufRemaining, &len); + break; + case SigTlvP2PManageability: + status |= + dot11f_pack_tlv_p2_p_manageability( + 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/core/mac/src/sys/legacy/src/utils/src/log_api.c b/core/mac/src/sys/legacy/src/utils/src/log_api.c new file mode 100644 index 000000000000..8ec7b8c9e8be --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/log_api.c @@ -0,0 +1,200 @@ +/* + * 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. + */ + +/* + * log_api.cc - Handles log messages for all the modules. + * Author: Kevin Nguyen + * Date: 02/27/02 + * History:- + * 02/11/02 Created. + * 03/12/02 Rearrange log_debug parameter list and add more params. + * -------------------------------------------------------------------- + * + */ + +#include +#include +#include +#include + +#include +#include "utils_global.h" +#include "mac_init_api.h" + +#include "cdf_trace.h" + +#ifdef ANI_OS_TYPE_ANDROID +#include +#endif + +/* --------------------------------------------------------------------- */ +/** + * log_init() + * + * FUNCTION: + * This function is called to prepare the logging utility. + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param tpAniSirGlobal Sirius software parameter strucutre pointer + * @return None + */ +tSirRetStatus log_init(tpAniSirGlobal pMac) +{ + uint32_t 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; + +} /*** log_init() ***/ + +void log_deinit(tpAniSirGlobal pMac) +{ + return; +} + +/** + * log_dbg() + * + ***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 log_dbg(tpAniSirGlobal pMac, uint8_t modId, uint32_t 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. */ + + log_debug(pMac, modId, debugLevel, pStr, marker); + + va_end(marker); /* Reset variable arguments. */ + } +#endif +} + +CDF_TRACE_LEVEL get_vos_debug_level(uint32_t debugLevel) +{ + switch (debugLevel) { + case LOGP: + return CDF_TRACE_LEVEL_FATAL; + case LOGE: + return CDF_TRACE_LEVEL_ERROR; + case LOGW: + return CDF_TRACE_LEVEL_WARN; + case LOG1: + return CDF_TRACE_LEVEL_INFO; + case LOG2: + return CDF_TRACE_LEVEL_INFO_HIGH; + case LOG3: + return CDF_TRACE_LEVEL_INFO_MED; + case LOG4: + return CDF_TRACE_LEVEL_INFO_LOW; + default: + return CDF_TRACE_LEVEL_INFO_LOW; + } +} + +static inline CDF_MODULE_ID get_vos_module_id(uint8_t modId) +{ + switch (modId) { + case SIR_HAL_MODULE_ID: + return CDF_MODULE_ID_WMA; + + 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 CDF_MODULE_ID_PE; + + case SIR_SYS_MODULE_ID: + return CDF_MODULE_ID_SYS; + + case SIR_SMS_MODULE_ID: + return CDF_MODULE_ID_SME; + + default: + return CDF_MODULE_ID_SYS; + } +} + +#define LOG_SIZE 256 +void log_debug(tpAniSirGlobal pMac, uint8_t modId, uint32_t debugLevel, + const char *pStr, va_list marker) +{ + CDF_TRACE_LEVEL cdf_debug_level; + CDF_MODULE_ID cdf_module_id; + char logBuffer[LOG_SIZE]; + + cdf_debug_level = get_vos_debug_level(debugLevel); + cdf_module_id = get_vos_module_id(modId); + + vsnprintf(logBuffer, LOG_SIZE - 1, pStr, marker); + CDF_TRACE(cdf_module_id, cdf_debug_level, "%s", logBuffer); + + /* The caller must check loglevel */ + CDF_ASSERT((debugLevel <= + pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(modId)]) + && (LOGP != debugLevel)); +} /*** end log_debug() ***/ diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c new file mode 100644 index 000000000000..7d0d9ac102f3 --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -0,0 +1,759 @@ +/* + * 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 mac_trace.c + + \brief implementation for trace related APIs + + \author Sunit Bhatia + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "mac_trace.h" +#include "wma_types.h" +#include "csr_neighbor_roam.h" +#include "csr_internal.h" +#include "lim_global.h" +#include "cdf_memory.h" +#include "cdf_trace.h" +#include "wma_if.h" + +#ifdef TRACE_RECORD +/** + * mac_trace_get_neighbour_roam_state() - Get the neighbor roam state + * @neighbourroamstate: State in numeric form + * + * This function will return a string equivalent of the state. + * + * Return: String equivalent of the state. + **/ +uint8_t *mac_trace_get_neighbour_roam_state(uint16_t 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_REASSOCIATING); +#ifdef WLAN_FEATURE_VOWIFI_11R + 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 (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_getcsr_roam_state() - Get the csr roam state + * @csr_roam_state: State in numeric form + * + * This function will return a string equivalent of the state. + * + * Return: String equivalent of the state. + **/ +uint8_t *mac_trace_getcsr_roam_state(uint16_t csr_roam_state) +{ + switch (csr_roam_state) { + CASE_RETURN_STRING(eCSR_ROAMING_STATE_STOP); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_IDLE); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_JOINING); + CASE_RETURN_STRING(eCSR_ROAMING_STATE_JOINED); + + default: + return (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_getcsr_roam_sub_state() - Get the csr roam sub state + * @csr_roam_sub_state: State in numeric form + * + * This function will return a string equivalent of the state. + * + * Return: String equivalent of the state. + **/ +uint8_t *mac_trace_getcsr_roam_sub_state(uint16_t csr_roam_sub_state) +{ + switch (csr_roam_sub_state) { + 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 (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_lim_sme_state() - Get the lim sme state + * @lim_state: State in numeric form + * + * This function will return a string equivalent of the state. + * + * Return: String equivalent of the state. + **/ +uint8_t *mac_trace_get_lim_sme_state(uint16_t lim_state) +{ + switch (lim_state) { + 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 (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_lim_mlm_state() - Get the lim mlm state + * @mlmstate: State in numeric form + * + * This function will return a string equivalent of the state. + * + * Return: String equivalent of the state. + **/ +uint8_t *mac_trace_get_lim_mlm_state(uint16_t mlm_state) +{ + switch (mlm_state) { + 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 (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_sme_msg_string() - Get the msg + * @sme_msg: message type in numeric form + * + * This function will return a string equivalent of the message. + * + * Return: String equivalent of the message type. + **/ +uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) +{ + switch (sme_msg) { + 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_ASSOC_IND); + CASE_RETURN_STRING(eWNI_SME_ASSOC_CNF); + CASE_RETURN_STRING(eWNI_SME_SWITCH_CHL_IND); + CASE_RETURN_STRING(eWNI_SME_STOP_BSS_REQ); + CASE_RETURN_STRING(eWNI_SME_STOP_BSS_RSP); + CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_BSS_IND); + 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_DELTS_REQ); + CASE_RETURN_STRING(eWNI_SME_DELTS_RSP); + CASE_RETURN_STRING(eWNI_SME_DELTS_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_RSP); + CASE_RETURN_STRING(eWNI_SME_MGMT_FRM_IND); + CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RDY_IND); + CASE_RETURN_STRING(eWNI_SME_SEND_ACTION_FRAME_IND); + CASE_RETURN_STRING(eWNI_SME_ACTION_FRAME_SEND_CNF); + CASE_RETURN_STRING(eWNI_SME_ABORT_REMAIN_ON_CHAN_IND); + CASE_RETURN_STRING(eWNI_SME_UPDATE_NOA); + CASE_RETURN_STRING(eWNI_SME_CLEAR_DFS_CHANNEL_LIST); + CASE_RETURN_STRING(eWNI_SME_GET_SNR_REQ); + CASE_RETURN_STRING(eWNI_SME_LINK_STATUS_IND); + + CASE_RETURN_STRING(eWNI_PMC_MSG_TYPES_BEGIN); + + CASE_RETURN_STRING(eWNI_PMC_SMPS_STATE_IND); +#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_RSP); + 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); +#ifdef FEATURE_WLAN_SCAN_PNO + CASE_RETURN_STRING(eWNI_SME_PREF_NETWORK_FOUND_IND); +#endif /* FEATURE_WLAN_SCAN_PNO */ + CASE_RETURN_STRING(eWNI_SME_CHANGE_COUNTRY_CODE); + CASE_RETURN_STRING(eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE); + CASE_RETURN_STRING(eWNI_SME_MAX_ASSOC_EXCEEDED); +#ifdef WLAN_FEATURE_GTK_OFFLOAD + CASE_RETURN_STRING(eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP); +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + 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_SET_HW_MODE_REQ); + CASE_RETURN_STRING(eWNI_SME_SET_HW_MODE_RESP); + CASE_RETURN_STRING(eWNI_SME_HW_MODE_TRANS_IND); + default: + return (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_wma_msg_string() - Get the msg + * @wma_msg: message type in numeric form + * + * This function will return a string equivalent of the message. + * + * Return: String equivalent of the message type. + **/ +uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) +{ + switch (wma_msg) { + CASE_RETURN_STRING(WMA_ADD_STA_REQ); + CASE_RETURN_STRING(WMA_ADD_STA_RSP); + CASE_RETURN_STRING(WMA_ADD_STA_SELF_RSP); + CASE_RETURN_STRING(WMA_DELETE_STA_REQ); + CASE_RETURN_STRING(WMA_DELETE_STA_RSP); + CASE_RETURN_STRING(WMA_ADD_BSS_REQ); + CASE_RETURN_STRING(WMA_ADD_BSS_RSP); + CASE_RETURN_STRING(WMA_DELETE_BSS_REQ); + CASE_RETURN_STRING(WMA_DELETE_BSS_RSP); + CASE_RETURN_STRING(WMA_SEND_BEACON_REQ); + CASE_RETURN_STRING(WMA_SET_BSSKEY_REQ); + CASE_RETURN_STRING(WMA_SET_BSSKEY_RSP); + CASE_RETURN_STRING(WMA_SET_STAKEY_REQ); + CASE_RETURN_STRING(WMA_SET_STAKEY_RSP); + CASE_RETURN_STRING(WMA_UPDATE_EDCA_PROFILE_IND); + + CASE_RETURN_STRING(WMA_UPDATE_BEACON_IND); + CASE_RETURN_STRING(WMA_UPDATE_CF_IND); + CASE_RETURN_STRING(WMA_CHNL_SWITCH_REQ); + CASE_RETURN_STRING(WMA_ADD_TS_REQ); + CASE_RETURN_STRING(WMA_DEL_TS_REQ); + CASE_RETURN_STRING(WMA_EXIT_PS_REQ); + CASE_RETURN_STRING(WMA_ENTER_PS_REQ); + CASE_RETURN_STRING(WMA_MISSED_BEACON_IND); + + CASE_RETURN_STRING(WMA_CFG_RXP_FILTER_REQ); + CASE_RETURN_STRING(WMA_SWITCH_CHANNEL_RSP); + CASE_RETURN_STRING(WMA_P2P_NOA_ATTR_IND); + CASE_RETURN_STRING(WMA_P2P_NOA_START_IND); + CASE_RETURN_STRING(WMA_PWR_SAVE_CFG); + CASE_RETURN_STRING(WMA_REGISTER_PE_CALLBACK); + + CASE_RETURN_STRING(WMA_IBSS_STA_ADD); + CASE_RETURN_STRING(WMA_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND); + CASE_RETURN_STRING(WMA_SET_LINK_STATE); + CASE_RETURN_STRING(WMA_SET_LINK_STATE_RSP); + CASE_RETURN_STRING(WMA_SET_STA_BCASTKEY_REQ); + CASE_RETURN_STRING(WMA_SET_STA_BCASTKEY_RSP); + CASE_RETURN_STRING(WMA_ADD_TS_RSP); + CASE_RETURN_STRING(WMA_DPU_MIC_ERROR); + + CASE_RETURN_STRING(WMA_TIMER_CHIP_MONITOR_TIMEOUT); + CASE_RETURN_STRING(WMA_TIMER_TRAFFIC_ACTIVITY_REQ); + CASE_RETURN_STRING(WMA_TIMER_ADC_RSSI_STATS); +#ifdef FEATURE_WLAN_ESE + CASE_RETURN_STRING(WMA_TSM_STATS_REQ); + CASE_RETURN_STRING(WMA_TSM_STATS_RSP); +#endif + CASE_RETURN_STRING(WMA_SET_MIMOPS_REQ); + CASE_RETURN_STRING(WMA_SET_MIMOPS_RSP); + CASE_RETURN_STRING(WMA_SYS_READY_IND); + CASE_RETURN_STRING(WMA_SET_TX_POWER_REQ); + CASE_RETURN_STRING(WMA_SET_TX_POWER_RSP); + CASE_RETURN_STRING(WMA_GET_TX_POWER_REQ); + + CASE_RETURN_STRING(WMA_TRANSMISSION_CONTROL_IND); + CASE_RETURN_STRING(WMA_ENABLE_UAPSD_REQ); + CASE_RETURN_STRING(WMA_DISABLE_UAPSD_REQ); + CASE_RETURN_STRING(WMA_BEACON_FILTER_IND); + CASE_RETURN_STRING(WMA_WOW_ADD_PTRN); + CASE_RETURN_STRING(WMA_WOW_DEL_PTRN); + CASE_RETURN_STRING(WMA_WOWL_ENTER_REQ); + CASE_RETURN_STRING(WMA_WOWL_EXIT_REQ); + CASE_RETURN_STRING(WMA_GET_STATISTICS_REQ); + CASE_RETURN_STRING(WMA_GET_STATISTICS_RSP); + CASE_RETURN_STRING(WMA_SET_KEY_DONE); + + CASE_RETURN_STRING(WMA_BTC_SET_CFG); + CASE_RETURN_STRING(WMA_HANDLE_FW_MBOX_RSP); + CASE_RETURN_STRING(WMA_SEND_PROBE_RSP_TMPL); +#ifdef FEATURE_OEM_DATA_SUPPORT + CASE_RETURN_STRING(WMA_START_OEM_DATA_REQ); + CASE_RETURN_STRING(WMA_START_OEM_DATA_RSP); +#endif /* SUPPORT_BEACON_FILTER */ + CASE_RETURN_STRING(WMA_SET_MAX_TX_POWER_REQ); + CASE_RETURN_STRING(WMA_SET_HOST_OFFLOAD); + CASE_RETURN_STRING(WMA_SET_KEEP_ALIVE); +#ifdef WLAN_NS_OFFLOAD + CASE_RETURN_STRING(WMA_SET_NS_OFFLOAD); +#endif /* WLAN_NS_OFFLOAD */ + CASE_RETURN_STRING(WMA_ADD_STA_SELF_REQ); + CASE_RETURN_STRING(WMA_DEL_STA_SELF_REQ); + CASE_RETURN_STRING(WMA_SET_P2P_GO_NOA_REQ); + CASE_RETURN_STRING(WMA_WLAN_SUSPEND_IND); + CASE_RETURN_STRING(WMA_WLAN_RESUME_REQ); +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + CASE_RETURN_STRING(WMA_WLAN_EXT_WOW); + CASE_RETURN_STRING(WMA_WLAN_SET_APP_TYPE1_PARAMS); + CASE_RETURN_STRING(WMA_WLAN_SET_APP_TYPE2_PARAMS); +#endif + CASE_RETURN_STRING(WMA_MSG_TYPES_END); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STRING(WMA_AGGR_QOS_REQ); + CASE_RETURN_STRING(WMA_AGGR_QOS_RSP); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + CASE_RETURN_STRING(WMA_FTM_CMD_REQ); + CASE_RETURN_STRING(WMA_FTM_CMD_RSP); +#ifdef FEATURE_WLAN_SCAN_PNO + CASE_RETURN_STRING(WMA_SET_PNO_REQ); + CASE_RETURN_STRING(WMA_SME_SCAN_CACHE_UPDATED); +#endif /* FEATURE_WLAN_SCAN_PNO */ + CASE_RETURN_STRING(WMA_ROAM_SCAN_OFFLOAD_REQ); +#ifdef WLAN_FEATURE_PACKET_FILTERING + CASE_RETURN_STRING(WMA_8023_MULTICAST_LIST_REQ); + CASE_RETURN_STRING(WMA_RECEIVE_FILTER_SET_FILTER_REQ); + CASE_RETURN_STRING + (WMA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ); + CASE_RETURN_STRING + (WMA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP); + CASE_RETURN_STRING(WMA_RECEIVE_FILTER_CLEAR_FILTER_REQ); +#endif /* WLAN_FEATURE_PACKET_FILTERING */ +#ifdef WLAN_FEATURE_GTK_OFFLOAD + CASE_RETURN_STRING(WMA_GTK_OFFLOAD_REQ); + CASE_RETURN_STRING(WMA_GTK_OFFLOAD_GETINFO_REQ); + CASE_RETURN_STRING(WMA_GTK_OFFLOAD_GETINFO_RSP); +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + CASE_RETURN_STRING(WMA_SET_TM_LEVEL_REQ); +#ifdef WLAN_FEATURE_11AC + CASE_RETURN_STRING(WMA_UPDATE_OP_MODE); + CASE_RETURN_STRING(WMA_UPDATE_MEMBERSHIP); + CASE_RETURN_STRING(WMA_UPDATE_USERPOS); +#endif + CASE_RETURN_STRING(WMA_START_SCAN_OFFLOAD_REQ); + CASE_RETURN_STRING(WMA_STOP_SCAN_OFFLOAD_REQ); + CASE_RETURN_STRING(WMA_UPDATE_CHAN_LIST_REQ); + CASE_RETURN_STRING(WMA_CLI_SET_CMD); +#ifndef REMOVE_PKT_LOG + CASE_RETURN_STRING(WMA_PKTLOG_ENABLE_REQ); +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + CASE_RETURN_STRING(WMA_SET_PLM_REQ); +#endif + CASE_RETURN_STRING(WMA_CONFIG_PARAM_UPDATE_REQ); + CASE_RETURN_STRING(WMA_RATE_UPDATE_IND); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(WMA_UPDATE_FW_TDLS_STATE); + CASE_RETURN_STRING(WMA_UPDATE_TDLS_PEER_STATE); +#endif + CASE_RETURN_STRING(WMA_ADD_PERIODIC_TX_PTRN_IND); + CASE_RETURN_STRING(WMA_TX_POWER_LIMIT); +#ifdef FEATURE_WLAN_LPHB + CASE_RETURN_STRING(WMA_LPHB_CONF_REQ); +#endif + CASE_RETURN_STRING(WMA_DHCP_START_IND); + CASE_RETURN_STRING(WMA_DHCP_STOP_IND); +#ifdef FEATURE_WLAN_CH_AVOID + CASE_RETURN_STRING(WMA_CH_AVOID_UPDATE_REQ); +#endif +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + CASE_RETURN_STRING(WMA_SET_AUTO_SHUTDOWN_TIMER_REQ); +#endif + CASE_RETURN_STRING(WMA_INIT_THERMAL_INFO_CMD); + CASE_RETURN_STRING(WMA_SET_THERMAL_LEVEL); + CASE_RETURN_STRING(WMA_SET_SAP_INTRABSS_DIS); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(WMA_ROAM_OFFLOAD_SYNCH_CNF); + CASE_RETURN_STRING(WMA_ROAM_OFFLOAD_SYNCH_FAIL); +#endif + CASE_RETURN_STRING(SIR_HAL_SET_BASE_MACADDR_IND); + CASE_RETURN_STRING(WMA_LINK_STATUS_GET_REQ); +#ifdef DHCP_SERVER_OFFLOAD + CASE_RETURN_STRING(WMA_SET_DHCP_SERVER_OFFLOAD_CMD); +#endif + CASE_RETURN_STRING(WMA_OCB_SET_CONFIG_CMD); + CASE_RETURN_STRING(WMA_OCB_SET_UTC_TIME_CMD); + CASE_RETURN_STRING(WMA_OCB_START_TIMING_ADVERT_CMD); + CASE_RETURN_STRING(WMA_OCB_STOP_TIMING_ADVERT_CMD); + CASE_RETURN_STRING(WMA_OCB_GET_TSF_TIMER_CMD); + CASE_RETURN_STRING(WMA_DCC_GET_STATS_CMD); + CASE_RETURN_STRING(WMA_DCC_CLEAR_STATS_CMD); + CASE_RETURN_STRING(WMA_DCC_UPDATE_NDL_CMD); + CASE_RETURN_STRING(WMA_SET_IE_INFO); + CASE_RETURN_STRING(WNI_CFG_DNLD_REQ); + CASE_RETURN_STRING(SIR_HAL_UNIT_TEST_CMD); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(SIR_HAL_ROAM_INVOKE); +#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(SIR_HAL_START_STOP_LOGGING); + CASE_RETURN_STRING(SIR_HAL_FLUSH_LOG_TO_FW); + CASE_RETURN_STRING(SIR_HAL_SOC_SET_PCL_TO_FW); + CASE_RETURN_STRING(SIR_HAL_SOC_SET_HW_MODE); + CASE_RETURN_STRING(SIR_HAL_SOC_DUAL_MAC_CFG_REQ); + CASE_RETURN_STRING(WMA_RADAR_DETECTED_IND); + CASE_RETURN_STRING(WMA_TIMER_TRAFFIC_STATS_IND); +#ifdef WLAN_FEATURE_11W + CASE_RETURN_STRING(WMA_EXCLUDE_UNENCRYPTED_IND); +#endif + CASE_RETURN_STRING(WMA_WOWL_ENTER_RSP); + CASE_RETURN_STRING(WMA_WOWL_EXIT_RSP); + CASE_RETURN_STRING(WMA_SET_MAX_TX_POWER_RSP); + CASE_RETURN_STRING(WMA_SET_MAX_TX_POWER_PER_BAND_REQ); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(WMA_SET_TDLS_LINK_ESTABLISH_REQ); + CASE_RETURN_STRING(WMA_SET_TDLS_LINK_ESTABLISH_REQ_RSP); +#endif + CASE_RETURN_STRING(WMA_CSA_OFFLOAD_EVENT); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + CASE_RETURN_STRING(WMA_ROAM_OFFLOAD_SYNCH_IND); +#endif + CASE_RETURN_STRING(WMA_HIDDEN_SSID_VDEV_RESTART); +#ifdef WLAN_FEATURE_11AC + CASE_RETURN_STRING(WMA_UPDATE_RX_NSS); +#endif +#ifdef WLAN_FEATURE_NAN + CASE_RETURN_STRING(WMA_NAN_REQUEST); +#endif + CASE_RETURN_STRING(WMA_RX_SCAN_EVENT); + CASE_RETURN_STRING(WMA_IBSS_PEER_INACTIVITY_IND); + CASE_RETURN_STRING(WMA_DEL_PERIODIC_TX_PTRN_IND); +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STRING(WMA_TDLS_SHOULD_DISCOVER_CMD); + CASE_RETURN_STRING(WMA_TDLS_SHOULD_TEARDOWN_CMD); + CASE_RETURN_STRING(WMA_TDLS_PEER_DISCONNECTED_CMD); + CASE_RETURN_STRING(WMA_TDLS_SET_OFFCHAN_MODE); +#endif + CASE_RETURN_STRING(WMA_DFS_RADAR_IND); + CASE_RETURN_STRING(WMA_DFS_BEACON_TX_SUCCESS_IND); + CASE_RETURN_STRING(WMA_DISASSOC_TX_COMP); + CASE_RETURN_STRING(WMA_DEAUTH_TX_COMP); + CASE_RETURN_STRING(WMA_GET_LINK_SPEED); + CASE_RETURN_STRING(WMA_MODEM_POWER_STATE_IND); +#ifdef WLAN_FEATURE_STATS_EXT + CASE_RETURN_STRING(WMA_STATS_EXT_REQUEST); +#endif + CASE_RETURN_STRING(WMA_IPA_OFFLOAD_ENABLE_DISABLE); + CASE_RETURN_STRING(WMA_GET_TEMPERATURE_REQ); +#ifdef FEATURE_WLAN_EXTSCAN + CASE_RETURN_STRING(WMA_EXTSCAN_GET_CAPABILITIES_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_START_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_STOP_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_GET_CACHED_RESULTS_REQ); + CASE_RETURN_STRING(WMA_SET_EPNO_LIST_REQ); + CASE_RETURN_STRING(WMA_SET_PASSPOINT_LIST_REQ); + CASE_RETURN_STRING(WMA_RESET_PASSPOINT_LIST_REQ); + CASE_RETURN_STRING(WMA_EXTSCAN_SET_SSID_HOTLIST_REQ); +#endif /* FEATURE_WLAN_EXTSCAN */ +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + CASE_RETURN_STRING(WMA_LINK_LAYER_STATS_CLEAR_REQ); + CASE_RETURN_STRING(WMA_LINK_LAYER_STATS_SET_REQ); + CASE_RETURN_STRING(WMA_LINK_LAYER_STATS_GET_REQ); + CASE_RETURN_STRING(WMA_LINK_LAYER_STATS_RESULTS_RSP); +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + CASE_RETURN_STRING(WMA_SET_SCAN_MAC_OUI_REQ); +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + CASE_RETURN_STRING(WMA_LED_FLASHING_REQ); +#endif + CASE_RETURN_STRING(WMA_PROCESS_FW_EVENT); +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + CASE_RETURN_STRING(WMA_UPDATE_Q2Q_IE_IND); +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + CASE_RETURN_STRING(WMA_SET_RSSI_MONITOR_REQ); + CASE_RETURN_STRING(WMA_FW_MEM_DUMP_REQ); + default: + return (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_lim_msg_string() - Get the msg + * @lim_msg: message type in numeric form + * + * This function will return a string equivalent of the message. + * + * Return: String equivalent of the message type. + **/ +uint8_t *mac_trace_get_lim_msg_string(uint16_t lim_msg) +{ + switch (lim_msg) { + 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_DELETE_STA_CONTEXT_IND); + CASE_RETURN_STRING(SIR_LIM_UPDATE_BEACON); + 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_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_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_MSG_TYPES_END); + + default: + return (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_cfg_msg_string() - Get the msg + * @cfg_msg: message type in numeric form + * + * This function will return a string equivalent of the message. + * + * Return: String equivalent of the message type. + **/ +uint8_t *mac_trace_get_cfg_msg_string(uint16_t cfg_msg) +{ + switch (cfg_msg) { + 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 (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace_get_info_log_string() - Get the log info + * @info_log: message type in numeric form + * + * This function will return a string equivalent of the message. + * + * Return: String equivalent of the message type. + **/ +uint8_t *mac_trace_get_info_log_string(uint16_t info_log) +{ + switch (info_log) { + CASE_RETURN_STRING(eLOG_NODROP_MISSED_BEACON_SCENARIO); + CASE_RETURN_STRING(eLOG_PROC_DEAUTH_FRAME_SCENARIO); + default: + return (uint8_t *) "UNKNOWN"; + break; + } +} + +/** + * mac_trace() - Main function used for MAC Trace + * @mac_ctx: Global MAC context + * @code: code + * @session: session id + * @data: data to be traced. + * + * Return: None + **/ +void mac_trace(tpAniSirGlobal mac_ctx, uint8_t code, + uint16_t session, uint32_t data) +{ + /* + * Today mac_trace is being invoked by PE only, need to remove this + * function once PE is migrated to using new trace API. + */ + mac_trace_new(mac_ctx, CDF_MODULE_ID_PE, code, session, data); +} + +/** + * mac_trace_new() - New function used for MAC Trace + * @mac_ctx: Global MAC context + * @code: code + * @session: session id + * @data: data to be traced. + * + * Return: None + **/ +void mac_trace_new(tpAniSirGlobal mac_ctx, uint8_t module, uint8_t code, + uint16_t session, uint32_t data) +{ + cdf_trace(module, code, session, data); +} + +#endif diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c new file mode 100644 index 000000000000..7dea42c89d37 --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -0,0 +1,5654 @@ +/* + * 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 parser_api.cc contains the code for parsing + * 802.11 messages. + * Author: Pierre Vandwalle + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "sir_api.h" +#include "ani_global.h" +#include "parser_api.h" +#include "cfg_api.h" +#include "lim_utils.h" +#include "utils_parser.h" +#include "lim_ser_des_utils.h" +#include "sch_api.h" +#include "wmm_apsd.h" +#if defined WLAN_FEATURE_VOWIFI +#include "rrm_api.h" +#endif + +#include "cds_regdomain_common.h" + +/* ////////////////////////////////////////////////////////////////////// */ +void dot11f_log(tpAniSirGlobal pMac, int loglevel, const char *pString, ...) +{ +#ifdef WLAN_DEBUG + if ((uint32_t) loglevel > + pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(SIR_DBG_MODULE_ID)]) { + return; + } else { + va_list marker; + + va_start(marker, pString); /* Initialize variable arguments. */ + + log_debug(pMac, SIR_DBG_MODULE_ID, loglevel, pString, marker); + + va_end(marker); /* Reset variable arguments. */ + } +#endif +} + +void swap_bit_field16(uint16_t in, uint16_t *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 swap_bit_field32(uint32_t in, uint32_t *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 __print_wmm_params(tpAniSirGlobal pMac, + tDot11fIEWMMParams *pWmm) +{ + lim_log(pMac, LOG1, FL("WMM Parameters Received: \n")); + lim_log(pMac, LOG1, + FL + ("BE: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d \n"), + pWmm->acbe_aifsn, pWmm->acbe_acm, pWmm->acbe_aci, + pWmm->acbe_acwmin, pWmm->acbe_acwmax, pWmm->acbe_txoplimit); + + lim_log(pMac, LOG1, + FL + ("BK: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d \n"), + pWmm->acbk_aifsn, pWmm->acbk_acm, pWmm->acbk_aci, + pWmm->acbk_acwmin, pWmm->acbk_acwmax, pWmm->acbk_txoplimit); + + lim_log(pMac, LOG1, + FL + ("VI: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d \n"), + pWmm->acvi_aifsn, pWmm->acvi_acm, pWmm->acvi_aci, + pWmm->acvi_acwmin, pWmm->acvi_acwmax, pWmm->acvi_txoplimit); + + lim_log(pMac, LOG1, + FL + ("VO: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d \n"), + 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 find_ie_location(tpAniSirGlobal pMac, tpSirRSNie pRsnIe, uint8_t EID) +{ + int idx, ieLen, bytesLeft; + int ret_val = -1; + + /* Here's what's going on: 'rsnIe' looks like this: */ + + /* typedef struct sSirRSNie */ + /* { */ + /* uint16_t length; */ + /* uint8_t 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 <= (uint16_t) (ieLen)) { + dot11f_log(pMac, LOG3, + FL("No IE (%d) in find_ie_location.\n"), EID); + return ret_val; + } + bytesLeft -= ieLen; + ieLen = pRsnIe->rsnIEdata[idx + 1] + 2; + idx += ieLen; + } + + return ret_val; +} + +tSirRetStatus +populate_dot11f_capabilities(tpAniSirGlobal pMac, + tDot11fFfCapabilities *pDot11f, + tpPESession psessionEntry) +{ + uint16_t cfg; + tSirRetStatus nSirStatus; + + nSirStatus = cfg_get_capability_info(pMac, &cfg, psessionEntry); + if (eSIR_SUCCESS != nSirStatus) { + dot11f_log(pMac, LOGP, FL("Failed to retrieve the Capabilities b" + "itfield from CFG (%d).\n"), + nSirStatus); + return nSirStatus; + } + + swap_bit_field16(cfg, (uint16_t *) pDot11f); + + return eSIR_SUCCESS; +} /* End populate_dot11f_capabilities. */ + +/** + * 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 = cds_regdm_get_opclass_from_channel( + mac_ptr->scan.countryCodeCurrent, + session_entry->gLimChannelSwitch.primaryChannel, + session_entry->gLimChannelSwitch.ch_width); + dot_11_ptr->new_channel = + session_entry->gLimChannelSwitch.primaryChannel; + dot_11_ptr->switch_count = + session_entry->gLimChannelSwitch.switchCount; + dot_11_ptr->present = 1; +} + +void +populate_dot11f_chan_switch_ann(tpAniSirGlobal pMac, + tDot11fIEChanSwitchAnn *pDot11f, + tpPESession psessionEntry) +{ + pDot11f->switchMode = psessionEntry->gLimChannelSwitch.switchMode; + pDot11f->newChannel = psessionEntry->gLimChannelSwitch.primaryChannel; + pDot11f->switchCount = + (uint8_t) psessionEntry->gLimChannelSwitch.switchCount; + + pDot11f->present = 1; +} + +void +populate_dot11f_chan_switch_wrapper(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 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 */ + +#ifdef WLAN_FEATURE_11AC +void +populate_dot11f_wider_bw_chan_switch_ann(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 +populate_dot11f_country(tpAniSirGlobal pMac, + tDot11fIECountry *pDot11f, tpPESession psessionEntry) +{ + uint32_t len, maxlen, codelen; + uint16_t item; + tSirRetStatus nSirStatus; + tSirRFBand rfBand; + uint8_t temp[CFG_MAX_STR_LEN], code[3]; + + if (psessionEntry->lim11dEnabled) { + lim_get_rf_band_new(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); + + cdf_mem_copy(pDot11f->country, code, codelen); + + if (len > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) { + dot11f_log(pMac, LOGE, + FL("len:%d is out of bounds, resetting.\n"), + len); + len = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE; + } + + pDot11f->num_triplets = (uint8_t) (len / 3); + cdf_mem_copy((uint8_t *) pDot11f->triplets, temp, len); + + pDot11f->present = 1; + } + + return eSIR_SUCCESS; +} /* End populate_dot11f_country. */ + +#ifdef QCA_WIFI_3_0_EMU +/** + * populate_dot11f_ds_params() - To populate DS IE params + * mac_ctx: Pointer to global mac context + * dot11f_param: pointer to DS params IE + * channel: channel number + * + * This routine will populate DS param in management frame like + * beacon, probe response, and etc. + * + * Return: Overall sucess + */ +tSirRetStatus +populate_dot11f_ds_params(tpAniSirGlobal mac_ctx, + tDot11fIEDSParams *dot11f_param, uint8_t channel) +{ + /* .11a/11b/g mode PHY => Include the DS Parameter Set IE: */ + dot11f_param->curr_channel = channel; + dot11f_param->present = 1; + + return eSIR_SUCCESS; +} /* End populate_dot11f_ds_params. */ +#else +/** + * populate_dot11f_ds_params() - To populate DS IE params + * mac_ctx: Pointer to global mac context + * dot11f_param: pointer to DS params IE + * channel: channel number + * + * This routine will populate DS param in management frame like + * beacon, probe response, and etc. + * + * Return: Overall sucess + */ +tSirRetStatus +populate_dot11f_ds_params(tpAniSirGlobal mac_ctx, + tDot11fIEDSParams *dot11f_param, uint8_t channel) +{ + if (IS_24G_CH(channel)) { + /* .11b/g mode PHY => Include the DS Parameter Set IE: */ + dot11f_param->curr_channel = channel; + dot11f_param->present = 1; + } + + return eSIR_SUCCESS; +} +#endif + +#define SET_AIFSN(aifsn) (((aifsn) < 2) ? 2 : (aifsn)) + +void +populate_dot11f_edca_param_set(tpAniSirGlobal pMac, + tDot11fIEEDCAParamSet *pDot11f, + tpPESession psessionEntry) +{ + + if (psessionEntry->limQosEnabled) { + /* change to bitwise operation, after this is fixed in frames. */ + pDot11f->qos = + (uint8_t) (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 +populate_dot11f_erp_info(tpAniSirGlobal pMac, + tDot11fIEERPInfo *pDot11f, tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + uint32_t val; + tSirRFBand rfBand = SIR_BAND_UNKNOWN; + + lim_get_rf_band_new(pMac, &rfBand, psessionEntry); + if (SIR_BAND_2_4_GHZ == rfBand) { + pDot11f->present = 1; + + val = psessionEntry->cfgProtection.fromllb; + if (!val) { + dot11f_log(pMac, LOGE, + FL + ("11B protection not enabled. Not populating ERP IE %d\n"), + 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 populate_dot11f_erp_info. */ + +tSirRetStatus +populate_dot11f_ext_supp_rates(tpAniSirGlobal pMac, uint8_t nChannelNum, + tDot11fIEExtSuppRates *pDot11f, + tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + uint32_t nRates = 0; + uint8_t rates[WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN]; + + /* 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; + cdf_mem_copy(rates, psessionEntry->extRateSet.rate, + nRates); + } else { + dot11f_log(pMac, LOGE, + FL("no session context exists while" + " populating Operational Rate Set\n")); + } + } 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 = (uint8_t) nRates; + cdf_mem_copy(pDot11f->rates, rates, nRates); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_ext_supp_rates. */ + +tSirRetStatus +populate_dot11f_ext_supp_rates1(tpAniSirGlobal pMac, + uint8_t nChannelNum, + tDot11fIEExtSuppRates *pDot11f) +{ + uint32_t nRates; + tSirRetStatus nSirStatus; + uint8_t 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_cfg_get_str' 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 = (uint8_t) nRates; + cdf_mem_copy(pDot11f->rates, rates, nRates); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; +} /* populate_dot11f_ext_supp_rates1. */ + +tSirRetStatus +populate_dot11f_ht_caps(tpAniSirGlobal pMac, + tpPESession psessionEntry, tDot11fIEHTCaps *pDot11f) +{ + uint32_t nCfgValue, nCfgLen; + uint8_t nCfgValue8; + tSirRetStatus nSirStatus; + tSirMacHTParametersInfo *pHTParametersInfo; + union { + uint16_t 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; + } + + dot11f_log(pMac, LOG2, + FL + ("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d\n"), + pDot11f->supportedChannelWidthSet, pDot11f->mimoPowerSave, + pDot11f->greenField, pDot11f->shortGI20MHz, + pDot11f->shortGI40MHz, pDot11f->dsssCckMode40MHz); + + CFG_GET_INT(nSirStatus, pMac, WNI_CFG_HT_AMPDU_PARAMS, nCfgValue); + + nCfgValue8 = (uint8_t) nCfgValue; + pHTParametersInfo = (tSirMacHTParametersInfo *) &nCfgValue8; + + pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor; + pDot11f->mpduDensity = pHTParametersInfo->mpduDensity; + pDot11f->reserved1 = pHTParametersInfo->reserved; + + dot11f_log(pMac, LOG2, FL("AMPDU Param: %x\n"), nCfgValue); + + CFG_GET_STR(nSirStatus, pMac, WNI_CFG_SUPPORTED_MCS_SET, + pDot11f->supportedMCSSet, nCfgLen, + SIZE_OF_SUPPORTED_MCS_SET); + + if (psessionEntry) { + if (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; + } + } + } + if (psessionEntry->nss == 1) + pDot11f->supportedMCSSet[1] = 0; + } + + 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 = (uint8_t) 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 populate_dot11f_ht_caps. */ + +#ifdef WLAN_FEATURE_11AC + +void lim_log_vht_cap(tpAniSirGlobal pMac, tDot11fIEVHTCaps *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + lim_log(pMac, LOG1, FL("maxMPDULen (2): %d\n"), pDot11f->maxMPDULen); + lim_log(pMac, LOG1, FL("supportedChannelWidthSet (2): %d\n"), + pDot11f->supportedChannelWidthSet); + lim_log(pMac, LOG1, FL("ldpcCodingCap (1): %d\n"), + pDot11f->ldpcCodingCap); + lim_log(pMac, LOG1, FL("shortGI80MHz (1): %d\n"), pDot11f->shortGI80MHz); + lim_log(pMac, LOG1, FL("shortGI160and80plus80MHz (1): %d\n"), + pDot11f->shortGI160and80plus80MHz); + lim_log(pMac, LOG1, FL("txSTBC (1): %d\n"), pDot11f->txSTBC); + lim_log(pMac, LOG1, FL("rxSTBC (3): %d\n"), pDot11f->rxSTBC); + lim_log(pMac, LOG1, FL("suBeamFormerCap (1): %d\n"), + pDot11f->suBeamFormerCap); + lim_log(pMac, LOG1, FL("suBeamformeeCap (1): %d\n"), + pDot11f->suBeamformeeCap); + lim_log(pMac, LOG1, FL("csnofBeamformerAntSup (3): %d\n"), + pDot11f->csnofBeamformerAntSup); + lim_log(pMac, LOG1, FL("numSoundingDim (3): %d\n"), + pDot11f->numSoundingDim); + lim_log(pMac, LOG1, FL("muBeamformerCap (1): %d\n"), + pDot11f->muBeamformerCap); + lim_log(pMac, LOG1, FL("muBeamformeeCap (1): %d\n"), + pDot11f->muBeamformeeCap); + lim_log(pMac, LOG1, FL("vhtTXOPPS (1): %d\n"), pDot11f->vhtTXOPPS); + lim_log(pMac, LOG1, FL("htcVHTCap (1): %d\n"), pDot11f->htcVHTCap); + lim_log(pMac, LOG1, FL("maxAMPDULenExp (3): %d\n"), + pDot11f->maxAMPDULenExp); + lim_log(pMac, LOG1, FL("vhtLinkAdaptCap (2): %d\n"), + pDot11f->vhtLinkAdaptCap); + lim_log(pMac, LOG1, FL("rxAntPattern (1): %d\n"), + pDot11f->vhtLinkAdaptCap); + lim_log(pMac, LOG1, FL("txAntPattern (1): %d\n"), + pDot11f->vhtLinkAdaptCap); + lim_log(pMac, LOG1, FL("reserved1 (2): %d\n"), pDot11f->reserved1); + lim_log(pMac, LOG1, FL("rxMCSMap (16): %d\n"), pDot11f->rxMCSMap); + lim_log(pMac, LOG1, FL("rxHighSupDataRate (13): %d\n"), + pDot11f->rxHighSupDataRate); + lim_log(pMac, LOG1, FL("reserve (3): %d\n"), pDot11f->reserved2); + lim_log(pMac, LOG1, FL("txMCSMap (16): %d\n"), pDot11f->txMCSMap); + lim_log(pMac, LOG1, FL("txSupDataRate (13): %d\n"), + pDot11f->txSupDataRate); + lim_log(pMac, LOG1, FL("reserv (3): %d\n"), pDot11f->reserved3); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void lim_log_vht_operation(tpAniSirGlobal pMac, tDot11fIEVHTOperation *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + lim_log(pMac, LOG1, FL("chanWidth : %d\n"), pDot11f->chanWidth); + lim_log(pMac, LOG1, FL("chanCenterFreqSeg1: %d\n"), + pDot11f->chanCenterFreqSeg1); + lim_log(pMac, LOG1, FL("chanCenterFreqSeg2: %d\n"), + pDot11f->chanCenterFreqSeg2); + lim_log(pMac, LOG1, FL("basicMCSSet: %d\n"), pDot11f->basicMCSSet); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void lim_log_vht_ext_bss_load(tpAniSirGlobal pMac, tDot11fIEVHTExtBssLoad *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + lim_log(pMac, LOG1, FL("muMIMOCapStaCount : %d\n"), + pDot11f->muMIMOCapStaCount); + lim_log(pMac, LOG1, FL("ssUnderUtil: %d\n"), pDot11f->ssUnderUtil); + lim_log(pMac, LOG1, FL("FortyMHzUtil: %d\n"), pDot11f->FortyMHzUtil); + lim_log(pMac, LOG1, FL("EightyMHzUtil: %d\n"), pDot11f->EightyMHzUtil); + lim_log(pMac, LOG1, FL("OneSixtyMHzUtil: %d\n"), + pDot11f->OneSixtyMHzUtil); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void lim_log_operating_mode(tpAniSirGlobal pMac, tDot11fIEOperatingMode *pDot11f) +{ +#ifdef DUMP_MGMT_CNTNTS + lim_log(pMac, LOG1, FL("ChanWidth : %d\n"), pDot11f->chanWidth); + lim_log(pMac, LOG1, FL("reserved: %d\n"), pDot11f->reserved); + lim_log(pMac, LOG1, FL("rxNSS: %d\n"), pDot11f->rxNSS); + lim_log(pMac, LOG1, FL("rxNSS Type: %d\n"), pDot11f->rxNSSType); +#endif /* DUMP_MGMT_CNTNTS */ +} + +void lim_log_qos_map_set(tpAniSirGlobal pMac, tSirQosMapSet *pQosMapSet) +{ + uint8_t i; + lim_log(pMac, LOG1, FL("num of dscp exceptions : %d"), + pQosMapSet->num_dscp_exceptions); + for (i = 0; i < pQosMapSet->num_dscp_exceptions; i++) { + lim_log(pMac, LOG1, FL("dscp value: %d"), + pQosMapSet->dscp_exceptions[i][0]); + lim_log(pMac, LOG1, FL("User priority value: %d"), + pQosMapSet->dscp_exceptions[i][1]); + } + for (i = 0; i < 8; i++) { + lim_log(pMac, LOG1, FL("dscp low for up %d: %d"), i, + pQosMapSet->dscp_range[i][0]); + lim_log(pMac, LOG1, FL("dscp high for up %d: %d"), i, + pQosMapSet->dscp_range[i][1]); + } +} + +tSirRetStatus +populate_dot11f_vht_caps(tpAniSirGlobal pMac, + tpPESession psessionEntry, tDot11fIEVHTCaps *pDot11f) +{ + tSirRetStatus nStatus; + uint32_t 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); + + nCfgValue = 0; + if (psessionEntry->htConfig.ht_sgi) + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ, + nCfgValue); + + pDot11f->shortGI80MHz = (nCfgValue & 0x0001); + + 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; + } + pDot11f->suBeamFormerCap = psessionEntry->enable_su_tx_bformer; + } 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); + 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; + } + } + if (psessionEntry->nss == 1) { + pDot11f->txMCSMap |= DISABLE_NSS2_MCS; + pDot11f->rxMCSMap |= DISABLE_NSS2_MCS; + } + } + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, + nCfgValue); + pDot11f->txSupDataRate = (nCfgValue & 0x00001FFF); + + pDot11f->reserved3 = 0; + + lim_log_vht_cap(pMac, pDot11f); + + return eSIR_SUCCESS; + +} + +tSirRetStatus +populate_dot11f_vht_operation(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEVHTOperation *pDot11f) +{ + tSirRetStatus nStatus; + uint32_t nCfgValue = 0; + + pDot11f->present = 1; + + if (psessionEntry->ch_width > CH_WIDTH_40MHZ) { + pDot11f->chanWidth = psessionEntry->ch_width - 1; + pDot11f->chanCenterFreqSeg1 = + psessionEntry->ch_center_freq_seg0; + if (psessionEntry->ch_width == CH_WIDTH_80P80MHZ) + pDot11f->chanCenterFreqSeg2 = + psessionEntry->ch_center_freq_seg1; + else + pDot11f->chanCenterFreqSeg2 = 0; + } else { + pDot11f->chanWidth = 0; + pDot11f->chanCenterFreqSeg1 = 0; + pDot11f->chanCenterFreqSeg2 = 0; + } + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_BASIC_MCS_SET, nCfgValue); + pDot11f->basicMCSSet = (uint16_t) nCfgValue; + + lim_log_vht_operation(pMac, pDot11f); + + return eSIR_SUCCESS; + +} + +tSirRetStatus +populate_dot11f_vht_ext_bss_load(tpAniSirGlobal pMac, + tDot11fIEVHTExtBssLoad *pDot11f) +{ + tSirRetStatus nStatus; + uint32_t nCfgValue = 0; + + pDot11f->present = 1; + + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_MU_MIMO_CAP_STA_COUNT, + nCfgValue); + pDot11f->muMIMOCapStaCount = (uint8_t) nCfgValue; + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_SS_UNDER_UTIL, nCfgValue); + pDot11f->ssUnderUtil = (uint8_t) nCfgValue; + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_40MHZ_UTILIZATION, nCfgValue); + pDot11f->FortyMHzUtil = (uint8_t) nCfgValue; + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_80MHZ_UTILIZATION, nCfgValue); + pDot11f->EightyMHzUtil = (uint8_t) nCfgValue; + + nCfgValue = 0; + CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_160MHZ_UTILIZATION, nCfgValue); + pDot11f->EightyMHzUtil = (uint8_t) nCfgValue; + + lim_log_vht_ext_bss_load(pMac, pDot11f); + + return eSIR_SUCCESS; +} + +tSirRetStatus +populate_dot11f_ext_cap(tpAniSirGlobal pMac, + bool isVHTEnabled, tDot11fIEExtCap *pDot11f, + tpPESession psessionEntry) +{ + uint32_t val = 0; + struct s_ext_cap *p_ext_cap; + + pDot11f->present = 1; + + if (!psessionEntry) { + lim_log(pMac, LOG1, FL("11MC - enabled for non-SAP cases")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else if (psessionEntry->sap_dot11mc) { + lim_log(pMac, LOG1, FL("11MC support enabled")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else { + if (eLIM_AP_ROLE != psessionEntry->limSystemRole) { + lim_log(pMac, LOG1, FL("11MC support enabled")); + pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN; + } else { + lim_log(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 == true) + p_ext_cap->oper_mode_notification = 1; +#endif + + if (wlan_cfg_get_int(pMac, WNI_CFG_RTT3_ENABLE, &val) != eSIR_SUCCESS) { + lim_log(pMac, LOGE, + FL("could not retrieve RTT3 Variable from DAT File \n")); + return eSIR_FAILURE; + } + + if (val) { /* If set to true then set RTTv3 */ + if (!psessionEntry || LIM_IS_STA_ROLE(psessionEntry)) { + p_ext_cap->fine_time_meas_initiator = + (pMac->fine_time_meas_cap & + FINE_TIME_MEAS_STA_INITIATOR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (pMac->fine_time_meas_cap & + FINE_TIME_MEAS_STA_RESPONDER) ? 1 : 0; + } else if (LIM_IS_AP_ROLE(psessionEntry)) { + p_ext_cap->fine_time_meas_initiator = + (pMac->fine_time_meas_cap & + FINE_TIME_MEAS_SAP_INITIATOR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (pMac->fine_time_meas_cap & + FINE_TIME_MEAS_SAP_RESPONDER) ? 1 : 0; + } + } +#ifdef QCA_HT_2040_COEX + if (pMac->roam.configParam.obssEnabled) + p_ext_cap->bss_coexist_mgmt_support = 1; +#endif + p_ext_cap->ext_chan_switch = 1; + + return eSIR_SUCCESS; +} + +tSirRetStatus +populate_dot11f_operating_mode(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 +populate_dot11f_ht_info(tpAniSirGlobal pMac, + tDot11fIEHTInfo *pDot11f, tpPESession psessionEntry) +{ + uint32_t nCfgValue, nCfgLen; + uint8_t htInfoField1; + uint16_t htInfoField2; + tSirRetStatus nSirStatus; + tSirMacHTInfoField1 *pHTInfoField1; + tSirMacHTInfoField2 *pHTInfoField2; + union { + uint16_t nCfgValue16; + tSirMacHTInfoField3 infoField3; + } uHTInfoField; + union { + uint16_t 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(lim_log(pMac, LOG1, + FL + ("Invalid session entry in populate_dot11f_ht_info()\n")); + ) + return eSIR_FAILURE; + } + + pDot11f->primaryChannel = psessionEntry->currentOperChannel; + + CFG_GET_INT(nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD1, nCfgValue); + + htInfoField1 = (uint8_t) nCfgValue; + + pHTInfoField1 = (tSirMacHTInfoField1 *) &htInfoField1; + pHTInfoField1->rifsMode = psessionEntry->beaconParams.fRIFSMode; + pHTInfoField1->serviceIntervalGranularity = + pMac->lim.gHTServiceIntervalGranularity; + + if (psessionEntry == NULL) { + PELOGE(lim_log(pMac, LOG1, + FL + ("Keep the value retrieved from cfg for secondary channel offset and recommended Tx Width set\n")); + ) + } 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); + + uHTInfoField2.nCfgValue16 = nCfgValue & 0xFFFF; /* this is added for fixing CRs on MDM9K platform - 257951, 259577 */ + + uHTInfoField2.infoField2.opMode = psessionEntry->htOperMode; + uHTInfoField2.infoField2.nonGFDevicesPresent = + psessionEntry->beaconParams.llnNonGFCoexist; + uHTInfoField2.infoField2.obssNonHTStaPresent = psessionEntry->beaconParams.gHTObssMode; /*added for Obss */ + + uHTInfoField2.infoField2.reserved = 0; + + } else { + CFG_GET_INT(nSirStatus, pMac, WNI_CFG_HT_INFO_FIELD2, + nCfgValue); + + htInfoField2 = (uint16_t) nCfgValue; + + pHTInfoField2 = (tSirMacHTInfoField2 *) &htInfoField2; + pHTInfoField2->opMode = pMac->lim.gHTOperMode; + pHTInfoField2->nonGFDevicesPresent = + pMac->lim.gHTNonGFDevicesPresent; + pHTInfoField2->obssNonHTStaPresent = pMac->lim.gHTObssMode; /*added for Obss */ + + 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 populate_dot11f_ht_info. */ + +void +populate_dot11f_ibss_params(tpAniSirGlobal pMac, + tDot11fIEIBSSParams *pDot11f, + tpPESession psessionEntry) +{ + uint32_t val = 0; + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + if (wlan_cfg_get_int(pMac, + WNI_CFG_IBSS_ATIM_WIN_SIZE, + &val) != eSIR_SUCCESS) { + PELOGE(lim_log + (pMac, LOGE, + FL("could not retrieve IBSS ATIM WIN size")); + ) + } + pDot11f->present = 1; + /* ATIM duration is always set to 0 */ + pDot11f->atim = val; + } + +} /* End populate_dot11f_ibss_params. */ + +#ifdef ANI_SUPPORT_11H +tSirRetStatus +populate_dot11f_measurement_report0(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f) +{ + pDot11f->token = pReq->measReqIE.measToken; + pDot11f->late = 0; + pDot11f->incapable = 0; + pDot11f->refused = 1; + pDot11f->type = SIR_MAC_BASIC_MEASUREMENT_TYPE; + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} /* End PopulatedDot11fMeasurementReport0. */ +tSirRetStatus +populate_dot11f_measurement_report1(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f) +{ + pDot11f->token = pReq->measReqIE.measToken; + pDot11f->late = 0; + pDot11f->incapable = 0; + pDot11f->refused = 1; + pDot11f->type = SIR_MAC_CCA_MEASUREMENT_TYPE; + pDot11f->present = 1; + return eSIR_SUCCESS; +} /* End PopulatedDot11fMeasurementReport1. */ +tSirRetStatus +populate_dot11f_measurement_report2(tpAniSirGlobal pMac, + tpSirMacMeasReqActionFrame pReq, + tDot11fIEMeasurementReport *pDot11f) +{ + pDot11f->token = pReq->measReqIE.measToken; + pDot11f->late = 0; + pDot11f->incapable = 0; + pDot11f->refused = 1; + pDot11f->type = SIR_MAC_RPI_MEASUREMENT_TYPE; + pDot11f->present = 1; + return eSIR_SUCCESS; +} /* End PopulatedDot11fMeasurementReport2. */ +#endif + +void +populate_dot11f_power_caps(tpAniSirGlobal pMac, + tDot11fIEPowerCaps *pCaps, + uint8_t 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 populate_dot11f_power_caps. */ + +tSirRetStatus +populate_dot11f_power_constraints(tpAniSirGlobal pMac, + tDot11fIEPowerConstraints *pDot11f) +{ + uint32_t cfg; + tSirRetStatus nSirStatus; + + CFG_GET_INT(nSirStatus, pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, cfg); + + pDot11f->localPowerConstraints = (uint8_t) cfg; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} /* End populate_dot11f_power_constraints. */ + +void +populate_dot11f_qos_caps_ap(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 +populate_dot11f_qos_caps_station(tpAniSirGlobal pMac, + tDot11fIEQOSCapsStation *pDot11f) +{ + uint32_t val = 0; + + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, FL("could not retrieve Max SP Length \n")); + ) + + pDot11f->more_data_ack = 0; + pDot11f->max_sp_length = (uint8_t) 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 +populate_dot11f_rsn(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIERSN *pDot11f) +{ + uint32_t status; + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_RSN))) { + status = dot11f_unpack_ie_rsn(pMac, pRsnIe->rsnIEdata + idx + 2, /* EID, length */ + pRsnIe->rsnIEdata[idx + 1], + pDot11f); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL("Parse failure in PopulateDot11fRS" + "N (0x%08x).\n"), status); + return eSIR_FAILURE; + } + dot11f_log(pMac, LOG2, + FL("dot11f_unpack_ie_rsn returned 0x%08x in " + "populate_dot11f_rsn.\n"), status); + } + + } + + return eSIR_SUCCESS; +} /* End populate_dot11f_rsn. */ + +tSirRetStatus populate_dot11f_rsn_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIERSNOpaque *pDot11f) +{ + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_RSN))) { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1]; + cdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2, /* EID, len */ + pRsnIe->rsnIEdata[idx + 1]); + } + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_rsn_opaque. */ + +#if defined(FEATURE_WLAN_WAPI) + +tSirRetStatus +populate_dot11f_wapi(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIEWAPI *pDot11f) +{ + uint32_t status; + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_WAPI))) { + status = dot11f_unpack_ie_wapi(pMac, pRsnIe->rsnIEdata + idx + 2, /* EID, length */ + pRsnIe->rsnIEdata[idx + 1], + pDot11f); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL + ("Parse failure in populate_dot11f_wapi (0x%08x).\n"), + status); + return eSIR_FAILURE; + } + dot11f_log(pMac, LOG2, + FL("dot11f_unpack_ie_rsn returned 0x%08x in " + "populate_dot11f_wapi.\n"), status); + } + } + + return eSIR_SUCCESS; +} /* End populate_dot11f_wapi. */ + +tSirRetStatus populate_dot11f_wapi_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWAPIOpaque *pDot11f) +{ + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_WAPI))) { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1]; + cdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2, /* EID, len */ + pRsnIe->rsnIEdata[idx + 1]); + } + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_wapi_opaque. */ + +#endif /* defined(FEATURE_WLAN_WAPI) */ + +void +populate_dot11f_ssid(tpAniSirGlobal pMac, + tSirMacSSid *pInternal, tDot11fIESSID *pDot11f) +{ + pDot11f->present = 1; + pDot11f->num_ssid = pInternal->length; + if (pInternal->length) { + cdf_mem_copy((uint8_t *) pDot11f->ssid, + (uint8_t *) &pInternal->ssId, pInternal->length); + } +} /* End populate_dot11f_ssid. */ + +tSirRetStatus populate_dot11f_ssid2(tpAniSirGlobal pMac, tDot11fIESSID *pDot11f) +{ + uint32_t nCfg; + tSirRetStatus nSirStatus; + + CFG_GET_STR(nSirStatus, pMac, WNI_CFG_SSID, pDot11f->ssid, nCfg, 32); + pDot11f->num_ssid = (uint8_t) nCfg; + pDot11f->present = 1; + return eSIR_SUCCESS; +} /* End populate_dot11f_ssid2. */ + +void +populate_dot11f_schedule(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 populate_dot11f_schedule. */ + +void +populate_dot11f_supp_channels(tpAniSirGlobal pMac, + tDot11fIESuppChannels *pDot11f, + uint8_t nAssocType, tpPESession psessionEntry) +{ + uint8_t i; + uint8_t *p; + + if (nAssocType == LIM_REASSOC) { + p = (uint8_t *) psessionEntry->pLimReAssocReq-> + supportedChannels.channelList; + pDot11f->num_bands = + psessionEntry->pLimReAssocReq->supportedChannels.numChnl; + } else { + p = (uint8_t *) 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 populate_dot11f_supp_channels. */ + +tSirRetStatus +populate_dot11f_supp_rates(tpAniSirGlobal pMac, + uint8_t nChannelNum, + tDot11fIESuppRates *pDot11f, tpPESession psessionEntry) +{ + tSirRetStatus nSirStatus; + uint32_t nRates; + uint8_t 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; + cdf_mem_copy(rates, psessionEntry->rateSet.rate, + nRates); + } else { + dot11f_log(pMac, LOGE, + FL + ("no session context exists while populating Operational Rate Set\n")); + 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 = (uint8_t) nRates; + cdf_mem_copy(pDot11f->rates, rates, nRates); + pDot11f->present = 1; + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_supp_rates. */ + +/** + * populate_dot11f_rates_tdls() - populate supported rates and + * extended supported rates IE. + * @p_mac gloabl - header. + * @p_supp_rates - pointer to supported rates IE + * @p_ext_supp_rates - pointer to extended supported rates IE + * + * This function populates the supported rates and extended supported + * rates IE based in the STA capability. If the number of rates + * supported is less than MAX_NUM_SUPPORTED_RATES, only supported rates + * IE is populated. + * + * Return: tSirRetStatus eSIR_SUCCESS on Success and eSIR_FAILURE + * on failure. + */ + +tSirRetStatus +populate_dot11f_rates_tdls(tpAniSirGlobal p_mac, + tDot11fIESuppRates *p_supp_rates, + tDot11fIEExtSuppRates *p_ext_supp_rates) +{ + tSirMacRateSet temp_rateset; + tSirMacRateSet temp_rateset2; + uint32_t val, i; + uint32_t self_dot11mode = 0; + + wlan_cfg_get_int(p_mac, WNI_CFG_DOT11_MODE, &self_dot11mode); + + /** + * Include 11b rates only when the device configured in + * auto, 11a/b/g or 11b_only + */ + if ((self_dot11mode == WNI_CFG_DOT11_MODE_ALL) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11A) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11AC) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11N) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11G) || + (self_dot11mode == WNI_CFG_DOT11_MODE_11B) ) { + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfg_get_str(p_mac, WNI_CFG_SUPPORTED_RATES_11B, + (uint8_t *)&temp_rateset.rate, &val); + temp_rateset.numRates = (uint8_t) 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_cfg_get_str(p_mac, WNI_CFG_SUPPORTED_RATES_11A, + (uint8_t *)&temp_rateset2.rate, &val); + temp_rateset2.numRates = (uint8_t) val; + } else { + temp_rateset2.numRates = 0; + } + + if ((temp_rateset.numRates + temp_rateset2.numRates) > + SIR_MAC_MAX_NUMBER_OF_RATES) { + lim_log(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; + cdf_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; + cdf_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; + cdf_mem_copy(p_ext_supp_rates->rates, + (uint8_t *)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 +populate_dot11f_tpc_report(tpAniSirGlobal pMac, + tDot11fIETPCReport *pDot11f, tpPESession psessionEntry) +{ + uint16_t staid, txPower; + tSirRetStatus nSirStatus; + + nSirStatus = lim_get_mgmt_staid(pMac, &staid, psessionEntry); + if (eSIR_SUCCESS != nSirStatus) { + dot11f_log(pMac, LOG1, FL("Failed to get the STAID in Populat" + "eDot11fTPCReport; lim_get_mgmt_staid " + "returned status %d.\n"), 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 = (uint8_t) txPower; + pDot11f->link_margin = 0; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} /* End populate_dot11f_tpc_report. */ + +void populate_dot11f_ts_info(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 populate_dot11f_wmm(tpAniSirGlobal pMac, + tDot11fIEWMMInfoAp *pInfo, + tDot11fIEWMMParams *pParams, + tDot11fIEWMMCaps *pCaps, tpPESession psessionEntry) +{ + if (psessionEntry->limWmeEnabled) { + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + /* if ( ! sirIsPropCapabilityEnabled( pMac, SIR_MAC_PROP_CAPABILITY_WME ) ) */ + { + populate_dot11f_wmm_info_ap(pMac, pInfo, + psessionEntry); + } + } else { + { + populate_dot11f_wmm_params(pMac, pParams, + psessionEntry); + } + + if (psessionEntry->limWsmEnabled) { + populate_dot11f_wmm_caps(pCaps); + } + } + } +} /* End populate_dot11f_wmm. */ + +void populate_dot11f_wmm_caps(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 populate_dot11f_re_assoc_tspec(tpAniSirGlobal pMac, + tDot11fReAssocRequest *pReassoc, + tpPESession psessionEntry) +{ + uint8_t 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; idx < numTspecs; idx++) { + populate_dot11f_wmmtspec(&pTspec->tspec, + &pReassoc->WMMTSPEC[idx]); + pTspec->tspec.mediumTime = 0; + pTspec++; + } + } +} +#endif + +void populate_dot11f_wmm_info_ap(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 populate_dot11f_wmm_info_station_per_session(tpAniSirGlobal pMac, + tpPESession psessionEntry, + tDot11fIEWMMInfoStation *pInfo) +{ + uint32_t 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_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) != eSIR_SUCCESS) + PELOGE(lim_log + (pMac, LOGE, FL("could not retrieve Max SP Length \n")); + ) + + pInfo->max_sp_length = (uint8_t) val; + pInfo->present = 1; +} + +void populate_dot11f_wmm_params(tpAniSirGlobal pMac, + tDot11fIEWMMParams *pParams, + tpPESession psessionEntry) +{ + pParams->version = SIR_MAC_OUI_VERSION_1; + + if (LIM_IS_AP_ROLE(psessionEntry)) + pParams->qosInfo = + (psessionEntry-> + apUapsdEnable << 7) | ((uint8_t) (0x0f & psessionEntry-> + gLimEdcaParamSetCount)); + else + pParams->qosInfo = + (pMac->lim. + gUapsdEnable << 7) | ((uint8_t) (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 populate_dot11f_wmm_params. */ + +void populate_dot11f_wmm_schedule(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 populate_dot11f_wmm_schedule. */ + +tSirRetStatus +populate_dot11f_wpa(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, tDot11fIEWPA *pDot11f) +{ + uint32_t status; + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_WPA))) { + status = dot11f_unpack_ie_wpa(pMac, pRsnIe->rsnIEdata + idx + 2 + 4, /* EID, length, OUI */ + pRsnIe->rsnIEdata[idx + 1] - 4, /* OUI */ + pDot11f); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL("Parse failure in PopulateDot11fWP" + "A (0x%08x).\n"), status); + return eSIR_FAILURE; + } + } + } + + return eSIR_SUCCESS; +} /* End populate_dot11f_wpa. */ + +tSirRetStatus populate_dot11f_wpa_opaque(tpAniSirGlobal pMac, + tpSirRSNie pRsnIe, + tDot11fIEWPAOpaque *pDot11f) +{ + int idx; + + if (pRsnIe->length) { + if (0 <= (idx = find_ie_location(pMac, pRsnIe, DOT11F_EID_WPA))) { + pDot11f->present = 1; + pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1] - 4; + cdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2 + 4, /* EID, len, OUI */ + pRsnIe->rsnIEdata[idx + 1] - 4); /* OUI */ + } + } + + return eSIR_SUCCESS; + +} /* End populate_dot11f_wpa_opaque. */ + +/* ////////////////////////////////////////////////////////////////////// */ + +tSirRetStatus +sir_convert_probe_req_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tpSirProbeReq pProbeReq) +{ + uint32_t status; + tDot11fProbeRequest pr; + + /* Ok, zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pProbeReq, sizeof(tSirProbeReq), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_probe_request(pMac, pFrame, nFrame, &pr); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse a Probe Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Probe Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + } + /* & "transliterate" from a 'tDot11fProbeRequestto' a 'tSirProbeReq'... */ + if (!pr.SSID.present) { + PELOGW(lim_log + (pMac, LOGW, FL("Mandatory IE SSID not present!\n")); + ) + } else { + pProbeReq->ssidPresent = 1; + convert_ssid(pMac, &pProbeReq->ssId, &pr.SSID); + } + + if (!pr.SuppRates.present) { + PELOGW(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + return eSIR_FAILURE; + } else { + pProbeReq->suppRatesPresent = 1; + convert_supp_rates(pMac, &pProbeReq->supportedRates, + &pr.SuppRates); + } + + if (pr.ExtSuppRates.present) { + pProbeReq->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pProbeReq->extendedRates, + &pr.ExtSuppRates); + } + + if (pr.HTCaps.present) { + cdf_mem_copy(&pProbeReq->HTCaps, &pr.HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (pr.WscProbeReq.present) { + pProbeReq->wscIePresent = 1; + memcpy(&pProbeReq->probeReqWscIeInfo, &pr.WscProbeReq, + sizeof(tDot11fIEWscProbeReq)); + } +#ifdef WLAN_FEATURE_11AC + if (pr.VHTCaps.present) { + cdf_mem_copy(&pProbeReq->VHTCaps, &pr.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } +#endif + + if (pr.P2PProbeReq.present) { + pProbeReq->p2pIePresent = 1; + } + + return eSIR_SUCCESS; + +} /* End sir_convert_probe_req_frame2_struct. */ + +tSirRetStatus sir_convert_probe_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, + tpSirProbeRespBeacon pProbeResp) +{ + uint32_t status; + tDot11fProbeResponse *pr; + + /* Ok, zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pProbeResp, sizeof(tSirProbeRespBeacon), 0); + + pr = cdf_mem_malloc(sizeof(tDot11fProbeResponse)); + if (NULL == pr) { + lim_log(pMac, LOGE, FL("Failed to allocate memory\n")); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) pr, sizeof(tDot11fProbeResponse), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_probe_response(pMac, pFrame, nFrame, pr); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse a Probe Response (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + cdf_mem_free(pr); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Probe Response (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + } + /* & "transliterate" from a 'tDot11fProbeResponse' to a 'tSirProbeRespBeacon'... */ + + /* Timestamp */ + cdf_mem_copy((uint8_t *) pProbeResp->timeStamp, + (uint8_t *) &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(lim_log + (pMac, LOGW, FL("Mandatory IE SSID not present!\n")); + ) + } else { + pProbeResp->ssidPresent = 1; + convert_ssid(pMac, &pProbeResp->ssId, &pr->SSID); + } + + if (!pr->SuppRates.present) { + PELOGW(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + } else { + pProbeResp->suppRatesPresent = 1; + convert_supp_rates(pMac, &pProbeResp->supportedRates, + &pr->SuppRates); + } + + if (pr->ExtSuppRates.present) { + pProbeResp->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pProbeResp->extendedRates, + &pr->ExtSuppRates); + } + + if (pr->CFParams.present) { + pProbeResp->cfPresent = 1; + convert_cf_params(pMac, &pProbeResp->cfParamSet, &pr->CFParams); + } + + if (pr->Country.present) { + pProbeResp->countryInfoPresent = 1; + convert_country(pMac, &pProbeResp->countryInfoParam, + &pr->Country); + } + + if (pr->EDCAParamSet.present) { + pProbeResp->edcaPresent = 1; + convert_edca_param(pMac, &pProbeResp->edcaParams, + &pr->EDCAParamSet); + } + + if (pr->ChanSwitchAnn.present) { + pProbeResp->channelSwitchPresent = 1; + cdf_mem_copy(&pProbeResp->channelSwitchIE, &pr->ChanSwitchAnn, + sizeof(pProbeResp->channelSwitchIE)); + } + + if (pr->ext_chan_switch_ann.present) { + pProbeResp->ext_chan_switch_present = 1; + cdf_mem_copy(&pProbeResp->ext_chan_switch, + &pr->ext_chan_switch_ann, + sizeof(tDot11fIEext_chan_switch_ann)); + } + + if (pr->sec_chan_offset_ele.present) { + pProbeResp->sec_chan_offset_present = 1; + cdf_mem_copy(&pProbeResp->sec_chan_offset, + &pr->sec_chan_offset_ele, + sizeof(pProbeResp->sec_chan_offset)); + } + + if (pr->TPCReport.present) { + pProbeResp->tpcReportPresent = 1; + cdf_mem_copy(&pProbeResp->tpcReport, &pr->TPCReport, + sizeof(tDot11fIETPCReport)); + } + + if (pr->PowerConstraints.present) { + pProbeResp->powerConstraintPresent = 1; + cdf_mem_copy(&pProbeResp->localPowerConstraint, + &pr->PowerConstraints, + sizeof(tDot11fIEPowerConstraints)); + } + + if (pr->Quiet.present) { + pProbeResp->quietIEPresent = 1; + cdf_mem_copy(&pProbeResp->quietIE, &pr->Quiet, + sizeof(tDot11fIEQuiet)); + } + + if (pr->HTCaps.present) { + cdf_mem_copy(&pProbeResp->HTCaps, &pr->HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (pr->HTInfo.present) { + cdf_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; + convert_rsn_opaque(pMac, &pProbeResp->rsn, &pr->RSNOpaque); + } + + if (pr->WPA.present) { + pProbeResp->wpaPresent = 1; + convert_wpa(pMac, &pProbeResp->wpa, &pr->WPA); + } + + if (pr->WMMParams.present) { + pProbeResp->wmeEdcaPresent = 1; + convert_wmm_params(pMac, &pProbeResp->edcaParams, &pr->WMMParams); + PELOG1(lim_log + (pMac, LOG1, + FL("WMM Parameter present in Probe Response Frame!\n")); + __print_wmm_params(pMac, &pr->WMMParams); + ) + } + + if (pr->WMMInfoAp.present) { + pProbeResp->wmeInfoPresent = 1; + PELOG1(lim_log + (pMac, LOG1, + FL + ("WMM Information Element present in Probe Response Frame!\n")); + ) + } + + if (pr->WMMCaps.present) { + pProbeResp->wsmCapablePresent = 1; + } + + if (pr->ERPInfo.present) { + pProbeResp->erpPresent = 1; + convert_erp_info(pMac, &pProbeResp->erpIEInfo, &pr->ERPInfo); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pr->MobilityDomain.present) { + /* MobilityDomain */ + pProbeResp->mdiePresent = 1; + cdf_mem_copy((uint8_t *) &(pProbeResp->mdie[0]), + (uint8_t *) &(pr->MobilityDomain.MDID), + sizeof(uint16_t)); + pProbeResp->mdie[2] = + ((pr->MobilityDomain.overDSCap << 0) | (pr->MobilityDomain. + resourceReqCap << + 1)); +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(pMac, LOG2, FL("mdie=%02x%02x%02x\n"), + (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) { + cdf_mem_copy(&pProbeResp->QBSSLoad, &pr->QBSSLoad, + sizeof(tDot11fIEQBSSLoad)); + } +#endif + if (pr->P2PProbeRes.present) { + cdf_mem_copy(&pProbeResp->P2PProbeRes, &pr->P2PProbeRes, + sizeof(tDot11fIEP2PProbeRes)); + } +#ifdef WLAN_FEATURE_11AC + if (pr->VHTCaps.present) { + cdf_mem_copy(&pProbeResp->VHTCaps, &pr->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pr->VHTOperation.present) { + cdf_mem_copy(&pProbeResp->VHTOperation, &pr->VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } + if (pr->VHTExtBssLoad.present) { + cdf_mem_copy(&pProbeResp->VHTExtBssLoad, &pr->VHTExtBssLoad, + sizeof(tDot11fIEVHTExtBssLoad)); + } +#endif + pProbeResp->Vendor1IEPresent = pr->Vendor1IE.present; + pProbeResp->Vendor3IEPresent = pr->Vendor3IE.present; + + pProbeResp->vendor2_ie.present = pr->vendor2_ie.present; + if (pr->vendor2_ie.present) { + pProbeResp->vendor2_ie.type = pr->vendor2_ie.type; + pProbeResp->vendor2_ie.sub_type = pr->vendor2_ie.sub_type; + } + if (pr->vendor2_ie.VHTCaps.present) { + cdf_mem_copy(&pProbeResp->vendor2_ie.VHTCaps, + &pr->vendor2_ie.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pr->vendor2_ie.VHTOperation.present) { + cdf_mem_copy(&pProbeResp->vendor2_ie.VHTOperation, + &pr->vendor2_ie.VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } + cdf_mem_free(pr); + return eSIR_SUCCESS; + +} /* End sir_convert_probe_frame2_struct. */ + +tSirRetStatus +sir_convert_assoc_req_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tpSirAssocReq pAssocReq) +{ + tDot11fAssocRequest *ar; + uint32_t status; + + ar = cdf_mem_malloc(sizeof(tDot11fAssocRequest)); + if (NULL == ar) { + lim_log(pMac, LOGE, FL("Failed to allocate memory\n")); + return eSIR_MEM_ALLOC_FAILED; + } + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAssocReq, sizeof(tSirAssocReq), 0); + cdf_mem_set((uint8_t *) ar, sizeof(tDot11fAssocRequest), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_assoc_request(pMac, pFrame, nFrame, ar); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse an Association Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + cdf_mem_free(ar); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking an Assoication Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (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; + convert_ssid(pMac, &pAssocReq->ssId, &ar->SSID); + } + /* Supported Rates */ + if (ar->SuppRates.present) { + pAssocReq->suppRatesPresent = 1; + convert_supp_rates(pMac, &pAssocReq->supportedRates, + &ar->SuppRates); + } + /* Extended Supported Rates */ + if (ar->ExtSuppRates.present) { + pAssocReq->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pAssocReq->extendedRates, + &ar->ExtSuppRates); + } + /* QOS Capabilities: */ + if (ar->QOSCapsStation.present) { + pAssocReq->qosCapabilityPresent = 1; + convert_qos_caps_station(pMac, &pAssocReq->qosCapability, + &ar->QOSCapsStation); + } + /* WPA */ + if (ar->WPAOpaque.present) { + pAssocReq->wpaPresent = 1; + convert_wpa_opaque(pMac, &pAssocReq->wpa, &ar->WPAOpaque); + } +#ifdef FEATURE_WLAN_WAPI + if (ar->WAPIOpaque.present) { + pAssocReq->wapiPresent = 1; + convert_wapi_opaque(pMac, &pAssocReq->wapi, &ar->WAPIOpaque); + } +#endif + /* RSN */ + if (ar->RSNOpaque.present) { + pAssocReq->rsnPresent = 1; + convert_rsn_opaque(pMac, &pAssocReq->rsn, &ar->RSNOpaque); + } + /* WSC IE */ + if (ar->WscIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_wsc_opaque(pMac, &pAssocReq->addIE, &ar->WscIEOpaque); + } + + if (ar->P2PIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_p2p_opaque(pMac, &pAssocReq->addIE, &ar->P2PIEOpaque); + } +#ifdef WLAN_FEATURE_WFD + if (ar->WFDIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_wfd_opaque(pMac, &pAssocReq->addIE, &ar->WFDIEOpaque); + } +#endif + + /* Power Capabilities */ + if (ar->PowerCaps.present) { + pAssocReq->powerCapabilityPresent = 1; + convert_power_caps(pMac, &pAssocReq->powerCapability, + &ar->PowerCaps); + } + /* Supported Channels */ + if (ar->SuppChannels.present) { + pAssocReq->supportedChannelsPresent = 1; + convert_supp_channels(pMac, &pAssocReq->supportedChannels, + &ar->SuppChannels); + } + + if (ar->HTCaps.present) { + cdf_mem_copy(&pAssocReq->HTCaps, &ar->HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (ar->WMMInfoStation.present) { + pAssocReq->wmeInfoPresent = 1; + cdf_mem_copy(&pAssocReq->WMMInfoStation, &ar->WMMInfoStation, + sizeof(tDot11fIEWMMInfoStation)); + + } + + if (ar->WMMCaps.present) + pAssocReq->wsmCapablePresent = 1; + + if (!pAssocReq->ssidPresent) { + PELOG2(lim_log + (pMac, LOG2, FL("Received Assoc without SSID IE.\n")); + ) + cdf_mem_free(ar); + return eSIR_FAILURE; + } + + if (!pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent) { + PELOG2(lim_log + (pMac, LOG2, + FL("Received Assoc without supp rate IE.\n")); + ) + cdf_mem_free(ar); + return eSIR_FAILURE; + } +#ifdef WLAN_FEATURE_11AC + if (ar->VHTCaps.present) { + cdf_mem_copy(&pAssocReq->VHTCaps, &ar->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + lim_log(pMac, LOGW, FL("Received Assoc Req with VHT Cap\n")); + lim_log_vht_cap(pMac, &pAssocReq->VHTCaps); + } + if (ar->OperatingMode.present) { + cdf_mem_copy(&pAssocReq->operMode, &ar->OperatingMode, + sizeof(tDot11fIEOperatingMode)); + lim_log(pMac, LOGW, + FL("Received Assoc Req with Operating Mode IE\n")); + lim_log_operating_mode(pMac, &pAssocReq->operMode); + } +#endif + if (ar->ExtCap.present) { + struct s_ext_cap *ext_cap; + cdf_mem_copy(&pAssocReq->ExtCap.bytes, &ar->ExtCap.bytes, + ar->ExtCap.num_bytes); + + ext_cap = (struct s_ext_cap *)&pAssocReq->ExtCap.bytes; + lim_log(pMac, LOG1, + FL("timingMeas: %d, finetimingMeas Init: %d, Resp: %d"), + ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, + ext_cap->fine_time_meas_responder); + } + cdf_mem_free(ar); + return eSIR_SUCCESS; + +} /* End sir_convert_assoc_req_frame2_struct. */ + +tSirRetStatus +sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tpSirAssocRsp pAssocRsp) +{ + static tDot11fAssocResponse ar; + uint32_t status; + uint8_t cnt = 0; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAssocRsp, sizeof(tSirAssocRsp), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_assoc_response(pMac, pFrame, nFrame, &ar); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse an Association Response (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking an Association Response (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (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(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + } else { + pAssocRsp->suppRatesPresent = 1; + convert_supp_rates(pMac, &pAssocRsp->supportedRates, + &ar.SuppRates); + } + + if (ar.ExtSuppRates.present) { + pAssocRsp->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pAssocRsp->extendedRates, + &ar.ExtSuppRates); + } + + if (ar.EDCAParamSet.present) { + pAssocRsp->edcaPresent = 1; + convert_edca_param(pMac, &pAssocRsp->edca, &ar.EDCAParamSet); + } + + if (ar.WMMParams.present) { + pAssocRsp->wmeEdcaPresent = 1; + convert_wmm_params(pMac, &pAssocRsp->edca, &ar.WMMParams); + lim_log(pMac, LOG1, FL("Received Assoc Resp with WMM Param")); + __print_wmm_params(pMac, &ar.WMMParams); + } + + if (ar.HTCaps.present) { + lim_log(pMac, LOG1, FL("Received Assoc Resp with HT Cap")); + cdf_mem_copy(&pAssocRsp->HTCaps, &ar.HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (ar.HTInfo.present) { + lim_log(pMac, LOG1, FL("Received Assoc Resp with HT Info")); + cdf_mem_copy(&pAssocRsp->HTInfo, &ar.HTInfo, + sizeof(tDot11fIEHTInfo)); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (ar.MobilityDomain.present) { + /* MobilityDomain */ + pAssocRsp->mdiePresent = 1; + cdf_mem_copy((uint8_t *) &(pAssocRsp->mdie[0]), + (uint8_t *) &(ar.MobilityDomain.MDID), + sizeof(uint16_t)); + pAssocRsp->mdie[2] = + ((ar.MobilityDomain.overDSCap << 0) | (ar.MobilityDomain. + resourceReqCap << + 1)); +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + lim_log(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 + lim_log(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; + cdf_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) { + cdf_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++) { + cdf_mem_copy(&pAssocRsp->TSPECInfo[cnt], + &ar.WMMTSPEC[cnt], + (sizeof(tDot11fIEWMMTSPEC) * + ar.num_WMMTSPEC)); + } + pAssocRsp->tspecPresent = true; + } + + if (ar.ESETrafStrmMet.present) { + pAssocRsp->tsmPresent = 1; + cdf_mem_copy(&pAssocRsp->tsmIE.tsid, + &ar.ESETrafStrmMet.tsid, sizeof(tSirMacESETSMIE)); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if (ar.VHTCaps.present) { + cdf_mem_copy(&pAssocRsp->VHTCaps, &ar.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + lim_log(pMac, LOG1, FL("Received Assoc Response with VHT Cap")); + lim_log_vht_cap(pMac, &pAssocRsp->VHTCaps); + } + if (ar.VHTOperation.present) { + cdf_mem_copy(&pAssocRsp->VHTOperation, &ar.VHTOperation, + sizeof(tDot11fIEVHTOperation)); + lim_log(pMac, LOG1, + FL("Received Assoc Response with VHT Operation")); + lim_log_vht_operation(pMac, &pAssocRsp->VHTOperation); + } +#endif + + if (ar.ExtCap.present) { + struct s_ext_cap *ext_cap; + cdf_mem_copy(&pAssocRsp->ExtCap.bytes, &ar.ExtCap.bytes, + ar.ExtCap.num_bytes); + + ext_cap = (struct s_ext_cap *)&pAssocRsp->ExtCap.bytes; + lim_log(pMac, LOG1, + FL("timingMeas: %d, finetimingMeas Init: %d, Resp: %d"), + ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, + ext_cap->fine_time_meas_responder); + } + + if (ar.QosMapSet.present) { + pAssocRsp->QosMapSet.present = 1; + convert_qos_mapset_frame(pMac, &pAssocRsp->QosMapSet, + &ar.QosMapSet); + lim_log(pMac, LOG1, + FL("Received Assoc Response with Qos Map Set")); + lim_log_qos_map_set(pMac, &pAssocRsp->QosMapSet); + } + + pAssocRsp->vendor2_ie.present = ar.vendor2_ie.present; + if (ar.vendor2_ie.present) { + pAssocRsp->vendor2_ie.type = ar.vendor2_ie.type; + pAssocRsp->vendor2_ie.sub_type = ar.vendor2_ie.sub_type; + } + + if (ar.vendor2_ie.VHTCaps.present) { + cdf_mem_copy(&pAssocRsp->vendor2_ie.VHTCaps, + &ar.vendor2_ie.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + lim_log(pMac, LOG1, + FL("Received Assoc Response with Vendor specific VHT Cap")); + lim_log_vht_cap(pMac, &pAssocRsp->VHTCaps); + } + if (ar.vendor2_ie.VHTOperation.present) { + cdf_mem_copy(&pAssocRsp->vendor2_ie.VHTOperation, + &ar.vendor2_ie.VHTOperation, + sizeof(tDot11fIEVHTOperation)); + lim_log(pMac, LOG1, + FL("Received Assoc Response with Vendor specific VHT Oper")); + lim_log_vht_operation(pMac, &pAssocRsp->VHTOperation); + } + return eSIR_SUCCESS; + +} /* End sir_convert_assoc_resp_frame2_struct. */ + +tSirRetStatus +sir_convert_reassoc_req_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tpSirAssocReq pAssocReq) +{ + static tDot11fReAssocRequest ar; + uint32_t status; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAssocReq, sizeof(tSirAssocReq), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_re_assoc_request(pMac, pFrame, nFrame, &ar); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse a Re-association Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Re-association Request (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (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; + convert_ssid(pMac, &pAssocReq->ssId, &ar.SSID); + } + /* Supported Rates */ + if (ar.SuppRates.present) { + pAssocReq->suppRatesPresent = 1; + convert_supp_rates(pMac, &pAssocReq->supportedRates, + &ar.SuppRates); + } + /* Extended Supported Rates */ + if (ar.ExtSuppRates.present) { + pAssocReq->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pAssocReq->extendedRates, + &ar.ExtSuppRates); + } + /* QOS Capabilities: */ + if (ar.QOSCapsStation.present) { + pAssocReq->qosCapabilityPresent = 1; + convert_qos_caps_station(pMac, &pAssocReq->qosCapability, + &ar.QOSCapsStation); + } + /* WPA */ + if (ar.WPAOpaque.present) { + pAssocReq->wpaPresent = 1; + convert_wpa_opaque(pMac, &pAssocReq->wpa, &ar.WPAOpaque); + } + /* RSN */ + if (ar.RSNOpaque.present) { + pAssocReq->rsnPresent = 1; + convert_rsn_opaque(pMac, &pAssocReq->rsn, &ar.RSNOpaque); + } + + /* Power Capabilities */ + if (ar.PowerCaps.present) { + pAssocReq->powerCapabilityPresent = 1; + convert_power_caps(pMac, &pAssocReq->powerCapability, + &ar.PowerCaps); + } + /* Supported Channels */ + if (ar.SuppChannels.present) { + pAssocReq->supportedChannelsPresent = 1; + convert_supp_channels(pMac, &pAssocReq->supportedChannels, + &ar.SuppChannels); + } + + if (ar.HTCaps.present) { + cdf_mem_copy(&pAssocReq->HTCaps, &ar.HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (ar.WMMInfoStation.present) { + pAssocReq->wmeInfoPresent = 1; + cdf_mem_copy(&pAssocReq->WMMInfoStation, &ar.WMMInfoStation, + sizeof(tDot11fIEWMMInfoStation)); + + } + + if (ar.WMMCaps.present) + pAssocReq->wsmCapablePresent = 1; + + if (!pAssocReq->ssidPresent) { + PELOG2(lim_log + (pMac, LOG2, FL("Received Assoc without SSID IE.\n")); + ) + return eSIR_FAILURE; + } + + if (!pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent) { + PELOG2(lim_log + (pMac, LOG2, + FL("Received Assoc without supp rate IE.\n")); + ) + return eSIR_FAILURE; + } + /* Why no call to 'updateAssocReqFromPropCapability' here, like */ + /* there is in 'sir_convert_assoc_req_frame2_struct'? */ + + /* WSC IE */ + if (ar.WscIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_wsc_opaque(pMac, &pAssocReq->addIE, &ar.WscIEOpaque); + } + + if (ar.P2PIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_p2p_opaque(pMac, &pAssocReq->addIE, &ar.P2PIEOpaque); + } +#ifdef WLAN_FEATURE_WFD + if (ar.WFDIEOpaque.present) { + pAssocReq->addIEPresent = 1; + convert_wfd_opaque(pMac, &pAssocReq->addIE, &ar.WFDIEOpaque); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if (ar.VHTCaps.present) { + cdf_mem_copy(&pAssocReq->VHTCaps, &ar.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (ar.OperatingMode.present) { + cdf_mem_copy(&pAssocReq->operMode, &ar.OperatingMode, + sizeof(tDot11fIEOperatingMode)); + lim_log(pMac, LOGW, + FL("Received Assoc Req with Operating Mode IE\n")); + lim_log_operating_mode(pMac, &pAssocReq->operMode); + } +#endif + + if (ar.ExtCap.present) { + struct s_ext_cap *ext_cap; + cdf_mem_copy(&pAssocReq->ExtCap.bytes, &ar.ExtCap.bytes, + ar.ExtCap.num_bytes); + + ext_cap = (struct s_ext_cap *)&pAssocReq->ExtCap.bytes; + lim_log(pMac, LOG1, + FL("timingMeas: %d, finetimingMeas Init: %d, Resp: %d"), + ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, + ext_cap->fine_time_meas_responder); + } + + return eSIR_SUCCESS; + +} /* End sir_convert_reassoc_req_frame2_struct. */ + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +tSirRetStatus +sir_beacon_ie_ese_bcn_report(tpAniSirGlobal pMac, + uint8_t *pPayload, const uint32_t nPayload, + uint8_t **outIeBuf, uint32_t *pOutIeLen) +{ + tDot11fBeaconIEs *pBies = NULL; + uint32_t status = CDF_STATUS_SUCCESS; + tSirRetStatus retStatus = eSIR_SUCCESS; + tSirEseBcnReportMandatoryIe eseBcnReportMandatoryIe; + + /* To store how many bytes are required to be allocated + for Bcn report mandatory Ies */ + uint16_t numBytes = 0, freeBytes = 0; + uint8_t *pos = NULL; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) &eseBcnReportMandatoryIe, + sizeof(eseBcnReportMandatoryIe), 0); + pBies = cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if (NULL == pBies) { + lim_log(pMac, LOGE, FL("Failed to allocate memory\n")); + return eSIR_MEM_ALLOC_FAILED; + } + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_beacon_i_es(pMac, pPayload, nPayload, pBies); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to parse Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + cdf_mem_free(pBies); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload); + ) + } + /* & "transliterate" from a 'tDot11fBeaconIEs' to a 'eseBcnReportMandatoryIe'... */ + if (!pBies->SSID.present) { + PELOGW(lim_log + (pMac, LOGW, FL("Mandatory IE SSID not present!\n")); + ) + } else { + eseBcnReportMandatoryIe.ssidPresent = 1; + convert_ssid(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(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + } else { + eseBcnReportMandatoryIe.suppRatesPresent = 1; + convert_supp_rates(pMac, &eseBcnReportMandatoryIe.supportedRates, + &pBies->SuppRates); + numBytes += + 1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates; + } + + if (pBies->FHParamSet.present) { + eseBcnReportMandatoryIe.fhParamPresent = 1; + convert_fh_params(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; + convert_cf_params(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; + cdf_mem_copy(&eseBcnReportMandatoryIe.rmEnabledCapabilities, + &pBies->RRMEnabledCap, + sizeof(tDot11fIERRMEnabledCap)); + numBytes += 1 + 1 + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX; + } + + *outIeBuf = cdf_mem_malloc(numBytes); + if (NULL == *outIeBuf) { + lim_log(pMac, LOGP, FL("Memory Allocation failure")); + cdf_mem_free(pBies); + return eSIR_MEM_ALLOC_FAILED; + } + 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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) 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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) 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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) &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)) { + lim_log(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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) &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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) &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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) &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)) { + lim_log(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++; + cdf_mem_copy(pos, + (uint8_t *) &eseBcnReportMandatoryIe. + rmEnabledCapabilities, + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX); + freeBytes -= (1 + 1 + SIR_MAC_RM_ENABLED_CAPABILITY_EID_MAX); + } + + if (freeBytes != 0) { + lim_log(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) { + cdf_mem_free(*outIeBuf); + *outIeBuf = NULL; + } + + cdf_mem_free(pBies); + return retStatus; +} + +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +tSirRetStatus +sir_parse_beacon_ie(tpAniSirGlobal pMac, + tpSirProbeRespBeacon pBeaconStruct, + uint8_t *pPayload, uint32_t nPayload) +{ + tDot11fBeaconIEs *pBies; + uint32_t status; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pBeaconStruct, sizeof(tSirProbeRespBeacon), 0); + + pBies = cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if (NULL == pBies) { + lim_log(pMac, LOGE, FL("Failed to allocate memory\n")); + return eSIR_MEM_ALLOC_FAILED; + } + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_beacon_i_es(pMac, pPayload, nPayload, pBies); + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to parse Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload); + ) + cdf_mem_free(pBies); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload); + ) + } + /* & "transliterate" from a 'tDot11fBeaconIEs' to a 'tSirProbeRespBeacon'... */ + if (!pBies->SSID.present) { + PELOGW(lim_log + (pMac, LOGW, FL("Mandatory IE SSID not present!\n")); + ) + } else { + pBeaconStruct->ssidPresent = 1; + convert_ssid(pMac, &pBeaconStruct->ssId, &pBies->SSID); + } + + if (!pBies->SuppRates.present) { + PELOGW(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + } else { + pBeaconStruct->suppRatesPresent = 1; + convert_supp_rates(pMac, &pBeaconStruct->supportedRates, + &pBies->SuppRates); + } + + if (pBies->ExtSuppRates.present) { + pBeaconStruct->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pBeaconStruct->extendedRates, + &pBies->ExtSuppRates); + } + + if (pBies->CFParams.present) { + pBeaconStruct->cfPresent = 1; + convert_cf_params(pMac, &pBeaconStruct->cfParamSet, + &pBies->CFParams); + } + + if (pBies->TIM.present) { + pBeaconStruct->timPresent = 1; + convert_tim(pMac, &pBeaconStruct->tim, &pBies->TIM); + } + + if (pBies->Country.present) { + pBeaconStruct->countryInfoPresent = 1; + convert_country(pMac, &pBeaconStruct->countryInfoParam, + &pBies->Country); + } + /* 11h IEs */ + if (pBies->TPCReport.present) { + pBeaconStruct->tpcReportPresent = 1; + cdf_mem_copy(&pBeaconStruct->tpcReport, + &pBies->TPCReport, sizeof(tDot11fIETPCReport)); + } + + if (pBies->PowerConstraints.present) { + pBeaconStruct->powerConstraintPresent = 1; + cdf_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) { + cdf_mem_copy(&pBeaconStruct->QBSSLoad, &pBies->QBSSLoad, + sizeof(tDot11fIEQBSSLoad)); + } +#endif + + if (pBies->EDCAParamSet.present) { + pBeaconStruct->edcaPresent = 1; + convert_edca_param(pMac, &pBeaconStruct->edcaParams, + &pBies->EDCAParamSet); + } + /* QOS Capabilities: */ + if (pBies->QOSCapsAp.present) { + pBeaconStruct->qosCapabilityPresent = 1; + convert_qos_caps(pMac, &pBeaconStruct->qosCapability, + &pBies->QOSCapsAp); + } + + if (pBies->ChanSwitchAnn.present) { + pBeaconStruct->channelSwitchPresent = 1; + cdf_mem_copy(&pBeaconStruct->channelSwitchIE, + &pBies->ChanSwitchAnn, + sizeof(pBeaconStruct->channelSwitchIE)); + } + + if (pBies->ext_chan_switch_ann.present) { + pBeaconStruct->ext_chan_switch_present = 1; + cdf_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; + cdf_mem_copy(&pBeaconStruct->sec_chan_offset, + &pBies->sec_chan_offset_ele, + sizeof(pBeaconStruct->sec_chan_offset)); + } + + if (pBies->Quiet.present) { + pBeaconStruct->quietIEPresent = 1; + cdf_mem_copy(&pBeaconStruct->quietIE, &pBies->Quiet, + sizeof(tDot11fIEQuiet)); + } + + if (pBies->HTCaps.present) { + cdf_mem_copy(&pBeaconStruct->HTCaps, &pBies->HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (pBies->HTInfo.present) { + cdf_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; + convert_rsn(pMac, &pBeaconStruct->rsn, &pBies->RSN); + } + + if (pBies->WPA.present) { + pBeaconStruct->wpaPresent = 1; + convert_wpa(pMac, &pBeaconStruct->wpa, &pBies->WPA); + } + + if (pBies->WMMParams.present) { + pBeaconStruct->wmeEdcaPresent = 1; + convert_wmm_params(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; + convert_erp_info(pMac, &pBeaconStruct->erpIEInfo, + &pBies->ERPInfo); + } +#ifdef WLAN_FEATURE_11AC + if (pBies->VHTCaps.present) { + pBeaconStruct->VHTCaps.present = 1; + cdf_mem_copy(&pBeaconStruct->VHTCaps, &pBies->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pBies->VHTOperation.present) { + pBeaconStruct->VHTOperation.present = 1; + cdf_mem_copy(&pBeaconStruct->VHTOperation, &pBies->VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } + if (pBies->VHTExtBssLoad.present) { + pBeaconStruct->VHTExtBssLoad.present = 1; + cdf_mem_copy(&pBeaconStruct->VHTExtBssLoad, + &pBies->VHTExtBssLoad, + sizeof(tDot11fIEVHTExtBssLoad)); + } + if (pBies->OperatingMode.present) { + pBeaconStruct->OperatingMode.present = 1; + cdf_mem_copy(&pBeaconStruct->OperatingMode, + &pBies->OperatingMode, + sizeof(tDot11fIEOperatingMode)); + } +#endif + + if (pBies->MobilityDomain.present) { + pBeaconStruct->mdiePresent = 1; + cdf_mem_copy(pBeaconStruct->mdie, &pBies->MobilityDomain.MDID, + SIR_MDIE_SIZE); + } + + pBeaconStruct->Vendor1IEPresent = pBies->Vendor1IE.present; + pBeaconStruct->Vendor3IEPresent = pBies->Vendor3IE.present; + pBeaconStruct->vendor2_ie.present = pBies->vendor2_ie.present; + if (pBies->vendor2_ie.present) { + pBeaconStruct->vendor2_ie.type = pBies->vendor2_ie.type; + pBeaconStruct->vendor2_ie.sub_type = pBies->vendor2_ie.sub_type; + } + + if (pBies->vendor2_ie.VHTCaps.present) { + pBeaconStruct->vendor2_ie.VHTCaps.present = 1; + cdf_mem_copy(&pBeaconStruct->vendor2_ie.VHTCaps, + &pBies->vendor2_ie.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pBies->vendor2_ie.VHTOperation.present) { + pBeaconStruct->vendor2_ie.VHTOperation.present = 1; + cdf_mem_copy(&pBeaconStruct->vendor2_ie.VHTOperation, + &pBies->vendor2_ie.VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } + cdf_mem_free(pBies); + return eSIR_SUCCESS; +} /* End sir_parse_beacon_ie. */ + +tSirRetStatus +sir_convert_beacon_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + tpSirProbeRespBeacon pBeaconStruct) +{ + tDot11fBeacon *pBeacon; + uint32_t status, nPayload; + uint8_t *pPayload; + tpSirMacMgmtHdr pHdr; + uint8_t mappedRXCh; + uint8_t rfBand; + + pPayload = WMA_GET_RX_MPDU_DATA(pFrame); + nPayload = WMA_GET_RX_PAYLOAD_LEN(pFrame); + pHdr = WMA_GET_RX_MAC_HEADER(pFrame); + mappedRXCh = WMA_GET_RX_CH(pFrame); + rfBand = WMA_GET_RX_RFBAND(pFrame); + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pBeaconStruct, sizeof(tSirProbeRespBeacon), 0); + + pBeacon = cdf_mem_malloc(sizeof(tDot11fBeacon)); + if (NULL == pBeacon) { + lim_log(pMac, LOGE, FL("Failed to allocate memory\n")); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_set((uint8_t *) pBeacon, sizeof(tDot11fBeacon), 0); + + /* get the MAC address out of the BD, */ + cdf_mem_copy(pBeaconStruct->bssid, pHdr->sa, 6); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_beacon(pMac, pPayload, nPayload, pBeacon); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL("Failed to parse Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload); + ) + cdf_mem_free(pBeacon); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes):\n"), + status, nPayload); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload); + ) + } + /* & "transliterate" from a 'tDot11fBeacon' to a 'tSirProbeRespBeacon'... */ + /* Timestamp */ + cdf_mem_copy((uint8_t *) pBeaconStruct->timeStamp, + (uint8_t *) &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(lim_log + (pMac, LOGW, FL("Mandatory IE SSID not present!\n")); + ) + } else { + pBeaconStruct->ssidPresent = 1; + convert_ssid(pMac, &pBeaconStruct->ssId, &pBeacon->SSID); + } + + if (!pBeacon->SuppRates.present) { + PELOGW(lim_log + (pMac, LOGW, + FL("Mandatory IE Supported Rates not present!\n")); + ) + } else { + pBeaconStruct->suppRatesPresent = 1; + convert_supp_rates(pMac, &pBeaconStruct->supportedRates, + &pBeacon->SuppRates); + } + + if (pBeacon->ExtSuppRates.present) { + pBeaconStruct->extendedRatesPresent = 1; + convert_ext_supp_rates(pMac, &pBeaconStruct->extendedRates, + &pBeacon->ExtSuppRates); + } + + if (pBeacon->CFParams.present) { + pBeaconStruct->cfPresent = 1; + convert_cf_params(pMac, &pBeaconStruct->cfParamSet, + &pBeacon->CFParams); + } + + if (pBeacon->TIM.present) { + pBeaconStruct->timPresent = 1; + convert_tim(pMac, &pBeaconStruct->tim, &pBeacon->TIM); + } + + if (pBeacon->Country.present) { + pBeaconStruct->countryInfoPresent = 1; + convert_country(pMac, &pBeaconStruct->countryInfoParam, + &pBeacon->Country); + } + /* QOS Capabilities: */ + if (pBeacon->QOSCapsAp.present) { + pBeaconStruct->qosCapabilityPresent = 1; + convert_qos_caps(pMac, &pBeaconStruct->qosCapability, + &pBeacon->QOSCapsAp); + } + + if (pBeacon->EDCAParamSet.present) { + pBeaconStruct->edcaPresent = 1; + convert_edca_param(pMac, &pBeaconStruct->edcaParams, + &pBeacon->EDCAParamSet); + } + + if (pBeacon->ChanSwitchAnn.present) { + pBeaconStruct->channelSwitchPresent = 1; + cdf_mem_copy(&pBeaconStruct->channelSwitchIE, + &pBeacon->ChanSwitchAnn, + sizeof(pBeaconStruct->channelSwitchIE)); + } + + if (pBeacon->ext_chan_switch_ann.present) { + pBeaconStruct->ext_chan_switch_present = 1; + cdf_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; + cdf_mem_copy(&pBeaconStruct->sec_chan_offset, + &pBeacon->sec_chan_offset_ele, + sizeof(pBeaconStruct->sec_chan_offset)); + } + + if (pBeacon->TPCReport.present) { + pBeaconStruct->tpcReportPresent = 1; + cdf_mem_copy(&pBeaconStruct->tpcReport, &pBeacon->TPCReport, + sizeof(tDot11fIETPCReport)); + } + + if (pBeacon->PowerConstraints.present) { + pBeaconStruct->powerConstraintPresent = 1; + cdf_mem_copy(&pBeaconStruct->localPowerConstraint, + &pBeacon->PowerConstraints, + sizeof(tDot11fIEPowerConstraints)); + } + + if (pBeacon->Quiet.present) { + pBeaconStruct->quietIEPresent = 1; + cdf_mem_copy(&pBeaconStruct->quietIE, &pBeacon->Quiet, + sizeof(tDot11fIEQuiet)); + } + + if (pBeacon->HTCaps.present) { + cdf_mem_copy(&pBeaconStruct->HTCaps, &pBeacon->HTCaps, + sizeof(tDot11fIEHTCaps)); + } + + if (pBeacon->HTInfo.present) { + cdf_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 { + pBeaconStruct->channelNumber = mappedRXCh; + lim_log(pMac, LOG1, + FL("Channel info is not present in Beacon")); + } + + if (pBeacon->RSN.present) { + pBeaconStruct->rsnPresent = 1; + convert_rsn(pMac, &pBeaconStruct->rsn, &pBeacon->RSN); + } + + if (pBeacon->WPA.present) { + pBeaconStruct->wpaPresent = 1; + convert_wpa(pMac, &pBeaconStruct->wpa, &pBeacon->WPA); + } + + if (pBeacon->WMMParams.present) { + pBeaconStruct->wmeEdcaPresent = 1; + convert_wmm_params(pMac, &pBeaconStruct->edcaParams, + &pBeacon->WMMParams); + PELOG1(lim_log + (pMac, LOG1, + FL("WMM Parameter present in Beacon Frame!\n")); + __print_wmm_params(pMac, &pBeacon->WMMParams); + ) + } + + if (pBeacon->WMMInfoAp.present) { + pBeaconStruct->wmeInfoPresent = 1; + PELOG1(lim_log + (pMac, LOG1, FL("WMM Info present in Beacon Frame!\n")); + ) + } + + if (pBeacon->WMMCaps.present) { + pBeaconStruct->wsmCapablePresent = 1; + } + + if (pBeacon->ERPInfo.present) { + pBeaconStruct->erpPresent = 1; + convert_erp_info(pMac, &pBeaconStruct->erpIEInfo, + &pBeacon->ERPInfo); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pBeacon->MobilityDomain.present) { + /* MobilityDomain */ + pBeaconStruct->mdiePresent = 1; + cdf_mem_copy((uint8_t *) &(pBeaconStruct->mdie[0]), + (uint8_t *) &(pBeacon->MobilityDomain.MDID), + sizeof(uint16_t)); + 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; + cdf_mem_copy(&pBeaconStruct->eseTxPwr, + &pBeacon->ESETxmitPower, + sizeof(tDot11fIEESETxmitPower)); + } + if (pBeacon->QBSSLoad.present) { + cdf_mem_copy(&pBeaconStruct->QBSSLoad, + &pBeacon->QBSSLoad, sizeof(tDot11fIEQBSSLoad)); + } +#endif + +#ifdef WLAN_FEATURE_11AC + if (pBeacon->VHTCaps.present) { + cdf_mem_copy(&pBeaconStruct->VHTCaps, &pBeacon->VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pBeacon->VHTOperation.present) { + cdf_mem_copy(&pBeaconStruct->VHTOperation, + &pBeacon->VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } + if (pBeacon->VHTExtBssLoad.present) { + cdf_mem_copy(&pBeaconStruct->VHTExtBssLoad, + &pBeacon->VHTExtBssLoad, + sizeof(tDot11fIEVHTExtBssLoad)); + } + if (pBeacon->OperatingMode.present) { + cdf_mem_copy(&pBeaconStruct->OperatingMode, + &pBeacon->OperatingMode, + sizeof(tDot11fIEOperatingMode)); + } + if (pBeacon->WiderBWChanSwitchAnn.present) { + pBeaconStruct->WiderBWChanSwitchAnnPresent = 1; + cdf_mem_copy(&pBeaconStruct->WiderBWChanSwitchAnn, + &pBeacon->WiderBWChanSwitchAnn, + sizeof(tDot11fIEWiderBWChanSwitchAnn)); + } +#endif + + /* IBSS Peer Params */ + if (pBeacon->IBSSParams.present) { + pBeaconStruct->IBSSParams.present = 1; + cdf_mem_copy(&pBeaconStruct->IBSSParams, &pBeacon->IBSSParams, + sizeof(tDot11fIEIBSSParams)); + } + + pBeaconStruct->Vendor1IEPresent = pBeacon->Vendor1IE.present; + pBeaconStruct->Vendor3IEPresent = pBeacon->Vendor3IE.present; + + pBeaconStruct->vendor2_ie.present = pBeacon->vendor2_ie.present; + if (pBeacon->vendor2_ie.present) { + pBeaconStruct->vendor2_ie.type = pBeacon->vendor2_ie.type; + pBeaconStruct->vendor2_ie.sub_type = + pBeacon->vendor2_ie.sub_type; + } + if (pBeacon->vendor2_ie.present) { + PELOG1(lim_log(pMac, LOG1, + FL("Vendor Specific VHT caps present in Beacon Frame!")); + ) + } + if (pBeacon->vendor2_ie.VHTCaps.present) { + cdf_mem_copy(&pBeaconStruct->vendor2_ie.VHTCaps, + &pBeacon->vendor2_ie.VHTCaps, + sizeof(tDot11fIEVHTCaps)); + } + if (pBeacon->vendor2_ie.VHTOperation.present) { + cdf_mem_copy(&pBeaconStruct->vendor2_ie.VHTOperation, + &pBeacon->VHTOperation, + sizeof(tDot11fIEVHTOperation)); + } +#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 */ + + + cdf_mem_free(pBeacon); + return eSIR_SUCCESS; + +} /* End sir_convert_beacon_frame2_struct. */ + +tSirRetStatus +sir_convert_auth_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tpSirMacAuthFrameBody pAuth) +{ + static tDot11fAuthentication auth; + uint32_t status; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAuth, sizeof(tSirMacAuthFrameBody), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_authentication(pMac, pFrame, nFrame, &auth); + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, + FL + ("Failed to parse an Authentication frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, + FL + ("There were warnings while unpacking an Authentication frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (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; + cdf_mem_copy(pAuth->challengeText, auth.ChallengeText.text, + auth.ChallengeText.num_text); + } + + return eSIR_SUCCESS; + +} /* End sir_convert_auth_frame2_struct. */ + +tSirRetStatus +sir_convert_addts_req2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tSirAddtsReqInfo *pAddTs) +{ + tDot11fAddTSRequest addts = { {0}}; + tDot11fWMMAddTSRequest wmmaddts = { {0}}; + uint8_t j; + uint16_t i; + uint32_t status; + + if (SIR_MAC_QOS_ADD_TS_REQ != *(pFrame + 1)) { + lim_log(pMac, LOGE, FL("sir_convert_addts_req2_struct invoked " + "with an Action of %d; this is not " + "supported & is probably an error."), + *(pFrame + 1)); + return eSIR_FAILURE; + } + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAddTs, sizeof(tSirAddtsReqInfo), 0); + + /* delegate to the framesc-generated code, */ + switch (*pFrame) { + case SIR_MAC_ACTION_QOS_MGMT: + status = dot11f_unpack_add_ts_request(pMac, pFrame, nFrame, &addts); + break; + case SIR_MAC_ACTION_WME: + status = + dot11f_unpack_wmm_add_ts_request(pMac, pFrame, nFrame, + &wmmaddts); + break; + default: + lim_log(pMac, LOGE, FL("sir_convert_addts_req2_struct invoked " + "with a Category of %d; this is not" + " supported & is probably an error."), + *pFrame); + return eSIR_FAILURE; + } + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, FL("Failed to parse an Add TS Request f" + "rame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, FL("There were warnings while unpackin" + "g an Add TS Request frame (0x%08x," + "%d bytes):\n"), status, nFrame); + PELOG2(sir_dump_buf + (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) { + convert_tspec(pMac, &pAddTs->tspec, &addts.TSPEC); + } else { + lim_log(pMac, LOGE, + FL + ("Mandatory TSPEC element missing in Add TS Request.\n")); + return eSIR_FAILURE; + } + + if (addts.num_TCLAS) { + pAddTs->numTclas = (uint8_t) addts.num_TCLAS; + + for (i = 0U; i < addts.num_TCLAS; ++i) { + if (eSIR_SUCCESS != + convert_tclas(pMac, &(pAddTs->tclasInfo[i]), + &(addts.TCLAS[i]))) { + lim_log(pMac, LOGE, + FL + ("Failed to convert a TCLAS IE.\n")); + return eSIR_FAILURE; + } + } + } + + if (addts.TCLASSPROC.present) { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.TCLASSPROC.processing; + } + + if (addts.WMMTSPEC.present) { + pAddTs->wsmTspecPresent = 1; + convert_wmmtspec(pMac, &pAddTs->tspec, &addts.WMMTSPEC); + } + + if (addts.num_WMMTCLAS) { + j = (uint8_t) (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 != + convert_wmmtclas(pMac, + &(pAddTs->tclasInfo[i]), + &(addts.WMMTCLAS[i]))) { + lim_log(pMac, LOGE, + FL + ("Failed to convert a TCLAS IE.\n")); + return eSIR_FAILURE; + } + } + } + + if (addts.WMMTCLASPROC.present) { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.WMMTCLASPROC.processing; + } + + if (1 < pAddTs->numTclas && (!pAddTs->tclasProcPresent)) { + lim_log(pMac, LOGE, + FL("%d TCLAS IE but not TCLASPROC IE.\n"), + pAddTs->numTclas); + return eSIR_FAILURE; + } + } else { + pAddTs->dialogToken = wmmaddts.DialogToken.token; + + if (wmmaddts.WMMTSPEC.present) { + pAddTs->wmeTspecPresent = 1; + convert_wmmtspec(pMac, &pAddTs->tspec, + &wmmaddts.WMMTSPEC); + } else { + lim_log(pMac, LOGE, + FL("Mandatory WME TSPEC element missing!\n")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; + +} /* End sir_convert_addts_req2_struct. */ + +tSirRetStatus +sir_convert_addts_rsp2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tSirAddtsRspInfo *pAddTs) +{ + tDot11fAddTSResponse addts = { {0}}; + tDot11fWMMAddTSResponse wmmaddts = { {0}}; + uint8_t j; + uint16_t i; + uint32_t status; + + if (SIR_MAC_QOS_ADD_TS_RSP != *(pFrame + 1)) { + lim_log(pMac, LOGE, FL("sir_convert_addts_rsp2_struct invoked " + "with an Action of %d; this is not " + "supported & is probably an error."), + *(pFrame + 1)); + return eSIR_FAILURE; + } + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pAddTs, sizeof(tSirAddtsRspInfo), 0); + cdf_mem_set((uint8_t *) &addts, sizeof(tDot11fAddTSResponse), 0); + cdf_mem_set((uint8_t *) &wmmaddts, sizeof(tDot11fWMMAddTSResponse), 0); + + /* delegate to the framesc-generated code, */ + switch (*pFrame) { + case SIR_MAC_ACTION_QOS_MGMT: + status = + dot11f_unpack_add_ts_response(pMac, pFrame, nFrame, &addts); + break; + case SIR_MAC_ACTION_WME: + status = + dot11f_unpack_wmm_add_ts_response(pMac, pFrame, nFrame, + &wmmaddts); + break; + default: + lim_log(pMac, LOGE, FL("sir_convert_addts_rsp2_struct invoked " + "with a Category of %d; this is not" + " supported & is probably an error."), + *pFrame); + return eSIR_FAILURE; + } + + if (DOT11F_FAILED(status)) { + lim_log(pMac, LOGE, FL("Failed to parse an Add TS Response f" + "rame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(pMac, LOGW, FL("There were warnings while unpackin" + "g an Add TS Response frame (0x%08x," + "%d bytes):\n"), status, nFrame); + PELOG2(sir_dump_buf + (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) { + convert_ts_delay(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) { + lim_log(pMac, LOGW, FL("Missing TSDelay IE.\n")); + } + + if (addts.TSPEC.present) { + convert_tspec(pMac, &pAddTs->tspec, &addts.TSPEC); + } else { + lim_log(pMac, LOGE, + FL + ("Mandatory TSPEC element missing in Add TS Response.\n")); + return eSIR_FAILURE; + } + + if (addts.num_TCLAS) { + pAddTs->numTclas = (uint8_t) addts.num_TCLAS; + + for (i = 0U; i < addts.num_TCLAS; ++i) { + if (eSIR_SUCCESS != + convert_tclas(pMac, &(pAddTs->tclasInfo[i]), + &(addts.TCLAS[i]))) { + lim_log(pMac, LOGE, + FL + ("Failed to convert a TCLAS IE.\n")); + 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; + cdf_mem_copy(&pAddTs->tsmIE.tsid, + &addts.ESETrafStrmMet.tsid, + sizeof(tSirMacESETSMIE)); + } +#endif + if (addts.Schedule.present) { + pAddTs->schedulePresent = 1; + convert_schedule(pMac, &pAddTs->schedule, + &addts.Schedule); + } + + if (addts.WMMSchedule.present) { + pAddTs->schedulePresent = 1; + convert_wmm_schedule(pMac, &pAddTs->schedule, + &addts.WMMSchedule); + } + + if (addts.WMMTSPEC.present) { + pAddTs->wsmTspecPresent = 1; + convert_wmmtspec(pMac, &pAddTs->tspec, &addts.WMMTSPEC); + } + + if (addts.num_WMMTCLAS) { + j = (uint8_t) (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 != + convert_wmmtclas(pMac, + &(pAddTs->tclasInfo[i]), + &(addts.WMMTCLAS[i]))) { + lim_log(pMac, LOGE, + FL + ("Failed to convert a TCLAS IE.\n")); + return eSIR_FAILURE; + } + } + } + + if (addts.WMMTCLASPROC.present) { + pAddTs->tclasProcPresent = 1; + pAddTs->tclasProc = addts.WMMTCLASPROC.processing; + } + + if (1 < pAddTs->numTclas && (!pAddTs->tclasProcPresent)) { + lim_log(pMac, LOGE, + FL("%d TCLAS IE but not TCLASPROC IE.\n"), + pAddTs->numTclas); + return eSIR_FAILURE; + } + } else { + pAddTs->dialogToken = wmmaddts.DialogToken.token; + pAddTs->status = + (tSirMacStatusCodes) wmmaddts.StatusCode.statusCode; + + if (wmmaddts.WMMTSPEC.present) { + pAddTs->wmeTspecPresent = 1; + convert_wmmtspec(pMac, &pAddTs->tspec, + &wmmaddts.WMMTSPEC); + } else { + lim_log(pMac, LOGE, + FL("Mandatory WME TSPEC element missing!\n")); + return eSIR_FAILURE; + } + +#ifdef FEATURE_WLAN_ESE + if (wmmaddts.ESETrafStrmMet.present) { + pAddTs->tsmPresent = 1; + cdf_mem_copy(&pAddTs->tsmIE.tsid, + &wmmaddts.ESETrafStrmMet.tsid, + sizeof(tSirMacESETSMIE)); + } +#endif + + } + + return eSIR_SUCCESS; + +} /* End sir_convert_addts_rsp2_struct. */ + +tSirRetStatus +sir_convert_delts_req2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, tSirDeltsReqInfo *pDelTs) +{ + tDot11fDelTS delts = { {0}}; + tDot11fWMMDelTS wmmdelts = { {0}}; + uint32_t status; + + if (SIR_MAC_QOS_DEL_TS_REQ != *(pFrame + 1)) { + lim_log(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, */ + cdf_mem_set((uint8_t *) pDelTs, sizeof(tSirDeltsReqInfo), 0); + + /* delegate to the framesc-generated code, */ + switch (*pFrame) { + case SIR_MAC_ACTION_QOS_MGMT: + status = dot11f_unpack_del_ts(pMac, pFrame, nFrame, &delts); + break; + case SIR_MAC_ACTION_WME: + status = dot11f_unpack_wmm_del_ts(pMac, pFrame, nFrame, &wmmdelts); + break; + default: + lim_log(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)) { + lim_log(pMac, LOGE, FL("Failed to parse an Del TS Request f" + "rame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + dot11f_log(pMac, LOGW, FL("There were warnings while unpackin" + "g an Del TS Request frame (0x%08x," + "%d bytes):\n"), status, nFrame); + PELOG2(sir_dump_buf + (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 = + (uint16_t) delts.TSInfo.traffic_type; + pDelTs->tsinfo.traffic.tsid = (uint16_t) delts.TSInfo.tsid; + pDelTs->tsinfo.traffic.direction = + (uint16_t) delts.TSInfo.direction; + pDelTs->tsinfo.traffic.accessPolicy = + (uint16_t) delts.TSInfo.access_policy; + pDelTs->tsinfo.traffic.aggregation = + (uint16_t) delts.TSInfo.aggregation; + pDelTs->tsinfo.traffic.psb = (uint16_t) delts.TSInfo.psb; + pDelTs->tsinfo.traffic.userPrio = + (uint16_t) delts.TSInfo.user_priority; + pDelTs->tsinfo.traffic.ackPolicy = + (uint16_t) delts.TSInfo.tsinfo_ack_pol; + + pDelTs->tsinfo.schedule.schedule = + (uint8_t) delts.TSInfo.schedule; + } else { + if (wmmdelts.WMMTSPEC.present) { + pDelTs->wmeTspecPresent = 1; + convert_wmmtspec(pMac, &pDelTs->tspec, + &wmmdelts.WMMTSPEC); + } else { + dot11f_log(pMac, LOGE, + FL("Mandatory WME TSPEC element missing!\n")); + return eSIR_FAILURE; + } + } + + return eSIR_SUCCESS; + +} /* End sir_convert_delts_req2_struct. */ + +tSirRetStatus +sir_convert_qos_map_configure_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + uint32_t nFrame, + tSirQosMapSet *pQosMapSet) +{ + tDot11fQosMapConfigure mapConfigure; + uint32_t status; + status = + dot11f_unpack_qos_map_configure(pMac, pFrame, nFrame, &mapConfigure); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL + ("Failed to parse Qos Map Configure frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + dot11f_log(pMac, LOGW, + FL + ("There were warnings while unpacking Qos Map Configure frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + } + pQosMapSet->present = mapConfigure.QosMapSet.present; + convert_qos_mapset_frame(pMac->hHdd, pQosMapSet, &mapConfigure.QosMapSet); + lim_log_qos_map_set(pMac, pQosMapSet); + return eSIR_SUCCESS; +} + +#ifdef ANI_SUPPORT_11H +tSirRetStatus +sir_convert_tpc_req_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + tpSirMacTpcReqActionFrame pTpcReqFrame, + uint32_t nFrame) +{ + tDot11fTPCRequest req; + uint32_t status; + cdf_mem_set((uint8_t *) pTpcReqFrame, sizeof(tSirMacTpcReqActionFrame), + 0); + status = dot11f_unpack_tpc_request(pMac, pFrame, nFrame, &req); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL + ("Failed to parse a TPC Request frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + dot11f_log(pMac, LOGW, + FL + ("There were warnings while unpacking a TPC Request frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + } + /* & "transliterate" from a 'tDot11fTPCRequest' to a */ + /* 'tSirMacTpcReqActionFrame'... */ + pTpcReqFrame->actionHeader.category = req.Category.category; + pTpcReqFrame->actionHeader.actionID = req.Action.action; + pTpcReqFrame->actionHeader.dialogToken = req.DialogToken.token; + if (req.TPCRequest.present) { + pTpcReqFrame->type = DOT11F_EID_TPCREQUEST; + pTpcReqFrame->length = 0; + } else { + dot11f_log(pMac, LOGW, FL("!!!Rcv TPC Req of inalid type!\n")); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; +} /* End sir_convert_tpc_req_frame2_struct. */ +tSirRetStatus +sir_convert_meas_req_frame2_struct(tpAniSirGlobal pMac, + uint8_t *pFrame, + tpSirMacMeasReqActionFrame pMeasReqFrame, + uint32_t nFrame) +{ + tDot11fMeasurementRequest mr; + uint32_t status; + + /* Zero-init our [out] parameter, */ + cdf_mem_set((uint8_t *) pMeasReqFrame, + sizeof(tpSirMacMeasReqActionFrame), 0); + + /* delegate to the framesc-generated code, */ + status = dot11f_unpack_measurement_request(pMac, pFrame, nFrame, &mr); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOGE, + FL + ("Failed to parse a Measurement Request frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + dot11f_log(pMac, LOGW, + FL + ("There were warnings while unpacking a Measurement Request frame (0x%08x, %d bytes):\n"), + status, nFrame); + PELOG2(sir_dump_buf + (pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame); + ) + } + /* & "transliterate" from a 'tDot11fMeasurementRequest' to a */ + /* 'tpSirMacMeasReqActionFrame'... */ + pMeasReqFrame->actionHeader.category = mr.Category.category; + pMeasReqFrame->actionHeader.actionID = mr.Action.action; + pMeasReqFrame->actionHeader.dialogToken = mr.DialogToken.token; + + if (0 == mr.num_MeasurementRequest) { + dot11f_log(pMac, LOGE, + FL + ("Missing mandatory IE in Measurement Request Frame.\n")); + return eSIR_FAILURE; + } else if (1 < mr.num_MeasurementRequest) { + lim_log(pMac, LOGW, + FL("Warning: dropping extra Measurement Request IEs!")); + } + + pMeasReqFrame->measReqIE.type = DOT11F_EID_MEASUREMENTREQUEST; + pMeasReqFrame->measReqIE.length = DOT11F_IE_MEASUREMENTREQUEST_MIN_LEN; + pMeasReqFrame->measReqIE.measToken = + mr.MeasurementRequest[0].measurement_token; + pMeasReqFrame->measReqIE.measReqMode = + (mr.MeasurementRequest[0].reserved << 3) | (mr. + MeasurementRequest[0]. + enable << 2) | (mr. + MeasurementRequest + [0]. + request + << 1) | + (mr.MeasurementRequest[0].report /*<< 0 */ ); + pMeasReqFrame->measReqIE.measType = + mr.MeasurementRequest[0].measurement_type; + + pMeasReqFrame->measReqIE.measReqField.channelNumber = + mr.MeasurementRequest[0].channel_no; + + cdf_mem_copy(pMeasReqFrame->measReqIE.measReqField.measStartTime, + mr.MeasurementRequest[0].meas_start_time, 8); + + pMeasReqFrame->measReqIE.measReqField.measDuration = + mr.MeasurementRequest[0].meas_duration; + + return eSIR_SUCCESS; + +} /* End sir_convert_meas_req_frame2_struct. */ +#endif + +void populate_dot11f_tspec(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 populate_dot11f_tspec. */ + +void populate_dot11f_wmmtspec(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 populate_dot11f_wmmtspec. */ + +#if defined(FEATURE_WLAN_ESE) +/* Fill the ESE version currently supported */ +void populate_dot11f_ese_version(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 populate_dot11f_ese_rad_mgmt_cap(tDot11fIEESERadMgmtCap *pESERadMgmtCap) +{ + pESERadMgmtCap->present = 1; + pESERadMgmtCap->mgmt_state = RM_STATE_NORMAL; + pESERadMgmtCap->mbssid_mask = 0; + pESERadMgmtCap->reserved = 0; +} + +tSirRetStatus populate_dot11f_ese_cckm_opaque(tpAniSirGlobal pMac, + tpSirCCKMie pCCKMie, + tDot11fIEESECckmOpaque *pDot11f) +{ + int idx; + if (pCCKMie->length) { + if (0 <= (idx = find_ie_location(pMac, (tpSirRSNie) pCCKMie, + DOT11F_EID_ESECCKMOPAQUE))) { + pDot11f->present = 1; + /* Dont include OUI */ + pDot11f->num_data = pCCKMie->cckmIEdata[idx + 1] - 4; + cdf_mem_copy(pDot11f->data, pCCKMie->cckmIEdata + idx + 2 + 4, /* EID,len,OUI */ + pCCKMie->cckmIEdata[idx + 1] - 4); /* Skip OUI */ + } + } + return eSIR_SUCCESS; +} /* End populate_dot11f_ese_cckm_opaque. */ + +void populate_dot11_tsrsie(tpAniSirGlobal pMac, + tSirMacESETSRSIE *pOld, + tDot11fIEESETrafStrmRateSet *pDot11f, + uint8_t rate_length) +{ + pDot11f->tsid = pOld->tsid; + cdf_mem_copy(pDot11f->tsrates, pOld->rates, rate_length); + pDot11f->num_tsrates = rate_length; + pDot11f->present = 1; +} +#endif + +tSirRetStatus +populate_dot11f_tclas(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: + cdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.source, + (uint8_t *) &pOld->tclasParams.eth.srcAddr, 6); + cdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.dest, + (uint8_t *) &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) { + cdf_mem_copy(pDot11f->info.IpParams.params.IpV4Params. + source, pOld->tclasParams.ipv4.srcIpAddr, + 4); + cdf_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 { + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.source, + (uint8_t *) pOld->tclasParams.ipv6. + srcIpAddr, 16); + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.dest, + (uint8_t *) 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; + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.flow_label, + (uint8_t *) pOld->tclasParams.ipv6. + flowLabel, 3); + } + break; + case SIR_MAC_TCLASTYPE_8021DQ: + pDot11f->info.Params8021dq.tag_type = + pOld->tclasParams.t8021dq.tag; + break; + default: + lim_log(pMac, LOGE, + FL("Bad TCLAS type %d in populate_dot11f_tclas.\n"), + pDot11f->classifier_type); + return eSIR_FAILURE; + } + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} /* End populate_dot11f_tclas. */ + +tSirRetStatus +populate_dot11f_wmmtclas(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: + cdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.source, + (uint8_t *) &pOld->tclasParams.eth.srcAddr, 6); + cdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.dest, + (uint8_t *) &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) { + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV4Params.source, + (uint8_t *) pOld->tclasParams.ipv4. + srcIpAddr, 4); + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV4Params.dest, + (uint8_t *) 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 { + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.source, + (uint8_t *) pOld->tclasParams.ipv6. + srcIpAddr, 16); + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.dest, + (uint8_t *) 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; + cdf_mem_copy((uint8_t *) &pDot11f->info.IpParams. + params.IpV6Params.flow_label, + (uint8_t *) pOld->tclasParams.ipv6. + flowLabel, 3); + } + break; + case SIR_MAC_TCLASTYPE_8021DQ: + pDot11f->info.Params8021dq.tag_type = + pOld->tclasParams.t8021dq.tag; + break; + default: + lim_log(pMac, LOGE, + FL("Bad TCLAS type %d in populate_dot11f_tclas.\n"), + pDot11f->classifier_type); + return eSIR_FAILURE; + } + + pDot11f->present = 1; + + return eSIR_SUCCESS; + +} /* End populate_dot11f_wmmtclas. */ + +tSirRetStatus populate_dot11f_wsc(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + + uint32_t wpsState; + + pDot11f->Version.present = 1; + pDot11f->Version.major = 0x01; + pDot11f->Version.minor = 0x00; + + if (wlan_cfg_get_int(pMac, (uint16_t) WNI_CFG_WPS_STATE, &wpsState) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, "Failed to cfg get id %d\n", + WNI_CFG_WPS_STATE); + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (uint8_t) 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 populate_dot11f_wsc_registrar_info(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + const struct sLimWscIeInfo *const pWscIeInfo = &(pMac->lim.wscIeInfo); + uint32_t devicepasswdId; + + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked; + + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar; + + if (wlan_cfg_get_int + (pMac, (uint16_t) WNI_CFG_WPS_DEVICE_PASSWORD_ID, + &devicepasswdId) != eSIR_SUCCESS) + lim_log(pMac, LOGP, "Failed to cfg get id %d\n", + WNI_CFG_WPS_DEVICE_PASSWORD_ID); + + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = (uint16_t) 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 de_populate_dot11f_wsc_registrar_info(tpAniSirGlobal pMac, + tDot11fIEWscBeacon *pDot11f) +{ + pDot11f->APSetupLocked.present = 0; + pDot11f->SelectedRegistrar.present = 0; + pDot11f->DevicePasswordID.present = 0; + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + return eSIR_SUCCESS; +} + +tSirRetStatus populate_dot11f_probe_res_wpsi_es(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 = + (uint8_t) ((pSirWPSProbeRspIE->Version & 0xF0) >> 4); + pDot11f->Version.minor = + (uint8_t) (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 = (uint8_t) 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; + cdf_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; + cdf_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; + cdf_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; + cdf_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; + cdf_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; + cdf_mem_copy(pDot11f->PrimaryDeviceType.oui, + pSirWPSProbeRspIE->PrimaryDeviceOUI, + sizeof(pSirWPSProbeRspIE->PrimaryDeviceOUI)); + pDot11f->PrimaryDeviceType.primary_category = + (uint16_t) pSirWPSProbeRspIE->PrimaryDeviceCategory; + pDot11f->PrimaryDeviceType.sub_category = + (uint16_t) 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; + cdf_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 populate_dot11f_assoc_res_wpsi_es(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 = + (uint8_t) ((pSirWPSProbeRspIE->Version & 0xF0) >> 4); + pDot11f->Version.minor = + (uint8_t) (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 populate_dot11f_beacon_wpsi_es(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 = + (uint8_t) ((pSirWPSBeaconIE->Version & 0xF0) >> 4); + pDot11f->Version.minor = + (uint8_t) (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 = (uint8_t) 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; + cdf_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 populate_dot11f_wsc_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes *pDot11f) +{ + uint32_t cfgMethods; + uint32_t cfgStrLen; + uint32_t val; + uint32_t wpsVersion, wpsState; + + if (wlan_cfg_get_int(pMac, (uint16_t) WNI_CFG_WPS_VERSION, &wpsVersion) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, "Failed to cfg get id %d\n", + WNI_CFG_WPS_VERSION); + + pDot11f->Version.present = 1; + pDot11f->Version.major = (uint8_t) ((wpsVersion & 0xF0) >> 4); + pDot11f->Version.minor = (uint8_t) (wpsVersion & 0x0F); + + if (wlan_cfg_get_int(pMac, (uint16_t) WNI_CFG_WPS_STATE, &wpsState) != + eSIR_SUCCESS) + lim_log(pMac, LOGP, "Failed to cfg get id %d\n", + WNI_CFG_WPS_STATE); + + pDot11f->WPSState.present = 1; + pDot11f->WPSState.state = (uint8_t) 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_cfg_get_str to get it. */ + pDot11f->UUID_E.present = 1; + cfgStrLen = WNI_CFG_WPS_UUID_LEN; + if (wlan_cfg_get_str(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_cfg_get_str(pMac, + WNI_CFG_MANUFACTURER_NAME, + pDot11f->Manufacturer.name, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->Manufacturer.num_name = 0; + } else { + pDot11f->Manufacturer.num_name = + (uint8_t) (cfgStrLen & 0x000000FF); + } + + pDot11f->ModelName.present = 1; + cfgStrLen = WNI_CFG_MODEL_NAME_LEN; + if (wlan_cfg_get_str(pMac, + WNI_CFG_MODEL_NAME, + pDot11f->ModelName.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->ModelName.num_text = 0; + } else { + pDot11f->ModelName.num_text = + (uint8_t) (cfgStrLen & 0x000000FF); + } + + pDot11f->ModelNumber.present = 1; + cfgStrLen = WNI_CFG_MODEL_NUMBER_LEN; + if (wlan_cfg_get_str(pMac, + WNI_CFG_MODEL_NUMBER, + pDot11f->ModelNumber.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->ModelNumber.num_text = 0; + } else { + pDot11f->ModelNumber.num_text = + (uint8_t) (cfgStrLen & 0x000000FF); + } + + pDot11f->SerialNumber.present = 1; + cfgStrLen = WNI_CFG_MANUFACTURER_PRODUCT_VERSION_LEN; + if (wlan_cfg_get_str(pMac, + WNI_CFG_MANUFACTURER_PRODUCT_VERSION, + pDot11f->SerialNumber.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->SerialNumber.num_text = 0; + } else { + pDot11f->SerialNumber.num_text = + (uint8_t) (cfgStrLen & 0x000000FF); + } + + pDot11f->PrimaryDeviceType.present = 1; + + if (wlan_cfg_get_int(pMac, WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("cfg get prim device category failed\n")); + } else + pDot11f->PrimaryDeviceType.primary_category = (uint16_t) val; + + if (wlan_cfg_get_int(pMac, WNI_CFG_WPS_PIMARY_DEVICE_OUI, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, FL("cfg get prim device OUI failed\n")); + } else { + *(pDot11f->PrimaryDeviceType.oui) = + (uint8_t) ((val >> 24) & 0xff); + *(pDot11f->PrimaryDeviceType.oui + 1) = + (uint8_t) ((val >> 16) & 0xff); + *(pDot11f->PrimaryDeviceType.oui + 2) = + (uint8_t) ((val >> 8) & 0xff); + *(pDot11f->PrimaryDeviceType.oui + 3) = + (uint8_t) ((val & 0xff)); + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_WPS_DEVICE_SUB_CATEGORY, &val) != + eSIR_SUCCESS) { + lim_log(pMac, LOGP, + FL("cfg get prim device sub category failed\n")); + } else + pDot11f->PrimaryDeviceType.sub_category = (uint16_t) val; + + pDot11f->DeviceName.present = 1; + cfgStrLen = WNI_CFG_MANUFACTURER_PRODUCT_NAME_LEN; + if (wlan_cfg_get_str(pMac, + WNI_CFG_MANUFACTURER_PRODUCT_NAME, + pDot11f->DeviceName.text, + &cfgStrLen) != eSIR_SUCCESS) { + pDot11f->DeviceName.num_text = 0; + } else { + pDot11f->DeviceName.num_text = + (uint8_t) (cfgStrLen & 0x000000FF); + } + + if (wlan_cfg_get_int(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 = + (uint16_t) (cfgMethods & 0x0000FFFF); + } + + pDot11f->RFBands.present = 0; + + pDot11f->present = 1; + return eSIR_SUCCESS; +} + +tSirRetStatus populate_dot11f_wsc_registrar_info_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes * + pDot11f) +{ + const struct sLimWscIeInfo *const pWscIeInfo = &(pMac->lim.wscIeInfo); + uint32_t devicepasswdId; + + pDot11f->APSetupLocked.present = 1; + pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked; + + pDot11f->SelectedRegistrar.present = 1; + pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar; + + if (wlan_cfg_get_int + (pMac, (uint16_t) WNI_CFG_WPS_DEVICE_PASSWORD_ID, + &devicepasswdId) != eSIR_SUCCESS) + lim_log(pMac, LOGP, "Failed to cfg get id %d\n", + WNI_CFG_WPS_DEVICE_PASSWORD_ID); + + pDot11f->DevicePasswordID.present = 1; + pDot11f->DevicePasswordID.id = (uint16_t) 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 de_populate_dot11f_wsc_registrar_info_in_probe_res(tpAniSirGlobal pMac, + tDot11fIEWscProbeRes * + pDot11f) +{ + pDot11f->APSetupLocked.present = 0; + pDot11f->SelectedRegistrar.present = 0; + pDot11f->DevicePasswordID.present = 0; + pDot11f->SelectedRegistrarConfigMethods.present = 0; + + return eSIR_SUCCESS; +} + +tSirRetStatus populate_dot11f_assoc_res_wsc_ie(tpAniSirGlobal pMac, + tDot11fIEWscAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq) +{ + tDot11fIEWscAssocReq parsedWscAssocReq = { 0, }; + uint8_t *wscIe; + + wscIe = + limGetWscIEPtr(pMac, pRcvdAssocReq->addIE.addIEdata, + pRcvdAssocReq->addIE.length); + if (wscIe != NULL) { + /* retreive WSC IE from given AssocReq */ + dot11f_unpack_ie_wsc_assoc_req(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 populate_dot11_assoc_res_p2p_ie(tpAniSirGlobal pMac, + tDot11fIEP2PAssocRes *pDot11f, + tpSirAssocReq pRcvdAssocReq) +{ + uint8_t *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 populate_dot11f_wfatpc(tpAniSirGlobal pMac, + tDot11fIEWFATPC *pDot11f, uint8_t txPower, + uint8_t linkMargin) +{ + pDot11f->txPower = txPower; + pDot11f->linkMargin = linkMargin; + pDot11f->present = 1; + + return eSIR_SUCCESS; +} + +tSirRetStatus populate_dot11f_beacon_report(tpAniSirGlobal pMac, + tDot11fIEMeasurementReport *pDot11f, + tSirMacBeaconReport *pBeaconReport) +{ + + pDot11f->report.Beacon.regClass = pBeaconReport->regClass; + pDot11f->report.Beacon.channel = pBeaconReport->channel; + cdf_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; + cdf_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; + cdf_mem_copy(pDot11f->report.Beacon.BeaconReportFrmBody. + reportedFields, pBeaconReport->Ies, + pBeaconReport->numIes); + pDot11f->report.Beacon.BeaconReportFrmBody.num_reportedFields = + pBeaconReport->numIes; + } + + return eSIR_SUCCESS; + +} + +tSirRetStatus populate_dot11f_rrm_ie(tpAniSirGlobal pMac, + tDot11fIERRMEnabledCap *pDot11f, + tpPESession psessionEntry) +{ + tpRRMCaps pRrmCaps; + + pRrmCaps = rrm_get_capabilities(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->reserved = pRrmCaps->reserved; + + pDot11f->present = 1; + return eSIR_SUCCESS; +} +#endif + +#if defined WLAN_FEATURE_VOWIFI_11R +void populate_mdie(tpAniSirGlobal pMac, + tDot11fIEMobilityDomain *pDot11f, + uint8_t mdie[SIR_MDIE_SIZE]) +{ + pDot11f->present = 1; + pDot11f->MDID = (uint16_t) ((mdie[1] << 8) | (mdie[0])); + + /* Plugfest fix */ + pDot11f->overDSCap = (mdie[2] & 0x01); + pDot11f->resourceReqCap = ((mdie[2] >> 1) & 0x01); + +} + +void populate_ft_info(tpAniSirGlobal pMac, tDot11fIEFTInfo *pDot11f) +{ + pDot11f->present = 1; + pDot11f->IECount = 0; /* TODO: put valid data during reassoc. */ + /* All other info is zero. */ + +} +#endif + +void populate_dot11f_assoc_rsp_rates(tpAniSirGlobal pMac, + tDot11fIESuppRates *pSupp, + tDot11fIEExtSuppRates *pExt, + uint16_t *_11bRates, uint16_t *_11aRates) +{ + uint8_t num_supp = 0, num_ext = 0; + uint8_t i, j; + + for (i = 0; (i < SIR_NUM_11B_RATES && _11bRates[i]); i++, num_supp++) { + pSupp->rates[num_supp] = (uint8_t) _11bRates[i]; + } + for (j = 0; (j < SIR_NUM_11A_RATES && _11aRates[j]); j++) { + if (num_supp < 8) + pSupp->rates[num_supp++] = (uint8_t) _11aRates[j]; + else + pExt->rates[num_ext++] = (uint8_t) _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 populate_dot11f_timeout_interval(tpAniSirGlobal pMac, + tDot11fIETimeoutInterval *pDot11f, + uint8_t type, uint32_t value) +{ + pDot11f->present = 1; + pDot11f->timeoutType = type; + pDot11f->timeoutValue = value; +} + +/** + * populate_dot11f_timing_advert_frame() - Populate the TA mgmt frame fields + * @pMac: the MAC context + * @frame: pointer to the TA frame + * + * Return: The SIR status. + */ +tSirRetStatus populate_dot11f_timing_advert_frame(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_cfg_get_int(mac_ctx, WNI_CFG_PRIVACY_ENABLED, &val); + if (val) + frame->Capabilities.privacy = 1; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_SHORT_PREAMBLE, &val); + if (val) + frame->Capabilities.shortPreamble = 1; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_11H_ENABLED, &val); + if (val) + frame->Capabilities.spectrumMgt = 1; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_QOS_ENABLED, &val); + if (val) + frame->Capabilities.qos = 1; + + wlan_cfg_get_int(mac_ctx, WNI_CFG_APSD_ENABLED, &val); + if (val) + frame->Capabilities.apsd = 1; + + wlan_cfg_get_int(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); + cdf_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); + cdf_mem_copy((uint8_t *)&frame->Country.triplets, temp, len); + frame->Country.present = 1; + + /* PowerConstraints */ + wlan_cfg_get_int(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; +} + +/* parser_api.c ends here. */ diff --git a/core/mac/src/sys/legacy/src/utils/src/utils_api.c b/core/mac/src/sys/legacy/src/utils/src/utils_api.c new file mode 100644 index 000000000000..524bbd217fd6 --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/utils_api.c @@ -0,0 +1,91 @@ +/* + * 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: utils_api.cc */ +/* */ +/* Description: Implemention of a few utility routines. */ +/* */ +/* Author: Neelay Das */ +/* */ +/* // */ +/* Change gHistory: */ +/* 12/15/2003 - NDA - Initial version. */ +/* */ +/* =================================================================== */ + +#include "utils_api.h" + +/* ------------------------------------------------------------------- */ +/** + * sir_dump_buf() + * + * FUNCTION: + * This function is called to dump a buffer with a certain level + * + * LOGIC: + * + * ASSUMPTIONS: + * None. + * + * NOTE: + * + * @param pBuf: buffer pointer + * @return None. + */ +void +sir_dump_buf(tpAniSirGlobal pMac, uint8_t modId, uint32_t level, uint8_t *buf, + uint32_t size) +{ + uint32_t i; + + if (level > pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(modId)]) + return; + + log_dbg(pMac, modId, level, FL("Dumping %d bytes in host order\n"), + size); + + for (i = 0; (i + 7) < size; i += 8) { + log_dbg(pMac, modId, level, + "%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 < size; i++) { + log_dbg(pMac, modId, level, "%02x ", buf[i]); + + if ((i + 1) == size) + log_dbg(pMac, modId, level, "\n"); + } + +} /*** end sir_dump_buf() ***/ diff --git a/core/mac/src/sys/legacy/src/utils/src/utils_parser.c b/core/mac/src/sys/legacy/src/utils/src/utils_parser.c new file mode 100644 index 000000000000..9b91902ae7de --- /dev/null +++ b/core/mac/src/sys/legacy/src/utils/src/utils_parser.c @@ -0,0 +1,827 @@ +/* + * 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 utils_parser.cc contains the code for parsing + * 802.11 messages. + * Author: Pierre Vandwalle + * Date: 03/18/02 + * History:- + * Date Modified by Modification Information + * -------------------------------------------------------------------- + * + */ + +#include "ani_global.h" +#include "utils_parser.h" +#include "lim_ser_des_utils.h" + +void convert_ssid(tpAniSirGlobal pMac, tSirMacSSid *pOld, tDot11fIESSID *pNew) +{ + pOld->length = pNew->num_ssid; + cdf_mem_copy(pOld->ssId, pNew->ssid, pNew->num_ssid); +} + +void convert_supp_rates(tpAniSirGlobal pMac, + tSirMacRateSet *pOld, tDot11fIESuppRates *pNew) +{ + pOld->numRates = pNew->num_rates; + cdf_mem_copy(pOld->rate, pNew->rates, pNew->num_rates); +} + +void convert_ext_supp_rates(tpAniSirGlobal pMac, + tSirMacRateSet *pOld, tDot11fIEExtSuppRates *pNew) +{ + pOld->numRates = pNew->num_rates; + cdf_mem_copy(pOld->rate, pNew->rates, pNew->num_rates); +} + +void convert_qos_caps(tpAniSirGlobal pMac, + tSirMacQosCapabilityIE *pOld, tDot11fIEQOSCapsAp *pNew) +{ + pOld->type = 46; + pOld->length = 1; + + pOld->qosInfo.count = pNew->count; +} + +void convert_qos_caps_station(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 convert_wpa(tpAniSirGlobal pMac, + tSirMacWpaInfo *pOld, tDot11fIEWPA *pNew) +{ + /* This is awful, I know, but the old code just rammed the IE into an */ + /* array... */ + uint8_t buffer[257]; + uint32_t status, written = 0, nbuffer = 257; + status = dot11f_pack_ie_wpa(pMac, pNew, buffer, nbuffer, &written); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOG2, FL("Failed to re-pack the WPA IE (0x%0x" + "8).\n"), status); + return eSIR_FAILURE; + } + + pOld->length = (uint8_t) written - 2; + cdf_mem_copy(pOld->info, buffer + 2, pOld->length); + + return eSIR_SUCCESS; +} + +tSirRetStatus convert_wpa_opaque(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; + cdf_mem_copy(pOld->info + 4, pNew->data, pNew->num_data); + + return eSIR_SUCCESS; +} + +#ifdef FEATURE_WLAN_WAPI +tSirRetStatus convert_wapi_opaque(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; + cdf_mem_copy(pOld->info, pNew->data, pNew->num_data); + + return eSIR_SUCCESS; +} +#endif + +tSirRetStatus convert_wsc_opaque(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 ! */ + uint8_t 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; + cdf_mem_copy(pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data); + + return eSIR_SUCCESS; +} + +tSirRetStatus convert_p2p_opaque(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 ! */ + uint8_t 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; + cdf_mem_copy(pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data); + + return eSIR_SUCCESS; +} + +#ifdef WLAN_FEATURE_WFD +tSirRetStatus convert_wfd_opaque(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 ! */ + uint8_t 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; + cdf_mem_copy(pOld->addIEdata + curAddIELen, pNew->data, pNew->num_data); + + return eSIR_SUCCESS; +} +#endif + +tSirRetStatus convert_rsn(tpAniSirGlobal pMac, + tSirMacRsnInfo *pOld, tDot11fIERSN *pNew) +{ + uint8_t buffer[257]; + uint32_t status, written = 0, nbuffer = 257; + status = dot11f_pack_ie_rsn(pMac, pNew, buffer, nbuffer, &written); + if (DOT11F_FAILED(status)) { + dot11f_log(pMac, LOG2, FL("Failed to re-pack the RSN IE (0x%0x" + "8).\n"), status); + return eSIR_FAILURE; + } + + pOld->length = (uint8_t) written - 2; + cdf_mem_copy(pOld->info, buffer + 2, pOld->length); + + return eSIR_SUCCESS; +} + +tSirRetStatus convert_rsn_opaque(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; + cdf_mem_copy(pOld->info, pNew->data, pOld->length); + + return eSIR_SUCCESS; +} + +void convert_power_caps(tpAniSirGlobal pMac, + tSirMacPowerCapabilityIE *pOld, + tDot11fIEPowerCaps *pNew) +{ + pOld->type = 33; + pOld->length = 2; + pOld->minTxPower = pNew->minTxPower; + pOld->maxTxPower = pNew->maxTxPower; +} + +void convert_supp_channels(tpAniSirGlobal pMac, + tSirMacSupportedChannelIE *pOld, + tDot11fIESuppChannels *pNew) +{ + pOld->type = 36; + pOld->length = (pNew->num_bands * 2); + cdf_mem_copy((uint8_t *) pOld->supportedChannels, + (uint8_t *) pNew->bands, pOld->length); +} + +void convert_cf_params(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 convert_fh_params(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 convert_tim(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; + + cdf_mem_copy(pOld->bitmap, pNew->vbmp, pNew->num_vbmp); +} + +void convert_country(tpAniSirGlobal pMac, + tSirCountryInformation *pOld, tDot11fIECountry *pNew) +{ + int i; + + cdf_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 convert_wmm_params(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *pOld, tDot11fIEWMMParams *pNew) +{ + pOld->type = 221; + pOld->length = 24; + + cdf_mem_copy((uint8_t *) &pOld->qosInfo, (uint8_t *) &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 convert_erp_info(tpAniSirGlobal pMac, + tSirMacErpInfo *pOld, tDot11fIEERPInfo *pNew) +{ + pOld->nonErpPresent = pNew->non_erp_present; + pOld->useProtection = pNew->use_prot; + pOld->barkerPreambleMode = pNew->barker_preamble; +} + +void convert_edca_param(tpAniSirGlobal pMac, + tSirMacEdcaParamSetIE *pOld, + tDot11fIEEDCAParamSet *pNew) +{ + pOld->type = 12; + pOld->length = 20; + + cdf_mem_copy((uint8_t *) &pOld->qosInfo, (uint8_t *) &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 convert_tspec(tpAniSirGlobal pMac, + tSirMacTspecIE *pOld, tDot11fIETSPEC *pNew) +{ + pOld->tsinfo.traffic.trafficType = (uint16_t) pNew->traffic_type; + pOld->tsinfo.traffic.tsid = (uint16_t) pNew->tsid; + pOld->tsinfo.traffic.direction = (uint16_t) pNew->direction; + pOld->tsinfo.traffic.accessPolicy = (uint16_t) pNew->access_policy; + pOld->tsinfo.traffic.aggregation = (uint16_t) pNew->aggregation; + pOld->tsinfo.traffic.psb = (uint16_t) pNew->psb; + pOld->tsinfo.traffic.userPrio = (uint16_t) pNew->user_priority; + pOld->tsinfo.traffic.ackPolicy = (uint16_t) pNew->tsinfo_ack_pol; + + pOld->tsinfo.schedule.schedule = (uint8_t) 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 convert_tclas(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, tDot11fIETCLAS *pNew) +{ + uint32_t length = 0; + + if (DOT11F_FAILED(dot11f_get_packed_ietclas(pMac, pNew, &length))) { + return eSIR_FAILURE; + } + + pOld->tclas.type = DOT11F_EID_TCLAS; + pOld->tclas.length = (uint8_t) 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: + cdf_mem_copy(pOld->tclasParams.eth.srcAddr, + pNew->info.EthParams.source, 6); + cdf_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; + cdf_mem_copy(pOld->tclasParams.ipv4.srcIpAddr, + pNew->info.IpParams.params.IpV4Params. + source, 4); + cdf_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; + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + srcIpAddr, + (uint8_t *) pNew->info.IpParams.params. + IpV6Params.source, 16); + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + dstIpAddr, + (uint8_t *) 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; + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + flowLabel, + (uint8_t *) 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 convert_wmmtspec(tpAniSirGlobal pMac, + tSirMacTspecIE *pOld, tDot11fIEWMMTSPEC *pNew) +{ + pOld->tsinfo.traffic.trafficType = (uint16_t) pNew->traffic_type; + pOld->tsinfo.traffic.tsid = (uint16_t) pNew->tsid; + pOld->tsinfo.traffic.direction = (uint16_t) pNew->direction; + pOld->tsinfo.traffic.accessPolicy = (uint16_t) pNew->access_policy; + pOld->tsinfo.traffic.aggregation = (uint16_t) pNew->aggregation; + pOld->tsinfo.traffic.psb = (uint16_t) pNew->psb; + pOld->tsinfo.traffic.userPrio = (uint16_t) pNew->user_priority; + pOld->tsinfo.traffic.ackPolicy = (uint16_t) 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 convert_wmmtclas(tpAniSirGlobal pMac, + tSirTclasInfo *pOld, tDot11fIEWMMTCLAS *pNew) +{ + uint32_t length = 0; + + if (DOT11F_FAILED(dot11f_get_packed_iewmmtclas(pMac, pNew, &length))) { + return eSIR_FAILURE; + } + + pOld->tclas.type = DOT11F_EID_WMMTCLAS; + pOld->tclas.length = (uint8_t) 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: + cdf_mem_copy(pOld->tclasParams.eth.srcAddr, + pNew->info.EthParams.source, 6); + cdf_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; + cdf_mem_copy(pOld->tclasParams.ipv4.srcIpAddr, + pNew->info.IpParams.params.IpV4Params. + source, 4); + cdf_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; + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + srcIpAddr, + (uint8_t *) pNew->info.IpParams.params. + IpV6Params.source, 16); + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + dstIpAddr, + (uint8_t *) 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; + cdf_mem_copy((uint8_t *) pOld->tclasParams.ipv6. + flowLabel, + (uint8_t *) 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 convert_ts_delay(tpAniSirGlobal pMac, + tSirMacTsDelayIE *pOld, tDot11fIETSDelay *pNew) +{ + pOld->type = DOT11F_EID_TSDELAY; + pOld->length = 4U; + pOld->delay = pNew->delay; +} + +void convert_schedule(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 convert_wmm_schedule(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 convertto_big_endian(void *ptr, uint16_t size) +{ + uint8_t *temp_ptr; + uint32_t *dest_ptr; + + dest_ptr = (uint32_t *) ptr; + while (size) { + temp_ptr = (uint8_t *) dest_ptr; + *dest_ptr = + (temp_ptr[0] << 24) | (temp_ptr[1] << 16) | (temp_ptr[2] << + 8) | + temp_ptr[3]; + dest_ptr++; + size -= 4; + } +} + +void create_scan_data_null_frame(tpAniSirGlobal pMac, tSirMacMgmtHdr *macMgmtHdr, + uint8_t 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 = + (uint8_t) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = + (uint8_t) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + cdf_mem_copy((void *)&macMgmtHdr->da, + (void *)bssid, sizeof(tSirMacAddr)); + cdf_mem_copy((void *)&macMgmtHdr->sa, + (void *)selfMacAddr, sizeof(tSirMacAddr)); + cdf_mem_copy((void *)&macMgmtHdr->bssId, + (void *)bssid, sizeof(tSirMacAddr)); + + return; +} + +void create_scan_cts_frame(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 = + (uint8_t) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = + (uint8_t) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> 8); + cdf_mem_copy((void *)macMgmtHdr->da, (void *)selfMac, + sizeof(tSirMacAddr)); + + return; +} + +void convert_qos_mapset_frame(tpAniSirGlobal pMac, tSirQosMapSet *Qos, + tDot11fIEQosMapSet *dot11fIE) +{ + uint8_t i, j = 0; + 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 create_init_scan_raw_frame(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 = + (uint8_t) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = + (uint8_t) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> + 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + cdf_mem_copy((void *)&macMgmtHdr->da, (void *)pSta[0].bssId, 6); + cdf_mem_copy(&macMgmtHdr->sa, pSta[0].staAddr, 6); + cdf_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 = + (uint8_t) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = + (uint8_t) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> + 8); + cdf_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 create_finish_scan_raw_frame(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 = + (uint8_t) (SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff); + macMgmtHdr->durationHi = + (uint8_t) ((SIR_MAC_MAX_DURATION_MICRO_SECONDS & 0xff00) >> + 8); + macMgmtHdr->seqControl.fragNum = 0; + macMgmtHdr->seqControl.seqNumLo = 0; + macMgmtHdr->seqControl.seqNumHi = 2; + cdf_mem_copy((void *)macMgmtHdr->da, (void *)pSta[0].bssId, 6); + cdf_mem_copy(macMgmtHdr->sa, pSta[0].staAddr, 6); + cdf_mem_copy((void *)macMgmtHdr->bssId, (void *)pSta[0].bssId, + 6); + + } + + return; +#endif +} + +/* utils_parser.c ends here. */ diff --git a/core/sap/dfs/inc/ath_dfs_structs.h b/core/sap/dfs/inc/ath_dfs_structs.h new file mode 100644 index 000000000000..8a3e8f853d2f --- /dev/null +++ b/core/sap/dfs/inc/ath_dfs_structs.h @@ -0,0 +1,257 @@ +/* + * 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 { + uint32_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 + */ + uint32_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 { + uint32_t rp_numpulses; /* Num of pulses in radar burst */ + uint32_t rp_pulsedur; /* Duration of each pulse in usecs */ + uint32_t rp_pulsefreq; /* Frequency of pulses in burst */ + uint32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + uint32_t rp_patterntype; /* fixed or variable pattern type */ + uint32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + uint32_t rp_threshold; /* Threshold for MF output to indicateC + radar match */ + uint32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + uint32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + uint32_t rp_rssithresh; /* Min rssi to be considered a radar pulse */ + uint32_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. + */ + uint32_t rp_ignore_pri_window; + uint32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_staggered_pulse { + uint32_t rp_numpulses; /* Num of pulses in radar burst */ + uint32_t rp_pulsedur; /* Duration of each pulse in usecs */ + uint32_t rp_min_pulsefreq; /* Frequency of pulses in burst */ + uint32_t rp_max_pulsefreq; /* Frequency of pulses in burst */ + uint32_t rp_patterntype; /* fixed or variable pattern type */ + uint32_t rp_pulsevar; /* Time variation of pulse duration for + matched filter (single-sided) in usecs */ + uint32_t rp_threshold; /* Thershold for MF output to indicateC + radar match */ + uint32_t rp_mindur; /* Min pulse duration to be considered for + this pulse type */ + uint32_t rp_maxdur; /* Max pusle duration to be considered for + this pulse type */ + uint32_t rp_rssithresh; /* Min rssi to be considered a radar pulse */ + uint32_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. */ + uint32_t rp_pulseid; /* Unique ID for identifying filter */ +}; + +struct dfs_bin5pulse { + uint32_t b5_threshold; /* Num of bin5 pulses to indicate detection */ + uint32_t b5_mindur; /* Min duration for a bin5 pulse */ + uint32_t b5_maxdur; /* Max duration for a bin5 pulse */ + uint32_t b5_timewindow; /* Window over which to count bin5 pulses */ + uint32_t b5_rssithresh; /* Min rssi to be considered a pulse */ + uint32_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 { + uint32_t nol_chfreq; /* Centre frequency, MHz */ + uint32_t nol_chwidth; /* Width, MHz */ + unsigned long nol_start_ticks; /* start ticks, OS specific */ + uint32_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 + */ + uint32_t pe_relpwr; + + /* + * Pulse Relative step threshold in 0.5dB steps + */ + uint32_t pe_relstep; + + /* + * Max length of radar sign in 0.8us units + */ + uint32_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) +{ + cdf_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 { + uint32_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/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h new file mode 100644 index 000000000000..18087207e094 --- /dev/null +++ b/core/sap/dfs/inc/dfs.h @@ -0,0 +1,824 @@ +/* + * Copyright (c) 2005-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE 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. + + ===========================================================================*/ + +#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 /* CDF_NBUF_EXEMPT_NO_EXEMPTION, etc. */ +#include /* cdf_nbuf_t, etc. */ +#include /* cdf_assert */ +#include /* cdf_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 "cds_ieee80211_common.h" +#include "cds_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))) { \ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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* / */ +/* use 145 for osprey conversion is already done using dfs->dur_multiplier */ +#define MAX_BIN5_DUR 145 +#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) cdf_spin_lock_bh((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_UNLOCK(_dfs) cdf_spin_unlock_bh((&(_dfs)->dfs_radarqlock)) +#define ATH_DFSQ_LOCK_INIT(_dfs) cdf_spinlock_init(&(_dfs)->dfs_radarqlock) + +#define ATH_ARQ_LOCK(_dfs) cdf_spin_lock_bh((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_UNLOCK(_dfs) cdf_spin_unlock_bh((&(_dfs)->dfs_arqlock)) +#define ATH_ARQ_LOCK_INIT(_dfs) cdf_spinlock_init(&(_dfs)->dfs_arqlock) + +#define ATH_DFSEVENTQ_LOCK(_dfs) cdf_spin_lock_bh((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_UNLOCK(_dfs) cdf_spin_unlock_bh((&(_dfs)->dfs_eventqlock)) +#define ATH_DFSEVENTQ_LOCK_INIT(_dfs) \ + cdf_spinlock_init((&(_dfs)->dfs_eventqlock)) +/* Mask for time stamp from descriptor */ +#define DFS_TSMASK 0xFFFFFFFF +/* Shift for time stamp from descriptor */ +#define DFS_TSSHIFT 32 +/* 64 bit TSF wrap value */ +#define DFS_TSF_WRAP 0xFFFFFFFFFFFFFFFFULL +/* TS mask for 64 bit value */ +#define DFS_64BIT_TSFMASK 0x0000000000007FFFULL + +#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 */ +/* Max number of dfs events which can be q'd */ +#define DFS_MAX_EVENTS 1024 + +#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 */ +/* max num of pulses in a burst */ +#define DFS_BIN_MAX_PULSES 60 +#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 */ +/* Max number of pulses kept in buffer */ +#define DFS_MAX_PULSE_BUFFER_SIZE 1024 +#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 cdf_spinlock_t dfsq_lock_t; + +#ifdef WIN32 +#pragma pack(push, dfs_pulseparams, 1) +#endif +struct dfs_pulseparams { + uint64_t p_time; /* time for start of pulse in usecs */ + uint8_t p_dur; /* Duration of pulse in usecs */ + uint8_t p_rssi; /* Duration of pulse in usecs */ +} cdf_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]; + uint32_t pl_firstelem; /* Index of the first element */ + uint32_t pl_lastelem; /* Index of the last element */ + uint32_t pl_numelems; /* Number of elements in the delay line */ +} cdf_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 { + uint64_t re_full_ts; /* 64-bit full timestamp from interrupt time */ + uint32_t re_ts; /* Original 15 bit recv timestamp */ + uint8_t re_rssi; /* rssi of radar event */ + uint8_t re_dur; /* duration of radar pulse */ + uint8_t re_chanindex; /* Channel of event */ + uint8_t re_flags; /* Event flags */ + uint32_t re_freq; /* Centre frequency of event, KHz */ + uint32_t re_freq_lo; /* Lower bounds of frequency, KHz */ + uint32_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 */ +} cdf_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 */ +/* Number of radar channels we keep state for */ +#define DFS_NUM_RADAR_STATES 64 +/* Max number radar filters for each type */ +#define DFS_MAX_NUM_RADAR_FILTERS 10 +/* Number of different radar types */ +#define DFS_MAX_RADAR_TYPES 32 + +struct dfs_ar_state { + uint32_t ar_prevwidth; + uint32_t ar_phyerrcount[DFS_AR_MAX_ACK_RADAR_DUR]; + uint32_t ar_acksum; + uint32_t ar_packetthreshold; /* Thresh to determine traffic load */ + uint32_t ar_parthreshold; /* Thresh to determine peak */ + uint32_t ar_radarrssi; /* Rssi threshold for AR event */ + uint16_t ar_prevtimestamp; + uint16_t ar_peaklist[DFS_AR_MAX_NUM_PEAKS]; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_delayelem, 1) +#endif +struct dfs_delayelem { + /* Current "filter" time for start of pulse in usecs */ + uint32_t de_time; + /* Duration of pulse in usecs */ + uint8_t de_dur; + /* rssi of pulse in dB */ + uint8_t de_rssi; + /* time stamp for this delay element */ + uint64_t de_ts; +} cdf_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 { + /* Array of pulses in delay line */ + struct dfs_delayelem dl_elems[DFS_MAX_DL_SIZE]; + /* Last timestamp the delay line was used (in usecs) */ + uint64_t dl_last_ts; + /* Index of the first element */ + uint32_t dl_firstelem; + /* Index of the last element */ + uint32_t dl_lastelem; + /* Number of elements in the delay line */ + uint32_t dl_numelems; +} cdf_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_delayline) +#endif + +#ifdef WIN32 +#pragma pack(push, dfs_filter, 1) +#endif +struct dfs_filter { + /* Delay line of pulses for this filter */ + struct dfs_delayline rf_dl; + /* Number of pulses in the filter */ + uint32_t rf_numpulses; + /* min pri to be considered for this filter */ + uint32_t rf_minpri; + /* max pri to be considered for this filter */ + uint32_t rf_maxpri; + /* match filter output threshold for radar detect */ + uint32_t rf_threshold; + /* Length (in usecs) of the filter */ + uint32_t rf_filterlen; + /* fixed or variable pattern type */ + uint32_t rf_patterntype; + /* indicates if it is a fixed pri pulse */ + uint32_t rf_fixed_pri_radar_pulse; + /* Min duration for this radar filter */ + uint32_t rf_mindur; + /* Max duration for this radar filter */ + uint32_t rf_maxdur; + uint32_t rf_ignore_pri_window; + /* Unique ID corresponding to the original filter ID */ + uint32_t rf_pulseid; +} cdf_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_filter) +#endif + +struct dfs_filtertype { + struct dfs_filter ft_filters[DFS_MAX_NUM_RADAR_FILTERS]; + /* Duration of pulse which specifies filter type */ + uint32_t ft_filterdur; + /* Num filters of this type */ + uint32_t ft_numfilters; + /* Last timestamp this filtertype was used(in usecs) */ + uint64_t ft_last_ts; + /* min pulse duration to be considered for this filter type */ + uint32_t ft_mindur; + /* max pulse duration to be considered for this filter type */ + uint32_t ft_maxdur; + /* min rssi to be considered for this filter type */ + uint32_t ft_rssithresh; + /* Num pulses in each filter of this type */ + uint32_t ft_numpulses; + /* fixed or variable pattern type */ + uint32_t ft_patterntype; + /* min pri to be considered for this type */ + uint32_t ft_minpri; + /* rssi threshold margin. In Turbo Mode HW + * reports rssi 3dB lower than in non TURBO + * mode. This will offset that diff. + */ + uint32_t ft_rssimargin; +}; + +struct dfs_state { + struct ieee80211_channel rs_chan; /* Channel info */ + uint8_t rs_chanindex; /* Channel index in radar structure */ + uint32_t rs_numradarevents; /* Number of radar events */ + + struct ath_dfs_phyerr_param rs_param; +}; + +/* 30 minutes in seconds */ +#define DFS_NOL_TIMEOUT_S (30*60) +/* 5 minutes in seconds - debugging */ +/* #define DFS_NOL_TIMEOUT_S (5*60) */ +#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 { + uint32_t nol_freq; /* centre frequency */ + uint32_t nol_chwidth; /* event width (MHz) */ + unsigned long nol_start_ticks; /* NOL start time in OS ticks */ + uint32_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 */ +} cdf_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_nolelem) +#endif + +/* Pass structure to DFS NOL timer */ +struct dfs_nol_timer_arg { + struct ath_dfs *dfs; + uint16_t delfreq; + uint16_t delchwidth; +}; + +#ifdef WIN32 +#pragma pack(push, dfs_info, 1) +#endif +struct dfs_info { + /* Use the NOL when radar found (default: true) */ + int rn_use_nol; + /* Number of different types of radars */ + uint32_t rn_numradars; + /* Last 64 bit timstamp from recv interrupt */ + uint64_t rn_lastfull_ts; + /* last 15 bit ts from recv descriptor */ + uint16_t rn_last_ts; + /* last unique 32 bit ts from recv descriptor */ + uint32_t rn_last_unique_ts; + /* Prefix to prepend to 15 bit recv ts */ + uint64_t rn_ts_prefix; + /* Number of bin5 radar pulses to search for */ + uint32_t rn_numbin5radars; + /* Value of fast diversity gc limit from init file */ + uint32_t rn_fastdivGCval; + /* Min rssi for all radar types */ + int32_t rn_minrssithresh; + /* Max pulse width in TSF ticks */ + uint32_t rn_maxpulsedur; + + uint8_t dfs_ext_chan_busy; + uint64_t ext_chan_busy_ts; + + uint64_t dfs_bin5_chirp_ts; + uint8_t dfs_last_bin5_dur; +} cdf_packed; +#ifdef WIN32 +#pragma pack(pop, dfs_info) +#endif + +struct dfs_bin5elem { + uint64_t be_ts; /* Timestamp for the bin5 element */ + uint32_t be_rssi; /* Rssi for the bin5 element */ + uint32_t be_dur; /* Duration of bin5 element */ +}; + +struct dfs_bin5radars { + /* List of bin5 elems that fall within the time window */ + struct dfs_bin5elem br_elems[DFS_MAX_B5_SIZE]; + /* Index of the first element */ + uint32_t br_firstelem; + /* Index of the last element */ + uint32_t br_lastelem; + /* Number of elements in the delay line */ + uint32_t br_numelems; + /* Original info about bin5 pulse */ + struct dfs_bin5pulse br_pulse; +}; + +struct dfs_stats { + uint32_t num_radar_detects; /* total num. of radar detects */ + uint32_t total_phy_errors; + uint32_t owl_phy_errors; + uint32_t pri_phy_errors; + uint32_t ext_phy_errors; + uint32_t dc_phy_errors; + uint32_t early_ext_phy_errors; + uint32_t bwinfo_errors; + uint32_t datalen_discards; + uint32_t rssi_discards; + uint64_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 { + uint64_t ts; /* 64-bit full timestamp from interrupt time */ + uint32_t diff_ts; /* diff timestamp */ + uint8_t rssi; /* rssi of radar event */ + uint8_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 */ +/*in MS */ +#define ATH_DFS_WAIT_POLL_PERIOD_MS ((ATH_DFS_WAIT_POLL_PERIOD) * 1000) +#define ATH_DFS_TEST_RETURN_PERIOD 2 /* 2 seconds */ +/* n MS */ +#define ATH_DFS_TEST_RETURN_PERIOD_MS ((ATH_DFS_TEST_RETURN_PERIOD) * 1000) +#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 + +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 */ + uint32_t dfsdomain; /* cur. DFS domain */ + uint32_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 + /* Default phy params per radar state */ + struct ath_dfs_phyerr_param dfs_defaultparams; + struct dfs_stats ath_dfs_stats; /* DFS related stats */ + struct dfs_pulseline *pulses; /* pulse history */ + struct dfs_event *events; /* Events structure */ + + uint32_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; + /* IEEE chan num to return to after + * a dfs mute test + */ + uint8_t ath_dfstest_ieeechan; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + uint32_t ath_dfs_cac_time; /* CAC period */ + uint32_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 */ + uint8_t dfs_bangradar; +#endif + os_timer_t ath_dfs_task_timer; /* dfs wait timer */ + int dur_multiplier; + + uint16_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 */ + /* + * when TLV is supported, # of radar events ignored after TLV is parsed + */ + int dfs_phyerr_reject_count; + /* number of radar events queued for matching the filters */ + int dfs_phyerr_queued_count; + int dfs_phyerr_freq_min; + int dfs_phyerr_freq_max; + int dfs_phyerr_w53_counter; + /* allow pulse if they are within multiple of PRI for the radar type */ + int dfs_pri_multiplier; + 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 { + uint64_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 */ + + uint32_t rs_tstamp; /* 32 bit TSF from RX descriptor (event) */ + uint32_t freq; /* Centre frequency of event - KHz */ + uint32_t freq_lo; /* Lower bounds of frequency - KHz */ + uint32_t freq_hi; /* Upper bounds of frequency - KHz */ + + uint8_t rssi; /* pulse RSSI */ + uint8_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 uint32_t threshtype, const uint32_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, + uint32_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, uint64_t thists); +int dfs_bin5_check(struct ath_dfs *dfs); +int dfs_check_chirping(struct ath_dfs *dfs, void *buf, + uint16_t datalen, int is_ctl, + int is_ext, int *slope, int *is_dc); +uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, + uint8_t old_dur); +uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, + uint8_t old_dur); +int dfs_get_random_bin5_dur(struct ath_dfs *dfs, uint64_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 */ +uint32_t dfs_round(int32_t val); +struct dfs_state *dfs_getchanstate(struct ath_dfs *dfs, uint8_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, uint32_t deltaT, uint64_t this_ts); + +int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, + uint32_t dur, int ext_chan_flag); +int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, + uint32_t deltaT, uint32_t dur, int ext_chan_flag); + +int dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, + struct dfs_delayline *dl, uint32_t score, + uint32_t refpri, uint32_t refdur, int ext_chan_flag, + int fundamentalpri); +int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, + uint32_t deltaT, uint32_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/core/sap/dfs/inc/dfs_interface.h b/core/sap/dfs/inc/dfs_interface.h new file mode 100644 index 000000000000..ce0a49bcf93b --- /dev/null +++ b/core/sap/dfs/inc/dfs_interface.h @@ -0,0 +1,171 @@ +/* + * 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. + */ + +/*=========================================================================== + + dfs_interface.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + + ===========================================================================*/ + +#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); + */ + +uint16_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, + uint16_t datalen, uint8_t rssi, uint8_t ext_rssi, + uint32_t rs_tstamp, uint64_t fulltsf, + bool enable_log); +int dfs_control(struct ieee80211com *ic, u_int id, void *indata, + uint32_t insize, void *outdata, uint32_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/core/sap/dfs/inc/radar_filters.h b/core/sap/dfs/inc/radar_filters.h new file mode 100644 index 000000000000..5837d06a27d4 --- /dev/null +++ b/core/sap/dfs/inc/radar_filters.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +/*=========================================================================== + + radar_filters.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + + ===========================================================================*/ + +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, 22, 0, 3, 0, 5}, + + /* FCC TYPE 4 */ + {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 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/core/sap/dfs/sources b/core/sap/dfs/sources new file mode 100644 index 000000000000..3899f4156c92 --- /dev/null +++ b/core/sap/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/cdf header files will preempt any +# header files of the same names from the regular cdf 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/core/sap/dfs/src/dfs.c b/core/sap/dfs/src/dfs.c new file mode 100644 index 000000000000..a9191517f5ec --- /dev/null +++ b/core/sap/dfs/src/dfs.c @@ -0,0 +1,993 @@ +/* + * Copyright (c) 2002-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE 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 "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; +uint32_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; + dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; + 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) { + *(uint32_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; + + 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), + CDF_TIMER_TYPE_SW); +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + OS_INIT_TIMER(NULL, &(dfs->ath_dfstesttimer), dfs_testtimer_task, + (void *)ic, CDF_TIMER_TYPE_SW); + 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; n < DFS_MAX_RADAR_TYPES; n++) { + dfs->dfs_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; n < DFS_MAX_RADAR_TYPES; n++) { + if (dfs->dfs_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; n < DFS_MAX_RADAR_TYPES; n++) { + if (dfs->dfs_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; + /* uint32_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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)) { + + uint8_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, uint32_t insize, void *outdata, uint32_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; + uint32_t val = 0; +#ifndef ATH_DFS_RADAR_DETECTION_ONLY + struct dfsreq_nolinfo *nol; + uint32_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 < sizeof(struct dfs_ioctl_params)) { + error = -EINVAL; + break; + } + *outsize = sizeof(struct dfs_ioctl_params); + dfsparams = (struct dfs_ioctl_params *)outdata; + + /* + * Fetch the DFS thresholds using the internal representation. + */ + (void)dfs_get_thresholds(ic, &peout); + + /* + * Convert them to the dfs IOCTL representation. + */ + ath_dfs_dfsparam_to_ioctlparam(&peout, dfsparams); + break; + case DFS_RADARDETECTS: + if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof(uint32_t); + *((uint32_t *) outdata) = dfs->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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_debug_mask = *(uint32_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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_false_rssi_thres = *(uint32_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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->ath_dfs_peak_mag = *(uint32_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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + if (*(uint32_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(uint32_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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + data = (uint32_t *) indata; + dfs->ath_dfstesttime = *data; + dfs->ath_dfstesttime *= (1000); /* convert sec into ms */ + break; + case DFS_GET_USENOL: + if (!outdata || !outsize || *outsize < sizeof(uint32_t)) { + error = -EINVAL; + break; + } + *outsize = sizeof(uint32_t); + *((uint32_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(uint32_t) || !indata) { + error = -EINVAL; + break; + } + dfs->dfs_rinfo.rn_use_nol = *(uint32_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 uint32_t threshtype, + const uint32_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; +} + +uint16_t dfs_usenol(struct ieee80211com *ic) +{ + struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; + return dfs ? (uint16_t) dfs->dfs_rinfo.rn_use_nol : 0; +} + +uint16_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/core/sap/dfs/src/dfs_bindetects.c b/core/sap/dfs/src/dfs_bindetects.c new file mode 100644 index 000000000000..7c48309942ca --- /dev/null +++ b/core/sap/dfs/src/dfs_bindetects.c @@ -0,0 +1,485 @@ +/* + * 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_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, + uint32_t dur, int ext_chan_flag) +{ + struct dfs_pulseline *pl = dfs->pulses; + int i, n, refpri, primargin, numpulses = 0; + uint64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, + window_start, window_end; + uint32_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; i < pl->pl_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", + (uint32_t) window_start, (uint32_t) window_end); + for (i = 0; i < pl->pl_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", (uint32_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, + uint32_t deltaT, uint64_t this_ts) +{ + uint32_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; n < dl->dl_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 = (uint32_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, uint32_t deltaT, + uint32_t width, int ext_chan_flag) +{ + uint32_t refpri, refdur, searchpri, deltapri, deltapri_2, deltapri_3, + averagerefpri; + uint32_t n, i, primargin, durmargin, highscore, highscoreindex; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0; + struct dfs_delayline *dl; + uint32_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; n < dl->dl_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; n < dl->dl_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; i < dl->dl_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; n < dl->dl_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, uint32_t score, uint32_t refpri, + uint32_t refdur, int ext_chan_flag, int fundamentalpri) +{ + uint32_t searchpri, searchdur, searchrssi, deltapri = 0, deltapri1 = + 0, deltapri2 = 0, deltadur, averagerefpri = 0, MatchCount = 0; + uint32_t delta_ts_variance, delta_time_stamps, prev_good_timestamp = 0; + int delayindex, dindex; + uint32_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; i < dl->dl_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; i < dl->dl_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; j < rf->rf_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) + && (fundamentalpri < + refpri + 100)) { + numpulsetochk = 4; + } + } else { + numpulsetochk = 4; + } + for (j = 0; j < numpulsetochk; j++) { + delta_ts_variance = + DFS_DIFF(delta_time_stamps, + ((j + + 1) * fundamentalpri)); + if (delta_ts_variance < + (2 * (j + 1) * primargin)) { + numpulses++; + if (rf->rf_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/core/sap/dfs/src/dfs_debug.c b/core/sap/dfs/src/dfs_debug.c new file mode 100644 index 000000000000..71f917ad00e6 --- /dev/null +++ b/core/sap/dfs/src/dfs_debug.c @@ -0,0 +1,160 @@ +/* + * 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_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; i < dl->dl_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; i < DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_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; j < ft->ft_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; + uint32_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/core/sap/dfs/src/dfs_fcc_bin5.c b/core/sap/dfs/src/dfs_fcc_bin5.c new file mode 100644 index 000000000000..ccc9fe6d2b7c --- /dev/null +++ b/core/sap/dfs/src/dfs_fcc_bin5.c @@ -0,0 +1,874 @@ +/* + * 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_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 */ + if (!(dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO)) + b5_rssithresh += br->br_pulse.b5_rssimargin; + + /* + * 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, uint64_t thists) +{ + uint32_t index, stop; + uint64_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) > + ((uint64_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]; + uint32_t n = 0, i = 0, i1 = 0, this = 0, prev = 0, rssi_diff = + 0, width_diff = 0, bursts = 0; + uint32_t total_diff = 0, average_diff = 0, total_width = + 0, average_width = 0, numevents = 0; + uint64_t pri; + + if (dfs == NULL) { + DFS_PRINTK("%s: ic_dfs is NULL\n", __func__); + return 1; + } + for (n = 0; n < dfs->dfs_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, + uint16_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; + uint8_t *fft_data_ptr; + + *slope = 0; + *is_dc = 0; + + num_fft_packets = datalen / FFT_LEN; + fft_data_ptr = ((uint8_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 = ((uint8_t *) buf); + + if (is_ctl) { + + fft_data_ptr = ((uint8_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 = + ((uint8_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 = + ((uint8_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 = ((uint8_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 = + ((uint8_t *) buf) + (FFT_LEN * (num_fft_packets - 1)); + ext_high1 = *(fft_data_ptr + FFT_UPPER_BIN_MAX_INDEX_BYTE) >> 2; + fft_data_ptr = + ((uint8_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, uint16_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 }; + + uint8_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; + + 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; + } + + ptr = (uint8_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; + + 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; + } + /* + * 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, + uint16_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); +} + +uint8_t +dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, + uint8_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, uint64_t tstamp) +{ + uint8_t new_dur = MIN_BIN5_DUR; + int range; + + get_random_bytes(&new_dur, sizeof(uint8_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/core/sap/dfs/src/dfs_init.c b/core/sap/dfs/src/dfs_init.c new file mode 100644 index 000000000000..ca259c4af8ea --- /dev/null +++ b/core/sap/dfs/src/dfs_init.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_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: sc_dfs is NULL", __func__, __LINE__); + return; + } + pl = dfs->pulses; + + if (pl == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: pl==NULL, dfs=%p", __func__, __LINE__, dfs); + return; + } + + if (dfs->dfs_b5radars == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; i < DFS_MAX_RADAR_TYPES; i++) { + if (dfs->dfs_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) +{ + uint32_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; + uint32_t max_pulsedur = 0; + + if (dfs == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; i < DFS_MAX_RADAR_OVERLAP; i++) + (dfs->dfs_radartable[n])[i] = -1; + } + /* Now, initialize the radar filters */ + for (p = 0; p < numradars; p++) { + ft = NULL; + for (n = 0; n < dfs->dfs_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++) { + uint32_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; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; n < numb5radars; n++) { + dfs->dfs_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; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s[%d]: DFS min filter rssiThresh = %d", + __func__, __LINE__, min_rssithresh); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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/core/sap/dfs/src/dfs_ioctl.h b/core/sap/dfs/src/dfs_ioctl.h new file mode 100644 index 000000000000..abe6c0c8c75e --- /dev/null +++ b/core/sap/dfs/src/dfs_ioctl.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/*=========================================================================== + + dfs_ioctl.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + + ===========================================================================*/ + +/* + * 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 { + uint16_t nol_freq; /* NOL channel frequency */ + uint16_t nol_chwidth; + unsigned long nol_start_ticks; /* OS ticks when the NOL timer started */ + uint32_t nol_timeout_ms; /* Nol timeout value in msec */ +}; + +struct dfsreq_nolinfo { + uint32_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/core/sap/dfs/src/dfs_ioctl_private.h b/core/sap/dfs/src/dfs_ioctl_private.h new file mode 100644 index 000000000000..6b268b713e86 --- /dev/null +++ b/core/sap/dfs/src/dfs_ioctl_private.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +/*=========================================================================== + + dfs_ioctl_private.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + + ===========================================================================*/ + +/* + * 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/core/sap/dfs/src/dfs_misc.c b/core/sap/dfs/src/dfs_misc.c new file mode 100644 index 000000000000..8cf4a2c8cd4a --- /dev/null +++ b/core/sap/dfs/src/dfs_misc.c @@ -0,0 +1,276 @@ +/* + * 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_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; + + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + 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; + } + 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; + + if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + 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; + } + return thresh; +} + +uint32_t dfs_round(int32_t val) +{ + uint32_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, uint8_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; i < DFS_NUM_RADAR_STATES; i++) { + if ((dfs->dfs_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 = (uint8_t) i; + return &(dfs->dfs_radar[i]); + } + } + /* No existing channel found, look for first free channel state entry */ + for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { + if (dfs->dfs_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 = (uint8_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/core/sap/dfs/src/dfs_nol.c b/core/sap/dfs/src/dfs_nol.c new file mode 100644 index 000000000000..5a5ec795bc3f --- /dev/null +++ b/core/sap/dfs/src/dfs_nol.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2002-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE 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 "cdf_time.h" /* cdf_time_t, cdf_system_time_after */ + +static void +dfs_nol_delete(struct ath_dfs *dfs, uint16_t delfreq, uint16_t delchwidth); + +static os_timer_func(dfs_remove_from_nol) +{ + struct dfs_nol_timer_arg *nol_arg; + struct ath_dfs *dfs; + struct ieee80211com *ic; + uint16_t delfreq; + uint16_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 = + cdf_system_ticks_to_msecs(cdf_system_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 + uint32_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 = + cdf_system_ticks_to_msecs(cdf_system_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, + uint32_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 = cdf_system_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 = cdf_system_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, CDF_TIMER_TYPE_SW); + 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, uint16_t delfreq, uint16_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, + (cdf_system_ticks_to_msecs + (cdf_system_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/core/sap/dfs/src/dfs_phyerr.h b/core/sap/dfs/src/dfs_phyerr.h new file mode 100644 index 000000000000..22a900f2e060 --- /dev/null +++ b/core/sap/dfs/src/dfs_phyerr.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* + * dfs_phyerr.h + * + * OVERVIEW: + * + * Source code borrowed from QCA_MAIN DFS module + * + * DEPENDENCIES: + * + * Are listed for each API below. + */ + + +#ifndef __DFS_PHYERR_H__ +#define __DFS_PHYERR_H__ + +extern int dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, + uint16_t datalen, uint8_t rssi, + uint8_t ext_rssi, uint32_t rs_tstamp, + uint64_t fulltsf, struct dfs_phy_err *e, + bool enable_log); + +#endif /* __DFS_PHYERR_H__ */ diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c new file mode 100644 index 000000000000..205c170873b3 --- /dev/null +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -0,0 +1,726 @@ +/* + * 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 "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; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "\n ############ Radar Summary ############\n"); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - pulsedur = %d micro seconds\n", __func__, + rsu->pulse_duration); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - rssi = %d dbm\n", __func__, + rsu->rssi); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - ischirp = %d\n", __func__, + rsu->is_chirp); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - sidx = %d\n", __func__, + rsu->sidx); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - delta_peak = %d\n", __func__, + rsu->delta_peak); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - delta_diff = %d\n", __func__, + rsu->delta_diff); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - raw tsf = %d\n", __func__, + rsu->raw_tsf); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - tsf_offset = %d micro seconds\n", + __func__, rsu->tsf_offset); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Radar Summary - cooked tsf = %d\n", __func__, + (rsu->raw_tsf - rsu->tsf_offset)); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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)); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 + */ + + 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; + } + +} + +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, + uint8_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: LEN=%d, avail=%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; + /* + * For now, the only 11ac channel with freq1/freq2 setup is + * VHT80. + * + * XXX should have a flag macro to check this! + */ + } else 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); + } + + /* + * 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, uint16_t datalen, + uint8_t rssi, uint8_t ext_rssi, uint32_t rs_tstamp, + uint64_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; + + 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)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_DEBUG, + "%s[%d]:parse failed invalid phyerror cnt = %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/core/sap/dfs/src/dfs_phyerr_tlv.h b/core/sap/dfs/src/dfs_phyerr_tlv.h new file mode 100644 index 000000000000..d65375267cfd --- /dev/null +++ b/core/sap/dfs/src/dfs_phyerr_tlv.h @@ -0,0 +1,206 @@ +/* + * 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. + */ + +/*=========================================================================== + + dfs_phyerr_tlv.h + + OVERVIEW: + + Source code borrowed from QCA_MAIN DFS module + + DEPENDENCIES: + + Are listed for each API below. + + ===========================================================================*/ + +#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/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c new file mode 100644 index 000000000000..1cabfd4dd9f2 --- /dev/null +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -0,0 +1,855 @@ +/* + * Copyright (c) 2002-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE 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 "dfs.h" +#include "dfs_phyerr.h" /* For chip-specific phyerr func 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; + + /* 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); + + 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; + + /* + * 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? + */ + return ieee80211_chan2freq(ic, ic->ic_curchan) + + (chan_offset / 2); + } + + /* + * For non-wide channels, the centre frequency is just ic_freq. + * The centre frequency for pri events is still ic_freq. + */ + if (is_pri) + return ieee80211_chan2freq(ic, ic->ic_curchan); + + if (is_ext) + return ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width; + + /* XXX shouldn't get here */ + return ieee80211_chan2freq(ic, ic->ic_curchan); +} + +/* + * 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, uint16_t datalen, + uint8_t rssi, uint8_t ext_rssi, uint32_t rs_tstamp, + uint64_t fulltsf, struct dfs_phy_err *e) +{ + const char *cbuf = (const char *)buf; + uint8_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 = ((uint8_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=%dMHz, freq_lo=%dMHz, freq_hi=%dMHz\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, uint16_t datalen, + uint8_t rssi, uint8_t ext_rssi, uint32_t rs_tstamp, + uint64_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; + uint8_t dur = 0; + uint8_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, + "dur=%u rssi=%u bw_info=0x%x datalen = %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, + uint16_t datalen, uint8_t rssi, uint8_t ext_rssi, + uint32_t rs_tstamp, uint64_t fulltsf, + struct dfs_phy_err *e) +{ + const char *cbuf = (const char *)buf; + uint8_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) + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "%s: %s\n", + __func__, buf); +#endif /* def CONFIG_ENABLE_DUMP_PHYERR_CONTENTS */ +} + +void +dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, + uint8_t r_rssi, uint8_t r_ext_rssi, uint32_t r_rs_tstamp, + uint64_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: chan is NULL\n", __func__); + return; + } + + if (IEEE80211_IS_CHAN_RADAR(chan)) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "%s: Radar already found in the channel, " + " do not queue radar data\n", __func__); + return; + } + + 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; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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. + */ + if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) { + 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)) { + 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); + } + } + + /* + * 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/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c new file mode 100644 index 000000000000..789364899988 --- /dev/null +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2002-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE 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 uint8_t dfs_process_pulse_dur(struct ath_dfs *dfs, uint8_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 (uint8_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; + uint32_t tabledepth, index; + uint64_t deltafull_ts = 0, this_ts, deltaT; + struct ieee80211_channel *thischan; + struct dfs_pulseline *pl; + static uint32_t test_ts = 0; + static uint32_t diff_ts = 0; + int ext_chan_event_flag = 0; +#if 0 + int pri_multiplier = 2; +#endif + int i; + + if (dfs == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: dfs is NULL", __func__, __LINE__); + return 0; + } + pl = dfs->pulses; + if (!(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, + "%s: radar event on non-DFS chan", __func__); + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + return 0; + } +#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; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; + 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 += + (((uint64_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 > + ((uint64_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 > (uint64_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 | ((uint64_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 = (uint32_t) this_ts - test_ts; + test_ts = (uint32_t) this_ts; + DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, + "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu", + (uint32_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++; + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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__, (uint32_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 == 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)) { + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s:chan->ic_flags=0x%x, MHz separation=%d\n", + __func__, chan->ic_flags, + chan->ic_pri_freq_center_freq_mhz_separation); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: Peak Idx =%d,re.re_dur =%d,diff_ts =%d\n", + __func__, re.sidx, re.re_dur, diff_ts); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "\n%s: Modify pulse dur to fit 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))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "\n%s:chan->ic_flags=0x%x,MHz Separation=%d\n", + __func__, chan->ic_flags, + chan->ic_pri_freq_center_freq_mhz_separation); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s:Peak Index =%d,re.re_dur =%d,diff_ts =%d\n", + __func__, re.sidx, re.re_dur, diff_ts); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s:Modify ETSI pulse dur to 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); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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; + (p < ft->ft_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); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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); + CDF_TRACE + (CDF_MODULE_ID_SAP, + CDF_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); + CDF_TRACE + (CDF_MODULE_ID_SAP, + CDF_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, + (uint32_t) + deltaT, + re. + re_dur); + } else { + found = + dfs_bin_check(dfs, rf, + (uint32_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); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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); + 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); + } + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_w53_counter = 0; + } + /* CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "IN FUNC %s[%d]: retval = %d ",__func__,__LINE__,retval); */ + return retval; +/* #endif */ +/* return 1; */ +} + +#endif /* ATH_SUPPORT_DFS */ diff --git a/core/sap/dfs/src/dfs_staggered.c b/core/sap/dfs/src/dfs_staggered.c new file mode 100644 index 000000000000..71c04b573b0a --- /dev/null +++ b/core/sap/dfs/src/dfs_staggered.c @@ -0,0 +1,308 @@ +/* + * 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_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(uint32_t sample_pri, uint32_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(uint32_t highestpri, uint32_t midpri, + uint32_t lowestpri, uint32_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, + uint32_t deltaT, uint32_t width) +{ + uint32_t refpri, refdur, searchpri = 0, deltapri; /* , averagerefpri; */ + uint32_t n, i, primargin, durmargin; + int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0; + struct dfs_delayline *dl; + uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff; +#if 0 + int numpulses = 0; +#endif + int higherthan, lowerthan, numscores; + int numpulseshigh = 0, numpulsesmid = 0, numpulsestemp = 0; + uint32_t lowestscore = 0, lowestscoreindex = 0, lowestpri = 0; + uint32_t midscore = 0, midscoreindex = 0, midpri = 0; + uint32_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; n < dl->dl_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; n < dl->dl_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; i < dl->dl_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; n < dl->dl_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; n < dl->dl_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/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h new file mode 100644 index 000000000000..dc450e22abe8 --- /dev/null +++ b/core/sap/inc/sap_api.h @@ -0,0 +1,920 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef WLAN_QCT_WLANSAP_H +#define WLAN_QCT_WLANSAP_H + +/** + * W L A N S O F T A P P A L L A Y E R + * E X T E R N A L A P I + * + * DESCRIPTION + * This file contains the external API exposed by the wlan SAP PAL layer + * module. + */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "cds_api.h" +#include "cds_packet.h" +#include "cdf_types.h" + +#include "p2p_api.h" +#include "sme_api.h" +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------------------- + * 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 + +/* defines for WPS config states */ +#define SAP_WPS_DISABLED 0 +#define SAP_WPS_ENABLED_UNCONFIGURED 1 +#define SAP_WPS_ENABLED_CONFIGURED 2 +#define MAX_NAME_SIZE 64 +#define MAX_TEXT_SIZE 32 + +#define MAX_CHANNEL_LIST_LEN 256 +#ifdef WLAN_FEATURE_MBSSID +#define CDF_MAX_NO_OF_SAP_MODE 2 /* max # of SAP */ +#else +#define CDF_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 */ +#define SAP_ACS_WEIGHT_MAX (4444) + +/*-------------------------------------------------------------------------- + * reasonCode taken from 802.11 standard. + * ------------------------------------------------------------------------*/ + +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, + /* this type is added to support accept & deny list at the same time */ + eSAP_SUPPORT_ACCEPT_AND_DENY = 2, + /*In this mode all MAC addresses are allowed to connect */ + eSAP_ALLOW_ALL = 3, +} 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 del 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 assoc req to upper layers */ + /* + * Event sent when we have successfully associated a station and + * upper layer neeeds to allocate a context + */ + eSAP_STA_ASSOC_EVENT, + /* + * Event sent when we have successfully reassociated a station and + * upper layer neeeds to allocate a context + */ + eSAP_STA_REASSOC_EVENT, + /* + * Event sent when associated a station has disassociated as a + * result of various conditions + */ + eSAP_STA_DISASSOC_EVENT, + /* Event sent when user called wlansap_set_key_sta */ + eSAP_STA_SET_KEY_EVENT, + /* Event sent whenever there is MIC failure detected */ + eSAP_STA_MIC_FAILURE_EVENT, + /* Event sent when user called wlansap_get_assoc_stations */ + eSAP_ASSOC_STA_CALLBACK_EVENT, + /* Event send when user call wlansap_get_wps_session_overlap */ + eSAP_GET_WPSPBC_SESSION_EVENT, + /* Event send on WPS PBC probe request is received */ + eSAP_WPS_PBC_PROBE_REQ_EVENT, + eSAP_INDICATE_MGMT_FRAME, + eSAP_REMAIN_CHAN_READY, + eSAP_SEND_ACTION_CNF, + eSAP_DISCONNECT_ALL_P2P_CLIENT, + eSAP_MAC_TRIG_STOP_BSS_EVENT, + /* + * Event send when a STA in neither white list or black list tries to + * associate in softap mode + */ + eSAP_UNKNOWN_STA_JOIN, + /* Event send when a new STA is rejected association since softAP + * max assoc limit has reached + */ + eSAP_MAX_ASSOC_EXCEEDED, + eSAP_CHANNEL_CHANGE_EVENT, + eSAP_DFS_CAC_START, + eSAP_DFS_CAC_INTERRUPTED, + eSAP_DFS_CAC_END, + eSAP_DFS_RADAR_DETECT, + /* Event sent when user need to get the DFS NOL from CNSS */ + eSAP_DFS_NOL_GET, + /* Event sent when user need to set the DFS NOL to CNSS */ + eSAP_DFS_NOL_SET, + /* No ch available after DFS RADAR detect */ + eSAP_DFS_NO_AVAILABLE_CHANNEL, +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + eSAP_ACS_SCAN_SUCCESS_EVENT, +#endif + eSAP_ACS_CHANNEL_SELECTED, +} eSapHddEvent; + +typedef enum { + eSAP_OPEN_SYSTEM, + eSAP_SHARED_KEY, + eSAP_AUTO_SWITCH +} eSapAuthType; + +typedef enum { + /* Disassociation was internally initated from CORE stack */ + eSAP_MAC_INITATED_DISASSOC = 0x10000, + /* + * Disassociation was internally initated from host by + * invoking wlansap_disassoc_sta call + */ + eSAP_USR_INITATED_DISASSOC +} eSapDisassocReason; + +/*Handle bool 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. */ + /* Channel not selected during intial scan. */ + eSAP_START_BSS_CHANNEL_NOT_SELECTED, + 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 */ + /* no WPS probe request in 120 second */ + eSAP_WPSPBC_NO_WPSPBC_PROBE_REQ_IN120S, + /* One WPS probe request in 120 second */ + eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S, +} eWPSPBCOverlap; + +/*---------------------------------------------------------------------------- + * Typedefs + * -------------------------------------------------------------------------*/ +typedef struct sap_StartBssCompleteEvent_s { + uint8_t status; + uint8_t operatingChannel; + uint16_t staId; /* self StaID */ + uint8_t sessionId; /* SoftAP SME session ID */ +} tSap_StartBssCompleteEvent; + +typedef struct sap_StopBssCompleteEvent_s { + uint8_t status; +} tSap_StopBssCompleteEvent; + +typedef struct sap_StationAssocIndication_s { + struct cdf_mac_addr staMac; + uint8_t assoId; + uint8_t staId; + uint8_t status; + /* Required for indicating the frames to upper layer */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; + bool fWmmEnabled; + eCsrAuthType negotiatedAuthType; + eCsrEncryptionType negotiatedUCEncryptionType; + eCsrEncryptionType negotiatedMCEncryptionType; + bool fAuthRequired; +} tSap_StationAssocIndication; + +typedef struct sap_StationAssocReassocCompleteEvent_s { + struct cdf_mac_addr staMac; + uint8_t staId; + uint8_t status; + uint8_t ies[MAX_ASSOC_IND_IE_LEN]; + uint16_t iesLen; + uint32_t statusCode; + eSapAuthType SapAuthType; + bool wmmEnabled; + /* Required for indicating the frames to upper layer */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; + uint32_t assocRespLength; + uint8_t *assocRespPtr; + uint8_t timingMeasCap; + tSirSmeChanInfo chan_info; +} tSap_StationAssocReassocCompleteEvent; + +typedef struct sap_StationDisassocCompleteEvent_s { + struct cdf_mac_addr staMac; + uint8_t staId; /* STAID should not be used */ + uint8_t status; + uint32_t statusCode; + eSapDisassocReason reason; +} tSap_StationDisassocCompleteEvent; + +typedef struct sap_StationSetKeyCompleteEvent_s { + uint8_t status; + struct cdf_mac_addr peerMacAddr; +} tSap_StationSetKeyCompleteEvent; + +/*struct corresponding to SAP_STA_MIC_FAILURE_EVENT */ +typedef struct sap_StationMICFailureEvent_s { + struct cdf_mac_addr srcMacAddr; /* address used to compute MIC */ + struct cdf_mac_addr staMac; /* taMacAddr transmitter address */ + struct cdf_mac_addr dstMacAddr; + eSapBool multicast; + uint8_t IV1; /* first byte of IV */ + uint8_t keyId; /* second byte of IV */ + uint8_t TSC[SIR_CIPHER_SEQ_CTR_SIZE]; /* sequence number */ + +} tSap_StationMICFailureEvent; +/*Structure to return MAC address of associated stations */ +typedef struct sap_AssocMacAddr_s { + struct cdf_mac_addr staMac; /* Associated station's MAC address */ + uint8_t assocId; /* Associated station's Association ID */ + uint8_t staId; /* Allocated station Id */ + uint8_t ShortGI40Mhz; + uint8_t ShortGI20Mhz; + uint8_t Support40Mhz; + uint32_t requestedMCRate; + tSirSupportedRates supportedRates; +} tSap_AssocMacAddr, *tpSap_AssocMacAddr; + +/*struct corresponding to SAP_ASSOC_STA_CALLBACK_EVENT */ +typedef struct sap_AssocStaListEvent_s { + CDF_MODULE_ID module; + /* module id that was passed in wlansap_get_assoc_stations API */ + uint8_t noOfAssocSta; /* Number of associated stations */ + tpSap_AssocMacAddr pAssocStas; + /* + * Pointer to pre allocated memory to obtain list of + * associated stations passed in wlansap_get_assoc_stations API + */ +} tSap_AssocStaListEvent; + +typedef struct sap_GetWPSPBCSessionEvent_s { + uint8_t status; + /* module id that was passed in wlansap_get_assoc_stations API */ + CDF_MODULE_ID module; + uint8_t UUID_E[16]; /* Unique identifier of the AP. */ + struct cdf_mac_addr addr; + eWPSPBCOverlap wpsPBCOverlap; +} tSap_GetWPSPBCSessionEvent; + +typedef struct sap_WPSPBCProbeReqEvent_s { + uint8_t status; + /* module id that was passed in wlansap_get_assoc_stations API */ + CDF_MODULE_ID module; + tSirWPSPBCProbeReq WPSPBCProbeReq; +} tSap_WPSPBCProbeReqEvent; + +typedef struct sap_ManagementFrameInfo_s { + uint32_t nFrameLength; + uint8_t frameType; + uint32_t rxChan; /* Channel of where packet is received */ + /* + * 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. + */ + uint8_t *pbFrames; +} tSap_ManagementFrameInfo; + +typedef struct sap_SendActionCnf_s { + eSapStatus actionSendSuccess; +} tSap_SendActionCnf; + +typedef struct sap_UnknownSTAJoinEvent_s { + struct cdf_mac_addr macaddr; +} tSap_UnknownSTAJoinEvent; + +typedef struct sap_MaxAssocExceededEvent_s { + struct cdf_mac_addr macaddr; +} tSap_MaxAssocExceededEvent; + +typedef struct sap_DfsNolInfo_s { + uint16_t sDfsList; /* size of pDfsList in byte */ + void *pDfsList; /* pointer to pDfsList buffer */ +} tSap_DfsNolInfo; + +/** + * sap_acs_ch_selected_s - the structure to hold the selected channels + * @pri_channel: Holds the ACS selected primary channel + * @sec_channel: Holds the ACS selected secondary channel + * + * Holds the primary and secondary channel selected by ACS and is + * used to send it to the HDD. + */ +struct sap_ch_selected_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; +}; + +/** + * sap_roc_ready_ind_s - the structure to hold the scan id + * @scan_id: scan identifier + * + * Holds scan identifier + */ +struct sap_roc_ready_ind_s { + uint32_t scan_id; +}; +/* + * This struct will be filled in and passed to tpWLAN_SAPEventCB that is + * provided during wlansap_start_bss 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 { + /*SAP_START_BSS_EVENT */ + tSap_StartBssCompleteEvent sapStartBssCompleteEvent; + /*SAP_STOP_BSS_EVENT */ + tSap_StopBssCompleteEvent sapStopBssCompleteEvent; + /*SAP_ASSOC_INDICATION */ + tSap_StationAssocIndication sapAssocIndication; + /*SAP_STA_ASSOC_EVENT, SAP_STA_REASSOC_EVENT */ + tSap_StationAssocReassocCompleteEvent + sapStationAssocReassocCompleteEvent; + /*SAP_STA_DISASSOC_EVENT */ + tSap_StationDisassocCompleteEvent + sapStationDisassocCompleteEvent; + /*SAP_STA_SET_KEY_EVENT */ + tSap_StationSetKeyCompleteEvent sapStationSetKeyCompleteEvent; + /*SAP_STA_MIC_FAILURE_EVENT */ + tSap_StationMICFailureEvent sapStationMICFailureEvent; + /*SAP_ASSOC_STA_CALLBACK_EVENT */ + tSap_AssocStaListEvent sapAssocStaListEvent; + /*SAP_GET_WPSPBC_SESSION_EVENT */ + tSap_GetWPSPBCSessionEvent sapGetWPSPBCSessionEvent; + /*eSAP_WPS_PBC_PROBE_REQ_EVENT */ + tSap_WPSPBCProbeReqEvent sapPBCProbeReqEvent; + /*eSAP_INDICATE_MGMT_FRAME */ + tSap_ManagementFrameInfo sapManagementFrameInfo; + /* eSAP_SEND_ACTION_CNF */ + tSap_SendActionCnf sapActionCnf; + /* eSAP_UNKNOWN_STA_JOIN */ + tSap_UnknownSTAJoinEvent sapUnknownSTAJoin; + /* eSAP_MAX_ASSOC_EXCEEDED */ + tSap_MaxAssocExceededEvent sapMaxAssocExceeded; + /*eSAP_DFS_NOL_XXX */ + tSap_DfsNolInfo sapDfsNolInfo; + struct sap_ch_selected_s sap_ch_selected; + struct sap_roc_ready_ind_s sap_roc_ind; + + } sapevt; +} tSap_Event, *tpSap_Event; + +typedef struct sap_SSID { + uint8_t length; + uint8_t ssId[MAX_SSID_LEN]; +} cdf_packed tSap_SSID_t; + +typedef struct sap_SSIDInfo { + tSap_SSID_t ssid; /* SSID of the AP */ + /* SSID should/shouldn't be bcast in probe RSP & beacon */ + uint8_t ssidHidden; +} cdf_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; + uint8_t pcl_channels[NUM_RF_CHANNELS]; + uint32_t pcl_ch_count; + /* 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; + struct cdf_mac_addr accept_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ + bool ieee80211d; /* Specify if 11D is enabled or disabled */ + bool protEnabled; /* Specify if protection is enabled or disabled */ + /* Specify if OBSS protection is enabled or disabled */ + bool obssProtEnabled; + struct cdf_mac_addr deny_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ + struct cdf_mac_addr self_macaddr; /* self macaddress or BSSID */ + uint8_t channel; /* Operation channel */ + uint8_t sec_ch; + chan_params_t ch_params; + uint32_t ch_width_orig; + uint8_t max_num_sta; /* maximum number of STAs in station table */ + uint8_t dtim_period; /* dtim interval */ + uint8_t num_accept_mac; + uint8_t num_deny_mac; + /* Max ie length 255 * 2(WPA+RSN) + 2 bytes(vendor specific ID) * 2 */ + uint8_t RSNWPAReqIE[(SIR_MAC_MAX_IE_LENGTH * 2) + 4]; + /* it is ignored if [0] is 0. */ + uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t RSNAuthType; + uint8_t RSNEncryptType; + uint8_t mcRSNEncryptType; + eSapAuthType authType; + bool privacy; + bool UapsdEnable; + bool fwdWPSPBCProbeReq; + /* 0 - disabled, 1 - not configured , 2 - configured */ + uint8_t wps_state; + uint16_t ht_capab; + uint16_t RSNWPAReqIELength; /* The byte count in the pWPAReqIE */ + uint32_t beacon_int; /* Beacon Interval */ + uint32_t ap_table_max_size; + uint32_t ap_table_expiration_time; + uint32_t ht_op_mode_fixed; + tCDF_CON_MODE persona; /* Tells us which persona its GO or AP for now */ + uint8_t disableDFSChSwitch; + bool enOverLapCh; +#ifdef WLAN_FEATURE_11W + bool mfpRequired; + bool mfpCapable; +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + struct sap_acs_cfg acs_cfg; + uint16_t probeRespIEsBufferLen; + /* buffer for addn ies comes from hostapd */ + void *pProbeRespIEsBuffer; + uint16_t assocRespIEsLen; + /* buffer for addn ies comes from hostapd */ + void *pAssocRespIEsBuffer; + uint16_t probeRespBcnIEsLen; + /* buffer for addn ies comes from hostapd */ + void *pProbeRespBcnIEsBuffer; + 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 { + uint8_t num_name; + uint8_t name[MAX_NAME_SIZE]; +} tSapName; + +typedef struct sSapText { + uint8_t num_text; + uint8_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 { + uint8_t dfs_channel_number; + eSapDfsChanStatus_t radar_status_flag; + uint64_t radar_found_timestamp; +} tSapDfsNolInfo; + +typedef struct sSapDfsInfo { + cdf_mc_timer_t sap_dfs_cac_timer; + uint8_t sap_radar_found_status; + /* + * New channel to move to when a Radar is + * detected on current Channel + */ + uint8_t target_channel; + uint8_t last_radar_found_channel; + uint8_t ignore_cac; + eSapDfsCACState_t cac_state; + uint8_t user_provided_target_channel; + + /* + * Requests for Channel Switch Announcement IE + * generation and transmission + */ + uint8_t csaIERequired; + uint8_t numCurrentRegDomainDfsChannels; + tSapDfsNolInfo sapDfsChannelNolList[NUM_5GHZ_CHANNELS]; + uint8_t is_dfs_cac_timer_running; + /* + * New channel width and new channel bonding mode + * will only be updated via channel fallback mechanism + */ + uint8_t orig_cbMode; + uint8_t orig_chanWidth; + uint8_t new_chanWidth; + uint8_t new_cbMode; + + /* + * INI param to enable/disable SAP W53 + * channel operation. + */ + uint8_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. + */ + uint8_t sap_operating_chan_preferred_location; + + /* + * Flag to indicate if DFS test mode is enabled and + * channel switch is disabled. + */ + uint8_t disable_dfs_ch_switch; +} tSapDfsInfo; + +typedef struct tagSapCtxList { + uint8_t sessionID; + void *pSapContext; + tCDF_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 { + uint32_t FieldPresent; + uint32_t Version; /* Version. 0x10 = version 1.0, 0x11 = etc. */ + uint32_t wpsState; /* 1 = unconfigured, 2 = configured. */ + bool APSetupLocked; /* Must be included if value is true */ + /* indicates if user has recently activated a reg to add an Enrollee. */ + bool SelectedRegistra; + uint16_t DevicePasswordID; /* Device Password ID */ + /* Selected Registrar config method */ + uint16_t SelectedRegistraCfgMethod; + uint8_t ResponseType; /* Response type */ + uint8_t UUID_E[16]; /* Unique identifier of the AP. */ + tSapName Manufacture; + tSapText ModelName; + tSapText ModelNumber; + tSapText SerialNumber; + /* Device Category ID: 1Computer, 2Input Device, ... */ + uint32_t PrimaryDeviceCategory; + /* Vendor specific OUI for Device Sub Category */ + uint8_t PrimaryDeviceOUI[4]; + /* + * Device Sub Category ID: 1-PC, + * 2-Server if Device Category is computer + */ + uint32_t DeviceSubCategory; + tSapText DeviceName; + uint16_t ConfigMethod; /* Configuaration method */ + uint8_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 { + uint32_t FieldPresent; + uint32_t Version; /* Version. 0x10 = version 1.0, 0x11 = etc. */ + uint32_t wpsState; /* 1 = unconfigured, 2 = configured. */ + bool APSetupLocked; /* Must be included if value is true */ + /* indicates if user has recently activated a reg to add an Enrollee. */ + bool SelectedRegistra; + uint16_t DevicePasswordID; /* Device Password ID */ + uint16_t SelectedRegistraCfgMethod; /* Selected reg config method */ + uint8_t UUID_E[16]; /* Unique identifier of the AP. */ + uint8_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 { + uint32_t FieldPresent; + uint32_t Version; + uint8_t ResposeType; +} tSap_WPSAssocRspIE; + +typedef struct sap_WPSIE_s { + eSapWPSIE_CODE sapWPSIECode; + union { + tSap_WPSProbeRspIE sapWPSProbeRspIE; /* WPS Set Probe Resp IE */ + tSap_WPSBeaconIE sapWPSBeaconIE; /* WPS Set Beacon IE */ + tSap_WPSAssocRspIE sapWPSAssocRspIE; /* WPS Set Assoc Resp 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 { + uint32_t txUCFcnt; + uint32_t txMCFcnt; + uint32_t txBCFcnt; + uint32_t txUCBcnt; + uint32_t txMCBcnt; + uint32_t txBCBcnt; + uint32_t rxUCFcnt; + uint32_t rxMCFcnt; + uint32_t rxBCFcnt; + uint32_t rxUCBcnt; + uint32_t rxMCBcnt; + uint32_t rxBCBcnt; + uint32_t rxBcnt; + uint32_t rxBcntCRCok; + uint32_t rxRate; +#ifdef WLANTL_DEBUG + uint32_t pktCounterRateIdx[MAX_RATE_INDEX]; + uint32_t pktCounterRssi[MAX_NUM_RSSI]; +#endif +} tSap_SoftapStats, *tpSap_SoftapStats; +/* Channel/Frequency table */ +extern const tRfChannelProps rf_channels[NUM_RF_CHANNELS]; +#ifdef FEATURE_WLAN_CH_AVOID +/* Store channel safety information */ +typedef struct { + uint16_t channelNumber; + bool isSafe; +} sapSafeChannelType; +#endif /* FEATURE_WLAN_CH_AVOID */ +#ifdef WLAN_FEATURE_MBSSID +void sap_cleanup_channel_list(void *sapContext); +#else +void sap_cleanup_channel_list(void); +#endif +void sapCleanupAllChannelList(void); +CDF_STATUS wlansap_set_wps_ie(void *p_cds_gctx, tSap_WPSIE *pWPSIe); +CDF_STATUS wlansap_update_wps_ie(void *p_cds_gctx); +CDF_STATUS wlansap_stop_Wps(void *p_cds_gctx); +CDF_STATUS wlansap_get_wps_state(void *p_cds_gctx, bool *pbWPSState); + +#ifdef WLAN_FEATURE_MBSSID +void * +#else +CDF_STATUS +#endif +wlansap_open(void *p_cds_gctx); +CDF_STATUS wlansap_start(void *p_cds_gctx); +CDF_STATUS wlansap_stop(void *p_cds_gctx); +CDF_STATUS wlansap_close(void *p_cds_gctx); +typedef CDF_STATUS (*tpWLAN_SAPEventCB)(tpSap_Event pSapEvent, + void *pUsrContext); +uint8_t wlansap_get_state(void *p_cds_gctx); + +CDF_STATUS wlansap_start_bss(void *p_cds_gctx, + tpWLAN_SAPEventCB pSapEventCallback, + tsap_Config_t *pConfig, void *pUsrContext); + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +uint16_t wlansap_check_cc_intf(void *Ctx); +#endif +CDF_STATUS wlansap_set_mac_acl(void *p_cds_gctx, tsap_Config_t *pConfig); +CDF_STATUS wlansap_stop_bss(void *p_cds_gctx); +CDF_STATUS wlansap_disassoc_sta(void *p_cds_gctx, + const uint8_t *pPeerStaMac); +CDF_STATUS wlansap_deauth_sta(void *p_cds_gctx, + struct tagCsrDelStaParams *pDelStaParams); +CDF_STATUS wlansap_set_channel_change_with_csa(void *p_cds_gctx, + uint32_t targetChannel); +CDF_STATUS wlansap_set_key_sta(void *p_cds_gctx, + tCsrRoamSetKey *pSetKeyInfo); +CDF_STATUS wlansap_get_assoc_stations(void *p_cds_gctx, + CDF_MODULE_ID module, tpSap_AssocMacAddr pAssocStas); +CDF_STATUS wlansap_remove_wps_session_overlap(void *p_cds_gctx, + struct cdf_mac_addr pRemoveMac); +CDF_STATUS wlansap_get_wps_session_overlap(void *p_cds_gctx); +CDF_STATUS wlansap_set_counter_measure(void *p_cds_gctx, bool bEnable); +CDF_STATUS wlan_sap_getstation_ie_information(void *p_cds_gctx, + uint32_t *pLen, uint8_t *pBuf); +CDF_STATUS wlansap_clear_acl(void *p_cds_gctx); +CDF_STATUS wlansap_get_acl_accept_list(void *p_cds_gctx, + struct cdf_mac_addr *pAcceptList, uint8_t *nAcceptList); +CDF_STATUS wlansap_get_acl_deny_list(void *pCtx, + struct cdf_mac_addr *pDenyList, uint8_t *nDenyList); +CDF_STATUS wlansap_set_mode(void *p_cds_gctx, uint32_t mode); +CDF_STATUS wlansap_get_acl_mode(void *p_cds_gctx, eSapMacAddrACL *mode); +CDF_STATUS wlansap_modify_acl(void *p_cds_gctx, + uint8_t *pPeerStaMac, eSapACLType listType, eSapACLCmdType cmd); +CDF_STATUS wlansap_set_wparsn_ies + (void *p_cds_gctx, uint8_t *pWPARSNIEs, uint32_t WPARSNIEsLen); +CDF_STATUS wlansap_send_action + (void *p_cds_gctx, + const uint8_t *pBuf, uint32_t len, uint16_t wait, uint16_t channel_freq); +CDF_STATUS wlansap_remain_on_channel + (void *p_cds_gctx, + uint8_t channel, + uint32_t duration, remainOnChanCallback callback, void *pContext, + uint32_t *scan_id); +CDF_STATUS wlansap_cancel_remain_on_channel(void *p_cds_gctx, + uint32_t scan_id); +CDF_STATUS wlansap_register_mgmt_frame + (void *p_cds_gctx, + uint16_t frameType, uint8_t *matchData, uint16_t matchLen); +CDF_STATUS wlansap_de_register_mgmt_frame + (void *p_cds_gctx, + uint16_t frameType, uint8_t *matchData, uint16_t matchLen); +CDF_STATUS wlansap_channel_change_request(void *p_cds_gctx, + uint8_t tArgetChannel); +CDF_STATUS wlansap_start_beacon_req(void *pSapCtx); +CDF_STATUS wlansap_dfs_send_csa_ie_request(void *pSapCtx); +CDF_STATUS wlansap_get_dfs_ignore_cac(tHalHandle hHal, uint8_t *pIgnore_cac); +CDF_STATUS wlansap_set_dfs_ignore_cac(tHalHandle hHal, uint8_t ignore_cac); +CDF_STATUS wlansap_set_dfs_restrict_japan_w53(tHalHandle hHal, + uint8_t disable_Dfs_JapanW3); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +CDF_STATUS +wlan_sap_set_channel_avoidance(tHalHandle hal, bool sap_channel_avoidance); +#endif + +CDF_STATUS wlansap_set_dfs_preferred_channel_location(tHalHandle hHal, + uint8_t dfs_Preferred_Channels_location); +CDF_STATUS wlansap_set_dfs_target_chnl(tHalHandle hHal, + uint8_t target_channel); +uint32_t wlan_sap_get_vht_ch_width(void *ctx); +void wlan_sap_set_vht_ch_width(void *ctx, uint32_t vht_channel_width); +CDF_STATUS wlansap_update_sap_config_add_ie(tsap_Config_t *pConfig, + const uint8_t * + pAdditionIEBuffer, + uint16_t additionIELength, + eUpdateIEsType updateType); +CDF_STATUS wlansap_reset_sap_config_add_ie(tsap_Config_t *pConfig, + eUpdateIEsType updateType); +void wlansap_extend_to_acs_range(uint8_t *startChannelNum, + uint8_t *endChannelNum, + uint8_t *bandStartChannel, + uint8_t *bandEndChannel); +CDF_STATUS wlansap_get_dfs_nol(void *pSapCtx); +CDF_STATUS wlansap_set_dfs_nol(void *pSapCtx, eSapDfsNolType conf); +void wlansap_populate_del_sta_params(const uint8_t *mac, + uint16_t reason_code, + uint8_t subtype, + struct tagCsrDelStaParams *pDelStaParams); +CDF_STATUS wlansap_acs_chselect(void *pvos_gctx, + tpWLAN_SAPEventCB pacs_event_callback, + tsap_Config_t *pconfig, + void *pusr_context); +#ifdef __cplusplus +} +#endif +#endif /* #ifndef WLAN_QCT_WLANSAP_H */ diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c new file mode 100644 index 000000000000..4ea65dcec7ed --- /dev/null +++ b/core/sap/src/sap_api_link_cntl.c @@ -0,0 +1,1209 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p A p i L i n k C n t l . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + Link Control functions. + + The functions externalized by this module are to be called ONLY by other + WLAN modules (HDD) + + DEPENDENCIES: + + Are listed for each API below. + ===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "cdf_trace.h" +/* Pick up the CSR callback definition */ +#include "csr_api.h" +#include "sme_api.h" +/* SAP Internal API header file */ +#include "sap_internal.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 + * -------------------------------------------------------------------------*/ + +/* + * wlansap_scan_callback() - Callback for Scan (scan results) Events + * + * @hal_handle : tHalHandle passed in with the scan request + * @ctx : The second context pass in for the caller (sapContext) + * @scanID : scanID got after the scan + * + * Callback for Scan (scan results) Events + * + * Return: Status + */ +CDF_STATUS wlansap_scan_callback(tHalHandle hal_handle, + void *ctx, /* Opaque SAP handle */ + uint8_t session_id, + uint32_t scan_id, eCsrScanStatus scan_status) { + tScanResultHandle result = NULL; + CDF_STATUS get_result_status = CDF_STATUS_E_FAILURE; + ptSapContext sap_ctx = (ptSapContext) ctx; + tWLAN_SAPEvent sapEvent; /* State machine event */ + uint8_t operChannel = 0; + CDF_STATUS sap_sm_status; + +#ifdef SOFTAP_CHANNEL_RANGE + uint32_t event; +#endif + + if (NULL == hal_handle) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return CDF_STATUS_E_FAILURE; + } + if (sap_ctx->sapsMachine == eSAP_DISCONNECTED) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + "In %s BSS already stopped", __func__); + return CDF_STATUS_E_FAILURE; + } + + switch (scan_status) { + case eCSR_SCAN_SUCCESS: + /* sapScanCompleteCallback with eCSR_SCAN_SUCCESS */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, CSR scanStatus = %s (%d)", __func__, + "eCSR_SCAN_SUCCESS", scan_status); + + /** + * Get scan results, Run channel selection algorithm, + * select channel and keep in sap_ctx->Channel + */ + get_result_status = + sme_scan_get_result(hal_handle, sap_ctx->sessionId, NULL, + &result); + + event = eSAP_MAC_SCAN_COMPLETE; + + if ((get_result_status != CDF_STATUS_SUCCESS) + && (get_result_status != CDF_STATUS_E_NULL_VALUE)) { + /* No scan results */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s, Get scan result failed! ret = %d", + __func__, get_result_status); + break; + } +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (scan_id != 0) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Sending ACS Scan skip event", __func__); + sap_signal_hdd_event(sap_ctx, NULL, + eSAP_ACS_SCAN_SUCCESS_EVENT, + (void *) eSAP_STATUS_SUCCESS); + } else + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: ACS scan id: %d (skipped ACS SCAN)", + __func__, scan_id); +#endif + operChannel = sap_select_channel(hal_handle, sap_ctx, result); + + sme_scan_result_purge(hal_handle, result); + break; + + default: + event = eSAP_CHANNEL_SELECTION_FAILED; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, CSR scanStatus = %s (%d)", __func__, + "eCSR_SCAN_ABORT/FAILURE", scan_status); + } + + if (operChannel == SAP_CHANNEL_NOT_SELECTED) +#ifdef SOFTAP_CHANNEL_RANGE + { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: No suitable channel selected due to DFS, LTE" + "COEX and concurrent mode restrictions", __func__); + + sap_ctx->sapsMachine = eSAP_CH_SELECT; + event = eSAP_CHANNEL_SELECTION_FAILED; + } +#else + sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#endif + else { + sap_ctx->channel = operChannel; + } + + sap_ctx->ch_params.ch_width = sap_ctx->acs_cfg->ch_width; + sme_set_ch_params(hal_handle, + sap_ctx->csr_roamProfile.phyMode, + sap_ctx->channel, + sap_ctx->secondary_ch, + &sap_ctx->ch_params); +#ifdef SOFTAP_CHANNEL_RANGE + if (sap_ctx->channelList != NULL) { + /* Always free up the memory for channel selection whatever + * the result */ + cdf_mem_free(sap_ctx->channelList); + sap_ctx->channelList = NULL; + } +#endif + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Channel selected = %d", __func__, + sap_ctx->channel); + + /* Fill in the event structure */ + sapEvent.event = event; + /* pCsrRoamInfo; */ + sapEvent.params = 0; + /* roamstatus */ + sapEvent.u1 = scan_status; + /* roamResult */ + sapEvent.u2 = 0; + + /* Handle event */ + sap_sm_status = sap_fsm(sap_ctx, &sapEvent); + + return sap_sm_status; +} /* wlansap_scan_callback */ + + +/** + * 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; + chan_params_t ch_params = {0}; + + ch_params.ch_width = sap_ctx->acs_cfg->ch_width; + sme_set_ch_params(hal, sap_ctx->csr_roamProfile.phyMode, channel, + sec_ch, &ch_params); + + sap_ctx->acs_cfg->ch_width = ch_params.ch_width; + if (sap_ctx->acs_cfg->ch_width > CH_WIDTH_40MHZ) + sap_ctx->acs_cfg->vht_seg0_center_ch = + ch_params.center_freq_seg0; + else + sap_ctx->acs_cfg->vht_seg0_center_ch = 0; + + if (sap_ctx->acs_cfg->ch_width == CH_WIDTH_80P80MHZ) + sap_ctx->acs_cfg->vht_seg1_center_ch = + ch_params.center_freq_seg1; + else + sap_ctx->acs_cfg->vht_seg1_center_ch = 0; + + if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch - 4; + else if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) + sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch + 4; + else + sap_ctx->acs_cfg->ht_sec_ch = 0; +} + +/** + * sap_hdd_signal_event_handler() - routine to inform hostapd via callback + * + * ctx: pointer to sap context which was passed to callback + * + * this routine will be registered as callback to sme_close_session, so upon + * closure of sap session it notifies the hostapd + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_hdd_signal_event_handler(void *ctx) +{ + ptSapContext sap_ctx = (struct sSapContext *)ctx; + CDF_STATUS status; + if (NULL == sap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("sap context is not valid")); + return CDF_STATUS_E_FAILURE; + } + status = sap_signal_hdd_event(sap_ctx, NULL, + sap_ctx->sap_state, + (void *) sap_ctx->sap_status); + return status; +} + +/** + * + * wlansap_pre_start_bss_acs_scan_callback() - callback for scan results + * + * hal_handle: the hal_handle passed in with the scan request + * pcontext: the second context pass in for the caller, opaque sap Handle. + * scanid: scan id passed + * sessionid: session identifier + * status: status of scan -success, failure or abort + * + * Api for scan callback. This function is invoked as a result of scan + * completion and reports the scan results. + * + * Return: The CDF_STATUS code associated with performing the operation + */ +CDF_STATUS +wlansap_pre_start_bss_acs_scan_callback(tHalHandle hal_handle, void *pcontext, + uint8_t sessionid, uint32_t scanid, + eCsrScanStatus scan_status) +{ + tScanResultHandle presult = NULL; + CDF_STATUS scan_get_result_status = CDF_STATUS_E_FAILURE; + ptSapContext sap_ctx = (ptSapContext)pcontext; + uint8_t oper_channel = 0; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (eCSR_SCAN_SUCCESS != scan_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CSR scan_status = eCSR_SCAN_ABORT/FAILURE (%d), choose default channel"), + scan_status); +#ifdef SOFTAP_CHANNEL_RANGE + if (sap_ctx->acs_cfg->hw_mode == eCSR_DOT11_MODE_11a) + sap_ctx->channel = SAP_DEFAULT_5GHZ_CHANNEL; + else + sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#else + sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL; +#endif + sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED; + sap_ctx->sap_status = eSAP_STATUS_SUCCESS; + goto close_session; + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR scan_status = eCSR_SCAN_SUCCESS (%d)"), scan_status); + /* + * Now do + * 1. Get scan results + * 2. Run channel selection algorithm + * select channel and store in pSapContext->Channel + */ + scan_get_result_status = sme_scan_get_result(hal_handle, + sap_ctx->sessionId, + NULL, &presult); + if ((scan_get_result_status != CDF_STATUS_SUCCESS) && + (scan_get_result_status != CDF_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 + */ + oper_channel = SAP_CHANNEL_NOT_SELECTED; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Get scan result failed! ret = %d"), + scan_get_result_status); + } else { +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (scanid != 0) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Sending ACS Scan skip event")); + sap_signal_hdd_event(sap_ctx, NULL, + eSAP_ACS_SCAN_SUCCESS_EVENT, + (void *) eSAP_STATUS_SUCCESS); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("ACS scanid: %d (skipped ACS SCAN)"), + scanid); + } +#endif + oper_channel = sap_select_channel(hal_handle, sap_ctx, presult); + sme_scan_result_purge(hal_handle, presult); + } + + if (oper_channel == SAP_CHANNEL_NOT_SELECTED) { +#ifdef SOFTAP_CHANNEL_RANGE + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("No suitable channel selected")); + + sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED; + sap_ctx->sap_status = eSAP_STATUS_FAILURE; + goto close_session; + } else { +#else + sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL; + } else { +#endif + /* Valid Channel Found from scan results. */ + sap_ctx->acs_cfg->pri_ch = oper_channel; + sap_ctx->channel = oper_channel; + } + sap_config_acs_result(hal_handle, sap_ctx, + sap_ctx->acs_cfg->ht_sec_ch); + +#ifdef SOFTAP_CHANNEL_RANGE + if (sap_ctx->channelList != NULL) { + /* + * Always free up the memory for + * channel selection whatever + * the result + */ + cdf_mem_free(sap_ctx->channelList); + sap_ctx->channelList = NULL; + } +#endif + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Channel selected = %d"), sap_ctx->channel); + sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED; + sap_ctx->sap_status = eSAP_STATUS_SUCCESS; +close_session: + status = sme_close_session(hal_handle, + sap_ctx->sessionId, sap_hdd_signal_event_handler, + sap_ctx); + if (CDF_STATUS_SUCCESS != status) + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CloseSession failed")); + else + sap_ctx->isScanSessionOpen = eSAP_FALSE; + sap_ctx->sessionId = 0xff; + return status; +} + +/** + * wlansap_roam_process_ch_change_success() - handles the case for + * eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS in function wlansap_roam_callback() + * + * @mac_ctx: mac global context + * @sap_ctx: sap context + * @csr_roam_info: raom info struct + * @ret_status: update return status + * + * Return: void + */ +static void +wlansap_roam_process_ch_change_success(tpAniSirGlobal mac_ctx, + ptSapContext sap_ctx, + tCsrRoamInfo *csr_roam_info, + CDF_STATUS *ret_status) +{ + tWLAN_SAPEvent sap_event; + CDF_STATUS cdf_status; + /* + * Channel change is successful. If the new channel is a DFS channel, + * then we will to perform channel availability check for 60 seconds + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: changing target channel to [%d]"), + mac_ctx->sap.SapDfsInfo.target_channel); + sap_ctx->channel = mac_ctx->sap.SapDfsInfo.target_channel; + /* Identify if this is channel change in radar detected state */ + if (eSAP_DISCONNECTING != sap_ctx->sapsMachine) + return; + + /* check if currently selected channel is a DFS channel */ + if (CHANNEL_STATE_DFS == cds_get_channel_state(sap_ctx->channel)) { + if ((false == mac_ctx->sap.SapDfsInfo.ignore_cac) + && (eSAP_DFS_DO_NOT_SKIP_CAC == + mac_ctx->sap.SapDfsInfo.cac_state)) { + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: from state eSAP_DISCONNECTING => DISCONNECTED with ignore cac false on sapctx[%p]"), + sap_ctx); + /* DFS Channel */ + sap_event.event = eSAP_DFS_CHANNEL_CAC_START; + sap_event.params = csr_roam_info; + sap_event.u1 = 0; + sap_event.u2 = 0; + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING with ignore cac true on sapctx[%p]"), + sap_ctx); + + /* Start beaconing on the new channel */ + wlansap_start_beacon_req(sap_ctx); + sap_ctx->sapsMachine = eSAP_STARTING; + mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false; + sap_event.event = eSAP_MAC_START_BSS_SUCCESS; + sap_event.params = csr_roam_info; + sap_event.u1 = eCSR_ROAM_INFRA_IND; + sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING on sapctx[%p]"), + sap_ctx); + /* non-DFS channel */ + sap_ctx->sapsMachine = eSAP_STARTING; + mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false; + sap_event.event = eSAP_MAC_START_BSS_SUCCESS; + sap_event.params = csr_roam_info; + sap_event.u1 = eCSR_ROAM_INFRA_IND; + sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED; + } + + /* Handle the event */ + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + *ret_status = CDF_STATUS_E_FAILURE; +} + +/** + * wlansap_roam_process_dfs_chansw_update_fail() - handles the case for + * eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE in wlansap_roam_callback() + * + * @hal: hal global context + * @sap_ctx: sap context + * @ret_status: update return status + * + * Return: void + */ +static void +wlansap_roam_process_dfs_chansw_update_fail(tHalHandle hHal, + ptSapContext sap_ctx, + CDF_STATUS *ret_status) +{ + tWLAN_SAPEvent sap_event; + uint8_t intf; + CDF_STATUS cdf_status; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal); + eCsrPhyMode phy_mode = sap_ctx->csr_roamProfile.phyMode; + uint8_t dfs_beacon_start_req = 0; + + if (sap_ctx->csr_roamProfile.disableDFSChSwitch) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("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 = eSAP_TRUE; + *ret_status = sme_roam_start_beacon_req(hHal, sap_ctx->bssid, + dfs_beacon_start_req); + return; + } + /* + * 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 != sap_ctx->sapsMachine) { + /* Further actions to be taken here */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state\n"), + sap_ctx->sapsMachine); + return; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: from state eSAP_STARTED => eSAP_DISCONNECTING")); + /* SAP to be moved to DISCONNECTING state */ + sap_ctx->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 (mac_ctx->sap.SapDfsInfo.target_channel) + sme_set_ch_params(hHal, phy_mode, + mac_ctx->sap.SapDfsInfo.target_channel, 0, + &sap_ctx->ch_params); + /* + * 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) { + /* Send channel switch request */ + sap_event.event = eWNI_SME_CHANNEL_CHANGE_REQ; + sap_event.params = 0; + sap_event.u1 = 0; + sap_event.u2 = 0; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: Posting event eWNI_SME_CHANNEL_CHANGE_REQ to sapFSM")); + /* Handle event */ + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + *ret_status = CDF_STATUS_E_FAILURE; + return; + } + + sap_ctx->is_sap_ready_for_chnl_chng = 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 (false == + is_concurrent_sap_ready_for_channel_change(hHal, sap_ctx)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: sapctx[%p] ready but not concurrent sap"), + sap_ctx); + *ret_status = CDF_STATUS_SUCCESS; + return; + } + + /* Issue channel change req for each sapctx */ + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + ptSapContext pSapContext; + if (!((CDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona) + && (mac_ctx->sap.sapCtxList[intf].pSapContext != NULL))) + continue; + + pSapContext = mac_ctx->sap.sapCtxList[intf].pSapContext; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs:issue chnl change for sapctx[%p]"), + pSapContext); + /* Send channel switch request */ + sap_event.event = eWNI_SME_CHANNEL_CHANGE_REQ; + sap_event.params = 0; + sap_event.u1 = 0; + sap_event.u2 = 0; + /* Handle event */ + cdf_status = sap_fsm(pSapContext, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("post chnl chng req failed, sap[%p]"), + sap_ctx); + *ret_status = CDF_STATUS_E_FAILURE; + } else { + pSapContext->is_sap_ready_for_chnl_chng = false; + } + } + return; +} + +/** + * wlansap_roam_process_dfs_radar_found() - handles the case for + * eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND in wlansap_roam_callback() + * + * @mac_ctx: mac global context + * @sap_ctx: sap context + * @ret_status: update return status + * + * Return: result of operation + */ +static void +wlansap_roam_process_dfs_radar_found(tpAniSirGlobal mac_ctx, + ptSapContext sap_ctx, + CDF_STATUS *ret_status) +{ + CDF_STATUS cdf_status; + tWLAN_SAPEvent sap_event; + if (eSAP_DFS_CAC_WAIT == sap_ctx->sapsMachine) { + if (sap_ctx->csr_roamProfile.disableDFSChSwitch) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "sapdfs: DFS channel switch disabled"); + return; + } + if (false == mac_ctx->sap.SapDfsInfo.sap_radar_found_status) + return; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_MED, + FL("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. + */ + cdf_mc_timer_stop(&mac_ctx->sap.SapDfsInfo.sap_dfs_cac_timer); + cdf_mc_timer_destroy(&mac_ctx->sap.SapDfsInfo.sap_dfs_cac_timer); + + /* + * User space is already indicated the CAC start and if + * CAC end on this channel is not indicated, the user + * space will be in some undefined state (e.g., UI frozen) + */ + cdf_status = sap_signal_hdd_event(sap_ctx, NULL, + eSAP_DFS_CAC_INTERRUPTED, + (void *) eSAP_STATUS_SUCCESS); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 + */ + } + + mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + sap_event.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND; + sap_event.params = 0; + sap_event.u1 = 0; + sap_event.u2 = 0; + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + *ret_status = CDF_STATUS_E_FAILURE; + return; + } + if (eSAP_STARTED == sap_ctx->sapsMachine) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("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 + */ + sap_event.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START; + sap_event.params = 0; + sap_event.u1 = 0; + sap_event.u2 = 0; + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + *ret_status = CDF_STATUS_E_FAILURE; + return; + } + /* Further actions to be taken here */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state\n"), + sap_ctx->sapsMachine); + + return; +} + +/** + * wlansap_roam_process_infra_assoc_ind() - handles the case for + * eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND in wlansap_roam_callback() + * + * @sap_ctx: sap context + * @roam_result: roam result + * @csr_roam_info: roam info struct + * @ret_status: update return status + * + * Return: result of operation + */ +static void +wlansap_roam_process_infra_assoc_ind(ptSapContext sap_ctx, + eCsrRoamResult roam_result, + tCsrRoamInfo *csr_roam_info, + CDF_STATUS *ret_status) +{ + CDF_STATUS cdf_status; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND (%d)\n"), + roam_result); + sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen; + if (sap_ctx->nStaWPARSnReqIeLength) + cdf_mem_copy(sap_ctx->pStaWpaRsnReqIE, csr_roam_info->prsnIE, + sap_ctx->nStaWPARSnReqIeLength); +#ifdef FEATURE_WLAN_WAPI + sap_ctx->nStaWAPIReqIeLength = csr_roam_info->wapiIELen; + if (sap_ctx->nStaWAPIReqIeLength) + cdf_mem_copy(sap_ctx->pStaWapiReqIE, csr_roam_info->pwapiIE, + sap_ctx->nStaWAPIReqIeLength); +#endif + sap_ctx->nStaAddIeLength = csr_roam_info->addIELen; + if (sap_ctx->nStaAddIeLength) + cdf_mem_copy(sap_ctx->pStaAddIE, csr_roam_info->paddIE, + sap_ctx->nStaAddIeLength); + sap_ctx->SapQosCfg.WmmIsEnabled = csr_roam_info->wmmEnabledSta; + /* MAC filtering */ + cdf_status = sap_is_peer_mac_allowed(sap_ctx, + (uint8_t *) csr_roam_info->peerMac.bytes); + + if (CDF_STATUS_SUCCESS == cdf_status) { + cdf_status = sap_signal_hdd_event(sap_ctx, + csr_roam_info, eSAP_STA_ASSOC_IND, + (void *) eSAP_STATUS_SUCCESS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CSR roam_result = (%d) MAC ("MAC_ADDRESS_STR") fail"), + roam_result, MAC_ADDR_ARRAY( + csr_roam_info->peerMac.bytes)); + *ret_status = CDF_STATUS_E_FAILURE; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + FL("CSR roam_result = (%d) MAC ("MAC_ADDRESS_STR") not allowed"), + roam_result, + MAC_ADDR_ARRAY(csr_roam_info->peerMac.bytes)); + *ret_status = CDF_STATUS_E_FAILURE; + } + return; +} + +/** + * wlansap_roam_callback() - Callback for Roam (connection status) Events + * @ctx : pContext passed in with the roam request + * @csr_roam_info : Pointer to a tCsrRoamInfo + * @roamId : to identify the callback related roam request. + * 0 means unsolicit + * @roam_status : Flag indicating the status of the callback + * @roam_result : Result + * + * This function finds dot11 mode based on current mode, operating channel and + * fw supported modes. + * + * Return: Status of operation + */ +CDF_STATUS +wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, + eRoamCmdStatus roam_status, eCsrRoamResult roam_result) +{ + /* sap_ctx value */ + ptSapContext sap_ctx = (ptSapContext) ctx; + /* State machine event */ + tWLAN_SAPEvent sap_event; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx); + tpAniSirGlobal mac_ctx = NULL; + uint8_t intf; + + if (NULL == hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid hal")); + cdf_ret_status = CDF_STATUS_E_NOMEM; + return cdf_ret_status; + } + + mac_ctx = PMAC_STRUCT(hal); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Before switch on roam_status = %d\n"), roam_status); + switch (roam_status) { + case eCSR_ROAM_SESSION_OPENED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Calling sme_roam_connect with eCSR_BSS_TYPE_INFRA_AP")); + sap_ctx->isSapSessionOpen = eSAP_TRUE; + cdf_ret_status = sme_roam_connect(hal, sap_ctx->sessionId, + &sap_ctx->csr_roamProfile, + &sap_ctx->csr_roamId); + break; + case eCSR_ROAM_INFRA_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_INFRA_IND (%d)\n"), + roam_status); + if (roam_result == eCSR_ROAM_RESULT_INFRA_START_FAILED) { + /* Fill in the event structure */ + sap_event.event = eSAP_MAC_START_FAILS; + sap_event.params = csr_roam_info; + sap_event.u1 = roam_status; + sap_event.u2 = roam_result; + /* Handle event */ + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case eCSR_ROAM_LOSTLINK: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_LOSTLINK (%d)\n"), + roam_status); + break; + case eCSR_ROAM_MIC_ERROR_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_MIC_ERROR_IND (%d)\n"), + roam_status); + break; + case eCSR_ROAM_SET_KEY_COMPLETE: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_SET_KEY_COMPLETE (%d)\n"), + roam_status); + if (roam_result == eCSR_ROAM_RESULT_FAILURE) + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_SET_KEY_EVENT, + (void *) eSAP_STATUS_FAILURE); + break; + case eCSR_ROAM_ASSOCIATION_COMPLETION: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_ASSOCIATION_COMPLETION (%d)\n"), + roam_status); + if (roam_result == eCSR_ROAM_RESULT_FAILURE) + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_REASSOC_EVENT, + (void *) eSAP_STATUS_FAILURE); + break; + case eCSR_ROAM_DISASSOCIATED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_DISASSOCIATED (%d)\n"), + roam_status); + if (roam_result == eCSR_ROAM_RESULT_MIC_FAILURE) + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_MIC_FAILURE_EVENT, + (void *) eSAP_STATUS_FAILURE); + break; + case eCSR_ROAM_WPS_PBC_PROBE_REQ_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_status = eCSR_ROAM_WPS_PBC_PROBE_REQ_IND (%d)\n"), + roam_status); + break; + case eCSR_ROAM_INDICATE_MGMT_FRAME: + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_INDICATE_MGMT_FRAME, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_REMAIN_CHAN_READY: + /* roamId contains scan identifier */ + sap_ctx->roc_ind_scan_id = csr_roam_info->roc_scan_id; + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_REMAIN_CHAN_READY, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_SEND_ACTION_CNF: + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_SEND_ACTION_CNF, + (void *) ((eSapStatus) + ((roam_result == eCSR_ROAM_RESULT_NONE) ? + eSAP_STATUS_SUCCESS : eSAP_STATUS_FAILURE))); + break; + case eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS: + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_DISCONNECT_ALL_P2P_CLIENT, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_SEND_P2P_STOP_BSS: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Received stopbss")); + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_MAC_TRIG_STOP_BSS_EVENT, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_DFS_RADAR_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Received Radar Indication")); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: Indicate eSAP_DFS_RADAR_DETECT to HDD")); + sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_RADAR_DETECT, + (void *) eSAP_STATUS_SUCCESS); + /* sync to latest DFS-NOL */ + sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_NOL_GET, + (void *) eSAP_STATUS_SUCCESS); + mac_ctx->sap.SapDfsInfo.target_channel = + sap_indicate_radar(sap_ctx, &csr_roam_info->dfs_event); + /* if there is an assigned next channel hopping */ + if (0 < mac_ctx->sap.SapDfsInfo.user_provided_target_channel) { + mac_ctx->sap.SapDfsInfo.target_channel = + mac_ctx->sap.SapDfsInfo.user_provided_target_channel; + mac_ctx->sap.SapDfsInfo.user_provided_target_channel = + 0; + } + if (mac_ctx->sap.SapDfsInfo.target_channel != 0) { + mac_ctx->sap.SapDfsInfo.cac_state = + eSAP_DFS_DO_NOT_SKIP_CAC; + sap_cac_reset_notify(hal); + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_NOL_SET, + (void *) eSAP_STATUS_SUCCESS); + break; + } + /* Issue stopbss for each sapctx */ + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + ptSapContext pSapContext; + if (((CDF_SAP_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona) || + (CDF_P2P_GO_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona)) && + mac_ctx->sap.sapCtxList[intf].pSapContext != + NULL) { + pSapContext = + mac_ctx->sap.sapCtxList[intf].pSapContext; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("sapdfs: no available channel for sapctx[%p], StopBss"), + pSapContext); + wlansap_stop_bss(pSapContext); + } + } + break; + case eCSR_ROAM_DFS_CHAN_SW_NOTIFY: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Received Chan Sw Update Notification")); + break; + case eCSR_ROAM_SET_CHANNEL_RSP: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Received set channel response")); + break; + default: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CSR roam_status not handled roam_status = %s (%d)\n"), + get_e_roam_cmd_status_str(roam_status), + roam_status); + break; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Before switch on roam_result = %d\n"), roam_result); + + switch (roam_result) { + case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND: + wlansap_roam_process_infra_assoc_ind(sap_ctx, roam_result, + csr_roam_info, &cdf_ret_status); + break; + case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF (%d)\n"), + roam_result); + sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen; + if (sap_ctx->nStaWPARSnReqIeLength) + cdf_mem_copy(sap_ctx->pStaWpaRsnReqIE, + csr_roam_info->prsnIE, + sap_ctx->nStaWPARSnReqIeLength); + + sap_ctx->nStaAddIeLength = csr_roam_info->addIELen; + if (sap_ctx->nStaAddIeLength) + cdf_mem_copy(sap_ctx->pStaAddIE, + csr_roam_info->paddIE, + sap_ctx->nStaAddIeLength); + + sap_ctx->SapQosCfg.WmmIsEnabled = + csr_roam_info->wmmEnabledSta; + /* Fill in the event structure */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_ASSOC_EVENT, + (void *) eSAP_STATUS_SUCCESS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_DISASSOC_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_DISASSOC_IND (%d)\n"), + roam_result); + /* Fill in the event structure */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_DISASSOC_EVENT, + (void *) eSAP_STATUS_SUCCESS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_DEAUTH_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_DEAUTH_IND (%d)\n"), + roam_result); + /* + * Fill in the event structure + * we use the same event inorder to inform HDD to disassociate + * the station + */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_DISASSOC_EVENT, + (void *) eSAP_STATUS_SUCCESS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_MIC_ERROR_GROUP: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP (%d)\n"), + roam_result); + /* + * Fill in the event structure + * TODO: support for group key MIC failure event to be handled + */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_MIC_FAILURE_EVENT, + (void *) NULL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_MIC_ERROR_UNICAST: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST (%d)\n"), + roam_result); + /* + * Fill in the event structure + * TODO: support for unicast key MIC failure event to be handled + */ + cdf_status = + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_MIC_FAILURE_EVENT, + (void *) NULL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case eCSR_ROAM_RESULT_AUTHENTICATED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_AUTHENTICATED (%d)\n"), + roam_result); + /* Fill in the event structure */ + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_SET_KEY_EVENT, + (void *) eSAP_STATUS_SUCCESS); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_ASSOCIATED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_ASSOCIATED (%d)\n"), + roam_result); + /* Fill in the event structure */ + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_REASSOC_EVENT, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_RESULT_INFRA_STARTED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_STARTED (%d)\n"), + roam_result); + /* + * 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 + */ + sap_event.event = eSAP_MAC_START_BSS_SUCCESS; + sap_event.params = csr_roam_info; + sap_event.u1 = roam_status; + sap_event.u2 = roam_result; + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_INFRA_STOPPED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_STOPPED (%d)\n"), + roam_result); + /* Fill in the event structure */ + sap_event.event = eSAP_MAC_READY_FOR_CONNECTIONS; + sap_event.params = csr_roam_info; + sap_event.u1 = roam_status; + sap_event.u2 = roam_result; + /* Handle event */ + cdf_status = sap_fsm(sap_ctx, &sap_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND (%d)\n"), + roam_result); + /* + * Fill in the event structure + * TODO: support for group key MIC failure event to be handled + */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_WPS_PBC_PROBE_REQ_EVENT, + (void *) NULL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; + case eCSR_ROAM_RESULT_FORCED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_FORCED (%d)\n"), + roam_result); + /* + * This event can be used to inform hdd about user triggered + * disassoc event + * Fill in the event structure + */ + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_DISASSOC_EVENT, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_RESULT_NONE: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_NONE (%d)\n"), + roam_result); + /* + * This event can be used to inform hdd about user triggered + * disassoc event + * Fill in the event structure + */ + if (roam_status == eCSR_ROAM_SET_KEY_COMPLETE) + sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_STA_SET_KEY_EVENT, + (void *) eSAP_STATUS_SUCCESS); + break; + case eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("CSR roam_result = eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED (%d)\n"), + roam_result); + /* Fill in the event structure */ + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_MAX_ASSOC_EXCEEDED, + NULL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + + break; + case eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND: + wlansap_roam_process_dfs_radar_found(mac_ctx, sap_ctx, + &cdf_ret_status); + break; + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS: + case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE: + wlansap_roam_process_dfs_chansw_update_fail(hal, sap_ctx, + &cdf_ret_status); + break; + case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS: + wlansap_roam_process_ch_change_success(mac_ctx, sap_ctx, + csr_roam_info, &cdf_ret_status); + 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 + */ + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + /* Inform cfg80211 and hostapd that BSS is not alive anymore */ + break; + default: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CSR roam_result = %s (%d) not handled\n"), + get_e_csr_roam_result_str(roam_result), + roam_result); + break; + } + return cdf_ret_status; +} diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c new file mode 100644 index 000000000000..cb8e89fb8bbf --- /dev/null +++ b/core/sap/src/sap_ch_select.c @@ -0,0 +1,2030 @@ +/* + * 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 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. + ===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_trace.h" +#include "csr_api.h" +#include "sme_api.h" +#include "sap_ch_select.h" +#include "sap_internal.h" +#ifdef ANI_OS_TYPE_QNX +#include "stdio.h" +#endif +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#include "lim_utils.h" +#include "parser_api.h" +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#ifdef CONFIG_CNSS +#include +#endif + +/*-------------------------------------------------------------------------- + Function definitions + --------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------- + Defines + --------------------------------------------------------------------------*/ +#define SAP_DEBUG + +#define IS_RSSI_VALID(extRssi, rssi) \ + ( \ + ((extRssi < rssi) ? true : 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 if (pSapCtx->acs_cfg->start_ch >= 14)\ + acs_band = eCSR_DOT11_MODE_11a; \ + else \ + acs_band = eCSR_DOT11_MODE_abg; \ +} + +#ifdef FEATURE_WLAN_CH_AVOID +sapSafeChannelType safe_channels[NUM_20MHZ_RF_CHANNELS] = { + /*CH , SAFE, default safe */ + {1, true} + , /* RF_CHAN_1, */ + {2, true} + , /* RF_CHAN_2, */ + {3, true} + , /* RF_CHAN_3, */ + {4, true} + , /* RF_CHAN_4, */ + {5, true} + , /* RF_CHAN_5, */ + {6, true} + , /* RF_CHAN_6, */ + {7, true} + , /* RF_CHAN_7, */ + {8, true} + , /* RF_CHAN_8, */ + {9, true} + , /* RF_CHAN_9, */ + {10, true} + , /* RF_CHAN_10, */ + {11, true} + , /* RF_CHAN_11, */ + {12, true} + , /* RF_CHAN_12, */ + {13, true} + , /* RF_CHAN_13, */ + {14, true} + , /* RF_CHAN_14, */ + {240, true} + , /* RF_CHAN_240, */ + {244, true} + , /* RF_CHAN_244, */ + {248, true} + , /* RF_CHAN_248, */ + {252, true} + , /* RF_CHAN_252, */ + {208, true} + , /* RF_CHAN_208, */ + {212, true} + , /* RF_CHAN_212, */ + {216, true} + , /* RF_CHAN_216, */ + {36, true} + , /* RF_CHAN_36, */ + {40, true} + , /* RF_CHAN_40, */ + {44, true} + , /* RF_CHAN_44, */ + {48, true} + , /* RF_CHAN_48, */ + {52, true} + , /* RF_CHAN_52, */ + {56, true} + , /* RF_CHAN_56, */ + {60, true} + , /* RF_CHAN_60, */ + {64, true} + , /* RF_CHAN_64, */ + {100, true} + , /* RF_CHAN_100, */ + {104, true} + , /* RF_CHAN_104, */ + {108, true} + , /* RF_CHAN_108, */ + {112, true} + , /* RF_CHAN_112, */ + {116, true} + , /* RF_CHAN_116, */ + {120, true} + , /* RF_CHAN_120, */ + {124, true} + , /* RF_CHAN_124, */ + {128, true} + , /* RF_CHAN_128, */ + {132, true} + , /* RF_CHAN_132, */ + {136, true} + , /* RF_CHAN_136, */ + {140, true} + , /* RF_CHAN_140, */ + {144, true} + , /* RF_CHAN_144, */ + {149, true} + , /* RF_CHAN_149, */ + {153, true} + , /* RF_CHAN_153, */ + {157, true} + , /* RF_CHAN_157, */ + {161, true} + , /* RF_CHAN_161, */ + {165, true} + , /* RF_CHAN_165, */ +}; +#endif + +typedef struct { + uint16_t chStartNum; + uint32_t weight; +} sapAcsChannelInfo; + +sapAcsChannelInfo acs_ht40_channels5_g[] = { + {36, SAP_ACS_WEIGHT_MAX}, + {44, SAP_ACS_WEIGHT_MAX}, + {52, SAP_ACS_WEIGHT_MAX}, + {60, SAP_ACS_WEIGHT_MAX}, + {100, SAP_ACS_WEIGHT_MAX}, + {108, SAP_ACS_WEIGHT_MAX}, + {116, SAP_ACS_WEIGHT_MAX}, + {124, SAP_ACS_WEIGHT_MAX}, + {132, SAP_ACS_WEIGHT_MAX}, + {140, SAP_ACS_WEIGHT_MAX}, + {149, SAP_ACS_WEIGHT_MAX}, + {157, SAP_ACS_WEIGHT_MAX}, +}; + +sapAcsChannelInfo acs_ht80_channels[] = { + {36, SAP_ACS_WEIGHT_MAX}, + {52, SAP_ACS_WEIGHT_MAX}, + {100, SAP_ACS_WEIGHT_MAX}, + {116, SAP_ACS_WEIGHT_MAX}, + {132, SAP_ACS_WEIGHT_MAX}, + {149, SAP_ACS_WEIGHT_MAX}, +}; + +sapAcsChannelInfo acs_ht40_channels24_g[] = { + {1, SAP_ACS_WEIGHT_MAX}, + {2, SAP_ACS_WEIGHT_MAX}, + {3, SAP_ACS_WEIGHT_MAX}, + {4, SAP_ACS_WEIGHT_MAX}, + {9, SAP_ACS_WEIGHT_MAX}, +}; + +#define CHANNEL_165 165 + +/* rssi discount for channels in PCL */ +#define PCL_RSSI_DISCOUNT 10 + +#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_scan_result_get_first(hal, scan_result); + + while (node) { + total_ie_len = (node->BssDescriptor.length + + sizeof(uint16_t) + sizeof(uint32_t) - + sizeof(tSirBssDescription)); + temp_ptr = cfg_get_vendor_ie_ptr_from_oui(mac_ctx, + SIR_MAC_QCOM_VENDOR_OUI, + SIR_MAC_QCOM_VENDOR_SIZE, + ((uint8_t *)&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; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 = SAP_ACS_WEIGHT_MAX + 1; + spect_ch[i].weight_copy = + SAP_ACS_WEIGHT_MAX + 1; + break; + } + } /* if (temp_ptr) */ + node = sme_scan_result_get_next(hal, scan_result); + } +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +#ifdef FEATURE_WLAN_CH_AVOID +/*========================================================================== + FUNCTION sap_update_unsafe_channel_list + + DESCRIPTION + Function Undate unsafe channel list table + + DEPENDENCIES + NA. + + IN + SapContext pointer + + RETURN VALUE + NULL + ============================================================================*/ +#ifdef CONFIG_CNSS +void sap_update_unsafe_channel_list(ptSapContext pSapCtx) +{ + uint16_t i, j; + uint16_t unsafe_channel_list[NUM_20MHZ_RF_CHANNELS]; + uint16_t unsafe_channel_count = 0; + + /* Flush, default set all channel safe */ + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + safe_channels[i].isSafe = 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 == true) { + if (CDS_IS_DFS_CH(safe_channels[i].channelNumber)) { + safe_channels[i].isSafe = false; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: DFS Ch %d is not safe in" + " Concurrent mode", + __func__, + safe_channels[i].channelNumber); + } + } + } +#endif + + cnss_get_wlan_unsafe_channel(unsafe_channel_list, + &unsafe_channel_count, + sizeof(unsafe_channel_list)); + + for (i = 0; i < unsafe_channel_count; i++) { + for (j = 0; j < NUM_20MHZ_RF_CHANNELS; j++) { + if (safe_channels[j].channelNumber == + unsafe_channel_list[i]) { + /* Found unsafe channel, update it */ + safe_channels[j].isSafe = false; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("CH %d is not safe"), + unsafe_channel_list[i]); + break; + } + } + } + + return; +} +#else +void sap_update_unsafe_channel_list(ptSapContext pSapCtx) +{ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Not implemented", __func__); + return; +} +#endif + +#endif /* FEATURE_WLAN_CH_AVOID */ + +/*========================================================================== + FUNCTION sap_cleanup_channel_list + + DESCRIPTION + Function sap_cleanup_channel_list frees up the memory allocated to the channel list. + + DEPENDENCIES + NA. + + PARAMETERS + + IN + NULL + + RETURN VALUE + NULL + ============================================================================*/ + +void sap_cleanup_channel_list( +#ifdef WLAN_FEATURE_MBSSID + void *p_cds_gctx +#else + void +#endif + ) { +#ifndef WLAN_FEATURE_MBSSID + void *p_cds_gctx = cds_get_global_context(); +#endif + ptSapContext pSapCtx; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "Cleaning up the channel list structure"); + + if (NULL == p_cds_gctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "SAP Global Context is NULL"); + return; + } + + pSapCtx = CDS_GET_SAP_CB(p_cds_gctx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "SAP Context is NULL"); + return; + } + + pSapCtx->SapChnlList.numChannel = 0; + if (pSapCtx->SapChnlList.channelList) { + cdf_mem_free(pSapCtx->SapChnlList.channelList); + pSapCtx->SapChnlList.channelList = NULL; + } + + pSapCtx->SapAllChnlList.numChannel = 0; + if (pSapCtx->SapAllChnlList.channelList) { + cdf_mem_free(pSapCtx->SapAllChnlList.channelList); + pSapCtx->SapAllChnlList.channelList = NULL; + } +} + +/** + * sap_select_preferred_channel_from_channel_list() - to calc best cahnnel + * @best_chnl: best channel already calculated among all the chanels + * @sap_ctx: sap context + * @spectinfo_param: Pointer to tSapChSelSpectInfo structure + * + * This function 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. + * + * Return: uint8_t best channel + */ +uint8_t sap_select_preferred_channel_from_channel_list(uint8_t best_chnl, + ptSapContext sap_ctx, + tSapChSelSpectInfo *spectinfo_param) +{ + uint8_t i = 0; + + /* + * If Channel List is not Configured don't do anything + * Else return the Best Channel from the Channel List + */ + if ((NULL == sap_ctx->acs_cfg->ch_list) || + (NULL == spectinfo_param) || + (0 == sap_ctx->acs_cfg->ch_list_count)) + return best_chnl; + + if (best_chnl <= 0 || best_chnl > 252) + return SAP_CHANNEL_NOT_SELECTED; + + /* Select the best channel from allowed list */ + for (i = 0; i < sap_ctx->acs_cfg->ch_list_count; i++) { + if (sap_ctx->acs_cfg->ch_list[i] == best_chnl) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "Best channel is: %d", + best_chnl); + return best_chnl; + } + } + + return SAP_CHANNEL_NOT_SELECTED; +} + +/*========================================================================== + FUNCTION sap_chan_sel_init + + DESCRIPTION + Function sap_chan_sel_init 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 + bool: Success or FAIL + + SIDE EFFECTS + ============================================================================*/ +bool sap_chan_sel_init(tHalHandle halHandle, + tSapChSelSpectInfo *pSpectInfoParams, ptSapContext pSapCtx) +{ + tSapSpectChInfo *pSpectCh = NULL; + uint8_t *pChans = NULL; + uint16_t channelnum = 0; + tpAniSirGlobal pMac = PMAC_STRUCT(halHandle); + bool chSafe = true; +#ifdef FEATURE_WLAN_CH_AVOID + uint16_t i; +#endif + uint32_t dfs_master_cap_enabled; + bool include_dfs_ch = true; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "In %s", + __func__); + + pSpectInfoParams->numSpectChans = + pMac->scan.base_channels.numChannels; + + /* Allocate memory for weight computation of 2.4GHz */ + pSpectCh = + (tSapSpectChInfo *) cdf_mem_malloc((pSpectInfoParams->numSpectChans) + * sizeof(*pSpectCh)); + + if (pSpectCh == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s, CDF_MALLOC_ERR", __func__); + return eSAP_FALSE; + } + + cdf_mem_zero(pSpectCh, + (pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh)); + + /* Initialize the pointers in the DfsParams to the allocated memory */ + pSpectInfoParams->pSpectCh = pSpectCh; + + pChans = pMac->scan.base_channels.channelList; + +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || defined(WLAN_FEATURE_MBSSID) + if (pSapCtx->dfs_ch_disable == true) + include_dfs_ch = false; +#endif + sme_cfg_get_int(halHandle, WNI_CFG_DFS_MASTER_ENABLED, + &dfs_master_cap_enabled); + if (dfs_master_cap_enabled == 0) + include_dfs_ch = false; + + /* Fill the channel number in the spectrum in the operating freq band */ + for (channelnum = 0; + channelnum < pSpectInfoParams->numSpectChans; + channelnum++, pChans++) { + chSafe = true; + + /* check if the channel is in NOL blacklist */ + if (sap_dfs_is_channel_in_nol_list(pSapCtx, *pChans, + PHY_SINGLE_CHANNEL_CENTERED)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Ch %d is in NOL list", __func__, + *pChans); + chSafe = false; + continue; + } + + if (include_dfs_ch == false) { + if (CDS_IS_DFS_CH(*pChans)) { + chSafe = false; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 ((safe_channels[i].channelNumber == *pChans) && + (false == safe_channels[i].isSafe)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Ch %d is not safe", __func__, + *pChans); + chSafe = false; + break; + } + } +#endif /* FEATURE_WLAN_CH_AVOID */ + + /* OFDM rates are not supported on channel 14 */ + if (*pChans == 14 && + eCSR_DOT11_MODE_11b != pSapCtx->csr_roamProfile.phyMode) { + pSpectCh++; + continue; + } + + if (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 */ + } + pSpectCh++; + } + return eSAP_TRUE; +} + +/*========================================================================== + FUNCTION sapweight_rssi_count + + 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 + uint32_t : Calculated channel weight based on above two + + SIDE EFFECTS + ============================================================================*/ +uint32_t sapweight_rssi_count(int8_t rssi, uint16_t count) +{ + int32_t rssiWeight = 0; + int32_t countWeight = 0; + uint32_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; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, rssiWeight=%d, countWeight=%d, rssicountWeight=%d", + __func__, rssiWeight, countWeight, rssicountWeight); + + return rssicountWeight; +} + +/** + * sap_update_rssi_bsscount() - updates bss count and rssi effect. + * + * @pSpectCh: Channel Information + * @offset: Channel Offset + * @sap_24g: Channel is in 2.4G or 5G + * + * sap_update_rssi_bsscount updates bss count and rssi effect based + * on the channel offset. + * + * Return: None. + */ + +void sap_update_rssi_bsscount(tSapSpectChInfo *pSpectCh, int32_t offset, + bool sap_24g) +{ + tSapSpectChInfo *pExtSpectCh = NULL; + int32_t rssi, rsssi_effect; + + pExtSpectCh = (pSpectCh + offset); + if (pExtSpectCh != NULL) { + ++pExtSpectCh->bssCount; + switch (offset) { + case -1: + case 1: + rsssi_effect = sap_24g ? + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + break; + case -2: + case 2: + rsssi_effect = sap_24g ? + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + break; + case -3: + case 3: + rsssi_effect = sap_24g ? + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + break; + case -4: + case 4: + rsssi_effect = + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + break; + default: + rsssi_effect = 0; + break; + } + + rssi = pSpectCh->rssiAgr + rsssi_effect; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + pExtSpectCh->rssiAgr = rssi; + if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) + pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; + } +} + +/** + * sap_upd_chan_spec_params() - sap_upd_chan_spec_params + * updates channel parameters obtained from Beacon + * @pBeaconStruct Beacon strucutre populated by parse_beacon function + * @channelWidth Channel width + * @secondaryChannelOffset Secondary Channel Offset + * @vhtSupport If channel supports VHT + * @centerFreq Central frequency for the given channel. + * + * sap_upd_chan_spec_params updates the spectrum channels based on the + * pBeaconStruct obtained from Beacon IE + * + * Return: NA. + */ + +void sap_upd_chan_spec_params(tSirProbeRespBeacon *pBeaconStruct, + uint16_t *channelWidth, + uint16_t *secondaryChannelOffset, + uint16_t *vhtSupport, + uint16_t *centerFreq) +{ + if (NULL == pBeaconStruct) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("pBeaconStruct is NULL")); + return; + } + + 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; + } + } + } +} + +/** + * sap_interference_rssi_count_5G() - sap_interference_rssi_count + * considers the Adjacent channel rssi and + * data count(here number of BSS observed) + * @spect_ch: Channel Information + * @chan_width: Channel width parsed from beacon IE + * @sec_chan_offset: Secondary Channel Offset + * @center_freq: Central frequency for the given channel. + * @channel_id: channel_id + * + * sap_interference_rssi_count_5G considers the Adjacent channel rssi + * and data count(here number of BSS observed) + * + * Return: NA. + */ + +void sap_interference_rssi_count_5G(tSapSpectChInfo *spect_ch, + uint16_t chan_width, + uint16_t sec_chan_offset, + uint16_t center_freq, uint8_t channel_id) +{ + if (NULL == spect_ch) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("spect_ch is NULL")); + return; + } + + /* Updating the received ChannelWidth */ + if (spect_ch->channelWidth != chan_width) + spect_ch->channelWidth = chan_width; + /* If received ChannelWidth is other than HT20, + * we need to update the extension channel Params as well + * chan_width == 0, HT20 + * chan_width == 1, HT40 + * chan_width == 2, VHT80 + */ + + switch (spect_ch->channelWidth) { + case eHT_CHANNEL_WIDTH_40MHZ: /* HT40 */ + switch (sec_chan_offset) { + /* Above the Primary Channel */ + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + sap_update_rssi_bsscount(spect_ch, 1, false); + break; + + /* Below the Primary channel */ + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + sap_update_rssi_bsscount(spect_ch, -1, false); + break; + } + break; + case eHT_CHANNEL_WIDTH_80MHZ: /* VHT80 */ + if ((center_freq - channel_id) == 6) { + sap_update_rssi_bsscount(spect_ch, 1, false); + sap_update_rssi_bsscount(spect_ch, 2, false); + sap_update_rssi_bsscount(spect_ch, 3, false); + } else if ((center_freq - channel_id) == 2) { + sap_update_rssi_bsscount(spect_ch, -1, false); + sap_update_rssi_bsscount(spect_ch, 1, false); + sap_update_rssi_bsscount(spect_ch, 2, false); + } else if ((center_freq - channel_id) == -2) { + sap_update_rssi_bsscount(spect_ch, -2, false); + sap_update_rssi_bsscount(spect_ch, -1, false); + sap_update_rssi_bsscount(spect_ch, 1, false); + } else if ((center_freq - channel_id) == -6) { + sap_update_rssi_bsscount(spect_ch, -1, false); + sap_update_rssi_bsscount(spect_ch, -2, false); + sap_update_rssi_bsscount(spect_ch, -3, false); + } + break; + default: + break; + } +} + +/** + * sap_interference_rssi_count() - sap_interference_rssi_count + * considers the Adjacent channel rssi + * and data count(here number of BSS observed) + * @spect_ch Channel Information + * + * sap_interference_rssi_count considers the Adjacent channel rssi + * and data count(here number of BSS observed) + * + * Return: None. + */ + +void sap_interference_rssi_count(tSapSpectChInfo *spect_ch) +{ + if (NULL == spect_ch) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: spect_ch is NULL", __func__); + return; + } + + switch (spect_ch->chNum) { + case CHANNEL_1: + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + sap_update_rssi_bsscount(spect_ch, 4, true); + break; + + case CHANNEL_2: + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + sap_update_rssi_bsscount(spect_ch, 4, true); + break; + case CHANNEL_3: + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + sap_update_rssi_bsscount(spect_ch, 4, true); + break; + case CHANNEL_4: + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + sap_update_rssi_bsscount(spect_ch, 4, true); + break; + + case CHANNEL_5: + case CHANNEL_6: + case CHANNEL_7: + case CHANNEL_8: + case CHANNEL_9: + case CHANNEL_10: + sap_update_rssi_bsscount(spect_ch, -4, true); + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + sap_update_rssi_bsscount(spect_ch, 4, true); + break; + + case CHANNEL_11: + sap_update_rssi_bsscount(spect_ch, -4, true); + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + sap_update_rssi_bsscount(spect_ch, 3, true); + break; + + case CHANNEL_12: + sap_update_rssi_bsscount(spect_ch, -4, true); + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + sap_update_rssi_bsscount(spect_ch, 2, true); + break; + + case CHANNEL_13: + sap_update_rssi_bsscount(spect_ch, -4, true); + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + sap_update_rssi_bsscount(spect_ch, 1, true); + break; + + case CHANNEL_14: + sap_update_rssi_bsscount(spect_ch, -4, true); + sap_update_rssi_bsscount(spect_ch, -3, true); + sap_update_rssi_bsscount(spect_ch, -2, true); + sap_update_rssi_bsscount(spect_ch, -1, true); + break; + + default: + break; + } +} + +/*========================================================================== + Function ch_in_pcl + + Description + Check if a channel is in the preferred channel list + + Parameters + sap_ctx SAP context pointer + channel input channel number + + Return Value + true: channel is in PCL + false: channel is not in PCL + ==========================================================================*/ +bool ch_in_pcl(ptSapContext sap_ctx, uint8_t channel) +{ + uint32_t i; + + for (i = 0; i < sap_ctx->acs_cfg->pcl_ch_count; i++) { + if (channel == sap_ctx->acs_cfg->pcl_channels[i]) + return true; + } + + return false; +} + +/*========================================================================== + FUNCTION sap_compute_spect_weight + + 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 + + RETURN VALUE + void : NULL + + SIDE EFFECTS + ============================================================================*/ +void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, + tHalHandle halHandle, tScanResultHandle pResult, + ptSapContext sap_ctx) +{ + int8_t rssi = 0; + uint8_t chn_num = 0; + uint8_t channel_id = 0; + + tCsrScanResultInfo *pScanResult; + tSapSpectChInfo *pSpectCh = pSpectInfoParams->pSpectCh; + uint32_t operatingBand; + uint16_t channelWidth; + uint16_t secondaryChannelOffset; + uint16_t centerFreq; + uint16_t vhtSupport; + uint32_t ieLen = 0; + tSirProbeRespBeacon *pBeaconStruct; + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + + pBeaconStruct = cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (NULL == pBeaconStruct) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "Unable to allocate memory in sap_compute_spect_weight\n"); + return; + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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_scan_result_get_first(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(uint16_t) + sizeof(uint32_t) - + sizeof(tSirBssDescription)); + cdf_mem_set((uint8_t *) pBeaconStruct, + sizeof(tSirProbeRespBeacon), 0); + + if ((sir_parse_beacon_ie + (pMac, pBeaconStruct, + (uint8_t *) (pScanResult->BssDescriptor.ieFields), + ieLen)) == eSIR_SUCCESS) { + sap_upd_chan_spec_params(pBeaconStruct, + &channelWidth, &secondaryChannelOffset, + &vhtSupport, ¢erFreq); + } + } + /* 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 */ + + /* + * Connsidering the Extension Channel + * only in a channels + */ + switch (operatingBand) { + case eCSR_DOT11_MODE_11a: + sap_interference_rssi_count_5G( + pSpectCh, channelWidth, + secondaryChannelOffset, centerFreq, + channel_id); + break; + + case eCSR_DOT11_MODE_11g: + sap_interference_rssi_count(pSpectCh); + break; + + case eCSR_DOT11_MODE_abg: + sap_interference_rssi_count_5G( + pSpectCh, channelWidth, + secondaryChannelOffset, centerFreq, + channel_id); + sap_interference_rssi_count(pSpectCh); + break; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 \n", + __func__, + pScanResult->BssDescriptor. + channelIdSelf, + pScanResult->BssDescriptor.channelId, + pScanResult->BssDescriptor.rssi, + pSpectCh->bssCount, pScanResult, + pSpectCh->channelWidth, + secondaryChannelOffset, centerFreq); + pSpectCh++; + break; + } else { + pSpectCh++; + } + } + + pScanResult = sme_scan_result_get_next(halHandle, pResult); + } + + /* Calculate the weights for all channels in the spectrum pSpectCh */ + pSpectCh = pSpectInfoParams->pSpectCh; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = (int8_t) pSpectCh->rssiAgr; + if (ch_in_pcl(sap_ctx, chn_num)) + rssi -= PCL_RSSI_DISCOUNT; + + pSpectCh->weight = + SAPDFS_NORMALISE_1000 * sapweight_rssi_count(rssi, + pSpectCh-> + bssCount); + pSpectCh->weight_copy = pSpectCh->weight; + + /* ------ Debug Info ------ */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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++; + } + cdf_mem_free(pBeaconStruct); +} + +/*========================================================================== + FUNCTION sap_chan_sel_exit + + 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 sap_chan_sel_exit(tSapChSelSpectInfo *pSpectInfoParams) +{ + /* Free all the allocated memory */ + cdf_mem_free(pSpectInfoParams->pSpectCh); +} + +/*========================================================================== + FUNCTION sap_sort_chl_weight + + 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 sap_sort_chl_weight(tSapChSelSpectInfo *pSpectInfoParams) +{ + tSapSpectChInfo temp; + + tSapSpectChInfo *pSpectCh = NULL; + uint32_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) { + cdf_mem_copy(&temp, &pSpectCh[minWeightIndex], + sizeof(*pSpectCh)); + cdf_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], + sizeof(*pSpectCh)); + cdf_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh)); + } + } +} + +/** + * sap_sort_chl_weight_ht80() - to sort the channels with the least weight + * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure + * + * Funtion to sort the channels with the least weight first for HT80 channels + * + * Return: none + */ +void sap_sort_chl_weight_ht80(tSapChSelSpectInfo *pSpectInfoParams) +{ + uint8_t i, j, n; + tSapSpectChInfo *pSpectInfo; + uint8_t minIdx; + + pSpectInfo = pSpectInfoParams->pSpectCh; + /* for each HT80 channel, calculate the combined weight of the + four 20MHz weight */ + for (i = 0; i < ARRAY_SIZE(acs_ht80_channels); i++) { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (pSpectInfo[j].chNum == + acs_ht80_channels[i].chStartNum) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + 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))) { + /* + * some channels does not exist in pSectInfo array, + * skip this channel and those in the same HT80 width + */ + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum + 4) == + pSpectInfo[j + 1].chNum) + pSpectInfo[j + 1].weight = + SAP_ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum + 8) == + pSpectInfo[j + 2].chNum) + pSpectInfo[j + 2].weight = + SAP_ACS_WEIGHT_MAX * 4; + if ((pSpectInfo[j].chNum + 12) == + pSpectInfo[j + 3].chNum) + pSpectInfo[j + 3].weight = + SAP_ACS_WEIGHT_MAX * 4; + continue; + } + /*found the channel, add the 4 adjacent channels' weight */ + acs_ht80_channels[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 if (pSpectInfo[j + 2].weight <= + pSpectInfo[j + 3].weight) { + /* upper 2 channels are better choice */ + 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 = SAP_ACS_WEIGHT_MAX * 4; + + pSpectInfo[j + minIdx].weight = acs_ht80_channels[i].weight; + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (CHANNEL_165 == pSpectInfo[j].chNum) { + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 4; + break; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d Weight= %d rssi=%d bssCount=%d"), + pSpectInfo->chNum, pSpectInfo->weight, + pSpectInfo->rssiAgr, pSpectInfo->bssCount); + pSpectInfo++; + } +} + +/** + * sap_sort_chl_weight_ht40_24_g() - to sort channel with the least weight + * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure + * + * Funtion to sort the channels with the least weight first for HT40 channels + * + * Return: none + */ +void sap_sort_chl_weight_ht40_24_g(tSapChSelSpectInfo *pSpectInfoParams) +{ + uint8_t i, j; + tSapSpectChInfo *pSpectInfo; + uint32_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(acs_ht40_channels24_g); i++) { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (pSpectInfo[j].chNum == + acs_ht40_channels24_g[i].chStartNum) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + if (!((pSpectInfo[j].chNum + 4) == pSpectInfo[j + 4].chNum)) { + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2; + continue; + } + /* + * 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 = + SAP_ACS_WEIGHT_MAX * 2; + pSpectInfo[j + 8].weight = + SAP_ACS_WEIGHT_MAX * 2; + } else { + pSpectInfo[j + 4].weight = + tmpWeight1; + /* for secondary channel selection */ + pSpectInfo[j].weight = + SAP_ACS_WEIGHT_MAX * 2 + - 1; + pSpectInfo[j + 8].weight = + SAP_ACS_WEIGHT_MAX * 2; + } + } else { + if (pSpectInfo[j + 4].weight <= + pSpectInfo[j + 8].weight) { + pSpectInfo[j + 4].weight = + tmpWeight2; + pSpectInfo[j].weight = + SAP_ACS_WEIGHT_MAX * 2; + /* for secondary channel selection */ + pSpectInfo[j + 8].weight = + SAP_ACS_WEIGHT_MAX * 2 + - 1; + } else { + pSpectInfo[j + 8].weight = + tmpWeight2; + pSpectInfo[j].weight = + SAP_ACS_WEIGHT_MAX * 2; + pSpectInfo[j + 4].weight = + SAP_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 = + SAP_ACS_WEIGHT_MAX * 2; + } else { + pSpectInfo[j + 4].weight = tmpWeight1; + pSpectInfo[j].weight = + SAP_ACS_WEIGHT_MAX * 2; + } + } + } +} + +/*========================================================================== + FUNCTION sap_sort_chl_weight_ht40_5_g + + 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 sap_sort_chl_weight_ht40_5_g(tSapChSelSpectInfo *pSpectInfoParams) +{ + uint8_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(acs_ht40_channels5_g); i++) { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (pSpectInfo[j].chNum == + acs_ht40_channels5_g[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) { + acs_ht40_channels5_g[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 = + acs_ht40_channels5_g[i].weight; + /* mark the adjacent channel's weight as max value so + that it will be sorted to the bottom */ + pSpectInfo[j + 1].weight = + SAP_ACS_WEIGHT_MAX * 2; + } else { + pSpectInfo[j + 1].weight = + acs_ht40_channels5_g[i].weight; + /* mark the adjacent channel's weight as max value so + that it will be sorted to the bottom */ + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2; + } + + } else + pSpectInfo[j].weight = SAP_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 = SAP_ACS_WEIGHT_MAX * 2; + break; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d", + __func__, pSpectInfo->chNum, pSpectInfo->weight, + pSpectInfo->rssiAgr, pSpectInfo->bssCount); + pSpectInfo++; + } + + sap_sort_chl_weight(pSpectInfoParams); +} + +/*========================================================================== + FUNCTION sap_sort_chl_weight_all + + 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 sap_sort_chl_weight_all(ptSapContext pSapCtx, + tSapChSelSpectInfo *pSpectInfoParams, + uint32_t operatingBand) +{ + tSapSpectChInfo *pSpectCh = NULL; + uint32_t j = 0; +#ifndef SOFTAP_CHANNEL_RANGE + uint32_t i = 0; +#endif + + pSpectCh = pSpectInfoParams->pSpectCh; +#ifdef SOFTAP_CHANNEL_RANGE + + switch (pSapCtx->acs_cfg->ch_width) { + case CH_WIDTH_40MHZ: + if (eCSR_DOT11_MODE_11g == operatingBand) + sap_sort_chl_weight_ht40_24_g(pSpectInfoParams); + else if (eCSR_DOT11_MODE_11a == operatingBand) + sap_sort_chl_weight_ht40_5_g(pSpectInfoParams); + else { + sap_sort_chl_weight_ht40_24_g(pSpectInfoParams); + sap_sort_chl_weight_ht40_5_g(pSpectInfoParams); + } + sap_sort_chl_weight(pSpectInfoParams); + break; + + case CH_WIDTH_80MHZ: + sap_sort_chl_weight_ht80(pSpectInfoParams); + break; + + case CH_WIDTH_20MHZ: + default: + /* Sorting the channels as per weights as 20MHz channels */ + sap_sort_chl_weight(pSpectInfoParams); + } + +#else + /* Sorting the channels as per weights */ + for (i = 0; i < SPECT_24GHZ_CH_COUNT; i++) { + minWeightIndex = i; + for (j = i + 1; j < SPECT_24GHZ_CH_COUNT; j++) { + if (pSpectCh[j].weight < + pSpectCh[minWeightIndex].weight) { + minWeightIndex = j; + } + } + if (minWeightIndex != i) { + cdf_mem_copy(&temp, &pSpectCh[minWeightIndex], + sizeof(*pSpectCh)); + cdf_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], + sizeof(*pSpectCh)); + cdf_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh)); + } + } +#endif + + /* For testing */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Sorted Spectrum Channels Weight", __func__); + pSpectCh = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 sap_filter_over_lap_ch + + 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 + bool : true if channel is accepted. + + SIDE EFFECTS + ============================================================================*/ +bool sap_filter_over_lap_ch(ptSapContext pSapCtx, uint16_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 sap_select_channel + + 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 + uint8_t : Success - channel number, Fail - zero + + SIDE EFFECTS + ============================================================================*/ +uint8_t sap_select_channel(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 */ + uint8_t bestChNum = SAP_CHANNEL_NOT_SELECTED; +#ifdef FEATURE_WLAN_CH_AVOID + uint8_t i; + uint8_t firstSafeChannelInRange = SAP_CHANNEL_NOT_SELECTED; +#endif +#ifdef SOFTAP_CHANNEL_RANGE + uint32_t startChannelNum; + uint32_t endChannelNum; + uint32_t operatingBand = 0; + uint32_t tmpChNum; + uint8_t count; +#endif + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Running SAP Ch Select", __func__); + +#ifdef FEATURE_WLAN_CH_AVOID + sap_update_unsafe_channel_list(pSapCtx); +#endif + + if (NULL == pScanResult) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: No external AP present\n", __func__); + +#ifndef SOFTAP_CHANNEL_RANGE + return bestChNum; +#else + startChannelNum = pSapCtx->acs_cfg->start_ch; + endChannelNum = pSapCtx->acs_cfg->end_ch; + + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: start - end: %d - %d\n", __func__, + startChannelNum, endChannelNum); + +#ifndef FEATURE_WLAN_CH_AVOID /* FEATURE_WLAN_CH_AVOID NOT defined case */ + pSapCtx->acs_cfg->pri_ch = startChannelNum; + pSapCtx->acs_cfg->ht_sec_ch = 0; + /* pick the first channel in configured range */ + return startChannelNum; +#else /* FEATURE_WLAN_CH_AVOID defined */ + + /* get a channel in PCL and within the range */ + for (i = 0; i < pSapCtx->acs_cfg->pcl_ch_count; i++) { + if ((pSapCtx->acs_cfg->pcl_channels[i] >= + startChannelNum) + && (pSapCtx->acs_cfg->pcl_channels[i] <= + endChannelNum)) { + firstSafeChannelInRange = + pSapCtx->acs_cfg->pcl_channels[i]; + break; + } + } + if (SAP_CHANNEL_NOT_SELECTED != firstSafeChannelInRange) + return firstSafeChannelInRange; + + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + if ((safe_channels[i].channelNumber >= startChannelNum) + && (safe_channels[i].channelNumber <= + endChannelNum)) { + CHANNEL_STATE channel_type = + cds_get_channel_state(safe_channels[i]. + channelNumber); + + if ((channel_type == CHANNEL_STATE_DISABLE) || + (channel_type == CHANNEL_STATE_INVALID)) + continue; + + if (safe_channels[i].isSafe == true) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: channel %d in the configuration is safe\n", + __func__, + safe_channels[i]. + channelNumber); + firstSafeChannelInRange = + safe_channels[i].channelNumber; + break; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: channel %d in the configuration is unsafe\n", + __func__, + safe_channels[i].channelNumber); + } + } + + /* if 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 (sap_chan_sel_init(halHandle, pSpectInfoParams, pSapCtx) != eSAP_TRUE) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 */ + sap_compute_spect_weight(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 + startChannelNum = pSapCtx->acs_cfg->start_ch; + endChannelNum = pSapCtx->acs_cfg->end_ch; + SET_ACS_BAND(operatingBand, pSapCtx); + + pSapCtx->acsBestChannelInfo.channelNum = 0; + pSapCtx->acsBestChannelInfo.weight = SAP_ACS_WEIGHT_MAX; + + /* Sort the channel list as per the computed weights, lesser weight first. */ + sap_sort_chl_weight_all(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 = + sap_select_preferred_channel_from_channel_list + (bestChNum, pSapCtx, pSpectInfoParams); + if (bestChNum == SAP_CHANNEL_NOT_SELECTED) { + /* not in preferred channel list, go to next best channel */ + continue; + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* Weight of the channels(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 + */ + if (sap_check_in_avoid_ch_list(pSapCtx, + bestChNum)) { + bestChNum = SAP_CHANNEL_NOT_SELECTED; + continue; + } +#endif + + 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 (sap_filter_over_lap_ch(pSapCtx, + pSpectInfoParams-> + pSpectCh[count]. + chNum)) { + tmpChNum = + pSpectInfoParams-> + pSpectCh[count].chNum; + tmpChNum = + sap_select_preferred_channel_from_channel_list + (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. */ + sap_sort_chl_weight_all(pSapCtx, halHandle, pSpectInfoParams); + /* Get the first channel in sorted array as best 20M Channel */ + bestChNum = (uint8_t) pSpectInfoParams->pSpectCh[0].chNum; + /* Select Best Channel from Channel List if Configured */ + bestChNum = sap_select_preferred_channel_from_channel_list(bestChNum, + pSapCtx, + pSpectInfoParams); +#endif + + /** in case the best channel seleted is not in PCL and there is another + * channel which has same weightage and is in PCL, choose the one in + * PCL + */ + for (count = 0; count < pSpectInfoParams->numSpectChans; count++) { + /** check if a pcl channel has the same weightage + * as the best channel + */ + if (ch_in_pcl(pSapCtx, pSpectInfoParams->pSpectCh[count].chNum) + && (pSpectInfoParams->pSpectCh[count].weight == + pSapCtx->acsBestChannelInfo.weight)) { + if (sap_select_preferred_channel_from_channel_list( + pSpectInfoParams->pSpectCh[count].chNum, + pSapCtx, pSpectInfoParams) == + SAP_CHANNEL_NOT_SELECTED) + continue; + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (sap_check_in_avoid_ch_list(pSapCtx, bestChNum)) + continue; +#endif + bestChNum = pSpectInfoParams->pSpectCh[count].chNum; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + "change best channel to %d in PCL", + bestChNum); + break; + } + } + + 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 == CH_WIDTH_40MHZ)) { + if ((bestChNum >= 5) && (bestChNum <= 7)) { + int weight_below, weight_above, i; + tSapSpectChInfo *pspect_info; + + weight_below = weight_above = SAP_ACS_WEIGHT_MAX; + pspect_info = pSpectInfoParams->pSpectCh; + for (i = 0; i < pSpectInfoParams->numSpectChans; + i++) { + if (pspect_info[i].chNum == (bestChNum - 4)) + weight_below = pspect_info[i].weight; + + if (pspect_info[i].chNum == (bestChNum + 4)) + weight_above = pspect_info[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 */ + sap_chan_sel_exit(pSpectInfoParams); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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/core/sap/src/sap_ch_select.h b/core/sap/src/sap_ch_select.h new file mode 100644 index 000000000000..abefd5266bec --- /dev/null +++ b/core/sap/src/sap_ch_select.h @@ -0,0 +1,187 @@ +/* + * 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(__SAP_CH_SELECT_H) +#define __SAP_CH_SELECT_H + +/*=========================================================================== + + sapChSelect.h + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP modules + functions for channel selection. + + DEPENDENCIES: + + Are listed for each API below. + ===========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "ani_global.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 { + uint8_t channelMap:4; + uint8_t rsvd:4; + uint8_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 { + uint8_t channel; + bool valid; /* if the channel is valid to be picked as new channel */ +} tChannelInfo; + +typedef struct sAll5GChannelList { + uint8_t numChannel; + tChannelInfo *channelList; +} tAll5GChannelList; + +typedef struct sSapChannelListInfo { + uint8_t numChannel; + uint8_t *channelList; +} tSapChannelListInfo; + +typedef struct { + uint16_t chNum; /* Channel Number */ + uint16_t channelWidth; /* Channel Width */ + uint16_t bssCount; /* bss found in scanresult for this channel */ + int32_t rssiAgr; /* Max value of rssi among all BSS(es) from scanresult for this channel */ + uint32_t weight; /* Weightage of this channel */ + uint32_t weight_copy; /* copy of the orignal weight */ + bool 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 */ + uint8_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 */ + uint16_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 { + uint8_t leak_chan; /* leak channel */ + uint32_t leak_lvl; /* tx leakage lvl */ +} tSapTxLeakInfo; + +typedef struct sSapChanMatrixInfo { + uint8_t channel; /* channel to switch from */ + tSapTxLeakInfo chan_matrix[RF_CHAN_144 - RF_CHAN_36 + 1]; +} tSapChanMatrixInfo; + +#endif /* if !defined __SAP_CH_SELECT_H */ diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c new file mode 100644 index 000000000000..3d2021e6de66 --- /dev/null +++ b/core/sap/src/sap_fsm.c @@ -0,0 +1,4754 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/*=========================================================================== + + s a p F s m . C + + OVERVIEW: + + This software unit holds the implementation of the WLAN SAP Finite + State Machine modules + + DEPENDENCIES: + + Are listed for each API below. + ===========================================================================*/ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "sap_internal.h" +/* Pick up the SME API definitions */ +#include "sme_api.h" +/* Pick up the PMC API definitions */ +#include "cds_utils.h" +#include "cds_ieee80211_common_i.h" +#include "cds_reg_service.h" +#include "cdf_util.h" +#include "cds_concurrency.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_CH_AVOID +extern sapSafeChannelType safe_channels[]; +#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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, +}; + +/* 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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + +}; + +/* 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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN}, + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, + + {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}, + {144, SAP_TX_LEAKAGE_MIN} + } }, +}; +#endif /* WLAN_ENABLE_CHNL_MATRIX_RESTRICTION */ + +/*---------------------------------------------------------------------------- + * Static Function Declarations and Definitions + * -------------------------------------------------------------------------*/ +#ifdef SOFTAP_CHANNEL_RANGE +static CDF_STATUS sap_get_channel_list(ptSapContext sapContext, + uint8_t **channelList, + uint8_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 CDF_STATUS sap_get5_g_hz_channel_list(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 sap_stop_dfs_cac_timer(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 sap_start_dfs_cac_timer(ptSapContext sapContext); + +/** sap_hdd_event_to_string() - convert hdd event to string + * @event: eSapHddEvent event type + * + * This function converts eSapHddEvent into string + * + * Return: string for the @event. + */ +static uint8_t *sap_hdd_event_to_string(eSapHddEvent event) +{ + switch (event) { + CASE_RETURN_STRING(eSAP_START_BSS_EVENT); + CASE_RETURN_STRING(eSAP_STOP_BSS_EVENT); + CASE_RETURN_STRING(eSAP_STA_ASSOC_IND); + CASE_RETURN_STRING(eSAP_STA_ASSOC_EVENT); + CASE_RETURN_STRING(eSAP_STA_REASSOC_EVENT); + CASE_RETURN_STRING(eSAP_STA_DISASSOC_EVENT); + CASE_RETURN_STRING(eSAP_STA_SET_KEY_EVENT); + CASE_RETURN_STRING(eSAP_STA_MIC_FAILURE_EVENT); + CASE_RETURN_STRING(eSAP_ASSOC_STA_CALLBACK_EVENT); + CASE_RETURN_STRING(eSAP_GET_WPSPBC_SESSION_EVENT); + CASE_RETURN_STRING(eSAP_WPS_PBC_PROBE_REQ_EVENT); + CASE_RETURN_STRING(eSAP_INDICATE_MGMT_FRAME); + CASE_RETURN_STRING(eSAP_REMAIN_CHAN_READY); + CASE_RETURN_STRING(eSAP_SEND_ACTION_CNF); + CASE_RETURN_STRING(eSAP_DISCONNECT_ALL_P2P_CLIENT); + CASE_RETURN_STRING(eSAP_MAC_TRIG_STOP_BSS_EVENT); + CASE_RETURN_STRING(eSAP_UNKNOWN_STA_JOIN); + CASE_RETURN_STRING(eSAP_MAX_ASSOC_EXCEEDED); + CASE_RETURN_STRING(eSAP_CHANNEL_CHANGE_EVENT); + CASE_RETURN_STRING(eSAP_DFS_CAC_START); + CASE_RETURN_STRING(eSAP_DFS_CAC_END); + CASE_RETURN_STRING(eSAP_DFS_RADAR_DETECT); + CASE_RETURN_STRING(eSAP_DFS_NOL_GET); + CASE_RETURN_STRING(eSAP_DFS_NOL_SET); + CASE_RETURN_STRING(eSAP_DFS_NO_AVAILABLE_CHANNEL); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + CASE_RETURN_STRING(eSAP_ACS_SCAN_SUCCESS_EVENT); +#endif + CASE_RETURN_STRING(eSAP_ACS_CHANNEL_SELECTED); + default: + return "eSAP_HDD_EVENT_UNKNOWN"; + } +} + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/*========================================================================== + FUNCTION sap_event_init + + DESCRIPTION + Function for initializing sWLAN_SAPEvent structure + + DEPENDENCIES + NA. + + PARAMETERS + + IN + sapEvent : State machine event + + RETURN VALUE + + None + + SIDE EFFECTS + ============================================================================*/ +static inline void sap_event_init(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 + */ +bool +sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, + ePhyChanBondState cbMode, + uint8_t NOL_channel, + tSapTxLeakInfo **pTarget_chnl_mtrx) +{ + tSapTxLeakInfo *target_chan_matrix = NULL; + tSapChanMatrixInfo *pchan_matrix = NULL; + uint32_t nchan_matrix; + int i = 0; + + switch (cbMode) { + case PHY_SINGLE_CHANNEL_CENTERED: + /* HT20 */ + pchan_matrix = ht20_chan; + nchan_matrix = CDF_ARRAY_SIZE(ht20_chan); + break; + case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: + case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + /* HT40 */ + pchan_matrix = ht40_chan; + nchan_matrix = CDF_ARRAY_SIZE(ht40_chan); + 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 = CDF_ARRAY_SIZE(ht80_chan); + break; +#endif + default: + /* handle exception and fall back to HT20 table */ + pchan_matrix = ht20_chan; + nchan_matrix = CDF_ARRAY_SIZE(ht20_chan); + 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 false; + } else { + *pTarget_chnl_mtrx = target_chan_matrix; + return true; + } +} + +/** + * sap_mark_channels_leaking_into_nol() - to mark channel leaking in to nol + * @sap_ctx: pointer to SAP context + * @cb_mode: channel bonding mode + * @nol: nol info + * @temp_ch_lst_sz: the target channel list + * @temp_ch_lst: the target channel list + * + * This function removes the channels from temp channel list that + * (if selected as target channel) will cause leakage in one of + * the NOL channels + * + * Return: CDF_STATUS + */ + +CDF_STATUS +sap_mark_channels_leaking_into_nol(ptSapContext sap_ctx, + ePhyChanBondState cb_mode, + tSapDfsNolInfo *nol, + uint8_t temp_ch_lst_sz, + uint8_t *temp_ch_lst) +{ + tSapTxLeakInfo *target_chan_matrix = NULL; + uint32_t num_channel = (RF_CHAN_144 - RF_CHAN_36) + 1; + uint32_t i = 0; + uint32_t j = 0; + uint32_t k = 0; + uint8_t dfs_nol_channel; + + + /* traverse target_chan_matrix and */ + for (i = 0; i < NUM_5GHZ_CHANNELS ; i++) { + dfs_nol_channel = nol[i].dfs_channel_number; + if (nol[i].radar_status_flag == eSAP_DFS_CHANNEL_USABLE || + nol[i].radar_status_flag == eSAP_DFS_CHANNEL_AVAILABLE) { + /* not present in NOL */ + continue; + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_DEBUG, + FL("sapdfs: processing NOL channel: %d"), + dfs_nol_channel); + if (false == sap_find_target_channel_in_channel_matrix( + sap_ctx, cb_mode, dfs_nol_channel, + &target_chan_matrix)) { + /* + * should never happen, we should always find a table + * here, if we don't, need a fix here! + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Couldn't find target channel matrix!")); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + /* + * following is based on assumption that both temp_ch_lst + * and target channel matrix are in increasing order of + * channelID + */ + for (j = 0, k = 0; j < temp_ch_lst_sz && k < num_channel;) { + if (temp_ch_lst[j] == 0) { + j++; + continue; + } + if (target_chan_matrix[k].leak_chan != temp_ch_lst[j]) { + k++; + continue; + } + /* + * check leakage from candidate channel + * to NOL channel + */ + if (target_chan_matrix[k].leak_lvl <= + SAP_TX_LEAKAGE_THRES) { + /* + * candidate channel will have + * bad leakage in NOL channel, + * remove from temp list + */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: channel: %d will have bad leakage due to channel: %d\n"), + dfs_nol_channel, temp_ch_lst[j]); + temp_ch_lst[j] = 0; + break; + } + j++; + k++; + } + } /* end of loop that selects each NOL */ + return CDF_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 sap_set_bitmap(chan_bonding_bitmap *pBitmap, uint8_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; + } + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Channel=%d is not in the bitmap"), channel); +} + +/** + * sap_populate_available_channels - To populate available channel + * @bitmap: bitmap to populate + * @current_cbmode: cb mode to check for channel availability + * @avail_chnl: available channel list to populate + * + * 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 + * + * Return: number of channels found + */ +static uint8_t sap_populate_available_channels(chan_bonding_bitmap *bitmap, + ePhyChanBondState current_cbmode, + uint8_t *avail_chnl) +{ + uint8_t i = 0; + uint8_t chnl_count = 0; + uint8_t start_channel = 0; + + switch (current_cbmode) { +#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 = bitmap->chanBondingSet[i].startChannel; + if (bitmap->chanBondingSet[i].channelMap == + SAP_80MHZ_MASK) { + avail_chnl[chnl_count++] = start_channel; + avail_chnl[chnl_count++] = start_channel + 4; + avail_chnl[chnl_count++] = start_channel + 8; + avail_chnl[chnl_count++] = 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 = bitmap->chanBondingSet[i].startChannel; + if ((bitmap->chanBondingSet[i].channelMap & + SAP_40MHZ_MASK_L) == SAP_40MHZ_MASK_L) { + avail_chnl[chnl_count++] = start_channel; + avail_chnl[chnl_count++] = start_channel + 4; + } else if ((bitmap->chanBondingSet[i].channelMap & + SAP_40MHZ_MASK_H) == SAP_40MHZ_MASK_H) { + avail_chnl[chnl_count++] = start_channel + 8; + avail_chnl[chnl_count++] = start_channel + 12; + } + } + break; + default: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid case.")); + break; + } + + return chnl_count; +} + +/* + * FUNCTION sap_dfs_is_w53_invalid + * + * 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 : bool + * true: If W53 operation is disabled + * false: If W53 operation is enabled + * + * SIDE EFFECTS + */ +bool sap_dfs_is_w53_invalid(tHalHandle hHal, uint8_t channelID) +{ + tpAniSirGlobal pMac; + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return false; + } + + /* + * Check for JAPAN W53 Channel operation capability + */ + if (true == pMac->sap.SapDfsInfo.is_dfs_w53_disabled && + true == IS_CHAN_JAPAN_W53(channelID)) { + return true; + } + + return false; +} + +/* + * FUNCTION sap_dfs_is_channel_in_preferred_location + * + * 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 :bool + * true:If Channel location is same as the preferred location + * false:If Channel location is not same as the preferred location + * + * SIDE EFFECTS + */ +bool sap_dfs_is_channel_in_preferred_location(tHalHandle hHal, uint8_t channelID) +{ + tpAniSirGlobal pMac; + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("invalid pMac")); + return true; + } + if ((SAP_CHAN_PREFERRED_INDOOR == + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location) && + (true == IS_CHAN_JAPAN_OUTDOOR(channelID))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL + ("CHAN=%d is Outdoor so invalid,preferred Indoor only"), + channelID); + return false; + } else if ((SAP_CHAN_PREFERRED_OUTDOOR == + pMac->sap.SapDfsInfo.sap_operating_chan_preferred_location) + && (true == IS_CHAN_JAPAN_INDOOR(channelID))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL + ("CHAN=%d is Indoor so invalid,preferred Outdoor only"), + channelID); + return false; + } + + return true; +} + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +/** + * sap_check_in_avoid_ch_list() - checks if given channel present is channel + * avoidance list + * + * @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 uint8_t sap_random_channel_sel(ptSapContext sapContext) +{ + uint32_t random_byte = 0; + uint8_t available_ch_cnt = 0; + uint8_t avail_dfs_chan_count = 0; + uint8_t avail_non_dfs_chan_count = 0; + uint8_t valid_chnl_count = 0; + uint8_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,}; + uint8_t target_channel = 0; + bool isChannelNol = false; + bool isOutOfRange = false; + chan_bonding_bitmap channelBitmap; + uint8_t i = 0; + uint8_t channelID; + tHalHandle hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + tpAniSirGlobal pMac; + uint32_t chanWidth; + ePhyChanBondState cbModeCurrent; + uint8_t *tmp_ch_lst = NULL; + uint8_t dfs_region; + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("invalid hHal")); + return target_channel; + } + + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = + (sapContext->ch_width_orig > CH_WIDTH_20MHZ ? 1 : 0); + 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 (sap_get5_g_hz_channel_list(sapContext)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL("Getting 5Ghz channel list failed")); + return target_channel; + } + + cds_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 (true == sap_dfs_is_w53_invalid(hHal, channelID)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL + ("index:%d, Channel=%d Invalid,Japan W53 Disabled"), + i, channelID); + sapContext->SapAllChnlList.channelList[i]. + valid = 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 (false == + sap_dfs_is_channel_in_preferred_location(hHal, + channelID)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 = false; + valid_chnl_count--; + continue; + } + } + + if (cds_get_channel_state(channelID) == + CHANNEL_STATE_DFS) { + isChannelNol = + sap_dfs_is_channel_in_nol_list(sapContext, + channelID, + PHY_SINGLE_CHANNEL_CENTERED); + if (true == isChannelNol) { + /* + * Mark this channel invalid since it is still + * in DFS Non-Occupancy-Period which is 30 mins. + */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL + ("index: %d, Channel = %d Present in NOL LIST"), + i, channelID); + sapContext->SapAllChnlList.channelList[i]. + valid = false; + valid_chnl_count--; + continue; + } + } + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + /* avoid ch 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)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 + = false; + } + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + /* check if the channel is within ACS channel range */ + isOutOfRange = sap_acs_channel_check(sapContext, channelID); + if (true == isOutOfRange) { + /* + * mark this channel invalid since it is out of ACS + * channel range + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL + ("index: %d, Channel = %d out of ACS channel range"), + i, channelID); + sapContext->SapAllChnlList.channelList[i].valid = false; + valid_chnl_count--; + continue; + } + } /* end of check for NOL or ACS channels */ + + /* valid_chnl_count now have number of valid channels */ + tmp_ch_lst = cdf_mem_malloc(valid_chnl_count); + if (tmp_ch_lst == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("sapdfs: memory alloc failed")); + return target_channel; + } + + do { + uint8_t j = 0; +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + tSapDfsNolInfo *nol = 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) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL + ("sapdfs: Adding Channel = %d to temp List"), + sapContext->SapAllChnlList. + channelList[i].channel); + tmp_ch_lst[j++] = sapContext->SapAllChnlList. + channelList[i].channel; + } + } + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL + ("sapdfs: Processing temp channel list against NOL.") + ); + if (CDF_STATUS_SUCCESS != + sap_mark_channels_leaking_into_nol(sapContext, + cbModeCurrent, + nol, + valid_chnl_count, + tmp_ch_lst)) { + cdf_mem_free(tmp_ch_lst); + return target_channel; + } +#endif + cdf_mem_zero(availableChannels, sizeof(availableChannels)); + cdf_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 */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 (tmp_ch_lst[i] != 0) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_DEBUG, + FL("sapdfs: processing channel: %d "), + tmp_ch_lst[i]); + /* + * for 20MHz, directly create available + * channel list + */ + if (cbModeCurrent == + PHY_SINGLE_CHANNEL_CENTERED) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_DEBUG, + FL + ("sapdfs: Channel=%d added to available list"), + tmp_ch_lst[i]); + availableChannels[available_ch_cnt++] = + tmp_ch_lst[i]; + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_DEBUG, + FL("sapdfs: Channel=%d added to bitmap"), + tmp_ch_lst[i]); + sap_set_bitmap(&channelBitmap, + tmp_ch_lst[i]); + } + } + } + + /* + * if 40 MHz or 80 MHz, populate available + * channel list from bitmap + */ + if (cbModeCurrent != PHY_SINGLE_CHANNEL_CENTERED) { + available_ch_cnt = + sap_populate_available_channels(&channelBitmap, + cbModeCurrent, + availableChannels); + /* + * if no valid channel bonding found, + * fallback to lower bandwidth + */ + if (available_ch_cnt == 0) { + if (cbModeCurrent >= + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL + ("sapdfs:No 80MHz cb found, falling to 40MHz")); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL + ("sapdfs:Changing chanWidth from [%d] to [%d]"), + chanWidth, + CH_WIDTH_40MHZ); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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 = CH_WIDTH_40MHZ; + /* continue to start of do loop */ + continue; + } else if (cbModeCurrent >= + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL + ("sapdfs:No 40MHz cb found, falling to 20MHz")); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL + ("sapdfs:Changing chanWidth from [%d] to [%d]"), + chanWidth, + CH_WIDTH_20MHZ); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + FL + ("sapdfs:Changing CB mode from [%d] to [%d]"), + cbModeCurrent, + PHY_SINGLE_CHANNEL_CENTERED); + cbModeCurrent = + PHY_SINGLE_CHANNEL_CENTERED; + chanWidth = CH_WIDTH_20MHZ; + /* continue to start of do loop */ + continue; + } + } + } + + /* + * by now, available channels list will be populated or + * no channels are avaialbe + */ + if (available_ch_cnt) { + for (i = 0; i < available_ch_cnt; i++) { + if (CDS_IS_DFS_CH(availableChannels[i])) { + avail_dfs_chan_list[ + avail_dfs_chan_count++] = + availableChannels[i]; + } else { + avail_non_dfs_chan_list[ + avail_non_dfs_chan_count++] = + availableChannels[i]; + } + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("No target channel found")); + } + + cds_rand_get_bytes(0, (uint8_t *)&random_byte, 1); + + /* Give preference to non-DFS channel */ + if (!pMac->f_prefer_non_dfs_on_radar) { + i = (random_byte + cdf_mc_timer_get_system_ticks()) % + available_ch_cnt; + target_channel = availableChannels[i]; + } else if (avail_non_dfs_chan_count) { + i = (random_byte + cdf_mc_timer_get_system_ticks()) % + avail_non_dfs_chan_count; + target_channel = avail_non_dfs_chan_list[i]; + } else { + i = (random_byte + cdf_mc_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; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New CB mode = %d"), + pMac->sap.SapDfsInfo.new_cbMode); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: New Channel width = %d"), + pMac->sap.SapDfsInfo.new_chanWidth); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: target_channel = %d"), + target_channel); + break; + /* this loop will iterate at max 3 times */ + } while (1); + cdf_mem_free(tmp_ch_lst); + return target_channel; +} + +bool sap_acs_channel_check(ptSapContext sapContext, uint8_t channelNumber) +{ + int i = 0; + if (!sapContext->acs_cfg->acs_mode) + return false; + + if ((channelNumber >= sapContext->acs_cfg->start_ch) || + (channelNumber <= sapContext->acs_cfg->end_ch)) { + if (!sapContext->acs_cfg->ch_list) { + return false; + } else { + for (i = 0; i < sapContext->acs_cfg->ch_list_count; i++) + if (channelNumber == + sapContext->acs_cfg->ch_list[i]) + return false; + } + } + return true; +} + +/** + * sap_mark_dfs_channels() - to mark dfs channel + * @sapContext: pointer sap context + * @channels: list of channels + * @numChannels: number of channels + * @time: time + * + * Mark the channels in NOL with time and eSAP_DFS_CHANNEL_UNAVAILABLE + * + * Return: none + */ +void sap_mark_dfs_channels(ptSapContext sapContext, uint8_t *channels, + uint8_t numChannels, uint64_t time) +{ + int i, j; + tSapDfsNolInfo *psapDfsChannelNolList = NULL; + uint8_t nRegDomainDfsChannels; + tHalHandle hHal; + tpAniSirGlobal pMac; + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == channels) + return; + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("invalid hHal")); + return; + } + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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])) + continue; + /* + * 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) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d already in NOL"), + channels[i]); + continue; + } + /* + * Capture the Radar Found timestamp on the + * Current Channel in ms. + */ + psapDfsChannelNolList[j].radar_found_timestamp = time; + /* Mark the Channel to be unavailble for next 30 mins */ + psapDfsChannelNolList[j].radar_status_flag = + eSAP_DFS_CHANNEL_UNAVAILABLE; + + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d Added to NOL LIST"), + channels[i]); + } + } +} + +/* + * This Function is to get bonding channels from primary channel. + * + */ +uint8_t sap_get_bonding_channels(ptSapContext sapContext, uint8_t channel, + uint8_t *channels, uint8_t size, + ePhyChanBondState chanBondState) +{ + tHalHandle hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + tpAniSirGlobal pMac; + uint8_t numChannel; + + if (channels == NULL) + return 0; + + if (size < MAX_BONDED_CHANNELS) + return 0; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else + return 0; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; +} + +/** + * sap_dfs_check_if_channel_avaialable() - Check if a channel is out of NOL + * @nol: Pointer to the Non-Occupancy List. + * + * This function Checks if a given channel is available or + * usable or unavailable based on the time lapse since the + * last radar time stamp. + * + * Return: true if channel available or usable, false if unavailable. + */ +static bool sap_dfs_check_if_channel_avaialable(tSapDfsNolInfo *nol) +{ + uint64_t time_since_last_radar, time_when_radar_found, current_time = 0; + uint64_t max_jiffies; + + if ((nol->radar_status_flag == eSAP_DFS_CHANNEL_USABLE) || + (nol->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. + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL("Chan=%d not in NOL,CHAN AVAILABLE"), + nol->dfs_channel_number); + return true; + } else if (nol->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. + */ + time_when_radar_found = nol->radar_found_timestamp; + current_time = cds_get_monotonic_boottime(); + if (current_time < time_when_radar_found) { + /* cds_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 = (uint64_t)UINT_MAX * 1000; + time_since_last_radar = (max_jiffies - + time_when_radar_found) + (current_time); + } else { + time_since_last_radar = current_time - + time_when_radar_found; + } + if (time_since_last_radar >= SAP_DFS_NON_OCCUPANCY_PERIOD) { + nol->radar_status_flag = eSAP_DFS_CHANNEL_AVAILABLE; + nol->radar_found_timestamp = 0; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL("Chan=%d not in NOL, Channel AVAILABLE"), + nol->dfs_channel_number); + return true; + } else { + /* + * Channel is not still available for + * SAP operation so return true; As the + * Channel is still in + * Non-occupancy-Period. + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL("Chan=%d in NOL, Channel UNAVAILBLE"), + nol->dfs_channel_number); + return false; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid Radar Status Flag")); + } + return true; +} + +/** + * sap_dfs_is_channel_in_nol_list() - given bonded channel is available + * @sap_context: Handle to SAP context. + * @channel_number: Channel on which availability should be checked. + * @chan_bondState: The channel bonding mode of the passed channel. + * + * This function Checks if a given bonded channel is available or + * usable for DFS operation. + * + * Return: false if channel is available, true if channel is in NOL. + */ +bool +sap_dfs_is_channel_in_nol_list(ptSapContext sap_context, + uint8_t channel_number, + ePhyChanBondState chan_bondState) +{ + int i, j; + tHalHandle h_hal = CDS_GET_HAL_CB(sap_context->p_cds_gctx); + tpAniSirGlobal mac_ctx; + uint8_t channels[MAX_BONDED_CHANNELS]; + uint8_t num_channels; + tSapDfsNolInfo *nol; + tSapDfsInfo *dfs_info; + bool channel_available; + + if (NULL == h_hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("invalid h_hal")); + return false; + } else { + mac_ctx = PMAC_STRUCT(h_hal); + } + + dfs_info = &mac_ctx->sap.SapDfsInfo; + if ((dfs_info->numCurrentRegDomainDfsChannels == 0) || + (dfs_info->numCurrentRegDomainDfsChannels > + NUM_5GHZ_CHANNELS)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + FL("invalid dfs channel count %d"), + dfs_info->numCurrentRegDomainDfsChannels); + return false; + } + + /* get the bonded channels */ + num_channels = sap_get_bonding_channels(sap_context, channel_number, + channels, MAX_BONDED_CHANNELS, chan_bondState); + + /* check for NOL, first on will break the loop */ + for (j = 0; j < num_channels; j++) { + for (i = 0; i < dfs_info->numCurrentRegDomainDfsChannels; i++) { + nol = &dfs_info->sapDfsChannelNolList[i]; + if (nol->dfs_channel_number != channels[j]) + continue; + + channel_available = + sap_dfs_check_if_channel_avaialable(nol); + + if (channel_available == false) + break; + + } /* loop for dfs channels */ + + if (i < dfs_info->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 < num_channels && + i < dfs_info->numCurrentRegDomainDfsChannels) { + if (num_channels > MAX_BONDED_CHANNELS) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + FL("num_channel>MAX_BONDED_CHANNEL, reset")); + num_channels = MAX_BONDED_CHANNELS; + } + nol = &dfs_info->sapDfsChannelNolList[i]; + sap_mark_dfs_channels(sap_context, channels, num_channels, + nol->radar_found_timestamp); + + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sap_signal_hdd_event(sap_context, NULL, eSAP_DFS_NOL_SET, + (void *) eSAP_STATUS_SUCCESS); + + return true; + } + + return false; +} + +/** + * sap_goto_channel_sel - Function for initiating scan request for SME + * @sap_context: Sap Context value. + * @sap_event: State machine event + * @sap_do_acs_pre_start_bss: true, if ACS scan is issued pre start BSS + * false, if ACS scan is issued post start BSS. + * + * Initiates sme scan for ACS to pick a channel. + * + * Return: The CDF_STATUS code associated with performing the operation. + */ +CDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, + ptWLAN_SAPEvent sap_event, + bool sap_do_acs_pre_start_bss) +{ + + /* Initiate a SCAN request */ + CDF_STATUS cdf_ret_status; + /* To be initialised if scan is required */ + tCsrScanRequest scan_request; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + +#ifdef SOFTAP_CHANNEL_RANGE + uint8_t *channel_list = NULL; + uint8_t num_of_channels = 0; +#endif + tHalHandle h_hal; + uint8_t con_ch; + + h_hal = cds_get_context(CDF_MODULE_ID_SME); + if (NULL == h_hal) { + /* we have a serious problem */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + FL("invalid h_hal")); + return CDF_STATUS_E_FAULT; + } +#ifdef WLAN_FEATURE_MBSSID + if (cds_concurrent_beaconing_sessions_running()) { + con_ch = + sme_get_concurrent_operation_channel(h_hal); + + if (con_ch && sap_context->channel == AUTO_CHANNEL_SELECT) { + sap_context->dfs_ch_disable = true; + } else if (con_ch && sap_context->channel != con_ch && + CDS_IS_DFS_CH(sap_context->channel)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + FL("MCC DFS not supported in AP_AP Mode")); + return CDF_STATUS_E_ABORTED; + } +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (sap_context->cc_switch_mode != + CDF_MCC_TO_SCC_SWITCH_DISABLE) { + con_ch = sme_check_concurrent_channel_overlap(h_hal, + sap_context->channel, + sap_context->csr_roamProfile.phyMode, + sap_context->cc_switch_mode); + if (con_ch) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "%s: Override ch %d to %d due to CC Intf", + __func__, sap_context->channel, con_ch); + sap_context->channel = con_ch; + } + } +#endif + } +#endif + + if (cds_get_concurrency_mode() == (CDF_STA_MASK | CDF_SAP_MASK)) { +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE + if (sap_context->channel == AUTO_CHANNEL_SELECT) + sap_context->dfs_ch_disable = true; + else if (CDS_IS_DFS_CH(sap_context->channel)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + FL("DFS not supported in STA_AP Mode")); + return CDF_STATUS_E_ABORTED; + } +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + if (sap_context->cc_switch_mode != + CDF_MCC_TO_SCC_SWITCH_DISABLE) { + con_ch = sme_check_concurrent_channel_overlap(h_hal, + sap_context->channel, + sap_context->csr_roamProfile.phyMode, + sap_context->cc_switch_mode); + if (con_ch && !CDS_IS_DFS_CH(con_ch)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "%s: Override ch %d to %d due to CC Intf", + __func__, sap_context->channel, con_ch); + sap_context->channel = con_ch; + } + } +#endif + } + + if (sap_context->channel == AUTO_CHANNEL_SELECT) { +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("%s skip_acs_status = %d "), __func__, + sap_context->acs_cfg->skip_scan_status); + if (sap_context->acs_cfg->skip_scan_status != + eSAP_SKIP_ACS_SCAN) { +#endif + cdf_mem_zero(&scan_request, sizeof(scan_request)); + + /* + * Set scanType to Active scan. FW takes care of using passive + * scan for DFS and active for non DFS channels. + */ + scan_request.scanType = eSIR_ACTIVE_SCAN; + + /* Set min and max channel time to zero */ + scan_request.minChnTime = 0; + scan_request.maxChnTime = 0; + + /* Set BSSType to default type */ + scan_request.BSSType = eCSR_BSS_TYPE_ANY; + +#ifndef SOFTAP_CHANNEL_RANGE + /*Scan all the channels */ + scan_request.ChannelInfo.num_of_channels = 0; + + scan_request.ChannelInfo.ChannelList = NULL; + + scan_request.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + /* eCSR_SCAN_REQUEST_11D_SCAN; */ + +#else + + sap_get_channel_list(sap_context, &channel_list, + &num_of_channels); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (num_of_channels != 0) { +#endif + /*Scan the channels in the list */ + scan_request.ChannelInfo.numOfChannels = + num_of_channels; + + scan_request.ChannelInfo.ChannelList = + channel_list; + + scan_request.requestType = + eCSR_SCAN_SOFTAP_CHANNEL_RANGE; + + sap_context->channelList = channel_list; + +#endif + /* Set requestType to Full scan */ + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("calling sme_scan_request")); +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + if (sap_context->acs_cfg->skip_scan_status == + eSAP_DO_NEW_ACS_SCAN) +#endif + sme_scan_flush_result(h_hal); + if (true == sap_do_acs_pre_start_bss) { + /* + * when ID == 0 11D scan/active scan with callback, + * min-maxChntime set in csrScanRequest()? + * csrScanCompleteCallback callback + * pContext scan_request_id filled up + */ + cdf_ret_status = sme_scan_request(h_hal, + sap_context->sessionId, + &scan_request, + &wlansap_pre_start_bss_acs_scan_callback, + sap_context); + } else { + /* + * when ID == 0 11D scan/active scan with callback, + * min-maxChntime set in csrScanRequest()? + * csrScanCompleteCallback callback, + * pContext scan_request_id filled up + */ + cdf_ret_status = sme_scan_request(h_hal, + sap_context->sessionId, + &scan_request, + &wlansap_scan_callback, + sap_context); + } + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("sme_scan_request fail %d!!!"), + cdf_ret_status); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("SAP Configuring default channel, Ch=%d"), + sap_context->channel); + /* In case of error, switch to default channel */ + sap_context->channel = SAP_DEFAULT_24GHZ_CHANNEL; + +#ifdef SOFTAP_CHANNEL_RANGE + if (sap_context->channelList != NULL) { + sap_context->channel = + sap_context->channelList[0]; + cdf_mem_free(sap_context-> + channelList); + sap_context->channelList = NULL; + } +#endif + if (true == sap_do_acs_pre_start_bss) { + /* + * In case of ACS req before start Bss, + * return failure so that the calling + * fucntion can use the default channel. + */ + return CDF_STATUS_E_FAILURE; + } else { + /* Fill in the event structure */ + sap_event_init(sap_event); + /* Handle event */ + cdf_status = sap_fsm(sap_context, sap_event); + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("return sme_ScanReq, scanID=%d, Ch=%d"), + scan_request.scan_id, sap_context->channel); + } +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + } + } else { + sap_context->acs_cfg->skip_scan_status = eSAP_SKIP_ACS_SCAN; + } + + if (sap_context->acs_cfg->skip_scan_status == eSAP_SKIP_ACS_SCAN) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("## %s SKIPPED ACS SCAN"), __func__); + wlansap_scan_callback(h_hal, sap_context, + sap_context->sessionId, 0, eCSR_SCAN_SUCCESS); + } +#endif + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("for configured channel, Ch= %d"), + sap_context->channel); + if (sap_do_acs_pre_start_bss == true) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("ACS end due to Ch override. Sel Ch = %d"), + sap_context->channel); + sap_context->acs_cfg->pri_ch = sap_context->channel; + sap_context->acs_cfg->ch_width = + sap_context->ch_width_orig; + sap_config_acs_result(h_hal, sap_context, 0); + return CDF_STATUS_E_CANCELED; + } else { + /* + * Fill in the event structure + * Eventhough scan was not done, + * means a user set channel was chosen + */ + sap_event_init(sap_event); + /* Handle event */ + cdf_status = sap_fsm(sap_context, sap_event); + } + } + + /* + * 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 + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("before exiting sap_goto_channel_sel channel=%d"), + sap_context->channel); + + return CDF_STATUS_SUCCESS; +} + +/*========================================================================== + 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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS sap_open_session(tHalHandle hHal, ptSapContext sapContext) +{ + uint32_t type, subType; + CDF_STATUS cdf_ret_status; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (sapContext->csr_roamProfile.csrPersona == CDF_P2P_GO_MODE) + status = cds_get_vdev_types(CDF_P2P_GO_MODE, &type, &subType); + else + status = cds_get_vdev_types(CDF_SAP_MODE, &type, &subType); + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "failed to get vdev type"); + return CDF_STATUS_E_FAILURE; + } + /* Open SME Session for Softap */ + cdf_ret_status = sme_open_session(hHal, + &wlansap_roam_callback, + sapContext, + sapContext->self_mac_addr, + &sapContext->sessionId, type, subType); + + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_roam_connect status = %d", + __func__, cdf_ret_status); + + return CDF_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->csr_roamProfile.csrPersona; + return CDF_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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS +sap_goto_starting + (ptSapContext sapContext, + ptWLAN_SAPEvent sapEvent, eCsrRoamBssType bssType) { + /* tHalHandle */ + tHalHandle hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + CDF_STATUS cdf_ret_status; + + /*- - - - - - - - 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, }; + sapContext->key_type = 0x05; + sapContext->key_length = 32; + cdf_mem_copy(sapContext->key_material, key_material, sizeof(key_material)); /* Need a key size define */ + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "In %s", + __func__); + + if (NULL == hHal) { + /* we have a serious problem */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "In %s, invalid hHal", __func__); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = sap_open_session(hHal, sapContext); + + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Error: In %s calling sap_open_session status = %d", + __func__, cdf_ret_status); + return CDF_STATUS_E_FAILURE; + } + + return CDF_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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS sap_goto_disconnecting(ptSapContext sapContext) +{ + CDF_STATUS cdf_ret_status; + tHalHandle hHal; + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + /* we have a serious problem */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s, invalid hHal", __func__); + return CDF_STATUS_E_FAULT; + } + + sap_free_roam_profile(&sapContext->csr_roamProfile); + cdf_ret_status = sme_roam_stop_bss(hHal, sapContext->sessionId); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_roam_stop_bss status = %d", + __func__, cdf_ret_status); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS sap_roam_session_close_callback(void *pContext) +{ + ptSapContext sapContext = (ptSapContext) pContext; + return sap_signal_hdd_event(sapContext, NULL, + eSAP_STOP_BSS_EVENT, + (void *) 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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS sap_goto_disconnected(ptSapContext sapContext) +{ + CDF_STATUS cdf_status = CDF_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 */ + cdf_status = sap_fsm(sapContext, &sapEvent); + + return cdf_status; +} + +/** + * sap_signal_hdd_event() - send event notification + * @sap_ctx: Sap Context + * @csr_roaminfo: Pointer to CSR roam information + * @sap_hddevent: SAP HDD event + * @context: to pass the element for future support + * + * Function for HDD to send the event notification using callback + * + * Return: CDF_STATUS + */ +CDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx, + tCsrRoamInfo *csr_roaminfo, eSapHddEvent sap_hddevent, + void *context) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tSap_Event sap_ap_event; /* This now encodes ALL event types */ + tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx); + tpAniSirGlobal mac_ctx; + tSirSmeChanInfo *chaninfo; + tSap_StationAssocIndication *assoc_ind; + tSap_StartBssCompleteEvent *bss_complete; + struct sap_ch_selected_s *acs_selected; + tSap_StationAssocReassocCompleteEvent *reassoc_complete; + tSap_StationDisassocCompleteEvent *disassoc_comp; + tSap_StationSetKeyCompleteEvent *key_complete; + tSap_StationMICFailureEvent *mic_failure; + tSap_ManagementFrameInfo *mgmt_frame; + + /* Format the Start BSS Complete event to return... */ + if (NULL == sap_ctx->pfnSapEventCallback) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + if (NULL == hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid hal")); + return CDF_STATUS_E_FAILURE; + } + mac_ctx = PMAC_STRUCT(hal); + if (NULL == mac_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid MAC context")); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("SAP event callback event = %s"), + sap_hdd_event_to_string(sap_hddevent)); + + switch (sap_hddevent) { + case eSAP_STA_ASSOC_IND: + /* TODO - Indicate the assoc request indication to OS */ + sap_ap_event.sapHddEventCode = eSAP_STA_ASSOC_IND; + assoc_ind = &sap_ap_event.sapevt.sapAssocIndication; + + cdf_copy_macaddr(&assoc_ind->staMac, &csr_roaminfo->peerMac); + assoc_ind->staId = csr_roaminfo->staId; + assoc_ind->status = 0; + /* Required for indicating the frames to upper layer */ + assoc_ind->beaconLength = csr_roaminfo->beaconLength; + assoc_ind->beaconPtr = csr_roaminfo->beaconPtr; + assoc_ind->assocReqLength = csr_roaminfo->assocReqLength; + assoc_ind->assocReqPtr = csr_roaminfo->assocReqPtr; + assoc_ind->fWmmEnabled = csr_roaminfo->wmmEnabledSta; + if (csr_roaminfo->u.pConnectedProfile != NULL) { + assoc_ind->negotiatedAuthType = + csr_roaminfo->u.pConnectedProfile->AuthType; + assoc_ind->negotiatedUCEncryptionType = + csr_roaminfo->u.pConnectedProfile->EncryptionType; + assoc_ind->negotiatedMCEncryptionType = + csr_roaminfo->u.pConnectedProfile->mcEncryptionType; + assoc_ind->fAuthRequired = csr_roaminfo->fAuthRequired; + } + break; + case eSAP_START_BSS_EVENT: + sap_ap_event.sapHddEventCode = eSAP_START_BSS_EVENT; + bss_complete = &sap_ap_event.sapevt.sapStartBssCompleteEvent; + + bss_complete->status = (eSapStatus) context; + if (csr_roaminfo != NULL) + bss_complete->staId = csr_roaminfo->staId; + else + bss_complete->staId = 0; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("(eSAP_START_BSS_EVENT): staId = %d"), + bss_complete->staId); + + bss_complete->operatingChannel = (uint8_t) sap_ctx->channel; + bss_complete->sessionId = sap_ctx->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: +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + case eSAP_ACS_SCAN_SUCCESS_EVENT: +#endif + sap_ap_event.sapHddEventCode = sap_hddevent; + sap_ap_event.sapevt.sapStopBssCompleteEvent.status = + (eSapStatus) context; + break; + + case eSAP_ACS_CHANNEL_SELECTED: + sap_ap_event.sapHddEventCode = sap_hddevent; + acs_selected = &sap_ap_event.sapevt.sap_ch_selected; + if (eSAP_STATUS_SUCCESS == (eSapStatus)context) { + acs_selected->pri_ch = sap_ctx->acs_cfg->pri_ch; + acs_selected->ht_sec_ch = sap_ctx->acs_cfg->ht_sec_ch; + acs_selected->ch_width = sap_ctx->acs_cfg->ch_width; + acs_selected->vht_seg0_center_ch = + sap_ctx->acs_cfg->vht_seg0_center_ch; + acs_selected->vht_seg1_center_ch = + sap_ctx->acs_cfg->vht_seg1_center_ch; + } else if (eSAP_STATUS_FAILURE == (eSapStatus)context) { + acs_selected->pri_ch = 0; + } + break; + + case eSAP_STOP_BSS_EVENT: + sap_ap_event.sapHddEventCode = eSAP_STOP_BSS_EVENT; + sap_ap_event.sapevt.sapStopBssCompleteEvent.status = + (eSapStatus) context; + break; + + case eSAP_STA_ASSOC_EVENT: + case eSAP_STA_REASSOC_EVENT: + reassoc_complete = + &sap_ap_event.sapevt.sapStationAssocReassocCompleteEvent; + + if (csr_roaminfo->fReassocReq) + sap_ap_event.sapHddEventCode = eSAP_STA_REASSOC_EVENT; + else + sap_ap_event.sapHddEventCode = eSAP_STA_ASSOC_EVENT; + + cdf_copy_macaddr(&reassoc_complete->staMac, + &csr_roaminfo->peerMac); + reassoc_complete->staId = csr_roaminfo->staId; + reassoc_complete->statusCode = csr_roaminfo->statusCode; + reassoc_complete->iesLen = csr_roaminfo->rsnIELen; + cdf_mem_copy(reassoc_complete->ies, csr_roaminfo->prsnIE, + csr_roaminfo->rsnIELen); + +#ifdef FEATURE_WLAN_WAPI + if (csr_roaminfo->wapiIELen) { + uint8_t len = reassoc_complete->iesLen; + reassoc_complete->iesLen += csr_roaminfo->wapiIELen; + cdf_mem_copy(&reassoc_complete->ies[len], + csr_roaminfo->pwapiIE, + csr_roaminfo->wapiIELen); + } +#endif + if (csr_roaminfo->addIELen) { + uint8_t len = reassoc_complete->iesLen; + reassoc_complete->iesLen += csr_roaminfo->addIELen; + cdf_mem_copy(&reassoc_complete->ies[len], + csr_roaminfo->paddIE, + csr_roaminfo->addIELen); + } + + /* also fill up the channel info from the csr_roamInfo */ + chaninfo = &reassoc_complete->chan_info; + + chaninfo->chan_id = csr_roaminfo->chan_info.chan_id; + chaninfo->mhz = csr_roaminfo->chan_info.mhz; + chaninfo->info = csr_roaminfo->chan_info.info; + chaninfo->band_center_freq1 = + csr_roaminfo->chan_info.band_center_freq1; + chaninfo->band_center_freq2 = + csr_roaminfo->chan_info.band_center_freq2; + chaninfo->reg_info_1 = + csr_roaminfo->chan_info.reg_info_1; + chaninfo->reg_info_2 = + csr_roaminfo->chan_info.reg_info_2; + + reassoc_complete->wmmEnabled = csr_roaminfo->wmmEnabledSta; + reassoc_complete->status = (eSapStatus) context; + reassoc_complete->timingMeasCap = csr_roaminfo->timingMeasCap; + break; + + case eSAP_STA_DISASSOC_EVENT: + sap_ap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT; + disassoc_comp = + &sap_ap_event.sapevt.sapStationDisassocCompleteEvent; + + cdf_copy_macaddr(&disassoc_comp->staMac, + &csr_roaminfo->peerMac); + disassoc_comp->staId = csr_roaminfo->staId; + if (csr_roaminfo->reasonCode == eCSR_ROAM_RESULT_FORCED) + disassoc_comp->reason = eSAP_USR_INITATED_DISASSOC; + else + disassoc_comp->reason = eSAP_MAC_INITATED_DISASSOC; + + disassoc_comp->statusCode = csr_roaminfo->statusCode; + disassoc_comp->status = (eSapStatus) context; + break; + + case eSAP_STA_SET_KEY_EVENT: + sap_ap_event.sapHddEventCode = eSAP_STA_SET_KEY_EVENT; + key_complete = + &sap_ap_event.sapevt.sapStationSetKeyCompleteEvent; + key_complete->status = (eSapStatus) context; + cdf_copy_macaddr(&key_complete->peerMacAddr, + &csr_roaminfo->peerMac); + break; + + case eSAP_STA_MIC_FAILURE_EVENT: + sap_ap_event.sapHddEventCode = eSAP_STA_MIC_FAILURE_EVENT; + mic_failure = &sap_ap_event.sapevt.sapStationMICFailureEvent; + + cdf_mem_copy(&mic_failure->srcMacAddr, + csr_roaminfo->u.pMICFailureInfo->srcMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&mic_failure->staMac.bytes, + csr_roaminfo->u.pMICFailureInfo->taMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&mic_failure->dstMacAddr.bytes, + csr_roaminfo->u.pMICFailureInfo->dstMacAddr, + sizeof(tSirMacAddr)); + mic_failure->multicast = + csr_roaminfo->u.pMICFailureInfo->multicast; + mic_failure->IV1 = csr_roaminfo->u.pMICFailureInfo->IV1; + mic_failure->keyId = csr_roaminfo->u.pMICFailureInfo->keyId; + cdf_mem_copy(mic_failure->TSC, + csr_roaminfo->u.pMICFailureInfo->TSC, + SIR_CIPHER_SEQ_CTR_SIZE); + break; + + case eSAP_ASSOC_STA_CALLBACK_EVENT: + break; + + case eSAP_WPS_PBC_PROBE_REQ_EVENT: + sap_ap_event.sapHddEventCode = eSAP_WPS_PBC_PROBE_REQ_EVENT; + + cdf_mem_copy(&sap_ap_event.sapevt.sapPBCProbeReqEvent. + WPSPBCProbeReq, csr_roaminfo->u.pWPSPBCProbeReq, + sizeof(tSirWPSPBCProbeReq)); + break; + + case eSAP_INDICATE_MGMT_FRAME: + sap_ap_event.sapHddEventCode = eSAP_INDICATE_MGMT_FRAME; + mgmt_frame = &sap_ap_event.sapevt.sapManagementFrameInfo; + + mgmt_frame->nFrameLength = csr_roaminfo->nFrameLength; + mgmt_frame->pbFrames = csr_roaminfo->pbFrames; + mgmt_frame->frameType = csr_roaminfo->frameType; + mgmt_frame->rxChan = csr_roaminfo->rxChan; + break; + + case eSAP_REMAIN_CHAN_READY: + sap_ap_event.sapHddEventCode = eSAP_REMAIN_CHAN_READY; + sap_ap_event.sapevt.sap_roc_ind.scan_id = + sap_ctx->roc_ind_scan_id; + break; + case eSAP_SEND_ACTION_CNF: + sap_ap_event.sapHddEventCode = eSAP_SEND_ACTION_CNF; + sap_ap_event.sapevt.sapActionCnf.actionSendSuccess = + (eSapStatus) context; + break; + + case eSAP_DISCONNECT_ALL_P2P_CLIENT: + sap_ap_event.sapHddEventCode = eSAP_DISCONNECT_ALL_P2P_CLIENT; + sap_ap_event.sapevt.sapActionCnf.actionSendSuccess = + (eSapStatus) context; + break; + + case eSAP_MAC_TRIG_STOP_BSS_EVENT: + sap_ap_event.sapHddEventCode = eSAP_MAC_TRIG_STOP_BSS_EVENT; + sap_ap_event.sapevt.sapActionCnf.actionSendSuccess = + (eSapStatus) context; + break; + + case eSAP_UNKNOWN_STA_JOIN: + sap_ap_event.sapHddEventCode = eSAP_UNKNOWN_STA_JOIN; + cdf_mem_copy((void *) sap_ap_event.sapevt.sapUnknownSTAJoin. + macaddr.bytes, (void *) context, + CDF_MAC_ADDR_SIZE); + break; + + case eSAP_MAX_ASSOC_EXCEEDED: + sap_ap_event.sapHddEventCode = eSAP_MAX_ASSOC_EXCEEDED; + cdf_copy_macaddr(&sap_ap_event.sapevt. + sapMaxAssocExceeded.macaddr, + &csr_roaminfo->peerMac); + break; + + case eSAP_CHANNEL_CHANGE_EVENT: + /* + * Reconfig ACS result info. For DFS AP-AP Mode Sec AP ACS + * follows pri AP + */ + sap_ctx->acs_cfg->pri_ch = sap_ctx->channel; + sap_ctx->acs_cfg->ch_width = sap_ctx->ch_params.ch_width; + sap_config_acs_result(hal, sap_ctx, sap_ctx->secondary_ch); + + sap_ap_event.sapHddEventCode = eSAP_CHANNEL_CHANGE_EVENT; + + acs_selected = &sap_ap_event.sapevt.sap_ch_selected; + acs_selected->pri_ch = sap_ctx->acs_cfg->pri_ch; + acs_selected->ht_sec_ch = sap_ctx->acs_cfg->ht_sec_ch; + acs_selected->ch_width = sap_ctx->acs_cfg->ch_width; + acs_selected->vht_seg0_center_ch = + sap_ctx->acs_cfg->vht_seg0_center_ch; + acs_selected->vht_seg1_center_ch = + sap_ctx->acs_cfg->vht_seg1_center_ch; + break; + + case eSAP_DFS_NOL_GET: + sap_ap_event.sapHddEventCode = eSAP_DFS_NOL_GET; + sap_ap_event.sapevt.sapDfsNolInfo.sDfsList = + NUM_5GHZ_CHANNELS * sizeof(tSapDfsNolInfo); + sap_ap_event.sapevt.sapDfsNolInfo.pDfsList = (void *) + (&mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList[0]); + break; + + case eSAP_DFS_NOL_SET: + sap_ap_event.sapHddEventCode = eSAP_DFS_NOL_SET; + sap_ap_event.sapevt.sapDfsNolInfo.sDfsList = + mac_ctx->sap.SapDfsInfo.numCurrentRegDomainDfsChannels * + sizeof(tSapDfsNolInfo); + sap_ap_event.sapevt.sapDfsNolInfo.pDfsList = (void *) + (&mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList[0]); + break; + + default: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("SAP Unknown callback event = %d"), + sap_hddevent); + break; + } + cdf_status = (*sap_ctx->pfnSapEventCallback) + (&sap_ap_event, sap_ctx->pUsrContext); + + return cdf_status; + +} + +/*========================================================================== + 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); + uint8_t intf = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) && + pMac->sap.sapCtxList[intf].pSapContext != NULL) { + return pMac->sap.sapCtxList[intf].pSapContext; + } + } + + return NULL; +} + +/*========================================================================== + FUNCTION sap_close_session + + 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 CDF_STATUS code associated with performing the operation + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + NA + ============================================================================*/ +CDF_STATUS sap_close_session(tHalHandle hHal, + ptSapContext sapContext, + csr_roamSessionCloseCallback callback, bool valid) +{ + CDF_STATUS cdf_status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (false == valid) { + cdf_status = sme_close_session(hHal, + sapContext->sessionId, + callback, NULL); + } else { + cdf_status = sme_close_session(hHal, + sapContext->sessionId, + callback, sapContext); + } + + sapContext->isCacStartNotified = false; + sapContext->isCacEndNotified = 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 */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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) { + cdf_mc_timer_stop(&pMac->sap.SapDfsInfo. + sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + cdf_mc_timer_destroy( + &pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + } + pMac->sap.SapDfsInfo.cac_state = eSAP_DFS_DO_NOT_SKIP_CAC; + sap_cac_reset_notify(hHal); + cdf_mem_zero(&pMac->sap, sizeof(pMac->sap)); + } + + return cdf_status; +} + +/*========================================================================== + FUNCTION sap_cac_reset_notify + + 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_cac_reset_notify(tHalHandle hHal) +{ + uint8_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 (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) + && pMac->sap.sapCtxList[intf].pSapContext != NULL) { + pSapContext->isCacStartNotified = false; + pSapContext->isCacEndNotified = false; + } + } +} + +/*========================================================================== + FUNCTION sap_cac_start_notify + + DESCRIPTION Function will be called to notify eSAP_DFS_CAC_START event + to HDD + + DEPENDENCIES PARAMETERS + IN hHAL : HAL pointer + + RETURN VALUE : CDF_STATUS. + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS sap_cac_start_notify(tHalHandle hHal) +{ + uint8_t intf = 0; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + ptSapContext pSapContext = + (ptSapContext) pMac->sap.sapCtxList[intf].pSapContext; + if (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) + && pMac->sap.sapCtxList[intf].pSapContext != NULL && + (false == pSapContext->isCacStartNotified)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Signaling eSAP_DFS_CAC_START to HDD for sapctx[%p]", + pSapContext); + + cdf_status = sap_signal_hdd_event(pSapContext, NULL, + eSAP_DFS_CAC_START, + (void *) + eSAP_STATUS_SUCCESS); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacStartNotified on interface[%d]", + __func__, intf); + return cdf_status; + } + pSapContext->isCacStartNotified = true; + } + } + return cdf_status; +} + +/*========================================================================== + FUNCTION sap_cac_end_notify + + DESCRIPTION Function will be called to notify eSAP_DFS_CAC_END event + to HDD + + DEPENDENCIES PARAMETERS + IN hHAL : HAL pointer + + RETURN VALUE : CDF_STATUS. + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS sap_cac_end_notify(tHalHandle hHal, tCsrRoamInfo *roamInfo) +{ + uint8_t intf; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS cdf_status = CDF_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 (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) + && pMac->sap.sapCtxList[intf].pSapContext != NULL && + (false == pSapContext->isCacEndNotified)) { + pSapContext = pMac->sap.sapCtxList[intf].pSapContext; + cdf_status = sap_signal_hdd_event(pSapContext, NULL, + eSAP_DFS_CAC_END, + (void *) + eSAP_STATUS_SUCCESS); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacEndNotified on interface[%d]", + __func__, intf); + return cdf_status; + } + pSapContext->isCacEndNotified = true; + pMac->sap.SapDfsInfo.sap_radar_found_status = false; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Start beacon request on sapctx[%p]", + pSapContext); + + /* Start beaconing on the new channel */ + wlansap_start_beacon_req(pSapContext); + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 */ + cdf_status = sap_signal_hdd_event(pSapContext, roamInfo, + eSAP_START_BSS_EVENT, + (void *) + eSAP_STATUS_SUCCESS); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "In %s, failed setting isCacEndNotified on interface[%d]", + __func__, intf); + return cdf_status; + } + + /* Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 cdf_status; +} + +/** + * sap_fsm_state_disconnected() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * @hal: HAL handle + * + * This function is called for state transition from "eSAP_DISCONNECTED" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_disconnected(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx, + tHalHandle hal) +{ + uint32_t msg = sap_event->event; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + if (msg == eSAP_HDD_START_INFRA_BSS) { + /* + * Transition from eSAP_DISCONNECTED to eSAP_CH_SELECT + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("new from state %s => %s"), + "eSAP_DISCONNECTED", "eSAP_CH_SELECT"); + + /* There can be one SAP Session for softap */ + if (sap_ctx->isSapSessionOpen == eSAP_TRUE) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + FL("SME Session is already opened")); + return CDF_STATUS_E_EXISTS; + } + + sap_ctx->sessionId = 0xff; + + if ((sap_ctx->channel == AUTO_CHANNEL_SELECT) && + (sap_ctx->isScanSessionOpen == eSAP_FALSE)) { + uint32_t type, subtype; + if (CDF_STATUS_SUCCESS == cds_get_vdev_types( + CDF_STA_MODE, &type, &subtype)) { + /* Open SME Session for scan */ + cdf_status = sme_open_session(hal, NULL, + sap_ctx, sap_ctx->self_mac_addr, + &sap_ctx->sessionId, type, subtype); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("Error: calling sme_open_session")); + } else { + sap_ctx->isScanSessionOpen = eSAP_TRUE; + } + } + } + /* init dfs channel nol */ + sap_init_dfs_channel_nol_list(sap_ctx); + + /* Set SAP device role */ + sap_ctx->sapsMachine = eSAP_CH_SELECT; + + /* + * Perform sme_ScanRequest. This scan request is post start bss + * request so, set the third to false. + */ + cdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false); + + /* + * Transition from eSAP_DISCONNECTED to eSAP_CH_SELECT + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "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 + */ + sap_ctx->sapsMachine = eSAP_DFS_CAC_WAIT; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("from state eSAP_DISCONNECTED => SAP_DFS_CAC_WAIT")); + if (mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running != true) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: starting dfs cac timer on sapctx[%p]"), + sap_ctx); + sap_start_dfs_cac_timer(sap_ctx); + } + + cdf_status = sap_cac_start_notify(hal); + } else if (msg == eSAP_CHANNEL_SELECTION_RETRY) { + /* Set SAP device role */ + sap_ctx->sapsMachine = eSAP_CH_SELECT; + + /* + * Perform sme_ScanRequest. This scan request is post start bss + * request so, set the third to false. + */ + cdf_status = sap_goto_channel_sel(sap_ctx, sap_event, false); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, event msg %d"), + "eSAP_DISCONNECTED", msg); + } + + return cdf_status; +} + +/** + * sap_fsm_state_ch_select() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * @hal: HAL handle + * + * This function is called for state transition from "eSAP_CH_SELECT" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_ch_select(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx, + tHalHandle hal) +{ + uint32_t msg = sap_event->event; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + uint32_t cbmode; + bool b_leak_chan = false; +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + uint8_t temp_chan; + tSapDfsNolInfo *p_nol; +#endif + + if (sap_ctx->isScanSessionOpen == eSAP_TRUE) { + /* scan completed, so close the session */ + cdf_status = sme_close_session(hal, sap_ctx->sessionId, + NULL, NULL); + if (CDF_STATUS_SUCCESS != cdf_status) + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("CloseSession error event msg %d"), msg); + else + sap_ctx->isScanSessionOpen = eSAP_FALSE; + sap_ctx->sessionId = 0xff; + } + + if (msg == eSAP_MAC_SCAN_COMPLETE) { + /* get the bonding mode */ + if (sap_ctx->channel <= 14) + cbmode = sme_get_cb_phy_state_from_cb_ini_value( + sme_get_channel_bonding_mode24_g(hal)); + else + cbmode = sme_get_cb_phy_state_from_cb_ini_value( + sme_get_channel_bonding_mode5_g(hal)); + +#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION + temp_chan = sap_ctx->channel; + p_nol = mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList; + + sap_mark_channels_leaking_into_nol(sap_ctx, + cbmode, p_nol, 1, &temp_chan); + + /* + * if selelcted channel has leakage to channels + * in NOL, the temp_chan will be reset + */ + b_leak_chan = (temp_chan != sap_ctx->channel); +#endif + /* + * check if channel is in DFS_NOL or if the channel + * has leakage to the channels in NOL + */ + if (sap_dfs_is_channel_in_nol_list(sap_ctx, sap_ctx->channel, + cbmode) || b_leak_chan) { + uint8_t ch; + + /* find a new available channel */ + ch = sap_random_channel_sel(sap_ctx); + if (ch == 0) { + /* No available channel found */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("No available channel found!!!")); + sap_signal_hdd_event(sap_ctx, NULL, + eSAP_DFS_NO_AVAILABLE_CHANNEL, + (void *)eSAP_STATUS_SUCCESS); + return CDF_STATUS_E_FAULT; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("channel %d is in NOL, StartBss on new channel %d"), + sap_ctx->channel, ch); + + sap_ctx->channel = ch; + sme_set_ch_params(hal, sap_ctx->csr_roamProfile.phyMode, + sap_ctx->channel, sap_ctx->secondary_ch, + &sap_ctx->ch_params); + } + if (sap_ctx->channel > 14 && + (sap_ctx->csr_roamProfile.phyMode == eCSR_DOT11_MODE_11g || + sap_ctx->csr_roamProfile.phyMode == + eCSR_DOT11_MODE_11g_ONLY)) + sap_ctx->csr_roamProfile.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 (cds_concurrent_beaconing_sessions_running()) { + uint16_t con_ch; + + con_ch = sme_get_concurrent_operation_channel(hal); + if (con_ch && CDS_IS_DFS_CH(con_ch)) + sap_ctx->channel = con_ch; + } +#endif + /* + * Transition from eSAP_CH_SELECT to eSAP_STARTING + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_CH_SELECT", "eSAP_STARTING"); + /* Channel selected. Now can sap_goto_starting */ + sap_ctx->sapsMachine = eSAP_STARTING; + /* Specify the channel */ + sap_ctx->csr_roamProfile.ChannelInfo.numOfChannels = + 1; + sap_ctx->csr_roamProfile.ChannelInfo.ChannelList = + &sap_ctx->csr_roamProfile.operationChannel; + sap_ctx->csr_roamProfile.operationChannel = + (uint8_t) sap_ctx->channel; + sap_ctx->csr_roamProfile.ch_params.ch_width = + sap_ctx->ch_params.ch_width; + sap_ctx->csr_roamProfile.ch_params.center_freq_seg0 = + sap_ctx->ch_params.center_freq_seg0; + sap_ctx->csr_roamProfile.ch_params.center_freq_seg1 = + sap_ctx->ch_params.center_freq_seg1; + sap_ctx->csr_roamProfile.ch_params.sec_ch_offset = + sap_ctx->ch_params.sec_ch_offset; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("notify hostapd about channel selection: %d"), + sap_ctx->channel); + sap_signal_hdd_event(sap_ctx, NULL, + eSAP_CHANNEL_CHANGE_EVENT, + (void *) eSAP_STATUS_SUCCESS); + cdf_status = sap_goto_starting(sap_ctx, sap_event, + eCSR_BSS_TYPE_INFRA_AP); + } else if (msg == eSAP_CHANNEL_SELECTION_FAILED) { + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Cannot start BSS, ACS Fail")); + } else if (msg == eSAP_HDD_STOP_INFRA_BSS) { + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + sap_signal_hdd_event(sap_ctx, NULL, eSAP_START_BSS_EVENT, + (void *)eSAP_STATUS_FAILURE); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: BSS stopped when Ch select in Progress", __func__); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, invalid event msg %d"), + "eSAP_CH_SELECT", msg); + } + + return cdf_status; +} + +/** + * sap_fsm_state_dfs_cac_wait() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * @hal: HAL handle + * + * This function is called for state transition from "eSAP_DFS_CAC_WAIT" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_dfs_cac_wait(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx, + tHalHandle hal) +{ + uint32_t msg = sap_event->event; + tCsrRoamInfo *roam_info = (tCsrRoamInfo *) (sap_event->params); + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + if (msg == eSAP_DFS_CHANNEL_CAC_START) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_CH_SELECT", "eSAP_DFS_CAC_WAIT"); + if (mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running != true) + sap_start_dfs_cac_timer(sap_ctx); + cdf_status = sap_cac_start_notify(hal); + } else if (msg == eSAP_DFS_CHANNEL_CAC_RADAR_FOUND) { + uint8_t intf; + /* + * Radar found while performing channel availability + * check, need to switch the channel again + */ + eCsrPhyMode phymode = sap_ctx->csr_roamProfile.phyMode; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "ENTERTRED CAC WAIT STATE-->eSAP_DISCONNECTING\n"); + if (mac_ctx->sap.SapDfsInfo.target_channel) { + sme_set_ch_params(hal, phymode, + mac_ctx->sap.SapDfsInfo.target_channel, 0, + &sap_ctx->ch_params); + } + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + ptSapContext t_sap_ctx; + if (((CDF_SAP_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona) || + (CDF_P2P_GO_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona)) && + mac_ctx->sap.sapCtxList[intf].pSapContext != NULL) { + t_sap_ctx = + mac_ctx->sap.sapCtxList[intf].pSapContext; + /* SAP to be moved to DISCONNECTING state */ + sap_ctx->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 + */ + sap_signal_hdd_event(t_sap_ctx, NULL, + eSAP_DFS_RADAR_DETECT, + (void *)eSAP_STATUS_SUCCESS); + + wlansap_channel_change_request( + (void *)t_sap_ctx, + mac_ctx->sap.SapDfsInfo.target_channel); + } + } + } else if (msg == eSAP_DFS_CHANNEL_CAC_END) { + cdf_status = sap_cac_end_notify(hal, roam_info); + } else if (msg == eSAP_HDD_STOP_INFRA_BSS) { + /* Transition from eSAP_DFS_CAC_WAIT to eSAP_DISCONNECTING */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "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(hal)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: no sessions are valid, stopping timer")); + sap_stop_dfs_cac_timer(sap_ctx); + } + + sap_ctx->sapsMachine = eSAP_DISCONNECTING; + cdf_status = sap_goto_disconnecting(sap_ctx); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, invalid event msg %d"), + "eSAP_DFS_CAC_WAIT", msg); + } + + return cdf_status; +} + +/** + * sap_fsm_state_starting() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * @hal: HAL handle + * + * This function is called for state transition from "eSAP_STARTING" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_starting(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx, + tHalHandle hal) +{ + uint32_t msg = sap_event->event; + tCsrRoamInfo *roam_info = (tCsrRoamInfo *) (sap_event->params); + tSapDfsInfo *sap_dfs_info; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + if (msg == eSAP_MAC_START_BSS_SUCCESS) { + /* + * Transition from eSAP_STARTING to eSAP_STARTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state channel = %d %s => %s"), + sap_ctx->channel, "eSAP_STARTING", "eSAP_STARTED"); + sap_ctx->sapsMachine = eSAP_STARTED; + + /* Action code for transition */ + cdf_status = sap_signal_hdd_event(sap_ctx, roam_info, + eSAP_START_BSS_EVENT, + (void *) 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 (CHANNEL_STATE_DFS == + cds_get_channel_state(sap_ctx->channel)) { + sap_dfs_info = &mac_ctx->sap.SapDfsInfo; + if ((false == sap_dfs_info->ignore_cac) && + (eSAP_DFS_DO_NOT_SKIP_CAC == + sap_dfs_info->cac_state)) { + /* Move the device in CAC_WAIT_STATE */ + sap_ctx->sapsMachine = eSAP_DFS_CAC_WAIT; + + /* + * Need to stop the OS transmit queues, + * so that no traffic can flow down the stack + */ + + /* Start CAC wait timer */ + if (sap_dfs_info->is_dfs_cac_timer_running != + true) + sap_start_dfs_cac_timer(sap_ctx); + cdf_status = sap_cac_start_notify(hal); + + } else { + wlansap_start_beacon_req(sap_ctx); + } + } + } else if (msg == eSAP_MAC_START_FAILS) { + /* + * Transition from STARTING to DISCONNECTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("from state %s => %s"), + "eSAP_STARTING", "eSAP_DISCONNECTED"); + + /*Action code for transition */ + cdf_status = sap_signal_hdd_event(sap_ctx, NULL, + eSAP_START_BSS_EVENT, + (void *) eSAP_STATUS_FAILURE); + cdf_status = sap_goto_disconnected(sap_ctx); + /* Advance outer statevar */ + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + } else if (msg == eSAP_HDD_STOP_INFRA_BSS) { + /* + * Transition from eSAP_STARTING to eSAP_DISCONNECTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_STARTING", "eSAP_DISCONNECTED"); + + /* Advance outer statevar */ + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + cdf_status = sap_signal_hdd_event(sap_ctx, NULL, + eSAP_START_BSS_EVENT, + (void *) eSAP_STATUS_FAILURE); + cdf_status = sap_goto_disconnected(sap_ctx); + /* Close the SME session */ + + if (eSAP_TRUE == sap_ctx->isSapSessionOpen) { + if (CDF_STATUS_SUCCESS == sap_close_session(hal, + sap_ctx, NULL, false)) + sap_ctx->isSapSessionOpen = eSAP_FALSE; + } + } else if (msg == eSAP_OPERATING_CHANNEL_CHANGED) { + /* The operating channel has changed, update hostapd */ + sap_ctx->channel = + (uint8_t) mac_ctx->sap.SapDfsInfo.target_channel; + + sap_ctx->sapsMachine = eSAP_STARTED; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_STARTING", "eSAP_STARTED"); + + /* Indicate change in the state to upper layers */ + cdf_status = sap_signal_hdd_event(sap_ctx, roam_info, + eSAP_START_BSS_EVENT, + (void *)eSAP_STATUS_SUCCESS); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, invalid event msg %d"), + "eSAP_STARTING", msg); + } + + return cdf_status; +} + +/** + * sap_fsm_state_started() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * + * This function is called for state transition from "eSAP_STARTED" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_started(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx) +{ + uint32_t msg = sap_event->event; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + if (msg == eSAP_HDD_STOP_INFRA_BSS) { + /* + * Transition from eSAP_STARTED to eSAP_DISCONNECTING + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_STARTED", "eSAP_DISCONNECTING"); + sap_ctx->sapsMachine = eSAP_DISCONNECTING; + cdf_status = sap_goto_disconnecting(sap_ctx); + } else if (eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START == msg) { + uint8_t intf; + /* + * Radar is seen on the current operating channel + * send CSA IE for all associated stations + * Request for CSA IE transmission + */ + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + ptSapContext temp_sap_ctx; + if (((CDF_SAP_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona) || + (CDF_P2P_GO_MODE == + mac_ctx->sap.sapCtxList[intf].sapPersona)) && + mac_ctx->sap.sapCtxList[intf].pSapContext != NULL) { + temp_sap_ctx = + mac_ctx->sap.sapCtxList[intf].pSapContext; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: Sending CSAIE for sapctx[%p]"), + temp_sap_ctx); + + cdf_status = wlansap_dfs_send_csa_ie_request( + (void *) temp_sap_ctx); + } + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, invalid event msg %d"), + "eSAP_STARTED", msg); + } + + return cdf_status; +} + +/** + * sap_fsm_state_disconnecting() - utility function called from sap fsm + * @sap_ctx: SAP context + * @sap_event: SAP event buffer + * @mac_ctx: global MAC context + * + * This function is called for state transition from "eSAP_DISCONNECTING" + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_fsm_state_disconnecting(ptSapContext sap_ctx, + ptWLAN_SAPEvent sap_event, tpAniSirGlobal mac_ctx, + tHalHandle hal) +{ + uint32_t msg = sap_event->event; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + + if (msg == eSAP_MAC_READY_FOR_CONNECTIONS) { + /* + * Transition from eSAP_DISCONNECTING to eSAP_DISCONNECTED + * (both without substates) + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("from state %s => %s"), + "eSAP_DISCONNECTING", "eSAP_DISCONNECTED"); + sap_ctx->sapsMachine = eSAP_DISCONNECTED; + + /* Close the SME session */ + if (eSAP_TRUE == sap_ctx->isSapSessionOpen) { + sap_ctx->isSapSessionOpen = eSAP_FALSE; + cdf_status = sap_close_session(hal, sap_ctx, + sap_roam_session_close_callback, true); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_status = sap_signal_hdd_event(sap_ctx, NULL, + eSAP_STOP_BSS_EVENT, + (void *)eSAP_STATUS_SUCCESS); + } + } + } else if (msg == eWNI_SME_CHANNEL_CHANGE_REQ) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: Send channel change request on sapctx[%p]"), + sap_ctx); + /* + * Most likely, radar has been detected and SAP wants to + * change the channel + */ + cdf_status = wlansap_channel_change_request((void *) sap_ctx, + mac_ctx->sap.SapDfsInfo.target_channel); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("Sending DFS eWNI_SME_CHANNEL_CHANGE_REQ")); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("in state %s, invalid event msg %d"), + "eSAP_DISCONNECTING", msg); + } + + return cdf_status; +} + +/** + * sap_fsm() - SAP statem machine entry function + * @sap_ctx: SAP context + * @sap_event: SAP event + * + * SAP statem machine entry function + * + * Return: CDF_STATUS + */ +CDF_STATUS sap_fsm(ptSapContext sap_ctx, ptWLAN_SAPEvent sap_event) +{ + /* + * Retrieve the phy link state machine structure + * from the sap_ctx value + * state var that keeps track of state machine + */ + eSapFsmStates_t state_var = sap_ctx->sapsMachine; + uint32_t msg = sap_event->event; /* State machine input event message */ + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx); + tpAniSirGlobal mac_ctx; + + if (NULL == hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid hal")); + return CDF_STATUS_E_FAILURE; + } + + mac_ctx = PMAC_STRUCT(hal); + if (NULL == mac_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid MAC context")); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_DEBUG, + FL("sap_ctx=%p, state_var=%d, msg=0x%x"), + sap_ctx, state_var, msg); + + switch (state_var) { + case eSAP_DISCONNECTED: + cdf_status = sap_fsm_state_disconnected(sap_ctx, sap_event, + mac_ctx, hal); + break; + + case eSAP_CH_SELECT: + cdf_status = sap_fsm_state_ch_select(sap_ctx, sap_event, + mac_ctx, hal); + break; + + case eSAP_DFS_CAC_WAIT: + cdf_status = sap_fsm_state_dfs_cac_wait(sap_ctx, sap_event, + mac_ctx, hal); + break; + + case eSAP_STARTING: + cdf_status = sap_fsm_state_starting(sap_ctx, sap_event, + mac_ctx, hal); + break; + + case eSAP_STARTED: + cdf_status = sap_fsm_state_started(sap_ctx, sap_event, + mac_ctx); + break; + + case eSAP_DISCONNECTING: + cdf_status = sap_fsm_state_disconnecting(sap_ctx, sap_event, + mac_ctx, hal); + break; + } + return cdf_status; +} + +eSapStatus +sapconvert_to_csr_profile(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; + + cdf_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; + cdf_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 = + cdf_mem_malloc(pconfig_params->RSNWPAReqIELength); + if (NULL == profile->pRSNReqIE) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + " %s Fail to alloc memory", __func__); + return eSAP_STATUS_FAILURE; + } + cdf_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 = (uint16_t) 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]) + cdf_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 sap_free_roam_profile(tCsrRoamProfile *profile) +{ + if (profile->pRSNReqIE) { + cdf_mem_free(profile->pRSNReqIE); + profile->pRSNReqIE = NULL; + } +} + +void sap_sort_mac_list(struct cdf_mac_addr *macList, uint8_t size) +{ + uint8_t outer, inner; + struct cdf_mac_addr temp; + int32_t nRes = -1; + + if ((NULL == macList) || (size > MAX_ACL_MAC_ADDRESS)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = + cdf_mem_compare2((macList + inner)->bytes, + (macList + inner + 1)->bytes, + CDF_MAC_ADDR_SIZE); + if (nRes > 0) { + cdf_mem_copy(temp.bytes, + (macList + inner + 1)->bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy((macList + inner + 1)->bytes, + (macList + inner)->bytes, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy((macList + inner)->bytes, + temp.bytes, CDF_MAC_ADDR_SIZE); + } + } + } +} + +eSapBool +sap_search_mac_list(struct cdf_mac_addr *macList, + uint8_t num_mac, uint8_t *peerMac, + uint8_t *index) +{ + int32_t nRes = -1; + int8_t nStart = 0, nEnd, nMiddle; + nEnd = num_mac - 1; + + if ((NULL == macList) || (num_mac > MAX_ACL_MAC_ADDRESS)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = + cdf_mem_compare2(&macList[nMiddle], peerMac, + CDF_MAC_ADDR_SIZE); + + if (0 == nRes) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = (uint8_t) nMiddle; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, "index %d", + *index); + } + return eSAP_TRUE; + } + if (nRes < 0) + nStart = nMiddle + 1; + else + nEnd = nMiddle - 1; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "search not succ"); + return eSAP_FALSE; +} + +void sap_add_mac_to_acl(struct cdf_mac_addr *macList, + uint8_t *size, uint8_t *peerMac) +{ + int32_t nRes = -1; + int i; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "add acl entered"); + + if (NULL == macList || *size == 0 || *size > MAX_ACL_MAC_ADDRESS) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("either buffer is NULL or size = %d is incorrect."), + *size); + return; + } + + for (i = ((*size) - 1); i >= 0; i--) { + nRes = + cdf_mem_compare2(&macList[i], peerMac, CDF_MAC_ADDR_SIZE); + if (nRes > 0) { + /* Move alphabetically greater mac addresses one index down to allow for insertion + of new mac in sorted order */ + cdf_mem_copy((macList + i + 1)->bytes, + (macList + i)->bytes, CDF_MAC_ADDR_SIZE); + } else { + break; + } + } + /* This should also take care of if the element is the first to be added in the list */ + cdf_mem_copy((macList + i + 1)->bytes, peerMac, CDF_MAC_ADDR_SIZE); + /* increment the list size */ + (*size)++; +} + +void sap_remove_mac_from_acl(struct cdf_mac_addr *macList, + uint8_t *size, uint8_t index) +{ + int i; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 sap_search_mac_list 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 ((macList == NULL) || (*size == 0) || + (*size > MAX_ACL_MAC_ADDRESS)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 */ + cdf_mem_copy((macList + i)->bytes, (macList + i + 1)->bytes, + CDF_MAC_ADDR_SIZE); + } + /* The last space should be made empty since all mac addesses moved one step up */ + cdf_mem_zero((macList + (*size) - 1)->bytes, CDF_MAC_ADDR_SIZE); + /* reduce the list size by 1 */ + (*size)--; +} + +void sap_print_acl(struct cdf_mac_addr *macList, uint8_t size) +{ + int i; + uint8_t *macArray; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "print acl entered"); + + if ((NULL == macList) || (size == 0) || (size >= MAX_ACL_MAC_ADDRESS)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, either buffer is NULL or size %d is incorrect.", + __func__, size); + return; + } + + for (i = 0; i < size; i++) { + macArray = (macList + i)->bytes; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "** ACL entry %i - " MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(macArray)); + } + return; +} + +CDF_STATUS sap_is_peer_mac_allowed(ptSapContext sapContext, uint8_t *peerMac) +{ + if (eSAP_ALLOW_ALL == sapContext->eSapMacAddrAclMode) + return CDF_STATUS_SUCCESS; + + if (sap_search_mac_list + (sapContext->acceptMacList, sapContext->nAcceptMac, peerMac, NULL)) + return CDF_STATUS_SUCCESS; + + if (sap_search_mac_list + (sapContext->denyMacList, sapContext->nDenyMac, peerMac, NULL)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, Peer " MAC_ADDRESS_STR " in deny list", + __func__, MAC_ADDR_ARRAY(peerMac)); + return CDF_STATUS_E_FAILURE; + } + /* A new station CAN associate, unless in deny list. Less stringent mode */ + if (eSAP_ACCEPT_UNLESS_DENIED == sapContext->eSapMacAddrAclMode) + return CDF_STATUS_SUCCESS; + + /* A new station CANNOT associate, unless in accept list. More stringent mode */ + if (eSAP_DENY_UNLESS_ACCEPTED == sapContext->eSapMacAddrAclMode) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 CDF_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) { + sap_signal_hdd_event(sapContext, NULL, eSAP_UNKNOWN_STA_JOIN, + (void *) peerMac); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +#ifdef SOFTAP_CHANNEL_RANGE +/** + * sap_get_channel_list() - get the list of channels + * @sap_ctx: sap context + * @ch_list: pointer to channel list array + * @num_ch: pointer to number of channels. + * + * This function populates the list of channels for scanning. + * + * Return: CDF_STATUS + */ +static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, + uint8_t **ch_list, + uint8_t *num_ch) +{ + uint8_t loop_count; + uint8_t *list; + uint8_t ch_count; + uint8_t start_ch_num, band_start_ch; + uint8_t end_ch_num, band_end_ch; + uint32_t en_lte_coex; + tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx); +#ifdef FEATURE_WLAN_CH_AVOID + uint8_t i; +#endif + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + + if (NULL == hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid HAL pointer from p_cds_gctx")); + *num_ch = 0; + *ch_list = NULL; + return CDF_STATUS_E_FAULT; + } + + start_ch_num = sap_ctx->acs_cfg->start_ch; + end_ch_num = sap_ctx->acs_cfg->end_ch; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("startChannel %d, EndChannel %d, HW:%d"), + start_ch_num, end_ch_num, + sap_ctx->acs_cfg->hw_mode); + + wlansap_extend_to_acs_range(&start_ch_num, &end_ch_num, + &band_start_ch, &band_end_ch); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("expanded startChannel %d,EndChannel %d"), + start_ch_num, end_ch_num); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("band_start_ch %d, band_end_ch %d"), + band_start_ch, band_end_ch); + + sme_cfg_get_int(hal, WNI_CFG_ENABLE_LTE_COEX, &en_lte_coex); + + /* Check if LTE coex is enabled and 2.4GHz is selected */ + if (en_lte_coex && (band_start_ch == RF_CHAN_1) && + (band_end_ch == RF_CHAN_14)) { + /* Set 2.4GHz upper limit to channel 9 for LTE COEX */ + band_end_ch = RF_CHAN_9; + } + + /* Allocate the max number of channel supported */ + list = (uint8_t *) cdf_mem_malloc(NUM_5GHZ_CHANNELS + + NUM_24GHZ_CHANNELS); + if (NULL == list) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Unable to allocate channel list")); + *num_ch = 0; + *ch_list = NULL; + return CDF_STATUS_E_NOMEM; + } + + /* Search for the Active channels in the given range */ + ch_count = 0; + for (loop_count = band_start_ch; loop_count <= band_end_ch; + loop_count++) { + /* go to next channel if rf_channel is out of range */ + if ((start_ch_num > rf_channels[loop_count].channelNum) || + (end_ch_num < rf_channels[loop_count].channelNum)) + continue; + /* + * go to next channel if none of these condition pass + * - DFS scan enabled and chan not in CHANNEL_STATE_DISABLE + * - DFS scan disable but chan in CHANNEL_STATE_ENABLE + */ + if (!(((eSAP_TRUE == mac_ctx->scan.fEnableDFSChnlScan) && + (reg_channels[loop_count].enabled)) || + ((eSAP_FALSE == mac_ctx->scan.fEnableDFSChnlScan) && + (CHANNEL_STATE_ENABLE == + reg_channels[loop_count].enabled)))) + continue; + +#ifdef FEATURE_WLAN_CH_AVOID + for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { + if ((safe_channels[i].channelNumber == + rf_channels[loop_count].channelNum)) { + /* Check if channel is safe */ + if (true == safe_channels[i].isSafe) { +#endif +#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE + uint8_t ch; + ch = rf_channels[loop_count].channelNum; + if ((sap_ctx->acs_cfg->skip_scan_status == + eSAP_DO_PAR_ACS_SCAN)) { + if ((ch >= sap_ctx->acs_cfg->skip_scan_range1_stch && + ch <= sap_ctx->acs_cfg->skip_scan_range1_endch) || + (ch >= sap_ctx->acs_cfg->skip_scan_range2_stch && + ch <= sap_ctx->acs_cfg->skip_scan_range2_endch)) { + list[ch_count] = + rf_channels[loop_count].channelNum; + ch_count++; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + FL("%d %d added to ACS ch range"), + ch_count, ch); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("%d %d skipped from ACS ch range"), + ch_count, ch); + } + } else { + list[ch_count] = + rf_channels[loop_count].channelNum; + ch_count++; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + FL("%d %d added to ACS ch range"), + ch_count, ch); + } +#else + list[ch_count] = rf_channels[loop_count].channelNum; + ch_count++; +#endif +#ifdef FEATURE_WLAN_CH_AVOID + } + break; + } + } +#endif + } + if (0 == ch_count) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("No active channels present for the current region")); + /* + * LTE COEX: channel range outside the restricted 2.4GHz + * band limits + */ + if (en_lte_coex && (start_ch_num > band_end_ch)) + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + FL("SAP can't be started as due to LTE COEX")); + } + + /* return the channel list and number of channels to scan */ + *num_ch = ch_count; + if (ch_count != 0) { + *ch_list = list; + } else { + *ch_list = NULL; + cdf_mem_free(list); + } + + for (loop_count = 0; loop_count < ch_count; loop_count++) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_DEBUG, + FL("channel number: %d"), list[loop_count]); + } + return CDF_STATUS_SUCCESS; +} +#endif + +/* + * Function for initializing list of 2.4/5 Ghz [NON-DFS/DFS] + * available channels in the current regulatory domain. + */ +static CDF_STATUS sap_get5_g_hz_channel_list(ptSapContext sapContext) +{ + uint8_t count = 0; + int i; + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Invalid sapContext pointer on sap_get_channel_list"); + return CDF_STATUS_E_FAULT; + } + + if (sapContext->SapAllChnlList.channelList) { + cdf_mem_free(sapContext->SapAllChnlList.channelList); + sapContext->SapAllChnlList.channelList = NULL; + } + + sapContext->SapAllChnlList.channelList = + (tChannelInfo *) cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN * + sizeof(tChannelInfo)); + if (NULL == sapContext->SapAllChnlList.channelList) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + " Memory Allocation failed sap_get_channel_list"); + return CDF_STATUS_E_NOMEM; + } + + for (i = RF_CHAN_36; i <= RF_CHAN_165; i++) { + if (reg_channels[i].enabled == CHANNEL_STATE_ENABLE || + reg_channels[i].enabled == CHANNEL_STATE_DFS) { + sapContext->SapAllChnlList.channelList[count].channel = + rf_channels[i].channelNum; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "%s[%d] CHANNEL = %d", __func__, __LINE__, + sapContext->SapAllChnlList.channelList[count]. + channel); + sapContext->SapAllChnlList.channelList[count].valid = + true; + count++; + } + } + + sapContext->SapAllChnlList.numChannel = count; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "%s[%d] NUMBER OF CHANNELS count = %d" + "sapContext->SapAllChnlList.numChannel = %d", + __func__, __LINE__, count, + sapContext->SapAllChnlList.numChannel); + return CDF_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 + */ +uint8_t sap_indicate_radar(ptSapContext sapContext, + tSirSmeDfsEventInd *dfs_event) +{ + uint8_t target_channel = 0; + tHalHandle hHal; + tpAniSirGlobal pMac; + + if (NULL == sapContext || NULL == dfs_event) { + /* Invalid sap context of dfs event passed */ + return 0; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 = eSAP_TRUE; + + if (sapContext->csr_roamProfile.disableDFSChSwitch) { + return sapContext->channel; + } + + /* set the Radar Found flag in SapDfsInfo */ + pMac->sap.SapDfsInfo.sap_radar_found_status = true; + + sap_get5_g_hz_channel_list(sapContext); + + if (dfs_event->chan_list.nchannels > SIR_DFS_MAX_20M_SUB_CH) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, + FL("nchannels >SIR_DFS_MAX_20M_SUB_CH so resetting")); + dfs_event->chan_list.nchannels = SIR_DFS_MAX_20M_SUB_CH; + } + + sap_mark_dfs_channels(sapContext, dfs_event->chan_list.channels, + dfs_event->chan_list.nchannels, + cds_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 = sap_random_channel_sel(sapContext); + if (0 == target_channel) { + sap_signal_hdd_event(sapContext, NULL, + eSAP_DFS_NO_AVAILABLE_CHANNEL, + (void *) eSAP_STATUS_SUCCESS); + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 sap_fsm(). + */ +void sap_dfs_cac_timer_callback(void *data) +{ + ptSapContext sapContext; + tWLAN_SAPEvent sapEvent; + tHalHandle hHal = (tHalHandle) data; + tpAniSirGlobal pMac; + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return; + } + pMac = PMAC_STRUCT(hHal); + sapContext = sap_find_valid_concurrent_session(hHal); + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s no SAP contexts are found", __func__); + return; + } + + /* Check to ensure that SAP is in DFS WAIT state */ + if (sapContext->sapsMachine == eSAP_DFS_CAC_WAIT) { + cdf_mc_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = false; + + /* + * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sap_fsm + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; + + sap_fsm(sapContext, &sapEvent); + } + +} + +/* + * Function to stop the DFS CAC Timer + */ +static int sap_stop_dfs_cac_timer(ptSapContext sapContext) +{ + tHalHandle hHal; + tpAniSirGlobal pMac; + if (sapContext == NULL) + return 0; + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return 0; + } + pMac = PMAC_STRUCT(hHal); + + if (CDF_TIMER_STATE_RUNNING != + cdf_mc_timer_get_current_state(&pMac->sap.SapDfsInfo. + sap_dfs_cac_timer)) { + return 0; + } + + cdf_mc_timer_stop(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0; + + return 0; +} + + +/** + * sap_is_channel_bonding_etsi_weather_channel() - check weather chan bonding. + * @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->ch_params.ch_width != CH_WIDTH_20MHZ)) + return true; + + return false; +} + +/* + * Function to start the DFS CAC Timer + * when SAP is started on a DFS channel + */ +int sap_start_dfs_cac_timer(ptSapContext sapContext) +{ + CDF_STATUS status; + uint32_t cacTimeOut; + tHalHandle hHal = NULL; + tpAniSirGlobal pMac = NULL; + uint8_t dfs_region; + + if (sapContext == NULL) { + return 0; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; + + cds_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; + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: SAP_DFS_CHANNEL_CAC_START on CH - %d, CAC TIMEOUT - %d sec", + sapContext->channel, cacTimeOut / 1000); + + cdf_mc_timer_init(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer, + CDF_TIMER_TYPE_SW, + sap_dfs_cac_timer_callback, (void *) hHal); + + /*Start the CAC timer */ + status = + cdf_mc_timer_start(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer, + cacTimeOut); + if (status == CDF_STATUS_SUCCESS) { + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = true; + return 1; + } else { + return 0; + } +} + +/* + * This function initializes the NOL list + * parameters required to track the radar + * found DFS channels in the current Reg. Domain . + */ +CDF_STATUS sap_init_dfs_channel_nol_list(ptSapContext sapContext) +{ + uint8_t count = 0; + int i; + bool bFound = false; + tHalHandle hHal; + tpAniSirGlobal pMac; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Invalid sapContext pointer on sap_init_dfs_channel_nol_list"); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s invalid hHal", __func__); + return CDF_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT(hHal); + + /* to indicate hdd to get cnss dfs nol */ + if (CDF_STATUS_SUCCESS == sap_signal_hdd_event(sapContext, NULL, + eSAP_DFS_NOL_GET, + (void *) + eSAP_STATUS_SUCCESS)) { + bFound = true; + } + + for (i = RF_CHAN_36; i <= RF_CHAN_165; i++) { + if (reg_channels[i].enabled == CHANNEL_STATE_DFS) { + /* if dfs nol is not found, initialize it */ + if (!bFound) { + pMac->sap.SapDfsInfo.sapDfsChannelNolList[count] + .dfs_channel_number = + rf_channels[i].channelNum; + + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_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; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "%s[%d] NUMBER OF DFS CHANNELS = %d", + __func__, __LINE__, + pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels); + + return CDF_STATUS_SUCCESS; +} + +/* + * This function will calculate how many interfaces + * have sap persona and returns total number of sap persona. + */ +uint8_t sap_get_total_number_sap_intf(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t intf = 0; + uint8_t intf_count = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_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 + */ +bool is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, + ptSapContext sapContext) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + ptSapContext pSapContext; + uint8_t intf = 0; + + for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) { + if (((CDF_SAP_MODE == pMac->sap.sapCtxList[intf].sapPersona) + || + (CDF_P2P_GO_MODE == pMac->sap.sapCtxList[intf].sapPersona)) + && pMac->sap.sapCtxList[intf].pSapContext != NULL) { + pSapContext = + (ptSapContext) pMac->sap.sapCtxList[intf]. + pSapContext; + if (pSapContext == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("sapCtx matched [%p]"), + sapContext); + continue; + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL + ("concurrent sapCtx[%p] didn't matche with [%p]"), + pSapContext, sapContext); + return pSapContext->is_sap_ready_for_chnl_chng; + } + } + } + return false; +} diff --git a/core/sap/src/sap_fsm_ext.h b/core/sap/src/sap_fsm_ext.h new file mode 100644 index 000000000000..ad98431f2924 --- /dev/null +++ b/core/sap/src/sap_fsm_ext.h @@ -0,0 +1,61 @@ +/* + * 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/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h new file mode 100644 index 000000000000..a94c251c581b --- /dev/null +++ b/core/sap/src/sap_internal.h @@ -0,0 +1,430 @@ +/* + * 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 + +/* + * This file contains the internal API exposed by the wlan SAP PAL layer + * module. + */ + +#include "cds_api.h" +#include "cds_packet.h" + +/* Pick up the CSR API definitions */ +#include "csr_api.h" +#include "sap_api.h" +#include "sap_fsm_ext.h" +#include "sap_ch_select.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 true +#ifdef WLAN_FEATURE_MBSSID +/* When MBSSID feature is enabled, SAP context is directly passed to SAP APIs */ +#define CDS_GET_SAP_CB(ctx) (ptSapContext)(ctx) +#else +/* How do I get SAP context from cds context? */ +#define CDS_GET_SAP_CB(ctx) cds_get_context(CDF_MODULE_ID_SAP) +#endif + +#define CDS_GET_HAL_CB(ctx) cds_get_context(CDF_MODULE_ID_PE) +/* 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 *reg_channels; + +/*---------------------------------------------------------------------------- + * 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 { + uint8_t WmmIsEnabled; +} tSapQosCfg; + +typedef struct sSapAcsChannelInfo { + uint32_t channelNum; + uint32_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 { + + cdf_mutex_t SapGlobalLock; + + /* Include the current channel of AP */ + uint32_t channel; + uint32_t secondary_ch; + + /* Include the SME(CSR) sessionId here */ + uint8_t sessionId; + + /* Include the key material for this physical link */ + uint8_t key_type; + uint8_t key_length; + uint8_t key_material[32]; + + /* Include the associations MAC addresses */ + uint8_t self_mac_addr[CDS_MAC_ADDRESS_LEN]; + + /* Own SSID */ + uint8_t ownSsid[MAX_SSID_LEN]; + uint32_t ownSsidLen; + + /* Flag for signaling if security is enabled */ + uint8_t ucSecEnabled; + + /* Include the SME(CSR) context here */ + tCsrRoamProfile csr_roamProfile; + uint32_t csr_roamId; + + /* Sap session */ + bool isSapSessionOpen; + + /* SAP event Callback to hdd */ + tpWLAN_SAPEventCB pfnSapEventCallback; + + /* Include the enclosing CDS context here */ + void *p_cds_gctx; + + /* + * 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 */ + struct cdf_mac_addr bssid; + + /* Mac filtering settings */ + eSapMacAddrACL eSapMacAddrAclMode; + struct cdf_mac_addr acceptMacList[MAX_ACL_MAC_ADDRESS]; + uint8_t nAcceptMac; + struct cdf_mac_addr denyMacList[MAX_ACL_MAC_ADDRESS]; + uint8_t nDenyMac; + + /* QOS config */ + tSapQosCfg SapQosCfg; + + void *pUsrContext; + + uint32_t nStaWPARSnReqIeLength; + uint8_t pStaWpaRsnReqIE[MAX_ASSOC_IND_IE_LEN]; + tSirAPWPSIEs APWPSIEs; + tSirRSNie APWPARSNIEs; + +#ifdef FEATURE_WLAN_WAPI + uint32_t nStaWAPIReqIeLength; + uint8_t pStaWapiReqIE[MAX_ASSOC_IND_IE_LEN]; +#endif + + uint32_t nStaAddIeLength; + uint8_t pStaAddIE[MAX_ASSOC_IND_IE_LEN]; + uint8_t *channelList; + tSapChannelListInfo SapChnlList; + uint16_t ch_width_orig; + chan_params_t ch_params; + + /* session to scan */ + bool 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; + + tSapAcsChannelInfo acsBestChannelInfo; + bool enableOverLapCh; + struct sap_acs_cfg *acs_cfg; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || \ + defined(WLAN_FEATURE_MBSSID) + bool dfs_ch_disable; +#endif + bool isCacEndNotified; + bool isCacStartNotified; + bool 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 */ + /* + * sap_state, sap_status are created + * to inform upper layers about ACS scan status. + * Don't use these members for anyother purposes. + */ + eSapHddEvent sap_state; + eSapStatus sap_status; + uint32_t roc_ind_scan_id; +} *ptSapContext; + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +/* The main per-Physical Link (per WLAN association) context. */ +extern ptSapContext gp_sap_ctx; + +/*---------------------------------------------------------------------------- + * SAP state machine event definition + * -------------------------------------------------------------------------*/ +/* The event structure */ +typedef struct sWLAN_SAPEvent { + /* A VOID pointer type for all possible inputs */ + void *params; + /* State machine input event message */ + uint32_t event; + /* introduced to handle csr_roam_completeCallback roamStatus */ + uint32_t u1; + /* introduced to handle csr_roam_completeCallback roamResult */ + uint32_t u2; +} tWLAN_SAPEvent, *ptWLAN_SAPEvent; + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +CDF_STATUS +wlansap_scan_callback + (tHalHandle halHandle, + void *pContext, + uint8_t sessionId, uint32_t scanID, eCsrScanStatus scanStatus); + +CDF_STATUS +wlansap_pre_start_bss_acs_scan_callback( + tHalHandle hal_handle, + void *pcontext, + uint8_t sessionid, + uint32_t scanid, + eCsrScanStatus scan_status +); + +CDF_STATUS +wlansap_roam_callback + (void *pContext, + tCsrRoamInfo *pCsrRoamInfo, + uint32_t roamId, + eRoamCmdStatus roamStatus, eCsrRoamResult roamResult); + +CDF_STATUS wlansap_clean_cb(ptSapContext pSapCtx, uint32_t freeFlag); +CDF_STATUS SapFsm(ptSapContext sapContext, ptWLAN_SAPEvent sapEvent, + uint8_t *status); + +void +wlansap_pmc_full_pwr_req_cb(void *callbackContext, CDF_STATUS status); + +uint8_t sap_select_channel(tHalHandle halHandle, ptSapContext pSapCtx, + tScanResultHandle pScanResult); + +CDF_STATUS +sap_signal_hdd_event(ptSapContext sapContext, + tCsrRoamInfo *pCsrRoamInfo, + eSapHddEvent sapHddevent, void *); + +CDF_STATUS sap_fsm(ptSapContext sapContext, ptWLAN_SAPEvent sapEvent); + +eSapStatus +sapconvert_to_csr_profile(tsap_Config_t *pconfig_params, + eCsrRoamBssType bssType, + tCsrRoamProfile *profile); + +void sap_free_roam_profile(tCsrRoamProfile *profile); + +CDF_STATUS +sap_is_peer_mac_allowed(ptSapContext sapContext, uint8_t *peerMac); + +void +sap_sort_mac_list(struct cdf_mac_addr *macList, uint8_t size); + +void +sap_add_mac_to_acl(struct cdf_mac_addr *macList, uint8_t *size, + uint8_t *peerMac); + +void +sap_remove_mac_from_acl(struct cdf_mac_addr *macList, uint8_t *size, + uint8_t index); + +void +sap_print_acl(struct cdf_mac_addr *macList, uint8_t size); + +eSapBool +sap_search_mac_list(struct cdf_mac_addr *macList, uint8_t num_mac, + uint8_t *peerMac, uint8_t *index); + +CDF_STATUS sap_acquire_global_lock(ptSapContext pSapCtx); + +CDF_STATUS sap_release_global_lock(ptSapContext pSapCtx); + +#ifdef FEATURE_WLAN_CH_AVOID +void sap_update_unsafe_channel_list(ptSapContext pSapCtx); +#endif /* FEATURE_WLAN_CH_AVOID */ + +uint8_t +sap_indicate_radar(ptSapContext sapContext, + tSirSmeDfsEventInd *dfs_event); + +CDF_STATUS sap_init_dfs_channel_nol_list(ptSapContext sapContext); + +bool sap_dfs_is_channel_in_nol_list(ptSapContext sapContext, + uint8_t channelNumber, + ePhyChanBondState chanBondState); +void sap_dfs_cac_timer_callback(void *data); + +void sap_cac_reset_notify(tHalHandle hHal); + +bool sap_acs_channel_check(ptSapContext sapContext, uint8_t channelNumber); + +bool +sap_channel_matrix_check(ptSapContext sapContext, + ePhyChanBondState cbMode, + uint8_t target_channel); + +bool is_concurrent_sap_ready_for_channel_change(tHalHandle hHal, + ptSapContext + sapContext); + +uint8_t sap_get_total_number_sap_intf(tHalHandle hHal); + +bool sap_dfs_is_w53_invalid(tHalHandle hHal, uint8_t channelID); + +bool sap_dfs_is_channel_in_preferred_location(tHalHandle hHal, + uint8_t channelID); + +CDF_STATUS sap_goto_channel_sel( + ptSapContext sapContext, + ptWLAN_SAPEvent sapEvent, + bool sap_do_acs_pre_start_bss); + +void sap_config_acs_result(tHalHandle hal, ptSapContext sap_ctx, + uint32_t sec_ch); +/** + * 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); +#ifdef __cplusplus +} +#endif +#endif diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c new file mode 100644 index 000000000000..5b0e28b4e072 --- /dev/null +++ b/core/sap/src/sap_module.c @@ -0,0 +1,3272 @@ +/* + * 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. + */ + +/** + * =========================================================================== + * sapModule.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. + * =========================================================================== + */ + +/* $Header$ */ + +/*---------------------------------------------------------------------------- + * Include Files + * -------------------------------------------------------------------------*/ +#include "cdf_trace.h" +#include "cdf_util.h" +/* Pick up the sme callback registration API */ +#include "sme_api.h" + +/* SAP API header file */ + +#include "sap_internal.h" +#include "sme_inside.h" +#include "cds_ieee80211_common_i.h" +#include "cds_regdomain_common.h" + +/*---------------------------------------------------------------------------- + * Preprocessor Definitions and Constants + * -------------------------------------------------------------------------*/ +#define SAP_DEBUG + +/*---------------------------------------------------------------------------- + * Type Declarations + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Global Data Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * External declarations for global context + * -------------------------------------------------------------------------*/ +/* No! Get this from CDS. */ +/* The main per-Physical Link (per WLAN association) context. */ +ptSapContext gp_sap_ctx; + +/*---------------------------------------------------------------------------- + * Static Variable Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Static Function Declarations and Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Externalized Function Definitions + * -------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Function Declarations and Documentation + * -------------------------------------------------------------------------*/ + +/** + * wlansap_open() - WLAN SAP open function call + * @p_cds_gctx: Pointer to the global cds context; a handle to SAP's + * + * Called at driver initialization (cds_open). SAP will initialize + * all its internal resources and will wait for the call to start to + * register with the other modules. + * + * Return: The result code associated with performing the operation + * + * #ifdef WLAN_FEATURE_MBSSID + * void *: Pointer to the SAP context + * #else + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL ; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + * #endif + */ +#ifdef WLAN_FEATURE_MBSSID +void * +#else +CDF_STATUS +#endif +wlansap_open(void *p_cds_gctx) { + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +#ifdef WLAN_FEATURE_MBSSID + /* amically allocate the sapContext */ + pSapCtx = (ptSapContext) cdf_mem_malloc(sizeof(tSapContext)); +#else + if (NULL == p_cds_gctx) { + CDF_ASSERT(p_cds_gctx); + return CDF_STATUS_E_NOMEM; + } + /*------------------------------------------------------------------------ + Allocate (and sanity check?!) SAP control block + ------------------------------------------------------------------------*/ + cds_alloc_context(p_cds_gctx, CDF_MODULE_ID_SAP, (void **)&pSapCtx, + sizeof(tSapContext)); +#endif + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); +#ifdef WLAN_FEATURE_MBSSID + return NULL; +#else + return CDF_STATUS_E_FAULT; +#endif + } + + cdf_mem_zero(pSapCtx, sizeof(tSapContext)); + + /*------------------------------------------------------------------------ + Clean up SAP control block, initialize all values + ------------------------------------------------------------------------*/ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_open"); + + wlansap_clean_cb(pSapCtx, 0); /*do not empty */ + + /* Setup the "link back" to the CDS context */ + pSapCtx->p_cds_gctx = p_cds_gctx; + + /* Store a pointer to the SAP context provided by CDS */ + gp_sap_ctx = pSapCtx; + + /*------------------------------------------------------------------------ + Allocate internal resources + ------------------------------------------------------------------------*/ + +#ifdef WLAN_FEATURE_MBSSID + return pSapCtx; +#else + return CDF_STATUS_SUCCESS; +#endif +} /* wlansap_open */ + +/** + * wlansap_start() - wlan start SAP. + * @pCtx: Pointer to the global cds 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 + * + * Called as part of the overall start procedure (cds_enable). SAP will + * use this call to register with TL as the SAP entity for SAP RSN frames. + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault. + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_start(void *pCtx) +{ + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_start invoked successfully"); + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + pSapCtx = CDS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_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->csr_roamProfile.SSIDs.numOfSSIDs = 1; /* This is true for now. */ + pSapCtx->csr_roamProfile.SSIDs.SSIDList = pSapCtx->SSIDList; /* Array of two */ + pSapCtx->csr_roamProfile.SSIDs.SSIDList[0].SSID.length = 0; + pSapCtx->csr_roamProfile.SSIDs.SSIDList[0].handoffPermitted = false; + pSapCtx->csr_roamProfile.SSIDs.SSIDList[0].ssidHidden = + pSapCtx->SSIDList[0].ssidHidden; + + pSapCtx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; /* This is true for now. */ + pSapCtx->csr_roamProfile.BSSIDs.bssid = &pSapCtx->bssid; + + /* Now configure the auth type in the roaming profile. To open. */ + pSapCtx->csr_roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM; /* open is the default */ + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init(&pSapCtx->SapGlobalLock))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "wlansap_start failed init lock"); + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_stop() - stop SAP module. + * @pCtx: Pointer to the global cds 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 + * + * Called by cds_disable 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. + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault. + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_stop(void *pCtx) +{ + ptSapContext pSapCtx = NULL; + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_stop invoked successfully "); + + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sap_free_roam_profile(&pSapCtx->csr_roamProfile); + + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy(&pSapCtx->SapGlobalLock))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "wlansap_stop failed destroy lock"); + return CDF_STATUS_E_FAULT; + } + /*------------------------------------------------------------------------ + Stop SAP (de-register RSN handler!?) + ------------------------------------------------------------------------*/ + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_close - close SAP module. + * @pCtx: Pointer to the global cds 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. + * + * Called by cds_close during general driver close procedure. SAP will clean up + * all the internal resources. + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_close(void *pCtx) +{ + ptSapContext pSapCtx = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_close invoked"); + + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Cleanup SAP control block. + ------------------------------------------------------------------------*/ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_close"); + wlansap_clean_cb(pSapCtx, + true); /* empty queues/lists/pkts if any */ + +#ifdef WLAN_FEATURE_MBSSID + cdf_mem_free(pSapCtx); +#else + /*------------------------------------------------------------------------ + Free SAP context from CDS global + ------------------------------------------------------------------------*/ + cds_free_context(pCtx, CDF_MODULE_ID_SAP, pSapCtx); +#endif + + return CDF_STATUS_SUCCESS; +} /* wlansap_close */ + +/*---------------------------------------------------------------------------- + * Utility Function implementations + * -------------------------------------------------------------------------*/ + +/** + * wlansap_clean_cb() - clean SAP callback function. + * @pCtx: Pointer to the global cds 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. + * + * Clear out all fields in the SAP context. + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_clean_cb(ptSapContext pSapCtx, uint32_t freeFlag /* 0 / *do not empty* /); */ + ) { + /*------------------------------------------------------------------------ + Sanity check SAP control block + ------------------------------------------------------------------------*/ + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Clean up SAP control block, initialize all values + ------------------------------------------------------------------------*/ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_clean_cb"); + + cdf_mem_zero(pSapCtx, sizeof(tSapContext)); + + pSapCtx->p_cds_gctx = NULL; + + pSapCtx->sapsMachine = eSAP_DISCONNECTED; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 CDF_STATUS_SUCCESS; +} /* wlansap_clean_cb */ + +/*========================================================================== + FUNCTION wlansap_pmc_full_pwr_req_cb + + DESCRIPTION + Callback provide to PMC in the pmc_request_full_power API. + + DEPENDENCIES + + PARAMETERS + + IN + callbackContext: The user passed in a context to identify + status: The cdf_ret_status + + RETURN VALUE + None + + SIDE EFFECTS + ============================================================================*/ +void +wlansap_pmc_full_pwr_req_cb(void *callbackContext, CDF_STATUS status) +{ + if (CDF_IS_STATUS_SUCCESS(status)) { + /* If success what else to be handled??? */ + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "wlansap_pmc_full_pwr_req_cb: PMC failed to put the chip in Full power"); + + } + +} /* wlansap_pmc_full_pwr_req_cb */ + +/** + * wlansap_get_state() - get SAP state + * @pCtx: Pointer to the global cds 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 api returns the current SAP state to the caller. + * + * Return: uint8_t - the SAP FSM state. + */ +uint8_t wlansap_get_state(void *pCtx) +{ + ptSapContext pSapCtx = NULL; + + pSapCtx = CDS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + return pSapCtx->sapsMachine; +} + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/*========================================================================== + FUNCTION wlansap_check_cc_intf + + DESCRIPTION Restart SAP if Concurrent Channel interfering + + DEPENDENCIES NA. + + PARAMETERS + IN + Ctx: Pointer to cds Context or Sap Context based on MBSSID + + RETURN VALUE NONE + + SIDE EFFECTS + ============================================================================*/ +uint16_t wlansap_check_cc_intf(void *Ctx) +{ + tHalHandle hHal; + uint16_t intf_ch; + ptSapContext pSapCtx = CDS_GET_SAP_CB(Ctx); + + hHal = (tHalHandle) CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid MAC context from p_cds_gctx", __func__); + return 0; + } + intf_ch = sme_check_concurrent_channel_overlap(hHal, 0, 0, + pSapCtx->cc_switch_mode); + return intf_ch; +} +#endif + + /** + * wlansap_set_scan_acs_channel_params() - Config scan and channel parameters. + * pconfig: Pointer to the SAP config + * psap_ctx: Pointer to the SAP Context. + * pusr_context: Parameter that will be passed + * back in all the SAP callback events. + * + * This api function is used to copy Scan and Channel parameters from sap + * config to sap context. + * + * Return: The result code associated with + * performing the operation + */ +CDF_STATUS +wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig, + ptSapContext psap_ctx, + void *pusr_context) +{ + tHalHandle h_hal = NULL; + + if (NULL == pconfig) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid pconfig passed ", __func__); + return CDF_STATUS_E_FAULT; + } + + if (NULL == psap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid pconfig passed ", __func__); + return CDF_STATUS_E_FAULT; + } + + /* Channel selection is auto or configured */ + psap_ctx->channel = pconfig->channel; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + psap_ctx->cc_switch_mode = pconfig->cc_switch_mode; +#endif + psap_ctx->pUsrContext = pusr_context; + psap_ctx->enableOverLapCh = pconfig->enOverLapCh; + psap_ctx->acs_cfg = &pconfig->acs_cfg; + psap_ctx->ch_width_orig = pconfig->acs_cfg.ch_width; + psap_ctx->secondary_ch = pconfig->sec_ch; + + /* + * Set the BSSID to your "self MAC Addr" read + * the mac address from Configuation ITEM received + * from HDD + */ + psap_ctx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; + cdf_mem_copy(psap_ctx->csr_roamProfile.BSSIDs.bssid, + psap_ctx->self_mac_addr, + sizeof(struct cdf_mac_addr)); + + /* + * Save a copy to SAP context + */ + cdf_mem_copy(psap_ctx->csr_roamProfile.BSSIDs.bssid, + pconfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(psap_ctx->self_mac_addr, + pconfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + + h_hal = (tHalHandle)CDS_GET_HAL_CB(psap_ctx->p_cds_gctx); + if (NULL == h_hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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_get_concurrent_operation_channel(h_hal)) && + pconfig->ieee80211d) { + /* Setting the region/country information */ + sme_set_reg_info(h_hal, pconfig->countryCode); + sme_apply_channel_power_info_to_fw(h_hal); + } + } + + return CDF_STATUS_SUCCESS; +} +/** + * wlan_sap_get_vht_ch_width() - Returns SAP VHT channel width. + * @ctx: Pointer to cds Context or Sap Context based on MBSSID + * + * This function provides the SAP current VHT channel with. + * + * Return: VHT channel width + */ +uint32_t wlan_sap_get_vht_ch_width(void *ctx) +{ + ptSapContext sap_ctx = CDS_GET_SAP_CB(ctx); + + if (!sap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid SAP pointer from ctx")); + return 0; + } + + return sap_ctx->ch_params.ch_width; +} + +/** + * wlan_sap_set_vht_ch_width() - Sets SAP VHT channel width. + * @ctx: Pointer to cds Context or Sap Context based on MBSSID + * @vht_channel_width: SAP VHT channel width value. + * + * This function sets the SAP current VHT channel with. + * + * Return: None + */ +void wlan_sap_set_vht_ch_width(void *ctx, uint32_t vht_channel_width) +{ + ptSapContext sap_ctx = CDS_GET_SAP_CB(ctx); + + if (!sap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid SAP pointer from ctx")); + return; + } + + sap_ctx->ch_params.ch_width = vht_channel_width; +} + +/** + * wlansap_start_bss() - start BSS + * @pCtx: Pointer to the global cds 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. + * + * This api function provides SAP FSM event eWLAN_SAP_PHYSICAL_LINK_CREATE for + * starting AP BSS + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_start_bss(void *pCtx, /* pwextCtx */ + tpWLAN_SAPEventCB pSapEventCallback, + tsap_Config_t *pConfig, void *pUsrContext) { + tWLAN_SAPEvent sapEvent; /* State machine event */ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + tHalHandle hHal; + tpAniSirGlobal pmac = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_start_bss: sapContext=%p", pSapCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + pSapCtx->sapsMachine = eSAP_DISCONNECTED; + + /* Channel selection is auto or configured */ + pSapCtx->channel = pConfig->channel; + pSapCtx->ch_params.ch_width = pConfig->ch_params.ch_width; + pSapCtx->ch_params.center_freq_seg0 = + pConfig->ch_params.center_freq_seg0; + pSapCtx->ch_params.center_freq_seg1 = + pConfig->ch_params.center_freq_seg1; + pSapCtx->ch_params.sec_ch_offset = + pConfig->ch_params.sec_ch_offset; + 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->pUsrContext = pUsrContext; + pSapCtx->enableOverLapCh = pConfig->enOverLapCh; + pSapCtx->acs_cfg = &pConfig->acs_cfg; + /* Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD */ + pSapCtx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; + cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, + pSapCtx->self_mac_addr, sizeof(struct cdf_mac_addr)); + + /* Save a copy to SAP context */ + cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, + pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pSapCtx->self_mac_addr, + pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + + /* copy the configuration items to csrProfile */ + sapconvert_to_csr_profile(pConfig, eCSR_BSS_TYPE_INFRA_AP, + &pSapCtx->csr_roamProfile); + hHal = (tHalHandle) CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from p_cds_gctx", + __func__); + return CDF_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_get_concurrent_operation_channel(hHal)) && + pConfig->ieee80211d) { + /* Setting the region/country information */ + sme_set_reg_info(hHal, pConfig->countryCode); + sme_apply_channel_power_info_to_fw(hHal); + } + } + + pmac = PMAC_STRUCT(hHal); + if (NULL == pmac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + /* + * 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; + cdf_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sap_sort_mac_list(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sap_sort_mac_list(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 */ + cdf_status = sap_fsm(pSapCtx, &sapEvent); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "SoftAp role has not been enabled"); + } + + return cdf_status; +} /* wlansap_start_bss */ + +/** + * wlansap_set_mac_acl() - set MAC list entry in ACL. + * @pCtx: Pointer to the global cds 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. + * @pConfig: Pointer to SAP config. + * + * This api function provides SAP to set mac list entry in accept list as well + * as deny list + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_set_mac_acl(void *pCtx, /* pwextCtx */ + tsap_Config_t *pConfig) { + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_set_mac_acl"); + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + /* Copy MAC filtering settings to sap context */ + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + + if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) { + cdf_mem_copy(pSapCtx->acceptMacList, + pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sap_sort_mac_list(pSapCtx->acceptMacList, + pSapCtx->nAcceptMac); + } else if (eSAP_ACCEPT_UNLESS_DENIED == + pSapCtx->eSapMacAddrAclMode) { + cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sap_sort_mac_list(pSapCtx->denyMacList, pSapCtx->nDenyMac); + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s : SoftAp role has not been enabled", __func__); + return CDF_STATUS_E_FAULT; + } + + return cdf_status; +} /* wlansap_set_mac_acl */ + +/** + * wlansap_stop_bss() - stop BSS. + * @pCtx: Pointer to the global cds 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 api function provides SAP FSM event eSAP_HDD_STOP_INFRA_BSS for + * stopping AP BSS + * + * Return: The result code associated with performing the operation + * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL; + * access would cause a page fault + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_stop_bss(void *pCtx) +{ + tWLAN_SAPEvent sapEvent; /* State machine event */ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid Global CDS handle", __func__); + return CDF_STATUS_E_FAULT; + } + + pSapCtx = CDS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + /* Fill in the event structure for FSM */ + sapEvent.event = eSAP_HDD_STOP_INFRA_BSS; + sapEvent.params = 0; + + /* Handle event */ + cdf_status = sap_fsm(pSapCtx, &sapEvent); + + return cdf_status; +} + +/** + * wlansap_get_assoc_stations() - get list of associated stations. + * @pCtx: Pointer to the global cds 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 + * CDF_MODULE_ID_PE will be probed + * @pAssocStas: Pointer to list of associated stations that are known to the + * module specified in mod parameter + * + * This api function is used to probe the list of associated stations from + * various modules of CORE stack + * NOTE: The memory for this list will be allocated by the caller of this API + * + * Return: The result code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS +wlansap_get_assoc_stations + (void *pCtx, CDF_MODULE_ID modId, tpSap_AssocMacAddr pAssocStas) { + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sme_roam_get_associated_stas(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, modId, + pSapCtx->pUsrContext, + (void **) pSapCtx->pfnSapEventCallback, + (uint8_t *) pAssocStas); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_remove_wps_session_overlap() - remove overlapping wps session. + * @pCtx: Pointer to the global cds 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 struct cdf_mac_addr for session MAC address + * + * This api function provides for Ap App/HDD to remove an entry from session + * overlap info. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + * CDF_STATUS_E_FAULT: Session is not dectected. + * The parameter is function not valid. + */ +CDF_STATUS +wlansap_remove_wps_session_overlap(void *pCtx, + struct cdf_mac_addr pRemoveMac) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sme_roam_get_wps_session_overlap(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, pSapCtx->pUsrContext, + (void **) pSapCtx->pfnSapEventCallback, + pRemoveMac); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_get_wps_session_overlap() - get overlapping wps session. + * @pCtx: Pointer to the global cds 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 api function provides for Ap App/HDD to get WPS session overlap info. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_get_wps_session_overlap(void *pCtx) +{ + struct cdf_mac_addr pRemoveMac = CDF_MAC_ADDR_ZERO_INITIALIZER; + + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sme_roam_get_wps_session_overlap(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, pSapCtx->pUsrContext, + (void **) pSapCtx->pfnSapEventCallback, + pRemoveMac); + + return CDF_STATUS_SUCCESS; +} + +/* This routine will set the mode of operation for ACL dynamically*/ +CDF_STATUS wlansap_set_mode(void *pCtx, uint32_t mode) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + pSapCtx->eSapMacAddrAclMode = (eSapMacAddrACL) mode; + return CDF_STATUS_SUCCESS; +} + +/* Get ACL Mode */ +CDF_STATUS wlansap_get_acl_mode(void *pCtx, eSapMacAddrACL *mode) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + *mode = pSapCtx->eSapMacAddrAclMode; + return CDF_STATUS_SUCCESS; +} + +/* API to get ACL Accept List */ +CDF_STATUS +wlansap_get_acl_accept_list(void *pCtx, struct cdf_mac_addr *pAcceptList, + uint8_t *nAcceptList) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + + memcpy((void *)pAcceptList, (void *)pSapCtx->acceptMacList, + (pSapCtx->nAcceptMac * CDF_MAC_ADDR_SIZE)); + *nAcceptList = pSapCtx->nAcceptMac; + return CDF_STATUS_SUCCESS; +} + +/* API to get Deny List */ +CDF_STATUS +wlansap_get_acl_deny_list(void *pCtx, struct cdf_mac_addr *pDenyList, + uint8_t *nDenyList) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + + memcpy((void *)pDenyList, (void *)pSapCtx->denyMacList, + (pSapCtx->nDenyMac * CDF_MAC_ADDR_SIZE)); + *nDenyList = pSapCtx->nDenyMac; + return CDF_STATUS_SUCCESS; +} + +/* This routine will clear all the entries in accept list as well as deny list */ + +CDF_STATUS wlansap_clear_acl(void *pCtx) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + uint8_t i; + + if (NULL == pSapCtx) { + return CDF_STATUS_E_RESOURCES; + } + + if (pSapCtx->denyMacList != NULL) { + for (i = 0; i < (pSapCtx->nDenyMac - 1); i++) { + cdf_mem_zero((pSapCtx->denyMacList + i)->bytes, + CDF_MAC_ADDR_SIZE); + + } + } + sap_print_acl(pSapCtx->denyMacList, pSapCtx->nDenyMac); + pSapCtx->nDenyMac = 0; + + if (pSapCtx->acceptMacList != NULL) { + for (i = 0; i < (pSapCtx->nAcceptMac - 1); i++) { + cdf_mem_zero((pSapCtx->acceptMacList + i)->bytes, + CDF_MAC_ADDR_SIZE); + + } + } + sap_print_acl(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + pSapCtx->nAcceptMac = 0; + + return CDF_STATUS_SUCCESS; +} + +/* + * wlansap_modify_acl() -Update ACL entries + * + * @ctx: Global context + * @peer_sta_mac: peer sta mac to be updated. + * @list_type: white/Black list type. + * @cmd: command to be executed on ACL. + * + * This function is called when a peer needs to be added or deleted from the + * white/black ACL + * + * Return: Status + */ + +CDF_STATUS +wlansap_modify_acl + (void *ctx, + uint8_t *peer_sta_mac, eSapACLType list_type, eSapACLCmdType cmd) { + eSapBool sta_white_list = eSAP_FALSE, sta_black_list = eSAP_FALSE; + uint8_t staWLIndex, staBLIndex; + ptSapContext sap_ctx = CDS_GET_SAP_CB(ctx); + + if (NULL == sap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP Context", __func__); + return CDF_STATUS_E_FAULT; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "Modify ACL entered\n" "Before modification of ACL\n" + "size of accept and deny lists %d %d", sap_ctx->nAcceptMac, + sap_ctx->nDenyMac); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "*** WHITE LIST ***"); + sap_print_acl(sap_ctx->acceptMacList, sap_ctx->nAcceptMac); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "*** BLACK LIST ***"); + sap_print_acl(sap_ctx->denyMacList, sap_ctx->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 */ + sta_white_list = + sap_search_mac_list(sap_ctx->acceptMacList, sap_ctx->nAcceptMac, + peer_sta_mac, &staWLIndex); + sta_black_list = + sap_search_mac_list(sap_ctx->denyMacList, sap_ctx->nDenyMac, + peer_sta_mac, &staBLIndex); + + if (sta_white_list && sta_black_list) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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(peer_sta_mac)); + return CDF_STATUS_E_FAILURE; + + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "cmd %d", cmd); + + switch (list_type) { + case eSAP_WHITE_LIST: + if (cmd == ADD_STA_TO_ACL) { + /* error check */ + /* if list is already at max, return failure */ + if (sap_ctx->nAcceptMac == MAX_ACL_MAC_ADDRESS) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "White list is already maxed out. Cannot accept " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_E_FAILURE; + } + if (sta_white_list) { + /* Do nothing if already present in white list. Just print a warning */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "MAC address already present in white list " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_SUCCESS; + } + if (sta_black_list) { + /* remove it from black list before adding to the white list */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "STA present in black list so first remove from it"); + sap_remove_mac_from_acl(sap_ctx-> + denyMacList, + &sap_ctx->nDenyMac, + staBLIndex); + } + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + "... Now add to the white list"); + sap_add_mac_to_acl(sap_ctx->acceptMacList, + &sap_ctx->nAcceptMac, + peer_sta_mac); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + "size of accept and deny lists %d %d", + sap_ctx->nAcceptMac, + sap_ctx->nDenyMac); + } else if (cmd == DELETE_STA_FROM_ACL) { + if (sta_white_list) { + + struct tagCsrDelStaParams delStaParams; + + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + "Delete from white list"); + sap_remove_mac_from_acl(sap_ctx->acceptMacList, + &sap_ctx->nAcceptMac, + staWLIndex); + /* If a client is deleted from white list and it is connected, send deauth */ + wlansap_populate_del_sta_params(peer_sta_mac, + eCsrForcedDeauthSta, + (SIR_MAC_MGMT_DEAUTH >> 4), + &delStaParams); + wlansap_deauth_sta(ctx, &delStaParams); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + "size of accept and deny lists %d %d", + sap_ctx->nAcceptMac, + sap_ctx->nDenyMac); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "MAC address to be deleted is not present in the white list " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_E_FAILURE; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Invalid cmd type passed"); + return CDF_STATUS_E_FAILURE; + } + break; + + case eSAP_BLACK_LIST: + + if (cmd == ADD_STA_TO_ACL) { + struct tagCsrDelStaParams delStaParams; + /* error check */ + /* if list is already at max, return failure */ + if (sap_ctx->nDenyMac == MAX_ACL_MAC_ADDRESS) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "Black list is already maxed out. Cannot accept " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_E_FAILURE; + } + if (sta_black_list) { + /* Do nothing if already present in white list */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "MAC address already present in black list " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_SUCCESS; + } + if (sta_white_list) { + /* remove it from white list before adding to the black list */ + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "Present in white list so first remove from it"); + sap_remove_mac_from_acl(sap_ctx-> + acceptMacList, + &sap_ctx-> + nAcceptMac, + staWLIndex); + } + /* If we are adding a client to the black list; if its connected, send deauth */ + wlansap_populate_del_sta_params(peer_sta_mac, + eCsrForcedDeauthSta, + (SIR_MAC_MGMT_DEAUTH >> 4), + &delStaParams); + wlansap_deauth_sta(ctx, &delStaParams); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + "... Now add to black list"); + sap_add_mac_to_acl(sap_ctx->denyMacList, + &sap_ctx->nDenyMac, peer_sta_mac); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + "size of accept and deny lists %d %d", + sap_ctx->nAcceptMac, + sap_ctx->nDenyMac); + } else if (cmd == DELETE_STA_FROM_ACL) { + if (sta_black_list) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + "Delete from black list"); + sap_remove_mac_from_acl(sap_ctx->denyMacList, + &sap_ctx->nDenyMac, + staBLIndex); + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + "no accept and deny mac %d %d", + sap_ctx->nAcceptMac, + sap_ctx->nDenyMac); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_WARN, + "MAC address to be deleted is not present in the black list " + MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(peer_sta_mac)); + return CDF_STATUS_E_FAILURE; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Invalid cmd type passed"); + return CDF_STATUS_E_FAILURE; + } + break; + + default: + { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Invalid list type passed %d", list_type); + return CDF_STATUS_E_FAILURE; + } + } + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, + "After modification of ACL"); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "*** WHITE LIST ***"); + sap_print_acl(sap_ctx->acceptMacList, sap_ctx->nAcceptMac); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "*** BLACK LIST ***"); + sap_print_acl(sap_ctx->denyMacList, sap_ctx->nDenyMac); + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_disassoc_sta() - initiate disassociation of station. + * @pCtx: Pointer to the global cds 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 + * + * This api function provides for Ap App/HDD initiated disassociation of station + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_disassoc_sta(void *pCtx, const uint8_t *pPeerStaMac) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sme_roam_disconnect_sta(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, pPeerStaMac); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_deauth_sta() - Ap App/HDD initiated deauthentication of station + * @pCtx : Pointer to the global cds 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 + * + * This api function provides for Ap App/HDD initiated deauthentication of + * station + * + * Return: The CDF_STATUS code associated with performing the operation + */ +CDF_STATUS wlansap_deauth_sta(void *pCtx, + struct tagCsrDelStaParams *pDelStaParams) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return cdf_status; + } + + cdf_ret_status = + sme_roam_deauth_sta(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, pDelStaParams); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + cdf_status = CDF_STATUS_SUCCESS; + } + return cdf_status; +} + +/*========================================================================== + FUNCTION wlansap_set_channel_change_with_csa + + 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 + p_cds_gctx : Pointer to cds global context structure + targetChannel : New target channel to change to. + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS +wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) +{ + + ptSapContext sapContext = NULL; + tWLAN_SAPEvent sapEvent; + tpAniSirGlobal pMac = NULL; + void *hHal = NULL; + + sapContext = CDS_GET_SAP_CB(p_cds_gctx); + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); + + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT(hHal); + + /* + * Now, validate if the passed channel is valid in the + * current regulatory domain. + */ + if (sapContext->channel != targetChannel && + ((cds_get_channel_state(targetChannel) == + CHANNEL_STATE_ENABLE) || + (cds_get_channel_state(targetChannel) == + CHANNEL_STATE_DFS && + !cds_concurrent_open_sessions_running()))) { + /* + * 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) { + /* + * Copy the requested target channel + * to sap context. + */ + pMac->sap.SapDfsInfo.target_channel = targetChannel; + /* + * TODO: need to identify the allowed channel width and + * bonding mode. + */ + pMac->sap.SapDfsInfo.new_chanWidth = 0; + pMac->sap.SapDfsInfo.new_cbMode = 0; + + /* + * Set the CSA IE required flag. + */ + pMac->sap.SapDfsInfo.csaIERequired = 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 = true; + + /* + * 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; + + sap_fsm(sapContext, &sapEvent); + + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to request Channel Change, since" + "SAP is not in eSAP_STARTED state", __func__); + return CDF_STATUS_E_FAULT; + } + + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Channel = %d is not valid in the current" + "regulatory domain", __func__, targetChannel); + + return CDF_STATUS_E_FAULT; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Posted eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START" + "successfully to sap_fsm for Channel = %d", + __func__, targetChannel); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_set_counter_measure() - set counter measure. + * @pCtx: Pointer to the global cds 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. + * + * 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. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_set_counter_measure(void *pCtx, bool bEnable) +{ + ptSapContext pSapCtx = CDS_GET_SAP_CB(pCtx); + + /*------------------------------------------------------------------------ + Sanity check + Extract SAP control block + ------------------------------------------------------------------------*/ + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + sme_roam_tkip_counter_measures(CDS_GET_HAL_CB(pSapCtx->p_cds_gctx), + pSapCtx->sessionId, bEnable); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_set_key_sta() - set keys for a stations. + * @pCtx: Pointer to the global cds 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 + * + * This api function provides for Ap App/HDD to set key for a station. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_set_key_sta(void *pCtx, tCsrRoamSetKey *pSetKeyInfo) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + uint32_t roamId = 0xFF; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + cdf_ret_status = + sme_roam_set_key(hHal, pSapCtx->sessionId, pSetKeyInfo, + &roamId); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + cdf_status = CDF_STATUS_SUCCESS; + } else { + cdf_status = CDF_STATUS_E_FAULT; + } + } else + cdf_status = CDF_STATUS_E_FAULT; + + return cdf_status; +} + +/** + * wlan_sap_getstation_ie_information() - RSNIE Population + * + * @ctx: Global context + * @len: Length of @buf + * @buf: RSNIE IE data + * + * Populate RSN IE from CSR to HDD context + * + * Return: CDF_STATUS enumeration + */ + +CDF_STATUS +wlan_sap_getstation_ie_information + (void *ctx, uint32_t *len, uint8_t *buf) { + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + ptSapContext sap_ctx = NULL; + uint32_t ie_len = 0; + tCDF_CON_MODE mode; + + mode = cds_get_conparam(); + if (CDF_SAP_MODE != mode) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%d: called in wrong mode ", + mode); + return CDF_STATUS_E_FAULT; + } + + sap_ctx = CDS_GET_SAP_CB(ctx); + if (NULL == sap_ctx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid SAP pointer from pCtx")); + return CDF_STATUS_E_FAULT; + } + + if (len) { + ie_len = *len; + *len = sap_ctx->nStaWPARSnReqIeLength; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("WPAIE len : %x"), *len); + if ((buf) && (ie_len >= sap_ctx->nStaWPARSnReqIeLength)) { + cdf_mem_copy(buf, + sap_ctx->pStaWpaRsnReqIE, + sap_ctx->nStaWPARSnReqIeLength); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + FL("WPAIE: %02x:%02x:%02x:%02x:%02x:%02x"), + buf[0], buf[1], buf[2], buf[3], buf[4], + buf[5]); + cdf_status = CDF_STATUS_SUCCESS; + } + } + return cdf_status; +} + +/** + * wlansap_set_wps_ie() - set WPI IE + * @pCtx: Pointer to the global cds 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 + * + * This api function provides API for App/HDD to set WPS IE. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise. + */ +CDF_STATUS wlansap_set_wps_ie(void *pCtx, tSap_WPSIE *pSap_WPSIe) +{ + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s, %d", __func__, __LINE__); + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + + if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { + if (pSap_WPSIe->sapWPSIECode == eSAP_WPS_BEACON_IE) { + cdf_mem_copy(&pSapCtx->APWPSIEs.SirWPSBeaconIE, + &pSap_WPSIe->sapwpsie. + sapWPSBeaconIE, + sizeof(tSap_WPSBeaconIE)); + } else if (pSap_WPSIe->sapWPSIECode == + eSAP_WPS_PROBE_RSP_IE) { + cdf_mem_copy(&pSapCtx->APWPSIEs. + SirWPSProbeRspIE, + &pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE, + sizeof(tSap_WPSProbeRspIE)); + } else { + sap_release_global_lock(pSapCtx); + return CDF_STATUS_E_FAULT; + } + sap_release_global_lock(pSapCtx); + return CDF_STATUS_SUCCESS; + } else + return CDF_STATUS_E_FAULT; + } else + return CDF_STATUS_E_FAULT; +} + +/** + * wlansap_update_wps_ie() - update WPI IE + * @pCtx: Pointer to the global cds 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 api function provides API for App/HDD to update WPS IE. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise. + */ +CDF_STATUS wlansap_update_wps_ie(void *pCtx) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; + ptSapContext pSapCtx = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s, %d", __func__, __LINE__); + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = + sme_roam_update_apwpsie(hHal, pSapCtx->sessionId, + &pSapCtx->APWPSIEs); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + cdf_status = CDF_STATUS_SUCCESS; + } else { + cdf_status = CDF_STATUS_E_FAULT; + } + + } + + return cdf_status; +} + +/** + * wlansap_get_wps_state() - get WPS session state + * @pCtx: Pointer to the global cds 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. + * @pbWPSState: Pointer to variable to indicate if device is in + * WPS Registration state + * + * This api function provides for Ap App/HDD to check if WPS session in process. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS wlansap_get_wps_state(void *pCtx, bool *bWPSState) +{ + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s, %d", __func__, __LINE__); + + if (CDF_SAP_MODE == cds_get_conparam()) { + + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + + if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { + if (pSapCtx->APWPSIEs.SirWPSProbeRspIE. + FieldPresent & + SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) + *bWPSState = true; + else + *bWPSState = false; + + sap_release_global_lock(pSapCtx); + + return CDF_STATUS_SUCCESS; + } else + return CDF_STATUS_E_FAULT; + } else + return CDF_STATUS_E_FAULT; + +} + +CDF_STATUS sap_acquire_global_lock(ptSapContext pSapCtx) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; + + if (CDF_IS_STATUS_SUCCESS(cdf_mutex_acquire(&pSapCtx->SapGlobalLock))) { + cdf_status = CDF_STATUS_SUCCESS; + } + + return cdf_status; +} + +CDF_STATUS sap_release_global_lock(ptSapContext pSapCtx) +{ + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; + + if (CDF_IS_STATUS_SUCCESS(cdf_mutex_release(&pSapCtx->SapGlobalLock))) { + cdf_status = CDF_STATUS_SUCCESS; + } + + return cdf_status; +} + +/** + * wlansap_set_wparsn_ies() - set WPA RSN IEs + * @pCtx: Pointer to the global cds 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 + * + * This api function provides for Ap App/HDD to set AP WPA and RSN IE in its + * beacon and probe response. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise + */ +CDF_STATUS wlansap_set_wparsn_ies + (void *pCtx, uint8_t *pWPARSNIEs, uint32_t WPARSNIEsLen) { + ptSapContext pSapCtx = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + + pSapCtx->APWPARSNIEs.length = (uint16_t) WPARSNIEsLen; + cdf_mem_copy(pSapCtx->APWPARSNIEs.rsnIEdata, pWPARSNIEs, + WPARSNIEsLen); + + cdf_ret_status = + sme_roam_update_apwparsni_es(hHal, pSapCtx->sessionId, + &pSapCtx->APWPARSNIEs); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + return CDF_STATUS_SUCCESS; + } else { + return CDF_STATUS_E_FAULT; + } + } + + return CDF_STATUS_E_FAULT; +} + +/** + * wlansap_send_action() - send action frame + * @pCtx: Pointer to the global cds 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 + * + * This api function provides to send action frame sent by upper layer. + * + * Return: The CDF_STATUS code associated with performing the operation +* CDF_STATUS_SUCCESS: Success and error code otherwise + */ +CDF_STATUS wlansap_send_action(void *pCtx, const uint8_t *pBuf, + uint32_t len, uint16_t wait, uint16_t channel_freq) +{ + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = + sme_send_action(hHal, pSapCtx->sessionId, pBuf, len, 0, + 0, channel_freq); + + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Failed to Send Action Frame"); + + return CDF_STATUS_E_FAULT; +} + +/** + * wlansap_remain_on_channel() - set remain on channel + * @pCtx: Pointer to the global cds 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. + * @scan_id: scan identifier + * + * This api function provides to set Remain On channel on specified channel + * for specified duration. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise + */ +CDF_STATUS wlansap_remain_on_channel(void *pCtx, + uint8_t channel, uint32_t duration, remainOnChanCallback callback, + void *pContext, uint32_t *scan_id) +{ + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = sme_remain_on_channel(hHal, pSapCtx->sessionId, + channel, duration, callback, pContext, + true, scan_id); + + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Failed to Set Remain on Channel"); + + return CDF_STATUS_E_FAULT; +} + +/** + * wlansap_cancel_remain_on_channel() - cancel remain on channel + * @pCtx: Pointer to the global cds 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 api cancel previous remain on channel request. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwie + */ +CDF_STATUS wlansap_cancel_remain_on_channel(void *pCtx, + uint32_t scan_id) +{ + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || + (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = + sme_cancel_remain_on_channel(hHal, pSapCtx->sessionId, + scan_id); + + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Failed to Cancel Remain on Channel"); + + return CDF_STATUS_E_FAULT; +} +/** + * wlansap_register_mgmt_frame() - register management frame + * @pCtx: Pointer to the global cds 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 + * + * 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 + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise + */ +CDF_STATUS wlansap_register_mgmt_frame + (void *pCtx, + uint16_t frameType, uint8_t *matchData, uint16_t matchLen) { + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = sme_register_mgmt_frame(hHal, pSapCtx->sessionId, + frameType, matchData, + matchLen); + + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Failed to Register MGMT frame"); + + return CDF_STATUS_E_FAULT; +} + +/** + * wlansap_de_register_mgmt_frame() - de register management frame + * @pCtx: Pointer to the global cds 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 + * + * This API is used to deregister previously registered frame. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise + */ +CDF_STATUS wlansap_de_register_mgmt_frame + (void *pCtx, + uint16_t frameType, uint8_t *matchData, uint16_t matchLen) { + ptSapContext pSapCtx = NULL; + void *hHal = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + + if (CDF_SAP_MODE == cds_get_conparam()) { + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } + + cdf_ret_status = + sme_deregister_mgmt_frame(hHal, pSapCtx->sessionId, frameType, + matchData, matchLen); + + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; + } + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "Failed to Deregister MGMT frame"); + + return CDF_STATUS_E_FAULT; +} + +/*========================================================================== + FUNCTION wlansap_channel_change_request + + 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 cds global context structure + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS +wlansap_channel_change_request(void *pSapCtx, uint8_t targetChannel) +{ + ptSapContext sapContext = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + tpAniSirGlobal mac_ctx = NULL; + eCsrPhyMode phy_mode; + uint32_t cb_mode; + uint32_t vht_channel_width; + chan_params_t ch_params; + sapContext = (ptSapContext) pSapCtx; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + mac_ctx = PMAC_STRUCT(hHal); + phy_mode = sapContext->csr_roamProfile.phyMode; + sapContext->csr_roamProfile.ChannelInfo.ChannelList[0] = targetChannel; + /* + * We are getting channel bonding mode from sapDfsInfor structure + * because we've implemented channel width fallback mechanism for DFS + * which will result in channel width changing dynamically. + */ + cb_mode = mac_ctx->sap.SapDfsInfo.new_cbMode; + vht_channel_width = mac_ctx->sap.SapDfsInfo.new_chanWidth; + ch_params.ch_width = vht_channel_width; + sme_set_ch_params(hHal, phy_mode, targetChannel, 0, &ch_params); + sapContext->ch_params.ch_width = vht_channel_width; + sapContext->csr_roamProfile.ch_params.ch_width = vht_channel_width; + cdf_ret_status = sme_roam_channel_change_req(hHal, sapContext->bssid, + cb_mode, &sapContext->csr_roamProfile); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + sap_signal_hdd_event(sapContext, NULL, + eSAP_CHANNEL_CHANGE_EVENT, + (void *) eSAP_STATUS_SUCCESS); + + return CDF_STATUS_SUCCESS; + } + return CDF_STATUS_E_FAULT; +} + +/*========================================================================== + + FUNCTION wlansap_start_beacon_req + 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 cds global context structure + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_start_beacon_req(void *pSapCtx) +{ + ptSapContext sapContext = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + uint8_t dfsCacWaitStatus = 0; + tpAniSirGlobal pMac = NULL; + sapContext = (ptSapContext) pSapCtx; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_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 == false) { + /* CAC Wait done without any Radar Detection */ + dfsCacWaitStatus = true; + cdf_ret_status = sme_roam_start_beacon_req(hHal, + sapContext->bssid, + dfsCacWaitStatus); + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + return CDF_STATUS_SUCCESS; + } + return CDF_STATUS_E_FAULT; + } + + return CDF_STATUS_E_FAULT; +} + +/*========================================================================== + FUNCTION wlansap_dfs_send_csa_ie_request + + DESCRIPTION + This API is used to send channel switch announcement request to PE + DEPENDENCIES + NA. + + PARAMETERS + IN + pSapCtx: Pointer to cds global context structure + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_dfs_send_csa_ie_request(void *pSapCtx) +{ + ptSapContext sapContext = NULL; + CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; + void *hHal = NULL; + tpAniSirGlobal pMac = NULL; + uint32_t cbmode, vht_ch_width; + uint8_t ch_bandwidth; + sapContext = (ptSapContext) pSapCtx; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT(hHal); + + /* + * We are getting channel bonding mode from sapDfsInfor structure + * because we've implemented channel width fallback mechanism for DFS + * which will result in channel width changing dynamically. + */ + vht_ch_width = pMac->sap.SapDfsInfo.new_chanWidth; + cbmode = pMac->sap.SapDfsInfo.new_cbMode; + + 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; + } + + cdf_ret_status = sme_roam_csa_ie_request(hHal, + sapContext->bssid, + pMac->sap.SapDfsInfo.target_channel, + pMac->sap.SapDfsInfo.csaIERequired, + ch_bandwidth); + + if (cdf_ret_status == CDF_STATUS_SUCCESS) { + return CDF_STATUS_SUCCESS; + } + + return CDF_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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_get_dfs_ignore_cac(tHalHandle hHal, uint8_t *pIgnore_cac) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + *pIgnore_cac = pMac->sap.SapDfsInfo.ignore_cac; + return CDF_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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_set_dfs_ignore_cac(tHalHandle hHal, uint8_t ignore_cac) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + pMac->sap.SapDfsInfo.ignore_cac = (ignore_cac >= true) ? + true : false; + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_set_dfs_restrict_japan_w53() - enable/disable dfS for japan + * @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 + * + * This API is used to enable or disable Japan W53 Band + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success + */ +CDF_STATUS +wlansap_set_dfs_restrict_japan_w53(tHalHandle hHal, uint8_t disable_Dfs_W53) +{ + tpAniSirGlobal pMac = NULL; + CDF_STATUS status; + uint8_t dfs_region; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + cds_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; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL("sapdfs: SET DFS JAPAN W53 DISABLED = %d"), + pMac->sap.SapDfsInfo.is_dfs_w53_disabled); + + status = CDF_STATUS_SUCCESS; + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL + ("Regdomain not japan, set disable JP W53 not valid")); + + status = CDF_STATUS_E_FAULT; + } + + return status; +} + +#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 + */ +CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("hal or mac_ctx pointer NULL")); + return CDF_STATUS_E_FAULT; + } + mac_ctx->sap.sap_channel_avoidance = sap_channel_avoidance; + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/** + * wlansap_set_dfs_preferred_channel_location() - set dfs preferred channel + * @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. + * + * This API is used to set sap preferred channels location + * to resetrict the DFS random channel selection algorithm + * either Indoor/Outdoor channels only. + * + * Return: The CDF_STATUS code associated with performing the operation + * CDF_STATUS_SUCCESS: Success and error code otherwise. + */ +CDF_STATUS +wlansap_set_dfs_preferred_channel_location(tHalHandle hHal, + uint8_t + dfs_Preferred_Channels_location) +{ + tpAniSirGlobal pMac = NULL; + CDF_STATUS status; + uint8_t dfs_region; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + cds_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; + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO_LOW, + FL + ("sapdfs:Set Preferred Operating Channel location=%d"), + pMac->sap.SapDfsInfo. + sap_operating_chan_preferred_location); + + status = CDF_STATUS_SUCCESS; + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL + ("sapdfs:NOT JAPAN REG, Invalid Set preferred chans location")); + + status = CDF_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 CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_set_dfs_target_chnl(tHalHandle hHal, uint8_t target_channel) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL != hHal) { + pMac = PMAC_STRUCT(hHal); + } else { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal pointer", __func__); + return CDF_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 CDF_STATUS_SUCCESS; +} + +CDF_STATUS +wlansap_update_sap_config_add_ie(tsap_Config_t *pConfig, + const uint8_t *pAdditionIEBuffer, + uint16_t additionIELength, + eUpdateIEsType updateType) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t bufferValid = false; + uint16_t bufferLength = 0; + uint8_t *pBuffer = NULL; + + if (NULL == pConfig) { + return CDF_STATUS_E_FAULT; + } + + if ((pAdditionIEBuffer != NULL) && (additionIELength != 0)) { + /* initialize the buffer pointer so that pe can copy */ + if (additionIELength > 0) { + bufferLength = additionIELength; + pBuffer = cdf_mem_malloc(bufferLength); + if (NULL == pBuffer) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Could not allocate the buffer ")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(pBuffer, pAdditionIEBuffer, bufferLength); + bufferValid = true; + } + } + + switch (updateType) { + case eUPDATE_IE_PROBE_BCN: + if (bufferValid) { + pConfig->probeRespBcnIEsLen = bufferLength; + pConfig->pProbeRespBcnIEsBuffer = pBuffer; + } else { + cdf_mem_free(pConfig->pProbeRespBcnIEsBuffer); + pConfig->probeRespBcnIEsLen = 0; + pConfig->pProbeRespBcnIEsBuffer = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 { + cdf_mem_free(pConfig->pProbeRespIEsBuffer); + pConfig->probeRespIEsBufferLen = 0; + pConfig->pProbeRespIEsBuffer = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 { + cdf_mem_free(pConfig->pAssocRespIEsBuffer); + pConfig->assocRespIEsLen = 0; + pConfig->pAssocRespIEsBuffer = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL + ("No Assoc Response IE received in set beacon")); + } + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("No matching buffer type %d"), updateType); + if (pBuffer != NULL) + cdf_mem_free(pBuffer); + break; + } + + return status; +} + +CDF_STATUS +wlansap_reset_sap_config_add_ie(tsap_Config_t *pConfig, eUpdateIEsType updateType) +{ + if (NULL == pConfig) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid Config pointer", __func__); + return CDF_STATUS_E_FAULT; + } + + switch (updateType) { + case eUPDATE_IE_ALL: /*only used to reset */ + case eUPDATE_IE_PROBE_RESP: + cdf_mem_free(pConfig->pProbeRespIEsBuffer); + pConfig->probeRespIEsBufferLen = 0; + pConfig->pProbeRespIEsBuffer = NULL; + if (eUPDATE_IE_ALL != updateType) + break; + + case eUPDATE_IE_ASSOC_RESP: + cdf_mem_free(pConfig->pAssocRespIEsBuffer); + pConfig->assocRespIEsLen = 0; + pConfig->pAssocRespIEsBuffer = NULL; + if (eUPDATE_IE_ALL != updateType) + break; + + case eUPDATE_IE_PROBE_BCN: + cdf_mem_free(pConfig->pProbeRespBcnIEsBuffer); + pConfig->probeRespBcnIEsLen = 0; + pConfig->pProbeRespBcnIEsBuffer = NULL; + if (eUPDATE_IE_ALL != updateType) + break; + + default: + if (eUPDATE_IE_ALL != updateType) + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Invalid buffer type %d"), updateType); + break; + } + return CDF_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 + ============================================================================*/ +void wlansap_extend_to_acs_range(uint8_t *startChannelNum, + uint8_t *endChannelNum, + uint8_t *bandStartChannel, + uint8_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) + + uint8_t tmp_startChannelNum = 0, tmp_endChannelNum = 0; + + if (*startChannelNum <= 14 && *endChannelNum <= 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 if (*startChannelNum >= 36 && *endChannelNum >= 36) { + *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; + } else { + *bandStartChannel = RF_CHAN_1; + *bandEndChannel = RF_CHAN_165; + tmp_startChannelNum = *startChannelNum > 5 ? + (*startChannelNum - ACS_2G_EXTEND) : 1; + tmp_endChannelNum = (*endChannelNum + ACS_5G_EXTEND) <= 165 ? + (*endChannelNum + ACS_5G_EXTEND) : 165; + } + + /* Note if the ACS range include only DFS channels, do not cross 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 (CDS_IS_DFS_CH(*startChannelNum)) { + while (!CDS_IS_DFS_CH(tmp_startChannelNum) && + tmp_startChannelNum < *startChannelNum) + tmp_startChannelNum += ACS_WLAN_20M_CH_INC; + + *startChannelNum = tmp_startChannelNum; + } + if (CDS_IS_DFS_CH(*endChannelNum)) { + while (!CDS_IS_DFS_CH(tmp_endChannelNum) && + tmp_endChannelNum > *endChannelNum) + tmp_endChannelNum -= ACS_WLAN_20M_CH_INC; + + *endChannelNum = tmp_endChannelNum; + } +} + +/*========================================================================== + FUNCTION wlansap_get_dfs_nol + + DESCRIPTION + This API is used to dump the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to cds global context structure + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_get_dfs_nol(void *pSapCtx) +{ + int i = 0; + ptSapContext sapContext = (ptSapContext) pSapCtx; + void *hHal = NULL; + tpAniSirGlobal pMac = NULL; + uint64_t current_time, found_time, elapsed_time; + unsigned long left_time; + tSapDfsNolInfo *dfs_nol = NULL; + bool bAvailable = false; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT(hHal); + + if (!pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: DFS NOL is empty", __func__); + return CDF_STATUS_SUCCESS; + } + + dfs_nol = pMac->sap.SapDfsInfo.sapDfsChannelNolList; + + if (!dfs_nol) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: DFS NOL context is null", __func__); + return CDF_STATUS_E_FAULT; + } + + for (i = 0; i < pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels; + i++) { + if (!dfs_nol[i].dfs_channel_number) + continue; + + current_time = cds_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; + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Channel[%d] is UNAVAILABLE [%lu min left]", + __func__, + dfs_nol[i].dfs_channel_number, left_time); + } + } + + return CDF_STATUS_SUCCESS; +} + +/*========================================================================== + FUNCTION wlansap_set_dfs_nol + + DESCRIPTION + This API is used to set the dfs nol + DEPENDENCIES + NA. + + PARAMETERS + IN + sapContext: Pointer to cds global context structure + conf: set type + + RETURN VALUE + The CDF_STATUS code associated with performing the operation + + CDF_STATUS_SUCCESS: Success + + SIDE EFFECTS + ============================================================================*/ +CDF_STATUS wlansap_set_dfs_nol(void *pSapCtx, eSapDfsNolType conf) +{ + int i = 0; + ptSapContext sapContext = (ptSapContext) pSapCtx; + void *hHal = NULL; + tpAniSirGlobal pMac = NULL; + + if (NULL == sapContext) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + pMac = PMAC_STRUCT(hHal); + + if (!pMac->sap.SapDfsInfo.numCurrentRegDomainDfsChannels) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, + "%s: DFS NOL is empty", __func__); + return CDF_STATUS_SUCCESS; + } + + if (conf == eSAP_DFS_NOL_CLEAR) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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++) { + uint32_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 = + cds_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; + } + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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 { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: unsupport type %d", __func__, conf); + } + + /* set DFS-NOL back to keep it update-to-date in CNSS */ + sap_signal_hdd_event(sapContext, NULL, eSAP_DFS_NOL_SET, + (void *) eSAP_STATUS_SUCCESS); + + return CDF_STATUS_SUCCESS; +} + +/** + * wlansap_populate_del_sta_params() - populate delete station parameter + * @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. + * + * This API is used to populate delete station parameter structure + * + * Return: none + */ + +void wlansap_populate_del_sta_params(const uint8_t *mac, + uint16_t reason_code, + uint8_t subtype, + struct tagCsrDelStaParams *pDelStaParams) +{ + if (NULL == mac) + cdf_set_macaddr_broadcast(&pDelStaParams->peerMacAddr); + else + cdf_mem_copy(pDelStaParams->peerMacAddr.bytes, mac, + CDF_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); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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.bytes)); +} + +/** + * wlansap_acs_chselect() - Initiates acs channel selection + * @pvos_gctx: Pointer to vos global context structure + * @pacs_event_callback: Callback function in hdd called by sap + * to inform hdd about channel section result + * @pconfig: Pointer to configuration structure + * passed down from hdd + * @pusr_context: Parameter that will be passed back in all + * the sap callback events. + * + * This function serves as an api for hdd to initiate acs scan pre + * start bss. + * + * Return: The CDF_STATUS code associated with performing the operation. + */ +CDF_STATUS +wlansap_acs_chselect(void *pvos_gctx, + tpWLAN_SAPEventCB pacs_event_callback, + tsap_Config_t *pconfig, + void *pusr_context) +{ + ptSapContext sap_context = NULL; + tHalHandle h_hal = NULL; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pmac = NULL; + + sap_context = CDS_GET_SAP_CB(pvos_gctx); + if (NULL == sap_context) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pvos_gctx", __func__); + + return CDF_STATUS_E_FAULT; + } + + h_hal = (tHalHandle)CDS_GET_HAL_CB(sap_context->p_cds_gctx); + if (NULL == h_hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid MAC context from pvosGCtx", __func__); + return CDF_STATUS_E_FAULT; + } + + if (sap_context->isSapSessionOpen == eSAP_TRUE) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL, + "%s:SME Session is already opened\n", __func__); + return CDF_STATUS_E_EXISTS; + } + + sap_context->sessionId = 0xff; + + pmac = PMAC_STRUCT(h_hal); + sap_context->acs_cfg = &pconfig->acs_cfg; + sap_context->ch_width_orig = pconfig->acs_cfg.ch_width; + sap_context->csr_roamProfile.phyMode = pconfig->acs_cfg.hw_mode; + + if (sap_context->isScanSessionOpen == eSAP_FALSE) { + uint32_t type, subType; + + /* + * Now, configure the scan and ACS channel params + * to issue a scan request. + */ + wlansap_set_scan_acs_channel_params(pconfig, sap_context, + pusr_context); + + if (CDF_STATUS_SUCCESS == + cds_get_vdev_types(CDF_STA_MODE, &type, &subType)) { + /* + * Open SME Session for scan + */ + if (CDF_STATUS_SUCCESS != sme_open_session(h_hal, + NULL, sap_context, + sap_context->self_mac_addr, + &sap_context->sessionId, + type, subType)) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "Error: In %s calling sme_OpenSession", + __func__); + return CDF_STATUS_E_FAILURE; + } else { + sap_context->isScanSessionOpen = eSAP_TRUE; + } + } + + /* + * Copy the HDD callback function to report the + * ACS result after scan in SAP context callback function. + */ + sap_context->pfnSapEventCallback = pacs_event_callback; + /* + * init dfs channel nol + */ + sap_init_dfs_channel_nol_list(sap_context); + + /* + * 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. + */ + cdf_status = sap_goto_channel_sel(sap_context, NULL, true); + + if (CDF_STATUS_E_ABORTED == cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "In %s,DFS not supported in the current operating mode", + __func__); + return CDF_STATUS_E_FAILURE; + } else if (CDF_STATUS_E_CANCELED == cdf_status) { + /* + * ERROR is returned when either the SME scan request + * failed or ACS is overridden due to other constrainst + * So send selected channel to HDD + */ + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Scan Req Failed/ACS Overridden")); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Selected channel = %d"), + sap_context->channel); + if (sap_context->isScanSessionOpen == eSAP_TRUE) { + /* ACS scan not needed so close session */ + tHalHandle h_hal = CDS_GET_HAL_CB( + sap_context->p_cds_gctx); + if (h_hal == NULL) + return CDF_STATUS_E_FAILURE; + + if (sme_close_session(h_hal, + sap_context->sessionId, NULL, NULL) == + CDF_STATUS_SUCCESS) + sap_context->isScanSessionOpen = + eSAP_FALSE; + else + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + "ACS Scan Session close fail"); + sap_context->sessionId = 0xff; + } + + return sap_signal_hdd_event(sap_context, NULL, + eSAP_ACS_CHANNEL_SELECTED, + (void *) eSAP_STATUS_SUCCESS); + } else if (CDF_STATUS_SUCCESS == cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Successfully Issued a Pre Start Bss Scan Request")); + } + } + return cdf_status; +} + +/** + * wlan_sap_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 wlan_sap_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; +} diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h new file mode 100644 index 000000000000..117240d9a75a --- /dev/null +++ b/core/sme/inc/csr_api.h @@ -0,0 +1,1644 @@ +/* + * 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 csr_api.h + * + * Exports and types for the Common Scan and Roaming Module interfaces. + */ + +#ifndef CSRAPI_H__ +#define CSRAPI_H__ + +#include "sir_api.h" +#include "sir_mac_prot_def.h" +#include "csr_link_list.h" + +#define CSR_INVALID_SCANRESULT_HANDLE (NULL) + +typedef enum { + CH_WIDTH_20MHZ = 0, + CH_WIDTH_40MHZ = 1, + CH_WIDTH_80MHZ = 2, + CH_WIDTH_160MHZ = 3, + CH_WIDTH_80P80MHZ = 4 +} phy_ch_width; + +typedef struct ch_params_s { + phy_ch_width ch_width; + uint8_t sec_ch_offset; + uint8_t center_freq_seg0; + uint8_t center_freq_seg1; +} chan_params_t; + +typedef enum { + /* never used */ + eCSR_AUTH_TYPE_NONE, + /* 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 + /* WAPI */ + eCSR_ENCRYPT_TYPE_WPI, +#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 { + /* 11a/b/g only, no HT, no proprietary */ + eCSR_DOT11_MODE_abg = 0x0001, + 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, + + /* specify the number of maximum bits for phyMode */ + eCSR_NUM_PHY_MODE = 16, +} eCsrPhyMode; + +typedef enum { + eCSR_BSS_TYPE_NONE, + eCSR_BSS_TYPE_INFRASTRUCTURE, + eCSR_BSS_TYPE_INFRA_AP, /* SoftAP AP */ + eCSR_BSS_TYPE_IBSS, /* IBSS network we'll NOT start */ + eCSR_BSS_TYPE_START_IBSS, /* IBSS network we'll start if no partners */ + 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_PROBE_SCAN, /* direct probe on entry from candidate list */ + 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 abort due to band change */ + eCSR_SCAN_ABORT_SSID_ONLY +} 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 { + uint8_t numOfChannels; + uint8_t *ChannelList; /* it will be an array of channels */ +} tCsrChannelInfo, *tpCsrChannelInfo; + +typedef struct tagCsrSSIDInfo { + tSirMacSSid SSID; + bool handoffPermitted; + bool ssidHidden; +} tCsrSSIDInfo; + +typedef struct tagCsrSSIDs { + uint32_t numOfSSIDs; + tCsrSSIDInfo *SSIDList; /* To be allocated for array of SSIDs */ +} tCsrSSIDs; + +typedef struct tagCsrBSSIDs { + uint32_t numOfBSSIDs; + struct cdf_mac_addr *bssid; +} tCsrBSSIDs; + +typedef struct tagCsrStaParams { + uint16_t capability; + uint8_t extn_capability[SIR_MAC_MAX_EXTN_CAP]; + uint8_t supported_rates_len; + uint8_t supported_rates[SIR_MAC_MAX_SUPP_RATES]; + uint8_t htcap_present; + tSirHTCap HTCap; + uint8_t vhtcap_present; + tSirVHTCap VHTCap; + uint8_t uapsd_queues; + uint8_t max_sp; + uint8_t supported_channels_len; + uint8_t supported_channels[SIR_MAC_MAX_SUPP_CHANNELS]; + uint8_t supported_oper_classes_len; + uint8_t supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} tCsrStaParams; + +typedef struct tagCsrScanRequest { + tSirScanType scanType; + struct cdf_mac_addr bssid; + eCsrRoamBssType BSSType; + tCsrSSIDs SSIDs; + tCsrChannelInfo ChannelInfo; + uint32_t minChnTime; /* in units of milliseconds */ + uint32_t maxChnTime; /* in units of milliseconds */ + uint32_t restTime; /* in units of milliseconds */ + uint32_t uIEFieldLen; + uint8_t *pIEField; + eCsrRequestType requestType; /* 11d scan or full scan */ + bool p2pSearch; + bool skipDfsChnlInP2pSearch; + bool bcnRptReqScan; /* is Scan issued by Beacon Report Request */ + uint32_t scan_id; + uint32_t timestamp; +} tCsrScanRequest; + +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 for hidden SSID timer */ + /* + * 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 { + + uint32_t numEntries; + eCsrEncryptionType encryptionType[eCSR_NUM_OF_ENCRYPT_TYPE]; + +} tCsrEncryptionList, *tpCsrEncryptionList; + +typedef struct tagCsrAuthList { + uint32_t numEntries; + eCsrAuthType authType[eCSR_NUM_OF_SUPPORT_AUTH_TYPE]; +} tCsrAuthList, *tpCsrAuthList; + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsrMobilityDomainInfo { + uint8_t mdiePresent; + uint16_t mobilityDomain; +} tCsrMobilityDomainInfo; +#endif + +#ifdef FEATURE_WLAN_ESE +typedef struct tagCsrEseCckmInfo { + uint32_t reassoc_req_num; + bool krk_plumbed; + uint8_t krk[SIR_KRK_KEY_LEN]; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t 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) +typedef struct tagCsrEseCckmIe { + uint8_t cckmIe[CSR_DOT11F_IE_RSN_MAX_LEN]; + uint8_t cckmIeLen; +} tCsrEseCckmIe; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +typedef struct sCsrChannel_ { + uint8_t numChannels; + uint8_t channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +} sCsrChannel; + +typedef struct tagCsrScanResultFilter { + tCsrBSSIDs BSSIDs; + 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; + /* its a bit mask of all the needed phy mode defined in eCsrPhyMode */ + eCsrPhyMode phyMode; + /* + * If countryCode[0] is not 0, countryCode is checked + * independent of fCheckUnknownCountryCode + */ + uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t uapsd_mask; + /* For WPS filtering if true => auth and ecryption should be ignored */ + bool bWPSAssociation; + bool bOSENAssociation; +#if defined WLAN_FEATURE_VOWIFI + /* + * For measurement reports --> if set, only SSID, + * BSSID and channel is considered for filtering. + */ + bool fMeasurement; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif + bool p2pResult; +#ifdef WLAN_FEATURE_11W + /* Management Frame Protection */ + bool MFPEnabled; + uint8_t MFPRequired; + uint8_t 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; + struct sCsrChannel_ pcl_channels; + tCDF_CON_MODE csrPersona; +} tCsrScanResultFilter; + +typedef struct sCsrChnPower_ { + uint8_t firstChannel; + uint8_t numChannels; + uint8_t maxtxPower; +} sCsrChnPower; + +typedef struct tagCsr11dinfo { + sCsrChannel Channels; + uint8_t 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, + /* it means error happens before assoc_start/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. it 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, + /* IBSS indications. */ + eCSR_ROAM_IBSS_IND, + /* + * 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_IBSS_LEAVE, /* IBSS indications. */ + /* BSS in WDS mode status indication */ + eCSR_ROAM_WDS_IND, + /* BSS in SoftAP mode status indication */ + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_WPS_PBC_PROBE_REQ_IND, +#ifdef WLAN_FEATURE_VOWIFI_11R + eCSR_ROAM_FT_RESPONSE, +#endif + eCSR_ROAM_FT_START, + eCSR_ROAM_INDICATE_MGMT_FRAME, + eCSR_ROAM_REMAIN_CHAN_READY, + eCSR_ROAM_SEND_ACTION_CNF, + /* this mean error happens before assoc_start/roam_start is called. */ + eCSR_ROAM_SESSION_OPENED, + eCSR_ROAM_FT_REASSOC_FAILED, +#ifdef FEATURE_WLAN_LFR + eCSR_ROAM_PMK_NOTIFY, +#endif + /* + * Following 4 enums are used by FEATURE_WLAN_LFR_METRICS + * but they are needed for compilation even when + * FEATURE_WLAN_LFR_METRICS is not defined. + */ + eCSR_ROAM_PREAUTH_INIT_NOTIFY, + eCSR_ROAM_PREAUTH_STATUS_SUCCESS, + eCSR_ROAM_PREAUTH_STATUS_FAILURE, + eCSR_ROAM_HANDOVER_SUCCESS, +#ifdef FEATURE_WLAN_TDLS + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND, +#endif + /* Disaconnect all the clients */ + eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, + /* Stopbss triggered from SME due to different */ + eCSR_ROAM_SEND_P2P_STOP_BSS, + /* beacon interval */ +#ifdef WLAN_FEATURE_11W + eCSR_ROAM_UNPROT_MGMT_FRAME_IND, +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + eCSR_ROAM_TSM_IE_IND, + eCSR_ROAM_CCKM_PREAUTH_NOTIFY, + eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, + eCSR_ROAM_ESE_BCN_REPORT_IND, +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + + /* Radar indication from lower layers */ + eCSR_ROAM_DFS_RADAR_IND, + eCSR_ROAM_SET_CHANNEL_RSP, + + /* Channel sw update notification */ + eCSR_ROAM_DFS_CHAN_SW_NOTIFY, +} eRoamCmdStatus; + +/* comment inside indicates what roaming callback gets */ +typedef enum { + eCSR_ROAM_RESULT_NONE, + /* + * 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, + 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 */ + eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED, + /* Assoc rejected due to concurrent session running on a diff channel */ + eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL, +#ifdef FEATURE_WLAN_TDLS + eCSR_ROAM_RESULT_ADD_TDLS_PEER, + eCSR_ROAM_RESULT_UPDATE_TDLS_PEER, + eCSR_ROAM_RESULT_DELETE_TDLS_PEER, + eCSR_ROAM_RESULT_TEARDOWN_TDLS_PEER_IND, + eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND, + eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP, + eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER, + eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN, + eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED, +#endif + + eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS, + eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, + eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE, +} 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 */ + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED, + /* Associated in an Infrastructure network. */ + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED, + /* Participating in IBSS network though disconnection */ + eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED, + /* Participating in IBSS network with partner stations also present */ + eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED, + /* Participating in WDS network in AP/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, + +} 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 + +/* WEP keysize (in bits) */ +typedef enum { + /* 40 bit key + 24bit IV = 64bit WEP */ + eCSR_SECURITY_WEP_KEYSIZE_40 = 40, + /* 104bit key + 24bit IV = 128bit WEP */ + eCSR_SECURITY_WEP_KEYSIZE_104 = 104, + 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; + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +/** + * 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 + */ +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 { + struct cdf_mac_addr BSSID; + bool preAuthSupported; +} tPmkidCandidateInfo; + +typedef struct tagPmkidCacheInfo { + struct cdf_mac_addr BSSID; + uint8_t PMKID[CSR_RSN_PMKID_SIZE]; +} tPmkidCacheInfo; + +#ifdef FEATURE_WLAN_WAPI +typedef struct tagBkidCandidateInfo { + struct cdf_mac_addr BSSID; + bool preAuthSupported; +} tBkidCandidateInfo; + +typedef struct tagBkidCacheInfo { + struct cdf_mac_addr BSSID; + uint8_t BKID[CSR_WAPI_BKID_SIZE]; +} tBkidCacheInfo; +#endif /* FEATURE_WLAN_WAPI */ + +typedef struct tagCsrKeys { + /* Also use to indicate whether the key index is set */ + uint8_t KeyLength[CSR_MAX_NUM_KEY]; + uint8_t KeyMaterial[CSR_MAX_NUM_KEY][CSR_MAX_KEY_LEN]; + uint8_t defaultIndex; +} tCsrKeys; + +/* + * Following fields which're part of tCsrRoamConnectedProfile might need + * modification dynamically once STA is up & running & this'd 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 + */ + uint8_t uapsd_mask; + /* HDD might ask to modify this field */ + uint16_t 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 bit mask of all the needed phy mode defined in eCsrPhyMode */ + uint32_t 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 */ + bool MFPEnabled; + uint8_t MFPRequired; + uint8_t MFPCapable; +#endif + tCsrKeys Keys; + eCsrCBChoice CBMode; + tCsrChannelInfo ChannelInfo; + uint8_t operationChannel; + chan_params_t ch_params; + /* If this is 0, SME will fill in for caller. */ + uint16_t beaconInterval; + /* + * 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 resp this'd carry cnf of what ACs U-APSD got setup for + */ + uint8_t uapsd_mask; + uint32_t nWPAReqIELength; /* The byte count in the pWPAReqIE */ + uint8_t *pWPAReqIE; /* If not null,it's IE byte stream for WPA */ + uint32_t nRSNReqIELength; /* The byte count in the pRSNReqIE */ + uint8_t *pRSNReqIE; /* If not null,it's IE byte stream for RSN */ +#ifdef FEATURE_WLAN_WAPI + uint32_t nWAPIReqIELength;/* The byte count in the pWAPIReqIE */ + uint8_t *pWAPIReqIE; /* If not null,it's IE byte stream for WAPI */ +#endif /* FEATURE_WLAN_WAPI */ + + uint32_t nAddIEScanLength;/* pAddIE for scan (at the time of join) */ + /* + * If not null,it's the IE byte stream for additional IE, + * which can be WSC IE and/or P2P IE + */ + uint8_t *pAddIEScan; + uint32_t nAddIEAssocLength; /* The byte count in the pAddIE for assoc */ + /* + * If not null, it has the IE byte stream for additional IE, + * which can be WSC IE and/or P2P IE + */ + uint8_t *pAddIEAssoc; + /* it is ignored if [0] is 0. */ + uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; + /* WPS Association if true => auth and ecryption should be ignored */ + bool bWPSAssociation; + bool bOSENAssociation; + uint32_t nWSCReqIELength; /* The byte count in the pWSCReqIE */ + uint8_t *pWSCReqIE; /* If not null,it's IE byte stream for WSC */ + uint8_t ieee80211d; + uint8_t privacy; + bool fwdWPSPBCProbeReq; + tAniAuthType csr80211AuthType; + uint32_t dtimPeriod; + bool ApUapsdEnable; + bool protEnabled; + bool obssProtEnabled; + uint16_t cfg_protection; + uint8_t wps_state; +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif + tCDF_CON_MODE csrPersona; + uint8_t disableDFSChSwitch; + /* addIe params */ + tSirAddIeParams addIeParams; + uint8_t sap_dot11mc; +} tCsrRoamProfile; + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +typedef struct tagCsrRoamHTProfile { + uint8_t phymode; + uint8_t htCapability; + uint8_t htSupportedChannelWidthSet; + uint8_t htRecommendedTxWidthSet; + ePhyChanBondState htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + uint8_t vhtCapability; + uint8_t vhtTxChannelWidthSet; + uint8_t apCenterChan; + uint8_t apChanWidth; +#endif +} tCsrRoamHTProfile; +#endif +typedef struct tagCsrRoamConnectedProfile { + tSirMacSSid SSID; + bool handoffPermitted; + bool ssidHidden; + struct cdf_mac_addr bssid; + eCsrRoamBssType BSSType; + eCsrAuthType AuthType; + tCsrAuthList AuthInfo; + eCsrEncryptionType EncryptionType; + tCsrEncryptionList EncryptionInfo; + eCsrEncryptionType mcEncryptionType; + tCsrEncryptionList mcEncryptionInfo; + eCsrCBChoice CBMode; + uint8_t operationChannel; + uint32_t vht_channel_width; + uint16_t 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) + */ + uint8_t acm_mask; + tCsrRoamModifyProfileFields modifyProfileFields; + uint32_t nAddIEAssocLength; + /* + * If not null,it's IE byte stream for additional IE, + * which can be WSC IE and/or P2P IE + */ + uint8_t *pAddIEAssoc; + tSirBssDescription *pBssDesc; + bool qap; /* AP supports QoS */ + bool qosConnection; /* A connection is QoS enabled */ +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsrMobilityDomainInfo MDID; +#endif +#ifdef FEATURE_WLAN_ESE + tCsrEseCckmInfo eseCckmInfo; + bool isESEAssoc; +#endif + uint32_t dot11Mode; + uint8_t proxyARPService; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tCsrRoamHTProfile HTProfile; +#endif +#ifdef WLAN_FEATURE_11W + /* Management Frame Protection */ + bool MFPEnabled; + uint8_t MFPRequired; + uint8_t MFPCapable; +#endif +} tCsrRoamConnectedProfile; + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsr11rConfigParams { + bool IsFTResourceReqSupported; +} tCsr11rConfigParams; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +typedef struct tagCsrNeighborRoamConfigParams { + + uint32_t nNeighborScanTimerPeriod; + uint8_t nNeighborLookupRssiThreshold; + uint16_t nNeighborScanMinChanTime; + uint16_t nNeighborScanMaxChanTime; + sCsrChannel neighborScanChanList; + uint8_t nMaxNeighborRetries; + uint16_t nNeighborResultsRefreshPeriod; + uint16_t nEmptyScanRefreshPeriod; + uint8_t nOpportunisticThresholdDiff; + uint8_t nRoamRescanRssiDiff; + uint8_t nRoamBmissFirstBcnt; + uint8_t nRoamBmissFinalBcnt; + uint8_t nRoamBeaconRssiWeight; + uint8_t 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 { + uint32_t FragmentationThreshold; + /* keep this uint32_t. This gets converted to ePhyChannelBondState */ + uint32_t channelBondingMode24GHz; + uint32_t channelBondingMode5GHz; + eCsrPhyMode phyMode; + eCsrBand eBand; + uint32_t RTSThreshold; + uint32_t HeartbeatThresh50; + uint32_t HeartbeatThresh24; + eCsrCBChoice cbChoice; + eCsrBand bandCapability; /* indicate hw capability */ + uint16_t TxRate; + eCsrRoamWmmUserModeType WMMSupportMode; + bool Is11eSupportEnabled; + bool Is11dSupportEnabled; + bool Is11dSupportEnabledOriginal; + bool Is11hSupportEnabled; + bool shortSlotTime; + bool ProprietaryRatesEnabled; + uint8_t AdHocChannel24; + uint8_t AdHocChannel5G; + /* + * this number minus one is the number of times a scan doesn't find it + * before it is removed + */ + uint32_t nScanResultAgeCount; + /* scan res aging time threshold when Not-Connect-No-PowerSave,in sec */ + uint32_t scanAgeTimeNCNPS; + /* scan res aging time threshold when Not-Connect-Power-Save,in sec */ + uint32_t scanAgeTimeNCPS; + /* scan res aging time threshold when Connect-No-Power-Save, in sec */ + uint32_t scanAgeTimeCNPS; + /* scan res aging time threshold when Connect-Power-Save, in sec */ + uint32_t scanAgeTimeCPS; + /* In sec, CSR'll try this long before gives up. 0 means no roaming */ + uint32_t nRoamingTime; + /* to set the RSSI difference for each category */ + uint8_t bCatRssiOffset; + /* to set MCC Enable/Disable mode */ + uint8_t fEnableMCCMode; + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + /* + * 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 + */ + uint8_t fAllowMCCGODiffBI; + tCsr11dinfo Csr11dinfo; + + /* Country Code Priority */ + bool fSupplicantCountryCodeHasPriority; + uint16_t vccRssiThreshold; + uint32_t vccUlMacLossThreshold; + uint32_t nPassiveMinChnTime; /* in units of milliseconds */ + uint32_t nPassiveMaxChnTime; /* in units of milliseconds */ + uint32_t nActiveMinChnTime; /* in units of milliseconds */ + uint32_t nActiveMaxChnTime; /* in units of milliseconds */ + uint32_t nInitialDwellTime; /* in units of milliseconds */ + bool initial_scan_no_dfs_chnl; +#ifdef WLAN_AP_STA_CONCURRENCY + uint32_t nPassiveMinChnTimeConc; /* in units of milliseconds */ + uint32_t nPassiveMaxChnTimeConc; /* in units of milliseconds */ + uint32_t nActiveMinChnTimeConc; /* in units of milliseconds */ + uint32_t nActiveMaxChnTimeConc; /* in units of milliseconds */ + uint32_t nRestTimeConc; /* in units of milliseconds */ + /* num of channels combined for STA in each split scan operation */ + uint8_t nNumStaChanCombinedConc; + /* number of channels combined for P2P in each split scan operation */ + uint8_t nNumP2PChanCombinedConc; +#endif + /* + * 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. + */ + uint8_t nTxPowerCap; + /* stats request frequency from PE while in full power */ + uint32_t statsReqPeriodicity; + /* stats request frequency from PE while in power save */ + uint32_t statsReqPeriodicityInPS; +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsr11rConfigParams csr11rConfig; +#endif +#ifdef FEATURE_WLAN_ESE + uint8_t isEseIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_LFR + uint8_t isFastRoamIniFeatureEnabled; + uint8_t MAWCEnabled; +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + uint8_t isFastTransitionEnabled; + uint8_t RoamRssiDiff; + bool 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 + */ + bool 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. + */ + bool 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 + */ + bool 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) + */ + uint8_t fEnableDFSChnlScan; + /* + * To enable/disable scanning 2.4Ghz channels twice on a single scan + * request from HDD + */ + bool fScanTwice; +#ifdef WLAN_FEATURE_11AC + uint32_t nVhtChannelWidth; + uint8_t enableTxBF; + uint8_t txBFCsnValue; + uint8_t enable2x2; + bool enableVhtFor24GHz; + uint8_t enableMuBformee; + uint8_t enableVhtpAid; + uint8_t enableVhtGid; +#endif + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmps; + bool ignore_peer_erp_info; + /* + * To enable/disable scanning only 2.4Ghz channels on first scan + */ + bool fFirstScanOnly2GChnl; +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + bool nRoamPrefer5GHz; + bool nRoamIntraBand; + uint8_t nProbes; + uint16_t nRoamScanHomeAwayTime; + + bool isRoamOffloadScanEnabled; + bool bFastRoamInConIniFeatureEnabled; +#endif + uint8_t scanCfgAgingTime; + uint8_t enableTxLdpc; + uint8_t isAmsduSupportInAMPDU; + uint8_t nSelect5GHzMargin; + uint8_t isCoalesingInIBSSAllowed; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + uint8_t allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + bool isRoamOffloadEnabled; +#endif + bool obssEnabled; + uint8_t conc_custom_rule1; + uint8_t conc_custom_rule2; + uint8_t is_sta_connection_in_5gz_enabled; + bool sendDeauthBeforeCon; + + /* 802.11p enable */ + bool enable_dot11p; + uint8_t max_scan_count; +} tCsrConfigParam; + +/* Tush */ +typedef struct tagCsrUpdateConfigParam { + tCsr11dinfo Csr11dinfo; +} tCsrUpdateConfigParam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define csr_roamIsRoamOffloadEnabled(pMac) \ + (pMac->roam.configParam.isRoamOffloadEnabled) +#define DEFAULT_REASSOC_FAILURE_TIMEOUT 1000 +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* connected but not authenticated */ +#define CSR_ROAM_AUTH_STATUS_CONNECTED 0x1 +/* connected and authenticated */ +#define CSR_ROAM_AUTH_STATUS_AUTHENTICATED 0x2 +#endif + +typedef struct tagCsrRoamInfo { + tCsrRoamProfile *pProfile; + tSirBssDescription *pBssDesc; + uint32_t nBeaconLength; + uint32_t nAssocReqLength; + uint32_t nAssocRspLength; + uint32_t nFrameLength; + uint8_t frameType; + /* + * 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. + */ + uint8_t *pbFrames; + bool fReassocReq; /* set to true if for re-association */ + bool fReassocRsp; /* set to true if for re-association */ + struct cdf_mac_addr bssid; + /* + * Only valid in IBSS. this is the peers MAC address for + * eCSR_ROAM_RESULT_IBSS_NEW_PEER or PEER_DEPARTED + */ + struct cdf_mac_addr peerMac; + tSirResultCodes statusCode; + /* this'd be our own defined or sent from otherBSS(per 802.11spec) */ + uint32_t reasonCode; + uint8_t staId; /* Peer stationId when connected */ + /* + * The DPU signatures will be sent eventually to TL to help it + * determine the assoc to which a packet belongs to unicast DPU sign + */ + uint8_t ucastSig; + uint8_t bcastSig; /* Broadcast DPU signature */ + /* false means auth needed from supplicant. true means authenticated */ + bool fAuthRequired; + uint8_t sessionId; + uint8_t rsnIELen; + uint8_t *prsnIE; + uint8_t wapiIELen; + uint8_t *pwapiIE; + uint8_t addIELen; + uint8_t *paddIE; + union { + tSirMicFailureInfo *pMICFailureInfo; + tCsrRoamConnectedProfile *pConnectedProfile; + tSirWPSPBCProbeReq *pWPSPBCProbeReq; + } u; + bool wmmEnabledSta; /* set to true if WMM enabled STA */ + uint32_t dtimPeriod; +#ifdef FEATURE_WLAN_ESE + bool isESEAssoc; +#ifdef FEATURE_WLAN_ESE_UPLOAD + tSirTsmIE tsmIe; + uint32_t timestamp[2]; + uint16_t tsmRoamDelay; + tSirEseBcnReportRsp *pEseBcnReportRsp; +#endif /* FEATURE_WLAN_ESE_UPLOAD */ +#endif + void *pRemainCtx; + uint32_t roc_scan_id; + uint32_t rxChan; +#ifdef FEATURE_WLAN_TDLS + uint8_t 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 */ + uint32_t beaconLength; + uint8_t *beaconPtr; + uint32_t assocReqLength; + uint8_t *assocReqPtr; + int8_t rxRssi; + tSirSmeDfsEventInd dfs_event; + tSirChanChangeResponse *channelChangeRespEvent; + /* Timing and fine Timing measurement capability clubbed together */ + uint8_t timingMeasCap; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t roamSynchInProgress; + uint8_t synchAuthStatus; + uint8_t kck[SIR_KCK_KEY_LEN]; + uint8_t kek[SIR_KEK_KEY_LEN]; + uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; +#endif + tSirSmeChanInfo chan_info; +} tCsrRoamInfo; + +typedef struct tagCsrFreqScanInfo { + uint32_t nStartFreq; /* in unit of MHz */ + uint32_t nEndFreq; /* in unit of MHz */ + tSirScanType scanType; +} tCsrFreqScanInfo; + +typedef struct sSirSmeAssocIndToUpperLayerCnf { + uint16_t messageType; /* eWNI_SME_ASSOC_CNF */ + uint16_t length; + uint8_t sessionId; + tSirResultCodes statusCode; + tSirMacAddr bssId; /* Self BSSID */ + tSirMacAddr peerMacAddr; + uint16_t aid; + tSirMacAddr alternateBssId; + uint8_t alternateChannelId; + uint8_t wmmEnabledSta; /* set to true if WMM enabled STA */ + tSirRSNie rsnIE; /* RSN IE received from peer */ + tSirWAPIie wapiIE; /* WAPI IE received from peer */ + tSirAddie addIE; /* this can be WSC and/or P2P IE */ + uint8_t reassocReq; /* set to true if reassoc */ + /* Timing and fine Timing measurement capability clubbed together */ + uint8_t timingMeasCap; + tSirSmeChanInfo chan_info; +} tSirSmeAssocIndToUpperLayerCnf, *tpSirSmeAssocIndToUpperLayerCnf; + +typedef struct tagCsrSummaryStatsInfo { + uint32_t retry_cnt[4]; + uint32_t multiple_retry_cnt[4]; + uint32_t tx_frm_cnt[4]; + /* uint32_t num_rx_frm_crc_err; same as rx_error_cnt */ + /* uint32_t num_rx_frm_crc_ok; same as rx_frm_cnt */ + uint32_t rx_frm_cnt; + uint32_t frm_dup_cnt; + uint32_t fail_cnt[4]; + uint32_t rts_fail_cnt; + uint32_t ack_fail_cnt; + uint32_t rts_succ_cnt; + uint32_t rx_discard_cnt; + uint32_t rx_error_cnt; + uint32_t tx_byte_cnt; + +} tCsrSummaryStatsInfo; + +typedef struct tagCsrGlobalClassAStatsInfo { + uint32_t rx_frag_cnt; + uint32_t promiscuous_rx_frag_cnt; + /* uint32_t rx_fcs_err; */ + uint32_t rx_input_sensitivity; + uint32_t max_pwr; + /* uint32_t default_pwr; */ + uint32_t sync_fail_cnt; + uint32_t tx_rate; + /* mcs index for HT20 and HT40 rates */ + uint32_t mcs_index; + /* to diff between HT20 & HT40 rates;short & long guard interval */ + uint32_t tx_rate_flags; + +} tCsrGlobalClassAStatsInfo; + +typedef struct tagCsrGlobalClassBStatsInfo { + uint32_t uc_rx_wep_unencrypted_frm_cnt; + uint32_t uc_rx_mic_fail_cnt; + uint32_t uc_tkip_icv_err; + uint32_t uc_aes_ccmp_format_err; + uint32_t uc_aes_ccmp_replay_cnt; + uint32_t uc_aes_ccmp_decrpt_err; + uint32_t uc_wep_undecryptable_cnt; + uint32_t uc_wep_icv_err; + uint32_t uc_rx_decrypt_succ_cnt; + uint32_t uc_rx_decrypt_fail_cnt; + uint32_t mcbc_rx_wep_unencrypted_frm_cnt; + uint32_t mcbc_rx_mic_fail_cnt; + uint32_t mcbc_tkip_icv_err; + uint32_t mcbc_aes_ccmp_format_err; + uint32_t mcbc_aes_ccmp_replay_cnt; + uint32_t mcbc_aes_ccmp_decrpt_err; + uint32_t mcbc_wep_undecryptable_cnt; + uint32_t mcbc_wep_icv_err; + uint32_t mcbc_rx_decrypt_succ_cnt; + uint32_t mcbc_rx_decrypt_fail_cnt; + +} tCsrGlobalClassBStatsInfo; + +typedef struct tagCsrGlobalClassCStatsInfo { + uint32_t rx_amsdu_cnt; + uint32_t rx_ampdu_cnt; + uint32_t tx_20_frm_cnt; + uint32_t rx_20_frm_cnt; + uint32_t rx_mpdu_in_ampdu_cnt; + uint32_t ampdu_delimiter_crc_err; + +} tCsrGlobalClassCStatsInfo; + +typedef struct tagCsrGlobalClassDStatsInfo { + uint32_t tx_uc_frm_cnt; + uint32_t tx_mc_frm_cnt; + uint32_t tx_bc_frm_cnt; + uint32_t rx_uc_frm_cnt; + uint32_t rx_mc_frm_cnt; + uint32_t rx_bc_frm_cnt; + uint32_t tx_uc_byte_cnt[4]; + uint32_t tx_mc_byte_cnt; + uint32_t tx_bc_byte_cnt; + uint32_t rx_uc_byte_cnt[4]; + uint32_t rx_mc_byte_cnt; + uint32_t rx_bc_byte_cnt; + uint32_t rx_byte_cnt; + uint32_t num_rx_bytes_crc_ok; + uint32_t rx_rate; + +} tCsrGlobalClassDStatsInfo; + +typedef struct tagCsrPerStaStatsInfo { + uint32_t tx_frag_cnt[4]; + uint32_t tx_ampdu_cnt; + uint32_t tx_mpdu_in_ampdu_cnt; +} tCsrPerStaStatsInfo; + +typedef struct tagCsrRoamSetKey { + eCsrEncryptionType encType; + tAniKeyDirection keyDirection; /* Tx, Rx or Tx-and-Rx */ + struct cdf_mac_addr peerMac; /* Peer MAC. ALL 1's for group key */ + uint8_t paeRole; /* 0 for supplicant */ + uint8_t keyId; /* Key index */ + uint16_t keyLength; /* Number of bytes containing the key in pKey */ + uint8_t Key[CSR_MAX_KEY_LEN]; + uint8_t keyRsc[CSR_MAX_RSC_LEN]; +} tCsrRoamSetKey; + +typedef struct tagCsrRoamRemoveKey { + eCsrEncryptionType encType; + struct cdf_mac_addr peerMac; /* Peer MAC. ALL 1's for group key */ + uint8_t keyId; /* key index */ +} tCsrRoamRemoveKey; + +#ifdef FEATURE_WLAN_TDLS + +typedef struct tagCsrLinkEstablishParams { + tSirMacAddr peerMac; + uint8_t uapsdQueues; + uint8_t maxSp; + uint8_t isBufSta; + uint8_t isOffChannelSupported; + uint8_t isResponder; + uint8_t supportedChannelsLen; + uint8_t supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + uint8_t supportedOperClassesLen; + uint8_t supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} tCsrTdlsLinkEstablishParams; + +typedef struct tagCsrTdlsSendMgmt { + tSirMacAddr peerMac; + uint8_t frameType; + uint8_t dialog; + uint16_t statusCode; + uint8_t responder; + uint32_t peerCapability; + uint8_t *buf; + uint8_t len; + +} tCsrTdlsSendMgmt; +#endif + +typedef void *tScanResultHandle; + +typedef enum { + REASSOC = 0, + FASTREASSOC = 1 +} handoff_src; + +typedef struct tagCsrHandoffRequest { + struct cdf_mac_addr bssid; + uint8_t channel; + uint8_t src; /* To check if its a REASSOC or a FASTREASSOC IOCTL */ +} tCsrHandoffRequest; + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +typedef struct tagCsrEseBeaconReqParams { + uint16_t measurementToken; + uint8_t channel; + uint8_t scanMode; + uint16_t measurementDuration; +} tCsrEseBeaconReqParams, *tpCsrEseBeaconReqParams; + +typedef struct tagCsrEseBeaconReq { + uint8_t numBcnReqIe; + tCsrEseBeaconReqParams bcnReq[SIR_ESE_MAX_MEAS_IE_REQS]; +} tCsrEseBeaconReq, *tpCsrEseBeaconReq; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +struct tagCsrDelStaParams { + struct cdf_mac_addr peerMacAddr; + uint16_t reason_code; + uint8_t subtype; +}; + +/* + * NOTE: p2 is the second context pass in for the caller + * NOTE: what if callback is called before requester gets the scanId?? + */ +typedef CDF_STATUS (*csr_scan_completeCallback)(tHalHandle, void *p2, + uint8_t sessionId, + uint32_t scanID, + eCsrScanStatus status); +typedef CDF_STATUS (*csr_roam_completeCallback)(void *pContext, + tCsrRoamInfo * pParam, + uint32_t roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult); +typedef CDF_STATUS (*csr_roamSessionCloseCallback)(void *pContext); + +#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) +#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)) +#define CSR_IS_CLOSE_SESSION_COMMAND(pCommand) \ + ((pCommand)->command == eSmeCommandDelStaSession) + +CDF_STATUS csr_set_channels(tHalHandle hHal, tCsrConfigParam *pParam); + +CDF_STATUS csr_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode); + +/* enum to string conversion for debug output */ +const char *get_e_roam_cmd_status_str(eRoamCmdStatus val); +const char *get_e_csr_roam_result_str(eCsrRoamResult val); +CDF_STATUS csr_set_phy_mode(tHalHandle hHal, uint32_t phyMode, eCsrBand eBand, + bool *pfRestartNeeded); +typedef void (*csr_roamLinkQualityIndCallback) + (eCsrRoamLinkQualityInd ind, void *pContext); +typedef void (*tCsrStatsCallback)(void *stats, void *pContext); +typedef void (*tCsrRssiCallback)(int8_t rssi, uint32_t staId, void *pContext); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +typedef void (*tCsrTsmStatsCallback)(tAniTrafStrmMetrics tsmMetrics, + uint32_t staId, void *pContext); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +typedef void (*tCsrSnrCallback)(int8_t snr, uint32_t staId, void *pContext); + +#ifdef WLAN_FEATURE_VOWIFI_11R +CDF_STATUS csr_roam_issue_ft_preauth_req(tHalHandle hHal, uint32_t sessionId, + tpSirBssDescription pBssDescription); +#endif +CDF_STATUS csr_set_band(tHalHandle hHal, uint8_t sessionId, eCsrBand eBand); +eCsrBand csr_get_current_band(tHalHandle hHal); +typedef void (*csr_readyToSuspendCallback)(void *pContext, bool suspended); +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +typedef void (*csr_readyToExtWoWCallback)(void *pContext, bool status); +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS csr_roam_issue_ft_roam_offload_synch(tHalHandle hHal, + uint32_t sessionId, tSirBssDescription *pBssDescription); +#endif +typedef void (*tCsrLinkStatusCallback)(uint8_t status, void *pContext); +#endif diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h new file mode 100644 index 000000000000..e12fc255d23e --- /dev/null +++ b/core/sme/inc/csr_internal.h @@ -0,0 +1,1403 @@ +/* + * 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 csr_internal.h + * + * Define internal data structure for MAC. + */ +#ifndef CSRINTERNAL_H__ +#define CSRINTERNAL_H__ + +#include "cdf_status.h" +#include "cdf_lock.h" + +#include "cdf_mc_timer.h" +#include "csr_support.h" +#include "cds_reg_service.h" + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "csr_neighbor_roam.h" +#endif + +#include "sir_types.h" + +#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 + +/* session ID invalid */ +#define CSR_SESSION_ID_INVALID 0xFF +/* No of sessions to be supported, and a session is for Infra, IBSS or BT-AMP */ +#define CSR_ROAM_SESSION_MAX 5 +#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 == SME_SESSION_ID_ANY) +#define CSR_MAX_NUM_COUNTRY_CODE 100 +#define CSR_IS_SELECT_5GHZ_MARGIN(pMac) \ + ( \ + (((pMac)->roam.configParam.nSelect5GHzMargin) ? true : false) \ + ) +#define CSR_IS_SELECT_5G_PREFERRED(pMac) \ + ( \ + (((pMac)->roam.configParam.roam_params.is_5g_pref_enabled) ? \ + true : 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) ? true : false) \ + ) +#define CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac) \ + ( \ + (((pMac)->roam.configParam.nRoamIntraBand) ? true : false) \ + ) +#endif +#define CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac) \ + ( \ + (((pMac)->roam.configParam.bFastRoamInConIniFeatureEnabled) ? \ + true : false) \ + ) + +/* Support for "Fast roaming" (i.e., ESE, LFR, or 802.11r.) */ +#define CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 + +/* Used to determine what to set to the WNI_CFG_DOT11_MODE */ +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. Its for CSR's internal use */ + eCSR_CFG_DOT11_MODE_AUTO, +} eCsrCfgDot11Mode; + +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 succeed, try rest of the channels */ + eCsrScanUserRequest, + eCsrScanForSsid, + eCsrScanIdleScan, + eCsrScanProbeBss, /* direct prb on entry from candidate list-HO */ + eCsrScanAbortNormalScan,/* aborting a normal scan */ + eCsrScanP2PFindPeer, + eCsrScanCandidateFound, +} eCsrScanReason; + +typedef enum { + /* Roaming because we've not established the initial connection. */ + eCsrNoConnection, + /* roaming because LIM reported a cap change in the associated AP. */ + eCsrCapsChange, + /* roaming because someone asked us to Disassoc & stay disassociated. */ + eCsrForcedDisassoc, + /* roaming because an 802.11 request was issued to the driver. */ + eCsrHddIssued, + /* roaming because we lost link to an associated AP */ + eCsrLostLink1, + eCsrLostLink2, + eCsrLostLink3, + /* roaming because we need to force a Disassoc due to MIC failure */ + eCsrForcedDisassocMICFailure, + eCsrHddIssuedReassocToSameAP, + eCsrSmeIssuedReassocToSameAP, + eCsrSmeIssuedReassocToDiffAP, + /* roaming becuase someone asked us to deauth and stay disassociated. */ + eCsrForcedDeauth, + /* will be issued by Handoff logic to disconect from current AP */ + eCsrSmeIssuedDisassocForHandoff, + /* will be issued by Handoff logic to join a new AP with same profile */ + eCsrSmeIssuedAssocToSimilarAP, + /* ibss jointimer fired before any peer showedup, so shutdown network */ + eCsrSmeIssuedIbssJoinFailure, + 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, + /* Continue the current roam command after disconnect */ + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, + 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_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; + +/** + * enum eCSR_WLAN_DIAG_EVENT_TYPE - enum for DIAG events + * @eCSR_EVENT_SCAN_COMPLETE - scan complete + * @eCSR_EVENT_SCAN_RES_FOUND - scan result found + */ +typedef enum { + eCSR_EVENT_TYPE_INVALID = 0, + eCSR_EVENT_SCAN_COMPLETE = 64, + eCSR_EVENT_SCAN_RES_FOUND = 65, +} eCSR_WLAN_DIAG_EVENT_TYPE; + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +typedef struct tagCsrChannel { + uint8_t numChannels; + uint8_t channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +} tCsrChannel; + +typedef struct tagScanProfile { + uint32_t minChnTime; + uint32_t maxChnTime; + uint32_t restTime; /* This is ignored if not associated */ + uint32_t numOfChannels; + uint8_t *pChannelList; + tSirScanType scanType; + eCsrRoamBssType bssType; + uint8_t ssid[WNI_CFG_SSID_LEN]; + uint8_t bReturnAfter1stMatch; + uint8_t fUniqueResult; + uint8_t freshScan; + struct cdf_mac_addr bssid; +} tScanProfile; + +typedef struct tagBssConfigParam { + eCsrMediaAccessType qosType; + tSirMacSSid SSID; + uint32_t uRTSThresh; + uint32_t uDeferThresh; + eCsrCfgDot11Mode uCfgDot11Mode; + eCsrBand eBand; + uint8_t standardRate[CSR_DOT11_SUPPORTED_RATES_MAX]; + uint8_t extendedRate[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; + eCsrExposedTxRate txRate; + tAniAuthType authType; + eCsrEncryptionType encType; + uint32_t uShortSlotTime; + uint32_t uHTSupport; + uint32_t uPowerLimit; + uint32_t uHeartBeatThresh; + uint32_t uJoinTimeOut; + tSirMacCapabilityInfo BssCap; + bool f11hSupport; + ePhyChanBondState cbMode; +} tBssConfigParam; + +typedef struct tagCsrRoamStartBssParams { + tSirMacSSid ssId; + + /* + * This is the BSSID for the party we want to + * join (only use for IBSS or WDS). + */ + struct cdf_mac_addr bssid; + tSirNwType sirNwType; + ePhyChanBondState cbMode; + tSirMacRateSet operationalRateSet; + tSirMacRateSet extendedRateSet; + uint8_t operationChn; + chan_params_t ch_params; + eCsrCfgDot11Mode uCfgDot11Mode; + uint8_t privacy; + bool fwdWPSPBCProbeReq; + bool protEnabled; + bool obssProtEnabled; + tAniAuthType authType; + uint16_t beaconInterval; /* If this is 0, SME'll fill in for caller */ + uint16_t ht_protection; + uint32_t dtimPeriod; + uint8_t ApUapsdEnable; + uint8_t ssidHidden; + uint8_t wps_state; + tCDF_CON_MODE bssPersona; + uint16_t nRSNIELength; /* If 0, pRSNIE is ignored. */ + uint8_t *pRSNIE; /* If not null, it has IE byte stream for RSN */ + /* Flag used to indicate update beaconInterval */ + bool updatebeaconInterval; +#ifdef WLAN_FEATURE_11W + bool mfpCapable; + bool mfpRequired; +#endif + tSirAddIeParams addIeParams; + uint8_t sap_dot11mc; +} tCsrRoamStartBssParams; + +typedef struct tagScanCmd { + uint32_t scanID; + csr_scan_completeCallback callback; + void *pContext; + eCsrScanReason reason; + eCsrRoamState lastRoamState[CSR_ROAM_SESSION_MAX]; + tCsrRoamProfile *pToRoamProfile; + /* this is the ID related to the pToRoamProfile */ + uint32_t roamId; + union { + tCsrScanRequest scanRequest; + /* tCsrBGScanRequest bgScanRequest is no longer used */ + } u; + /* This flag will be set while aborting the scan due to band change */ + bool abortScanDueToBandChange; + cdf_mc_timer_t csr_scan_timer; +} tScanCmd; + +typedef struct tagRoamCmd { + uint32_t roamId; + eCsrRoamReason roamReason; + tCsrRoamProfile roamProfile; + tScanResultHandle hBSSList; /* BSS list fits the profile */ + /* + * point to the current BSS in the list that is roaming. + * It starts from head to tail + * */ + tListElem *pRoamBssEntry; + tSirBssDescription *pLastRoamBss; /* the last BSS we try and failed */ + bool fReleaseBssList; /* whether to free hBSSList */ + bool fReleaseProfile; /* whether to free roamProfile */ + bool fReassoc; /* whether this cmd is for reassoc */ + /* whether pMac->roam.pCurRoamProfile needs to be updated */ + bool fUpdateCurRoamProfile; + /* + * this is for CSR internal used only. And it should not be assigned + * when creating the command. This causes the roam cmd not todo anything + */ + bool fReassocToSelfNoCapChange; + + bool fStopWds; + tSirMacAddr peerMac; + tSirMacReasonCodes reason; +} tRoamCmd; + +typedef struct tagSetKeyCmd { + uint32_t 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 */ + uint8_t paeRole; /* 0 for supplicant */ + uint8_t keyId; /* Kye index */ + uint8_t keyLength; /* Number of bytes containing the key in pKey */ + uint8_t Key[CSR_MAX_KEY_LEN]; + uint8_t keyRsc[CSR_MAX_RSC_LEN]; +} tSetKeyCmd; + +typedef struct tagWmStatusChangeCmd { + eCsrRoamWmStatusChangeTypes Type; + union { + tSirSmeDeauthInd DeauthIndMsg; + tSirSmeDisassocInd DisassocIndMsg; + } u; + +} tWmStatusChangeCmd; + +typedef struct tagAddStaForSessionCmd { + /* Session self mac addr */ + tSirMacAddr selfMacAddr; + tCDF_CON_MODE currDeviceMode; + uint32_t type; + uint32_t subType; + uint8_t sessionId; +} tAddStaForSessionCmd; + +typedef struct tagDelStaForSessionCmd { + /* Session self mac addr */ + tSirMacAddr selfMacAddr; + csr_roamSessionCloseCallback callback; + void *pContext; +} tDelStaForSessionCmd; + +/* This structure represents one scan request */ +typedef struct tagCsrCmd { + tListElem Link; + eCsrRoamCommands command; + uint8_t sessionId; /* Session ID for this command */ + union { + tScanCmd scanCmd; + tRoamCmd roamCmd; + tWmStatusChangeCmd wmStatusChangeCmd; + tSetKeyCmd setKeyCmd; + tAddStaForSessionCmd addStaSessionCmd; + tDelStaForSessionCmd delStaSessionCmd; + } u; +} tCsrCmd; + +#ifdef WLAN_FEATURE_VOWIFI_11R +typedef struct tagCsr11rConfig { + bool IsFTResourceReqSupported; +} tCsr11rConfig; +#endif + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +typedef struct tagCsrNeighborRoamConfig { + uint32_t nNeighborScanTimerPeriod; + uint8_t nNeighborLookupRssiThreshold; + uint16_t nNeighborScanMinChanTime; + uint16_t nNeighborScanMaxChanTime; + sCsrChannel neighborScanChanList; + uint8_t nMaxNeighborRetries; + uint16_t nNeighborResultsRefreshPeriod; + uint16_t nEmptyScanRefreshPeriod; + uint8_t nOpportunisticThresholdDiff; + uint8_t nRoamRescanRssiDiff; + uint8_t nRoamBmissFirstBcnt; + uint8_t nRoamBmissFinalBcnt; + uint8_t nRoamBeaconRssiWeight; + uint8_t 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 { + uint32_t agingCount; + uint32_t FragmentationThreshold; + uint32_t channelBondingMode24GHz; + uint32_t channelBondingMode5GHz; + uint32_t RTSThreshold; + eCsrPhyMode phyMode; + eCsrCfgDot11Mode uCfgDot11Mode; + eCsrBand eBand; + uint32_t HeartbeatThresh50; + uint32_t HeartbeatThresh24; + eCsrCBChoice cbChoice; + eCsrBand bandCapability; /* indicate hw capability */ + eCsrRoamWmmUserModeType WMMSupportMode; + bool Is11eSupportEnabled; + bool Is11dSupportEnabled; + bool Is11dSupportEnabledOriginal; + bool Is11hSupportEnabled; + bool shortSlotTime; + bool ProprietaryRatesEnabled; + bool fenableMCCMode; + bool mcc_rts_cts_prot_enable; + bool mcc_bcast_prob_resp_enable; + uint16_t TxRate; + uint8_t fAllowMCCGODiffBI; + uint8_t AdHocChannel24; + uint8_t AdHocChannel5G; + /* scan res agingtime threshold when Not-Connect-No-Power-Save,in sec */ + uint32_t scanAgeTimeNCNPS; + /* scan res aging time threshold when Not-Connect-Power-Save, in sec*/ + uint32_t scanAgeTimeNCPS; + /* scan res aging time threshold when Connect-No-Power-Save, in sec*/ + uint32_t scanAgeTimeCNPS; + /* scan res aging time threshold when Connect-Power-Savein sec */ + uint32_t scanAgeTimeCPS; + /* each RSSI category has one value */ + uint32_t BssPreferValue[CSR_NUM_RSSI_CAT]; + int RSSICat[CSR_NUM_RSSI_CAT]; + uint8_t bCatRssiOffset; /* to set RSSI difference for each category */ + /* In secs, CSR'll try this long before gives up, 0 means no roaming */ + uint32_t nRoamingTime; + /* + * 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. + */ + /* Country Code Priority */ + bool fSupplicantCountryCodeHasPriority; + + uint16_t vccRssiThreshold; + uint32_t vccUlMacLossThreshold; + + uint32_t nPassiveMinChnTime; /* in units of milliseconds */ + uint32_t nPassiveMaxChnTime; /* in units of milliseconds */ + uint32_t nActiveMinChnTime; /* in units of milliseconds */ + uint32_t nActiveMaxChnTime; /* in units of milliseconds */ + + uint32_t nInitialDwellTime; /* in units of milliseconds */ + bool initial_scan_no_dfs_chnl; +#ifdef WLAN_AP_STA_CONCURRENCY + uint32_t nPassiveMinChnTimeConc;/* in units of milliseconds */ + uint32_t nPassiveMaxChnTimeConc;/* in units of milliseconds */ + uint32_t nActiveMinChnTimeConc; /* in units of milliseconds */ + uint32_t nActiveMaxChnTimeConc; /* in units of milliseconds */ + uint32_t nRestTimeConc; /* in units of milliseconds */ + /* number of channels combined for Sta in each split scan operation */ + uint8_t nNumStaChanCombinedConc; + /* number of channels combined for P2P in each split scan operation */ + uint8_t nNumP2PChanCombinedConc; +#endif + /* + * in dBm, the max TX power. The actual TX power is the lesser of this + * value & 11d. If 11d is disable, the lesser of this & default setting. + */ + uint8_t nTxPowerCap; + uint32_t statsReqPeriodicity; /* stats req freq while in fullpower */ + uint32_t statsReqPeriodicityInPS;/* stats req freq while in powersave */ + uint32_t dtimPeriod; + bool ssidHidden; +#ifdef WLAN_FEATURE_VOWIFI_11R + tCsr11rConfig csr11rConfig; +#endif +#ifdef FEATURE_WLAN_LFR + uint8_t isFastRoamIniFeatureEnabled; + uint8_t MAWCEnabled; + uint8_t isRoamOffloadScanEnabled; + bool bFastRoamInConIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + uint8_t isEseIniFeatureEnabled; +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) \ + || defined(FEATURE_WLAN_LFR) + uint8_t isFastTransitionEnabled; + uint8_t RoamRssiDiff; + bool nRoamPrefer5GHz; + bool nRoamIntraBand; + bool isWESModeEnabled; + bool nRoamScanControl; + uint8_t nProbes; + uint16_t 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 + */ + bool addTSWhenACMIsOff; + bool fValidateList; + /* + * Remove this code once SLM_Sessionization is supported + * BMPS_WORKAROUND_NOT_NEEDED + */ + bool doBMPSWorkaround; + /* To enable scanning 2g channels twice on single scan req from HDD */ + bool fScanTwice; +#ifdef WLAN_FEATURE_11AC + uint32_t nVhtChannelWidth; + uint8_t txBFEnable; + uint8_t txBFCsnValue; + uint8_t enable2x2; + bool enableVhtFor24GHz; + uint8_t txMuBformee; + uint8_t enableVhtpAid; + uint8_t enableVhtGid; +#endif + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmps; + uint8_t txLdpcEnable; + /* + * Enable/Disable heartbeat offload + */ + bool enableHeartBeatOffload; + uint8_t isAmsduSupportInAMPDU; + uint8_t nSelect5GHzMargin; + uint8_t isCoalesingInIBSSAllowed; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + uint8_t cc_switch_mode; +#endif + uint8_t allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + bool isRoamOffloadEnabled; +#endif + bool obssEnabled; + bool ignore_peer_erp_info; + uint8_t conc_custom_rule1; + uint8_t conc_custom_rule2; + uint8_t is_sta_connection_in_5gz_enabled; + struct roam_ext_params roam_params; + bool sendDeauthBeforeCon; +} tCsrConfig; + +typedef struct tagCsrChannelPowerInfo { + tListElem link; + uint8_t firstChannel; + uint8_t numChannels; + uint8_t txPower; + uint8_t 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) + */ + uint32_t reasonCode; + tSirMacAddr bssId; +} tCsrRoamJoinStatus; + +typedef struct tagCsrOsChannelMask { + uint8_t numChannels; + bool scanEnabled[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint8_t channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; +} tCsrOsChannelMask; + +typedef struct tagCsrVotes11d { + uint8_t votes; + uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; +} tCsrVotes11d; + +typedef struct tagCsrScanStruct { + tScanProfile scanProfile; + tDblLinkList scanResultList; + tDblLinkList tempScanResults; + bool fScanEnable; + bool fFullScanIssued; +#ifdef WLAN_AP_STA_CONCURRENCY + cdf_mc_timer_t hTimerStaApConcTimer; +#endif + cdf_mc_timer_t hTimerIdleScan; + cdf_mc_timer_t hTimerResultCfgAging; + /* + * changes on every scan, it is used as a flag for whether 11d info is + * found on every scan + */ + uint8_t channelOf11dInfo; + uint8_t scanResultCfgAgingTime; + tSirScanType curScanType; + tCsrChannel channels11d; + tChannelListWithPower defaultPowerTable[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + tChannelListWithPower + defaultPowerTable40MHz[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint32_t numChannelsDefault; + tCsrChannel base_channels; /* The channel base to work on */ + tCsrChannel base40MHzChannels; /* center channels for 40MHz channels */ + tDblLinkList channelPowerInfoList24; + tDblLinkList channelPowerInfoList5G; + uint32_t nLastAgeTimeOut; + uint32_t nAgingCountDown; + uint8_t countryCodeDefault[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t countryCodeCurrent[WNI_CFG_COUNTRY_CODE_LEN]; + uint8_t countryCode11d[WNI_CFG_COUNTRY_CODE_LEN]; + v_REGDOMAIN_t domainIdDefault; /* default regulatory domain */ + v_REGDOMAIN_t domainIdCurrent; /* current regulatory domain */ + + /* Bssid for current country code */ + struct cdf_mac_addr currentCountryBssid; + + int8_t currentCountryRSSI; /* RSSI for current country code */ + bool fCancelIdleScan; + uint8_t countryCodeCount; + /* counts for various advertized country codes */ + tCsrVotes11d votes11d[CSR_MAX_NUM_COUNTRY_CODE]; + /* + * in 11d IE from probe rsp or beacons of neighboring APs + * will use the most popular one (max count) + */ + uint8_t countryCodeElected[WNI_CFG_COUNTRY_CODE_LEN]; + bool fRestartIdleScan; + uint32_t nIdleScanTimeGap; + /* keep a track of channels to be scnned while in traffic condition */ + tCsrOsChannelMask osScanChannelMask; + uint16_t 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. + */ + bool 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 + */ + bool 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) + */ + uint8_t fEnableDFSChnlScan; + /* + * To enable/disable scanning only 2.4Ghz channels on first scan + */ + bool fFirstScanOnly2GChnl; + bool 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]; + int8_t inScanResultBestAPRssi; + csr_scan_completeCallback callback11dScanDone; + bool fcc_constraint; + uint8_t max_scan_count; +} tCsrScanStruct; + +/* + * Save the connected information. This structure + connectedProfile + * should contain all information about the connection + */ +typedef struct tagRoamCsrConnectedInfo { + uint32_t nBeaconLength; + uint32_t nAssocReqLength; + uint32_t nAssocRspLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + /* len of the parsed RIC resp IEs received in reassoc response */ + uint32_t nRICRspLength; +#endif +#ifdef FEATURE_WLAN_ESE + uint32_t nTspecIeLength; +#endif + /* + * 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. + */ + uint8_t *pbFrames; + uint8_t staId; +} tCsrRoamConnectedInfo; + +typedef struct tagCsrLinkQualityIndInfo { + csr_roamLinkQualityIndCallback callback; + void *context; +} tCsrLinkQualityIndInfo; + +typedef struct tagCsrPeStatsReqInfo { + tListElem link; /* list links */ + uint32_t statsMask; + uint32_t periodicity; + bool rspPending; + cdf_mc_timer_t hPeStatsTimer; + bool timerRunning; + uint8_t staId; + uint8_t numClient; + tpAniSirGlobal pMac; + /* To remember if the peStats timer is stopped successfully or not */ + bool timerStopFailed; + uint8_t sessionId; + +} tCsrPeStatsReqInfo; + +typedef struct tagCsrStatsClientReqInfo { + tListElem link; /* list links */ + eCsrStatsRequesterType requesterId; + tCsrStatsCallback callback; + uint32_t periodicity; + void *pContext; + uint32_t statsMask; + tCsrPeStatsReqInfo *pPeStaEntry; + uint8_t staId; + cdf_mc_timer_t timer; + bool timerExpired; + tpAniSirGlobal pMac; /* TODO: Confirm this change BTAMP */ + uint8_t sessionId; +} tCsrStatsClientReqInfo; + +typedef struct tagCsrTlStatsReqInfo { + uint32_t periodicity; + bool timerRunning; + cdf_mc_timer_t hTlStatsTimer; + uint8_t 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 { + uint8_t roamedVdevId; /* vdevId after roaming */ + int8_t txMgmtPower; /* HAL fills in the tx power used for */ + uint8_t rssi; /* RSSI */ + uint8_t roamReason; /* Roam reason */ + uint8_t nss; /* no of spatial streams */ + uint16_t chainMask; /* chainmask */ + uint16_t smpsMode; /* smps.mode */ + tSirMacAddr bssid; /* MAC address of roamed AP */ + bool bRoamSynchInProgress; /* a roam offload synch */ + tCsrRoamOffloadAuthStatus authStatus; /* auth status */ + uint8_t kck[SIR_KCK_KEY_LEN]; + uint8_t kek[SIR_KEK_KEY_LEN]; + uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; + tpSirBssDescription bss_desc_ptr; /*BSS descriptor*/ +} csr_roam_offload_synch_params; +#endif + +struct csr_roam_stored_profile { + uint32_t session_id; + tCsrRoamProfile profile; + tScanResultHandle bsslist_handle; + eCsrRoamReason reason; + uint32_t roam_id; + bool imediate_flag; + bool clear_flag; +}; + +typedef struct tagCsrRoamSession { + uint8_t sessionId; /* Session ID */ + bool sessionActive; /* true if it is used */ + + /* For BT-AMP station, this serve as BSSID for self-BSS. */ + struct cdf_mac_addr selfMacAddr; + + csr_roam_completeCallback callback; + void *pContext; + eCsrConnectState connectState; + tCsrRoamConnectedProfile connectedProfile; + tCsrRoamConnectedInfo connectedInfo; + tCsrRoamProfile *pCurRoamProfile; + tSirBssDescription *pConnectBssDesc; + uint16_t NumPmkidCache; /* valid number of pmkid in the cache*/ + uint16_t curr_cache_idx; /* the index in pmkidcache to write next to */ + tPmkidCacheInfo PmkidCacheInfo[CSR_MAX_PMKID_ALLOWED]; + uint8_t 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 alloc memory all time + */ + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + int32_t sPendingCommands; /* 0 means CSR is ok to low power */ +#ifdef FEATURE_WLAN_WAPI + uint16_t NumBkidCache; + tBkidCacheInfo BkidCacheInfo[CSR_MAX_BKID_ALLOWED]; +#endif /* FEATURE_WLAN_WAPI */ + /* + * indicate whether CSR is roaming + * (either via lostlink or dynamic roaming) + */ + bool fRoaming; + /* + * to remember some parameters needed for START_BSS. + * All member must be set every time we try to join or start an IBSS + */ + tCsrRoamStartBssParams bssParams; + /* the byte count of pWpaRsnIE; */ + uint32_t nWpaRsnReqIeLength; + /* contain the WPA/RSN IE in assoc req or one sent in beacon(IBSS) */ + uint8_t *pWpaRsnReqIE; + /* the byte count for pWpaRsnRspIE */ + uint32_t nWpaRsnRspIeLength; + /* this contain the WPA/RSN IE in beacon/probe rsp */ + uint8_t *pWpaRsnRspIE; +#ifdef FEATURE_WLAN_WAPI + /* the byte count of pWapiReqIE; */ + uint32_t nWapiReqIeLength; + /* this contain the WAPI IE in assoc req or one sent in beacon (IBSS) */ + uint8_t *pWapiReqIE; + /* the byte count for pWapiRspIE */ + uint32_t nWapiRspIeLength; + /* this contain the WAPI IE in beacon/probe rsp */ + uint8_t *pWapiRspIE; +#endif /* FEATURE_WLAN_WAPI */ + uint32_t nAddIEScanLength; /* the byte count of pAddIeScanIE; */ + /* contains the additional IE in (unicast) probe req at time of join */ + uint8_t *pAddIEScan; + uint32_t nAddIEAssocLength; /* the byte count for pAddIeAssocIE */ + uint8_t *pAddIEAssoc; + uint32_t roamingStartTime; /* in units of 10ms */ + tCsrTimerInfo roamingTimerInfo; + eCsrRoamingReason roamingReason; + bool fCancelRoaming; + cdf_mc_timer_t hTimerRoaming; + /* the roamResult that is used when the roaming timer fires */ + eCsrRoamResult roamResult; + /* This is the reason code for join(assoc) failure */ + tCsrRoamJoinStatus joinFailStatusCode; + /* status from PE for deauth/disassoc(lostlink) or our own dyn roam */ + uint32_t roamingStatusCode; + uint16_t NumPmkidCandidate; + tPmkidCandidateInfo PmkidCandidateInfo[CSR_MAX_PMKID_ALLOWED]; +#ifdef FEATURE_WLAN_WAPI + uint16_t NumBkidCandidate; + tBkidCandidateInfo BkidCandidateInfo[CSR_MAX_BKID_ALLOWED]; +#endif + bool fWMMConnection; + bool fQOSConnection; +#ifdef FEATURE_WLAN_ESE + tCsrEseCckmInfo eseCckmInfo; + bool isPrevApInfoValid; + tSirMacSSid prevApSSID; + struct cdf_mac_addr prevApBssid; + uint8_t prevOpChannel; + uint16_t clientDissSecs; + uint32_t roamTS1; +#if defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrEseCckmIe suppCckmIeInfo; +#endif +#endif + uint8_t bRefAssocStartCnt; /* Tracking assoc start indication */ + tSirHTConfig htConfig; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pnoStarted; +#endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + csr_roam_offload_synch_params roamOffloadSynchParams; + uint8_t psk_pmk[SIR_ROAM_SCAN_PSK_SIZE]; + size_t pmk_len; + uint8_t RoamKeyMgmtOffloadEnabled; +#endif +#if defined WLAN_FEATURE_VOWIFI_11R + tftSMEContext ftSmeContext; +#endif + /* This count represents the number of bssid's we try to join. */ + uint8_t join_bssid_count; + struct csr_roam_stored_profile stored_roam_profile; +} tCsrRoamSession; + +typedef struct tagCsrRoamStruct { + uint32_t nextRoamId; + tDblLinkList roamCmdPendingList; + tDblLinkList channelList5G; + tDblLinkList channelList24; + tCsrConfig configParam; + uint32_t numChannelsEeprom; /* total channels of eeprom */ + tCsrChannel baseChannels; /* 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 alloc mem all time + */ + tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint32_t numValidChannels; /* total number of channels in CFG */ + int32_t sPendingCommands; + cdf_mc_timer_t hTimerWaitForKey; /* support timeout for WaitForKey */ + 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 g_cds_context; /* used for interaction with TL */ + tCsrTimerInfo WaitForKeyTimerInfo; + tCsrRoamSession *roamSession; + uint32_t transactionId; /* Current transaction ID for internal use. */ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tCsrNeighborRoamControlInfo neighborRoamInfo[CSR_ROAM_SESSION_MAX]; +#endif +#ifdef FEATURE_WLAN_LFR + uint8_t isFastRoamIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + uint8_t isEseIniFeatureEnabled; +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) \ + || defined(FEATURE_WLAN_LFR) + uint8_t RoamRssiDiff; + bool isWESModeEnabled; +#endif + uint32_t deauthRspStatus; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t *pReassocResp; /* reassociation response from new AP */ + uint16_t 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_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 + +#define CSR_IS_PHY_MODE_11n(phy_mode) \ + ((eCSR_DOT11_MODE_11n == phy_mode) || \ + (eCSR_DOT11_MODE_11n_ONLY == phy_mode) || \ + (eCSR_DOT11_MODE_11ac == phy_mode) || \ + (eCSR_DOT11_MODE_11ac_ONLY == phy_mode)) + +#define CSR_IS_PHY_MODE_11ac(phy_mode) \ + ((eCSR_DOT11_MODE_11ac == phy_mode) || \ + (eCSR_DOT11_MODE_11ac_ONLY == phy_mode)) +/* + * 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_GET_BAND(ch_num) \ + ((CDS_IS_CHANNEL_24GHZ(ch_num)) ? eCSR_BAND_24 : eCSR_BAND_5G) +#define CSR_IS_11D_INFO_FOUND(pMac) \ + (0 != (pMac)->scan.channelOf11dInfo) +#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) +#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)) + +CDF_STATUS csr_get_channel_and_power_list(tpAniSirGlobal pMac); +CDF_STATUS csrScanFilter11dResult(tpAniSirGlobal pMac); + +CDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac); + +CDF_STATUS csr_set_modify_profile_fields(tpAniSirGlobal pMac, + uint32_t sessionId, tCsrRoamModifyProfileFields * + pModifyProfileFields); +CDF_STATUS csr_get_modify_profile_fields(tpAniSirGlobal pMac, + uint32_t sessionId, tCsrRoamModifyProfileFields * + pModifyProfileFields); +void csr_set_global_cfgs(tpAniSirGlobal pMac); +void csr_set_default_dot11_mode(tpAniSirGlobal pMac); +void csrScanSetChannelMask(tpAniSirGlobal pMac, tCsrChannelInfo *pChannelInfo); +bool csr_is_conn_state_disconnected(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_connected_ibss(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_disconnected_ibss(tpAniSirGlobal pMac, + uint32_t sessionId); +bool csr_is_conn_state_connected_infra(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_connected(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_infra(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_ibss(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_wds(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_connected_wds(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_conn_state_disconnected_wds(tpAniSirGlobal pMac, + uint32_t sessionId); +bool csr_is_any_session_in_connect_state(tpAniSirGlobal pMac); +bool csr_is_all_session_disconnected(tpAniSirGlobal pMac); +bool csr_is_sta_session_connected(tpAniSirGlobal pMac); +bool csr_is_p2p_session_connected(tpAniSirGlobal pMac); +bool csr_is_any_session_connected(tpAniSirGlobal pMac); +bool csr_is_infra_connected(tpAniSirGlobal pMac); +bool csr_is_concurrent_infra_connected(tpAniSirGlobal pMac); +bool csr_is_concurrent_session_running(tpAniSirGlobal pMac); +bool csr_is_infra_ap_started(tpAniSirGlobal pMac); +bool csr_is_ibss_started(tpAniSirGlobal pMac); +bool csr_is_btamp_started(tpAniSirGlobal pMac); +bool csr_is_btamp(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_valid_mc_concurrent_session(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc); +bool csr_is_conn_state_connected_infra_ap(tpAniSirGlobal pMac, + uint32_t sessionId); +CDF_STATUS csr_get_statistics(tpAniSirGlobal pMac, + eCsrStatsRequesterType requesterId, + uint32_t statsMask, tCsrStatsCallback callback, + uint32_t periodicity, bool cache, uint8_t staId, + void *pContext, uint8_t sessionId); +CDF_STATUS csr_get_rssi(tpAniSirGlobal pMac, tCsrRssiCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, int8_t lastRSSI, + void *pContext, void *p_cds_context); +CDF_STATUS csr_get_snr(tpAniSirGlobal pMac, tCsrSnrCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, void *pContext); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS csr_get_tsm_stats(tpAniSirGlobal pMac, + tCsrTsmStatsCallback callback, + uint8_t staId, + struct cdf_mac_addr bssId, + void *pContext, void *p_cds_context, uint8_t tid); +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam); +CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, + tCsrConfigParam *pParam); +CDF_STATUS csr_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf); +CDF_STATUS csr_open(tpAniSirGlobal pMac); +CDF_STATUS csr_init_chan_list(tpAniSirGlobal mac, uint8_t *alpha2); +CDF_STATUS csr_close(tpAniSirGlobal pMac); +CDF_STATUS csr_start(tpAniSirGlobal pMac); +CDF_STATUS csr_stop(tpAniSirGlobal pMac, tHalStopType stopType); +CDF_STATUS csr_ready(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_WAPI +CDF_STATUS csr_scan_get_bkid_candidate_list(tpAniSirGlobal pMac, + uint32_t sessionId, tBkidCandidateInfo * pBkidList, + uint32_t *pNumItems); +CDF_STATUS csr_roam_get_wapi_req_ie(tpAniSirGlobal pMac, + uint32_t sessionId, uint32_t *pLen, uint8_t *pBuf); +CDF_STATUS csr_roam_get_wapi_rsp_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf); +uint8_t csr_construct_wapi_ie(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe); +#endif /* FEATURE_WLAN_WAPI */ + +CDF_STATUS csr_roam_update_apwpsie(tpAniSirGlobal pMac, uint32_t sessionId, + tSirAPWPSIEs * pAPWPSIES); +CDF_STATUS csr_roam_update_wparsni_es(tpAniSirGlobal pMac, uint32_t sessionId, + tSirRSNie *pAPSirRSNie); +void csr_set_cfg_privacy(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + bool fPrivacy); +int8_t csr_get_infra_session_id(tpAniSirGlobal pMac); +uint8_t csr_get_infra_operation_channel(tpAniSirGlobal pMac, uint8_t sessionId); +bool csr_is_session_client_and_connected(tpAniSirGlobal pMac, + uint8_t sessionId); +uint8_t csr_get_concurrent_operation_channel(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal pMac, + uint16_t sap_ch, eCsrPhyMode sap_phymode, + uint8_t cc_switch_mode); +#endif +CDF_STATUS csr_roam_copy_connect_profile(tpAniSirGlobal pMac, + uint32_t sessionId, tCsrRoamConnectedProfile *pProfile); +bool csr_is_set_key_allowed(tpAniSirGlobal pMac, uint32_t sessionId); + +void csr_set_opposite_band_channel_info(tpAniSirGlobal pMac); +#ifdef FEATURE_WLAN_SCAN_PNO +CDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd * + pPrefNetworkFoundInd); +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* Returns whether the current association is a 11r assoc or not */ +bool csr_roam_is11r_assoc(tpAniSirGlobal pMac, uint8_t sessionId); +#endif + +#ifdef FEATURE_WLAN_ESE +/* Returns whether the current association is a ESE assoc or not */ +bool csr_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId); +bool csr_roam_is_ese_ini_feature_enabled(tpAniSirGlobal pMac); +bool csr_neighbor_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId); +#endif + +/* Remove this code once SLM_Sessionization is supported */ +void csr_disconnect_all_active_sessions(tpAniSirGlobal pMac); + +#ifdef FEATURE_WLAN_LFR +/* Returns whether "Legacy Fast Roaming" is enabled...or not */ +bool csr_roam_is_fast_roam_enabled(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_roam_is_roam_offload_scan_enabled(tpAniSirGlobal pMac); +bool csr_is_channel_present_in_list(uint8_t *pChannelList, int numChannels, + uint8_t channel); +CDF_STATUS csr_add_to_channel_list_front(uint8_t *pChannelList, int numChannels, + uint8_t channel); +CDF_STATUS csr_roam_offload_scan_rsp_hdlr(tpAniSirGlobal pMac, + tpSirRoamOffloadScanRsp scanOffloadRsp); +CDF_STATUS csr_handoff_request(tpAniSirGlobal pMac, uint8_t sessionId, + tCsrHandoffRequest *pHandoffInfo); +bool csr_roam_is_sta_mode(tpAniSirGlobal pMac, uint32_t sessionId); +#endif + +/* Post Channel Change Indication */ +CDF_STATUS csr_roam_channel_change_req(tpAniSirGlobal pMac, + struct cdf_mac_addr bssid, uint8_t cb_mode, + tCsrRoamProfile *profile); + +/* Post Beacon Tx Start Indication */ +CDF_STATUS csr_roam_start_beacon_req(tpAniSirGlobal pMac, + struct cdf_mac_addr bssid, uint8_t dfsCacWaitStatus); + +CDF_STATUS +csr_roam_send_chan_sw_ie_request(tpAniSirGlobal pMac, struct cdf_mac_addr bssid, + uint8_t targetChannel, uint8_t csaIeReqd, uint8_t ch_bandwidth); +CDF_STATUS +csr_roam_modify_add_ies(tpAniSirGlobal pMac, + tSirModifyIE *pModifyIE, eUpdateIEsType updateType); +CDF_STATUS +csr_roam_update_add_ies(tpAniSirGlobal pMac, + tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void csr_process_roam_offload_synch_ind(tHalHandle hHal, + roam_offload_synch_ind * roam_synch_ind_ptr); +CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac, + roam_offload_synch_ind *roam_synch_ind_ptr); +void csr_process_ho_fail_ind(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, + uint32_t session_id); +CDF_STATUS 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 +CDF_STATUS csr_get_channels_and_power(tpAniSirGlobal pMac); + +/* csr_scan_process_single_bssdescr() - Add a bssdescriptor to scan table + * + * @mac_ctx - MAC context + * @bssdescr - Pointer to BSS description structure that contains + * everything from beacon/probe response frame and additional + * information. + * @scan_id - Scan identifier of the scan request that was running + * when this beacon was received. Reserved for future when + * firmware provides that information. + * @flags - Reserved for future use. + * + * Callback routine called by LIM when it receives a beacon or probe response + * from the device. 802.11 frame is already converted to internal + * tSirBssDescription data structure. + * + * Return: 0 or other error codes. + */ + +CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDescription, + uint32_t scan_id, uint32_t flags); + +#endif diff --git a/core/sme/inc/csr_link_list.h b/core/sme/inc/csr_link_list.h new file mode 100644 index 000000000000..11462468313b --- /dev/null +++ b/core/sme/inc/csr_link_list.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. + */ + +/** + * \file csr_link_list.h + * + * Exports and types for the Common link list interfaces. + */ + +#ifndef CSR_LINK_LIST_H__ +#define CSR_LINK_LIST_H__ + +#include "cdf_lock.h" +#include "cdf_mc_timer.h" +#include "cds_api.h" +#include "sir_types.h" + +#define LL_ACCESS_LOCK true +#define LL_ACCESS_NOLOCK 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; + cdf_mutex_t Lock; + uint32_t Count; + tHddHandle hHdd; + tListFlag Flag; + /*command debugging */ + uint32_t cmdTimeoutDuration; /* command timeout duration */ + cdf_mc_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 *)( \ + (uint8_t *)(address) - \ + (uint8_t *)(&((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)) + +uint32_t csr_ll_count(tDblLinkList *pList); +CDF_STATUS csr_ll_open(tHddHandle hHdd, tDblLinkList *pList); +void csr_ll_close(tDblLinkList *pList); +void csr_ll_lock(tDblLinkList *pList); +void csr_ll_unlock(tDblLinkList *pList); +bool csr_ll_is_list_empty(tDblLinkList *pList, bool fInterlocked); +void csr_ll_insert_head(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked); +void csr_ll_insert_tail(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked); +/* This function put pNewEntry before pEntry. Caller should have found pEntry */ +void csr_ll_insert_entry(tDblLinkList *pList, tListElem *pEntry, + tListElem *pNewEntry, bool fInterlocked); +tListElem *csr_ll_peek_head(tDblLinkList *pList, bool fInterlocked); +tListElem *csr_ll_peek_tail(tDblLinkList *pList, bool fInterlocked); +tListElem *csr_ll_remove_head(tDblLinkList *pList, bool fInterlocked); +tListElem *csr_ll_remove_tail(tDblLinkList *pList, bool fInterlocked); +bool csr_ll_remove_entry(tDblLinkList *pList, tListElem *pEntryToRemove, + bool fInterlocked); +void csr_ll_purge(tDblLinkList *pList, bool fInterlocked); +/* csr_ll_next return NULL if reaching the end or list is empty */ +tListElem *csr_ll_next(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked); +tListElem *csr_ll_previous(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked); +bool csr_ll_find_entry(tDblLinkList *pList, tListElem *pEntryToFind); +#endif diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h new file mode 100644 index 000000000000..6bf27d01a963 --- /dev/null +++ b/core/sme/inc/csr_neighbor_roam.h @@ -0,0 +1,311 @@ +/* + * 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 csr_neighbor_roam.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_REASSOCIATING, +#ifdef WLAN_FEATURE_VOWIFI_11R + 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 { + uint8_t maxNeighborRetries; + uint32_t neighborScanPeriod; + tCsrChannelInfo channelInfo; + uint8_t neighborLookupThreshold; + uint8_t neighborReassocThreshold; + uint32_t minChannelScanTime; + uint32_t maxChannelScanTime; + uint16_t neighborResultsRefreshPeriod; + uint16_t emptyScanRefreshPeriod; + uint8_t nOpportunisticThresholdDiff; + uint8_t nRoamRescanRssiDiff; + uint8_t nRoamBmissFirstBcnt; + uint8_t nRoamBmissFinalBcnt; + uint8_t nRoamBeaconRssiWeight; + uint8_t 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 { + /* Flag to mark reception of IAPP Neighbor list */ + bool IAPPNeighborListReceived; + /* Current channel index that is being scanned */ + uint8_t currentChanIndex; + /* Max number of channels in channel list and the list of channels */ + tCsrChannelInfo currentChannelListInfo; +} tCsrNeighborRoamChannelInfo, *tpCsrNeighborRoamChannelInfo; + +typedef struct sCsrNeighborRoamBSSInfo { + tListElem List; + uint8_t apPreferenceVal; + 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 */ +/* Max number of MAC addresses with which the pre-auth was failed */ +#define MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS 10 +#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 Preauth was failed */ +typedef struct sCsrPreauthFailListInfo { + uint8_t numMACAddress; + tSirMacAddr macAddress[MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS]; +} tCsrPreauthFailListInfo, *tpCsrPreauthFailListInfo; + +typedef struct sCsrNeighborReportBssInfo { + uint8_t channelNum; + uint8_t neighborScore; + tSirMacAddr neighborBssId; +} tCsrNeighborReportBssInfo, *tpCsrNeighborReportBssInfo; + +typedef struct sCsr11rAssocNeighborInfo { + bool preauthRspPending; + bool neighborRptPending; + uint8_t currentNeighborRptRetryNum; + tCsrPreauthFailListInfo preAuthFailList; + uint32_t neighborReportTimeout; + uint32_t PEPreauthRespTimeout; + uint8_t numPreAuthRetries; + tDblLinkList preAuthDoneList; /* llist which consists/preauth nodes */ + uint8_t numBssFromNeighborReport; + /* Contains info needed during REPORT_SCAN State */ + tCsrNeighborReportBssInfo neighboReportBssInfo[MAX_BSS_IN_NEIGHBOR_RPT]; +} tCsr11rAssocNeighborInfo, *tpCsr11rAssocNeighborInfo; +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#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; + struct cdf_mac_addr currAPbssid; /* current assoc AP */ + uint8_t currAPoperationChannel; /* current assoc AP */ + tCsrNeighborRoamChannelInfo roamChannelInfo; + uint8_t currentNeighborLookupThreshold; + uint8_t currentOpportunisticThresholdDiff; + uint8_t currentRoamRescanRssiDiff; + tDblLinkList roamableAPList; /* List of current FT candidates */ + tCsrRoamProfile csrNeighborRoamProfile; +#ifdef WLAN_FEATURE_VOWIFI_11R + bool is11rAssoc; + tCsr11rAssocNeighborInfo FTRoamInfo; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + bool isESEAssoc; + bool isVOAdmitted; + uint16_t MinQBssLoadRequired; +#endif +#ifdef FEATURE_WLAN_LFR + /* + * Previous connected profile. + * If the new profile does not match previous we re-initialize + * occupied channel list + */ + tCsrRoamConnectedProfile prevConnProfile; + /* upper layer requested a reassoc */ + uint8_t uOsRequestedHandoff; + /* handoff related info came with upper layer's req for reassoc */ + tCsrHandoffRequest handoffReqInfo; +#endif + uint8_t currentRoamBmissFirstBcnt; + uint8_t currentRoamBmissFinalBcnt; + uint8_t currentRoamBeaconRssiWeight; + uint8_t last_sent_cmd; +} tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo; + +/* All the necessary Function declarations are here */ +CDF_STATUS csr_neighbor_roam_indicate_connect(tpAniSirGlobal pMac, + uint8_t sessionId, CDF_STATUS status); +CDF_STATUS csr_neighbor_roam_indicate_disconnect(tpAniSirGlobal pMac, + uint8_t sessionId); +bool csr_neighbor_roam_is_handoff_in_progress(tpAniSirGlobal pMac, + uint8_t sessionId); +void csr_neighbor_roam_request_handoff(tpAniSirGlobal pMac, uint8_t sessionId); +CDF_STATUS csr_neighbor_roam_init(tpAniSirGlobal pMac, uint8_t sessionId); +void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId); +void csr_neighbor_roam_purge_preauth_failed_list(tpAniSirGlobal pMac); +CDF_STATUS csr_neighbor_roam_transit_to_cfg_chan_scan(tpAniSirGlobal pMac, + uint8_t sessionId); +CDF_STATUS csrNeighborRoamTransitionToPreauthDone(tpAniSirGlobal pMac); +CDF_STATUS csr_neighbor_roam_prepare_scan_profile_filter(tpAniSirGlobal pMac, + tCsrScanResultFilter *pScanFilter, uint8_t sessionId); +bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo pHandoffNode, uint8_t sessionId); +CDF_STATUS csr_neighbor_roam_preauth_rsp_handler(tpAniSirGlobal pMac, + uint8_t sessionId, tSirRetStatus limStatus); +#ifdef WLAN_FEATURE_VOWIFI_11R +bool csr_neighbor_roam_is11r_assoc(tpAniSirGlobal pMac, uint8_t sessionId); +#endif +CDF_STATUS csr_neighbor_roam_create_chan_list_from_neighbor_report( + tpAniSirGlobal pMac, uint8_t sessionId); +void csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + tpAniSirGlobal pMac, uint8_t sessionId); +bool csr_neighbor_roam_state_preauth_done(tpAniSirGlobal pMac, + uint8_t sessionId); +bool csr_neighbor_middle_of_roaming(tpAniSirGlobal pMac, uint8_t sessionId); +CDF_STATUS csr_neighbor_roam_set_lookup_rssi_threshold(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t neighborLookupRssiThreshold); +CDF_STATUS csr_neighbor_roam_set_opportunistic_scan_threshold_diff( + tpAniSirGlobal pMac, uint8_t sessionId, + uint8_t nOpportunisticThresholdDiff); +CDF_STATUS csr_neighbor_roam_set_roam_rescan_rssi_diff(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t nRoamRescanRssiDiff); +CDF_STATUS csr_neighbor_roam_set_roam_bmiss_first_bcnt(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t nRoamBmissFirstBcnt); +CDF_STATUS csr_neighbor_roam_set_roam_bmiss_final_bcnt(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t nRoamBmissFinalBcnt); +CDF_STATUS csr_neighbor_roam_set_roam_beacon_rssi_weight(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t nRoamBeaconRssiWeight); +CDF_STATUS csr_neighbor_roam_update_fast_roaming_enabled(tpAniSirGlobal pMac, + uint8_t sessionId, const bool fastRoamEnabled); +CDF_STATUS csr_neighbor_roam_update_ese_mode_enabled(tpAniSirGlobal pMac, + uint8_t sessionId, const bool eseMode); +CDF_STATUS csr_neighbor_roam_channels_filter_by_current_band( + tpAniSirGlobal pMac, uint8_t sessionId, + uint8_t *pInputChannelList, + uint8_t inputNumOfChannels, + uint8_t *pOutputChannelList, + uint8_t *pMergedOutputNumOfChannels); +CDF_STATUS csr_neighbor_roam_merge_channel_lists(tpAniSirGlobal pMac, + uint8_t *pInputChannelList, + uint8_t inputNumOfChannels, + uint8_t *pOutputChannelList, + uint8_t outputNumOfChannels, + uint8_t *pMergedOutputNumOfChannels); +void csr_roam_reset_roam_params(tpAniSirGlobal mac_ptr); +#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 + +CDF_STATUS csr_roam_offload_scan(tpAniSirGlobal pMac, uint8_t sessionId, + uint8_t command, uint8_t reason); +CDF_STATUS csr_neighbor_roam_candidate_found_ind_hdlr(tpAniSirGlobal pMac, + void *pMsg); +CDF_STATUS csr_neighbor_roam_handoff_req_hdlr(tpAniSirGlobal pMac, void *pMsg); +CDF_STATUS csr_neighbor_roam_proceed_with_handoff_req(tpAniSirGlobal pMac, + uint8_t sessionId); +CDF_STATUS csr_neighbor_roam_sssid_scan_done(tpAniSirGlobal pMac, + uint8_t sessionId, CDF_STATUS status); +CDF_STATUS csr_neighbor_roam_start_lfr_scan(tpAniSirGlobal pMac, + uint8_t sessionId); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS csr_set_cckm_ie(tpAniSirGlobal pMac, const uint8_t sessionId, + const uint8_t *pCckmIe, const uint8_t ccKmIeLen); +CDF_STATUS csr_roam_read_tsf(tpAniSirGlobal pMac, uint8_t *pTimestamp, + const uint8_t sessionId); +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, + uint8_t sessionId); +CDF_STATUS csr_neighbor_roam_offload_update_preauth_list(tpAniSirGlobal pMac, + roam_offload_synch_ind *roam_synch_ind_ptr, uint8_t sessionId); +#endif +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ +#endif /* CSR_NEIGHBOR_ROAM_H */ diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h new file mode 100644 index 000000000000..c484e6ec67b0 --- /dev/null +++ b/core/sme/inc/csr_support.h @@ -0,0 +1,378 @@ +/* + * 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 csr_support.h + * + * Exports and types for the Common Scan and Roaming supporting interfaces. + */ +#ifndef CSR_SUPPORT_H__ +#define CSR_SUPPORT_H__ + +#include "csr_link_list.h" +#include "csr_api.h" +#include "cds_reg_service.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) +/* minimum size of the IE->length is the size of the Oui + Version. */ +#define CSR_WPA_IE_MIN_SIZE (6) +#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 +/* max idx, should be last & highest */ +#define CSR_OUI_WAPI_WAI_MAX_INDEX 0x03 +#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; + +/* Generic Information Element Structure */ +typedef struct sDot11IEHeader { + uint8_t ElementID; + uint8_t Length; +} cdf_packed tDot11IEHeader; + +typedef struct tagCsrWpaIe { + tDot11IEHeader IeHeader; + uint8_t Oui[CSR_WPA_OUI_SIZE]; + uint16_t Version; + uint8_t MulticastOui[CSR_WPA_OUI_SIZE]; + uint16_t cUnicastCyphers; + struct { + uint8_t Oui[CSR_WPA_OUI_SIZE]; + } cdf_packed UnicastOui[1]; +} cdf_packed tCsrWpaIe; + +typedef struct tagCsrWpaAuthIe { + uint16_t cAuthenticationSuites; + struct { + uint8_t Oui[CSR_WPA_OUI_SIZE]; + } cdf_packed AuthOui[1]; +} cdf_packed tCsrWpaAuthIe; + +typedef struct tagCsrRSNIe { + tDot11IEHeader IeHeader; + uint16_t Version; + uint8_t MulticastOui[CSR_RSN_OUI_SIZE]; + uint16_t cUnicastCyphers; + struct { + uint8_t Oui[CSR_RSN_OUI_SIZE]; + } cdf_packed UnicastOui[1]; +} cdf_packed tCsrRSNIe; + +typedef struct tagCsrRSNAuthIe { + uint16_t cAuthenticationSuites; + struct { + uint8_t Oui[CSR_RSN_OUI_SIZE]; + } cdf_packed AuthOui[1]; +} cdf_packed tCsrRSNAuthIe; + +typedef struct tagCsrRSNCapabilities { + uint16_t PreAuthSupported:1; + uint16_t NoPairwise:1; + uint16_t PTKSAReplayCounter:2; + uint16_t GTKSAReplayCounter:2; + uint16_t MFPRequired:1; + uint16_t MFPCapable:1; + uint16_t Reserved:8; +} cdf_packed tCsrRSNCapabilities; + +typedef struct tagCsrRSNPMKIe { + uint16_t cPMKIDs; + struct { + uint8_t PMKID[CSR_RSN_PMKID_SIZE]; + } cdf_packed PMKIDList[1]; +} cdf_packed tCsrRSNPMKIe; + +typedef struct tCsrIELenInfo { + uint8_t min; + uint8_t max; +} cdf_packed tCsrIELenInfo; + +#ifdef FEATURE_WLAN_WAPI +typedef struct tagCsrWapiIe { + tDot11IEHeader IeHeader; + uint16_t Version; + uint16_t cAuthenticationSuites; + struct { + uint8_t Oui[CSR_WAPI_OUI_SIZE]; + } cdf_packed AuthOui[1]; + uint16_t cUnicastCyphers; + struct { + uint8_t Oui[CSR_WAPI_OUI_SIZE]; + } cdf_packed UnicastOui[1]; + uint8_t MulticastOui[CSR_WAPI_OUI_SIZE]; + struct { + uint16_t PreAuthSupported:1; + uint16_t Reserved:15; + } cdf_packed tCsrWapiCapabilities; +} cdf_packed tCsrWapiIe; +#endif /* FEATURE_WLAN_WAPI */ + +typedef struct tagRoamingTimerInfo { + tpAniSirGlobal pMac; + uint8_t 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 len needed of Tlv with with len bytes of data */ +#define GET_TLV_MSG_LEN(len) \ + GET_ROUND_UP((sizeof(tCsrCfgMsgTlvHdr) + (len)), sizeof(uint32_t)) + +bool csr_get_bss_id_bss_desc(tHalHandle hHal, tSirBssDescription *pSirBssDesc, + struct cdf_mac_addr *pBssId); +bool csr_is_bss_id_equal(tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2); +eCsrMediaAccessType csr_get_qo_s_from_bss_desc(tHalHandle hHal, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes); +bool csr_is_nullssid(uint8_t *pBssSsid, uint8_t len); +bool csr_is_infra_bss_desc(tSirBssDescription *pSirBssDesc); +bool csr_is_ibss_bss_desc(tSirBssDescription *pSirBssDesc); +bool csr_is_privacy(tSirBssDescription *pSirBssDesc); +tSirResultCodes csr_get_disassoc_rsp_status_code(tSirSmeDisassocRsp * + pSmeDisassocRsp); +tSirResultCodes csr_get_de_auth_rsp_status_code(tSirSmeDeauthRsp *pSmeRsp); +uint32_t csr_get_frag_thresh(tHalHandle hHal); +uint32_t csr_get_rts_thresh(tHalHandle hHal); +eCsrPhyMode csr_get_phy_mode_from_bssDesc(tSirBssDescription *pSirBssDesc); +uint32_t csr_get11h_power_constraint(tHalHandle hHal, + tDot11fIEPowerConstraints *pPowerConstraint); +uint8_t csr_construct_rsn_ie(tHalHandle hHal, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe); +uint8_t csr_construct_wpa_ie(tHalHandle hHal, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe); +#ifdef FEATURE_WLAN_WAPI +bool csr_is_profile_wapi(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 + */ +uint8_t csr_retrieve_wpa_ie(tHalHandle hHal, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe); +bool csr_is_ssid_equal(tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, + tDot11fBeaconIEs *pIes2); +/* Null ssid means match */ +bool csr_is_ssid_in_list(tHalHandle hHal, tSirMacSSid *pSsid, + tCsrSSIDs *pSsidList); +bool csr_is_profile_wpa(tCsrRoamProfile *pProfile); +bool csr_is_profile_rsn(tCsrRoamProfile *pProfile); +/* + * 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 + */ +uint8_t csr_retrieve_rsn_ie(tHalHandle hHal, uint32_t 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 + */ +uint8_t csr_retrieve_wapi_ie(tHalHandle hHal, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe); +#endif /* FEATURE_WLAN_WAPI */ +bool csr_rates_is_dot11_rate11b_supported_rate(uint8_t dot11Rate); +bool csr_rates_is_dot11_rate11a_supported_rate(uint8_t dot11Rate); +tAniEdType csr_translate_encrypt_type_to_ed_type( + eCsrEncryptionType EncryptType); +/* + * pIes shall contain IEs from pSirBssDesc. + * It shall be returned from function csr_get_parsed_bss_description_ies + */ +bool csr_is_security_match(tHalHandle hHal, tCsrAuthList *authType, + tCsrEncryptionList *pUCEncryptionType, + tCsrEncryptionList *pMCEncryptionType, bool *pMFPEnabled, + uint8_t *pMFPRequired, uint8_t *pMFPCapable, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, + eCsrAuthType *negotiatedAuthtype, + eCsrEncryptionType *negotiatedUCCipher, + eCsrEncryptionType *negotiatedMCCipher); +bool csr_is_bss_type_match(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2); +bool csr_is_bss_type_ibss(eCsrRoamBssType bssType); +bool csr_is_bss_type_wds(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 + */ +bool csr_match_bss(tHalHandle hHal, tSirBssDescription *pBssDesc, + tCsrScanResultFilter *pFilter, eCsrAuthType *pNegAuth, + eCsrEncryptionType *pNegUc, eCsrEncryptionType *pNegMc, + tDot11fBeaconIEs **ppIes); +bool csr_is_bssid_match(tHalHandle hHal, struct cdf_mac_addr *pProfBssid, + struct cdf_mac_addr *BssBssid); +bool csr_match_bss_to_connect_profile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes); +void csr_add_rate_bitmap(uint8_t rate, uint16_t *pRateBitmap); +bool csr_check_rate_bitmap(uint8_t rate, uint16_t RateBitmap); +bool csr_rates_is_dot11_rate_supported(tHalHandle hHal, uint8_t rate); +uint16_t csr_rates_find_best_rate(tSirMacRateSet *pSuppRates, + tSirMacRateSet *pExtRates, tSirMacPropRateSet *pPropRates); +tSirBssType csr_translate_bsstype_to_mac_type(eCsrRoamBssType csrtype); +/* Caller allocates memory for pIEStruct */ +CDF_STATUS csr_parse_bss_description_ies(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 + */ +CDF_STATUS csr_get_parsed_bss_description_ies(tHalHandle hHal, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs **ppIEStruct); + +bool csrValidateCountryString(tHalHandle hHal, uint8_t *pCountryString); +tSirScanType csr_get_scan_type(tpAniSirGlobal pMac, uint8_t chnId); +uint8_t csr_to_upper(uint8_t ch); +CDF_STATUS csr_get_phy_mode_from_bss(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 + */ +CDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamModifyProfileFields *pModProfileFields, + uint32_t *pRoamId, bool fForce); + +CDF_STATUS csr_isconcurrentsession_valid(tpAniSirGlobal pMac, + uint32_t cursessionId, tCDF_CON_MODE currBssPersona); +/* BeaconInterval validation for MCC support */ +CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channelId, + uint16_t *beaconInterval, uint32_t cursessionId, + tCDF_CON_MODE currBssPersona); +#ifdef WLAN_FEATURE_VOWIFI_11R +bool csr_is_profile11r(tCsrRoamProfile *pProfile); +bool csr_is_auth_type11r(eCsrAuthType AuthType, uint8_t mdiePresent); +#endif +#ifdef FEATURE_WLAN_ESE +bool csr_is_auth_type_ese(eCsrAuthType AuthType); +bool csr_is_profile_ese(tCsrRoamProfile *pProfile); +#endif + +#endif diff --git a/core/sme/inc/nan_api.h b/core/sme/inc/nan_api.h new file mode 100644 index 000000000000..ee275cb3afaa --- /dev/null +++ b/core/sme/inc/nan_api.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** + * + * Name: nan_api.h + * + * Description: NAN FSM defines. + * + */ + +#ifndef __NAN_API_H__ +#define __NAN_API_H__ + +#include "cdf_types.h" +#include "cdf_types.h" + +typedef struct sNanRequestReq { + uint16_t request_data_len; + const uint8_t *request_data; +} tNanRequestReq, *tpNanRequestReq; + +typedef void (*NanCallback)(void *, tSirNanEvent *); +void sme_nan_register_callback(tHalHandle hHal, NanCallback callback); +CDF_STATUS sme_nan_request(tpNanRequestReq input); + +#endif /* __NAN_API_H__ */ diff --git a/core/sme/inc/oem_data_api.h b/core/sme/inc/oem_data_api.h new file mode 100644 index 000000000000..c7ec08c3b4f0 --- /dev/null +++ b/core/sme/inc/oem_data_api.h @@ -0,0 +1,87 @@ +/* + * 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 FEATURE_OEM_DATA_SUPPORT + +/** + * \file oem_data_api.h + * + * Exports and types for the Common OEM DATA REQ/RSP Module interfaces. + */ + +#ifndef __OEM_DATA_API_H__ +#define __OEM_DATA_API_H__ +#include "sir_api.h" +#include "sir_mac_prot_def.h" +#include "csr_link_list.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 + +/* Structure for defining req sent to the PE */ +typedef struct tagOemDataReq { + uint8_t sessionId; + uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; +} tOemDataReq, tOemDataReqConfig; + +typedef struct tagOemDataRsp { + uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; +} tOemDataRsp; + +typedef enum { + eOEM_DATA_REQ_SUCCESS = 1, + eOEM_DATA_REQ_FAILURE, + eOEM_DATA_REQ_INVALID_MODE, +} eOemDataReqStatus; +CDF_STATUS oem_data_oem_data_req_open(tHalHandle hHal); +CDF_STATUS oem_data_oem_data_req_close(tHalHandle hHal); + +/* + * HDD Callback function for the sme to callback when + * the oem data rsp is available + */ +typedef CDF_STATUS (*oem_data_oem_data_reqCompleteCallback)(tHalHandle, + void *p2, uint32_t oemDataReqID, eOemDataReqStatus status); + +CDF_STATUS oem_data_oem_data_req(tHalHandle, uint8_t, tOemDataReqConfig *, + uint32_t *pOemDataReqID, + oem_data_oem_data_reqCompleteCallback callback, + void *pContext); +CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *); +CDF_STATUS oem_data_is_oem_data_req_allowed(tHalHandle hHal); +typedef void (*sme_send_oem_data_rsp_msg)(int length, uint8_t *oem_data_rsp); +#endif /* _OEM_DATA_API_H__ */ + +#endif /* FEATURE_OEM_DATA_SUPPORT */ diff --git a/core/sme/inc/oem_data_internal.h b/core/sme/inc/oem_data_internal.h new file mode 100644 index 000000000000..bf6a63460c77 --- /dev/null +++ b/core/sme/inc/oem_data_internal.h @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * + * \file oem_data_internal.h + * + * Exports and types for the Common OEM DATA REQ/RSP Module interfaces. + */ + +#ifndef __OEM_DATA_INTERNAL_H__ +#define __OEM_DATA_INTERNAL_H__ + +#include "csr_support.h" +#include "cds_reg_service.h" +#include "oem_data_api.h" + +typedef struct tagOemDataStruct { + /* a global req id */ + uint32_t nextOemReqId; + /* indicates that currently a request has been posted and */ + bool oemDataReqActive; + /* callback function pointer for returning the response */ + oem_data_oem_data_reqCompleteCallback callback; + /* context of the original caller */ + void *pContext; + uint32_t oemDataReqID; /* original request ID */ + tOemDataReqConfig oemDataReqConfig; /* current oem data request */ + uint8_t sessionId; /* Session on which oem data req is active */ + /* callback for sending data response to oem application */ + sme_send_oem_data_rsp_msg oem_data_rsp_callback; +} tOemDataStruct; + +typedef struct tagOemDataCmd { + uint32_t oemDataReqID; + oem_data_oem_data_reqCompleteCallback callback; + void *pContext; + tOemDataReq oemDataReq; +} tOemDataCmd; +#endif /* __OEM_DATA_INTERNAL_H__ */ + +#endif /* FEATURE_OEM_DATA_SUPPORT */ diff --git a/core/sme/inc/p2p_api.h b/core/sme/inc/p2p_api.h new file mode 100644 index 000000000000..8b16507f8857 --- /dev/null +++ b/core/sme/inc/p2p_api.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/** + * + * Name: p2p_api.h + * + * Description: P2P FSM defines. + * + * + */ + +#ifndef __P2P_API_H__ +#define __P2P_API_H__ + +#include "cdf_types.h" +#include "cdf_types.h" +#include "cdf_mc_timer.h" +#include "cdf_lock.h" + +typedef struct sP2pPsConfig { + uint8_t opp_ps; + uint32_t ctWindow; + uint8_t count; + uint32_t duration; + uint32_t interval; + uint32_t single_noa_duration; + uint8_t psSelection; + uint8_t sessionid; +} tP2pPsConfig, *tpP2pPsConfig; + +typedef CDF_STATUS (*remainOnChanCallback)(tHalHandle, void *context, + CDF_STATUS status, uint32_t scan_id); + +typedef struct sRemainOnChn { + uint8_t chn; + uint32_t 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 cds_context; + tHalHandle hHal; + uint8_t sessionId; /* Session id corresponding to P2P */ + uint8_t SMEsessionId; + uint8_t probeReqForwarding; + uint8_t *probeRspIe; + uint32_t probeRspIeLength; +} tp2pContext, *tPp2pContext; + +CDF_STATUS sme_remain_on_channel(tHalHandle hHal, uint8_t sessionId, + uint8_t channel, uint32_t duration, + remainOnChanCallback callback, + void *pContext, uint8_t isP2PProbeReqAllowed, + uint32_t *scan_id); +CDF_STATUS sme_report_probe_req(tHalHandle hHal, uint8_t flag); +CDF_STATUS sme_update_p2p_ie(tHalHandle hHal, void *p2pIe, + uint32_t p2pIeLength); +CDF_STATUS sme_send_action(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBuf, uint32_t len, uint16_t wait, bool noack, + uint16_t channel_freq); +CDF_STATUS sme_cancel_remain_on_channel(tHalHandle hHal, + uint8_t sessionId, uint32_t scan_id); +CDF_STATUS sme_p2p_open(tHalHandle hHal); +CDF_STATUS p2p_stop(tHalHandle hHal); +CDF_STATUS sme_p2p_close(tHalHandle hHal); +CDF_STATUS sme_p2p_set_ps(tHalHandle hHal, tP2pPsConfig *data); +CDF_STATUS p2p_remain_on_channel(tHalHandle hHal, uint8_t sessionId, + uint8_t channel, uint32_t duration, + remainOnChanCallback callback, + void *pContext, uint8_t isP2PProbeReqAllowed, + uint32_t scan_id); +CDF_STATUS p2p_send_action(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBuf, uint32_t len, uint16_t wait, bool noack, + uint16_t channel_freq); +CDF_STATUS p2p_cancel_remain_on_channel(tHalHandle hHal, + uint8_t sessionId, uint32_t scan_id); +CDF_STATUS p2p_set_ps(tHalHandle hHal, tP2pPsConfig *pNoA); +tSirRFBand get_rf_band(uint8_t channel); +#endif /* __P2P_API_H__ */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h new file mode 100644 index 000000000000..1da4dcf32876 --- /dev/null +++ b/core/sme/inc/sme_api.h @@ -0,0 +1,1027 @@ +/* + * 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(__SME_API_H) +#define __SME_API_H + +/** + * file smeApi.h + * + * brief prototype for SME APIs + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "csr_api.h" +#include "cds_mq.h" +#include "cdf_lock.h" +#include "cdf_types.h" +#include "sir_api.h" +#include "cds_reg_service.h" +#include "p2p_api.h" +#include "cds_regdomain.h" +#include "sme_internal.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oem_data_api.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "sme_rrm_internal.h" +#endif +#include "sir_types.h" +/*-------------------------------------------------------------------------- + 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_SESSION_ID_ANY 50 + +#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) + +/* Macro to indicate invalid no of tspecs */ +#define INVALID_TSPEC 100 + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef void (*hdd_ftm_msg_processor)(void *); +typedef struct _smeConfigParams { + tCsrConfigParam csrConfig; +#if defined WLAN_FEATURE_VOWIFI + tRrmConfigParam rrmConfig; +#endif +#if defined FEATURE_WLAN_LFR + uint8_t isFastRoamIniFeatureEnabled; + uint8_t MAWCEnabled; +#endif +#if defined FEATURE_WLAN_ESE + uint8_t isEseIniFeatureEnabled; +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) + uint8_t isFastTransitionEnabled; + uint8_t RoamRssiDiff; + bool isWESModeEnabled; +#endif + uint8_t isAmsduSupportInAMPDU; + bool pnoOffload; + uint8_t fEnableDebugLog; + uint8_t max_intf_count; + bool enable5gEBT; + bool 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; + bool is_ps_enabled; + bool policy_manager_enabled; + uint32_t fine_time_meas_cap; + uint32_t dual_mac_feature_disable; +} tSmeConfigParams, *tpSmeConfigParams; + +#ifdef FEATURE_WLAN_TDLS +#define SME_TDLS_MAX_SUPP_CHANNELS 128 +#define SME_TDLS_MAX_SUPP_OPER_CLASSES 32 + +typedef struct _smeTdlsPeerCapParams { + uint8_t isPeerResponder; + uint8_t peerUapsdQueue; + uint8_t peerMaxSp; + uint8_t peerBuffStaSupport; + uint8_t peerOffChanSupport; + uint8_t peerCurrOperClass; + uint8_t selfCurrOperClass; + uint8_t peerChanLen; + uint8_t peerChan[SME_TDLS_MAX_SUPP_CHANNELS]; + uint8_t peerOperClassLen; + uint8_t peerOperClass[SME_TDLS_MAX_SUPP_OPER_CLASSES]; + uint8_t prefOffChanNum; + uint8_t prefOffChanBandwidth; + uint8_t opClassForPrefOffChan; + uint8_t opClassForPrefOffChanIsSet; +} tSmeTdlsPeerCapParams; + +typedef enum { + eSME_TDLS_PEER_STATE_PEERING, + eSME_TDLS_PEER_STATE_CONNECTED, + eSME_TDLS_PEER_STATE_TEARDOWN +} eSmeTdlsPeerState; + +typedef struct _smeTdlsPeerStateParams { + uint32_t vdevId; + tSirMacAddr peerMacAddr; + uint32_t 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 sme_tdls_chan_switch_params_struct { + uint32_t vdev_id; + tSirMacAddr peer_mac_addr; + uint16_t tdls_off_ch_bw_offset;/* Target Off Channel Bandwidth offset */ + uint8_t tdls_off_channel; /* Target Off Channel */ + uint8_t tdls_off_ch_mode; /* TDLS Off Channel Mode */ + uint8_t is_responder; /* is peer responder or initiator */ +} sme_tdls_chan_switch_params; +#endif /* FEATURE_WLAN_TDLS */ + +/* Thermal Mitigation*/ +typedef struct { + uint16_t smeMinTempThreshold; + uint16_t smeMaxTempThreshold; +} tSmeThermalLevelInfo; + +#define SME_MAX_THERMAL_LEVELS (4) +typedef struct { + /* Array of thermal levels */ + tSmeThermalLevelInfo smeThermalLevels[SME_MAX_THERMAL_LEVELS]; + uint8_t smeThermalMgmtEnabled; + uint32_t smeThrottlePeriod; +} tSmeThermalParams; + +typedef enum { + SME_AC_BK = 0, + SME_AC_BE = 1, + SME_AC_VI = 2, + SME_AC_VO = 3 +} sme_ac_enum_type; + +/* TSPEC Direction Enum Type */ +typedef enum { + /* uplink */ + SME_TX_DIR = 0, + /* downlink */ + SME_RX_DIR = 1, + /* bidirectional */ + SME_BI_DIR = 2, +} sme_tspec_dir_type; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +CDF_STATUS sme_open(tHalHandle hHal); +CDF_STATUS sme_init_chan_list(tHalHandle hal, uint8_t *alpha2, + COUNTRY_CODE_SOURCE cc_src); +CDF_STATUS sme_close(tHalHandle hHal); +CDF_STATUS sme_start(tHalHandle hHal); +CDF_STATUS sme_stop(tHalHandle hHal, tHalStopType stopType); +CDF_STATUS sme_open_session(tHalHandle hHal, csr_roam_completeCallback callback, + void *pContext, uint8_t *pSelfMacAddr, + uint8_t *pbSessionId, uint32_t type, + uint32_t subType); +void sme_set_curr_device_mode(tHalHandle hHal, tCDF_CON_MODE currDeviceMode); +CDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId, + csr_roamSessionCloseCallback callback, + void *pContext); +CDF_STATUS sme_update_roam_params(tHalHandle hHal, uint8_t session_id, + struct roam_ext_params roam_params_src, int update_param); +CDF_STATUS sme_update_config(tHalHandle hHal, + tpSmeConfigParams pSmeConfigParams); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS sme_set_plm_request(tHalHandle hHal, tpSirPlmReq pPlm); +#endif + +CDF_STATUS sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams); +CDF_STATUS sme_get_soft_ap_domain(tHalHandle hHal, + v_REGDOMAIN_t *domainIdSoftAp); +CDF_STATUS sme_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode); +CDF_STATUS sme_change_config_params(tHalHandle hHal, + tCsrUpdateConfigParam *pUpdateConfigParam); +CDF_STATUS sme_hdd_ready_ind(tHalHandle hHal); +CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg); +void sme_free_msg(tHalHandle hHal, cds_msg_t *pMsg); +CDF_STATUS sme_scan_request(tHalHandle hHal, uint8_t sessionId, + tCsrScanRequest *, csr_scan_completeCallback callback, + void *pContext); +CDF_STATUS sme_scan_get_result(tHalHandle hHal, uint8_t sessionId, + tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult); +CDF_STATUS sme_get_ap_channel_from_scan_cache(tHalHandle hHal, + tCsrRoamProfile *profile, + tScanResultHandle *scan_cache, + uint8_t *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); +CDF_STATUS sme_issue_stored_joinreq(tHalHandle hal_handle, + uint32_t *roam_id, + uint32_t session_id); +CDF_STATUS sme_scan_flush_result(tHalHandle hHal); +CDF_STATUS sme_filter_scan_results(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_scan_flush_p2p_result(tHalHandle hHal, uint8_t sessionId); +tCsrScanResultInfo *sme_scan_result_get_first(tHalHandle, + tScanResultHandle hScanResult); +tCsrScanResultInfo *sme_scan_result_get_next(tHalHandle, + tScanResultHandle hScanResult); +CDF_STATUS sme_scan_result_purge(tHalHandle hHal, + tScanResultHandle hScanResult); +CDF_STATUS sme_scan_get_pmkid_candidate_list(tHalHandle hHal, uint8_t sessionId, + tPmkidCandidateInfo *pPmkidList, + uint32_t *pNumItems); +CDF_STATUS sme_roam_connect(tHalHandle hHal, uint8_t sessionId, + tCsrRoamProfile *pProfile, uint32_t *pRoamId); +CDF_STATUS sme_roam_reassoc(tHalHandle hHal, uint8_t sessionId, + tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + uint32_t *pRoamId, bool fForce); +CDF_STATUS sme_roam_connect_to_last_profile(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_roam_disconnect(tHalHandle hHal, uint8_t sessionId, + eCsrRoamDisconnectReason reason); +CDF_STATUS sme_roam_stop_bss(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_roam_get_associated_stas(tHalHandle hHal, uint8_t sessionId, + CDF_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, + uint8_t *pAssocStasBuf); +CDF_STATUS sme_roam_disconnect_sta(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pPeerMacAddr); +CDF_STATUS sme_roam_deauth_sta(tHalHandle hHal, uint8_t sessionId, + struct tagCsrDelStaParams *pDelStaParams); +CDF_STATUS sme_roam_tkip_counter_measures(tHalHandle hHal, uint8_t sessionId, + bool bEnable); +CDF_STATUS sme_roam_get_wps_session_overlap(tHalHandle hHal, uint8_t sessionId, + void *pUsrContext, + void *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac); +CDF_STATUS sme_roam_get_connect_state(tHalHandle hHal, uint8_t sessionId, + eCsrConnectState *pState); +CDF_STATUS sme_roam_get_connect_profile(tHalHandle hHal, uint8_t sessionId, + tCsrRoamConnectedProfile *pProfile); +CDF_STATUS sme_roam_free_connect_profile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile); +CDF_STATUS sme_roam_set_pmkid_cache(tHalHandle hHal, uint8_t sessionId, + tPmkidCacheInfo *pPMKIDCache, + uint32_t numItems, + bool update_entire_cache); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS sme_roam_set_psk_pmk(tHalHandle hHal, uint8_t sessionId, + uint8_t *pPSK_PMK, size_t pmk_len); +#endif +CDF_STATUS sme_roam_get_security_req_ie(tHalHandle hHal, uint8_t sessionId, + uint32_t *pLen, uint8_t *pBuf, + eCsrSecurityType secType); +CDF_STATUS sme_roam_get_security_rsp_ie(tHalHandle hHal, uint8_t sessionId, + uint32_t *pLen, uint8_t *pBuf, + eCsrSecurityType secType); +uint32_t sme_roam_get_num_pmkid_cache(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_roam_get_pmkid_cache(tHalHandle hHal, uint8_t sessionId, + uint32_t *pNum, + tPmkidCacheInfo *pPmkidCache); +CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam); +CDF_STATUS sme_get_statistics(tHalHandle hHal, + eCsrStatsRequesterType requesterId, + uint32_t statsMask, tCsrStatsCallback callback, + uint32_t periodicity, bool cache, uint8_t staId, + void *pContext, uint8_t sessionId); +CDF_STATUS sme_get_rssi(tHalHandle hHal, + tCsrRssiCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, int8_t lastRSSI, + void *pContext, void *p_cds_context); +CDF_STATUS sme_get_snr(tHalHandle hHal, + tCsrSnrCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, void *pContext); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS sme_get_tsm_stats(tHalHandle hHal, + tCsrTsmStatsCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, + void *pContext, void *p_cds_context, uint8_t tid); +CDF_STATUS sme_set_cckm_ie(tHalHandle hHal, + uint8_t sessionId, + uint8_t *pCckmIe, uint8_t cckmIeLen); +CDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId, + const tCsrEseBeaconReq *pEseBcnReq); +#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +CDF_STATUS sme_cfg_set_int(tHalHandle hal, uint16_t cfg_id, uint32_t value); +CDF_STATUS sme_cfg_set_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str, + uint32_t length); +CDF_STATUS sme_cfg_get_int(tHalHandle hal, uint16_t cfg_id, + uint32_t *cfg_value); +CDF_STATUS sme_cfg_get_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str, + uint32_t *length); +CDF_STATUS sme_get_modify_profile_fields(tHalHandle hHal, uint8_t sessionId, + tCsrRoamModifyProfileFields * + pModifyProfileFields); + +extern CDF_STATUS sme_set_host_power_save(tHalHandle hHal, bool psMode); + +void sme_set_dhcp_till_power_active_flag(tHalHandle hHal, uint8_t flag); +extern CDF_STATUS sme_register11d_scan_done_callback(tHalHandle hHal, + csr_scan_completeCallback); +#ifdef FEATURE_OEM_DATA_SUPPORT +extern CDF_STATUS sme_register_oem_data_rsp_callback(tHalHandle h_hal, + sme_send_oem_data_rsp_msg callback); +#endif + +extern CDF_STATUS sme_wow_add_pattern(tHalHandle hHal, + struct wow_add_pattern *pattern, uint8_t sessionId); +extern CDF_STATUS sme_wow_delete_pattern(tHalHandle hHal, + struct wow_delete_pattern *pattern, uint8_t sessionId); + +void sme_register_ftm_msg_processor(tHalHandle hal, + hdd_ftm_msg_processor callback); + +extern CDF_STATUS sme_enter_wowl(tHalHandle hHal, + void (*enter_wowl_callback_routine)(void + *callbackContext, + CDF_STATUS status), + void *enter_wowl_callback_context, +#ifdef WLAN_WAKEUP_EVENTS + void (*wake_reason_ind_cb)(void *callbackContext, + tpSirWakeReasonInd + wake_reason_ind), + void *wake_reason_ind_cb_ctx, +#endif /* WLAN_WAKEUP_EVENTS */ + tpSirSmeWowlEnterParams wowl_enter_params, + uint8_t sessionId); + +extern CDF_STATUS sme_exit_wowl(tHalHandle hHal, + tpSirSmeWowlExitParams wowl_exit_params); +CDF_STATUS sme_roam_set_key(tHalHandle, uint8_t sessionId, + tCsrRoamSetKey *pSetKey, uint32_t *pRoamId); +CDF_STATUS sme_get_country_code(tHalHandle hHal, uint8_t *pBuf, uint8_t *pbLen); + + +void sme_apply_channel_power_info_to_fw(tHalHandle hHal); + +/* some support functions */ +bool sme_is11d_supported(tHalHandle hHal); +bool sme_is11h_supported(tHalHandle hHal); +bool sme_is_wmm_supported(tHalHandle hHal); + +typedef void (*tSmeChangeCountryCallback)(void *pContext); +CDF_STATUS sme_change_country_code(tHalHandle hHal, + tSmeChangeCountryCallback callback, + uint8_t *pCountry, + void *pContext, + void *p_cds_context, + tAniBool countryFromUserSpace, + tAniBool sendRegHint); +CDF_STATUS sme_generic_change_country_code(tHalHandle hHal, + uint8_t *pCountry, + v_REGDOMAIN_t reg_domain); + +CDF_STATUS sme_dhcp_start_ind(tHalHandle hHal, + uint8_t device_mode, + uint8_t *macAddr, uint8_t sessionId); +CDF_STATUS sme_dhcp_stop_ind(tHalHandle hHal, + uint8_t device_mode, + uint8_t *macAddr, uint8_t sessionId); +void sme_set_cfg_privacy(tHalHandle hHal, tCsrRoamProfile *pProfile, + bool fPrivacy); +void sme_get_recovery_stats(tHalHandle hHal); +#if defined WLAN_FEATURE_VOWIFI +CDF_STATUS sme_neighbor_report_request(tHalHandle hHal, uint8_t sessionId, + tpRrmNeighborReq pRrmNeighborReq, + tpRrmNeighborRspCallbackInfo callbackInfo); +#endif +CDF_STATUS sme_get_wcnss_wlan_compiled_version(tHalHandle hHal, + tSirVersionType * pVersion); +CDF_STATUS sme_get_wcnss_wlan_reported_version(tHalHandle hHal, + tSirVersionType *pVersion); +CDF_STATUS sme_get_wcnss_software_version(tHalHandle hHal, + uint8_t *pVersion, uint32_t versionBufferSize); +CDF_STATUS sme_get_wcnss_hardware_version(tHalHandle hHal, + uint8_t *pVersion, uint32_t versionBufferSize); +#ifdef FEATURE_WLAN_WAPI +CDF_STATUS sme_scan_get_bkid_candidate_list(tHalHandle hHal, uint32_t sessionId, + tBkidCandidateInfo * pBkidList, + uint32_t *pNumItems); +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_OEM_DATA_SUPPORT +CDF_STATUS sme_oem_data_req(tHalHandle hHal, + uint8_t sessionId, + tOemDataReqConfig *, + uint32_t *pOemDataReqID, + oem_data_oem_data_reqCompleteCallback callback, + void *pContext); +#endif /*FEATURE_OEM_DATA_SUPPORT */ +CDF_STATUS sme_roam_update_apwpsie(tHalHandle, uint8_t sessionId, + tSirAPWPSIEs * pAPWPSIES); +CDF_STATUS sme_roam_update_apwparsni_es(tHalHandle hHal, uint8_t sessionId, + tSirRSNie *pAPSirRSNie); +CDF_STATUS sme_change_mcc_beacon_interval(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_set_host_offload(tHalHandle hHal, uint8_t sessionId, + tpSirHostOffloadReq pRequest); +CDF_STATUS sme_set_keep_alive(tHalHandle hHal, uint8_t sessionId, + tpSirKeepAliveReq pRequest); +CDF_STATUS sme_get_operation_channel(tHalHandle hHal, uint32_t *pChannel, + uint8_t sessionId); +CDF_STATUS sme_register_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + uint16_t frameType, uint8_t *matchData, + uint16_t matchLen); +CDF_STATUS sme_deregister_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + uint16_t frameType, uint8_t *matchData, + uint16_t matchLen); +CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, + tpSirWlanSetRxpFilters wlanRxpFilterParam); +CDF_STATUS sme_ConfigureAppsCpuWakeupState(tHalHandle hHal, bool isAppsAwake); +CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, + tpSirWlanSuspendParam wlanSuspendParam, + csr_readyToSuspendCallback, + void *callbackContext); +CDF_STATUS sme_configure_resume_req(tHalHandle hHal, + tpSirWlanResumeParam wlanResumeParam); +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +CDF_STATUS sme_configure_ext_wo_w(tHalHandle hHal, + tpSirExtWoWParams wlanExtParams, + csr_readyToSuspendCallback callback, + void *callbackContext); +CDF_STATUS sme_configure_app_type1_params(tHalHandle hHal, + tpSirAppType1Params wlanAppType1Params); +CDF_STATUS sme_configure_app_type2_params(tHalHandle hHal, + tpSirAppType2Params wlanAppType2Params); +#endif +int8_t sme_get_infra_session_id(tHalHandle hHal); +uint8_t sme_get_infra_operation_channel(tHalHandle hHal, uint8_t sessionId); +uint8_t sme_get_concurrent_operation_channel(tHalHandle hHal); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch, + eCsrPhyMode sapPhyMode, + uint8_t cc_switch_mode); +#endif +CDF_STATUS sme_abort_mac_scan(tHalHandle hHal, uint8_t sessionId, + eCsrAbortReason reason); +CDF_STATUS sme_get_cfg_valid_channels(tHalHandle hHal, uint8_t *aValidChannels, + uint32_t *len); +#ifdef FEATURE_WLAN_SCAN_PNO +CDF_STATUS sme_set_preferred_network_list(tHalHandle hHal, + tpSirPNOScanReq pRequest, + uint8_t sessionId, + preferred_network_found_ind_cb + callbackRoutine, void *callbackContext); + +CDF_STATUS sme_preferred_network_found_ind(tHalHandle hHal, void *pMsg); +#endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef WLAN_FEATURE_PACKET_FILTERING +CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, + tpSirRcvFltMcAddrList pMulticastAddrs); +CDF_STATUS sme_receive_filter_set_filter(tHalHandle hHal, + tpSirRcvPktFilterCfgType pRcvPktFilterCfg, + uint8_t sessionId); +CDF_STATUS sme_receive_filter_clear_filter(tHalHandle hHal, + tpSirRcvFltPktClearParam pRcvFltPktClearParam, + uint8_t sessionId); +#endif /* WLAN_FEATURE_PACKET_FILTERING */ +bool sme_is_channel_valid(tHalHandle hHal, uint8_t channel); +CDF_STATUS sme_set_freq_band(tHalHandle hHal, uint8_t sessionId, + eCsrBand eBand); +CDF_STATUS sme_get_freq_band(tHalHandle hHal, eCsrBand *pBand); +#ifdef WLAN_FEATURE_GTK_OFFLOAD +CDF_STATUS sme_set_gtk_offload(tHalHandle hal_ctx, + tpSirGtkOffloadParams request, + uint8_t session_id); +CDF_STATUS sme_get_gtk_offload(tHalHandle hal_ctx, + gtk_offload_get_info_callback callback_routine, + void *callback_context, uint8_t session_id); +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ +uint16_t sme_chn_to_freq(uint8_t chanNum); +bool sme_is_channel_valid(tHalHandle hHal, uint8_t channel); +CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, tSirMacAddr pBssid, + tSirMacAddr pSelfMacAddress, int8_t dB); +CDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t db); +CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, + tSirMacAddr pBSSId, + tCDF_CON_MODE dev_mode, int power); +CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr); +CDF_STATUS sme_hide_ssid(tHalHandle hHal, uint8_t sessionId, + uint8_t ssidHidden); +CDF_STATUS sme_set_tm_level(tHalHandle hHal, uint16_t newTMLevel, + uint16_t tmMode); +void sme_feature_caps_exchange(tHalHandle hHal); +void sme_disable_feature_capablity(uint8_t feature_index); +void sme_reset_power_values_for5_g(tHalHandle hHal); +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) +CDF_STATUS sme_update_roam_prefer5_g_hz(tHalHandle hHal, bool nRoamPrefer5GHz); +CDF_STATUS sme_set_roam_intra_band(tHalHandle hHal, const bool nRoamIntraBand); +CDF_STATUS sme_update_roam_scan_n_probes(tHalHandle hHal, uint8_t sessionId, + const uint8_t nProbes); +CDF_STATUS sme_update_roam_scan_home_away_time(tHalHandle hHal, + uint8_t sessionId, + const uint16_t nRoamScanHomeAwayTime, + const bool bSendOffloadCmd); + +bool sme_get_roam_intra_band(tHalHandle hHal); +uint8_t sme_get_roam_scan_n_probes(tHalHandle hHal); +uint16_t sme_get_roam_scan_home_away_time(tHalHandle hHal); +CDF_STATUS sme_update_roam_rssi_diff(tHalHandle hHal, uint8_t sessionId, + uint8_t RoamRssiDiff); +CDF_STATUS sme_update_fast_transition_enabled(tHalHandle hHal, + bool isFastTransitionEnabled); +CDF_STATUS sme_update_wes_mode(tHalHandle hHal, bool isWESModeEnabled, + uint8_t sessionId); +CDF_STATUS sme_set_roam_scan_control(tHalHandle hHal, uint8_t sessionId, + bool roamScanControl); +#endif /* (WLAN_FEATURE_VOWIFI_11R)||(FEATURE_WLAN_ESE)||(FEATURE_WLAN_LFR) */ + +#ifdef FEATURE_WLAN_LFR +CDF_STATUS sme_update_is_fast_roam_ini_feature_enabled(tHalHandle hHal, + uint8_t sessionId, + const bool + isFastRoamIniFeatureEnabled); +CDF_STATUS sme_update_is_mawc_ini_feature_enabled(tHalHandle hHal, + const bool MAWCEnabled); +CDF_STATUS sme_stop_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason); +CDF_STATUS sme_start_roaming(tHalHandle hHal, uint8_t sessionId, + uint8_t reason); +CDF_STATUS sme_update_enable_fast_roam_in_concurrency(tHalHandle hHal, + bool bFastRoamInConIniFeatureEnabled); +#endif /* FEATURE_WLAN_LFR */ +#ifdef FEATURE_WLAN_ESE +CDF_STATUS sme_update_is_ese_feature_enabled(tHalHandle hHal, uint8_t sessionId, + const bool isEseIniFeatureEnabled); +#endif /* FEATURE_WLAN_ESE */ +CDF_STATUS sme_update_config_fw_rssi_monitoring(tHalHandle hHal, + bool fEnableFwRssiMonitoring); +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +CDF_STATUS sme_set_roam_rescan_rssi_diff(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nRoamRescanRssiDiff); +uint8_t sme_get_roam_rescan_rssi_diff(tHalHandle hHal); + +CDF_STATUS sme_set_roam_opportunistic_scan_threshold_diff(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nOpportunisticThresholdDiff); +uint8_t sme_get_roam_opportunistic_scan_threshold_diff(tHalHandle hHal); +CDF_STATUS sme_set_neighbor_lookup_rssi_threshold(tHalHandle hHal, + uint8_t sessionId, uint8_t neighborLookupRssiThreshold); +CDF_STATUS sme_set_delay_before_vdev_stop(tHalHandle hHal, + uint8_t sessionId, uint8_t delay_before_vdev_stop); +uint8_t sme_get_neighbor_lookup_rssi_threshold(tHalHandle hHal); +CDF_STATUS sme_set_neighbor_scan_refresh_period(tHalHandle hHal, + uint8_t sessionId, uint16_t neighborScanResultsRefreshPeriod); +uint16_t sme_get_neighbor_scan_refresh_period(tHalHandle hHal); +uint16_t sme_get_empty_scan_refresh_period(tHalHandle hHal); +CDF_STATUS sme_update_empty_scan_refresh_period(tHalHandle hHal, + uint8_t sessionId, uint16_t nEmptyScanRefreshPeriod); +CDF_STATUS sme_set_neighbor_scan_min_chan_time(tHalHandle hHal, + const uint16_t nNeighborScanMinChanTime, + uint8_t sessionId); +CDF_STATUS sme_set_neighbor_scan_max_chan_time(tHalHandle hHal, + uint8_t sessionId, const uint16_t nNeighborScanMaxChanTime); +uint16_t sme_get_neighbor_scan_min_chan_time(tHalHandle hHal, + uint8_t sessionId); +uint32_t sme_get_neighbor_roam_state(tHalHandle hHal, uint8_t sessionId); +uint32_t sme_get_current_roam_state(tHalHandle hHal, uint8_t sessionId); +uint32_t sme_get_current_roam_sub_state(tHalHandle hHal, uint8_t sessionId); +uint32_t sme_get_lim_sme_state(tHalHandle hHal); +uint32_t sme_get_lim_mlm_state(tHalHandle hHal); +bool sme_is_lim_session_valid(tHalHandle hHal, uint8_t sessionId); +uint32_t sme_get_lim_sme_session_state(tHalHandle hHal, uint8_t sessionId); +uint32_t sme_get_lim_mlm_session_state(tHalHandle hHal, uint8_t sessionId); +uint16_t sme_get_neighbor_scan_max_chan_time(tHalHandle hHal, + uint8_t sessionId); +CDF_STATUS sme_set_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId, + const uint16_t nNeighborScanPeriod); +uint16_t sme_get_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId); +CDF_STATUS sme_set_roam_bmiss_first_bcnt(tHalHandle hHal, + uint8_t sessionId, const uint8_t nRoamBmissFirstBcnt); +uint8_t sme_get_roam_bmiss_first_bcnt(tHalHandle hHal); +CDF_STATUS sme_set_roam_bmiss_final_bcnt(tHalHandle hHal, uint8_t sessionId, + const uint8_t nRoamBmissFinalBcnt); +uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal); +CDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal, uint8_t sessionId, + const uint8_t nRoamBeaconRssiWeight); +uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal); +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) +uint8_t sme_get_roam_rssi_diff(tHalHandle hHal); +CDF_STATUS sme_change_roam_scan_channel_list(tHalHandle hHal, uint8_t sessionId, + uint8_t *pChannelList, + uint8_t numChannels); +#ifdef FEATURE_WLAN_ESE_UPLOAD +CDF_STATUS sme_set_ese_roam_scan_channel_list(tHalHandle hHal, + uint8_t sessionId, uint8_t *pChannelList, + uint8_t numChannels); +#endif +CDF_STATUS sme_get_roam_scan_channel_list(tHalHandle hHal, + uint8_t *pChannelList, uint8_t *pNumChannels, + uint8_t sessionId); +bool sme_get_is_ese_feature_enabled(tHalHandle hHal); +bool sme_get_wes_mode(tHalHandle hHal); +bool sme_get_roam_scan_control(tHalHandle hHal); +bool sme_get_is_lfr_feature_enabled(tHalHandle hHal); +bool sme_get_is_ft_feature_enabled(tHalHandle hHal); +#endif +CDF_STATUS sme_update_roam_scan_offload_enabled(tHalHandle hHal, + bool nRoamScanOffloadEnabled); +uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue); +#ifdef FEATURE_WLAN_TDLS +CDF_STATUS sme_send_tdls_link_establish_params(tHalHandle hHal, + uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams * + tdlsLinkEstablishParams); +CDF_STATUS sme_send_tdls_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, uint8_t frame_type, + uint8_t dialog, uint16_t status, + uint32_t peerCapability, uint8_t *buf, + uint8_t len, uint8_t responder); +CDF_STATUS sme_change_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams); +CDF_STATUS sme_add_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac); +CDF_STATUS sme_delete_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac); +void sme_set_tdls_power_save_prohibited(tHalHandle hHal, uint32_t sessionId, + bool val); +CDF_STATUS sme_send_tdls_chan_switch_req( + tHalHandle hal, + sme_tdls_chan_switch_params *ch_switch_params); +#endif + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_update_enable_ssr(tHalHandle hHal, bool enableSSR); +CDF_STATUS sme_set_phy_mode(tHalHandle hHal, eCsrPhyMode phyMode); +eCsrPhyMode sme_get_phy_mode(tHalHandle hHal); +/* + * SME API to determine the channel bonding mode + */ +CDF_STATUS sme_set_ch_params(tHalHandle hHal, eCsrPhyMode eCsrPhyMode, + uint8_t channel, uint8_t ht_sec_ch, chan_params_t *ch_params); +CDF_STATUS sme_handoff_request(tHalHandle hHal, uint8_t sessionId, + tCsrHandoffRequest *pHandoffInfo); +CDF_STATUS sme_is_sta_p2p_client_connected(tHalHandle hHal); +#ifdef FEATURE_WLAN_LPHB +CDF_STATUS sme_lphb_config_req(tHalHandle hHal, + tSirLPHBReq * lphdReq, + void (*pCallbackfn)(void *pHddCtx, + tSirLPHBInd * indParam)); +#endif /* FEATURE_WLAN_LPHB */ +CDF_STATUS sme_add_periodic_tx_ptrn(tHalHandle hHal, tSirAddPeriodicTxPtrn + *addPeriodicTxPtrnParams); +CDF_STATUS sme_del_periodic_tx_ptrn(tHalHandle hHal, tSirDelPeriodicTxPtrn + *delPeriodicTxPtrnParams); +void sme_enable_disable_split_scan(tHalHandle hHal, uint8_t nNumStaChan, + uint8_t nNumP2PChan); +CDF_STATUS sme_send_rate_update_ind(tHalHandle hHal, + tSirRateUpdateInd *rateUpdateParams); +CDF_STATUS sme_roam_del_pmkid_from_cache(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBSSId, bool flush_cache); +void sme_get_command_q_status(tHalHandle hHal); + +/* + * SME API to enable/disable idle mode powersave + * This should be called only if powersave offload + * is enabled + */ +CDF_STATUS sme_set_idle_powersave_config(void *cds_context, + tHalHandle hHal, uint32_t value); +CDF_STATUS sme_notify_modem_power_state(tHalHandle hHal, uint32_t value); + +/*SME API to convert convert the ini value to the ENUM used in csr and MAC*/ +ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value); +int sme_update_ht_config(tHalHandle hHal, uint8_t sessionId, uint16_t htCapab, + int value); +int16_t sme_get_ht_config(tHalHandle hHal, uint8_t session_id, + uint16_t ht_capab); +#ifdef QCA_HT_2040_COEX +CDF_STATUS sme_notify_ht2040_mode(tHalHandle hHal, uint16_t staId, + struct cdf_mac_addr macAddrSTA, + uint8_t sessionId, + uint8_t channel_type); +CDF_STATUS sme_set_ht2040_mode(tHalHandle hHal, uint8_t sessionId, + uint8_t channel_type, bool obssEnabled); +#endif +CDF_STATUS sme_get_reg_info(tHalHandle hHal, uint8_t chanId, + uint32_t *regInfo1, uint32_t *regInfo2); +#ifdef FEATURE_WLAN_TDLS +CDF_STATUS sme_update_fw_tdls_state(tHalHandle hHal, void *psmeTdlsParams, + bool useSmeLock); +CDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal, + tSmeTdlsPeerStateParams *pPeerStateParams); +#endif /* FEATURE_WLAN_TDLS */ +#ifdef FEATURE_WLAN_CH_AVOID +CDF_STATUS sme_add_ch_avoid_callback(tHalHandle hHal, + void (*pCallbackfn)(void *hdd_context, void *indi_param)); +CDF_STATUS sme_ch_avoid_update_req(tHalHandle hHal); +#else +static inline +CDF_STATUS sme_add_ch_avoid_callback(tHalHandle hHal, + void (*pCallbackfn)(void *hdd_context, void *indi_param)) +{ + return CDF_STATUS_E_NOSUPPORT; +} + +static inline +CDF_STATUS sme_ch_avoid_update_req(tHalHandle hHal) +{ + return CDF_STATUS_E_NOSUPPORT; +} +#endif /* FEATURE_WLAN_CH_AVOID */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +CDF_STATUS sme_set_auto_shutdown_cb(tHalHandle hHal, void (*pCallbackfn)(void)); +CDF_STATUS sme_set_auto_shutdown_timer(tHalHandle hHal, uint32_t timer_value); +#endif +CDF_STATUS sme_roam_channel_change_req(tHalHandle hHal, + struct cdf_mac_addr bssid, uint32_t cb_mode, + tCsrRoamProfile *profile); +CDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, + struct cdf_mac_addr bssid, uint8_t dfsCacWaitStatus); +CDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct cdf_mac_addr bssid, + uint8_t targetChannel, uint8_t csaIeReqd, uint8_t ch_bandwidth); +CDF_STATUS sme_init_thermal_info(tHalHandle hHal, + tSmeThermalParams thermalParam); +CDF_STATUS sme_set_thermal_level(tHalHandle hHal, uint8_t level); +CDF_STATUS sme_txpower_limit(tHalHandle hHal, tSirTxPowerLimit *psmetx); +CDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq, + void *plsContext, + void (*pCallbackfn)(tSirLinkSpeedInfo *indParam, + void *pContext)); +CDF_STATUS sme_modify_add_ie(tHalHandle hHal, + tSirModifyIE *pModifyIE, eUpdateIEsType updateType); +CDF_STATUS sme_update_add_ie(tHalHandle hHal, + tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType); +CDF_STATUS sme_update_connect_debug(tHalHandle hHal, uint32_t set_value); +CDF_STATUS sme_ap_disable_intra_bss_fwd(tHalHandle hHal, uint8_t sessionId, + bool disablefwd); +uint32_t sme_get_channel_bonding_mode5_g(tHalHandle hHal); +uint32_t sme_get_channel_bonding_mode24_g(tHalHandle hHal); +#ifdef WLAN_FEATURE_STATS_EXT +typedef struct sStatsExtRequestReq { + uint32_t request_data_len; + uint8_t *request_data; +} tStatsExtRequestReq, *tpStatsExtRequestReq; +typedef void (*StatsExtCallback)(void *, tStatsExtEvent *); +void sme_stats_ext_register_callback(tHalHandle hHal, + StatsExtCallback callback); +CDF_STATUS sme_stats_ext_request(uint8_t session_id, + tpStatsExtRequestReq input); +CDF_STATUS sme_stats_ext_event(tHalHandle hHal, void *pMsg); +#endif +CDF_STATUS sme_update_dfs_scan_mode(tHalHandle hHal, + uint8_t sessionId, + uint8_t allowDFSChannelRoam); +uint8_t sme_get_dfs_scan_mode(tHalHandle hHal); +bool sme_sta_in_middle_of_roaming(tHalHandle hHal, uint8_t sessionId); + +#ifdef FEATURE_WLAN_EXTSCAN +CDF_STATUS sme_get_valid_channels_by_band(tHalHandle hHal, uint8_t wifiBand, + uint32_t *aValidChannels, + uint8_t *pNumChannels); +CDF_STATUS sme_ext_scan_get_capabilities(tHalHandle hHal, + tSirGetExtScanCapabilitiesReqParams *pReq); +CDF_STATUS sme_ext_scan_start(tHalHandle hHal, + tSirWifiScanCmdReqParams *pStartCmd); +CDF_STATUS sme_ext_scan_stop(tHalHandle hHal, + tSirExtScanStopReqParams *pStopReq); +CDF_STATUS sme_set_bss_hotlist(tHalHandle hHal, + tSirExtScanSetBssidHotListReqParams * + pSetHotListReq); +CDF_STATUS sme_reset_bss_hotlist(tHalHandle hHal, + tSirExtScanResetBssidHotlistReqParams * + pResetReq); +CDF_STATUS sme_set_significant_change(tHalHandle hHal, + tSirExtScanSetSigChangeReqParams * + pSetSignificantChangeReq); +CDF_STATUS sme_reset_significant_change(tHalHandle hHal, + tSirExtScanResetSignificantChangeReqParams + *pResetReq); +CDF_STATUS sme_get_cached_results(tHalHandle hHal, + tSirExtScanGetCachedResultsReqParams * + pCachedResultsReq); + +CDF_STATUS sme_set_epno_list(tHalHandle hal, + struct wifi_epno_params *req_msg); +CDF_STATUS sme_set_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *req_msg); +CDF_STATUS sme_reset_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *req_msg); +CDF_STATUS +sme_set_ssid_hotlist(tHalHandle hal, + struct sir_set_ssid_hotlist_request *request); + +CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, + void (*pExtScanIndCb)(void *, const uint16_t, void *)); +#endif /* FEATURE_WLAN_EXTSCAN */ +CDF_STATUS sme_abort_roam_scan(tHalHandle hHal, uint8_t sessionId); +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +CDF_STATUS sme_ll_stats_clear_req(tHalHandle hHal, + tSirLLStatsClearReq * pclearStatsReq); +CDF_STATUS sme_ll_stats_set_req(tHalHandle hHal, + tSirLLStatsSetReq *psetStatsReq); +CDF_STATUS sme_ll_stats_get_req(tHalHandle hHal, + tSirLLStatsGetReq *pgetStatsReq); +CDF_STATUS sme_set_link_layer_stats_ind_cb(tHalHandle hHal, + void (*callbackRoutine)(void *callbackCtx, + int indType, void *pRsp)); +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +CDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req); +CDF_STATUS sme_fw_mem_dump_register_cb(tHalHandle hHal, + void (*callback_routine)(void *cb_context, + struct fw_dump_rsp *rsp)); +CDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hHal); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS sme_update_roam_offload_enabled(tHalHandle hHal, + bool nRoamOffloadEnabled); +CDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hHal, + uint8_t sessionId, + bool nRoamKeyMgmtOffloadEnabled); +#endif +#ifdef WLAN_FEATURE_NAN +CDF_STATUS sme_nan_event(tHalHandle hHal, void *pMsg); +#endif /* WLAN_FEATURE_NAN */ +CDF_STATUS sme_get_link_status(tHalHandle hHal, + tCsrLinkStatusCallback callback, + void *pContext, uint8_t sessionId); +CDF_STATUS sme_get_temperature(tHalHandle hHal, + void *tempContext, + void (*pCallbackfn)(int temperature, + void *pContext)); +CDF_STATUS sme_set_scanning_mac_oui(tHalHandle hHal, + tSirScanMacOui *pScanMacOui); + +#ifdef IPA_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 + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal, + uint8_t session_id, + struct sir_ipa_offload_enable_disable *request); +#else +static inline CDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal, + uint8_t session_id, + struct sir_ipa_offload_enable_disable *request) +{ + return CDF_STATUS_SUCCESS; +} +#endif /* IPA_OFFLOAD */ + +#ifdef DHCP_SERVER_OFFLOAD +CDF_STATUS sme_set_dhcp_srv_offload(tHalHandle hHal, + tSirDhcpSrvOffloadInfo * pDhcpSrvInfo); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +CDF_STATUS sme_set_led_flashing(tHalHandle hHal, uint8_t type, + uint32_t x0, uint32_t x1); +#endif +CDF_STATUS sme_handle_dfs_chan_scan(tHalHandle hHal, uint8_t dfs_flag); +CDF_STATUS sme_set_mas(uint32_t val); +CDF_STATUS sme_set_miracast(tHalHandle hal, uint8_t filter_type); + +CDF_STATUS sme_configure_modulated_dtim(tHalHandle hal, uint8_t session_id, + uint32_t modulated_dtim); + +CDF_STATUS sme_configure_stats_avg_factor(tHalHandle hal, uint8_t session_id, + uint16_t stats_avg_factor); + +CDF_STATUS sme_configure_guard_time(tHalHandle hal, uint8_t session_id, + uint32_t guard_time); + +CDF_STATUS sme_wifi_start_logger(tHalHandle hal, + struct sir_wifi_start_log start_log); + +bool sme_neighbor_middle_of_roaming(tHalHandle hHal, + uint8_t sessionId); + +CDF_STATUS sme_enable_uapsd_for_ac(void *cds_ctx, uint8_t sta_id, + sme_ac_enum_type ac, uint8_t tid, + uint8_t pri, uint32_t srvc_int, + uint32_t sus_int, + sme_tspec_dir_type dir, + uint8_t psb, uint32_t sessionId, + uint32_t delay_interval); + +CDF_STATUS sme_disable_uapsd_for_ac(void *cds_ctx, uint8_t sta_id, + sme_ac_enum_type ac, + uint32_t sessionId); + +CDF_STATUS sme_set_rssi_monitoring(tHalHandle hal, + struct rssi_monitor_req *input); +CDF_STATUS sme_set_rssi_threshold_breached_cb(tHalHandle hal, + void (*cb)(void *, struct rssi_breach_event *)); + +CDF_STATUS sme_update_nss(tHalHandle h_hal, uint8_t nss); + +bool sme_is_any_session_in_connected_state(tHalHandle h_hal); + +CDF_STATUS sme_soc_set_pcl(tHalHandle hal, + struct sir_pcl_list msg); +CDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, + struct sir_hw_mode msg); +void sme_register_hw_mode_trans_cb(tHalHandle hal, + hw_mode_transition_cb callback); +CDF_STATUS sme_nss_update_request(tHalHandle hHal, uint32_t vdev_id, + uint8_t new_nss, void *cback, + uint8_t next_action, void *hdd_context); + +typedef void (*sme_peer_authorized_fp) (uint32_t vdev_id); +CDF_STATUS sme_set_peer_authorized(uint8_t *peer_addr, + sme_peer_authorized_fp auth_fp, + uint32_t vdev_id); +CDF_STATUS sme_soc_set_dual_mac_config(tHalHandle hal, + struct sir_dual_mac_config msg); + +void sme_set_scan_disable(tHalHandle h_hal, int value); +void sme_setdef_dot11mode(tHalHandle hal); + +CDF_STATUS sme_disable_non_fcc_channel(tHalHandle hHal, + bool fcc_constraint); + +CDF_STATUS sme_update_roam_scan_hi_rssi_scan_params(tHalHandle hal_handle, + uint8_t session_id, + uint32_t notify_id, + int32_t val); + +void wlan_sap_enable_phy_error_logs(tHalHandle hal, bool enable_log); +void sme_set_dot11p_config(tHalHandle hal, bool enable_dot11p); + +CDF_STATUS sme_ocb_set_config(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_config *config); + +CDF_STATUS sme_ocb_set_utc_time(tHalHandle hHal, struct sir_ocb_utc *utc); + +CDF_STATUS sme_ocb_start_timing_advert(tHalHandle hHal, + struct sir_ocb_timing_advert *timing_advert); + +CDF_STATUS sme_ocb_stop_timing_advert(tHalHandle hHal, + struct sir_ocb_timing_advert *timing_advert); + +CDF_STATUS sme_ocb_get_tsf_timer(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_get_tsf_timer *request); + +CDF_STATUS sme_dcc_get_stats(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_get_stats *request); + +CDF_STATUS sme_dcc_clear_stats(tHalHandle hHal, uint32_t vdev_id, + uint32_t dcc_stats_bitmap); + +CDF_STATUS sme_dcc_update_ndl(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_update_ndl *request); + +CDF_STATUS sme_register_for_dcc_stats_event(tHalHandle hHal, void *context, + ocb_callback callback); +void sme_add_set_thermal_level_callback(tHalHandle hal, + sme_set_thermal_level_callback callback); + +#endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_ft_api.h b/core/sme/inc/sme_ft_api.h new file mode 100644 index 000000000000..59e722f43f46 --- /dev/null +++ b/core/sme/inc/sme_ft_api.h @@ -0,0 +1,107 @@ +/* + * 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) + +#if !defined(__SME_FTAPI_H) +#define __SME_FTAPI_H + +#include + +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 */ + /* + * Sent auth1 and waiting auth2 We are now ready for FT phase, + * send auth1, recd auth2 + */ + eFT_WAIT_AUTH2, + eFT_AUTH_COMPLETE, + /* Now we have sent Auth Rsp to the supplicant and waiting */ + /* Reassoc Req from the supplicant. */ + eFT_REASSOC_REQ_WAIT, + /* + * We have received the Reassoc request from supplicant. + * Waiting for the keys. + */ + eFT_SET_KEY_WAIT, +} tFTIEStates; + +/* FT neighbor roam callback user context */ +typedef struct sFTRoamCallbackUsrCtx { + tpAniSirGlobal pMac; + uint8_t sessionId; +} tFTRoamCallbackUsrCtx, *tpFTRoamCallbackUsrCtx; + +typedef struct sFTSMEContext { + /* Received and processed during pre-auth */ + uint8_t *auth_ft_ies; + uint32_t auth_ft_ies_length; + /* Received and processed during re-assoc */ + uint8_t *reassoc_ft_ies; + uint16_t reassoc_ft_ies_length; + /* Pre-Auth info */ + tFTIEStates FTState; /* The state of FT in the current 11rAssoc */ + tSirMacAddr preAuthbssId; /* BSSID to preauth to */ + uint32_t smeSessionId; + /* Saved pFTPreAuthRsp */ + tpSirFTPreAuthRsp psavedFTPreAuthRsp; + bool setFTPreAuthState; + bool setFTPTKState; + /* Time to trigger reassoc once pre-auth is successful */ + cdf_mc_timer_t preAuthReassocIntvlTimer; + bool addMDIE; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint32_t r0kh_id_len; + uint8_t r0kh_id[SIR_ROAM_R0KH_ID_MAX_LEN]; +#endif + /* User context for the timer callback */ + tpFTRoamCallbackUsrCtx pUsrCtx; +} tftSMEContext, *tpftSMEContext; + +/*-------------------------------------------------------------------------- + Prototype functions + ------------------------------------------------------------------------*/ +void sme_ft_open(tHalHandle hHal, uint32_t sessionId); +void sme_ft_close(tHalHandle hHal, uint32_t sessionId); +void sme_ft_reset(tHalHandle hHal, uint32_t sessionId); +void sme_set_ft_ies(tHalHandle hHal, uint32_t sessionId, const uint8_t *ft_ies, + uint16_t ft_ies_length); +CDF_STATUS sme_ft_update_key(tHalHandle hHal, uint32_t sessionId, + tCsrRoamSetKey *pFTKeyInfo); +void sme_get_ft_pre_auth_response(tHalHandle hHal, uint32_t sessionId, + uint8_t *ft_ies, uint32_t ft_ies_ip_len, + uint16_t *ft_ies_length); +void sme_get_rici_es(tHalHandle hHal, uint32_t sessionId, uint8_t *ric_ies, + uint32_t ric_ies_ip_len, uint32_t *ric_ies_length); +void sme_preauth_reassoc_intvl_timer_callback(void *context); +void sme_set_ft_pre_auth_state(tHalHandle hHal, uint32_t sessionId, bool state); +bool sme_get_ft_pre_auth_state(tHalHandle hHal, uint32_t sessionId); +bool sme_get_ftptk_state(tHalHandle hHal, uint32_t sessionId); +void sme_set_ftptk_state(tHalHandle hHal, uint32_t sessionId, bool state); +#endif + +#endif /* #if !defined( __SME_FTAPI_H ) */ diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h new file mode 100644 index 000000000000..396166f202b0 --- /dev/null +++ b/core/sme/inc/sme_inside.h @@ -0,0 +1,287 @@ +/* + * 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 sme_inside.h + * + * \brief prototype for SME structures and APIs used insside SME + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_status.h" +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "sir_api.h" +#include "csr_internal.h" +#include "sme_qos_api.h" +#include "sme_qos_internal.h" + +#ifdef FEATURE_OEM_DATA_SUPPORT +#include "oem_data_internal.h" +#endif + +#if defined WLAN_FEATURE_VOWIFI +#include "sme_rrm_api.h" +#endif +ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue); + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +#define SME_TOTAL_COMMAND 40 + +typedef struct sGenericPmcCmd { + uint32_t size; /* sizeof the data in the union, if any */ + uint32_t sessionId; + /* if true, the cmd shalln't put back to the queue, free mem instead. */ + bool fReleaseWhenDone; + union { + tSirSmeWowlEnterParams enterWowlInfo; + tSirSmeWowlExitParams exitWowlInfo; + } u; +} tGenericPmcCmd; + +typedef struct sGenericQosCmd { + sme_QosWmmTspecInfo tspecInfo; + sme_QosEdcaAcType ac; + uint8_t tspec_mask; +} tGenericQosCmd; + +typedef struct sRemainChlCmd { + uint8_t chn; + uint8_t phyMode; + uint32_t duration; + uint8_t isP2PProbeReqAllowed; + uint32_t scan_id; + void *callback; + void *callbackCtx; +} tRemainChlCmd; + +typedef struct sNoACmd { + tP2pPsConfig NoA; +} tNoACmd; +#ifdef FEATURE_WLAN_TDLS +typedef struct TdlsSendMgmtInfo { + tSirMacAddr peerMac; + uint8_t frameType; + uint8_t dialog; + uint16_t statusCode; + uint8_t responder; + uint32_t peerCapability; + uint8_t *buf; + uint8_t len; +} tTdlsSendMgmtCmdInfo; + +typedef struct TdlsLinkEstablishInfo { + tSirMacAddr peerMac; + uint8_t uapsdQueues; + uint8_t maxSp; + uint8_t isBufSta; + uint8_t isOffChannelSupported; + uint8_t isResponder; + uint8_t supportedChannelsLen; + uint8_t supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; + uint8_t supportedOperClassesLen; + uint8_t supportedOperClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES]; +} tTdlsLinkEstablishCmdInfo; + +typedef struct TdlsAddStaInfo { + eTdlsAddOper tdlsAddOper; + tSirMacAddr peerMac; + uint16_t capability; + uint8_t extnCapability[SIR_MAC_MAX_EXTN_CAP]; + uint8_t supportedRatesLen; + uint8_t supportedRates[SIR_MAC_MAX_SUPP_RATES]; + uint8_t htcap_present; + tSirHTCap HTCap; + uint8_t vhtcap_present; + tSirVHTCap VHTCap; + uint8_t uapsdQueues; + uint8_t maxSp; +} tTdlsAddStaCmdInfo; + +typedef struct TdlsDelStaInfo { + tSirMacAddr peerMac; +} tTdlsDelStaCmdInfo; +/* + * TDLS cmd info, CMD from SME to PE. + */ +typedef struct s_tdls_cmd { + uint32_t size; + union { + tTdlsLinkEstablishCmdInfo tdlsLinkEstablishCmdInfo; + tTdlsSendMgmtCmdInfo tdlsSendMgmtCmdInfo; + tTdlsAddStaCmdInfo tdlsAddStaCmdInfo; + tTdlsDelStaCmdInfo tdlsDelStaCmdInfo; + } u; +} tTdlsCmd; +#endif /* FEATURE_WLAN_TDLS */ + +/** + * struct s_nss_update_cmd - Format of nss update request + * @new_nss: new nss value + * @session_id: Session ID + * @set_hw_mode_cb: HDD nss update callback + * @context: Adapter context + */ +struct s_nss_update_cmd { + uint32_t new_nss; + uint32_t session_id; + void *nss_update_cb; + void *context; + uint8_t next_action; +}; + +typedef struct tagSmeCmd { + tListElem Link; + eSmeCommandType command; + uint32_t sessionId; + union { + tScanCmd scanCmd; + tRoamCmd roamCmd; + tWmStatusChangeCmd wmStatusChangeCmd; + tSetKeyCmd setKeyCmd; + 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 sir_hw_mode set_hw_mode_cmd; + struct s_nss_update_cmd nss_update_cmd; + struct sir_dual_mac_config set_dual_mac_cmd; + } u; +} tSmeCmd; + +/*-------------------------------------------------------------------------- + Internal to SME + ------------------------------------------------------------------------*/ +tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac); +void sme_push_command(tpAniSirGlobal pMac, tSmeCmd *pCmd, bool fHighPriority); +void sme_process_pending_queue(tpAniSirGlobal pMac); +void sme_release_command(tpAniSirGlobal pMac, tSmeCmd *pCmd); +void purge_sme_session_cmd_list(tpAniSirGlobal pMac, uint32_t sessionId, + tDblLinkList *pList); +bool sme_command_pending(tpAniSirGlobal pMac); +bool pmc_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +bool qos_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +CDF_STATUS csr_process_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +CDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_roam_process_wm_status_change_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand); +void csr_reinit_roam_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_reinit_wm_status_change_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_reinit_set_key_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand); +void csr_release_command_set_key(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, bool fStopping); + +CDF_STATUS csr_is_valid_channel(tpAniSirGlobal pMac, uint8_t chnNum); +bool csr_roam_is_valid40_mhz_channel(tpAniSirGlobal pmac, uint8_t channel); + +CDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme); +CDF_STATUS sme_release_global_lock(tSmeStruct *psSme); + +#ifdef FEATURE_OEM_DATA_SUPPORT +CDF_STATUS oem_data_process_oem_data_req_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand); +#endif + +CDF_STATUS csr_process_add_sta_session_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand); +CDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg); +CDF_STATUS csr_process_del_sta_session_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand); +CDF_STATUS csr_process_del_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg); + +#ifdef FEATURE_WLAN_SCAN_PNO +CDF_STATUS pmc_set_preferred_network_list(tHalHandle hHal, + tpSirPNOScanReq pRequest, + uint8_t sessionId, + preferred_network_found_ind_cb + callbackRoutine, void *callbackContext); +#endif /* FEATURE_WLAN_SCAN_PNO */ +bool csr_roamGetConcurrencyConnectStatusForBmps(tpAniSirGlobal pMac); +#ifdef FEATURE_WLAN_TDLS +CDF_STATUS csr_tdls_send_mgmt_req(tHalHandle hHal, uint8_t sessionId, + tCsrTdlsSendMgmt * tdlsSendMgmt); +CDF_STATUS csr_tdls_send_link_establish_params(tHalHandle hHal, + uint8_t sessionId, const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams *tdlsLinkEstablishParams); +CDF_STATUS csr_tdls_add_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac); +CDF_STATUS csr_tdls_change_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams); +CDF_STATUS csr_tdls_del_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac); +CDF_STATUS csr_tdls_process_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +CDF_STATUS csr_tdls_process_link_establish(tpAniSirGlobal pMac, tSmeCmd *cmd); +CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, + void *pMsgBuf); +#endif /* FEATURE_WLAN_TDLS */ + +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ + defined(FEATURE_WLAN_LFR) +CDF_STATUS csr_flush_cfg_bg_scan_roam_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId); +CDF_STATUS csr_create_bg_scan_roam_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, const uint8_t *pChannelList, + const uint8_t numChannels); +CDF_STATUS csr_update_bg_scan_config_ini_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, eCsrBand eBand); +#endif + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS csr_create_roam_scan_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t *pChannelList, + uint8_t numChannels, + const eCsrBand eBand); +#endif + +ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue); +void active_list_cmd_timeout_handle(void *userData); +void csr_process_set_dual_mac_config(tpAniSirGlobal mac, tSmeCmd *command); +void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command); +void csr_process_nss_update_req(tpAniSirGlobal mac, tSmeCmd *command); +#endif /* #if !defined( __SMEINSIDE_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h new file mode 100644 index 000000000000..4ff54c72872b --- /dev/null +++ b/core/sme/inc/sme_internal.h @@ -0,0 +1,223 @@ +/* + * 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(__SMEINTERNAL_H) +#define __SMEINTERNAL_H + +/** + * \file sme_internal.h + * + * \brief prototype for SME internal structures and APIs used for SME and MAC + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_status.h" +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "host_diag_core_event.h" +#include "csr_link_list.h" +#include "sme_power_save.h" + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ + +/* Mask can be only have one bit set */ +typedef enum eSmeCommandType { + eSmeNoCommand = 0, + eSmeDropCommand, + /* this is not a command, it is to identify this is a CSR command */ + eSmeCsrCommandMask = 0x10000, + eSmeCommandScan, + eSmeCommandRoam, + eSmeCommandWmStatusChange, + eSmeCommandSetKey, + eSmeCommandAddStaSession, + eSmeCommandDelStaSession, +#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 */ + eSmeCommandEnterBmps, + eSmeCommandExitBmps, + eSmeCommandEnterUapsd, + eSmeCommandExitUapsd, + 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, + e_sme_command_set_hw_mode, + e_sme_command_nss_update, + e_sme_command_set_dual_mac_config, +} eSmeCommandType; + +typedef enum eSmeState { + SME_STATE_STOP, + SME_STATE_START, + SME_STATE_READY, +} eSmeState; + +#define SME_IS_START(pMac) (SME_STATE_STOP != (pMac)->sme.state) +#define SME_IS_READY(pMac) (SME_STATE_READY == (pMac)->sme.state) + +typedef struct sStatsExtEvent { + uint32_t vdev_id; + uint32_t event_data_len; + uint8_t event_data[]; +} tStatsExtEvent, *tpStatsExtEvent; + +#define MAX_ACTIVE_CMD_STATS 16 + +typedef struct sActiveCmdStats { + eSmeCommandType command; + uint32_t reason; + uint32_t sessionId; + uint64_t timestamp; +} tActiveCmdStats; + +typedef struct sSelfRecoveryStats { + tActiveCmdStats activeCmdStats[MAX_ACTIVE_CMD_STATS]; + uint8_t cmdStatsIndx; +} tSelfRecoveryStats; + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/* GTK Offload Information Callback declaration */ +typedef void (*gtk_offload_get_info_callback)(void *callback_context, + tpSirGtkOffloadGetInfoRspParams + pGtkOffloadGetInfoRsp); +#endif +#ifdef FEATURE_WLAN_SCAN_PNO +/*Pref netw found Cb declaration*/ +typedef void (*preferred_network_found_ind_cb)(void *callback_context, + tpSirPrefNetworkFoundInd + pPrefNetworkFoundInd); +#endif + +typedef void (*ocb_callback)(void *context, void *response); +typedef void (*sme_set_thermal_level_callback)(void *context, u_int8_t level); + +typedef struct tagSmeStruct { + eSmeState state; + cdf_mutex_t lkSmeGlobalLock; + uint32_t totalSmeCmd; + void *pSmeCmdBufAddr; + tDblLinkList smeCmdActiveList; + tDblLinkList smeCmdPendingList; + tDblLinkList smeCmdFreeList; /* preallocated roam cmd list */ + tCDF_CON_MODE currDeviceMode; +#ifdef FEATURE_WLAN_LPHB + void (*pLphbIndCb)(void *pHddCtx, tSirLPHBInd *indParam); +#endif /* FEATURE_WLAN_LPHB */ + /* pending scan command list */ + tDblLinkList smeScanCmdPendingList; + /* active scan command list */ + tDblLinkList smeScanCmdActiveList; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + host_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 */ + uint8_t max_intf_count; + void (*StatsExtCallback)(void *, tStatsExtEvent *); + /* linkspeed callback */ + void (*pLinkSpeedIndCb)(tSirLinkSpeedInfo *indParam, + void *pDevContext); + void *pLinkSpeedCbContext; +#ifdef FEATURE_WLAN_EXTSCAN + void (*pExtScanIndCb)(void *, const uint16_t, void *); +#endif /* FEATURE_WLAN_EXTSCAN */ +#ifdef WLAN_FEATURE_NAN + void (*nanCallback)(void *, tSirNanEvent *); +#endif + bool enableSelfRecovery; + tCsrLinkStatusCallback linkStatusCallback; + void *linkStatusContext; + /* get temperature event context and callback */ + void *pTemperatureCbContext; + void (*pGetTemperatureCb)(int temperature, void *context); + uint8_t miracast_value; + struct ps_global_info ps_global_info; +#ifdef WLAN_FEATURE_GTK_OFFLOAD + /* routine to call for GTK Offload Information */ + gtk_offload_get_info_callback gtk_offload_get_info_cb; + /* value to be passed as parameter to routine specified above */ + void *gtk_offload_get_info_cb_context; +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ +#ifdef FEATURE_WLAN_SCAN_PNO + /* routine to call for Preferred Network Found Indication */ + preferred_network_found_ind_cb pref_netw_found_cb; + /* value to be passed as parameter to routine specified above */ + void *preferred_network_found_ind_cb_ctx; +#endif /* FEATURE_WLAN_SCAN_PNO */ + void (*rssi_threshold_breached_cb)(void *, struct rssi_breach_event *); +#ifdef WLAN_FEATURE_MEMDUMP + void (*fw_dump_callback)(void *context, struct fw_dump_rsp *rsp); +#endif + hw_mode_transition_cb sme_hw_mode_trans_cb; + /* 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; + sme_set_thermal_level_callback set_thermal_level_cb; +} tSmeStruct, *tpSmeStruct; + +#endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/inc/sme_power_save.h b/core/sme/inc/sme_power_save.h new file mode 100644 index 000000000000..295f644dbd45 --- /dev/null +++ b/core/sme/inc/sme_power_save.h @@ -0,0 +1,152 @@ +/* + * 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(__SME_POWER_SAVE_H) +#define __SME_POWER_SAVE_H +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "ani_system_defs.h" +#include "sir_api.h" + +#define MAX_SME_SESSIONS 5 +/* Auto Ps Entry Timer Default value - 1000 ms */ +#define AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE 1000 + +/* Auto Deferred Ps Entry Timer value - 20000 ms */ +#define AUTO_DEFERRED_PS_ENTRY_TIMER_DEFAULT_VALUE 20000 + + + +/** + * enum ps_state - State of the power save + * @FULL_POWER_MODE: for Full power mode + * @LEGACY_POWER_SAVE_MODE: For Legacy Power Save mode + * @UAPSD_MODE: for UAPSD power save + */ + +enum ps_state { + FULL_POWER_MODE, + LEGACY_POWER_SAVE_MODE, + UAPSD_MODE +}; + +/** + * struct ps_params - maintain power save state and USAPD params + * @mac_ctx: mac_ctx + * @session_id: Session Id. + * @ps_state : State of the power save + * @uapsd_per_ac_trigger_enable_mask: dynamic UPASD mask setting + * derived from AddTS Rsp and DelTS frame. + * If a particular AC bit is set, it means AC is trigger enabled. + * @uapsd_per_ac_delivery_enable_mask: dynamic UPASD mask setting + * derived from AddTS Rsp and DelTs frame. + * If a particular AC bit is set, it means AC is delivery enabled. + * @ac_admit_mask: used 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 + * @ uapsd_per_ac_bit_mask: 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. + * @enter_wowl_callback_routine: routine to call for wowl request. + * @enter_wowl_callback_context: value to be passed as parameter to + * routine specified above. + * @wowl_enter_params: WOWL mode configuration. + * @wake_reason_ind_cb: routine to call for wake reason indication. + * @wake_reason_ind_cb_ctx: value to be passed as parameter to + * routine specified above. + */ + +struct ps_params { + void *mac_ctx; + uint32_t session_id; + enum ps_state ps_state; + uint8_t uapsd_per_ac_trigger_enable_mask; + uint8_t uapsd_per_ac_delivery_enable_mask; + uint8_t ac_admit_mask[SIR_MAC_DIRECTION_DIRECT]; + uint8_t uapsd_per_ac_bit_mask; + /* WOWL param */ + void (*enter_wowl_callback_routine)(void *callback_context, + CDF_STATUS status); + void *enter_wowl_callback_context; + tSirSmeWowlEnterParams wowl_enter_params; +#ifdef WLAN_WAKEUP_EVENTS + void (*wake_reason_ind_cb)(void *callback_context, + tpSirWakeReasonInd wake_reason_ind); + void *wake_reason_ind_cb_ctx; +#endif /* WLAN_WAKEUP_EVENTS */ +#ifdef FEATURE_WLAN_TDLS + bool is_tdls_power_save_prohibited; +#endif + /* + * Auto Sta Ps Enable Timer + * Upon expiration of this timer + * Power Save Offload module will + * try to enable sta mode ps + */ + cdf_mc_timer_t auto_ps_enable_timer; + +}; + +/** + * struct ps_global_info - global struct for Power save information + * @ps_enabled: Power Save is enabled or not in ini + * @ps_params: maintain power save state and USAPD params + */ +struct ps_global_info { + bool ps_enabled; + struct ps_params ps_params[MAX_SME_SESSIONS]; + /* Remain in Power active till DHCP completes */ + bool remain_in_power_active_till_dhcp; +}; + +/** + * enum sme_ps_cmd: power save message to send WMA + * @SME_PS_ENABLE: For power save enable. + * @SME_PS_DISABLE: for Power save disable. + * @SME_PS_UAPSD_ENABLE; for UAPSD enable. + * @SME_PS_UAPSD_DISABLE: for UAPSD disable. + * @SME_PS_WOWL_ENTER: for WOWL Enter. + * @SME_PS_WOWL_EXIT: for WOWL Exit. + * @SME_PS_WOWL_ADD_BCAST_PTRN: Add bcst WOWL pattern. + * @SME_PS_WOWL_DEL_BCAST_PTRN: Del Bcsr Wowl Pattern. + */ +enum sme_ps_cmd { + SME_PS_ENABLE = 0, + SME_PS_DISABLE, + SME_PS_UAPSD_ENABLE, + SME_PS_UAPSD_DISABLE, + SME_PS_WOWL_ENTER, + SME_PS_WOWL_EXIT, + SME_PS_WOWL_ADD_BCAST_PTRN, + SME_PS_WOWL_DEL_BCAST_PTRN, +}; + +#endif diff --git a/core/sme/inc/sme_power_save_api.h b/core/sme/inc/sme_power_save_api.h new file mode 100644 index 000000000000..e4fa67b7e167 --- /dev/null +++ b/core/sme/inc/sme_power_save_api.h @@ -0,0 +1,97 @@ +/* + * 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(__SME_POWER_SAVE_API_H) +#define __SME_POWER_SAVE_API_H + +#include "sme_power_save.h" +#include "ani_global.h" +#include "sme_inside.h" + +CDF_STATUS sme_ps_enable_disable(tHalHandle hal_ctx, uint32_t session_id, + enum sme_ps_cmd command); + +CDF_STATUS sme_ps_uapsd_enable(tHalHandle hal_ctx, uint32_t session_id); + +CDF_STATUS sme_ps_uapsd_disable(tHalHandle hal_ctx, uint32_t session_id); + +/* Condition check if driver is ready to enter in PS */ +CDF_STATUS sme_enable_sta_ps_check(tpAniSirGlobal mac_ctx, uint32_t session_id); + +CDF_STATUS sme_ps_process_command(tpAniSirGlobal mac_ctx, + uint32_t session_id, + enum sme_ps_cmd command); + +void sme_set_tspec_uapsd_mask_per_session(tpAniSirGlobal mac_ctx, + tSirMacTSInfo *ts_info, + uint8_t session_id); +/* Full Power Req Callback */ +typedef void (*uapsd_start_indication_cb)(void *callback_context, + uint32_t session_id, CDF_STATUS status); + +CDF_STATUS sme_ps_start_uapsd(tHalHandle hal_ctx, uint32_t session_id, + uapsd_start_indication_cb uapsd_start_ind_cb, + void *callback_context); +CDF_STATUS sme_set_ps_host_offload(tHalHandle hal_ctx, + tpSirHostOffloadReq request, + uint8_t session_id); + +#ifdef WLAN_NS_OFFLOAD +CDF_STATUS sme_set_ps_ns_offload(tHalHandle hal_ctx, + tpSirHostOffloadReq request, + uint8_t session_id); + +#endif /* WLAN_NS_OFFLOAD */ +/* / Post a message to PE module */ +tSirRetStatus sme_post_pe_message(tpAniSirGlobal mac_ctx, tpSirMsgQ pMsg); + +CDF_STATUS sme_ps_enable_auto_ps_timer(tHalHandle hal_ctx, + uint32_t sessionId, + bool isReassoc); +CDF_STATUS sme_ps_disable_auto_ps_timer(tHalHandle hal_ctx, + uint32_t sessionId); + +CDF_STATUS sme_ps_open(tHalHandle hal_ctx); + +CDF_STATUS sme_ps_open_per_session(tHalHandle hal_ctx, uint32_t session_id); + +void sme_auto_ps_entry_timer_expired(void *ps_param); +CDF_STATUS sme_ps_close(tHalHandle hal_ctx); +CDF_STATUS sme_ps_close_per_session(tHalHandle hal_ctx, uint32_t sessionId); + +CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, + tpSirPNOScanReq request, + uint8_t session_id, + preferred_network_found_ind_cb + callback_routine, + void *callback_context); + +CDF_STATUS sme_is_auto_ps_timer_running(tHalHandle hal_ctx, + uint32_t session_id); + +#endif /* #if !defined(__SME_POWER_SAVE_API_H) */ + diff --git a/core/sme/inc/sme_qos_api.h b/core/sme/inc/sme_qos_api.h new file mode 100644 index 000000000000..2dd02de6511a --- /dev/null +++ b/core/sme/inc/sme_qos_api.h @@ -0,0 +1,257 @@ +/* + * 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(__SME_QOSAPI_H) +#define __SME_QOSAPI_H + +/** + * \file sme_qos_api.h + * + * \brief prototype for SME QoS APIs + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "ani_global.h" +#include "sir_api.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 + +/*--------------------------------------------------------------------------- + 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, + /* sync or async: in case of async notify 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 + * (CDF_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 + * (CDF_STATUS_E_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, + /* sync or async: in case of async notify HDD with current QoS Param */ + 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, + /* sync or async: in case of async notify HDD with current QoS Param */ + 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 + * (CDF_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 + * (CDF_STATUS_E_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:powersave mode changed by PMC from UAPSD to Full power */ + SME_QOS_STATUS_OUT_OF_APSD_POWER_MODE_IND = 400, + /* async:powersave 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 { + uint8_t burst_size_defn; + sme_QosWmmAckPolicyType ack_policy; + sme_QosWmmUpType up; /* User priority */ + uint8_t psb; /* power-save bit */ + sme_QosWmmDirType direction; /* Direction */ + uint8_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; + uint16_t nominal_msdu_size; + uint16_t maximum_msdu_size; + uint32_t min_service_interval; + uint32_t max_service_interval; + uint32_t inactivity_interval; + uint32_t suspension_interval; + uint32_t svc_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t max_burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw_allowance; + uint16_t medium_time; +} sme_QosWmmTspecInfo; + +/*-------------------------------------------------------------------------- + External APIs + ------------------------------------------------------------------------*/ +typedef CDF_STATUS (*sme_QosCallback)(tHalHandle hHal, void *HDDcontext, + sme_QosWmmTspecInfo *pCurrentQoSInfo, + sme_QosStatusType status, uint32_t QosFlowID); +sme_QosStatusType sme_qos_setup_req(tHalHandle hHal, uint32_t sessionId, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosCallback QoSCallback, void *HDDcontext, + sme_QosWmmUpType UPType, uint32_t *pQosFlowID); +sme_QosStatusType sme_qos_modify_req(tHalHandle hHal, + sme_QosWmmTspecInfo *pQoSInfo, uint32_t QosFlowID); +sme_QosStatusType sme_qos_release_req(tHalHandle hHal, uint32_t QosFlowID); +bool sme_qos_is_ts_info_ack_policy_valid(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, uint8_t sessionId); +void sme_qos_update_hand_off(uint8_t sessionId, bool updateHandOff); +CDF_STATUS sme_update_dsc_pto_up_mapping(tHalHandle hHal, + sme_QosWmmUpType *dscpmapping, uint8_t sessionId); + +CDF_STATUS sme_offload_qos_process_out_of_uapsd_mode(tpAniSirGlobal mac_ctx, + uint32_t session_id); +CDF_STATUS sme_offload_qos_process_into_uapsd_mode(tpAniSirGlobal mac_ctx, + uint32_t session_id); +bool sme_qos_tspec_active(tpAniSirGlobal pMac, sme_ac_enum_type ac, + uint8_t sessionId, uint8_t *pActiveTspec); + +#endif /* #if !defined( __SME_QOSAPI_H ) */ diff --git a/core/sme/inc/sme_qos_internal.h b/core/sme/inc/sme_qos_internal.h new file mode 100644 index 000000000000..f3db9e5d1d02 --- /dev/null +++ b/core/sme/inc/sme_qos_internal.h @@ -0,0 +1,138 @@ +/* + * 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(__SMEQOSINTERNAL_H) +#define __SMEQOSINTERNAL_H + +/** + * \file sme_qos_internal.h + * + * \brief prototype for SME QoS APIs + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "ani_global.h" +#include "sir_api.h" +#include "sme_qos_api.h" +#include "sme_internal.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_qos_csr_event_indType; + +#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 + ------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_open(tpAniSirGlobal pMac); +CDF_STATUS sme_qos_close(tpAniSirGlobal pMac); +CDF_STATUS sme_qos_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, + void *pMsgBuf); + +/*-------------------------------------------------------------------------- + Internal APIs for CSR + ------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_validate_params(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc); +CDF_STATUS sme_qos_csr_event_ind(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_qos_csr_event_indType ind, void *pEvent_info); +uint8_t sme_qos_get_acm_mask(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes); +#ifdef FEATURE_WLAN_ESE +uint8_t sme_qos_ese_retrieve_tspec_info(tpAniSirGlobal pMac, uint8_t sessionId, + tTspecInfo * pTspecInfo); +#endif + +#endif /* #if !defined( __SMEQOSINTERNAL_H ) */ diff --git a/core/sme/inc/sme_rrm_api.h b/core/sme/inc/sme_rrm_api.h new file mode 100644 index 000000000000..743c77e8b23a --- /dev/null +++ b/core/sme/inc/sme_rrm_api.h @@ -0,0 +1,67 @@ +/* + * 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_rrm_api.h + * + * \brief prototype for SME RRM APIs + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "ani_global.h" +#include "sir_api.h" +#include "sme_internal.h" +#include "sme_rrm_internal.h" + +CDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, + void *pMsgBuf); +CDF_STATUS rrm_close(tpAniSirGlobal pMac); +CDF_STATUS rrm_ready(tpAniSirGlobal pMac); +CDF_STATUS rrm_open(tpAniSirGlobal pMac); +CDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, + tpRrmConfigParam pRrmConfig); +CDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, + uint8_t sessionId, tpRrmNeighborReq pNeighborReq, + tpRrmNeighborRspCallbackInfo callbackInfo); +tRrmNeighborReportDesc *sme_rrm_get_first_bss_entry_from_neighbor_cache( + tpAniSirGlobal pMac); +tRrmNeighborReportDesc *sme_rrm_get_next_bss_entry_from_neighbor_cache( + tpAniSirGlobal pMac, + tpRrmNeighborReportDesc pBssEntry); +CDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, + void *pMsgBuf); + +#endif diff --git a/core/sme/inc/sme_rrm_internal.h b/core/sme/inc/sme_rrm_internal.h new file mode 100644 index 000000000000..76415d5c84ff --- /dev/null +++ b/core/sme/inc/sme_rrm_internal.h @@ -0,0 +1,108 @@ +/* + * 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 sme_rrm_internal.h + * + * \brief prototype for SME RRM APIs + */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_lock.h" +#include "cdf_trace.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "rrm_global.h" + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +typedef struct sRrmConfigParam { + uint8_t rrmEnabled; + uint8_t maxRandnInterval; +} tRrmConfigParam, *tpRrmConfigParam; + +typedef struct sRrmNeighborReportDesc { + tListElem List; + tSirNeighborBssDescription *pNeighborBssDescription; + uint32_t roamScore; + uint8_t sessionId; +} tRrmNeighborReportDesc, *tpRrmNeighborReportDesc; + +typedef void (*NeighborReportRspCallback)(void *context, + CDF_STATUS cdf_status); + +typedef struct sRrmNeighborRspCallbackInfo { + uint32_t timeout; /* in ms.. min value is 10 (10ms) */ + NeighborReportRspCallback neighborRspCallback; + void *neighborRspCallbackContext; +} tRrmNeighborRspCallbackInfo, *tpRrmNeighborRspCallbackInfo; + +typedef struct sRrmNeighborRequestControlInfo { + /* To check whether a neighbor req is already sent & response pending */ + bool isNeighborRspPending; + cdf_mc_timer_t neighborRspWaitTimer; + tRrmNeighborRspCallbackInfo neighborRspCallbackInfo; +} tRrmNeighborRequestControlInfo, *tpRrmNeighborRequestControlInfo; + +typedef struct sRrmSMEContext { + uint16_t token; + struct cdf_mac_addr sessionBssId; + uint8_t regClass; + /* list of all channels to be measured. */ + tCsrChannelInfo channelList; + uint8_t currentIndex; + /* SSID used in the measuring beacon report. */ + tAniSSID ssId; + tSirMacAddr bssId; /* bssid used for beacon report measurement. */ + /* Randomization interval to be used in subsequent measurements. */ + uint16_t randnIntvl; + uint16_t duration[SIR_ESE_MAX_MEAS_IE_REQS]; + uint8_t measMode[SIR_ESE_MAX_MEAS_IE_REQS]; + tRrmConfigParam rrmConfig; + cdf_mc_timer_t IterMeasTimer; + tDblLinkList neighborReportCache; + tRrmNeighborRequestControlInfo neighborReqControlInfo; + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrEseBeaconReq eseBcnReqInfo; + bool eseBcnReqInProgress; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + tRrmMsgReqSource msgSource; +} tRrmSMEContext, *tpRrmSMEContext; + +typedef struct sRrmNeighborReq { + uint8_t no_ssid; + tSirMacSSid ssid; +} tRrmNeighborReq, *tpRrmNeighborReq; + +#endif /* #if !defined( __SMERRMINTERNAL_H ) */ diff --git a/core/sme/inc/sme_trace.h b/core/sme/inc/sme_trace.h new file mode 100644 index 000000000000..7bd1fecdd9c9 --- /dev/null +++ b/core/sme/inc/sme_trace.h @@ -0,0 +1,137 @@ +/* + * 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 + */ + +#ifndef __SME_TRACE_H__ +#define __SME_TRACE_H__ + +#include "mac_trace.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_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_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_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, +}; + +void sme_trace_init(tpAniSirGlobal pMac); +#endif /* __SME_TRACE_H__ */ diff --git a/core/sme/inc/sms_debug.h b/core/sme/inc/sms_debug.h new file mode 100644 index 000000000000..adebc13604be --- /dev/null +++ b/core/sme/inc/sms_debug.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/** + * \file cssDebug.h + * + * Define debug log interface for SMS. + */ + +#ifndef SMS_DEBUG_H__ +#define SMS_DEBUG_H__ + +#include "utils_api.h" +#include "sir_debug.h" + +#if !defined(__printf) +#define __printf(a, b) +#endif + +void __printf(3, 4) + sms_log(tpAniSirGlobal pMac, uint32_t loglevel, + const char *pString, ...); + +#endif /* __SMS_DEBUG_H__ */ diff --git a/core/sme/inc/wlan_ps_wow_diag.h b/core/sme/inc/wlan_ps_wow_diag.h new file mode 100644 index 000000000000..3d1cbc3d2b91 --- /dev/null +++ b/core/sme/inc/wlan_ps_wow_diag.h @@ -0,0 +1,136 @@ +/* + * 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 "host_diag_core_event.h" +#include "host_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_ENTER_FULL_POWER_REQ = 7, + WLAN_PMC_CURRENT_STATE = 8, + WLAN_PS_MODE_ENABLE_REQ = 9, + WLAN_PS_MODE_DISABLE_REQ = 10, + WLAN_WINMOB_D_POWER_STATE = 11, + WLAN_BMPS_DTIM_PERIOD = 12, + WLAN_BMPS_FINAL_LI = 13, + WLAN_BMPS_SET_CONFIG = 14, + +} wlan_ps_evt_subtype_t; + +/* maps directly to eRequestFullPowerReason */ +typedef enum { + /* PE received a MAX_MISSED_BEACON_IND */ + WLAN_MISSED_BEACON_IND_RCVD, + /* PE received a SIR_HAL_BMPS_STATUS_IND */ + WLAN_BMPS_STATUS_IND_RCVD, + /* BMPS mode was disabled by HDD in SME */ + WLAN_BMPS_MODE_DISABLED, + /* Link has been disconnected requested by HDD */ + WLAN_LINK_DISCONNECTED_BY_HDD, + /* Disconnect due to linklost or requested by peer */ + WLAN_LINK_DISCONNECTED_BY_OTHER, + /* HDD request full power for some reason */ + WLAN_FULL_PWR_NEEDED_BY_HDD, + /* BAP request full power for BT_AMP */ + WLAN_FULL_PWR_NEEDED_BY_BAP, + /* CSR requests full power */ + WLAN_FULL_PWR_NEEDED_BY_CSR, + /* QOS requests full power */ + WLAN_FULL_PWR_NEEDED_BY_QOS, + /* No specific reason. General reason code */ + WLAN_REASON_OTHER +} 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_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 */ + WLAN_UAPSD_MODE_POWER_SAVE, /* Unscheduled Auto PS Delivery Mode */ + WLAN_STANDBY_MODE_POWER_SAVE, /* Standby Power Save Mode */ + WLAN_WOWL_MODE_POWER_SAVE /* Wake-on-Wireless 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/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c new file mode 100644 index 000000000000..98a1f2607fc9 --- /dev/null +++ b/core/sme/src/common/sme_api.c @@ -0,0 +1,14610 @@ +/* + * 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 smeApi.c + + \brief Definitions for SME APIs + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "sms_debug.h" +#include "sme_api.h" +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "csr_internal.h" +#include "wma_types.h" +#include "wma_if.h" +#include "cdf_trace.h" +#include "sme_trace.h" +#include "cdf_types.h" +#include "cdf_trace.h" +#include "cds_utils.h" +#include "sap_api.h" +#include "mac_trace.h" +#ifdef WLAN_FEATURE_NAN +#include "nan_api.h" +#endif +#include "cds_regdomain_common.h" +#include "cfg_api.h" +#include "sme_power_save_api.h" +#include "wma.h" + +extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb); + +#define LOG_SIZE 256 +#define READ_MEMORY_DUMP_CMD 9 +#define TL_INIT_STATE 0 + +static tSelfRecoveryStats g_self_recovery_stats; +/* TxMB Functions */ +extern CDF_STATUS pmc_prepare_command(tpAniSirGlobal pMac, uint32_t sessionId, + eSmeCommandType cmdType, void *pvParam, + uint32_t size, tSmeCmd **ppCmd); +extern void pmc_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +extern void qos_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +extern CDF_STATUS p2p_process_remain_on_channel_cmd(tpAniSirGlobal pMac, + tSmeCmd *p2pRemainonChn); +extern CDF_STATUS sme_remain_on_chn_rsp(tpAniSirGlobal pMac, uint8_t *pMsg); +extern CDF_STATUS sme_mgmt_frm_ind(tHalHandle hHal, + tpSirSmeMgmtFrameInd pSmeMgmtFrm); +extern CDF_STATUS sme_remain_on_chn_ready(tHalHandle hHal, uint8_t *pMsg); +extern CDF_STATUS sme_send_action_cnf(tHalHandle hHal, uint8_t *pMsg); + +static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac); +static void sme_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fStopping); + +eCsrPhyMode sme_get_phy_mode(tHalHandle hHal); + +CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf); + +void sme_disconnect_connected_sessions(tpAniSirGlobal pMac); + +CDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac, + void *pMsgBuf); + +CDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId); +#endif + +#ifdef WLAN_FEATURE_11W +CDF_STATUS sme_unprotected_mgmt_frm_ind(tHalHandle hHal, + tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm); +#endif + +/* Message processor for events from DFS */ +CDF_STATUS dfs_msg_processor(tpAniSirGlobal pMac, + uint16_t msg_type, void *pMsgBuf); + +/* Channel Change Response Indication Handler */ +CDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac, + uint16_t msg_type, void *pMsgBuf); + +/* Internal SME APIs */ +CDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + + if (psSme) { + if (CDF_IS_STATUS_SUCCESS + (cdf_mutex_acquire(&psSme->lkSmeGlobalLock))) { + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +CDF_STATUS sme_release_global_lock(tSmeStruct *psSme) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + + if (psSme) { + if (CDF_IS_STATUS_SUCCESS + (cdf_mutex_release(&psSme->lkSmeGlobalLock))) { + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/** + * sme_process_set_hw_mode_resp() - Process set HW mode response + * @mac: Global MAC pointer + * @msg: HW mode response + * + * Processes the HW mode response and invokes the HDD callback + * to process further + */ +static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) +{ + tListElem *entry = NULL; + tSmeCmd *command = NULL; + bool found; + hw_mode_cb callback = NULL; + struct sir_set_hw_mode_resp *param; + + param = (struct sir_set_hw_mode_resp *)msg; + if (!param) { + sms_log(mac, LOGE, FL("HW mode resp param is NULL")); + /* Not returning. Need to check if active command list + * needs to be freed + */ + } + + entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac, LOGE, FL("No cmd found in active list")); + return CDF_STATUS_E_FAILURE; + } + + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (!command) { + sms_log(mac, LOGE, FL("Base address is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (e_sme_command_set_hw_mode != command->command) { + sms_log(mac, LOGE, FL("Command mismatch!")); + return CDF_STATUS_E_FAILURE; + } + + callback = command->u.set_hw_mode_cmd.set_hw_mode_cb; + if (callback) { + if (!param) { + sms_log(mac, LOGE, + FL("Callback failed since HW mode params is NULL")); + } else { + sms_log(mac, LOGE, + FL("Calling HDD callback for HW mode response")); + callback(param->status, + param->cfgd_hw_mode_index, + param->num_vdev_mac_entries, + param->vdev_mac_map); + } + } else { + sms_log(mac, LOGE, FL("Callback does not exist")); + } + + found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK); + if (found) { + /* Now put this command back on the avilable command list */ + sme_release_command(mac, command); + } + sme_process_pending_queue(mac); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_process_hw_mode_trans_ind() - Process HW mode transition indication + * @mac: Global MAC pointer + * @msg: HW mode transition response + * + * Processes the HW mode transition indication and invoke the HDD callback + * to process further + */ +static CDF_STATUS sme_process_hw_mode_trans_ind(tpAniSirGlobal mac, + uint8_t *msg) +{ + hw_mode_transition_cb callback = NULL; + struct sir_hw_mode_trans_ind *param; + + param = (struct sir_hw_mode_trans_ind *)msg; + if (!param) { + sms_log(mac, LOGE, FL("HW mode trans ind param is NULL")); + return CDF_STATUS_E_FAILURE; + } + + callback = mac->sme.sme_hw_mode_trans_cb; + if (callback) { + sms_log(mac, LOGE, FL("Calling registered callback...")); + callback(param->old_hw_mode_index, + param->new_hw_mode_index, + param->num_vdev_mac_entries, + param->vdev_mac_map); + } + + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) +{ + CDF_STATUS status; + tSmeCmd *pCmd; + uint32_t cmd_idx; + CDF_STATUS cdf_status; + cdf_mc_timer_t *cmdTimeoutTimer = NULL; + + pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND; + + status = csr_ll_open(pMac->hHdd, &pMac->sme.smeCmdActiveList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + + status = csr_ll_open(pMac->hHdd, &pMac->sme.smeCmdPendingList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + + status = csr_ll_open(pMac->hHdd, &pMac->sme.smeScanCmdActiveList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + + status = csr_ll_open(pMac->hHdd, &pMac->sme.smeScanCmdPendingList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + + status = csr_ll_open(pMac->hHdd, &pMac->sme.smeCmdFreeList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + + pCmd = cdf_mem_malloc(sizeof(tSmeCmd) * pMac->sme.totalSmeCmd); + if (NULL == pCmd) + status = CDF_STATUS_E_NOMEM; + else { + status = CDF_STATUS_SUCCESS; + + cdf_mem_set(pCmd, sizeof(tSmeCmd) * pMac->sme.totalSmeCmd, 0); + pMac->sme.pSmeCmdBufAddr = pCmd; + + for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { + csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, + &pCmd[cmd_idx].Link, LL_ACCESS_LOCK); + } + } + + /* This timer is only to debug the active list command timeout */ + + cmdTimeoutTimer = + (cdf_mc_timer_t *) cdf_mem_malloc(sizeof(cdf_mc_timer_t)); + if (cmdTimeoutTimer) { + pMac->sme.smeCmdActiveList.cmdTimeoutTimer = cmdTimeoutTimer; + cdf_status = + cdf_mc_timer_init(pMac->sme.smeCmdActiveList. + cmdTimeoutTimer, CDF_TIMER_TYPE_SW, + active_list_cmd_timeout_handle, (void *)pMac); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Init Timer fail for active list command process time out"); + cdf_mem_free(pMac->sme.smeCmdActiveList. + cmdTimeoutTimer); + pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL; + } else { + pMac->sme.smeCmdActiveList.cmdTimeoutDuration = + CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE; + } + } + +end: + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGE, "failed to initialize sme command list:%d\n", + status); + + return status; +} + +void sme_release_command(tpAniSirGlobal pMac, tSmeCmd *pCmd) +{ + pCmd->command = eSmeNoCommand; + csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK); +} + +static void sme_release_cmd_list(tpAniSirGlobal pMac, tDblLinkList *pList) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + + while ((pEntry = csr_ll_remove_head(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); + sme_abort_command(pMac, pCommand, true); + } +} + +static void purge_sme_cmd_list(tpAniSirGlobal pMac) +{ + /* release any out standing commands back to free command list */ + sme_release_cmd_list(pMac, &pMac->sme.smeCmdPendingList); + sme_release_cmd_list(pMac, &pMac->sme.smeCmdActiveList); + sme_release_cmd_list(pMac, &pMac->sme.smeScanCmdPendingList); + sme_release_cmd_list(pMac, &pMac->sme.smeScanCmdActiveList); +} + +void purge_sme_session_cmd_list(tpAniSirGlobal pMac, uint32_t sessionId, + tDblLinkList *pList) +{ + /* release any out standing commands back to free command list */ + tListElem *pEntry, *pNext; + tSmeCmd *pCommand; + tDblLinkList localList; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return; + } + + csr_ll_lock(pList); + pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK); + while (pEntry != NULL) { + pNext = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (pCommand->sessionId == sessionId) { + if (csr_ll_remove_entry(pList, pEntry, LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntry, + LL_ACCESS_NOLOCK); + } + } + pEntry = pNext; + } + csr_ll_unlock(pList); + + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sme_abort_command(pMac, pCommand, true); + } + csr_ll_close(&localList); +} + +static CDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + purge_sme_cmd_list(pMac); + csr_ll_close(&pMac->sme.smeCmdPendingList); + csr_ll_close(&pMac->sme.smeCmdActiveList); + csr_ll_close(&pMac->sme.smeScanCmdPendingList); + csr_ll_close(&pMac->sme.smeScanCmdActiveList); + csr_ll_close(&pMac->sme.smeCmdFreeList); + + /*destroy active list command time out timer */ + cdf_mc_timer_destroy(pMac->sme.smeCmdActiveList.cmdTimeoutTimer); + cdf_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer); + pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL; + + status = cdf_mutex_acquire(&pMac->sme.lkSmeGlobalLock); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, + FL("Failed to acquire the lock status = %d"), status); + goto done; + } + + if (NULL != pMac->sme.pSmeCmdBufAddr) { + cdf_mem_free(pMac->sme.pSmeCmdBufAddr); + pMac->sme.pSmeCmdBufAddr = NULL; + } + + status = cdf_mutex_release(&pMac->sme.lkSmeGlobalLock); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, + FL("Failed to release the lock status = %d"), status); + } +done: + return status; +} + +void dump_csr_command_info(tpAniSirGlobal pMac, tSmeCmd *pCmd) +{ + switch (pCmd->command) { + case eSmeCommandScan: + sms_log(pMac, LOGE, " scan command reason is %d", + pCmd->u.scanCmd.reason); + break; + + case eSmeCommandRoam: + sms_log(pMac, LOGE, " roam command reason is %d", + pCmd->u.roamCmd.roamReason); + break; + + case eSmeCommandWmStatusChange: + sms_log(pMac, LOGE, " WMStatusChange command type is %d", + pCmd->u.wmStatusChangeCmd.Type); + break; + + case eSmeCommandSetKey: + sms_log(pMac, LOGE, " setKey command auth(%d) enc(%d)", + pCmd->u.setKeyCmd.authType, pCmd->u.setKeyCmd.encType); + break; + + default: + sms_log(pMac, LOGE, " default: Unhandled command %d", + pCmd->command); + break; + } +} + +tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac) +{ + tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL; + tListElem *pEntry; + static int sme_command_queue_full; + + pEntry = csr_ll_remove_head(&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 tfhe message buffers). */ + if (pEntry) { + pRetCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + /* reset when free list is available */ + sme_command_queue_full = 0; + } else { + int idx = 1; + + /* Cannot change pRetCmd here since it needs to return later. */ + pEntry = + csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + } + sms_log(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 */ + dump_csr_command_info(pMac, pTempCmd); + } + } /* if(pTempCmd) */ + + /* dump what is in the pending queue */ + csr_ll_lock(&pMac->sme.smeCmdPendingList); + pEntry = + csr_ll_peek_head(&pMac->sme.smeCmdPendingList, + LL_ACCESS_NOLOCK); + while (pEntry && !sme_command_queue_full) { + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + /* Print only 1st five commands from pending queue. */ + if (idx <= 5) + sms_log(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 */ + dump_csr_command_info(pMac, pTempCmd); + } + pEntry = + csr_ll_next(&pMac->sme.smeCmdPendingList, pEntry, + LL_ACCESS_NOLOCK); + } + /* Increment static variable so that it prints + * pending command only once + */ + sme_command_queue_full++; + + csr_ll_unlock(&pMac->sme.smeCmdPendingList); + + /* There may be some more command in CSR's own pending queue */ + csr_ll_lock(&pMac->roam.roamCmdPendingList); + pEntry = + csr_ll_peek_head(&pMac->roam.roamCmdPendingList, + LL_ACCESS_NOLOCK); + while (pEntry) { + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sms_log(pMac, LOGE, + "Out of command buffer.... CSR pending command #%d (0x%X)", + idx++, pTempCmd->command); + dump_csr_command_info(pMac, pTempCmd); + pEntry = + csr_ll_next(&pMac->roam.roamCmdPendingList, pEntry, + LL_ACCESS_NOLOCK); + } + csr_ll_unlock(&pMac->roam.roamCmdPendingList); + } + + /* memset to zero */ + if (pRetCmd) { + cdf_mem_set((uint8_t *)&pRetCmd->command, + sizeof(pRetCmd->command), 0); + cdf_mem_set((uint8_t *)&pRetCmd->sessionId, + sizeof(pRetCmd->sessionId), 0); + cdf_mem_set((uint8_t *)&pRetCmd->u, sizeof(pRetCmd->u), 0); + } + + return pRetCmd; +} + +void sme_push_command(tpAniSirGlobal pMac, tSmeCmd *pCmd, bool fHighPriority) +{ + if (!SME_IS_START(pMac)) { + sms_log(pMac, LOGE, FL("Sme in stop state")); + CDF_ASSERT(0); + return; + } + + if (fHighPriority) { + csr_ll_insert_head(&pMac->sme.smeCmdPendingList, &pCmd->Link, + LL_ACCESS_LOCK); + } else { + csr_ll_insert_tail(&pMac->sme.smeCmdPendingList, &pCmd->Link, + LL_ACCESS_LOCK); + } + + /* process the command queue... */ + sme_process_pending_queue(pMac); + + return; +} + +/* For commands that need to do extra cleanup. */ +static void sme_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fStopping) +{ + if (eSmePmcCommandMask & pCommand->command) { + sms_log(pMac, LOG1, + "No need to process PMC commands"); + return; + } + if (eSmeCsrCommandMask & pCommand->command) { + csr_abort_command(pMac, pCommand, fStopping); + return; + } + 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, + pCommand->u.remainChlCmd.scan_id); + } + } + sme_release_command(pMac, pCommand); + break; + default: + sme_release_command(pMac, pCommand); + break; + } + +} + +tListElem *csr_get_cmd_to_process(tpAniSirGlobal pMac, tDblLinkList *pList, + uint8_t sessionId, bool 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 = csr_ll_peek_head(pList, LL_ACCESS_LOCK); + while (pCurEntry) { + pCommand = GET_BASE_ADDR(pCurEntry, tSmeCmd, Link); + if (pCommand->sessionId != sessionId) { + sms_log(pMac, LOG1, + "selected the command with different sessionId"); + return pCurEntry; + } + + pCurEntry = csr_ll_next(pList, pCurEntry, fInterlocked); + } + + sms_log(pMac, LOG1, "No command pending with different sessionId"); + return NULL; +} + +bool sme_process_scan_queue(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pSmeEntry = NULL; + tSmeCmd *pSmeCommand = NULL; + bool status = true; + + if ((!csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList, + LL_ACCESS_LOCK))) { + pSmeEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (pSmeEntry) + pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link); + } + csr_ll_lock(&pMac->sme.smeScanCmdActiveList); + if (csr_ll_is_list_empty(&pMac->sme.smeScanCmdPendingList, + LL_ACCESS_LOCK)) + goto end; + pEntry = csr_ll_peek_head(&pMac->sme.smeScanCmdPendingList, + LL_ACCESS_LOCK); + if (!pEntry) + goto end; + + sms_log(pMac, LOGE, + FL("scan_count in active scanlist %d "), + pMac->sme.smeScanCmdActiveList.Count); + + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (pSmeCommand != NULL) { + /* + * if scan is running on one interface and SME receives + * the next command on the same interface then + * dont the allow the command to be queued to + * smeCmdPendingList. If next scan is allowed on + * the same interface the CSR state machine will + * get screwed up. + */ + if (pSmeCommand->sessionId == pCommand->sessionId) { + status = 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)) { + sms_log(pMac, LOGE, + FL("Can't process cmd(%d), waiting for key"), + pCommand->command); + status = false; + goto end; + } + } + if (csr_ll_remove_entry(&pMac->sme.smeScanCmdPendingList, pEntry, + LL_ACCESS_LOCK)) { + csr_ll_insert_head(&pMac->sme.smeScanCmdActiveList, + &pCommand->Link, LL_ACCESS_NOLOCK); + switch (pCommand->command) { + case eSmeCommandScan: + sms_log(pMac, LOG1, FL("Processing scan offload cmd.")); + cdf_mc_timer_start(&pCommand->u.scanCmd.csr_scan_timer, + CSR_ACTIVE_SCAN_LIST_CMD_TIMEOUT); + csr_process_scan_command(pMac, pCommand); + break; + case eSmeCommandRemainOnChannel: + sms_log(pMac, LOG1, + FL("Processing remain on channel offload cmd")); + p2p_process_remain_on_channel_cmd(pMac, pCommand); + break; + default: + sms_log(pMac, LOGE, + FL("Wrong cmd enqueued to ScanCmdPendingList")); + pEntry = csr_ll_remove_head( + &pMac->sme.smeScanCmdActiveList, + LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sme_release_command(pMac, pCommand); + break; + } + } +end: + csr_ll_unlock(&pMac->sme.smeScanCmdActiveList); + return status; +} + +/** + * sme_process_command() - processes SME commnd + * @mac_ctx: mac global context + * + * This function is called by sme_process_pending_queue() in a while loop + * + * Return: true indicates that caller function can proceed to next cmd + * false otherwise. + */ +bool sme_process_command(tpAniSirGlobal pMac) +{ + bool fContinue = false; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pSmeEntry; + tSmeCmd *pSmeCommand; + + /* + * if the ActiveList is empty, then nothing is active so we can process + * a pending command... + * alwasy lock active list before locking pending list + */ + csr_ll_lock(&pMac->sme.smeCmdActiveList); + if (!csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList, + LL_ACCESS_NOLOCK)) { + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + goto process_scan_q; + } + + if (csr_ll_is_list_empty(&pMac->sme.smeCmdPendingList, + LL_ACCESS_LOCK)) { + /* No command waiting */ + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + goto process_scan_q; + } + + /* + * 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 (!csr_ll_is_list_empty( + &pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK)) { + pSmeEntry = csr_ll_peek_head(&pMac->sme.smeScanCmdActiveList, + LL_ACCESS_LOCK); + if (pSmeEntry) { + pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link); + pEntry = csr_get_cmd_to_process(pMac, + &pMac->sme.smeCmdPendingList, + pSmeCommand->sessionId, + LL_ACCESS_LOCK); + goto sme_process_cmd; + } + } + + /* Peek the command */ + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK); +sme_process_cmd: + if (!pEntry) { + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + goto process_scan_q; + } + 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) + && !CSR_IS_SET_KEY_COMMAND(pCommand)) { + if (CSR_IS_CLOSE_SESSION_COMMAND(pCommand)) { + tSmeCmd *sme_cmd = NULL; + + sms_log(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 (status == CDF_STATUS_SUCCESS && sme_cmd) { + csr_ll_lock(&pMac->sme.smeCmdPendingList); + csr_ll_insert_head(&pMac->sme.smeCmdPendingList, + &sme_cmd->Link, LL_ACCESS_NOLOCK); + pEntry = csr_ll_peek_head( + &pMac->sme.smeCmdPendingList, + LL_ACCESS_NOLOCK); + csr_ll_unlock(&pMac->sme.smeCmdPendingList); + goto sme_process_cmd; + } + } + + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + sms_log(pMac, LOGE, + FL("SessionId %d: Can't process cmd(%d), waiting for key"), + pCommand->sessionId, pCommand->command); + fContinue = false; + goto process_scan_q; + } + + if (!csr_ll_remove_entry(&pMac->sme.smeCmdPendingList, pEntry, + LL_ACCESS_LOCK)) { + /* This is odd. Some one else pull off the command. */ + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + goto process_scan_q; + } + /* we can reuse the pCommand. Insert the command onto the ActiveList */ + csr_ll_insert_head(&pMac->sme.smeCmdActiveList, &pCommand->Link, + LL_ACCESS_NOLOCK); + /* .... and process the command. */ + MTRACE(cdf_trace(CDF_MODULE_ID_SME, TRACE_CODE_SME_COMMAND, + pCommand->sessionId, pCommand->command)); + + switch (pCommand->command) { + case eSmeCommandScan: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + status = csr_process_scan_command(pMac, pCommand); + break; + case eSmeCommandRoam: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + status = csr_roam_process_command(pMac, pCommand); + if (!CDF_IS_STATUS_SUCCESS(status) + && csr_ll_remove_entry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) + csr_release_command_roam(pMac, pCommand); + break; + case eSmeCommandWmStatusChange: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_roam_process_wm_status_change_command(pMac, pCommand); + break; + case eSmeCommandSetKey: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + status = csr_roam_process_set_key_command(pMac, pCommand); + if (!CDF_IS_STATUS_SUCCESS(status) + && csr_ll_remove_entry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) { + csr_release_command_set_key(pMac, pCommand); + } + break; + case eSmeCommandAddStaSession: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_process_add_sta_session_command(pMac, pCommand); + break; + case eSmeCommandDelStaSession: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_process_del_sta_session_command(pMac, pCommand); + break; +#ifdef FEATURE_OEM_DATA_SUPPORT + case eSmeCommandOemDataReq: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + oem_data_process_oem_data_req_command(pMac, pCommand); + break; +#endif + case eSmeCommandRemainOnChannel: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + p2p_process_remain_on_channel_cmd(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: + break; + case eSmeCommandAddTs: + case eSmeCommandDelTs: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + fContinue = qos_process_command(pMac, pCommand); + if (fContinue && csr_ll_remove_entry( + &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_NOLOCK)) { + /* The command failed, remove it */ + qos_release_command(pMac, pCommand); + } +#endif + break; +#ifdef FEATURE_WLAN_TDLS + case eSmeCommandTdlsSendMgmt: + case eSmeCommandTdlsAddPeer: + case eSmeCommandTdlsDelPeer: + case eSmeCommandTdlsLinkEstablish: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("sending TDLS Command 0x%x to PE"), + pCommand->command); + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + status = csr_tdls_process_cmd(pMac, pCommand); + break; +#endif + case e_sme_command_set_hw_mode: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_process_set_hw_mode(pMac, pCommand); + break; + case e_sme_command_nss_update: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_process_nss_update_req(pMac, pCommand); + break; + case e_sme_command_set_dual_mac_config: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + csr_process_set_dual_mac_config(pMac, pCommand); + break; + default: + /* something is wrong */ + /* remove it from the active list */ + sms_log(pMac, LOGE, FL("unknown command %d"), + pCommand->command); + pEntry = csr_ll_remove_head(&pMac->sme.smeCmdActiveList, + LL_ACCESS_NOLOCK); + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sme_release_command(pMac, pCommand); + status = CDF_STATUS_E_FAILURE; + break; + } + if (!CDF_IS_STATUS_SUCCESS(status)) + fContinue = true; +process_scan_q: + if (!(sme_process_scan_queue(pMac))) + fContinue = false; + return fContinue; +} + +void sme_process_pending_queue(tpAniSirGlobal pMac) +{ + while (sme_process_command(pMac)) + ; +} + +bool sme_command_pending(tpAniSirGlobal pMac) +{ + return !csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK) + || !csr_ll_is_list_empty(&pMac->sme.smeCmdPendingList, + LL_ACCESS_NOLOCK); +} + +/* Global APIs */ + +/** + * sme_open() - Initialze all SME modules and put them at idle state + * @hHal: The handle returned by mac_open + * + * The function initializes each module inside SME, PMC, 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 mac_open. + * + * Return: CDF_STATUS_SUCCESS - SME is successfully initialized. + * Other status means SME is failed to be initialized + */ +CDF_STATUS sme_open(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); +#ifndef WLAN_FEATURE_MBSSID + void *p_cds_gctx = cds_get_global_context(); +#endif + + pMac->sme.state = SME_STATE_STOP; + pMac->sme.currDeviceMode = CDF_STA_MODE; + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init( + &pMac->sme.lkSmeGlobalLock))) { + sms_log(pMac, LOGE, FL("sme_open failed init lock")); + return CDF_STATUS_E_FAILURE; + } + status = csr_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("csr_open failed, status=%d"), status); + return status; + } + + status = sme_ps_open(hHal); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("sme_ps_open failed during initialization with status=%d"), + status); + return status; + } +#ifdef FEATURE_WLAN_TDLS + pMac->is_tdls_power_save_prohibited = 0; +#endif + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + status = sme_qos_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Qos open, status=%d"), status); + return status; + } +#endif +#ifdef FEATURE_OEM_DATA_SUPPORT + status = oem_data_oem_data_req_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("oem_data_oem_data_req_open, status=%d"), + status); + return status; + } +#endif + status = init_sme_cmd_list(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; +#ifndef WLAN_FEATURE_MBSSID + if (NULL == p_cds_gctx) { + sms_log(pMac, LOGE, FL("p_cds_gctx is NULL")); + return CDF_STATUS_E_FAILURE; + } + status = wlansap_open(p_cds_gctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("wlansap_open failed, status=%d"), + status); + return status; + } +#endif + +#if defined WLAN_FEATURE_VOWIFI + status = rrm_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("rrm_open failed, status=%d"), status); + return status; + } +#endif + sme_p2p_open(pMac); + sme_trace_init(pMac); + return status; +} + +/* + * sme_init_chan_list, triggers channel setup based on country code. + */ +CDF_STATUS sme_init_chan_list(tHalHandle hal, uint8_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 = 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 mac_open. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return CDF_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, NO_SESSION, 0)); + if (NULL == pSmeConfigParams) { + sms_log(pMac, LOGE, + "Empty config param structure for SME, nothing to update"); + return status; + } + + status = csr_set_channels(hHal, &pSmeConfigParams->csrConfig); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_change_default_config_param failed with status=%d", + status); + } + return status; +} + +/** + * sme_set_scan_disable() - Dynamically enable/disable scan + * @h_hal: Handle to HAL + * + * This command gives the user an option to dynamically + * enable or disable scans. + * + * Return: None + */ +void sme_set_scan_disable(tHalHandle h_hal, int value) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal); + mac_ctx->lim.scan_disabled = value; + sms_log(mac_ctx, LOG1, FL("value=%d"), value); +} +/*-------------------------------------------------------------------------- + + \brief sme_get_soft_ap_domain() - 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 CDF_STATUS_SUCCESS - SME successfully completed the request. + + Other status means, failed to get the current regulatory domain. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_get_soft_ap_domain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN, + NO_SESSION, 0)); + if (NULL == domainIdSoftAp) { + sms_log(pMac, LOGE, "Uninitialized domain Id"); + return status; + } + + *domainIdSoftAp = pMac->scan.domainIdCurrent; + status = CDF_STATUS_SUCCESS; + + return status; +} + +CDF_STATUS sme_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SET_REGINFO, NO_SESSION, 0)); + if (NULL == apCntryCode) { + sms_log(pMac, LOGE, "Empty Country Code, nothing to update"); + return status; + } + + status = csr_set_reg_info(hHal, apCntryCode); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, "csr_set_reg_info failed with status=%d", + status); + } + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS sme_set_plm_request(tHalHandle hHal, tpSirPlmReq pPlmReq) +{ + CDF_STATUS status; + bool ret = false; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t ch_list[WNI_CFG_VALID_CHANNEL_LIST] = { 0 }; + uint8_t count, valid_count = 0; + cds_msg_t msg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, pPlmReq->sessionId); + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), + pPlmReq->sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Invalid Sessionid")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!pPlmReq->enable) + goto send_plm_start; + /* validating channel numbers */ + for (count = 0; count < pPlmReq->plmNumCh; count++) { + ret = csr_is_supported_channel(pMac, pPlmReq->plmChList[count]); + if (ret && pPlmReq->plmChList[count] > 14) { + if (CHANNEL_STATE_DFS == cds_get_channel_state( + pPlmReq->plmChList[count])) { + /* DFS channel is provided, no PLM bursts can be + * transmitted. Ignoring these channels. + */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("DFS channel %d ignored for PLM"), + pPlmReq->plmChList[count]); + continue; + } + } else if (!ret) { + /* Not supported, ignore the channel */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Unsupported channel %d ignored for PLM"), + 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 */ + cdf_mem_set((void *)pPlmReq->plmChList, + pPlmReq->plmNumCh, 0); + if (valid_count) + cdf_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; + +send_plm_start: + /* PLM START */ + msg.type = WMA_SET_PLM_REQ; + msg.reserved = 0; + msg.bodyptr = pPlmReq; + + if (!CDF_IS_STATUS_SUCCESS(cds_mq_post_message(CDF_MODULE_ID_WMA, + &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_SET_PLM_REQ to WMA")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + sme_release_global_lock(&pMac->sme); + return status; +} +#endif + +/*-------------------------------------------------------------------------- + + \brief sme_update_config() - Change configurations for all SME moduels + + The function updates some configuration for modules in SME, 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 mac_open. + \Param pSmeConfigParams - a pointer to a caller allocated object of + typedef struct _smeConfigParams. + + \return CDF_STATUS_SUCCESS - SME update the config parameters successfully. + + Other status means SME is failed to update the config parameters. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, NO_SESSION, + 0)); + if (NULL == pSmeConfigParams) { + sms_log(pMac, LOGE, + "Empty config param structure for SME, nothing to update"); + return status; + } + + status = + csr_change_default_config_param(pMac, &pSmeConfigParams->csrConfig); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_change_default_config_param failed with status=%d", + status); + } +#if defined WLAN_FEATURE_VOWIFI + status = + rrm_change_default_config_param(hHal, &pSmeConfigParams->rrmConfig); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "rrm_change_default_config_param 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 (csr_is_all_session_disconnected(pMac)) { + csr_set_global_cfgs(pMac); + } + + /* + * If scan offload is enabled then lim has allow the sending of + * scan request to firmware even in powersave mode. The firmware has + * to take care of exiting from power save mode + */ + status = sme_cfg_set_int(hHal, WNI_CFG_SCAN_IN_POWERSAVE, true); + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CFG"); + } + pMac->isCoalesingInIBSSAllowed = + pSmeConfigParams->csrConfig.isCoalesingInIBSSAllowed; + + /* 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->sme.ps_global_info.ps_enabled = + pSmeConfigParams->is_ps_enabled; + + pMac->policy_manager_enabled = pSmeConfigParams->policy_manager_enabled; + pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap; + pMac->dual_mac_feature_disable = + pSmeConfigParams->dual_mac_feature_disable; + + return status; +} + +/** + * sme_update_roam_params() - Store/Update the roaming params + * @hal: 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. + */ +CDF_STATUS sme_update_roam_params(tHalHandle hal, + uint8_t session_id, struct roam_ext_params roam_params_src, + int update_param) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct roam_ext_params *roam_params_dst; + uint8_t i; + + roam_params_dst = &mac_ctx->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: + cdf_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; i < roam_params_dst->num_ssid_allowed_list; i++) { + roam_params_dst->ssid_allowed_list[i].length = + roam_params_src.ssid_allowed_list[i].length; + cdf_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: + cdf_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; i < roam_params_dst->num_bssid_favored; i++) { + cdf_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: + cdf_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; i < roam_params_dst->num_bssid_avoid_list; i++) { + cdf_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; + } + csr_roam_offload_scan(mac_ctx, session_id, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + update_param); + return 0; +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void sme_process_get_gtk_info_rsp(tHalHandle hHal, + tpSirGtkOffloadGetInfoRspParams + pGtkOffloadGetInfoRsp) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return; + } + if (pMac->sme.gtk_offload_get_info_cb == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: HDD callback is null", __func__); + return; + } + pMac->sme.gtk_offload_get_info_cb( + pMac->sme.gtk_offload_get_info_cb_context, + pGtkOffloadGetInfoRsp); +} +#endif + +/*-------------------------------------------------------------------------- + + \fn - sme_process_ready_to_suspend + \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 mac_open. + pReadyToSuspend - Parameter received along with ready to suspend + indication from WMA. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_process_ready_to_suspend(tHalHandle hHal, + tpSirReadyToSuspendInd pReadyToSuspend) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_process_ready_to_ext_wo_w + \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 mac_open. + pReadyToExtWoW - Parameter received along with ready to Ext WoW + indication from WMA. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_process_ready_to_ext_wo_w(tHalHandle hHal, + tpSirReadyToExtWoWInd pReadyToExtWoW) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_change_config_params + \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 mac_open. + + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_change_config_params(tHalHandle hHal, + tCsrUpdateConfigParam *pUpdateConfigParam) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pUpdateConfigParam) { + sms_log(pMac, LOGE, + "Empty config param structure for SME, nothing to reset"); + return status; + } + + status = csr_change_config_params(pMac, pUpdateConfigParam); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, "csrUpdateConfigParam failed with status=%d", + status); + } + + return status; + +} + +/*-------------------------------------------------------------------------- + + \brief sme_hdd_ready_ind() - 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. + + This is a synchronous call + \param hHal - The handle returned by mac_open. + + \return CDF_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE + successfully. + + Other status means SME failed to send the message to PE. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_hdd_ready_ind(tHalHandle hHal) +{ + tSirSmeReadyReq Msg; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_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); + Msg.add_bssdescr_cb = csr_scan_process_single_bssdescr; + + + if (eSIR_FAILURE != u_mac_post_ctrl_msg(hHal, (tSirMbMsg *) &Msg)) { + status = CDF_STATUS_SUCCESS; + } else { + sms_log(pMac, LOGE, + "u_mac_post_ctrl_msg failed to send eWNI_SME_SYS_READY_IND"); + break; + } + + status = csr_ready(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_ready failed with status=%d", + status); + break; + } + +#if defined WLAN_FEATURE_VOWIFI + if (CDF_STATUS_SUCCESS != rrm_ready(hHal)) { + status = CDF_STATUS_E_FAILURE; + sms_log(pMac, LOGE, "rrm_ready 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, CSR, etc. . Upon + successfully return, all modules are ready to run. + This is a synchronous call + \param hHal - The handle returned by mac_open. + + \return CDF_STATUS_SUCCESS - SME is ready. + + Other status means SME is failed to start + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_start(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do { + status = csr_start(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_start failed during smeStart with status=%d", + status); + break; + } + +#ifndef WLAN_FEATURE_MBSSID + status = wlansap_start(cds_get_global_context()); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "wlansap_start failed during smeStart with status=%d", + status); + break; + } +#endif + + pMac->sme.state = SME_STATE_START; + } while (0); + + return status; +} + +/** + * sme_handle_scan_req() - Scan request handler + * @mac_ctx: MAC global context + * @msg: message buffer + * + * Scan request message from upper layer is handled as + * part of this API + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_handle_scan_req(tpAniSirGlobal mac_ctx, + void *msg) +{ + struct ani_scan_req *scan_msg; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint16_t session_id; + csr_scan_completeCallback callback; + + scan_msg = msg; + session_id = scan_msg->session_id; + callback = scan_msg->callback; + status = csr_scan_request(mac_ctx, session_id, + scan_msg->scan_param, + callback, scan_msg->ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("scan request failed. session_id %d"), session_id); + } + csr_scan_free_request(mac_ctx, scan_msg->scan_param); + return status; +} + +/** + * sme_handle_roc_req() - Roc request handler + * @mac_ctx: MAC global context + * @msg: message buffer + * + * Roc request message from upper layer is handled as + * part of this API + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_handle_roc_req(tHalHandle hal, + void *msg) +{ + struct ani_roc_req *roc_msg; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + remainOnChanCallback callback; + + if (msg == NULL) { + sms_log(mac_ctx, LOGE, FL("ROC request is NULL")); + return status; + } + + roc_msg = msg; + callback = roc_msg->callback; + status = p2p_remain_on_channel(hal, roc_msg->session_id, + roc_msg->channel, roc_msg->duration, callback, + roc_msg->ctx, roc_msg->is_p2pprobe_allowed, + roc_msg->scan_id); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("scan request failed. session_id %d scan_id %d"), + roc_msg->session_id, roc_msg->scan_id); + } + return status; +} + +#ifdef WLAN_FEATURE_11W +/*------------------------------------------------------------------ + * + * Handle the unprotected management frame indication from LIM and + * forward it to HDD. + * + *------------------------------------------------------------------*/ + +CDF_STATUS sme_unprotected_mgmt_frm_ind(tHalHandle hHal, + tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = { 0 }; + uint32_t SessionId = pSmeMgmtFrm->sessionId; + + pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen; + pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; + pRoamInfo.frameType = pSmeMgmtFrm->frameType; + + /* forward the mgmt frame to HDD */ + csr_roam_call_callback(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 + * + *------------------------------------------------------------------*/ +CDF_STATUS dfs_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo roamInfo = { 0 }; + tSirSmeDfsEventInd *dfs_event; + tSirSmeCSAIeTxCompleteRsp *csaIeTxCompleteRsp; + uint32_t 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) { + sms_log(pMac, LOGE, + "%s: pMsg is NULL for eWNI_SME_DFS_RADAR_FOUND message", + __func__); + return CDF_STATUS_E_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Radar indication event occurred"); + break; + } + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + { + csaIeTxCompleteRsp = + (tSirSmeCSAIeTxCompleteRsp *) pMsgBuf; + if (NULL == csaIeTxCompleteRsp) { + sms_log(pMac, LOGE, + "%s: pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND", + __func__); + return CDF_STATUS_E_FAILURE; + } + sessionId = csaIeTxCompleteRsp->sessionId; + roamStatus = eCSR_ROAM_DFS_CHAN_SW_NOTIFY; + roamResult = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Received eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND for session id [%d]", + sessionId); + break; + } + default: + { + sms_log(pMac, LOG1, "%s: Invalid DFS message = 0x%x", + __func__, msgType); + status = CDF_STATUS_E_FAILURE; + return status; + } + } + + /* Indicate Radar Event to SAP */ + csr_roam_call_callback(pMac, sessionId, &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. + * + *------------------------------------------------------------------*/ +CDF_STATUS sme_tsm_ie_ind(tHalHandle hHal, tSirSmeTsmIEInd *pSmeTsmIeInd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = { 0 }; + uint32_t 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 */ + csr_roam_call_callback(pMac, + SessionId, &pRoamInfo, 0, eCSR_ROAM_TSM_IE_IND, 0); + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_cckm_ie + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_cckm_ie(tHalHandle hHal, uint8_t sessionId, + uint8_t *pCckmIe, uint8_t cckmIeLen) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_set_cckm_ie(pMac, sessionId, pCckmIe, cckmIeLen); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_ese_beacon_request + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId, + const tCsrEseBeaconReq *pEseBcnReq) +{ + CDF_STATUS status = eSIR_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpSirBeaconReportReqInd pSmeBcnReportReq = NULL; + tCsrEseBeaconReqParams *pBeaconReq = NULL; + uint8_t counter = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + if (pSmeRrmContext->eseBcnReqInProgress == true) { + sms_log(pMac, LOGE, + "A Beacon Report Req is already in progress"); + return CDF_STATUS_E_RESOURCES; + } + + /* Store the info in RRM context */ + cdf_mem_copy(&pSmeRrmContext->eseBcnReqInfo, pEseBcnReq, + sizeof(tCsrEseBeaconReq)); + + /* Prepare the request to send to SME. */ + pSmeBcnReportReq = cdf_mem_malloc(sizeof(tSirBeaconReportReqInd)); + if (NULL == pSmeBcnReportReq) { + sms_log(pMac, LOGP, + "Memory Allocation Failure!!! ESE BcnReq Ind to SME"); + return CDF_STATUS_E_NOMEM; + } + + pSmeRrmContext->eseBcnReqInProgress = true; + + sms_log(pMac, LOGE, "Sending Beacon Report Req to SME"); + cdf_mem_zero(pSmeBcnReportReq, sizeof(tSirBeaconReportReqInd)); + + pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND; + pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd); + cdf_mem_copy(pSmeBcnReportReq->bssId, + pSession->connectedProfile.bssid.bytes, + 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_rrm_process_beacon_report_req_ind(pMac, pSmeBcnReportReq); + + if (status != CDF_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 + * + * @mac_ctx: pointer to MAC handle. + * @msg: pointer to received SME msg. + * + * This function process the received SME message and calls the corresponding + * callback which was already registered with SME. + * + * Return: None + */ +#ifdef WLAN_FEATURE_MEMDUMP +static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal mac_ctx, cds_msg_t *msg) +{ + if (msg->bodyptr) { + if (mac_ctx->sme.fw_dump_callback) + mac_ctx->sme.fw_dump_callback(mac_ctx->hHdd, + (struct fw_dump_rsp *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + } +} +#else +static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal mac_ctx, cds_msg_t *msg) +{ +} +#endif + +/** + * sme_process_dual_mac_config_resp() - Process set Dual mac config response + * @mac: Global MAC pointer + * @msg: Dual mac config response + * + * Processes the dual mac configuration response and invokes the HDD callback + * to process further + */ +static CDF_STATUS sme_process_dual_mac_config_resp(tpAniSirGlobal mac, + uint8_t *msg) +{ + tListElem *entry = NULL; + tSmeCmd *command = NULL; + bool found; + dual_mac_cb callback = NULL; + struct sir_dual_mac_config_resp *param; + + param = (struct sir_dual_mac_config_resp *)msg; + if (!param) { + sms_log(mac, LOGE, FL("Dual mac config resp param is NULL")); + /* Not returning. Need to check if active command list + * needs to be freed + */ + } + + entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac, LOGE, FL("No cmd found in active list")); + return CDF_STATUS_E_FAILURE; + } + + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (!command) { + sms_log(mac, LOGE, FL("Base address is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (e_sme_command_set_dual_mac_config != command->command) { + sms_log(mac, LOGE, FL("Command mismatch!")); + return CDF_STATUS_E_FAILURE; + } + + callback = command->u.set_dual_mac_cmd.set_dual_mac_cb; + if (callback) { + if (!param) { + sms_log(mac, LOGE, + FL("Callback failed-Dual mac config is NULL")); + } else { + sms_log(mac, LOG1, + FL("Calling HDD callback for Dual mac config")); + callback(param->status, + command->u.set_dual_mac_cmd.scan_config, + command->u.set_dual_mac_cmd.fw_mode_config); + } + } else { + sms_log(mac, LOGE, FL("Callback does not exist")); + } + + found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK); + if (found) + /* Now put this command back on the available command list */ + sme_release_command(mac, command); + + sme_process_pending_queue(mac); + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + + \brief sme_process_msg() - 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 mac_open. + \param pMsg - A pointer to a caller allocated object of tSirMsgQ. + + \return CDF_STATUS_SUCCESS - SME successfully process the message. + + Other status means SME failed to process the message to HAL. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMsg == NULL) { + sms_log(pMac, LOGE, "Empty message for SME"); + return status; + } + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, FL("Locking failed, bailing out")); + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + return status; + } + if (!SME_IS_START(pMac)) { + sms_log(pMac, LOGW, FL("message type %d in stop state ignored"), + pMsg->type); + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + goto release_lock; + } + switch (pMsg->type) { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case eWNI_SME_ROAM_OFFLOAD_SYNCH_IND: + csr_process_roam_offload_synch_ind(pMac, + (roam_offload_synch_ind *) pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_HO_FAIL_IND: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("LFR3: Rcvd eWNI_SME_HO_FAIL_IND")); + csr_process_ho_fail_ind(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; +#endif + case eWNI_PMC_SMPS_STATE_IND: + 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: + 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_qos_msg_processor(pMac, pMsg->type, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); +#endif + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#if defined WLAN_FEATURE_VOWIFI + case eWNI_SME_NEIGHBOR_REPORT_IND: + case eWNI_SME_BEACON_REPORT_REQ_IND: +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, FL("Received RRM message. Message Id = %d"), + pMsg->type); +#endif + if (pMsg->bodyptr) { + status = sme_rrm_msg_processor(pMac, pMsg->type, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + 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_handle_oem_data_rsp(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + sme_process_pending_queue(pMac); + break; +#endif + case eWNI_SME_ADD_STA_SELF_RSP: + if (pMsg->bodyptr) { + status = csr_process_add_sta_session_rsp(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_DEL_STA_SELF_RSP: + if (pMsg->bodyptr) { + status = csr_process_del_sta_session_rsp(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_REMAIN_ON_CHN_RSP: + if (pMsg->bodyptr) { + status = sme_remain_on_chn_rsp(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_REMAIN_ON_CHN_RDY_IND: + if (pMsg->bodyptr) { + status = sme_remain_on_chn_ready(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_MGMT_FRM_IND: + if (pMsg->bodyptr) { + sme_mgmt_frm_ind(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_ACTION_FRAME_SEND_CNF: + if (pMsg->bodyptr) { + status = sme_send_action_cnf(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#ifdef FEATURE_WLAN_SCAN_PNO + case eWNI_SME_PREF_NETWORK_FOUND_IND: + if (pMsg->bodyptr) { + status = sme_preferred_network_found_ind((void *)pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#endif /* FEATURE_WLAN_SCAN_PNO */ + case eWNI_SME_CHANGE_COUNTRY_CODE: + if (pMsg->bodyptr) { + status = sme_handle_change_country_code((void *)pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE: + if (pMsg->bodyptr) { + status = sme_handle_generic_change_country_code( + (void *)pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_SCAN_CMD: + if (pMsg->bodyptr) { + status = sme_handle_scan_req(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_ROC_CMD: + if (pMsg->bodyptr) { + status = sme_handle_roc_req(hHal, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#ifdef FEATURE_WLAN_TDLS + /* + * command rescived from PE, SME tdls msg processor shall be called + * to process commands recieved 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 = tdls_msg_processor(pMac, pMsg->type, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#endif +#ifdef WLAN_FEATURE_11W + case eWNI_SME_UNPROT_MGMT_FRM_IND: + if (pMsg->bodyptr) { + sme_unprotected_mgmt_frm_ind(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_TSM_IE_IND: + if (pMsg->bodyptr) { + sme_tsm_ie_ind(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_ROAM_SCAN_OFFLOAD_RSP: + status = csr_roam_offload_scan_rsp_hdlr((void *)pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP: + if (pMsg->bodyptr) { + sme_process_get_gtk_info_rsp(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + 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); + cdf_mem_free(pMsg->bodyptr); + break; +#endif /* FEATURE_WLAN_LPHB */ + + case eWNI_SME_READY_TO_SUSPEND_IND: + if (pMsg->bodyptr) { + sme_process_ready_to_suspend(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + case eWNI_SME_READY_TO_EXTWOW_IND: + if (pMsg->bodyptr) { + sme_process_ready_to_ext_wo_w(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("CH avoid notification")); + pMac->sme.pChAvoidNotificationCb(pMac->hHdd, + pMsg->bodyptr); + } + cdf_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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Auto shutdown notification")); + pMac->sme.pAutoShutdownNotificationCb(); + } + cdf_mem_free(pMsg->bodyptr); + break; +#endif + case eWNI_SME_DFS_RADAR_FOUND: + case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND: + status = dfs_msg_processor(pMac, pMsg->type, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_CHANNEL_CHANGE_RSP: + if (pMsg->bodyptr) { + status = sme_process_channel_change_resp(pMac, + pMsg->type, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#ifdef WLAN_FEATURE_STATS_EXT + case eWNI_SME_STATS_EXT_EVENT: + if (pMsg->bodyptr) { + status = sme_stats_ext_event(hHal, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; +#endif + case eWNI_SME_LINK_SPEED_IND: + if (pMac->sme.pLinkSpeedIndCb) + pMac->sme.pLinkSpeedIndCb(pMsg->bodyptr, + pMac->sme.pLinkSpeedCbContext); + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_CSA_OFFLOAD_EVENT: + if (pMsg->bodyptr) { + csr_scan_flush_bss_entry(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } + break; +#ifdef WLAN_FEATURE_NAN + case eWNI_SME_NAN_EVENT: + if (pMsg->bodyptr) { + sme_nan_event(hHal, pMsg->bodyptr); + cdf_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; + cdf_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); + } + cdf_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 + sms_log(pMac, LOGE, + FL("callback not registered to process %d"), + pMsg->type); + + cdf_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 + sms_log(pMac, LOGE, + FL("callback not registered to process %d"), + pMsg->type); + + cdf_mem_free(pMsg->bodyptr); + break; +#endif + case eWNI_SME_FW_DUMP_IND: + sme_process_fw_mem_dump_rsp(pMac, pMsg); + break; + case eWNI_SME_SET_HW_MODE_RESP: + if (pMsg->bodyptr) { + status = sme_process_set_hw_mode_resp(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_HW_MODE_TRANS_IND: + if (pMsg->bodyptr) { + status = sme_process_hw_mode_trans_ind(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + break; + case eWNI_SME_NSS_UPDATE_RSP: + if (pMsg->bodyptr) { + status = sme_process_nss_update_resp(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + 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 { + sms_log(pMac, LOGE, FL( + "Message error. The callback is NULL.")); + } + pMac->sme.ocb_set_config_callback = NULL; + pMac->sme.ocb_set_config_context = NULL; + cdf_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 { + sms_log(pMac, LOGE, FL( + "Message error. The callback is NULL.")); + } + pMac->sme.ocb_get_tsf_timer_callback = NULL; + pMac->sme.ocb_get_tsf_timer_context = NULL; + cdf_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 { + sms_log(pMac, LOGE, FL( + "Message error. The callback is NULL.")); + } + pMac->sme.dcc_get_stats_callback = NULL; + pMac->sme.dcc_get_stats_context = NULL; + cdf_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 { + sms_log(pMac, LOGE, FL( + "Message error. The callback is NULL.")); + } + pMac->sme.dcc_update_ndl_callback = NULL; + pMac->sme.dcc_update_ndl_context = NULL; + cdf_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 { + sms_log(pMac, LOGE, FL( + "Message error. The callback is NULL.")); + } + cdf_mem_free(pMsg->bodyptr); + break; + case eWNI_SME_SET_DUAL_MAC_CFG_RESP: + if (pMsg->bodyptr) { + status = sme_process_dual_mac_config_resp(pMac, + pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + 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; + default: + + if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) + && (pMsg->type <= eWNI_SME_MSG_TYPES_END)) { + /* CSR */ + if (pMsg->bodyptr) { + status = csr_msg_processor(hHal, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + } else { + sms_log(pMac, LOGE, FL("Empty message for %d"), + pMsg->type); + } + } else { + sms_log(pMac, LOGW, FL("Unknown message type %d"), + pMsg->type); + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + } + } /* switch */ +release_lock: + sme_release_global_lock(&pMac->sme); + return status; +} + +/** + * sme_process_nss_update_resp() - Process nss update response + * @mac: Global MAC pointer + * @msg: nss update response + * + * Processes the nss update response and invokes the HDD + * callback to process further + */ +CDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg) +{ + tListElem *entry = NULL; + tSmeCmd *command = NULL; + bool found; + nss_update_cb callback = NULL; + struct sir_beacon_tx_complete_rsp *param; + + param = (struct sir_beacon_tx_complete_rsp *)msg; + if (!param) { + sms_log(mac, LOGE, FL("nss update resp param is NULL")); + /* Not returning. Need to check if active command list + * needs to be freed + */ + } + + entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac, LOGE, FL("No cmd found in active list")); + return CDF_STATUS_E_FAILURE; + } + + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (!command) { + sms_log(mac, LOGE, FL("Base address is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (e_sme_command_nss_update != command->command) { + sms_log(mac, LOGE, FL("Command mismatch!")); + return CDF_STATUS_E_FAILURE; + } + + callback = command->u.nss_update_cmd.nss_update_cb; + if (callback) { + if (!param) { + sms_log(mac, LOGE, + FL("Callback failed since nss update params is NULL")); + } else { + sms_log(mac, LOGE, + FL("Calling HDD callback for nss update response")); + callback(command->u.nss_update_cmd.context, + param->tx_status, + param->session_id, + command->u.nss_update_cmd.next_action); + } + } else { + sms_log(mac, LOGE, FL("Callback does not exisit")); + } + + found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK); + if (found) { + /* Now put this command back on the avilable command list */ + sme_release_command(mac, command); + } + sme_process_pending_queue(mac); + return CDF_STATUS_SUCCESS; +} + +/* No need to hold the global lock here because this function can only be called */ +/* after sme_stop. */ +void sme_free_msg(tHalHandle hHal, cds_msg_t *pMsg) +{ + if (pMsg) { + if (pMsg->bodyptr) { + cdf_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, CSR, etc. . Upon + return, all modules are at idle state ready to start. + + This is a synchronous call + \param hHal - The handle returned by mac_open + \param tHalStopType - reason for stopping + + \return CDF_STATUS_SUCCESS - SME is stopped. + + Other status means SME is failed to stop but caller should still + consider SME is stopped. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_stop(tHalHandle hHal, tHalStopType stopType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_STATUS fail_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + +#ifndef WLAN_FEATURE_MBSSID + status = wlansap_stop(cds_get_global_context()); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "wlansap_stop failed during smeStop with status=%d", + status); + fail_status = status; + } +#endif + + p2p_stop(hHal); + + status = csr_stop(pMac, stopType); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_stop failed during smeStop with status=%d", status); + fail_status = status; + } + + purge_sme_cmd_list(pMac); + + if (!CDF_IS_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, 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 mac_close. + This is a synchronous call + \param hHal - The handle returned by mac_open + + \return CDF_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 + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_close(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_STATUS fail_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (!pMac) + return CDF_STATUS_E_FAILURE; + + /* Note: pSession will be invalid from here on, do not access */ + status = csr_close(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_close failed during sme close with status=%d", + status); + fail_status = status; + } +#ifndef WLAN_FEATURE_MBSSID + status = wlansap_close(cds_get_global_context()); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "WLANSAP_close failed during sme close with status=%d", + status); + fail_status = status; + } +#endif + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + status = sme_qos_close(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "Qos close failed during sme close with status=%d", + status); + fail_status = status; + } +#endif +#ifdef FEATURE_OEM_DATA_SUPPORT + status = oem_data_oem_data_req_close(hHal); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "OEM DATA REQ close failed during sme close with status=%d", + status); + fail_status = status; + } +#endif + status = sme_ps_close(hHal); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "sme_ps_close failed during smeClose status=%d", + status); + fail_status = status; + } + +#if defined WLAN_FEATURE_VOWIFI + status = rrm_close(hHal); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "RRM close failed during sme close with status=%d", + status); + fail_status = status; + } +#endif + + sme_p2p_close(hHal); + + free_sme_cmd_list(pMac); + + if (!CDF_IS_STATUS_SUCCESS + (cdf_mutex_destroy(&pMac->sme.lkSmeGlobalLock))) { + fail_status = CDF_STATUS_E_FAILURE; + } + + if (!CDF_IS_STATUS_SUCCESS(fail_status)) { + status = fail_status; + } + + pMac->sme.state = SME_STATE_STOP; + + return status; +} + +/** + * sme_scan_request() - wrapper function to Request a 11d or full scan from CSR. + * @hal: hal global context + * @session_id: session id + * @scan_req: scan req + * @callback: a callback function that scan calls upon finish, will not + * be called if csr_scan_request returns error + * @ctx: a pointer passed in for the callback + * + * This is a wrapper function to Request a 11d or full scan from CSR. This is + * an asynchronous call + * + * Return: Status of operation + */ +CDF_STATUS sme_scan_request(tHalHandle hal, uint8_t session_id, + tCsrScanRequest *scan_req, + csr_scan_completeCallback callback, void *ctx) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + struct ani_scan_req *scan_msg; + cds_msg_t msg; + uint32_t scan_req_id, scan_count; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_REQ, session_id, + scan_req->scanType)); + if (!mac_ctx->scan.fScanEnable) { + sms_log(mac_ctx, LOGE, FL("fScanEnable false")); + return status; + } + + scan_count = csr_ll_count(&mac_ctx->sme.smeScanCmdActiveList); + if (scan_count >= mac_ctx->scan.max_scan_count) { + sms_log(mac_ctx, LOGE, FL("Max scan reached")); + return CDF_STATUS_E_FAILURE; + } + wma_get_scan_id(&scan_req_id); + scan_req->scan_id = scan_req_id; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("Unable to acquire lock")); + return status; + } + sms_log(mac_ctx, LOG1, FL(" called")); + scan_msg = cdf_mem_malloc(sizeof(struct ani_scan_req)); + if (NULL == scan_msg) { + sms_log(mac_ctx, LOGE, + " scan_req: failed to allocate mem for msg"); + sme_release_global_lock(&mac_ctx->sme); + return CDF_STATUS_E_NOMEM; + } + scan_msg->msg_type = eWNI_SME_SCAN_CMD; + scan_msg->msg_len = (uint16_t) sizeof(struct ani_scan_req); + scan_msg->session_id = session_id; + scan_msg->callback = callback; + scan_msg->ctx = ctx; + scan_msg->scan_param = cdf_mem_malloc(sizeof(tCsrScanRequest)); + if (NULL == scan_msg->scan_param) { + sms_log(mac_ctx, LOGE, + "scan_req:failed to allocate mem for scanreq"); + sme_release_global_lock(&mac_ctx->sme); + cdf_mem_free(scan_msg); + return CDF_STATUS_E_NOMEM; + } + csr_scan_copy_request(mac_ctx, scan_msg->scan_param, scan_req); + msg.type = eWNI_SME_SCAN_CMD; + msg.bodyptr = scan_msg; + msg.reserved = 0; + msg.bodyval = 0; + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(mac_ctx, LOGE, + " sme_scan_req failed to post msg"); + csr_scan_free_request(mac_ctx, scan_msg->scan_param); + cdf_mem_free(scan_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac_ctx->sme); + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_get_result + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_scan_get_result(tHalHandle hHal, uint8_t sessionId, + tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS, sessionId, + 0)); + sms_log(pMac, LOG2, FL("enter")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_scan_get_result(hHal, pFilter, phResult); + sme_release_global_lock(&pMac->sme); + } + sms_log(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: CDF_STATUS. + */ +CDF_STATUS sme_get_ap_channel_from_scan_cache(tHalHandle hal_handle, + tCsrRoamProfile *profile, + tScanResultHandle *scan_cache, + uint8_t *ap_chnl_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + tCsrScanResultFilter *scan_filter = NULL; + tScanResultHandle filtered_scan_result = NULL; + tSirBssDescription first_ap_profile; + + if (NULL == mac_ctx) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("mac_ctx is NULL")); + return CDF_STATUS_E_FAILURE; + } + scan_filter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == scan_filter) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("scan_filter mem alloc failed")); + return CDF_STATUS_E_FAILURE; + } else { + cdf_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0); + cdf_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 = csr_roam_prepare_filter_from_profile(mac_ctx, + profile, + scan_filter); + } + + if (CDF_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 { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Preparing the profile filter failed")); + cdf_mem_free(scan_filter); + return CDF_STATUS_E_FAILURE; + } + } + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_STATUS_SUCCESS == status) { + status = csr_scan_get_result(hal_handle, scan_filter, + &filtered_scan_result); + if (CDF_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; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Found best AP & its on chnl[%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; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Scan is empty, set chnl to 0")); + status = CDF_STATUS_E_FAILURE; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to get scan get result")); + status = CDF_STATUS_E_FAILURE; + } + csr_free_scan_filter(mac_ctx, scan_filter); + sme_release_global_lock(&mac_ctx->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Aquiring lock failed")); + status = CDF_STATUS_E_FAILURE; + } + + cdf_mem_free(scan_filter); + + return 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); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + bool ret_status = true; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ, + session_id, 0)); + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_STATUS_SUCCESS == status) { + if (false == csr_store_joinreq_param(mac_ctx, profile, + scan_cache, roam_id, session_id)) { + ret_status = false; + } + sme_release_global_lock(&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); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + bool ret_status = true; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ, + session_id, 0)); + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_STATUS_SUCCESS == status) { + if (false == csr_clear_joinreq_param(mac_ctx, + session_id)) { + ret_status = false; + } + sme_release_global_lock(&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: CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE. + **/ +CDF_STATUS sme_issue_stored_joinreq(tHalHandle hal_handle, + uint32_t *roam_id, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_STATUS ret_status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ, + session_id, 0)); + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_STATUS_SUCCESS == status) { + if (CDF_STATUS_SUCCESS != csr_issue_stored_joinreq(mac_ctx, + roam_id, + session_id)) { + ret_status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac_ctx->sme); + } else { + csr_clear_joinreq_param(mac_ctx, session_id); + ret_status = CDF_STATUS_E_FAILURE; + } + return ret_status; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_flush_result + \brief a wrapper function to request CSR to clear scan results. + This is a synchronous call + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_scan_flush_result(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, + 0, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_scan_flush_result(hHal); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_filter_scan_results + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_filter_scan_results(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS, + sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_scan_filter_results(pMac); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +CDF_STATUS sme_scan_flush_p2p_result(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS, + sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_scan_flush_selective_result(hHal, true); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_result_get_first + \brief a wrapper function to request CSR to returns the first element of + scan result. + This is a synchronous call + \param hScanResult - returned from csr_scan_get_result + \return tCsrScanResultInfo * - NULL if no result + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_scan_result_get_first(tHalHandle hHal, + tScanResultHandle hScanResult) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrScanResultInfo *pRet = NULL; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pRet = csr_scan_result_get_first(pMac, hScanResult); + sme_release_global_lock(&pMac->sme); + } + + return pRet; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_result_get_next + \brief a wrapper function to request CSR to returns the next element of + scan result. It can be called without calling csr_scan_result_get_first + first + This is a synchronous call + \param hScanResult - returned from csr_scan_get_result + \return Null if no result or reach the end + ---------------------------------------------------------------------------*/ +tCsrScanResultInfo *sme_scan_result_get_next(tHalHandle hHal, + tScanResultHandle hScanResult) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrScanResultInfo *pRet = NULL; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETNEXT, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pRet = csr_scan_result_get_next(pMac, hScanResult); + sme_release_global_lock(&pMac->sme); + } + + return pRet; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_result_purge + \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 csr_scan_get_result. hScanResult is + considered gone by + calling this function and even before this function reutrns. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_scan_result_purge(tHalHandle hHal, tScanResultHandle hScanResult) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_scan_result_purge(hHal, hScanResult); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_scan_get_pmkid_candidate_list + \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 retruning, this is + either the number needed or number of items put into + pPmkidList + \return CDF_STATUS - 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 + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_scan_get_pmkid_candidate_list(tHalHandle hHal, uint8_t sessionId, + tPmkidCandidateInfo *pPmkidList, + uint32_t *pNumItems) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + csr_scan_get_pmkid_candidate_list(pMac, sessionId, + pPmkidList, + pNumItems); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +eCsrPhyMode sme_get_phy_mode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.phyMode; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_channel_bonding_mode5_g + \brief get the channel bonding mode for 5G band + \param hHal - HAL handle + \return channel bonding mode for 5G + ---------------------------------------------------------------------------*/ +uint32_t sme_get_channel_bonding_mode5_g(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeConfigParams smeConfig; + + sme_get_config_param(pMac, &smeConfig); + + return smeConfig.csrConfig.channelBondingMode5GHz; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_channel_bonding_mode24_g + \brief get the channel bonding mode for 2.4G band + \param hHal - HAL handle + \return channel bonding mode for 2.4G + ---------------------------------------------------------------------------*/ +uint32_t sme_get_channel_bonding_mode24_g(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeConfigParams smeConfig; + + sme_get_config_param(pMac, &smeConfig); + + return smeConfig.csrConfig.channelBondingMode24GHz; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_connect + \brief a wrapper function to request CSR to inititiate an association + This is an asynchronous call. + \param sessionId - the sessionId returned by sme_open_session. + \param pProfile - description of the network to which to connect + \param hBssListIn - a list of BSS descriptor to roam to. It is returned + from csr_scan_get_result + \param pRoamId - to get back the request ID + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_connect(tHalHandle hHal, uint8_t sessionId, + tCsrRoamProfile *pProfile, uint32_t *pRoamId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (!pMac) { + return CDF_STATUS_E_FAILURE; + } + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_CONNECT, sessionId, 0)); + sms_log(pMac, LOG2, FL("enter")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_connect(pMac, sessionId, pProfile, + pRoamId); + } else { + sms_log(pMac, LOGE, FL("invalid sessionID %d"), + sessionId); + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } else { + sms_log(pMac, LOGE, FL("sme_acquire_global_lock failed")); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_phy_mode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by mac_open. + + \param phyMode new phyMode which is to set + + \return CDF_STATUS SUCCESS. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_set_phy_mode(tHalHandle hHal, eCsrPhyMode phyMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return CDF_STATUS_E_FAILURE; + } + + pMac->roam.configParam.phyMode = phyMode; + pMac->roam.configParam.uCfgDot11Mode = + csr_get_cfg_dot11_mode_from_csr_phy_mode(NULL, + pMac->roam.configParam.phyMode, + pMac->roam.configParam. + ProprietaryRatesEnabled); + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_reassoc + \brief a wrapper function to request CSR to inititiate 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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_reassoc(tHalHandle hHal, uint8_t sessionId, + tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + uint32_t *pRoamId, bool fForce) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_REASSOC, sessionId, 0)); + sms_log(pMac, LOG2, FL("enter")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + if ((NULL == pProfile) && (fForce == 1)) { + status = + csr_reassoc(pMac, sessionId, + &modProfileFields, pRoamId, + fForce); + } else { + status = + csr_roam_reassoc(pMac, sessionId, pProfile, + modProfileFields, pRoamId); + } + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_connect_to_last_profile + \brief a wrapper function to request CSR to disconnect and reconnect with + the same profile + This is an asynchronous call. + \return CDF_STATUS. It returns fail if currently connected + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_connect_to_last_profile(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, + sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csr_roam_connect_to_last_profile(pMac, sessionId); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_disconnect + \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 meanful. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_disconnect(tHalHandle hHal, uint8_t sessionId, + eCsrRoamDisconnectReason reason) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT, sessionId, + reason)); + sms_log(pMac, LOG2, FL("enter")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csr_roam_disconnect(pMac, sessionId, reason); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_stop_bss + \brief To stop BSS for Soft AP. This is an asynchronous API. + \param hHal - Global structure + \param sessionId - sessionId of SoftAP + \return CDF_STATUS SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_stop_bss(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + sms_log(pMac, LOG2, FL("enter")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csr_roam_issue_stop_bss_cmd(pMac, sessionId, true); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_disconnect_sta + \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 CDF_STATUS SUCCESS Roam callback will be called to indicate actual results + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_disconnect_sta(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pPeerMacAddr) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_ASSERT(0); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csr_roam_issue_disassociate_sta_cmd(pMac, + sessionId, pPeerMacAddr, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/** + * sme_roam_deauth_sta() - deauthenticate a station + * @hHal: Global structure + * @sessionId: SessionId of SoftAP + * @pDelStaParams: Pointer to parameters of the station to deauthenticate + * + * To disassociate a station. This is an asynchronous API. + * + * Return: CDF_STATUS_SUCCESS on success or another CDF_STATUS error + * code on error. Roam callback will be called to indicate actual + * result + */ +CDF_STATUS sme_roam_deauth_sta(tHalHandle hHal, uint8_t sessionId, + struct tagCsrDelStaParams *pDelStaParams) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_ASSERT(0); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_issue_deauth_sta_cmd(pMac, sessionId, + pDelStaParams); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_tkip_counter_measures + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_tkip_counter_measures(tHalHandle hHal, uint8_t sessionId, + bool bEnable) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_ASSERT(0); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_issue_tkip_counter_measures(pMac, sessionId, + bEnable); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_associated_stas + \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 associtated stations is + to be probed. If an invalid module is passed then + by default CDF_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 associatd + stations info + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_associated_stas(tHalHandle hHal, uint8_t sessionId, + CDF_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, + uint8_t *pAssocStasBuf) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_ASSERT(0); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_associated_stas(pMac, sessionId, modId, + pUsrContext, + pfnSapEventCallback, + pAssocStasBuf); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_wps_session_overlap + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_wps_session_overlap(tHalHandle hHal, uint8_t sessionId, + void *pUsrContext, void + *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_ASSERT(0); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_wps_session_overlap(pMac, sessionId, + pUsrContext, + pfnSapEventCallback, + pRemoveMac); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_connect_state + \brief a wrapper function to request CSR to return the current connect state + of Roaming + This is a synchronous call. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_connect_state(tHalHandle hHal, uint8_t sessionId, + eCsrConnectState *pState) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_connect_state(pMac, sessionId, pState); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_connect_profile + \brief a wrapper function to request CSR to return the current connect + profile. Caller must call csr_roam_free_connect_profile after it is done + and before reuse for another csr_roam_get_connect_profile call. + This is a synchronous call. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return CDF_STATUS. Failure if not connected + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_connect_profile(tHalHandle hHal, uint8_t sessionId, + tCsrRoamConnectedProfile *pProfile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE, + sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_connect_profile(pMac, sessionId, pProfile); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_free_connect_profile + \brief a wrapper function to request CSR to free and reinitialize the + profile returned previously by csr_roam_get_connect_profile. + This is a synchronous call. + \param pProfile - pointer to a caller allocated structure + tCsrRoamConnectedProfile + \return CDF_STATUS. + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_free_connect_profile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_free_connect_profile(pMac, pProfile); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_set_pmkid_cache + \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 retruning, 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 CDF_STATUS - 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 + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_set_pmkid_cache(tHalHandle hHal, uint8_t sessionId, + tPmkidCacheInfo *pPMKIDCache, + uint32_t numItems, bool update_entire_cache) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE, sessionId, + numItems)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_set_pmkid_cache(pMac, sessionId, pPMKIDCache, + numItems, update_entire_cache); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +CDF_STATUS sme_roam_del_pmkid_from_cache(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBSSId, bool flush_cache) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = csr_roam_del_pmkid_from_cache(pMac, sessionId, + pBSSId, flush_cache); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + * \fn sme_roam_set_psk_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 CDF_STATUS -status whether PSK/PMK is set or not + *--------------------------------------------------------------------------- + */ +CDF_STATUS sme_roam_set_psk_pmk(tHalHandle hHal, uint8_t sessionId, + uint8_t *pPSK_PMK, size_t pmk_len) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_set_psk_pmk(pMac, sessionId, pPSK_PMK, + pmk_len); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} +#endif +/* --------------------------------------------------------------------------- + \fn sme_roam_get_security_req_ie + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_security_req_ie(tHalHandle hHal, uint8_t sessionId, + uint32_t *pLen, uint8_t *pBuf, + eCsrSecurityType secType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_wpa_rsn_req_ie(hHal, sessionId, pLen, pBuf); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_security_rsp_ie + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_security_rsp_ie(tHalHandle hHal, uint8_t sessionId, + uint32_t *pLen, uint8_t *pBuf, + eCsrSecurityType secType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_wpa_rsn_rsp_ie(pMac, sessionId, pLen, pBuf); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_num_pmkid_cache + \brief a wrapper function to request CSR to return number of PMKID cache + entries + This is a synchronous call. + \return uint32_t - the number of PMKID cache entries + ---------------------------------------------------------------------------*/ +uint32_t sme_roam_get_num_pmkid_cache(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint32_t numPmkidCache = 0; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + numPmkidCache = + csr_roam_get_num_pmkid_cache(pMac, sessionId); + status = CDF_STATUS_SUCCESS; + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return numPmkidCache; +} + +/* --------------------------------------------------------------------------- + \fn sme_roam_get_pmkid_cache + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not + big enough + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_get_pmkid_cache(tHalHandle hHal, uint8_t sessionId, + uint32_t *pNum, tPmkidCacheInfo *pPmkidCache) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE, sessionId, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_roam_get_pmkid_cache(pMac, sessionId, pNum, + pPmkidCache); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_config_param + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_get_config_param(pMac, &pParam->csrConfig); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, "%s csr_get_config_param failed", + __func__); + sme_release_global_lock(&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->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->policy_manager_enabled = pMac->policy_manager_enabled; + pParam->fine_time_meas_cap = pMac->fine_time_meas_cap; + pParam->dual_mac_feature_disable = + pMac->dual_mac_feature_disable; + pParam->is_ps_enabled = pMac->sme.ps_global_info.ps_enabled; + pParam->pnoOffload = pMac->pnoOffload; + pParam->fEnableDebugLog = pMac->fEnableDebugLog; + pParam->enable5gEBT = pMac->enable5gEBT; + pParam->f_sta_miracast_mcc_rest_time_val = + pMac->f_sta_miracast_mcc_rest_time_val; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/** + * sme_cfg_set_int() - Sets the cfg parameter value. + * @hal: Handle to hal. + * @cfg_id: Configuration parameter ID. + * @value: value to be saved in the cfg parameter. + * + * This function sets the string value in cfg parameter. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_cfg_set_int(tHalHandle hal, uint16_t cfg_id, uint32_t value) +{ + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (eSIR_SUCCESS != cfg_set_int(pmac, cfg_id, value)) + status = CDF_STATUS_E_FAILURE; + + return status; +} + +/** + * sme_cfg_set_str() - Sets the cfg parameter string. + * @hal: Handle to hal. + * @cfg_id: Configuration parameter ID. + * @str: Pointer to the string buffer. + * @length: Length of the string. + * + * This function sets the string value in cfg parameter. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_cfg_set_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str, + uint32_t length) +{ + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (eSIR_SUCCESS != cfg_set_str(pmac, cfg_id, str, length)) + status = CDF_STATUS_E_FAILURE; + + return status; +} + +/** + * sme_cfg_get_int() - Gets the cfg parameter value. + * @hal: Handle to hal. + * @cfg_id: Configuration parameter ID. + * @cfg_value: Pointer to variable in which cfg value + * will be saved. + * + * This function gets the value of the cfg parameter. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_cfg_get_int(tHalHandle hal, uint16_t cfg_id, uint32_t *cfg_value) +{ + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (eSIR_SUCCESS != wlan_cfg_get_int(pmac, cfg_id, cfg_value)) + status = CDF_STATUS_E_FAILURE; + + return status; +} + +/** + * sme_cfg_get_str() - Gets the cfg parameter string. + * @hal: Handle to hal. + * @cfg_id: Configuration parameter ID. + * @str: Pointer to the string buffer. + * @length: Pointer to length of the string. + * + * This function gets the string value of the cfg parameter. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_cfg_get_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str, + uint32_t *length) +{ + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (eSIR_SUCCESS != wlan_cfg_get_str(pmac, cfg_id, str, length)) + status = CDF_STATUS_E_INVAL; + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_modify_profile_fields + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_get_modify_profile_fields(tHalHandle hHal, uint8_t sessionId, + tCsrRoamModifyProfileFields * + pModifyProfileFields) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS, sessionId, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = + csr_get_modify_profile_fields(pMac, sessionId, + pModifyProfileFields); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_dhcp_till_power_active_flag + \brief Sets/Clears DHCP related flag to disable/enable auto PS + \param hal - The handle returned by mac_open. + ---------------------------------------------------------------------------*/ +void sme_set_dhcp_till_power_active_flag(tHalHandle hal, uint8_t flag) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct ps_global_info *ps_global_info = &mac->sme.ps_global_info; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG, NO_SESSION, + flag)); + /* Set/Clear the DHCP flag which will disable/enable auto PS */ + ps_global_info->remain_in_power_active_till_dhcp = flag; +} + +/* --------------------------------------------------------------------------- + \fn sme_register11d_scan_done_callback + \brief Register a routine of type csr_scan_completeCallback which is + called whenever an 11d scan is done + \param hHal - The handle returned by mac_open. + \param callback - 11d scan complete routine to be registered + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_register11d_scan_done_callback(tHalHandle hHal, + csr_scan_completeCallback callback) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pMac->scan.callback11dScanDone = callback; + + return status; +} + +#ifdef FEATURE_OEM_DATA_SUPPORT +/** + * sme_register_oem_data_rsp_callback() - Register a routine of + * type send_oem_data_rsp_msg + * @h_hal: Handle returned by mac_open. + * @callback: Callback to send response + * to oem application. + * + * sme_oem_data_rsp_callback is used to register sme_send_oem_data_rsp_msg + * callback function. + * + * Return: CDF_STATUS. + */ +CDF_STATUS sme_register_oem_data_rsp_callback(tHalHandle h_hal, + sme_send_oem_data_rsp_msg callback) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pmac = PMAC_STRUCT(h_hal); + + pmac->oemData.oem_data_rsp_callback = callback; + + return status; + +} +#endif + +/** + * sme_register_ftm_msg_processor() - registers hdd ftm message processor + * function to MAC/SYS + * + * @hal: hal handle + * @callback: hdd function that has to be registered + * + * Return: void + */ +void sme_register_ftm_msg_processor(tHalHandle hal, + hdd_ftm_msg_processor callback) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + + if (mac_ctx == NULL) { + sms_log(mac_ctx, LOGE, FL("mac_ctx is NULL")); + return; + } + mac_ctx->ftm_msg_processor_callback = callback; + return; +} + +/** + * sme_wow_add_pattern() - add a wow pattern in fw + * @hHal: handle returned by mac_open + * @pattern: pointer to input pattern + * + * Add a pattern for Pattern Byte Matching in WoW mode. Firmware will + * do a pattern match on these patterns when WoW is enabled during system + * suspend. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_wow_add_pattern(tHalHandle hal, + struct wow_add_pattern *pattern, + uint8_t session_id) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + struct wow_add_pattern *ptrn; + tSirRetStatus ret_code = eSIR_SUCCESS; + tSirMsgQ msg_q; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_WOWL_ADDBCAST_PATTERN, session_id, + 0)); + ptrn = cdf_mem_malloc(sizeof(*ptrn)); + if (NULL == ptrn) { + sms_log(pMac, LOGP, + FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); + return CDF_STATUS_E_NOMEM; + } + (void)cdf_mem_copy(ptrn, pattern, sizeof(*ptrn)); + + msg_q.type = WMA_WOW_ADD_PTRN; + msg_q.reserved = 0; + msg_q.bodyptr = ptrn; + msg_q.bodyval = 0; + + sms_log(pMac, LOG1, FL("Sending WMA_WOWL_ADD_BCAST_PTRN to HAL")); + ret_code = wma_post_ctrl_msg(pMac, &msg_q); + if (eSIR_SUCCESS != ret_code) { + sms_log(pMac, LOGE, + FL("Posting WMA_WOWL_ADD_BCAST_PTRN failed, reason=%X"), + ret_code); + } + return ret_code; +} + +/** + * sme_wow_delete_pattern() - delete user configured wow pattern in target + * @hHal: handle returned by mac_open. + * @pattern: pointer to delete pattern parameter + * @sessionId: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_wow_delete_pattern(tHalHandle hal, + struct wow_delete_pattern *pattern, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + struct wow_delete_pattern *delete_ptrn; + tSirRetStatus ret_code = eSIR_SUCCESS; + tSirMsgQ msg_q; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_WOWL_DELBCAST_PATTERN, sessionId, + 0)); + delete_ptrn = cdf_mem_malloc(sizeof(*delete_ptrn)); + if (NULL == delete_ptrn) { + sms_log(pMac, LOGP, + FL("Fail to allocate memory for WoWLAN Delete Bcast Pattern ")); + return CDF_STATUS_E_NOMEM; + } + (void)cdf_mem_copy(delete_ptrn, pattern, sizeof(*delete_ptrn)); + msg_q.type = WMA_WOW_DEL_PTRN; + msg_q.reserved = 0; + msg_q.bodyptr = delete_ptrn; + msg_q.bodyval = 0; + + sms_log(pMac, LOG1, FL("Sending WMA_WOWL_DEL_BCAST_PTRN")); + + ret_code = wma_post_ctrl_msg(pMac, &msg_q); + if (eSIR_SUCCESS != ret_code) { + sms_log(pMac, LOGE, + FL("Posting WMA_WOWL_DEL_BCAST_PTRN failed, reason=%X"), + ret_code); + } + return ret_code; +} + +/** + * sme_enter_wowl(): SME API exposed to HDD to request enabling of WOWL mode. + * @hal_ctx - The handle returned by mac_open. + * @enter_wowl_callback_routine - Callback routine provided by HDD. + * Used for success/failure notification by SME + * @enter_wowl_callback_context - A cookie passed by HDD, that is passed + * back to HDD at the time of callback. + * @wake_reason_ind_cb - Callback routine provided by HDD. + * Used for Wake Reason Indication by SME + * @wake_reason_ind_cb_ctx - A cookie passed by HDD, that is passed + * back to HDD at the time of callback. + * + * 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. + * + * Return: CDF_STATUS + * CDF_STATUS_SUCCESS Device is already in WoWLAN mode + * CDF_STATUS_E_FAILURE Device cannot enter WoWLAN mode. + * CDF_STATUS_PMC_PENDING Request accepted. SME will enable + * WOWL after BMPS mode is entered. + */ +CDF_STATUS sme_enter_wowl(tHalHandle hal_ctx, + void (*enter_wowl_callback_routine)(void + *callback_context, + CDF_STATUS status), + void *enter_wowl_callback_context, +#ifdef WLAN_WAKEUP_EVENTS + void (*wakeIndicationCB)(void *callback_context, + tpSirWakeReasonInd + wake_reason_ind), + void *wakeIndicationCBContext, +#endif /* WLAN_WAKEUP_EVENTS */ + tpSirSmeWowlEnterParams wowl_enter_params, + uint8_t session_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ENTER_WOWL, session_id, 0)); + + /* cache the WOWL information */ + ps_global_info->ps_params[session_id].wowl_enter_params = + *wowl_enter_params; + ps_global_info->ps_params[session_id].enter_wowl_callback_routine = + enter_wowl_callback_routine; + ps_global_info->ps_params[session_id].enter_wowl_callback_context = + enter_wowl_callback_context; +#ifdef WLAN_WAKEUP_EVENTS + /* Cache the Wake Reason Indication callback information */ + ps_global_info->ps_params[session_id].wake_reason_ind_cb = + wakeIndicationCB; + ps_global_info->ps_params[session_id].wake_reason_ind_cb_ctx = + wakeIndicationCBContext; +#endif /* WLAN_WAKEUP_EVENTS */ + + status = sme_ps_process_command(mac_ctx, session_id, SME_PS_WOWL_ENTER); + return status; +} +/** + *sme_exit_wowl(): SME API exposed to HDD to request exit from WoWLAN mode. + * @hal_ctx - The handle returned by mac_open. + * @wowl_exit_params - Carries info on which smesession + * wowl exit is requested. + * + * SME will initiate exit from WoWLAN mode and device will be + * put in BMPS mode. + * Return CDF_STATUS + * CDF_STATUS_E_FAILURE Device cannot exit WoWLAN mode. + * CDF_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + */ +CDF_STATUS sme_exit_wowl(tHalHandle hal_ctx, + tpSirSmeWowlExitParams wowl_exit_params) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + uint8_t session_id; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_EXIT_WOWL, NO_SESSION, 0)); + session_id = wowl_exit_params->sessionId; + status = sme_ps_process_command(mac_ctx, session_id, SME_PS_WOWL_EXIT); + return status; +} + +/** + * sme_roam_set_key() - To set encryption key. + * @hal: hal global context + * @session_id: session id + * @set_key: pointer to a caller allocated object of tCsrSetContextInfo + * @ptr_roam_id: Upon success return, this is the id caller can use to + * identify the request in roamcallback + * + * This function should be called only when connected. This is an asynchronous + * API. + * + * Return: Status of operation + */ +CDF_STATUS sme_roam_set_key(tHalHandle hal, uint8_t session_id, + tCsrRoamSetKey *set_key, uint32_t *ptr_roam_id) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + uint32_t roam_id; + uint32_t i; + tCsrRoamSession *session = NULL; + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_SET_KEY, + session_id, 0)); + if (set_key->keyLength > CSR_MAX_KEY_LEN) { + sms_log(mac_ctx, LOGE, FL("Invalid key length %d"), + set_key->keyLength); + return CDF_STATUS_E_FAILURE; + } + /*Once Setkey is done, we can go in BMPS */ + if (set_key->keyLength) + ps_global_info->remain_in_power_active_till_dhcp = false; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam); + if (ptr_roam_id) + *ptr_roam_id = roam_id; + + sms_log(mac_ctx, LOG2, FL("keyLength %d"), set_key->keyLength); + for (i = 0; i < set_key->keyLength; i++) + sms_log(mac_ctx, LOG2, FL("%02x"), set_key->Key[i]); + + sms_log(mac_ctx, LOG2, "\n session_id=%d roam_id=%d", session_id, + roam_id); + session = CSR_GET_SESSION(mac_ctx, session_id); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id); + sme_release_global_lock(&mac_ctx->sme); + return CDF_STATUS_E_FAILURE; + } + if (CSR_IS_INFRA_AP(&session->connectedProfile) + && set_key->keyDirection == eSIR_TX_DEFAULT) { + if ((eCSR_ENCRYPT_TYPE_WEP40 == set_key->encType) + || (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == + set_key->encType)) { + session->pCurRoamProfile->negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + } + if ((eCSR_ENCRYPT_TYPE_WEP104 == set_key->encType) + || (eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == + set_key->encType)) { + session->pCurRoamProfile->negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + } + } + status = csr_roam_set_key(mac_ctx, session_id, set_key, roam_id); + sme_release_global_lock(&mac_ctx->sme); + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_rssi + \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 p_cds_context - cds context + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_rssi(tHalHandle hHal, + tCsrRssiCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, int8_t lastRSSI, + void *pContext, void *p_cds_context) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_RSSI, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_get_rssi(pMac, callback, + staId, bssId, lastRSSI, + pContext, p_cds_context); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_snr + \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 p_cds_context - cds context + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_snr(tHalHandle hHal, + tCsrSnrCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, void *pContext) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_get_snr(pMac, callback, staId, bssId, pContext); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* --------------------------------------------------------------------------- + \fn sme_get_tsm_stats + \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 p_cds_context - cds context + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_tsm_stats(tHalHandle hHal, + tCsrTsmStatsCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, + void *pContext, void *p_cds_context, uint8_t tid) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_get_tsm_stats(pMac, callback, + staId, bssId, pContext, p_cds_context, + tid); + sme_release_global_lock(&pMac->sme); + } + return status; +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_get_statistics + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_statistics(tHalHandle hHal, + eCsrStatsRequesterType requesterId, + uint32_t statsMask, tCsrStatsCallback callback, + uint32_t periodicity, bool cache, uint8_t staId, + void *pContext, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_STATS, NO_SESSION, + periodicity)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + csr_get_statistics(pMac, requesterId, statsMask, callback, + periodicity, cache, staId, pContext, + sessionId); + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +CDF_STATUS sme_get_link_status(tHalHandle hHal, + tCsrLinkStatusCallback callback, + void *pContext, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tAniGetLinkStatus *pMsg; + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pMsg = cdf_mem_malloc(sizeof(tAniGetLinkStatus)); + if (NULL == pMsg) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for link status", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + pMsg->msgType = WMA_LINK_STATUS_GET_REQ; + pMsg->msgLen = (uint16_t) sizeof(tAniGetLinkStatus); + pMsg->sessionId = sessionId; + pMac->sme.linkStatusContext = pContext; + pMac->sme.linkStatusCallback = callback; + + cds_message.type = WMA_LINK_STATUS_GET_REQ; + cds_message.bodyptr = pMsg; + cds_message.reserved = 0; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_message))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post LINK STATUS MSG fail", __func__); + cdf_mem_free(pMsg); + pMac->sme.linkStatusContext = NULL; + pMac->sme.linkStatusCallback = NULL; + status = CDF_STATUS_E_FAILURE; + } + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_get_country_code + + \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 CDF_STATUS SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_get_country_code(tHalHandle hHal, uint8_t *pBuf, uint8_t *pbLen) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE, NO_SESSION, 0)); + + return csr_get_country_code(pMac, pBuf, pbLen); +} + +/** + * sme_apply_channel_power_info_to_fw() - sends channel info to fw + * @hHal: hal handle + * + * This function sends the channel power info to firmware + * + * Return: none + */ +void sme_apply_channel_power_info_to_fw(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + csr_apply_channel_power_info_wrapper(pMac); +} + +/* some support functions */ +bool sme_is11d_supported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + return csr_is11d_supported(pMac); +} + +bool sme_is11h_supported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + return csr_is11h_supported(pMac); +} + +bool sme_is_wmm_supported(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + return csr_is_wmm_supported(pMac); +} + +/* --------------------------------------------------------------------------- + + \fn sme_change_country_code + + \brief Change Country code from upperlayer during WLAN driver operation. + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + + \param pCountry New Country Code String + + \param sendRegHint If we want to send reg hint to nl80211 + + \return CDF_STATUS SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_change_country_code(tHalHandle hHal, + tSmeChangeCountryCallback callback, + uint8_t *pCountry, + void *pContext, + void *p_cds_context, + tAniBool countryFromUserSpace, + tAniBool sendRegHint) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg; + tAniChangeCountryCodeReq *pMsg; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CHANGE_CNTRYCODE, NO_SESSION, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL(" called")); + + if ((pMac->roam.configParam.Is11dSupportEnabledOriginal == true) + && (!pMac->roam.configParam. + fSupplicantCountryCodeHasPriority)) { + + sms_log(pMac, LOGW, + "Set Country Code Fail since the STA is associated and userspace does not have priority "); + + sme_release_global_lock(&pMac->sme); + status = CDF_STATUS_E_FAILURE; + return status; + } + + pMsg = cdf_mem_malloc(sizeof(tAniChangeCountryCodeReq)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, + " csrChangeCountryCode: failed to allocate mem for req"); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + pMsg->msgType = eWNI_SME_CHANGE_COUNTRY_CODE; + pMsg->msgLen = (uint16_t) sizeof(tAniChangeCountryCodeReq); + cdf_mem_copy(pMsg->countryCode, pCountry, 3); + pMsg->countryFromUserSpace = countryFromUserSpace; + pMsg->sendRegHint = sendRegHint; + pMsg->changeCCCallback = callback; + pMsg->pDevContext = pContext; + pMsg->p_cds_context = p_cds_context; + + msg.type = eWNI_SME_CHANGE_COUNTRY_CODE; + msg.bodyptr = pMsg; + msg.reserved = 0; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(pMac, LOGE, + " sme_change_country_code failed to post msg to self "); + cdf_mem_free((void *)pMsg); + status = CDF_STATUS_E_FAILURE; + } + sms_log(pMac, LOG1, FL(" returned")); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + + \fn sme_generic_change_country_code + + \brief Change Country code from upperlayer during WLAN driver operation. + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + + \param pCountry New Country Code String + + \param reg_domain regulatory domain + + \return CDF_STATUS SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + + -----------------------------------------------------------------------------*/ +CDF_STATUS sme_generic_change_country_code(tHalHandle hHal, + uint8_t *pCountry, + v_REGDOMAIN_t reg_domain) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg; + tAniGenericChangeCountryCodeReq *pMsg; + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: pMac is null", __func__); + return status; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL(" called")); + pMsg = cdf_mem_malloc(sizeof(tAniGenericChangeCountryCodeReq)); + + if (NULL == pMsg) { + sms_log(pMac, LOGE, + " sme_generic_change_country_code: failed to allocate mem for req"); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + pMsg->msgType = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; + pMsg->msgLen = + (uint16_t) sizeof(tAniGenericChangeCountryCodeReq); + cdf_mem_copy(pMsg->countryCode, pCountry, 2); + pMsg->domain_index = reg_domain; + pMsg->countryCode[2] = ' '; /* For ASCII space */ + + msg.type = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; + msg.bodyptr = pMsg; + msg.reserved = 0; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(pMac, LOGE, + "sme_generic_change_country_code failed to post msg to self"); + cdf_mem_free(pMsg); + status = CDF_STATUS_E_FAILURE; + } + sms_log(pMac, LOG1, FL(" returned")); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_dhcp_start_ind + + \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 CDF_STATUS SUCCESS. + + FAILURE or RESOURCES The API finished and failed. + --------------------------------------------------------------------------*/ +CDF_STATUS sme_dhcp_start_ind(tHalHandle hHal, + uint8_t device_mode, + uint8_t *macAddr, uint8_t sessionId) +{ + CDF_STATUS status; + CDF_STATUS cdf_status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tAniDHCPInd *pMsg; + tCsrRoamSession *pSession; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found "), + sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + pMsg = (tAniDHCPInd *) cdf_mem_malloc(sizeof(tAniDHCPInd)); + if (NULL == pMsg) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp start", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + pMsg->msgType = WMA_DHCP_START_IND; + pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); + pMsg->device_mode = device_mode; + cdf_mem_copy(pMsg->adapterMacAddr, macAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->peerMacAddr, + pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + cds_message.type = WMA_DHCP_START_IND; + cds_message.bodyptr = pMsg; + cds_message.reserved = 0; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post DHCP Start MSG fail", __func__); + cdf_mem_free(pMsg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_dhcp_stop_ind + + \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 CDF_STATUS SUCCESS. + FAILURE or RESOURCES The API finished and failed. + --------------------------------------------------------------------------*/ +CDF_STATUS sme_dhcp_stop_ind(tHalHandle hHal, + uint8_t device_mode, + uint8_t *macAddr, uint8_t sessionId) +{ + CDF_STATUS status; + CDF_STATUS cdf_status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tAniDHCPInd *pMsg; + tCsrRoamSession *pSession; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found "), + sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + pMsg = (tAniDHCPInd *) cdf_mem_malloc(sizeof(tAniDHCPInd)); + if (NULL == pMsg) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp stop", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + pMsg->msgType = WMA_DHCP_STOP_IND; + pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); + pMsg->device_mode = device_mode; + cdf_mem_copy(pMsg->adapterMacAddr, macAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->peerMacAddr, + pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + cds_message.type = WMA_DHCP_STOP_IND; + cds_message.bodyptr = pMsg; + cds_message.reserved = 0; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post DHCP Stop MSG fail", __func__); + cdf_mem_free(pMsg); + status = CDF_STATUS_E_FAILURE; + } + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_cfg_privacy + \brief API to set configure privacy parameters + \param hHal - The handle returned by mac_open. + \param pProfile - Pointer CSR Roam profile. + \param fPrivacy - This parameter indicates status of privacy + + \return void + ---------------------------------------------------------------------------*/ +void sme_set_cfg_privacy(tHalHandle hHal, + tCsrRoamProfile *pProfile, bool fPrivacy) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_CFGPRIVACY, NO_SESSION, 0)); + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + csr_set_cfg_privacy(pMac, pProfile, fPrivacy); + sme_release_global_lock(&pMac->sme); + } +} + +#if defined WLAN_FEATURE_VOWIFI +/* --------------------------------------------------------------------------- + \fn sme_neighbor_report_request + \brief API to request neighbor report. + \param hHal - The handle returned by mac_open. + \param pRrmNeighborReq - Pointer to a caller allocated object of type + tRrmNeighborReq. Caller owns the memory and is + responsible for freeing it. + \return CDF_STATUS + CDF_STATUS_E_FAILURE - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_neighbor_report_request(tHalHandle hHal, uint8_t sessionId, + tpRrmNeighborReq pRrmNeighborReq, + tpRrmNeighborRspCallbackInfo callbackInfo) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, NO_SESSION, + 0)); + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + status = + sme_rrm_neighbor_report_request(hHal, sessionId, + pRrmNeighborReq, callbackInfo); + sme_release_global_lock(&pMac->sme); + } + + return status; +} +#endif + +void sms_log(tpAniSirGlobal pMac, uint32_t 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. */ + + log_debug(pMac, SIR_SMS_MODULE_ID, loglevel, pString, marker); + + va_end(marker); /* Reset variable arguments. */ + } +#endif +} + +/* --------------------------------------------------------------------------- + \fn sme_get_wcnss_wlan_compiled_version + \brief This API returns the version of the WCNSS WLAN API with + which the HOST driver was built + \param hHal - The handle returned by mac_open. + \param pVersion - Points to the Version structure to be filled + \return CDF_STATUS + CDF_STATUS_E_INVAL - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_wcnss_wlan_compiled_version(tHalHandle hHal, + tSirVersionType *pVersion) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + if (pVersion != NULL) + status = CDF_STATUS_SUCCESS; + else + status = CDF_STATUS_E_INVAL; + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_wcnss_wlan_reported_version + \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 mac_open. + \param pVersion - Points to the Version structure to be filled + \return CDF_STATUS + CDF_STATUS_E_INVAL - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_wcnss_wlan_reported_version(tHalHandle hHal, + tSirVersionType *pVersion) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + if (pVersion != NULL) + status = CDF_STATUS_SUCCESS; + else + status = CDF_STATUS_E_INVAL; + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_wcnss_software_version + \brief This API returns the version string of the WCNSS driver + \param hHal - The handle returned by mac_open. + \param pVersion - Points to the Version string buffer to be filled + \param versionBufferSize - THe size of the Version string buffer + \return CDF_STATUS + CDF_STATUS_E_INVAL - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_wcnss_software_version(tHalHandle hHal, + uint8_t *pVersion, + uint32_t versionBufferSize) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_CONTEXT_t cds_context = cds_get_global_context(); + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + if (pVersion != NULL) { + status = + wma_get_wcnss_software_version(cds_context, + pVersion, + versionBufferSize); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_wcnss_hardware_version + \brief This API returns the version string of the WCNSS hardware + \param hHal - The handle returned by mac_open. + \param pVersion - Points to the Version string buffer to be filled + \param versionBufferSize - THe size of the Version string buffer + \return CDF_STATUS + CDF_STATUS_E_INVAL - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_get_wcnss_hardware_version(tHalHandle hHal, + uint8_t *pVersion, + uint32_t versionBufferSize) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + if (pVersion != NULL) + status = CDF_STATUS_SUCCESS; + else + status = CDF_STATUS_E_INVAL; + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +#ifdef FEATURE_WLAN_WAPI + +/* --------------------------------------------------------------------------- + \fn sme_scan_get_bkid_candidate_list + \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 retruning, this is + either the number needed or number of items put into + pPmkidList + \return CDF_STATUS - 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 + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_scan_get_bkid_candidate_list(tHalHandle hHal, uint32_t sessionId, + tBkidCandidateInfo *pBkidList, + uint32_t *pNumItems) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + csr_scan_get_bkid_candidate_list(pMac, sessionId, pBkidList, + pNumItems); + sme_release_global_lock(&pMac->sme); + } + + return status; +} +#endif /* FEATURE_WLAN_WAPI */ + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/***************************************************************************** + OEM DATA related modifications and function additions +*****************************************************************************/ + +/* --------------------------------------------------------------------------- + \fn sme_oem_data_req + \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 + \param callback - a callback function that is called upon finish + \param pContext - a pointer passed in for the callback + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_oem_data_req(tHalHandle hHal, + uint8_t sessionId, + tOemDataReqConfig *pOemDataReqConfig, + uint32_t *pOemDataReqID, + oem_data_oem_data_reqCompleteCallback callback, + void *pContext) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do { + /* acquire the lock for the sme object */ + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + uint32_t lOemDataReqId = pMac->oemData.oemDataReqID++; /* let it wrap around */ + + if (pOemDataReqID) { + *pOemDataReqID = lOemDataReqId; + } else { + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + status = + oem_data_oem_data_req(hHal, sessionId, + pOemDataReqConfig, pOemDataReqID, + callback, pContext); + + /* release the lock for the sme object */ + sme_release_global_lock(&pMac->sme); + } + } while (0); + + sms_log(pMac, LOGW, "exiting function %s", __func__); + + return status; +} + +#endif /*FEATURE_OEM_DATA_SUPPORT */ + +/*-------------------------------------------------------------------------- + + \brief sme_open_session() - Open a session for scan/roam operation. + + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + \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 CDF_STATUS_SUCCESS - session is opened. sessionId returned. + + Other status means SME is failed to open the session. + CDF_STATUS_E_RESOURCES - no more session available. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_open_session(tHalHandle hHal, csr_roam_completeCallback callback, + void *pContext, + uint8_t *pSelfMacAddr, uint8_t *pbSessionId, + uint32_t type, uint32_t subType) +{ + CDF_STATUS status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: type=%d, subType=%d", __func__, type, subType); + + if (NULL == pbSessionId) { + status = CDF_STATUS_E_INVAL; + } else { + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = + csr_roam_open_session(pMac, callback, pContext, + pSelfMacAddr, pbSessionId, type, + subType); + + sme_release_global_lock(&pMac->sme); + } + } + if (NULL != pbSessionId) + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_OPEN_SESSION, + *pbSessionId, 0)); + + return status; +} + +/*-------------------------------------------------------------------------- + + \brief sme_close_session() - Open a session for scan/roam operation. + + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + + \param sessionId - A previous opened session's ID. + + \return CDF_STATUS_SUCCESS - session is closed. + + Other status means SME is failed to open the session. + CDF_STATUS_E_INVAL - session is not opened. + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId, + csr_roamSessionCloseCallback callback, + void *pContext) +{ + CDF_STATUS status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_close_session(pMac, sessionId, false, + callback, pContext); + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_roam_update_apwpsie + + \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 CDF_STATUS – SUCCESS – + + FAILURE or RESOURCES – The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_update_apwpsie(tHalHandle hHal, uint8_t sessionId, + tSirAPWPSIEs *pAPWPSIES) +{ + + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + status = csr_roam_update_apwpsie(pMac, sessionId, pAPWPSIES); + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_roam_update_apwparsni_es + + \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 CDF_STATUS – SUCCESS – + + FAILURE or RESOURCES – The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_update_apwparsni_es(tHalHandle hHal, uint8_t sessionId, + tSirRSNie *pAPSirRSNie) +{ + + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + status = csr_roam_update_wparsni_es(pMac, sessionId, pAPSirRSNie); + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_change_mcc_beacon_interval + + \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 CDF_STATUS SUCCESS + FAILURE or RESOURCES + The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_change_mcc_beacon_interval(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + sms_log(pMac, LOG1, FL("Update Beacon PARAMS ")); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_send_chng_mcc_beacon_interval(pMac, sessionId); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/** + * sme_set_host_offload(): API to set the host offload feature. + * @hHal: The handle returned by mac_open. + * @sessionId: Session Identifier + * @request: Pointer to the offload request. + * + * Return CDF_STATUS + */ +CDF_STATUS sme_set_host_offload(tHalHandle hHal, uint8_t sessionId, + tpSirHostOffloadReq request) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD, sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { +#ifdef WLAN_NS_OFFLOAD + if (SIR_IPV6_NS_OFFLOAD == request->offloadType) { + status = sme_set_ps_ns_offload(hHal, request, + sessionId); + } else +#endif /* WLAN_NS_OFFLOAD */ + { + status = sme_set_ps_host_offload(hHal, request, + sessionId); + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +/** + * sme_set_gtk_offload(): API to set GTK offload information. + * @hHal: The handle returned by mac_open. + * @sessionId: Session Identifier + * @pGtkOffload: Pointer to the GTK offload request.. + * + * Return CDF_STATUS + */ +CDF_STATUS sme_set_gtk_offload(tHalHandle hHal, + tpSirGtkOffloadParams pGtkOffload, + uint8_t sessionId) +{ + tpSirGtkOffloadParams request_buf; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "%s: KeyReplayCounter: %lld", __func__, + pGtkOffload->ullKeyReplayCounter); + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Session not found ", __func__); + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for GTK offload request")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + *request_buf = *pGtkOffload; + + msg.type = WMA_GTK_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post SIR_HAL_SET_GTK_OFFLOAD message to HAL")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_get_gtk_offload(): API to get GTK offload information + * @hHal: The handle returned by mac_open. + * @callback_routine: callback_routine. + * @sessionId: Session Identifier. + * callback_context: callback_context. + * + * Return CDF_STATUS + */ +CDF_STATUS sme_get_gtk_offload(tHalHandle hHal, + gtk_offload_get_info_callback callback_routine, + void *callback_context, uint8_t session_id) +{ + tpSirGtkOffloadGetInfoRspParams request_buf; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: Entered", + __func__); + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Session not found ", __func__); + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for Get GTK offload request")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(request_buf->bssId, pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + msg.type = WMA_GTK_OFFLOAD_GETINFO_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + + /* Cache the Get GTK Offload callback information */ + if (NULL != pMac->sme.gtk_offload_get_info_cb) { + + /* 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->sme.gtk_offload_get_info_cb = callback_routine; + pMac->sme.gtk_offload_get_info_cb_context = callback_context; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_GTK_OFFLOAD_GETINFO_REQ message to WMA")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + +/* --------------------------------------------------------------------------- + \fn sme_set_keep_alive + \brief API to set the Keep Alive feature. + \param hHal - The handle returned by mac_open. + \param request - Pointer to the Keep Alive request. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_keep_alive(tHalHandle hHal, uint8_t session_id, + tpSirKeepAliveReq request) +{ + tpSirKeepAliveReq request_buf; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_LOW, + FL("WMA_SET_KEEP_ALIVE message")); + + if (pSession == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Session not Found")); + return CDF_STATUS_E_FAILURE; + } + request_buf = cdf_mem_malloc(sizeof(tSirKeepAliveReq)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for keep alive request")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(request->bssId, pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(request_buf, request, sizeof(tSirKeepAliveReq)); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_LOW, + "buff TP %d input TP %d ", request_buf->timePeriod, + request->timePeriod); + request_buf->sessionId = session_id; + + msg.type = WMA_SET_KEEP_ALIVE; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_SET_KEEP_ALIVE message to WMA")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +/* --------------------------------------------------------------------------- + \fn sme_set_preferred_network_list + \brief API to set the Preferred Network List Offload feature. + \param hHal - The handle returned by mac_open. + \param request - Pointer to the offload request. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_preferred_network_list(tHalHandle hHal, + tpSirPNOScanReq request, + uint8_t sessionId, + void (*callback_routine)(void *callback_context, + tSirPrefNetworkFoundInd + *pPrefNetworkFoundInd), + void *callback_context) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sme_set_ps_preferred_network_list(hHal, request, sessionId, + callback_routine, callback_context); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +#endif /* FEATURE_WLAN_SCAN_PNO */ + +/* --------------------------------------------------------------------------- + \fn sme_abort_mac_scan + \brief API to cancel MAC scan. + \param hHal - The handle returned by mac_open. + \param sessionId - sessionId on which we need to abort scan. + \param reason - Reason to abort the scan. + \return CDF_STATUS + CDF_STATUS_E_FAILURE - failure + CDF_STATUS_SUCCESS success + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_abort_mac_scan(tHalHandle hHal, uint8_t sessionId, + eCsrAbortReason reason) +{ + CDF_STATUS status; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ABORT_MACSCAN, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_scan_abort_mac_scan(pMac, sessionId, reason); + + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* ---------------------------------------------------------------------------- + \fn sme_get_operation_channel + \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 CDF_STATUS_SUCCESS + CDF_STATUS_E_FAILURE + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_get_operation_channel(tHalHandle hHal, uint32_t *pChannel, + uint8_t 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 CDF_STATUS_SUCCESS; + } + } + return CDF_STATUS_E_FAILURE; +} /* sme_get_operation_channel ends here */ + +/* --------------------------------------------------------------------------- + + \fn sme_RegisterMgtFrame + + \brief To register managment 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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_register_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + uint16_t frameType, uint8_t *matchData, + uint16_t matchLen) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REGISTER_MGMTFR, sessionId, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + tSirRegisterMgmtFrame *pMsg; + uint16_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), + sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!CSR_IS_SESSION_ANY(sessionId) && !pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s Invalid Sessionid", __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + len = sizeof(tSirRegisterMgmtFrame) + matchLen; + + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set(pMsg, len, 0); + pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; + pMsg->length = len; + pMsg->sessionId = sessionId; + pMsg->registerFrame = true; + pMsg->frameType = frameType; + pMsg->matchLen = matchLen; + cdf_mem_copy(pMsg->matchData, matchData, matchLen); + status = cds_send_mb_message_to_mac(pMsg); + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_DeregisterMgtFrame + + \brief To De-register managment 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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_deregister_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + uint16_t frameType, uint8_t *matchData, + uint16_t matchLen) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR, sessionId, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + tSirRegisterMgmtFrame *pMsg; + uint16_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), + sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!CSR_IS_SESSION_ANY(sessionId) && !pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s Invalid Sessionid", __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + len = sizeof(tSirRegisterMgmtFrame) + matchLen; + + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set(pMsg, len, 0); + pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ; + pMsg->length = len; + pMsg->registerFrame = false; + pMsg->frameType = frameType; + pMsg->matchLen = matchLen; + cdf_mem_copy(pMsg->matchData, matchData, matchLen); + status = cds_send_mb_message_to_mac(pMsg); + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/** + * sme_remain_on_channel - API to request remain on channel for 'x' duration + * + * @hHal: pointer to MAC handle + * @session_id: Session identifier + * @channel: channel information + * @duration: duration in ms + * @callback: HDD registered callback to process reaminOnChannelRsp + * @context: HDD Callback param + * @scan_id: scan identifier + * + * This function process the roc request and generates scan identifier.s + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_remain_on_channel(tHalHandle hHal, uint8_t session_id, + uint8_t channel, uint32_t duration, + remainOnChanCallback callback, + void *pContext, uint8_t isP2PProbeReqAllowed, + uint32_t *scan_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal); + uint32_t san_req_id, scan_count; + struct ani_roc_req *roc_msg; + cds_msg_t msg; + + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_REMAIN_ONCHAN, session_id, 0)); + + scan_count = csr_ll_count(&mac_ctx->sme.smeScanCmdActiveList); + if (scan_count >= mac_ctx->scan.max_scan_count) { + sms_log(mac_ctx, LOGE, FL("Max scan reached")); + return CDF_STATUS_E_FAILURE; + } + + wma_get_scan_id(&san_req_id); + *scan_id = san_req_id; + status = sme_acquire_global_lock(&mac_ctx->sme); + + sms_log(mac_ctx, LOG1, FL(" called")); + roc_msg = cdf_mem_malloc(sizeof(struct ani_roc_req)); + if (NULL == roc_msg) { + sms_log(mac_ctx, LOGE, + " scan_req: failed to allocate mem for msg"); + sme_release_global_lock(&mac_ctx->sme); + return CDF_STATUS_E_NOMEM; + } + roc_msg->msg_type = eWNI_SME_ROC_CMD; + roc_msg->msg_len = (uint16_t) sizeof(struct ani_roc_req); + roc_msg->session_id = session_id; + roc_msg->callback = callback; + roc_msg->duration = duration; + roc_msg->channel = channel; + roc_msg->is_p2pprobe_allowed = isP2PProbeReqAllowed; + roc_msg->ctx = pContext; + roc_msg->scan_id = *scan_id; + msg.type = eWNI_SME_ROC_CMD; + msg.bodyptr = roc_msg; + msg.reserved = 0; + msg.bodyval = 0; + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(mac_ctx, LOGE, + " sme_scan_req failed to post msg"); + cdf_mem_free(roc_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac_ctx->sme); + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_report_probe_req + \brief API to enable/disable forwarding of probeReq to apps in p2p. + \param hHal - The handle returned by mac_open. + \param falg: to set the Probe request forarding to wpa_supplicant in listen state in p2p + \return CDF_STATUS + ---------------------------------------------------------------------------*/ + +#ifndef WLAN_FEATURE_CONCURRENT_P2P +CDF_STATUS sme_report_probe_req(tHalHandle hHal, uint8_t flag) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do { + /* acquire the lock for the sme object */ + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* call set in context */ + pMac->p2pContext.probeReqForwarding = flag; + /* release the lock for the sme object */ + sme_release_global_lock(&pMac->sme); + } + } while (0); + + sms_log(pMac, LOGW, "exiting function %s", __func__); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_p2p_ie + \brief API to set the P2p Ie in p2p context + \param hHal - The handle returned by mac_open. + \param p2pIe - Ptr to p2pIe from HDD. + \param p2pIeLength: length of p2pIe + \return CDF_STATUS + ---------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_p2p_ie(tHalHandle hHal, void *p2pIe, uint32_t p2pIeLength) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_P2P_IE, NO_SESSION, 0)); + /* acquire the lock for the sme object */ + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (NULL != pMac->p2pContext.probeRspIe) { + cdf_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIeLength = 0; + } + + pMac->p2pContext.probeRspIe = cdf_mem_malloc(p2pIeLength); + if (NULL == pMac->p2pContext.probeRspIe) { + sms_log(pMac, LOGE, "%s: Unable to allocate P2P IE", + __func__); + pMac->p2pContext.probeRspIeLength = 0; + status = CDF_STATUS_E_NOMEM; + } else { + pMac->p2pContext.probeRspIeLength = p2pIeLength; + + sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG2, + pMac->p2pContext.probeRspIe, + pMac->p2pContext.probeRspIeLength); + cdf_mem_copy((uint8_t *) pMac->p2pContext.probeRspIe, + p2pIe, p2pIeLength); + } + + /* release the lock for the sme object */ + sme_release_global_lock(&pMac->sme); + } + + sms_log(pMac, LOG2, "exiting function %s", __func__); + + return status; +} +#endif + +/* --------------------------------------------------------------------------- + \fn sme_send_action + \brief API to send action frame from supplicant. + \param hHal - The handle returned by mac_open. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ + +CDF_STATUS sme_send_action(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBuf, uint32_t len, + uint16_t wait, bool noack, + uint16_t channel_freq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SEND_ACTION, sessionId, 0)); + /* acquire the lock for the sme object */ + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + p2p_send_action(hHal, sessionId, pBuf, len, wait, noack, + channel_freq); + /* release the lock for the sme object */ + sme_release_global_lock(&pMac->sme); + } + + sms_log(pMac, LOGW, "exiting function %s", __func__); + + return status; +} + +CDF_STATUS sme_cancel_remain_on_channel(tHalHandle hHal, + uint8_t sessionId, uint32_t scan_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CANCEL_REMAIN_ONCHAN, sessionId, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = p2p_cancel_remain_on_channel(hHal, sessionId, scan_id); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* Power Save Related */ +CDF_STATUS sme_p2p_set_ps(tHalHandle hHal, tP2pPsConfig *data) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = p2p_set_ps(hHal, data); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_configure_rxp_filter + + \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 mac_open. + + 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 CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, + tpSirWlanSetRxpFilters wlanRxpFilterParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_RXPFIL, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cds_message.bodyptr = wlanRxpFilterParam; + cds_message.type = WMA_CFG_RXP_FILTER_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_configure_suspend_ind + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be suspended + + \param + + hHal - The handle returned by mac_open. + + wlanSuspendParam- Depicts the wlan suspend params + + csr_readyToSuspendCallback - Callback to be called when ready to suspend + event is received. + callback_context - Context associated with csr_readyToSuspendCallback. + + \return CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, + tpSirWlanSuspendParam wlanSuspendParam, + csr_readyToSuspendCallback callback, + void *callback_context) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_SUSPENDIND, NO_SESSION, + 0)); + + pMac->readyToSuspendCallback = callback; + pMac->readyToSuspendContext = callback_context; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cds_message.bodyptr = wlanSuspendParam; + cds_message.type = WMA_WLAN_SUSPEND_IND; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->readyToSuspendCallback = NULL; + pMac->readyToSuspendContext = NULL; + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_configure_resume_req + + \brief + SME will pass this request to lower mac to Indicate that the wlan needs to + be Resumed + + \param + + hHal - The handle returned by mac_open. + + wlanResumeParam- Depicts the wlan resume params + + \return CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_resume_req(tHalHandle hHal, + tpSirWlanResumeParam wlanResumeParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_RESUMEREQ, NO_SESSION, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cds_message.bodyptr = wlanResumeParam; + cds_message.type = WMA_WLAN_RESUME_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +/* --------------------------------------------------------------------------- + + \fn sme_configure_ext_wo_w + + \brief + SME will pass this request to lower mac to configure Extr WoW + + \param + + hHal - The handle returned by mac_open. + + wlanExtParams- Depicts the wlan Ext params + + \return CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_ext_wo_w(tHalHandle hHal, + tpSirExtWoWParams wlanExtParams, + csr_readyToExtWoWCallback callback, + void *callback_context) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tpSirExtWoWParams MsgPtr = cdf_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return CDF_STATUS_E_NOMEM; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW, NO_SESSION, 0)); + + pMac->readyToExtWoWCallback = callback; + pMac->readyToExtWoWContext = callback_context; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + /* serialize the req through MC thread */ + cdf_mem_copy(MsgPtr, wlanExtParams, sizeof(*MsgPtr)); + cds_message.bodyptr = MsgPtr; + cds_message.type = WMA_WLAN_EXT_WOW; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + pMac->readyToExtWoWCallback = NULL; + pMac->readyToExtWoWContext = NULL; + cdf_mem_free(MsgPtr); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + pMac->readyToExtWoWCallback = NULL; + pMac->readyToExtWoWContext = NULL; + cdf_mem_free(MsgPtr); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_configure_app_type1_params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by mac_open. + + wlanAppType1Params- Depicts the wlan App Type 1(Indoor) params + + \return CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_app_type1_params(tHalHandle hHal, + tpSirAppType1Params wlanAppType1Params) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tpSirAppType1Params MsgPtr = cdf_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return CDF_STATUS_E_NOMEM; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1, NO_SESSION, + 0)); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cdf_mem_copy(MsgPtr, wlanAppType1Params, sizeof(*MsgPtr)); + cds_message.bodyptr = MsgPtr; + cds_message.type = WMA_WLAN_SET_APP_TYPE1_PARAMS; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_mem_free(MsgPtr); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + cdf_mem_free(MsgPtr); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_configure_app_type2_params + + \brief + SME will pass this request to lower mac to configure Indoor WoW parameters. + + \param + + hHal - The handle returned by mac_open. + + wlanAppType2Params- Depicts the wlan App Type 2 (Outdoor) params + + \return CDF_STATUS + + --------------------------------------------------------------------------- */ +CDF_STATUS sme_configure_app_type2_params(tHalHandle hHal, + tpSirAppType2Params wlanAppType2Params) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tpSirAppType2Params MsgPtr = cdf_mem_malloc(sizeof(*MsgPtr)); + + if (!MsgPtr) + return CDF_STATUS_E_NOMEM; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2, NO_SESSION, + 0)); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cdf_mem_copy(MsgPtr, wlanAppType2Params, sizeof(*MsgPtr)); + cds_message.bodyptr = MsgPtr; + cds_message.type = WMA_WLAN_SET_APP_TYPE2_PARAMS; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_mem_free(MsgPtr); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + cdf_mem_free(MsgPtr); + } + + return status; +} +#endif + +/* --------------------------------------------------------------------------- + + \fn sme_get_infra_session_id + + \brief To get the session ID for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + + \return sessionid, -1 if infra session is not connected + + -------------------------------------------------------------------------------*/ +int8_t sme_get_infra_session_id(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int8_t sessionid = -1; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + sessionid = csr_get_infra_session_id(pMac); + + sme_release_global_lock(&pMac->sme); + } + + return sessionid; +} + +/* --------------------------------------------------------------------------- + + \fn sme_get_infra_operation_channel + + \brief To get the operating channel for infra session, if connected + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + \param sessionId - the sessionId returned by sme_open_session. + + \return operating channel, 0 if infra session is not connected + + -------------------------------------------------------------------------------*/ +uint8_t sme_get_infra_operation_channel(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t channel = 0; + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + channel = csr_get_infra_operation_channel(pMac, sessionId); + + sme_release_global_lock(&pMac->sme); + } + + return channel; +} + +/* This routine will return poerating 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 */ +uint8_t sme_get_concurrent_operation_channel(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t channel = 0; + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + channel = csr_get_concurrent_operation_channel(pMac); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, "%s: " + " Other Concurrent Channel = %d", __func__, channel); + sme_release_global_lock(&pMac->sme); + } + + return channel; +} + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch, + eCsrPhyMode sapPhyMode, + uint8_t cc_switch_mode) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint16_t channel = 0; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + channel = + csr_check_concurrent_channel_overlap(pMac, sap_ch, sapPhyMode, + cc_switch_mode); + sme_release_global_lock(&pMac->sme); + } + + return channel; +} +#endif + +#ifdef FEATURE_WLAN_SCAN_PNO +/****************************************************************************** +* +* Name: sme_preferred_network_found_ind +* +* Description: +* Invoke Preferred Network Found Indication +* +* Parameters: +* hHal - HAL handle for device +* pMsg - found network description +* +* Returns: CDF_STATUS +* +******************************************************************************/ +CDF_STATUS sme_preferred_network_found_ind(tHalHandle hHal, void *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = + (tSirPrefNetworkFoundInd *) pMsg; + uint8_t dumpSsId[SIR_MAC_MAX_SSID_LENGTH + 1]; + uint8_t ssIdLength = 0; + + if (NULL == pMsg) { + sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (pMac->pnoOffload) { + /* Call Preferred Network Found Indication callback routine. */ + if (pMac->sme.pref_netw_found_cb != NULL) { + pMac->sme.pref_netw_found_cb(pMac->sme. + preferred_network_found_ind_cb_ctx, + pPrefNetworkFoundInd); + } + return status; + } + + if (pPrefNetworkFoundInd->ssId.length > 0) { + ssIdLength = CSR_MIN(SIR_MAC_MAX_SSID_LENGTH, + pPrefNetworkFoundInd->ssId.length); + cdf_mem_copy(dumpSsId, pPrefNetworkFoundInd->ssId.ssId, + ssIdLength); + dumpSsId[ssIdLength] = 0; + sms_log(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_scan_flush_result(hHal); + + /* Save the frame to scan result */ + if (pPrefNetworkFoundInd->mesgLen > + sizeof(tSirPrefNetworkFoundInd)) { + /* we may have a frame */ + status = csr_scan_save_preferred_network_found(pMac, + pPrefNetworkFoundInd); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to save preferred network")); + } + } else { + sms_log(pMac, LOGE, + FL(" not enough data length %d needed %zu"), + pPrefNetworkFoundInd->mesgLen, + sizeof(tSirPrefNetworkFoundInd)); + } + + /* Call Preferred Netowrk Found Indication callback routine. */ + if (CDF_IS_STATUS_SUCCESS(status) + && (pMac->sme.pref_netw_found_cb != NULL)) { + pMac->sme.pref_netw_found_cb(pMac->sme. + preferred_network_found_ind_cb_ctx, + pPrefNetworkFoundInd); + } + } else { + sms_log(pMac, LOGE, "%s: callback failed - SSID is NULL", + __func__); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +#endif /* FEATURE_WLAN_SCAN_PNO */ + +CDF_STATUS sme_get_cfg_valid_channels(tHalHandle hHal, uint8_t *aValidChannels, + uint32_t *len) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_get_cfg_valid_channels(pMac, aValidChannels, len); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_handle_change_country_code + + \brief Change Country code, Reg Domain and channel list + + \details Country Code Priority + 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 courtry code. + User can send reset command XX (instead of country code) to reset the + country code to default values. + 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 mac_open. + \param pMsgBuf - MSG Buffer + + \return CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tAniChangeCountryCodeReq *pMsg; + v_REGDOMAIN_t domainIdIoctl; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + static country_code_t default_country; + pMsg = (tAniChangeCountryCodeReq *) pMsgBuf; + + /* + * if the reset Supplicant country code command is triggered, + * enable 11D, reset the country code and return + */ + if (true == + cdf_mem_compare(pMsg->countryCode, SME_INVALID_COUNTRY_CODE, 2)) { + pMac->roam.configParam.Is11dSupportEnabled = + pMac->roam.configParam.Is11dSupportEnabledOriginal; + + cdf_status = cds_read_default_country(default_country); + + /* read the country code and use it */ + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_mem_copy(pMsg->countryCode, + default_country, + WNI_CFG_COUNTRY_CODE_LEN); + } else { + status = CDF_STATUS_E_FAILURE; + return status; + } + /* + * Update the 11d country to default country so that when + * callback is received for this default country, driver will + * not disable the 11d taking it as valid country by user. + */ + sms_log(pMac, LOG1, + FL("Set default country code (%c%c) as invalid country received"), + pMsg->countryCode[0], pMsg->countryCode[1]); + cdf_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 = false; + } + } + + if (pMac->roam.configParam.Is11dSupportEnabled) + return CDF_STATUS_SUCCESS; + + /* Set Current Country code and Current Regulatory domain */ + status = csr_set_country_code(pMac, pMsg->countryCode); + if (CDF_STATUS_SUCCESS != status) { + /* Supplicant country code failed. So give 11D priority */ + pMac->roam.configParam.Is11dSupportEnabled = + pMac->roam.configParam.Is11dSupportEnabledOriginal; + sms_log(pMac, LOGE, "Set Country Code Fail %d", status); + return status; + } + + /* overwrite the defualt country code */ + cdf_mem_copy(pMac->scan.countryCodeDefault, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + + /* Get Domain ID from country code */ + status = csr_get_regulatory_domain_for_country(pMac, + pMac->scan.countryCodeCurrent, + (v_REGDOMAIN_t *) & + domainIdIoctl, COUNTRY_QUERY); + if (status != CDF_STATUS_SUCCESS) { + sms_log(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; + sms_log(pMac, LOG1, FL("Country Code unrecognized by driver")); + } + + status = wma_set_reg_domain(pMac, domainIdIoctl); + + if (status != CDF_STATUS_SUCCESS) { + sms_log(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) { + sms_log(pMac, LOGW, + FL + ("Clearing currentCountryBssid, countryCode11d")); + cdf_mem_zero(&pMac->scan.currentCountryBssid, + sizeof(struct cdf_mac_addr)); + cdf_mem_zero(pMac->scan.countryCode11d, + sizeof(pMac->scan.countryCode11d)); + } + } + + if (pMsg->changeCCCallback) { + ((tSmeChangeCountryCallback) (pMsg->changeCCCallback))((void *) + pMsg-> + pDevContext); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_handle_change_country_code_by_user() - handles country ch req + * @mac_ctx: mac global context + * @msg: request msg packet + * + * 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. + * + * Return: status of operation + */ +CDF_STATUS +sme_handle_change_country_code_by_user(tpAniSirGlobal mac_ctx, + tAniGenericChangeCountryCodeReq *msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + v_REGDOMAIN_t reg_domain_id; + bool is_11d_country = false; + bool supplicant_priority = + mac_ctx->roam.configParam.fSupplicantCountryCodeHasPriority; + + sms_log(mac_ctx, LOG1, FL(" called")); + reg_domain_id = (v_REGDOMAIN_t) msg->domain_index; + if (memcmp(msg->countryCode, mac_ctx->scan.countryCode11d, + CDS_COUNTRY_CODE_LEN) == 0) { + is_11d_country = true; + } + /* Set the country code given by userspace when 11dOriginal is false + * when 11doriginal is True,is_11d_country =0 and + * fSupplicantCountryCodeHasPriority = 0, then revert the country code, + * and return failure + */ + if (mac_ctx->roam.configParam.Is11dSupportEnabledOriginal == true + && !is_11d_country && !supplicant_priority) { + sms_log(mac_ctx, LOGW, + FL("Incorrect country req, nullify this")); + + /* 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 ((mac_ctx->scan.countryCode11d[0] == 0) + && (mac_ctx->scan.countryCode11d[1] == 0)) + status = csr_get_regulatory_domain_for_country(mac_ctx, + "00", (v_REGDOMAIN_t *) ®_domain_id, + COUNTRY_IE); + else + status = csr_get_regulatory_domain_for_country(mac_ctx, + mac_ctx->scan.countryCode11d, + (v_REGDOMAIN_t *) ®_domain_id, + COUNTRY_IE); + + return CDF_STATUS_E_FAILURE; + } + /* if Supplicant country code has priority, disable 11d */ + if (!is_11d_country && supplicant_priority) + mac_ctx->roam.configParam.Is11dSupportEnabled = false; + cdf_mem_copy(mac_ctx->scan.countryCodeCurrent, msg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + status = wma_set_reg_domain(mac_ctx, reg_domain_id); + if (false == is_11d_country) { + /* overwrite the defualt country code */ + cdf_mem_copy(mac_ctx->scan.countryCodeDefault, + mac_ctx->scan.countryCodeCurrent, + WNI_CFG_COUNTRY_CODE_LEN); + /* set to default domain ID */ + mac_ctx->scan.domainIdDefault = mac_ctx->scan.domainIdCurrent; + } + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac_ctx, 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 (!supplicant_priority && (false == is_11d_country)) { + sms_log(mac_ctx, LOGW, + FL("Clearing currentCountryBssid, countryCode11d")); + cdf_mem_zero(&mac_ctx->scan.currentCountryBssid, + sizeof(struct cdf_mac_addr)); + cdf_mem_zero(mac_ctx->scan.countryCode11d, + sizeof(mac_ctx->scan.countryCode11d)); + } + } + /* get the channels based on new cc */ + status = csr_get_channel_and_power_list(mac_ctx); + + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac_ctx, LOGE, FL("fail to get Channels")); + return status; + } + /* reset info based on new cc, and we are done */ + csr_apply_channel_power_info_wrapper(mac_ctx); + + /* Country code Changed, Purge Only scan result + * which does not have channel number belong to 11d + * channel list + */ + csr_scan_filter_results(mac_ctx); + /* Do active scans after the country is set by User hints or + * Country IE + */ + mac_ctx->scan.curScanType = eSIR_ACTIVE_SCAN; + sme_disconnect_connected_sessions(mac_ctx); + sms_log(mac_ctx, LOG1, FL(" returned")); + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_handle_change_country_code_by_core + + \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 mac_open. + \param pMsg - Carrying new CC set in kernel + + \return CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_handle_change_country_code_by_core(tpAniSirGlobal pMac, + tAniGenericChangeCountryCodeReq * + pMsg) +{ + CDF_STATUS status; + + sms_log(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])) { + sms_log(pMac, LOGW, + FL + ("Setting countryCode11d & countryCodeCurrent to world CC")); + cdf_mem_copy(pMac->scan.countryCode11d, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + cdf_mem_copy(pMac->scan.countryCodeCurrent, pMsg->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } + + status = wma_set_reg_domain(pMac, REGDOMAIN_WORLD); + + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, FL(" fail to set regId")); + return status; + } else { + status = csr_get_channel_and_power_list(pMac); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, FL(" fail to get Channels ")); + } else { + csr_apply_channel_and_power_list(pMac); + } + } + /* Country code Changed, Purge Only scan result + * which does not have channel number belong to 11d + * channel list + */ + csr_scan_filter_results(pMac); + sms_log(pMac, LOG1, FL(" returned")); + return CDF_STATUS_SUCCESS; +} + +static bool +sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch) +{ + uint8_t i; + tCsrChannel *ch_lst_info; + ch_lst_info = &mac_ctx->scan.base_channels; + for (i = 0; i < ch_lst_info->numChannels; i++) { + if (ch_lst_info->channelList[i] == curr_ch) + return true; + } + + ch_lst_info = &mac_ctx->scan.base40MHzChannels; + for (i = 0; i < ch_lst_info->numChannels; i++) { + if (ch_lst_info->channelList[i] == curr_ch) + return true; + } + return false; +} +/** + * sme_disconnect_connected_sessions() - Disconnect STA and P2P client session + * if channel is not supported + * @mac_ctx: mac global context + * + * If new country code does not support the channel on which STA/P2P client + * is connetced, it sends the disconnect to the AP/P2P GO + * + * Return: void + */ +void sme_disconnect_connected_sessions(tpAniSirGlobal mac_ctx) +{ + uint8_t session_id, found = false; + uint8_t curr_ch; + + for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) { + if (!csr_is_session_client_and_connected(mac_ctx, session_id)) + continue; + found = false; + /* Session is connected.Check the channel */ + curr_ch = csr_get_infra_operation_channel(mac_ctx, + session_id); + sms_log(mac_ctx, LOGW, + FL("Current Operating channel : %d, session :%d"), + curr_ch, session_id); + found = sme_search_in_base_ch_lst(mac_ctx, curr_ch); + if (!found) { + sms_log(mac_ctx, LOGW, FL("Disconnect Session :%d"), + session_id); + csr_roam_disconnect(mac_ctx, session_id, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + } +} + +/* --------------------------------------------------------------------------- + + \fn sme_handle_generic_change_country_code + + \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 mac_open. + \param pMsgBuf - message buffer + + \return CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac, + void *pMsgBuf) +{ + tAniGenericChangeCountryCodeReq *pMsg; + v_REGDOMAIN_t reg_domain_id; + + sms_log(pMac, LOG1, FL(" called")); + pMsg = (tAniGenericChangeCountryCodeReq *) pMsgBuf; + reg_domain_id = (v_REGDOMAIN_t) pMsg->domain_index; + + if (REGDOMAIN_COUNT == reg_domain_id) { + sme_handle_change_country_code_by_core(pMac, pMsg); + } else { + sme_handle_change_country_code_by_user(pMac, pMsg); + } + sms_log(pMac, LOG1, FL(" returned")); + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_PACKET_FILTERING +CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, + tpSirRcvFltMcAddrList pMulticastAddrs) +{ + tpSirRcvFltMcAddrList request_buf; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = NULL; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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) && + csr_is_conn_state_infra(pMac, sessionId)) { + pSession = CSR_GET_SESSION(pMac, sessionId); + } + + if (pSession == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Unable to find " "the session Id: %d", __func__, + sessionId); + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to " + "allocate memory for 8023 Multicast List request", + __func__); + return CDF_STATUS_E_NOMEM; + } + + if (!csr_is_conn_state_connected_infra(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Ignoring the " + "indication as we are not connected", __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(request_buf, pMulticastAddrs, + sizeof(tSirRcvFltMcAddrList)); + + cdf_mem_copy(request_buf->selfMacAddr, pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(request_buf->bssId, pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + msg.type = WMA_8023_MULTICAST_LIST_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to " + "post WMA_8023_MULTICAST_LIST message to WMA", + __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_receive_filter_set_filter(tHalHandle hHal, + tpSirRcvPktFilterCfgType pRcvPktFilterCfg, + uint8_t sessionId) +{ + tpSirRcvPktFilterCfgType request_buf; + int32_t allocSize; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + uint8_t idx = 0; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: filterType=%d, " + "filterId = %d", __func__, + pRcvPktFilterCfg->filterType, pRcvPktFilterCfg->filterId); + + allocSize = sizeof(tSirRcvPktFilterCfgType); + + request_buf = cdf_mem_malloc(allocSize); + + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to " + "allocate memory for Receive Filter Set Filter request", + __func__); + return CDF_STATUS_E_NOMEM; + } + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Session Not found ", __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(pRcvPktFilterCfg->selfMacAddr, pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(pRcvPktFilterCfg->bssId, + pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(request_buf, pRcvPktFilterCfg, allocSize); + + msg.type = WMA_RECEIVE_FILTER_SET_FILTER_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "Pkt Flt Req : " + "FT %d FID %d ", + request_buf->filterType, request_buf->filterId); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "Pkt Flt Req : " + "params %d CT %d", + request_buf->numFieldParams, request_buf->coalesceTime); + + for (idx = 0; idx < request_buf->numFieldParams; idx++) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "Proto %d Comp Flag %d ", + request_buf->paramsData[idx].protocolLayer, + request_buf->paramsData[idx].cmpFlag); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "Data Offset %d Data Len %d", + request_buf->paramsData[idx].dataOffset, + request_buf->paramsData[idx].dataLength); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "CData: %d:%d:%d:%d:%d:%d", + request_buf->paramsData[idx].compareData[0], + request_buf->paramsData[idx].compareData[1], + request_buf->paramsData[idx].compareData[2], + request_buf->paramsData[idx].compareData[3], + request_buf->paramsData[idx].compareData[4], + request_buf->paramsData[idx].compareData[5]); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "MData: %d:%d:%d:%d:%d:%d", + request_buf->paramsData[idx].dataMask[0], + request_buf->paramsData[idx].dataMask[1], + request_buf->paramsData[idx].dataMask[2], + request_buf->paramsData[idx].dataMask[3], + request_buf->paramsData[idx].dataMask[4], + request_buf->paramsData[idx].dataMask[5]); + + } + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post " + "WMA_RECEIVE_FILTER_SET_FILTER message to WMA", + __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_receive_filter_clear_filter(tHalHandle hHal, + tpSirRcvFltPktClearParam + pRcvFltPktClearParam, uint8_t sessionId) +{ + tpSirRcvFltPktClearParam request_buf; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: filterId = %d", + __func__, pRcvFltPktClearParam->filterId); + + request_buf = cdf_mem_malloc(sizeof(tSirRcvFltPktClearParam)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for Receive Filter " + "Clear Filter request", __func__); + return CDF_STATUS_E_NOMEM; + } + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Session Not find ", __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(pRcvFltPktClearParam->selfMacAddr, + pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(pRcvFltPktClearParam->bssId, + pSession->connectedProfile.bssid.bytes, sizeof(tSirMacAddr)); + + cdf_mem_copy(request_buf, pRcvFltPktClearParam, + sizeof(tSirRcvFltPktClearParam)); + + msg.type = WMA_RECEIVE_FILTER_CLEAR_FILTER_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post " + "WMA_RECEIVE_FILTER_CLEAR_FILTER message to WMA", + __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_PACKET_FILTERING */ + +/* --------------------------------------------------------------------------- + + \fn sme_is_channel_valid + + \brief To check if the channel is valid for currently established domain + This is a synchronous API. + + \param hHal - The handle returned by mac_open. + \param channel - channel to verify + + \return true/false, true if channel is valid + + -------------------------------------------------------------------------------*/ +bool sme_is_channel_valid(tHalHandle hHal, uint8_t channel) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + bool valid = false; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + valid = csr_roam_is_channel_valid(pMac, channel); + + sme_release_global_lock(&pMac->sme); + } + + return valid; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_freq_band + \brief Used to set frequency band. + \param hHal + \param sessionId - Session Identifier + \eBand band value to be configured + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_freq_band(tHalHandle hHal, uint8_t sessionId, eCsrBand eBand) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_set_band(hHal, sessionId, eBand); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_freq_band + \brief Used to get the current band settings. + \param hHal + \pBand pointer to hold band value + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_get_freq_band(tHalHandle hHal, eCsrBand *pBand) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + *pBand = csr_get_current_band(hHal); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_max_tx_power_per_band + + \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 CDF_STATUS + + ----------------------------------------------------------------------------*/ +CDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t dB) +{ + cds_msg_t msg; + tpMaxTxPowerPerBandParams pMaxTxPowerPerBandParams = NULL; + + pMaxTxPowerPerBandParams = + cdf_mem_malloc(sizeof(tMaxTxPowerPerBandParams)); + if (NULL == pMaxTxPowerPerBandParams) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s:Not able to allocate memory for pMaxTxPowerPerBandParams", + __func__); + return CDF_STATUS_E_NOMEM; + } + + pMaxTxPowerPerBandParams->power = dB; + pMaxTxPowerPerBandParams->bandInfo = band; + + msg.type = WMA_SET_MAX_TX_POWER_PER_BAND_REQ; + msg.reserved = 0; + msg.bodyptr = pMaxTxPowerPerBandParams; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s:Not able to post WMA_SET_MAX_TX_POWER_PER_BAND_REQ", + __func__); + cdf_mem_free(pMaxTxPowerPerBandParams); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_max_tx_power + + \brief 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 CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, tSirMacAddr pBssid, + tSirMacAddr pSelfMacAddress, int8_t dB) +{ + cds_msg_t msg; + tpMaxTxPowerParams pMaxTxParams = NULL; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW, NO_SESSION, 0)); + pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams)); + if (NULL == pMaxTxParams) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for pMaxTxParams", + __func__); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(pMaxTxParams->bssId, pBssid, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSelfMacAddress, + CDF_MAC_ADDR_SIZE); + pMaxTxParams->power = dB; + + msg.type = WMA_SET_MAX_TX_POWER_REQ; + msg.reserved = 0; + msg.bodyptr = pMaxTxParams; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_SET_MAX_TX_POWER_REQ message to WMA", + __func__); + cdf_mem_free(pMaxTxParams); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_custom_mac_addr + + \brief Set the customer Mac Address. + + \param customMacAddr customer MAC Address + \- return CDF_STATUS + + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr) +{ + cds_msg_t msg; + tSirMacAddr *pBaseMacAddr; + + pBaseMacAddr = cdf_mem_malloc(sizeof(tSirMacAddr)); + if (NULL == pBaseMacAddr) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for pBaseMacAddr")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(*pBaseMacAddr, customMacAddr, sizeof(tSirMacAddr)); + + msg.type = SIR_HAL_SET_BASE_MACADDR_IND; + msg.reserved = 0; + msg.bodyptr = pBaseMacAddr; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Not able to post SIR_HAL_SET_BASE_MACADDR_IND message to WMA")); + cdf_mem_free(pBaseMacAddr); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/* ---------------------------------------------------------------------------- + \fn sme_set_tx_power + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, + tSirMacAddr pBSSId, tCDF_CON_MODE dev_mode, int dBm) +{ + cds_msg_t msg; + tpMaxTxPowerParams pTxParams = NULL; + int8_t power = (int8_t) dBm; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_TXPOW, sessionId, 0)); + + /* make sure there is no overflow */ + if ((int)power != dBm) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: error, invalid power = %d", __func__, dBm); + return CDF_STATUS_E_FAILURE; + } + + pTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams)); + if (NULL == pTxParams) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for pTxParams", + __func__); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(pTxParams->bssId, pBSSId, CDF_MAC_ADDR_SIZE); + pTxParams->power = power; /* unit is dBm */ + pTxParams->dev_mode = dev_mode; + msg.type = WMA_SET_TX_POWER_REQ; + msg.reserved = 0; + msg.bodyptr = pTxParams; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: failed to post WMA_SET_TX_POWER_REQ to WMA", + __func__); + cdf_mem_free(pTxParams); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_hide_ssid + + \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 CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_hide_ssid(tHalHandle hHal, uint8_t sessionId, uint8_t ssidHidden) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint16_t len; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + tpSirUpdateParams pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), + sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!pSession->sessionActive) + CDF_ASSERT(0); + + /* Create the message and send to lim */ + len = sizeof(tSirUpdateParams); + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else { + cdf_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 = cds_send_mb_message_to_mac(pMsg); + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_tm_level + \brief Set Thermal Mitigation Level to RIVA + \param hHal - The handle returned by mac_open. + \param newTMLevel - new Thermal Mitigation Level + \param tmMode - Thermal Mitigation handle mode, default 0 + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_tm_level(tHalHandle hHal, uint16_t newTMLevel, uint16_t tmMode) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tAniSetTmLevelReq *setTmLevelReq = NULL; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_TMLEVEL, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + setTmLevelReq = + (tAniSetTmLevelReq *) + cdf_mem_malloc(sizeof(tAniSetTmLevelReq)); + if (NULL == setTmLevelReq) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for sme_set_tm_level", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + setTmLevelReq->tmMode = tmMode; + setTmLevelReq->newTmLevel = newTMLevel; + + /* serialize the req through MC thread */ + cds_message.bodyptr = setTmLevelReq; + cds_message.type = WMA_SET_TM_LEVEL_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post Set TM Level MSG fail", __func__); + cdf_mem_free(setTmLevelReq); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/*--------------------------------------------------------------------------- + + \brief sme_feature_caps_exchange() - SME interface to exchange capabilities between + Host and FW. + + \param hHal - HAL handle for device + + \return NONE + + ---------------------------------------------------------------------------*/ +void sme_feature_caps_exchange(tHalHandle hHal) +{ + MTRACE(cdf_trace + (CDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_CAPS_EXCH, NO_SESSION, + 0)); +} + +/*--------------------------------------------------------------------------- + + \brief sme_disable_feature_capablity() - SME interface to disable Active mode offload capablity + in Host. + + \param hHal - HAL handle for device + + \return NONE + + ---------------------------------------------------------------------------*/ +void sme_disable_feature_capablity(uint8_t feature_index) +{ +} + +/* --------------------------------------------------------------------------- + \fn sme_reset_power_values_for5_g + \brief Reset the power values for 5G band with default power values. + \param hHal - HAL handle for device + \- return NONE + -------------------------------------------------------------------------*/ +void sme_reset_power_values_for5_g(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_RESET_PW5G, NO_SESSION, 0)); + csr_save_channel_power_for_band(pMac, true); + csr_apply_power2_current(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_update_roam_prefer5_g_hz + \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 + -------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_roam_prefer5_g_hz(tHalHandle hHal, bool nRoamPrefer5GHz) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_RP5G, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: gRoamPrefer5GHz is changed from %d to %d", + __func__, pMac->roam.configParam.nRoamPrefer5GHz, + nRoamPrefer5GHz); + pMac->roam.configParam.nRoamPrefer5GHz = nRoamPrefer5GHz; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_intra_band + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_intra_band(tHalHandle hHal, const bool nRoamIntraBand) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: gRoamIntraBand is changed from %d to %d", + __func__, pMac->roam.configParam.nRoamIntraBand, + nRoamIntraBand); + pMac->roam.configParam.nRoamIntraBand = nRoamIntraBand; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_roam_scan_n_probes + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_update_roam_scan_n_probes(tHalHandle hHal, uint8_t sessionId, + const uint8_t nProbes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: gRoamScanNProbes is changed from %d to %d", + __func__, pMac->roam.configParam.nProbes, nProbes); + pMac->roam.configParam.nProbes = nProbes; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NPROBES_CHANGED); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_roam_scan_home_away_time + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_update_roam_scan_home_away_time(tHalHandle hHal, + uint8_t sessionId, + const uint16_t nRoamScanHomeAwayTime, + const bool bSendOffloadCmd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME, + NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: gRoamScanHomeAwayTime is changed from %d to %d", + __func__, + pMac->roam.configParam.nRoamScanHomeAwayTime, + nRoamScanHomeAwayTime); + pMac->roam.configParam.nRoamScanHomeAwayTime = + nRoamScanHomeAwayTime; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled && bSendOffloadCmd) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_HOME_AWAY_TIME_CHANGED); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_roam_intra_band + \brief get Intra band roaming + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +bool sme_get_roam_intra_band(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND, NO_SESSION, 0)); + return pMac->roam.configParam.nRoamIntraBand; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_roam_scan_n_probes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +uint8_t sme_get_roam_scan_n_probes(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.nProbes; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_roam_scan_home_away_time + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +uint16_t sme_get_roam_scan_home_away_time(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.nRoamScanHomeAwayTime; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_roam_rssi_diff + \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 + -------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_roam_rssi_diff(tHalHandle hHal, uint8_t sessionId, + uint8_t RoamRssiDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_RSSI_DIFF_CHANGED); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_update_fast_transition_enabled() - 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 mac_open. + \return CDF_STATUS_SUCCESS - SME update isFastTransitionEnabled config + successfully. + Other status means SME is failed to update isFastTransitionEnabled. + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_update_fast_transition_enabled(tHalHandle hHal, + bool isFastTransitionEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED, NO_SESSION, + 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: FastTransitionEnabled is changed from %d to %d", + __func__, + pMac->roam.configParam.isFastTransitionEnabled, + isFastTransitionEnabled); + pMac->roam.configParam.isFastTransitionEnabled = + isFastTransitionEnabled; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_wes_mode + \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 CDF_STATUS_SUCCESS - SME update isWESModeEnabled config successfully. + Other status means SME is failed to update isWESModeEnabled. + -------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_wes_mode(tHalHandle hHal, bool isWESModeEnabled, + uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %s", + isWESModeEnabled, + pMac->roam.configParam.isWESModeEnabled, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_scan_control + \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 CDF_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_scan_control(tHalHandle hHal, uint8_t sessionId, + bool roamScanControl) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_SET_SCANCTRL, NO_SESSION, 0)); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pMac->roam.configParam.nRoamScanControl = roamScanControl; + if (0 == roamScanControl) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR runtime successfully cleared roam scan cache"); + csr_flush_cfg_bg_scan_roam_channel_list(pMac, sessionId); + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_FLUSH_CHANNEL_LIST); + } + } + sme_release_global_lock(&pMac->sme); + } + return status; +} +#endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_ESE) || (FEATURE_WLAN_LFR) */ + +#ifdef FEATURE_WLAN_LFR +/*-------------------------------------------------------------------------- + \brief sme_update_is_fast_roam_ini_feature_enabled() - 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 mac_open. + \param sessionId - Session Identifier + \return CDF_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config + successfully. + Other status means SME is failed to update isFastRoamIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_update_is_fast_roam_ini_feature_enabled + (tHalHandle hHal, + uint8_t sessionId, const bool isFastRoamIniFeatureEnabled) { + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->roam.configParam.isFastRoamIniFeatureEnabled == + isFastRoamIniFeatureEnabled) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 CDF_STATUS_SUCCESS; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "%s: FastRoamEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isFastRoamIniFeatureEnabled, + isFastRoamIniFeatureEnabled); + pMac->roam.configParam.isFastRoamIniFeatureEnabled = + isFastRoamIniFeatureEnabled; + csr_neighbor_roam_update_fast_roaming_enabled(pMac, sessionId, + isFastRoamIniFeatureEnabled); + + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_update_is_mawc_ini_feature_enabled() - + 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 mac_open. + \return CDF_STATUS_SUCCESS - SME update MAWCEnabled config successfully. + Other status means SME is failed to update MAWCEnabled. + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_update_is_mawc_ini_feature_enabled(tHalHandle hHal, + const bool MAWCEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: MAWCEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.MAWCEnabled, MAWCEnabled); + pMac->roam.configParam.MAWCEnabled = MAWCEnabled; + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/*-------------------------------------------------------------------------- + \brief sme_stop_roaming() - Stop roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by mac_open + \param sessionId - Session Identifier + \return CDF_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_stop_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, + reason); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_start_roaming() - Start roaming for a given sessionId + This is a synchronous call + \param hHal - The handle returned by mac_open + \param sessionId - Session Identifier + \return CDF_STATUS_SUCCESS on success + Other status on failure + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_start_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + reason); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_update_enable_fast_roam_in_concurrency() - enable/disable LFR if + Concurrent session exists + This is a synchronuous call + \param hHal - The handle returned by mac_open. + \return CDF_STATUS_SUCCESS + Other status means SME is failed + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_enable_fast_roam_in_concurrency(tHalHandle hHal, + bool + bFastRoamInConIniFeatureEnabled) +{ + + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = + bFastRoamInConIniFeatureEnabled; + if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) { + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = + 0; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} +#endif /* FEATURE_WLAN_LFR */ + +#ifdef FEATURE_WLAN_ESE +/*-------------------------------------------------------------------------- + \brief sme_update_is_ese_feature_enabled() - 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 mac_open. + \param sessionId - Session Identifier + \param isEseIniFeatureEnabled - flag to enable/disable + \return CDF_STATUS_SUCCESS - SME update isEseIniFeatureEnabled config + successfully. + Other status means SME is failed to update isEseIniFeatureEnabled. + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_update_is_ese_feature_enabled + (tHalHandle hHal, uint8_t sessionId, const bool isEseIniFeatureEnabled) { + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->roam.configParam.isEseIniFeatureEnabled == + isEseIniFeatureEnabled) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 CDF_STATUS_SUCCESS; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: EseEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isEseIniFeatureEnabled, + isEseIniFeatureEnabled); + pMac->roam.configParam.isEseIniFeatureEnabled = isEseIniFeatureEnabled; + csr_neighbor_roam_update_ese_mode_enabled(pMac, sessionId, + isEseIniFeatureEnabled); + + if (true == isEseIniFeatureEnabled) { + sme_update_fast_transition_enabled(hHal, true); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ESE_INI_CFG_CHANGED); + } + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_ESE */ + +/*-------------------------------------------------------------------------- + \brief sme_update_config_fw_rssi_monitoring() - 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 mac_open. + \return CDF_STATUS_SUCCESS - SME update fEnableFwRssiMonitoring. + config successfully. + Other status means SME is failed to update fEnableFwRssiMonitoring. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_config_fw_rssi_monitoring(tHalHandle hHal, + bool fEnableFwRssiMonitoring) +{ + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + + if (sme_cfg_set_int (hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR, + fEnableFwRssiMonitoring) == CDF_STATUS_E_FAILURE) { + cdf_ret_status = CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Could not pass on WNI_CFG_PS_RSSI_MONITOR to CFG"); + } + + return cdf_ret_status; +} + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +/* --------------------------------------------------------------------------- + \fn sme_set_roam_opportunistic_scan_threshold_diff + \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 CDF_STATUS_SUCCESS - SME update nOpportunisticThresholdDiff config + successfully. + else SME is failed to update nOpportunisticThresholdDiff. + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_opportunistic_scan_threshold_diff(tHalHandle hHal, + uint8_t sessionId, + const uint8_t + nOpportunisticThresholdDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_opportunistic_scan_threshold_diff(pMac, + sessionId, + nOpportunisticThresholdDiff); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_get_roam_opportunistic_scan_threshold_diff() + \brief gets Opportunistic Scan threshold diff + This is a synchronous call + \param hHal - The handle returned by mac_open + \return uint8_t - nOpportunisticThresholdDiff + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_roam_opportunistic_scan_threshold_diff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig. + nOpportunisticThresholdDiff; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_rescan_rssi_diff + \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 CDF_STATUS_SUCCESS - SME update nRoamRescanRssiDiff config + successfully. + else SME is failed to update nRoamRescanRssiDiff. + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_rescan_rssi_diff(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nRoamRescanRssiDiff) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_roam_rescan_rssi_diff(pMac, sessionId, + nRoamRescanRssiDiff); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_get_roam_rescan_rssi_diff + \brief gets roam rescan rssi diff + This is a synchronous call + \param hHal - The handle returned by mac_open + \return int8_t - nRoamRescanRssiDiff + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_roam_rescan_rssi_diff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_bmiss_first_bcnt + \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 CDF_STATUS_SUCCESS - SME update nRoamBmissFirstBcnt + successfully. + else SME is failed to update nRoamBmissFirstBcnt + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_bmiss_first_bcnt(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nRoamBmissFirstBcnt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_roam_bmiss_first_bcnt(pMac, sessionId, + nRoamBmissFirstBcnt); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_roam_bmiss_first_bcnt + \brief get neighbor roam beacon miss first count + \param hHal - The handle returned by mac_open. + \return uint8_t - neighbor roam beacon miss first count + -------------------------------------------------------------------------*/ +uint8_t sme_get_roam_bmiss_first_bcnt(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_bmiss_final_bcnt + \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 CDF_STATUS_SUCCESS - SME update nRoamBmissFinalBcnt + successfully. + else SME is failed to update nRoamBmissFinalBcnt + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_bmiss_final_bcnt(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nRoamBmissFinalBcnt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_roam_bmiss_final_bcnt(pMac, sessionId, + nRoamBmissFinalBcnt); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_get_roam_bmiss_final_bcnt + \brief gets Roam count for final beacon miss + This is a synchronous call + \param hHal - The handle returned by mac_open + \return uint8_t - nRoamBmissFinalBcnt + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_roam_beacon_rssi_weight + \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 CDF_STATUS_SUCCESS - SME update nRoamBeaconRssiWeight config + successfully. + else SME is failed to update nRoamBeaconRssiWeight + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal, + uint8_t sessionId, + const uint8_t nRoamBeaconRssiWeight) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_roam_beacon_rssi_weight(pMac, sessionId, + nRoamBeaconRssiWeight); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \fn sme_get_roam_beacon_rssi_weight + \brief gets Roam beacon rssi weight + This is a synchronous call + \param hHal - The handle returned by mac_open + \return uint8_t - nRoamBeaconRssiWeight + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight; +} + +/*-------------------------------------------------------------------------- + \brief sme_set_neighbor_lookup_rssi_threshold() - update neighbor lookup + rssi threshold + This is a synchronous call + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return CDF_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_set_neighbor_lookup_rssi_threshold + (tHalHandle hHal, uint8_t sessionId, uint8_t neighborLookupRssiThreshold) { + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_neighbor_roam_set_lookup_rssi_threshold(pMac, sessionId, + neighborLookupRssiThreshold); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pMac->roam.configParam.neighborRoamConfig. + nNeighborLookupRssiThreshold = + neighborLookupRssiThreshold; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_set_delay_before_vdev_stop() - update delay before VDEV_STOP + This is a synchronous call + \param hal - The handle returned by macOpen. + \param session_id - Session Identifier + \param delay_before_vdev_stop - value to be set + \return CDF_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_set_delay_before_vdev_stop(tHalHandle hal, + uint8_t session_id, + uint8_t delay_before_vdev_stop) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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[session_id].cfgParams. + delay_before_vdev_stop = delay_before_vdev_stop; + pMac->roam.configParam.neighborRoamConfig. + delay_before_vdev_stop = delay_before_vdev_stop; + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_neighbor_lookup_rssi_threshold() - get neighbor lookup + rssi threshold + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return CDF_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_neighbor_lookup_rssi_threshold(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig. + nNeighborLookupRssiThreshold; +} + +/*-------------------------------------------------------------------------- + \brief sme_set_neighbor_scan_refresh_period() - set neighbor scan results + refresh period + This is a synchronous call + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return CDF_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +CDF_STATUS sme_set_neighbor_scan_refresh_period + (tHalHandle hHal, + uint8_t sessionId, uint16_t neighborScanResultsRefreshPeriod) { + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pNeighborRoamConfig = + &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pNeighborRoamConfig->nNeighborResultsRefreshPeriod = + neighborScanResultsRefreshPeriod; + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = + neighborScanResultsRefreshPeriod; + + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_update_roam_scan_offload_enabled() - enable/disable roam scan + offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return CDF_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_roam_scan_offload_enabled(tHalHandle hHal, + bool nRoamScanOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL + ("gRoamScanOffloadEnabled is changed from %d to %d"), + pMac->roam.configParam.isRoamOffloadScanEnabled, + nRoamScanOffloadEnabled); + pMac->roam.configParam.isRoamOffloadScanEnabled = + nRoamScanOffloadEnabled; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_neighbor_scan_refresh_period() - get neighbor scan results + refresh period + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return uint16_t - Neighbor scan results refresh period value + \sa + --------------------------------------------------------------------------*/ +uint16_t sme_get_neighbor_scan_refresh_period(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig. + nNeighborResultsRefreshPeriod; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_empty_scan_refresh_period() - get empty scan refresh period + This is a synchronuous call + \param hHal - The handle returned by mac_open. + \return CDF_STATUS_SUCCESS - SME update config successful. + Other status means SME is failed to update + \sa + --------------------------------------------------------------------------*/ +uint16_t sme_get_empty_scan_refresh_period(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.neighborRoamConfig. + nEmptyScanRefreshPeriod; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_empty_scan_refresh_period + \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 + -------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_empty_scan_refresh_period(tHalHandle hHal, uint8_t sessionId, + uint16_t nEmptyScanRefreshPeriod) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pNeighborRoamConfig = + &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pNeighborRoamConfig->nEmptyScanRefreshPeriod = + nEmptyScanRefreshPeriod; + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod = + nEmptyScanRefreshPeriod; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_EMPTY_SCAN_REF_PERIOD_CHANGED); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_neighbor_scan_min_chan_time + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_neighbor_scan_min_chan_time(tHalHandle hHal, + const uint16_t + nNeighborScanMinChanTime, + uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + + pMac->roam.configParam.neighborRoamConfig. + nNeighborScanMinChanTime = nNeighborScanMinChanTime; + pMac->roam.neighborRoamInfo[sessionId].cfgParams. + minChannelScanTime = nNeighborScanMinChanTime; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_neighbor_scan_max_chan_time + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_neighbor_scan_max_chan_time(tHalHandle hHal, uint8_t sessionId, + const uint16_t + nNeighborScanMaxChanTime) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pNeighborRoamConfig = + &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pNeighborRoamConfig->nNeighborScanMaxChanTime = + nNeighborScanMaxChanTime; + pNeighborRoamInfo->cfgParams.maxChannelScanTime = + nNeighborScanMaxChanTime; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_SCAN_CH_TIME_CHANGED); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_neighbor_scan_min_chan_time + \brief get neighbor scan min channel time + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint16_t - channel min time value + -------------------------------------------------------------------------*/ +uint16_t sme_get_neighbor_scan_min_chan_time(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.neighborRoamInfo[sessionId].cfgParams. + minChannelScanTime; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_neighbor_roam_state + \brief get neighbor roam state + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint32_t - neighbor roam state + -------------------------------------------------------------------------*/ +uint32_t sme_get_neighbor_roam_state(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.neighborRoamInfo[sessionId].neighborRoamState; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_current_roam_state + \brief get current roam state + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint32_t - current roam state + -------------------------------------------------------------------------*/ +uint32_t sme_get_current_roam_state(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.curState[sessionId]; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_current_roam_sub_state + \brief get neighbor roam sub state + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint32_t - current roam sub state + -------------------------------------------------------------------------*/ +uint32_t sme_get_current_roam_sub_state(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.curSubState[sessionId]; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_lim_sme_state + \brief get Lim Sme state + \param hHal - The handle returned by mac_open. + \return uint32_t - Lim Sme state + -------------------------------------------------------------------------*/ +uint32_t sme_get_lim_sme_state(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gLimSmeState; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_lim_mlm_state + \brief get Lim Mlm state + \param hHal - The handle returned by mac_open. + \return uint32_t - Lim Mlm state + -------------------------------------------------------------------------*/ +uint32_t sme_get_lim_mlm_state(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gLimMlmState; +} + +/* --------------------------------------------------------------------------- + \fn sme_is_lim_session_valid + \brief is Lim session valid + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return bool - true or false + -------------------------------------------------------------------------*/ +bool sme_is_lim_session_valid(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gpSession[sessionId].valid; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_lim_sme_session_state + \brief get Lim Sme session state + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint32_t - Lim Sme session state + -------------------------------------------------------------------------*/ +uint32_t sme_get_lim_sme_session_state(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gpSession[sessionId].limSmeState; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_lim_mlm_session_state + \brief get Lim Mlm session state + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint32_t - Lim Mlm session state + -------------------------------------------------------------------------*/ +uint32_t sme_get_lim_mlm_session_state(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->lim.gpSession[sessionId].limMlmState; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_neighbor_scan_max_chan_time + \brief get neighbor scan max channel time + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint16_t - channel max time value + -------------------------------------------------------------------------*/ +uint16_t sme_get_neighbor_scan_max_chan_time(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.neighborRoamInfo[sessionId].cfgParams. + maxChannelScanTime; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_neighbor_scan_period + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId, + const uint16_t nNeighborScanPeriod) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamConfig *pNeighborRoamConfig = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pNeighborRoamConfig = + &pMac->roam.configParam.neighborRoamConfig; + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pNeighborRoamConfig->nNeighborScanTimerPeriod = + nNeighborScanPeriod; + pNeighborRoamInfo->cfgParams.neighborScanPeriod = + nNeighborScanPeriod; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_SCAN_HOME_TIME_CHANGED); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_neighbor_scan_period + \brief get neighbor scan period + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return uint16_t - neighbor scan period + -------------------------------------------------------------------------*/ +uint16_t sme_get_neighbor_scan_period(tHalHandle hHal, uint8_t 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_get_roam_rssi_diff() - get Roam rssi diff + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return uint16_t - Rssi diff value + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_roam_rssi_diff(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.RoamRssiDiff; +} + +/** + * sme_change_roam_scan_channel_list() - to change scan channel list + * @hHal: pointer HAL handle returned by mac_open + * @sessionId: sme session id + * @pChannelList: Output channel list + * @numChannels: Output number of channels + * + * This routine is called to Change roam scan channel list. + * This is a synchronous call + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_change_roam_scan_channel_list(tHalHandle hHal, uint8_t sessionId, + uint8_t *pChannelList, + uint8_t numChannels) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; + uint8_t newChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; + uint8_t i = 0, j = 0; + tCsrChannelInfo *chan_info; + + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + return status; + } + chan_info = &pNeighborRoamInfo->cfgParams.channelInfo; + + if (NULL != chan_info->ChannelList) { + for (i = 0; i < chan_info->numOfChannels; i++) { + if (j < sizeof(oldChannelList)) + j += snprintf(oldChannelList + j, + sizeof(oldChannelList) - + j, "%d", + chan_info->ChannelList[i]); + else + break; + } + } + csr_flush_cfg_bg_scan_roam_channel_list(pMac, sessionId); + csr_create_bg_scan_roam_channel_list(pMac, sessionId, pChannelList, + numChannels); + sme_set_roam_scan_control(hHal, sessionId, 1); + if (NULL != chan_info->ChannelList) { + j = 0; + for (i = 0; i < chan_info->numOfChannels; i++) { + if (j < sizeof(newChannelList)) + j += snprintf(newChannelList + j, + sizeof(newChannelList) - + j, " %d", + chan_info->ChannelList[i]); + else + break; + } + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("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_release_global_lock(&pMac->sme); + + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + return status; +} + +#ifdef FEATURE_WLAN_ESE_UPLOAD +/** + * sme_set_ese_roam_scan_channel_list() - To set ese roam scan channel list + * @hHal: pointer HAL handle returned by mac_open + * @sessionId: sme session id + * @pChannelList: Output channel list + * @numChannels: Output number of channels + * + * This routine is called to set ese roam scan channel list. + * This is a synchronous call + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_set_ese_roam_scan_channel_list(tHalHandle hHal, + uint8_t sessionId, + uint8_t *pChannelList, + uint8_t numChannels) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + tpCsrChannelInfo curchnl_list_info + = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 }; + uint8_t newChannelList[128] = { 0 }; + uint8_t i = 0, j = 0; + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + return status; + } + if (NULL != curchnl_list_info->ChannelList) { + for (i = 0; i < curchnl_list_info->numOfChannels; i++) { + j += snprintf(oldChannelList + j, + sizeof(oldChannelList) - j, "%d", + curchnl_list_info->ChannelList[i]); + } + } + status = csr_create_roam_scan_channel_list(pMac, sessionId, + pChannelList, numChannels, + csr_get_current_band(hHal)); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (NULL != curchnl_list_info->ChannelList) { + j = 0; + for (i = 0; i < curchnl_list_info->numOfChannels; i++) { + j += snprintf(newChannelList + j, + sizeof(newChannelList) - j, "%d", + curchnl_list_info->ChannelList[i]); + } + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "ESE roam scan chnl list successfully set to %s-old value is %s-roam state is %d", + newChannelList, oldChannelList, + pNeighborRoamInfo->neighborRoamState); + } + sme_release_global_lock(&pMac->sme); + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + return status; +} +#endif + +/** + * sme_get_roam_scan_channel_list() - To get roam scan channel list + * @hHal: HAL pointer + * @pChannelList: Output channel list + * @pNumChannels: Output number of channels + * @sessionId: Session Identifier + * + * To get roam scan channel list This is a synchronous call + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_get_roam_scan_channel_list(tHalHandle hHal, + uint8_t *pChannelList, uint8_t *pNumChannels, + uint8_t sessionId) +{ + int i = 0; + uint8_t *pOutPtr = pChannelList; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + FL("Roam Scan channel list is NOT yet initialized")); + *pNumChannels = 0; + sme_release_global_lock(&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_release_global_lock(&pMac->sme); + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_is_ese_feature_enabled() - get ESE feature enabled or not + This is a synchronuous call + \param hHal - The handle returned by mac_open. + \return true (1) - if the ESE feature is enabled + false (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +bool sme_get_is_ese_feature_enabled(tHalHandle hHal) +{ +#ifdef FEATURE_WLAN_ESE + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return csr_roam_is_ese_ini_feature_enabled(pMac); +#else + return false; +#endif +} + +/*-------------------------------------------------------------------------- + \brief sme_get_wes_mode() - get WES Mode + This is a synchronous call + \param hHal - The handle returned by mac_open + \return uint8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +bool sme_get_wes_mode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.isWESModeEnabled; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_roam_scan_control() - get scan control + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return bool - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +bool sme_get_roam_scan_control(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.nRoamScanControl; +} +#endif + +/*-------------------------------------------------------------------------- + \brief sme_get_is_lfr_feature_enabled() - get LFR feature enabled or not + This is a synchronuous call + \param hHal - The handle returned by mac_open. + \return true (1) - if the feature is enabled + false (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +bool sme_get_is_lfr_feature_enabled(tHalHandle hHal) +{ +#ifdef FEATURE_WLAN_LFR + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.isFastRoamIniFeatureEnabled; +#else + return false; +#endif +} + +/*-------------------------------------------------------------------------- + \brief sme_get_is_ft_feature_enabled() - get FT feature enabled or not + This is a synchronuous call + \param hHal - The handle returned by mac_open. + \return true (1) - if the feature is enabled + false (0) - if feature is disabled (compile or runtime) + \sa + --------------------------------------------------------------------------*/ +bool sme_get_is_ft_feature_enabled(tHalHandle hHal) +{ +#ifdef WLAN_FEATURE_VOWIFI_11R + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.isFastTransitionEnabled; +#else + return false; +#endif +} + +/* --------------------------------------------------------------------------- + \fn sme_is_feature_supported_by_fw + \brief Check if an feature is enabled by FW + + \param feattEnumValue - Enumeration value from placeHolderInCapBitmap + \- return 1/0 (true/false) + -------------------------------------------------------------------------*/ +uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue) +{ + return IS_FEATURE_SUPPORTED_BY_FW(featEnumValue); +} + +#ifdef FEATURE_WLAN_TDLS + +/* --------------------------------------------------------------------------- + \fn sme_send_tdls_link_establish_params + \brief API to send TDLS Peer Link Establishment Parameters. + + \param peerMac - peer's Mac Adress. + \param tdlsLinkEstablishParams - TDLS Peer Link Establishment Parameters + \- return CDF_STATUS_SUCCES + -------------------------------------------------------------------------*/ +CDF_STATUS sme_send_tdls_link_establish_params(tHalHandle hHal, + uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams * + tdlsLinkEstablishParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_tdls_send_link_establish_params(hHal, sessionId, + peerMac, tdlsLinkEstablishParams); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_send_tdls_mgmt_frame + \brief API to send TDLS management frames. + + \param peerMac - peer's Mac Adress. + \param frame_type - Type of TDLS mgmt frame to be sent. + \param dialog - dialog token used in the frame. + \param status - status to be incuded in the frame. + \param peerCapability - peer cpabilities + \param buf - additional IEs to be included + \param len - lenght of additional Ies + \param responder - Tdls request type + \- return CDF_STATUS_SUCCES + -------------------------------------------------------------------------*/ +CDF_STATUS sme_send_tdls_mgmt_frame(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, + uint8_t frame_type, + uint8_t dialog, uint16_t statusCode, + uint32_t peerCapability, uint8_t *buf, + uint8_t len, uint8_t responder) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrTdlsSendMgmt sendTdlsReq = { {0} }; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_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 = csr_tdls_send_mgmt_req(hHal, sessionId, &sendTdlsReq); + + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/* --------------------------------------------------------------------------- + \fn sme_change_tdls_peer_sta + \brief API to Update TDLS peer sta parameters. + + \param peerMac - peer's Mac Adress. + \param staParams - Peer Station Parameters + \- return CDF_STATUS_SUCCES + -------------------------------------------------------------------------*/ +CDF_STATUS sme_change_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pstaParams) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s :pstaParams is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_tdls_change_peer_sta(hHal, sessionId, peerMac, + pstaParams); + + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/* --------------------------------------------------------------------------- + \fn sme_add_tdls_peer_sta + \brief API to Add TDLS peer sta entry. + + \param peerMac - peer's Mac Adress. + \- return CDF_STATUS_SUCCES + -------------------------------------------------------------------------*/ +CDF_STATUS sme_add_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_tdls_add_peer_sta(hHal, sessionId, peerMac); + + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/* --------------------------------------------------------------------------- + \fn sme_delete_tdls_peer_sta + \brief API to Delete TDLS peer sta entry. + + \param peerMac - peer's Mac Adress. + \- return CDF_STATUS_SUCCES + -------------------------------------------------------------------------*/ +CDF_STATUS sme_delete_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_tdls_del_peer_sta(hHal, sessionId, peerMac); + + sme_release_global_lock(&pMac->sme); + } + + return status; + +} + +/* --------------------------------------------------------------------------- + \fn sme_set_tdls_power_save_prohibited + \API to set/reset the is_tdls_power_save_prohibited. + + \- return void + -------------------------------------------------------------------------*/ +void sme_set_tdls_power_save_prohibited(tHalHandle hHal, uint32_t sessionId, + bool val) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + struct ps_global_info *ps_global_info = &pMac->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[sessionId]; + ps_param->is_tdls_power_save_prohibited = val; + return; +} + +/* --------------------------------------------------------------------------- + \fn sme_update_fw_tdls_state + + \brief + SME will send message to WMA to set TDLS state in f/w + + \param + + hHal - The handle returned by mac_open + + psmeTdlsParams - TDLS state info to update in f/w + + useSmeLock - Need to acquire SME Global Lock before state update or not + + \return CDF_STATUS + --------------------------------------------------------------------------- */ +CDF_STATUS sme_update_fw_tdls_state(tHalHandle hHal, void *psmeTdlsParams, + bool useSmeLock) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = NULL; + cds_msg_t cds_message; + + /* only acquire sme global lock before state update if asked to */ + if (useSmeLock) { + pMac = PMAC_STRUCT(hHal); + if (NULL == pMac) + return CDF_STATUS_E_FAILURE; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS != status) + return status; + } + + /* serialize the req through MC thread */ + cds_message.bodyptr = psmeTdlsParams; + cds_message.type = WMA_UPDATE_FW_TDLS_STATE; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + /* release the lock if it was acquired */ + if (useSmeLock) + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * sme_update_tdls_peer_state() - to update the state of TDLS peer + * @hHal: The handle returned by mac_open + * @peerStateParams: TDLS Peer state info to update in f/w + * + * SME will send message to WMA to set TDLS Peer state in f/w + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal, + tSmeTdlsPeerStateParams *peerStateParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tTdlsPeerStateParams *pTdlsPeerStateParams = NULL; + tTdlsPeerCapParams *peer_cap = NULL; + cds_msg_t cds_message; + uint8_t num; + uint8_t chanId; + uint8_t i; + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + pTdlsPeerStateParams = cdf_mem_malloc(sizeof(*pTdlsPeerStateParams)); + if (NULL == pTdlsPeerStateParams) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("failed to allocate mem for tdls peer state param")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(pTdlsPeerStateParams, sizeof(*pTdlsPeerStateParams)); + cdf_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 = + WMA_TDLS_PEER_STATE_PEERING; + break; + + case eSME_TDLS_PEER_STATE_CONNECTED: + pTdlsPeerStateParams->peerState = + WMA_TDLS_PEER_STATE_CONNECTED; + break; + + case eSME_TDLS_PEER_STATE_TEARDOWN: + pTdlsPeerStateParams->peerState = + WMA_TDLS_PEER_STATE_TEARDOWN; + break; + + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("invalid peer state param (%d)"), + peerStateParams->peerState); + cdf_mem_free(pTdlsPeerStateParams); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + peer_cap = &(pTdlsPeerStateParams->peerCap); + peer_cap->isPeerResponder = + peerStateParams->peerCap.isPeerResponder; + peer_cap->peerUapsdQueue = + peerStateParams->peerCap.peerUapsdQueue; + peer_cap->peerMaxSp = + peerStateParams->peerCap.peerMaxSp; + peer_cap->peerBuffStaSupport = + peerStateParams->peerCap.peerBuffStaSupport; + peer_cap->peerOffChanSupport = + peerStateParams->peerCap.peerOffChanSupport; + peer_cap->peerCurrOperClass = + peerStateParams->peerCap.peerCurrOperClass; + peer_cap->selfCurrOperClass = + peerStateParams->peerCap.selfCurrOperClass; + + num = 0; + for (i = 0; i < peerStateParams->peerCap.peerChanLen; i++) { + chanId = peerStateParams->peerCap.peerChan[i]; + if (!csr_roam_is_channel_valid(pMac, chanId)) + continue; + peer_cap->peerChan[num].chanId = chanId; + peer_cap->peerChan[num].pwr = + csr_get_cfg_max_tx_power(pMac, chanId); + + if (cds_get_channel_state(chanId) == CHANNEL_STATE_DFS) + peer_cap->peerChan[num].dfsSet = + true; + else + peer_cap->peerChan[num].dfsSet = + false; + num++; + } + peer_cap->peerChanLen = num; + peer_cap->peerOperClassLen = + peerStateParams->peerCap.peerOperClassLen; + for (i = 0; i < HAL_TDLS_MAX_SUPP_OPER_CLASSES; i++) { + peer_cap->peerOperClass[i] = + peerStateParams->peerCap.peerOperClass[i]; + } + + peer_cap->prefOffChanNum = + peerStateParams->peerCap.prefOffChanNum; + peer_cap->prefOffChanBandwidth = + peerStateParams->peerCap.prefOffChanBandwidth; + + if (peerStateParams->peerCap.opClassForPrefOffChanIsSet) { + peer_cap->opClassForPrefOffChan = + peerStateParams->peerCap.opClassForPrefOffChan; + } else { + /* + * 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 (peer_cap->prefOffChanBandwidth & + (1 << BW_40_OFFSET_BIT)) { + peer_cap->opClassForPrefOffChan = + cds_regdm_get_opclass_from_channel( + pMac->scan.countryCodeCurrent, + peer_cap->prefOffChanNum, + BW40_LOW_PRIMARY); + if (!peer_cap->opClassForPrefOffChan) { + peer_cap->opClassForPrefOffChan = + cds_regdm_get_opclass_from_channel( + pMac->scan.countryCodeCurrent, + peer_cap->prefOffChanNum, + BW40_HIGH_PRIMARY); + } + } else if (peer_cap->prefOffChanBandwidth & + (1 << BW_20_OFFSET_BIT)) { + peer_cap->opClassForPrefOffChan = + cds_regdm_get_opclass_from_channel( + pMac->scan.countryCodeCurrent, + peer_cap->prefOffChanNum, + BW20); + } else { + peer_cap->opClassForPrefOffChan = + cds_regdm_get_opclass_from_channel( + pMac->scan.countryCodeCurrent, + peer_cap->prefOffChanNum, + BWALL); + } + } + cds_message.type = WMA_UPDATE_TDLS_PEER_STATE; + cds_message.reserved = 0; + cds_message.bodyptr = pTdlsPeerStateParams; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + cdf_mem_free(pTdlsPeerStateParams); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + return status; +} + +/** + * sme_send_tdls_chan_switch_req() - send tdls channel switch request + * @hal: UMAC handler + * @ch_switch_params: Pointer to the chan switch parameter structure + * + * API to set tdls channel switch parameters. + * + * Return: CDF_STATUS_SUCCESS on success; another CDF_STATUS_* code otherwise + */ +CDF_STATUS sme_send_tdls_chan_switch_req(tHalHandle hal, + sme_tdls_chan_switch_params *ch_switch_params) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tdls_chan_switch_params *chan_switch_params = NULL; + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&mac->sme); + if (CDF_STATUS_SUCCESS != status) + return status; + chan_switch_params = cdf_mem_malloc(sizeof(*chan_switch_params)); + if (NULL == chan_switch_params) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("fail to alloc mem for tdls chan switch param")); + sme_release_global_lock(&mac->sme); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_zero(chan_switch_params, sizeof(*chan_switch_params)); + + switch (ch_switch_params->tdls_off_ch_mode) { + case ENABLE_CHANSWITCH: + chan_switch_params->tdls_sw_mode = WMA_TDLS_ENABLE_OFFCHANNEL; + break; + + case DISABLE_CHANSWITCH: + chan_switch_params->tdls_sw_mode = WMA_TDLS_DISABLE_OFFCHANNEL; + break; + + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("invalid off channel command (%d)"), + ch_switch_params->tdls_off_ch_mode); + cdf_mem_free(chan_switch_params); + sme_release_global_lock(&mac->sme); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(&chan_switch_params->peer_mac_addr, + &ch_switch_params->peer_mac_addr, sizeof(tSirMacAddr)); + chan_switch_params->vdev_id = ch_switch_params->vdev_id; + chan_switch_params->tdls_off_ch = ch_switch_params->tdls_off_channel; + chan_switch_params->tdls_off_ch_bw_offset = + ch_switch_params->tdls_off_ch_bw_offset; + chan_switch_params->is_responder = ch_switch_params->is_responder; + + switch (chan_switch_params->tdls_off_ch_bw_offset) { + case (1 << BW_20_OFFSET_BIT): + chan_switch_params->oper_class = + cds_regdm_get_opclass_from_channel( + mac->scan.countryCodeCurrent, + chan_switch_params->tdls_off_ch, + BW20); + break; + case (1 << BW_40_OFFSET_BIT): + chan_switch_params->oper_class = + cds_regdm_get_opclass_from_channel( + mac->scan.countryCodeCurrent, + chan_switch_params->tdls_off_ch, + BW40_LOW_PRIMARY); + if (!chan_switch_params->oper_class) { + chan_switch_params->oper_class = + cds_regdm_get_opclass_from_channel( + mac->scan.countryCodeCurrent, + chan_switch_params->tdls_off_ch, + BW40_HIGH_PRIMARY); + } + break; + default: + chan_switch_params->oper_class = + cds_regdm_get_opclass_from_channel( + mac->scan.countryCodeCurrent, + chan_switch_params->tdls_off_ch, + BWALL); + break; + } /* end switch */ + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Country Code=%s, Req offset=%d, Selected Operate Class=%d"), + mac->scan.countryCodeCurrent, + chan_switch_params->tdls_off_ch_bw_offset, + chan_switch_params->oper_class); + + cds_message.type = WMA_TDLS_SET_OFFCHAN_MODE; + cds_message.reserved = 0; + cds_message.bodyptr = chan_switch_params; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Message Post failed status=%d"), + cdf_status); + cdf_mem_free(chan_switch_params); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} +#endif /* FEATURE_WLAN_TDLS */ + +CDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq, + void *plsContext, + void (*pCallbackfn)(tSirLinkSpeedInfo *indParam, + void *pContext)) +{ + + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + if ((NULL == pCallbackfn) && + (NULL == pMac->sme.pLinkSpeedIndCb)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Indication Call back did not registered", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } else if (NULL != pCallbackfn) { + pMac->sme.pLinkSpeedCbContext = plsContext; + pMac->sme.pLinkSpeedIndCb = pCallbackfn; + } + /* serialize the req through MC thread */ + cds_message.bodyptr = lsReq; + cds_message.type = WMA_GET_LINK_SPEED; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post Link Speed msg fail", __func__); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_update_enable_ssr(tHalHandle hHal, bool enableSSR) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "SSR level is changed %d", enableSSR); + /* not serializing this messsage, as this is only going + * to set a variable in WMA/WDI + */ + WMA_SetEnableSSR(enableSSR); + sme_release_global_lock(&pMac->sme); + } + return; +} + +CDF_STATUS sme_check_ch_in_band(tpAniSirGlobal mac_ctx, uint8_t start_ch, + uint8_t ch_cnt) +{ + uint8_t i; + for (i = 0; i < ch_cnt; i++) { + if (CDF_STATUS_SUCCESS != csr_is_valid_channel(mac_ctx, + (start_ch + i*4))) + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +void sme_set_160bw_params(tpAniSirGlobal mac_ctx, uint8_t channel, + chan_params_t *ch_params) +{ + uint8_t start_ch = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (channel >= 36 && channel <= 64) { + ch_params->center_freq_seg0 = 50; + start_ch = 36; + } else if (channel >= 100 && channel <= 128) { + ch_params->center_freq_seg0 = 114; + start_ch = 100; + } else { + ch_params->ch_width = CH_WIDTH_80MHZ; + } + + if (ch_params->ch_width == CH_WIDTH_160MHZ) + status = sme_check_ch_in_band(mac_ctx, start_ch, 8); + + if (CDF_STATUS_SUCCESS != status) + ch_params->ch_width = CH_WIDTH_80MHZ; +} + +void sme_set_80bw_params(tpAniSirGlobal mac_ctx, uint8_t channel, + chan_params_t *ch_params) +{ + uint8_t start_ch = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (channel >= 36 && channel <= 48) { + ch_params->center_freq_seg0 = 42; + start_ch = 36; + } else if (channel >= 52 && channel <= 64) { + ch_params->center_freq_seg0 = 58; + start_ch = 52; + } else if (channel >= 100 && channel <= 112) { + ch_params->center_freq_seg0 = 106; + start_ch = 100; + } else if (channel >= 116 && channel <= 128) { + ch_params->center_freq_seg0 = 122; + start_ch = 116; + } else if (channel >= 132 && channel <= 144) { + ch_params->center_freq_seg0 = 138; + start_ch = 132; + } else if (channel >= 149 && channel <= 161) { + ch_params->center_freq_seg0 = 155; + start_ch = 149; + } else { + ch_params->ch_width = CH_WIDTH_40MHZ; + } + + if (ch_params->ch_width == CH_WIDTH_80MHZ) + status = sme_check_ch_in_band(mac_ctx, start_ch, 4); + + if (CDF_STATUS_SUCCESS != status) + ch_params->ch_width = CH_WIDTH_40MHZ; +} + +void sme_set_40bw_params(tpAniSirGlobal mac_ctx, uint8_t channel, + chan_params_t *ch_params, uint8_t is_11ac_mode) +{ + uint8_t tmp; + uint8_t center_freq = 0; + bool valid_40Mhz_ch = true; + + if (channel == 165) { + ch_params->ch_width = CH_WIDTH_20MHZ; + ch_params->center_freq_seg0 = 0; + ch_params->sec_ch_offset = PHY_SINGLE_CHANNEL_CENTERED; + return; + } + tmp = channel % 2; + if ((channel - tmp) % 8) { + ch_params->sec_ch_offset = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + center_freq = channel + 2; + } else { + ch_params->sec_ch_offset = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + center_freq = channel - 2; + } + if ((!is_11ac_mode) || (is_11ac_mode && + (ch_params->ch_width == CH_WIDTH_40MHZ))) { + ch_params->ch_width = CH_WIDTH_40MHZ; + ch_params->center_freq_seg0 = center_freq; + valid_40Mhz_ch = csr_roam_is_valid40_mhz_channel(mac_ctx, + ch_params->center_freq_seg0); + } + if (!valid_40Mhz_ch) { + ch_params->ch_width = CH_WIDTH_20MHZ; + ch_params->center_freq_seg0 = 0; + ch_params->sec_ch_offset = PHY_SINGLE_CHANNEL_CENTERED; + } +} + +/* + * SME API to determine the channel bonding mode + */ +CDF_STATUS sme_set_ch_params(tHalHandle hHal, eCsrPhyMode eCsrPhyMode, + uint8_t channel, uint8_t ht_sec_ch, chan_params_t *ch_params) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal); + int is_11ac_mode = CSR_IS_PHY_MODE_11ac(eCsrPhyMode); + + if (!CSR_IS_PHY_MODE_11n(eCsrPhyMode) || + ch_params->ch_width == CH_WIDTH_20MHZ || + CDF_STATUS_SUCCESS != csr_is_valid_channel(mac_ctx, channel)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid Channel/phymode config: CB Mode disabled", + __func__); + ch_params->ch_width = CH_WIDTH_20MHZ; + ch_params->sec_ch_offset = PHY_SINGLE_CHANNEL_CENTERED; + if (channel <= 14) + mac_ctx->roam.configParam.channelBondingMode24GHz = + PHY_SINGLE_CHANNEL_CENTERED; + else + mac_ctx->roam.configParam.channelBondingMode5GHz = + PHY_SINGLE_CHANNEL_CENTERED; + return CDF_STATUS_SUCCESS; + } + + sms_log(mac_ctx, LOGW, "%s: channel - %d, vht channel width - %d", + __func__, channel, ch_params->ch_width); + + if (CDS_IS_CHANNEL_5GHZ(channel)) { + if (ch_params->ch_width == CH_WIDTH_160MHZ) + sme_set_160bw_params(mac_ctx, channel, ch_params); + if ((ch_params->ch_width == CH_WIDTH_80MHZ) || + (ch_params->ch_width == CH_WIDTH_80P80MHZ)) + sme_set_80bw_params(mac_ctx, channel, ch_params); + + sme_set_40bw_params(mac_ctx, channel, + ch_params, is_11ac_mode); + + mac_ctx->roam.configParam.channelBondingMode5GHz = + ch_params->sec_ch_offset; + } else if (CDS_IS_CHANNEL_24GHZ(channel)) { + if (channel >= 1 && channel < 5) { + ch_params->ch_width = CH_WIDTH_40MHZ; + ch_params->sec_ch_offset = + PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + ch_params->center_freq_seg0 = channel + 2; + } else if (channel >= 5 && channel <= 9) { + ch_params->ch_width = CH_WIDTH_40MHZ; + if (0 != ht_sec_ch) { + if (ht_sec_ch > channel) { + ch_params->sec_ch_offset = + PHY_DOUBLE_CHANNEL_LOW_PRIMARY; + ch_params->center_freq_seg0 = + channel + 2; + } else { + ch_params->sec_ch_offset = + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + ch_params->center_freq_seg0 = + channel - 2; + } + } else { + /* in case ht_sec_ch is not set by ACS or + * calling function, set the secondary channel + * offset value to lower channel + */ + ch_params->sec_ch_offset = + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + ch_params->center_freq_seg0 = channel - 2; + } + } else if (channel > 9 && channel <= 13) { + ch_params->ch_width = CH_WIDTH_40MHZ; + ch_params->sec_ch_offset = + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; + ch_params->center_freq_seg0 = channel - 2; + } else if (channel == 14) { + ch_params->ch_width = CH_WIDTH_20MHZ; + ch_params->sec_ch_offset = + PHY_SINGLE_CHANNEL_CENTERED; + ch_params->center_freq_seg0 = 0; + } + mac_ctx->roam.configParam.channelBondingMode24GHz = + ch_params->sec_ch_offset; + } + return CDF_STATUS_SUCCESS; +} + +/*convert the ini value to the ENUM used in csr and MAC for CB state*/ +ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value) +{ + return csr_convert_cb_ini_value_to_phy_cb_state(cb_ini_value); +} + +/*-------------------------------------------------------------------------- + + \brief sme_set_curr_device_mode() - Sets the current operating device mode. + \param hHal - The handle returned by mac_open. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ + +void sme_set_curr_device_mode(tHalHandle hHal, tCDF_CON_MODE currDeviceMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->sme.currDeviceMode = currDeviceMode; + return; +} + +/*-------------------------------------------------------------------------- + \brief sme_handoff_request() - a wrapper function to Request a handoff + from CSR. + This is a synchronous call + \param hHal - The handle returned by mac_open + \param sessionId - Session Identifier + \param pHandoffInfo - info provided by HDD with the handoff request (namely: + BSSID, channel etc.) + \return CDF_STATUS_SUCCESS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_handoff_request(tHalHandle hHal, + uint8_t sessionId, + tCsrHandoffRequest *pHandoffInfo) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: invoked", __func__); + status = csr_handoff_request(pMac, sessionId, pHandoffInfo); + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +#ifdef IPA_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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal, uint8_t session_id, + struct sir_ipa_offload_enable_disable *request) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + struct sir_ipa_offload_enable_disable *request_buf; + cds_msg_t msg; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + request_buf = cdf_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for \ + IPA_OFFLOAD_ENABLE_DISABLE")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + request_buf->offload_type = request->offload_type; + request_buf->vdev_id = request->vdev_id; + request_buf->enable = request->enable; + + msg.type = WMA_IPA_OFFLOAD_ENABLE_DISABLE; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDS_MQ_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_IPA_OFFLOAD_\ + ENABLE_DISABLE message to WMA")); + cdf_mem_free(request_buf); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + sme_release_global_lock(&pMac->sme); + } + + return CDF_STATUS_SUCCESS; +} +#endif /* IPA_OFFLOAD */ + +/* + * SME API to check if there is any infra station or + * P2P client is connected + */ +CDF_STATUS sme_is_sta_p2p_client_connected(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + if (csr_is_infra_connected(pMac)) { + return CDF_STATUS_SUCCESS; + } + return CDF_STATUS_E_FAILURE; +} + +#ifdef FEATURE_WLAN_LPHB +/* --------------------------------------------------------------------------- + \fn sme_lphb_config_req + \API to make configuration LPHB within FW. + \param hHal - The handle returned by mac_open + \param lphdReq - LPHB request argument by client + \param pCallbackfn - LPHB timeout notification callback function pointer + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +CDF_STATUS sme_lphb_config_req + (tHalHandle hHal, + tSirLPHBReq *lphdReq, + void (*pCallbackfn)(void *pHddCtx, tSirLPHBInd *indParam) + ) { + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + if ((LPHB_SET_EN_PARAMS_INDID == lphdReq->cmd) && + (NULL == pCallbackfn) && (NULL == pMac->sme.pLphbIndCb)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Indication Call back did not registered", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } else if (NULL != pCallbackfn) { + pMac->sme.pLphbIndCb = pCallbackfn; + } + + /* serialize the req through MC thread */ + cds_message.bodyptr = lphdReq; + cds_message.type = WMA_LPHB_CONF_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post Config LPHB MSG fail", __func__); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&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 mac_open + \return NONE. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan(tHalHandle hHal, uint8_t nNumStaChan, + uint8_t nNumP2PChan) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pMac->roam.configParam.nNumStaChanCombinedConc = nNumStaChan; + pMac->roam.configParam.nNumP2PChanCombinedConc = nNumP2PChan; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: SCAN nNumStaChanCombinedConc : %d," + "nNumP2PChanCombinedConc : %d ", + __func__, nNumStaChan, nNumP2PChan); + + return; + +} + +/** + * sme_add_periodic_tx_ptrn() - Add Periodic TX Pattern + * @hal: global hal handle + * @addPeriodicTxPtrnParams: request message + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS +sme_add_periodic_tx_ptrn(tHalHandle hal, + struct sSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sSirAddPeriodicTxPtrn *req_msg; + cds_msg_t msg; + + sms_log(mac, LOG1, FL("enter")); + + req_msg = cdf_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + sms_log(mac, LOGE, FL("memory allocation failed")); + return CDF_STATUS_E_NOMEM; + } + + *req_msg = *addPeriodicTxPtrnParams; + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + msg.bodyptr = req_msg; + msg.type = WMA_ADD_PERIODIC_TX_PTRN_IND; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + } + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_del_periodic_tx_ptrn() - Delete Periodic TX Pattern + * @hal: global hal handle + * @delPeriodicTxPtrnParams: request message + * + * Return: CDF_STATUS enumeration + */ +CDF_STATUS +sme_del_periodic_tx_ptrn(tHalHandle hal, + struct sSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sSirDelPeriodicTxPtrn *req_msg; + cds_msg_t msg; + + sms_log(mac, LOG1, FL("enter")); + + req_msg = cdf_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + sms_log(mac, LOGE, FL("memory allocation failed")); + return CDF_STATUS_E_NOMEM; + } + + *req_msg = *delPeriodicTxPtrnParams; + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + msg.bodyptr = req_msg; + msg.type = WMA_DEL_PERIODIC_TX_PTRN_IND; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + } + sme_release_global_lock(&mac->sme); + return status; +} + +void sme_get_command_q_status(tHalHandle hHal) +{ + tSmeCmd *pTempCmd = NULL; + tListElem *pEntry; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: pMac is NULL", __func__); + return; + } + + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + } + sms_log(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 */ + dump_csr_command_info(pMac, pTempCmd); + } + } /* if(pTempCmd) */ + + sms_log(pMac, LOGE, "Currently smeCmdPendingList has %d commands", + csr_ll_count(&pMac->sme.smeCmdPendingList)); + + sms_log(pMac, LOGE, "Currently roamCmdPendingList has %d commands", + csr_ll_count(&pMac->roam.roamCmdPendingList)); + + return; +} + +/** + * sme_set_dot11p_config() - API to set the 802.11p config + * @hHal: The handle returned by macOpen + * @enable_dot11p: 802.11p config param + */ +void sme_set_dot11p_config(tHalHandle hHal, bool enable_dot11p) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->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 = cdf_mem_malloc(length); + if (!dst) + return NULL; + + *dst = *src; + + cursor = dst; + cursor += sizeof(*dst); + dst->channels = cursor; + cursor += src->channel_count * sizeof(*src->channels); + cdf_mem_copy(dst->channels, src->channels, + src->channel_count * sizeof(*src->channels)); + dst->schedule = cursor; + cursor += src->schedule_size * sizeof(*src->schedule); + cdf_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; + cdf_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; + cdf_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: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_ocb_set_config(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_config *config) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_ocb_config *msg_body; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_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 = CDF_STATUS_E_BUSY; + goto end; + } + + msg_body = sme_copy_sir_ocb_config(config); + + if (!msg_body) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + + msg.type = WMA_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; + + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), status); + pMac->sme.ocb_set_config_callback = callback; + pMac->sme.ocb_set_config_context = context; + cdf_mem_free(msg_body); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * sme_ocb_set_utc_time() - Set the OCB UTC time + * @hHal: reference to the HAL + * @utc: the UTC time struct + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_ocb_set_utc_time(tHalHandle hHal, struct sir_ocb_utc *utc) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_ocb_utc *sme_utc; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + sme_utc = cdf_mem_malloc(sizeof(*sme_utc)); + if (!sme_utc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Malloc failed")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + *sme_utc = *utc; + + msg.type = WMA_OCB_SET_UTC_TIME_CMD; + msg.reserved = 0; + msg.bodyptr = sme_utc; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post message to WDA")); + cdf_mem_free(utc); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * sme_ocb_start_timing_advert() - Start sending timing advert frames + * @hHal: reference to the HAL + * @timing_advert: the timing advertisement struct + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_ocb_start_timing_advert(tHalHandle hHal, + struct sir_ocb_timing_advert *timing_advert) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + void *buf; + struct sir_ocb_timing_advert *sme_timing_advert; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + buf = cdf_mem_malloc(sizeof(*sme_timing_advert) + + timing_advert->template_length); + if (!buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for start TA")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + + sme_timing_advert = (struct sir_ocb_timing_advert *)buf; + *sme_timing_advert = *timing_advert; + sme_timing_advert->template_value = buf + sizeof(*sme_timing_advert); + cdf_mem_copy(sme_timing_advert->template_value, + timing_advert->template_value, timing_advert->template_length); + + msg.type = WMA_OCB_START_TIMING_ADVERT_CMD; + msg.reserved = 0; + msg.bodyptr = buf; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post msg to WDA")); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * sme_ocb_stop_timing_advert() - Stop sending timing advert frames on a channel + * @hHal: reference to the HAL + * @timing_advert: the timing advertisement struct + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_ocb_stop_timing_advert(tHalHandle hHal, + struct sir_ocb_timing_advert *timing_advert) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_ocb_timing_advert *sme_timing_advert; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + sme_timing_advert = cdf_mem_malloc(sizeof(*timing_advert)); + if (!sme_timing_advert) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for stop TA")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + *sme_timing_advert = *timing_advert; + + msg.type = WMA_OCB_STOP_TIMING_ADVERT_CMD; + msg.reserved = 0; + msg.bodyptr = sme_timing_advert; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post msg to WDA")); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * 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: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_ocb_get_tsf_timer(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_ocb_get_tsf_timer *request) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_ocb_get_tsf_timer *msg_body; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = cdf_mem_malloc(sizeof(*msg_body)); + if (!msg_body) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + *msg_body = *request; + + msg.type = WMA_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 */ + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), status); + pMac->sme.ocb_get_tsf_timer_callback = NULL; + pMac->sme.ocb_get_tsf_timer_context = NULL; + cdf_mem_free(msg_body); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * 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: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_dcc_get_stats(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_get_stats *request) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_dcc_get_stats *msg_body; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = cdf_mem_malloc(sizeof(*msg_body) + + request->request_array_len); + if (!msg_body) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + *msg_body = *request; + msg_body->request_array = (void *)msg_body + sizeof(*msg_body); + cdf_mem_copy(msg_body->request_array, request->request_array, + request->request_array_len); + + msg.type = WMA_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; + + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), status); + pMac->sme.dcc_get_stats_callback = callback; + pMac->sme.dcc_get_stats_context = context; + cdf_mem_free(msg_body); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * sme_dcc_clear_stats() - Clear the DCC stats + * @hHal: reference to the HAL + * @vdev_id: vdev id for OCB interface + * @dcc_stats_bitmap: the entries in the stats to clear + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_dcc_clear_stats(tHalHandle hHal, uint32_t vdev_id, + uint32_t dcc_stats_bitmap) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_dcc_clear_stats *request; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + request = cdf_mem_malloc(sizeof(struct sir_dcc_clear_stats)); + if (!request) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + + cdf_mem_zero(request, sizeof(*request)); + request->vdev_id = vdev_id; + request->dcc_stats_bitmap = dcc_stats_bitmap; + + msg.type = WMA_DCC_CLEAR_STATS_CMD; + msg.bodyptr = request; + + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post msg to WDA")); + cdf_mem_free(request); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * 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: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_dcc_update_ndl(tHalHandle hHal, void *context, + ocb_callback callback, + struct sir_dcc_update_ndl *request) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg = {0}; + struct sir_dcc_update_ndl *msg_body; + + /* Lock the SME structure */ + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + + /* Allocate memory for the WMI request, and copy the parameter */ + msg_body = cdf_mem_malloc(sizeof(*msg_body) + + request->dcc_ndl_chan_list_len + + request->dcc_ndl_active_state_list_len); + if (!msg_body) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to allocate memory")); + status = CDF_STATUS_E_NOMEM; + 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; + cdf_mem_copy(msg_body->dcc_ndl_chan_list, request->dcc_ndl_chan_list, + request->dcc_ndl_active_state_list_len); + cdf_mem_copy(msg_body->dcc_ndl_active_state_list, + request->dcc_ndl_active_state_list, + request->dcc_ndl_active_state_list_len); + + msg.type = WMA_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; + + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Error posting message to WDA: %d"), status); + pMac->sme.dcc_update_ndl_callback = NULL; + pMac->sme.dcc_update_ndl_context = NULL; + cdf_mem_free(msg_body); + goto end; + } + +end: + sme_release_global_lock(&pMac->sme); + + return status; +} + +/** + * 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: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE on failure + */ +CDF_STATUS sme_register_for_dcc_stats_event(tHalHandle hHal, void *context, + ocb_callback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + status = sme_acquire_global_lock(&pMac->sme); + pMac->sme.dcc_stats_event_callback = callback; + pMac->sme.dcc_stats_event_context = context; + sme_release_global_lock(&pMac->sme); + + return 0; +} + +void sme_get_recovery_stats(tHalHandle hHal) +{ + uint8_t i; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Self Recovery Stats"); + for (i = 0; i < MAX_ACTIVE_CMD_STATS; i++) { + if (eSmeNoCommand != + g_self_recovery_stats.activeCmdStats[i].command) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "timestamp %llu: command 0x%0X: reason %d: session %d", + g_self_recovery_stats.activeCmdStats[i]. + timestamp, + g_self_recovery_stats.activeCmdStats[i].command, + g_self_recovery_stats.activeCmdStats[i].reason, + g_self_recovery_stats.activeCmdStats[i]. + sessionId); + } + } +} + +/** + * sme_save_active_cmd_stats() - To save active command stats + * @hHal: HAL context + * + * This routine is to save active command stats + * + * Return: None + */ +void sme_save_active_cmd_stats(tHalHandle hHal) +{ + tSmeCmd *pTempCmd = NULL; + tListElem *pEntry; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t statidx = 0; + tActiveCmdStats *actv_cmd_stat = NULL; + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("pMac is NULL")); + return; + } + + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) + pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + + if (!pTempCmd) + return; + + if (eSmeCsrCommandMask & pTempCmd->command) { + statidx = g_self_recovery_stats.cmdStatsIndx; + actv_cmd_stat = &g_self_recovery_stats.activeCmdStats[statidx]; + actv_cmd_stat->command = pTempCmd->command; + actv_cmd_stat->sessionId = pTempCmd->sessionId; + actv_cmd_stat->timestamp = cds_get_monotonic_boottime(); + if (eSmeCommandRoam == pTempCmd->command) + actv_cmd_stat->reason = pTempCmd->u.roamCmd.roamReason; + else if (eSmeCommandScan == pTempCmd->command) + actv_cmd_stat->reason = pTempCmd->u.scanCmd.reason; + else + actv_cmd_stat->reason = 0xFF; + + g_self_recovery_stats.cmdStatsIndx = + ((g_self_recovery_stats.cmdStatsIndx + 1) & + (MAX_ACTIVE_CMD_STATS - 1)); + } + return; +} + +void active_list_cmd_timeout_handle(void *userData) +{ + if (NULL == userData) + return; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Active List command timeout Cmd List Count %d", __func__, + csr_ll_count(&((tpAniSirGlobal) userData)->sme. + smeCmdActiveList)); + sme_get_command_q_status((tHalHandle) userData); + + if (((tpAniSirGlobal) userData)->sme.enableSelfRecovery) { + sme_save_active_cmd_stats((tHalHandle) userData); + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } +} + +CDF_STATUS sme_notify_modem_power_state(tHalHandle hHal, uint32_t value) +{ + cds_msg_t msg; + tpSirModemPowerStateInd request_buf; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(tSirModemPowerStateInd)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for MODEM POWER STATE IND", + __func__); + return CDF_STATUS_E_NOMEM; + } + + request_buf->param = value; + + msg.type = WMA_MODEM_POWER_STATE_IND; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_MODEM_POWER_STATE_IND message" + " to WMA", __func__); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +#ifdef QCA_HT_2040_COEX +CDF_STATUS sme_notify_ht2040_mode(tHalHandle hHal, uint16_t staId, + struct cdf_mac_addr macAddrSTA, + uint8_t sessionId, + uint8_t channel_type) +{ + cds_msg_t msg; + tUpdateVHTOpMode *pHtOpMode = NULL; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + return CDF_STATUS_E_FAILURE; + } + + pHtOpMode = cdf_mem_malloc(sizeof(tUpdateVHTOpMode)); + if (NULL == pHtOpMode) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for setting OP mode", + __func__); + return CDF_STATUS_E_NOMEM; + } + + 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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid OP mode", __func__); + return CDF_STATUS_E_FAILURE; + } + + pHtOpMode->staId = staId, + cdf_mem_copy(pHtOpMode->peer_mac, macAddrSTA.bytes, + sizeof(tSirMacAddr)); + pHtOpMode->smesessionId = sessionId; + + msg.type = WMA_UPDATE_OP_MODE; + msg.reserved = 0; + msg.bodyptr = pHtOpMode; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_UPDATE_OP_MODE message" + " to WMA", __func__); + cdf_mem_free(pHtOpMode); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: Notifed FW about OP mode: %d for staId=%d", + __func__, pHtOpMode->opMode, staId); + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_ht2040_mode + + \brief To update HT Operation beacon IE. + + \param + + \return CDF_STATUS SUCCESS + FAILURE or RESOURCES + The API finished and failed. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_set_ht2040_mode(tHalHandle hHal, uint8_t sessionId, + uint8_t channel_type, bool obssEnabled) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + ePhyChanBondState cbMode; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s:Error!!! Invalid HT20/40 mode !", __func__); + return CDF_STATUS_E_FAILURE; + } + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_set_ht2040_mode(pMac, sessionId, + cbMode, obssEnabled); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn sme_set_phy_cb_mode24_g + + \brief Changes PHY channel bonding mode + + \param hHal - The handle returned by mac_open. + + \param cbMode new channel bonding mode which is to set + + \return CDF_STATUS SUCCESS. + + -------------------------------------------------------------------------------*/ +CDF_STATUS sme_set_phy_cb_mode24_g(tHalHandle hHal, ePhyChanBondState phyCBMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == pMac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return CDF_STATUS_E_FAILURE; + } + + pMac->roam.configParam.channelBondingMode24GHz = phyCBMode; + + return CDF_STATUS_SUCCESS; +} +#endif + +/* + * SME API to enable/disable idle mode powersave + * This should be called only if powersave offload + * is enabled + */ +CDF_STATUS sme_set_idle_powersave_config(void *cds_context, + tHalHandle hHal, uint32_t value) +{ + void *wmaContext = cds_get_context(CDF_MODULE_ID_WMA); + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (NULL == wmaContext) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: wmaContext is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + " Idle Ps Set Value %d", value); + + pMac->imps_enabled = false; + if (CDF_STATUS_SUCCESS != wma_set_idle_ps_config(wmaContext, value)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + " Failed to Set Idle Ps Value %d", value); + return CDF_STATUS_E_FAILURE; + } + if (value) + pMac->imps_enabled = true; + return CDF_STATUS_SUCCESS; +} + +int16_t sme_get_ht_config(tHalHandle hHal, uint8_t session_id, uint16_t ht_capab) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id); + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "invalid ht capability"); + return -EIO; + } +} + +int sme_update_ht_config(tHalHandle hHal, uint8_t sessionId, uint16_t htCapab, + int value) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: pSession is NULL", __func__); + return -EIO; + } + + if (CDF_STATUS_SUCCESS != wma_set_htconfig(sessionId, htCapab, value)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_send_rate_update_ind + \brief API to Update rate + \param hHal - The handle returned by mac_open + \param rateUpdateParams - Pointer to rate update params + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_send_rate_update_ind(tHalHandle hHal, + tSirRateUpdateInd *rateUpdateParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status; + cds_msg_t msg; + tSirRateUpdateInd *rate_upd = cdf_mem_malloc(sizeof(tSirRateUpdateInd)); + + if (rate_upd == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Rate update struct alloc failed"); + return CDF_STATUS_E_FAILURE; + } + *rate_upd = *rateUpdateParams; + + if (rate_upd->mcastDataRate24GHz == HT20_SHORT_GI_MCS7_RATE) + rate_upd->mcastDataRate24GHzTxFlag = + eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + else if (rate_upd->reliableMcastDataRate == + HT20_SHORT_GI_MCS7_RATE) + rate_upd->reliableMcastDataRateTxFlag = + eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + msg.type = WMA_RATE_UPDATE_IND; + msg.bodyptr = rate_upd; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able " + "to post WMA_SET_RMC_RATE_IND to WMA!", + __func__); + + sme_release_global_lock(&pMac->sme); + cdf_mem_free(rate_upd); + return CDF_STATUS_E_FAILURE; + } + + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_SUCCESS; + } + + return status; +} + +/** + * sme_get_reg_info() - To get registration info + * @hHal: HAL context + * @chanId: channel id + * @regInfo1: first reg info to fill + * @regInfo2: second reg info to fill + * + * This routine will give you reg info + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_get_reg_info(tHalHandle hHal, uint8_t chanId, + uint32_t *regInfo1, uint32_t *regInfo2) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status; + uint8_t i; + bool found = false; + + status = sme_acquire_global_lock(&pMac->sme); + *regInfo1 = 0; + *regInfo2 = 0; + if (!CDF_IS_STATUS_SUCCESS(status)) + return 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 = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&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 CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_auto_shutdown_cb(tHalHandle hHal, void (*pCallbackfn)(void) + ) { + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Plug in Auto shutdown event callback", __func__); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + if (NULL != pCallbackfn) { + pMac->sme.pAutoShutdownNotificationCb = pCallbackfn; + } + sme_release_global_lock(&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 mac_open + \param timer_val - The auto shutdown timer value to be set + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_auto_shutdown_timer(tHalHandle hHal, uint32_t timer_val) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirAutoShutdownCmdParams *auto_sh_cmd; + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + auto_sh_cmd = (tSirAutoShutdownCmdParams *) + cdf_mem_malloc(sizeof(tSirAutoShutdownCmdParams)); + if (auto_sh_cmd == NULL) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + auto_sh_cmd->timer_val = timer_val; + + /* serialize the req through MC thread */ + cds_message.bodyptr = auto_sh_cmd; + cds_message.type = WMA_SET_AUTO_SHUTDOWN_TIMER_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post Auto shutdown MSG fail", __func__); + cdf_mem_free(auto_sh_cmd); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: Posted Auto shutdown MSG", __func__); + sme_release_global_lock(&pMac->sme); + } + + return status; +} +#endif + +#ifdef FEATURE_WLAN_CH_AVOID +/* --------------------------------------------------------------------------- + \fn sme_add_ch_avoid_callback + \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 CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_add_ch_avoid_callback + (tHalHandle hHal, void (*pCallbackfn)(void *pAdapter, void *indParam) + ) { + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Plug in CH AVOID CB", __func__); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + if (NULL != pCallbackfn) { + pMac->sme.pChAvoidNotificationCb = pCallbackfn; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ch_avoid_update_req + \API to request channel avoidance update from FW. + \param hHal - The handle returned by mac_open + \param update_type - The udpate_type parameter of this request call + \- return Configuration message posting status, SUCCESS or Fail + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ch_avoid_update_req(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirChAvoidUpdateReq *cauReq; + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + cauReq = (tSirChAvoidUpdateReq *) + cdf_mem_malloc(sizeof(tSirChAvoidUpdateReq)); + if (NULL == cauReq) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "%s Request Buffer Alloc Fail", __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_NOMEM; + } + + cauReq->reserved_param = 0; + + /* serialize the req through MC thread */ + cds_message.bodyptr = cauReq; + cds_message.type = WMA_CH_AVOID_UPDATE_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Post Ch Avoid Update MSG fail", + __func__); + cdf_mem_free(cauReq); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: Posted Ch Avoid Update MSG", __func__); + sme_release_global_lock(&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 + * + */ +CDF_STATUS sme_set_miracast(tHalHandle hal, uint8_t filter_type) +{ + cds_msg_t msg; + uint32_t *val; + tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); + + val = cdf_mem_malloc(sizeof(*val)); + if (NULL == val || NULL == mac_ptr) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid pointer", __func__); + return CDF_STATUS_E_NOMEM; + } + + *val = filter_type; + + msg.type = SIR_HAL_SET_MIRACAST; + msg.reserved = 0; + msg.bodyptr = val; + + if (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!", + __func__); + cdf_mem_free(val); + return CDF_STATUS_E_FAILURE; + } + + mac_ptr->sme.miracast_value = filter_type; + return CDF_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 + * + */ +CDF_STATUS sme_set_mas(uint32_t val) +{ + cds_msg_t msg; + uint32_t *ptr_val; + + ptr_val = cdf_mem_malloc(sizeof(*ptr_val)); + if (NULL == ptr_val) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: could not allocate ptr_val", __func__); + return CDF_STATUS_E_NOMEM; + } + + *ptr_val = val; + + msg.type = SIR_HAL_SET_MAS; + msg.reserved = 0; + msg.bodyptr = ptr_val; + + if (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!", + __func__); + cdf_mem_free(ptr_val); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/* ------------------------------------------------------------------------- + \fn sme_roam_channel_change_req + \brief API to Indicate Channel change to new target channel + \param hHal - The handle returned by mac_open + \param targetChannel - New Channel to move the SAP to. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_channel_change_req(tHalHandle hHal, + struct cdf_mac_addr bssid, uint32_t cb_mode, tCsrRoamProfile *profile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t ch_mode; + + ch_mode = (profile->ChannelInfo.ChannelList[0] <= + CSR_MAX_2_4_GHZ_SUPPORTED_CHANNELS) ? + pMac->roam.configParam.channelBondingMode24GHz : + pMac->roam.configParam.channelBondingMode5GHz; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + FL("sapdfs: requested cbmode=[%d] & new negotiated cbmode[%d]"), + cb_mode, ch_mode); + status = csr_roam_channel_change_req(pMac, bssid, ch_mode, + profile); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* ------------------------------------------------------------------------- + \fn sme_process_channel_change_resp + \brief API to Indicate Channel change response message to SAP. + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac, + uint16_t msg_type, void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo proam_info = { 0 }; + eCsrRoamResult roamResult; + tpSwitchChannelParams pChnlParams = (tpSwitchChannelParams) pMsgBuf; + uint32_t SessionId = pChnlParams->peSessionId; + + proam_info.channelChangeRespEvent = + (tSirChanChangeResponse *) + cdf_mem_malloc(sizeof(tSirChanChangeResponse)); + if (NULL == proam_info.channelChangeRespEvent) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, + "Channel Change Event Allocation Failed: %d\n", status); + return status; + } + if (msg_type == eWNI_SME_CHANNEL_CHANGE_RSP) { + proam_info.channelChangeRespEvent->sessionId = SessionId; + proam_info.channelChangeRespEvent->newChannelNumber = + pChnlParams->channelNumber; + proam_info.channelChangeRespEvent->secondaryChannelOffset = + pChnlParams->ch_width; + + if (pChnlParams->status == CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Received success eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", + SessionId); + proam_info.channelChangeRespEvent->channelChangeStatus = + 1; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "sapdfs: Received failure eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]", + SessionId); + proam_info.channelChangeRespEvent->channelChangeStatus = + 0; + roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; + } + + csr_roam_call_callback(pMac, SessionId, &proam_info, 0, + eCSR_ROAM_SET_CHANNEL_RSP, roamResult); + + } else { + status = CDF_STATUS_E_FAILURE; + sms_log(pMac, LOGE, "Invalid Channel Change Resp Message: %d\n", + status); + } + cdf_mem_free(proam_info.channelChangeRespEvent); + + return status; +} + +/* ------------------------------------------------------------------------- + \fn sme_roam_start_beacon_req + \brief API to Indicate LIM to start Beacon Tx + \after SAP CAC Wait is completed. + \param hHal - The handle returned by mac_open + \param sessionId - session ID + \param dfsCacWaitStatus - CAC WAIT status flag + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, struct cdf_mac_addr bssid, + uint8_t dfsCacWaitStatus) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_start_beacon_req(pMac, bssid, dfsCacWaitStatus); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* ------------------------------------------------------------------------- + \fn sme_roam_csa_ie_request + \brief API to request CSA IE transmission from PE + \param hHal - The handle returned by mac_open + \param pDfsCsaReq - CSA IE request + \param bssid - SAP bssid + \param ch_bandwidth - Channel offset + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct cdf_mac_addr bssid, + uint8_t targetChannel, uint8_t csaIeReqd, + uint8_t ch_bandwidth) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_send_chan_sw_ie_request(pMac, bssid, targetChannel, + csaIeReqd, ch_bandwidth); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_init_thermal_info + \brief SME API to initialize the thermal mitigation parameters + \param hHal + \param thermalParam : thermal mitigation parameters + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_init_thermal_info(tHalHandle hHal, tSmeThermalParams thermalParam) +{ + t_thermal_mgmt *pWmaParam; + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pWmaParam = (t_thermal_mgmt *) cdf_mem_malloc(sizeof(t_thermal_mgmt)); + if (NULL == pWmaParam) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: could not allocate tThermalMgmt", __func__); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero((void *)pWmaParam, sizeof(t_thermal_mgmt)); + + pWmaParam->thermalMgmtEnabled = thermalParam.smeThermalMgmtEnabled; + pWmaParam->throttlePeriod = thermalParam.smeThrottlePeriod; + pWmaParam->thermalLevels[0].minTempThreshold = + thermalParam.smeThermalLevels[0].smeMinTempThreshold; + pWmaParam->thermalLevels[0].maxTempThreshold = + thermalParam.smeThermalLevels[0].smeMaxTempThreshold; + pWmaParam->thermalLevels[1].minTempThreshold = + thermalParam.smeThermalLevels[1].smeMinTempThreshold; + pWmaParam->thermalLevels[1].maxTempThreshold = + thermalParam.smeThermalLevels[1].smeMaxTempThreshold; + pWmaParam->thermalLevels[2].minTempThreshold = + thermalParam.smeThermalLevels[2].smeMinTempThreshold; + pWmaParam->thermalLevels[2].maxTempThreshold = + thermalParam.smeThermalLevels[2].smeMaxTempThreshold; + pWmaParam->thermalLevels[3].minTempThreshold = + thermalParam.smeThermalLevels[3].smeMinTempThreshold; + pWmaParam->thermalLevels[3].maxTempThreshold = + thermalParam.smeThermalLevels[3].smeMaxTempThreshold; + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + msg.type = WMA_INIT_THERMAL_INFO_CMD; + msg.bodyptr = pWmaParam; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_SET_THERMAL_INFO_CMD to WMA!", + __func__); + cdf_mem_free(pWmaParam); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_SUCCESS; + } + cdf_mem_free(pWmaParam); + return CDF_STATUS_E_FAILURE; +} + +/** + * sme_add_set_thermal_level_callback() - Plug in set thermal level callback + * @hal: Handle returned by macOpen + * @callback: sme_set_thermal_level_callback + * + * Plug in set thermal level callback + * + * Return: none + */ +void sme_add_set_thermal_level_callback(tHalHandle hal, + sme_set_thermal_level_callback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + + pMac->sme.set_thermal_level_cb = callback; +} + +/** + * sme_set_thermal_level() - SME API to set the thermal mitigation level + * @hal: Handler to HAL + * @level: Thermal mitigation level + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_set_thermal_level(tHalHandle hal, uint8_t level) +{ + cds_msg_t msg; + tpAniSirGlobal pMac = PMAC_STRUCT(hal); + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + cdf_mem_set(&msg, sizeof(msg), 0); + msg.type = WMA_SET_THERMAL_LEVEL; + msg.bodyval = level; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_SET_THERMAL_LEVEL to WMA!", + __func__); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_SUCCESS; + } + return CDF_STATUS_E_FAILURE; +} + +/* --------------------------------------------------------------------------- + \fn sme_txpower_limit + \brief SME API to set txpower limits + \param hHal + \param psmetx : power limits for 2g/5g + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_txpower_limit(tHalHandle hHal, tSirTxPowerLimit *psmetx) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_msg_t cds_message; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + cds_message.type = WMA_TX_POWER_LIMIT; + cds_message.reserved = 0; + cds_message.bodyptr = psmetx; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: not able to post WMA_TX_POWER_LIMIT", + __func__); + status = CDF_STATUS_E_FAILURE; + cdf_mem_free(psmetx); + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +CDF_STATUS sme_update_connect_debug(tHalHandle hHal, uint32_t set_value) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->fEnableDebugLog = set_value; + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ap_disable_intra_bss_fwd + + \brief + SME will send message to WMA to set Intra BSS in txrx + + \param + + hHal - The handle returned by mac_open + + sessionId - session id ( vdev id) + + disablefwd - bool value that indicate disable intrabss fwd disable + + \return CDF_STATUS + --------------------------------------------------------------------------- */ +CDF_STATUS sme_ap_disable_intra_bss_fwd(tHalHandle hHal, uint8_t sessionId, + bool disablefwd) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + int status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_msg_t cds_message; + tpDisableIntraBssFwd pSapDisableIntraFwd = NULL; + + /* Prepare the request to send to SME. */ + pSapDisableIntraFwd = cdf_mem_malloc(sizeof(tDisableIntraBssFwd)); + if (NULL == pSapDisableIntraFwd) { + sms_log(pMac, LOGP, "Memory Allocation Failure!!! %s", __func__); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(pSapDisableIntraFwd, sizeof(tDisableIntraBssFwd)); + + pSapDisableIntraFwd->sessionId = sessionId; + pSapDisableIntraFwd->disableintrabssfwd = disablefwd; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* serialize the req through MC thread */ + cds_message.bodyptr = pSapDisableIntraFwd; + cds_message.type = WMA_SET_SAP_INTRABSS_DIS; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + status = CDF_STATUS_E_FAILURE; + cdf_mem_free(pSapDisableIntraFwd); + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +#ifdef WLAN_FEATURE_STATS_EXT + +/****************************************************************************** + \fn sme_stats_ext_register_callback + + \brief + a function called to register the callback that send vendor event for stats + ext + + \param callback - callback to be registered +******************************************************************************/ +void sme_stats_ext_register_callback(tHalHandle hHal, StatsExtCallback callback) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pMac->sme.StatsExtCallback = callback; +} + +/****************************************************************************** + \fn sme_stats_ext_request + + \brief + a function called when HDD receives STATS EXT vendor command from userspace + + \param sessionID - vdevID for the stats ext request + + \param input - Stats Ext Request structure ptr + + \return CDF_STATUS +******************************************************************************/ +CDF_STATUS sme_stats_ext_request(uint8_t session_id, tpStatsExtRequestReq input) +{ + cds_msg_t msg; + tpStatsExtRequest data; + size_t data_len; + + data_len = sizeof(tStatsExtRequest) + input->request_data_len; + data = cdf_mem_malloc(data_len); + + if (data == NULL) { + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(data, data_len); + data->vdev_id = session_id; + data->request_data_len = input->request_data_len; + if (input->request_data_len) { + cdf_mem_copy(data->request_data, + input->request_data, input->request_data_len); + } + + msg.type = WMA_STATS_EXT_REQUEST; + msg.reserved = 0; + msg.bodyptr = data; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_STATS_EXT_REQUEST message to WMA", + __func__); + cdf_mem_free(data); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/****************************************************************************** + \fn sme_stats_ext_event + + \brief + a callback function called when SME received eWNI_SME_STATS_EXT_EVENT + response from WMA + + \param hHal - HAL handle for device + \param pMsg - Message body passed from WMA; includes NAN header + \return CDF_STATUS +******************************************************************************/ +CDF_STATUS sme_stats_ext_event(tHalHandle hHal, void *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (NULL == pMsg) { + sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = CDF_STATUS_E_FAILURE; + } else { + sms_log(pMac, LOG2, "SME: entering %s", __func__); + + if (pMac->sme.StatsExtCallback) { + pMac->sme.StatsExtCallback(pMac->hHdd, + (tpStatsExtEvent) pMsg); + } + } + + return status; +} + +#endif + +/* --------------------------------------------------------------------------- + \fn sme_update_dfs_scan_mode + \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 CDF_STATUS_SUCCESS - SME update DFS roaming scan config + successfully. + Other status means SME failed to update DFS roaming scan config. + \sa + -------------------------------------------------------------------------*/ +CDF_STATUS sme_update_dfs_scan_mode(tHalHandle hHal, uint8_t sessionId, + uint8_t allowDFSChannelRoam) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set AllowDFSChannelRoam Mode to " + "%d - old value is %d - roam state is %s", + allowDFSChannelRoam, + pMac->roam.configParam.allowDFSChannelRoam, + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo + [sessionId]. + neighborRoamState)); + pMac->roam.configParam.allowDFSChannelRoam = + allowDFSChannelRoam; + sme_release_global_lock(&pMac->sme); + } + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_DFS_SCAN_MODE_CHANGED); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_get_dfs_scan_mode() - get DFS roam scan mode + This is a synchronous call + \param hHal - The handle returned by mac_open. + \return DFS roaming scan mode 0 (disable), 1 (passive), 2 (active) + \sa + --------------------------------------------------------------------------*/ +uint8_t sme_get_dfs_scan_mode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + return pMac->roam.configParam.allowDFSChannelRoam; +} + +/*---------------------------------------------------------------------------- + \fn sme_modify_add_ie + \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 + -----------------------------------------------------------------------------*/ +CDF_STATUS sme_modify_add_ie(tHalHandle hHal, + tSirModifyIE *pModifyIE, eUpdateIEsType updateType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_modify_add_ies(pMac, pModifyIE, updateType); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/*---------------------------------------------------------------------------- + \fn sme_update_add_ie + \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 + -----------------------------------------------------------------------------*/ +CDF_STATUS sme_update_add_ie(tHalHandle hHal, + tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + status = sme_acquire_global_lock(&pMac->sme); + + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_update_add_ies(pMac, pUpdateIE, updateType); + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_sta_in_middle_of_roaming + \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 + -------------------------------------------------------------------------*/ +bool sme_sta_in_middle_of_roaming(tHalHandle hHal, uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool ret = false; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + ret = csr_neighbor_middle_of_roaming(hHal, sessionId); + sme_release_global_lock(&pMac->sme); + } + return ret; +} + + +/** + * sme_update_dsc_pto_up_mapping() + * @hHal: HAL context + * @dscpmapping: pointer to DSCP mapping structure + * @sessionId: SME session id + * + * This routine is called to update dscp mapping + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_update_dsc_pto_up_mapping(tHalHandle hHal, + sme_QosWmmUpType *dscpmapping, + uint8_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t i, j, peSessionId; + tCsrRoamSession *pCsrSession = NULL; + tpPESession pSession = NULL; + + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + pCsrSession = CSR_GET_SESSION(pMac, sessionId); + if (pCsrSession == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Session lookup fails for CSR session")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Invalid session Id %u"), sessionId); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + pSession = pe_find_session_by_bssid(pMac, + pCsrSession->connectedProfile.bssid.bytes, + &peSessionId); + + if (pSession == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL(" Session lookup fails for BSSID")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + + if (!pSession->QosMapSet.present) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("QOS Mapping IE not present")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } + 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; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("User Priority %d isn't used"), 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_release_global_lock(&pMac->sme); + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_abort_roam_scan + \brief API to abort current roam scan cycle by roam scan offload module. + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \return CDF_STATUS + ---------------------------------------------------------------------------*/ + +CDF_STATUS sme_abort_roam_scan(tHalHandle hHal, uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + sms_log(pMac, LOGW, "entering function %s", __func__); + if (pMac->roam.configParam.isRoamOffloadScanEnabled) { + /* acquire the lock for the sme object */ + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_ABORT_SCAN, + REASON_ROAM_ABORT_ROAM_SCAN); + /* release the lock for the sme object */ + sme_release_global_lock(&pMac->sme); + } + } + + return status; +} + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * sme_get_valid_channels_by_band() - to fetch valid channels filtered by band + * @hHal: HAL context + * @wifiBand: RF band information + * @aValidChannels: output array to store channel info + * @pNumChannels: output number of channels + * + * SME API to fetch all valid channels filtered by band + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_get_valid_channels_by_band(tHalHandle hHal, + uint8_t wifiBand, + uint32_t *aValidChannels, + uint8_t *pNumChannels) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t numChannels = 0; + uint8_t i = 0; + uint32_t totValidChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if (!aValidChannels || !pNumChannels) { + sms_log(pMac, CDF_TRACE_LEVEL_ERROR, + FL("Output channel list/NumChannels is NULL")); + return CDF_STATUS_E_INVAL; + } + + if ((wifiBand < WIFI_BAND_UNSPECIFIED) || (wifiBand >= WIFI_BAND_MAX)) { + sms_log(pMac, CDF_TRACE_LEVEL_ERROR, + FL("Invalid wifiBand (%d)"), wifiBand); + return CDF_STATUS_E_INVAL; + } + + status = sme_get_cfg_valid_channels(hHal, &chanList[0], + &totValidChannels); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, CDF_TRACE_LEVEL_ERROR, + FL("Fail to get valid channel list (err=%d)"), status); + return status; + } + + switch (wifiBand) { + case WIFI_BAND_UNSPECIFIED: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("Unspec Band, return all (%d) valid channels"), + totValidChannels); + numChannels = totValidChannels; + for (i = 0; i < totValidChannels; i++) { + aValidChannels[i] = cds_chan_to_freq(chanList[i]); + } + break; + + case WIFI_BAND_BG: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_BG (2.4 GHz)")); + for (i = 0; i < totValidChannels; i++) { + if (CDS_IS_CHANNEL_24GHZ(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A (5 GHz without DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CDS_IS_CHANNEL_5GHZ(chanList[i]) && + !CDS_IS_DFS_CH(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_ABG: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_ABG (2.4 GHz + 5 GHz; no DFS)")); + for (i = 0; i < totValidChannels; i++) { + if ((CDS_IS_CHANNEL_24GHZ(chanList[i]) || + CDS_IS_CHANNEL_5GHZ(chanList[i])) && + !CDS_IS_DFS_CH(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A_DFS_ONLY: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A_DFS (5 GHz DFS only)")); + for (i = 0; i < totValidChannels; i++) { + if (CDS_IS_CHANNEL_5GHZ(chanList[i]) && + CDS_IS_DFS_CH(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_A_WITH_DFS: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_A_WITH_DFS (5 GHz with DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CDS_IS_CHANNEL_5GHZ(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + case WIFI_BAND_ABG_WITH_DFS: + sms_log(pMac, CDF_TRACE_LEVEL_INFO, + FL("WIFI_BAND_ABG_WITH_DFS (2.4 GHz+5 GHz with DFS)")); + for (i = 0; i < totValidChannels; i++) { + if (CDS_IS_CHANNEL_24GHZ(chanList[i]) || + CDS_IS_CHANNEL_5GHZ(chanList[i])) { + aValidChannels[numChannels++] = + cds_chan_to_freq(chanList[i]); + } + } + break; + + default: + sms_log(pMac, CDF_TRACE_LEVEL_ERROR, + FL("Unknown wifiBand (%d))"), wifiBand); + return CDF_STATUS_E_INVAL; + break; + } + *pNumChannels = numChannels; + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ext_scan_get_capabilities + \brief SME API to fetch extscan capabilities + \param hHal + \param pReq: extscan capabilities structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ext_scan_get_capabilities(tHalHandle hHal, + tSirGetExtScanCapabilitiesReqParams * + pReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pReq; + cds_message.type = WMA_EXTSCAN_GET_CAPABILITIES_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ext_scan_start + \brief SME API to issue extscan start + \param hHal + \param pStartCmd: extscan start structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ext_scan_start(tHalHandle hHal, + tSirWifiScanCmdReqParams *pStartCmd) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pStartCmd; + cds_message.type = WMA_EXTSCAN_START_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ext_scan_stop + \brief SME API to issue extscan stop + \param hHal + \param pStopReq: extscan stop structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ext_scan_stop(tHalHandle hHal, tSirExtScanStopReqParams *pStopReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pStopReq; + cds_message.type = WMA_EXTSCAN_STOP_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_bss_hotlist + \brief SME API to set BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_bss_hotlist(tHalHandle hHal, + tSirExtScanSetBssidHotListReqParams * + pSetHotListReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pSetHotListReq; + cds_message.type = WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_reset_bss_hotlist + \brief SME API to reset BSSID hotlist + \param hHal + \param pSetHotListReq: extscan set hotlist structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_reset_bss_hotlist(tHalHandle hHal, + tSirExtScanResetBssidHotlistReqParams * + pResetReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pResetReq; + cds_message.type = WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_significant_change + \brief SME API to set significant change + \param hHal + \param pSetSignificantChangeReq: extscan set significant change structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_significant_change(tHalHandle hHal, + tSirExtScanSetSigChangeReqParams * + pSetSignificantChangeReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pSetSignificantChangeReq; + cds_message.type = WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_reset_significant_change + \brief SME API to reset significant change + \param hHal + \param pResetReq: extscan reset significant change structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_reset_significant_change(tHalHandle hHal, + tSirExtScanResetSignificantChangeReqParams + *pResetReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pResetReq; + cds_message.type = WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_cached_results + \brief SME API to get cached results + \param hHal + \param pCachedResultsReq: extscan get cached results structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_get_cached_results(tHalHandle hHal, + tSirExtScanGetCachedResultsReqParams * + pCachedResultsReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pCachedResultsReq; + cds_message.type = WMA_EXTSCAN_GET_CACHED_RESULTS_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/** + * sme_set_epno_list() - set epno network list + * @hHal: global hal handle + * @input: request message + * + * This function constructs the cds message and fill in message type, + * bodyptr with %input and posts it to WDA queue. + * + * Return: eHalStatus enumeration + */ +CDF_STATUS sme_set_epno_list(tHalHandle hal, + struct wifi_epno_params *input) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct wifi_epno_params *req_msg; + int len, i; + + sms_log(mac, LOG1, FL("enter")); + len = sizeof(*req_msg) + + (input->num_networks * sizeof(struct wifi_epno_network)); + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_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; + cdf_mem_copy(req_msg->networks[i].ssid.ssId, + input->networks[i].ssid.ssId, + req_msg->networks[i].ssid.length); + } + + status = sme_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = WMA_SET_EPNO_LIST_REQ; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_set_passpoint_list() - set passpoint network list + * @hal: global hal handle + * @input: request message + * + * This function constructs the cds message and fill in message type, + * bodyptr with @input and posts it to WDA queue. + * + * Return: eHalStatus enumeration + */ +CDF_STATUS sme_set_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *input) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct wifi_passpoint_req *req_msg; + int len, i; + + sms_log(mac, LOG1, FL("enter")); + len = sizeof(*req_msg) + + (input->num_networks * sizeof(struct wifi_passpoint_network)); + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_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; + cdf_mem_copy(req_msg->networks[i].realm, + input->networks[i].realm, + strlen(input->networks[i].realm) + 1); + cdf_mem_copy(req_msg->networks[i].plmn, + input->networks[i].plmn, + SIR_PASSPOINT_PLMN_LEN); + cdf_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_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = WMA_SET_PASSPOINT_LIST_REQ; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_reset_passpoint_list() - reset passpoint network list + * @hHal: global hal handle + * @input: request message + * + * Return: eHalStatus enumeration + */ +CDF_STATUS sme_reset_passpoint_list(tHalHandle hal, + struct wifi_passpoint_req *input) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct wifi_passpoint_req *req_msg; + + sms_log(mac, LOG1, FL("enter")); + req_msg = cdf_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(req_msg, sizeof(*req_msg)); + req_msg->request_id = input->request_id; + req_msg->session_id = input->session_id; + + status = sme_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = WMA_RESET_PASSPOINT_LIST_REQ; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_set_ssid_hotlist() - Set the SSID hotlist + * @hal: SME handle + * @request: set ssid hotlist request + * + * Return: eHalStatus + */ +CDF_STATUS +sme_set_ssid_hotlist(tHalHandle hal, + struct sir_set_ssid_hotlist_request *request) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct sir_set_ssid_hotlist_request *set_req; + + set_req = cdf_mem_malloc(sizeof(*set_req)); + if (!set_req) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_FAILURE; + } + + *set_req = *request; + status = sme_acquire_global_lock(&mac->sme); + if (CDF_STATUS_SUCCESS == status) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = set_req; + cds_message.type = WMA_EXTSCAN_SET_SSID_HOTLIST_REQ; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + sme_release_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(set_req); + status = CDF_STATUS_E_FAILURE; + } + } else { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(set_req); + status = CDF_STATUS_E_FAILURE; + } + return status; +} + +CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, + void (*pExtScanIndCb)(void *, + const uint16_t, + void *)) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pMac->sme.pExtScanIndCb = pExtScanIndCb; + sme_release_global_lock(&pMac->sme); + } + return status; +} + +#else +CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, + void (*pExtScanIndCb)(void *, const uint16_t, void *)) +{ + return CDF_STATUS_SUCCESS; +} + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +/* --------------------------------------------------------------------------- + \fn sme_ll_stats_clear_req + \brief SME API to clear Link Layer Statistics + \param hHal + \param pclearStatsReq: Link Layer clear stats request params structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ll_stats_clear_req(tHalHandle hHal, + tSirLLStatsClearReq *pclearStatsReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tSirLLStatsClearReq *clear_stats_req; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "staId = %u", pclearStatsReq->staId); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "statsClearReqMask = 0x%X", + pclearStatsReq->statsClearReqMask); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "stopReq = %u", pclearStatsReq->stopReq); + + clear_stats_req = cdf_mem_malloc(sizeof(*clear_stats_req)); + + if (!clear_stats_req) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WMA_LL_STATS_CLEAR_REQ", + __func__); + return CDF_STATUS_E_NOMEM; + } + + *clear_stats_req = *pclearStatsReq; + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = clear_stats_req; + cds_message.type = WMA_LINK_LAYER_STATS_CLEAR_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: not able to post WMA_LL_STATS_CLEAR_REQ", + __func__); + cdf_mem_free(clear_stats_req); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "%s: " + "sme_acquire_global_lock error", __func__); + cdf_mem_free(clear_stats_req); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ll_stats_set_req + \brief SME API to set the Link Layer Statistics + \param hHal + \param psetStatsReq: Link Layer set stats request params structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ll_stats_set_req(tHalHandle hHal, tSirLLStatsSetReq *psetStatsReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tSirLLStatsSetReq *set_stats_req; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: MPDU Size = %u", __func__, + psetStatsReq->mpduSizeThreshold); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + " Aggressive Stats Collections = %u", + psetStatsReq->aggressiveStatisticsGathering); + + set_stats_req = cdf_mem_malloc(sizeof(*set_stats_req)); + + if (!set_stats_req) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WMA_LL_STATS_SET_REQ", + __func__); + return CDF_STATUS_E_NOMEM; + } + + *set_stats_req = *psetStatsReq; + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = set_stats_req; + cds_message.type = WMA_LINK_LAYER_STATS_SET_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: not able to post WMA_LL_STATS_SET_REQ", + __func__); + cdf_mem_free(set_stats_req); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "%s: " + "sme_acquire_global_lock error", __func__); + cdf_mem_free(set_stats_req); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_ll_stats_get_req + \brief SME API to get the Link Layer Statistics + \param hHal + \param pgetStatsReq: Link Layer get stats request params structure + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_ll_stats_get_req(tHalHandle hHal, tSirLLStatsGetReq *pgetStatsReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tSirLLStatsGetReq *get_stats_req; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "reqId = %u", pgetStatsReq->reqId); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "staId = %u", pgetStatsReq->staId); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "Stats Type = %u", pgetStatsReq->paramIdMask); + + get_stats_req = cdf_mem_malloc(sizeof(*get_stats_req)); + + if (!get_stats_req) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WMA_LL_STATS_GET_REQ", + __func__); + return CDF_STATUS_E_NOMEM; + } + + *get_stats_req = *pgetStatsReq; + + if (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = get_stats_req; + cds_message.type = WMA_LINK_LAYER_STATS_GET_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: not able to post WMA_LL_STATS_GET_REQ", + __func__); + + cdf_mem_free(get_stats_req); + status = CDF_STATUS_E_FAILURE; + + } + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "%s: " + "sme_acquire_global_lock error", __func__); + cdf_mem_free(get_stats_req); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_link_layer_stats_ind_cb + \brief SME API to trigger the stats are available after get request + \param hHal + \param callback_routine - HDD callback which needs to be invoked after + getting status notification from FW + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_link_layer_stats_ind_cb + (tHalHandle hHal, + void (*callback_routine)(void *callbackCtx, int indType, void *pRsp) + ) { + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + pMac->sme.pLinkLayerStatsIndCallback = callback_routine; + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "%s: " + "sme_acquire_global_lock error", __func__); + } + + return status; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +/** + * sme_fw_mem_dump_register_cb() - Register fw memory dump callback + * + * @hal - MAC global handle + * @callback_routine - callback routine from HDD + * + * This API is invoked by HDD to register its callback in SME + * + * Return: CDF_STATUS + */ +#ifdef WLAN_FEATURE_MEMDUMP +CDF_STATUS sme_fw_mem_dump_register_cb(tHalHandle hal, + void (*callback_routine)(void *cb_context, + struct fw_dump_rsp *rsp)) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + + status = sme_acquire_global_lock(&pmac->sme); + if (CDF_STATUS_SUCCESS == status) { + pmac->sme.fw_dump_callback = callback_routine; + sme_release_global_lock(&pmac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock error")); + } + + return status; +} +#else +CDF_STATUS sme_fw_mem_dump_register_cb(tHalHandle hal, + void (*callback_routine)(void *cb_context, + struct fw_dump_rsp *rsp)) +{ + return CDF_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: CDF_STATUS + */ +#ifdef WLAN_FEATURE_MEMDUMP +CDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hal) +{ + CDF_STATUS status; + tpAniSirGlobal pmac = PMAC_STRUCT(hal); + + status = sme_acquire_global_lock(&pmac->sme); + if (CDF_STATUS_SUCCESS == status) { + pmac->sme.fw_dump_callback = NULL; + sme_release_global_lock(&pmac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock error")); + } + + return status; +} +#else +CDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hal) +{ + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_update_roam_offload_enabled() - enable/disable roam offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + \param hHal - The handle returned by mac_open. + \param nRoamOffloadEnabled - The bool to update with + \return CDF_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_roam_offload_enabled(tHalHandle hHal, + bool nRoamOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: LFR3:gRoamOffloadEnabled is changed from %d to %d", + __func__, pMac->roam.configParam.isRoamOffloadEnabled, + nRoamOffloadEnabled); + pMac->roam.configParam.isRoamOffloadEnabled = + nRoamOffloadEnabled; + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_update_roam_key_mgmt_offload_enabled() - enable/disable key mgmt + offload + This is a synchronous call + \param hHal - The handle returned by mac_open. + \param sessionId - Session Identifier + \param nRoamKeyMgmtOffloadEnabled - The bool to update with + \return CDF_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +CDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hHal, + uint8_t sessionId, + bool nRoamKeyMgmtOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: LFR3: KeyMgmtOffloadEnabled changed to %d", + __func__, nRoamKeyMgmtOffloadEnabled); + status = csr_roam_set_key_mgmt_offload(pMac, + sessionId, + nRoamKeyMgmtOffloadEnabled); + } else { + status = CDF_STATUS_E_INVAL; + } + sme_release_global_lock(&pMac->sme); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_get_temperature + \brief SME API to get the pdev temperature + \param hHal + \param temperature context + \param pCallbackfn: callback fn with response (temperature) + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_get_temperature(tHalHandle hHal, + void *tempContext, + void (*pCallbackfn)(int temperature, + void *pContext)) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + if ((NULL == pCallbackfn) && + (NULL == pMac->sme.pGetTemperatureCb)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Indication Call back did not registered")); + sme_release_global_lock(&pMac->sme); + return CDF_STATUS_E_FAILURE; + } else if (NULL != pCallbackfn) { + pMac->sme.pTemperatureCbContext = tempContext; + pMac->sme.pGetTemperatureCb = pCallbackfn; + } + /* serialize the req through MC thread */ + cds_message.bodyptr = NULL; + cds_message.type = WMA_GET_TEMPERATURE_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Post Get Temperature msg fail")); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} + +/* --------------------------------------------------------------------------- + \fn sme_set_scanning_mac_oui + \brief SME API to set scanning mac oui + \param hHal + \param pScanMacOui: Scanning Mac Oui (input 3 bytes) + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_scanning_mac_oui(tHalHandle hHal, tSirScanMacOui *pScanMacOui) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = pScanMacOui; + cds_message.type = WMA_SET_SCAN_MAC_OUI_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Msg post Set Scan Mac OUI failed")); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } + return status; +} +#endif + +#ifdef DHCP_SERVER_OFFLOAD +/* --------------------------------------------------------------------------- + \fn sme_set_dhcp_srv_offload + \brief SME API to set DHCP server offload info + \param hHal + \param pDhcpSrvInfo : DHCP server offload info struct + \- return CDF_STATUS + -------------------------------------------------------------------------*/ +CDF_STATUS sme_set_dhcp_srv_offload(tHalHandle hHal, + tSirDhcpSrvOffloadInfo *pDhcpSrvInfo) +{ + cds_msg_t cds_message; + tSirDhcpSrvOffloadInfo *pSmeDhcpSrvInfo; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pSmeDhcpSrvInfo = cdf_mem_malloc(sizeof(*pSmeDhcpSrvInfo)); + + if (!pSmeDhcpSrvInfo) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WMA_SET_DHCP_SERVER_OFFLOAD_CMD", + __func__); + return CDF_STATUS_E_NOMEM; + } + + *pSmeDhcpSrvInfo = *pDhcpSrvInfo; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + cds_message.type = WMA_SET_DHCP_SERVER_OFFLOAD_CMD; + cds_message.bodyptr = pSmeDhcpSrvInfo; + + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_message))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post WMA_SET_DHCP_SERVER_OFFLOAD_CMD to WMA!", + __func__); + cdf_mem_free(pSmeDhcpSrvInfo); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: sme_acquire_global_lock error!", __func__); + cdf_mem_free(pSmeDhcpSrvInfo); + } + + return status; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +/* --------------------------------------------------------------------------- + \fn sme_set_led_flashing + \brief API to set the Led flashing parameters. + \param hHal - The handle returned by mac_open. + \param x0, x1 - led flashing parameters + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS sme_set_led_flashing(tHalHandle hHal, uint8_t type, + uint32_t x0, uint32_t x1) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t cds_message; + tSirLedFlashingReq *ledflashing; + + ledflashing = cdf_mem_malloc(sizeof(*ledflashing)); + if (!ledflashing) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Not able to allocate memory for WMA_LED_TIMING_REQ")); + return CDF_STATUS_E_NOMEM; + } + + ledflashing->pattern_id = type; + ledflashing->led_x0 = x0; + ledflashing->led_x1 = x1; + + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Serialize the req through MC thread */ + cds_message.bodyptr = ledflashing; + cds_message.type = WMA_LED_FLASHING_REQ; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + status = CDF_STATUS_E_FAILURE; + sme_release_global_lock(&pMac->sme); + } + return status; +} +#endif + +/** + * sme_handle_dfS_chan_scan() - handle DFS channel configuration + * @h_hal: corestack handler + * @dfs_flag: flag indicating dfs channel enable/disable + * Return: CDF_STATUS + */ +CDF_STATUS sme_handle_dfs_chan_scan(tHalHandle h_hal, uint8_t dfs_flag) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(h_hal); + + status = sme_acquire_global_lock(&mac->sme); + + if (CDF_STATUS_SUCCESS == status) { + + mac->scan.fEnableDFSChnlScan = dfs_flag; + + /* update the channel list to the firmware */ + status = csr_update_channel_list(mac); + + sme_release_global_lock(&mac->sme); + } + + return status; +} + + +/** + * sme_configure_stats_avg_factor() - function to config avg. stats factor + * @hal: hal + * @session_id: session ID + * @stats_avg_factor: average stats factor + * + * This function configures the stats avg factor in firmware + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_configure_stats_avg_factor(tHalHandle hal, uint8_t session_id, + uint16_t stats_avg_factor) +{ + cds_msg_t msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sir_stats_avg_factor *stats_factor; + + stats_factor = cdf_mem_malloc(sizeof(*stats_factor)); + + if (!stats_factor) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for SIR_HAL_CONFIG_STATS_FACTOR", + __func__); + return CDF_STATUS_E_NOMEM; + } + + status = sme_acquire_global_lock(&mac->sme); + + if (CDF_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 (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post SIR_HAL_CONFIG_STATS_FACTOR to WMA!", + __func__); + cdf_mem_free(stats_factor); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: sme_acquire_global_lock error!", + __func__); + cdf_mem_free(stats_factor); + } + + return status; +} + +/** + * sme_configure_guard_time() - function to configure guard time + * @hal: hal + * @session_id: session id + * @guard_time: guard time + * + * This function configures the guard time in firmware + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_configure_guard_time(tHalHandle hal, uint8_t session_id, + uint32_t guard_time) +{ + cds_msg_t msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + struct sir_guard_time_request *g_time; + + g_time = cdf_mem_malloc(sizeof(*g_time)); + + if (!g_time) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for SIR_HAL_CONFIG_GUARD_TIME", + __func__); + return CDF_STATUS_E_NOMEM; + } + + status = sme_acquire_global_lock(&mac->sme); + + if (CDF_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 (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post SIR_HAL_CONFIG_GUARD_TIME to WMA!", + __func__); + cdf_mem_free(g_time); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: sme_acquire_global_lock error!", + __func__); + cdf_mem_free(g_time); + } + + 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 modulated dtim in firmware + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_configure_modulated_dtim(tHalHandle h_hal, uint8_t session_id, + uint32_t modulated_dtim) +{ + cds_msg_t msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(h_hal); + wma_cli_set_cmd_t *iwcmd; + + iwcmd = cdf_mem_malloc(sizeof(*iwcmd)); + if (NULL == iwcmd) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_FATAL, + "%s: cdf_mem_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + status = sme_acquire_global_lock(&mac->sme); + + if (CDF_STATUS_SUCCESS == status) { + + cdf_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 = WMA_CLI_SET_CMD; + msg.reserved = 0; + msg.bodyptr = (void *)iwcmd; + + if (!CDF_IS_STATUS_SUCCESS( + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post GEN_PARAM_DYNAMIC_DTIM to WMA!", + __func__); + cdf_mem_free(iwcmd); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: sme_acquire_global_lock error!", + __func__); + cdf_mem_free(iwcmd); + } + + return status; +} + +/* + * sme_wifi_start_logger() - Send the start/stop logging command to WMA + * to either start/stop logging + * @hal: HAL context + * @start_log: Structure containing the wifi start logger params + * + * This function sends the start/stop logging command to WMA + * + * Return: CDF_STATUS_SUCCESS on successful posting + */ +CDF_STATUS sme_wifi_start_logger(tHalHandle hal, + struct sir_wifi_start_log start_log) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct sir_wifi_start_log *req_msg; + uint32_t len; + + len = sizeof(*req_msg); + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_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_acquire_global_lock(&mac->sme); + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = SIR_HAL_START_STOP_LOGGING; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + + return status; +} + +/** + * sme_neighbor_middle_of_roaming() - 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 + * csr_neighbor_middle_of_roaming to know STA is in the + * middle of roaming states + * + * Return: True or False + * + */ +bool sme_neighbor_middle_of_roaming(tHalHandle hHal, uint8_t sessionId) +{ + return csr_neighbor_middle_of_roaming(PMAC_STRUCT(hHal), sessionId); +} + +/* + * sme_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 + */ +CDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac) +{ + CDF_STATUS status; + cds_msg_t message; + + status = sme_acquire_global_lock(&mac->sme); + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + return status; + } + + /* Serialize the req through MC thread */ + message.bodyptr = NULL; + message.type = SIR_HAL_FLUSH_LOG_TO_FW; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_enable_uapsd_for_ac() - enable uapsd for access catagory requerst to WMA + * @cds_ctx: cds context + * @sta_id: station id + * @ac: access catagory + * @tid: tid value + * @pri: user priority + * @srvc_int: service interval + * @sus_int: suspend interval + * @dir: tspec direction + * @psb: PSB value + * @sessionId: session id + * @delay_interval: delay interval + * + * Return: CDF status + */ +CDF_STATUS sme_enable_uapsd_for_ac(void *cds_ctx, uint8_t sta_id, + sme_ac_enum_type ac, uint8_t tid, + uint8_t pri, uint32_t srvc_int, + uint32_t sus_int, + sme_tspec_dir_type dir, + uint8_t psb, uint32_t sessionId, + uint32_t delay_interval) +{ + void *wma_handle; + t_wma_trigger_uapsd_params uapsd_params; + enum uapsd_ac access_category; + + if (!psb) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "No need to configure auto trigger:psb is 0"); + return CDF_STATUS_SUCCESS; + } + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma_handle) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "wma_handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + + switch (ac) { + case SME_AC_BK: + access_category = UAPSD_BK; + break; + case SME_AC_BE: + access_category = UAPSD_BE; + break; + case SME_AC_VI: + access_category = UAPSD_VI; + break; + case SME_AC_VO: + access_category = UAPSD_VO; + break; + default: + return CDF_STATUS_E_FAILURE; + } + + uapsd_params.wmm_ac = access_category; + uapsd_params.user_priority = pri; + uapsd_params.service_interval = srvc_int; + uapsd_params.delay_interval = delay_interval; + uapsd_params.suspend_interval = sus_int; + + if (CDF_STATUS_SUCCESS != + wma_trigger_uapsd_params(wma_handle, sessionId, &uapsd_params)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to Trigger Uapsd params for sessionId %d", + sessionId); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_disable_uapsd_for_ac() - disable uapsed access catagory request to WMA + * @cds_ctx: cds context + * @sta_id: station id + * @ac: access catagory + * @sessionId: session id + * + * Return: CDF status + */ +CDF_STATUS sme_disable_uapsd_for_ac(void *cds_ctx, uint8_t sta_id, + sme_ac_enum_type ac, + uint32_t sessionId) +{ + void *wma_handle; + enum uapsd_ac access_category; + + switch (ac) { + case SME_AC_BK: + access_category = UAPSD_BK; + break; + case SME_AC_BE: + access_category = UAPSD_BE; + break; + case SME_AC_VI: + access_category = UAPSD_VI; + break; + case SME_AC_VO: + access_category = UAPSD_VO; + break; + default: + return CDF_STATUS_E_FAILURE; + } + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma_handle) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "wma handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + if (CDF_STATUS_SUCCESS != + wma_disable_uapsd_per_ac(wma_handle, sessionId, access_category)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to disable uapsd for ac %d for sessionId %d", + ac, sessionId); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_update_nss() - SME API to change the number for spatial streams + * (1 or 2) + * @hal: Handle returned by mac open + * @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 + * + */ +CDF_STATUS sme_update_nss(tHalHandle h_hal, uint8_t nss) +{ + CDF_STATUS 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_acquire_global_lock(&mac_ctx->sme); + + if (CDF_STATUS_SUCCESS == status) { + mac_ctx->roam.configParam.enable2x2 = (nss == 1) ? 0 : 1; + + /* get the HT capability info*/ + sme_cfg_get_int(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_release_global_lock(&mac_ctx->sme); + } + return status; +} + +/** + * 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: CDF_STATUS enumeration. + */ +CDF_STATUS sme_set_rssi_threshold_breached_cb(tHalHandle hal, + void (*cb)(void *, struct rssi_breach_event *)) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + return status; + } + + mac->sme.rssi_threshold_breached_cb = cb; + sme_release_global_lock(&mac->sme); + return status; +} + +/** + * sme_is_any_session_in_connected_state() - SME wrapper API to + * check if any session is in connected state or not. + * + * @hal: Handle returned by mac open + * + * This function is used to check if any valid sme session is in + * connected state or not. + * + * Return: true if any session is connected, else false. + * + */ +bool sme_is_any_session_in_connected_state(tHalHandle h_hal) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal); + CDF_STATUS status; + bool ret = false; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_STATUS_SUCCESS == status) { + ret = csr_is_any_session_in_connect_state(mac_ctx); + sme_release_global_lock(&mac_ctx->sme); + } + return ret; +} + +/** + * 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: CDF_STATUS enumeration + */ +CDF_STATUS sme_set_rssi_monitoring(tHalHandle hal, + struct rssi_monitor_req *input) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct rssi_monitor_req *req_msg; + + sms_log(mac, LOG1, FL("enter")); + req_msg = cdf_mem_malloc(sizeof(*req_msg)); + if (!req_msg) { + sms_log(mac, LOGE, FL("memory allocation failed")); + return CDF_STATUS_E_NOMEM; + } + + *req_msg = *input; + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("sme_acquire_global_lock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = WMA_SET_RSSI_MONITOR_REQ; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("cds_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + } + sme_release_global_lock(&mac->sme); + + return status; +} + +/** + * sme_fw_mem_dump() - Get FW memory dump + * @hHal: hal handle + * @recvd_req: received memory dump request. + * + * This API is invoked by HDD to indicate FW to start + * dumping firmware memory. + * + * Return: CDF_STATUS + */ +#ifdef WLAN_FEATURE_MEMDUMP +CDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + cds_msg_t msg; + struct fw_dump_req *send_req; + struct fw_dump_seg_req seg_req; + int loop; + + send_req = cdf_mem_malloc(sizeof(*send_req)); + if (!send_req) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failed for WDA_FW_MEM_DUMP")); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(send_req, recvd_req, sizeof(*send_req)); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("request_id:%d num_seg:%d"), + send_req->request_id, send_req->num_seg); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Segment Information")); + for (loop = 0; loop < send_req->num_seg; loop++) { + seg_req = send_req->segment[loop]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("seg_number:%d"), loop); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 (CDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) { + msg.bodyptr = send_req; + msg.type = WMA_FW_MEM_DUMP_REQ; + msg.reserved = 0; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &msg); + if (CDF_STATUS_SUCCESS != cdf_status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_FW_MEM_DUMP")); + cdf_mem_free(send_req); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&pMac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to acquire SME Global Lock")); + cdf_mem_free(send_req); + status = CDF_STATUS_E_FAILURE; + } + + return status; +} +#else +CDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req) +{ + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_MEMDUMP */ + +/* + * sme_soc_set_pcl() - Send WMI_SOC_SET_PCL_CMDID to the WMA + * @hal: Handle returned by macOpen + * @msg: PCL channel list and length structure + * + * Sends the command to WMA to send WMI_SOC_SET_PCL_CMDID to FW + * Return: CDF_STATUS_SUCCESS on successful posting + */ +CDF_STATUS sme_soc_set_pcl(tHalHandle hal, + struct sir_pcl_list msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + cds_msg_t cds_message; + struct sir_pcl_list *req_msg; + uint32_t len, i; + + len = sizeof(*req_msg); + + req_msg = cdf_mem_malloc(len); + if (!req_msg) { + sms_log(mac, LOGE, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(req_msg, len); + + for (i = 0; i < msg.pcl_len; i++) + req_msg->pcl_list[i] = msg.pcl_list[i]; + + req_msg->pcl_len = msg.pcl_len; + + status = sme_acquire_global_lock(&mac->sme); + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac, LOGE, + FL("sme_AcquireGlobalLock failed!(status=%d)"), + status); + cdf_mem_free(req_msg); + return status; + } + + /* Serialize the req through MC thread */ + cds_message.bodyptr = req_msg; + cds_message.type = SIR_HAL_SOC_SET_PCL_TO_FW; + status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, + FL("vos_mq_post_message failed!(err=%d)"), + status); + cdf_mem_free(req_msg); + status = CDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + + return status; +} + +/* + * sme_soc_set_hw_mode() - Send WMI_SOC_SET_HW_MODE_CMDID to the WMA + * @hal: Handle returned by macOpen + * @msg: HW mode structure containing hw mode and callback details + * + * Sends the command to CSR to send WMI_SOC_SET_HW_MODE_CMDID to FW + * Return: CDF_STATUS_SUCCESS on successful posting + */ +CDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, + struct sir_hw_mode msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tSmeCmd *cmd = NULL; + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, FL("Failed to acquire lock")); + return CDF_STATUS_E_RESOURCES; + } + + cmd = sme_get_command_buffer(mac); + if (!cmd) { + sms_log(mac, LOGE, FL("Get command buffer failed")); + sme_release_global_lock(&mac->sme); + return CDF_STATUS_E_NULL_VALUE; + } + + cmd->command = e_sme_command_set_hw_mode; + cmd->u.set_hw_mode_cmd.hw_mode_index = msg.hw_mode_index; + cmd->u.set_hw_mode_cmd.set_hw_mode_cb = msg.set_hw_mode_cb; + + sms_log(mac, LOG1, FL("Queuing e_sme_command_set_hw_mode to CSR")); + csr_queue_sme_command(mac, cmd, false); + + sme_release_global_lock(&mac->sme); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_register_hw_mode_trans_cb() - HW mode transition callback registration + * @hal: Handle returned by macOpen + * @callback: HDD callback to be registered + * + * Registers the HDD callback with SME. This callback will be invoked when + * HW mode transition event is received from the FW + * + * Return: None + */ +void sme_register_hw_mode_trans_cb(tHalHandle hal, + hw_mode_transition_cb callback) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + mac->sme.sme_hw_mode_trans_cb = callback; + sms_log(mac, LOG1, FL("HW mode transition callback registered")); +} + +/** + * sme_nss_update_request() - Send beacon templete update to FW with new + * nss value + * @hal: Handle returned by macOpen + * @vdev_id: the session id + * @new_nss: the new nss value + * @cback: hdd callback + * @next_action: next action to happen at policy mgr after beacon update + * + * Sends the command to CSR to send to PE + * Return: CDF_STATUS_SUCCESS on successful posting + */ +CDF_STATUS sme_nss_update_request(tHalHandle hHal, uint32_t vdev_id, + uint8_t new_nss, void *cback, uint8_t next_action, + void *hdd_context) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac = PMAC_STRUCT(hHal); + tSmeCmd *cmd = NULL; + + status = sme_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + cmd = sme_get_command_buffer(mac); + if (!cmd) { + sms_log(mac, LOGE, FL("Get command buffer failed")); + sme_release_global_lock(&mac->sme); + return CDF_STATUS_E_NULL_VALUE; + } + cmd->command = e_sme_command_nss_update; + /* Sessionized modules may require this info */ + cmd->sessionId = vdev_id; + cmd->u.nss_update_cmd.new_nss = new_nss; + cmd->u.nss_update_cmd.session_id = vdev_id; + cmd->u.nss_update_cmd.nss_update_cb = cback; + cmd->u.nss_update_cmd.context = hdd_context; + cmd->u.nss_update_cmd.next_action = next_action; + + sms_log(mac, LOG1, FL("Queuing e_sme_command_nss_update to CSR")); + csr_queue_sme_command(mac, cmd, false); + sme_release_global_lock(&mac->sme); + } + return status; +} + +/** + * sme_soc_set_dual_mac_config() - Set dual mac configurations + * @hal: Handle returned by macOpen + * @msg: Structure containing the dual mac config parameters + * + * Queues configuration information to CSR to configure + * WLAN firmware for the dual MAC features + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_soc_set_dual_mac_config(tHalHandle hal, + struct sir_dual_mac_config msg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tSmeCmd *cmd; + + status = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, FL("Failed to acquire lock")); + return CDF_STATUS_E_RESOURCES; + } + + cmd = sme_get_command_buffer(mac); + if (!cmd) { + sms_log(mac, LOGE, FL("Get command buffer failed")); + sme_release_global_lock(&mac->sme); + return CDF_STATUS_E_NULL_VALUE; + } + + cmd->command = e_sme_command_set_dual_mac_config; + cmd->u.set_dual_mac_cmd.scan_config = msg.scan_config; + cmd->u.set_dual_mac_cmd.fw_mode_config = msg.fw_mode_config; + cmd->u.set_dual_mac_cmd.set_dual_mac_cb = msg.set_dual_mac_cb; + + sms_log(mac, LOG1, + FL("Queuing e_sme_command_set_dual_mac_config to CSR: %x %x"), + cmd->u.set_dual_mac_cmd.scan_config, + cmd->u.set_dual_mac_cmd.fw_mode_config); + csr_queue_sme_command(mac, cmd, false); + + sme_release_global_lock(&mac->sme); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_set_peer_authorized() - call peer authorized callback + * @peer_addr: peer mac address + * @auth_cb: auth callback + * @vdev_id: vdev id + * + * Return: CDF Status + */ +CDF_STATUS sme_set_peer_authorized(uint8_t *peer_addr, + sme_peer_authorized_fp auth_cb, + uint32_t vdev_id) +{ + void *wma_handle; + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma_handle) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "wma handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + + wma_set_peer_authorized_cb(wma_handle, auth_cb); + return wma_set_peer_param(wma_handle, peer_addr, WMI_PEER_AUTHORIZE, + 1, vdev_id); +} + +/* + * sme_disable_non_fcc_channel() - non-fcc channel disable request + * @hal: HAL pointer + * @fcc_constraint: true: disable, false; enable + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_disable_non_fcc_channel(tHalHandle hal, bool fcc_constraint) +{ + CDF_STATUS status; + tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal); + + status = sme_acquire_global_lock(&mac_ptr->sme); + + if (CDF_STATUS_SUCCESS == status) { + + if (fcc_constraint != mac_ptr->scan.fcc_constraint) { + mac_ptr->scan.fcc_constraint = fcc_constraint; + + /* update the channel list in firmware */ + status = csr_update_channel_list(mac_ptr); + } + + sme_release_global_lock(&mac_ptr->sme); + } + + return status; +} +/** + * sme_setdef_dot11mode() - Updates pMac with default dot11mode + * @hal: Global MAC pointer + * + * Return: NULL. + */ +void sme_setdef_dot11mode(tHalHandle hal) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + csr_set_default_dot11_mode(mac_ctx); +} + +/** + * 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: CDF_STATUS - SME update config successful. + * Other status means SME failed to update + */ + +CDF_STATUS 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); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamConfig *nr_config = NULL; + tpCsrNeighborRoamControlInfo nr_info = NULL; + uint32_t reason = 0; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (CDF_IS_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: gRoamScanHirssiMaxCount %d => %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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("gRoamScanHiRssiDelta %d => %d"), + 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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("gRoamScanHiRssiDelay %d => %d"), + 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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("gRoamScanHiRssiUpperBound %d => %d"), + 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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("invalid parameter notify_id %d"), + notify_id); + status = CDF_STATUS_E_INVAL; + break; + } + sme_release_global_lock(&mac_ctx->sme); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled && + status == CDF_STATUS_SUCCESS) { + csr_roam_offload_scan(mac_ctx, session_id, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason); + } +#endif + + return status; +} + diff --git a/core/sme/src/common/sme_ft_api.c b/core/sme/src/common/sme_ft_api.c new file mode 100644 index 000000000000..b48e13f10cb3 --- /dev/null +++ b/core/sme/src/common/sme_ft_api.c @@ -0,0 +1,634 @@ +/* + * 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 Definitions for SME FT APIs + + ========================================================================*/ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include +#include + +/*-------------------------------------------------------------------------- + Initialize the FT context. + ------------------------------------------------------------------------*/ +void sme_ft_open(tHalHandle hHal, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL != pSession) { + /* Clean up the context */ + cdf_mem_set(&pSession->ftSmeContext, sizeof(tftSMEContext), 0); + + pSession->ftSmeContext.pUsrCtx = + cdf_mem_malloc(sizeof(tFTRoamCallbackUsrCtx)); + + if (NULL == pSession->ftSmeContext.pUsrCtx) { + sms_log(pMac, LOGE, FL("Memory allocation failure")); + return; + } + pSession->ftSmeContext.pUsrCtx->pMac = pMac; + pSession->ftSmeContext.pUsrCtx->sessionId = sessionId; + + status = + cdf_mc_timer_init(&pSession->ftSmeContext. + preAuthReassocIntvlTimer, + CDF_TIMER_TYPE_SW, + sme_preauth_reassoc_intvl_timer_callback, + (void *)pSession->ftSmeContext.pUsrCtx); + + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, + FL + ("Preauth Reassoc interval Timer allocation failed")); + cdf_mem_free(pSession->ftSmeContext.pUsrCtx); + pSession->ftSmeContext.pUsrCtx = NULL; + return; + } + } +} + +/*-------------------------------------------------------------------------- + Cleanup the SME FT Global context. + ------------------------------------------------------------------------*/ +void sme_ft_close(tHalHandle hHal, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = NULL; + + /* Clear the FT Context */ + sme_ft_reset(hHal, sessionId); + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL != pSession) { + /* check if the timer is running */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&pSession->ftSmeContext. + preAuthReassocIntvlTimer)) { + cdf_mc_timer_stop(&pSession->ftSmeContext. + preAuthReassocIntvlTimer); + } + + if (CDF_STATUS_SUCCESS != + cdf_mc_timer_destroy(&pSession->ftSmeContext. + preAuthReassocIntvlTimer)) { + sms_log(pMac, LOGE, + FL("preAuthReAssocTimer destroy failed")); + } + + if (pSession->ftSmeContext.pUsrCtx != NULL) { + sms_log(pMac, LOG1, + FL + ("Freeing ftSmeContext.pUsrCtx and setting to NULL")); + cdf_mem_free(pSession->ftSmeContext.pUsrCtx); + pSession->ftSmeContext.pUsrCtx = NULL; + } + } +} + +void sme_set_ft_pre_auth_state(tHalHandle hHal, uint32_t sessionId, bool state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (pSession) + pSession->ftSmeContext.setFTPreAuthState = state; +} + +bool sme_get_ft_pre_auth_state(tHalHandle hHal, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (pSession) + return pSession->ftSmeContext.setFTPreAuthState; + + return false; +} + +/** + * sme_set_ft_ies() - to set FT IEs + * @hal_ptr: pointer to HAL + * @session_id: sme session id + * @ft_ies: pointer to FT IEs + * @ft_ies_length: length of FT IEs + * + * Each time the supplicant sends down the FT IEs to the driver. This function + * is called in SME. This fucntion packages and sends the FT IEs to PE. + * + * Return: none + */ +void sme_set_ft_ies(tHalHandle hal_ptr, uint32_t session_id, + const uint8_t *ft_ies, uint16_t ft_ies_length) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ptr); + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (NULL == session || NULL == ft_ies) { + sms_log(mac_ctx, LOGE, FL(" ft ies or session is NULL")); + return; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!(CDF_IS_STATUS_SUCCESS(status))) + return; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(mac_ctx, LOG1, "FT IEs Req is received in state %d", + session->ftSmeContext.FTState); +#endif + + /* Global Station FT State */ + switch (session->ftSmeContext.FTState) { + case eFT_START_READY: + case eFT_AUTH_REQ_READY: + if ((session->ftSmeContext.auth_ft_ies) && + (session->ftSmeContext.auth_ft_ies_length)) { + /* Free the one we recvd last from supplicant */ + cdf_mem_free(session->ftSmeContext.auth_ft_ies); + session->ftSmeContext.auth_ft_ies_length = 0; + session->ftSmeContext.auth_ft_ies = NULL; + } + /* Save the FT IEs */ + session->ftSmeContext.auth_ft_ies = + cdf_mem_malloc(ft_ies_length); + if (NULL == session->ftSmeContext.auth_ft_ies) { + sms_log(mac_ctx, LOGE, + FL("Mem alloc failed for auth_ft_ies")); + sme_release_global_lock(&mac_ctx->sme); + return; + } + session->ftSmeContext.auth_ft_ies_length = ft_ies_length; + cdf_mem_copy((uint8_t *)session->ftSmeContext.auth_ft_ies, + ft_ies, ft_ies_length); + session->ftSmeContext.FTState = eFT_AUTH_REQ_READY; + +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(mac_ctx, LOG1, + FL("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 + */ +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(mac_ctx, LOG1, + FL("Preauth done & rcving AUTHREQ in state %d"), + session->ftSmeContext.FTState); + sms_log(mac_ctx, LOG1, + FL("Unhandled reception of FT IES in state %d"), + session->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'r ready to start sending Reassoc req + */ +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(mac_ctx, LOG1, FL("New Reassoc Req=%p in state %d"), + ft_ies, session->ftSmeContext.FTState); +#endif + if ((session->ftSmeContext.reassoc_ft_ies) && + (session->ftSmeContext.reassoc_ft_ies_length)) { + /* Free the one we recvd last from supplicant */ + cdf_mem_free(session->ftSmeContext.reassoc_ft_ies); + session->ftSmeContext.reassoc_ft_ies_length = 0; + } + /* Save the FT IEs */ + session->ftSmeContext.reassoc_ft_ies = + cdf_mem_malloc(ft_ies_length); + if (NULL == session->ftSmeContext.reassoc_ft_ies) { + sms_log(mac_ctx, LOGE, + FL("Mem alloc fail for reassoc_ft_ie")); + sme_release_global_lock(&mac_ctx->sme); + return; + } + session->ftSmeContext.reassoc_ft_ies_length = + ft_ies_length; + cdf_mem_copy((uint8_t *)session->ftSmeContext.reassoc_ft_ies, + ft_ies, ft_ies_length); + + session->ftSmeContext.FTState = eFT_SET_KEY_WAIT; +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(mac_ctx, LOG1, + FL("ft_ies_length=%d state=%d"), ft_ies_length, + session->ftSmeContext.FTState); +#endif + + break; + + default: + sms_log(mac_ctx, LOGE, FL("Unhandled state=%d"), + session->ftSmeContext.FTState); + break; + } + sme_release_global_lock(&mac_ctx->sme); +} + +/** + * sme_ft_send_update_key_ind() - To send key update indication for FT session + * @hal: pointer to HAL + * @session_id: sme session id + * @ftkey_info: FT key information + * + * To send key update indication for FT session + * + * Return: CDF_STATUS + */ +static +CDF_STATUS sme_ft_send_update_key_ind(tHalHandle hal, uint32_t session_id, + tCsrRoamSetKey *ftkey_info) +{ + tSirFTUpdateKeyInfo *msg; + uint16_t msglen; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tSirKeyMaterial *keymaterial = NULL; + tAniEdType ed_type; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + int i = 0; + + sms_log(mac_ctx, LOG1, FL("keyLength %d"), ftkey_info->keyLength); + for (i = 0; i < ftkey_info->keyLength; i++) + sms_log(mac_ctx, LOG1, FL("%02x"), ftkey_info->Key[i]); +#endif + + if (ftkey_info->keyLength > CSR_MAX_KEY_LEN) { + sms_log(mac_ctx, LOGE, FL("invalid keyLength %d"), + ftkey_info->keyLength); + return CDF_STATUS_E_FAILURE; + } + msglen = sizeof(tSirFTUpdateKeyInfo); + + msg = cdf_mem_malloc(msglen); + if (NULL == msg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(msg, msglen, 0); + msg->messageType = eWNI_SME_FT_UPDATE_KEY; + msg->length = msglen; + + keymaterial = &msg->keyMaterial; + keymaterial->length = ftkey_info->keyLength; + ed_type = csr_translate_encrypt_type_to_ed_type(ftkey_info->encType); + keymaterial->edType = ed_type; + keymaterial->numKeys = 1; + keymaterial->key[0].keyId = ftkey_info->keyId; + keymaterial->key[0].unicast = (uint8_t) true; + keymaterial->key[0].keyDirection = ftkey_info->keyDirection; + + cdf_mem_copy(&keymaterial->key[0].keyRsc, + ftkey_info->keyRsc, CSR_MAX_RSC_LEN); + keymaterial->key[0].paeRole = ftkey_info->paeRole; + keymaterial->key[0].keyLength = ftkey_info->keyLength; + + if (ftkey_info->keyLength && ftkey_info->Key) { + cdf_mem_copy(&keymaterial->key[0].key, ftkey_info->Key, + ftkey_info->keyLength); + if (ftkey_info->keyLength == 16) { + sms_log(mac_ctx, LOG1, + FL("set update ind keyidx(%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"), + msg->keyMaterial.key[0].keyId, + (tAniEdType) msg->keyMaterial.edType, + msg->keyMaterial.key[0].key[0], + msg->keyMaterial.key[0].key[1], + msg->keyMaterial.key[0].key[2], + msg->keyMaterial.key[0].key[3], + msg->keyMaterial.key[0].key[4], + msg->keyMaterial.key[0].key[5], + msg->keyMaterial.key[0].key[6], + msg->keyMaterial.key[0].key[7], + msg->keyMaterial.key[0].key[8], + msg->keyMaterial.key[0].key[9], + msg->keyMaterial.key[0].key[10], + msg->keyMaterial.key[0].key[11], + msg->keyMaterial.key[0].key[12], + msg->keyMaterial.key[0].key[13], + msg->keyMaterial.key[0].key[14], + msg->keyMaterial.key[0].key[15]); + } + } + + cdf_mem_copy(&msg->bssId[0], + &ftkey_info->peerMac.bytes[0], CDF_MAC_ADDR_SIZE); + msg->smeSessionId = session_id; + sms_log(mac_ctx, LOG1, "BSSID = " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(msg->bssId)); + status = cds_send_mb_message_to_mac(msg); + + return status; +} + +bool sme_get_ftptk_state(tHalHandle hHal, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return false; + } + return pSession->ftSmeContext.setFTPTKState; +} + +void sme_set_ftptk_state(tHalHandle hHal, uint32_t sessionId, bool state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return; + } + pSession->ftSmeContext.setFTPTKState = state; +} + +CDF_STATUS sme_ft_update_key(tHalHandle hHal, uint32_t sessionId, + tCsrRoamSetKey *pFTKeyInfo) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (!pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (pFTKeyInfo == NULL) { + sms_log(pMac, LOGE, "%s: pFTKeyInfo is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + status = sme_acquire_global_lock(&pMac->sme); + if (!(CDF_IS_STATUS_SUCCESS(status))) { + return CDF_STATUS_E_FAILURE; + } +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(pMac, LOG1, "sme_ft_update_key is received in state %d", + pSession->ftSmeContext.FTState); +#endif + + /* Global Station FT State */ + switch (pSession->ftSmeContext.FTState) { + case eFT_SET_KEY_WAIT: + if (sme_get_ft_pre_auth_state(hHal, sessionId) == true) { + status = + sme_ft_send_update_key_ind(pMac, sessionId, pFTKeyInfo); + if (status != 0) { + sms_log(pMac, LOGE, "%s: Key set failure %d", + __func__, status); + pSession->ftSmeContext.setFTPTKState = false; + status = CDF_STATUS_FT_PREAUTH_KEY_FAILED; + } else { + pSession->ftSmeContext.setFTPTKState = true; + status = CDF_STATUS_FT_PREAUTH_KEY_SUCCESS; + sms_log(pMac, LOG1, "%s: Key set success", + __func__); + } + sme_set_ft_pre_auth_state(hHal, sessionId, false); + } + + pSession->ftSmeContext.FTState = eFT_START_READY; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(pMac, LOG1, "%s: state changed to %d status %d", + __func__, pSession->ftSmeContext.FTState, status); +#endif + break; + + default: + sms_log(pMac, LOGW, "%s: Unhandled state=%d", __func__, + pSession->ftSmeContext.FTState); + status = CDF_STATUS_E_FAILURE; + break; + } + sme_release_global_lock(&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_get_ft_pre_auth_response(tHalHandle hHal, uint32_t sessionId, + uint8_t *ft_ies, uint32_t ft_ies_ip_len, + uint16_t *ft_ies_length) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (!pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return; + } + + *ft_ies_length = 0; + + status = sme_acquire_global_lock(&pMac->sme); + if (!(CDF_IS_STATUS_SUCCESS(status))) + return; + + /* All or nothing - proceed only if both BSSID and FT IE fit */ + if ((CDF_MAC_ADDR_SIZE + + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length) > + ft_ies_ip_len) { + sme_release_global_lock(&pMac->sme); + return; + } + /* hdd needs to pack the bssid also along with the */ + /* auth response to supplicant */ + cdf_mem_copy(ft_ies, pSession->ftSmeContext.preAuthbssId, + CDF_MAC_ADDR_SIZE); + + /* Copy the auth resp FTIEs */ + cdf_mem_copy(&(ft_ies[CDF_MAC_ADDR_SIZE]), + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies, + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length); + + *ft_ies_length = CDF_MAC_ADDR_SIZE + + pSession->ftSmeContext.psavedFTPreAuthRsp->ft_ies_length; + + pSession->ftSmeContext.FTState = eFT_REASSOC_REQ_WAIT; + +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + sms_log(pMac, LOG1, FL(" Filled auth resp = %d"), *ft_ies_length); +#endif + sme_release_global_lock(&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_get_rici_es(tHalHandle hHal, uint32_t sessionId, uint8_t *ric_ies, + uint32_t ric_ies_ip_len, uint32_t *ric_ies_length) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (!pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return; + } + + *ric_ies_length = 0; + + status = sme_acquire_global_lock(&pMac->sme); + if (!(CDF_IS_STATUS_SUCCESS(status))) + return; + + /* All or nothing */ + if (pSession->ftSmeContext.psavedFTPreAuthRsp->ric_ies_length > + ric_ies_ip_len) { + sme_release_global_lock(&pMac->sme); + return; + } + + cdf_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 + sms_log(pMac, LOG1, FL(" Filled ric ies = %d"), *ric_ies_length); +#endif + + sme_release_global_lock(&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_preauth_reassoc_intvl_timer_callback(void *context) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *) context; + + if (pUsrCtx) { + csr_neighbor_roam_request_handoff(pUsrCtx->pMac, + pUsrCtx->sessionId); + } +#endif + return; +} + +/*-------------------------------------------------------------------------- + Reset the FT context. + ------------------------------------------------------------------------*/ +void sme_ft_reset(tHalHandle hHal, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = NULL; + + if (pMac == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 + sms_log(pMac, LOG1, + FL("Freeing FT Auth IE %p and setting to NULL"), + pSession->ftSmeContext.auth_ft_ies); +#endif + cdf_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 + sms_log(pMac, LOG1, + FL + ("Freeing FT Reassoc IE %p and setting to NULL"), + pSession->ftSmeContext.reassoc_ft_ies); +#endif + cdf_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 + sms_log(pMac, LOG1, + FL + ("Freeing FtPreAuthRsp %p and setting to NULL"), + pSession->ftSmeContext.psavedFTPreAuthRsp); +#endif + cdf_mem_free(pSession->ftSmeContext.psavedFTPreAuthRsp); + pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; + } + pSession->ftSmeContext.setFTPreAuthState = false; + pSession->ftSmeContext.setFTPTKState = false; + + cdf_mem_zero(pSession->ftSmeContext.preAuthbssId, + CDF_MAC_ADDR_SIZE); + pSession->ftSmeContext.FTState = eFT_START_READY; + } +} + +/* End of File */ +#endif /* WLAN_FEATURE_VOWIFI_11R */ diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c new file mode 100644 index 000000000000..a08ce2bdb4ec --- /dev/null +++ b/core/sme/src/common/sme_power_save.c @@ -0,0 +1,1214 @@ +/* + * 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. + */ + +#include "sme_power_save.h" +#include "sme_power_save_api.h" +#include "sms_debug.h" +#include "cdf_memory.h" +#include "cdf_types.h" +#include "wma_types.h" +#include "wmm_apsd.h" +#include "cfg_api.h" +#include "csr_inside_api.h" + +/** + * sme_post_ps_msg_to_wma(): post message to WMA. + * @type: type + * @body: body pointer + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_post_ps_msg_to_wma(uint16_t type, void *body) +{ + cds_msg_t msg; + + msg.type = type; + msg.reserved = 0; + msg.bodyptr = body; + msg.bodyval = 0; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message( + CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Posting message %d failed", + __func__, type); + cdf_mem_free(body); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_ps_enable_ps_req_params(): enables power save req params + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_enable_ps_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + struct sEnablePsParams *enable_ps_req_params; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + enable_ps_req_params = cdf_mem_malloc(sizeof(*enable_ps_req_params)); + if (NULL == enable_ps_req_params) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed for enable_ps_req_params")); + return CDF_STATUS_E_NOMEM; + } + enable_ps_req_params->psSetting = eSIR_ADDON_NOTHING; + enable_ps_req_params->sessionid = session_id; + + status = sme_post_ps_msg_to_wma(WMA_ENTER_PS_REQ, enable_ps_req_params); + if (!CDF_IS_STATUS_SUCCESS(status)) + return CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Message WMA_ENTER_PS_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_ps_disable_ps_req_params(): Disable power save req params + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_disable_ps_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + struct sDisablePsParams *disable_ps_req_params; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + disable_ps_req_params = cdf_mem_malloc(sizeof(*disable_ps_req_params)); + if (NULL == disable_ps_req_params) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed for sDisablePsParams")); + return CDF_STATUS_E_NOMEM; + } + + disable_ps_req_params->psSetting = eSIR_ADDON_NOTHING; + disable_ps_req_params->sessionid = session_id; + + status = sme_post_ps_msg_to_wma(WMA_EXIT_PS_REQ, disable_ps_req_params); + if (!CDF_IS_STATUS_SUCCESS(status)) + return CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Message WMA_EXIT_PS_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_ps_enable_uapsd_req_params(): enables UASPD req params + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_enable_uapsd_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + + struct sEnableUapsdParams *enable_uapsd_req_params; + uint8_t uapsd_delivery_mask = 0; + uint8_t uapsd_trigger_mask = 0; + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + enable_uapsd_req_params = + cdf_mem_malloc(sizeof(*enable_uapsd_req_params)); + if (NULL == enable_uapsd_req_params) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed for enable_uapsd_req_params")); + return CDF_STATUS_E_NOMEM; + } + + + uapsd_delivery_mask = + ps_param->uapsd_per_ac_bit_mask | + ps_param->uapsd_per_ac_delivery_enable_mask; + + uapsd_trigger_mask = + ps_param->uapsd_per_ac_bit_mask | + ps_param->uapsd_per_ac_trigger_enable_mask; + + + enable_uapsd_req_params->uapsdParams.bkDeliveryEnabled = + LIM_UAPSD_GET(ACBK, uapsd_delivery_mask); + + enable_uapsd_req_params->uapsdParams.beDeliveryEnabled = + LIM_UAPSD_GET(ACBE, uapsd_delivery_mask); + + enable_uapsd_req_params->uapsdParams.viDeliveryEnabled = + LIM_UAPSD_GET(ACVI, uapsd_delivery_mask); + + enable_uapsd_req_params->uapsdParams.voDeliveryEnabled = + LIM_UAPSD_GET(ACVO, uapsd_delivery_mask); + + enable_uapsd_req_params->uapsdParams.bkTriggerEnabled = + LIM_UAPSD_GET(ACBK, uapsd_trigger_mask); + + enable_uapsd_req_params->uapsdParams.beTriggerEnabled = + LIM_UAPSD_GET(ACBE, uapsd_trigger_mask); + + enable_uapsd_req_params->uapsdParams.viTriggerEnabled = + LIM_UAPSD_GET(ACVI, uapsd_trigger_mask); + + enable_uapsd_req_params->uapsdParams.voTriggerEnabled = + LIM_UAPSD_GET(ACVO, uapsd_trigger_mask); + + enable_uapsd_req_params->sessionid = session_id; + + status = sme_post_ps_msg_to_wma(WMA_ENABLE_UAPSD_REQ, + enable_uapsd_req_params); + if (!CDF_IS_STATUS_SUCCESS(status)) + return CDF_STATUS_E_FAILURE; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Msg WMA_ENABLE_UAPSD_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_ps_disable_uapsd_req_params(): disables UASPD req params + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_disable_uapsd_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + struct sDisableUapsdParams *disable_uapsd_req_params; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + disable_uapsd_req_params = + cdf_mem_malloc(sizeof(*disable_uapsd_req_params)); + if (NULL == disable_uapsd_req_params) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed for disable_uapsd_req_params")); + return CDF_STATUS_E_NOMEM; + } + + disable_uapsd_req_params->sessionid = session_id; + status = sme_post_ps_msg_to_wma(WMA_DISABLE_UAPSD_REQ, + disable_uapsd_req_params); + if (!CDF_IS_STATUS_SUCCESS(status)) + return CDF_STATUS_E_FAILURE; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Message WMA_DISABLE_UAPSD_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_ps_enter_wowl_req_params(): enable WOWL req Parama + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_enter_wowl_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + struct sSirHalWowlEnterParams *hal_wowl_params; + struct sSirSmeWowlEnterParams *sme_wowl_params; + uint32_t cfg_value = 0; + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + + sme_wowl_params = + &ps_global_info->ps_params[session_id].wowl_enter_params; + + hal_wowl_params = cdf_mem_malloc(sizeof(*hal_wowl_params)); + if (NULL == hal_wowl_params) { + sms_log(mac_ctx, LOGP, + FL("Fail to allocate memory for Enter Wowl Request ")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set((uint8_t *) hal_wowl_params, sizeof(*hal_wowl_params), 0); + + /* fill in the message field */ + hal_wowl_params->ucMagicPktEnable = sme_wowl_params->ucMagicPktEnable; + hal_wowl_params->ucPatternFilteringEnable = + sme_wowl_params->ucPatternFilteringEnable; + cdf_mem_copy((uint8_t *) hal_wowl_params->magicPtrn, + (uint8_t *) sme_wowl_params->magicPtrn, + sizeof(tSirMacAddr)); + +#ifdef WLAN_WAKEUP_EVENTS + hal_wowl_params->ucWoWEAPIDRequestEnable = + sme_wowl_params->ucWoWEAPIDRequestEnable; + hal_wowl_params->ucWoWEAPOL4WayEnable = + sme_wowl_params->ucWoWEAPOL4WayEnable; + hal_wowl_params->ucWowNetScanOffloadMatch = + sme_wowl_params->ucWowNetScanOffloadMatch; + hal_wowl_params->ucWowGTKRekeyError = + sme_wowl_params->ucWowGTKRekeyError; + hal_wowl_params->ucWoWBSSConnLoss = + sme_wowl_params->ucWoWBSSConnLoss; +#endif /* WLAN_WAKEUP_EVENTS */ + + if (wlan_cfg_get_int + (mac_ctx, WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE, + &cfg_value) != eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE")); + goto end; + } + hal_wowl_params->ucUcastPatternFilteringEnable = (uint8_t) cfg_value; + + if (wlan_cfg_get_int + (mac_ctx, WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE, + &cfg_value) != eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE")); + goto end; + } + hal_wowl_params->ucWowChnlSwitchRcv = (uint8_t) cfg_value; + + if (wlan_cfg_get_int + (mac_ctx, WNI_CFG_WOWLAN_DEAUTH_ENABLE, &cfg_value) != + eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_DEAUTH_ENABLE ")); + goto end; + } + hal_wowl_params->ucWowDeauthRcv = (uint8_t) cfg_value; + + if (wlan_cfg_get_int + (mac_ctx, WNI_CFG_WOWLAN_DISASSOC_ENABLE, &cfg_value) != + eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_DISASSOC_ENABLE ")); + goto end; + } + hal_wowl_params->ucWowDisassocRcv = (uint8_t) cfg_value; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_WOWLAN_MAX_MISSED_BEACON, + &cfg_value) != eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_MISSED_BEACON ")); + goto end; + } + hal_wowl_params->ucWowMaxMissedBeacons = (uint8_t) cfg_value; + + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD, + &cfg_value) != eSIR_SUCCESS) { + sms_log(mac_ctx, LOGP, + FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD ")); + goto end; + } + hal_wowl_params->ucWowMaxSleepUsec = (uint8_t) cfg_value; + + hal_wowl_params->sessionId = sme_wowl_params->sessionId; + + if (CDF_STATUS_SUCCESS == sme_post_ps_msg_to_wma(WMA_WOWL_ENTER_REQ, + hal_wowl_params)){ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Msg WMA_WOWL_ENTER_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; + } else + goto end; + +end: + if (hal_wowl_params != NULL) + cdf_mem_free(hal_wowl_params); + return CDF_STATUS_E_FAILURE; +} + +/** + * sme_ps_exit_wowl_req_params(): Exit WOWL req params + * @mac_ctx: global mac context + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_exit_wowl_req_params(tpAniSirGlobal mac_ctx, + uint32_t session_id) +{ + struct sSirHalWowlExitParams *hal_wowl_msg; + hal_wowl_msg = cdf_mem_malloc(sizeof(*hal_wowl_msg)); + if (NULL == hal_wowl_msg) { + sms_log(mac_ctx, LOGP, + FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set((uint8_t *) hal_wowl_msg, + sizeof(*hal_wowl_msg), 0); + hal_wowl_msg->sessionId = session_id; + + if (CDF_STATUS_SUCCESS == sme_post_ps_msg_to_wma(WMA_WOWL_EXIT_REQ, + hal_wowl_msg)){ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Msg WMA_WOWL_EXIT_REQ Successfully sent to WMA")); + return CDF_STATUS_SUCCESS; + } + if (hal_wowl_msg != NULL) + cdf_mem_free(hal_wowl_msg); + return CDF_STATUS_E_FAILURE; +} + +/** + * sme_ps_process_command(): Sme process power save messages + * and pass messages to WMA. + * @mac_ctx: global mac context + * @session_id: session id + * sme_ps_cmd: power save message + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_process_command(tpAniSirGlobal mac_ctx, uint32_t session_id, + enum sme_ps_cmd command) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) { + sms_log(mac_ctx, LOGE, "Invalid Session_id %x", session_id); + return eSIR_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Power Save command %d"), command); + switch (command) { + case SME_PS_ENABLE: + status = sme_ps_enable_ps_req_params(mac_ctx, session_id); + break; + case SME_PS_DISABLE: + status = sme_ps_disable_ps_req_params(mac_ctx, session_id); + break; + case SME_PS_UAPSD_ENABLE: + status = sme_ps_enable_uapsd_req_params(mac_ctx, session_id); + break; + case SME_PS_UAPSD_DISABLE: + status = sme_ps_disable_uapsd_req_params(mac_ctx, session_id); + break; + case SME_PS_WOWL_ENTER: + status = sme_ps_enter_wowl_req_params(mac_ctx, session_id); + break; + case SME_PS_WOWL_EXIT: + status = sme_ps_exit_wowl_req_params(mac_ctx, session_id); + break; + + default: + sms_log(mac_ctx, LOGE, FL("Invalid command type %d"), + command); + status = CDF_STATUS_E_FAILURE; + break; + } + if (status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to enter in PS, Command: %d"), command); + } + return status; +} + +/** + * sme_enable_sta_ps_check(): Checks if it is ok to enable power save or not. + * @mac_ctx: global mac context + * @session_id: session id + * + *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. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_enable_sta_ps_check(tpAniSirGlobal mac_ctx, uint32_t session_id) +{ + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + + /* Check if Sta Ps is enabled. */ + if (!ps_global_info->ps_enabled) { + sms_log(mac_ctx, LOG1, + "Cannot initiate PS. PS is disabled in ini"); + return CDF_STATUS_E_FAILURE; + } + + /* Check whether the given session is Infra and in Connected State */ + if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) { + sms_log(mac_ctx, LOGE, "Sta not infra/connected state %d", + session_id); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; + +} + +/** + * sme_ps_enable_disable(): function to enable/disable PS. + * @hal_ctx: global hal_handle + * @session_id: session id + * sme_ps_cmd: power save message + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_enable_disable(tHalHandle hal_ctx, uint32_t session_id, + enum sme_ps_cmd command) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + status = sme_enable_sta_ps_check(mac_ctx, session_id); + if (status != CDF_STATUS_SUCCESS) + return status; + status = sme_ps_process_command(mac_ctx, session_id, command); + return status; +} + +/** + * sme_ps_uapsd_enable(): function to enable UAPSD. + * @hal_ctx: global hal_handle + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_uapsd_enable(tHalHandle hal_ctx, uint32_t session_id) +{ + + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + status = sme_enable_sta_ps_check(mac_ctx, session_id); + if (status != CDF_STATUS_SUCCESS) + return status; + status = sme_ps_process_command(mac_ctx, session_id, + SME_PS_UAPSD_ENABLE); + if (status == CDF_STATUS_SUCCESS) + sme_offload_qos_process_into_uapsd_mode(mac_ctx, session_id); + + return status; +} + +/** + * sme_ps_uapsd_disable(): function to disable UAPSD. + * @hal_ctx: global hal_handle + * @session_id: session id + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_uapsd_disable(tHalHandle hal_ctx, uint32_t session_id) +{ + + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + status = sme_enable_sta_ps_check(mac_ctx, session_id); + if (status != CDF_STATUS_SUCCESS) + return status; + status = sme_ps_process_command(mac_ctx, session_id, + SME_PS_UAPSD_DISABLE); + if (status == CDF_STATUS_SUCCESS) + sme_offload_qos_process_out_of_uapsd_mode(mac_ctx, session_id); + + return status; +} + +/** + * sme_set_tspec_uapsd_mask_per_session(): set tspec UAPSD mask per session + * @mac_ctx: global mac context + * @ts_info: tspec info. + * @session_id: session id + * + * Return: CDF_STATUS + */ +void sme_set_tspec_uapsd_mask_per_session(tpAniSirGlobal mac_ctx, + tSirMacTSInfo *ts_info, + uint8_t session_id) +{ + uint8_t user_prio = (uint8_t) ts_info->traffic.userPrio; + uint16_t direction = ts_info->traffic.direction; + uint8_t ac = upToAc(user_prio); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + sms_log(mac_ctx, LOGE, FL("Set UAPSD mask for AC %d, dir %d, action=%d") + , ac, direction, ts_info->traffic.psb); + + /* 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 (ts_info->traffic.psb) { + if (direction == SIR_MAC_DIRECTION_UPLINK) + ps_param->uapsd_per_ac_trigger_enable_mask |= + (1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + ps_param->uapsd_per_ac_delivery_enable_mask |= + (1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) { + ps_param->uapsd_per_ac_trigger_enable_mask |= + (1 << ac); + ps_param->uapsd_per_ac_delivery_enable_mask |= + (1 << ac); + } + } else { + if (direction == SIR_MAC_DIRECTION_UPLINK) + ps_param->uapsd_per_ac_trigger_enable_mask &= + ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_DNLINK) + ps_param->uapsd_per_ac_delivery_enable_mask &= + ~(1 << ac); + else if (direction == SIR_MAC_DIRECTION_BIDIR) { + ps_param->uapsd_per_ac_trigger_enable_mask &= + ~(1 << ac); + ps_param->uapsd_per_ac_delivery_enable_mask &= + ~(1 << ac); + } + } + + /* + * 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. + */ + if (direction == SIR_MAC_DIRECTION_UPLINK) { + ps_param->ac_admit_mask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + } else if (direction == SIR_MAC_DIRECTION_DNLINK) { + ps_param->ac_admit_mask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } else if (direction == SIR_MAC_DIRECTION_BIDIR) { + ps_param->ac_admit_mask[SIR_MAC_DIRECTION_UPLINK] |= + (1 << ac); + ps_param->ac_admit_mask[SIR_MAC_DIRECTION_DNLINK] |= + (1 << ac); + } + + sms_log(mac_ctx, LOG1, + FL("New ps_param->uapsd_per_ac_trigger_enable_mask = 0x%x "), + ps_param->uapsd_per_ac_trigger_enable_mask); + sms_log(mac_ctx, LOG1, + FL("New ps_param->uapsd_per_ac_delivery_enable_mask = 0x%x "), + ps_param->uapsd_per_ac_delivery_enable_mask); + sms_log(mac_ctx, LOG1, + FL("New ps_param->ac_admit_mask[SIR_MAC_DIRECTION_UPLINK] = 0x%x "), + ps_param->ac_admit_mask[SIR_MAC_DIRECTION_UPLINK]); + return; +} + +/** + * sme_ps_start_uapsd(): function to start UAPSD. + * @hal_ctx: global hal_handle + * @session_id: session id + * @uapsd_start_ind_cb: uapsd start indiation cb + * @callback_context: callback context + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_ps_start_uapsd(tHalHandle hal_ctx, uint32_t session_id, + uapsd_start_indication_cb uapsd_start_ind_cb, + void *callback_context) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + status = sme_ps_uapsd_enable(hal_ctx, session_id); + return status; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +static tSirRetStatus +sme_populate_mac_header(tpAniSirGlobal mac_ctx, + uint8_t *bd, + uint8_t type, + uint8_t sub_type, + tSirMacAddr peer_addr, tSirMacAddr self_mac_addr) +{ + tSirRetStatus status_code = eSIR_SUCCESS; + tpSirMacMgmtHdr mac_hdr; + + /* / Prepare MAC management header */ + mac_hdr = (tpSirMacMgmtHdr) (bd); + + /* Prepare FC */ + mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + mac_hdr->fc.type = type; + mac_hdr->fc.subType = sub_type; + + /* Prepare Address 1 */ + cdf_mem_copy((uint8_t *) mac_hdr->da, (uint8_t *) peer_addr, + sizeof(tSirMacAddr)); + + sir_copy_mac_addr(mac_hdr->sa, self_mac_addr); + + /* Prepare Address 3 */ + cdf_mem_copy((uint8_t *) mac_hdr->bssId, (uint8_t *) peer_addr, + sizeof(tSirMacAddr)); + return status_code; +} /*** sme_populate_mac_header() ***/ + +static tSirRetStatus +sme_prepare_probe_req_template(tpAniSirGlobal mac_ctx, + uint8_t channel_num, + uint32_t dot11mode, + tSirMacAddr self_mac_addr, + uint8_t *frame, + uint16_t *pus_len, tCsrRoamSession *psession) +{ + tDot11fProbeRequest pr; + uint32_t status, bytes, payload; + tSirRetStatus sir_status; + /*Bcast tx */ + tSirMacAddr bss_id = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + /** + * The scheme here is to fill out a 'tDot11fProbeRequest' structure + * and then hand it off to 'dot11f_pack_probe_request' (for + * serialization). We start by zero-initializing the structure: + */ + cdf_mem_set((uint8_t *) &pr, sizeof(pr), 0); + + populate_dot11f_supp_rates(mac_ctx, channel_num, &pr.SuppRates, NULL); + + if (WNI_CFG_DOT11_MODE_11B != dot11mode) { + populate_dot11f_ext_supp_rates1(mac_ctx, channel_num, + &pr.ExtSuppRates); + } + + if (IS_DOT11_MODE_HT(dot11mode)) { + populate_dot11f_ht_caps(mac_ctx, 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? + */ + status = dot11f_get_packed_probe_request_size(mac_ctx, &pr, &payload); + if (DOT11F_FAILED(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to calculate the packed size for a Probe Request (0x%08x)."), + status); + + /* We'll fall back on the worst case scenario: */ + payload = sizeof(tDot11fProbeRequest); + } else if (DOT11F_WARNED(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("There were warnings while calculating the packed size for a Probe Request (0x%08x)."), + status); + } + + bytes = payload + sizeof(tSirMacMgmtHdr); + + /* Prepare outgoing frame */ + cdf_mem_set(frame, bytes, 0); + + /* Next, we fill out the buffer descriptor: */ + sir_status = sme_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bss_id, + self_mac_addr); + + if (eSIR_SUCCESS != sir_status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to populate the buffer descriptor for a Probe Request (%d)."), + sir_status); + return sir_status; /* allocated! */ + } + /* That done, pack the Probe Request: */ + status = dot11f_pack_probe_request(mac_ctx, &pr, frame + + sizeof(tSirMacMgmtHdr), + payload, &payload); + if (DOT11F_FAILED(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).", status); + return eSIR_FAILURE; /* allocated! */ + } else if (DOT11F_WARNED(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request"); + } + + *pus_len = payload + sizeof(tSirMacMgmtHdr); + return eSIR_SUCCESS; +} /* End sme_prepare_probe_req_template. */ + +CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, + tpSirPNOScanReq request, + uint8_t session_id, + preferred_network_found_ind_cb callback_routine, + void *callback_context) +{ + tpSirPNOScanReq request_buf; + cds_msg_t msg; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + uint8_t uc_dot11_mode; + + if (NULL == session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: session is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: SSID = 0x%08x%08x%08x%08x%08x%08x%08x%08x, 0x%08x%08x%08x%08x%08x%08x%08x%08x", __func__, + *((uint32_t *) &request->aNetworks[0].ssId.ssId[0]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[4]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[8]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[12]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[16]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[20]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[24]), + *((uint32_t *) &request->aNetworks[0].ssId.ssId[28]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[0]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[4]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[8]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[12]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[16]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[20]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[24]), + *((uint32_t *) &request->aNetworks[1].ssId.ssId[28])); + + if (!session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: session is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(tSirPNOScanReq)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for PNO request")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(request_buf, request, sizeof(tSirPNOScanReq)); + + /*Must translate the mode first */ + uc_dot11_mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(mac_ctx, + csr_find_best_phy_mode + (mac_ctx, + mac_ctx->roam. + configParam. + phyMode)); + + /*Prepare a probe request for 2.4GHz band and one for 5GHz band */ + if (eSIR_SUCCESS == + sme_prepare_probe_req_template(mac_ctx, + SIR_PNO_24G_DEFAULT_CH, + uc_dot11_mode, session->selfMacAddr.bytes, + request_buf->p24GProbeTemplate, + &request_buf->us24GProbeTemplateLen, + session)) { + /* Append IE passed by supplicant(if any) + * to probe request + */ + if ((0 < request->us24GProbeTemplateLen) && + ((request_buf->us24GProbeTemplateLen + + request->us24GProbeTemplateLen) < + SIR_PNO_MAX_PB_REQ_SIZE)) { + cdf_mem_copy((uint8_t *) &request_buf-> + p24GProbeTemplate + + request_buf->us24GProbeTemplateLen, + (uint8_t *) &request->p24GProbeTemplate, + request->us24GProbeTemplateLen); + request_buf->us24GProbeTemplateLen += + request->us24GProbeTemplateLen; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("request->us24GProbeTemplateLen = %d"), + request->us24GProbeTemplateLen); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("Extra ie discarded on 2.4G, IE len = %d"), + request->us24GProbeTemplateLen); + } + } + + if (eSIR_SUCCESS == + sme_prepare_probe_req_template(mac_ctx, + SIR_PNO_5G_DEFAULT_CH, uc_dot11_mode, + session->selfMacAddr.bytes, + request_buf->p5GProbeTemplate, + &request_buf->us5GProbeTemplateLen, + session)) { + /* Append IE passed by supplicant(if any) + * to probe request + */ + if ((0 < request->us5GProbeTemplateLen) && + ((request_buf->us5GProbeTemplateLen + + request->us5GProbeTemplateLen) < + SIR_PNO_MAX_PB_REQ_SIZE)) { + cdf_mem_copy((uint8_t *) &request_buf-> + p5GProbeTemplate + + request_buf->us5GProbeTemplateLen, + (uint8_t *) &request->p5GProbeTemplate, + request->us5GProbeTemplateLen); + request_buf->us5GProbeTemplateLen += + request->us5GProbeTemplateLen; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("request_buf->us5GProbeTemplateLen = %d"), + request->us5GProbeTemplateLen); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Extra IE discarded on 5G, IE length = %d"), + request->us5GProbeTemplateLen); + } + } + + if (mac_ctx->pnoOffload) { + if (request_buf->enable) + session->pnoStarted = true; + else + session->pnoStarted = false; + + request_buf->sessionId = session_id; + } + + msg.type = WMA_SET_PNO_REQ; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_SET_PNO_REQ message to WMA")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + /* Cache the Preferred Network Found Indication callback information */ + mac_ctx->sme.pref_netw_found_cb = + callback_routine; + mac_ctx->sme.preferred_network_found_ind_cb_ctx = + callback_context; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "-%s", __func__); + + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_SCAN_PNO */ + +/** + * sme_set_ps_host_offload(): Set the host offload feature. + * @hal_ctx - The handle returned by mac_open. + * @request - Pointer to the offload request. + * + * Return CDF_STATUS + * CDF_STATUS_E_FAILURE Cannot set the offload. + * CDF_STATUS_SUCCESS Request accepted. + */ +CDF_STATUS sme_set_ps_host_offload(tHalHandle hal_ctx, + tpSirHostOffloadReq request, + uint8_t session_id) +{ + tpSirHostOffloadReq request_buf; + cds_msg_t msg; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: IP address = %d.%d.%d.%d", __func__, + request->params.hostIpv4Addr[0], + request->params.hostIpv4Addr[1], + request->params.hostIpv4Addr[2], + request->params.hostIpv4Addr[3]); + + if (NULL == session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: SESSION not Found", __func__); + return CDF_STATUS_E_FAILURE; + } + + request_buf = cdf_mem_malloc(sizeof(tSirHostOffloadReq)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for host offload request")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(request->bssId, session->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + cdf_mem_copy(request_buf, request, sizeof(tSirHostOffloadReq)); + + msg.type = WMA_SET_HOST_OFFLOAD; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_SET_HOST_OFFLOAD msg to WMA")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_NS_OFFLOAD +/** + * sme_set_ps_ns_offload(): Set the host offload feature. + * @hal_ctx - The handle returned by mac_open. + * @request - Pointer to the offload request. + * + * Return CDF_STATUS + * CDF_STATUS_E_FAILURE Cannot set the offload. + * CDF_STATUS_SUCCESS Request accepted. + */ +CDF_STATUS sme_set_ps_ns_offload(tHalHandle hal_ctx, + tpSirHostOffloadReq request, + uint8_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + tpSirHostOffloadReq request_buf; + cds_msg_t msg; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + + if (NULL == session) { + sms_log(mac_ctx, LOGE, FL("Session not found ")); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(request->bssId, session->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + request_buf = cdf_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for NS offload request")); + return CDF_STATUS_E_NOMEM; + } + *request_buf = *request; + + msg.type = WMA_SET_NS_OFFLOAD; + msg.reserved = 0; + msg.bodyptr = request_buf; + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post SIR_HAL_SET_HOST_OFFLOAD message to HAL")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +#endif /* WLAN_NS_OFFLOAD */ +/* -------------------------------------------------------------------- */ +/** + * sme_post_pe_message + * + * FUNCTION: + * Post a message to the pmm message queue + * + * LOGIC: + * + * ASSUMPTIONS: + * + * NOTE: + * + * @param msg pointer to message + * @return None + */ + +tSirRetStatus sme_post_pe_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + CDF_STATUS cdf_status; + cdf_status = cds_mq_post_message(CDS_MQ_ID_PE, (cds_msg_t *) msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(mac_ctx, LOGP, + FL("cds_mq_post_message failed with status code %d"), + cdf_status); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +CDF_STATUS sme_ps_enable_auto_ps_timer(tHalHandle hal_ctx, + uint32_t session_id, + bool is_reassoc) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + CDF_STATUS cdf_status; + uint32_t timer_value; + + if (is_reassoc) + timer_value = AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE; + else + timer_value = AUTO_DEFERRED_PS_ENTRY_TIMER_DEFAULT_VALUE; + + sms_log(mac_ctx, LOGE, FL("Start auto_ps_timer for %d is_reassoc:%d "), + timer_value, is_reassoc); + + cdf_status = cdf_mc_timer_start(&ps_param->auto_ps_enable_timer, + timer_value); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + if (CDF_STATUS_E_ALREADY == cdf_status) { + /* Consider this ok since the timer is already started*/ + sms_log(mac_ctx, LOGW, + FL("auto_ps_timer is already started")); + } else { + sms_log(mac_ctx, LOGP, + FL("Cannot start auto_ps_timer")); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_ps_disable_auto_ps_timer(tHalHandle hal_ctx, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + /* + * Stop the auto ps entry timer if runnin + */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &ps_param->auto_ps_enable_timer)) { + sms_log(mac_ctx, LOGE, + FL("Stop auto_ps_enable_timer Timer for session ID:%d "), + session_id); + cdf_mc_timer_stop(&ps_param->auto_ps_enable_timer); + } + return CDF_STATUS_SUCCESS; +} + + +CDF_STATUS sme_ps_open(tHalHandle hal_ctx) +{ + + uint32_t i; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + + sms_log(mac_ctx, LOG1, FL("Enter")); + + for (i = 0; i < MAX_SME_SESSIONS; i++) { + if (CDF_STATUS_SUCCESS != sme_ps_open_per_session(hal_ctx, i)) { + sms_log(mac_ctx, LOGE, + FL("PMC Init Failed for session %d"), i); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} + + +CDF_STATUS sme_ps_open_per_session(tHalHandle hal_ctx, uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + ps_param->session_id = session_id; + ps_param->mac_ctx = mac_ctx; + + sms_log(mac_ctx, LOG1, FL("Enter")); + /* Allocate a timer to enable ps automatically */ + if (!CDF_IS_STATUS_SUCCESS(cdf_mc_timer_init( + &ps_param->auto_ps_enable_timer, + CDF_TIMER_TYPE_SW, + sme_auto_ps_entry_timer_expired, + ps_param))) { + sms_log(mac_ctx, LOGE, + FL("Cannot allocate timer for auto ps entry")); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; + +} + +void sme_auto_ps_entry_timer_expired(void *data) +{ + struct ps_params *ps_params = (struct ps_params *)data; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)ps_params->mac_ctx; + uint32_t session_id = ps_params->session_id; + CDF_STATUS status = CDF_STATUS_SUCCESS; + status = sme_enable_sta_ps_check(mac_ctx, session_id); + + if (CDF_STATUS_SUCCESS == status) { + sme_ps_enable_disable((tHalHandle)mac_ctx, session_id, + SME_PS_ENABLE); + } else { + status = + cdf_mc_timer_start(&ps_params->auto_ps_enable_timer, + AUTO_PS_ENTRY_TIMER_DEFAULT_VALUE); + if (!CDF_IS_STATUS_SUCCESS(status) + && (CDF_STATUS_E_ALREADY != status)) { + sms_log(mac_ctx, LOGP, + FL("Cannot start traffic timer")); + } + } +} + +CDF_STATUS sme_ps_close(tHalHandle hal_ctx) +{ + uint32_t i; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + + sms_log(mac_ctx, LOG2, FL("Enter")); + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) + sme_ps_close_per_session(hal_ctx, i); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_ps_close_per_session(tHalHandle hal_ctx, uint32_t session_id) +{ + + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + /* + * Stop the auto ps entry timer if running + */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &ps_param->auto_ps_enable_timer)) { + cdf_mc_timer_stop(&ps_param->auto_ps_enable_timer); + } + cdf_status = + cdf_mc_timer_destroy(&ps_param->auto_ps_enable_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + sms_log(mac_ctx, LOGE, FL("Cannot deallocate suto PS timer")); + return cdf_status; +} + +CDF_STATUS sme_is_auto_ps_timer_running(tHalHandle hal_ctx, + uint32_t session_id) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx); + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[session_id]; + bool status = false; + /* + * Check if the auto ps entry timer if running + */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state( + &ps_param->auto_ps_enable_timer)) { + status = true; + } + return status; +} + diff --git a/core/sme/src/common/sme_trace.c b/core/sme/src/common/sme_trace.c new file mode 100644 index 000000000000..d6d85fd44409 --- /dev/null +++ b/core/sme/src/common/sme_trace.c @@ -0,0 +1,209 @@ +/* + * 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 "ani_global.h" /* for tpAniSirGlobal */ +#include "sms_debug.h" +#include "mac_trace.h" +#include "sme_trace.h" +#include "sme_internal.h" +#ifndef SME_TRACE_RECORD +void sme_trace_init(tpAniSirGlobal pMac) +{ + return; +} +#endif +#ifdef SME_TRACE_RECORD + +static uint8_t *sme_trace_get_rx_msg_string(uint32_t 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_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_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_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_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); + + default: + return "UNKNOWN"; + break; + } +} + +static uint8_t *sme_trace_get_command_string(uint32_t 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(eSmeCommandAddStaSession); + CASE_RETURN_STRING(eSmeCommandDelStaSession); + CASE_RETURN_STRING(eSmePmcCommandMask); + CASE_RETURN_STRING(eSmeCommandEnterBmps); + CASE_RETURN_STRING(eSmeCommandExitBmps); + CASE_RETURN_STRING(eSmeCommandEnterUapsd); + CASE_RETURN_STRING(eSmeCommandExitUapsd); + 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); + default: + return "UNKNOWN"; + break; + } +} + +static void sme_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, + uint16_t recIndex) +{ + if (TRACE_CODE_SME_COMMAND == pRecord->code) { + sms_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, + "SME COMMAND:", sme_trace_get_command_string(pRecord->data), + pRecord->data); + } else { + sms_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(0x%x)", + recIndex, pRecord->time, pRecord->session, "RX HDD MSG:", + sme_trace_get_rx_msg_string(pRecord->code), pRecord->data); + } +} + +void sme_trace_init(tpAniSirGlobal pMac) +{ + cdf_trace_register(CDF_MODULE_ID_SME, (tp_cdf_trace_cb) & sme_trace_dump); +} +#endif diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c new file mode 100644 index 000000000000..9074f37cae7c --- /dev/null +++ b/core/sme/src/csr/csr_api_roam.c @@ -0,0 +1,18860 @@ +/* + * 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 csr_api_roam.c + + Implementation for the Common Roaming interfaces. + ========================================================================== */ +#include "ani_global.h" /* for tpAniSirGlobal */ +#include "wma_types.h" +#include "wma_if.h" /* for STA_INVALID_IDX. */ +#include "lim_utils.h" +#include "cds_mq.h" +#include "csr_inside_api.h" +#include "sms_debug.h" +#include "sme_qos_internal.h" +#include "sme_inside.h" +#include "host_diag_core_event.h" +#include "host_diag_core_log.h" +#include "csr_api.h" +#include "csr_internal.h" +#include "cds_reg_service.h" +#include "mac_trace.h" +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "csr_neighbor_roam.h" +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ +#include "cds_regdomain_common.h" +#include "cds_utils.h" +#include "sir_types.h" +#include "cfg_api.h" +#include "sme_power_save_api.h" +#include "wma.h" +#include "cds_concurrency.h" + +#define CSR_NUM_IBSS_START_CHANNELS_50 4 +#define CSR_NUM_IBSS_START_CHANNELS_24 3 +/* 5 seconds, for WPA, WPA2, CCKM */ +#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (5 * CDF_MC_TIMER_TO_SEC_UNIT) +/* 120 seconds, for WPS */ +#define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * CDF_MC_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 +/* Choose the largest possible value that can be accomodates in 8 bit signed */ +/* variable. */ +#define SNR_HACK_BMPS (127) + +static bool b_roam_scan_offload_started; + +/*-------------------------------------------------------------------------- + Static Type declarations + ------------------------------------------------------------------------*/ +static tCsrRoamSession csr_roam_roam_session[CSR_ROAM_SESSION_MAX]; + +/*-------------------------------------------------------------------------- + Type declarations + ------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +int diag_auth_type_from_csr_type(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 diag_enc_type_from_csr_type(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 uint8_t + csr_start_ibss_channels50[CSR_NUM_IBSS_START_CHANNELS_50] = { 36, 40, 44, 48 }; +static const uint8_t + csr_start_ibss_channels24[CSR_NUM_IBSS_START_CHANNELS_24] = { 1, 6, 11 }; +static void init_config_param(tpAniSirGlobal pMac); +static bool csr_roam_process_results(tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrRoamCompleteResult Result, + void *Context); +static CDF_STATUS csr_roam_start_ibss(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + bool *pfSameIbss); +static void csr_roam_update_connected_profile_from_new_bss(tpAniSirGlobal pMac, + uint32_t sessionId, + tSirSmeNewBssInfo * + pNewBss); +static void csr_roam_prepare_bss_params(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes); +static ePhyChanBondState csr_get_cb_mode_from_ies(tpAniSirGlobal pMac, + uint8_t primaryChn, + tDot11fBeaconIEs *pIes); + +static void csr_roaming_state_config_cnf_processor(tpAniSirGlobal pMac, + uint32_t result); +CDF_STATUS csr_roam_open(tpAniSirGlobal pMac); +CDF_STATUS csr_roam_close(tpAniSirGlobal pMac); +void csr_roamMICErrorTimerHandler(void *pv); +void csr_roamTKIPCounterMeasureTimerHandler(void *pv); +bool csr_roam_is_same_profile_keys(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pConnProfile, + tCsrRoamProfile *pProfile2); + +static CDF_STATUS csr_roam_start_roaming_timer(tpAniSirGlobal pMac, + uint32_t sessionId, + uint32_t interval); +static CDF_STATUS csr_roam_stop_roaming_timer(tpAniSirGlobal pMac, + uint32_t sessionId); +static void csr_roam_roaming_timer_handler(void *pv); +CDF_STATUS csr_roam_start_wait_for_key_timer(tpAniSirGlobal pMac, uint32_t interval); +CDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac); +static void csr_roam_wait_for_key_time_out_handler(void *pv); +static CDF_STATUS csr_init11d_info(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo); +static CDF_STATUS csr_init_channel_power_list(tpAniSirGlobal pMac, + tCsr11dinfo *ps11dinfo); +static CDF_STATUS csr_roam_free_connected_info(tpAniSirGlobal pMac, + tCsrRoamConnectedInfo * + pConnectedInfo); +CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr peerMacAddr, uint8_t numKeys, + tAniEdType edType, bool fUnicast, + tAniKeyDirection aniKeyDirection, + uint8_t keyId, uint8_t keyLength, + uint8_t *pKey, uint8_t paeRole, + uint8_t *pKeyRsc); +static CDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac, + uint32_t sessionId, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, + tCsrRoamProfile *pProfile); +void csr_roamStatisticsTimerHandler(void *pv); +void csr_roamStatsGlobalClassDTimerHandler(void *pv); +static void csr_roam_link_up(tpAniSirGlobal pMac, struct cdf_mac_addr bssid); +static void csr_roam_link_down(tpAniSirGlobal pMac, uint32_t sessionId); +void csr_roam_vcc_trigger(tpAniSirGlobal pMac); +CDF_STATUS csr_send_mb_stats_req_msg(tpAniSirGlobal pMac, uint32_t statsMask, + uint8_t staId, uint8_t sessionId); +/* + pStaEntry is no longer invalid upon the return of this function. + */ +static void csr_roam_remove_stat_list_entry(tpAniSirGlobal pMac, tListElem *pEntry); +static eCsrCfgDot11Mode csr_roam_get_phy_mode_band_for_bss(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, + uint8_t operationChn, + eCsrBand *pBand); +static CDF_STATUS csr_roam_get_qos_info_from_bss(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc); +tCsrStatsClientReqInfo *csr_roam_insert_entry_into_list(tpAniSirGlobal pMac, + tDblLinkList *pStaList, + tCsrStatsClientReqInfo * + pStaEntry); +void csr_roam_stats_client_timer_handler(void *pv); +tCsrPeStatsReqInfo *csr_roam_check_pe_stats_req_list(tpAniSirGlobal pMac, + uint32_t statsMask, + uint32_t periodicity, + bool *pFound, uint8_t staId, + uint8_t sessionId); +void csr_roam_report_statistics(tpAniSirGlobal pMac, uint32_t statsMask, + tCsrStatsCallback callback, uint8_t staId, + void *pContext); +void csr_roam_tl_stats_timer_handler(void *pv); +void csr_roam_pe_stats_timer_handler(void *pv); +tListElem *csr_roam_check_client_req_list(tpAniSirGlobal pMac, uint32_t statsMask); +void csr_roam_remove_entry_from_pe_stats_req_list(tpAniSirGlobal pMac, + tCsrPeStatsReqInfo *pPeStaEntry); +tListElem *csr_roam_find_in_pe_stats_req_list(tpAniSirGlobal pMac, uint32_t statsMask); +CDF_STATUS csr_roam_dereg_statistics_req(tpAniSirGlobal pMac); +static uint32_t csr_find_ibss_session(tpAniSirGlobal pMac); +static uint32_t csr_find_session_by_type(tpAniSirGlobal, tCDF_CON_MODE); +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 CDF_STATUS csr_roam_start_wds(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc); +static void csr_init_session(tpAniSirGlobal pMac, uint32_t sessionId); +static CDF_STATUS csr_roam_issue_set_key_command(tpAniSirGlobal pMac, + uint32_t sessionId, + tCsrRoamSetKey *pSetKey, + uint32_t roamId); +static CDF_STATUS csr_roam_get_qos_info_from_bss(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc); +void csr_roam_reissue_roam_command(tpAniSirGlobal pMac); +static void csr_ser_des_unpack_diassoc_rsp(uint8_t *pBuf, + tSirSmeDisassocRsp *pRsp); +void csr_reinit_preauth_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_init_operating_classes(tHalHandle hHal); + +/* Initialize global variables */ +static void csr_roam_init_globals(tpAniSirGlobal pMac) +{ + if (pMac) { + cdf_mem_zero(&csr_roam_roam_session, sizeof(csr_roam_roam_session)); + pMac->roam.roamSession = csr_roam_roam_session; + } + return; +} + +static void csr_roam_de_init_globals(tpAniSirGlobal pMac) +{ + if (pMac) { + pMac->roam.roamSession = NULL; + } + return; +} + +CDF_STATUS csr_open(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t i; + + do { + /* Initialize CSR Roam Globals */ + csr_roam_init_globals(pMac); + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_STOP, i); + + init_config_param(pMac); + status = csr_scan_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + status = csr_roam_open(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + pMac->roam.nextRoamId = 1; /* Must not be 0 */ + if (!CDF_IS_STATUS_SUCCESS + (csr_ll_open(pMac->hHdd, + &pMac->roam.statsClientReqList))) + break; + if (!CDF_IS_STATUS_SUCCESS + (csr_ll_open(pMac->hHdd, + &pMac->roam.peStatsReqList))) + break; + if (!CDF_IS_STATUS_SUCCESS + (csr_ll_open(pMac->hHdd, + &pMac->roam.roamCmdPendingList))) + break; + } while (0); + + return status; +} + +CDF_STATUS csr_init_chan_list(tpAniSirGlobal mac, uint8_t *alpha2) +{ + CDF_STATUS 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]; + + sms_log(mac, LOGE, FL("init time country code %.2s"), + mac->scan.countryCodeDefault); + + status = csr_get_regulatory_domain_for_country(mac, + mac->scan.countryCodeDefault, + ®_id, source); + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac, LOGE, + FL("csr_get_regulatory_domain_for_country failed")); + return status; + } + + if (cds_set_reg_domain(mac, reg_id) != CDF_STATUS_SUCCESS) { + sms_log(mac, LOGE, FL("cds_set_reg_domain failed")); + return CDF_STATUS_E_FAILURE; + } + mac->scan.domainIdDefault = reg_id; + mac->scan.domainIdCurrent = mac->scan.domainIdDefault; + cdf_mem_copy(mac->scan.countryCodeCurrent, + mac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN); + cdf_mem_copy(mac->scan.countryCodeElected, + mac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN); + status = csr_get_channel_and_power_list(mac); + csr_clear_votes_for_country_info(mac); + return status; +} + +CDF_STATUS csr_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + v_REGDOMAIN_t regId; + uint8_t cntryCodeLength; + if (NULL == apCntryCode) { + sms_log(pMac, LOGE, FL(" Invalid country Code Pointer")); + return CDF_STATUS_E_FAILURE; + } + sms_log(pMac, LOG1, FL(" country Code %.2s"), apCntryCode); + + cntryCodeLength = WNI_CFG_COUNTRY_CODE_LEN; + status = csr_get_regulatory_domain_for_country(pMac, apCntryCode, ®Id, + COUNTRY_USER); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, + FL(" fail to get regId for country Code %.2s"), + apCntryCode); + return status; + } + status = wma_set_reg_domain(hHal, regId); + if (status != CDF_STATUS_SUCCESS) { + sms_log(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 */ + cdf_mem_set(pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN, 0); + + /* Copy 2 or 3 bytes country code */ + cdf_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) { + cdf_mem_set(pMac->scan.countryCodeDefault + 2, 1, 0x20); + } + cdf_mem_copy(pMac->scan.countryCodeCurrent, + pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN); + status = csr_get_channel_and_power_list(pMac); + return status; +} + +CDF_STATUS csr_set_channels(tHalHandle hHal, tCsrConfigParam *pParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t index = 0; + cdf_mem_copy(pParam->Csr11dinfo.countryCode, + pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); + for (index = 0; index < pMac->scan.base_channels.numChannels; + index++) { + pParam->Csr11dinfo.Channels.channelList[index] = + pMac->scan.base_channels.channelList[index]; + pParam->Csr11dinfo.ChnPower[index].firstChannel = + pMac->scan.base_channels.channelList[index]; + pParam->Csr11dinfo.ChnPower[index].numChannels = 1; + pParam->Csr11dinfo.ChnPower[index].maxtxPower = + pMac->scan.defaultPowerTable[index].pwr; + } + pParam->Csr11dinfo.Channels.numChannels = + pMac->scan.base_channels.numChannels; + + return status; +} + +CDF_STATUS csr_close(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + csr_roam_close(pMac); + csr_scan_close(pMac); + csr_ll_close(&pMac->roam.statsClientReqList); + csr_ll_close(&pMac->roam.peStatsReqList); + csr_ll_close(&pMac->roam.roamCmdPendingList); + /* DeInit Globals */ + csr_roam_de_init_globals(pMac); + return status; +} + +static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * + pdefaultPowerTable, + uint8_t ChannelNum) +{ + uint8_t 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 occured */ + CDF_ASSERT(0); + return 0; +} + +CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) +{ + tSirUpdateChanList *pChanList; + tCsrScanStruct *pScan = &pMac->scan; + uint8_t numChan = pScan->base_channels.numChannels; + uint8_t num_channel = 0; + uint32_t bufLen; + cds_msg_t msg; + uint8_t i, j, social_channel[MAX_SOCIAL_CHANNELS] = { 1, 6, 11 }; + uint8_t channel_state; + + if (CSR_IS_5G_BAND_ONLY(pMac)) { + for (i = 0; i < MAX_SOCIAL_CHANNELS; i++) { + if (cds_get_channel_state(social_channel[i]) + == CHANNEL_STATE_ENABLE) + numChan++; + } + } + + bufLen = sizeof(tSirUpdateChanList) + + (sizeof(tSirUpdateChanParam) * (numChan)); + + csr_init_operating_classes((tHalHandle) pMac); + pChanList = (tSirUpdateChanList *) cdf_mem_malloc(bufLen); + if (!pChanList) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Failed to allocate memory for tSirUpdateChanList"); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(pChanList, bufLen); + + for (i = 0; i < pScan->base_channels.numChannels; i++) { + /* Scan is not performed on DSRC channels*/ + if (pScan->base_channels.channelList[i] >= MIN_11P_CHANNEL) + continue; + if (pScan->fcc_constraint) { + if (pScan->base_channels.channelList[i] == 12) + continue; + if (pScan->base_channels.channelList[i] == 13) + continue; + } + channel_state = + cds_get_channel_state( + pScan->base_channels.channelList[i]); + if ((CHANNEL_STATE_ENABLE == channel_state) || + pMac->scan.fEnableDFSChnlScan) { + pChanList->chanParam[num_channel].chanId = + pScan->base_channels.channelList[i]; + pChanList->chanParam[num_channel].pwr = + csr_find_channel_pwr(pScan->defaultPowerTable, + pChanList->chanParam[num_channel].chanId); + if (CHANNEL_STATE_ENABLE == channel_state) + pChanList->chanParam[num_channel].dfsSet = + false; + else + pChanList->chanParam[num_channel].dfsSet = + true; + num_channel++; + } + } + + if (CSR_IS_5G_BAND_ONLY(pMac)) { + for (j = 0; j < MAX_SOCIAL_CHANNELS; j++) { + if (cds_get_channel_state(social_channel[j]) + == CHANNEL_STATE_ENABLE) { + pChanList->chanParam[num_channel].chanId = + social_channel[j]; + pChanList->chanParam[num_channel].pwr = + csr_find_channel_pwr(pScan->defaultPowerTable, + social_channel[j]); + pChanList->chanParam[num_channel].dfsSet = false; + num_channel++; + } + } + } + + msg.type = WMA_UPDATE_CHAN_LIST_REQ; + msg.reserved = 0; + msg.bodyptr = pChanList; + pChanList->numChan = num_channel; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to post msg to WMA", __func__); + cdf_mem_free(pChanList); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_start(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t i; + + do { + /* save the global cds context */ + pMac->roam.g_cds_context = cds_get_global_context(); + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_IDLE, i); + + status = csr_roam_start(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + + pMac->roam.sPendingCommands = 0; + csr_scan_enable(pMac); +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) + status = csr_neighbor_roam_init(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 (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, + " csr_start: Couldn't Init HO control blk "); + break; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "Scan offload is enabled, update default chan list"); + status = csr_update_channel_list(pMac); + + } while (0); + return status; +} + +CDF_STATUS csr_stop(tpAniSirGlobal pMac, tHalStopType stopType) +{ + uint32_t sessionId; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + csr_roam_close_session(pMac, sessionId, true, NULL, NULL); + } + csr_scan_disable(pMac); + pMac->scan.fCancelIdleScan = false; + pMac->scan.fRestartIdleScan = false; + csr_ll_purge(&pMac->roam.roamCmdPendingList, true); + +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + csr_neighbor_roam_close(pMac, sessionId); +#endif + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) + if (CSR_IS_SESSION_VALID(pMac, sessionId)) + csr_scan_flush_result(pMac); + + /* Reset the domain back to the deault */ + pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_STOP, sessionId); + pMac->roam.curSubState[sessionId] = eCSR_ROAM_SUBSTATE_NONE; + } + + /* 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) { + b_roam_scan_offload_started = false; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_ready(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + /* If the gScanAgingTime is set to '0' then scan results aging timeout + based on timer feature is not enabled */ + + if (0 != pMac->scan.scanResultCfgAgingTime) { + csr_scan_start_result_cfg_aging_timer(pMac); + } + status = csr_apply_channel_and_power_list(pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "csr_apply_channel_and_power_list failed during csr_ready with status=%d", + status); + } + return status; +} + +void csr_set_default_dot11_mode(tpAniSirGlobal pMac) +{ + uint32_t wniDot11mode = 0; + wniDot11mode = + csr_translate_to_wni_cfg_dot11_mode(pMac, + pMac->roam.configParam.uCfgDot11Mode); + cfg_set_int(pMac, WNI_CFG_DOT11_MODE, wniDot11mode); +} + +void csr_set_global_cfgs(tpAniSirGlobal pMac) +{ + + cfg_set_int(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, + csr_get_frag_thresh(pMac)); + cfg_set_int(pMac, WNI_CFG_RTS_THRESHOLD, csr_get_rts_thresh(pMac)); + cfg_set_int(pMac, WNI_CFG_11D_ENABLED, + ((pMac->roam.configParam.Is11hSupportEnabled) ? pMac->roam. + configParam.Is11dSupportEnabled : pMac->roam.configParam. + Is11dSupportEnabled)); + cfg_set_int(pMac, WNI_CFG_11H_ENABLED, + pMac->roam.configParam.Is11hSupportEnabled); + /* 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 + */ + cfg_set_int(pMac, WNI_CFG_CHANNEL_BONDING_MODE, + !!(pMac->roam.configParam.channelBondingMode5GHz)); + cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, + pMac->roam.configParam.HeartbeatThresh24); + + /* Update the operating mode to configured value during initialization, */ + /* So that client can advertise full capabilities in Probe request frame. */ + csr_set_default_dot11_mode(pMac); +} + +CDF_STATUS csr_roam_open(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t 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 = + cdf_mc_timer_init(&pMac->roam.hTimerWaitForKey, + CDF_TIMER_TYPE_SW, + csr_roam_wait_for_key_time_out_handler, + &pMac->roam.WaitForKeyTimerInfo); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("cannot allocate memory for WaitForKey time out timer")); + break; + } + status = + cdf_mc_timer_init(&pMac->roam.tlStatsReqInfo.hTlStatsTimer, + CDF_TIMER_TYPE_SW, + csr_roam_tl_stats_timer_handler, pMac); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("cannot allocate memory for summary Statistics timer")); + return CDF_STATUS_E_FAILURE; + } + } while (0); + return status; +} + +CDF_STATUS csr_roam_close(tpAniSirGlobal pMac) +{ + uint32_t sessionId; + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + csr_roam_close_session(pMac, sessionId, true, NULL, NULL); + } + cdf_mc_timer_stop(&pMac->roam.hTimerWaitForKey); + cdf_mc_timer_destroy(&pMac->roam.hTimerWaitForKey); + cdf_mc_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + cdf_mc_timer_destroy(&pMac->roam.tlStatsReqInfo.hTlStatsTimer); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_start(tpAniSirGlobal pMac) +{ + (void)pMac; + return CDF_STATUS_SUCCESS; +} + +void csr_roam_stop(tpAniSirGlobal pMac, uint32_t sessionId) +{ + csr_roam_stop_roaming_timer(pMac, sessionId); + /* deregister the clients requesting stats from PE/TL & also stop the corresponding timers */ + csr_roam_dereg_statistics_req(pMac); +} + +CDF_STATUS csr_roam_get_connect_state(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrConnectState *pState) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + if (CSR_IS_SESSION_VALID(pMac, sessionId) && (NULL != pState)) { + status = CDF_STATUS_SUCCESS; + *pState = pMac->roam.roamSession[sessionId].connectState; + } + return status; +} + +CDF_STATUS csr_roam_copy_connect_profile(tpAniSirGlobal pMac, + uint32_t sessionId, tCsrRoamConnectedProfile *pProfile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t size = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tCsrRoamConnectedProfile *connected_prof; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + if (!pProfile) { + sms_log(pMac, LOGE, FL("profile not found")); + return CDF_STATUS_E_FAILURE; + } + + if (pSession->pConnectBssDesc) { + size = pSession->pConnectBssDesc->length + + sizeof(pSession->pConnectBssDesc->length); + if (size) { + pProfile->pBssDesc = cdf_mem_malloc(size); + if (NULL != pProfile->pBssDesc) { + cdf_mem_copy(pProfile->pBssDesc, + pSession->pConnectBssDesc, + size); + status = CDF_STATUS_SUCCESS; + } else { + return CDF_STATUS_E_FAILURE; + } + } else { + pProfile->pBssDesc = NULL; + } + connected_prof = &(pSession->connectedProfile); + pProfile->AuthType = connected_prof->AuthType; + pProfile->EncryptionType = connected_prof->EncryptionType; + pProfile->mcEncryptionType = connected_prof->mcEncryptionType; + pProfile->BSSType = connected_prof->BSSType; + pProfile->operationChannel = connected_prof->operationChannel; + pProfile->CBMode = connected_prof->CBMode; + cdf_mem_copy(&pProfile->bssid, &connected_prof->bssid, + sizeof(struct cdf_mac_addr)); + cdf_mem_copy(&pProfile->SSID, &connected_prof->SSID, + sizeof(tSirMacSSid)); +#ifdef WLAN_FEATURE_VOWIFI_11R + if (connected_prof->MDID.mdiePresent) { + pProfile->MDID.mdiePresent = 1; + pProfile->MDID.mobilityDomain = + connected_prof->MDID.mobilityDomain; + } else { + pProfile->MDID.mdiePresent = 0; + pProfile->MDID.mobilityDomain = 0; + } +#endif +#ifdef FEATURE_WLAN_ESE + pProfile->isESEAssoc = connected_prof->isESEAssoc; + if (csr_is_auth_type_ese(connected_prof->AuthType)) { + cdf_mem_copy(pProfile->eseCckmInfo.krk, + connected_prof->eseCckmInfo.krk, + SIR_KRK_KEY_LEN); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + cdf_mem_copy(pProfile->eseCckmInfo.btk, + connected_prof->eseCckmInfo.btk, + SIR_BTK_KEY_LEN); +#endif + pProfile->eseCckmInfo.reassoc_req_num = + connected_prof->eseCckmInfo.reassoc_req_num; + pProfile->eseCckmInfo.krk_plumbed = + connected_prof->eseCckmInfo.krk_plumbed; + } +#endif + } + return status; +} + +CDF_STATUS csr_roam_get_connect_profile(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamConnectedProfile *pProfile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if ((csr_is_conn_state_connected(pMac, sessionId)) || + (csr_is_conn_state_ibss(pMac, sessionId))) { + if (pProfile) { + status = + csr_roam_copy_connect_profile(pMac, sessionId, + pProfile); + } + } + return status; +} + +CDF_STATUS csr_roam_free_connect_profile(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pProfile) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (pProfile->pBssDesc) { + cdf_mem_free(pProfile->pBssDesc); + } + if (pProfile->pAddIEAssoc) { + cdf_mem_free(pProfile->pAddIEAssoc); + } + cdf_mem_set(pProfile, sizeof(tCsrRoamConnectedProfile), 0); + + pProfile->AuthType = eCSR_AUTH_TYPE_UNKNOWN; + return status; +} + +static CDF_STATUS csr_roam_free_connected_info(tpAniSirGlobal pMac, + tCsrRoamConnectedInfo * + pConnectedInfo) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + if (pConnectedInfo->pbFrames) { + cdf_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 csr_release_command_preauth(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csr_reinit_preauth_cmd(pMac, pCommand); + csr_release_command(pMac, pCommand); +} + +void csr_release_command_roam(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csr_reinit_roam_cmd(pMac, pCommand); + csr_release_command(pMac, pCommand); +} + +void csr_release_command_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + cdf_mc_timer_stop(&pCommand->u.scanCmd.csr_scan_timer); + cdf_mc_timer_destroy(&pCommand->u.scanCmd.csr_scan_timer); + csr_reinit_scan_cmd(pMac, pCommand); + csr_release_command(pMac, pCommand); +} + +void csr_release_command_wm_status_change(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csr_reinit_wm_status_change_cmd(pMac, pCommand); + csr_release_command(pMac, pCommand); +} + +void csr_reinit_set_key_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + cdf_mem_set(&pCommand->u.setKeyCmd, sizeof(tSetKeyCmd), 0); +} + +void csr_release_command_set_key(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + csr_reinit_set_key_cmd(pMac, pCommand); + csr_release_command(pMac, pCommand); +} + +/** + * 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; + tSmeCmd *cmd = NULL; + + entry = csr_ll_peek_head(&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, + cmd->u.remainChlCmd.scan_id); + sms_log(mac_ctx, LOGE, + FL("Remove RoC Request from Active Cmd List")); + /* Put this cmd back on the available command list */ + if (csr_ll_remove_entry(&mac_ctx->sme.smeCmdActiveList, + entry, LL_ACCESS_LOCK)) + sme_release_command(mac_ctx, cmd); + } + } +} + +void csr_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, bool fStopping) +{ + + if (eSmeCsrCommandMask & pCommand->command) { + switch (pCommand->command) { + case eSmeCommandScan: + /* We need to inform the requester before dropping the scan command */ + sms_log(pMac, LOGW, + "%s: Drop scan reason %d callback %p", __func__, + pCommand->u.scanCmd.reason, + pCommand->u.scanCmd.callback); + if (NULL != pCommand->u.scanCmd.callback) { + sms_log(pMac, LOGW, "%s callback scan requester", + __func__); + csr_scan_call_callback(pMac, pCommand, + eCSR_SCAN_ABORT); + } + csr_release_command_scan(pMac, pCommand); + break; + case eSmeCommandRoam: + csr_release_command_roam(pMac, pCommand); + break; + + case eSmeCommandWmStatusChange: + csr_release_command_wm_status_change(pMac, pCommand); + break; + + case eSmeCommandSetKey: + csr_release_command_set_key(pMac, pCommand); + break; + + default: + sms_log(pMac, LOGW, " CSR abort standard command %d", + pCommand->command); + csr_release_command(pMac, pCommand); + break; + } + } +} + +void csr_roam_substate_change(tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate, + uint32_t sessionId) +{ + sms_log(pMac, LOG1, FL("CSR RoamSubstate: [ %s <== %s ]"), + mac_trace_getcsr_roam_sub_state(NewSubstate), + mac_trace_getcsr_roam_sub_state(pMac->roam.curSubState[sessionId])); + if (pMac->roam.curSubState[sessionId] == NewSubstate) { + return; + } + pMac->roam.curSubState[sessionId] = NewSubstate; +} + +eCsrRoamState csr_roam_state_change(tpAniSirGlobal pMac, + eCsrRoamState NewRoamState, uint8_t sessionId) +{ + eCsrRoamState PreviousState; + + sms_log(pMac, LOG1, FL("CSR RoamState[%hu]: [ %s <== %s ]"), sessionId, + mac_trace_getcsr_roam_state(NewRoamState), + mac_trace_getcsr_roam_state(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)) { + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + sessionId); + } + + pMac->roam.curState[sessionId] = NewRoamState; + } + return PreviousState; +} + +void csr_assign_rssi_for_category(tpAniSirGlobal pMac, int8_t bestApRssi, + uint8_t catOffset) +{ + int i; + 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 init_config_param(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 = false; + pMac->roam.configParam.Is11dSupportEnabledOriginal = false; + pMac->roam.configParam.Is11eSupportEnabled = true; + pMac->roam.configParam.Is11hSupportEnabled = true; + pMac->roam.configParam.RTSThreshold = 2346; + pMac->roam.configParam.shortSlotTime = true; + pMac->roam.configParam.WMMSupportMode = eCsrRoamWmmAuto; + pMac->roam.configParam.ProprietaryRatesEnabled = true; + pMac->roam.configParam.TxRate = eCSR_TX_RATE_AUTO; + 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; + } + csr_assign_rssi_for_category(pMac, CSR_BEST_RSSI_VALUE, + CSR_DEFAULT_RSSI_DB_GAP); + pMac->roam.configParam.nRoamingTime = CSR_DEFAULT_ROAMING_TIME; + pMac->roam.configParam.fSupplicantCountryCodeHasPriority = 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; +#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.nNumStaChanCombinedConc = + CSR_NUM_STA_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumP2PChanCombinedConc = + CSR_NUM_P2P_CHAN_COMBINED_CONC; +#endif + 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.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 = 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 csr_get_current_band(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 + */ +CDF_STATUS csr_flush_roam_scan_roam_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + /* Free up the memory first (if required) */ + if (NULL != + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + ChannelList) { + cdf_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 + */ +CDF_STATUS csr_flush_cfg_bg_scan_roam_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + /* Free up the memory first (if required) */ + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + cdf_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 + */ +CDF_STATUS csr_create_bg_scan_roam_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, + const uint8_t *pChannelList, + const uint8_t numChannels) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = numChannels; + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = + cdf_mem_malloc(pNeighborRoamInfo->cfgParams.channelInfo. + numOfChannels); + + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + sms_log(pMac, LOGE, + FL("Memory Allocation for CFG Channel List failed")); + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0; + return CDF_STATUS_E_NOMEM; + } + + /* Update the roam global structure */ + cdf_mem_copy(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pChannelList, + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); + 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 + */ +CDF_STATUS csr_create_roam_scan_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t *pChannelList, + uint8_t numChannels, + const eCsrBand eBand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo + = &pMac->roam.neighborRoamInfo[sessionId]; + uint8_t outNumChannels = 0; + uint8_t inNumChannels = numChannels; + uint8_t *inPtr = pChannelList; + uint8_t i = 0; + uint8_t ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t tmpChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 }; + uint8_t 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) { + csr_neighbor_roam_merge_channel_lists(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 (CDS_IS_CHANNEL_24GHZ(inPtr[i]) + && csr_roam_is_channel_valid(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 (CDS_IS_CHANNEL_5GHZ(inPtr[i]) && + csr_roam_is_channel_valid(pMac, inPtr[i]) && + !CDS_IS_DFS_CH(inPtr[i])) { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + } else if (eCSR_BAND_ALL == eBand) { + for (i = 0; i < inNumChannels; i++) { + if (csr_roam_is_channel_valid(pMac, inPtr[i]) && + !CDS_IS_DFS_CH(inPtr[i])) { + ChannelList[outNumChannels++] = inPtr[i]; + } + } + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "Invalid band, No operation carried out (Band %d)", + eBand); + return CDF_STATUS_E_INVAL; + } + /* + * 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)) { + csr_neighbor_roam_channels_filter_by_current_band(pMac, + sessionId, + ChannelList, + outNumChannels, + tmpChannelList, + &outNumChannels); + cdf_mem_copy(ChannelList, tmpChannelList, outNumChannels); + } + /* Prepare final roam scan channel list */ + if (outNumChannels) { + /* Clear the channel list first */ + if (NULL != currChannelListInfo->ChannelList) { + cdf_mem_free(currChannelListInfo->ChannelList); + currChannelListInfo->ChannelList = NULL; + currChannelListInfo->numOfChannels = 0; + } + currChannelListInfo->ChannelList + = cdf_mem_malloc(outNumChannels * sizeof(uint8_t)); + if (NULL == currChannelListInfo->ChannelList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "Failed to allocate memory for roam scan channel list"); + currChannelListInfo->numOfChannels = 0; + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(currChannelListInfo->ChannelList, + ChannelList, outNumChannels); + } + return status; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +CDF_STATUS csr_set_band(tHalHandle hHal, uint8_t sessionId, eCsrBand eBand) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "failed to set band cfg80211 = %u, band = %u", + pMac->roam.configParam.uCfgDot11Mode, eBand); + return CDF_STATUS_E_INVAL; + } + 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "failed to set band dot11mode = %u, band = %u", + pMac->roam.configParam.uCfgDot11Mode, eBand); + return CDF_STATUS_E_INVAL; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; + + status = csr_get_channel_and_power_list(pMac); + if (CDF_STATUS_SUCCESS == status) + csr_apply_channel_and_power_list(pMac); + return status; +} + +/* The funcns csr_convert_cb_ini_value_to_phy_cb_state and csr_convert_phy_cb_state_to_ini_value 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 csr_change_default_config_param using this funcn + * The enum values are as follows: + * PHY_SINGLE_CHANNEL_CENTERED = 0 + * PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1 + * PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3 + */ +ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_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; +} + +uint32_t csr_convert_phy_cb_state_to_ini_value(ePhyChanBondState phyCbState) +{ + + uint32_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; +} + +CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, + tCsrConfigParam *pParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (pParam) { + pMac->roam.configParam.WMMSupportMode = pParam->WMMSupportMode; + cfg_set_int(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) { + sms_log(pMac, LOGW, + "Invalid CB value from ini in 2.4GHz band %d, CB DISABLED", + pParam->channelBondingMode24GHz); + } + pMac->roam.configParam.channelBondingMode24GHz = + csr_convert_cb_ini_value_to_phy_cb_state(pParam-> + channelBondingMode24GHz); + if (pParam->channelBondingMode5GHz > MAX_CB_VALUE_IN_INI) { + sms_log(pMac, LOGW, + "Invalid CB value from ini in 5GHz band %d, CB DISABLED", + pParam->channelBondingMode5GHz); + } + pMac->roam.configParam.channelBondingMode5GHz = + csr_convert_cb_ini_value_to_phy_cb_state(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.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; + cfg_set_int(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME, + pParam->nActiveMaxChnTime); + } + if (pParam->nActiveMinChnTime) { + pMac->roam.configParam.nActiveMinChnTime = + pParam->nActiveMinChnTime; + cfg_set_int(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, + pParam->nActiveMinChnTime); + } + if (pParam->nPassiveMaxChnTime) { + pMac->roam.configParam.nPassiveMaxChnTime = + pParam->nPassiveMaxChnTime; + cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pParam->nPassiveMaxChnTime); + } + if (pParam->nPassiveMinChnTime) { + pMac->roam.configParam.nPassiveMinChnTime = + pParam->nPassiveMinChnTime; + cfg_set_int(pMac, WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME, + pParam->nPassiveMinChnTime); + } +#ifdef WLAN_AP_STA_CONCURRENCY + if (pParam->nActiveMaxChnTimeConc) { + pMac->roam.configParam.nActiveMaxChnTimeConc = + pParam->nActiveMaxChnTimeConc; + } + if (pParam->nActiveMinChnTimeConc) { + pMac->roam.configParam.nActiveMinChnTimeConc = + pParam->nActiveMinChnTimeConc; + } + if (pParam->nPassiveMaxChnTimeConc) { + pMac->roam.configParam.nPassiveMaxChnTimeConc = + pParam->nPassiveMaxChnTimeConc; + } + if (pParam->nPassiveMinChnTimeConc) { + pMac->roam.configParam.nPassiveMinChnTimeConc = + pParam->nPassiveMinChnTimeConc; + } + if (pParam->nRestTimeConc) { + pMac->roam.configParam.nRestTimeConc = + pParam->nRestTimeConc; + } + if (pParam->nNumStaChanCombinedConc) { + pMac->roam.configParam.nNumStaChanCombinedConc = + pParam->nNumStaChanCombinedConc; + } + if (pParam->nNumP2PChanCombinedConc) { + pMac->roam.configParam.nNumP2PChanCombinedConc = + pParam->nNumP2PChanCombinedConc; + } +#endif + pMac->roam.configParam.eBand = pParam->eBand; + pMac->roam.configParam.uCfgDot11Mode = + csr_get_cfg_dot11_mode_from_csr_phy_mode(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; + } + + csr_assign_rssi_for_category(pMac, CSR_BEST_RSSI_VALUE, + pParam->bCatRssiOffset); + pMac->roam.configParam.nRoamingTime = pParam->nRoamingTime; + pMac->roam.configParam.fSupplicantCountryCodeHasPriority = + pParam->fSupplicantCountryCodeHasPriority; + pMac->roam.configParam.vccRssiThreshold = + pParam->vccRssiThreshold; + pMac->roam.configParam.vccUlMacLossThreshold = + pParam->vccUlMacLossThreshold; + pMac->roam.configParam.statsReqPeriodicity = + pParam->statsReqPeriodicity; + pMac->roam.configParam.statsReqPeriodicityInPS = + pParam->statsReqPeriodicityInPS; + /* Assign this before calling csr_init11d_info */ + pMac->roam.configParam.nTxPowerCap = pParam->nTxPowerCap; + if (csr_is11d_supported(pMac)) { + status = csr_init11d_info(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 (csr_is11h_supported(pMac) && !csr_is11d_supported(pMac)) { + csr_init_channel_power_list(pMac, &pParam->Csr11dinfo); + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + cdf_mem_copy(&pMac->roam.configParam.csr11rConfig, + &pParam->csr11rConfig, + sizeof(tCsr11rConfigParams)); + sms_log(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.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 + pMac->roam.configParam.isRoamOffloadScanEnabled = + pParam->isRoamOffloadScanEnabled; + pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = + pParam->bFastRoamInConIniFeatureEnabled; +#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 + cdf_mem_copy(&pMac->roam.configParam.neighborRoamConfig, + &pParam->neighborRoamConfig, + sizeof(tCsrNeighborRoamConfigParams)); + sms_log(pMac, LOG1, "nNeighborScanTimerPerioid = %d", + pMac->roam.configParam.neighborRoamConfig. + nNeighborScanTimerPeriod); + sms_log(pMac, LOG1, "nNeighborLookupRssiThreshold = %d", + pMac->roam.configParam.neighborRoamConfig. + nNeighborLookupRssiThreshold); + sms_log(pMac, LOG1, "nOpportunisticThresholdDiff = %d", + pMac->roam.configParam.neighborRoamConfig. + nOpportunisticThresholdDiff); + sms_log(pMac, LOG1, "nRoamRescanRssiDiff = %d", + pMac->roam.configParam.neighborRoamConfig. + nRoamRescanRssiDiff); + sms_log(pMac, LOG1, "nNeighborScanMinChanTime = %d", + pMac->roam.configParam.neighborRoamConfig. + nNeighborScanMinChanTime); + sms_log(pMac, LOG1, "nNeighborScanMaxChanTime = %d", + pMac->roam.configParam.neighborRoamConfig. + nNeighborScanMaxChanTime); + sms_log(pMac, LOG1, "nMaxNeighborRetries = %d", + pMac->roam.configParam.neighborRoamConfig. + nMaxNeighborRetries); + sms_log(pMac, LOG1, "nNeighborResultsRefreshPeriod = %d", + pMac->roam.configParam.neighborRoamConfig. + nNeighborResultsRefreshPeriod); + sms_log(pMac, LOG1, "nEmptyScanRefreshPeriod = %d", + pMac->roam.configParam.neighborRoamConfig. + nEmptyScanRefreshPeriod); + { + int i; + sms_log(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++) { + sms_log(pMac, LOG1, "%d ", + pMac->roam.configParam. + neighborRoamConfig.neighborScanChanList. + channelList[i]); + } + } + sms_log(pMac, LOG1, "nRoamBmissFirstBcnt = %d", + pMac->roam.configParam.neighborRoamConfig. + nRoamBmissFirstBcnt); + sms_log(pMac, LOG1, "nRoamBmissFinalBcnt = %d", + pMac->roam.configParam.neighborRoamConfig. + nRoamBmissFinalBcnt); + sms_log(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.max_scan_count = pParam->max_scan_count; + /* This parameter is not available in cfg and not passed from upper layers. Instead it is initialized here + * This paramtere 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.ignore_peer_erp_info = + pParam->ignore_peer_erp_info; + pMac->roam.configParam.isAmsduSupportInAMPDU = + pParam->isAmsduSupportInAMPDU; + pMac->roam.configParam.nSelect5GHzMargin = + pParam->nSelect5GHzMargin; + 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->roam.configParam.sendDeauthBeforeCon = + pParam->sendDeauthBeforeCon; + + pMac->enable_dot11p = pParam->enable_dot11p; + } + + return status; +} + +CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) +{ + int i; + tCsrConfig *cfg_params = &pMac->roam.configParam; + + if (!pParam) + return CDF_STATUS_E_INVAL; + + pParam->WMMSupportMode = cfg_params->WMMSupportMode; + pParam->Is11eSupportEnabled = cfg_params->Is11eSupportEnabled; + pParam->FragmentationThreshold = cfg_params->FragmentationThreshold; + pParam->Is11dSupportEnabled = cfg_params->Is11dSupportEnabled; + pParam->Is11dSupportEnabledOriginal = + cfg_params->Is11dSupportEnabledOriginal; + pParam->Is11hSupportEnabled = cfg_params->Is11hSupportEnabled; + pParam->channelBondingMode24GHz = csr_convert_phy_cb_state_to_ini_value( + cfg_params->channelBondingMode24GHz); + pParam->channelBondingMode5GHz = csr_convert_phy_cb_state_to_ini_value( + cfg_params->channelBondingMode5GHz); + pParam->RTSThreshold = cfg_params->RTSThreshold; + pParam->phyMode = cfg_params->phyMode; + pParam->shortSlotTime = cfg_params->shortSlotTime; + pParam->HeartbeatThresh24 = cfg_params->HeartbeatThresh24; + pParam->HeartbeatThresh50 = cfg_params->HeartbeatThresh50; + pParam->ProprietaryRatesEnabled = cfg_params->ProprietaryRatesEnabled; + pParam->TxRate = cfg_params->TxRate; + pParam->AdHocChannel24 = cfg_params->AdHocChannel24; + pParam->AdHocChannel5G = cfg_params->AdHocChannel5G; + pParam->bandCapability = cfg_params->bandCapability; + pParam->cbChoice = cfg_params->cbChoice; + pParam->nActiveMaxChnTime = cfg_params->nActiveMaxChnTime; + pParam->nActiveMinChnTime = cfg_params->nActiveMinChnTime; + pParam->nPassiveMaxChnTime = cfg_params->nPassiveMaxChnTime; + pParam->nPassiveMinChnTime = cfg_params->nPassiveMinChnTime; +#ifdef WLAN_AP_STA_CONCURRENCY + pParam->nActiveMaxChnTimeConc = cfg_params->nActiveMaxChnTimeConc; + pParam->nActiveMinChnTimeConc = cfg_params->nActiveMinChnTimeConc; + pParam->nPassiveMaxChnTimeConc = cfg_params->nPassiveMaxChnTimeConc; + pParam->nPassiveMinChnTimeConc = cfg_params->nPassiveMinChnTimeConc; + pParam->nRestTimeConc = cfg_params->nRestTimeConc; + pParam->nNumStaChanCombinedConc = cfg_params->nNumStaChanCombinedConc; + pParam->nNumP2PChanCombinedConc = cfg_params->nNumP2PChanCombinedConc; +#endif + pParam->eBand = cfg_params->eBand; + pParam->nScanResultAgeCount = cfg_params->agingCount; + pParam->scanAgeTimeNCNPS = cfg_params->scanAgeTimeNCNPS; + pParam->scanAgeTimeNCPS = cfg_params->scanAgeTimeNCPS; + pParam->scanAgeTimeCNPS = cfg_params->scanAgeTimeCNPS; + pParam->scanAgeTimeCPS = cfg_params->scanAgeTimeCPS; + pParam->bCatRssiOffset = cfg_params->bCatRssiOffset; + pParam->nRoamingTime = cfg_params->nRoamingTime; + pParam->fSupplicantCountryCodeHasPriority = + cfg_params->fSupplicantCountryCodeHasPriority; + pParam->vccRssiThreshold = cfg_params->vccRssiThreshold; + pParam->vccUlMacLossThreshold = cfg_params->vccUlMacLossThreshold; + pParam->nTxPowerCap = cfg_params->nTxPowerCap; + pParam->statsReqPeriodicity = cfg_params->statsReqPeriodicity; + pParam->statsReqPeriodicityInPS = cfg_params->statsReqPeriodicityInPS; + pParam->addTSWhenACMIsOff = cfg_params->addTSWhenACMIsOff; + pParam->fValidateList = cfg_params->fValidateList; + pParam->fEnableBypass11d = pMac->scan.fEnableBypass11d; + pParam->fEnableDFSChnlScan = pMac->scan.fEnableDFSChnlScan; + pParam->fScanTwice = cfg_params->fScanTwice; + pParam->fFirstScanOnly2GChnl = pMac->scan.fFirstScanOnly2GChnl; + pParam->fEnableMCCMode = cfg_params->fenableMCCMode; + pParam->fAllowMCCGODiffBI = cfg_params->fAllowMCCGODiffBI; + pParam->scanCfgAgingTime = pMac->scan.scanResultCfgAgingTime; +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + cdf_mem_copy(&pParam->neighborRoamConfig, + &cfg_params->neighborRoamConfig, + sizeof(tCsrNeighborRoamConfigParams)); +#endif +#ifdef WLAN_FEATURE_11AC + pParam->nVhtChannelWidth = cfg_params->nVhtChannelWidth; + pParam->enableTxBF = cfg_params->txBFEnable; + pParam->txBFCsnValue = cfg_params->txBFCsnValue; + pParam->enableMuBformee = cfg_params->txMuBformee; + pParam->enableVhtFor24GHz = cfg_params->enableVhtFor24GHz; + pParam->ignore_peer_erp_info = cfg_params->ignore_peer_erp_info; + pParam->enable2x2 = cfg_params->enable2x2; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + cdf_mem_copy(&cfg_params->csr11rConfig, &pParam->csr11rConfig, + sizeof(tCsr11rConfigParams)); +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pParam->isFastTransitionEnabled = cfg_params->isFastTransitionEnabled; + pParam->RoamRssiDiff = cfg_params->RoamRssiDiff; + pParam->nRoamPrefer5GHz = cfg_params->nRoamPrefer5GHz; + pParam->nRoamIntraBand = cfg_params->nRoamIntraBand; + pParam->isWESModeEnabled = cfg_params->isWESModeEnabled; + pParam->nProbes = cfg_params->nProbes; + pParam->nRoamScanHomeAwayTime = cfg_params->nRoamScanHomeAwayTime; +#endif + pParam->isRoamOffloadScanEnabled = cfg_params->isRoamOffloadScanEnabled; + pParam->bFastRoamInConIniFeatureEnabled = + cfg_params->bFastRoamInConIniFeatureEnabled; +#ifdef FEATURE_WLAN_LFR + pParam->isFastRoamIniFeatureEnabled = + cfg_params->isFastRoamIniFeatureEnabled; +#endif +#ifdef FEATURE_WLAN_ESE + pParam->isEseIniFeatureEnabled = cfg_params->isEseIniFeatureEnabled; +#endif +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + cdf_mem_copy(&pParam->neighborRoamConfig, + &cfg_params->neighborRoamConfig, + sizeof(tCsrNeighborRoamConfigParams)); + sms_log(pMac, LOG1, + FL("Num of Channels in CFG Channel List: %d"), + cfg_params->neighborRoamConfig. + neighborScanChanList.numChannels); + for (i = 0; i < cfg_params->neighborRoamConfig. + neighborScanChanList.numChannels; i++) { + sms_log(pMac, LOG1, "%d ", + cfg_params->neighborRoamConfig. + neighborScanChanList.channelList[i]); + } +#endif + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pParam->cc_switch_mode = cfg_params->cc_switch_mode; +#endif + pParam->enableTxLdpc = cfg_params->txLdpcEnable; + pParam->isAmsduSupportInAMPDU = cfg_params->isAmsduSupportInAMPDU; + pParam->nSelect5GHzMargin = cfg_params->nSelect5GHzMargin; + pParam->isCoalesingInIBSSAllowed = cfg_params->isCoalesingInIBSSAllowed; + pParam->allowDFSChannelRoam = cfg_params->allowDFSChannelRoam; + pParam->nInitialDwellTime = cfg_params->nInitialDwellTime; + pParam->initial_scan_no_dfs_chnl = cfg_params->initial_scan_no_dfs_chnl; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + pParam->isRoamOffloadEnabled = cfg_params->isRoamOffloadEnabled; +#endif + pParam->enable_dot11p = pMac->enable_dot11p; + csr_set_channels(pMac, pParam); + pParam->obssEnabled = cfg_params->obssEnabled; + pParam->conc_custom_rule1 = cfg_params->conc_custom_rule1; + pParam->conc_custom_rule2 = cfg_params->conc_custom_rule2; + pParam->is_sta_connection_in_5gz_enabled = + cfg_params->is_sta_connection_in_5gz_enabled; + pParam->sendDeauthBeforeCon = + cfg_params->sendDeauthBeforeCon; + pParam->max_scan_count = pMac->scan.max_scan_count; + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_set_phy_mode(tHalHandle hHal, uint32_t phyMode, eCsrBand eBand, + bool *pfRestartNeeded) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + bool fRestartNeeded = false; + eCsrPhyMode newPhyMode = eCSR_DOT11_MODE_AUTO; + if (eCSR_BAND_24 == eBand) { + if (CSR_IS_RADIO_A_ONLY(pMac)) + goto end; + if (eCSR_DOT11_MODE_11a & phyMode) + goto end; + } + if (eCSR_BAND_5G == eBand) { + if (CSR_IS_RADIO_BG_ONLY(pMac)) + goto end; + if ((eCSR_DOT11_MODE_11b & phyMode) + || (eCSR_DOT11_MODE_11b_ONLY & phyMode) + || (eCSR_DOT11_MODE_11g & phyMode) + || (eCSR_DOT11_MODE_11g_ONLY & phyMode)) + goto end; + } + 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) + goto end; + newPhyMode = eCSR_DOT11_MODE_11n_ONLY; + } else if (eCSR_DOT11_MODE_11g_ONLY & phyMode) { + if (eCSR_DOT11_MODE_11g_ONLY != phyMode) + goto end; + if (eCSR_BAND_5G == eBand) + goto end; + 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) + goto end; + if (eCSR_BAND_5G == eBand) + goto end; + 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 + goto end; + } 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 */ + sms_log(pMac, LOGE, + FL("can't recognize phymode 0x%08X"), + phyMode); + newPhyMode = eCSR_DOT11_MODE_AUTO; + } + } + /* Done validating */ + status = CDF_STATUS_SUCCESS; + /* Now we need to check whether a restart is needed. */ + if (eBand != pMac->roam.configParam.eBand) { + fRestartNeeded = true; + goto end; + } + if (newPhyMode != pMac->roam.configParam.phyMode) { + fRestartNeeded = true; + goto end; + } +end: + if (CDF_IS_STATUS_SUCCESS(status)) { + pMac->roam.configParam.eBand = eBand; + pMac->roam.configParam.phyMode = newPhyMode; + if (pfRestartNeeded) + *pfRestartNeeded = fRestartNeeded; + } + return status; +} + +/** + * csr_prune_ch_list() - prunes the channel list to keep only a type of channels + * @ch_lst: existing channel list + * @is_24_GHz: indicates if 2.5 GHz or 5 GHz channels are required + * + * Return: void + */ +void csr_prune_ch_list(tCsrChannel *ch_lst, bool is_24_GHz) +{ + uint8_t idx = 0, num_channels = 0; + for ( ; idx < ch_lst->numChannels; idx++) { + if (is_24_GHz) { + if (CDS_IS_CHANNEL_24GHZ(ch_lst->channelList[idx])) { + ch_lst->channelList[num_channels] = + ch_lst->channelList[idx]; + num_channels++; + } + } else { + if (CDS_IS_CHANNEL_5GHZ(ch_lst->channelList[idx])) { + ch_lst->channelList[num_channels] = + ch_lst->channelList[idx]; + num_channels++; + } + } + } + /* + * Cleanup the rest of channels. Note we only need to clean up the + * channels if we had to trim the list. Calling cdf_mem_set() with a 0 + * size is going to throw asserts on the debug builds so let's be a bit + * smarter about that. Zero out the reset of the channels only if we + * need to. The amount of memory to clear is the number of channesl that + * we trimmed (ch_lst->numChannels - num_channels) times the size of a + * channel in the structure. + */ + if (ch_lst->numChannels > num_channels) { + cdf_mem_set(&ch_lst->channelList[num_channels], + sizeof(ch_lst->channelList[0]) * + (ch_lst->numChannels - num_channels), 0); + } + ch_lst->numChannels = num_channels; +} + +/** + * csr_prune_channel_list_for_mode() - prunes the channel list + * @mac_ctx: global mac context + * @ch_lst: existing channel list + * + * Prunes the channel list according to band stored in mac_ctx + * + * Return: void + */ +void csr_prune_channel_list_for_mode(tpAniSirGlobal mac_ctx, + tCsrChannel *ch_lst) +{ + /* for dual band NICs, don't need to trim the channel list.... */ + if (CSR_IS_OPEARTING_DUAL_BAND(mac_ctx)) + return; + /* + * 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(mac_ctx)) + csr_prune_ch_list(ch_lst, true); + else if (CSR_IS_5G_BAND_ONLY(mac_ctx)) + csr_prune_ch_list(ch_lst, false); +} + +#define INFRA_AP_DEFAULT_CHANNEL 6 +CDF_STATUS csr_is_valid_channel(tpAniSirGlobal pMac, uint8_t chnNum) +{ + uint8_t index = 0; + CDF_STATUS status = CDF_STATUS_E_NOSUPPORT; + + /* regulatory check */ + for (index = 0; index < pMac->scan.base_channels.numChannels; + index++) { + if (pMac->scan.base_channels.channelList[index] == chnNum) { + status = CDF_STATUS_SUCCESS; + break; + } + } + + if (status == CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("channel %d is in dfs nol"), + chnNum); + status = CDF_STATUS_E_FAILURE; + break; + } + } + } + + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("channel %d is not available"), chnNum); + } + + return status; +} + +CDF_STATUS csr_get_channel_and_power_list(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t num20MHzChannelsFound = 0; + CDF_STATUS cdf_status; + uint8_t Index = 0; + uint8_t 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 */ + cdf_status = + cds_get_channel_list_with_power(pMac->scan.defaultPowerTable, + &num20MHzChannelsFound, + pMac->scan.defaultPowerTable40MHz, + &num40MHzChannelsFound); + if ((CDF_STATUS_SUCCESS != cdf_status) || (num20MHzChannelsFound == 0)) { + sms_log(pMac, LOGE, FL("failed to get channels ")); + status = CDF_STATUS_E_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.base_channels.channelList[Index] = + pMac->scan.defaultPowerTable[Index].chanId; + } + pMac->scan.base_channels.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; +} + +CDF_STATUS csr_apply_channel_and_power_list(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + csr_prune_channel_list_for_mode(pMac, &pMac->scan.base_channels); + csr_save_channel_power_for_band(pMac, false); + csr_save_channel_power_for_band(pMac, true); + /* Apply the base channel list, power info, and set the Country code... */ + csr_apply_channel_power_info_to_fw(pMac, + &pMac->scan.base_channels, + pMac->scan.countryCodeCurrent); + + csr_init_operating_classes((tHalHandle) pMac); + return status; +} + +CDF_STATUS csr_change_config_params(tpAniSirGlobal pMac, + tCsrUpdateConfigParam *pUpdateConfigParam) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsr11dinfo *ps11dinfo = NULL; + ps11dinfo = &pUpdateConfigParam->Csr11dinfo; + status = csr_init11d_info(pMac, ps11dinfo); + return status; +} + +static CDF_STATUS csr_init11d_info(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint8_t index; + uint32_t count = 0; + tSirMacChanInfo *pChanInfo; + tSirMacChanInfo *pChanInfoStart; + bool 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.base_channels.numChannels = + ps11dinfo->Channels.numChannels; + cdf_mem_copy(pMac->scan.base_channels.channelList, + ps11dinfo->Channels.channelList, + ps11dinfo->Channels.numChannels); + } else { + /* No change */ + return CDF_STATUS_SUCCESS; + } + /* legacy maintenance */ + + cdf_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 initilaize with default again */ + if (0 == pMac->scan.countryCodeCurrent[0]) { + cdf_mem_copy(pMac->scan.countryCodeCurrent, + ps11dinfo->countryCode, WNI_CFG_COUNTRY_CODE_LEN); + } + /* need to add the max power channel list */ + pChanInfo = + cdf_mem_malloc(sizeof(tSirMacChanInfo) * + WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (pChanInfo != NULL) { + cdf_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 = + CDF_MIN(ps11dinfo->ChnPower[index].maxtxPower, + pMac->roam.configParam.nTxPowerCap); + pChanInfo++; + count++; + } + if (count) { + csr_save_to_channel_power2_g_5_g(pMac, + count * + sizeof(tSirMacChanInfo), + pChanInfoStart); + } + cdf_mem_free(pChanInfoStart); + } + /* Only apply them to CFG when not in STOP state. Otherwise they will be applied later */ + if (CDF_IS_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... */ + csr_apply_channel_power_info_to_fw(pMac, + &pMac->scan. + base_channels, + pMac->scan. + countryCodeCurrent); + } + } + return status; +} + +/* Initialize the Channel + Power List in the local cache and in the CFG */ +CDF_STATUS csr_init_channel_power_list(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo) +{ + uint8_t index; + uint32_t count = 0; + tSirMacChanInfo *pChanInfo; + tSirMacChanInfo *pChanInfoStart; + + if (!ps11dinfo || !pMac) { + return CDF_STATUS_E_FAILURE; + } + + pChanInfo = + cdf_mem_malloc(sizeof(tSirMacChanInfo) * + WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (pChanInfo != NULL) { + cdf_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 = + CDF_MIN(ps11dinfo->ChnPower[index].maxtxPower, + pMac->roam.configParam.nTxPowerCap); + pChanInfo++; + count++; + } + if (count) { + csr_save_to_channel_power2_g_5_g(pMac, + count * + sizeof(tSirMacChanInfo), + pChanInfoStart); + } + cdf_mem_free(pChanInfoStart); + } + + return CDF_STATUS_SUCCESS; +} + +/* pCommand may be NULL */ +/* Pass in sessionId in case pCommand is NULL. sessionId is not used in case pCommand is not NULL. */ +void csr_roam_remove_duplicate_command(tpAniSirGlobal pMac, uint32_t sessionId, + tSmeCmd *pCommand, + eCsrRoamReason eRoamReason) +{ + tListElem *pEntry, *pNextEntry; + tSmeCmd *pDupCommand; + tDblLinkList localList; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return; + } + csr_ll_lock(&pMac->sme.smeCmdPendingList); + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK); + while (pEntry) { + pNextEntry = + csr_ll_next(&pMac->sme.smeCmdPendingList, pEntry, + LL_ACCESS_NOLOCK); + pDupCommand = GET_BASE_ADDR(pEntry, 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 ((pCommand && (pCommand->sessionId == pDupCommand->sessionId) + && ((pCommand->command == pDupCommand->command) && + /* + * This peermac check is requried for Softap/GO + * scenarios. For STA scenario below OR check will + * suffice as pCommand will always be NULL for STA + * scenarios + */ + (cdf_mem_compare + (pDupCommand->u.roamCmd.peerMac, + pCommand->u.roamCmd.peerMac, + CDF_MAC_ADDR_SIZE)) + && (pCommand->u.roamCmd.roamReason == + pDupCommand->u.roamCmd.roamReason + || eCsrForcedDisassoc == + pCommand->u.roamCmd.roamReason + || eCsrHddIssued == + pCommand->u.roamCmd.roamReason))) + || + /* below the pCommand is NULL */ + ((sessionId == pDupCommand->sessionId) && + (eSmeCommandRoam == pDupCommand->command) && + ((eCsrForcedDisassoc == eRoamReason) || + (eCsrHddIssued == eRoamReason)) + ) + ) { + sms_log(pMac, LOGW, FL(" roamReason = %d"), + pDupCommand->u.roamCmd.roamReason); + /* Remove the 'stale' roam command from the pending list... */ + if (csr_ll_remove_entry + (&pMac->sme.smeCmdPendingList, pEntry, + LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntry, + LL_ACCESS_NOLOCK); + } + } + pEntry = pNextEntry; + } + csr_ll_unlock(&pMac->sme.smeCmdPendingList); + + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pDupCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + /* Tell caller that the command is cancelled */ + csr_roam_call_callback(pMac, pDupCommand->sessionId, NULL, + pDupCommand->u.roamCmd.roamId, + eCSR_ROAM_CANCELLED, eCSR_ROAM_RESULT_NONE); + csr_release_command_roam(pMac, pDupCommand); + } + csr_ll_close(&localList); +} + +/** + * csr_roam_populate_channels() - Helper function to populate channels + * @beacon_ies: pointer to beacon ie + * @roam_info: Roaming related information + * @chan1: center freq 1 + * @chan2: center freq2 + * + * This function will issue populate chan1 and chan2 based on beacon ie + * + * Return: none. + */ +static void csr_roam_populate_channels(tDot11fBeaconIEs *beacon_ies, + tCsrRoamInfo *roam_info, + uint8_t *chan1, uint8_t *chan2) +{ + ePhyChanBondState phy_state; + if (beacon_ies->VHTOperation.present) { + *chan1 = beacon_ies->VHTOperation.chanCenterFreqSeg1; + *chan2 = beacon_ies->VHTOperation.chanCenterFreqSeg2; + roam_info->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; + + roam_info->chan_info.info = MODE_11NA_HT40; + } else { + *chan1 = beacon_ies->HTInfo.primaryChannel; + roam_info->chan_info.info = MODE_11NA_HT20; + } + *chan2 = 0; + } else { + *chan1 = 0; + *chan2 = 0; + roam_info->chan_info.info = MODE_11A; + } +} + +CDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamInfo *pRoamInfo, uint32_t roamId, + eRoamCmdStatus u1, eCsrRoamResult u2) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + uint32_t rssi = 0; + WLAN_HOST_DIAG_EVENT_DEF(connectionStatus, + host_event_wlan_status_payload_type); +#endif + tCsrRoamSession *pSession; + tDot11fBeaconIEs *beacon_ies = NULL; + uint8_t chan1, chan2; + + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + sms_log(pMac, LOGE, "Session ID:%d is not valid", sessionId); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (false == pSession->sessionActive) { + sms_log(pMac, LOG1, "%s Session is not Active", __func__); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG4, "Received RoamCmdStatus %d with Roam Result %d", u1, + u2); + + if (eCSR_ROAM_ASSOCIATION_COMPLETION == u1 && + eCSR_ROAM_RESULT_ASSOCIATED == u2 && pRoamInfo) { + sms_log(pMac, LOGW, + FL("Assoc complete result=%d status=%d reason=%d"), + u2, pRoamInfo->statusCode, pRoamInfo->reasonCode); + beacon_ies = cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ((NULL != beacon_ies) && (NULL != pRoamInfo->pBssDesc)) { + status = csr_parse_bss_description_ies( + (tHalHandle) pMac, pRoamInfo->pBssDesc, + beacon_ies); + csr_roam_populate_channels(beacon_ies, pRoamInfo, + &chan1, &chan2); + if (0 != chan1) + pRoamInfo->chan_info.band_center_freq1 = + cds_chan_to_freq(chan1); + else + pRoamInfo->chan_info.band_center_freq1 = 0; + if (0 != chan2) + pRoamInfo->chan_info.band_center_freq2 = + cds_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 = + cds_chan_to_freq(pRoamInfo->chan_info.chan_id); + pRoamInfo->chan_info.reg_info_1 = + (csr_get_cfg_max_tx_power(pMac, + pRoamInfo->chan_info.chan_id) << 16); + pRoamInfo->chan_info.reg_info_2 = + (csr_get_cfg_max_tx_power(pMac, + pRoamInfo->chan_info.chan_id) << 8); + cdf_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 + * csr_roam_call_callback before notifying a failed roam + * completion through csr_roam_complete. The latter in + * turn calls csr_roam_process_results which tries to + * once again call csr_roam_call_callback 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 = (uint8_t) 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 unknow. 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; + } + status = pSession->callback(pSession->pContext, pRoamInfo, + roamId, u1, u2); + } + /* + * EVENT_WLAN_STATUS: eCSR_ROAM_ASSOCIATION_COMPLETION, + * eCSR_ROAM_LOSTLINK, + * eCSR_ROAM_DISASSOCIATED, + */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + cdf_mem_set(&connectionStatus, + sizeof(host_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 (cfg_set_int(pMac, WNI_CFG_CURRENT_RSSI, + connectionStatus.rssi) == eSIR_FAILURE) + sms_log(pMac, LOGE, + FL("Can't pass WNI_CFG_CURRENT_RSSI to cfg")); + + connectionStatus.qosCapability = + pRoamInfo->u.pConnectedProfile->qosConnection; + connectionStatus.authType = + (uint8_t) diag_auth_type_from_csr_type( + pRoamInfo->u.pConnectedProfile->AuthType); + connectionStatus.encryptionType = + (uint8_t) diag_enc_type_from_csr_type( + pRoamInfo->u.pConnectedProfile->EncryptionType); + cdf_mem_copy(connectionStatus.ssid, + pRoamInfo->u.pConnectedProfile->SSID.ssId, 6); + + connectionStatus.reason = eCSR_REASON_UNSPECIFIED; + cdf_mem_copy(&pMac->sme.eventPayload, &connectionStatus, + sizeof(host_event_wlan_status_payload_type)); + WLAN_HOST_DIAG_EVENT_REPORT(&connectionStatus, + EVENT_WLAN_STATUS); + } + if ((eCSR_ROAM_MIC_ERROR_IND == u1) + || (eCSR_ROAM_RESULT_MIC_FAILURE == u2)) { + cdf_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(host_event_wlan_status_payload_type)); + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(pMac, + WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_MIC_ERROR; + WLAN_HOST_DIAG_EVENT_REPORT(&connectionStatus, + EVENT_WLAN_STATUS); + } + if (eCSR_ROAM_RESULT_FORCED == u2) { + cdf_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(host_event_wlan_status_payload_type)); + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(pMac, + WNI_CFG_CURRENT_RSSI, &rssi))) + connectionStatus.rssi = rssi; + + connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT; + connectionStatus.reason = eCSR_REASON_USER_REQUESTED; + WLAN_HOST_DIAG_EVENT_REPORT(&connectionStatus, + EVENT_WLAN_STATUS); + } + if (eCSR_ROAM_RESULT_DISASSOC_IND == u2) { + cdf_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(host_event_wlan_status_payload_type)); + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(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_HOST_DIAG_EVENT_REPORT(&connectionStatus, + EVENT_WLAN_STATUS); + } + if (eCSR_ROAM_RESULT_DEAUTH_IND == u2) { + cdf_mem_copy(&connectionStatus, &pMac->sme.eventPayload, + sizeof(host_event_wlan_status_payload_type)); + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(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_HOST_DIAG_EVENT_REPORT(&connectionStatus, + EVENT_WLAN_STATUS); + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + return status; +} + +/* Returns whether handoff is currently in progress or not */ +bool csr_roam_is_handoff_in_progress(tpAniSirGlobal pMac, uint8_t sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csr_neighbor_roam_is_handoff_in_progress(pMac, sessionId); +#else + return false; +#endif +} + +CDF_STATUS csr_roam_issue_disassociate(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamSubState NewSubstate, + bool fMICFailure) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct cdf_mac_addr bssId = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + uint16_t reasonCode; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 ((csr_roam_is_handoff_in_progress(pMac, sessionId)) && + (NewSubstate != eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF)) { + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + cdf_copy_macaddr(&bssId, + pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs. + bssid); + } else +#endif + if (pSession->pConnectBssDesc) { + cdf_mem_copy(&bssId.bytes, pSession->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + } + + sms_log(pMac, LOG2, + FL("CSR Attempting to Disassociate Bssid=" MAC_ADDRESS_STR + " subState = %s reason=%d"), MAC_ADDR_ARRAY(bssId.bytes), + mac_trace_getcsr_roam_sub_state(NewSubstate), reasonCode); + + csr_roam_substate_change(pMac, NewSubstate, sessionId); + + status = csr_send_mb_disassoc_req_msg(pMac, sessionId, bssId.bytes, + reasonCode); + + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_link_down(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_qos_csr_event_ind(pMac, (uint8_t) sessionId, + SME_QOS_CSR_DISCONNECT_REQ, NULL); + } +#endif + } else { + sms_log(pMac, LOGW, + FL("csr_send_mb_disassoc_req_msg failed with status %d"), + status); + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn csr_roam_issue_disassociate_sta_cmd + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_issue_disassociate_sta_cmd(tpAniSirGlobal pMac, + uint32_t sessionId, + const uint8_t *pPeerMacAddr, + uint32_t reason) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + + do { + pCommand = csr_get_command_buffer(pMac); + if (!pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + break; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.roamCmd.roamReason = eCsrForcedDisassocSta; + cdf_mem_copy(pCommand->u.roamCmd.peerMac, pPeerMacAddr, 6); + pCommand->u.roamCmd.reason = (tSirMacReasonCodes) reason; + status = csr_queue_sme_command(pMac, pCommand, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } while (0); + + return status; +} + +/** + * csr_roam_issue_deauthSta() - delete a associated station + * @sessionId: Session Id for Soft AP + * @pDelStaParams: Pointer to parameters of the station to deauthenticate + * + * CSR function that HDD calls to delete a associated station + * + * Return: CDF_STATUS_SUCCESS on success or another CDF_STATUS_* on error + */ +CDF_STATUS csr_roam_issue_deauth_sta_cmd(tpAniSirGlobal pMac, + uint32_t sessionId, + struct tagCsrDelStaParams *pDelStaParams) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + + do { + pCommand = csr_get_command_buffer(pMac); + if (!pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + break; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta; + cdf_mem_copy(pCommand->u.roamCmd.peerMac, + pDelStaParams->peerMacAddr.bytes, + sizeof(tSirMacAddr)); + pCommand->u.roamCmd.reason = + (tSirMacReasonCodes)pDelStaParams->reason_code; + status = csr_queue_sme_command(pMac, pCommand, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } while (0); + + return status; +} + +CDF_STATUS +csr_roam_issue_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t sessionId, + bool bEnable) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + struct cdf_mac_addr bssId = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, + "csr_roam_issue_tkip_counter_measures:CSR Session not found"); + return status; + } + if (pSession->pConnectBssDesc) { + cdf_mem_copy(bssId.bytes, pSession->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + } else { + sms_log(pMac, LOGE, + "csr_roam_issue_tkip_counter_measures:Connected BSS Description in CSR Session not found"); + return status; + } + sms_log(pMac, LOG2, + "CSR issuing tkip counter measures for Bssid = " MAC_ADDRESS_STR + ", Enable = %d", MAC_ADDR_ARRAY(bssId.bytes), bEnable); + status = + csr_send_mb_tkip_counter_measures_req_msg(pMac, sessionId, + bEnable, bssId.bytes); + return status; +} + +CDF_STATUS +csr_roam_get_associated_stas(tpAniSirGlobal pMac, uint32_t sessionId, + CDF_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, uint8_t *pAssocStasBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct cdf_mac_addr bssId = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, + "csr_roam_get_associated_stas:CSR Session not found"); + return status; + } + if (pSession->pConnectBssDesc) { + cdf_mem_copy(bssId.bytes, pSession->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + } else { + sms_log(pMac, LOGE, + "csr_roam_get_associated_stas:Connected BSS Description in CSR Session not found"); + return status; + } + sms_log(pMac, LOG2, + "CSR getting associated stations for Bssid = " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId.bytes)); + status = + csr_send_mb_get_associated_stas_req_msg(pMac, sessionId, modId, + bssId.bytes, + pUsrContext, + pfnSapEventCallback, + pAssocStasBuf); + return status; +} + +CDF_STATUS +csr_roam_get_wps_session_overlap(tpAniSirGlobal pMac, uint32_t sessionId, + void *pUsrContext, void *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct cdf_mac_addr bssId = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, + "csr_roam_get_wps_session_overlap:CSR Session not found"); + return status; + } + if (pSession->pConnectBssDesc) { + cdf_mem_copy(bssId.bytes, pSession->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + } else { + sms_log(pMac, LOGE, + "csr_roam_get_wps_session_overlap:Connected BSS Description in CSR Session not found"); + return status; + } + sms_log(pMac, LOG2, + "CSR getting WPS Session Overlap for Bssid = " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId.bytes)); + + status = + csr_send_mb_get_wpspbc_sessions(pMac, sessionId, bssId.bytes, pUsrContext, + pfnSapEventCallback, pRemoveMac); + + return status; +} + +CDF_STATUS csr_roam_issue_deauth(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamSubState NewSubstate) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct cdf_mac_addr bssId = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pSession->pConnectBssDesc) { + cdf_mem_copy(bssId.bytes, pSession->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + } + sms_log(pMac, LOG2, "CSR Attempting to Deauth Bssid= " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssId.bytes)); + csr_roam_substate_change(pMac, NewSubstate, sessionId); + + status = + csr_send_mb_deauth_req_msg(pMac, sessionId, bssId.bytes, + eSIR_MAC_DEAUTH_LEAVING_BSS_REASON); + if (CDF_IS_STATUS_SUCCESS(status)) + csr_roam_link_down(pMac, sessionId); + else { + sms_log(pMac, LOGE, + FL + ("csr_send_mb_deauth_req_msg failed with status %d Session ID: %d" + MAC_ADDRESS_STR), status, sessionId, + MAC_ADDR_ARRAY(bssId.bytes)); + } + + return status; +} + +CDF_STATUS csr_roam_save_connected_bss_desc(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + uint32_t size; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_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) { + csr_free_connect_bss_desc(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 */ + csr_free_connect_bss_desc(pMac, sessionId); + } + } + if (NULL == pSession->pConnectBssDesc) { + pSession->pConnectBssDesc = cdf_mem_malloc(size); + } + if (NULL == pSession->pConnectBssDesc) + status = CDF_STATUS_E_NOMEM; + else + cdf_mem_copy(pSession->pConnectBssDesc, pBssDesc, size); + } + return status; +} + +CDF_STATUS csr_roam_prepare_bss_config(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes) +{ + eCsrCfgDot11Mode cfgDot11Mode; + CDF_ASSERT(pIes != NULL); + if (pIes == NULL) + return CDF_STATUS_E_FAILURE; + + cdf_mem_copy(&pBssConfig->BssCap, &pBssDesc->capabilityInfo, + sizeof(tSirMacCapabilityInfo)); + /* get qos */ + pBssConfig->qosType = csr_get_qo_s_from_bss_desc(pMac, pBssDesc, pIes); + /* get SSID */ + if (pIes->SSID.present) { + cdf_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 (csr_is_nullssid(pBssConfig->SSID.ssId, pBssConfig->SSID.length)) { + sms_log(pMac, LOGW, FL("BSS desc SSID is a wild card")); + /* Return failed if profile doesn't have an SSID either. */ + if (pProfile->SSIDs.numOfSSIDs == 0) { + sms_log(pMac, LOGW, + FL("BSS desc and profile doesn't have SSID")); + return CDF_STATUS_E_FAILURE; + } + } + if (CDS_IS_CHANNEL_5GHZ(pBssDesc->channelId)) + pBssConfig->eBand = eCSR_BAND_5G; + else + pBssConfig->eBand = eCSR_BAND_24; + /* phymode */ + if (csr_is_phy_mode_match(pMac, pProfile->phyMode, pBssDesc, + pProfile, &cfgDot11Mode, pIes)) { + pBssConfig->uCfgDot11Mode = cfgDot11Mode; + } else { + sms_log(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 = false; + else + pBssConfig->f11hSupport = + pMac->roam.configParam.Is11hSupportEnabled; + /* power constraint */ + pBssConfig->uPowerLimit = + csr_get11h_power_constraint(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 = + CDF_MAX(10 * pBssDesc->beaconInterval, + CSR_JOIN_FAILURE_TIMEOUT_MIN); + else + pBssConfig->uJoinTimeOut = + CSR_JOIN_FAILURE_TIMEOUT_DEFAULT; + /* validate CB */ + pBssConfig->cbMode = csr_get_cb_mode_from_ies(pMac, pBssDesc->channelId, + pIes); + + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS csr_roam_prepare_bss_config_from_profile(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, + tBssConfigParam * + pBssConfig, + tSirBssDescription * + pBssDesc) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t operationChannel = 0; + uint8_t qAPisEnabled = false; + /* SSID */ + pBssConfig->SSID.length = 0; + if (pProfile->SSIDs.numOfSSIDs) { + /* only use the first one */ + cdf_mem_copy(&pBssConfig->SSID, + &pProfile->SSIDs.SSIDList[0].SSID, + sizeof(tSirMacSSid)); + } else { + /* SSID must present */ + return CDF_STATUS_E_FAILURE; + } + /* Settomg up the capabilities */ + if (csr_is_bss_type_ibss(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 = + csr_roam_get_phy_mode_band_for_bss(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 (csr_roam_get_qos_info_from_bss(pMac, pBssDesc) == + CDF_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 */ + /* Take the preferred Auth type. */ + switch (pProfile->AuthType.authType[0]) { + 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 = 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 CDF_STATUS csr_roam_get_qos_info_from_bss(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tDot11fBeaconIEs *pIes = NULL; + + do { + if (!CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies( + pMac, pBssDesc, &pIes))) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "csr_roam_get_qos_info_from_bss() failed"); + break; + } + /* check if the AP is QAP & it supports APSD */ + if (CSR_IS_QOS_BSS(pIes)) { + status = CDF_STATUS_SUCCESS; + } + } while (0); + + if (NULL != pIes) { + cdf_mem_free(pIes); + } + + return status; +} + +void csr_set_cfg_privacy(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, + bool fPrivacy) +{ + /* + * the only difference between this function and + * the csr_set_cfg_privacyFromProfile() 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... + */ + uint32_t PrivacyEnabled = 0, RsnEnabled = 0, WepDefaultKeyId = 0; + uint32_t WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_5; + uint32_t Key0Length = 0, Key1Length = 0, Key2Length = 0, Key3Length = 0; + + /* Reserve for the biggest key */ + uint8_t Key0[WNI_CFG_WEP_DEFAULT_KEY_1_LEN]; + uint8_t Key1[WNI_CFG_WEP_DEFAULT_KEY_2_LEN]; + uint8_t Key2[WNI_CFG_WEP_DEFAULT_KEY_3_LEN]; + uint8_t 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; + /* 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]) { + cdf_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]) { + cdf_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]) { + cdf_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]) { + cdf_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]) { + cdf_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]) { + cdf_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]) { + cdf_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]) { + cdf_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 */ + /* + * this is the only difference between this function and + * the csr_set_cfg_privacyFromProfile(). + * (setting of the privacy CFG based on the advertised + * privacy setting from AP for WPA/WAPI associations). + */ + PrivacyEnabled = (0 != fPrivacy); + /* turn on RSN enabled for WPA associations */ + RsnEnabled = 1; + /* clear static WEP keys that may be hanging around. */ + Key0Length = 0; + Key1Length = 0; + Key2Length = 0; + Key3Length = 0; + break; + default: + PrivacyEnabled = 0; + RsnEnabled = 0; + break; + } + + cfg_set_int(pMac, WNI_CFG_PRIVACY_ENABLED, PrivacyEnabled); + cfg_set_int(pMac, WNI_CFG_RSN_ENABLED, RsnEnabled); + cfg_set_str(pMac, WNI_CFG_WEP_DEFAULT_KEY_1, Key0, Key0Length); + cfg_set_str(pMac, WNI_CFG_WEP_DEFAULT_KEY_2, Key1, Key1Length); + cfg_set_str(pMac, WNI_CFG_WEP_DEFAULT_KEY_3, Key2, Key2Length); + cfg_set_str(pMac, WNI_CFG_WEP_DEFAULT_KEY_4, Key3, Key3Length); + cfg_set_int(pMac, WNI_CFG_WEP_KEY_LENGTH, WepKeyLength); + cfg_set_int(pMac, WNI_CFG_WEP_DEFAULT_KEYID, WepDefaultKeyId); +} + +static void csr_set_cfg_ssid(tpAniSirGlobal pMac, tSirMacSSid *pSSID) +{ + uint32_t len = 0; + if (pSSID->length <= WNI_CFG_SSID_LEN) { + len = pSSID->length; + } + cfg_set_str(pMac, WNI_CFG_SSID, (uint8_t *) pSSID->ssId, len); +} + +CDF_STATUS csr_set_qos_to_cfg(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrMediaAccessType qosType) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t QoSEnabled; + uint32_t 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 = (bool) WmeEnabled; + pMac->roam.roamSession[sessionId].fQOSConnection = (bool) QoSEnabled; + return status; +} + +static CDF_STATUS csr_get_rate_set(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, + tSirMacRateSet *pOpRateSet, + tSirMacRateSet *pExRateSet) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int i; + eCsrCfgDot11Mode cfgDot11Mode; + uint8_t *pDstRate; + uint16_t rateBitmap = 0; + cdf_mem_set(pOpRateSet, sizeof(tSirMacRateSet), 0); + cdf_mem_set(pExRateSet, sizeof(tSirMacRateSet), 0); + CDF_ASSERT(pIes != NULL); + + if (NULL == pIes) { + sms_log(pMac, LOGE, FL("failed to parse BssDesc")); + return status; + } + + csr_is_phy_mode_match(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've 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 (csr_rates_is_dot11_rate_supported(pMac, + pIes->SuppRates.rates[i]) && + !csr_check_rate_bitmap( + pIes->SuppRates.rates[i], + rateBitmap)) { + csr_add_rate_bitmap(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 + ) && pIes->ExtSuppRates.present) { + /* + * If there are extended rates in the beacon, + * we will reflect those extended rates that we support in our + * extended operational rate + */ + pDstRate = pExRateSet->rate; + for (i = 0; i < pIes->ExtSuppRates.num_rates; i++) { + if (csr_rates_is_dot11_rate_supported(pMac, + pIes->ExtSuppRates.rates[i]) && + !csr_check_rate_bitmap( + pIes->ExtSuppRates.rates[i], + rateBitmap)) { + *pDstRate++ = pIes->ExtSuppRates.rates[i]; + pExRateSet->numRates++; + } + } + } + if (pOpRateSet->numRates > 0 || pExRateSet->numRates > 0) + status = CDF_STATUS_SUCCESS; + return status; +} + +static void csr_set_cfg_rate_set(tpAniSirGlobal pMac, eCsrPhyMode phyMode, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + int i; + uint8_t *pDstRate; + eCsrCfgDot11Mode cfgDot11Mode; + uint8_t OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX]; /* leave enough room for the max number of rates */ + uint32_t OperationalRatesLength = 0; + uint8_t ExtendedOperationalRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; /* leave enough room for the max number of rates */ + uint32_t ExtendedOperationalRatesLength = 0; + uint8_t MCSRateIdxSet[SIZE_OF_SUPPORTED_MCS_SET]; + uint32_t MCSRateLength = 0; + CDF_ASSERT(pIes != NULL); + if (NULL != pIes) { + csr_is_phy_mode_match(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 (csr_rates_is_dot11_rate_supported + (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 (csr_rates_is_dot11_rate_supported + (pMac, pIes->ExtSuppRates.rates[i]) + && (ExtendedOperationalRatesLength < + CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX)) { + *pDstRate++ = + pIes->ExtSuppRates.rates[i]; + ExtendedOperationalRatesLength++; + } + } + } + } + /* Enable proprietary MAC features if peer node is Airgo node and STA */ + /* user wants to use them */ + /* For ANI network companions, we need to populate the proprietary rate */ + /* set with any proprietary rates we found in the beacon, only if user */ + /* allows them... */ + /* No proprietary modes... */ + /* 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... */ + cfg_set_str(pMac, WNI_CFG_OPERATIONAL_RATE_SET, + OperationalRates, OperationalRatesLength); + cfg_set_str(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + ExtendedOperationalRates, + ExtendedOperationalRatesLength); + cfg_set_str(pMac, WNI_CFG_CURRENT_MCS_SET, MCSRateIdxSet, + MCSRateLength); + } /* Parsing BSSDesc */ + else { + sms_log(pMac, LOGE, FL("failed to parse BssDesc")); + } +} + +static void csr_set_cfg_rate_set_from_profile(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; + /* leave enough room for the max number of rates */ + uint8_t OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX]; + uint32_t OperationalRatesLength = 0; + /* leave enough room for the max number of rates */ + uint8_t ExtendedOperationalRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX]; + uint32_t ExtendedOperationalRatesLength = 0; + /* leave enough room for the max number of proprietary rates */ + uint8_t ProprietaryOperationalRates[4]; + uint32_t ProprietaryOperationalRatesLength = 0; + uint32_t PropRatesEnable = 0; + uint8_t operationChannel = 0; + if (pProfile->ChannelInfo.ChannelList) { + operationChannel = pProfile->ChannelInfo.ChannelList[0]; + } + cfgDot11Mode = + csr_roam_get_phy_mode_band_for_bss(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); + cdf_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); + cdf_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); + cdf_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); + cdf_mem_copy(OperationalRates, + DefaultSupportedRates11b.supportedRateSet.rate, + OperationalRatesLength); + + /* 11a rates go in the Extended rate set. */ + ExtendedOperationalRatesLength = + DefaultSupportedRates11a.supportedRateSet.numRates * + sizeof(*DefaultSupportedRates11a.supportedRateSet.rate); + cdf_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); + cdf_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... */ + cfg_set_str(pMac, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, + OperationalRatesLength); + cfg_set_str(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, + ExtendedOperationalRates, ExtendedOperationalRatesLength); + cfg_set_str(pMac, WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET, + ProprietaryOperationalRates, + ProprietaryOperationalRatesLength); +} + +void csr_roam_ccm_cfg_set_callback(tpAniSirGlobal pMac, int32_t result) +{ + tListElem *pEntry = + csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + uint32_t sessionId; + tSmeCmd *pCommand = NULL; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tCsrRoamSession *pSession = NULL; +#endif + if (NULL == pEntry) { + sms_log(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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR3:csr_roam_cfg_set_callback"); + } +#endif + + if (CSR_IS_ROAM_JOINING(pMac, sessionId) + && CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId)) { + csr_roaming_state_config_cnf_processor(pMac, (uint32_t) result); + } +} + +/* This function is very dump. It is here because PE still need WNI_CFG_PHY_MODE */ +uint32_t csr_roam_get_phy_mode_from_dot11_mode(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 csr_get_htcb_state_from_vhtcb_state(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 */ +CDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes, bool resetCountry) +{ + tSirRetStatus status; + uint32_t cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + uint8_t 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 (csr_learn_11dcountry_information(pMac, pBssDesc, pIes, true)) { + csr_apply_country_information(pMac); + } + if ((csr_is11d_supported(pMac)) && pIes) { + if (!pIes->Country.present) { + csr_apply_channel_power_info_wrapper(pMac); + } 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 */ + cdf_mem_copy(pMac->scan.currentCountryBssid.bytes, + pBssDesc->bssId, + sizeof(tSirMacAddr)); + } + } + } + /* Qos */ + csr_set_qos_to_cfg(pMac, sessionId, pBssConfig->qosType); + /* SSID */ + csr_set_cfg_ssid(pMac, &pBssConfig->SSID); + + /* Auth type */ + cfg_set_int(pMac, WNI_CFG_AUTHENTICATION_TYPE, pBssConfig->authType); + /* encryption type */ + csr_set_cfg_privacy(pMac, pProfile, (bool) pBssConfig->BssCap.privacy); + /* short slot time */ + cfg_set_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + pBssConfig->uShortSlotTime); + /* 11d */ + cfg_set_int(pMac, WNI_CFG_11D_ENABLED, + ((pBssConfig->f11hSupport) ? pBssConfig->f11hSupport : + pProfile->ieee80211d)); + cfg_set_int(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, + pBssConfig->uPowerLimit); + /* 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 (CDS_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) { + csr_set_cfg_rate_set(pMac, (eCsrPhyMode) pProfile->phyMode, + pProfile, pBssDesc, pIes); + } else { + csr_set_cfg_rate_set_from_profile(pMac, pProfile); + } + /* Make this the last CFG to set. The callback will trigger a join_req */ + /* Join time out */ + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_CONFIG, sessionId); + + status = cfg_set_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + pBssConfig->uJoinTimeOut); + csr_roam_ccm_cfg_set_callback(pMac, status); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_stop_network(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status; + tBssConfigParam *pBssConfig; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + pBssConfig = cdf_mem_malloc(sizeof(tBssConfigParam)); + if (NULL == pBssConfig) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pBssConfig, sizeof(tBssConfigParam), 0); + status = csr_roam_prepare_bss_config(pMac, pProfile, pBssDesc, + pBssConfig, pIes); + if (CDF_IS_STATUS_SUCCESS(status)) { + eCsrRoamSubState substate; + substate = eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING; + 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 (csr_is_bss_type_ibss(pProfile->BSSType) || + CSR_IS_WDS(pProfile) || + CSR_IS_INFRA_AP(pProfile)) + csr_roam_prepare_bss_params(pMac, sessionId, pProfile, + pBssDesc, pBssConfig, pIes); + + /* + * If we are in an IBSS, then stop the IBSS... + * Not worry about WDS connection for now + */ + if (csr_is_conn_state_ibss(pMac, sessionId)) { + status = csr_roam_issue_stop_bss(pMac, sessionId, + substate); + } else if (csr_is_conn_state_infra(pMac, sessionId)) { + /* + * 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 && (csr_is_ibss_bss_desc(pBssDesc) || + !csr_is_ssid_equal(pMac, + pSession->pConnectBssDesc, + pBssDesc, pIes))) + status = csr_roam_issue_disassociate(pMac, + sessionId, substate, false); + else if (pBssDesc) + /* + * In an infra & going to an infra network with + * the same SSID. This calls for a reassoc seq. + * So issue the CFG sets for this new AP. Set + * parameters for this Bss. + */ + status = csr_roam_set_bss_config_cfg(pMac, + sessionId, pProfile, pBssDesc, + pBssConfig, pIes, false); + } else if (pBssDesc || CSR_IS_WDS_AP(pProfile) || + CSR_IS_INFRA_AP(pProfile)) { + /* + * Neither in IBSS nor in Infra. We can go ahead and set + * the cfg for tne new network... nothing to stop. + */ + bool is11rRoamingFlag = false; + is11rRoamingFlag = csr_roam_is11r_assoc(pMac, + sessionId); + /* Set parameters for this Bss. */ + status = csr_roam_set_bss_config_cfg(pMac, sessionId, + pProfile, pBssDesc, pBssConfig, pIes, + is11rRoamingFlag); + } + } /* Success getting BSS config info */ + cdf_mem_free(pBssConfig); + return status; +} + +/** + * csr_roam_state_for_same_profile() - Determine roam state for same profile + * @mac_ctx: pointer to mac context + * @profile: Roam profile + * @session: Roam session + * @session_id: session id + * @ies_local: local ies + * @bss_descr: bss description + * + * This function will determine the roam state for same profile + * + * Return: Roaming state. + */ +static eCsrJoinState csr_roam_state_for_same_profile(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, tCsrRoamSession *session, + uint32_t session_id, tDot11fBeaconIEs *ies_local, + tSirBssDescription *bss_descr) +{ + CDF_STATUS status; + tBssConfigParam bssConfig; + if (csr_roam_is_same_profile_keys(mac_ctx, &session->connectedProfile, + profile)) + return eCsrReassocToSelfNoCapChange; + /* The key changes */ + cdf_mem_set(&bssConfig, sizeof(bssConfig), 0); + status = csr_roam_prepare_bss_config(mac_ctx, profile, bss_descr, + &bssConfig, ies_local); + if (CDF_IS_STATUS_SUCCESS(status)) { + session->bssParams.uCfgDot11Mode = + bssConfig.uCfgDot11Mode; + session->bssParams.cbMode = + bssConfig.cbMode; + /* reapply the cfg including keys so reassoc happens. */ + status = csr_roam_set_bss_config_cfg(mac_ctx, session_id, + profile, bss_descr, &bssConfig, + ies_local, false); + if (CDF_IS_STATUS_SUCCESS(status)) + return eCsrContinueRoaming; + } + + return eCsrStopRoaming; + +} + +eCsrJoinState csr_roam_join(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrScanResultInfo *pScanResult, + tCsrRoamProfile *pProfile) +{ + eCsrJoinState eRoamState = eCsrContinueRoaming; + tSirBssDescription *pBssDesc = &pScanResult->BssDescriptor; + tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *) (pScanResult->pvIes); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return eCsrStopRoaming; + } + + if (CSR_IS_WDS_STA(pProfile) && + !CDF_IS_STATUS_SUCCESS(csr_roam_start_wds(pMac, sessionId, + pProfile, pBssDesc))) + return eCsrStopRoaming; + if (!pIesLocal && + !CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(pMac, + pBssDesc, &pIesLocal))) { + sms_log(pMac, LOGE, FL("fail to parse IEs")); + return eCsrStopRoaming; + } + if (csr_is_infra_bss_desc(pBssDesc)) { + /* + * If we are connected in infra mode and the join bss descr 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 (csr_is_conn_state_connected_infra(pMac, sessionId) && + csr_is_bss_id_equal(pMac, + pBssDesc, pSession->pConnectBssDesc) && + csr_is_ssid_equal(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, wihch will force an Authentication (with the + * new Auth type) followed by a new Association. + */ + if (csr_is_same_profile(pMac, + &pSession->connectedProfile, pProfile)) { + sms_log(pMac, LOGW, + FL("detect same profile")); + eRoamState = + csr_roam_state_for_same_profile(pMac, + pProfile, pSession, sessionId, + pIesLocal, pBssDesc); + } else if (!CDF_IS_STATUS_SUCCESS( + csr_roam_issue_disassociate(pMac, + sessionId, + eCSR_ROAM_SUBSTATE_DISASSOC_REQ, + false))) { + sms_log(pMac, LOGE, + FL("fail disassoc session %d"), + sessionId); + eRoamState = eCsrStopRoaming; + } + } else if (!CDF_IS_STATUS_SUCCESS(csr_roam_stop_network(pMac, + sessionId, pProfile, pBssDesc, pIesLocal))) { + /* we used to pre-auth here with open auth + * networks but that wasn't working so well. + * stop the existing network before attempting + * to join the new network... */ + eRoamState = eCsrStopRoaming; + } + } else if (!CDF_IS_STATUS_SUCCESS(csr_roam_stop_network(pMac, sessionId, + pProfile, pBssDesc, + pIesLocal))) { + eRoamState = eCsrStopRoaming; + } + + if (pIesLocal && !pScanResult->pvIes) + cdf_mem_free(pIesLocal); + return eRoamState; +} + +CDF_STATUS csr_roam_should_roam(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc, uint32_t roamId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.pBssDesc = pBssDesc; + status = + csr_roam_call_callback(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 csr_roam_assign_default_param(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + /* Need to get all negotiated types in place first */ + /* auth type */ + /* Take the preferred Auth type. */ + switch (pCommand->u.roamCmd.roamProfile.AuthType.authType[0]) { + 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 uncast ones. */ + pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0]; +} + +static void csr_set_abort_roaming_command(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: + sms_log(pMac, LOGE, + FL(" aborting roaming reason %d not recognized"), + pCommand->u.roamCmd.roamReason); + break; + } +} + +/** + * csr_roam_select_bss() - Handle join scenario based on profile + * @mac_ctx: Global MAC Context + * @roam_bss_entry: The next BSS to join + * @csr_result_info: Result of join + * @csr_scan_result: Global scan result + * @session_id: SME Session ID + * @roam_id: Roaming ID + * @roam_state: Current roaming state + * @bss_list: BSS List + * + * Return: true if the entire BSS list is done, false otherwise. + */ +static bool csr_roam_select_bss(tpAniSirGlobal mac_ctx, + tListElem *roam_bss_entry, tCsrScanResultInfo **csr_result_info, + tCsrScanResult **csr_scan_result, uint32_t session_id, + uint32_t roam_id, eCsrJoinState *roam_state, + tScanResultList *bss_list) +{ + uint8_t conc_channel = 0; + bool status = false; + tCsrScanResult *scan_result = NULL; + tCsrScanResultInfo *result = NULL; + + while (roam_bss_entry) { + scan_result = GET_BASE_ADDR(roam_bss_entry, tCsrScanResult, + Link); + /* + * If concurrency enabled take the + * concurrent connected channel first. + * Valid multichannel concurrent + * sessions exempted + */ + result = &scan_result->Result; + if (cds_concurrent_open_sessions_running() && + !csr_is_valid_mc_concurrent_session(mac_ctx, + session_id, &result->BssDescriptor)) { + conc_channel = csr_get_concurrent_operation_channel( + mac_ctx); + sms_log(mac_ctx, LOG1, FL("csr Conc Channel = %d"), + conc_channel); + if ((conc_channel) && (conc_channel == + 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 + */ + sms_log(mac_ctx, LOG1, FL("Conc chnl match=%d"), + conc_channel); + conc_channel = 0; + } + } + + /* Ok to roam this */ + if (!conc_channel && + CDF_IS_STATUS_SUCCESS(csr_roam_should_roam(mac_ctx, + session_id, &result->BssDescriptor, roam_id))) { + status = false; + break; + } else { + *roam_state = eCsrStopRoamingDueToConcurrency; + status = true; + } + roam_bss_entry = csr_ll_next(&bss_list->List, roam_bss_entry, + LL_ACCESS_LOCK); + } + *csr_result_info = result; + *csr_scan_result = scan_result; + return status; +} + +/** + * csr_roam_join_handle_profile() - Handle join scenario based on profile + * @mac_ctx: Global MAC Context + * @session_id: SME Session ID + * @cmd: Command + * @roam_info_ptr: Pointed to the roaming info for join + * @roam_state: Current roaming state + * @result: Result of join + * @scan_result: Global scan result + * + * Return: None + */ +static void csr_roam_join_handle_profile(tpAniSirGlobal mac_ctx, + uint32_t session_id, tSmeCmd *cmd, tCsrRoamInfo *roam_info_ptr, + eCsrJoinState *roam_state, tCsrScanResultInfo *result, + tCsrScanResult *scan_result) +{ +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + uint8_t acm_mask = 0; +#endif + CDF_STATUS status; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tCsrRoamProfile *profile = &cmd->u.roamCmd.roamProfile; + tDot11fBeaconIEs *ies_local = NULL; + /* + * 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(profile)) { + if (roam_info_ptr && session->bRefAssocStartCnt) { + session->bRefAssocStartCnt--; + roam_info_ptr->pProfile = profile; + /* + * Complete the last assoc attempt as a + * new one is about to be tried + */ + csr_roam_call_callback(mac_ctx, session_id, + roam_info_ptr, cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_NOT_ASSOCIATED); + } + /* If roaming has stopped, don't continue the roaming command */ + if (!CSR_IS_ROAMING(session) && CSR_IS_ROAMING_COMMAND(cmd)) { + /* No need to complete roaming as it already complete */ + sms_log(mac_ctx, LOGW, + FL( + "Roam cmd(reason %d)aborted as roam complete"), + cmd->u.roamCmd.roamReason); + *roam_state = eCsrStopRoaming; + csr_set_abort_roaming_command(mac_ctx, cmd); + return; + } + cdf_mem_set(roam_info_ptr, sizeof(tCsrRoamInfo), 0); + if (!scan_result) + cmd->u.roamCmd.roamProfile.uapsd_mask = 0; + else + ies_local = scan_result->Result.pvIes; + + if (scan_result && !ies_local && + (!CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies( + mac_ctx, + &result->BssDescriptor, + &ies_local)))) { + sms_log(mac_ctx, LOGE, FL(" cannot parse IEs")); + *roam_state = eCsrStopRoaming; + return; + } + roam_info_ptr->pBssDesc = &result->BssDescriptor; + cmd->u.roamCmd.pLastRoamBss = roam_info_ptr->pBssDesc; + /* dont put uapsd_mask if BSS doesn't support uAPSD */ + if (scan_result && cmd->u.roamCmd.roamProfile.uapsd_mask + && CSR_IS_QOS_BSS(ies_local) + && CSR_IS_UAPSD_BSS(ies_local)) { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_qos_get_acm_mask(mac_ctx, + &result->BssDescriptor, ies_local); +#endif /* WLAN_MDM_CODE_REDUCTION_OPT */ + } else { + cmd->u.roamCmd.roamProfile.uapsd_mask = 0; + } + if (ies_local && !result->pvIes) + cdf_mem_free(ies_local); + roam_info_ptr->pProfile = profile; + session->bRefAssocStartCnt++; + csr_roam_call_callback(mac_ctx, session_id, roam_info_ptr, + cmd->u.roamCmd.roamId, eCSR_ROAM_ASSOCIATION_START, + eCSR_ROAM_RESULT_NONE); + } + if (NULL != cmd->u.roamCmd.pRoamBssEntry) { + /* + * We have BSS + * Need to assign these value because + * they are used in csr_is_same_profile + */ + scan_result = GET_BASE_ADDR(cmd->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + /* + * The OSEN IE doesn't provide the cipher suite.Therefore set + * to constant value of AES + */ + if (cmd->u.roamCmd.roamProfile.bOSENAssociation) { + cmd->u.roamCmd.roamProfile.negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_AES; + cmd->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + eCSR_ENCRYPT_TYPE_AES; + } else { + /* Negotiated while building scan result. */ + cmd->u.roamCmd.roamProfile.negotiatedUCEncryptionType = + scan_result->ucEncryptionType; + cmd->u.roamCmd.roamProfile.negotiatedMCEncryptionType = + scan_result->mcEncryptionType; + } + cmd->u.roamCmd.roamProfile.negotiatedAuthType = + scan_result->authType; + if (CSR_IS_START_IBSS(&cmd->u.roamCmd.roamProfile)) { + if (csr_is_same_profile(mac_ctx, + &session->connectedProfile, profile)) { + *roam_state = eCsrStartIbssSameIbss; + return; + } + } + if (cmd->u.roamCmd.fReassocToSelfNoCapChange) { + /* trying to connect to the one already connected */ + cmd->u.roamCmd.fReassocToSelfNoCapChange = false; + *roam_state = eCsrReassocToSelfNoCapChange; + return; + } + /* Attempt to Join this Bss... */ + *roam_state = csr_roam_join(mac_ctx, session_id, + &scan_result->Result, profile); + return; + } + + /* For an IBSS profile, then we need to start the IBSS. */ + if (CSR_IS_START_IBSS(profile)) { + bool same_ibss = false; + /* Attempt to start this IBSS... */ + csr_roam_assign_default_param(mac_ctx, cmd); + status = csr_roam_start_ibss(mac_ctx, session_id, + profile, &same_ibss); + if (CDF_IS_STATUS_SUCCESS(status)) { + if (same_ibss) + *roam_state = eCsrStartIbssSameIbss; + else + *roam_state = eCsrContinueRoaming; + } else { + /* it somehow fail need to stop */ + *roam_state = eCsrStopRoaming; + } + return; + } else if ((CSR_IS_WDS_AP(profile)) || + (CSR_IS_INFRA_AP(profile))) { + /* Attempt to start this WDS... */ + csr_roam_assign_default_param(mac_ctx, cmd); + /* For AP WDS, we dont have any BSSDescription */ + status = csr_roam_start_wds(mac_ctx, session_id, profile, NULL); + if (CDF_IS_STATUS_SUCCESS(status)) + *roam_state = eCsrContinueRoaming; + else + *roam_state = eCsrStopRoaming; + } else { + /* Nothing we can do */ + sms_log(mac_ctx, LOGW, FL("cannot continue without BSS list")); + *roam_state = eCsrStopRoaming; + return; + } + +} +/** + * csr_roam_join_next_bss() - Pick the next BSS for join + * @mac_ctx: Global MAC Context + * @cmd: Command + * @use_same_bss: Use Same BSS to Join + * + * Return: The Join State + */ +static eCsrJoinState csr_roam_join_next_bss(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd, bool use_same_bss) +{ + tCsrScanResult *scan_result = NULL; + eCsrJoinState roam_state = eCsrStopRoaming; + tScanResultList *bss_list = + (tScanResultList *) cmd->u.roamCmd.hBSSList; + bool done = false; + tCsrRoamInfo roam_info, *roam_info_ptr = NULL; + uint32_t session_id = cmd->sessionId; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tCsrRoamProfile *profile = &cmd->u.roamCmd.roamProfile; + tCsrRoamJoinStatus *join_status; + tCsrScanResultInfo *result = NULL; + + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id); + return eCsrStopRoaming; + } + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + cdf_mem_copy(&roam_info.bssid, &session->joinFailStatusCode.bssId, + sizeof(tSirMacAddr)); + /* + * When handling AP's capability change, continue to associate + * to same BSS and make sure pRoamBssEntry is not Null. + */ + if ((NULL != bss_list) && + ((false == use_same_bss) || + (cmd->u.roamCmd.pRoamBssEntry == NULL))) { + if (cmd->u.roamCmd.pRoamBssEntry == NULL) { + /* Try the first BSS */ + cmd->u.roamCmd.pLastRoamBss = NULL; + cmd->u.roamCmd.pRoamBssEntry = + csr_ll_peek_head(&bss_list->List, + LL_ACCESS_LOCK); + } else { + cmd->u.roamCmd.pRoamBssEntry = + csr_ll_next(&bss_list->List, + cmd->u.roamCmd.pRoamBssEntry, + LL_ACCESS_LOCK); + /* + * Done with all the BSSs. + * In this case, will tell HDD the + * completion + */ + if (NULL == cmd->u.roamCmd.pRoamBssEntry) + goto end; + /* + * We need to indicate to HDD that we + * are done with this one. + */ + roam_info.pBssDesc = cmd->u.roamCmd.pLastRoamBss; + join_status = &session->joinFailStatusCode; + roam_info.statusCode = join_status->statusCode; + roam_info.reasonCode = join_status->reasonCode; + roam_info_ptr = &roam_info; + } + done = csr_roam_select_bss(mac_ctx, + cmd->u.roamCmd.pRoamBssEntry, &result, + &scan_result, session_id, cmd->u.roamCmd.roamId, + &roam_state, bss_list); + if (done) + goto end; + } + if (!roam_info_ptr) + roam_info_ptr = &roam_info; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + csr_roam_join_handle_profile(mac_ctx, session_id, cmd, roam_info_ptr, + &roam_state, result, scan_result); +end: + if ((eCsrStopRoaming == roam_state) && CSR_IS_INFRASTRUCTURE(profile) && + (session->bRefAssocStartCnt > 0)) { + /* + * Need to indicate association_completion if association_start + * has been done + */ + session->bRefAssocStartCnt--; + /* + * Complete the last assoc attempte as a + * new one is about to be tried + */ + roam_info_ptr = &roam_info; + roam_info_ptr->pProfile = profile; + csr_roam_call_callback(mac_ctx, session_id, + roam_info_ptr, cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_NOT_ASSOCIATED); + } + + return roam_state; +} + +static CDF_STATUS csr_roam(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + eCsrJoinState RoamState; + eCsrRoamSubState substate; + uint32_t sessionId = pCommand->sessionId; + + /* Attept to join a Bss... */ + RoamState = csr_roam_join_next_bss(pMac, pCommand, false); + + /* if nothing to join.. */ + if ((eCsrStopRoaming == RoamState) || + (eCsrStopRoamingDueToConcurrency == RoamState)) { + bool fComplete = false; + /* and if connected in Infrastructure mode... */ + if (csr_is_conn_state_infra(pMac, sessionId)) { + /* ... then we need to issue a disassociation */ + substate = eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN; + status = csr_roam_issue_disassociate(pMac, sessionId, + substate, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, + FL("fail issuing disassoc status = %d"), + status); + /* + * roam command is completed by caller in the + * failed case + */ + fComplete = true; + } + } else if (csr_is_conn_state_ibss(pMac, sessionId)) { + status = csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, + FL("fail issuing stop bss status = %d"), + status); + /* + * roam command is completed by caller in the + * failed case + */ + fComplete = true; + } + } else if (csr_is_conn_state_connected_infra_ap(pMac, + sessionId)) { + substate = eCSR_ROAM_SUBSTATE_STOP_BSS_REQ; + status = csr_roam_issue_stop_bss(pMac, sessionId, + substate); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, + FL("fail issuing stop bss status = %d"), + status); + /* + * roam command is completed by caller in the + * failed case + */ + fComplete = true; + } + } else { + fComplete = true; + } + + if (fComplete) { + /* otherwise, we can complete the Roam command here. */ + if (eCsrStopRoamingDueToConcurrency == RoamState) + csr_roam_complete(pMac, + eCsrJoinFailureDueToConcurrency, NULL); + else + csr_roam_complete(pMac, + eCsrNothingToJoin, NULL); + } + } else if (eCsrReassocToSelfNoCapChange == RoamState) { + csr_roam_complete(pMac, eCsrSilentlyStopRoamingSaveState, + NULL); + } else if (eCsrStartIbssSameIbss == RoamState) { + csr_roam_complete(pMac, eCsrSilentlyStopRoaming, NULL); + } + + return status; +} + +CDF_STATUS csr_process_ft_reassoc_roam_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + uint32_t sessionId; + tCsrRoamSession *pSession; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDesc = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming) { + /* the roaming is cancelled. Simply complete the command */ + sms_log(pMac, LOG1, FL("Roam command canceled")); + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + return CDF_STATUS_E_FAILURE; + } + if (pCommand->u.roamCmd.pRoamBssEntry) { + pScanResult = + GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + pBssDesc = &pScanResult->Result.BssDescriptor; + } else { + /* the roaming is cancelled. Simply complete the command */ + sms_log(pMac, LOG1, FL("Roam command canceled")); + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + return CDF_STATUS_E_FAILURE; + } + status = csr_roam_issue_reassociate(pMac, sessionId, pBssDesc, + (tDot11fBeaconIEs *) (pScanResult-> + Result.pvIes), + &pCommand->u.roamCmd.roamProfile); + return status; +} + +/** + * csr_roam_trigger_reassociate() - Helper function to trigger reassociate + * @mac_ctx: pointer to mac context + * @cmd: sme command + * @roam_info: Roaming infor structure + * @session_ptr: session pointer + * @session_id: session id + * + * This function will trigger reassociate. + * + * Return: CDF_STATUS for success or failure. + */ +static CDF_STATUS csr_roam_trigger_reassociate(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd, tCsrRoamInfo *roam_info, + tCsrRoamSession *session_ptr, uint32_t session_id) +{ + tDot11fBeaconIEs *pIes = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (session_ptr->pConnectBssDesc) { + status = csr_get_parsed_bss_description_ies(mac_ctx, + session_ptr->pConnectBssDesc, &pIes); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("fail to parse IEs")); + } else { + roam_info->reasonCode = + eCsrRoamReasonStaCapabilityChanged; + csr_roam_call_callback(mac_ctx, session_ptr->sessionId, + roam_info, 0, eCSR_ROAM_ROAMING_START, + eCSR_ROAM_RESULT_NONE); + session_ptr->roamingReason = eCsrReassocRoaming; + roam_info->pBssDesc = session_ptr->pConnectBssDesc; + roam_info->pProfile = &cmd->u.roamCmd.roamProfile; + session_ptr->bRefAssocStartCnt++; + csr_roam_call_callback(mac_ctx, session_id, roam_info, + cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_START, + eCSR_ROAM_RESULT_NONE); + + sms_log(mac_ctx, LOG1, + FL("calling csr_roam_issue_reassociate")); + status = csr_roam_issue_reassociate(mac_ctx, session_id, + session_ptr->pConnectBssDesc, pIes, + &cmd->u.roamCmd.roamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("failed status %d"), + status); + csr_release_command_roam(mac_ctx, cmd); + } + + cdf_mem_free(pIes); + pIes = NULL; + } + } else { + sms_log(mac_ctx, LOGE, FL + ("reassoc to same AP failed as connected BSS is NULL")); + status = CDF_STATUS_E_FAILURE; + } + return status; +} + +CDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + uint32_t sessionId = pCommand->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + sms_log(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]) { + sms_log(pMac, LOGE, + FL("Ignore eCsrForcedDisassoc cmd on roam state" + " %d"), eCSR_ROAMING_STATE_IDLE); + return CDF_STATUS_E_FAILURE; + } + + status = csr_roam_process_disassoc_deauth(pMac, pCommand, + true, false); + csr_free_roam_profile(pMac, sessionId); + break; + case eCsrSmeIssuedDisassocForHandoff: + /* Not to free pMac->roam.pCurRoamProfile (via + * csr_free_roam_profile) because its needed after disconnect */ + status = csr_roam_process_disassoc_deauth(pMac, pCommand, + true, false); + + break; + case eCsrForcedDisassocMICFailure: + status = csr_roam_process_disassoc_deauth(pMac, pCommand, + true, true); + csr_free_roam_profile(pMac, sessionId); + break; + case eCsrForcedDeauth: + status = csr_roam_process_disassoc_deauth(pMac, pCommand, + false, false); + csr_free_roam_profile(pMac, sessionId); + break; + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + status = csr_roam_trigger_reassociate(pMac, pCommand, &roamInfo, + pSession, sessionId); + break; + case eCsrCapsChange: + sms_log(pMac, LOGE, FL("received eCsrCapsChange ")); + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, + sessionId); + status = csr_roam_issue_disassociate(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, + false); + break; + case eCsrSmeIssuedFTReassoc: + sms_log(pMac, LOG1, FL("received FT Reassoc Req ")); + status = csr_process_ft_reassoc_roam_command(pMac, pCommand); + break; + + case eCsrStopBss: + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, + sessionId); + status = csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); + break; + + case eCsrForcedDisassocSta: + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, + sessionId); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_DISASSOC_REQ, + sessionId); + status = csr_send_mb_disassoc_req_msg(pMac, sessionId, + pCommand->u.roamCmd.peerMac, + pCommand->u.roamCmd.reason); + break; + + case eCsrForcedDeauthSta: + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, + sessionId); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_DEAUTH_REQ, + sessionId); + status = csr_send_mb_deauth_req_msg(pMac, sessionId, + pCommand->u.roamCmd.peerMac, + pCommand->u.roamCmd.reason); + break; + + case eCsrPerformPreauth: + sms_log(pMac, LOG1, FL("Attempting FT PreAuth Req")); + status = csr_roam_issue_ft_preauth_req(pMac, sessionId, + pCommand->u.roamCmd.pLastRoamBss); + break; + default: + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, + sessionId); + + if (pCommand->u.roamCmd.fUpdateCurRoamProfile) { + /* Remember the roaming profile */ + csr_free_roam_profile(pMac, sessionId); + pSession->pCurRoamProfile = + cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (NULL != pSession->pCurRoamProfile) { + cdf_mem_set(pSession->pCurRoamProfile, + sizeof(tCsrRoamProfile), 0); + csr_roam_copy_profile(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 = csr_roam(pMac, pCommand); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGW, + FL("csr_roam() failed with status = 0x%08X"), + status); + break; + } + return status; +} + +void csr_reinit_preauth_cmd(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 */ + cdf_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0); +} + +void csr_reinit_roam_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + if (pCommand->u.roamCmd.fReleaseBssList) { + csr_scan_result_purge(pMac, pCommand->u.roamCmd.hBSSList); + pCommand->u.roamCmd.fReleaseBssList = false; + pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + } + if (pCommand->u.roamCmd.fReleaseProfile) { + csr_release_profile(pMac, &pCommand->u.roamCmd.roamProfile); + pCommand->u.roamCmd.fReleaseProfile = false; + } + pCommand->u.roamCmd.pRoamBssEntry = NULL; + /* Because u.roamCmd is union and share with scanCmd and StatusChange */ + cdf_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0); +} + +void csr_reinit_wm_status_change_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + cdf_mem_set(&pCommand->u.wmStatusChangeCmd, sizeof(tWmStatusChangeCmd), + 0); +} + +void csr_roam_complete(tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, + void *Context) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + bool fReleaseCommand = true; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "%s: Roam Completion ...", __func__); + pEntry = csr_ll_peek_head(&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 = + csr_roam_process_results(pMac, pCommand, Result, + Context); + if (fReleaseCommand) { + if (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + csr_release_command_roam(pMac, pCommand); + } else { + sms_log(pMac, LOGE, + " **********csr_roam_complete fail to release command reason %d", + pCommand->u.roamCmd.roamReason); + } + } else { + sms_log(pMac, LOGE, + " **********csr_roam_complete fail to release command reason %d", + pCommand->u.roamCmd.roamReason); + } + } else { + sms_log(pMac, LOGW, + "CSR: Roam Completion called but ROAM command is not ACTIVE ..."); + } + } else { + sms_log(pMac, LOGW, + "CSR: Roam Completion called but NO commands are ACTIVE ..."); + } + if (fReleaseCommand) { + sme_process_pending_queue(pMac); + } +} + +void csr_reset_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + cdf_mem_set(&(pSession->PmkidCandidateInfo[0]), + sizeof(tPmkidCandidateInfo) * CSR_MAX_PMKID_ALLOWED, 0); + pSession->NumPmkidCandidate = 0; +} + +#ifdef FEATURE_WLAN_WAPI +void csr_reset_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + cdf_mem_set(&(pSession->BkidCandidateInfo[0]), + sizeof(tBkidCandidateInfo) * CSR_MAX_BKID_ALLOWED, 0); + pSession->NumBkidCandidate = 0; +} +#endif /* FEATURE_WLAN_WAPI */ +extern uint8_t csr_wpa_oui[][CSR_WPA_OUI_SIZE]; + +/** + * csr_roam_save_params() - Helper function to save params + * @mac_ctx: pointer to mac context + * @session_ptr: Session pointer + * @auth_type: auth type + * @ie_ptr: pointer to ie + * @ie_local: pointr to local ie + * + * This function will save params to session + * + * Return: none. + */ +static CDF_STATUS csr_roam_save_params(tpAniSirGlobal mac_ctx, + tCsrRoamSession *session_ptr, + eCsrAuthType auth_type, + tDot11fBeaconIEs *ie_ptr, + tDot11fBeaconIEs *ie_local) +{ + uint32_t nIeLen; + uint8_t *pIeBuf; + + if ((eCSR_AUTH_TYPE_RSN == auth_type) || +#if defined WLAN_FEATURE_VOWIFI_11R + (eCSR_AUTH_TYPE_FT_RSN == auth_type) || + (eCSR_AUTH_TYPE_FT_RSN_PSK == auth_type) || +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#if defined WLAN_FEATURE_11W + (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == auth_type) || + (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == auth_type) || +#endif + (eCSR_AUTH_TYPE_RSN_PSK == auth_type)) { + if (ie_local->RSN.present) { + tDot11fIERSN *rsnie = &ie_local->RSN; + /* + * Calculate the actual length + * version + gp_cipher_suite + pwise_cipher_suite_count + * + akm_suite_count + reserved + pwise_cipher_suites + */ + nIeLen = 8 + 2 + 2 + + (rsnie->pwise_cipher_suite_count * 4) + + (rsnie->akm_suite_count * 4); + if (rsnie->pmkid_count) + /* pmkid */ + nIeLen += 2 + rsnie->pmkid_count * 4; + + /* nIeLen doesn't count EID and length fields */ + session_ptr->pWpaRsnRspIE = cdf_mem_malloc(nIeLen + 2); + if (NULL == session_ptr->pWpaRsnRspIE) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(session_ptr->pWpaRsnRspIE, + nIeLen + 2, 0); + session_ptr->pWpaRsnRspIE[0] = DOT11F_EID_RSN; + session_ptr->pWpaRsnRspIE[1] = (uint8_t) nIeLen; + /* copy upto akm_suites */ + pIeBuf = session_ptr->pWpaRsnRspIE + 2; + cdf_mem_copy(pIeBuf, &rsnie->version, + sizeof(rsnie->version)); + pIeBuf += sizeof(rsnie->version); + cdf_mem_copy(pIeBuf, &rsnie->gp_cipher_suite, + sizeof(rsnie->gp_cipher_suite)); + pIeBuf += sizeof(rsnie->gp_cipher_suite); + cdf_mem_copy(pIeBuf, &rsnie->pwise_cipher_suite_count, + sizeof(rsnie->pwise_cipher_suite_count)); + pIeBuf += sizeof(rsnie->pwise_cipher_suite_count); + if (rsnie->pwise_cipher_suite_count) { + /* copy pwise_cipher_suites */ + cdf_mem_copy(pIeBuf, rsnie->pwise_cipher_suites, + rsnie->pwise_cipher_suite_count * 4); + pIeBuf += rsnie->pwise_cipher_suite_count * 4; + } + cdf_mem_copy(pIeBuf, &rsnie->akm_suite_count, 2); + pIeBuf += 2; + if (rsnie->akm_suite_count) { + /* copy akm_suites */ + cdf_mem_copy(pIeBuf, rsnie->akm_suites, + rsnie->akm_suite_count * 4); + pIeBuf += rsnie->akm_suite_count * 4; + } + /* copy the rest */ + cdf_mem_copy(pIeBuf, rsnie->akm_suites + + rsnie->akm_suite_count * 4, + 2 + rsnie->pmkid_count * 4); + session_ptr->nWpaRsnRspIeLength = nIeLen + 2; + } + } else if ((eCSR_AUTH_TYPE_WPA == auth_type) || + (eCSR_AUTH_TYPE_WPA_PSK == auth_type)) { + if (ie_local->WPA.present) { + tDot11fIEWPA *wpaie = &ie_local->WPA; + /* Calculate the actual length wpaie */ + nIeLen = 12 + 2 /* auth_suite_count */ + + wpaie->unicast_cipher_count * 4 + + wpaie->auth_suite_count * 4; + + /* The WPA capabilities follows the Auth Suite + * (two octects)-- this field is optional, and + * we always "send" zero, so just remove it. This is + * consistent with our assumptions in the frames + * compiler; nIeLen doesn't count EID & length fields */ + session_ptr->pWpaRsnRspIE = cdf_mem_malloc(nIeLen + 2); + if (NULL == session_ptr->pWpaRsnRspIE) + return CDF_STATUS_E_NOMEM; + session_ptr->pWpaRsnRspIE[0] = DOT11F_EID_WPA; + session_ptr->pWpaRsnRspIE[1] = (uint8_t) nIeLen; + pIeBuf = session_ptr->pWpaRsnRspIE + 2; + /* Copy WPA OUI */ + cdf_mem_copy(pIeBuf, &csr_wpa_oui[1], 4); + pIeBuf += 4; + cdf_mem_copy(pIeBuf, &wpaie->version, + 8 + wpaie->unicast_cipher_count * 4); + pIeBuf += 8 + wpaie->unicast_cipher_count * 4; + cdf_mem_copy(pIeBuf, &wpaie->auth_suite_count, + 2 + wpaie->auth_suite_count * 4); + pIeBuf += wpaie->auth_suite_count * 4; + session_ptr->nWpaRsnRspIeLength = nIeLen + 2; + } + } +#ifdef FEATURE_WLAN_WAPI + else if ((eCSR_AUTH_TYPE_WAPI_WAI_PSK == auth_type) || + (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == + auth_type)) { + if (ie_local->WAPI.present) { + tDot11fIEWAPI *wapi_ie = &ie_local->WAPI; + /* Calculate the actual length of wapi ie*/ + nIeLen = 4 + 2 /* pwise_cipher_suite_count */ + + wapi_ie->akm_suite_count * 4 + + wapi_ie->unicast_cipher_suite_count * 4 + + 6; /* gp_cipher_suite + preauth + reserved */ + + if (wapi_ie->bkid_count) + nIeLen += 2 + wapi_ie->bkid_count * 4; + + /* nIeLen doesn't count EID and length fields */ + session_ptr->pWapiRspIE = + cdf_mem_malloc(nIeLen + 2); + if (NULL == session_ptr->pWapiRspIE) + return CDF_STATUS_E_NOMEM; + session_ptr->pWapiRspIE[0] = DOT11F_EID_WAPI; + session_ptr->pWapiRspIE[1] = (uint8_t) nIeLen; + pIeBuf = session_ptr->pWapiRspIE + 2; + /* copy upto akm_suite_count */ + cdf_mem_copy(pIeBuf, &wapi_ie->version, 2); + pIeBuf += 4; + if (wapi_ie->akm_suite_count) { + /* copy akm_suites */ + cdf_mem_copy(pIeBuf, + wapi_ie->akm_suites, + wapi_ie->akm_suite_count * 4); + pIeBuf += wapi_ie->akm_suite_count * 4; + } + cdf_mem_copy(pIeBuf, + &wapi_ie->unicast_cipher_suite_count, 2); + pIeBuf += 2; + if (wapi_ie->unicast_cipher_suite_count) { + uint16_t suite_size = + wapi_ie->unicast_cipher_suite_count * 4; + /* copy pwise_cipher_suites */ + cdf_mem_copy(pIeBuf, + wapi_ie->unicast_cipher_suites, + suite_size); + pIeBuf += suite_size; + } + /* gp_cipher_suite */ + cdf_mem_copy(pIeBuf, + wapi_ie->multicast_cipher_suite, 4); + pIeBuf += 4; + /* preauth + reserved */ + cdf_mem_copy(pIeBuf, + wapi_ie->multicast_cipher_suite + 4, 2); + pIeBuf += 2; + if (wapi_ie->bkid_count) { + /* bkid_count */ + cdf_mem_copy(pIeBuf, &wapi_ie->bkid_count, 2); + pIeBuf += 2; + /* copy akm_suites */ + cdf_mem_copy(pIeBuf, wapi_ie->bkid, + wapi_ie->bkid_count * 4); + pIeBuf += wapi_ie->bkid_count * 4; + } + session_ptr->nWapiRspIeLength = nIeLen + 2; + } + } +#endif /* FEATURE_WLAN_WAPI */ + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS csr_roam_save_security_rsp_ie(tpAniSirGlobal pMac, + uint32_t sessionId, + eCsrAuthType authType, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tDot11fBeaconIEs *pIesLocal = pIes; + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:csr_roam_save_security_rsp_ie")); + } +#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 && !CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies(pMac, + pSirBssDesc, &pIesLocal))) + sms_log(pMac, LOGE, FL(" cannot parse IEs")); + if (pIesLocal) { + status = csr_roam_save_params(pMac, pSession, authType, + pIes, pIesLocal); + if (!pIes) + /* locally allocated */ + cdf_mem_free(pIesLocal); + } + } + return status; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* Returns whether the current association is a 11r assoc or not */ +bool csr_roam_is11r_assoc(tpAniSirGlobal pMac, uint8_t sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csr_neighbor_roam_is11r_assoc(pMac, sessionId); +#else + return false; +#endif +} +#endif +#ifdef FEATURE_WLAN_ESE +/* Returns whether the current association is a ESE assoc or not */ +bool csr_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId) +{ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + return csr_neighbor_roam_is_ese_assoc(pMac, sessionId); +#else + return false; +#endif +} +#endif +#ifdef FEATURE_WLAN_LFR +/* Returns whether "Legacy Fast Roaming" is currently enabled...or not */ +bool csr_roam_is_fast_roam_enabled(tpAniSirGlobal pMac, uint32_t 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 != + CDF_STA_MODE) { + return false; + } + } + } + if (true == CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac)) { + return pMac->roam.configParam.isFastRoamIniFeatureEnabled; + } else { + return pMac->roam.configParam.isFastRoamIniFeatureEnabled && + (!csr_is_concurrent_session_running(pMac)); + } +} + +#ifdef FEATURE_WLAN_ESE +/** + * csr_neighbor_roam_is_ese_assoc() - Check the Association type + * @mac_ctx: Global MAC Context + * @session_id: Session ID on which the check should be done + * + * This function returns whether the current association + * is a ESE assoc or not + * + * Return: True if ESE association, false otherwise. + **/ +bool csr_neighbor_roam_is_ese_assoc(tpAniSirGlobal mac_ctx, uint8_t session_id) +{ + return mac_ctx->roam.neighborRoamInfo[session_id].isESEAssoc; +} +#endif /* FEATURE_WLAN_ESE */ + +/* Returns whether "FW based BG scan" is currently enabled...or not */ +bool csr_roam_is_roam_offload_scan_enabled(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.isRoamOffloadScanEnabled; +} +#endif + +#if defined(FEATURE_WLAN_ESE) +bool csr_roam_is_ese_ini_feature_enabled(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.isEseIniFeatureEnabled; +} +#endif /*FEATURE_WLAN_ESE */ + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +eCsrPhyMode csr_roamdot11mode_to_phymode(uint8_t 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 +CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tpSirSmeRoamOffloadSynchCnf pRoamOffloadSynchCnf; + cds_msg_t msg; + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + pRoamOffloadSynchCnf = + cdf_mem_malloc(sizeof(tSirSmeRoamOffloadSynchCnf)); + if (NULL == pRoamOffloadSynchCnf) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: not able to allocate memory for roam" + "offload synch confirmation data", __func__); + pSession->roamOffloadSynchParams.bRoamSynchInProgress = + false; + return CDF_STATUS_E_NOMEM; + } + pRoamOffloadSynchCnf->sessionId = sessionId; + msg.type = WMA_ROAM_OFFLOAD_SYNCH_CNF; + msg.reserved = 0; + msg.bodyptr = pRoamOffloadSynchCnf; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "LFR3: Posting WMA_ROAM_OFFLOAD_SYNCH_CNF"); + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "%s: Not able to post WMA_ROAM_OFFLOAD_SYNCH_CNF message to WMA", + __func__); + cdf_mem_free(pRoamOffloadSynchCnf); + pSession->roamOffloadSynchParams.bRoamSynchInProgress = + false; + return CDF_STATUS_E_FAILURE; + } + pSession->roamOffloadSynchParams.bRoamSynchInProgress = false; + return CDF_STATUS_SUCCESS; +} + +void csr_roam_synch_clean_up (tpAniSirGlobal mac, uint8_t session_id) +{ + cds_msg_t msg; + struct roam_offload_synch_fail *roam_offload_failed = NULL; + tCsrRoamSession *session = &mac->roam.roamSession[session_id]; + + /* Clean up the roam synch in progress for LFR3 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Roam Synch Failed, Clean Up", __func__); + session->roamOffloadSynchParams.bRoamSynchInProgress = false; + + roam_offload_failed = cdf_mem_malloc( + sizeof(struct roam_offload_synch_fail)); + if (NULL == roam_offload_failed) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: unable to allocate memory for roam synch fail" , + __func__); + return; + } + + roam_offload_failed->session_id = session_id; + msg.type = WMA_ROAM_OFFLOAD_SYNCH_FAIL; + msg.reserved = 0; + msg.bodyptr = roam_offload_failed; + if (!CDF_IS_STATUS_SUCCESS(cds_mq_post_message(CDF_MODULE_ID_WMA, + &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "%s: Unable to post WMA_ROAM_OFFLOAD_SYNCH_FAIL to WMA", + __func__); + cdf_mem_free(roam_offload_failed); + } +} +#endif + +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/** + * csr_roam_copy_ht_profile() - Copy from src to dst + * @dst_profile: Destination HT profile + * @src_profile: Source HT profile + * + * Copy the HT profile from the given source to destination + * + * Return: None + */ +static void csr_roam_copy_ht_profile(tCsrRoamHTProfile *dst_profile, + tSirSmeHTProfile *src_profile) +{ + dst_profile->phymode = + csr_roamdot11mode_to_phymode(src_profile->dot11mode); + dst_profile->htCapability = src_profile->htCapability; + dst_profile->htSupportedChannelWidthSet = + src_profile->htSupportedChannelWidthSet; + dst_profile->htRecommendedTxWidthSet = + src_profile->htRecommendedTxWidthSet; + dst_profile->htSecondaryChannelOffset = + src_profile->htSecondaryChannelOffset; +#ifdef WLAN_FEATURE_11AC + dst_profile->vhtCapability = src_profile->vhtCapability; + dst_profile->vhtTxChannelWidthSet = src_profile->vhtTxChannelWidthSet; + dst_profile->apCenterChan = src_profile->apCenterChan; + dst_profile->apChanWidth = src_profile->apChanWidth; +#endif +} +#endif + +/** + * csr_roam_process_results_default() - Process the result for start bss + * @mac_ctx: Global MAC Context + * @cmd: Command to be processed + * @context: Additional data in context of the cmd + * + * Return: None + */ +static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd, void *context, eCsrRoamCompleteResult res) +{ + uint32_t session_id = cmd->sessionId; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tCsrRoamInfo roam_info; + CDF_STATUS status; + + sms_log(mac_ctx, LOGW, FL("receives no association indication")); + sms_log(mac_ctx, LOG1, FL("Assoc ref count %d"), + session->bRefAssocStartCnt); + if (CSR_IS_INFRASTRUCTURE(&session->connectedProfile) + || CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ(mac_ctx, session_id)) { + /* + * do not free for the other profiles as we need + * to send down stop BSS later + */ + csr_free_connect_bss_desc(mac_ctx, session_id); + csr_roam_free_connect_profile(mac_ctx, + &session->connectedProfile); + csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); + csr_set_default_dot11_mode(mac_ctx); + } + + switch (cmd->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: + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE, + session_id); + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.pBssDesc = cmd->u.roamCmd.pLastRoamBss; + roam_info.pProfile = &cmd->u.roamCmd.roamProfile; + roam_info.statusCode = session->joinFailStatusCode.statusCode; + roam_info.reasonCode = session->joinFailStatusCode.reasonCode; + cdf_mem_copy(&roam_info.bssid, + &session->joinFailStatusCode.bssId, + sizeof(struct cdf_mac_addr)); + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + /* + * If Join fails while Handoff is in progress, indicate + * disassociated event to supplicant to reconnect + */ + if (csr_roam_is_handoff_in_progress(mac_ctx, session_id)) { + csr_neighbor_roam_indicate_connect(mac_ctx, + (uint8_t)session_id, CDF_STATUS_E_FAILURE); + } +#endif + if (session->bRefAssocStartCnt > 0) { + session->bRefAssocStartCnt--; + if (eCsrJoinFailureDueToConcurrency == res) + csr_roam_call_callback(mac_ctx, session_id, + &roam_info, cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL); + else + csr_roam_call_callback(mac_ctx, session_id, + &roam_info, cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } else { + /* + * bRefAssocStartCnt is not incremented when + * eRoamState == eCsrStopRoamingDueToConcurrency + * in csr_roam_join_next_bss API. so handle this in + * else case by sending assoc failure + */ + csr_roam_call_callback(mac_ctx, session_id, + &roam_info, cmd->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, + eCSR_ROAM_RESULT_FAILURE); + } + sms_log(mac_ctx, LOG1, FL("roam(reason %d) failed"), + cmd->u.roamCmd.roamReason); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_update_hand_off((uint8_t) session_id, false); + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, + SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csr_roam_completion(mac_ctx, session_id, NULL, cmd, + eCSR_ROAM_RESULT_FAILURE, false); +#ifdef FEATURE_WLAN_BTAMP_UT_RF + /* + * For WDS STA. To fix the issue where the WDS AP side may + * be too busy by BT activity and not able to receive + * WLAN traffic. Retry the join + */ + if (CSR_IS_WDS_STA(profile)) + csr_roam_start_join_retry_timer(mac_ctx, session_id, + CSR_JOIN_RETRY_TIMEOUT_PERIOD); +#endif + break; + case eCsrHddIssuedReassocToSameAP: + case eCsrSmeIssuedReassocToSameAP: + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE, + session_id); + + csr_roam_call_callback(mac_ctx, session_id, NULL, + cmd->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, + eCSR_ROAM_RESULT_FORCED); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, + SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csr_roam_completion(mac_ctx, session_id, NULL, cmd, + eCSR_ROAM_RESULT_FAILURE, false); + break; + case eCsrForcedDisassoc: + case eCsrForcedDeauth: + case eCsrSmeIssuedIbssJoinFailure: + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE, + session_id); + + if (eCsrSmeIssuedIbssJoinFailure == cmd->u.roamCmd.roamReason) + /* notify HDD that IBSS join failed */ + csr_roam_call_callback(mac_ctx, session_id, NULL, 0, + eCSR_ROAM_IBSS_IND, + eCSR_ROAM_RESULT_IBSS_JOIN_FAILED); + else + csr_roam_call_callback(mac_ctx, session_id, NULL, + cmd->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, + eCSR_ROAM_RESULT_FORCED); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, + SME_QOS_CSR_DISCONNECT_IND, + NULL); +#endif + csr_roam_link_down(mac_ctx, session_id); + + if (mac_ctx->roam.deauthRspStatus == eSIR_SME_DEAUTH_STATUS) { + sms_log(mac_ctx, LOGW, + FL("FW still in connected state")); + break; + } + break; + case eCsrForcedIbssLeave: + csr_roam_call_callback(mac_ctx, session_id, NULL, + cmd->u.roamCmd.roamId, eCSR_ROAM_IBSS_LEAVE, + eCSR_ROAM_RESULT_IBSS_STOP); + break; + case eCsrForcedDisassocMICFailure: + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE, + session_id); + + csr_roam_call_callback(mac_ctx, session_id, NULL, + cmd->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, + eCSR_ROAM_RESULT_MIC_FAILURE); +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, + SME_QOS_CSR_DISCONNECT_REQ, NULL); +#endif + break; + case eCsrStopBss: + csr_roam_call_callback(mac_ctx, session_id, NULL, + cmd->u.roamCmd.roamId, eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_STOPPED); + break; + case eCsrForcedDisassocSta: + case eCsrForcedDeauthSta: + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, + session_id); + session = CSR_GET_SESSION(mac_ctx, session_id); + if (CSR_IS_SESSION_VALID(mac_ctx, session_id) && + CSR_IS_INFRA_AP(&session->connectedProfile)) { + roam_info.u.pConnectedProfile = + &session->connectedProfile; + cdf_mem_copy(roam_info.peerMac.bytes, + cmd->u.roamCmd.peerMac, + sizeof(tSirMacAddr)); + roam_info.reasonCode = eCSR_ROAM_RESULT_FORCED; + roam_info.statusCode = eSIR_SME_SUCCESS; + status = csr_roam_call_callback(mac_ctx, session_id, + &roam_info, cmd->u.roamCmd.roamId, + eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_FORCED); + } + break; + case eCsrLostLink1: + /* if lost link roam1 failed, then issue lost link Scan2 ... */ + csr_scan_request_lost_link2(mac_ctx, session_id); + break; + case eCsrLostLink2: + /* if lost link roam2 failed, then issue lost link scan3 ... */ + csr_scan_request_lost_link3(mac_ctx, session_id); + break; + case eCsrLostLink3: + default: + csr_roam_state_change(mac_ctx, + eCSR_ROAMING_STATE_IDLE, session_id); + + /* We are done with one round of lostlink roaming here */ + csr_scan_handle_failed_lostlink3(mac_ctx, session_id); + break; + } +} + +/** + * csr_roam_process_start_bss_success() - Process the result for start bss + * @mac_ctx: Global MAC Context + * @cmd: Command to be processed + * @context: Additional data in context of the cmd + * + * Return: None + */ +static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd, void *context) +{ + uint32_t session_id = cmd->sessionId; + tCsrRoamProfile *profile = &cmd->u.roamCmd.roamProfile; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tSirBssDescription *bss_desc = NULL; + tCsrRoamInfo roam_info; + tSirSmeStartBssRsp *start_bss_rsp = NULL; + tCsrScanResult *scan_res = NULL; + eRoamCmdStatus roam_status; + eCsrRoamResult roam_result; + tDot11fBeaconIEs *ies_ptr = NULL; + tSirMacAddr bcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + CDF_STATUS status; + host_log_ibss_pkt_type *ibss_log; + uint32_t bi; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile *src_profile = NULL; + tCsrRoamHTProfile *dst_profile = NULL; +#endif + + /* + * 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. + */ + sms_log(mac_ctx, LOG2, FL("receives start BSS ok indication")); + status = CDF_STATUS_E_FAILURE; + start_bss_rsp = (tSirSmeStartBssRsp *) context; + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + if (CSR_IS_IBSS(profile)) + session->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; + else if (CSR_IS_INFRA_AP(profile)) + session->connectState = + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED; + else + session->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED; + if (!CSR_IS_WDS_STA(profile)) { + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, + session_id); + bss_desc = &start_bss_rsp->bssDescription; + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies(mac_ctx, bss_desc, + &ies_ptr))) { + sms_log(mac_ctx, LOGW, FL("cannot parse IBSS IEs")); + roam_info.pBssDesc = bss_desc; + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, eCSR_ROAM_IBSS_IND, + eCSR_ROAM_RESULT_IBSS_START_FAILED); + return; + } + if (!CSR_IS_INFRA_AP(profile)) { + scan_res = + csr_scan_append_bss_description(mac_ctx, + bss_desc, ies_ptr, false, + session_id); + } + csr_roam_save_connected_bss_desc(mac_ctx, session_id, bss_desc); + csr_roam_free_connect_profile(mac_ctx, + &session->connectedProfile); + csr_roam_free_connected_info(mac_ctx, + &session->connectedInfo); + if (bss_desc) { + csr_roam_save_connected_infomation(mac_ctx, session_id, + profile, bss_desc, ies_ptr); + cdf_mem_copy(&roam_info.bssid, &bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + } + /* We are done with the IEs so free it */ + cdf_mem_free(ies_ptr); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + WLAN_HOST_DIAG_LOG_ALLOC(ibss_log, + host_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if (ibss_log) { + if (CSR_INVALID_SCANRESULT_HANDLE == + cmd->u.roamCmd.hBSSList) { + /* + * We start the IBSS (didn't find any + * matched IBSS out there) + */ + ibss_log->eventId = + WLAN_IBSS_EVENT_START_IBSS_RSP; + } else { + ibss_log->eventId = + WLAN_IBSS_EVENT_JOIN_IBSS_RSP; + } + if (bss_desc) { + cdf_mem_copy(ibss_log->bssid, + bss_desc->bssId, 6); + ibss_log->operatingChannel = + bss_desc->channelId; + } + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int( + mac_ctx, + WNI_CFG_BEACON_INTERVAL, + &bi))) + /* U8 is not enough for BI */ + ibss_log->beaconInterval = (uint8_t) bi; + WLAN_HOST_DIAG_LOG_REPORT(ibss_log); + } +#endif + /* + * 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(profile->negotiatedUCEncryptionType) + && session->pCurRoamProfile + && !CSR_IS_INFRA_AP(session->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(session->pCurRoamProfile)) { + /* NO keys. these key parameters don't matter */ + csr_roam_issue_set_context_req(mac_ctx, + session_id, + profile->negotiatedMCEncryptionType, + bss_desc, &bcast_mac, false, + false, eSIR_TX_RX, 0, 0, NULL, 0); + } + + } + } else { + /* + * Keep the state to eCSR_ROAMING_STATE_JOINING. + * Need to send join_req. + */ + if (cmd->u.roamCmd.pRoamBssEntry) { + scan_res = GET_BASE_ADDR(cmd->u.roamCmd. + pRoamBssEntry, tCsrScanResult, Link); + if (scan_res) { + bss_desc = &scan_res->Result.BssDescriptor; + ies_ptr = (tDot11fBeaconIEs *) + (scan_res->Result.pvIes); + /* Set the roaming substate to join attempt */ + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_JOIN_REQ, + session_id); + status = csr_send_join_req_msg(mac_ctx, + session_id, bss_desc, + profile, ies_ptr, + eWNI_SME_JOIN_REQ); + } + } else { + sms_log(mac_ctx, LOGE, + "StartBSS for WDS station with no BssDesc"); + CDF_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(profile)) { + roam_status = eCSR_ROAM_IBSS_IND; + roam_result = eCSR_ROAM_RESULT_IBSS_STARTED; + if (CSR_IS_WDS(profile)) { + roam_status = eCSR_ROAM_WDS_IND; + roam_result = eCSR_ROAM_RESULT_WDS_STARTED; + } + if (CSR_IS_INFRA_AP(profile)) { + roam_status = eCSR_ROAM_INFRA_IND; + roam_result = 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 + */ + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.statusCode = session->joinFailStatusCode.statusCode; + roam_info.reasonCode = session->joinFailStatusCode.reasonCode; + /* We start the IBSS (didn't find any matched IBSS out there) */ + roam_info.pBssDesc = bss_desc; + roam_info.staId = (uint8_t) start_bss_rsp->staId; + cdf_mem_copy(roam_info.bssid.bytes, bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + if (!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && + (csr_is_concurrent_session_running(mac_ctx))) { + mac_ctx->roam.configParam.doBMPSWorkaround = 1; + } +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + dst_profile = &session->connectedProfile.HTProfile; + src_profile = &start_bss_rsp->HTProfile; + if (mac_ctx->roam.configParam.cc_switch_mode + != CDF_MCC_TO_SCC_SWITCH_DISABLE) + csr_roam_copy_ht_profile(dst_profile, src_profile); +#endif + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, + roam_status, roam_result); + } + + + if (CSR_IS_WDS_STA(profile)) { + /* need to send stop BSS because we fail to send join_req */ + csr_roam_issue_disassociate_cmd(mac_ctx, session_id, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, + eCSR_ROAM_WDS_IND, + eCSR_ROAM_RESULT_WDS_STOPPED); + } +} + +/** + * csr_roam_process_join_res() - Process the Join results + * @mac_ctx: Global MAC Context + * @result: Result after the command was processed + * @cmd: Command to be processed + * @context: Additional data in context of the cmd + * + * Process the join results which are obtained in a succesful join + * + * Return: None + */ +static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, + eCsrRoamCompleteResult res, tSmeCmd *cmd, void *context) +{ + tSirMacAddr bcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + sme_QosAssocInfo assoc_info; + uint32_t key_timeout_interval = 0; + uint8_t acm_mask = 0; /* HDD needs ACM mask in assoc rsp callback */ + uint32_t session_id = cmd->sessionId; + tCsrRoamProfile *profile = &cmd->u.roamCmd.roamProfile; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tSirBssDescription *bss_desc = NULL; + tCsrScanResult *scan_res = NULL; + sme_qos_csr_event_indType ind_qos; + csr_roam_offload_synch_params *roam_offload_params = NULL; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + tSirSmeHTProfile *src_profile = NULL; + tCsrRoamHTProfile *dst_profile = NULL; +#endif + tCsrRoamConnectedProfile *conn_profile = NULL; + tDot11fBeaconIEs *ies_ptr = NULL; + tCsrRoamInfo roam_info; + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + tSirSmeJoinRsp *join_rsp = (tSirSmeJoinRsp *) context; + uint32_t len; + + roam_offload_params = &session->roamOffloadSynchParams; + conn_profile = &session->connectedProfile; + if (eCsrReassocSuccess == res) + ind_qos = SME_QOS_CSR_REASSOC_COMPLETE; + else + ind_qos = SME_QOS_CSR_ASSOC_COMPLETE; + sms_log(mac_ctx, LOGW, FL("receives association indication")); + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + /* always free the memory here */ + if (session->pWpaRsnRspIE) { + session->nWpaRsnRspIeLength = 0; + cdf_mem_free(session->pWpaRsnRspIE); + session->pWpaRsnRspIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + if (session->pWapiRspIE) { + session->nWapiRspIeLength = 0; + cdf_mem_free(session->pWapiRspIE); + session->pWapiRspIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_BTAMP_UT_RF + session->maxRetryCount = 0; + csr_roam_stop_join_retry_timer(mac_ctx, session_id); +#endif + /* + * Reset remain_in_power_active_till_dhcp as + * it might have been set by last failed secured connection. + * It should be set only for secured connection. + */ + ps_global_info->remain_in_power_active_till_dhcp = false; + if (CSR_IS_INFRASTRUCTURE(profile)) + session->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + else + session->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 == cmd->u.roamCmd.roamReason) + || (eCsrSmeIssuedReassocToSameAP == + cmd->u.roamCmd.roamReason)) { + bss_desc = session->pConnectBssDesc; + if (bss_desc) + cdf_mem_copy(&roam_info.bssid, &bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + } else { + if (cmd->u.roamCmd.pRoamBssEntry) { + scan_res = GET_BASE_ADDR(cmd->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + if (scan_res != NULL) { + bss_desc = &scan_res->Result.BssDescriptor; + ies_ptr = (tDot11fBeaconIEs *) + (scan_res->Result.pvIes); + cdf_mem_copy(&roam_info.bssid, &bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + } + } + } + if (bss_desc) { + roam_info.staId = STA_INVALID_IDX; + csr_roam_save_connected_infomation(mac_ctx, session_id, + profile, bss_desc, ies_ptr); + /* Save WPA/RSN IE */ + csr_roam_save_security_rsp_ie(mac_ctx, session_id, + profile->negotiatedAuthType, bss_desc, ies_ptr); +#ifdef FEATURE_WLAN_ESE + roam_info.isESEAssoc = conn_profile->isESEAssoc; +#endif + + /* + * csr_roam_state_change also affects sub-state. + * Hence, csr_roam_state_change happens first and then + * substate change. + * Moving even save profile above so that below + * mentioned conditon is also met. + * JEZ100225: Moved to after saving the profile. + * Fix needed in main/latest + */ + csr_roam_state_change(mac_ctx, + eCSR_ROAMING_STATE_JOINED, session_id); + + /* + * 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). + * + * this reordering was done on titan_prod_usb branch + * and is being replicated here. + */ + + if (CSR_IS_ENC_TYPE_STATIC + (profile->negotiatedUCEncryptionType) && + !profile->bWPSAssociation) { + /* + * Issue the set Context request to LIM to establish + * the Unicast STA context + */ + if (!CDF_IS_STATUS_SUCCESS( + csr_roam_issue_set_context_req(mac_ctx, + session_id, + profile->negotiatedUCEncryptionType, + bss_desc, &(bss_desc->bssId), + false, true, + eSIR_TX_RX, 0, 0, NULL, 0))) { + /* NO keys. these key parameters don't matter */ + sms_log(mac_ctx, LOGE, + FL("Set context for unicast fail")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, session_id); + } + /* + * Issue the set Context request to LIM + * to establish the Broadcast STA context + * NO keys. these key parameters don't matter + */ + csr_roam_issue_set_context_req(mac_ctx, session_id, + profile->negotiatedMCEncryptionType, + bss_desc, &bcast_mac, false, false, + eSIR_TX_RX, 0, 0, NULL, 0); + } else { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_offload_params->bRoamSynchInProgress + && (roam_offload_params->authStatus + == CSR_ROAM_AUTH_STATUS_AUTHENTICATED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Don't start waitforkey timer")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, session_id); + } else { +#endif + /* Need to wait for supplicant authtication */ + roam_info.fAuthRequired = true; + /* + * Set the substate to WaitForKey in case + * authentiation is needed + */ + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, + session_id); + + /* + * Set remain_in_power_active_till_dhcp to make + * sure we wait for until keys are set before + * going into BMPS. + */ + ps_global_info->remain_in_power_active_till_dhcp + = true; + + if (profile->bWPSAssociation) + key_timeout_interval = + CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD; + else + key_timeout_interval = + CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD; + + /* Save session_id in case of timeout */ + mac_ctx->roam.WaitForKeyTimerInfo.sessionId = + (uint8_t) session_id; + /* + * This time should be long enough for the rest + * of the process plus setting key + */ + if (!CDF_IS_STATUS_SUCCESS + (csr_roam_start_wait_for_key_timer( + mac_ctx, key_timeout_interval)) + ) { + /* Reset state so nothing is blocked. */ + sms_log(mac_ctx, LOGE, FL + ("Failed preauth timer start")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, + session_id); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } +#endif + } + + assoc_info.pBssDesc = bss_desc; /* could be NULL */ + assoc_info.pProfile = profile; + if (context) { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_offload_params->bRoamSynchInProgress) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Clear Connected info")); +#endif + csr_roam_free_connected_info(mac_ctx, + &session->connectedInfo); + len = join_rsp->assocReqLength + + join_rsp->assocRspLength + + join_rsp->beaconLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + len += join_rsp->parsedRicRspLen; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + len += join_rsp->tspecIeLen; +#endif + if (len) { + session->connectedInfo.pbFrames = + cdf_mem_malloc(len); + if (session->connectedInfo.pbFrames != + NULL) { + cdf_mem_copy( + session->connectedInfo.pbFrames, + join_rsp->frames, len); + session->connectedInfo.nAssocReqLength = + join_rsp->assocReqLength; + session->connectedInfo.nAssocRspLength = + join_rsp->assocRspLength; + session->connectedInfo.nBeaconLength = + join_rsp->beaconLength; +#ifdef WLAN_FEATURE_VOWIFI_11R + session->connectedInfo.nRICRspLength = + join_rsp->parsedRicRspLen; +#endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef FEATURE_WLAN_ESE + session->connectedInfo.nTspecIeLength = + join_rsp->tspecIeLen; +#endif + roam_info.nAssocReqLength = + join_rsp->assocReqLength; + roam_info.nAssocRspLength = + join_rsp->assocRspLength; + roam_info.nBeaconLength = + join_rsp->beaconLength; + roam_info.pbFrames = + session->connectedInfo.pbFrames; + } + } + if (cmd->u.roamCmd.fReassoc) + roam_info.fReassocReq = + roam_info.fReassocRsp = true; + conn_profile->vht_channel_width = + join_rsp->vht_channel_width; + session->connectedInfo.staId = + (uint8_t) join_rsp->staId; + roam_info.staId = (uint8_t) join_rsp->staId; + roam_info.ucastSig = (uint8_t) join_rsp->ucastSig; + roam_info.bcastSig = (uint8_t) join_rsp->bcastSig; + roam_info.timingMeasCap = join_rsp->timingMeasCap; +#ifdef FEATURE_WLAN_TDLS + roam_info.tdls_prohibited = join_rsp->tdls_prohibited; + roam_info.tdls_chan_swit_prohibited = + join_rsp->tdls_chan_swit_prohibited; + sms_log(mac_ctx, LOG1, + FL("tdls:prohibit: %d, chan_swit_prohibit: %d"), + roam_info.tdls_prohibited, + roam_info.tdls_chan_swit_prohibited); +#endif +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + src_profile = &join_rsp->HTProfile; + dst_profile = &conn_profile->HTProfile; + if (mac_ctx->roam.configParam.cc_switch_mode + != CDF_MCC_TO_SCC_SWITCH_DISABLE) + csr_roam_copy_ht_profile(dst_profile, + src_profile); +#endif + } else { + if (cmd->u.roamCmd.fReassoc) { + roam_info.fReassocReq = + roam_info.fReassocRsp = true; + roam_info.nAssocReqLength = + session->connectedInfo.nAssocReqLength; + roam_info.nAssocRspLength = + session->connectedInfo.nAssocRspLength; + roam_info.nBeaconLength = + session->connectedInfo.nBeaconLength; + roam_info.pbFrames = + session->connectedInfo.pbFrames; + } + } + + /* + * Update the staId from the previous connected profile info + * as the reassociation is triggred at SME/HDD + */ + + if ((eCsrHddIssuedReassocToSameAP == + cmd->u.roamCmd.roamReason) || + (eCsrSmeIssuedReassocToSameAP == + cmd->u.roamCmd.roamReason)) + roam_info.staId = session->connectedInfo.staId; + +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + /* + * Indicate SME-QOS with reassoc success event, + * only after copying the frames + */ + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, ind_qos, + &assoc_info); +#endif + roam_info.pBssDesc = bss_desc; + roam_info.statusCode = + session->joinFailStatusCode.statusCode; + roam_info.reasonCode = + session->joinFailStatusCode.reasonCode; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_qos_get_acm_mask(mac_ctx, bss_desc, NULL); +#endif + conn_profile->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 (conn_profile->modifyProfileFields.uapsd_mask) { + sms_log(mac_ctx, LOGE, + " uapsd_mask (0x%X) set, request UAPSD now", + conn_profile->modifyProfileFields.uapsd_mask); + sme_ps_start_uapsd(mac_ctx, session_id, + NULL, NULL); + } + conn_profile->dot11Mode = session->bssParams.uCfgDot11Mode; + roam_info.u.pConnectedProfile = conn_profile; + + if (session->bRefAssocStartCnt > 0) { + session->bRefAssocStartCnt--; + if (!IS_FEATURE_SUPPORTED_BY_FW + (SLM_SESSIONIZATION) && + (csr_is_concurrent_session_running(mac_ctx))) { + mac_ctx->roam.configParam.doBMPSWorkaround = 1; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_offload_params->bRoamSynchInProgress) { + roam_info.roamSynchInProgress = 1; + roam_info.synchAuthStatus = + roam_offload_params->authStatus; + cdf_mem_copy(roam_info.kck, + roam_offload_params->kck, + SIR_KCK_KEY_LEN); + cdf_mem_copy(roam_info.kek, + roam_offload_params->kek, + SIR_KEK_KEY_LEN); + cdf_mem_copy(roam_info.replay_ctr, + roam_offload_params->replay_ctr, + SIR_REPLAY_CTR_LEN); + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL + ("LFR3: Copy KCK, KEK and Replay Ctr")); + } +#endif + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_ASSOCIATED); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_offload_params->bRoamSynchInProgress + && (roam_offload_params->authStatus + == CSR_ROAM_AUTH_STATUS_CONNECTED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Send Synch Cnf for Auth status connected")); + csr_roam_offload_send_synch_cnf(mac_ctx, + session_id); + } +#endif + } + + csr_roam_completion(mac_ctx, session_id, NULL, cmd, + eCSR_ROAM_RESULT_NONE, true); + csr_reset_pmkid_candidate_list(mac_ctx, session_id); +#ifdef FEATURE_WLAN_WAPI + csr_reset_bkid_candidate_list(mac_ctx, session_id); +#endif + } else { + sms_log(mac_ctx, LOGW, + "Roam command doesn't have a BSS desc"); + } + /* 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(mac_ctx, session_id)) { +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_offload_params->bRoamSynchInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL + ("NO CSR_IS_WAIT_FOR_KEY -> csr_roam_link_up")); + } +#endif + csr_roam_link_up(mac_ctx, conn_profile->bssid); + } +} + +/** + * csr_roam_process_results() - Process the Roam Results + * @mac_ctx: Global MAC Context + * @cmd: Command that has been processed + * @res: Results available after processing the command + * @context: Context + * + * Process the available results and make an appropriate decision + * + * Return: true if the command can be released, else not. + */ +static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, + eCsrRoamCompleteResult res, void *context) +{ + bool release_cmd = true; + tSirBssDescription *bss_desc = NULL; + tCsrRoamInfo roam_info; + uint32_t session_id = cmd->sessionId; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tCsrRoamProfile *profile = &cmd->u.roamCmd.roamProfile; + eRoamCmdStatus roam_status; + eCsrRoamResult roam_result; + host_log_ibss_pkt_type *ibss_log; + + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found "), session_id); + return false; + } + sms_log(mac_ctx, LOG1, FL("Processing ROAM results...")); + switch (res) { + case eCsrJoinSuccess: + case eCsrReassocSuccess: + csr_roam_process_join_res(mac_ctx, res, cmd, context); + break; + case eCsrStartBssSuccess: + csr_roam_process_start_bss_success(mac_ctx, cmd, context); + break; + case eCsrStartBssFailure: +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + WLAN_HOST_DIAG_LOG_ALLOC(ibss_log, + host_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if (ibss_log) { + ibss_log->status = WLAN_IBSS_STATUS_FAILURE; + WLAN_HOST_DIAG_LOG_REPORT(ibss_log); + } +#endif + roam_status = eCSR_ROAM_IBSS_IND; + roam_result = eCSR_ROAM_RESULT_IBSS_STARTED; + if (CSR_IS_WDS(profile)) { + roam_status = eCSR_ROAM_WDS_IND; + roam_result = eCSR_ROAM_RESULT_WDS_STARTED; + } + if (CSR_IS_INFRA_AP(profile)) { + roam_status = eCSR_ROAM_INFRA_IND; + roam_result = eCSR_ROAM_RESULT_INFRA_START_FAILED; + } + if (context) { + bss_desc = (tSirBssDescription *) context; + } else { + bss_desc = NULL; + } + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.pBssDesc = bss_desc; + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, roam_status, + roam_result); + csr_set_default_dot11_mode(mac_ctx); + break; + case eCsrSilentlyStopRoaming: + /* + * We are here because we try to start the same IBSS. + * No message to PE. return the roaming state to Joined. + */ + sms_log(mac_ctx, LOGW, FL("receives silently stop roam ind")); + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, + session_id); + csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE, + session_id); + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.pBssDesc = session->pConnectBssDesc; + if (roam_info.pBssDesc) + cdf_mem_copy(&roam_info.bssid, + &roam_info.pBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + /* + * Since there is no change in the current state, simply pass + * back no result otherwise HDD may be mistakenly mark to + * disconnected state. + */ + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->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 */ + sms_log(mac_ctx, LOGW, + FL("receives silently stop roaming indication")); + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + + /* to aviod resetting the substate to NONE */ + mac_ctx->roam.curState[session_id] = eCSR_ROAMING_STATE_JOINED; + /* + * No need to change substate to wai_for_key because there + * is no state change + */ + roam_info.pBssDesc = session->pConnectBssDesc; + if (roam_info.pBssDesc) + cdf_mem_copy(&roam_info.bssid, + &roam_info.pBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + roam_info.statusCode = session->joinFailStatusCode.statusCode; + roam_info.reasonCode = session->joinFailStatusCode.reasonCode; + roam_info.nBeaconLength = session->connectedInfo.nBeaconLength; + roam_info.nAssocReqLength = + session->connectedInfo.nAssocReqLength; + roam_info.nAssocRspLength = + session->connectedInfo.nAssocRspLength; + roam_info.pbFrames = session->connectedInfo.pbFrames; + roam_info.staId = session->connectedInfo.staId; + roam_info.u.pConnectedProfile = &session->connectedProfile; + if (0 == roam_info.staId) { + CDF_ASSERT(0); + return false; + } + session->bRefAssocStartCnt--; + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_ASSOCIATED); + csr_roam_completion(mac_ctx, session_id, NULL, cmd, + eCSR_ROAM_RESULT_ASSOCIATED, true); + break; + case eCsrReassocFailure: +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, + SME_QOS_CSR_REASSOC_FAILURE, NULL); +#endif + case eCsrJoinWdsFailure: + sms_log(mac_ctx, LOGW, FL("failed to join WDS")); + csr_free_connect_bss_desc(mac_ctx, session_id); + csr_roam_free_connect_profile(mac_ctx, + &session->connectedProfile); + csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.pBssDesc = cmd->u.roamCmd.pLastRoamBss; + roam_info.statusCode = session->joinFailStatusCode.statusCode; + roam_info.reasonCode = session->joinFailStatusCode.reasonCode; + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->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: + csr_roam_process_results_default(mac_ctx, cmd, context, res); + break; + } + return release_cmd; +} + +CDF_STATUS csr_roam_copy_profile(tpAniSirGlobal pMac, + tCsrRoamProfile *pDstProfile, + tCsrRoamProfile *pSrcProfile) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t size = 0; + + cdf_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0); + if (pSrcProfile->BSSIDs.numOfBSSIDs) { + size = sizeof(struct cdf_mac_addr) * pSrcProfile->BSSIDs.numOfBSSIDs; + pDstProfile->BSSIDs.bssid = cdf_mem_malloc(size); + if (NULL == pDstProfile->BSSIDs.bssid) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->BSSIDs.numOfBSSIDs = + pSrcProfile->BSSIDs.numOfBSSIDs; + cdf_mem_copy(pDstProfile->BSSIDs.bssid, + pSrcProfile->BSSIDs.bssid, size); + } + if (pSrcProfile->SSIDs.numOfSSIDs) { + size = sizeof(tCsrSSIDInfo) * pSrcProfile->SSIDs.numOfSSIDs; + pDstProfile->SSIDs.SSIDList = cdf_mem_malloc(size); + if (NULL == pDstProfile->SSIDs.SSIDList) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->SSIDs.numOfSSIDs = + pSrcProfile->SSIDs.numOfSSIDs; + cdf_mem_copy(pDstProfile->SSIDs.SSIDList, + pSrcProfile->SSIDs.SSIDList, size); + } + if (pSrcProfile->nWPAReqIELength) { + pDstProfile->pWPAReqIE = + cdf_mem_malloc(pSrcProfile->nWPAReqIELength); + if (NULL == pDstProfile->pWPAReqIE) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->nWPAReqIELength = + pSrcProfile->nWPAReqIELength; + cdf_mem_copy(pDstProfile->pWPAReqIE, pSrcProfile->pWPAReqIE, + pSrcProfile->nWPAReqIELength); + } + if (pSrcProfile->nRSNReqIELength) { + pDstProfile->pRSNReqIE = + cdf_mem_malloc(pSrcProfile->nRSNReqIELength); + if (NULL == pDstProfile->pRSNReqIE) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->nRSNReqIELength = + pSrcProfile->nRSNReqIELength; + cdf_mem_copy(pDstProfile->pRSNReqIE, pSrcProfile->pRSNReqIE, + pSrcProfile->nRSNReqIELength); + } +#ifdef FEATURE_WLAN_WAPI + if (pSrcProfile->nWAPIReqIELength) { + pDstProfile->pWAPIReqIE = + cdf_mem_malloc(pSrcProfile->nWAPIReqIELength); + if (NULL == pDstProfile->pWAPIReqIE) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->nWAPIReqIELength = + pSrcProfile->nWAPIReqIELength; + cdf_mem_copy(pDstProfile->pWAPIReqIE, pSrcProfile->pWAPIReqIE, + pSrcProfile->nWAPIReqIELength); + } +#endif /* FEATURE_WLAN_WAPI */ + if (pSrcProfile->nAddIEScanLength) { + pDstProfile->pAddIEScan = + cdf_mem_malloc(pSrcProfile->nAddIEScanLength); + if (NULL == pDstProfile->pAddIEScan) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->nAddIEScanLength = + pSrcProfile->nAddIEScanLength; + cdf_mem_copy(pDstProfile->pAddIEScan, pSrcProfile->pAddIEScan, + pSrcProfile->nAddIEScanLength); + } + if (pSrcProfile->nAddIEAssocLength) { + pDstProfile->pAddIEAssoc = + cdf_mem_malloc(pSrcProfile->nAddIEAssocLength); + if (NULL == pDstProfile->pAddIEAssoc) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->nAddIEAssocLength = + pSrcProfile->nAddIEAssocLength; + cdf_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc, + pSrcProfile->nAddIEAssocLength); + } + if (pSrcProfile->ChannelInfo.ChannelList) { + pDstProfile->ChannelInfo.ChannelList = + cdf_mem_malloc(pSrcProfile->ChannelInfo. + numOfChannels); + if (NULL == pDstProfile->ChannelInfo.ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + pDstProfile->ChannelInfo.numOfChannels = + pSrcProfile->ChannelInfo.numOfChannels; + cdf_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 (csr_is_profile_wapi(pSrcProfile)) + if (pDstProfile->phyMode & eCSR_DOT11_MODE_11n) + pDstProfile->phyMode &= ~eCSR_DOT11_MODE_11n; +#endif /* FEATURE_WLAN_WAPI */ + pDstProfile->CBMode = pSrcProfile->CBMode; + pDstProfile->ch_params.ch_width = pSrcProfile->ch_params.ch_width; + pDstProfile->ch_params.center_freq_seg0 = + pSrcProfile->ch_params.center_freq_seg0; + pDstProfile->ch_params.center_freq_seg1 = + pSrcProfile->ch_params.center_freq_seg1; + pDstProfile->ch_params.sec_ch_offset = + pSrcProfile->ch_params.sec_ch_offset; + /*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; + cdf_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 + cdf_mem_copy(&pDstProfile->addIeParams, &pSrcProfile->addIeParams, + sizeof(tSirAddIeParams)); +end: + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_release_profile(pMac, pDstProfile); + pDstProfile = NULL; + } + + return status; +} + +CDF_STATUS csr_roam_copy_connected_profile(tpAniSirGlobal pMac, + uint32_t sessionId, tCsrRoamProfile *pDstProfile) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamConnectedProfile *pSrcProfile = + &pMac->roam.roamSession[sessionId].connectedProfile; + + cdf_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0); + + pDstProfile->BSSIDs.bssid = cdf_mem_malloc(sizeof(struct cdf_mac_addr)); + if (NULL == pDstProfile->BSSIDs.bssid) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, + FL("failed to allocate memory for BSSID " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pSrcProfile->bssid.bytes)); + goto end; + } + pDstProfile->BSSIDs.numOfBSSIDs = 1; + cdf_copy_macaddr(pDstProfile->BSSIDs.bssid, &pSrcProfile->bssid); + + if (pSrcProfile->SSID.ssId) { + pDstProfile->SSIDs.SSIDList = + cdf_mem_malloc(sizeof(tCsrSSIDInfo)); + if (NULL == pDstProfile->SSIDs.SSIDList) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, + FL("failed to allocate memory for SSID " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pSrcProfile->bssid.bytes)); + goto end; + } + pDstProfile->SSIDs.numOfSSIDs = 1; + pDstProfile->SSIDs.SSIDList[0].handoffPermitted = + pSrcProfile->handoffPermitted; + pDstProfile->SSIDs.SSIDList[0].ssidHidden = + pSrcProfile->ssidHidden; + cdf_mem_copy(&pDstProfile->SSIDs.SSIDList[0].SSID, + &pSrcProfile->SSID, sizeof(tSirMacSSid)); + } + if (pSrcProfile->nAddIEAssocLength) { + pDstProfile->pAddIEAssoc = + cdf_mem_malloc(pSrcProfile->nAddIEAssocLength); + if (NULL == pDstProfile->pAddIEAssoc) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, + FL("failed to allocate mem for additional ie")); + goto end; + } + pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength; + cdf_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc, + pSrcProfile->nAddIEAssocLength); + } + pDstProfile->ChannelInfo.ChannelList = cdf_mem_malloc(1); + if (NULL == pDstProfile->ChannelInfo.ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + 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; + cdf_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 + +end: + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_release_profile(pMac, pDstProfile); + pDstProfile = NULL; + } + + return status; +} + +CDF_STATUS csr_roam_issue_connect(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tScanResultHandle hBSSList, + eCsrRoamReason reason, uint32_t roamId, + bool fImediate, bool fClearScan) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + } else { + if (fClearScan) { + csr_scan_abort_mac_scan_not_for_connect(pMac, sessionId); + } + pCommand->u.roamCmd.fReleaseProfile = 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 = + CDF_STA_MODE; + } else { + /* make a copy of the profile */ + status = + csr_roam_copy_profile(pMac, + &pCommand->u.roamCmd.roamProfile, + pProfile); + if (CDF_IS_STATUS_SUCCESS(status)) { + pCommand->u.roamCmd.fReleaseProfile = true; + } + } + + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) 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 = true; + pCommand->u.roamCmd.fUpdateCurRoamProfile = true; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("CSR PERSONA=%d"), + pCommand->u.roamCmd.roamProfile.csrPersona); + status = csr_queue_sme_command(pMac, pCommand, fImediate); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } + + return status; +} + +CDF_STATUS csr_roam_issue_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields *pMmodProfileFields, + eCsrRoamReason reason, uint32_t roamId, + bool fImediate) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + } else { + csr_scan_abort_mac_scan_not_for_connect(pMac, sessionId); + if (pProfile) { + /* This is likely trying to reassoc to different profile */ + pCommand->u.roamCmd.fReleaseProfile = false; + /* make a copy of the profile */ + status = + csr_roam_copy_profile(pMac, + &pCommand->u.roamCmd.roamProfile, + pProfile); + pCommand->u.roamCmd.fUpdateCurRoamProfile = true; + } else { + status = + csr_roam_copy_connected_profile(pMac, sessionId, + &pCommand->u.roamCmd. + roamProfile); + /* how to update WPA/WPA2 info in roamProfile?? */ + pCommand->u.roamCmd.roamProfile.uapsd_mask = + pMmodProfileFields->uapsd_mask; + } + if (CDF_IS_STATUS_SUCCESS(status)) { + pCommand->u.roamCmd.fReleaseProfile = true; + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) 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 bool set to false */ + pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + pCommand->u.roamCmd.fReleaseBssList = false; + pCommand->u.roamCmd.fReassoc = true; + csr_roam_remove_duplicate_command(pMac, sessionId, pCommand, + reason); + status = csr_queue_sme_command(pMac, pCommand, fImediate); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_roam_completion(pMac, sessionId, NULL, pCommand, + eCSR_ROAM_RESULT_FAILURE, false); + csr_release_command_roam(pMac, pCommand); + } + } + return status; +} + +CDF_STATUS csr_roam_enqueue_preauth(tpAniSirGlobal pMac, uint32_t sessionId, + tpSirBssDescription pBssDescription, + eCsrRoamReason reason, bool fImmediate) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + } else { + if (pBssDescription) { + /* copy over the parameters we need later */ + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) 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 = csr_queue_sme_command(pMac, pCommand, fImmediate); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + (" fail to enqueue preauth command, status = %d"), + status); + csr_release_command_preauth(pMac, pCommand); + } + } else { + /* Return failure */ + status = CDF_STATUS_E_RESOURCES; + } + } + return status; +} + +CDF_STATUS csr_dequeue_roam_command(tpAniSirGlobal pMac, eCsrRoamReason reason) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if ((eSmeCommandRoam == pCommand->command) && + (eCsrPerformPreauth == reason)) { + sms_log(pMac, LOG1, FL("DQ-Command = %d, Reason = %d"), + pCommand->command, + pCommand->u.roamCmd.roamReason); + if (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + csr_release_command_preauth(pMac, pCommand); + } + } else if ((eSmeCommandRoam == pCommand->command) && + (eCsrSmeIssuedFTReassoc == reason)) { + sms_log(pMac, LOG1, FL("DQ-Command = %d, Reason = %d"), + pCommand->command, + pCommand->u.roamCmd.roamReason); + if (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + csr_release_command_roam(pMac, pCommand); + } + } else { + sms_log(pMac, LOGE, FL("Command = %d, Reason = %d "), + pCommand->command, + pCommand->u.roamCmd.roamReason); + } + } else { + sms_log(pMac, LOGE, + FL("pEntry NULL for eWNI_SME_FT_PRE_AUTH_RSP")); + } + sme_process_pending_queue(pMac); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + uint32_t *pRoamId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tScanResultHandle hBSSList; + tCsrScanResultFilter *pScanFilter; + uint32_t roamId = 0; + bool fCallCallback = false; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tSirBssDescription first_ap_profile; + + if (NULL == pSession) { + sms_log(pMac, LOGE, + FL("session does not exist for given sessionId:%d"), + sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (NULL == pProfile) { + sms_log(pMac, LOGP, FL("No profile specified")); + return CDF_STATUS_E_FAILURE; + } + /* Initialize the count before proceeding with the Join requests */ + pSession->join_bssid_count = 0; + sms_log(pMac, LOG1, + FL("called BSSType = %d authtype = %d encryType = %d"), + pProfile->BSSType, pProfile->AuthType.authType[0], + pProfile->EncryptionType.encryptionType[0]); + csr_roam_cancel_roaming(pMac, sessionId); + csr_scan_remove_fresh_scan_command(pMac, sessionId); + /* Only abort the scan if its not used for other roam/connect purpose */ + csr_scan_abort_mac_scan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT); + csr_roam_remove_duplicate_command(pMac, sessionId, NULL, eCsrHddIssued); + /* Check whether ssid changes */ + if (csr_is_conn_state_connected(pMac, sessionId) && + pProfile->SSIDs.numOfSSIDs && !csr_is_ssid_in_list(pMac, + &pSession->connectedProfile.SSID, &pProfile->SSIDs)) + csr_roam_issue_disassociate_cmd(pMac, sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); +#ifdef FEATURE_WLAN_BTAMP_UT_RF + pSession->maxRetryCount = CSR_JOIN_MAX_RETRY_COUNT; +#endif + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + + cdf_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; + } else { + /* Here is the profile we need to connect to */ + status = csr_roam_prepare_filter_from_profile(pMac, + pProfile, pScanFilter); + } + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if (pRoamId) + *pRoamId = roamId; + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pScanFilter); + goto end; + } + + /*Save the WPS info */ + if (NULL != pProfile) { + pScanFilter->bWPSAssociation = + pProfile->bWPSAssociation; + pScanFilter->bOSENAssociation = + pProfile->bOSENAssociation; + } else { + pScanFilter->bWPSAssociation = 0; + pScanFilter->bOSENAssociation = 0; + } + if ((pProfile && CSR_IS_WDS_AP(pProfile)) || (pProfile + && CSR_IS_INFRA_AP(pProfile))) { + /* This can be started right away */ + status = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL, + eCsrHddIssued, roamId, false, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("CSR failed to issue start BSS cmd with status = 0x%08X"), + status); + fCallCallback = true; + } else { + sms_log(pMac, LOG1, + FL("Connect request to proceed for sap mode")); + } + + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + goto end; + } + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + sms_log(pMac, LOG1, + FL("******* csr_scan_get_result Status ****** %d"), status); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* check if set hw mode needs to be done */ + if ((pMac->policy_manager_enabled) && + (pScanFilter->csrPersona == CDF_STA_MODE)) { + csr_get_bssdescr_from_scan_handle(hBSSList, + &first_ap_profile); + if (!cds_handle_conc_multiport(sessionId, + first_ap_profile.channelId)) { + sms_log(pMac, LOG1, FL("conc multiport error")); + csr_scan_result_purge(pMac, hBSSList); + fCallCallback = true; + goto error; + } + } + + status = csr_roam_issue_connect(pMac, sessionId, pProfile, + hBSSList, eCsrHddIssued, roamId, false, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("CSR failed to issue connect cmd with status = 0x%08X"), + status); + csr_scan_result_purge(pMac, hBSSList); + fCallCallback = true; + } + } else if (NULL != pProfile) { + /* Check whether it is for start ibss */ + if (CSR_IS_START_IBSS(pProfile)) { + status = csr_roam_issue_connect(pMac, sessionId, + pProfile, NULL, eCsrHddIssued, + roamId, false, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("CSR failed to issue startIBSS cmd with status = 0x%08X"), + status); + fCallCallback = true; + } + } else { + /* scan for this SSID */ + status = csr_scan_for_ssid(pMac, sessionId, pProfile, + roamId, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("CSR failed to issue SSID scan cmd with status = 0x%08X"), + status); + fCallCallback = true; + } else { + sms_log(pMac, LOG1, + FL("SSID scan requested")); + } + } + } else { + fCallCallback = true; + } + +error: + if (NULL != pProfile) + /* + * we need to free memory for filter + * if profile exists + */ + csr_free_scan_filter(pMac, pScanFilter); + + cdf_mem_free(pScanFilter); +end: + /* tell the caller if we fail to trigger a join request */ + if (fCallCallback) { + csr_roam_call_callback(pMac, sessionId, NULL, roamId, + eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE); + } + return status; +} + +/** + * csr_roam_reassoc() - process reassoc command + * @mac_ctx: mac global context + * @session_id: session id + * @profile: roam profile + * @mod_fields: AC info being modified in reassoc + * @roam_id: roam id to be populated + * + * Return: status of operation + */ +CDF_STATUS +csr_roam_reassoc(tpAniSirGlobal mac_ctx, uint32_t session_id, + tCsrRoamProfile *profile, + tCsrRoamModifyProfileFields mod_fields, + uint32_t *roam_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool fCallCallback = true; + uint32_t roamId = 0; + + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == profile) { + sms_log(mac_ctx, LOGP, FL("No profile specified")); + return CDF_STATUS_E_FAILURE; + } + sms_log(mac_ctx, LOG1, + FL("called BSSType = %d authtype = %d encryType = %d"), + profile->BSSType, profile->AuthType.authType[0], + profile->EncryptionType.encryptionType[0]); + csr_roam_cancel_roaming(mac_ctx, session_id); + csr_scan_remove_fresh_scan_command(mac_ctx, session_id); + csr_scan_abort_mac_scan_not_for_connect(mac_ctx, session_id); + csr_roam_remove_duplicate_command(mac_ctx, session_id, NULL, + eCsrHddIssuedReassocToSameAP); + if (csr_is_conn_state_connected(mac_ctx, session_id)) { + if (profile) { + if (profile->SSIDs.numOfSSIDs && + csr_is_ssid_in_list(mac_ctx, + &session->connectedProfile.SSID, + &profile->SSIDs)) { + fCallCallback = false; + } else { + /* + * Connected SSID did not match with what is + * asked in profile + */ + sms_log(mac_ctx, LOG1, FL("SSID mismatch")); + } + } else if (!cdf_mem_compare(&mod_fields, + &session->connectedProfile.modifyProfileFields, + sizeof(tCsrRoamModifyProfileFields))) { + fCallCallback = false; + } else { + sms_log(mac_ctx, LOG1, + /* + * Either the profile is NULL or none of the + * fields in tCsrRoamModifyProfileFields got + * modified + */ + FL("Profile NULL or nothing to modify.")); + } + } else { + sms_log(mac_ctx, LOG1, FL("Not connected! No need to reassoc")); + } + if (!fCallCallback) { + roamId = GET_NEXT_ROAM_ID(&mac_ctx->roam); + if (roam_id) + *roam_id = roamId; + status = csr_roam_issue_reassoc(mac_ctx, session_id, profile, + &mod_fields, eCsrHddIssuedReassocToSameAP, + roamId, false); + } else { + status = csr_roam_call_callback(mac_ctx, session_id, NULL, + roamId, eCSR_ROAM_FAILED, + eCSR_ROAM_RESULT_FAILURE); + } + return status; +} + +CDF_STATUS csr_roam_join_last_profile(tpAniSirGlobal pMac, uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tScanResultHandle hBSSList = NULL; + tCsrScanResultFilter *pScanFilter = NULL; + uint32_t roamId; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pSession->pCurRoamProfile) { + csr_scan_abort_mac_scan_not_for_connect(pMac, sessionId); + /* We have to make a copy of pCurRoamProfile because it + * will be free inside csr_roam_issue_connect */ + pProfile = cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (NULL == pProfile) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + cdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + status = csr_roam_copy_profile(pMac, pProfile, + pSession->pCurRoamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) { + status = CDF_STATUS_E_NOMEM; + goto end; + } + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csr_roam_prepare_filter_from_profile(pMac, pProfile, + pScanFilter); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* we want to put the last connected BSS to the + * very beginning, if possible */ + csr_move_bss_to_head_from_bssid(pMac, + &pSession->connectedProfile.bssid, hBSSList); + status = csr_roam_issue_connect(pMac, sessionId, + pProfile, hBSSList, eCsrHddIssued, + roamId, false, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_scan_result_purge(pMac, hBSSList); + goto end; + } + } else { + /* scan for this SSID only incase AP suppresses SSID */ + status = csr_scan_for_ssid(pMac, sessionId, pProfile, + roamId, true); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto end; + } + } /* We have a profile */ + else { + sms_log(pMac, LOGW, FL("cannot find a roaming profile")); + goto end; + } +end: + if (pScanFilter) { + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + } + if (NULL != pProfile) { + csr_release_profile(pMac, pProfile); + cdf_mem_free(pProfile); + } + return status; +} + +CDF_STATUS csr_roam_reconnect(tpAniSirGlobal pMac, uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + if (csr_is_conn_state_connected(pMac, sessionId)) { + status = + csr_roam_issue_disassociate_cmd(pMac, sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = csr_roam_join_last_profile(pMac, sessionId); + } + } + return status; +} + +CDF_STATUS csr_roam_connect_to_last_profile(tpAniSirGlobal pMac, uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + sms_log(pMac, LOGW, FL("is called")); + csr_roam_cancel_roaming(pMac, sessionId); + csr_roam_remove_duplicate_command(pMac, sessionId, NULL, eCsrHddIssued); + if (csr_is_conn_state_disconnected(pMac, sessionId)) { + status = csr_roam_join_last_profile(pMac, sessionId); + } + return status; +} + +CDF_STATUS csr_roam_process_disassoc_deauth(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fDisassoc, bool fMICFailure) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool fComplete = false; + eCsrRoamSubState NewSubstate; + uint32_t sessionId = pCommand->sessionId; + + if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) { + sms_log(pMac, LOG1, + FL(" Stop Wait for key timer and change substate to" + " eCSR_ROAM_SUBSTATE_NONE")); + csr_roam_stop_wait_for_key_timer(pMac); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId); + } + /* change state to 'Roaming'... */ + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + + if (csr_is_conn_state_ibss(pMac, sessionId)) { + /* If we are in an IBSS, then stop the IBSS... */ + status = + csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); + fComplete = (!CDF_IS_STATUS_SUCCESS(status)); + } else if (csr_is_conn_state_infra(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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL + ("set to substate eCSR_ROAM_SUBSTATE_DISASSOC_STA_HAS_LEFT")); + } + if (fDisassoc) { + status = + csr_roam_issue_disassociate(pMac, sessionId, + NewSubstate, fMICFailure); + } else { + status = + csr_roam_issue_deauth(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DEAUTH_REQ); + } + fComplete = (!CDF_IS_STATUS_SUCCESS(status)); + } else if (csr_is_conn_state_wds(pMac, sessionId)) { + if (CSR_IS_WDS_AP + (&pMac->roam.roamSession[sessionId].connectedProfile)) { + status = + csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); + fComplete = (!CDF_IS_STATUS_SUCCESS(status)); + } + /* This has to be WDS station */ + else if (csr_is_conn_state_connected_wds(pMac, sessionId)) { + /* This has to be WDS station */ + pCommand->u.roamCmd.fStopWds = true; + if (fDisassoc) { + status = + csr_roam_issue_disassociate(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, + fMICFailure); + fComplete = (!CDF_IS_STATUS_SUCCESS(status)); + } + } + } else { + /* we got a dis-assoc request while not connected to any peer */ + /* just complete the command */ + fComplete = true; + status = CDF_STATUS_E_FAILURE; + } + if (fComplete) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } + + if (CDF_IS_STATUS_SUCCESS(status)) { + if (csr_is_conn_state_infra(pMac, sessionId)) { + /* Set the state to disconnect here */ + pMac->roam.roamSession[sessionId].connectState = + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } + } else { + sms_log(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: CDF_STATUS_SUCCESS on success else CDF_STATUS_E_RESOURCES on failure + */ + +CDF_STATUS csr_prepare_disconnect_command(tpAniSirGlobal mac, + uint32_t session_id, tSmeCmd **sme_cmd) +{ + tSmeCmd *command; + + command = csr_get_command_buffer(mac); + if (!command) { + sms_log(mac, LOGE, FL("fail to get command buffer")); + return CDF_STATUS_E_RESOURCES; + } + + command->command = eSmeCommandRoam; + command->sessionId = (uint8_t)session_id; + command->u.roamCmd.roamReason = eCsrForcedDisassoc; + + *sme_cmd = command; + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + bool fHighPriority = false; + do { + pCommand = csr_get_command_buffer(pMac); + if (!pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + break; + } + /* Change the substate in case it is wait-for-key */ + if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) { + csr_roam_stop_wait_for_key_timer(pMac); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + sessionId); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) sessionId; + sms_log(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: + fHighPriority = true; + 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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL + ("SME convert to internal reason code eCsrStaHasLeft")); + break; + default: + break; + } + status = csr_queue_sme_command(pMac, pCommand, fHighPriority); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } while (0); + return status; +} + +CDF_STATUS csr_roam_issue_stop_bss_cmd(tpAniSirGlobal pMac, uint32_t sessionId, + bool fHighPriority) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csr_get_command_buffer(pMac); + if (NULL != pCommand) { + /* Change the substate in case it is wait-for-key */ + if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) { + csr_roam_stop_wait_for_key_timer(pMac); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + sessionId); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.roamCmd.roamReason = eCsrStopBss; + status = csr_queue_sme_command(pMac, pCommand, fHighPriority); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } else { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + status = CDF_STATUS_E_RESOURCES; + } + return status; +} + +CDF_STATUS csr_roam_disconnect_internal(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } +#ifdef FEATURE_WLAN_BTAMP_UT_RF + /* Stop the retry */ + pSession->maxRetryCount = 0; + csr_roam_stop_join_retry_timer(pMac, sessionId); +#endif + /* Not to call cancel roaming here */ + /* Only issue disconnect when necessary */ + if (csr_is_conn_state_connected(pMac, sessionId) + || csr_is_bss_type_ibss(pSession->connectedProfile.BSSType) + || csr_is_bss_type_wds(pSession->connectedProfile.BSSType) + || csr_is_roam_command_waiting_for_session(pMac, sessionId)) { + sms_log(pMac, LOG2, FL("called")); + status = csr_roam_issue_disassociate_cmd(pMac, sessionId, + reason); + } else { + csr_scan_abort_scan_for_ssid(pMac, sessionId); + status = CDF_STATUS_CMD_NOT_QUEUED; + sms_log(pMac, LOG1, + FL + (" Disconnect cmd not queued, Roam command is not present" + " return with status %d"), status); + } + return status; +} + +CDF_STATUS csr_roam_disconnect(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + csr_roam_cancel_roaming(pMac, sessionId); + csr_roam_remove_duplicate_command(pMac, sessionId, NULL, + eCsrForcedDisassoc); + + return csr_roam_disconnect_internal(pMac, sessionId, reason); +} + +CDF_STATUS csr_roam_save_connected_infomation(tpAniSirGlobal pMac, + uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tDot11fBeaconIEs *pIesTemp = pIes; + uint8_t index; + tCsrRoamSession *pSession = NULL; + tCsrRoamConnectedProfile *pConnectProfile = NULL; + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + pConnectProfile = &pSession->connectedProfile; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("csr_roam_save_connected_infomation")); + } +#endif + if (pConnectProfile->pAddIEAssoc) { + cdf_mem_free(pConnectProfile->pAddIEAssoc); + pConnectProfile->pAddIEAssoc = NULL; + } + cdf_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) { + sms_log(pMac, LOGW, FL("ERROR: Beacon interval is ZERO")); + } + cdf_mem_copy(&pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys)); + /* saving the addional IE`s like Hot spot indication element and extended capabilities */ + if (pProfile->nAddIEAssocLength) { + pConnectProfile->pAddIEAssoc = + cdf_mem_malloc(pProfile->nAddIEAssocLength); + if (NULL == pConnectProfile->pAddIEAssoc) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("Failed to allocate memory for additional IEs")); + return CDF_STATUS_E_FAILURE; + } + pConnectProfile->nAddIEAssocLength = + pProfile->nAddIEAssocLength; + cdf_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 */ + csr_get_bss_id_bss_desc(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 = + csr_get_parsed_bss_description_ies(pMac, pSirBssDesc, + &pIesTemp); + } +#ifdef FEATURE_WLAN_ESE + if ((csr_is_profile_ese(pProfile) || + (CDF_IS_STATUS_SUCCESS(status) && (pIesTemp->ESEVersion.present) + && (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM))) + && (pMac->roam.configParam.isEseIniFeatureEnabled)) { + pConnectProfile->isESEAssoc = 1; + } +#endif + /* save ssid */ + if (CDF_IS_STATUS_SUCCESS(status)) { + if (pIesTemp->SSID.present) { + pConnectProfile->SSID.length = pIesTemp->SSID.num_ssid; + cdf_mem_copy(pConnectProfile->SSID.ssId, + pIesTemp->SSID.ssid, + pIesTemp->SSID.num_ssid); + } + /* Save the bss desc */ + status = + csr_roam_save_connected_bss_desc(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-> + proxy_arp_service; + } + + if (NULL == pIes) { + /* Free memory if it allocated locally */ + cdf_mem_free(pIesTemp); + } + } + /* Save Qos connection */ + pConnectProfile->qosConnection = + pMac->roam.roamSession[sessionId].fWMMConnection; + + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_free_connect_bss_desc(pMac, sessionId); + } + for (index = 0; index < pProfile->SSIDs.numOfSSIDs; index++) { + if ((pProfile->SSIDs.SSIDList[index].SSID.length == + pConnectProfile->SSID.length) + && cdf_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; +} + + +static bool is_disconnect_pending(tpAniSirGlobal pmac, + uint8_t sessionid) +{ + tListElem *entry = NULL; + tListElem *next_entry = NULL; + tSmeCmd *command = NULL; + bool disconnect_cmd_exist = false; + + csr_ll_lock(&pmac->sme.smeCmdPendingList); + entry = csr_ll_peek_head(&pmac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK); + while (entry) { + next_entry = csr_ll_next(&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; + } + csr_ll_unlock(&pmac->sme.smeCmdPendingList); + return disconnect_cmd_exist; +} + +static void csr_roam_join_rsp_processor(tpAniSirGlobal pMac, + tSirSmeJoinRsp *pSmeJoinRsp) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamSession *session_ptr; + + if (pSmeJoinRsp) { + session_ptr = CSR_GET_SESSION(pMac, pSmeJoinRsp->sessionId); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Sme Join Response is NULL")); + return; + } + if (!session_ptr) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session %d not found"), pSmeJoinRsp->sessionId); + return; + } + /* The head of the active list is the request we sent */ + pEntry = csr_ll_peek_head(&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_qos_csr_event_ind(pMac, pSmeJoinRsp->sessionId, + SME_QOS_CSR_HANDOFF_COMPLETE, NULL); +#endif + } + /* * + * The join bssid count can be reset as soon as + * we are done with the join requests and returning + * the response to upper layers + * */ + session_ptr->join_bssid_count = 0; + csr_roam_complete(pMac, eCsrJoinSuccess, (void *)pSmeJoinRsp); + } else { + uint32_t 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; + } + session_ptr->joinFailStatusCode.statusCode = + pSmeJoinRsp->statusCode; + session_ptr->joinFailStatusCode.reasonCode = + pSmeJoinRsp->protStatusCode; + sms_log(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 (csr_roam_is_handoff_in_progress(pMac, pSmeJoinRsp->sessionId)) { + csr_roam_call_callback(pMac, pSmeJoinRsp->sessionId, NULL, + roamId, eCSR_ROAM_DISASSOCIATED, + eCSR_ROAM_RESULT_FORCED); + /* Should indicate neighbor roam algorithm about the connect failure here */ + csr_neighbor_roam_indicate_connect(pMac, + pSmeJoinRsp->sessionId, + CDF_STATUS_E_FAILURE); + } +#endif + /* + * if userspace has issued disconnection, + * driver should not continue connecting + */ + is_dis_pending = is_disconnect_pending(pMac, session_ptr->sessionId); + if (pCommand && (session_ptr->join_bssid_count < + CSR_MAX_BSSID_COUNT) && !is_dis_pending) { + if (CSR_IS_WDS_STA(&pCommand->u.roamCmd.roamProfile)) { + pCommand->u.roamCmd.fStopWds = true; + session_ptr->connectedProfile.BSSType = + eCSR_BSS_TYPE_WDS_STA; + csr_roam_reissue_roam_command(pMac); + } else if (CSR_IS_WDS(&pCommand->u.roamCmd.roamProfile)) { + session_ptr->join_bssid_count = 0; + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } else { + csr_roam(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 (session_ptr->join_bssid_count >= + CSR_MAX_BSSID_COUNT) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Excessive Join Req Failures")); + + if (is_dis_pending) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("disconnect is pending, complete roam")); + + session_ptr->join_bssid_count = 0; + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } + } /*else: ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) */ +} + +CDF_STATUS csr_roam_issue_join(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile, + uint32_t roamId) +{ + CDF_STATUS status; + sms_log(pMac, LOG1, "Attempting to Join Bssid= " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pSirBssDesc->bssId)); + + /* Set the roaming substate to 'join attempt'... */ + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId); + /* attempt to Join this BSS... */ + status = + csr_send_join_req_msg(pMac, sessionId, pSirBssDesc, pProfile, pIes, + eWNI_SME_JOIN_REQ); + return status; +} + +static CDF_STATUS csr_roam_issue_reassociate(tpAniSirGlobal pMac, + uint32_t sessionId, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, + tCsrRoamProfile *pProfile) +{ + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_JOINING, sessionId); + /* Set the roaming substate to 'join attempt'... */ + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL(" calling csr_send_join_req_msg (eWNI_SME_REASSOC_REQ)")); + /* attempt to Join this BSS... */ + return csr_send_join_req_msg(pMac, sessionId, pSirBssDesc, pProfile, pIes, + eWNI_SME_REASSOC_REQ); +} + +void csr_roam_reissue_roam_command(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + tCsrRoamInfo roamInfo; + uint32_t sessionId; + tCsrRoamSession *pSession; + + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (NULL == pEntry) { + sms_log(pMac, LOGE, + FL("Disassoc rsp can't continue, no active CMD")); + return; + } + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandRoam != pCommand->command) { + sms_log(pMac, LOGW, FL("Active cmd, is not a roaming CMD")); + return; + } + sessionId = pCommand->sessionId; + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return; + } + + if (!pCommand->u.roamCmd.fStopWds) { + if (pSession->bRefAssocStartCnt > 0) { + /* + * bRefAssocStartCnt was incremented in + * csr_roam_join_next_bss when the roam command issued + * previously. As part of reissuing the roam command + * again csr_roam_join_next_bss is going increment + * RefAssocStartCnt. So make sure to decrement the + * bRefAssocStartCnt + */ + pSession->bRefAssocStartCnt--; + } + if (eCsrStopRoaming == csr_roam_join_next_bss(pMac, pCommand, + true)) { + sms_log(pMac, LOGW, + FL("Failed to reissue join command")); + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } + return; + } + cdf_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; + csr_roam_call_callback(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; + csr_roam_call_callback(pMac, sessionId, &roamInfo, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_DISASSOCIATED); + } + + if (!CDF_IS_STATUS_SUCCESS(csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_STOP_BSS_REQ))) { + sms_log(pMac, LOGE, + FL("Failed to reissue stop_bss command for WDS")); + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } +} + +bool csr_is_roam_command_waiting_for_session(tpAniSirGlobal pMac, uint32_t sessionId) +{ + bool fRet = false; + tListElem *pEntry; + tSmeCmd *pCommand = NULL; + /* alwasy lock active list before locking pending list */ + csr_ll_lock(&pMac->sme.smeCmdActiveList); + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if ((eSmeCommandRoam == pCommand->command) + && (sessionId == pCommand->sessionId)) { + fRet = true; + } + } + if (false == fRet) { + csr_ll_lock(&pMac->sme.smeCmdPendingList); + pEntry = + csr_ll_peek_head(&pMac->sme.smeCmdPendingList, + LL_ACCESS_NOLOCK); + while (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if ((eSmeCommandRoam == pCommand->command) + && (sessionId == pCommand->sessionId)) { + fRet = true; + break; + } + pEntry = + csr_ll_next(&pMac->sme.smeCmdPendingList, pEntry, + LL_ACCESS_NOLOCK); + } + csr_ll_unlock(&pMac->sme.smeCmdPendingList); + } + if (false == fRet) { + csr_ll_lock(&pMac->roam.roamCmdPendingList); + pEntry = + csr_ll_peek_head(&pMac->roam.roamCmdPendingList, + LL_ACCESS_NOLOCK); + while (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if ((eSmeCommandRoam == pCommand->command) + && (sessionId == pCommand->sessionId)) { + fRet = true; + break; + } + pEntry = + csr_ll_next(&pMac->roam.roamCmdPendingList, pEntry, + LL_ACCESS_NOLOCK); + } + csr_ll_unlock(&pMac->roam.roamCmdPendingList); + } + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + return fRet; +} + +bool csr_is_roam_command_waiting(tpAniSirGlobal pMac) +{ + bool fRet = false; + uint32_t i; + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + fRet = csr_is_roam_command_waiting_for_session(pMac, i); + if (CSR_IS_SESSION_VALID(pMac, i) + && (fRet)) { + break; + } + } + return fRet; +} + +bool csr_is_command_waiting(tpAniSirGlobal pMac) +{ + bool fRet = false; + /* alwasy lock active list before locking pending list */ + csr_ll_lock(&pMac->sme.smeCmdActiveList); + fRet = csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if (false == fRet) { + fRet = + csr_ll_is_list_empty(&pMac->sme.smeCmdPendingList, + LL_ACCESS_LOCK); + } + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + return fRet; +} + +bool csr_is_scan_for_roam_command_active(tpAniSirGlobal pMac) +{ + bool fRet = false; + tListElem *pEntry; + tCsrCmd *pCommand; + /* alwasy lock active list before locking pending list */ + csr_ll_lock(&pMac->sme.smeCmdActiveList); + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tCsrCmd, Link); + if ((eCsrRoamCommandScan == pCommand->command) && + ((eCsrScanForSsid == pCommand->u.scanCmd.reason) || + (eCsrScanP2PFindPeer == pCommand->u.scanCmd.reason))) { + fRet = true; + } + } + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + return fRet; +} + +CDF_STATUS csr_roam_issue_reassociate_cmd(tpAniSirGlobal pMac, uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand = NULL; + bool fHighPriority = true; + bool fRemoveCmd = false; + tListElem *pEntry; + /* Delete the old assoc command. All is setup for reassoc to be serialized */ + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (!pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + return CDF_STATUS_E_RESOURCES; + } + if (eSmeCommandRoam == pCommand->command) { + if (pCommand->u.roamCmd.roamReason == + eCsrSmeIssuedAssocToSimilarAP) { + fRemoveCmd = + csr_ll_remove_entry(&pMac->sme. + smeCmdActiveList, pEntry, + LL_ACCESS_LOCK); + } else { + sms_log(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) { + sms_log(pMac, LOGE, + FL + (" fail to get command buffer as expected based on previous connect roam command")); + return CDF_STATUS_E_RESOURCES; + } + do { + /* Change the substate in case it is wait-for-key */ + if (CSR_IS_WAIT_FOR_KEY(pMac, sessionId)) { + csr_roam_stop_wait_for_key_timer(pMac); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + sessionId); + } + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.roamCmd.roamReason = eCsrSmeIssuedFTReassoc; + status = csr_queue_sme_command(pMac, pCommand, fHighPriority); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + csr_release_command_roam(pMac, pCommand); + } + } while (0); + + return status; +} + +static void +csr_roaming_state_config_cnf_processor(tpAniSirGlobal mac_ctx, + uint32_t result) +{ + tListElem *entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + tCsrScanResult *scan_result = NULL; + tSirBssDescription *bss_desc = NULL; + tSmeCmd *cmd = NULL; + uint32_t session_id; + tCsrRoamSession *session; + tDot11fBeaconIEs *local_ies = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (NULL == entry) { + sms_log(mac_ctx, LOGE, FL("CFG_CNF with active list empty")); + return; + } + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + session_id = cmd->sessionId; + session = CSR_GET_SESSION(mac_ctx, session_id); + + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id); + return; + } + + if (CSR_IS_ROAMING(session) && session->fCancelRoaming) { + /* the roaming is cancelled. Simply complete the command */ + sms_log(mac_ctx, LOGW, FL("Roam command canceled")); + csr_roam_complete(mac_ctx, eCsrNothingToJoin, NULL); + return; + } + + /* If the roaming has stopped, not to continue the roaming command */ + if (!CSR_IS_ROAMING(session) && CSR_IS_ROAMING_COMMAND(cmd)) { + /* No need to complete roaming here as it already completes */ + sms_log(mac_ctx, LOGW, + FL("Roam cmd (reason %d) aborted(roaming completed)"), + cmd->u.roamCmd.roamReason); + csr_set_abort_roaming_command(mac_ctx, cmd); + csr_roam_complete(mac_ctx, eCsrNothingToJoin, NULL); + return; + } + + if (!IS_SIR_STATUS_SUCCESS(result)) { + /* + * In the event the configuration failed, for infra let the roam + * processor attempt to join something else... + */ + if (cmd->u.roamCmd.pRoamBssEntry + && CSR_IS_INFRASTRUCTURE(&cmd->u.roamCmd.roamProfile)) { + csr_roam(mac_ctx, cmd); + } else { + /* We need to complete the command */ + if (csr_is_bss_type_ibss + (cmd->u.roamCmd.roamProfile.BSSType)) { + csr_roam_complete(mac_ctx, eCsrStartBssFailure, + NULL); + } else { + csr_roam_complete(mac_ctx, eCsrNothingToJoin, + NULL); + } + } + return; + } + + /* we have active entry */ + sms_log(mac_ctx, LOG2, "Cfg sequence complete"); + /* + * Successfully set the configuration parameters for the new Bss. + * Attempt to join the roaming Bss + */ + if (cmd->u.roamCmd.pRoamBssEntry) { + scan_result = GET_BASE_ADDR(cmd->u.roamCmd.pRoamBssEntry, + tCsrScanResult, + Link); + bss_desc = &scan_result->Result.BssDescriptor; + } + if (csr_is_bss_type_ibss(cmd->u.roamCmd.roamProfile.BSSType) + || CSR_IS_WDS(&cmd->u.roamCmd.roamProfile) + || CSR_IS_INFRA_AP(&cmd->u.roamCmd.roamProfile)) { + if (!CDF_IS_STATUS_SUCCESS(csr_roam_issue_start_bss(mac_ctx, + session_id, &session->bssParams, + &cmd->u.roamCmd.roamProfile, + bss_desc, + cmd->u.roamCmd.roamId))) { + sms_log(mac_ctx, LOGE, FL("CSR start BSS failed")); + /* We need to complete the command */ + csr_roam_complete(mac_ctx, eCsrStartBssFailure, NULL); + } + return; + } + + if (!cmd->u.roamCmd.pRoamBssEntry) { + sms_log(mac_ctx, LOGE, FL("pRoamBssEntry is NULL")); + /* We need to complete the command */ + csr_roam_complete(mac_ctx, eCsrJoinFailure, NULL); + return; + } + + if (NULL == scan_result) { + /* If we are roaming TO an Infrastructure BSS... */ + CDF_ASSERT(scan_result != NULL); + return; + } + + if (!csr_is_infra_bss_desc(bss_desc)) { + sms_log(mac_ctx, LOGW, + FL("found BSSType mismatching the one in BSS descp")); + return; + } + + local_ies = (tDot11fBeaconIEs *) scan_result->Result.pvIes; + if (!local_ies) { + status = csr_get_parsed_bss_description_ies(mac_ctx, bss_desc, + &local_ies); + if (!CDF_IS_STATUS_SUCCESS(status)) + return; + } + + if (csr_is_conn_state_connected_infra(mac_ctx, session_id)) { + if (csr_is_ssid_equal(mac_ctx, session->pConnectBssDesc, + bss_desc, local_ies)) { + cmd->u.roamCmd.fReassoc = true; + csr_roam_issue_reassociate(mac_ctx, session_id, + bss_desc, local_ies, + &cmd->u.roamCmd.roamProfile); + } else { + /* + * otherwise, we have to issue a new Join request to LIM + * because we disassociated from the previously + * associated AP. + */ + status = csr_roam_issue_join(mac_ctx, session_id, + bss_desc, local_ies, + &cmd->u.roamCmd.roamProfile, + cmd->u.roamCmd.roamId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* try something else */ + csr_roam(mac_ctx, cmd); + } + } + } else { + status = CDF_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 (csr_roam_is_handoff_in_progress(mac_ctx, session_id) + && csr_roam_is11r_assoc(mac_ctx, session_id)) { + status = csr_roam_issue_reassociate(mac_ctx, + session_id, bss_desc, + (tDot11fBeaconIEs *) + (scan_result->Result.pvIes), + &cmd->u.roamCmd.roamProfile); + } else +#endif +#ifdef FEATURE_WLAN_ESE + if (csr_roam_is_handoff_in_progress(mac_ctx, session_id) + && csr_roam_is_ese_assoc(mac_ctx, session_id)) { + /* Now serialize the reassoc command. */ + status = csr_roam_issue_reassociate_cmd(mac_ctx, + session_id); + } else +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_handoff_in_progress(mac_ctx, session_id) + && csr_roam_is_fast_roam_enabled(mac_ctx, session_id)) { + /* Now serialize the reassoc command. */ + status = csr_roam_issue_reassociate_cmd(mac_ctx, + session_id); + } else +#endif + { + /* + * else we are not connected and attempting to Join. Issue the + * Join request. + */ + status = csr_roam_issue_join(mac_ctx, session_id, + bss_desc, + (tDot11fBeaconIEs *) + (scan_result->Result.pvIes), + &cmd->u.roamCmd.roamProfile, + cmd->u.roamCmd.roamId); + } + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* try something else */ + csr_roam(mac_ctx, cmd); + } + } + if (!scan_result->Result.pvIes) { + /* Locally allocated */ + cdf_mem_free(local_ies); + } +} + +static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, + tpSirSmeJoinRsp pSmeJoinRsp) +{ + eCsrRoamCompleteResult result; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pSmeJoinRsp->sessionId]; + tCsrRoamInfo roamInfo; + uint32_t roamId = 0; + + if (eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("CSR SmeReassocReq Successful")); + result = eCsrReassocSuccess; + /* Defeaturize this part later if needed */ +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + /* Since the neighbor roam algorithm uses reassoc req for handoff instead of join, + * we need the response contents while processing the result in csr_roam_process_results() */ + if (csr_roam_is_handoff_in_progress(pMac, pSmeJoinRsp->sessionId)) { + /* Need to dig more on indicating events to SME QoS module */ + sme_qos_csr_event_ind(pMac, pSmeJoinRsp->sessionId, + SME_QOS_CSR_HANDOFF_COMPLETE, NULL); + csr_roam_complete(pMac, result, pSmeJoinRsp); + } else +#endif + { + csr_roam_complete(pMac, result, NULL); + } + } + /* Should we handle this similar to handling the join failure? Is it ok + * to call csr_roam_complete() with state as CsrJoinFailure */ + else { + sms_log(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_INVALID_PARAMETERS == + pSmeJoinRsp->statusCode)) { + /* Inform HDD to turn off FT flag in HDD */ + if (pNeighborRoamInfo) { + cdf_mem_zero(&roamInfo, sizeof(tCsrRoamInfo)); + csr_roam_call_callback(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. + */ + csr_roam_complete(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 (!CDF_IS_STATUS_SUCCESS + (csr_roam_issue_disassociate + (pMac, pSmeJoinRsp->sessionId, + eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, false))) { + csr_roam_complete(pMac, eCsrJoinFailure, NULL); + } + } +} + +static void csr_roam_roaming_state_stop_bss_rsp_processor(tpAniSirGlobal pMac, + tSirSmeRsp *pSmeRsp) +{ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + host_log_ibss_pkt_type *pIbssLog; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_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_HOST_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)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } else + if (CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE + (pMac, pSmeRsp->sessionId)) { + csr_roam_reissue_roam_command(pMac); + } +} + +/** + * csr_dequeue_command() - removes a command from active cmd list + * @pMac: mac global context + * + * Return: void + */ +static void +csr_dequeue_command(tpAniSirGlobal mac_ctx) +{ + bool fRemoveCmd; + tSmeCmd *cmd = NULL; + tListElem *entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac_ctx, LOGE, FL("NO commands are active")); + return; + } + + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + /* + * If the head of the queue is Active and it is a given cmd type, remove + * and put this on the Free queue. + */ + if (eSmeCommandRoam != cmd->command) { + sms_log(mac_ctx, LOGE, FL("Roam command not active")); + return; + } + /* + * 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 = csr_ll_remove_entry(&mac_ctx->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK); + if (cmd->u.roamCmd.fReleaseProfile) { + csr_release_profile(mac_ctx, &cmd->u.roamCmd.roamProfile); + cmd->u.roamCmd.fReleaseProfile = false; + } + if (fRemoveCmd) + csr_release_command_roam(mac_ctx, cmd); + else + sms_log(mac_ctx, LOGE, FL("fail to remove cmd reason %d"), + cmd->u.roamCmd.roamReason); +} + +/** + * csr_post_roam_failure() - post roam failure back to csr and issues a disassoc + * @pMac: mac global context + * @session_id: session id + * @roam_info: roam info struct + * @scan_filter: scan filter to free + * @cur_roam_profile: current csr roam profile + * + * Return: void + */ +static void +csr_post_roam_failure(tpAniSirGlobal mac_ctx, + uint32_t session_id, + tCsrRoamInfo *roam_info, + tCsrScanResultFilter *scan_filter, + tCsrRoamProfile *cur_roam_profile) +{ + CDF_STATUS status; + + if (scan_filter) { + csr_free_scan_filter(mac_ctx, scan_filter); + cdf_mem_free(scan_filter); + } + if (cur_roam_profile) + cdf_mem_free(cur_roam_profile); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + csr_roam_synch_clean_up(mac_ctx, session_id); +#endif + /* Inform the upper layers that the reassoc failed */ + cdf_mem_zero(roam_info, sizeof(tCsrRoamInfo)); + csr_roam_call_callback(mac_ctx, session_id, roam_info, 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 csr_roam_complete which would remove the roam + * command from SME active queue. + */ + status = csr_roam_issue_disassociate(mac_ctx, session_id, + eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("csr_roam_issue_disassociate failed, status %d"), + status); + csr_roam_complete(mac_ctx, eCsrJoinFailure, NULL); + } +} + +/** + * csr_check_profile_in_scan_cache() - finds if roam profile is present in scan + * cache or not + * @pMac: mac global context + * @scan_filter: out param, scan filter + * @neighbor_roam_info: roam info struct + * @hBSSList: scan result + * + * Return: true if found else false. + */ +static bool +csr_check_profile_in_scan_cache(tpAniSirGlobal mac_ctx, + tCsrScanResultFilter **scan_filter, + tpCsrNeighborRoamControlInfo neighbor_roam_info, + tScanResultHandle *hBSSList) +{ + CDF_STATUS status; + *scan_filter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == *scan_filter) { + sms_log(mac_ctx, LOGE, FL("alloc for ScanFilter failed.")); + return false; + } + cdf_mem_set(*scan_filter, sizeof(tCsrScanResultFilter), 0); + (*scan_filter)->scan_filter_for_roam = 1; + status = csr_roam_prepare_filter_from_profile(mac_ctx, + &neighbor_roam_info->csrNeighborRoamProfile, + *scan_filter); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("failed to prepare scan filter, status %d"), + status); + return false; + } + status = csr_scan_get_result(mac_ctx, *scan_filter, hBSSList); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("csr_scan_get_result failed, status %d"), + status); + return false; + } + return true; +} + +void csr_roam_roaming_state_disassoc_rsp_processor(tpAniSirGlobal pMac, + tSirSmeDisassocRsp *pSmeRsp) +{ +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + tScanResultHandle hBSSList; + tCsrRoamInfo roamInfo; + tCsrScanResultFilter *pScanFilter = NULL; + uint32_t roamId = 0; + tCsrRoamProfile *pCurRoamProfile = NULL; +#endif + CDF_STATUS status; + uint32_t sessionId; + tCsrRoamSession *pSession; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL; + tSirSmeDisassocRsp SmeDisassocRsp; + + csr_ser_des_unpack_diassoc_rsp((uint8_t *) pSmeRsp, &SmeDisassocRsp); + sessionId = SmeDisassocRsp.sessionId; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, FL("sessionId %d"), + sessionId); + + if (csr_is_conn_state_infra(pMac, sessionId)) { + pMac->roam.roamSession[sessionId].connectState = + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return; + } + + if (CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN(pMac, sessionId)) { + sms_log(pMac, LOG2, "***eCsrNothingToJoin***"); + csr_roam_complete(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 == SmeDisassocRsp.statusCode) { + sms_log(pMac, LOG2, + FL("CSR force disassociated successful")); + /* + * A callback to HDD will be issued from + * csr_roam_complete so no need to do anything here + */ + } + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } else if (CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("CSR SmeDisassocReq due to HO on session %d"), + sessionId); + pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + /* + * First ensure if the roam profile is in the scan cache. + * If not, post a reassoc failure and disconnect. + */ + if (!csr_check_profile_in_scan_cache(pMac, &pScanFilter, + pNeighborRoamInfo, &hBSSList)) + goto POST_ROAM_FAILURE; + + /* + * After ensuring that the roam profile is in the scan result + * list, dequeue the command from the active list. + */ + csr_dequeue_command(pMac); + + /* notify HDD about handoff and provide the BSSID too */ + roamInfo.reasonCode = eCsrRoamReasonBetterAP; + + cdf_copy_macaddr(&roamInfo.bssid, + pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid); + + csr_roam_call_callback(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 = cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (pCurRoamProfile != NULL) { + /* + * notify sub-modules like QoS etc. that handoff + * happening + */ + sme_qos_csr_event_ind(pMac, sessionId, + SME_QOS_CSR_HANDOFF_ASSOC_REQ, + NULL); + cdf_mem_set(pCurRoamProfile, sizeof(tCsrRoamProfile), + 0); + csr_roam_copy_profile(pMac, pCurRoamProfile, + pSession->pCurRoamProfile); + /* make sure to put it at the head of the cmd queue */ + status = csr_roam_issue_connect(pMac, sessionId, + pCurRoamProfile, hBSSList, + eCsrSmeIssuedAssocToSimilarAP, + roamId, true, false); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGE, + FL("issue_connect failed. status %d"), + status); + + csr_release_profile(pMac, pCurRoamProfile); + cdf_mem_free(pCurRoamProfile); + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return; + } + +POST_ROAM_FAILURE: + csr_post_roam_failure(pMac, sessionId, &roamInfo, + pScanFilter, pCurRoamProfile); +#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 */ + csr_roam_complete(pMac, eCsrJoinFailure, NULL); + } else { + if (eSIR_SME_SUCCESS == SmeDisassocRsp.statusCode) { + /* + * Successfully disassociated from the 'old' Bss. + * We get Disassociate response in three conditions. + * 1) The case where we are disasociating from an Infra + * Bss to start an IBSS. + * 2) When we are disassociating from an Infra Bss to + * join an IBSS or a new infra network. + * 3) 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 + */ + sms_log(pMac, LOG2, + FL("Disassociated successfully")); + } else { + sms_log(pMac, LOGE, + FL("DisassocReq failed, statusCode= 0x%08X"), + SmeDisassocRsp.statusCode); + } + /* We are not done yet. Get the data and continue roaming */ + csr_roam_reissue_roam_command(pMac); + } +} + +static void csr_roam_roaming_state_deauth_rsp_processor(tpAniSirGlobal pMac, + tSirSmeDeauthRsp *pSmeRsp) +{ + tSirResultCodes statusCode; + /* No one is sending eWNI_SME_DEAUTH_REQ to PE. */ + sms_log(pMac, LOGW, FL("is no-op")); + statusCode = csr_get_de_auth_rsp_status_code(pSmeRsp); + pMac->roam.deauthRspStatus = statusCode; + if (CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(pMac, pSmeRsp->sessionId)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL); + } else { + if (eSIR_SME_SUCCESS == statusCode) { + /* Successfully deauth from the 'old' Bss... */ + /* */ + sms_log(pMac, LOG2, + "CSR SmeDeauthReq disassociated Successfully"); + } else { + sms_log(pMac, LOGW, + "SmeDeauthReq failed with statusCode= 0x%08X", + statusCode); + } + /* We are not done yet. Get the data and continue roaming */ + csr_roam_reissue_roam_command(pMac); + } +} + +static void csr_roam_roaming_state_start_bss_rsp_processor(tpAniSirGlobal pMac, + tSirSmeStartBssRsp * + pSmeStartBssRsp) +{ + eCsrRoamCompleteResult result; + + if (eSIR_SME_SUCCESS == pSmeStartBssRsp->statusCode) { + sms_log(pMac, LOGW, "SmeStartBssReq Successful"); + result = eCsrStartBssSuccess; + } else { + sms_log(pMac, LOGW, + "SmeStartBssReq failed with statusCode= 0x%08X", + pSmeStartBssRsp->statusCode); + /* Let csr_roam_complete decide what to do */ + result = eCsrStartBssFailure; + } + csr_roam_complete(pMac, result, pSmeStartBssRsp); +} + +/** + * csr_roaming_state_msg_processor() - process roaming messages + * @pMac: mac global context + * @pMsgBuf: message buffer + * + * We need to be careful on whether to cast pMsgBuf (pSmeRsp) to other type of + * strucutres. It depends on how the message is constructed. If the message is + * sent by lim_send_sme_rsp, 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. + * + * Return: status of operation + */ +void csr_roaming_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tSirSmeRsp *pSmeRsp; + tSmeIbssPeerInd *pIbssPeerInd; + tCsrRoamInfo roamInfo; + pSmeRsp = (tSirSmeRsp *) pMsgBuf; + sms_log(pMac, LOG2, FL("Message %d[0x%04X] received in substate %s"), + pSmeRsp->messageType, pSmeRsp->messageType, + mac_trace_getcsr_roam_sub_state( + 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 */ + csr_roam_join_rsp_processor(pMac, + (tSirSmeJoinRsp *) pSmeRsp); + break; + case eWNI_SME_REASSOC_RSP: + /* or the Reassociation response message... */ + if (CSR_IS_ROAM_SUBSTATE_REASSOC_REQ(pMac, pSmeRsp->sessionId)) + csr_roam_roaming_state_reassoc_rsp_processor(pMac, + (tpSirSmeJoinRsp) pSmeRsp); + break; + case eWNI_SME_STOP_BSS_RSP: + /* or the Stop Bss response message... */ + csr_roam_roaming_state_stop_bss_rsp_processor(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) + || CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, + pSmeRsp->sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("eWNI_SME_DISASSOC_RSP subState = %s"), + mac_trace_getcsr_roam_sub_state( + pMac->roam.curSubState[pSmeRsp->sessionId])); + csr_roam_roaming_state_disassoc_rsp_processor(pMac, + (tSirSmeDisassocRsp *) pSmeRsp); + } + break; + case eWNI_SME_DEAUTH_RSP: + /* or the Deauthentication response message... */ + if (CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ(pMac, pSmeRsp->sessionId)) + csr_roam_roaming_state_deauth_rsp_processor(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)) + csr_roam_roaming_state_start_bss_rsp_processor(pMac, + (tSirSmeStartBssRsp *) pSmeRsp); + break; + /* In case CSR issues STOP_BSS, we need to tell HDD about peer departed + * becasue PE is removing them + */ + case eWNI_SME_IBSS_PEER_DEPARTED_IND: + pIbssPeerInd = (tSmeIbssPeerInd *) pSmeRsp; + sms_log(pMac, LOGE, + FL("Peer departed ntf from LIM in joining state")); + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.staId = (uint8_t) pIbssPeerInd->staId; + roamInfo.ucastSig = (uint8_t) pIbssPeerInd->ucastSig; + roamInfo.bcastSig = (uint8_t) pIbssPeerInd->bcastSig; + cdf_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, + sizeof(struct cdf_mac_addr)); + csr_roam_call_callback(pMac, pSmeRsp->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 + sms_log(pMac, LOGE, + FL("pGetRssiReq->rssiCallback is NULL")); + } + break; + default: + sms_log(pMac, LOG1, + FL("Unexpected message type = %d[0x%X] received in substate %s"), + pSmeRsp->messageType, pSmeRsp->messageType, + mac_trace_getcsr_roam_sub_state( + pMac->roam.curSubState[pSmeRsp->sessionId])); + /* If we are connected, check the link status change */ + if (!csr_is_conn_state_disconnected(pMac, pSmeRsp->sessionId)) + csr_roam_check_for_link_status_change(pMac, pSmeRsp); + break; + } +} + +void csr_roam_joined_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tSirSmeRsp *pSirMsg = (tSirSmeRsp *) pMsgBuf; + switch (pSirMsg->messageType) { + case eWNI_SME_GET_STATISTICS_RSP: + sms_log(pMac, LOG2, FL("Stats rsp from PE")); + csr_roam_stats_rsp_processor(pMac, pSirMsg); + break; + case eWNI_SME_UPPER_LAYER_ASSOC_CNF: + { + tCsrRoamSession *pSession; + tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; + tCsrRoamInfo roamInfo; + tCsrRoamInfo *pRoamInfo = NULL; + uint32_t sessionId; + CDF_STATUS status; + sms_log(pMac, LOG1, + FL + ("ASSOCIATION confirmation can be given to upper layer ")); + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + pRoamInfo = &roamInfo; + pUpperLayerAssocCnf = + (tSirSmeAssocIndToUpperLayerCnf *) pMsgBuf; + status = + csr_roam_get_session_id_from_bssid(pMac, + (struct cdf_mac_addr *) + pUpperLayerAssocCnf-> + bssId, &sessionId); + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(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 = (uint8_t) pUpperLayerAssocCnf->aid; + pRoamInfo->rsnIELen = + (uint8_t) pUpperLayerAssocCnf->rsnIE.length; + pRoamInfo->prsnIE = + pUpperLayerAssocCnf->rsnIE.rsnIEdata; +#ifdef FEATURE_WLAN_WAPI + pRoamInfo->wapiIELen = + (uint8_t) pUpperLayerAssocCnf->wapiIE.length; + pRoamInfo->pwapiIE = + pUpperLayerAssocCnf->wapiIE.wapiIEdata; +#endif + pRoamInfo->addIELen = + (uint8_t) pUpperLayerAssocCnf->addIE.length; + pRoamInfo->paddIE = + pUpperLayerAssocCnf->addIE.addIEdata; + cdf_mem_copy(pRoamInfo->peerMac.bytes, + pUpperLayerAssocCnf->peerMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&pRoamInfo->bssid, + pUpperLayerAssocCnf->bssId, + sizeof(struct cdf_mac_addr)); + pRoamInfo->wmmEnabledSta = + pUpperLayerAssocCnf->wmmEnabledSta; + pRoamInfo->timingMeasCap = + pUpperLayerAssocCnf->timingMeasCap; + cdf_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 = + csr_roam_call_callback(pMac, sessionId, + pRoamInfo, 0, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); + } + if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) { + cdf_sleep(100); + pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; /* Sta */ + status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); /* Sta */ + } + + } + break; + default: + csr_roam_check_for_link_status_change(pMac, pSirMsg); + break; + } +} + +CDF_STATUS csr_roam_issue_set_context_req(tpAniSirGlobal pMac, + uint32_t sessionId, + eCsrEncryptionType EncryptType, + tSirBssDescription *pBssDescription, + tSirMacAddr *bssId, bool addKey, + bool fUnicast, + tAniKeyDirection aniKeyDirection, + uint8_t keyId, uint16_t keyLength, + uint8_t *pKey, uint8_t paeRole) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tAniEdType edType; + + if (eCSR_ENCRYPT_TYPE_UNKNOWN == EncryptType) { + EncryptType = eCSR_ENCRYPT_TYPE_NONE; + } + + edType = csr_translate_encrypt_type_to_ed_type(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 + * distrubuted). + */ + if (CSR_IS_ENC_TYPE_STATIC(EncryptType) || addKey) { + tCsrRoamSetKey setKey; + setKey.encType = EncryptType; + setKey.keyDirection = aniKeyDirection; + cdf_mem_copy(&setKey.peerMac, bssId, sizeof(struct cdf_mac_addr)); + /* 0 for supplicant */ + setKey.paeRole = paeRole; + /* Key index */ + setKey.keyId = keyId; + setKey.keyLength = keyLength; + if (keyLength) { + cdf_mem_copy(setKey.Key, pKey, keyLength); + } + status = csr_roam_issue_set_key_command(pMac, sessionId, + &setKey, 0); + } + return status; +} + +/** + * csr_update_key_cmd() - update key info in set key command + * @mac_ctx: mac global context + * @session: roam session + * @set_key: input set key command + * @set_key_cmd: set key command to update + * @enqueue_cmd: indicates if command need to be enqueued to sme + * + * This function will validate the key length, adjust if too long. Tt will + * update bool enqueue_cmd, to false if some error has occured key are local. + * + * Return: status of operation + */ +static CDF_STATUS +csr_update_key_cmd(tpAniSirGlobal mac_ctx, tCsrRoamSession *session, + tCsrRoamSetKey *set_key, tSmeCmd *set_key_cmd, + bool *enqueue_cmd) +{ + switch (set_key->encType) { + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + /* KeyLength maybe 0 for static WEP */ + if (set_key->keyLength) { + if (set_key->keyLength < CSR_WEP40_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid WEP40 keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + + set_key_cmd->u.setKeyCmd.keyLength = CSR_WEP40_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_WEP40_KEY_LEN); + } + *enqueue_cmd = true; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + /* KeyLength maybe 0 for static WEP */ + if (set_key->keyLength) { + if (set_key->keyLength < CSR_WEP104_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid WEP104 keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + + set_key_cmd->u.setKeyCmd.keyLength = CSR_WEP104_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_WEP104_KEY_LEN); + } + *enqueue_cmd = true; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + if (set_key->keyLength < CSR_TKIP_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid TKIP keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + set_key_cmd->u.setKeyCmd.keyLength = CSR_TKIP_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_TKIP_KEY_LEN); + *enqueue_cmd = true; + break; + case eCSR_ENCRYPT_TYPE_AES: + if (set_key->keyLength < CSR_AES_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid AES/CCMP keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + set_key_cmd->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_AES_KEY_LEN); + *enqueue_cmd = true; + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + if (set_key->keyLength < CSR_WAPI_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid WAPI keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + set_key_cmd->u.setKeyCmd.keyLength = CSR_WAPI_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_WAPI_KEY_LEN); + if (session->pCurRoamProfile) { + session->pCurRoamProfile->negotiatedUCEncryptionType = + eCSR_ENCRYPT_TYPE_WPI; + } else { + sms_log(mac_ctx, LOGW, + FL("pCurRoamProfile is NULL.")); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + *enqueue_cmd = true; + break; +#endif /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE + case eCSR_ENCRYPT_TYPE_KRK: + /* no need to enqueue KRK key request, since they are local */ + *enqueue_cmd = false; + if (set_key->keyLength < CSR_KRK_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid KRK keylength [= %d]"), + set_key->keyLength); + return CDF_STATUS_E_INVAL; + } + cdf_mem_copy(session->eseCckmInfo.krk, set_key->Key, + CSR_KRK_KEY_LEN); + session->eseCckmInfo.reassoc_req_num = 1; + session->eseCckmInfo.krk_plumbed = true; + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case eCSR_ENCRYPT_TYPE_BTK: + /* no need to enqueue KRK key request, since they are local */ + *enqueue_cmd = false; + if (set_key->keyLength < SIR_BTK_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("LFR3:Invalid BTK keylength [= %d]"), + set_key->keyLength); + return CDF_STATUS_E_INVAL; + } + cdf_mem_copy(session->eseCckmInfo.btk, set_key->Key, + SIR_BTK_KEY_LEN); + break; +#endif +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_11W + /* Check for 11w BIP */ + case eCSR_ENCRYPT_TYPE_AES_CMAC: + if (set_key->keyLength < CSR_AES_KEY_LEN) { + sms_log(mac_ctx, LOGW, + FL("Invalid AES/CCMP keylength [= %d]"), + set_key->keyLength); + *enqueue_cmd = false; + return CDF_STATUS_E_INVAL; + } + set_key_cmd->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; + cdf_mem_copy(set_key_cmd->u.setKeyCmd.Key, set_key->Key, + CSR_AES_KEY_LEN); + *enqueue_cmd = true; + break; +#endif /* WLAN_FEATURE_11W */ + default: + /* for open security also we want to enqueue command */ + *enqueue_cmd = true; + return CDF_STATUS_SUCCESS; + } /* end of switch */ + return CDF_STATUS_SUCCESS; +} + + +static CDF_STATUS csr_roam_issue_set_key_command(tpAniSirGlobal pMac, + uint32_t sessionId, + tCsrRoamSetKey *pSetKey, + uint32_t roamId) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + bool enqueue_cmd = true; + tSmeCmd *pCommand = NULL; +#if defined(FEATURE_WLAN_ESE) || defined (FEATURE_WLAN_WAPI) + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } +#endif /* FEATURE_WLAN_ESE */ + + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + sms_log(pMac, LOGE, FL(" fail to get command buffer")); + return CDF_STATUS_E_RESOURCES; + } + cdf_mem_zero(pCommand, sizeof(tSmeCmd)); + pCommand->command = eSmeCommandSetKey; + pCommand->sessionId = (uint8_t) sessionId; + /* + * following function will validate the key length, Adjust if too long. + * for static WEP the keys are not set thru' SetContextReq + * + * it will update bool enqueue_cmd, to false if some error has occured + * key are local. enqueue sme command only if enqueue_cmd is true + * status is indication of success or failure and will be returned to + * called of current function if command is not enqueued due to key req + * being local + */ + status = csr_update_key_cmd(pMac, pSession, pSetKey, + pCommand, &enqueue_cmd); + if (enqueue_cmd) { + pCommand->u.setKeyCmd.roamId = roamId; + pCommand->u.setKeyCmd.encType = pSetKey->encType; + pCommand->u.setKeyCmd.keyDirection = pSetKey->keyDirection; + cdf_mem_copy(&pCommand->u.setKeyCmd.peerMac, &pSetKey->peerMac, + sizeof(struct cdf_mac_addr)); + /* 0 for supplicant */ + pCommand->u.setKeyCmd.paeRole = pSetKey->paeRole; + pCommand->u.setKeyCmd.keyId = pSetKey->keyId; + cdf_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 = csr_queue_sme_command(pMac, pCommand, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("fail to send message status = %d"), status); + /* update to false so that command can be freed */ + enqueue_cmd = false; + } + } + + /* + * Free the command if enqueue_cmd == false: + * this means that command was not enqueued because either there has + * been a failure, or it is a "local" operation like the set ESE CCKM + * KRK key. + */ + if (false == enqueue_cmd) + csr_release_command_set_key(pMac, pCommand); + + return status; +} + +CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status; + uint8_t numKeys = (pCommand->u.setKeyCmd.keyLength) ? 1 : 0; + tAniEdType edType = + csr_translate_encrypt_type_to_ed_type(pCommand->u.setKeyCmd.encType); + bool fUnicast = + (pCommand->u.setKeyCmd.peerMac[0] == 0xFF) ? false : true; + uint32_t sessionId = pCommand->sessionId; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + WLAN_HOST_DIAG_EVENT_DEF(setKeyEvent, + host_event_wlan_security_payload_type); + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (eSIR_ED_NONE != edType) { + cdf_mem_set(&setKeyEvent, + sizeof(host_event_wlan_security_payload_type), 0); + if (*((uint8_t *) &pCommand->u.setKeyCmd.peerMac) & 0x01) { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_REQ; + setKeyEvent.encryptionModeMulticast = + (uint8_t) diag_enc_type_from_csr_type(pCommand->u. + setKeyCmd.encType); + setKeyEvent.encryptionModeUnicast = + (uint8_t) diag_enc_type_from_csr_type(pSession-> + connectedProfile. + EncryptionType); + } else { + setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_REQ; + setKeyEvent.encryptionModeUnicast = + (uint8_t) diag_enc_type_from_csr_type(pCommand->u. + setKeyCmd.encType); + setKeyEvent.encryptionModeMulticast = + (uint8_t) diag_enc_type_from_csr_type(pSession-> + connectedProfile. + mcEncryptionType); + } + cdf_mem_copy(setKeyEvent.bssid, + pSession->connectedProfile.bssid.bytes, + CDF_MAC_ADDR_SIZE); + if (CSR_IS_ENC_TYPE_STATIC(pCommand->u.setKeyCmd.encType)) { + uint32_t defKeyId; + /* It has to be static WEP here */ + if (IS_SIR_STATUS_SUCCESS + (wlan_cfg_get_int + (pMac, WNI_CFG_WEP_DEFAULT_KEYID, &defKeyId))) { + setKeyEvent.keyId = (uint8_t) defKeyId; + } + } else { + setKeyEvent.keyId = pCommand->u.setKeyCmd.keyId; + } + setKeyEvent.authMode = + (uint8_t) diag_auth_type_from_csr_type(pSession-> + connectedProfile. + AuthType); + WLAN_HOST_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY); + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + if (csr_is_set_key_allowed(pMac, sessionId)) { + status = csr_send_mb_set_context_req_msg(pMac, sessionId, + (uint8_t *) &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 { + sms_log(pMac, LOGW, FL(" cannot process not connected")); + /* Set this status so the error handling take care of the case. */ + status = CDF_STATUS_CSR_WRONG_STATE; + } + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL(" error status %d"), status); + csr_roam_call_callback(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 (*((uint8_t *) &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_HOST_DIAG_EVENT_REPORT(&setKeyEvent, + EVENT_WLAN_SECURITY); + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + } + return status; +} + +CDF_STATUS csr_roam_set_key(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamSetKey *pSetKey, uint32_t roamId) +{ + CDF_STATUS status; + + if (!csr_is_set_key_allowed(pMac, sessionId)) { + status = CDF_STATUS_CSR_WRONG_STATE; + } else { + status = + csr_roam_issue_set_key_command(pMac, sessionId, pSetKey, roamId); + } + return status; +} + +/* + Prepare a filter base on a profile for parsing the scan results. + Upon successful return, caller MUST call csr_free_scan_filter on + pScanFilter when it is done with the filter. + */ +CDF_STATUS +csr_roam_prepare_filter_from_profile(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, + tCsrScanResultFilter *scan_fltr) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t size = 0; + uint8_t idx = 0; + tCsrChannelInfo *fltr_ch_info = &scan_fltr->ChannelInfo; + tCsrChannelInfo *profile_ch_info = &profile->ChannelInfo; + struct roam_ext_params *roam_params; + uint8_t i; + + roam_params = &mac_ctx->roam.configParam.roam_params; + + if (profile->BSSIDs.numOfBSSIDs) { + size = sizeof(struct cdf_mac_addr) * profile->BSSIDs.numOfBSSIDs; + scan_fltr->BSSIDs.bssid = cdf_mem_malloc(size); + if (NULL == scan_fltr->BSSIDs.bssid) { + status = CDF_STATUS_E_NOMEM; + goto free_filter; + } + scan_fltr->BSSIDs.numOfBSSIDs = profile->BSSIDs.numOfBSSIDs; + cdf_mem_copy(scan_fltr->BSSIDs.bssid, + profile->BSSIDs.bssid, size); + } + + if (profile->SSIDs.numOfSSIDs) { + if (!CSR_IS_WDS_STA(profile)) { + scan_fltr->SSIDs.numOfSSIDs = profile->SSIDs.numOfSSIDs; + } else { + /* + * For WDS station we always use idx 1 for self SSID. + * Index 0 for peer's SSID that we want to join + */ + scan_fltr->SSIDs.numOfSSIDs = 1; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("No of Allowed List:%d"), + roam_params->num_ssid_allowed_list); + if (scan_fltr->scan_filter_for_roam + && roam_params->num_ssid_allowed_list) { + scan_fltr->SSIDs.numOfSSIDs = + roam_params->num_ssid_allowed_list; + size = sizeof(tCsrSSIDInfo) * + scan_fltr->SSIDs.numOfSSIDs; + scan_fltr->SSIDs.SSIDList = cdf_mem_malloc(size); + if (NULL == scan_fltr->SSIDs.SSIDList) + status = CDF_STATUS_E_FAILURE; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_filter; + for (i = 0; + i < roam_params->num_ssid_allowed_list; + i++) { + cdf_mem_copy((void *) + scan_fltr->SSIDs.SSIDList[i].SSID.ssId, + roam_params->ssid_allowed_list[i].ssId, + roam_params->ssid_allowed_list[i].length); + scan_fltr->SSIDs.SSIDList[i].SSID.length = + roam_params->ssid_allowed_list[i].length; + scan_fltr->SSIDs.SSIDList[i].handoffPermitted = + 1; + scan_fltr->SSIDs.SSIDList[i].ssidHidden = 0; + } + } else { + size = sizeof(tCsrSSIDInfo) * + profile->SSIDs.numOfSSIDs; + scan_fltr->SSIDs.SSIDList = cdf_mem_malloc(size); + if (NULL == scan_fltr->SSIDs.SSIDList) { + status = CDF_STATUS_E_NOMEM; + goto free_filter; + } + cdf_mem_copy(scan_fltr->SSIDs.SSIDList, + profile->SSIDs.SSIDList, size); + } + } + + if (!profile_ch_info->ChannelList + || (profile_ch_info->ChannelList[0] == 0)) { + fltr_ch_info->numOfChannels = 0; + fltr_ch_info->ChannelList = NULL; + } else if (profile_ch_info->numOfChannels) { + fltr_ch_info->numOfChannels = 0; + fltr_ch_info->ChannelList = + cdf_mem_malloc(sizeof(*(fltr_ch_info->ChannelList)) * + profile_ch_info->numOfChannels); + if (NULL == fltr_ch_info->ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto free_filter; + } + + for (idx = 0; idx < profile_ch_info->numOfChannels; idx++) { + if (csr_roam_is_channel_valid(mac_ctx, + profile_ch_info->ChannelList[idx])) { + fltr_ch_info-> + ChannelList[fltr_ch_info->numOfChannels] + = profile_ch_info->ChannelList[idx]; + fltr_ch_info->numOfChannels++; + } else { + sms_log(mac_ctx, LOG1, + FL("Channel (%d) is invalid"), + profile_ch_info->ChannelList[idx]); + } + } + } else { + sms_log(mac_ctx, LOGE, FL("Channel list empty")); + status = CDF_STATUS_E_FAILURE; + goto free_filter; + } + scan_fltr->uapsd_mask = profile->uapsd_mask; + scan_fltr->authType = profile->AuthType; + scan_fltr->EncryptionType = profile->EncryptionType; + scan_fltr->mcEncryptionType = profile->mcEncryptionType; + scan_fltr->BSSType = profile->BSSType; + scan_fltr->phyMode = profile->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 (csr_is_profile_wapi(profile)) { + if (scan_fltr->phyMode & eCSR_DOT11_MODE_11n) + scan_fltr->phyMode &= ~eCSR_DOT11_MODE_11n; + if (scan_fltr->phyMode & eCSR_DOT11_MODE_AUTO) + scan_fltr->phyMode &= ~eCSR_DOT11_MODE_AUTO; + if (!scan_fltr->phyMode) + scan_fltr->phyMode = eCSR_DOT11_MODE_11g; + } +#endif /* FEATURE_WLAN_WAPI */ + /*Save the WPS info */ + scan_fltr->bWPSAssociation = profile->bWPSAssociation; + scan_fltr->bOSENAssociation = profile->bOSENAssociation; + if (profile->countryCode[0]) { + /* + * This causes the matching function to use countryCode as one + * of the criteria. + */ + cdf_mem_copy(scan_fltr->countryCode, profile->countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (profile->MDID.mdiePresent) { + scan_fltr->MDID.mdiePresent = 1; + scan_fltr->MDID.mobilityDomain = profile->MDID.mobilityDomain; + } +#endif + +#ifdef WLAN_FEATURE_11W + /* Management Frame Protection */ + scan_fltr->MFPEnabled = profile->MFPEnabled; + scan_fltr->MFPRequired = profile->MFPRequired; + scan_fltr->MFPCapable = profile->MFPCapable; +#endif + scan_fltr->csrPersona = profile->csrPersona; + +free_filter: + if (!CDF_IS_STATUS_SUCCESS(status)) + csr_free_scan_filter(mac_ctx, scan_fltr); + + return status; +} + +bool csr_roam_issue_wm_status_change(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamWmStatusChangeTypes Type, + tSirSmeRsp *pSmeRsp) +{ + bool fCommandQueued = false; + tSmeCmd *pCommand; + do { + /* Validate the type is ok... */ + if ((eCsrDisassociated != Type) + && (eCsrDeauthenticated != Type)) + break; + pCommand = csr_get_command_buffer(pMac); + if (!pCommand) { + sms_log(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)) { + csr_roam_stop_wait_for_key_timer(pMac); + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + sessionId); + } + pCommand->command = eSmeCommandWmStatusChange; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.wmStatusChangeCmd.Type = Type; + if (eCsrDisassociated == Type) { + cdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u. + DisassocIndMsg, pSmeRsp, + sizeof(pCommand->u.wmStatusChangeCmd.u. + DisassocIndMsg)); + } else { + cdf_mem_copy(&pCommand->u.wmStatusChangeCmd.u. + DeauthIndMsg, pSmeRsp, + sizeof(pCommand->u.wmStatusChangeCmd.u. + DeauthIndMsg)); + } + if (CDF_IS_STATUS_SUCCESS + (csr_queue_sme_command(pMac, pCommand, true))) { + fCommandQueued = true; + } else { + sms_log(pMac, LOGE, FL(" fail to send message ")); + csr_release_command_wm_status_change(pMac, pCommand); + } + + /* AP has issued Dissac/Deauth, Set the operating mode value to configured value */ + csr_set_default_dot11_mode(pMac); + } while (0); + return fCommandQueued; +} + +static CDF_STATUS csr_send_snr_request(void *pGetRssiReq) +{ + void *wma_handle; + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma_handle) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "wma_handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + + if (CDF_STATUS_SUCCESS != + wma_send_snr_request(wma_handle, pGetRssiReq)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to Trigger wma stats request"); + return CDF_STATUS_E_FAILURE; + } + + /* dont send success, otherwise call back + * will released with out values */ + return CDF_STATUS_E_BUSY; +} + +static void csr_update_rssi(tpAniSirGlobal pMac, void *pMsg) +{ + int8_t rssi = 0; + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) pMsg; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + if (pGetRssiReq) { + if (NULL != pGetRssiReq->p_cds_context) { + cdf_status = csr_send_snr_request(pGetRssiReq); + } else { + sms_log(pMac, LOGE, + FL("pGetRssiReq->p_cds_context is NULL")); + return; + } + + if (NULL != pGetRssiReq->rssiCallback) { + if (cdf_status != CDF_STATUS_E_BUSY) + ((tCsrRssiCallback) (pGetRssiReq->rssiCallback)) + (rssi, pGetRssiReq->staId, + pGetRssiReq->pDevContext); + else + sms_log(pMac, LOG1, + FL + ("rssi request is posted. waiting for reply")); + } else { + sms_log(pMac, LOGE, + FL("pGetRssiReq->rssiCallback is NULL")); + return; + } + } else { + sms_log(pMac, LOGE, FL("pGetRssiReq is NULL")); + } + return; + +} + +static void csr_update_snr(tpAniSirGlobal pMac, void *pMsg) +{ + tAniGetSnrReq *pGetSnrReq = (tAniGetSnrReq *) pMsg; + + if (pGetSnrReq) { + if (CDF_STATUS_SUCCESS != wma_get_snr(pGetSnrReq)) { + sms_log(pMac, LOGE, FL("Error in wma_get_snr")); + return; + } + + } else { + sms_log(pMac, LOGE, FL("pGetSnrReq is NULL")); + } + return; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +void csr_tsm_stats_rsp_processor(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; + } + cdf_mem_free(reqBkp); + pTsmStatsRsp->tsmStatsReq = NULL; + } else { + sms_log(pMac, LOGE, FL("reqBkp is NULL")); + if (NULL != reqBkp) { + cdf_mem_free(reqBkp); + pTsmStatsRsp->tsmStatsReq = NULL; + } + } + } else { + sms_log(pMac, LOGE, FL("pTsmStatsRsp is NULL")); + } + return; +} + +void csr_send_ese_adjacent_ap_rep_ind(tpAniSirGlobal pMac, tCsrRoamSession *pSession) +{ + uint32_t roamTS2 = 0; + tCsrRoamInfo roamInfo; + tpPESession pSessionEntry = NULL; + uint8_t sessionId = CSR_SESSION_ID_INVALID; + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return; + } + + roamTS2 = cdf_mc_timer_get_system_time(); + roamInfo.tsmRoamDelay = roamTS2 - pSession->roamTS1; + sms_log(pMac, LOG1, "Bssid(" MAC_ADDRESS_STR ") Roaming Delay(%u ms)", + MAC_ADDR_ARRAY(pSession->connectedProfile.bssid.bytes), + roamInfo.tsmRoamDelay); + + pSessionEntry = pe_find_session_by_bssid(pMac, + pSession->connectedProfile.bssid.bytes, + &sessionId); + if (NULL == pSessionEntry) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return; + } + + pSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly + = roamInfo.tsmRoamDelay; + + csr_roam_call_callback(pMac, pSession->sessionId, &roamInfo, + 0, eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, 0); +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +CDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, tSirMacAddr *bssId) +{ + tpSirResetAPCapsChange pMsg; + uint16_t len; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* Create the message and send to lim */ + len = sizeof(tSirResetAPCapsChange); + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(pMsg, sizeof(tSirResetAPCapsChange), 0); + pMsg->messageType = eWNI_SME_RESET_AP_CAPS_CHANGED; + pMsg->length = len; + cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + sms_log(pMac, LOG1, + FL("CSR reset caps change for Bssid= " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMsg->bssId)); + status = cds_send_mb_message_to_mac(pMsg); + } else { + sms_log(pMac, LOGE, FL("Memory allocation failed\n")); + } + return status; +} + +static void +csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSirSmeAssocInd *pAssocInd; + tCsrRoamInfo roam_info; + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + + sms_log(mac_ctx, LOG1, FL("Receive WNI_SME_ASSOC_IND from SME")); + pAssocInd = (tSirSmeAssocInd *) msg_ptr; + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *) pAssocInd->bssId, &sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOG1, + FL("Couldn't find session_id for given BSSID")); + return; + } + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); + return; + } + roam_info_ptr = &roam_info; + /* Required for indicating the frames to upper layer */ + roam_info_ptr->assocReqLength = pAssocInd->assocReqLength; + roam_info_ptr->assocReqPtr = pAssocInd->assocReqPtr; + roam_info_ptr->beaconPtr = pAssocInd->beaconPtr; + roam_info_ptr->beaconLength = pAssocInd->beaconLength; + roam_info_ptr->statusCode = eSIR_SME_SUCCESS; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + roam_info_ptr->staId = (uint8_t) pAssocInd->staId; + roam_info_ptr->rsnIELen = (uint8_t) pAssocInd->rsnIE.length; + roam_info_ptr->prsnIE = pAssocInd->rsnIE.rsnIEdata; +#ifdef FEATURE_WLAN_WAPI + roam_info_ptr->wapiIELen = (uint8_t) pAssocInd->wapiIE.length; + roam_info_ptr->pwapiIE = pAssocInd->wapiIE.wapiIEdata; +#endif + roam_info_ptr->addIELen = (uint8_t) pAssocInd->addIE.length; + roam_info_ptr->paddIE = pAssocInd->addIE.addIEdata; + cdf_mem_copy(roam_info_ptr->peerMac.bytes, + pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(roam_info_ptr->bssid.bytes, + pAssocInd->bssId, + sizeof(struct cdf_mac_addr)); + roam_info_ptr->wmmEnabledSta = pAssocInd->wmmEnabledSta; + roam_info_ptr->timingMeasCap = pAssocInd->timingMeasCap; + cdf_mem_copy(&roam_info_ptr->chan_info, + &pAssocInd->chan_info, + sizeof(tSirSmeChanInfo)); + if (CSR_IS_WDS_AP(roam_info_ptr->u.pConnectedProfile)) + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 0, eCSR_ROAM_WDS_IND, + eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); + if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile)) { + if (session->pCurRoamProfile && + CSR_IS_ENC_TYPE_STATIC( + session->pCurRoamProfile->negotiatedUCEncryptionType)) { + /* NO keys... these key parameters don't matter. */ + csr_roam_issue_set_context_req(mac_ctx, sessionId, + session->pCurRoamProfile->negotiatedUCEncryptionType, + session->pConnectBssDesc, + &(roam_info_ptr->peerMac.bytes), + false, true, eSIR_TX_RX, 0, 0, NULL, 0); + roam_info_ptr->fAuthRequired = false; + } else { + roam_info_ptr->fAuthRequired = true; + } + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 0, eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND); + if (!CDF_IS_STATUS_SUCCESS(status)) + /* Refused due to Mac filtering */ + roam_info_ptr->statusCode = eSIR_SME_ASSOC_REFUSED; + } + + /* Send Association completion message to PE */ + status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status); + /* + * send a message to CSR itself just to avoid the EAPOL frames going + * OTA before association response + */ + if (CSR_IS_WDS_AP(roam_info_ptr->u.pConnectedProfile)) { + status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac_ctx, + pAssocInd, status, sessionId); + } else if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile) + && (roam_info_ptr->statusCode != eSIR_SME_ASSOC_REFUSED)) { + roam_info_ptr->fReassocReq = pAssocInd->reassocReq; + status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac_ctx, + pAssocInd, status, sessionId); + } +} + +static void +csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSirSmeDisassocInd *pDisassocInd; + tSmeCmd cmd; + tCsrRoamInfo roam_info; + + /* + * 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 *) msg_ptr; + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *) pDisassocInd->bssId, &sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("Session Id not found for BSSID " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pDisassocInd->bssId)); + return; + } + + sms_log(mac_ctx, LOGE, + FL("DISASSOCIATION Indication from MAC for session %d "), + sessionId); + sms_log(mac_ctx, 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 (csr_roam_is11r_assoc(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif +#ifdef FEATURE_WLAN_ESE + if (csr_roam_is_ese_assoc(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); + return; + } + if (csr_is_conn_state_infra(mac_ctx, sessionId)) + session->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) sessionId, + SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csr_roam_link_down(mac_ctx, sessionId); + csr_roam_issue_wm_status_change(mac_ctx, sessionId, + eCsrDisassociated, msg_ptr); + if (CSR_IS_INFRA_AP(&session->connectedProfile)) { + roam_info_ptr = &roam_info; + roam_info_ptr->statusCode = pDisassocInd->statusCode; + roam_info_ptr->reasonCode = pDisassocInd->reasonCode; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + roam_info_ptr->staId = (uint8_t) pDisassocInd->staId; + cdf_mem_copy(roam_info_ptr->peerMac.bytes, + pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&roam_info_ptr->bssid.bytes, + pDisassocInd->bssId, + sizeof(struct cdf_mac_addr)); + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 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 + */ + cmd.command = eSmeCommandRoam; + cmd.sessionId = (uint8_t) sessionId; + cmd.u.roamCmd.roamReason = eCsrForcedDeauthSta; + cdf_mem_copy(cmd.u.roamCmd.peerMac, + pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + csr_roam_remove_duplicate_command(mac_ctx, sessionId, &cmd, + eCsrForcedDeauthSta); + } +} + +static void +csr_roam_chk_lnk_deauth_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSirSmeDeauthInd *pDeauthInd; + tCsrRoamInfo roam_info; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + sms_log(mac_ctx, LOG1, FL("DEAUTHENTICATION Indication from MAC")); + pDeauthInd = (tpSirSmeDeauthInd) msg_ptr; + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *) pDeauthInd-> + bssId, &sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) + return; + /* 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 (csr_roam_is11r_assoc(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif +#ifdef FEATURE_WLAN_ESE + if (csr_roam_is_ese_assoc(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionId) && + (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + mac_ctx, sessionId); +#endif + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); + return; + } + + if (csr_is_conn_state_infra(mac_ctx, sessionId)) + session->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + sme_qos_csr_event_ind(mac_ctx, (uint8_t) sessionId, + SME_QOS_CSR_DISCONNECT_IND, NULL); +#endif + csr_roam_link_down(mac_ctx, sessionId); + csr_roam_issue_wm_status_change(mac_ctx, sessionId, + eCsrDeauthenticated, + msg_ptr); + if (CSR_IS_INFRA_AP(&session->connectedProfile)) { + roam_info_ptr = &roam_info; + roam_info_ptr->statusCode = pDeauthInd->statusCode; + roam_info_ptr->reasonCode = pDeauthInd->reasonCode; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + roam_info_ptr->staId = (uint8_t) pDeauthInd->staId; + cdf_mem_copy(roam_info_ptr->peerMac.bytes, + pDeauthInd->peerMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&roam_info_ptr->bssid.bytes, + pDeauthInd->bssId, + sizeof(struct cdf_mac_addr)); + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 0, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_DEAUTH_IND); + } +} + +static void +csr_roam_chk_lnk_swt_ch_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tpSirSmeSwitchChannelInd pSwitchChnInd; + + /* in case of STA, the SWITCH_CHANNEL originates from its AP */ + sms_log(mac_ctx, LOGW, FL("eWNI_SME_SWITCH_CHL_IND from SME")); + pSwitchChnInd = (tpSirSmeSwitchChannelInd) msg_ptr; + /* Update with the new channel id. The channel id is hidden in the + * statusCode. + */ + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *) pSwitchChnInd->bssId, &sessionId); + if (CDF_IS_STATUS_SUCCESS(status)) { + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, + FL("session %d not found"), sessionId); + return; + } + session->connectedProfile.operationChannel = + (uint8_t) pSwitchChnInd->newChannelId; + if (session->pConnectBssDesc) { + session->pConnectBssDesc->channelId = + (uint8_t) pSwitchChnInd->newChannelId; + } + } +} + +static void +csr_roam_chk_lnk_deauth_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSirSmeDeauthRsp *pDeauthRsp = (tSirSmeDeauthRsp *) msg_ptr; + tCsrRoamInfo roam_info; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + sms_log(mac_ctx, LOGW, FL("eWNI_SME_DEAUTH_RSP from SME")); + sessionId = pDeauthRsp->sessionId; + if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) + return; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (CSR_IS_INFRA_AP(&session->connectedProfile)) { + roam_info_ptr = &roam_info; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + cdf_mem_copy(roam_info_ptr->peerMac.bytes, + pDeauthRsp->peerMacAddr, + sizeof(tSirMacAddr)); + roam_info_ptr->reasonCode = eCSR_ROAM_RESULT_FORCED; + roam_info_ptr->statusCode = pDeauthRsp->statusCode; + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 0, + eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_FORCED); + } +} + +static void +csr_roam_chk_lnk_disassoc_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tCsrRoamInfo roam_info; + /* + * session id is invalid here so cant use it to access the array + * curSubstate as index + */ + tSirSmeDisassocRsp *pDisassocRsp = (tSirSmeDisassocRsp *) msg_ptr; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + sms_log(mac_ctx, LOGW, FL("eWNI_SME_DISASSOC_RSP from SME ")); + sessionId = pDisassocRsp->sessionId; + if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) + return; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (CSR_IS_INFRA_AP(&session->connectedProfile)) { + roam_info_ptr = &roam_info; + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + cdf_mem_copy(roam_info_ptr->peerMac.bytes, + pDisassocRsp->peerMacAddr, + sizeof(tSirMacAddr)); + roam_info_ptr->reasonCode = eCSR_ROAM_RESULT_FORCED; + roam_info_ptr->statusCode = pDisassocRsp->statusCode; + status = csr_roam_call_callback(mac_ctx, sessionId, + roam_info_ptr, 0, + eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_FORCED); + } +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void +csr_roam_diag_mic_fail(tpAniSirGlobal mac_ctx, uint32_t sessionId) +{ + WLAN_HOST_DIAG_EVENT_DEF(secEvent, + host_event_wlan_security_payload_type); + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); + return; + } + cdf_mem_set(&secEvent, sizeof(host_event_wlan_security_payload_type), + 0); + secEvent.eventId = WLAN_SECURITY_EVENT_MIC_ERROR; + secEvent.encryptionModeMulticast = + (uint8_t) diag_enc_type_from_csr_type( + session->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = + (uint8_t) diag_enc_type_from_csr_type( + session->connectedProfile.EncryptionType); + secEvent.authMode = + (uint8_t) diag_auth_type_from_csr_type( + session->connectedProfile.AuthType); + cdf_mem_copy(secEvent.bssid, session->connectedProfile.bssid.bytes, + CDF_MAC_ADDR_SIZE); + WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +static void +csr_roam_chk_lnk_mic_fail_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tCsrRoamInfo roam_info; + tpSirSmeMicFailureInd pMicInd = (tpSirSmeMicFailureInd) msg_ptr; + eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *) pMicInd->bssId, &sessionId); + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.u.pMICFailureInfo = &pMicInd->info; + roam_info_ptr = &roam_info; + if (pMicInd->info.multicast) + result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP; + else + result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST; + csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, + eCSR_ROAM_MIC_ERROR_IND, result); + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_roam_diag_mic_fail(mac_ctx, sessionId); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ +} + +static void +csr_roam_chk_lnk_pbs_probe_req_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo roam_info; + tpSirSmeProbeReqInd pProbeReqInd = (tpSirSmeProbeReqInd) msg_ptr; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + sms_log(mac_ctx, LOG1, FL("WPS PBC Probe request Indication from SME")); + + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *)pProbeReqInd->bssId, &sessionId); + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); + roam_info.u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq; + csr_roam_call_callback(mac_ctx, sessionId, &roam_info, + 0, eCSR_ROAM_WPS_PBC_PROBE_REQ_IND, + eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND); + } +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void +csr_roam_diag_joined_new_bss(tpAniSirGlobal mac_ctx, + tSirSmeNewBssInfo *pNewBss) +{ + host_log_ibss_pkt_type *pIbssLog; + uint32_t bi; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_log_ibss_pkt_type, + LOG_WLAN_IBSS_C); + if (!pIbssLog) + return; + pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING; + if (pNewBss) { + cdf_mem_copy(pIbssLog->bssid, pNewBss->bssId, 6); + if (pNewBss->ssId.length) + cdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId, + pNewBss->ssId.length); + pIbssLog->operatingChannel = pNewBss->channelNumber; + } + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(mac_ctx, + WNI_CFG_BEACON_INTERVAL, + &bi))) + /* U8 is not enough for beacon interval */ + pIbssLog->beaconInterval = (uint8_t) bi; + WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +static void +csr_roam_chk_lnk_wm_status_change_ntf(tpAniSirGlobal mac_ctx, + tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSirSmeWmStatusChangeNtf *pStatusChangeMsg; + tCsrRoamInfo roam_info; + tSirSmeApNewCaps *pApNewCaps; + eCsrRoamResult result = eCSR_ROAM_RESULT_NONE; + tSirMacAddr Broadcastaddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + tSirSmeNewBssInfo *pNewBss; + eRoamCmdStatus roamStatus = eCSR_ROAM_FAILED; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + pStatusChangeMsg = (tSirSmeWmStatusChangeNtf *) msg_ptr; + switch (pStatusChangeMsg->statusChangeCode) { + case eSIR_SME_IBSS_ACTIVE: + sessionId = csr_find_ibss_session(mac_ctx); + if (CSR_SESSION_ID_INVALID == sessionId) + break; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), + sessionId); + return; + } + session->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED; + if (session->pConnectBssDesc) { + cdf_mem_copy(&roam_info.bssid, + session->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + roam_info.u.pConnectedProfile = + &session->connectedProfile; + roam_info_ptr = &roam_info; + } else { + sms_log(mac_ctx, LOGE, + FL("CSR: connected BSS is empty")); + } + result = eCSR_ROAM_RESULT_IBSS_CONNECT; + roamStatus = eCSR_ROAM_CONNECT_STATUS_UPDATE; + break; + + case eSIR_SME_IBSS_INACTIVE: + sessionId = csr_find_ibss_session(mac_ctx); + if (CSR_SESSION_ID_INVALID != sessionId) { + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, + FL("session %d not found"), sessionId); + return; + } + session->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. */ + sms_log(mac_ctx, LOGW, + FL("CSR: eSIR_SME_JOINED_NEW_BSS received from PE")); + sessionId = csr_find_ibss_session(mac_ctx); + if (CSR_SESSION_ID_INVALID == sessionId) + break; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), + sessionId); + return; + } + /* update the connection state information */ + pNewBss = &pStatusChangeMsg->statusChangeInfo.newBssInfo; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_roam_diag_joined_new_bss(mac_ctx, pNewBss); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + csr_roam_update_connected_profile_from_new_bss(mac_ctx, + sessionId, + pNewBss); + + if ((eCSR_ENCRYPT_TYPE_NONE == + session->connectedProfile.EncryptionType)) { + csr_roam_issue_set_context_req(mac_ctx, + sessionId, + session->connectedProfile.EncryptionType, + session->pConnectBssDesc, + &Broadcastaddr, false, false, + eSIR_TX_RX, 0, 0, NULL, 0); + } + result = eCSR_ROAM_RESULT_IBSS_COALESCED; + roamStatus = eCSR_ROAM_IBSS_IND; + cdf_mem_copy(&roam_info.bssid, &pNewBss->bssId, + sizeof(struct cdf_mac_addr)); + roam_info_ptr = &roam_info; + /* This BSSID is the real BSSID, save it */ + if (session->pConnectBssDesc) + cdf_mem_copy(session->pConnectBssDesc->bssId, + &pNewBss->bssId, sizeof(struct cdf_mac_addr)); + break; + + /* + * detection by LIM that the capabilities of the associated + * AP have changed. + */ + case eSIR_SME_AP_CAPS_CHANGED: + pApNewCaps = &pStatusChangeMsg->statusChangeInfo.apNewCaps; + sms_log(mac_ctx, LOGW, + FL("CSR handling eSIR_SME_AP_CAPS_CHANGED")); + status = csr_roam_get_session_id_from_bssid(mac_ctx, + (struct cdf_mac_addr *)pApNewCaps->bssId, &sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + if (eCSR_ROAMING_STATE_JOINED == + mac_ctx->roam.curState[sessionId] + && ((eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC + == mac_ctx->roam.curSubState[sessionId]) + || (eCSR_ROAM_SUBSTATE_NONE == + mac_ctx->roam.curSubState[sessionId]) + || (eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC + == mac_ctx->roam.curSubState[sessionId]) + || (eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC == + mac_ctx->roam.curSubState[sessionId]))) { + sms_log(mac_ctx, LOGW, + FL("Calling csr_roam_disconnect_internal")); + csr_roam_disconnect_internal(mac_ctx, sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + } else { + sms_log(mac_ctx, LOGW, + FL("Skipping the new scan as CSR is in state %s and sub-state %s"), + mac_trace_getcsr_roam_state( + mac_ctx->roam.curState[sessionId]), + mac_trace_getcsr_roam_sub_state( + mac_ctx->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 + */ + csr_send_reset_ap_caps_changed(mac_ctx, + &pApNewCaps->bssId); + } + break; + + default: + roamStatus = eCSR_ROAM_FAILED; + result = eCSR_ROAM_RESULT_NONE; + break; + } /* end switch on statusChangeCode */ + if (eCSR_ROAM_RESULT_NONE != result) { + csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, + roamStatus, result); + } +} + +static void +csr_roam_chk_lnk_ibss_new_peer_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSmeIbssPeerInd *pIbssPeerInd = (tSmeIbssPeerInd *) msg_ptr; + tCsrRoamInfo roam_info; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + host_log_ibss_pkt_type *pIbssLog; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_log_ibss_pkt_type, + LOG_WLAN_IBSS_C); + if (pIbssLog) { + pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_JOIN; + cdf_mem_copy(pIbssLog->peerMacAddr, &pIbssPeerInd->peerAddr, 6); + WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + sessionId = csr_find_ibss_session(mac_ctx); + if (CSR_SESSION_ID_INVALID == sessionId) + return; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, 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 (!session->pConnectBssDesc) { + sms_log(mac_ctx, LOGW, FL("CSR: connected BSS is empty")); + goto callback_and_free; + } + cdf_mem_copy(&roam_info.peerMac, pIbssPeerInd->peerAddr, + sizeof(struct cdf_mac_addr)); + cdf_mem_copy(&roam_info.bssid, session->pConnectBssDesc->bssId, + sizeof(struct cdf_mac_addr)); + if (pIbssPeerInd->mesgLen > sizeof(tSmeIbssPeerInd)) { + roam_info.pbFrames = cdf_mem_malloc((pIbssPeerInd->mesgLen - + sizeof(tSmeIbssPeerInd))); + if (NULL == roam_info.pbFrames) { + status = CDF_STATUS_E_NOMEM; + } else { + status = CDF_STATUS_SUCCESS; + roam_info.nBeaconLength = pIbssPeerInd->mesgLen - + sizeof(tSmeIbssPeerInd); + cdf_mem_copy(roam_info.pbFrames, + ((uint8_t *) pIbssPeerInd) + + sizeof(tSmeIbssPeerInd), + roam_info.nBeaconLength); + } + roam_info.staId = (uint8_t) pIbssPeerInd->staId; + roam_info.ucastSig = (uint8_t) pIbssPeerInd->ucastSig; + roam_info.bcastSig = (uint8_t) pIbssPeerInd->bcastSig; + roam_info.pBssDesc = cdf_mem_malloc( + session->pConnectBssDesc->length); + if (NULL == roam_info.pBssDesc) { + status = CDF_STATUS_E_NOMEM; + if (roam_info.pbFrames) + cdf_mem_free(roam_info.pbFrames); + if (roam_info.pBssDesc) + cdf_mem_free(roam_info.pBssDesc); + } else { + status = CDF_STATUS_SUCCESS; + cdf_mem_copy(roam_info.pBssDesc, + session->pConnectBssDesc, + session->pConnectBssDesc->length); + roam_info_ptr = &roam_info; + } + } else { + roam_info_ptr = &roam_info; + } + if ((eCSR_ENCRYPT_TYPE_NONE == + session->connectedProfile.EncryptionType)) { + /* NO keys. these key parameters don't matter */ + csr_roam_issue_set_context_req(mac_ctx, sessionId, + session->connectedProfile.EncryptionType, + session->pConnectBssDesc, &(pIbssPeerInd->peerAddr), + false, true, eSIR_TX_RX, 0, 0, NULL, 0); + } + +callback_and_free: + /* send up the sec type for the new peer */ + if (roam_info_ptr) + roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; + csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, + eCSR_ROAM_CONNECT_STATUS_UPDATE, + eCSR_ROAM_RESULT_IBSS_NEW_PEER); + if (roam_info_ptr) { + if (roam_info.pbFrames) + cdf_mem_free(roam_info.pbFrames); + if (roam_info.pBssDesc) + cdf_mem_free(roam_info.pBssDesc); + } +} + +static void +csr_roam_chk_lnk_ibss_peer_departed_ind(tpAniSirGlobal mac_ctx, + tSirSmeRsp *msg_ptr) +{ + uint32_t sessionId = CSR_SESSION_ID_INVALID; + tCsrRoamInfo roam_info; + tSmeIbssPeerInd *pIbssPeerInd; + + if (NULL == msg_ptr) { + sms_log(mac_ctx, LOGE, FL("IBSS peer ind. message is NULL")); + return; + } + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + pIbssPeerInd = (tSmeIbssPeerInd *) msg_ptr; + sessionId = csr_find_ibss_session(mac_ctx); + if (CSR_SESSION_ID_INVALID != sessionId) { +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + host_log_ibss_pkt_type *pIbssLog; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_log_ibss_pkt_type, + LOG_WLAN_IBSS_C); + if (pIbssLog) { + pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_LEAVE; + if (pIbssPeerInd) { + cdf_mem_copy(pIbssLog->peerMacAddr, + &pIbssPeerInd->peerAddr, 6); + } + WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + sms_log(mac_ctx, LOGW, + FL("CSR: Peer departed notification from LIM")); + roam_info.staId = (uint8_t) pIbssPeerInd->staId; + roam_info.ucastSig = (uint8_t) pIbssPeerInd->ucastSig; + roam_info.bcastSig = (uint8_t) pIbssPeerInd->bcastSig; + cdf_mem_copy(&roam_info.peerMac, pIbssPeerInd->peerAddr, + sizeof(struct cdf_mac_addr)); + csr_roam_call_callback(mac_ctx, sessionId, &roam_info, 0, + eCSR_ROAM_CONNECT_STATUS_UPDATE, + eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); + } +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void +csr_roam_diag_set_ctx_rsp(tpAniSirGlobal mac_ctx, + tCsrRoamSession *session, + tSirSmeSetContextRsp *pRsp) +{ + WLAN_HOST_DIAG_EVENT_DEF(setKeyEvent, + host_event_wlan_security_payload_type); + if (eCSR_ENCRYPT_TYPE_NONE == + session->connectedProfile.EncryptionType) + return; + cdf_mem_set(&setKeyEvent, + sizeof(host_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 = + (uint8_t) diag_enc_type_from_csr_type( + session->connectedProfile.mcEncryptionType); + setKeyEvent.encryptionModeUnicast = + (uint8_t) diag_enc_type_from_csr_type( + session->connectedProfile.EncryptionType); + cdf_mem_copy(setKeyEvent.bssid, session->connectedProfile.bssid.bytes, + CDF_MAC_ADDR_SIZE); + setKeyEvent.authMode = + (uint8_t) diag_auth_type_from_csr_type( + session->connectedProfile.AuthType); + if (eSIR_SME_SUCCESS != pRsp->statusCode) + setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE; + WLAN_HOST_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +static void +csr_roam_chk_lnk_set_ctx_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + tCsrRoamSession *session; + uint32_t sessionId = CSR_SESSION_ID_INVALID; + CDF_STATUS status; + tCsrRoamInfo *roam_info_ptr = NULL; + tSmeCmd *cmd; + tCsrRoamInfo roam_info; + eCsrRoamResult result = eCSR_ROAM_RESULT_NONE; + tSirSmeSetContextRsp *pRsp = (tSirSmeSetContextRsp *) msg_ptr; + tListElem *entry; + tSirMacAddr Broadcastaddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac_ctx, LOGE, FL("CSR: NO commands are ACTIVE ...")); + goto process_pending_n_exit; + } + + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (eSmeCommandSetKey != cmd->command) { + sms_log(mac_ctx, LOGE, FL("CSR: setkey cmd is not ACTIVE ...")); + goto process_pending_n_exit; + } + sessionId = cmd->sessionId; + session = CSR_GET_SESSION(mac_ctx, sessionId); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); + return; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_roam_diag_set_ctx_rsp(mac_ctx, session, pRsp); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + if (CSR_IS_WAIT_FOR_KEY(mac_ctx, sessionId)) { + csr_roam_stop_wait_for_key_timer(mac_ctx); + /* We are done with authentication, whethere succeed or not */ + csr_roam_substate_change(mac_ctx, 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 (csr_is_conn_state_connected_infra(mac_ctx, sessionId)) + csr_roam_link_up(mac_ctx, + session->connectedProfile.bssid); + } + if (eSIR_SME_SUCCESS == pRsp->statusCode) { + cdf_mem_copy(&roam_info.peerMac, &pRsp->peerMacAddr, + sizeof(struct cdf_mac_addr)); + /* 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 (cdf_mem_compare(&Broadcastaddr, pRsp->peerMacAddr, + sizeof(tSirMacAddr))) { + tpSirSetActiveModeSetBncFilterReq pMsg; + pMsg = cdf_mem_malloc( + sizeof(tSirSetActiveModeSetBncFilterReq)); + pMsg->messageType = eWNI_SME_SET_BCN_FILTER_REQ; + pMsg->length = sizeof(uint8_t); + pMsg->seesionId = sessionId; + status = cds_send_mb_message_to_mac(pMsg); + result = eCSR_ROAM_RESULT_AUTHENTICATED; + } else { + result = eCSR_ROAM_RESULT_NONE; + } + roam_info_ptr = &roam_info; + } else { + result = eCSR_ROAM_RESULT_FAILURE; + sms_log(mac_ctx, LOGE, + FL("CSR: setkey command failed(%d) PeerMac " + MAC_ADDRESS_STR), + pRsp->statusCode, MAC_ADDR_ARRAY(pRsp->peerMacAddr)); + } + csr_roam_call_callback(mac_ctx, sessionId, &roam_info, + cmd->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_qos_csr_event_ind(mac_ctx, (uint8_t) sessionId, + SME_QOS_CSR_SET_KEY_SUCCESS_IND, NULL); +#ifdef FEATURE_WLAN_ESE + /* Send Adjacent AP repot to new AP. */ + if (result == eCSR_ROAM_RESULT_AUTHENTICATED + && session->isPrevApInfoValid + && session->connectedProfile.isESEAssoc) { +#ifdef FEATURE_WLAN_ESE_UPLOAD + csr_send_ese_adjacent_ap_rep_ind(mac_ctx, session); +#else + csr_ese_send_adjacent_ap_rep_msg(mac_ctx, session); +#endif + session->isPrevApInfoValid = false; + } +#endif + if (csr_ll_remove_entry(&mac_ctx->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK)) + csr_release_command_set_key(mac_ctx, cmd); + +process_pending_n_exit: + sme_process_pending_queue(mac_ctx); +} + + +static void +csr_roam_chk_lnk_max_assoc_exceeded(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) +{ + uint32_t sessionId = CSR_SESSION_ID_INVALID; + tSmeMaxAssocInd *pSmeMaxAssocInd; + tCsrRoamInfo roam_info; + + cdf_mem_set(&roam_info, sizeof(roam_info), 0); + pSmeMaxAssocInd = (tSmeMaxAssocInd *) msg_ptr; + sms_log(mac_ctx, LOG1, + FL("max assoc have been reached, new peer cannot be accepted")); + sessionId = pSmeMaxAssocInd->sessionId; + roam_info.sessionId = sessionId; + cdf_mem_copy(&roam_info.peerMac, pSmeMaxAssocInd->peerMac, + sizeof(struct cdf_mac_addr)); + csr_roam_call_callback(mac_ctx, sessionId, &roam_info, 0, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED); +} + +void csr_roam_check_for_link_status_change(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) +{ + if (NULL == pSirMsg) { + sms_log(pMac, LOGE, FL("pSirMsg is NULL")); + return; + } + switch (pSirMsg->messageType) { + case eWNI_SME_ASSOC_IND: + csr_roam_chk_lnk_assoc_ind(pMac, pSirMsg); + break; + case eWNI_SME_DISASSOC_IND: + csr_roam_chk_lnk_disassoc_ind(pMac, pSirMsg); + break; + case eWNI_SME_DEAUTH_IND: + csr_roam_chk_lnk_deauth_ind(pMac, pSirMsg); + break; + case eWNI_SME_SWITCH_CHL_IND: + csr_roam_chk_lnk_swt_ch_ind(pMac, pSirMsg); + break; + case eWNI_SME_DEAUTH_RSP: + csr_roam_chk_lnk_deauth_rsp(pMac, pSirMsg); + break; + case eWNI_SME_DISASSOC_RSP: + csr_roam_chk_lnk_disassoc_rsp(pMac, pSirMsg); + break; + case eWNI_SME_MIC_FAILURE_IND: + csr_roam_chk_lnk_mic_fail_ind(pMac, pSirMsg); + break; + case eWNI_SME_WPS_PBC_PROBE_REQ_IND: + csr_roam_chk_lnk_pbs_probe_req_ind(pMac, pSirMsg); + break; + case eWNI_SME_WM_STATUS_CHANGE_NTF: + csr_roam_chk_lnk_wm_status_change_ntf(pMac, pSirMsg); + break; + case eWNI_SME_IBSS_NEW_PEER_IND: + csr_roam_chk_lnk_ibss_new_peer_ind(pMac, pSirMsg); + break; + case eWNI_SME_IBSS_PEER_DEPARTED_IND: + csr_roam_chk_lnk_ibss_peer_departed_ind(pMac, pSirMsg); + break; + case eWNI_SME_SETCONTEXT_RSP: + csr_roam_chk_lnk_set_ctx_rsp(pMac, pSirMsg); + break; + case eWNI_SME_GET_STATISTICS_RSP: + sms_log(pMac, LOG2, FL("Stats rsp from PE")); + csr_roam_stats_rsp_processor(pMac, pSirMsg); + break; +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case eWNI_SME_GET_TSM_STATS_RSP: + sms_log(pMac, LOG2, FL("TSM Stats rsp from PE")); + csr_tsm_stats_rsp_processor(pMac, pSirMsg); + break; +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + case eWNI_SME_GET_RSSI_REQ: + sms_log(pMac, LOG2, FL("GetRssiReq from self")); + csr_update_rssi(pMac, pSirMsg); + break; + case eWNI_SME_GET_SNR_REQ: + sms_log(pMac, LOG2, FL("GetSnrReq from self")); + csr_update_snr(pMac, pSirMsg); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_PRE_AUTH_RSP: + csr_roam_ft_pre_auth_rsp_processor(pMac, (tpSirFTPreAuthRsp) pSirMsg); + break; +#endif + case eWNI_SME_MAX_ASSOC_EXCEEDED: + csr_roam_chk_lnk_max_assoc_exceeded(pMac, pSirMsg); + break; + case eWNI_SME_CANDIDATE_FOUND_IND: + sms_log(pMac, LOG2, FL("Candidate found indication from PE")); + csr_neighbor_roam_candidate_found_ind_hdlr(pMac, pSirMsg); + break; + case eWNI_SME_HANDOFF_REQ: + sms_log(pMac, LOG2, FL("Handoff Req from self")); + csr_neighbor_roam_handoff_req_hdlr(pMac, pSirMsg); + break; + default: + break; + } /* end switch on message type */ +} + +void csr_call_roaming_completion_callback(tpAniSirGlobal pMac, + tCsrRoamSession *pSession, + tCsrRoamInfo *pRoamInfo, uint32_t roamId, + eCsrRoamResult roamResult) +{ + if (pSession) { + if (pSession->bRefAssocStartCnt) { + pSession->bRefAssocStartCnt--; + + if (0 != pSession->bRefAssocStartCnt) { + CDF_ASSERT(pSession->bRefAssocStartCnt == 0); + return; + } + /* Need to call association_completion because there is an assoc_start pending. */ + csr_roam_call_callback(pMac, pSession->sessionId, NULL, + roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } + csr_roam_call_callback(pMac, pSession->sessionId, pRoamInfo, + roamId, eCSR_ROAM_ROAMING_COMPLETION, + roamResult); + } else { + sms_log(pMac, LOGW, FL(" pSession is NULL")); + } +} + +CDF_STATUS csr_roam_start_roaming(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamingReason roamingReason) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + if (CSR_IS_LOSTLINK_ROAMING(roamingReason) && + (false == pMac->roam.roamSession[sessionId].fCancelRoaming)) { + status = csr_scan_request_lost_link1(pMac, sessionId); + } + return status; +} + +/* return a bool to indicate whether roaming completed or continue. */ +bool csr_roam_complete_roaming(tpAniSirGlobal pMac, uint32_t sessionId, + bool fForce, eCsrRoamResult roamResult) +{ + bool fCompleted = true; + uint32_t roamTime = + (uint32_t) (pMac->roam.configParam.nRoamingTime * + CDF_TICKS_PER_SECOND); + uint32_t curTime = (uint32_t) cdf_mc_timer_get_system_ticks(); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return false; + } + /* Check whether time is up */ + if (pSession->fCancelRoaming || fForce || + ((curTime - pSession->roamingStartTime) > roamTime) || + eCsrReassocRoaming == pSession->roamingReason || + eCsrDynamicRoaming == pSession->roamingReason) { + sms_log(pMac, LOGW, FL(" indicates roaming completion")); + if (pSession->fCancelRoaming + && CSR_IS_LOSTLINK_ROAMING(pSession->roamingReason)) { + /* roaming is cancelled, tell HDD to indicate disconnect */ + /* Because LIM overload deauth_ind for both deauth frame and missed beacon */ + /* we need to use this logic to detinguish 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; + } + } + csr_call_roaming_completion_callback(pMac, pSession, NULL, 0, + roamResult); + pSession->roamingReason = eCsrNotRoaming; + } else { + pSession->roamResult = roamResult; + if (!CDF_IS_STATUS_SUCCESS + (csr_roam_start_roaming_timer + (pMac, sessionId, CDF_MC_TIMER_TO_SEC_UNIT))) { + csr_call_roaming_completion_callback(pMac, pSession, NULL, + 0, roamResult); + pSession->roamingReason = eCsrNotRoaming; + } else { + fCompleted = false; + } + } + return fCompleted; +} + +void csr_roam_cancel_roaming(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if (CSR_IS_ROAMING(pSession)) { + sms_log(pMac, LOGW, "Cancel roaming"); + pSession->fCancelRoaming = 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 */ + csr_roam_complete_roaming(pMac, sessionId, true, + roamResult); + /* Since CSR may be in lostlink roaming situation, abort all roaming related activities */ + csr_scan_abort_mac_scan(pMac, sessionId, + eCSR_SCAN_ABORT_DEFAULT); + csr_roam_stop_roaming_timer(pMac, sessionId); + } + } +} + +void csr_roam_roaming_timer_handler(void *pv) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *) pv; + tpAniSirGlobal pMac = pInfo->pMac; + uint32_t sessionId = pInfo->sessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if (false == pSession->fCancelRoaming) { + if (!CDF_IS_STATUS_SUCCESS + (csr_roam_start_roaming + (pMac, sessionId, pSession->roamingReason))) { + csr_call_roaming_completion_callback(pMac, pSession, NULL, + 0, + pSession->roamResult); + pSession->roamingReason = eCsrNotRoaming; + } + } +} + +CDF_STATUS csr_roam_start_roaming_timer(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t interval) +{ + CDF_STATUS status; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG1, " csrScanStartRoamingTimer"); + pSession->roamingTimerInfo.sessionId = (uint8_t) sessionId; + status = cdf_mc_timer_start(&pSession->hTimerRoaming, + interval / CDF_MC_TIMER_TO_MS_UNIT); + + return status; +} + +CDF_STATUS csr_roam_stop_roaming_timer(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return cdf_mc_timer_stop + (&pMac->roam.roamSession[sessionId].hTimerRoaming); +} + +void csr_roam_wait_for_key_time_out_handler(void *pv) +{ + tCsrTimerInfo *pInfo = (tCsrTimerInfo *) pv; + tpAniSirGlobal pMac = pInfo->pMac; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, pInfo->sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (pSession == NULL) { + sms_log(pMac, LOGE, "%s: session not found", __func__); + return; + } + + sms_log(pMac, LOGW, + FL("WaitForKey timer expired in state=%s sub-state=%s"), + mac_trace_get_neighbour_roam_state(pMac->roam. + neighborRoamInfo[pInfo->sessionId]. + neighborRoamState), + mac_trace_getcsr_roam_sub_state(pMac->roam. + curSubState[pInfo->sessionId])); + + if (CSR_IS_WAIT_FOR_KEY(pMac, pInfo->sessionId)) { +#ifdef FEATURE_WLAN_LFR + if (csr_neighbor_roam_is_handoff_in_progress(pMac, pInfo->sessionId)) { + /* + * Enable heartbeat timer when hand-off is in progress + * and Key Wait timer expired. + */ + sms_log(pMac, LOG2, + "Enabling HB timer after WaitKey expiry" + " (nHBCount=%d)", + pMac->roam.configParam.HeartbeatThresh24); + cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, + pMac->roam.configParam.HeartbeatThresh24); + } +#endif + sms_log(pMac, LOGE, " SME pre-auth state timeout. "); + + /* Change the substate so command queue is unblocked. */ + if (CSR_ROAM_SESSION_MAX > pInfo->sessionId) { + csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_NONE, + pInfo->sessionId); + } + + if (csr_is_conn_state_connected_infra(pMac, pInfo->sessionId)) { + csr_roam_link_up(pMac, + pSession->connectedProfile.bssid); + sme_process_pending_queue(pMac); + status = sme_acquire_global_lock(&pMac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_disconnect(pMac, pInfo->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + sme_release_global_lock(&pMac->sme); + } + } else { + sms_log(pMac, LOGE, "%s: session not found", __func__); + } + } + +} + +CDF_STATUS csr_roam_start_wait_for_key_timer(tpAniSirGlobal pMac, uint32_t interval) +{ + CDF_STATUS status; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pMac->roam.WaitForKeyTimerInfo. + sessionId]; +#ifdef FEATURE_WLAN_LFR + if (csr_neighbor_roam_is_handoff_in_progress(pMac, + pMac->roam.WaitForKeyTimerInfo. + sessionId)) { + /* Disable heartbeat timer when hand-off is in progress */ + sms_log(pMac, LOG2, + FL("disabling HB timer in state=%s sub-state=%s"), + mac_trace_get_neighbour_roam_state(pNeighborRoamInfo-> + neighborRoamState), + mac_trace_getcsr_roam_sub_state(pMac->roam. + curSubState[pMac->roam. + WaitForKeyTimerInfo. + sessionId] + )); + cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0); + } +#endif + sms_log(pMac, LOG1, " csrScanStartWaitForKeyTimer"); + status = cdf_mc_timer_start(&pMac->roam.hTimerWaitForKey, + interval / CDF_MC_TIMER_TO_MS_UNIT); + + return status; +} + +CDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[pMac->roam.WaitForKeyTimerInfo. + sessionId]; + + sms_log(pMac, LOG2, + FL("WaitForKey timer stopped in state=%s sub-state=%s"), + mac_trace_get_neighbour_roam_state(pNeighborRoamInfo-> + neighborRoamState), + mac_trace_getcsr_roam_sub_state(pMac->roam. + curSubState[pMac->roam. + WaitForKeyTimerInfo. + sessionId])); +#ifdef FEATURE_WLAN_LFR + if (csr_neighbor_roam_is_handoff_in_progress(pMac, + pMac->roam.WaitForKeyTimerInfo. + sessionId)) { + /* + * Enable heartbeat timer when hand-off is in progress + * and Key Wait timer got stopped for some reason + */ + sms_log(pMac, LOG2, "Enabling HB timer after WaitKey stop" + " (nHBCount=%d)", + pMac->roam.configParam.HeartbeatThresh24); + cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, + pMac->roam.configParam.HeartbeatThresh24); + } +#endif + return cdf_mc_timer_stop(&pMac->roam.hTimerWaitForKey); +} + +void csr_roam_completion(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand, + eCsrRoamResult roamResult, bool fSuccess) +{ + eRoamCmdStatus roamStatus = csr_get_roam_complete_status(pMac, sessionId); + uint32_t roamId = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if (pCommand) { + roamId = pCommand->u.roamCmd.roamId; + if (sessionId != pCommand->sessionId) { + CDF_ASSERT(sessionId == pCommand->sessionId); + return; + } + } + if (eCSR_ROAM_ROAMING_COMPLETION == roamStatus) { + /* if success, force roaming completion */ + csr_roam_complete_roaming(pMac, sessionId, fSuccess, roamResult); + } else { + if (pSession->bRefAssocStartCnt != 0) { + CDF_ASSERT(pSession->bRefAssocStartCnt == 0); + return; + } + sms_log(pMac, LOGW, + FL + (" indicates association completion. roamResult = %d"), + roamResult); + csr_roam_call_callback(pMac, sessionId, pRoamInfo, roamId, + roamStatus, roamResult); + } +} + +CDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t type, tSirSmeRsp *pSirMsg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeDeauthInd *pDeauthIndMsg = NULL; + tSirSmeDisassocInd *pDisassocIndMsg = NULL; + eCsrRoamResult result = eCSR_ROAM_RESULT_LOSTLINK; + tCsrRoamInfo *pRoamInfo = NULL; + tCsrRoamInfo roamInfo; + bool fToRoam; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_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 = 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 dosent know the reason code + * eSIR_BEACON_MISSED is defined as locally + */ + } else { + sms_log(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)) { + csr_roam_call_callback(pMac, sessionId, NULL, 0, + eCSR_ROAM_LOSTLINK_DETECTED, result); + /*Move the state to Idle after disconnection */ + csr_roam_state_change(pMac, eCSR_ROAMING_STATE_IDLE, sessionId); + + } + + if (eWNI_SME_DISASSOC_IND == type) { + status = csr_send_mb_disassoc_cnf_msg(pMac, pDisassocIndMsg); + } else if (eWNI_SME_DEAUTH_IND == type) { + status = csr_send_mb_deauth_cnf_msg(pMac, pDeauthIndMsg); + } + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* If fail to send confirmation to PE, not to trigger roaming */ + fToRoam = false; + } + /* prepare to tell HDD to disconnect */ + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.statusCode = (tSirResultCodes) pSession->roamingStatusCode; + roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; + if (eWNI_SME_DISASSOC_IND == type) { + /* staMacAddr */ + cdf_mem_copy(roamInfo.peerMac.bytes, + pDisassocIndMsg->peerMacAddr, + sizeof(tSirMacAddr)); + roamInfo.staId = (uint8_t) pDisassocIndMsg->staId; + roamInfo.reasonCode = pDisassocIndMsg->reasonCode; + } else if (eWNI_SME_DEAUTH_IND == type) { + /* staMacAddr */ + cdf_mem_copy(roamInfo.peerMac.bytes, + pDeauthIndMsg->peerMacAddr, + sizeof(tSirMacAddr)); + roamInfo.staId = (uint8_t) pDeauthIndMsg->staId; + roamInfo.reasonCode = pDeauthIndMsg->reasonCode; + } + sms_log(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 */ + csr_roam_remove_connected_bss_from_scan_cache(pMac, + &pSession-> + connectedProfile); + /* Not to do anying for lostlink with WDS */ + status = csr_roam_start_roaming(pMac, sessionId, + (eWNI_SME_DEAUTH_IND == type) ? + eCsrLostlinkRoamingDeauth : + eCsrLostlinkRoamingDisassoc); + if (pMac->roam.configParam.nRoamingTime) { + status = csr_roam_start_roaming(pMac, sessionId, + (eWNI_SME_DEAUTH_IND == type) ? + eCsrLostlinkRoamingDeauth : + eCsrLostlinkRoamingDisassoc); + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + /* For IBSS, we need to give some more info to HDD */ + if (csr_is_bss_type_ibss + (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 = + (uint32_t) cdf_mc_timer_get_system_ticks(); + csr_roam_call_callback(pMac, sessionId, pRoamInfo, + 0, eCSR_ROAM_ROAMING_START, + eCSR_ROAM_RESULT_LOSTLINK); + } else { + sms_log(pMac, LOGW, + " %s Fail to start roaming, status = %d", + __func__, status); + fToRoam = false; + } + } else { + /* We are told not to roam, indicate lostlink */ + fToRoam = false; + } + } + if (!fToRoam) { + /* Tell HDD about the lost link */ + if (!CSR_IS_INFRA_AP(&pSession->connectedProfile)) { + /* Don't call csr_roam_call_callback for GO/SoftAp case as this indication + * was already given as part of eWNI_SME_DISASSOC_IND msg handling in + * csr_roam_check_for_link_status_change API. + */ + csr_roam_call_callback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_LOSTLINK, result); + } + + } + + return status; +} + +CDF_STATUS csr_roam_lost_link_afterhandoff_failure(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + pSession->fCancelRoaming = false; + /* Only remove the connected BSS in infrastructure mode */ + csr_roam_remove_connected_bss_from_scan_cache(pMac, + &pSession->connectedProfile); + if (pMac->roam.configParam.nRoamingTime) { + status = csr_roam_start_roaming(pMac, sessionId, + pSession->roamingReason); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* + * before starting the lost link logic release + * the roam command for handoff + */ + pEntry = + csr_ll_peek_head(&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 (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, + pEntry, LL_ACCESS_LOCK)) { + csr_release_command_roam(pMac, + pCommand); + } + } + } + sms_log(pMac, LOGW, "Lost link roaming started ..."); + } + } else { + /* We are told not to roam, indicate lostlink */ + status = CDF_STATUS_E_FAILURE; + } + + return status; +} + +void csr_roam_wm_status_change_complete(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + pEntry = csr_ll_peek_head(&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 (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + csr_release_command_wm_status_change(pMac, pCommand); + } else { + sms_log(pMac, LOGE, + " ******csr_roam_wm_status_change_complete fail to release command"); + } + + } else { + sms_log(pMac, LOGW, + "CSR: WmStatusChange Completion called but LOST LINK command is not ACTIVE ..."); + } + } else { + sms_log(pMac, LOGW, + "CSR: WmStatusChange Completion called but NO commands are ACTIVE ..."); + } + sme_process_pending_queue(pMac); +} + +void csr_roam_process_wm_status_change_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tSirSmeRsp *pSirSmeMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, pCommand->sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), + pCommand->sessionId); + return; + } + sms_log(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 = + csr_roam_lost_link(pMac, pCommand->sessionId, + eWNI_SME_DISASSOC_IND, pSirSmeMsg); + break; + case eCsrDeauthenticated: + pSirSmeMsg = + (tSirSmeRsp *) &pCommand->u.wmStatusChangeCmd.u. + DeauthIndMsg; + status = + csr_roam_lost_link(pMac, pCommand->sessionId, + eWNI_SME_DEAUTH_IND, pSirSmeMsg); + break; + default: + sms_log(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 (!CDF_IS_STATUS_SUCCESS + (csr_roam_issue_stop_bss_cmd(pMac, pCommand->sessionId, true))) { + /* This is not good */ + sms_log(pMac, LOGE, + FL(" failed to issue stopBSS command")); + } + } + /* Lost Link just triggers a roaming sequence. We can complte the Lost Link */ + /* command here since there is nothing else to do. */ + csr_roam_wm_status_change_complete(pMac); +} + + +/** + * csr_compute_mode_and_band() - computes dot11mode + * @pMac: mac global context + * @dot11_mode: out param, do11 mode calculated + * @band: out param, band caclculated + * @opr_ch: operating channels + * + * This function finds dot11 mode based on current mode, operating channel and + * fw supported modes. + * + * Return: void + */ +static void +csr_compute_mode_and_band(tpAniSirGlobal mac_ctx, + eCsrCfgDot11Mode *dot11_mode, + eCsrBand *band, + uint8_t opr_ch) +{ + bool vht_24_ghz = mac_ctx->roam.configParam.enableVhtFor24GHz; + switch (mac_ctx->roam.configParam.uCfgDot11Mode) { + case eCSR_CFG_DOT11_MODE_11A: + *dot11_mode = eCSR_CFG_DOT11_MODE_11A; + *band = eCSR_BAND_5G; + break; + case eCSR_CFG_DOT11_MODE_11B: + *dot11_mode = eCSR_CFG_DOT11_MODE_11B; + *band = eCSR_BAND_24; + break; + case eCSR_CFG_DOT11_MODE_11G: + *dot11_mode = eCSR_CFG_DOT11_MODE_11G; + *band = eCSR_BAND_24; + break; + case eCSR_CFG_DOT11_MODE_11N: + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + *band = CSR_GET_BAND(opr_ch); + 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 (CDS_IS_CHANNEL_24GHZ(opr_ch) && !vht_24_ghz) + /* Disable 11AC operation */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + else + *dot11_mode = eCSR_CFG_DOT11_MODE_11AC; + } else { + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + } + *band = CSR_GET_BAND(opr_ch); + 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 (CDS_IS_CHANNEL_24GHZ(opr_ch) && !vht_24_ghz) + /* Disable 11AC operation */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + else + *dot11_mode = eCSR_CFG_DOT11_MODE_11AC_ONLY; + } else { + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + } + *band = CSR_GET_BAND(opr_ch); + 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 (CDS_IS_CHANNEL_24GHZ(opr_ch) + && !vht_24_ghz) + /* Disable 11AC operation */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + else + *dot11_mode = eCSR_CFG_DOT11_MODE_11AC; + } else { + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; + } +#else + *dot11_mode = eCSR_CFG_DOT11_MODE_11N; +#endif + *band = CSR_GET_BAND(opr_ch); + break; + default: + /* + * Global dot11 Mode setting is 11a/b/g. use the channel number + * to determine the Mode setting. + */ + if (eCSR_OPERATING_CHANNEL_AUTO == opr_ch) { + *band = mac_ctx->roam.configParam.eBand; + if (eCSR_BAND_24 == *band) { + /* + * See reason in else if ( CDS_IS_CHANNEL_24GHZ + * (opr_ch) ) to pick 11B + */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11B; + } else { + /* prefer 5GHz */ + *band = eCSR_BAND_5G; + *dot11_mode = eCSR_CFG_DOT11_MODE_11A; + } + } else if (CDS_IS_CHANNEL_24GHZ(opr_ch)) { + /* + * 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. + */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11B; + *band = eCSR_BAND_24; + } else { + /* else, it's a 5.0GHz channel. Set mode to 11a. */ + *dot11_mode = eCSR_CFG_DOT11_MODE_11A; + *band = eCSR_BAND_5G; + } + break; + } /* switch */ +} + +/** + * csr_roam_get_phy_mode_band_for_bss() - This function returns band and mode + * information. + * @mac_ctx: mac global context + * @profile: bss profile + * @band: out param, band caclculated + * @opr_ch: operating channels + * + * This function finds dot11 mode based on current mode, operating channel and + * fw supported modes. 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. + * + * Return: dot11mode + */ +static eCsrCfgDot11Mode +csr_roam_get_phy_mode_band_for_bss(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, + uint8_t opr_chn, + eCsrBand *p_band) +{ + eCsrBand band; + eCsrCfgDot11Mode curr_mode = mac_ctx->roam.configParam.uCfgDot11Mode; + eCsrCfgDot11Mode cfg_dot11_mode = + csr_get_cfg_dot11_mode_from_csr_phy_mode(profile, + (eCsrPhyMode) profile->phyMode, + mac_ctx->roam.configParam.ProprietaryRatesEnabled); + + /* + * If the global setting for dot11Mode is set to auto/abg, we overwrite + * the setting in the profile. + */ + if (((!CSR_IS_INFRA_AP(profile) && !CSR_IS_WDS(profile)) + && ((eCSR_CFG_DOT11_MODE_AUTO == curr_mode) + || (eCSR_CFG_DOT11_MODE_ABG == curr_mode))) + || (eCSR_CFG_DOT11_MODE_AUTO == cfg_dot11_mode) + || (eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode)) { + csr_compute_mode_and_band(mac_ctx, &cfg_dot11_mode, + &band, opr_chn); + } /* if( eCSR_CFG_DOT11_MODE_ABG == cfg_dot11_mode ) */ + else { + /* dot11 mode is set, lets pick the band */ + if (eCSR_OPERATING_CHANNEL_AUTO == opr_chn) { + /* channel is Auto also. */ + band = mac_ctx->roam.configParam.eBand; + if (eCSR_BAND_ALL == band) { + /* prefer 5GHz */ + band = eCSR_BAND_5G; + } + } else{ + band = CSR_GET_BAND(opr_chn); + } + } + if (p_band) + *p_band = band; + + if (opr_chn == 14) { + sms_log(mac_ctx, LOGE, FL("Switching to Dot11B mode")); + cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11B; + } + + /* + * Incase of WEP Security encryption type is coming as part of add key. + * So while STart BSS dont have information + */ + if ((!CSR_IS_11n_ALLOWED(profile->EncryptionType.encryptionType[0]) + || ((profile->privacy == 1) + && (profile->EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_NONE))) + && ((eCSR_CFG_DOT11_MODE_11N == cfg_dot11_mode) || +#ifdef WLAN_FEATURE_11AC + (eCSR_CFG_DOT11_MODE_11AC == cfg_dot11_mode) +#endif + )) { + /* We cannot do 11n here */ + if (CDS_IS_CHANNEL_24GHZ(opr_chn)) + cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11G; + else + cfg_dot11_mode = eCSR_CFG_DOT11_MODE_11A; + } + return cfg_dot11_mode; +} + +CDF_STATUS csr_roam_issue_stop_bss(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamSubState NewSubstate) +{ + CDF_STATUS status; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + { + host_log_ibss_pkt_type *pIbssLog; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_log_ibss_pkt_type, + LOG_WLAN_IBSS_C); + if (pIbssLog) { + pIbssLog->eventId = WLAN_IBSS_EVENT_STOP_REQ; + WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + /* Set the roaming substate to 'stop Bss request'... */ + csr_roam_substate_change(pMac, NewSubstate, sessionId); + + /* attempt to stop the Bss (reason code is ignored...) */ + status = csr_send_mb_stop_bss_req_msg(pMac, sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGW, + FL("csr_send_mb_stop_bss_req_msg failed with status %d"), + status); + } + return status; +} + +/* pNumChan is a caller allocated space with the sizeof pChannels */ +CDF_STATUS csr_get_cfg_valid_channels(tpAniSirGlobal pMac, uint8_t *pChannels, + uint32_t *pNumChan) +{ + if (!IS_SIR_STATUS_SUCCESS(wlan_cfg_get_str(pMac, + WNI_CFG_VALID_CHANNEL_LIST, + (uint8_t *) pChannels, pNumChan))) + return CDF_STATUS_E_FAILURE; + return CDF_STATUS_SUCCESS; +} + +tPowerdBm csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel) +{ + uint32_t cfgLength = 0; + uint16_t cfgId = 0; + tPowerdBm maxTxPwr = 0; + uint8_t *pCountryInfo = NULL; + CDF_STATUS status; + uint8_t count = 0; + uint8_t firstChannel; + uint8_t maxChannels; + + if (CDS_IS_CHANNEL_5GHZ(channel)) { + cfgId = WNI_CFG_MAX_TX_POWER_5; + cfgLength = WNI_CFG_MAX_TX_POWER_5_LEN; + } else if (CDS_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 = cdf_mem_malloc(cfgLength); + if (NULL == pCountryInfo) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (status != CDF_STATUS_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("%s: failed to allocate memory, status = %d"), + __FUNCTION__, status); + goto error; + } + if (wlan_cfg_get_str(pMac, cfgId, (uint8_t *)pCountryInfo, + &cfgLength) != eSIR_SUCCESS) { + goto error; + } + /* Identify the channel and maxtxpower */ + 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) + cdf_mem_free(pCountryInfo); + + return maxTxPwr; +} + +bool csr_roam_is_channel_valid(tpAniSirGlobal pMac, uint8_t channel) +{ + bool fValid = false; + uint32_t idxValidChannels; + uint32_t len = sizeof(pMac->roam.validChannelList); + + if (CDF_IS_STATUS_SUCCESS + (csr_get_cfg_valid_channels(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; +} + +bool csr_roam_is_valid40_mhz_channel(tpAniSirGlobal pMac, uint8_t channel) +{ + bool fValid = false; + uint8_t i; + for (i = 0; i < pMac->scan.base40MHzChannels.numChannels; i++) { + if (channel == pMac->scan.base40MHzChannels.channelList[i]) { + fValid = true; + break; + } + } + return fValid; +} + +/* This function check and validate whether the NIC can do CB (40MHz) */ +static ePhyChanBondState csr_get_cb_mode_from_ies(tpAniSirGlobal pMac, + uint8_t primaryChn, + tDot11fBeaconIEs *pIes) +{ + ePhyChanBondState eRet = PHY_SINGLE_CHANNEL_CENTERED; + uint8_t centerChn; + uint32_t ChannelBondingMode; + if (CDS_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.channelBondingMode5GHz; + } + + if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == ChannelBondingMode) + return PHY_SINGLE_CHANNEL_CENTERED; + + /* Figure what the other side's CB mode */ + if (!(pIes->HTCaps.present && (eHT_CHANNEL_WIDTH_40MHZ == + pIes->HTCaps.supportedChannelWidthSet))) { + return PHY_SINGLE_CHANNEL_CENTERED; + } + + /* Check set as TKIP or not. */ + if (((NULL != &(pIes->RSN.pwise_cipher_suites[0][0]) && + (pIes->RSN.pwise_cipher_suite_count == 1)) && + !memcmp(&(pIes->RSN.pwise_cipher_suites[0][0]), + "\x00\x0f\xac\x02", 4)) + || (((NULL != &(pIes->WPA)) && + (pIes->WPA.unicast_cipher_count == 1)) + && ((NULL != &(pIes->WPA.unicast_ciphers[0])) + && !memcmp(&(pIes->WPA.unicast_ciphers[0]), + "\x00\x0f\xac\x02", 4)))) { + sms_log(pMac, LOGW, + " No channel bonding in TKIP mode "); + return PHY_SINGLE_CHANNEL_CENTERED; + } + + if (!pIes->HTInfo.present) + return PHY_SINGLE_CHANNEL_CENTERED; + + /* + * This is called during INFRA STA/CLIENT and should use the merged + * value of supported channel width and recommended tx width as per + * standard + */ + sms_log(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) + && !csr_roam_is_valid40_mhz_channel(pMac, centerChn)) { + sms_log(pMac, LOGE, + "Invalid center channel (%d), disable 40MHz mode", + centerChn); + eRet = PHY_SINGLE_CHANNEL_CENTERED; + } + return eRet; +} + +bool csr_is_encryption_in_list(tpAniSirGlobal pMac, + tCsrEncryptionList *pCipherList, + eCsrEncryptionType encryptionType) +{ + bool fFound = false; + uint32_t idx; + for (idx = 0; idx < pCipherList->numEntries; idx++) { + if (pCipherList->encryptionType[idx] == encryptionType) { + fFound = true; + break; + } + } + return fFound; +} + +bool csr_is_auth_in_list(tpAniSirGlobal pMac, tCsrAuthList *pAuthList, + eCsrAuthType authType) +{ + bool fFound = false; + uint32_t idx; + for (idx = 0; idx < pAuthList->numEntries; idx++) { + if (pAuthList->authType[idx] == authType) { + fFound = true; + break; + } + } + return fFound; +} + +bool csr_is_same_profile(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pProfile1, + tCsrRoamProfile *pProfile2) +{ + uint32_t i; + bool fCheck = false; + tCsrScanResultFilter *pScanFilter = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (!(pProfile1 && pProfile2)) + return fCheck; + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) + return fCheck; + + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csr_roam_prepare_filter_from_profile(pMac, pProfile2, + pScanFilter); + if (!(CDF_IS_STATUS_SUCCESS(status))) + goto free_scan_filter; + + for (i = 0; i < pScanFilter->SSIDs.numOfSSIDs; i++) { + fCheck = csr_is_ssid_match(pMac, + pScanFilter->SSIDs.SSIDList[i].SSID.ssId, + pScanFilter->SSIDs.SSIDList[i].SSID.length, + pProfile1->SSID.ssId, + pProfile1->SSID.length, + false); + if (fCheck) + break; + } + if (!fCheck) + goto free_scan_filter; + + if (!csr_is_auth_in_list(pMac, &pProfile2->AuthType, + pProfile1->AuthType) + || (pProfile2->BSSType != pProfile1->BSSType) + || !csr_is_encryption_in_list(pMac, &pProfile2->EncryptionType, + pProfile1->EncryptionType)) { + fCheck = false; + goto free_scan_filter; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pProfile1->MDID.mdiePresent || pProfile2->MDID.mdiePresent) { + if (pProfile1->MDID.mobilityDomain + != pProfile2->MDID.mobilityDomain) { + fCheck = false; + goto free_scan_filter; + } + } +#endif + /* Match found */ + fCheck = true; +free_scan_filter: + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return fCheck; +} + +bool csr_roam_is_same_profile_keys(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pConnProfile, + tCsrRoamProfile *pProfile2) +{ + bool fCheck = false; + int i; + do { + /* Only check for static WEP */ + if (!csr_is_encryption_in_list + (pMac, &pProfile2->EncryptionType, + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) + && !csr_is_encryption_in_list(pMac, + &pProfile2->EncryptionType, + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)) { + fCheck = true; + break; + } + if (!csr_is_encryption_in_list + (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 (!cdf_mem_compare(&pConnProfile->Keys.KeyMaterial[i], + &pProfile2->Keys.KeyMaterial[i], + pProfile2->Keys.KeyLength[i])) { + break; + } + } + if (i == CSR_MAX_NUM_KEY) { + fCheck = true; + } + } while (0); + return fCheck; +} + +/* IBSS */ + +uint8_t csr_roam_get_ibss_start_channel_number50(tpAniSirGlobal pMac) +{ + uint8_t channel = 0; + uint32_t idx; + uint32_t idxValidChannels; + bool fFound = false; + uint32_t len = sizeof(pMac->roam.validChannelList); + + if (eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel5G) { + channel = pMac->roam.configParam.AdHocChannel5G; + if (!csr_roam_is_channel_valid(pMac, channel)) { + channel = 0; + } + } + if (0 == channel + && + CDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels + (pMac, + (uint8_t *) pMac->roam.validChannelList, + &len))) { + for (idx = 0; (idx < CSR_NUM_IBSS_START_CHANNELS_50) && !fFound; + idx++) { + for (idxValidChannels = 0; + (idxValidChannels < len) && !fFound; + idxValidChannels++) { + if (csr_start_ibss_channels50[idx] == + pMac->roam. + validChannelList[idxValidChannels]) { + fFound = true; + channel = csr_start_ibss_channels50[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 (CDS_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; +} + +uint8_t csr_roam_get_ibss_start_channel_number24(tpAniSirGlobal pMac) +{ + uint8_t channel = 1; + uint32_t idx; + uint32_t idxValidChannels; + bool fFound = false; + uint32_t len = sizeof(pMac->roam.validChannelList); + + if (eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel24) { + channel = pMac->roam.configParam.AdHocChannel24; + if (!csr_roam_is_channel_valid(pMac, channel)) { + channel = 0; + } + } + + if (0 == channel + && + CDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels + (pMac, + (uint8_t *) pMac->roam.validChannelList, + &len))) { + for (idx = 0; (idx < CSR_NUM_IBSS_START_CHANNELS_24) && !fFound; + idx++) { + for (idxValidChannels = 0; + (idxValidChannels < len) && !fFound; + idxValidChannels++) { + if (csr_start_ibss_channels24[idx] == + pMac->roam. + validChannelList[idxValidChannels]) { + fFound = true; + channel = csr_start_ibss_channels24[idx]; + } + } + } + } + + return channel; +} + +/** + * csr_populate_basic_rates() - populates OFDM or CCK rates + * @rates: rate struct to populate + * @type: true: ofdm rates, false: cck rates + * @masked: indicates if rates are to be masked with + * CSR_DOT11_BASIC_RATE_MASK + * + * This function will populate OFDM or CCK rates + * + * Return: void + */ +static void +csr_populate_basic_rates(tSirMacRateSet *rate_set, bool type, bool masked) +{ + uint8_t ofdm_rates[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 + }; + uint8_t cck_rates[4] = { + SIR_MAC_RATE_1, + SIR_MAC_RATE_2, + SIR_MAC_RATE_5_5, + SIR_MAC_RATE_11 + }; + + if (type == true) { + rate_set->numRates = 8; + cdf_mem_copy(rate_set->rate, ofdm_rates, sizeof(ofdm_rates)); + if (masked) { + rate_set->rate[0] |= CSR_DOT11_BASIC_RATE_MASK; + rate_set->rate[2] |= CSR_DOT11_BASIC_RATE_MASK; + rate_set->rate[4] |= CSR_DOT11_BASIC_RATE_MASK; + } + } else { + rate_set->numRates = 4; + cdf_mem_copy(rate_set->rate, cck_rates, sizeof(cck_rates)); + if (masked) { + rate_set->rate[0] |= CSR_DOT11_BASIC_RATE_MASK; + rate_set->rate[1] |= CSR_DOT11_BASIC_RATE_MASK; + rate_set->rate[2] |= CSR_DOT11_BASIC_RATE_MASK; + rate_set->rate[3] |= CSR_DOT11_BASIC_RATE_MASK; + } + } +} + +/** + * csr_convert_mode_to_nw_type() - convert mode into network type + * @dot11_mode: dot11_mode + * @band: 2.4 or 5 GHz + * + * Return: tSirNwType + */ +static tSirNwType +csr_convert_mode_to_nw_type(eCsrCfgDot11Mode dot11_mode, eCsrBand band) +{ + switch (dot11_mode) { + case eCSR_CFG_DOT11_MODE_11G: + return eSIR_11G_NW_TYPE; + case eCSR_CFG_DOT11_MODE_11B: + return eSIR_11B_NW_TYPE; + case eCSR_CFG_DOT11_MODE_11A: + return eSIR_11A_NW_TYPE; + case eCSR_CFG_DOT11_MODE_11N: + default: + /* + * Because LIM only verifies it against 11a, 11b or 11g, set + * only 11g or 11a here + */ + if (eCSR_BAND_24 == band) + return eSIR_11G_NW_TYPE; + else + return eSIR_11A_NW_TYPE; + } + return eSIR_DONOT_USE_NW_TYPE; +} + +/** + * csr_roam_get_bss_start_parms() - get bss start param from profile + * @pMac: mac global context + * @pProfile: roam profile + * @pParam: out param, start bss params + * + * This function populates start bss param from roam profile + * + * Return: void + */ +static void +csr_roam_get_bss_start_parms(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, + tCsrRoamStartBssParams *pParam) +{ + eCsrBand band; + uint8_t opr_ch = 0; + tSirNwType nw_type; + uint8_t tmp_opr_ch = 0; + tSirMacRateSet *opr_rates = &pParam->operationalRateSet; + tSirMacRateSet *ext_rates = &pParam->extendedRateSet; + + if (pProfile->ChannelInfo.numOfChannels + && pProfile->ChannelInfo.ChannelList) { + tmp_opr_ch = pProfile->ChannelInfo.ChannelList[0]; + } + + pParam->uCfgDot11Mode = csr_roam_get_phy_mode_band_for_bss(pMac, + pProfile, tmp_opr_ch, &band); + + if (((pProfile->csrPersona == CDF_P2P_CLIENT_MODE) + || (pProfile->csrPersona == CDF_P2P_GO_MODE)) + && (pParam->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11B)) { + /* This should never happen */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + FL("For P2P (persona %d) dot11_mode is 11B"), + pProfile->csrPersona); + CDF_ASSERT(0); + } + + nw_type = csr_convert_mode_to_nw_type(pParam->uCfgDot11Mode, band); + ext_rates->numRates = 0; + + switch (nw_type) { + default: + sms_log(pMac, LOGE, FL("sees an unknown pSirNwType (%d)"), + nw_type); + case eSIR_11A_NW_TYPE: + csr_populate_basic_rates(opr_rates, true, true); + if (eCSR_OPERATING_CHANNEL_ANY != tmp_opr_ch) { + opr_ch = tmp_opr_ch; + break; + } + opr_ch = csr_roam_get_ibss_start_channel_number50(pMac); + if (0 == opr_ch && + 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 + * csr_roam_get_phy_mode_band_for_bss always picks 11a + * for AUTO + */ + nw_type = eSIR_11B_NW_TYPE; + opr_ch = csr_roam_get_ibss_start_channel_number24(pMac); + csr_populate_basic_rates(opr_rates, false, true); + } + break; + case eSIR_11B_NW_TYPE: + csr_populate_basic_rates(opr_rates, false, true); + if (eCSR_OPERATING_CHANNEL_ANY == tmp_opr_ch) + opr_ch = csr_roam_get_ibss_start_channel_number24(pMac); + else + opr_ch = tmp_opr_ch; + break; + case eSIR_11G_NW_TYPE: + /* For P2P Client and P2P GO, disable 11b rates */ + if ((pProfile->csrPersona == CDF_P2P_CLIENT_MODE) + || (pProfile->csrPersona == CDF_P2P_GO_MODE) + || (eCSR_CFG_DOT11_MODE_11G_ONLY == + pParam->uCfgDot11Mode)) { + csr_populate_basic_rates(opr_rates, true, true); + } else { + csr_populate_basic_rates(opr_rates, false, true); + csr_populate_basic_rates(ext_rates, true, false); + } + + if (eCSR_OPERATING_CHANNEL_ANY == tmp_opr_ch) + opr_ch = csr_roam_get_ibss_start_channel_number24(pMac); + else + opr_ch = tmp_opr_ch; + break; + } + pParam->operationChn = opr_ch; + pParam->sirNwType = nw_type; + pParam->ch_params.ch_width = pProfile->ch_params.ch_width; + pParam->ch_params.center_freq_seg0 = + pProfile->ch_params.center_freq_seg0; + pParam->ch_params.center_freq_seg1 = + pProfile->ch_params.center_freq_seg1; + pParam->ch_params.sec_ch_offset = + pProfile->ch_params.sec_ch_offset; +} + +static void +csr_roam_get_bss_start_parms_from_bss_desc(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, + tCsrRoamStartBssParams *pParam) +{ + if (!pParam) { + sms_log(pMac, LOGE, FL("BSS param's pointer is NULL")); + return; + } + + pParam->sirNwType = pBssDesc->nwType; + pParam->cbMode = PHY_SINGLE_CHANNEL_CENTERED; + pParam->operationChn = pBssDesc->channelId; + cdf_mem_copy(&pParam->bssid, pBssDesc->bssId, sizeof(struct cdf_mac_addr)); + + if (!pIes) { + pParam->ssId.length = 0; + pParam->operationalRateSet.numRates = 0; + sms_log(pMac, LOGE, FL("IEs struct pointer is NULL")); + return; + } + + if (pIes->SuppRates.present) { + pParam->operationalRateSet.numRates = pIes->SuppRates.num_rates; + if (pIes->SuppRates.num_rates > SIR_MAC_RATESET_EID_MAX) { + sms_log(pMac, LOGE, + FL("num_rates: %d > max val, resetting"), + pIes->SuppRates.num_rates); + pIes->SuppRates.num_rates = SIR_MAC_RATESET_EID_MAX; + } + cdf_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) { + sms_log(pMac, LOGE, + FL("num_rates: %d > max val, resetting"), + pIes->ExtSuppRates.num_rates); + pIes->ExtSuppRates.num_rates = SIR_MAC_RATESET_EID_MAX; + } + cdf_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; + cdf_mem_copy(pParam->ssId.ssId, pIes->SSID.ssid, + pParam->ssId.length); + } + pParam->cbMode = csr_get_cb_mode_from_ies(pMac, pParam->operationChn, + pIes); +} + +static void csr_roam_determine_max_rate_for_ad_hoc(tpAniSirGlobal pMac, + tSirMacRateSet *pSirRateSet) +{ + uint8_t MaxRate = 0; + uint32_t i; + uint8_t *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; +} + +CDF_STATUS csr_roam_issue_start_bss(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamStartBssParams *pParam, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, uint32_t roamId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + eCsrBand eBand; + /* Set the roaming substate to 'Start BSS attempt'... */ + csr_roam_substate_change(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)) { + host_log_ibss_pkt_type *pIbssLog; + WLAN_HOST_DIAG_LOG_ALLOC(pIbssLog, host_log_ibss_pkt_type, + LOG_WLAN_IBSS_C); + if (pIbssLog) { + if (pBssDesc) { + pIbssLog->eventId = + WLAN_IBSS_EVENT_JOIN_IBSS_REQ; + cdf_mem_copy(pIbssLog->bssid, pBssDesc->bssId, + 6); + } else { + pIbssLog->eventId = + WLAN_IBSS_EVENT_START_IBSS_REQ; + } + cdf_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_HOST_DIAG_LOG_REPORT(pIbssLog); + } + } +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + /* Put RSN information in for Starting BSS */ + pParam->nRSNIELength = (uint16_t) 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 (csr_is_valid_channel(pMac, pParam->operationChn) != + CDF_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 = + csr_roam_get_phy_mode_band_for_bss(pMac, pProfile, + pParam-> + operationChn, + &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 = + csr_send_mb_start_bss_req_msg(pMac, sessionId, pProfile->BSSType, pParam, + pBssDesc); + return status; +} + +static void csr_roam_prepare_bss_params(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, + tBssConfigParam *pBssConfig, + tDot11fBeaconIEs *pIes) +{ + uint8_t Channel; + ePhyChanBondState cbMode = PHY_SINGLE_CHANNEL_CENTERED; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + if (pBssDesc) { + csr_roam_get_bss_start_parms_from_bss_desc(pMac, pBssDesc, pIes, + &pSession->bssParams); + /* Since csr_roam_get_bss_start_parms_from_bss_desc 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)) { + cdf_mem_copy(&pSession->bssParams.bssid, + &pSession->selfMacAddr, + sizeof(struct cdf_mac_addr)); + } + } else { + csr_roam_get_bss_start_parms(pMac, pProfile, &pSession->bssParams); + /* Use the first SSID */ + if (pProfile->SSIDs.numOfSSIDs) { + cdf_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)) { + cdf_mem_copy(&pSession->bssParams.bssid, + &pSession->selfMacAddr, + sizeof(struct cdf_mac_addr)); + } + /* Use the first BSSID */ + else if (pProfile->BSSIDs.numOfBSSIDs) { + cdf_mem_copy(&pSession->bssParams.bssid, + pProfile->BSSIDs.bssid, + sizeof(struct cdf_mac_addr)); + } else { + cdf_mem_set(&pSession->bssParams.bssid, + sizeof(struct cdf_mac_addr), 0); + } + } + Channel = pSession->bssParams.operationChn; + /* Set operating channel in pProfile which will be used */ + /* in csr_roam_set_bss_config_cfg() to determine channel bonding */ + /* mode and will be configured in CFG later */ + pProfile->operationChannel = Channel; + + if (Channel == 0) { + sms_log(pMac, LOGE, + " CSR cannot find a channel to start IBSS"); + } else { + + csr_roam_determine_max_rate_for_ad_hoc(pMac, + &pSession->bssParams. + operationalRateSet); + if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_START_IBSS(pProfile)) { + if (CDS_IS_CHANNEL_24GHZ(Channel)) { + cbMode = + pMac->roam.configParam. + channelBondingMode24GHz; + } else { + cbMode = + pMac->roam.configParam. + channelBondingMode5GHz; + } + sms_log(pMac, LOG1, "## cbMode %d", cbMode); + pBssConfig->cbMode = cbMode; + pSession->bssParams.cbMode = cbMode; + } + } +} + +static CDF_STATUS csr_roam_start_ibss(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + bool *pfSameIbss) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool fSameIbss = false; + + if (csr_is_conn_state_ibss(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 (csr_is_same_profile + (pMac, &pMac->roam.roamSession[sessionId].connectedProfile, + pProfile)) { + fSameIbss = true; + } else { + status = + csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING); + } + } else if (csr_is_conn_state_connected_infra(pMac, sessionId)) { + /* Disassociate from the connected Infrastructure network... */ + status = + csr_roam_issue_disassociate(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, + false); + } else { + tBssConfigParam *pBssConfig; + + pBssConfig = cdf_mem_malloc(sizeof(tBssConfigParam)); + if (NULL == pBssConfig) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_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 = + csr_roam_prepare_bss_config_from_profile(pMac, pProfile, + pBssConfig, + NULL); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* save dotMode */ + pMac->roam.roamSession[sessionId].bssParams. + uCfgDot11Mode = pBssConfig->uCfgDot11Mode; + /* Prepare some more parameters for this IBSS */ + csr_roam_prepare_bss_params(pMac, sessionId, + pProfile, NULL, + pBssConfig, NULL); + status = + csr_roam_set_bss_config_cfg(pMac, sessionId, + pProfile, NULL, + pBssConfig, NULL, + false); + } + + cdf_mem_free(pBssConfig); + } /* Allocate memory */ + } + + if (pfSameIbss) { + *pfSameIbss = fSameIbss; + } + return status; +} + +static void csr_roam_update_connected_profile_from_new_bss(tpAniSirGlobal pMac, + uint32_t sessionId, + tSirSmeNewBssInfo *pNewBss) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(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. */ + cdf_mem_copy(&pSession->connectedProfile.bssid.bytes, + &(pNewBss->bssId), sizeof(struct cdf_mac_addr)); + } + return; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS csr_roam_set_psk_pmk(tpAniSirGlobal pMac, uint32_t sessionId, + uint8_t *pPSK_PMK, size_t pmk_len) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(pSession->psk_pmk, pPSK_PMK, sizeof(pSession->psk_pmk)); + pSession->pmk_len = pmk_len; + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void +csr_roam_diag_set_pmkid(tCsrRoamSession *pSession) +{ + WLAN_HOST_DIAG_EVENT_DEF(secEvent, + host_event_wlan_security_payload_type); + cdf_mem_set(&secEvent, + sizeof(host_event_wlan_security_payload_type), 0); + secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_UPDATE; + secEvent.encryptionModeMulticast = + (uint8_t) diag_enc_type_from_csr_type( + pSession->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = + (uint8_t) diag_enc_type_from_csr_type( + pSession->connectedProfile.EncryptionType); + cdf_mem_copy(secEvent.bssid, + pSession->connectedProfile.bssid.bytes, + CDF_MAC_ADDR_SIZE); + secEvent.authMode = (uint8_t) diag_auth_type_from_csr_type( + pSession->connectedProfile.AuthType); + WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +CDF_STATUS +csr_roam_set_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId, + tPmkidCacheInfo *pPMKIDCache, uint32_t numItems, + bool update_entire_cache) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + uint32_t i = 0; + tPmkidCacheInfo *pmksa; + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, FL("numItems = %d"), numItems); + + if (numItems > CSR_MAX_PMKID_ALLOWED) + return CDF_STATUS_E_INVAL; + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_roam_diag_set_pmkid(pSession); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + + if (update_entire_cache) { + if (numItems && pPMKIDCache) { + pSession->NumPmkidCache = (uint16_t) numItems; + cdf_mem_copy(pSession->PmkidCacheInfo, pPMKIDCache, + sizeof(tPmkidCacheInfo) * numItems); + pSession->curr_cache_idx = (uint16_t)numItems; + } + return CDF_STATUS_SUCCESS; + } + + for (i = 0; i < numItems; i++) { + pmksa = &pPMKIDCache[i]; + + /* Delete the entry if present */ + csr_roam_del_pmkid_from_cache(pMac, sessionId, + pmksa->BSSID.bytes, false); + + /* Add entry to the cache */ + cdf_copy_macaddr( + &pSession->PmkidCacheInfo[pSession->curr_cache_idx].BSSID, + &pmksa->BSSID); + cdf_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 CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, + uint32_t sessionId, + const uint8_t *pBSSId, + bool flush_cache) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + bool fMatchFound = false; + uint32_t Index; + uint32_t curr_idx; + uint32_t i; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + /* Check if there are no entries to delete */ + if (0 == pSession->NumPmkidCache) { + sms_log(pMac, LOG1, FL("No entries to delete/Flush")); + return CDF_STATUS_SUCCESS; + } + + if (flush_cache) { + /* Flush the entire cache */ + cdf_mem_zero(pSession->PmkidCacheInfo, + sizeof(tPmkidCacheInfo) * CSR_MAX_PMKID_ALLOWED); + pSession->NumPmkidCache = 0; + pSession->curr_cache_idx = 0; + return CDF_STATUS_SUCCESS; + } + + /* !flush_cache - so look up in the cache */ + for (Index = 0; Index < CSR_MAX_PMKID_ALLOWED; Index++) { + if (cdf_mem_compare(pSession->PmkidCacheInfo[Index].BSSID.bytes, + pBSSId, CDF_MAC_ADDR_SIZE)) { + fMatchFound = 1; + + /* Clear this - the matched entry */ + cdf_mem_zero(&pSession->PmkidCacheInfo[Index], + sizeof(tPmkidCacheInfo)); + break; + } + } + + if (Index == CSR_MAX_PMKID_ALLOWED && !fMatchFound) { + sms_log(pMac, LOG1, FL("No such PMKSA entry exists" + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBSSId)); + return CDF_STATUS_SUCCESS; + } + + /* Match Found, Readjust the other entries */ + curr_idx = pSession->curr_cache_idx; + if (Index < curr_idx) { + for (i = Index; i < (curr_idx - 1); i++) { + cdf_mem_copy(&pSession->PmkidCacheInfo[i], + &pSession->PmkidCacheInfo[i + 1], + sizeof(tPmkidCacheInfo)); + } + + pSession->curr_cache_idx--; + cdf_mem_zero(&pSession->PmkidCacheInfo + [pSession->curr_cache_idx], + sizeof(tPmkidCacheInfo)); + } else if (Index > curr_idx) { + for (i = Index; i > (curr_idx); i--) { + cdf_mem_copy(&pSession->PmkidCacheInfo[i], + &pSession->PmkidCacheInfo[i - 1], + sizeof(tPmkidCacheInfo)); + } + + cdf_mem_zero(&pSession->PmkidCacheInfo + [pSession->curr_cache_idx], + sizeof(tPmkidCacheInfo)); + } + + /* Decrement the count since an entry has been deleted */ + pSession->NumPmkidCache--; + return CDF_STATUS_SUCCESS; +} + +uint32_t csr_roam_get_num_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return pMac->roam.roamSession[sessionId].NumPmkidCache; +} + +CDF_STATUS csr_roam_get_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pNum, tPmkidCacheInfo *pPmkidCache) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tPmkidCacheInfo *pmksa; + uint16_t i, j; + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (!pNum || !pPmkidCache) { + sms_log(pMac, LOGE, FL("Either pNum or pPmkidCache is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (pSession->NumPmkidCache == 0) { + *pNum = 0; + return CDF_STATUS_SUCCESS; + } + + if (*pNum < pSession->NumPmkidCache) { + return CDF_STATUS_E_FAILURE; + } + + if (pSession->NumPmkidCache > CSR_MAX_PMKID_ALLOWED) { + sms_log(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 (!cdf_is_macaddr_zero(&pmksa->BSSID)) { + cdf_mem_copy(pPmkidCache, pmksa, + sizeof(tPmkidCacheInfo)); + pPmkidCache++; + j++; + } + } + + *pNum = pSession->NumPmkidCache; + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_get_wpa_rsn_req_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + uint32_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pLen) { + len = *pLen; + *pLen = pSession->nWpaRsnReqIeLength; + if (pBuf) { + if (len >= pSession->nWpaRsnReqIeLength) { + cdf_mem_copy(pBuf, pSession->pWpaRsnReqIE, + pSession->nWpaRsnReqIeLength); + status = CDF_STATUS_SUCCESS; + } + } + } + return status; +} + +CDF_STATUS csr_roam_get_wpa_rsn_rsp_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + uint32_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pLen) { + len = *pLen; + *pLen = pSession->nWpaRsnRspIeLength; + if (pBuf) { + if (len >= pSession->nWpaRsnRspIeLength) { + cdf_mem_copy(pBuf, pSession->pWpaRsnRspIE, + pSession->nWpaRsnRspIeLength); + status = CDF_STATUS_SUCCESS; + } + } + } + return status; +} + +#ifdef FEATURE_WLAN_WAPI +CDF_STATUS csr_roam_get_wapi_req_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + uint32_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pLen) { + len = *pLen; + *pLen = pSession->nWapiReqIeLength; + if (pBuf) { + if (len >= pSession->nWapiReqIeLength) { + cdf_mem_copy(pBuf, pSession->pWapiReqIE, + pSession->nWapiReqIeLength); + status = CDF_STATUS_SUCCESS; + } + } + } + return status; +} + +CDF_STATUS csr_roam_get_wapi_rsp_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + uint32_t len; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (pLen) { + len = *pLen; + *pLen = pSession->nWapiRspIeLength; + if (pBuf) { + if (len >= pSession->nWapiRspIeLength) { + cdf_mem_copy(pBuf, pSession->pWapiRspIE, + pSession->nWapiRspIeLength); + status = CDF_STATUS_SUCCESS; + } + } + } + return status; +} +#endif /* FEATURE_WLAN_WAPI */ +eRoamCmdStatus csr_get_roam_complete_status(tpAniSirGlobal pMac, uint32_t sessionId) +{ + eRoamCmdStatus retStatus = eCSR_ROAM_CONNECT_COMPLETION; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return retStatus; + } + + if (CSR_IS_ROAMING(pSession)) { + retStatus = eCSR_ROAM_ROAMING_COMPLETION; + pSession->fRoaming = false; + } + return retStatus; +} + +/* This function remove the connected BSS from te cached scan result */ +CDF_STATUS +csr_roam_remove_connected_bss_from_scan_cache(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pConnProfile) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsrScanResultFilter *pScanFilter = NULL; + tListElem *pEntry; + tCsrScanResult *pResult; + tDot11fBeaconIEs *pIes; + bool fMatch; + + if ((cdf_is_macaddr_zero(&pConnProfile->bssid) || + cdf_is_macaddr_broadcast(&pConnProfile->bssid))) + return status; + /* + * Prepare the filter. Only fill in the necessary fields. Not all fields + * are needed + */ + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + pScanFilter->BSSIDs.bssid = cdf_mem_malloc(sizeof(struct cdf_mac_addr)); + if (NULL == pScanFilter->BSSIDs.bssid) { + cdf_mem_free(pScanFilter); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(pScanFilter->BSSIDs.bssid, + &pConnProfile->bssid, sizeof(struct cdf_mac_addr)); + pScanFilter->BSSIDs.numOfBSSIDs = 1; + if (!csr_is_nullssid(pConnProfile->SSID.ssId, + pConnProfile->SSID.length)) { + pScanFilter->SSIDs.SSIDList = cdf_mem_malloc( + sizeof(tCsrSSIDInfo)); + if (NULL == pScanFilter->SSIDs.SSIDList) { + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return CDF_STATUS_E_NOMEM; + } + cdf_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 = false; + pScanFilter->bOSENAssociation = false; + pScanFilter->countryCode[0] = 0; + pScanFilter->phyMode = eCSR_DOT11_MODE_AUTO; + csr_ll_lock(&pMac->scan.scanResultList); + pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while (pEntry) { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pIes = (tDot11fBeaconIEs *) (pResult->Result.pvIes); + fMatch = csr_match_bss(pMac, &pResult->Result.BssDescriptor, + pScanFilter, NULL, NULL, NULL, &pIes); + /* Release the IEs allocated by csr_match_bss is needed */ + if (!pResult->Result.pvIes) { + /* + * need to free the IEs since it is allocated + * by csr_match_bss + */ + cdf_mem_free(pIes); + } + if (fMatch) { + /* We found the one */ + if (csr_ll_remove_entry(&pMac->scan.scanResultList, + pEntry, LL_ACCESS_NOLOCK)) + /* Free the memory */ + csr_free_scan_result_entry(pMac, pResult); + break; + } + pEntry = csr_ll_next(&pMac->scan.scanResultList, + pEntry, LL_ACCESS_NOLOCK); + } /* while */ + csr_ll_unlock(&pMac->scan.scanResultList); + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return status; +} + +static CDF_STATUS csr_roam_start_wds(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tBssConfigParam bssConfig; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + if (csr_is_conn_state_ibss(pMac, sessionId)) { + status = + csr_roam_issue_stop_bss(pMac, sessionId, + eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING); + } else if (csr_is_conn_state_connected_infra(pMac, sessionId)) { + /* Disassociate from the connected Infrastructure network... */ + status = + csr_roam_issue_disassociate(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 (csr_is_conn_state_wds(pMac, sessionId)) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_set(&bssConfig, sizeof(tBssConfigParam), 0); + /* Assume HDD provide bssid in profile */ + cdf_copy_macaddr(&pSession->bssParams.bssid, + pProfile->BSSIDs.bssid); + /* there is no Bss description before we start an WDS so we need */ + /* to adopt all Bss configuration parameters from the Profile. */ + status = + csr_roam_prepare_bss_config_from_profile(pMac, pProfile, + &bssConfig, pBssDesc); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Save profile for late use */ + csr_free_roam_profile(pMac, sessionId); + pSession->pCurRoamProfile = + cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (pSession->pCurRoamProfile != NULL) { + cdf_mem_set(pSession->pCurRoamProfile, + sizeof(tCsrRoamProfile), 0); + csr_roam_copy_profile(pMac, + pSession->pCurRoamProfile, + pProfile); + } + /* Prepare some more parameters for this WDS */ + csr_roam_prepare_bss_params(pMac, sessionId, pProfile, NULL, + &bssConfig, NULL); + status = + csr_roam_set_bss_config_cfg(pMac, sessionId, pProfile, + NULL, &bssConfig, NULL, + false); + } + } + + return status; +} + +/** + * csr_add_supported_5Ghz_channels()- Add valid 5Ghz channels + * in Join req. + * @mac_ctx: pointer to global mac structure + * @csr_join_req: join req sent to lim + * + * This function is called to update valid 5Ghz channels + * in Join req. + * + * Return: void + */ +static void csr_add_supported_5Ghz_channels(tpAniSirGlobal mac_ctx, + tSirSmeJoinReq *csr_join_req) +{ + uint16_t i, j; + uint32_t size = 0; + + if (!csr_join_req) { + sms_log(mac_ctx, LOGE, FL(" csr_join_reqis NULL")); + return; + } + + size = sizeof(mac_ctx->roam.validChannelList); + if (CDF_IS_STATUS_SUCCESS + (csr_get_cfg_valid_channels(mac_ctx, + (uint8_t *) mac_ctx->roam.validChannelList, + &size))) { + for (i = 0, j = 0; i < size; i++) { + /* Only add 5ghz channels.*/ + if (CDS_IS_CHANNEL_5GHZ + (mac_ctx->roam.validChannelList[i])) { + csr_join_req->supportedChannels.channelList[j] = + mac_ctx->roam.validChannelList[i]; + j++; + } + } + csr_join_req->supportedChannels.numChnl = j; + } else { + sms_log(mac_ctx, LOGE, + FL("can not find any valid channel")); + csr_join_req->supportedChannels.numChnl = 0; + } +} + +/** + * 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 acces 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 should + * keep in mind not to access the components DIRECTLY after tSirRSNie. + */ +CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDescription, + tCsrRoamProfile *pProfile, + tDot11fBeaconIEs *pIes, uint16_t messageType) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t acm_mask = 0, uapsd_mask; + uint16_t msgLen, ieLen; + tSirMacRateSet OpRateSet; + tSirMacRateSet ExRateSet; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + uint32_t dwTmp, ucDot11Mode = 0; + /* RSN MAX is bigger than WPA MAX */ + uint8_t wpaRsnIE[DOT11F_IE_RSN_MAX_LEN]; + uint8_t txBFCsnValue = 0; + tSirSmeJoinReq *csr_join_req; + tSirMacCapabilityInfo *pAP_capabilityInfo; + tAniBool fTmp; + int8_t pwrLimit = 0; + struct ps_global_info *ps_global_info = &pMac->sme.ps_global_info; + struct ps_params *ps_param = &ps_global_info->ps_params[sessionId]; + uint8_t ese_config = 0; + + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + /* To satisfy klockworks */ + if (NULL == pBssDescription) { + sms_log(pMac, LOGE, FL(" pBssDescription is NULL")); + return CDF_STATUS_E_FAILURE; + } + + do { + pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS; + pSession->joinFailStatusCode.reasonCode = 0; + cdf_mem_copy(&pSession->joinFailStatusCode.bssId, + &pBssDescription->bssId, sizeof(tSirMacAddr)); + /* + * the tSirSmeJoinReq which includes a single + * bssDescription. it includes a single uint32_t for the + * IE fields, but the length field in the bssDescription + * needs to be interpreted to determine length of IE fields + * So, take the size of the tSirSmeJoinReq, subtract size of + * bssDescription, add the number of bytes indicated by the + * length field of the bssDescription, add the size of length + * field because it not included in the lenghth field. + */ + msgLen = sizeof(tSirSmeJoinReq) - sizeof(*pBssDescription) + + pBssDescription->length + + sizeof(pBssDescription->length) + + /* + * add in the size of the WPA IE that + * we may build. + */ + sizeof(tCsrWpaIe) + sizeof(tCsrWpaAuthIe) + + sizeof(uint16_t); + csr_join_req = cdf_mem_malloc(msgLen); + if (NULL == csr_join_req) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(csr_join_req, msgLen, 0); + csr_join_req->messageType = messageType; + csr_join_req->length = msgLen; + csr_join_req->sessionId = (uint8_t) sessionId; + csr_join_req->transactionId = 0; + if (pIes->SSID.present && pIes->SSID.num_ssid) { + csr_join_req->ssId.length = pIes->SSID.num_ssid; + cdf_mem_copy(&csr_join_req->ssId.ssId, pIes->SSID.ssid, + pIes->SSID.num_ssid); + } else + csr_join_req->ssId.length = 0; + cdf_mem_copy(&csr_join_req->selfMacAddr, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + /* bsstype */ + dwTmp = csr_translate_bsstype_to_mac_type + (pProfile->BSSType); + /* Override BssType for BTAMP */ + if (dwTmp == eSIR_BTAMP_STA_MODE) + dwTmp = eSIR_BTAMP_AP_MODE; + csr_join_req->bsstype = dwTmp; + /* dot11mode */ + ucDot11Mode = + csr_translate_to_wni_cfg_dot11_mode(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; + } + csr_join_req->dot11mode = (uint8_t) ucDot11Mode; +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + csr_join_req->cc_switch_mode = + pMac->roam.configParam.cc_switch_mode; +#endif + csr_join_req->staPersona = (uint8_t) pProfile->csrPersona; + csr_join_req->cbMode = (uint8_t) pSession->bssParams.cbMode; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("CSR PERSONA=%d CSR CbMode %d"), + pProfile->csrPersona, pSession->bssParams.cbMode); + csr_join_req->uapsdPerAcBitmask = pProfile->uapsd_mask; + status = + csr_get_rate_set(pMac, pProfile, + (eCsrPhyMode) pProfile->phyMode, + pBssDescription, pIes, &OpRateSet, + &ExRateSet); + ps_param->uapsd_per_ac_bit_mask = + pProfile->uapsd_mask; + if (CDF_IS_STATUS_SUCCESS(status)) { + /* OperationalRateSet */ + if (OpRateSet.numRates) { + csr_join_req->operationalRateSet.numRates = + OpRateSet.numRates; + cdf_mem_copy(&csr_join_req->operationalRateSet. + rate, OpRateSet.rate, + OpRateSet.numRates); + } else + csr_join_req->operationalRateSet.numRates = 0; + + /* ExtendedRateSet */ + if (ExRateSet.numRates) { + csr_join_req->extendedRateSet.numRates = + ExRateSet.numRates; + cdf_mem_copy(&csr_join_req->extendedRateSet. + rate, ExRateSet.rate, + ExRateSet.numRates); + } else + csr_join_req->extendedRateSet.numRates = 0; + } else { + csr_join_req->operationalRateSet.numRates = 0; + csr_join_req->extendedRateSet.numRates = 0; + } + /* rsnIE */ + if (csr_is_profile_wpa(pProfile)) { + /* Insert the Wpa IE into the join request */ + ieLen = + csr_retrieve_wpa_ie(pMac, pProfile, + pBssDescription, pIes, + (tCsrWpaIe *) (wpaRsnIE)); + } else if (csr_is_profile_rsn(pProfile)) { + /* Insert the RSN IE into the join request */ + ieLen = + csr_retrieve_rsn_ie(pMac, sessionId, pProfile, + pBssDescription, pIes, + (tCsrRSNIe *) (wpaRsnIE)); + } +#ifdef FEATURE_WLAN_WAPI + else if (csr_is_profile_wapi(pProfile)) { + /* Insert the WAPI IE into the join request */ + ieLen = + csr_retrieve_wapi_ie(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) { + sms_log(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 (csr_is_profile_wapi(pProfile)) { + /* Check whether we need to allocate more mem */ + if (ieLen > pSession->nWapiReqIeLength) { + if (pSession->pWapiReqIE + && pSession->nWapiReqIeLength) { + cdf_mem_free(pSession-> + pWapiReqIE); + } + pSession->pWapiReqIE = + cdf_mem_malloc(ieLen); + if (NULL == pSession->pWapiReqIE) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + } + pSession->nWapiReqIeLength = ieLen; + cdf_mem_copy(pSession->pWapiReqIE, wpaRsnIE, + ieLen); + csr_join_req->rsnIE.length = ieLen; + cdf_mem_copy(&csr_join_req->rsnIE.rsnIEdata, + wpaRsnIE, ieLen); + } else /* should be WPA/WPA2 otherwise */ +#endif /* FEATURE_WLAN_WAPI */ + { + /* Check whether we need to allocate more mem */ + if (ieLen > pSession->nWpaRsnReqIeLength) { + if (pSession->pWpaRsnReqIE + && pSession->nWpaRsnReqIeLength) { + cdf_mem_free(pSession-> + pWpaRsnReqIE); + } + pSession->pWpaRsnReqIE = + cdf_mem_malloc(ieLen); + if (NULL == pSession->pWpaRsnReqIE) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + } + pSession->nWpaRsnReqIeLength = ieLen; + cdf_mem_copy(pSession->pWpaRsnReqIE, wpaRsnIE, + ieLen); + csr_join_req->rsnIE.length = ieLen; + cdf_mem_copy(&csr_join_req->rsnIE.rsnIEdata, + wpaRsnIE, ieLen); + } + } else { + /* free whatever old info */ + pSession->nWpaRsnReqIeLength = 0; + if (pSession->pWpaRsnReqIE) { + cdf_mem_free(pSession->pWpaRsnReqIE); + pSession->pWpaRsnReqIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + pSession->nWapiReqIeLength = 0; + if (pSession->pWapiReqIE) { + cdf_mem_free(pSession->pWapiReqIE); + pSession->pWapiReqIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ + csr_join_req->rsnIE.length = 0; + } +#ifdef FEATURE_WLAN_ESE + if (eWNI_SME_JOIN_REQ == messageType) + csr_join_req->cckmIE.length = 0; + else if (eWNI_SME_REASSOC_REQ == messageType) { + /* cckmIE */ + if (csr_is_profile_ese(pProfile)) { + /* Insert the CCKM IE into the join request */ +#ifdef FEATURE_WLAN_ESE_UPLOAD + ieLen = pSession->suppCckmIeInfo.cckmIeLen; + cdf_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) + */ + csr_join_req->cckmIE.length = ieLen; + cdf_mem_copy(&csr_join_req->cckmIE.cckmIEdata, + wpaRsnIE, ieLen); + } else + csr_join_req->cckmIE.length = 0; + } +#endif /* FEATURE_WLAN_ESE */ + /* addIEScan */ + if (pProfile->nAddIEScanLength && pProfile->pAddIEScan) { + ieLen = pProfile->nAddIEScanLength; + if (ieLen > pSession->nAddIEScanLength) { + if (pSession->pAddIEScan + && pSession->nAddIEScanLength) { + cdf_mem_free(pSession->pAddIEScan); + } + pSession->pAddIEScan = cdf_mem_malloc(ieLen); + if (NULL == pSession->pAddIEScan) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + } + pSession->nAddIEScanLength = ieLen; + cdf_mem_copy(pSession->pAddIEScan, pProfile->pAddIEScan, + ieLen); + csr_join_req->addIEScan.length = ieLen; + cdf_mem_copy(&csr_join_req->addIEScan.addIEdata, + pProfile->pAddIEScan, ieLen); + } else { + pSession->nAddIEScanLength = 0; + if (pSession->pAddIEScan) { + cdf_mem_free(pSession->pAddIEScan); + pSession->pAddIEScan = NULL; + } + csr_join_req->addIEScan.length = 0; + } + /* addIEAssoc */ + if (pProfile->nAddIEAssocLength && pProfile->pAddIEAssoc) { + ieLen = pProfile->nAddIEAssocLength; + if (ieLen > pSession->nAddIEAssocLength) { + if (pSession->pAddIEAssoc + && pSession->nAddIEAssocLength) { + cdf_mem_free(pSession->pAddIEAssoc); + } + pSession->pAddIEAssoc = cdf_mem_malloc(ieLen); + if (NULL == pSession->pAddIEAssoc) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + } + pSession->nAddIEAssocLength = ieLen; + cdf_mem_copy(pSession->pAddIEAssoc, + pProfile->pAddIEAssoc, ieLen); + csr_join_req->addIEAssoc.length = ieLen; + cdf_mem_copy(&csr_join_req->addIEAssoc.addIEdata, + pProfile->pAddIEAssoc, ieLen); + } else { + pSession->nAddIEAssocLength = 0; + if (pSession->pAddIEAssoc) { + cdf_mem_free(pSession->pAddIEAssoc); + pSession->pAddIEAssoc = NULL; + } + csr_join_req->addIEAssoc.length = 0; + } + + if (eWNI_SME_REASSOC_REQ == messageType) { + /* Unmask any AC in reassoc that is ACM-set */ + uapsd_mask = (uint8_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_qos_get_acm_mask(pMac, + pBssDescription, + pIes); +#endif /* WLAN_MDM_CODE_REDUCTION_OPT */ + else + uapsd_mask = 0; + } + } + + csr_join_req->UCEncryptionType = + csr_translate_encrypt_type_to_ed_type + (pProfile->negotiatedUCEncryptionType); + + csr_join_req->MCEncryptionType = + csr_translate_encrypt_type_to_ed_type + (pProfile->negotiatedMCEncryptionType); +#ifdef WLAN_FEATURE_11W + if (pProfile->MFPEnabled) + csr_join_req->MgmtEncryptionType = eSIR_ED_AES_128_CMAC; + else + csr_join_req->MgmtEncryptionType = eSIR_ED_NONE; +#endif +#ifdef FEATURE_WLAN_ESE + ese_config = pMac->roam.configParam.isEseIniFeatureEnabled; +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + pProfile->MDID.mdiePresent = pBssDescription->mdiePresent; + if (csr_is_profile11r(pProfile) +#ifdef FEATURE_WLAN_ESE + && + !((pProfile->negotiatedAuthType == + eCSR_AUTH_TYPE_OPEN_SYSTEM) && (pIes->ESEVersion.present) + && (ese_config)) +#endif + ) + csr_join_req->is11Rconnection = true; + else + csr_join_req->is11Rconnection = false; +#endif +#ifdef FEATURE_WLAN_ESE + if (true == ese_config) + csr_join_req->isESEFeatureIniEnabled = true; + else + csr_join_req->isESEFeatureIniEnabled = false; + + /* A profile can not be both ESE and 11R. But an 802.11R AP + * may be advertising support for ESE as well. So if we are + * associating Open or explicitly ESE then we will get ESE. + * If we are associating explictly 11R only then we will get + * 11R. + */ + if ((csr_is_profile_ese(pProfile) || + ((pIes->ESEVersion.present) && + (pProfile->negotiatedAuthType == + eCSR_AUTH_TYPE_OPEN_SYSTEM))) + && (ese_config)) + csr_join_req->isESEconnection = true; + else + csr_join_req->isESEconnection = false; + + if (eWNI_SME_JOIN_REQ == messageType) { + tESETspecInfo eseTspec; + /* + * ESE-Tspec IEs in the ASSOC request is presently not + * supported. so nullify the TSPEC parameters + */ + cdf_mem_set(&eseTspec, sizeof(tESETspecInfo), 0); + cdf_mem_copy(&csr_join_req->eseTspecInfo, + &eseTspec, sizeof(tESETspecInfo)); + } else if (eWNI_SME_REASSOC_REQ == messageType) { + if ((csr_is_profile_ese(pProfile) || + ((pIes->ESEVersion.present) + && (pProfile->negotiatedAuthType == + eCSR_AUTH_TYPE_OPEN_SYSTEM))) && + (ese_config)) { + tESETspecInfo eseTspec; + cdf_mem_set(&eseTspec, sizeof(tESETspecInfo), + 0); + eseTspec.numTspecs = + sme_qos_ese_retrieve_tspec_info(pMac, + sessionId, + (tTspecInfo *) &eseTspec. + tspec[0]); + csr_join_req->eseTspecInfo.numTspecs = + eseTspec.numTspecs; + if (eseTspec.numTspecs) { + cdf_mem_copy(&csr_join_req->eseTspecInfo + .tspec[0], + &eseTspec.tspec[0], + (eseTspec.numTspecs * + sizeof(tTspecInfo))); + } + } else { + tESETspecInfo eseTspec; + /** + * ESE-Tspec IEs in the ASSOC request is + * presently not supported. so nullify the TSPEC + * parameters + */ + cdf_mem_set(&eseTspec, sizeof(tESETspecInfo), + 0); + cdf_mem_copy(&csr_join_req->eseTspecInfo, + &eseTspec, + sizeof(tESETspecInfo)); + } + } +#endif /* FEATURE_WLAN_ESE */ +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + if (ese_config +#ifdef FEATURE_WLAN_LFR + || csr_roam_is_fast_roam_enabled(pMac, sessionId) +#endif + ) { + csr_join_req->isFastTransitionEnabled = true; + } else { + csr_join_req->isFastTransitionEnabled = false; + } +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) + csr_join_req->isFastRoamIniFeatureEnabled = true; + else + csr_join_req->isFastRoamIniFeatureEnabled = false; +#endif + + csr_join_req->txLdpcIniFeatureEnabled = + (uint8_t) pMac->roam.configParam.txLdpcEnable; + + if ((csr_is11h_supported(pMac)) + && (CDS_IS_CHANNEL_5GHZ(pBssDescription->channelId)) + && (pIes->Country.present) + && (!pMac->roam.configParam. + fSupplicantCountryCodeHasPriority)) { + csr_save_to_channel_power2_g_5_g(pMac, + pIes->Country.num_triplets * + sizeof(tSirMacChanInfo), + (tSirMacChanInfo *) + (&pIes->Country.triplets[0])); + csr_apply_power2_current(pMac); + } + cdf_mem_copy(&csr_join_req->htConfig, + &pSession->htConfig, sizeof(tSirHTConfig)); +#ifdef WLAN_FEATURE_11AC + csr_join_req->txBFIniFeatureEnabled = + (uint8_t) pMac->roam.configParam.txBFEnable; + + if (pMac->roam.configParam.txBFEnable) { + txBFCsnValue = + (uint8_t)pMac->roam.configParam.txBFCsnValue; + if (IS_BSS_VHT_CAPABLE(pIes->VHTCaps) && + pIes->VHTCaps.numSoundingDim) + txBFCsnValue = CDF_MIN(txBFCsnValue, + pIes->VHTCaps.numSoundingDim); + else if (IS_BSS_VHT_CAPABLE(pIes->vendor2_ie.VHTCaps) + && pIes->vendor2_ie.VHTCaps.numSoundingDim) + txBFCsnValue = CDF_MIN(txBFCsnValue, + pIes->vendor2_ie.VHTCaps.numSoundingDim); + } + csr_join_req->txBFCsnValue = txBFCsnValue; + + csr_join_req->txMuBformee = + (uint8_t) pMac->roam.configParam.txMuBformee; + + csr_join_req->enableVhtpAid = + (uint8_t) pMac->roam.configParam.enableVhtpAid; + + csr_join_req->enableVhtGid = + (uint8_t) pMac->roam.configParam.enableVhtGid; + +#endif + csr_join_req->enableAmpduPs = + (uint8_t) pMac->roam.configParam.enableAmpduPs; + + csr_join_req->enableHtSmps = + (uint8_t) pMac->roam.configParam.enableHtSmps; + + csr_join_req->htSmps = (uint8_t) pMac->roam.configParam.htSmps; + + csr_join_req->isAmsduSupportInAMPDU = + (uint8_t) pMac->roam.configParam.isAmsduSupportInAMPDU; + + if (pMac->roam.roamSession[sessionId].fWMMConnection) + csr_join_req->isWMEenabled = true; + else + csr_join_req->isWMEenabled = false; + + if (pMac->roam.roamSession[sessionId].fQOSConnection) + csr_join_req->isQosEnabled = true; + else + csr_join_req->isQosEnabled = false; + + if (pProfile->bOSENAssociation) + csr_join_req->isOSENConnection = true; + else + csr_join_req->isOSENConnection = false; + + 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 (csr_is11h_supported(pMac) && pAP_capabilityInfo->spectrumMgt + && eSIR_11A_NW_TYPE == pBssDescription->nwType) { + fTmp = (tAniBool) 1; + } else + fTmp = (tAniBool) 0; + + csr_join_req->spectrumMgtIndicator = fTmp; + csr_join_req->powerCap.minTxPower = MIN_TX_PWR_CAP; + /* + * 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 = csr_get_cfg_max_tx_power(pMac, + pBssDescription->channelId); + if (0 != pwrLimit) + csr_join_req->powerCap.maxTxPower = pwrLimit; + else + csr_join_req->powerCap.maxTxPower = MAX_TX_PWR_CAP; + + csr_add_supported_5Ghz_channels(pMac, csr_join_req); + + csr_join_req->uapsdPerAcBitmask = (uint8_t)pProfile->uapsd_mask; + /* Move the entire BssDescription into the join request. */ + cdf_mem_copy(&csr_join_req->bssDescription, pBssDescription, + pBssDescription->length + + sizeof(pBssDescription->length)); + + /* + * 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) + && CDS_IS_CHANNEL_5GHZ(pBssDescription-> + channelId)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("STA-conn on 5G isn't allowed")); + status = CDF_STATUS_E_FAILURE; + break; + } + if (!CDS_IS_CHANNEL_5GHZ(pBssDescription->channelId) && + (false == csr_is_conn_allow_2g_band(pMac, + pBssDescription->channelId))) { + status = CDF_STATUS_E_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 (!CDS_IS_CHANNEL_24GHZ(pBssDescription->channelId) && + (false == csr_is_conn_allow_5g_band(pMac, + pBssDescription->channelId))) { + status = CDF_STATUS_E_FAILURE; + break; + } + } + status = cds_send_mb_message_to_mac(csr_join_req); + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* + * cds_send_mb_message_to_mac would've released the mem + * allocated by csr_join_req. Let's make it defensive by + * assigning NULL to the pointer. + */ + csr_join_req = NULL; + break; + } else { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + if (eWNI_SME_JOIN_REQ == messageType) { + /* Notify QoS module that join happening */ + pSession->join_bssid_count++; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + "BSSID Count = %d", + pSession->join_bssid_count); + sme_qos_csr_event_ind(pMac, (uint8_t) sessionId, + SME_QOS_CSR_JOIN_REQ, NULL); + } else if (eWNI_SME_REASSOC_REQ == messageType) { + /* Notify QoS module that reassoc happening */ + sme_qos_csr_event_ind(pMac, (uint8_t) sessionId, + SME_QOS_CSR_REASSOC_REQ, + NULL); + } +#endif + } + } while (0); + + /* Clean up the memory in case of any failure */ + if (!CDF_IS_STATUS_SUCCESS(status) && (NULL != csr_join_req)) + cdf_mem_free(csr_join_req); + + return status; +} + +/* */ +CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, uint16_t reasonCode) +{ + tSirSmeDisassocReq *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) + return CDF_STATUS_E_FAILURE; + + pMsg = cdf_mem_malloc(sizeof(tSirSmeDisassocReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pMsg, sizeof(tSirSmeDisassocReq), 0); + pMsg->messageType = eWNI_SME_DISASSOC_REQ; + pMsg->length = sizeof(tSirSmeDisassocReq); + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; + if ((pSession->pCurRoamProfile != NULL) + && ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) + || (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))) { + cdf_mem_copy(&pMsg->bssId, + &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->peerMacAddr, + bssId, + sizeof(tSirMacAddr)); + } else { + cdf_mem_copy(&pMsg->bssId, + bssId, + sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->peerMacAddr, + bssId, + sizeof(tSirMacAddr)); + } + pMsg->reasonCode = reasonCode; + /* + * 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 + && csr_roam_is11r_assoc(pMac, sessionId) +#endif + ) { + /* Set DoNotSendOverTheAir flag to 1 only for handoff case */ + pMsg->doNotSendOverTheAir = CSR_DONT_SEND_DISASSOC_OVER_THE_AIR; + } + return cds_send_mb_message_to_mac(pMsg); +} + +CDF_STATUS csr_send_mb_tkip_counter_measures_req_msg(tpAniSirGlobal pMac, + uint32_t sessionId, bool bEnable, + tSirMacAddr bssId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeTkipCntrMeasReq *pMsg; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeTkipCntrMeasReq)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeTkipCntrMeasReq), 0); + pMsg->messageType = eWNI_SME_TKIP_CNTR_MEAS_REQ; + pMsg->length = sizeof(tSirSmeTkipCntrMeasReq); + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; + cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + pMsg->bEnable = bEnable; + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS +csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + CDF_MODULE_ID modId, tSirMacAddr bssId, + void *pUsrContext, void *pfnSapEventCallback, + uint8_t *pAssocStasBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeGetAssocSTAsReq *pMsg; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeGetAssocSTAsReq)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeGetAssocSTAsReq), 0); + pMsg->messageType = eWNI_SME_GET_ASSOC_STAS_REQ; + cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + pMsg->modId = modId; + cdf_mem_copy(pMsg->pUsrContext, + pUsrContext, sizeof(void *)); + cdf_mem_copy(pMsg->pSapEventCallback, + pfnSapEventCallback, sizeof(void *)); + cdf_mem_copy(pMsg->pAssocStasArray, + pAssocStasBuf, sizeof(void *)); + pMsg->length = sizeof(struct sSirSmeGetAssocSTAsReq); + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS +csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, void *pUsrContext, + void *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeGetWPSPBCSessionsReq *pMsg; + + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeGetWPSPBCSessionsReq)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeGetWPSPBCSessionsReq), 0); + pMsg->messageType = eWNI_SME_GET_WPSPBC_SESSION_REQ; + cdf_mem_copy(pMsg->pUsrContext, pUsrContext, sizeof(void *)); + cdf_mem_copy(pMsg->pSapEventCallback, pfnSapEventCallback, + sizeof(void *)); + cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->pRemoveMac, pRemoveMac.bytes, + CDF_MAC_ADDR_SIZE); + pMsg->length = sizeof(struct sSirSmeGetWPSPBCSessionsReq); + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_send_chng_mcc_beacon_interval(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tpSirChangeBIParams pMsg; + uint16_t len = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + /* NO need to update the Beacon Params if update beacon parameter flag is not set */ + if (!pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval) + return CDF_STATUS_SUCCESS; + + pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = + false; + + /* Create the message and send to lim */ + len = sizeof(tSirChangeBIParams); + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(pMsg, sizeof(tSirChangeBIParams), 0); + pMsg->messageType = eWNI_SME_CHNG_MCC_BEACON_INTERVAL; + pMsg->length = len; + + /* bssId */ + cdf_mem_copy((tSirMacAddr *) pMsg->bssId, + &pSession->selfMacAddr, sizeof(tSirMacAddr)); + sms_log(pMac, LOG1, + FL("CSR Attempting to change BI for Bssid= " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssId)); + pMsg->sessionId = sessionId; + sms_log(pMac, LOG1, FL(" session %d BeaconInterval %d"), + sessionId, + pMac->roam.roamSession[sessionId].bssParams. + beaconInterval); + pMsg->beaconInterval = + pMac->roam.roamSession[sessionId].bssParams.beaconInterval; + status = cds_send_mb_message_to_mac(pMsg); + } + return status; +} + +#ifdef QCA_HT_2040_COEX +CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, + ePhyChanBondState cbMode, bool obssEnabled) +{ + tpSirSetHT2040Mode pMsg; + uint16_t len = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + /* Create the message and send to lim */ + len = sizeof(tSirSetHT2040Mode); + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_set(pMsg, sizeof(tSirSetHT2040Mode), 0); + pMsg->messageType = eWNI_SME_SET_HT_2040_MODE; + pMsg->length = len; + + /* bssId */ + cdf_mem_copy((tSirMacAddr *) pMsg->bssId, + &pSession->selfMacAddr, sizeof(tSirMacAddr)); + sms_log(pMac, LOG1, + FL("CSR Attempting to set HT20/40 mode for Bssid= " + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssId)); + pMsg->sessionId = sessionId; + sms_log(pMac, LOG1, FL(" session %d HT20/40 mode %d"), + sessionId, cbMode); + pMsg->cbMode = cbMode; + pMsg->obssEnabled = obssEnabled; + status = cds_send_mb_message_to_mac(pMsg); + } + return status; +} +#endif + +CDF_STATUS csr_send_mb_deauth_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, uint16_t reasonCode) +{ + tSirSmeDeauthReq *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) + return CDF_STATUS_E_FAILURE; + + pMsg = cdf_mem_malloc(sizeof(tSirSmeDeauthReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pMsg, sizeof(tSirSmeDeauthReq), 0); + pMsg->messageType = eWNI_SME_DEAUTH_REQ; + pMsg->length = sizeof(tSirSmeDeauthReq); + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; + + if ((pSession->pCurRoamProfile != NULL) + && ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) + || (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))) { + cdf_mem_copy(&pMsg->bssId, + &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + } else { + cdf_mem_copy(&pMsg->bssId, + bssId, + sizeof(tSirMacAddr)); + } + + /* Set the peer MAC address before sending the message to LIM */ + cdf_mem_copy(&pMsg->peerMacAddr, + bssId, + sizeof(tSirMacAddr)); + pMsg->reasonCode = reasonCode; + + return cds_send_mb_message_to_mac(pMsg); +} + +CDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeDisassocInd pDisassocInd) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeDisassocCnf *pMsg; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeDisassocCnf)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeDisassocCnf), 0); + pMsg->messageType = eWNI_SME_DISASSOC_CNF; + pMsg->statusCode = eSIR_SME_SUCCESS; + pMsg->length = sizeof(tSirSmeDisassocCnf); + cdf_mem_copy(pMsg->peerMacAddr, pDisassocInd->peerMacAddr, + sizeof(pMsg->peerMacAddr)); + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pMsg); + break; + } + + cdf_mem_copy(pMsg->bssId, pDisassocInd->bssId, + sizeof(pMsg->peerMacAddr)); + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pMsg); + break; + } + + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeDeauthInd pDeauthInd) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeDeauthCnf *pMsg; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeDeauthCnf)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeDeauthCnf), 0); + pMsg->messageType = eWNI_SME_DEAUTH_CNF; + pMsg->statusCode = eSIR_SME_SUCCESS; + pMsg->length = sizeof(tSirSmeDeauthCnf); + cdf_mem_copy(pMsg->bssId, pDeauthInd->bssId, + sizeof(pMsg->bssId)); + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pMsg); + break; + } + cdf_mem_copy(pMsg->peerMacAddr, pDeauthInd->peerMacAddr, + sizeof(pMsg->peerMacAddr)); + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pMsg); + break; + } + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, + CDF_STATUS Halstatus) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeAssocCnf *pMsg; + + sms_log(pMac, LOG1, + FL("Posting eWNI_SME_ASSOC_CNF to LIM.HalStatus :%d"), + Halstatus); + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeAssocCnf)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, sizeof(tSirSmeAssocCnf), 0); + pMsg->messageType = eWNI_SME_ASSOC_CNF; + pMsg->length = sizeof(tSirSmeAssocCnf); + if (CDF_IS_STATUS_SUCCESS(Halstatus)) + pMsg->statusCode = eSIR_SME_SUCCESS; + else + pMsg->statusCode = eSIR_SME_ASSOC_REFUSED; + /* bssId */ + cdf_mem_copy(pMsg->bssId, pAssocInd->bssId, + sizeof(tSirMacAddr)); + /* peerMacAddr */ + cdf_mem_copy(pMsg->peerMacAddr, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + /* aid */ + pMsg->aid = pAssocInd->aid; + /* alternateBssId */ + cdf_mem_copy(pMsg->alternateBssId, pAssocInd->bssId, + sizeof(tSirMacAddr)); + /* alternateChannelId */ + pMsg->alternateChannelId = 11; + /* pMsg is freed by cds_send_mb_message_to_mac in anycase*/ + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeAssocInd pAssocInd, + CDF_STATUS Halstatus, + uint8_t sessionId) +{ + tSirMsgQ msgQ; + tSirSmeAssocIndToUpperLayerCnf *pMsg; + uint8_t *pBuf; + tSirResultCodes statusCode; + uint16_t wTmp; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeAssocIndToUpperLayerCnf)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, sizeof(tSirSmeAssocIndToUpperLayerCnf), 0); + + pMsg->messageType = eWNI_SME_UPPER_LAYER_ASSOC_CNF; + pMsg->length = sizeof(tSirSmeAssocIndToUpperLayerCnf); + + pMsg->sessionId = sessionId; + + pBuf = (uint8_t *) &pMsg->statusCode; + if (CDF_IS_STATUS_SUCCESS(Halstatus)) + statusCode = eSIR_SME_SUCCESS; + else + statusCode = eSIR_SME_ASSOC_REFUSED; + cdf_mem_copy(pBuf, &statusCode, sizeof(tSirResultCodes)); + pBuf += sizeof(tSirResultCodes); + /* bssId */ + cdf_mem_copy((tSirMacAddr *) pBuf, pAssocInd->bssId, + sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + /* peerMacAddr */ + cdf_mem_copy((tSirMacAddr *) pBuf, pAssocInd->peerMacAddr, + sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + /* StaId */ + wTmp = pAssocInd->staId; + cdf_mem_copy(pBuf, &wTmp, sizeof(uint16_t)); + pBuf += sizeof(uint16_t); + /* alternateBssId */ + cdf_mem_copy((tSirMacAddr *) pBuf, pAssocInd->bssId, + sizeof(tSirMacAddr)); + pBuf += sizeof(tSirMacAddr); + /* alternateChannelId */ + *pBuf = 11; + pBuf += sizeof(uint8_t); + /* Instead of copying roam Info, we just copy only WmmEnabled, RsnIE information */ + /* Wmm */ + *pBuf = pAssocInd->wmmEnabledSta; + pBuf += sizeof(uint8_t); + /* RSN IE */ + cdf_mem_copy((tSirRSNie *) pBuf, &pAssocInd->rsnIE, + sizeof(tSirRSNie)); + pBuf += sizeof(tSirRSNie); +#ifdef FEATURE_WLAN_WAPI + /* WAPI IE */ + cdf_mem_copy((tSirWAPIie *) pBuf, &pAssocInd->wapiIE, + sizeof(tSirWAPIie)); + pBuf += sizeof(tSirWAPIie); +#endif + /* Additional IE */ + cdf_mem_copy((void *)pBuf, &pAssocInd->addIE, + sizeof(tSirAddie)); + pBuf += sizeof(tSirAddie); + /* reassocReq */ + *pBuf = pAssocInd->reassocReq; + pBuf += sizeof(uint8_t); + /* timingMeasCap */ + *pBuf = pAssocInd->timingMeasCap; + pBuf += sizeof(uint8_t); + cdf_mem_copy((void *)pBuf, &pAssocInd->chan_info, + sizeof(tSirSmeChanInfo)); + msgQ.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF; + msgQ.bodyptr = pMsg; + msgQ.bodyval = 0; + sys_process_mmh_msg(pMac, &msgQ); + } while (0); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr peerMacAddr, uint8_t numKeys, + tAniEdType edType, bool fUnicast, + tAniKeyDirection aniKeyDirection, + uint8_t keyId, uint8_t keyLength, + uint8_t *pKey, uint8_t paeRole, + uint8_t *pKeyRsc) +{ + tSirSmeSetContextReq *pMsg; + uint16_t msgLen; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + sms_log(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(struct sSirSmeSetContextReq); + + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, msgLen, 0); + pMsg->messageType = eWNI_SME_SETCONTEXT_REQ; + pMsg->length = msgLen; + pMsg->sessionId = (uint8_t) sessionId; + pMsg->transactionId = 0; + cdf_mem_copy(pMsg->peerMacAddr, peerMacAddr, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->bssId, + pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + + /** + * 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 ? + */ + pMsg->keyMaterial.length = + sizeof(pMsg->keyMaterial.numKeys) + + (numKeys * sizeof(pMsg->keyMaterial.key)); + pMsg->keyMaterial.edType = edType; + pMsg->keyMaterial.numKeys = numKeys; + pMsg->keyMaterial.key[0].keyId = keyId; + pMsg->keyMaterial.key[0].unicast = fUnicast; + pMsg->keyMaterial.key[0].keyDirection = aniKeyDirection; + cdf_mem_copy(pMsg->keyMaterial.key[0].keyRsc, + pKeyRsc, CSR_MAX_RSC_LEN); + /* 0 is Supplicant */ + pMsg->keyMaterial.key[0].paeRole = paeRole; + pMsg->keyMaterial.key[0].keyLength = keyLength; + if (keyLength && pKey) { + cdf_mem_copy(pMsg->keyMaterial.key[0].key, + pKey, keyLength); + sms_log(pMac, LOG1, + FL("SME set keyIndx (%d) encType (%d) key"), + keyId, edType); + sir_dump_buf(pMac, SIR_SMS_MODULE_ID, LOG1, pKey, + keyLength); + } + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamBssType bssType, + tCsrRoamStartBssParams *pParam, + tSirBssDescription *pBssDesc) +{ + tSirSmeStartBssReq *pMsg; + uint16_t wTmp; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS; + pSession->joinFailStatusCode.reasonCode = 0; + pMsg = cdf_mem_malloc(sizeof(tSirSmeStartBssReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pMsg, sizeof(tSirSmeStartBssReq), 0); + pMsg->messageType = eWNI_SME_START_BSS_REQ; + pMsg->sessionId = sessionId; + pMsg->length = sizeof(tSirSmeStartBssReq); + pMsg->transactionId = 0; + cdf_mem_copy(pMsg->bssId, pParam->bssid.bytes, sizeof(tSirMacAddr)); + /* selfMacAddr */ + cdf_mem_copy(pMsg->selfMacAddr, + pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + /* beaconInterval */ + if (pBssDesc && pBssDesc->beaconInterval) + wTmp = pBssDesc->beaconInterval; + else if (pParam->beaconInterval) + wTmp = pParam->beaconInterval; + else + wTmp = WNI_CFG_BEACON_INTERVAL_STADEF; + + if (csr_isconcurrentsession_valid(pMac, sessionId, pParam->bssPersona) + == CDF_STATUS_SUCCESS) { + csr_validate_mcc_beacon_interval(pMac, + pParam->operationChn, + &wTmp, + sessionId, + pParam->bssPersona); + /* Update the beacon Interval */ + pParam->beaconInterval = wTmp; + } else { + sms_log(pMac, LOGE, + FL("****Start BSS failed persona already exists***")); + cdf_mem_free(pMsg); + return CDF_STATUS_E_FAILURE; + } + pMsg->beaconInterval = wTmp; + pMsg->dot11mode = + csr_translate_to_wni_cfg_dot11_mode(pMac, + pParam->uCfgDot11Mode); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + pMsg->cc_switch_mode = pMac->roam.configParam.cc_switch_mode; +#endif + pMsg->bssType = csr_translate_bsstype_to_mac_type(bssType); + cdf_mem_copy(&pMsg->ssId, &pParam->ssId, sizeof(pParam->ssId)); + pMsg->channelId = pParam->operationChn; + /* What should we really do for the cbmode. */ + pMsg->cbMode = (ePhyChanBondState) pParam->cbMode; + pMsg->vht_channel_width = pParam->ch_params.ch_width; + pMsg->center_freq_seg0 = pParam->ch_params.center_freq_seg0; + pMsg->center_freq_seg1 = pParam->ch_params.center_freq_seg1; + pMsg->sec_ch_offset = pParam->ch_params.sec_ch_offset; + pMsg->privacy = pParam->privacy; + pMsg->apUapsdEnable = pParam->ApUapsdEnable; + pMsg->ssidHidden = pParam->ssidHidden; + pMsg->fwdWPSPBCProbeReq = (uint8_t) pParam->fwdWPSPBCProbeReq; + pMsg->protEnabled = (uint8_t) pParam->protEnabled; + pMsg->obssProtEnabled = (uint8_t) pParam->obssProtEnabled; + /* set cfg related to protection */ + pMsg->ht_capab = pParam->ht_protection; + pMsg->authType = pParam->authType; + pMsg->dtimPeriod = pParam->dtimPeriod; + pMsg->wps_state = pParam->wps_state; + pMsg->isCoalesingInIBSSAllowed = pMac->isCoalesingInIBSSAllowed; + pMsg->bssPersona = pParam->bssPersona; + pMsg->txLdpcIniFeatureEnabled = pMac->roam.configParam.txLdpcEnable; +#ifdef WLAN_FEATURE_11W + pMsg->pmfCapable = pParam->mfpCapable; + pMsg->pmfRequired = pParam->mfpRequired; +#endif + + if (pParam->nRSNIELength > sizeof(pMsg->rsnIE.rsnIEdata)) { + cdf_mem_free(pMsg); + return CDF_STATUS_E_INVAL; + } + pMsg->rsnIE.length = pParam->nRSNIELength; + cdf_mem_copy(pMsg->rsnIE.rsnIEdata, + pParam->pRSNIE, + pParam->nRSNIELength); + pMsg->nwType = (tSirNwType)pParam->sirNwType; + cdf_mem_copy(&pMsg->operationalRateSet, + &pParam->operationalRateSet, + sizeof(tSirMacRateSet)); + cdf_mem_copy(&pMsg->extendedRateSet, + &pParam->extendedRateSet, + sizeof(tSirMacRateSet)); + cdf_mem_copy(&pMsg->htConfig, + &pSession->htConfig, + sizeof(tSirHTConfig)); + cdf_mem_copy(&pMsg->addIeParams, + &pParam->addIeParams, + sizeof(pParam->addIeParams)); + pMsg->obssEnabled = pMac->roam.configParam.obssEnabled; + pMsg->sap_dot11mc = pParam->sap_dot11mc; + + return cds_send_mb_message_to_mac(pMsg); +} + +CDF_STATUS csr_send_mb_stop_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tSirSmeStopBssReq *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + pMsg = cdf_mem_malloc(sizeof(tSirSmeStopBssReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, sizeof(tSirSmeStopBssReq), 0); + pMsg->messageType = eWNI_SME_STOP_BSS_REQ; + pMsg->sessionId = sessionId; + pMsg->length = sizeof(tSirSmeStopBssReq); + pMsg->transactionId = 0; + pMsg->reasonCode = 0; + /* + * if BSSType is WDS sta, use selfmacAddr as bssid, + * else use bssid in connectedProfile + */ + if (CSR_IS_CONN_WDS_STA(&pSession->connectedProfile)) + cdf_mem_copy(&pMsg->bssId, + &pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + else + cdf_mem_copy(&pMsg->bssId, + &pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + return cds_send_mb_message_to_mac(pMsg); +} + +CDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamModifyProfileFields *pModProfileFields, + uint32_t *pRoamId, bool fForce) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t roamId = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if ((csr_is_conn_state_connected(pMac, sessionId)) && + (fForce || (!cdf_mem_compare(&pModProfileFields, + &pSession->connectedProfile. + modifyProfileFields, + sizeof(tCsrRoamModifyProfileFields))))) { + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if (pRoamId) { + *pRoamId = roamId; + } + + status = + csr_roam_issue_reassoc(pMac, sessionId, NULL, + pModProfileFields, + eCsrSmeIssuedReassocToSameAP, + roamId, false); + } + return status; +} + +static CDF_STATUS csr_roam_session_opened(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo roamInfo; + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + status = csr_roam_call_callback(pMac, sessionId, &roamInfo, 0, + eCSR_ROAM_SESSION_OPENED, + eCSR_ROAM_RESULT_NONE); + return status; +} + +CDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg) +{ + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + struct add_sta_self_params *rsp; + struct send_extcap_ie *msg; + CDF_STATUS status; + + if (pMsg == NULL) { + sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (!pEntry) { + sms_log(pMac, LOGE, "in %s NO commands are ACTIVE ...", + __func__); + return CDF_STATUS_E_FAILURE; + } + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandAddStaSession != pCommand->command) { + sms_log(pMac, LOGE, "in %s Cmd not in active list ...", + __func__); + return CDF_STATUS_E_FAILURE; + } + rsp = (struct add_sta_self_params *) pMsg; + sms_log(pMac, LOG1, "Add Sta self rsp status = %d", rsp->status); + + if (CDF_STATUS_SUCCESS == rsp->status && + (WMI_VDEV_TYPE_STA == rsp->type || + (WMI_VDEV_TYPE_AP == rsp->type && + WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == rsp->sub_type))) { + sms_log(pMac, LOG1, FL("send SET IE msg to PE")); + msg = cdf_mem_malloc(sizeof(*msg)); + if (NULL == msg) { + sms_log(pMac, LOGE, FL("Memory allocation failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set(msg, sizeof(*msg), 0); + msg->msg_type = eWNI_SME_SET_IE_REQ; + msg->session_id = rsp->session_id; + msg->length = sizeof(*msg); + status = cds_send_mb_message_to_mac(msg); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGE, + FL("Failed to send down the set IE req ")); + } + + csr_roam_session_opened(pMac, pCommand->sessionId); + /* Remove this command out of the active list */ + if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + /* Now put this command back on the avilable command list */ + csr_release_command(pMac, pCommand); + } + sme_process_pending_queue(pMac); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_issue_add_sta_for_session_req(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr sessionMacAddr, + uint32_t type, uint32_t subType) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + status = CDF_STATUS_E_RESOURCES; + } else { + pCommand->command = eSmeCommandAddStaSession; + pCommand->sessionId = (uint8_t) sessionId; + cdf_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 = csr_queue_sme_command(pMac, pCommand, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* Should be panic?? */ + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + } + } + return status; +} + +CDF_STATUS csr_process_add_sta_session_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + tAddStaForSessionCmd *pAddStaReq = + &pCommand->u.addStaSessionCmd; + uint8_t sessionId = pCommand->sessionId; + struct add_sta_self_params *add_sta_self_req; + CDF_STATUS status = CDF_STATUS_E_NOMEM; + tSirMsgQ msg; + + add_sta_self_req = cdf_mem_malloc(sizeof(struct add_sta_self_params)); + if (NULL == add_sta_self_req) { + lim_log(pMac, LOGP, + FL + ("Unable to allocate memory for tAddSelfStaParams")); + return status; + } + + cdf_mem_copy(add_sta_self_req->self_mac_addr, pAddStaReq->selfMacAddr, + sizeof(tSirMacAddr)); + add_sta_self_req->curr_device_mode = pAddStaReq->currDeviceMode; + add_sta_self_req->session_id = sessionId; + add_sta_self_req->type = pAddStaReq->type; + add_sta_self_req->sub_type = pAddStaReq->subType; + + msg.type = WMA_ADD_STA_SELF_REQ; + msg.reserved = 0; + msg.bodyptr = add_sta_self_req; + msg.bodyval = 0; + + lim_log(pMac, LOG1, + FL + ("Send WMA_ADD_STA_SELF_REQ for selfMac=" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(add_sta_self_req->self_mac_addr)); + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type)); + status = wma_post_ctrl_msg(pMac, &msg); + + if (status != CDF_STATUS_SUCCESS) { + lim_log(pMac, LOGP, FL("wma_post_ctrl_msg failed")); + cdf_mem_free(add_sta_self_req); + add_sta_self_req = NULL; + } + return status; +} + +CDF_STATUS csr_roam_open_session(tpAniSirGlobal pMac, + csr_roam_completeCallback callback, + void *pContext, + uint8_t *pSelfMacAddr, uint8_t *pbSessionId, + uint32_t type, uint32_t subType) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t i, value = 0; + union { + uint16_t 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) { + sms_log(pMac, LOGE, + FL + ("Session does not exist for interface %d"), + i); + break; + } + status = CDF_STATUS_SUCCESS; + pSession->sessionActive = true; + pSession->sessionId = (uint8_t) i; + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Initialize FT related data structures only in STA mode */ + sme_ft_open(pMac, pSession->sessionId); +#endif + + pSession->callback = callback; + pSession->pContext = pContext; + cdf_mem_copy(&pSession->selfMacAddr, pSelfMacAddr, + sizeof(struct cdf_mac_addr)); + *pbSessionId = (uint8_t) i; + status = + cdf_mc_timer_init(&pSession->hTimerRoaming, + CDF_TIMER_TYPE_SW, + csr_roam_roaming_timer_handler, + &pSession->roamingTimerInfo); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("cannot allocate memory for Roaming timer")); + break; + } + /* get the HT capability info */ + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &value) + != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_CDF, + CDF_TRACE_LEVEL_ERROR, + "%s: could not get HT capability info", + __func__); + break; + } +#ifdef FEATURE_WLAN_BTAMP_UT_RF + status = cdf_mc_timer_init(&pSession->hTimerJoinRetry, + CDF_TIMER_TYPE_SW, + csr_roam_join_retry_timer_handler, + &pSession-> + joinRetryTimerInfo); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("cannot allocate memory for join retry timer")); + break; + } +#endif + 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 = true; + status = + csr_issue_add_sta_for_session_req(pMac, i, pSelfMacAddr, + type, subType); + break; + } + } + if (pMac->sme.max_intf_count == i) { + /* No session is available */ + sms_log(pMac, LOGE, + "%s: Reached max interfaces: %d! Session creation will fail", + __func__, pMac->sme.max_intf_count); + status = CDF_STATUS_E_RESOURCES; + } + return status; +} + +CDF_STATUS csr_process_del_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + struct del_sta_self_params *rsp; + uint8_t sessionId; + + if (pMsg == NULL) { + sms_log(pMac, LOGE, FL("msg ptr is NULL")); + return status; + } + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (!pEntry) { + sms_log(pMac, LOGE, FL("NO commands are ACTIVE ...")); + return status; + } + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sessionId = pCommand->sessionId; + if (eSmeCommandDelStaSession != pCommand->command) { + sms_log(pMac, LOGE, FL("NO Del sta session command ACTIVE")); + return status; + } + rsp = (struct del_sta_self_params *) pMsg; + sms_log(pMac, LOG1, FL("Del Sta rsp status = %d"), rsp->status); + /* This session is done. */ + csr_cleanup_session(pMac, sessionId); + if (pCommand->u.delStaSessionCmd.callback) { + status = sme_release_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOG1, FL("Failed to Release Lock")); + else { + pCommand->u.delStaSessionCmd. + callback(pCommand->u.delStaSessionCmd.pContext); + status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("Failed to get Lock")); + return status; + } + } + } + /* Remove this command out of the active list */ + if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList, pEntry, + LL_ACCESS_LOCK)) { + /* Now put this command back on the avilable command list */ + csr_release_command(pMac, pCommand); + } + sme_process_pending_queue(pMac); + status = CDF_STATUS_SUCCESS; + return status; +} + + +CDF_STATUS csr_issue_del_sta_for_session_req(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr sessionMacAddr, + csr_roamSessionCloseCallback callback, + void *pContext) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *pCommand; + pCommand = csr_get_command_buffer(pMac); + if (NULL == pCommand) { + status = CDF_STATUS_E_RESOURCES; + } else { + pCommand->command = eSmeCommandDelStaSession; + pCommand->sessionId = (uint8_t) sessionId; + pCommand->u.delStaSessionCmd.callback = callback; + pCommand->u.delStaSessionCmd.pContext = pContext; + cdf_mem_copy(pCommand->u.delStaSessionCmd.selfMacAddr, + sessionMacAddr, sizeof(tSirMacAddr)); + status = csr_queue_sme_command(pMac, pCommand, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* Should be panic?? */ + sms_log(pMac, LOGE, + FL(" fail to send message status = %d"), status); + } + } + return status; +} + +CDF_STATUS csr_process_del_sta_session_command(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + struct del_sta_self_params *del_sta_self_req; + tSirMsgQ msg; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + del_sta_self_req = cdf_mem_malloc(sizeof(struct del_sta_self_params)); + if (NULL == del_sta_self_req) { + lim_log(pMac, LOGP, + FL(" mem alloc failed for tDelStaSelfParams")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(del_sta_self_req->self_mac_addr, + pCommand->u.delStaSessionCmd.selfMacAddr, + sizeof(tSirMacAddr)); + + del_sta_self_req->session_id = pCommand->sessionId; + msg.type = WMA_DEL_STA_SELF_REQ; + msg.reserved = 0; + msg.bodyptr = del_sta_self_req; + msg.bodyval = 0; + + sms_log(pMac, LOG1, + FL("sending WMA_DEL_STA_SELF_REQ")); + MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type)); + status = wma_post_ctrl_msg(pMac, &msg); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGP, FL("wma_post_ctrl_msg failed")); + cdf_mem_free(del_sta_self_req); + } + return status; +} + +static void purge_csr_session_cmd_list(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tDblLinkList *pList = &pMac->roam.roamCmdPendingList; + tListElem *pEntry, *pNext; + tSmeCmd *pCommand; + tDblLinkList localList; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return; + } + csr_ll_lock(pList); + pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK); + while (pEntry != NULL) { + pNext = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (pCommand->sessionId == sessionId) { + if (csr_ll_remove_entry(pList, pEntry, LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntry, + LL_ACCESS_NOLOCK); + } + } + pEntry = pNext; + } + csr_ll_unlock(pList); + + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + csr_abort_command(pMac, pCommand, true); + } + csr_ll_close(&localList); +} + +void csr_cleanup_session(tpAniSirGlobal pMac, uint32_t sessionId) +{ + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + csr_roam_stop(pMac, sessionId); + + /* Clean up FT related data structures */ +#if defined WLAN_FEATURE_VOWIFI_11R + sme_ft_close(pMac, sessionId); +#endif + csr_free_connect_bss_desc(pMac, sessionId); + csr_roam_free_connect_profile(pMac, &pSession->connectedProfile); + csr_roam_free_connected_info(pMac, &pSession->connectedInfo); + cdf_mc_timer_destroy(&pSession->hTimerRoaming); +#ifdef FEATURE_WLAN_BTAMP_UT_RF + cdf_mc_timer_destroy(&pSession->hTimerJoinRetry); +#endif + purge_sme_session_cmd_list(pMac, sessionId, + &pMac->sme.smeCmdPendingList); + purge_sme_session_cmd_list(pMac, sessionId, + &pMac->sme. + smeScanCmdPendingList); + + purge_csr_session_cmd_list(pMac, sessionId); + csr_init_session(pMac, sessionId); + } +} + +CDF_STATUS csr_roam_close_session(tpAniSirGlobal pMac, uint32_t sessionId, + bool fSync, + csr_roamSessionCloseCallback callback, + void *pContext) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (fSync) { + csr_cleanup_session(pMac, sessionId); + } else { + purge_sme_session_cmd_list(pMac, sessionId, + &pMac->sme.smeCmdPendingList); + purge_sme_session_cmd_list(pMac, sessionId, + &pMac->sme.smeScanCmdPendingList); + + purge_csr_session_cmd_list(pMac, sessionId); + status = csr_issue_del_sta_for_session_req(pMac, + sessionId, + pSession->selfMacAddr.bytes, + callback, pContext); + } + } else { + status = CDF_STATUS_E_INVAL; + } + return status; +} + +static void csr_init_session(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } + + pSession->sessionActive = false; + pSession->sessionId = CSR_SESSION_ID_INVALID; + pSession->callback = NULL; + pSession->pContext = NULL; + pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + csr_free_roam_profile(pMac, sessionId); + csr_roam_free_connect_profile(pMac, &pSession->connectedProfile); + csr_roam_free_connected_info(pMac, &pSession->connectedInfo); + csr_free_connect_bss_desc(pMac, sessionId); + csr_scan_enable(pMac); + cdf_mem_set(&pSession->selfMacAddr, sizeof(struct cdf_mac_addr), 0); + if (pSession->pWpaRsnReqIE) { + cdf_mem_free(pSession->pWpaRsnReqIE); + pSession->pWpaRsnReqIE = NULL; + } + pSession->nWpaRsnReqIeLength = 0; + if (pSession->pWpaRsnRspIE) { + cdf_mem_free(pSession->pWpaRsnRspIE); + pSession->pWpaRsnRspIE = NULL; + } + pSession->nWpaRsnRspIeLength = 0; +#ifdef FEATURE_WLAN_WAPI + if (pSession->pWapiReqIE) { + cdf_mem_free(pSession->pWapiReqIE); + pSession->pWapiReqIE = NULL; + } + pSession->nWapiReqIeLength = 0; + if (pSession->pWapiRspIE) { + cdf_mem_free(pSession->pWapiRspIE); + pSession->pWapiRspIE = NULL; + } + pSession->nWapiRspIeLength = 0; +#endif /* FEATURE_WLAN_WAPI */ + if (pSession->pAddIEScan) { + cdf_mem_free(pSession->pAddIEScan); + pSession->pAddIEScan = NULL; + } + pSession->nAddIEScanLength = 0; + if (pSession->pAddIEAssoc) { + cdf_mem_free(pSession->pAddIEAssoc); + pSession->pAddIEAssoc = NULL; + } + pSession->nAddIEAssocLength = 0; +} + +CDF_STATUS csr_roam_get_session_id_from_bssid(tpAniSirGlobal pMac, + struct cdf_mac_addr *bssid, + uint32_t *pSessionId) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint32_t i; + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i)) { + if (cdf_is_macaddr_equal(bssid, + &pMac->roam.roamSession[i].connectedProfile. + bssid)) { + /* Found it */ + status = CDF_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 uint32_t csr_find_ibss_session(tpAniSirGlobal pMac) +{ + uint32_t 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 + && + (csr_is_bss_type_ibss + (pSession->connectedProfile.BSSType))) { + /* Found it */ + nRet = i; + break; + } + } + } + return nRet; +} + +static void csr_roam_link_up(tpAniSirGlobal pMac, struct cdf_mac_addr bssid) +{ + /* Update the current BSS info in ho control block based on connected + profile info from pmac global structure */ + + sms_log(pMac, LOGW, + " csr_roam_link_up: WLAN link UP with AP= " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(bssid.bytes)); + /* 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 + { + uint32_t sessionId = 0; + /* Indicate the neighbor roal algorithm about the connect indication */ + csr_roam_get_session_id_from_bssid(pMac, &bssid, + &sessionId); + csr_neighbor_roam_indicate_connect(pMac, sessionId, + CDF_STATUS_SUCCESS); + } +#endif +} + +static void csr_roam_link_down(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(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; + } + /* + * Incase of station mode, immediately stop data transmission whenever + * link down is detected. + */ + if (csr_roam_is_sta_mode(pMac, sessionId) + && !CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId) +#ifdef WLAN_FEATURE_VOWIFI_11R + && !csr_roam_is11r_assoc(pMac, sessionId) +#endif + ) { + sms_log(pMac, LOG1, FL("Inform Link lost for session %d"), + sessionId); + csr_roam_call_callback(pMac, sessionId, NULL, 0, + eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_LOSTLINK); + } + /* deregister the clients requesting stats from PE/TL & also stop the corresponding timers */ + csr_roam_dereg_statistics_req(pMac); + pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; +#if defined WLAN_FEATURE_NEIGHBOR_ROAMING + /* Indicate the neighbor roal algorithm about the disconnect indication */ + csr_neighbor_roam_indicate_disconnect(pMac, sessionId); +#endif + + /* Remove this code once SLM_Sessionization is supported */ + /* BMPS_WORKAROUND_NOT_NEEDED */ + if (!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && + csr_is_infra_ap_started(pMac) && + pMac->roam.configParam.doBMPSWorkaround) { + pMac->roam.configParam.doBMPSWorkaround = 0; + } + +} + +void csr_roam_tl_stats_timer_handler(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pv); + CDF_STATUS status; + pMac->roam.tlStatsReqInfo.timerRunning = false; + + sms_log(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 = + cdf_mc_timer_start(&pMac->roam.tlStatsReqInfo. + hTlStatsTimer, + pMac->roam.tlStatsReqInfo. + periodicity); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_tl_stats_timer_handler:cannot start TlStatsTimer timer")); + return; + } + pMac->roam.tlStatsReqInfo.timerRunning = true; + } + } +} + +void csr_roam_pe_stats_timer_handler(void *pv) +{ + tCsrPeStatsReqInfo *pPeStatsReqListEntry = (tCsrPeStatsReqInfo *) pv; + CDF_STATUS status; + tpAniSirGlobal pMac = pPeStatsReqListEntry->pMac; + CDF_STATUS cdf_status; + pPeStatsReqListEntry->timerRunning = false; + if (pPeStatsReqListEntry->timerStopFailed == true) { + /* If we entered here, meaning the timer could not be successfully */ + /* stopped in csr_roam_remove_entry_from_pe_stats_req_list(). So do it here. */ + + /* Destroy the timer */ + cdf_status = + cdf_mc_timer_destroy(&pPeStatsReqListEntry->hPeStatsTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_pe_stats_timer_handler:failed to destroy hPeStatsTimer timer")); + } + /* Free the entry */ + cdf_mem_free(pPeStatsReqListEntry); + pPeStatsReqListEntry = NULL; + } else { + if (!pPeStatsReqListEntry->rspPending) { + status = + csr_send_mb_stats_req_msg(pMac, + pPeStatsReqListEntry-> + statsMask & ~(1 << + eCsrGlobalClassDStats), + pPeStatsReqListEntry->staId, + pPeStatsReqListEntry-> + sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_pe_stats_timer_handler:failed to send down stats req to PE")); + } else { + pPeStatsReqListEntry->rspPending = true; + } + } + /* send down a req */ + if (pPeStatsReqListEntry->periodicity && + (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&pPeStatsReqListEntry-> + hPeStatsTimer))) { + if (pPeStatsReqListEntry->periodicity < + pMac->roam.configParam. + statsReqPeriodicityInPS) { + pPeStatsReqListEntry->periodicity = + pMac->roam.configParam. + statsReqPeriodicityInPS; + } + /* start timer */ + cdf_status = + cdf_mc_timer_start(&pPeStatsReqListEntry-> + hPeStatsTimer, + pPeStatsReqListEntry-> + periodicity); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_pe_stats_timer_handler:cannot start hPeStatsTimer timer")); + return; + } + pPeStatsReqListEntry->timerRunning = true; + + } + + } +} + +void csr_roam_stats_client_timer_handler(void *pv) +{ + tCsrStatsClientReqInfo *pStaEntry = (tCsrStatsClientReqInfo *) pv; + if (CDF_TIMER_STATE_STOPPED == + cdf_mc_timer_get_current_state(&pStaEntry->timer)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("roam stats client timer is stopped")); + } +} + +CDF_STATUS csr_send_mb_stats_req_msg(tpAniSirGlobal pMac, uint32_t statsMask, + uint8_t staId, uint8_t sessionId) +{ + tAniGetPEStatsReq *pMsg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + pMsg = cdf_mem_malloc(sizeof(tAniGetPEStatsReq)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, FL("Failed to allocate mem for stats req ")); + return CDF_STATUS_E_NOMEM; + } + /* need to initiate a stats request to PE */ + pMsg->msgType = eWNI_SME_GET_STATISTICS_REQ; + pMsg->msgLen = (uint16_t) sizeof(tAniGetPEStatsReq); + pMsg->staId = staId; + pMsg->statsMask = statsMask; + pMsg->sessionId = sessionId; + status = cds_send_mb_message_to_mac(pMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("Failed to send down the stats req ")); + } + return status; +} + +/** + * csr_update_stats() - updates correct stats struct in mac_ctx + * @mac: mac global context + * @stats_type: stats type + * @sme_stats_rsp: stats rsp msg packet + * @stats: input stats data buffer to fill in mac_ctx struct + * @length: out param - stats length + * + * This function fills corresponding stats struct in mac_cts based on stats type + * passed + * + * Return: void + */ +static void +csr_update_stats(tpAniSirGlobal mac, uint8_t stats_type, + tAniGetPEStatsRsp *sme_stats_rsp, + uint8_t **stats, uint32_t *length) +{ + switch (stats_type) { + case eCsrSummaryStats: + sms_log(mac, LOG2, FL("summary stats")); + cdf_mem_copy((uint8_t *) &mac->roam.summaryStatsInfo, *stats, + sizeof(tCsrSummaryStatsInfo)); + *stats += sizeof(tCsrSummaryStatsInfo); + *length -= sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + sms_log(mac, LOG2, FL("ClassA stats")); + cdf_mem_copy((uint8_t *) &mac->roam.classAStatsInfo, *stats, + sizeof(tCsrGlobalClassAStatsInfo)); + *stats += sizeof(tCsrGlobalClassAStatsInfo); + *length -= sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + sms_log(mac, LOG2, FL("ClassB stats")); + cdf_mem_copy((uint8_t *) &mac->roam.classBStatsInfo, *stats, + sizeof(tCsrGlobalClassBStatsInfo)); + *stats += sizeof(tCsrGlobalClassBStatsInfo); + *length -= sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + sms_log(mac, LOG2, FL("ClassC stats")); + cdf_mem_copy((uint8_t *) &mac->roam.classCStatsInfo, *stats, + sizeof(tCsrGlobalClassCStatsInfo)); + *stats += sizeof(tCsrGlobalClassCStatsInfo); + *length -= sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrPerStaStats: + sms_log(mac, LOG2, FL("PerSta stats")); + if (CSR_MAX_STA > sme_stats_rsp->staId) { + cdf_mem_copy( + &mac->roam.perStaStatsInfo[sme_stats_rsp->staId], + *stats, sizeof(tCsrPerStaStatsInfo)); + } else { + sms_log(mac, LOGE, FL("out bound staId:%d. failed to copy PerSta stats"), + sme_stats_rsp->staId); + CDF_ASSERT(0); + } + *stats += sizeof(tCsrPerStaStatsInfo); + *length -= sizeof(tCsrPerStaStatsInfo); + break; + default: + sms_log(mac, LOGW, FL("unknown stats type")); + break; + } +} + +/** + * csr_roam_stats_rsp_processor() - processes stats rsp msg + * @pMac mac global context + * @pSirMsg: incoming message + * + * Return: void + */ +void csr_roam_stats_rsp_processor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) +{ + tAniGetPEStatsRsp *pSmeStatsRsp; + tListElem *pEntry = NULL; + tCsrStatsClientReqInfo *pTempStaEntry = NULL; + tCsrPeStatsReqInfo *pPeStaEntry = NULL; + uint32_t tempMask = 0; + uint8_t counter = 0; + uint8_t *pStats = NULL; + uint32_t length = 0; + void *p_cds_gctx; + int8_t rssi = 0, snr = 0; + uint32_t *pRssi = NULL, *pSnr = NULL; + uint32_t linkCapacity; + pSmeStatsRsp = (tAniGetPEStatsRsp *) pSirMsg; + + if (pSmeStatsRsp->rc) { + sms_log(pMac, LOGW, FL("stats rsp from PE shows failure")); + goto post_update; + } + tempMask = pSmeStatsRsp->statsMask; + pStats = ((uint8_t *) &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 strucutres in PMAC */ + while (tempMask) { + if (tempMask & 1) { + csr_update_stats(pMac, counter, pSmeStatsRsp, + &pStats, &length); + } + tempMask >>= 1; + counter++; + } + p_cds_gctx = cds_get_global_context(); + if (length != 0) { + pRssi = (uint32_t *) pStats; + rssi = (int8_t) *pRssi; + pStats += sizeof(uint32_t); + length -= sizeof(uint32_t); + } else { + /* If riva is not sending rssi, continue to use the hack */ + rssi = RSSI_HACK_BMPS; + } + + if (length != 0) { + linkCapacity = *(uint32_t *) pStats; + pStats += sizeof(uint32_t); + length -= sizeof(uint32_t); + } else { + linkCapacity = 0; + } + + if (length != 0) { + pSnr = (uint32_t *) pStats; + snr = (int8_t) *pSnr; + } else { + snr = SNR_HACK_BMPS; + } + +post_update: + /* make sure to update the pe stats req list */ + pEntry = csr_roam_find_in_pe_stats_req_list(pMac, pSmeStatsRsp->statsMask); + if (pEntry) { + pPeStaEntry = GET_BASE_ADDR(pEntry, tCsrPeStatsReqInfo, link); + pPeStaEntry->rspPending = false; + + } + /* check the one timer cases */ + pEntry = csr_roam_check_client_req_list(pMac, pSmeStatsRsp->statsMask); + if (pEntry) { + pTempStaEntry = + GET_BASE_ADDR(pEntry, tCsrStatsClientReqInfo, link); + if (pTempStaEntry->timerExpired) { + /* send up the stats report */ + csr_roam_report_statistics(pMac, pTempStaEntry->statsMask, + pTempStaEntry->callback, + pTempStaEntry->staId, + pTempStaEntry->pContext); + /* also remove from the client list */ + csr_roam_remove_stat_list_entry(pMac, pEntry); + pTempStaEntry = NULL; + } + } +} + +tListElem *csr_roam_find_in_pe_stats_req_list(tpAniSirGlobal pMac, uint32_t statsMask) +{ + tListElem *pEntry = NULL; + tCsrPeStatsReqInfo *pTempStaEntry = NULL; + pEntry = csr_ll_peek_head(&pMac->roam.peStatsReqList, LL_ACCESS_LOCK); + if (!pEntry) { + /* list empty */ + sms_log(pMac, LOG2, + "csr_roam_find_in_pe_stats_req_list: List empty, no request to PE"); + return NULL; + } + while (pEntry) { + pTempStaEntry = GET_BASE_ADDR(pEntry, tCsrPeStatsReqInfo, link); + if (pTempStaEntry->statsMask == statsMask) { + sms_log(pMac, LOG3, + "csr_roam_find_in_pe_stats_req_list: match found"); + break; + } + pEntry = + csr_ll_next(&pMac->roam.peStatsReqList, pEntry, + LL_ACCESS_NOLOCK); + } + return pEntry; +} + +tListElem *csr_roam_checkn_update_client_req_list(tpAniSirGlobal pMac, + tCsrStatsClientReqInfo *pStaEntry, + bool update) +{ + tListElem *pEntry; + tCsrStatsClientReqInfo *pTempStaEntry; + pEntry = csr_ll_peek_head(&pMac->roam.statsClientReqList, LL_ACCESS_LOCK); + if (!pEntry) { + /* list empty */ + sms_log(pMac, LOG2, + "csr_roam_checkn_update_client_req_list: 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)) { + sms_log(pMac, LOG3, + "csr_roam_checkn_update_client_req_list: match found"); + if (update) { + pTempStaEntry->periodicity = + pStaEntry->periodicity; + pTempStaEntry->callback = pStaEntry->callback; + pTempStaEntry->pContext = pStaEntry->pContext; + } + break; + } + pEntry = + csr_ll_next(&pMac->roam.statsClientReqList, pEntry, + LL_ACCESS_NOLOCK); + } + return pEntry; +} + +tListElem *csr_roam_check_client_req_list(tpAniSirGlobal pMac, uint32_t statsMask) +{ + tListElem *pEntry; + tCsrStatsClientReqInfo *pTempStaEntry; + pEntry = csr_ll_peek_head(&pMac->roam.statsClientReqList, LL_ACCESS_LOCK); + if (!pEntry) { + /* list empty */ + sms_log(pMac, LOG2, + "csr_roam_check_client_req_list: 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) { + sms_log(pMac, LOG3, + "csr_roam_check_client_req_list: match found"); + break; + } + pEntry = + csr_ll_next(&pMac->roam.statsClientReqList, pEntry, + LL_ACCESS_NOLOCK); + } + return pEntry; +} + +void csr_roam_vcc_trigger(tpAniSirGlobal pMac) +{ + eCsrRoamLinkQualityInd newVccLinkQuality; + uint32_t ul_mac_loss = 0; + uint32_t 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) { + CDF_ASSERT(ul_mac_loss_trigger_threshold != 0); + return; + } + sms_log(pMac, LOGW, "csr_roam_vcc_trigger: UL_MAC_LOSS_THRESHOLD is %d", + ul_mac_loss_trigger_threshold); + if (ul_mac_loss_trigger_threshold < ul_mac_loss) { + sms_log(pMac, LOGW, "csr_roam_vcc_trigger: link quality is POOR "); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; + } else { + sms_log(pMac, LOGW, "csr_roam_vcc_trigger: link quality is GOOD"); + newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND; + } + sms_log(pMac, LOGW, + "csr_roam_vcc_trigger: link qual : *** UL_MAC_LOSS %d *** ", + ul_mac_loss); + if (newVccLinkQuality != pMac->roam.vccLinkQuality) { + sms_log(pMac, LOGW, + "csr_roam_vcc_trigger: link quality changed: trigger necessary"); + if (NULL != pMac->roam.linkQualityIndInfo.callback) { + sms_log(pMac, LOGW, + "csr_roam_vcc_trigger: 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; + +} + +tCsrStatsClientReqInfo *csr_roam_insert_entry_into_list(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 == csr_roam_checkn_update_client_req_list(pMac, pStaEntry, true)) { + + pNewStaEntry = cdf_mem_malloc(sizeof(tCsrStatsClientReqInfo)); + if (NULL == pNewStaEntry) { + sms_log(pMac, LOGW, + "csr_roam_insert_entry_into_list: 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; + + csr_ll_insert_tail(pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK); + } + return pNewStaEntry; +} + +tCsrPeStatsReqInfo *csr_roam_insert_entry_into_pe_stats_req_list(tpAniSirGlobal pMac, + tDblLinkList * + pStaList, + tCsrPeStatsReqInfo * + pStaEntry) +{ + tCsrPeStatsReqInfo *pNewStaEntry = NULL; + pNewStaEntry = cdf_mem_malloc(sizeof(tCsrPeStatsReqInfo)); + if (NULL == pNewStaEntry) { + sms_log(pMac, LOGW, + "csr_roam_insert_entry_into_pe_stats_req_list: 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; + + csr_ll_insert_tail(pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK); + return pNewStaEntry; +} + +CDF_STATUS csr_get_rssi(tpAniSirGlobal pMac, + tCsrRssiCallback callback, + uint8_t staId, + struct cdf_mac_addr bssId, + int8_t lastRSSI, void *pContext, void *p_cds_context) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t msg; + uint32_t sessionId; + + tAniGetRssiReq *pMsg; + sms_log(pMac, LOG2, FL("called")); + + status = csr_roam_get_session_id_from_bssid(pMac, &bssId, &sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + callback(lastRSSI, staId, pContext); + sms_log(pMac, LOGE, FL("Failed to get SessionId")); + return CDF_STATUS_E_FAILURE; + } + + pMsg = cdf_mem_malloc(sizeof(tAniGetRssiReq)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, + " csr_get_rssi: failed to allocate mem for req "); + return CDF_STATUS_E_NOMEM; + } + + pMsg->msgType = eWNI_SME_GET_RSSI_REQ; + pMsg->msgLen = (uint16_t) sizeof(tAniGetRssiReq); + pMsg->sessionId = sessionId; + pMsg->staId = staId; + pMsg->rssiCallback = callback; + pMsg->pDevContext = pContext; + pMsg->p_cds_context = p_cds_context; + /* + * 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 (CDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(pMac, LOGE, " csr_get_rssi failed to post msg to self "); + cdf_mem_free((void *)pMsg); + status = CDF_STATUS_E_FAILURE; + } + sms_log(pMac, LOG2, FL("returned")); + return status; +} + +CDF_STATUS csr_get_snr(tpAniSirGlobal pMac, + tCsrSnrCallback callback, + uint8_t staId, struct cdf_mac_addr bssId, void *pContext) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t msg; + uint32_t sessionId; + + tAniGetSnrReq *pMsg; + + sms_log(pMac, LOG2, FL("called")); + + pMsg = (tAniGetSnrReq *) cdf_mem_malloc(sizeof(tAniGetSnrReq)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, "%s: failed to allocate mem for req", + __func__); + return CDF_STATUS_E_NOMEM; + } + + csr_roam_get_session_id_from_bssid(pMac, &bssId, &sessionId); + + pMsg->msgType = eWNI_SME_GET_SNR_REQ; + pMsg->msgLen = (uint16_t) 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 (CDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(pMac, LOGE, "%s failed to post msg to self", __func__); + cdf_mem_free((void *)pMsg); + status = CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG2, FL("returned")); + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS csr_get_tsm_stats(tpAniSirGlobal pMac, + tCsrTsmStatsCallback callback, + uint8_t staId, + struct cdf_mac_addr bssId, + void *pContext, void *p_cds_context, uint8_t tid) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tAniGetTsmStatsReq *pMsg = NULL; + pMsg = cdf_mem_malloc(sizeof(tAniGetTsmStatsReq)); + if (!pMsg) { + sms_log(pMac, LOGE, + "csr_get_tsm_stats: failed to allocate mem for req"); + return CDF_STATUS_E_NOMEM; + } + /* need to initiate a stats request to PE */ + pMsg->msgType = eWNI_SME_GET_TSM_STATS_REQ; + pMsg->msgLen = (uint16_t) sizeof(tAniGetTsmStatsReq); + pMsg->staId = staId; + pMsg->tid = tid; + cdf_mem_copy(pMsg->bssId, bssId.bytes, sizeof(tSirMacAddr)); + pMsg->tsmStatsCallback = callback; + pMsg->pDevContext = pContext; + pMsg->p_cds_context = p_cds_context; + status = cds_send_mb_message_to_mac(pMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, + " csr_get_tsm_stats: failed to send down the rssi req"); + /* pMsg is freed by cds_send_mb_message_to_mac */ + status = CDF_STATUS_E_FAILURE; + } + return status; +} +#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ + +/** + * csr_deregister_client_request() - deregisters a get stats request + * @mac_ctx: mac global context + * @sta_entry: stats request entry + * + * Return: status of operation + */ +static CDF_STATUS +csr_deregister_client_request(tpAniSirGlobal mac_ctx, + tCsrStatsClientReqInfo *sta_entry) +{ + CDF_STATUS status; + tListElem *entry = NULL; + tCsrStatsClientReqInfo *ptr_sta_entry = NULL; + + entry = csr_roam_checkn_update_client_req_list(mac_ctx, sta_entry, + false); + if (!entry) { + sms_log(mac_ctx, LOGW, + FL("callback is empty in the request & couldn't find any existing request in statsClientReqList")); + return CDF_STATUS_E_FAILURE; + } + /* clean up & return */ + ptr_sta_entry = GET_BASE_ADDR(entry, tCsrStatsClientReqInfo, link); + if (NULL != ptr_sta_entry->pPeStaEntry) { + ptr_sta_entry->pPeStaEntry->numClient--; + /* check if we need to delete the entry from peStatsReqList */ + if (!ptr_sta_entry->pPeStaEntry->numClient) + csr_roam_remove_entry_from_pe_stats_req_list(mac_ctx, + ptr_sta_entry->pPeStaEntry); + } + /* check if we need to stop the tl stats timer too */ + mac_ctx->roam.tlStatsReqInfo.numClient--; + if (!mac_ctx->roam.tlStatsReqInfo.numClient) { + if (mac_ctx->roam.tlStatsReqInfo.timerRunning) { + status = cdf_mc_timer_stop( + &mac_ctx->roam.tlStatsReqInfo.hTlStatsTimer); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("cannot stop TlStatsTimer timer")); + return status; + } + } + mac_ctx->roam.tlStatsReqInfo.periodicity = 0; + mac_ctx->roam.tlStatsReqInfo.timerRunning = false; + } + cdf_mc_timer_stop(&ptr_sta_entry->timer); + /* Destroy the cdf timer... */ + status = cdf_mc_timer_destroy(&ptr_sta_entry->timer); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(mac_ctx, LOGE, + FL("failed to destroy Client req timer")); + + csr_roam_remove_stat_list_entry(mac_ctx, entry); + return CDF_STATUS_SUCCESS; +} + +/** + * csr_insert_stats_request_to_list() - inserts request to existing list + * @mac_ctx: mac global context + * @sta_entry: stats request entry + * @periodicity: periodicity of stats + * + * Return: status of operation + */ +static CDF_STATUS +csr_insert_stats_request_to_list(tpAniSirGlobal mac_ctx, + tCsrStatsClientReqInfo *sta_entry, + uint32_t periodicity) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrStatsClientReqInfo *ptr_sta_entry = csr_roam_insert_entry_into_list( + mac_ctx, &mac_ctx->roam.statsClientReqList, + sta_entry); + if (!ptr_sta_entry) { + sms_log(mac_ctx, LOGW, + FL("Failed to insert req in statsClientReqList")); + return CDF_STATUS_E_FAILURE; + } + /* Init & start timer if needed */ + ptr_sta_entry->periodicity = periodicity; + if (ptr_sta_entry->periodicity) { + status = cdf_mc_timer_init(&ptr_sta_entry->timer, + CDF_TIMER_TYPE_SW, + csr_roam_stats_client_timer_handler, + ptr_sta_entry); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("cannot init StatsClient timer")); + return CDF_STATUS_E_FAILURE; + } + status = cdf_mc_timer_start(&ptr_sta_entry->timer, + ptr_sta_entry->periodicity); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("cannot start StatsClient timer")); + return CDF_STATUS_E_FAILURE; + } + } + return status; +} + +/** + * csr_get_statistics_from_tl() - fetch stats from tl layer + * @mac_ctx: mac global context + * @cache: indicate if cached stats are required + * @staId: station id + * @periodicity: periodicity of stats + * + * Return: status of operation + */ +static CDF_STATUS +csr_get_statistics_from_tl(tpAniSirGlobal mac_ctx, + bool cache, + uint8_t staId, + uint32_t periodicity) +{ + CDF_STATUS status; + + if (cache && mac_ctx->roam.tlStatsReqInfo.numClient) { + sms_log(mac_ctx, LOGE, FL("Looking for cached stats from TL")); + mac_ctx->roam.tlStatsReqInfo.numClient++; + return CDF_STATUS_SUCCESS; + } + + /* update periodicity */ + if (mac_ctx->roam.tlStatsReqInfo.periodicity) + mac_ctx->roam.tlStatsReqInfo.periodicity = + CDF_MIN(periodicity, + mac_ctx->roam.tlStatsReqInfo.periodicity); + else + mac_ctx->roam.tlStatsReqInfo.periodicity = periodicity; + + if (mac_ctx->roam.tlStatsReqInfo.periodicity + < CSR_MIN_TL_STAT_QUERY_PERIOD) { + mac_ctx->roam.tlStatsReqInfo.periodicity = + CSR_MIN_TL_STAT_QUERY_PERIOD; + } + + if (!mac_ctx->roam.tlStatsReqInfo.timerRunning) { + + if (mac_ctx->roam.tlStatsReqInfo.periodicity) { + /* start timer */ + status = cdf_mc_timer_start( + &mac_ctx->roam.tlStatsReqInfo.hTlStatsTimer, + mac_ctx->roam.tlStatsReqInfo.periodicity); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("cannot start TlStatsTimer timer")); + return CDF_STATUS_E_FAILURE; + } + mac_ctx->roam.tlStatsReqInfo.timerRunning = true; + } + } + mac_ctx->roam.tlStatsReqInfo.numClient++; + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_get_statistics(tpAniSirGlobal pMac, + eCsrStatsRequesterType requesterId, + uint32_t statsMask, + tCsrStatsCallback callback, + uint32_t periodicity, + bool cache, + uint8_t staId, + void *pContext, + uint8_t sessionId) +{ + tCsrStatsClientReqInfo staEntry; + tCsrPeStatsReqInfo *pPeStaEntry = NULL; + bool found = false; + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool insertInClientList = false; + uint32_t temp_mask = 0; + + if (csr_is_all_session_disconnected(pMac)) + return CDF_STATUS_E_FAILURE; + + if (csr_neighbor_middle_of_roaming(pMac, sessionId)) { + sms_log(pMac, LOG1, FL("in the middle of roaming states")); + return CDF_STATUS_E_FAILURE; + } + + if ((!statsMask) && (!callback)) { + sms_log(pMac, LOGW, + FL("statsMask & callback empty in the request")); + return CDF_STATUS_E_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)) + return csr_deregister_client_request(pMac, &staEntry); + + if (cache && !periodicity) { + /* return the cached stats */ + csr_roam_report_statistics(pMac, statsMask, callback, staId, + pContext); + return CDF_STATUS_SUCCESS; + } + /* 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 */ + temp_mask = statsMask & ~(1 << eCsrGlobalClassDStats); + if (temp_mask) { + /* check if same req made already & waiting for rsp */ + pPeStaEntry = csr_roam_check_pe_stats_req_list(pMac, + temp_mask, periodicity, &found, + staId, sessionId); + if (!pPeStaEntry) + /* bail out, maxed out on num of req for PE */ + return CDF_STATUS_E_FAILURE; + else + staEntry.pPeStaEntry = pPeStaEntry; + } + /* + * request stats from TL rightaway if requested by client, + * update tlStatsReqInfo if needed + */ + temp_mask = statsMask & (1 << eCsrGlobalClassDStats); + if (temp_mask) { + status = csr_get_statistics_from_tl(pMac, cache, staId, + periodicity); + if (!CDF_IS_STATUS_SUCCESS(status)) + return status; + } + insertInClientList = true; + } + /* if one time report requested with non cached result from PE/TL */ + else if (!cache && !periodicity) { + temp_mask = statsMask & ~(1 << eCsrGlobalClassDStats); + if (temp_mask) { + /* send down a req */ + status = csr_send_mb_stats_req_msg(pMac, + temp_mask, staId, sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGE, + FL("failed to send down stats req")); + /* + * so that when the stats rsp comes back from PE we + * respond to upper layer right away + */ + staEntry.timerExpired = true; + insertInClientList = true; + } + /* if looking for stats from TL only */ + if (!insertInClientList) { + /* return the stats */ + csr_roam_report_statistics(pMac, statsMask, callback, + staId, pContext); + return CDF_STATUS_SUCCESS; + } + } + if (insertInClientList) + return csr_insert_stats_request_to_list(pMac, &staEntry, + periodicity); + + return CDF_STATUS_SUCCESS; +} + +static tSirRetStatus +csr_roam_scan_offload_populate_mac_header(tpAniSirGlobal pMac, + uint8_t *pBD, + uint8_t type, + uint8_t 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 */ + cdf_mem_copy((uint8_t *) pMacHdr->da, (uint8_t *) peerAddr, + sizeof(tSirMacAddr)); + + sir_copy_mac_addr(pMacHdr->sa, selfMacAddr); + + /* Prepare Address 3 */ + cdf_mem_copy((uint8_t *) pMacHdr->bssId, (uint8_t *) peerAddr, + sizeof(tSirMacAddr)); + return statusCode; +} /*** csr_roam_scan_offload_populate_mac_header() ***/ + +static tSirRetStatus +csr_roam_scan_offload_prepare_probe_req_template(tpAniSirGlobal pMac, + uint8_t nChannelNum, + uint32_t dot11mode, + tSirMacAddr selfMacAddr, + uint8_t *pFrame, + uint16_t *pusLen, + tCsrRoamSession *psession) +{ + tDot11fProbeRequest pr; + uint32_t nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus; + /*Bcast tx */ + tSirMacAddr bssId = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + cdf_mem_set((uint8_t *) &pr, sizeof(pr), 0); + + populate_dot11f_supp_rates(pMac, nChannelNum, &pr.SuppRates, NULL); + + if (WNI_CFG_DOT11_MODE_11B != dot11mode) { + populate_dot11f_ext_supp_rates1(pMac, nChannelNum, + &pr.ExtSuppRates); + } + + if (IS_DOT11_MODE_HT(dot11mode)) { + populate_dot11f_ht_caps(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 = dot11f_get_packed_probe_request_size(pMac, &pr, &nPayload); + if (DOT11F_FAILED(nStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + cdf_mem_set(pFrame, nBytes, 0); + + nSirStatus = + csr_roam_scan_offload_populate_mac_header(pMac, pFrame, + SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssId, + selfMacAddr); + + if (eSIR_SUCCESS != nSirStatus) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to populate the buffer descriptor for a Probe Request (%d).\n", + nSirStatus); + return nSirStatus; + } + + nStatus = dot11f_pack_probe_request(pMac, &pr, pFrame + + sizeof(tSirMacMgmtHdr), + nPayload, &nPayload); + if (DOT11F_FAILED(nStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).\n", + nStatus); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(nStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 +CDF_STATUS csr_roam_set_key_mgmt_offload(tpAniSirGlobal pMac, + uint32_t sessionId, + bool nRoamKeyMgmtOffloadEnabled) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + pSession->RoamKeyMgmtOffloadEnabled = nRoamKeyMgmtOffloadEnabled; + return CDF_STATUS_SUCCESS; +} + +/** + * csr_update_roam_scan_offload_request() - updates req msg with roam offload + * paramters + * @pMac: mac global context + * @req_buf: out param, roam offload scan request packet + * @session: roam session + * + * Return: void + */ +static void +csr_update_roam_scan_offload_request(tpAniSirGlobal mac_ctx, + tSirRoamOffloadScanReq *req_buf, + tCsrRoamSession *session) +{ + cdf_mem_copy(req_buf->PSK_PMK, session->psk_pmk, + sizeof(req_buf->PSK_PMK)); + req_buf->pmk_len = session->pmk_len; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR3: PMK Length = %d", req_buf->pmk_len); + req_buf->R0KH_ID_Length = session->ftSmeContext.r0kh_id_len; + cdf_mem_copy(req_buf->R0KH_ID, + session->ftSmeContext.r0kh_id, + req_buf->R0KH_ID_Length); + req_buf->Prefer5GHz = mac_ctx->roam.configParam.nRoamPrefer5GHz; + req_buf->RoamRssiCatGap = mac_ctx->roam.configParam.bCatRssiOffset; + req_buf->Select5GHzMargin = mac_ctx->roam.configParam.nSelect5GHzMargin; + if (wlan_cfg_get_int(mac_ctx, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, + (uint32_t *) &req_buf->ReassocFailureTimeout) + != eSIR_SUCCESS) { + sms_log(mac_ctx, LOGE, + FL("could not retrieve ReassocFailureTimeout value")); + req_buf->ReassocFailureTimeout = + DEFAULT_REASSOC_FAILURE_TIMEOUT; + } +#ifdef FEATURE_WLAN_ESE + if (csr_is_auth_type_ese(req_buf->ConnectedNetwork.authentication)) { + cdf_mem_copy(req_buf->KRK, session->eseCckmInfo.krk, + SIR_KRK_KEY_LEN); + cdf_mem_copy(req_buf->BTK, session->eseCckmInfo.btk, + SIR_BTK_KEY_LEN); + } +#endif + req_buf->AcUapsd.acbe_uapsd = + SIR_UAPSD_GET(ACBE, mac_ctx->lim.gUapsdPerAcBitmask); + req_buf->AcUapsd.acbk_uapsd = + SIR_UAPSD_GET(ACBK, mac_ctx->lim.gUapsdPerAcBitmask); + req_buf->AcUapsd.acvi_uapsd = + SIR_UAPSD_GET(ACVI, mac_ctx->lim.gUapsdPerAcBitmask); + req_buf->AcUapsd.acvo_uapsd = + SIR_UAPSD_GET(ACVO, mac_ctx->lim.gUapsdPerAcBitmask); +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +/** + * csr_check_band_channel_match() - check if passed band and channel match + * paramters + * @band: band to match with channel + * @channel: channel to match with band + * + * Return: bool if match else false + */ +static bool +csr_check_band_channel_match(eCsrBand band, uint8_t channel) +{ + if (eCSR_BAND_ALL == band) + return true; + + if (eCSR_BAND_24 == band && CDS_IS_CHANNEL_24GHZ(channel)) + return true; + + if (eCSR_BAND_5G == band && CDS_IS_CHANNEL_5GHZ(channel)) + return true; + + return false; +} + +/** + * csr_fetch_ch_lst_from_ini() - fetch channel list from ini and update req msg + * paramters + * @mac_ctx: global mac ctx + * @roam_info: roam info struct + * @req_buf: out param, roam offload scan request packet + * + * Return: result of operation + */ +static CDF_STATUS +csr_fetch_ch_lst_from_ini(tpAniSirGlobal mac_ctx, + tpCsrNeighborRoamControlInfo roam_info, + tSirRoamOffloadScanReq *req_buf) +{ + eCsrBand band; + uint8_t i = 0; + uint8_t num_channels = 0; + uint8_t *ch_lst = roam_info->cfgParams.channelInfo.ChannelList; + /* + * The INI channels need to be filtered with respect to the current band + * that is supported. + */ + band = mac_ctx->roam.configParam.bandCapability; + if ((eCSR_BAND_24 != band) && (eCSR_BAND_5G != band) + && (eCSR_BAND_ALL != band)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Invalid band(%d), roam scan offload req aborted"), + band); + return CDF_STATUS_E_FAILURE; + } + + for (i = 0; i < roam_info->cfgParams.channelInfo.numOfChannels; i++) { + if (!csr_check_band_channel_match(band, *ch_lst)) + continue; + /* Allow DFS channels only if the DFS roaming is enabled */ + if (((mac_ctx->roam.configParam.allowDFSChannelRoam != + CSR_ROAMING_DFS_CHANNEL_DISABLED) + || (!CDS_IS_DFS_CH(*ch_lst))) + && csr_roam_is_channel_valid(mac_ctx, *ch_lst) + && *ch_lst && (num_channels < SIR_ROAM_MAX_CHANNELS)) { + req_buf->ConnectedNetwork.ChannelCache[num_channels++] = + *ch_lst; + } + ch_lst++; + } + req_buf->ConnectedNetwork.ChannelCount = num_channels; + req_buf->ChannelCacheType = CHANNEL_LIST_STATIC; + return CDF_STATUS_SUCCESS; +} + +/** + * csr_fetch_ch_lst_from_occupied_lst() - fetch channel list from occupied list + * and update req msg + * paramters + * @mac_ctx: global mac ctx + * @session_id: session id + * @reason: reason to roam + * @req_buf: out param, roam offload scan request packet + * @roam_info: roam info struct + * + * Return: void + */ +static void +csr_fetch_ch_lst_from_occupied_lst(tpAniSirGlobal mac_ctx, + uint8_t session_id, + uint8_t reason, + tSirRoamOffloadScanReq *req_buf, + tpCsrNeighborRoamControlInfo roam_info) +{ + uint8_t i = 0; + uint8_t num_channels = 0; + uint8_t *ch_lst = + mac_ctx->scan.occupiedChannels[session_id].channelList; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Num of channels before filtering=%d", + mac_ctx->scan.occupiedChannels[session_id].numChannels); + for (i = 0; i < mac_ctx->scan.occupiedChannels[session_id].numChannels; + i++) { + if (((mac_ctx->roam.configParam.allowDFSChannelRoam != + CSR_ROAMING_DFS_CHANNEL_DISABLED) + || (!CDS_IS_DFS_CH(*ch_lst))) + && *ch_lst && (num_channels < SIR_ROAM_MAX_CHANNELS)) { + req_buf->ConnectedNetwork.ChannelCache[num_channels++] = + *ch_lst; + } + if (*ch_lst) + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "DFSRoam=%d, ChnlState=%d, Chnl=%d, num_ch=%d", + mac_ctx->roam.configParam.allowDFSChannelRoam, + cds_get_channel_state(*ch_lst), *ch_lst, + num_channels); + ch_lst++; + } + req_buf->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) + req_buf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH; + else { + if (csr_neighbor_roam_is_new_connected_profile(mac_ctx, + session_id)) + req_buf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT; + else + req_buf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; + } +} + +#ifdef FEATURE_WLAN_ESE +/** + * csr_fetch_ch_lst_from_received_list() - fetch channel list from received list + * and update req msg + * paramters + * @mac_ctx: global mac ctx + * @roam_info: roam info struct + * @curr_ch_lst_info: current channel list info + * @req_buf: out param, roam offload scan request packet + * + * Return: void + */ +static void +csr_fetch_ch_lst_from_received_list(tpAniSirGlobal mac_ctx, + tpCsrNeighborRoamControlInfo roam_info, + tpCsrChannelInfo curr_ch_lst_info, + tSirRoamOffloadScanReq *req_buf) +{ + uint8_t i = 0; + uint8_t num_channels = 0; + uint8_t *ch_lst = NULL; + + if (curr_ch_lst_info->numOfChannels == 0) + return; + + ch_lst = curr_ch_lst_info->ChannelList; + for (i = 0; i < curr_ch_lst_info->numOfChannels; i++) { + if (((mac_ctx->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CDS_IS_DFS_CH(*ch_lst))) && *ch_lst) { + req_buf->ConnectedNetwork.ChannelCache[num_channels++] = + *ch_lst; + } + ch_lst++; + } + req_buf->ConnectedNetwork.ChannelCount = num_channels; + req_buf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; +} +#endif + +/** + * csr_fetch_valid_ch_lst() - fetch channel list from valid channel list and + * update req msg + * paramters + * @mac_ctx: global mac ctx + * @req_buf: out param, roam offload scan request packet + * + * Return: void + */ +static CDF_STATUS +csr_fetch_valid_ch_lst(tpAniSirGlobal mac_ctx, + tSirRoamOffloadScanReq *req_buf) +{ + CDF_STATUS status; + uint32_t host_channels = 0; + uint8_t *ch_lst = NULL; + uint8_t i = 0, num_channels = 0; + + host_channels = sizeof(mac_ctx->roam.validChannelList); + status = csr_get_cfg_valid_channels(mac_ctx, + mac_ctx->roam.validChannelList, + &host_channels); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to get the valid channel list")); + return status; + } + ch_lst = mac_ctx->roam.validChannelList; + mac_ctx->roam.numValidChannels = host_channels; + for (i = 0; i < mac_ctx->roam.numValidChannels; i++) { + if (((mac_ctx->roam.configParam.allowDFSChannelRoam + != CSR_ROAMING_DFS_CHANNEL_DISABLED) || + (!CDS_IS_DFS_CH(*ch_lst))) && *ch_lst) { + req_buf->ValidChannelList[num_channels++] = *ch_lst; + } + ch_lst++; + } + req_buf->ValidChannelCount = num_channels; + return status; +} + +/** + * csr_create_roam_scan_offload_request() - init roam offload scan request + * + * paramters + * @mac_ctx: global mac ctx + * @command: roam scan offload command input + * @session_id: session id + * @reason: reason to roam + * @session: roam session + * @roam_info: roam info struct + * + * Return: roam offload scan request packet buffer + */ +static tSirRoamOffloadScanReq * +csr_create_roam_scan_offload_request(tpAniSirGlobal mac_ctx, + uint8_t command, + uint8_t session_id, + uint8_t reason, + tCsrRoamSession *session, + tpCsrNeighborRoamControlInfo roam_info) +{ + CDF_STATUS status; + uint8_t i, j, dot11_mode; + bool ese_neighbor_list_recvd = false; + uint8_t ch_cache_str[128] = { 0 }; + tSirRoamOffloadScanReq *req_buf = NULL; + tpCsrChannelInfo curr_ch_lst_info = + &roam_info->roamChannelInfo.currentChannelListInfo; +#ifdef FEATURE_WLAN_ESE + /* + * this flag will be true if connection is ESE and no neighbor + * list received or if the connection is not ESE + */ + ese_neighbor_list_recvd = ((roam_info->isESEAssoc) + && (roam_info->roamChannelInfo.IAPPNeighborListReceived + == false)) + || (roam_info->isESEAssoc == false); +#endif /* FEATURE_WLAN_ESE */ + + req_buf = cdf_mem_malloc(sizeof(tSirRoamOffloadScanReq)); + if (NULL == req_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Mem alloc for roam scan offload req failed.")); + return NULL; + } + cdf_mem_zero(req_buf, sizeof(tSirRoamOffloadScanReq)); + req_buf->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 (csr_neighbor_middle_of_roaming((tHalHandle)mac_ctx, + session_id)) + req_buf->middle_of_roaming = 1; + else + csr_roam_reset_roam_params(mac_ctx); + req_buf->RoamScanOffloadEnabled = 0; + } else { + req_buf->RoamScanOffloadEnabled = + mac_ctx->roam.configParam.isRoamOffloadScanEnabled; + } + cdf_mem_copy(req_buf->ConnectedNetwork.currAPbssid, + roam_info->currAPbssid.bytes, sizeof(struct cdf_mac_addr)); + req_buf->ConnectedNetwork.ssId.length = + mac_ctx->roam.roamSession[session_id]. + connectedProfile.SSID.length; + cdf_mem_copy(req_buf->ConnectedNetwork.ssId.ssId, + mac_ctx->roam.roamSession[session_id]. + connectedProfile.SSID.ssId, + req_buf->ConnectedNetwork.ssId.length); + req_buf->ConnectedNetwork.authentication = + mac_ctx->roam.roamSession[session_id].connectedProfile.AuthType; + req_buf->ConnectedNetwork.encryption = + mac_ctx->roam.roamSession[session_id]. + connectedProfile.EncryptionType; + req_buf->ConnectedNetwork.mcencryption = + mac_ctx->roam.roamSession[session_id]. + connectedProfile.mcEncryptionType; +#ifdef WLAN_FEATURE_11W + req_buf->ConnectedNetwork.mfp_enabled = + mac_ctx->roam.roamSession[session_id].connectedProfile.MFPEnabled; +#endif + req_buf->delay_before_vdev_stop = + roam_info->cfgParams.delay_before_vdev_stop; + req_buf->OpportunisticScanThresholdDiff = + roam_info->cfgParams.nOpportunisticThresholdDiff; + req_buf->RoamRescanRssiDiff = + roam_info->cfgParams.nRoamRescanRssiDiff; + req_buf->RoamRssiDiff = mac_ctx->roam.configParam.RoamRssiDiff; + req_buf->reason = reason; + req_buf->NeighborScanTimerPeriod = + roam_info->cfgParams.neighborScanPeriod; + req_buf->NeighborRoamScanRefreshPeriod = + roam_info->cfgParams.neighborResultsRefreshPeriod; + req_buf->NeighborScanChannelMinTime = + roam_info->cfgParams.minChannelScanTime; + req_buf->NeighborScanChannelMaxTime = + roam_info->cfgParams.maxChannelScanTime; + req_buf->EmptyRefreshScanPeriod = + roam_info->cfgParams.emptyScanRefreshPeriod; + req_buf->RoamBmissFirstBcnt = + roam_info->cfgParams.nRoamBmissFirstBcnt; + req_buf->RoamBmissFinalBcnt = + roam_info->cfgParams.nRoamBmissFinalBcnt; + req_buf->RoamBeaconRssiWeight = + roam_info->cfgParams.nRoamBeaconRssiWeight; + /* MAWC feature */ + req_buf->MAWCEnabled = mac_ctx->roam.configParam.MAWCEnabled; +#ifdef FEATURE_WLAN_ESE + req_buf->IsESEAssoc = + csr_neighbor_roam_is_ese_assoc(mac_ctx, session_id) && + ((req_buf->ConnectedNetwork.authentication == + eCSR_AUTH_TYPE_OPEN_SYSTEM) || + (csr_is_auth_type_ese(req_buf-> + ConnectedNetwork.authentication))); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:IsEseAssoc=%d\n"), req_buf->IsESEAssoc); +#endif + if (ese_neighbor_list_recvd || curr_ch_lst_info->numOfChannels == 0) { + /* + * Retrieve the Channel Cache either from ini or from the + * occupied channels list. Give Preference to INI Channels + */ + if (roam_info->cfgParams.channelInfo.numOfChannels) { + status = csr_fetch_ch_lst_from_ini(mac_ctx, roam_info, + req_buf); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(req_buf); + return NULL; + } + } else { + csr_fetch_ch_lst_from_occupied_lst(mac_ctx, session_id, + reason, req_buf, roam_info); + } + } +#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 + */ + csr_fetch_ch_lst_from_received_list(mac_ctx, roam_info, + curr_ch_lst_info, req_buf); + } +#endif + for (i = 0, j = 0; i < req_buf->ConnectedNetwork.ChannelCount; i++) { + if (j < sizeof(ch_cache_str)) { + j += snprintf(ch_cache_str + j, + sizeof(ch_cache_str) - j, " %d", + req_buf->ConnectedNetwork. + ChannelCache[i]); + } else + break; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("ChnlCacheType:%d, No of Chnls:%d,Channels: %s"), + req_buf->ChannelCacheType, + req_buf->ConnectedNetwork.ChannelCount, ch_cache_str); + + /* Maintain the Valid Channels List */ + status = csr_fetch_valid_ch_lst(mac_ctx, req_buf); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(req_buf); + return NULL; + } + + req_buf->MDID.mdiePresent = + mac_ctx->roam.roamSession[session_id]. + connectedProfile.MDID.mdiePresent; + req_buf->MDID.mobilityDomain = + mac_ctx->roam.roamSession[session_id]. + connectedProfile.MDID.mobilityDomain; + req_buf->sessionId = session_id; + req_buf->nProbes = mac_ctx->roam.configParam.nProbes; + req_buf->HomeAwayTime = mac_ctx->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 (req_buf->HomeAwayTime < (req_buf->NeighborScanChannelMaxTime + + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + FL("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)"), + req_buf->HomeAwayTime, + (req_buf->NeighborScanChannelMaxTime + + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME))); + req_buf->HomeAwayTime = 0; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("HomeAwayTime:%d"), req_buf->HomeAwayTime); + + /*Prepare a probe request for 2.4GHz band and one for 5GHz band */ + dot11_mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(mac_ctx, + csr_find_best_phy_mode(mac_ctx, + mac_ctx->roam.configParam.phyMode)); + csr_roam_scan_offload_prepare_probe_req_template(mac_ctx, + SIR_ROAM_SCAN_24G_DEFAULT_CH, dot11_mode, + session->selfMacAddr.bytes, req_buf->p24GProbeTemplate, + &req_buf->us24GProbeTemplateLen, session); + + csr_roam_scan_offload_prepare_probe_req_template(mac_ctx, + SIR_ROAM_SCAN_5G_DEFAULT_CH, dot11_mode, + session->selfMacAddr.bytes, + req_buf->p5GProbeTemplate, &req_buf->us5GProbeTemplateLen, + session); + req_buf->allowDFSChannelRoam = + mac_ctx->roam.configParam.allowDFSChannelRoam; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + req_buf->RoamOffloadEnabled = csr_roamIsRoamOffloadEnabled(mac_ctx); + req_buf->RoamKeyMgmtOffloadEnabled = session->RoamKeyMgmtOffloadEnabled; + /* Roam Offload piggybacks upon the Roam Scan offload command. */ + if (req_buf->RoamOffloadEnabled) + csr_update_roam_scan_offload_request(mac_ctx, req_buf, session); + cdf_mem_copy(&req_buf->roam_params, + &mac_ctx->roam.configParam.roam_params, + sizeof(req_buf->roam_params)); +#endif + return req_buf; +} +/** + * 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) && + cdf_mem_compare(roam_params->ssid_allowed_list[i].ssId, + req_buffer->ConnectedNetwork.ssId.ssId, + roam_params->ssid_allowed_list[i].length)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Whitelist contains connected profile SSID"); + match = true; + break; + } + } + if (!match) { + if (roam_params->num_ssid_allowed_list >= + MAX_SSID_ALLOWED_LIST) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Whitelist is FULL. Cannot Add another entry"); + return; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; + cdf_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 | RSO_START | RSO_STOP | RSO_RESTART | RSO_UPDATE_CFG|| + *|| -------------------------------------------------------------------------|| + *|| RSO_START | NO | YES | NO | NO || + *|| RSO_STOP | YES | YES | YES | YES || + *|| RSO_RESTART | YES | NO | NO | YES || + *|| RSO_UPDATE_CFG | YES | NO | YES | YES || + *||==========================================================================|| + **/ +#define RSO_START_BIT (1<roam.neighborRoamInfo[session_id]; + uint8_t 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; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Wrong RSO command %d, not allowed"), command); + return 0;/*Cmd Not allowed*/ + } + ret_val = desiredMask & (1 << neigh_roam_info->last_sent_cmd); + return ret_val; +} + +/** + * csr_roam_offload_scan() - populates roam offload scan request and sends to + * WMA + * + * paramters + * @mac_ctx: global mac ctx + * @session_id: session id + * @command: roam scan offload command input + * @reason: reason to roam + * + * Return: result of operation + */ +CDF_STATUS +csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, + uint8_t command, uint8_t reason) +{ + uint8_t *state = NULL; + cds_msg_t msg; + tSirRoamOffloadScanReq *req_buf; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tpCsrNeighborRoamControlInfo roam_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + struct roam_ext_params *roam_params_dst; + struct roam_ext_params *roam_params_src; + uint8_t i; + + if (NULL == session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session is null")); + return CDF_STATUS_E_FAILURE; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session->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 + */ + b_roam_scan_offload_started = false; + return CDF_STATUS_SUCCESS; + } +#endif + if (0 == csr_roam_is_roam_offload_scan_enabled(mac_ctx)) { + sms_log(mac_ctx, LOGE, "isRoamOffloadScanEnabled not set"); + return CDF_STATUS_E_FAILURE; + } + if (!csr_is_RSO_cmd_allowed(mac_ctx, command, session_id) && + reason != REASON_ROAM_SET_BLACKLIST_BSSID) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("RSO out-of-sync command %d lastSentCmd %d"), + command, roam_info->last_sent_cmd); + return CDF_STATUS_E_FAILURE; + } + + if ((true == b_roam_scan_offload_started) + && (ROAM_SCAN_OFFLOAD_START == command)) { + sms_log(mac_ctx, LOGE, "Roam Scan Offload is already started"); + return CDF_STATUS_E_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 ((roam_info->neighborRoamState == + eCSR_NEIGHBOR_ROAM_STATE_INIT) && + (command != ROAM_SCAN_OFFLOAD_STOP) && + (reason != REASON_ROAM_SET_BLACKLIST_BSSID)) { + state = mac_trace_get_neighbour_roam_state( + roam_info->neighborRoamState); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("Scan Command not sent to FW state=%s and cmd=%d"), + state, command); + return CDF_STATUS_E_FAILURE; + } + + req_buf = csr_create_roam_scan_offload_request(mac_ctx, command, + session_id, reason, + session, roam_info); + if (!req_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Failed to create req packet")); + return CDF_STATUS_E_FAILURE; + } + roam_params_dst = &req_buf->roam_params; + roam_params_src = &mac_ctx->roam.configParam.roam_params; + if (reason == REASON_ROAM_SET_SSID_ALLOWED) + check_allowed_ssid_list(req_buf, 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) + req_buf->LookupThreshold = + roam_params_src->alert_rssi_threshold; + else + req_buf->LookupThreshold = + (int8_t)roam_info->cfgParams.neighborLookupThreshold * + (-1); + cdf_mem_copy(roam_params_dst, roam_params_src, + sizeof(struct roam_ext_params)); + /* + * 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) + req_buf->RoamRssiDiff = roam_params_src->rssi_diff; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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, rssi_diff: %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, + req_buf->RoamRssiDiff, roam_params_dst->alert_rssi_threshold); + + for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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++) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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++) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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]); + } + + req_buf->hi_rssi_scan_max_count = + roam_info->cfgParams.hi_rssi_scan_max_count; + req_buf->hi_rssi_scan_rssi_delta = + roam_info->cfgParams.hi_rssi_scan_rssi_delta; + req_buf->hi_rssi_scan_delay = + roam_info->cfgParams.hi_rssi_scan_delay; + req_buf->hi_rssi_scan_rssi_ub = + roam_info->cfgParams.hi_rssi_scan_rssi_ub; + + msg.type = WMA_ROAM_SCAN_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = req_buf; + if (!CDF_IS_STATUS_SUCCESS + (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post message to WMA", + __func__); + cdf_mem_free(req_buf); + return CDF_STATUS_E_FAILURE; + } else { + if (ROAM_SCAN_OFFLOAD_START == command) + b_roam_scan_offload_started = true; + else if (ROAM_SCAN_OFFLOAD_STOP == command) + b_roam_scan_offload_started = false; + } + /* update the last sent cmd */ + roam_info->last_sent_cmd = command; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Roam Scan Offload Command %d, Reason %d", command, reason); + return status; +} + +CDF_STATUS csr_roam_offload_scan_rsp_hdlr(tpAniSirGlobal pMac, + tpSirRoamOffloadScanRsp scanOffloadRsp) +{ + switch (scanOffloadRsp->reason) { + case 0: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Rsp for Roam Scan Offload with failure status"); + break; + case REASON_OS_REQUESTED_ROAMING_NOW: + csr_neighbor_roam_proceed_with_handoff_req(pMac, + scanOffloadRsp->sessionId); + break; + + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "Rsp for Roam Scan Offload with reason %d", + scanOffloadRsp->reason); + } + return CDF_STATUS_SUCCESS; +} + +tCsrPeStatsReqInfo *csr_roam_check_pe_stats_req_list(tpAniSirGlobal pMac, + uint32_t statsMask, + uint32_t periodicity, + bool *pFound, + uint8_t staId, uint8_t sessionId) +{ + bool found = false; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrPeStatsReqInfo staEntry; + tCsrPeStatsReqInfo *pTempStaEntry = NULL; + tListElem *pStaEntry = NULL; + CDF_STATUS cdf_status; + *pFound = false; + + pStaEntry = csr_roam_find_in_pe_stats_req_list(pMac, statsMask); + if (pStaEntry) { + pTempStaEntry = + GET_BASE_ADDR(pStaEntry, tCsrPeStatsReqInfo, link); + if (pTempStaEntry->periodicity) { + pTempStaEntry->periodicity = + CDF_MIN(periodicity, + pTempStaEntry->periodicity); + } else { + pTempStaEntry->periodicity = periodicity; + } + pTempStaEntry->numClient++; + found = true; + } else { + cdf_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 = + csr_roam_insert_entry_into_pe_stats_req_list(pMac, + &pMac->roam. + peStatsReqList, + &staEntry); + if (!pTempStaEntry) { + /* msg */ + sms_log(pMac, LOGW, + "csr_roam_check_pe_stats_req_list: Failed to insert req in peStatsReqList"); + return NULL; + } + } + 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 = csr_send_mb_stats_req_msg(pMac, + statsMask & ~(1 << + eCsrGlobalClassDStats), + staId, sessionId); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_check_pe_stats_req_list:failed to send down stats req to PE")); + } else { + pTempStaEntry->rspPending = true; + } + } + if (pTempStaEntry->periodicity) { + if (!found) { + + cdf_status = + cdf_mc_timer_init(&pTempStaEntry-> + hPeStatsTimer, + CDF_TIMER_TYPE_SW, + csr_roam_pe_stats_timer_handler, + pTempStaEntry); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_check_pe_stats_req_list:cannot init hPeStatsTimer timer")); + return NULL; + } + } + /* start timer */ + sms_log(pMac, LOG1, + "csr_roam_check_pe_stats_req_list:peStatsTimer period %d", + pTempStaEntry->periodicity); + cdf_status = + cdf_mc_timer_start(&pTempStaEntry->hPeStatsTimer, + pTempStaEntry->periodicity); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_check_pe_stats_req_list: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 csr_roam_remove_stat_list_entry(tpAniSirGlobal pMac, tListElem *pEntry) +{ + if (pEntry) { + if (csr_ll_remove_entry + (&pMac->roam.statsClientReqList, pEntry, LL_ACCESS_LOCK)) { + cdf_mem_free(GET_BASE_ADDR + (pEntry, tCsrStatsClientReqInfo, link)); + } + } +} + +void csr_roam_remove_entry_from_pe_stats_req_list(tpAniSirGlobal pMac, + tCsrPeStatsReqInfo *pPeStaEntry) +{ + tListElem *pEntry; + tCsrPeStatsReqInfo *pTempStaEntry; + CDF_STATUS cdf_status; + pEntry = csr_ll_peek_head(&pMac->roam.peStatsReqList, LL_ACCESS_LOCK); + if (!pEntry) { + sms_log(pMac, LOGE, FL(" List empty, no stats req for PE")); + return; + } + while (pEntry) { + pTempStaEntry = GET_BASE_ADDR(pEntry, tCsrPeStatsReqInfo, link); + if (NULL == pTempStaEntry + || (pTempStaEntry->statsMask != + pPeStaEntry->statsMask)) { + pEntry = csr_ll_next(&pMac->roam.peStatsReqList, pEntry, + LL_ACCESS_NOLOCK); + continue; + } + sms_log(pMac, LOGW, FL("Match found")); + if (pTempStaEntry->timerRunning) { + cdf_status = cdf_mc_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 (cdf_status == CDF_STATUS_SUCCESS) { + /* the timer is successfully stopped */ + pTempStaEntry->timerRunning = false; + /* Destroy the timer */ + cdf_status = cdf_mc_timer_destroy( + &pTempStaEntry->hPeStatsTimer); + } 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 (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL("failed to stop/destroy timer")); + } + } + + if (csr_ll_remove_entry(&pMac->roam.peStatsReqList, pEntry, + LL_ACCESS_LOCK)) { + /* + * Only free the memory if we could stop the timer + * successfully + */ + if (!pTempStaEntry->timerStopFailed) { + cdf_mem_free(pTempStaEntry); + pTempStaEntry = NULL; + } + break; + } + pEntry = csr_ll_next(&pMac->roam.peStatsReqList, pEntry, + LL_ACCESS_NOLOCK); + } /* end of while loop */ + return; +} + +void csr_roam_report_statistics(tpAniSirGlobal pMac, uint32_t statsMask, + tCsrStatsCallback callback, uint8_t staId, + void *pContext) +{ + uint8_t stats[500]; + uint8_t *pStats = NULL; + uint32_t tempMask = 0; + uint8_t counter = 0; + if (!callback) { + sms_log(pMac, LOGE, FL("Cannot report callback NULL")); + return; + } + if (!statsMask) { + sms_log(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 strucutres in PMAC */ + switch (counter) { + case eCsrSummaryStats: + sms_log(pMac, LOG2, FL("Summary stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + summaryStatsInfo, + sizeof(tCsrSummaryStatsInfo)); + pStats += sizeof(tCsrSummaryStatsInfo); + break; + case eCsrGlobalClassAStats: + sms_log(pMac, LOG2, FL("ClassA stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + classAStatsInfo, + sizeof(tCsrGlobalClassAStatsInfo)); + pStats += sizeof(tCsrGlobalClassAStatsInfo); + break; + case eCsrGlobalClassBStats: + sms_log(pMac, LOG2, FL("ClassB stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + classBStatsInfo, + sizeof(tCsrGlobalClassBStatsInfo)); + pStats += sizeof(tCsrGlobalClassBStatsInfo); + break; + case eCsrGlobalClassCStats: + sms_log(pMac, LOG2, FL("ClassC stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + classCStatsInfo, + sizeof(tCsrGlobalClassCStatsInfo)); + pStats += sizeof(tCsrGlobalClassCStatsInfo); + break; + case eCsrGlobalClassDStats: + sms_log(pMac, LOG2, FL("ClassD stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + classDStatsInfo, + sizeof(tCsrGlobalClassDStatsInfo)); + pStats += sizeof(tCsrGlobalClassDStatsInfo); + break; + case eCsrPerStaStats: + sms_log(pMac, LOG2, FL("PerSta stats")); + cdf_mem_copy(pStats, + (uint8_t *) &pMac->roam. + perStaStatsInfo[staId], + sizeof(tCsrPerStaStatsInfo)); + pStats += sizeof(tCsrPerStaStatsInfo); + break; + default: + sms_log(pMac, LOGE, + FL("Unknown stats type and counter %d"), + counter); + break; + } + } + tempMask >>= 1; + counter++; + } + callback(stats, pContext); +} + +CDF_STATUS csr_roam_dereg_statistics_req(tpAniSirGlobal pMac) +{ + tListElem *pEntry = NULL; + tListElem *pPrevEntry = NULL; + tCsrStatsClientReqInfo *pTempStaEntry = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status; + pEntry = csr_ll_peek_head(&pMac->roam.statsClientReqList, LL_ACCESS_LOCK); + if (!pEntry) { + /* list empty */ + sms_log(pMac, LOGW, + "csr_roam_dereg_statistics_req: 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 */ + csr_roam_report_statistics(pMac, pTempStaEntry->statsMask, + pTempStaEntry->callback, + pTempStaEntry->staId, + pTempStaEntry->pContext); + csr_roam_remove_stat_list_entry(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) { + csr_roam_remove_entry_from_pe_stats_req_list(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 = + cdf_mc_timer_stop(&pMac->roam. + tlStatsReqInfo. + hTlStatsTimer); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_dereg_statistics_req:cannot stop TlStatsTimer timer")); + /* we will continue */ + } + } + pMac->roam.tlStatsReqInfo.periodicity = 0; + pMac->roam.tlStatsReqInfo.timerRunning = false; + } + if (pTempStaEntry->periodicity) { + /* While creating StaEntry in csr_get_statistics, */ + /* Initializing and starting timer only when periodicity is set. */ + /* So Stop and Destroy timer only when periodicity is set. */ + + cdf_mc_timer_stop(&pTempStaEntry->timer); + /* Destroy the cdf timer... */ + cdf_status = + cdf_mc_timer_destroy(&pTempStaEntry->timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + sms_log(pMac, LOGE, + FL + ("csr_roam_dereg_statistics_req:failed to destroy Client req timer")); + } + } + + pPrevEntry = pEntry; + pEntry = + csr_ll_next(&pMac->roam.statsClientReqList, pEntry, + LL_ACCESS_NOLOCK); + } + /* the last one */ + if (pPrevEntry) { + pTempStaEntry = + GET_BASE_ADDR(pPrevEntry, tCsrStatsClientReqInfo, link); + /* send up the stats report */ + csr_roam_report_statistics(pMac, pTempStaEntry->statsMask, + pTempStaEntry->callback, + pTempStaEntry->staId, + pTempStaEntry->pContext); + csr_roam_remove_stat_list_entry(pMac, pPrevEntry); + } + return status; + +} + +tSmeCmd *csr_get_command_buffer(tpAniSirGlobal pMac) +{ + tSmeCmd *pCmd = sme_get_command_buffer(pMac); + if (pCmd) { + pMac->roam.sPendingCommands++; + } + return pCmd; +} + +void csr_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + if (pMac->roam.sPendingCommands > 0) { + /* All command allocated through csr_get_command_buffer need to */ + /* decrement the pending count when releasing. */ + pMac->roam.sPendingCommands--; + sme_release_command(pMac, pCommand); + } else { + sms_log(pMac, LOGE, FL("no pending commands")); + CDF_ASSERT(0); + } +} + +/* Return SUCCESS is the command is queued, failed */ +CDF_STATUS csr_queue_sme_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fHighPriority) +{ + bool fNoCmdPending; + + if (!SME_IS_START(pMac)) { + sms_log(pMac, LOGE, FL("Sme in stop state")); + CDF_ASSERT(0); + return CDF_STATUS_E_PERM; + } + + if ((eSmeCommandScan == pCommand->command) && pMac->scan.fDropScanCmd) { + sms_log(pMac, LOGW, FL(" drop scan (scan reason %d) command"), + pCommand->u.scanCmd.reason); + return CDF_STATUS_CSR_WRONG_STATE; + } + + if ((pCommand->command == eSmeCommandScan) + || (pCommand->command == eSmeCommandRemainOnChannel)) { + sms_log(pMac, LOGW, + FL("scan pending list count %d scan_id %d"), + pMac->sme.smeScanCmdPendingList.Count, + pCommand->u.scanCmd.scanID); + csr_ll_insert_tail(&pMac->sme.smeScanCmdPendingList, + &pCommand->Link, LL_ACCESS_LOCK); + /* process the command queue... */ + sme_process_pending_queue(pMac); + return CDF_STATUS_SUCCESS; + } + /* Make sure roamCmdPendingList is not empty first */ + fNoCmdPending = + csr_ll_is_list_empty(&pMac->roam.roamCmdPendingList, false); + if (fNoCmdPending) { + sme_push_command(pMac, pCommand, fHighPriority); + } else { + /* no list lock is needed since SME lock is held */ + if (!fHighPriority) { + csr_ll_insert_tail(&pMac->roam.roamCmdPendingList, + &pCommand->Link, false); + } else { + csr_ll_insert_head(&pMac->roam.roamCmdPendingList, + &pCommand->Link, false); + } + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_roam_update_apwpsie(tpAniSirGlobal pMac, uint32_t sessionId, + tSirAPWPSIEs *pAPWPSIES) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirUpdateAPWPSIEsReq *pMsg; + + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pSession) { + sms_log(pMac, LOGE, + FL(" Session does not exist for session id %d"), + sessionId); + return CDF_STATUS_E_FAILURE; + } + + do { + pMsg = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, sizeof(tSirUpdateAPWPSIEsReq), 0); + pMsg->messageType = eWNI_SME_UPDATE_APWPSIE_REQ; + pMsg->transactionId = 0; + cdf_mem_copy(pMsg->bssId, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + pMsg->sessionId = sessionId; + cdf_mem_copy(&pMsg->APWPSIEs, pAPWPSIES, + sizeof(tSirAPWPSIEs)); + pMsg->length = sizeof(struct sSirUpdateAPWPSIEsReq); + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +CDF_STATUS csr_roam_update_wparsni_es(tpAniSirGlobal pMac, uint32_t sessionId, + tSirRSNie *pAPSirRSNie) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirUpdateAPWPARSNIEsReq *pMsg; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pSession) { + sms_log(pMac, LOGE, + FL(" Session does not exist for session id %d"), + sessionId); + return CDF_STATUS_E_FAILURE; + } + do { + pMsg = cdf_mem_malloc(sizeof(tSirUpdateAPWPARSNIEsReq)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + cdf_mem_set(pMsg, sizeof(tSirUpdateAPWPARSNIEsReq), 0); + pMsg->messageType = eWNI_SME_SET_APWPARSNIEs_REQ; + pMsg->transactionId = 0; + cdf_mem_copy(pMsg->bssId, &pSession->selfMacAddr, + sizeof(tSirMacAddr)); + pMsg->sessionId = sessionId; + cdf_mem_copy(&pMsg->APWPARSNIEs, pAPSirRSNie, + sizeof(tSirRSNie)); + pMsg->length = sizeof(struct sSirUpdateAPWPARSNIEsReq); + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +CDF_STATUS +csr_roam_issue_ft_preauth_req(tHalHandle hHal, uint32_t sessionId, + tpSirBssDescription pBssDescription) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tpSirFTPreAuthReq pftPreAuthReq; + uint16_t auth_req_len = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL == pSession) { + sms_log(pMac, LOGE, + FL("Session does not exist for session id(%d)"), + sessionId); + return CDF_STATUS_E_FAILURE; + } + + auth_req_len = sizeof(tSirFTPreAuthReq); + pftPreAuthReq = (tpSirFTPreAuthReq) cdf_mem_malloc(auth_req_len); + if (NULL == pftPreAuthReq) { + sms_log(pMac, LOGE, + FL("Memory allocation for FT Preauth request failed")); + return CDF_STATUS_E_NOMEM; + } + /* Save the SME Session ID here. We need it while processing the preauth response */ + pSession->ftSmeContext.smeSessionId = sessionId; + cdf_mem_zero(pftPreAuthReq, auth_req_len); + + pftPreAuthReq->pbssDescription = + (tpSirBssDescription) cdf_mem_malloc(sizeof(pBssDescription->length) + + pBssDescription->length); + if (NULL == pftPreAuthReq->pbssDescription) { + sms_log(pMac, LOGE, + FL("Memory allocation for FT Preauth request failed")); + return CDF_STATUS_E_NOMEM; + } + + pftPreAuthReq->messageType = eWNI_SME_FT_PRE_AUTH_REQ; + + pftPreAuthReq->preAuthchannelNum = pBssDescription->channelId; + + cdf_mem_copy((void *)&pftPreAuthReq->currbssId, + (void *)pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy((void *)&pftPreAuthReq->preAuthbssId, + (void *)pBssDescription->bssId, sizeof(tSirMacAddr)); + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csr_roam_is11r_assoc(pMac, sessionId) && + (pMac->roam.roamSession[sessionId].connectedProfile.AuthType != + eCSR_AUTH_TYPE_OPEN_SYSTEM)) { + pftPreAuthReq->ft_ies_length = + (uint16_t) pSession->ftSmeContext.auth_ft_ies_length; + cdf_mem_copy(pftPreAuthReq->ft_ies, + pSession->ftSmeContext.auth_ft_ies, + pSession->ftSmeContext.auth_ft_ies_length); + } else +#endif + { + pftPreAuthReq->ft_ies_length = 0; + } + cdf_mem_copy(pftPreAuthReq->pbssDescription, pBssDescription, + sizeof(pBssDescription->length) + pBssDescription->length); + pftPreAuthReq->length = auth_req_len; + return cds_send_mb_message_to_mac(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 csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, + tpSirFTPreAuthRsp pFTPreAuthRsp) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; +#if defined(FEATURE_WLAN_LFR) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + tCsrRoamInfo roamInfo; +#endif + eCsrAuthType conn_Auth_type; + uint32_t sessionId = pFTPreAuthRsp->smeSessionId; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return; + } +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING + status = + csr_neighbor_roam_preauth_rsp_handler(pMac, pFTPreAuthRsp->smeSessionId, + pFTPreAuthRsp->status); + if (status != CDF_STATUS_SUCCESS) { + /* + * Bail out if pre-auth was not even processed. + */ + sms_log(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 (CDF_STATUS_SUCCESS != (CDF_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 (csr_roam_is11r_assoc(pMac, pFTPreAuthRsp->smeSessionId) +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) + || csr_roam_is_ese_assoc(pMac, pFTPreAuthRsp->smeSessionId) +#endif + ) { + sme_qos_csr_event_ind(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 = + cdf_mc_timer_start(&pSession->ftSmeContext.preAuthReassocIntvlTimer, + 60); + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, + FL + ("Preauth reassoc interval timer start failed to start with status %d"), + status); + return; + } + /* Save the received response */ + cdf_mem_copy((void *)&pSession->ftSmeContext.preAuthbssId, + (void *)pFTPreAuthRsp->preAuthbssId, sizeof(struct cdf_mac_addr)); + if (csr_roam_is11r_assoc(pMac, pFTPreAuthRsp->smeSessionId)) + csr_roam_call_callback(pMac, pFTPreAuthRsp->smeSessionId, NULL, 0, + eCSR_ROAM_FT_RESPONSE, + eCSR_ROAM_RESULT_NONE); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + if (csr_roam_is_ese_assoc(pMac, pFTPreAuthRsp->smeSessionId)) { + /* read TSF */ + csr_roam_read_tsf(pMac, (uint8_t *) roamInfo.timestamp, + pFTPreAuthRsp->smeSessionId); + /* Save the bssid from the received response */ + cdf_mem_copy((void *)&roamInfo.bssid, + (void *)pFTPreAuthRsp->preAuthbssId, + sizeof(struct cdf_mac_addr)); + csr_roam_call_callback(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 (csr_roam_is_fast_roam_enabled(pMac, pFTPreAuthRsp->smeSessionId)) { + /* Save the bssid from the received response */ + cdf_mem_copy((void *)&roamInfo.bssid, + (void *)pFTPreAuthRsp->preAuthbssId, + sizeof(struct cdf_mac_addr)); + csr_roam_call_callback(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; + if (csr_roam_is11r_assoc(pMac, pFTPreAuthRsp->smeSessionId) && + (conn_Auth_type == eCSR_AUTH_TYPE_OPEN_SYSTEM)) { + uint16_t ft_ies_length; + ft_ies_length = pFTPreAuthRsp->ric_ies_length; + + if ((pSession->ftSmeContext.reassoc_ft_ies) && + (pSession->ftSmeContext.reassoc_ft_ies_length)) { + cdf_mem_free(pSession->ftSmeContext.reassoc_ft_ies); + pSession->ftSmeContext.reassoc_ft_ies_length = 0; + pSession->ftSmeContext.reassoc_ft_ies = NULL; + } + + pSession->ftSmeContext.reassoc_ft_ies = + cdf_mem_malloc(ft_ies_length); + if (NULL == pSession->ftSmeContext.reassoc_ft_ies) { + sms_log(pMac, LOGE, + FL("Memory allocation failed for ft_ies")); + return; + } else { + /* Copy the RIC IEs to reassoc IEs */ + cdf_mem_copy(((uint8_t *) pSession->ftSmeContext. + reassoc_ft_ies), + (uint8_t *) pFTPreAuthRsp->ric_ies, + pFTPreAuthRsp->ric_ies_length); + pSession->ftSmeContext.reassoc_ft_ies_length = + ft_ies_length; + pSession->ftSmeContext.addMDIE = true; + } + } + /* Done with it, init it. */ + pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; +} +#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 (uint16_t) + reasonCode - 4 bytes (sizeof(tSirResultCodes)) + peerMacAddr - 6 bytes + The rest is conditionally defined of (WNI_POLARIS_FW_PRODUCT == AP) and not used + */ +static void csr_ser_des_unpack_diassoc_rsp(uint8_t *pBuf, tSirSmeDisassocRsp *pRsp) +{ + if (pBuf && pRsp) { + pBuf += 4; /* skip type and length */ + pRsp->sessionId = *pBuf++; + cdf_get_u16(pBuf, (uint16_t *) &pRsp->transactionId); + pBuf += 2; + cdf_get_u32(pBuf, (uint32_t *) &pRsp->statusCode); + pBuf += 4; + cdf_mem_copy(pRsp->peerMacAddr, pBuf, 6); + } +} + +/* Returns whether a session is in CDF_STA_MODE...or not */ +bool csr_roam_is_sta_mode(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = NULL; + pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL(" %s: session %d not found "), __func__, + sessionId); + return false; + } + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + sms_log(pMac, LOGE, FL(" %s: Inactive session"), __func__); + return false; + } + if (eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType) { + return 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 == CDF_STA_MODE) { + return true; + } else { + sms_log(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), + __func__); + return false; + } + } + + return false; +} + +CDF_STATUS csr_handoff_request(tpAniSirGlobal pMac, + uint8_t sessionId, + tCsrHandoffRequest *pHandoffInfo) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t msg; + + tAniHandoffReq *pMsg; + pMsg = cdf_mem_malloc(sizeof(tAniHandoffReq)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, + " csr_handoff_request: failed to allocate mem for req "); + return CDF_STATUS_E_NOMEM; + } + pMsg->msgType = eWNI_SME_HANDOFF_REQ; + pMsg->msgLen = (uint16_t) sizeof(tAniHandoffReq); + pMsg->sessionId = sessionId; + pMsg->channel = pHandoffInfo->channel; + pMsg->handoff_src = pHandoffInfo->src; + cdf_mem_copy(pMsg->bssid, pHandoffInfo->bssid.bytes, CDF_MAC_ADDR_SIZE); + msg.type = eWNI_SME_HANDOFF_REQ; + msg.bodyptr = pMsg; + msg.reserved = 0; + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME, &msg)) { + sms_log(pMac, LOGE, + " csr_handoff_request failed to post msg to self "); + cdf_mem_free((void *)pMsg); + status = CDF_STATUS_E_FAILURE; + } + return status; +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +/* --------------------------------------------------------------------------- + \fn csr_set_cckm_ie + \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 + -------------------------------------------------------------------------*/ +CDF_STATUS csr_set_cckm_ie(tpAniSirGlobal pMac, const uint8_t sessionId, + const uint8_t *pCckmIe, const uint8_t ccKmIeLen) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(pSession->suppCckmIeInfo.cckmIe, pCckmIe, ccKmIeLen); + pSession->suppCckmIeInfo.cckmIeLen = ccKmIeLen; + return status; +} + +/* --------------------------------------------------------------------------- + \fn csr_roam_read_tsf + \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 timestamp + \- return Success or failure + -------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_read_tsf(tpAniSirGlobal pMac, uint8_t *pTimestamp, + uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrNeighborRoamBSSInfo handoffNode; + uint32_t timer_diff = 0; + uint32_t timeStamp[2]; + tpSirBssDescription pBssDescription = NULL; + csr_neighbor_roam_get_handoff_ap_info(pMac, &handoffNode, sessionId); + pBssDescription = handoffNode.pBssDescription; + /* Get the time diff in milli seconds */ + timer_diff = + cdf_mc_timer_get_system_time() - pBssDescription->scanSysTimeMsec; + /* Convert msec to micro sec timer */ + timer_diff = (uint32_t) (timer_diff * SYSTEM_TIME_MSEC_TO_USEC); + timeStamp[0] = pBssDescription->timeStamp[0]; + timeStamp[1] = pBssDescription->timeStamp[1]; + update_cckmtsf(&(timeStamp[0]), &(timeStamp[1]), &timer_diff); + cdf_mem_copy(pTimestamp, (void *)&timeStamp[0], sizeof(uint32_t) * 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 + */ +CDF_STATUS +csr_roam_channel_change_req(tpAniSirGlobal pMac, struct cdf_mac_addr bssid, + uint8_t cbMode, tCsrRoamProfile *profile) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirChanChangeRequest *pMsg; + tCsrRoamStartBssParams param; + + csr_roam_get_bss_start_parms(pMac, profile, ¶m); + pMsg = cdf_mem_malloc(sizeof(tSirChanChangeRequest)); + if (!pMsg) { + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set((void *)pMsg, sizeof(tSirChanChangeRequest), 0); + + pMsg->messageType = eWNI_SME_CHANNEL_CHANGE_REQ; + pMsg->messageLen = sizeof(tSirChanChangeRequest); + pMsg->targetChannel = profile->ChannelInfo.ChannelList[0]; + pMsg->cbMode = cbMode; + pMsg->channel_width = profile->ch_params.ch_width; + pMsg->dot11mode = csr_translate_to_wni_cfg_dot11_mode(pMac, + pMac->roam.configParam.uCfgDot11Mode); + pMsg->center_freq_seg_0 = pMsg->targetChannel; + pMsg->center_freq_seg_1 = 0; + cdf_mem_copy(pMsg->bssid, bssid.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(&pMsg->operational_rateset, + ¶m.operationalRateSet, sizeof(pMsg->operational_rateset)); + cdf_mem_copy(&pMsg->extended_rateset, + ¶m.extendedRateSet, sizeof(pMsg->extended_rateset)); + status = cds_send_mb_message_to_mac(pMsg); + + return status; +} + +/* + * Post Beacon Tx Start request to LIM + * immediately after SAP CAC WAIT is + * completed without any RADAR indications. + */ +CDF_STATUS csr_roam_start_beacon_req(tpAniSirGlobal pMac, + struct cdf_mac_addr bssid, + uint8_t dfsCacWaitStatus) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirStartBeaconIndication *pMsg; + + pMsg = cdf_mem_malloc(sizeof(tSirStartBeaconIndication)); + + if (!pMsg) { + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set((void *)pMsg, sizeof(tSirStartBeaconIndication), 0); + pMsg->messageType = eWNI_SME_START_BEACON_REQ; + pMsg->messageLen = sizeof(tSirStartBeaconIndication); + pMsg->beaconStartStatus = dfsCacWaitStatus; + cdf_mem_copy(pMsg->bssid, bssid.bytes, CDF_MAC_ADDR_SIZE); + + status = cds_send_mb_message_to_mac(pMsg); + + return status; +} + +/*---------------------------------------------------------------------------- + \fn csr_roam_modify_add_ies + \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 + -----------------------------------------------------------------------------*/ +CDF_STATUS +csr_roam_modify_add_ies(tpAniSirGlobal pMac, + tSirModifyIE *pModifyIE, eUpdateIEsType updateType) +{ + tpSirModifyIEsInd pModifyAddIEInd = NULL; + uint8_t *pLocalBuffer = NULL; + CDF_STATUS status; + + /* following buffer will be freed by consumer (PE) */ + pLocalBuffer = cdf_mem_malloc(pModifyIE->ieBufferlength); + + if (NULL == pLocalBuffer) { + sms_log(pMac, LOGE, FL("Memory Allocation Failure!!!")); + return CDF_STATUS_E_NOMEM; + } + + pModifyAddIEInd = cdf_mem_malloc(sizeof(tSirModifyIEsInd)); + if (NULL == pModifyAddIEInd) { + sms_log(pMac, LOGE, FL("Memory Allocation Failure!!!")); + cdf_mem_free(pLocalBuffer); + return CDF_STATUS_E_NOMEM; + } + + /*copy the IE buffer */ + cdf_mem_copy(pLocalBuffer, pModifyIE->pIEBuffer, + pModifyIE->ieBufferlength); + cdf_mem_zero(pModifyAddIEInd, sizeof(tSirModifyIEsInd)); + + pModifyAddIEInd->msgType = eWNI_SME_MODIFY_ADDITIONAL_IES; + pModifyAddIEInd->msgLen = sizeof(tSirModifyIEsInd); + + cdf_mem_copy(pModifyAddIEInd->modifyIE.bssid, pModifyIE->bssid, + sizeof(tSirMacAddr)); + + pModifyAddIEInd->modifyIE.smeSessionId = pModifyIE->smeSessionId; + pModifyAddIEInd->modifyIE.notify = pModifyIE->notify; + pModifyAddIEInd->modifyIE.ieID = pModifyIE->ieID; + pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen; + pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer; + pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength; + + pModifyAddIEInd->updateType = updateType; + + status = cds_send_mb_message_to_mac(pModifyAddIEInd); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg" + "!!! status %d"), status); + cdf_mem_free(pLocalBuffer); + } + return status; +} + +/*---------------------------------------------------------------------------- + \fn csr_roam_update_add_ies + \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 + -----------------------------------------------------------------------------*/ +CDF_STATUS +csr_roam_update_add_ies(tpAniSirGlobal pMac, + tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType) +{ + tpSirUpdateIEsInd pUpdateAddIEs = NULL; + uint8_t *pLocalBuffer = NULL; + CDF_STATUS status; + + if (pUpdateIE->ieBufferlength != 0) { + /* Following buffer will be freed by consumer (PE) */ + pLocalBuffer = cdf_mem_malloc(pUpdateIE->ieBufferlength); + if (NULL == pLocalBuffer) { + sms_log(pMac, LOGE, FL("Memory Allocation Failure!!!")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(pLocalBuffer, pUpdateIE->pAdditionIEBuffer, + pUpdateIE->ieBufferlength); + } + + pUpdateAddIEs = cdf_mem_malloc(sizeof(tSirUpdateIEsInd)); + if (NULL == pUpdateAddIEs) { + sms_log(pMac, LOGE, FL("Memory Allocation Failure!!!")); + if (pLocalBuffer != NULL) { + cdf_mem_free(pLocalBuffer); + } + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(pUpdateAddIEs, sizeof(tSirUpdateIEsInd)); + + pUpdateAddIEs->msgType = eWNI_SME_UPDATE_ADDITIONAL_IES; + pUpdateAddIEs->msgLen = sizeof(tSirUpdateIEsInd); + + cdf_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 = cds_send_mb_message_to_mac(pUpdateAddIEs); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("Failed to send eWNI_SME_UPDATE_ADDTIONAL_IES msg" + "!!! status %d"), status); + cdf_mem_free(pLocalBuffer); + } + return status; +} + +/** + * csr_roam_send_chan_sw_ie_request() - Request to transmit CSA IE + * @mac_ctx: Global MAC context + * @bssid: BSSID + * @target_channel: Channel on which to send the IE + * @csa_ie_reqd: Include/Exclude CSA IE. + * @ch_bandwidth: Channel offset + * + * This function sends request to transmit channel switch announcement + * IE to lower layers + * + * Return: success or failure + **/ +CDF_STATUS +csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx, + struct cdf_mac_addr bssid, uint8_t target_channel, + uint8_t csa_ie_reqd, uint8_t ch_bandwidth) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirDfsCsaIeRequest *msg; + + msg = cdf_mem_malloc(sizeof(tSirDfsCsaIeRequest)); + if (!msg) { + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set((void *)msg, sizeof(tSirDfsCsaIeRequest), 0); + msg->msgType = eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ; + msg->msgLen = sizeof(tSirDfsCsaIeRequest); + + msg->targetChannel = target_channel; + msg->csaIeRequired = csa_ie_reqd; + cdf_mem_copy(msg->bssid, bssid.bytes, CDF_MAC_ADDR_SIZE); + msg->ch_bandwidth = ch_bandwidth; + + status = cds_send_mb_message_to_mac(msg); + + return status; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/*---------------------------------------------------------------------------- +* fn csr_process_roam_offload_synch_ind +* brief This will process the roam synch indication received from +* lower layers.This function also calls another API to +* parse the beacon IE and fill the appropriate fields +* param pMac - pMac global structure +* param pMsgBuf - Message buffer received from lower layers +* --------------------------------------------------------------------------*/ +void csr_process_roam_offload_synch_ind(tHalHandle hHal, + roam_offload_synch_ind *roam_synch_ind_ptr) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *session_ptr = NULL; + uint8_t session_id = roam_synch_ind_ptr->roamedVdevId; + session_ptr = CSR_GET_SESSION(pMac, roam_synch_ind_ptr->roamedVdevId); + if (!session_ptr) { + sms_log(pMac, LOGE, FL("LFR3: session %d not found "), + roam_synch_ind_ptr->roamedVdevId); + goto err_synch_rsp; + } + if (!CDF_IS_STATUS_SUCCESS(csr_scan_save_roam_offload_ap_to_scan_cache( + pMac, roam_synch_ind_ptr))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "fail to save roam offload AP to scan cache"); + goto err_synch_rsp; + } + session_ptr->roamOffloadSynchParams.rssi = roam_synch_ind_ptr->rssi; + session_ptr->roamOffloadSynchParams.roamReason = + roam_synch_ind_ptr->roamReason; + session_ptr->roamOffloadSynchParams.roamedVdevId = + roam_synch_ind_ptr->roamedVdevId; + cdf_mem_copy(session_ptr->roamOffloadSynchParams.bssid, + roam_synch_ind_ptr->bssId, sizeof(tSirMacAddr)); + session_ptr->roamOffloadSynchParams.txMgmtPower = + roam_synch_ind_ptr->txMgmtPower; + session_ptr->roamOffloadSynchParams.authStatus = + roam_synch_ind_ptr->authStatus; + session_ptr->roamOffloadSynchParams.bRoamSynchInProgress = true; + /*Save the BSS descriptor for later use*/ + session_ptr->roamOffloadSynchParams.bss_desc_ptr = + roam_synch_ind_ptr->bss_desc_ptr; + pMac->roam.reassocRespLen = roam_synch_ind_ptr->reassocRespLength; + pMac->roam.pReassocResp = + cdf_mem_malloc(pMac->roam.reassocRespLen); + if (NULL == pMac->roam.pReassocResp) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "Memory allocation for reassoc response failed"); + goto err_synch_rsp; + } + cdf_mem_copy(pMac->roam.pReassocResp, + (uint8_t *)roam_synch_ind_ptr + + roam_synch_ind_ptr->reassocRespOffset, + pMac->roam.reassocRespLen); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "LFR3:%s: the reassoc resp frame data:", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + pMac->roam.pReassocResp, pMac->roam.reassocRespLen); + + cdf_mem_copy(session_ptr->roamOffloadSynchParams.kck, + roam_synch_ind_ptr->kck, SIR_KCK_KEY_LEN); + cdf_mem_copy(session_ptr->roamOffloadSynchParams.kek, + roam_synch_ind_ptr->kek, SIR_KEK_KEY_LEN); + cdf_mem_copy(session_ptr->roamOffloadSynchParams.replay_ctr, + roam_synch_ind_ptr->replay_ctr, SIR_REPLAY_CTR_LEN); + if (CDF_STATUS_SUCCESS != csr_neighbor_roam_offload_update_preauth_list( + pMac, roam_synch_ind_ptr, session_id)) { + /** + *Bail out if Roam Offload Synch Response was not even handled. + **/ + sms_log(pMac, LOGE, FL("Roam Offload Synch Response " + "was not processed")); + goto err_synch_rsp; + } + + csr_neighbor_roam_request_handoff(pMac, session_id); + +err_synch_rsp: + cdf_mem_free(roam_synch_ind_ptr->bss_desc_ptr); + roam_synch_ind_ptr->bss_desc_ptr = NULL; +} + +/*---------------------------------------------------------------------------- +* fn csr_process_ho_fail_ind +* 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 csr_process_ho_fail_ind(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tSirSmeHOFailureInd *pSmeHOFailInd = (tSirSmeHOFailureInd *) pMsgBuf; + uint32_t sessionId; + + if (pSmeHOFailInd) + sessionId = pSmeHOFailInd->sessionId; + else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "LFR3: Hand-Off Failure Ind is NULL"); + return; + } + /* Roaming is supported only on Infra STA Mode. */ + if (!csr_roam_is_sta_mode(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "LFR3:HO Fail cannot be handled for session %d", + sessionId); + return; + } + csr_roam_synch_clean_up(pMac, sessionId); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "LFR3:Issue Disconnect on session %d", sessionId); + csr_roam_disconnect(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +/** + * csr_update_op_class_array() - update op class for each band + * @mac_ctx: mac global context + * @op_classes: out param, operating class array to update + * @channel_info: channel info + * @ch_name: channel band name to display in debug messages + * @i: out param, stores number of operating classes + * + * Return: void + */ +static void +csr_update_op_class_array(tpAniSirGlobal mac_ctx, + uint8_t *op_classes, + tCsrChannel *channel_info, + char *ch_name, + uint8_t *i) +{ + uint8_t j = 0, idx = 0, class = 0; + bool found = false; + uint8_t num_channels = channel_info->numChannels; + + sms_log(mac_ctx, LOG1, + FL("Num of %s channels, %d"), + ch_name, num_channels); + + for (idx = 0; idx < num_channels + && *i < (SIR_MAC_MAX_SUPP_OPER_CLASSES - 1); idx++) { + class = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel_info->channelList[idx], + BWALL); + sms_log(mac_ctx, LOG4, FL("for chan %d, op class: %d"), + channel_info->channelList[idx], class); + + found = false; + for (j = 0; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; j++) { + if (op_classes[j] == class) { + found = true; + break; + } + } + if (!found) { + op_classes[*i] = class; + *i = *i + 1; + } + } +} + +/** + * csr_update_op_class_array() - update op class for all bands + * @hHal: global hal context + * + * Return: void + */ +void csr_init_operating_classes(tHalHandle hHal) +{ + uint8_t i = 0; + uint8_t j = 0; + uint8_t swap = 0; + uint8_t numClasses = 0; + uint8_t opClasses[SIR_MAC_MAX_SUPP_OPER_CLASSES] = {0,}; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + sms_log(pMac, LOG1, FL("Current Country = %c%c"), + pMac->scan.countryCodeCurrent[0], + pMac->scan.countryCodeCurrent[1]); + + csr_update_op_class_array(pMac, opClasses, + &pMac->scan.base_channels, "20MHz", &i); + csr_update_op_class_array(pMac, opClasses, + &pMac->scan.base40MHzChannels, "40MHz", &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; + } + } + } + + sms_log(pMac, LOG1, FL("Number of unique supported op classes %d"), + numClasses); + for (i = 0; i < numClasses; i++) { + sms_log(pMac, LOG1, FL("supported opClasses[%d] = %d"), i, + opClasses[i]); + } + + /* Set the ordered list of op classes in regdomain + * for use by other modules + */ + cds_regdm_set_curr_opclasses(numClasses, &opClasses[0]); +} + +/** + * csr_find_session_by_type() - This function will find given session type from + * all sessions. + * @mac_ctx: pointer to mac context. + * @type: session type + * + * Return: session id for give session type. + **/ +static uint32_t +csr_find_session_by_type(tpAniSirGlobal mac_ctx, tCDF_CON_MODE type) +{ + 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)) + continue; + + session_ptr = CSR_GET_SESSION(mac_ctx, i); + if (type == session_ptr->bssParams.bssPersona) { + 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("channel is zero, connection not allowed")); + + return false; + } + + sap_session_id = csr_find_session_by_type(mac_ctx, CDF_SAP_MODE); + 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)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Can't allow STA to connect, chnls 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("channel is zero, connection not allowed")); + return false; + } + + p2pgo_session_id = csr_find_session_by_type(mac_ctx, CDF_P2P_GO_MODE); + 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)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Can't allow STA to connect, chnls 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) { + csr_scan_result_purge(mac_ctx, + sta_session->stored_roam_profile.bsslist_handle); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; + csr_release_profile(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; + csr_roam_copy_profile(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: CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE. + **/ +CDF_STATUS csr_issue_stored_joinreq(tpAniSirGlobal mac_ctx, + uint32_t *roam_id, + uint32_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *sta_session; + uint32_t new_roam_id; + + sta_session = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == sta_session) + return CDF_STATUS_E_FAILURE; + new_roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam); + *roam_id = new_roam_id; + status = csr_roam_issue_connect(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 (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("CSR failed issuing connect cmd with status = 0x%08X"), + status); + csr_clear_joinreq_param(mac_ctx, session_id); + } + return status; +} + +/** + * csr_process_set_hw_mode() - Set HW mode command to PE + * @mac: Globacl MAC pointer + * @command: Command received from SME + * + * Posts the set HW mode command to PE. This message passing + * through PE is required for PE's internal management + * + * Return: None + */ +void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) +{ + uint32_t len; + struct s_sir_set_hw_mode *cmd; + CDF_STATUS status; + tSirMsgQ msg; + struct sir_set_hw_mode_resp *param; + + /* Setting HW mode is for the entire system. + * So, no need to check session + */ + + if (!command) { + sms_log(mac, LOGE, FL("Set HW mode param is NULL")); + goto fail; + } + + len = sizeof(*cmd); + cmd = cdf_mem_malloc(len); + if (!cmd) { + sms_log(mac, LOGE, FL("Memory allocation failed")); + /* Probably the fail response will also fail during malloc. + * Still proceeding to send response! + */ + goto fail; + } + + cdf_mem_set(cmd, len, 0); + + cmd->messageType = eWNI_SME_SET_HW_MODE_REQ; + cmd->length = len; + cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index; + /* + * Below callback and context info are not needed for PE as of now. + * Storing the passed value in the same s_sir_set_hw_mode format. + */ + cmd->set_hw.set_hw_mode_cb = command->u.set_hw_mode_cmd.set_hw_mode_cb; + + sms_log(mac, LOG1, + FL("Posting eWNI_SME_SET_HW_MODE_REQ to PE")); + + status = cds_send_mb_message_to_mac(cmd); + if (CDF_STATUS_SUCCESS != status) { + sms_log(mac, LOGE, FL("Posting to PE failed")); + return; + } + return; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + sms_log(mac, LOGE, + FL("Malloc fail: Fail to send response to SME")); + return; + } + sms_log(mac, LOGE, FL("Sending set HW fail response to SME")); + param->status = SET_HW_MODE_STATUS_ECANCELED; + param->cfgd_hw_mode_index = 0; + param->num_vdev_mac_entries = 0; + msg.type = eWNI_SME_SET_HW_MODE_RESP; + msg.bodyptr = param; + msg.bodyval = 0; + sys_process_mmh_msg(mac, &msg); +} + +/** + * csr_process_set_dual_mac_config() - Set HW mode command to PE + * @mac: Global MAC pointer + * @command: Command received from SME + * + * Posts the set dual mac config command to PE. + * + * Return: None + */ +void csr_process_set_dual_mac_config(tpAniSirGlobal mac, tSmeCmd *command) +{ + uint32_t len; + struct sir_set_dual_mac_cfg *cmd; + CDF_STATUS status; + tSirMsgQ msg; + struct sir_dual_mac_config_resp *param; + + /* Setting MAC configuration is for the entire system. + * So, no need to check session + */ + + if (!command) { + sms_log(mac, LOGE, FL("Set HW mode param is NULL")); + goto fail; + } + + len = sizeof(*cmd); + cmd = cdf_mem_malloc(len); + if (!cmd) { + sms_log(mac, LOGE, FL("Memory allocation failed")); + /* Probably the fail response will also fail during malloc. + * Still proceeding to send response! + */ + goto fail; + } + + cmd->message_type = eWNI_SME_SET_DUAL_MAC_CFG_REQ; + cmd->length = len; + cmd->set_dual_mac.scan_config = command->u.set_dual_mac_cmd.scan_config; + cmd->set_dual_mac.fw_mode_config = + command->u.set_dual_mac_cmd.fw_mode_config; + /* + * Below callback and context info are not needed for PE as of now. + * Storing the passed value in the same sir_set_dual_mac_cfg format. + */ + cmd->set_dual_mac.set_dual_mac_cb = + command->u.set_dual_mac_cmd.set_dual_mac_cb; + + sms_log(mac, LOG1, + FL("Posting eWNI_SME_SET_DUAL_MAC_CFG_REQ to PE: %x %x"), + cmd->set_dual_mac.scan_config, + cmd->set_dual_mac.fw_mode_config); + + status = cds_send_mb_message_to_mac(cmd); + if (CDF_STATUS_SUCCESS != status) { + sms_log(mac, LOGE, FL("Posting to PE failed")); + return; + } + return; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + sms_log(mac, LOGE, + FL("Malloc fail: Fail to send response to SME")); + return; + } + sms_log(mac, LOGE, FL("Sending set dual mac fail response to SME")); + param->status = SET_HW_MODE_STATUS_ECANCELED; + msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP; + msg.bodyptr = param; + msg.bodyval = 0; + sys_process_mmh_msg(mac, &msg); +} + +/** + * csr_process_nss_update_req() - Update nss command to PE + * @mac: Globacl MAC pointer + * @command: Command received from SME + * + * Posts the nss update command to PE. This message passing + * through PE is required for PE's internal management + * + * Return: None + */ +void csr_process_nss_update_req(tpAniSirGlobal mac, tSmeCmd *command) +{ + uint32_t len; + struct sir_nss_update_request *msg; + CDF_STATUS status; + tSirMsgQ msg_return; + struct sir_beacon_tx_complete_rsp *param; + + tCsrRoamSession *session = + CSR_GET_SESSION(mac, command->sessionId); + + if (!session) { + sms_log(mac, LOGE, FL("Session not found")); + goto fail; + } + + if (!command) { + sms_log(mac, LOGE, FL("nss update param is NULL")); + goto fail; + } + + len = sizeof(*msg); + msg = cdf_mem_malloc(len); + if (!msg) { + sms_log(mac, LOGE, FL("Memory allocation failed")); + /* Probably the fail response is also fail during malloc. + * Still proceeding to send response! + */ + goto fail; + } + + cdf_mem_set((void *)msg, sizeof(*msg), 0); + msg->msgType = eWNI_SME_NSS_UPDATE_REQ; + msg->msgLen = sizeof(*msg); + + msg->new_nss = command->u.nss_update_cmd.new_nss; + msg->vdev_id = command->u.nss_update_cmd.session_id; + + sms_log(mac, LOG1, + FL("Posting eWNI_SME_NSS_UPDATE_REQ to PE")); + + status = cds_send_mb_message_to_mac(msg); + if (CDF_STATUS_SUCCESS != status) { + sms_log(mac, LOGE, FL("Posting to PE failed")); + return; + } + return; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + sms_log(mac, LOGE, + FL("Malloc fail: Fail to send response to SME")); + return; + } + sms_log(mac, LOGE, FL("Sending nss update fail response to SME")); + param->tx_status = CDF_STATUS_E_FAILURE; + param->session_id = command->u.nss_update_cmd.session_id; + msg_return.type = eWNI_SME_NSS_UPDATE_RSP; + msg_return.bodyptr = param; + msg_return.bodyval = 0; + sys_process_mmh_msg(mac, &msg_return); +} diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c new file mode 100644 index 000000000000..68f0aeeef874 --- /dev/null +++ b/core/sme/src/csr/csr_api_scan.c @@ -0,0 +1,6941 @@ +/* + * 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 csr_api_scan.c + + Implementation for the Common Scan interfaces. + ========================================================================== */ + +#include "ani_global.h" + +#include "cds_mq.h" +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "sms_debug.h" + +#include "csr_support.h" + +#include "host_diag_core_log.h" +#include "host_diag_core_event.h" + +#include "cds_reg_service.h" +#include "wma_types.h" +#include "cds_utils.h" +#include "cfg_api.h" +#include "lim_api.h" +#include "wma.h" + +#include "cds_concurrency.h" +#include "wlan_hdd_main.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 initialsed 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) +#define CSR_SCAN_RESULT_RSSI_WEIGHT 80 /* must be less than 100, represent the persentage of new RSSI */ + +#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 PCL_ADVANTAGE 30 +#define PCL_RSSI_THRESHOLD -75 + +#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \ + ((pMac)->scan.nBssLimit <= (csr_ll_count(&(pMac)->scan.scanResultList))) + +void csr_scan_get_result_timer_handler(void *); +static void csr_scan_result_cfg_aging_timer_handler(void *pv); +static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType, + tCsrScanRequest *pScanRequest); +#ifdef WLAN_AP_STA_CONCURRENCY +static void csr_sta_ap_conc_timer_handler(void *); +#endif +bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId); +CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList, + uint8_t NumChannels); +void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList, + uint32_t cfgId); +void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode); +void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList); +void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrScanStatus scanStatus); +static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac, uint8_t *pChannels, + uint8_t numChn, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs **ppIes); +bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel); +void csr_prune_channel_list_for_mode(tpAniSirGlobal pMac, + tCsrChannel *pChannelList); + +#define CSR_IS_SOCIAL_CHANNEL(channel) \ + (((channel) == 1) || ((channel) == 6) || ((channel) == 11)) + +static void csr_release_scan_cmd_pending_list(tpAniSirGlobal pMac) +{ + tListElem *pEntry; + tSmeCmd *pCommand; + + while ((pEntry = + csr_ll_remove_head(&pMac->scan.scanCmdPendingList, + LL_ACCESS_LOCK)) != NULL) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCsrCommandMask & pCommand->command) { + csr_abort_command(pMac, pCommand, true); + } else { + sms_log(pMac, LOGE, FL("Error: Received command : %d"), + pCommand->command); + } + } +} + +/* pResult is invalid calling this function. */ +void csr_free_scan_result_entry(tpAniSirGlobal pMac, tCsrScanResult *pResult) +{ + if (NULL != pResult->Result.pvIes) { + cdf_mem_free(pResult->Result.pvIes); + } + cdf_mem_free(pResult); +} + +static CDF_STATUS csr_ll_scan_purge_result(tpAniSirGlobal pMac, + tDblLinkList *pList) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry; + tCsrScanResult *pBssDesc; + + csr_ll_lock(pList); + + while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + csr_free_scan_result_entry(pMac, pBssDesc); + } + + csr_ll_unlock(pList); + + return status; +} + +CDF_STATUS csr_scan_open(tpAniSirGlobal mac_ctx) +{ + CDF_STATUS status; + + csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanResultList); + csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.tempScanResults); + csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList24); + csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList5G); +#ifdef WLAN_AP_STA_CONCURRENCY + csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanCmdPendingList); +#endif + mac_ctx->scan.fFullScanIssued = false; + mac_ctx->scan.nBssLimit = CSR_MAX_BSS_SUPPORT; +#ifdef WLAN_AP_STA_CONCURRENCY + status = cdf_mc_timer_init(&mac_ctx->scan.hTimerStaApConcTimer, + CDF_TIMER_TYPE_SW, + csr_sta_ap_conc_timer_handler, + mac_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("Mem Alloc failed for hTimerStaApConcTimer timer")); + return status; + } +#endif + status = cdf_mc_timer_init(&mac_ctx->scan.hTimerResultCfgAging, + CDF_TIMER_TYPE_SW, + csr_scan_result_cfg_aging_timer_handler, + mac_ctx); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(mac_ctx, LOGE, + FL("Mem Alloc failed for CFG ResultAging timer")); + + return status; +} + +CDF_STATUS csr_scan_close(tpAniSirGlobal pMac) +{ + csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults); + csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList); +#ifdef WLAN_AP_STA_CONCURRENCY + csr_release_scan_cmd_pending_list(pMac); +#endif + csr_ll_close(&pMac->scan.scanResultList); + csr_ll_close(&pMac->scan.tempScanResults); +#ifdef WLAN_AP_STA_CONCURRENCY + csr_ll_close(&pMac->scan.scanCmdPendingList); +#endif + csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList24); + csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList5G); + csr_ll_close(&pMac->scan.channelPowerInfoList24); + csr_ll_close(&pMac->scan.channelPowerInfoList5G); + csr_scan_disable(pMac); + cdf_mc_timer_destroy(&pMac->scan.hTimerResultCfgAging); +#ifdef WLAN_AP_STA_CONCURRENCY + cdf_mc_timer_destroy(&pMac->scan.hTimerStaApConcTimer); +#endif + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_scan_enable(tpAniSirGlobal pMac) +{ + + pMac->scan.fScanEnable = true; + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_scan_disable(tpAniSirGlobal pMac) +{ + + csr_scan_stop_timers(pMac); + pMac->scan.fScanEnable = false; + + return CDF_STATUS_SUCCESS; +} + +/* Set scan timing parameters according to state of other driver sessions */ +/* No validation of the parameters is performed. */ +static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType, + tCsrScanRequest *pScanRequest) +{ +#ifdef WLAN_AP_STA_CONCURRENCY + if (csr_is_any_session_connected(pMac)) { + /* Reset passive scan time as per ini parameter. */ + cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pMac->roam.configParam.nPassiveMaxChnTimeConc); + /* 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->restTime = pMac->roam.configParam.nRestTimeConc; + + /* 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. */ + cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, + pMac->roam.configParam.nPassiveMaxChnTime); + 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; + } +#ifdef WLAN_AP_STA_CONCURRENCY + /* No rest time if no sessions are connected. */ + pScanRequest->restTime = 0; +#endif +} + +/** + * csr_scan_2g_only_request() - 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 CDF_STATUS +csr_scan_2g_only_request(tpAniSirGlobal mac_ctx, + tSmeCmd *scan_cmd, + tCsrScanRequest *scan_req) +{ + uint8_t idx, lst_sz = 0; + + CDF_ASSERT(scan_cmd && scan_req); + /* To silence the KW tool null check is added */ + if ((scan_cmd == NULL) || (scan_req == NULL)) { + sms_log(mac_ctx, LOGE, + FL(" Scan Cmd or Scan Request is NULL ")); + return CDF_STATUS_E_INVAL; + } + + if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType) + return CDF_STATUS_SUCCESS; + + sms_log(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 = + cdf_mem_malloc(NUM_24GHZ_CHANNELS); + if (NULL == scan_req->ChannelInfo.ChannelList) { + sms_log(mac_ctx, LOGE, FL("Memory allocation failed.")); + return CDF_STATUS_E_NOMEM; + } + for (idx = 1; idx <= NUM_24GHZ_CHANNELS; idx++) { + if (csr_is_supported_channel(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] <= + CDS_24_GHZ_CHANNEL_14 + && csr_is_supported_channel(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 CDF_STATUS_SUCCESS; +} + +static void +csr_set_scan_reason(tSmeCmd *scan_cmd, eCsrRequestType req_type) +{ + switch (req_type) { + case eCSR_SCAN_REQUEST_11D_SCAN: + scan_cmd->u.scanCmd.reason = eCsrScan11d1; + break; +#ifdef SOFTAP_CHANNEL_RANGE + case eCSR_SCAN_SOFTAP_CHANNEL_RANGE: +#endif + case eCSR_SCAN_REQUEST_FULL_SCAN: + case eCSR_SCAN_P2P_DISCOVERY: + scan_cmd->u.scanCmd.reason = eCsrScanUserRequest; + break; + case eCSR_SCAN_HO_PROBE_SCAN: + scan_cmd->u.scanCmd.reason = eCsrScanProbeBss; + break; + case eCSR_SCAN_P2P_FIND_PEER: + scan_cmd->u.scanCmd.reason = eCsrScanP2PFindPeer; + break; + default: + break; + } +} + +static CDF_STATUS +csr_issue_11d_scan(tpAniSirGlobal mac_ctx, tSmeCmd *scan_cmd, + tCsrScanRequest *scan_req, uint16_t session_id) +{ + CDF_STATUS status; + tSmeCmd *scan_11d_cmd = NULL; + tCsrScanRequest tmp_rq; + tCsrChannelInfo *pChnInfo = &tmp_rq.ChannelInfo; + uint32_t numChn = mac_ctx->scan.base_channels.numChannels; + tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, session_id); + + if (csr_session == NULL) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), + session_id); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + if (!(((false == mac_ctx->first_scan_done) + && (eCSR_SCAN_REQUEST_11D_SCAN != scan_req->requestType)) +#ifdef SOFTAP_CHANNEL_RANGE + && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != scan_req->requestType) +#endif + && (false == mac_ctx->scan.fEnableBypass11d))) + return CDF_STATUS_SUCCESS; + + cdf_mem_set(&tmp_rq, sizeof(tCsrScanRequest), 0); + scan_11d_cmd = csr_get_command_buffer(mac_ctx); + if (!scan_11d_cmd) { + sms_log(mac_ctx, LOGE, FL("scan_11d_cmd failed")); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_set(&scan_11d_cmd->u.scanCmd, sizeof(tScanCmd), 0); + pChnInfo->ChannelList = cdf_mem_malloc(numChn); + if (NULL == pChnInfo->ChannelList) { + sms_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(pChnInfo->ChannelList, + mac_ctx->scan.base_channels.channelList, numChn); + + pChnInfo->numOfChannels = (uint8_t) numChn; + scan_11d_cmd->command = eSmeCommandScan; + scan_11d_cmd->u.scanCmd.callback = mac_ctx->scan.callback11dScanDone; + scan_11d_cmd->u.scanCmd.pContext = NULL; + wma_get_scan_id(&scan_11d_cmd->u.scanCmd.scanID); + tmp_rq.BSSType = eCSR_BSS_TYPE_ANY; + tmp_rq.scan_id = scan_11d_cmd->u.scanCmd.scanID; + + status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, &scan_11d_cmd); + + if (csr_is11d_supported(mac_ctx)) { + tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan; + if (scan_req->bcnRptReqScan) + tmp_rq.scanType = scan_req->scanType ? + eSIR_PASSIVE_SCAN : scan_req->scanType; + else + tmp_rq.scanType = eSIR_PASSIVE_SCAN; + tmp_rq.requestType = eCSR_SCAN_REQUEST_11D_SCAN; + scan_11d_cmd->u.scanCmd.reason = eCsrScan11d1; + tmp_rq.maxChnTime = + mac_ctx->roam.configParam.nPassiveMaxChnTime; + tmp_rq.minChnTime = + mac_ctx->roam.configParam.nPassiveMinChnTime; + } else { + tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan; + if (scan_req->bcnRptReqScan) + tmp_rq.scanType = scan_req->scanType; + else + tmp_rq.scanType = eSIR_ACTIVE_SCAN; + tmp_rq.requestType = scan_req->requestType; + scan_11d_cmd->u.scanCmd.reason = scan_cmd->u.scanCmd.reason; + tmp_rq.maxChnTime = mac_ctx->roam.configParam.nActiveMaxChnTime; + tmp_rq.minChnTime = mac_ctx->roam.configParam.nActiveMinChnTime; + } + if (mac_ctx->roam.configParam.nInitialDwellTime) { + tmp_rq.maxChnTime = mac_ctx->roam.configParam.nInitialDwellTime; + sms_log(mac_ctx, LOG1, FL("11d scan, updating dwell time for first scan %u"), + tmp_rq.maxChnTime); + } + + status = csr_scan_copy_request(mac_ctx, + &scan_11d_cmd->u.scanCmd.u.scanRequest, &tmp_rq); + /* Free the channel list */ + cdf_mem_free(pChnInfo->ChannelList); + pChnInfo->ChannelList = NULL; + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("csr_scan_copy_request failed")); + return CDF_STATUS_E_FAILURE; + } + + mac_ctx->scan.scanProfile.numOfChannels = + scan_11d_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + + + status = csr_queue_sme_command(mac_ctx, scan_11d_cmd, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("Failed to send message status = %d"), + status); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_scan_request(tpAniSirGlobal pMac, uint16_t sessionId, + tCsrScanRequest *scan_req, + csr_scan_completeCallback callback, void *pContext) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tSmeCmd *scan_cmd = NULL; + tCsrScanRequest *pTempScanReq = NULL; + tCsrConfig *cfg_prm = &pMac->roam.configParam; + + if (scan_req == NULL) { + sms_log(pMac, LOGE, FL("scan_req is NULL")); + CDF_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 the scan request is for specific SSId the length of SSID will be + * greater than 7 as SSID for p2p search contains "DIRECT-") + */ + if (scan_req->p2pSearch + && scan_req->SSIDs.numOfSSIDs + && (NULL != scan_req->SSIDs.SSIDList) + && (scan_req->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN)) { + sms_log(pMac, LOG1, FL("P2P: Increasing the min and max Dwell time to %d for specific SSID scan %.*s"), + MAX_CHN_TIME_TO_FIND_GO, + scan_req->SSIDs.SSIDList->SSID.length, + scan_req->SSIDs.SSIDList->SSID.ssId); + scan_req->maxChnTime = MAX_CHN_TIME_TO_FIND_GO; + scan_req->minChnTime = MIN_CHN_TIME_TO_FIND_GO; + } + + if (!pMac->scan.fScanEnable) { + sms_log(pMac, LOGE, FL("SId: %d Scanning not enabled Scan type=%u, numOfSSIDs=%d P2P search=%d"), + sessionId, scan_req->requestType, + scan_req->SSIDs.numOfSSIDs, + scan_req->p2pSearch); + goto release_cmd; + } + + scan_cmd = csr_get_command_buffer(pMac); + if (!scan_cmd) { + sms_log(pMac, LOGE, FL("scan_cmd is NULL")); + goto release_cmd; + } + + cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0); + scan_cmd->command = eSmeCommandScan; + scan_cmd->sessionId = sessionId; + if (scan_cmd->sessionId >= CSR_ROAM_SESSION_MAX) + sms_log(pMac, LOGE, FL("Invalid Sme SessionID: %d"), sessionId); + scan_cmd->u.scanCmd.callback = callback; + scan_cmd->u.scanCmd.pContext = pContext; + csr_set_scan_reason(scan_cmd, scan_req->requestType); + if (scan_req->minChnTime == 0 && scan_req->maxChnTime == 0) { + /* The caller doesn't set the time correctly. Set it here */ + csr_set_default_scan_timing(pMac, scan_req->scanType, scan_req); + sms_log(pMac, LOG1, + FL("Setting default min %d and max %d ChnTime"), + scan_req->minChnTime, scan_req->maxChnTime); + } +#ifdef WLAN_AP_STA_CONCURRENCY + /* Need to set restTime only if at least one session is connected */ + if (scan_req->restTime == 0 && csr_is_any_session_connected(pMac)) { + scan_req->restTime = cfg_prm->nRestTimeConc; + if (scan_req->scanType == eSIR_ACTIVE_SCAN) { + scan_req->maxChnTime = cfg_prm->nActiveMaxChnTimeConc; + scan_req->minChnTime = cfg_prm->nActiveMinChnTimeConc; + } else { + scan_req->maxChnTime = cfg_prm->nPassiveMaxChnTimeConc; + scan_req->minChnTime = cfg_prm->nPassiveMinChnTimeConc; + } + } +#endif + /* Increase dwell time in case P2P Search and Miracast is not present */ + if (scan_req->p2pSearch && scan_req->ChannelInfo.numOfChannels + == P2P_SOCIAL_CHANNELS && (!(pMac->sme.miracast_value))) { + scan_req->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE; + } + scan_cmd->u.scanCmd.scanID = scan_req->scan_id; + /* + * 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. + */ + status = csr_issue_11d_scan(pMac, scan_cmd, scan_req, sessionId); + if (status != CDF_STATUS_SUCCESS) + goto release_cmd; + + /* + * 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) { + csr_scan_2g_only_request(pMac, scan_cmd, scan_req); + pMac->first_scan_done = true; + } + + + if (cfg_prm->nInitialDwellTime) { + scan_req->maxChnTime = cfg_prm->nInitialDwellTime; + cfg_prm->nInitialDwellTime = 0; + sms_log(pMac, LOG1, FL("updating dwell time for first scan %u"), + scan_req->maxChnTime); + } + + status = csr_scan_copy_request(pMac, &scan_cmd->u.scanCmd.u.scanRequest, + scan_req); + /* + * 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. + */ + cfg_prm->initial_scan_no_dfs_chnl = 0; + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("fail to copy request status = %d"), status); + goto release_cmd; + } + + pTempScanReq = &scan_cmd->u.scanCmd.u.scanRequest; + pMac->scan.scanProfile.numOfChannels = + pTempScanReq->ChannelInfo.numOfChannels; + status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, scan_cmd); + sms_log(pMac, LOG1, + FL("SId=%d scanId=%d Scan reason=%u numSSIDs=%d numChan=%d P2P search=%d minCT=%d maxCT=%d uIEFieldLen=%d"), + sessionId, scan_cmd->u.scanCmd.scanID, + scan_cmd->u.scanCmd.reason, pTempScanReq->SSIDs.numOfSSIDs, + pTempScanReq->ChannelInfo.numOfChannels, + pTempScanReq->p2pSearch, pTempScanReq->minChnTime, + pTempScanReq->maxChnTime, pTempScanReq->uIEFieldLen); + + status = csr_queue_sme_command(pMac, scan_cmd, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("fail to send message status = %d"), status); + } + +release_cmd: + if (!CDF_IS_STATUS_SUCCESS(status) && scan_cmd) { + sms_log(pMac, LOGE, FL(" SId: %d Failed with status=%d" + " Scan reason=%u numOfSSIDs=%d" + " P2P search=%d scanId=%d"), + sessionId, status, scan_cmd->u.scanCmd.reason, + scan_req->SSIDs.numOfSSIDs, scan_req->p2pSearch, + scan_cmd->u.scanCmd.scanID); + csr_release_command_scan(pMac, scan_cmd); + } + + return status; +} + +CDF_STATUS csr_issue_roam_after_lostlink_scan(tpAniSirGlobal pMac, + uint32_t sessionId, + eCsrRoamReason reason) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tScanResultHandle hBSSList = NULL; + tCsrScanResultFilter *pScanFilter = NULL; + uint32_t roamId = 0; + tCsrRoamProfile *pProfile = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG1, FL("Entry")); + if (pSession->fCancelRoaming) { + sms_log(pMac, LOGW, FL("lost link roaming canceled")); + status = CDF_STATUS_SUCCESS; + goto free_filter; + } + /* Here is the profile we need to connect to */ + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) { + status = CDF_STATUS_E_NOMEM; + goto free_filter; + } + cdf_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 csr_roam_issue_connect + */ + pProfile = cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (NULL == pProfile) { + status = CDF_STATUS_E_NOMEM; + goto free_filter; + } + cdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + status = csr_roam_copy_profile(pMac, pProfile, + pSession->pCurRoamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_filter; + status = csr_roam_prepare_filter_from_profile(pMac, pProfile, + pScanFilter); + } /* We have a profile */ + roamId = GET_NEXT_ROAM_ID(&pMac->roam); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_filter; + + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_filter; + + if (eCsrLostLink1 == reason) { + /* if possible put the last connected BSS in beginning */ + csr_move_bss_to_head_from_bssid(pMac, + &pSession->connectedProfile.bssid, hBSSList); + } + status = csr_roam_issue_connect(pMac, sessionId, pProfile, hBSSList, + reason, roamId, true, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_scan_result_purge(pMac, hBSSList); + } + +free_filter: + if (pScanFilter) { + /* we need to free memory for filter if profile exists */ + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + } + if (NULL != pProfile) { + csr_release_profile(pMac, pProfile); + cdf_mem_free(pProfile); + } + return status; +} + +CDF_STATUS csr_scan_handle_failed_lostlink1(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + sms_log(pMac, LOGW, "Lost link scan 1 failed"); + if (pSession->fCancelRoaming) + return CDF_STATUS_E_FAILURE; + if (!pSession->pCurRoamProfile) + return csr_scan_request_lost_link3(pMac, sessionId); + /* + * 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 lostlink scan2 */ + return csr_scan_request_lost_link2(pMac, sessionId); + if (!pSession->pCurRoamProfile->ChannelInfo.ChannelList + || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) { + /* go straight to lostlink scan3 */ + return csr_scan_request_lost_link3(pMac, sessionId); + } + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_scan_handle_failed_lostlink2(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, "Lost link scan 2 failed"); + if (pSession->fCancelRoaming) + return CDF_STATUS_E_FAILURE; + + if (!pSession->pCurRoamProfile + || !pSession->pCurRoamProfile->ChannelInfo.ChannelList + || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) { + /* try lostlink scan3 */ + return csr_scan_request_lost_link3(pMac, sessionId); + } + return CDF_STATUS_E_FAILURE; +} + +CDF_STATUS csr_scan_handle_failed_lostlink3(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + sms_log(pMac, LOGW, "Lost link scan 3 failed"); + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS +csr_update_lost_link1_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, + tCsrRoamSession *pSession, uint32_t session_id) +{ + uint8_t i, num_ch = 0; + tScanResultHandle bss_lst = NULL; + tCsrScanResultInfo *scan_result = NULL; + tCsrScanResultFilter *scan_filter = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrSSIDs *ssid_list = &cmd->u.scanCmd.u.scanRequest.SSIDs; + tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo; + + cmd->command = eSmeCommandScan; + cmd->sessionId = (uint8_t) session_id; + cmd->u.scanCmd.reason = eCsrScanLostLink1; + cmd->u.scanCmd.callback = NULL; + cmd->u.scanCmd.pContext = NULL; + cmd->u.scanCmd.u.scanRequest.maxChnTime = + mac_ctx->roam.configParam.nActiveMaxChnTime; + cmd->u.scanCmd.u.scanRequest.minChnTime = + mac_ctx->roam.configParam.nActiveMinChnTime; + cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + wma_get_scan_id(&cmd->u.scanCmd.scanID); + status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, &cmd); + cmd->u.scanCmd.u.scanRequest.scan_id = + cmd->u.scanCmd.scanID; + + if (pSession->connectedProfile.SSID.length) { + /* + * on error: following memory will be released by call to + * csr_release_command_scan in the end + */ + ssid_list->SSIDList = cdf_mem_malloc(sizeof(tCsrSSIDInfo)); + if (NULL == ssid_list->SSIDList) + return CDF_STATUS_E_NOMEM; + ssid_list->numOfSSIDs = 1; + cdf_mem_copy(&ssid_list->SSIDList[0].SSID, + &pSession->connectedProfile.SSID, + sizeof(tSirMacSSid)); + } else { + ssid_list->numOfSSIDs = 0; + } + + if (!pSession->pCurRoamProfile) + return CDF_STATUS_SUCCESS; + + scan_filter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == scan_filter) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0); + status = csr_roam_prepare_filter_from_profile(mac_ctx, + pSession->pCurRoamProfile, scan_filter); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_lost_link1_local_mem; + + if (!(CDF_IS_STATUS_SUCCESS(csr_scan_get_result(mac_ctx, scan_filter, + &bss_lst)) && bss_lst)) { + if (csr_roam_is_channel_valid(mac_ctx, + pSession->connectedProfile.operationChannel)) { + ch_info->ChannelList = cdf_mem_malloc(1); + if (NULL == ch_info->ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto free_lost_link1_local_mem; + } + ch_info->ChannelList[0] = + pSession->connectedProfile.operationChannel; + ch_info->numOfChannels = 1; + } + return status; + } + + /* on error: this mem will be released by csr_release_command_scan */ + ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (NULL == ch_info->ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto free_lost_link1_local_mem; + } + + scan_result = csr_scan_result_get_next(mac_ctx, bss_lst); + while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) { + for (i = 0; i < num_ch; i++) { + if (ch_info->ChannelList[i] == + scan_result->BssDescriptor.channelId) + break; + } + if (i == num_ch) + ch_info->ChannelList[num_ch++] = + scan_result->BssDescriptor.channelId; + scan_result = csr_scan_result_get_next(mac_ctx, bss_lst); + } + /* Include the last connected BSS' channel */ + if (csr_roam_is_channel_valid(mac_ctx, + pSession->connectedProfile.operationChannel)) { + for (i = 0; i < num_ch; i++) { + if (ch_info->ChannelList[i] == + pSession->connectedProfile.operationChannel) + break; + } + if (i == num_ch) + ch_info->ChannelList[num_ch++] = + pSession->connectedProfile.operationChannel; + } + ch_info->numOfChannels = num_ch; +free_lost_link1_local_mem: + if (scan_filter) { + csr_free_scan_filter(mac_ctx, scan_filter); + cdf_mem_free(scan_filter); + } + if (bss_lst) + csr_scan_result_purge(mac_ctx, bss_lst); + return status; +} + +/** + * csr_scan_request_lost_link1() - start scan on link lost 1 + * @mac_ctx: mac global context + * @session_id: session id + * + * 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 + * + * Return: status of operation + */ +CDF_STATUS +csr_scan_request_lost_link1(tpAniSirGlobal mac_ctx, uint32_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *cmd = NULL; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id); + return CDF_STATUS_E_FAILURE; + } + + sms_log(mac_ctx, LOGW, FL("Entry")); + cmd = csr_get_command_buffer(mac_ctx); + if (!cmd) { + status = CDF_STATUS_E_RESOURCES; + goto release_lost_link1_cmd; + } + cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0); + status = csr_update_lost_link1_cmd(mac_ctx, cmd, session, session_id); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto release_lost_link1_cmd; + + cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid, + sizeof(struct cdf_mac_addr), 0xFF); + status = csr_queue_sme_command(mac_ctx, cmd, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("fail to send message status = %d"), status); + } + +release_lost_link1_cmd: + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGW, FL("failed with status %d"), status); + if (cmd) + csr_release_command_scan(mac_ctx, cmd); + status = csr_scan_handle_failed_lostlink1(mac_ctx, session_id); + } + return status; +} + +static CDF_STATUS +csr_update_lost_link2_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, + uint32_t session_id, tCsrRoamSession *session) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t i, num_ch = 0; + tScanResultHandle bss_lst = NULL; + tCsrScanResultInfo *scan_result = NULL; + tCsrScanResultFilter *scan_fltr = NULL; + tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo; + + cmd->command = eSmeCommandScan; + cmd->sessionId = (uint8_t) session_id; + cmd->u.scanCmd.reason = eCsrScanLostLink2; + cmd->u.scanCmd.callback = NULL; + cmd->u.scanCmd.pContext = NULL; + cmd->u.scanCmd.u.scanRequest.maxChnTime = + mac_ctx->roam.configParam.nActiveMaxChnTime; + cmd->u.scanCmd.u.scanRequest.minChnTime = + mac_ctx->roam.configParam.nActiveMinChnTime; + cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + wma_get_scan_id(&cmd->u.scanCmd.scanID); + cmd->u.scanCmd.u.scanRequest.scan_id = + cmd->u.scanCmd.scanID; + if (!session->pCurRoamProfile) + return CDF_STATUS_SUCCESS; + status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, &cmd); + scan_fltr = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == scan_fltr) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(scan_fltr, sizeof(tCsrScanResultFilter), 0); + status = csr_roam_prepare_filter_from_profile(mac_ctx, + session->pCurRoamProfile, scan_fltr); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_lost_link2_local_mem; + + status = csr_scan_get_result(mac_ctx, scan_fltr, &bss_lst); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_lost_link2_local_mem; + + if (!bss_lst) + goto free_lost_link2_local_mem; + + ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (NULL == ch_info->ChannelList) { + status = CDF_STATUS_E_NOMEM; + goto free_lost_link2_local_mem; + } + scan_result = csr_scan_result_get_next(mac_ctx, bss_lst); + while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) { + for (i = 0; i < num_ch; i++) { + if (ch_info->ChannelList[i] == + scan_result->BssDescriptor.channelId) + break; + } + if (i == num_ch) + ch_info->ChannelList[num_ch++] = + scan_result->BssDescriptor.channelId; + scan_result = csr_scan_result_get_next(mac_ctx, bss_lst); + } + ch_info->numOfChannels = num_ch; + +free_lost_link2_local_mem: + if (scan_fltr) { + csr_free_scan_filter(mac_ctx, scan_fltr); + cdf_mem_free(scan_fltr); + } + if (bss_lst) + csr_scan_result_purge(mac_ctx, bss_lst); + return status; +} + +/** + * csr_scan_request_lost_link2() - start scan on link lost 2 + * @mac_ctx: mac global context + * @session_id: session id + * + * 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 + * + * Return: status of operation + */ +CDF_STATUS +csr_scan_request_lost_link2(tpAniSirGlobal mac_ctx, uint32_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *cmd = NULL; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id); + return CDF_STATUS_E_FAILURE; + } + + sms_log(mac_ctx, LOGW, FL(" called")); + cmd = csr_get_command_buffer(mac_ctx); + if (!cmd) { + status = CDF_STATUS_E_RESOURCES; + goto release_lost_link2_cmd; + } + cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0); + status = csr_update_lost_link2_cmd(mac_ctx, cmd, session_id, session); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto release_lost_link2_cmd; + + cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid, + sizeof(struct cdf_mac_addr), 0xFF); + /* Put to the head in pending queue */ + status = csr_queue_sme_command(mac_ctx, cmd, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("fail to send message status = %d"), status); + goto release_lost_link2_cmd; + } + +release_lost_link2_cmd: + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGW, FL("failed with status %d"), status); + if (cmd) + csr_release_command_scan(mac_ctx, cmd); + status = csr_scan_handle_failed_lostlink2(mac_ctx, session_id); + } + return status; +} + +/** + * csr_scan_request_lost_link3() - To actively scan all valid channels + * @mac_ctx: mac global context + * @session_id: session id + * + * Return: status of operation + */ +CDF_STATUS +csr_scan_request_lost_link3(tpAniSirGlobal mac_ctx, uint32_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSmeCmd *cmd; + + sms_log(mac_ctx, LOGW, FL(" called")); + do { + cmd = csr_get_command_buffer(mac_ctx); + if (!cmd) { + status = CDF_STATUS_E_RESOURCES; + break; + } + cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0); + cmd->command = eSmeCommandScan; + cmd->sessionId = (uint8_t) session_id; + cmd->u.scanCmd.reason = eCsrScanLostLink3; + cmd->u.scanCmd.callback = NULL; + cmd->u.scanCmd.pContext = NULL; + cmd->u.scanCmd.u.scanRequest.maxChnTime = + mac_ctx->roam.configParam.nActiveMaxChnTime; + cmd->u.scanCmd.u.scanRequest.minChnTime = + mac_ctx->roam.configParam.nActiveMinChnTime; + cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; + wma_get_scan_id(&cmd->u.scanCmd.scanID); + status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, &cmd); + cmd->u.scanCmd.u.scanRequest.scan_id = + cmd->u.scanCmd.scanID; + cdf_set_macaddr_broadcast(&cmd->u.scanCmd.u.scanRequest.bssid); + /* Put to the head of pending queue */ + status = csr_queue_sme_command(mac_ctx, cmd, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("fail to send message status = %d"), status); + break; + } + } while (0); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGW, FL("failed with status %d"), status); + if (cmd) + csr_release_command_scan(mac_ctx, cmd); + } + + return status; +} + +CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE; + tCsrScanResultFilter *pScanFilter = NULL; + tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; + uint32_t sessionId = pCommand->sessionId; + + do { + /* If this scan is for LFR */ + if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { + /* notify LFR state m/c */ + status = csr_neighbor_roam_sssid_scan_done(pMac, + sessionId, CDF_STATUS_SUCCESS); + if (CDF_STATUS_SUCCESS != status) + csr_neighbor_roam_start_lfr_scan(pMac, + sessionId); + status = CDF_STATUS_SUCCESS; + break; + } + /* + * If there is roam command waiting, ignore this roam because + * the newer roam command is the one to execute + */ + if (csr_is_roam_command_waiting_for_session(pMac, sessionId)) { + sms_log(pMac, LOGW, + FL("aborts because roam command waiting")); + break; + } + if (pProfile == NULL) + break; + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) { + status = CDF_STATUS_E_NOMEM; + break; + } + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + status = csr_roam_prepare_filter_from_profile(pMac, pProfile, + pScanFilter); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + status = csr_roam_issue_connect(pMac, sessionId, pProfile, + hBSSList, eCsrHddIssued, + pCommand->u.scanCmd.roamId, + true, true); + } while (0); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + if (CSR_INVALID_SCANRESULT_HANDLE != hBSSList) { + csr_scan_result_purge(pMac, hBSSList); + } + /* We haven't done anything to this profile */ + csr_roam_call_callback(pMac, sessionId, NULL, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, + eCSR_ROAM_RESULT_FAILURE); + } + if (pScanFilter) { + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + } + return status; +} + +CDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal pMac, + tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t sessionId = pCommand->sessionId; + tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + eCsrRoamResult roam_result; + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + /* If this scan is for LFR */ + if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) { + /* notify LFR state m/c */ + status = csr_neighbor_roam_sssid_scan_done(pMac, sessionId, + CDF_STATUS_E_FAILURE); + if (CDF_STATUS_SUCCESS != status) + csr_neighbor_roam_start_lfr_scan(pMac, sessionId); + return CDF_STATUS_SUCCESS; + } +#ifdef WLAN_DEBUG + if (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) { + char str[36]; + tSirMacSSid *ptr_ssid = + &pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID; + cdf_mem_copy(str, ptr_ssid->ssId, ptr_ssid->length); + str[ptr_ssid->length] = 0; + sms_log(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 = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL, + eCsrHddIssued, pCommand->u.scanCmd.roamId, + true, true); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("failed to issue startIBSS, status: 0x%08X"), + status); + csr_roam_call_callback(pMac, sessionId, NULL, + pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED, + eCSR_ROAM_RESULT_FAILURE); + } + return status; + } + roam_result = eCSR_ROAM_RESULT_FAILURE; + if (NULL != pProfile && csr_is_bss_type_ibss(pProfile->BSSType)) { + roam_result = eCSR_ROAM_RESULT_IBSS_START_FAILED; + goto roam_completion; + } + /* Only indicate assoc_completion if we indicate assoc_start. */ + if (pSession->bRefAssocStartCnt > 0) { + tCsrRoamInfo *pRoamInfo = NULL, roamInfo; + + cdf_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--; + csr_roam_call_callback(pMac, sessionId, pRoamInfo, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_COMPLETION, + eCSR_ROAM_RESULT_FAILURE); + } else { + csr_roam_call_callback(pMac, sessionId, NULL, + pCommand->u.scanCmd.roamId, + eCSR_ROAM_ASSOCIATION_FAILURE, + eCSR_ROAM_RESULT_FAILURE); + } +roam_completion: + csr_roam_completion(pMac, sessionId, NULL, pCommand, roam_result, + false); + return status; +} + +CDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac, + tScanResultHandle hScanList) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + tScanResultList *pScanList = (tScanResultList *) hScanList; + + if (pScanList) { + status = csr_ll_scan_purge_result(pMac, &pScanList->List); + csr_ll_close(&pScanList->List); + cdf_mem_free(pScanList); + } + return status; +} + +/** + * csr_derive_prefer_value_from_rssi() - to derive prefer value + * @mac_ctx: Global MAC Context + * @rssi: RSSI of the BSS + * + * This routine will derive preferred value from given rssi + * + * Return: value between 0 to 14 + */ +static int csr_derive_prefer_value_from_rssi(tpAniSirGlobal mac_ctx, int rssi) +{ + int i = CSR_NUM_RSSI_CAT - 1, pref_val = 0; + while (i >= 0) { + if (rssi >= mac_ctx->roam.configParam.RSSICat[i]) { + pref_val = mac_ctx->roam.configParam.BssPreferValue[i]; + break; + } + i--; + }; + return pref_val; +} + +/** + * is_channel_found_in_pcl() - to check if channel is present in pcl + * @mac_ctx: Global MAC Context + * @channel_id: channel of bss + * @filter: pointer to filter created through profile + * + * to check if provided channel is present in pcl + * + * Return: true or false + */ +static bool is_channel_found_in_pcl(tpAniSirGlobal mac_ctx, int channel_id, + tCsrScanResultFilter *filter) +{ + int i; + bool status = false; + + if (NULL == filter) + return status; + + for (i = 0; i < filter->pcl_channels.numChannels; i++) { + if (filter->pcl_channels.channelList[i] == channel_id) { + status = true; + break; + } + } + 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, struct cdf_mac_addr *bssid) +{ + int modified_rssi; + int boost_factor; + int penalty_factor; + int i; + struct roam_ext_params *roam_params; + struct cdf_mac_addr fav_bssid; + struct cdf_mac_addr local_bssid; + + modified_rssi = rssi; + cdf_mem_zero(&local_bssid.bytes, CDF_MAC_ADDR_SIZE); + if (bssid) + cdf_mem_copy(local_bssid.bytes, bssid->bytes, + CDF_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) && + CDS_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); + } + sms_log(mac_ctx, LOG2, + FL("5G BSSID"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"), + MAC_ADDR_ARRAY(local_bssid.bytes), + rssi, modified_rssi, channel_id); + } + /* + * Check if there are preferred bssid and then apply the + * preferred score + */ + cdf_mem_zero(&fav_bssid.bytes, CDF_MAC_ADDR_SIZE); + if (roam_params->num_bssid_favored) { + for (i = 0; i < roam_params->num_bssid_favored; i++) { + cdf_mem_copy(fav_bssid.bytes, + &roam_params->bssid_favored[i], + CDF_MAC_ADDR_SIZE); + if (!cdf_is_macaddr_equal(&fav_bssid, bssid)) + continue; + modified_rssi += roam_params->bssid_favored_factor[i]; + sms_log(mac_ctx, LOG2, + FL("Pref"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"), + MAC_ADDR_ARRAY(local_bssid.bytes), + rssi, modified_rssi, channel_id); + } + } + return modified_rssi; +} + +/** + * csr_get_bss_prefer_value() - Get the preference value for BSS + * @mac_ctx: Global MAC Context + * @rssi: RSSI of the BSS + * @bssid: BSSID to which the preference value is returned + * @channel_id: Channel on which the AP is parked + * + * Each BSS descriptor should be assigned a preference value ranging from + * 14-0, which will be used as an RSSI bucket score while sorting the + * scan results. + * + * Return: Preference value for the BSSID + */ +static uint32_t csr_get_bss_prefer_value(tpAniSirGlobal mac_ctx, int rssi, + struct cdf_mac_addr *bssid, int channel_id) +{ + uint32_t ret = 0; + int 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(mac_ctx, rssi, channel_id, bssid); + ret = csr_derive_prefer_value_from_rssi(mac_ctx, modified_rssi); + + return ret; +} + +/* Return a CapValue base on the capabilities of a BSS */ +static uint32_t csr_get_bss_cap_value(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + uint32_t 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) && CDS_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; + struct cdf_mac_addr local_mac; + + rssi1 = bss1->Result.BssDescriptor.rssi; + rssi2 = bss2->Result.BssDescriptor.rssi; + /* + * Apply the boost and penlty logic and check + * which is the best RSSI + */ + cdf_mem_zero(&local_mac.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(&local_mac.bytes, + &bss1->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE); + rssi1 = csr_get_altered_rssi(mac_ctx, rssi1, + bss1->Result.BssDescriptor.channelId, + &local_mac); + cdf_mem_copy(&local_mac.bytes, + &bss2->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE); + rssi2 = csr_get_altered_rssi(mac_ctx, rssi2, + bss2->Result.BssDescriptor.channelId, + &local_mac); + if (CSR_IS_BETTER_RSSI(rssi1, rssi2)) + ret = true; + else + ret = false; + return ret; +} + +/** + * csr_is_better_bss() - 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_bss(tpAniSirGlobal mac_ctx, + tCsrScanResult *bss1, tCsrScanResult *bss2) +{ + bool ret; + + if (CSR_IS_BETTER_PREFER_VALUE(bss1->preferValue, bss2->preferValue)) { + ret = true; + } else if (CSR_IS_EQUAL_PREFER_VALUE + (bss1->preferValue, bss2->preferValue)) { + if (CSR_IS_BETTER_CAP_VALUE(bss1->capValue, bss2->capValue)) + ret = true; + else if (CSR_IS_EQUAL_CAP_VALUE + (bss1->capValue, bss2->capValue)) { + if (csr_is_better_rssi(mac_ctx, bss1, bss2)) + ret = true; + else + ret = false; + } else { + ret = false; + } + } else { + ret = false; + } + + return ret; +} + +#ifdef FEATURE_WLAN_LFR +/* Add the channel to the occupiedChannels array */ +static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac, + tCsrScanResult *pResult, + uint8_t sessionId, + tCsrChannel *occupied_ch, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status; + uint8_t ch; + uint8_t num_occupied_ch = occupied_ch->numChannels; + uint8_t *occupied_ch_lst = occupied_ch->channelList; + + ch = pResult->Result.BssDescriptor.channelId; + if (csr_is_channel_present_in_list(occupied_ch_lst, num_occupied_ch, ch) + || !csr_neighbor_roam_connected_profile_match(pMac, sessionId, + pResult, pIes)) + return; + + status = csr_add_to_channel_list_front(occupied_ch_lst, + num_occupied_ch, ch); + if (CDF_IS_STATUS_SUCCESS(status)) { + occupied_ch->numChannels++; + sms_log(pMac, LOG2, + FL("Added channel %d to the list (count=%d)"), + ch, occupied_ch->numChannels); + if (occupied_ch->numChannels > + CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN) + occupied_ch->numChannels = + CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN; + } +} +#endif + +/* Put the BSS into the scan result list */ +/* pIes can not be NULL */ +static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult, + tDot11fBeaconIEs *pIes, uint32_t sessionId) +{ +#ifdef FEATURE_WLAN_LFR + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#endif + + struct cdf_mac_addr bssid; + uint8_t channel_id = pResult->Result.BssDescriptor.channelId; + cdf_mem_zero(&bssid.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(bssid.bytes, &pResult->Result.BssDescriptor.bssId, + CDF_MAC_ADDR_SIZE); + pResult->preferValue = csr_get_bss_prefer_value(pMac, + (int)pResult->Result.BssDescriptor.rssi, + &bssid, channel_id); + pResult->capValue = csr_get_bss_cap_value(pMac, + &pResult->Result.BssDescriptor, pIes); + csr_ll_insert_tail(&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 + */ + csr_scan_add_to_occupied_channels(pMac, pResult, sessionId, + &pMac->scan.occupiedChannels[sessionId], pIes); + } +#endif +} + +static void +csr_parser_scan_result_for_5ghz_preference(tpAniSirGlobal pMac, + tCsrScanResultFilter *pFilter) +{ + bool fMatch; + CDF_STATUS status; + tListElem *pEntry; + tDot11fBeaconIEs *pIes; + tCsrScanResult *pBssDesc; + uint8_t i = 0; + + /* Find out the best AP Rssi going thru the scan results */ + pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while (NULL != pEntry) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + fMatch = false; + + for (i = 0; pFilter && (i < pFilter->SSIDs.numOfSSIDs); i++) { + fMatch = csr_is_ssid_match(pMac, + pFilter->SSIDs.SSIDList[i].SSID.ssId, + pFilter->SSIDs.SSIDList[i].SSID.length, + pBssDesc->Result.ssId.ssId, + pBssDesc->Result.ssId.length, true); + if (!fMatch) + continue; + + pIes = (tDot11fBeaconIEs *)(pBssDesc->Result.pvIes); + /* At this time, Result.pvIes may be NULL */ + status = csr_get_parsed_bss_description_ies(pMac, + &pBssDesc->Result.BssDescriptor, &pIes); + if (!pIes && (!CDF_IS_STATUS_SUCCESS(status))) + continue; + + sms_log(pMac, LOG1, FL("SSID Matched")); + if (pFilter->bOSENAssociation) { + fMatch = true; + sms_log(pMac, LOG1, FL("Security Matched")); + if ((pBssDesc->Result.pvIes == NULL) && pIes) + cdf_mem_free(pIes); + continue; + } +#ifdef WLAN_FEATURE_11W + fMatch = csr_is_security_match(pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + &pFilter->MFPEnabled, + &pFilter->MFPRequired, + &pFilter->MFPCapable, + &pBssDesc->Result.BssDescriptor, + pIes, NULL, NULL, NULL); +#else + fMatch = csr_is_security_match(pMac, &pFilter->authType, + &pFilter->EncryptionType, + &pFilter->mcEncryptionType, + NULL, NULL, NULL, + &pBssDesc->Result.BssDescriptor, + pIes, NULL, NULL, NULL); +#endif + if ((pBssDesc->Result.pvIes == NULL) && pIes) + cdf_mem_free(pIes); + if (fMatch) + sms_log(pMac, LOG1, FL("Security Matched")); + } /* for loop ends */ + + if (fMatch + && (pBssDesc->Result.BssDescriptor.rssi > + pMac->scan.inScanResultBestAPRssi)) { + sms_log(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 = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } +} + +static void +csr_prefer_5ghz(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter) +{ + tListElem *pEntry; + tCsrScanResult *pBssDesc; + struct roam_ext_params *roam_params = NULL; + + if (!pMac->roam.configParam.nSelect5GHzMargin && + !CSR_IS_SELECT_5G_PREFERRED(pMac)) + return; + + pMac->scan.inScanResultBestAPRssi = -128; + roam_params = &pMac->roam.configParam.roam_params; +#ifdef WLAN_DEBUG_ROAM_OFFLOAD + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("nSelect5GHzMargin")); +#endif + csr_ll_lock(&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)) + csr_parser_scan_result_for_5ghz_preference(pMac, pFilter); + if (-128 != pMac->scan.inScanResultBestAPRssi || + CSR_IS_SELECT_5G_PREFERRED(pMac)) { + sms_log(pMac, LOG1, FL("Best AP Rssi is %d"), + pMac->scan.inScanResultBestAPRssi); + /* Modify Rssi category based on best AP Rssi */ + if (-128 != pMac->scan.inScanResultBestAPRssi) + csr_assign_rssi_for_category(pMac, + pMac->scan.inScanResultBestAPRssi, + pMac->roam.configParam.bCatRssiOffset); + pEntry = csr_ll_peek_head(&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) 5G Preference feature. + */ + pBssDesc->preferValue = csr_get_bss_prefer_value(pMac, + (int)pBssDesc->Result.BssDescriptor.rssi, + (struct cdf_mac_addr *) + &pBssDesc->Result.BssDescriptor.bssId, + pBssDesc->Result.BssDescriptor.channelId); + + sms_log(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 = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } + } + csr_ll_unlock(&pMac->scan.scanResultList); +} + +static CDF_STATUS +csr_save_ies(tpAniSirGlobal pMac, + tCsrScanResultFilter *pFilter, + tCsrScanResult *pBssDesc, + tDot11fBeaconIEs **pNewIes, + bool *fMatch, + eCsrEncryptionType *uc, + eCsrEncryptionType *mc, + eCsrAuthType *auth) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tDot11fBeaconIEs *pIes = NULL; + + if (!pFilter) + return status; + *fMatch = csr_match_bss(pMac, &pBssDesc->Result.BssDescriptor, + pFilter, auth, uc, mc, &pIes); +#ifdef WLAN_DEBUG_ROAM_OFFLOAD + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("csr_match_bss fmatch %d"), *fMatch); +#endif + if (NULL == pIes) + return status; + /* Only save it when matching */ + if (!(*fMatch) && !pBssDesc->Result.pvIes) { + cdf_mem_free(pIes); + return status; + } + if (!pBssDesc->Result.pvIes) { + /* + * csr_match_bss allocates the memory. Simply pass it and it + * is freed later + */ + *pNewIes = pIes; + return status; + } + /* + * 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 = cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if (NULL == *pNewIes) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, FL("fail to allocate memory for IEs")); + /* Need to free memory allocated by csr_match_bss */ + if (!pBssDesc->Result.pvIes) + cdf_mem_free(pIes); + return status; + } + cdf_mem_copy(*pNewIes, pIes, sizeof(tDot11fBeaconIEs)); + return status; +} + +static CDF_STATUS +csr_save_scan_entry(tpAniSirGlobal pMac, + tCsrScanResultFilter *pFilter, + bool fMatch, + tCsrScanResult *pBssDesc, + tDot11fBeaconIEs *pNewIes, + tScanResultList *pRetList, + uint32_t *count, + eCsrEncryptionType uc, + eCsrEncryptionType mc, + eCsrAuthType *auth) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrScanResult *pResult; + uint32_t bssLen, allocLen; + /* To sort the list */ + tListElem *pTmpEntry; + tCsrScanResult *pTmpResult; + + if (!(NULL == pFilter || fMatch)) + return status; + + bssLen = pBssDesc->Result.BssDescriptor.length + + sizeof(pBssDesc->Result.BssDescriptor.length); + allocLen = sizeof(tCsrScanResult) + bssLen; + pResult = cdf_mem_malloc(allocLen); + if (NULL == pResult) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, + FL("fail to allocate memory for scan result, len=%d"), + allocLen); + if (pNewIes) + cdf_mem_free(pNewIes); + return status; + } + cdf_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 */ + cdf_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 (csr_ll_is_list_empty(&pRetList->List, LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&pRetList->List, &pResult->Link, + LL_ACCESS_NOLOCK); + (*count)++; + return status; + } + + pTmpEntry = csr_ll_peek_head(&pRetList->List, LL_ACCESS_NOLOCK); + while (pTmpEntry) { + pTmpResult = GET_BASE_ADDR(pTmpEntry, tCsrScanResult, Link); + if (csr_is_better_bss(pMac, pResult, pTmpResult)) { + csr_ll_insert_entry(&pRetList->List, pTmpEntry, + &pResult->Link, LL_ACCESS_NOLOCK); + /* To indicate we are done */ + pResult = NULL; + break; + } + pTmpEntry = csr_ll_next(&pRetList->List, + pTmpEntry, LL_ACCESS_NOLOCK); + } + if (pResult != NULL) { + /* This one is not better than any one */ + csr_ll_insert_tail(&pRetList->List, &pResult->Link, + LL_ACCESS_NOLOCK); + } + (*count)++; + return status; +} + +/** + * csr_calc_pref_val_by_pcl() - to calculate preferred value + * @mac_ctx: mac context + * @filter: filter to find match from scan result + * @bss_descr: pointer to bss descriptor + * + * this routine calculates the new preferred value to be given to + * provided bss if its channel falls under preferred channel list. + * Thump rule is higer the RSSI better the boost. + * + * Return: success or failure + */ +static CDF_STATUS csr_calc_pref_val_by_pcl(tpAniSirGlobal mac_ctx, + tCsrScanResultFilter *filter, + tCsrScanResult *bss_descr) +{ + int temp_rssi = 0, new_pref_val = 0; + int orig_pref_val = 0; + + if (NULL == mac_ctx || NULL == bss_descr) + return CDF_STATUS_E_FAILURE; + + if (mac_ctx->policy_manager_enabled && + is_channel_found_in_pcl(mac_ctx, + bss_descr->Result.BssDescriptor.channelId, filter) && + (bss_descr->Result.BssDescriptor.rssi > PCL_RSSI_THRESHOLD)) { + orig_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx, + bss_descr->Result.BssDescriptor.rssi); + temp_rssi = bss_descr->Result.BssDescriptor.rssi + + (PCL_ADVANTAGE/(CSR_NUM_RSSI_CAT - + orig_pref_val)); + if (temp_rssi > 0) + temp_rssi = 0; + new_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx, + temp_rssi); + + sms_log(mac_ctx, LOG1, + FL("%pM: rssi:%d org pref=%d temp rssi:%d new pref=%d pref=%d updated pref=%d"), + bss_descr->Result.BssDescriptor.bssId, + bss_descr->Result.BssDescriptor.rssi, + orig_pref_val, temp_rssi, new_pref_val, + bss_descr->preferValue, + CSR_MAX(new_pref_val, bss_descr->preferValue)); + + bss_descr->preferValue = + CSR_MAX(new_pref_val, bss_descr->preferValue); + } + return CDF_STATUS_SUCCESS; +} + +static CDF_STATUS +csr_parse_scan_results(tpAniSirGlobal pMac, + tCsrScanResultFilter *pFilter, + tScanResultList *pRetList, + uint32_t *count) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry; + bool fMatch = false; + tCsrScanResult *pBssDesc = NULL; + tDot11fBeaconIEs *pIes, *pNewIes = NULL; + eCsrEncryptionType uc, mc; + eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; + uint32_t len = 0; + enum cds_con_mode new_mode; + + + csr_ll_lock(&pMac->scan.scanResultList); + + if (pFilter) { + if (cds_map_concurrency_mode(pMac->hHdd, + &pFilter->csrPersona, &new_mode)) { + status = cds_get_pcl(pMac->hHdd, new_mode, + &pFilter->pcl_channels.channelList[0], &len); + pFilter->pcl_channels.numChannels = (uint8_t)len; + } + } + + if (CDF_STATUS_E_FAILURE == status) + sms_log(pMac, CDF_TRACE_LEVEL_ERROR, + FL("Retrieving pcl failed from HDD")); + pEntry = csr_ll_peek_head(&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 csr_match_bss for any error condition, + * otherwiase, it will be freed later + */ + fMatch = false; + pNewIes = NULL; + status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes, + &fMatch, &uc, &mc, &auth); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + /* + * Modify the prefer value to honor PCL list + */ + if (pFilter && pFilter->pcl_channels.numChannels > 0) + csr_calc_pref_val_by_pcl(pMac, pFilter, pBssDesc); + status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc, + pNewIes, pRetList, count, uc, mc, + &auth); + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } /* while */ + csr_ll_unlock(&pMac->scan.scanResultList); + return status; +} + +CDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac, + tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult) +{ + CDF_STATUS status; + tScanResultList *pRetList; + uint32_t count = 0; + + if (phResult) + *phResult = CSR_INVALID_SCANRESULT_HANDLE; + + csr_prefer_5ghz(pMac, pFilter); + + pRetList = cdf_mem_malloc(sizeof(tScanResultList)); + if (NULL == pRetList) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pRetList, sizeof(tScanResultList), 0); + csr_ll_open(pMac->hHdd, &pRetList->List); + pRetList->pCurEntry = NULL; + status = csr_parse_scan_results(pMac, pFilter, pRetList, &count); + sms_log(pMac, LOG2, FL("return %d BSS"), csr_ll_count(&pRetList->List)); + if (!CDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) { + /* Fail or No one wants the result. */ + csr_scan_result_purge(pMac, (tScanResultHandle) pRetList); + } else { + if (0 == count) { + /* We are here meaning the there is no match */ + csr_ll_close(&pRetList->List); + cdf_mem_free(pRetList); + status = CDF_STATUS_E_NULL_VALUE; + } else if (phResult) { + *phResult = 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 + * csr_roam_roaming_state_disassoc_rsp_processor. + * If it is needed to remove this routine, + * first ensure that we recover gracefully from + * csr_roam_roaming_state_disassoc_rsp_processor if + * csr_scan_get_result returns with a failure because + * of not being able to find the roaming BSS. + */ +bool csr_scan_flush_denied(tpAniSirGlobal pMac) +{ + uint8_t sessionId; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + if (csr_neighbor_middle_of_roaming(pMac, sessionId)) + return 1; + } + } + return 0; +} + +CDF_STATUS csr_scan_flush_result(tpAniSirGlobal pMac) +{ + bool isFlushDenied = csr_scan_flush_denied(pMac); + + if (isFlushDenied) { + sms_log(pMac, LOGW, "%s: scan flush denied in roam state %d", + __func__, isFlushDenied); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG4, "%s: Flushing all scan results", __func__); + csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults); + csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList); + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_scan_flush_selective_result(tpAniSirGlobal pMac, bool flushP2P) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry, *pFreeElem; + tCsrScanResult *pBssDesc; + tDblLinkList *pList = &pMac->scan.scanResultList; + + csr_ll_lock(pList); + + pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK); + while (pEntry != NULL) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + if (flushP2P == cdf_mem_compare(pBssDesc->Result.ssId.ssId, + "DIRECT-", 7)) { + pFreeElem = pEntry; + pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK); + csr_free_scan_result_entry(pMac, pBssDesc); + continue; + } + pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + } + + csr_ll_unlock(pList); + + return status; +} + +void csr_scan_flush_bss_entry(tpAniSirGlobal pMac, + tpSmeCsaOffloadInd pCsaOffloadInd) +{ + tListElem *pEntry, *pFreeElem; + tCsrScanResult *pBssDesc; + tDblLinkList *pList = &pMac->scan.scanResultList; + + csr_ll_lock(pList); + + pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK); + while (pEntry != NULL) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + if (cdf_mem_compare(pBssDesc->Result.BssDescriptor.bssId, + pCsaOffloadInd->bssId, sizeof(tSirMacAddr))) { + pFreeElem = pEntry; + pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK); + csr_free_scan_result_entry(pMac, pBssDesc); + sms_log(pMac, LOG1, FL("Removed BSS entry:%pM"), + pCsaOffloadInd->bssId); + continue; + } + + pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + } + + csr_ll_unlock(pList); +} + +/** + * csr_check11d_channel + * + ***FUNCTION: + * This function is called from csr_scan_filter_results 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 + */ + +CDF_STATUS csr_check11d_channel(uint8_t channelId, uint8_t *pChannelList, + uint32_t numChannels) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint8_t i = 0; + + for (i = 0; i < numChannels; i++) { + if (pChannelList[i] == channelId) { + status = CDF_STATUS_SUCCESS; + break; + } + } + return status; +} + +/** + * csr_scan_filter_results + * + ***FUNCTION: + * This function is called from csr_apply_country_information 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 + */ + +CDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry, *pTempEntry; + tCsrScanResult *pBssDesc; + uint32_t len = sizeof(pMac->roam.validChannelList); + + /* Get valid channels list from CFG */ + if (!CDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels(pMac, + pMac->roam. + validChannelList, + &len))) { + sms_log(pMac, LOGE, "Failed to get Channel list from CFG"); + } + + csr_ll_lock(&pMac->scan.scanResultList); + pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while (pEntry) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pTempEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId, + pMac->roam.validChannelList, len)) { + /* Remove Scan result which does not have 11d channel */ + if (csr_ll_remove_entry(&pMac->scan.scanResultList, + pEntry, LL_ACCESS_NOLOCK)) { + csr_free_scan_result_entry(pMac, pBssDesc); + } + } else { + sms_log(pMac, LOG1, FL("%d is a Valid channel"), + pBssDesc->Result.BssDescriptor.channelId); + } + pEntry = pTempEntry; + } + + csr_ll_unlock(&pMac->scan.scanResultList); + csr_ll_lock(&pMac->scan.tempScanResults); + + pEntry = csr_ll_peek_head(&pMac->scan.tempScanResults, + LL_ACCESS_NOLOCK); + while (pEntry) { + pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pTempEntry = csr_ll_next(&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK); + if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId, + pMac->roam.validChannelList, len)) { + /* Remove Scan result which does not have 11d channel */ + if (csr_ll_remove_entry + (&pMac->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK)) { + csr_free_scan_result_entry(pMac, pBssDesc); + } + } else { + sms_log(pMac, LOG1, FL("%d is a Valid channel"), + pBssDesc->Result.BssDescriptor.channelId); + } + pEntry = pTempEntry; + } + + csr_ll_unlock(&pMac->scan.tempScanResults); + return status; +} + +CDF_STATUS csr_scan_copy_result_list(tpAniSirGlobal pMac, tScanResultHandle hIn, + tScanResultHandle *phResult) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tScanResultList *pRetList, *pInList = (tScanResultList *) hIn; + tCsrScanResult *pResult, *pScanResult; + uint32_t count = 0; + tListElem *pEntry; + uint32_t bssLen, allocLen; + + if (phResult) { + *phResult = CSR_INVALID_SCANRESULT_HANDLE; + } + pRetList = cdf_mem_malloc(sizeof(tScanResultList)); + if (NULL == pRetList) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set(pRetList, sizeof(tScanResultList), 0); + csr_ll_open(pMac->hHdd, &pRetList->List); + pRetList->pCurEntry = NULL; + csr_ll_lock(&pMac->scan.scanResultList); + csr_ll_lock(&pInList->List); + + pEntry = csr_ll_peek_head(&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 = cdf_mem_malloc(allocLen); + if (NULL == pResult) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_scan_result_purge(pMac, + (tScanResultHandle *) + pRetList); + count = 0; + break; + } + cdf_mem_set(pResult, allocLen, 0); + cdf_mem_copy(&pResult->Result.BssDescriptor, + &pScanResult->Result.BssDescriptor, + bssLen); + if (pScanResult->Result.pvIes) { + pResult->Result.pvIes = + cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if (NULL == pResult->Result.pvIes) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + /* Free the memory we allocate above first */ + cdf_mem_free(pResult); + csr_scan_result_purge(pMac, + (tScanResultHandle *) + pRetList); + count = 0; + break; + } + cdf_mem_copy(pResult->Result.pvIes, + pScanResult->Result.pvIes, + sizeof(tDot11fBeaconIEs)); + } + csr_ll_insert_tail(&pRetList->List, &pResult->Link, + LL_ACCESS_LOCK); + count++; + pEntry = + csr_ll_next(&pInList->List, pEntry, LL_ACCESS_NOLOCK); + } /* while */ + csr_ll_unlock(&pInList->List); + csr_ll_unlock(&pMac->scan.scanResultList); + + if (CDF_IS_STATUS_SUCCESS(status)) { + if (0 == count) { + csr_ll_close(&pRetList->List); + cdf_mem_free(pRetList); + status = CDF_STATUS_E_NULL_VALUE; + } else if (phResult) { + *phResult = pRetList; + } + } + } /* Allocated pRetList */ + + return status; +} + +CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac, + void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirMbMsg *pMsg = (tSirMbMsg *) pMsgBuf; + tCsrRoamSession *pSession; + tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; + tCsrRoamInfo roamInfo; + tCsrRoamInfo *pRoamInfo = NULL; + uint32_t sessionId; + + if (eWNI_SME_SCAN_RSP == pMsg->type) + return csr_scan_sme_scan_response(pMac, pMsgBuf); + + if (pMsg->type != eWNI_SME_UPPER_LAYER_ASSOC_CNF) { + if (csr_is_any_session_in_connect_state(pMac)) { + /* + * In case of we are connected, we need to check whether + * connect status changes because scan may also run + * while connected. + */ + csr_roam_check_for_link_status_change(pMac, + (tSirSmeRsp *) pMsgBuf); + } else { + sms_log(pMac, LOGW, + FL("Message [0x%04x] received in wrong state"), + pMsg->type); + } + return status; + } + + sms_log(pMac, LOG1, + FL("Scanning: ASSOC cnf can be given to upper layer")); + cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + pRoamInfo = &roamInfo; + pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *) pMsgBuf; + status = csr_roam_get_session_id_from_bssid(pMac, + (struct cdf_mac_addr *)pUpperLayerAssocCnf->bssId, &sessionId); + pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + + /* send the status code as Success */ + pRoamInfo->statusCode = eSIR_SME_SUCCESS; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + pRoamInfo->staId = (uint8_t) pUpperLayerAssocCnf->aid; + pRoamInfo->rsnIELen = (uint8_t) pUpperLayerAssocCnf->rsnIE.length; + pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata; + pRoamInfo->addIELen = (uint8_t) pUpperLayerAssocCnf->addIE.length; + pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata; + cdf_mem_copy(pRoamInfo->peerMac.bytes, + pUpperLayerAssocCnf->peerMacAddr, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(&pRoamInfo->bssid.bytes, pUpperLayerAssocCnf->bssId, + CDF_MAC_ADDR_SIZE); + 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 = csr_roam_call_callback(pMac, sessionId, + pRoamInfo, 0, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); + } + if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) { + cdf_sleep(100); + pMac->roam.roamSession[sessionId].connectState = + eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; + status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0, + eCSR_ROAM_WDS_IND, + eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); + } + return status; +} + +void csr_check_n_save_wsc_ie(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr, + tSirBssDescription *pOldBssDescr) +{ + int idx, len; + uint8_t *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(uint16_t) + sizeof(uint32_t) - + DOT11F_IE_WSCPROBERES_MIN_LEN - 2; + pbIe = (uint8_t *) 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])) { + /* Founrd it */ + if ((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= + pbIe[1]) { + cdf_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 */ +bool csr_remove_dup_bss_description(tpAniSirGlobal pMac, + tSirBssDescription *bss_dscp, + tDot11fBeaconIEs *pIes, tAniSSID *pSsid, + v_TIME_t *timer, bool fForced) +{ + tListElem *pEntry; + tCsrScanResult *scan_entry; + bool fRC = false; + int8_t scan_entry_rssi = 0; + + /* + * 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. + */ + csr_ll_lock(&pMac->scan.scanResultList); + pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + + while (pEntry) { + scan_entry = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + /* + * we have a duplicate scan results only when BSSID, SSID, + * Channel and NetworkType matches + */ + if (csr_is_duplicate_bss_description(pMac, + &scan_entry->Result.BssDescriptor, + bss_dscp, pIes, fForced)) { + /* + * Following is mathematically a = (aX + b(100-X))/100 + * where: + * a = bss_dscp->rssi, b = scan_entry_rssi + * and X = CSR_SCAN_RESULT_RSSI_WEIGHT + */ + scan_entry_rssi = scan_entry->Result.BssDescriptor.rssi; + bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi * + CSR_SCAN_RESULT_RSSI_WEIGHT) + + ((int32_t) scan_entry_rssi * + (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100); + /* Remove the old entry from the list */ + if (csr_ll_remove_entry + (&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 = scan_entry->Result.ssId; + *timer = scan_entry->Result.timer; + csr_check_n_save_wsc_ie(pMac, bss_dscp, + &scan_entry->Result. + BssDescriptor); + csr_free_scan_result_entry(pMac, scan_entry); + } else { + sms_log(pMac, LOGW, FL("fail to remove entry")); + } + fRC = true; + /* + * If we found a match, we can stop looking through + * the list. + */ + break; + } + pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } + + csr_ll_unlock(&pMac->scan.scanResultList); + return fRC; +} + +CDF_STATUS csr_add_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tPmkidCandidateInfo *pmkid_info = NULL; +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + WLAN_HOST_DIAG_EVENT_DEF(secEvent, + host_event_wlan_security_payload_type); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, FL("NumPmkidCandidate = %d"), + pSession->NumPmkidCandidate); + if (!pIes) + return status; + /* check if this is a RSN BSS */ + if (!pIes->RSN.present) + return status; + + if (pSession->NumPmkidCandidate >= CSR_MAX_PMKID_ALLOWED) + return CDF_STATUS_E_FAILURE; + + /* BSS is capable of doing pre-authentication */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + cdf_mem_set(&secEvent, sizeof(host_event_wlan_security_payload_type), + 0); + secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND; + secEvent.encryptionModeMulticast = (uint8_t)diag_enc_type_from_csr_type( + pSession->connectedProfile.mcEncryptionType); + secEvent.encryptionModeUnicast = (uint8_t)diag_enc_type_from_csr_type( + pSession->connectedProfile.EncryptionType); + cdf_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid.bytes, + CDF_MAC_ADDR_SIZE); + secEvent.authMode = (uint8_t)diag_auth_type_from_csr_type( + pSession->connectedProfile.AuthType); + WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY); +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + + pmkid_info = &pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate]; + /* if yes, then add to PMKIDCandidateList */ + cdf_mem_copy(pmkid_info->BSSID.bytes, pBssDesc->bssId, + CDF_MAC_ADDR_SIZE); + /* Bit 0 offirst byte - PreAuthentication Capability */ + if ((pIes->RSN.RSN_Cap[0] >> 0) & 0x1) + pmkid_info->preAuthSupported = true; + else + pmkid_info->preAuthSupported = false; + pSession->NumPmkidCandidate++; + 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 + */ +CDF_STATUS csr_process_bss_desc_for_pmkid_list(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes, + uint8_t sessionId) +{ + tCsrRoamSession *pSession; + tDot11fBeaconIEs *pIesLocal = pIes; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (!(pIesLocal || + CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies(pMac, pBssDesc, + &pIesLocal)))) + return status; + + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + if (!pIes) + cdf_mem_free(pIesLocal); + return status; + } + + pSession = CSR_GET_SESSION(pMac, sessionId); + if (csr_is_conn_state_connected_infra(pMac, sessionId) + && (eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType) + && csr_match_bss_to_connect_profile(pMac, + &pSession->connectedProfile, + pBssDesc, pIesLocal)) { + /* This new BSS fits the current profile connected */ + status = csr_add_pmkid_candidate_list(pMac, sessionId, + pBssDesc, pIesLocal); + if (!CDF_IS_STATUS_SUCCESS(status)) + sms_log(pMac, LOGE, + FL("csr_add_pmkid_candidate_list failed")); + else + status = CDF_STATUS_SUCCESS; + } + + if (!pIes) + cdf_mem_free(pIesLocal); + + return status; +} + +#ifdef FEATURE_WLAN_WAPI +CDF_STATUS csr_add_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, + "csr_add_bkid_candidate_list 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 */ + cdf_mem_copy(pSession-> + BkidCandidateInfo[pSession-> + NumBkidCandidate]. + BSSID.bytes, pBssDesc->bssId, + CDF_MAC_ADDR_SIZE); + if (pIes->WAPI.preauth) { + pSession->BkidCandidateInfo[pSession-> + NumBkidCandidate]. + preAuthSupported = true; + } else { + pSession->BkidCandidateInfo[pSession-> + NumBkidCandidate]. + preAuthSupported = false; + } + pSession->NumBkidCandidate++; + } else { + status = CDF_STATUS_E_FAILURE; + } + } + } + + return status; +} + +/* + * This function checks whether new AP is found for the current connected + * profile, if so add to BKIDCandidateList + */ +bool csr_process_bss_desc_for_bkid_list(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + bool fRC = false; + tDot11fBeaconIEs *pIesLocal = pIes; + uint32_t sessionId; + tCsrRoamSession *pSession; + CDF_STATUS status; + + if (!(pIesLocal || + CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies(pMac, pBssDesc, + &pIesLocal)))) + return fRC; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) + continue; + pSession = CSR_GET_SESSION(pMac, sessionId); + if (csr_is_conn_state_connected_infra(pMac, sessionId) + && (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == + pSession->connectedProfile.AuthType) + && csr_match_bss_to_connect_profile(pMac, + &pSession->connectedProfile, + pBssDesc, pIesLocal)) { + /* this new BSS fits the current profile connected */ + status = csr_add_bkid_candidate_list(pMac, sessionId, + pBssDesc, pIesLocal); + if (CDF_IS_STATUS_SUCCESS(status)) + fRC = true; + } + } + if (!pIes) + cdf_mem_free(pIesLocal); + return fRC; +} + +#endif + +static void +csr_remove_from_tmp_list(tpAniSirGlobal mac_ctx, + uint8_t reason, + uint8_t session_id) +{ + CDF_STATUS status; + tListElem *entry; + tCsrScanResult *bss_dscp; + tDot11fBeaconIEs *local_ie = NULL; + bool dup_bss; + tAniSSID tmpSsid; + v_TIME_t timer = 0; + + tmpSsid.length = 0; + while ((entry = csr_ll_remove_tail(&mac_ctx->scan.tempScanResults, + LL_ACCESS_LOCK)) != NULL) { + bss_dscp = GET_BASE_ADDR(entry, tCsrScanResult, Link); + sms_log(mac_ctx, LOG2, + FL("...Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = -%d"), + MAC_ADDR_ARRAY(bss_dscp->Result.BssDescriptor. + bssId), + bss_dscp->Result.BssDescriptor.channelId, + bss_dscp->Result.BssDescriptor.rssi * (-1)); + + /* At this time, bss_dscp->Result.pvIes may be NULL */ + local_ie = (tDot11fBeaconIEs *)(bss_dscp->Result.pvIes); + status = csr_get_parsed_bss_description_ies(mac_ctx, + &bss_dscp->Result.BssDescriptor, &local_ie); + if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) { + sms_log(mac_ctx, LOGE, FL("Cannot pared IEs")); + csr_free_scan_result_entry(mac_ctx, bss_dscp); + continue; + } + dup_bss = csr_remove_dup_bss_description(mac_ctx, + &bss_dscp->Result.BssDescriptor, + local_ie, &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(mac_ctx)) { + sms_log(mac_ctx, LOGW, FL("BSS limit reached")); + if ((bss_dscp->Result.pvIes == NULL) && local_ie) + cdf_mem_free(local_ie); + csr_free_scan_result_entry(mac_ctx, bss_dscp); + /* Continue because there may be duplicated BSS */ + continue; + } + /* check for duplicate scan results */ + if (!dup_bss) { + status = csr_process_bss_desc_for_pmkid_list(mac_ctx, + &bss_dscp->Result.BssDescriptor, + local_ie, session_id); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* Found a new BSS */ + csr_roam_call_callback(mac_ctx, session_id, + 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. + * + * 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 + */ + v_TIME_t time_gap = cdf_mc_timer_get_system_time() - + timer; + if ((0 == bss_dscp->Result.ssId.length) + && (time_gap <= HIDDEN_TIMER) + && tmpSsid.length) { + bss_dscp->Result.timer = timer; + bss_dscp->Result.ssId = tmpSsid; + } + } + + if (csr_is11d_supported(mac_ctx) + && local_ie->Country.present) { + csr_add_vote_for_country_info(mac_ctx, + local_ie->Country.country); + sms_log(mac_ctx, LOGW, + FL("11d AP Bssid "MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( + bss_dscp->Result.BssDescriptor.bssId), + bss_dscp->Result.BssDescriptor.channelId, + bss_dscp->Result.BssDescriptor.rssi * (-1), + local_ie->Country.country[0], + local_ie->Country.country[1]); + } + /* append to main list */ + csr_scan_add_result(mac_ctx, bss_dscp, local_ie, session_id); + if ((bss_dscp->Result.pvIes == NULL) && local_ie) + cdf_mem_free(local_ie); + } /* end of loop */ +} + +static void csr_move_temp_scan_results_to_main_list(tpAniSirGlobal pMac, + uint8_t reason, + uint8_t sessionId) +{ + tCsrRoamSession *pSession; + uint32_t i; + + /* remove the BSS descriptions from temporary list */ + csr_remove_from_tmp_list(pMac, reason, sessionId); + /* + * We don't need to update CC while connected to an AP which is + * advertising CC already + */ + if (!csr_is11d_supported(pMac)) + return; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (!CSR_IS_SESSION_VALID(pMac, i)) + continue; + pSession = CSR_GET_SESSION(pMac, i); + if (csr_is_conn_state_connected(pMac, i)) { + sms_log(pMac, LOGW, + FL("No need to update CC in connected state")); + return; + } + } + csr_elected_country_info(pMac); + csr_learn_11dcountry_information(pMac, NULL, NULL, true); +} + +static tCsrScanResult *csr_scan_save_bss_description(tpAniSirGlobal pMac, + tSirBssDescription * + pBSSDescription, + tDot11fBeaconIEs *pIes, + uint8_t sessionId) +{ + tCsrScanResult *pCsrBssDescription = NULL; + uint32_t cbBSSDesc; + uint32_t 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 = cdf_mem_malloc(cbAllocated); + if (NULL != pCsrBssDescription) { + cdf_mem_set(pCsrBssDescription, cbAllocated, 0); + pCsrBssDescription->AgingCount = + (int32_t) pMac->roam.configParam.agingCount; + sms_log(pMac, LOGW, + FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "), + pCsrBssDescription->AgingCount, + MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor. + bssId)); + cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor, + pBSSDescription, cbBSSDesc); +#if defined(CDF_ENSBALED) + if (NULL != pCsrBssDescription->Result.pvIes) { + CDF_ASSERT(pCsrBssDescription->Result.pvIes == NULL); + return NULL; + } +#endif + csr_scan_add_result(pMac, pCsrBssDescription, pIes, sessionId); + } + + return pCsrBssDescription; +} + +/* Append a Bss Description... */ +tCsrScanResult *csr_scan_append_bss_description(tpAniSirGlobal pMac, + tSirBssDescription * + pSirBssDescription, + tDot11fBeaconIEs *pIes, + bool fForced, uint8_t sessionId) +{ + tCsrScanResult *pCsrBssDescription = NULL; + tAniSSID tmpSsid; + v_TIME_t timer = 0; + int result; + + tmpSsid.length = 0; + result = csr_remove_dup_bss_description(pMac, pSirBssDescription, + pIes, &tmpSsid, &timer, + fForced); + pCsrBssDescription = csr_scan_save_bss_description(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 ((cdf_mc_timer_get_system_time() - timer) <= + HIDDEN_TIMER) { + pCsrBssDescription->Result.ssId = tmpSsid; + pCsrBssDescription->Result.timer = timer; + } + } + } + + return pCsrBssDescription; +} + +void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList) +{ + tCsrChannelPowerInfo *pChannelSet; + tListElem *pEntry; + + csr_ll_lock(pChannelList); + /* + * Remove the channel sets from the learned list and put them + * in the free list + */ + while ((pEntry = csr_ll_remove_head(pChannelList, + LL_ACCESS_NOLOCK)) != NULL) { + pChannelSet = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link); + if (pChannelSet) + cdf_mem_free(pChannelSet); + } + csr_ll_unlock(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 + */ +CDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac, + uint32_t tableSize, + tSirMacChanInfo *channelTable) +{ + uint32_t i = tableSize / sizeof(tSirMacChanInfo); + tSirMacChanInfo *pChannelInfo; + tCsrChannelPowerInfo *pChannelSet; + bool f2GHzInfoFound = false; + bool f2GListPurged = false, f5GListPurged = false; + + pChannelInfo = channelTable; + /* atleast 3 bytes have to be remaining -- from "countryString" */ + while (i--) { + pChannelSet = cdf_mem_malloc(sizeof(tCsrChannelPowerInfo)); + if (NULL == pChannelSet) { + pChannelInfo++; + continue; + } + cdf_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 ((CDS_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) && + ((pChannelSet->firstChannel + + (pChannelSet->numChannels - 1)) <= + CDS_MAX_24GHz_CHANNEL_NUMBER)) { + pChannelSet->interChannelOffset = 1; + f2GHzInfoFound = true; + } else if ((CDS_IS_CHANNEL_5GHZ(pChannelSet->firstChannel)) + && ((pChannelSet->firstChannel + + ((pChannelSet->numChannels - 1) * 4)) <= + CDS_MAX_5GHz_CHANNEL_NUMBER)) { + pChannelSet->interChannelOffset = 4; + f2GHzInfoFound = false; + } else { + sms_log(pMac, LOGW, + FL("Invalid Channel %d Present in Country IE"), + pChannelSet->firstChannel); + cdf_mem_free(pChannelSet); + return CDF_STATUS_E_FAILURE; + } + pChannelSet->txPower = CDF_MIN(pChannelInfo->maxTxPower, + pMac->roam.configParam.nTxPowerCap); + if (f2GHzInfoFound) { + if (!f2GListPurged) { + /* purge previous results if found new */ + csr_purge_channel_power(pMac, + &pMac->scan. + channelPowerInfoList24); + f2GListPurged = true; + } + if (CSR_IS_OPERATING_BG_BAND(pMac)) { + /* add to the list of 2.4 GHz channel sets */ + csr_ll_insert_tail(&pMac->scan. + channelPowerInfoList24, + &pChannelSet->link, + LL_ACCESS_LOCK); + } else { + sms_log(pMac, LOGW, + FL("Adding 11B/G ch in 11A. 1st ch %d"), + pChannelSet->firstChannel); + cdf_mem_free(pChannelSet); + } + } else { + /* 5GHz info found */ + if (!f5GListPurged) { + /* purge previous results if found new */ + csr_purge_channel_power(pMac, + &pMac->scan. + channelPowerInfoList5G); + f5GListPurged = true; + } + if (CSR_IS_OPERATING_A_BAND(pMac)) { + /* add to the list of 5GHz channel sets */ + csr_ll_insert_tail(&pMac->scan. + channelPowerInfoList5G, + &pChannelSet->link, + LL_ACCESS_LOCK); + } else { + sms_log(pMac, LOGW, + FL("Adding 11A ch in B/G. 1st ch %d"), + pChannelSet->firstChannel); + cdf_mem_free(pChannelSet); + } + } + pChannelInfo++; /* move to next entry */ + } + return CDF_STATUS_SUCCESS; +} + +static void csr_clear_dfs_channel_list(tpAniSirGlobal pMac) +{ + tSirMbMsg *pMsg; + uint16_t msgLen; + + msgLen = (uint16_t) (sizeof(tSirMbMsg)); + pMsg = cdf_mem_malloc(msgLen); + if (NULL != pMsg) { + cdf_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = eWNI_SME_CLEAR_DFS_CHANNEL_LIST; + pMsg->msgLen = msgLen; + cds_send_mb_message_to_mac(pMsg); + } +} + +void csr_apply_power2_current(tpAniSirGlobal pMac) +{ + sms_log(pMac, LOG3, FL(" Updating Cfg with power settings")); + csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList24, + WNI_CFG_MAX_TX_POWER_2_4); + csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList5G, + WNI_CFG_MAX_TX_POWER_5); +} + +void csr_apply_channel_power_info_to_fw(tpAniSirGlobal mac_ctx, + tCsrChannel *ch_lst, + uint8_t *countryCode) +{ + int i; + uint8_t num_ch = 0; + uint8_t tempNumChannels = 0; + tCsrChannel tmp_ch_lst; + + if (ch_lst->numChannels) { + tempNumChannels = CSR_MIN(ch_lst->numChannels, + WNI_CFG_VALID_CHANNEL_LIST_LEN); + for (i = 0; i < tempNumChannels; i++) { + tmp_ch_lst.channelList[num_ch] = ch_lst->channelList[i]; + num_ch++; + } + tmp_ch_lst.numChannels = num_ch; + /* Store the channel+power info in the global place: Cfg */ + csr_apply_power2_current(mac_ctx); + csr_set_cfg_valid_channel_list(mac_ctx, tmp_ch_lst.channelList, + tmp_ch_lst.numChannels); + /* + * extend scan capability, build a scan list based on the + * channel list : channel# + active/passive scan + */ + csr_set_cfg_scan_control_list(mac_ctx, countryCode, + &tmp_ch_lst); + /* Send msg to Lim to clear DFS channel list */ + csr_clear_dfs_channel_list(mac_ctx); + } else { + sms_log(mac_ctx, LOGE, FL("11D channel list is empty")); + } + csr_set_cfg_country_code(mac_ctx, countryCode); +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void csr_diag_reset_country_information(tpAniSirGlobal pMac) +{ + + host_log_802_11d_pkt_type *p11dLog; + int Index; + WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type, + LOG_WLAN_80211D_C); + if (!p11dLog) + return; + + p11dLog->eventId = WLAN_80211D_EVENT_RESET; + cdf_mem_copy(p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3); + p11dLog->numChannel = pMac->scan.base_channels.numChannels; + if (p11dLog->numChannel <= HOST_LOG_MAX_NUM_CHANNEL) { + cdf_mem_copy(p11dLog->Channels, + pMac->scan.base_channels.channelList, + p11dLog->numChannel); + for (Index = 0; + Index < pMac->scan.base_channels.numChannels; + Index++) { + p11dLog->TxPwr[Index] = CDF_MIN( + pMac->scan.defaultPowerTable[Index].pwr, + pMac->roam.configParam.nTxPowerCap); + } + } + if (!pMac->roam.configParam.Is11dSupportEnabled) + p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED; + else + p11dLog->supportMultipleDomain = + WLAN_80211D_SUPPORT_MULTI_DOMAIN; + WLAN_HOST_DIAG_LOG_REPORT(p11dLog); +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +/** + * csr_apply_channel_power_info_wrapper() - sends channel info to fw + * @pMac: main MAC data structure + * + * This function sends the channel power info to firmware + * + * Return: none + */ +void csr_apply_channel_power_info_wrapper(tpAniSirGlobal pMac) +{ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_diag_reset_country_information(pMac); +#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ + csr_prune_channel_list_for_mode(pMac, &pMac->scan.base_channels); + csr_save_channel_power_for_band(pMac, false); + csr_save_channel_power_for_band(pMac, true); + /* apply the channel list, power settings, and the country code. */ + csr_apply_channel_power_info_to_fw(pMac, + &pMac->scan.base_channels, pMac->scan.countryCodeCurrent); + /* clear the 11d channel list */ + cdf_mem_set(&pMac->scan.channels11d, sizeof(pMac->scan.channels11d), 0); +} + +void csr_clear_votes_for_country_info(tpAniSirGlobal pMac) +{ + pMac->scan.countryCodeCount = 0; + cdf_mem_set(pMac->scan.votes11d, + sizeof(tCsrVotes11d) * CSR_MAX_NUM_COUNTRY_CODE, 0); +} + +void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode) +{ + bool match = false; + uint8_t i; + + /* convert to UPPER here so we are assured + * the strings are always in upper case. + */ + for (i = 0; i < 3; i++) { + pCountryCode[i] = (uint8_t) csr_to_upper(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 (!CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(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 = (cdf_mem_compare(pMac->scan.votes11d[i].countryCode, + pCountryCode, 2)); + if (match) { + break; + } + } + + if (match) { + pMac->scan.votes11d[i].votes++; + } else { + cdf_mem_copy(pMac->scan.votes11d[pMac->scan.countryCodeCount]. + countryCode, pCountryCode, 3); + pMac->scan.votes11d[pMac->scan.countryCodeCount].votes = 1; + pMac->scan.countryCodeCount++; + } + + return; +} + +bool csr_elected_country_info(tpAniSirGlobal pMac) +{ + bool fRet = false; + uint8_t maxVotes = 0; + uint8_t 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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) { + cdf_mem_copy(pMac->scan.countryCodeElected, + pMac->scan.votes11d[j].countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + cdf_mem_copy(pMac->scan.countryCode11d, + pMac->scan.votes11d[j].countryCode, + WNI_CFG_COUNTRY_CODE_LEN); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; +} + +/** + * csr_set_country_code() - Set country code + * @pMac: main MAC data structure + * @pCountry: ptr to Country Code + * + * This function sends the channel power info to firmware + * + * Return: none + */ +CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + v_REGDOMAIN_t domainId; + + if (pCountry) { + + status = csr_get_regulatory_domain_for_country(pMac, pCountry, + &domainId, + COUNTRY_USER); + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_copy(pMac->scan.countryCodeCurrent, + pCountry, + WNI_CFG_COUNTRY_CODE_LEN); + csr_set_cfg_country_code(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 csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list, + uint32_t *num_ch, + tChannelListWithPower *chn_pwr_info) +{ + tListElem *entry; + uint32_t chn_idx = 0, idx; + tCsrChannelPowerInfo *ch_set; + + /* Get 2.4Ghz first */ + entry = csr_ll_peek_head(list, LL_ACCESS_LOCK); + while (entry && (chn_idx < *num_ch)) { + ch_set = GET_BASE_ADDR(entry, tCsrChannelPowerInfo, link); + for (idx = 0; (idx < ch_set->numChannels) + && (chn_idx < *num_ch); idx++) { + chn_pwr_info[chn_idx].chanId = + (uint8_t) (ch_set->firstChannel + + (idx * ch_set->interChannelOffset)); + chn_pwr_info[chn_idx++].pwr = ch_set->txPower; + } + entry = csr_ll_next(list, entry, LL_ACCESS_LOCK); + } + *num_ch = chn_idx; + + return; +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx) +{ + host_log_802_11d_pkt_type *p11dLog; + tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint32_t nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp; + + WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type, + LOG_WLAN_80211D_C); + if (!p11dLog) + return; + + p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET; + cdf_mem_copy(p11dLog->countryCode, mac_ctx->scan.countryCode11d, 3); + p11dLog->numChannel = mac_ctx->scan.channels11d.numChannels; + if (p11dLog->numChannel > HOST_LOG_MAX_NUM_CHANNEL) + goto diag_end; + + cdf_mem_copy(p11dLog->Channels, + mac_ctx->scan.channels11d.channelList, + p11dLog->numChannel); + csr_get_channel_power_info(mac_ctx, + &mac_ctx->scan.channelPowerInfoList24, + &nChnInfo, chnPwrInfo); + nTmp = nChnInfo; + nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp; + csr_get_channel_power_info(mac_ctx, + &mac_ctx->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; + } + } + } +diag_end: + if (!mac_ctx->roam.configParam.Is11dSupportEnabled) + p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED; + else + p11dLog->supportMultipleDomain = + WLAN_80211D_SUPPORT_MULTI_DOMAIN; + WLAN_HOST_DIAG_LOG_REPORT(p11dLog); +} +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +/** + * csr_apply_country_information() - apply country code information + * @pMac: core MAC data structure + * + * This function programs the new country code + * + * Return: none + */ +void csr_apply_country_information(tpAniSirGlobal pMac) +{ + v_REGDOMAIN_t domainId; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (!csr_is11d_supported(pMac) + || 0 == pMac->scan.channelOf11dInfo) + return; + status = csr_get_regulatory_domain_for_country(pMac, + pMac->scan.countryCode11d, &domainId, COUNTRY_QUERY); + if (!CDF_IS_STATUS_SUCCESS(status)) + return; + /* Check whether we need to enforce default domain */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_diag_apply_country_info(pMac); +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + + if (pMac->scan.domainIdCurrent != domainId) + return; + if (pMac->scan.domainIdCurrent != domainId) { + sms_log(pMac, LOGW, FL("Domain Changed Old %d, new %d"), + pMac->scan.domainIdCurrent, domainId); + status = wma_set_reg_domain(pMac, domainId); + } + if (status != CDF_STATUS_SUCCESS) + sms_log(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; +} + +void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f) +{ + uint32_t idx, count = 0; + tSirMacChanInfo *chan_info; + tSirMacChanInfo *ch_info_start; + int32_t max_ch_idx; + bool tmp_bool; + uint8_t ch = 0; + + max_ch_idx = + (pMac->scan.base_channels.numChannels < + WNI_CFG_VALID_CHANNEL_LIST_LEN) ? + pMac->scan.base_channels.numChannels : + WNI_CFG_VALID_CHANNEL_LIST_LEN; + + chan_info = cdf_mem_malloc(sizeof(tSirMacChanInfo) * + WNI_CFG_VALID_CHANNEL_LIST_LEN); + if (NULL == chan_info) + return; + + cdf_mem_set(chan_info, sizeof(tSirMacChanInfo) * + WNI_CFG_VALID_CHANNEL_LIST_LEN, 0); + ch_info_start = chan_info; + for (idx = 0; idx < max_ch_idx; idx++) { + ch = pMac->scan.defaultPowerTable[idx].chanId; + tmp_bool = (fill_5f && CDS_IS_CHANNEL_5GHZ(ch)) + || (!fill_5f && CDS_IS_CHANNEL_24GHZ(ch)); + if (!tmp_bool) + continue; + + if (count >= WNI_CFG_VALID_CHANNEL_LIST_LEN) { + sms_log(pMac, LOGW, FL("count(%d) exceeded"), count); + break; + } + + chan_info->firstChanNum = + pMac->scan.defaultPowerTable[idx].chanId; + chan_info->numChannels = 1; + chan_info->maxTxPower = + CDF_MIN(pMac->scan.defaultPowerTable[idx].pwr, + pMac->roam.configParam.nTxPowerCap); + chan_info++; + count++; + } + if (count) { + csr_save_to_channel_power2_g_5_g(pMac, + count * sizeof(tSirMacChanInfo), ch_info_start); + } + cdf_mem_free(ch_info_start); +} + +bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId) +{ + bool fRet = false; + uint32_t i; + + for (i = 0; i < pMac->scan.base_channels.numChannels; i++) { + if (channelId == + pMac->scan.base_channels.channelList[i]) { + fRet = true; + break; + } + } + + return fRet; +} + +/* + * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d + */ +bool csr_learn_11dcountry_information(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, bool fForce) +{ + CDF_STATUS status; + uint8_t *pCountryCodeSelected; + bool fRet = false; + v_REGDOMAIN_t domainId; + tDot11fBeaconIEs *pIesLocal = pIes; + bool useVoting = false; + + if (CDF_SAP_MODE == cds_get_conparam()) + return CDF_STATUS_SUCCESS; + + if ((NULL == pSirBssDesc) && (NULL == pIes)) + useVoting = true; + + /* check if .11d support is enabled */ + if (!csr_is11d_supported(pMac)) + goto free_ie; + + if (false == useVoting) { + if (!pIesLocal && + (!CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies( + pMac, pSirBssDesc, &pIesLocal)))) + goto free_ie; + /* check if country information element is present */ + if (!pIesLocal->Country.present) + /* No country info */ + goto free_ie; + status = csr_get_regulatory_domain_for_country(pMac, + pIesLocal->Country.country, &domainId, + COUNTRY_QUERY); + if (CDF_IS_STATUS_SUCCESS(status) + && (domainId == REGDOMAIN_WORLD)) + goto free_ie; + } /* useVoting == false */ + + if (false == useVoting) + pCountryCodeSelected = pIesLocal->Country.country; + else + pCountryCodeSelected = pMac->scan.countryCodeElected; + + status = csr_get_regulatory_domain_for_country(pMac, + pCountryCodeSelected, &domainId, COUNTRY_IE); + if (status != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, FL("fail to get regId %d"), domainId); + fRet = false; + goto free_ie; + } + + /* updating 11d Country Code with Country code selected. */ + cdf_mem_copy(pMac->scan.countryCode11d, pCountryCodeSelected, + WNI_CFG_COUNTRY_CODE_LEN); + fRet = true; +free_ie: + if (!pIes && pIesLocal) { + /* locally allocated */ + cdf_mem_free(pIesLocal); + } + return fRet; +} + +void csr_save_scan_results(tpAniSirGlobal pMac, uint8_t reason, + uint8_t sessionId) +{ + sms_log(pMac, LOG4, "%s: Saving scan results", __func__); + + /* initialize this to false. profMoveInterimScanResultsToMainList() routine */ + /* will set this to the channel where an .11d beacon is seen */ + pMac->scan.channelOf11dInfo = 0; + /* move the scan results from interim list to the main scan list */ + csr_move_temp_scan_results_to_main_list(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 (csr_is11d_supported(pMac)) { + csr_apply_country_information(pMac); + } +} + +void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + switch (pCommand->u.scanCmd.reason) { + case eCsrScanAbortNormalScan: + default: + csr_scan_free_request(pMac, &pCommand->u.scanCmd.u.scanRequest); + break; + } + if (pCommand->u.scanCmd.pToRoamProfile) { + csr_release_profile(pMac, pCommand->u.scanCmd.pToRoamProfile); + cdf_mem_free(pCommand->u.scanCmd.pToRoamProfile); + } + cdf_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0); +} + +eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac, + tSmeCmd *pCommand, + bool 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; + default: + NextCommand = eCsrNextScanNothing; + break; + } + return NextCommand; +} + +/* Return whether the pCommand is finished. */ +bool csr_handle_scan11d1_failure(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + bool fRet = true; + + /* Apply back the default setting and passively scan one more time. */ + csr_apply_channel_power_info_wrapper(pMac); + pCommand->u.scanCmd.reason = eCsrScan11d2; + if (CDF_IS_STATUS_SUCCESS(csr_scan_channels(pMac, pCommand))) { + fRet = false; + } + + return fRet; +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void +csr_diag_scan_complete(tpAniSirGlobal pMac, + tSmeCmd *pCommand, + tSirSmeScanRsp *pScanRsp) +{ + host_log_scan_pkt_type *pScanLog = NULL; + tScanResultHandle hScanResult; + tCsrScanResultInfo *pScanResult; + tDot11fBeaconIEs *pIes; + int n = 0, c = 0; + CDF_STATUS status; + + WLAN_HOST_DIAG_LOG_ALLOC(pScanLog, + host_log_scan_pkt_type, + LOG_WLAN_SCAN_C); + if (!pScanLog) + return; + + if (eCsrScanProbeBss == 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) { + pScanLog->status = WLAN_SCAN_STATUS_FAILURE; + WLAN_HOST_DIAG_LOG_REPORT(pScanLog); + return; + } + + status = csr_scan_get_result(pMac, NULL, &hScanResult); + if (!CDF_IS_STATUS_SUCCESS(status)) { + WLAN_HOST_DIAG_LOG_REPORT(pScanLog); + return; + } + + pScanResult = csr_scan_result_get_next(pMac, hScanResult); + while (pScanResult != NULL) { + if (n < HOST_LOG_MAX_NUM_BSSID) { + status = csr_get_parsed_bss_description_ies(pMac, + &pScanResult->BssDescriptor, &pIes); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("fail to parse IEs")); + break; + } + cdf_mem_copy(pScanLog->bssid[n], + pScanResult->BssDescriptor.bssId, 6); + if (pIes && pIes->SSID.present && + HOST_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid) { + cdf_mem_copy(pScanLog->ssid[n], + pIes->SSID.ssid, + pIes->SSID.num_ssid); + } + cdf_mem_free(pIes); + n++; + } + c++; + pScanResult = csr_scan_result_get_next(pMac, hScanResult); + } + pScanLog->numSsid = (uint8_t) n; + pScanLog->totalSsid = (uint8_t) c; + csr_scan_result_purge(pMac, hScanResult); + WLAN_HOST_DIAG_LOG_REPORT(pScanLog); + + csr_diag_event_report(pMac, eCSR_EVENT_SCAN_COMPLETE, eSIR_SUCCESS, + eSIR_SUCCESS); + if (c > 0) + csr_diag_event_report(pMac, eCSR_EVENT_SCAN_RES_FOUND, + eSIR_SUCCESS, eSIR_SUCCESS); +} +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +static void +csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, + eCsrScanCompleteNextCommand *nxt_cmd, + bool *remove_cmd, uint32_t session_id) +{ + CDF_STATUS status; + switch (*nxt_cmd) { + case eCsrNext11dScan1Success: + case eCsrNext11dScan2Success: + sms_log(mac_ctx, LOG2, + FL("11dScan1/3 produced results. Reissue Active scan")); + /* + * if we found country information, no need to continue scanning + * further, bail out + */ + *remove_cmd = true; + *nxt_cmd = 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 + */ + *remove_cmd = csr_handle_scan11d1_failure(mac_ctx, pCommand); + if (*remove_cmd) + *nxt_cmd = eCsrNext11dScanComplete; + break; + case eCsrNextLostLinkScan1Success: + status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id, + eCsrLostLink1); + if (!CDF_IS_STATUS_SUCCESS(status)) + csr_scan_handle_failed_lostlink1(mac_ctx, session_id); + break; + case eCsrNextLostLinkScan2Success: + status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id, + eCsrLostLink2); + if (!CDF_IS_STATUS_SUCCESS(status)) + csr_scan_handle_failed_lostlink2(mac_ctx, session_id); + break; + case eCsrNextLostLinkScan3Success: + status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id, + eCsrLostLink3); + if (!CDF_IS_STATUS_SUCCESS(status)) + csr_scan_handle_failed_lostlink3(mac_ctx, session_id); + break; + case eCsrNextLostLinkScan1Failed: + csr_scan_handle_failed_lostlink1(mac_ctx, session_id); + break; + case eCsrNextLostLinkScan2Failed: + csr_scan_handle_failed_lostlink2(mac_ctx, session_id); + break; + case eCsrNextLostLinkScan3Failed: + csr_scan_handle_failed_lostlink3(mac_ctx, session_id); + break; + case eCsrNexteScanForSsidSuccess: + csr_scan_handle_search_for_ssid(mac_ctx, pCommand); + break; + case eCsrNexteScanForSsidFailure: + csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand); + break; + default: + break; + } +} + +/** + * csr_get_active_scan_entry() - To get scan entry from active command list + * + * @mac_ctx - MAC context + * @scan_id - Scan identifier of the scan request + * @entry - scan entry returned. + * + * Scan entry in the active scan list mapping to the sent scan id + * is returned to the caller. + * + * Return: CDF_STATUS. + */ +CDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac_ctx, + uint32_t scan_id, tListElem **entry) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tListElem *localentry; + tSmeCmd *cmd; + uint32_t cmd_scan_id = 0; + + csr_ll_lock(&mac_ctx->sme.smeScanCmdActiveList); + + if (csr_ll_is_list_empty(&mac_ctx->sme.smeScanCmdActiveList, + LL_ACCESS_NOLOCK)) { + sms_log(mac_ctx, LOGE, + FL(" Active list Empty scanId: %d"), scan_id); + return CDF_STATUS_SUCCESS; + } + localentry = csr_ll_peek_head(&mac_ctx->sme.smeScanCmdActiveList, + LL_ACCESS_NOLOCK); + do { + cmd = GET_BASE_ADDR(localentry, tSmeCmd, Link); + if (cmd->command == eSmeCommandScan) + cmd_scan_id = cmd->u.scanCmd.u.scanRequest.scan_id; + else if (cmd->command == eSmeCommandRemainOnChannel) + cmd_scan_id = cmd->u.remainChlCmd.scan_id; + if (cmd_scan_id == scan_id) { + sms_log(mac_ctx, LOG1, FL(" scanId Matched %d"), + scan_id); + *entry = localentry; + csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList); + return CDF_STATUS_SUCCESS; + } + localentry = csr_ll_next(&mac_ctx->sme.smeScanCmdActiveList, + localentry, LL_ACCESS_NOLOCK); + } while (localentry); + csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList); + return status; +} + +/* Return whether the command should be removed */ +bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) +{ + eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing; + tListElem *pEntry = NULL; + tSmeCmd *pCommand; + bool fRemoveCommand = true; + bool fSuccess; + uint32_t sessionId = 0; + + csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry); + if (!pEntry) { + sms_log(pMac, LOGE, + FL("Scan Completion called but NO cmd ACTIVE ...")); + return false; + } + + 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) { + sms_log(pMac, LOGW, + FL("Scan Completion called, but active SCAN cmd")); + return false; + } + + sessionId = pCommand->sessionId; + if (eSIR_SME_SUCCESS != pScanRsp->statusCode) { + fSuccess = 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 = (!csr_ll_is_list_empty(&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) { + sms_log(pMac, LOG1, FL("Filtering the scan results")); + csr_scan_filter_results(pMac); + } else { + sms_log(pMac, LOG1, + FL("11d_scan_done, flushing the scan results")); + } + pCommand->u.scanCmd.abortScanDueToBandChange = false; + } + csr_save_scan_results(pMac, pCommand->u.scanCmd.reason, sessionId); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR + csr_diag_scan_complete(pMac, pCommand, pScanRsp); +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess); + /* We reuse the command here instead reissue a new command */ + csr_handle_nxt_cmd(pMac, pCommand, &NextCommand, + &fRemoveCommand, sessionId); + return fRemoveCommand; +} + +static void +csr_scan_remove_dup_bss_description_from_interim_list(tpAniSirGlobal mac_ctx, + tSirBssDescription *bss_dscp, + tDot11fBeaconIEs *pIes) +{ + tListElem *pEntry; + tCsrScanResult *scan_bss_dscp; + int8_t scan_entry_rssi = 0; + /* + * 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. + */ + sms_log(mac_ctx, LOG4, FL(" for BSS " MAC_ADDRESS_STR " "), + MAC_ADDR_ARRAY(bss_dscp->bssId)); + csr_ll_lock(&mac_ctx->scan.tempScanResults); + pEntry = csr_ll_peek_head(&mac_ctx->scan.tempScanResults, + LL_ACCESS_NOLOCK); + while (pEntry) { + scan_bss_dscp = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + /* + * we have a duplicate scan results only when BSSID, SSID, + * Channel and NetworkType matches + */ + scan_entry_rssi = scan_bss_dscp->Result.BssDescriptor.rssi; + if (csr_is_duplicate_bss_description(mac_ctx, + &scan_bss_dscp->Result.BssDescriptor, bss_dscp, + pIes, false)) { + /* + * Following is mathematically a = (aX + b(100-X))/100 + * where: + * a = bss_dscp->rssi, b = scan_entry_rssi + * and X = CSR_SCAN_RESULT_RSSI_WEIGHT + */ + bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi * + CSR_SCAN_RESULT_RSSI_WEIGHT) + + ((int32_t) scan_entry_rssi * + (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100); + /* Remove the 'old' entry from the list */ + if (csr_ll_remove_entry(&mac_ctx->scan.tempScanResults, + pEntry, LL_ACCESS_NOLOCK)) { + csr_check_n_save_wsc_ie(mac_ctx, bss_dscp, + &scan_bss_dscp->Result. + BssDescriptor); + /* + * we need to free the memory associated with + * this node + */ + csr_free_scan_result_entry(mac_ctx, + scan_bss_dscp); + } + /* + * If we found a match, we can stop looking through + * the list. + */ + break; + } + pEntry = csr_ll_next(&mac_ctx->scan.tempScanResults, pEntry, + LL_ACCESS_NOLOCK); + } + + csr_ll_unlock(&mac_ctx->scan.tempScanResults); +} + +/* Caller allocated memory pfNewBssForConn to return whether new candidate for */ +/* current connection is found. Cannot be NULL */ +tCsrScanResult *csr_scan_save_bss_description_to_interim_list(tpAniSirGlobal pMac, + tSirBssDescription * + pBSSDescription, + tDot11fBeaconIEs *pIes) +{ + tCsrScanResult *pCsrBssDescription = NULL; + uint32_t cbBSSDesc; + uint32_t 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; + + sms_log(pMac, LOG4, FL("new BSS description, length %d, cbBSSDesc %d"), + cbAllocated, cbBSSDesc); + pCsrBssDescription = cdf_mem_malloc(cbAllocated); + if (NULL != pCsrBssDescription) { + cdf_mem_set(pCsrBssDescription, cbAllocated, 0); + cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor, + pBSSDescription, cbBSSDesc); + pCsrBssDescription->AgingCount = + (int32_t) pMac->roam.configParam.agingCount; + sms_log(pMac, LOG4, + FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "), + pCsrBssDescription->AgingCount, + MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor. + bssId)); + /* Save SSID separately for later use */ + if (pIes->SSID.present + && !csr_is_nullssid(pIes->SSID.ssid, pIes->SSID.num_ssid)) { + /* SSID not hidden */ + uint32_t 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 = + cdf_mc_timer_get_system_time(); + cdf_mem_copy(pCsrBssDescription->Result.ssId.ssId, + pIes->SSID.ssid, len); + } + csr_ll_insert_tail(&pMac->scan.tempScanResults, + &pCsrBssDescription->Link, LL_ACCESS_LOCK); + } + + return pCsrBssDescription; +} + +bool csr_is_duplicate_bss_description(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, + tDot11fBeaconIEs *pIes2, bool fForced) +{ + bool fMatch = false; + tSirMacCapabilityInfo *pCap1, *pCap2; + tDot11fBeaconIEs *pIes1 = NULL; + tDot11fBeaconIEs *pIesTemp = pIes2; + CDF_STATUS status; + + pCap1 = (tSirMacCapabilityInfo *) &pSirBssDesc1->capabilityInfo; + pCap2 = (tSirMacCapabilityInfo *) &pSirBssDesc2->capabilityInfo; + + if (pCap1->ess != pCap2->ess) + goto free_ies; + + if (pCap1->ess && + cdf_is_macaddr_equal((struct cdf_mac_addr *) pSirBssDesc1->bssId, + (struct cdf_mac_addr *) pSirBssDesc2->bssId) + && (fForced + || (cds_chan_to_band(pSirBssDesc1->channelId) == + cds_chan_to_band((pSirBssDesc2->channelId))))) { + fMatch = true; + /* Check for SSID match, if exists */ + status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1, + &pIes1); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_ies; + + if (NULL == pIesTemp) { + status = csr_get_parsed_bss_description_ies(pMac, + pSirBssDesc2, &pIesTemp); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_ies; + } + if (pIes1->SSID.present && pIesTemp->SSID.present) { + fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid, + pIes1->SSID.num_ssid, + pIesTemp->SSID.ssid, + pIesTemp->SSID.num_ssid, + true); + } + } else if (pCap1->ibss && (pSirBssDesc1->channelId == + pSirBssDesc2->channelId)) { + status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1, + &pIes1); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_ies; + + if (NULL == pIesTemp) { + status = csr_get_parsed_bss_description_ies(pMac, + pSirBssDesc2, &pIesTemp); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto free_ies; + } + + /* Same channel cannot have same SSID for different IBSS */ + if (pIes1->SSID.present && pIesTemp->SSID.present) { + fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid, + pIes1->SSID.num_ssid, + pIesTemp->SSID.ssid, + pIesTemp->SSID.num_ssid, + true); + } + } + /* In case of P2P devices, ess and ibss will be set to zero */ + else if (!pCap1->ess && + cdf_is_macaddr_equal( + (struct cdf_mac_addr *) pSirBssDesc1->bssId, + (struct cdf_mac_addr *) pSirBssDesc2->bssId)) { + fMatch = true; + } + +free_ies: + if (pIes1) + cdf_mem_free(pIes1); + if ((NULL == pIes2) && pIesTemp) + /* locally allocated */ + cdf_mem_free(pIesTemp); + return fMatch; +} + +bool csr_is_network_type_equal(tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2) +{ + return pSirBssDesc1->nwType == pSirBssDesc2->nwType; +} + +/* to check whether the BSS matches the dot11Mode */ +static bool csr_scan_is_bss_allowed(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + bool fAllowed = false; + eCsrPhyMode phyMode; + + if (CDF_IS_STATUS_SUCCESS + (csr_get_phy_mode_from_bss(pMac, pBssDesc, &phyMode, pIes))) { + switch (pMac->roam.configParam.phyMode) { + case eCSR_DOT11_MODE_11b: + fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode); + break; + case eCSR_DOT11_MODE_11g: + fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode); + break; + case eCSR_DOT11_MODE_11g_ONLY: + fAllowed = (bool) (eCSR_DOT11_MODE_11g == phyMode); + break; + case eCSR_DOT11_MODE_11a: + fAllowed = (bool) ((eCSR_DOT11_MODE_11b != phyMode) + && (eCSR_DOT11_MODE_11g != phyMode)); + break; + case eCSR_DOT11_MODE_11n_ONLY: + fAllowed = (bool) ((eCSR_DOT11_MODE_11n == phyMode)); + break; + +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac_ONLY: + fAllowed = (bool) ((eCSR_DOT11_MODE_11ac == phyMode)); + break; +#endif + case eCSR_DOT11_MODE_11b_ONLY: + fAllowed = (bool) (eCSR_DOT11_MODE_11b == phyMode); + break; + case eCSR_DOT11_MODE_11n: +#ifdef WLAN_FEATURE_11AC + case eCSR_DOT11_MODE_11ac: +#endif + default: + fAllowed = true; + break; + } + } + + return fAllowed; +} + +/* Return pIes to caller for future use when returning true. */ +static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac, + uint8_t *pChannels, + uint8_t numChn, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs **ppIes) +{ + bool valid = false; + tDot11fBeaconIEs *pIes = NULL; + uint8_t index; + CDF_STATUS status; + + 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 funtions. 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) { + valid = true; + break; + } + } + *ppIes = NULL; + if (valid) { + status = csr_get_parsed_bss_description_ies(pMac, pBssDesc, + &pIes); + if (!CDF_IS_STATUS_SUCCESS(status)) + return false; + + valid = csr_scan_is_bss_allowed(pMac, pBssDesc, pIes); + if (valid) + *ppIes = pIes; + else + cdf_mem_free(pIes); + } + return valid; +} + +static void csr_update_scantype(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIes, + uint8_t channelId) +{ + if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType) + return; + + if (csr_is11d_supported(pMac)) { + /* Check whether the BSS is acceptable based on + * 11d info and our config. + */ + if (!csr_match_country_code(pMac, NULL, pIes)) + return; + + /* check if channel is acceptable by config */ + if (csr_is_supported_channel(pMac, channelId)) + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + + } else + pMac->scan.curScanType = eSIR_ACTIVE_SCAN; + +} + +/* Return whether last scan result is received */ +static bool csr_scan_process_scan_results(tpAniSirGlobal pMac, tSmeCmd *pCommand, + tSirSmeScanRsp *pScanRsp, + bool *pfRemoveCommand) +{ + bool fRet = false, fRemoveCommand = false; + + sms_log(pMac, LOG1, FL("scan reason = %d, response status code = %d"), + pCommand->u.scanCmd.reason, pScanRsp->statusCode); + fRemoveCommand = csr_scan_complete(pMac, pScanRsp); + fRet = true; + if (pfRemoveCommand) { + *pfRemoveCommand = fRemoveCommand; + } + return fRet; +} + +/* csr_scan_process_single_bssdescr() - Add a bssdescriptor to scan table + * + * @mac_ctx - MAC context + * @bssdescr - Pointer to BSS description structure that contains + * everything from beacon/probe response frame and additional + * information. + * @scan_id - Scan identifier of the scan request that was running + * when this beacon was received. Reserved for future when + * firmware provides that information. + * @flags - Reserved for future use. + * + * Callback routine called by LIM when it receives a beacon or probe response + * from the device. 802.11 frame is already converted to internal + * tSirBssDescription data structure. + * + * Return: 0 or other error codes. + */ + +CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal mac_ctx, + tSirBssDescription *bssdescr, + uint32_t scan_id, uint32_t flags) +{ + tDot11fBeaconIEs *ies = NULL; + uint8_t *chanlist = NULL; + uint8_t cnt_channels = 0; + uint32_t len = sizeof(mac_ctx->roam.validChannelList); + + sms_log(mac_ctx, LOG4, "CSR: Processing single bssdescr"); + if (CDF_IS_STATUS_SUCCESS( + csr_get_cfg_valid_channels(mac_ctx, + (uint8_t *) mac_ctx->roam.validChannelList, + &len))) { + chanlist = mac_ctx->roam.validChannelList; + cnt_channels = (uint8_t) len; + } else { + /* Cannot continue */ + sms_log(mac_ctx, LOGW, + FL("Received results on invalid channel")); + return CDF_STATUS_E_INVAL; + } + + if (csr_scan_validate_scan_result(mac_ctx, chanlist, + cnt_channels, bssdescr, &ies)) { + csr_scan_remove_dup_bss_description_from_interim_list + (mac_ctx, bssdescr, ies); + csr_scan_save_bss_description_to_interim_list + (mac_ctx, bssdescr, ies); + csr_update_scantype(mac_ctx, ies, bssdescr->channelId); + /* Free the resource */ + if (ies != NULL) + cdf_mem_free(ies); + } + return CDF_STATUS_SUCCESS; +} + + +bool csr_scan_is_wild_card_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + uint8_t bssid[CDF_MAC_ADDR_SIZE] = {0}; + bool f = cdf_mem_compare(pCommand->u.scanCmd.u.scanRequest.bssid.bytes, + bssid, sizeof(struct cdf_mac_addr)); + /* + * It is not a wild card scan if the bssid is not broadcast and + * the number of SSID is 1. + */ + return (f || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid.bytes[0])) + && (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1); +} + +CDF_STATUS csr_scan_sme_scan_response(tpAniSirGlobal pMac, + void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand; + eCsrScanStatus scanStatus; + tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf; + bool fRemoveCommand = true; + eCsrScanReason reason = eCsrScanOther; + + csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry); + if (!pEntry) + goto error_handling; + + sms_log(pMac, LOG1, FL("Scan completion called:scan_id %d, entry = %p"), + pScanRsp->scan_id, pEntry); + + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandScan != pCommand->command) + goto error_handling; + + scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ? + eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE; + reason = pCommand->u.scanCmd.reason; + switch (pCommand->u.scanCmd.reason) { + case eCsrScanAbortNormalScan: + break; + case eCsrScanP2PFindPeer: + scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ? + eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE; + csr_scan_process_scan_results(pMac, pCommand, pScanRsp, NULL); + break; + default: + if (csr_scan_process_scan_results(pMac, pCommand, pScanRsp, + &fRemoveCommand) + && csr_scan_is_wild_card_scan(pMac, pCommand) + && !pCommand->u.scanCmd.u.scanRequest.p2pSearch) { + + /* Age out logic will be taken care by the age out timer */ + } + break; + } + if (fRemoveCommand) + csr_release_scan_command(pMac, pCommand, scanStatus); + sme_process_pending_queue(pMac); + return status; + +error_handling: +#ifdef FEATURE_WLAN_SCAN_PNO + if (pMac->pnoOffload && pScanRsp->statusCode == eSIR_PNO_SCAN_SUCCESS) { + sms_log(pMac, LOGE, FL("PNO Scan completion called.")); + csr_save_scan_results(pMac, eCsrScanCandidateFound, + pScanRsp->sessionId); + return CDF_STATUS_SUCCESS; + } else { + /* + * Scan completion was called, PNO is active, but scan + * response was not PNO + */ + sms_log(pMac, LOGE, + FL("Scan completion called, scan rsp was not PNO.")); + return CDF_STATUS_E_FAILURE; + } +#endif + sms_log(pMac, LOGE, FL("Scan completion called, but no active SCAN command.")); + return CDF_STATUS_E_FAILURE; +} + +tCsrScanResultInfo *csr_scan_result_get_first(tpAniSirGlobal pMac, + tScanResultHandle hScanResult) +{ + tListElem *pEntry; + tCsrScanResult *pResult; + tCsrScanResultInfo *pRet = NULL; + tScanResultList *pResultList = (tScanResultList *) hScanResult; + + if (pResultList) { + csr_ll_lock(&pResultList->List); + pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK); + if (pEntry) { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pRet = &pResult->Result; + } + pResultList->pCurEntry = pEntry; + csr_ll_unlock(&pResultList->List); + } + + return pRet; +} + +tCsrScanResultInfo *csr_scan_result_get_next(tpAniSirGlobal pMac, + tScanResultHandle hScanResult) +{ + tListElem *pEntry = NULL; + tCsrScanResult *pResult = NULL; + tCsrScanResultInfo *pRet = NULL; + tScanResultList *pResultList = (tScanResultList *) hScanResult; + + if (!pResultList) + return NULL; + + csr_ll_lock(&pResultList->List); + if (NULL == pResultList->pCurEntry) { + pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK); + } else { + pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry, + LL_ACCESS_NOLOCK); + } + if (pEntry) { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + pRet = &pResult->Result; + } + pResultList->pCurEntry = pEntry; + csr_ll_unlock(&pResultList->List); + return pRet; +} + +/* + * This function moves the first BSS that matches the bssid to the + * head of the result + */ +CDF_STATUS csr_move_bss_to_head_from_bssid(tpAniSirGlobal pMac, + struct cdf_mac_addr *bssid, + tScanResultHandle hScanResult) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tScanResultList *pResultList = (tScanResultList *) hScanResult; + tCsrScanResult *pResult = NULL; + tListElem *pEntry = NULL; + + if (!(pResultList && bssid)) + return status; + + csr_ll_lock(&pResultList->List); + pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK); + while (pEntry) { + pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); + if (cdf_mem_compare(bssid, pResult->Result.BssDescriptor.bssId, + sizeof(struct cdf_mac_addr))) { + status = CDF_STATUS_SUCCESS; + csr_ll_remove_entry(&pResultList->List, pEntry, + LL_ACCESS_NOLOCK); + csr_ll_insert_head(&pResultList->List, pEntry, + LL_ACCESS_NOLOCK); + break; + } + pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry, + LL_ACCESS_NOLOCK); + } + csr_ll_unlock(&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. */ +bool csr_scan_age_out_bss(tpAniSirGlobal pMac, tCsrScanResult *pResult) +{ + bool fRet = false; + uint32_t i; + tCsrRoamSession *pSession; + bool isConnBssfound = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (!CSR_IS_SESSION_VALID(pMac, i)) + continue; + pSession = CSR_GET_SESSION(pMac, i); + /* Not to remove the BSS we are connected to. */ + if (csr_is_conn_state_connected_infra(pMac, i) + && (NULL != pSession->pConnectBssDesc) + && (csr_is_duplicate_bss_description(pMac, + &pResult->Result.BssDescriptor, + pSession->pConnectBssDesc, NULL, false))) { + isConnBssfound = true; + break; + } + } + if (isConnBssfound) { + /* + * Reset the counter so that aging out of connected BSS won't + * hapeen too soon + */ + pResult->AgingCount = + (int32_t) pMac->roam.configParam.agingCount; + sms_log(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 = + (uint32_t) cdf_mc_timer_get_system_ticks(); + return fRet; + } + sms_log(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 (csr_ll_remove_entry(&pMac->scan.scanResultList, &pResult->Link, + LL_ACCESS_NOLOCK)) { + if (cdf_is_macaddr_equal( + (struct cdf_mac_addr *) &pResult->Result.BssDescriptor.bssId, + (struct cdf_mac_addr *) &pMac->scan.currentCountryBssid)) { + sms_log(pMac, LOGW, + FL("Aging out 11d BSS " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY( + pResult->Result.BssDescriptor.bssId)); + pMac->scan.currentCountryRSSI = -128; + } + csr_free_scan_result_entry(pMac, pResult); + fRet = true; + } + return fRet; +} + +CDF_STATUS csr_scan_age_results(tpAniSirGlobal pMac, + tSmeGetScanChnRsp *pScanChnInfo) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry, *tmpEntry; + tCsrScanResult *pResult; + tLimScanChn *pChnInfo; + uint8_t i; + + csr_ll_lock(&pMac->scan.scanResultList); + for (i = 0; i < pScanChnInfo->numChn; i++) { + pChnInfo = &pScanChnInfo->scanChn[i]; + pEntry = + csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while (pEntry) { + tmpEntry = + csr_ll_next(&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) { + sms_log(pMac, LOGW, + " age out due to ref count"); + csr_scan_age_out_bss(pMac, pResult); + } else { + pResult->AgingCount--; + sms_log(pMac, LOGW, + FL + ("Decremented AgingCount=%d for BSS " + MAC_ADDRESS_STR ""), + pResult->AgingCount, + MAC_ADDR_ARRAY(pResult->Result. + BssDescriptor. + bssId)); + } + } + pEntry = tmpEntry; + } + } + csr_ll_unlock(&pMac->scan.scanResultList); + + return status; +} + +CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, + tCsrScanRequest *pScanReq, + tScanReqParam *pScanReqParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeScanReq *pMsg; + uint16_t msgLen; + tSirScanType scanType = pScanReq->scanType; + uint32_t minChnTime; /* in units of milliseconds */ + uint32_t maxChnTime; /* in units of milliseconds */ + uint32_t i; + uint8_t selfMacAddr[CDF_MAC_ADDR_SIZE]; + uint8_t *pSelfMac = NULL; + + msgLen = (uint16_t) (sizeof(tSirSmeScanReq) - + sizeof(pMsg->channelList.channelNumber) + + (sizeof(pMsg->channelList.channelNumber) * + pScanReq->ChannelInfo.numOfChannels)) + + (pScanReq->uIEFieldLen); + + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) { + sms_log(pMac, LOGE, FL("memory allocation failed")); + sms_log(pMac, LOG1, FL("Failed: SId: %d FirstMatch = %d" + " UniqueResult = %d freshScan = %d hiddenSsid = %d"), + sessionId, pScanReqParam->bReturnAfter1stMatch, + pScanReqParam->fUniqueResult, pScanReqParam->freshScan, + pScanReqParam->hiddenSsid); + sms_log(pMac, LOG1, + FL("scanType = %u BSSType = %u numOfSSIDs = %d" + " numOfChannels = %d requestType = %d p2pSearch = %d\n"), + pScanReq->scanType, pScanReq->BSSType, + pScanReq->SSIDs.numOfSSIDs, + pScanReq->ChannelInfo.numOfChannels, + pScanReq->requestType, pScanReq->p2pSearch); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set(pMsg, msgLen, 0); + pMsg->messageType = eWNI_SME_SCAN_REQ; + pMsg->length = msgLen; + /* ToDO: Fill in session info when we need to do scan base on session */ + if ((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) + sms_log(pMac, LOGE, FL(" Invalid Sme Session ID = %d"), + pMsg->sessionId); + pMsg->transactionId = 0; + pMsg->dot11mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(pMac, + csr_find_best_phy_mode(pMac, + pMac->roam.configParam.phyMode)); + pMsg->bssType = csr_translate_bsstype_to_mac_type(pScanReq->BSSType); + + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + pSelfMac = (uint8_t *) + &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 = (uint8_t *) + &pMac->roam.roamSession[i].selfMacAddr; + break; + } + } + if (CSR_ROAM_SESSION_MAX == i) { + uint32_t len = CDF_MAC_ADDR_SIZE; + pSelfMac = selfMacAddr; + status = wlan_cfg_get_str(pMac, WNI_CFG_STA_ID, + pSelfMac, &len); + if (!CDF_IS_STATUS_SUCCESS(status) + || (len < CDF_MAC_ADDR_SIZE)) { + sms_log(pMac, LOGE, + FL("Can't get self MAC address = %d"), + status); + /* Force failed status */ + status = CDF_STATUS_E_FAILURE; + goto send_scan_req; + } + } + } + cdf_mem_copy((uint8_t *) pMsg->selfMacAddr, + pSelfMac, sizeof(tSirMacAddr)); + + /* sir_copy_mac_addr */ + cdf_mem_copy(pMsg->bssId, &pScanReq->bssid, sizeof(tSirMacAddr)); + if (cdf_is_macaddr_zero(&pScanReq->bssid)) + cdf_mem_set(pMsg->bssId, sizeof(tSirMacAddr), 0xff); + else + cdf_mem_copy(pMsg->bssId, pScanReq->bssid.bytes, + CDF_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) + && (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 = 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++) { + cdf_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 = minChnTime; + pMsg->maxChannelTime = maxChnTime; + /* hidden SSID option */ + pMsg->hiddenSsid = pScanReqParam->hiddenSsid; + /* rest time */ + pMsg->restTime = pScanReq->restTime; + 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 = + (uint8_t) pScanReq->ChannelInfo.numOfChannels; + if (pScanReq->ChannelInfo.numOfChannels) { + /* Assuming the channelNumber is uint8_t (1 byte) */ + cdf_mem_copy(pMsg->channelList.channelNumber, + pScanReq->ChannelInfo.ChannelList, + pScanReq->ChannelInfo.numOfChannels); + } + + pMsg->uIEFieldLen = (uint16_t) pScanReq->uIEFieldLen; + pMsg->uIEFieldOffset = (uint16_t) (sizeof(tSirSmeScanReq) - + sizeof(pMsg->channelList.channelNumber) + + (sizeof(pMsg->channelList.channelNumber) * + pScanReq->ChannelInfo.numOfChannels)); + if (pScanReq->uIEFieldLen != 0) { + cdf_mem_copy((uint8_t *) pMsg + pMsg->uIEFieldOffset, + pScanReq->pIEField, pScanReq->uIEFieldLen); + } + pMsg->p2pSearch = pScanReq->p2pSearch; + pMsg->scan_id = pScanReq->scan_id; + +send_scan_req: + sms_log(pMac, LOG1, + FL("scanId %d domainIdCurrent %d scanType %d bssType %d requestType %d numChannels %d"), + pMsg->scan_id, pMac->scan.domainIdCurrent, pMsg->scanType, + pMsg->bssType, pScanReq->requestType, + pMsg->channelList.numChannels); + + for (i = 0; i < pMsg->channelList.numChannels; i++) { + sms_log(pMac, LOG1, FL("channelNumber[%d]= %d"), i, + pMsg->channelList.channelNumber[i]); + } + + if (CDF_IS_STATUS_SUCCESS(status)) { + status = cds_send_mb_message_to_mac(pMsg); + } else { + sms_log(pMac, LOGE, + FL("failed to send down scan req with status = %d"), + status); + cdf_mem_free(pMsg); + } + return status; +} + +CDF_STATUS csr_send_mb_scan_result_req(tpAniSirGlobal pMac, + uint32_t sessionId, + tScanReqParam *pScanReqParam) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeScanReq *pMsg; + uint16_t msgLen; + + msgLen = (uint16_t) (sizeof(tSirSmeScanReq)); + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pMsg, msgLen, 0); + pMsg->messageType = eWNI_SME_SCAN_REQ; + pMsg->length = 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 = cds_send_mb_message_to_mac(pMsg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("Failed to send down scan req with status = %d\n"), + status); + } + return status; +} + +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +static void csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + host_log_scan_pkt_type *pScanLog = NULL; + + WLAN_HOST_DIAG_LOG_ALLOC(pScanLog, + host_log_scan_pkt_type, + LOG_WLAN_SCAN_C); + if (!pScanLog) + return; + + if (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 = + (uint8_t) pCommand->u.scanCmd.u.scanRequest.minChnTime; + pScanLog->maxChnTime = + (uint8_t) pCommand->u.scanCmd.u.scanRequest.maxChnTime; + pScanLog->numChannel = + (uint8_t) pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + if (pScanLog->numChannel && + (pScanLog->numChannel < HOST_LOG_MAX_NUM_CHANNEL)) { + cdf_mem_copy(pScanLog->channels, + pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, + pScanLog->numChannel); + } + WLAN_HOST_DIAG_LOG_REPORT(pScanLog); +} +#else +#define csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) (void)0; +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ + +CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tScanReqParam scanReq; + + /* + * 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 (eCsrScanProbeBss == pCommand->u.scanCmd.reason) + scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION; + csr_diag_scan_channels(pMac, pCommand); + csr_clear_votes_for_country_info(pMac); + status = csr_send_mb_scan_req(pMac, pCommand->sessionId, + &pCommand->u.scanCmd.u.scanRequest, + &scanReq); + return status; +} + +static CDF_STATUS +csr_issue_user_scan(tpAniSirGlobal mac_ctx, tSmeCmd *cmd) +{ + int i, j; + CDF_STATUS status; + uint32_t len = 0; + uint8_t *ch_lst = NULL; + tCsrChannelInfo new_ch_info = { 0, NULL }; + + if (!mac_ctx->roam.configParam.fScanTwice) + return csr_scan_channels(mac_ctx, cmd); + + /* We scan 2.4 channel twice */ + if (cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels + && (NULL != cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)) { + len = cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + /* allocate twice the channel */ + new_ch_info.ChannelList = (uint8_t *) cdf_mem_malloc(len * 2); + ch_lst = cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList; + } else { + /* get the valid channel list to scan all. */ + len = sizeof(mac_ctx->roam.validChannelList); + status = csr_get_cfg_valid_channels(mac_ctx, + (uint8_t *) mac_ctx->roam.validChannelList, &len); + if (CDF_IS_STATUS_SUCCESS(status)) { + /* allocate twice the channel */ + new_ch_info.ChannelList = + (uint8_t *) cdf_mem_malloc(len * 2); + ch_lst = mac_ctx->roam.validChannelList; + } + } + if (NULL == new_ch_info.ChannelList) { + new_ch_info.numOfChannels = 0; + } else { + j = 0; + for (i = 0; i < len; i++) { + new_ch_info.ChannelList[j++] = ch_lst[i]; + if (CDS_MAX_24GHz_CHANNEL_NUMBER >= ch_lst[i]) + new_ch_info.ChannelList[j++] = ch_lst[i]; + } + if (NULL != + cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) { + /* + * ch_lst points to the channellist from the command, + * free it. + */ + cdf_mem_free( + cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList); + cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = + NULL; + } + cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j; + cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList = + new_ch_info.ChannelList; + } + + return csr_scan_channels(mac_ctx, cmd); +} + +CDF_STATUS csr_process_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + sms_log(pMac, LOG3, + FL("starting SCAN cmd in %d state. reason %d"), + pCommand->u.scanCmd.lastRoamState[pCommand->sessionId], + pCommand->u.scanCmd.reason); + + switch (pCommand->u.scanCmd.reason) { + case eCsrScanUserRequest: + status = csr_issue_user_scan(pMac, pCommand); + break; + default: + status = csr_scan_channels(pMac, pCommand); + break; + } + + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_release_scan_command(pMac, pCommand, eCSR_SCAN_FAILURE); + } + + return status; +} + +/** + * csr_scan_copy_request_valid_channels_only() - scan request of valid channels + * @mac_ctx : pointer to Global Mac Structure + * @dst_req: pointer to tCsrScanRequest + * @skip_dfs_chnl: 1 - skip dfs channel, 0 - don't skip dfs channel + * @src_req: pointer to tCsrScanRequest + * + * This function makes a copy of scan request with valid channels + * + * Return: none + */ +static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, + tCsrScanRequest *dst_req, uint8_t skip_dfs_chnl, + tCsrScanRequest *src_req) +{ + uint32_t index = 0; + uint32_t new_index = 0; + + for (index = 0; index < src_req->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 (src_req->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL && + ((csr_roam_is_valid_channel(mac_ctx, + src_req->ChannelInfo.ChannelList[index])) || + ((eCSR_SCAN_P2P_DISCOVERY == src_req->requestType) && + CSR_IS_SOCIAL_CHANNEL( + src_req->ChannelInfo.ChannelList[index])))) { + if (((src_req->skipDfsChnlInP2pSearch || skip_dfs_chnl) + && (CHANNEL_STATE_DFS == + cds_get_channel_state(src_req-> + ChannelInfo. + ChannelList + [index]))) + ) { +#ifdef FEATURE_WLAN_LFR + sms_log(mac_ctx, LOG2, + FL(" reqType=%d, numOfChannels=%d, ignoring DFS channel %d"), + src_req->requestType, + src_req->ChannelInfo.numOfChannels, + src_req->ChannelInfo.ChannelList + [index]); +#endif + continue; + } + + dst_req->ChannelInfo.ChannelList[new_index] = + src_req->ChannelInfo.ChannelList[index]; + new_index++; + } + } + dst_req->ChannelInfo.numOfChannels = new_index; +} + +/** + * csr_scan_copy_request() - Function to copy scan request + * @mac_ctx : pointer to Global Mac Structure + * @dst_req: pointer to tCsrScanRequest + * @src_req: pointer to tCsrScanRequest + * + * This function makes a copy of scan request + * + * Return: 0 - Success, Error number - Failure + */ +CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, + tCsrScanRequest *dst_req, + tCsrScanRequest *src_req) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t len = sizeof(mac_ctx->roam.validChannelList); + uint32_t index = 0; + uint32_t new_index = 0; + CHANNEL_STATE channel_state; + bool skip_dfs_chnl = + mac_ctx->roam.configParam.initial_scan_no_dfs_chnl || + !mac_ctx->scan.fEnableDFSChnlScan; + + status = csr_scan_free_request(mac_ctx, dst_req); + if (!CDF_IS_STATUS_SUCCESS(status)) + goto complete; + cdf_mem_copy(dst_req, src_req, sizeof(tCsrScanRequest)); + /* Re-initialize the pointers to NULL since we did a copy */ + dst_req->pIEField = NULL; + dst_req->ChannelInfo.ChannelList = NULL; + dst_req->SSIDs.SSIDList = NULL; + + if (src_req->uIEFieldLen) { + dst_req->pIEField = + cdf_mem_malloc(src_req->uIEFieldLen); + if (NULL == dst_req->pIEField) { + status = CDF_STATUS_E_NOMEM; + sms_log(mac_ctx, LOGE, + FL("No memory for scanning IE fields")); + goto complete; + } else { + status = CDF_STATUS_SUCCESS; + cdf_mem_copy(dst_req->pIEField, src_req->pIEField, + src_req->uIEFieldLen); + dst_req->uIEFieldLen = src_req->uIEFieldLen; + } + } + + /* Allocate memory for IE field */ + if (src_req->ChannelInfo.numOfChannels == 0) { + dst_req->ChannelInfo.ChannelList = NULL; + dst_req->ChannelInfo.numOfChannels = 0; + } else { + dst_req->ChannelInfo.ChannelList = + cdf_mem_malloc(src_req->ChannelInfo.numOfChannels * + sizeof(*dst_req->ChannelInfo.ChannelList)); + if (NULL == dst_req->ChannelInfo.ChannelList) { + status = CDF_STATUS_E_NOMEM; + dst_req->ChannelInfo.numOfChannels = 0; + sms_log(mac_ctx, LOGE, + FL("No memory for scanning Channel List")); + goto complete; + } + + if ((src_req->scanType == eSIR_PASSIVE_SCAN) && + (src_req->requestType == eCSR_SCAN_REQUEST_11D_SCAN)) { + for (index = 0; index < src_req->ChannelInfo. + numOfChannels; index++) { + channel_state = + cds_get_channel_state(src_req-> + ChannelInfo. + ChannelList[index]); + if (src_req->ChannelInfo.ChannelList[index] < + MIN_11P_CHANNEL && + ((CHANNEL_STATE_ENABLE == + channel_state) || + ((CHANNEL_STATE_DFS == channel_state) && + !skip_dfs_chnl))) { + dst_req->ChannelInfo.ChannelList + [new_index] = + src_req-> + ChannelInfo. + ChannelList + [index]; + new_index++; + } + } + dst_req->ChannelInfo.numOfChannels = new_index; + } else if (CDF_IS_STATUS_SUCCESS( + csr_get_cfg_valid_channels(mac_ctx, + mac_ctx->roam.validChannelList, + &len))) { + new_index = 0; + mac_ctx->roam.numValidChannels = len; + csr_scan_copy_request_valid_channels_only(mac_ctx, + dst_req, skip_dfs_chnl, + src_req); + } else { + sms_log(mac_ctx, LOGE, + FL("Couldn't get the valid Channel List, keeping requester's list")); + new_index = 0; + for (index = 0; index < src_req->ChannelInfo. + numOfChannels; index++) { + if (src_req->ChannelInfo.ChannelList[index] < + MIN_11P_CHANNEL) { + dst_req->ChannelInfo. + ChannelList[new_index] = + src_req->ChannelInfo. + ChannelList[index]; + new_index++; + } + } + dst_req->ChannelInfo.numOfChannels = + new_index; + } + } /* Allocate memory for Channel List */ + if (src_req->SSIDs.numOfSSIDs == 0) { + dst_req->SSIDs.numOfSSIDs = 0; + dst_req->SSIDs.SSIDList = NULL; + } else { + dst_req->SSIDs.SSIDList = + cdf_mem_malloc(src_req->SSIDs.numOfSSIDs * + sizeof(*dst_req->SSIDs.SSIDList)); + if (NULL == dst_req->SSIDs.SSIDList) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { + dst_req->SSIDs.numOfSSIDs = + src_req->SSIDs.numOfSSIDs; + cdf_mem_copy(dst_req->SSIDs.SSIDList, + src_req->SSIDs.SSIDList, + src_req->SSIDs.numOfSSIDs * + sizeof(*dst_req->SSIDs.SSIDList)); + } else { + dst_req->SSIDs.numOfSSIDs = 0; + sms_log(mac_ctx, LOGE, + FL("No memory for scanning SSID List")); + goto complete; + } + } /* Allocate memory for SSID List */ + dst_req->p2pSearch = src_req->p2pSearch; + dst_req->skipDfsChnlInP2pSearch = + src_req->skipDfsChnlInP2pSearch; + dst_req->scan_id = src_req->scan_id; + dst_req->timestamp = src_req->timestamp; + +complete: + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_scan_free_request(mac_ctx, dst_req); + } + + return status; +} + +CDF_STATUS csr_scan_free_request(tpAniSirGlobal pMac, tCsrScanRequest *pReq) +{ + + if (pReq->ChannelInfo.ChannelList) { + cdf_mem_free(pReq->ChannelInfo.ChannelList); + pReq->ChannelInfo.ChannelList = NULL; + } + pReq->ChannelInfo.numOfChannels = 0; + if (pReq->pIEField) { + cdf_mem_free(pReq->pIEField); + pReq->pIEField = NULL; + } + pReq->uIEFieldLen = 0; + if (pReq->SSIDs.SSIDList) { + cdf_mem_free(pReq->SSIDs.SSIDList); + pReq->SSIDs.SSIDList = NULL; + } + pReq->SSIDs.numOfSSIDs = 0; + + return CDF_STATUS_SUCCESS; +} + +void csr_scan_call_callback(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 { + sms_log(pMac, LOG2, "%s:%d - Callback NULL!!!", __func__, + __LINE__); + } +} + +void csr_scan_stop_timers(tpAniSirGlobal pMac) +{ + if (0 != pMac->scan.scanResultCfgAgingTime) { + csr_scan_stop_result_cfg_aging_timer(pMac); + } + +} + +#ifdef WLAN_AP_STA_CONCURRENCY +/** + * csr_sta_ap_conc_timer_handler - Function to handle STA,AP concurrency timer + * @pv: pointer variable + * + * Function handles STA,AP concurrency timer + * + * Return: none + */ +static void csr_sta_ap_conc_timer_handler(void *pv) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv); + tListElem *entry; + tSmeCmd *scan_cmd; + uint32_t session_id = CSR_SESSION_ID_INVALID; + tCsrScanRequest scan_req; + tSmeCmd *send_scancmd = NULL; + uint8_t num_chn = 0; + uint8_t numchan_combinedconc = 0; + uint8_t i, j; + tCsrChannelInfo *chn_info = NULL; + uint8_t channel_to_scan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + CDF_STATUS status; + + csr_ll_lock(&mac_ctx->scan.scanCmdPendingList); + + entry = csr_ll_peek_head(&mac_ctx->scan.scanCmdPendingList, + LL_ACCESS_NOLOCK); + + if (NULL == entry) { + csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList); + return; + } + + + chn_info = &scan_req.ChannelInfo; + scan_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + num_chn = + scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels; + session_id = scan_cmd->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 ((csr_is_sta_session_connected(mac_ctx) && + !csr_is_p2p_session_connected(mac_ctx))) + numchan_combinedconc = + mac_ctx->roam.configParam.nNumStaChanCombinedConc; + else if (csr_is_p2p_session_connected(mac_ctx)) + numchan_combinedconc = + mac_ctx->roam.configParam.nNumP2PChanCombinedConc; + + if ((num_chn > numchan_combinedconc) && + ((csr_is_sta_session_connected(mac_ctx) && +#ifdef FEATURE_WLAN_LFR + (csr_is_concurrent_infra_connected(mac_ctx)) && +#endif + (scan_cmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) || + (csr_is_p2p_session_connected(mac_ctx)))) { + cdf_mem_set(&scan_req, sizeof(tCsrScanRequest), 0); + + /* optimize this to use 2 command buffer only */ + send_scancmd = csr_get_command_buffer(mac_ctx); + if (!send_scancmd) { + sms_log(mac_ctx, LOGE, + FL(" Failed to get Queue command buffer")); + csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList); + return; + } + send_scancmd->command = scan_cmd->command; + send_scancmd->sessionId = scan_cmd->sessionId; + send_scancmd->u.scanCmd.callback = NULL; + send_scancmd->u.scanCmd.pContext = + scan_cmd->u.scanCmd.pContext; + send_scancmd->u.scanCmd.reason = + scan_cmd->u.scanCmd.reason; + /* let it wrap around */ + wma_get_scan_id(&send_scancmd->u.scanCmd.scanID); + + /* + * First copy all the parameters to local variable of scan + * request + */ + csr_scan_copy_request(mac_ctx, &scan_req, + &scan_cmd->u.scanCmd.u.scanRequest); + + /* + * Now modify the elements of local var scan request required + * to be modified for split scan + */ + if (scan_req.ChannelInfo.ChannelList != NULL) { + cdf_mem_free(scan_req.ChannelInfo.ChannelList); + scan_req.ChannelInfo.ChannelList = NULL; + } + + chn_info->numOfChannels = numchan_combinedconc; + cdf_mem_copy(&channel_to_scan[0], + &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo. + ChannelList[0], chn_info->numOfChannels + * sizeof(uint8_t)); + chn_info->ChannelList = &channel_to_scan[0]; + + for (i = 0, j = numchan_combinedconc; + i < (num_chn - numchan_combinedconc); + i++, j++) { + /* Move all the channels one step */ + scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo. + ChannelList[i] = + scan_cmd->u.scanCmd.u.scanRequest. + ChannelInfo.ChannelList[j]; + } + + /* reduce outstanding # of channels to be scanned */ + scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = + num_chn - numchan_combinedconc; + + scan_req.BSSType = eCSR_BSS_TYPE_ANY; + /* Modify callers parameters in case of concurrency */ + scan_req.scanType = eSIR_ACTIVE_SCAN; + /* Use concurrency values for min/maxChnTime. */ + csr_set_default_scan_timing(mac_ctx, scan_req.scanType, + &scan_req); + + status = csr_scan_copy_request(mac_ctx, + &send_scancmd->u.scanCmd.u. + scanRequest, &scan_req); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL(" Failed to get copy csr_scan_request = %d"), + status); + csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList); + return; + } + /* Clean the local scan variable */ + scan_req.ChannelInfo.ChannelList = NULL; + scan_req.ChannelInfo.numOfChannels = 0; + csr_scan_free_request(mac_ctx, &scan_req); + } else { + /* + * no active connected session present or numChn == 1 + * scan all remaining channels + */ + send_scancmd = scan_cmd; + /* remove this command from pending list */ + if (csr_ll_remove_head(&mac_ctx->scan.scanCmdPendingList, + /* + * In case between PeekHead and here, the entry + * got removed by another thread. + */ + LL_ACCESS_NOLOCK) == NULL) { + sms_log(mac_ctx, LOGE, + FL(" Failed to remove entry from scanCmdPendingList")); + } + + } + csr_queue_sme_command(mac_ctx, send_scancmd, false); + + + csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList); + +} +#endif + +CDF_STATUS csr_scan_start_result_cfg_aging_timer(tpAniSirGlobal pMac) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (pMac->scan.fScanEnable) { + status = + cdf_mc_timer_start(&pMac->scan.hTimerResultCfgAging, + CSR_SCAN_RESULT_CFG_AGING_INTERVAL / + CDF_MC_TIMER_TO_MS_UNIT); + } + return status; +} + +CDF_STATUS csr_scan_stop_result_cfg_aging_timer(tpAniSirGlobal pMac) +{ + return cdf_mc_timer_stop(&pMac->scan.hTimerResultCfgAging); +} + +/** + * csr_scan_result_cfg_aging_timer_handler() - Time based scan aging handler + * @pv: Global context + * + * This routine is to handle scan aging based on user configured timer value. + * + * Return: None + */ +static void csr_scan_result_cfg_aging_timer_handler(void *pv) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv); + tListElem *entry, *tmp_entry; + tCsrScanResult *result; + uint32_t ageout_time = + mac_ctx->scan.scanResultCfgAgingTime * CDF_TICKS_PER_SECOND/10; + uint32_t cur_time = (uint32_t) cdf_mc_timer_get_system_ticks(); + uint8_t *bssId; + + csr_ll_lock(&mac_ctx->scan.scanResultList); + entry = csr_ll_peek_head(&mac_ctx->scan.scanResultList, LL_ACCESS_NOLOCK); + while (entry) { + tmp_entry = csr_ll_next(&mac_ctx->scan.scanResultList, entry, + LL_ACCESS_NOLOCK); + result = GET_BASE_ADDR(entry, tCsrScanResult, Link); + /* + * cdf_mc_timer_get_system_ticks() returns in 10ms interval. + * so ageout time value also updated to 10ms interval value. + */ + if ((cur_time - result->Result.BssDescriptor.nReceivedTime) > + ageout_time) { + bssId = result->Result.BssDescriptor.bssId; + sms_log(mac_ctx, LOGW, + FL("age out due to time out"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(bssId)); + csr_scan_age_out_bss(mac_ctx, result); + } + entry = tmp_entry; + } + csr_ll_unlock(&mac_ctx->scan.scanResultList); + cdf_mc_timer_start(&mac_ctx->scan.hTimerResultCfgAging, + CSR_SCAN_RESULT_CFG_AGING_INTERVAL / + CDF_MC_TIMER_TO_MS_UNIT); +} + +bool csr_scan_remove_fresh_scan_command(tpAniSirGlobal pMac, uint8_t sessionId) +{ + bool fRet = false; + tListElem *pEntry, *pEntryTmp; + tSmeCmd *pCommand; + tDblLinkList localList; + tDblLinkList *pCmdList; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return fRet; + } + + pCmdList = &pMac->sme.smeScanCmdPendingList; + + csr_ll_lock(pCmdList); + pEntry = csr_ll_peek_head(pCmdList, LL_ACCESS_NOLOCK); + while (pEntry) { + pEntryTmp = csr_ll_next(pCmdList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (!((eSmeCommandScan == pCommand->command) + && (sessionId == pCommand->sessionId))) { + pEntry = pEntryTmp; + continue; + } + sms_log(pMac, LOGW, + FL("-------- abort scan command reason = %d"), + pCommand->u.scanCmd.reason); + /* The rest are fresh scan requests */ + if (csr_ll_remove_entry(pCmdList, pEntry, + LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntry, + LL_ACCESS_NOLOCK); + } + fRet = true; + pEntry = pEntryTmp; + } + + csr_ll_unlock(pCmdList); + + while ((pEntry = csr_ll_remove_head(&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); + } + csr_release_command_scan(pMac, pCommand); + } + csr_ll_close(&localList); + + return fRet; +} + +void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrScanStatus scanStatus) +{ + eCsrScanReason reason = pCommand->u.scanCmd.reason; + bool status; + tDblLinkList *cmd_list = NULL; + + csr_scan_call_callback(pMac, pCommand, scanStatus); + sms_log(pMac, LOG1, FL("Remove Scan command reason = %d, scan_id %d"), + reason, pCommand->u.scanCmd.scanID); + cmd_list = &pMac->sme.smeScanCmdActiveList; + status = csr_ll_remove_entry(cmd_list, &pCommand->Link, LL_ACCESS_LOCK); + if (!status) { + sms_log(pMac, LOGE, + FL("cannot release command reason %d scan_id %d"), + pCommand->u.scanCmd.reason, + pCommand->u.scanCmd.scanID); + return; + } + csr_release_command_scan(pMac, pCommand); +} + +CDF_STATUS csr_scan_get_pmkid_candidate_list(tpAniSirGlobal pMac, + uint32_t sessionId, + tPmkidCandidateInfo *pPmkidList, + uint32_t *pNumItems) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tCsrScanResultFilter *pScanFilter; + tCsrScanResultInfo *pScanResult; + tScanResultHandle hBSSList; + uint32_t nItems = *pNumItems; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, FL("pMac->scan.NumPmkidCandidate = %d"), + pSession->NumPmkidCandidate); + csr_reset_pmkid_candidate_list(pMac, sessionId); + if (!(csr_is_conn_state_connected(pMac, sessionId) + && pSession->pCurRoamProfile)) + return status; + + *pNumItems = 0; + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + /* Here is the profile we need to connect to */ + status = csr_roam_prepare_filter_from_profile(pMac, + pSession->pCurRoamProfile, pScanFilter); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pScanFilter); + return status; + } + + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return status; + } + + if (pSession->NumPmkidCandidate < nItems) { + pScanResult = csr_scan_result_get_next(pMac, hBSSList); + while (pScanResult != NULL) { + /* NumPmkidCandidate adds up here */ + csr_process_bss_desc_for_pmkid_list(pMac, + &pScanResult->BssDescriptor, + (tDot11fBeaconIEs *)(pScanResult->pvIes), + sessionId); + pScanResult = csr_scan_result_get_next(pMac, hBSSList); + } + } + + if (pSession->NumPmkidCandidate) { + *pNumItems = pSession->NumPmkidCandidate; + cdf_mem_copy(pPmkidList, pSession->PmkidCandidateInfo, + pSession->NumPmkidCandidate * + sizeof(tPmkidCandidateInfo)); + } + + csr_scan_result_purge(pMac, hBSSList); + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return status; +} + +#ifdef FEATURE_WLAN_WAPI +CDF_STATUS csr_scan_get_bkid_candidate_list(tpAniSirGlobal pMac, + uint32_t sessionId, + tBkidCandidateInfo *pBkidList, + uint32_t *pNumItems) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tCsrScanResultFilter *pScanFilter; + tCsrScanResultInfo *pScanResult; + tScanResultHandle hBSSList; + uint32_t nItems = *pNumItems; + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOGW, FL("pMac->scan.NumBkidCandidate = %d"), + pSession->NumBkidCandidate); + csr_reset_bkid_candidate_list(pMac, sessionId); + if (!(csr_is_conn_state_connected(pMac, sessionId) + && pSession->pCurRoamProfile)) + return status; + + *pNumItems = 0; + pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter)); + if (NULL == pScanFilter) + return CDF_STATUS_E_NOMEM; + + cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0); + /* Here is the profile we need to connect to */ + status = csr_roam_prepare_filter_from_profile(pMac, + pSession->pCurRoamProfile, pScanFilter); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(pScanFilter); + return status; + } + + status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); + if (!CDF_IS_STATUS_SUCCESS(status)) { + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return status; + } + + if (pSession->NumBkidCandidate < nItems) { + pScanResult = csr_scan_result_get_next(pMac, hBSSList); + while (pScanResult != NULL) { + /* pMac->scan.NumBkidCandidate adds up here */ + csr_process_bss_desc_for_bkid_list(pMac, + &pScanResult->BssDescriptor, + (tDot11fBeaconIEs *)(pScanResult->pvIes)); + pScanResult = csr_scan_result_get_next(pMac, hBSSList); + } + } + + if (pSession->NumBkidCandidate) { + *pNumItems = pSession->NumBkidCandidate; + cdf_mem_copy(pBkidList, pSession->BkidCandidateInfo, + pSession->NumBkidCandidate * + sizeof(tBkidCandidateInfo)); + } + + csr_scan_result_purge(pMac, hBSSList); + csr_free_scan_filter(pMac, pScanFilter); + cdf_mem_free(pScanFilter); + return status; +} +#endif /* FEATURE_WLAN_WAPI */ + +/** + * csr_roam_copy_channellist() - Function to copy channel list + * @mac_ctx: pointer to Global Mac structure + * @profile: pointer to tCsrRoamProfile + * @scan_cmd: pointer to tSmeCmd + * @index: index for channellist + * + * Function copies channel list + * + * Return: none + */ +static void csr_roam_copy_channellist(tpAniSirGlobal mac_ctx, + tCsrRoamProfile *profile, + tSmeCmd *scan_cmd, uint8_t index) +{ + tCsrChannelInfo *channel_info = + &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo; + + for (index = 0; index < profile->ChannelInfo.numOfChannels; + index++) { + if (!csr_roam_is_valid_channel(mac_ctx, + profile->ChannelInfo.ChannelList[index])) { + sms_log(mac_ctx, LOGW, + FL("process a channel (%d) that is invalid"), + profile->ChannelInfo.ChannelList[index]); + continue; + } + channel_info->ChannelList[channel_info->numOfChannels] = + profile->ChannelInfo.ChannelList[index]; + scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++; + } +} + +/** + * csr_scan_for_ssid() - Function usually used for BSSs that suppresses SSID + * @mac_ctx: Pointer to Global Mac structure + * @profile: pointer to tCsrRoamProfile + * @roam_id: variable representing roam id + * @notify: boolean variable + * + * Function is usually used for BSSs that suppresses SSID so the profile + * shall have one and only one SSID. + * + * Return: Success - CDF_STATUS_SUCCESS, Failure - error number + */ +CDF_STATUS csr_scan_for_ssid(tpAniSirGlobal mac_ctx, uint32_t session_id, + tCsrRoamProfile *profile, uint32_t roam_id, + bool notify) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + tSmeCmd *scan_cmd = NULL; + tCsrScanRequest *scan_req = NULL; + uint8_t index = 0; + uint32_t num_ssid = profile->SSIDs.numOfSSIDs; + tpCsrNeighborRoamControlInfo neighbor_roaminfo = + &mac_ctx->roam.neighborRoamInfo[session_id]; + tCsrSSIDs *ssids = NULL; + + sms_log(mac_ctx, LOG2, FL("called")); + + /* For WDS, we use the index 0. There must be at least one in there */ + if (CSR_IS_WDS_STA(profile) && num_ssid) + num_ssid = 1; + + if (!(mac_ctx->scan.fScanEnable) && (num_ssid != 1)) { + sms_log(mac_ctx, LOGE, + FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"), + mac_ctx->scan.fScanEnable, profile->SSIDs.numOfSSIDs); + return status; + } + + scan_cmd = csr_get_command_buffer(mac_ctx); + + if (!scan_cmd) { + sms_log(mac_ctx, LOGE, + FL("failed to allocate command buffer")); + goto error; + } + + cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0); + scan_cmd->u.scanCmd.pToRoamProfile = + cdf_mem_malloc(sizeof(tCsrRoamProfile)); + + if (NULL == scan_cmd->u.scanCmd.pToRoamProfile) + status = CDF_STATUS_E_NOMEM; + else + status = csr_roam_copy_profile(mac_ctx, + scan_cmd->u.scanCmd.pToRoamProfile, + profile); + + if (!CDF_IS_STATUS_SUCCESS(status)) + goto error; + + scan_cmd->u.scanCmd.roamId = roam_id; + scan_cmd->command = eSmeCommandScan; + scan_cmd->sessionId = (uint8_t) session_id; + scan_cmd->u.scanCmd.callback = NULL; + scan_cmd->u.scanCmd.pContext = NULL; + scan_cmd->u.scanCmd.reason = eCsrScanForSsid; + + /* let it wrap around */ + wma_get_scan_id(&scan_cmd->u.scanCmd.scanID); + cdf_mem_set(&scan_cmd->u.scanCmd.u.scanRequest, + sizeof(tCsrScanRequest), 0); + status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer, + CDF_TIMER_TYPE_SW, + csr_scan_active_list_timeout_handle, &scan_cmd); + scan_req = &scan_cmd->u.scanCmd.u.scanRequest; + scan_req->scanType = eSIR_ACTIVE_SCAN; + scan_req->BSSType = profile->BSSType; + scan_req->scan_id = scan_cmd->u.scanCmd.scanID; + /* + * To avoid 11b rate in probe request Set p2pSearch + * flag as 1 for P2P Client Mode + */ + if (CDF_P2P_CLIENT_MODE == profile->csrPersona) + scan_req->p2pSearch = 1; + + /* Allocate memory for IE field */ + if (profile->pAddIEScan) { + scan_req->pIEField = + cdf_mem_malloc(profile->nAddIEScanLength); + + if (NULL == scan_req->pIEField) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + cdf_mem_set(scan_req->pIEField, + profile->nAddIEScanLength, 0); + + if (CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_copy(scan_req->pIEField, + profile->pAddIEScan, + profile->nAddIEScanLength); + scan_req->uIEFieldLen = profile->nAddIEScanLength; + } else { + sms_log(mac_ctx, LOGE, + "No memory for scanning IE fields"); + } + } else + scan_req->uIEFieldLen = 0; + + /* + * For one channel be good enpugh time to receive beacon + * atleast + */ + if (1 == profile->ChannelInfo.numOfChannels) { + if (neighbor_roaminfo->handoffReqInfo.src == + FASTREASSOC) { + scan_req->maxChnTime = + MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC; + scan_req->minChnTime = + MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC; + /* Reset this value */ + neighbor_roaminfo->handoffReqInfo.src = 0; + } else { + scan_req->maxChnTime = + MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL; + scan_req->minChnTime = + MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL; + } + } else { + scan_req->maxChnTime = + mac_ctx->roam.configParam.nActiveMaxChnTime; + scan_req->minChnTime = + mac_ctx->roam.configParam.nActiveMinChnTime; + } + + if (profile->BSSIDs.numOfBSSIDs == 1) + cdf_copy_macaddr(&scan_req->bssid, + profile->BSSIDs.bssid); + else + cdf_set_macaddr_broadcast(&scan_req->bssid); + + if (profile->ChannelInfo.numOfChannels) { + scan_req->ChannelInfo.ChannelList = + cdf_mem_malloc(sizeof(*scan_req->ChannelInfo.ChannelList) * + profile->ChannelInfo.numOfChannels); + + if (NULL == scan_req->ChannelInfo.ChannelList) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + scan_req->ChannelInfo.numOfChannels = 0; + + if (CDF_IS_STATUS_SUCCESS(status)) { + csr_roam_is_channel_valid(mac_ctx, + profile->ChannelInfo.ChannelList[0]); + csr_roam_copy_channellist(mac_ctx, + profile, scan_cmd, index); + } else { + goto error; + } + } else { + scan_req->ChannelInfo.numOfChannels = 0; + } + + if (profile->SSIDs.numOfSSIDs) { + scan_req->SSIDs.SSIDList = + cdf_mem_malloc(profile->SSIDs.numOfSSIDs * + sizeof(tCsrSSIDInfo)); + + if (NULL == scan_req->SSIDs.SSIDList) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + if (!CDF_IS_STATUS_SUCCESS(status)) + goto error; + + ssids = &scan_req->SSIDs; + ssids->numOfSSIDs = 1; + + cdf_mem_copy(scan_req->SSIDs.SSIDList, + profile->SSIDs.SSIDList, + sizeof(tCsrSSIDInfo)); + } + + /* Start process the command */ + status = csr_queue_sme_command(mac_ctx, scan_cmd, false); +error: + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL(" failed to iniate scan with status = %d"), status); + if (scan_cmd) + csr_release_command_scan(mac_ctx, scan_cmd); + if (notify) + csr_roam_call_callback(mac_ctx, session_id, NULL, + roam_id, eCSR_ROAM_FAILED, + eCSR_ROAM_RESULT_FAILURE); + } + return status; +} + +void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList, + uint8_t NumChannels) +{ + uint32_t dataLen = sizeof(uint8_t) * NumChannels; + CDF_STATUS status; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: dump valid channel list(NumChannels(%d))", + __func__, NumChannels); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + pChannelList, NumChannels); + cfg_set_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList, + dataLen); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 = csr_update_channel_list(pMac); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "failed to update the supported channel list"); + } + return; +} + +/* + * The Tx power limits are saved in the cfg for future usage. + */ +void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList, + uint32_t cfgId) +{ + tListElem *pEntry; + uint32_t cbLen = 0, dataLen, tmp_len; + tCsrChannelPowerInfo *ch_set; + uint32_t idx; + tSirMacChanInfo *ch_pwr_set; + uint8_t *pBuf = NULL; + + /* allocate maximum space for all channels */ + dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo); + pBuf = cdf_mem_malloc(dataLen); + if (pBuf == NULL) + return; + + cdf_mem_set(pBuf, dataLen, 0); + ch_pwr_set = (tSirMacChanInfo *) (pBuf); + pEntry = csr_ll_peek_head(pList, LL_ACCESS_LOCK); + /* + * write the tuples (startChan, numChan, txPower) for each channel found + * in the channel power list. + */ + while (pEntry) { + ch_set = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link); + if (1 != ch_set->interChannelOffset) { + /* + * we keep the 5G channel sets internally with an + * interchannel offset of 4. Expand these to the right + * format. (inter channel offset of 1 is the only option + * for the triplets that 11d advertises. + */ + tmp_len = cbLen + (ch_set->numChannels * + sizeof(tSirMacChanInfo)); + if (tmp_len >= dataLen) { + /* + * expanding this entry will overflow our + * allocation + */ + sms_log(pMac, LOGE, + FL("Buffer overflow, start %d, num %d, offset %d"), + ch_set->firstChannel, + ch_set->numChannels, + ch_set->interChannelOffset); + break; + } + + for (idx = 0; idx < ch_set->numChannels; idx++) { + ch_pwr_set->firstChanNum = (tSirMacChanNum) + (ch_set->firstChannel + (idx * + ch_set->interChannelOffset)); + sms_log(pMac, LOG3, + FL("Setting Channel Number %d"), + ch_pwr_set->firstChanNum); + ch_pwr_set->numChannels = 1; + ch_pwr_set->maxTxPower = + CDF_MIN(ch_set->txPower, + pMac->roam.configParam.nTxPowerCap); + sms_log(pMac, LOG3, + FL("Setting Max Transmit Power %d"), + ch_pwr_set->maxTxPower); + cbLen += sizeof(tSirMacChanInfo); + ch_pwr_set++; + } + } else { + if (cbLen >= dataLen) { + /* this entry will overflow our allocation */ + sms_log(pMac, LOGE, + FL("Buffer overflow, start %d, num %d, offset %d"), + ch_set->firstChannel, + ch_set->numChannels, + ch_set->interChannelOffset); + break; + } + ch_pwr_set->firstChanNum = ch_set->firstChannel; + sms_log(pMac, LOG3, FL("Setting Channel Number %d"), + ch_pwr_set->firstChanNum); + ch_pwr_set->numChannels = ch_set->numChannels; + ch_pwr_set->maxTxPower = CDF_MIN(ch_set->txPower, + pMac->roam.configParam.nTxPowerCap); + sms_log(pMac, LOG3, + FL("Setting Max Tx Power %d, nTxPower %d"), + ch_pwr_set->maxTxPower, + pMac->roam.configParam.nTxPowerCap); + cbLen += sizeof(tSirMacChanInfo); + ch_pwr_set++; + } + pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_LOCK); + } + if (cbLen) + cfg_set_str(pMac, cfgId, (uint8_t *) pBuf, cbLen); + + cdf_mem_free(pBuf); +} + +void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode) +{ + uint8_t cc[WNI_CFG_COUNTRY_CODE_LEN]; + /* v_REGDOMAIN_t DomainId */ + + sms_log(pMac, LOG3, FL("Setting Country Code in Cfg %s"), countryCode); + cdf_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'; + } + cfg_set_str(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN); + + /* + * Need to let HALPHY know about the current domain so it can apply some + * domain-specific settings (TX filter...) + */ + /* + if(CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country( + pMac, cc, &DomainId))) { + halPhySetRegDomain(pMac, DomainId); + } */ +} + +CDF_STATUS csr_get_country_code(tpAniSirGlobal pMac, uint8_t *pBuf, + uint8_t *pbLen) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + uint32_t len; + + if (pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN)) { + len = *pbLen; + status = wlan_cfg_get_str(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len); + if (CDF_IS_STATUS_SUCCESS(status)) { + *pbLen = (uint8_t) len; + } + } + + return status; +} + +void csr_set_cfg_scan_control_list(tpAniSirGlobal pMac, uint8_t *countryCode, + tCsrChannel *pChannelList) +{ + uint8_t i, j; + bool found = false; + uint8_t *pControlList = NULL; + uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN; + + pControlList = cdf_mem_malloc(WNI_CFG_SCAN_CONTROL_LIST_LEN); + if (pControlList != NULL) { + cdf_mem_set((void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN, + 0); + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_str(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] = + csr_get_scan_type(pMac, + pControlList[j]); + found = false; /* reset the flag */ + } + + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: dump scan control list", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, pControlList, + len); + + cfg_set_str(pMac, WNI_CFG_SCAN_CONTROL_LIST, + pControlList, len); + } /* Successfully getting scan control list */ + cdf_mem_free(pControlList); + } /* AllocateMemory */ +} + +CDF_STATUS csr_scan_abort_mac_scan(tpAniSirGlobal pMac, uint8_t sessionId, + eCsrAbortReason reason) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + pMac->scan.fDropScanCmd = true; + csr_remove_cmd_with_session_id_from_pending_list(pMac, + sessionId, &pMac->sme.smeScanCmdPendingList, + eSmeCommandScan); + pMac->scan.fDropScanCmd = false; + csr_abort_scan_from_active_list(pMac, + &pMac->sme.smeScanCmdActiveList, sessionId, + eSmeCommandScan, reason); + + return status; +} + +void csr_remove_cmd_with_session_id_from_pending_list(tpAniSirGlobal pMac, + uint8_t sessionId, + tDblLinkList *pList, + eSmeCommandType commandType) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL("failed to open list")); + return; + } + + csr_ll_lock(pList); + pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK); + if (pEntry) { + /* + * 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 = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link); + + if (!((pCommand->command == commandType) && + (pCommand->sessionId == sessionId))) + continue; + /* Remove that entry only */ + if (csr_ll_remove_entry(pList, pEntryToRemove, + LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntryToRemove, + LL_ACCESS_NOLOCK); + } + } + } + csr_ll_unlock(pList); + + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + sms_log(pMac, LOG1, FL("Sending abort for scan command ID %d"), + pCommand->u.scanCmd.scanID); + csr_abort_command(pMac, pCommand, false); + } + + csr_ll_close(&localList); +} + +void csr_remove_cmd_from_pending_list(tpAniSirGlobal pMac, + tDblLinkList *pList, + eSmeCommandType commandType) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return; + } + + csr_ll_lock(pList); + if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) { + pEntry = csr_ll_peek_head(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 = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link); + /* Remove that entry only that matches cmd type */ + if (pCommand->command == commandType && + csr_ll_remove_entry(pList, pEntryToRemove, + LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntryToRemove, + LL_ACCESS_NOLOCK); + } + } + } + csr_ll_unlock(pList); + + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + csr_abort_command(pMac, pCommand, false); + } + csr_ll_close(&localList); + +} + +CDF_STATUS csr_scan_abort_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + + pMac->scan.fDropScanCmd = true; + csr_remove_scan_for_ssid_from_pending_list(pMac, + &pMac->sme.smeScanCmdPendingList, sessionId); + pMac->scan.fDropScanCmd = false; + csr_abort_scan_from_active_list(pMac, &pMac->sme.smeScanCmdActiveList, + sessionId, eSmeCommandScan, eCSR_SCAN_ABORT_SSID_ONLY); + return status; +} + +void csr_remove_scan_for_ssid_from_pending_list(tpAniSirGlobal pMac, + tDblLinkList *pList, + uint32_t sessionId) +{ + tDblLinkList localList; + tListElem *pEntry; + tSmeCmd *pCommand; + tListElem *pEntryToRemove; + + cdf_mem_zero(&localList, sizeof(tDblLinkList)); + if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) { + sms_log(pMac, LOGE, FL(" failed to open list")); + return; + } + csr_ll_lock(pList); + if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) { + pEntry = csr_ll_peek_head(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 = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); + pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link); + + if (!((eSmeCommandScan == pCommand->command) && + (sessionId == pCommand->sessionId))) + continue; + if (eCsrScanForSsid != pCommand->u.scanCmd.reason) + continue; + /* Remove that entry only */ + if (csr_ll_remove_entry(pList, pEntryToRemove, + LL_ACCESS_NOLOCK)) { + csr_ll_insert_tail(&localList, pEntryToRemove, + LL_ACCESS_NOLOCK); + } + } + } + csr_ll_unlock(pList); + while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + csr_abort_command(pMac, pCommand, false); + } + csr_ll_close(&localList); +} + + +/** + * csr_send_scan_abort() - Sends scan abort command to firmware + * @mac_ctx: Pointer to Global Mac structure + * @session_id: CSR session identification + * @scan_id: scan identifier + * + * .Sends scan abort command to firmware + * + * Return: None + */ +static void csr_send_scan_abort(tpAniSirGlobal mac_ctx, + uint32_t session_id, uint32_t scan_id) +{ + tSirSmeScanAbortReq *msg; + uint16_t msg_len; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq)); + msg = cdf_mem_malloc(msg_len); + if (NULL == msg) { + sms_log(mac_ctx, LOGE, + FL("Failed to alloc memory for SmeScanAbortReq")); + return; + } + cdf_mem_zero((void *)msg, msg_len); + msg->type = eWNI_SME_SCAN_ABORT_IND; + msg->msgLen = msg_len; + msg->sessionId = session_id; + msg->scan_id = scan_id; + sms_log(mac_ctx, LOG2, + FL("Abort scan sent to Firmware scan_id %d session %d"), + scan_id, session_id); + status = cds_send_mb_message_to_mac(msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(msg); + sms_log(mac_ctx, LOGE, + FL("Failed to send abort scan.scan_id %d session %d"), + scan_id, session_id); + } + return; +} + +/** + * csr_abort_scan_from_active_list() - Remove Scan command from active list + * @mac_ctx: Pointer to Global Mac structure + * @list: pointer to scan active list + * @session_id: CSR session identification + * @scan_cmd_type: scan command type + * @abort_reason: abort reason + * + * .Remove Scan command from active scan list + * + * Return: Success - CDF_STATUS_SUCCESS, Failure - error number + */ +CDF_STATUS csr_abort_scan_from_active_list(tpAniSirGlobal mac_ctx, + tDblLinkList *list, uint32_t session_id, + eSmeCommandType scan_cmd_type, eCsrAbortReason abort_reason) +{ + tListElem *entry; + tSmeCmd *cmd; + tListElem *entry_remove; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + csr_ll_lock(list); + if (!csr_ll_is_list_empty(list, LL_ACCESS_NOLOCK)) { + entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK); + while (entry) { + entry_remove = entry; + entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK); + cmd = GET_BASE_ADDR(entry_remove, tSmeCmd, Link); + + /* Skip if command and session id not matched */ + if (!((scan_cmd_type == cmd->command) && + (session_id == cmd->sessionId))) + continue; + /*skip if abort reason is for SSID*/ + if ((abort_reason == eCSR_SCAN_ABORT_SSID_ONLY) && + (eCsrScanForSsid != cmd->u.scanCmd.reason)) + continue; + if (abort_reason == eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE) + cmd->u.scanCmd.abortScanDueToBandChange = + true; + csr_send_scan_abort(mac_ctx, cmd->sessionId, + cmd->u.scanCmd.scanID); + } + } + csr_ll_unlock(list); + + return status; +} + + +CDF_STATUS csr_scan_abort_mac_scan_not_for_connect(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + if (!csr_is_scan_for_roam_command_active(pMac)) { + /* + * Only abort the scan if it is not used for other roam/connect + * purpose + */ + status = csr_scan_abort_mac_scan(pMac, sessionId, + eCSR_SCAN_ABORT_DEFAULT); + } + return status; +} +bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel) +{ + bool fValid = false; + uint32_t idx_valid_ch; + uint32_t len = pMac->roam.numValidChannels; + + for (idx_valid_ch = 0; (idx_valid_ch < len); idx_valid_ch++) { + if (channel == pMac->roam.validChannelList[idx_valid_ch]) { + fValid = true; + break; + } + } + return fValid; +} + +#ifdef FEATURE_WLAN_SCAN_PNO +CDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd * + pPrefNetworkFoundInd) +{ + uint32_t uLen = 0; + tpSirProbeRespBeacon parsed_frm; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDescr = NULL; + bool fDupBss; + tDot11fBeaconIEs *local_ie = NULL; + tAniSSID tmpSsid; + v_TIME_t timer = 0; + CDF_STATUS status; + + tpSirMacMgmtHdr macHeader = + (tpSirMacMgmtHdr) pPrefNetworkFoundInd->data; + parsed_frm = + (tpSirProbeRespBeacon) cdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + + if (NULL == parsed_frm) { + sms_log(pMac, LOGE, FL("fail to allocate memory for frame")); + return CDF_STATUS_E_NOMEM; + } + if (pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A) { + sms_log(pMac, LOGE, + FL("Incorrect len(%d)"), + pPrefNetworkFoundInd->frameLength); + cdf_mem_free(parsed_frm); + return CDF_STATUS_E_FAILURE; + } + if (sir_convert_probe_frame2_struct(pMac, + &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A], + pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A, + parsed_frm) != eSIR_SUCCESS + || !parsed_frm->ssidPresent) { + sms_log(pMac, LOGE, FL("Parse error ProbeResponse, length=%d"), + pPrefNetworkFoundInd->frameLength); + cdf_mem_free(parsed_frm); + return CDF_STATUS_E_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 = cdf_mem_malloc(sizeof(tCsrScanResult) + uLen); + if (NULL == pScanResult) { + sms_log(pMac, LOGE, FL("fail to allocate memory for frame")); + cdf_mem_free(parsed_frm); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set(pScanResult, sizeof(tCsrScanResult) + uLen, 0); + pBssDescr = &pScanResult->Result.BssDescriptor; + /* + * Length of BSS desription is without length of length itself and + * length of pointer that holds the next BSS description + */ + pBssDescr->length = (uint16_t) (sizeof(tSirBssDescription) - + sizeof(uint16_t) - sizeof(uint32_t) + uLen); + if (parsed_frm->dsParamsPresent) + pBssDescr->channelId = parsed_frm->channelNumber; + else if (parsed_frm->HTInfo.present) + pBssDescr->channelId = parsed_frm->HTInfo.primaryChannel; + else + pBssDescr->channelId = parsed_frm->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 < parsed_frm->supportedRates.numRates; i++) { + if (sirIsArate(parsed_frm->supportedRates.rate[i] + & 0x7f)) { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (parsed_frm->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 = parsed_frm->beaconInterval; + if (!pBssDescr->beaconInterval) { + sms_log(pMac, LOGW, FL("Bcn Interval is Zero , default to 100" + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBssDescr->bssId)); + pBssDescr->beaconInterval = 100; + } + pBssDescr->timeStamp[0] = parsed_frm->timeStamp[0]; + pBssDescr->timeStamp[1] = parsed_frm->timeStamp[1]; + pBssDescr->capabilityInfo = *((uint16_t *)&parsed_frm->capabilityInfo); + cdf_mem_copy((uint8_t *) &pBssDescr->bssId, + (uint8_t *) macHeader->bssId, sizeof(tSirMacAddr)); + pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks(); + sms_log(pMac, LOG2, FL("Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = %d"), + MAC_ADDR_ARRAY(pBssDescr->bssId), pBssDescr->channelId, + pBssDescr->rssi); + /* IEs */ + if (uLen) { + cdf_mem_copy(&pBssDescr->ieFields, + pPrefNetworkFoundInd->data + (SIR_MAC_HDR_LEN_3A + + SIR_MAC_B_PR_SSID_OFFSET), uLen); + } + local_ie = (tDot11fBeaconIEs *) (pScanResult->Result.pvIes); + status = csr_get_parsed_bss_description_ies(pMac, + &pScanResult->Result.BssDescriptor, &local_ie); + if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) { + sms_log(pMac, LOGE, FL("Cannot parse IEs")); + csr_free_scan_result_entry(pMac, pScanResult); + cdf_mem_free(parsed_frm); + return CDF_STATUS_E_RESOURCES; + } + + fDupBss = csr_remove_dup_bss_description(pMac, + &pScanResult->Result.BssDescriptor, + local_ie, &tmpSsid, &timer, false); + /* Check whether we have reach out limit */ + if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) { + /* Limit reach */ + sms_log(pMac, LOGE, FL("BSS limit reached")); + /* Free the resources */ + if ((pScanResult->Result.pvIes == NULL) && local_ie) + cdf_mem_free(local_ie); + csr_free_scan_result_entry(pMac, pScanResult); + cdf_mem_free(parsed_frm); + return CDF_STATUS_E_RESOURCES; + } + /* Add to scan cache */ + csr_scan_add_result(pMac, pScanResult, local_ie, + pPrefNetworkFoundInd->sessionId); + + if ((pScanResult->Result.pvIes == NULL) && local_ie) + cdf_mem_free(local_ie); + cdf_mem_free(parsed_frm); + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_SCAN_PNO */ + +#ifdef FEATURE_WLAN_LFR +void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tListElem *pEntry = NULL; + tCsrScanResult *pBssDesc = NULL; + tDot11fBeaconIEs *pIes = NULL; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) { + /* + * Ini file contains neighbor scan channel list, hence NO need + * to build occupied channel list" + */ + sms_log(pMac, LOG1, FL("Ini contains neighbor scan ch list")); + return; + } + + if (!csr_neighbor_roam_is_new_connected_profile(pMac, sessionId)) { + /* + * Do not flush occupied list since current roam profile matches + * previous + */ + sms_log(pMac, LOG2, FL("Current roam profile matches prev")); + return; + } + + /* Empty occupied channels here */ + pMac->scan.occupiedChannels[sessionId].numChannels = 0; + + csr_ll_lock(&pMac->scan.scanResultList); + pEntry = csr_ll_peek_head(&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 && !CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies(pMac, + &pBssDesc->Result.BssDescriptor, &pIes))) + continue; + csr_scan_add_to_occupied_channels(pMac, pBssDesc, sessionId, + &pMac->scan.occupiedChannels[sessionId], pIes); + /* + * Free the memory allocated for pIes in + * csr_get_parsed_bss_description_ies + */ + if ((pBssDesc->Result.pvIes == NULL) && pIes) + cdf_mem_free(pIes); + pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, + LL_ACCESS_NOLOCK); + } /* while */ + csr_ll_unlock(&pMac->scan.scanResultList); +} +#endif + +CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac, + uint32_t sessionId, + struct cdf_mac_addr bssid, + uint8_t channel) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tDot11fBeaconIEs *pNewIes = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tSirBssDescription *pNewBssDescriptor = NULL; + uint32_t size = 0; + + if (NULL == pSession) { + status = CDF_STATUS_E_FAILURE; + return status; + } + sms_log(pMac, LOG2, FL("Current bssid::"MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pSession->pConnectBssDesc->bssId)); + sms_log(pMac, LOG2, FL("My bssid::"MAC_ADDRESS_STR" channel %d"), + MAC_ADDR_ARRAY(bssid.bytes), channel); + + if (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies( + pMac, pSession->pConnectBssDesc, + &pNewIes))) { + sms_log(pMac, LOGE, FL("Failed to parse IEs")); + status = CDF_STATUS_E_FAILURE; + goto free_mem; + } + size = pSession->pConnectBssDesc->length + + sizeof(pSession->pConnectBssDesc->length); + if (!size) { + sms_log(pMac, LOGE, FL("length of bss descriptor is 0")); + status = CDF_STATUS_E_FAILURE; + goto free_mem; + } + pNewBssDescriptor = cdf_mem_malloc(size); + if (NULL == pNewBssDescriptor) { + sms_log(pMac, LOGE, FL("memory allocation failed")); + status = CDF_STATUS_E_FAILURE; + goto free_mem; + } + cdf_mem_copy(pNewBssDescriptor, pSession->pConnectBssDesc, size); + /* change the BSSID & channel as passed */ + cdf_mem_copy(pNewBssDescriptor->bssId, bssid.bytes, + sizeof(tSirMacAddr)); + pNewBssDescriptor->channelId = channel; + if (NULL == csr_scan_append_bss_description(pMac, pNewBssDescriptor, + pNewIes, true, sessionId)) { + sms_log(pMac, LOGE, + FL("csr_scan_append_bss_description failed")); + status = CDF_STATUS_E_FAILURE; + goto free_mem; + } + sms_log(pMac, LOGE, FL("entry successfully added in scan cache")); + +free_mem: + if (pNewIes) { + cdf_mem_free(pNewIes); + } + if (pNewBssDescriptor) { + cdf_mem_free(pNewBssDescriptor); + } + return status; +} + +#ifdef FEATURE_WLAN_ESE +/* Update the TSF with the difference in system time */ +void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1, + uint32_t *incr) +{ + uint64_t timeStamp64 = ((uint64_t) *timeStamp1 << 32) | (*timeStamp0); + timeStamp64 = (uint64_t) (timeStamp64 + (uint64_t) *incr); + *timeStamp0 = (uint32_t) (timeStamp64 & 0xffffffff); + *timeStamp1 = (uint32_t) ((timeStamp64 >> 32) & 0xffffffff); +} +#endif + +/** + * csr_scan_save_roam_offload_ap_to_scan_cache + * 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 roam_sync_ind_ptr Roam Synch Indication from + * firmware which also contains the beacon/probe + * response + * @return Status + */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac, + roam_offload_synch_ind *roam_sync_ind_ptr) +{ + uint32_t length = 0; + bool dup_bss; + tDot11fBeaconIEs *ies_local_ptr = NULL; + tAniSSID tmpSsid; + v_TIME_t timer = 0; + tCsrScanResult *scan_res_ptr = NULL; + uint8_t session_id = roam_sync_ind_ptr->roamedVdevId; + + length = roam_sync_ind_ptr->beaconProbeRespLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + scan_res_ptr = cdf_mem_malloc(sizeof(tCsrScanResult) + length); + if (scan_res_ptr == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + " fail to allocate memory for frame"); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(scan_res_ptr, sizeof(tCsrScanResult) + length); + cdf_mem_copy(&scan_res_ptr->Result.BssDescriptor, + roam_sync_ind_ptr->bss_desc_ptr, + (sizeof(tSirBssDescription) + length)); + ies_local_ptr = (tDot11fBeaconIEs *)(scan_res_ptr->Result.pvIes); + if (!ies_local_ptr && + (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies( + pMac, &scan_res_ptr->Result. + BssDescriptor, + &ies_local_ptr)))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s:Cannot Parse IEs", __func__); + csr_free_scan_result_entry(pMac, scan_res_ptr); + return CDF_STATUS_E_RESOURCES; + } + + dup_bss = csr_remove_dup_bss_description(pMac, + &scan_res_ptr->Result.BssDescriptor, + ies_local_ptr, &tmpSsid, &timer, true); + if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s:BSS Limit Exceed", __func__); + if ((scan_res_ptr->Result.pvIes == NULL) && ies_local_ptr) + cdf_mem_free(ies_local_ptr); + + csr_free_scan_result_entry(pMac, scan_res_ptr); + return CDF_STATUS_E_RESOURCES; + } + csr_scan_add_result(pMac, scan_res_ptr, ies_local_ptr, session_id); + return CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Empty bss_list")); + return NULL; + } + if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("bss_list->List is empty")); + cdf_mem_free(bss_list); + return NULL; + } + first_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK); + if (first_element) { + scan_result = GET_BASE_ADDR(first_element, + tCsrScanResult, + Link); + cdf_mem_copy(bss_descr, + &scan_result->Result.BssDescriptor, + sizeof(tSirBssDescription)); + } + return bss_descr; +} + +/** + * scan_active_list_cmd_timeout_handle() - To handle scan active command timeout + * @userData: scan context + * + * This routine is to handle scan active command timeout + * + * Return: None + */ +void csr_scan_active_list_timeout_handle(void *userData) +{ + tSmeCmd *scan_cmd = (tSmeCmd *) userData; + tHalHandle *hal_ctx = cds_get_context(CDF_MODULE_ID_PE); + tpAniSirGlobal mac_ctx; + uint16_t scan_id; + tSirSmeScanAbortReq *msg; + uint16_t msg_len; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (scan_cmd == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Scan Timeout: Scan command is NULL")); + return; + } + mac_ctx = PMAC_STRUCT(hal_ctx); + scan_id = scan_cmd->u.scanCmd.scanID; + sms_log(mac_ctx, LOGE, + FL("Scan Timeout:Sending abort to Firmware ID %d session %d "), + scan_id, scan_cmd->sessionId); + msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq)); + msg = cdf_mem_malloc(msg_len); + if (NULL == msg) { + sms_log(mac_ctx, LOGE, + FL("Failed to alloc memory for SmeScanAbortReq")); + return; + } + cdf_mem_zero((void *)msg, msg_len); + msg->type = eWNI_SME_SCAN_ABORT_IND; + msg->msgLen = msg_len; + msg->sessionId = scan_cmd->sessionId; + msg->scan_id = scan_id; + status = cds_send_mb_message_to_mac(msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL(" Failed to post message to LIM")); + cdf_mem_free(msg); + } + csr_release_scan_command(mac_ctx, scan_cmd, eCSR_SCAN_FAILURE); + return; +} diff --git a/core/sme/src/csr/csr_cmd_process.c b/core/sme/src/csr/csr_cmd_process.c new file mode 100644 index 000000000000..7fa7ec8aaa28 --- /dev/null +++ b/core/sme/src/csr/csr_cmd_process.c @@ -0,0 +1,189 @@ +/* + * 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 csr_cmd_process.c + + Implementation for processing various commands. + ========================================================================== */ + +#include "ani_global.h" + +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "sms_debug.h" +#include "mac_trace.h" + +/** + * csr_msg_processor() - To process all csr msg + * @mac_ctx: mac context + * @msg_buf: message buffer + * + * This routine will handle all the message for csr to process + * + * Return: CDF_STATUS + */ +CDF_STATUS csr_msg_processor(tpAniSirGlobal mac_ctx, void *msg_buf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeRsp *sme_rsp = (tSirSmeRsp *) msg_buf; +#ifdef FEATURE_WLAN_SCAN_PNO + tSirMbMsg *msg = (tSirMbMsg *) msg_buf; + tCsrRoamSession *session; +#endif + uint8_t session_id = sme_rsp->sessionId; + eCsrRoamState cur_state = mac_ctx->roam.curState[session_id]; + + sms_log(mac_ctx, LOG2, + FL("msg %d[0x%04X] recvd in curstate %s & substate %s id(%d)"), + sme_rsp->messageType, sme_rsp->messageType, + mac_trace_getcsr_roam_state(cur_state), + mac_trace_getcsr_roam_sub_state( + mac_ctx->roam.curSubState[session_id]), + session_id); + +#ifdef FEATURE_WLAN_SCAN_PNO + /* + * PNO scan responses have to be handled irrespective of CSR roam state. + * Check if PNO has been started & only then process the PNO scan result + * Also note that normal scan isn't 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'll be processed as usual based on the current CSR roam state. + */ + session = CSR_GET_SESSION(mac_ctx, session_id); + if (!session) { + sms_log(mac_ctx, LOGE, FL("session %d not found, msgType : %d"), + session_id, msg->type); + return CDF_STATUS_E_FAILURE; + } + + if (eWNI_SME_SCAN_RSP == msg->type) { + status = csr_scanning_state_msg_processor(mac_ctx, msg_buf); + if (CDF_STATUS_SUCCESS != status) + sms_log(mac_ctx, LOGE, + FL("handling PNO scan resp 0x%X CSR state %d"), + sme_rsp->messageType, cur_state); + return status; + } +#endif + + /* Process the message based on the state of the roaming states... */ +#if defined(ANI_RTT_DEBUG) + if (!pAdapter->fRttModeEnabled) { +#endif + switch (cur_state) { + case eCSR_ROAMING_STATE_JOINED: + /* are we in joined state */ + csr_roam_joined_state_msg_processor(mac_ctx, msg_buf); + break; + case eCSR_ROAMING_STATE_JOINING: + /* are we in roaming states */ +#if defined(ANI_EMUL_ASSOC) + emulRoamingStateMsgProcessor(pAdapter, pMBBufHdr); +#endif + csr_roaming_state_msg_processor(mac_ctx, msg_buf); + break; + + default: + /* + * For all other messages, we ignore it + * 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 == sme_rsp->messageType) { + sms_log(mac_ctx, LOGW, + FL("handling msg 0x%X CSR state is %d"), + sme_rsp->messageType, cur_state); + csr_roam_check_for_link_status_change(mac_ctx, + sme_rsp); + } else if (eWNI_SME_GET_RSSI_REQ == + sme_rsp->messageType) { + tAniGetRssiReq *pGetRssiReq = + (tAniGetRssiReq *) msg_buf; + if (NULL == pGetRssiReq->rssiCallback) { + sms_log(mac_ctx, LOGE, + FL("rssiCallback is NULL")); + return status; + } + sms_log(mac_ctx, LOGW, + FL("msg eWNI_SME_GET_RSSI_REQ is not handled by CSR in state %d. calling RSSI callback"), + cur_state); + ((tCsrRssiCallback)(pGetRssiReq->rssiCallback))( + pGetRssiReq->lastRSSI, + pGetRssiReq->staId, + pGetRssiReq->pDevContext); + } else { + sms_log(mac_ctx, LOGE, + FL("Message 0x%04X is not handled by CSR state is %d session Id %d"), + sme_rsp->messageType, cur_state, + session_id); + + if (eWNI_SME_FT_PRE_AUTH_RSP == + sme_rsp->messageType) { + sms_log(mac_ctx, LOGE, + FL("Dequeue eSmeCommandRoam command with reason eCsrPerformPreauth")); + csr_dequeue_roam_command(mac_ctx, + eCsrPerformPreauth); + } else if (eWNI_SME_REASSOC_RSP == + sme_rsp->messageType) { + sms_log(mac_ctx, LOGE, + FL("Dequeue eSmeCommandRoam command with reason eCsrSmeIssuedFTReassoc")); + csr_dequeue_roam_command(mac_ctx, + eCsrSmeIssuedFTReassoc); + } + } + break; + } /* switch */ +#if defined(ANI_RTT_DEBUG) + } +#endif + return status; +} + +bool csr_check_ps_ready(void *pv) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pv); + + if (pMac->roam.sPendingCommands < 0) { + CDF_ASSERT(pMac->roam.sPendingCommands >= 0); + return 0; + } + return pMac->roam.sPendingCommands == 0; +} + +bool csr_check_ps_offload_ready(void *pv, uint32_t sessionId) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(pv); + + CDF_ASSERT(pMac->roam.sPendingCommands >= 0); + return pMac->roam.sPendingCommands == 0; +} + diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h new file mode 100644 index 000000000000..16797840820a --- /dev/null +++ b/core/sme/src/csr/csr_inside_api.h @@ -0,0 +1,1070 @@ +/* + * 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 csr_inside_api.h + + Define interface only used by CSR. + ========================================================================== */ +#ifndef CSR_INSIDE_API_H__ +#define CSR_INSIDE_API_H__ + +#include "csr_support.h" +#include "sme_inside.h" +#include "cds_reg_service.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 + +#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_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 300 +#define SYSTEM_TIME_MSEC_TO_USEC 1000 + +/* This number minus 1 means the number of times a channel is scanned before a BSS is remvoed from */ +/* cache scan result */ +#define CSR_AGING_COUNT 3 +#define CSR_SCAN_GET_RESULT_INTERVAL (5 * CDF_MC_TIMER_TO_SEC_UNIT) /* 5 seconds */ +#define CSR_MIC_ERROR_TIMEOUT (60 * CDF_MC_TIMER_TO_SEC_UNIT) /* 60 seconds */ +#define CSR_TKIP_COUNTER_MEASURE_TIMEOUT (60 * CDF_MC_TIMER_TO_SEC_UNIT) /* 60 seconds */ + +#define CSR_SCAN_RESULT_CFG_AGING_INTERVAL (CDF_MC_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 (int8_t) 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_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) +#define CSR_ACTIVE_SCAN_LIST_CMD_TIMEOUT (1000*30) + +#define CSR_MAX_BSSID_COUNT ((CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE/4000) * 3) +#define CSR_CUSTOM_CONC_GO_BI 100 +#define MIN_11P_CHANNEL (rf_channels[MIN_5_9GHZ_CHANNEL].channelNum) + +typedef enum { + eCsrNextScanNothing, + eCsrNextLostLinkScan1Success, + eCsrNextLostLinkScan1Failed, + eCsrNextLostLinkScan2Success, + eCsrNextLostLinkScan2Failed, + eCsrNextLostLinkScan3Success, + eCsrNexteScanForSsidSuccess, + eCsrNextLostLinkScan3Failed, + eCsrNext11dScan1Failure, + eCsrNext11dScan1Success, + eCsrNext11dScan2Failure, + eCsrNext11dScan2Success, + eCsrNext11dScanComplete, + eCsrNexteScanForSsidFailure, + +} eCsrScanCompleteNextCommand; + +typedef enum { + eCsrJoinSuccess, + eCsrJoinFailure, + eCsrReassocSuccess, + eCsrReassocFailure, + eCsrNothingToJoin, + eCsrStartBssSuccess, + eCsrStartBssFailure, + eCsrSilentlyStopRoaming, + eCsrSilentlyStopRoamingSaveState, + eCsrJoinWdsFailure, + eCsrJoinFailureDueToConcurrency, + +} eCsrRoamCompleteResult; + +typedef struct tagScanReqParam { + uint8_t bReturnAfter1stMatch; + uint8_t fUniqueResult; + uint8_t freshScan; + uint8_t hiddenSsid; + uint8_t reserved; +} tScanReqParam; + +typedef struct tagCsrScanResult { + tListElem Link; + int32_t AgingCount; /* This BSS is removed when it reaches 0 or less */ + uint32_t preferValue; /* The bigger the number, the better the BSS. This value override capValue */ + uint32_t capValue; /* The biggger the better. This value is in use only if we have equal preferValue */ + /* This member must be the last in the structure because the end of tSirBssDescription (inside) is an */ + /* array with nonknown 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))) + +extern const tRfChannelProps rf_channels[NUM_RF_CHANNELS]; +eCsrRoamState csr_roam_state_change(tpAniSirGlobal pMac, + eCsrRoamState NewRoamState, uint8_t sessionId); +CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf); +void csr_roaming_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf); +void csr_roam_joined_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf); +bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp); +void csr_release_command_roam(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_release_command_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_release_command_wm_status_change(tpAniSirGlobal pMac, tSmeCmd *pCommand); +extern void csr_release_roc_req_cmd(tpAniSirGlobal mac_ctx); + +bool csr_is_duplicate_bss_description(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, + tDot11fBeaconIEs *pIes2, bool fForced); +CDF_STATUS csr_roam_save_connected_bss_desc(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDesc); +bool csr_is_network_type_equal(tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2); +CDF_STATUS csr_scan_sme_scan_response(tpAniSirGlobal pMac, void *pMsgBuf); +/* + Prepare a filter base on a profile for parsing the scan results. + Upon successful return, caller MUST call csr_free_scan_filter on + pScanFilter when it is done with the filter. + */ +CDF_STATUS csr_roam_prepare_filter_from_profile(tpAniSirGlobal pMac, + tCsrRoamProfile *pProfile, + tCsrScanResultFilter *pScanFilter); +CDF_STATUS csr_roam_copy_profile(tpAniSirGlobal pMac, + tCsrRoamProfile *pDstProfile, + tCsrRoamProfile *pSrcProfile); +CDF_STATUS csr_roam_start(tpAniSirGlobal pMac); +void csr_roam_stop(tpAniSirGlobal pMac, uint32_t sessionId); +void csr_roam_startMICFailureTimer(tpAniSirGlobal pMac); +void csr_roam_stopMICFailureTimer(tpAniSirGlobal pMac); +void csr_roam_startTKIPCounterMeasureTimer(tpAniSirGlobal pMac); +void csr_roam_stopTKIPCounterMeasureTimer(tpAniSirGlobal pMac); + +CDF_STATUS csr_scan_open(tpAniSirGlobal pMac); +CDF_STATUS csr_scan_close(tpAniSirGlobal pMac); +CDF_STATUS csr_scan_request_lost_link1(tpAniSirGlobal pMac, uint32_t sessionId); +CDF_STATUS csr_scan_request_lost_link2(tpAniSirGlobal pMac, uint32_t sessionId); +CDF_STATUS csr_scan_request_lost_link3(tpAniSirGlobal pMac, uint32_t sessionId); +CDF_STATUS csr_scan_handle_failed_lostlink1(tpAniSirGlobal pMac, + uint32_t sessionId); +CDF_STATUS csr_scan_handle_failed_lostlink2(tpAniSirGlobal pMac, + uint32_t sessionId); +CDF_STATUS csr_scan_handle_failed_lostlink3(tpAniSirGlobal pMac, + uint32_t sessionId); +tCsrScanResult *csr_scan_append_bss_description(tpAniSirGlobal pMac, + tSirBssDescription * + pSirBssDescription, + tDot11fBeaconIEs *pIes, + bool fForced, uint8_t sessionId); +void csr_scan_call_callback(tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrScanStatus scanStatus); +CDF_STATUS csr_scan_copy_request(tpAniSirGlobal pMac, tCsrScanRequest *pDstReq, + tCsrScanRequest *pSrcReq); +CDF_STATUS csr_scan_free_request(tpAniSirGlobal pMac, tCsrScanRequest *pReq); +CDF_STATUS csr_scan_copy_result_list(tpAniSirGlobal pMac, tScanResultHandle hIn, + tScanResultHandle *phResult); +CDF_STATUS csr_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, uint32_t roamId, + bool notify); +CDF_STATUS csr_scan_start_result_cfg_aging_timer(tpAniSirGlobal pMac); +CDF_STATUS csr_scan_stop_result_cfg_aging_timer(tpAniSirGlobal pMac); +void csr_scan_stop_timers(tpAniSirGlobal pMac); +/* To remove fresh scan commands from the pending queue */ +bool csr_scan_remove_fresh_scan_command(tpAniSirGlobal pMac, uint8_t sessionId); +CDF_STATUS csr_scan_abort_mac_scan(tpAniSirGlobal pMac, uint8_t sessionId, + eCsrAbortReason reason); +void csr_remove_cmd_from_pending_list(tpAniSirGlobal pMac, tDblLinkList *pList, + eSmeCommandType commandType); +void csr_remove_cmd_with_session_id_from_pending_list(tpAniSirGlobal pMac, + uint8_t sessionId, + tDblLinkList *pList, + eSmeCommandType commandType); +CDF_STATUS csr_scan_abort_mac_scan_not_for_connect(tpAniSirGlobal pMac, + uint8_t sessionId); +CDF_STATUS csr_scan_abort_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId); +void csr_remove_scan_for_ssid_from_pending_list(tpAniSirGlobal pMac, + tDblLinkList *pList, + uint32_t sessionId); + +CDF_STATUS csr_abort_scan_from_active_list(tpAniSirGlobal pMac, + tDblLinkList *pList, uint32_t sessionId, + eSmeCommandType scan_cmd_type, eCsrAbortReason abort_reason); + +/* 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. */ +CDF_STATUS csr_scan_age_results(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 */ +bool csr_learn_11dcountry_information(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, bool fForce); +void csr_apply_country_information(tpAniSirGlobal pMac); +void csr_set_cfg_scan_control_list(tpAniSirGlobal pMac, uint8_t *countryCode, + tCsrChannel *pChannelList); +void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_free_scan_result_entry(tpAniSirGlobal pMac, tCsrScanResult *pResult); + +CDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamInfo *pRoamInfo, uint32_t roamId, + eRoamCmdStatus u1, eCsrRoamResult u2); +CDF_STATUS csr_roam_issue_connect(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tScanResultHandle hBSSList, + eCsrRoamReason reason, uint32_t roamId, + bool fImediate, bool fClearScan); +CDF_STATUS csr_roam_issue_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields *pModProfileFields, + eCsrRoamReason reason, uint32_t roamId, + bool fImediate); +void csr_roam_complete(tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, + void *Context); +CDF_STATUS csr_roam_issue_set_context_req(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrEncryptionType EncryptType, + tSirBssDescription *pBssDescription, + tSirMacAddr *bssId, bool addKey, + bool fUnicast, + tAniKeyDirection aniKeyDirection, + uint8_t keyId, uint16_t keyLength, + uint8_t *pKey, uint8_t paeRole); +CDF_STATUS csr_roam_process_disassoc_deauth(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fDisassoc, bool fMICFailure); +CDF_STATUS csr_roam_save_connected_infomation(tpAniSirGlobal pMac, + uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes); +void csr_roam_check_for_link_status_change(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg); +void csr_roam_stats_rsp_processor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg); +CDF_STATUS csr_roam_issue_start_bss(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamStartBssParams *pParam, + tCsrRoamProfile *pProfile, + tSirBssDescription *pBssDesc, uint32_t roamId); +CDF_STATUS csr_roam_issue_stop_bss(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamSubState NewSubstate); +bool csr_is_same_profile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile1, + tCsrRoamProfile *pProfile2); +bool csr_is_roam_command_waiting(tpAniSirGlobal pMac); +bool csr_is_roam_command_waiting_for_session(tpAniSirGlobal pMac, uint32_t sessionId); +bool csr_is_scan_for_roam_command_active(tpAniSirGlobal pMac); +eRoamCmdStatus csr_get_roam_complete_status(tpAniSirGlobal pMac, + uint32_t sessionId); +/* pBand can be NULL if caller doesn't need to get it */ +CDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason); +CDF_STATUS csr_roam_disconnect_internal(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason); +/* pCommand may be NULL */ +void csr_roam_remove_duplicate_command(tpAniSirGlobal pMac, uint32_t sessionId, + tSmeCmd *pCommand, + eCsrRoamReason eRoamReason); + +CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirBssDescription *pBssDescription, + tCsrRoamProfile *pProfile, + tDot11fBeaconIEs *pIes, uint16_t messageType); +CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, uint16_t reasonCode); +CDF_STATUS csr_send_mb_deauth_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, uint16_t reasonCode); +CDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeDisassocInd pDisassocInd); +CDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeDeauthInd pDeauthInd); +CDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, + CDF_STATUS status); +CDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac, + tpSirSmeAssocInd pAssocInd, + CDF_STATUS Halstatus, + uint8_t sessionId); +CDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamBssType bssType, + tCsrRoamStartBssParams *pParam, + tSirBssDescription *pBssDesc); +CDF_STATUS csr_send_mb_stop_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId); + +/* Caller should put the BSS' ssid to fiedl bssSsid when comparing SSID for a BSS. */ +bool csr_is_ssid_match(tpAniSirGlobal pMac, uint8_t *ssid1, uint8_t ssid1Len, + uint8_t *bssSsid, uint8_t bssSsidLen, bool fSsidRequired); +bool csr_is_phy_mode_match(tpAniSirGlobal pMac, uint32_t phyMode, + tSirBssDescription *pSirBssDesc, + tCsrRoamProfile *pProfile, + eCsrCfgDot11Mode *pReturnCfgDot11Mode, + tDot11fBeaconIEs *pIes); +bool csr_roam_is_channel_valid(tpAniSirGlobal pMac, uint8_t channel); + +/* pNumChan is a caller allocated space with the sizeof pChannels */ +CDF_STATUS csr_get_cfg_valid_channels(tpAniSirGlobal pMac, uint8_t *pChannels, + uint32_t *pNumChan); +void csr_roam_ccm_cfg_set_callback(tpAniSirGlobal pMac, int32_t result); + +tPowerdBm csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel); + +/* To free the last roaming profile */ +void csr_free_roam_profile(tpAniSirGlobal pMac, uint32_t sessionId); +void csr_free_connect_bss_desc(tpAniSirGlobal pMac, uint32_t sessionId); +CDF_STATUS csr_move_bss_to_head_from_bssid(tpAniSirGlobal pMac, + struct cdf_mac_addr *bssid, + tScanResultHandle hScanResult); +bool csr_check_ps_ready(void *pv); +bool csr_check_ps_offload_ready(void *pv, uint32_t sessionId); + +/* to free memory allocated inside the profile structure */ +void csr_release_profile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile); +/* To free memory allocated inside scanFilter */ +void csr_free_scan_filter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter); +eCsrCfgDot11Mode csr_get_cfg_dot11_mode_from_csr_phy_mode(tCsrRoamProfile *pProfile, + eCsrPhyMode phyMode, + bool fProprietary); +uint32_t csr_translate_to_wni_cfg_dot11_mode(tpAniSirGlobal pMac, + eCsrCfgDot11Mode csrDot11Mode); +void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fPopulate5GBand); +void csr_apply_channel_power_info_to_fw(tpAniSirGlobal pMac, + tCsrChannel *pChannelList, + uint8_t *countryCode); +void csr_apply_power2_current(tpAniSirGlobal pMac); +void csr_assign_rssi_for_category(tpAniSirGlobal pMac, int8_t bestApRssi, + uint8_t catOffset); +CDF_STATUS csr_roam_remove_connected_bss_from_scan_cache(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile * + pConnProfile); +CDF_STATUS csr_roam_start_roaming(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamingReason roamingReason); +/* return a bool to indicate whether roaming completed or continue. */ +bool csr_roam_complete_roaming(tpAniSirGlobal pMac, uint32_t sessionId, + bool fForce, eCsrRoamResult roamResult); +void csr_roam_completion(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand, + eCsrRoamResult roamResult, bool fSuccess); +void csr_roam_cancel_roaming(tpAniSirGlobal pMac, uint32_t sessionId); +void csr_apply_channel_power_info_wrapper(tpAniSirGlobal pMac); +void csr_reset_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId); +#ifdef FEATURE_WLAN_WAPI +void csr_reset_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId); +#endif /* FEATURE_WLAN_WAPI */ +CDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac, uint32_t tableSize, + tSirMacChanInfo *channelTable); + +/* 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 */ +bool csr_match_country_code(tpAniSirGlobal pMac, uint8_t *pCountry, + tDot11fBeaconIEs *pIes); +CDF_STATUS csr_roam_set_key(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamSetKey *pSetKey, uint32_t roamId); +CDF_STATUS csr_roam_open_session(tpAniSirGlobal pMac, + csr_roam_completeCallback callback, void *pContext, + uint8_t *pSelfMacAddr, uint8_t *pbSessionId, + uint32_t type, uint32_t subType); +/* fSync: true means cleanupneeds to handle synchronously. */ +CDF_STATUS csr_roam_close_session(tpAniSirGlobal pMac, uint32_t sessionId, + bool fSync, + csr_roamSessionCloseCallback callback, + void *pContext); +void csr_cleanup_session(tpAniSirGlobal pMac, uint32_t sessionId); +CDF_STATUS csr_roam_get_session_id_from_bssid(tpAniSirGlobal pMac, struct cdf_mac_addr *bssid, + uint32_t *pSessionId); +eCsrCfgDot11Mode csr_find_best_phy_mode(tpAniSirGlobal pMac, uint32_t phyMode); + +/* --------------------------------------------------------------------------- + \fn csr_scan_enable + \brief Enable the scanning feature of CSR. It must be called before any scan request can be performed. + \param tHalHandle - HAL context handle + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_enable(tpAniSirGlobal); + +/* --------------------------------------------------------------------------- + \fn csr_scan_disable + \brief Disableing the scanning feature of CSR. After this function return success, no scan is performed until + a successfull to csr_scan_enable + \param tHalHandle - HAL context handle + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_disable(tpAniSirGlobal); +/* --------------------------------------------------------------------------- + \fn csr_scan_request + \brief Request a 11d or full scan. + \param callback - a callback function that scan calls upon finish, will not be called if csr_scan_request returns error + \param pContext - a pointer passed in for the callback + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_request(tpAniSirGlobal, uint16_t, tCsrScanRequest *, + csr_scan_completeCallback 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 csr_scan_request + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csrScanAbort(tpAniSirGlobal, uint32_t scanRequestID); + +/* --------------------------------------------------------------------------- + \fn csr_scan_get_result + \brief Return scan results. + \param pFilter - If pFilter is NULL, all cached results are returned + \param phResult - an object for the result. + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_get_result(tpAniSirGlobal, tCsrScanResultFilter *pFilter, + tScanResultHandle *phResult); + +/* --------------------------------------------------------------------------- + \fn csr_scan_flush_result + \brief Clear scan results. + \param pMac - pMac global pointer + \param sessionId - Session Identifier + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_flush_result(tpAniSirGlobal); +/* --------------------------------------------------------------------------- + * \fn csr_scan_filter_results + * \brief Filter scan results based on valid channel list. + * \param pMac - Pointer to Global MAC structure + * \return CDF_STATUS + ***------------------------------------------------------------------------------- + */ +CDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac); + +void csr_save_scan_results(tpAniSirGlobal pMac, uint8_t reason, + uint8_t sessionId); + +CDF_STATUS csr_scan_flush_selective_result(tpAniSirGlobal, bool flushP2P); + +/* --------------------------------------------------------------------------- + \fn csr_scan_result_get_first + \brief Returns the first element of scan result. + \param hScanResult - returned from csr_scan_get_result + \return tCsrScanResultInfo * - NULL if no result + -------------------------------------------------------------------------------*/ +tCsrScanResultInfo *csr_scan_result_get_first(tpAniSirGlobal, + tScanResultHandle hScanResult); +/* --------------------------------------------------------------------------- + \fn csr_scan_result_get_next + \brief Returns the next element of scan result. It can be called without calling csr_scan_result_get_first first + \param hScanResult - returned from csr_scan_get_result + \return Null if no result or reach the end + -------------------------------------------------------------------------------*/ +tCsrScanResultInfo *csr_scan_result_get_next(tpAniSirGlobal, + tScanResultHandle hScanResult); + +/* --------------------------------------------------------------------------- + \fn csr_get_country_code + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_get_country_code(tpAniSirGlobal pMac, uint8_t *pBuf, + uint8_t *pbLen); + +/* --------------------------------------------------------------------------- + \fn csr_set_country_code + \brief this function is to set the country code so channel/power setting matches the countrycode and + the domain it belongs to. + \param pCountry - Caller allocated buffer with at least 3 bytes specifying the country code + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry); + +/* --------------------------------------------------------------------------- + \fn csr_get_regulatory_domain_for_country + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_get_regulatory_domain_for_country(tpAniSirGlobal pMac, + uint8_t *pCountry, + v_REGDOMAIN_t *pDomainId, + v_CountryInfoSource_t source); + +/* some support functions */ +bool csr_is11d_supported(tpAniSirGlobal pMac); +bool csr_is11h_supported(tpAniSirGlobal pMac); +bool csr_is11e_supported(tpAniSirGlobal pMac); +bool csr_is_wmm_supported(tpAniSirGlobal pMac); +bool csr_is_mcc_supported(tpAniSirGlobal pMac); + +/* Return SUCCESS is the command is queued, failed */ +CDF_STATUS csr_queue_sme_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + bool fHighPriority); +tSmeCmd *csr_get_command_buffer(tpAniSirGlobal pMac); +void csr_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); +void csr_scan_flush_bss_entry(tpAniSirGlobal pMac, + tpSmeCsaOffloadInd pCsaOffloadInd); +CDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac, uint32_t scan_id, + tListElem **entry); + +#ifdef FEATURE_WLAN_WAPI +bool csr_is_profile_wapi(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 diag_auth_type_from_csr_type(eCsrAuthType authType); +int diag_enc_type_from_csr_type(eCsrEncryptionType encType); +#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ +/* --------------------------------------------------------------------------- + \fn csr_scan_result_purge + \brief remove all items(tCsrScanResult) in the list and free memory for each item + \param hScanResult - returned from csr_scan_get_result. hScanResult is considered gone by + calling this function and even before this function reutrns. + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac, + tScanResultHandle hScanResult); + +/* /////////////////////////////////////////Common Scan ends */ + +/* --------------------------------------------------------------------------- + \fn csr_roam_connect + \brief To inititiate an association + \param pProfile - can be NULL to join to any open ones + \param pRoamId - to get back the request ID + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + uint32_t *pRoamId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_reassoc + \brief To inititiate 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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tCsrRoamModifyProfileFields modProfileFields, + uint32_t *pRoamId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_reconnect + \brief To disconnect and reconnect with the same profile + \return CDF_STATUS. It returns fail if currently not connected + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_reconnect(tpAniSirGlobal pMac, uint32_t sessionId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_set_pmkid_cache + \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 retruning, this is either the number needed or number of items put into pPMKIDCache + \return CDF_STATUS - 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 + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_set_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId, + tPmkidCacheInfo *pPMKIDCache, + uint32_t numItems, bool update_entire_cache); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/* --------------------------------------------------------------------------- + *\fn csr_roam_set_psk_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 CDF_STATUS - usually it succeed unless sessionId is not found + *\Note: + *-------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_set_psk_pmk(tpAniSirGlobal pMac, uint32_t sessionId, + uint8_t *pPSK_PMK, size_t pmk_len); + +/* --------------------------------------------------------------------------- + *\fn csr_roam_set_key_mgmt_offload + *\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 CDF_STATUS - usually it succeed unless sessionId is not found + *\Note: + *-------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_set_key_mgmt_offload(tpAniSirGlobal pMac, + uint32_t sessionId, + bool nRoamKeyMgmtOffloadEnabled); +#endif +/* --------------------------------------------------------------------------- + \fn csr_roam_get_wpa_rsn_req_ie + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_wpa_rsn_req_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_wpa_rsn_rsp_ie + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_wpa_rsn_rsp_ie(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pLen, uint8_t *pBuf); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_num_pmkid_cache + \brief return number of PMKID cache entries + \return uint32_t - the number of PMKID cache entries + -------------------------------------------------------------------------------*/ +uint32_t csr_roam_get_num_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_pmkid_cache + \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 CDF_STATUS - when fail, it usually means the buffer allocated is not big enough + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_pmkid_cache(tpAniSirGlobal pMac, uint32_t sessionId, + uint32_t *pNum, tPmkidCacheInfo *pPmkidCache); + +/** + * csr_roam_get_connect_profile() - To return the current connect profile, + * caller must call csr_roam_free_connect_profile after it is done and before + * reuse for another csr_roam_get_connect_profile call. + * + * @pMac: pointer to global adapter context + * @sessionId: session ID + * @pProfile: pointer to a caller allocated structure + * tCsrRoamConnectedProfile + * + * Return: CDF_STATUS. Failure if not connected, success otherwise + */ +CDF_STATUS csr_roam_get_connect_profile(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_connect_state + \brief To return the current connect state of Roaming + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_connect_state(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrConnectState *pState); + +/* --------------------------------------------------------------------------- + \fn csr_roam_free_connect_profile + \brief To free and reinitialize the profile return previous by csr_roam_get_connect_profile. + \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile + \return CDF_STATUS. + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_free_connect_profile(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pProfile); + +/* --------------------------------------------------------------------------- + \fn csr_apply_channel_and_power_list + \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 CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_apply_channel_and_power_list(tpAniSirGlobal pMac); + +/** + * csr_change_config_params() - The CSR API exposed for HDD to provide config + * params to CSR during SMEs stop -> start sequence. + * + * @pMac: pointer to global adapter context + * @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. + * + * 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. + * + * Return: CDF_STATUS. status of operation + */ +CDF_STATUS csr_change_config_params(tpAniSirGlobal pMac, + tCsrUpdateConfigParam *pUpdateConfigParam); + +/* --------------------------------------------------------------------------- + \fn csr_roam_connect_to_last_profile + \brief To disconnect and reconnect with the same profile + \return CDF_STATUS. It returns fail if currently connected + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_connect_to_last_profile(tpAniSirGlobal pMac, uint32_t sessionId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_disconnect + \brief To disconnect from a network + \param reason -- To indicate the reason for disconnecting. Currently, only eCSR_DISCONNECT_REASON_MIC_ERROR is meanful. + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_disconnect(tpAniSirGlobal pMac, uint32_t sessionId, + eCsrRoamDisconnectReason reason); + +/* --------------------------------------------------------------------------- + \fn csr_scan_get_pmkid_candidate_list + \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 retruning, this is either the number needed or number of items put into pPmkidList + \return CDF_STATUS - 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 + -------------------------------------------------------------------------------*/ +CDF_STATUS csr_scan_get_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId, + tPmkidCandidateInfo *pPmkidList, + uint32_t *pNumItems); + +/* This function is used to stop a BSS. It is similar of csr_roamIssueDisconnect but this function */ +/* doesn't have any logic other than blindly trying to stop BSS */ +CDF_STATUS csr_roam_issue_stop_bss_cmd(tpAniSirGlobal pMac, uint32_t sessionId, + bool fHighPriority); + +void csr_call_roaming_completion_callback(tpAniSirGlobal pMac, + tCsrRoamSession *pSession, + tCsrRoamInfo *pRoamInfo, uint32_t roamId, + eCsrRoamResult roamResult); + +/* --------------------------------------------------------------------------- + \fn csr_roam_issue_disassociate_sta_cmd + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_issue_disassociate_sta_cmd(tpAniSirGlobal pMac, + uint32_t sessionId, + const uint8_t *pPeerMacAddr, + uint32_t reason); + +/** + * csr_roam_issue_deauth_sta_cmd() - issue deauthenticate station command + * @pMac: Pointer to global structure for MAC + * @sessionId: Session Id for Soft AP + * @pDelStaParams: Pointer to parameters of the station to deauthenticate + * + * CSR function that HDD calls to issue a deauthenticate station command + * + * Return: CDF_STATUS_SUCCESS on success or another CDF_STATUS_* on error + */ +CDF_STATUS csr_roam_issue_deauth_sta_cmd(tpAniSirGlobal pMac, + uint32_t sessionId, + struct tagCsrDelStaParams *pDelStaParams); + +/* --------------------------------------------------------------------------- + \fn csr_roam_issue_tkip_counter_measures + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_issue_tkip_counter_measures(tpAniSirGlobal pMac, + uint32_t sessionId, bool bEnable); + +CDF_STATUS csr_send_mb_tkip_counter_measures_req_msg(tpAniSirGlobal pMac, + uint32_t sessinId, bool bEnable, + tSirMacAddr bssId); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_associated_stas + \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 associatd stations info + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_associated_stas(tpAniSirGlobal pMac, uint32_t sessionId, + CDF_MODULE_ID modId, void *pUsrContext, + void *pfnSapEventCallback, + uint8_t *pAssocStasBuf); + +CDF_STATUS csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, + uint32_t sessionId, + CDF_MODULE_ID modId, + tSirMacAddr bssId, + void *pUsrContext, + void *pfnSapEventCallback, + uint8_t *pAssocStasBuf); + +/* --------------------------------------------------------------------------- + \fn csr_roam_get_wps_session_overlap + \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 CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_roam_get_wps_session_overlap(tpAniSirGlobal pMac, uint32_t sessionId, + void *pUsrContext, + void *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac); + +CDF_STATUS csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, uint32_t sessionId, + tSirMacAddr bssId, void *pUsrContext, + void *pfnSapEventCallback, + struct cdf_mac_addr pRemoveMac); + +/* --------------------------------------------------------------------------- + \fn csr_send_chng_mcc_beacon_interval + \brief csr function that HDD calls to send Update beacon interval + \param sessionId - session Id for Soft AP + \return CDF_STATUS + ---------------------------------------------------------------------------*/ +CDF_STATUS +csr_send_chng_mcc_beacon_interval(tpAniSirGlobal pMac, uint32_t sessionId); + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + \fn csr_roam_ft_pre_auth_rsp_processor + \brief csr function that handles pre auth response from LIM + ---------------------------------------------------------------------------*/ +void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, + tpSirFTPreAuthRsp pFTPreAuthRsp); +#endif + + +#if defined(FEATURE_WLAN_ESE) +void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1, + uint32_t *incr); +#endif + +CDF_STATUS csr_roam_enqueue_preauth(tpAniSirGlobal pMac, uint32_t sessionId, + tpSirBssDescription pBssDescription, + eCsrRoamReason reason, bool fImmediate); +CDF_STATUS csr_dequeue_roam_command(tpAniSirGlobal pMac, eCsrRoamReason reason); +#ifdef FEATURE_WLAN_LFR +void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId); +bool csr_neighbor_roam_is_new_connected_profile(tpAniSirGlobal pMac, + uint8_t sessionId); +bool csr_neighbor_roam_connected_profile_match(tpAniSirGlobal pMac, + uint8_t sessionId, + tCsrScanResult *pResult, + tDot11fBeaconIEs *pIes); +#endif + +CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac, + uint32_t sessionId, + struct cdf_mac_addr bssid, + uint8_t channel); + +CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac); +CDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, + uint32_t sessionId, + const uint8_t *pBSSId, + bool flush_cache); + +bool csr_elected_country_info(tpAniSirGlobal pMac); +void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode); +void csr_clear_votes_for_country_info(tpAniSirGlobal pMac); + +#endif + +#ifdef QCA_HT_2040_COEX +CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, + ePhyChanBondState cbMode, bool obssEnabled); +#endif +tSirBssDescription* +csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, + tSirBssDescription *bss_descr); +void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, + eCsrScanStatus scanStatus); +void csr_scan_active_list_timeout_handle(void *userData); +CDF_STATUS csr_prepare_disconnect_command(tpAniSirGlobal mac, + uint32_t session_id, tSmeCmd **sme_cmd); diff --git a/core/sme/src/csr/csr_link_list.c b/core/sme/src/csr/csr_link_list.c new file mode 100644 index 000000000000..1fa0b8b6f5a7 --- /dev/null +++ b/core/sme/src/csr/csr_link_list.c @@ -0,0 +1,571 @@ +/* + * 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. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csr_link_list.c + + Implementation for the Common link list interfaces. + ========================================================================== */ + +#include "csr_link_list.h" +#include "cdf_lock.h" +#include "cdf_memory.h" +#include "cdf_trace.h" +#include "cdf_mc_timer.h" + +CDF_INLINE_FN void csr_list_init(tListElem *pList) +{ + pList->last = pList->next = pList; +} + +CDF_INLINE_FN void csr_list_remove_entry(tListElem *pEntry) +{ + tListElem *pLast; + tListElem *pNext; + + pLast = pEntry->last; + pNext = pEntry->next; + pLast->next = pNext; + pNext->last = pLast; +} + +CDF_INLINE_FN tListElem *csr_list_remove_head(tListElem *pHead) +{ + tListElem *pEntry; + tListElem *pNext; + + pEntry = pHead->next; + pNext = pEntry->next; + pHead->next = pNext; + pNext->last = pHead; + + return pEntry; +} + +CDF_INLINE_FN tListElem *csr_list_remove_tail(tListElem *pHead) +{ + tListElem *pEntry; + tListElem *pLast; + + pEntry = pHead->last; + pLast = pEntry->last; + pHead->last = pLast; + pLast->next = pHead; + + return pEntry; +} + +CDF_INLINE_FN void csr_list_insert_tail(tListElem *pHead, tListElem *pEntry) +{ + tListElem *pLast; + + pLast = pHead->last; + pEntry->last = pLast; + pEntry->next = pHead; + pLast->next = pEntry; + pHead->last = pEntry; +} + +CDF_INLINE_FN void csr_list_insert_head(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 csr_list_insert_entry(tListElem *pEntry, tListElem *pNewEntry) +{ + tListElem *pLast; + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; +} + +uint32_t csr_ll_count(tDblLinkList *pList) +{ + uint32_t c = 0; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return c; + } + + if (pList && (LIST_FLAG_OPEN == pList->Flag)) { + c = pList->Count; + } + + return c; +} + +void csr_ll_lock(tDblLinkList *pList) +{ + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + cdf_mutex_acquire(&pList->Lock); + } +} + +void csr_ll_unlock(tDblLinkList *pList) +{ + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + cdf_mutex_release(&pList->Lock); + } +} + +bool csr_ll_is_list_empty(tDblLinkList *pList, bool fInterlocked) +{ + bool fEmpty = true; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return fEmpty; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + fEmpty = csrIsListEmpty(&pList->ListHead); + + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + return fEmpty; +} + +bool csr_ll_find_entry(tDblLinkList *pList, tListElem *pEntryToFind) +{ + bool fFound = false; + tListElem *pEntry; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return fFound; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + pEntry = csr_ll_peek_head(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 = true; + break; + } + pEntry = pEntry->next; + } + + } + return fFound; +} + +CDF_STATUS csr_ll_open(tHddHandle hHdd, tDblLinkList *pList) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS cdf_status; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (LIST_FLAG_OPEN != pList->Flag) { + pList->Count = 0; + pList->cmdTimeoutTimer = NULL; + cdf_status = cdf_mutex_init(&pList->Lock); + + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + csr_list_init(&pList->ListHead); + pList->Flag = LIST_FLAG_OPEN; + pList->hHdd = hHdd; + } else { + status = CDF_STATUS_E_FAILURE; + } + } + return status; +} + +void csr_ll_close(tDblLinkList *pList) +{ + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + /* Make sure the list is empty... */ + csr_ll_purge(pList, LL_ACCESS_LOCK); + cdf_mutex_destroy(&pList->Lock); + pList->Flag = LIST_FLAG_CLOSE; + } +} + +void csr_ll_insert_tail(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked) +{ + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + csr_list_insert_tail(&pList->ListHead, pEntry); + pList->Count++; + if (fInterlocked) { + csr_ll_unlock(pList); + } + } +} + +void csr_ll_insert_head(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked) +{ + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + csr_list_insert_head(&pList->ListHead, pEntry); + pList->Count++; + if (fInterlocked) { + csr_ll_unlock(pList); + } + if (pList->cmdTimeoutTimer && pList->cmdTimeoutDuration) { + /* timer to detect pending command in activelist */ + cdf_mc_timer_start(pList->cmdTimeoutTimer, + pList->cmdTimeoutDuration); + } + } +} + +void csr_ll_insert_entry(tDblLinkList *pList, tListElem *pEntry, + tListElem *pNewEntry, bool fInterlocked) +{ + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + csr_list_insert_entry(pEntry, pNewEntry); + pList->Count++; + if (fInterlocked) { + csr_ll_unlock(pList); + } + } +} + +tListElem *csr_ll_remove_tail(tDblLinkList *pList, bool fInterlocked) +{ + tListElem *pEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead)) { + + pEntry = csr_list_remove_tail(&pList->ListHead); + pList->Count--; + } + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pEntry; +} + +tListElem *csr_ll_peek_tail(tDblLinkList *pList, bool fInterlocked) +{ + tListElem *pEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead)) { + pEntry = pList->ListHead.last; + } + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pEntry; +} + +tListElem *csr_ll_remove_head(tDblLinkList *pList, bool fInterlocked) +{ + tListElem *pEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead)) { + pEntry = csr_list_remove_head(&pList->ListHead); + pList->Count--; + } + + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pEntry; +} + +tListElem *csr_ll_peek_head(tDblLinkList *pList, bool fInterlocked) +{ + tListElem *pEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead)) { + pEntry = pList->ListHead.next; + } + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pEntry; +} + +void csr_ll_purge(tDblLinkList *pList, bool fInterlocked) +{ + tListElem *pEntry; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK))) { + /* just remove everything from the list until */ + /* nothing left on the list. */ + } + if (fInterlocked) { + csr_ll_unlock(pList); + } + } +} + +bool csr_ll_remove_entry(tDblLinkList *pList, tListElem *pEntryToRemove, + bool fInterlocked) +{ + bool fFound = false; + tListElem *pEntry; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return fFound; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + pEntry = csr_ll_peek_head(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) { + csr_list_remove_entry(pEntry); + pList->Count--; + + fFound = true; + break; + } + + pEntry = pEntry->next; + } + if (fInterlocked) { + csr_ll_unlock(pList); + } + if (pList->cmdTimeoutTimer) { + cdf_mc_timer_stop(pList->cmdTimeoutTimer); + } + } + + return fFound; +} + +tListElem *csr_ll_next(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked) +{ + tListElem *pNextEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pNextEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead) + && csr_ll_find_entry(pList, pEntry)) { + pNextEntry = pEntry->next; + /* Make sure we don't walk past the head */ + if (pNextEntry == &pList->ListHead) { + pNextEntry = NULL; + } + } + + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pNextEntry; +} + +tListElem *csr_ll_previous(tDblLinkList *pList, tListElem *pEntry, + bool fInterlocked) +{ + tListElem *pNextEntry = NULL; + + if (!pList) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: Error!! pList is Null", __func__); + return pNextEntry; + } + + if (LIST_FLAG_OPEN == pList->Flag) { + if (fInterlocked) { + csr_ll_lock(pList); + } + + if (!csrIsListEmpty(&pList->ListHead) + && csr_ll_find_entry(pList, pEntry)) { + pNextEntry = pEntry->last; + /* Make sure we don't walk past the head */ + if (pNextEntry == &pList->ListHead) { + pNextEntry = NULL; + } + } + + if (fInterlocked) { + csr_ll_unlock(pList); + } + } + + return pNextEntry; +} diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c new file mode 100644 index 000000000000..5aef6cf3e0f8 --- /dev/null +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -0,0 +1,3541 @@ +/* + * 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 csr_neighbor_roam.c + + Implementation for the simple roaming algorithm for 802.11r Fast + transitions and Legacy roaming for Android platform. + ========================================================================== */ + +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING +#include "wma_types.h" +#include "cds_mq.h" +#include "csr_inside_api.h" +#include "sms_debug.h" +#include "sme_qos_internal.h" +#include "sme_inside.h" +#include "host_diag_core_event.h" +#include "host_diag_core_log.h" +#include "csr_api.h" +#include "sme_api.h" +#include "csr_neighbor_roam.h" +#include "mac_trace.h" + +#define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 +#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG +#define NEIGHBOR_ROAM_DEBUG sms_log +#else +#define NEIGHBOR_ROAM_DEBUG(x ...) +#endif + +static void csr_neighbor_roam_reset_channel_info(tpCsrNeighborRoamChannelInfo + rChInfo); +static void csr_neighbor_roam_reset_preauth_control_info(tpAniSirGlobal pMac, + uint8_t sessionId); + +CDF_STATUS csr_roam_copy_connected_profile(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pDstProfile); + +#ifdef WLAN_FEATURE_VOWIFI_11R +static CDF_STATUS csr_neighbor_roam_issue_preauth_req(tpAniSirGlobal pMac, + uint8_t sessionId); +#endif + +#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(mac_ctx, newstate, session) \ +{ \ + mac_ctx->roam.neighborRoamInfo[session].prevNeighborRoamState = \ + mac_ctx->roam.neighborRoamInfo[session].neighborRoamState; \ + mac_ctx->roam.neighborRoamInfo[session].neighborRoamState = newstate; \ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, \ + FL("Sessionid (%d) NeighborRoam transition from %s to %s"), \ + session, csr_neighbor_roam_state_to_string( \ + mac_ctx->roam.neighborRoamInfo[session].prevNeighborRoamState),\ + csr_neighbor_roam_state_to_string(newstate)); \ +} + +uint8_t *csr_neighbor_roam_state_to_string(uint8_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_REASSOCIATING); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING); + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE); + default: + return "eCSR_NEIGHBOR_ROAM_STATE_UNKNOWN"; + } + +} + +#ifdef FEATURE_WLAN_LFR_METRICS +/** + * csr_neighbor_roam_send_lfr_metric_event() - Send event of LFR metric + * @mac_ctx: Handle returned by mac_open. + * @session_id: Session information + * @bssid: BSSID of attempted AP + * @status: Result of LFR operation + * + * LFR metrics - pre-auth completion metric + * Send the event to supplicant indicating pre-auth result + * + * Return: void + */ + +static void csr_neighbor_roam_send_lfr_metric_event( + tpAniSirGlobal mac_ctx, + uint8_t session_id, + tSirMacAddr bssid, + eRoamCmdStatus status) +{ + tCsrRoamInfo *roam_info; + + roam_info = cdf_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roam_info) { + sms_log(mac_ctx, LOG1, FL("Memory allocation failed!")); + } else { + cdf_mem_copy((void *)roam_info->bssid, + (void *)bssid, sizeof(*roam_info)); + csr_roam_call_callback(mac_ctx, session_id, roam_info, 0, + status, 0); + cdf_mem_free(roam_info); + } +} +#else +/* Empty inline function will be a no-op */ +static inline void csr_neighbor_roam_send_lfr_metric_event( + tpAniSirGlobal mac_ctx, + uint8_t session_id, + tSirMacAddr bssid, + eRoamCmdStatus status) +{ + ; +} +#endif + +/** + * csr_neighbor_roam_free_neighbor_roam_bss_node() + * + * @mac_ctx: Pointer to Global MAC structure + * @neighborRoamBSSNode: Neighbor Roam BSS Node to be freed + * + * This function frees all the internal pointers CSR NeighborRoam BSS Info + * and also frees the node itself + * + * Return: None + */ +void csr_neighbor_roam_free_neighbor_roam_bss_node(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo + neighborRoamBSSNode) +{ + if (neighborRoamBSSNode) { + if (neighborRoamBSSNode->pBssDescription) { + cdf_mem_free(neighborRoamBSSNode->pBssDescription); + neighborRoamBSSNode->pBssDescription = NULL; + } + cdf_mem_free(neighborRoamBSSNode); + neighborRoamBSSNode = NULL; + } + + return; +} + +/** + * csr_neighbor_roam_remove_roamable_ap_list_entry() + * + * @mac_ctx: Pointer to Global MAC structure + * @pList: The list from which the entry should be removed + * @pNeighborEntry: Neighbor Roam BSS Node to be removed + * + * This function removes a given entry from the given list + * + * Return: true if successfully removed, else false + */ +bool csr_neighbor_roam_remove_roamable_ap_list_entry(tpAniSirGlobal pMac, + tDblLinkList *pList, + tpCsrNeighborRoamBSSInfo + pNeighborEntry) +{ + if (pList) { + return csr_ll_remove_entry(pList, &pNeighborEntry->List, + LL_ACCESS_LOCK); + } + + sms_log(pMac, LOGE, + FL + ("Removing neighbor BSS node from list failed. Current count = %d"), + csr_ll_count(pList)); + + return false; +} + +/** + * csr_neighbor_roam_next_roamable_ap() - Get next AP from roamable AP list + * @mac_ctx - The handle returned by mac_open. + * @plist - The list from which the entry should be returned + * @neighbor_entry - Neighbor Roam BSS Node whose next entry should be returned + * + * Gets the entry next to passed entry. If NULL is passed, return the entry + * in the head of the list + * + * Return: Neighbor Roam BSS Node to be returned + */ +tpCsrNeighborRoamBSSInfo csr_neighbor_roam_next_roamable_ap( + tpAniSirGlobal mac_ctx, tDblLinkList *llist, + tpCsrNeighborRoamBSSInfo neighbor_entry) +{ + tListElem *entry = NULL; + tpCsrNeighborRoamBSSInfo result = NULL; + + if (llist) { + if (NULL == neighbor_entry) + entry = csr_ll_peek_head(llist, LL_ACCESS_LOCK); + else + entry = csr_ll_next(llist, &neighbor_entry->List, + LL_ACCESS_LOCK); + if (entry) + result = GET_BASE_ADDR(entry, tCsrNeighborRoamBSSInfo, + List); + } + + return result; +} + +/** + * csr_neighbor_roam_free_roamable_bss_list() - Frees roamable APs list + * @mac_ctx: The handle returned by mac_open. + * @llist: Neighbor Roam BSS List to be emptied + * + * Empties and frees all the nodes in the roamable AP list + * + * Return: none + */ +void csr_neighbor_roam_free_roamable_bss_list(tpAniSirGlobal mac_ctx, + tDblLinkList *llist) +{ + tpCsrNeighborRoamBSSInfo result = NULL; + + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOG2, + FL("Emptying the BSS list. Current count = %d"), + csr_ll_count(llist)); + + /* + * Pick up the head, remove and free the node till + * the list becomes empty + */ + while ((result = csr_neighbor_roam_next_roamable_ap(mac_ctx, llist, + NULL)) != NULL) { + csr_neighbor_roam_remove_roamable_ap_list_entry(mac_ctx, + llist, result); + csr_neighbor_roam_free_neighbor_roam_bss_node(mac_ctx, result); + } + return; +} + +static void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) { + csr_neighbor_roam_issue_preauth_req(pMac, sessionId); + } else { + sms_log(pMac, LOGE, FL("Roaming is diisabled")); + } +} + +CDF_STATUS +csr_neighbor_roam_update_fast_roaming_enabled(tpAniSirGlobal pMac, + uint8_t sessionId, + const bool fastRoamEnabled) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + /* set fast roam enable/disable flag */ + pMac->roam.configParam.isFastRoamIniFeatureEnabled = fastRoamEnabled; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + if (true == fastRoamEnabled) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } else { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } + break; + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL + ("Currently in INIT state, Nothing to do")); + break; + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL + ("Unexpected state %s, returning failure"), + mac_trace_get_neighbour_roam_state + (pNeighborRoamInfo->neighborRoamState)); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +#ifdef FEATURE_WLAN_ESE +CDF_STATUS csr_neighbor_roam_update_ese_mode_enabled(tpAniSirGlobal pMac, + uint8_t sessionId, + const bool eseMode) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + if (true == eseMode) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } else if (false == eseMode) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, + FL + ("Currently in INIT state, Nothing to do")); + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL + ("Unexpected state %d, returning failure"), + pNeighborRoamInfo->neighborRoamState); + break; + } + return cdf_status; +} +#endif + +CDF_STATUS csr_neighbor_roam_set_lookup_rssi_threshold(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t + neighborLookupRssiThreshold) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG.")); + pNeighborRoamInfo->cfgParams.neighborLookupThreshold = + neighborLookupRssiThreshold; + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_LOOKUP_THRESH_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, " + "just set lookupRssi threshold.")); + pNeighborRoamInfo->cfgParams.neighborLookupThreshold = + neighborLookupRssiThreshold; + pNeighborRoamInfo->currentNeighborLookupThreshold = + pNeighborRoamInfo->cfgParams.neighborLookupThreshold; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL + ("Unexpected state %s, returning failure"), + mac_trace_get_neighbour_roam_state + (pNeighborRoamInfo->neighborRoamState)); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +CDF_STATUS +csr_neighbor_roam_set_opportunistic_scan_threshold_diff(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t + nOpportunisticThresholdDiff) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG")); + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + + csr_roam_offload_scan(pMac, + sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_OPPORTUNISTIC_THRESH_DIFF_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, " + "just set opportunistic threshold diff")); + pNeighborRoamInfo->cfgParams.nOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + pNeighborRoamInfo->currentOpportunisticThresholdDiff = + nOpportunisticThresholdDiff; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +CDF_STATUS +csr_neighbor_roam_set_roam_rescan_rssi_diff(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t nRoamRescanRssiDiff) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG.")); + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff = + nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + nRoamRescanRssiDiff; + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_RESCAN_RSSI_DIFF_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, " + "just set rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamRescanRssiDiff = + nRoamRescanRssiDiff; + pNeighborRoamInfo->currentRoamRescanRssiDiff = + nRoamRescanRssiDiff; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +CDF_STATUS +csr_neighbor_roam_set_roam_bmiss_first_bcnt(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t nRoamBmissFirstBcnt) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG.")); + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + + csr_roam_offload_scan(pMac, + sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BMISS_FIRST_BCNT_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, + LOG2, FL + ("Currently in INIT state, safe to set roam rescan rssi diff")); + pNeighborRoamInfo->cfgParams.nRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + pNeighborRoamInfo->currentRoamBmissFirstBcnt = + nRoamBmissFirstBcnt; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +CDF_STATUS +csr_neighbor_roam_set_roam_bmiss_final_bcnt(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t nRoamBmissFinalBcnt) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG.")); + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BMISS_FINAL_BCNT_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, " + "just set roam fianl bmiss count")); + pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + pNeighborRoamInfo->currentRoamBmissFinalBcnt = + nRoamBmissFinalBcnt; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +CDF_STATUS +csr_neighbor_roam_set_roam_beacon_rssi_weight(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t nRoamBeaconRssiWeight) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in CONNECTED state, " + "sending ROAM_SCAN_OFFLOAD_UPDATE_CFG.")); + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_ROAM_BEACON_RSSI_WEIGHT_CHANGED); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Currently in INIT state, " + "just set roam beacon rssi weight")); + pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + pNeighborRoamInfo->currentRoamBeaconRssiWeight = + nRoamBeaconRssiWeight; + break; + + default: + NEIGHBOR_ROAM_DEBUG(pMac, + LOGE, + FL("Unexpected state %d returning failure"), + pNeighborRoamInfo->neighborRoamState); + cdf_status = CDF_STATUS_E_FAILURE; + break; + } + return cdf_status; +} + +/*CleanUP Routines*/ +static void csr_neighbor_roam_reset_channel_info(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) + cdf_mem_free(rChInfo->currentChannelListInfo. + ChannelList); + + rChInfo->currentChannelListInfo.ChannelList = NULL; + } else { + rChInfo->currentChanIndex = 0; + } +} + +static void csr_neighbor_roam_reset_preauth_control_info(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + pNeighborRoamInfo->is11rAssoc = false; + /* Purge pre-auth fail list */ + csr_neighbor_roam_purge_preauth_failed_list(pMac); +#endif + + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = 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 = false; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + cdf_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * + MAX_BSS_IN_NEIGHBOR_RPT); +#endif + pNeighborRoamInfo->uOsRequestedHandoff = 0; + cdf_mem_zero(&pNeighborRoamInfo->handoffReqInfo, + sizeof(tCsrHandoffRequest)); +} + +/** + * csr_neighbor_roam_reset_connected_state_control_info() + * + * @mac_ctx: Pointer to Global MAC structure + * @sessionId : session id + * + * 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 + * + * Return: None + */ +void csr_neighbor_roam_reset_connected_state_control_info(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + csr_neighbor_roam_reset_channel_info(&pNeighborRoamInfo->roamChannelInfo); + csr_neighbor_roam_free_roamable_bss_list(pMac, + &pNeighborRoamInfo->roamableAPList); + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Do not free up the preauth done list here */ + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + pNeighborRoamInfo->FTRoamInfo.neighborRptPending = false; + pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + pNeighborRoamInfo->FTRoamInfo.preauthRspPending = 0; + cdf_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * + MAX_BSS_IN_NEIGHBOR_RPT); +#endif + pNeighborRoamInfo->uOsRequestedHandoff = 0; + cdf_mem_zero(&pNeighborRoamInfo->handoffReqInfo, + sizeof(tCsrHandoffRequest)); +} + +void csr_neighbor_roam_reset_report_scan_state_control_info(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + cdf_zero_macaddr(&pNeighborRoamInfo->currAPbssid); +#ifdef FEATURE_WLAN_ESE + pNeighborRoamInfo->isESEAssoc = false; + pNeighborRoamInfo->isVOAdmitted = false; + pNeighborRoamInfo->MinQBssLoadRequired = 0; +#endif + + /* Purge roamable AP list */ + csr_neighbor_roam_free_roamable_bss_list(pMac, + &pNeighborRoamInfo->roamableAPList); + return; +} + +/** + * csr_neighbor_roam_reset_init_state_control_info() + * + * @mac_ctx: Pointer to Global MAC structure + * @sessionId : session id + * + * 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 + * + * Return: None + */ +void csr_neighbor_roam_reset_init_state_control_info(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + csr_neighbor_roam_reset_connected_state_control_info(pMac, sessionId); + + /* In addition to the above resets, + we should clear off the curAPBssId/Session ID in the timers */ + csr_neighbor_roam_reset_report_scan_state_control_info(pMac, sessionId); +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_purge_preauth_fail_list + + \brief This function empties the preauth fail list + + \param pMac - The handle returned by mac_open. + + \return VOID + + ---------------------------------------------------------------------------*/ +void csr_neighbor_roam_purge_preauth_fail_list(tpAniSirGlobal pMac) +{ + uint8_t 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) { + cdf_mem_zero(pNeighborRoamInfo->FTRoamInfo. + preAuthFailList. + macAddress[pNeighborRoamInfo->FTRoamInfo. + preAuthFailList.numMACAddress - + 1], sizeof(tSirMacAddr)); + pNeighborRoamInfo->FTRoamInfo.preAuthFailList. + numMACAddress--; + } + } + return; +} + +/** + * csr_neighbor_roam_add_preauth_fail() - add bssid to preauth failed list + * @mac_ctx: The handle returned by mac_open. + * @bssid: BSSID to be added to the preauth fail list + * + * This function adds the given BSSID to the Preauth fail list + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS csr_neighbor_roam_add_preauth_fail(tpAniSirGlobal mac_ctx, + uint8_t session_id, + tSirMacAddr bssid) +{ + uint8_t i = 0; + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + uint8_t num_mac_addr = neighbor_roam_info->FTRoamInfo.preAuthFailList. + numMACAddress; + + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGE, + FL(" Added BSSID " MAC_ADDRESS_STR " to Preauth failed list"), + MAC_ADDR_ARRAY(bssid)); + + for (i = 0; + i < neighbor_roam_info->FTRoamInfo.preAuthFailList.numMACAddress; + i++) { + if (true == cdf_mem_compare( + neighbor_roam_info->FTRoamInfo.preAuthFailList.macAddress[i], + bssid, sizeof(tSirMacAddr))) { + sms_log(mac_ctx, LOGW, FL("BSSID "MAC_ADDRESS_STR" already present in preauth fail list"), + MAC_ADDR_ARRAY(bssid)); + return CDF_STATUS_SUCCESS; + } + } + + if ((num_mac_addr + 1) > MAX_NUM_PREAUTH_FAIL_LIST_ADDRESS) { + sms_log(mac_ctx, LOGE, + FL("Cannot add, preauth fail list is full.")); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(neighbor_roam_info->FTRoamInfo.preAuthFailList. + macAddress[num_mac_addr], bssid, sizeof(tSirMacAddr)); + neighbor_roam_info->FTRoamInfo.preAuthFailList.numMACAddress++; + + return CDF_STATUS_SUCCESS; +} + +/** + * csr_neighbor_roam_is_preauth_candidate() + * + * @mac_ctx: Pointer to Global MAC structure + * @bssId : BSSID of the candidate + * + * This function checks whether the given MAC address is already present + * in the preauth fail list and returns true/false accordingly + * + * Return: true if preauth candidate, false otherwise + */ +bool csr_neighbor_roam_is_preauth_candidate(tpAniSirGlobal pMac, + uint8_t sessionId, tSirMacAddr bssId) +{ + uint8_t i = 0; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (csr_roam_is_roam_offload_scan_enabled(pMac)) { + return true; + } + if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress) + return true; + + for (i = 0; + i < pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress; + i++) { + if (true == + cdf_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 false; + } + } + + return true; +} + +/** + * csr_neighbor_roam_issue_preauth_req() - Send preauth request to first AP + * @mac_ctx: The handle returned by mac_open. + * @session_id: Session information + * + * This function issues preauth request to PE with the 1st AP entry in the + * roamable AP list + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +static CDF_STATUS csr_neighbor_roam_issue_preauth_req(tpAniSirGlobal mac_ctx, + uint8_t session_id) +{ + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo neighbor_bss_node; + + + if (false != neighbor_roam_info->FTRoamInfo.preauthRspPending) { + /* This must not be true here */ + CDF_ASSERT(neighbor_roam_info->FTRoamInfo.preauthRspPending == + false); + return CDF_STATUS_E_FAILURE; + } + + /* + * Issue Preauth request to PE here. + * Need to issue the preauth request with the BSSID that is in the + * head of the roamable 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 + */ + neighbor_bss_node = csr_neighbor_roam_next_roamable_ap(mac_ctx, + &neighbor_roam_info->roamableAPList, NULL); + + if (NULL == neighbor_bss_node) { + sms_log(mac_ctx, LOGW, FL("Roamable AP list is empty.. ")); + return CDF_STATUS_E_FAILURE; + } else { + csr_neighbor_roam_send_lfr_metric_event(mac_ctx, session_id, + neighbor_bss_node->pBssDescription->bssId, + eCSR_ROAM_PREAUTH_INIT_NOTIFY); + status = csr_roam_enqueue_preauth(mac_ctx, session_id, + neighbor_bss_node->pBssDescription, + eCsrPerformPreauth, true); + + sms_log(mac_ctx, LOG1, + FL("Before Pre-Auth: BSSID " MAC_ADDRESS_STR ", Ch:%d"), + MAC_ADDR_ARRAY( + neighbor_bss_node->pBssDescription->bssId), + (int)neighbor_bss_node->pBssDescription->channelId); + + if (CDF_STATUS_SUCCESS != status) { + sms_log(mac_ctx, LOGE, + FL("Return failed preauth request status %d"), + status); + return status; + } + } + + neighbor_roam_info->FTRoamInfo.preauthRspPending = true; + + /* Increment the preauth retry count */ + neighbor_roam_info->FTRoamInfo.numPreAuthRetries++; + + /* Transition the state to preauthenticating */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (mac_ctx, eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING, + session_id) + + return status; +} + +/** + * csr_neighbor_roam_preauth_rsp_handler() - handle preauth response + * @mac_ctx: The handle returned by mac_open. + * @session_id: SME session + * @lim_status: eSIR_SUCCESS/eSIR_FAILURE/eSIR_LIM_MAX_STA_REACHED_ERROR/ + * eSIT_LIM_AUTH_RSP_TIMEOUT status from PE + * + * 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 roamable AP list and add the BSSID to + * pre-auth failed list. If no more entries present in roamable AP list, + * transition to REPORT_SCAN state. + * + * Return: CDF_STATUS_SUCCESS on success (i.e. pre-auth processed), + * CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS csr_neighbor_roam_preauth_rsp_handler(tpAniSirGlobal mac_ctx, + uint8_t session_id, + tSirRetStatus lim_status) +{ + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + CDF_STATUS preauth_processed = CDF_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo preauth_rsp_node = NULL; + + if (false == neighbor_roam_info->FTRoamInfo.preauthRspPending) { + /* + * This can happen when we disconnect immediately + * after sending a pre-auth request. During processing + * of the disconnect command, we would have reset + * preauthRspPending and transitioned to INIT state. + */ + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGW, + FL("Unexpected pre-auth response in state %d"), + neighbor_roam_info->neighborRoamState); + preauth_processed = CDF_STATUS_E_FAILURE; + goto DEQ_PREAUTH; + } + /* We can receive it in these 2 states. */ + if ((neighbor_roam_info->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING)) { + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGW, + FL("Preauth response received in state %s"), + mac_trace_get_neighbour_roam_state + (neighbor_roam_info->neighborRoamState)); + preauth_processed = CDF_STATUS_E_FAILURE; + goto DEQ_PREAUTH; + } + + neighbor_roam_info->FTRoamInfo.preauthRspPending = false; + + if (eSIR_SUCCESS == lim_status) + preauth_rsp_node = + csr_neighbor_roam_next_roamable_ap( + mac_ctx, + &neighbor_roam_info->roamableAPList, + NULL); + if ((eSIR_SUCCESS == lim_status) && (NULL != preauth_rsp_node)) { + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOG1, + FL("Preauth completed successfully after %d tries"), + neighbor_roam_info->FTRoamInfo.numPreAuthRetries); + sms_log(mac_ctx, LOG1, + FL("After Pre-Auth: BSSID " MAC_ADDRESS_STR ", Ch:%d"), + MAC_ADDR_ARRAY( + preauth_rsp_node->pBssDescription->bssId), + (int)preauth_rsp_node->pBssDescription->channelId); + + csr_neighbor_roam_send_lfr_metric_event(mac_ctx, session_id, + preauth_rsp_node->pBssDescription->bssId, + eCSR_ROAM_PREAUTH_STATUS_SUCCESS); + /* + * Preauth completed successfully. Insert the preauthenticated + * node to tail of preAuthDoneList. + */ + csr_neighbor_roam_remove_roamable_ap_list_entry(mac_ctx, + &neighbor_roam_info->roamableAPList, + preauth_rsp_node); + csr_ll_insert_tail( + &neighbor_roam_info->FTRoamInfo.preAuthDoneList, + &preauth_rsp_node->List, LL_ACCESS_LOCK); + + /* Pre-auth successful. Transition to PREAUTH Done state */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (mac_ctx, eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, + session_id) + neighbor_roam_info->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 neighbor_bss_node = NULL; + tListElem *entry; + + sms_log(mac_ctx, LOGE, + FL("Preauth failed retry number %d, status = 0x%x"), + neighbor_roam_info->FTRoamInfo.numPreAuthRetries, + lim_status); + + /* + * Preauth failed. Add the bssId to the preAuth failed list + * of MAC Address. Also remove the AP from roamable AP list. + */ + if ((neighbor_roam_info->FTRoamInfo.numPreAuthRetries >= + CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES) || + (eSIR_LIM_MAX_STA_REACHED_ERROR == lim_status)) { + /* + * We are going to remove the node as it fails for + * more than MAX tries. Reset this count to 0 + */ + neighbor_roam_info->FTRoamInfo.numPreAuthRetries = 0; + + /* + * The one in the head of the list should be one with + * which we issued pre-auth and failed + */ + entry = csr_ll_remove_head( + &neighbor_roam_info->roamableAPList, + LL_ACCESS_LOCK); + if (!entry) { + sms_log(mac_ctx, LOGE, + FL("Preauth list is empty")); + goto NEXT_PREAUTH; + } + neighbor_bss_node = GET_BASE_ADDR(entry, + tCsrNeighborRoamBSSInfo, + List); + /* + * Add the BSSID to pre-auth fail list if + * it is not requested by HDD + */ + if (!neighbor_roam_info->uOsRequestedHandoff) + status = + csr_neighbor_roam_add_preauth_fail( + mac_ctx, session_id, + neighbor_bss_node-> + pBssDescription->bssId); + csr_neighbor_roam_send_lfr_metric_event(mac_ctx, + session_id, + neighbor_bss_node->pBssDescription->bssId, + eCSR_ROAM_PREAUTH_STATUS_FAILURE); + /* Now we can free this node */ + csr_neighbor_roam_free_neighbor_roam_bss_node( + mac_ctx, neighbor_bss_node); + } +NEXT_PREAUTH: + /* Issue preauth request for the same/next entry */ + if (CDF_STATUS_SUCCESS == csr_neighbor_roam_issue_preauth_req( + mac_ctx, session_id)) + goto DEQ_PREAUTH; + + if (csr_roam_is_roam_offload_scan_enabled(mac_ctx)) { + if (neighbor_roam_info->uOsRequestedHandoff) { + neighbor_roam_info->uOsRequestedHandoff = 0; + csr_roam_offload_scan(mac_ctx, 0, + ROAM_SCAN_OFFLOAD_START, + REASON_PREAUTH_FAILED_FOR_ALL); + } else { + csr_roam_offload_scan(mac_ctx, 0, + ROAM_SCAN_OFFLOAD_RESTART, + REASON_PREAUTH_FAILED_FOR_ALL); + } + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (mac_ctx, eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, + session_id); + } + } + +DEQ_PREAUTH: + csr_dequeue_roam_command(mac_ctx, eCsrPerformPreauth); + return preauth_processed; +} +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * csr_neighbor_roam_offload_update_preauth_list() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * @roam_sync_ind_ptr: Roam offload sync Ind Info + * + * This function handles the RoamOffloadSynch and adds the + * roamed AP to the preauth done list + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS +csr_neighbor_roam_offload_update_preauth_list(tpAniSirGlobal pMac, + roam_offload_synch_ind *roam_sync_ind_ptr, uint8_t session_id) +{ + tpCsrNeighborRoamControlInfo neighbor_roam_info_ptr = + &pMac->roam.neighborRoamInfo[session_id]; + tpCsrNeighborRoamBSSInfo bss_info_ptr; + uint16_t bss_desc_len; + + if (neighbor_roam_info_ptr->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) { + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL("LFR3:Roam Offload Synch Ind received in state %d"), + neighbor_roam_info_ptr->neighborRoamState); + return CDF_STATUS_E_FAILURE; + } + + bss_info_ptr = cdf_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo)); + if (NULL == bss_info_ptr) { + sms_log(pMac, LOGE, + FL("LFR3:Memory allocation for Neighbor Roam BSS Info failed")); + return CDF_STATUS_E_NOMEM; + } + bss_desc_len = roam_sync_ind_ptr->bss_desc_ptr->length + + sizeof(roam_sync_ind_ptr->bss_desc_ptr->length); + bss_info_ptr->pBssDescription = cdf_mem_malloc(bss_desc_len); + if (bss_info_ptr->pBssDescription != NULL) { + cdf_mem_copy(bss_info_ptr->pBssDescription, + roam_sync_ind_ptr->bss_desc_ptr, + bss_desc_len); + } else { + sms_log(pMac, LOGE, + FL("LFR3:Mem alloc for Neighbor Roam BSS Descriptor failed")); + cdf_mem_free(bss_info_ptr); + return CDF_STATUS_E_NOMEM; + + } + csr_ll_insert_tail(&neighbor_roam_info_ptr->FTRoamInfo.preAuthDoneList, + &bss_info_ptr->List, LL_ACCESS_LOCK); + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (pMac, eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, session_id) + neighbor_roam_info_ptr->FTRoamInfo.numPreAuthRetries = 0; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR3:Entry added to Auth Done List"); + + return CDF_STATUS_SUCCESS; +} +#endif +/** + * csr_neighbor_roam_prepare_scan_profile_filter() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * @scan_filter: Populated scan filter based on the connected profile + * + * This function creates a scan filter based on the currently + * connected profile. Based on this filter, scan results are obtained + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS +csr_neighbor_roam_prepare_scan_profile_filter(tpAniSirGlobal pMac, + tCsrScanResultFilter *pScanFilter, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo nbr_roam_info = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamConnectedProfile *pCurProfile = + &pMac->roam.roamSession[sessionId].connectedProfile; + uint8_t i = 0; + struct roam_ext_params *roam_params; + uint8_t num_ch = 0; + + CDF_ASSERT(pScanFilter != NULL); + if (pScanFilter == NULL) + return CDF_STATUS_E_FAILURE; + + cdf_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 */ + if (nbr_roam_info->uOsRequestedHandoff) { + pScanFilter->BSSIDs.numOfBSSIDs = 1; + pScanFilter->BSSIDs.bssid = + cdf_mem_malloc(sizeof(tSirMacAddr) * + pScanFilter->BSSIDs.numOfBSSIDs); + if (NULL == pScanFilter->BSSIDs.bssid) { + sms_log(pMac, LOGE, + FL("Scan Filter BSSID mem alloc failed")); + return CDF_STATUS_E_NOMEM; + } + + cdf_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++) { + cdf_copy_macaddr(&pScanFilter->BSSIDs.bssid[i], + &nbr_roam_info->handoffReqInfo.bssid); + } + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 = + cdf_mem_malloc(sizeof(tCsrSSIDInfo) * + pScanFilter->SSIDs.numOfSSIDs); + if (NULL == pScanFilter->SSIDs.SSIDList) { + sms_log(pMac, LOGE, + FL("Scan Filter SSID mem alloc failed")); + return CDF_STATUS_E_NOMEM; + } + for (i = 0; i < roam_params->num_ssid_allowed_list; i++) { + pScanFilter->SSIDs.SSIDList[i].handoffPermitted = 1; + pScanFilter->SSIDs.SSIDList[i].ssidHidden = 0; + cdf_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 = + cdf_mem_malloc(sizeof(tCsrSSIDInfo)); + if (NULL == pScanFilter->SSIDs.SSIDList) { + sms_log(pMac, LOGE, + FL("Scan Filter SSID mem alloc failed")); + return CDF_STATUS_E_NOMEM; + } + pScanFilter->SSIDs.SSIDList->handoffPermitted = 1; + pScanFilter->SSIDs.SSIDList->ssidHidden = 0; + pScanFilter->SSIDs.SSIDList->SSID.length = + pCurProfile->SSID.length; + cdf_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,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; + + num_ch = + nbr_roam_info->roamChannelInfo.currentChannelListInfo.numOfChannels; + if (num_ch) { + /* + * We are intrested only in the scan results on channels we + * scanned + */ + pScanFilter->ChannelInfo.numOfChannels = num_ch; + pScanFilter->ChannelInfo.ChannelList = + cdf_mem_malloc(num_ch * sizeof(uint8_t)); + if (NULL == pScanFilter->ChannelInfo.ChannelList) { + sms_log(pMac, LOGE, + FL("Scan Filter Ch list mem alloc failed")); + cdf_mem_free(pScanFilter->SSIDs.SSIDList); + pScanFilter->SSIDs.SSIDList = NULL; + return CDF_STATUS_E_NOMEM; + } + for (i = 0; i < pScanFilter->ChannelInfo.numOfChannels; i++) { + pScanFilter->ChannelInfo.ChannelList[i] = + nbr_roam_info->roamChannelInfo.currentChannelListInfo. + ChannelList[i]; + } + } else { + pScanFilter->ChannelInfo.numOfChannels = 0; + pScanFilter->ChannelInfo.ChannelList = NULL; + } + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (nbr_roam_info->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 CDF_STATUS_SUCCESS; +} + +uint32_t csr_get_current_ap_rssi(tpAniSirGlobal pMac, + tScanResultHandle *pScanResultList, + uint8_t sessionId) +{ + tCsrScanResultInfo *pScanResult; + tpCsrNeighborRoamControlInfo nbr_roam_info = + &pMac->roam.neighborRoamInfo[sessionId]; + /* 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 */ + uint32_t CurrAPRssi = -125; + + while (NULL != + (pScanResult = csr_scan_result_get_next(pMac, *pScanResultList))) { + if (true == + cdf_mem_compare(pScanResult->BssDescriptor.bssId, + nbr_roam_info->currAPbssid.bytes, + 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; + +} + +/** + * csr_neighbor_roam_process_scan_results() - build roaming candidate list + * + * @mac_ctx: The handle returned by mac_open. + * @sessionid: Session information + * @scan_results_list: List obtained from csr_scan_get_result() + * + * This function applies various candidate checks like LFR, 11r, preauth, ESE + * and builds a roamable AP list. It applies age limit only if no suitable + * recent candidates are found. + * + * Output list is built in mac_ctx->roam.neighborRoamInfo[sessionid]. + * + * Return: void + */ + +static void +csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx, + uint8_t sessionid, + tScanResultHandle *scan_results_list) +{ + tCsrScanResultInfo *scan_result; + tpCsrNeighborRoamControlInfo n_roam_info = + &mac_ctx->roam.neighborRoamInfo[sessionid]; + tpCsrNeighborRoamBSSInfo bss_info; + uint32_t cur_ap_rssi; + uint32_t age_ticks = 0; + uint32_t limit_ticks = + cdf_system_msecs_to_ticks(ROAM_AP_AGE_LIMIT_MS); + uint8_t num_candidates = 0; + uint8_t num_dropped = 0; + /* + * first iteration of scan list should consider + * age constraint for candidates + */ + bool age_constraint = true; +#ifdef FEATURE_WLAN_ESE + uint16_t qpresent; + uint16_t qavail; + bool voadmitted; +#endif + /* + * 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. + */ + cur_ap_rssi = csr_get_current_ap_rssi(mac_ctx, scan_results_list, + sessionid); + + /* + * Expecting the scan result already to be in the sorted order based on + * 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 a 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 top of the list provided as it is by CSR Scan + * result API. Hence it is assumed that neighbor score and rssi score + * are in the same order. This will be taken care later. + */ + + do { + while (true) { + tSirBssDescription *descr; + + scan_result = csr_scan_result_get_next( + mac_ctx, *scan_results_list); + if (NULL == scan_result) + break; + descr = &scan_result->BssDescriptor; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("Scan result: BSSID " MAC_ADDRESS_STR + " (Rssi %ld, Ch:%d)"), + MAC_ADDR_ARRAY(descr->bssId), + abs(descr->rssi), descr->channelId); + + if (true == cdf_mem_compare(descr->bssId, + n_roam_info->currAPbssid.bytes, + sizeof(tSirMacAddr))) { + /* + * currently associated AP. Do not have this + * in the roamable AP list + */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + "SKIP-currently associated AP"); + continue; + } +#ifdef FEATURE_WLAN_LFR + /* + * In case of reassoc requested by upper layer, look + * for exact match of bssid & channel. csr cache might + * have duplicates + */ + if ((n_roam_info->uOsRequestedHandoff) && + ((false == cdf_mem_compare(descr->bssId, + n_roam_info->handoffReqInfo.bssid.bytes, + sizeof(tSirMacAddr))) + || (descr->channelId != + n_roam_info->handoffReqInfo.channel))) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + "SKIP-not a candidate AP for OS requested roam"); + continue; + } +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + if ((n_roam_info->is11rAssoc) && + (!csr_neighbor_roam_is_preauth_candidate(mac_ctx, + sessionid, descr->bssId))) { + sms_log(mac_ctx, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#ifdef FEATURE_WLAN_ESE + if (!csr_roam_is_roam_offload_scan_enabled(mac_ctx) && + (n_roam_info->isESEAssoc) && + !csr_neighbor_roam_is_preauth_candidate(mac_ctx, + sessionid, descr->bssId)) { + sms_log(mac_ctx, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + + qpresent = descr->QBSSLoad_present; + qavail = descr->QBSSLoad_avail; + voadmitted = n_roam_info->isVOAdmitted; + if (voadmitted) + sms_log(mac_ctx, LOG1, + FL("New AP QBSS present = %s, BW available = 0x%x, required = 0x%x"), + ((qpresent) ? "yes" : "no"), qavail, + n_roam_info->MinQBssLoadRequired); + if (voadmitted && qpresent && + (qavail < n_roam_info->MinQBssLoadRequired)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + "BSSID : " MAC_ADDRESS_STR " has no bandwidth, ignoring", + MAC_ADDR_ARRAY(descr->bssId)); + continue; + } + if (voadmitted && !qpresent) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + "BSSID : " MAC_ADDRESS_STR " has no QBSS LOAD IE, ignoring", + MAC_ADDR_ARRAY(descr->bssId)); + continue; + } +#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 (csr_roam_is_fast_roam_enabled(mac_ctx, sessionid) && + !csr_neighbor_roam_is_preauth_candidate(mac_ctx, + sessionid, descr->bssId)) { + sms_log(mac_ctx, LOGE, + FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } +#endif /* FEATURE_WLAN_LFR */ + + /* check the age of the AP */ + age_ticks = (uint32_t) cdf_mc_timer_get_system_ticks() - + descr->nReceivedTime; + if (age_constraint == true && age_ticks > limit_ticks) { + num_dropped++; + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_WARN, + FL("Old AP (probe rsp/beacon) skipped.") + ); + continue; + } + + /* Finished all checks, now add it to candidate list */ + bss_info = + cdf_mem_malloc(sizeof(tCsrNeighborRoamBSSInfo)); + if (NULL == bss_info) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed. Ignored candidate.")); + continue; + } + bss_info->pBssDescription = + cdf_mem_malloc(descr->length + + sizeof(descr->length)); + if (bss_info->pBssDescription != NULL) { + cdf_mem_copy(bss_info->pBssDescription, descr, + descr->length + sizeof(descr->length)); + } else { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed. Ignored candidate.")); + cdf_mem_free(bss_info); + continue; + } + /* + * Assign some preference value for now. Need to + * calculate theactual score based on RSSI and neighbor + * AP score + */ + bss_info->apPreferenceVal = 10; + num_candidates++; + csr_ll_insert_tail(&n_roam_info->roamableAPList, + &bss_info->List, LL_ACCESS_LOCK); + } /* end of while (csr_scan_result_get_next) */ + + /* if some candidates were found, then no need to repeat */ + if (num_candidates) + break; + /* + * if age_constraint is already false, we have done two + * iterations and no candidate were found + */ + if (age_constraint == false) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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. + */ + age_constraint = false; + /* if no candidates were dropped no need to repeat */ + } while (num_dropped); + + /* + * 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 + */ + csr_scan_result_purge(mac_ctx, *scan_results_list); +} + +static CDF_STATUS csr_neighbor_roam_process_scan_complete(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrScanResultFilter scanFilter; + tScanResultHandle scanResult; + uint32_t tempVal = 0; + CDF_STATUS hstatus; + + hstatus = csr_neighbor_roam_prepare_scan_profile_filter(pMac, + &scanFilter, + sessionId); + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, + FL + ("11R/ESE/Other Association: Prepare scan to find neighbor AP filter status = %d"), + hstatus); + if (CDF_STATUS_SUCCESS != hstatus) { + sms_log(pMac, LOGE, + FL + ("Scan Filter preparation failed for Assoc type %d.. Bailing out.."), + tempVal); + return CDF_STATUS_E_FAILURE; + } + hstatus = csr_scan_get_result(pMac, &scanFilter, &scanResult); + if (hstatus != CDF_STATUS_SUCCESS) { + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, + FL("Get Scan Result status code %d"), + hstatus); + } + /* Process the scan results and update roamable AP list */ + csr_neighbor_roam_process_scan_results(pMac, sessionId, &scanResult); + + /* Free the scan filter */ + csr_free_scan_filter(pMac, &scanFilter); + + tempVal = csr_ll_count(&pNeighborRoamInfo->roamableAPList); + + if (tempVal) { + csr_neighbor_roam_trigger_handoff(pMac, sessionId); + return CDF_STATUS_SUCCESS; + } + + if (csr_roam_is_roam_offload_scan_enabled(pMac)) { + if (pNeighborRoamInfo->uOsRequestedHandoff) { + csr_roam_offload_scan(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 */ + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_RESTART, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + } + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (pMac, eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, sessionId); + } + return CDF_STATUS_SUCCESS; + +} + + +#if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI +/** + * csr_neighbor_roam_channels_filter_by_current_band() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * @input_ch_list: The input channel list + * @input_num_of_ch: The number of channels in input channel list + * @output_ch_list: The output channel list + * @output_num_of_ch: The number of channels in output channel list + * @merged_output_num_of_ch: The final number of channels in the + * output channel list. + * + * This function is used to filter out the channels based on the + * currently associated AP channel + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS csr_neighbor_roam_channels_filter_by_current_band(tpAniSirGlobal pMac, + uint8_t sessionId, + uint8_t * + pInputChannelList, + uint8_t + inputNumOfChannels, + uint8_t * + pOutputChannelList, + uint8_t * + pMergedOutputNumOfChannels) +{ + uint8_t i = 0; + uint8_t numChannels = 0; + uint8_t currAPoperationChannel = + pMac->roam.neighborRoamInfo[sessionId].currAPoperationChannel; + /* Check for NULL pointer */ + if (!pInputChannelList) + return CDF_STATUS_E_INVAL; + + /* Check for NULL pointer */ + if (!pOutputChannelList) + return CDF_STATUS_E_INVAL; + + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return CDF_STATUS_E_INVAL; + } + for (i = 0; i < inputNumOfChannels; i++) { + if (get_rf_band(currAPoperationChannel) == + get_rf_band(pInputChannelList[i])) { + pOutputChannelList[numChannels] = pInputChannelList[i]; + numChannels++; + } + } + + /* Return final number of channels */ + *pMergedOutputNumOfChannels = numChannels; + + return CDF_STATUS_SUCCESS; +} + +/** + * csr_neighbor_roam_channels_filter_by_current_band() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * @input_ch_list: The additional channels to merge in to the + * "merged" channels list. + * @input_num_of_ch: The number of additional channels. + * @output_ch_list: The place to put the "merged" channel list. + * @output_num_of_ch: The original number of channels in the + * "merged" channels list. + * @merged_output_num_of_ch: The final number of channels in the + * "merged" channel list. + * + * 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 + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS csr_neighbor_roam_merge_channel_lists(tpAniSirGlobal pMac, + uint8_t *pInputChannelList, + uint8_t inputNumOfChannels, + uint8_t *pOutputChannelList, + uint8_t outputNumOfChannels, + uint8_t * + pMergedOutputNumOfChannels) +{ + uint8_t i = 0; + uint8_t j = 0; + uint8_t numChannels = outputNumOfChannels; + + /* Check for NULL pointer */ + if (!pInputChannelList) + return CDF_STATUS_E_INVAL; + + /* Check for NULL pointer */ + if (!pOutputChannelList) + return CDF_STATUS_E_INVAL; + + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return CDF_STATUS_E_INVAL; + } + if (outputNumOfChannels >= WNI_CFG_VALID_CHANNEL_LIST_LEN) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Output Channels %d", + __func__, outputNumOfChannels); + return CDF_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]) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: Merge Neighbor channel list reached Max " + "limit %d", __func__, numChannels); + break; + } + } + + /* Return final number of channels */ + *pMergedOutputNumOfChannels = numChannels; + + return CDF_STATUS_SUCCESS; +} + +/** + * csr_neighbor_roam_create_chan_list_from_neighbor_report() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * + * 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 + * + * Return: CDF_STATUS_SUCCESS on success, CDF_STATUS_E_FAILURE otherwise + */ +CDF_STATUS csr_neighbor_roam_create_chan_list_from_neighbor_report(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpRrmNeighborReportDesc pNeighborBssDesc; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + uint8_t numChannels = 0; + uint8_t i = 0; + uint8_t channelList[MAX_BSS_IN_NEIGHBOR_RPT]; + uint8_t mergedOutputNumOfChannels = 0; + + /* This should always start from 0 whenever we create a channel list out of neighbor AP list */ + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + + pNeighborBssDesc = sme_rrm_get_first_bss_entry_from_neighbor_cache(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 = (uint8_t) pNeighborBssDesc->roamScore; + cdf_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 (get_rf_band + (pNeighborRoamInfo-> + currAPoperationChannel) == + get_rf_band(pNeighborBssDesc-> + pNeighborBssDescription-> + channel)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + "%s: [INFOLOG] Adding %d to Neighbor channel list\n", + __func__, + pNeighborBssDesc-> + pNeighborBssDescription-> + channel); + channelList[numChannels] = + pNeighborBssDesc-> + pNeighborBssDescription->channel; + numChannels++; + } + } + } + + pNeighborBssDesc = + sme_rrm_get_next_bss_entry_from_neighbor_cache(pMac, + pNeighborBssDesc); + } + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + ChannelList) { + cdf_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 = + cdf_mem_malloc((numChannels) * sizeof(uint8_t)); + if (NULL == + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + ChannelList) { + sms_log(pMac, LOGE, + FL + ("Memory allocation for Channel list failed.. TL event ignored")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_copy(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + ChannelList, channelList, (numChannels) * sizeof(uint8_t)); + 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) { + csr_neighbor_roam_merge_channel_lists(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) { + sms_log(pMac, LOG1, + FL("IAPP Neighbor list callback received as expected" + "in state %s."), + mac_trace_get_neighbour_roam_state(pNeighborRoamInfo-> + neighborRoamState)); + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = + true; + if (csr_roam_is_roam_offload_scan_enabled(pMac)) { + csr_roam_offload_scan(pMac, sessionId, + ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_CHANNEL_LIST_CHANGED); + } + } + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; + + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +#ifdef FEATURE_WLAN_LFR +/** + * csr_neighbor_roam_is_ssid_and_security_match() - to match ssid/security + * @pMac: Pointer to mac context + * @pCurProfile: pointer to current roam profile + * @pBssDesc: pointer to bss description + * @pIes: pointer to local ies + * + * This routine will be called to see if SSID and security parameters + * are matching. + * + * Return: bool + */ +bool csr_neighbor_roam_is_ssid_and_security_match(tpAniSirGlobal pMac, + tCsrRoamConnectedProfile *pCurProfile, + tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes) +{ + tCsrAuthList authType; + tCsrEncryptionList uCEncryptionType; + tCsrEncryptionList mCEncryptionType; + bool 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; + + /* Again, treat missing pIes as a non-match. */ + if (!pIes) + return false; + + /* Treat a missing SSID as a non-match. */ + if (!pIes->SSID.present) + return false; + + fMatch = csr_is_ssid_match(pMac, + (void *)pCurProfile->SSID.ssId, + pCurProfile->SSID.length, + pIes->SSID.ssid, + pIes->SSID.num_ssid, 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 = csr_is_security_match(pMac, &authType, + &uCEncryptionType, + &mCEncryptionType, NULL, + NULL, NULL, pBssDesc, + pIes, NULL, NULL, NULL); + return fMatch; + } else { + return fMatch; + } + +} + +bool csr_neighbor_roam_is_new_connected_profile(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamConnectedProfile *pCurrProfile = NULL; + tCsrRoamConnectedProfile *pPrevProfile = NULL; + tDot11fBeaconIEs *pIes = NULL; + tSirBssDescription *pBssDesc = NULL; + bool 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 (CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies(pMac, pBssDesc, &pIes)) + && csr_neighbor_roam_is_ssid_and_security_match(pMac, + pCurrProfile, pBssDesc, pIes)) { + fNew = false; + } + if (pIes) { + cdf_mem_free(pIes); + } + } + + if (fNew) { + sms_log(pMac, LOG1, + FL("Prev roam profile did not match current")); + } else { + sms_log(pMac, LOG1, FL("Prev roam profile matches current")); + } + + return fNew; +} + +bool csr_neighbor_roam_connected_profile_match(tpAniSirGlobal pMac, + uint8_t 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 csr_neighbor_roam_is_ssid_and_security_match(pMac, pCurProfile, + pBssDesc, pIes); +} + +/** + * csr_neighbor_roam_prepare_non_occupied_channel_list() - prepare non-occup CL + * @pMac: The handle returned by mac_open + * @pInputChannelList: The default channels list + * @numOfChannels: The number of channels in the default channels list + * @pOutputChannelList: The place to put the non-occupied channel list + * @pOutputNumOfChannels: Number of channels in the non-occupied channel list + * + * 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 + * + * Return CDF_STATUS + */ +CDF_STATUS +csr_neighbor_roam_prepare_non_occupied_channel_list(tpAniSirGlobal pMac, + uint8_t sessionId, uint8_t *pInputChannelList, + uint8_t numOfChannels, uint8_t *pOutputChannelList, + uint8_t *pOutputNumOfChannels) +{ + uint8_t i = 0; + uint8_t outputNumOfChannels = 0; + uint8_t numOccupiedChannels = + pMac->scan.occupiedChannels[sessionId].numChannels; + uint8_t *pOccupiedChannelList = + pMac->scan.occupiedChannels[sessionId].channelList; + + for (i = 0; i < numOfChannels; i++) { + if (csr_is_channel_present_in_list + (pOccupiedChannelList, numOccupiedChannels, + pInputChannelList[i])) + continue; + /* + * DFS channel will be added in the list only when the + * DFS Roaming scan flag is enabled + */ + if (CDS_IS_DFS_CH(pInputChannelList[i])) { + if (CSR_ROAMING_DFS_CHANNEL_DISABLED != + pMac->roam.configParam.allowDFSChannelRoam) { + pOutputChannelList[outputNumOfChannels++] = + pInputChannelList[i]; + } + } else { + pOutputChannelList[outputNumOfChannels++] = + pInputChannelList[i]; + } + } + + sms_log(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 CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_LFR */ + +/** + * csr_roam_reset_roam_params - API to reset the roaming parameters + * @mac_ctx: Pointer to the global MAC structure + * + * The BSSID blacklist should not be cleared since it has to + * be used across connections. These parameters will be cleared + * and sent to firmware with with the roaming STOP command. + * + * Return: VOID + */ +void csr_roam_reset_roam_params(tpAniSirGlobal mac_ctx) +{ + struct roam_ext_params *roam_params = NULL; + + /* + * clear all the whitelist parameters and remaining + * needs to be retained across connections. + */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("Roaming parameters are reset")); + roam_params = &mac_ctx->roam.configParam.roam_params; + roam_params->num_ssid_allowed_list = 0; + cdf_mem_set(&roam_params->ssid_allowed_list, 0, + sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST); +} + +/** + * csr_neighbor_roam_indicate_disconnect() - To indicate disconnect + * @pMac: The handle returned by mac_open + * @sessionId: CSR session id that got disconnected + * + * 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 + * + * Return: CDF_STATUS + */ +CDF_STATUS csr_neighbor_roam_indicate_disconnect(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; +#ifdef FEATURE_WLAN_LFR + tCsrRoamConnectedProfile *pPrevProfile = + &pNeighborRoamInfo->prevConnProfile; +#endif + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + tCsrRoamSession *roam_session = NULL; + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Disconn ind on session %d in state %d from bss :" + MAC_ADDRESS_STR), sessionId, + pNeighborRoamInfo->neighborRoamState, + MAC_ADDR_ARRAY(pSession->connectedProfile.bssid.bytes)); +#ifdef FEATURE_WLAN_LFR + /* + * Free the current previous profile and move + * the current profile to prev profile. + */ + csr_roam_free_connect_profile(pMac, pPrevProfile); + csr_roam_copy_connect_profile(pMac, sessionId, pPrevProfile); +#endif + /* + * clear the roaming parameters that are per connection. + * For a new connection, they have to be programmed again. + */ + if (!csr_neighbor_middle_of_roaming((tHalHandle)pMac, sessionId)) + csr_roam_reset_roam_params(pMac); + if (NULL != pSession) { + roam_session = &pMac->roam.roamSession[sessionId]; + if (NULL != pSession->pCurRoamProfile && (CDF_STA_MODE != + roam_session->pCurRoamProfile->csrPersona)) { + sms_log(pMac, LOGE, + FL("Ignore disconn ind rcvd from nonSTA persona" + "sessionId: %d, csrPersonna %d"), + sessionId, + (int)roam_session->pCurRoamProfile->csrPersona); + return CDF_STATUS_SUCCESS; + } +#ifdef FEATURE_WLAN_ESE + if (pSession->connectedProfile.isESEAssoc) { + cdf_mem_copy(&pSession->prevApSSID, + &pSession->connectedProfile.SSID, + sizeof(tSirMacSSid)); + cdf_copy_macaddr(&pSession->prevApBssid, + &pSession->connectedProfile.bssid); + pSession->prevOpChannel = + pSession->connectedProfile.operationChannel; + pSession->isPrevApInfoValid = true; + pSession->roamTS1 = cdf_mc_timer_get_system_time(); + } +#endif + } + + switch (pNeighborRoamInfo->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: + /* + * Stop scan and neighbor refresh timers. + * These are indeed not required when we'r in reassoc state. + */ + 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'll + * in-turn block scans. + */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId); + pNeighborRoamInfo->roamChannelInfo. + IAPPNeighborListReceived = false; + } + break; + + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + csr_neighbor_roam_reset_init_state_control_info(pMac, + sessionId); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = + false; + csr_neighbor_roam_reset_connected_state_control_info(pMac, + sessionId); + break; + + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: + /* Stop pre-auth to reassoc interval timer */ + cdf_mc_timer_stop(&pSession->ftSmeContext. + preAuthReassocIntvlTimer); + case eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING: + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = + false; + csr_neighbor_roam_reset_preauth_control_info(pMac, sessionId); + csr_neighbor_roam_reset_report_scan_state_control_info(pMac, + sessionId); + break; + default: + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Received disconnect event" + "in state %s "), + mac_trace_get_neighbour_roam_state( + pNeighborRoamInfo->neighborRoamState)); + NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Transit to INIT state")); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, sessionId) + pNeighborRoamInfo->roamChannelInfo. + IAPPNeighborListReceived = false; + break; + } + /*Inform the Firmware to STOP Scanning as the host has a disconnect. */ + if (csr_roam_is_sta_mode(pMac, sessionId)) { + csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_STOP, + REASON_DISCONNECTED); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * csr_neighbor_roam_info_ctx_init() - Initialize neighbor roam struct + * @pMac: mac context + * @session_id: Session Id + * + * This initializes all the necessary data structures related to the + * associated AP. + * + * Return: CDF status + */ +static void csr_neighbor_roam_info_ctx_init( + tpAniSirGlobal pMac, + uint8_t session_id) +{ + tpCsrNeighborRoamControlInfo ngbr_roam_info = + &pMac->roam.neighborRoamInfo[session_id]; + tCsrRoamSession *session = &pMac->roam.roamSession[session_id]; + +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + int init_ft_flag = false; +#endif + +#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 == + ngbr_roam_info->neighborRoamState) + csr_init_occupied_channels_list(pMac, session_id); +#endif + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (pMac, eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, session_id); + + cdf_copy_macaddr(&ngbr_roam_info->currAPbssid, + &session->connectedProfile.bssid); + ngbr_roam_info->currAPoperationChannel = + session->connectedProfile.operationChannel; + ngbr_roam_info->currentNeighborLookupThreshold = + ngbr_roam_info->cfgParams.neighborLookupThreshold; + ngbr_roam_info->currentOpportunisticThresholdDiff = + ngbr_roam_info->cfgParams.nOpportunisticThresholdDiff; + ngbr_roam_info->currentRoamRescanRssiDiff = + ngbr_roam_info->cfgParams.nRoamRescanRssiDiff; + ngbr_roam_info->currentRoamBmissFirstBcnt = + ngbr_roam_info->cfgParams.nRoamBmissFirstBcnt; + ngbr_roam_info->currentRoamBmissFinalBcnt = + ngbr_roam_info->cfgParams.nRoamBmissFinalBcnt; + ngbr_roam_info->currentRoamBeaconRssiWeight = + ngbr_roam_info->cfgParams.nRoamBeaconRssiWeight; + +#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 */ + csr_neighbor_roam_free_roamable_bss_list(pMac, + &ngbr_roam_info->FTRoamInfo.preAuthDoneList); +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + /* Based on the auth scheme tell if we are 11r */ + if (csr_is_auth_type11r + (session->connectedProfile.AuthType, + session->connectedProfile.MDID.mdiePresent)) { + if (pMac->roam.configParam.isFastTransitionEnabled) + init_ft_flag = true; + ngbr_roam_info->is11rAssoc = true; + } else + ngbr_roam_info->is11rAssoc = false; + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("11rAssoc is = %d"), + ngbr_roam_info->is11rAssoc); +#endif + +#ifdef FEATURE_WLAN_ESE + /* Based on the auth scheme tell if we are 11r */ + if (session->connectedProfile.isESEAssoc) { + if (pMac->roam.configParam.isFastTransitionEnabled) + init_ft_flag = true; + ngbr_roam_info->isESEAssoc = true; + } else + ngbr_roam_info->isESEAssoc = false; + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("isESEAssoc is = %d ft = %d"), + ngbr_roam_info->isESEAssoc, init_ft_flag); +#endif +#ifdef FEATURE_WLAN_LFR + /* If "Legacy Fast Roaming" is enabled */ + if (csr_roam_is_fast_roam_enabled(pMac, session_id)) + init_ft_flag = true; +#endif +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + if (init_ft_flag == false) + return; + /* Initialize all the data structures needed for the 11r FT Preauth */ + ngbr_roam_info->FTRoamInfo.currentNeighborRptRetryNum = 0; + csr_neighbor_roam_purge_preauth_failed_list(pMac); + if (!cds_is_multiple_active_sta_sessions() && + csr_roam_is_roam_offload_scan_enabled(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 (!csr_roam_is_sta_mode(pMac, session_id)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Wrong Mode %d", + session->connectedProfile.BSSType); + return; + } + ngbr_roam_info->uOsRequestedHandoff = 0; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session->roamOffloadSynchParams.bRoamSynchInProgress) { + if (pMac->roam.pReassocResp != NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + "Free Reassoc Rsp"); + cdf_mem_free(pMac->roam.pReassocResp); + pMac->roam.pReassocResp = NULL; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR3:Send SynchCnf auth, authenticated"); + csr_roam_offload_send_synch_cnf(pMac, session_id); + } else +#endif + csr_roam_offload_scan(pMac, session_id, + ROAM_SCAN_OFFLOAD_START, + REASON_CONNECT); + } +#endif +} + +/** + * csr_neighbor_roam_indicate_connect() + * @pMac: mac context + * @session_id: Session Id + * @cdf_status: CDF status + * + * 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 + * + * Return: CDF status + */ +CDF_STATUS csr_neighbor_roam_indicate_connect( + tpAniSirGlobal pMac, uint8_t session_id, + CDF_STATUS cdf_status) +{ + tpCsrNeighborRoamControlInfo ngbr_roam_info = + &pMac->roam.neighborRoamInfo[session_id]; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tCsrRoamInfo roamInfo; + tCsrRoamSession *session = &pMac->roam.roamSession[session_id]; + tpSirSetActiveModeSetBncFilterReq msg; +#endif + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* if session id invalid then we need return failure */ + if (NULL == ngbr_roam_info || !CSR_IS_SESSION_VALID(pMac, session_id) + || (NULL == pMac->roam.roamSession[session_id].pCurRoamProfile)) { + return CDF_STATUS_E_FAILURE; + } + + sms_log(pMac, LOG2, + FL("Connect ind. received with session id %d in state %s"), + session_id, mac_trace_get_neighbour_roam_state( + ngbr_roam_info->neighborRoamState)); + + /* Bail out if this is NOT a STA persona */ + if (pMac->roam.roamSession[session_id].pCurRoamProfile->csrPersona != + CDF_STA_MODE) { + sms_log(pMac, LOGE, + FL("Ignoring Connect ind received from a non STA." + "session_id: %d, csrPersonna %d"), session_id, + (int)session->pCurRoamProfile->csrPersona); + return CDF_STATUS_SUCCESS; + } + /* if a concurrent session is running */ + if ((false == + CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac)) && + (csr_is_concurrent_session_running(pMac))) { + sms_log(pMac, LOGE, + FL("Ignoring Connect ind. received in multisession %d"), + csr_is_concurrent_session_running(pMac)); + return CDF_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (session->roamOffloadSynchParams.bRoamSynchInProgress && + (eSIR_ROAM_AUTH_STATUS_AUTHENTICATED == + session->roamOffloadSynchParams.authStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "LFR3:csr_neighbor_roam_indicate_connect"); + msg = cdf_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq)); + if (msg == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "LFR3:Mem Alloc failed for beacon Filter Req"); + return CDF_STATUS_E_NOMEM; + } + msg->messageType = eWNI_SME_SET_BCN_FILTER_REQ; + msg->length = sizeof(uint8_t); + msg->seesionId = session_id; + status = cds_send_mb_message_to_mac(msg); + cdf_copy_macaddr(&roamInfo.peerMac, + &session->connectedProfile.bssid); + roamInfo.roamSynchInProgress = + session->roamOffloadSynchParams.bRoamSynchInProgress; + csr_roam_call_callback(pMac, session_id, &roamInfo, 0, + eCSR_ROAM_SET_KEY_COMPLETE, + eCSR_ROAM_RESULT_AUTHENTICATED); + } +#endif + + switch (ngbr_roam_info->neighborRoamState) { + case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: + if (CDF_STATUS_SUCCESS != cdf_status) { + /** + * Just transition the state to INIT state.Rest of the + * clean up happens when we get next connect indication + */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION( + pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, + session_id) + ngbr_roam_info->roamChannelInfo.IAPPNeighborListReceived = + false; + break; + } + /* Fall through if the status is SUCCESS */ + case eCSR_NEIGHBOR_ROAM_STATE_INIT: + /* Reset all the data structures here */ + csr_neighbor_roam_reset_init_state_control_info(pMac, + session_id); + csr_neighbor_roam_info_ctx_init(pMac, session_id); + break; + default: + sms_log(pMac, LOGE, + FL("Connect evt received in invalid state %s Ignoring"), + mac_trace_get_neighbour_roam_state( + ngbr_roam_info->neighborRoamState)); + break; + } + return status; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_purge_preauth_failed_list + + \brief This function purges all the MAC addresses in the pre-auth fail list + + \param pMac - The handle returned by mac_open. + + \return VOID + + ---------------------------------------------------------------------------*/ +void csr_neighbor_roam_purge_preauth_failed_list(tpAniSirGlobal pMac) +{ + uint8_t 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++) { + cdf_mem_zero(pNeighborRoamInfo->FTRoamInfo. + preAuthFailList.macAddress[i], + sizeof(tSirMacAddr)); + } + pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress = 0; + } +} + +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_init11r_assoc_info + + \brief This function initializes 11r related neighbor roam data structures + + \param pMac - The handle returned by mac_open. + + \return CDF_STATUS_SUCCESS on success, corresponding error code otherwise + + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_neighbor_roam_init11r_assoc_info(tpAniSirGlobal pMac) +{ + CDF_STATUS status; + uint8_t 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 = 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 = false; + pFTRoamInfo->preauthRspPending = false; + + pFTRoamInfo->currentNeighborRptRetryNum = 0; + pFTRoamInfo->numBssFromNeighborReport = 0; + + cdf_mem_zero(pFTRoamInfo->neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * + MAX_BSS_IN_NEIGHBOR_RPT); + + status = csr_ll_open(pMac->hHdd, &pFTRoamInfo->preAuthDoneList); + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, + FL("LL Open of preauth done AP List failed")); + return CDF_STATUS_E_RESOURCES; + } + } + return status; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_init + + \brief This function initializes neighbor roam data structures + + \param pMac - The handle returned by mac_open. + + \return CDF_STATUS_SUCCESS on success, corresponding error code otherwise + + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_neighbor_roam_init(tpAniSirGlobal pMac, uint8_t sessionId) +{ + CDF_STATUS 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.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; + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = + cdf_mem_malloc(pMac->roam.configParam.neighborRoamConfig. + neighborScanChanList.numChannels); + + if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + sms_log(pMac, LOGE, + FL("Memory Allocation for CFG Channel List failed")); + return CDF_STATUS_E_NOMEM; + } + + /* Update the roam global structure from CFG */ + cdf_mem_copy(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList, + pMac->roam.configParam.neighborRoamConfig. + neighborScanChanList.channelList, + pMac->roam.configParam.neighborRoamConfig. + neighborScanChanList.numChannels); + 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; + + cdf_zero_macaddr(&pNeighborRoamInfo->currAPbssid); + 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 + cdf_mem_set(&pNeighborRoamInfo->prevConnProfile, + sizeof(tCsrRoamConnectedProfile), 0); +#endif + + status = csr_ll_open(pMac->hHdd, &pNeighborRoamInfo->roamableAPList); + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, FL("LL Open of roam able AP List failed")); + cdf_mem_free(pNeighborRoamInfo->cfgParams.channelInfo. + ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + return CDF_STATUS_E_RESOURCES; + } + + pNeighborRoamInfo->roamChannelInfo.currentChanIndex = + CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + numOfChannels = 0; + pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = + NULL; + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = false; + +#ifdef WLAN_FEATURE_VOWIFI_11R + status = csr_neighbor_roam_init11r_assoc_info(pMac); + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, FL("LL Open of roam able AP List failed")); + cdf_mem_free(pNeighborRoamInfo->cfgParams.channelInfo. + ChannelList); + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + csr_ll_close(&pNeighborRoamInfo->roamableAPList); + return CDF_STATUS_E_RESOURCES; + } +#endif + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = false; + /* Set the Last Sent Cmd as RSO_STOP */ + pNeighborRoamInfo->last_sent_cmd = ROAM_SCAN_OFFLOAD_STOP; + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_close + + \brief This function closes/frees all the neighbor roam data structures + + \param pMac - The handle returned by mac_open. + \param sessionId - Session identifier + \return VOID + + ---------------------------------------------------------------------------*/ +void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + + if (eCSR_NEIGHBOR_ROAM_STATE_CLOSED == + pNeighborRoamInfo->neighborRoamState) { + sms_log(pMac, LOGW, + FL("Neighbor Roam Algorithm Already Closed")); + return; + } + + if (pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + cdf_mem_free(pNeighborRoamInfo->cfgParams.channelInfo. + ChannelList); + + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + + /* Should free up the nodes in the list before closing the double Linked list */ + csr_neighbor_roam_free_roamable_bss_list(pMac, + &pNeighborRoamInfo->roamableAPList); + csr_ll_close(&pNeighborRoamInfo->roamableAPList); + + if (pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo. + ChannelList) { + cdf_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.IAPPNeighborListReceived = false; + + /* Free the profile.. */ + csr_release_profile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile); +#ifdef FEATURE_WLAN_LFR + csr_roam_free_connect_profile(pMac, &pNeighborRoamInfo->prevConnProfile); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; + pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; + cdf_mem_zero(pNeighborRoamInfo->FTRoamInfo.neighboReportBssInfo, + sizeof(tCsrNeighborReportBssInfo) * + MAX_BSS_IN_NEIGHBOR_RPT); + csr_neighbor_roam_free_roamable_bss_list(pMac, + &pNeighborRoamInfo->FTRoamInfo. + preAuthDoneList); + csr_ll_close(&pNeighborRoamInfo->FTRoamInfo.preAuthDoneList); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(pMac, + eCSR_NEIGHBOR_ROAM_STATE_CLOSED, sessionId) + + return; +} + +/** + * csr_neighbor_roam_request_handoff() - Handoff to a different AP + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * + * 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 + * + * Return: none + */ +void csr_neighbor_roam_request_handoff(tpAniSirGlobal mac_ctx, + uint8_t session_id) +{ + tCsrRoamInfo roam_info; + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + tCsrNeighborRoamBSSInfo handoff_node; + uint32_t roamid = 0; + CDF_STATUS status; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, "%s session_id=%d", + __func__, session_id); + + if (neighbor_roam_info->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) { + sms_log(mac_ctx, LOGE, + FL("Roam requested when Neighbor roam is in %s state"), + mac_trace_get_neighbour_roam_state( + neighbor_roam_info->neighborRoamState)); + return; + } + + if (false == csr_neighbor_roam_get_handoff_ap_info(mac_ctx, + &handoff_node, session_id)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("failed to obtain handoff AP")); + return; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("HANDOFF CANDIDATE BSSID "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(handoff_node.pBssDescription->bssId)); + + cdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo)); + csr_roam_call_callback(mac_ctx, session_id, &roam_info, roamid, + eCSR_ROAM_FT_START, eSIR_SME_SUCCESS); + + cdf_mem_zero(&roam_info, sizeof(tCsrRoamInfo)); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION + (mac_ctx, eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING, session_id) + + csr_neighbor_roam_send_lfr_metric_event(mac_ctx, session_id, + handoff_node.pBssDescription->bssId, + eCSR_ROAM_HANDOVER_SUCCESS); + /* Free the profile.. Just to make sure we dont leak memory here */ + csr_release_profile(mac_ctx, + &neighbor_roam_info->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 = csr_roam_copy_connected_profile(mac_ctx, session_id, + &neighbor_roam_info->csrNeighborRoamProfile); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("csr_roam_copy_connected_profile failed %d"), + status); + return; + } + cdf_mem_copy(neighbor_roam_info->csrNeighborRoamProfile.BSSIDs.bssid, + handoff_node.pBssDescription->bssId, sizeof(tSirMacAddr)); + neighbor_roam_info->csrNeighborRoamProfile.ChannelInfo.ChannelList[0] = + handoff_node.pBssDescription->channelId; + + NEIGHBOR_ROAM_DEBUG(mac_ctx, LOGW, + " csr_roamHandoffRequested: disassociating with current AP"); + + if (!CDF_IS_STATUS_SUCCESS + (csr_roam_issue_disassociate_cmd + (mac_ctx, session_id, + eCSR_DISCONNECT_REASON_HANDOFF))) { + sms_log(mac_ctx, LOGW, + "csr_roamHandoffRequested: fail to issue disassociate"); + return; + } + /* notify HDD for handoff, providing the BSSID too */ + roam_info.reasonCode = eCsrRoamReasonBetterAP; + + cdf_mem_copy(roam_info.bssid.bytes, + handoff_node.pBssDescription->bssId, + sizeof(struct cdf_mac_addr)); + + csr_roam_call_callback(mac_ctx, session_id, &roam_info, 0, + eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE); + + return; +} + +/** + * csr_neighbor_roam_is_handoff_in_progress() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * + * This function returns whether handoff is in progress or not based on + * the current neighbor roam state + * + * Return: true if reassoc in progress, false otherwise + */ +bool csr_neighbor_roam_is_handoff_in_progress(tpAniSirGlobal pMac, uint8_t sessionId) +{ + if (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING == + pMac->roam.neighborRoamInfo[sessionId].neighborRoamState) + return true; + + return false; +} + +#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(WLAN_FEATURE_NEIGHBOR_ROAMING) +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_is11r_assoc + + \brief This function returns whether the current association is a 11r assoc or not + + \param pMac - The handle returned by mac_open. + + \return true if current assoc is 11r, false otherwise + + ---------------------------------------------------------------------------*/ +bool csr_neighbor_roam_is11r_assoc(tpAniSirGlobal pMac, uint8_t sessionId) +{ + return pMac->roam.neighborRoamInfo[sessionId].is11rAssoc; +} +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/** + * csr_neighbor_roam_get_handoff_ap_info - Identifies the best AP for roaming + * + * @pMac: mac context + * @session_id: Session Id + * @hand_off_node: AP node that is the handoff candidate returned + * + * 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 roamable AP list + * + * Return: true if able find handoff AP, false otherwise + */ + +bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo hand_off_node, + uint8_t session_id) +{ + tpCsrNeighborRoamControlInfo ngbr_roam_info = + &pMac->roam.neighborRoamInfo[session_id]; + tpCsrNeighborRoamBSSInfo bss_node = NULL; + + if (NULL == hand_off_node) { + CDF_ASSERT(NULL != hand_off_node); + return false; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (ngbr_roam_info->is11rAssoc) { + /* Always the BSS info in the head is the handoff candidate */ + bss_node = csr_neighbor_roam_next_roamable_ap( + pMac, + &ngbr_roam_info->FTRoamInfo.preAuthDoneList, + NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csr_ll_count(& + ngbr_roam_info->FTRoamInfo.preAuthDoneList)); + } else +#endif +#ifdef FEATURE_WLAN_ESE + if (ngbr_roam_info->isESEAssoc) { + /* Always the BSS info in the head is the handoff candidate */ + bss_node = + csr_neighbor_roam_next_roamable_ap(pMac, + &ngbr_roam_info->FTRoamInfo.preAuthDoneList, + NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csr_ll_count(&ngbr_roam_info->FTRoamInfo. + preAuthDoneList)); + } else +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(pMac, session_id)) { + /* Always the BSS info in the head is the handoff candidate */ + bss_node = + csr_neighbor_roam_next_roamable_ap(pMac, + &ngbr_roam_info->FTRoamInfo.preAuthDoneList, + NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csr_ll_count( + &ngbr_roam_info->FTRoamInfo.preAuthDoneList)); + } else +#endif + { + bss_node = + csr_neighbor_roam_next_roamable_ap(pMac, + &ngbr_roam_info->roamableAPList, + NULL); + NEIGHBOR_ROAM_DEBUG(pMac, LOG1, + FL("Number of Handoff candidates = %d"), + csr_ll_count(&ngbr_roam_info->roamableAPList)); + } + if (NULL == bss_node) + return false; + cdf_mem_copy(hand_off_node, bss_node, sizeof(tCsrNeighborRoamBSSInfo)); + return true; +} + +/* --------------------------------------------------------------------------- + \brief This function returns true if preauth is completed + + \param pMac - The handle returned by mac_open. + + \return bool + + ---------------------------------------------------------------------------*/ +bool csr_neighbor_roam_state_preauth_done(tpAniSirGlobal pMac, uint8_t 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 mac_open. + + \return bool + ---------------------------------------------------------------------------*/ +void csr_neighbor_roam_tranistion_preauth_done_to_disconnected(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + tCsrRoamSession *session = CSR_GET_SESSION(pMac, sessionId); + + if (!session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("session is NULL")); + return; + } + + if (pNeighborRoamInfo->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE) + return; + + /* Stop timer */ + cdf_mc_timer_stop(&session->ftSmeContext.preAuthReassocIntvlTimer); + + /* Transition to init state */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(pMac, eCSR_NEIGHBOR_ROAM_STATE_INIT, + sessionId) + pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = false; +} + +/* --------------------------------------------------------------------------- + \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 bool + + ---------------------------------------------------------------------------*/ +bool csr_neighbor_middle_of_roaming(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + bool val = (eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING == + pNeighborRoamInfo->neighborRoamState) || + (eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE == + pNeighborRoamInfo->neighborRoamState); + return val; +} + +/** + * csr_neighbor_roam_candidate_found_ind_hdlr() + * + * @mac_ctx: Pointer to Global MAC structure + * @msg_buf: pointer to msg buff + * + * This function is called by CSR as soon as TL posts the candidate + * found indication to SME via MC thread + * + * Return: CDF_STATUS_SUCCESS on success, corresponding error code otherwise + */ +CDF_STATUS csr_neighbor_roam_candidate_found_ind_hdlr(tpAniSirGlobal pMac, void *pMsg) +{ + tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd = + (tSirSmeCandidateFoundInd *) pMsg; + uint32_t sessionId = pSirSmeCandidateFoundInd->sessionId; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + sms_log(pMac, LOG1, FL("Received indication from firmware")); + + /* we must be in connected state, if not ignore it */ + if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != + pNeighborRoamInfo->neighborRoamState) + || (pNeighborRoamInfo->uOsRequestedHandoff)) { + sms_log(pMac, LOGE, + FL + ("Received in not CONNECTED state OR uOsRequestedHandoff is set. Ignore it")); + status = CDF_STATUS_E_FAILURE; + } else { + /* Firmware indicated that roaming candidate is found. Beacons + * are already in the SME scan results table. + * Process the results for choosing best roaming candidate. + */ + csr_save_scan_results(pMac, eCsrScanCandidateFound, + sessionId); + /* Future enhancements: + * If firmware tags candidate beacons, give them preference + * for roaming. + * Age out older entries so that new candidate beacons + * will get preference. + */ + status = csr_neighbor_roam_process_scan_complete(pMac, + sessionId); + if (CDF_STATUS_SUCCESS != status) { + sms_log(pMac, LOGE, + FL("Neighbor scan process complete failed with status %d"), + status); + return CDF_STATUS_E_FAILURE; + } + } + + return status; +} + +/** + * csr_neighbor_roam_process_handoff_req - Processes handoff request + * + * @mac_ctx Pointer to mac context + * @session_id SME session id + * + * This function is called start with the handoff process. First do a + * SSID scan for the BSSID provided. + * + * Return: status + */ +CDF_STATUS csr_neighbor_roam_process_handoff_req( + tpAniSirGlobal mac_ctx, + uint8_t session_id) +{ + tpCsrNeighborRoamControlInfo roam_ctrl_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t roam_id; + tCsrRoamProfile *profile = NULL; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + uint8_t i = 0; + + if (NULL == session) { + sms_log(mac_ctx, LOGE, FL("session is NULL ")); + return CDF_STATUS_E_FAILURE; + } + + roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam); + profile = cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (NULL == profile) { + sms_log(mac_ctx, LOGE, FL("Memory alloc failed")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set(profile, sizeof(tCsrRoamProfile), 0); + status = + csr_roam_copy_profile(mac_ctx, profile, + session->pCurRoamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("Profile copy failed")); + goto end; + } + /* Add the BSSID & Channel */ + profile->BSSIDs.numOfBSSIDs = 1; + if (NULL == profile->BSSIDs.bssid) { + profile->BSSIDs.bssid = + cdf_mem_malloc(sizeof(tSirMacAddr) * + profile->BSSIDs.numOfBSSIDs); + if (NULL == profile->BSSIDs.bssid) { + sms_log(mac_ctx, LOGE, FL("mem alloc failed for BSSID")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + } + + cdf_mem_zero(profile->BSSIDs.bssid, + sizeof(tSirMacAddr) * + profile->BSSIDs.numOfBSSIDs); + + /* Populate the BSSID from handoff info received from HDD */ + for (i = 0; i < profile->BSSIDs.numOfBSSIDs; i++) { + cdf_copy_macaddr(&profile->BSSIDs.bssid[i], + &roam_ctrl_info->handoffReqInfo.bssid); + } + + profile->ChannelInfo.numOfChannels = 1; + if (NULL == profile->ChannelInfo.ChannelList) { + profile->ChannelInfo.ChannelList = + cdf_mem_malloc(sizeof(*profile-> + ChannelInfo.ChannelList) * + profile->ChannelInfo.numOfChannels); + if (NULL == profile->ChannelInfo.ChannelList) { + sms_log(mac_ctx, LOGE, + FL("mem alloc failed for ChannelList")); + status = CDF_STATUS_E_NOMEM; + goto end; + } + } + profile->ChannelInfo.ChannelList[0] = + roam_ctrl_info->handoffReqInfo.channel; + + /* do a SSID scan */ + status = + csr_scan_for_ssid(mac_ctx, session_id, profile, roam_id, false); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("SSID scan failed")); + } + +end: + if (NULL != profile) { + csr_release_profile(mac_ctx, profile); + cdf_mem_free(profile); + } + + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_sssid_scan_done + + \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 handoff process + + \param pMac - The handle returned by mac_open. + + \return CDF_STATUS_SUCCESS on success, corresponding error code otherwise + + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_neighbor_roam_sssid_scan_done(tpAniSirGlobal pMac, + uint8_t sessionId, CDF_STATUS status) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + CDF_STATUS hstatus; + + sms_log(pMac, LOGE, FL("called ")); + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != + pNeighborRoamInfo->neighborRoamState) { + sms_log(pMac, LOGE, + FL("Received in not CONNECTED state. Ignore it")); + return CDF_STATUS_E_FAILURE; + } + /* if SSID scan failed to find our candidate add an entry to csr scan cache ourself */ + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Add an entry to csr scan cache")); + hstatus = csr_scan_create_entry_in_scan_cache(pMac, sessionId, + pNeighborRoamInfo-> + handoffReqInfo.bssid, + pNeighborRoamInfo-> + handoffReqInfo.channel); + if (CDF_STATUS_SUCCESS != hstatus) { + sms_log(pMac, LOGE, + FL + ("csr_scan_create_entry_in_scan_cache failed with status %d"), + hstatus); + return CDF_STATUS_E_FAILURE; + } + } + + /* Now we have completed scanning for the candidate provided by HDD. Let move on to HO */ + hstatus = csr_neighbor_roam_process_scan_complete(pMac, sessionId); + + if (CDF_STATUS_SUCCESS != hstatus) { + sms_log(pMac, LOGE, + FL + ("Neighbor scan process complete failed with status %d"), + hstatus); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + + +/** + * csr_neighbor_roam_handoff_req_hdlr - Processes handoff request + * @mac_ctx Pointer to mac context + * @msg message sent to HDD + * + * This function is called by CSR as soon as it gets a handoff request + * to SME via MC thread + * + * Return: status + */ +CDF_STATUS csr_neighbor_roam_handoff_req_hdlr( + tpAniSirGlobal mac_ctx, void *msg) +{ + tAniHandoffReq *handoff_req = (tAniHandoffReq *) msg; + uint32_t session_id = handoff_req->sessionId; + tpCsrNeighborRoamControlInfo roam_ctrl_info = + &mac_ctx->roam.neighborRoamInfo[session_id]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != + roam_ctrl_info->neighborRoamState) { + sms_log(mac_ctx, LOGE, + FL("Received in not CONNECTED state. Ignore it")); + return CDF_STATUS_E_FAILURE; + } + + /* save the handoff info came from HDD as part of the reassoc req */ + handoff_req = (tAniHandoffReq *) msg; + if (NULL == handoff_req) { + sms_log(mac_ctx, LOGE, FL("Received msg is NULL")); + return CDF_STATUS_E_FAILURE; + } + + /* sanity check */ + if (true == cdf_mem_compare(handoff_req->bssid, + roam_ctrl_info->currAPbssid.bytes, + sizeof(tSirMacAddr))) { + sms_log(mac_ctx, LOGE, + FL + ("Received req has same BSSID as current AP!!")); + return CDF_STATUS_E_FAILURE; + } + roam_ctrl_info->handoffReqInfo.channel = + handoff_req->channel; + roam_ctrl_info->handoffReqInfo.src = + handoff_req->handoff_src; + cdf_mem_copy(&roam_ctrl_info->handoffReqInfo.bssid.bytes, + &handoff_req->bssid, CDF_MAC_ADDR_SIZE); + roam_ctrl_info->uOsRequestedHandoff = 1; + status = csr_roam_offload_scan(mac_ctx, session_id, + ROAM_SCAN_OFFLOAD_STOP, + REASON_OS_REQUESTED_ROAMING_NOW); + if (CDF_STATUS_SUCCESS != status) { + sms_log(mac_ctx, LOGE, + FL("csr_roam_offload_scan failed")); + roam_ctrl_info->uOsRequestedHandoff = 0; + } + return status; +} + +/** + * csr_neighbor_roam_proceed_with_handoff_req() + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: Session ID + * + * 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 + * + * Return: CDF_STATUS_SUCCESS on success, corresponding error code otherwise + */ +CDF_STATUS csr_neighbor_roam_proceed_with_handoff_req(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = + &pMac->roam.neighborRoamInfo[sessionId]; + CDF_STATUS status = CDF_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if ((eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != + pNeighborRoamInfo->neighborRoamState) + || (!pNeighborRoamInfo->uOsRequestedHandoff)) { + sms_log(pMac, LOGE, + FL + ("Received in not CONNECTED state or uOsRequestedHandoff is not set. Ignore it")); + status = CDF_STATUS_E_FAILURE; + } else { + /* Let's go ahead with handoff */ + status = csr_neighbor_roam_process_handoff_req(pMac, sessionId); + } + if (!CDF_IS_STATUS_SUCCESS(status)) { + pNeighborRoamInfo->uOsRequestedHandoff = 0; + } + return status; +} + +/* --------------------------------------------------------------------------- + + \fn csr_neighbor_roam_start_lfr_scan + + \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 mac_open. + + \return CDF_STATUS_SUCCESS on success, corresponding error code otherwise + + ---------------------------------------------------------------------------*/ +CDF_STATUS csr_neighbor_roam_start_lfr_scan(tpAniSirGlobal pMac, uint8_t 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 */ + csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c new file mode 100644 index 000000000000..30fadcd205cd --- /dev/null +++ b/core/sme/src/csr/csr_tdls_process.c @@ -0,0 +1,820 @@ +/* + * 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 csr_tdls_process.c + + Implementation for the TDLS interface to PE. + ========================================================================== */ + +#ifdef FEATURE_WLAN_TDLS + +#include "ani_global.h" /* for tpAniSirGlobal */ +#include "cds_mq.h" +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "sms_debug.h" + +#include "csr_support.h" + +#include "host_diag_core_log.h" +#include "host_diag_core_event.h" +#include "csr_internal.h" + +/* + * common routine to remove TDLS cmd from SME command list.. + * commands are removed after getting reponse from PE. + */ +CDF_STATUS csr_tdls_remove_sme_cmd(tpAniSirGlobal pMac, eSmeCommandType cmdType) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tListElem *pEntry; + tSmeCmd *pCommand; + + pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (cmdType == pCommand->command) { + if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList, + pEntry, LL_ACCESS_LOCK)) { + cdf_mem_zero(&pCommand->u.tdlsCmd, + sizeof(tTdlsCmd)); + csr_release_command(pMac, pCommand); + sme_process_pending_queue(pMac); + status = CDF_STATUS_SUCCESS; + } + } + } + return status; +} + +/** + * csr_tdls_send_mgmt_req() - to send a TDLS frame to PE through SME + * @hHal: HAL context + * @sessionId: SME session id + * @tdlsSendMgmt: tdls mgmt pointer + * + * TDLS request API, called from HDD to send a TDLS frame in SME/CSR and + * send message to PE to trigger TDLS discovery procedure. + */ +CDF_STATUS csr_tdls_send_mgmt_req(tHalHandle hHal, uint8_t sessionId, + tCsrTdlsSendMgmt *tdlsSendMgmt) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *tdlsSendMgmtCmd; + tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + /* If connected and in Infra. Only then allow this */ + if (!CSR_IS_SESSION_VALID(pMac, sessionId) || + !csr_is_conn_state_connected_infra(pMac, sessionId) || + (NULL == tdlsSendMgmt)) + return status; + tdlsSendMgmtCmd = csr_get_command_buffer(pMac); + if (!tdlsSendMgmtCmd) + return status; + 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; + cdf_mem_copy(tdlsSendMgmtCmdInfo->peerMac, tdlsSendMgmt->peerMac, + sizeof(tSirMacAddr)); + + if ((0 != tdlsSendMgmt->len) && (NULL != tdlsSendMgmt->buf)) { + tdlsSendMgmtCmdInfo->buf = cdf_mem_malloc(tdlsSendMgmt->len); + if (NULL == tdlsSendMgmtCmdInfo->buf) { + status = CDF_STATUS_E_NOMEM; + sms_log(pMac, LOGE, FL("Alloc Failed")); + CDF_ASSERT(0); + return status; + } + cdf_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); + sme_push_command(pMac, tdlsSendMgmtCmd, false); + status = CDF_STATUS_SUCCESS; + return status; +} + +/* + * TDLS request API, called from HDD to add a TDLS peer + */ +CDF_STATUS csr_tdls_change_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrStaParams *pstaParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *tdlsAddStaCmd; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + /* If connected and in Infra. Only then allow this */ + if (CSR_IS_SESSION_VALID(pMac, sessionId) && + csr_is_conn_state_connected_infra(pMac, sessionId) && + (NULL != peerMac) && (NULL != pstaParams)) { + + tdlsAddStaCmd = csr_get_command_buffer(pMac); + + if (tdlsAddStaCmd) { + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = + &tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo; + + tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_UPDATE; + + tdlsAddStaCmd->sessionId = sessionId; + + cdf_mem_copy(tdlsAddStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)); + tdlsAddStaCmdInfo->capability = pstaParams->capability; + tdlsAddStaCmdInfo->uapsdQueues = + pstaParams->uapsd_queues; + tdlsAddStaCmdInfo->maxSp = pstaParams->max_sp; + cdf_mem_copy(tdlsAddStaCmdInfo->extnCapability, + pstaParams->extn_capability, + sizeof(pstaParams->extn_capability)); + + tdlsAddStaCmdInfo->htcap_present = + pstaParams->htcap_present; + if (pstaParams->htcap_present) + cdf_mem_copy(&tdlsAddStaCmdInfo->HTCap, + &pstaParams->HTCap, + sizeof(pstaParams->HTCap)); + else + cdf_mem_set(&tdlsAddStaCmdInfo->HTCap, + sizeof(pstaParams->HTCap), 0); + + tdlsAddStaCmdInfo->vhtcap_present = + pstaParams->vhtcap_present; + if (pstaParams->vhtcap_present) + cdf_mem_copy(&tdlsAddStaCmdInfo->VHTCap, + &pstaParams->VHTCap, + sizeof(pstaParams->VHTCap)); + else + cdf_mem_set(&tdlsAddStaCmdInfo->VHTCap, + sizeof(pstaParams->VHTCap), 0); + + tdlsAddStaCmdInfo->supportedRatesLen = + pstaParams->supported_rates_len; + + if (0 != pstaParams->supported_rates_len) + cdf_mem_copy(&tdlsAddStaCmdInfo->supportedRates, + pstaParams->supported_rates, + pstaParams->supported_rates_len); + + tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer; + tdlsAddStaCmd->u.tdlsCmd.size = + sizeof(tTdlsAddStaCmdInfo); + sme_push_command(pMac, tdlsAddStaCmd, false); + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/* + * TDLS request API, called from HDD to Send Link Establishment Parameters + */ +CDF_STATUS csr_tdls_send_link_establish_params(tHalHandle hHal, + uint8_t sessionId, + const tSirMacAddr peerMac, + tCsrTdlsLinkEstablishParams * + tdlsLinkEstablishParams) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *tdlsLinkEstablishCmd; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + /* If connected and in Infra. Only then allow this */ + if (CSR_IS_SESSION_VALID(pMac, sessionId) && + csr_is_conn_state_connected_infra(pMac, sessionId) && + (NULL != peerMac)) { + tdlsLinkEstablishCmd = csr_get_command_buffer(pMac); + + if (tdlsLinkEstablishCmd) { + tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo = + &tdlsLinkEstablishCmd->u.tdlsCmd.u. + tdlsLinkEstablishCmdInfo; + + tdlsLinkEstablishCmd->sessionId = sessionId; + + cdf_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; + cdf_mem_copy(tdlsLinkEstablishCmdInfo-> + supportedChannels, + tdlsLinkEstablishParams->supportedChannels, + tdlsLinkEstablishParams-> + supportedChannelsLen); + tdlsLinkEstablishCmdInfo->supportedChannelsLen = + tdlsLinkEstablishParams->supportedChannelsLen; + cdf_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); + sme_push_command(pMac, tdlsLinkEstablishCmd, false); + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/* + * TDLS request API, called from HDD to add a TDLS peer + */ +CDF_STATUS csr_tdls_add_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *tdlsAddStaCmd; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + /* If connected and in Infra. Only then allow this */ + if (CSR_IS_SESSION_VALID(pMac, sessionId) && + csr_is_conn_state_connected_infra(pMac, sessionId) && + (NULL != peerMac)) { + tdlsAddStaCmd = csr_get_command_buffer(pMac); + + if (tdlsAddStaCmd) { + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = + &tdlsAddStaCmd->u.tdlsCmd.u.tdlsAddStaCmdInfo; + + tdlsAddStaCmd->sessionId = sessionId; + tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_ADD; + + cdf_mem_copy(tdlsAddStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)); + + tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer; + tdlsAddStaCmd->u.tdlsCmd.size = + sizeof(tTdlsAddStaCmdInfo); + sme_push_command(pMac, tdlsAddStaCmd, false); + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/* + * TDLS request API, called from HDD to delete a TDLS peer + */ +CDF_STATUS csr_tdls_del_peer_sta(tHalHandle hHal, uint8_t sessionId, + const tSirMacAddr peerMac) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *tdlsDelStaCmd; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + /* If connected and in Infra. Only then allow this */ + if (CSR_IS_SESSION_VALID(pMac, sessionId) && + csr_is_conn_state_connected_infra(pMac, sessionId) && + (NULL != peerMac)) { + tdlsDelStaCmd = csr_get_command_buffer(pMac); + + if (tdlsDelStaCmd) { + tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo = + &tdlsDelStaCmd->u.tdlsCmd.u.tdlsDelStaCmdInfo; + + tdlsDelStaCmd->sessionId = sessionId; + + cdf_mem_copy(tdlsDelStaCmdInfo->peerMac, + peerMac, sizeof(tSirMacAddr)); + + tdlsDelStaCmd->command = eSmeCommandTdlsDelPeer; + tdlsDelStaCmd->u.tdlsCmd.size = + sizeof(tTdlsDelStaCmdInfo); + sme_push_command(pMac, tdlsDelStaCmd, false); + status = CDF_STATUS_SUCCESS; + } + } + + return status; +} + +/* + * TDLS messages sent to PE . + */ +CDF_STATUS tdls_send_message(tpAniSirGlobal pMac, uint16_t msg_type, + void *msg_data, uint32_t msg_size) +{ + + tSirMbMsg *pMsg = (tSirMbMsg *) msg_data; + pMsg->type = msg_type; + pMsg->msgLen = (uint16_t) (msg_size); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + ("sending msg = %d"), pMsg->type); + /* Send message. */ + if (cds_send_mb_message_to_mac(pMsg) != CDF_STATUS_SUCCESS) { + sms_log(pMac, LOGE, FL("Cannot send message")); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_tdls_process_send_mgmt(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + tTdlsSendMgmtCmdInfo *tdlsSendMgmtCmdInfo = + &cmd->u.tdlsCmd.u.tdlsSendMgmtCmdInfo; + tSirTdlsSendMgmtReq *tdlsSendMgmtReq = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + if (NULL == pSession->pConnectBssDesc) { + sms_log(pMac, LOGE, FL("BSS Description is not present")); + return CDF_STATUS_E_FAILURE; + } + + tdlsSendMgmtReq = + cdf_mem_malloc(sizeof(tSirTdlsSendMgmtReq) + + tdlsSendMgmtCmdInfo->len); + if (NULL == tdlsSendMgmtReq) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("alloc failed")); + CDF_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; + + cdf_mem_copy(tdlsSendMgmtReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + + cdf_mem_copy(tdlsSendMgmtReq->peerMac, + tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr)); + + if (tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) { + cdf_mem_copy(tdlsSendMgmtReq->addIe, tdlsSendMgmtCmdInfo->buf, + tdlsSendMgmtCmdInfo->len); + + } + /* Send the request to PE. */ + sms_log(pMac, LOG1, "sending TDLS Mgmt Frame req to PE "); + status = tdls_send_message(pMac, eWNI_SME_TDLS_SEND_MGMT_REQ, + (void *)tdlsSendMgmtReq, + sizeof(tSirTdlsSendMgmtReq) + + tdlsSendMgmtCmdInfo->len); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Failed to send request to MAC")); + } + if (tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) { + /* Done with the buf. Free it. */ + cdf_mem_free(tdlsSendMgmtCmdInfo->buf); + tdlsSendMgmtCmdInfo->buf = NULL; + tdlsSendMgmtCmdInfo->len = 0; + } + + return status; +} + +CDF_STATUS csr_tdls_process_add_sta(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + tTdlsAddStaCmdInfo *tdlsAddStaCmdInfo = + &cmd->u.tdlsCmd.u.tdlsAddStaCmdInfo; + tSirTdlsAddStaReq *tdlsAddStaReq = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) { + sms_log(pMac, LOGE, FL("BSS description is not present")); + return CDF_STATUS_E_FAILURE; + } + + tdlsAddStaReq = cdf_mem_malloc(sizeof(tSirTdlsAddStaReq)); + if (NULL == tdlsAddStaReq) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("alloc failed")); + CDF_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; + + cdf_mem_copy(tdlsAddStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + + cdf_mem_copy(tdlsAddStaReq->peerMac, + tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr)); + + tdlsAddStaReq->capability = tdlsAddStaCmdInfo->capability; + tdlsAddStaReq->uapsd_queues = tdlsAddStaCmdInfo->uapsdQueues; + tdlsAddStaReq->max_sp = tdlsAddStaCmdInfo->maxSp; + + cdf_mem_copy(tdlsAddStaReq->extn_capability, + tdlsAddStaCmdInfo->extnCapability, SIR_MAC_MAX_EXTN_CAP); + tdlsAddStaReq->htcap_present = tdlsAddStaCmdInfo->htcap_present; + cdf_mem_copy(&tdlsAddStaReq->htCap, + &tdlsAddStaCmdInfo->HTCap, + sizeof(tdlsAddStaCmdInfo->HTCap)); + tdlsAddStaReq->vhtcap_present = tdlsAddStaCmdInfo->vhtcap_present; + cdf_mem_copy(&tdlsAddStaReq->vhtCap, + &tdlsAddStaCmdInfo->VHTCap, + sizeof(tdlsAddStaCmdInfo->VHTCap)); + tdlsAddStaReq->supported_rates_length = + tdlsAddStaCmdInfo->supportedRatesLen; + cdf_mem_copy(&tdlsAddStaReq->supported_rates, + tdlsAddStaCmdInfo->supportedRates, + tdlsAddStaCmdInfo->supportedRatesLen); + + /* Send the request to PE. */ + sms_log(pMac, LOGE, "sending TDLS Add Sta req to PE "); + status = tdls_send_message(pMac, eWNI_SME_TDLS_ADD_STA_REQ, + (void *)tdlsAddStaReq, + sizeof(tSirTdlsAddStaReq)); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Failed to send request to MAC")); + } + return status; +} + +CDF_STATUS csr_tdls_process_del_sta(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + tTdlsDelStaCmdInfo *tdlsDelStaCmdInfo = + &cmd->u.tdlsCmd.u.tdlsDelStaCmdInfo; + tSirTdlsDelStaReq *tdlsDelStaReq = NULL; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId); + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) { + sms_log(pMac, LOGE, FL("BSS description is not present")); + return CDF_STATUS_E_FAILURE; + } + + tdlsDelStaReq = cdf_mem_malloc(sizeof(tSirTdlsDelStaReq)); + if (NULL == tdlsDelStaReq) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("alloc failed")); + CDF_ASSERT(0); + return status; + } + tdlsDelStaReq->sessionId = cmd->sessionId; + /* Using dialog as transactionId. This can be used to match response with request */ + tdlsDelStaReq->transactionId = 0; + + cdf_mem_copy(tdlsDelStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + + cdf_mem_copy(tdlsDelStaReq->peerMac, + tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr)); + + /* Send the request to PE. */ + sms_log(pMac, LOG1, + "sending TDLS Del Sta " MAC_ADDRESS_STR " req to PE", + MAC_ADDR_ARRAY(tdlsDelStaCmdInfo->peerMac)); + status = tdls_send_message(pMac, eWNI_SME_TDLS_DEL_STA_REQ, + (void *)tdlsDelStaReq, + sizeof(tSirTdlsDelStaReq)); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Failed to send request to MAC")); + } + return status; +} + +/* + * commands received from CSR + */ +CDF_STATUS csr_tdls_process_cmd(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + eSmeCommandType cmdType = cmd->command; + bool status = true; + switch (cmdType) { + case eSmeCommandTdlsSendMgmt: + { + status = csr_tdls_process_send_mgmt(pMac, cmd); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = false; + } + } + break; + case eSmeCommandTdlsAddPeer: + { + status = csr_tdls_process_add_sta(pMac, cmd); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = false; + } + } + break; + case eSmeCommandTdlsDelPeer: + { + status = csr_tdls_process_del_sta(pMac, cmd); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = false; + } + } + break; + case eSmeCommandTdlsLinkEstablish: + { + status = csr_tdls_process_link_establish(pMac, cmd); + if (CDF_IS_STATUS_SUCCESS(status)) { + status = false; + } + } + break; + default: + { + /* TODO: Add defualt handling */ + break; + } + + } + return status; +} + +CDF_STATUS csr_tdls_process_link_establish(tpAniSirGlobal pMac, tSmeCmd *cmd) +{ + tTdlsLinkEstablishCmdInfo *tdlsLinkEstablishCmdInfo = + &cmd->u.tdlsCmd.u.tdlsLinkEstablishCmdInfo; + tSirTdlsLinkEstablishReq *tdlsLinkEstablishReq = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, cmd->sessionId); + + if (NULL == pSession) { + sms_log(pMac, LOGE, FL("pSession is NULL")); + return CDF_STATUS_E_FAILURE; + } + + tdlsLinkEstablishReq = cdf_mem_malloc(sizeof(tSirTdlsLinkEstablishReq)); + + if (tdlsLinkEstablishReq == NULL) { + sms_log(pMac, LOGE, FL("alloc failed")); + CDF_ASSERT(0); + return CDF_STATUS_E_NOMEM; + } + tdlsLinkEstablishReq->sessionId = cmd->sessionId; + /* Using dialog as transactionId. This can be used to match response with request */ + tdlsLinkEstablishReq->transactionId = 0; + cdf_mem_copy(tdlsLinkEstablishReq->peerMac, + tdlsLinkEstablishCmdInfo->peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsLinkEstablishReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsLinkEstablishReq->supportedChannels, + tdlsLinkEstablishCmdInfo->supportedChannels, + tdlsLinkEstablishCmdInfo->supportedChannelsLen); + tdlsLinkEstablishReq->supportedChannelsLen = + tdlsLinkEstablishCmdInfo->supportedChannelsLen; + cdf_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. */ + sms_log(pMac, LOGE, "sending TDLS Link Establish Request to PE \n"); + status = tdls_send_message(pMac, eWNI_SME_TDLS_LINK_ESTABLISH_REQ, + (void *)tdlsLinkEstablishReq, + sizeof(tSirTdlsLinkEstablishReq)); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, FL("Failed to send request to MAC\n")); + } + return status; +} + +/* + * TDLS Message processor, will be called after TDLS message recieved from + * PE + */ +CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, + void *pMsgBuf) +{ + tCsrRoamInfo roamInfo = { 0 }; + eCsrRoamResult roamResult; + tSirTdlsAddStaRsp *addStaRsp = (tSirTdlsAddStaRsp *) pMsgBuf; + tSirTdlsDelStaRsp *delStaRsp = (tSirTdlsDelStaRsp *) pMsgBuf; + tpSirTdlsDelStaInd pSirTdlsDelStaInd = (tpSirTdlsDelStaInd) pMsgBuf; + tpSirTdlsDelAllPeerInd pSirTdlsDelAllPeerInd = + (tpSirTdlsDelAllPeerInd) pMsgBuf; + tpSirMgmtTxCompletionInd tdls_tx_comp_ind = + (tpSirMgmtTxCompletionInd) pMsgBuf; + tSirTdlsLinkEstablishReqRsp *linkEstablishReqRsp = + (tSirTdlsLinkEstablishReqRsp *) pMsgBuf; + tSirTdlsEventnotify *tevent = (tSirTdlsEventnotify *) pMsgBuf; + + switch (msgType) { + case eWNI_SME_TDLS_SEND_MGMT_RSP: + /* remove pending eSmeCommandTdlsDiscovery command */ + csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsSendMgmt); + break; + case eWNI_SME_TDLS_ADD_STA_RSP: + cdf_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; + csr_roam_call_callback(pMac, addStaRsp->sessionId, + &roamInfo, 0, eCSR_ROAM_TDLS_STATUS_UPDATE, + roamResult); + + /* remove pending eSmeCommandTdlsDiscovery command */ + csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsAddPeer); + break; + case eWNI_SME_TDLS_DEL_STA_RSP: + cdf_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. + */ + csr_roam_call_callback(pMac, delStaRsp->sessionId, + &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_DELETE_TDLS_PEER); + + csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsDelPeer); + break; + case eWNI_SME_TDLS_DEL_STA_IND: + cdf_mem_copy(&roamInfo.peerMac, + pSirTdlsDelStaInd->peerMac, + sizeof(tSirMacAddr)); + roamInfo.staId = pSirTdlsDelStaInd->staId; + roamInfo.reasonCode = pSirTdlsDelStaInd->reasonCode; + + /* Sending the TEARDOWN indication to HDD. */ + csr_roam_call_callback(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: + /* Sending the TEARDOWN indication to HDD. */ + csr_roam_call_callback(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: + roamInfo.reasonCode = + tdls_tx_comp_ind->txCompleteStatus; + + csr_roam_call_callback(pMac, + tdls_tx_comp_ind->sessionId, + &roamInfo, 0, + eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND, + 0); + break; + case eWNI_SME_TDLS_LINK_ESTABLISH_RSP: + csr_roam_call_callback(pMac, + linkEstablishReqRsp->sessionId, + &roamInfo, 0, + eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_LINK_ESTABLISH_REQ_RSP); + /* remove pending eSmeCommandTdlsLinkEstablish command */ + csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsLinkEstablish); + break; + case eWNI_SME_TDLS_SHOULD_DISCOVER: + cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, + 0, eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER); + break; + case eWNI_SME_TDLS_SHOULD_TEARDOWN: + cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, + 0, eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN); + break; + case eWNI_SME_TDLS_PEER_DISCONNECTED: + cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, + sizeof(tSirMacAddr)); + roamInfo.reasonCode = tevent->peer_reason; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, + 0, eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED); + break; + default: + break; + } + + return CDF_STATUS_SUCCESS; +} +#endif diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c new file mode 100644 index 000000000000..eea8cbd2fb27 --- /dev/null +++ b/core/sme/src/csr/csr_util.c @@ -0,0 +1,5626 @@ +/* + * 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 csr_util.c + + Implementation supporting routines for CSR. + ========================================================================== */ + +#include "ani_global.h" + +#include "csr_support.h" +#include "csr_inside_api.h" +#include "sms_debug.h" +#include "sme_qos_internal.h" +#include "wma_types.h" +#include "cds_utils.h" + + +uint8_t csr_wpa_oui[][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 */ +}; + +uint8_t csr_rsn_oui[][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 +uint8_t csr_wapi_oui[][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 */ +uint8_t csr_wme_info_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; +uint8_t csr_wme_parm_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; + + +/* ////////////////////////////////////////////////////////////////////// */ + +/** + * \var g_phy_rates_suppt + * + * \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 bools (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 = g_phy_rates_suppt[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 bool g_phy_rates_suppt[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_e_roam_cmd_status_str(eRoamCmdStatus val) +{ + switch (val) { + CASE_RETURN_STR(eCSR_ROAM_CANCELLED); + CASE_RETURN_STR(eCSR_ROAM_ROAMING_START); + CASE_RETURN_STR(eCSR_ROAM_ROAMING_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); + default: + return "unknown"; + } +} + +const char *get_e_csr_roam_result_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"; + } +} + +bool csr_get_bss_id_bss_desc(tHalHandle hHal, tSirBssDescription *pSirBssDesc, + struct cdf_mac_addr *pBssId) +{ + cdf_mem_copy(pBssId, &pSirBssDesc->bssId[0], + sizeof(struct cdf_mac_addr)); + return true; +} + +bool csr_is_bss_id_equal(tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + bool fEqual = false; + struct cdf_mac_addr bssId1; + struct cdf_mac_addr bssId2; + + do { + if (!pSirBssDesc1) + break; + if (!pSirBssDesc2) + break; + + if (!csr_get_bss_id_bss_desc(pMac, pSirBssDesc1, &bssId1)) + break; + if (!csr_get_bss_id_bss_desc(pMac, pSirBssDesc2, &bssId2)) + break; + + fEqual = cdf_is_macaddr_equal(&bssId1, &bssId2); + } while (0); + + return fEqual; +} + +bool csr_is_conn_state_connected_ibss(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED == + pMac->roam.roamSession[sessionId].connectState; +} + +bool csr_is_conn_state_disconnected_ibss(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED == + pMac->roam.roamSession[sessionId].connectState; +} + +bool csr_is_conn_state_connected_infra(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED == + pMac->roam.roamSession[sessionId].connectState; +} + +bool csr_is_conn_state_connected(tpAniSirGlobal pMac, uint32_t sessionId) +{ + if (csr_is_conn_state_connected_ibss(pMac, sessionId) + || csr_is_conn_state_connected_infra(pMac, sessionId) + || csr_is_conn_state_connected_wds(pMac, sessionId)) + return true; + else + return false; +} + +bool csr_is_conn_state_infra(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return csr_is_conn_state_connected_infra(pMac, sessionId); +} + +bool csr_is_conn_state_ibss(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return csr_is_conn_state_connected_ibss(pMac, sessionId) || + csr_is_conn_state_disconnected_ibss(pMac, sessionId); +} + +bool csr_is_conn_state_connected_wds(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED == + pMac->roam.roamSession[sessionId].connectState; +} + +bool csr_is_conn_state_connected_infra_ap(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + return (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED == + pMac->roam.roamSession[sessionId].connectState) || + (eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED == + pMac->roam.roamSession[sessionId].connectState); +} + +bool csr_is_conn_state_disconnected_wds(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED == + pMac->roam.roamSession[sessionId].connectState; +} + +bool csr_is_conn_state_wds(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return csr_is_conn_state_connected_wds(pMac, sessionId) || + csr_is_conn_state_disconnected_wds(pMac, sessionId); +} + +bool csr_is_conn_state_ap(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession; + pSession = CSR_GET_SESSION(pMac, sessionId); + if (!pSession) + return false; + if (CSR_IS_INFRA_AP(&pSession->connectedProfile)) + return true; + return false; +} + +bool csr_is_any_session_in_connect_state(tpAniSirGlobal pMac) +{ + uint32_t i; + bool fRc = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) && + (csr_is_conn_state_infra(pMac, i) + || csr_is_conn_state_ibss(pMac, i) + || csr_is_conn_state_ap(pMac, i))) { + fRc = true; + break; + } + } + + return fRc; +} + +int8_t csr_get_infra_session_id(tpAniSirGlobal pMac) +{ + uint8_t i; + int8_t sessionid = -1; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && csr_is_conn_state_infra(pMac, i)) { + sessionid = i; + break; + } + } + + return sessionid; +} + +uint8_t csr_get_infra_operation_channel(tpAniSirGlobal pMac, uint8_t sessionId) +{ + uint8_t channel; + + if (CSR_IS_SESSION_VALID(pMac, sessionId)) { + channel = + pMac->roam.roamSession[sessionId].connectedProfile. + operationChannel; + } else { + channel = 0; + } + return channel; +} + +bool csr_is_session_client_and_connected(tpAniSirGlobal pMac, uint8_t sessionId) +{ + tCsrRoamSession *pSession = NULL; + if (CSR_IS_SESSION_VALID(pMac, sessionId) + && csr_is_conn_state_infra(pMac, sessionId)) { + pSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL != pSession->pCurRoamProfile) { + if ((pSession->pCurRoamProfile->csrPersona == + CDF_STA_MODE) + || (pSession->pCurRoamProfile->csrPersona == + CDF_P2P_CLIENT_MODE)) + return true; + } + } + return false; +} + +/** + * csr_get_concurrent_operation_channel() - To get concurrent operating channel + * @mac_ctx: Pointer to mac context + * + * 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 + * + * Return: uint8_t + */ +uint8_t csr_get_concurrent_operation_channel(tpAniSirGlobal mac_ctx) +{ + tCsrRoamSession *session = NULL; + uint8_t i = 0; + tCDF_CON_MODE persona; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (!CSR_IS_SESSION_VALID(mac_ctx, i)) + continue; + session = CSR_GET_SESSION(mac_ctx, i); + if (NULL == session->pCurRoamProfile) + continue; + persona = session->pCurRoamProfile->csrPersona; + if ((((persona == CDF_STA_MODE) || + (persona == CDF_P2P_CLIENT_MODE)) && + (session->connectState == + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)) || + (((persona == CDF_P2P_GO_MODE) || + (persona == CDF_SAP_MODE)) + && (session->connectState != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED))) + return session->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) + +/** + * csr_get_ch_from_ht_profile() - to get channel from HT profile + * @pMac: pointer to Mac context + * @htp: pointer to HT profile + * @och: operating channel + * @cfreq: channel frequency + * @hbw: half bandwidth + * + * This function will fill half bandwidth and channel frequency based + * on the HT profile + * + * Return: none + */ +void csr_get_ch_from_ht_profile(tpAniSirGlobal pMac, tCsrRoamHTProfile *htp, + uint16_t och, uint16_t *cfreq, uint16_t *hbw) +{ + uint16_t 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; + + sms_log(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 = cds_chan_to_freq(cch); + return; +} + +/** + * csr_calc_chb_for_sap_phymode() - to calc channel bandwidth for sap phymode + * @mac_ctx: pointer to mac context + * @sap_ch: SAP operating channel + * @sap_phymode: SAP physical mode + * @sap_cch: concurrency channel + * @sap_hbw: SAP half bw + * @chb: channel bandwidth + * + * This routine is called to calculate channel bandwidth + * + * Return: none + */ +static void csr_calc_chb_for_sap_phymode(tpAniSirGlobal mac_ctx, + uint16_t *sap_ch, eCsrPhyMode *sap_phymode, + uint16_t *sap_cch, uint16_t *sap_hbw, uint8_t *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 (mac_ctx->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 +} + +/** + * csr_handle_conc_chnl_overlap_for_sap_go - To handle overlap for AP+AP + * @mac_ctx: pointer to mac context + * @session: Current session + * @sap_ch: SAP/GO operating channel + * @sap_hbw: SAP/GO half bw + * @sap_cfreq: SAP/GO channel frequency + * @intf_ch: concurrent SAP/GO operating channel + * @intf_hbw: concurrent SAP/GO half bw + * @intf_cfreq: concurrent SAP/GO channel frequency + * + * This routine is called to check if one SAP/GO channel is overlapping with + * other SAP/GO channel + * + * Return: none + */ +static void csr_handle_conc_chnl_overlap_for_sap_go(tpAniSirGlobal mac_ctx, + tCsrRoamSession *session, + uint16_t *sap_ch, uint16_t *sap_hbw, uint16_t *sap_cfreq, + uint16_t *intf_ch, uint16_t *intf_hbw, uint16_t *intf_cfreq) +{ + /* + * 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 == mac_ctx->roam.configParam.conc_custom_rule1 && + 0 == mac_ctx->roam.configParam.conc_custom_rule2) { + if (*sap_ch == 0) { + *sap_ch = session->connectedProfile.operationChannel; + csr_get_ch_from_ht_profile(mac_ctx, + &session->connectedProfile.HTProfile, + *sap_ch, sap_cfreq, sap_hbw); + } else if (*sap_ch != + session->connectedProfile.operationChannel) { + *intf_ch = session->connectedProfile.operationChannel; + csr_get_ch_from_ht_profile(mac_ctx, + &session->connectedProfile.HTProfile, + *intf_ch, intf_cfreq, intf_hbw); + } + } else if (*sap_ch == 0 && + (session->pCurRoamProfile->csrPersona == + CDF_SAP_MODE)) { + *sap_ch = session->connectedProfile.operationChannel; + csr_get_ch_from_ht_profile(mac_ctx, + &session->connectedProfile.HTProfile, + *sap_ch, sap_cfreq, sap_hbw); + } +} + + +/** + * csr_check_concurrent_channel_overlap() - To check concurrent overlap chnls + * @mac_ctx: Pointer to mac context + * @sap_ch: SAP channel + * @sap_phymode: SAP phy mode + * @cc_switch_mode: concurrent switch mode + * + * This routine will be called to check concurrent overlap channels + * + * Return: uint16_t + */ +uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, + uint16_t sap_ch, eCsrPhyMode sap_phymode, + uint8_t cc_switch_mode) +{ + tCsrRoamSession *session = NULL; + uint8_t i = 0, chb = PHY_SINGLE_CHANNEL_CENTERED; + uint16_t intf_ch = 0, sap_hbw = 0, intf_hbw = 0, intf_cfreq = 0; + uint16_t sap_cfreq = 0; + uint16_t sap_lfreq, sap_hfreq, intf_lfreq, intf_hfreq, sap_cch; + + if (mac_ctx->roam.configParam.cc_switch_mode == + CDF_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 = mac_ctx->roam.configParam.channelBondingMode5GHz; + else + chb = mac_ctx->roam.configParam.channelBondingMode24GHz; + + if (chb) + csr_calc_chb_for_sap_phymode(mac_ctx, &sap_ch, + &sap_phymode, &sap_cch, &sap_hbw, &chb); + sap_cfreq = cds_chan_to_freq(sap_cch); + } + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (!CSR_IS_SESSION_VALID(mac_ctx, i)) + continue; + + session = CSR_GET_SESSION(mac_ctx, i); + if (NULL == session->pCurRoamProfile) + continue; + if (((session->pCurRoamProfile->csrPersona == CDF_STA_MODE) || + (session->pCurRoamProfile->csrPersona == + CDF_P2P_CLIENT_MODE)) && + (session->connectState == + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)) { + intf_ch = session->connectedProfile.operationChannel; + csr_get_ch_from_ht_profile(mac_ctx, + &session->connectedProfile.HTProfile, + intf_ch, &intf_cfreq, &intf_hbw); + } else if (((session->pCurRoamProfile->csrPersona == + CDF_P2P_GO_MODE) || + (session->pCurRoamProfile->csrPersona == + CDF_SAP_MODE)) && + (session->connectState != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + csr_handle_conc_chnl_overlap_for_sap_go(mac_ctx, + session, &sap_ch, &sap_hbw, &sap_cfreq, + &intf_ch, &intf_hbw, &intf_cfreq); + } + } + + if (intf_ch && sap_ch != intf_ch && + cc_switch_mode != CDF_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; + + sms_log(mac_ctx, 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, cds_chan_to_freq(sap_ch), + cds_freq_to_chan(sap_cfreq), sap_cfreq, sap_hbw * 2, + sap_lfreq, sap_hfreq, intf_ch, + cds_chan_to_freq(intf_ch), cds_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 == CDF_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; + } + + sms_log(mac_ctx, LOGE, FL("##Concurrent Channels %s Interfering"), + intf_ch == 0 ? "Not" : "Are"); + return intf_ch; +} +#endif + +bool csr_is_all_session_disconnected(tpAniSirGlobal pMac) +{ + uint32_t i; + bool fRc = true; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && !csr_is_conn_state_disconnected(pMac, i)) { + fRc = false; + break; + } + } + + return fRc; +} + +/** + * csr_is_sta_session_connected() - to find if concurrent sta is active + * @mac_ctx: pointer to mac context + * + * This function will iterate through each session and check if sta + * session exist and active + * + * Return: true or false + */ +bool csr_is_sta_session_connected(tpAniSirGlobal mac_ctx) +{ + uint32_t i; + tCsrRoamSession *pSession = NULL; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(mac_ctx, i) && + !csr_is_conn_state_disconnected(mac_ctx, i)) { + pSession = CSR_GET_SESSION(mac_ctx, i); + + if ((NULL != pSession->pCurRoamProfile) && + (CDF_STA_MODE == + pSession->pCurRoamProfile->csrPersona)) + return true; + } + } + + return false; +} + +/** + * csr_is_p2p_session_connected() - to find if any p2p session is active + * @mac_ctx: pointer to mac context + * + * This function will iterate through each session and check if any p2p + * session exist and active + * + * Return: true or false + */ +bool csr_is_p2p_session_connected(tpAniSirGlobal pMac) +{ + uint32_t i; + tCsrRoamSession *pSession = NULL; + tCDF_CON_MODE persona; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && !csr_is_conn_state_disconnected(pMac, i)) { + pSession = CSR_GET_SESSION(pMac, i); + persona = pSession->pCurRoamProfile->csrPersona; + if ((NULL != pSession->pCurRoamProfile) && + ((CDF_P2P_CLIENT_MODE == persona) || + (CDF_P2P_GO_MODE == persona))) { + return true; + } + } + } + + return false; +} + +bool csr_is_any_session_connected(tpAniSirGlobal pMac) +{ + uint32_t i, count; + bool fRc = false; + + count = 0; + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && !csr_is_conn_state_disconnected(pMac, i)) + count++; + } + + if (count > 0) + fRc = true; + return fRc; +} + +bool csr_is_infra_connected(tpAniSirGlobal pMac) +{ + uint32_t i; + bool fRc = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && csr_is_conn_state_connected_infra(pMac, i)) { + fRc = true; + break; + } + } + + return fRc; +} + +bool csr_is_concurrent_infra_connected(tpAniSirGlobal pMac) +{ + uint32_t i, noOfConnectedInfra = 0; + + bool fRc = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && csr_is_conn_state_connected_infra(pMac, i)) { + ++noOfConnectedInfra; + } + } + + /* More than one Infra Sta Connected */ + if (noOfConnectedInfra > 1) + fRc = true; + return fRc; +} + +bool csr_is_ibss_started(tpAniSirGlobal pMac) +{ + uint32_t i; + bool fRc = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && csr_is_conn_state_ibss(pMac, i)) { + fRc = true; + break; + } + } + + return fRc; +} + +bool csr_is_btamp_started(tpAniSirGlobal pMac) +{ + uint32_t i; + bool fRc = false; + + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && csr_is_conn_state_connected_wds(pMac, i)) { + fRc = true; + break; + } + } + + return fRc; +} + +bool csr_is_concurrent_session_running(tpAniSirGlobal pMac) +{ + uint32_t sessionId, noOfCocurrentSession = 0; + eCsrConnectState connectState; + + bool fRc = 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 = true; + return fRc; +} + +bool csr_is_infra_ap_started(tpAniSirGlobal pMac) +{ + uint32_t sessionId; + bool fRc = false; + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + if (CSR_IS_SESSION_VALID(pMac, sessionId) + && (csr_is_conn_state_connected_infra_ap(pMac, sessionId))) { + fRc = true; + break; + } + } + + return fRc; + +} + +bool csr_is_btamp(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return csr_is_conn_state_connected_wds(pMac, sessionId); +} + +bool csr_is_conn_state_disconnected(tpAniSirGlobal pMac, uint32_t sessionId) +{ + return eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED == + pMac->roam.roamSession[sessionId].connectState; +} + +/** + * csr_is_valid_mc_concurrent_session() - To check concurren session is valid + * @mac_ctx: pointer to mac context + * @session_id: session id + * @bss_descr: bss description + * + * This function validates the concurrent session + * + * Return: true or false + */ +bool csr_is_valid_mc_concurrent_session(tpAniSirGlobal mac_ctx, + uint32_t session_id, + tSirBssDescription *bss_descr) +{ + tCsrRoamSession *pSession = NULL; + + /* Check for MCC support */ + if (!mac_ctx->roam.configParam.fenableMCCMode) + return false; + if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) + return false; + /* Validate BeaconInterval */ + pSession = CSR_GET_SESSION(mac_ctx, session_id); + if (NULL == pSession->pCurRoamProfile) + return false; + if (CDF_STATUS_SUCCESS == + csr_isconcurrentsession_valid(mac_ctx, session_id, + pSession->pCurRoamProfile->csrPersona)) { + if (CDF_STATUS_SUCCESS == + csr_validate_mcc_beacon_interval(mac_ctx, + bss_descr->channelId, + &bss_descr->beaconInterval, session_id, + pSession->pCurRoamProfile->csrPersona)) + return true; + } + return false; +} + +static tSirMacCapabilityInfo csr_get_bss_capabilities(tSirBssDescription * + pSirBssDesc) +{ + tSirMacCapabilityInfo dot11Caps; + + /* tSirMacCapabilityInfo is 16-bit */ + cdf_get_u16((uint8_t *) &pSirBssDesc->capabilityInfo, + (uint16_t *) &dot11Caps); + + return dot11Caps; +} + +bool csr_is_infra_bss_desc(tSirBssDescription *pSirBssDesc) +{ + tSirMacCapabilityInfo dot11Caps = csr_get_bss_capabilities(pSirBssDesc); + + return (bool) dot11Caps.ess; +} + +bool csr_is_ibss_bss_desc(tSirBssDescription *pSirBssDesc) +{ + tSirMacCapabilityInfo dot11Caps = csr_get_bss_capabilities(pSirBssDesc); + + return (bool) dot11Caps.ibss; +} + +bool csr_is_qo_s_bss_desc(tSirBssDescription *pSirBssDesc) +{ + tSirMacCapabilityInfo dot11Caps = csr_get_bss_capabilities(pSirBssDesc); + + return (bool) dot11Caps.qos; +} + +bool csr_is_privacy(tSirBssDescription *pSirBssDesc) +{ + tSirMacCapabilityInfo dot11Caps = csr_get_bss_capabilities(pSirBssDesc); + + return (bool) dot11Caps.privacy; +} + +bool csr_is11d_supported(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.Is11dSupportEnabled; +} + +bool csr_is11h_supported(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.Is11hSupportEnabled; +} + +bool csr_is11e_supported(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.Is11eSupportEnabled; +} + +bool csr_is_mcc_supported(tpAniSirGlobal pMac) +{ + return pMac->roam.configParam.fenableMCCMode; + +} + +bool csr_is_wmm_supported(tpAniSirGlobal pMac) +{ + if (eCsrRoamWmmNoQos == pMac->roam.configParam.WMMSupportMode) + return false; + else + return true; +} + +/* pIes is the IEs for pSirBssDesc2 */ +bool csr_is_ssid_equal(tHalHandle hHal, tSirBssDescription *pSirBssDesc1, + tSirBssDescription *pSirBssDesc2, tDot11fBeaconIEs *pIes2) +{ + bool 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 + && + !CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies + (pMac, pSirBssDesc2, + &pIesLocal))) { + sms_log(pMac, LOGE, FL(" fail to parse IEs")); + break; + } + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies(pMac, + pSirBssDesc1, &pIes1))) { + break; + } + if ((!pIes1->SSID.present) || (!pIesLocal->SSID.present)) + break; + if (pIes1->SSID.num_ssid != pIesLocal->SSID.num_ssid) + break; + cdf_mem_copy(Ssid1.ssId, pIes1->SSID.ssid, + pIes1->SSID.num_ssid); + cdf_mem_copy(Ssid2.ssId, pIesLocal->SSID.ssid, + pIesLocal->SSID.num_ssid); + + fEqual = + cdf_mem_compare(Ssid1.ssId, Ssid2.ssId, + pIesLocal->SSID.num_ssid); + + } while (0); + if (pIes1) + cdf_mem_free(pIes1); + if (pIesLocal && !pIes2) + cdf_mem_free(pIesLocal); + + return fEqual; +} + +/* pIes can be passed in as NULL if the caller doesn't have one prepared */ +bool csr_is_bss_description_wme(tHalHandle hHal, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + /* Assume that WME is found... */ + bool fWme = true; + tDot11fBeaconIEs *pIesTemp = pIes; + + do { + if (pIesTemp == NULL) { + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (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 (!csr_is_wmm_supported(pMac) && fWme) { + if (!pIesTemp->HTCaps.present) { + fWme = false; + } + } + if ((pIes == NULL) && (NULL != pIesTemp)) { + /* we allocate memory here so free it before returning */ + cdf_mem_free(pIesTemp); + } + + return fWme; +} + +eCsrMediaAccessType csr_get_qo_s_from_bss_desc(tHalHandle hHal, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) +{ + eCsrMediaAccessType qosType = eCSR_MEDIUM_ACCESS_DCF; + + if (NULL == pIes) { + CDF_ASSERT(pIes != NULL); + return qosType; + } + + do { + /* if we find WMM in the Bss Description, then we let this */ + /* override and use WMM. */ + if (csr_is_bss_description_wme(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 (csr_is_qo_s_bss_desc(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 + && !csr_is11e_supported(hHal)) { + qosType = eCSR_MEDIUM_ACCESS_DCF; + } + } + + } while (0); + + return qosType; +} + +/* Caller allocates memory for pIEStruct */ +CDF_STATUS csr_parse_bss_description_ies(tHalHandle hHal, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIEStruct) +{ + CDF_STATUS status = CDF_STATUS_E_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 + (dot11f_unpack_beacon_i_es + (pMac, (uint8_t *) pBssDesc->ieFields, ieLen, + pIEStruct))) { + status = CDF_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 */ +CDF_STATUS csr_get_parsed_bss_description_ies(tHalHandle hHal, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs **ppIEStruct) +{ + CDF_STATUS status = CDF_STATUS_E_INVAL; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pBssDesc && ppIEStruct) { + *ppIEStruct = cdf_mem_malloc(sizeof(tDot11fBeaconIEs)); + if ((*ppIEStruct) != NULL) { + cdf_mem_set((void *)*ppIEStruct, + sizeof(tDot11fBeaconIEs), 0); + status = + csr_parse_bss_description_ies(hHal, pBssDesc, + *ppIEStruct); + if (!CDF_IS_STATUS_SUCCESS(status)) { + cdf_mem_free(*ppIEStruct); + *ppIEStruct = NULL; + } + } else { + sms_log(pMac, LOGE, FL(" failed to allocate memory")); + CDF_ASSERT(0); + return CDF_STATUS_E_NOMEM; + } + } + + return status; +} + +bool csr_is_nullssid(uint8_t *pBssSsid, uint8_t len) +{ + bool fNullSsid = false; + + uint32_t SsidLength; + uint8_t *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; +} + +uint32_t csr_get_frag_thresh(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + return pMac->roam.configParam.FragmentationThreshold; +} + +uint32_t csr_get_rts_thresh(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + return pMac->roam.configParam.RTSThreshold; +} + +eCsrPhyMode csr_translate_to_phy_mode_from_bss_desc(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; +} + +uint32_t csr_translate_to_wni_cfg_dot11_mode(tpAniSirGlobal pMac, + eCsrCfgDot11Mode csrDot11Mode) +{ + uint32_t ret; + + switch (csrDot11Mode) { + case eCSR_CFG_DOT11_MODE_AUTO: + sms_log(pMac, LOGW, + FL(" Warning: sees eCSR_CFG_DOT11_MODE_AUTO ")); + if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + ret = WNI_CFG_DOT11_MODE_11AC; + else + ret = WNI_CFG_DOT11_MODE_11N; + 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; + 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; + default: + sms_log(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; +} + +/** + * csr_get_phy_mode_from_bss() - Get Phy Mode + * @pMac: Global MAC context + * @pBSSDescription: BSS Descriptor + * @pPhyMode: Physical Mode + * @pIes: Pointer to the IE fields + * + * This function should only return the super set of supported modes + * 11n implies 11b/g/a/n. + * + * Return: success + **/ +CDF_STATUS csr_get_phy_mode_from_bss(tpAniSirGlobal pMac, + tSirBssDescription *pBSSDescription, + eCsrPhyMode *pPhyMode, tDot11fBeaconIEs *pIes) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + eCsrPhyMode phyMode = + csr_translate_to_phy_mode_from_bss_desc(pBSSDescription); + + if (pIes) { + if (pIes->HTCaps.present) { + phyMode = eCSR_DOT11_MODE_11n; +#ifdef WLAN_FEATURE_11AC + if (IS_BSS_VHT_CAPABLE(pIes->VHTCaps) || + IS_BSS_VHT_CAPABLE(pIes->vendor2_ie.VHTCaps)) + phyMode = eCSR_DOT11_MODE_11ac; +#endif + } + *pPhyMode = phyMode; + } + + return status; +} + +/** + * csr_get_phy_mode_in_use() - to get phymode + * @phyModeIn: physical mode + * @bssPhyMode: physical mode in bss + * @f5GhzBand: 5Ghz band + * @pCfgDot11ModeToUse: dot11 mode in use + * + * 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 + * + * Return: true or false + */ +bool csr_get_phy_mode_in_use(eCsrPhyMode phyModeIn, eCsrPhyMode bssPhyMode, + bool f5GhzBand, eCsrCfgDot11Mode *pCfgDot11ModeToUse) +{ + bool fMatch = false; + eCsrCfgDot11Mode cfgDot11Mode; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N; + + switch (phyModeIn) { + /* 11a or 11b or 11g */ + case eCSR_DOT11_MODE_abg: + fMatch = true; + if (f5GhzBand) + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + else if (eCSR_DOT11_MODE_11b == bssPhyMode) + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + else + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + break; + + case eCSR_DOT11_MODE_11a: + if (f5GhzBand) { + fMatch = true; + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + } + break; + + case eCSR_DOT11_MODE_11g: + if (!f5GhzBand) { + fMatch = true; + if (eCSR_DOT11_MODE_11b == bssPhyMode) + cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B; + else + 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; +} + +/** + * csr_is_phy_mode_match() - to find if phy mode matches + * @pMac: pointer to mac context + * @phyMode: physical mode + * @pSirBssDesc: bss description + * @pProfile: pointer to roam profile + * @pReturnCfgDot11Mode: dot1 mode to return + * @pIes: pointer to IEs + * + * This function decides whether the one of the bit of phyMode is matching the + * mode in the BSS and allowed by the user setting + * + * Return: true or false based on mode that fits the criteria + */ +bool csr_is_phy_mode_match(tpAniSirGlobal pMac, uint32_t phyMode, + tSirBssDescription *pSirBssDesc, + tCsrRoamProfile *pProfile, + eCsrCfgDot11Mode *pReturnCfgDot11Mode, + tDot11fBeaconIEs *pIes) +{ + bool fMatch = false; + eCsrPhyMode phyModeInBssDesc = eCSR_DOT11_MODE_AUTO, phyMode2; + eCsrCfgDot11Mode cfgDot11ModeToUse = eCSR_CFG_DOT11_MODE_AUTO; + uint32_t bitMask, loopCount; + + if (!CDF_IS_STATUS_SUCCESS(csr_get_phy_mode_from_bss(pMac, pSirBssDesc, + &phyModeInBssDesc, pIes))) + return fMatch; + + 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 = csr_get_phy_mode_in_use(phyMode2, phyModeInBssDesc, + CDS_IS_CHANNEL_5GHZ(pSirBssDesc->channelId), + &cfgDot11ModeToUse); + } else { + bitMask = 1; + loopCount = 0; + while (loopCount < eCSR_NUM_PHY_MODE) { + phyMode2 = (phyMode & (bitMask << loopCount++)); + if (0 != phyMode2 && csr_get_phy_mode_in_use(phyMode2, + phyModeInBssDesc, + CDS_IS_CHANNEL_5GHZ + (pSirBssDesc->channelId), + &cfgDot11ModeToUse)) { + fMatch = true; + 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 (!CDS_IS_CHANNEL_5GHZ + (pSirBssDesc->channelId)) { + cfgDot11ModeToUse = + eCSR_CFG_DOT11_MODE_11G; + } else { + cfgDot11ModeToUse = + eCSR_CFG_DOT11_MODE_11A; + } + } + } + *pReturnCfgDot11Mode = cfgDot11ModeToUse; + } + + return fMatch; +} + +eCsrCfgDot11Mode csr_find_best_phy_mode(tpAniSirGlobal pMac, uint32_t 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; +} + +uint32_t csr_get11h_power_constraint(tHalHandle hHal, + tDot11fIEPowerConstraints *pPowerConstraint) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint32_t 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; +} + +bool csr_is_profile_wpa(tCsrRoamProfile *pProfile) +{ + bool 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; +} + +bool csr_is_profile_rsn(tCsrRoamProfile *pProfile) +{ + bool 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; +} + +/** + * csr_isconcurrentsession_valid() - check if concurrent session is valid + * @mac_ctx: pointer to mac context + * @cur_sessionid: current session id + * @cur_bss_persona: current BSS persona + * + * This function will check if concurrent session is valid + * + * Return: CDF_STATUS + */ +CDF_STATUS +csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, + tCDF_CON_MODE cur_bss_persona) +{ + uint32_t sessionid = 0; + tCDF_CON_MODE bss_persona; + eCsrConnectState connect_state, temp; + tCsrRoamSession *roam_session; + + for (sessionid = 0; sessionid < CSR_ROAM_SESSION_MAX; sessionid++) { + if (cur_sessionid == sessionid) + continue; + if (!CSR_IS_SESSION_VALID(mac_ctx, sessionid)) + continue; + roam_session = &mac_ctx->roam.roamSession[sessionid]; + bss_persona = roam_session->bssParams.bssPersona; + connect_state = roam_session->connectState; + + switch (cur_bss_persona) { + case CDF_STA_MODE: + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("** STA session **")); + return CDF_STATUS_SUCCESS; + + case CDF_SAP_MODE: + temp = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; +#ifndef WLAN_FEATURE_MBSSID + if ((bss_persona == CDF_SAP_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("sap mode already exist")); + return CDF_STATUS_E_FAILURE; + } else +#endif + if ((bss_persona == CDF_IBSS_MODE) + && (connect_state != temp)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Can't start GO")); + return CDF_STATUS_E_FAILURE; + } + break; + + case CDF_P2P_GO_MODE: + temp = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; + if ((bss_persona == CDF_P2P_GO_MODE) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("GO mode already exists")); + return CDF_STATUS_E_FAILURE; + } else if ((bss_persona == CDF_IBSS_MODE) + && (connect_state != temp)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Can't start SAP")); + return CDF_STATUS_E_FAILURE; + } + break; + case CDF_IBSS_MODE: + if ((bss_persona == CDF_IBSS_MODE) && (connect_state != + eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("IBSS mode already exist")); + return CDF_STATUS_E_FAILURE; + } else if (((bss_persona == CDF_P2P_GO_MODE) || + (bss_persona == CDF_SAP_MODE)) && + (connect_state != + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Can't start GO")); + return CDF_STATUS_E_FAILURE; + } + break; + case CDF_P2P_CLIENT_MODE: + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("**P2P-Client session**")); + return CDF_STATUS_SUCCESS; + default: + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Persona not handled = %d"), + cur_bss_persona); + break; + } + } + return CDF_STATUS_SUCCESS; + +} + +/** + * csr_update_mcc_p2p_beacon_interval() - update p2p beacon interval + * @mac_ctx: pointer to mac context + * + * This function is to update the mcc p2p beacon interval + * + * Return: CDF_STATUS + */ +CDF_STATUS csr_update_mcc_p2p_beacon_interval(tpAniSirGlobal mac_ctx) +{ + uint32_t session_id = 0; + tCsrRoamSession *roam_session; + + /* If MCC is not supported just break and return SUCCESS */ + if (!mac_ctx->roam.configParam.fenableMCCMode) + return CDF_STATUS_E_FAILURE; + + for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) { + /* + * If GO in MCC support different beacon interval, + * change the BI of the P2P-GO + */ + roam_session = &mac_ctx->roam.roamSession[session_id]; + if (roam_session->bssParams.bssPersona != CDF_P2P_GO_MODE) + continue; + /* + * Handle different BI scneario 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 ((mac_ctx->roam.configParam.fAllowMCCGODiffBI == 0x04) + && (roam_session->bssParams. + updatebeaconInterval)) { + return csr_send_chng_mcc_beacon_interval(mac_ctx, + session_id); + } else if (roam_session->bssParams.updatebeaconInterval) { + /* + * If the configuration of fAllowMCCGODiffBI is set to + * other than 0x04 + */ + return csr_roam_call_callback(mac_ctx, + session_id, + NULL, 0, + eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, + eCSR_ROAM_RESULT_NONE); + } + } + return CDF_STATUS_E_FAILURE; +} + +uint16_t csr_calculate_mcc_beacon_interval(tpAniSirGlobal pMac, uint16_t sta_bi, + uint16_t go_gbi) +{ + uint8_t num_beacons = 0; + uint8_t is_multiple = 0; + uint16_t go_cbi = 0; + uint16_t go_fbi = 0; + uint16_t 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 initialise with 100 + */ + sta_bi = 100; + sms_log(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; +} + +CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channelId, + uint16_t *beaconInterval, + uint32_t cursessionId, + tCDF_CON_MODE currBssPersona) +{ + uint32_t sessionId = 0; + uint16_t new_beaconInterval = 0; + + /* If MCC is not supported just break */ + if (!pMac->roam.configParam.fenableMCCMode) { + return CDF_STATUS_E_FAILURE; + } + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) { + if (cursessionId != sessionId) { + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + continue; + } + + switch (currBssPersona) { + case CDF_STA_MODE: + if (pMac->roam.roamSession[sessionId]. + pCurRoamProfile && + (pMac->roam.roamSession[sessionId]. + pCurRoamProfile->csrPersona == + CDF_P2P_CLIENT_MODE)) { + /* check for P2P client mode */ + sms_log(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 == + CDF_SAP_MODE) { + if (pMac->roam.roamSession[sessionId]. + bssParams.operationChn != + channelId) { + sms_log(pMac, LOGE, + FL + ("*** MCC with SAP+STA sessions ****")); + return CDF_STATUS_SUCCESS; + } + } else if (pMac->roam.roamSession[sessionId]. + bssParams.bssPersona == + CDF_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 + CDF_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 = + csr_calculate_mcc_beacon_interval(pMac, + *beaconInterval, + pMac->roam. + roamSession + [sessionId]. + bssParams. + beaconInterval); + } + sms_log(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 */ + sms_log(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 + = true; + return + csr_update_mcc_p2p_beacon_interval + (pMac); + } + return + CDF_STATUS_SUCCESS; + } + /* Disconnect the P2P session */ + else if (pMac->roam.configParam. + fAllowMCCGODiffBI == + 0x03) { + pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = false; + return + csr_roam_call_callback + (pMac, sessionId, + NULL, 0, + eCSR_ROAM_SEND_P2P_STOP_BSS, + eCSR_ROAM_RESULT_NONE); + } else { + sms_log(pMac, LOGE, + FL + ("BeaconInterval is different cannot connect to preferred AP...")); + return + CDF_STATUS_E_FAILURE; + } + } + } + break; + + case CDF_P2P_CLIENT_MODE: + if (pMac->roam.roamSession[sessionId]. + pCurRoamProfile && + (pMac->roam.roamSession[sessionId]. + pCurRoamProfile->csrPersona == + CDF_STA_MODE)) { + /* check for P2P client mode */ + sms_log(pMac, LOG1, + FL + (" Ignore Beacon Interval Validation...")); + } else if (pMac->roam.roamSession[sessionId]. + bssParams.bssPersona == + CDF_P2P_GO_MODE) { + /* Check for P2P go scenario */ + if ((pMac->roam.roamSession[sessionId]. + bssParams.operationChn != + channelId) + && (pMac->roam. + roamSession[sessionId]. + bssParams.beaconInterval != + *beaconInterval)) { + sms_log(pMac, LOGE, + FL + ("BeaconInterval is different cannot connect to P2P_GO network ...")); + return CDF_STATUS_E_FAILURE; + } + } + break; + + case CDF_SAP_MODE: + break; + + case CDF_P2P_GO_MODE: + { + if (pMac->roam.roamSession[sessionId]. + pCurRoamProfile && + ((pMac->roam.roamSession[sessionId]. + pCurRoamProfile->csrPersona == + CDF_P2P_CLIENT_MODE) || + (pMac->roam.roamSession[sessionId]. + pCurRoamProfile->csrPersona == + CDF_STA_MODE))) { + /* check for P2P_client scenario */ + if ((pMac->roam. + roamSession[sessionId]. + connectedProfile. + operationChannel == 0) + && (pMac->roam. + roamSession[sessionId]. + connectedProfile. + beaconInterval == 0)) { + continue; + } + + if (csr_is_conn_state_connected_infra + (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 incase of client or STA case + */ + /* Calculate beacon Interval for P2P-GO incase 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 = + csr_calculate_mcc_beacon_interval + (pMac, + pMac->roam. + roamSession + [sessionId]. + connectedProfile. + beaconInterval, + *beaconInterval); + } + if (*beaconInterval != + new_beaconInterval) + *beaconInterval + = + new_beaconInterval; + return + CDF_STATUS_SUCCESS; + } + } + } + break; + + default: + sms_log(pMac, LOGE, + FL(" Persona not supported : %d"), + currBssPersona); + return CDF_STATUS_E_FAILURE; + } + } + } + + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/* Function to return true if the authtype is 11r */ +bool csr_is_auth_type11r(eCsrAuthType AuthType, uint8_t 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 */ +bool csr_is_profile11r(tCsrRoamProfile *pProfile) +{ + return csr_is_auth_type11r(pProfile->negotiatedAuthType, + pProfile->MDID.mdiePresent); +} + +#endif + +#ifdef FEATURE_WLAN_ESE + +/* Function to return true if the authtype is ESE */ +bool csr_is_auth_type_ese(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 */ +bool csr_is_profile_ese(tCsrRoamProfile *pProfile) +{ + return csr_is_auth_type_ese(pProfile->negotiatedAuthType); +} + +#endif + +#ifdef FEATURE_WLAN_WAPI +bool csr_is_profile_wapi(tCsrRoamProfile *pProfile) +{ + bool 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 bool csr_is_wapi_oui_equal(tpAniSirGlobal pMac, uint8_t *Oui1, + uint8_t *Oui2) +{ + return cdf_mem_compare(Oui1, Oui2, CSR_WAPI_OUI_SIZE); +} + +static bool csr_is_wapi_oui_match(tpAniSirGlobal pMac, + uint8_t AllCyphers[][CSR_WAPI_OUI_SIZE], + uint8_t cAllCyphers, uint8_t Cypher[], + uint8_t Oui[]) +{ + bool fYes = false; + uint8_t idx; + + for (idx = 0; idx < cAllCyphers; idx++) { + if (csr_is_wapi_oui_equal(pMac, AllCyphers[idx], Cypher)) { + fYes = true; + break; + } + } + + if (fYes && Oui) { + cdf_mem_copy(Oui, AllCyphers[idx], CSR_WAPI_OUI_SIZE); + } + + return fYes; +} +#endif /* FEATURE_WLAN_WAPI */ + +static bool csr_is_wpa_oui_equal(tpAniSirGlobal pMac, uint8_t *Oui1, + uint8_t *Oui2) +{ + return cdf_mem_compare(Oui1, Oui2, CSR_WPA_OUI_SIZE); +} + +static bool csr_is_oui_match(tpAniSirGlobal pMac, + uint8_t AllCyphers[][CSR_WPA_OUI_SIZE], + uint8_t cAllCyphers, uint8_t Cypher[], uint8_t Oui[]) +{ + bool fYes = false; + uint8_t idx; + + for (idx = 0; idx < cAllCyphers; idx++) { + if (csr_is_wpa_oui_equal(pMac, AllCyphers[idx], Cypher)) { + fYes = true; + break; + } + } + + if (fYes && Oui) { + cdf_mem_copy(Oui, AllCyphers[idx], CSR_WPA_OUI_SIZE); + } + + return fYes; +} + +static bool csr_match_rsnoui_index(tpAniSirGlobal pMac, + uint8_t AllCyphers[][CSR_RSN_OUI_SIZE], + uint8_t cAllCyphers, uint8_t ouiIndex, + uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllCyphers, cAllCyphers, csr_rsn_oui[ouiIndex], Oui); + +} + +#ifdef FEATURE_WLAN_WAPI +static bool csr_match_wapi_oui_index(tpAniSirGlobal pMac, + uint8_t AllCyphers[][CSR_WAPI_OUI_SIZE], + uint8_t cAllCyphers, uint8_t ouiIndex, + uint8_t Oui[]) +{ + return csr_is_wapi_oui_match + (pMac, AllCyphers, cAllCyphers, csr_wapi_oui[ouiIndex], Oui); + +} +#endif /* FEATURE_WLAN_WAPI */ + +static bool csr_match_wpaoui_index(tpAniSirGlobal pMac, + uint8_t AllCyphers[][CSR_RSN_OUI_SIZE], + uint8_t cAllCyphers, uint8_t ouiIndex, + uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllCyphers, cAllCyphers, csr_wpa_oui[ouiIndex], Oui); + +} + +#ifdef FEATURE_WLAN_WAPI +static bool csr_is_auth_wapi_cert(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_WAPI_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_wapi_oui_match + (pMac, AllSuites, cAllSuites, csr_wapi_oui[1], Oui); +} + +static bool csr_is_auth_wapi_psk(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_WAPI_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_wapi_oui_match + (pMac, AllSuites, cAllSuites, csr_wapi_oui[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 bool csr_is_ft_auth_rsn(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[03], Oui); +} + +/* + * Function for 11R FT Authentication. We match the FT Authentication Cipher + * suite here. This matches for FT Auth with the PSK. + */ +static bool csr_is_ft_auth_rsn_psk(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[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 bool csr_is_ese_cckm_auth_rsn(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[06], Oui); +} + +static bool csr_is_ese_cckm_auth_wpa(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_WPA_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_wpa_oui[06], Oui); +} + +#endif + +static bool csr_is_auth_rsn(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[01], Oui); +} + +static bool csr_is_auth_rsn_psk(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[02], Oui); +} + +#ifdef WLAN_FEATURE_11W +static bool csr_is_auth_rsn_psk_sha256(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[07], Oui); +} +static bool csr_is_auth_rsn8021x_sha256(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_RSN_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_rsn_oui[8], Oui); +} +#endif + +static bool csr_is_auth_wpa(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_WPA_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_wpa_oui[01], Oui); +} + +static bool csr_is_auth_wpa_psk(tpAniSirGlobal pMac, + uint8_t AllSuites[][CSR_WPA_OUI_SIZE], + uint8_t cAllSuites, uint8_t Oui[]) +{ + return csr_is_oui_match + (pMac, AllSuites, cAllSuites, csr_wpa_oui[02], Oui); +} + +uint8_t csr_get_oui_index_from_cipher(eCsrEncryptionType enType) +{ + uint8_t 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; +} +/** + * csr_get_rsn_information() - to get RSN infomation + * @hal: pointer to HAL + * @auth_type: auth type + * @encr_type: encryption type + * @mc_encryption: multicast encryption type + * @rsn_ie: pointer to RSN IE + * @ucast_cipher: Unicast cipher + * @mcast_cipher: Multicast cipher + * @auth_suite: Authentication suite + * @capabilities: RSN capabilities + * @negotiated_authtype: Negotiated auth type + * @negotiated_mccipher: negotiated multicast cipher + * + * This routine will get all RSN information + * + * Return: bool + */ +bool csr_get_rsn_information(tHalHandle hal, tCsrAuthList *auth_type, + eCsrEncryptionType encr_type, + tCsrEncryptionList *mc_encryption, + tDot11fIERSN *rsn_ie, uint8_t *ucast_cipher, + uint8_t *mcast_cipher, uint8_t *auth_suite, + tCsrRSNCapabilities *capabilities, + eCsrAuthType *negotiated_authtype, + eCsrEncryptionType *negotiated_mccipher) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + bool acceptable_cipher = false; + uint8_t c_ucast_cipher = 0; + uint8_t c_mcast_cipher = 0; + uint8_t c_auth_suites = 0, i; + uint8_t unicast[CSR_RSN_OUI_SIZE]; + uint8_t multicast[CSR_RSN_OUI_SIZE]; + uint8_t authsuites[CSR_RSN_MAX_AUTH_SUITES][CSR_RSN_OUI_SIZE]; + uint8_t authentication[CSR_RSN_OUI_SIZE]; + uint8_t mccipher_arr[CSR_RSN_MAX_MULTICAST_CYPHERS][CSR_RSN_OUI_SIZE]; + eCsrAuthType neg_authtype = eCSR_AUTH_TYPE_UNKNOWN; + + if (!rsn_ie->present) + goto end; + c_mcast_cipher++; + cdf_mem_copy(mccipher_arr, rsn_ie->gp_cipher_suite, + CSR_RSN_OUI_SIZE); + c_ucast_cipher = + (uint8_t) (rsn_ie->pwise_cipher_suite_count); + c_auth_suites = (uint8_t) (rsn_ie->akm_suite_count); + for (i = 0; i < c_auth_suites && i < CSR_RSN_MAX_AUTH_SUITES; i++) { + cdf_mem_copy((void *)&authsuites[i], + (void *)&rsn_ie->akm_suites[i], CSR_RSN_OUI_SIZE); + } + + /* Check - Is requested unicast Cipher supported by the BSS. */ + acceptable_cipher = csr_match_rsnoui_index(mac_ctx, + rsn_ie->pwise_cipher_suites, c_ucast_cipher, + csr_get_oui_index_from_cipher(encr_type), + unicast); + + if (!acceptable_cipher) + goto end; + + /* unicast is supported. Pick the first matching Group cipher, if any */ + for (i = 0; i < mc_encryption->numEntries; i++) { + acceptable_cipher = csr_match_rsnoui_index(mac_ctx, + mccipher_arr, c_mcast_cipher, + csr_get_oui_index_from_cipher( + mc_encryption->encryptionType[i]), + multicast); + if (acceptable_cipher) + break; + } + if (!acceptable_cipher) + goto end; + + if (negotiated_mccipher) + *negotiated_mccipher = mc_encryption->encryptionType[i]; + + /* Initializing with false as it has true value already */ + acceptable_cipher = false; + for (i = 0; i < auth_type->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 (csr_is_ft_auth_rsn(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_FT_RSN == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_FT_RSN; + } + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) + && csr_is_ft_auth_rsn_psk(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_FT_RSN_PSK == + auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_FT_RSN_PSK; + } +#endif +#ifdef FEATURE_WLAN_ESE + /* ESE only supports 802.1X. No PSK. */ + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) && + csr_is_ese_cckm_auth_rsn(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_CCKM_RSN == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_CCKM_RSN; + } +#endif + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) + && csr_is_auth_rsn(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_RSN == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_RSN; + } + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) + && csr_is_auth_rsn_psk(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_RSN_PSK == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_RSN_PSK; + } +#ifdef WLAN_FEATURE_11W + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) + && csr_is_auth_rsn_psk_sha256(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == + auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_RSN_PSK_SHA256; + } + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) && + csr_is_auth_rsn8021x_sha256(mac_ctx, authsuites, + c_auth_suites, authentication)) { + if (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == + auth_type->authType[i]) + neg_authtype = 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 != neg_authtype) { + acceptable_cipher = true; + break; + } + } /* for */ +end: + if (acceptable_cipher) { + if (mcast_cipher) + cdf_mem_copy(mcast_cipher, multicast, + CSR_RSN_OUI_SIZE); + + if (ucast_cipher) + cdf_mem_copy(ucast_cipher, unicast, CSR_RSN_OUI_SIZE); + + if (auth_suite) + cdf_mem_copy(auth_suite, authentication, + CSR_RSN_OUI_SIZE); + + if (negotiated_authtype) + *negotiated_authtype = neg_authtype; + + if (capabilities) { + /* Bit 0 Preauthentication */ + capabilities->PreAuthSupported = + (rsn_ie->RSN_Cap[0] >> 0) & 0x1; + /* Bit 1 No Pairwise */ + capabilities->NoPairwise = + (rsn_ie->RSN_Cap[0] >> 1) & 0x1; + /* Bit 2, 3 PTKSA Replay Counter */ + capabilities->PTKSAReplayCounter = + (rsn_ie->RSN_Cap[0] >> 2) & 0x3; + /* Bit 4, 5 GTKSA Replay Counter */ + capabilities->GTKSAReplayCounter = + (rsn_ie->RSN_Cap[0] >> 4) & 0x3; +#ifdef WLAN_FEATURE_11W + /* Bit 6 MFPR */ + capabilities->MFPRequired = + (rsn_ie->RSN_Cap[0] >> 6) & 0x1; + /* Bit 7 MFPC */ + capabilities->MFPCapable = + (rsn_ie->RSN_Cap[0] >> 7) & 0x1; +#else + /* Bit 6 MFPR */ + capabilities->MFPRequired = 0; + /* Bit 7 MFPC */ + capabilities->MFPCapable = 0; +#endif + /* remaining reserved */ + capabilities->Reserved = rsn_ie->RSN_Cap[1] & 0xff; + } + } + return acceptable_cipher; +} + +#ifdef WLAN_FEATURE_11W +/** + * csr_is_pmf_capabilities_in_rsn_match() - check for PMF capability + * @hHal: Global HAL handle + * @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. + * + * This function is to match our current capabilities with the AP + * to which we are expecting make the connection. + * + * Return: 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 bool +csr_is_pmf_capabilities_in_rsn_match(tHalHandle hHal, + bool *pFilterMFPEnabled, + uint8_t *pFilterMFPRequired, + uint8_t *pFilterMFPCapable, + tDot11fIERSN *pRSNIe) +{ + uint8_t apProfileMFPCapable = 0; + uint8_t 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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "AP is not capable to make PMF connection"); + return false; + } else if (*pFilterMFPEnabled && *pFilterMFPCapable && + !(*pFilterMFPRequired) && + (apProfileMFPCapable == 0)) { + /* + * This is tricky, because supplicant asked us to + * make mandatory PMF connection eventhough PMF + * connection is optional here. + * so if AP is not capable of PMF then drop it. + * Don't try to connect with it. + */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "we need PMF connection & AP isn't capable to make PMF connection"); + return 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 + */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "AP needs PMF connection and we are not capable of pmf connection"); + return false; + } else if (!(*pFilterMFPEnabled) && *pFilterMFPCapable && + (apProfileMFPCapable == 1)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "we don't need PMF connection even though both parties are capable"); + return false; + } + } + return true; +} +#endif + +bool csr_is_rsn_match(tHalHandle hHal, tCsrAuthList *pAuthType, + eCsrEncryptionType enType, + tCsrEncryptionList *pEnMcType, + bool *pMFPEnabled, uint8_t *pMFPRequired, + uint8_t *pMFPCapable, + tDot11fBeaconIEs *pIes, + eCsrAuthType *pNegotiatedAuthType, + eCsrEncryptionType *pNegotiatedMCCipher) +{ + bool fRSNMatch = false; + + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fRSNMatch = + csr_get_rsn_information(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 = csr_is_pmf_capabilities_in_rsn_match(hHal, pMFPEnabled, + pMFPRequired, + pMFPCapable, + &pIes->RSN); + } +#endif + return fRSNMatch; +} + +bool csr_lookup_pmkid(tpAniSirGlobal pMac, uint32_t sessionId, uint8_t *pBSSId, + uint8_t *pPMKId) +{ + bool fRC = false, fMatchFound = false; + uint32_t Index; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return false; + } + + do { + for (Index = 0; Index < CSR_MAX_PMKID_ALLOWED; Index++) { + sms_log(pMac, LOG1, + "match PMKID " MAC_ADDRESS_STR " to ", + MAC_ADDR_ARRAY(pBSSId)); + if (cdf_mem_compare + (pBSSId, pSession->PmkidCacheInfo[Index].BSSID.bytes, + sizeof(struct cdf_mac_addr))) { + /* match found */ + fMatchFound = true; + break; + } + } + + if (!fMatchFound) + break; + + cdf_mem_copy(pPMKId, pSession->PmkidCacheInfo[Index].PMKID, + CSR_RSN_PMKID_SIZE); + + fRC = true; + } while (0); + sms_log(pMac, LOGW, + "csr_lookup_pmkid called return match = %d pMac->roam.NumPmkidCache = %d", + fRC, pSession->NumPmkidCache); + + return fRC; +} + +uint8_t csr_construct_rsn_ie(tHalHandle hHal, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRSNIe *pRSNIe) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + bool fRSNMatch; + uint8_t cbRSNIe = 0; + uint8_t UnicastCypher[CSR_RSN_OUI_SIZE]; + uint8_t MulticastCypher[CSR_RSN_OUI_SIZE]; + uint8_t AuthSuite[CSR_RSN_OUI_SIZE]; + tCsrRSNAuthIe *pAuthSuite; + tCsrRSNCapabilities RSNCapabilities; + tCsrRSNPMKIe *pPMK; + uint8_t PMKId[CSR_RSN_PMKID_SIZE]; +#ifdef WLAN_FEATURE_11W + uint8_t *pGroupMgmtCipherSuite; +#endif + tDot11fBeaconIEs *pIesLocal = pIes; + eCsrAuthType negAuthType = eCSR_AUTH_TYPE_UNKNOWN; + + sms_log(pMac, LOGW, "%s called...", __func__); + + do { + if (!csr_is_profile_rsn(pProfile)) + break; + + if (!pIesLocal + && + (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (pMac, pSirBssDesc, &pIesLocal)))) { + break; + } + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fRSNMatch = + csr_get_rsn_information(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; + + cdf_mem_copy(pRSNIe->MulticastOui, MulticastCypher, + sizeof(MulticastCypher)); + + pRSNIe->cUnicastCyphers = 1; + + cdf_mem_copy(&pRSNIe->UnicastOui[0], UnicastCypher, + sizeof(UnicastCypher)); + + pAuthSuite = + (tCsrRSNAuthIe *) (&pRSNIe-> + UnicastOui[pRSNIe->cUnicastCyphers]); + + pAuthSuite->cAuthenticationSuites = 1; + cdf_mem_copy(&pAuthSuite->AuthOui[0], AuthSuite, + sizeof(AuthSuite)); + + /* RSN capabilities follows the Auth Suite (two octects) */ + /* !!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 + *(uint16_t *) (&pAuthSuite->AuthOui[1]) = + *((uint16_t *) (&RSNCapabilities)); + + pPMK = + (tCsrRSNPMKIe *) (((uint8_t *) (&pAuthSuite->AuthOui[1])) + + sizeof(uint16_t)); + + /* Don't include the PMK SA IDs for CCKM associations. */ + if ( +#ifdef FEATURE_WLAN_ESE + (eCSR_AUTH_TYPE_CCKM_RSN != negAuthType) && +#endif + csr_lookup_pmkid(pMac, sessionId, pSirBssDesc->bssId, + &(PMKId[0]))) { + pPMK->cPMKIDs = 1; + + cdf_mem_copy(pPMK->PMKIDList[0].PMKID, PMKId, + CSR_RSN_PMKID_SIZE); + } else { + pPMK->cPMKIDs = 0; + } + +#ifdef WLAN_FEATURE_11W + if (pProfile->MFPEnabled) { + pGroupMgmtCipherSuite = + (uint8_t *) pPMK + sizeof(uint16_t) + + (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE); + cdf_mem_copy(pGroupMgmtCipherSuite, csr_rsn_oui[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 = + (uint8_t) (sizeof(*pRSNIe) - sizeof(pRSNIe->IeHeader) + + sizeof(*pAuthSuite) + + sizeof(tCsrRSNCapabilities)); + if (pPMK->cPMKIDs) { + pRSNIe->IeHeader.Length += (uint8_t) (sizeof(uint16_t) + + (pPMK->cPMKIDs * + CSR_RSN_PMKID_SIZE)); + } +#ifdef WLAN_FEATURE_11W + if (pProfile->MFPEnabled) { + if (0 == pPMK->cPMKIDs) + pRSNIe->IeHeader.Length += sizeof(uint16_t); + 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 */ + cdf_mem_free(pIesLocal); + } + + return cbRSNIe; +} + +#ifdef FEATURE_WLAN_WAPI +/** + * csr_get_wapi_information() - to get WAPI infomation + * @hal: pointer to HAL + * @auth_type: auth type + * @encr_type: encryption type + * @mc_encryption: multicast encryption type + * @wapi_ie: pointer to WAPI IE + * @ucast_cipher: Unicast cipher + * @mcast_cipher: Multicast cipher + * @auth_suite: Authentication suite + * @negotiated_authtype: Negotiated auth type + * @negotiated_mccipher: negotiated multicast cipher + * + * This routine will get all WAPI information + * + * Return: bool + */ +bool csr_get_wapi_information(tHalHandle hal, tCsrAuthList *auth_type, + eCsrEncryptionType encr_type, + tCsrEncryptionList *mc_encryption, + tDot11fIEWAPI *wapi_ie, uint8_t *ucast_cipher, + uint8_t *mcast_cipher, uint8_t *auth_suite, + eCsrAuthType *negotiated_authtype, + eCsrEncryptionType *negotiated_mccipher) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + bool acceptable_cipher = false; + uint8_t c_ucast_cipher = 0; + uint8_t c_mcast_cipher = 0; + uint8_t c_auth_suites = 0, i; + uint8_t unicast[CSR_WAPI_OUI_SIZE]; + uint8_t multicast[CSR_WAPI_OUI_SIZE]; + uint8_t authsuites[CSR_WAPI_MAX_AUTH_SUITES][CSR_WAPI_OUI_SIZE]; + uint8_t authentication[CSR_WAPI_OUI_SIZE]; + uint8_t mccipher_arr[CSR_WAPI_MAX_MULTICAST_CYPHERS][CSR_WAPI_OUI_SIZE]; + eCsrAuthType neg_authtype = eCSR_AUTH_TYPE_UNKNOWN; + uint8_t wapioui_idx = 0; + + if (!wapi_ie->present) + goto end; + + c_mcast_cipher++; + cdf_mem_copy(mccipher_arr, wapi_ie->multicast_cipher_suite, + CSR_WAPI_OUI_SIZE); + c_ucast_cipher = (uint8_t) (wapi_ie->unicast_cipher_suite_count); + c_auth_suites = (uint8_t) (wapi_ie->akm_suite_count); + for (i = 0; i < c_auth_suites && i < CSR_WAPI_MAX_AUTH_SUITES; i++) + cdf_mem_copy((void *)&authsuites[i], + (void *)&wapi_ie->akm_suites[i], CSR_WAPI_OUI_SIZE); + + wapioui_idx = csr_get_oui_index_from_cipher(encr_type); + if (wapioui_idx >= CSR_OUI_WAPI_WAI_MAX_INDEX) { + sms_log(mac_ctx, LOGE, + FL("Wapi OUI index = %d out of limit"), + wapioui_idx); + acceptable_cipher = false; + goto end; + } + /* Check - Is requested unicast Cipher supported by the BSS. */ + acceptable_cipher = csr_match_wapi_oui_index(mac_ctx, + wapi_ie->unicast_cipher_suites, + c_ucast_cipher, wapioui_idx, unicast); + if (!acceptable_cipher) + goto end; + + /* unicast is supported. Pick the first matching Group cipher, if any */ + for (i = 0; i < mc_encryption->numEntries; i++) { + wapioui_idx = csr_get_oui_index_from_cipher( + mc_encryption->encryptionType[i]); + if (wapioui_idx >= CSR_OUI_WAPI_WAI_MAX_INDEX) { + sms_log(mac_ctx, LOGE, + FL("Wapi OUI index = %d out of limit"), + wapioui_idx); + acceptable_cipher = false; + break; + } + acceptable_cipher = csr_match_wapi_oui_index(mac_ctx, + mccipher_arr, c_mcast_cipher, + wapioui_idx, multicast); + if (acceptable_cipher) + break; + } + if (!acceptable_cipher) + goto end; + + if (negotiated_mccipher) + *negotiated_mccipher = + mc_encryption->encryptionType[i]; + + /* + * Ciphers are supported, Match authentication algorithm and + * pick first matching authtype + */ + if (csr_is_auth_wapi_cert + (mac_ctx, authsuites, c_auth_suites, authentication)) { + neg_authtype = + eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + } else if (csr_is_auth_wapi_psk(mac_ctx, authsuites, + c_auth_suites, authentication)) { + neg_authtype = eCSR_AUTH_TYPE_WAPI_WAI_PSK; + } else { + acceptable_cipher = false; + neg_authtype = eCSR_AUTH_TYPE_UNKNOWN; + } + + /* Caller doesn't care about auth type, or BSS doesn't match */ + if ((0 == auth_type->numEntries) || (false == acceptable_cipher)) + goto end; + + acceptable_cipher = false; + for (i = 0; i < auth_type->numEntries; i++) { + if (auth_type->authType[i] == neg_authtype) { + acceptable_cipher = true; + break; + } + } + +end: + if (acceptable_cipher) { + if (mcast_cipher) + cdf_mem_copy(mcast_cipher, multicast, + CSR_WAPI_OUI_SIZE); + if (ucast_cipher) + cdf_mem_copy(ucast_cipher, unicast, CSR_WAPI_OUI_SIZE); + if (auth_suite) + cdf_mem_copy(auth_suite, authentication, + CSR_WAPI_OUI_SIZE); + if (negotiated_authtype) + *negotiated_authtype = neg_authtype; + } + return acceptable_cipher; +} + +bool csr_is_wapi_match(tHalHandle hHal, tCsrAuthList *pAuthType, + eCsrEncryptionType enType, tCsrEncryptionList *pEnMcType, + tDot11fBeaconIEs *pIes, eCsrAuthType *pNegotiatedAuthType, + eCsrEncryptionType *pNegotiatedMCCipher) +{ + bool fWapiMatch = false; + + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fWapiMatch = + csr_get_wapi_information(hHal, pAuthType, enType, pEnMcType, + &pIes->WAPI, NULL, NULL, NULL, + pNegotiatedAuthType, pNegotiatedMCCipher); + + return fWapiMatch; +} + +bool csr_lookup_bkid(tpAniSirGlobal pMac, uint32_t sessionId, uint8_t *pBSSId, + uint8_t *pBKId) +{ + bool fRC = false, fMatchFound = false; + uint32_t Index; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), sessionId); + return false; + } + + do { + for (Index = 0; Index < pSession->NumBkidCache; Index++) { + sms_log(pMac, LOGW, "match BKID " MAC_ADDRESS_STR " to ", + MAC_ADDR_ARRAY(pBSSId)); + if (cdf_mem_compare + (pBSSId, pSession->BkidCacheInfo[Index].BSSID.bytes, + sizeof(struct cdf_mac_addr))) { + /* match found */ + fMatchFound = true; + break; + } + } + + if (!fMatchFound) + break; + + cdf_mem_copy(pBKId, pSession->BkidCacheInfo[Index].BKID, + CSR_WAPI_BKID_SIZE); + + fRC = true; + } while (0); + sms_log(pMac, LOGW, + "csr_lookup_bkid called return match = %d pMac->roam.NumBkidCache = %d", + fRC, pSession->NumBkidCache); + + return fRC; +} + +uint8_t csr_construct_wapi_ie(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe) +{ + bool fWapiMatch = false; + uint8_t cbWapiIe = 0; + uint8_t UnicastCypher[CSR_WAPI_OUI_SIZE]; + uint8_t MulticastCypher[CSR_WAPI_OUI_SIZE]; + uint8_t AuthSuite[CSR_WAPI_OUI_SIZE]; + uint8_t BKId[CSR_WAPI_BKID_SIZE]; + uint8_t *pWapi = NULL; + bool fBKIDFound = false; + tDot11fBeaconIEs *pIesLocal = pIes; + + do { + if (!csr_is_profile_wapi(pProfile)) + break; + + if (!pIesLocal + && + (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (pMac, pSirBssDesc, &pIesLocal)))) { + break; + } + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fWapiMatch = + csr_get_wapi_information(pMac, &pProfile->AuthType, + pProfile->negotiatedUCEncryptionType, + &pProfile->mcEncryptionType, + &pIesLocal->WAPI, UnicastCypher, + MulticastCypher, AuthSuite, NULL, + NULL); + if (!fWapiMatch) + break; + + cdf_mem_set(pWapiIe, sizeof(tCsrWapiIe), 0); + + pWapiIe->IeHeader.ElementID = DOT11F_EID_WAPI; + + pWapiIe->Version = CSR_WAPI_VERSION_SUPPORTED; + + pWapiIe->cAuthenticationSuites = 1; + cdf_mem_copy(&pWapiIe->AuthOui[0], AuthSuite, + sizeof(AuthSuite)); + + pWapi = (uint8_t *) (&pWapiIe->AuthOui[1]); + + *pWapi = (uint16_t) 1; /* cUnicastCyphers */ + pWapi += 2; + cdf_mem_copy(pWapi, UnicastCypher, sizeof(UnicastCypher)); + pWapi += sizeof(UnicastCypher); + + cdf_mem_copy(pWapi, MulticastCypher, sizeof(MulticastCypher)); + pWapi += sizeof(MulticastCypher); + + /* WAPI capabilities follows the Auth Suite (two octects) */ + /* 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 = + csr_lookup_bkid(pMac, sessionId, pSirBssDesc->bssId, + &(BKId[0])); + + if (fBKIDFound) { + /* Do we need to change the endianness here */ + *pWapi = (uint16_t) 1; /* cBKIDs */ + pWapi += 2; + cdf_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 = + (uint8_t) (sizeof(*pWapiIe) - sizeof(pWapiIe->IeHeader)); + + /*2 bytes for BKID Count field */ + pWapiIe->IeHeader.Length += sizeof(uint16_t); + + 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 */ + cdf_mem_free(pIesLocal); + } + + return cbWapiIe; +} +#endif /* FEATURE_WLAN_WAPI */ + +/** + * csr_get_wpa_cyphers() - to get WPA cipher info + * @mac_ctx: pointer to mac context + * @auth_type: auth type + * @encr_type: encryption type + * @mc_encryption: multicast encryption type + * @wpa_ie: pointer to WPA IE + * @ucast_cipher: Unicast cipher + * @mcast_cipher: Multicast cipher + * @auth_suite: Authentication suite + * @negotiated_authtype: Negotiated auth type + * @negotiated_mccipher: negotiated multicast cipher + * + * This routine will get all WPA information + * + * Return: bool + */ +bool csr_get_wpa_cyphers(tpAniSirGlobal mac_ctx, tCsrAuthList *auth_type, + eCsrEncryptionType encr_type, tCsrEncryptionList *mc_encryption, + tDot11fIEWPA *wpa_ie, uint8_t *ucast_cipher, + uint8_t *mcast_cipher, uint8_t *auth_suite, + eCsrAuthType *negotiated_authtype, + eCsrEncryptionType *negotiated_mccipher) +{ + bool acceptable_cipher = false; + uint8_t c_ucast_cipher = 0; + uint8_t c_mcast_cipher = 0; + uint8_t c_auth_suites = 0; + uint8_t unicast[CSR_WPA_OUI_SIZE]; + uint8_t multicast[CSR_WPA_OUI_SIZE]; + uint8_t authentication[CSR_WPA_OUI_SIZE]; + uint8_t mccipher_arr[1][CSR_WPA_OUI_SIZE]; + uint8_t i; + eCsrAuthType neg_authtype = eCSR_AUTH_TYPE_UNKNOWN; + + if (!wpa_ie->present) + goto end; + c_mcast_cipher = 1; + cdf_mem_copy(mccipher_arr, wpa_ie->multicast_cipher, CSR_WPA_OUI_SIZE); + c_ucast_cipher = (uint8_t) (wpa_ie->unicast_cipher_count); + c_auth_suites = (uint8_t) (wpa_ie->auth_suite_count); + + /* Check - Is requested unicast Cipher supported by the BSS. */ + acceptable_cipher = csr_match_wpaoui_index(mac_ctx, + wpa_ie->unicast_ciphers, c_ucast_cipher, + csr_get_oui_index_from_cipher(encr_type), + unicast); + if (!acceptable_cipher) + goto end; + /* unicast is supported. Pick the first matching Group cipher, if any */ + for (i = 0; i < mc_encryption->numEntries; i++) { + acceptable_cipher = csr_match_wpaoui_index(mac_ctx, + mccipher_arr, c_mcast_cipher, + csr_get_oui_index_from_cipher( + mc_encryption->encryptionType[i]), + multicast); + if (acceptable_cipher) + break; + } + if (!acceptable_cipher) + goto end; + + if (negotiated_mccipher) + *negotiated_mccipher = mc_encryption->encryptionType[i]; + + /* Initializing with false as it has true value already */ + acceptable_cipher = false; + for (i = 0; i < auth_type->numEntries; i++) { + /* + * Ciphers are supported, Match authentication algorithm and + * pick first matching authtype + */ + if (csr_is_auth_wpa(mac_ctx, wpa_ie->auth_suites, c_auth_suites, + authentication)) { + if (eCSR_AUTH_TYPE_WPA == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_WPA; + } + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) && + csr_is_auth_wpa_psk(mac_ctx, + wpa_ie->auth_suites, c_auth_suites, + authentication)) { + if (eCSR_AUTH_TYPE_WPA_PSK == auth_type->authType[i]) + neg_authtype = eCSR_AUTH_TYPE_WPA_PSK; + } +#ifdef FEATURE_WLAN_ESE + if ((neg_authtype == eCSR_AUTH_TYPE_UNKNOWN) + && csr_is_ese_cckm_auth_wpa(mac_ctx, + wpa_ie->auth_suites, c_auth_suites, + authentication)) { + if (eCSR_AUTH_TYPE_CCKM_WPA == auth_type->authType[i]) + neg_authtype = 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 != neg_authtype) { + acceptable_cipher = true; + break; + } + } + +end: + if (acceptable_cipher) { + if (mcast_cipher) + cdf_mem_copy((uint8_t **) mcast_cipher, multicast, + CSR_WPA_OUI_SIZE); + + if (ucast_cipher) + cdf_mem_copy((uint8_t **) ucast_cipher, unicast, + CSR_WPA_OUI_SIZE); + + if (auth_suite) + cdf_mem_copy((uint8_t **) auth_suite, authentication, + CSR_WPA_OUI_SIZE); + + if (negotiated_authtype) + *negotiated_authtype = neg_authtype; + } + + return acceptable_cipher; +} + +bool csr_is_wpa_encryption_match(tpAniSirGlobal pMac, tCsrAuthList *pAuthType, + eCsrEncryptionType enType, + tCsrEncryptionList *pEnMcType, + tDot11fBeaconIEs *pIes, + eCsrAuthType *pNegotiatedAuthtype, + eCsrEncryptionType *pNegotiatedMCCipher) +{ + bool fWpaMatch = false; + + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fWpaMatch = + csr_get_wpa_cyphers(pMac, pAuthType, enType, pEnMcType, &pIes->WPA, + NULL, NULL, NULL, pNegotiatedAuthtype, + pNegotiatedMCCipher); + + return fWpaMatch; +} + +uint8_t csr_construct_wpa_ie(tHalHandle hHal, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + bool fWpaMatch; + uint8_t cbWpaIe = 0; + uint8_t UnicastCypher[CSR_WPA_OUI_SIZE]; + uint8_t MulticastCypher[CSR_WPA_OUI_SIZE]; + uint8_t AuthSuite[CSR_WPA_OUI_SIZE]; + tCsrWpaAuthIe *pAuthSuite; + tDot11fBeaconIEs *pIesLocal = pIes; + + do { + if (!csr_is_profile_wpa(pProfile)) + break; + + if (!pIesLocal + && + (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (pMac, pSirBssDesc, &pIesLocal)))) { + break; + } + /* See if the cyphers in the Bss description match with the settings in the profile. */ + fWpaMatch = + csr_get_wpa_cyphers(hHal, &pProfile->AuthType, + pProfile->negotiatedUCEncryptionType, + &pProfile->mcEncryptionType, + &pIesLocal->WPA, UnicastCypher, + MulticastCypher, AuthSuite, NULL, NULL); + if (!fWpaMatch) + break; + + pWpaIe->IeHeader.ElementID = SIR_MAC_WPA_EID; + + cdf_mem_copy(pWpaIe->Oui, csr_wpa_oui[01], sizeof(pWpaIe->Oui)); + + pWpaIe->Version = CSR_WPA_VERSION_SUPPORTED; + + cdf_mem_copy(pWpaIe->MulticastOui, MulticastCypher, + sizeof(MulticastCypher)); + + pWpaIe->cUnicastCyphers = 1; + + cdf_mem_copy(&pWpaIe->UnicastOui[0], UnicastCypher, + sizeof(UnicastCypher)); + + pAuthSuite = + (tCsrWpaAuthIe *) (&pWpaIe-> + UnicastOui[pWpaIe->cUnicastCyphers]); + + pAuthSuite->cAuthenticationSuites = 1; + cdf_mem_copy(&pAuthSuite->AuthOui[0], AuthSuite, + sizeof(AuthSuite)); + + /* The WPA capabilities follows the Auth Suite (two octects)-- */ + /* 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 */ + cdf_mem_free(pIesLocal); + } + + return cbWpaIe; +} + +/* 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 */ +uint8_t csr_retrieve_wpa_ie(tHalHandle hHal, tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWpaIe *pWpaIe) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t cbWpaIe = 0; + + do { + if (!csr_is_profile_wpa(pProfile)) + break; + if (pProfile->nWPAReqIELength && pProfile->pWPAReqIE) { + if (SIR_MAC_WPA_IE_MAX_LENGTH >= + pProfile->nWPAReqIELength) { + cbWpaIe = (uint8_t) pProfile->nWPAReqIELength; + cdf_mem_copy(pWpaIe, pProfile->pWPAReqIE, + cbWpaIe); + } else { + sms_log(pMac, LOGW, + " csr_retrieve_wpa_ie detect invalid WPA IE length (%d) ", + pProfile->nWPAReqIELength); + } + } else { + cbWpaIe = + csr_construct_wpa_ie(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 guarrantee it can contain a max length WPA IE */ +uint8_t csr_retrieve_rsn_ie(tHalHandle hHal, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrRSNIe *pRsnIe) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t cbRsnIe = 0; + + do { + if (!csr_is_profile_rsn(pProfile)) + break; +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) { + /* If "Legacy Fast Roaming" is enabled ALWAYS rebuild the RSN IE from */ + /* scratch. So it contains the current PMK-IDs */ + cbRsnIe = + csr_construct_rsn_ie(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 = (uint8_t) pProfile->nRSNReqIELength; + cdf_mem_copy(pRsnIe, pProfile->pRSNReqIE, + cbRsnIe); + } else { + sms_log(pMac, LOGW, + " csr_retrieve_rsn_ie detect invalid RSN IE length (%d) ", + pProfile->nRSNReqIELength); + } + } else { + cbRsnIe = + csr_construct_rsn_ie(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 guarrantee it can contain a max length WAPI IE */ +uint8_t csr_retrieve_wapi_ie(tHalHandle hHal, uint32_t sessionId, + tCsrRoamProfile *pProfile, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes, tCsrWapiIe *pWapiIe) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint8_t cbWapiIe = 0; + + do { + if (!csr_is_profile_wapi(pProfile)) + break; + if (pProfile->nWAPIReqIELength && pProfile->pWAPIReqIE) { + if (DOT11F_IE_WAPI_MAX_LEN >= + pProfile->nWAPIReqIELength) { + cbWapiIe = (uint8_t) pProfile->nWAPIReqIELength; + cdf_mem_copy(pWapiIe, pProfile->pWAPIReqIE, + cbWapiIe); + } else { + sms_log(pMac, LOGW, + " csr_retrieve_wapi_ie detect invalid WAPI IE length (%d) ", + pProfile->nWAPIReqIELength); + } + } else { + cbWapiIe = + csr_construct_wapi_ie(pMac, sessionId, pProfile, + pSirBssDesc, pIes, pWapiIe); + } + } while (0); + + return cbWapiIe; +} +#endif /* FEATURE_WLAN_WAPI */ + +bool csr_rates_is_dot11_rate11b_supported_rate(uint8_t dot11Rate) +{ + bool fSupported = false; + uint16_t nonBasicRate = + (uint16_t) (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; +} + +bool csr_rates_is_dot11_rate11a_supported_rate(uint8_t dot11Rate) +{ + bool fSupported = false; + uint16_t nonBasicRate = + (uint16_t) (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 csr_translate_encrypt_type_to_ed_type(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; +} + +/** + * csr_validate_wep() - to validate wep + * @uc_encry_type: unicast encryption type + * @auth_list: Auth list + * @mc_encryption_list: multicast encryption type + * @negotiated_authtype: negotiated auth type + * @negotiated_mc_encry: negotiated mc encry type + * @bss_descr: BSS description + * @ie_ptr: IE pointer + * + * This function just checks whether HDD is giving correct values for + * Multicast cipher and Auth + * + * Return: bool + */ +bool csr_validate_wep(tpAniSirGlobal mac_ctx, eCsrEncryptionType uc_encry_type, + tCsrAuthList *auth_list, + tCsrEncryptionList *mc_encryption_list, + eCsrAuthType *negotiated_authtype, + eCsrEncryptionType *negotiated_mc_encry, + tSirBssDescription *bss_descr, tDot11fBeaconIEs *ie_ptr) +{ + uint32_t idx; + bool match = false; + eCsrAuthType negotiated_auth = eCSR_AUTH_TYPE_OPEN_SYSTEM; + eCsrEncryptionType negotiated_mccipher = eCSR_ENCRYPT_TYPE_UNKNOWN; + + /* If privacy bit is not set, consider no match */ + if (!csr_is_privacy(bss_descr)) + goto end; + + for (idx = 0; idx < mc_encryption_list->numEntries; idx++) { + switch (mc_encryption_list->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 (uc_encry_type == + mc_encryption_list->encryptionType[idx]) { + match = true; + negotiated_mccipher = + mc_encryption_list->encryptionType[idx]; + } + break; + default: + match = false; + break; + } + if (match) + break; + } + + if (!match) + goto end; + + for (idx = 0; idx < auth_list->numEntries; idx++) { + switch (auth_list->authType[idx]) { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + case eCSR_AUTH_TYPE_SHARED_KEY: + case eCSR_AUTH_TYPE_AUTOSWITCH: + match = true; + negotiated_auth = auth_list->authType[idx]; + break; + default: + match = false; + } + if (match) + break; + } + + if (!match) + goto end; + + if (!ie_ptr) + goto end; + + /* + * In case of WPA / WPA2, check whether it supports WEP as well. + * Prepare the encryption type for WPA/WPA2 functions + */ + if (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == uc_encry_type) + uc_encry_type = eCSR_ENCRYPT_TYPE_WEP40; + else if (eCSR_ENCRYPT_TYPE_WEP104 == uc_encry_type) + uc_encry_type = eCSR_ENCRYPT_TYPE_WEP104; + + /* else we can use the encryption type directly */ + if (ie_ptr->WPA.present) { + match = cdf_mem_compare(ie_ptr->WPA.multicast_cipher, + csr_wpa_oui[csr_get_oui_index_from_cipher( + uc_encry_type)], + CSR_WPA_OUI_SIZE); + if (match) + goto end; + } + if (ie_ptr->RSN.present) { + match = cdf_mem_compare(ie_ptr->RSN.gp_cipher_suite, + csr_rsn_oui[csr_get_oui_index_from_cipher( + uc_encry_type)], + CSR_RSN_OUI_SIZE); + } + + +end: + if (match) { + if (negotiated_authtype) + *negotiated_authtype = negotiated_auth; + if (negotiated_mc_encry) + *negotiated_mc_encry = negotiated_mccipher; + } + return match; +} + +/** + * csr_validate_open_none() - Check if the security is matching + * @bss_desc: BSS Descriptor on which the check is done + * @mc_enc_type: Multicast encryption type + * @mc_cipher: Multicast Cipher + * @auth_type: Authentication type + * @neg_auth_type: Negotiated Auth type with the AP + * + * Return: Boolean value to tell if matched or not. + */ +static bool csr_validate_open_none(tSirBssDescription *bss_desc, + tCsrEncryptionList *mc_enc_type, eCsrEncryptionType *mc_cipher, + tCsrAuthList *auth_type, eCsrAuthType *neg_auth_type) +{ + bool match; + uint8_t idx; + + /* + * 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 (csr_is_privacy(bss_desc)) + match = false; + else + match = true; + if (match) { + match = false; + /* Check MC cipher and Auth type requested. */ + for (idx = 0; idx < mc_enc_type->numEntries; idx++) { + if (eCSR_ENCRYPT_TYPE_NONE == + mc_enc_type->encryptionType[idx]) { + match = true; + *mc_cipher = mc_enc_type->encryptionType[idx]; + break; + } + } + if (!match) + return match; + + match = false; + /* Check Auth list. It should contain AuthOpen. */ + for (idx = 0; idx < auth_type->numEntries; idx++) { + if ((eCSR_AUTH_TYPE_OPEN_SYSTEM == + auth_type->authType[idx]) || + (eCSR_AUTH_TYPE_AUTOSWITCH == + auth_type->authType[idx])) { + match = true; + *neg_auth_type = + eCSR_AUTH_TYPE_OPEN_SYSTEM; + break; + } + } + if (!match) + return match; + + } + return match; +} + +/** + * csr_validate_any_default() - Check if the security is matching + * @hal: Global HAL handle + * @auth_type: Authentication type + * @mc_enc_type: Multicast encryption type + * @mfp_enabled: Management frame protection feature + * @mfp_required: Mangement frame protection mandatory + * @mfp_capable: Device capable of MFP + * @ies_ptr: Pointer to the IE fields + * @neg_auth_type: Negotiated Auth type with the AP + * @bss_desc: BSS Descriptor + * @neg_uc_cipher: Negotiated unicast cipher suite + * @neg_mc_cipher: Negotiated multicast cipher + * + * Return: Boolean value to tell if matched or not. + */ +static bool csr_validate_any_default(tHalHandle hal, tCsrAuthList *auth_type, + tCsrEncryptionList *mc_enc_type, bool *mfp_enabled, + uint8_t *mfp_required, uint8_t *mfp_capable, + tDot11fBeaconIEs *ies_ptr, eCsrAuthType *neg_auth_type, + tSirBssDescription *bss_desc, eCsrEncryptionType *uc_cipher, + eCsrEncryptionType *mc_cipher) +{ + bool match_any = false; + bool match = true; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + /* It is allowed to match anything. Try the more secured ones first. */ + if (ies_ptr) { + /* Check AES first */ + *uc_cipher = eCSR_ENCRYPT_TYPE_AES; + match_any = csr_is_rsn_match(hal, auth_type, + *uc_cipher, mc_enc_type, mfp_enabled, + mfp_required, mfp_capable, ies_ptr, + neg_auth_type, mc_cipher); + if (!match_any) { + /* Check TKIP */ + *uc_cipher = eCSR_ENCRYPT_TYPE_TKIP; + match_any = csr_is_rsn_match(hal, auth_type, *uc_cipher, + mc_enc_type, mfp_enabled, mfp_required, + mfp_capable, ies_ptr, neg_auth_type, + mc_cipher); + } +#ifdef FEATURE_WLAN_WAPI + if (!match_any) { + /* Check WAPI */ + *uc_cipher = eCSR_ENCRYPT_TYPE_WPI; + match_any = csr_is_wapi_match(hal, auth_type, + *uc_cipher, mc_enc_type, ies_ptr, + neg_auth_type, mc_cipher); + } +#endif + } + if (match_any) + return match; + *uc_cipher = eCSR_ENCRYPT_TYPE_WEP104; + if (csr_validate_wep(mac_ctx, *uc_cipher, auth_type, mc_enc_type, + neg_auth_type, mc_cipher, bss_desc, ies_ptr)) + return match; + *uc_cipher = eCSR_ENCRYPT_TYPE_WEP40; + if (csr_validate_wep(mac_ctx, *uc_cipher, auth_type, mc_enc_type, + neg_auth_type, mc_cipher, bss_desc, ies_ptr)) + return match; + *uc_cipher = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + if (csr_validate_wep(mac_ctx, *uc_cipher, auth_type, mc_enc_type, + neg_auth_type, mc_cipher, bss_desc, ies_ptr)) + return match; + *uc_cipher = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + if (csr_validate_wep(mac_ctx, *uc_cipher, auth_type, mc_enc_type, + neg_auth_type, mc_cipher, bss_desc, ies_ptr)) + return match; + /* It must be open and no enc */ + if (csr_is_privacy(bss_desc)) { + match = false; + return match; + } + + *neg_auth_type = eCSR_AUTH_TYPE_OPEN_SYSTEM; + *mc_cipher = eCSR_ENCRYPT_TYPE_NONE; + *uc_cipher = eCSR_ENCRYPT_TYPE_NONE; + return match; + +} + +/** + * csr_is_security_match() - Check if the security is matching + * @hal: Global HAL handle + * @auth_type: Authentication type + * @uc_enc_type: Unicast Encryption type + * @mc_enc_type: Multicast encryption type + * @mfp_enabled: Management frame protection feature + * @mfp_required: Mangement frame protection mandatory + * @mfp_capable: Device capable of MFP + * @bss_desc: BSS Descriptor + * @ies_ptr: Pointer to the IE fields + * @neg_auth_type: Negotiated Auth type with the AP + * @neg_uc_cipher: Negotiated unicast cipher suite + * @neg_mc_cipher: Negotiated multicast cipher + * + * Return: Boolean value to tell if matched or not. + */ +bool csr_is_security_match(tHalHandle hal, tCsrAuthList *auth_type, + tCsrEncryptionList *uc_enc_type, + tCsrEncryptionList *mc_enc_type, bool *mfp_enabled, + uint8_t *mfp_required, uint8_t *mfp_capable, + tSirBssDescription *bss_desc, tDot11fBeaconIEs *ies_ptr, + eCsrAuthType *neg_auth_type, + eCsrEncryptionType *neg_uc_cipher, + eCsrEncryptionType *neg_mc_cipher) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + bool match = false; + uint8_t i; + eCsrEncryptionType mc_cipher = eCSR_ENCRYPT_TYPE_UNKNOWN; + eCsrEncryptionType uc_cipher = eCSR_ENCRYPT_TYPE_UNKNOWN; + eCsrAuthType local_neg_auth_type = eCSR_AUTH_TYPE_UNKNOWN; + + for (i = 0; ((i < uc_enc_type->numEntries) && (!match)); i++) { + uc_cipher = uc_enc_type->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 (uc_cipher) { + case eCSR_ENCRYPT_TYPE_NONE: + match = csr_validate_open_none(bss_desc, mc_enc_type, + &mc_cipher, auth_type, + &local_neg_auth_type); + 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. + */ + match = csr_validate_wep(mac_ctx, uc_cipher, auth_type, + mc_enc_type, &local_neg_auth_type, + &mc_cipher, bss_desc, ies_ptr); + + break; + /* these are all of the WPA encryption types... */ + case eCSR_ENCRYPT_TYPE_WEP40: + case eCSR_ENCRYPT_TYPE_WEP104: + match = csr_validate_wep(mac_ctx, uc_cipher, auth_type, + mc_enc_type, &local_neg_auth_type, + &mc_cipher, bss_desc, ies_ptr); + break; + + case eCSR_ENCRYPT_TYPE_TKIP: + case eCSR_ENCRYPT_TYPE_AES: + if (!ies_ptr) { + match = false; + break; + } + /* First check if there is a RSN match */ + match = csr_is_rsn_match(mac_ctx, auth_type, + uc_cipher, mc_enc_type, + mfp_enabled, mfp_required, + mfp_capable, ies_ptr, + &local_neg_auth_type, + &mc_cipher); + /* If not RSN, then check WPA match */ + if (!match) + match = csr_is_wpa_encryption_match( + mac_ctx, auth_type, + uc_cipher, mc_enc_type, + ies_ptr, + &local_neg_auth_type, + &mc_cipher); + break; +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: /* WAPI */ + if (ies_ptr) + match = csr_is_wapi_match(hal, auth_type, + uc_cipher, mc_enc_type, ies_ptr, + &local_neg_auth_type, + &mc_cipher); + else + match = false; + break; +#endif /* FEATURE_WLAN_WAPI */ + case eCSR_ENCRYPT_TYPE_ANY: + default: + match = csr_validate_any_default(hal, auth_type, + mc_enc_type, mfp_enabled, mfp_required, + mfp_capable, ies_ptr, + &local_neg_auth_type, bss_desc, + &uc_cipher, &mc_cipher); + break; + } + + } + + if (match) { + if (neg_uc_cipher) + *neg_uc_cipher = uc_cipher; + if (neg_mc_cipher) + *neg_mc_cipher = mc_cipher; + if (neg_auth_type) + *neg_auth_type = local_neg_auth_type; + } + return match; +} + +bool csr_is_ssid_match(tpAniSirGlobal pMac, uint8_t *ssid1, uint8_t ssid1Len, + uint8_t *bssSsid, uint8_t bssSsidLen, bool fSsidRequired) +{ + bool 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 Wildcards 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 trated same */ + /* as NULL SSID */ + if (csr_is_nullssid(bssSsid, bssSsidLen)) { + if (false == fSsidRequired) { + fMatch = true; + break; + } + } + + if (ssid1Len != bssSsidLen) + break; + if (cdf_mem_compare(bssSsid, ssid1, bssSsidLen)) { + fMatch = true; + break; + } + + } while (0); + + return fMatch; +} + +/* Null ssid means match */ +bool csr_is_ssid_in_list(tHalHandle hHal, tSirMacSSid *pSsid, + tCsrSSIDs *pSsidList) +{ + bool fMatch = false; + uint32_t i; + + if (pSsidList && pSsid) { + for (i = 0; i < pSsidList->numOfSSIDs; i++) { + if (csr_is_nullssid + (pSsidList->SSIDList[i].SSID.ssId, + pSsidList->SSIDList[i].SSID.length) + || + ((pSsidList->SSIDList[i].SSID.length == + pSsid->length) + && cdf_mem_compare(pSsid->ssId, + pSsidList->SSIDList[i].SSID. + ssId, pSsid->length))) { + fMatch = true; + break; + } + } + } + + return fMatch; +} + +bool csr_is_bssid_match(tHalHandle hHal, struct cdf_mac_addr *pProfBssid, + struct cdf_mac_addr *BssBssid) +{ + bool fMatch = false; + struct cdf_mac_addr ProfileBssid; + + /* for efficiency of the MAC_ADDRESS functions, move the */ + /* Bssid's into MAC_ADDRESS structs. */ + cdf_mem_copy(&ProfileBssid, pProfBssid, sizeof(struct cdf_mac_addr)); + + 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 (cdf_is_macaddr_zero(&ProfileBssid) || + cdf_is_macaddr_broadcast(&ProfileBssid)) { + fMatch = true; + break; + } + + if (cdf_is_macaddr_equal(BssBssid, &ProfileBssid)) { + fMatch = true; + break; + } + + } while (0); + + return fMatch; +} + +bool csr_is_bss_type_match(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2) +{ + if ((eCSR_BSS_TYPE_ANY != bssType1 && eCSR_BSS_TYPE_ANY != bssType2) + && (bssType1 != bssType2)) + return false; + else + return true; +} + +bool csr_is_bss_type_ibss(eCsrRoamBssType bssType) +{ + return (bool) + (eCSR_BSS_TYPE_START_IBSS == bssType + || eCSR_BSS_TYPE_IBSS == bssType); +} + +bool csr_is_bss_type_wds(eCsrRoamBssType bssType) +{ + return (bool) + (eCSR_BSS_TYPE_WDS_STA == bssType + || eCSR_BSS_TYPE_WDS_AP == bssType); +} + +bool csr_is_bss_type_caps_match(eCsrRoamBssType bssType, + tSirBssDescription *pSirBssDesc) +{ + bool fMatch = true; + + do { + switch (bssType) { + case eCSR_BSS_TYPE_ANY: + break; + + case eCSR_BSS_TYPE_INFRASTRUCTURE: + case eCSR_BSS_TYPE_WDS_STA: + if (!csr_is_infra_bss_desc(pSirBssDesc)) + fMatch = false; + + break; + + case eCSR_BSS_TYPE_IBSS: + case eCSR_BSS_TYPE_START_IBSS: + if (!csr_is_ibss_bss_desc(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 bool csr_is_capabilities_match(tpAniSirGlobal pMac, eCsrRoamBssType bssType, + tSirBssDescription *pSirBssDesc) +{ + return csr_is_bss_type_caps_match(bssType, pSirBssDesc); +} + +static bool csr_is_specific_channel_match(tpAniSirGlobal pMac, + tSirBssDescription *pSirBssDesc, + uint8_t Channel) +{ + bool 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; +} + +bool csr_is_channel_band_match(tpAniSirGlobal pMac, uint8_t channelId, + tSirBssDescription *pSirBssDesc) +{ + bool 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 = + csr_is_specific_channel_match(pMac, pSirBssDesc, + channelId); + } + + } while (0); + + return fMatch; +} + +/** + * csr_is_aggregate_rate_supported() - to check if aggregate rate is supported + * @mac_ctx: pointer to mac context + * @rate: A rate in units of 500kbps + * + * + * 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. + * + * Return: true if the adapter is currently capable of supporting this rate + */ + +static bool csr_is_aggregate_rate_supported(tpAniSirGlobal mac_ctx, + uint16_t rate) +{ + bool supported = false; + uint16_t idx, new_rate; + + /* In case basic rate flag is set */ + new_rate = BITS_OFF(rate, CSR_DOT11_BASIC_RATE_MASK); + if (eCSR_CFG_DOT11_MODE_11A == + mac_ctx->roam.configParam.uCfgDot11Mode) { + switch (new_rate) { + case eCsrSuppRate_6Mbps: + case eCsrSuppRate_9Mbps: + case eCsrSuppRate_12Mbps: + case eCsrSuppRate_18Mbps: + case eCsrSuppRate_24Mbps: + case eCsrSuppRate_36Mbps: + case eCsrSuppRate_48Mbps: + case eCsrSuppRate_54Mbps: + supported = true; + break; + default: + supported = false; + break; + } + + } else if (eCSR_CFG_DOT11_MODE_11B == + mac_ctx->roam.configParam.uCfgDot11Mode) { + switch (new_rate) { + case eCsrSuppRate_1Mbps: + case eCsrSuppRate_2Mbps: + case eCsrSuppRate_5_5Mbps: + case eCsrSuppRate_11Mbps: + supported = true; + break; + default: + supported = false; + break; + } + } else if (!mac_ctx->roam.configParam.ProprietaryRatesEnabled) { + + switch (new_rate) { + 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: + supported = true; + break; + default: + supported = false; + break; + } + } else if (eCsrSuppRate_1Mbps == new_rate || + eCsrSuppRate_2Mbps == new_rate || + eCsrSuppRate_5_5Mbps == new_rate || + eCsrSuppRate_11Mbps == new_rate) { + supported = true; + } else { + idx = 0x1; + + switch (new_rate) { + case eCsrSuppRate_6Mbps: + supported = g_phy_rates_suppt[0][idx]; + break; + case eCsrSuppRate_9Mbps: + supported = g_phy_rates_suppt[1][idx]; + break; + case eCsrSuppRate_12Mbps: + supported = g_phy_rates_suppt[2][idx]; + break; + case eCsrSuppRate_18Mbps: + supported = g_phy_rates_suppt[3][idx]; + break; + case eCsrSuppRate_20Mbps: + supported = g_phy_rates_suppt[4][idx]; + break; + case eCsrSuppRate_24Mbps: + supported = g_phy_rates_suppt[5][idx]; + break; + case eCsrSuppRate_36Mbps: + supported = g_phy_rates_suppt[6][idx]; + break; + case eCsrSuppRate_40Mbps: + supported = g_phy_rates_suppt[7][idx]; + break; + case eCsrSuppRate_42Mbps: + supported = g_phy_rates_suppt[8][idx]; + break; + case eCsrSuppRate_48Mbps: + supported = g_phy_rates_suppt[9][idx]; + break; + case eCsrSuppRate_54Mbps: + supported = g_phy_rates_suppt[10][idx]; + break; + case eCsrSuppRate_72Mbps: + supported = g_phy_rates_suppt[11][idx]; + break; + case eCsrSuppRate_80Mbps: + supported = g_phy_rates_suppt[12][idx]; + break; + case eCsrSuppRate_84Mbps: + supported = g_phy_rates_suppt[13][idx]; + break; + case eCsrSuppRate_96Mbps: + supported = g_phy_rates_suppt[14][idx]; + break; + case eCsrSuppRate_108Mbps: + supported = g_phy_rates_suppt[15][idx]; + break; + case eCsrSuppRate_120Mbps: + supported = g_phy_rates_suppt[16][idx]; + break; + case eCsrSuppRate_126Mbps: + supported = g_phy_rates_suppt[17][idx]; + break; + case eCsrSuppRate_144Mbps: + supported = g_phy_rates_suppt[18][idx]; + break; + case eCsrSuppRate_160Mbps: + supported = g_phy_rates_suppt[19][idx]; + break; + case eCsrSuppRate_168Mbps: + supported = g_phy_rates_suppt[20][idx]; + break; + case eCsrSuppRate_192Mbps: + supported = g_phy_rates_suppt[21][idx]; + break; + case eCsrSuppRate_216Mbps: + supported = g_phy_rates_suppt[22][idx]; + break; + case eCsrSuppRate_240Mbps: + supported = g_phy_rates_suppt[23][idx]; + break; + default: + supported = false; + break; + } + } + return supported; +} + +/** + * csr_is_rate_set_match() - to check if rate set is matching + * @mac_ctx: pointer to mac context + * @bss_supported_rates: supported rates of BSS + * @bss_ext_supp_rates: extended rates of bss + * + * This routine is to checke if rate set is matched or no + * + * Return: bool + */ +static bool csr_is_rate_set_match(tpAniSirGlobal mac_ctx, + tDot11fIESuppRates *bss_supported_rates, + tDot11fIEExtSuppRates *bss_ext_supp_rates) +{ + bool match = true; + uint32_t i; + + /* + * Validate that all of the Basic rates advertised in the Bss + * description are supported + */ + if (bss_supported_rates) { + for (i = 0; i < bss_supported_rates->num_rates; i++) { + if (!CSR_IS_BASIC_RATE(bss_supported_rates->rates[i])) + continue; + if (!csr_is_aggregate_rate_supported(mac_ctx, + bss_supported_rates->rates[i])) { + match = false; + break; + } + } + } + if (match && bss_ext_supp_rates) { + for (i = 0; i < bss_ext_supp_rates->num_rates; i++) { + if (!CSR_IS_BASIC_RATE(bss_ext_supp_rates->rates[i])) + continue; + if (!csr_is_aggregate_rate_supported(mac_ctx, + bss_ext_supp_rates->rates[i])) { + match = false; + break; + } + } + } + return match; +} + +/** + * csr_match_bss() - to compare the bss + * @hal: pointer to hal context + * @bss_descr: pointer bss description + * @filter: scan filter + * @neg_auth: negotiated auth + * @neg_uc: negotiated for unicast + * @neg_mc: negotiated for multicast + * @ie_dblptr: double pointer to IE + * + * This routine will be called to match the bss + * If caller want to get the *ie_dblptr allocated by this function, + * pass in *ie_dblptr = NULL + * + * Return: bool + */ +bool csr_match_bss(tHalHandle hal, tSirBssDescription *bss_descr, + tCsrScanResultFilter *filter, eCsrAuthType *neg_auth, + eCsrEncryptionType *neg_uc, eCsrEncryptionType *neg_mc, + tDot11fBeaconIEs **ie_dblptr) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + bool rc = false, check, blacklist_check; + uint32_t i; + tDot11fBeaconIEs *ie_ptr = NULL; + uint8_t *pb; + struct roam_ext_params *roam_params; + uint8_t *p2p_macaddr = NULL; + + roam_params = &mac_ctx->roam.configParam.roam_params; + if ((NULL == ie_dblptr) || (*ie_dblptr) == NULL) { + /* If no IEs passed in, get our own. */ + if (!CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies(mac_ctx, + bss_descr, &ie_ptr))) { + goto end; + } + } else { + /* Save the one pass in for local use */ + ie_ptr = *ie_dblptr; + } + + /* Check if caller wants P2P */ + check = (!filter->p2pResult || ie_ptr->P2PBeaconProbeRes.present); + if (!check) + goto end; + + /* Check for Blacklist BSSID's and avoid connections */ + blacklist_check = false; + for (i = 0; i < roam_params->num_bssid_avoid_list; i++) { + if (cdf_is_macaddr_equal((struct cdf_mac_addr *) + &roam_params->bssid_avoid_list[i], + (struct cdf_mac_addr *)bss_descr->bssId)) { + blacklist_check = true; + break; + } + } + if (blacklist_check) { + sms_log(mac_ctx, LOGE, + FL("Don't Attempt connect to blacklist bssid")); + goto end; + } + + if (ie_ptr->SSID.present) { + for (i = 0; i < filter->SSIDs.numOfSSIDs; i++) { + check = csr_is_ssid_match(mac_ctx, + filter->SSIDs.SSIDList[i].SSID.ssId, + filter->SSIDs.SSIDList[i].SSID.length, + ie_ptr->SSID.ssid, + ie_ptr->SSID.num_ssid, true); + if (check) + break; + } + if (!check) + goto end; + } + check = true; + p2p_macaddr = ie_ptr->P2PBeaconProbeRes.P2PDeviceInfo.P2PDeviceAddress; + for (i = 0; i < filter->BSSIDs.numOfBSSIDs; i++) { + check = csr_is_bssid_match(mac_ctx, + (struct cdf_mac_addr *)&filter->BSSIDs.bssid[i], + (struct cdf_mac_addr *)bss_descr->bssId); + if (check) + break; + + if (filter->p2pResult && ie_ptr->P2PBeaconProbeRes.present) { + check = csr_is_bssid_match(mac_ctx, + (struct cdf_mac_addr *) + &filter->BSSIDs.bssid[i], + (struct cdf_mac_addr *)p2p_macaddr); + if (check) + break; + } + } + if (!check) + goto end; + + check = true; + for (i = 0; i < filter->ChannelInfo.numOfChannels; i++) { + check = csr_is_channel_band_match(mac_ctx, + filter->ChannelInfo.ChannelList[i], bss_descr); + if (check) + break; + } + if (!check) + goto end; +#if defined WLAN_FEATURE_VOWIFI + /* If this is for measurement filtering */ + if (filter->fMeasurement) { + rc = true; + goto end; + } +#endif + if (!csr_is_phy_mode_match(mac_ctx, filter->phyMode, bss_descr, + NULL, NULL, ie_ptr)) + goto end; + +#ifdef WLAN_FEATURE_11W + if ((!filter->bWPSAssociation) && (!filter->bOSENAssociation) && + !csr_is_security_match(mac_ctx, &filter->authType, + &filter->EncryptionType, + &filter->mcEncryptionType, + &filter->MFPEnabled, + &filter->MFPRequired, + &filter->MFPCapable, + bss_descr, ie_ptr, neg_auth, + neg_uc, neg_mc)) +#else + if ((!filter->bWPSAssociation) && (!filter->bOSENAssociation) && + !csr_is_security_match(mac_ctx, &filter->authType, + &filter->EncryptionType, + &filter->mcEncryptionType, + NULL, NULL, NULL, + bss_descr, ie_ptr, neg_auth, + neg_uc, neg_mc)) +#endif + goto end; + if (!csr_is_capabilities_match(mac_ctx, filter->BSSType, bss_descr)) + goto end; + if (!csr_is_rate_set_match(mac_ctx, &ie_ptr->SuppRates, + &ie_ptr->ExtSuppRates)) + goto end; + if ((eCsrRoamWmmQbssOnly == mac_ctx->roam.configParam.WMMSupportMode) + && !CSR_IS_QOS_BSS(ie_ptr)) + goto end; + /* + * Check country. check even when pb is NULL because we may + * want to make sure + */ + pb = (filter->countryCode[0]) ? (filter->countryCode) : NULL; + check = csr_match_country_code(mac_ctx, pb, ie_ptr); + if (!check) + goto end; + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (filter->MDID.mdiePresent && csr_roam_is11r_assoc(mac_ctx, + mac_ctx->roam.roamSession->sessionId)) { + if (bss_descr->mdiePresent) { + if (filter->MDID.mobilityDomain != + (bss_descr->mdie[1] << 8 | + bss_descr->mdie[0])) + goto end; + } else { + goto end; + } + } +#endif + rc = true; + +end: + if (ie_dblptr) + *ie_dblptr = ie_ptr; + else if (ie_ptr) + cdf_mem_free(ie_ptr); + return rc; +} + +bool csr_match_connected_bss_security(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 csr_is_security_match(pMac, &authList, &ucEncryptionList, + &mcEncryptionList, NULL, NULL, NULL, + pBssDesc, pIes, NULL, NULL, NULL); + +} + +bool csr_match_bss_to_connect_profile(tHalHandle hHal, + tCsrRoamConnectedProfile *pProfile, + tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + bool fRC = false, fCheck; + tDot11fBeaconIEs *pIesLocal = pIes; + + do { + if (!pIes) { + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (pMac, pBssDesc, &pIesLocal))) { + break; + } + } + fCheck = true; + if (pIesLocal->SSID.present) { + bool fCheckSsid = false; + if (pProfile->SSID.length) { + fCheckSsid = true; + } + fCheck = + csr_is_ssid_match(pMac, pProfile->SSID.ssId, + pProfile->SSID.length, + pIesLocal->SSID.ssid, + pIesLocal->SSID.num_ssid, + fCheckSsid); + if (!fCheck) + break; + } + if (!csr_match_connected_bss_security + (pMac, pProfile, pBssDesc, pIesLocal)) + break; + if (!csr_is_capabilities_match(pMac, pProfile->BSSType, pBssDesc)) + break; + if (!csr_is_rate_set_match + (pMac, &pIesLocal->SuppRates, &pIesLocal->ExtSuppRates)) + break; + fCheck = + csr_is_channel_band_match(pMac, pProfile->operationChannel, + pBssDesc); + if (!fCheck) + break; + + fRC = true; + + } while (0); + + if (!pIes && pIesLocal) { + /* locally allocated */ + cdf_mem_free(pIesLocal); + } + + return fRC; +} + +void csr_add_rate_bitmap(uint8_t rate, uint16_t *pRateBitmap) +{ + uint16_t rateBitmap; + uint16_t 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; +} + +bool csr_check_rate_bitmap(uint8_t rate, uint16_t rateBitmap) +{ + uint16_t 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; +} + +bool csr_rates_is_dot11_rate_supported(tHalHandle hHal, uint8_t rate) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + uint16_t n = BITS_OFF(rate, CSR_DOT11_BASIC_RATE_MASK); + + return csr_is_aggregate_rate_supported(pMac, n); +} + +uint16_t csr_rates_mac_prop_to_dot11(uint16_t Rate) +{ + uint16_t 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; +} + +uint16_t csr_rates_find_best_rate(tSirMacRateSet *pSuppRates, + tSirMacRateSet *pExtRates, + tSirMacPropRateSet *pPropRates) +{ + uint8_t i; + uint16_t 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 = + (uint16_t) CSR_MAX(nBest, + pSuppRates-> + rate[i] & (~CSR_DOT11_BASIC_RATE_MASK)); + } + + if (NULL != pExtRates) { + for (i = 0U; i < pExtRates->numRates; ++i) { + nBest = + (uint16_t) CSR_MAX(nBest, + pExtRates-> + rate[i] & + (~CSR_DOT11_BASIC_RATE_MASK)); + } + } + + if (NULL != pPropRates) { + for (i = 0U; i < pPropRates->numPropRates; ++i) { + nBest = + (uint16_t) CSR_MAX(nBest, + csr_rates_mac_prop_to_dot11 + (pPropRates->propRate[i])); + } + } + + return nBest; +} + +void csr_release_profile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) +{ + if (pProfile) { + if (pProfile->BSSIDs.bssid) { + cdf_mem_free(pProfile->BSSIDs.bssid); + pProfile->BSSIDs.bssid = NULL; + } + if (pProfile->SSIDs.SSIDList) { + cdf_mem_free(pProfile->SSIDs.SSIDList); + pProfile->SSIDs.SSIDList = NULL; + } + if (pProfile->pWPAReqIE) { + cdf_mem_free(pProfile->pWPAReqIE); + pProfile->pWPAReqIE = NULL; + } + if (pProfile->pRSNReqIE) { + cdf_mem_free(pProfile->pRSNReqIE); + pProfile->pRSNReqIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + if (pProfile->pWAPIReqIE) { + cdf_mem_free(pProfile->pWAPIReqIE); + pProfile->pWAPIReqIE = NULL; + } +#endif /* FEATURE_WLAN_WAPI */ + + if (pProfile->pAddIEScan) { + cdf_mem_free(pProfile->pAddIEScan); + pProfile->pAddIEScan = NULL; + } + + if (pProfile->pAddIEAssoc) { + cdf_mem_free(pProfile->pAddIEAssoc); + pProfile->pAddIEAssoc = NULL; + } + if (pProfile->ChannelInfo.ChannelList) { + cdf_mem_free(pProfile->ChannelInfo.ChannelList); + pProfile->ChannelInfo.ChannelList = NULL; + } + cdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0); + } +} + +void csr_free_scan_filter(tpAniSirGlobal pMac, tCsrScanResultFilter *pScanFilter) +{ + if (pScanFilter->BSSIDs.bssid) { + cdf_mem_free(pScanFilter->BSSIDs.bssid); + pScanFilter->BSSIDs.bssid = NULL; + } + if (pScanFilter->ChannelInfo.ChannelList) { + cdf_mem_free(pScanFilter->ChannelInfo.ChannelList); + pScanFilter->ChannelInfo.ChannelList = NULL; + } + if (pScanFilter->SSIDs.SSIDList) { + cdf_mem_free(pScanFilter->SSIDs.SSIDList); + pScanFilter->SSIDs.SSIDList = NULL; + } +} + +void csr_free_roam_profile(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + + if (pSession->pCurRoamProfile) { + csr_release_profile(pMac, pSession->pCurRoamProfile); + cdf_mem_free(pSession->pCurRoamProfile); + pSession->pCurRoamProfile = NULL; + } +} + +void csr_free_connect_bss_desc(tpAniSirGlobal pMac, uint32_t sessionId) +{ + tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; + + if (pSession->pConnectBssDesc) { + cdf_mem_free(pSession->pConnectBssDesc); + pSession->pConnectBssDesc = NULL; + } +} + +tSirResultCodes csr_get_disassoc_rsp_status_code(tSirSmeDisassocRsp * + pSmeDisassocRsp) +{ + uint8_t *pBuffer = (uint8_t *) pSmeDisassocRsp; + uint32_t ret; + + pBuffer += (sizeof(uint16_t) + sizeof(uint16_t) + sizeof(tSirMacAddr)); + /* tSirResultCodes is an enum, assuming is 32bit */ + /* If we cannot make this assumption, use copymemory */ + cdf_get_u32(pBuffer, &ret); + + return (tSirResultCodes) ret; +} + +tSirResultCodes csr_get_de_auth_rsp_status_code(tSirSmeDeauthRsp *pSmeRsp) +{ + uint8_t *pBuffer = (uint8_t *) pSmeRsp; + uint32_t ret; + + pBuffer += + (sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint8_t) + + sizeof(uint16_t)); + /* tSirResultCodes is an enum, assuming is 32bit */ + /* If we cannot make this assumption, use copymemory */ + cdf_get_u32(pBuffer, &ret); + + return (tSirResultCodes) ret; +} + +tSirScanType csr_get_scan_type(tpAniSirGlobal pMac, uint8_t chnId) +{ + tSirScanType scanType = eSIR_PASSIVE_SCAN; + CHANNEL_STATE channelEnabledType; + + channelEnabledType = cds_get_channel_state(chnId); + if (CHANNEL_STATE_ENABLE == channelEnabledType) { + scanType = eSIR_ACTIVE_SCAN; + } + return scanType; +} + +uint8_t csr_to_upper(uint8_t ch) +{ + uint8_t chOut; + + if (ch >= 'a' && ch <= 'z') { + chOut = ch - 'a' + 'A'; + } else { + chOut = ch; + } + return chOut; +} + +tSirBssType csr_translate_bsstype_to_mac_type(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 csr_get_cfg_dot11_mode_from_csr_phy_mode(tCsrRoamProfile *pProfile, + eCsrPhyMode phyMode, + bool fProprietary) +{ + uint32_t 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; +} + +CDF_STATUS csr_get_regulatory_domain_for_country + (tpAniSirGlobal pMac, + uint8_t *pCountry, + v_REGDOMAIN_t *pDomainId, v_CountryInfoSource_t source) { + CDF_STATUS status = CDF_STATUS_E_INVAL; + CDF_STATUS cdf_status; + country_code_t countryCode; + v_REGDOMAIN_t domainId; + + if (pCountry) { + countryCode[0] = pCountry[0]; + countryCode[1] = pCountry[1]; + cdf_status = cds_get_reg_domain_from_country_code(&domainId, + countryCode, + source); + + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + if (pDomainId) { + *pDomainId = domainId; + } + status = CDF_STATUS_SUCCESS; + } else { + sms_log(pMac, LOGW, + FL + (" Couldn't find domain for country code %c%c"), + pCountry[0], pCountry[1]); + status = CDF_STATUS_E_INVAL; + } + } + + 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. */ +bool csr_match_country_code(tpAniSirGlobal pMac, uint8_t *pCountry, + tDot11fBeaconIEs *pIes) +{ + bool fRet = true; + + do { + if (!csr_is11d_supported(pMac)) { + break; + } + if (!pIes) { + sms_log(pMac, LOGE, FL(" No IEs")); + break; + } + + if (pCountry) { + uint32_t i; + + if (!pIes->Country.present) { + fRet = false; + break; + } + /* Convert the CountryCode characters to upper */ + for (i = 0; i < WNI_CFG_COUNTRY_CODE_LEN - 1; i++) { + pCountry[i] = csr_to_upper(pCountry[i]); + } + if (!cdf_mem_compare(pIes->Country.country, pCountry, + WNI_CFG_COUNTRY_CODE_LEN - 1)) { + fRet = false; + break; + } + } + } while (0); + + return fRet; +} + +CDF_STATUS csr_get_modify_profile_fields(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamModifyProfileFields * + pModifyProfileFields) +{ + + if (!pModifyProfileFields) { + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_copy(pModifyProfileFields, + &pMac->roam.roamSession[sessionId].connectedProfile. + modifyProfileFields, sizeof(tCsrRoamModifyProfileFields)); + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS csr_set_modify_profile_fields(tpAniSirGlobal pMac, uint32_t sessionId, + tCsrRoamModifyProfileFields * + pModifyProfileFields) +{ + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + + cdf_mem_copy(&pSession->connectedProfile.modifyProfileFields, + pModifyProfileFields, sizeof(tCsrRoamModifyProfileFields)); + + return CDF_STATUS_SUCCESS; +} + + +bool csr_is_set_key_allowed(tpAniSirGlobal pMac, uint32_t sessionId) +{ + bool fRet = 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, 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 no matter + * what the state is. + */ + sms_log(pMac, LOG2, + FL(" is not what it intends to. Must be revisit or removed")); + if ((NULL == pSession) + || (csr_is_conn_state_disconnected(pMac, sessionId) + && (pSession->pCurRoamProfile != NULL) + && (!(CSR_IS_INFRA_AP(pSession->pCurRoamProfile)))) + ) { + fRet = false; + } + + return fRet; +} + +/* no need to acquire lock for this basic function */ +uint16_t sme_chn_to_freq(uint8_t chanNum) +{ + int i; + + for (i = 0; i < NUM_RF_CHANNELS; i++) { + if (rf_channels[i].channelNum == chanNum) { + return rf_channels[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 csr_disconnect_all_active_sessions(tpAniSirGlobal pMac) +{ + uint8_t i; + + /* Disconnect all the active sessions */ + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i) + && !csr_is_conn_state_disconnected(pMac, i)) { + csr_roam_disconnect_internal(pMac, i, + eCSR_DISCONNECT_REASON_UNSPECIFIED); + } + } +} + +#ifdef FEATURE_WLAN_LFR +bool csr_is_channel_present_in_list(uint8_t *pChannelList, + int numChannels, uint8_t channel) +{ + int i = 0; + + /* Check for NULL pointer */ + if (!pChannelList || (numChannels == 0)) { + return false; + } + /* Look for the channel in the list */ + for (i = 0; (i < numChannels) && + (i < WNI_CFG_VALID_CHANNEL_LIST_LEN); i++) { + if (pChannelList[i] == channel) + return true; + } + + return false; +} + +CDF_STATUS csr_add_to_channel_list_front(uint8_t *pChannelList, + int numChannels, uint8_t channel) +{ + int i = 0; + + /* Check for NULL pointer */ + if (!pChannelList) + return CDF_STATUS_E_NULL_VALUE; + + /* Make room for the addition. (Start moving from the back.) */ + for (i = numChannels; i > 0; i--) { + pChannelList[i] = pChannelList[i - 1]; + } + + /* Now add the NEW channel...at the front */ + pChannelList[0] = channel; + + return CDF_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) +{ + WLAN_HOST_DIAG_EVENT_DEF(diag_event, host_event_wlan_pe_payload_type); + + cdf_mem_zero(&diag_event, sizeof(host_event_wlan_pe_payload_type)); + + /* diag_event.bssid is already all zeroes */ + diag_event.sme_state = sme_get_lim_sme_state(pmac); + diag_event.mlm_state = sme_get_lim_mlm_state(pmac); + diag_event.event_type = event_type; + diag_event.status = status; + diag_event.reason_code = reasoncode; + + WLAN_HOST_DIAG_EVENT_REPORT(&diag_event, EVENT_WLAN_PE); + return; +} +#endif diff --git a/core/sme/src/nan/nan_api.c b/core/sme/src/nan/nan_api.c new file mode 100644 index 000000000000..f2008ef03b71 --- /dev/null +++ b/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 "sms_debug.h" +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "nan_api.h" +#include "lim_api.h" +#include "cfg_api.h" + +/****************************************************************************** + * Function: sme_nan_register_callback + * + * 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_nan_register_callback(tHalHandle hHal, NanCallback callback) +{ + tpAniSirGlobal pMac = NULL; + + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("hHal is not valid")); + return; + } + pMac = PMAC_STRUCT(hHal); + pMac->sme.nanCallback = callback; +} + +/****************************************************************************** + * Function: sme_nan_request + * + * Description: + * This function gets called when HDD receives NAN vendor command + * from userspace + * + * Args: + * Nan Request structure ptr + * + * Returns: + * CDF_STATUS + *****************************************************************************/ +CDF_STATUS sme_nan_request(tpNanRequestReq input) +{ + cds_msg_t msg; + tpNanRequest data; + size_t data_len; + + data_len = sizeof(tNanRequest) + input->request_data_len; + data = cdf_mem_malloc(data_len); + + if (data == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failure")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(data, data_len); + data->request_data_len = input->request_data_len; + if (input->request_data_len) { + cdf_mem_copy(data->request_data, + input->request_data, input->request_data_len); + } + + msg.type = WMA_NAN_REQUEST; + msg.reserved = 0; + msg.bodyptr = data; + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL + ("Not able to post WMA_NAN_REQUEST message to WMA")); + cdf_mem_free(data); + return CDF_STATUS_SUCCESS; + } + + return CDF_STATUS_SUCCESS; +} + +/****************************************************************************** +* Function: sme_nan_event +* +* 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 WMA; includes NAN header +* +* Returns: +* CDF_STATUS +******************************************************************************/ +CDF_STATUS sme_nan_event(tHalHandle hHal, void *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + if (NULL == pMsg) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("msg ptr is NULL")); + status = CDF_STATUS_E_FAILURE; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + FL("SME: Received sme_nan_event")); + if (pMac->sme.nanCallback) { + pMac->sme.nanCallback(pMac->hHdd, + (tSirNanEvent *) pMsg); + } + } + + return status; +} diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c new file mode 100644 index 000000000000..aeb0a0db450b --- /dev/null +++ b/core/sme/src/oem_data/oem_data_api.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifdef FEATURE_OEM_DATA_SUPPORT +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + \file oem_data_api.c + + Implementation for the OEM DATA REQ/RSP interfaces. + ========================================================================== */ +#include "ani_global.h" +#include "oem_data_api.h" +#include "cds_mq.h" +#include "sme_inside.h" +#include "sms_debug.h" + +#include "csr_support.h" + +#include "host_diag_core_log.h" +#include "host_diag_core_event.h" + +/* --------------------------------------------------------------------------- + \fn oem_data_oem_data_req_open + \brief This function must be called before any API call to (OEM DATA REQ/RSP module) + \return CDF_STATUS + -------------------------------------------------------------------------------*/ + +CDF_STATUS oem_data_oem_data_req_open(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do { + /* initialize all the variables to null */ + cdf_mem_set(&(pMac->oemData), sizeof(tOemDataStruct), 0); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "oem_data_oem_data_req_open: Cannot allocate memory for the timer function"); + break; + } + } while (0); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oem_data_oem_data_req_close + \brief This function must be called before closing the csr module + \return CDF_STATUS + -------------------------------------------------------------------------------*/ + +CDF_STATUS oem_data_oem_data_req_close(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + do { + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + "oem_data_oem_data_req_close: Failed in oem_data_oem_data_req_close at StopTimers"); + break; + } + + /* initialize all the variables to null */ + cdf_mem_set(&(pMac->oemData), sizeof(tOemDataStruct), 0); + } while (0); + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + \fn oem_data_release_oem_data_req_command + \brief This function removes the oemDataCommand from the active list and + and frees up any memory occupied by this + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +void oem_data_release_oem_data_req_command(tpAniSirGlobal pMac, + tSmeCmd *pOemDataCmd, + eOemDataReqStatus oemDataReqStatus) +{ + + /* First take this command out of the active list */ + if (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, &pOemDataCmd->Link, LL_ACCESS_LOCK)) { + cdf_mem_set(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd), + 0); + + /* Now put this command back on the avilable command list */ + sme_release_command(pMac, pOemDataCmd); + } else { + sms_log(pMac, LOGE, + "OEM_DATA: **************** oem_data_release_oem_data_req_command cannot release the command"); + } +} + +/* --------------------------------------------------------------------------- + \fn oem_data_oem_data_req + \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 + \param callback - a callback function that is called upon finish + \param pContext - a pointer passed in for the callback + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, + uint8_t sessionId, + tOemDataReqConfig *oemDataReqConfig, + uint32_t *pOemDataReqID, + oem_data_oem_data_reqCompleteCallback callback, + void *pContext) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *pOemDataCmd = NULL; + + do { + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + status = CDF_STATUS_E_FAILURE; + break; + } + + pMac->oemData.oemDataReqConfig.sessionId = sessionId; + pMac->oemData.callback = callback; + pMac->oemData.pContext = pContext; + pMac->oemData.oemDataReqID = *(pOemDataReqID); + + cdf_mem_copy((void *)(pMac->oemData.oemDataReqConfig. + oemDataReq), + (void *)(oemDataReqConfig->oemDataReq), + OEM_DATA_REQ_SIZE); + + pMac->oemData.oemDataReqActive = false; + + pOemDataCmd = sme_get_command_buffer(pMac); + + /* fill up the command before posting it. */ + if (pOemDataCmd) { + pOemDataCmd->command = eSmeCommandOemDataReq; + pOemDataCmd->u.oemDataCmd.callback = callback; + pOemDataCmd->u.oemDataCmd.pContext = pContext; + pOemDataCmd->u.oemDataCmd.oemDataReqID = + pMac->oemData.oemDataReqID; + + /* set the oem data request */ + pOemDataCmd->u.oemDataCmd.oemDataReq.sessionId = + pMac->oemData.oemDataReqConfig.sessionId; + cdf_mem_copy((void *)(pOemDataCmd->u.oemDataCmd. + oemDataReq.oemDataReq), + (void *)(pMac->oemData.oemDataReqConfig. + oemDataReq), OEM_DATA_REQ_SIZE); + } else { + status = CDF_STATUS_E_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 */ + sme_push_command(pMac, pOemDataCmd, false); + + } while (0); + + if (!CDF_IS_STATUS_SUCCESS(status) && pOemDataCmd) { + oem_data_release_oem_data_req_command(pMac, pOemDataCmd, + eOEM_DATA_REQ_FAILURE); + pMac->oemData.oemDataReqActive = false; + } + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oem_data_send_mb_oem_data_req + \brief Request an OEM DATA REQ to be passed down to PE + \param pMac: + \param pOemDataReq: Pointer to the oem data request + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS oem_data_send_mb_oem_data_req(tpAniSirGlobal pMac, + tOemDataReq *pOemDataReq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirOemDataReq *pMsg; + uint16_t msgLen; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, pOemDataReq->sessionId); + + sms_log(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); + + msgLen = (uint16_t) (sizeof(tSirOemDataReq)); + + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) { + sms_log(pMac, LOGP, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set(pMsg, msgLen, 0); + pMsg->messageType = eWNI_SME_OEM_DATA_REQ; + pMsg->messageLen = msgLen; + cdf_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr.bytes, + sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->oemDataReq, pOemDataReq->oemDataReq, + OEM_DATA_REQ_SIZE); + sms_log(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); + status = cds_send_mb_message_to_mac(pMsg); + + sms_log(pMac, LOGW, "OEM_DATA: exiting Function %s", __func__); + + return status; +} + +/** + * oem_data_process_oem_data_req_command() - process oem data request command + * @pMac: Mac context + * @pOemDataReqCmd: pointer to oem data request command + * + * This function is called by the sme_process_command when the case hits + * eSmeCommandOemDataReq. + * + * Return: CDF_STATUS + */ +CDF_STATUS oem_data_process_oem_data_req_command(tpAniSirGlobal pMac, + tSmeCmd *pOemDataReqCmd) +{ + CDF_STATUS status = CDF_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 (CDF_STATUS_SUCCESS == oem_data_is_oem_data_req_allowed(pMac)) { + sms_log(pMac, LOG1, + FL("OEM_DATA REQ allowed in the current mode")); + pMac->oemData.oemDataReqActive = true; + status = oem_data_send_mb_oem_data_req(pMac, + &(pOemDataReqCmd->u.oemDataCmd.oemDataReq)); + } else { + sms_log(pMac, LOG1, + FL("OEM_DATA REQ not allowed in the current mode")); + status = CDF_STATUS_E_FAILURE; + } + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("OEM_DATA Failure, Release command")); + oem_data_release_oem_data_req_command(pMac, pOemDataReqCmd, + eOEM_DATA_REQ_INVALID_MODE); + pMac->oemData.oemDataReqActive = false; + } + + return status; +} + +/** + * sme_handle_oem_data_rsp() - processes the oem data response + * @hHal: Handle returned by mac_open. + * @pMsg: Pointer to the pSirOemDataRsp + * + * This function processes the oem data response obtained from the PE + * + * Return: CDF_STATUS. + */ +CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *pMsg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tSirOemDataRsp *pOemDataRsp = NULL; + uint32_t *msgSubType; + + pMac = PMAC_STRUCT(hHal); + + sms_log(pMac, LOG1, "%s: OEM_DATA Entering", __func__); + + do { + if (pMsg == NULL) { + sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__); + status = CDF_STATUS_E_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 sunsequent response to upper user layer. + */ + pEntry = + csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (pEntry) { + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandOemDataReq == pCommand->command) { + if (csr_ll_remove_entry + (&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) { + cdf_mem_set(&(pCommand->u.oemDataCmd), + sizeof(tOemDataCmd), 0); + sme_release_command(pMac, pCommand); + } + } + } + + pOemDataRsp = (tSirOemDataRsp *) pMsg; + + /* check if message is to be forwarded to oem application or not */ + msgSubType = (uint32_t *) (&pOemDataRsp->oemDataRsp[0]); + if (*msgSubType != OEM_MESSAGE_SUBTYPE_INTERNAL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: calling send_oem_data_rsp_msg, msgSubType(0x%x)", + __func__, *msgSubType); + if (pMac->oemData.oem_data_rsp_callback != NULL) { + pMac->oemData.oem_data_rsp_callback( + sizeof(tOemDataRsp), + &pOemDataRsp->oemDataRsp[0]); + } + } else + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: received internal oem data resp, msgSubType (0x%x)", + __func__, *msgSubType); + } while (0); + + return status; +} + +/* --------------------------------------------------------------------------- + \fn oem_data_is_oem_data_req_allowed + \brief This function checks if OEM DATA REQs can be performed in the + current driver state + \return CDF_STATUS + -------------------------------------------------------------------------------*/ +CDF_STATUS oem_data_is_oem_data_req_allowed(tHalHandle hHal) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t 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 (csr_is_conn_state_ibss(pMac, sessionId) + || csr_is_btamp(pMac, sessionId)) { + /* co-exist with IBSS or BT-AMP mode is not supported */ + sms_log(pMac, LOGW, + "OEM DATA REQ is not allowed due to IBSS|BTAMP exist in session %d", + sessionId); + status = CDF_STATUS_CSR_WRONG_STATE; + break; + } + } + } + + sms_log(pMac, LOG1, "Exiting oem_data_is_oem_data_req_allowed with status %d", + status); + + return (status); +} + +#endif /*FEATURE_OEM_DATA_SUPPORT */ diff --git a/core/sme/src/p2p/p2p_api.c b/core/sme/src/p2p/p2p_api.c new file mode 100644 index 000000000000..ec8b742263c8 --- /dev/null +++ b/core/sme/src/p2p/p2p_api.c @@ -0,0 +1,419 @@ +/* + * 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 "sme_api.h" +#include "sms_debug.h" +#include "csr_inside_api.h" +#include "sme_inside.h" +#include "p2p_api.h" +#include "lim_api.h" +#include "cfg_api.h" +#include "wma.h" + +/*------------------------------------------------------------------ + * + * handle SME remain on channel request. + * + *------------------------------------------------------------------*/ + +CDF_STATUS p2p_process_remain_on_channel_cmd(tpAniSirGlobal pMac, + tSmeCmd *p2pRemainonChn) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tSirRemainOnChnReq *pMsg; + uint32_t len; + tCsrRoamSession *pSession = + CSR_GET_SESSION(pMac, p2pRemainonChn->sessionId); + + if (!pSession) { + sms_log(pMac, LOGE, FL(" session %d not found "), + p2pRemainonChn->sessionId); + goto error; + } + + if (!pSession->sessionActive) { + sms_log(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 */ + sms_log(pMac, LOGE, FL(" Message length is very large, %d"), + len); + goto error; + } + + pMsg = cdf_mem_malloc(len); + if (NULL == pMsg) + goto error; + else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s call", + __func__); + cdf_mem_set(pMsg, sizeof(tSirRemainOnChnReq), 0); + pMsg->messageType = eWNI_SME_REMAIN_ON_CHANNEL_REQ; + pMsg->length = (uint16_t) len; + cdf_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr.bytes, + 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; + pMsg->scan_id = p2pRemainonChn->u.remainChlCmd.scan_id; + if (pMac->p2pContext.probeRspIeLength) + cdf_mem_copy((void *)pMsg->probeRspIe, + (void *)pMac->p2pContext.probeRspIe, + pMac->p2pContext.probeRspIeLength); + status = cds_send_mb_message_to_mac(pMsg); + } +error: + if (CDF_STATUS_E_FAILURE == status) + csr_release_roc_req_cmd(pMac); + return status; +} + +/*------------------------------------------------------------------ + * + * handle LIM remain on channel rsp: Success/failure. + * + *------------------------------------------------------------------*/ + +CDF_STATUS sme_remain_on_chn_rsp(tpAniSirGlobal pMac, uint8_t *pMsg) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + bool fFound; + remainOnChanCallback callback = NULL; + struct sir_roc_rsp *rsp = (struct sir_roc_rsp *)pMsg; + + csr_get_active_scan_entry(pMac, rsp->scan_id, &pEntry); + if (!pEntry) { + sms_log(pMac, LOGE, FL("No cmd found in active list.")); + return status; + } + + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandRemainOnChannel != pCommand->command) + return status; + + callback = pCommand->u.remainChlCmd.callback; + if (callback) + callback(pMac, pCommand->u.remainChlCmd.callbackCtx, + rsp->status, rsp->scan_id); + + fFound = csr_ll_remove_entry(&pMac->sme.smeScanCmdActiveList, pEntry, + LL_ACCESS_LOCK); + if (fFound) { + /* Now put this command back on the avilable command list */ + sme_release_command(pMac, pCommand); + } + sme_process_pending_queue(pMac); + return status; +} + +/*------------------------------------------------------------------ + * + * Handle the Mgmt frm ind from LIM and forward to HDD. + * + *------------------------------------------------------------------*/ + +CDF_STATUS sme_mgmt_frm_ind(tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo pRoamInfo = { 0 }; + uint8_t i = 0; + uint32_t SessionId = pSmeMgmtFrm->sessionId; + + pRoamInfo.nFrameLength = + pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd); + pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; + pRoamInfo.frameType = pSmeMgmtFrm->frameType; + pRoamInfo.rxChan = pSmeMgmtFrm->rxChan; + pRoamInfo.rxRssi = pSmeMgmtFrm->rxRssi; + if (CSR_IS_SESSION_ANY(SessionId)) { + for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { + if (CSR_IS_SESSION_VALID(pMac, i)) { + SessionId = i; + break; + } + } + } + + if (i == CSR_ROAM_SESSION_MAX) { + sms_log(pMac, LOGE, FL("No valid sessions found.")); + return CDF_STATUS_E_FAILURE; + } + /* forward the mgmt frame to HDD */ + csr_roam_call_callback(pMac, SessionId, &pRoamInfo, 0, + eCSR_ROAM_INDICATE_MGMT_FRAME, 0); + + return status; +} + +/*------------------------------------------------------------------ + * + * Handle the remain on channel ready indication from PE + * + *------------------------------------------------------------------*/ + +CDF_STATUS sme_remain_on_chn_ready(tHalHandle hHal, uint8_t *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tListElem *pEntry = NULL; + tSmeCmd *pCommand = NULL; + tCsrRoamInfo RoamInfo; + struct sir_roc_rsp *rsp = (struct sir_roc_rsp *)pMsg; + + csr_get_active_scan_entry(pMac, rsp->scan_id, &pEntry); + if (!pEntry) { + sms_log(pMac, LOGE, FL("No cmd found in active list.")); + return status; + } + sms_log(pMac, LOG1, + FL("Ready Ind %d %d"), rsp->session_id, rsp->scan_id); + pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link); + if (eSmeCommandRemainOnChannel == pCommand->command) { + RoamInfo.roc_scan_id = rsp->scan_id; + /* forward the indication to HDD */ + RoamInfo.pRemainCtx = pCommand->u.remainChlCmd.callbackCtx; + csr_roam_call_callback(pMac, rsp->session_id, + &RoamInfo, 0, + eCSR_ROAM_REMAIN_CHAN_READY, 0); + } + + return status; +} + +CDF_STATUS sme_send_action_cnf(tHalHandle hHal, uint8_t *pMsg) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamInfo RoamInfo; + tSirSmeRsp *pSmeRsp = (tSirSmeRsp *) pMsg; + + /* forward the indication to HDD */ + /* RoamInfo can be passed as NULL....todo */ + csr_roam_call_callback(pMac, pSmeRsp->sessionId, &RoamInfo, 0, + eCSR_ROAM_SEND_ACTION_CNF, + (pSmeRsp->statusCode == eSIR_SME_SUCCESS) ? 0 : + eCSR_ROAM_RESULT_SEND_ACTION_FAIL); + return status; +} + +CDF_STATUS sme_p2p_open(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + CDF_STATUS status = CDF_STATUS_SUCCESS; + + /* If static structure is too big, Need to change this function to allocate memory dynamically */ + cdf_mem_zero(&pMac->p2pContext, sizeof(tp2pContext)); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + sme_p2p_close(hHal); + } + + return status; +} + +CDF_STATUS p2p_stop(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->p2pContext.probeRspIe) { + cdf_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIe = NULL; + } + + pMac->p2pContext.probeRspIeLength = 0; + + return CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_p2p_close(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (pMac->p2pContext.probeRspIe) { + cdf_mem_free(pMac->p2pContext.probeRspIe); + pMac->p2pContext.probeRspIe = NULL; + } + + pMac->p2pContext.probeRspIeLength = 0; + + return CDF_STATUS_SUCCESS; +} + +tSirRFBand get_rf_band(uint8_t 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 p2p_remain_on_channel + \brief API to post the remain on channel command. + \param hHal - The handle returned by mac_open. + \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 CDF_STATUS + + -------------------------------------------------------------------------------*/ +CDF_STATUS p2p_remain_on_channel(tHalHandle hHal, uint8_t sessionId, + uint8_t channel, uint32_t duration, + remainOnChanCallback callback, + void *pContext, uint8_t isP2PProbeReqAllowed, + uint32_t scan_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSmeCmd *pRemainChlCmd = NULL; + uint32_t phyMode; + + pRemainChlCmd = sme_get_command_buffer(pMac); + if (pRemainChlCmd == NULL) + return CDF_STATUS_E_FAILURE; + + if (SIR_BAND_5_GHZ == get_rf_band(channel)) { + phyMode = WNI_CFG_PHY_MODE_11A; + } else { + phyMode = WNI_CFG_PHY_MODE_11G; + } + + cfg_set_int(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; + pRemainChlCmd->u.remainChlCmd.scan_id = scan_id; + + /* Put it at the head of the Q if we just finish finding the peer and ready to send a frame */ + status = csr_queue_sme_command(pMac, pRemainChlCmd, false); + } while (0); + + sms_log(pMac, LOGW, "exiting function %s", __func__); + + return (status); +} + +CDF_STATUS p2p_send_action(tHalHandle hHal, uint8_t sessionId, + const uint8_t *pBuf, uint32_t len, uint16_t wait, + bool noack, uint16_t channel_freq) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirMbMsgP2p *pMsg; + uint16_t msgLen; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + " %s sends action frame", __func__); + msgLen = (uint16_t) ((sizeof(tSirMbMsgP2p)) + len); + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = eWNI_SME_SEND_ACTION_FRAME_IND; + pMsg->msgLen = msgLen; + pMsg->sessionId = sessionId; + pMsg->noack = noack; + pMsg->channel_freq = channel_freq; + pMsg->wait = (uint16_t) wait; + cdf_mem_copy(pMsg->data, pBuf, len); + status = cds_send_mb_message_to_mac(pMsg); + } + return (status); +} + +CDF_STATUS p2p_cancel_remain_on_channel(tHalHandle hHal, + uint8_t sessionId, uint32_t scan_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirMbMsgP2p *pMsg; + uint16_t msgLen; + + /* Need to check session ID to support concurrency */ + + msgLen = (uint16_t) (sizeof(tSirMbMsgP2p)); + pMsg = cdf_mem_malloc(msgLen); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set((void *)pMsg, msgLen, 0); + pMsg->type = eWNI_SME_ABORT_REMAIN_ON_CHAN_IND; + pMsg->msgLen = msgLen; + pMsg->sessionId = sessionId; + pMsg->scan_id = scan_id; + status = cds_send_mb_message_to_mac(pMsg); + } + + return (status); +} + +CDF_STATUS p2p_set_ps(tHalHandle hHal, tP2pPsConfig *pNoA) +{ + tpP2pPsConfig pNoAParam; + tSirMsgQ msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + pNoAParam = cdf_mem_malloc(sizeof(tP2pPsConfig)); + if (NULL == pNoAParam) + status = CDF_STATUS_E_NOMEM; + else { + cdf_mem_set(pNoAParam, sizeof(tP2pPsConfig), 0); + cdf_mem_copy(pNoAParam, pNoA, sizeof(tP2pPsConfig)); + msg.type = eWNI_SME_UPDATE_NOA; + msg.bodyval = 0; + msg.bodyptr = pNoAParam; + lim_post_msg_api(pMac, &msg); + } + return status; +} diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c new file mode 100644 index 000000000000..7506fab4864d --- /dev/null +++ b/core/sme/src/qos/sme_qos.c @@ -0,0 +1,7834 @@ +/* + * 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 sme_qos.c + + \brief implementation for SME QoS APIs + + ========================================================================*/ +/* $Header$ */ +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ + +#include "ani_global.h" + +#include "sme_inside.h" +#include "host_diag_core_event.h" +#include "host_diag_core_log.h" + +#ifdef WLAN_FEATURE_VOWIFI_11R +#include "sms_debug.h" +#include "utils_parser.h" +#endif +#include "sme_power_save_api.h" + +#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 flowlist (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_qos_u_pto_ac_map[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_qos_a_cto_up_map[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 */ + uint8_t sessionId; + uint8_t tspec_mask; + sme_QosReasonType reason; + uint32_t QosFlowID; + sme_QosEdcaAcType ac_type; + sme_QosWmmTspecInfo QoSInfo; + void *HDDcontext; + sme_QosCallback QoSCallback; + bool hoRenewal; /* 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 */ +} sme_QosFlowInfoEntry; +/*--------------------------------------------------------------------------- + DESCRIPTION + SME QoS module's setup request cmd related information structure. + ---------------------------------------------------------------------------*/ +typedef struct sme_qos_setupCmdInfo_s { + uint32_t QosFlowID; + sme_QosWmmTspecInfo QoSInfo; + void *HDDcontext; + sme_QosCallback QoSCallback; + sme_QosWmmUpType UPType; + bool hoRenewal; /* 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 */ +} sme_qos_setupCmdInfo; +/*--------------------------------------------------------------------------- + DESCRIPTION + SME QoS module's modify cmd related information structure. + ---------------------------------------------------------------------------*/ +typedef struct sme_QosModifyCmdInfo_s { + uint32_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 { + uint8_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 { + uint32_t QosFlowID; +} sme_QosReleaseCmdInfo; +/*--------------------------------------------------------------------------- + DESCRIPTION + SME QoS module's buffered cmd related information structure. + ---------------------------------------------------------------------------*/ +typedef struct sme_QosCmdInfo_s { + sme_QosCmdType command; + tpAniSirGlobal pMac; + uint8_t sessionId; + union { + sme_qos_setupCmdInfo 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 { + uint8_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]; + bool 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 */ + uint8_t tspec_mask_status; /* status showing if both the indices are in use */ + uint8_t tspec_pending; /* tspec negotiation going on for which index */ + bool hoRenewal; /* 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 */ +#ifdef WLAN_FEATURE_VOWIFI_11R + uint8_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 */ + uint8_t sessionId; + /* is the session currently active */ + bool 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 */ + uint8_t apsdMask; + /* association information for this session */ + sme_QosAssocInfo assocInfo; + /* ID assigned to our reassoc request */ + uint32_t roamID; + /* maintaining a powersave status in QoS module, to be fed back to PMC at */ + /* times through the sme_qos_pmc_check_routine */ + bool readyForPowerSave; + /* are we in the process of handing off to a different AP */ + bool handoffRequested; + /* following reassoc or AddTS has UAPSD already been requested from PMC */ + bool uapsdAlreadyRequested; + /* commands that are being buffered for this session */ + tDblLinkList bufferedCommandList; + +#ifdef WLAN_FEATURE_VOWIFI_11R + bool 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 { + uint32_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 { + uint8_t sessionId; + uint8_t index; + sme_QosSearchKey key; + sme_QosWmmDirType direction; + uint8_t tspec_mask; +} sme_QosSearchInfo; +/*--------------------------------------------------------------------------- + DESCRIPTION + SME QoS module's internal control block. + ---------------------------------------------------------------------------*/ +struct sme_qos_cb_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 */ + uint32_t nextFlowId; + /* counter for assigning Dialog Tokens */ + uint8_t nextDialogToken; +} sme_qos_cb; +typedef CDF_STATUS (*sme_QosProcessSearchEntry)(tpAniSirGlobal pMac, + tListElem *pEntry); + +sme_QosStatusType sme_qos_internal_setup_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosCallback QoSCallback, + void *HDDcontext, + sme_QosWmmUpType UPType, + uint32_t QosFlowID, + bool buffered_cmd, bool hoRenewal); +sme_QosStatusType sme_qos_internal_modify_req(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, + uint32_t QosFlowID, + bool buffered_cmd); +sme_QosStatusType sme_qos_internal_release_req(tpAniSirGlobal pMac, + uint32_t QosFlowID, + bool buffered_cmd); +sme_QosStatusType sme_qos_setup(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pTspec_Info, + sme_QosEdcaAcType ac); +CDF_STATUS sme_qos_add_ts_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pTspec_Info, + sme_QosEdcaAcType ac); +CDF_STATUS sme_qos_del_ts_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosEdcaAcType ac, uint8_t tspec_mask); +CDF_STATUS sme_qos_process_add_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf); +CDF_STATUS sme_qos_process_del_ts_ind(tpAniSirGlobal pMac, void *pMsgBuf); +CDF_STATUS sme_qos_process_del_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf); +CDF_STATUS sme_qos_process_assoc_complete_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_reassoc_req_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_reassoc_success_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info); +CDF_STATUS sme_qos_process_reassoc_failure_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info); +CDF_STATUS sme_qos_process_disconnect_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_join_req_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_handoff_assoc_req_ev(tpAniSirGlobal pMac, + uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_handoff_success_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info); +CDF_STATUS sme_qos_process_handoff_failure_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info); +#ifdef WLAN_FEATURE_VOWIFI_11R +CDF_STATUS sme_qos_process_preauth_success_ind(tpAniSirGlobal pMac, + uint8_t sessionId, + void *pEvent_info); +CDF_STATUS sme_qos_process_set_key_success_ind(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info); +CDF_STATUS sme_qos_process_aggr_qos_rsp(tpAniSirGlobal pMac, void *pMsgBuf); +CDF_STATUS sme_qos_ft_aggr_qos_req(tpAniSirGlobal pMac, uint8_t sessionId); +#endif +CDF_STATUS sme_qos_process_add_ts_success_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirAddtsRspInfo *pRsp); +CDF_STATUS sme_qos_process_add_ts_failure_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirAddtsRspInfo *pRsp); +CDF_STATUS sme_qos_aggregate_params(sme_QosWmmTspecInfo *pInput_Tspec_Info, + sme_QosWmmTspecInfo *pCurrent_Tspec_Info, + sme_QosWmmTspecInfo *pUpdated_Tspec_Info); +static CDF_STATUS sme_qos_update_params(uint8_t sessionId, + sme_QosEdcaAcType ac, + uint8_t tspec_mask, + sme_QosWmmTspecInfo *pTspec_Info); +sme_QosWmmUpType sme_qos_ac_to_up(sme_QosEdcaAcType ac); +sme_QosEdcaAcType sme_qos_up_to_ac(sme_QosWmmUpType up); +bool sme_qos_is_acm(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes); +tListElem *sme_qos_find_in_flow_list(sme_QosSearchInfo search_key); +CDF_STATUS sme_qos_find_all_in_flow_list(tpAniSirGlobal pMac, + sme_QosSearchInfo search_key, + sme_QosProcessSearchEntry fnp); +static void sme_qos_state_transition(uint8_t sessionId, + sme_QosEdcaAcType ac, + sme_QosStates new_state); +CDF_STATUS sme_qos_buffer_cmd(sme_QosCmdInfo *pcmd, bool insert_head); +static CDF_STATUS sme_qos_process_buffered_cmd(uint8_t sessionId); +CDF_STATUS sme_qos_save_assoc_info(sme_QosSessionInfo *pSession, + sme_QosAssocInfo *pAssoc_info); +CDF_STATUS sme_qos_setup_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +CDF_STATUS sme_qos_modification_notify_fnp(tpAniSirGlobal pMac, + tListElem *pEntry); +CDF_STATUS sme_qos_modify_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +CDF_STATUS sme_qos_del_ts_ind_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +CDF_STATUS sme_qos_reassoc_success_ev_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +CDF_STATUS sme_qos_add_ts_failure_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +CDF_STATUS sme_qos_add_ts_success_fnp(tpAniSirGlobal pMac, tListElem *pEntry); +static bool sme_qos_is_rsp_pending(uint8_t sessionId, sme_QosEdcaAcType ac); +static bool sme_qos_is_uapsd_active(void); + +void sme_qos_pmc_offload_start_uapsd_callback(void *callbackContext, + uint32_t sessionId, CDF_STATUS status); +bool sme_qos_pmc_offload_check_routine(void *callbackContext, uint32_t sessionId); + +static CDF_STATUS sme_qos_buffer_existing_flows(tpAniSirGlobal pMac, + uint8_t sessionId); +static CDF_STATUS sme_qos_delete_existing_flows(tpAniSirGlobal pMac, + uint8_t sessionId); +static void sme_qos_cleanup_ctrl_blk_for_handoff(tpAniSirGlobal pMac, + uint8_t sessionId); +static CDF_STATUS sme_qos_delete_buffered_requests(tpAniSirGlobal pMac, + uint8_t sessionId); +bool sme_qos_validate_requested_params(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, + uint8_t sessionId); + +extern CDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme); +extern CDF_STATUS sme_release_global_lock(tSmeStruct *psSme); +static CDF_STATUS qos_issue_command(tpAniSirGlobal pMac, uint8_t sessionId, + eSmeCommandType cmdType, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosEdcaAcType ac, uint8_t tspec_mask); +/* + sme_qos_re_request_add_ts to re-send AddTS for the combined QoS request + */ +static sme_QosStatusType sme_qos_re_request_add_ts(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosEdcaAcType ac, + uint8_t tspecMask); +static void sme_qos_init_a_cs(tpAniSirGlobal pMac, uint8_t sessionId); +static CDF_STATUS sme_qos_request_reassoc(tpAniSirGlobal pMac, uint8_t sessionId, + tCsrRoamModifyProfileFields * + pModFields, bool fForce); +static uint32_t sme_qos_assign_flow_id(void); +static uint8_t sme_qos_assign_dialog_token(void); +static CDF_STATUS sme_qos_update_tspec_mask(uint8_t sessionId, + sme_QosSearchInfo search_key, + uint8_t new_tspec_mask); + +/* External APIs definitions */ + +/** + * sme_qos_open() - called to initialize SME QoS module. + * @pMac: global MAC context + * + * This function must be called before any API call to + * SME QoS module. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_open(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + uint8_t sessionId; + CDF_STATUS status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: initializing SME-QoS module", __func__, __LINE__); + /* init the control block */ + /* (note that this will make all sessions invalid) */ + cdf_mem_zero(&sme_qos_cb, sizeof(sme_qos_cb)); + sme_qos_cb.pMac = pMac; + sme_qos_cb.nextFlowId = SME_QOS_MIN_FLOW_ID; + sme_qos_cb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN; + /* init flow list */ + status = csr_ll_open(pMac->hHdd, &sme_qos_cb.flow_list); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: %d: cannot initialize Flow List", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) { + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pSession->sessionId = sessionId; + /* initialize the session's per-AC information */ + sme_qos_init_a_cs(pMac, sessionId); + /* initialize the session's buffered command list */ + status = csr_ll_open(pMac->hHdd, &pSession->bufferedCommandList); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: %d: cannot initialize cmd list for session %d", + __func__, __LINE__, sessionId); + return CDF_STATUS_E_FAILURE; + } + pSession->readyForPowerSave = true; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: done initializing SME-QoS module", + __func__, __LINE__); + return CDF_STATUS_SUCCESS; +} + +/* -------------------------------------------------------------------------- + \brief sme_qos_close() - 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_qos_open. + \param pMac - Pointer to the global MAC parameter structure. + + \return CDF_STATUS + ----------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_close(tpAniSirGlobal pMac) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + uint8_t sessionId; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: closing down SME-QoS", __func__, __LINE__); + + /* cleanup control block */ + /* close the flow list */ + csr_ll_close(&sme_qos_cb.flow_list); + /* shut down all of the sessions */ + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) { + pSession = &sme_qos_cb.sessionInfo[sessionId]; + if (pSession == NULL) + continue; + + sme_qos_init_a_cs(pMac, sessionId); + /* this session doesn't require UAPSD */ + pSession->apsdMask = 0; + + pSession->uapsdAlreadyRequested = false; + pSession->handoffRequested = false; + pSession->readyForPowerSave = true; + pSession->roamID = 0; + /* need to clean up buffered req */ + sme_qos_delete_buffered_requests(pMac, sessionId); + /* need to clean up flows */ + sme_qos_delete_existing_flows(pMac, sessionId); + + /* Clean up the assoc info if already allocated */ + if (pSession->assocInfo.pBssDesc) { + cdf_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + /* close the session's buffered command list */ + csr_ll_close(&pSession->bufferedCommandList); + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + sme_qos_state_transition(sessionId, ac, SME_QOS_CLOSED); + } + pSession->sessionActive = false; + pSession->readyForPowerSave = true; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: closed down QoS", __func__, __LINE__); + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_setup_req() - The SME QoS API exposed to HDD to request for QoS + * on a particular AC. + * @hHal: The handle returned by mac_open. + * @sessionId: sessionId returned by sme_open_session. + * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + * related info as defined above, provided by HDD + * @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 + * @HDDcontext: A cookie passed by HDD to be used by SME during any QoS + * notification (through the callabck) to HDD + * @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 + * @pQosFlowID: Identification per flow running on each AC generated by + * SME. It is only meaningful if the QoS setup for the flow is + * successful + * 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. + * Return: CDF_STATUS_SUCCESS - Setup is successful. + * Other status means Setup request failed + */ +sme_QosStatusType sme_qos_setup_req(tHalHandle hHal, uint32_t sessionId, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosCallback QoSCallback, + void *HDDcontext, + sme_QosWmmUpType UPType, + uint32_t *pQosFlowID) +{ + sme_QosSessionInfo *pSession; + CDF_STATUS lock_status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + sme_QosStatusType status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Setup requested by client on session %d", + __func__, __LINE__, sessionId); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(lock_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_cb.sessionInfo[sessionId]; + if (!pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_assign_flow_id(); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_internal_setup_req(pMac, (uint8_t) sessionId, + pQoSInfo, QoSCallback, + HDDcontext, UPType, + *pQosFlowID, false, + false); + } + } + sme_release_global_lock(&pMac->sme); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS setup return status on session %d is %d", + __func__, __LINE__, sessionId, status); + return status; +} + +/** + * sme_qos_modify_req() - The SME QoS API exposed to HDD to request for + * modification of certain QoS params on a flow running on a particular AC. + * @hHal: The handle returned by mac_open. + * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + * related info as defined above, provided by HDD + * @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 + * + * 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 succesful 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. + * + * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful. + * Other status means request failed + */ +sme_QosStatusType sme_qos_modify_req(tHalHandle hHal, + sme_QosWmmTspecInfo *pQoSInfo, + uint32_t QosFlowID) +{ + CDF_STATUS lock_status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + sme_QosStatusType status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Modify requested by client for Flow %d", + __func__, __LINE__, QosFlowID); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(lock_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_internal_modify_req(pMac, pQoSInfo, QosFlowID, false); + sme_release_global_lock(&pMac->sme); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Modify return status on Flow %d is %d", + __func__, __LINE__, QosFlowID, status); + return status; +} + +/** + * sme_qos_release_req() - The SME QoS API exposed to HDD to request for + * releasing a QoS flow running on a particular AC. + * + * @hHal: The handle returned by mac_open. + * @QosFlowID: Identification per flow running on each AC generated by SME + * It is only meaningful if the QoS setup for the flow is successful + * + * This function should be called only if a QoS is set up with a valid FlowID. + * HDD sould invoke this API only if an explicit request for QoS release has + * come from Application + * + * Return: CDF_STATUS_SUCCESS - Release is successful. + */ +sme_QosStatusType sme_qos_release_req(tHalHandle hHal, uint32_t QosFlowID) +{ + CDF_STATUS lock_status = CDF_STATUS_E_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + sme_QosStatusType status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release requested by client for Flow %d", + __func__, __LINE__, QosFlowID); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(lock_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_internal_release_req(pMac, QosFlowID, false); + sme_release_global_lock(&pMac->sme); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release return status on Flow %d is %d", + __func__, __LINE__, QosFlowID, status); + return status; +} + +void qos_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + cdf_mem_zero(&pCommand->u.qosCmd, sizeof(tGenericQosCmd)); + sme_release_command(pMac, pCommand); +} + +/** + * sme_qos_msg_processor() - Processes QOS messages + * @mac_ctx: Pointer to the global MAC parameter structure. + * @msg_type: the type of msg passed by PE as defined in wni_api.h + * @msg: a pointer to a buffer that maps to various structures bases. + * + * sme_process_msg() calls this function for the messages that + * are handled by SME QoS module. + * + * Return: CDF_STATUS enumeration. + */ +CDF_STATUS sme_qos_msg_processor(tpAniSirGlobal mac_ctx, + uint16_t msg_type, void *msg) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tListElem *entry = NULL; + tSmeCmd *command; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL(" msg = %d for QoS"), msg_type); + /* switch on the msg type & make the state transition accordingly */ + switch (msg_type) { + case eWNI_SME_ADDTS_RSP: + entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (NULL == entry) + break; + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (eSmeCommandAddTs == command->command) { + status = sme_qos_process_add_ts_rsp(mac_ctx, msg); + if (csr_ll_remove_entry + (&mac_ctx->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK)) { + qos_release_command(mac_ctx, command); + } + sme_process_pending_queue(mac_ctx); + } + break; + case eWNI_SME_DELTS_RSP: + entry = + csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (NULL == entry) + break; + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (eSmeCommandDelTs == command->command) { + status = sme_qos_process_del_ts_rsp(mac_ctx, msg); + if (csr_ll_remove_entry + (&mac_ctx->sme.smeCmdActiveList, entry, + LL_ACCESS_LOCK)) { + qos_release_command(mac_ctx, command); + } + sme_process_pending_queue(mac_ctx); + } + break; + case eWNI_SME_DELTS_IND: + status = sme_qos_process_del_ts_ind(mac_ctx, msg); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case eWNI_SME_FT_AGGR_QOS_RSP: + status = sme_qos_process_aggr_qos_rsp(mac_ctx, msg); + break; +#endif + default: + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("unknown msg type = %d"), + msg_type); + break; + } + return status; +} + +/** + * sme_qos_validate_params() - validate SME QOS parameters. + * @pMac: Pointer to the global MAC parameter structure. + * @pBssDesc: Pointer to the BSS Descriptor information passed down by + * CSR to PE while issuing the Join request + * + * The SME QoS API exposed to CSR to validate AP + * capabilities regarding QoS support & any other QoS parameter validation. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_validate_params(tpAniSirGlobal pMac, + tSirBssDescription *pBssDesc) +{ + tDot11fBeaconIEs *pIes = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: validation for QAP & APSD", __func__, __LINE__); + do { + if (!CDF_IS_STATUS_SUCCESS( + csr_get_parsed_bss_description_ies( + pMac, pBssDesc, &pIes))) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: csr_get_parsed_bss_description_ies() failed", + __func__, __LINE__); + break; + } + /* check if the AP is QAP & it supports APSD */ + if (!CSR_IS_QOS_BSS(pIes)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: AP doesn't support APSD", + __func__, __LINE__); + break; + } + status = CDF_STATUS_SUCCESS; + } while (0); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: validated with status = %d", + __func__, __LINE__, status); + if (pIes) { + cdf_mem_free(pIes); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_csr_event_ind() - The QoS sub-module in SME expects notifications + from CSR when certain events occur as mentioned in sme_qos_csr_event_indType. + \param pMac - Pointer to the global MAC parameter structure. + \param ind - The event occurred of type sme_qos_csr_event_indType. + \param pEvent_info - Information related to the event + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_csr_event_ind(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_qos_csr_event_indType ind, void *pEvent_info) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_process_assoc_complete_ev(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_REASSOC_REQ: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_reassoc_req_ev(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_REASSOC_COMPLETE: + /* expecting assoc info in pEvent_info */ + status = + sme_qos_process_reassoc_success_ev(pMac, sessionId, + pEvent_info); + break; + case SME_QOS_CSR_REASSOC_FAILURE: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_reassoc_failure_ev(pMac, sessionId, + pEvent_info); + break; + case SME_QOS_CSR_DISCONNECT_REQ: + case SME_QOS_CSR_DISCONNECT_IND: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_disconnect_ev(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_JOIN_REQ: + /* nothing expected in pEvent_info */ + status = sme_qos_process_join_req_ev(pMac, sessionId, pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_ASSOC_REQ: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_handoff_assoc_req_ev(pMac, sessionId, + pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_COMPLETE: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_handoff_success_ev(pMac, sessionId, + pEvent_info); + break; + case SME_QOS_CSR_HANDOFF_FAILURE: + /* nothing expected in pEvent_info */ + status = + sme_qos_process_handoff_failure_ev(pMac, sessionId, + pEvent_info); + break; +#ifdef WLAN_FEATURE_VOWIFI_11R + case SME_QOS_CSR_PREAUTH_SUCCESS_IND: + status = + sme_qos_process_preauth_success_ind(pMac, sessionId, + pEvent_info); + break; +#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) + case SME_QOS_CSR_SET_KEY_SUCCESS_IND: + status = + sme_qos_process_set_key_success_ind(pMac, sessionId, + pEvent_info); + break; +#endif +#endif + default: + /* Err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On Session %d Unknown Event %d received from CSR", + __func__, __LINE__, sessionId, ind); + break; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On Session %d processed Event %d with status %d", + __func__, __LINE__, sessionId, ind, status); + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_get_acm_mask() - 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_qos_csr_event_indType. + + \return a bit mask indicating for which ACs AP has ACM set to 1 + + \sa + + --------------------------------------------------------------------------*/ +uint8_t sme_qos_get_acm_mask(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) +{ + sme_QosEdcaAcType ac; + uint8_t acm_mask = 0; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_is_acm(pMac, pSirBssDesc, ac, pIes)) { + acm_mask = acm_mask | (1 << (SME_QOS_EDCA_AC_VO - ac)); + } + + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: mask is %d", __func__, __LINE__, acm_mask); + return acm_mask; +} + +/* Internal function definitions */ + +/** + * sme_qos_internal_setup_req() - The SME QoS internal setup request handling + * function. + * + * @pMac: Pointer to the global MAC parameter structure. + * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + * related info as defined above, provided by HDD + * @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 + * @HDDcontext: A cookie passed by HDD to be used by SME during any QoS + * notification (through the callabck) to HDD + * @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 + * @QosFlowID: Identification per flow running on each AC generated by + * SME. It is only meaningful if the QoS setup for the flow is + * successful + * @buffered_cmd: tells us if the cmd was a buffered one or fresh from + * client + * + * 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. + * + * Return: CDF_STATUS_SUCCESS - Setup is successful. + * Other status means Setup request failed + */ +sme_QosStatusType sme_qos_internal_setup_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosCallback QoSCallback, + void *HDDcontext, + sme_QosWmmUpType UPType, + uint32_t QosFlowID, + bool buffered_cmd, bool 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; + uint8_t tmask = 0; + uint8_t new_tmask = 0; + sme_QosSearchInfo search_key; + CDF_STATUS hstatus; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for flow %d", + __func__, __LINE__, sessionId, QosFlowID); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + /* if caller sent an empty TSPEC, fill up with the default one */ + if (!pQoSInfo) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_up_to_ac(UPType); + if (SME_QOS_EDCA_AC_MAX == ac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_cb.def_QoSInfo[ac]; + } else { + /* find the AC */ + ac = sme_qos_up_to_ac(pQoSInfo->ts_info.up); + if (SME_QOS_EDCA_AC_MAX == ac) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_validate_requested_params(pMac, pQoSInfo, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave for the duration of this request */ + pSession->readyForPowerSave = 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 safegaurd the above scenario, & also won't + * confuse PE with back to back Addts or Addts followed by Reassoc + */ + if (sme_qos_is_rsp_pending(sessionId, ac)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + /* 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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = true; + return SME_QOS_STATUS_SETUP_FAILURE_RSP; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_setup(pMac, sessionId, &Tspec_Info, ac); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_LINK_UP " + "sme_qos_setup 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 powersave back on */ + pSession->readyForPowerSave = 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 = cdf_mem_malloc(sizeof(*pentry)); + if (!pentry) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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); + CDF_ASSERT(0); + cdf_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 = 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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Creating entry on session %d at %p with flowID %d", + __func__, __LINE__, + sessionId, pentry, QosFlowID); + csr_ll_insert_tail(&sme_qos_cb.flow_list, &pentry->link, + true); + } else { + /* unexpected status returned by sme_qos_setup() */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_qos_setup", + __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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = 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_qos_is_acm(pMac, pSession->assocInfo.pBssDesc, ac, + NULL)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: tspec_mask_status can't be 0 for ac = %d in " + "state = %d", __func__, + __LINE__, ac, + pACInfo->curr_state); + CDF_ASSERT(0); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = 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 bidirecional, 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 { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "%s: %d: tmask = %d, new_tmask = %d in state = %d", + __func__, __LINE__, + tmask, new_tmask, pACInfo->curr_state); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_aggregate_params(&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; + + hstatus = sme_qos_aggregate_params( + &Tspec_Info, &pACInfo-> + curr_QoSInfo + [SME_QOS_TSPEC_INDEX_0], + &pACInfo-> + requested_QoSInfo + [tmask - 1]); + if (hstatus == CDF_STATUS_SUCCESS) { + hstatus = + sme_qos_aggregate_params + (&pACInfo-> + curr_QoSInfo + [SME_QOS_TSPEC_INDEX_1], + &pACInfo-> + requested_QoSInfo[tmask - + 1], + NULL); + } + } + + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: failed to aggregate params", + __func__, __LINE__); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = 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 { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: no flows running for ac = %d while in state = %d", + __func__, __LINE__, ac, pACInfo->curr_state); + CDF_ASSERT(0); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = 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_qos_setup(pMac, sessionId, + &pACInfo->requested_QoSInfo[tmask - 1], ac); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_qos_setup 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 powersave back on */ + pSession->readyForPowerSave = 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 *) + cdf_mem_malloc(sizeof(*pentry)); + if (!pentry) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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) { + cdf_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_qos_find_all_in_flow_list + (pMac, search_key, + sme_qos_setup_fnp); + if (!CDF_IS_STATUS_SUCCESS + (hstatus)) { + CDF_TRACE + (CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: couldn't notify other " + "entries on this AC =%d", + __func__, __LINE__, + ac); + } + } + } + pentry->hoRenewal = 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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d creating entry at %p with flowID %d", + __func__, __LINE__, + sessionId, pentry, QosFlowID); + csr_ll_insert_tail(&sme_qos_cb.flow_list, &pentry->link, + true); + } else { + /* unexpected status returned by sme_qos_setup() */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_qos_setup", + __func__, __LINE__, sessionId, status); + new_state = pACInfo->curr_state; + } + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = true; + CDF_ASSERT(0); + new_state = pACInfo->curr_state; + } + /* if current state is same as previous no need for transistion, + 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_qos_state_transition(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_qos_process_buffered_cmd(sessionId); + } + return status; +} + +/** + * sme_qos_internal_modify_req() - The SME QoS internal function to request + * for modification of certain QoS params on a flow running on a particular AC. + * @pMac: Pointer to the global MAC parameter structure. + * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + * related info as defined above, provided by HDD + * @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 + * + * 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. + * + * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP - Modification is successful. + * Other status means request failed + */ +sme_QosStatusType sme_qos_internal_modify_req(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, + uint32_t QosFlowID, + bool 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; + uint8_t sessionId; + CDF_STATUS hstatus; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked for flow %d", __func__, __LINE__, QosFlowID); + + cdf_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_qos_find_in_flow_list(search_key); + if (!pEntry) { + /* Err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + + /* validate QoS params */ + if (!sme_qos_validate_requested_params(pMac, pQoSInfo, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave for the duration of this request */ + pSession->readyForPowerSave = 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 safegaurd the above scenario, & also won't + * confuse PE with back to back Addts or Addts followed by Reassoc + */ + if (sme_qos_is_rsp_pending(sessionId, ac)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + /* 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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = true; + return SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 *) cdf_mem_malloc(sizeof(*pNewEntry)); + if (!pNewEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = 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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + csr_ll_insert_tail(&sme_qos_cb.flow_list, &pNewEntry->link, + true); + /* update TSPEC with the new param set */ + hstatus = sme_qos_update_params(sessionId, + ac, pNewEntry->tspec_mask, + &Aggr_Tspec_Info); + if (CDF_IS_STATUS_SUCCESS(hstatus)) { + pACInfo->requested_QoSInfo[pNewEntry->tspec_mask - 1] = + Aggr_Tspec_Info; + /* if ACM, send out a new ADDTS */ + status = sme_qos_setup(pMac, sessionId, + &pACInfo-> + requested_QoSInfo[pNewEntry-> + tspec_mask - 1], + ac); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_qos_setup 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 powersave back on */ + pSession->readyForPowerSave = 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; + + cdf_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_qos_find_all_in_flow_list(pMac, search_key, + sme_qos_modify_fnp); + if (!CDF_IS_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; + cdf_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_qos_find_all_in_flow_list + (pMac, search_key, + sme_qos_modification_notify_fnp); + if (!CDF_IS_STATUS_SUCCESS + (hstatus)) { + CDF_TRACE + (CDF_MODULE_ID_SME, + CDF_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_qos_setup() */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_qos_setup", __func__, + __LINE__, sessionId, status); + new_state = SME_QOS_QOS_ON; + } + } else { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: sme_qos_update_params() failed", + __func__, __LINE__); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = 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_qos_state_transition(sessionId, ac, new_state); + } else { + pACInfo->prev_state = SME_QOS_REQUESTED; + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = 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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = 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_qos_process_buffered_cmd(sessionId); + } + return status; +} + +/** + * sme_qos_internal_release_req() - release QOS flow on a particular AC + * @pMac: Pointer to the global MAC parameter structure. + * @QosFlowID: Identification per flow running on each AC generated by SME + * It is only meaningful if the QoS setup for the flow is successful + * + * The SME QoS internal function to request + * for releasing a QoS flow running on a particular AC. + + * Return: CDF_STATUS_SUCCESS - Release is successful. + */ +sme_QosStatusType sme_qos_internal_release_req(tpAniSirGlobal pMac, + uint32_t QosFlowID, + bool 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; + bool deltsIssued = false; + uint8_t sessionId; + CDF_STATUS hstatus; + bool biDirectionalFlowsPresent = false; + bool uplinkFlowsPresent = false; + bool downlinkFlowsPresent = false; + tListElem *pResult = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked for flow %d", __func__, __LINE__, QosFlowID); + + cdf_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_qos_find_in_flow_list(search_key); + + if (!pEntry) { + /* Err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + /* need to vote off powersave for the duration of this request */ + pSession->readyForPowerSave = 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 safegaurd the above scenario, & also won't + * confuse PE with back to back Addts or Addts followed by Reassoc + */ + if (sme_qos_is_rsp_pending(sessionId, ac)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + /* 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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: couldn't buffer the release request in state = %d", + __func__, __LINE__, pACInfo->curr_state); + /* unable to buffer the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = true; + return SME_QOS_STATUS_RELEASE_FAILURE_RSP; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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-diretional. + * 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 aggregaed 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) { + cdf_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_qos_find_in_flow_list(search_key); + if (pResult) + biDirectionalFlowsPresent = 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_qos_find_in_flow_list(search_key); + if (pResult) + uplinkFlowsPresent = true; + + /* Check if downlink flows exist */ + search_key.direction = + SME_QOS_WMM_TS_DIR_DOWNLINK; + pResult = + sme_qos_find_in_flow_list(search_key); + if (pResult) + downlinkFlowsPresent = true; + + if (uplinkFlowsPresent + && downlinkFlowsPresent) { + /* Need to split the uni-directional flows into SME_QOS_TSPEC_INDEX_0 and SME_QOS_TSPEC_INDEX_1 */ + + cdf_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_qos_update_tspec_mask + (sessionId, search_key, + SME_QOS_TSPEC_MASK_BIT_2_SET); + + /* Aggregate all downstream flows */ + hstatus = + sme_qos_update_params + (sessionId, ac, + SME_QOS_TSPEC_MASK_BIT_2_SET, + &Aggr_Tspec_Info); + + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 susequent 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 (!CDF_IS_STATUS_SUCCESS + (sme_qos_buffer_cmd + (&cmd, false))) { + CDF_TRACE + (CDF_MODULE_ID_SME, + CDF_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 buffer the request */ + /* nothing is pending so vote powersave back on */ + pSession-> + readyForPowerSave = + 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_qos_update_params(sessionId, + ac, flow_info->tspec_mask, + &Aggr_Tspec_Info); + if (CDF_IS_STATUS_SUCCESS(hstatus)) { + pACInfo->requested_QoSInfo[flow_info-> + tspec_mask - 1] = + Aggr_Tspec_Info; + /* if ACM, send out a new ADDTS */ + status = sme_qos_setup(pMac, sessionId, + &pACInfo-> + requested_QoSInfo + [flow_info->tspec_mask - + 1], ac); + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d with AC %d in state SME_QOS_QOS_ON " + "sme_qos_setup 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 powersave back on */ + pSession->readyForPowerSave = 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, flow_info, + QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, + pEntry, true); + pDeletedFlow = flow_info; + if (SME_QOS_STATUS_SETUP_SUCCESS_APSD_SET_ALREADY == status) { + cdf_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_qos_find_all_in_flow_list + (pMac, search_key, + sme_qos_setup_fnp); + if (!CDF_IS_STATUS_SUCCESS + (hstatus)) { + CDF_TRACE + (CDF_MODULE_ID_SME, + CDF_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_qos_setup() */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unexpected status %d " + "returned by sme_qos_setup", + __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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d deleting entry at " + "%p with flowID %d", __func__, + __LINE__, sessionId, + flow_info, QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, + pEntry, 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: sme_qos_update_params() failed", + __func__, __LINE__); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = 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; + /* check if delts needs to be sent */ + if (CSR_IS_ADDTS_WHEN_ACMOFF_SUPPORTED(pMac) || + sme_qos_is_acm(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 */ + csr_get_modify_profile_fields(pMac, + flow_info-> + sessionId, + &modifyProfileFields); + modifyProfileFields.uapsd_mask = + pSession->apsdMask; + csr_set_modify_profile_fields(pMac, + flow_info-> + sessionId, + &modifyProfileFields); + if (!pSession->apsdMask) { + /* this session no longer needs UAPSD */ + /* do any sessions still require UAPSD? */ + if (!sme_qos_is_uapsd_active()) { + /* No sessions require UAPSD so turn it off */ + /* (really don't care when PMC stops it) */ + sme_ps_uapsd_disable( + pMac, sessionId); + } + } + } + if (SME_QOS_RELEASE_DEFAULT == pACInfo->relTrig) { + /* send delts */ + hstatus = + qos_issue_command(pMac, sessionId, + eSmeCommandDelTs, + NULL, ac, + flow_info-> + tspec_mask); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: sme_qos_del_ts_req() failed", + __func__, __LINE__); + status = + SME_QOS_STATUS_RELEASE_FAILURE_RSP; + /* we won't be waiting for a response from the AP */ + /* so vote powersave back on */ + pSession->readyForPowerSave = + true; + } else { + pACInfo->tspec_mask_status &= + SME_QOS_TSPEC_MASK_BIT_1_2_SET + & (~flow_info->tspec_mask); + deltsIssued = true; + } + } else { + pSession->readyForPowerSave = true; + pACInfo->tspec_mask_status &= + SME_QOS_TSPEC_MASK_BIT_1_2_SET & + (~flow_info->tspec_mask); + deltsIssued = true; + } + } else if (pSession->apsdMask & + (1 << (SME_QOS_EDCA_AC_VO - ac))) { + /* reassoc logic */ + csr_get_modify_profile_fields(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_qos_is_uapsd_active()) { + /* No sessions require UAPSD so turn it off */ + /* (really don't care when PMC stops it) */ + sme_ps_uapsd_disable( + pMac, sessionId); + } + } + hstatus = sme_qos_request_reassoc(pMac, sessionId, + &modifyProfileFields, + false); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: Reassoc failed", + __func__, __LINE__); + status = + SME_QOS_STATUS_RELEASE_FAILURE_RSP; + /* we won't be waiting for a response from the AP */ + /* so vote powersave back on */ + pSession->readyForPowerSave = true; + } else { + pACInfo->reassoc_pending = false; /* no need to wait */ + pACInfo->prev_state = SME_QOS_LINK_UP; + pACInfo->tspec_pending = 0; + } + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: nothing to do for AC = %d", + __func__, __LINE__, ac); + /* we won't be waiting for a response from the AP */ + /* so vote powersave back on */ + pSession->readyForPowerSave = 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); + + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Exceeded the array bounds of pACInfo->num_flows", + __func__, __LINE__); + CDF_ASSERT(0); + return + SME_QOS_STATUS_RELEASE_INVALID_PARAMS_RSP; + } + + if (false == deltsIssued) { + cdf_mem_zero(&pACInfo-> + curr_QoSInfo[flow_info-> + tspec_mask - 1], + sizeof(sme_QosWmmTspecInfo)); + } + cdf_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d deleting entry at %p with flowID %d", + __func__, __LINE__, + sessionId, flow_info, QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, + 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_qos_state_transition(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_qos_buffer_cmd(&cmd, buffered_cmd); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave back on */ + pSession->readyForPowerSave = 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: release request in unexpected state = %d", + __func__, __LINE__, pACInfo->curr_state); + CDF_ASSERT(0); + /* unable to service the request */ + /* nothing is pending so vote powersave back on */ + pSession->readyForPowerSave = true; + break; + } + /* if we deleted a flow, reclaim the memory */ + if (pDeletedFlow) { + cdf_mem_free(pDeletedFlow); + } + if ((SME_QOS_STATUS_RELEASE_SUCCESS_RSP == status)) { + (void)sme_qos_process_buffered_cmd(sessionId); + } + return status; +} + +/** + * sme_qos_setup() - internal SME QOS setup function. + * @pMac: Pointer to the global MAC parameter structure. + * @sessionId: Session upon which setup is being performed + * @pTspec_Info: Pointer to sme_QosWmmTspecInfo which contains the WMM + * TSPEC related info as defined above + * @ac: Enumeration of the various EDCA Access Categories. + * + * 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. + * 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 + * + * Return: SME_QOS_STATUS_SETUP_SUCCESS_RSP if the setup is successful' + */ +sme_QosStatusType sme_qos_setup(tpAniSirGlobal pMac, + uint8_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; + CDF_STATUS hstatus; + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session Id %d is invalid", + __func__, __LINE__, sessionId); + return status; + } + pSession = &sme_qos_cb.sessionInfo[sessionId]; + if (!pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session %d is inactive", + __func__, __LINE__, sessionId); + return status; + } + if (!pSession->assocInfo.pBssDesc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session %d has an Invalid BSS Descriptor", + __func__, __LINE__, sessionId); + return status; + } + hstatus = csr_get_parsed_bss_description_ies(pMac, + pSession->assocInfo.pBssDesc, + &pIes); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AP doesn't support QoS", + __func__, __LINE__, sessionId); + cdf_mem_free(pIes); + /* notify HDD through the synchronous status msg */ + return SME_QOS_STATUS_SETUP_NOT_QOS_AP_RSP; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_is_acm(pMac, pSession->assocInfo.pBssDesc, + ac, NULL)) { + /* ACM is enabled for this AC so we must send an AddTS */ + 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 = + (uint8_t) (SME_QOS_WMM_UP_NC - + pTspec_Info->ts_info.up); + } + /* addts logic */ + hstatus = + qos_issue_command(pMac, sessionId, eSmeCommandAddTs, + pTspec_Info, ac, 0); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: sme_qos_add_ts_req() failed", + __func__, __LINE__); + break; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d reassoc needed " + "to disable APSD on AC %d", __func__, + __LINE__, sessionId, ac); + csr_get_modify_profile_fields(pMac, sessionId, + &modifyProfileFields); + modifyProfileFields.uapsd_mask |= + pSession->apsdMask; + modifyProfileFields.uapsd_mask &= + ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + hstatus = + sme_qos_request_reassoc(pMac, sessionId, + &modifyProfileFields, + false); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: Unable to request reassociation", + __func__, __LINE__); + break; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 = true; + } + } else { + /* we don't need APSD on this AC */ + /* and we don't currently have APSD on this AC */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("On session %d reassoc needed to enable APSD on AC %d"), + sessionId, ac); + /* reassoc logic */ + /* update the UAPSD mask to include the new */ + /* AC on which APSD is requested */ + csr_get_modify_profile_fields(pMac, sessionId, + &modifyProfileFields); + modifyProfileFields.uapsd_mask |= + pSession->apsdMask; + modifyProfileFields.uapsd_mask |= + 1 << (SME_QOS_EDCA_AC_VO - ac); + hstatus = + sme_qos_request_reassoc(pMac, sessionId, + &modifyProfileFields, + false); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: Unable to request reassociation", + __func__, __LINE__); + break; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("On session %d reassociation to enable APSD on AC %d is pending"), + sessionId, ac); + status = + SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + pACInfo->reassoc_pending = true; + } + } + } while (0); + + cdf_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! + */ +CDF_STATUS sme_qos_process_set_key_success_ind(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info) +{ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "########### Set Key Complete #############"); + (void)sme_qos_process_buffered_cmd(sessionId); + return CDF_STATUS_SUCCESS; +} +#endif + +#ifdef FEATURE_WLAN_ESE +/** + * sme_qos_ese_save_tspec_response() - save TSPEC parameters. + * @pMac: Pointer to the global MAC parameter structure. + * @sessionId: SME session ID + * @pTspec: Pointer to the TSPEC IE from the reassoc rsp + * @ac: Access Category for which this TSPEC rsp is received + * @tspecIndex: flow/direction + * + * This function saves the TSPEC parameters that came along in the TSPEC IE + * in the reassoc response + * + * Return: CDF_STATUS_SUCCESS - Release is successful. + */ +CDF_STATUS sme_qos_ese_save_tspec_response(tpAniSirGlobal pMac, uint8_t sessionId, + tDot11fIEWMMTSPEC *pTspec, uint8_t ac, + uint8_t tspecIndex) +{ + tpSirAddtsRsp pAddtsRsp = + &sme_qos_cb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex]; + + ac = sme_qos_u_pto_ac_map[pTspec->user_priority]; + + cdf_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + convert_wmmtspec(pMac, &pAddtsRsp->rsp.tspec, pTspec); + } + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_ese_process_reassoc_tspec_rsp() - process ese reassoc tspec response + * @pMac: Pointer to the global MAC parameter structure. + * @sessionId: SME session ID + * @pEven_info: Pointer to the smeJoinRsp structure + * + * 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 reasso req from the STA would carry the TSPEC parameters which were + * already negotiated with the older AP. + * + * Return: CDF_STATUS_SUCCESS - Release is successful. + */ +CDF_STATUS sme_qos_ese_process_reassoc_tspec_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + tDot11fIEWMMTSPEC *pTspecIE = NULL; + tCsrRoamSession *pCsrSession = NULL; + tCsrRoamConnectedInfo *pCsrConnectedInfo = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + uint8_t ac, numTspec, cnt; + uint8_t tspec_flow_index, tspec_mask_status; + uint32_t tspecIeLen; + + pCsrSession = CSR_GET_SESSION(pMac, sessionId); + if (NULL == pCsrSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session %d not found"), sessionId); + return CDF_STATUS_E_FAILURE; + } + pCsrConnectedInfo = &pCsrSession->connectedInfo; + pSession = &sme_qos_cb.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 atleast equal to the one TSPEC IE */ + tspecIeLen = pCsrConnectedInfo->nTspecIeLength; + if (tspecIeLen < sizeof(tDot11fIEWMMTSPEC)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("ESE Tspec IE len %d less than min %zu"), + tspecIeLen, sizeof(tDot11fIEWMMTSPEC)); + return CDF_STATUS_E_FAILURE; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "TspecLen = %d, pbFrames = %p, pTspecIE = %p", + tspecIeLen, pCsrConnectedInfo->pbFrames, pTspecIE); + + numTspec = (tspecIeLen) / sizeof(tDot11fIEWMMTSPEC); + for (cnt = 0; cnt < numTspec; cnt++) { + ac = sme_qos_up_to_ac(pTspecIE->user_priority); + if (ac >= SME_QOS_EDCA_AC_MAX) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("ac %d more than it`s max value"), ac); + return CDF_STATUS_E_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + tspec_mask_status = pACInfo->tspec_mask_status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_WARN, + FL + ("Found Tspec entry flow = %d AC = %d"), + tspec_flow_index, ac); + sme_qos_ese_save_tspec_response(pMac, sessionId, + pTspecIE, ac, + tspec_flow_index); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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_qos_ft_aggr_qos_req(pMac, sessionId); + + return status; +} + +/** + * sme_qos_copy_tspec_info() - copy tspec info. + * @pMac: Pointer to the global MAC parameter structure. + * @pTspec_Info: source structure + * @pTspec: destination structure + * + * This function copies the existing TSPEC parameters from the source structure + * to the destination structure. + * + * Return: None + */ +static void sme_qos_copy_tspec_info(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 */ + if (pTspec_Info->ts_info.psb) { + 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; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: up = %d, tid = %d", + __func__, __LINE__, + pTspec_Info->ts_info.up, pTspec_Info->ts_info.tid); +} + +/** + * sme_qos_ese_retrieve_tspec_info() - retrieve tspec info. + * @pMac: Pointer to the global MAC parameter structure. + * @sessionId: SME session ID + * @pTspecInfo: Pointer to the structure to carry back the TSPEC parameters + * + * 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. + * + * Return: uint8_t - number of existing negotiated TSPECs + */ +uint8_t sme_qos_ese_retrieve_tspec_info(tpAniSirGlobal mac_ctx, + uint8_t session_id, tTspecInfo *tspec_info) +{ + sme_QosSessionInfo *session; + sme_QosACInfo *ac_info; + uint8_t ac, num_tspec = 0; + tTspecInfo *dst_tspec = tspec_info; + uint8_t tspec_mask; + uint8_t tspec_pending; + + /* + * TODO: Check if TSPEC has already been established + * if not return + */ + session = &sme_qos_cb.sessionInfo[session_id]; + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + volatile uint8_t index = 0; + ac_info = &session->ac_info[ac]; + tspec_pending = ac_info->tspec_pending; + tspec_mask = ac_info->tspec_mask_status; + do { + /* + * If a tspec status is pending, take + * requested_QoSInfo for RIC request, + * else use curr_QoSInfo for the + * RIC request + */ + if ((tspec_mask & SME_QOS_TSPEC_MASK_BIT_1_SET) + && (tspec_pending & + SME_QOS_TSPEC_MASK_BIT_1_SET)){ + sme_qos_copy_tspec_info(mac_ctx, + &ac_info->requested_QoSInfo[index], + &dst_tspec->tspec); + dst_tspec->valid = true; + num_tspec++; + dst_tspec++; + } else if ((tspec_mask & SME_QOS_TSPEC_MASK_BIT_1_SET) + && !(tspec_pending & + SME_QOS_TSPEC_MASK_BIT_1_SET)){ + sme_qos_copy_tspec_info(mac_ctx, + &ac_info->curr_QoSInfo[index], + &dst_tspec->tspec); + dst_tspec->valid = true; + num_tspec++; + dst_tspec++; + } + tspec_mask >>= 1; + tspec_pending >>= 1; + index++; + } while (tspec_mask); + } + return num_tspec; +} + +#endif + +#ifdef WLAN_FEATURE_VOWIFI_11R + +CDF_STATUS sme_qos_create_tspec_ricie(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pTspec_Info, + uint8_t *pRICBuffer, uint32_t *pRICLength, + uint8_t *pRICIdentifier) +{ + tDot11fIERICDataDesc ricIE; + uint32_t nStatus; + + if (pRICBuffer == NULL || pRICIdentifier == NULL || pRICLength == NULL) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_zero(&ricIE, sizeof(tDot11fIERICDataDesc)); + + ricIE.present = 1; + ricIE.RICData.present = 1; + ricIE.RICData.resourceDescCount = 1; + ricIE.RICData.statusCode = 0; + ricIE.RICData.Identifier = sme_qos_assign_dialog_token(); +#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 */ + if (pTspec_Info->ts_info.psb) { + 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 = + dot11f_pack_ie_ric_data_desc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), + pRICLength); + if (DOT11F_FAILED(nStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + if (pTspec_Info->ts_info.psb) { + 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 = + dot11f_pack_ie_ric_data_desc(pMac, &ricIE, pRICBuffer, sizeof(ricIE), + pRICLength); + if (DOT11F_FAILED(nStatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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; +} +/** + * sme_qos_process_ft_reassoc_req_ev()- processes reassoc request + * + * @session_id: SME Session Id + * + * This function Process reassoc request related to QOS + * + * Return: CDF_STATUS enumeration value. + */ +static CDF_STATUS sme_qos_process_ft_reassoc_req_ev( + uint8_t sessionId) +{ + sme_QosSessionInfo *session; + sme_QosACInfo *ac_info; + uint8_t ac, qos_requested = false; + uint8_t tspec_index; + sme_QosFlowInfoEntry *flow_info = NULL; + tListElem *entry = NULL; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Invoked on session %d"), sessionId); + + session = &sme_qos_cb.sessionInfo[sessionId]; + + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + ac_info = &session->ac_info[ac]; + qos_requested = false; + + for (tspec_index = 0; + tspec_index < SME_QOS_TSPEC_INDEX_MAX; + tspec_index++) { + /* + * Only in the below case, copy the AC's curr + * QoS Info to requested QoS info + */ + if ((ac_info->ricIdentifier[tspec_index] + && !ac_info->tspec_pending) + || (ac_info-> + tspec_mask_status & (1 << tspec_index))) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("Copying the currentQos to " + "requestedQos for AC=%d, flow=%d"), + ac, tspec_index); + + ac_info->requested_QoSInfo[tspec_index] = + ac_info->curr_QoSInfo[tspec_index]; + cdf_mem_zero( + &ac_info->curr_QoSInfo[tspec_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 (ac_info->curr_state) { + case SME_QOS_HANDOFF: + sme_qos_state_transition(sessionId, ac, + SME_QOS_REQUESTED); + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("FT Reassoc req event in" + " unexpected state %d"), + ac_info->curr_state); + CDF_ASSERT(0); + } + } + } + + /* + * At this point of time, we are + * disconnected from the old AP, so it is safe + * to reset all these session variables + */ + session->apsdMask = 0; + session->uapsdAlreadyRequested = 0; + session->readyForPowerSave = 0; + + /* + * Now change reason and HO renewal of + * all the flow in this session only + */ + entry = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!entry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + FL("Flow List empty, nothing to update")); + return CDF_STATUS_E_FAILURE; + } + + do { + flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link); + if (sessionId == flow_info->sessionId) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Changing FlowID %d reason to SETUP" + "and HO renewal to false"), + flow_info->QosFlowID); + flow_info->reason = SME_QOS_REASON_SETUP; + flow_info->hoRenewal = true; + } + entry = csr_ll_next(&sme_qos_cb.flow_list, entry, false); + } while (entry); + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_fill_aggr_info - fill QOS Aggregation info + * + * @ac_id - index to the AC + * @ts_id - index to TS for a given AC + * @direction - traffic direction + * @msg - QOS message + * @session - sme session information + * + * this is a helper function to populate aggregation information + * for QOS message. + * + * Return: None + */ +static void sme_qos_fill_aggr_info(int ac_id, int ts_id, + sme_QosWmmDirType direction, + tSirAggrQosReq *msg, + sme_QosSessionInfo *session) +{ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + FL("Found tspec entry AC=%d, flow=%d, direction = %d"), + ac_id, ts_id, direction); + + msg->aggrInfo.aggrAddTsInfo[ac_id].dialogToken = + sme_qos_assign_dialog_token(); + msg->aggrInfo.aggrAddTsInfo[ac_id].lleTspecPresent = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.lleTspecPresent; + msg->aggrInfo.aggrAddTsInfo[ac_id].numTclas = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.numTclas; + cdf_mem_copy(msg->aggrInfo.aggrAddTsInfo[ac_id].tclasInfo, + session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasInfo, + SIR_MAC_TCLASIE_MAXNUM); + msg->aggrInfo.aggrAddTsInfo[ac_id].tclasProc = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasProc; + msg->aggrInfo.aggrAddTsInfo[ac_id].tclasProcPresent = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.tclasProcPresent; + msg->aggrInfo.aggrAddTsInfo[ac_id].tspec = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.tspec; + msg->aggrInfo.aggrAddTsInfo[ac_id].wmeTspecPresent = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.wmeTspecPresent; + msg->aggrInfo.aggrAddTsInfo[ac_id].wsmTspecPresent = + session->ac_info[ac_id].addTsRsp[ts_id].rsp.wsmTspecPresent; + msg->aggrInfo.tspecIdx |= (1 << ac_id); + + /* Mark the index for this AC as pending for response, which would be */ + /* used to validate the AddTS response from HAL->PE->SME */ + session->ac_info[ac_id].tspec_pending = (1 << ts_id); + + return; +} + +/** + * sme_qos_ft_aggr_qos_req - send aggregated QOS request + * + * @mac_ctx - global MAC context + * @session_id - sme session Id + * + * This function is used to send aggregated QOS request to HAL. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_ft_aggr_qos_req(tpAniSirGlobal mac_ctx, uint8_t session_id) +{ + tSirAggrQosReq *aggr_req = NULL; + sme_QosSessionInfo *session; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + int i, j = 0; + uint8_t direction; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("invoked on session %d"), session_id); + + session = &sme_qos_cb.sessionInfo[session_id]; + + aggr_req = (tSirAggrQosReq *) cdf_mem_malloc(sizeof(tSirAggrQosReq)); + + if (!aggr_req) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("couldn't allocate memory for the msg buffer")); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(aggr_req, sizeof(tSirAggrQosReq)); + + aggr_req->messageType = eWNI_SME_FT_AGGR_QOS_REQ; + aggr_req->length = sizeof(tSirAggrQosReq); + aggr_req->sessionId = session_id; + aggr_req->timeout = 0; + aggr_req->rspReqd = true; + cdf_mem_copy(&aggr_req->bssId[0], + &session->assocInfo.pBssDesc->bssId[0], + sizeof(struct cdf_mac_addr)); + + for (i = 0; i < SME_QOS_EDCA_AC_MAX; i++) { + for (j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("ac=%d, tspec_mask_staus=%x, tspec_index=%d"), + i, session->ac_info[i].tspec_mask_status, j); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("direction = %d"), + session->ac_info[i].addTsRsp[j].rsp.tspec. + tsinfo.traffic.direction); + /* Check if any flow is active on this AC */ + if (!((session->ac_info[i].tspec_mask_status) & + (1 << j))) + continue; + + direction = session->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)) { + sme_qos_fill_aggr_info(i, j, direction, + aggr_req, session); + } + } + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Sending aggregated message to HAL 0x%x"), + aggr_req->aggrInfo.tspecIdx); + + if (CDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(aggr_req))) { + status = CDF_STATUS_SUCCESS; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("sent down a AGGR QoS req to PE")); + } + + return status; +} + +CDF_STATUS sme_qos_process_ftric_response(tpAniSirGlobal pMac, uint8_t sessionId, + tDot11fIERICDataDesc *pRicDataDesc, + uint8_t ac, uint8_t tspecIndex) +{ + uint8_t i = 0; + tpSirAddtsRsp pAddtsRsp + = + &sme_qos_cb.sessionInfo[sessionId].ac_info[ac].addTsRsp[tspecIndex]; + + cdf_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 */ + convert_tspec(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 */ + convert_tclas(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 */ + convert_schedule(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) + convert_ts_delay(pMac, &pAddtsRsp->rsp.delay, + &pRicDataDesc->TSDelay); + + /* Need to call for WMMTSPEC */ + if (pRicDataDesc->WMMTSPEC.present) { + convert_wmmtspec(pMac, &pAddtsRsp->rsp.tspec, + &pRicDataDesc->WMMTSPEC); + } + /* return sme_qos_process_add_ts_rsp(pMac, &addtsRsp); */ + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_process_aggr_qos_rsp - process qos aggregation response + * + * @mac_ctx - global mac context + * @msgbuf - SME message buffer + * + * this function process the QOS aggregation response received. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_process_aggr_qos_rsp(tpAniSirGlobal mac_ctx, void *msgbuf) +{ + tpSirAggrQosRsp rsp = (tpSirAggrQosRsp) msgbuf; + tSirAddtsRsp addtsrsp; + CDF_STATUS status = CDF_STATUS_SUCCESS; + int i, j = 0; + uint8_t sessionid = rsp->sessionId; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Received AGGR_QOS resp from LIM")); + + /* Copy the updated response information for TSPEC of all the ACs */ + for (i = 0; i < SIR_QOS_NUM_AC_MAX; i++) { + uint8_t tspec_mask_status = + sme_qos_cb.sessionInfo[sessionid].ac_info[i]. + tspec_mask_status; + for (j = 0; j < SME_QOS_TSPEC_INDEX_MAX; j++) { + uint8_t direction = + sme_qos_cb.sessionInfo[sessionid]. + ac_info[i].addTsRsp[j].rsp.tspec.tsinfo.traffic. + direction; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Addts rsp from LIM AC=%d, flow=%d dir=%d, tspecIdx=%x"), + i, j, direction, rsp->aggrInfo.tspecIdx); + + /* Check if the direction is Uplink or bi-directional */ + if (!(((1 << i) & rsp->aggrInfo.tspecIdx) && + ((tspec_mask_status) & (1 << j)) && + ((direction == SME_QOS_WMM_TS_DIR_UPLINK) || + (direction == SME_QOS_WMM_TS_DIR_BOTH)))) { + continue; + } + addtsrsp = + sme_qos_cb.sessionInfo[sessionid].ac_info[i]. + addTsRsp[j]; + addtsrsp.rc = rsp->aggrInfo.aggrRsp[i].status; + addtsrsp.rsp.status = rsp->aggrInfo.aggrRsp[i].status; + addtsrsp.rsp.tspec = rsp->aggrInfo.aggrRsp[i].tspec; + + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("Processing Addts rsp from LIM AC=%d, flow=%d"), + i, j); + /* post ADD TS response for each */ + if (sme_qos_process_add_ts_rsp(mac_ctx, &addtsrsp) != + CDF_STATUS_SUCCESS) + status = CDF_STATUS_E_FAILURE; + } + } + return status; +} + +/** + * sme_qos_find_matching_tspec() - utility function to find matching tspec + * @mac_ctx: global MAC context + * @sessionid: session ID + * @ac: AC index + * @ac_info: Current AC info + * @ric_data_desc: pointer to ric data + * @ric_rsplen: pointer to ric response length + * + * This utility function is called by sme_qos_process_ft_reassoc_rsp_ev + * to find the matching tspec + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_qos_find_matching_tspec(tpAniSirGlobal mac_ctx, + uint8_t sessionid, uint8_t ac, sme_QosACInfo *ac_info, + tDot11fIERICDataDesc *ric_data_desc, uint32_t *ric_rsplen) +{ + uint8_t tspec_flow_index; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + 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 (!ac_info->ricIdentifier[tspec_flow_index]) + continue; + + if (!*ric_rsplen) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("RIC Response not received for AC %d on " + "TSPEC Index %d, RIC Req Identifier = %d"), + ac, tspec_flow_index, + ac_info->ricIdentifier[tspec_flow_index]); + CDF_ASSERT(0); + continue; + } + /* Now we got response for this identifier. Process it. */ + if (!ric_data_desc->present) + continue; + if (!ric_data_desc->RICData.present) + continue; + + if (ric_data_desc->RICData.Identifier != + ac_info->ricIdentifier[tspec_flow_index]) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("RIC response order not same as request sent. " + "Request ID = %d, Response ID = %d"), + ac_info->ricIdentifier[tspec_flow_index], + ric_data_desc->RICData.Identifier); + CDF_ASSERT(0); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO, + FL("Processing RIC Response for AC %d, " + "TSPEC Flow index %d with RIC ID %d "), + ac, tspec_flow_index, + ric_data_desc->RICData.Identifier); + status = sme_qos_process_ftric_response(mac_ctx, + sessionid, ric_data_desc, ac, + tspec_flow_index); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Failed with status %d for AC %d in " + "TSPEC Flow index = %d"), + status, ac, tspec_flow_index); + } + } + ric_data_desc++; + *ric_rsplen -= sizeof(tDot11fIERICDataDesc); + } + return status; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * sme_qos_find_matching_tspec_lfr3() - utility function to find matching tspec + * @mac_ctx: global MAC context + * @sessionid: session ID + * @ac: AC index + * @qos_session: QOS session + * @ric_data_desc: pointer to ric data + * @ric_rsplen: ric response length + * + * This utility function is called by sme_qos_process_ft_reassoc_rsp_ev + * to find the matching tspec while LFR3 is enabled. + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_qos_find_matching_tspec_lfr3(tpAniSirGlobal mac_ctx, + uint8_t sessionid, uint8_t ac, sme_QosSessionInfo *qos_session, + tDot11fIERICDataDesc *ric_data_desc, uint32_t ric_rsplen) +{ + sme_QosACInfo *ac_info; + uint8_t tspec_flow_idx; + bool found = false; + sme_QosWmmDirType direction, qos_dir; + uint8_t ac1; + tDot11fIERICDataDesc *ric_data = NULL; + uint32_t ric_len; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + ric_data = ric_data_desc; + ric_len = ric_rsplen; + ac_info = &qos_session->ac_info[ac]; + for (tspec_flow_idx = 0; tspec_flow_idx < SME_QOS_TSPEC_INDEX_MAX; + tspec_flow_idx++) { + if (!((qos_session->ac_info[ac].tspec_mask_status) & + (1 << tspec_flow_idx))) + goto sme_qos_next_ric; + qos_dir = + ac_info->requested_QoSInfo[tspec_flow_idx].ts_info.direction; + do { + ac1 = sme_qos_up_to_ac( + ric_data->WMMTSPEC.user_priority); + if (ac == SME_QOS_EDCA_AC_MAX) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Invalid AC %d UP %d"), ac, + ric_data->WMMTSPEC.user_priority); + break; + } + direction = ric_data->WMMTSPEC.direction; + if (ac == ac1 && direction == qos_dir) { + found = true; + status = sme_qos_process_ftric_response(mac_ctx, + sessionid, ric_data, ac, + tspec_flow_idx); + if (CDF_STATUS_SUCCESS != status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Failed with status %d for AC %d " + "in TSPEC Flow index = %d"), + status, ac, tspec_flow_idx); + } + break; + } + ric_data++; + ric_len -= sizeof(tDot11fIERICDataDesc); + } while (ric_len); +sme_qos_next_ric: + ric_data = ric_data_desc; + ric_len = ric_rsplen; + found = false; + } + + return status; +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +CDF_STATUS sme_qos_process_ft_reassoc_rsp_ev(tpAniSirGlobal mac_ctx, + uint8_t sessionid, void *event_info) +{ + sme_QosSessionInfo *qos_session; + sme_QosACInfo *ac_info; + uint8_t ac; + tDot11fIERICDataDesc *ric_data_desc = NULL; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, sessionid); + tCsrRoamConnectedInfo *csr_conn_info = NULL; + uint32_t ric_rsplen; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tDot11fIERICDataDesc *ric_data = NULL; + uint32_t ric_len; +#endif + + if (NULL == csr_session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("The Session pointer is NULL")); + return CDF_STATUS_E_FAILURE; + } + csr_conn_info = &csr_session->connectedInfo; + ric_rsplen = csr_conn_info->nRICRspLength; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("invoked on session %d"), sessionid); + + qos_session = &sme_qos_cb.sessionInfo[sessionid]; + + ric_data_desc = (tDot11fIERICDataDesc *) ((csr_conn_info->pbFrames) + + (csr_conn_info->nBeaconLength + + csr_conn_info->nAssocReqLength + + csr_conn_info->nAssocRspLength)); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (!csr_session->roamOffloadSynchParams.bRoamSynchInProgress) { +#endif + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + ac_info = &qos_session->ac_info[ac]; + sme_qos_find_matching_tspec(mac_ctx, sessionid, ac, + ac_info, ric_data_desc, &ric_rsplen); + } + + if (ric_rsplen) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("RIC Response still follows despite traversing " + "through all ACs. Remaining len = %d"), ric_rsplen); + CDF_ASSERT(0); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("LFR3-11r Compare RIC in Reassoc Resp to find" + " matching tspec in host.")); + ric_data = ric_data_desc; + ric_len = ric_rsplen; + if (ric_rsplen && ric_data_desc->present && + ric_data_desc->WMMTSPEC.present) { + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; + ac++) { + sme_qos_find_matching_tspec_lfr3(mac_ctx, + sessionid, ac, qos_session, ric_data, + ric_len); + } + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("LFR3-11r ric_rsplen is zero or ric_data_desc is" + " not present or wmmtspec is not present")); + } + } +#endif + + /* Send the Aggregated QoS request to HAL */ + status = sme_qos_ft_aggr_qos_req(mac_ctx, sessionid); + + return status; +} + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/** + * sme_qos_add_ts_req() - send ADDTS request. + * @pMac: Pointer to the global MAC parameter structure. + * @sessionId: Session upon which the TSPEC should be added + * @pTspec_Info: Pointer to sme_QosWmmTspecInfo which contains the WMM + * TSPEC related info as defined above + * @ac: Enumeration of the various EDCA Access Categories. + * + * This function is used to send down the ADDTS request with TSPEC params to PE + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_add_ts_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosWmmTspecInfo *pTspec_Info, + sme_QosEdcaAcType ac) +{ + tSirAddtsReq *pMsg = NULL; + sme_QosSessionInfo *pSession; + CDF_STATUS status = CDF_STATUS_E_FAILURE; +#ifdef FEATURE_WLAN_ESE + tCsrRoamSession *pCsrSession = CSR_GET_SESSION(pMac, sessionId); +#endif +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type); +#endif + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: sessionId(%d) is invalid", + __func__, __LINE__, sessionId); + return CDF_STATUS_E_FAILURE; + } + + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pMsg = (tSirAddtsReq *) cdf_mem_malloc(sizeof(tSirAddtsReq)); + if (!pMsg) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the msg buffer", + __func__, __LINE__); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(pMsg, sizeof(tSirAddtsReq)); + pMsg->messageType = eWNI_SME_ADDTS_REQ; + pMsg->length = sizeof(tSirAddtsReq); + pMsg->sessionId = sessionId; + pMsg->timeout = 0; + pMsg->rspReqd = true; + pMsg->req.dialogToken = sme_qos_assign_dialog_token(); + /*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 */ + if (pTspec_Info->ts_info.psb) { + 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: BSS descriptor is NULL so we don't send request to PE", + __func__, __LINE__); + cdf_mem_free(pMsg); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(&pMsg->bssId[0], + &pSession->assocInfo.pBssDesc->bssId[0], + sizeof(struct cdf_mac_addr)); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 (CDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(pMsg))) { + status = CDF_STATUS_SUCCESS; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_del_ts_req() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_del_ts_req(tpAniSirGlobal pMac, + uint8_t sessionId, + sme_QosEdcaAcType ac, uint8_t tspec_mask) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + tSirDeltsReq *pMsg; + sme_QosWmmTspecInfo *pTspecInfo; + CDF_STATUS status = CDF_STATUS_E_FAILURE; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + WLAN_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type); +#endif + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d", + __func__, __LINE__, sessionId, ac); + pMsg = (tSirDeltsReq *) cdf_mem_malloc(sizeof(tSirDeltsReq)); + if (!pMsg) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the msg buffer", + __func__, __LINE__); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(pMsg, sizeof(tSirDeltsReq)); + /* get pointer to the TSPEC being deleted */ + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + pTspecInfo = &pACInfo->curr_QoSInfo[tspec_mask - 1]; + pMsg->messageType = eWNI_SME_DELTS_REQ; + pMsg->length = sizeof(tSirDeltsReq); + pMsg->sessionId = sessionId; + pMsg->rspReqd = 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: BSS descriptor is NULL so we don't send request to PE", + __func__, __LINE__); + cdf_mem_free(pMsg); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_copy(&pMsg->bssId[0], + &pSession->assocInfo.pBssDesc->bssId[0], + sizeof(struct cdf_mac_addr)); + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: up = %d, tid = %d", + __func__, __LINE__, + pTspecInfo->ts_info.up, pTspecInfo->ts_info.tid); + cdf_mem_zero(&pACInfo->curr_QoSInfo[tspec_mask - 1], + sizeof(sme_QosWmmTspecInfo)); + if (CDF_IS_STATUS_SUCCESS(cds_send_mb_message_to_mac(pMsg))) { + status = CDF_STATUS_SUCCESS; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: sme_qos_del_ts_req: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_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + } + sme_set_tspec_uapsd_mask_per_session(pMac, + &pMsg->req.tspec.tsinfo, + sessionId); + + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_add_ts_rsp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_add_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirAddtsRsp paddts_rsp = (tpSirAddtsRsp) pMsgBuf; + sme_QosSessionInfo *pSession; + uint8_t sessionId = paddts_rsp->sessionId; + CDF_STATUS status = CDF_STATUS_E_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_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type); +#endif + + pSession = &sme_qos_cb.sessionInfo[sessionId]; + +#ifdef WLAN_FEATURE_VOWIFI_11R + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", + __func__, __LINE__, sessionId, up); + + ac = sme_qos_up_to_ac(up); + if (SME_QOS_EDCA_AC_MAX == ac) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + + return CDF_STATUS_E_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + if (SME_QOS_HANDOFF == pACInfo->curr_state) { + sms_log(pMac, LOG1, + FL + ("ADDTS Response received for AC %d in HANDOFF State.. Dropping"), + ac); + pSession->readyForPowerSave = true; + return CDF_STATUS_SUCCESS; + } +#endif + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 powersave */ + pSession->readyForPowerSave = 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_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + status = + sme_qos_process_add_ts_failure_rsp(pMac, sessionId, + &paddts_rsp->rsp); + } else { + status = + sme_qos_process_add_ts_success_rsp(pMac, sessionId, + &paddts_rsp->rsp); + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_del_ts_rsp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_del_ts_rsp(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirDeltsRsp pDeltsRsp = (tpSirDeltsRsp) pMsgBuf; + sme_QosSessionInfo *pSession; + uint8_t sessionId = pDeltsRsp->sessionId; + /* msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d with return code %d", + __func__, __LINE__, sessionId, pDeltsRsp->rc); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + /* our outstanding request has been serviced */ + /* we can go into powersave */ + pSession->readyForPowerSave = true; + (void)sme_qos_process_buffered_cmd(sessionId); + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_del_ts_ind() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_del_ts_ind(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirDeltsRsp pdeltsind = (tpSirDeltsRsp) pMsgBuf; + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + uint8_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_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type); +#endif + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d for UP %d", + __func__, __LINE__, sessionId, up); + ac = sme_qos_up_to_ac(up); + if (SME_QOS_EDCA_AC_MAX == ac) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + return CDF_STATUS_E_FAILURE; + } + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + + cdf_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 perticular AC & delete them, also send HDD indication */ + /* through the callback it registered per request */ + if (!CDF_IS_STATUS_SUCCESS + (sme_qos_find_all_in_flow_list(pMac, search_key, sme_qos_del_ts_ind_fnp))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: no match found for ac = %d", __func__, + __LINE__, search_key.key.ac_type); + CDF_ASSERT(0); + return CDF_STATUS_E_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_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_assoc_complete_ev() - Function to process the + SME_QOS_CSR_ASSOC_COMPLETE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_assoc_complete_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_BE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: pEvent_info is NULL", + __func__, __LINE__); + return status; + } + if (!((sme_QosAssocInfo *) pEvent_info)->pBssDesc) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: pBssDesc is NULL", + __func__, __LINE__); + return status; + } + if ((pSession->assocInfo.pBssDesc) && + (csr_is_bssid_match + (pMac, (struct cdf_mac_addr *) &pSession->assocInfo.pBssDesc->bssId, + (struct cdf_mac_addr *) &(((sme_QosAssocInfo *) pEvent_info)-> + pBssDesc->bssId)))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: assoc with the same BSS, no update needed", + __func__, __LINE__); + } else { + status = sme_qos_save_assoc_info(pSession, pEvent_info); + } + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); + CDF_ASSERT(0); + return status; + } + /* the session is active */ + pSession->sessionActive = true; + if (pSession->handoffRequested) { + pSession->handoffRequested = false; + /* renew all flows */ + (void)sme_qos_process_buffered_cmd(sessionId); + status = CDF_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_qos_state_transition(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: + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, sessionId, ac, + pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_reassoc_req_ev() - Function to process the + SME_QOS_CSR_REASSOC_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_reassoc_req_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSession->ftHandoffInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + sme_qos_process_ft_reassoc_req_ev(sessionId); + return CDF_STATUS_SUCCESS; + } +#endif + + if (pSession->handoffRequested) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + /* buffer the existing flows to be renewed after handoff is done */ + sme_qos_buffer_existing_flows(pMac, sessionId); + /* clean up the control block partially for handoff */ + sme_qos_cleanup_ctrl_blk_for_handoff(pMac, sessionId); + return CDF_STATUS_SUCCESS; + } +/* TBH: Assuming both handoff algo & 11r willn't be enabled at the same time */ +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSession->ftHandoffInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + sme_qos_process_ft_reassoc_req_ev(sessionId); + return CDF_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_qos_state_transition(sessionId, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + /* This is normal because sme_qos_request_reassoc may already change the state */ + break; + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_handle_handoff_state() - utility function called by + * sme_qos_process_reassoc_success_ev + * @mac_ctx: global MAC context + * @qos_session: QOS session + * @ac_info: AC information + * @ac: current AC index + * @sessionid: session id + * + * This function is called by sme_qos_process_reassoc_success_ev + * to update the state machine on the reception of reassoc success + * notificaiton + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_handle_handoff_state(tpAniSirGlobal mac_ctx, + sme_QosSessionInfo *qos_session, sme_QosACInfo *ac_info, + sme_QosEdcaAcType ac, uint8_t sessionid) + +{ + sme_QosSearchInfo search_key; + sme_QosSearchInfo search_key1; + sme_QosEdcaAcType ac_index; + tListElem *list_elt = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + /* return to our previous state */ + sme_qos_state_transition(sessionid, ac, ac_info->prev_state); + /* for which ac APSD (hence the reassoc) is requested */ + if (!ac_info->reassoc_pending) + return CDF_STATUS_SUCCESS; + + /* + * update the apsd mask in CB - make sure to take care of the + * case where we are resetting the bit in apsd_mask + */ + if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb) + qos_session->apsdMask |= 1 << (SME_QOS_EDCA_AC_VO - ac); + else + qos_session->apsdMask &= ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + + ac_info->reassoc_pending = false; + /* + * during setup it gets set as addts & reassoc both gets a + * pending flag ac_info->tspec_pending = 0; + */ + sme_qos_state_transition(sessionid, ac, SME_QOS_QOS_ON); + /* notify HDD with new Service Interval */ + ac_info->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0] = + ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0]; + cdf_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?? */ + + cdf_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++) { + list_elt = sme_qos_find_in_flow_list(search_key1); + if (list_elt) { + flow_info = GET_BASE_ADDR(list_elt, + sme_QosFlowInfoEntry, link); + if (flow_info->ac_type == ac) { + ac_info->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 + */ + status = sme_qos_find_all_in_flow_list(mac_ctx, search_key, + sme_qos_reassoc_success_ev_fnp); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("no match found for ac = %d"), + search_key.key.ac_type); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + ac_info->hoRenewal = false; + cdf_mem_zero(&ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + + return status; +} + +/** + * sme_qos_process_reassoc_success_ev() - process SME_QOS_CSR_REASSOC_COMPLETE + * + * @mac_ctx: global MAC context + * @sessionid: session ID + * @event_info: event buffer from CSR + * + * Function to process the SME_QOS_CSR_REASSOC_COMPLETE event indication + * from CSR + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_process_reassoc_success_ev(tpAniSirGlobal mac_ctx, + uint8_t sessionid, void *event_info) +{ + + tCsrRoamSession *csr_roam_session = NULL; + sme_QosSessionInfo *qos_session; + sme_QosACInfo *ac_info; + sme_QosEdcaAcType ac; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("invoked on session %d"), sessionid); + + if (CSR_ROAM_SESSION_MAX <= sessionid) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("invoked on session %d"), sessionid); + return status; + } + + csr_roam_session = CSR_GET_SESSION(mac_ctx, sessionid); + + qos_session = &sme_qos_cb.sessionInfo[sessionid]; + /* + * our pending reassociation has completed + * we can allow powersave + */ + qos_session->readyForPowerSave = true; + + /* get the association info */ + if (!event_info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("event_info is NULL")); + return status; + } + + if (!((sme_QosAssocInfo *) event_info)->pBssDesc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("pBssDesc is NULL")); + return status; + } + status = sme_qos_save_assoc_info(qos_session, event_info); + if (status) + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_save_assoc_info() failed")); + + /* + * Assuming both handoff algo & 11r willn't be enabled + * at the same time + */ + if (qos_session->handoffRequested) { + qos_session->handoffRequested = false; + /* renew all flows */ + (void)sme_qos_process_buffered_cmd(sessionid); + return CDF_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_VOWIFI_11R + if (qos_session->ftHandoffInProgress) { + if (csr_roam_is11r_assoc(mac_ctx, sessionid)) { + if (csr_roam_session && + csr_roam_session->connectedInfo.nRICRspLength) { + status = sme_qos_process_ft_reassoc_rsp_ev( + mac_ctx, sessionid, event_info); + } + } +#ifdef FEATURE_WLAN_ESE + /* + * If ESE association check for TSPEC IEs in the + * reassoc rsp frame + */ + if (csr_roam_is_ese_assoc(mac_ctx, sessionid)) { + if (csr_roam_session && + csr_roam_session->connectedInfo.nTspecIeLength) { + status = sme_qos_ese_process_reassoc_tspec_rsp( + mac_ctx, sessionid, event_info); + } + } +#endif + qos_session->ftHandoffInProgress = false; + qos_session->handoffRequested = false; + return status; + } +#endif + + qos_session->sessionActive = true; + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + ac_info = &qos_session->ac_info[ac]; + switch (ac_info->curr_state) { + case SME_QOS_HANDOFF: + status = sme_qos_handle_handoff_state(mac_ctx, + qos_session, ac_info, ac, sessionid); + break; + case SME_QOS_INIT: + case SME_QOS_CLOSED: + /* NOP */ + status = CDF_STATUS_SUCCESS; + break; + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("session %d AC %d is in wrong state %d"), + sessionid, ac, ac_info->curr_state); + CDF_ASSERT(0); + break; + } + } + (void)sme_qos_process_buffered_cmd(sessionid); + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_reassoc_failure_ev() - Function to process the + SME_QOS_CSR_REASSOC_FAILURE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_reassoc_failure_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + /* our pending reassociation has completed */ + /* we can allow powersave */ + pSession->readyForPowerSave = 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_qos_state_transition(sessionId, ac, SME_QOS_INIT); + if (pACInfo->reassoc_pending) { + pACInfo->reassoc_pending = false; + } + cdf_mem_zero(&pACInfo-> + curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + cdf_mem_zero(&pACInfo-> + requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + cdf_mem_zero(&pACInfo-> + curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + cdf_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } + /* need to clean up flows */ + sme_qos_delete_existing_flows(pMac, sessionId); + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_handoff_assoc_req_ev() - Function to process the + SME_QOS_CSR_HANDOFF_ASSOC_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_handoff_assoc_req_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + uint8_t ac; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.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_qos_state_transition(sessionId, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + /* print error msg */ +#ifdef WLAN_FEATURE_VOWIFI_11R + if (pSession->ftHandoffInProgress) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (csr_roam_is11r_assoc(pMac, sessionId)) { + pSession->ftHandoffInProgress = true; + } +#endif + /* If FT handoff is in progress, legacy handoff need not be enabled */ + if (!pSession->ftHandoffInProgress) { + pSession->handoffRequested = true; + } + /* this session no longer needs UAPSD */ + pSession->apsdMask = 0; + /* do any sessions still require UAPSD? */ + sme_ps_uapsd_disable(pMac, sessionId); + pSession->uapsdAlreadyRequested = false; + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_handoff_success_ev() - Function to process the + SME_QOS_CSR_HANDOFF_COMPLETE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_handoff_success_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + uint8_t ac; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.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_qos_state_transition(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 = CDF_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 + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_handoff_failure_ev() - Function to process the + SME_QOS_CSR_HANDOFF_FAILURE event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_handoff_failure_ev(tpAniSirGlobal pMac, + uint8_t sessionId, void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + uint8_t ac; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.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_qos_state_transition(sessionId, ac, SME_QOS_INIT); + /* need to clean up flows: TODO */ + cdf_mem_zero(&pACInfo-> + curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + cdf_mem_zero(&pACInfo-> + requested_QoSInfo[SME_QOS_TSPEC_INDEX_0], + sizeof(sme_QosWmmTspecInfo)); + cdf_mem_zero(&pACInfo-> + curr_QoSInfo[SME_QOS_TSPEC_INDEX_1], + sizeof(sme_QosWmmTspecInfo)); + cdf_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: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d AC %d is in wrong state %d", + __func__, __LINE__, + sessionId, ac, pACInfo->curr_state); + CDF_ASSERT(0); + break; + } + } + /* no longer in handoff */ + pSession->handoffRequested = false; + /* clean up the assoc info */ + if (pSession->assocInfo.pBssDesc) { + cdf_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_disconnect_ev() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_disconnect_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.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 + ) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + CDF_ASSERT(0); + return CDF_STATUS_SUCCESS; + } + + return CDF_STATUS_SUCCESS; + } + sme_qos_init_a_cs(pMac, sessionId); + /* this session doesn't require UAPSD */ + pSession->apsdMask = 0; + + sme_ps_uapsd_disable(pMac, sessionId); + + pSession->uapsdAlreadyRequested = false; + pSession->handoffRequested = false; + pSession->readyForPowerSave = true; + pSession->roamID = 0; + /* need to clean up buffered req */ + sme_qos_delete_buffered_requests(pMac, sessionId); + /* need to clean up flows */ + sme_qos_delete_existing_flows(pMac, sessionId); + /* clean up the assoc info */ + if (pSession->assocInfo.pBssDesc) { + cdf_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + sme_qos_cb.sessionInfo[sessionId].sessionActive = false; + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_join_req_ev() - Function to process the + SME_QOS_CSR_JOIN_REQ event indication from CSR + \param pEvent_info - Pointer to relevant info from CSR. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_join_req_ev(tpAniSirGlobal pMac, uint8_t sessionId, + void *pEvent_info) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + if (pSession->handoffRequested) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_ASSERT(0); + } + /* buffer the existing flows to be renewed after handoff is done */ + sme_qos_buffer_existing_flows(pMac, sessionId); + /* clean up the control block partially for handoff */ + sme_qos_cleanup_ctrl_blk_for_handoff(pMac, sessionId); + return CDF_STATUS_SUCCESS; + } + + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + sme_qos_state_transition(sessionId, ac, SME_QOS_INIT); + } + /* clean up the assoc info if already set */ + if (pSession->assocInfo.pBssDesc) { + cdf_mem_free(pSession->assocInfo.pBssDesc); + pSession->assocInfo.pBssDesc = NULL; + } + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_VOWIFI_11R +/** + * sme_qos_process_preauth_success_ind() - process preauth success indication + * @mac_ctx: global MAC context + * @sessionid: session ID + * @event_info: event buffer + * + * Function to process the SME_QOS_CSR_PREAUTH_SUCCESS_IND event indication + * from CSR + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_process_preauth_success_ind(tpAniSirGlobal mac_ctx, + uint8_t sessionid, void *event_info) +{ + sme_QosSessionInfo *qos_session; + tCsrRoamSession *sme_session = CSR_GET_SESSION(mac_ctx, sessionid); + sme_QosACInfo *ac_info; + uint8_t ac; + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint16_t ric_offset = 0; + uint32_t ric_ielen = 0; + uint8_t *ric_ie; + uint8_t tspec_mask_status = 0; + uint8_t tspec_pending_status = 0; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("invoked on SME session %d"), sessionid); + + if (NULL == sme_session) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_session is NULL")); + return CDF_STATUS_E_INVAL; + } + + qos_session = &sme_qos_cb.sessionInfo[sessionid]; + + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + ac_info = &qos_session->ac_info[ac]; + + switch (ac_info->curr_state) { + case SME_QOS_LINK_UP: + case SME_QOS_REQUESTED: + case SME_QOS_QOS_ON: + sme_qos_state_transition(sessionid, ac, SME_QOS_HANDOFF); + break; + case SME_QOS_HANDOFF: + /* print error msg */ + case SME_QOS_CLOSED: + case SME_QOS_INIT: + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Session %d AC %d is in wrong state %d"), + sessionid, ac, ac_info->curr_state); + CDF_ASSERT(0); + break; + } + } + + qos_session->ftHandoffInProgress = true; + + /* Check if its a 11R roaming before preparing the RIC IEs */ + if (!csr_roam_is11r_assoc(mac_ctx, sessionid)) + return status; + + /* Data is accessed from saved PreAuth Rsp */ + if (NULL == sme_session->ftSmeContext.psavedFTPreAuthRsp) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("psavedFTPreAuthRsp is NULL")); + return CDF_STATUS_E_INVAL; + } + + /* + * 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 + */ + ric_ie = sme_session->ftSmeContext.psavedFTPreAuthRsp->ric_ies; + ric_offset = + sme_session->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 uint8_t tspec_idx = 0; + ric_ielen = 0; + ac_info = &qos_session->ac_info[ac]; + tspec_pending_status = ac_info->tspec_pending; + tspec_mask_status = ac_info->tspec_mask_status; + cdf_mem_zero(ac_info->ricIdentifier, SME_QOS_TSPEC_INDEX_MAX); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) + goto add_next_ric; + + /* + * 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_qos_create_tspec_ricie(mac_ctx, + &ac_info->requested_QoSInfo[tspec_idx], + ric_ie + ric_offset, &ric_ielen, + &ac_info->ricIdentifier[tspec_idx]); + } else { + status = sme_qos_create_tspec_ricie(mac_ctx, + &ac_info->curr_QoSInfo[tspec_idx], + ric_ie + ric_offset, &ric_ielen, + &ac_info->ricIdentifier[tspec_idx]); + } +add_next_ric: + ric_offset += ric_ielen; + sme_session->ftSmeContext.psavedFTPreAuthRsp-> + ric_ies_length += ric_ielen; + tspec_mask_status >>= 1; + tspec_pending_status >>= 1; + tspec_idx++; + } while (tspec_mask_status); + } + return status; +} + +#endif + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_add_ts_failure_rsp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_add_ts_failure_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirAddtsRspInfo *pRsp) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + sme_QosSearchInfo search_key; + uint8_t tspec_pending; + sme_QosWmmUpType up = + (sme_QosWmmUpType) pRsp->tspec.tsinfo.traffic.userPrio; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", __func__, __LINE__, + sessionId, up); + ac = sme_qos_up_to_ac(up); + if (SME_QOS_EDCA_AC_MAX == ac) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + return CDF_STATUS_E_FAILURE; + } + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + /* is there a TSPEC request pending on this AC? */ + tspec_pending = pACInfo->tspec_pending; + if (!tspec_pending) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d an AddTS is not pending on AC %d", + __func__, __LINE__, sessionId, ac); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + cdf_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 (!CDF_IS_STATUS_SUCCESS + (sme_qos_find_all_in_flow_list + (pMac, search_key, sme_qos_add_ts_failure_fnp))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d no match found for ac = %d", + __func__, __LINE__, sessionId, + search_key.key.ac_type); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + cdf_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_qos_state_transition(sessionId, ac, SME_QOS_LINK_UP); + } else { + sme_qos_state_transition(sessionId, ac, SME_QOS_QOS_ON); + } + pACInfo->tspec_pending = 0; + + (void)sme_qos_process_buffered_cmd(sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_update_tspec_mask() - Utiltity function to update the tspec. + * @sessionid: Session upon which the TSPEC is being updated + * @search_key: search key + * @new_tspec_mask: tspec to be set for this AC + * + * Typical usage while aggregating unidirectional flows into a bi-directional + * flow on AC which is running multiple flows + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_qos_update_tspec_mask(uint8_t sessionid, + sme_QosSearchInfo search_key, + uint8_t new_tspec_mask) +{ + tListElem *list_elt = NULL, *list_next_elt = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosSessionInfo *qos_session; + sme_QosACInfo *ac_info; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("invoked on session %d for AC %d TSPEC %d"), + sessionid, search_key.key.ac_type, new_tspec_mask); + + qos_session = &sme_qos_cb.sessionInfo[sessionid]; + + if (search_key.key.ac_type < SME_QOS_EDCA_AC_MAX) { + ac_info = &qos_session->ac_info[search_key.key.ac_type]; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Exceeded the array bounds")); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!list_elt) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Flow List empty, nothing to update")); + return CDF_STATUS_E_FAILURE; + } + + while (list_elt) { + list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt, + false); + flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link); + + if (search_key.sessionId != flow_info->sessionId) { + list_elt = list_next_elt; + continue; + } + + 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)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("Flow %d matches"), flow_info->QosFlowID); + ac_info->num_flows[flow_info->tspec_mask - 1]--; + ac_info->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)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("Flow %d matches"), flow_info->QosFlowID); + ac_info->num_flows[flow_info->tspec_mask - 1]--; + ac_info->num_flows[new_tspec_mask - 1]++; + flow_info->tspec_mask = new_tspec_mask; + } + } + list_elt = list_next_elt; + } + + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_process_add_ts_success_rsp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_process_add_ts_success_rsp(tpAniSirGlobal pMac, + uint8_t sessionId, + tSirAddtsRspInfo *pRsp) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac, ac_index; + sme_QosSearchInfo search_key; + sme_QosSearchInfo search_key1; + uint8_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_HOST_DIAG_EVENT_DEF(qos, host_event_wlan_qos_payload_type); + host_log_qos_tspec_pkt_type *log_ptr = NULL; +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for UP %d", + __func__, __LINE__, sessionId, up); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + ac = sme_qos_up_to_ac(up); + if (SME_QOS_EDCA_AC_MAX == ac) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid AC %d from UP %d", + __func__, __LINE__, ac, up); + return CDF_STATUS_E_FAILURE; + } + pACInfo = &pSession->ac_info[ac]; + /* is there a TSPEC request pending on this AC? */ + tspec_pending = pACInfo->tspec_pending; + if (!tspec_pending) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d an AddTS is not pending on AC %d", + __func__, __LINE__, sessionId, ac); + return CDF_STATUS_E_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 { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Exceeded the array bounds of pACInfo->requested_QosInfo", + __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_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; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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)) { + cdf_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_qos_update_tspec_mask(sessionId, search_key, + SME_QOS_TSPEC_MASK_BIT_1_SET); + } + + cdf_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_qos_find_in_flow_list(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; + } + } + } + cdf_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 (!CDF_IS_STATUS_SUCCESS + (sme_qos_find_all_in_flow_list + (pMac, search_key, sme_qos_add_ts_success_fnp))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d no match found for ac %d", + __func__, __LINE__, sessionId, + search_key.key.ac_type); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + pACInfo->hoRenewal = false; + cdf_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_HOST_DIAG_EVENT_REPORT(&qos, EVENT_WLAN_QOS); + WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_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_HOST_DIAG_LOG_REPORT(log_ptr); +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + pACInfo->tspec_pending = 0; + + sme_qos_state_transition(sessionId, ac, SME_QOS_QOS_ON); + + sme_set_tspec_uapsd_mask_per_session(pMac, + &pRsp->tspec.tsinfo, sessionId); + + (void)sme_qos_process_buffered_cmd(sessionId); + return CDF_STATUS_SUCCESS; + +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_aggregate_params() - Utiltity function to increament 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_aggregate_params(sme_QosWmmTspecInfo *pInput_Tspec_Info, + sme_QosWmmTspecInfo *pCurrent_Tspec_Info, + sme_QosWmmTspecInfo *pUpdated_Tspec_Info) +{ + sme_QosWmmTspecInfo TspecInfo; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked", __func__, __LINE__); + if (!pInput_Tspec_Info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: input is NULL, nothing to aggregate", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + if (!pCurrent_Tspec_Info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Current is NULL, can't aggregate", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + cdf_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 = + CDF_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 = + CDF_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 = + CDF_MAX(pCurrent_Tspec_Info->maximum_msdu_size, + pInput_Tspec_Info->maximum_msdu_size); + + /*------------------------------------------------------------------------- + Inactivity interval : these sizes are `maxed' + -------------------------------------------------------------------------*/ + TspecInfo.inactivity_interval = + CDF_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 = + CDF_MIN(pCurrent_Tspec_Info->delay_bound, + pInput_Tspec_Info->delay_bound); + } else { + TspecInfo.delay_bound = pInput_Tspec_Info->delay_bound; + } + TspecInfo.max_burst_size = CDF_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 = + CDF_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) { + cdf_mem_copy(pUpdated_Tspec_Info, &TspecInfo, + sizeof(sme_QosWmmTspecInfo)); + } else { + cdf_mem_copy(pCurrent_Tspec_Info, &TspecInfo, + sizeof(sme_QosWmmTspecInfo)); + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_update_params() - Utiltity 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +static CDF_STATUS sme_qos_update_params(uint8_t sessionId, + sme_QosEdcaAcType ac, + uint8_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; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: invoked on session %d for AC %d TSPEC %d", + __func__, __LINE__, sessionId, ac, tspec_mask); + if (!pTspec_Info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: output is NULL, can't aggregate", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + cdf_mem_zero(&Tspec_Info, sizeof(sme_QosWmmTspecInfo)); + pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, nothing to update", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + pSession = &sme_qos_cb.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 = csr_ll_next(&sme_qos_cb.flow_list, pEntry, 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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Skipping Flow %d as it is marked " + "for release/modify", __func__, + __LINE__, flow_info->QosFlowID); + } else + if (!CDF_IS_STATUS_SUCCESS + (sme_qos_aggregate_params + (&flow_info->QoSInfo, &Tspec_Info, NULL))) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: sme_qos_aggregate_params() failed", + __func__, __LINE__); + } + } + pEntry = pNextEntry; + } + /* return the aggregate */ + *pTspec_Info = Tspec_Info; + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_ac_to_up() - Utiltity 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_qos_ac_to_up(sme_QosEdcaAcType ac) +{ + sme_QosWmmUpType up = SME_QOS_WMM_UP_MAX; + if (ac >= 0 && ac < SME_QOS_EDCA_AC_MAX) { + up = sme_qos_a_cto_up_map[ac]; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "%s: %d: ac = %d up = %d returned", + __func__, __LINE__, ac, up); + return up; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_up_to_ac() - Utiltity function to map an UP to AC + \param up - Enumeration of the various User priorities (UP). + \return an Access Category + + \sa + + --------------------------------------------------------------------------*/ +sme_QosEdcaAcType sme_qos_up_to_ac(sme_QosWmmUpType up) +{ + sme_QosEdcaAcType ac = SME_QOS_EDCA_AC_MAX; + if (up >= 0 && up < SME_QOS_WMM_UP_MAX) { + ac = sme_qos_u_pto_ac_map[up]; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "%s: %d: up = %d ac = %d returned", + __func__, __LINE__, up, ac); + return ac; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_state_transition() - 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_qos_state_transition(uint8_t sessionId, + sme_QosEdcaAcType ac, + sme_QosStates new_state) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pACInfo = &pSession->ac_info[ac]; + pACInfo->prev_state = pACInfo->curr_state; + pACInfo->curr_state = new_state; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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); +} + +/** + * sme_qos_find_in_flow_list() - find a flow entry from the flow list + * @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 + * + * Utility function to find an flow entry from the flow_list. + * + * Return: pointer to the list element + */ +tListElem *sme_qos_find_in_flow_list(sme_QosSearchInfo search_key) +{ + tListElem *list_elt = NULL, *list_next_elt = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!list_elt) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Flow List empty, can't search")); + return NULL; + } + + while (list_elt) { + list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt, + false); + flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link); + + if ((search_key.sessionId != flow_info->sessionId) && + (search_key.sessionId != SME_QOS_SEARCH_SESSION_ID_ANY)) { + list_elt = list_next_elt; + continue; + } + + if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) { + if (search_key.key.QosFlowID == flow_info->QosFlowID) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on flowID, ending search")); + break; + } + } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) { + if (search_key.key.ac_type == flow_info->ac_type) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on ac, ending search")); + break; + } + } else if (search_key.index & SME_QOS_SEARCH_KEY_INDEX_3) { + if (search_key.key.reason == flow_info->reason) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on reason, ending search")); + 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)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on reason, ending search")); + break; + } + } + list_elt = list_next_elt; + } + return list_elt; +} + +/** + * sme_qos_find_all_in_flow_list() - find a flow entry in the flow list + * @mac_ctx: global MAC context + * @search_key: search key + * @fnp: function pointer specifying the action type for the entry found + * + * Utility function to find an flow entry from the flow_list & act on it. + * 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: None + */ +CDF_STATUS sme_qos_find_all_in_flow_list(tpAniSirGlobal mac_ctx, + sme_QosSearchInfo search_key, + sme_QosProcessSearchEntry fnp) +{ + tListElem *list_elt = NULL, *list_next_elt = NULL; + sme_QosSessionInfo *qos_session; + sme_QosFlowInfoEntry *flow_info = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + sme_QosEdcaAcType ac_type; + + list_elt = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!list_elt) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Flow List empty, can't search")); + return CDF_STATUS_E_FAILURE; + } + + while (list_elt) { + list_next_elt = csr_ll_next(&sme_qos_cb.flow_list, list_elt, + false); + flow_info = GET_BASE_ADDR(list_elt, sme_QosFlowInfoEntry, link); + qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId]; + if ((search_key.sessionId != flow_info->sessionId) && + (search_key.sessionId != SME_QOS_SEARCH_SESSION_ID_ANY)) { + list_elt = list_next_elt; + continue; + } + + if ((search_key.index & SME_QOS_SEARCH_KEY_INDEX_1) && + (search_key.key.QosFlowID == flow_info->QosFlowID)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on flowID, ending search")); + status = fnp(mac_ctx, list_elt); + if (CDF_STATUS_E_FAILURE == status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Failed to process entry")); + break; + } + } else if ((search_key.index & SME_QOS_SEARCH_KEY_INDEX_2) && + (search_key.key.ac_type == flow_info->ac_type)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("match found on ac, ending search")); + ac_type = flow_info->ac_type; + flow_info->hoRenewal = + qos_session->ac_info[ac_type].hoRenewal; + status = fnp(mac_ctx, list_elt); + if (CDF_STATUS_E_FAILURE == status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("Failed to process entry")); + break; + } + } + list_elt = list_next_elt; + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_is_acm() - Utility function to check if a particular AC + mandates Admission Control. + \param ac - Enumeration of the various EDCA Access Categories. + + \return true if the AC mandates Admission Control + + \sa + + --------------------------------------------------------------------------*/ +bool sme_qos_is_acm(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, + sme_QosEdcaAcType ac, tDot11fBeaconIEs *pIes) +{ + bool ret_val = false; + tDot11fBeaconIEs *pIesLocal; + if (!pSirBssDesc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: pSirBssDesc is NULL", __func__, __LINE__); + return false; + } + + if (NULL != pIes) { + /* IEs were provided so use them locally */ + pIesLocal = pIes; + } else { + /* IEs were not provided so parse them ourselves */ + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies + (pMac, pSirBssDesc, &pIesLocal))) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: csr_get_parsed_bss_description_ies() failed", + __func__, __LINE__); + return 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 = true; + break; + case SME_QOS_EDCA_AC_BK: + if (pIesLocal->WMMParams.acbk_acm) + ret_val = true; + break; + case SME_QOS_EDCA_AC_VI: + if (pIesLocal->WMMParams.acvi_acm) + ret_val = true; + break; + case SME_QOS_EDCA_AC_VO: + if (pIesLocal->WMMParams.acvo_acm) + ret_val = true; + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: unknown AC = %d", + __func__, __LINE__, ac); + /* Assert */ + CDF_ASSERT(0); + break; + } + } /* IS_QOS_BSS */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + cdf_mem_free(pIesLocal); + } + return ret_val; +} + +/** + * sme_qos_buffer_existing_flows() - buffer existing flows in flow_list + * @mac_ctx: global MAC context + * @sessionid: session ID + * + * Utility function to buffer the existing flows in flow_list, + * so that we can renew them after handoff is done. + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_qos_buffer_existing_flows(tpAniSirGlobal mac_ctx, + uint8_t sessionid) +{ + tListElem *list_entry = NULL, *list_nextentry = NULL; + sme_QosSessionInfo *qos_session; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosCmdInfo cmd; + sme_qos_setupCmdInfo *setupinfo; + + list_entry = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!list_entry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Flow List empty, nothing to buffer")); + return CDF_STATUS_E_FAILURE; + } + + while (list_entry) { + list_nextentry = csr_ll_next(&sme_qos_cb.flow_list, list_entry, + false); + flow_info = GET_BASE_ADDR(list_entry, sme_QosFlowInfoEntry, + link); + if (flow_info->sessionId != sessionid) { + list_entry = list_nextentry; + continue; + } + + if ((SME_QOS_REASON_REQ_SUCCESS == flow_info->reason) || + (SME_QOS_REASON_SETUP == flow_info->reason)) { + cmd.command = SME_QOS_SETUP_REQ; + cmd.pMac = mac_ctx; + cmd.sessionId = sessionid; + setupinfo = &cmd.u.setupCmdInfo; + + setupinfo->HDDcontext = flow_info->HDDcontext; + setupinfo->QoSInfo = flow_info->QoSInfo; + setupinfo->QoSCallback = flow_info->QoSCallback; + /* shouldn't be needed */ + setupinfo->UPType = SME_QOS_WMM_UP_MAX; + setupinfo->QosFlowID = flow_info->QosFlowID; + if (SME_QOS_REASON_SETUP == flow_info->reason) + setupinfo->hoRenewal = false; + else + setupinfo->hoRenewal = true; + + if (!CDF_IS_STATUS_SUCCESS + (sme_qos_buffer_cmd(&cmd, true))) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("couldn't buffer the setup request" + " for flow %d in handoff state"), + flow_info->QosFlowID); + else + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("buffered a setup request for " + "flow %d in handoff state"), + flow_info->QosFlowID); + } else if (SME_QOS_REASON_RELEASE == flow_info->reason) { + cmd.command = SME_QOS_RELEASE_REQ; + cmd.pMac = mac_ctx; + cmd.sessionId = sessionid; + cmd.u.releaseCmdInfo.QosFlowID = flow_info->QosFlowID; + if (!CDF_IS_STATUS_SUCCESS + (sme_qos_buffer_cmd(&cmd, true))) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("couldn't buffer the release req" + " for flow %d in handoff state"), + flow_info->QosFlowID); + else + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("buffered a release request for " + "flow %d in handoff state"), + flow_info->QosFlowID); + } else if (SME_QOS_REASON_MODIFY_PENDING == + flow_info->reason) { + cmd.command = SME_QOS_MODIFY_REQ; + cmd.pMac = mac_ctx; + cmd.sessionId = sessionid; + cmd.u.modifyCmdInfo.QosFlowID = flow_info->QosFlowID; + cmd.u.modifyCmdInfo.QoSInfo = flow_info->QoSInfo; + if (!CDF_IS_STATUS_SUCCESS + (sme_qos_buffer_cmd(&cmd, true))) + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("couldn't buffer the modify req" + " for flow %d in handoff state"), + flow_info->QosFlowID); + else + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_INFO_HIGH, + FL("buffered a modify request for " + "flow %d in handoff state"), + flow_info->QosFlowID); + } + /* delete the entry from Flow List */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Deleting original entry at %p with flowID %d"), + flow_info, flow_info->QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, list_entry, true); + cdf_mem_free(flow_info); + + list_entry = list_nextentry; + } + qos_session = &sme_qos_cb.sessionInfo[sessionid]; + qos_session->uapsdAlreadyRequested = false; + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_delete_existing_flows() - Utility function to Delete the existing + flows in flow_list, if we lost connectivity. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +static CDF_STATUS sme_qos_delete_existing_flows(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + tListElem *pEntry = NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, true); + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "%s: %d: Flow List empty, nothing to delete", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + while (pEntry) { + pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, 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); + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 */ + csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, + true); + cdf_mem_free(flow_info); + } + pEntry = pNextEntry; + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_buffer_cmd() - buffer a request. + * @pcmd: a pointer to the cmd structure to be saved inside the buffered + * cmd link list + * @insert_head: flag indicate if cmd should be added to the list head. + * + * Utility function to buffer a request (setup/modify/release) from client + * while processing another one on the same AC. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_buffer_cmd(sme_QosCmdInfo *pcmd, bool insert_head) +{ + sme_QosSessionInfo *pSession; + sme_QosCmdInfoEntry *pentry = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked", __func__, __LINE__); + pentry = + (sme_QosCmdInfoEntry *) cdf_mem_malloc(sizeof(sme_QosCmdInfoEntry)); + if (!pentry) { + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Memory allocation failure", + __func__, __LINE__); + return CDF_STATUS_E_NOMEM; + } + /* copy the entire CmdInfo */ + pentry->cmdInfo = *pcmd; + + pSession = &sme_qos_cb.sessionInfo[pcmd->sessionId]; + if (insert_head) { + csr_ll_insert_head(&pSession->bufferedCommandList, &pentry->link, + true); + } else { + csr_ll_insert_tail(&pSession->bufferedCommandList, &pentry->link, + true); + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_process_buffered_cmd() - process qos buffered request + * @session_id: Session ID + * + * Utility function to process a buffered request (setup/modify/release) + * initially came from the client. + * + * Return:CDF_STATUS + */ +static CDF_STATUS sme_qos_process_buffered_cmd(uint8_t session_id) +{ + sme_QosSessionInfo *qos_session; + sme_QosCmdInfoEntry *pcmd = NULL; + tListElem *list_elt = NULL; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + sme_QosCmdInfo *qos_cmd = NULL; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Invoked on session %d"), session_id); + qos_session = &sme_qos_cb.sessionInfo[session_id]; + if (!csr_ll_is_list_empty(&qos_session->bufferedCommandList, false)) { + list_elt = csr_ll_remove_head(&qos_session->bufferedCommandList, + true); + if (!list_elt) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("no more buffered commands on session %d"), + session_id); + qos_session->readyForPowerSave = true; + return CDF_STATUS_E_FAILURE; + } + pcmd = GET_BASE_ADDR(list_elt, sme_QosCmdInfoEntry, link); + qos_cmd = &pcmd->cmdInfo; + switch (qos_cmd->command) { + case SME_QOS_SETUP_REQ: + hdd_status = sme_qos_internal_setup_req( + qos_cmd->pMac, qos_cmd->sessionId, + &qos_cmd->u.setupCmdInfo.QoSInfo, + qos_cmd->u.setupCmdInfo.QoSCallback, + qos_cmd->u.setupCmdInfo.HDDcontext, + qos_cmd->u.setupCmdInfo.UPType, + qos_cmd->u.setupCmdInfo.QosFlowID, + true, qos_cmd->u.setupCmdInfo.hoRenewal); + if (SME_QOS_STATUS_SETUP_FAILURE_RSP == hdd_status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_internal_setup_req failed on session %d"), + session_id); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case SME_QOS_RELEASE_REQ: + hdd_status = sme_qos_internal_release_req(qos_cmd->pMac, + qos_cmd->u.releaseCmdInfo.QosFlowID, + true); + if (SME_QOS_STATUS_RELEASE_FAILURE_RSP == hdd_status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_internal_release_req failed on session %d"), + session_id); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case SME_QOS_MODIFY_REQ: + hdd_status = sme_qos_internal_modify_req(qos_cmd->pMac, + &qos_cmd->u.modifyCmdInfo.QoSInfo, + qos_cmd->u.modifyCmdInfo.QosFlowID, + true); + if (SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == + hdd_status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_internal_modify_req failed on session %d"), + session_id); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + case SME_QOS_RESEND_REQ: + hdd_status = sme_qos_re_request_add_ts(qos_cmd->pMac, + qos_cmd->sessionId, + &qos_cmd->u.resendCmdInfo.QoSInfo, + qos_cmd->u.resendCmdInfo.ac, + qos_cmd->u.resendCmdInfo.tspecMask); + if (SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP == + hdd_status) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_re_request_add_ts failed on session %d"), + session_id); + cdf_ret_status = CDF_STATUS_E_FAILURE; + } + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("On session %d unknown cmd = %d"), + session_id, qos_cmd->command); + CDF_ASSERT(0); + break; + } + /* buffered command has been processed, reclaim the memory */ + cdf_mem_free(pcmd); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("cmd buffer empty")); + qos_session->readyForPowerSave = true; + } + return cdf_ret_status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_delete_buffered_requests() - Utility function to Delete the buffered + requests in the buffered_cmd_list, if we lost connectivity. + + \return CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +static CDF_STATUS sme_qos_delete_buffered_requests(tpAniSirGlobal pMac, + uint8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosCmdInfoEntry *pcmd = NULL; + tListElem *pEntry = NULL, *pNextEntry = NULL; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d", + __func__, __LINE__, sessionId); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + pEntry = csr_ll_peek_head(&pSession->bufferedCommandList, true); + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "%s: %d: Buffered List empty, nothing to delete on session %d", + __func__, __LINE__, sessionId); + return CDF_STATUS_E_FAILURE; + } + while (pEntry) { + pNextEntry = + csr_ll_next(&pSession->bufferedCommandList, pEntry, true); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "%s: %d: deleting entry from buffered List", __func__, + __LINE__); + /* delete the entry from Flow List */ + csr_ll_remove_entry(&pSession->bufferedCommandList, pEntry, + true); + /* reclaim the memory */ + pcmd = GET_BASE_ADDR(pEntry, sme_QosCmdInfoEntry, link); + cdf_mem_free(pcmd); + pEntry = pNextEntry; + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_save_assoc_info() - save assoc info. + * @pSession: pointer to QOS session + * @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 + * + * 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. + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_qos_save_assoc_info(sme_QosSessionInfo *pSession, + sme_QosAssocInfo *pAssoc_info) +{ + tSirBssDescription *pBssDesc = NULL; + uint32_t bssLen = 0; + if (NULL == pAssoc_info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: pAssoc_info is NULL", __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + /* clean up the assoc info if already set */ + if (pSession->assocInfo.pBssDesc) { + cdf_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 *) cdf_mem_malloc(bssLen); + if (!pBssDesc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: couldn't allocate memory for the bss Descriptor", + __func__, __LINE__); + return CDF_STATUS_E_NOMEM; + } + cdf_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 CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_setup_fnp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_setup_fnp(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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + pSession = &sme_qos_cb.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); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Entry with flowID = %d getting notified", + __func__, __LINE__, flow_info->QosFlowID); + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_modification_notify_fnp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_modification_notify_fnp(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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + pSession = &sme_qos_cb.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); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Entry with flowID = %d getting notified", + __func__, __LINE__, flow_info->QosFlowID); + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_modify_fnp() - Utility function (pointer) to delete the origianl + 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_modify_fnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosFlowInfoEntry *flow_info = NULL; + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting original entry at %p with flowID %d", + __func__, __LINE__, flow_info, flow_info->QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, true); + /* reclaim the memory */ + cdf_mem_free(flow_info); + break; + default: + break; + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_del_ts_ind_fnp() - Utility function (pointer) to find all Flows on + the perticular 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_del_ts_ind_fnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + sme_QosEdcaAcType ac; + CDF_STATUS lock_status = CDF_STATUS_E_FAILURE; + sme_QosStatusType status; + + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + /* delete the entry from Flow List */ + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + pSession = &sme_qos_cb.sessionInfo[flow_info->sessionId]; + pACInfo = &pSession->ac_info[ac]; + pACInfo->relTrig = SME_QOS_RELEASE_BY_AP; + + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!CDF_IS_STATUS_SUCCESS(lock_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_internal_release_req(pMac, flow_info->QosFlowID, false); + sme_release_global_lock(&pMac->sme); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: QoS Release return status on Flow %d is %d", + __func__, __LINE__, flow_info->QosFlowID, status); + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_reassoc_success_ev_fnp Notification function to HDD + * + * @mac_ctx: Mac context + * @entry: Pointer to an entry in the flow_list + * + * 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 + * + * Return: CDF_STATUS enumaration + */ +CDF_STATUS +sme_qos_reassoc_success_ev_fnp(tpAniSirGlobal mac_ctx, + tListElem *entry) +{ + sme_QosSessionInfo *qos_session; + sme_QosACInfo *ac_info; + sme_QosFlowInfoEntry *flow_info = NULL; + bool delete_entry = false; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + CDF_STATUS pmc_status = CDF_STATUS_E_FAILURE; + if (!entry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId]; + ac_info = &qos_session->ac_info[ac]; + switch (flow_info->reason) { + case SME_QOS_REASON_SETUP: + hdd_status = SME_QOS_STATUS_SETUP_SUCCESS_IND; + delete_entry = 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.Notify PMC as App is looking for APSD + * If we already requested then we don't need to + * do anything.*/ + if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb && + !qos_session->uapsdAlreadyRequested) { + /* this is the first flow to detect we need + * PMC in UAPSD mode */ + pmc_status = sme_ps_start_uapsd(mac_ctx, + flow_info->sessionId, + sme_qos_pmc_offload_start_uapsd_callback, + qos_session); + /* if PMC doesn't return success right away means + * it is yet to put the module in BMPS state & later + * to UAPSD state */ + if (CDF_STATUS_E_FAILURE == pmc_status) { + hdd_status = + SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED; + /* we need to always notify this case */ + flow_info->hoRenewal = false; + } else if (CDF_STATUS_PMC_PENDING == pmc_status) { + /* let other flows know PMC has been notified */ + qos_session->uapsdAlreadyRequested = + true; + + } + } + /* for any other pmc status we declare success */ + break; + case SME_QOS_REASON_RELEASE: + ac_info->num_flows[SME_QOS_TSPEC_INDEX_0]--; + /* fall through */ + case SME_QOS_REASON_MODIFY: + delete_entry = true; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND; + delete_entry = false; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + if (ac_info->requested_QoSInfo[SME_QOS_TSPEC_INDEX_0].ts_info.psb && + !qos_session->uapsdAlreadyRequested) { + /* this is the first flow to detect we need + * PMC in UAPSD mode */ + pmc_status = sme_ps_start_uapsd(mac_ctx, + flow_info->sessionId, + sme_qos_pmc_offload_start_uapsd_callback, + qos_session); + /* if PMC doesn't return success right away means + * it is yet to put the module in BMPS state & + * later to UAPSD state */ + if (CDF_STATUS_E_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 = false; + } else if (CDF_STATUS_PMC_PENDING == pmc_status) { + qos_session->uapsdAlreadyRequested = + 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 = false; + break; + } + if (!delete_entry) { + if (!flow_info->hoRenewal) { + flow_info->QoSCallback(mac_ctx, flow_info->HDDcontext, + &ac_info->curr_QoSInfo[SME_QOS_TSPEC_INDEX_0], + hdd_status, flow_info->QosFlowID); + } else { + flow_info->hoRenewal = false; + } + } else { + /* delete the entry from Flow List */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Deleting entry at %p with flowID %d"), + flow_info, flow_info->QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, entry, true); + /* reclaim the memory */ + cdf_mem_free(flow_info); + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_add_ts_failure_fnp() - 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 CDF_STATUS + + \sa + + --------------------------------------------------------------------------*/ +CDF_STATUS sme_qos_add_ts_failure_fnp(tpAniSirGlobal pMac, tListElem *pEntry) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosFlowInfoEntry *flow_info = NULL; + bool inform_hdd = false; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Entry is NULL", __func__, __LINE__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + pSession = &sme_qos_cb.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 = true; + break; + case SME_QOS_REASON_RELEASE: + hdd_status = SME_QOS_STATUS_RELEASE_FAILURE_RSP; + pACInfo->num_flows[pACInfo->tspec_pending - 1]--; + inform_hdd = true; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + inform_hdd = true; + break; + case SME_QOS_REASON_MODIFY: + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + case SME_QOS_REASON_REQ_SUCCESS: + default: + inform_hdd = 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Deleting entry at %p with flowID %d", + __func__, __LINE__, flow_info, flow_info->QosFlowID); + csr_ll_remove_entry(&sme_qos_cb.flow_list, pEntry, true); + /* reclaim the memory */ + cdf_mem_free(flow_info); + } + return CDF_STATUS_SUCCESS; +} + +/** + * sme_qos_add_ts_success_fnp() - Utility function (pointer) to notify HDD + * + * @mac_ctx: Mac context + * @entry: Pointer to an entry in the flow_list(i.e. tListElem structure). + * + * Description : 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 + * + * Return: Status + */ + +CDF_STATUS sme_qos_add_ts_success_fnp(tpAniSirGlobal mac_ctx, + tListElem *entry) +{ + sme_QosSessionInfo *qos_session; + sme_QosACInfo *ac_info; + sme_QosFlowInfoEntry *flow_info = NULL; + bool inform_hdd = false; + bool delete_entry = false; + sme_QosStatusType hdd_status = SME_QOS_STATUS_SETUP_FAILURE_RSP; + sme_QosEdcaAcType ac; + CDF_STATUS pmc_status = CDF_STATUS_E_FAILURE; + tCsrRoamModifyProfileFields profile_fields; + uint8_t psb; + uint8_t tspec_index; + + if (!entry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Entry is NULL")); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + flow_info = GET_BASE_ADDR(entry, sme_QosFlowInfoEntry, link); + ac = flow_info->ac_type; + qos_session = &sme_qos_cb.sessionInfo[flow_info->sessionId]; + ac_info = &qos_session->ac_info[ac]; + tspec_index = ac_info->tspec_pending - 1; + if (flow_info->tspec_mask != ac_info->tspec_pending) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL(" No need to notify the HDD, the ADDTS " + "success is not for index = %d of the AC = %d"), + flow_info->tspec_mask, ac); + return CDF_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 = false; + inform_hdd = true; + /* check if App is looking for APSD + * notify PMC as App is looking for APSD. If we already + * requested then we don't need to do anything */ + if (ac_info->requested_QoSInfo[tspec_index].ts_info.psb && + !qos_session->uapsdAlreadyRequested) { + /* this is the first flow to detect we need + * PMC in UAPSD mode */ + pmc_status = sme_ps_start_uapsd(mac_ctx, + flow_info->sessionId, + sme_qos_pmc_offload_start_uapsd_callback, + qos_session); + /* if PMC doesn't return success right away means + * it is yet to put the module in BMPS state & later + * to UAPSD state */ + if (CDF_STATUS_E_FAILURE == pmc_status) { + hdd_status = + SME_QOS_STATUS_SETUP_SUCCESS_IND_APSD_SET_FAILED; + /* we need to always notify this case */ + flow_info->hoRenewal = false; + } else if (CDF_STATUS_PMC_PENDING == pmc_status) { + /* let other flows know PMC has been notified */ + qos_session->uapsdAlreadyRequested = + true; + } + /* for any other pmc status we declare success */ + } + break; + case SME_QOS_REASON_RELEASE: + ac_info->num_flows[tspec_index]--; + hdd_status = SME_QOS_STATUS_RELEASE_SUCCESS_RSP; + inform_hdd = true; + delete_entry = true; + break; + case SME_QOS_REASON_MODIFY: + delete_entry = true; + inform_hdd = false; + break; + case SME_QOS_REASON_MODIFY_PENDING: + hdd_status = SME_QOS_STATUS_MODIFY_SETUP_SUCCESS_IND; + delete_entry = false; + flow_info->reason = SME_QOS_REASON_REQ_SUCCESS; + inform_hdd = true; + psb = ac_info->requested_QoSInfo[tspec_index].ts_info.psb; + /* notify PMC if App is looking for APSD + * notify PMC as App is looking for APSD. If we already + * requested then we don't need to do anything. */ + if (psb && !qos_session->uapsdAlreadyRequested) { + /* this is the first flow to detect + * we need PMC in UAPSD mode */ + pmc_status = + sme_ps_start_uapsd(mac_ctx, + flow_info->sessionId, + sme_qos_pmc_offload_start_uapsd_callback, + qos_session); + /* if PMC doesn't return success right + * away means it is yet to put + * the module in BMPS state & later to UAPSD state */ + if (CDF_STATUS_E_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 = false; + } else if (CDF_STATUS_PMC_PENDING == pmc_status) { + /* let other flows know PMC has been notified */ + qos_session->uapsdAlreadyRequested = + true; + } + /* for any other pmc status we declare success */ + } else if (!psb && + ((ac_info->num_flows[flow_info->tspec_mask - 1] == 1) + && (SME_QOS_TSPEC_MASK_BIT_1_2_SET != + ac_info->tspec_mask_status))) { + /* this is the only TSPEC active on this AC */ + /* so indicate that we no longer require APSD */ + qos_session->apsdMask &= + ~(1 << (SME_QOS_EDCA_AC_VO - ac)); + /* Also update modifyProfileFields.uapsd_mask + * in CSR for consistency */ + csr_get_modify_profile_fields(mac_ctx, + flow_info->sessionId, + &profile_fields); + profile_fields.uapsd_mask = + qos_session->apsdMask; + csr_set_modify_profile_fields(mac_ctx, + flow_info->sessionId, + &profile_fields); + if (!qos_session->apsdMask) { + sme_ps_uapsd_disable(mac_ctx, + flow_info->sessionId); + } + } + break; + case SME_QOS_REASON_REQ_SUCCESS: + hdd_status = SME_QOS_STATUS_SETUP_MODIFIED_IND; + inform_hdd = true; + default: + delete_entry = false; + break; + } + if (inform_hdd) { + if (!flow_info->hoRenewal) { + flow_info->QoSCallback(mac_ctx, flow_info->HDDcontext, + &ac_info->curr_QoSInfo[tspec_index], + hdd_status, + flow_info->QosFlowID); + } else { + flow_info->hoRenewal = false; + } + } + if (delete_entry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Deleting entry at %p with flowID %d"), + flow_info, flow_info->QosFlowID); + /* delete the entry from Flow List */ + csr_ll_remove_entry(&sme_qos_cb.flow_list, entry, true); + /* reclaim the memory */ + cdf_mem_free(flow_info); + } + return CDF_STATUS_SUCCESS; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_is_rsp_pending() - 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 interted in + \param ac - Enumeration of the various EDCA Access Categories. + + \return bool + true - Response is pending on an AC + + \sa + + --------------------------------------------------------------------------*/ +static bool sme_qos_is_rsp_pending(uint8_t sessionId, sme_QosEdcaAcType ac) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType acIndex; + bool status = false; + pSession = &sme_qos_cb.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 = true; + break; + } + } + return status; +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_update_hand_off() - 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_qos_update_hand_off(uint8_t sessionId, bool updateHandOff) +{ + sme_QosSessionInfo *pSession; + pSession = &sme_qos_cb.sessionInfo[sessionId]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, + "%s: %d: handoffRequested %d updateHandOff %d", + __func__, __LINE__, pSession->handoffRequested, + updateHandOff); + + pSession->handoffRequested = updateHandOff; + +} + +/*-------------------------------------------------------------------------- + \brief sme_qos_is_uapsd_active() - Function which can be called to determine + if any sessions require PMC to be in U-APSD mode. + \return bool + + 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 bool sme_qos_is_uapsd_active(void) +{ + sme_QosSessionInfo *pSession; + uint8_t sessionId; + for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; ++sessionId) { + pSession = &sme_qos_cb.sessionInfo[sessionId]; + if ((pSession->sessionActive) && (pSession->apsdMask)) { + return true; + } + } + /* no active sessions have U-APSD active */ + return false; +} + +/*-------------------------------------------------------------------------- + \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 pmc_start_uapsd call. + \param status - CDF_STATUS returned by PMC. + + \return None + + \sa + + --------------------------------------------------------------------------*/ +void sme_qos_pmc_offload_start_uapsd_callback(void *callbackContext, + uint32_t sessionId, CDF_STATUS status) +{ + sme_QosSessionInfo *pSession = callbackContext; + pSession->uapsdAlreadyRequested = false; +} + +bool sme_qos_pmc_offload_check_routine(void *callbackContext, uint32_t sessionId) +{ + sme_QosSessionInfo *pSession = &sme_qos_cb.sessionInfo[sessionId]; + + if ((pSession->sessionActive) && (!pSession->readyForPowerSave)) { + return false; + } + return true; + +} + + +CDF_STATUS sme_offload_qos_process_out_of_uapsd_mode(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry = NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + while (pEntry) { + pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, false); + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + pSession = &sme_qos_cb.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 CDF_STATUS_SUCCESS; +} + +CDF_STATUS sme_offload_qos_process_into_uapsd_mode(tpAniSirGlobal pMac, + uint32_t sessionId) +{ + sme_QosSessionInfo *pSession; + tListElem *pEntry = NULL, *pNextEntry = NULL; + sme_QosFlowInfoEntry *flow_info = NULL; + + pEntry = csr_ll_peek_head(&sme_qos_cb.flow_list, false); + if (!pEntry) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Flow List empty, can't search", + __func__, __LINE__); + return CDF_STATUS_E_FAILURE; + } + while (pEntry) { + pNextEntry = csr_ll_next(&sme_qos_cb.flow_list, pEntry, false); + flow_info = GET_BASE_ADDR(pEntry, sme_QosFlowInfoEntry, link); + pSession = &sme_qos_cb.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 CDF_STATUS_SUCCESS; +} + +void sme_qos_cleanup_ctrl_blk_for_handoff(tpAniSirGlobal pMac, uint8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + sme_QosEdcaAcType ac; + pSession = &sme_qos_cb.sessionInfo[sessionId]; + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + pACInfo = &pSession->ac_info[ac]; + cdf_mem_zero(pACInfo->curr_QoSInfo, + sizeof(sme_QosWmmTspecInfo) * + SME_QOS_TSPEC_INDEX_MAX); + cdf_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 = false; + pACInfo->tspec_mask_status = 0; + pACInfo->tspec_pending = false; + pACInfo->hoRenewal = false; + pACInfo->prev_state = SME_QOS_LINK_UP; + } +} + +/** + * sme_qos_is_ts_info_ack_policy_valid() - check if ACK policy is allowed. + * @pMac: The handle returned by mac_open. + * @pQoSInfo: Pointer to sme_QosWmmTspecInfo which contains the WMM TSPEC + * @ related info, provided by HDD + * @sessionId: sessionId returned by sme_open_session. + * + * The SME QoS API exposed to HDD to check if TS info ack policy field can be + * set to "HT-immediate block acknowledgement" + * + * Return: true - Current Association is HT association and so TS info ack + * policy can be set to "HT-immediate block acknowledgement" + */ +bool sme_qos_is_ts_info_ack_policy_valid(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, + uint8_t sessionId) +{ + tDot11fBeaconIEs *pIes = NULL; + sme_QosSessionInfo *pSession; + CDF_STATUS hstatus; + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session Id %d is invalid", + __func__, __LINE__, sessionId); + return false; + } + + pSession = &sme_qos_cb.sessionInfo[sessionId]; + + if (!pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session %d is inactive", + __func__, __LINE__, sessionId); + return false; + } + + if (!pSession->assocInfo.pBssDesc) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session %d has an Invalid BSS Descriptor", + __func__, __LINE__, sessionId); + return false; + } + + hstatus = csr_get_parsed_bss_description_ies(pMac, + pSession->assocInfo.pBssDesc, + &pIes); + if (!CDF_IS_STATUS_SUCCESS(hstatus)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d unable to parse BSS IEs", + __func__, __LINE__, sessionId); + return 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) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: On session %d HT Caps aren't present but application set ack policy to HT ", + __func__, __LINE__, sessionId); + + cdf_mem_free(pIes); + return false; + } + + cdf_mem_free(pIes); + return true; +} + +bool sme_qos_validate_requested_params(tpAniSirGlobal pMac, + sme_QosWmmTspecInfo *pQoSInfo, + uint8_t sessionId) +{ + bool rc = false; + + do { + if (SME_QOS_WMM_TS_DIR_RESV == pQoSInfo->ts_info.direction) + break; + if (!sme_qos_is_ts_info_ack_policy_valid(pMac, pQoSInfo, sessionId)) + break; + + rc = true; + } while (0); + return rc; +} + +static CDF_STATUS qos_issue_command(tpAniSirGlobal pMac, uint8_t sessionId, + eSmeCommandType cmdType, + sme_QosWmmTspecInfo *pQoSInfo, + sme_QosEdcaAcType ac, uint8_t tspec_mask) +{ + CDF_STATUS status = CDF_STATUS_E_RESOURCES; + tSmeCmd *pCommand = NULL; + do { + pCommand = sme_get_command_buffer(pMac); + if (!pCommand) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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 = CDF_STATUS_SUCCESS; + pCommand->u.qosCmd.tspecInfo = *pQoSInfo; + pCommand->u.qosCmd.ac = ac; + } else { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + "%s: %d: NULL pointer passed", + __func__, __LINE__); + status = CDF_STATUS_E_INVAL; + } + break; + case eSmeCommandDelTs: + status = CDF_STATUS_SUCCESS; + pCommand->u.qosCmd.ac = ac; + pCommand->u.qosCmd.tspec_mask = tspec_mask; + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid command type %d", + __func__, __LINE__, cmdType); + status = CDF_STATUS_E_INVAL; + break; + } + } while (0); + if (CDF_IS_STATUS_SUCCESS(status) && pCommand) { + sme_push_command(pMac, pCommand, false); + } else if (pCommand) { + qos_release_command(pMac, pCommand); + } + return status; +} + +bool qos_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + bool fRemoveCmd = true; + do { + switch (pCommand->command) { + case eSmeCommandAddTs: + status = + sme_qos_add_ts_req(pMac, (uint8_t) pCommand->sessionId, + &pCommand->u.qosCmd.tspecInfo, + pCommand->u.qosCmd.ac); + if (CDF_IS_STATUS_SUCCESS(status)) { + fRemoveCmd = false; + status = SME_QOS_STATUS_SETUP_REQ_PENDING_RSP; + } + break; + case eSmeCommandDelTs: + status = + sme_qos_del_ts_req(pMac, (uint8_t) pCommand->sessionId, + pCommand->u.qosCmd.ac, + pCommand->u.qosCmd.tspec_mask); + if (CDF_IS_STATUS_SUCCESS(status)) { + fRemoveCmd = false; + } + break; + default: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: invalid command type %d", + __func__, __LINE__, pCommand->command); + break; + } /* switch */ + } while (0); + return fRemoveCmd; +} + +/** + * sme_qos_re_request_add_ts - Re-send AddTS for the combined QoS request + * + * @mac_ctx Pointer to mac context + * @session_id SME session id + * @qos_info - Tspec information + * @ac - Access category + * @tspec_mask - Tspec Mask + * + * This function is called to re-send AddTS for the combined QoS request + * + * Return: status + */ +static +sme_QosStatusType sme_qos_re_request_add_ts(tpAniSirGlobal mac_ctx, + uint8_t session_id, sme_QosWmmTspecInfo *qos_info, + sme_QosEdcaAcType ac, uint8_t tspec_mask) +{ + sme_QosSessionInfo *session; + sme_QosACInfo *ac_info; + sme_QosStatusType status = SME_QOS_STATUS_MODIFY_SETUP_FAILURE_RSP; + sme_QosCmdInfo cmd; + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL(" Invoked on session %d for AC %d TSPEC %d"), + session_id, ac, tspec_mask); + session = &sme_qos_cb.sessionInfo[session_id]; + ac_info = &session->ac_info[ac]; + /* need to vote off powersave for the duration of this request */ + session->readyForPowerSave = false; + /* + * call PMC's request for power function + * AND another check is added considering the flowing scenario + * Addts reqest 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 safegaurd the above scenario, + * 2& also won't confuse PE with back to back Addts or Addts + * followed by Reassoc. + */ + if (sme_qos_is_rsp_pending(session_id, ac)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL(" 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"), + session_id, ac, + ac_info->curr_state); + /* buffer cmd */ + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = mac_ctx; + cmd.sessionId = session_id; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = tspec_mask; + cmd.u.resendCmdInfo.QoSInfo = *qos_info; + if (!CDF_IS_STATUS_SUCCESS(sme_qos_buffer_cmd(&cmd, false))) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_ERROR, + FL("On session %d unable to buffer the AddTS " + "request for AC %d TSPEC %d in state %d"), + session_id, ac, tspec_mask, + ac_info->curr_state); + /* unable to buffer the request + * nothing is pending so vote powersave back on */ + session->readyForPowerSave = 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 (ac_info->curr_state) { + case SME_QOS_QOS_ON: + { + /* if ACM, send out a new ADDTS */ + ac_info->hoRenewal = true; + status = sme_qos_setup(mac_ctx, session_id, qos_info, ac); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("sme_qos_setup returned in SME_QOS_QOS_ON state")); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + FL("sme_qos_setup AC %d with status =%d"), ac, status); + if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP != status) { + /* we aren't waiting for a response from the AP */ + /* so vote powersave back on */ + session->readyForPowerSave = true; + } + if (SME_QOS_STATUS_SETUP_REQ_PENDING_RSP == status) { + status = SME_QOS_STATUS_MODIFY_SETUP_PENDING_RSP; + ac_info->tspec_pending = tspec_mask; + } 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)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("UAPSD is setup already status = %d "), + status); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_qos_setup return status = %d "), + status); + } + } + break; + case SME_QOS_HANDOFF: + case SME_QOS_REQUESTED: + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Re-Add request in state = %d buffer the request"), + ac_info->curr_state); + cmd.command = SME_QOS_RESEND_REQ; + cmd.pMac = mac_ctx; + cmd.sessionId = session_id; + cmd.u.resendCmdInfo.ac = ac; + cmd.u.resendCmdInfo.tspecMask = tspec_mask; + cmd.u.resendCmdInfo.QoSInfo = *qos_info; + if (!CDF_IS_STATUS_SUCCESS(sme_qos_buffer_cmd(&cmd, false))) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL(" couldn't buf the read request state = %d"), + ac_info->curr_state); + /* unable to buffer the request + * nothing is pending so vote powersave back on */ + session->readyForPowerSave = 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, */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("ReAdd request in unexpected state = %d"), + ac_info->curr_state); + /* unable to service the request + * nothing is pending so vote powersave back on */ + session->readyForPowerSave = 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_qos_process_buffered_cmd(session_id); + } + return status; +} + +static void sme_qos_init_a_cs(tpAniSirGlobal pMac, uint8_t sessionId) +{ + sme_QosSessionInfo *pSession; + sme_QosEdcaAcType ac; + pSession = &sme_qos_cb.sessionInfo[sessionId]; + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + cdf_mem_zero(&pSession->ac_info[ac], sizeof(sme_QosACInfo)); + sme_qos_state_transition(sessionId, ac, SME_QOS_INIT); + } +} + +static CDF_STATUS sme_qos_request_reassoc(tpAniSirGlobal pMac, uint8_t sessionId, + tCsrRoamModifyProfileFields * + pModFields, bool fForce) +{ + sme_QosSessionInfo *pSession; + sme_QosACInfo *pACInfo; + CDF_STATUS status; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Invoked on session %d with UAPSD mask 0x%X", + __func__, __LINE__, sessionId, pModFields->uapsd_mask); + pSession = &sme_qos_cb.sessionInfo[sessionId]; + status = + csr_reassoc(pMac, sessionId, pModFields, &pSession->roamID, fForce); + if (CDF_IS_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]; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_qos_state_transition */ + /* will change the previous state */ + if (SME_QOS_HANDOFF != pACInfo->curr_state) { + sme_qos_state_transition(sessionId, ac, + SME_QOS_HANDOFF); + } + } + } + return status; +} + +static uint32_t sme_qos_assign_flow_id(void) +{ + uint32_t flowId; + flowId = sme_qos_cb.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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + "%s: %d: Software Test made the flow counter wrap, " + "QoS may no longer be functional", + __func__, __LINE__); + sme_qos_cb.nextFlowId = SME_QOS_MIN_FLOW_ID; + } else { + sme_qos_cb.nextFlowId++; + } + return flowId; +} + +static uint8_t sme_qos_assign_dialog_token(void) +{ + uint8_t token; + token = sme_qos_cb.nextDialogToken; + if (SME_QOS_MAX_DIALOG_TOKEN == token) { + /* wrap is ok */ + sme_qos_cb.nextDialogToken = SME_QOS_MIN_DIALOG_TOKEN; + } else { + sme_qos_cb.nextDialogToken++; + } + return token; +} + +/** + * sme_qos_tspec_active() - API exposed to HDD to check no of active Tspecs + * + * @pMac: The handle returned by macOpen + * @ac: Determines type of Access Category + * @sessionId: sessionId returned by sme_OpenSession + * @pActiveTspec: return the number of active Tspecs + * + * Return: true if success, otherwise false + */ +bool sme_qos_tspec_active(tpAniSirGlobal pMac, sme_ac_enum_type ac, + uint8_t sessionId, uint8_t *pActiveTspec) +{ + sme_QosSessionInfo *pSession = NULL; + sme_QosACInfo *pACInfo = NULL; + + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session Id %d is invalid", + __func__, __LINE__, sessionId); + return false; + } + + pSession = &sme_qos_cb.sessionInfo[sessionId]; + + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d pSession not found sessionId:%d", + __func__, __LINE__, sessionId); + return false; + } + + if (!pSession->sessionActive) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: %d: Session %d is inactive", + __func__, __LINE__, sessionId); + return false; + } + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: Session %d is active", + __func__, __LINE__, sessionId); + + 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 */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AC %d has QoS active", + __func__, __LINE__, sessionId, ac); + + /* Are any TSPECs active? */ + if (pACInfo->tspec_mask_status) { + /* 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 */ + *pActiveTspec = 2; + } else { + /* only one TSPEC is active */ + *pActiveTspec = 1; + } + } else { + *pActiveTspec = 0; + } + } else { + /* Hardcoding value to INVALID_TSPEC to indicate the caller + * not to update UAPSD parameters as QOS is not active + */ + *pActiveTspec = INVALID_TSPEC; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: %d: On session %d AC %d has no QoS active", + __func__, __LINE__, sessionId, ac); + } + + return true; +} + +#endif /* WLAN_MDM_CODE_REDUCTION_OPT */ diff --git a/core/sme/src/rrm/sme_rrm.c b/core/sme/src/rrm/sme_rrm.c new file mode 100644 index 000000000000..a68f71c09d68 --- /dev/null +++ b/core/sme/src/rrm/sme_rrm.c @@ -0,0 +1,1566 @@ +/* + * 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 sme_Rrm.c + + \brief implementation for SME RRM APIs + + ========================================================================*/ + +/* $Header$ */ + +#if defined WLAN_FEATURE_VOWIFI +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "ani_global.h" +#include "sme_inside.h" +#include "sme_api.h" +#include "sms_debug.h" +#include "cfg_api.h" + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "host_diag_core_event.h" +#include "host_diag_core_log.h" +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +#include "csr_inside_api.h" + +#include "rrm_global.h" + + +/* Roam score for a neighbor AP will be calculated based on the below definitions. + The calculated roam score will be used to select the roamable 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; + +/** + * rrm_ll_purge_neighbor_cache() -Purges all the entries in the neighbor cache + * + * @pMac: Pointer to the Hal Handle. + * @pList: Pointer the List that should be purged. + * + * This function purges all the entries in the neighbor cache and frees up all + * the internal nodes + * + * Return: void + */ +static void rrm_ll_purge_neighbor_cache(tpAniSirGlobal pMac, + tDblLinkList *pList) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pNeighborReportDesc; + csr_ll_lock(pList); + while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) { + pNeighborReportDesc = + GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List); + cdf_mem_free(pNeighborReportDesc->pNeighborBssDescription); + cdf_mem_free(pNeighborReportDesc); + } + csr_ll_unlock(pList); + return; +} + +/** + * rrm_indicate_neighbor_report_result() -calls the callback registered for + * neighbor report + * @pMac: Pointer to the Hal Handle. + * @cdf_status - CDF_STATUS_SUCCESS/CDF_STATUS_FAILURE based on whether a valid + * report is received or neighbor timer expired + * + * 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. + * + * Return: void + */ +void rrm_indicate_neighbor_report_result(tpAniSirGlobal pMac, CDF_STATUS cdf_status) +{ + NeighborReportRspCallback callback; + void *callbackContext; + + /* Reset the neighbor response pending status */ + pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = + false; + + /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */ + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&pMac->rrm.rrmSmeContext. + neighborReqControlInfo. + neighborRspWaitTimer)) { + sms_log(pMac, LOG1, FL("No entry in neighbor report cache")); + cdf_mc_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, cdf_status); + + return; + +} + +/** + * sme_RrmBeaconReportXmitInd () - Send beacon report + * @mac_ctx Pointer to mac context + * @result_arr scan results + * @msrmnt_status flag to indicate that the measurement is done. + * @bss_count bss count + * + * Create and send the beacon report Xmit ind message to PE. + * + * Return: status + */ + +static CDF_STATUS +sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, + tCsrScanResultInfo **result_arr, uint8_t msrmnt_status, + uint8_t bss_count) +{ + tpSirBssDescription bss_desc = NULL; + tpSirBeaconReportXmitInd beacon_rep; + uint16_t length, ie_len; + uint8_t i = 0, j = 0; + tCsrScanResultInfo *cur_result = NULL; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, "Beacon report xmit Ind to PE"); +#endif + + if (NULL == result_arr && !msrmnt_status) { + sms_log(mac_ctx, LOGE, "Beacon report xmit Ind to PE Failed"); + return CDF_STATUS_E_FAILURE; + } + + if (result_arr) + cur_result = result_arr[j]; + + do { + length = sizeof(tSirBeaconReportXmitInd); + beacon_rep = cdf_mem_malloc(length); + if (NULL == beacon_rep) { + sms_log(mac_ctx, LOGP, + "Unable to allocate memory for beacon report"); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_zero(beacon_rep, length); +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Allocated memory for beacon_rep")); +#endif + beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND; + beacon_rep->length = length; + beacon_rep->uDialogToken = rrm_ctx->token; + beacon_rep->duration = rrm_ctx->duration[0]; + beacon_rep->regClass = rrm_ctx->regClass; + cdf_mem_copy(beacon_rep->bssId, rrm_ctx->sessionBssId.bytes, + CDF_MAC_ADDR_SIZE); + + i = 0; + while (cur_result) { + bss_desc = &cur_result->BssDescriptor; + if (bss_desc == NULL) + break; + ie_len = GET_IE_LEN_IN_BSS(bss_desc->length); + beacon_rep->pBssDescription[i] = + cdf_mem_malloc(ie_len + + sizeof(tSirBssDescription)); + if (NULL == + beacon_rep->pBssDescription[i]) + break; + cdf_mem_copy(beacon_rep->pBssDescription[i], + bss_desc, sizeof(tSirBssDescription)); + cdf_mem_copy( + &beacon_rep->pBssDescription[i]->ieFields[0], + bss_desc->ieFields, ie_len); + sms_log(mac_ctx, LOG1, + ".RRM Result Bssid = " MAC_ADDRESS_STR + " chan= %d, rssi = -%d", + MAC_ADDR_ARRAY( + beacon_rep->pBssDescription[i]->bssId), + beacon_rep->pBssDescription[i]->channelId, + beacon_rep->pBssDescription[i]->rssi * (-1)); + beacon_rep->numBssDesc++; + if (++i >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + cur_result = + result_arr[j + i]; + } + + j += i; + if (!result_arr || (cur_result == NULL) + || (j >= bss_count)) { + cur_result = NULL; + sms_log(mac_ctx, LOG1, + "Reached to max/last BSS in cur_result list"); + } else { + cur_result = result_arr[j]; + sms_log(mac_ctx, LOG1, + "Move to the next BSS set in cur_result list"); + } + beacon_rep->fMeasureDone = + (cur_result) ? false : msrmnt_status; + sms_log(mac_ctx, LOG1, + "SME Sending BcnRepXmit to PE numBss %d i %d j %d", + beacon_rep->numBssDesc, i, j); + status = cds_send_mb_message_to_mac(beacon_rep); + } while (cur_result); + + return status; +} + +#if defined(FEATURE_WLAN_ESE_UPLOAD) +/** + * sme_ese_send_beacon_req_scan_results () - Send beacon report + * @mac_ctx Pointer to mac context + * @session_id - session id + * @result_arr scan results + * @msrmnt_status flag to indicate that the measurement is done. + * @bss_count number of bss found + * + * 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; + * + * Return: status + */ +static CDF_STATUS sme_ese_send_beacon_req_scan_results( + tpAniSirGlobal mac_ctx, uint32_t session_id, + uint8_t channel, tCsrScanResultInfo **result_arr, + uint8_t msrmnt_status, uint8_t bss_count) +{ + CDF_STATUS status = CDF_STATUS_E_FAILURE; + tSirRetStatus fill_ie_status; + tpSirBssDescription bss_desc = NULL; + uint32_t ie_len = 0; + uint32_t out_ie_len = 0; + uint8_t bss_counter = 0; + tCsrScanResultInfo *cur_result = NULL; + tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + tCsrRoamInfo roam_info; + tSirEseBcnReportRsp bcn_rpt_rsp; + tpSirEseBcnReportRsp bcn_report = &bcn_rpt_rsp; + tpCsrEseBeaconReqParams cur_meas_req = NULL; + uint8_t i = 0, j = 0; + tBcnReportFields *bcn_rpt_fields; + + if (NULL == rrm_ctx) { + sms_log(mac_ctx, LOGE, "rrm_ctx is NULL"); + return CDF_STATUS_E_FAILURE; + } + + if (NULL == result_arr && !msrmnt_status) { + sms_log(mac_ctx, LOGE, "Beacon report xmit Ind to HDD Failed"); + return CDF_STATUS_E_FAILURE; + } + + if (result_arr) + cur_result = result_arr[bss_counter]; + + cdf_mem_zero(&bcn_rpt_rsp, sizeof(tSirEseBcnReportRsp)); + do { + cur_meas_req = NULL; + for (i = 0; i < rrm_ctx->eseBcnReqInfo.numBcnReqIe; i++) { + if (rrm_ctx->eseBcnReqInfo.bcnReq[i].channel == + channel) { + cur_meas_req = + &rrm_ctx->eseBcnReqInfo.bcnReq[i]; + break; + } + } + if (NULL != cur_meas_req) + bcn_report->measurementToken = + cur_meas_req->measurementToken; + sms_log(mac_ctx, LOG1, "Channel(%d) MeasToken(%d)", channel, + bcn_report->measurementToken); + + j = 0; + while (cur_result) { + bss_desc = &cur_result->BssDescriptor; + if (NULL == bss_desc) { + cur_result = NULL; + break; + } + ie_len = GET_IE_LEN_IN_BSS(bss_desc->length); + bcn_rpt_fields = + &bcn_report->bcnRepBssInfo[j].bcnReportFields; + bcn_rpt_fields->ChanNum = + bss_desc->channelId; + bcn_report->bcnRepBssInfo[j].bcnReportFields.Spare = 0; + if (NULL != cur_meas_req) + bcn_rpt_fields->MeasDuration = + cur_meas_req->measurementDuration; + bcn_rpt_fields->PhyType = bss_desc->nwType; + bcn_rpt_fields->RecvSigPower = bss_desc->rssi; + bcn_rpt_fields->ParentTsf = bss_desc->parentTSF; + bcn_rpt_fields->TargetTsf[0] = bss_desc->timeStamp[0]; + bcn_rpt_fields->TargetTsf[1] = bss_desc->timeStamp[1]; + bcn_rpt_fields->BcnInterval = bss_desc->beaconInterval; + bcn_rpt_fields->CapabilityInfo = + bss_desc->capabilityInfo; + + cdf_mem_copy(bcn_rpt_fields->Bssid, + bss_desc->bssId, sizeof(tSirMacAddr)); + fill_ie_status = + sir_beacon_ie_ese_bcn_report(mac_ctx, + (uint8_t *) bss_desc->ieFields, + ie_len, + &(bcn_report->bcnRepBssInfo[j].pBuf), + &out_ie_len); + if (eSIR_FAILURE == fill_ie_status) + continue; + bcn_report->bcnRepBssInfo[j].ieLen = out_ie_len; + + sms_log(mac_ctx, LOG1, "Bssid(" MAC_ADDRESS_STR")" + "Channel=%d Rssi=%d", + MAC_ADDR_ARRAY(bss_desc->bssId), + bss_desc->channelId, (-1) * bss_desc->rssi); + bcn_report->numBss++; + if (++j >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + cur_result = result_arr[j]; + } + + bss_counter += j; + if (!result_arr || !cur_result + || (bss_counter >= SIR_BCN_REPORT_MAX_BSS_DESC)) { + cur_result = NULL; + sms_log(mac_ctx, LOGE, + "Reached to the max/last BSS in cur_result list"); + } else { + cur_result = result_arr[bss_counter]; + sms_log(mac_ctx, LOGE, + "Move to the next BSS set in cur_result list"); + } + + bcn_report->flag = + (msrmnt_status << 1) | ((cur_result) ? true : false); + + sms_log(mac_ctx, LOG1, "SME Sending BcnRep to HDD numBss(%d)" + " j(%d) bss_counter(%d) flag(%d)", + bcn_report->numBss, j, bss_counter, + bcn_report->flag); + + roam_info.pEseBcnReportRsp = bcn_report; + status = csr_roam_call_callback(mac_ctx, session_id, &roam_info, + 0, eCSR_ROAM_ESE_BCN_REPORT_IND, 0); + + /* Free the memory allocated to IE */ + for (i = 0; i < j; i++) + if (bcn_report->bcnRepBssInfo[i].pBuf) + cdf_mem_free(bcn_report->bcnRepBssInfo[i].pBuf); + } while (cur_result); + return status; +} + +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + +/** + * sme_rrm_send_scan_result() - to get scan result and send the beacon report + * @mac_ctx: pointer to mac context + * @num_chan: number of channels + * @chan_list: list of channels to fetch the result from + * @measurementdone: Flag to indicate measurement done or no + * + * This function is called to get the scan result from CSR and send the beacon + * report xmit ind message to PE + * + * Return: CDF_STATUS + */ +static CDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, + uint8_t num_chan, + uint8_t *chan_list, + uint8_t measurementdone) +{ + tCsrScanResultFilter filter; + tScanResultHandle result_handle; + tCsrScanResultInfo *scan_results, *next_result; + tCsrScanResultInfo *scanresults_arr[SIR_BCN_REPORT_MAX_BSS_DESC]; + CDF_STATUS status; + uint8_t counter = 0; + tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + uint32_t session_id; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Send scan result to PE ")); +#endif + + cdf_mem_zero(&filter, sizeof(filter)); + cdf_mem_zero(scanresults_arr, + sizeof(next_result) * SIR_BCN_REPORT_MAX_BSS_DESC); + filter.BSSIDs.numOfBSSIDs = 1; + filter.BSSIDs.bssid = (struct cdf_mac_addr *)&rrm_ctx->bssId; + + if (rrm_ctx->ssId.length) { + filter.SSIDs.SSIDList = + (tCsrSSIDInfo *) cdf_mem_malloc(sizeof(tCsrSSIDInfo)); + if (filter.SSIDs.SSIDList == NULL) { + sms_log(mac_ctx, LOGP, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Allocated memory for SSIDList")); +#endif + cdf_mem_zero(filter.SSIDs.SSIDList, sizeof(tCsrSSIDInfo)); + + filter.SSIDs.SSIDList->SSID.length = + rrm_ctx->ssId.length; + cdf_mem_copy(filter.SSIDs.SSIDList->SSID.ssId, + rrm_ctx->ssId.ssId, rrm_ctx->ssId.length); + filter.SSIDs.numOfSSIDs = 1; + } else { + filter.SSIDs.numOfSSIDs = 0; + } + + filter.ChannelInfo.numOfChannels = num_chan; + filter.ChannelInfo.ChannelList = chan_list; + filter.fMeasurement = true; + + /* + * In case this is beacon report request from last AP (before roaming) + * following call to csr_roam_get_session_id_from_bssid will fail, + * hence use current session ID instead of one stored in SME rrm context + */ + if (CDF_STATUS_E_FAILURE == csr_roam_get_session_id_from_bssid(mac_ctx, + &rrm_ctx->sessionBssId, &session_id)) { + sms_log(mac_ctx, LOG1, + FL("BSSID mismatch, using current session_id")); + session_id = mac_ctx->roam.roamSession->sessionId; + } + status = sme_scan_get_result(mac_ctx, (uint8_t) session_id, + &filter, &result_handle); + + if (filter.SSIDs.SSIDList) { + /* Free the memory allocated for SSIDList */ + cdf_mem_free(filter.SSIDs.SSIDList); +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Free memory for SSIDList")); +#endif + } + + if (NULL == result_handle) { + /* + * 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 respose 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) + return status; +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) + status = sme_ese_send_beacon_req_scan_results(mac_ctx, + session_id, chan_list[0], + NULL, measurementdone, 0); + else +#endif /*FEATURE_WLAN_ESE_UPLOAD */ + status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, + NULL, measurementdone, 0); + return status; + } + scan_results = sme_scan_result_get_first(mac_ctx, result_handle); + if (NULL == scan_results && measurementdone) { +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) { + status = sme_ese_send_beacon_req_scan_results(mac_ctx, + session_id, + chan_list[0], + NULL, + measurementdone, + 0); + } else +#endif /*FEATURE_WLAN_ESE_UPLOAD */ + status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, + NULL, measurementdone, 0); + } + counter = 0; + while (scan_results) { + next_result = sme_scan_result_get_next(mac_ctx, result_handle); + if (scan_results->timer >= rrm_scan_timer) + scanresults_arr[counter++] = scan_results; + scan_results = next_result; + if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + } + if (counter) { + sms_log(mac_ctx, LOG1, + FL(" Number of BSS Desc with RRM Scan %d "), + counter); +#if defined(FEATURE_WLAN_ESE_UPLOAD) + if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) + status = sme_ese_send_beacon_req_scan_results(mac_ctx, + session_id, chan_list[0], + scanresults_arr, measurementdone, + counter); + else +#endif /*FEATURE_WLAN_ESE_UPLOAD */ + status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, + scanresults_arr, measurementdone, + counter); + } + sme_scan_result_purge(mac_ctx, result_handle); + return status; +} + +/** + * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE + * @halHandle - Pointer to the Hal Handle. + * @pContext - Pointer to the data context. + * @scanId - Scan ID. + * @status - CSR Status. + * + * 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. + * + * Return : 0 for success, non zero for failure + */ + +static CDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, + void *pContext, + uint8_t sessionId, + uint32_t scanId, + eCsrScanStatus status) +{ + + uint16_t interval; + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + uint32_t time_tick; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(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_rrm_send_scan_result(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 randmization interval. */ + time_tick = cdf_mc_timer_get_system_ticks(); + interval = + time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, "Set timer for interval %d ", interval); +#endif + cdf_mc_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_rrm_send_scan_result(pMac, 1, + &pSmeRrmContext->channelList. + ChannelList[pSmeRrmContext->currentIndex], + true); + cdf_mem_free(pSmeRrmContext->channelList.ChannelList); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + pSmeRrmContext->eseBcnReqInProgress = false; +#endif +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, FL("Free memory for ChannelList")); +#endif + } + + return CDF_STATUS_SUCCESS; +} + +/** + * sme_rrm_issue_scan_req() - To issue rrm scan request + * @mac_ctx: pointer to mac context + * + * This routine is called to issue rrm scan request + * + * Return: CDF_STATUS + */ +CDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) +{ + /* Issue scan request. */ + tCsrScanRequest scan_req; + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + uint32_t session_id; + tSirScanType scan_type; + + status = csr_roam_get_session_id_from_bssid(mac_ctx, + &sme_rrm_ctx->sessionBssId, &session_id); + if (status != CDF_STATUS_SUCCESS) { + sms_log(mac_ctx, LOGE, FL("Invalid sme Session ID")); + return CDF_STATUS_E_FAILURE; + } + + if ((sme_rrm_ctx->currentIndex) >= + sme_rrm_ctx->channelList.numOfChannels) + return status; + + if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource || + eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource) + scan_type = sme_rrm_ctx->measMode[sme_rrm_ctx->currentIndex]; + else + scan_type = sme_rrm_ctx->measMode[0]; + + if ((eSIR_ACTIVE_SCAN == scan_type) || + (eSIR_PASSIVE_SCAN == scan_type)) { +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Issue scan request")); +#endif + cdf_mem_zero(&scan_req, sizeof(scan_req)); + /* set scan_type, active or passive */ + scan_req.bcnRptReqScan = true; + scan_req.scanType = scan_type; + cdf_mem_copy(&scan_req.bssid.bytes, sme_rrm_ctx->bssId, + CDF_MAC_ADDR_SIZE); + if (sme_rrm_ctx->ssId.length) { + scan_req.SSIDs.numOfSSIDs = 1; + scan_req.SSIDs.SSIDList = + (tCsrSSIDInfo *)cdf_mem_malloc( + sizeof(tCsrSSIDInfo)); + if (NULL == scan_req.SSIDs.SSIDList) { + sms_log(mac_ctx, LOGP, + FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, + FL("Allocated memory for pSSIDList")); +#endif + cdf_mem_zero(scan_req.SSIDs.SSIDList, + sizeof(tCsrSSIDInfo)); + scan_req.SSIDs.SSIDList->SSID.length = + sme_rrm_ctx->ssId.length; + cdf_mem_copy(scan_req.SSIDs.SSIDList->SSID.ssId, + sme_rrm_ctx->ssId.ssId, + sme_rrm_ctx->ssId.length); + } + + /* + * set min and max channel time + * sme_rrm_ctx->duration; Dont use min timeout. + */ + scan_req.minChnTime = 0; + if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource || + eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource) + scan_req.maxChnTime = sme_rrm_ctx->duration[ + sme_rrm_ctx->currentIndex]; + else + scan_req.maxChnTime = sme_rrm_ctx->duration[0]; + + sms_log(mac_ctx, LOG1, FL("Scan Type(%d) Max Dwell Time(%d)"), + scan_req.scanType, scan_req.maxChnTime); + + rrm_scan_timer = cdf_mc_timer_get_system_time(); + +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("For Duration %d "), + scan_req.maxChnTime); +#endif + /* set BSSType to default type */ + scan_req.BSSType = eCSR_BSS_TYPE_ANY; + /*Scan all the channels */ + scan_req.ChannelInfo.numOfChannels = 1; + scan_req.ChannelInfo.ChannelList = + &sme_rrm_ctx->channelList.ChannelList[ + sme_rrm_ctx->currentIndex]; +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("On channel %d "), + sme_rrm_ctx->channelList.ChannelList[ + sme_rrm_ctx->currentIndex]); +#endif + /* set requestType to full scan */ + scan_req.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; + status = sme_scan_request(mac_ctx, (uint8_t) session_id, + &scan_req, + &sme_rrm_scan_request_callback, NULL); + + if (sme_rrm_ctx->ssId.length) { + cdf_mem_free(scan_req.SSIDs.SSIDList); +#if defined WLAN_VOWIFI_DEBUG + sms_log(mac_ctx, LOGE, FL("Free memory for SSIDList")); +#endif + } + } else if (eSIR_BEACON_TABLE == scan_type) { + /* + * 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 ((sme_rrm_ctx->currentIndex + 1) < + sme_rrm_ctx->channelList.numOfChannels) { + sme_rrm_send_scan_result(mac_ctx, 1, + &sme_rrm_ctx->channelList.ChannelList[ + sme_rrm_ctx->currentIndex], false); + /* Advance the current index. */ + sme_rrm_ctx->currentIndex++; + sme_rrm_issue_scan_req(mac_ctx); +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + sme_rrm_ctx->eseBcnReqInProgress = false; +#endif + } else { + /* + * Done with the measurement. Clean up all context and + * send a message to PE with measurement done flag set. + */ + sme_rrm_send_scan_result(mac_ctx, 1, + &sme_rrm_ctx->channelList.ChannelList[ + sme_rrm_ctx->currentIndex], true); + cdf_mem_free(sme_rrm_ctx->channelList.ChannelList); + } + } else { + sms_log(mac_ctx, LOGE, FL("Unknown beacon report req mode(%d)"), + scan_type); + /* + * 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_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0); + } + return status; +} + +/** + * sme_rrm_process_beacon_report_req_ind() -Process beacon report request + * @pMac:- Global Mac structure + * @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. + * + * This is called to process the Beacon + * report request from peer AP forwarded through PE . + * + * Return : CDF_STATUS_SUCCESS - Validation is successful. + */ +CDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, void *pMsgBuf) +{ + tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + uint32_t len = 0, i = 0; + CDF_STATUS status = CDF_STATUS_SUCCESS; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(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_cfg_get_str_len(pMac, WNI_CFG_VALID_CHANNEL_LIST, &len); + pSmeRrmContext->channelList.ChannelList = cdf_mem_malloc(len); + if (pSmeRrmContext->channelList.ChannelList == NULL) { + sms_log(pMac, LOGP, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, FL("Allocated memory for ChannelList")); +#endif + csr_get_cfg_valid_channels(pMac, + pSmeRrmContext->channelList.ChannelList, + &len); + pSmeRrmContext->channelList.numOfChannels = (uint8_t) len; +#if defined WLAN_VOWIFI_DEBUG + sms_log(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 + sms_log(pMac, LOGE, "channel == 255"); +#endif + + len += pBeaconReq->channelList.numChannels; + + pSmeRrmContext->channelList.ChannelList = cdf_mem_malloc(len); + if (pSmeRrmContext->channelList.ChannelList == NULL) { + sms_log(pMac, LOGP, FL("cdf_mem_malloc failed")); + return CDF_STATUS_E_NOMEM; + } +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, FL("Allocated memory for ChannelList")); +#endif + + if (pBeaconReq->channelInfo.channelNum != 255) { +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, "channel == %d ", + pBeaconReq->channelInfo.channelNum); +#endif + if (csr_roam_is_channel_valid + (pMac, pBeaconReq->channelInfo.channelNum)) + pSmeRrmContext->channelList. + ChannelList[pSmeRrmContext->channelList. + numOfChannels++] = + pBeaconReq->channelInfo.channelNum; +#if defined WLAN_VOWIFI_DEBUG + else + sms_log(pMac, LOGE, + "is Invalid channel, Ignoring this channel"); +#endif + } + + for (i = 0; i < pBeaconReq->channelList.numChannels; i++) { + if (csr_roam_is_channel_valid + (pMac, pBeaconReq->channelList.channelNumber[i])) { + pSmeRrmContext->channelList. + ChannelList[pSmeRrmContext->channelList. + numOfChannels] = + pBeaconReq->channelList.channelNumber[i]; + pSmeRrmContext->channelList.numOfChannels++; + } + } + } + + /* Copy session bssid */ + cdf_mem_copy(pSmeRrmContext->sessionBssId.bytes, pBeaconReq->bssId, + sizeof(tSirMacAddr)); + + /* copy measurement bssid */ + cdf_mem_copy(pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, + sizeof(tSirMacAddr)); + + /* Copy ssid */ + cdf_mem_copy(&pSmeRrmContext->ssId, &pBeaconReq->ssId, + sizeof(tAniSSID)); + + pSmeRrmContext->token = pBeaconReq->uDialogToken; + pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass; + pSmeRrmContext->randnIntvl = + CDF_MAX(pBeaconReq->randomizationInterval, + pSmeRrmContext->rrmConfig.maxRandnInterval); + pSmeRrmContext->currentIndex = 0; + pSmeRrmContext->msgSource = pBeaconReq->msgSource; + cdf_mem_copy((uint8_t *) &pSmeRrmContext->measMode, + (uint8_t *) &pBeaconReq->fMeasurementtype, + SIR_ESE_MAX_MEAS_IE_REQS); + cdf_mem_copy((uint8_t *) &pSmeRrmContext->duration, + (uint8_t *) &pBeaconReq->measurementDuration, + SIR_ESE_MAX_MEAS_IE_REQS); + + status = sme_rrm_issue_scan_req(pMac); + + return status; +} + +/** + * sme_rrm_neighbor_report_request() - This is API can be used to trigger a + * Neighbor report from the peer. + * @sessionId: session identifier on which the request should be made. + * @pNeighborReq: a pointer to a neighbor report request. + * + * This is API can be used to trigger a Neighbor report from the peer. + * + * Return: CDF_STATUS_SUCCESS - Validation is successful. + */ +CDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t sessionId, + tpRrmNeighborReq pNeighborReq, + tpRrmNeighborRspCallbackInfo + callbackInfo) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpSirNeighborReportReqInd pMsg; + tCsrRoamSession *pSession; + +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, + FL("Request to send Neighbor report request received ")); +#endif + if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { + sms_log(pMac, LOGE, FL("Invalid session %d"), sessionId); + return CDF_STATUS_E_INVAL; + } + pSession = CSR_GET_SESSION(pMac, sessionId); + + /* If already a report is pending, return failure */ + if (true == + pMac->rrm.rrmSmeContext.neighborReqControlInfo. + isNeighborRspPending) { + sms_log(pMac, LOGE, + FL("Neighbor request already pending.. Not allowed")); + return CDF_STATUS_E_AGAIN; + } + + pMsg = cdf_mem_malloc(sizeof(tSirNeighborReportReqInd)); + if (NULL == pMsg) { + sms_log(pMac, LOGE, + "Unable to allocate memory for Neighbor request"); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_zero(pMsg, sizeof(tSirNeighborReportReqInd)); +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, FL(" Allocated memory for Neighbor request")); +#endif + + rrm_ll_purge_neighbor_cache(pMac, + &pMac->rrm.rrmSmeContext.neighborReportCache); + +#if defined WLAN_VOWIFI_DEBUG + sms_log(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); + cdf_mem_copy(&pMsg->bssId, &pSession->connectedProfile.bssid, + sizeof(tSirMacAddr)); + pMsg->noSSID = pNeighborReq->no_ssid; + cdf_mem_copy(&pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid)); + + status = cds_send_mb_message_to_mac(pMsg); + if (status != CDF_STATUS_SUCCESS) + return CDF_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 = + true; + + /* Start neighbor response wait timer now */ + cdf_mc_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo. + neighborRspWaitTimer, callbackInfo->timeout); + + return CDF_STATUS_SUCCESS; +} + +/** + * rrm_calculate_neighbor_ap_roam_score() - caclulates roam score + * @mac_ctx: mac global context + * @pNeighborReportDesc: Neighbor BSS Descriptor node for which roam score + * should be calculated + * + * 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. + * + * Return: void + */ +static void +rrm_calculate_neighbor_ap_roam_score(tpAniSirGlobal mac_ctx, + tpRrmNeighborReportDesc nbr_report_desc) +{ + tpSirNeighborBssDescripton nbr_bss_desc; + uint32_t roam_score = 0; +#ifdef FEATURE_WLAN_ESE + uint8_t session_id; +#endif + if (NULL == nbr_report_desc) { + CDF_ASSERT(0); + return; + } + + if (NULL == nbr_report_desc->pNeighborBssDescription) { + CDF_ASSERT(0); + return; + } + + nbr_bss_desc = nbr_report_desc->pNeighborBssDescription; + if (!nbr_bss_desc->bssidInfo.rrmInfo.fMobilityDomain) + goto check_11r_assoc; + + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN; + if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameSecurityMode) + goto check_11r_assoc; + + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY; + if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameAuthenticator) + goto check_11r_assoc; + + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE; + if (!nbr_bss_desc->bssidInfo.rrmInfo.fCapRadioMeasurement) + goto check_11r_assoc; + + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM; + if (nbr_bss_desc->bssidInfo.rrmInfo.fCapSpectrumMeasurement) + roam_score += + RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT; + + if (nbr_bss_desc->bssidInfo.rrmInfo.fCapQos) + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS; + + if (nbr_bss_desc->bssidInfo.rrmInfo.fCapApsd) + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD; + + if (nbr_bss_desc->bssidInfo.rrmInfo.fCapDelayedBlockAck) + roam_score += + RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA; + + if (nbr_bss_desc->bssidInfo.rrmInfo.fCapImmediateBlockAck) + roam_score += + RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA; + + if (nbr_bss_desc->bssidInfo.rrmInfo.fApPreauthReachable) + roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY; + +check_11r_assoc: +#ifdef FEATURE_WLAN_ESE + session_id = nbr_report_desc->sessionId; + /* It has come in the report so its the best score */ + if (csr_neighbor_roam_is11r_assoc(mac_ctx, session_id) == 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. + */ + roam_score += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST; + } +#endif + nbr_report_desc->roamScore = roam_score; +} + +/** + * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor + * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache + * + * 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 + * + * Return: void. + */ +void rrm_store_neighbor_rpt_by_roam_score(tpAniSirGlobal pMac, + tpRrmNeighborReportDesc pNeighborReportDesc) +{ + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tListElem *pEntry; + tRrmNeighborReportDesc *pTempNeighborReportDesc; + + if (NULL == pNeighborReportDesc) { + CDF_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) { + CDF_ASSERT(0); + return; + } + + if (csr_ll_is_list_empty + (&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) { + sms_log(pMac, LOGE, + FL + ("Neighbor report cache is empty.. Adding a entry now")); + /* Neighbor list cache is empty. Insert this entry in the tail */ + csr_ll_insert_tail(&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 = + csr_ll_peek_head(&pSmeRrmContext->neighborReportCache, + LL_ACCESS_LOCK); + while (pEntry != NULL) { + pTempNeighborReportDesc = + GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List); + if (pTempNeighborReportDesc->roamScore < + pNeighborReportDesc->roamScore) + break; + pEntry = + csr_ll_next(&pSmeRrmContext->neighborReportCache, + pEntry, LL_ACCESS_LOCK); + } + + if (pEntry) + /* This BSS roamscore is better than something in the list. Insert this before that one */ + csr_ll_insert_entry(&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 */ + csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache, + &pNeighborReportDesc->List, + LL_ACCESS_LOCK); + } + return; +} + +/** + * sme_rrm_process_neighbor_report() -Process the Neighbor report received + * from PE + * @pMac - Global MAC structure + * @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. + * This is called to process the Neighbor report received from PE. + * + * Return: CDF_STATUS_SUCCESS - Validation is successful + */ +CDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac, void *pMsgBuf) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf; + tpRrmNeighborReportDesc pNeighborReportDesc; + uint8_t i = 0; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + uint8_t sessionId; + + /* Get the session id */ + status = + csr_roam_get_session_id_from_bssid(pMac, + (struct cdf_mac_addr *) pNeighborRpt->bssId, + (uint32_t *) &sessionId); + if (CDF_IS_STATUS_SUCCESS(status)) { +#ifdef FEATURE_WLAN_ESE + /* Clear the cache for ESE. */ + if (csr_neighbor_roam_is_ese_assoc(pMac, sessionId)) { + rrm_ll_purge_neighbor_cache(pMac, + &pMac->rrm.rrmSmeContext. + neighborReportCache); + } +#endif + } + + for (i = 0; i < pNeighborRpt->numNeighborReports; i++) { + pNeighborReportDesc = + cdf_mem_malloc(sizeof(tRrmNeighborReportDesc)); + if (NULL == pNeighborReportDesc) { + sms_log(pMac, LOGE, + "Failed to allocate memory for RRM Neighbor report desc"); + status = CDF_STATUS_E_NOMEM; + goto end; + + } + + cdf_mem_zero(pNeighborReportDesc, + sizeof(tRrmNeighborReportDesc)); + pNeighborReportDesc->pNeighborBssDescription = + cdf_mem_malloc(sizeof(tSirNeighborBssDescription)); + if (NULL == pNeighborReportDesc->pNeighborBssDescription) { + sms_log(pMac, LOGE, + "Failed to allocate memory for RRM Neighbor report BSS Description"); + cdf_mem_free(pNeighborReportDesc); + status = CDF_STATUS_E_NOMEM; + goto end; + } + cdf_mem_zero(pNeighborReportDesc->pNeighborBssDescription, + sizeof(tSirNeighborBssDescription)); + cdf_mem_copy(pNeighborReportDesc->pNeighborBssDescription, + &pNeighborRpt->sNeighborBssDescription[i], + sizeof(tSirNeighborBssDescription)); + +#if defined WLAN_VOWIFI_DEBUG + sms_log(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 */ + rrm_calculate_neighbor_ap_roam_score(pMac, pNeighborReportDesc); + + /* Store the Neighbor report Desc in the cache based on the roam score */ + if (pNeighborReportDesc->roamScore > 0) { + rrm_store_neighbor_rpt_by_roam_score(pMac, + pNeighborReportDesc); + } else { + sms_log(pMac, LOGE, + FL("Roam score of BSSID " MAC_ADDRESS_STR + " is 0, Ignoring.."), + MAC_ADDR_ARRAY(pNeighborRpt-> + sNeighborBssDescription[i]. + bssId)); + + cdf_mem_free(pNeighborReportDesc-> + pNeighborBssDescription); + cdf_mem_free(pNeighborReportDesc); + } + } +end: + + if (!csr_ll_count(&pMac->rrm.rrmSmeContext.neighborReportCache)) + cdf_status = CDF_STATUS_E_FAILURE; + + /* Received a report from AP. Indicate SUCCESS to the caller if there are some valid reports */ + rrm_indicate_neighbor_report_result(pMac, cdf_status); + + return status; +} + +/** + * sme_rrm_msg_processor()-Process RRM message + * @pMac - Pointer to the global MAC parameter structure. + * @msg_type - the type of msg passed by PE as defined in wni_api.h + * @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. + * sme_process_msg() calls this function for the + * messages that are handled by SME RRM module. + * + * Return: CDF_STATUS_SUCCESS - Validation is successful. + */ +CDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, + void *pMsgBuf) +{ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_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_rrm_process_neighbor_report(pMac, pMsgBuf); + break; + + case eWNI_SME_BEACON_REPORT_REQ_IND: + sme_rrm_process_beacon_report_req_ind(pMac, pMsgBuf); + break; + + default: + /* err msg */ + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_rrm_msg_processor:unknown msg type = %d"), + msg_type); + + break; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * rrm_iter_meas_timer_handle() - Timer handler to handlet the timeout + * @ pMac - The handle returned by mac_open. + * + * Timer handler to handlet the timeout condition when a specific BT + * stop event does not come back, in which case to restore back the + * heartbeat timer. + * + * Return: NULL + */ +void rrm_iter_meas_timer_handle(void *userData) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) userData; +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, + "Randomization timer expired...send on next channel "); +#endif + /* Issue a scan req for next channel. */ + sme_rrm_issue_scan_req(pMac); +} +/** + * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout + * @pMac - The handle returned by mac_open. + * + * Timer handler to handle the timeout condition when a neighbor request is sent + * and no neighbor response is received from the AP + * + * Return: NULL + */ +void rrm_neighbor_rsp_timeout_handler(void *userData) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) userData; +#if defined WLAN_VOWIFI_DEBUG + sms_log(pMac, LOGE, "Neighbor Response timed out "); +#endif + rrm_indicate_neighbor_report_result(pMac, CDF_STATUS_E_FAILURE); + return; +} + +/** + * rrm_open() - Initialze all RRM module + * @ pMac: The handle returned by mac_open. + * + * Initialze all RRM module. + * + * Return: CDF_STATUS + */ +CDF_STATUS rrm_open(tpAniSirGlobal pMac) +{ + + CDF_STATUS cdf_status; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; + + pSmeRrmContext->rrmConfig.maxRandnInterval = 50; /* ms */ + + cdf_status = cdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer, + CDF_TIMER_TYPE_SW, + rrm_iter_meas_timer_handle, (void *)pMac); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "rrm_open: Fail to init timer"); + + return CDF_STATUS_E_FAILURE; + } + + cdf_status = + cdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo. + neighborRspWaitTimer, CDF_TIMER_TYPE_SW, + rrm_neighbor_rsp_timeout_handler, (void *)pMac); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "rrm_open: Fail to init timer"); + + return CDF_STATUS_E_FAILURE; + } + + pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = false; + + cdf_ret_status = + csr_ll_open(pMac->hHdd, &pSmeRrmContext->neighborReportCache); + if (CDF_STATUS_SUCCESS != cdf_ret_status) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "rrm_open: Fail to open neighbor cache result"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * rrm_close() - Release all RRM modules and their resources. + * @pMac - The handle returned by mac_open. + * + * Release all RRM modules and their resources. + * + * Return: CDF_STATUS + * CDF_STATUS_E_FAILURE success + * CDF_STATUS_SUCCESS failure + */ + +CDF_STATUS rrm_close(tpAniSirGlobal pMac) +{ + + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&pSmeRrmContext->IterMeasTimer)) { + cdf_status = cdf_mc_timer_stop(&pSmeRrmContext->IterMeasTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Timer stop fail")); + } + } + + cdf_status = cdf_mc_timer_destroy(&pSmeRrmContext->IterMeasTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Fail to destroy timer")); + + } + + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&pSmeRrmContext-> + neighborReqControlInfo. + neighborRspWaitTimer)) { + cdf_status = + cdf_mc_timer_stop(&pSmeRrmContext->neighborReqControlInfo. + neighborRspWaitTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + FL("Timer stop fail")); + } + } + + cdf_status = + cdf_mc_timer_destroy(&pSmeRrmContext->neighborReqControlInfo. + neighborRspWaitTimer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_FATAL, + FL("Fail to destroy timer")); + + } + + rrm_ll_purge_neighbor_cache(pMac, &pSmeRrmContext->neighborReportCache); + + csr_ll_close(&pSmeRrmContext->neighborReportCache); + + return cdf_status; + +} + +/* --------------------------------------------------------------------------- + + \fn rrm_ready + + \brief fn + + \param pMac - The handle returned by mac_open. + + \return CDF_STATUS + + ---------------------------------------------------------------------------*/ + +CDF_STATUS rrm_ready(tpAniSirGlobal pMac) +{ + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn rrm_change_default_config_param + \brief fn + + \param pMac - The handle returned by mac_open. + \param pRrmConfig - pointer to new rrm configs. + + \return CDF_STATUS + + ---------------------------------------------------------------------------*/ +CDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, + tpRrmConfigParam pRrmConfig) +{ + cdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, pRrmConfig, + sizeof(tRrmConfigParam)); + + return CDF_STATUS_SUCCESS; +} + +/* --------------------------------------------------------------------------- + + \fn sme_rrm_get_first_bss_entry_from_neighbor_cache() + + \brief This function returns the first entry from the neighbor cache to the caller + + \param pMac - The handle returned by mac_open. + + \return VOID + + ---------------------------------------------------------------------------*/ +tRrmNeighborReportDesc *sme_rrm_get_first_bss_entry_from_neighbor_cache(tpAniSirGlobal + pMac) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pTempBssEntry = NULL; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + + pEntry = + csr_ll_peek_head(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK); + + if (!pEntry || !csr_ll_count(&pSmeRrmContext->neighborReportCache)) { + /* list empty */ + sms_log(pMac, LOGW, FL("List empty")); + return NULL; + } + + pTempBssEntry = GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List); + + return pTempBssEntry; +} + +/** + * sme_rrm_get_next_bss_entry_from_neighbor_cache() - returns the entry next to + * the given entry + * @ pMac - The handle returned by mac_open. + * @pBssEntry- BSS entry + * + * This function returns the entry next to the given entry from the + * neighbor cache to the caller + * + * Return: NULL + */ +tRrmNeighborReportDesc *sme_rrm_get_next_bss_entry_from_neighbor_cache( + tpAniSirGlobal pMac, tpRrmNeighborReportDesc pBssEntry) +{ + tListElem *pEntry; + tRrmNeighborReportDesc *pTempBssEntry = NULL; + + pEntry = + csr_ll_next(&pMac->rrm.rrmSmeContext.neighborReportCache, + &pBssEntry->List, LL_ACCESS_LOCK); + + if (!pEntry) { + /* list empty */ + sms_log(pMac, LOGW, FL("List empty")); + return NULL; + } + + pTempBssEntry = GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List); + + return pTempBssEntry; +} + +#endif diff --git a/core/utils/epping/inc/epping_internal.h b/core/utils/epping/inc/epping_internal.h new file mode 100644 index 000000000000..ee32b4c7d4aa --- /dev/null +++ b/core/utils/epping/inc/epping_internal.h @@ -0,0 +1,197 @@ +/* + * 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 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 "htc_api.h" +#include "htc_packet.h" +#include "epping_test.h" +#include +#include +#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_open(void); +void epping_close(void); +void epping_disable(void); +int epping_enable(struct device *parent_dev); +#endif /* end #ifndef EPPING_MAIN_H */ diff --git a/core/utils/epping/src/epping_helper.c b/core/utils/epping/src/epping_helper.c new file mode 100644 index 000000000000..0e8e3ecd2f0b --- /dev/null +++ b/core/utils/epping/src/epping_helper.c @@ -0,0 +1,213 @@ +/* + * 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 "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] = + cdf_mem_malloc(sizeof(struct epping_cookie) * + MAX_COOKIE_SLOT_SIZE); + if (pEpping_ctx->s_cookie_mem == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: no mem for cookie (idx = %d)", __func__, + i); + goto error; + } + cdf_mem_zero(pEpping_ctx->s_cookie_mem[i], + sizeof(struct epping_cookie) * + MAX_COOKIE_SLOT_SIZE); + } + cdf_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]) { + cdf_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; + cdf_spin_lock_bh(&pEpping_ctx->cookie_lock); + pEpping_ctx->cookie_list = NULL; + pEpping_ctx->cookie_count = 0; + cdf_spin_unlock_bh(&pEpping_ctx->cookie_lock); + for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) { + if (pEpping_ctx->s_cookie_mem[i]) { + cdf_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) +{ + cdf_spin_lock_bh(&pEpping_ctx->cookie_lock); + cookie->next = pEpping_ctx->cookie_list; + pEpping_ctx->cookie_list = cookie; + pEpping_ctx->cookie_count++; + cdf_spin_unlock_bh(&pEpping_ctx->cookie_lock); +} + +struct epping_cookie *epping_alloc_cookie(epping_context_t *pEpping_ctx) +{ + struct epping_cookie *cookie; + + cdf_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--; + } + cdf_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_cdf_ctx(void) +{ + cdf_device_t *p_cdf_ctx; + + p_cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + return p_cdf_ctx; +} + +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(CDF_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(CDF_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_num_rx_recv[eid] = 0; + pAdapter->pEpping_ctx->kperf_num_tx_acks[eid] = 0; +} diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c new file mode 100644 index 000000000000..dd0c463e1793 --- /dev/null +++ b/core/utils/epping/src/epping_main.c @@ -0,0 +1,303 @@ +/* + * 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 "bmi.h" +#include "ol_fw.h" +#include "ol_if_athvar.h" +#include "hif.h" +#include "epping_main.h" +#include "epping_internal.h" + +#ifdef TIMER_MANAGER +#define TIMER_MANAGER_STR " +TIMER_MANAGER" +#else +#define TIMER_MANAGER_STR "" +#endif + +#ifdef MEMORY_DEBUG +#define MEMORY_DEBUG_STR " +MEMORY_DEBUG" +#else +#define MEMORY_DEBUG_STR "" +#endif + +#ifdef HIF_SDIO +#define WLAN_WAIT_TIME_WLANSTART 10000 +#else +#define WLAN_WAIT_TIME_WLANSTART 2000 +#endif + +/** + * epping_open(): End point ping driver open Function + * + * This function is called by HDD to open epping module + * + * + * return - 0 for success, negative for failure + */ +int epping_open(void) +{ + epping_context_t *pEpping_ctx; + v_CONTEXT_t cds_context; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); + + cds_context = cds_get_global_context(); + status = cds_alloc_context(cds_context, CDF_MODULE_ID_EPPING, + (void **)&pEpping_ctx, + sizeof(*pEpping_ctx)); + if (status != CDF_STATUS_SUCCESS) { + EPPING_LOG(CDF_TRACE_LEVEL_ERROR, "%s: cannot alloc epping context", __func__); + return -ENOMEM; + } + + pEpping_ctx->con_mode = cds_get_conparam(); + return 0; +} + +/** + * epping_disable(): End point ping driver disable Function + * + * This is the driver disable function - called by HDD to + * disable epping module + * + * return: none + */ +void epping_disable(void) +{ + epping_context_t *pEpping_ctx; + + pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + if (pEpping_ctx == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: error: pEpping_ctx = NULL", __func__); + return; + } + if (pEpping_ctx->epping_adapter) { + epping_destroy_adapter(pEpping_ctx->epping_adapter); + pEpping_ctx->epping_adapter = NULL; + } + hif_disable_isr(cds_get_context(CDF_MODULE_ID_HIF)); + hif_reset_soc(cds_get_context(CDF_MODULE_ID_HIF)); + htc_stop(cds_get_context(CDF_MODULE_ID_HTC)); + epping_cookie_cleanup(pEpping_ctx); +} + +/** + * epping_close(): End point ping driver close Function + * + * This is the driver close function - called by HDD to close epping module + * + * return: none + */ +void epping_close(void) +{ + epping_context_t *pEpping_ctx; + + pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + if (pEpping_ctx == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: error: pEpping_ctx = NULL", __func__); + return; + } + cds_free_context(NULL, CDF_MODULE_ID_EPPING, + cds_get_context(CDF_MODULE_ID_EPPING)); +} + +static void epping_target_suspend_acknowledge(void *context) +{ + epping_context_t *pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + int wow_nack = *((int *)context); + + if (NULL == pEpping_ctx) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: epping_ctx is NULL", __func__); + return; + } + /* EPPING_TODO: do we need wow_nack? */ + pEpping_ctx->wow_nack = wow_nack; +} + +/** + * epping_enable(): End point ping driver enable Function + * + * This is the driver enable function - called by HDD to enable + * epping module + * + * return - 0 : success, negative: error + */ +int epping_enable(struct device *parent_dev) +{ + int ret = 0; + epping_context_t *pEpping_ctx = NULL; + cds_context_type *p_cds_context = NULL; + cdf_device_t cdf_ctx; + HTC_INIT_INFO htcInfo; + struct ol_softc *scn; + tSirMacAddr adapter_macAddr; + + EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); + + p_cds_context = cds_get_global_context(); + + if (p_cds_context == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: Failed cds_get_global_context", __func__); + ret = -1; + return ret; + } + + pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + if (pEpping_ctx == NULL) { + EPPING_LOG(CDF_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); + + /* Initialize the timer module */ + cdf_timer_module_init(); + + scn = cds_get_context(CDF_MODULE_ID_HIF); + if (!scn) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: scn is null!", __func__); + return -1; + } + scn->enableuartprint = 0; + scn->enablefwlog = 0; + /* store target type and target version info in hdd ctx */ + pEpping_ctx->target_type = scn->target_type; + +#ifndef FEATURE_BMI_2 + /* Initialize BMI and Download firmware */ + if (bmi_download_firmware(scn)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: BMI failed to download target", __func__); + bmi_cleanup(scn); + return -1; + } +#endif + EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, + "%s: bmi_download_firmware done", __func__); + + htcInfo.pContext = p_cds_context->pHIFContext; + htcInfo.TargetFailure = ol_target_failure; + htcInfo.TargetSendSuspendComplete = epping_target_suspend_acknowledge; + cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + + /* Create HTC */ + p_cds_context->htc_ctx = htc_create(htcInfo.pContext, &htcInfo, cdf_ctx); + if (!p_cds_context->htc_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Failed to Create HTC", __func__); + bmi_cleanup(scn); + return -1; + } + pEpping_ctx->HTCHandle = + cds_get_context(CDF_MODULE_ID_HTC); + if (pEpping_ctx->HTCHandle == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: HTCHandle is NULL", __func__); + return -1; + } + scn->htc_handle = pEpping_ctx->HTCHandle; + + hif_claim_device(scn->hif_hdl, scn); + + if (bmi_done(scn)) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: Failed to complete BMI phase", __func__); + goto error_end; + } + /* start HIF */ + if (htc_wait_target(scn->htc_handle) != A_OK) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: htc_wait_target error", __func__); + goto error_end; + } + EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC ready", __func__); + + ret = epping_connect_service(pEpping_ctx); + if (ret != 0) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: htc_wait_targetdone", __func__); + goto error_end; + } + if (htc_start(pEpping_ctx->HTCHandle) != A_OK) { + goto error_end; + } + EPPING_LOG(CDF_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, + CDF_STA_MODE); + } + if (ret < 0 || pEpping_ctx->epping_adapter == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: epping_add_adaptererror error", __func__); + htc_stop(pEpping_ctx->HTCHandle); + epping_cookie_cleanup(pEpping_ctx); + goto error_end; + } + + EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__); + return ret; + +error_end: + htc_destroy(p_cds_context->htc_ctx); + p_cds_context->htc_ctx = NULL; + bmi_cleanup(scn); + return -1; +} diff --git a/core/utils/epping/src/epping_rx.c b/core/utils/epping/src/epping_rx.c new file mode 100644 index 000000000000..15928e120b8d --- /dev/null +++ b/core/utils/epping/src/epping_rx.c @@ -0,0 +1,161 @@ +/* + * 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 "epping_main.h" +#include "epping_internal.h" +#include "epping_test.h" +#include + +#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 - + htc_get_num_recv_buffers(pEpping_ctx->HTCHandle, Endpoint); + + if (buffersToRefill <= 0) { + /* fast return, nothing to fill */ + return; + } + + INIT_HTC_PACKET_QUEUE(&queue); + + EPPING_LOG(CDF_TRACE_LEVEL_INFO, + "%s: providing htc with %d buffers at eid=%d\n", + __func__, buffersToRefill, Endpoint); + + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { + osBuf = cdf_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, + cdf_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 */ + htc_add_receive_pkt_multiple(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(CDF_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); + } + cdf_nbuf_free(pktSkb); + return; + } + + /* deliver to up layer */ + if (pktSkb) { + if (EPPING_ALIGNMENT_PAD > 0) { + A_NETBUF_PULL(pktSkb, EPPING_ALIGNMENT_PAD); + } + if (enb_rx_dump) + epping_hex_dump((void *)cdf_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 (hdd_napi_enabled(HDD_NAPI_ANY)) + netif_receive_skb(pktSkb); + else + netif_rx_ni(pktSkb); + if ((pAdapter->stats.rx_packets % + EPPING_STATS_LOG_COUNT) == 0) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: total_rx_pkts = %lu", + __func__, + pAdapter->stats.rx_packets); + } + } else { + ++pAdapter->stats.rx_dropped; + cdf_nbuf_free(pktSkb); + } + } +} diff --git a/core/utils/epping/src/epping_tx.c b/core/utils/epping/src/epping_tx.c new file mode 100644 index 000000000000..38489b25ff82 --- /dev/null +++ b/core/utils/epping/src/epping_tx.c @@ -0,0 +1,385 @@ +/* + * 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 "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, cdf_nbuf_t skb) +{ + struct epping_cookie *cookie = NULL; + int skb_len, ret; + cdf_nbuf_t new_skb; + + cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); + if (cookie == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: epping_alloc_cookie returns no resource\n", + __func__); + return; + } + new_skb = cdf_nbuf_copy(skb); + if (!new_skb) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: cdf_nbuf_copy returns no resource\n", __func__); + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + return; + } + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, cdf_nbuf_data(skb), + cdf_nbuf_len(new_skb), eid, 0); + SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb); + skb_len = (int)cdf_nbuf_len(new_skb); + /* send the packet */ + ret = htc_send_pkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); + if (ret != A_OK) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: htc_send_pkt failed, ret = %d\n", __func__, ret); + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + cdf_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(cdf_nbuf_t skb, epping_adapter_t *pAdapter) +{ + EPPING_HEADER *eppingHdr = (EPPING_HEADER *) cdf_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(CDF_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(CDF_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]); + } + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, + cookie, cdf_nbuf_data(skb), cdf_nbuf_len(skb), + eid, 0); + SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, skb); + skb_len = skb->len; + /* send the packet */ + ret = htc_send_pkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); + epping_log_packet(pAdapter, &tmpHdr, ret, __func__); + if (ret != A_OK) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: htc_send_pkt 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) +{ + cdf_nbuf_t nodrop_skb; + + EPPING_LOG(CDF_TRACE_LEVEL_INFO, "%s: queue len: %d\n", __func__, + cdf_nbuf_queue_len(&pAdapter->nodrop_queue)); + + if (!cdf_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 = cdf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { + if (epping_tx_send_int(nodrop_skb, pAdapter)) { + EPPING_LOG(CDF_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 */ + cdf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, + nodrop_skb); + break; + } else { + EPPING_LOG(CDF_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) { + cdf_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; + cdf_softirq_timer_mod(&pAdapter->epping_timer, + TX_RETRY_TIMEOUT_IN_MS); + } + cdf_spin_unlock_bh(&pAdapter->data_lock); + } else { + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + } +} + +int epping_tx_send(cdf_nbuf_t skb, epping_adapter_t *pAdapter) +{ + cdf_nbuf_t nodrop_skb; + EPPING_HEADER *eppingHdr; + A_UINT8 ac = 0; + + eppingHdr = (EPPING_HEADER *) cdf_nbuf_data(skb); + + if (!IS_EPPING_PACKET(eppingHdr)) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: Recived non endpoint ping packets\n", __func__); + /* no packet to send, cleanup */ + cdf_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(CDF_TRACE_LEVEL_FATAL, + "%s: ac %d is not mapped to mboxping service\n", + __func__, ac); + cdf_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 = cdf_nbuf_queue_remove(&pAdapter->nodrop_queue))) { + if (epping_tx_send_int(nodrop_skb, pAdapter)) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: nodrop: %p xmit fail\n", __func__, + nodrop_skb); + /* fail to xmit so put the nodrop packet to the nodrop queue */ + cdf_nbuf_queue_insert_head(&pAdapter->nodrop_queue, + nodrop_skb); + /* no cookie so free the current skb */ + goto tx_fail; + } else { + EPPING_LOG(CDF_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 */ + cdf_nbuf_free(skb); + ++pAdapter->stats.tx_dropped; + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: Tx skb %p dropped, stats.tx_dropped = %ld\n", + __func__, skb, pAdapter->stats.tx_dropped); + return -ENOMEM; + } else { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: nodrop: %p queued\n", __func__, skb); + cdf_nbuf_queue_add(&pAdapter->nodrop_queue, skb); + cdf_spin_lock_bh(&pAdapter->data_lock); + if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) { + pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING; + cdf_softirq_timer_mod(&pAdapter->epping_timer, + TX_RETRY_TIMEOUT_IN_MS); + } + cdf_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; + cdf_nbuf_t pktSkb; + struct epping_cookie *cookie; + A_BOOL flushing = false; + cdf_nbuf_queue_t skb_queue; + HTC_PACKET *htc_pkt; + + cdf_nbuf_queue_init(&skb_queue); + + cdf_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 == cdf_nbuf_data(pktSkb)); + + /* add this to the list, use faster non-lock API */ + cdf_nbuf_queue_add(&skb_queue, pktSkb); + + if (A_SUCCESS(status)) { + ASSERT(htc_pkt->ActualLength == cdf_nbuf_len(pktSkb)); + } + EPPING_LOG(CDF_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(CDF_TRACE_LEVEL_INFO, "%s: OK\n", __func__); + flushing = false; + } + + epping_free_cookie(pAdapter->pEpping_ctx, cookie); + } + + cdf_spin_unlock_bh(&pAdapter->data_lock); + + /* free all skbs in our local list */ + while (cdf_nbuf_queue_len(&skb_queue)) { + /* use non-lock version */ + pktSkb = cdf_nbuf_queue_remove(&skb_queue); + if (pktSkb == NULL) + break; + cdf_nbuf_free(pktSkb); + pEpping_ctx->total_tx_acks++; + } + + if (!flushing) { + netif_wake_queue(dev); + } +} diff --git a/core/utils/epping/src/epping_txrx.c b/core/utils/epping/src/epping_txrx.c new file mode 100644 index 000000000000..240d43aede81 --- /dev/null +++ b/core/utils/epping/src/epping_txrx.c @@ -0,0 +1,457 @@ +/* + * 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 +#if defined(MSM_PLATFORM) && defined(HIF_PCI) +#include +#endif /* MSM_PLATFORM */ +#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(CDF_TRACE_LEVEL_FATAL, + "%s: netdev = NULL", __func__); + return; + } + + pAdapter = netdev_priv(dev); + if (pAdapter == NULL) { + EPPING_LOG(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + goto end; + } + + EPPING_LOG(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_FATAL, + "%s: EPPING adapter context is Null", __func__); + ret = -ENODEV; + goto end; + } + if (dev != pAdapter->dev) { + EPPING_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, + "%s: do not support ioctl %d (SIOCDEVPRIVATE + 1)", + __func__, cmd); + break; + default: + EPPING_LOG(CDF_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; + cdf_mem_copy(&pAdapter->macAddressCurrent, + psta_mac_addr->sa_data, ETH_ALEN); + cdf_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_FATAL, + "%s: pAdapter = NULL\n", __func__); + return; + } + + dev = pAdapter->dev; + pEpping_ctx = pAdapter->pEpping_ctx; + epping_unregister_adapter(pAdapter); + + cdf_spinlock_destroy(&pAdapter->data_lock); + cdf_softirq_timer_free(&pAdapter->epping_timer); + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + + while (cdf_nbuf_queue_len(&pAdapter->nodrop_queue)) { + cdf_nbuf_t tmp_nbuf = NULL; + tmp_nbuf = cdf_nbuf_queue_remove(&pAdapter->nodrop_queue); + if (tmp_nbuf) + cdf_nbuf_free(tmp_nbuf); + } + + free_netdev(dev); + if (!pEpping_ctx) + EPPING_LOG(CDF_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, + tCDF_CON_MODE 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)) + NET_NAME_UNKNOWN, +#endif + ether_setup); + if (dev == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: Cannot allocate epping_adapter_t\n", __func__); + return NULL; + } + + pAdapter = netdev_priv(dev); + cdf_mem_zero(pAdapter, sizeof(*pAdapter)); + pAdapter->dev = dev; + pAdapter->pEpping_ctx = pEpping_ctx; + pAdapter->device_mode = device_mode; /* station, SAP, etc */ + cdf_mem_copy(dev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr)); + cdf_mem_copy(pAdapter->macAddressCurrent.bytes, + macAddr, sizeof(tSirMacAddr)); + cdf_spinlock_init(&pAdapter->data_lock); + cdf_nbuf_queue_init(&pAdapter->nodrop_queue); + pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; + cdf_softirq_timer_init(epping_get_cdf_ctx(), &pAdapter->epping_timer, + epping_timer_expire, dev, CDF_TIMER_TYPE_SW); + dev->type = ARPHRD_IEEE80211; + dev->netdev_ops = &epping_drv_ops; + dev->watchdog_timeo = 5 * HZ; /* XXX */ + dev->tx_queue_len = EPPING_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; + + cdf_mem_zero(&connect, sizeof(connect)); + cdf_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 = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); + if (status != EOK) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "Failed to connect to Endpoint Ping BE service status:%d \n", + status); + return -1;; + } else { + EPPING_LOG(CDF_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 = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); + if (status != EOK) { + EPPING_LOG(CDF_TRACE_LEVEL_FATAL, + "Failed to connect to Endpoint Ping BK service status:%d \n", + status); + return -1;; + } else { + EPPING_LOG(CDF_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/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c new file mode 100644 index 000000000000..242c68545625 --- /dev/null +++ b/core/utils/fwlog/dbglog_host.c @@ -0,0 +1,4464 @@ +/* + * 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 "host_diag_core_event.h" +#include "qwlan_version.h" +#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) + +#if defined(DEBUG) + +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 ATH_DEBUG_MASK_DESCRIPTION g_fwlog_debug_description[] = { + {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_fwlog_debug_description), + g_fwlog_debug_description); +#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 < bitmap_len; ++i) { + module_id_bitmap_array[i] = module_id_bitmap[i]; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("wmi_dbg_cfg_send: param 0x%x val 0x%x \n ", param, + val)); + + status = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_DBGLOG_CFG_CMDID); + + if (status != A_OK) + cdf_nbuf_free(buf); + + return status; +} + +void +dbglog_set_vap_enable_bitmap(wmi_unified_t wmi_handle, + A_UINT32 vap_enable_bitmap) +{ + wmi_config_debug_module_cmd(wmi_handle, + WMI_DEBUG_LOG_PARAM_VDEV_ENABLE_BITMAP, + vap_enable_bitmap, NULL, 0); +} + +void +dbglog_set_mod_enable_bitmap(wmi_unified_t wmi_handle, A_UINT32 log_level, + A_UINT32 *mod_enable_bitmap, A_UINT32 bitmap_len) +{ + wmi_config_debug_module_cmd(wmi_handle, + WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP, + log_level, mod_enable_bitmap, bitmap_len); +} + +int dbglog_report_enable(wmi_unified_t wmi_handle, bool isenable) +{ + int bitmap[2] = { 0 }; + + if (isenable > 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 uint8_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 uint8_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 (cds_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 uint8_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 (cds_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 uint8_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 (cds_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_ucast 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, uint8_t *data, uint32_t datalen) +{ + + tp_wma_handle wma = (tp_wma_handle) scn; + wmitlv_cmd_param_info *param_buf; + uint8_t *datap; + uint32_t len = 0; + uint32_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 = (uint32_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, uint8_t *data, uint32_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; + uint8_t *datap; + uint32_t num_data = 0; /* Total events */ + uint32_t diag_data_len = 0; /* each fw diag payload */ + uint32_t diag_type = 0; + uint32_t i = 0; + uint32_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 = (uint8_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, uint8_t *data, uint32_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; + cdf_size_t length; + A_UINT32 dropped; + WMI_DEBUG_MESG_EVENTID_param_tlvs *param_buf; + uint8_t *datap; + uint32_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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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 < CDF_ARRAY_SIZE(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, + CDF_ARRAY_SIZE(nw_states), events, + CDF_ARRAY_SIZE(events)); + break; + case WLAN_IBSS_PS_SUB_MODULE_IBSS_SELF_PS: + dbglog_sm_print(timestamp, vap_id, numargs, args, + "IBSS PS Self", ps_states, + CDF_ARRAY_SIZE(ps_states), events, + CDF_ARRAY_SIZE(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, + CDF_ARRAY_SIZE(peer_ps_states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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, CDF_ARRAY_SIZE(states), events, + CDF_ARRAY_SIZE(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 = cdf_mem_malloc(total_len); + if (!pBuf) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("%s: cdf_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); + cdf_mem_free((void *)pBuf1); + return; + +} + +static void cnss_diag_send_driver_loaded(void) +{ + if (appstarted) { + host_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) +{ + host_event_wlan_bringup_status_payload_type wlan_bringup_status; + /* Send Driver down command */ + memset(&wlan_bringup_status, 0, + sizeof(host_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])); + wma_cli_set2_command(0, 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 (INVALID_PID != cnss_diag_pid) { + cnss_diag_send_driver_unloaded(); + cnss_diag_pid = INVALID_PID; + } + 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); + + /* 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 */ + + 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/core/utils/fwlog/dbglog_host.h b/core/utils/fwlog/dbglog_host.h new file mode 100644 index 000000000000..9b9e0e4e1f4b --- /dev/null +++ b/core/utils/fwlog/dbglog_host.h @@ -0,0 +1,127 @@ +/* + * 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 _DBGLOG_HOST_H_ +#define _DBGLOG_HOST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog_common.h" +#include "ol_defines.h" + +/* + * 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); + +/** 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/core/utils/host_diag_log/inc/host_diag_core_event.h b/core/utils/host_diag_log/inc/host_diag_core_event.h new file mode 100644 index 000000000000..7962dda35245 --- /dev/null +++ b/core/utils/host_diag_log/inc/host_diag_core_event.h @@ -0,0 +1,362 @@ +/* + * 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( __HOST_DIAG_CORE_EVENT_H ) +#define __HOST_DIAG_CORE_EVENT_H + +/**========================================================================= + + \file host_diag_core_event.h + + \brief WLAN UTIL host DIAG Events + + Definitions for DIAG Events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_types.h" +#include "cds_pack_align.h" +#include "i_host_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 { + uint8_t eventId; + uint8_t authMode; + uint8_t encryptionModeUnicast; + uint8_t encryptionModeMulticast; + uint8_t pmkIDMatch; + uint8_t bssid[6]; + uint8_t keyId; + uint8_t status; +} host_event_wlan_security_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_STATUS + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t eventId; + uint8_t ssid[6]; + uint8_t bssType; + uint8_t rssi; + uint8_t channel; + uint8_t qosCapability; + uint8_t authType; + uint8_t encryptionType; + uint8_t reason; + uint8_t reasonDisconnect; +} host_event_wlan_status_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_HANDOFF + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t eventId; + uint8_t currentApBssid[6]; + uint8_t currentApRssi; + uint8_t candidateApBssid[6]; + uint8_t candidateApRssi; +} host_event_wlan_handoff_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_VCC + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t eventId; + uint8_t rssi; + uint8_t txPer; + uint8_t rxPer; + int linkQuality; +} host_event_wlan_vcc_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_QOS + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t eventId; + uint8_t reasonCode; +} host_event_wlan_qos_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_PE + ------------------------------------------------------------------------*/ +typedef struct { + char bssid[6]; + uint16_t event_type; + uint16_t sme_state; + uint16_t mlm_state; + uint16_t status; + uint16_t reason_code; +} host_event_wlan_pe_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_ADD_BLOCK_ACK_SUCCESS + ------------------------------------------------------------------------*/ +typedef struct { + char ucBaPeerMac[6]; + uint8_t ucBaTid; + uint8_t ucBaBufferSize; + uint16_t usBaSSN; + uint8_t fInitiator; +} host_event_wlan_add_block_ack_success_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_ADD_BLOCK_ACK_FAILED + ------------------------------------------------------------------------*/ +typedef struct { + char ucBaPeerMac[6]; + uint8_t ucBaTid; + uint8_t ucReasonCode; + uint8_t fInitiator; +} host_event_wlan_add_block_ack_failed_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_SUCCESS + ------------------------------------------------------------------------*/ +typedef struct { + char ucBaPeerMac[6]; + uint8_t ucBaTid; + uint8_t ucDeleteReasonCode; +} host_event_wlan_add_block_ack_deleted_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_FAILED + ------------------------------------------------------------------------*/ +typedef struct { + char ucBaPeerMac[6]; + uint8_t ucBaTid; + uint8_t ucDeleteReasonCode; + uint8_t ucFailReasonCode; +} host_event_wlan_add_block_ack_delete_failed_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BSS_PROTECTION + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t event_type; + uint8_t prot_type; +} host_event_wlan_bss_prot_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BRINGUP_STATUS + ------------------------------------------------------------------------*/ +typedef struct { + uint16_t wlanStatus; + char driverVersion[10]; +} host_event_wlan_bringup_status_payload_type; + +CDS_PACK_START +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_POWERSAVE_GENERIC + ------------------------------------------------------------------------*/ +typedef CDS_PACK_PRE struct { + uint8_t event_subtype; + uint8_t full_power_request_reason; + uint8_t pmc_current_state; + uint8_t enable_disable_powersave_mode; + uint8_t winmob_d_power_state; + uint8_t dtim_period; + uint16_t final_listen_intv; + uint16_t bmps_auto_timer_duration; + uint16_t bmps_period; +} CDS_PACK_POST host_event_wlan_powersave_payload_type; + +CDS_PACK_END +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_POWERSAVE_WOW + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t event_subtype; + uint8_t wow_type; + uint8_t wow_magic_pattern[6]; + uint8_t wow_del_ptrn_id; + uint8_t wow_wakeup_cause; + uint8_t wow_wakeup_cause_pbm_ptrn_id; +} host_event_wlan_powersave_wow_payload_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_BTC + ------------------------------------------------------------------------*/ +typedef struct { + uint8_t eventId; + uint8_t btAddr[6]; + uint16_t connHandle; + uint8_t connStatus; + uint8_t linkType; + uint8_t scoInterval; + uint8_t scoWindow; + uint8_t retransWindow; + uint8_t mode; +} host_event_wlan_btc_type; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_EAPOL + ------------------------------------------------------------------------*/ +/** + * struct host_event_wlan_eapol - Structure holding the eapol information + * @event_sub_type: 0-Transmitted, 1-Received + * @eapol_packet_type: 0 - EAP Start, 1 - EAPOL Start, 2 - EAPOL Logoff + 3 - EAPOL Key, 4 - EAPOL Encapsulated Alert + * @eapol_key_info: This field from the driver is in big endian format. + * So, the masks .0x8013. can be used to extract the + * message type. After masking, the values corresponding + * to messages 1/2/3/4 are given below: + * Msg. 1 0x8000 + * Msg. 2 0x0001 + * Msg. 3 0x8013 + * Msg. 4 0x0003 + * @eapol_rate: Rate at which the frame is received + * @dest_addr: Destination address + * @src_addr: Source address + * + * This structure contains the EAPOL information related to logging + */ +struct host_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 host_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 information + */ +struct host_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 host_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 host_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 - Enum containing EAPOL sub type + * @WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED: EAPOL transmitted + * @WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED: EAPOL received + * + * This enum contains the EAPOL subtype + */ +enum wifi_connectivity_events { + WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED, + WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED, +}; + +/** + * enum wake_lock_reason - Reason for taking/releasing 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_AUTO_SUSPEND: Auto suspend related 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 + * + * Indicates the reason for which the wakelock was 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_AUTO_SUSPEND, + 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 /* __HOST_DIAG_CORE_EVENT_H */ diff --git a/core/utils/host_diag_log/inc/host_diag_core_log.h b/core/utils/host_diag_log/inc/host_diag_core_log.h new file mode 100644 index 000000000000..d17ad46dec5e --- /dev/null +++ b/core/utils/host_diag_log/inc/host_diag_core_log.h @@ -0,0 +1,380 @@ +/* + * 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( __HOST_DIAG_CORE_LOG_H ) +#define __HOST_DIAG_CORE_LOG_H + +/**========================================================================= + + \file host_diag_core_log.h + + \brief WLAN UTIL host DIAG logs + + Definitions for WLAN UTIL host diag events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include "cdf_types.h" +#include "i_host_diag_core_log.h" + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ +#define HOST_LOG_MAX_NUM_SSID (21) +#define HOST_LOG_MAX_NUM_BSSID (21) +#define HOST_LOG_MAX_SSID_SIZE (32) +#define HOST_LOG_MAX_BSSID_SIZE (6) +#define HOST_LOG_MAX_NUM_CHANNEL (64) +#define HOST_LOG_MAX_NUM_HO_CANDIDATE_APS (20) +#define HOST_LOG_MAX_WOW_PTRN_SIZE (128) +#define HOST_LOG_MAX_WOW_PTRN_MASK_SIZE (16) +#define VOS_LOG_PKT_LOG_SIZE (2048) +#define HOST_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; + uint8_t eventId; + uint8_t numSsid; + uint8_t ssid[HOST_LOG_MAX_NUM_SSID][HOST_LOG_MAX_SSID_SIZE]; + uint8_t bssid[HOST_LOG_MAX_NUM_BSSID][HOST_LOG_MAX_BSSID_SIZE]; + uint8_t totalSsid; + uint8_t minChnTime; + uint8_t maxChnTime; + uint16_t timeBetweenBgScan; + uint8_t BSSMode; + uint8_t numChannel; + uint8_t channels[HOST_LOG_MAX_NUM_CHANNEL]; + uint16_t status; +} host_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; + uint8_t eventId; + uint8_t channelSetting; + uint8_t bssid[HOST_LOG_MAX_BSSID_SIZE]; + uint8_t peerMacAddr[HOST_LOG_MAX_BSSID_SIZE]; + uint8_t ssid[HOST_LOG_MAX_SSID_SIZE]; + uint8_t operatingChannel; + uint8_t beaconInterval; + uint8_t status; +} host_log_ibss_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains the information related to 802.11D + LOG_WLAN_80211D_C 0x1498 + ---------------------------------------------------------------------------*/ +typedef struct { + log_hdr_type hdr; + uint8_t eventId; + uint8_t numChannel; + uint8_t Channels[HOST_LOG_MAX_NUM_CHANNEL]; + uint8_t TxPwr[HOST_LOG_MAX_NUM_CHANNEL]; + uint8_t countryCode[3]; + uint8_t supportMultipleDomain; +} host_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 { + uint8_t ssid[9]; + uint8_t bssid[HOST_LOG_MAX_BSSID_SIZE]; + uint8_t channel_id; + uint32_t qos_score; + uint32_t sec_score; + uint32_t rssi_score; + uint32_t overall_score; + uint32_t tx_per; /* represented as a % */ + uint32_t rx_per; /* represented as a % */ + +} host_log_ho_ap_info; + +typedef struct { + log_hdr_type hdr; + uint32_t num_aps; + host_log_ho_ap_info current_ap_info; + host_log_ho_ap_info + candidate_ap_info[HOST_LOG_MAX_NUM_HO_CANDIDATE_APS]; +} host_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; + uint8_t aci_be; + uint8_t cw_be; + uint16_t txoplimit_be; + uint8_t aci_bk; + uint8_t cw_bk; + uint16_t txoplimit_bk; + uint8_t aci_vi; + uint8_t cw_vi; + uint16_t txoplimit_vi; + uint8_t aci_vo; + uint8_t cw_vo; + uint16_t txoplimit_vo; +} host_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; + uint32_t bcn_rx_cnt; +} host_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; + uint8_t pattern_id; + uint8_t pattern_byte_offset; + uint8_t pattern_size; + uint8_t pattern[HOST_LOG_MAX_WOW_PTRN_SIZE]; + uint8_t pattern_mask_size; + uint8_t pattern_mask[HOST_LOG_MAX_WOW_PTRN_MASK_SIZE]; +} host_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 { + uint32_t retry_cnt[4]; + uint32_t multiple_retry_cnt[4]; + uint32_t tx_frm_cnt[4]; + uint32_t rx_frm_cnt; + uint32_t frm_dup_cnt; + uint32_t fail_cnt[4]; + uint32_t rts_fail_cnt; + uint32_t ack_fail_cnt; + uint32_t rts_succ_cnt; + uint32_t rx_discard_cnt; + uint32_t rx_error_cnt; + uint32_t tx_byte_cnt; + +} summaryStatsInfo; + +typedef struct { + uint32_t rx_frag_cnt; + uint32_t promiscuous_rx_frag_cnt; + uint32_t rx_input_sensitivity; + uint32_t max_pwr; + uint32_t sync_fail_cnt; + uint32_t tx_rate; + +} globalClassAStatsInfo; + +typedef struct { + uint32_t uc_rx_wep_unencrypted_frm_cnt; + uint32_t uc_rx_mic_fail_cnt; + uint32_t uc_tkip_icv_err; + uint32_t uc_aes_ccmp_format_err; + uint32_t uc_aes_ccmp_replay_cnt; + uint32_t uc_aes_ccmp_decrpt_err; + uint32_t uc_wep_undecryptable_cnt; + uint32_t uc_wep_icv_err; + uint32_t uc_rx_decrypt_succ_cnt; + uint32_t uc_rx_decrypt_fail_cnt; + uint32_t mcbc_rx_wep_unencrypted_frm_cnt; + uint32_t mcbc_rx_mic_fail_cnt; + uint32_t mcbc_tkip_icv_err; + uint32_t mcbc_aes_ccmp_format_err; + uint32_t mcbc_aes_ccmp_replay_cnt; + uint32_t mcbc_aes_ccmp_decrpt_err; + uint32_t mcbc_wep_undecryptable_cnt; + uint32_t mcbc_wep_icv_err; + uint32_t mcbc_rx_decrypt_succ_cnt; + uint32_t mcbc_rx_decrypt_fail_cnt; + +} globalClassBStatsInfo; + +typedef struct { + uint32_t rx_amsdu_cnt; + uint32_t rx_ampdu_cnt; + uint32_t tx_20_frm_cnt; + uint32_t rx_20_frm_cnt; + uint32_t rx_mpdu_in_ampdu_cnt; + uint32_t ampdu_delimiter_crc_err; + +} globalClassCStatsInfo; + +typedef struct { + uint32_t tx_uc_frm_cnt; + uint32_t tx_mc_frm_cnt; + uint32_t tx_bc_frm_cnt; + uint32_t rx_uc_frm_cnt; + uint32_t rx_mc_frm_cnt; + uint32_t rx_bc_frm_cnt; + uint32_t tx_uc_byte_cnt[4]; + uint32_t tx_mc_byte_cnt; + uint32_t tx_bc_byte_cnt; + uint32_t rx_uc_byte_cnt[4]; + uint32_t rx_mc_byte_cnt; + uint32_t rx_bc_byte_cnt; + uint32_t rx_byte_cnt; + uint32_t num_rx_bytes_crc_ok; + uint32_t rx_rate; + +} globalClassDStatsInfo; + +typedef struct { + uint32_t tx_frag_cnt[4]; + uint32_t tx_ampdu_cnt; + uint32_t tx_mpdu_in_ampdu_cnt; +} perStaStatsInfo; + +typedef struct { + log_hdr_type hdr; + uint8_t version; + uint8_t reserved[3]; + uint32_t stat_mask; + summaryStatsInfo summaryStats; + globalClassAStatsInfo globalClassAStats; + globalClassBStatsInfo globalClassBStats; + globalClassCStatsInfo globalClassCStats; + globalClassDStatsInfo globalClassDStats; + perStaStatsInfo perStaStats; +} host_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; + uint8_t tsinfo[3]; + uint16_t nominal_msdu_size; + uint16_t maximum_msdu_size; + uint32_t min_service_interval; + uint32_t max_service_interval; + uint32_t inactivity_interval; + uint32_t suspension_interval; + uint32_t svc_start_time; + uint32_t min_data_rate; + uint32_t mean_data_rate; + uint32_t peak_data_rate; + uint32_t max_burst_size; + uint32_t delay_bound; + uint32_t min_phy_rate; + uint16_t surplus_bw_allowance; + uint16_t medium_time; +} host_log_qos_tspec_pkt_type; + +/*--------------------------------------------------------------------------- + This packet contains data information when stall detected + LOG_TRSP_DATA_STALL_C 0x1801 + ---------------------------------------------------------------------------*/ + +typedef struct { + char channelName[4]; + uint32_t numDesc; + uint32_t numFreeDesc; + uint32_t numRsvdDesc; + uint32_t headDescOrder; + uint32_t tailDescOrder; + uint32_t ctrlRegVal; + uint32_t statRegVal; + uint32_t numValDesc; + uint32_t numInvalDesc; +} host_log_data_stall_channel_type; + +typedef struct { + log_hdr_type hdr; + uint32_t PowerState; + uint32_t numFreeBd; + host_log_data_stall_channel_type dxeChannelInfo[4]; +} host_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; + int8_t rssi; +} host_log_rssi_pkt_type; + +/** + * struct host_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 host_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 /* __HOST_DIAG_CORE_LOG_H */ diff --git a/core/utils/host_diag_log/inc/host_diag_event_defs.h b/core/utils/host_diag_log/inc/host_diag_event_defs.h new file mode 100644 index 000000000000..ca250c592db2 --- /dev/null +++ b/core/utils/host_diag_log/inc/host_diag_event_defs.h @@ -0,0 +1,61 @@ +/* + * 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 EVENT_DEFS_H +#define EVENT_DEFS_H + +typedef enum { + EVENT_DROP_ID = 0, + + /* Events between 0x1 to 0x674 are not used */ + + EVENT_WLAN_SECURITY = 0x675, /* 13 byte payload */ + EVENT_WLAN_STATUS, /* 15 byte payload */ + + /* Events 0x677 and 0x678 are not used */ + + EVENT_WLAN_QOS = 0x679, /* 2 byte payload */ + EVENT_WLAN_PE, /* 16 byte payload */ + + /* Events between 0x67b to 0x67f are not used */ + + EVENT_WLAN_BRINGUP_STATUS = 0x680, /* 12 byte payload */ + EVENT_WLAN_POWERSAVE_GENERIC, /* 16 byte payload */ + EVENT_WLAN_POWERSAVE_WOW, /* 11 byte payload */ + + /* Events between 0x683 to 0x690 are not used */ + + EVENT_WLAN_BTC = 0x691, /* 15 byte payload */ + EVENT_WLAN_EAPOL = 0xA8D,/* 18 bytes payload */ + EVENT_WLAN_WAKE_LOCK = 0xAA2, /* 96 bytes payload */ + EVENT_WLAN_BEACON_RECEIVED = 0xAA6, /* FW event: 2726 */ + EVENT_WLAN_LOG_COMPLETE = 0xAA7, /* 16 bytes payload */ + + EVENT_MAX_ID = 0x0FFF +} event_id_enum_type; + +#endif /* EVENT_DEFS_H */ diff --git a/core/utils/host_diag_log/inc/log_codes.h b/core/utils/host_diag_log/inc/log_codes.h new file mode 100644 index 000000000000..462ce9cc83e0 --- /dev/null +++ b/core/utils/host_diag_log/inc/log_codes.h @@ -0,0 +1,2078 @@ +/* + * 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 ((uint16_t) 0x1000) +#define LOG_WCDMA_BASE_C ((uint16_t) 0x4000) +#define LOG_GSM_BASE_C ((uint16_t) 0x5000) +#define LOG_LBS_BASE_C ((uint16_t) 0x6000) +#define LOG_UMTS_BASE_C ((uint16_t) 0x7000) +#define LOG_TDMA_BASE_C ((uint16_t) 0x8000) +#define LOG_DTV_BASE_C ((uint16_t) 0xA000) +#define LOG_APPS_BASE_C ((uint16_t) 0xB000) +#define LOG_LTE_BASE_C ((uint16_t) (0xB000 + 0x0010)) +#define LOG_LTE_LAST_C ((uint16_t) 0xB1FF) +#define LOG_WIMAX_BASE_C ((uint16_t) 0xB400) +#define LOG_DSP_BASE_C ((uint16_t) 0xC000) + +#define LOG_TOOLS_BASE_C ((uint16_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/core/utils/host_diag_log/src/host_diag_log.c b/core/utils/host_diag_log/src/host_diag_log.c new file mode 100644 index 000000000000..4fd357eb1547 --- /dev/null +++ b/core/utils/host_diag_log/src/host_diag_log.c @@ -0,0 +1,264 @@ +/* + * 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: host_diag_log.c + + OVERVIEW: This source file contains definitions for WLAN UTIL diag APIs + + DEPENDENCIES: + ============================================================================*/ + +#include "cdf_types.h" +#include "i_host_diag_core_log.h" +#include "host_diag_core_event.h" +#include "wlan_nlink_common.h" +#include "cds_sched.h" +#include "wlan_ptt_sock_svc.h" +#include "wlan_nlink_srv.h" +#include "cds_api.h" + +#define PTT_MSG_DIAG_CMDS_TYPE (0x5050) + +#define DIAG_TYPE_LOGS (1) +#define DIAG_TYPE_EVENTS (2) + +#define DIAG_SWAP16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8)) + +typedef struct event_report_s { + uint32_t diag_type; + uint16_t event_id; + uint16_t length; +} event_report_t; + +/**--------------------------------------------------------------------------- + + \brief host_diag_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 host_diag_log_set_code(void *ptr, uint16_t code) +{ + if (ptr) { + /* All log packets are required to start with 'log_header_type' */ + ((log_hdr_type *) ptr)->code = code; + } +} + +/**--------------------------------------------------------------------------- + + \brief host_diag_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 host_diag_log_set_length(void *ptr, uint16_t length) +{ + if (ptr) { + /* All log packets are required to start with 'log_header_type' */ + ((log_hdr_type *) ptr)->len = (uint16_t) length; + } +} + +/**--------------------------------------------------------------------------- + + \brief host_diag_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 host_diag_log_submit(void *plog_hdr_ptr) +{ + log_hdr_type *pHdr = (log_hdr_type *) plog_hdr_ptr; + tAniHdr *wmsg = NULL; + uint8_t *pBuf; + uint16_t data_len; + uint16_t total_len; + + if (cds_is_load_unload_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Unloading/Loading in Progress. Ignore!!!", + __func__); + return; + } + + if (nl_srv_is_initialized() != 0) + return; + + if (cds_is_multicast_logging()) { + data_len = pHdr->len; + + total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len; + + pBuf = (uint8_t *) cdf_mem_malloc(total_len); + + if (!pBuf) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "cdf_mem_malloc failed"); + return; + } + + cdf_mem_zero((void *)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 */ + *(uint32_t *) pBuf = DIAG_TYPE_LOGS; + pBuf += sizeof(uint32_t); + + memcpy(pBuf, pHdr, data_len); + ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC, + INVALID_PID); + cdf_mem_free((void *)wmsg); + } + return; +} + +/** + * host_diag_log_wlock() - 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 host_diag_log_wlock(uint32_t reason, const char *wake_lock_name, + uint32_t timeout, uint32_t status) +{ + WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, + struct host_event_wlan_wake_lock); + + if ((nl_srv_is_initialized() != 0) || + (cds_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_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK); +} + +/**--------------------------------------------------------------------------- + + \brief host_diag_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 host_diag_event_report_payload(uint16_t event_Id, uint16_t length, + void *pPayload) +{ + tAniHdr *wmsg = NULL; + uint8_t *pBuf; + event_report_t *pEvent_report; + uint16_t total_len; + + if (cds_is_load_unload_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "%s: Unloading/Loading in Progress. Ignore!!!", + __func__); + return; + } + + if (nl_srv_is_initialized() != 0) + return; + + if (cds_is_multicast_logging()) { + total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length; + + pBuf = (uint8_t *) cdf_mem_malloc(total_len); + + if (!pBuf) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "cdf_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); + + memcpy(pBuf, pPayload, length); + + if (ptt_sock_send_msg_to_app + (wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID) < 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "Ptt Socket error sending message to the app!!"); + cdf_mem_free((void *)wmsg); + return; + } + + cdf_mem_free((void *)wmsg); + } + + return; + +} diff --git a/core/utils/host_diag_log/src/i_host_diag_core_event.h b/core/utils/host_diag_log/src/i_host_diag_core_event.h new file mode 100644 index 000000000000..cd4d0c3d5523 --- /dev/null +++ b/core/utils/host_diag_log/src/i_host_diag_core_event.h @@ -0,0 +1,102 @@ +/* + * 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_HOST_DIAG_CORE_EVENT_H ) +#define __I_HOST_DIAG_CORE_EVENT_H + +/**========================================================================= + + \file i_host_diag_core_event.h + + \brief Android specific definitions for WLAN UTIL DIAG events + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include +#endif + +/*-------------------------------------------------------------------------- + Preprocessor definitions and constants + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT + +void host_diag_event_report_payload(uint16_t event_Id, uint16_t length, + void *pPayload); +/*--------------------------------------------------------------------------- + Allocate an event payload holder + ---------------------------------------------------------------------------*/ +#define WLAN_HOST_DIAG_EVENT_DEF( payload_name, payload_type ) \ + payload_type(payload_name) + +/*--------------------------------------------------------------------------- + Report the event + ---------------------------------------------------------------------------*/ +#define WLAN_HOST_DIAG_EVENT_REPORT( payload_ptr, ev_id ) \ + do { \ + host_diag_event_report_payload( ev_id, \ + sizeof( *(payload_ptr) ), \ + (void *)(payload_ptr) ); \ + } while (0) + +#else /* FEATURE_WLAN_DIAG_SUPPORT */ + +#define WLAN_HOST_DIAG_EVENT_DEF( payload_name, payload_type ) +#define WLAN_HOST_DIAG_EVENT_REPORT( payload_ptr, ev_id ) + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name, + uint32_t timeout, uint32_t status); +#else +static inline void host_diag_log_wlock(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_HOST_DIAG_CORE_EVENT_H */ diff --git a/core/utils/host_diag_log/src/i_host_diag_core_log.h b/core/utils/host_diag_log/src/i_host_diag_core_log.h new file mode 100644 index 000000000000..d670d5339f75 --- /dev/null +++ b/core/utils/host_diag_log/src/i_host_diag_core_log.h @@ -0,0 +1,132 @@ +/* + * 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_HOST_DIAG_CORE_LOG_H ) +#define __I_HOST_DIAG_CORE_LOG_H + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include +#endif + +/**========================================================================= + + \file i_host_diag_core_event.h + + \brief android-specific definitions for WLAN UTIL DIAG logs + + ========================================================================*/ + +/* $Header$ */ + +/*-------------------------------------------------------------------------- + Include Files + ------------------------------------------------------------------------*/ +#include +#include + +/*-------------------------------------------------------------------------- + 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. */ + uint16_t len; + + /* Specifies the log code for the entry */ + uint16_t code; + + /*Time Stamp lo */ + uint32_t ts_lo; + + /*Time Stamp hi */ + uint32_t ts_hi; +} __packed log_hdr_type; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void host_diag_log_set_code(void *ptr, uint16_t code); +void host_diag_log_set_length(void *ptr, uint16_t length); +void host_diag_log_set_timestamp(void *plog_hdr_ptr); +void host_diag_log_submit(void *plog_hdr_ptr); + +/*--------------------------------------------------------------------------- + Allocate an event payload holder + ---------------------------------------------------------------------------*/ + +#define WLAN_HOST_DIAG_LOG_ALLOC( payload_ptr, payload_type, log_code ) \ + do { \ + payload_ptr = ( payload_type *)cdf_mem_malloc(sizeof(payload_type)); \ + if(payload_ptr) { \ + cdf_mem_zero(payload_ptr, sizeof(payload_type)); \ + host_diag_log_set_code(payload_ptr, log_code); \ + host_diag_log_set_length(payload_ptr, sizeof(payload_type)); \ + } \ + } while (0) + +/*--------------------------------------------------------------------------- + Report the event + ---------------------------------------------------------------------------*/ +#define WLAN_HOST_DIAG_LOG_REPORT( payload_ptr ) \ + do { \ + if(payload_ptr) { \ + host_diag_log_submit( payload_ptr); \ + cdf_mem_free(payload_ptr); \ + } \ + } while (0) + +/*--------------------------------------------------------------------------- + Free the payload + ---------------------------------------------------------------------------*/ +#define WLAN_HOST_DIAG_LOG_FREE( payload_ptr ) \ + do \ + { \ + if( payload_ptr) \ + { \ + cdf_mem_free(payload_ptr); \ + } \ + } while (0) + +#else /* FEATURE_WLAN_DIAG_SUPPORT */ + +#define WLAN_HOST_DIAG_LOG_ALLOC( payload_ptr, payload_type, log_code ) +#define WLAN_HOST_DIAG_LOG_REPORT( payload_ptr ) +#define WLAN_HOST_DIAG_LOG_FREE( payload_ptr ) + +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __I_HOST_DIAG_CORE_LOG_H */ diff --git a/core/utils/logging/inc/wlan_logging_sock_svc.h b/core/utils/logging/inc/wlan_logging_sock_svc.h new file mode 100644 index 000000000000..c9070ab23480 --- /dev/null +++ b/core/utils/logging/inc/wlan_logging_sock_svc.h @@ -0,0 +1,61 @@ +/* + * 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 + +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(CDF_TRACE_LEVEL log_level, char *to_be_sent, int length); +void wlan_logging_set_per_pkt_stats(void); +void wlan_logging_set_log_level(void); +void wlan_logging_set_fw_flush_complete(void); +#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/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c new file mode 100644 index 000000000000..d82e008ce47c --- /dev/null +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -0,0 +1,817 @@ +/* + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/****************************************************************************** +* wlan_logging_sock_svc.c +* +******************************************************************************/ + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE +#include +#include +#include +#include +#include +#include +#include "pktlog_ac.h" +#include + +#define LOGGING_TRACE(level, args ...) \ + CDF_TRACE(CDF_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(CDF_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(CDF_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(CDF_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(CDF_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(CDF_MODULE_ID mod_id) +{ + switch (mod_id) { + case CDF_MODULE_ID_HDD_DATA: + case CDF_MODULE_ID_HDD_SAP_DATA: + case CDF_MODULE_ID_HTC: + case CDF_MODULE_ID_TXRX: + case CDF_MODULE_ID_HIF: + return true; + default: + return false; + } +} + +static void set_default_logtoapp_log_level(void) +{ + int i; + + /* module id 0 is reserved */ + for (i = 1; i < CDF_MODULE_ID_MAX; i++) { + if (is_data_path_module(i)) + cdf_trace_set_module_trace_level(i, + CDF_DATA_PATH_TRACE_LEVEL); + else + cdf_trace_set_value(i, CDF_TRACE_LEVEL_ALL, true); + } +} + +static void clear_default_logtoapp_log_level(void) +{ + int module; + + for (module = 0; module < CDF_MODULE_ID_MAX; module++) { + cdf_trace_set_value(module, CDF_TRACE_LEVEL_NONE, false); + cdf_trace_set_value(module, CDF_TRACE_LEVEL_FATAL, true); + cdf_trace_set_value(module, CDF_TRACE_LEVEL_ERROR, true); + } + + cdf_trace_set_value(CDF_MODULE_ID_RSV4, CDF_TRACE_LEVEL_NONE, + 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 (cds_is_multicast_logging() && + (!(gwlan_logging.drop_count % 0x40))) { + pr_err + ("%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; +} + +#ifdef QCA_WIFI_3_0_ADRASTEA +/** + * wlan_add_user_log_time_stamp() - add time stamp in WLAN log buffer + * @tbuf: Pointer to time stamp buffer + * @tbuf_sz: Time buffer size + * @ts: Time stamp value + * + * For adrastea time stamp is QTIMER raw tick which will be used by cnss_diag + * to convert it into user visible time stamp. In adrstea FW also uses QTIMER + * raw ticks which is needed to synchronize host and fw log time stamps + * + * + * For discrete solution e.g rome use system tick and convert it into + * seconds.milli seconds + */ +static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts) +{ + int tlen; + + tlen = scnprintf(tbuf, tbuf_sz, "[%s][%llu] ", current->comm, ts); + return tlen; +} +#else +/** + * wlan_add_user_log_time_stamp() - add time stamp in WLAN log buffer + * @tbuf: Pointer to time stamp buffer + * @tbuf_sz: Time buffer size + * @ts: Time stamp value + * + * For adrastea time stamp QTIMER raw tick which will be used by cnss_diag + * to convert it into user visible time stamp + * + * For discrete solution e.g rome use system tick and convert it into + * seconds.milli seconds + */ +static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts) +{ + int tlen; + uint32_t rem; + + rem = do_div(ts, CDF_MC_TIMER_TO_SEC_UNIT); + tlen = scnprintf(tbuf, tbuf_sz, "[%s][%lu.%06lu] ", current->comm, + (unsigned long) ts, (unsigned long)rem); + return tlen; +} +#endif + +int wlan_log_to_user(CDF_TRACE_LEVEL log_level, char *to_be_sent, int length) +{ + /* Add the current time stamp */ + char *ptr; + char tbuf[50]; + int tlen; + int total_log_len; + unsigned int *pfilled_length; + bool wake_up_thread = false; + unsigned long flags; + uint64_t ts; + + if (!cds_is_multicast_logging()) { + /* + * This is to make sure that we print the logs to kmsg console + * when no logger app is running. This is also needed to + * log the initial messages during loading of driver where even + * if app is running it will not be able to + * register with driver immediately and start logging all the + * messages. + */ + pr_info("%s\n", to_be_sent); + return 0; + } + + ts = cdf_get_log_timestamp(); + tlen = wlan_add_user_log_time_stamp(tbuf, sizeof(tbuf), ts); + + /* 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 + * CDF_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)) { + CDF_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)) { + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + } + + if (gwlan_logging.log_fe_to_console + && ((CDF_TRACE_LEVEL_FATAL == log_level) + || (CDF_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_HOST_DIAG_EVENT_DEF(wlan_diag_event, + struct host_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_HOST_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; + + cds_get_log_completion(&is_fatal, &indicator, &reason_code); + + /* Error on purpose, so that it will get logged in the kmsg */ + LOGGING_TRACE(CDF_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(CDF_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 CDF 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(CDF_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; + } + + cdf_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; + cds_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/core/utils/nlink/inc/wlan_nlink_common.h b/core/utils/nlink/inc/wlan_nlink_common.h new file mode 100644 index 000000000000..7dc7646832c7 --- /dev/null +++ b/core/utils/nlink/inc/wlan_nlink_common.h @@ -0,0 +1,139 @@ +/* + * 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. logging service) and WLAN kernel module. + + ===========================================================================*/ + +#ifndef WLAN_NLINK_COMMON_H__ +#define WLAN_NLINK_COMMON_H__ + +#include + +/*--------------------------------------------------------------------------- + * 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_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_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 + +#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_OEM = ANI_NL_MSG_BASE + 0x09, + 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]; +}; + +struct wlan_dfs_info { + uint16_t channel; + uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN]; +}; + +#endif /* WLAN_NLINK_COMMON_H__ */ diff --git a/core/utils/nlink/inc/wlan_nlink_srv.h b/core/utils/nlink/inc/wlan_nlink_srv.h new file mode 100644 index 000000000000..a973a7b1bfe2 --- /dev/null +++ b/core/utils/nlink/inc/wlan_nlink_srv.h @@ -0,0 +1,60 @@ +/* + * 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); +void nl_srv_exit(void); +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/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c new file mode 100644 index 000000000000..8ed084b8784b --- /dev/null +++ b/core/utils/nlink/src/wlan_nlink_srv.c @@ -0,0 +1,309 @@ +/* + * 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.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 { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + "NLINK: netlink_kernel_create failed"); + retcode = -ECONNREFUSED; + } + return retcode; +} + +/* + * Deinit the netlink service. + * Netlink service is unusable after this. + */ +void nl_srv_exit(void) +{ + if (nl_srv_is_initialized() == 0) + 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 { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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 { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + +#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 */ + + err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag); + + if (err < 0) + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + 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 */ + + err = + netlink_broadcast(nl_srv_sock, skb, 0, WLAN_NLINK_MCAST_GRP_ID, + flags); + + if (err < 0) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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))) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, + "NLINK: Received NL Msg with invalid len[%x]", + nlh->nlmsg_len); + return; + } + + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + "NLINK: Received NL msg type [%d]", type); + + /* 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 { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; + + return -EPERM; +} diff --git a/core/utils/pktlog/include/pktlog.h b/core/utils/pktlog/include/pktlog.h new file mode 100644 index 000000000000..cfbf221847a2 --- /dev/null +++ b/core/utils/pktlog/include/pktlog.h @@ -0,0 +1,39 @@ +/* + * 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 _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/core/utils/pktlog/include/pktlog_ac.h b/core/utils/pktlog/include/pktlog_ac.h new file mode 100644 index 000000000000..0a5a784fe574 --- /dev/null +++ b/core/utils/pktlog/include/pktlog_ac.h @@ -0,0 +1,163 @@ +/* + * 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 _PKTLOG_AC_H_ +#define _PKTLOG_AC_H_ +#ifndef REMOVE_PKT_LOG + +#include "ol_if_athvar.h" +#include +#include +#include "osdep.h" +#include +#include +#include +#include "hif.h" + +#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); + +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); + +#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) + +#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/core/utils/pktlog/include/pktlog_ac_api.h b/core/utils/pktlog/include/pktlog_ac_api.h new file mode 100644 index 000000000000..04b32f70f126 --- /dev/null +++ b/core/utils/pktlog/include/pktlog_ac_api.h @@ -0,0 +1,115 @@ +/* + * 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. + */ + +/* + * 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; + uint32_t log_state; + uint32_t saved_state; + uint32_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 */ + uint32_t thruput_thresh; + + /* (aggregated or single) packet size in bytes */ + uint32_t pktlen; + + /* a temporary variable for counting TX throughput only */ + /* PER threshold for triggered stop, 10 for 10%, range [1, 99] */ + uint32_t per_thresh; + + /* Phyerr threshold for triggered stop */ + uint32_t phyerr_thresh; + + /* time period for counting trigger parameters, in milisecond */ + uint32_t trigger_interval; + uint32_t start_time_thruput; + uint32_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/core/utils/pktlog/include/pktlog_ac_i.h b/core/utils/pktlog/include/pktlog_ac_i.h new file mode 100644 index 000000000000..07bbac07a168 --- /dev/null +++ b/core/utils/pktlog/include/pktlog_ac_i.h @@ -0,0 +1,67 @@ +/* + * 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 _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; + uint32_t flags; + uint16_t missed_cnt; + uint16_t log_type; + size_t log_size; + uint16_t timestamp; +#ifdef HELIUMPLUS + uint32_t type_specific_data; +#endif + 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, cdf_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/core/utils/pktlog/linux_ac.c b/core/utils/pktlog/linux_ac.c new file mode 100644 index 000000000000..3b5dc1b943fc --- /dev/null +++ b/core/utils/pktlog/linux_ac.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. + */ + +#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_host_diag_core_log.h" +#include "host_diag_core_log.h" +#include "ani_global.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) +{ + ol_txrx_pdev_handle pdev_txrx_handle; + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev_txrx_handle) + return NULL; + return pdev_txrx_handle->pl_dev; +} + +void ol_pl_set_name(ol_softc_handle scn, net_device_handle dev) +{ + ol_txrx_pdev_handle pdev_txrx_handle; + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); + if (pdev_txrx_handle && pdev_txrx_handle->pl_dev && dev) + 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) +{ + uint32_t page_cnt; + unsigned long vaddr; + struct page *vpg; + struct ath_pktlog_info *pl_info; + ol_txrx_pdev_handle pdev_txrx_handle; + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); + + if (!pdev_txrx_handle || !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 = 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; + ol_txrx_pdev_handle pdev_txrx_handle; + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); + + if (!pdev_txrx_handle || !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 = 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 host_log_pktlog_info *pktlog = NULL; + ol_txrx_pdev_handle txrx_pdev = + cds_get_context(CDF_MODULE_ID_TXRX); + 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 ((cds_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 host_log_pktlog_info *) + cdf_mem_malloc(sizeof(struct host_log_pktlog_info) + + VOS_LOG_PKT_LOG_SIZE); + if (!pktlog) { + printk(PKTLOG_TAG " %s: Memory allocation failed\n", + __func__); + return -ENOMEM; + } + + cdf_mem_zero(pktlog, VOS_LOG_PKT_LOG_SIZE); + host_diag_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) { + host_diag_log_set_length(pktlog, ret_val + + sizeof(struct host_log_pktlog_info)); + pktlog->seq_no = pl_info->buf->msg_index++; + WLAN_HOST_DIAG_LOG_REPORT(pktlog); + } else { + cdf_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 > HOST_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); + cdf_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)); + cdf_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)); + cdf_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)); + cdf_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 = CDF_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 = CDF_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 = CDF_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 = CDF_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; + + if (!scn) + return; + + pl_dev = get_pl_handle(scn); + + if (!pl_dev || g_pktlog_pde == NULL) + 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/core/utils/pktlog/pktlog_ac.c b/core/utils/pktlog/pktlog_ac.c new file mode 100644 index 000000000000..7bc10efb8826 --- /dev/null +++ b/core/utils/pktlog/pktlog_ac.c @@ -0,0 +1,449 @@ +/* + * 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. + */ + +/* + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 REMOVE_PKT_LOG +#include "cdf_memory.h" +#include "athdefs.h" +#include "pktlog_ac_i.h" +#include "cds_api.h" +#include "wma_types.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) +{ + cds_msg_t msg = { 0 }; + CDF_STATUS status; + struct ath_pktlog_wmi_params *param; + + param = cdf_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 = WMA_PKTLOG_ENABLE_REQ; + msg.bodyptr = param; + msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_WMA, &msg); + + if (status != CDF_STATUS_SUCCESS) { + cdf_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_txrx_pdev_t *txrx_pdev = + cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + + if (txrx_pdev == NULL || + txrx_pdev->pl_dev == NULL || + txrx_pdev->pl_dev->pl_info == NULL) + return -EFAULT; + + pl_dev = txrx_pdev->pl_dev; + pl_info = pl_dev->pl_info; + + 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; + ol_txrx_pdev_handle pdev_txrx_handle; + pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); + + if (pdev_txrx_handle == NULL || + pdev_txrx_handle->pl_dev == NULL || + pdev_txrx_handle->pl_dev->pl_info == NULL) + return; + + pl_info = pdev_txrx_handle->pl_dev->pl_info; + + OS_MEMZERO(pl_info, sizeof(*pl_info)); + PKTLOG_LOCK_INIT(pl_info); + + pl_info->buf_size = PKTLOG_DEFAULT_BUFSIZE; + pl_info->buf = NULL; + pl_info->log_state = 0; + pl_info->sack_thr = PKTLOG_DEFAULT_SACK_THR; + pl_info->tail_length = PKTLOG_DEFAULT_TAIL_LENGTH; + pl_info->thruput_thresh = PKTLOG_DEFAULT_THRUPUT_THRESH; + pl_info->per_thresh = PKTLOG_DEFAULT_PER_THRESH; + pl_info->phyerr_thresh = PKTLOG_DEFAULT_PHYERR_THRESH; + pl_info->trigger_interval = PKTLOG_DEFAULT_TRIGGER_INTERVAL; + pl_info->pktlen = 0; + pl_info->start_time_thruput = 0; + pl_info->start_time_per = 0; + + PKTLOG_TX_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RX_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RX_REMOTE_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RCFIND_SUBSCRIBER.callback = pktlog_callback; + PKTLOG_RCUPDATE_SUBSCRIBER.callback = pktlog_callback; +} + +int pktlog_enable(struct ol_softc *scn, int32_t log_state) +{ + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + struct ol_txrx_pdev_t *txrx_pdev; + int error; + + if (!scn) { + printk("%s: Invalid scn context\n", __func__); + ASSERT(0); + return -1; + } + + txrx_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!txrx_pdev) { + printk("%s: Invalid txrx_pdev context\n", __func__); + ASSERT(0); + return -1; + } + + pl_dev = txrx_pdev->pl_dev; + if (!pl_dev) { + printk("%s: Invalid pktlog context\n", __func__); + ASSERT(0); + return -1; + } + + pl_info = pl_dev->pl_info; + pl_dev->sc_osdev = &scn->aps_osdev; + + if (!pl_info) + return 0; + + if (log_state != 0 && !pl_dev->tgt_pktlog_enabled) { + if (pl_info->buf == NULL) { + error = pktlog_alloc_buf(scn); + + if (error != 0) + return error; + + if (!pl_info->buf) { + printk("%s: pktlog buf alloc failed\n", + __func__); + ASSERT(0); + return -1; + } + + } + + pl_info->buf->bufhdr.version = CUR_PKTLOG_VER; + pl_info->buf->bufhdr.magic_num = PKTLOG_MAGIC_NUM; + pl_info->buf->wr_offset = 0; + pl_info->buf->rd_offset = -1; + /* These below variables are used by per packet stats*/ + pl_info->buf->bytes_written = 0; + pl_info->buf->msg_index = 1; + pl_info->buf->offset = PKTLOG_READ_OFFSET; + + pl_info->start_time_thruput = os_get_timestamp(); + pl_info->start_time_per = pl_info->start_time_thruput; + + /* WDI subscribe */ + if (wdi_pktlog_subscribe(txrx_pdev, log_state)) { + printk("Unable to subscribe to the WDI %s\n", __func__); + return -1; + } + /* WMI command to enable pktlog on the firmware */ + if (pktlog_enable_tgt(scn, log_state)) { + printk("Device cannot be enabled, %s\n", __func__); + return -1; + } else { + pl_dev->tgt_pktlog_enabled = true; + } + } else if (!log_state && pl_dev->tgt_pktlog_enabled) { + pl_dev->pl_funcs->pktlog_disable(scn); + pl_dev->tgt_pktlog_enabled = false; + if (wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) { + printk("Cannot unsubscribe pktlog from the WDI\n"); + return -1; + } + } + + pl_info->log_state = log_state; + return 0; +} + +int pktlog_setsize(struct ol_softc *scn, int32_t size) +{ + ol_txrx_pdev_handle pdev_txrx_handle = + cds_get_context(CDF_MODULE_ID_TXRX); + struct ol_pktlog_dev_t *pl_dev; + struct ath_pktlog_info *pl_info; + + if (pdev_txrx_handle == NULL || + pdev_txrx_handle->pl_dev == NULL || + pdev_txrx_handle->pl_dev->pl_info == NULL) + return -EFAULT; + + pl_dev = pdev_txrx_handle->pl_dev; + 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/core/utils/pktlog/pktlog_internal.c b/core/utils/pktlog/pktlog_internal.c new file mode 100644 index 000000000000..23c01b456ff5 --- /dev/null +++ b/core/utils/pktlog/pktlog_internal.c @@ -0,0 +1,680 @@ +/* + * 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. + */ + +/* + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 REMOVE_PKT_LOG +#include "ol_txrx_types.h" +#include "ol_htt_tx_api.h" +#include "ol_tx_desc.h" +#include "cdf_memory.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; + uint16_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 = (uint16_t) log_size; + log_hdr->missed_cnt = plarg->missed_cnt; + log_hdr->timestamp = plarg->timestamp; +#ifdef HELIUMPLUS + log_hdr->type_specific_data = plarg->type_specific_data; +#endif + 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; +#ifdef HELIUMPLUS + plarg.type_specific_data = pl_hdr->type_specific_data; +#endif + 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 (cds_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 = *(uint16_t *) (wh->i_fc); + frm_hdr.seqctrl = *(uint16_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; + } + cdf_assert(txrx_pdev->pl_dev); + cdf_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); +#ifdef HELIUMPLUS + pl_hdr.type_specific_data = + *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); +#endif + 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); + cdf_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) { +#if !defined(HELIUMPLUS) + 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; + cdf_assert(txctl_log.priv.txdesc_ctl); + cdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl, + ((void *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cdf_assert(txctl_log.txdesc_hdr_ctl); + cdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, + sizeof(txctl_log.priv)); + /* Add Protocol information and HT specific information */ +#else + size_t log_size = sizeof(frm_hdr) + pl_hdr.size; + void *txdesc_hdr_ctl = (void *) + pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); + cdf_assert(txdesc_hdr_ctl); + cdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t))); + + cdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr)); + cdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr), + ((void *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); +#endif /* !defined(HELIUMPLUS) */ + } + + 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); + cdf_assert(txstat_log.ds_status); + cdf_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); + uint8_t *addr, *vap_addr; + uint8_t vdev_id; + cdf_nbuf_t netbuf; + uint32_t len; + + cdf_mem_set(&pl_msdu_info, sizeof(pl_msdu_info), 0); + + pl_msdu_info.num_msdu = *msdu_id_info; + pl_msdu_info.priv_size = sizeof(uint32_t) * + pl_msdu_info.num_msdu + sizeof(uint32_t); + log_size = sizeof(pl_msdu_info.priv); + + for (i = 0; i < pl_msdu_info.num_msdu; i++) { + /* + * Handle big endianess + * Increment msdu_id once after retrieving + * lower 16 bits and uppper 16 bits + */ + if (!(i % 2)) { + tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) + >> TX_DESC_ID_LOW_SHIFT); + } else { + tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) + >> TX_DESC_ID_HIGH_SHIFT); + msdu_id += 1; + } + tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); + cdf_assert(tx_desc); + netbuf = tx_desc->netbuf; + htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; + cdf_assert(htt_tx_desc); + + cdf_nbuf_peek_header(netbuf, &addr, &len); + + if (len < (2 * IEEE80211_ADDR_LEN)) { + cdf_print("TX frame does not have a valid" + " address\n"); + return -1; + } + /* Adding header information for the TX data frames */ + vdev_id = (uint8_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); + cdf_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)); + cdf_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, cdf_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; + cdf_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 *)(cdf_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); +#if defined(HELIUMPLUS) + pl_hdr.timestamp = + rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; + pl_hdr.type_specific_data = 0xDEADAA; +#else + pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; +#endif /* !defined(HELIUMPLUS) */ + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + cdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + + sizeof(struct htt_host_fw_desc_base), pl_hdr.size); + msdu = cdf_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); + + cdf_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) { + cdf_print("Invalid pdev in %s\n", __func__); + return A_ERROR; + } + if (!data) { + cdf_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); + + cdf_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); + cdf_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/core/utils/ptt/inc/wlan_ptt_sock_svc.h b/core/utils/ptt/inc/wlan_ptt_sock_svc.h new file mode 100644 index 000000000000..7e17dd8329ec --- /dev/null +++ b/core/utils/ptt/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 +/* + * 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); +void ptt_sock_deactivate_svc(void); +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/core/utils/ptt/src/wlan_ptt_sock_svc.c b/core/utils/ptt/src/wlan_ptt_sock_svc.c new file mode 100644 index 000000000000..b9a9c12c3320 --- /dev/null +++ b/core/utils/ptt/src/wlan_ptt_sock_svc.c @@ -0,0 +1,229 @@ +/* + * 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 + +#define PTT_SOCK_DEBUG +#ifdef PTT_SOCK_DEBUG +#define PTT_TRACE(level, args ...) CDF_TRACE(CDF_MODULE_ID_CDF, level, ## args) +#else +#define PTT_TRACE(level, args ...) +#endif + +/** ptt Process ID */ +static int32_t ptt_pid = INVALID_PID; + +#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) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "\n%p:", pbuf); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, " %02X", + *pbuf); + pbuf++; + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "\n"); +} +#endif + +/** + * ptt_sock_send_msg_to_app() - Send nl message to user space + * wmsg: Message header + * radio: Unit number of the radio + * src_mod: Message type + * pid: Process ID to which message will be unicast. Message + * will be broadcast when PID is INVALID_PID + * + * Utility function to send a netlink message to an application in user space + * + * Return: 0 on success and negative value on failure + */ +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(CDF_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(CDF_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(CDF_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(CDF_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 != INVALID_PID) + 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 */ + 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, ptt_pid) < 0) { + PTT_TRACE(CDF_TRACE_LEVEL_ERROR, + "%s: Error sending ANI_MSG_APP_REG_RSP to pid[%d]\n", + __func__, ptt_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(CDF_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(CDF_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(CDF_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(CDF_TRACE_LEVEL_ERROR, "%s: Unknown NL Msg [0x%X]\n", + __func__, type); + break; + } + return 0; +} + +/** + * ptt_sock_activate_svc() - activate PTT service + * + * Return: 0 + */ +int ptt_sock_activate_svc(void) +{ + 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; +} + +/** + * ptt_sock_deactivate_svc() - deactivate PTT service + * + * Return: Void + */ +void ptt_sock_deactivate_svc(void) +{ + ptt_pid = INVALID_PID; +} + +#endif /* PTT_SOCK_SVC_ENABLE */ diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h new file mode 100644 index 000000000000..9eec65bdadd8 --- /dev/null +++ b/core/wma/inc/wma.h @@ -0,0 +1,1981 @@ +/* + * 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 WMA_H +#define WMA_H + +#include "a_types.h" +#include "cdf_types.h" +#include "osapi_linux.h" +#include "htc_packet.h" +#include "i_cdf_event.h" +#include "wmi_services.h" +#include "wmi_unified.h" +#include "wmi_version.h" +#include "cdf_types.h" +#include "cfg_api.h" +#include "cdf_status.h" +#include "cds_sched.h" +#include "ol_txrx_api.h" +#include "sir_mac_prot_def.h" +#include "wma_types.h" +#include "ol_txrx_types.h" +#include +#include "utils_api.h" +#include "lim_types.h" +#include "wmi_unified_api.h" + +/* Platform specific configuration for max. no. of fragments */ +#define QCA_OL_11AC_TX_MAX_FRAGS 2 + +/* Private */ + +#ifndef QCA_WIFI_3_0_EMU + +#define WMA_READY_EVENTID_TIMEOUT 2000 +#define WMA_TGT_SUSPEND_COMPLETE_TIMEOUT 6000 +#define WMA_WAKE_LOCK_TIMEOUT 1000 +#define WMA_MAX_RESUME_RETRY 1000 +#define WMA_RESUME_TIMEOUT 6000 +#define MAX_MEM_CHUNKS 32 + +#else + +#define WMA_READY_EVENTID_TIMEOUT 200000 +#define WMA_TGT_SUSPEND_COMPLETE_TIMEOUT 300000 +#define WMA_WAKE_LOCK_TIMEOUT 1000 +#define WMA_MAX_RESUME_RETRY 1000 +#define WMA_RESUME_TIMEOUT 300000 +#define MAX_MEM_CHUNKS 32 + +#endif + +#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 ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, ## args) +#define WMA_LOGI(args ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO, ## args) +#define WMA_LOGW(args ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_WARN, ## args) +#define WMA_LOGE(args ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, ## args) +#define WMA_LOGP(args ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_FATAL, ## args) + +#define WMA_DEBUG_ALWAYS + +#ifdef WMA_DEBUG_ALWAYS +#define WMA_LOGA(args ...) \ + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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) + + +/* 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 + +#define WMA_BCN_BUF_MAX_SIZE 2500 +#define WMA_NOA_IE_SIZE(num_desc) (2 + (13 * (num_desc))) +#define WMA_MAX_NOA_DESCRIPTORS 4 + +#define WMA_TIM_SUPPORTED_PVB_LENGTH ((HAL_NUM_STA / 8) + 1) + +#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 + +#define WMA_BSS_STATUS_STARTED 0x1 +#define WMA_BSS_STATUS_STOPPED 0x2 + +#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_TXBF_INFO_STATS 0x07 +#define WMA_FW_SND_INFO_STATS 0x08 +#define WMA_FW_ERROR_INFO_STATS 0x09 +#define WMA_FW_TX_SELFGEN_INFO_STATS 0xa +#define WMA_FW_RX_REM_RING_BUF 0xc +#define WMA_FW_RX_TXBF_MUSU_NDPA 0xf + +#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_PEER_ASSOC_CNF_START 0x01 +#define WMA_PEER_ASSOC_TIMEOUT (3000) /* 3 seconds */ + +#define WMA_VDEV_START_REQUEST_TIMEOUT (3000) /* 3 seconds */ +#define WMA_VDEV_STOP_REQUEST_TIMEOUT (3000) /* 3 seconds */ + +#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 + +#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 + +/* + * 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 + + +/* 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) + +#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 */ + +#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) + + +#define WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE 1 + +#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 + +#define WMA_DFS_MAX_20M_SUB_CH 8 + +#define WMA_DEFAULT_HW_MODE_INDEX 0xFFFF + +/** + * struct probeTime_dwellTime - probe time, dwell time map + * @dwell_time: dwell time + * @probe_time: repeat probe time + */ +typedef struct probeTime_dwellTime { + uint8_t dwell_time; + uint8_t probe_time; +} t_probeTime_dwellTime; + +static const t_probeTime_dwellTime + probe_time_dwell_time_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 */ +}; + +/** + * enum t_wma_drv_type - wma driver type + * @WMA_DRIVER_TYPE_PRODUCTION: production driver type + * @WMA_DRIVER_TYPE_MFG: manufacture driver type + * @WMA_DRIVER_TYPE_INVALID: invalid driver type + */ +typedef enum { + WMA_DRIVER_TYPE_PRODUCTION = 0, + WMA_DRIVER_TYPE_MFG = 1, + WMA_DRIVER_TYPE_INVALID = 0x7FFFFFFF +} t_wma_drv_type; + +#ifdef FEATURE_WLAN_TDLS +/** + * enum t_wma_tdls_mode: TDLS mode + * @WMA_TDLS_SUPPORT_NOT_ENABLED: tdls is disable + * @WMA_TDLS_SUPPORT_DISABLED: suppress implicit trigger and not respond to peer + * @WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY: suppress implicit trigger, + * but respond to the peer + * @WMA_TDLS_SUPPORT_ENABLED: implicit trigger + */ +typedef enum { + WMA_TDLS_SUPPORT_NOT_ENABLED = 0, + WMA_TDLS_SUPPORT_DISABLED, + WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, + WMA_TDLS_SUPPORT_ENABLED, +} t_wma_tdls_mode; + +/** + * enum wma_tdls_peer_notification - TDLS events + * @WMA_TDLS_SHOULD_DISCOVER: 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_TEARDOWN: tdls link tear down recommended for peer + * due to tx bytes per second below + * tx_teardown_threshold + * NB: this notification sent once + * @WMA_TDLS_PEER_DISCONNECTED: tx peer TDLS link tear down complete + */ +enum wma_tdls_peer_notification { + WMA_TDLS_SHOULD_DISCOVER, + WMA_TDLS_SHOULD_TEARDOWN, + WMA_TDLS_PEER_DISCONNECTED, +}; + +/** + * enum wma_tdls_peer_reason - TDLS peer reason + * @WMA_TDLS_TEARDOWN_REASON_TX: tdls teardown recommended due to low transmits + * @WMA_TDLS_TEARDOWN_REASON_RATE: tdls tear down recommended due to + * packet rates < AP rates + * @WMA_TDLS_TEARDOWN_REASON_RSSI: tdls link tear down recommended + * due to poor RSSI + * @WMA_TDLS_TEARDOWN_REASON_SCAN: tdls link tear down recommended + * due to offchannel scan + * @WMA_TDLS_DISCONNECTED_REASON_PEER_DELETE: tdls peer disconnected + * due to peer deletion + */ +enum wma_tdls_peer_reason { + WMA_TDLS_TEARDOWN_REASON_TX, + WMA_TDLS_TEARDOWN_REASON_RATE, + WMA_TDLS_TEARDOWN_REASON_RSSI, + WMA_TDLS_TEARDOWN_REASON_SCAN, + WMA_TDLS_DISCONNECTED_REASON_PEER_DELETE, +}; +#endif /* FEATURE_WLAN_TDLS */ + + +/** + * enum t_wma_roam_preauth_chan_state_t - Roaming preauth channel state + * @WMA_ROAM_PREAUTH_CHAN_NONE: no preauth in progress + * @WMA_ROAM_PREAUTH_CHAN_REQUESTED: preaduth channel requested + * @WMA_ROAM_PREAUTH_ON_CHAN: preauth on channel + * @WMA_ROAM_PREAUTH_CHAN_CANCEL_REQUESTED: preauth channel cancel requested + * @WMA_ROAM_PREAUTH_CHAN_COMPLETED: preauth completed + */ +typedef enum { + 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; + +/** + * struct wma_mem_chunk - memory chunks + * @vaddr: virtual address + * @paddr: physical address + * @memctx: dma mapped memory + * @len: length of data + * @req_id: request id + * + * memory chunck allocated by Host to be managed by FW + * used only for low latency interfaces like pcie + */ +struct wma_mem_chunk { + uint32_t *vaddr; + uint32_t paddr; + cdf_dma_mem_context(memctx); + uint32_t len; + uint32_t req_id; +}; + +/** + * struct p2p_scan_param - p2p scan listen parameters + * @scan_id: scan id + * @p2p_scan_type: p2p scan type + */ +struct p2p_scan_param { + uint32_t scan_id; + tSirP2pScanType p2p_scan_type; +}; + +/** + * struct scan_param - scan parameters + * @scan_id: scan id + * @scan_requestor_id: scan requestor id + * @p2p_scan_type: p2p scan type + */ +struct scan_param { + uint32_t scan_id; + uint32_t scan_requestor_id; + tSirP2pScanType p2p_scan_type; +}; + +/** + * struct beacon_info - structure to store beacon template + * @buf: skb ptr + * @len: length + * @dma_mapped: is it dma mapped or not + * @tim_ie_offset: TIM IE offset + * @dtim_count: DTIM count + * @seq_no: sequence no + * @noa_sub_ie: NOA sub IE + * @noa_sub_ie_len: NOA sub IE length + * @noa_ie: NOA IE + * @p2p_ie_offset: p2p IE offset + * @lock: lock + */ +struct beacon_info { + cdf_nbuf_t buf; + uint32_t len; + uint8_t dma_mapped; + uint32_t tim_ie_offset; + uint8_t dtim_count; + uint16_t seq_no; + uint8_t noa_sub_ie[2 + WMA_NOA_IE_SIZE(WMA_MAX_NOA_DESCRIPTORS)]; + uint16_t noa_sub_ie_len; + uint8_t *noa_ie; + uint16_t p2p_ie_offset; + cdf_spinlock_t lock; +}; + +/** + * struct beacon_tim_ie - structure to store TIM IE of beacon + * @tim_ie: tim ie + * @tim_len: tim ie length + * @dtim_count: dtim count + * @dtim_period: dtim period + * @tim_bitctl: tim bit control + * @tim_bitmap: tim bitmap + */ +struct beacon_tim_ie { + uint8_t tim_ie; + uint8_t tim_len; + uint8_t dtim_count; + uint8_t dtim_period; + uint8_t tim_bitctl; + uint8_t tim_bitmap[1]; +} __ATTRIB_PACK; + +/** + * struct pps - packet power save parameter + * @paid_match_enable: paid match enable + * @gid_match_enable: gid match enable + * @tim_clear: time clear + * @dtim_clear: dtim clear + * @eof_delim: eof delim + * @mac_match: mac match + * @delim_fail: delim fail + * @nsts_zero: nsts zero + * @rssi_chk: RSSI check + * @ebt_5g: ebt 5GHz + */ +struct pps { + bool paid_match_enable; + bool gid_match_enable; + bool tim_clear; + bool dtim_clear; + bool eof_delim; + bool mac_match; + bool delim_fail; + bool nsts_zero; + bool rssi_chk; + bool ebt_5g; +}; + +/** + * struct qpower_params - qpower related parameters + * @max_ps_poll_cnt: max ps poll count + * @max_tx_before_wake: max tx before wake + * @spec_ps_poll_wake_interval: ps poll wake interval + * @max_spec_nodata_ps_poll: no data ps poll + */ +struct qpower_params { + uint32_t max_ps_poll_cnt; + uint32_t max_tx_before_wake; + uint32_t spec_ps_poll_wake_interval; + uint32_t max_spec_nodata_ps_poll; +}; + + +/** + * struct gtx_config_t - GTX config + * @gtxRTMask: for HT and VHT rate masks + * @gtxUsrcfg: host request for GTX mask + * @gtxPERThreshold: PER Threshold (default: 10%) + * @gtxPERMargin: PER margin (default: 2%) + * @gtxTPCstep: TCP step (default: 1) + * @gtxTPCMin: TCP min (default: 5) + * @gtxBWMask: BW mask (20/40/80/160 Mhz) + */ +typedef struct { + uint32_t gtxRTMask[2]; + uint32_t gtxUsrcfg; + uint32_t gtxPERThreshold; + uint32_t gtxPERMargin; + uint32_t gtxTPCstep; + uint32_t gtxTPCMin; + uint32_t gtxBWMask; +} gtx_config_t; + +/** + * struct pdev_cli_config_t - store pdev parameters + * @ani_enable: ANI is enabled/disable on target + * @ani_poll_len: store ANI polling period + * @ani_listen_len: store ANI listening period + * @ani_ofdm_level: store ANI OFDM immunity level + * @ani_cck_level: store ANI CCK immunity level + * @cwmenable: Dynamic bw is enable/disable in fw + * @txchainmask: tx chain mask + * @rxchainmask: rx chain mask + * @txpow2g: tx power limit for 2GHz + * @txpow5g: tx power limit for 5GHz + * @pwrgating: enable/disable power gating sleep + * @burst_enable: is burst enable/disable + * @burst_dur: burst duration + * + * This structure stores pdev parameters. + * Some of these parameters are set in fw and some + * parameters are only maintained in host. + */ +typedef struct { + uint32_t ani_enable; + uint32_t ani_poll_len; + uint32_t ani_listen_len; + uint32_t ani_ofdm_level; + uint32_t ani_cck_level; + uint32_t cwmenable; + uint32_t cts_cbw; + uint32_t txchainmask; + uint32_t rxchainmask; + uint32_t txpow2g; + uint32_t txpow5g; + uint32_t pwrgating; + uint32_t burst_enable; + uint32_t burst_dur; +} pdev_cli_config_t; + +/** + * struct vdev_cli_config_t - store vdev parameters + * @nss: nss width + * @ldpc: is ldpc is enable/disable + * @tx_stbc: TX STBC is enable/disable + * @rx_stbc: RX STBC is enable/disable + * @shortgi: short gi is enable/disable + * @rtscts_en: RTS/CTS is enable/disable + * @chwidth: channel width + * @tx_rate: tx rate + * @ampdu: ampdu size + * @amsdu: amsdu size + * @erx_adjust: enable/disable early rx enable + * @erx_bmiss_num: target bmiss number per sample + * @erx_bmiss_cycle: sample cycle + * @erx_slop_step: slop_step value + * @erx_init_slop: init slop + * @erx_adj_pause: pause adjust enable/disable + * @erx_dri_sample: enable/disable drift sample + * @pps_params: packet power save parameters + * @qpower_params: qpower parameters + * @gtx_info: GTX offload info + * + * This structure stores vdev parameters. + * Some of these parameters are set in fw and some + * parameters are only maintained in host. + */ +typedef struct { + uint32_t nss; + uint32_t ldpc; + uint32_t tx_stbc; + uint32_t rx_stbc; + uint32_t shortgi; + uint32_t rtscts_en; + uint32_t chwidth; + uint32_t tx_rate; + uint32_t ampdu; + uint32_t amsdu; + uint32_t erx_adjust; + uint32_t erx_bmiss_num; + uint32_t erx_bmiss_cycle; + uint32_t erx_slop_step; + uint32_t erx_init_slop; + uint32_t erx_adj_pause; + uint32_t erx_dri_sample; + struct pps pps_params; + struct qpower_params qpower_params; + gtx_config_t gtx_info; +} vdev_cli_config_t; + +/** + * struct wma_wow - store wow patterns + * @magic_ptrn_enable: magic pattern enable/disable + * @wow_enable: wow enable/disable + * @wow_enable_cmd_sent: is wow enable command sent to fw + * @deauth_enable: is deauth wakeup enable/disable + * @disassoc_enable: is disassoc wakeup enable/disable + * @bmiss_enable: is bmiss wakeup enable/disable + * @gtk_pdev_enable: is GTK based wakeup enable/disable + * @gtk_err_enable: is GTK error wakeup enable/disable + * @lphb_cache: lphb cache + * + * This structure stores wow patterns and + * wow related parameters in host. + */ +struct wma_wow { + bool magic_ptrn_enable; + bool wow_enable; + bool wow_enable_cmd_sent; + bool deauth_enable; + bool disassoc_enable; + bool bmiss_enable; + bool gtk_pdev_enable; + bool 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) + +/** + * struct wma_igtk_ipn_t - GTK IPN info + * @ipn: IPN info + */ +typedef struct { + uint8_t ipn[CMAC_IPN_LEN]; +} wma_igtk_ipn_t; + +/** + * struct wma_igtk_key_t - GTK key + * @key_length: key length + * @key: key + * @key_id: key id + */ +typedef struct { + uint16_t key_length; + uint8_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 + +/** + * struct vdev_restart_params_t - vdev restart parameters + * @vdev_id: vdev id + * @ssid: ssid + * @flags: flags + * @requestor_id: requestor id + * @chan: channel + * @hidden_ssid_restart_in_progress: hidden ssid restart flag + * @ssidHidden: is ssid hidden or not + */ +typedef struct { + A_UINT32 vdev_id; + wmi_ssid ssid; + A_UINT32 flags; + A_UINT32 requestor_id; + A_UINT32 disable_hw_ack; + wmi_channel chan; + cdf_atomic_t hidden_ssid_restart_in_progress; + uint8_t ssidHidden; +} vdev_restart_params_t; + +/** + * struct wma_txrx_node - txrx node + * @addr: mac address + * @bssid: bssid + * @handle: wma handle + * @beacon: beacon info + * @vdev_restart_params: vdev restart parameters + * @config: per vdev config parameters + * @scan_info: scan info + * @type: type + * @sub_type: sub type + * @nlo_match_evt_received: is nlo match event received or not + * @pno_in_progress: is pno in progress or not + * @plm_in_progress: is plm in progress or not + * @ptrn_match_enable: is pattern match is enable or not + * @num_wow_default_patterns: number of default wow patterns configured for vdev + * @num_wow_user_patterns: number of user wow patterns configured for vdev + * @conn_state: connection state + * @beaconInterval: beacon interval + * @llbCoexist: 11b coexist + * @shortSlotTimeSupported: is short slot time supported or not + * @dtimPeriod: DTIM period + * @chanmode: channel mode + * @vht_capable: VHT capablity flag + * @ht_capable: HT capablity flag + * @mhz: channel frequency in KHz + * @vdev_up: is vdev up or not + * @tsfadjust: TSF adjust + * @addBssStaContext: add bss context + * @aid: association id + * @rmfEnabled: Robust Management Frame (RMF) enabled/disabled + * @key: GTK key + * @uapsd_cached_val: uapsd cached value + * @stats_rsp: stats response + * @fw_stats_set: fw stats value + * @del_staself_req: delete sta self request + * @bss_status: bss status + * @rate_flags: rate flags + * @nss: nss value + * @is_channel_switch: is channel switch + * @pause_bitmap: pause bitmap + * @tx_power: tx power in dbm + * @max_tx_power: max tx power in dbm + * @nwType: network type (802.11a/b/g/n/ac) + * @staKeyParams: sta key parameters + * @ps_enabled: is powersave enable/disable + * @dtim_policy: DTIM policy + * @peer_count: peer count + * @roam_synch_in_progress: flag is in progress or not + * @plink_status_req: link status request + * @psnr_req: snr request + * @delay_before_vdev_stop: delay + * @tx_streams: number of tx streams can be used by the vdev + * @rx_streams: number of rx streams can be used by the vdev + * @chain_mask: chain mask can be used by the vdev + * @mac_id: the mac on which vdev is on + * + * It stores parameters per vdev in wma. + */ +struct wma_txrx_node { + uint8_t addr[IEEE80211_ADDR_LEN]; + uint8_t bssid[IEEE80211_ADDR_LEN]; + void *handle; + struct beacon_info *beacon; + vdev_restart_params_t vdev_restart_params; + vdev_cli_config_t config; + struct scan_param scan_info; + struct p2p_scan_param p2p_scan_info; + uint32_t type; + uint32_t sub_type; +#ifdef FEATURE_WLAN_SCAN_PNO + bool nlo_match_evt_received; + bool pno_in_progress; +#endif +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + bool plm_in_progress; +#endif + bool ptrn_match_enable; + uint8_t num_wow_default_patterns; + uint8_t num_wow_user_patterns; + bool conn_state; + tSirMacBeaconInterval beaconInterval; + uint8_t llbCoexist; + uint8_t shortSlotTimeSupported; + uint8_t dtimPeriod; + WLAN_PHY_MODE chanmode; + uint8_t vht_capable; + uint8_t ht_capable; + A_UINT32 mhz; + bool vdev_up; + uint64_t tsfadjust; + void *addBssStaContext; + uint8_t aid; + uint8_t rmfEnabled; +#ifdef WLAN_FEATURE_11W + wma_igtk_key_t key; +#endif /* WLAN_FEATURE_11W */ + uint32_t uapsd_cached_val; + tAniGetPEStatsRsp *stats_rsp; + uint8_t fw_stats_set; + void *del_staself_req; + cdf_atomic_t bss_status; + uint8_t rate_flags; + uint8_t nss; + bool is_channel_switch; + uint16_t pause_bitmap; + tPowerdBm tx_power; + tPowerdBm max_tx_power; + uint32_t nwType; +#if defined WLAN_FEATURE_VOWIFI_11R + void *staKeyParams; +#endif + bool ps_enabled; + uint32_t dtim_policy; + uint32_t peer_count; + bool roam_synch_in_progress; + void *plink_status_req; + void *psnr_req; + uint8_t delay_before_vdev_stop; +#ifdef FEATURE_WLAN_EXTSCAN + bool extscan_in_progress; +#endif + uint32_t alt_modulated_dtim; + bool alt_modulated_dtim_enabled; + uint32_t tx_streams; + uint32_t rx_streams; + uint32_t chain_mask; + uint32_t mac_id; +}; + +#if defined(QCA_WIFI_FTM) +#define MAX_UTF_EVENT_LENGTH 2048 +#define MAX_WMI_UTF_LEN 252 + +/** + * struct SEG_HDR_INFO_STRUCT - header info + * @len: length + * @msgref: message refrence + * @segmentInfo: segment info + * @pad: padding + */ +typedef struct { + A_UINT32 len; + A_UINT32 msgref; + A_UINT32 segmentInfo; + A_UINT32 pad; +} SEG_HDR_INFO_STRUCT; + +/** + * struct utf_event_info - UTF event info + * @data: data ptr + * @length: length + * @offset: offset + * @currentSeq: curent squence + * @expectedSeq: expected sequence + */ +struct utf_event_info { + uint8_t *data; + uint32_t length; + cdf_size_t offset; + uint8_t currentSeq; + uint8_t expectedSeq; +}; +#endif + +/** + * struct scan_timer_info - scan timer info + * @vdev_id: vdev id + * @scan_id: scan id + */ +typedef struct { + uint8_t vdev_id; + uint32_t scan_id; +} scan_timer_info; + +/** + * struct ibss_power_save_params - IBSS power save parameters + * @atimWindowLength: ATIM window length + * @isPowerSaveAllowed: is power save allowed + * @isPowerCollapseAllowed: is power collapsed allowed + * @isAwakeonTxRxEnabled: is awake on tx/rx enabled + * @inactivityCount: inactivity count + * @txSPEndInactivityTime: tx SP end inactivity time + * @ibssPsWarmupTime: IBSS power save warm up time + * @ibssPs1RxChainInAtimEnable: IBSS power save rx chain in ATIM enable + */ +typedef struct { + uint32_t atimWindowLength; + uint32_t isPowerSaveAllowed; + uint32_t isPowerCollapseAllowed; + uint32_t isAwakeonTxRxEnabled; + uint32_t inactivityCount; + uint32_t txSPEndInactivityTime; + uint32_t ibssPsWarmupTime; + uint32_t ibssPs1RxChainInAtimEnable; +} ibss_power_save_params; + +/** + * struct dbs_hw_mode_info - WLAN_DBS_HW_MODES_TLV Format + * @tlv_header: TLV header, TLV tag and len; tag equals WMITLV_TAG_ARRAY_UINT32 + * @hw_mode_list: WLAN_DBS_HW_MODE_LIST entries + */ +struct dbs_hw_mode_info { + uint32_t tlv_header; + uint32_t *hw_mode_list; +}; + +/* Current HTC credit is 2, pool size of 50 is sufficient */ +#define WMI_DESC_POOL_MAX 50 + +/** + * struct wmi_desc_t - wmi management Tx descriptor. + * @tx_cmpl_cb_func: completion callback function, when DL completion and + * OTA done. + * @ota_post_proc_func: Post process callback function registered. + * @nbuf: Network buffer to be freed. + * @desc_id: WMI descriptor. + */ + +struct wmi_desc_t { + pWMATxRxCompFunc tx_cmpl_cb; + pWMAAckFnTxComp ota_post_proc_cb; + cdf_nbuf_t nbuf; + uint32_t desc_id; +}; + +/** + * union wmi_desc_elem_t - linked list wmi desc pool. + * @next: Pointer next descritor in the pool. + * @wmi_desc: wmi descriptor element. + */ +union wmi_desc_elem_t { + union wmi_desc_elem_t *next; + struct wmi_desc_t wmi_desc; +}; + +/** + * struct dual_mac_config - Dual MAC configurations + * @prev_scan_config: Previous scan configuration + * @prev_fw_mode_config: Previous FW mode configuration + * @cur_scan_config: Current scan configuration + * @cur_fw_mode_config: Current FW mode configuration + * @req_scan_config: Requested scan configuration + * @req_fw_mode_config: Requested FW mode configuration + */ +struct dual_mac_config { + uint32_t prev_scan_config; + uint32_t prev_fw_mode_config; + uint32_t cur_scan_config; + uint32_t cur_fw_mode_config; + uint32_t req_scan_config; + uint32_t req_fw_mode_config; + +}; + +/** + * struct wmi_init_cmd - Saved wmi INIT command + * @buf: Buffer containing the wmi INIT command + * @buf_len: Length of the buffer + */ +struct wmi_init_cmd { + wmi_buf_t buf; + uint32_t buf_len; +}; + +/** + * struct t_wma_handle - wma context + * @wmi_handle: wmi handle + * @htc_handle: htc handle + * @cds_context: cds handle + * @mac_context: mac context + * @wma_ready_event: wma rx ready event + * @wma_resume_event: wma resume event + * @target_suspend: target suspend event + * @recovery_event: wma FW recovery event + * @max_station: max stations + * @max_bssid: max bssid + * @frame_xln_reqd: frame transmission required + * @driver_type: driver type + * @myaddr: current mac address + * @hwaddr: mac address from EEPROM + * @target_abi_vers: target firmware version + * @final_abi_vers: The final ABI version to be used for communicating + * @target_fw_version: Target f/w build version + * @lpss_support: LPSS feature is supported in target or not + * @wmi_ready: wmi status flag + * @wlan_init_status: wlan init status + * @cdf_dev: cdf device + * @phy_capability: PHY Capability from Target + * @max_frag_entry: Max number of Fragment entry + * @wmi_service_bitmap: wmi services bitmap received from Target + * @wlan_resource_config: resource config + * @frameTransRequired: frame transmission required + * @wmaGlobalSystemRole: global system role + * @tx_frm_download_comp_cb: Tx Frame Compl Cb registered by umac + * @tx_frm_download_comp_event: Event to wait for tx download completion + * @tx_queue_empty_event: wait for tx queue to get flushed + * @umac_ota_ack_cb: Ack Complete Callback registered by umac + * @umac_data_ota_ack_cb: ack complete callback + * @last_umac_data_ota_timestamp: timestamp when OTA of last umac data was done + * @last_umac_data_nbuf: cache nbuf ptr for the last umac data buf + * @needShutdown: is shutdown needed or not + * @num_mem_chunks: number of memory chunk + * @mem_chunks: memory chunks + * @tgt_cfg_update_cb: configuration update callback + * @dfs_radar_indication_cb: Callback to indicate radar to HDD + * @reg_cap: regulatory capablities + * @scan_id: scan id + * @interfaces: txrx nodes(per vdev) + * @pdevconfig: pdev related configrations + * @vdev_resp_queue: vdev response queue + * @vdev_respq_lock: vdev response queue lock + * @ht_cap_info: HT capablity info + * @vht_cap_info: VHT capablity info + * @vht_supp_mcs: VHT supported MCS + * @num_rf_chains: number of RF chains + * @utf_event_info: UTF event information + * @is_fw_assert: is fw asserted + * @wow: wow related patterns & parameters + * @no_of_suspend_ind: number of suspend indications + * @no_of_resume_ind: number of resume indications + * @mArpInfo: arp info + * @powersave_mode: power save mode + * @ptrn_match_enable_all_vdev: is pattern match is enable/disable + * @pGetRssiReq: get RSSI request + * @thermal_mgmt_info: Thermal mitigation related info + * @roam_offload_enabled: is roam offload enable/disable + * @roam_preauth_scan_state: roam preauth scan state + * @roam_preauth_scan_id: roam preauth scan id + * @roam_preauth_chanfreq: roam preauth channel frequency + * @roam_preauth_chan_context: roam preauth chan context + * @ol_ini_info: store ini status of arp offload, ns offload + * @ssdp: ssdp flag + * @ibss_started: is IBSS started or not + * @ibsskey_info: IBSS key info + * @dfs_ic: DFS umac interface information + * @hddTxFailCb: tx fail indication callback + * @pno_wake_lock: PNO wake lock + * @extscan_wake_lock: extscan wake lock + * @wow_wake_lock: wow wake lock + * @wow_nack: wow negative ack flag + * @ap_client_cnt: ap client count + * @is_wow_bus_suspended: is wow bus suspended flag + * @wma_scan_comp_timer: scan completion timer + * @dfs_phyerr_filter_offload: dfs phy error filter is offloaded or not + * @suitable_ap_hb_failure: better ap found + * @wma_ibss_power_save_params: IBSS Power Save config Parameters + * @IsRArateLimitEnabled: RA rate limiti s enabled or not + * @RArateLimitInterval: RA rate limit interval + * @is_lpass_enabled: Flag to indicate if LPASS feature is enabled or not + * @is_nan_enabled: Flag to indicate if NaN feature is enabled or not + * @staMaxLIModDtim: station max listen interval + * @staModDtim: station mode DTIM + * @staDynamicDtim: station dynamic DTIM + * @enable_mhf_offload: is MHF offload enable/disable + * @last_mhf_entries_timestamp: timestamp when last entries where set + * @dfs_pri_multiplier: DFS multiplier + * @hw_bd_id: hardware board id + * @hw_bd_info: hardware board info + * @in_d0wow: D0WOW is enable/disable + * @miracast_value: miracast value + * @log_completion_timer: log completion timer + * @mgmt_rx: management rx callback + * @num_dbs_hw_modes: Number of HW modes supported by the FW + * @dbs_mode: DBS HW mode list + * @old_hw_mode_index: Previous configured HW mode index + * @new_hw_mode_index: Current configured HW mode index + * @peer_authorized_cb: peer authorized hdd callback + * @ocb_callback: callback to OCB commands + * @ocb_resp: response to OCB commands + * @wow_pno_match_wake_up_count: PNO match wake up count + * @wow_pno_complete_wake_up_count: PNO complete wake up count + * @wow_gscan_wake_up_count: Gscan wake up count + * @wow_low_rssi_wake_up_count: Low rssi wake up count + * @wow_rssi_breach_wake_up_count: RSSI breach wake up count + * @wow_ucast_wake_up_count: WoW unicast packet wake up count + * @wow_bcast_wake_up_count: WoW brodcast packet wake up count + * @wow_ipv4_mcast_wake_up_count: WoW IPV4 mcast packet wake up count + * @wow_ipv6_mcast_wake_up_count: WoW IPV6 mcast packet wake up count + * @wow_ipv6_mcast_ra_stats: WoW IPV6 mcast RA packet wake up count + * @wow_ipv6_mcast_ns_stats: WoW IPV6 mcast NS packet wake up count + * @wow_ipv6_mcast_na_stats: WoW IPV6 mcast NA packet wake up count + * @dual_mac_cfg: Dual mac configuration params for scan and fw mode + * + * @max_scan: maximum scan requests than can be queued + * This structure is global wma context + * It contains global wma module parameters and + * handle of other modules. + * @saved_wmi_init_cmd: Saved WMI INIT command + * @service_ready_ext_evt: Wait event for service ready ext + */ +typedef struct { + void *wmi_handle; + void *htc_handle; + void *cds_context; + void *mac_context; + cdf_event_t wma_ready_event; + cdf_event_t wma_resume_event; + cdf_event_t target_suspend; + cdf_event_t recovery_event; + uint16_t max_station; + uint16_t max_bssid; + uint32_t frame_xln_reqd; + t_wma_drv_type driver_type; + uint8_t myaddr[IEEE80211_ADDR_LEN]; + uint8_t hwaddr[IEEE80211_ADDR_LEN]; + wmi_abi_version target_abi_vers; + wmi_abi_version final_abi_vers; + uint32_t target_fw_version; +#ifdef WLAN_FEATURE_LPSS + uint8_t lpss_support; +#endif + uint8_t ap_arpns_support; + bool wmi_ready; + uint32_t wlan_init_status; + cdf_device_t cdf_dev; + uint32_t phy_capability; + uint32_t max_frag_entry; + uint32_t wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; + wmi_resource_config wlan_resource_config; + uint32_t frameTransRequired; + tBssSystemRole wmaGlobalSystemRole; + pWMATxRxCompFunc tx_frm_download_comp_cb; + cdf_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. + */ + cdf_event_t tx_queue_empty_event; + pWMAAckFnTxComp umac_ota_ack_cb[SIR_MAC_MGMT_RESERVED15]; + pWMAAckFnTxComp umac_data_ota_ack_cb; + v_TIME_t last_umac_data_ota_timestamp; + cdf_nbuf_t last_umac_data_nbuf; + bool needShutdown; + uint32_t num_mem_chunks; + struct wma_mem_chunk mem_chunks[MAX_MEM_CHUNKS]; + wma_tgt_cfg_cb tgt_cfg_update_cb; + wma_dfs_radar_indication_cb dfs_radar_indication_cb; + HAL_REG_CAPABILITIES reg_cap; + uint32_t scan_id; + struct wma_txrx_node *interfaces; + pdev_cli_config_t pdevconfig; + struct list_head vdev_resp_queue; + cdf_spinlock_t vdev_respq_lock; + cdf_list_t wma_hold_req_queue; + cdf_spinlock_t wma_hold_req_q_lock; + uint32_t ht_cap_info; +#ifdef WLAN_FEATURE_11AC + uint32_t vht_cap_info; + uint32_t vht_supp_mcs; +#endif + uint32_t num_rf_chains; +#if defined(QCA_WIFI_FTM) + struct utf_event_info utf_event_info; +#endif + uint8_t is_fw_assert; + struct wma_wow wow; + uint8_t no_of_suspend_ind; + uint8_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; + uint8_t powersave_mode; + bool ptrn_match_enable_all_vdev; + void *pGetRssiReq; + t_thermal_mgmt thermal_mgmt_info; + bool roam_offload_enabled; + t_wma_roam_preauth_chan_state_t roam_preauth_scan_state; + uint32_t roam_preauth_scan_id; + uint16_t roam_preauth_chanfreq; + void *roam_preauth_chan_context; + /* 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 + */ + uint8_t ol_ini_info; + bool ssdp; + uint8_t ibss_started; + tSetBssKeyParams ibsskey_info; + struct ieee80211com *dfs_ic; + +#ifdef FEATURE_WLAN_SCAN_PNO + cdf_wake_lock_t pno_wake_lock; +#endif +#ifdef FEATURE_WLAN_EXTSCAN + cdf_wake_lock_t extscan_wake_lock; +#endif + cdf_wake_lock_t wow_wake_lock; + int wow_nack; + cdf_atomic_t is_wow_bus_suspended; + cdf_mc_timer_t wma_scan_comp_timer; + uint8_t dfs_phyerr_filter_offload; + bool suitable_ap_hb_failure; + ibss_power_save_params wma_ibss_power_save_params; +#ifdef FEATURE_WLAN_RA_FILTERING + bool IsRArateLimitEnabled; + uint16_t RArateLimitInterval; +#endif +#ifdef WLAN_FEATURE_LPSS + bool is_lpass_enabled; +#endif +#ifdef WLAN_FEATURE_NAN + bool is_nan_enabled; +#endif + uint8_t staMaxLIModDtim; + uint8_t staModDtim; + uint8_t staDynamicDtim; + int32_t dfs_pri_multiplier; + uint32_t hw_bd_id; + uint32_t hw_bd_info[HW_BD_INFO_SIZE]; + uint32_t miracast_value; + cdf_mc_timer_t log_completion_timer; + wma_mgmt_frame_rx_callback mgmt_rx; + uint32_t num_dbs_hw_modes; + struct dbs_hw_mode_info hw_mode; + uint32_t old_hw_mode_index; + uint32_t new_hw_mode_index; + cdf_atomic_t scan_id_counter; + wma_peer_authorized_fp peer_authorized_cb; + 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; + + /* OCB request contexts */ + struct sir_ocb_config *ocb_config_req; + struct dual_mac_config dual_mac_cfg; + struct { + uint16_t pool_size; + uint16_t num_free; + union wmi_desc_elem_t *array; + union wmi_desc_elem_t *freelist; + cdf_spinlock_t wmi_desc_pool_lock; + } wmi_desc_pool; + uint8_t max_scan; + struct wmi_init_cmd saved_wmi_init_cmd; + cdf_event_t service_ready_ext_evt; + uint16_t self_gen_frm_pwr; + bool tx_chain_mask_cck; +} t_wma_handle, *tp_wma_handle; + +/** + * struct wma_target_cap - target capabality + * @wmi_service_bitmap: wmi services bitmap + * @wlan_resource_config: resource config + */ +struct wma_target_cap { + /* wmi services bitmap received from Target */ + uint32_t wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; + /* default resource config,the os shim can overwrite it */ + wmi_resource_config wlan_resource_config; +}; + +/** + * struct t_wma_start_req - wma start request parameters + * @pConfigBuffer: config buffer + * @usConfigBufferLen: Length of the config buffer above + * @driver_type: Production or FTM driver + * @pUserData: user data + * @pIndUserData: indication function pointer to send to UMAC + * + * The shared memory between WDI and HAL is 4K so maximum data can be + * transferred from WDI to HAL is 4K + */ +typedef struct { + void *pConfigBuffer; + uint16_t usConfigBufferLen; + t_wma_drv_type driver_type; + void *pUserData; + void *pIndUserData; +} t_wma_start_req; + +/* 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; + +/** + * struct sHalMacStartParameter - mac start request parameters + * @driverType: driver type (production/FTM) + * @uConfigBufferLen: length of config buffer + */ +typedef struct cdf_packed sHalMacStartParameter { + tDriverType driverType; + uint32_t 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; + +extern void cds_wma_complete_cback(void *p_cds_context); +extern void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, + uint16_t regdmn5G, int8_t ctl2G, + int8_t ctl5G); +void wma_get_modeselect(tp_wma_handle wma, uint32_t *modeSelect); + +/** + * enum frame_index - Frame index + * @GENERIC_NODOWNLD_NOACK_COMP_INDEX: Frame index for no download comp no ack + * @GENERIC_DOWNLD_COMP_NOACK_COMP_INDEX: Frame index for download comp no ack + * @GENERIC_DOWNLD_COMP_ACK_COMP_INDEX: Frame index for download comp and ack + * @GENERIC_NODOWLOAD_ACK_COMP_INDEX: Frame index for no download comp and ack + * @FRAME_INDEX_MAX: maximum 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 +}; + +/** + * struct wma_tx_ack_work_ctx - tx ack work context + * @wma_handle: wma handle + * @sub_type: sub type + * @status: status + * @ack_cmp_work: work structure + */ +struct wma_tx_ack_work_ctx { + tp_wma_handle wma_handle; + uint16_t sub_type; + int32_t status; + struct work_struct ack_cmp_work; +}; + +/** + * struct wma_target_req - target request parameters + * @event_timeout: event timeout + * @node: list + * @user_data: user data + * @msg_type: message type + * @vdev_id: vdev id + * @type: type + */ +struct wma_target_req { + cdf_mc_timer_t event_timeout; + cdf_list_node_t node; + void *user_data; + uint32_t msg_type; + uint8_t vdev_id; + uint8_t type; +}; + +/** + * struct wma_vdev_start_req - vdev start request parameters + * @beacon_intval: beacon interval + * @dtim_period: dtim period + * @max_txpow: max tx power + * @chan_offset: channel offset + * @is_dfs: is dfs supported or not + * @vdev_id: vdev id + * @chan: channel + * @oper_mode: operating mode + * @ssid: ssid + * @hidden_ssid: hidden ssid + * @pmf_enabled: is pmf enabled or not + * @vht_capable: VHT capabality + * @ht_capable: HT capabality + * @dfs_pri_multiplier: DFS multiplier + * @dot11_mode: 802.11 mode + * @is_half_rate: is the channel operating at 10MHz + * @is_quarter_rate: is the channel operating at 5MHz + * @preferred_tx_streams: policy manager indicates the preferred + * number of transmit streams + * @preferred_rx_streams: policy manager indicates the preferred + * number of receive streams + */ +struct wma_vdev_start_req { + uint32_t beacon_intval; + uint32_t dtim_period; + int32_t max_txpow; + phy_ch_width chan_width; + bool is_dfs; + uint8_t vdev_id; + uint8_t chan; + uint8_t oper_mode; + tSirMacSSid ssid; + uint8_t hidden_ssid; + uint8_t pmf_enabled; + uint8_t vht_capable; + uint8_t ch_center_freq_seg0; + uint8_t ch_center_freq_seg1; + uint8_t ht_capable; + int32_t dfs_pri_multiplier; + uint8_t dot11_mode; + bool is_half_rate; + bool is_quarter_rate; + uint32_t preferred_tx_streams; + uint32_t preferred_rx_streams; +}; + +/** + * struct wma_set_key_params - set key parameters + * @vdev_id: vdev id + * @def_key_idx: used to see if we have to read the key from cfg + * @key_len: key length + * @peer_mac: peer mac address + * @singl_tid_rc: 1=Single TID based Replay Count, 0=Per TID based RC + * @key_type: key type + * @key_idx: key index + * @unicast: unicast flag + * @key_data: key data + */ +struct wma_set_key_params { + uint8_t vdev_id; + /* def_key_idx can be used to see if we have to read the key from cfg */ + uint32_t def_key_idx; + uint16_t key_len; + uint8_t peer_mac[IEEE80211_ADDR_LEN]; + uint8_t singl_tid_rc; + enum eAniEdType key_type; + uint32_t key_idx; + bool unicast; + uint8_t key_data[SIR_MAC_MAX_KEY_LENGTH]; +}; + +/** + * struct t_thermal_cmd_params - thermal command parameters + * @minTemp: minimum temprature + * @maxTemp: maximum temprature + * @thermalEnable: thermal enable + */ +typedef struct { + uint16_t minTemp; + uint16_t maxTemp; + uint8_t thermalEnable; +} t_thermal_cmd_params, *tp_thermal_cmd_params; + +/** + * enum wma_cfg_cmd_id - wma cmd ids + * @WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID: txrx firmware stats enable command + * @WMA_VDEV_TXRX_FWSTATS_RESET_CMDID: txrx firmware stats reset command + * @WMA_VDEV_MCC_SET_TIME_LATENCY: set MCC latency time + * @WMA_VDEV_MCC_SET_TIME_QUOTA: set MCC time quota + * @WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE: set IBSS ATIM window size + * @WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED: set IBSS enable power save + * @WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED: set IBSS power collapse enable + * @WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX: awake IBSS on TX/RX + * @WMA_VDEV_IBSS_SET_INACTIVITY_TIME: set IBSS inactivity time + * @WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME: set IBSS TXSP + * @WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS: set IBSS power save warmup time + * @WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW: set IBSS power save ATIM + * @WMA_VDEV_DFS_CONTROL_CMDID: DFS control command + * @WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID: get IPA microcontroller fw stats + * + * wma command 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, + WMA_VDEV_MCC_SET_TIME_LATENCY, + WMA_VDEV_MCC_SET_TIME_QUOTA, + 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, + WMA_VDEV_DFS_CONTROL_CMDID, + WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID, + WMA_CMD_ID_MAX +}; + +/** + * struct wma_trigger_uapsd_params - trigger uapsd parameters + * @wmm_ac: wmm access catagory + * @user_priority: user priority + * @service_interval: service interval + * @suspend_interval: suspend interval + * @delay_interval: delay interval + */ +typedef struct wma_trigger_uapsd_params { + uint32_t wmm_ac; + uint32_t user_priority; + uint32_t service_interval; + uint32_t suspend_interval; + uint32_t delay_interval; +} t_wma_trigger_uapsd_params, *tp_wma_trigger_uapsd_params; + +/** + * enum uapsd_peer_param_max_sp - U-APSD maximum service period of peer station + * @UAPSD_MAX_SP_LEN_UNLIMITED: unlimited max service period + * @UAPSD_MAX_SP_LEN_2: max service period = 2 + * @UAPSD_MAX_SP_LEN_4: max service period = 4 + * @UAPSD_MAX_SP_LEN_6: max service period = 6 + */ +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 +}; + +/** + * enum uapsd_peer_param_enabled_ac - U-APSD Enabled AC's of peer station + * @UAPSD_VO_ENABLED: enable uapsd for voice + * @UAPSD_VI_ENABLED: enable uapsd for video + * @UAPSD_BK_ENABLED: enable uapsd for background + * @UAPSD_BE_ENABLED: enable uapsd for best effort + */ +enum uapsd_peer_param_enabled_ac { + UAPSD_VO_ENABLED = 0x01, + UAPSD_VI_ENABLED = 0x02, + UAPSD_BK_ENABLED = 0x04, + UAPSD_BE_ENABLED = 0x08 +}; + +/** + * struct p2p_ie - P2P IE structural definition. + * @p2p_id: p2p id + * @p2p_len: p2p length + * @p2p_oui: p2p OUI + * @p2p_oui_type: p2p OUI type + */ +struct p2p_ie { + uint8_t p2p_id; + uint8_t p2p_len; + uint8_t p2p_oui[3]; + uint8_t p2p_oui_type; +} __packed; + +/** + * struct p2p_noa_descriptor - noa descriptor + * @type_count: 255: continuous schedule, 0: reserved + * @duration: Absent period duration in micro seconds + * @interval: Absent period interval in micro seconds + * @start_time: 32 bit tsf time when in starts + */ +struct p2p_noa_descriptor { + uint8_t type_count; + uint32_t duration; + uint32_t interval; + uint32_t start_time; +} __packed; + +/** + * struct p2p_sub_element_noa - p2p noa element + * @p2p_sub_id: p2p sub id + * @p2p_sub_len: p2p sub length + * @index: identifies instance of NOA su element + * @oppPS: oppPS state of the AP + * @ctwindow: ctwindow in TUs + * @num_descriptors: number of NOA descriptors + * @noa_descriptors: noa descriptors + */ +struct p2p_sub_element_noa { + uint8_t p2p_sub_id; + uint8_t p2p_sub_len; + uint8_t index; /* identifies instance of NOA su element */ + uint8_t oppPS:1, /* oppPS state of the AP */ + ctwindow:7; /* ctwindow in TUs */ + uint8_t num_descriptors; /* number of NOA descriptors */ + struct p2p_noa_descriptor noa_descriptors[WMA_MAX_NOA_DESCRIPTORS]; +}; + +/** + * struct wma_decap_info_t - decapsulation info + * @hdr: header + * @hdr_len: header length + */ +struct wma_decap_info_t { + uint8_t hdr[sizeof(struct ieee80211_qosframe_addr4)]; + int32_t hdr_len; +}; + +/** + * enum packet_power_save - packet power save params + * @WMI_VDEV_PPS_PAID_MATCH: paid match param + * @WMI_VDEV_PPS_GID_MATCH: gid match param + * @WMI_VDEV_PPS_EARLY_TIM_CLEAR: early tim clear param + * @WMI_VDEV_PPS_EARLY_DTIM_CLEAR: early dtim clear param + * @WMI_VDEV_PPS_EOF_PAD_DELIM: eof pad delim param + * @WMI_VDEV_PPS_MACADDR_MISMATCH: macaddr mismatch param + * @WMI_VDEV_PPS_DELIM_CRC_FAIL: delim CRC fail param + * @WMI_VDEV_PPS_GID_NSTS_ZERO: gid nsts zero param + * @WMI_VDEV_PPS_RSSI_CHECK: RSSI check param + * @WMI_VDEV_PPS_5G_EBT: 5G ebt param + */ +typedef enum { + 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; + +/** + * enum green_tx_param - green tx parameters + * @WMI_VDEV_PARAM_GTX_HT_MCS: ht mcs param + * @WMI_VDEV_PARAM_GTX_VHT_MCS: vht mcs param + * @WMI_VDEV_PARAM_GTX_USR_CFG: user cfg param + * @WMI_VDEV_PARAM_GTX_THRE: thre param + * @WMI_VDEV_PARAM_GTX_MARGIN: green tx margin param + * @WMI_VDEV_PARAM_GTX_STEP: green tx step param + * @WMI_VDEV_PARAM_GTX_MINTPC: mintpc param + * @WMI_VDEV_PARAM_GTX_BW_MASK: bandwidth mask + */ +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; + +#ifdef FEATURE_WLAN_TDLS +/** + * struct wma_tdls_params - TDLS parameters + * @vdev_id: vdev id + * @tdls_state: TDLS state + * @notification_interval_ms: notification inerval + * @tx_discovery_threshold: tx discovery threshold + * @tx_teardown_threshold: tx teardown threashold + * @rssi_teardown_threshold: RSSI teardown threshold + * @rssi_delta: RSSI delta + * @tdls_options: TDLS options + * @peer_traffic_ind_window: raffic indication window + * @peer_traffic_response_timeout: traffic response timeout + * @puapsd_mask: uapsd mask + * @puapsd_inactivity_time: uapsd inactivity time + * @puapsd_rx_frame_threshold: uapsd rx frame threshold + */ +typedef struct wma_tdls_params { + uint32_t vdev_id; + uint32_t tdls_state; + uint32_t notification_interval_ms; + uint32_t tx_discovery_threshold; + uint32_t tx_teardown_threshold; + int32_t rssi_teardown_threshold; + int32_t rssi_delta; + uint32_t tdls_options; + uint32_t peer_traffic_ind_window; + uint32_t peer_traffic_response_timeout; + uint32_t puapsd_mask; + uint32_t puapsd_inactivity_time; + uint32_t puapsd_rx_frame_threshold; +} t_wma_tdls_params; + +/** + * struct wma_tdls_peer_event - TDLS peer event + * @vdev_id: vdev id + * @peer_macaddr: peer MAC address + * @peer_status: TDLS peer status + * @peer_reason: TDLS peer reason + */ +typedef struct { + A_UINT32 vdev_id; + wmi_mac_addr peer_macaddr; + A_UINT32 peer_status; + A_UINT32 peer_reason; +} wma_tdls_peer_event; + +#endif /* FEATURE_WLAN_TDLS */ + +/** + * struct wma_dfs_radar_channel_list - dfs radar channel list + * @nchannels: nuber of channels + * @channels: Channel number including bonded channels on which + * radar is present + */ +struct wma_dfs_radar_channel_list { + A_UINT32 nchannels; + uint8_t channels[WMA_DFS_MAX_20M_SUB_CH]; +}; + +/** + * struct wma_dfs_radar_indication - Structure to indicate RADAR + * @vdev_id: vdev id + * @chan_list: Channel list on which RADAR is detected + * @dfs_radar_status: Flag to Indicate RADAR presence on the current channel + * @use_nol: Flag to indicate use NOL + */ +struct wma_dfs_radar_indication { + A_UINT32 vdev_id; + struct wma_dfs_radar_channel_list chan_list; + uint32_t dfs_radar_status; + int use_nol; +}; + +/** + * enum uapsd_ac - U-APSD Access Categories + * @UAPSD_BE: best effort + * @UAPSD_BK: back ground + * @UAPSD_VI: video + * @UAPSD_VO: voice + */ +enum uapsd_ac { + UAPSD_BE, + UAPSD_BK, + UAPSD_VI, + UAPSD_VO +}; + +CDF_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle, + uint32_t vdev_id, enum uapsd_ac ac); + +/** + * enum uapsd_up - U-APSD User Priorities + * @UAPSD_UP_BE: best effort + * @UAPSD_UP_BK: back ground + * @UAPSD_UP_RESV: reserve + * @UAPSD_UP_EE: Excellent Effort + * @UAPSD_UP_CL: Critical Applications + * @UAPSD_UP_VI: video + * @UAPSD_UP_VO: voice + * @UAPSD_UP_NC: Network Control + */ +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 +}; + +/** + * struct wma_unit_test_cmd - unit test command parameters + * @vdev_id: vdev id + * @module_id: module id + * @num_args: number of arguments + * @args: arguments + */ +typedef struct wma_unit_test_cmd { + uint32_t vdev_id; + WLAN_MODULE_ID module_id; + uint32_t num_args; + uint32_t args[WMA_MAX_NUM_ARGS]; +} t_wma_unit_test_cmd; + +/** + * struct wma_roam_invoke_cmd - roam invoke command + * @vdev_id: vdev id + * @bssid: mac address + * @channel: channel + */ +struct wma_roam_invoke_cmd { + uint32_t vdev_id; + uint8_t bssid[IEEE80211_ADDR_LEN]; + uint32_t channel; +}; + +/** + * struct wma_process_fw_event_params - fw event parameters + * @wmi_handle: wmi handle + * @evt_buf: event buffer + */ +typedef struct { + void *wmi_handle; + void *evt_buf; +} wma_process_fw_event_params; + +int wma_process_fw_event_handler(struct wmi_unified *wmi_handle, + wmi_buf_t evt_buf); + +A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype, + eCsrEncryptionType encr); +A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr); + +/* + * WMA-DFS Hooks + */ +int ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info); +uint64_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, uint32_t flags); +int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe); +uint32_t ieee80211_ieee2mhz(uint32_t chan, uint32_t flags); +int ol_if_dfs_get_ext_busy(struct ieee80211com *ic); +int ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + uint32_t *rxc_pcnt, uint32_t *rxf_pcnt, + uint32_t *txf_pcnt); +uint16_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); +uint16_t dfs_usenol(struct ieee80211com *ic); + +CDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_t vdev_id, + tp_wma_trigger_uapsd_params + trigger_uapsd_params); + +/* added to get average snr for both data and beacon */ +CDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle, void *pGetRssiReq); + + +CDF_STATUS wma_update_vdev_tbl(tp_wma_handle wma_handle, uint8_t vdev_id, + ol_txrx_vdev_handle tx_rx_vdev_handle, + uint8_t *mac, uint32_t vdev_type, bool add_del); + +void wma_send_flush_logs_to_fw(tp_wma_handle wma_handle); +void wma_log_completion_timeout(void *data); + +CDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma, + struct rssi_monitor_req *req); + +CDF_STATUS wma_send_soc_set_pcl_cmd(tp_wma_handle wma_handle, + struct sir_pcl_list *msg); + +CDF_STATUS wma_send_soc_set_hw_mode_cmd(tp_wma_handle wma_handle, + struct sir_hw_mode *msg); +CDF_STATUS wma_get_scan_id(uint32_t *scan_id); + +CDF_STATUS wma_send_soc_set_dual_mac_config(tp_wma_handle wma_handle, + struct sir_dual_mac_config *msg); +int wma_crash_inject(tp_wma_handle wma_handle, uint32_t type, + uint32_t delay_time_ms); + +struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, + uint8_t vdev_id, + uint32_t msg_type, uint8_t type, + void *params, uint32_t timeout); +struct wma_target_req *wma_fill_hold_req(tp_wma_handle wma, + uint8_t vdev_id, uint32_t msg_type, + uint8_t type, void *params, + uint32_t timeout); + +CDF_STATUS wma_vdev_start(tp_wma_handle wma, + struct wma_vdev_start_req *req, bool isRestart); + +void wma_remove_vdev_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type); + +int wmi_desc_pool_init(tp_wma_handle wma_handle, uint32_t pool_size); +void wmi_desc_pool_deinit(tp_wma_handle wma_handle); +struct wmi_desc_t *wmi_desc_get(tp_wma_handle wma_handle); +void wmi_desc_put(tp_wma_handle wma_handle, struct wmi_desc_t *wmi_desc); +int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params, + uint32_t len); +void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region); + +#if defined(FEATURE_LRO) +CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle, + struct wma_lro_config_cmd_t *wma_lro_cmd); +#else +static inline CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle, + struct wma_lro_config_cmd_t *wma_lro_cmd) +{ + return CDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h new file mode 100644 index 000000000000..ad78989f38ea --- /dev/null +++ b/core/wma/inc/wma_api.h @@ -0,0 +1,220 @@ +/* + * 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 WMA_API_H +#define WMA_API_H + +#include "osdep.h" +#include "cds_mq.h" +#include "ani_global.h" +#include "a_types.h" +#include "wmi_unified.h" +#ifdef NOT_YET +#include "htc_api.h" +#endif +#include "lim_global.h" + +typedef void *WMA_HANDLE; + +/** + * enum GEN_PARAM - general parameters + * @GEN_VDEV_PARAM_AMPDU: Set ampdu size + * @GEN_VDEV_PARAM_AMSDU: Set amsdu size + * @GEN_PARAM_DUMP_AGC_START: dump agc start + * @GEN_PARAM_DUMP_AGC: dump agc + * @GEN_PARAM_DUMP_CHANINFO_START: dump channel info start + * @GEN_PARAM_DUMP_CHANINFO: dump channel info + * @GEN_PARAM_CRASH_INJECT: inject crash + * @GEN_PARAM_DUMP_PCIE_ACCESS_LOG: dump pcie access log + * @GEN_PARAM_TX_CHAIN_MASK_CCK: cck tx chain mask + */ +typedef enum { + GEN_VDEV_PARAM_AMPDU = 0x1, + 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; + +#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 + +typedef void (*wma_peer_authorized_fp) (uint32_t vdev_id); + + +CDF_STATUS wma_pre_start(void *cds_context); + +CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg); + +CDF_STATUS wma_start(void *cds_context); + +CDF_STATUS wma_stop(void *cds_context, uint8_t reason); + +CDF_STATUS wma_close(void *cds_context); + +CDF_STATUS wma_wmi_service_close(void *cds_context); + +void wma_rx_ready_event(WMA_HANDLE handle, void *ev); + +void wma_rx_service_ready_event(WMA_HANDLE handle, void *ev); + +void wma_rx_service_ready_ext_event(WMA_HANDLE handle, void *ev); + +void wma_setneedshutdown(void *cds_context); + +bool wma_needshutdown(void *cds_context); + +CDF_STATUS wma_wait_for_ready_event(WMA_HANDLE handle); + +uint8_t wma_map_channel(uint8_t mapChannel); + +int wma_cli_get_command(int vdev_id, int param_id, int vpdev); +int wma_cli_set_command(int vdev_id, int param_id, int sval, int vpdev); +int wma_cli_set2_command(int vdev_id, int param_id, int sval1, + int sval2, int vpdev); + +CDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value); +CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); + +CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx, + uint8_t *pVersion, + uint32_t versionBufferSize); +int wma_bus_suspend(void); +int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); +void wma_target_suspend_acknowledge(void *context); +int wma_bus_resume(void); +int wma_resume_target(WMA_HANDLE handle); +CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle); +CDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle); +int wma_is_wow_mode_selected(WMA_HANDLE handle); +CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle); +CDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle); +bool wma_check_scan_in_progress(WMA_HANDLE handle); +void wma_set_peer_authorized_cb(void *wma_ctx, wma_peer_authorized_fp auth_cb); +int wma_set_peer_param(void *wma_ctx, uint8_t *peer_addr, uint32_t param_id, + uint32_t param_value, uint32_t vdev_id); +#ifdef NOT_YET +CDF_STATUS wma_update_channel_list(WMA_HANDLE handle, void *scan_chan_info); +#endif + +uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id); +struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id); +bool wma_is_vdev_up(uint8_t vdev_id); + +void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size); + +uint8_t wma_get_fw_wlan_feat_caps(uint8_t featEnumValue); +tSirRetStatus wma_post_ctrl_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +void wma_enable_disable_wakeup_event(WMA_HANDLE handle, + uint32_t vdev_id, + uint32_t bitmap, + bool enable); +void wma_register_wow_wakeup_events(WMA_HANDLE handle, uint8_t vdev_id, + uint8_t vdev_type, uint8_t sub_type); +void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id); +int8_t wma_get_hw_mode_idx_from_dbs_hw_list(enum hw_mode_ss_config mac0_ss, + enum hw_mode_bandwidth mac0_bw, + enum hw_mode_ss_config mac1_ss, + enum hw_mode_bandwidth mac1_bw, + enum hw_mode_dbs_capab dbs, + enum hw_mode_agile_dfs_capab dfs); +CDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx, + struct sir_hw_mode_params *hw_mode); +int8_t wma_get_num_dbs_hw_modes(void); +bool wma_is_hw_dbs_capable(void); +bool wma_is_hw_agile_dfs_capable(void); +int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id); +void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id, + uint32_t cfgd_hw_mode_index); +CDF_STATUS wma_get_old_and_new_hw_index(uint32_t *old_hw_mode_index, + uint32_t *new_hw_mode_index); +void wma_set_dbs_capability_ut(uint32_t dbs); +CDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs); +CDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode); +bool wma_is_dbs_enable(void); +bool wma_is_agile_dfs_enable(void); +CDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config, + bool dbs_scan, + bool dbs_plus_agile_scan, + bool single_mac_scan_with_dfs); +CDF_STATUS wma_get_updated_fw_mode_config(uint32_t *fw_mode_config, + bool dbs, + bool agile_dfs); +bool wma_get_dbs_scan_config(void); +bool wma_get_dbs_plus_agile_scan_config(void); +bool wma_get_single_mac_scan_with_dfs_config(void); +bool wma_get_dbs_config(void); +bool wma_get_agile_dfs_config(void); +bool wma_is_dual_mac_disabled_in_ini(void); +bool wma_get_prev_dbs_config(void); +bool wma_get_prev_agile_dfs_config(void); +bool wma_get_prev_dbs_scan_config(void); +bool wma_get_prev_dbs_plus_agile_scan_config(void); +bool wma_get_prev_single_mac_scan_with_dfs_config(void); + +#define LRO_IPV4_SEED_ARR_SZ 5 +#define LRO_IPV6_SEED_ARR_SZ 11 + +/** + * struct wma_lro_init_cmd_t - set LRO init parameters + * @lro_enable: indicates whether lro is enabled + * @tcp_flag: If the TCP flags from the packet do not match + * the values in this field after masking with TCP flags mask + * below, packet is not LRO eligible + * @tcp_flag_mask: field for comparing the TCP values provided + * above with the TCP flags field in the received packet + * @toeplitz_hash_ipv4: contains seed needed to compute the flow id + * 5-tuple toeplitz hash for ipv4 packets + * @toeplitz_hash_ipv6: contains seed needed to compute the flow id + * 5-tuple toeplitz hash for ipv6 packets + */ +struct wma_lro_config_cmd_t { + uint32_t lro_enable; + uint32_t tcp_flag:9, + tcp_flag_mask:9; + uint32_t toeplitz_hash_ipv4[LRO_IPV4_SEED_ARR_SZ]; + uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ]; +}; + +#if defined(FEATURE_LRO) +int wma_lro_init(struct wma_lro_config_cmd_t *lro_config); +#endif +bool wma_is_scan_simultaneous_capable(void); +#endif diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h new file mode 100644 index 000000000000..4bfc3fccad15 --- /dev/null +++ b/core/wma/inc/wma_dfs_interface.h @@ -0,0 +1,252 @@ +/* + * 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. + */ + +#include "ath_dfs_structs.h" +#include +#include "cds_ieee80211_common.h" + +#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 - channel info + * @ic_freq: frequency in MHz + * @ic_flags: channel flags + * @ic_flagext: flags extension + * @ic_ieee: IEEE channel number + * @ic_maxregpower: max regulatory power in dbm + * @ic_maxpower: max tx power in dbm + * @ic_minpower: min tx power in dbm + * @ic_regClassId: reg class id of this channel + * @ic_antennamax: max antenna gain from regulatory + * @ic_vhtop_ch_freq_seg1: channel center frequency + * @ic_vhtop_ch_freq_seg2: Channel Center frequency applicable + * @ic_pri_freq_center_freq_mhz_separation: separation b/w pri and center freq + */ +struct ieee80211_channel { + uint32_t ic_freq; + uint32_t ic_flags; + uint8_t ic_flagext; + uint8_t ic_ieee; + int8_t ic_maxregpower; + int8_t ic_maxpower; + int8_t ic_minpower; + uint8_t ic_regClassId; + uint8_t ic_antennamax; + uint32_t ic_vhtop_ch_freq_seg1; + uint32_t ic_vhtop_ch_freq_seg2; + int ic_pri_freq_center_freq_mhz_separation; +}; + +/** + * struct ieee80211_channel_list - channel list + * @cl_nchans: number of channels + * @cl_channels: channel info + */ +struct ieee80211_channel_list { + int cl_nchans; + struct ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH]; +}; + +/** + * struct ieee80211_dfs_state - dfs state + * @nol_event: nol event list + * @nol_timer: nol list processing + * @cac_timer: cac timer + * @cureps: current events/second + * @lastchan: chan w/ last radar event + * @newchan: chan selected next + * @cac_timeout_override: overridden cac timeout + * @flags: dfs flags + */ +struct ieee80211_dfs_state { + int nol_event[IEEE80211_CHAN_MAX]; + os_timer_t nol_timer; + os_timer_t cac_timer; + int cureps; + const struct ieee80211_channel *lastchan; + struct ieee80211_channel *newchan; + int cac_timeout_override; + uint8_t enable : 1, cac_timer_running : 1, ignore_dfs : 1, ignore_cac : 1; +}; + +/** + * struct ieee80211com - per device structure + * @ic_opmode: operation mode + * @ic_channels: ieee80211 channel list + * @ic_nchans: number of channels + * @ic_curchan: current channel + * @ic_isdfsregdomain: is opearting in dfs region + * @current_dfs_regdomain: current dfs regulatory domain + * @vdev_id: vdev id + * @last_radar_found_chan: last radar found channel + * @dfs_pri_multiplier: dfs multiplier + */ +typedef struct ieee80211com { + void (*ic_start_csa)(struct ieee80211com *ic, uint8_t ieeeChan); + void (*ic_get_ext_chan_info)(struct ieee80211com *ic, + struct ieee80211_channel_list *chan); + enum ieee80211_opmode ic_opmode; + struct ieee80211_channel *(*ic_find_channel)(struct ieee80211com *ic, + int freq, uint32_t flags); + uint64_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]; + int ic_nchans; + struct ieee80211_channel *ic_curchan; + uint8_t ic_isdfsregdomain; + int (*ic_get_dfsdomain)(struct ieee80211com *); + uint16_t (*ic_dfs_usenol)(struct ieee80211com *ic); + uint16_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, + uint32_t *rxc_pcnt, + uint32_t *rxf_pcnt, + uint32_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, uint32_t insize, + void *outdata, uint32_t *outsize); + HAL_DFS_DOMAIN current_dfs_regdomain; + uint8_t vdev_id; + uint8_t last_radar_found_chan; + int32_t dfs_pri_multiplier; + cdf_mutex_t chan_lock; +} IEEE80211COM, *PIEEE80211COM; + +/** + * ieee80211_chan2freq() - Convert channel to frequency value. + * @ic: ieee80211com ptr + * @c: ieee80211 channel + * + * Return: freqency in MHz + */ +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/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h new file mode 100644 index 000000000000..75c50f84ee03 --- /dev/null +++ b/core/wma/inc/wma_if.h @@ -0,0 +1,1429 @@ +/* + * 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 "cdf_types.h" +#include "sir_api.h" +#include "sir_params.h" + + +/* + * 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 + + +#define WMA_CONFIG_PARAM_UPDATE_REQ SIR_CFG_PARAM_UPDATE_IND + +#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 +/* Special station id for transmitting broadcast frames. */ +#define STA_ENTRY_BCAST 3 +#define STA_ENTRY_PEER STA_ENTRY_OTHER +#ifdef FEATURE_WLAN_TDLS +#define STA_ENTRY_TDLS_PEER 4 +#endif /* FEATURE_WLAN_TDLS */ + +#define STA_INVALID_IDX 0xFF + +/* invalid channel id. */ +#define INVALID_CHANNEL_ID 0 + +/* + * 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 ENC_POLICY_NULL 0 +#define ENC_POLICY_WEP40 1 +#define ENC_POLICY_WEP104 2 +#define ENC_POLICY_TKIP 3 +#define ENC_POLICY_AES_CCM 4 + +/* 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) + + +#define HAL_MAX_SUPP_CHANNELS 128 +#define HAL_MAX_SUPP_OPER_CLASSES 32 + +/** + * enum eFrameType - frame types + * @TXRX_FRM_RAW: raw frame + * @TXRX_FRM_ETH2: ethernet frame + * @TXRX_FRM_802_3: 802.3 frame + * @TXRX_FRM_802_11_MGMT: 802.11 mgmt frame + * @TXRX_FRM_802_11_CTRL: 802.11 control frame + * @TXRX_FRM_802_11_DATA: 802.11 data frame + */ +typedef enum { + TXRX_FRM_RAW, + TXRX_FRM_ETH2, + TXRX_FRM_802_3, + TXRX_FRM_802_11_MGMT, + TXRX_FRM_802_11_CTRL, + TXRX_FRM_802_11_DATA, + TXRX_FRM_IGNORED, /* This frame will be dropped */ + TXRX_FRM_MAX +} eFrameType; + +/** + * enum eFrameTxDir - frame tx direction + * @ANI_TXDIR_IBSS: IBSS frame + * @ANI_TXDIR_TODS: frame to DS + * @ANI_TXDIR_FROMDS: Frame from DS + * @ANI_TXDIR_WDS: WDS frame + */ +typedef enum { + ANI_TXDIR_IBSS = 0, + ANI_TXDIR_TODS, + ANI_TXDIR_FROMDS, + ANI_TXDIR_WDS +} eFrameTxDir; + +/** + *struct sAniBeaconStruct - Beacon structure + * @beaconLength: beacon length + * @macHdr: mac header for beacon + */ +typedef struct sAniBeaconStruct { + uint32_t beaconLength; + tSirMacMgmtHdr macHdr; +} cdf_packed tAniBeaconStruct, *tpAniBeaconStruct; + +/** + * struct sAniProbeRspStruct - probeRsp template structure + * @macHdr: mac header for probe response + */ +typedef struct sAniProbeRspStruct { + tSirMacMgmtHdr macHdr; + /* probeRsp body follows here */ +} cdf_packed tAniProbeRspStruct, *tpAniProbeRspStruct; + +/** + * struct tAddStaParams - add sta related parameters + * @bssId: bssid of sta + * @assocId: associd + * @staType: 0 - Self, 1 other/remote, 2 - bssid + * @staMac: MAC Address of STA + * @shortPreambleSupported: is short preamble supported or not + * @listenInterval: Listen interval + * @wmmEnabled: Support for 11e/WMM + * @uAPSD: U-APSD Flags: 1b per AC + * @maxSPLen: Max SP Length + * @htCapable: 11n HT capable STA + * @greenFieldCapable: 11n Green Field preamble support + * @txChannelWidthSet: TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz + * @mimoPS: MIMO Power Save + * @rifsMode: RIFS mode: 0 - NA, 1 - Allowed + * @lsigTxopProtection: L-SIG TXOP Protection mechanism + * @us32MaxAmpduDuration: in units of 32 us + * @maxAmpduSize: 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k + * @maxAmpduDensity: 3 : 0~7 : 2^(11nAMPDUdensity -4) + * @maxAmsduSize: 1 : 3839 bytes, 0 : 7935 bytes + * @fDsssCckMode40Mhz: DSSS CCK supported 40MHz + * @fShortGI40Mhz: short GI support for 40Mhz packets + * @fShortGI20Mhz: short GI support for 20Mhz packets + * @supportedRates: legacy supported rates + * @status: CDF status + * @staIdx: station index + * @bssIdx: BSSID of BSS to which the station is associated + * @updateSta: pdate the existing STA entry, if this flag is set + * @respReqd: A flag to indicate to HAL if the response message is required + * @rmfEnabled: Robust Management Frame (RMF) enabled/disabled + * @encryptType: The unicast encryption type in the association + * @ucUcastSig: Unicast DPU index + * @ucBcastSig: Broadcast DPU index + * @sessionId: PE session id + * @p2pCapableSta: if this is a P2P Capable Sta + * @csaOffloadEnable: CSA offload enable flag + * @vhtCapable: is VHT capabale or not + * @vhtTxChannelWidthSet: VHT channel width + * @vhtSupportedRxNss: VHT supported RX NSS + * @vhtTxBFCapable: txbf capable or not + * @vhtTxMUBformeeCapable: Bformee capable or not + * @enableVhtpAid: enable VHT AID + * @enableVhtGid: enable VHT GID + * @enableAmpduPs: AMPDU power save + * @enableHtSmps: enable HT SMPS + * @htSmpsconfig: HT SMPS config + * @htLdpcCapable: HT LDPC capable + * @vhtLdpcCapable: VHT LDPC capable + * @smesessionId: sme session id + * @wpa_rsn: RSN capable + * @capab_info: capabality info + * @ht_caps: HT capabalities + * @vht_caps: VHT vapabalities + * @nwType: NW Type + * @maxTxPower: max tx power + * @atimIePresent: Peer Atim Info + * @peerAtimWindowLength: peer ATIM Window length + * + * This structure contains parameter required for + * add sta request of upper layer. + */ +typedef struct { + tSirMacAddr bssId; + uint16_t 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. + */ + uint8_t staType; + uint8_t shortPreambleSupported; + tSirMacAddr staMac; + uint16_t listenInterval; + uint8_t wmmEnabled; + uint8_t uAPSD; + uint8_t maxSPLen; + uint8_t htCapable; + /* 11n Green Field preamble support + * 0 - Not supported, 1 - Supported + * Add it to RA related fields of sta entry in HAL + */ + uint8_t greenFieldCapable; + uint8_t ch_width; + + tSirMacHTMIMOPowerSaveState mimoPS; + uint8_t rifsMode; + /* L-SIG TXOP Protection mechanism + * 0 - No Support, 1 - Supported + * SG - there is global field. + */ + uint8_t lsigTxopProtection; + uint8_t us32MaxAmpduDuration; + uint8_t maxAmpduSize; + uint8_t maxAmpduDensity; + uint8_t maxAmsduSize; + + /* 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. + */ + uint8_t fDsssCckMode40Mhz; + uint8_t fShortGI40Mhz; + uint8_t fShortGI20Mhz; + 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 */ + CDF_STATUS status; + /* Station index; valid only when 'status' field value is + * CDF_STATUS_SUCCESS + */ + uint8_t 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. + */ + uint8_t bssIdx; + uint8_t updateSta; + uint8_t respReqd; + uint8_t rmfEnabled; + uint32_t encryptType; + uint8_t ucUcastSig; + uint8_t ucBcastSig; + uint8_t sessionId; + uint8_t p2pCapableSta; + uint8_t csaOffloadEnable; + uint8_t vhtCapable; + uint8_t vhtSupportedRxNss; + uint8_t vhtTxBFCapable; + uint8_t enable_su_tx_bformer; + uint8_t vhtTxMUBformeeCapable; + uint8_t enableVhtpAid; + uint8_t enableVhtGid; + uint8_t enableAmpduPs; + uint8_t enableHtSmps; + uint8_t htSmpsconfig; + uint8_t htLdpcCapable; + uint8_t vhtLdpcCapable; + uint8_t smesessionId; + uint8_t wpa_rsn; + uint16_t capab_info; + uint16_t ht_caps; + uint32_t vht_caps; + tSirNwType nwType; + tPowerdBm maxTxPower; + uint8_t atimIePresent; + uint32_t peerAtimWindowLength; + uint8_t nonRoamReassoc; +} tAddStaParams, *tpAddStaParams; + +/** + * struct tDeleteStaParams - parameters required for del sta request + * @staIdx: station index + * @assocId: association index + * @status: status + * @respReqd: is response required + * @sessionId: PE session id + * @smesessionId: SME session id + * @staType: station type + * @staMac: station mac + */ +typedef struct { + uint16_t staIdx; + uint16_t assocId; + CDF_STATUS status; + uint8_t respReqd; + uint8_t sessionId; + uint8_t smesessionId; + uint8_t staType; + tSirMacAddr staMac; +} tDeleteStaParams, *tpDeleteStaParams; + +/** + * struct tSetStaKeyParams - set key params + * @staIdx: station id + * @encType: encryption type + * @wepType: WEP type + * @defWEPIdx: Default WEP key, valid only for static WEP, must between 0 and 3 + * @key: valid only for non-static WEP encyrptions + * @singleTidRc: 1=Single TID based Replay Count, 0=Per TID based RC + * @smesessionId: sme session id + * @peerMacAddr: peer mac address + * @status: status + * @sessionId: session id + * @sendRsp: send response + * + * 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 { + uint16_t staIdx; + tAniEdType encType; + tAniWepType wepType; + uint8_t defWEPIdx; + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; + uint8_t singleTidRc; + uint8_t smesessionId; + tSirMacAddr peerMacAddr; + CDF_STATUS status; + uint8_t sessionId; + uint8_t sendRsp; +} tSetStaKeyParams, *tpSetStaKeyParams; + +/** + * struct sLimMlmSetKeysReq - set key request parameters + * @peerMacAddr: peer mac address + * @sessionId: PE session id + * @smesessionId: SME session id + * @aid: association id + * @edType: Encryption/Decryption type + * @numKeys: number of keys + * @key: key data + */ +typedef struct sLimMlmSetKeysReq { + tSirMacAddr peerMacAddr; + uint8_t sessionId; /* Added For BT-AMP Support */ + uint8_t smesessionId; /* Added for drivers based on wmi interface */ + uint16_t aid; + tAniEdType edType; /* Encryption/Decryption type */ + uint8_t numKeys; + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; +} tLimMlmSetKeysReq, *tpLimMlmSetKeysReq; + +/** + * struct tAddBssParams - parameters required for add bss params + * @bssId: MAC Address/BSSID + * @selfMacAddr: Self Mac Address + * @bssType: BSS type + * @operMode: AP - 0; STA - 1; + * @nwType: network type + * @shortSlotTimeSupported: is short slot time supported or not + * @llaCoexist: is 11a coexist or not + * @llbCoexist: 11b coexist supported or not + * @llgCoexist: 11g coexist supported or not + * @ht20Coexist: HT20 coexist supported or not + * @fLsigTXOPProtectionFullSupport: TXOP protection supported or not + * @fRIFSMode: RIFS is supported or not + * @beaconInterval: beacon interval + * @dtimPeriod: DTIM period + * @cfParamSet: CF Param Set + * @rateSet: MAC Rate Set + * @htCapable: Enable/Disable HT capabilities + * @obssProtEnabled: Enable/Disable OBSS protection + * @rmfEnabled: RMF enabled/disabled + * @htOperMode: HT Operating Mode + * @HT Operating Mode: Dual CTS Protection: 0 - Unused, 1 - Used + * @txChannelWidthSet: TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz + * @currentOperChannel: Current Operating Channel + * @currentExtChannel: Current Extension Channel, if applicable + * @staContext: sta context + * @status: status + * @bssIdx: BSS index allocated by HAL + * @updateBss: update the existing BSS entry, if this flag is set + * @ssId: Add BSSID info for rxp filter + * @respReqd: send the response message to LIM only when this flag is set + * @sessionId: PE session id + * @txMgmtPower: tx power used for mgmt frames + * @maxTxPower: max power to be used after applying the power constraint + * @extSetStaKeyParamValid: Ext Bss Config Msg if set + * @extSetStaKeyParam: SetStaKeyParams for ext bss msg + * @ucMaxProbeRespRetryLimit: probe Response Max retries + * @bHiddenSSIDEn: To Enable Hidden ssid. + * @bProxyProbeRespEn: To Enable Disable FW Proxy Probe Resp + * @halPersona: Persona for the BSS can be STA,AP,GO,CLIENT value + * @bSpectrumMgtEnabled: Spectrum Management Capability, 1:Enabled, 0:Disabled. + * @vhtCapable: VHT capablity + * @vhtTxChannelWidthSet: VHT tx channel width + * @reassocReq: Set only during roaming reassociation + * @chainMask: chain mask + * @smpsMode: SMPS mode + * @dot11_mode: 802.11 mode + */ +typedef struct { + tSirMacAddr bssId; +#ifdef HAL_SELF_STA_PER_BSS + tSirMacAddr selfMacAddr; +#endif /* HAL_SELF_STA_PER_BSS */ + tSirBssType bssType; + uint8_t operMode; + tSirNwType nwType; + uint8_t shortSlotTimeSupported; + uint8_t llaCoexist; + uint8_t llbCoexist; + uint8_t llgCoexist; + uint8_t ht20Coexist; + uint8_t llnNonGFCoexist; + uint8_t fLsigTXOPProtectionFullSupport; + uint8_t fRIFSMode; + tSirMacBeaconInterval beaconInterval; + uint8_t dtimPeriod; + tSirMacCfParamSet cfParamSet; + tSirMacRateSet rateSet; + uint8_t htCapable; + uint8_t obssProtEnabled; + uint8_t rmfEnabled; + tSirMacHTOperatingMode htOperMode; + uint8_t dualCTSProtection; + uint8_t txChannelWidthSet; + uint8_t currentOperChannel; + tAddStaParams staContext; + CDF_STATUS status; + uint16_t bssIdx; + /* 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. + */ + uint8_t updateBss; + tSirMacSSid ssId; + uint8_t respReqd; + uint8_t sessionId; +#if defined WLAN_FEATURE_VOWIFI + tPowerdBm txMgmtPower; + tPowerdBm maxTxPower; +#endif /* WLAN_FEATURE_VOWIFI */ + +#if defined WLAN_FEATURE_VOWIFI_11R + uint8_t extSetStaKeyParamValid; + tSetStaKeyParams extSetStaKeyParam; +#endif /* WLAN_FEATURE_VOWIFI_11R */ + + uint8_t ucMaxProbeRespRetryLimit; + uint8_t bHiddenSSIDEn; + uint8_t bProxyProbeRespEn; + uint8_t halPersona; + uint8_t bSpectrumMgtEnabled; + uint8_t vhtCapable; + phy_ch_width ch_width; + uint8_t ch_center_freq_seg0; + uint8_t ch_center_freq_seg1; + uint8_t reassocReq; /* Set only during roaming reassociation */ + uint16_t chainMask; + uint16_t smpsMode; + uint8_t dot11_mode; + uint8_t nonRoamReassoc; + uint8_t wps_state; + uint8_t nss; +} tAddBssParams, *tpAddBssParams; + +/** + * struct tDeleteBssParams - params required for del bss request + * @bssIdx: BSSID + * @status: CDF status + * @respReqd: response message to LIM only when this flag is set + * @sessionId: PE session id + * @bssid: BSSID mac address + * @smesessionId: sme session id + */ +typedef struct { + uint8_t bssIdx; + CDF_STATUS status; + uint8_t respReqd; + uint8_t sessionId; + tSirMacAddr bssid; + uint8_t smesessionId; +} tDeleteBssParams, *tpDeleteBssParams; + +/** + * struct sSirScanEntry - scan entry + * @bssIdx: BSSID + * @activeBSScnt: active BSS count + */ +typedef struct sSirScanEntry { + uint8_t bssIdx[HAL_NUM_BSSID]; + uint8_t activeBSScnt; +} tSirScanEntry, *ptSirScanEntry; + +/** + * struct tInitScanParams - params required for init scan request + * @bssid: BSSID + * @notifyBss: notify BSS + * @useNoA: use NOA + * @notifyHost: notify UMAC if set + * @frameLength: frame length + * @frameType: frame type + * @scanDuration: Indicates the scan duration (in ms) + * @macMgmtHdr: For creation of CTS-to-Self and Data-NULL MAC packets + * @scanEntry: scan entry + * @checkLinkTraffic: when this flag is set, HAL should check for + * link traffic prior to scan + * @status: status + */ +typedef struct { + tSirMacAddr bssid; + uint8_t notifyBss; + uint8_t useNoA; + uint8_t notifyHost; + uint8_t frameLength; + uint8_t frameType; + uint16_t scanDuration; + tSirMacMgmtHdr macMgmtHdr; + tSirScanEntry scanEntry; + tSirLinkTrafficCheck checkLinkTraffic; + CDF_STATUS 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; + +/** + * struct tDeleteStaContext - params required for delete sta request + * @assocId: association id + * @staId: station id + * @bssId: mac address + * @addr2: mac address + * @reasonCode: reason code + */ +typedef struct { + uint16_t assocId; + uint16_t staId; + tSirMacAddr bssId; + tSirMacAddr addr2; + uint16_t reasonCode; +} tDeleteStaContext, *tpDeleteStaContext; + +/** + * struct tStartScanParams - params required for start scan request + * @scanChannel: Indicates the current scan channel + * @status: return status + * @startTSF: TSF value + * @txMgmtPower: TX mgmt power + */ +typedef struct { + uint8_t scanChannel; + CDF_STATUS status; +#if defined WLAN_FEATURE_VOWIFI + uint32_t startTSF[2]; + tPowerdBm txMgmtPower; +#endif /* WLAN_FEATURE_VOWIFI */ +} tStartScanParams, *tpStartScanParams; + +/** + * struct tEndScanParams - params required for end scan request + * @scanChannel: Indicates the current scan channel + * @status: return status + */ +typedef struct { + uint8_t scanChannel; + CDF_STATUS status; +} tEndScanParams, *tpEndScanParams; + +/** + * struct tFinishScanParams - params required for finish scan request + * @bssid: BSSID + * @currentOperChannel: Current operating channel + * @cbState: channel bond state + * @notifyBss: notify BSS flag + * @notifyHost: notify host flag + * @frameLength: frame length + * @frameType: frame type + * @macMgmtHdr: For creation of CTS-to-Self and Data-NULL MAC packets + * @scanEntry: scan entry + * @status: return status + * Request Type = SIR_HAL_FINISH_SCAN_REQ + */ +typedef struct { + tSirMacAddr bssid; + uint8_t 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 + */ + uint8_t notifyBss; + uint8_t notifyHost; + uint8_t frameLength; + uint8_t frameType; + tSirMacMgmtHdr macMgmtHdr; + tSirScanEntry scanEntry; + CDF_STATUS 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 + +/** + * struct tStartOemDataReq - start OEM Data request + * @selfMacAddr: self mac address + * @status: return status + * @oemDataReq: OEM Data request + */ +typedef struct { + tSirMacAddr selfMacAddr; + CDF_STATUS status; + uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; +} tStartOemDataReq, *tpStartOemDataReq; + +/** + * struct tStartOemDataRsp - start OEM Data response + * @oemDataRsp: OEM Data response + */ +typedef struct { + uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; +} tStartOemDataRsp, *tpStartOemDataRsp; +#endif /* FEATURE_OEM_DATA_SUPPORT */ + +/** + * struct tBeaconGenParams - params required for beacon gen request + * @bssIdx: Identifies the BSSID for which it is time to generate a beacon + * @bssId: BSSID + * @numOfSta: Number of stations in power save, who have data pending + * @numOfStaWithoutData: Number of stations in power save, + * who don't have any data pending + * @fBroadcastTrafficPending: broadcast traffic pending flag + * @dtimCount: DTIM count + * @rsvd: reserved(padding) + */ +typedef struct sBeaconGenParams { + uint8_t bssIdx; + tSirMacAddr bssId; +#ifdef FIXME_VOLANS + uint8_t numOfSta; + uint8_t numOfStaWithoutData; + uint8_t fBroadcastTrafficPending; + uint8_t dtimCount; +#endif /* FIXME_VOLANS */ + uint8_t rsvd[3]; +} tBeaconGenParams, *tpBeaconGenParams; + +/** + * struct tSendbeaconParams - send beacon parameters + * @bssId: BSSID mac address + * @beacon: beacon data + * @beaconLength: beacon length of template + * @timIeOffset: TIM IE offset + * @p2pIeOffset: P2P IE offset + */ +typedef struct { + tSirMacAddr bssId; + uint8_t *beacon; + uint32_t beaconLength; + uint32_t timIeOffset; + uint16_t p2pIeOffset; +} tSendbeaconParams, *tpSendbeaconParams; + +/** + * struct tSendProbeRespParams - send probe response parameters + * @bssId: BSSID + * @pProbeRespTemplate: probe response template + * @probeRespTemplateLen: probe response template length + * @ucProxyProbeReqValidIEBmap: valid IE bitmap + */ +typedef struct sSendProbeRespParams { + tSirMacAddr bssId; + uint8_t *pProbeRespTemplate; + uint32_t probeRespTemplateLen; + uint32_t ucProxyProbeReqValidIEBmap[8]; +} tSendProbeRespParams, *tpSendProbeRespParams; + +/** + * struct tSetBssKeyParams - BSS key parameters + * @bssIdx: BSSID index + * @encType: encryption Type + * @numKeys: number of keys + * @key: key data + * @singleTidRc: 1=Single TID based Replay Count, 0=Per TID based RC + * @smesessionId: sme session id + * @status: return status of command + * @sessionId: PE session id + */ +typedef struct { + uint8_t bssIdx; + tAniEdType encType; + uint8_t numKeys; + tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; + uint8_t singleTidRc; + uint8_t smesessionId; + CDF_STATUS status; + uint8_t sessionId; +} tSetBssKeyParams, *tpSetBssKeyParams; + +/** + * struct tUpdateBeaconParams - update beacon request parameters + * @bssIdx: BSSID index + * @fShortPreamble: shortPreamble mode + * @fShortSlotTime: short Slot time + * @beaconInterval: Beacon Interval + * @llaCoexist: 11a coexist + * @llbCoexist: 11b coexist + * @llgCoexist: 11g coexist + * @ht20MhzCoexist: HT 20MHz coexist + * @fLsigTXOPProtectionFullSupport: TXOP protection supported or not + * @fRIFSMode: RIFS mode + * @paramChangeBitmap: change bitmap + * @smeSessionId: SME session id + */ +typedef struct { + uint8_t bssIdx; + uint8_t fShortPreamble; + uint8_t fShortSlotTime; + uint16_t beaconInterval; + uint8_t llaCoexist; + uint8_t llbCoexist; + uint8_t llgCoexist; + uint8_t ht20MhzCoexist; + uint8_t llnNonGFCoexist; + uint8_t fLsigTXOPProtectionFullSupport; + uint8_t fRIFSMode; + uint16_t paramChangeBitmap; + uint8_t smeSessionId; +} tUpdateBeaconParams, *tpUpdateBeaconParams; + +#ifdef WLAN_FEATURE_11AC +/** + * struct tUpdateVHTOpMode - VHT operating mode + * @opMode: VHT operating mode + * @staId: station id + * @smesessionId: SME session id + * @peer_mac: peer mac address + */ +typedef struct { + uint16_t opMode; + uint16_t staId; + uint16_t smesessionId; + tSirMacAddr peer_mac; +} tUpdateVHTOpMode, *tpUpdateVHTOpMode; + +/** + * struct tUpdateRxNss - update rx nss parameters + * @rxNss: rx nss value + * @staId: station id + * @smesessionId: sme session id + * @peer_mac: peer mac address + */ +typedef struct { + uint16_t rxNss; + uint16_t staId; + uint16_t smesessionId; + tSirMacAddr peer_mac; +} tUpdateRxNss, *tpUpdateRxNss; + +/** + * struct tUpdateMembership - update membership parmaters + * @membership: membership value + * @staId: station id + * @smesessionId: SME session id + * @peer_mac: peer mac address + */ +typedef struct { + uint32_t membership; + uint16_t staId; + uint16_t smesessionId; + tSirMacAddr peer_mac; +} tUpdateMembership, *tpUpdateMembership; + +/** + * struct tUpdateUserPos - update user position parmeters + * @userPos: user position + * @staId: station id + * @smesessionId: sme session id + * @peer_mac: peer mac address + */ +typedef struct { + uint32_t userPos; + uint16_t staId; + uint16_t smesessionId; + tSirMacAddr peer_mac; +} tUpdateUserPos, *tpUpdateUserPos; + +#endif /* WLAN_FEATURE_11AC */ + +/** + * struct tUpdateCFParams -CF parameters + * @bssIdx: BSSID index + * @cfpCount: CFP count + * @cfpPeriod: the number of DTIM intervals between the start of CFPs + */ +typedef struct { + uint8_t 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. + */ + uint8_t cfpCount; + uint8_t cfpPeriod; +} tUpdateCFParams, *tpUpdateCFParams; + +/** + * struct tSwitchChannelParams - switch channel request parameter + * @channelNumber: channel number + * @localPowerConstraint: local power constraint + * @secondaryChannelOffset: scondary channel offset + * @peSessionId: PE session id + * @txMgmtPower: TX mgmt power + * @maxTxPower: max tx power + * @selfStaMacAddr: self mac address + * @bssId: bssid + * @status: CDF status + * @chainMask: chanin mask + * @smpsMode: SMPS mode + * @isDfsChannel: is DFS channel + * @vhtCapable: VHT capable + * @dot11_mode: 802.11 mode + */ +typedef struct { + uint8_t channelNumber; +#ifndef WLAN_FEATURE_VOWIFI + uint8_t localPowerConstraint; +#endif /* WLAN_FEATURE_VOWIFI */ + uint8_t peSessionId; +#if defined WLAN_FEATURE_VOWIFI + tPowerdBm txMgmtPower; + tPowerdBm maxTxPower; +#endif /* WLAN_FEATURE_VOWIFI */ + 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; + CDF_STATUS status; + uint16_t chainMask; + uint16_t smpsMode; + uint8_t isDfsChannel; + uint8_t vhtCapable; + phy_ch_width ch_width; + uint8_t ch_center_freq_seg0; + uint8_t ch_center_freq_seg1; + uint8_t dot11_mode; + + uint8_t restart_on_chan_switch; + uint8_t nss; +} tSwitchChannelParams, *tpSwitchChannelParams; + +/** + * struct tpCSAOffloadParams - CSA offload request parameters + * @channel: channel + * @switchmode: switch mode + * @sec_chan_offset: second channel offset + * @new_ch_width: new channel width + * @new_ch_freq_seg1: channel center freq 1 + * @new_ch_freq_seg2: channel center freq 2 + * @ies_present_flag: IE present flag + */ +typedef struct CSAOffloadParams { + uint8_t channel; + uint8_t switchmode; + uint8_t sec_chan_offset; + uint8_t new_ch_width; + uint8_t new_ch_freq_seg1; + uint8_t new_ch_freq_seg2; + uint32_t ies_present_flag; + tSirMacAddr bssId; +} *tpCSAOffloadParams, tCSAOffloadParams; + +typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam, + bool status); + +/** + * struct tLinkStateParams - link state parameters + * @bssid: BSSID + * @selfMacAddr: self mac address + * @state: link state + * @callback: callback function pointer + * @callbackArg: callback argument + * @session: session context + */ +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 /* WLAN_FEATURE_VOWIFI_11R */ + bool status; +} tLinkStateParams, *tpLinkStateParams; + +/** + * struct tAddTsParams - ADDTS related parameters + * @staIdx: station index + * @tspecIdx: TSPEC handler uniquely identifying a TSPEC for a STA in a BSS + * @tspec: tspec value + * @status: CDF status + * @sessionId: session id + * @tsm_interval: TSM interval period passed from lim to WMA + * @setRICparams: RIC parameters + * @sme_session_id: sme session id + */ +typedef struct { + uint16_t staIdx; + uint16_t tspecIdx; + tSirMacTspecIE tspec; + CDF_STATUS status; + uint8_t sessionId; +#ifdef FEATURE_WLAN_ESE + uint16_t tsm_interval; +#endif /* FEATURE_WLAN_ESE */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t setRICparams; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + uint8_t sme_session_id; +} tAddTsParams, *tpAddTsParams; + +/** + * struct tDelTsParams - DELTS related parameters + * @staIdx: station index + * @tspecIdx: TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS + * @bssId: BSSID + * @sessionId: session id + * @userPrio: user priority + * @delTsInfo: DELTS info + * @setRICparams: RIC parameters + */ +typedef struct { + uint16_t staIdx; + uint16_t tspecIdx; + tSirMacAddr bssId; + uint8_t sessionId; + uint8_t userPrio; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + tSirDeltsReqInfo delTsInfo; + uint8_t setRICparams; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +} tDelTsParams, *tpDelTsParams; + +#ifdef WLAN_FEATURE_VOWIFI_11R + +#define HAL_QOS_NUM_TSPEC_MAX 2 +#define HAL_QOS_NUM_AC_MAX 4 + +/** + * struct tAggrAddTsParams - ADDTS parameters + * @staIdx: station index + * @tspecIdx: TSPEC handler uniquely identifying a TSPEC for a STA in a BSS + * @tspec: tspec value + * @status: CDF status + * @sessionId: session id + */ +typedef struct { + uint16_t staIdx; + uint16_t tspecIdx; + tSirMacTspecIE tspec[HAL_QOS_NUM_AC_MAX]; + CDF_STATUS status[HAL_QOS_NUM_AC_MAX]; + uint8_t sessionId; +} tAggrAddTsParams, *tpAggrAddTsParams; + +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +typedef tSirRetStatus (*tHalMsgCallback)(tpAniSirGlobal pMac, uint32_t mesgId, + void *mesgParam); + +/** + * struct tEdcaParams - EDCA parameters + * @bssIdx: BSSID index + * @acbe: best effort access catagory + * @acbk: Background access catagory + * @acvi: video access catagory + * @acvo: voice access catagory + */ +typedef struct { + uint16_t bssIdx; + tSirMacEdcaParamRecord acbe; + tSirMacEdcaParamRecord acbk; + tSirMacEdcaParamRecord acvi; + tSirMacEdcaParamRecord acvo; +} tEdcaParams, *tpEdcaParams; + +/** + * struct tSetMIMOPS - MIMO power save related parameters + * @staIdx: station index + * @htMIMOPSState: MIMO Power Save State + * @status: response status + * @fsendRsp: send response flag + * @peerMac: peer mac address + * @sessionId: session id + */ +typedef struct sSet_MIMOPS { + uint16_t staIdx; + tSirMacHTMIMOPowerSaveState htMIMOPSState; + CDF_STATUS status; + uint8_t fsendRsp; + tSirMacAddr peerMac; + uint8_t sessionId; +} tSetMIMOPS, *tpSetMIMOPS; + +/** + * struct tUapsdParams - Uapsd related parameters + * @bkDeliveryEnabled: BK delivery enable flag + * @beDeliveryEnabled: BE delivery enable flag + * @viDeliveryEnabled: VI delivery enable flag + * @voDeliveryEnabled: VO delivery enable flag + * @bkTriggerEnabled: BK trigger enable flag + * @beTriggerEnabled: BE trigger enable flag + * @viTriggerEnabled: VI trigger enable flag + * @voTriggerEnabled: VO trigger enable flag + * @status: response status + * @bssIdx: BSSID index + * Request Type = SIR_HAL_ENTER_UAPSD_REQ + */ +typedef struct sUapsdParams { + uint8_t bkDeliveryEnabled:1; + uint8_t beDeliveryEnabled:1; + uint8_t viDeliveryEnabled:1; + uint8_t voDeliveryEnabled:1; + uint8_t bkTriggerEnabled:1; + uint8_t beTriggerEnabled:1; + uint8_t viTriggerEnabled:1; + uint8_t voTriggerEnabled:1; + CDF_STATUS status; + uint8_t bssIdx; +} tUapsdParams, *tpUapsdParams; + +/** + * struct tHalIndCB - hal message indication callback + * @pHalIndCB: hal message indication callabck + */ +typedef struct tHalIndCB { + tHalMsgCallback pHalIndCB; +} tHalIndCB, *tpHalIndCB; + +/** + * struct sControlTxParams - control tx parameters + * @stopTx: stop transmission + * @fCtrlGlobal: Master flag to stop or resume all transmission + * @ctrlSta: If this flag is set, staBitmap + * @ctrlBss: If this flag is set, bssBitmap and beaconBitmap is valid + * @bssBitmap: bitmap of BSS indices to be stopped for resumed + * @beaconBitmap: this bitmap contains bitmap of BSS indices to be + * stopped for resumed for beacon transmission + */ +typedef struct sControlTxParams { + bool stopTx; + uint8_t fCtrlGlobal; + uint8_t ctrlSta; + uint8_t 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. + */ + uint32_t bssBitmap; + /* When ctrlBss is set, this bitmap contains bitmap of BSS indices to be + * stopped for resumed for beacon transmission. + */ + uint32_t beaconBitmap; +} tTxControlParams, *tpTxControlParams; + +/** + * struct tMaxTxPowerParams - Max Tx Power parameters + * @bssId: BSSID is needed to identify which session issued this request + * @selfStaMacAddr: self mac address + * @power: tx power in dbm + * @dev_mode: device mode + * Request Type = SIR_HAL_SET_MAX_TX_POWER_REQ + */ +typedef struct sMaxTxPowerParams { + tSirMacAddr bssId; + tSirMacAddr selfStaMacAddr; + /* In request, + * power == MaxTx power to be used. + * In response, + * power == tx power used for management frames. + */ + tPowerdBm power; + tCDF_CON_MODE dev_mode; +} tMaxTxPowerParams, *tpMaxTxPowerParams; + +/** + * struct tMaxTxPowerPerBandParams - max tx power per band info + * @bandInfo: band info + * @power: power in dbm + */ +typedef struct sMaxTxPowerPerBandParams { + eCsrBand bandInfo; + tPowerdBm power; +} tMaxTxPowerPerBandParams, *tpMaxTxPowerPerBandParams; + +/** + * struct add_sta_self_params - Add Sta Self params + * @self_mac_addr: self MAC Address + * @curr_device_mode: operating device mode + * @type: Vdev Type + * @sub_type: Vdev Sub Type + * @session_id: SME Session ID + * @status: response status code + */ +struct add_sta_self_params { + tSirMacAddr self_mac_addr; + tCDF_CON_MODE curr_device_mode; + uint32_t type; + uint32_t sub_type; + uint8_t session_id; + uint32_t status; +}; + +#ifdef FEATURE_WLAN_TDLS + +#define HAL_TDLS_MAX_SUPP_CHANNELS 128 +#define HAL_TDLS_MAX_SUPP_OPER_CLASSES 32 + +/** + * struct tTdlsPeerCapParams - TDLS peer capablities parameters + * @isPeerResponder: is peer responder or not + * @peerUapsdQueue: peer uapsd queue + * @peerMaxSp: peer max SP value + * @peerBuffStaSupport: peer buffer sta supported or not + * @peerOffChanSupport: peer offchannel support + * @peerCurrOperClass: peer current operating class + * @selfCurrOperClass: self current operating class + * @peerChanLen: peer channel length + * @peerChan: peer channel list + * @peerOperClassLen: peer operating class length + * @peerOperClass: peer operating class + * @prefOffChanNum: peer offchannel number + * @prefOffChanBandwidth: peer offchannel bandwidth + * @opClassForPrefOffChan: operating class for offchannel + */ +typedef struct { + uint8_t isPeerResponder; + uint8_t peerUapsdQueue; + uint8_t peerMaxSp; + uint8_t peerBuffStaSupport; + uint8_t peerOffChanSupport; + uint8_t peerCurrOperClass; + uint8_t selfCurrOperClass; + uint8_t peerChanLen; + tSirUpdateChanParam peerChan[HAL_TDLS_MAX_SUPP_CHANNELS]; + uint8_t peerOperClassLen; + uint8_t peerOperClass[HAL_TDLS_MAX_SUPP_OPER_CLASSES]; + uint8_t prefOffChanNum; + uint8_t prefOffChanBandwidth; + uint8_t opClassForPrefOffChan; +} tTdlsPeerCapParams; + +/** + * struct tTdlsPeerStateParams - TDLS peer state parameters + * @vdevId: vdev id + * @peerMacAddr: peer mac address + * @peerCap: peer capabality + */ +typedef struct sTdlsPeerStateParams { + uint32_t vdevId; + tSirMacAddr peerMacAddr; + uint32_t peerState; + tTdlsPeerCapParams peerCap; +} tTdlsPeerStateParams; + +/** + * struct tdls_chan_switch_params - channel switch parameter structure + * @vdev_id: vdev ID + * @peer_mac_addr: Peer mac address + * @tdls_off_ch_bw_offset: Target off-channel bandwitdh offset + * @tdls_off_ch: Target Off Channel + * @oper_class: Operating class for target channel + * @is_responder: Responder or initiator + */ +typedef struct tdls_chan_switch_params_struct { + uint32_t vdev_id; + tSirMacAddr peer_mac_addr; + uint16_t tdls_off_ch_bw_offset; + uint8_t tdls_off_ch; + uint8_t tdls_sw_mode; + uint8_t oper_class; + uint8_t is_responder; +} tdls_chan_switch_params; + +#endif /* FEATURE_WLAN_TDLS */ + +/** + * struct tAbortScanParams - Abort scan parameters + * @SessionId: session id + */ +typedef struct sAbortScanParams { + uint8_t SessionId; + uint32_t scan_id; +} tAbortScanParams, *tpAbortScanParams; + +/** + * struct del_sta_self_params - Del Sta Self params + * @session_id: SME Session ID + * @status: response status code + */ +struct del_sta_self_params { + tSirMacAddr self_mac_addr; + uint8_t session_id; + uint32_t status; +}; + +/** + * struct tP2pPsParams - P2P powersave related params + * @opp_ps: opportunistic power save + * @ctWindow: CT window + * @count: count + * @duration: duration + * @interval: interval + * @single_noa_duration: single shot noa duration + * @psSelection: power save selection + * @sessionId: session id + */ +typedef struct sP2pPsParams { + uint8_t opp_ps; + uint32_t ctWindow; + uint8_t count; + uint32_t duration; + uint32_t interval; + uint32_t single_noa_duration; + uint8_t psSelection; + uint8_t sessionId; +} tP2pPsParams, *tpP2pPsParams; + +/** + * struct tTdlsLinkEstablishParams - TDLS Link establish parameters + * @staIdx: station index + * @isResponder: responder flag + * @uapsdQueues: uapsd queue + * @maxSp: max SP period + * @isBufsta: is station flag + * @isOffChannelSupported: offchannel supported or not + * @peerCurrOperClass: peer current operating class + * @selfCurrOperClass: self current operating class + * @validChannelsLen: valid channel length + * @validChannels: valid channels + * @validOperClassesLen: valid operating class length + * @validOperClasses: valid operating class + * @status: return status of command + */ +typedef struct sTdlsLinkEstablishParams { + uint16_t staIdx; + uint8_t isResponder; + uint8_t uapsdQueues; + uint8_t maxSp; + uint8_t isBufsta; + uint8_t isOffChannelSupported; + uint8_t peerCurrOperClass; + uint8_t selfCurrOperClass; + uint8_t validChannelsLen; + uint8_t validChannels[HAL_MAX_SUPP_CHANNELS]; + uint8_t validOperClassesLen; + uint8_t validOperClasses[HAL_MAX_SUPP_OPER_CLASSES]; + uint32_t status; +} tTdlsLinkEstablishParams, *tpTdlsLinkEstablishParams; + +/** + * struct tHalHiddenSsidVdevRestart - hidden ssid vdev restart params + * @ssidHidden: is hidden ssid or not + * @sessionId: session id + */ +typedef struct tHalHiddenSsidVdevRestart { + uint8_t ssidHidden; + uint8_t sessionId; +} tHalHiddenSsidVdevRestart, *tpHalHiddenSsidVdevRestart; + + +extern void sys_process_mmh_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +/** + * struct tBeaconFilterMsg - Beacon Filtering data structure + * @capabilityInfo: capability info + * @capabilityMask: capabality mask + * @beaconInterval: beacon interval + * @ieNum: IE number + * @reserved: reserved + */ +typedef struct sBeaconFilterMsg { + uint16_t capabilityInfo; + uint16_t capabilityMask; + uint16_t beaconInterval; + uint16_t ieNum; + uint8_t bssIdx; + uint8_t reserved; +} cdf_packed tBeaconFilterMsg, *tpBeaconFilterMsg; + +/** + * struct tEidByteInfo - Eid byte info + * @offset: offset + * @value: value + * @bitMask: BIT mask + * @ref: refrence + */ +typedef struct sEidByteInfo { + uint8_t offset; + uint8_t value; + uint8_t bitMask; + uint8_t ref; +} cdf_packed tEidByteInfo, *tpEidByteInfo; + +/** + * struct tBeaconFilterIe - beacon filter IE + * @elementId: element IE + * @checkIePresence: check IE presence + * @byte: Eid byte info + */ +typedef struct sBeaconFilterIe { + uint8_t elementId; + uint8_t checkIePresence; + tEidByteInfo byte; +} cdf_packed tBeaconFilterIe, *tpBeaconFilterIe; + +/** + * struct tDisableIntraBssFwd - intra bss forward parameters + * @sessionId: session id + * @disableintrabssfwd: disable intra bss forward flag + */ +typedef struct sDisableIntraBssFwd { + uint16_t sessionId; + bool disableintrabssfwd; +} cdf_packed tDisableIntraBssFwd, *tpDisableIntraBssFwd; + +#ifdef WLAN_FEATURE_STATS_EXT +/** + * struct tStatsExtRequest - ext stats request + * @vdev_id: vdev id + * @request_data_len: request data length + * @request_data: request data + */ +typedef struct sStatsExtRequest { + uint32_t vdev_id; + uint32_t request_data_len; + uint8_t request_data[]; +} tStatsExtRequest, *tpStatsExtRequest; +#endif /* WLAN_FEATURE_STATS_EXT */ + +#ifdef WLAN_FEATURE_NAN +/** + * struct tNanRequest - NAN request params + * @request_data_len: request data length + * @request_data: request data + */ +typedef struct sNanRequest { + uint16_t request_data_len; + uint8_t request_data[]; +} tNanRequest, *tpNanRequest; +#endif /* WLAN_FEATURE_NAN */ + +#endif /* _HALMSGAPI_H_ */ diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h new file mode 100644 index 000000000000..a737fa2f10ec --- /dev/null +++ b/core/wma/inc/wma_internal.h @@ -0,0 +1,1097 @@ +/* + * 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 WMA_INTERNAL_H +#define WMA_INTERNAL_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 WMA + */ +#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 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 MAX_ENTRY_HOLD_REQ_QUEUE 2 +/** + * struct index_data_rate_type - non vht data rate type + * @beacon_rate_index: Beacon rate index + * @supported_rate: Supported rate table + */ +struct index_data_rate_type { + uint8_t beacon_rate_index; + uint16_t supported_rate[4]; +}; + +#ifdef WLAN_FEATURE_11AC +/** + * struct index_vht_data_rate_type - vht data rate type + * @beacon_rate_index: Beacon rate index + * @supported_VHT80_rate: VHT80 rate + * @supported_VHT40_rate: VHT40 rate + * @supported_VHT20_rate: VHT20 rate + */ +struct index_vht_data_rate_type { + uint8_t beacon_rate_index; + uint16_t supported_VHT80_rate[2]; + uint16_t supported_VHT40_rate[2]; + uint16_t supported_VHT20_rate[2]; +}; +#endif + +/* + * wma_main.c functions declarations + */ + +int +wmi_unified_pdev_set_param(wmi_unified_t wmi_handle, WMI_PDEV_PARAM param_id, + uint32_t param_value); + +void wma_send_msg(tp_wma_handle wma_handle, uint16_t msg_type, + void *body_ptr, uint32_t body_val); + +void wma_data_tx_ack_comp_hdlr(void *wma_context, + cdf_nbuf_t netbuf, int32_t status); + +CDF_STATUS wma_set_ppsconfig(uint8_t vdev_id, uint16_t pps_param, + int value); + +/* + * wma_scan_roam.c functions declarations + */ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_process_roam_invoke(WMA_HANDLE handle, + struct wma_roam_invoke_cmd *roaminvoke); + +void wma_process_roam_synch_fail(WMA_HANDLE handle, + struct roam_offload_synch_fail *synch_fail); + +int wma_roam_synch_event_handler(void *handle, uint8_t *event, + uint32_t len); +#endif + +CDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, + tSirScanOffloadReq *scan_req, + wmi_buf_t *buf, int *buf_len); + +CDF_STATUS wma_get_buf_stop_scan_cmd(tp_wma_handle wma_handle, + wmi_buf_t *buf, + int *buf_len, + tAbortScanParams *abort_scan_req); + +CDF_STATUS wma_start_scan(tp_wma_handle wma_handle, + tSirScanOffloadReq *scan_req, uint16_t msg_type); + +CDF_STATUS wma_stop_scan(tp_wma_handle wma_handle, + tAbortScanParams *abort_scan_req); + +CDF_STATUS wma_update_channel_list(WMA_HANDLE handle, + tSirUpdateChanList *chan_list); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +CDF_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle, + wmi_roam_offload_tlv_param * + roam_offload_params, + tSirRoamOffloadScanReq *roam_req); +#endif + +CDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle, + wmi_start_scan_cmd_fixed_param * + scan_cmd_fp, + tSirRoamOffloadScanReq *roam_req, + uint32_t mode, uint32_t vdev_id); + +CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req); + +CDF_STATUS wma_roam_scan_offload_scan_period(tp_wma_handle wma_handle, + uint32_t scan_period, + uint32_t scan_age, + uint32_t vdev_id); + +CDF_STATUS wma_roam_scan_offload_rssi_change(tp_wma_handle wma_handle, + uint32_t vdev_id, + int32_t rssi_change_thresh, + uint32_t bcn_rssi_weight, + uint32_t hirssi_delay_btw_scans); + +CDF_STATUS wma_roam_scan_offload_chan_list(tp_wma_handle wma_handle, + uint8_t chan_count, + uint8_t *chan_list, + uint8_t list_type, uint32_t vdev_id); + +A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype, + eCsrEncryptionType encr); + +A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr); + +void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, + tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, + wmi_ap_profile *ap_profile_p); + +void wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle, + tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, + wmi_start_scan_cmd_fixed_param * + scan_params); + +CDF_STATUS wma_roam_scan_offload_ap_profile(tp_wma_handle wma_handle, + wmi_ap_profile *ap_profile_p, + uint32_t vdev_id); + +CDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle, + A_INT32 first_bcnt, + A_UINT32 final_bcnt, uint32_t vdev_id); + +CDF_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle, + uint32_t command, uint32_t vdev_id); + +CDF_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req); + +CDF_STATUS wma_roam_preauth_chan_set(tp_wma_handle wma_handle, + tpSwitchChannelParams params, + uint8_t vdev_id); + +CDF_STATUS wma_roam_preauth_chan_cancel(tp_wma_handle wma_handle, + tpSwitchChannelParams params, + uint8_t vdev_id); + +void wma_roam_preauth_scan_event_handler(tp_wma_handle wma_handle, + uint8_t vdev_id, + wmi_scan_event_fixed_param * + wmi_event); + +void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params); + +#ifdef FEATURE_WLAN_SCAN_PNO +CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno); + +CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id); + +void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno); + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm); + +CDF_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm); + +void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm); +#endif + +void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId); +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts); +#endif + +#ifdef FEATURE_WLAN_EXTSCAN + +int wma_extscan_start_stop_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_operations_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_table_usage_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_capabilities_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_hotlist_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_cached_results_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_extscan_change_results_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int wma_passpoint_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + +int +wma_extscan_hotlist_ssid_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); +#endif + +void wma_register_extscan_event_handler(tp_wma_handle wma_handle); + +#ifdef FEATURE_WLAN_EXTSCAN +CDF_STATUS wma_get_buf_extscan_start_cmd(tp_wma_handle wma_handle, + tSirWifiScanCmdReqParams *pstart, + wmi_buf_t *buf, int *buf_len); + +CDF_STATUS wma_start_extscan(tp_wma_handle wma, + tSirWifiScanCmdReqParams *pstart); + +CDF_STATUS wma_stop_extscan(tp_wma_handle wma, + tSirExtScanStopReqParams *pstopcmd); + +CDF_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, + tSirExtScanSetBssidHotListReqParams * + photlist, int *buf_len); + +CDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma, + tSirExtScanSetBssidHotListReqParams + *photlist); + +CDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma, + tSirExtScanResetBssidHotlistReqParams + *photlist_reset); + +CDF_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle, + tSirExtScanSetSigChangeReqParams + *psigchange, wmi_buf_t *buf, + int *buf_len); + +CDF_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma, + tSirExtScanSetSigChangeReqParams * + psigchange); + +CDF_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma, + tSirExtScanResetSignificantChangeReqParams + *pResetReq); + +CDF_STATUS wma_extscan_get_cached_results(tp_wma_handle wma, + tSirExtScanGetCachedResultsReqParams * + pcached_results); + +CDF_STATUS wma_extscan_get_capabilities(tp_wma_handle wma, + tSirGetExtScanCapabilitiesReqParams * + pgetcapab); +CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma, + struct wifi_epno_params *req); + +CDF_STATUS wma_set_passpoint_network_list(tp_wma_handle wma, + struct wifi_passpoint_req *req); + +CDF_STATUS wma_reset_passpoint_network_list(tp_wma_handle wma, + struct wifi_passpoint_req *req); +CDF_STATUS +wma_set_ssid_hotlist(tp_wma_handle wma, + struct sir_set_ssid_hotlist_request *request); +#endif + +CDF_STATUS wma_ipa_offload_enable_disable(tp_wma_handle wma, + struct sir_ipa_offload_enable_disable *ipa_offload); + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_process_unit_test_cmd(WMA_HANDLE handle, + t_wma_unit_test_cmd *wma_utest); +#endif + +CDF_STATUS wma_scan_probe_setoui(tp_wma_handle wma, tSirScanMacOui *psetoui); + +int wma_scan_event_callback(WMA_HANDLE handle, uint8_t *data, uint32_t len); + +void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id); + +int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, + uint32_t len); + +#ifdef FEATURE_WLAN_SCAN_PNO +int wma_nlo_match_evt_handler(void *handle, uint8_t *event, uint32_t len); + +int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event, uint32_t len); +#endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +void wma_process_roam_synch_complete(WMA_HANDLE handle, + tSirSmeRoamOffloadSynchCnf *synchcnf); +#endif + +/* + * wma_dev_if.c functions declarations + */ + +void *wma_find_vdev_by_addr(tp_wma_handle wma, uint8_t *addr, + uint8_t *vdev_id); + +/** + * wma_find_vdev_by_id() - Returns vdev handle for given vdev id. + * @wma - wma handle + * @vdev_id - vdev ID + * + * Return: Returns vdev handle if given vdev id is valid. + * Otherwise returns NULL. + */ +static inline void *wma_find_vdev_by_id(tp_wma_handle wma, uint8_t vdev_id) +{ + if (vdev_id > wma->max_bssid) + return NULL; + + return wma->interfaces[vdev_id].handle; +} + +/** + * wma_get_vdev_count() - Returns number of active vdev. + * @wma - wma handle + * + * Return: Returns valid vdev count. + */ +static inline uint8_t wma_get_vdev_count(tp_wma_handle wma) +{ + uint8_t vdev_count = 0, i; + + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].handle) + vdev_count++; + } + return vdev_count; +} + +bool wma_is_vdev_in_ap_mode(tp_wma_handle wma, uint8_t vdev_id); + +#ifdef QCA_IBSS_SUPPORT +bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, uint8_t vdev_id); +#endif + +/** + * wma_find_bssid_by_vdev_id() - Get the BSS ID corresponding to the vdev ID + * @wma - wma handle + * @vdev_id - vdev ID + * + * Return: Returns pointer to bssid on success, + * otherwise returns NULL. + */ +static inline uint8_t *wma_find_bssid_by_vdev_id(tp_wma_handle wma, + uint8_t vdev_id) +{ + if (vdev_id >= wma->max_bssid) + return NULL; + + return wma->interfaces[vdev_id].bssid; +} + +void *wma_find_vdev_by_bssid(tp_wma_handle wma, uint8_t *bssid, + uint8_t *vdev_id); + +int wma_unified_vdev_create_send(wmi_unified_t wmi_handle, uint8_t if_id, + uint32_t type, uint32_t subtype, + uint8_t macaddr[IEEE80211_ADDR_LEN]); + +CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *pdel_sta_self_req_param, + uint8_t generateRsp); + +int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); + +int wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, uint32_t if_id, + uint32_t param_id, uint32_t param_value); + +int32_t wmi_unified_peer_flush_tids_send(wmi_unified_t wmi, + uint8_t peer_addr + [IEEE80211_ADDR_LEN], + uint32_t peer_tid_bitmap, + uint8_t vdev_id); + +void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid, + uint8_t vdev_id, ol_txrx_peer_handle peer, + bool roam_synch_in_progress); + +CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, + u8 peer_addr[IEEE80211_ADDR_LEN], + uint32_t peer_type, uint8_t vdev_id, + bool roam_synch_in_progress); + +int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, + u32 len); + +ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, + struct add_sta_self_params *self_sta_req, + uint8_t generateRsp); + +CDF_STATUS wma_vdev_start(tp_wma_handle wma, + struct wma_vdev_start_req *req, bool isRestart); + +void wma_vdev_resp_timer(void *data); + +struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, + uint8_t vdev_id, + uint32_t msg_type, uint8_t type, + void *params, uint32_t timeout); + +void wma_hold_req_timer(void *data); +struct wma_target_req *wma_fill_hold_req(tp_wma_handle wma, + uint8_t vdev_id, uint32_t msg_type, + uint8_t type, void *params, + uint32_t timeout); + +void wma_remove_vdev_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type); + +void wma_add_bss(tp_wma_handle wma, tpAddBssParams params); + +int wmi_unified_vdev_up_send(wmi_unified_t wmi, + uint8_t vdev_id, uint16_t aid, + uint8_t bssid[IEEE80211_ADDR_LEN]); + +void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta); + +void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta); + +int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, uint8_t vdev_id); + +void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params); + +int32_t wma_find_vdev_by_type(tp_wma_handle wma, int32_t type); + +void wma_set_vdev_intrabss_fwd(tp_wma_handle wma_handle, + tpDisableIntraBssFwd pdis_intra_fwd); + +/* + * wma_mgmt.c functions declarations + */ + +int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_t len); + +int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len); + +void wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len); + +int wma_unified_bcntx_status_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); + + +void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, + uint32_t method, uint32_t timeperiod, + uint8_t *hostv4addr, uint8_t *destv4addr, + uint8_t *destmac); + +int wma_vdev_install_key_complete_event_handler(void *handle, + uint8_t *event, + uint32_t len); + +int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, + tSirNwType nw_type, + tpAddStaParams params); + +int wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle, uint32_t if_id, + gtx_config_t *gtx_info); + +void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id, + uint8_t llbcoexist); + +void wma_process_update_beacon_params(tp_wma_handle wma, + tUpdateBeaconParams *bcn_params); + +void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam); + +void wma_set_bsskey(tp_wma_handle wma_handle, tpSetBssKeyParams key_info); + +void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma, + uint8_t vdev_id, + int8_t peer_num_delta); + +void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info); + +CDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle, + tEdcaParams *edca_params); + +int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event, + uint32_t len); + +void wma_send_probe_rsp_tmpl(tp_wma_handle wma, + tpSendProbeRespParams probe_rsp_info); + +void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info); + +void wma_set_keepalive_req(tp_wma_handle wma, + tSirKeepAliveReq *keepalive); + +void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id); + +void wma_process_update_opmode(tp_wma_handle wma_handle, + tUpdateVHTOpMode *update_vht_opmode); + +void wma_process_update_rx_nss(tp_wma_handle wma_handle, + tUpdateRxNss *update_rx_nss); + +void wma_process_update_membership(tp_wma_handle wma_handle, + tUpdateMembership *membership); + +void wma_process_update_userpos(tp_wma_handle wma_handle, + tUpdateUserPos *userpos); + +void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle, + tHalHiddenSsidVdevRestart *pReq); + +/* + * wma_power.c functions declarations + */ + +void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req); + +int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, + uint32_t vdev_id, uint32_t param, + uint32_t value); + +CDF_STATUS +wma_set_ibss_pwrsave_params(tp_wma_handle wma, uint8_t vdev_id); + +int32_t wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id, + uint8_t *peer_addr, uint8_t uapsd_value, + uint8_t max_sp); + +void wma_update_edca_params_for_ac(tSirMacEdcaParamRecord *edca_param, + wmi_wmm_vparams *wmm_param, int ac); + +void wma_set_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params); + +void wma_set_max_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params); + +int32_t wmi_unified_set_sta_ps(wmi_unified_t wmi_handle, + uint32_t vdev_id, uint8_t val); + +void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req); + +void wma_enable_uapsd_mode(tp_wma_handle wma, tpEnableUapsdParams ps_req); + +void wma_disable_uapsd_mode(tp_wma_handle wma, + tpDisableUapsdParams ps_req); + +CDF_STATUS wma_get_temperature(tp_wma_handle wma_handle); + +int wma_pdev_temperature_evt_handler(void *handle, uint8_t *event, + uint32_t len); + +CDF_STATUS wma_process_tx_power_limits(WMA_HANDLE handle, + tSirTxPowerLimit *ptxlim); + +void wma_update_noa(struct beacon_info *beacon, + struct p2p_sub_element_noa *noa_ie); + +void wma_update_probe_resp_noa(tp_wma_handle wma_handle, + struct p2p_sub_element_noa *noa_ie); + +int wma_p2p_noa_event_handler(void *handle, uint8_t *event, + uint32_t len); + +void wma_process_set_p2pgo_noa_req(tp_wma_handle wma, + tP2pPsParams *ps_params); + +void wma_process_set_mimops_req(tp_wma_handle wma_handle, + tSetMIMOPS *mimops); + +CDF_STATUS wma_set_mimops(tp_wma_handle wma, uint8_t vdev_id, int value); + +CDF_STATUS wma_notify_modem_power_state(void *wma_ptr, + tSirModemPowerStateInd *pReq); + +CDF_STATUS wma_set_smps_params(tp_wma_handle wma, uint8_t vdev_id, + int value); + +void wma_set_suspend_dtim(tp_wma_handle wma); + +void wma_set_resume_dtim(tp_wma_handle wma); + +/* + * wma_data.c functions declarations + */ + + +void wma_set_bss_rate_flags(struct wma_txrx_node *iface, + tpAddBssParams add_bss); + +int32_t wmi_unified_send_txbf(tp_wma_handle wma, tpAddStaParams params); + +void wma_update_txrx_chainmask(int num_rf_chains, int *cmd_value); + +int wma_peer_state_change_event_handler(void *handle, + uint8_t *event_buff, + uint32_t len); + +CDF_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t + mcc_adaptive_scheduler); + +CDF_STATUS wma_set_mcc_channel_time_latency + (tp_wma_handle wma, + uint32_t mcc_channel, uint32_t mcc_channel_time_latency); + +CDF_STATUS wma_set_mcc_channel_time_quota + (tp_wma_handle wma, + uint32_t adapter_1_chan_number, + uint32_t adapter_1_quota, uint32_t adapter_2_chan_number); + +void wma_set_linkstate(tp_wma_handle wma, tpLinkStateParams params); + +void wma_unpause_vdev(tp_wma_handle wma); + +CDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, + tSirRateUpdateInd * + pRateUpdateParams); + +CDF_STATUS wma_tx_attach(tp_wma_handle wma_handle); + +CDF_STATUS wma_tx_detach(tp_wma_handle wma_handle); + +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +int wma_mcc_vdev_tx_pause_evt_handler(void *handle, uint8_t *event, + uint32_t len); +#endif + +CDF_STATUS wma_process_init_thermal_info(tp_wma_handle wma, + t_thermal_mgmt *pThermalParams); + +CDF_STATUS wma_process_set_thermal_level(tp_wma_handle wma, + uint8_t thermal_level); + +CDF_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle, + t_thermal_cmd_params thermal_info); + +int wma_thermal_mgmt_evt_handler(void *handle, uint8_t *event, + uint32_t len); + +/* + * wma_utils.c functions declarations + */ + +#ifdef WLAN_FEATURE_STATS_EXT +int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf, + uint32_t len); +#endif + +tSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode); + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle); + +CDF_STATUS wma_process_ll_stats_clear_req + (tp_wma_handle wma, const tpSirLLStatsClearReq clearReq); + +CDF_STATUS wma_process_ll_stats_set_req + (tp_wma_handle wma, const tpSirLLStatsSetReq setReq); + +CDF_STATUS wma_process_ll_stats_get_req + (tp_wma_handle wma, const tpSirLLStatsGetReq getReq) ; + +int wma_unified_link_iface_stats_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len); +#endif + +void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus, + uint8_t link_status); + +int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); + +int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); + +CDF_STATUS wma_send_link_speed(uint32_t link_speed); + +int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); + +CDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle); + +int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap, + uint32_t len); + +bool wma_is_sap_active(tp_wma_handle wma_handle); + +bool wma_is_p2p_go_active(tp_wma_handle wma_handle); + +bool wma_is_p2p_cli_active(tp_wma_handle wma_handle); + +bool wma_is_sta_active(tp_wma_handle wma_handle); + +WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type, + uint8_t is_ht, uint8_t ch_width, + uint8_t is_vht); + +int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle, + uint8_t vdev_id, uint32_t value); + +int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle, + uint8_t vdev_id, uint32_t value); + +int wmi_crash_inject(wmi_unified_t wmi_handle, uint32_t type, + uint32_t delay_time_ms); + +void wma_get_stats_req(WMA_HANDLE handle, + tAniGetPEStatsReq *get_stats_param); + +#if defined(QCA_WIFI_FTM) +void wma_utf_detach(tp_wma_handle wma_handle); + +void wma_utf_attach(tp_wma_handle wma_handle); + +CDF_STATUS +wma_process_ftm_command(tp_wma_handle wma_handle, + struct ar6k_testmode_cmd_data *msg_buffer); +#endif + +/* + * wma_features.c functions declarations + */ + +void wma_process_link_status_req(tp_wma_handle wma, + tAniGetLinkStatus *pGetLinkStatus); + +#ifdef FEATURE_WLAN_LPHB +CDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req); + +#endif + +CDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle, + tAniDHCPInd *ta_dhcp_ind); + +WLAN_PHY_MODE wma_chan_to_mode(u8 chan, phy_ch_width chan_width, + u8 vht_capable, u8 dot11_mode); + +CDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed); + +#ifdef FEATURE_GREEN_AP +int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, + uint32_t value); +#endif + +void wma_wow_tx_complete(void *wma); + +int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id); + +int wmi_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id); + +#ifdef WLAN_FEATURE_NAN +int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf, uint32_t len); +#endif + +#ifdef FEATURE_WLAN_TDLS +int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len); +#endif + +int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len); + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +int wma_gtk_offload_status_event(void *handle, uint8_t *event, uint32_t len); +#endif + +#ifdef FEATURE_OEM_DATA_SUPPORT +int wma_oem_capability_event_callback(void *handle, + uint8_t *datap, uint32_t len); + +int wma_oem_measurement_report_event_callback(void *handle, uint8_t *datap, + uint32_t len); + +int wma_oem_error_report_event_callback(void *handle, uint8_t *datap, + uint32_t len); +#endif + +void wma_register_dfs_event_handler(tp_wma_handle wma_handle); + +int +wma_unified_dfs_phyerr_filter_offload_enable(tp_wma_handle wma_handle); + +#if !defined(REMOVE_PKT_LOG) +CDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle, + struct ath_pktlog_wmi_params *params); +#endif + +int wma_wow_wakeup_host_event(void *handle, uint8_t *event, + uint32_t len); +int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len); + +/** + * wma_get_wow_bus_suspend() - check is wow bus suspended or not + * @wma: wma handle + * + * Return: true/false + */ +static inline int wma_get_wow_bus_suspend(tp_wma_handle wma) +{ + + return cdf_atomic_read(&wma->is_wow_bus_suspended); +} + +CDF_STATUS wma_resume_req(tp_wma_handle wma); + +CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, + struct wow_add_pattern *ptrn); + +CDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma, + struct wow_delete_pattern *pattern); + +CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info); + +CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info); + +CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info); + +void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); + +void wma_aggr_qos_req(tp_wma_handle wma, + tAggrAddTsParams *pAggrQosRspMsg); + +void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg); + +int wma_process_receive_filter_set_filter_req(tp_wma_handle wma_handle, + tSirRcvPktFilterCfgType * + rcv_filter_param); + +int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma_handle, + tSirRcvFltPktClearParam * + rcv_clear_param); + +#ifdef FEATURE_OEM_DATA_SUPPORT +void wma_start_oem_data_req(tp_wma_handle wma_handle, + tStartOemDataReq *startOemDataReq); +#endif + +#ifdef FEATURE_WLAN_ESE +CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, + void *pTsmStatsMsg); +#endif + +CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, + tSirRcvFltMcAddrList *mcbc_param); +#ifdef WLAN_FEATURE_GTK_OFFLOAD +CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma, + tpSirGtkOffloadParams params); + +CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma, + tpSirGtkOffloadGetInfoRspParams + params); +#endif + +CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + tpSirHostOffloadReq pHostOffloadParams, + bool bArpOnly); + +CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle, + tSirAddPeriodicTxPtrn * + pAddPeriodicTxPtrnParams); + +CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle, + tSirDelPeriodicTxPtrn * + pDelPeriodicTxPtrnParams); + +#ifdef WLAN_FEATURE_STATS_EXT +CDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq); +#endif + +CDF_STATUS wma_process_ibss_route_table_update_ind(void *wma_handle, + tAniIbssRouteTable *pData); + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +int wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params); + +int wma_set_app_type1_params_in_fw(tp_wma_handle wma, + tpSirAppType1Params appType1Params); + +int wma_set_app_type2_params_in_fw(tp_wma_handle wma, + tpSirAppType2Params appType2Params); +#endif + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +int wma_auto_shutdown_event_handler(void *handle, uint8_t *event, + uint32_t len); + +CDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle, + tSirAutoShutdownCmdParams * + auto_sh_cmd); +#endif + +#ifdef WLAN_FEATURE_NAN + +CDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req); +#endif + +#ifdef DHCP_SERVER_OFFLOAD +int wma_process_dhcpserver_offload(tp_wma_handle wma_handle, + tSirDhcpSrvOffloadInfo * + pDhcpSrvOffloadInfo); +#endif + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +CDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle, + tSirLedFlashingReq *flashing); +#endif + +#ifdef FEATURE_WLAN_CH_AVOID +int wma_channel_avoid_evt_handler(void *handle, uint8_t *event, + uint32_t len); + +CDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle, + tSirChAvoidUpdateReq * + ch_avoid_update_req); +#endif + +int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); + +#ifdef FEATURE_WLAN_TDLS + +int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams); +int wma_update_tdls_peer_state(WMA_HANDLE handle, + tTdlsPeerStateParams *peerStateParams); +/** + * wma_set_tdls_offchan_mode() - set tdls off channel mode + * @handle: wma handle + * @chan_switch_params: Pointer to tdls channel switch parameter structure + * + * This function sets tdls off channel mode + * + * Return: 0 on success; negative errno otherwise + */ +int wma_set_tdls_offchan_mode(WMA_HANDLE wma_handle, + tdls_chan_switch_params *chan_switch_params); +#endif + +struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic); + +void wma_dfs_detach(struct ieee80211com *dfs_ic); + +void wma_dfs_configure(struct ieee80211com *ic); + +struct ieee80211_channel *wma_dfs_configure_channel(struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req + *req); +void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id); + +#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 +int wma_rssi_breached_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len); +#ifdef WLAN_FEATURE_MEMDUMP +int wma_fw_mem_dump_event_handler(void *handle, u_int8_t *cmd_param_info, + u_int32_t len); +CDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma, + struct fw_dump_req *mem_dump_req); +#else +static inline int wma_fw_mem_dump_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + return 0; +} + +static inline CDF_STATUS wma_process_fw_mem_dump_req(tp_wma_handle wma, + void *mem_dump_req) +{ + return CDF_STATUS_SUCCESS; +} +#endif +CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma, + struct vdev_ie_info *ie_info); +int wma_peer_assoc_conf_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); + +#endif diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h new file mode 100644 index 000000000000..eab91f69a892 --- /dev/null +++ b/core/wma/inc/wma_tgt_cfg.h @@ -0,0 +1,167 @@ +/* + * 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 WMA_TGT_CFG_H +#define WMA_TGT_CFG_H + +/** + * struct wma_tgt_services - target services + * @sta_power_save: sta power save + * @uapsd: uapsd + * @ap_dfs: ap dfs + * @en_11ac: enable 11ac + * @arp_offload: arp offload + * @early_rx: early rx + * @pno_offload: pno offload + * @beacon_offload: beacon offload + * @lte_coex_ant_share: LTE coex ant share + * @en_tdls: enable tdls + * @en_tdls_offchan: enable tdls offchan + * @en_tdls_uapsd_buf_sta: enable sta tdls uapsd buf + * @en_tdls_uapsd_sleep_sta: enable sta tdls uapsd sleep + * @en_roam_offload: enable roam offload + */ +struct wma_tgt_services { + uint32_t sta_power_save; + uint32_t uapsd; + uint32_t ap_dfs; + uint32_t en_11ac; + uint32_t arp_offload; + uint32_t early_rx; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_offload; +#endif /* FEATURE_WLAN_SCAN_PNO */ + bool beacon_offload; + uint32_t lte_coex_ant_share; +#ifdef FEATURE_WLAN_TDLS + bool en_tdls; + bool en_tdls_offchan; + bool en_tdls_uapsd_buf_sta; + bool en_tdls_uapsd_sleep_sta; +#endif /* FEATURE_WLAN_TDLS */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + bool en_roam_offload; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +}; + +/** + * struct wma_tgt_ht_cap - ht capabalitiy + * @mpdu_density: mpdu density + * @ht_rx_stbc: ht rx stbc + * @ht_tx_stbc: ht tx stbc + * @ht_rx_ldpc: ht rx ldpc + * @ht_sgi_20: ht sgi 20 + * @ht_sgi_40: ht sgi 40 + * @num_rf_chains: num of rf chains + */ +struct wma_tgt_ht_cap { + uint32_t mpdu_density; + bool ht_rx_stbc; + bool ht_tx_stbc; + bool ht_rx_ldpc; + bool ht_sgi_20; + bool ht_sgi_40; + uint32_t num_rf_chains; +}; + +#ifdef WLAN_FEATURE_11AC +/** + * struct wma_tgt_vht_cap - vht capabalities + * @vht_max_mpdu: vht max mpdu + * @supp_chan_width: supported channel width + * @vht_rx_ldpc: vht rx ldpc + * @vht_short_gi_80: vht short gi 80 + * @vht_short_gi_160: vht short gi 160 + * @vht_tx_stbc: vht tx stbc + * @vht_rx_stbc: vht rx stbc + * @vht_su_bformer: vht su bformer + * @vht_su_bformee: vht su bformee + * @vht_mu_bformer: vht mu bformer + * @vht_mu_bformee: vht mu bformee + * @vht_max_ampdu_len_exp: vht max ampdu len exp + * @vht_txop_ps: vht txop ps + */ +struct wma_tgt_vht_cap { + uint32_t vht_max_mpdu; + uint32_t supp_chan_width; + uint32_t vht_rx_ldpc; + uint32_t vht_short_gi_80; + uint32_t vht_short_gi_160; + uint32_t vht_tx_stbc; + uint32_t vht_rx_stbc; + uint32_t vht_su_bformer; + uint32_t vht_su_bformee; + uint32_t vht_mu_bformer; + uint32_t vht_mu_bformee; + uint32_t vht_max_ampdu_len_exp; + uint32_t vht_txop_ps; +}; +#endif /* WLAN_FEATURE_11AC */ + +/** + * struct wma_dfs_radar_ind - dfs radar indication + * @ieee_chan_number: ieee channel number + * @chan_freq: channel freq + * @dfs_radar_status: dfs radar status + */ +struct wma_dfs_radar_ind { + uint8_t ieee_chan_number; + uint32_t chan_freq; + uint32_t dfs_radar_status; +}; + +/** + * struct wma_tgt_cfg - target config + * @target_fw_version: target fw version + * @band_cap: band capability + * @reg_domain: reg domain + * @eeprom_rd_ext: eeprom rd ext + * @hw_macaddr: hw mcast addr + * @services: struct wma_tgt_services + * @ht_cap: struct wma_tgt_ht_cap + * @vht_cap: struct wma_tgt_vht_cap + * @max_intf_count: max interface count + * @lpss_support: lpass support + */ +struct wma_tgt_cfg { + uint32_t target_fw_version; + uint8_t band_cap; + uint32_t reg_domain; + uint32_t eeprom_rd_ext; + struct cdf_mac_addr hw_macaddr; + struct wma_tgt_services services; + struct wma_tgt_ht_cap ht_cap; +#ifdef WLAN_FEATURE_11AC + struct wma_tgt_vht_cap vht_cap; +#endif + uint8_t max_intf_count; +#ifdef WLAN_FEATURE_LPSS + uint8_t lpss_support; +#endif + uint8_t ap_arpns_support; +}; +#endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h new file mode 100644 index 000000000000..5f0a1883caa9 --- /dev/null +++ b/core/wma/inc/wma_types.h @@ -0,0 +1,679 @@ +/* + * 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_WMA_H +#define WLAN_QCT_WMA_H + +#include "ani_global.h" + +#include "wma_api.h" +#include "wma_tgt_cfg.h" +#include "i_cds_packet.h" + +#define IS_MCC_SUPPORTED 1 +#define IS_FEATURE_SUPPORTED_BY_FW(feat_enum_value) wma_get_fw_wlan_feat_caps(feat_enum_value) + +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 1 + +#define IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE 1 + +#ifdef FEATURE_WLAN_TDLS +#define IS_ADVANCE_TDLS_ENABLE 0 +#endif + +#ifdef WLAN_SOFTAP_VSTA_FEATURE +#define WMA_MAX_STA (41) +#else +#define WMA_MAX_STA (16) +#endif + +#define WMA_NVDownload_Start(x) ({ CDF_STATUS_SUCCESS; }) + +#define DPU_FEEDBACK_UNPROTECTED_ERROR 0x0F + +#define WMA_GET_RX_MAC_HEADER(pRxMeta) \ + (tpSirMacMgmtHdr)(((t_packetmeta *)pRxMeta)->mpdu_hdr_ptr) + +#define WMA_GET_RX_MPDUHEADER3A(pRxMeta) \ + (tpSirMacDataHdr3a)(((t_packetmeta *)pRxMeta)->mpdu_hdr_ptr) + +#define WMA_GET_RX_MPDU_HEADER_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_hdr_len) + +#define WMA_GET_RX_MPDU_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_len) + +#define WMA_GET_RX_PAYLOAD_LEN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_data_len) + +#define WMA_GET_RX_TSF_DELTA(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->tsf_delta) + +#define WMA_GET_RX_MAC_RATE_IDX(pRxMeta) 0 + +#define WMA_GET_RX_MPDU_DATA(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->mpdu_data_ptr) + +#define WMA_GET_RX_MPDU_HEADER_OFFSET(pRxMeta) 0 + +#define WMA_GET_RX_UNKNOWN_UCAST(pRxMeta) 0 + +#define WMA_GET_RX_CH(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->channel) + +#define WMA_IS_RX_BCAST(pRxMeta) 0 + +#define WMA_GET_RX_FT_DONE(pRxMeta) 0 + +#define WMA_GET_RX_DPU_FEEDBACK(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->dpuFeedback) + +#define WMA_GET_RX_BEACON_SENT(pRxMeta) 0 + +#define WMA_GET_RX_TSF_LATER(pRxMeta) 0 + +#define WMA_GET_RX_TIMESTAMP(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->timestamp) + +#define WMA_IS_RX_IN_SCAN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->scan) + +#define WMA_GET_OFFLOADSCANLEARN(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->offloadScanLearn) +#define WMA_GET_ROAMCANDIDATEIND(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->roamCandidateInd) +#define WMA_GET_SESSIONID(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->sessionId) +#define WMA_GET_SCAN_SRC(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->scan_src) + +#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 WMA_GET_RX_SNR(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->snr) + +#define WMA_GET_RX_RFBAND(pRxMeta) 0 + +#define WMA_MAX_TXPOWER_INVALID 127 +#define WMA_GET_RX_RSSI_DB(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->rssi) + +/* WMA Messages */ +#define WMA_MSG_TYPES_BEGIN SIR_HAL_MSG_TYPES_BEGIN +#define WMA_ITC_MSG_TYPES_BEGIN SIR_HAL_ITC_MSG_TYPES_BEGIN +#define WMA_RADAR_DETECTED_IND SIR_HAL_RADAR_DETECTED_IND + +#define WMA_ADD_STA_REQ SIR_HAL_ADD_STA_REQ +#define WMA_ADD_STA_RSP SIR_HAL_ADD_STA_RSP +#define WMA_ADD_STA_SELF_RSP SIR_HAL_ADD_STA_SELF_RSP +#define WMA_DELETE_STA_REQ SIR_HAL_DELETE_STA_REQ +#define WMA_DELETE_STA_RSP SIR_HAL_DELETE_STA_RSP +#define WMA_ADD_BSS_REQ SIR_HAL_ADD_BSS_REQ +#define WMA_ADD_BSS_RSP SIR_HAL_ADD_BSS_RSP +#define WMA_DELETE_BSS_REQ SIR_HAL_DELETE_BSS_REQ +#define WMA_DELETE_BSS_RSP SIR_HAL_DELETE_BSS_RSP +#define WMA_SEND_BEACON_REQ SIR_HAL_SEND_BEACON_REQ +#define WMA_SEND_PROBE_RSP_TMPL SIR_HAL_SEND_PROBE_RSP_TMPL + +#define WMA_SET_BSSKEY_REQ SIR_HAL_SET_BSSKEY_REQ +#define WMA_SET_BSSKEY_RSP SIR_HAL_SET_BSSKEY_RSP +#define WMA_SET_STAKEY_REQ SIR_HAL_SET_STAKEY_REQ +#define WMA_SET_STAKEY_RSP SIR_HAL_SET_STAKEY_RSP +#define WMA_UPDATE_EDCA_PROFILE_IND SIR_HAL_UPDATE_EDCA_PROFILE_IND + +#define WMA_UPDATE_BEACON_IND SIR_HAL_UPDATE_BEACON_IND +#define WMA_UPDATE_CF_IND SIR_HAL_UPDATE_CF_IND +#define WMA_CHNL_SWITCH_REQ SIR_HAL_CHNL_SWITCH_REQ +#define WMA_ADD_TS_REQ SIR_HAL_ADD_TS_REQ +#define WMA_DEL_TS_REQ SIR_HAL_DEL_TS_REQ + +#define WMA_MISSED_BEACON_IND SIR_HAL_MISSED_BEACON_IND + +#define WMA_ENTER_PS_REQ SIR_HAL_ENTER_PS_REQ +#define WMA_EXIT_PS_REQ SIR_HAL_EXIT_PS_REQ + +#define WMA_CFG_RXP_FILTER_REQ SIR_HAL_CFG_RXP_FILTER_REQ + +#define WMA_SWITCH_CHANNEL_RSP SIR_HAL_SWITCH_CHANNEL_RSP +#define WMA_P2P_NOA_ATTR_IND SIR_HAL_P2P_NOA_ATTR_IND +#define WMA_P2P_NOA_START_IND SIR_HAL_P2P_NOA_START_IND +#define WMA_PWR_SAVE_CFG SIR_HAL_PWR_SAVE_CFG +#define WMA_REGISTER_PE_CALLBACK SIR_HAL_REGISTER_PE_CALLBACK + +#define WMA_IBSS_STA_ADD SIR_HAL_IBSS_STA_ADD +#define WMA_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND SIR_HAL_TIMER_ADJUST_ADAPTIVE_THRESHOLD_IND +#define WMA_SET_LINK_STATE SIR_HAL_SET_LINK_STATE +#define WMA_SET_LINK_STATE_RSP SIR_HAL_SET_LINK_STATE_RSP +#define WMA_SET_STA_BCASTKEY_REQ SIR_HAL_SET_STA_BCASTKEY_REQ +#define WMA_SET_STA_BCASTKEY_RSP SIR_HAL_SET_STA_BCASTKEY_RSP +#define WMA_ADD_TS_RSP SIR_HAL_ADD_TS_RSP +#define WMA_DPU_MIC_ERROR SIR_HAL_DPU_MIC_ERROR +#define WMA_TIMER_CHIP_MONITOR_TIMEOUT SIR_HAL_TIMER_CHIP_MONITOR_TIMEOUT +#define WMA_TIMER_TRAFFIC_ACTIVITY_REQ SIR_HAL_TIMER_TRAFFIC_ACTIVITY_REQ +#define WMA_TIMER_ADC_RSSI_STATS SIR_HAL_TIMER_ADC_RSSI_STATS +#define WMA_TIMER_TRAFFIC_STATS_IND SIR_HAL_TRAFFIC_STATS_IND + +#ifdef WLAN_FEATURE_11W +#define WMA_EXCLUDE_UNENCRYPTED_IND SIR_HAL_EXCLUDE_UNENCRYPTED_IND +#endif + +#ifdef FEATURE_WLAN_ESE +#define WMA_TSM_STATS_REQ SIR_HAL_TSM_STATS_REQ +#define WMA_TSM_STATS_RSP SIR_HAL_TSM_STATS_RSP +#endif + +#define WMA_SET_MIMOPS_REQ SIR_HAL_SET_MIMOPS_REQ +#define WMA_SET_MIMOPS_RSP SIR_HAL_SET_MIMOPS_RSP +#define WMA_SYS_READY_IND SIR_HAL_SYS_READY_IND +#define WMA_SET_TX_POWER_REQ SIR_HAL_SET_TX_POWER_REQ +#define WMA_SET_TX_POWER_RSP SIR_HAL_SET_TX_POWER_RSP +#define WMA_GET_TX_POWER_REQ SIR_HAL_GET_TX_POWER_REQ + +/* Messages to support transmit_halt and transmit_resume */ +#define WMA_TRANSMISSION_CONTROL_IND SIR_HAL_TRANSMISSION_CONTROL_IND +#define WMA_BEACON_FILTER_IND SIR_HAL_BEACON_FILTER_IND + +#define WMA_ENABLE_UAPSD_REQ SIR_HAL_ENABLE_UAPSD_REQ +#define WMA_DISABLE_UAPSD_REQ SIR_HAL_DISABLE_UAPSD_REQ + +/* / PE <-> HAL WOWL messages */ +#define WMA_WOW_ADD_PTRN SIR_HAL_WOW_ADD_PTRN +#define WMA_WOW_DEL_PTRN SIR_HAL_WOW_DEL_PTRN +#define WMA_WOWL_ENTER_REQ SIR_HAL_WOWL_ENTER_REQ +#define WMA_WOWL_ENTER_RSP SIR_HAL_WOWL_ENTER_RSP +#define WMA_WOWL_EXIT_REQ SIR_HAL_WOWL_EXIT_REQ +#define WMA_WOWL_EXIT_RSP SIR_HAL_WOWL_EXIT_RSP +/* / PE <-> HAL statistics messages */ +#define WMA_GET_STATISTICS_REQ SIR_HAL_GET_STATISTICS_REQ +#define WMA_GET_STATISTICS_RSP SIR_HAL_GET_STATISTICS_RSP +#define WMA_SET_KEY_DONE SIR_HAL_SET_KEY_DONE + +/* / PE <-> HAL BTC messages */ +#define WMA_BTC_SET_CFG SIR_HAL_BTC_SET_CFG +#define WMA_HANDLE_FW_MBOX_RSP SIR_HAL_HANDLE_FW_MBOX_RSP + +#ifdef FEATURE_OEM_DATA_SUPPORT +/* PE <-> HAL OEM_DATA RELATED MESSAGES */ +#define WMA_START_OEM_DATA_REQ SIR_HAL_START_OEM_DATA_REQ +#define WMA_START_OEM_DATA_RSP SIR_HAL_START_OEM_DATA_RSP +#endif + +#define WMA_SET_MAX_TX_POWER_REQ SIR_HAL_SET_MAX_TX_POWER_REQ +#define WMA_SET_MAX_TX_POWER_RSP SIR_HAL_SET_MAX_TX_POWER_RSP +#define WMA_SET_TX_POWER_REQ SIR_HAL_SET_TX_POWER_REQ + +#define WMA_SET_MAX_TX_POWER_PER_BAND_REQ \ + SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ + +/* / PE <-> HAL Host Offload message */ +#define WMA_SET_HOST_OFFLOAD SIR_HAL_SET_HOST_OFFLOAD + +/* / PE <-> HAL Keep Alive message */ +#define WMA_SET_KEEP_ALIVE SIR_HAL_SET_KEEP_ALIVE + +#ifdef WLAN_NS_OFFLOAD +#define WMA_SET_NS_OFFLOAD SIR_HAL_SET_NS_OFFLOAD +#endif /* WLAN_NS_OFFLOAD */ +#define WMA_ADD_STA_SELF_REQ SIR_HAL_ADD_STA_SELF_REQ +#define WMA_DEL_STA_SELF_REQ SIR_HAL_DEL_STA_SELF_REQ + +#define WMA_SET_P2P_GO_NOA_REQ SIR_HAL_SET_P2P_GO_NOA_REQ + +#ifdef FEATURE_WLAN_TDLS +#define WMA_SET_TDLS_LINK_ESTABLISH_REQ SIR_HAL_TDLS_LINK_ESTABLISH_REQ +#define WMA_SET_TDLS_LINK_ESTABLISH_REQ_RSP SIR_HAL_TDLS_LINK_ESTABLISH_REQ_RSP +#endif + +#define WMA_WLAN_SUSPEND_IND SIR_HAL_WLAN_SUSPEND_IND +#define WMA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ +#define WMA_MSG_TYPES_END SIR_HAL_MSG_TYPES_END + +#ifdef WLAN_FEATURE_VOWIFI_11R +#define WMA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ +#define WMA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP +#endif /* WLAN_FEATURE_VOWIFI_11R */ + +/* FTM CMD MSG */ +#define WMA_FTM_CMD_REQ SIR_PTT_MSG_TYPES_BEGIN +#define WMA_FTM_CMD_RSP SIR_PTT_MSG_TYPES_END +#define WMA_CSA_OFFLOAD_EVENT SIR_CSA_OFFLOAD_EVENT + +#ifdef FEATURE_WLAN_SCAN_PNO +/*Requests sent to lower driver*/ +#define WMA_SET_PNO_REQ SIR_HAL_SET_PNO_REQ + +#endif /* FEATURE_WLAN_SCAN_PNO */ + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) +#define WMA_SET_PLM_REQ SIR_HAL_SET_PLM_REQ +#endif + +#define WMA_ROAM_SCAN_OFFLOAD_REQ SIR_HAL_ROAM_SCAN_OFFLOAD_REQ + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define WMA_ROAM_OFFLOAD_SYNCH_CNF SIR_HAL_ROAM_OFFLOAD_SYNCH_CNF +#define WMA_ROAM_OFFLOAD_SYNCH_IND SIR_HAL_ROAM_OFFLOAD_SYNCH_IND +#define WMA_ROAM_OFFLOAD_SYNCH_FAIL SIR_HAL_ROAM_OFFLOAD_SYNCH_FAIL +#endif + +#ifdef WLAN_FEATURE_PACKET_FILTERING +#define WMA_8023_MULTICAST_LIST_REQ SIR_HAL_8023_MULTICAST_LIST_REQ +#define WMA_RECEIVE_FILTER_SET_FILTER_REQ SIR_HAL_RECEIVE_FILTER_SET_FILTER_REQ +#define WMA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ +#define WMA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP SIR_HAL_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP +#define WMA_RECEIVE_FILTER_CLEAR_FILTER_REQ SIR_HAL_RECEIVE_FILTER_CLEAR_FILTER_REQ +#endif /* WLAN_FEATURE_PACKET_FILTERING */ + +#define WMA_DHCP_START_IND SIR_HAL_DHCP_START_IND +#define WMA_DHCP_STOP_IND SIR_HAL_DHCP_STOP_IND + +#define WMA_HIDDEN_SSID_VDEV_RESTART SIR_HAL_HIDE_SSID_VDEV_RESTART + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define WMA_GTK_OFFLOAD_REQ SIR_HAL_GTK_OFFLOAD_REQ +#define WMA_GTK_OFFLOAD_GETINFO_REQ SIR_HAL_GTK_OFFLOAD_GETINFO_REQ +#define WMA_GTK_OFFLOAD_GETINFO_RSP SIR_HAL_GTK_OFFLOAD_GETINFO_RSP +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + +#define WMA_SET_TM_LEVEL_REQ SIR_HAL_SET_TM_LEVEL_REQ + +#ifdef WLAN_FEATURE_11AC +#define WMA_UPDATE_OP_MODE SIR_HAL_UPDATE_OP_MODE +#define WMA_UPDATE_RX_NSS SIR_HAL_UPDATE_RX_NSS +#define WMA_UPDATE_MEMBERSHIP SIR_HAL_UPDATE_MEMBERSHIP +#define WMA_UPDATE_USERPOS SIR_HAL_UPDATE_USERPOS +#endif + +#ifdef WLAN_FEATURE_NAN +#define WMA_NAN_REQUEST SIR_HAL_NAN_REQUEST +#endif + +#define WMA_START_SCAN_OFFLOAD_REQ SIR_HAL_START_SCAN_OFFLOAD_REQ +#define WMA_STOP_SCAN_OFFLOAD_REQ SIR_HAL_STOP_SCAN_OFFLOAD_REQ +#define WMA_UPDATE_CHAN_LIST_REQ SIR_HAL_UPDATE_CHAN_LIST_REQ +#define WMA_RX_SCAN_EVENT SIR_HAL_RX_SCAN_EVENT +#define WMA_IBSS_PEER_INACTIVITY_IND SIR_HAL_IBSS_PEER_INACTIVITY_IND + +#define WMA_CLI_SET_CMD SIR_HAL_CLI_SET_CMD +#ifdef FEATURE_WLAN_SCAN_PNO +#define WMA_SME_SCAN_CACHE_UPDATED SIR_HAL_SME_SCAN_CACHE_UPDATED +#endif + +#ifndef REMOVE_PKT_LOG +#define WMA_PKTLOG_ENABLE_REQ SIR_HAL_PKTLOG_ENABLE_REQ +#endif + +#ifdef FEATURE_WLAN_LPHB +#define WMA_LPHB_CONF_REQ SIR_HAL_LPHB_CONF_IND +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_CH_AVOID +#define WMA_CH_AVOID_UPDATE_REQ SIR_HAL_CH_AVOID_UPDATE_REQ +#endif /* FEATURE_WLAN_CH_AVOID */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +#define WMA_SET_AUTO_SHUTDOWN_TIMER_REQ SIR_HAL_SET_AUTO_SHUTDOWN_TIMER_REQ +#endif + +#define WMA_ADD_PERIODIC_TX_PTRN_IND SIR_HAL_ADD_PERIODIC_TX_PTRN_IND +#define WMA_DEL_PERIODIC_TX_PTRN_IND SIR_HAL_DEL_PERIODIC_TX_PTRN_IND + +#define WMA_TX_POWER_LIMIT SIR_HAL_SET_TX_POWER_LIMIT + +#define WMA_RATE_UPDATE_IND SIR_HAL_RATE_UPDATE_IND + +#define WMA_INIT_THERMAL_INFO_CMD SIR_HAL_INIT_THERMAL_INFO_CMD +#define WMA_SET_THERMAL_LEVEL SIR_HAL_SET_THERMAL_LEVEL + +#ifdef FEATURE_WLAN_TDLS +#define WMA_UPDATE_FW_TDLS_STATE SIR_HAL_UPDATE_FW_TDLS_STATE +#define WMA_UPDATE_TDLS_PEER_STATE SIR_HAL_UPDATE_TDLS_PEER_STATE +#define WMA_TDLS_SHOULD_DISCOVER_CMD SIR_HAL_TDLS_SHOULD_DISCOVER +#define WMA_TDLS_SHOULD_TEARDOWN_CMD SIR_HAL_TDLS_SHOULD_TEARDOWN +#define WMA_TDLS_PEER_DISCONNECTED_CMD SIR_HAL_TDLS_PEER_DISCONNECTED +#define WMA_TDLS_SET_OFFCHAN_MODE SIR_HAL_TDLS_SET_OFFCHAN_MODE +#endif +#define WMA_SET_SAP_INTRABSS_DIS SIR_HAL_SET_SAP_INTRABSS_DIS + +/* Message to Indicate Radar Presence on SAP Channel */ +#define WMA_DFS_RADAR_IND SIR_HAL_DFS_RADAR_IND + +/* Message to indicate beacon tx completion after beacon template update + * beacon offload case + */ +#define WMA_DFS_BEACON_TX_SUCCESS_IND SIR_HAL_BEACON_TX_SUCCESS_IND +#define WMA_DISASSOC_TX_COMP SIR_HAL_DISASSOC_TX_COMP +#define WMA_DEAUTH_TX_COMP SIR_HAL_DEAUTH_TX_COMP +#define WMA_GET_LINK_SPEED SIR_HAL_GET_LINK_SPEED + +#define WMA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND + +#ifdef WLAN_FEATURE_STATS_EXT +#define WMA_STATS_EXT_REQUEST SIR_HAL_STATS_EXT_REQUEST +#endif + +#define WMA_IPA_OFFLOAD_ENABLE_DISABLE SIR_HAL_IPA_OFFLOAD_ENABLE_DISABLE + +#define WMA_GET_TEMPERATURE_REQ SIR_HAL_GET_TEMPERATURE_REQ + +#ifdef FEATURE_WLAN_EXTSCAN +#define WMA_EXTSCAN_GET_CAPABILITIES_REQ SIR_HAL_EXTSCAN_GET_CAPABILITIES_REQ +#define WMA_EXTSCAN_START_REQ SIR_HAL_EXTSCAN_START_REQ +#define WMA_EXTSCAN_STOP_REQ SIR_HAL_EXTSCAN_STOP_REQ +#define WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_REQ +#define WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_REQ +#define WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ SIR_HAL_EXTSCAN_SET_SIGNF_CHANGE_REQ +#define WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ SIR_HAL_EXTSCAN_RESET_SIGNF_CHANGE_REQ +#define WMA_EXTSCAN_GET_CACHED_RESULTS_REQ SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_REQ +#define WMA_SET_EPNO_LIST_REQ SIR_HAL_SET_EPNO_LIST_REQ +#define WMA_SET_PASSPOINT_LIST_REQ SIR_HAL_SET_PASSPOINT_LIST_REQ +#define WMA_RESET_PASSPOINT_LIST_REQ SIR_HAL_RESET_PASSPOINT_LIST_REQ +#define WMA_EXTSCAN_SET_SSID_HOTLIST_REQ SIR_HAL_EXTSCAN_SET_SSID_HOTLIST_REQ + +#endif /* FEATURE_WLAN_EXTSCAN */ + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +#define WMA_LINK_LAYER_STATS_CLEAR_REQ SIR_HAL_LL_STATS_CLEAR_REQ +#define WMA_LINK_LAYER_STATS_SET_REQ SIR_HAL_LL_STATS_SET_REQ +#define WMA_LINK_LAYER_STATS_GET_REQ SIR_HAL_LL_STATS_GET_REQ +#define WMA_LINK_LAYER_STATS_RESULTS_RSP SIR_HAL_LL_STATS_RESULTS_RSP +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#define WMA_LINK_STATUS_GET_REQ SIR_HAL_LINK_STATUS_GET_REQ + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +#define WMA_WLAN_EXT_WOW SIR_HAL_CONFIG_EXT_WOW +#define WMA_WLAN_SET_APP_TYPE1_PARAMS SIR_HAL_CONFIG_APP_TYPE1_PARAMS +#define WMA_WLAN_SET_APP_TYPE2_PARAMS SIR_HAL_CONFIG_APP_TYPE2_PARAMS +#endif + +#define WMA_SET_SCAN_MAC_OUI_REQ SIR_HAL_SET_SCAN_MAC_OUI_REQ + +#ifdef DHCP_SERVER_OFFLOAD +#define WMA_SET_DHCP_SERVER_OFFLOAD_CMD SIR_HAL_SET_DHCP_SERVER_OFFLOAD +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING +#define WMA_LED_FLASHING_REQ SIR_HAL_LED_FLASHING_REQ +#endif + +/* Message posted by wmi when wmi event is received from FW */ +#define WMA_PROCESS_FW_EVENT SIR_HAL_PROCESS_FW_EVENT + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE +#define WMA_UPDATE_Q2Q_IE_IND SIR_HAL_UPDATE_Q2Q_IE_IND +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ +#define WMA_SET_RSSI_MONITOR_REQ SIR_HAL_SET_RSSI_MONITOR_REQ + +#define WMA_FW_MEM_DUMP_REQ SIR_HAL_FW_MEM_DUMP_REQ + +#define WMA_OCB_SET_CONFIG_CMD SIR_HAL_OCB_SET_CONFIG_CMD +#define WMA_OCB_SET_UTC_TIME_CMD SIR_HAL_OCB_SET_UTC_TIME_CMD +#define WMA_OCB_START_TIMING_ADVERT_CMD SIR_HAL_OCB_START_TIMING_ADVERT_CMD +#define WMA_OCB_STOP_TIMING_ADVERT_CMD SIR_HAL_OCB_STOP_TIMING_ADVERT_CMD +#define WMA_OCB_GET_TSF_TIMER_CMD SIR_HAL_OCB_GET_TSF_TIMER_CMD +#define WMA_DCC_GET_STATS_CMD SIR_HAL_DCC_GET_STATS_CMD +#define WMA_DCC_CLEAR_STATS_CMD SIR_HAL_DCC_CLEAR_STATS_CMD +#define WMA_DCC_UPDATE_NDL_CMD SIR_HAL_DCC_UPDATE_NDL_CMD +#define WMA_SET_IE_INFO SIR_HAL_SET_IE_INFO + +#define WMA_LRO_CONFIG_CMD SIR_HAL_LRO_CONFIG_CMD + +/* Bit 6 will be used to control BD rate for Management frames */ +#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 + +#define wma_tx_frame(hHal, pFrmBuf, frmLen, frmType, txDir, tid, pCompFunc, \ + pData, txFlag, sessionid, channel_freq) \ + (CDF_STATUS)( wma_tx_packet( \ + cds_get_context(CDF_MODULE_ID_WMA), \ + (pFrmBuf), \ + (frmLen), \ + (frmType), \ + (txDir), \ + (tid), \ + (pCompFunc), \ + (pData), \ + (NULL), \ + (txFlag), \ + (sessionid), \ + (false), \ + (channel_freq))) + +#define wma_tx_frameWithTxComplete(hHal, pFrmBuf, frmLen, frmType, txDir, tid, \ + pCompFunc, pData, pCBackFnTxComp, txFlag, sessionid, tdlsflag, \ + channel_freq) \ + (CDF_STATUS)( wma_tx_packet( \ + cds_get_context(CDF_MODULE_ID_WMA), \ + (pFrmBuf), \ + (frmLen), \ + (frmType), \ + (txDir), \ + (tid), \ + (pCompFunc), \ + (pData), \ + (pCBackFnTxComp), \ + (txFlag), \ + (sessionid), \ + (tdlsflag), \ + (channel_freq))) + + +#define WMA_SetEnableSSR(enable_ssr) ((void)enable_ssr) + +/** + * struct sUapsd_Params - Powersave Offload Changes + * @bkDeliveryEnabled: BK delivery enabled flag + * @beDeliveryEnabled: BE delivery enabled flag + * @viDeliveryEnabled: VI delivery enabled flag + * @voDeliveryEnabled: VO delivery enabled flag + * @bkTriggerEnabled: BK trigger enabled flag + * @beTriggerEnabled: BE trigger enabled flag + * @viTriggerEnabled: VI trigger enabled flag + * @voTriggerEnabled: VO trigger enabled flag + */ +typedef struct sUapsd_Params { + uint8_t bkDeliveryEnabled:1; + uint8_t beDeliveryEnabled:1; + uint8_t viDeliveryEnabled:1; + uint8_t voDeliveryEnabled:1; + uint8_t bkTriggerEnabled:1; + uint8_t beTriggerEnabled:1; + uint8_t viTriggerEnabled:1; + uint8_t voTriggerEnabled:1; +} tUapsd_Params, *tpUapsd_Params; + +/** + * struct sEnablePsParams - Enable PowerSave Params + * @psSetting: power save setting + * @uapsdParams: UAPSD Parameters + * @bssid: mac address + * @sessionid: sme session id / vdev id + * @bcnDtimPeriod: beacon DTIM Period + * @status: success/failure + */ +typedef struct sEnablePsParams { + tSirAddonPsReq psSetting; + tUapsd_Params uapsdParams; + tSirMacAddr bssid; + uint32_t sessionid; + uint8_t bcnDtimPeriod; + uint32_t status; +} tEnablePsParams, *tpEnablePsParams; + +/** + * struct sDisablePsParams - Disable PowerSave Params + * @psSetting: power save setting + * @bssid: mac address + * @sessionid: sme session id / vdev id + * @status: success/failure + */ +typedef struct sDisablePsParams { + tSirAddonPsReq psSetting; + tSirMacAddr bssid; + uint32_t sessionid; + uint32_t status; +} tDisablePsParams, *tpDisablePsParams; + +/** + * struct sEnableUapsdParams - Enable Uapsd Params + * @uapsdParams: UAPSD parameters + * @bssid: mac address + * @sessionid: sme session id/ vdev id + * @status: success/failure + */ +typedef struct sEnableUapsdParams { + tUapsd_Params uapsdParams; + tSirMacAddr bssid; + uint32_t sessionid; + uint32_t status; +} tEnableUapsdParams, *tpEnableUapsdParams; + +/** + * struct sDisableUapsdParams - Disable Uapsd Params + * @bssid: mac address + * @sessionid: sme session id/ vdev id + * @status: success/failure + */ +typedef struct sDisableUapsdParams { + tSirMacAddr bssid; + uint32_t sessionid; + uint32_t status; +} tDisableUapsdParams, *tpDisableUapsdParams; + +typedef void (*pWMATxRxCompFunc)(void *pContext, void *pData, + bool bFreeData); + +/* callback function for TX complete */ +/* parameter 1 - global pMac pointer */ +/* parameter 2 - txComplete status : 1- success, 0 - failure. */ +typedef CDF_STATUS (*pWMAAckFnTxComp)(tpAniSirGlobal, uint32_t); + +/* generic callback for updating parameters from target to UMAC */ +typedef void (*wma_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 void (*wma_dfs_radar_indication_cb)(void *context, void *param); + +/** + * struct wma_cli_set_cmd_t - set command parameters + * @param_id: parameter id + * @param_value: parameter value + * @param_sec_value: parameter sec value + * @param_vdev_id: parameter vdev id + * @param_vp_dev: is it per vdev/pdev + */ +typedef struct { + uint32_t param_id; + uint32_t param_value; + uint32_t param_sec_value; + uint32_t param_vdev_id; + uint32_t param_vp_dev; +} wma_cli_set_cmd_t; + +#if defined(QCA_WIFI_FTM) +#define AR6K_TM_DATA_MAX_LEN 5000 +struct ar6k_testmode_cmd_data { + void *data; + int len; +}; +#endif + +#ifdef FEATURE_WLAN_TDLS +/** + * enum WMA_TdlsPeerState - TDLS PEER state + * @WMA_TDLS_PEER_STATE_PEERING: peer is making connection + * @WMA_TDLS_PEER_STATE_CONNECTED: peer is connected + * @WMA_TDLS_PEER_STATE_TEARDOWN: peer is teardown + */ +typedef enum { + WMA_TDLS_PEER_STATE_PEERING, + WMA_TDLS_PEER_STATE_CONNECTED, + WMA_TDLS_PEER_STATE_TEARDOWN, +} WMA_TdlsPeerState; + +/** + * enum wma_tdls_off_chan_mode - modes for WMI_TDLS_SET_OFFCHAN_MODE_CMDID + * @WMA_TDLS_ENABLE_OFFCHANNEL: enable off channel + * @WMA_TDLS_DISABLE_OFFCHANNEL: disable off channel + */ +typedef enum { + WMA_TDLS_ENABLE_OFFCHANNEL, + WMA_TDLS_DISABLE_OFFCHANNEL +} wma_tdls_off_chan_mode; + +#endif /* FEATURE_WLAN_TDLS */ + +tSirRetStatus wma_post_ctrl_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); + +tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb); + +CDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps); +CDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req); + +CDF_STATUS +wma_ds_peek_rx_packet_info + (cds_pkt_t *vosDataBuff, void **ppRxHeader, bool bSwap); + + +void wma_tx_abort(uint8_t vdev_id); + +CDF_STATUS wma_tx_packet(void *pWMA, + void *pFrmBuf, + uint16_t frmLen, + eFrameType frmType, + eFrameTxDir txDir, + uint8_t tid, + pWMATxRxCompFunc pCompFunc, + void *pData, + pWMAAckFnTxComp pAckTxComp, + uint8_t txFlag, uint8_t sessionId, bool tdlsflag, + uint16_t channel_freq); + +CDF_STATUS wma_open(void *p_cds_context, + wma_tgt_cfg_cb pTgtUpdCB, + wma_dfs_radar_indication_cb radar_ind_cb, + tMacOpenParameters *pMacParams); + +typedef CDF_STATUS (*wma_mgmt_frame_rx_callback)(void *p_cds_gctx, + void *cds_buff); + +CDF_STATUS wma_register_mgmt_frm_client(void *p_cds_gctx, + wma_mgmt_frame_rx_callback mgmt_rx_cb); + +CDF_STATUS wma_de_register_mgmt_frm_client(void *p_cds_gctx); + + +#endif diff --git a/core/wma/src/wlan_qct_wma_legacy.c b/core/wma/src/wlan_qct_wma_legacy.c new file mode 100644 index 000000000000..e11d46ece7e6 --- /dev/null +++ b/core/wma/src/wlan_qct_wma_legacy.c @@ -0,0 +1,157 @@ +/* + * 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: wlan_qct_wma_legacy.c + * + * 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. + * + */ + +/* Standard include files */ +/* Application Specific include files */ +#include "lim_api.h" +#include "cfg_api.h" +#include "wma.h" +#include "sme_power_save_api.h" +/* Locally used Defines */ + +#define HAL_MMH_MB_MSG_TYPE_MASK 0xFF00 + +/** + * wma_post_ctrl_msg() - Posts WMA messages to MC thread + * @pMac: MAC parameters structure + * @pMsg: pointer with message + * + * Return: Success or Failure + */ + +tSirRetStatus wma_post_ctrl_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_WMA, (cds_msg_t *) pMsg)) + return eSIR_FAILURE; + else + return eSIR_SUCCESS; +} + +/** + * wma_post_cfg_msg() - Posts MNT messages to gSirMntMsgQ + * @pMac: MAC parameters structure + * @pMsg: A pointer to the msg + * + * Return: Success or Failure + */ + +tSirRetStatus wma_post_cfg_msg(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 + */ + + cfg_process_mb_msg(pMac, (tSirMbMsg *) pMsg->bodyptr); + rc = eSIR_SUCCESS; + } while (0); + + return rc; +} + +/** + * u_mac_post_ctrl_msg() - post ctrl msg + * @pMb: A pointer to the maibox message + * + * Forwards the completely received message to the respective + * modules for further processing. + * + * 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. + * + * Return: success/error code + */ + +tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb) +{ + tSirMsgQ msg; + tpAniSirGlobal pMac = (tpAniSirGlobal) pSirGlobal; + + tSirMbMsg *pMbLocal; + msg.type = pMb->type; + msg.bodyval = 0; + + pMbLocal = cdf_mem_malloc(pMb->msgLen); + if (!pMbLocal) { + WMA_LOGE("Memory allocation failed! Can't send 0x%x\n", + msg.type); + return eSIR_MEM_ALLOC_FAILED; + } + + cdf_mem_copy((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 */ + wma_post_ctrl_msg(pMac, &msg); + break; + + case SIR_LIM_MSG_TYPES_BEGIN: /* Posts a message to the LIM MsgQ */ + lim_post_msg_api(pMac, &msg); + break; + + case SIR_CFG_MSG_TYPES_BEGIN: /* Posts a message to the CFG MsgQ */ + wma_post_cfg_msg(pMac, &msg); + break; + + case SIR_PMM_MSG_TYPES_BEGIN: /* Posts a message to the LIM MsgQ */ + sme_post_pe_message(pMac, &msg); + break; + + case SIR_PTT_MSG_TYPES_BEGIN: + cdf_mem_free(msg.bodyptr); + break; + + default: + WMA_LOGD("Unknown message type = 0x%X\n", msg.type); + cdf_mem_free(msg.bodyptr); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; + +} /* u_mac_post_ctrl_msg() */ + diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c new file mode 100644 index 000000000000..872863abd58b --- /dev/null +++ b/core/wma/src/wma_data.c @@ -0,0 +1,3084 @@ +/* + * 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_data.c + * This file contains tx/rx and data path related functions. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +typedef struct { + int32_t rate; + uint8_t 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 */ +}; + +/** + * wma_bin_search_rate() - binary search function to find rate + * @tbl: rate table + * @tbl_size: table size + * @mbpsx10_rate: return mbps rate + * @ret_flag: return flag + * + * Return: none + */ +static void wma_bin_search_rate(wma_search_rate_t *tbl, int32_t tbl_size, + int32_t *mbpsx10_rate, uint8_t *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; +} + +/** + * wma_fill_ofdm_cck_mcast_rate() - fill ofdm cck mcast rate + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_ofdm_cck_mcast_rate(int32_t mbpsx10_rate, + uint8_t nss, uint8_t *rate) +{ + uint8_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_set_ht_vht_mcast_rate() - set ht/vht mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @sgi_idx: shortgi index + * @sgi_rate: shortgi rate + * @lgi_idx: longgi index + * @lgi_rate: longgi rate + * @premable: preamble + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: none + */ +static void wma_set_ht_vht_mcast_rate(uint32_t shortgi, int32_t mbpsx10_rate, + uint8_t sgi_idx, int32_t sgi_rate, + uint8_t lgi_idx, int32_t lgi_rate, + uint8_t premable, uint8_t *rate, + int32_t *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; + } +} + +/** + * wma_fill_ht20_mcast_rate() - fill ht20 mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_ht20_mcast_rate(uint32_t shortgi, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *rate, + int32_t *streaming_rate) +{ + uint8_t sgi_idx = 0, lgi_idx = 0; + int32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_fill_ht40_mcast_rate() - fill ht40 mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_ht40_mcast_rate(uint32_t shortgi, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *rate, + int32_t *streaming_rate) +{ + uint8_t sgi_idx = 0, lgi_idx = 0; + int32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_fill_vht20_mcast_rate() - fill vht20 mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_vht20_mcast_rate(uint32_t shortgi, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *rate, + int32_t *streaming_rate) +{ + uint8_t sgi_idx = 0, lgi_idx = 0; + int32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_fill_vht40_mcast_rate() - fill vht40 mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_vht40_mcast_rate(uint32_t shortgi, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *rate, + int32_t *streaming_rate) +{ + uint8_t sgi_idx = 0, lgi_idx = 0; + int32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_fill_vht80_mcast_rate() - fill vht80 mcast rate + * @shortgi: short gaurd interval + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_vht80_mcast_rate(uint32_t shortgi, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *rate, + int32_t *streaming_rate) +{ + uint8_t sgi_idx = 0, lgi_idx = 0; + int32_t 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_fill_ht_mcast_rate() - fill ht mcast rate + * @shortgi: short gaurd interval + * @chwidth: channel width + * @chanmode: channel mode + * @mhz: frequency + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_ht_mcast_rate(uint32_t shortgi, + uint32_t chwidth, int32_t mbpsx10_rate, + uint8_t nss, WLAN_PHY_MODE chanmode, + uint8_t *rate, + int32_t *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) ? CDF_STATUS_SUCCESS : CDF_STATUS_E_INVAL; +} + +/** + * wma_fill_vht_mcast_rate() - fill vht mcast rate + * @shortgi: short gaurd interval + * @chwidth: channel width + * @chanmode: channel mode + * @mhz: frequency + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * @streaming_rate: streaming rate + * + * Return: CDF status + */ +static CDF_STATUS wma_fill_vht_mcast_rate(uint32_t shortgi, + uint32_t chwidth, + int32_t mbpsx10_rate, uint8_t nss, + WLAN_PHY_MODE chanmode, + uint8_t *rate, + int32_t *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) ? CDF_STATUS_SUCCESS : CDF_STATUS_E_INVAL; +} + +#define WMA_MCAST_1X1_CUT_OFF_RATE 2000 +/** + * wma_encode_mc_rate() - fill mc rates + * @shortgi: short gaurd interval + * @chwidth: channel width + * @chanmode: channel mode + * @mhz: frequency + * @mbpsx10_rate: mbps rates + * @nss: nss + * @rate: rate + * + * Return: CDF status + */ +static CDF_STATUS wma_encode_mc_rate(uint32_t shortgi, uint32_t chwidth, + WLAN_PHY_MODE chanmode, A_UINT32 mhz, + int32_t mbpsx10_rate, uint8_t nss, + uint8_t *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 + */ + uint8_t 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 */ + uint8_t rate_ht = *rate; + uint8_t rate_vht = *rate; + int32_t stream_rate_ht = 0; + int32_t stream_rate_vht = 0; + int32_t stream_rate = 0; + + ret = wma_fill_ht_mcast_rate(shortgi, chwidth, mbpsx10_rate, + nss, chanmode, &rate_ht, + &stream_rate_ht); + if (ret != CDF_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 != CDF_STATUS_SUCCESS) { + if (stream_rate_ht != 0) + ret = CDF_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; +} + +/** + * wma_set_bss_rate_flags() - set rate flags based on BSS capability + * @iface: txrx_node ctx + * @add_bss: add_bss params + * + * Return: none + */ +void wma_set_bss_rate_flags(struct wma_txrx_node *iface, + tpAddBssParams add_bss) +{ + iface->rate_flags = 0; + + if (add_bss->vhtCapable) { + if (add_bss->ch_width == CH_WIDTH_80P80MHZ) + iface->rate_flags |= eHAL_TX_RATE_VHT80; + if (add_bss->ch_width == CH_WIDTH_160MHZ) + iface->rate_flags |= eHAL_TX_RATE_VHT80; + if (add_bss->ch_width == CH_WIDTH_80MHZ) + iface->rate_flags |= eHAL_TX_RATE_VHT80; + else if (add_bss->ch_width) + iface->rate_flags |= eHAL_TX_RATE_VHT40; + else + iface->rate_flags |= eHAL_TX_RATE_VHT20; + } + /* avoid to conflict with htCapable flag */ + else if (add_bss->htCapable) { + if (add_bss->ch_width) + 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; +} + +/** + * wmi_unified_send_txbf() - set txbf parameter to fw + * @wma: wma handle + * @params: txbf parameters + * + * Return: 0 for success or error code + */ +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 = params->enable_su_tx_bformer; + 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, sutxbfer %d", + txbf_en.sutxbfee, txbf_en.mutxbfee, txbf_en.sutxbfer); + + return wmi_unified_vdev_set_param_send(wma->wmi_handle, + params->smesessionId, + WMI_VDEV_PARAM_TXBF, + *((A_UINT8 *) &txbf_en)); +} + +/** + * wma_data_tx_ack_work_handler() - process data tx ack + * @ack_work: work structure + * + * Return: none + */ +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; + pWMAAckFnTxComp ack_cb; + + if (cds_is_load_unload_in_progress()) { + 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; + cdf_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 + * + * Return: none + */ +void +wma_data_tx_ack_comp_hdlr(void *wma_context, cdf_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 = cds_get_context(CDF_MODULE_ID_TXRX); + + 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 = cdf_mem_malloc(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 /* CONFIG_CNSS */ + 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 */ + cdf_nbuf_unmap_single(pdev->osdev, netbuf, CDF_DMA_TO_DEVICE); + cdf_nbuf_free(netbuf); +} + +/** + * wma_update_txrx_chainmask() - update txrx chainmask + * @num_rf_chains: number rf chains + * @cmd_value: command value + * + * Return: none + */ +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; + } +} + +/** + * wma_peer_state_change_event_handler() - peer state change event handler + * @handle: wma handle + * @event_buff: event buffer + * @len: length of buffer + * + * This event handler unpauses vdev if peer state change to AUTHORIZED STATE + * + * Return: 0 for success or error code + */ +int wma_peer_state_change_event_handler(void *handle, + uint8_t *event_buff, + uint32_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: Received NULL event ptr from FW", __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 hdd + * can procced and unpause tx queue + */ +#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL + if (!wma_handle->peer_authorized_cb) { + WMA_LOGE("%s: peer authorized cb not registered", + __func__); + return -EINVAL; + } + wma_handle->peer_authorized_cb(vdev->vdev_id); +#endif + } + + return 0; +} + +/** + * wma_set_enable_disable_mcc_adaptive_scheduler() -enable/disable mcc scheduler + * @mcc_adaptive_scheduler: enable/disable + * + * This function enable/disable mcc adaptive scheduler in fw. + * + * Return: CDF_STATUS_SUCCESS for sucess or error code + */ +CDF_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t + 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; + uint16_t len = + sizeof(wmi_resmgr_adaptive_ocs_enable_disable_cmd_fixed_param); + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == wma) { + WMA_LOGE("%s : Failed to get wma", __func__); + return CDF_STATUS_E_FAULT; + } + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s : wmi_buf_alloc failed", __func__); + return CDF_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__); + cdf_nbuf_free(buf); + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_mcc_channel_time_latency() -set MCC channel time latency + * @wma: wma handle + * @mcc_channel: mcc channel + * @mcc_channel_time_latency: MCC channel time latency. + * + * 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 . + * + * Return: CDF status + */ +CDF_STATUS wma_set_mcc_channel_time_latency + (tp_wma_handle wma, + uint32_t mcc_channel, uint32_t mcc_channel_time_latency) +{ + int ret = -1; + wmi_buf_t buf = 0; + wmi_resmgr_set_chan_latency_cmd_fixed_param *cmdTL = NULL; + uint16_t len = 0; + uint8_t *buf_ptr = NULL; + uint32_t cfg_val = 0; + wmi_resmgr_chan_latency chan_latency; + struct sAniSirGlobal *pMac = NULL; + /* Note: we only support MCC time latency for a single channel */ + uint32_t num_channels = 1; + uint32_t channel1 = mcc_channel; + uint32_t chan1_freq = cds_chan_to_freq(channel1); + uint32_t latency_chan1 = mcc_channel_time_latency; + + if (!wma) { + WMA_LOGE("%s:NULL wma ptr. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + pMac = cds_get_context(CDF_MODULE_ID_PE); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* First step is to confirm if MCC is active */ + if (!lim_is_in_mcc(pMac)) { + WMA_LOGE("%s: MCC is not active. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + /* Confirm MCC adaptive scheduler feature is disabled */ + if (wlan_cfg_get_int(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 CDF_STATUS_SUCCESS; + } + } else { + WMA_LOGE("%s: Failed to get value for MCC_ADAPTIVE_SCHED, " + "Exit w/o setting latency", __func__); + CDF_ASSERT(0); + return CDF_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 CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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; + cdf_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__); + cdf_nbuf_free(buf); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_mcc_channel_time_quota() -set MCC channel time quota + * @wma: wma handle + * @adapter_1_chan_number: adapter 1 channel number + * @adapter_1_quota: adapter 1 quota + * @adapter_2_chan_number: adapter 2 channel number + * + * 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. + * + * Return: CDF status + */ +CDF_STATUS wma_set_mcc_channel_time_quota + (tp_wma_handle wma, + uint32_t adapter_1_chan_number, + uint32_t adapter_1_quota, uint32_t adapter_2_chan_number) +{ + int ret = -1; + wmi_buf_t buf = 0; + uint16_t len = 0; + uint8_t *buf_ptr = NULL; + uint32_t 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; + uint32_t channel1 = adapter_1_chan_number; + uint32_t channel2 = adapter_2_chan_number; + uint32_t quota_chan1 = adapter_1_quota; + /* Knowing quota of 1st chan., derive quota for 2nd chan. */ + uint32_t quota_chan2 = 100 - quota_chan1; + /* Note: setting time quota for MCC requires info for 2 channels */ + uint32_t num_channels = 2; + uint32_t chan1_freq = cds_chan_to_freq(adapter_1_chan_number); + uint32_t chan2_freq = cds_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__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + pMac = cds_get_context(CDF_MODULE_ID_PE); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* First step is to confirm if MCC is active */ + if (!lim_is_in_mcc(pMac)) { + WMA_LOGD("%s: MCC is not active. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + /* Confirm MCC adaptive scheduler feature is disabled */ + if (wlan_cfg_get_int(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 CDF_STATUS_SUCCESS; + } + } else { + WMA_LOGE("%s: Failed to retrieve " + "WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED. Exit", __func__); + CDF_ASSERT(0); + return CDF_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 CDF_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__); + CDF_ASSERT(0); + return CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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; + cdf_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; + cdf_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"); + cdf_nbuf_free(buf); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_linkstate() - set wma linkstate + * @wma: wma handle + * @params: link state params + * + * Return: none + */ +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; + uint8_t vdev_id, peer_id; + bool roam_synch_in_progress = false; + CDF_STATUS status; + + params->status = 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 = cds_get_context(CDF_MODULE_ID_TXRX); + + 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 = true; + } +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + status = wma_create_peer(wma, pdev, vdev, params->bssid, + WMI_PEER_TYPE_DEFAULT, vdev_id, + roam_synch_in_progress); + if (status != CDF_STATUS_SUCCESS) + params->status = false; + } else { + WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP", + __func__, vdev_id); + ol_txrx_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, WMA_SET_LINK_STATE_RSP, (void *)params, 0); +} + +/** + * wma_unpause_vdev - unpause all vdev + * @wma: wma handle + * + * unpause all vdev aftter resume/coming out of wow mode + * + * Return: none + */ +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; + +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + /* When host resume, by default, unpause all active vdev */ + if (wma->interfaces[vdev_id].pause_bitmap) { + ol_txrx_vdev_unpause(wma->interfaces[vdev_id].handle, + 0xffffffff); + wma->interfaces[vdev_id].pause_bitmap = 0; + } +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + + iface = &wma->interfaces[vdev_id]; + iface->conn_state = false; + } +} + +/** + * wma_process_rate_update_indate() - rate update indication + * @wma: wma handle + * @pRateUpdateParams: Rate update params + * + * This function update rate & short GI interval to fw based on params + * send by SME. + * + * Return: CDF status + */ +CDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, + tSirRateUpdateInd * + pRateUpdateParams) +{ + int32_t ret = 0; + uint8_t vdev_id = 0; + void *pdev; + int32_t mbpsx10_rate = -1; + uint32_t paramId; + uint8_t rate = 0; + uint32_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); + cdf_mem_free(pRateUpdateParams); + return CDF_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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Error, Invalid input rate value", __func__); + cdf_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); + cdf_mem_free(pRateUpdateParams); + return CDF_STATUS_E_FAILURE; + } + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + vdev_id, paramId, rate); + cdf_mem_free(pRateUpdateParams); + if (ret) { + WMA_LOGE("%s: Failed to Set rate, ret = %d", __func__, ret); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_mgmt_tx_ack_work_handler() - mgmt tx ack work queue + * @ack_work: work structure + * + * Return: none + */ +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; + pWMAAckFnTxComp ack_cb; + + if (cds_is_load_unload_in_progress()) { + 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); + + cdf_mem_free(work); + wma_handle->ack_work_ctx = NULL; +} + +/** + * wma_mgmt_tx_comp_conf_ind() - Post mgmt tx complete indication to PE. + * @wma_handle: Pointer to WMA handle + * @sub_type: Tx mgmt frame sub type + * @status: Mgmt frame tx status + * + * This function sends mgmt complition confirmation to PE for deauth + * and deassoc frames. + * + * Return: none + */ +static void +wma_mgmt_tx_comp_conf_ind(tp_wma_handle wma_handle, uint8_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, WMA_DISASSOC_TX_COMP, NULL, + tx_comp_status); + } else if (sub_type == SIR_MAC_MGMT_DEAUTH) { + wma_send_msg(wma_handle, WMA_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 + * @status: status of tx completion + * + * This is callback registered with TxRx for + * Ack Complete. + * + * Return: none + */ +static void +wma_mgmt_tx_ack_comp_hdlr(void *wma_context, cdf_nbuf_t netbuf, int32_t status) +{ + tpSirMacFrameCtl pFc = (tpSirMacFrameCtl) (cdf_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, + (uint8_t) pFc->subType, + status); + } else { + struct wma_tx_ack_work_ctx *ack_work; + + ack_work = + cdf_mem_malloc(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 /* CONFIG_CNSS */ + 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 + * @status: status of tx completion + * + * This function calls registered download callback while sending mgmt packet. + * + * Return: none + */ +static void +wma_mgmt_tx_dload_comp_hldr(void *wma_context, cdf_nbuf_t netbuf, + int32_t status) +{ + CDF_STATUS cdf_status = CDF_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 */ + cdf_status = cdf_event_set(&wma_handle->tx_frm_download_comp_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + WMA_LOGP("%s: Event Set failed - tx_frm_comp_event", __func__); +} + +/** + * wma_tx_attach() - attach tx related callbacks + * @pwmaCtx: wma context + * + * attaches tx fn with underlying layer. + * + * Return: CDF status + */ +CDF_STATUS wma_tx_attach(tp_wma_handle wma_handle) +{ + /* Get the Vos Context */ + p_cds_contextType cds_handle = + (p_cds_contextType) (wma_handle->cds_context); + + /* Get the txRx Pdev handle */ + ol_txrx_pdev_handle txrx_pdev = + (ol_txrx_pdev_handle) (cds_handle->pdev_txrx_ctx); + + /* Register for Tx Management Frames */ + ol_txrx_mgmt_tx_cb_set(txrx_pdev, GENERIC_NODOWLOAD_ACK_COMP_INDEX, + NULL, wma_mgmt_tx_ack_comp_hdlr, wma_handle); + + ol_txrx_mgmt_tx_cb_set(txrx_pdev, GENERIC_DOWNLD_COMP_NOACK_COMP_INDEX, + wma_mgmt_tx_dload_comp_hldr, NULL, wma_handle); + + ol_txrx_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 = cds_handle->pMACContext; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_tx_detach() - detach tx related callbacks + * @tp_wma_handle: wma context + * + * Deregister with TxRx for Tx Mgmt Download and Ack completion. + * + * Return: CDF status + */ +CDF_STATUS wma_tx_detach(tp_wma_handle wma_handle) +{ + uint32_t frame_index = 0; + + /* Get the Vos Context */ + p_cds_contextType cds_handle = + (p_cds_contextType) (wma_handle->cds_context); + + /* Get the txRx Pdev handle */ + ol_txrx_pdev_handle txrx_pdev = + (ol_txrx_pdev_handle) (cds_handle->pdev_txrx_ctx); + + /* Deregister with TxRx for Tx Mgmt completion call back */ + for (frame_index = 0; frame_index < FRAME_INDEX_MAX; frame_index++) + ol_txrx_mgmt_tx_cb_set(txrx_pdev, frame_index, NULL, NULL, + txrx_pdev); + + /* Destroy Tx Frame Complete event */ + cdf_event_destroy(&wma_handle->tx_frm_download_comp_event); + + /* Tx queue empty check event (dummy event) */ + cdf_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 CDF_STATUS_SUCCESS; +} + +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) +/** + * wma_mcc_vdev_tx_pause_evt_handler() - pause event handler + * @handle: wma handle + * @event: event buffer + * @len: data length + * + * This function handle pause event from fw and pause/unpause + * vdev. + * + * Return: 0 for success or error code. + */ +int wma_mcc_vdev_tx_pause_evt_handler(void *handle, uint8_t *event, + uint32_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; + uint8_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) + ol_txrx_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 */ + ol_txrx_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_LL_LEGACY_TX_FLOW_CONTROL */ + +/** + * wma_process_init_thermal_info() - initialize thermal info + * @wma: Pointer to WMA handle + * @pThermalParams: Pointer to thermal mitigation parameters + * + * 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 + * + * Returns: CDF_STATUS_SUCCESS for success otherwise failure + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + + curr_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return CDF_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 (CDF_STATUS_SUCCESS != + wma_set_thermal_mgmt(wma, thermal_params)) { + WMA_LOGE("Could not send thermal mgmt command to the firmware!"); + } + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_thermal_level_ind() - send SME set thermal level indication message + * @level: thermal level + * + * Send SME SET_THERMAL_LEVEL_IND message + * + * Returns: none + */ +static void wma_set_thermal_level_ind(u_int8_t level) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + WMA_LOGE(FL( + "Fail to post set thermal level ind msg")); +} + +/** + * wma_process_set_thermal_level() - sets thermal level + * @wma: Pointer to WMA handle + * @thermal_level : Thermal level + * + * This function sets the new thermal throttle level in the + * txrx module and sends down the corresponding temperature + * thresholds to the firmware + * + * Returns: CDF_STATUS_SUCCESS for success otherwise failure + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + + curr_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (NULL == curr_pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return CDF_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 command"); + return CDF_STATUS_E_FAILURE; + } + + if (thermal_level >= WLAN_WMA_MAX_THERMAL_LEVELS) { + WMA_LOGE("Invalid thermal level set %d", thermal_level); + return CDF_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 CDF_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 CDF_STATUS_SUCCESS; +} + + +/** + * wma_set_thermal_mgmt() - set thermal mgmt command to fw + * @wma_handle: Pointer to WMA handle + * @thermal_info: Thermal command information + * + * This function sends the thermal management command + * to the firmware + * + * Return: CDF_STATUS_SUCCESS for success otherwise failure + */ +CDF_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; + uint32_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 CDF_STATUS_E_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) { + cdf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send thermal mgmt command", __func__); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_thermal_mgmt_get_level() - returns throttle level + * @handle: Pointer to WMA handle + * @temp: temperature + * + * This function returns the thermal(throttle) level + * given the temperature + * + * Return: thermal (throttle) level + */ +uint8_t wma_thermal_mgmt_get_level(void *handle, uint32_t temp) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + int i; + uint8_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; +} + +/** + * wma_thermal_mgmt_evt_handler() - thermal mgmt event handler + * @wma_handle: Pointer to WMA handle + * @event: Thermal event information + * + * This function handles the thermal mgmt event from the firmware len + * + * Return: 0 for success otherwise failure + */ +int wma_thermal_mgmt_evt_handler(void *handle, uint8_t *event, + uint32_t len) +{ + tp_wma_handle wma; + wmi_thermal_mgmt_event_fixed_param *tm_event; + uint8_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 = cds_get_context(CDF_MODULE_ID_TXRX); + 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 (CDF_STATUS_SUCCESS != wma_set_thermal_mgmt(wma, thermal_params)) { + WMA_LOGE("Could not send thermal mgmt command to the firmware!"); + return -EINVAL; + } + + return 0; +} + +/** + * wma_decap_to_8023() - Decapsulate to 802.3 format + * @msdu: skb buffer + * @info: decapsulate info + * + * Return: none + */ +static void wma_decap_to_8023(cdf_nbuf_t msdu, struct wma_decap_info_t *info) +{ + struct llc_snap_hdr_t *llc_hdr; + uint16_t ether_type; + uint16_t l2_hdr_space; + struct ieee80211_qosframe_addr4 *wh; + uint8_t local_buf[ETHERNET_HDR_LEN]; + uint8_t *buf; + struct ethernet_hdr_t *ethr_hdr; + + buf = (uint8_t *) cdf_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 = cdf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN); + } else if (l2_hdr_space < ETHERNET_HDR_LEN) { + buf = cdf_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: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_TODS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr2, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_FROMDS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, + ETHERNET_ADDR_LEN); + cdf_mem_copy(ethr_hdr->src_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + break; + case IEEE80211_FC1_DIR_DSTODS: + cdf_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, + ETHERNET_ADDR_LEN); + cdf_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 { + uint32_t pktlen = + cdf_nbuf_len(msdu) - sizeof(ethr_hdr->ethertype); + ether_type = (uint16_t) pktlen; + ether_type = cdf_nbuf_len(msdu) - sizeof(struct ethernet_hdr_t); + ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; + ethr_hdr->ethertype[1] = (ether_type) & 0xff; + } + cdf_mem_copy(buf, ethr_hdr, ETHERNET_HDR_LEN); +} + +/** + * wma_ieee80211_hdrsize() - get 802.11 header size + * @data: 80211 frame + * + * Return: size of header + */ +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(uint16_t); + return size; +} + +/** + * wmi_desc_pool_init() - Initialize the WMI descriptor pool + * @wma_handle: handle to wma + * @pool_size: Size of wma pool + * + * Return: 0 for success, error code on failure. + */ +int wmi_desc_pool_init(tp_wma_handle wma_handle, uint32_t pool_size) +{ + int i; + + if (!pool_size) { + WMA_LOGE("%s: failed to allocate desc pool", __func__); + cdf_assert_always(pool_size); + return -EINVAL; + } + WMA_LOGE("%s: initialize desc pool of size %d", __func__, pool_size); + wma_handle->wmi_desc_pool.pool_size = pool_size; + wma_handle->wmi_desc_pool.num_free = pool_size; + wma_handle->wmi_desc_pool.array = cdf_mem_malloc(pool_size * + sizeof(union wmi_desc_elem_t)); + if (!wma_handle->wmi_desc_pool.array) { + WMA_LOGE("%s: failed to allocate desc pool", __func__); + return -ENOMEM; + } + wma_handle->wmi_desc_pool.freelist = &wma_handle-> + wmi_desc_pool.array[0]; + + for (i = 0; i < (pool_size - 1); i++) { + wma_handle->wmi_desc_pool.array[i].wmi_desc.desc_id = i; + wma_handle->wmi_desc_pool.array[i].next = + &wma_handle->wmi_desc_pool.array[i + 1]; + } + + wma_handle->wmi_desc_pool.array[i].next = NULL; + wma_handle->wmi_desc_pool.array[i].wmi_desc.desc_id = i; + + cdf_spinlock_init(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + return 0; +} + +/** + * wmi_desc_pool_deinit() - Deinitialize the WMI descriptor pool + * @wma_handle: handle to wma + * + * Return: None + */ +void wmi_desc_pool_deinit(tp_wma_handle wma_handle) +{ + cdf_spin_lock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + if (wma_handle->wmi_desc_pool.array) { + cdf_mem_free(wma_handle->wmi_desc_pool.array); + wma_handle->wmi_desc_pool.array = NULL; + } else { + WMA_LOGE("%s: Empty WMI descriptor pool", __func__); + } + + wma_handle->wmi_desc_pool.freelist = NULL; + wma_handle->wmi_desc_pool.pool_size = 0; + wma_handle->wmi_desc_pool.num_free = 0; + cdf_spin_unlock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + cdf_spinlock_destroy(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); +} + +/** + * wmi_desc_get() - Get wmi descriptor from wmi free descriptor pool + * @wma_handle: handle to wma + * + * Return: pointer to wmi descriptor, NULL on failure + */ +struct wmi_desc_t *wmi_desc_get(tp_wma_handle wma_handle) +{ + struct wmi_desc_t *wmi_desc = NULL; + + cdf_spin_lock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + if (wma_handle->wmi_desc_pool.freelist) { + wma_handle->wmi_desc_pool.num_free--; + wmi_desc = &wma_handle->wmi_desc_pool.freelist->wmi_desc; + wma_handle->wmi_desc_pool.freelist = + wma_handle->wmi_desc_pool.freelist->next; + } + cdf_spin_unlock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + + return wmi_desc; +} + +/** + * wmi_desc_put() - Put wmi descriptor to wmi free descriptor pool + * @wma_handle: handle to wma + * @wmi_desc: wmi descriptor + * + * Return: None + */ +void wmi_desc_put(tp_wma_handle wma_handle, struct wmi_desc_t *wmi_desc) +{ + cdf_spin_lock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); + ((union wmi_desc_elem_t *)wmi_desc)->next = + wma_handle->wmi_desc_pool.freelist; + wma_handle->wmi_desc_pool.freelist = (union wmi_desc_elem_t *)wmi_desc; + wma_handle->wmi_desc_pool.num_free++; + cdf_spin_unlock_bh(&wma_handle->wmi_desc_pool.wmi_desc_pool_lock); +} + +#define mgmt_tx_dl_frm_len 64 +static inline CDF_STATUS +mgmt_wmi_unified_cmd_send(tp_wma_handle wma_handle, void *tx_frame, + uint16_t frmLen, uint8_t vdev_id, + pWMATxRxCompFunc tx_complete_cb, + pWMAAckFnTxComp tx_ota_post_proc_cb, + uint16_t chanfreq, void *pData) +{ + wmi_buf_t buf; + wmi_mgmt_tx_send_cmd_fixed_param *cmd; + int32_t cmd_len; + uint64_t dma_addr; + struct wmi_desc_t *wmi_desc = NULL; + void *cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + uint8_t *bufp; + int32_t bufp_len = (frmLen < mgmt_tx_dl_frm_len) ? frmLen : + mgmt_tx_dl_frm_len; + + cmd_len = sizeof(wmi_mgmt_tx_send_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + roundup(bufp_len, sizeof(uint32_t)); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, cmd_len); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_mgmt_tx_send_cmd_fixed_param *)wmi_buf_data(buf); + bufp = (uint8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mgmt_tx_send_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_mgmt_tx_send_cmd_fixed_param)); + + cmd->vdev_id = vdev_id; + + wmi_desc = wmi_desc_get(wma_handle); + if (!wmi_desc) { + WMA_LOGE("%s: Failed to get wmi_desc", __func__); + goto err2; + } + wmi_desc->nbuf = tx_frame; + wmi_desc->tx_cmpl_cb = tx_complete_cb; + wmi_desc->ota_post_proc_cb = tx_ota_post_proc_cb; + + cmd->desc_id = wmi_desc->desc_id; + cmd->chanfreq = chanfreq; + bufp += sizeof(wmi_mgmt_tx_send_cmd_fixed_param); + WMITLV_SET_HDR(bufp, WMITLV_TAG_ARRAY_BYTE, roundup(bufp_len, + sizeof(uint32_t))); + bufp += WMI_TLV_HDR_SIZE; + cdf_mem_copy(bufp, pData, bufp_len); + cdf_nbuf_map_single(cdf_ctx, tx_frame, CDF_DMA_TO_DEVICE); + dma_addr = cdf_nbuf_get_frag_paddr_lo(tx_frame, 0); + cmd->paddr_lo = (uint32_t)(dma_addr & 0xffffffff); +#if defined(HELIUMPLUS_PADDR64) + cmd->paddr_hi = (uint32_t)((dma_addr >> 32) & 0x1F); +#endif + cmd->frame_len = frmLen; + cmd->buf_len = bufp_len; + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, cmd_len, + WMI_MGMT_TX_SEND_CMDID)) { + WMA_LOGE("%s: Failed to send mgmt Tx", __func__); + goto err1; + } + return CDF_STATUS_SUCCESS; +err1: + wmi_desc_put(wma_handle, wmi_desc); +err2: + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; +} + +/** + * wma_tx_packet() - Sends Tx Frame to TxRx + * @wma_context: wma context + * @tx_frame: frame buffer + * @frmLen: frame length + * @frmType: frame type + * @txDir: tx diection + * @tid: TID + * @tx_frm_download_comp_cb: tx download callback handler + * @tx_frm_ota_comp_cb: OTA complition handler + * @tx_flag: tx flag + * @vdev_id: vdev id + * @tdlsFlag: tdls flag + * + * This function sends the frame corresponding to the + * given vdev id. + * This is blocking call till the downloading of frame is complete. + * + * Return: CDF status + */ +CDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen, + eFrameType frmType, eFrameTxDir txDir, uint8_t tid, + pWMATxRxCompFunc tx_frm_download_comp_cb, void *pData, + pWMAAckFnTxComp tx_frm_ota_comp_cb, uint8_t tx_flag, + uint8_t vdev_id, bool tdlsFlag, uint16_t channel_freq) +{ + tp_wma_handle wma_handle = (tp_wma_handle) (wma_context); + int32_t status; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int32_t is_high_latency; + ol_txrx_vdev_handle txrx_vdev; + enum frame_index tx_frm_index = GENERIC_NODOWNLD_NOACK_COMP_INDEX; + tpSirMacFrameCtl pFc = (tpSirMacFrameCtl) (cdf_nbuf_data(tx_frame)); + uint8_t use_6mbps = 0; + uint8_t downld_comp_required = 0; + uint16_t chanfreq; +#ifdef WLAN_FEATURE_11W + uint8_t *pFrame = NULL; + void *pPacket = NULL; + uint16_t newFrmLen = 0; +#endif /* WLAN_FEATURE_11W */ + struct wma_txrx_node *iface; + tpAniSirGlobal pMac; + tpSirMacMgmtHdr mHdr; +#ifdef QCA_PKT_PROTO_TRACE + uint8_t proto_type = 0; +#endif /* QCA_PKT_PROTO_TRACE */ + + if (NULL == wma_handle) { + WMA_LOGE("wma_handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + iface = &wma_handle->interfaces[vdev_id]; + /* Get the vdev handle from vdev id */ + txrx_vdev = wma_handle->interfaces[vdev_id].handle; + + if (!txrx_vdev) { + WMA_LOGE("TxRx Vdev Handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + + if (frmType >= TXRX_FRM_MAX) { + WMA_LOGE("Invalid Frame Type Fail to send Frame"); + return CDF_STATUS_E_FAILURE; + } + + pMac = cds_get_context(CDF_MODULE_ID_PE); + if (!pMac) { + WMA_LOGE("pMac Handle is NULL"); + return CDF_STATUS_E_FAILURE; + } + /* + * Currently only support to + * send 80211 Mgmt and 80211 Data are added. + */ + if (!((frmType == TXRX_FRM_802_11_MGMT) || + (frmType == TXRX_FRM_802_11_DATA))) { + WMA_LOGE("No Support to send other frames except 802.11 Mgmt/Data"); + return CDF_STATUS_E_FAILURE; + } + mHdr = (tpSirMacMgmtHdr)cdf_nbuf_data(tx_frame); +#ifdef WLAN_FEATURE_11W + if ((iface && iface->rmfEnabled) && + (frmType == 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 *)cdf_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; + cdf_status = + cds_packet_alloc((uint16_t) newFrmLen, + (void **)&pFrame, + (void **)&pPacket); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGP("%s: Failed to allocate %d bytes for RMF status " + "code (%x)", __func__, newFrmLen, + cdf_status); + /* Free the original packet memory */ + cds_packet_free((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 + */ + cdf_mem_set(pFrame, newFrmLen, 0); + cdf_mem_copy(pFrame, wh, sizeof(*wh)); + cdf_mem_copy(pFrame + sizeof(*wh) + + IEEE80211_CCMP_HEADERLEN, + pData + sizeof(*wh), + frmLen - sizeof(*wh)); + + cds_packet_free((void *)tx_frame); + tx_frame = pPacket; + frmLen = newFrmLen; + } + } else { + /* Allocate extra bytes for MMIE */ + newFrmLen = frmLen + IEEE80211_MMIE_LEN; + cdf_status = cds_packet_alloc((uint16_t) newFrmLen, + (void **)&pFrame, + (void **)&pPacket); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGP("%s: Failed to allocate %d bytes for RMF status " + "code (%x)", __func__, newFrmLen, + cdf_status); + /* Free the original packet memory */ + cds_packet_free((void *)tx_frame); + goto error; + } + /* + * Initialize the frame with 0's and only fill + * MAC header and data. MMIE field will be + * filled by cds_attach_mmie API + */ + cdf_mem_set(pFrame, newFrmLen, 0); + cdf_mem_copy(pFrame, wh, sizeof(*wh)); + cdf_mem_copy(pFrame + sizeof(*wh), + pData + sizeof(*wh), frmLen - sizeof(*wh)); + if (!cds_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 */ + cds_packet_free((void *)tx_frame); + goto error; + } + cds_packet_free((void *)tx_frame); + tx_frame = pPacket; + frmLen = newFrmLen; + } + } +#endif /* WLAN_FEATURE_11W */ + + if ((frmType == TXRX_FRM_802_11_MGMT) && + (pFc->subType == SIR_MAC_MGMT_PROBE_RSP)) { + uint64_t adjusted_tsf_le; + struct ieee80211_frame *wh = + (struct ieee80211_frame *)cdf_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 == TXRX_FRM_802_11_DATA) { + cdf_nbuf_t ret; + cdf_nbuf_t skb = (cdf_nbuf_t) tx_frame; + ol_txrx_pdev_handle pdev = + cds_get_context(CDF_MODULE_ID_TXRX); + + struct wma_decap_info_t decap_info; + struct ieee80211_frame *wh = + (struct ieee80211_frame *)cdf_nbuf_data(skb); + v_TIME_t curr_timestamp = cdf_mc_timer_get_system_ticks(); + + if (pdev == NULL) { + WMA_LOGE("%s: pdev pointer is not available", __func__); + return CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + /* Take out 802.11 header from skb */ + decap_info.hdr_len = wma_ieee80211_hdrsize(wh); + cdf_mem_copy(decap_info.hdr, wh, decap_info.hdr_len); + cdf_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 */ + cdf_mem_set(skb->cb, sizeof(skb->cb), 0); + + /* Do the DMA Mapping */ + cdf_nbuf_map_single(pdev->osdev, skb, CDF_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 */ + ret = ol_tx_non_std(txrx_vdev, ol_tx_spec_no_free, skb); + + if (ret) { + WMA_LOGE("TxRx Rejected. Fail to do Tx"); + cdf_nbuf_unmap_single(pdev->osdev, skb, + CDF_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 CDF_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 CDF_STATUS_SUCCESS; + } + + is_high_latency = + ol_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 = cds_pkt_get_proto_type(tx_frame, + pMac->fEnableDebugLog, + NBUF_PKT_TRAC_TYPE_MGMT_ACTION); + if (proto_type & NBUF_PKT_TRAC_TYPE_MGMT_ACTION) + cds_pkt_trace_buf_update("WM:T:MACT"); + cdf_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 */ + cdf_status = + cdf_event_reset(&wma_handle->tx_frm_download_comp_event); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGP("%s: Event Reset failed tx comp event %x", + __func__, cdf_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 if (pFc->subType == SIR_MAC_MGMT_ACTION) { + chanfreq = channel_freq; + } 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 seq_num[%d]", + pFc->type, pFc->subType, + ((mHdr->seqControl.seqNumHi << 4) | + mHdr->seqControl.seqNumLo)); + } + } + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_MGMT_TX_WMI)) { + status = mgmt_wmi_unified_cmd_send(wma_handle, tx_frame, frmLen, + vdev_id, + tx_frm_download_comp_cb, + tx_frm_ota_comp_cb, + chanfreq, pData); + } else { + /* Hand over the Tx Mgmt frame to TxRx */ + status = ol_txrx_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 CDF_STATUS_SUCCESS; + + /* + * Wait for Download Complete + * if required + */ + if (downld_comp_required) { + /* + * Wait for Download Complete + * @ Integrated : Dxe Complete + * @ Discrete : Target Download Complete + */ + cdf_status = + cdf_wait_single_event(&wma_handle-> + tx_frm_download_comp_event, + WMA_TX_FRAME_COMPLETE_TIMEOUT); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + 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) + */ + } + } 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 CDF_STATUS_SUCCESS; + +error: + wma_handle->tx_frm_download_comp_cb = NULL; + return CDF_STATUS_E_FAILURE; +} + +/** + * wma_ds_peek_rx_packet_info() - peek rx packet info + * @pkt: packet + * @pkt_meta: packet meta + * @bSwap: byte swap + * + * Function fills the rx packet meta info from the the cds packet + * + * Return: CDF status + */ +CDF_STATUS wma_ds_peek_rx_packet_info(cds_pkt_t *pkt, void **pkt_meta, + bool bSwap) +{ + /* Sanity Check */ + if (pkt == NULL) { + WMA_LOGE("wma:Invalid parameter sent on wma_peek_rx_pkt_info"); + return CDF_STATUS_E_FAULT; + } + + *pkt_meta = &(pkt->pkt_meta); + + return CDF_STATUS_SUCCESS; +} + +/** + * ol_rx_err() - ol rx err handler + * @pdev: ol pdev + * @vdev_id: vdev id + * @peer_mac_addr: peer mac address + * @tid: TID + * @tsf32: TSF + * @err_type: error type + * @rx_frame: rx frame + * @pn: PN Number + * @key_id: key id + * + * This function handles rx error and send MIC error failure to LIM + * + * Return: none + */ +void ol_rx_err(ol_pdev_handle pdev, uint8_t vdev_id, + uint8_t *peer_mac_addr, int tid, uint32_t tsf32, + enum ol_rx_err_type err_type, cdf_nbuf_t rx_frame, + uint64_t *pn, uint8_t key_id) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + tpSirSmeMicFailureInd mic_err_ind; + struct ether_header *eth_hdr; + cds_msg_t cds_msg; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return; + } + + if (err_type != OL_RX_ERR_TKIP_MIC) + return; + + if (cdf_nbuf_len(rx_frame) < sizeof(*eth_hdr)) + return; + eth_hdr = (struct ether_header *)cdf_nbuf_data(rx_frame); + mic_err_ind = cdf_mem_malloc(sizeof(*mic_err_ind)); + if (!mic_err_ind) { + WMA_LOGE("%s: Failed to allocate memory for MIC indication message", + __func__); + return; + } + cdf_mem_set((void *)mic_err_ind, sizeof(*mic_err_ind), 0); + + mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND; + mic_err_ind->length = sizeof(*mic_err_ind); + mic_err_ind->sessionId = vdev_id; + cdf_mem_copy(mic_err_ind->bssId, + (struct cdf_mac_addr *) wma->interfaces[vdev_id].bssid, + sizeof(tSirMacAddr)); + cdf_mem_copy(mic_err_ind->info.taMacAddr, + (struct cdf_mac_addr *) peer_mac_addr, + sizeof(tSirMacAddr)); + cdf_mem_copy(mic_err_ind->info.srcMacAddr, + (struct cdf_mac_addr *) eth_hdr->ether_shost, + sizeof(tSirMacAddr)); + cdf_mem_copy(mic_err_ind->info.dstMacAddr, + (struct cdf_mac_addr *) 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); + cdf_mem_copy(mic_err_ind->info.TSC, pn, SIR_CIPHER_SEQ_CTR_SIZE); + + cdf_mem_set(&cds_msg, sizeof(cds_msg_t), 0); + cds_msg.type = eWNI_SME_MIC_FAILURE_IND; + cds_msg.bodyptr = (void *) mic_err_ind; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)) { + WMA_LOGE("%s: could not post mic failure indication to SME", + __func__); + cdf_mem_free((void *)mic_err_ind); + } +} + +/** + * wma_tx_abort() - abort tx + * @vdev_id: vdev id + * + * In case of deauth host abort transmitting packet. + * + * Return: none + */ +void wma_tx_abort(uint8_t vdev_id) +{ +#define PEER_ALL_TID_BITMASK 0xffffffff + tp_wma_handle wma; + uint32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK; + struct wma_txrx_node *iface; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + 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); + ol_txrx_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); +} + +#if defined(FEATURE_LRO) +/** + * wma_lro_config_cmd() - process the LRO config command + * @wma: Pointer to WMA handle + * @wma_lro_cmd: Pointer to LRO configuration parameters + * + * This function sends down the LRO configuration parameters to + * the firmware to enable LRO, sets the TCP flags and sets the + * seed values for the toeplitz hash generation + * + * Return: CDF_STATUS_SUCCESS for success otherwise failure + */ +CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle, + struct wma_lro_config_cmd_t *wma_lro_cmd) +{ + wmi_lro_info_cmd_fixed_param *cmd; + wmi_buf_t buf; + int status; + + if (NULL == wma_handle || NULL == wma_lro_cmd) { + WMA_LOGE("wma_lro_config_cmd': invalid input!"); + return CDF_STATUS_E_FAILURE; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd)); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set key cmd"); + return CDF_STATUS_E_FAILURE; + } + + cmd = (wmi_lro_info_cmd_fixed_param *) wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_lro_info_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_lro_info_cmd_fixed_param)); + + cmd->lro_enable = wma_lro_cmd->lro_enable; + WMI_LRO_INFO_TCP_FLAG_VALS_SET(cmd->tcp_flag_u32, + wma_lro_cmd->tcp_flag); + WMI_LRO_INFO_TCP_FLAGS_MASK_SET(cmd->tcp_flag_u32, + wma_lro_cmd->tcp_flag_mask); + cmd->toeplitz_hash_ipv4_0_3 = + wma_lro_cmd->toeplitz_hash_ipv4[0]; + cmd->toeplitz_hash_ipv4_4_7 = + wma_lro_cmd->toeplitz_hash_ipv4[1]; + cmd->toeplitz_hash_ipv4_8_11 = + wma_lro_cmd->toeplitz_hash_ipv4[2]; + cmd->toeplitz_hash_ipv4_12_15 = + wma_lro_cmd->toeplitz_hash_ipv4[3]; + cmd->toeplitz_hash_ipv4_16 = + wma_lro_cmd->toeplitz_hash_ipv4[4]; + + cmd->toeplitz_hash_ipv6_0_3 = + wma_lro_cmd->toeplitz_hash_ipv6[0]; + cmd->toeplitz_hash_ipv6_4_7 = + wma_lro_cmd->toeplitz_hash_ipv6[1]; + cmd->toeplitz_hash_ipv6_8_11 = + wma_lro_cmd->toeplitz_hash_ipv6[2]; + cmd->toeplitz_hash_ipv6_12_15 = + wma_lro_cmd->toeplitz_hash_ipv6[3]; + cmd->toeplitz_hash_ipv6_16_19 = + wma_lro_cmd->toeplitz_hash_ipv6[4]; + cmd->toeplitz_hash_ipv6_20_23 = + wma_lro_cmd->toeplitz_hash_ipv6[5]; + cmd->toeplitz_hash_ipv6_24_27 = + wma_lro_cmd->toeplitz_hash_ipv6[6]; + cmd->toeplitz_hash_ipv6_28_31 = + wma_lro_cmd->toeplitz_hash_ipv6[7]; + cmd->toeplitz_hash_ipv6_32_35 = + wma_lro_cmd->toeplitz_hash_ipv6[8]; + cmd->toeplitz_hash_ipv6_36_39 = + wma_lro_cmd->toeplitz_hash_ipv6[9]; + cmd->toeplitz_hash_ipv6_40 = + wma_lro_cmd->toeplitz_hash_ipv6[10]; + + WMA_LOGD("WMI_LRO_CONFIG: lro_enable %d, tcp_flag 0x%x", + cmd->lro_enable, cmd->tcp_flag_u32); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_LRO_CONFIG_CMDID); + if (status) { + cdf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send WMI_LRO_CONFIG_CMDID", __func__); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c new file mode 100644 index 000000000000..587b327cf8ad --- /dev/null +++ b/core/wma/src/wma_dev_if.c @@ -0,0 +1,4470 @@ +/* + * 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_dev_if.c + * This file contains vdev & peer related operations. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +/* FIXME: Inclusion of .c looks odd but this is how it is in internal codebase */ +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +#include "wma_ocb.h" + +/** + * wma_find_vdev_by_addr() - find vdev_id from mac address + * @wma: wma handle + * @addr: mac address + * @vdev_id: return vdev_id + * + * Return: Returns vdev handle or NULL if mac address don't match + */ +void *wma_find_vdev_by_addr(tp_wma_handle wma, uint8_t *addr, + uint8_t *vdev_id) +{ + uint8_t i; + + for (i = 0; i < wma->max_bssid; i++) { + if (cdf_is_macaddr_equal( + (struct cdf_mac_addr *) wma->interfaces[i].addr, + (struct cdf_mac_addr *) addr) == true) { + *vdev_id = i; + return wma->interfaces[i].handle; + } + } + return NULL; +} + + +/** + * wma_is_vdev_in_ap_mode() - check that vdev is in ap mode or not + * @wma: wma handle + * @vdev_id: vdev id + * + * Helper function to know whether given vdev id + * is in AP mode or not. + * + * Return: True/False + */ +bool wma_is_vdev_in_ap_mode(tp_wma_handle wma, uint8_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); + CDF_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 +/** + * wma_is_vdev_in_ibss_mode() - check that vdev is in ibss mode or not + * @wma: wma handle + * @vdev_id: vdev id + * + * Helper function to know whether given vdev id + * is in IBSS mode or not. + * + * Return: True/False + */ +bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, uint8_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); + CDF_ASSERT(0); + return false; + } + + if (intf[vdev_id].type == WMI_VDEV_TYPE_IBSS) + return true; + + return false; +} +#endif /* QCA_IBSS_SUPPORT */ + + +/** + * wma_find_vdev_by_bssid() - Get the corresponding vdev_id from BSSID + * @wma - wma handle + * @vdev_id - vdev ID + * + * Return: fill vdev_id with appropriate vdev id and return vdev + * handle or NULL if not found. + */ +void *wma_find_vdev_by_bssid(tp_wma_handle wma, uint8_t *bssid, + uint8_t *vdev_id) +{ + int i; + + for (i = 0; i < wma->max_bssid; i++) { + if (cdf_is_macaddr_equal( + (struct cdf_mac_addr *) wma->interfaces[i].bssid, + (struct cdf_mac_addr *) bssid) == true) { + *vdev_id = i; + return wma->interfaces[i].handle; + } + } + + return NULL; +} + +/** + * wma_get_txrx_vdev_type() - return operating mode of vdev + * @type: vdev_type + * + * Return: return operating mode as enum wlan_op_mode type + */ +enum wlan_op_mode wma_get_txrx_vdev_type(uint32_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 /* QCA_IBSS_SUPPORT */ + 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; +} + +/** + * wma_unified_vdev_create_send() - send VDEV create command to fw + * @wmi_handle: wmi handle + * @if_id: vdev id + * @type: vdev type + * @subtype: vdev subtype + * @macaddr: vdev mac address + * + * Return: 0 for success or error code + */ +int wma_unified_vdev_create_send(wmi_unified_t wmi_handle, uint8_t if_id, + uint32_t type, uint32_t subtype, + uint8_t macaddr[IEEE80211_ADDR_LEN]) +{ + wmi_vdev_create_cmd_fixed_param *cmd; + wmi_buf_t buf; + int len = sizeof(*cmd); + int ret; + + 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; + 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]); + 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; +} + +/** + * wma_unified_vdev_delete_send() - send VDEV delete command to fw + * @wmi_handle: wmi handle + * @if_id: vdev id + * + * Return: 0 for success or error code + */ +static int wma_unified_vdev_delete_send(wmi_unified_t wmi_handle, uint8_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; +} + +/** + * wma_find_req() - find target request for vdev id + * @wma: wma handle + * @vdev_id: vdev id + * @type: request type + * + * Return: return target request if found or NULL. + */ +static struct wma_target_req *wma_find_req(tp_wma_handle wma, + uint8_t vdev_id, uint8_t type) +{ + struct wma_target_req *req_msg = NULL; + bool found = false; + cdf_list_node_t *node1 = NULL, *node2 = NULL; + CDF_STATUS status; + + cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); + if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->wma_hold_req_queue, + &node2)) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("unable to get msg node from request queue")); + return NULL; + } + + do { + node1 = node2; + req_msg = cdf_container_of(node1, struct wma_target_req, node); + if (req_msg->vdev_id != vdev_id) + continue; + if (req_msg->type != type) + continue; + + found = true; + status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGD(FL("Failed to remove request for vdev_id %d type %d"), + vdev_id, type); + return NULL; + } + break; + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&wma->wma_hold_req_queue, node1, + &node2)); + + if (!found) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("target request not found for vdev_id %d type %d"), + vdev_id, type); + return NULL; + } + + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGD(FL("target request found for vdev id: %d type %d"), + vdev_id, type); + + return req_msg; +} + +/** + * wma_find_vdev_req() - find target request for vdev id + * @wma: wma handle + * @vdev_id: vdev id + * @type: request type + * + * Return: return target request if found or NULL. + */ +static struct wma_target_req *wma_find_vdev_req(tp_wma_handle wma, + uint8_t vdev_id, uint8_t type) +{ + struct wma_target_req *req_msg = NULL, *tmp; + bool found = false; + + cdf_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; + list_del(&req_msg->node); + break; + } + cdf_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_vdev_detach_callback() - send vdev detach response to upper layer + * @ctx: txrx node ptr + * + * Return: none + */ +void wma_vdev_detach_callback(void *ctx) +{ + tp_wma_handle wma; + struct wma_txrx_node *iface = (struct wma_txrx_node *)ctx; + struct del_sta_self_params *param; + struct wma_target_req *req_msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t sme_msg = { 0 }; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + + if (!wma || !iface->del_staself_req) { + WMA_LOGP("%s: wma %p iface %p", __func__, wma, + iface->del_staself_req); + return; + } + param = (struct del_sta_self_params *) iface->del_staself_req; + WMA_LOGD("%s: sending eWNI_SME_DEL_STA_SELF_RSP for vdev %d", + __func__, param->session_id); + + req_msg = wma_find_vdev_req(wma, param->session_id, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (req_msg) { + WMA_LOGD("%s: Found vdev request for vdev id %d", + __func__, param->session_id); + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + } + if (iface->addBssStaContext) + cdf_mem_free(iface->addBssStaContext); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + cdf_mem_free(iface->staKeyParams); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + cdf_mem_zero(iface, sizeof(*iface)); + param->status = CDF_STATUS_SUCCESS; + sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; + sme_msg.bodyptr = param; + sme_msg.bodyval = 0; + + status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); + cdf_mem_free(param); + } +} + +/** + * wma_vdev_detach() - send vdev delete command to fw + * @wma_handle: wma handle + * @pdel_sta_self_req_param: del sta params + * @generateRsp: generate Response flag + * + * Return: CDF status + */ +CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *pdel_sta_self_req_param, + uint8_t generateRsp) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + uint8_t peer_id; + uint8_t vdev_id = pdel_sta_self_req_param->session_id; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + struct wma_target_req *msg; + cds_msg_t sme_msg = { 0 }; + + 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->self_mac_addr); + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return CDF_STATUS_E_FAULT; + } + + peer = ol_txrx_find_peer_by_addr(pdev, + pdel_sta_self_req_param->self_mac_addr, + &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + pdel_sta_self_req_param->self_mac_addr); + } + wma_remove_peer(wma_handle, + pdel_sta_self_req_param->self_mac_addr, + vdev_id, peer, false); + } + if (cdf_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; + } + + if (!iface->handle) { + WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", + vdev_id); + cdf_mem_free(pdel_sta_self_req_param); + pdel_sta_self_req_param = NULL; + return status; + } + + + /* 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 = CDF_STATUS_E_FAILURE; + goto out; + } + + WMA_LOGA("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); + goto out; + } + + iface->del_staself_req = pdel_sta_self_req_param; + msg = wma_fill_vdev_req(wma_handle, vdev_id, WMA_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 = CDF_STATUS_E_NOMEM; + goto out; + } + WMA_LOGE("Call txrx detach with callback for vdev %d", vdev_id); + ol_txrx_vdev_detach(iface->handle, NULL, NULL); + wma_vdev_detach_callback(iface); + return status; +out: + if (iface->addBssStaContext) + cdf_mem_free(iface->addBssStaContext); +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + cdf_mem_free(iface->staKeyParams); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + cdf_mem_zero(iface, sizeof(*iface)); + pdel_sta_self_req_param->status = status; + if (generateRsp) { + sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; + sme_msg.bodyptr = pdel_sta_self_req_param; + sme_msg.bodyval = 0; + + status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); + cdf_mem_free(pdel_sta_self_req_param); + } + } + return status; +} + +/** + * wmi_unified_peer_delete_send() - send PEER delete command to fw + * @wmi: wmi handle + * @peer_addr: peer mac addr + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +static int32_t wmi_unified_peer_delete_send(wmi_unified_t wmi, + uint8_t + peer_addr[IEEE80211_ADDR_LEN], + uint8_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__); + cdf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +/** + * wma_vdev_start_rsp() - send vdev start response to upper layer + * @wma: wma handle + * @add_bss: add bss params + * @resp_event: response params + * + * Return: none + */ +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 /* QCA_IBSS_SUPPORT */ + + if (resp_event->status) { + add_bss->status = CDF_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 /* QCA_IBSS_SUPPORT */ + ) { + wma->interfaces[resp_event->vdev_id].beacon = + cdf_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 = CDF_STATUS_E_NOMEM; + goto send_fail_resp; + } + cdf_mem_zero(bcn, sizeof(*bcn)); + bcn->buf = cdf_nbuf_alloc(NULL, WMA_BCN_BUF_MAX_SIZE, 0, + sizeof(uint32_t), 0); + if (!bcn->buf) { + WMA_LOGE("%s: No memory allocated for beacon buffer", + __func__); + cdf_mem_free(bcn); + add_bss->status = CDF_STATUS_E_FAILURE; + goto send_fail_resp; + } + bcn->seq_no = MIN_SW_SEQ; + cdf_spinlock_init(&bcn->lock); + cdf_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 = CDF_STATUS_SUCCESS; + add_bss->bssIdx = resp_event->vdev_id; + add_bss->chainMask = resp_event->chain_mask; + if ((2 != resp_event->cfgd_rx_streams) || + (2 != resp_event->cfgd_tx_streams)) { + add_bss->nss = 1; + } + add_bss->smpsMode = host_map_smps_mode(resp_event->smps_mode); + if (WMA_DEFAULT_HW_MODE_INDEX == wma->new_hw_mode_index) { + WMA_LOGE("%s: Invalid index to update for vdev_id %d", + __func__, resp_event->vdev_id); + } else { + wma_update_intf_hw_mode_params(resp_event->vdev_id, + resp_event->mac_id, wma->new_hw_mode_index); + } +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, WMA_ADD_BSS_RSP, (void *)add_bss, 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: none + */ +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 = cdf_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, WMA_UPDATE_Q2Q_IE_IND, (void *)ap_vdev_ids, result); +} +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + +/** + * wma_vdev_start_resp_handler() - vdev start response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf; + wmi_vdev_start_response_event_fixed_param *resp_event; + struct wma_target_req *req_msg; + struct wma_txrx_node *iface; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == mac_ctx) { + WMA_LOGE("%s: Failed to get mac_ctx", __func__); + return -EINVAL; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + WMA_LOGD("%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; + if (!resp_event) { + WMA_LOGE("Invalid start response event buffer"); + return -EINVAL; + } + + if (resp_event->status == CDF_STATUS_SUCCESS) { + wma->interfaces[resp_event->vdev_id].tx_streams = + resp_event->cfgd_tx_streams; + wma->interfaces[resp_event->vdev_id].rx_streams = + resp_event->cfgd_rx_streams; + wma->interfaces[resp_event->vdev_id].chain_mask = + resp_event->chain_mask; + wma->interfaces[resp_event->vdev_id].mac_id = + resp_event->mac_id; + WMA_LOGI("%s: vdev:%d tx ss=%d rx ss=%d chain mask=%d mac=%d", + __func__, + resp_event->vdev_id, + wma->interfaces[resp_event->vdev_id].tx_streams, + wma->interfaces[resp_event->vdev_id].rx_streams, + wma->interfaces[resp_event->vdev_id].chain_mask, + wma->interfaces[resp_event->vdev_id].mac_id); + } + + if ((resp_event->vdev_id <= wma->max_bssid) && + (cdf_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; + } + cdf_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; + } + + cdf_mc_timer_stop(&req_msg->event_timeout); + +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + if (resp_event->status == CDF_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 == WMA_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; + if ((2 != resp_event->cfgd_rx_streams) || + (2 != resp_event->cfgd_tx_streams)) { + params->nss = 1; + } + params->smpsMode = host_map_smps_mode(resp_event->smps_mode); + params->status = resp_event->status; + if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT && + (iface->type == WMI_VDEV_TYPE_STA)) { + 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, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0); + } else if (req_msg->msg_type == WMA_ADD_BSS_REQ) { + tpAddBssParams bssParams = (tpAddBssParams) req_msg->user_data; + cdf_mem_copy(iface->bssid, bssParams->bssId, + IEEE80211_ADDR_LEN); + wma_vdev_start_rsp(wma, bssParams, resp_event); + } else if (req_msg->msg_type == WMA_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); + + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + + return 0; +} + +/** + * wmi_unified_vdev_set_param_send() - set per vdev params in fw + * @wmi_handle: wmi handle + * @if_if: vdev id + * @param_id: parameter id + * @param_value: parameter value + * + * Return: 0 for success or error code + */ +int +wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, uint32_t if_id, + uint32_t param_id, uint32_t param_value) +{ + int ret; + wmi_vdev_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_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; +} + +/** + * wmi_unified_peer_flush_tids_send() - flush peer tids packets in fw + * @wmi: wmi handle + * @peer_addr: peer mac address + * @peer_tid_bitmap: peer tid bitmap + * @vdev_id: vdev id + * + * Return: 0 for sucess or error code + */ +int32_t wmi_unified_peer_flush_tids_send(wmi_unified_t wmi, + uint8_t peer_addr[IEEE80211_ADDR_LEN], + uint32_t peer_tid_bitmap, + uint8_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__); + cdf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +/** + * wma_set_peer_authorized_cb() - set peer authorized callback function + * @wma_Ctx: wma handle + * @auth_cb: peer authorized callback + * + * Return: none + */ +void wma_set_peer_authorized_cb(void *wma_ctx, wma_peer_authorized_fp auth_cb) +{ + tp_wma_handle wma_handle = (tp_wma_handle) wma_ctx; + wma_handle->peer_authorized_cb = auth_cb; +} + +/** + * wma_set_peer_param() - set peer parameter in fw + * @wma_ctx: wma handle + * @peer_addr: peer mac address + * @param_id: parameter id + * @param_value: parameter value + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +int wma_set_peer_param(void *wma_ctx, uint8_t *peer_addr, uint32_t param_id, + uint32_t param_value, uint32_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"); + cdf_mem_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_remove_peer() - send remove peer command to fw + * @wma: wma handle + * @bssid: mac address + * @vdev_id: vdev id + * @peer: peer ptr + * @roam_synch_in_progress: roam in progress flag + * + * Return: none + */ +void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid, + uint8_t vdev_id, ol_txrx_peer_handle peer, + bool roam_synch_in_progress) +{ +#define PEER_ALL_TID_BITMASK 0xffffffff + uint32_t peer_tid_bitmap = PEER_ALL_TID_BITMASK; + uint8_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--; + WMA_LOGE("%s: Removed peer with peer_addr %pM vdevid %d peer_count %d", + __func__, bssid, vdev_id, wma->interfaces[vdev_id].peer_count); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_synch_in_progress) + return; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + /* 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 /* QCA_IBSS_SUPPORT */ + + wmi_unified_peer_delete_send(wma->wmi_handle, peer_addr, vdev_id); +#undef PEER_ALL_TID_BITMASK +} + +/** + * wmi_unified_peer_create_send() - send peer create command to fw + * @wmi: wmi handle + * @peer_addr: peer mac address + * @peer_type: peer type + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +static int wmi_unified_peer_create_send(wmi_unified_t wmi, + const uint8_t *peer_addr, + uint32_t peer_type, uint32_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__); + cdf_nbuf_free(buf); + return -EIO; + } + WMA_LOGD("%s: peer_addr %pM vdev_id %d", __func__, peer_addr, vdev_id); + return 0; +} + +/** + * wma_create_peer() - send peer create command to fw + * @wma: wma handle + * @pdev: txrx pdev ptr + * @vdev: txrx vdev ptr + * @peer_addr: peer mac addr + * @peer_type: peer type + * @vdev_id: vdev id + * @roam_synch_in_progress: roam in progress + * + * Return: CDF status + */ +CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, + u8 peer_addr[IEEE80211_ADDR_LEN], + uint32_t peer_type, uint8_t vdev_id, + bool 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_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); + return CDF_STATUS_SUCCESS; + } +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + 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) && + !cdf_mem_compare(peer_addr, vdev->mac_addr.raw, + IEEE80211_ADDR_LEN)) { + + tSetStaKeyParams key_info; + WMA_LOGD("%s: remote ibss peer %pM key clearing\n", __func__, + peer_addr); + cdf_mem_set(&key_info, sizeof(key_info), 0); + key_info.smesessionId = vdev_id; + cdf_mem_copy(key_info.peerMacAddr, peer_addr, + IEEE80211_ADDR_LEN); + key_info.sendRsp = false; + + wma_set_stakey(wma, &key_info); + } +#endif /* QCA_IBSS_SUPPORT */ + + return CDF_STATUS_SUCCESS; +err: + wma->interfaces[vdev_id].peer_count--; + return CDF_STATUS_E_FAILURE; +} + +/** + * wmi_unified_vdev_down_send() - send vdev down command to fw + * @wmi: wmi handle + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +static int wmi_unified_vdev_down_send(wmi_unified_t wmi, uint8_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__); + cdf_nbuf_free(buf); + return -EIO; + } + WMA_LOGE("%s: vdev_id %d", __func__, vdev_id); + return 0; +} + +#ifdef QCA_IBSS_SUPPORT + +/** + * wma_delete_all_ibss_peers() - delete all ibss peer for vdev_id + * @wma: wma handle + * @vdev_id: vdev id + * + * This function send peer delete command to fw for all + * peers in peer_list and remove ref count for peer id + * peer will actually remove from list after receving + * unmap event from firmware. + * + * Return: none + */ +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 */ + cdf_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) { + cdf_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); + if (cdf_atomic_read(&temp->delete_in_progress) == 0) { + wma_remove_peer(wma, temp->mac_addr.raw, + vdev_id, temp, false); + } + cdf_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; + } + cdf_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, + false); +} + +#endif /* QCA_IBSS_SUPPORT */ + +/** + * wma_delete_all_ap_remote_peers() - delete all ap peer for vdev_id + * @wma: wma handle + * @vdev_id: vdev id + * + * This function send peer delete command to fw for all + * peers in peer_list and remove ref count for peer id + * peer will actually remove from list after receving + * unmap event from firmware. + * + * Return: none + */ +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 */ + cdf_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) { + cdf_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); + if (cdf_atomic_read(&temp->delete_in_progress) == 0) { + wma_remove_peer(wma, temp->mac_addr.raw, + vdev_id, temp, false); + } + cdf_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; + } + + cdf_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); +} + +#ifdef QCA_IBSS_SUPPORT + +/** + * wma_recreate_ibss_vdev_and_bss_peer() - recreate IBSS vdev and create peer + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +static void wma_recreate_ibss_vdev_and_bss_peer(tp_wma_handle wma, + uint8_t vdev_id) +{ + ol_txrx_vdev_handle vdev; + struct add_sta_self_params add_sta_self_param; + struct del_sta_self_params del_sta_param; + CDF_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; + } + + cdf_copy_macaddr( + (struct cdf_mac_addr *) &(add_sta_self_param.self_mac_addr), + (struct cdf_mac_addr *) &(vdev->mac_addr)); + add_sta_self_param.session_id = vdev_id; + add_sta_self_param.type = WMI_VDEV_TYPE_IBSS; + add_sta_self_param.sub_type = 0; + add_sta_self_param.status = 0; + + /* delete old ibss vdev */ + del_sta_param.session_id = vdev_id; + cdf_mem_copy((void *)del_sta_param.self_mac_addr, + (void *)&(vdev->mac_addr), CDF_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; + } + + /* Register with TxRx Module for Data Ack Complete Cb */ + ol_txrx_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.self_mac_addr); + + /* create ibss bss peer */ + status = wma_create_peer(wma, vdev->pdev, vdev, vdev->mac_addr.raw, + WMI_PEER_TYPE_DEFAULT, vdev_id, false); + if (status != CDF_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 /* QCA_IBSS_SUPPORT */ + +/** + * wma_hidden_ssid_vdev_restart_on_vdev_stop() - restart vdev to set hidden ssid + * @wma_handle: wma handle + * @sessionId: session id + * + * Return: none + */ +void wma_hidden_ssid_vdev_restart_on_vdev_stop(tp_wma_handle wma_handle, + uint8_t sessionId) +{ + wmi_vdev_start_request_cmd_fixed_param *cmd; + wmi_buf_t buf; + wmi_channel *chan; + int32_t len; + uint8_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__); + cdf_atomic_set(&intr[sessionId].vdev_restart_params. + hidden_ssid_restart_in_progress, 0); + return; + } + buf_ptr = (uint8_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; + cdf_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 = (uint8_t *) (((uint8_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__); + cdf_atomic_set(&intr[sessionId].vdev_restart_params. + hidden_ssid_restart_in_progress, 0); + cdf_nbuf_free(buf); + } +} + +/** + * wma_vdev_stop_resp_handler() - vdev stop response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, + u32 len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_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; + uint8_t peer_id; + struct wma_txrx_node *iface; + int32_t status = 0; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = cds_get_context(CDF_MODULE_ID_PE); + 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__); + param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid event buffer"); + return -EINVAL; + } + resp_event = param_buf->fixed_param; + + if ((resp_event->vdev_id <= wma->max_bssid) && + (cdf_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 = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + WMA_LOGE("%s: pdev is NULL", __func__); + status = -EINVAL; + cdf_mc_timer_stop(&req_msg->event_timeout); + goto free_req_msg; + } + + cdf_mc_timer_stop(&req_msg->event_timeout); + if (req_msg->msg_type == WMA_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 /* QCA_IBSS_SUPPORT */ + { + 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, 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); + ol_txrx_vdev_unpause(iface->handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + iface->pause_bitmap &= ~(1 << PAUSE_TYPE_HOST); + cdf_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) + cdf_nbuf_unmap_single(pdev->osdev, bcn->buf, + CDF_DMA_TO_DEVICE); + cdf_nbuf_free(bcn->buf); + cdf_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 /* QCA_IBSS_SUPPORT */ + /* 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 == CDF_STATUS_FW_MSG_TIMEDOUT) { + cdf_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 = CDF_STATUS_SUCCESS; + wma_send_msg(wma, WMA_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: + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + return status; +} + +/** + * wma_vdev_attach() - create vdev in fw + * @wma_handle: wma handle + * @self_sta_req: self sta request + * @generateRsp: generate response + * + * This function creates vdev in target and + * attach this vdev to txrx module. It also set + * vdev related params to fw. + * + * Return: txrx vdev handle + */ +ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, + struct add_sta_self_params *self_sta_req, + uint8_t generateRsp) +{ + ol_txrx_vdev_handle txrx_vdev_handle = NULL; + ol_txrx_pdev_handle txrx_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + enum wlan_op_mode txrx_vdev_type; + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + uint32_t cfg_val; + uint16_t val16; + int ret; + tSirMacHTCapabilityInfo *phtCapInfo; + cds_msg_t sme_msg = { 0 }; + + 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->session_id, + self_sta_req->type, + self_sta_req->sub_type, + self_sta_req->self_mac_addr)) { + WMA_LOGP("%s: Unable to add an interface for ath_dev", + __func__); + status = CDF_STATUS_E_RESOURCES; + goto end; + } + + txrx_vdev_type = wma_get_txrx_vdev_type(self_sta_req->type); + + if (wlan_op_mode_unknown == txrx_vdev_type) { + WMA_LOGE("Failed to get txrx vdev type"); + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->session_id); + goto end; + } + + txrx_vdev_handle = ol_txrx_vdev_attach(txrx_pdev, + self_sta_req->self_mac_addr, + self_sta_req->session_id, + txrx_vdev_type); + wma_handle->interfaces[self_sta_req->session_id].pause_bitmap = 0; + + WMA_LOGA("vdev_id %hu, txrx_vdev_handle = %p", self_sta_req->session_id, + txrx_vdev_handle); + + if (NULL == txrx_vdev_handle) { + WMA_LOGP("%s: ol_txrx_vdev_attach failed", __func__); + status = CDF_STATUS_E_FAILURE; + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->session_id); + goto end; + } + wma_handle->interfaces[self_sta_req->session_id].handle = + txrx_vdev_handle; + + wma_handle->interfaces[self_sta_req->session_id].ptrn_match_enable = + wma_handle->ptrn_match_enable_all_vdev ? true : false; + + if (wlan_cfg_get_int(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_cfg_get_int(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_cfg_get_int(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; + + cdf_mem_copy(wma_handle->interfaces[self_sta_req->session_id].addr, + self_sta_req->self_mac_addr, + sizeof(wma_handle->interfaces[self_sta_req->session_id]. + addr)); + switch (self_sta_req->type) { + case WMI_VDEV_TYPE_STA: + if (wlan_cfg_get_int(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->session_id, + SIR_KEEP_ALIVE_NULL_PKT, + cfg_val, NULL, NULL, NULL); + break; + } + + wma_handle->interfaces[self_sta_req->session_id].type = + self_sta_req->type; + wma_handle->interfaces[self_sta_req->session_id].sub_type = + self_sta_req->sub_type; + cdf_atomic_init(&wma_handle->interfaces + [self_sta_req->session_id].bss_status); + + if (((self_sta_req->type == WMI_VDEV_TYPE_AP) && + (self_sta_req->sub_type == 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->self_mac_addr, self_sta_req->session_id); + status = wma_create_peer(wma_handle, txrx_pdev, + txrx_vdev_handle, + self_sta_req->self_mac_addr, + WMI_PEER_TYPE_DEFAULT, + self_sta_req->session_id, false); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to create peer", __func__); + status = CDF_STATUS_E_FAILURE; + wma_unified_vdev_delete_send(wma_handle->wmi_handle, + self_sta_req->session_id); + } + } + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + WMI_VDEV_PARAM_MCC_RTSCTS_PROTECTION_ENABLE, + mac->roam.configParam.mcc_rts_cts_prot_enable); + if (ret) + WMA_LOGE("Failed to set WMI VDEV MCC_RTSCTS_PROTECTION_ENABLE"); + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE, + mac->roam.configParam.mcc_bcast_prob_resp_enable); + if (ret) + WMA_LOGE("Failed to set WMI VDEV MCC_BROADCAST_PROBE_ENABLE"); + + if (wlan_cfg_get_int(mac, WNI_CFG_RTS_THRESHOLD, + &cfg_val) == eSIR_SUCCESS) { + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + 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_cfg_get_int(mac, WNI_CFG_FRAGMENTATION_THRESHOLD, + &cfg_val) == eSIR_SUCCESS) { + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + 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_cfg_get_int(mac, WNI_CFG_HT_CAP_INFO, &cfg_val) == eSIR_SUCCESS) { + val16 = (uint16_t) cfg_val; + phtCapInfo = (tSirMacHTCapabilityInfo *) &cfg_val; + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + 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->sub_type == 0)) { + wma_handle->roam_offload_enabled = true; + wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, + self_sta_req->session_id, + 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->sub_type == 0)) + wma_roam_scan_bmiss_cnt(wma_handle, + mac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt, + mac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt, + self_sta_req->session_id); + + if (wlan_cfg_get_int(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 != CDF_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"); + } + + wma_register_wow_wakeup_events(wma_handle, self_sta_req->session_id, + self_sta_req->type, + self_sta_req->sub_type); + wma_register_wow_default_patterns(wma_handle, self_sta_req->session_id); + +end: + self_sta_req->status = status; + +#ifdef QCA_IBSS_SUPPORT + if (generateRsp) +#endif + { + sme_msg.type = eWNI_SME_ADD_STA_SELF_RSP; + sme_msg.bodyptr = self_sta_req; + sme_msg.bodyval = 0; + + status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); + cdf_mem_free(self_sta_req); + } + } + return txrx_vdev_handle; +} + +/** + * wma_get_center_channel() - get center channel + * @chan: channel number + * @chan_offset: channel offset + * + * Return: center channel + */ +uint8_t wma_get_center_channel(uint8_t chan, uint8_t chan_offset) +{ + uint8_t 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; +} + +/** + * wma_vdev_start() - send vdev start request to fw + * @wma: wma handle + * @req: vdev start params + * @isRestart: isRestart flag + * + * Return: CDF status + */ +CDF_STATUS wma_vdev_start(tp_wma_handle wma, + struct wma_vdev_start_req *req, bool isRestart) +{ + wmi_vdev_start_request_cmd_fixed_param *cmd; + wmi_buf_t buf; + wmi_channel *chan; + int32_t len, ret; + WLAN_PHY_MODE chanmode; + uint8_t *buf_ptr; + struct wma_txrx_node *intr = wma->interfaces; + tpAniSirGlobal mac_ctx = NULL; + struct ath_dfs *dfs; + + mac_ctx = cds_get_context(CDF_MODULE_ID_PE); + if (mac_ctx == NULL) { + WMA_LOGE("%s: vdev start failed as mac_ctx is NULL", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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 = cds_chan_to_freq(req->chan); + chanmode = wma_chan_to_mode(req->chan, req->chan_width, + req->vht_capable, req->dot11_mode); + + intr[cmd->vdev_id].chanmode = chanmode; /* save channel mode */ + intr[cmd->vdev_id].ht_capable = req->ht_capable; + intr[cmd->vdev_id].vht_capable = req->vht_capable; + intr[cmd->vdev_id].config.gtx_info.gtxRTMask[0] = + CFG_TGT_DEFAULT_GTX_HT_MASK; + intr[cmd->vdev_id].config.gtx_info.gtxRTMask[1] = + CFG_TGT_DEFAULT_GTX_VHT_MASK; + intr[cmd->vdev_id].config.gtx_info.gtxUsrcfg = + CFG_TGT_DEFAULT_GTX_USR_CFG; + intr[cmd->vdev_id].config.gtx_info.gtxPERThreshold = + CFG_TGT_DEFAULT_GTX_PER_THRESHOLD; + intr[cmd->vdev_id].config.gtx_info.gtxPERMargin = + CFG_TGT_DEFAULT_GTX_PER_MARGIN; + intr[cmd->vdev_id].config.gtx_info.gtxTPCstep = + CFG_TGT_DEFAULT_GTX_TPC_STEP; + intr[cmd->vdev_id].config.gtx_info.gtxTPCMin = + CFG_TGT_DEFAULT_GTX_TPC_MIN; + intr[cmd->vdev_id].config.gtx_info.gtxBWMask = + CFG_TGT_DEFAULT_GTX_BW_MASK; + intr[cmd->vdev_id].mhz = chan->mhz; + + WMI_SET_CHANNEL_MODE(chan, chanmode); + chan->band_center_freq1 = chan->mhz; + + if (CH_WIDTH_20MHZ != req->chan_width) + chan->band_center_freq1 = + cds_chan_to_freq(req->ch_center_freq_seg0); + if (CH_WIDTH_80P80MHZ == req->chan_width) + chan->band_center_freq2 = + cds_chan_to_freq(req->ch_center_freq_seg1); + else + 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 = 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__); + + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + + cdf_mutex_acquire(&wma->dfs_ic->chan_lock); + if (wma->dfs_ic->ic_curchan) { + OS_FREE(wma->dfs_ic->ic_curchan); + wma->dfs_ic->ic_curchan = NULL; + } + + /* provide the current channel to DFS */ + wma->dfs_ic->ic_curchan = + wma_dfs_configure_channel(wma->dfs_ic, chan, + chanmode, req); + cdf_mutex_release(&wma->dfs_ic->chan_lock); + + wma_unified_dfs_phyerr_filter_offload_enable(wma); + dfs->disable_dfs_ch_switch = + mac_ctx->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); + cdf_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; + cmd->preferred_rx_streams = req->preferred_rx_streams; + cmd->preferred_tx_streams = req->preferred_tx_streams; + + buf_ptr = (uint8_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_LOGA("\n%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 " + "Tx SS %d, Rx SS %d", + __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, + req->preferred_tx_streams, req->preferred_rx_streams); + + /* 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; + cdf_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_freq2; + 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); + ol_txrx_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__); + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_peer_assoc_conf_handler() - peer assoc conf handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_peer_assoc_conf_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PEER_ASSOC_CONF_EVENTID_param_tlvs *param_buf; + wmi_peer_assoc_conf_event_fixed_param *event; + struct wma_target_req *req_msg; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + int status = 0; + + WMA_LOGD(FL("Enter")); + param_buf = (WMI_PEER_ASSOC_CONF_EVENTID_param_tlvs *) cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid peer assoc conf event buffer"); + return -EINVAL; + } + + event = param_buf->fixed_param; + if (!event) { + WMA_LOGE("Invalid peer assoc conf event buffer"); + return -EINVAL; + } + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->peer_macaddr, macaddr); + WMA_LOGD(FL("peer assoc conf for vdev:%d mac=%pM"), + event->vdev_id, macaddr); + + req_msg = wma_find_req(wma, event->vdev_id, + WMA_PEER_ASSOC_CNF_START); + + if (!req_msg) { + WMA_LOGE(FL("Failed to lookup request message for vdev %d"), + event->vdev_id); + return -EINVAL; + } + + cdf_mc_timer_stop(&req_msg->event_timeout); + + if (req_msg->msg_type == WMA_ADD_STA_REQ) { + tpAddStaParams params = (tpAddStaParams)req_msg->user_data; + if (!params) { + WMA_LOGE(FL("add STA params is NULL for vdev %d"), + event->vdev_id); + status = -EINVAL; + goto free_req_msg; + } + + /* peer assoc conf event means the cmd succeeds */ + params->status = CDF_STATUS_SUCCESS; + WMA_LOGE(FL("Send ADD_STA_RSP: statype %d vdev_id %d aid %d bssid %pM staIdx %d status %d"), + params->staType, params->smesessionId, + params->assocId, params->bssId, params->staIdx, + params->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)params, 0); + } else if (req_msg->msg_type == WMA_ADD_BSS_REQ) { + tpAddBssParams params = (tpAddBssParams) req_msg->user_data; + if (!params) { + WMA_LOGE(FL("add BSS params is NULL for vdev %d"), + event->vdev_id); + status = -EINVAL; + goto free_req_msg; + } + + /* peer assoc conf event means the cmd succeeds */ + params->status = CDF_STATUS_SUCCESS; + WMA_LOGE(FL("Send ADD BSS RSP: opermode %d update_bss %d nw_type %d bssid %pM" + " staIdx %d status %d"), params->operMode, + params->updateBss, params->nwType, params->bssId, + params->staContext.staIdx, params->status); + wma_send_msg(wma, WMA_ADD_BSS_RSP, (void *)params, 0); + } else { + WMA_LOGE(FL("Unhandled request message type: %d"), + req_msg->msg_type); + } + +free_req_msg: + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + + return status; +} + +/** + * wma_hold_req_timer() - wma hold request timeout function + * @data: target request params + * + * Return: none + */ +void wma_hold_req_timer(void *data) +{ + tp_wma_handle wma; + struct wma_target_req *tgt_req = (struct wma_target_req *)data; + struct wma_target_req *msg; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == wma) { + WMA_LOGE(FL("Failed to get wma")); + goto free_tgt_req; + } + + WMA_LOGA(FL("request %d is timed out for vdev_id - %d"), + tgt_req->msg_type, tgt_req->vdev_id); + msg = wma_find_req(wma, tgt_req->vdev_id, tgt_req->type); + + if (!msg) { + WMA_LOGE(FL("Failed to lookup request message - %d"), + tgt_req->msg_type); + goto free_tgt_req; + } + + if (tgt_req->msg_type == WMA_ADD_STA_REQ) { + tpAddStaParams params = (tpAddStaParams) tgt_req->user_data; + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA(FL("WMA_ADD_STA_REQ timed out")); + WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"), + params->staMac, params->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)params, 0); + } +free_tgt_req: + cdf_mc_timer_destroy(&tgt_req->event_timeout); + cdf_mem_free(tgt_req); +} + +/** + * wma_fill_hold_req() - fill wma request + * @wma: wma handle + * @msg_type: message type + * @type: request type + * @params: request params + * @timeout: timeout value + * + * Return: wma_target_req ptr + */ +struct wma_target_req *wma_fill_hold_req(tp_wma_handle wma, + uint8_t vdev_id, + uint32_t msg_type, uint8_t type, + void *params, uint32_t timeout) +{ + struct wma_target_req *req; + CDF_STATUS status; + + req = cdf_mem_malloc(sizeof(*req)); + if (!req) { + WMA_LOGP(FL("Failed to allocate memory for msg %d vdev %d"), + msg_type, vdev_id); + return NULL; + } + + WMA_LOGE(FL("vdev_id %d msg %d type %d"), vdev_id, msg_type, type); + req->vdev_id = vdev_id; + req->msg_type = msg_type; + req->type = type; + req->user_data = params; + cdf_mc_timer_init(&req->event_timeout, CDF_TIMER_TYPE_SW, + wma_hold_req_timer, req); + cdf_mc_timer_start(&req->event_timeout, timeout); + cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); + status = cdf_list_insert_back(&wma->wma_hold_req_queue, &req->node); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("Failed add request in queue")); + cdf_mem_free(req); + return NULL; + } + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + return req; +} + +/** + * wma_remove_req() - remove request + * @wma: wma handle + * @vdev_id: vdev id + * @type: type + * + * Return: none + */ +void wma_remove_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type) +{ + struct wma_target_req *req_msg; + + WMA_LOGE(FL("Remove req for vdev: %d type: %d"), vdev_id, type); + req_msg = wma_find_req(wma, vdev_id, type); + if (!req_msg) { + WMA_LOGE(FL("target req not found for vdev: %d type: %d"), + vdev_id, type); + return; + } + + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); +} + +/** + * wma_vdev_resp_timer() - wma response timeout function + * @data: target request params + * + * Return: none + */ +void wma_vdev_resp_timer(void *data) +{ + tp_wma_handle wma; + struct wma_target_req *tgt_req = (struct wma_target_req *)data; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + uint8_t peer_id; + struct wma_target_req *msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + cds_msg_t sme_msg = { 0 }; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + tpAniSirGlobal mac_ctx = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == mac_ctx) { + WMA_LOGE("%s: Failed to get mac_ctx", __func__); + goto free_tgt_req; + } +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + wma = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + goto free_tgt_req; + } + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + cdf_mc_timer_stop(&tgt_req->event_timeout); + goto free_tgt_req; + } + + 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); + goto free_tgt_req; + } + + if (tgt_req->msg_type == WMA_CHNL_SWITCH_REQ) { + tpSwitchChannelParams params = + (tpSwitchChannelParams) tgt_req->user_data; + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WMA_SWITCH_CHANNEL_REQ timedout", __func__); + wma_send_msg(wma, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0); + wma->roam_preauth_chan_context = NULL; + wma->roam_preauth_scan_id = -1; + } else if (tgt_req->msg_type == WMA_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); + cdf_mc_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); + cdf_mc_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 /* QCA_IBSS_SUPPORT */ + { + 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, 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); + ol_txrx_vdev_unpause(iface->handle, + OL_TXQ_PAUSE_REASON_VDEV_STOP); + iface->pause_bitmap &= ~(1 << PAUSE_TYPE_HOST); + cdf_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) + cdf_nbuf_unmap_single(pdev->osdev, bcn->buf, + CDF_DMA_TO_DEVICE); + cdf_nbuf_free(bcn->buf); + cdf_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 /* QCA_IBSS_SUPPORT */ + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WMA_DELETE_BSS_REQ timedout", __func__); + wma_send_msg(wma, WMA_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 == WMA_DEL_STA_SELF_REQ) { + struct wma_txrx_node *iface = + (struct wma_txrx_node *)tgt_req->user_data; + struct del_sta_self_params *params = + (struct del_sta_self_params *) iface->del_staself_req; + + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WMA_DEL_STA_SELF_REQ timedout", __func__); + sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; + sme_msg.bodyptr = iface->del_staself_req; + sme_msg.bodyval = 0; + + status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); + cdf_mem_free(iface->del_staself_req); + } + if (iface->addBssStaContext) + cdf_mem_free(iface->addBssStaContext); +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) + cdf_mem_free(iface->staKeyParams); +#endif /* WLAN_FEATURE_VOWIFI_11R */ + cdf_mem_zero(iface, sizeof(*iface)); + } else if (tgt_req->msg_type == WMA_ADD_BSS_REQ) { + tpAddBssParams params = (tpAddBssParams) tgt_req->user_data; + tDeleteBssParams *del_bss_params = + cdf_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 = + CDF_STATUS_FW_MSG_TIMEDOUT; + del_bss_params->sessionId = params->sessionId; + del_bss_params->bssIdx = params->bssIdx; + cdf_mem_copy(del_bss_params->bssid, params->bssId, + sizeof(tSirMacAddr)); + + WMA_LOGA("%s: WMA_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, WMA_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); + ol_txrx_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, WMA_ADD_BSS_RSP, (void *)params, 0); + goto free_tgt_req; +error0: + if (peer) + wma_remove_peer(wma, params->bssId, + tgt_req->vdev_id, peer, false); + wma_send_msg(wma, WMA_ADD_BSS_RSP, (void *)params, 0); + } else if (tgt_req->msg_type == WMA_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, CDF_STATUS_E_TIMEOUT); + } +free_tgt_req: + cdf_mc_timer_destroy(&tgt_req->event_timeout); + cdf_mem_free(tgt_req); +} + +/** + * wma_fill_vdev_req() - fill vdev request + * @wma: wma handle + * @msg_type: message type + * @type: request type + * @params: request params + * @timeout: timeout value + * + * Return: wma_target_req ptr + */ +struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, + uint8_t vdev_id, + uint32_t msg_type, uint8_t type, + void *params, uint32_t timeout) +{ + struct wma_target_req *req; + + req = cdf_mem_malloc(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; + cdf_mc_timer_init(&req->event_timeout, CDF_TIMER_TYPE_SW, + wma_vdev_resp_timer, req); + cdf_mc_timer_start(&req->event_timeout, timeout); + cdf_spin_lock_bh(&wma->vdev_respq_lock); + list_add_tail(&req->node, &wma->vdev_resp_queue); + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + return req; +} + +/** + * wma_remove_vdev_req() - remove vdev request + * @wma: wma handle + * @vdev_id: vdev id + * @type: type + * + * Return: none + */ +void wma_remove_vdev_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type) +{ + struct wma_target_req *req_msg; + + req_msg = wma_find_vdev_req(wma, vdev_id, type); + if (!req_msg) + return; + + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); +} + +/** + * wma_vdev_set_bss_params() - BSS set params functions + * @wma: wma handle + * @vdev_id: vdev id + * @beaconInterval: beacon interval + * @dtimPeriod: DTIM period + * @shortSlotTimeSupported: short slot time + * @llbCoexist: llbCoexist + * @maxTxPower: max tx power + * + * Return: none + */ +static void +wma_vdev_set_bss_params(tp_wma_handle wma, int vdev_id, + tSirMacBeaconInterval beaconInterval, + uint8_t dtimPeriod, uint8_t shortSlotTimeSupported, + uint8_t 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); +} + +/** + * wma_add_bss_ap_mode() - process add bss request in ap mode + * @wma: wma handle + * @add_bss: add bss parameters + * + * Return: none + */ +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; + uint8_t vdev_id, peer_id; + CDF_STATUS status; + tPowerdBm maxTxPower; +#ifdef WLAN_FEATURE_11W + int ret = 0; +#endif /* WLAN_FEATURE_11W */ + struct sir_hw_mode_params hw_mode = {0}; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + 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; + } + if (SAP_WPS_DISABLED == add_bss->wps_state) + wma_enable_disable_wakeup_event(wma, vdev_id, + (1 << WOW_PROBE_REQ_WPS_IE_EVENT), false); + 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, false); + if (status != CDF_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, WMA_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); + + cdf_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_width = add_bss->ch_width; + req.ch_center_freq_seg0 = add_bss->ch_center_freq_seg0; + req.ch_center_freq_seg1 = add_bss->ch_center_freq_seg1; + 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 /* WLAN_FEATURE_VOWIFI */ +#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) + cdf_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + status = wma_get_current_hw_mode(&hw_mode); + if (!CDF_IS_STATUS_SUCCESS(status)) + WMA_LOGE("wma_get_current_hw_mode failed"); + + if ((add_bss->nss == 2) && !hw_mode.dbs_cap) { + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + } else { + req.preferred_rx_streams = 1; + req.preferred_tx_streams = 1; + } + + status = wma_vdev_start(wma, &req, false); + if (status != CDF_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, false); +send_fail_resp: + add_bss->status = CDF_STATUS_E_FAILURE; + wma_send_msg(wma, WMA_ADD_BSS_RSP, (void *)add_bss, 0); +} + +#ifdef QCA_IBSS_SUPPORT +/** + * wma_add_bss_ibss_mode() - process add bss request in IBSS mode + * @wma: wma handle + * @add_bss: add bss parameters + * + * Return: none + */ +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; + uint8_t vdev_id, peer_id; + CDF_STATUS status; + struct add_sta_self_params add_sta_self_param; + struct del_sta_self_params del_sta_param; + tSetBssKeyParams key_info; + struct sir_hw_mode_params hw_mode = {0}; + + WMA_LOGD("%s: add_bss->sessionId = %d", __func__, add_bss->sessionId); + vdev_id = add_bss->sessionId; + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + goto send_fail_resp; + } + 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, (uint8_t *) &vdev->mac_addr, + vdev_id, peer, false); + } + + /* remove the non-ibss vdev */ + cdf_copy_macaddr( + (struct cdf_mac_addr *) &(del_sta_param.self_mac_addr), + (struct cdf_mac_addr *) &(vdev->mac_addr)); + del_sta_param.session_id = vdev_id; + del_sta_param.status = 0; + + wma_vdev_detach(wma, &del_sta_param, 0); + + /* create new vdev for ibss */ + cdf_copy_macaddr((struct cdf_mac_addr *) & + (add_sta_self_param.self_mac_addr), + (struct cdf_mac_addr *) &(add_bss->selfMacAddr)); + add_sta_self_param.session_id = vdev_id; + add_sta_self_param.type = WMI_VDEV_TYPE_IBSS; + add_sta_self_param.sub_type = 0; + add_sta_self_param.status = 0; + + vdev = wma_vdev_attach(wma, &add_sta_self_param, 0); + if (!vdev) { + WMA_LOGE("%s: Failed to create vdev", __func__); + goto send_fail_resp; + } + + /* Register with TxRx Module for Data Ack Complete Cb */ + ol_txrx_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, + false); + if (status != CDF_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__); + cdf_mem_set(&key_info, sizeof(key_info), 0); + key_info.smesessionId = vdev_id; + key_info.numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; + cdf_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, WMA_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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to Set IBSS Power Save Params to firmware", + __func__); + goto peer_cleanup; + } + } + + cdf_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_width = add_bss->ch_width; + req.ch_center_freq_seg0 = add_bss->ch_center_freq_seg0; + req.ch_center_freq_seg1 = add_bss->ch_center_freq_seg1; + req.vht_capable = add_bss->vhtCapable; +#if defined WLAN_FEATURE_VOWIF + req.max_txpow = add_bss->maxTxPower; +#else + req.max_txpow = 0; +#endif /* WLAN_FEATURE_VOWIF */ + 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) + cdf_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + status = wma_get_current_hw_mode(&hw_mode); + if (!CDF_IS_STATUS_SUCCESS(status)) + WMA_LOGE("wma_get_current_hw_mode failed"); + + if ((add_bss->nss == 2) && !hw_mode.dbs_cap) { + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + } else { + req.preferred_rx_streams = 1; + req.preferred_tx_streams = 1; + } + + WMA_LOGD("%s: chan %d chan_width %d", __func__, req.chan, + req.chan_width); + WMA_LOGD("%s: ssid = %s", __func__, req.ssid.ssId); + + status = wma_vdev_start(wma, &req, false); + if (status != CDF_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, false); + } +send_fail_resp: + add_bss->status = CDF_STATUS_E_FAILURE; + wma_send_msg(wma, WMA_ADD_BSS_RSP, (void *)add_bss, 0); +} +#endif /* QCA_IBSS_SUPPORT */ + +/** + * wma_add_bss_sta_mode() - process add bss request in sta mode + * @wma: wma handle + * @add_bss: add bss parameters + * + * Return: none + */ +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; + uint8_t vdev_id, peer_id; + ol_txrx_peer_handle peer; + CDF_STATUS status; + struct wma_txrx_node *iface; + int ret = 0; + int pps_val = 0; + bool roam_synch_in_progress = false; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + struct sir_hw_mode_params hw_mode = {0}; + bool peer_assoc_sent = false; + + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + goto send_fail_resp; + } + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + 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 WMA_ADD_STA_REQ */ + if (iface->addBssStaContext) { + cdf_mem_free(iface->addBssStaContext); + } + iface->addBssStaContext = cdf_mem_malloc(sizeof(tAddStaParams)); + if (!iface->addBssStaContext) { + WMA_LOGE("%s Failed to allocat memory", __func__); + goto send_fail_resp; + } + cdf_mem_copy(iface->addBssStaContext, &add_bss->staContext, + sizeof(tAddStaParams)); + +#if defined WLAN_FEATURE_VOWIFI_11R + if (iface->staKeyParams) { + cdf_mem_free(iface->staKeyParams); + iface->staKeyParams = NULL; + } + if (add_bss->extSetStaKeyParamValid) { + iface->staKeyParams = + cdf_mem_malloc(sizeof(tSetStaKeyParams)); + if (!iface->staKeyParams) { + WMA_LOGE("%s Failed to allocat memory", + __func__); + goto send_fail_resp; + } + cdf_mem_copy(iface->staKeyParams, + &add_bss->extSetStaKeyParam, + sizeof(tSetStaKeyParams)); + } +#endif /* WLAN_FEATURE_VOWIFI_11R */ + /* Save parameters later needed by WMA_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) { +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + 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, WMA_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); + + cdf_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + req.chan = add_bss->currentOperChannel; + req.chan_width = add_bss->ch_width; + req.ch_center_freq_seg0 = add_bss->ch_center_freq_seg0; + req.ch_center_freq_seg1 = add_bss->ch_center_freq_seg1; +#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) + cdf_mem_copy(req.ssid.ssId, add_bss->ssId.ssId, + add_bss->ssId.length); + status = wma_get_current_hw_mode(&hw_mode); + if (!CDF_IS_STATUS_SUCCESS(status)) + WMA_LOGE("wma_get_current_hw_mode failed"); + + if ((add_bss->nss == 2) && !hw_mode.dbs_cap) { + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + } else { + req.preferred_rx_streams = 1; + req.preferred_tx_streams = 1; + } + + status = wma_vdev_start(wma, &req, false); + if (status != CDF_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + goto peer_cleanup; + } +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + vdev = wma_find_vdev_by_id(wma, vdev_id); + if (!vdev) { + WMA_LOGE("%s Invalid txrx vdev", __func__); + goto peer_cleanup; + } + ol_txrx_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 { +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + 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); +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + 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; + } + ol_txrx_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); + peer_assoc_sent = true; +#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. + */ + cdf_mem_copy(iface->bssid, add_bss->bssId, IEEE80211_ADDR_LEN); + + } +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) ? + CDF_STATUS_E_FAILURE : CDF_STATUS_SUCCESS; + add_bss->bssIdx = add_bss->staContext.smesessionId; + cdf_mem_copy(add_bss->staContext.staMac, add_bss->bssId, + sizeof(add_bss->staContext.staMac)); + + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_PEER_ASSOC_CONF)) { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF not enabled")); + goto send_final_rsp; + } + + /* In case of reassoc, peer assoc cmd will not be sent */ + if (!peer_assoc_sent) + goto send_final_rsp; + + msg = wma_fill_hold_req(wma, vdev_id, WMA_ADD_BSS_REQ, + WMA_PEER_ASSOC_CNF_START, add_bss, + WMA_PEER_ASSOC_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to allocate request for vdev_id %d"), + vdev_id); + wma_remove_req(wma, vdev_id, WMA_PEER_ASSOC_CNF_START); + goto peer_cleanup; + } + return; + +send_final_rsp: + 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, WMA_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 = CDF_STATUS_E_FAILURE; + wma_send_msg(wma, WMA_ADD_BSS_RSP, (void *)add_bss, 0); +} + +/** + * wma_add_bss() - Add BSS request to fw as per opmode + * @wma: wma handle + * @params: add bss params + * + * Return: none + */ +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 CDF_SAP_MODE: + case CDF_P2P_GO_MODE: + /*If current bring up SAP/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 CDF_IBSS_MODE: + wma_add_bss_ibss_mode(wma, params); + break; +#endif + + default: + wma_add_bss_sta_mode(wma, params); + break; + } +} + +/** + * wmi_unified_vdev_up_send() - send vdev up command in fw + * @wmi: wmi handle + * @vdev_id: vdev id + * @aid: association ID + * @bssid: bssid + * + * Return: 0 for success or error code + */ +int wmi_unified_vdev_up_send(wmi_unified_t wmi, + uint8_t vdev_id, uint16_t aid, + uint8_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__); + cdf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_add_sta_req_ap_mode() - process add sta request in ap mode + * @wma: wma handle + * @add_sta: add sta params + * + * Return: none + */ +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; + uint8_t peer_id; + CDF_STATUS status; + int32_t ret; +#ifdef WLAN_FEATURE_11W + struct wma_txrx_node *iface = NULL; +#endif /* WLAN_FEATURE_11W */ + struct wma_target_req *msg; + bool peer_assoc_cnf = false; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + add_sta->status = CDF_STATUS_E_FAILURE; + goto send_rsp; + } + /* UMAC sends WMA_ADD_STA_REQ msg twice to WMA when the station + * associates. First WMA_ADD_STA_REQ will have staType as + * STA_ENTRY_PEER and second posting will have STA_ENTRY_SELF. + * Peer creation is done in first WMA_ADD_STA_REQ and second + * WMA_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 = CDF_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 = CDF_STATUS_E_FAILURE; + goto send_rsp; + } + + 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, 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, + false); + if (status != CDF_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 = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, false); + goto send_rsp; + } + + wmi_unified_send_txbf(wma, add_sta); + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_PEER_ASSOC_CONF)) { + peer_assoc_cnf = true; + msg = wma_fill_hold_req(wma, add_sta->smesessionId, + WMA_ADD_STA_REQ, WMA_PEER_ASSOC_CNF_START, + add_sta, WMA_PEER_ASSOC_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to alloc request for vdev_id %d"), + add_sta->smesessionId); + add_sta->status = CDF_STATUS_E_FAILURE; + wma_remove_req(wma, add_sta->smesessionId, + WMA_PEER_ASSOC_CNF_START); + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, false); + peer_assoc_cnf = false; + goto send_rsp; + } + } else { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF not enabled")); + } + + ret = wmi_unified_send_peer_assoc(wma, add_sta->nwType, add_sta); + if (ret) { + add_sta->status = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, 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 = &wma->interfaces[vdev->vdev_id]; + 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 = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, 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->status = CDF_STATUS_SUCCESS; +send_rsp: + /* Do not send add stat resp when peer assoc cnf is enabled */ + if (peer_assoc_cnf) { + WMA_LOGI(FL("WMI_SERVICE_PEER_ASSOC_CONF is enabled")); + return; + } + + WMA_LOGE(FL("statype %d vdev_id %d aid %d bssid %pM staIdx %d status %d"), + add_sta->staType, add_sta->smesessionId, + add_sta->assocId, add_sta->bssId, add_sta->staIdx, + add_sta->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)add_sta, 0); +} + +#ifdef FEATURE_WLAN_TDLS +/** + * wma_add_tdls_sta() - process add sta request in TDLS mode + * @wma: wma handle + * @add_sta: add sta params + * + * Return: none + */ +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; + uint8_t peer_id; + CDF_STATUS status; + int32_t ret; + tTdlsPeerStateParams *peerStateParams; + struct wma_target_req *msg; + bool peer_assoc_cnf = false; + + 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 = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + add_sta->status = CDF_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 = CDF_STATUS_E_FAILURE; + goto send_rsp; + } + + if (0 == add_sta->updateSta) { + /* its a add sta request * */ + 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, false); + if (status != CDF_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 = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, false); + 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 = cdf_mem_malloc(sizeof(tTdlsPeerStateParams)); + if (!peerStateParams) { + WMA_LOGE + ("%s: Failed to allocate memory for peerStateParams for %pM", + __func__, add_sta->staMac); + add_sta->status = CDF_STATUS_E_NOMEM; + goto send_rsp; + } + + cdf_mem_zero(peerStateParams, sizeof(*peerStateParams)); + peerStateParams->peerState = WMI_TDLS_PEER_STATE_PEERING; + peerStateParams->vdevId = vdev->vdev_id; + cdf_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 = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, false); + goto send_rsp; + } + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_PEER_ASSOC_CONF)) { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF is enabled")); + peer_assoc_cnf = true; + msg = wma_fill_hold_req(wma, add_sta->smesessionId, + WMA_ADD_STA_REQ, WMA_PEER_ASSOC_CNF_START, + add_sta, WMA_PEER_ASSOC_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to alloc request for vdev_id %d"), + add_sta->smesessionId); + add_sta->status = CDF_STATUS_E_FAILURE; + wma_remove_req(wma, add_sta->smesessionId, + WMA_PEER_ASSOC_CNF_START); + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, false); + peer_assoc_cnf = false; + goto send_rsp; + } + } else { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF not enabled")); + } + + 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 = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, + add_sta->smesessionId, peer, false); + goto send_rsp; + } + } + +send_rsp: + /* Do not send add stat resp when peer assoc cnf is enabled */ + if (peer_assoc_cnf) + return; + + WMA_LOGE(FL("statype %d vdev_id %d aid %d bssid %pM staIdx %d status %d"), + add_sta->staType, add_sta->smesessionId, + add_sta->assocId, add_sta->bssId, add_sta->staIdx, + add_sta->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)add_sta, 0); +} +#endif + +/** + * wma_add_sta_req_sta_mode() - process add sta request in sta mode + * @wma: wma handle + * @add_sta: add sta params + * + * Return: none + */ +static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) +{ + ol_txrx_pdev_handle pdev; + CDF_STATUS status = CDF_STATUS_SUCCESS; + ol_txrx_peer_handle peer; + struct wma_txrx_node *iface; + tPowerdBm maxTxPower; + int ret = 0; + struct wma_target_req *msg; + bool peer_assoc_cnf = false; + +#ifdef FEATURE_WLAN_TDLS + if (STA_ENTRY_TDLS_PEER == params->staType) { + wma_add_tdls_sta(wma, params); + return; + } +#endif + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + 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); + cdf_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 = CDF_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 WMA_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); + cdf_atomic_set(&iface->bss_status, + WMA_BSS_STATUS_STARTED); + iface->aid = params->assocId; + goto out; + } +#endif + wmi_unified_send_txbf(wma, params); + + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_PEER_ASSOC_CONF)) { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF is enabled")); + peer_assoc_cnf = true; + msg = wma_fill_hold_req(wma, params->smesessionId, + WMA_ADD_STA_REQ, WMA_PEER_ASSOC_CNF_START, + params, WMA_PEER_ASSOC_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to alloc request for vdev_id %d"), + params->smesessionId); + params->status = CDF_STATUS_E_FAILURE; + wma_remove_req(wma, params->smesessionId, + WMA_PEER_ASSOC_CNF_START); + wma_remove_peer(wma, params->staMac, + params->smesessionId, peer, false); + peer_assoc_cnf = false; + goto out; + } + } else { + WMA_LOGE(FL("WMI_SERVICE_PEER_ASSOC_CONF not enabled")); + } + + ret = wmi_unified_send_peer_assoc(wma, + iface->nwType, + (tAddStaParams *) iface->addBssStaContext); + if (ret) { + status = CDF_STATUS_E_FAILURE; + wma_remove_peer(wma, params->bssId, + params->smesessionId, peer, 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 = CDF_STATUS_E_FAILURE; + } else { + wma->interfaces[params->smesessionId].vdev_up = true; + } + + cdf_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 */ + + /* SM power save, configure the h/w as configured + * in the ini file. SMPS is not published in assoc + * request. Once configured, fw sends the required + * action frame to AP. + */ + if (params->enableHtSmps) + wma_set_mimops(wma, params->smesessionId, params->htSmpsconfig); + +#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; +out: + /* Do not send add stat resp when peer assoc cnf is enabled */ + if (peer_assoc_cnf) + return; + + params->status = status; + WMA_LOGE(FL("statype %d vdev_id %d aid %d bssid %pM staIdx %d status %d"), + params->staType, params->smesessionId, + params->assocId, params->bssId, params->staIdx, + params->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)params, 0); +} + +/** + * wma_delete_sta_req_ap_mode() - proces delete sta request from UMAC in AP mode + * @wma: wma handle + * @del_sta: delete sta params + * + * Return: none + */ +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 = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + del_sta->status = CDF_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 = CDF_STATUS_E_FAILURE; + goto send_del_rsp; + } + + wma_remove_peer(wma, peer->mac_addr.raw, del_sta->smesessionId, peer, + false); + del_sta->status = CDF_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, WMA_DELETE_STA_RSP, (void *)del_sta, 0); + } +} + +#ifdef FEATURE_WLAN_TDLS +/** + * wma_del_tdls_sta() - proces delete sta request from UMAC in TDLS + * @wma: wma handle + * @del_sta: delete sta params + * + * Return: none + */ +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 = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + del_sta->status = CDF_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 = CDF_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 = CDF_STATUS_E_FAILURE; + goto send_del_rsp; + } + + peerStateParams = cdf_mem_malloc(sizeof(tTdlsPeerStateParams)); + if (!peerStateParams) { + WMA_LOGE("%s: Failed to allocate memory for peerStateParams for: %pM", + __func__, del_sta->staMac); + del_sta->status = CDF_STATUS_E_NOMEM; + goto send_del_rsp; + } + + cdf_mem_zero(peerStateParams, sizeof(*peerStateParams)); + peerStateParams->peerState = WMA_TDLS_PEER_STATE_TEARDOWN; + peerStateParams->vdevId = vdev->vdev_id; + cdf_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 = CDF_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, WMA_DELETE_STA_RSP, (void *)del_sta, 0); + } +} +#endif + +/** + * wma_delete_sta_req_sta_mode() - proces delete sta request from UMAC + * @wma: wma handle + * @params: delete sta params + * + * Return: none + */ +static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, + tpDeleteStaParams params) +{ + CDF_STATUS status = CDF_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, WMA_DELETE_STA_RSP, (void *)params, 0); + } +} + +/** + * wma_add_sta() - process add sta request as per opmode + * @wma: wma handle + * @add_Sta: add sta params + * + * Return: none + */ +void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) +{ + uint8_t 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)) + 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; +#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: + hif_vote_link_up(); + 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 + +} + +/** + * wma_delete_sta() - process del sta request as per opmode + * @wma: wma handle + * @del_sta: delete sta params + * + * Return: none + */ +void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) +{ + uint8_t oper_mode = BSS_OPERATIONAL_MODE_STA; + uint8_t smesession_id = del_sta->smesessionId; + bool rsp_requested = del_sta->respReqd; + + if (wma_is_vdev_in_ap_mode(wma, smesession_id)) + 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; + 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: + hif_vote_link_down(); + 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); + cdf_mem_free(del_sta); + } +} + +/** + * wmi_unified_vdev_stop_send() - send vdev stop command to fw + * @wmi: wmi handle + * @vdev_id: vdev id + * + * Return: 0 for success or erro code + */ +int32_t wmi_unified_vdev_stop_send(wmi_unified_t wmi, uint8_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__); + cdf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_delete_bss() - process delete bss request from upper layer + * @wma: wma handle + * @params: del bss parameters + * + * Return: none + */ +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; + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t peer_id; + uint8_t max_wait_iterations = 0; + ol_txrx_vdev_handle txrx_vdev = NULL; + bool roam_synch_in_progress = false; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + 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 = CDF_STATUS_E_FAILURE; + goto out; + } + + cdf_mem_zero(wma->interfaces[params->smesessionId].bssid, + IEEE80211_ADDR_LEN); + + txrx_vdev = wma_find_vdev_by_id(wma, params->smesessionId); + if (!txrx_vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + status = CDF_STATUS_E_FAILURE; + goto out; + } + + /*Free the allocated stats response buffer for the the session */ + if (wma->interfaces[params->smesessionId].stats_rsp) { + cdf_mem_free(wma->interfaces[params->smesessionId].stats_rsp); + wma->interfaces[params->smesessionId].stats_rsp = NULL; + } + + if (wma->interfaces[params->smesessionId].psnr_req) { + cdf_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 = true; + WMA_LOGD("LFR3:%s: Setting vdev_up to FALSE for session %d", + __func__, params->smesessionId); + wma->interfaces[params->smesessionId].vdev_up = false; + goto detach_peer; + } +#endif + msg = wma_fill_vdev_req(wma, params->smesessionId, WMA_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 = CDF_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.")); + cdf_wait_single_event(&wma->tx_queue_empty_event, + WMA_TX_Q_RECHECK_TIMER_MAX_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); + ol_txrx_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 = CDF_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, WMA_DELETE_BSS_RSP, (void *)params, 0); +} + +/** + * wma_find_ibss_vdev() - This function finds vdev_id based on input type + * @wma: wma handle + * @type: vdev type + * + * Return: vdev id + */ +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 -EFAULT; +} + +/** + * wma_set_vdev_intrabss_fwd() - set intra_fwd value to wni_in. + * @wma_handle: wma handle + * @pdis_intra_fwd: Pointer to DisableIntraBssFwd struct + * + * Return: none + */ +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; + ol_vdev_rx_set_intrabss_fwd(txrx_vdev, + pdis_intra_fwd->disableintrabssfwd); +} diff --git a/core/wma/src/wma_dfs_interface.c b/core/wma/src/wma_dfs_interface.c new file mode 100644 index 000000000000..8c0fcd4ccb2e --- /dev/null +++ b/core/wma/src/wma_dfs_interface.c @@ -0,0 +1,245 @@ +/* + * 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_dfs_interface.c + * + * Source code borrowed from QCA_MAIN DFS module + */ + +#include "wma.h" +#include "ath_dfs_structs.h" +#include "wma_dfs_interface.h" + +#ifndef ATH_SUPPORT_DFS +#define ATH_SUPPORT_DFS 1 +#endif + +/** + * ol_if_dfs_attach() - dfs attach + * @ic: ieee80211com ptr + * @ptr: ath_dfs_caps ptr + * @radar_info: radar info + * + * Return: 0 for success or error code + */ +int ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info) +{ + struct ath_dfs_caps *pCap = (struct ath_dfs_caps *)ptr; + + cdf_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; +} + +/** + * ol_if_get_tsf64() - Place Holder API + * @ic: ieee80211com ptr + * + * We get the tsf from Firmware. + * + * Return: always return success(0) + */ +uint64_t ol_if_get_tsf64(struct ieee80211com *ic) +{ + return 0; +} + +/** + * ol_if_dfs_disable() - Place Holder API + * @ic: ieee80211com ptr + * + * ic_dfs_disable is just a place holder + * function since firmware takes care of + * disabling the dfs phyerrors disabling. + * + * Return: always return success(0) + */ +int ol_if_dfs_disable(struct ieee80211com *ic) +{ + return 0; +} + +/** + * ieee80211_find_channel() - find ieee80211 channel + * @ic: ieee80211com ptr + * @freq: frequency + * @flags: flags + * + * 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. + * + * Return: returns ieee80211_channel or NULL for error + */ +struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, + int freq, uint32_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 + * @ic: ieee80211com ptr + * @is_fastclk: is fastclock + * + * For offload solutions, radar PHY errors will be enabled + * by the target firmware when DFS is requested for the + * current channel. + * + * Return: Always returns success + */ +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; +} + +/** + * ieee80211_ieee2mhz() - Convert IEEE channel number to MHz frequency. + * @chan: channel number + * @flags: flags + * + * Return: frequency in MHz + */ +uint32_t ieee80211_ieee2mhz(uint32_t chan, uint32_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); + } +} + +/** + * ol_if_dfs_get_ext_busy() - Place holder function ic_get_ext_busy + * @ic: ieee80211com ptr + * + * Return: Always return success (0) + */ +int ol_if_dfs_get_ext_busy(struct ieee80211com *ic) +{ + return 0; +} + +/** + * ol_if_dfs_get_mib_cycle_counts_pct() - Place holder function + * @ic: ieee80211com ptr + * + * Return: Always return success (0) + */ +int +ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, + uint32_t *rxc_pcnt, uint32_t *rxf_pcnt, + uint32_t *txf_pcnt) +{ + return 0; +} + +/** + * ol_if_dfs_usenol() - dfs usenol call + * @ic: ieee80211com ptr + * + * Return: 0 fo success or error code + */ +uint16_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; +} + +/** + * ieee80211_mark_dfs() - indicate radar on current operating freq + * @ic: ieee80211com ptr + * @ichan: channel + * + * 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. + * + * Return: none + */ +void +ieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan) +{ + int status; + status = wma_dfs_indicate_radar(ic, ichan); +} diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c new file mode 100644 index 000000000000..065f2e300b12 --- /dev/null +++ b/core/wma/src/wma_features.c @@ -0,0 +1,7171 @@ +/* + * 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_features.c + * This file contains different features related functions like WoW, + * Offloads, TDLS etc. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "radar_filters.h" +#include "wma_internal.h" + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define WMA_WOW_STA_WAKE_UP_EVENTS ((1 << WOW_CSA_IE_EVENT) |\ + (1 << WOW_CLIENT_KICKOUT_EVENT) |\ + (1 << WOW_PATTERN_MATCH_EVENT) |\ + (1 << WOW_MAGIC_PKT_RECVD_EVENT) |\ + (1 << WOW_DEAUTH_RECVD_EVENT) |\ + (1 << WOW_DISASSOC_RECVD_EVENT) |\ + (1 << WOW_BMISS_EVENT) |\ + (1 << WOW_GTK_ERR_EVENT) |\ + (1 << WOW_BETTER_AP_EVENT) |\ + (1 << WOW_HTT_EVENT) |\ + (1 << WOW_RA_MATCH_EVENT) |\ + (1 << WOW_NLO_DETECTED_EVENT) |\ + (1 << WOW_EXTSCAN_EVENT))\ + +#define WMA_WOW_SAP_WAKE_UP_EVENTS ((1 << WOW_PROBE_REQ_WPS_IE_EVENT) |\ + (1 << WOW_PATTERN_MATCH_EVENT) |\ + (1 << WOW_AUTH_REQ_EVENT) |\ + (1 << WOW_ASSOC_REQ_EVENT) |\ + (1 << WOW_DEAUTH_RECVD_EVENT) |\ + (1 << WOW_DISASSOC_RECVD_EVENT) |\ + (1 << WOW_HTT_EVENT))\ + +static const uint8_t arp_ptrn[] = {0x08, 0x06}; +static const uint8_t arp_mask[] = {0xff, 0xff}; +static const uint8_t ns_ptrn[] = {0x86, 0xDD}; +static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; +static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +/** + * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme + * + * Return: 0 for success or error code + */ +static int wma_post_auto_shutdown_msg(void) +{ + tSirAutoShutdownEvtParams *auto_sh_evt; + CDF_STATUS cdf_status; + cds_msg_t sme_msg = { 0 }; + + auto_sh_evt = (tSirAutoShutdownEvtParams *) + cdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams)); + if (!auto_sh_evt) { + WMA_LOGE(FL("No Mem")); + 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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME"); + cdf_mem_free(auto_sh_evt); + return -EINVAL; + } + + return 0; +} +#endif +/** + * wma_send_snr_request() - send request to fw to get RSSI stats + * @wma_handle: wma handle + * @pGetRssiReq: get RSSI request + * + * Return: CDF status + */ +CDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle, + void *pGetRssiReq) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + uint8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + tAniGetRssiReq *pRssiBkUp = NULL; + + /* command is in progess */ + if (NULL != wma_handle->pGetRssiReq) + return CDF_STATUS_SUCCESS; + + /* create a copy of csrRssiCallback to send rssi value + * after wmi event + */ + if (pGetRssiReq) { + pRssiBkUp = cdf_mem_malloc(sizeof(tAniGetRssiReq)); + if (!pRssiBkUp) { + WMA_LOGE("Failed to allocate memory for tAniGetRssiReq"); + wma_handle->pGetRssiReq = NULL; + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set(pRssiBkUp, sizeof(tAniGetRssiReq), 0); + 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__); + cdf_mem_free(pRssiBkUp); + wma_handle->pGetRssiReq = NULL; + return CDF_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); + cdf_mem_free(pRssiBkUp); + wma_handle->pGetRssiReq = NULL; + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_snr() - get RSSI from fw + * @psnr_req: request params + * + * Return: CDF status + */ +CDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + tAniGetSnrReq *psnr_req_bkp; + uint8_t len = sizeof(wmi_request_stats_cmd_fixed_param); + tp_wma_handle wma_handle = NULL; + struct wma_txrx_node *intr; + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma_handle) { + WMA_LOGE("%s : Failed to get wma_handle", __func__); + return CDF_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 CDF_STATUS_SUCCESS; + } + + psnr_req_bkp = cdf_mem_malloc(sizeof(tAniGetSnrReq)); + if (!psnr_req_bkp) { + WMA_LOGE("Failed to allocate memory for tAniGetSnrReq"); + return CDF_STATUS_E_NOMEM; + } + + cdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0); + 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__); + cdf_mem_free(psnr_req_bkp); + return CDF_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); + cdf_mem_free(psnr_req_bkp); + intr->psnr_req = NULL; + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_process_link_status_req() - process link status request from UMAC + * @wma: wma handle + * @pGetLinkStatus: get link params + * + * Return: none + */ +void wma_process_link_status_req(tp_wma_handle wma, + tAniGetLinkStatus *pGetLinkStatus) +{ + wmi_buf_t buf; + wmi_request_stats_cmd_fixed_param *cmd; + uint8_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__); + cdf_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); +} + +#ifdef FEATURE_WLAN_LPHB +/** + * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests + * @wma_handle: WMA handle + * @lphb_conf_req: configuration info + * @by_user: whether this call is from user or cached resent + * + * Return: CDF status + */ +CDF_STATUS wma_lphb_conf_hbenable(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req, bool by_user) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int status = 0; + tSirLPHBEnableStruct *ts_lphb_enable; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_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 { + cdf_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 CDF_STATUS_SUCCESS; +error: + return cdf_status; +} + +/** + * wma_lphb_conf_tcp_params() - set tcp params of LPHB configuration requests + * @wma_handle: wma handle + * @lphb_conf_req: lphb config request + * + * Return: CDF status + */ +CDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int status = 0; + tSirLPHBTcpParamStruct *ts_lphb_tcp_param; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + return CDF_STATUS_SUCCESS; +error: + return cdf_status; +} + +/** + * wma_lphb_conf_tcp_pkt_filter() - configure tcp packet filter command of LPHB + * @wma_handle: wma handle + * @lphb_conf_req: lphb config request + * + * Return: CDF status + */ +CDF_STATUS wma_lphb_conf_tcp_pkt_filter(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int status = 0; + tSirLPHBTcpFilterStruct *ts_lphb_tcp_filter; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + return CDF_STATUS_SUCCESS; +error: + return cdf_status; +} + +/** + * wma_lphb_conf_udp_params() - configure udp param command of LPHB + * @wma_handle: wma handle + * @lphb_conf_req: lphb config request + * + * Return: CDF status + */ +CDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int status = 0; + tSirLPHBUdpParamStruct *ts_lphb_udp_param; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + return CDF_STATUS_SUCCESS; +error: + return cdf_status; +} + +/** + * wma_lphb_conf_udp_pkt_filter() - configure udp pkt filter command of LPHB + * @wma_handle: wma handle + * @lphb_conf_req: lphb config request + * + * Return: CDF status + */ +CDF_STATUS wma_lphb_conf_udp_pkt_filter(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int status = 0; + tSirLPHBUdpFilterStruct *ts_lphb_udp_filter; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + return CDF_STATUS_SUCCESS; +error: + return cdf_status; +} + +/** + * wma_process_lphb_conf_req() - handle LPHB configuration requests + * @wma_handle: wma handle + * @lphb_conf_req: lphb config request + * + * Return: CDF status + */ +CDF_STATUS wma_process_lphb_conf_req(tp_wma_handle wma_handle, + tSirLPHBReq *lphb_conf_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + if (lphb_conf_req == NULL) { + WMA_LOGE("%s : LPHB configuration is NULL", __func__); + return CDF_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: + cdf_status = wma_lphb_conf_hbenable(wma_handle, + lphb_conf_req, true); + break; + + case LPHB_SET_TCP_PARAMS_INDID: + cdf_status = wma_lphb_conf_tcp_params(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_TCP_PKT_FILTER_INDID: + cdf_status = wma_lphb_conf_tcp_pkt_filter(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_UDP_PARAMS_INDID: + cdf_status = wma_lphb_conf_udp_params(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_UDP_PKT_FILTER_INDID: + cdf_status = wma_lphb_conf_udp_pkt_filter(wma_handle, + lphb_conf_req); + break; + + case LPHB_SET_NETWORK_INFO_INDID: + default: + break; + } + + cdf_mem_free(lphb_conf_req); + return cdf_status; +} +#endif /* FEATURE_WLAN_LPHB */ + +/** + * wma_process_dhcp_ind() - process dhcp indication from SME + * @wma_handle: wma handle + * @ta_dhcp_ind: DHCP indication + * + * Return: CDF Status + */ +CDF_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; + uint8_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 CDF_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 CDF_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 == WMA_DHCP_START_IND ? + "WMA_DHCP_START_IND" : "WMA_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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 (WMA_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_chan_to_mode() - convert channel to phy mode + * @chan: channel number + * @chan_width: channel width + * @vht_capable: vht capable + * @dot11_mode: 802.11 mode + * + * Return: return phy mode + */ +WLAN_PHY_MODE wma_chan_to_mode(u8 chan, phy_ch_width chan_width, + 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_width) { + case CH_WIDTH_20MHZ: + /* 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 CH_WIDTH_40MHZ: + phymode = vht_capable ? MODE_11AC_VHT40 : + MODE_11NG_HT40; + break; + default: + break; + } + } + + /* 5 GHz band */ + if ((chan >= WMA_11A_CHANNEL_BEGIN) && (chan <= WMA_11A_CHANNEL_END)) { + switch (chan_width) { + case CH_WIDTH_20MHZ: + phymode = vht_capable ? MODE_11AC_VHT20 : + MODE_11NA_HT20; + break; + case CH_WIDTH_40MHZ: + phymode = vht_capable ? MODE_11AC_VHT40 : + MODE_11NA_HT40; + break; + case CH_WIDTH_80MHZ: + phymode = MODE_11AC_VHT80; + break; +#if CONFIG_160MHZ_SUPPORT != 0 + case CH_WIDTH_160MHZ: + phymode = MODE_11AC_VHT160; + break; + case CH_WIDTH_80P80MHZ: + phymode = MODE_11AC_VHT80_80; + break; +#endif + + 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 ch_width %d vht_capable %d " + "dot11_mode %d", __func__, phymode, chan, + chan_width, vht_capable, dot11_mode); + + return phymode; +} + +/** + * wma_get_link_speed() -send command to get linkspeed + * @handle: wma handle + * @pLinkSpeed: link speed info + * + * Return: CDF status + */ +CDF_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; + uint8_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 CDF_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 CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +#ifdef FEATURE_GREEN_AP + +/** + * wmi_unified_pdev_green_ap_ps_enable_cmd() - enable green ap powersave command + * @wmi_handle: wmi handle + * @value: value + * + * Return: 0 for success or error code + */ +int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, + uint32_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); + cdf_nbuf_free(buf); + return -EIO; + } + return 0; +} +#endif /* FEATURE_GREEN_AP */ + +#ifdef FEATURE_WLAN_LPHB +/** + * wma_lphb_handler() - send LPHB indication to SME + * @wma: wma handle + * @event: event handler + * + * Return: 0 for success or error code + */ +static int wma_lphb_handler(tp_wma_handle wma, uint8_t *event) +{ + wmi_hb_ind_event_fixed_param *hb_fp; + tSirLPHBInd *slphb_indication; + CDF_STATUS cdf_status; + cds_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 *) cdf_mem_malloc(sizeof(tSirLPHBInd)); + + if (!slphb_indication) { + WMA_LOGE("Invalid LPHB indication buffer"); + return -ENOMEM; + } + + 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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("Fail to post eWNI_SME_LPHB_IND msg to SME"); + cdf_mem_free(slphb_indication); + return -EINVAL; + } + + return 0; +} +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_RA_FILTERING +/** + * wma_wow_sta_ra_filter() - set RA filter pattern in fw + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: CDF status + */ +static CDF_STATUS wma_wow_sta_ra_filter(tp_wma_handle wma, uint8_t vdev_id) +{ + + WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; + struct wma_txrx_node *iface; + wmi_buf_t buf; + uint8_t *buf_ptr; + int32_t len; + int ret; + + iface = &wma->interfaces[vdev_id]; + + 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 CDF_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_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 = iface->num_wow_default_patterns++, + 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); + iface->num_wow_default_patterns--; + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; + +} +#endif /* FEATURE_WLAN_RA_FILTERING */ + +/** + * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_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; +} + +/** + * wmi_unified_csa_offload_enable() - sen CSA offload enable command + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: 0 for success or error code + */ +int wmi_unified_csa_offload_enable(tp_wma_handle wma, uint8_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 WLAN_FEATURE_NAN +/** + * wma_nan_rsp_event_handler() - Function is used to handle nan response + * @handle: wma handle + * @event_buf: event buffer + * @len: length of buffer + * + * Return: 0 for success or error code + */ +int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + WMI_NAN_EVENTID_param_tlvs *param_buf; + tSirNanEvent *nan_rsp_event; + wmi_nan_event_hdr *nan_rsp_event_hdr; + CDF_STATUS status; + cds_msg_t cds_msg; + uint8_t *buf_ptr; + uint32_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 = (uint8_t *) nan_rsp_event_hdr; + alloc_len = sizeof(tSirNanEvent); + alloc_len += nan_rsp_event_hdr->data_len; + nan_rsp_event = (tSirNanEvent *) cdf_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; + cdf_mem_copy(nan_rsp_event->event_data, buf_ptr + + sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE, + nan_rsp_event->event_data_len); + cds_msg.type = eWNI_SME_NAN_EVENT; + cds_msg.bodyptr = (void *)nan_rsp_event; + cds_msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post NaN response event to SME", + __func__); + cdf_mem_free(nan_rsp_event); + return -EFAULT; + } + WMA_LOGD("%s: NaN response event Posted to SME", __func__); + return 0; +} +#endif /* WLAN_FEATURE_NAN */ + +/** + * wma_csa_offload_handler() - CSA event handler + * @handle: wma handle + * @event: event buffer + * @len: buffer length + * + * This event is sent by firmware when it receives CSA IE. + * + * Return: 0 for success or error code + */ +int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_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; + uint8_t bssid[IEEE80211_ADDR_LEN]; + uint8_t vdev_id = 0; + uint8_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 = cdf_mem_malloc(sizeof(*csa_offload_event)); + if (!csa_offload_event) { + WMA_LOGE("CDF MEM Alloc Failed for csa_offload_event"); + return -EINVAL; + } + + cdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event)); + cdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN); + + 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"); + cdf_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 = cds_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); + cdf_mem_free(csa_offload_event); + return -EINVAL; + } + wma->interfaces[vdev_id].is_channel_switch = true; + wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0); + return 0; +} + +#ifdef FEATURE_OEM_DATA_SUPPORT + +/** + * wma_oem_capability_event_callback() - OEM capability event handler + * @handle: wma handle + * @datap: data ptr + * @len: data length + * + * Return: 0 for success or error code + */ +int wma_oem_capability_event_callback(void *handle, + uint8_t *datap, uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_CAPABILITY_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_t datalen; + uint32_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 = cdf_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_CAPABILITY_RSP; + cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} + +/** + * wma_oem_measurement_report_event_callback() - OEM measurement report handler + * @handle: wma handle + * @datap: data ptr + * @len: data length + * + * Return: 0 for success or error code + */ +int wma_oem_measurement_report_event_callback(void *handle, + uint8_t *datap, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_MEASUREMENT_REPORT_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_t datalen; + uint32_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 = cdf_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_MEASUREMENT_RSP; + cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} + +/** + * wma_oem_error_report_event_callback() - OEM error report handler + * @handle: wma handle + * @datap: data ptr + * @len: data length + * + * Return: 0 for success or error code + */ +int wma_oem_error_report_event_callback(void *handle, + uint8_t *datap, uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_ERROR_REPORT_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_t datalen; + uint32_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 = cdf_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s: Failed to alloc pStartOemDataRsp", __func__); + return -ENOMEM; + } + + cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_ERROR_REPORT_RSP; + cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); + + WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP, data len (%d)", + __func__, datalen); + + wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)pStartOemDataRsp, 0); + return 0; +} + +/** + * wma_start_oem_data_req() - start OEM data request to target + * @wma_handle: wma handle + * @startOemDataReq: start request params + * + * Return: none + */ +void wma_start_oem_data_req(tp_wma_handle wma_handle, + tStartOemDataReq *startOemDataReq) +{ + wmi_buf_t buf; + uint8_t *cmd; + int ret = 0; + uint32_t *msg_subtype; + tStartOemDataRsp *pStartOemDataRsp; + + WMA_LOGD("%s: Send OEM Data Request to target", __func__); + + if (!startOemDataReq) { + WMA_LOGE("%s: startOemDataReq is null", __func__); + goto out; + } + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not send Oem data request cmd", + __func__); + return; + } + + buf = wmi_buf_alloc(wma_handle->wmi_handle, + (OEM_DATA_REQ_SIZE + WMI_TLV_HDR_SIZE)); + if (!buf) { + WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + goto out; + } + + cmd = (uint8_t *) wmi_buf_data(buf); + + WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, OEM_DATA_REQ_SIZE); + cmd += WMI_TLV_HDR_SIZE; + cdf_mem_copy(cmd, &startOemDataReq->oemDataReq[0], OEM_DATA_REQ_SIZE); + + WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)", + __func__, OEM_DATA_REQ_SIZE); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + (OEM_DATA_REQ_SIZE + + WMI_TLV_HDR_SIZE), WMI_OEM_REQ_CMDID); + + if (ret != EOK) { + WMA_LOGE("%s:wmi cmd send failed", __func__); + cdf_nbuf_free(buf); + } + +out: + /* free oem data req buffer received from UMAC */ + if (startOemDataReq) + cdf_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 = cdf_mem_malloc(sizeof(*pStartOemDataRsp)); + if (!pStartOemDataRsp) { + WMA_LOGE("%s:failed to allocate memory for OEM Data Resp to PE", + __func__); + return; + } + cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); + *msg_subtype = WMI_OEM_INTERNAL_RSP; + + WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd", + __func__); + + wma_send_msg(wma_handle, WMA_START_OEM_DATA_RSP, + (void *)pStartOemDataRsp, 0); + + return; +} +#endif /* FEATURE_OEM_DATA_SUPPORT */ + + +/** + * wma_unified_dfs_radar_rx_event_handler() - dfs radar rx event handler + * @handle: wma handle + * @data: data buffer + * @datalen: data length + * + * 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 for Success and 0 for error + */ +static int wma_unified_dfs_radar_rx_event_handler(void *handle, + uint8_t *data, + uint32_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; + + cdf_mutex_acquire(&ic->chan_lock); + chan = ic->ic_curchan; + if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) { + WMA_LOGE + ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS", + __func__, chan->ic_ieee); + cdf_mutex_release(&ic->chan_lock); + return 0; + } + + cdf_mutex_release(&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 ((uint32_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 = (uint8_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 = (uint8_t) dfs->dfs_curchan_radindex; + } else { + if (dfs->dfs_extchan_radindex == -1) { + WMA_LOGI("%s phyerr on ext channel", __func__); + } + event->re_chanindex = (uint8_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; + +} + +/** + * wma_unified_phyerr_rx_event_handler() - phyerr event handler + * @handle: wma handle + * @data: data buffer + * @datalen: buffer length + * + * 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, + uint8_t *data, uint32_t datalen) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PHYERR_EVENTID_param_tlvs *param_tlvs; + wmi_comb_phyerr_rx_hdr *pe_hdr; + uint8_t *bufp; + wmi_single_phyerr_rx_event *ev; + struct ieee80211com *ic = wma->dfs_ic; + cdf_size_t n; + A_UINT64 tsf64 = 0; + int phy_err_code = 0; + int error = 0; + tpAniSirGlobal mac_ctx = + (tpAniSirGlobal)cds_get_context(CDF_MODULE_ID_PE); + 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; +} + +/** + * wma_register_dfs_event_handler() - register dfs event handler + * @wma_handle: wma handle + * + * Register appropriate dfs phyerror event handler + * based on phyerror filtering offload is enabled + * or disabled. + * + * Return: none + */ +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 (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; +} + + +/** + * wma_unified_dfs_phyerr_filter_offload_enable() - enable dfs phyerr filter + * @wma_handle: wma handle + * + * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or + * WMI_DFS_PHYERR_FILTER_DIS_CMDID command + * to firmware based on phyerr filtering + * offload status. + * + * Return: 1 success, 0 failure + */ +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; + uint16_t len; + int ret; + + if (NULL == wma_handle) { + WMA_LOGE("%s:wma_handle is NULL", __func__); + return 0; + } + + if (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; +} + +#if !defined(REMOVE_PKT_LOG) +/** + * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target + * @handle: wma handle + * @params: pktlog params + * + * Return: CDF status + */ +CDF_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 (!cds_is_packet_log_enabled()) { + WMA_LOGE("%s:pkt log is not enabled in cfg.ini", __func__); + return CDF_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 CDF_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 CDF_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 CDF_STATUS_SUCCESS; + +wmi_send_failed: + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; +} +#endif /* REMOVE_PKT_LOG */ + +static void wma_send_status_to_suspend_ind(tp_wma_handle wma, bool suspended) +{ + tSirReadyToSuspendInd *ready_to_suspend; + CDF_STATUS status; + cds_msg_t cds_msg; + uint8_t len; + + WMA_LOGD("Posting ready to suspend indication to umac"); + + len = sizeof(tSirReadyToSuspendInd); + ready_to_suspend = (tSirReadyToSuspendInd *) cdf_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; + + cds_msg.type = eWNI_SME_READY_TO_SUSPEND_IND; + cds_msg.bodyptr = (void *)ready_to_suspend; + cds_msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to post ready to suspend"); + cdf_mem_free(ready_to_suspend); + } +} + +/** + * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format + * @wake_reason - WOW wake reason + * + * Return: reason code in string format + */ +static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason) +{ + switch (wake_reason) { + case WOW_REASON_UNSPECIFIED: + return "UNSPECIFIED"; + 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 /* FEATURE_WLAN_RA_FILTERING */ + 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 /* FEATURE_WLAN_AUTO_SHUTDOWN */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WOW_REASON_ROAM_HO: + return "WOW_REASON_ROAM_HO"; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +#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"; + } + return "unknown"; +} + +/** + * 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) +{ + 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_wakeup_host_event() - wakeup host event handler + * @handle: wma handle + * @event: event data + * @len: buffer length + * + * Handler to catch wow wakeup host event. This event will have + * reason why the firmware has woken the host. + * + * Return: 0 for success or error + */ +int wma_wow_wakeup_host_event(void *handle, uint8_t *event, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *param_buf; + WOW_EVENT_INFO_fixed_param *wake_info; +#ifdef FEATURE_WLAN_SCAN_PNO + struct wma_txrx_node *node; +#endif /* FEATURE_WLAN_SCAN_PNO */ + uint32_t wake_lock_duration = 0; + uint32_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), + wake_info->wake_reason, wake_info->vdev_id); + + cdf_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_LOGA("Beacon miss indication on vdev %x", + wake_info->vdev_id); + wma_beacon_miss_handler(wma, wake_info->vdev_id); + 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 /* FEATURE_WLAN_RA_FILTERING */ +#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 /* FEATURE_WLAN_AUTO_SHUTDOWN */ +#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; + cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + } + break; +#endif /* FEATURE_WLAN_SCAN_PNO */ + + 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 *) + (((uint8_t *) wake_info) + + sizeof(WOW_EVENT_INFO_fixed_param) + + WOW_CSA_EVENT_OFFSET); + wma_csa_offload_handler(handle, (uint8_t *) ¶m, + sizeof(param)); + } + break; + +#ifdef FEATURE_WLAN_LPHB + case WOW_REASON_WLAN_HB: + wma_lphb_handler(wma, (uint8_t *) param_buf->hb_indevt); + break; +#endif /* FEATURE_WLAN_LPHB */ + + case WOW_REASON_HTT_EVENT: + break; + case WOW_REASON_PATTERN_MATCH_FOUND: + wma_wow_wake_up_stats_display(wma); + 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 */ + cdf_mem_copy((uint8_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); + cdf_trace_hex_dump(CDF_MODULE_ID_WMA, + CDF_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"); + cdf_mem_copy((uint8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + WMA_LOGD("wow_packet_buffer dump"); + cdf_trace_hex_dump(CDF_MODULE_ID_WMA, + CDF_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, + (uint8_t *) & + param, + 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"); + cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + WMA_LOGD("wow_packet_buffer dump"); + cdf_trace_hex_dump(CDF_MODULE_ID_WMA, + CDF_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_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) { + cdf_mem_copy((u_int8_t *) &wow_buf_pkt_len, + param_buf->wow_packet_buffer, 4); + if (wow_buf_pkt_len >= sizeof(param)) { + param.fixed_param = + (wmi_rssi_breach_event_fixed_param *) + (param_buf->wow_packet_buffer + 4); + wma_rssi_breached_event_handler(handle, + (u_int8_t *)¶m, + sizeof(param)); + } else { + WMA_LOGE("%s: Wrong length: %d bytes", + __func__, wow_buf_pkt_len); + } + } else + WMA_LOGD("No wow_packet_buffer present"); + } + break; + default: + break; + } + + if (wake_lock_duration) { + cdf_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; +} + +/** + * wma_pdev_resume_event_handler() - PDEV resume event handler + * @handle: wma handle + * @event: event data + * @len: buffer length + * + * Return: 0 for success or error + */ +int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + + WMA_LOGA("Received PDEV resume event"); + + cdf_event_set(&wma->wma_resume_event); + + return 0; +} +/** + * wma_set_wow_bus_suspend() - set suspend flag + * @wma: wma handle + * @val: value + * + * Return: none + */ +static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val) +{ + + cdf_atomic_set(&wma->is_wow_bus_suspended, val); +} + + + +/** + * wma_add_wow_wakeup_event() - Configures wow wakeup events. + * @wma: wma handle + * @vdev_id: vdev id + * @bitmap: Event bitmap + * @enable: enable/disable + * + * Return: CDF status + */ +static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, + uint32_t vdev_id, + uint32_t bitmap, + bool enable) +{ + WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd; + uint16_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 allocate wmi buffer", __func__); + return CDF_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 = vdev_id; + cmd->is_add = enable; + cmd->event_bitmap = bitmap; + + 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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Wakeup pattern 0x%x %s in fw", bitmap, + enable ? "enabled" : "disabled"); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_send_wow_patterns_to_fw() - Sends WOW patterns to FW. + * @wma: wma handle + * @vdev_id: vdev id + * @ptrn_id: pattern id + * @ptrn: pattern + * @ptrn_len: pattern length + * @ptrn_offset: pattern offset + * @mask: mask + * @mask_len: mask length + * @user: true for user configured pattern and false for default pattern + * + * Return: CDF status + */ +static CDF_STATUS wma_send_wow_patterns_to_fw(tp_wma_handle wma, + uint8_t vdev_id, uint8_t ptrn_id, + const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user) +{ + WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; + WOW_BITMAP_PATTERN_T *bitmap_pattern; + struct wma_txrx_node *iface; + wmi_buf_t buf; + uint8_t *buf_ptr; + int32_t len; + int ret; + + iface = &wma->interfaces[vdev_id]; + + 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 CDF_STATUS_E_NOMEM; + } + + cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_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; + /* + * For user configured wow pattern use pattern id sent by HDD + * and for default wow patterns generate pattern id internally + */ + if (user) + cmd->pattern_id = ptrn_id; + else + cmd->pattern_id = iface->num_wow_default_patterns++; + + 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)); + + cdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len); + cdf_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_LOGI("vdev id : %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d", + cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len, + bitmap_pattern->pattern_offset, user); + + WMA_LOGI("Pattern : "); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO, + &bitmap_pattern->patternbuf[0], bitmap_pattern->pattern_len); + + WMA_LOGI("Mask : "); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO, + &bitmap_pattern->bitmaskbuf[0], bitmap_pattern->pattern_len); + + 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); + if (!user) + iface->num_wow_default_patterns--; + return CDF_STATUS_E_FAILURE; + } + + if (user) + iface->num_wow_user_patterns++; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_wow_ap() - set WOW patterns in ap mode + * @wma: wma handle + * @vdev_id: vdev id + * + * Configures default WOW pattern for the given vdev_id which is in AP mode. + * + * Return: CDF status + */ +static CDF_STATUS wma_wow_ap(tp_wma_handle wma, uint8_t vdev_id) +{ + CDF_STATUS ret; + uint8_t arp_offset = 20; + uint8_t mac_mask[IEEE80211_ADDR_LEN]; + + /* Setup unicast pkt pattern */ + cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF); + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0, + wma->interfaces[vdev_id].addr, + IEEE80211_ADDR_LEN, 0, mac_mask, + IEEE80211_ADDR_LEN, false); + if (ret != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret); + return ret; + } + + /* + * Setup all ARP pkt pattern. This is dummy pattern hence the length + * is zero + */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0, + arp_ptrn, 0, arp_offset, arp_mask, 0, false); + if (ret != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW ARP pattern ret %d", ret); + return ret; + } + + return ret; +} + +/** + * wma_wow_sta() - set WOW patterns in sta mode + * @wma: wma handle + * @vdev_id: vdev id + * + * Configures default WOW pattern for the given vdev_id which is in sta mode. + * + * Return: CDF status + */ +static CDF_STATUS wma_wow_sta(tp_wma_handle wma, uint8_t vdev_id) +{ + uint8_t arp_offset = 12; + uint8_t discvr_offset = 30; + uint8_t mac_mask[IEEE80211_ADDR_LEN]; + CDF_STATUS ret = CDF_STATUS_SUCCESS; + + /* Setup unicast pkt pattern */ + cdf_mem_set(&mac_mask, IEEE80211_ADDR_LEN, 0xFF); + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0, + wma->interfaces[vdev_id].addr, + IEEE80211_ADDR_LEN, 0, mac_mask, + IEEE80211_ADDR_LEN, false); + if (ret != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW unicast pattern ret %d", ret); + 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, 0, + discvr_ptrn, sizeof(discvr_ptrn), discvr_offset, + discvr_mask, sizeof(discvr_ptrn), false); + if (ret != CDF_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"); + + /* 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 (!(wma->ol_ini_info & 0x1)) { + /* Setup all ARP pkt pattern */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0, + arp_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask), false); + if (ret != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW ARP pattern"); + return ret; + } + } + + /* for NS or NDP offload packets */ + if (!(wma->ol_ini_info & 0x2)) { + /* Setup all NS pkt pattern */ + ret = wma_send_wow_patterns_to_fw(wma, vdev_id, 0, + ns_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask), false); + if (ret != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to add WOW NS pattern"); + return ret; + } + } + + return ret; +} + +/** + * wma_register_wow_default_patterns() - register default wow patterns with fw + * @handle: Pointer to wma handle + * @vdev_id: vdev id + * + * WoW default wake up pattern rule is: + * - For STA & P2P CLI mode register for same STA specific wow patterns + * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns + * + * Return: none + */ +void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id) +{ + tp_wma_handle wma = handle; + struct wma_txrx_node *iface; + + if (vdev_id > wma->max_bssid) { + WMA_LOGE("Invalid vdev id %d", vdev_id); + return; + } + iface = &wma->interfaces[vdev_id]; + + if (iface->ptrn_match_enable) { + 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 SAP/GO/IBSS mode default wow patterns */ + WMA_LOGI("Config SAP specific default wow patterns vdev_id %d", + vdev_id); + wma_wow_ap(wma, vdev_id); + } else { + /* Configure STA/P2P CLI mode default wow patterns */ + WMA_LOGI("Config STA specific default wow patterns vdev_id %d", + vdev_id); + wma_wow_sta(wma, vdev_id); + if (wma->IsRArateLimitEnabled) { + WMA_LOGI("Config STA RA limit wow patterns vdev_id %d", + vdev_id); + wma_wow_sta_ra_filter(wma, vdev_id); + } + } + } + + return; +} + +/** + * wma_register_wow_wakeup_events() - register vdev specific wake events with fw + * @handle: Pointer to wma handle + * @vdev_id: vdev Id + * @vdev_type: vdev type + * @vdev_subtype: vdev sub type + * + * WoW wake up event rule is following: + * 1) STA mode and P2P CLI mode wake up events are same + * 2) SAP mode and P2P GO mode wake up events are same + * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT + * + * Return: none + */ +void wma_register_wow_wakeup_events(WMA_HANDLE handle, + uint8_t vdev_id, + uint8_t vdev_type, + uint8_t vdev_subtype) +{ + tp_wma_handle wma = handle; + uint32_t event_bitmap; + + WMA_LOGI("vdev_type %d vdev_subtype %d vdev_id %d", vdev_type, + vdev_subtype, vdev_id); + + if ((WMI_VDEV_TYPE_STA == vdev_type) || + ((WMI_VDEV_TYPE_AP == vdev_type) && + (WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == vdev_subtype))) { + /* Configure STA/P2P CLI mode specific default wake up events */ + event_bitmap = WMA_WOW_STA_WAKE_UP_EVENTS; + WMA_LOGI("STA specific default wake up event 0x%x vdev id %d", + event_bitmap, vdev_id); + } else if (WMI_VDEV_TYPE_IBSS == vdev_type) { + /* Configure IBSS mode specific default wake up events */ + event_bitmap = (WMA_WOW_STA_WAKE_UP_EVENTS | + (1 << WOW_BEACON_EVENT)); + WMA_LOGI("IBSS specific default wake up event 0x%x vdev id %d", + event_bitmap, vdev_id); + } else if (WMI_VDEV_TYPE_AP == vdev_type) { + /* Configure SAP/GO mode specific default wake up events */ + event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS; + WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d", + event_bitmap, vdev_id); + } else { + WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype); + return; + } + + wma_add_wow_wakeup_event(wma, vdev_id, event_bitmap, true); + + return; +} + +/** + * wma_enable_disable_wakeup_event() - Configures wow wakeup events + * @wma: wma handle + * @vdev_id: vdev id + * @bitmap: Event bitmap + * @enable: enable/disable + * + * Return: none + */ +void wma_enable_disable_wakeup_event(WMA_HANDLE handle, + uint32_t vdev_id, + uint32_t bitmap, + bool enable) +{ + tp_wma_handle wma = handle; + + WMA_LOGI("vdev_id %d wake up event 0x%x enable %d", + vdev_id, bitmap, enable); + wma_add_wow_wakeup_event(wma, vdev_id, bitmap, enable); +} + +/** + * wma_enable_wow_in_fw() - wnable wow in fw + * @wma: wma handle + * + * Return: CDF status + */ +CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle) +{ + 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 = cds_get_context(CDF_MODULE_ID_PE); + + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return CDF_STATUS_E_FAILURE; + } +#endif /* CONFIG_CNSS */ + + 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 CDF_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; + if (hif_can_suspend_link()) + cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED; + else + cmd->pause_iface_config = WOW_IFACE_PAUSE_DISABLED; + + WMA_LOGI("suspend type: %s", + cmd->pause_iface_config == WOW_IFACE_PAUSE_ENABLED ? + "WOW_IFACE_PAUSE_ENABLED" : "WOW_IFACE_PAUSE_DISABLED"); + + cdf_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); + + WMA_LOGD("Credits:%d; Pending_Cmds: %d", + host_credits, wmi_pending_cmds); + + if (host_credits < WMI_WOW_REQUIRED_CREDITS) { + WMA_LOGE("%s: Host Doesn't have enough credits to Post WMI_WOW_ENABLE_CMDID! " + "Credits:%d, pending_cmds:%d\n", __func__, host_credits, + wmi_pending_cmds); +#ifndef QCA_WIFI_3_0_EMU + goto error; +#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 (cdf_wait_single_event(&wma->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) + != CDF_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)); +#ifdef CONFIG_CNSS + if (pMac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } +#else + CDF_BUG(0); +#endif /* CONFIG_CNSS */ + wmi_set_target_suspend(wma->wmi_handle, false); + return CDF_STATUS_E_FAILURE; + } + + if (wma->wow_nack) { + WMA_LOGE("FW not ready to WOW"); + wmi_set_target_suspend(wma->wmi_handle, false); + return CDF_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 (!cds_is_logp_in_progress()) + CDF_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 = cds_get_context(CDF_MODULE_ID_HIF); + + if (scn == NULL) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAULT; + } + + htc_cancel_deferred_target_sleep(scn); + + wma->wow.wow_enable_cmd_sent = true; + + return CDF_STATUS_SUCCESS; + +error: + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; +} + +/** + * wma_resume_req() - clear configured wow patterns in fw + * @wma: wma handle + * + * Return: CDF status + */ +CDF_STATUS wma_resume_req(tp_wma_handle wma) +{ + wma->no_of_resume_ind++; + + if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) + return CDF_STATUS_SUCCESS; + + wma->no_of_resume_ind = 0; + + /* Reset the DTIM Parameters */ + wma_set_resume_dtim(wma); + /* 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); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_wow_delete_pattern() - delete wow pattern in target + * @wma: wma handle + * @ptrn_id: pattern id + * @vdev_id: vdev id + * @user: true for user pattern and false for default pattern + * + * Return: CDF status + */ +static CDF_STATUS wma_wow_delete_pattern(tp_wma_handle wma, uint8_t ptrn_id, + uint8_t vdev_id, bool user) +{ + WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd; + struct wma_txrx_node *iface; + wmi_buf_t buf; + int32_t len; + int ret; + + len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param); + + iface = &wma->interfaces[vdev_id]; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return CDF_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 = vdev_id; + cmd->pattern_id = ptrn_id; + cmd->pattern_type = WOW_BITMAP_PATTERN; + + WMA_LOGI("Deleting pattern id: %d vdev id %d in fw", + cmd->pattern_id, vdev_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 CDF_STATUS_E_FAILURE; + } + + if (user) + iface->num_wow_user_patterns--; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_wow_add_pattern() - add wow pattern in target + * @wma: wma handle + * @ptrn: wow pattern + * + * This function does following: + * 1) Delete all default patterns of the vdev + * 2) Add received wow patterns for given vdev in target. + * + * Target is responsible for caching wow patterns accross multiple + * suspend/resumes until the pattern is deleted by user + * + * Return: CDF status + */ +CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn) +{ + uint8_t id; + uint8_t bit_to_check, pos; + struct wma_txrx_node *iface; + CDF_STATUS ret = CDF_STATUS_SUCCESS; + uint8_t new_mask[SIR_WOWL_BCAST_PATTERN_MAX_SIZE]; + + if (ptrn->session_id > wma->max_bssid) { + WMA_LOGE("Invalid vdev id (%d)", ptrn->session_id); + return CDF_STATUS_E_INVAL; + } + + iface = &wma->interfaces[ptrn->session_id]; + + /* clear all default patterns cofigured by wma */ + for (id = 0; id < iface->num_wow_default_patterns; id++) + wma_wow_delete_pattern(wma, id, ptrn->session_id, false); + + iface->num_wow_default_patterns = 0; + + WMA_LOGI("Add user passed wow pattern id %d vdev id %d", + ptrn->pattern_id, ptrn->session_id); + /* + * Convert received pattern mask value from bit representation + * 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 + */ + cdf_mem_zero(new_mask, sizeof(new_mask)); + for (pos = 0; pos < ptrn->pattern_size; pos++) { + bit_to_check = (WMA_NUM_BITS_IN_BYTE - 1) - + (pos % WMA_NUM_BITS_IN_BYTE); + bit_to_check = 0x1 << bit_to_check; + if (ptrn->pattern_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, ptrn->session_id, + ptrn->pattern_id, + ptrn->pattern, ptrn->pattern_size, + ptrn->pattern_byte_offset, new_mask, + ptrn->pattern_size, true); + if (ret != CDF_STATUS_SUCCESS) + WMA_LOGE("Failed to add wow pattern %d", ptrn->pattern_id); + + return ret; +} + +/** + * wma_wow_delete_user_pattern() - delete user configured wow pattern in target + * @wma: wma handle + * @ptrn: wow pattern + * + * This function does following: + * 1) Deletes a particular user configured wow pattern in target + * 2) After deleting all user wow patterns add default wow patterns + * specific to that vdev. + * + * Return: CDF status + */ +CDF_STATUS wma_wow_delete_user_pattern(tp_wma_handle wma, + struct wow_delete_pattern *pattern) +{ + struct wma_txrx_node *iface; + + if (pattern->session_id > wma->max_bssid) { + WMA_LOGE("Invalid vdev id %d", pattern->session_id); + return CDF_STATUS_E_INVAL; + } + + iface = &wma->interfaces[pattern->session_id]; + if (iface->num_wow_user_patterns <= 0) { + WMA_LOGE("No valid user pattern. Num user pattern %u vdev %d", + iface->num_wow_user_patterns, pattern->session_id); + return CDF_STATUS_E_INVAL; + } + + WMA_LOGI("Delete user passed wow pattern id %d total user pattern %d", + pattern->pattern_id, iface->num_wow_user_patterns); + + wma_wow_delete_pattern(wma, pattern->pattern_id, + pattern->session_id, true); + + /* configure default patterns once all user patterns are deleted */ + if (!iface->num_wow_user_patterns) + wma_register_wow_default_patterns(wma, pattern->session_id); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_wow_enter() - store enable/disable status for pattern + * @wma: wma handle + * @info: wow parameters + * + * Records pattern enable/disable status locally. This choice will + * take effect when the driver enter into suspend state. + * + * Return: CDF status + */ +CDF_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); + cdf_mem_free(info); + return CDF_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; + + cdf_mem_free(info); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_wow_exit() - clear all wma states + * @wma: wma handle + * @info: wow params + * + * Return: CDF status + */ +CDF_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); + cdf_mem_free(info); + return CDF_STATUS_E_INVAL; + } + + iface = &wma->interfaces[info->sessionId]; + iface->ptrn_match_enable = false; + wma->wow.magic_ptrn_enable = false; + cdf_mem_free(info); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_suspend_req() - Handles suspend indication request received from umac. + * @wma: wma handle + * @info: suspend params + * + * Return: CDF status + */ +CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) +{ + struct wma_txrx_node *iface; + bool connected = false, pno_in_progress = false; + uint8_t i; + bool extscan_in_progress = false; + + wma->no_of_suspend_ind++; + + if (info->sessionId > wma->max_bssid) { + WMA_LOGE("Invalid vdev id (%d)", info->sessionId); + cdf_mem_free(info); + return CDF_STATUS_E_INVAL; + } + + iface = &wma->interfaces[info->sessionId]; + if (!iface) { + WMA_LOGD("vdev %d node is not found", info->sessionId); + cdf_mem_free(info); + return CDF_STATUS_SUCCESS; + } + + if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) { + cdf_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 CDF_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)) { + cdf_mem_free(info); + return CDF_STATUS_SUCCESS; + } + + wma->no_of_suspend_ind = 0; + wma->wow.gtk_pdev_enable = 0; + /* + * 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 /* QCA_IBSS_SUPPORT */ + ) && 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); + goto enable_wow; + } + } + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].conn_state) { + connected = true; + break; + } +#ifdef FEATURE_WLAN_SCAN_PNO + if (wma->interfaces[i].pno_in_progress) { + WMA_LOGD("PNO is in progress, enabling wow"); + pno_in_progress = true; + break; + } +#endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef FEATURE_WLAN_EXTSCAN + if (wma->interfaces[i].extscan_in_progress) { + WMA_LOGD("Extscan is in progress, enabling wow"); + 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 (!connected && !pno_in_progress && !extscan_in_progress) { + WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); + cdf_mem_free(info); + goto send_ready_to_suspend; + } + +enable_wow: + WMA_LOGE("WOW Suspend"); + + /* + * 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 /* FEATURE_WLAN_LPHB */ + + wma->wow.wow_enable = true; + wma->wow.wow_enable_cmd_sent = false; + + cdf_mem_free(info); + +send_ready_to_suspend: + /* Set the Suspend DTIM Parameters */ + wma_set_suspend_dtim(wma); + wma_send_status_to_suspend_ind(wma, true); + + /* to handle race between hif_pci_suspend and + * unpause/pause tx handler + */ + wma_set_wow_bus_suspend(wma, 1); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_send_host_wakeup_ind_to_fw() - send wakeup ind to fw + * @wma: wma handle + * + * Sends host wakeup indication to FW. On receiving this indication, + * FW will come out of WOW. + * + * Return: CDF status + */ +static CDF_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; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int32_t len; + int ret; +#ifdef CONFIG_CNSS + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return CDF_STATUS_E_FAILURE; + } +#endif /* CONFIG_CNSS */ + + 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 CDF_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)); + + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Host wakeup indication sent to fw"); + + cdf_status = cdf_wait_single_event(&(wma->wma_resume_event), + WMA_RESUME_TIMEOUT); + if (CDF_STATUS_SUCCESS != cdf_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 (!cds_is_logp_in_progress()) { +#ifdef CONFIG_CNSS + if (pMac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } +#else + CDF_BUG(0); +#endif /* CONFIG_CNSS */ + } else { + WMA_LOGE("%s: SSR in progress, ignore resume timeout", + __func__); + } + } else { + WMA_LOGD("Host wakeup received"); + } + + if (CDF_STATUS_SUCCESS == cdf_status) + wmi_set_target_suspend(wma->wmi_handle, false); + + return cdf_status; +} + +/** + * wma_disable_wow_in_fw() - Disable wow in PCIe resume context. + * @handle: wma handle + * + * Return: 0 for success or error code + */ +CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle) +{ + tp_wma_handle wma = handle; + CDF_STATUS ret; + + if (!wma->wow.wow_enable || !wma->wow.wow_enable_cmd_sent) + return CDF_STATUS_SUCCESS; + + ret = wma_send_host_wakeup_ind_to_fw(wma); + + if (ret != CDF_STATUS_SUCCESS) + return ret; + + wma->wow.wow_enable = false; + 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; + } +} + +/** + * wma_del_ts_req() - send DELTS request to fw + * @wma: wma handle + * @msg: delts params + * + * Return: none + */ +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__); + cdf_nbuf_free(buf); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (msg->setRICparams == true) + wma_set_ric_req(wma, msg, false); +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +err: + cdf_mem_free(msg); +} + +/** + * wma_aggr_qos_req() - send aggr qos request to fw + * @wma: handle to wma + * @pAggrQosRspMsg - combined struct for all ADD_TS requests. + * + * A function to handle WMA_AGGR_QOS_REQ. This will send out + * ADD_TS requestes to firmware in loop for all the ACs with + * active flow. + * + * Return: none + */ +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] = CDF_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] = + CDF_STATUS_E_FAILURE; + cdf_nbuf_free(buf); + } + } + } + +aggr_qos_exit: + /* send reponse to upper layers from here only. */ + wma_send_msg(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0); +} + +/** + * wma_add_ts_req() - send ADDTS request to fw + * @wma: wma handle + * @msg: ADDTS params + * + * Return: none + */ +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 + */ + uint32_t intervalMiliseconds; + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + 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 /* FEATURE_WLAN_ESE */ + msg->status = CDF_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 = CDF_STATUS_E_FAILURE; + cdf_nbuf_free(buf); + } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (msg->setRICparams == true) + wma_set_ric_req(wma, msg, true); +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +err: + wma_send_msg(wma, WMA_ADD_TS_RSP, msg, 0); +} + +/** + * wma_enable_disable_packet_filter() - enable/disable packet filter in target + * @wma: Pointer to wma handle + * @vdev_id: vdev id + * @enable: Flag to enable/disable packet filter + * + * Return: 0 for success or error code + */ +static int wma_enable_disable_packet_filter(tp_wma_handle wma, + uint8_t vdev_id, bool enable) +{ + int32_t len; + int ret = 0; + wmi_buf_t buf; + WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd; + + len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return -ENOMEM; + } + + cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_PACKET_FILTER_ENABLE_CMD_fixed_param)); + + cmd->vdev_id = vdev_id; + if (enable) + cmd->enable = PACKET_FILTER_SET_ENABLE; + else + cmd->enable = PACKET_FILTER_SET_DISABLE; + + WMA_LOGE("%s: Packet filter enable %d for vdev_id %d", + __func__, cmd->enable, vdev_id); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PACKET_FILTER_ENABLE_CMDID); + if (ret) + WMA_LOGE("Failed to send packet filter wmi cmd to fw"); + + return ret; +} + +/** + * wma_config_packet_filter() - configure packet filter in target + * @wma: Pointer to wma handle + * @vdev_id: vdev id + * @rcv_filter_param: Packet filter parameters + * @filter_id: Filter id + * @enable: Flag to add/delete packet filter configuration + * + * Return: 0 for success or error code + */ +static int wma_config_packet_filter(tp_wma_handle wma, + uint8_t vdev_id, tSirRcvPktFilterCfgType *rcv_filter_param, + uint8_t filter_id, bool enable) +{ + int len, i; + int err = 0; + wmi_buf_t buf; + WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd; + + + /* allocate the memory */ + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("Failed to allocate buffer to send set_param cmd"); + return -ENOMEM; + } + + cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param)); + + cmd->vdev_id = vdev_id; + cmd->filter_id = filter_id; + if (enable) + cmd->filter_action = PACKET_FILTER_SET_ACTIVE; + else + cmd->filter_action = PACKET_FILTER_SET_INACTIVE; + + if (enable) { + cmd->num_params = CDF_MIN( + WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER, + rcv_filter_param->numFieldParams); + cmd->filter_type = rcv_filter_param->filterType; + cmd->coalesce_time = rcv_filter_param->coalesceTime; + + for (i = 0; i < cmd->num_params; i++) { + cmd->paramsData[i].proto_type = + rcv_filter_param->paramsData[i].protocolLayer; + cmd->paramsData[i].cmp_type = + rcv_filter_param->paramsData[i].cmpFlag; + cmd->paramsData[i].data_length = + rcv_filter_param->paramsData[i].dataLength; + cmd->paramsData[i].data_offset = + rcv_filter_param->paramsData[i].dataOffset; + memcpy(&cmd->paramsData[i].compareData, + rcv_filter_param->paramsData[i].compareData, + sizeof(cmd->paramsData[i].compareData)); + memcpy(&cmd->paramsData[i].dataMask, + rcv_filter_param->paramsData[i].dataMask, + sizeof(cmd->paramsData[i].dataMask)); + } + } + + WMA_LOGE("Packet filter action %d filter with id: %d, num_params=%d", + cmd->filter_action, cmd->filter_id, cmd->num_params); + /* send the command along with data */ + err = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PACKET_FILTER_CONFIG_CMDID); + if (err) { + WMA_LOGE("Failed to send pkt_filter cmd"); + wmi_buf_free(buf); + return -EIO; + } + + /* Enable packet filter */ + if (enable) + wma_enable_disable_packet_filter(wma, vdev_id, true); + + return 0; +} + +/** + * wma_process_receive_filter_set_filter_req() - enable packet filter + * @wma_handle: wma handle + * @rcv_filter_param: filter params + * + * Return: 0 for success or error code + */ +int wma_process_receive_filter_set_filter_req(tp_wma_handle wma, + tSirRcvPktFilterCfgType *rcv_filter_param) +{ + int ret = 0; + uint8_t vdev_id; + + /* Get the vdev id */ + if (!wma_find_vdev_by_bssid(wma, rcv_filter_param->bssId, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", + rcv_filter_param->bssId); + return -EINVAL; + } + + ret = wma_config_packet_filter(wma, vdev_id, rcv_filter_param, + rcv_filter_param->filterId, true); + + return ret; +} + +/** + * wma_process_receive_filter_clear_filter_req() - disable packet filter + * @wma_handle: wma handle + * @rcv_clear_param: filter params + * + * Return: 0 for success or error code + */ +int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma, + tSirRcvFltPktClearParam *rcv_clear_param) +{ + int ret = 0; + uint8_t vdev_id; + + /* Get the vdev id */ + if (!wma_find_vdev_by_bssid(wma, rcv_clear_param->bssId, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", rcv_clear_param->bssId); + return -EINVAL; + } + + ret = wma_config_packet_filter(wma, vdev_id, NULL, + rcv_clear_param->filterId, false); + + return ret; +} + +#ifdef FEATURE_WLAN_ESE + +#define TSM_DELAY_HISTROGRAM_BINS 4 +/** + * wma_process_tsm_stats_req() - process tsm stats request + * @wma_handler - handle to wma + * @pTsmStatsMsg - TSM stats struct that needs to be populated and + * passed in message. + * + * A parallel function to WMA_ProcessTsmStatsReq for pronto. This + * function fetches stats from data path APIs and post + * WMA_TSM_STATS_RSP msg back to LIM. + * + * Return: CDF status + */ +CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, + void *pTsmStatsMsg) +{ + uint8_t counter; + uint32_t queue_delay_microsec = 0; + uint32_t tx_delay_microsec = 0; + uint16_t packet_count = 0; + uint16_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 /* FEATURE_WLAN_ESE_UPLOAD */ + 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 + */ + uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, }; + + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + cdf_mem_free(pTsmStatsMsg); + return CDF_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) cdf_mem_malloc(sizeof(tAniGetTsmStatsRsp)); + if (NULL == pTsmRspParams) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "%s: CDF MEM Alloc Failure", __func__); + CDF_ASSERT(0); + cdf_mem_free(pTsmStatsMsg); + return CDF_STATUS_E_NOMEM; + } + pTsmRspParams->staId = pStats->staId; + pTsmRspParams->rc = eSIR_FAILURE; + pTsmRspParams->tsmStatsReq = pStats; + pTsmMetric = &pTsmRspParams->tsmMetrics; +#else + pTsmMetric = (tpAniTrafStrmMetrics)&(pStats->tsmMetrics); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + /* 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, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0); +#else + wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmStatsMsg, 0); +#endif /* FEATURE_WLAN_ESE_UPLOAD */ + return CDF_STATUS_SUCCESS; +} + +#endif /* FEATURE_WLAN_ESE */ + +/** + * wma_add_clear_mcbc_filter() - set mcast filter command to fw + * @wma_handle: wma handle + * @vdev_id: vdev id + * @multicastAddr: mcast address + * @clearList: clear list flag + * + * Return: 0 for success or error code + */ +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); + cdf_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"); + cdf_mem_free(buf); + return -EIO; + } + WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d\n", + cmd->action, vdev_id, clearList); + WMA_LOGD("MCBC MAC Addr: %0x:%0x:%0x:%0x:%0x:%0x\n", + multicastAddr[0], multicastAddr[1], multicastAddr[2], + multicastAddr[3], multicastAddr[4], multicastAddr[5]); + return 0; +} + +/** + * wma_process_mcbc_set_filter_req() - process mcbc set filter request + * @wma_handle: wma handle + * @mcbc_param: mcbc params + * + * Return: CDF status + */ +CDF_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_LOGE("Number of multicast addresses is 0"); + return CDF_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 CDF_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 CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_GTK_OFFLOAD +#define GTK_OFFLOAD_ENABLE 0 +#define GTK_OFFLOAD_DISABLE 1 + +/** + * wma_gtk_offload_status_event() - GTK offload status event handler + * @handle: wma handle + * @event: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_gtk_offload_status_event(void *handle, uint8_t *event, + uint32_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; + cds_msg_t cds_msg; + uint8_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 = cdf_mem_malloc(sizeof(*resp)); + if (!resp) { + WMA_LOGE("%s: Failed to alloc response", __func__); + return -ENOMEM; + } + cdf_mem_zero(resp, sizeof(*resp)); + resp->mesgType = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + resp->mesgLen = sizeof(*resp); + resp->ulStatus = CDF_STATUS_SUCCESS; + resp->ulTotalRekeyCount = status->refresh_cnt; + /* TODO: Is the total rekey count and GTK rekey count same? */ + resp->ulGTKRekeyCount = status->refresh_cnt; + + cdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter, + GTK_REPLAY_COUNTER_BYTES); + + cdf_mem_copy(resp->bssId, bssid, IEEE80211_ADDR_LEN); + +#ifdef IGTK_OFFLOAD + /* TODO: Is the refresh count same for GTK and IGTK? */ + resp->ulIGTKRekeyCount = status->refresh_cnt; +#endif /* IGTK_OFFLOAD */ + + cds_msg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + cds_msg.bodyptr = (void *)resp; + cds_msg.bodyval = 0; + + if (cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg) + != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to post GTK response to SME"); + cdf_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; +} + +/** + * wma_send_gtk_offload_req() - send GTK offload command to fw + * @wma: wma handle + * @vdev_id: vdev id + * @params: GTK offload parameters + * + * Return: CDF status + */ +static CDF_STATUS wma_send_gtk_offload_req(tp_wma_handle wma, uint8_t vdev_id, + tpSirGtkOffloadParams params) +{ + int len; + wmi_buf_t buf; + WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; + CDF_STATUS status = CDF_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 = CDF_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 */ + cdf_mem_copy(cmd->KCK, params->aKCK, GTK_OFFLOAD_KCK_BYTES); + cdf_mem_copy(cmd->KEK, params->aKEK, GTK_OFFLOAD_KEK_BYTES); + cdf_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 = CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags); +out: + WMA_LOGD("%s Exit", __func__); + return status; +} + +/** + * wma_process_gtk_offload_req() - process GTK offload req from umac + * @handle: wma handle + * @params: GTK offload params + * + * Return: CDF status + */ +CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma, + tpSirGtkOffloadParams params) +{ + uint8_t vdev_id; + CDF_STATUS status = CDF_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 = CDF_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 = CDF_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 != CDF_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: + cdf_mem_free(params); + WMA_LOGD("%s Exit", __func__); + return status; +} + +/** + * wma_process_gtk_offload_getinfo_req() - send GTK offload cmd to fw + * @wma: wma handle + * @params: GTK offload params + * + * Return: CDF status + */ +CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma, + tpSirGtkOffloadGetInfoRspParams params) +{ + uint8_t vdev_id; + int len; + wmi_buf_t buf; + WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; + CDF_STATUS status = CDF_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 = CDF_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 = CDF_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 = CDF_STATUS_E_FAILURE; + } +out: + cdf_mem_free(params); + WMA_LOGD("%s Exit", __func__); + return status; +} +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + +/** + * wma_enable_arp_ns_offload() - enable ARP NS offload + * @wma: wma handle + * @tpSirHostOffloadReq: offload request + * @bArpOnly: flag + * + * To configure ARP NS off load data to firmware + * when target goes to wow mode. + * + * Return: CDF Status + */ +CDF_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; + uint8_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); + cdf_mem_free(pHostOffloadParams); + return CDF_STATUS_E_INVAL; + } + + if (!wma->interfaces[vdev_id].vdev_up) { + + WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id); + cdf_mem_free(pHostOffloadParams); + return CDF_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__); + cdf_mem_free(pHostOffloadParams); + return CDF_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) + cdf_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("NS solicitedIp: %pI6, targetIp: %pI6", + &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 /* WLAN_NS_OFFLOAD */ + 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); + cdf_mem_free(pHostOffloadParams); + return CDF_STATUS_E_FAILURE; + } + + cdf_mem_free(pHostOffloadParams); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn + * @handle: wma handle + * @pAddPeriodicTxPtrnParams: tx ptrn params + * + * Retrun: CDF status + */ +CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(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; + uint8_t *buf_ptr; + uint32_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 CDF_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 CDF_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); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_INVAL; + } + buf_ptr = (uint8_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; + cdf_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn + * @handle: wma handle + * @pDelPeriodicTxPtrnParams: tx ptrn params + * + * Retrun: CDF status + */ +CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(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; + uint32_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 CDF_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 CDF_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); + cdf_nbuf_free(wmi_buf); + return CDF_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_STATS_EXT +/** + * wma_stats_ext_req() - request ext stats from fw + * @wma_ptr: wma handle + * @preq: stats ext params + * + * Return: CDF status + */ +CDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle) wma_ptr; + wmi_req_stats_ext_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_t len; + uint8_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 = (uint8_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; + cdf_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 /* WLAN_FEATURE_STATS_EXT */ + +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT +/** + * wma_send_status_of_ext_wow() - send ext wow status to SME + * @wma: wma handle + * @status: status + * + * Return: none + */ +static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status) +{ + tSirReadyToExtWoWInd *ready_to_extwow; + CDF_STATUS vstatus; + cds_msg_t cds_msg; + uint8_t len; + + WMA_LOGD("Posting ready to suspend indication to umac"); + + len = sizeof(tSirReadyToExtWoWInd); + ready_to_extwow = (tSirReadyToExtWoWInd *) cdf_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; + + cds_msg.type = eWNI_SME_READY_TO_EXTWOW_IND; + cds_msg.bodyptr = (void *)ready_to_extwow; + cds_msg.bodyval = 0; + + vstatus = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (vstatus != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to post ready to suspend"); + cdf_mem_free(ready_to_extwow); + } +} + +/** + * wma_enable_ext_wow() - enable ext wow in fw + * @wma: wma handle + * @params: ext wow params + * + * Return:0 for success or error code + */ +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 CDF_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 CDF_STATUS_E_FAILURE; + } + + wma_send_status_of_ext_wow(wma, true); + return CDF_STATUS_SUCCESS; + +} + +/** + * wma_set_app_type1_params_in_fw() - set app type1 params in fw + * @wma: wma handle + * @appType1Params: app type1 params + * + * Return: CDF status + */ +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 CDF_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); + cdf_mem_copy(cmd->ident, appType1Params->identification_id, 8); + cmd->ident_len = appType1Params->id_length; + cdf_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_app_type2_params_in_fw() - set app type2 params in fw + * @wma: wma handle + * @appType2Params: app type2 params + * + * Return: CDF status + */ +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 CDF_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; + + cdf_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; + +} +#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */ + +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +/** + * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger + * @handle: wma handle + * @event: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_auto_shutdown_event_handler(void *handle, uint8_t *event, + uint32_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(); +} + +/** + * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware + * @wma: wma handle + * @auto_sh_cmd: auto shutdown timer value + * + * Return: CDF status + */ +CDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle, + tSirAutoShutdownCmdParams * + auto_sh_cmd) +{ + int status = 0; + wmi_buf_t buf = NULL; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */ + +#ifdef WLAN_FEATURE_NAN +/** + * wma_nan_req() - to send nan request to target + * @wma: wma_handle + * @nan_req: request data which will be non-null + * + * Return: CDF status + */ +CDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req) +{ + int ret; + tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr; + wmi_nan_cmd_param *cmd; + wmi_buf_t buf; + uint16_t len = sizeof(*cmd); + uint16_t nan_data_len, nan_data_len_aligned; + uint8_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 CDF_STATUS_E_FAILURE; + } + nan_data_len = nan_req->request_data_len; + nan_data_len_aligned = roundup(nan_req->request_data_len, + sizeof(uint32_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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; + cdf_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 /* WLAN_FEATURE_NAN */ + +#ifdef DHCP_SERVER_OFFLOAD +/** + * wma_process_dhcpserver_offload() - enable DHCP server offload + * @wma_handle: wma handle + * @pDhcpSrvOffloadInfo: DHCP server offload info + * + * Return: 0 for success or error code + */ +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); + cdf_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 = 0; + 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 +/** + * wma_set_led_flashing() - set led flashing in fw + * @wma_handle: wma handle + * @flashing: flashing request + * + * Return: CDF status + */ +CDF_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; + uint8_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 CDF_STATUS_E_INVAL; + } + if (!flashing) { + WMA_LOGE(FL("invalid parameter: flashing")); + return CDF_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 = (uint8_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; + + 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 CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */ + +#ifdef FEATURE_WLAN_CH_AVOID +/** + * wma_channel_avoid_evt_handler() - process channel to avoid event from FW. + * @handle: wma handle + * @event: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_channel_avoid_evt_handler(void *handle, uint8_t *event, + uint32_t len) +{ + wmi_avoid_freq_ranges_event_fixed_param *afr_fixed_param; + wmi_avoid_freq_range_desc *afr_desc; + uint32_t num_freq_ranges, freq_range_idx; + tSirChAvoidIndType *sca_indication; + CDF_STATUS cdf_status; + cds_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 *) + cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("Fail to post eWNI_SME_CH_AVOID_IND msg to SME"); + cdf_mem_free(sca_indication); + return -EINVAL; + } + + return 0; +} + +/** + * wma_process_ch_avoid_update_req() - handles channel avoid update request + * @wma_handle: wma handle + * @ch_avoid_update_req: channel avoid update params + * + * Return: CDF status + */ +CDF_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; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGI("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI", + __func__); + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_WLAN_CH_AVOID */ + +/** + * wma_set_reg_domain() - set reg domain + * @clientCtxt: client context + * @regId: reg id + * + * Return: CDF status + */ +CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId) +{ + if (CDF_STATUS_SUCCESS != + cds_set_reg_domain(clientCtxt, regId)) + return CDF_STATUS_E_INVAL; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_send_regdomain_info_to_fw() - send regdomain info to fw + * @reg_dmn: reg domain + * @regdmn2G: 2G reg domain + * @regdmn5G: 5G reg domain + * @ctl2G: 2G test limit + * @ctl5G: 5G test limit + * + * Return: none + */ +void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, + uint16_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); + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + 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__); + cdf_nbuf_free(buf); + } + + if ((((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_JAPAN) || + ((reg_dmn & ~COUNTRY_ERD_FLAG) == CTRY_KOREA_ROC)) && + (true == wma->tx_chain_mask_cck)) + cck_mask_val = 1; + + cck_mask_val |= (wma->self_gen_frm_pwr << 16); + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK, + cck_mask_val); + if (ret) + WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d", + ret); + + return; +} + +/** + * wma_bus_suspend() - handles bus suspend request from hdd + * + * Calls the appropriate handler based on configuration and event + * + * Return: 0 for success or error code + */ +int wma_bus_suspend(void) +{ + WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == handle) { + WMA_LOGE("%s: wma context is NULL", __func__); + return -EFAULT; + } + + WMA_LOGE("%s: wow mode selected %d", __func__, + wma_is_wow_mode_selected(handle)); + + if (wma_check_scan_in_progress(handle)) { + WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__); + return -EBUSY; + } + + if (wma_is_wow_mode_selected(handle)) + return cdf_status_to_os_return(wma_enable_wow_in_fw(handle)); + + return wma_suspend_target(handle, 0); +} + +/** + * wma_bus_resume() - handles bus resume request from hdd + * @handle: valid wma handle + * + * Calls the appropriate handler based on configuration + * + * Return: 0 for success or error code + */ +int wma_bus_resume(void) +{ + WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); + int wow_mode; + if (NULL == handle) { + WMA_LOGE("%s: wma context is NULL", __func__); + return -EFAULT; + } + + wow_mode = wma_is_wow_mode_selected(handle); + WMA_LOGE("%s: wow mode %d", __func__, wow_mode); + + if (!wow_mode) + return wma_resume_target(handle); + + return cdf_status_to_os_return(wma_disable_wow_in_fw(handle)); +} + +/** + * wma_suspend_target() - suspend target + * @handle: wma handle + * @disable_target_intr: disable target interrupt + * + * Return: 0 for success or error code + */ +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; + uint32_t len = sizeof(*cmd); + struct ol_softc *scn; + int ret; + + if (!wma_handle || !wma_handle->wmi_handle) { + WMA_LOGE("WMA is closed. can not issue suspend cmd"); + return -EINVAL; + } + /* + * 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 -ENOMEM; + + 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; + } + cdf_event_reset(&wma_handle->target_suspend); + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, wmibuf, len, + WMI_PDEV_SUSPEND_CMDID); + if (ret < 0) { + cdf_nbuf_free(wmibuf); + return ret; + } + + wmi_set_target_suspend(wma_handle->wmi_handle, true); + + if (cdf_wait_single_event(&wma_handle->target_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) + != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to get ACK from firmware for pdev suspend"); + wmi_set_target_suspend(wma_handle->wmi_handle, false); + return -EFAULT; + } + + scn = cds_get_context(CDF_MODULE_ID_HIF); + + if (scn == NULL) { + WMA_LOGE("%s: Failed to get HIF context", __func__); + CDF_ASSERT(0); + return -EFAULT; + } + + htc_cancel_deferred_target_sleep(scn); + + return 0; +} + +/** + * wma_target_suspend_acknowledge() - update target susspend status + * @context: wma context + * + * Return: none + */ +void wma_target_suspend_acknowledge(void *context) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + int wow_nack = *((int *)context); + + if (NULL == wma) { + WMA_LOGE("%s: wma is NULL", __func__); + return; + } + + wma->wow_nack = wow_nack; + cdf_event_set(&wma->target_suspend); + if (wow_nack) + cdf_wake_lock_timeout_acquire(&wma->wow_wake_lock, + WMA_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_WOW); +} + +/** + * wma_resume_target() - resume target + * @handle: wma handle + * + * Return: 0 for success or error code + */ +int wma_resume_target(WMA_HANDLE handle) +{ + int ret; + tp_wma_handle wma = (tp_wma_handle) handle; + wmi_buf_t wmibuf; + wmi_pdev_resume_cmd_fixed_param *cmd; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; +#ifdef CONFIG_CNSS + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + if (NULL == pMac) { + WMA_LOGE("%s: Unable to get PE context", __func__); + return -EINVAL; + } +#endif /* CONFIG_CNSS */ + + wmibuf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd)); + if (wmibuf == NULL) { + return -ENOMEM; + } + 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; + cdf_event_reset(&wma->wma_resume_event); + ret = wmi_unified_cmd_send(wma->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); + } + + cdf_status = cdf_wait_single_event(&(wma->wma_resume_event), + WMA_RESUME_TIMEOUT); + if (CDF_STATUS_SUCCESS != cdf_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 (!cds_is_logp_in_progress()) { +#ifdef CONFIG_CNSS + if (pMac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } +#else + CDF_BUG(0); +#endif /* CONFIG_CNSS */ + } else { + WMA_LOGE("%s: SSR in progress, ignore resume timeout", + __func__); + } + } else { + WMA_LOGD("Host wakeup received"); + } + + if (CDF_STATUS_SUCCESS == cdf_status) + wmi_set_target_suspend(wma->wmi_handle, false); + + return ret; +} + +/** + * wma_get_modeselect() - get modeSelect flag based on phy_capability + * @wma: wma handle + * @modeSelect: mode Select + * + * Return: none + */ +void wma_get_modeselect(tp_wma_handle wma, uint32_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; + } +} + + +#ifdef FEATURE_WLAN_TDLS +/** + * wma_tdls_event_handler() - handle TDLS event + * @handle: wma handle + * @event: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_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 -EINVAL; + } + + param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return -EINVAL; + } + + peer_event = param_buf->fixed_param; + if (!peer_event) { + WMA_LOGE("%s: received null event data from target", __func__); + return -EINVAL; + } + + tdls_event = (tSirTdlsEventnotify *) + cdf_mem_malloc(sizeof(*tdls_event)); + if (!tdls_event) { + WMA_LOGE("%s: failed to allocate memory for tdls_event", + __func__); + return -ENOMEM; + } + + 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 = WMA_TDLS_SHOULD_DISCOVER_CMD; + break; + case WMI_TDLS_SHOULD_TEARDOWN: + tdls_event->messageType = WMA_TDLS_SHOULD_TEARDOWN_CMD; + break; + case WMI_TDLS_PEER_DISCONNECTED: + tdls_event->messageType = WMA_TDLS_PEER_DISCONNECTED_CMD; + break; + default: + WMA_LOGE("%s: Discarding unknown tdls event(%d) from target", + __func__, peer_event->peer_status); + return -EINVAL; + } + + 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: + WMA_LOGE("%s: unknown reason(%d) in tdls event(%d) from target", + __func__, peer_event->peer_reason, + peer_event->peer_status); + return -EINVAL; + } + + 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; +} + +/** + * wma_set_tdls_offchan_mode() - set tdls off channel mode + * @handle: wma handle + * @chan_switch_params: Pointer to tdls channel switch parameter structure + * + * This function sets tdls off channel mode + * + * Return: 0 on success; Negative errno otherwise + */ +int wma_set_tdls_offchan_mode(WMA_HANDLE handle, + tdls_chan_switch_params *chan_switch_params) +{ + 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(FL( + "WMA is closed, can not issue tdls off channel cmd" + )); + ret = -EINVAL; + goto end; + } + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + 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(chan_switch_params->peer_mac_addr, + &cmd->peer_macaddr); + cmd->vdev_id = chan_switch_params->vdev_id; + cmd->offchan_mode = chan_switch_params->tdls_sw_mode; + cmd->is_peer_responder = chan_switch_params->is_responder; + cmd->offchan_num = chan_switch_params->tdls_off_ch; + cmd->offchan_bw_bitmap = chan_switch_params->tdls_off_ch_bw_offset; + cmd->offchan_oper_class = chan_switch_params->oper_class; + + WMA_LOGD(FL("Peer MAC Addr mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"), + cmd->peer_macaddr.mac_addr31to0, + cmd->peer_macaddr.mac_addr47to32); + + WMA_LOGD(FL( + "vdev_id: %d, off channel mode: %d, off channel Num: %d, off channel offset: 0x%x, is_peer_responder: %d, operating class: %d" + ), + 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(FL("failed to send tdls off chan command")); + cdf_nbuf_free(wmi_buf); + ret = -EIO; + } + +end: + if (chan_switch_params) + cdf_mem_free(chan_switch_params); + return ret; +} + +/** + * wma_update_fw_tdls_state() - send enable/disable tdls for a vdev + * @wma: wma handle + * @pwmaTdlsparams: TDLS params + * + * Return: 0 for sucess or error code + */ +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; + uint16_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 { + 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; + + 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 ", + __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); + + 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__); + cdf_nbuf_free(wmi_buf); + ret = -EIO; + goto end_fw_tdls_state; + } + WMA_LOGD("%s: vdev_id %d", __func__, wma_tdls->vdev_id); + +end_fw_tdls_state: + if (pwmaTdlsparams) + cdf_mem_free(pwmaTdlsparams); + return ret; +} + +/** + * wma_update_tdls_peer_state() - update TDLS peer state + * @handle: wma handle + * @peerStateParams: TDLS peer state params + * + * Return: 0 for success or error code + */ +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; + uint8_t *buf_ptr; + uint32_t i; + ol_txrx_pdev_handle pdev; + uint8_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 (!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 (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) { + cdf_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 = (uint8_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 WMA_TDLS_PEER_STATE_PEERING: + cmd->peer_state = WMI_TDLS_PEER_STATE_PEERING; + break; + case WMA_TDLS_PEER_STATE_CONNECTED: + cmd->peer_state = WMI_TDLS_PEER_STATE_CONNECTED; + break; + case WMA_TDLS_PEER_STATE_TEARDOWN: + cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN; + 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 = + cds_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__); + cdf_nbuf_free(wmi_buf); + ret = -EIO; + goto end_tdls_peer_state; + } + + /* in case of teardown, remove peer from fw */ + if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) { + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + 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; + } + + 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, false); + } + +end_tdls_peer_state: + if (peerStateParams) + cdf_mem_free(peerStateParams); + return ret; +} +#endif /* FEATURE_WLAN_TDLS */ + + +/** + * wma_dfs_attach() - Attach DFS methods to the umac state. + * @dfs_ic: ieee80211com ptr + * + * Return: Return ieee80211com ptr with updated info + */ +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; + cdf_mutex_init(&dfs_ic->chan_lock); + /* Initializes DFS Data Structures and queues */ + dfs_attach(dfs_ic); + + return dfs_ic; +} + +/** + * wma_dfs_detach() - Detach DFS methods + * @dfs_ic: ieee80211com ptr + * + * Return: none + */ +void wma_dfs_detach(struct ieee80211com *dfs_ic) +{ + dfs_detach(dfs_ic); + + cdf_mutex_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); +} + +/** + * wma_dfs_configure() - configure dfs + * @ic: ieee80211com ptr + * + * Configures Radar Filters during + * vdev start/channel change/regulatory domain + * change.This Configuration enables to program + * the DFS pattern matching module. + * + * Return: none + */ +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 = CDF_ARRAY_SIZE(dfs_fcc_radars); + rinfo.b5pulses = dfs_fcc_bin5pulses; + rinfo.numb5radars = CDF_ARRAY_SIZE(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 = CDF_ARRAY_SIZE(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 = CDF_ARRAY_SIZE(dfs_mkk4_radars); + rinfo.b5pulses = dfs_jpn_bin5pulses; + rinfo.numb5radars = CDF_ARRAY_SIZE(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__); + } +} + +/** + * wma_dfs_configure_channel() - configure DFS channel + * @dfs_ic: ieee80211com ptr + * @chan: wmi channel + * @chanmode: channel mode + * @ req: vdev start request + * + * Set the Channel parameters in to DFS module + * Also,configure the DFS radar filters for + * matching the DFS phyerrors. + * + * Return: ieee80211 channel / NULL for error + */ +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; + } + 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 (CH_WIDTH_80MHZ == req->chan_width) { + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80; + } + if (CH_WIDTH_40MHZ == req->chan_width) { + if (req->chan < req->ch_center_freq_seg0) + dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ? + IEEE80211_CHAN_VHT40PLUS : + IEEE80211_CHAN_HT40PLUS); + else + dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ? + IEEE80211_CHAN_VHT40MINUS : + IEEE80211_CHAN_HT40MINUS); + } else if (CH_WIDTH_20MHZ == req->chan_width) { + 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; +} + + +/** + * wma_set_dfs_region() - set DFS region + * @wma: wma handle + * + * Configure the DFS region for DFS radar filter initialization + * + * Return: none + */ +void wma_set_dfs_region(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); +} + +/** + * wma_get_channels() - prepare dfs radar channel list + * @ichan: channel + * @chan_list: return channel list + * + * Return: return number of channels + */ +int wma_get_channels(struct ieee80211_channel *ichan, + struct wma_dfs_radar_channel_list *chan_list) +{ + uint8_t center_chan = cds_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; +} + + +/** + * wma_dfs_indicate_radar() - Indicate Radar to SAP/HDD + * @ic: ieee80211com ptr + * @ichan: ieee 80211 channel + * + * Return: 0 for success or error code + */ +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 wma_dfs_radar_ind wma_radar_event; + tpAniSirGlobal pmac = NULL; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (wma == NULL) { + WMA_LOGE("%s: DFS- Invalid wma", __func__); + return -ENOENT; + } + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + pmac = (tpAniSirGlobal) + cds_get_context(CDF_MODULE_ID_PE); + + 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 *) + cdf_mem_malloc(sizeof(struct wma_dfs_radar_indication)); + if (radar_event == NULL) { + WMA_LOGE("%s:DFS- Invalid radar_event", __func__); + return -ENOMEM; + } + + /* + * 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. + */ + if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) || + (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) { + wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; + /* Indicate the radar event to HDD to stop the netif Tx queues */ + wma_radar_event.ieee_chan_number = ichan->ic_ieee; + wma_radar_event.chan_freq = ichan->ic_freq; + wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND; + wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event); + WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__); + + /* + * 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, WMA_DFS_RADAR_IND, (void *)radar_event, 0); + WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__); + } + + return 0; +} + +#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: CDF_STATUS_SUCCESS for success otherwise failure + * + */ +CDF_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGI(FL("Get firmware mem dump request sent successfully")); + return CDF_STATUS_SUCCESS; +} + +/** + * 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 + * + * Return: CDF_STATUS + */ +static CDF_STATUS wma_fw_mem_dump_rsp(uint32_t req_id, uint32_t status) +{ + struct fw_dump_rsp *dump_rsp; + cds_msg_t sme_msg = {0}; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + dump_rsp = cdf_mem_malloc(sizeof(*dump_rsp)); + + if (!dump_rsp) { + WMA_LOGE(FL("Memory allocation failed.")); + cdf_status = CDF_STATUS_E_NOMEM; + return cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Fail to post fw mem dump ind msg")); + cdf_mem_free(dump_rsp); + } + + return cdf_status; +} + +/** + * 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. + * + * Return: integer (0 for success and error code otherwise) + */ +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; + CDF_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 (CDF_STATUS_SUCCESS != status) { + WMA_LOGE("Error posting FW MEM DUMP RSP."); + return -EINVAL; + } + + WMA_LOGI("FW MEM DUMP RSP posted successfully"); + return 0; +} +#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: CDF_STATUS_SUCCESS for success otherwise failure + * + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + + /* Validate the input */ + if (ie_info->length <= 0) { + WMA_LOGE(FL("Invalid IE length")); + return CDF_STATUS_E_INVAL; + } + + 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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + cdf_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; + + cdf_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; +} + diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c new file mode 100644 index 000000000000..0676686d68e0 --- /dev/null +++ b/core/wma/src/wma_main.c @@ -0,0 +1,5382 @@ +/* + * 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_main.c + * + * This file contains wma initialization and FW exchange + * related functions. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#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 "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +#include "wma_ocb.h" + +#define WMA_LOG_COMPLETION_TIMER 10000 /* 10 seconds */ +#define WMA_SERVICE_READY_EXT_TIMEOUT 2000 /* 2 seconds */ + +static uint32_t g_fw_wlan_feat_caps; + +/** + * wma_get_fw_wlan_feat_caps() - get fw feature capablity + * @featEnumValue: feature enum value + * + * Return: true/false + */ +uint8_t wma_get_fw_wlan_feat_caps(uint8_t featEnumValue) +{ + return (g_fw_wlan_feat_caps & (1 << featEnumValue)) ? true : false; +} + +/** + * wma_set_default_tgt_config() - set default tgt config + * @wma_handle: wma handle + * + * Return: none + */ +static void wma_set_default_tgt_config(tp_wma_handle wma_handle) +{ + struct ol_softc *scn; + uint8_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 = cds_get_context(CDF_MODULE_ID_HIF); + if (!scn) { + WMA_LOGE("%s: cds_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)); + tgt_cfg.scan_max_pending_req = wma_handle->max_scan; + + 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 /* PERE_IP_HDR_ALIGNMENT_WAR */ + wma_handle->wlan_resource_config = tgt_cfg; +} + +/** + * wma_cli_get_command() - WMA "get" command processor + * @vdev_id: virtual device for the command + * @param_id: parameter id + * @vpdev: parameter category + * + * Return: parameter value on success, -EINVAL on failure + */ +int wma_cli_get_command(int vdev_id, int param_id, int vpdev) +{ + int ret = 0; + tp_wma_handle wma; + struct wma_txrx_node *intr = NULL; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + + 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 /* QCA_SUPPORT_GTX */ + 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_POWER_GATING_SLEEP: + ret = wma->pdevconfig.pwrgating; + 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_cli_set2_command() - WMA "set 2 params" command processor + * @vdev_id: virtual device for the command + * @param_id: parameter id + * @sval1: first parameter value + * @sval2: second parameter value + * @vpdev: parameter category + * + * Command handler for set operations which require 2 parameters + * + * Return: 0 on success, errno on failure + */ +int wma_cli_set2_command(int vdev_id, int param_id, int sval1, + int sval2, int vpdev) +{ + cds_msg_t msg = { 0 }; + wma_cli_set_cmd_t *iwcmd; + + iwcmd = cdf_mem_malloc(sizeof(*iwcmd)); + if (!iwcmd) { + WMA_LOGE("%s: Failed alloc memory for iwcmd", __func__); + return -ENOMEM; + } + + cdf_mem_zero(iwcmd, sizeof(*iwcmd)); + iwcmd->param_value = sval1; + iwcmd->param_sec_value = sval2; + iwcmd->param_vdev_id = vdev_id; + iwcmd->param_id = param_id; + iwcmd->param_vp_dev = vpdev; + msg.type = WMA_CLI_SET_CMD; + msg.reserved = 0; + msg.bodyptr = iwcmd; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + WMA_LOGP("%s: Failed to post WMA_CLI_SET_CMD msg", + __func__); + cdf_mem_free(iwcmd); + return -EIO; + } + return 0; +} + +/** + * wma_cli_set_command() - WMA "set" command processor + * @vdev_id: virtual device for the command + * @param_id: parameter id + * @sval: parameter value + * @vpdev: parameter category + * + * Command handler for set operations + * + * Return: 0 on success, errno on failure + */ +int wma_cli_set_command(int vdev_id, int param_id, int sval, int vpdev) +{ + return wma_cli_set2_command(vdev_id, param_id, sval, 0, vpdev); + +} + +/** + * wma_set_priv_cfg() - set private config parameters + * @wma_handle: wma handle + * @privcmd: private command + * + * Return: 0 for success or error code + */ +static int32_t wma_set_priv_cfg(tp_wma_handle wma_handle, + wma_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: + 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 */ + uint8_t mcc_channel = privcmd->param_value & 0x000000FF; + uint8_t 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. + */ + uint8_t adapter_2_chan_number = + privcmd->param_value & 0x000000FF; + uint8_t adapter_1_chan_number = + (privcmd->param_value & 0x0000FF00) >> 8; + uint8_t 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; + + case WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID: + { + ol_txrx_pdev_handle pdev; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + WMA_LOGE("pdev NULL for uc stat"); + return -EINVAL; + } + ol_txrx_ipa_uc_get_stat(pdev); + } + break; + + default: + WMA_LOGE("Invalid wma config command id:%d", privcmd->param_id); + ret = -EINVAL; + } + return ret; +} + +/** + * wmi_unified_pdev_set_param() - set pdev parameters + * @wmi_handle: wmi handle + * @param_id: parameter id + * @param_value: parameter value + * + * Return: 0 on success, errno on failure + */ +int +wmi_unified_pdev_set_param(wmi_unified_t wmi_handle, WMI_PDEV_PARAM param_id, + uint32_t param_value) +{ + int ret; + wmi_pdev_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_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; +} + +/** + * 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, + wma_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"); + } +} + + +/** + * wma_process_cli_set_cmd() - set parameters to fw + * @wma: wma handle + * @privcmd: command + * + * Return: none + */ +static void wma_process_cli_set_cmd(tp_wma_handle wma, + wma_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 = cds_get_context(CDF_MODULE_ID_PE); + struct qpower_params *qparams = &intr[vid].config.qpower_params; + + WMA_LOGD("wmihandle %p", wma->wmi_handle); + + if (NULL == pMac) { + WMA_LOGE("%s: Failed to get pMac", __func__); + return; + } + + if (privcmd->param_id >= WMI_CMDID_MAX) { + /* + * This configuration setting is not done using any wmi + * command, call appropriate handler. + */ + if (wma_set_priv_cfg(wma, privcmd)) + WMA_LOGE("Failed to set wma priv congiuration"); + return; + } + + switch (privcmd->param_vp_dev) { + case VDEV_CMD: + WMA_LOGD("vdev id %d pid %d pval %d", privcmd->param_vdev_id, + privcmd->param_id, privcmd->param_value); + ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, + privcmd->param_vdev_id, + privcmd->param_id, + privcmd->param_value); + if (ret) { + WMA_LOGE("wmi_unified_vdev_set_param_send failed ret %d", + ret); + return; + } + break; + case PDEV_CMD: + WMA_LOGD("pdev pid %d pval %d", privcmd->param_id, + privcmd->param_value); + if ((privcmd->param_id == WMI_PDEV_PARAM_RX_CHAIN_MASK) || + (privcmd->param_id == WMI_PDEV_PARAM_TX_CHAIN_MASK)) { + wma_update_txrx_chainmask(wma->num_rf_chains, + &privcmd->param_value); + } + ret = wmi_unified_pdev_set_param(wma->wmi_handle, + privcmd->param_id, + privcmd->param_value); + if (ret) { + WMA_LOGE("wmi_unified_vdev_set_param_send failed ret %d", + ret); + return; + } + break; + case GEN_CMD: + { + ol_txrx_vdev_handle vdev = NULL; + struct wma_txrx_node *intr = wma->interfaces; + + vdev = wma_find_vdev_by_id(wma, privcmd->param_vdev_id); + if (!vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + return; + } + + WMA_LOGD("gen pid %d pval %d", privcmd->param_id, + privcmd->param_value); + + switch (privcmd->param_id) { + case GEN_VDEV_PARAM_AMPDU: + ret = ol_txrx_aggr_cfg(vdev, privcmd->param_value, 0); + if (ret) + WMA_LOGE("ol_txrx_aggr_cfg set ampdu failed ret %d", + ret); + else + intr[privcmd->param_vdev_id].config.ampdu = + privcmd->param_value; + break; + case GEN_VDEV_PARAM_AMSDU: + ret = ol_txrx_aggr_cfg(vdev, 0, privcmd->param_value); + if (ret) + WMA_LOGE("ol_txrx_aggr_cfg set amsdu failed ret %d", + ret); + else + intr[privcmd->param_vdev_id].config. + amsdu = privcmd->param_value; + break; + case GEN_PARAM_DUMP_AGC_START: + htc_dump(wma->htc_handle, AGC_DUMP, true); + break; + case GEN_PARAM_DUMP_AGC: + htc_dump(wma->htc_handle, AGC_DUMP, false); + break; + case GEN_PARAM_DUMP_CHANINFO_START: + htc_dump(wma->htc_handle, CHAN_DUMP, true); + break; + case GEN_PARAM_DUMP_CHANINFO: + htc_dump(wma->htc_handle, CHAN_DUMP, false); + break; + case GEN_PARAM_DUMP_WATCHDOG: + htc_dump(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; +#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG + case GEN_PARAM_DUMP_PCIE_ACCESS_LOG: + htc_dump(wma->htc_handle, PCIE_DUMP, false); + break; +#endif /* CONFIG_ATH_PCIE_ACCESS_DEBUG */ + 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 wma_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_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_POWER_GATING_SLEEP: + wma->pdevconfig.pwrgating = 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 (cfg_set_int(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 (cfg_set_int(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 wma_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); + } +} + +/** + * wma_process_fw_event() - process any fw event + * @wma: wma handle + * @buf: fw event buffer + * + * This function process any fw event to serialize it through mc thread. + * + * Return: none + */ +static int wma_process_fw_event(tp_wma_handle wma, + wma_process_fw_event_params *buf) +{ + struct wmi_unified *wmi_handle = (struct wmi_unified *)buf->wmi_handle; + + wmi_process_fw_event(wmi_handle, buf->evt_buf); + return 0; +} + +/** + * wma_process_fw_event_handler() - common event handler to serialize + * event processing through mc_thread + * @wmi_handle: wmi handle + * @evt_buf: event buffer + * + * Return: 0 on success, errno on failure + */ +int wma_process_fw_event_handler(struct wmi_unified *wmi_handle, + wmi_buf_t evt_buf) +{ + wma_process_fw_event_params *params_buf; + cds_msg_t cds_msg = { 0 }; + + params_buf = cdf_mem_malloc(sizeof(wma_process_fw_event_params)); + if (!params_buf) { + WMA_LOGE("%s: Failed alloc memory for params_buf", __func__); + cdf_nbuf_free(evt_buf); + return -ENOMEM; + } + + params_buf->wmi_handle = wmi_handle; + params_buf->evt_buf = evt_buf; + + cds_msg.type = WMA_PROCESS_FW_EVENT; + cds_msg.bodyptr = params_buf; + cds_msg.bodyval = 0; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_WMA, &cds_msg)) { + WMA_LOGP("%s: Failed to post WMA_PROCESS_FW_EVENT msg", + __func__); + cdf_nbuf_free(evt_buf); + cdf_mem_free(params_buf); + return -EFAULT; + } + WMA_LOGD("WMA_PROCESS_FW_EVENT posted"); + return 0; + +} + +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * ol_cfg_set_flow_control_parameters() - set flow control parameters + * @olCfg: cfg parameters + * @mac_params: mac parameters + * + * Return: none + */ +static +void ol_cfg_set_flow_control_parameters(struct txrx_pdev_cfg_param_t *olCfg, + tMacOpenParameters *mac_params) +{ + olCfg->tx_flow_start_queue_offset = + mac_params->tx_flow_start_queue_offset; + olCfg->tx_flow_stop_queue_th = + mac_params->tx_flow_stop_queue_th; +} +#else +static +void ol_cfg_set_flow_control_parameters(struct txrx_pdev_cfg_param_t *olCfg, + tMacOpenParameters *mac_params) +{ + return; +} +#endif + +#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 + +/** + * wma_open() - Allocate wma context and initialize it. + * @cds_context: cds context + * @wma_tgt_cfg_cb: tgt config callback fun + * @radar_ind_cb: dfs radar indication callback + * @mac_params: mac parameters + * + * Return: 0 on success, errno on failure + */ +CDF_STATUS wma_open(void *cds_context, + wma_tgt_cfg_cb tgt_cfg_cb, + wma_dfs_radar_indication_cb radar_ind_cb, + tMacOpenParameters *mac_params) +{ + tp_wma_handle wma_handle; + HTC_HANDLE htc_handle; + cdf_device_t cdf_dev; + void *wmi_handle; + CDF_STATUS cdf_status; + struct ol_softc *scn; + struct txrx_pdev_cfg_param_t olCfg = { 0 }; + + WMA_LOGD("%s: Enter", __func__); + + cdf_dev = cds_get_context(CDF_MODULE_ID_CDF_DEVICE); + htc_handle = cds_get_context(CDF_MODULE_ID_HTC); + + if (!htc_handle) { + WMA_LOGP("%s: Invalid HTC handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* Alloc memory for WMA Context */ + cdf_status = cds_alloc_context(cds_context, CDF_MODULE_ID_WMA, + (void **)&wma_handle, + sizeof(t_wma_handle)); + + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: Memory allocation failed for wma_handle", + __func__); + return cdf_status; + } + + cdf_mem_zero(wma_handle, sizeof(t_wma_handle)); + + if (cds_get_conparam() != CDF_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + cdf_wake_lock_init(&wma_handle->pno_wake_lock, "wlan_pno_wl"); +#endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef FEATURE_WLAN_EXTSCAN + cdf_wake_lock_init(&wma_handle->extscan_wake_lock, + "wlan_extscan_wl"); +#endif /* FEATURE_WLAN_EXTSCAN */ + cdf_wake_lock_init(&wma_handle->wow_wake_lock, "wlan_wow_wl"); + } + + /* attach the wmi */ + wmi_handle = wmi_unified_attach(wma_handle, + wma_process_fw_event_handler); + if (!wmi_handle) { + WMA_LOGP("%s: failed to attach WMI", __func__); + cdf_status = CDF_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->cds_context = cds_context; + wma_handle->cdf_dev = cdf_dev; + wma_handle->max_scan = mac_params->max_scan; + + /* initialize default target config */ + wma_set_default_tgt_config(wma_handle); + + 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; + + + wma_handle->tx_chain_mask_cck = mac_params->tx_chain_mask_cck; + wma_handle->self_gen_frm_pwr = mac_params->self_gen_frm_pwr; + + /* 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 /* WLAN_FEATURE_RX_FULL_REORDER_OL */ + olCfg.enable_rxthread = mac_params->enable_rxthread; + olCfg.ip_tcp_udp_checksum_offload = + mac_params->ip_tcp_udp_checksum_offload; + olCfg.ce_classify_enabled = mac_params->ce_classify_enabled; + + ol_cfg_set_flow_control_parameters(&olCfg, mac_params); + + ((p_cds_contextType) cds_context)->cfg_ctx = + ol_pdev_cfg_attach(((p_cds_contextType) cds_context)->cdf_ctx, + olCfg); + if (!(((p_cds_contextType) cds_context)->cfg_ctx)) { + WMA_LOGP("%s: failed to init cfg handle", __func__); + cdf_status = CDF_STATUS_E_NOMEM; + goto err_wmi_handle; + } + + /* adjust the cfg_ctx default value based on setting */ + ol_set_cfg_rx_fwd_disabled((ol_pdev_handle) + ((p_cds_contextType) cds_context)->cfg_ctx, + (uint8_t) mac_params->apDisableIntraBssFwd); + + /* adjust the packet log enable default value based on CFG INI setting */ + ol_set_cfg_packet_log_enabled((ol_pdev_handle) + ((p_cds_contextType) cds_context)-> + cfg_ctx, + (uint8_t)cds_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 (cds_get_conparam() == CDF_FTM_MODE) + wma_utf_attach(wma_handle); +#endif /* QCA_WIFI_FTM */ + + /*TODO: Recheck below parameters */ + scn = cds_get_context(CDF_MODULE_ID_HIF); + + if (NULL == scn) { + WMA_LOGE("%s: Failed to get scn", __func__); + cdf_status = CDF_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; + + 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; +#ifdef FEATURE_WLAN_RA_FILTERING + wma_handle->IsRArateLimitEnabled = mac_params->IsRArateLimitEnabled; + wma_handle->RArateLimitInterval = mac_params->RArateLimitInterval; +#endif /* FEATURE_WLAN_RA_FILTERING */ +#ifdef WLAN_FEATURE_LPSS + wma_handle->is_lpass_enabled = mac_params->is_lpass_enabled; +#endif + wma_set_nan_enable(wma_handle, mac_params); + /* + * 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 = cdf_mem_malloc(sizeof(struct wma_txrx_node) * + wma_handle->max_bssid); + if (!wma_handle->interfaces) { + WMA_LOGP("%s: failed to allocate interface table", __func__); + cdf_status = CDF_STATUS_E_NOMEM; + goto err_scn_context; + } + cdf_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; + wma_handle->old_hw_mode_index = WMA_DEFAULT_HW_MODE_INDEX; + wma_handle->new_hw_mode_index = WMA_DEFAULT_HW_MODE_INDEX; + wma_handle->saved_wmi_init_cmd.buf = NULL; + + cdf_status = cdf_event_init(&wma_handle->wma_ready_event); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: wma_ready_event initialization failed", __func__); + goto err_event_init; + } + cdf_status = cdf_event_init(&wma_handle->target_suspend); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: target suspend event initialization failed", + __func__); + goto err_event_init; + } + + /* Init Tx Frame Complete event */ + cdf_status = cdf_event_init(&wma_handle->tx_frm_download_comp_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGP("%s: failed to init tx_frm_download_comp_event", + __func__); + goto err_event_init; + } + + /* Init tx queue empty check event */ + cdf_status = cdf_event_init(&wma_handle->tx_queue_empty_event); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGP("%s: failed to init tx_queue_empty_event", __func__); + goto err_event_init; + } + + cdf_status = cdf_event_init(&wma_handle->wma_resume_event); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: wma_resume_event initialization failed", + __func__); + goto err_event_init; + } + + cdf_status = cdf_event_init(&wma_handle->recovery_event); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: recovery event initialization failed", __func__); + goto err_event_init; + } + + INIT_LIST_HEAD(&wma_handle->vdev_resp_queue); + cdf_spinlock_init(&wma_handle->vdev_respq_lock); + cdf_list_init(&wma_handle->wma_hold_req_queue, + MAX_ENTRY_HOLD_REQ_QUEUE); + cdf_spinlock_init(&wma_handle->wma_hold_req_q_lock); + cdf_atomic_init(&wma_handle->is_wow_bus_suspended); + cdf_atomic_init(&wma_handle->scan_id_counter); + + /* 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 /* FEATURE_OEM_DATA_SUPPORT */ + /* + * 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); + + /* Firmware debug log */ + cdf_status = dbglog_init(wma_handle->wmi_handle); + if (cdf_status != CDF_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 /* WLAN_FEATURE_NAN */ + +#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 /* WLAN_FEATURE_STATS_EXT */ +#ifdef FEATURE_WLAN_EXTSCAN + wma_register_extscan_event_handler(wma_handle); +#endif /* WLAN_FEATURE_STATS_EXT */ + + 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); + + /* Register peer assoc conf event handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_ASSOC_CONF_EVENTID, + wma_peer_assoc_conf_handler); + + return CDF_STATUS_SUCCESS; + +err_dbglog_init: + cdf_spinlock_destroy(&wma_handle->vdev_respq_lock); + cdf_spinlock_destroy(&wma_handle->wma_hold_req_q_lock); +err_event_init: + wmi_unified_unregister_event_handler(wma_handle->wmi_handle, + WMI_DEBUG_PRINT_EVENTID); + cdf_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 /* QCA_WIFI_FTM */ +err_wmi_handle: + cdf_mem_free(((p_cds_contextType) cds_context)->cfg_ctx); + OS_FREE(wmi_handle); + +err_wma_handle: + + if (cds_get_conparam() != CDF_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + cdf_wake_lock_destroy(&wma_handle->pno_wake_lock); +#endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef FEATURE_WLAN_EXTSCAN + cdf_wake_lock_destroy(&wma_handle->extscan_wake_lock); +#endif /* FEATURE_WLAN_EXTSCAN */ + cdf_wake_lock_destroy(&wma_handle->wow_wake_lock); + } + cds_free_context(cds_context, CDF_MODULE_ID_WMA, wma_handle); + + WMA_LOGD("%s: Exit", __func__); + + return cdf_status; +} + +/** + * wma_pre_start() - wma pre start + * @cds_ctx: cds context + * + * Return: 0 on success, errno on failure + */ +CDF_STATUS wma_pre_start(void *cds_ctx) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + A_STATUS status = A_OK; + tp_wma_handle wma_handle; + cds_msg_t wma_msg = { 0 }; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* Validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: invalid argument", __func__); + cdf_status = CDF_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__); + cdf_status = CDF_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; + + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &wma_msg); + if (CDF_STATUS_SUCCESS != cdf_status) { + WMA_LOGP("%s: Failed to post WNI_CFG_DNLD_REQ msg", __func__); + CDF_ASSERT(0); + cdf_status = CDF_STATUS_E_FAILURE; + } +end: + WMA_LOGD("%s: Exit", __func__); + return cdf_status; +} + +/** + * wma_send_msg() - Send wma message to PE. + * @wma_handle: wma handle + * @msg_type: message type + * @body_ptr: message body ptr + * @body_val: message body value + * + * Return: none + */ +void wma_send_msg(tp_wma_handle wma_handle, uint16_t msg_type, + void *body_ptr, uint32_t body_val) +{ + tSirMsgQ msg = { 0 }; + uint32_t status = CDF_STATUS_SUCCESS; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + msg.type = msg_type; + msg.bodyval = body_val; + msg.bodyptr = body_ptr; + status = lim_post_msg_api(pMac, &msg); + if (CDF_STATUS_SUCCESS != status) { + if (NULL != body_ptr) + cdf_mem_free(body_ptr); + CDF_ASSERT(0); + } + return; +} + +/** + * wma_set_base_macaddr_indicate() - set base mac address in fw + * @wma_handle: wma handle + * @customAddr: base mac address + * + * Return: 0 for success or error code + */ +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); + cdf_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"); + cdf_mem_free(buf); + return -EIO; + } + WMA_LOGD("Base MAC Addr: " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY((*customAddr))); + + 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, + uint8_t *event, + uint32_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) + cdf_mem_free(wma->events_logs_list); + + /* Store the event list for run time enable/disable */ + wma->events_logs_list = cdf_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__); + cdf_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) +{ + CDF_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 CDF_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 && (cds_is_log_report_in_progress() == false)) { + WMA_LOGE("Received WMI flush event without sending CMD"); + return -EINVAL; + } else if (!reason_code && cds_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 = cdf_mc_timer_stop(&wma->log_completion_timer); + if (status != CDF_STATUS_SUCCESS) + WMA_LOGE("Failed to stop the log completion timeout"); + cds_logging_set_fw_flush_complete(); + } else if (reason_code && cds_is_log_report_in_progress() == false) { + /* Asynchronous flush event for fatal events */ + WMA_LOGE("Received asynchronous WMI flush event: reason=%d", + reason_code); + status = cds_set_log_completion(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_FIRMWARE, + reason_code); + if (CDF_STATUS_SUCCESS != status) { + WMA_LOGE("%s: Failed to set log trigger params", + __func__); + return CDF_STATUS_E_FAILURE; + } + cds_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 CDF_STATUS_E_FAILURE; + } + return 0; +} + +/** + * wma_soc_set_hw_mode_resp_evt_handler() - Set HW mode resp evt handler + * @handle: WMI handle + * @event: Event recevied from FW + * @len: Length of the event + * + * Event handler for WMI_SOC_SET_HW_MODE_RESP_EVENTID that is sent to host + * driver in response to a WMI_SOC_SET_HW_MODE_CMDID being sent to WLAN firmware + * + * Return: Success on receiving valid params from FW + */ +static int wma_soc_set_hw_mode_resp_evt_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + WMI_SOC_SET_HW_MODE_RESP_EVENTID_param_tlvs *param_buf; + wmi_soc_set_hw_mode_response_event_fixed_param *wmi_event; + wmi_soc_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; + uint32_t i; + struct sir_set_hw_mode_resp *hw_mode_resp; + tp_wma_handle wma = (tp_wma_handle) handle; + + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* Since WMA handle itself is NULL, we cannot send fail + * response back to LIM here + */ + return CDF_STATUS_E_NULL_VALUE; + } + + hw_mode_resp = cdf_mem_malloc(sizeof(*hw_mode_resp)); + if (!hw_mode_resp) { + WMA_LOGI("%s: Memory allocation failed", __func__); + /* Since this memory allocation itself failed, we cannot + * send fail response back to LIM here + */ + return CDF_STATUS_E_NULL_VALUE; + } + + param_buf = (WMI_SOC_SET_HW_MODE_RESP_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("Invalid WMI_SOC_SET_HW_MODE_RESP_EVENTID event"); + /* Need to send response back to upper layer to free + * active command list + */ + goto fail; + } + + wmi_event = param_buf->fixed_param; + hw_mode_resp->status = wmi_event->status; + hw_mode_resp->cfgd_hw_mode_index = wmi_event->cfgd_hw_mode_index; + hw_mode_resp->num_vdev_mac_entries = wmi_event->num_vdev_mac_entries; + + WMA_LOGI("%s: status:%d cfgd_hw_mode_index:%d num_vdev_mac_entries:%d", + __func__, wmi_event->status, + wmi_event->cfgd_hw_mode_index, + wmi_event->num_vdev_mac_entries); + vdev_mac_entry = + param_buf->wmi_soc_set_hw_mode_response_vdev_mac_mapping; + + /* Store the vdev-mac map in WMA and prepare to send to PE */ + for (i = 0; i < wmi_event->num_vdev_mac_entries; i++) { + uint32_t vdev_id, mac_id; + vdev_id = vdev_mac_entry[i].vdev_id; + mac_id = vdev_mac_entry[i].mac_id; + + WMA_LOGI("%s: vdev_id:%d mac_id:%d", + __func__, vdev_id, mac_id); + + hw_mode_resp->vdev_mac_map[i].vdev_id = vdev_id; + hw_mode_resp->vdev_mac_map[i].mac_id = mac_id; + wma_update_intf_hw_mode_params(vdev_id, mac_id, + wmi_event->cfgd_hw_mode_index); + } + + if (hw_mode_resp->status == SET_HW_MODE_STATUS_OK) { + if (WMA_DEFAULT_HW_MODE_INDEX == wma->new_hw_mode_index) { + wma->new_hw_mode_index = wmi_event->cfgd_hw_mode_index; + } else { + wma->old_hw_mode_index = wma->new_hw_mode_index; + wma->new_hw_mode_index = wmi_event->cfgd_hw_mode_index; + } + } + + WMA_LOGI("%s: Updated: old_hw_mode_index:%d new_hw_mode_index:%d", + __func__, wma->old_hw_mode_index, wma->new_hw_mode_index); + + wma_send_msg(wma, SIR_HAL_SOC_SET_HW_MODE_RESP, + (void *) hw_mode_resp, 0); + + return CDF_STATUS_SUCCESS; + +fail: + WMA_LOGE("%s: Sending fail response to LIM", __func__); + hw_mode_resp->status = SET_HW_MODE_STATUS_ECANCELED; + hw_mode_resp->cfgd_hw_mode_index = 0; + hw_mode_resp->num_vdev_mac_entries = 0; + wma_send_msg(wma, SIR_HAL_SOC_SET_HW_MODE_RESP, + (void *) hw_mode_resp, 0); + + return CDF_STATUS_E_FAILURE; +} + +/** + * wma_soc_hw_mode_transition_evt_handler() - HW mode transition evt handler + * @handle: WMI handle + * @event: Event recevied from FW + * @len: Length of the event + * + * Event handler for WMI_SOC_HW_MODE_TRANSITION_EVENTID that indicates an + * asynchronous hardware mode transition. This event notifies the host driver + * that firmware independently changed the hardware mode for some reason, such + * as Coex, LFR 3.0, etc + * + * Return: Success on receiving valid params from FW + */ +static int wma_soc_hw_mode_transition_evt_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + uint32_t i; + WMI_SOC_HW_MODE_TRANSITION_EVENTID_param_tlvs *param_buf; + wmi_soc_hw_mode_transition_event_fixed_param *wmi_event; + wmi_soc_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; + struct sir_hw_mode_trans_ind *hw_mode_trans_ind; + tp_wma_handle wma = (tp_wma_handle) handle; + + if (!wma) { + /* This is an async event. So, not sending any event to LIM */ + WMA_LOGE("Invalid WMA handle"); + return CDF_STATUS_E_NULL_VALUE; + } + + param_buf = (WMI_SOC_HW_MODE_TRANSITION_EVENTID_param_tlvs *) event; + if (!param_buf) { + /* This is an async event. So, not sending any event to LIM */ + WMA_LOGE("Invalid WMI_SOC_HW_MODE_TRANSITION_EVENTID event"); + return CDF_STATUS_E_FAILURE; + } + + hw_mode_trans_ind = cdf_mem_malloc(sizeof(*hw_mode_trans_ind)); + if (!hw_mode_trans_ind) { + WMA_LOGI("%s: Memory allocation failed", __func__); + return CDF_STATUS_E_NULL_VALUE; + } + + wmi_event = param_buf->fixed_param; + hw_mode_trans_ind->old_hw_mode_index = wmi_event->old_hw_mode_index; + hw_mode_trans_ind->new_hw_mode_index = wmi_event->new_hw_mode_index; + hw_mode_trans_ind->num_vdev_mac_entries = + wmi_event->num_vdev_mac_entries; + WMA_LOGI("%s: old_hw_mode_index:%d new_hw_mode_index:%d entries=%d", + __func__, wmi_event->old_hw_mode_index, + wmi_event->new_hw_mode_index, wmi_event->num_vdev_mac_entries); + + vdev_mac_entry = + param_buf->wmi_soc_set_hw_mode_response_vdev_mac_mapping; + + /* Store the vdev-mac map in WMA and prepare to send to HDD */ + for (i = 0; i < wmi_event->num_vdev_mac_entries; i++) { + uint32_t vdev_id, mac_id; + vdev_id = vdev_mac_entry[i].vdev_id; + mac_id = vdev_mac_entry[i].mac_id; + + WMA_LOGI("%s: vdev_id:%d mac_id:%d", + __func__, vdev_id, mac_id); + + hw_mode_trans_ind->vdev_mac_map[i].vdev_id = vdev_id; + hw_mode_trans_ind->vdev_mac_map[i].mac_id = mac_id; + wma_update_intf_hw_mode_params(vdev_id, mac_id, + wmi_event->new_hw_mode_index); + } + wma->old_hw_mode_index = wmi_event->old_hw_mode_index; + wma->new_hw_mode_index = wmi_event->new_hw_mode_index; + + WMA_LOGI("%s: Updated: old_hw_mode_index:%d new_hw_mode_index:%d", + __func__, wma->old_hw_mode_index, wma->new_hw_mode_index); + + /* Pass the message to PE */ + wma_send_msg(wma, SIR_HAL_SOC_HW_MODE_TRANS_IND, + (void *) hw_mode_trans_ind, 0); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_soc_set_dual_mode_config_resp_evt_handler() - Dual mode evt handler + * @handle: WMI handle + * @event: Event received from FW + * @len: Length of the event + * + * Notifies the host driver of the completion or failure of a + * WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID command. This event would be returned to + * the host driver once the firmware has completed a reconfiguration of the Scan + * and FW mode configuration. This changes could include entering or leaving a + * dual mac configuration for either scan and/or more permanent firmware mode. + * + * Return: Success on receiving valid params from FW + */ +static int wma_soc_set_dual_mode_config_resp_evt_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID_param_tlvs *param_buf; + wmi_soc_set_dual_mac_config_response_event_fixed_param *wmi_event; + tp_wma_handle wma = (tp_wma_handle) handle; + struct sir_dual_mac_config_resp *dual_mac_cfg_resp; + + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* Since the WMA handle is NULL, we cannot send resp to LIM. + * So, returning from here. + */ + return CDF_STATUS_E_NULL_VALUE; + } + + dual_mac_cfg_resp = cdf_mem_malloc(sizeof(*dual_mac_cfg_resp)); + if (!dual_mac_cfg_resp) { + WMA_LOGE("%s: Memory allocation failed", __func__); + /* Since the mem alloc failed, we cannot send resp to LIM. + * So, returning from here. + */ + return CDF_STATUS_E_NULL_VALUE; + } + + param_buf = (WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID_param_tlvs *) + event; + if (!param_buf) { + WMA_LOGE("%s: Invalid event", __func__); + goto fail; + } + + wmi_event = param_buf->fixed_param; + WMA_LOGI("%s: status:%d", __func__, wmi_event->status); + dual_mac_cfg_resp->status = wmi_event->status; + + if (SET_HW_MODE_STATUS_OK == dual_mac_cfg_resp->status) { + wma->dual_mac_cfg.prev_scan_config = + wma->dual_mac_cfg.cur_scan_config; + wma->dual_mac_cfg.prev_fw_mode_config = + wma->dual_mac_cfg.cur_fw_mode_config; + wma->dual_mac_cfg.cur_scan_config = + wma->dual_mac_cfg.req_scan_config; + wma->dual_mac_cfg.cur_fw_mode_config = + wma->dual_mac_cfg.req_fw_mode_config; + } + + /* Pass the message to PE */ + wma_send_msg(wma, SIR_HAL_SOC_DUAL_MAC_CFG_RESP, + (void *) dual_mac_cfg_resp, 0); + + return CDF_STATUS_SUCCESS; + +fail: + WMA_LOGE("%s: Sending fail response to LIM", __func__); + dual_mac_cfg_resp->status = SET_HW_MODE_STATUS_ECANCELED; + wma_send_msg(wma, SIR_HAL_SOC_DUAL_MAC_CFG_RESP, + (void *) dual_mac_cfg_resp, 0); + + return CDF_STATUS_E_FAILURE; + +} + +/** + * wma_start() - wma start function. + * Intialize event handlers and timers. + * @cds_ctx: cds context + * + * Return: 0 on success, CDF Error on failure + */ +CDF_STATUS wma_start(void *cds_ctx) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tp_wma_handle wma_handle; + int status; + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid handle", __func__); + cdf_status = CDF_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__); + cdf_status = CDF_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__); + cdf_status = CDF_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__); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PDEV_RESUME_EVENTID, + wma_pdev_resume_event_handler); + if (status) { + WMA_LOGP("%s: Failed to register PDEV resume event handler", + __func__); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + +#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"); + cdf_status = CDF_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"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + } +#endif /* FEATURE_WLAN_SCAN_PNO */ + +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + 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_LL_LEGACY_TX_FLOW_CONTROL */ + +#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"); + cdf_status = CDF_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"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } +#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */ + 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"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + status = wma_ocb_register_event_handlers(wma_handle); + if (status) { + WMA_LOGE("Failed to register ocb event handlers"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + cdf_status = CDF_STATUS_SUCCESS; + +#ifdef QCA_WIFI_FTM + /* + * Tx mgmt attach requires TXRX context which is not created + * in FTM mode. So skip the TX mgmt attach. + */ + if (cds_get_conparam() == CDF_FTM_MODE) + goto end; +#endif /* QCA_WIFI_FTM */ + + cdf_status = wma_tx_attach(wma_handle); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: Failed to register tx management", __func__); + goto end; + } + + /* Initialize log completion timeout */ + cdf_status = cdf_mc_timer_init(&wma_handle->log_completion_timer, + CDF_TIMER_TYPE_SW, + wma_log_completion_timeout, + wma_handle); + if (cdf_status != CDF_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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register get_temperature event cb"); + cdf_status = CDF_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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register log flush complete event cb"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + /* Initialize the WMI_SOC_SET_HW_MODE_RESP_EVENTID event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SOC_SET_HW_MODE_RESP_EVENTID, + wma_soc_set_hw_mode_resp_evt_handler); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register set hw mode resp event cb"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + /* Initialize the WMI_SOC_HW_MODE_TRANSITION_EVENTID event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SOC_HW_MODE_TRANSITION_EVENTID, + wma_soc_hw_mode_transition_evt_handler); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register hw mode transition event cb"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + /* Initialize the set dual mac configuration event handler */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID, + wma_soc_set_dual_mode_config_resp_evt_handler); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register hw mode transition event cb"); + cdf_status = CDF_STATUS_E_FAILURE; + goto end; + } + + cdf_status = cdf_event_init(&wma_handle->service_ready_ext_evt); + if (CDF_STATUS_SUCCESS != cdf_status) { + WMA_LOGE("Unable to init service_ready_ext_evt"); + goto end; + } + +end: + WMA_LOGD("%s: Exit", __func__); + return cdf_status; +} + +/** + * wma_stop() - wma stop function. + * cleanup timers and suspend target. + * @cds_ctx: cds context + * @reason: reason for wma_stop. + * + * Return: 0 on success, CDF Error on failure + */ +CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) +{ + tp_wma_handle wma_handle; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + WMA_LOGD("%s: Enter", __func__); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid handle", __func__); + cdf_status = CDF_STATUS_E_INVAL; + goto end; + } +#ifdef QCA_WIFI_FTM + /* + * Tx mgmt detach requires TXRX context which is not created + * in FTM mode. So skip the TX mgmt detach. + */ + if (cds_get_conparam() == CDF_FTM_MODE) { + cdf_status = CDF_STATUS_SUCCESS; + goto end; + } +#endif /* QCA_WIFI_FTM */ + + if (wma_handle->ack_work_ctx) { + cds_flush_work(&wma_handle->ack_work_ctx->ack_cmp_work); + cdf_mem_free(wma_handle->ack_work_ctx); + wma_handle->ack_work_ctx = NULL; + } + + /* Destroy the timer for log completion */ + cdf_status = cdf_mc_timer_destroy(&wma_handle->log_completion_timer); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to destroy the log completion timer"); + } + + /* There's no need suspend target which is already down during SSR. */ + if (!cds_is_logp_in_progress()) { +#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 /* HIF_USB */ + } + + cdf_status = wma_tx_detach(wma_handle); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: Failed to deregister tx management", __func__); + goto end; + } + + cdf_status = cdf_event_destroy(&wma_handle->service_ready_ext_evt); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to destroy service_ready_ext_evt"); + goto end; + } + +end: + WMA_LOGD("%s: Exit", __func__); + return cdf_status; +} + +/** + * wma_cleanup_hold_req() - cleanup hold request queue + * @wma: wma handle + * + * Return: none + */ +static void wma_cleanup_hold_req(tp_wma_handle wma) +{ + struct wma_target_req *req_msg = NULL; + cdf_list_node_t *node1 = NULL, *node2 = NULL; + CDF_STATUS status; + + cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); + if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->wma_hold_req_queue, + &node2)) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGI(FL("request queue maybe empty")); + return; + } + + do { + node1 = node2; + req_msg = (struct wma_target_req *)node1; + status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("Failed to remove request for vdev_id %d type %d"), + req_msg->vdev_id, req_msg->type); + return; + } else { + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + } + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&wma->wma_hold_req_queue, node1, + &node2)); + + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); +} + +/** + * wma_cleanup_vdev_resp() - cleanup vdev response queue + * @wma: wma handle + * + * Return: none + */ +static void wma_cleanup_vdev_resp(tp_wma_handle wma) +{ + struct wma_target_req *msg, *tmp; + + cdf_spin_lock_bh(&wma->vdev_respq_lock); + list_for_each_entry_safe(msg, tmp, &wma->vdev_resp_queue, node) { + list_del(&msg->node); + cdf_mc_timer_destroy(&msg->event_timeout); + cdf_mem_free(msg); + } + cdf_spin_unlock_bh(&wma->vdev_respq_lock); +} + +/** + * wma_wmi_service_close() - close wma wmi service interface. + * @cds_ctx: cds context + * + * Return: 0 on success, CDF Error on failure + */ +CDF_STATUS wma_wmi_service_close(void *cds_ctx) +{ + tp_wma_handle wma_handle; + struct beacon_info *bcn; + int i; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return CDF_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) + cdf_nbuf_unmap_single(wma_handle->cdf_dev, + bcn->buf, CDF_DMA_TO_DEVICE); + cdf_nbuf_free(bcn->buf); + cdf_mem_free(bcn); + wma_handle->interfaces[i].beacon = NULL; + } + + if (wma_handle->interfaces[i].handle) { + cdf_mem_free(wma_handle->interfaces[i].handle); + wma_handle->interfaces[i].handle = NULL; + } + } + + cdf_mem_free(wma_handle->interfaces); + /* free the wma_handle */ + cds_free_context(wma_handle->cds_context, CDF_MODULE_ID_WMA, + wma_handle); + + cdf_mem_free(((p_cds_contextType) cds_ctx)->cfg_ctx); + WMA_LOGD("%s: Exit", __func__); + return CDF_STATUS_SUCCESS; +} + + + +/** + * wma_close() - wma close function. + * cleanup resources attached with wma. + * @cds_ctx: cds context + * + * Return: 0 on success, CDF Error on failure + */ +CDF_STATUS wma_close(void *cds_ctx) +{ + tp_wma_handle wma_handle; + uint32_t idx; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGP("%s: Invalid wmi handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* Free DBS list */ + if (wma_handle->hw_mode.hw_mode_list) { + cdf_mem_free(wma_handle->hw_mode.hw_mode_list); + wma_handle->hw_mode.hw_mode_list = NULL; + WMA_LOGI("%s: DBS list is freed", __func__); + } + + if (wma_handle->events_logs_list) { + cdf_mem_free(wma_handle->events_logs_list); + wma_handle->events_logs_list = NULL; + WMA_LOGD("%s: Event log list freed", __func__); + } + + if (wma_handle->saved_wmi_init_cmd.buf) { + wmi_buf_free(wma_handle->saved_wmi_init_cmd.buf); + wma_handle->saved_wmi_init_cmd.buf = NULL; + } + + if (cds_get_conparam() != CDF_FTM_MODE) { +#ifdef FEATURE_WLAN_SCAN_PNO + cdf_wake_lock_destroy(&wma_handle->pno_wake_lock); +#endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef FEATURE_WLAN_EXTSCAN + cdf_wake_lock_destroy(&wma_handle->extscan_wake_lock); +#endif /* FEATURE_WLAN_EXTSCAN */ + cdf_wake_lock_destroy(&wma_handle->wow_wake_lock); + } + + /* unregister Firmware debug log */ + cdf_status = dbglog_deinit(wma_handle->wmi_handle); + if (cdf_status != CDF_STATUS_SUCCESS) + WMA_LOGP("%s: dbglog_deinit failed", __func__); + + /* close the cdf events */ + cdf_event_destroy(&wma_handle->wma_ready_event); + cdf_event_destroy(&wma_handle->target_suspend); + cdf_event_destroy(&wma_handle->wma_resume_event); + cdf_event_destroy(&wma_handle->recovery_event); + wma_cleanup_vdev_resp(wma_handle); + wma_cleanup_hold_req(wma_handle); + for (idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { + cdf_os_mem_free_consistent(wma_handle->cdf_dev, + wma_handle->mem_chunks[idx].len, + wma_handle->mem_chunks[idx].vaddr, + wma_handle->mem_chunks[idx].paddr, + cdf_get_dma_mem_context( + (&(wma_handle->mem_chunks[idx])), + memctx)); + } + +#if defined(QCA_WIFI_FTM) + /* Detach UTF and unregister the handler */ + if (cds_get_conparam() == CDF_FTM_MODE) + wma_utf_detach(wma_handle); +#endif /* QCA_WIFI_FTM */ + + if (NULL != wma_handle->dfs_ic) { + wma_dfs_detach(wma_handle->dfs_ic); + wma_handle->dfs_ic = NULL; + } + + if (NULL != wma_handle->pGetRssiReq) { + cdf_mem_free(wma_handle->pGetRssiReq); + wma_handle->pGetRssiReq = NULL; + } + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_MGMT_TX_WMI)) { + wmi_desc_pool_deinit(wma_handle); + } + + WMA_LOGD("%s: Exit", __func__); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_update_fw_config() - update fw configuration + * @wma_handle: wma handle + * @tgt_cap: target capabality + * + * Return: none + */ +static void 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 = + CDF_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; +} + +/** + * wma_alloc_host_mem_chunk() - allocate host memory + * @wma_handle: wma handle + * @req_id: request id + * @idx: index + * @num_units: number of units + * @unit_len: unit length + * + * allocate a chunk of memory at the index indicated and + * if allocation fail allocate smallest size possiblr and + * return number of units allocated. + * + * Return: number of units or 0 for error. + */ +static uint32_t wma_alloc_host_mem_chunk(tp_wma_handle wma_handle, + uint32_t req_id, uint32_t idx, + uint32_t num_units, uint32_t unit_len) +{ + cdf_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 = + cdf_os_mem_alloc_consistent(wma_handle->cdf_dev, + num_units * unit_len, &paddr, + cdf_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 +/** + * wma_alloc_host_mem() - allocate amount of memory requested by FW. + * @wma_handle: wma handle + * @req_id: request id + * @num_units: number of units + * @unit_len: unit length + * + * Return: none + */ +static void wma_alloc_host_mem(tp_wma_handle wma_handle, uint32_t req_id, + uint32_t num_units, uint32_t unit_len) +{ + uint32_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; +} + +/** + * wma_update_target_services() - update target services from wma handle + * @wh: wma handle + * @cfg: target services + * + * Return: none + */ +static inline void wma_update_target_services(tp_wma_handle wh, + struct wma_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) + g_fw_wlan_feat_caps |= (1 << DOT11AC); + + /* Proactive ARP response */ + g_fw_wlan_feat_caps |= (1 << WLAN_PERIODIC_TX_PTRN); + + /* Enable WOW */ + g_fw_wlan_feat_caps |= (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 /* FEATURE_WLAN_SCAN_PNO */ + +#ifdef FEATURE_WLAN_EXTSCAN + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_EXTSCAN)) { + g_fw_wlan_feat_caps |= (1 << EXTENDED_SCAN); + } +#endif /* FEATURE_WLAN_EXTSCAN */ + cfg->lte_coex_ant_share = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_LTE_ANT_SHARE_SUPPORT); +#ifdef FEATURE_WLAN_TDLS + /* Enable TDLS */ + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_TDLS)) { + cfg->en_tdls = 1; + g_fw_wlan_feat_caps |= (1 << TDLS); + } + /* Enable advanced TDLS features */ + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, + WMI_SERVICE_TDLS_OFFCHAN)) { + cfg->en_tdls_offchan = 1; + g_fw_wlan_feat_caps |= (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 /* FEATURE_WLAN_TDLS */ + 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 /* WLAN_FEATURE_ROAM_OFFLOAD */ +#ifdef WLAN_FEATURE_NAN + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_NAN)) + g_fw_wlan_feat_caps |= (1 << NAN); +#endif /* WLAN_FEATURE_NAN */ + + if (WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, WMI_SERVICE_RTT)) + g_fw_wlan_feat_caps |= (1 << RTT); +} + +/** + * wma_update_target_ht_cap() - update ht capabality from wma handle + * @wh: wma handle + * @cfg: ht capabality + * + * Return: none + */ +static inline void wma_update_target_ht_cap(tp_wma_handle wh, + struct wma_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\n\ + mpdu_density - %d ht_rx_ldpc - %d ht_sgi_20 - %d\n\ + 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 +/** + * wma_update_target_vht_cap() - update vht capabality from wma handle + * @wh: wma handle + * @cfg: vht capabality + * + * Return: none + */ +static inline void wma_update_target_vht_cap(tp_wma_handle wh, + struct wma_tgt_vht_cap *cfg) +{ + + if (wh->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_11454) + cfg->vht_max_mpdu = WMI_VHT_CAP_MAX_MPDU_LEN_11454; + else if (wh->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_7935) + cfg->vht_max_mpdu = WMI_VHT_CAP_MAX_MPDU_LEN_7935; + else + cfg->vht_max_mpdu = 0; + + + if (wh->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ) { + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_80P80MHZ; + cfg->supp_chan_width |= 1 << eHT_CHANNEL_WIDTH_160MHZ; + } else if (wh->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ) + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_160MHZ; + else + cfg->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_80MHZ; + + cfg->vht_rx_ldpc = wh->vht_cap_info & WMI_VHT_CAP_RX_LDPC; + + cfg->vht_short_gi_80 = wh->vht_cap_info & WMI_VHT_CAP_SGI_80MHZ; + cfg->vht_short_gi_160 = wh->vht_cap_info & WMI_VHT_CAP_SGI_160MHZ; + + cfg->vht_tx_stbc = wh->vht_cap_info & WMI_VHT_CAP_TX_STBC; + + cfg->vht_rx_stbc = (wh->vht_cap_info & WMI_VHT_CAP_RX_STBC_1SS) | + (wh->vht_cap_info & WMI_VHT_CAP_RX_STBC_2SS) | + (wh->vht_cap_info & WMI_VHT_CAP_RX_STBC_3SS) ; + + cfg->vht_max_ampdu_len_exp = (wh->vht_cap_info & + WMI_VHT_CAP_MAX_AMPDU_LEN_EXP) + >> WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT; + + cfg->vht_su_bformer = wh->vht_cap_info & WMI_VHT_CAP_SU_BFORMER; + + cfg->vht_su_bformee = wh->vht_cap_info & WMI_VHT_CAP_SU_BFORMEE; + + cfg->vht_mu_bformer = wh->vht_cap_info & WMI_VHT_CAP_MU_BFORMER; + + cfg->vht_mu_bformee = wh->vht_cap_info & WMI_VHT_CAP_MU_BFORMEE; + + cfg->vht_txop_ps = wh->vht_cap_info & WMI_VHT_CAP_TXOP_PS; + + WMA_LOGD(" %s: max_mpdu %d supp_chan_width %x rx_ldpc %x\n \ + short_gi_80 %x tx_stbc %x rx_stbc %x txop_ps %x\n \ + 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 */ + +/** + * wma_update_hdd_cfg() - update HDD config + * @wma_handle: wma handle + * + * Return: none + */ +static void wma_update_hdd_cfg(tp_wma_handle wma_handle) +{ + struct wma_tgt_cfg tgt_cfg; + void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + + tgt_cfg.reg_domain = wma_handle->reg_cap.eeprom_rd; + 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: + tgt_cfg.band_cap = eCSR_BAND_24; + break; + case WMI_11A_CAPABILITY: + case WMI_11NA_CAPABILITY: + case WMI_11AC_CAPABILITY: + tgt_cfg.band_cap = eCSR_BAND_5G; + break; + case WMI_11AG_CAPABILITY: + case WMI_11NAG_CAPABILITY: + default: + tgt_cfg.band_cap = eCSR_BAND_ALL; + } + + tgt_cfg.max_intf_count = wma_handle->wlan_resource_config.num_vdevs; + + cdf_mem_copy(tgt_cfg.hw_macaddr.bytes, wma_handle->hwaddr, + ATH_MAC_LEN); + + wma_update_target_services(wma_handle, &tgt_cfg.services); + wma_update_target_ht_cap(wma_handle, &tgt_cfg.ht_cap); +#ifdef WLAN_FEATURE_11AC + wma_update_target_vht_cap(wma_handle, &tgt_cfg.vht_cap); +#endif /* #ifdef WLAN_FEATURE_11AC */ + + tgt_cfg.target_fw_version = wma_handle->target_fw_version; +#ifdef WLAN_FEATURE_LPSS + tgt_cfg.lpss_support = wma_handle->lpss_support; +#endif /* WLAN_FEATURE_LPSS */ + tgt_cfg.ap_arpns_support = wma_handle->ap_arpns_support; + wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg); +} + +/** + * wma_setup_wmi_init_msg() - fill wmi init message buffer + * @wma_handle: wma handle + * @ev: ready event fixed params + * @param_buf: redy event TLVs + * @len: buffer length + * + * Return: wmi buffer or NULL for error + */ +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, + uint32_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; + uint8_t *buf_ptr; + wmi_resource_config *resource_cfg; + wlan_host_memory_chunk *host_mem_chunks; + uint32_t mem_chunk_len = 0; + uint16_t idx; + uint32_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 = (uint8_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) { + CDF_ASSERT(0); + cdf_nbuf_free(buf); + return NULL; + } + + cmd->num_host_mem_chunks = 0; + for (idx = 0; idx < ev->num_mem_reqs; ++idx) { + num_units = ev_mem_reqs[idx].num_units; + if (ev_mem_reqs[idx].num_unit_info & NUM_UNITS_IS_NUM_PEERS) { + /* + * number of units to allocate is number + * of peers, 1 extra for self peer on + * target. this needs to be fied, host + * and target can get out of sync + */ + num_units = resource_cfg->num_peers + 1; + } + WMA_LOGD + ("idx %d req %d num_units %d num_unit_info %d unit size %d actual units %d ", + idx, ev_mem_reqs[idx].req_id, + ev_mem_reqs[idx].num_units, + ev_mem_reqs[idx].num_unit_info, + ev_mem_reqs[idx].unit_size, num_units); + wma_alloc_host_mem(wma_handle, ev_mem_reqs[idx].req_id, + num_units, ev_mem_reqs[idx].unit_size); + } + for (idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { + WMITLV_SET_HDR(&(host_mem_chunks[idx].tlv_header), + WMITLV_TAG_STRUC_wlan_host_memory_chunk, + WMITLV_GET_STRUCT_TLVLEN + (wlan_host_memory_chunk)); + host_mem_chunks[idx].ptr = wma_handle->mem_chunks[idx].paddr; + host_mem_chunks[idx].size = wma_handle->mem_chunks[idx].len; + host_mem_chunks[idx].req_id = + wma_handle->mem_chunks[idx].req_id; + WMA_LOGD("chunk %d len %d requested ,ptr 0x%x ", + idx, host_mem_chunks[idx].size, + host_mem_chunks[idx].ptr); + } + cmd->num_host_mem_chunks = wma_handle->num_mem_chunks; + len += (wma_handle->num_mem_chunks * sizeof(wlan_host_memory_chunk)); + WMITLV_SET_HDR((buf_ptr + sizeof(*cmd) + sizeof(wmi_resource_config)), + WMITLV_TAG_ARRAY_STRUC, + (sizeof(wlan_host_memory_chunk) * + wma_handle->num_mem_chunks)); + cdf_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); + + cdf_mem_copy(&wma_handle->final_abi_vers, &cmd->host_abi_vers, + sizeof(wmi_abi_version)); + return buf; +} + +/** + * wma_dump_dbs_hw_mode() - Print the DBS HW modes + * @wma_handle: WMA handle + * + * Prints the DBS HW modes sent by the FW as part + * of WMI ready event + * + * Return: None + */ +void wma_dump_dbs_hw_mode(tp_wma_handle wma_handle) +{ + uint32_t i, param; + + if (!wma_handle) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return; + } + + for (i = 0; i < wma_handle->num_dbs_hw_modes; i++) { + param = wma_handle->hw_mode.hw_mode_list[i]; + WMA_LOGA("%s:[%d]-MAC0: tx_ss:%d rx_ss:%d bw_idx:%d", + __func__, i, + WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param), + WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param), + WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(param)); + WMA_LOGA("%s:[%d]-MAC1: tx_ss:%d rx_ss:%d bw_idx:%d", + __func__, i, + WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param), + WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param), + WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(param)); + WMA_LOGA("%s:[%d] DBS:%d Agile DFS:%d", __func__, i, + WMI_DBS_HW_MODE_DBS_MODE_GET(param), + WMI_DBS_HW_MODE_AGILE_DFS_GET(param)); + } +} + +/** + * wma_init_scan_fw_mode_config() - Initialize scan/fw mode config + * @wma_handle: WMA handle + * + * Enables all the valid bits of concurrent_scan_config_bits and + * fw_mode_config_bits. + * + * Return: None + */ +void wma_init_scan_fw_mode_config(tp_wma_handle wma_handle) +{ + tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE); + + WMA_LOGD("%s: Enter", __func__); + + if (!mac) { + WMA_LOGE("%s: Invalid mac handle", __func__); + return; + } + + if (!wma_handle) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return; + } + + wma_handle->dual_mac_cfg.cur_scan_config = 0; + wma_handle->dual_mac_cfg.cur_fw_mode_config = 0; + + /* If dual mac features are disabled in the INI, we + * need not proceed further + */ + if (mac->dual_mac_feature_disable) { + WMA_LOGE("%s: Disabling dual mac capabilities", __func__); + /* All capabilites are initialized to 0. We can return */ + goto done; + } + + /* The input from FW team is that, by default all the + * bits of concurrent_scan_config_bits and + * FW_mode_config_bits will be enabled. So, + * enabling all the bits here. Adding this API so that + * in the future/variant chipsets, when not all bits are + * enabled, FW can send the initial configuration of the above + * two parameters using the service ready event and they + * can be initialized here. + */ + /* Initialize concurrent_scan_config_bits */ + WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET( + wma_handle->dual_mac_cfg.cur_scan_config, 1); + WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET( + wma_handle->dual_mac_cfg.cur_scan_config, 1); + WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET( + wma_handle->dual_mac_cfg.cur_scan_config, 1); + + /* Initialize FW_mode_config_bits */ + WMI_DBS_FW_MODE_CFG_DBS_SET( + wma_handle->dual_mac_cfg.cur_fw_mode_config, 1); + WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET( + wma_handle->dual_mac_cfg.cur_fw_mode_config, 1); +done: + /* Initialize the previous scan/fw mode config */ + wma_handle->dual_mac_cfg.prev_scan_config = + wma_handle->dual_mac_cfg.cur_scan_config; + wma_handle->dual_mac_cfg.prev_fw_mode_config = + wma_handle->dual_mac_cfg.cur_fw_mode_config; + + WMA_LOGD("%s: cur_scan_config:%x cur_fw_mode_config:%x", + __func__, + wma_handle->dual_mac_cfg.cur_scan_config, + wma_handle->dual_mac_cfg.cur_fw_mode_config); +} + +/** + * wma_rx_service_ready_event() - event handler to process + * wmi rx sevice ready event. + * @handle: wma handle + * @cmd_param_info: command params info + * + * Return: none + */ +void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) +{ + wmi_buf_t buf; + uint32_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; + uint32_t *ev_wlan_dbs_hw_mode_list; + + 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->num_dbs_hw_modes = ev->num_dbs_hw_modes; + ev_wlan_dbs_hw_mode_list = param_buf->wlan_dbs_hw_mode_list; + wma_handle->hw_mode.hw_mode_list = + cdf_mem_malloc(sizeof(*wma_handle->hw_mode.hw_mode_list) * + wma_handle->num_dbs_hw_modes); + if (!wma_handle->hw_mode.hw_mode_list) { + WMA_LOGE("%s: Memory allocation failed for DBS", __func__); + /* Continuing with the rest of the processing */ + } + cdf_mem_copy(wma_handle->hw_mode.hw_mode_list, + ev_wlan_dbs_hw_mode_list, + (sizeof(*wma_handle->hw_mode.hw_mode_list) * + wma_handle->num_dbs_hw_modes)); + + wma_dump_dbs_hw_mode(wma_handle); + + wma_init_scan_fw_mode_config(wma_handle); + + 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; + cdf_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 /* WLAN_FEATURE_11AC */ + wma_handle->num_rf_chains = ev->num_rf_chains; + + wma_handle->target_fw_version = ev->fw_build_vers; + ol_tx_set_desc_global_pool_size(ev->num_msdu_desc); + wma_handle->new_hw_mode_index = ev->default_dbs_hw_mode_index; + + WMA_LOGD("%s: Firmware default hw mode index : %d", + __func__, ev->default_dbs_hw_mode_index); + 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; + cdf_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; + cdf_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 */ + cdf_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 /* WLAN_FEATURE_LPSS */ + + /* + * This Service bit is added to check for ARP/NS Offload + * support for LL/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; + } + } + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_MGMT_TX_WMI)) { + WMA_LOGE("Firmware supports management TX over WMI,use WMI interface instead of HTT for management Tx"); + status = wmi_desc_pool_init(wma_handle, WMI_DESC_POOL_MAX); + if (status) { + WMA_LOGE("Failed to initialize wmi descriptor pool"); + return; + } + /* + * Register Tx completion event handler for MGMT Tx over WMI + * case + */ + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_MGMT_TX_COMPLETION_EVENTID, + wma_mgmt_tx_completion_handler); + if (status) { + WMA_LOGE("Failed to register MGMT over WMI completion handler"); + return; + } + + } else { + WMA_LOGE("FW doesnot support WMI_SERVICE_MGMT_TX_WMI, Use HTT interface for Management Tx"); + } +#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 /* WLAN_FEATURE_GTK_OFFLOAD */ + + 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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to register log supported event cb"); + return; + } + + cdf_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); + cdf_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; + } +} + +/** + * wma_rx_service_ready_ext_event() - evt handler for sevice ready ext event. + * @handle: wma handle + * @event: params of the service ready extended event + * + * Return: none + */ +void wma_rx_service_ready_ext_event(WMA_HANDLE handle, void *event) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_SERVICE_READY_EXT_EVENTID_param_tlvs *param_buf; + wmi_service_ready_ext_event_fixed_param *ev; + int status; + CDF_STATUS ret; + + WMA_LOGD("%s: Enter", __func__); + + if (!wma_handle) { + WMA_LOGP("%s: Invalid WMA handle", __func__); + return; + } + + param_buf = (WMI_SERVICE_READY_EXT_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGP("%s: Invalid event", __func__); + return; + } + + ev = param_buf->fixed_param; + if (!ev) { + WMA_LOGP("%s: Invalid buffer", __func__); + return; + } + + WMA_LOGA("WMA <-- WMI_SERVICE_READY_EXT_EVENTID"); + + if (!wma_handle->saved_wmi_init_cmd.buf) { + WMA_LOGP("Service ready ext event w/o WMI_SERVICE_EXT_MSG!"); + return; + } + + ret = cdf_event_set(&wma_handle->service_ready_ext_evt); + if (CDF_STATUS_SUCCESS != ret) { + WMA_LOGP("Failed to set service_ready_ext_evt"); + return; + } + + WMA_LOGA("WMA --> WMI_INIT_CMDID"); + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, + wma_handle->saved_wmi_init_cmd.buf, + wma_handle->saved_wmi_init_cmd.buf_len, + WMI_INIT_CMDID); + if (status != EOK) { + /* In success case, WMI layer will free after getting copy + * engine TX complete interrupt + */ + WMA_LOGE("Failed to send WMI_INIT_CMDID command"); + wmi_buf_free(wma_handle->saved_wmi_init_cmd.buf); + } + wma_handle->saved_wmi_init_cmd.buf = NULL; + +} + +/** + * wma_rx_ready_event() - event handler to process + * wmi rx ready event. + * @handle: wma handle + * @cmd_param_info: command params info + * + * Return: none + */ +void 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__); + CDF_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; + } + } + cdf_mem_copy(&wma_handle->final_abi_vers, &ev->fw_abi_vers, + sizeof(wmi_abi_version)); + cdf_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); + + cdf_event_set(&wma_handle->wma_ready_event); + + WMA_LOGD("Exit"); +} + +/** + * wma_setneedshutdown() - setting wma needshutdown flag + * @cds_ctx: cds context + * + * Return: none + */ +void wma_setneedshutdown(void *cds_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid arguments", __func__); + CDF_ASSERT(0); + return; + } + + wma_handle->needShutdown = true; + WMA_LOGD("%s: Exit", __func__); +} + +/** + * wma_needshutdown() - Is wma needs shutdown? + * @cds_ctx: cds context + * + * Return: returns true/false + */ +bool wma_needshutdown(void *cds_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma_handle) { + WMA_LOGP("%s: Invalid arguments", __func__); + CDF_ASSERT(0); + return false; + } + + WMA_LOGD("%s: Exit", __func__); + return wma_handle->needShutdown; +} + +/** + * wma_wait_for_ready_event() - wait for wma ready event + * @handle: wma handle + * + * Return: 0 for success or CDF error + */ +CDF_STATUS wma_wait_for_ready_event(WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + CDF_STATUS cdf_status; + + /* wait until WMI_READY_EVENTID received from FW */ + cdf_status = cdf_wait_single_event(&(wma_handle->wma_ready_event), + WMA_READY_EVENTID_TIMEOUT); + + if (CDF_STATUS_SUCCESS != cdf_status) { + WMA_LOGP("%s: Timeout waiting for ready event from FW", + __func__); + cdf_status = CDF_STATUS_E_FAILURE; + } + return cdf_status; +} + +/** + * wma_set_ppsconfig() - set pps config in fw + * @vdev_id: vdev id + * @pps_param: pps params + * @val : param value + * + * Return: 0 for success or CDF error + */ +CDF_STATUS wma_set_ppsconfig(uint8_t vdev_id, uint16_t pps_param, + int val) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + int ret = -EIO; + uint32_t pps_val; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return CDF_STATUS_E_INVAL; + } + + 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 /* NOT_YET */ +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) ? CDF_STATUS_E_FAILURE : CDF_STATUS_SUCCESS; +} + +/** + * 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: CDF_SUCCESS for success otherwise failure + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + + val = (*mas_val); + + if (CDF_STATUS_SUCCESS != + wma_set_enable_disable_mcc_adaptive_scheduler(val)) { + WMA_LOGE("%s: Unable to enable/disable MAS", __func__); + return CDF_STATUS_E_FAILURE; + } else { + WMA_LOGE("%s: Value is %d", __func__, val); + } + + return CDF_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: CDF_SUCCESS for success otherwise failure + * + */ +CDF_STATUS wma_process_set_miracast(tp_wma_handle wma, uint32_t *miracast_val) +{ + if (NULL == wma || NULL == miracast_val) { + WMA_LOGE("%s: Invalid input to store miracast value", __func__); + return CDF_STATUS_E_FAILURE; + } + + wma->miracast_value = *miracast_val; + WMA_LOGE("%s: Miracast value is %d", __func__, wma->miracast_value); + + return CDF_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: CDF_STATUS_SUCCESS for success otherwise failure + * + */ +static CDF_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 CDF_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: CDF_STATUS_SUCCESS for success otherwise failure + * + */ +static CDF_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 CDF_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; +} + +/** + * 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) +{ + 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; + } + + scn = cds_get_context(CDF_MODULE_ID_HIF); + + 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) +{ + CDF_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 = cdf_mc_timer_start(&wma_handle->log_completion_timer, + WMA_LOG_COMPLETION_TIMER); + if (status != CDF_STATUS_SUCCESS) + WMA_LOGE("Failed to start the log completion timer"); +} + +/** + * wma_mc_process_msg() - process wma messages and call appropriate function. + * @cds_context: cds context + * @msg: message + * + * Return: CDF_SUCCESS for success otherwise failure + */ +CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tp_wma_handle wma_handle; + ol_txrx_vdev_handle txrx_vdev_handle = NULL; + extern uint8_t *mac_trace_get_wma_msg_string(uint16_t wmaMsg); + + WMA_LOGI("%s: Enter", __func__); + if (NULL == msg) { + WMA_LOGE("msg is NULL"); + CDF_ASSERT(0); + cdf_status = CDF_STATUS_E_INVAL; + goto end; + } + + WMA_LOGD("msg->type = %x %s", msg->type, + mac_trace_get_wma_msg_string(msg->type)); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma_handle) { + WMA_LOGP("%s: wma_handle is NULL", __func__); + CDF_ASSERT(0); + cdf_mem_free(msg->bodyptr); + cdf_status = CDF_STATUS_E_INVAL; + goto end; + } + + switch (msg->type) { + + /* Message posted by wmi for all control path related + * FW events to serialize through mc_thread. + */ + case WMA_PROCESS_FW_EVENT: + wma_process_fw_event(wma_handle, + (wma_process_fw_event_params *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + +#ifdef FEATURE_WLAN_ESE + case WMA_TSM_STATS_REQ: + WMA_LOGA("McThread: WMA_TSM_STATS_REQ"); + wma_process_tsm_stats_req(wma_handle, (void *)msg->bodyptr); + break; +#endif /* FEATURE_WLAN_ESE */ + case WNI_CFG_DNLD_REQ: + WMA_LOGA("McThread: WNI_CFG_DNLD_REQ"); + cdf_status = wma_wni_cfg_dnld(wma_handle); + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + cds_wma_complete_cback(cds_context); + } else { + WMA_LOGD("config download failure"); + } + break; + case WMA_ADD_STA_SELF_REQ: + txrx_vdev_handle = + wma_vdev_attach(wma_handle, + (struct add_sta_self_params *) msg-> + bodyptr, 1); + if (!txrx_vdev_handle) { + WMA_LOGE("Failed to attach vdev"); + } else { + /* Register with TxRx Module for Data Ack Complete Cb */ + ol_txrx_data_tx_cb_set(txrx_vdev_handle, + wma_data_tx_ack_comp_hdlr, + wma_handle); + } + break; + case WMA_DEL_STA_SELF_REQ: + wma_vdev_detach(wma_handle, + (struct del_sta_self_params *) msg->bodyptr, 1); + break; + case WMA_START_SCAN_OFFLOAD_REQ: + wma_start_scan(wma_handle, msg->bodyptr, msg->type); + cdf_mem_free(msg->bodyptr); + break; + case WMA_STOP_SCAN_OFFLOAD_REQ: + wma_stop_scan(wma_handle, msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_UPDATE_CHAN_LIST_REQ: + wma_update_channel_list(wma_handle, + (tSirUpdateChanList *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_LINK_STATE: + wma_set_linkstate(wma_handle, (tpLinkStateParams) msg->bodyptr); + break; + case WMA_CHNL_SWITCH_REQ: + wma_set_channel(wma_handle, + (tpSwitchChannelParams) msg->bodyptr); + break; + case WMA_ADD_BSS_REQ: + wma_add_bss(wma_handle, (tpAddBssParams) msg->bodyptr); + break; + case WMA_ADD_STA_REQ: + wma_add_sta(wma_handle, (tpAddStaParams) msg->bodyptr); + break; + case WMA_SET_BSSKEY_REQ: + wma_set_bsskey(wma_handle, (tpSetBssKeyParams) msg->bodyptr); + break; + case WMA_SET_STAKEY_REQ: + wma_set_stakey(wma_handle, (tpSetStaKeyParams) msg->bodyptr); + break; + case WMA_DELETE_STA_REQ: + wma_delete_sta(wma_handle, (tpDeleteStaParams) msg->bodyptr); + break; + case WMA_DELETE_BSS_REQ: + wma_delete_bss(wma_handle, (tpDeleteBssParams) msg->bodyptr); + break; + case WMA_UPDATE_EDCA_PROFILE_IND: + wma_process_update_edca_param_req(wma_handle, + (tEdcaParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SEND_BEACON_REQ: + wma_send_beacon(wma_handle, (tpSendbeaconParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SEND_PROBE_RSP_TMPL: + wma_send_probe_rsp_tmpl(wma_handle, + (tpSendProbeRespParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_CLI_SET_CMD: + wma_process_cli_set_cmd(wma_handle, + (wma_cli_set_cmd_t *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#if !defined(REMOVE_PKT_LOG) + case WMA_PKTLOG_ENABLE_REQ: + wma_pktlog_wmi_send_cmd(wma_handle, + (struct ath_pktlog_wmi_params *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* REMOVE_PKT_LOG */ +#if defined(QCA_WIFI_FTM) + case WMA_FTM_CMD_REQ: + wma_process_ftm_command(wma_handle, + (struct ar6k_testmode_cmd_data *)msg->bodyptr); + break; +#endif /* QCA_WIFI_FTM */ + case WMA_ENTER_PS_REQ: + wma_enable_sta_ps_mode(wma_handle, + (tpEnablePsParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXIT_PS_REQ: + wma_disable_sta_ps_mode(wma_handle, + (tpDisablePsParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_ENABLE_UAPSD_REQ: + wma_enable_uapsd_mode(wma_handle, + (tpEnableUapsdParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_DISABLE_UAPSD_REQ: + wma_disable_uapsd_mode(wma_handle, + (tpDisableUapsdParams) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_TX_POWER_REQ: + wma_set_tx_power(wma_handle, (tpMaxTxPowerParams) msg->bodyptr); + break; + case WMA_SET_MAX_TX_POWER_REQ: + wma_set_max_tx_power(wma_handle, + (tpMaxTxPowerParams) msg->bodyptr); + break; + case WMA_SET_KEEP_ALIVE: + wma_set_keepalive_req(wma_handle, + (tSirKeepAliveReq *) msg->bodyptr); + break; +#ifdef FEATURE_WLAN_SCAN_PNO + case WMA_SET_PNO_REQ: + wma_config_pno(wma_handle, (tpSirPNOScanReq) msg->bodyptr); + break; + + case WMA_SME_SCAN_CACHE_UPDATED: + wma_scan_cache_updated_ind(wma_handle, msg->bodyval); + break; +#endif /* FEATURE_WLAN_SCAN_PNO */ +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + case WMA_SET_PLM_REQ: + wma_config_plm(wma_handle, (tpSirPlmReq) msg->bodyptr); + break; +#endif + case WMA_GET_STATISTICS_REQ: + wma_get_stats_req(wma_handle, + (tAniGetPEStatsReq *) msg->bodyptr); + break; + + case WMA_CONFIG_PARAM_UPDATE_REQ: + wma_update_cfg_params(wma_handle, (tSirMsgQ *) msg); + break; + + case WMA_UPDATE_OP_MODE: + wma_process_update_opmode(wma_handle, + (tUpdateVHTOpMode *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_UPDATE_RX_NSS: + wma_process_update_rx_nss(wma_handle, + (tUpdateRxNss *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_11AC + case WMA_UPDATE_MEMBERSHIP: + wma_process_update_membership(wma_handle, + (tUpdateMembership *) msg->bodyptr); + break; + case WMA_UPDATE_USERPOS: + wma_process_update_userpos(wma_handle, + (tUpdateUserPos *) msg->bodyptr); + break; +#endif /* WLAN_FEATURE_11AC */ + case WMA_UPDATE_BEACON_IND: + wma_process_update_beacon_params(wma_handle, + (tUpdateBeaconParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + + case WMA_ADD_TS_REQ: + wma_add_ts_req(wma_handle, (tAddTsParams *) msg->bodyptr); + break; + + case WMA_DEL_TS_REQ: + wma_del_ts_req(wma_handle, (tDelTsParams *) msg->bodyptr); + break; + + case WMA_AGGR_QOS_REQ: + wma_aggr_qos_req(wma_handle, (tAggrAddTsParams *) msg->bodyptr); + break; + + case WMA_RECEIVE_FILTER_SET_FILTER_REQ: + wma_process_receive_filter_set_filter_req(wma_handle, + (tSirRcvPktFilterCfgType *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + + case WMA_RECEIVE_FILTER_CLEAR_FILTER_REQ: + wma_process_receive_filter_clear_filter_req(wma_handle, + (tSirRcvFltPktClearParam *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + + case WMA_WOW_ADD_PTRN: + wma_wow_add_pattern(wma_handle, + (struct wow_add_pattern *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_WOW_DEL_PTRN: + wma_wow_delete_user_pattern(wma_handle, + (struct wow_delete_pattern *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_WOWL_ENTER_REQ: + wma_wow_enter(wma_handle, + (tpSirHalWowlEnterParams) msg->bodyptr); + break; + case WMA_WOWL_EXIT_REQ: + wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); + break; + case WMA_WLAN_SUSPEND_IND: + wma_suspend_req(wma_handle, + (tpSirWlanSuspendParam) msg->bodyptr); + break; + case WMA_8023_MULTICAST_LIST_REQ: + wma_process_mcbc_set_filter_req(wma_handle, + (tpSirRcvFltMcAddrList) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_GTK_OFFLOAD + case WMA_GTK_OFFLOAD_REQ: + wma_process_gtk_offload_req(wma_handle, + (tpSirGtkOffloadParams) msg->bodyptr); + break; + + case WMA_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 WMA_START_OEM_DATA_REQ: + wma_start_oem_data_req(wma_handle, + (tStartOemDataReq *) msg->bodyptr); + break; +#endif /* FEATURE_OEM_DATA_SUPPORT */ + case WMA_SET_HOST_OFFLOAD: + wma_enable_arp_ns_offload(wma_handle, + (tpSirHostOffloadReq) msg->bodyptr, + true); + break; +#ifdef WLAN_NS_OFFLOAD + case WMA_SET_NS_OFFLOAD: + wma_enable_arp_ns_offload(wma_handle, + (tpSirHostOffloadReq) msg->bodyptr, + false); + break; +#endif /*WLAN_NS_OFFLOAD */ + case WMA_ROAM_SCAN_OFFLOAD_REQ: + /* + * Main entry point or roaming directives from CSR. + */ + wma_process_roam_scan_req(wma_handle, + (tSirRoamOffloadScanReq *) msg->bodyptr); + break; + + case WMA_RATE_UPDATE_IND: + wma_process_rate_update_indicate(wma_handle, + (tSirRateUpdateInd *) msg->bodyptr); + break; + +#ifdef FEATURE_WLAN_TDLS + case WMA_UPDATE_FW_TDLS_STATE: + wma_update_fw_tdls_state(wma_handle, + (t_wma_tdls_params *) msg->bodyptr); + break; + case WMA_UPDATE_TDLS_PEER_STATE: + wma_update_tdls_peer_state(wma_handle, + (tTdlsPeerStateParams *) msg->bodyptr); + break; + case WMA_TDLS_SET_OFFCHAN_MODE: + wma_set_tdls_offchan_mode(wma_handle, + (tdls_chan_switch_params *)msg->bodyptr); + break; +#endif /* FEATURE_WLAN_TDLS */ + case WMA_ADD_PERIODIC_TX_PTRN_IND: + wma_process_add_periodic_tx_ptrn_ind(wma_handle, + (tSirAddPeriodicTxPtrn *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_DEL_PERIODIC_TX_PTRN_IND: + wma_process_del_periodic_tx_ptrn_ind(wma_handle, + (tSirDelPeriodicTxPtrn *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_TX_POWER_LIMIT: + wma_process_tx_power_limits(wma_handle, + (tSirTxPowerLimit *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#ifdef FEATURE_WLAN_LPHB + case WMA_LPHB_CONF_REQ: + wma_process_lphb_conf_req(wma_handle, + (tSirLPHBReq *) msg->bodyptr); + break; +#endif /* FEATURE_WLAN_LPHB */ + +#ifdef FEATURE_WLAN_CH_AVOID + case WMA_CH_AVOID_UPDATE_REQ: + wma_process_ch_avoid_update_req(wma_handle, + (tSirChAvoidUpdateReq *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* FEATURE_WLAN_CH_AVOID */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN + case WMA_SET_AUTO_SHUTDOWN_TIMER_REQ: + wma_set_auto_shutdown_timer_req(wma_handle, msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* FEATURE_WLAN_AUTO_SHUTDOWN */ + case WMA_DHCP_START_IND: + case WMA_DHCP_STOP_IND: + wma_process_dhcp_ind(wma_handle, (tAniDHCPInd *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + + case WMA_INIT_THERMAL_INFO_CMD: + wma_process_init_thermal_info(wma_handle, + (t_thermal_mgmt *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + + case WMA_SET_THERMAL_LEVEL: + wma_process_set_thermal_level(wma_handle, msg->bodyval); + break; + + case WMA_SET_P2P_GO_NOA_REQ: + wma_process_set_p2pgo_noa_req(wma_handle, + (tP2pPsParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_MIMOPS_REQ: + wma_process_set_mimops_req(wma_handle, + (tSetMIMOPS *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_SAP_INTRABSS_DIS: + wma_set_vdev_intrabss_fwd(wma_handle, + (tDisableIntraBssFwd *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_GET_LINK_SPEED: + wma_get_link_speed(wma_handle, msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_MODEM_POWER_STATE_IND: + wma_notify_modem_power_state(wma_handle, + (tSirModemPowerStateInd *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_WLAN_RESUME_REQ: + wma_resume_req(wma_handle); + break; + +#ifdef WLAN_FEATURE_STATS_EXT + case WMA_STATS_EXT_REQUEST: + wma_stats_ext_req(wma_handle, + (tpStatsExtRequest) (msg->bodyptr)); + cdf_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_STATS_EXT */ + case WMA_HIDDEN_SSID_VDEV_RESTART: + wma_hidden_ssid_vdev_restart(wma_handle, + (tHalHiddenSsidVdevRestart *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_EXTWOW_SUPPORT + case WMA_WLAN_EXT_WOW: + wma_enable_ext_wow(wma_handle, + (tSirExtWoWParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_WLAN_SET_APP_TYPE1_PARAMS: + wma_set_app_type1_params_in_fw(wma_handle, + (tSirAppType1Params *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_WLAN_SET_APP_TYPE2_PARAMS: + wma_set_app_type2_params_in_fw(wma_handle, + (tSirAppType2Params *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_EXTWOW_SUPPORT */ +#ifdef FEATURE_WLAN_EXTSCAN + case WMA_EXTSCAN_START_REQ: + wma_start_extscan(wma_handle, + (tSirWifiScanCmdReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_STOP_REQ: + wma_stop_extscan(wma_handle, + (tSirExtScanStopReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ: + wma_extscan_start_hotlist_monitor(wma_handle, + (tSirExtScanSetBssidHotListReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ: + wma_extscan_stop_hotlist_monitor(wma_handle, + (tSirExtScanResetBssidHotlistReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ: + wma_extscan_start_change_monitor(wma_handle, + (tSirExtScanSetSigChangeReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ: + wma_extscan_stop_change_monitor(wma_handle, + (tSirExtScanResetSignificantChangeReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_GET_CACHED_RESULTS_REQ: + wma_extscan_get_cached_results(wma_handle, + (tSirExtScanGetCachedResultsReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_EXTSCAN_GET_CAPABILITIES_REQ: + wma_extscan_get_capabilities(wma_handle, + (tSirGetExtScanCapabilitiesReqParams *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_EPNO_LIST_REQ: + wma_set_epno_network_list(wma_handle, + (struct wifi_epno_params *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_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); + cdf_mem_free(msg->bodyptr); + break; + case WMA_RESET_PASSPOINT_LIST_REQ: + wma_reset_passpoint_network_list(wma_handle, + (struct wifi_passpoint_req *)msg->bodyptr); + break; + case WMA_EXTSCAN_SET_SSID_HOTLIST_REQ: + wma_set_ssid_hotlist(wma_handle, + (struct sir_set_ssid_hotlist_request *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* FEATURE_WLAN_EXTSCAN */ + case WMA_SET_SCAN_MAC_OUI_REQ: + wma_scan_probe_setoui(wma_handle, msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + case WMA_LINK_LAYER_STATS_CLEAR_REQ: + wma_process_ll_stats_clear_req(wma_handle, + (tpSirLLStatsClearReq) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_LINK_LAYER_STATS_SET_REQ: + wma_process_ll_stats_set_req(wma_handle, + (tpSirLLStatsSetReq) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_LINK_LAYER_STATS_GET_REQ: + wma_process_ll_stats_get_req(wma_handle, + (tpSirLLStatsGetReq) msg->bodyptr); + cdf_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); + cdf_mem_free(msg->bodyptr); + break; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + case WMA_ROAM_OFFLOAD_SYNCH_CNF: + wma_process_roam_synch_complete(wma_handle, + (tSirSmeRoamOffloadSynchCnf *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_ROAM_OFFLOAD_SYNCH_FAIL: + wma_process_roam_synch_fail(wma_handle, + (struct roam_offload_synch_fail *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_ROAM_INVOKE: + wma_process_roam_invoke(wma_handle, + (struct wma_roam_invoke_cmd *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ +#ifdef WLAN_FEATURE_NAN + case WMA_NAN_REQUEST: + wma_nan_req(wma_handle, (tNanRequest *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_NAN */ + case SIR_HAL_SET_BASE_MACADDR_IND: + wma_set_base_macaddr_indicate(wma_handle, + (tSirMacAddr *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_LINK_STATUS_GET_REQ: + wma_process_link_status_req(wma_handle, + (tAniGetLinkStatus *) msg->bodyptr); + break; + case WMA_GET_TEMPERATURE_REQ: + wma_get_temperature(wma_handle); + cdf_mem_free(msg->bodyptr); + break; +#ifdef DHCP_SERVER_OFFLOAD + case WMA_SET_DHCP_SERVER_OFFLOAD_CMD: + wma_process_dhcpserver_offload(wma_handle, + (tSirDhcpSrvOffloadInfo *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef WLAN_FEATURE_GPIO_LED_FLASHING + case WMA_LED_FLASHING_REQ: + wma_set_led_flashing(wma_handle, + (tSirLedFlashingReq *) msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; +#endif /* WLAN_FEATURE_GPIO_LED_FLASHING */ + case SIR_HAL_SET_MAS: + wma_process_set_mas(wma_handle, + (uint32_t *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_SET_MIRACAST: + wma_process_set_miracast(wma_handle, + (uint32_t *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_CONFIG_STATS_FACTOR: + wma_config_stats_factor(wma_handle, + (struct sir_stats_avg_factor *) + msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_CONFIG_GUARD_TIME: + wma_config_guard_time(wma_handle, + (struct sir_guard_time_request *) + msg->bodyptr); + case WMA_IPA_OFFLOAD_ENABLE_DISABLE: + wma_ipa_offload_enable_disable(wma_handle, + (struct sir_ipa_offload_enable_disable *)msg->bodyptr); + cdf_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); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_FLUSH_LOG_TO_FW: + wma_send_flush_logs_to_fw(wma_handle); + /* Body ptr is NULL here */ + break; + case WMA_SET_RSSI_MONITOR_REQ: + wma_set_rssi_monitoring(wma_handle, + (struct rssi_monitor_req *)msg->bodyptr); + break; + case WMA_FW_MEM_DUMP_REQ: + wma_process_fw_mem_dump_req(wma_handle, + (struct fw_dump_req *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_SOC_SET_PCL_TO_FW: + wma_send_soc_set_pcl_cmd(wma_handle, + (struct sir_pcl_list *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_SOC_SET_HW_MODE: + wma_send_soc_set_hw_mode_cmd(wma_handle, + (struct sir_hw_mode *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_OCB_SET_CONFIG_CMD: + wma_ocb_set_config_req(wma_handle, + (struct sir_ocb_config *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_OCB_SET_UTC_TIME_CMD: + wma_ocb_set_utc_time(wma_handle, + (struct sir_ocb_utc *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_OCB_START_TIMING_ADVERT_CMD: + wma_ocb_start_timing_advert(wma_handle, + (struct sir_ocb_timing_advert *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_OCB_STOP_TIMING_ADVERT_CMD: + wma_ocb_stop_timing_advert(wma_handle, + (struct sir_ocb_timing_advert *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_DCC_CLEAR_STATS_CMD: + wma_dcc_clear_stats(wma_handle, + (struct sir_dcc_clear_stats *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_OCB_GET_TSF_TIMER_CMD: + wma_ocb_get_tsf_timer(wma_handle, + (struct sir_ocb_get_tsf_timer *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_DCC_GET_STATS_CMD: + wma_dcc_get_stats(wma_handle, + (struct sir_dcc_get_stats *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_DCC_UPDATE_NDL_CMD: + wma_dcc_update_ndl(wma_handle, + (struct sir_dcc_update_ndl *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case SIR_HAL_SOC_DUAL_MAC_CFG_REQ: + wma_send_soc_set_dual_mac_config(wma_handle, + (struct sir_dual_mac_config *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_SET_IE_INFO: + wma_process_set_ie_info(wma_handle, + (struct vdev_ie_info *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; + case WMA_LRO_CONFIG_CMD: + wma_lro_config_cmd(wma_handle, + (struct wma_lro_config_cmd_t *)msg->bodyptr); + cdf_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) { + cdf_mem_free(msg->bodyptr); + } + } +end: + WMA_LOGI("%s: Exit", __func__); + return cdf_status; +} + +/** + * 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 */ + cds_logging_set_fw_flush_complete(); + + return; +} + +/** + * wma_send_soc_set_pcl_cmd() - Send WMI_SOC_SET_PCL_CMDID to FW + * @wma_handle: WMA handle + * @msg: PCL structure containing the PCL and the number of channels + * + * WMI_SOC_SET_PCL_CMDID provides a Preferred Channel List (PCL) to the WLAN + * firmware. The DBS Manager is the consumer of this information in the WLAN + * firmware. The channel list will be used when a Virtual DEVice (VDEV) needs + * to migrate to a new channel without host driver involvement. An example of + * this behavior is Legacy Fast Roaming (LFR 3.0). Generally, the host will + * manage the channel selection without firmware involvement. + * + * Return: Success if the cmd is sent successfully to the firmware + */ +CDF_STATUS wma_send_soc_set_pcl_cmd(tp_wma_handle wma_handle, + struct sir_pcl_list *msg) +{ + wmi_soc_set_pcl_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t *cmd_args, i, len; + + if (!wma_handle) { + WMA_LOGE("%s: WMA handle is NULL. Cannot issue command", + __func__); + return CDF_STATUS_E_NULL_VALUE; + } + + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + (msg->pcl_len * sizeof(uint32_t)); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_soc_set_pcl_cmd_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_t *) cmd; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_soc_set_pcl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_soc_set_pcl_cmd_fixed_param)); + cmd->num_chan = msg->pcl_len; + WMA_LOGI("%s: PCL len:%d", __func__, cmd->num_chan); + + buf_ptr += sizeof(wmi_soc_set_pcl_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (msg->pcl_len * sizeof(uint32_t))); + cmd_args = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < msg->pcl_len ; i++) { + cmd_args[i] = msg->pcl_list[i]; + WMA_LOGI("%s: PCL chan:%d", __func__, cmd_args[i]); + } + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_SOC_SET_PCL_CMDID)) { + WMA_LOGE("%s: Failed to send WMI_SOC_SET_PCL_CMDID", __func__); + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_send_soc_set_hw_mode_cmd() - Send WMI_SOC_SET_HW_MODE_CMDID to FW + * @wma_handle: WMA handle + * @msg: Structure containing the following parameters + * + * - hw_mode_index: The HW_Mode field is a enumerated type that is selected + * from the HW_Mode table, which is returned in the WMI_SERVICE_READY_EVENTID. + * + * Provides notification to the WLAN firmware that host driver is requesting a + * HardWare (HW) Mode change. This command is needed to support iHelium in the + * configurations that include the Dual Band Simultaneous (DBS) feature. + * + * Return: Success if the cmd is sent successfully to the firmware + */ +CDF_STATUS wma_send_soc_set_hw_mode_cmd(tp_wma_handle wma_handle, + struct sir_hw_mode *msg) +{ + wmi_soc_set_hw_mode_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint32_t len; + struct sir_set_hw_mode_resp *param; + + if (!wma_handle) { + WMA_LOGE("%s: WMA handle is NULL. Cannot issue command", + __func__); + /* Handle is NULL. Will not be able to send failure + * response as well + */ + return CDF_STATUS_E_NULL_VALUE; + } + + if (!msg) { + WMA_LOGE("%s: Set HW mode param is NULL", __func__); + /* Lets try to free the active command list */ + goto fail; + } + + len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + goto fail; + } + + cmd = (wmi_soc_set_hw_mode_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_soc_set_hw_mode_cmd_fixed_param)); + cmd->hw_mode_index = msg->hw_mode_index; + WMA_LOGI("%s: HW mode index:%d", __func__, cmd->hw_mode_index); + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_SOC_SET_HW_MODE_CMDID)) { + WMA_LOGE("%s: Failed to send WMI_SOC_SET_HW_MODE_CMDID", + __func__); + cdf_nbuf_free(buf); + goto fail; + } + return CDF_STATUS_SUCCESS; +fail: + param = cdf_mem_malloc(sizeof(*param)); + if (!param) { + WMA_LOGE("%s: Memory allocation failed", __func__); + return CDF_STATUS_E_NULL_VALUE; + } + param->status = SET_HW_MODE_STATUS_ECANCELED; + param->cfgd_hw_mode_index = 0; + param->num_vdev_mac_entries = 0; + WMA_LOGE("%s: Sending HW mode fail response to LIM", __func__); + wma_send_msg(wma_handle, SIR_HAL_SOC_SET_HW_MODE_RESP, + (void *) param, 0); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_send_soc_set_dual_mac_config() - Set dual mac config to FW + * @wma_handle: WMA handle + * @msg: Dual MAC config parameters + * + * Configures WLAN firmware with the dual MAC features + * + * Return: CDF_STATUS. 0 on success. + */ +CDF_STATUS wma_send_soc_set_dual_mac_config(tp_wma_handle wma_handle, + struct sir_dual_mac_config *msg) +{ + wmi_soc_set_dual_mac_config_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint32_t len; + + if (!wma_handle) { + WMA_LOGE("%s: WMA handle is NULL. Cannot issue command", + __func__); + return CDF_STATUS_E_NULL_VALUE; + } + + if (!msg) { + WMA_LOGE("%s: Set dual mode config is NULL", __func__); + return CDF_STATUS_E_NULL_VALUE; + } + + len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_FAILURE; + } + + cmd = (wmi_soc_set_dual_mac_config_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_soc_set_dual_mac_config_cmd_fixed_param)); + cmd->concurrent_scan_config_bits = msg->scan_config; + cmd->fw_mode_config_bits = msg->fw_mode_config; + WMA_LOGI("%s: scan_config:%x fw_mode_config:%x", + __func__, msg->scan_config, msg->fw_mode_config); + + wma_handle->dual_mac_cfg.req_scan_config = msg->scan_config; + wma_handle->dual_mac_cfg.req_fw_mode_config = msg->fw_mode_config; + + if (wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID)) { + WMA_LOGE("%s: Failed to send WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID", + __func__); + cdf_nbuf_free(buf); + } + return CDF_STATUS_SUCCESS; +} + +/** + * 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); +} +#if defined(FEATURE_LRO) +/** + * wma_lro_init() - sends LRO configuration to FW + * @lro_config: pointer to the config parameters + * + * This function ends LRO configuration to FW. + * + * Return: 0 for success or reasons for failure + */ +int wma_lro_init(struct wma_lro_config_cmd_t *lro_config) +{ + cds_msg_t msg = {0}; + struct wma_lro_config_cmd_t *iwcmd; + + iwcmd = cdf_mem_malloc(sizeof(*iwcmd)); + if (!iwcmd) { + WMA_LOGE("memory allocation for WMA_LRO_CONFIG_CMD failed!"); + return -ENOMEM; + } + + *iwcmd = *lro_config; + + msg.type = WMA_LRO_CONFIG_CMD; + msg.reserved = 0; + msg.bodyptr = iwcmd; + + if (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) { + WMA_LOGE("Failed to post WMA_LRO_CONFIG_CMD msg!"); + cdf_mem_free(iwcmd); + return -EAGAIN; + } + + WMA_LOGD("sending the LRO configuration to the fw"); + return 0; +} +#endif diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c new file mode 100644 index 000000000000..c6f0b3ab6b83 --- /dev/null +++ b/core/wma/src/wma_mgmt.c @@ -0,0 +1,3208 @@ +/* + * 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_mgmt.c + * + * This file contains STA/SAP/IBSS and protocol related functions. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +#include "csr_api.h" +#include "ol_fw.h" +#include "dfs.h" +#include "wma_internal.h" + +/** + * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL + * @wma: wma handle + * @pdev: txrx pdev + * @vdev_id: vdev id + * @param_buf: SWBA parameters + * + * Return: none + */ +static void wma_send_bcn_buf_ll(tp_wma_handle wma, + ol_txrx_pdev_handle pdev, + uint8_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; + uint8_t *bcn_payload; + wmi_buf_t wmi_buf; + CDF_STATUS 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; + uint8_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; + } + + cdf_spin_lock_bh(&bcn->lock); + + bcn_payload = cdf_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) + cdf_mem_copy(&tim_ie->tim_bitmap, tim_info->tim_bitmap, + WMA_TIM_SUPPORTED_PVB_LENGTH); + else + cdf_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; + *(uint16_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)) { + cdf_mem_zero(&noa_ie, sizeof(noa_ie)); + + noa_ie.index = + (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info); + noa_ie.oppPS = + (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info); + noa_ie.ctwindow = + (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info); + noa_ie.num_descriptors = + (uint8_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 = + (uint8_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) { + cdf_nbuf_unmap_single(pdev->osdev, bcn->buf, CDF_DMA_TO_DEVICE); + bcn->dma_mapped = 0; + } + ret = cdf_nbuf_map_single(pdev->osdev, bcn->buf, CDF_DMA_TO_DEVICE); + if (ret != CDF_STATUS_SUCCESS) { + cdf_nbuf_free(wmi_buf); + WMA_LOGE("%s: failed map beacon buf to DMA region", __func__); + cdf_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 = cdf_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); + } + cdf_spin_unlock_bh(&bcn->lock); +} + +/** + * wma_beacon_swba_handler() - swba event handler + * @handle: wma handle + * @event: event data + * @len: data length + * + * SWBA event is alert event to Host requesting host to Queue a beacon + * for transmission use only in host beacon mode + * + * Return: 0 for success or error code + */ +int wma_beacon_swba_handler(void *handle, uint8_t *event, uint32_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; + uint32_t vdev_map; + ol_txrx_pdev_handle pdev; + uint8_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 = cds_get_context(CDF_MODULE_ID_TXRX); + 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 (!ol_cfg_is_high_latency(pdev->ctrl_pdev)) + wma_send_bcn_buf_ll(wma, pdev, vdev_id, param_buf); + break; + } + return 0; +} + +/** + * wma_peer_sta_kickout_event_handler() - kickout event handler + * @handle: wma handle + * @event: event data + * @len: data length + * + * Kickout event is received from firmware on observing beacon miss + * It handles kickout event for different modes and indicate to + * upper layers. + * + * Return: 0 for success or error code + */ +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; + uint8_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 = cds_get_context(CDF_MODULE_ID_TXRX); + 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 (ol_txrx_get_vdevid(peer, &vdev_id) != CDF_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) + cdf_mem_malloc(sizeof(tSirIbssPeerInactivityInd)); + if (!p_inactivity) { + WMA_LOGE("CDF MEM Alloc Failed for tSirIbssPeerInactivity"); + return -ENOMEM; + } + + p_inactivity->staIdx = peer_id; + cdf_mem_copy(p_inactivity->peerAddr, macaddr, + IEEE80211_ADDR_LEN); + wma_send_msg(wma, WMA_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) + cdf_mem_malloc(sizeof(tDeleteStaContext)); + if (!del_sta_ctx) { + WMA_LOGE("%s: mem alloc failed for tDeleteStaContext for TDLS peer: %pM", + __func__, macaddr); + return -ENOMEM; + } + + del_sta_ctx->staId = peer_id; + cdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN); + cdf_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) && + cdf_mem_compare(wma->interfaces[vdev_id].bssid, + macaddr, IEEE80211_ADDR_LEN)) { + /* + * 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); + 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) && + cdf_mem_compare(wma->interfaces[vdev_id].bssid, + macaddr, IEEE80211_ADDR_LEN)) { + /* + * 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); + goto exit_handler; + } + break; + + case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY: + default: + break; + } + + /* + * default action is to send delete station context indication to LIM + */ + del_sta_ctx = + (tpDeleteStaContext) cdf_mem_malloc(sizeof(tDeleteStaContext)); + if (!del_sta_ctx) { + WMA_LOGE("CDF MEM Alloc Failed for tDeleteStaContext"); + return -ENOMEM; + } + + del_sta_ctx->staId = peer_id; + cdf_mem_copy(del_sta_ctx->addr2, macaddr, IEEE80211_ADDR_LEN); + cdf_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; + wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, (void *)del_sta_ctx, + 0); + +exit_handler: + WMA_LOGD("%s: Exit", __func__); + return 0; +} + +/** + * wma_unified_bcntx_status_event_handler() - beacon tx status event handler + * @handle: wma handle + * @cmd_param_info: event data + * @len: data length + * + * 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: 0 for success or error code + */ +int wma_unified_bcntx_status_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_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 *) + cdf_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 = WMA_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, WMA_DFS_BEACON_TX_SUCCESS_IND, + (void *)beacon_tx_complete_ind, 0); + return 0; +} + +/** + * wma_get_link_probe_timeout() - get link timeout based on sub type + * @mac: UMAC handler + * @sub_type: vdev syb type + * @max_inactive_time: return max inactive time + * @max_unresponsive_time: return max unresponsive time + * + * Return: none + */ +static inline void wma_get_link_probe_timeout(struct sAniSirGlobal *mac, + uint32_t sub_type, + uint32_t *max_inactive_time, + uint32_t *max_unresponsive_time) +{ + uint32_t keep_alive; + uint16_t 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_cfg_get_int(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_cfg_get_int(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; +} + +/** + * wma_set_sap_keepalive() - set SAP keep alive parameters to fw + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id) +{ + uint32_t min_inactive_time, max_inactive_time, max_unresponsive_time; + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + + 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); +} + +/** + * wma_set_sta_keep_alive() - set sta keep alive parameters + * @wma: wma handle + * @vdev_id: vdev id + * @method: method for keep alive + * @timeperiod: time period + * @hostv4addr: host ipv4 address + * @destv4addr: dst ipv4 address + * @destmac: destination mac + * + * This function sets keep alive related parameters in fw. + * + * Return: none + */ +void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, + uint32_t method, uint32_t timeperiod, + uint8_t *hostv4addr, uint8_t *destv4addr, + uint8_t *destmac) +{ + wmi_buf_t buf; + WMI_STA_KEEPALIVE_CMD_fixed_param *cmd; + WMI_STA_KEEPALVE_ARP_RESPONSE *arp_rsp; + uint8_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 = (uint8_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) { + cmd->method = WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE; + cdf_mem_copy(&arp_rsp->sender_prot_addr, hostv4addr, + SIR_IPV4_ADDR_LEN); + cdf_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"); + cdf_nbuf_free(buf); + } + + WMA_LOGD("%s: Exit", __func__); + return; +} + +/** + * wma_vdev_install_key_complete_event_handler() - install key complete handler + * @handle: wma handle + * @event: event data + * @len: data length + * + * This event is sent by fw once WPA/WPA2 keys are installed in fw. + * + * Return: 0 for success or error code + */ +int wma_vdev_install_key_complete_event_handler(void *handle, + uint8_t *event, + uint32_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 -EINVAL; + } + + param_buf = (WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return -EINVAL; + } + + key_fp = param_buf->fixed_param; + if (!key_fp) { + WMA_LOGE("%s: received null event data from target", __func__); + return -EINVAL; + } + /* + * 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; +} +/* + * 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 uint8_t wma_mpdu_spacing[] = { 0, 1, 1, 1, 2, 4, 8, 16 }; + +/** + * wma_parse_mpdudensity() - give mpdu spacing from mpdu density + * @mpdudensity: mpdu density + * + * Return: mpdu spacing or 0 for error + */ +static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity) +{ + if (mpdudensity < sizeof(wma_mpdu_spacing)) + return wma_mpdu_spacing[mpdudensity]; + else + return 0; +} + +/** + * wmi_unified_send_peer_assoc() - send peer assoc command to fw + * @wma: wma handle + * @nw_type: nw type + * @params: add sta params + * + * This function send peer assoc command to firmware with + * different parameters. + * + * Return: 0 for success or error code + */ +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; + uint8_t rx_stbc, tx_stbc; + uint8_t *rate_pos, *buf_ptr; + wmi_rate_set peer_legacy_rates, peer_ht_rates; + wmi_vht_rate_set *mcs; + uint32_t num_peer_legacy_rates; + uint32_t num_peer_ht_rates; + uint32_t num_peer_11b_rates = 0; + uint32_t num_peer_11a_rates = 0; + uint32_t phymode; + uint32_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 = cds_get_context(CDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + return -EINVAL; + } + + cdf_mem_zero(&peer_legacy_rates, sizeof(wmi_rate_set)); + cdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set)); + + phymode = wma_peer_phymode(nw_type, params->staType, + params->htCapable, + params->ch_width, + params->vhtCapable); + + /* Legacy Rateset */ + rate_pos = (uint8_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(uint32_t)); + + /* HT Rateset */ + max_rates = sizeof(peer_ht_rates.rates) / + sizeof(peer_ht_rates.rates[0]); + rate_pos = (uint8_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) { + uint8_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); + cdf_mem_copy((uint8_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(uint32_t)); + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + /* Place holder for peer legacy rate array */ + (num_peer_legacy_rates * sizeof(uint8_t)) + /* peer legacy rate array size */ + WMI_TLV_HDR_SIZE + /* Place holder for peer Ht rate array */ + (num_peer_ht_rates * sizeof(uint8_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 = (uint8_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 /* QCA_IBSS_SUPPORT */ +#ifdef FEATURE_WLAN_TDLS + || (STA_ENTRY_TDLS_PEER == params->staType) +#endif /* FEATURE_WLAN_TDLS */ + ) + 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->ch_width) { + 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->ch_width == CH_WIDTH_80MHZ) + cmd->peer_flags |= WMI_PEER_80MHZ; + else if (params->ch_width == CH_WIDTH_160MHZ) + cmd->peer_flags |= WMI_PEER_160MHZ; + else if (params->ch_width == CH_WIDTH_80P80MHZ) + cmd->peer_flags |= WMI_PEER_160MHZ; + + cmd->peer_vht_caps = params->vht_caps; +#endif /* WLAN_FEATURE_11AC */ + + 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 /* FEATURE_WLAN_TDLS */ + + if (params->wpa_rsn +#ifdef FEATURE_WLAN_WAPI + || params->encryptType == eSIR_ED_WPI +#endif /* FEATURE_WLAN_WAPI */ + ) + cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY; + if (params->wpa_rsn >> 1) + cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY; + + ol_txrx_peer_state_update(pdev, params->bssId, ol_txrx_peer_state_auth); + +#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); + cdf_nbuf_free(buf); + return ret; + } + } +#endif /* FEATURE_WLAN_WAPI */ + + 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; + cdf_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; + cdf_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 + */ + 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); + cdf_nbuf_free(buf); + } + return ret; +} + +/** + * wmi_unified_vdev_set_gtx_cfg_send() - set GTX params + * @wmi_handle: wmi handle + * @if_id: vdev id + * @gtx_info: GTX config params + * + * This function set GTX related params in firmware. + * + * Return: 0 for success or error code + */ +int wmi_unified_vdev_set_gtx_cfg_send(wmi_unified_t wmi_handle, uint32_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 -ENOMEM; + } + 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_update_protection_mode() - update protection mode + * @wma: wma handle + * @vdev_id: vdev id + * @llbcoexist: protection mode info + * + * This function set protection mode(RTS/CTS) to fw for passed vdev id. + * + * Return: none + */ +void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id, + uint8_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); +} + +/** + * wma_update_beacon_interval() - update beacon interval in fw + * @wma: wma handle + * @vdev_id: vdev id + * @beaconInterval: becon interval + * + * Return: none + */ +static void +wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id, + uint16_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); +} + +/** + * wma_process_update_beacon_params() - update beacon parameters to target + * @wma: wma handle + * @bcn_params: beacon parameters + * + * Return: none + */ +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); +} + +/** + * wma_update_cfg_params() - update cfg parameters to target + * @wma: wma handle + * @cfgParam: cfg parameter + * + * Return: none + */ +void wma_update_cfg_params(tp_wma_handle wma, tSirMsgQ *cfgParam) +{ + uint8_t vdev_id; + uint32_t param_id; + uint32_t 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 = cds_get_context(CDF_MODULE_ID_PE); + + if (NULL == pmac) { + WMA_LOGE("%s: Failed to get pmac", __func__); + return; + } + + if (wlan_cfg_get_int(pmac, (uint16_t) 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); + } + } +} + +/** + * wma_read_cfg_wepkey() - fill key_info for WEP key + * @wma_handle: wma handle + * @key_info: key_info ptr + * @def_key_idx: default key index + * @num_keys: number of keys + * + * This function reads WEP keys from cfg and fills + * up key_info. + * + * Return: none + */ +static void wma_read_cfg_wepkey(tp_wma_handle wma_handle, + tSirKeys *key_info, uint32_t *def_key_idx, + uint8_t *num_keys) +{ + tSirRetStatus status; + uint32_t val = SIR_MAC_KEY_LENGTH; + uint8_t i, j; + + WMA_LOGD("Reading WEP keys from cfg"); + /* NOTE:def_key_idx is initialized to 0 by the caller */ + status = wlan_cfg_get_int(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_cfg_get_str(wma_handle->mac_context, + (uint16_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 = (uint16_t) val; + j++; + } + } + *num_keys = j; +} + +/** + * wma_setup_install_key_cmd() - fill wmi buffer as per key parameters + * @wma_handle: wma handle + * @key_params: key parameters + * @len: length + * @mode: op mode + * + * This function setsup wmi buffer from information + * passed in key_params. + * + * Return: filled wmi buffer ptr or NULL for error + */ +static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, + struct wma_set_key_params + *key_params, uint32_t *len, + uint8_t mode) +{ + wmi_vdev_install_key_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint8_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(uint32_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 = (uint8_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; + + cdf_mem_copy(&cmd->wpi_key_rsc_counter, &rx_iv, + WPI_IV_LEN); + cdf_mem_copy(&cmd->wpi_key_tsc_counter, &tx_iv, + WPI_IV_LEN); + cmd->key_cipher = WMI_CIPHER_WAPI; + break; + } +#endif /* FEATURE_WLAN_WAPI */ + 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); + cdf_nbuf_free(buf); + return NULL; + } + + buf_ptr += sizeof(wmi_vdev_install_key_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, + roundup(key_params->key_len, sizeof(uint32_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; + uint32_t *destp, *srcp; + + destp = (uint32_t *) key_data; + srcp = (uint32_t *) key_params->key_data; + for (i = 0; + i < roundup(key_params->key_len, sizeof(uint32_t)) / 4; + i++) { + *destp = le32_to_cpu(*srcp); + destp++; + srcp++; + } + } +#else + cdf_mem_copy((void *)key_data, + (const void *)key_params->key_data, key_params->key_len); +#endif /* BIG_ENDIAN_HOST */ + 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; + cdf_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)) + cdf_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; +} + +/** + * wma_set_bsskey() - set encryption key to fw. + * @wma_handle: wma handle + * @key_info: key info + * + * Return: none + */ +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; + uint32_t len = 0, i; + uint32_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 = CDF_STATUS_E_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 = CDF_STATUS_SUCCESS; + if (wma_handle->ibss_started > 0) + goto out; + WMA_LOGD("Caching IBSS Key"); + cdf_mem_copy(&wma_handle->ibsskey_info, key_info, + sizeof(tSetBssKeyParams)); + } + + cdf_mem_set(&key_params, sizeof(key_params), 0); + 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) { + cdf_mem_copy(key_params.peer_mac, + wma_handle->interfaces[key_info->smesessionId].bssid, + IEEE80211_ADDR_LEN); + } else { + /* vdev mac address will be passed for all other modes */ + cdf_mem_copy(key_params.peer_mac, txrx_vdev->mac_addr.raw, + IEEE80211_ADDR_LEN); + 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); + } + + 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) { + cdf_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + cdf_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + cdf_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + cdf_mem_copy((void *)key_params.key_data, + (const void *)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 = CDF_STATUS_E_NOMEM; + goto out; + } + + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_INSTALL_KEY_CMDID); + if (status) { + cdf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", + __func__); + key_info->status = CDF_STATUS_E_FAILURE; + goto out; + } + } + + wma_handle->ibss_started++; + /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */ + key_info->status = CDF_STATUS_SUCCESS; + +out: + wma_send_msg(wma_handle, WMA_SET_BSSKEY_RSP, (void *)key_info, 0); +} + +#ifdef QCA_IBSS_SUPPORT +/** + * wma_calc_ibss_heart_beat_timer() - calculate IBSS heart beat timer + * @peer_num: number of peers + * + * Return: heart beat timer value + */ +static uint16_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 uint16_t heart_beat_timer[MAX_IBSS_PEERS] = { + 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 > MAX_IBSS_PEERS) + return 0; + + return heart_beat_timer[peer_num - 1]; + +} + +/** + * wma_adjust_ibss_heart_beat_timer() - set ibss heart beat timer in fw. + * @wma: wma handle + * @vdev_id: vdev id + * @peer_num_delta: peer number delta value + * + * Return: none + */ +void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma, + uint8_t vdev_id, + int8_t peer_num_delta) +{ + ol_txrx_vdev_handle vdev; + int16_t new_peer_num; + uint16_t new_timer_value_sec; + uint32_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 > MAX_IBSS_PEERS || 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 = ((uint32_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 */ +/** + * wma_set_ibsskey_helper() - cached IBSS key in wma handle + * @wma_handle: wma handle + * @key_info: set bss key info + * @peerMacAddr: peer mac address + * + * Return: none + */ +static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, + tpSetBssKeyParams key_info, + uint8_t *peerMacAddr) +{ + struct wma_set_key_params key_params; + wmi_buf_t buf; + int32_t status; + uint32_t len = 0, i; + uint32_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 = CDF_STATUS_E_FAILURE; + return; + } + + cdf_mem_set(&key_params, sizeof(key_params), 0); + 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); + + cdf_mem_copy(key_params.peer_mac, peerMacAddr, IEEE80211_ADDR_LEN); + + 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) { + cdf_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + cdf_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + cdf_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + cdf_mem_copy((void *)key_params.key_data, + (const void *)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) { + cdf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", + __func__); + } + } +} + +/** + * wma_set_stakey() - set encryption key + * @wma_handle: wma handle + * @key_info: station key info + * + * This function sets encryption key for WEP/WPA/WPA2 + * encryption mode in firmware and send response to upper layer. + * + * Return: none + */ +void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) +{ + wmi_buf_t buf; + int32_t status, i; + uint32_t len = 0; + ol_txrx_pdev_handle txrx_pdev; + ol_txrx_vdev_handle txrx_vdev; + struct ol_txrx_peer_t *peer; + uint8_t num_keys = 0, peer_id; + struct wma_set_key_params key_params; + uint32_t def_key_idx = 0; + + WMA_LOGD("STA key setup"); + + /* Get the txRx Pdev handle */ + txrx_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!txrx_pdev) { + WMA_LOGE("%s:Invalid txrx pdev handle", __func__); + key_info->status = CDF_STATUS_E_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 = CDF_STATUS_E_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 = CDF_STATUS_E_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; + } + } + } + } + cdf_mem_set(&key_params, sizeof(key_params), 0); + 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; + cdf_mem_copy((void *)key_params.peer_mac, + (const void *)key_info->peerMacAddr, IEEE80211_ADDR_LEN); + 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) { + cdf_mem_copy(key_params.key_data, + key_info->key[i].key, 16); + cdf_mem_copy(&key_params.key_data[16], + &key_info->key[i].key[24], 8); + cdf_mem_copy(&key_params.key_data[24], + &key_info->key[i].key[16], 8); + } else + cdf_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 = CDF_STATUS_E_NOMEM; + 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) { + cdf_nbuf_free(buf); + WMA_LOGE("%s:Failed to send install key command", + __func__); + key_info->status = CDF_STATUS_E_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 = CDF_STATUS_SUCCESS; +out: + if (key_info->sendRsp) + wma_send_msg(wma_handle, WMA_SET_STAKEY_RSP, (void *)key_info, + 0); +} + +/** + * wma_process_update_edca_param_req() - update EDCA params + * @handle: wma handle + * @edca_params: edca parameters + * + * This function updates EDCA parameters to the target + * + * Return: CDF Status + */ +CDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle, + tEdcaParams *edca_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + uint8_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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 = cds_get_context(CDF_MODULE_ID_TXRX); + ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param); + + return CDF_STATUS_SUCCESS; + +fail: + wmi_buf_free(buf); + WMA_LOGE("%s: Failed to set WMM Paremeters", __func__); + return CDF_STATUS_E_FAILURE; +} + +/** + * wmi_unified_probe_rsp_tmpl_send() - send probe response template to fw + * @wma: wma handle + * @vdev_id: vdev id + * @probe_rsp_info: probe response info + * + * Return: 0 for success or error code + */ +static int wmi_unified_probe_rsp_tmpl_send(tp_wma_handle wma, + uint8_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; + uint32_t tmpl_len, tmpl_len_aligned, wmi_buf_len; + uint8_t *frm, *buf_ptr; + int ret; + uint64_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 = (uint8_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; + cdf_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; +} + +/** + * wmi_unified_bcn_tmpl_send() - send beacon template to fw + * @wma:wma handle + * @vdev_id: vdev id + * @bcn_info: beacon info + * @bytes_to_strip: bytes to strip + * + * Return: 0 for success or error code + */ +static int wmi_unified_bcn_tmpl_send(tp_wma_handle wma, + uint8_t vdev_id, + tpSendbeaconParams bcn_info, + uint8_t bytes_to_strip) +{ + wmi_bcn_tmpl_cmd_fixed_param *cmd; + wmi_bcn_prb_info *bcn_prb_info; + wmi_buf_t wmi_buf; + uint32_t tmpl_len, tmpl_len_aligned, wmi_buf_len; + uint8_t *frm, *buf_ptr; + int ret; + uint8_t *p2p_ie; + uint16_t p2p_ie_len = 0; + uint64_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 = (uint16_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 = *(uint32_t *) &bcn_info->beacon[0]; + else + tmpl_len = bcn_info->beaconLength; + if (p2p_ie_len) { + tmpl_len -= (uint32_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 = (uint8_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; + cdf_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; +} + +/** + * wma_store_bcn_tmpl() - store beacon template + * @wma: wma handle + * @vdev_id: vdev id + * @bcn_info: beacon params + * + * This function stores beacon template locally. + * This will send to target on the reception of + * SWBA event. + * + * Return: CDF status + */ +CDF_STATUS wma_store_bcn_tmpl(tp_wma_handle wma, uint8_t vdev_id, + tpSendbeaconParams bcn_info) +{ + struct beacon_info *bcn; + uint32_t len; + uint8_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 CDF_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 CDF_STATUS_E_INVAL; + } + WMA_LOGD("%s: Storing received beacon template buf to local buffer", + __func__); + cdf_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. + */ + cdf_nbuf_trim_tail(bcn->buf, cdf_nbuf_len(bcn->buf)); + memcpy(cdf_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 = cdf_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; + } + + cdf_nbuf_put_tail(bcn->buf, len); + bcn->len = len; + + cdf_spin_unlock_bh(&bcn->lock); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_tbttoffset_update_event_handler() - tbtt offset update handler + * @handle: wma handle + * @event: event buffer + * @len: data length + * + * Return: 0 for success or error code + */ +int wma_tbttoffset_update_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf; + wmi_tbtt_offset_event_fixed_param *tbtt_offset_event; + struct wma_txrx_node *intf; + struct beacon_info *bcn; + tSendbeaconParams bcn_info; + uint32_t *adjusted_tsf = NULL; + uint32_t if_id = 0, vdev_map; + + if (!wma) { + WMA_LOGE("Invalid wma handle"); + return -EINVAL; + } + + 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; + intf = wma->interfaces; + vdev_map = tbtt_offset_event->vdev_map; + adjusted_tsf = param_buf->tbttoffset_list; + 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]; + + cdf_spin_lock_bh(&bcn->lock); + cdf_mem_zero(&bcn_info, sizeof(bcn_info)); + bcn_info.beacon = cdf_nbuf_data(bcn->buf); + bcn_info.p2pIeOffset = bcn->p2p_ie_offset; + bcn_info.beaconLength = bcn->len; + bcn_info.timIeOffset = bcn->tim_ie_offset; + cdf_spin_unlock_bh(&bcn->lock); + + /* Update beacon template in firmware */ + wmi_unified_bcn_tmpl_send(wma, if_id, &bcn_info, 0); + } + return 0; +} + +/** + * wma_p2p_go_set_beacon_ie() - set beacon IE for p2p go + * @wma_handle: wma handle + * @vdev_id: vdev id + * @p2pIe: p2p IE + * + * Return: 0 for success or error code + */ +static int wma_p2p_go_set_beacon_ie(t_wma_handle *wma_handle, + A_UINT32 vdev_id, uint8_t *p2pIe) +{ + int ret; + wmi_p2p_go_set_beacon_ie_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t ie_len, ie_len_aligned, wmi_buf_len; + uint8_t *buf_ptr; + + ie_len = (uint32_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 = (uint8_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; + cdf_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; +} + +/** + * wma_send_probe_rsp_tmpl() - send probe resp template + * @wma: wma handle + * @probe_rsp_info: probe response info + * + * This funciton sends probe response template to fw which + * firmware will use in case of probe response offload. + * + * Return: none + */ +void wma_send_probe_rsp_tmpl(tp_wma_handle wma, + tpSendProbeRespParams probe_rsp_info) +{ + ol_txrx_vdev_handle vdev; + uint8_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; + } + } +} + +/** + * wma_send_beacon() - send beacon template + * @wma: wma handle + * @bcn_info: beacon info + * + * This funciton store beacon template locally and + * update keep alive parameters + * + * Return: none + */ +void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) +{ + ol_txrx_vdev_handle vdev; + uint8_t vdev_id; + CDF_STATUS status; + uint8_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 != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s : wma_store_bcn_tmpl Failed", __func__); + return; + } + if (!wma->interfaces[vdev_id].vdev_up) { + if (wmi_unified_vdev_up_send(wma->wmi_handle, vdev_id, 0, + bcn_info->bssId) < 0) { + WMA_LOGE("%s : failed to send vdev up", __func__); + return; + } + wma->interfaces[vdev_id].vdev_up = true; + wma_set_sap_keepalive(wma, vdev_id); + } +} + +/** + * wma_set_keepalive_req() - send keep alive request to fw + * @wma: wma handle + * @keepalive: keep alive parameters + * + * Return: none + */ +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); + + cdf_mem_free(keepalive); +} + +/** + * wma_beacon_miss_handler() - beacon miss event handler + * @wma: wma handle + * @vdev_id: vdev id + * + * This function send beacon miss indication to upper layers. + * + * Return: none + */ +void wma_beacon_miss_handler(tp_wma_handle wma, uint32_t vdev_id) +{ + tSirSmeMissedBeaconInd *beacon_miss_ind; + + beacon_miss_ind = (tSirSmeMissedBeaconInd *) cdf_mem_malloc + (sizeof(tSirSmeMissedBeaconInd)); + + if (NULL == beacon_miss_ind) { + WMA_LOGE("%s: Memory allocation failure", __func__); + return; + } + beacon_miss_ind->messageType = WMA_MISSED_BEACON_IND; + beacon_miss_ind->length = sizeof(tSirSmeMissedBeaconInd); + beacon_miss_ind->bssIdx = vdev_id; + + wma_send_msg(wma, WMA_MISSED_BEACON_IND, (void *)beacon_miss_ind, 0); +} + +/** + * wma_mgmt_tx_completion_handler() - wma mgmt Tx completion event handler + * @handle: wma handle + * @cmpl_event_params: completion event handler data + * @len: length of @cmpl_event_params + * + * Return: 0 on success; error number otherwise + */ + +int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params, + uint32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *param_buf; + wmi_mgmt_tx_compl_event_fixed_param *cmpl_params; + struct wmi_desc_t *wmi_desc; + + ol_txrx_pdev_handle pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + param_buf = (WMI_MGMT_TX_COMPLETION_EVENTID_param_tlvs *) + cmpl_event_params; + if (!param_buf && !wma_handle) { + WMA_LOGE("%s: Invalid mgmt Tx completion event", __func__); + return -EINVAL; + } + cmpl_params = param_buf->fixed_param; + + WMA_LOGI("%s: status:%d wmi_desc_id:%d", __func__, cmpl_params->status, + cmpl_params->desc_id); + + wmi_desc = (struct wmi_desc_t *) + (&wma_handle->wmi_desc_pool.array[cmpl_params->desc_id]); + + if (!wmi_desc) { + WMA_LOGE("%s: Invalid wmi desc", __func__); + return -EINVAL; + } + + if (wmi_desc->nbuf) + cdf_nbuf_unmap_single(pdev->osdev, wmi_desc->nbuf, + CDF_DMA_TO_DEVICE); + if (wmi_desc->tx_cmpl_cb) + wmi_desc->tx_cmpl_cb(wma_handle->mac_context, + wmi_desc->nbuf, 1); + + if (wmi_desc->ota_post_proc_cb) + wmi_desc->ota_post_proc_cb((tpAniSirGlobal) + wma_handle->mac_context, + cmpl_params->status); + + wmi_desc_put(wma_handle, wmi_desc); + + return 0; +} + +/** + * wma_process_update_opmode() - process update VHT opmode cmd from UMAC + * @wma_handle: wma handle + * @update_vht_opmode: vht opmode + * + * Return: none + */ +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); +} + +/** + * wma_process_update_rx_nss() - process update RX NSS cmd from UMAC + * @wma_handle: wma handle + * @update_rx_nss: rx nss value + * + * Return: none + */ +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 rx_nss = update_rx_nss->rxNss; + + wma_update_txrx_chainmask(wma_handle->num_rf_chains, &rx_nss); + + intr->nss = (uint8_t)rx_nss; + update_rx_nss->rxNss = (uint32_t)rx_nss; + + 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 WLAN_FEATURE_11AC +/** + * wma_process_update_membership() - process update group membership cmd + * @wma_handle: wma handle + * @membership: group membership info + * + * Return: none + */ +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); +} + +/** + * wma_process_update_userpos() - process update user pos cmd from UMAC + * @wma_handle: wma handle + * @userpos: user pos value + * + * Return: none + */ +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 /* WLAN_FEATURE_11AC */ + +/** + * wma_set_htconfig() - set ht config parameters to target + * @vdev_id: vdev id + * @ht_capab: ht capablity + * @value: value of ht param + * + * Return: CDF status + */ +CDF_STATUS wma_set_htconfig(uint8_t vdev_id, uint16_t ht_capab, int value) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + int ret = -EIO; + + if (NULL == wma) { + WMA_LOGE("%s: Failed to get wma", __func__); + return CDF_STATUS_E_INVAL; + } + + 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) ? CDF_STATUS_E_FAILURE : CDF_STATUS_SUCCESS; +} + +/** + * wma_hidden_ssid_vdev_restart() - vdev restart for hidden ssid + * @wma_handle: wma handle + * @pReq: hidden ssid vdev restart request + * + * Return: none + */ +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; + cdf_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); + ol_txrx_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__); + cdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params. + hidden_ssid_restart_in_progress, 0); + return; + } +} + + +#ifdef WLAN_FEATURE_11W + +/** + * wma_extract_ccmp_pn() - extract 6 byte PN from the CCMP header + * @ccmp_ptr: CCMP header + * + * Return: PN extracted from header. + */ +static uint64_t wma_extract_ccmp_pn(uint8_t *ccmp_ptr) +{ + uint8_t rsvd, key, pn[6]; + uint64_t new_pn; + + /* + * +-----+-----+------+----------+-----+-----+-----+-----+ + * | PN0 | PN1 | rsvd | rsvd/key | PN2 | PN3 | PN4 | PN5 | + * +-----+-----+------+----------+-----+-----+-----+-----+ + * CCMP Header Format + */ + + /* Extract individual bytes */ + pn[0] = (uint8_t) *ccmp_ptr; + pn[1] = (uint8_t) *(ccmp_ptr + 1); + rsvd = (uint8_t) *(ccmp_ptr + 2); + key = (uint8_t) *(ccmp_ptr + 3); + pn[2] = (uint8_t) *(ccmp_ptr + 4); + pn[3] = (uint8_t) *(ccmp_ptr + 5); + pn[4] = (uint8_t) *(ccmp_ptr + 6); + pn[5] = (uint8_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); + + WMA_LOGE("PN of received packet is %llu", new_pn); + return new_pn; +} + +/** + * wma_is_ccmp_pn_replay_attack() - detect replay attacking using PN in CCMP + * @cds_ctx: cds context + * @wh: 802.11 frame header + * @ccmp_ptr: CCMP frame header + * + * Return: true/false + */ +static bool +wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh, + uint8_t *ccmp_ptr) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + uint8_t vdev_id, peer_id; + uint8_t *last_pn_valid; + uint64_t *last_pn, new_pn; + uint32_t *rmf_pn_replays; + + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + WMA_LOGE("%s: Failed to find pdev", __func__); + return true; + } + + vdev = wma_find_vdev_by_addr(cds_ctx, wh->i_addr2, &vdev_id); + if (!vdev) { + WMA_LOGE("%s: Failed to find vdev", __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) { + WMA_LOGE("%s: Failed to find peer, Not able to validate PN", + __func__); + return true; + } + + new_pn = wma_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; + WMA_LOGE("%s: PN validation successful", __func__); + } else { + WMA_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; +} + +/** + * wma_process_rmf_frame() - process rmf frame + * @wma_handle: wma handle + * @iface: txrx node + * @wh: 80211 frame + * @rx_pkt: rx packet + * @wbuf: Buffer + * + * Return: 0 for success or error code + */ +static +int wma_process_rmf_frame(tp_wma_handle wma_handle, + struct wma_txrx_node *iface, + struct ieee80211_frame *wh, + cds_pkt_t *rx_pkt, + cdf_nbuf_t wbuf) +{ + uint8_t *efrm, *orig_hdr; + uint16_t key_id; + uint8_t *ccmp; + + if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) { + if (IEEE80211_IS_BROADCAST(wh->i_addr1) || + IEEE80211_IS_MULTICAST(wh->i_addr1)) { + WMA_LOGE("Encrypted BC/MC frame dropping the frame"); + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + + orig_hdr = (uint8_t *) cdf_nbuf_data(wbuf); + /* Pointer to head of CCMP header */ + ccmp = orig_hdr + sizeof(*wh); + if (wma_is_ccmp_pn_replay_attack( + wma_handle, wh, ccmp)) { + WMA_LOGE("Dropping the frame"); + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + + /* Strip privacy headers (and trailer) + * for a received frame + */ + cdf_mem_move(orig_hdr + + IEEE80211_CCMP_HEADERLEN, wh, + sizeof(*wh)); + cdf_nbuf_pull_head(wbuf, + IEEE80211_CCMP_HEADERLEN); + cdf_nbuf_trim_tail(wbuf, IEEE80211_CCMP_MICLEN); + + rx_pkt->pkt_meta.mpdu_hdr_ptr = + cdf_nbuf_data(wbuf); + rx_pkt->pkt_meta.mpdu_len = cdf_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_meta.tsf_delta = rx_pkt->pkt_meta.tsf_delta; + rx_pkt->pkt_buf = wbuf; + WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"), + MAC_ADDR_ARRAY(wh->i_addr3), rx_pkt->pkt_meta.tsf_delta); + } else { + if (IEEE80211_IS_BROADCAST(wh->i_addr1) || + IEEE80211_IS_MULTICAST(wh->i_addr1)) { + efrm = cdf_nbuf_data(wbuf) + + cdf_nbuf_len(wbuf); + + key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2); + if (!((key_id == WMA_IGTK_KEY_INDEX_4) + || (key_id == WMA_IGTK_KEY_INDEX_5))) { + WMA_LOGE("Invalid KeyID(%d) dropping the frame", key_id); + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + + if (cds_is_mmie_valid(iface->key.key, + iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, + (uint8_t *) wh, efrm)) { + WMA_LOGE("Protected BC/MC frame MMIE validation successful"); + /* Remove MMIE */ + cdf_nbuf_trim_tail(wbuf, + cds_get_mmie_size()); + } else { + WMA_LOGE("BC/MC MIC error or MMIE not present, dropping the frame"); + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + } else { + WMA_LOGE("Rx unprotected unicast mgmt frame"); + rx_pkt->pkt_meta.dpuFeedback = + DPU_FEEDBACK_UNPROTECTED_ERROR; + } + } + return 0; +} +#endif + +/** + * wma_mgmt_rx_process() - process management rx frame. + * @handle: wma handle + * @data: rx data + * @data_len: data length + * + * Return: 0 for success or error code + */ +static int wma_mgmt_rx_process(void *handle, uint8_t *data, + uint32_t data_len) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL; + wmi_mgmt_rx_hdr *hdr = NULL; + struct wma_txrx_node *iface = NULL; + uint8_t vdev_id; + cds_pkt_t *rx_pkt; + cdf_nbuf_t wbuf; + struct ieee80211_frame *wh; + uint8_t mgt_type, mgt_subtype; + int status; + + if (!wma_handle) { + WMA_LOGE("%s: Failed to get WMA context", __func__); + return -EINVAL; + } + + param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *) data; + if (!param_tlvs) { + WMA_LOGE("Get NULL point message from FW"); + return -EINVAL; + } + + hdr = param_tlvs->hdr; + if (!hdr) { + WMA_LOGE("Rx event is NULL"); + return -EINVAL; + } + + if (hdr->buf_len < sizeof(struct ieee80211_frame)) { + WMA_LOGE("Invalid rx mgmt packet"); + return -EINVAL; + } + + rx_pkt = cdf_mem_malloc(sizeof(*rx_pkt)); + if (!rx_pkt) { + WMA_LOGE("Failed to allocate rx packet"); + return -ENOMEM; + } + + cdf_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 absolute rssi value from the current rssi value + *the sinr value is hardcoded into 0 in the core stack*/ + rx_pkt->pkt_meta.rssi = hdr->snr + WMA_TGT_NOISE_FLOOR_DBM; + rx_pkt->pkt_meta.snr = hdr->snr; + /* + * 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 = (uint32_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; + + rx_pkt->pkt_meta.roamCandidateInd = 0; + + /* Why not just use rx_event->hdr.buf_len? */ + wbuf = cdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false); + if (!wbuf) { + WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)", + __func__, hdr->buf_len); + cdf_mem_free(rx_pkt); + return -ENOMEM; + } + + cdf_nbuf_put_tail(wbuf, hdr->buf_len); + cdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL); + wh = (struct ieee80211_frame *)cdf_nbuf_data(wbuf); + + rx_pkt->pkt_meta.mpdu_hdr_ptr = cdf_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; + + WMA_LOGD(FL("BSSID: "MAC_ADDRESS_STR" tsf_delta: %u"), + MAC_ADDR_ARRAY(wh->i_addr3), hdr->tsf_delta); + +#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; + uint32_t *destp, *srcp; + destp = (uint32_t *) wh; + srcp = (uint32_t *) param_tlvs->bufp; + for (i = 0; + i < (roundup(hdr->buf_len, sizeof(uint32_t)) / 4); i++) { + *destp = cpu_to_le32(*srcp); + destp++; + srcp++; + } + } +#else + cdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len); +#endif + + if (!wma_handle->mgmt_rx) { + WMA_LOGE("Not registered for Mgmt rx, dropping the frame"); + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } + + /* 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; + + iface = wma_find_vdev_by_addr(wma_handle, wh->i_addr3, &vdev_id); + rx_pkt->pkt_meta.sessionId = vdev_id; + +#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)) { + if (iface && iface->rmfEnabled) { + status = wma_process_rmf_frame(wma_handle, + iface, wh, rx_pkt, wbuf); + if (status != 0) + return status; + } + } +#endif /* WLAN_FEATURE_11W */ + wma_handle->mgmt_rx(wma_handle, rx_pkt); + return 0; +} + +/** + * wma_de_register_mgmt_frm_client() - deregister management frame + * @cds_ctx: cds context + * + * Return: CDF status + */ +CDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx) +{ + tp_wma_handle wma_handle; + +#ifdef QCA_WIFI_FTM + if (cds_get_conparam() == CDF_FTM_MODE) + return CDF_STATUS_SUCCESS; +#endif + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma_handle) { + WMA_LOGE("%s: Failed to get WMA context", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (wmi_unified_unregister_event_handler(wma_handle->wmi_handle, + WMI_MGMT_RX_EVENTID) != 0) { + WMA_LOGE("Failed to Unregister rx mgmt handler with wmi"); + return CDF_STATUS_E_FAILURE; + } + wma_handle->mgmt_rx = NULL; + return CDF_STATUS_SUCCESS; +} + +/** + * wma_register_mgmt_frm_client() - register management frame callback + * @cds_ctx: cds context + * @mgmt_frm_rx: management frame + * + * Return: CDF status + */ +CDF_STATUS wma_register_mgmt_frm_client( + void *cds_ctx, wma_mgmt_frame_rx_callback mgmt_frm_rx) +{ + tp_wma_handle wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (!wma_handle) { + WMA_LOGE("%s: Failed to get WMA context", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_MGMT_RX_EVENTID, + wma_mgmt_rx_process) != 0) { + WMA_LOGE("Failed to register rx mgmt handler with wmi"); + return CDF_STATUS_E_FAILURE; + } + wma_handle->mgmt_rx = mgmt_frm_rx; + + return CDF_STATUS_SUCCESS; +} diff --git a/core/wma/src/wma_ocb.c b/core/wma/src/wma_ocb.c new file mode 100644 index 000000000000..15d321202aab --- /dev/null +++ b/core/wma/src/wma_ocb.c @@ -0,0 +1,1119 @@ +/* + * 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 "cds_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) +{ + CDF_STATUS cdf_status; + struct sir_ocb_set_config_response *resp; + cds_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 : NULL); + + /* + * If the command was successful, save the channel information in the + * vdev. + */ + if (status == CDF_STATUS_SUCCESS && vdev && req) { + if (vdev->ocb_channel_info) + cdf_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 = + cdf_mem_malloc(buf_size); + cdf_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. */ + cdf_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = NULL; + + resp = cdf_mem_malloc(sizeof(*resp)); + if (!resp) + return -ENOMEM; + + resp->status = status; + + msg.type = eWNI_SME_OCB_SET_CONFIG_RSP; + msg.bodyptr = resp; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Fail to post msg to SME")); + cdf_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 = cdf_mem_malloc(length); + if (!dst) + return NULL; + + *dst = *src; + + cursor = dst; + cursor += sizeof(*dst); + dst->channels = cursor; + cursor += src->channel_count * sizeof(*dst->channels); + cdf_mem_copy(dst->channels, src->channels, + src->channel_count * sizeof(*dst->channels)); + dst->schedule = cursor; + cursor += src->schedule_size * sizeof(*dst->schedule); + cdf_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; + cdf_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; + cdf_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; + CDF_STATUS status = CDF_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) { + cdf_mem_zero(&req, sizeof(req)); + /* Enqueue OCB Set Schedule request message */ + msg = wma_fill_vdev_req(wma_handle, config_req->session_id, + WMA_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 = CDF_STATUS_E_NOMEM; + return status; + } + req.chan = cds_freq_to_chan(config_req->channels[0].chan_freq); + req.vdev_id = msg->vdev_id; + if (cds_chan_to_band(req.chan) == CDS_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) + cdf_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = copy_sir_ocb_config(config_req); + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + + status = wma_vdev_start(wma_handle, &req, false); + if (status != CDF_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) +{ + CDF_STATUS cdf_status = 0; + + if (!wma_handle->ocb_config_req) { + WMA_LOGE(FL("The request could not be found")); + return CDF_STATUS_E_EMPTY; + } + + cdf_status = wma_ocb_set_config(wma_handle, wma_handle->ocb_config_req); + return cdf_status; +} + +static WLAN_PHY_MODE wma_ocb_freq_to_mode(uint32_t freq) +{ + if (cds_chan_to_band(cds_freq_to_chan(freq)) == CDS_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; + cdf_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; + cdf_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) + cdf_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) { + cdf_mem_free(wma_handle->ocb_config_req); + wma_handle->ocb_config_req = NULL; + } + + 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); + cdf_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) +{ + CDF_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; + cdf_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) +{ + CDF_STATUS cdf_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; + cds_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 = cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + cdf_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + cdf_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; + cdf_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) +{ + CDF_STATUS cdf_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; + cds_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 = cdf_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); + cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + cdf_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); + cdf_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) +{ + CDF_STATUS cdf_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 CDF_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 CDF_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); + cdf_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; + cdf_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; + cdf_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 */ + cdf_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 (cdf_status) { + WMA_LOGE(FL("Failed to send WMI message: %d"), cdf_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) +{ + CDF_STATUS cdf_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; + cds_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 = cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + cdf_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) +{ + CDF_STATUS cdf_status; + struct sir_dcc_get_stats_response *response; + WMI_DCC_STATS_EVENTID_param_tlvs *param_tlvs; + wmi_dcc_stats_event_fixed_param *fix_param; + cds_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 = cdf_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); + cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Failed to post msg to SME")); + cdf_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 CDF_STATUS_SUCCESS; +} diff --git a/core/wma/src/wma_ocb.h b/core/wma/src/wma_ocb.h new file mode 100644 index 000000000000..c2e5ae37ebe7 --- /dev/null +++ b/core/wma/src/wma_ocb.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. + */ + +#ifndef __WMA_OCB_H +#define __WMA_OCB_H + +#include "wma.h" +#include "sir_api.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/core/wma/src/wma_power.c b/core/wma/src/wma_power.c new file mode 100644 index 000000000000..59e79759b011 --- /dev/null +++ b/core/wma/src/wma_power.c @@ -0,0 +1,2250 @@ +/* + * 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_power.c + * This file contains powersave related functions. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +/** + * wmi_unified_modem_power_state() - set modem power state to fw + * @wmi_handle: wmi handle + * @param_value: parameter value + * + * Return: 0 for success or error code + */ +static int +wmi_unified_modem_power_state(wmi_unified_t wmi_handle, uint32_t param_value) +{ + int ret; + wmi_modem_power_state_cmd_param *cmd; + wmi_buf_t buf; + uint16_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; +} + +/** + * wmi_unified_set_sta_ps_param() - set sta power save parameter to fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @param: param + * @value: parameter value + * + * Return: 0 for success or error code. + */ +int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle, + uint32_t vdev_id, uint32_t param, + uint32_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 = cds_get_context(CDF_MODULE_ID_WMA); + 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); + cdf_nbuf_free(buf); + return -EIO; + } + /* Store the PS Status */ + iface->ps_enabled = value ? true : false; + return 0; +} + +#ifdef QCA_IBSS_SUPPORT +/** + * wma_set_ibss_pwrsave_params() - set ibss power save parameter to fw + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: 0 for success or error code. + */ +CDF_STATUS +wma_set_ibss_pwrsave_params(tp_wma_handle wma, uint8_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 CDF_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 CDF_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 CDF_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 CDF_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 CDF_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 CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* QCA_IBSS_SUPPORT */ + +/** + * wmi_unified_set_ap_ps_param() - set ap powersave parameters + * @wma_ctx: wma context + * @vdev_id: vdev id + * @peer_addr: peer mac address + * @param: parameter + * @value: prameter value + * + * Return: 0 for success or error code + */ +static int32_t wmi_unified_set_ap_ps_param(void *wma_ctx, uint32_t vdev_id, + uint8_t *peer_addr, uint32_t param, + uint32_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"); + cdf_mem_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_set_ap_peer_uapsd() - set powersave parameters in ap mode to fw + * @wma: wma handle + * @vdev_id: vdev id + * @peer_addr: peer mac address + * @uapsd_value: uapsd value + * @max_sp: maximum service period + * + * Return: 0 for success or error code. + */ +int32_t wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id, + uint8_t *peer_addr, uint8_t uapsd_value, + uint8_t max_sp) +{ + uint32_t uapsd = 0; + uint32_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; +} + +/** + * wma_update_edca_params_for_ac() - to update per ac EDCA parameters + * @edca_param: EDCA parameters + * @wmm_param: wmm parameters + * @ac: access category + * + * Return: none + */ +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); +} + +/** + * wma_set_tx_power() - set tx power limit in fw + * @handle: wma handle + * @tx_pwr_params: tx power parameters + * + * Return: none + */ +void wma_set_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + uint8_t vdev_id; + int ret = -1; + void *pdev; + + if (tx_pwr_params->dev_mode == CDF_SAP_MODE || + tx_pwr_params->dev_mode == CDF_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); + cdf_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); + cdf_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: + cdf_mem_free(tx_pwr_params); + if (ret) + WMA_LOGE("Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT"); +} + +/** + * wma_set_max_tx_power() - set max tx power limit in fw + * @handle: wma handle + * @tx_pwr_params: tx power parameters + * + * Return: none + */ +void wma_set_max_tx_power(WMA_HANDLE handle, + tMaxTxPowerParams *tx_pwr_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + uint8_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); + cdf_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); + cdf_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: + cdf_mem_free(tx_pwr_params); + if (ret) + WMA_LOGE("%s: Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT", + __func__); +} + +/** + * wmi_unified_set_sta_ps() - set sta powersave params in fw + * @handle: wma handle + * @vdev_id: vdev id + * @val: value + * + * Return: 0 for success or error code. + */ +int32_t wmi_unified_set_sta_ps(wmi_unified_t wmi_handle, + uint32_t vdev_id, uint8_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); + cdf_nbuf_free(buf); + return -EIO; + } + return 0; +} + +/** + * wma_get_uapsd_mask() - get uapsd mask based on uapsd parameters + * @uapsd_params: uapsed parameters + * + * Return: uapsd mask + */ +static inline uint32_t wma_get_uapsd_mask(tpUapsd_Params uapsd_params) +{ + uint32_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; +} + +/** + * wma_set_force_sleep() - set power save parameters to fw + * @wma: wma handle + * @vdev_id: vdev id + * @enable: enable/disable + * @qpower_config: qpower configuration + * + * Return: 0 for success or error code + */ +static int32_t wma_set_force_sleep(tp_wma_handle wma, + uint32_t vdev_id, + uint8_t enable, + enum powersave_qpower_mode qpower_config) +{ + int32_t ret; + uint32_t cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + uint32_t rx_wake_policy; + uint32_t tx_wake_threshold; + uint32_t pspoll_count; + uint32_t inactivity_time; + uint32_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_cfg_get_int(mac, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT"); + cfg_data_val = POWERSAVE_DEFAULT_INACTIVITY_TIME; + } + inactivity_time = (uint32_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_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_MAX_PS_POLL"); + } + if (cfg_data_val) + pspoll_count = (uint32_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_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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 = (uint32_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_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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_set_qpower_force_sleep() - set qpower params in fw + * @wma: wma handle + * @vdev_id: vdev id + * @enable: value + * + * Return: 0 for success or error code. + */ +int32_t wma_set_qpower_force_sleep(tp_wma_handle wma, uint32_t vdev_id, + uint8_t enable) +{ + int32_t ret; + uint32_t cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + uint32_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_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_MAX_PS_POLL"); + } + if (cfg_data_val) { + pspoll_count = (uint32_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_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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; + } +} + +/** + * wma_enable_sta_ps_mode() - enable sta powersave params in fw + * @wma: wma handle + * @ps_req: power save request + * + * Return: none + */ +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 (!iface->handle) { + WMA_LOGE("vdev id %d is not active", vdev_id); + return; + } + 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); + return; + } + + ret = wma_set_force_sleep(wma, vdev_id, false, + qpower_config); + if (ret) { + WMA_LOGE("Enable Sta Ps Failed vdevId %d", vdev_id); + return; + } + } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) { + uint32_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); + return; + } + /* 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); + return; + } + } + iface->dtimPeriod = ps_req->bcnDtimPeriod; +} + +/** + * wma_disable_sta_ps_mode() - disable sta powersave params in fw + * @wma: wma handle + * @ps_req: power save request + * + * Return: none + */ +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); + return; + } + + /* 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 + */ + } + } +} + +/** + * wma_enable_uapsd_mode() - enable uapsd mode in fw + * @wma: wma handle + * @ps_req: power save request + * + * Return: none + */ +void wma_enable_uapsd_mode(tp_wma_handle wma, tpEnableUapsdParams ps_req) +{ + int32_t ret; + uint32_t vdev_id = ps_req->sessionid; + uint32_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); + return; + } + + 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); + return; + } + + 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); + return; + } + +} + +/** + * wma_disable_uapsd_mode() - disable uapsd mode in fw + * @wma: wma handle + * @ps_req: power save request + * + * Return: none + */ +void wma_disable_uapsd_mode(tp_wma_handle wma, + tpDisableUapsdParams ps_req) +{ + int32_t ret; + uint32_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); + return; + } + + 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); + return; + } + + /* 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); + return; + } +} + +/** + * wmi_unified_set_sta_uapsd_auto_trig_cmd() - set uapsd auto trigger command + * @wmi_handle: wma handle + * @vdevid: vdev id + * @peer_addr: peer mac address + * @autoTriggerparam: auto trigger parameters + * @num_ac: number of access category + * + * 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. + * + * Return: 0 for success or error code. + */ +int32_t +wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle, + uint32_t vdevid, + uint8_t peer_addr[IEEE80211_ADDR_LEN], + uint8_t *autoTriggerparam, + uint32_t num_ac) +{ + wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd; + int32_t ret; + uint32_t param_len = num_ac * sizeof(wmi_sta_uapsd_auto_trig_param); + uint32_t cmd_len = sizeof(*cmd) + param_len + WMI_TLV_HDR_SIZE; + uint32_t i; + wmi_buf_t buf; + uint8_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 = (uint8_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; + cdf_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; +} + +/** + * wma_trigger_uapsd_params() - set trigger uapsd parameter + * @wmi_handle: wma handle + * @vdev_id: vdev id + * @trigger_uapsd_params: trigger uapsd parameters + * + * 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. + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_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 CDF_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, + (uint8_t *) (&uapsd_trigger_param), 1); + if (ret) { + WMA_LOGE("Fail to send uapsd param cmd for vdevid %d ret = %d", + ret, vdev_id); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_disable_uapsd_per_ac() - disable uapsd per ac + * @wmi_handle: wma handle + * @vdev_id: vdev id + * @ac: access category + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle, + uint32_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 CDF_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, + (uint8_t *)(&uapsd_trigger_param), 1); + if (ret) { + WMA_LOGE("Fail to send auto trig cmd for vdevid %d ret = %d", + ret, vdev_id); + return CDF_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 CDF_STATUS_E_FAILURE; + } + WMA_LOGD("Disable Uapsd per ac vdevId %d val %d", vdev_id, + iface->uapsd_cached_val); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_temperature() - get pdev temperature req + * @wmi_handle: wma handle + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_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); + uint8_t *buf_ptr; + + if (!wma_handle) { + WMA_LOGE(FL("WMA is closed, can not issue cmd")); + return CDF_STATUS_E_INVAL; + } + + wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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 CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_pdev_temperature_evt_handler() - pdev temperature event handler + * @handle: wma handle + * @event: event buffer + * @len : length + * + * Return: 0 for success or error code. + */ +int wma_pdev_temperature_evt_handler(void *handle, uint8_t *event, + uint32_t len) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE(FL("Fail to post get temperature ind msg")); + } + + return 0; +} + +/** + * wma_process_tx_power_limits() - sends the power limits for 2g/5g to firmware + * @handle: wma handle + * @ptxlim: power limit value + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_process_tx_power_limits(WMA_HANDLE handle, + tSirTxPowerLimit *ptxlim) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + int32_t ret = 0; + uint32_t txpower_params2g = 0; + uint32_t txpower_params5g = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue tx power limit", + __func__); + return CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_add_p2p_ie() - add p2p IE + * @frm: ptr where p2p ie needs to add + * + * Return: ptr after p2p ie + */ +uint8_t *wma_add_p2p_ie(uint8_t *frm) +{ + uint8_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); +} + +/** + * wma_update_beacon_noa_ie() - update beacon ie + * @bcn: beacon info + * @new_noa_sub_ie_len: ie length + * + * Return: none + */ +static void wma_update_beacon_noa_ie(struct beacon_info *bcn, + uint16_t new_noa_sub_ie_len) +{ + struct p2p_ie *p2p_ie; + uint8_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 */ + cdf_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)); + cdf_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 = cdf_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; + cdf_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); +} + +/** + * wma_p2p_create_sub_ie_noa() - put p2p noa ie + * @buf: buffer + * @noa: noa element ie + * @new_noa_sub_ie_len: ie length + * + * Return: none + */ +static void wma_p2p_create_sub_ie_noa(uint8_t *buf, + struct p2p_sub_element_noa *noa, + uint16_t *new_noa_sub_ie_len) +{ + uint8_t tmp_octet = 0; + int i; + uint8_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); +} + +/** + * wma_update_noa() - update noa params + * @beacon: beacon info + * @noa_ie: noa ie + * + * Return: none + */ +void wma_update_noa(struct beacon_info *beacon, + struct p2p_sub_element_noa *noa_ie) +{ + uint16_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); +} + +/** + * wma_update_probe_resp_noa() - update noa IE in probe response + * @wma_handle: wma handle + * @noa_ie: noa ie + * + * Return: none + */ +void wma_update_probe_resp_noa(tp_wma_handle wma_handle, + struct p2p_sub_element_noa *noa_ie) +{ + tSirP2PNoaAttr *noa_attr = + (tSirP2PNoaAttr *) cdf_mem_malloc(sizeof(tSirP2PNoaAttr)); + WMA_LOGD("Received update NoA event"); + if (!noa_attr) { + WMA_LOGE("Failed to allocate memory for tSirP2PNoaAttr"); + return; + } + + cdf_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); +} + +/** + * wma_p2p_noa_event_handler() - p2p noa event handler + * @handle: wma handle + * @event: event data + * @len: length + * + * Return: 0 for success or error code. + */ +int wma_p2p_noa_event_handler(void *handle, uint8_t *event, + uint32_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; + uint8_t vdev_id, i; + wmi_p2p_noa_info *p2p_noa_info; + struct p2p_sub_element_noa noa_ie; + uint8_t *buf_ptr; + uint32_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 = (uint8_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)) { + + cdf_mem_zero(&noa_ie, sizeof(noa_ie)); + noa_ie.index = + (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info); + noa_ie.oppPS = + (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info); + noa_ie.ctwindow = + (uint8_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 = (uint8_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 = + (uint8_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; +} + +/** + * wma_set_p2pgo_noa_req() - send p2p go noa request to fw + * @wma: wma handle + * @noa: p2p power save parameters + * + * Return: none + */ +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; + uint8_t *buf_ptr; + uint16_t len; + int32_t status; + uint32_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 = (uint8_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__); +} + +/** + * wma_set_p2pgo_oppps_req() - send p2p go opp power save request to fw + * @wma: wma handle + * @noa: p2p opp power save parameters + * + * Return: none + */ +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__); +} + +/** + * wma_process_set_p2pgo_noa_req() - process p2pgo noa request + * @handle: wma handle + * @ps_params: powersave params + * + * Return: none + */ +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__); +} + +/** + * wma_process_set_mimops_req() - Set the received MiMo PS state to firmware + * @handle: wma handle + * @mimops: MIMO powersave params + * + * Return: none + */ +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); +} + +/** + * wma_set_mimops() - set MIMO powersave + * @handle: wma handle + * @vdev_id: vdev id + * @value: value + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_set_mimops(tp_wma_handle wma, uint8_t vdev_id, int value) +{ + int ret = CDF_STATUS_SUCCESS; + wmi_sta_smps_force_mode_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_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; + + 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 CDF_STATUS_E_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; +} + +/** + * wma_notify_modem_power_state() - notify modem power state + * @wma_ptr: wma handle + * @pReq: modem power state + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_notify_modem_power_state(void *wma_ptr, + tSirModemPowerStateInd *pReq) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle) wma_ptr; + + 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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Successfully notify Modem Power State %d", pReq->param); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_idle_ps_config() - enable/disble Low Power Support(Pdev Specific) + * @wma_ptr: wma handle + * @idle_ps: idle powersave + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle) wma_ptr; + + 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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Successfully Set Idle Ps Config %d", idle_ps); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_smps_params() - set smps params + * @wma: wma handle + * @vdev_id: vdev id + * @value: value + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_set_smps_params(tp_wma_handle wma, uint8_t vdev_id, + int value) +{ + int ret = CDF_STATUS_SUCCESS; + wmi_sta_smps_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_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; +} + +/** + * wma_set_vdev_suspend_dtim() - set suspend dtim parameters in fw + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, uint8_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; + uint32_t listen_interval; + uint32_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; + } + + 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); + } + + WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, listen_interval); + + 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) + WMA_LOGE("Failed to Set to Normal DTIM vdevId %d", + vdev_id); + + /* Set it to Normal DTIM */ + iface->dtim_policy = NORMAL_DTIM; + WMA_LOGD("Set DTIM Policy to Normal Dtim vdevId %d", vdev_id); + } +} + +/** + * wma_set_suspend_dtim() - set suspend dtim + * @wma: wma handle + * + * Return: none + */ +void wma_set_suspend_dtim(tp_wma_handle wma) +{ + uint8_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); + } + } +} + +/** + * wma_set_vdev_resume_dtim() - set resume dtim parameters in fw + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +static void wma_set_vdev_resume_dtim(tp_wma_handle wma, uint8_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; + uint32_t cfg_data_val = 0; + /* get mac to acess CFG data base */ + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + /* Set Listen Interval */ + if ((NULL == mac) || (wlan_cfg_get_int(mac, + WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val) != + eSIR_SUCCESS)) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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!"); + } + } +} + +/** + * wma_set_resume_dtim() - set resume dtim + * @wma: wma handle + * + * Return: none + */ +void wma_set_resume_dtim(tp_wma_handle wma) +{ + uint8_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); + } + } +} + diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c new file mode 100644 index 000000000000..708202473f97 --- /dev/null +++ b/core/wma/src/wma_scan_roam.c @@ -0,0 +1,6886 @@ +/* + * 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_scan_roam.c + * This file contains functions related to scan and + * roaming functionality. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +/* FIXME: Inclusion of .c looks odd but this is how it is in internal codebase */ +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +#define WMA_MCC_MIRACAST_REST_TIME 400 +#define WMA_SCAN_ID_MASK 0x0fff + +#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 + +/** + * wma_set_p2p_scan_info() - set p2p scan info in wma handle + * @wma_handle: wma handle + * @scan_id: scan id + * @vdev_id: vdev id + * @p2p_scan_type: p2p scan type + * + * Return: none + */ +static inline void wma_set_p2p_scan_info(tp_wma_handle wma_handle, + uint32_t scan_id, + uint32_t vdev_id, + tSirP2pScanType p2p_scan_type) +{ + wma_handle->interfaces[vdev_id].p2p_scan_info.scan_id = scan_id; + wma_handle->interfaces[vdev_id].p2p_scan_info.p2p_scan_type = + p2p_scan_type; +} + +/** + * wma_reset_p2p_scan_info() - reset scan info from wma handle + * @wma_handle: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +static inline void wma_reset_p2p_scan_info(tp_wma_handle wma_handle, + uint8_t vdev_id) +{ + cdf_mem_zero((void *)&(wma_handle->interfaces[vdev_id].p2p_scan_info), + sizeof(struct p2p_scan_param)); +} + +/** + * wma_is_mcc_24G() - check that if device is in 2.4GHz MCC + * @handle: wma handle + * + * Return: true/false + */ +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 <= + CDS_CHAN_14_FREQ)) + return true; + else + prev_chan = wma_handle->interfaces[i].mhz; + } + } + return false; +} + +/** + * wma_get_buf_start_scan_cmd() - Fill start scan command + * @wma_handle: wma handle + * @scan_req: scan request + * @buf: wmi buffer to be filled in + * @buf_len: buf length + * + * Fill individual elements of wmi_start_scan_req and TLV for + * channel list, bssid, ssid etc. + * + * Return: CDF status + */ +CDF_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; + uint32_t *tmp_ptr, ie_len_with_pad; + CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; + uint8_t *buf_ptr; + uint32_t dwell_time; + uint8_t SSID_num; + int i; + int len = sizeof(*cmd); + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + + if (!pMac) { + WMA_LOGP("%s: pMac is NULL!", __func__); + return CDF_STATUS_E_FAILURE; + } + + len += WMI_TLV_HDR_SIZE; /* Length TLV placeholder for array of uint32_t */ + /* calculate the length of buffer required */ + if (scan_req->channelList.numChannels) + len += scan_req->channelList.numChannels * sizeof(uint32_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(uint32_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 CDF_STATUS_E_FAILURE; + } + + buf_ptr = (uint8_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)); + + cmd->vdev_id = scan_req->sessionId; + /* + * host cycles through the lower 12 bits for scan id generation + * and prefix 0xA000 to scan id + */ + if (scan_req->scan_id < WMA_HOST_SCAN_REQID_PREFIX) { + WMA_LOGE("Received scan_id 0x%x is wrong", + cmd->scan_id); + scan_req->scan_id = scan_req->scan_id & WMA_SCAN_ID_MASK; + /* Appending the 0xA000 to scan Id*/ + cmd->scan_id = scan_req->scan_id | WMA_HOST_SCAN_REQID_PREFIX; + } else { + cmd->scan_id = scan_req->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_cfg_get_int(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 only one value restTime 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 at least half + * of the requested time and then leave if there is no traffic. + */ + cmd->min_rest_time = scan_req->restTime / 2; + 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 = WMA_SCAN_IDLE_TIME_DEFAULT; + + /* Large timeout value for full scan cycle, 30 seconds */ + cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; + + /* do not add OFDM rates in 11B mode */ + if (scan_req->dot11mode != WNI_CFG_DOT11_MODE_11B) + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; + else + WMA_LOGD("OFDM_RATES not included in 11B mode"); + + /* Do not combine multiple channels in a single burst. Come back + * to home channel for data traffic after every foreign channel. + * By default, prefer throughput performance over scan cycle time. + */ + cmd->burst_duration = 0; + + if (!scan_req->p2pScanType) { + WMA_LOGD("Normal Scan request"); + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; + if (!scan_req->numSsid) + cmd->scan_ctrl_flags |= WMI_SCAN_ADD_BCAST_PROBE_REQ; + if (scan_req->scanType == eSIR_PASSIVE_SCAN) + cmd->scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; + cmd->scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; + + /* + * Decide burst_duration and dwell_time_active based on + * what type of devices are active. + */ + do { + if (wma_is_sap_active(wma_handle) && + wma_is_p2p_go_active(wma_handle) && + wma_is_sta_active(wma_handle)) { + if (scan_req->maxChannelTime <= + WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION) + cmd->burst_duration = + scan_req->maxChannelTime; + else + cmd->burst_duration = + WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION; + break; + } + if (wma_is_sap_active(wma_handle)) { + /* Background scan while SoftAP is sending beacons. + * Max duration of CTS2self is 32 ms, which limits + * the dwell time. + */ + cmd->dwell_time_active = + CDF_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) { + uint8_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) { + uint8_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 = (uint32_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] = + cds_chan_to_freq(scan_req->channelList. + channelNumber[i]); + } + } + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_UINT32, + (cmd->num_chan * sizeof(uint32_t))); + buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_chan * sizeof(uint32_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; + cdf_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 = probe_time_dwell_time_map[ + CDF_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(uint32_t)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_with_pad); + if (scan_req->uIEFieldLen) { + cdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, + (uint8_t *) scan_req + + (scan_req->uIEFieldOffset), scan_req->uIEFieldLen); + } + buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad; + + *buf_len = len; + return CDF_STATUS_SUCCESS; +error: + cdf_mem_free(*buf); + *buf = NULL; + return cdf_status; +} + +/** + * wma_get_buf_stop_scan_cmd() - Fill stop scan command + * @wma_handle: wma handle + * @buf: wmi buffer to be filled in + * @buf_len: buf length + * @abort_scan_req: abort scan request + * + * Fill wmi_stop_scan_cmd buffer. + * + * Return: CDF status + */ +CDF_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; + CDF_STATUS cdf_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__); + cdf_status = CDF_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_HOST_SCAN_REQUESTOR_ID_PREFIX | + WMA_DEFAULT_SCAN_REQUESTER_ID; + cmd->scan_id = abort_scan_req->scan_id; + /* stop the scan with the corresponding scan_id */ + cmd->req_type = WMI_SCAN_STOP_ONE; + + *buf_len = len; + cdf_status = CDF_STATUS_SUCCESS; +error: + return cdf_status; + +} + + +/** + * wma_start_scan() - start scan command + * @wma_handle: wma handle + * @scan_req: scan request params + * @msg_type: message time + * + * Send start scan command to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_start_scan(tp_wma_handle wma_handle, + tSirScanOffloadReq *scan_req, uint16_t msg_type) +{ + uint32_t vdev_id, scan_id; + CDF_STATUS cdf_status = CDF_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 error; + } + + /* Sanity check to find whether vdev id active or not */ + if (msg_type != WMA_START_SCAN_OFFLOAD_REQ && + !wma_handle->interfaces[scan_req->sessionId].handle) { + WMA_LOGA("vdev id [%d] is not active", scan_req->sessionId); + goto error; + } + + /* Fill individual elements of wmi_start_scan_req and + * TLV for channel list, bssid, ssid etc ... */ + cdf_status = wma_get_buf_start_scan_cmd(wma_handle, scan_req, + &buf, &len); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to get buffer for start scan cmd"); + goto error; + } + + if (NULL == buf) { + WMA_LOGE("Failed to get buffer for saving current scan info"); + goto error; + } + + /* Save current scan info */ + cmd = (wmi_start_scan_cmd_fixed_param *) wmi_buf_data(buf); + if (msg_type == WMA_CHNL_SWITCH_REQ) { + /* Adjust parameters for channel switch scan */ + cmd->min_rest_time = WMA_ROAM_PREAUTH_REST_TIME; + cmd->max_rest_time = WMA_ROAM_PREAUTH_REST_TIME; + cmd->max_scan_time = WMA_ROAM_PREAUTH_MAX_SCAN_TIME; + cmd->scan_priority = WMI_SCAN_PRIORITY_HIGH; + cmd->scan_id = scan_req->scan_id; + wma_handle->roam_preauth_scan_id = cmd->scan_id; + } + if (scan_req->p2pScanType == P2P_SCAN_TYPE_LISTEN) + wma_set_p2p_scan_info(wma_handle, cmd->scan_id, + cmd->vdev_id, P2P_SCAN_TYPE_LISTEN); + WMA_LOGE("scan_id 0x%x, vdev_id %d, p2pScanType %d, msg_type 0x%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; + WMA_LOGI("ActiveDwell %d, PassiveDwell %d, ScanFlags 0x%x NumChan %d", + cmd->dwell_time_active, cmd->dwell_time_passive, + cmd->scan_ctrl_flags, cmd->num_chan); + + 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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("WMA --> WMI_START_SCAN_CMDID"); + + return CDF_STATUS_SUCCESS; +error: + /* Send completion event for only for start scan request */ + if (msg_type == WMA_START_SCAN_OFFLOAD_REQ) { + scan_event = + (tSirScanOffloadEvent *) + cdf_mem_malloc(sizeof(tSirScanOffloadEvent)); + if (!scan_event) { + WMA_LOGP("%s: Failed to allocate memory for scan rsp", + __func__); + return CDF_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->sessionId = scan_req->sessionId; + scan_event->p2pScanType = scan_req->p2pScanType; + scan_event->scanId = scan_req->scan_id; + wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event, + 0); + } + return cdf_status; +} + +/** + * wma_stop_scan() - stop scan command + * @wma_handle: wma handle + * @abort_scan_req: abort scan params + * + * Send stop scan command to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_stop_scan(tp_wma_handle wma_handle, + tAbortScanParams *abort_scan_req) +{ + CDF_STATUS cdf_status; + wmi_buf_t buf; + int status = 0; + int len; + + cdf_status = wma_get_buf_stop_scan_cmd(wma_handle, &buf, &len, + abort_scan_req); + if (cdf_status != CDF_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"); + cdf_status = CDF_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + WMA_LOGE("scan_id %x, vdev_id %x", + abort_scan_req->scan_id, abort_scan_req->SessionId); + WMA_LOGI("WMA --> WMI_STOP_SCAN_CMDID"); + + return CDF_STATUS_SUCCESS; +error: + if (buf) + cdf_nbuf_free(buf); +error1: + return cdf_status; +} + +/** + * wma_update_channel_list() - update channel list + * @handle: wma handle + * @chan_list: channel list + * + * Function is used to update the support channel list in fw. + * + * Return: CDF status + */ +CDF_STATUS wma_update_channel_list(WMA_HANDLE handle, + tSirUpdateChanList *chan_list) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_buf_t buf; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_scan_chan_list_cmd_fixed_param *cmd; + int status, i; + uint8_t *buf_ptr; + wmi_channel *chan_info; + uint16_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"); + cdf_status = CDF_STATUS_E_NOMEM; + goto end; + } + + buf_ptr = (uint8_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); + + 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 = + cds_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_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); + + 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); + + 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) { + cdf_status = CDF_STATUS_E_FAILURE; + WMA_LOGE("Failed to send WMI_SCAN_CHAN_LIST_CMDID"); + wmi_buf_free(buf); + } +end: + return cdf_status; +} + + +/** + * wma_roam_scan_offload_mode() - send roam scan mode request to fw + * @wma_handle: wma handle + * @scan_cmd_fp: start scan command ptr + * @roam_req: roam request param + * @mode: mode + * @vdev_id: vdev id + * + * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback + * of WMI_ROAM_SCAN_MODE. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_mode(tp_wma_handle wma_handle, + wmi_start_scan_cmd_fixed_param * + scan_cmd_fp, + tSirRoamOffloadScanReq *roam_req, + uint32_t mode, uint32_t vdev_id) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_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 = e_csr_auth_type_to_rsn_authmode + (roam_req->ConnectedNetwork.authentication, + roam_req->ConnectedNetwork.encryption); + WMA_LOGD("%s : auth mode = %d", __func__, auth_mode); +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + /* 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 /* WLAN_FEATURE_ROAM_OFFLOAD */ + 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 /* WLAN_FEATURE_ROAM_OFFLOAD */ + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_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; + cdf_mem_copy(roam_offload_ese->krk, + roam_req->KRK, + sizeof(roam_req->KRK)); + cdf_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; + cdf_mem_copy(roam_offload_11r->r0kh_id, + roam_req->R0KH_ID, + roam_offload_11r->r0kh_id_len); + cdf_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"); + } + + cdf_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 /* WLAN_FEATURE_ROAM_OFFLOAD */ + 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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_MODE", __func__); + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_roam_scan_offload_rssi_threshold() - set scan offload rssi threashold + * @wma_handle: wma handle + * @roam_req: Roaming request buffer + * + * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len, rssi_thresh, rssi_thresh_diff; + uint8_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; + int32_t good_rssi_threshold; + uint32_t hirssi_scan_max_count; + uint32_t hirssi_scan_delta; + int32_t hirssi_upper_bound; + + /* 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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d", + status); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI(FL("roam_scan_rssi_thresh=%d, roam_rssi_thresh_diff=%d"), + rssi_thresh, rssi_thresh_diff); + WMA_LOGI( + FL("hirssi_scan max_count=%d, delta=%d, hirssi_upper_bound=%d"), + hirssi_scan_max_count, hirssi_scan_delta, hirssi_upper_bound); + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_roam_scan_offload_scan_period() - set roam offload scan period + * @wma_handle: wma handle + * @scan_period: scan period + * @scan_age: scan age + * @vdev_id: vdev id + * + * Send WMI_ROAM_SCAN_PERIOD parameters to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_scan_period(tp_wma_handle wma_handle, + uint32_t scan_period, + uint32_t scan_age, + uint32_t vdev_id) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_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 CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_roam_scan_offload_rssi_change() - set roam offload RSSI change threshold + * @wma_handle: wma handle + * @rssi_change_thresh: RSSI Change threshold + * @bcn_rssi_weight: beacon RSSI weight + * @vdev_id: vdev id + * + * Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD parameters to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_rssi_change(tp_wma_handle wma_handle, + uint32_t vdev_id, + int32_t rssi_change_thresh, + uint32_t bcn_rssi_weight, + uint32_t hirssi_delay_btw_scans) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI(FL("roam_scan_rssi_change_thresh=%d, bcn_rssi_weight=%d"), + rssi_change_thresh, bcn_rssi_weight); + WMA_LOGI(FL("hirssi_delay_btw_scans=%d"), hirssi_delay_btw_scans); + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_roam_scan_offload_chan_list() - set roam offload channel list + * @wma_handle: wma handle + * @chan_count: channel count + * @chan_list: channel list + * @list_type: list type + * @vdev_id: vdev id + * + * Set roam offload channel list. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_chan_list(tp_wma_handle wma_handle, + uint8_t chan_count, + uint8_t *chan_list, + uint8_t list_type, uint32_t vdev_id) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len, list_tlv_len; + int i; + uint8_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 CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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(uint32_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] = cds_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CHAN_LIST", __func__); + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * e_csr_auth_type_to_rsn_authmode() - map csr auth type to rsn authmode + * @authtype: CSR authtype + * @encr: CSR Encryption + * + * Map CSR's authentication type into RSN auth mode used by firmware + * + * Return: WMI RSN auth mode + */ +A_UINT32 e_csr_auth_type_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 /* WLAN_FEATURE_VOWIFI_11R */ +#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 /* FEATURE_WLAN_WAPI */ +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_WPA: + case eCSR_AUTH_TYPE_CCKM_RSN: + return WMI_AUTH_CCKM; +#endif /* FEATURE_WLAN_ESE */ +#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 /* WLAN_FEATURE_11W */ + 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; + } +} + +/** + * e_csr_encryption_type_to_rsn_cipherset() - map csr enc type to ESN cipher + * @encr: CSR Encryption + * + * Map CSR's encryption type into RSN cipher types used by firmware + * + * Return: WMI RSN cipher + */ +A_UINT32 e_csr_encryption_type_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; + } +} + +/** + * wma_roam_scan_fill_ap_profile() - fill ap_profile + * @wma_handle: wma handle + * @pMac: Mac ptr + * @roam_req: roam offload scan request + * @ap_profile_p: ap profile + * + * Fill ap_profile structure from configured parameters + * + * Return: none + */ +void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle, + tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, + wmi_ap_profile *ap_profile_p) +{ + cdf_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; + cdf_mem_copy(ap_profile_p->ssid.ssid, + roam_req->ConnectedNetwork.ssId.ssId, + ap_profile_p->ssid.ssid_len); + ap_profile_p->rsn_authmode = + e_csr_auth_type_to_rsn_authmode(roam_req->ConnectedNetwork.authentication, + roam_req->ConnectedNetwork.encryption); + ap_profile_p->rsn_ucastcipherset = + e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.encryption); + ap_profile_p->rsn_mcastcipherset = + e_csr_encryption_type_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.mfp_enabled) + ap_profile_p->flags |= WMI_AP_PROFILE_FLAG_PMF; +#endif + } +} + +/** + * wma_roam_scan_scan_params() - fill roam scan params + * @wma_handle: wma handle + * @pMac: Mac ptr + * @scan_params: scan parameters + * @roam_req: NULL if this routine is called before connect + * It will be non-NULL if called after assoc. + * + * Fill scan_params structure from configured parameters + * + * Return: none + */ +void wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle, + tpAniSirGlobal pMac, + tSirRoamOffloadScanReq *roam_req, + wmi_start_scan_cmd_fixed_param * + scan_params) +{ + uint8_t channels_per_burst = 0; + uint32_t val = 0; + + if (NULL == pMac) { + WMA_LOGE("%s: pMac is NULL", __func__); + return; + } + + cdf_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; + 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_cfg_get_int + (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 = + CDF_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) ? + CDF_MAX(scan_params->dwell_time_active / roam_req->nProbes, + 1) : 0; + scan_params->probe_spacing_time = 0; + scan_params->probe_delay = 0; + /* 30 seconds for full scan cycle */ + scan_params->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; + 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); +} + +/** + * wma_roam_scan_offload_ap_profile() - set roam ap profile in fw + * @wma_handle: wma handle + * @ap_profile_p: ap profile + * @vdev_id: vdev id + * + * Send WMI_ROAM_AP_PROFILE to firmware + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_ap_profile(tp_wma_handle wma_handle, + wmi_ap_profile *ap_profile_p, + uint32_t vdev_id) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + + cdf_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("WMA --> WMI_ROAM_AP_PROFILE and other parameters"); + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_roam_scan_filter() - Filter to be applied while roaming + * @wma_handle: Global WMA Handle + * @roam_req: Request which contains the filters + * + * There are filters such as whitelist, blacklist and preferred + * list that need to be applied to the scan results to form the + * probable candidates for roaming. + * + * Return: Return success upon succesfully passing the + * parameters to the firmware, otherwise failure. + */ +CDF_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 CDF_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 CDF_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; i < num_bssid_black_list; i++) { + WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr); + bssid_src_ptr += ATH_MAC_LEN; + bssid_dst_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (num_bssid_black_list * sizeof(wmi_mac_addr)); + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (num_ssid_white_list * sizeof(wmi_ssid))); + ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < num_ssid_white_list; i++) { + memcpy(&ssid_ptr->ssid, &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: SSID length=%d", __func__, ssid_ptr->ssid_len); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_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; i < num_bssid_preferred_list; i++) { + WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, + (wmi_mac_addr *)bssid_dst_ptr); + bssid_src_ptr += ATH_MAC_LEN; + bssid_dst_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (num_bssid_preferred_list * sizeof(wmi_mac_addr)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (num_bssid_preferred_list * sizeof(uint32_t))); + bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < num_bssid_preferred_list; i++) { + *bssid_preferred_factor_ptr = + roam_params->bssid_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("cmd WMI_ROAM_FILTER_CMDID returned Error %d", + status); + goto error; + } + return CDF_STATUS_SUCCESS; +error: + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; +} + +/** + * wma_roam_scan_bmiss_cnt() - set bmiss count to fw + * @wma_handle: wma handle + * @first_bcnt: first bmiss count + * @final_bcnt: final bmiss count + * @vdev_id: vdev id + * + * set first & final biss count to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle, + A_INT32 first_bcnt, + A_UINT32 final_bcnt, uint32_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_roam_scan_offload_command() - set roam offload command + * @wma_handle: wma handle + * @command: command + * @vdev_id: vdev id + * + * This function set roam offload command to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_roam_scan_offload_command(tp_wma_handle wma_handle, + uint32_t command, uint32_t vdev_id) +{ + CDF_STATUS cdf_status; + wmi_roam_scan_cmd_fixed_param *cmd_fp; + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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); + cdf_status = CDF_STATUS_E_FAILURE; + goto error; + } + + WMA_LOGI("%s: WMA --> WMI_ROAM_SCAN_CMD", __func__); + return CDF_STATUS_SUCCESS; + +error: + wmi_buf_free(buf); + + return cdf_status; +} + +/** + * wma_process_roam_scan_req() - process roam request + * @wma_handle: wma handle + * @roam_req: roam request parameters + * + * Main routine to handle ROAM commands coming from CSR module. + * + * Return: CDF status + */ +CDF_STATUS wma_process_roam_scan_req(tp_wma_handle wma_handle, + tSirRoamOffloadScanReq *roam_req) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + wmi_start_scan_cmd_fixed_param scan_params; + wmi_ap_profile ap_profile; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + uint32_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 CDF_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. + */ + cdf_mem_free(roam_req); + return CDF_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; + + cdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + roam_req); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + cdf_status = wma_roam_scan_bmiss_cnt(wma_handle, + roam_req->RoamBmissFirstBcnt, + roam_req->RoamBmissFinalBcnt, + roam_req->sessionId); + if (cdf_status != CDF_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) { + cdf_status = + wma_roam_scan_offload_scan_period(wma_handle, + roam_req->EmptyRefreshScanPeriod, + roam_req->EmptyRefreshScanPeriod * 3, + roam_req->sessionId); + if (cdf_status != CDF_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. + */ + cdf_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 (cdf_status != CDF_STATUS_SUCCESS) + break; + + wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, + &ap_profile); + + cdf_status = wma_roam_scan_offload_ap_profile(wma_handle, + &ap_profile, + roam_req->sessionId); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + + cdf_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 ((cdf_status != CDF_STATUS_SUCCESS) && + (cdf_status != CDF_STATUS_E_EMPTY)) + break; + + + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, + &scan_params); + cdf_status = + wma_roam_scan_offload_mode(wma_handle, &scan_params, + roam_req, mode, + roam_req->sessionId); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + cdf_status = wma_roam_scan_filter(wma_handle, roam_req); + if (cdf_status != CDF_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); + cdf_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) { + cdf_status = wma_roam_scan_filter(wma_handle, roam_req); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("clear for roam scan filter failed"); + break; + } + } + + if (roam_req->reason == + REASON_OS_REQUESTED_ROAMING_NOW) { + cds_msg_t cds_msg; + tSirRoamOffloadScanRsp *scan_offload_rsp; + scan_offload_rsp = + cdf_mem_malloc(sizeof(*scan_offload_rsp)); + if (!scan_offload_rsp) { + WMA_LOGE("%s: Alloc failed for scan_offload_rsp", + __func__); + cdf_mem_free(roam_req); + return CDF_STATUS_E_NOMEM; + } + cds_msg.type = eWNI_SME_ROAM_SCAN_OFFLOAD_RSP; + scan_offload_rsp->sessionId = roam_req->sessionId; + scan_offload_rsp->reason = roam_req->reason; + cds_msg.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 (CDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, + (cds_msg_t *) &cds_msg)) { + cdf_mem_free(scan_offload_rsp); + CDF_TRACE(CDF_MODULE_ID_WMA, + CDF_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. + */ + cdf_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 = 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); + cdf_status = + wma_roam_scan_offload_mode(wma_handle, &scan_params, + roam_req, + WMI_ROAM_SCAN_MODE_NONE, + roam_req->sessionId); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + + if (roam_req->RoamScanOffloadEnabled == false) + break; + + cdf_status = wma_roam_scan_bmiss_cnt(wma_handle, + roam_req->RoamBmissFirstBcnt, + roam_req->RoamBmissFinalBcnt, + roam_req->sessionId); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + cdf_status = wma_roam_scan_filter(wma_handle, roam_req); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("Sending update for roam scan filter failed"); + break; + } + + + /* + * Runtime (after association) changes to rssi thresholds and + * other parameters. + */ + cdf_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 ((cdf_status != CDF_STATUS_SUCCESS) && + (cdf_status != CDF_STATUS_E_EMPTY)) + break; + + + cdf_status = wma_roam_scan_offload_rssi_thresh(wma_handle, + roam_req); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + + if (roam_req->EmptyRefreshScanPeriod > 0) { + cdf_status = + wma_roam_scan_offload_scan_period(wma_handle, + roam_req->EmptyRefreshScanPeriod, + roam_req->EmptyRefreshScanPeriod * 3, + roam_req->sessionId); + if (cdf_status != CDF_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; + } + + cdf_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 (cdf_status != CDF_STATUS_SUCCESS) + break; + + wma_roam_scan_fill_ap_profile(wma_handle, pMac, roam_req, + &ap_profile); + cdf_status = + wma_roam_scan_offload_ap_profile(wma_handle, &ap_profile, + roam_req->sessionId); + if (cdf_status != CDF_STATUS_SUCCESS) + break; + + wma_roam_scan_fill_scan_params(wma_handle, pMac, roam_req, + &scan_params); + cdf_status = + wma_roam_scan_offload_mode(wma_handle, &scan_params, + roam_req, mode, + roam_req->sessionId); + + break; + + default: + break; + } + cdf_mem_free(roam_req); + return cdf_status; +} + +/** + * wma_roam_preauth_chan_set() - set preauth channel + * @wma_handle: wma handle + * @params: switch channel params + * @vdev_id: vdev id + * + * Send a single channel passive scan request + * to handle set_channel operation for preauth + * + * Return: CDF atatus + */ +CDF_STATUS wma_roam_preauth_chan_set(tp_wma_handle wma_handle, + tpSwitchChannelParams params, + uint8_t vdev_id) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + tSirScanOffloadReq scan_req; + uint8_t bssid[IEEE80211_ADDR_LEN] = { + 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) { + cdf_status = CDF_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 + */ + cdf_mem_zero(&scan_req, sizeof(scan_req)); + cdf_copy_macaddr((struct cdf_mac_addr *) &scan_req.bssId, + (struct cdf_mac_addr *) bssid); + cdf_copy_macaddr((struct cdf_mac_addr *) &scan_req.selfMacAddr, + (struct cdf_mac_addr *) ¶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_get_scan_id(&scan_req.scan_id); + wma_handle->roam_preauth_chanfreq = + cds_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; + cdf_status = wma_start_scan(wma_handle, &scan_req, WMA_CHNL_SWITCH_REQ); + + if (cdf_status == CDF_STATUS_SUCCESS) + return cdf_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 WMA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, cdf_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = cdf_status; + wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0); + return cdf_status; +} + +/** + * wma_roam_preauth_chan_cancel() - cancel preauth scan + * @wma_handle: wma handle + * @params: switch channel parameters + * @vdev_id: vdev id + * + * Return: CDF status + */ +CDF_STATUS wma_roam_preauth_chan_cancel(tp_wma_handle wma_handle, + tpSwitchChannelParams params, + uint8_t vdev_id) +{ + tAbortScanParams abort_scan_req; + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + + WMA_LOGI("%s: channel %d", __func__, params->channelNumber); + /* Check for prior operation in progress */ + if (wma_handle->roam_preauth_chan_context != NULL) { + cdf_status = CDF_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; + cdf_status = wma_stop_scan(wma_handle, &abort_scan_req); + if (cdf_status == CDF_STATUS_SUCCESS) + return cdf_status; + /* Failed operation. Safely clear context */ + wma_handle->roam_preauth_chan_context = NULL; + +send_resp: + WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, cdf_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = cdf_status; + wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0); + return cdf_status; +} + +/** + * wma_roam_preauth_scan_event_handler() - preauth scan event handler + * @wma_handle: wma handle + * @vdev_id: vdev id + * @wmi_event: event data + * + * This function handles preauth scan event and send appropriate + * message to upper layers. + * + * Return: none + */ +void wma_roam_preauth_scan_event_handler(tp_wma_handle wma_handle, + uint8_t vdev_id, + wmi_scan_event_fixed_param * + wmi_event) +{ + CDF_STATUS cdf_status = CDF_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; + cdf_status = CDF_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; + cdf_status = CDF_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 WMA 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; + } + + params = (tpSwitchChannelParams) wma_handle->roam_preauth_chan_context; + if (params) { + WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, cdf_status); + params->chainMask = wma_handle->pdevconfig.txchainmask; + params->smpsMode = SMPS_MODE_DISABLED; + params->status = cdf_status; + wma_send_msg(wma_handle, WMA_SWITCH_CHANNEL_RSP, (void *)params, + 0); + wma_handle->roam_preauth_chan_context = NULL; + } + +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + +/** + * wma_process_roam_invoke() - send roam invoke command to fw. + * @handle: wma handle + * @roaminvoke: roam invoke command + * + * Send roam invoke command to fw for fastreassoc. + * + * Return: none + */ +void wma_process_roam_invoke(WMA_HANDLE handle, + struct 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)cds_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; +} + +/** + * wma_process_roam_synch_fail() -roam synch failure handle + * @handle: wma handle + * @synch_fail: roam synch fail parameters + * + * Return: none + */ +void wma_process_roam_synch_fail(WMA_HANDLE handle, + struct roam_offload_synch_fail *synch_fail) +{ + 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.*/ + wma_handle->interfaces[synch_fail->session_id].roam_synch_in_progress = + false; +} + +/** + * wma_roam_synch_event_handler() - roam synch event handler + * @handle: wma handle + * @event: event data + * @len: length of data + * + * This function is roam synch event handler. It sends roam + * indication for upper layer. + */ +int wma_roam_synch_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; + wmi_roam_synch_event_fixed_param *synch_event = NULL; + uint8_t *bcn_probersp_ptr = NULL; + uint8_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; + roam_offload_synch_ind *roam_synch_ind_ptr; + + 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) { + WMA_LOGE("%s: Ignoring RSI since one is already in progress", + __func__); + return -EINVAL; + } + wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true; + len = sizeof(roam_offload_synch_ind) + + synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len; + roam_synch_ind_ptr = + (roam_offload_synch_ind *) cdf_mem_malloc(len); + if (!roam_synch_ind_ptr) { + 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 abort_scan; + WMA_LOGD("LFR3: Aborting Scan with scan_id=%d\n", + wma->interfaces[synch_event->vdev_id].scan_info.scan_id); + abort_scan.SessionId = synch_event->vdev_id; + wma_stop_scan(wma, &abort_scan); + } + + roam_synch_ind_ptr->messageType = eWNI_SME_ROAM_OFFLOAD_SYNCH_IND; + roam_synch_ind_ptr->length = size; + roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id; + roam_synch_ind_ptr->authStatus = synch_event->auth_status; + roam_synch_ind_ptr->roamReason = synch_event->roam_reason; + roam_synch_ind_ptr->rssi = synch_event->rssi; + roam_synch_ind_ptr->isBeacon = synch_event->is_beacon; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, + roam_synch_ind_ptr->bssId); + roam_synch_ind_ptr->beaconProbeRespOffset = + sizeof(roam_offload_synch_ind); + bcn_probersp_ptr = + (uint8_t *) roam_synch_ind_ptr + + roam_synch_ind_ptr->beaconProbeRespOffset; + roam_synch_ind_ptr->beaconProbeRespLength = + synch_event->bcn_probe_rsp_len; + cdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, + roam_synch_ind_ptr->beaconProbeRespLength); + roam_synch_ind_ptr->reassocRespOffset = + sizeof(roam_offload_synch_ind) + + roam_synch_ind_ptr->beaconProbeRespLength; + roam_synch_ind_ptr->reassocRespLength = synch_event->reassoc_rsp_len; + reassoc_rsp_ptr = (uint8_t *) roam_synch_ind_ptr + + roam_synch_ind_ptr->reassocRespOffset; + cdf_mem_copy(reassoc_rsp_ptr, + param_buf->reassoc_rsp_frame, + roam_synch_ind_ptr->reassocRespLength); + chan = (wmi_channel *) param_buf->chan; + roam_synch_ind_ptr->chan_freq = chan->mhz; + key = (wmi_key_material *) param_buf->key; + if (key != NULL) { + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->replay_counter, SIR_REPLAY_CTR_LEN); + cdf_mem_copy(roam_synch_ind_ptr->kck, key->kck, + SIR_KCK_KEY_LEN); + cdf_mem_copy(roam_synch_ind_ptr->kek, key->kek, + SIR_KEK_KEY_LEN); + cdf_mem_copy(roam_synch_ind_ptr->replay_ctr, + key->replay_counter, SIR_REPLAY_CTR_LEN); + } + wma_send_msg(wma, WMA_ROAM_OFFLOAD_SYNCH_IND, + (void *) roam_synch_ind_ptr, 0); + return 0; +} + +/** + * 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 + */ +int wma_rssi_breached_event_handler(void *handle, + u_int8_t *cmd_param_info, u_int32_t len) +{ + WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf; + wmi_rssi_breach_event_fixed_param *event; + struct rssi_breach_event rssi; + tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE); + + 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; +} + +/** + * wma_roam_scan_fill_self_caps() - fill capabilities + * @wma_handle: wma handle + * @roam_offload_params: offload parameters + * @roam_req: roam request + * + * This function fills roam self capablities. + * + * Return: CDF status + */ +CDF_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; + uint32_t val = 0; + uint32_t nCfgValue; + uint16_t *pCfgValue16; + uint8_t nCfgValue8, *pCfgValue8; + tSirMacQosInfoStation macQosInfoSta; + union { + uint16_t nCfgValue16; + tSirMacHTCapabilityInfo htCapInfo; + tSirMacExtendedHTCapabilityInfo extHtCapInfo; + } uHTCapabilityInfo; + + cdf_mem_set(&macQosInfoSta, sizeof(tSirMacQosInfoStation), 0); + /* Roaming is done only for INFRA STA type. + * So, ess will be one and ibss will be Zero */ + pMac = cds_get_context(CDF_MODULE_ID_PE); + if (!pMac) { + WMA_LOGE("%s:NULL pMac ptr. Exiting", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_PRIVACY_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + selfCaps.ess = 1; + selfCaps.ibss = 0; + if (val) + selfCaps.privacy = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_SHORT_PREAMBLE"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.shortPreamble = 1; + + selfCaps.pbcc = 0; + selfCaps.channelAgility = 0; + if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, + &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.shortSlotTime = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_11H_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.spectrumMgt = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_QOS_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.qos = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_APSD_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.apsd = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_RRM_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + if (val) + selfCaps.rrm = 1; + if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != + eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_BLOCK_ACK_ENABLED"); + return CDF_STATUS_E_FAILURE; + } + selfCaps.delayedBA = + (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); + selfCaps.immediateBA = + (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); + pCfgValue16 = (uint16_t *) &selfCaps; + roam_offload_params->capability = (*pCfgValue16) & 0xFFFF; + + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &nCfgValue) != + eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_HT_CAP_INFO"); + return CDF_STATUS_E_FAILURE; + } + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + roam_offload_params->ht_caps_info = + uHTCapabilityInfo.nCfgValue16 & 0xFFFF; + if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &nCfgValue) != + eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_HT_AMPDU_PARAMS"); + return CDF_STATUS_E_FAILURE; + } + /* tSirMacHTParametersInfo */ + nCfgValue8 = (uint8_t) nCfgValue; + roam_offload_params->ampdu_param = (nCfgValue8) & 0xFF; + + val = ROAM_OFFLOAD_NUM_MCS_SET; + if (wlan_cfg_get_str(pMac, WNI_CFG_SUPPORTED_MCS_SET, + (uint8_t *) roam_offload_params->mcsset, + &val) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_SUPPORTED_MCS_SET"); + return CDF_STATUS_E_FAILURE; + } + if (wlan_cfg_get_int(pMac, WNI_CFG_EXT_HT_CAP_INFO, &nCfgValue) != + eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_EXT_HT_CAP_INFO"); + return CDF_STATUS_E_FAILURE; + } + /* uHTCapabilityInfo.extHtCapInfo */ + uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF; + roam_offload_params->ht_ext_cap = + uHTCapabilityInfo.nCfgValue16 & 0xFFFF; + + if (wlan_cfg_get_int(pMac, WNI_CFG_TX_BF_CAP, &nCfgValue) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_TX_BF_CAP"); + return CDF_STATUS_E_FAILURE; + } + /* tSirMacTxBFCapabilityInfo */ + nCfgValue8 = (uint8_t) nCfgValue; + roam_offload_params->ht_txbf = nCfgValue8 & 0xFF; + if (wlan_cfg_get_int(pMac, WNI_CFG_AS_CAP, &nCfgValue) != eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_AS_CAP"); + return CDF_STATUS_E_FAILURE; + } + /* tSirMacASCapabilityInfo */ + nCfgValue8 = (uint8_t) nCfgValue; + roam_offload_params->asel_cap = nCfgValue8 & 0xFF; + + /* QOS Info */ + if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &nCfgValue) != + eSIR_SUCCESS) { + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Failed to get WNI_CFG_MAX_SP_LENGTH"); + return CDF_STATUS_E_FAILURE; + } + nCfgValue8 = (uint8_t) 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 = (uint8_t *) &macQosInfoSta; + /* macQosInfoSta Only queue_request is set.Refer to + * populate_dot11f_wmm_caps for more details + */ + roam_offload_params->qos_caps = (*pCfgValue8) & 0xFF; + roam_offload_params->wmm_caps = 0x4 & 0xFF; + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_ric_req() - set ric request element + * @wma: wma handle + * @msg: message + * @is_add_ts: is addts required + * + * This function sets ric request element for 11r roaming. + * + * Return: none + */ +void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts) +{ + wmi_ric_request_fixed_param *cmd; + wmi_ric_tspec *tspec_param; + wmi_buf_t buf; + uint8_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 = (uint8_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 + cdf_mem_copy(((uint8_t *) &tspec_param->ts_info) + 1, + ((uint8_t *) &ptspecIE->tsinfo) + 1, 2); +#else + cdf_mem_copy(((uint8_t *) &tspec_param->ts_info), + ((uint8_t *) &ptspecIE->tsinfo) + 1, 2); +#endif /* ANI_LITTLE_BIT_ENDIAN */ + + 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 = CDF_STATUS_E_FAILURE; + cdf_nbuf_free(buf); + } +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +/** + * wma_process_unit_test_cmd() - send unit test command to fw. + * @handle: wma handle + * @wma_utest: unit test command + * + * This function send unit test command to fw. + * + * Return: none + */ +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; + uint8_t *buf_ptr; + int i; + uint16_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 = (uint8_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(uint32_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__); + cdf_nbuf_free(wmi_buf); + return; + } + return; +} + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + +/** + * wma_roam_ho_fail_handler() - LFR3.0 roam hand off failed handler + * @wma: wma handle + * @vdev_id: vdev id + * + * Return: none + */ +static void wma_roam_ho_fail_handler(tp_wma_handle wma, uint32_t vdev_id) +{ + tSirSmeHOFailureInd *ho_failure_ind; + cds_msg_t sme_msg = { 0 }; + CDF_STATUS cdf_status; + + ho_failure_ind = cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("Fail to post eWNI_SME_HO_FAIL_IND msg to SME"); + cdf_mem_free(ho_failure_ind); + return; + } + return; +} + +/** + * wma_process_roam_synch_complete() - roam synch complete command to fw. + * @handle: wma handle + * @synchcnf: offload synch confirmation params + * + * This function sends roam synch complete event to fw. + * + * Return: none + */ +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; + uint8_t *buf_ptr; + uint16_t len; + bool 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 == false) { + WMA_LOGE("%s: Dont send roam synch complete", __func__); + return; + } else { + wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress = + false; + } + 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 = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return; + } + return; +} +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + +/** + * wma_set_channel() - set channel + * @wma: wma handle + * @params: switch channel parameters + * + * Return: none + */ +void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) +{ + struct wma_vdev_start_req req; + struct wma_target_req *msg; + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t vdev_id, peer_id; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + struct wma_txrx_node *intr = wma->interfaces; + struct sir_hw_mode_params hw_mode = {0}; + + 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 = CDF_STATUS_E_FAILURE; + goto send_resp; + } + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); + status = CDF_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 (cds_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 = CDF_STATUS_SUCCESS; + } + goto send_resp; + } + } + cdf_mem_zero(&req, sizeof(req)); + req.vdev_id = vdev_id; + msg = wma_fill_vdev_req(wma, req.vdev_id, WMA_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 = CDF_STATUS_E_NOMEM; + goto send_resp; + } + req.chan = params->channelNumber; + req.chan_width = params->ch_width; + req.vht_capable = params->vhtCapable; + req.ch_center_freq_seg0 = params->ch_center_freq_seg0; + req.ch_center_freq_seg1 = params->ch_center_freq_seg1; + req.dot11_mode = params->dot11_mode; + status = wma_get_current_hw_mode(&hw_mode); + if (!CDF_IS_STATUS_SUCCESS(status)) + WMA_LOGE("wma_get_current_hw_mode failed"); + + if ((params->nss == 2) && !hw_mode.dbs_cap) { + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + } else { + req.preferred_rx_streams = 1; + req.preferred_tx_streams = 1; + } + +#ifdef WLAN_FEATURE_VOWIFI + req.max_txpow = params->maxTxPower; +#else + req.max_txpow = params->localPowerConstraint; +#endif /* WLAN_FEATURE_VOWIFI */ + 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 == true)) + wma->interfaces[req.vdev_id].is_channel_switch = true; + + status = wma_vdev_start(wma, &req, + wma->interfaces[req.vdev_id].is_channel_switch); + if (status != CDF_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, req.vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGP("%s: vdev start failed status = %d", __func__, status); + goto send_resp; + } + + if (wma->interfaces[req.vdev_id].is_channel_switch) + wma->interfaces[req.vdev_id].is_channel_switch = false; + return; +send_resp: + WMA_LOGD("%s: channel %d ch_width %d txpower %d status %d", __func__, + params->channelNumber, params->ch_width, +#ifdef WLAN_FEATURE_VOWIFI + params->maxTxPower, +#else + params->localPowerConstraint, +#endif /* WLAN_FEATURE_VOWIFI */ + status); + params->status = status; + WMA_LOGI("%s: sending WMA_SWITCH_CHANNEL_RSP, status = 0x%x", + __func__, status); + wma_send_msg(wma, WMA_SWITCH_CHANNEL_RSP, (void *)params, 0); +} + +#ifdef FEATURE_WLAN_SCAN_PNO + +/** + * wma_pno_start() - PNO start request + * @wma: wma handle + * @pno: PNO request + * + * This function request FW to start PNO request. + * Request: CDF status + */ +CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) +{ + wmi_nlo_config_cmd_fixed_param *cmd; + nlo_configured_parameters *nlo_list; + uint32_t *channel_list; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint8_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_t channel_list */ + + len += sizeof(uint32_t) * CDF_MIN(pno->aNetworks[0].ucChannelCount, + WMI_NLO_MAX_CHAN); + len += sizeof(nlo_configured_parameters) * + CDF_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 CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (uint8_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; + + /* Copy scan interval */ + if (pno->scanTimers.ucScanTimersCount) { + cmd->fast_scan_period = + WMA_SEC_TO_MSEC(pno->scanTimers.aTimerValues[0]. + uTimerValue); + cmd->slow_scan_period = cmd->fast_scan_period; + WMA_LOGD("Scan period : %d msec", cmd->slow_scan_period); + } + + buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param); + + cmd->no_of_ssids = CDF_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; + cdf_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 = CDF_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(uint32_t))); + buf_ptr += WMI_TLV_HDR_SIZE; + + channel_list = (uint32_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] = cds_chan_to_freq(channel_list[i]); + + WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]); + } + buf_ptr += cmd->num_of_channels * sizeof(uint32_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 CDF_STATUS_E_FAILURE; + } + + wma->interfaces[pno->sessionId].pno_in_progress = true; + + WMA_LOGD("PNO start request sent successfully for vdev %d", + pno->sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_pno_stop() - PNO stop request + * @wma: wma handle + * @vdev_id: vdev id + * + * This function request FW to stop ongoing PNO operation. + * + * Return: CDF status + */ +CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id) +{ + wmi_nlo_config_cmd_fixed_param *cmd; + int32_t len = sizeof(*cmd); + wmi_buf_t buf; + uint8_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 CDF_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_t channel_list */ + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf); + buf_ptr = (uint8_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 CDF_STATUS_E_FAILURE; + } + + wma->interfaces[vdev_id].pno_in_progress = false; + + WMA_LOGD("PNO stop request sent successfully for vdev %d", vdev_id); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_config_pno() - config PNO + * @wma: wma handle + * @pno: PNO request parameters + * + * Return: none + */ +void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno) +{ + CDF_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. */ + cdf_mem_free(pno); +} + +#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) + +/** + * wma_plm_start() - plm start request + * @wma: wma handle + * @plm: plm request parameters + * + * This function request FW to start PLM. + * + * Return: CDF status + */ +CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm) +{ + wmi_vdev_plmreq_start_cmd_fixed_param *cmd; + uint32_t *channel_list; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint8_t count; + int ret; + + if (NULL == plm || NULL == wma) { + WMA_LOGE("%s: input pointer is NULL ", __func__); + return CDF_STATUS_E_FAILURE; + } + WMA_LOGD("PLM Start"); + + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; /* TLV place holder for channel_list */ + len += sizeof(uint32_t) * plm->plmNumCh; + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return CDF_STATUS_E_NOMEM; + } + cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (uint8_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(uint32_t))); + + buf_ptr += WMI_TLV_HDR_SIZE; + if (cmd->num_chans) { + channel_list = (uint32_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] = + cds_chan_to_freq(channel_list[count]); + WMA_LOGD("Ch[%d]: %d MHz", count, channel_list[count]); + } + buf_ptr += cmd->num_chans * sizeof(uint32_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 CDF_STATUS_E_FAILURE; + } + wma->interfaces[plm->sessionId].plm_in_progress = true; + + WMA_LOGD("Plm start request sent successfully for vdev %d", + plm->sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_plm_stop() - plm stop request + * @wma: wma handle + * @plm: plm request parameters + * + * This function request FW to stop PLM. + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + int ret; + + if (NULL == plm || NULL == wma) { + WMA_LOGE("%s: input pointer is NULL ", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (false == wma->interfaces[plm->sessionId].plm_in_progress) { + WMA_LOGE("No active plm req found, skip plm stop req"); + return CDF_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 CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *) wmi_buf_data(buf); + + buf_ptr = (uint8_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 CDF_STATUS_E_FAILURE; + } + wma->interfaces[plm->sessionId].plm_in_progress = false; + + WMA_LOGD("Plm stop request sent successfully for vdev %d", + plm->sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_config_plm()- config PLM + * @wma: wma handle + * @plm: plm request parameters + * + * Return: none + */ +void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm) +{ + CDF_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. */ + cdf_mem_free(plm); + plm = NULL; +} +#endif + +/** + * wma_scan_cache_updated_ind() - scan update indication + * @wma: wma handle + * @sessionId: session ID + * + * After pushing cached scan results (that are stored in LIM) to SME, + * PE will post WMA_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. + * + * Return: none + */ +void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId) +{ + tSirPrefNetworkFoundInd *nw_found_ind; + CDF_STATUS status; + cds_msg_t cds_msg; + uint8_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 *) cdf_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; + + cds_msg.type = eWNI_SME_PREF_NETWORK_FOUND_IND; + cds_msg.bodyptr = (void *)nw_found_ind; + cds_msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post PNO completion match event to SME", + __func__); + cdf_mem_free(nw_found_ind); + } +} + +#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 + */ +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_nlo_match_evt_handler() - nlo match event handler + * @handle: wma handle + * @event: event data + * @len: data length + * + * Record NLO match event comes from FW. It's a indication that + * one of the profile is matched. + * + * Return: 0 for success or error code. + */ +int wma_nlo_match_evt_handler(void *handle, uint8_t *event, + uint32_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; + + cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + + return 0; +} + +/** + * wma_nlo_scan_cmp_evt_handler() - nlo scan completion handler + * @handle: wma handle + * @event: event handler + * @len: length of data + * + * This function handles NLO scan completion event. + * + * Return: 0 for success or error code. + */ +int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event, + uint32_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 recieved skipping PNO complete ind for vdev %d", + nlo_event->vdev_id); + goto skip_pno_cmp_ind; + } + + cdf_wake_lock_release(&wma->pno_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_PNO); + scan_event = + (tSirScanOffloadEvent *) + cdf_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_LOGE("Posting PNO Scan completion to umac"); + cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, + WMA_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_PNO); + cdf_mem_zero(scan_event, sizeof(tSirScanOffloadEvent)); + scan_event->reasonCode = eSIR_PNO_SCAN_SUCCESS; + scan_event->event = SCAN_EVENT_COMPLETED; + scan_event->sessionId = nlo_event->vdev_id; + wma_send_msg(wma, WMA_RX_SCAN_EVENT, (void *)scan_event, 0); + } else { + WMA_LOGE("Memory allocation failed for tSirScanOffloadEvent"); + } + +skip_pno_cmp_ind: + return 0; +} + +#endif + +/** + * wma_register_extscan_event_handler() - register extscan event handler + * @wma_handle: wma handle + * + * This function register extscan related event handlers. + * + * Return: none + */ +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; +} + +#ifdef FEATURE_WLAN_EXTSCAN + +/** + * wma_extscan_start_stop_event_handler() - extscan start/stop event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: data length + * + * This function handles different extscan related commands + * like start/stop/get results etc and indicate to upper layers. + * + * Return: 0 for success or error code. + */ +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; + struct sir_extscan_generic_response *extscan_ind; + uint16_t event_type; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + 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_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; + extscan_ind = cdf_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; + break; + case WMI_EXTSCAN_STOP_CMDID: + event_type = eSIR_EXTSCAN_STOP_RSP; + extscan_ind->status = event->status; + extscan_ind->request_id = event->request_id; + 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", + __func__, event->status); + cdf_mem_free(extscan_ind); + return -EINVAL; + } + pMac->sme.pExtScanIndCb(pMac->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); + cdf_mem_free(extscan_ind); + return 0; +} + +/** + * wma_extscan_operations_event_handler() - extscan operation event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length + * + * This function handles different operations related event and indicate + * upper layers with appropriate callback. + * + * Return: 0 for success or error code. + */ +int wma_extscan_operations_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf; + wmi_extscan_operation_event_fixed_param *oprn_event; + tSirExtScanOnScanEventIndParams *oprn_ind; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + 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_OPERATION_EVENTID_param_tlvs *) + cmd_param_info; + if (!param_buf) { + WMA_LOGE("%s: Invalid scan operation event", __func__); + return -EINVAL; + } + oprn_event = param_buf->fixed_param; + oprn_ind = cdf_mem_malloc(sizeof(*oprn_ind)); + if (!oprn_ind) { + WMA_LOGE("%s: extscan memory allocation failed", __func__); + cdf_mem_free(oprn_ind); + return -ENOMEM; + } + + oprn_ind->requestId = oprn_event->request_id; + + switch (oprn_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__); + cdf_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__); + cdf_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__, oprn_event->event); + cdf_mem_free(oprn_ind); + return -EINVAL; + } + pMac->sme.pExtScanIndCb(pMac->hHdd, + eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, oprn_ind); + WMA_LOGI("%s: sending scan progress event to hdd", __func__); +exit_handler: + cdf_mem_free(oprn_ind); + return 0; +} + +/** + * wma_extscan_table_usage_event_handler() - extscan table usage event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length + * + * This function handles table usage related event and indicate + * upper layers with appropriate callback. + * + * Return: 0 for success or error code. + */ +int wma_extscan_table_usage_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf; + wmi_extscan_table_usage_event_fixed_param *event; + tSirExtScanResultsAvailableIndParams *tbl_usg_ind; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + 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 = cdf_mem_malloc(sizeof(*tbl_usg_ind)); + if (!tbl_usg_ind) { + WMA_LOGE("%s: table usage allocation failed", __func__); + return -ENOMEM; + } + 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_LOGI("%s: sending scan_res available event to hdd", __func__); + cdf_mem_free(tbl_usg_ind); + return 0; +} + +/** + * wma_extscan_capabilities_event_handler() - extscan capabilities event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length + * + * This function handles capabilities event and indicate + * upper layers with registered callback. + * + * Return: 0 for success or error code. + */ +int wma_extscan_capabilities_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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 = cds_get_context(CDF_MODULE_ID_PE); + 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 = cdf_mem_malloc(sizeof(*dest_capab)); + if (!dest_capab) { + WMA_LOGE("%s: Allocation failed for capabilities buffer", + __func__); + return -ENOMEM; + } + 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_LOGI("%s: sending capabilities event to hdd", __func__); + cdf_mem_free(dest_capab); + return 0; +} + +/** + * wma_extscan_hotlist_match_event_handler() - hotlist match event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length + * + * This function handles hotlist match event and indicate + * upper layers with registered callback. + * + * Return: 0 for success or error code. + */ +int wma_extscan_hotlist_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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 = cds_get_context(CDF_MODULE_ID_PE); + + 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 = cdf_mem_malloc(sizeof(*dest_hotlist) + + sizeof(*dest_ap) * numap); + if (!dest_hotlist) { + WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__); + return -ENOMEM; + } + 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.bytes); + cdf_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_LOGI("%s: sending hotlist match event to hdd", __func__); + cdf_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 = cdf_mem_malloc(t_scan_id_grp->num_results * + sizeof(*ap)); + if (!t_scan_id_grp->ap) { + WMA_LOGD("%s: cdf_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.bytes); + + cdf_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; +} + +/** + * wma_extscan_cached_results_event_handler() - cached results event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length of @cmd_param_info + * + * This function handles cached results event and indicate + * cached results to upper layer. + * + * Return: 0 for success or error code. + */ +int wma_extscan_cached_results_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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, buf_len; + + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + 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_LOGE("%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 = cdf_mem_malloc(sizeof(*dest_cachelist)); + if (!dest_cachelist) { + WMA_LOGE("%s: cdf_mem_malloc failed", __func__); + return -ENOMEM; + } + cdf_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("%s: scan_ids_cnt %d", __func__, scan_ids_cnt); + dest_cachelist->num_scan_ids = scan_ids_cnt; + + buf_len = sizeof(*dest_result) * scan_ids_cnt; + dest_cachelist->result = cdf_mem_malloc(buf_len); + if (!dest_cachelist->result) { + WMA_LOGE("%s: Allocation failed for scanid grouping", __func__); + cdf_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++) { + cdf_mem_free(dest_result->ap); + dest_result++; + } + cdf_mem_free(dest_cachelist->result); + cdf_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; +} + +/** + * wma_extscan_change_results_event_handler() - change results event handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: length + * + * This function handles change results event and indicate + * change results to upper layer. + * + * Return: 0 for success or error code. + */ +int wma_extscan_change_results_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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; + uint8_t *src_rssi; + int count = 0; + int moredata; + int rssi_num = 0; + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + 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 = cdf_mem_malloc(sizeof(*dest_chglist) + + sizeof(*dest_ap) * numap + + sizeof(int32_t) * rssi_num); + if (!dest_chglist) { + WMA_LOGE("%s: Allocation failed for change monitor", __func__); + return -ENOMEM; + } + 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.bytes); + 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(int32_t); + 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_LOGI("%s: sending change monitor results", __func__); + cdf_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 + */ +int wma_passpoint_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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 mac = cds_get_context(CDF_MODULE_ID_PE); + + 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_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 = cdf_mem_malloc(sizeof(*dest_match) + + event->ie_length + event->anqp_length); + if (!dest_match) { + WMA_LOGE("%s: cdf_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.bytes); + cdf_mem_copy(dest_ap->ssid, event->ssid.ssid, + event->ssid.ssid_len); + dest_ap->ssid[event->ssid.ssid_len] = '\0'; + cdf_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) + + WMI_TLV_HDR_SIZE, dest_ap->ieLength); + cdf_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) + + WMI_TLV_HDR_SIZE + dest_ap->ieLength, + dest_match->anqp_len); + + mac->sme.pExtScanIndCb(mac->hHdd, + eSIR_PASSPOINT_NETWORK_FOUND_IND, + dest_match); + WMA_LOGI("%s: sending passpoint match event to hdd", __func__); + cdf_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 + */ +int +wma_extscan_hotlist_ssid_match_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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 = cds_get_context(CDF_MODULE_ID_PE); + + 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 = cdf_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.bytes); + cdf_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_LOGI("%s: sending hotlist ssid match event", __func__); + cdf_mem_free(dest_hotlist); + return 0; +} + +/** + * wma_get_buf_extscan_start_cmd() - Fill extscan start request + * @handle: wma handle + * @pstart: scan command request params + * @buf: event buffer + * @buf_len: length of buffer + * + * This function fills individual elements of extscan request and + * TLV for buckets, channel list. + * + * Return: CDF Status. + */ +CDF_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]; + + uint8_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 */ + uint32_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(uint32_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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; + 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 CDF_STATUS_SUCCESS; +} + +/** + * wma_start_extscan() - start extscan command to fw. + * @handle: wma handle + * @pstart: scan command request params + * + * This function sends start extscan request to fw. + * + * Return: CDF Status. + */ +CDF_STATUS wma_start_extscan(tp_wma_handle wma, + tSirWifiScanCmdReqParams *pstart) +{ + CDF_STATUS cdf_status = CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + /* Fill individual elements of extscan request and + * TLV for buckets, channel list. + */ + cdf_status = wma_get_buf_extscan_start_cmd(wma, pstart, &buf, &len); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer for ext scan cmd", __func__); + return CDF_STATUS_E_FAILURE; + } + if (!buf) { + WMA_LOGE("%s:Failed to get buffer" + "for current extscan info", __func__); + return CDF_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__); + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + wma->interfaces[pstart->sessionId].extscan_in_progress = true; + WMA_LOGD("Extscan start request sent successfully for vdev %d", + pstart->sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_stop_extscan() - stop extscan command to fw. + * @handle: wma handle + * @pstopcmd: stop scan command request params + * + * This function sends stop extscan request to fw. + * + * Return: CDF Status. + */ +CDF_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; + uint8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__); + return CDF_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + wma->interfaces[pstopcmd->sessionId].extscan_in_progress = false; + WMA_LOGD("Extscan stop request sent successfully for vdev %d", + pstopcmd->sessionId); + + return CDF_STATUS_SUCCESS; +} + +/** wma_get_hotlist_entries_per_page() - hotlist entries per page + * @wmi_handle: wmi handle. + * @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() - prepare hotlist command + * @handle: wma handle + * @photlist: hotlist command params + * @buf_len: buffer length + * + * This function fills individual elements for hotlist request and + * TLV for bssid entries + * + * Return: CDF Status. + */ +CDF_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 = NULL; + wmi_extscan_hotlist_entry *dest_hotlist; + tSirAPThresholdParam *src_ap = photlist->ap; + wmi_buf_t buf; + uint8_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 CDF_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 = CDF_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 CDF_STATUS_E_FAILURE; + } + buf_ptr = (uint8_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.bytes, + &dest_hotlist->bssid); + + WMA_LOGD("%s:channel:%d min_rssi %d", + __func__, dest_hotlist->channel, + 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__); + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + index = index + min_entries; + num_entries = numap - min_entries; + len = cmd_len; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_start_hotlist_monitor() - start hotlist monitor + * @wma: wma handle + * @photlist: hotlist request params + * + * This function configures hotlist monitor in fw. + * + * Return: CDF status + */ +CDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma, + tSirExtScanSetBssidHotListReqParams + *photlist) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + int len; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd", + __func__); + return CDF_STATUS_E_INVAL; + } + /* Fill individual elements for hotlist request and + * TLV for bssid entries + */ + cdf_status = wma_get_buf_extscan_hotlist_cmd(wma, photlist, &len); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer" + "for hotlist scan cmd", __func__); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_stop_hotlist_monitor() - stop hotlist monitor + * @wma: wma handle + * @photlist_reset: hotlist reset params + * + * This function configures hotlist monitor to stop in fw. + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + int hotlist_entries = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return CDF_STATUS_E_INVAL; + } + if (!photlist_reset) { + WMA_LOGE("%s: Invalid reset hotlist buffer", __func__); + return CDF_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_buf_extscan_change_monitor_cmd() - fill change monitor request + * @wma: wma handle + * @psigchange: change monitor request params + * @buf: wmi buffer + * @buf_len: buffer length + * + * This function fills elements of change monitor request buffer. + * + * Return: CDF status + */ +CDF_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; + uint8_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 CDF_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 CDF_STATUS_E_FAILURE; + } + buf_ptr = (uint8_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.bytes, + &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 CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_start_change_monitor() - send start change monitor cmd + * @wma: wma handle + * @psigchange: change monitor request params + * + * This function sends start change monitor request to fw. + * + * Return: CDF status + */ +CDF_STATUS wma_extscan_start_change_monitor(tp_wma_handle wma, + tSirExtScanSetSigChangeReqParams * + psigchange) +{ + CDF_STATUS cdf_status = CDF_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 CDF_STATUS_E_INVAL; + } + /* Fill individual elements of change monitor and + * TLV info ... */ + + cdf_status = wma_get_buf_extscan_change_monitor_cmd(wma, + psigchange, &buf, + &len); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to get buffer for change monitor cmd", + __func__); + return CDF_STATUS_E_FAILURE; + } + if (!buf) { + WMA_LOGE("%s: Failed to get buffer", __func__); + return CDF_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__); + cdf_nbuf_free(buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_stop_change_monitor() - send stop change monitor cmd + * @wma: wma handle + * @pResetReq: Reset change request params + * + * This function sends stop change monitor request to fw. + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + int change_list = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return CDF_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: ext scan not enabled", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_get_cached_results() - extscan get cached results + * @wma: wma handle + * @pcached_results: cached results parameters + * + * This function send request to fw to get cached results. + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, cannot issue cmd", __func__); + return CDF_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_extscan_get_capabilities() - extscan get capabilities + * @wma: wma handle + * @pgetcapab: get capabilities params + * + * This function send request to fw to get extscan capabilities. + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return CDF_STATUS_E_INVAL; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +CDF_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; + ol_txrx_vdev_handle vdev; + struct txrx_pdev_cfg_t *cfg; + int32_t intra_bss_fwd = 0; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", + __func__); + return CDF_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 CDF_STATUS_E_FAILURE; + } + + if (ipa_offload->offload_type > STA_RX_DATA_OFFLOAD) { + return CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + /* + * 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 CDF_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 CDF_STATUS_E_FAILURE; + } + + return CDF_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 + */ +CDF_STATUS 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 CDF_STATUS_E_FAILURE; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_STATUS_E_NOSUPPORT; + } + + /* TLV place holder for array of structures + * nlo_configured_parameters(nlo_list) */ + len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; + len += sizeof(nlo_configured_parameters) * + CDF_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 CDF_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 = req->session_id; + cmd->flags = WMI_NLO_CONFIG_ENLO; + + buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param); + + cmd->no_of_ssids = CDF_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; + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("set ePNO list request sent successfully for vdev %d", + req->session_id); + + return CDF_STATUS_SUCCESS; +} + +/** + * 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: CDF_STATUS enumeration + */ +CDF_STATUS 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 CDF_STATUS_E_FAILURE; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_STATUS_E_NOSUPPORT; + } + + 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 CDF_STATUS_E_NOMEM; + } + + 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); + cdf_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]); + + cdf_mem_copy(&cmd->roaming_consortium_ids[j], + &req->networks[i].roaming_consortium_ids[j], + PASSPOINT_ROAMING_CONSORTIUM_ID_LEN); + } + cdf_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 CDF_STATUS_E_FAILURE; + } + } + + WMA_LOGD("Set passpoint network list request is sent successfully for vdev %d", + req->session_id); + + return CDF_STATUS_SUCCESS; +} + +/** + * 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: CDF_STATUS enumeration + */ +CDF_STATUS 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 CDF_STATUS_E_FAILURE; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", __func__); + return CDF_STATUS_E_NOSUPPORT; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return CDF_STATUS_E_NOMEM; + } + + 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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Reset passpoint network list request is sent successfully for vdev %d", + req->session_id); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_set_ssid_hotlist() - Handle an SSID hotlist set request + * @wma: WMA handle + * @request: SSID hotlist set request from SME + * + * Return: CDF_STATUS enumeration + */ +CDF_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 CDF_STATUS_E_FAILURE; + } + if (!request) { + WMA_LOGE("%s: Invalid request buffer", __func__); + return CDF_STATUS_E_FAILURE; + } + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_EXTSCAN)) { + WMA_LOGE("%s: extscan not enabled", + __func__); + return CDF_STATUS_E_NOSUPPORT; + } + + /* 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 CDF_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; + cdf_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 CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} +#endif + +/** + * wma_scan_probe_setoui() - set scan probe OUI + * @wma: wma handle + * @psetoui: OUI parameters + * + * set scan probe OUI parameters in firmware + * + * Return: CDF status + */ +CDF_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; + uint8_t *buf_ptr; + uint32_t *oui_buf; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_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; + cdf_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__); + cdf_nbuf_free(wmi_buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_scan_event_callback() - scan event callback + * @handle: wma handle + * @data: event data + * @len: data length + * + * This function process scan event and provide indication + * to upper layers. + * + * Return: 0 for success or error code. + */ +int wma_scan_event_callback(WMA_HANDLE handle, uint8_t *data, + uint32_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; + uint8_t vdev_id; + uint32_t scan_id; + + 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; + + if (wma_handle->roam_preauth_scan_id == wmi_event->scan_id) { + /* This is the scan requested by roam preauth set_channel operation */ + + if (wmi_event->event & WMI_SCAN_FINISH_EVENTS) { + WMA_LOGE("roam scan complete: scan_id 0x%x, vdev_id %d", + wmi_event->scan_id, vdev_id); + /*wma_reset_scan_info(wma_handle, vdev_id);*/ + } + + 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 -EFAULT; + } + + wma_roam_preauth_scan_event_handler(wma_handle, + vdev_id, wmi_event); + return 0; + + } + + scan_event = (tSirScanOffloadEvent *) cdf_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; + + if (scan_event->scanId == + wma_handle->interfaces[vdev_id].p2p_scan_info.scan_id) { + scan_event->p2pScanType = P2P_SCAN_TYPE_LISTEN; + if (scan_event->event == SCAN_EVENT_COMPLETED) + wma_reset_p2p_scan_info(wma_handle, vdev_id); + } + 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 0x%x, vdev_id %d", + wmi_event->scan_id, vdev_id); + } + + wma_send_msg(wma_handle, WMA_RX_SCAN_EVENT, (void *)scan_event, 0); + return 0; +} + + +/** + * wma_roam_better_ap_handler() - better ap event handler + * @wma: wma handle + * @vdev_id: vdev id + * + * 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 to SME. + * + * Return: none + */ +void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id) +{ + cds_msg_t cds_msg; + tSirSmeCandidateFoundInd *candidate_ind; + + /* 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); + } + + candidate_ind = cdf_mem_malloc(sizeof(tSirSmeCandidateFoundInd)); + if (!candidate_ind) { + WMA_LOGE("%s: Alloc failed for tSirSmeCandidateFoundInd", + __func__); + return; + } + + candidate_ind->messageType = eWNI_SME_CANDIDATE_FOUND_IND; + candidate_ind->sessionId = vdev_id; + candidate_ind->length = sizeof(tSirSmeCandidateFoundInd); + + cds_msg.type = eWNI_SME_CANDIDATE_FOUND_IND; + cds_msg.bodyptr = candidate_ind; + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO, + FL("posting candidate ind to SME")); + + if (CDF_STATUS_SUCCESS != cds_mq_post_message(CDS_MQ_ID_SME, + (cds_msg_t *) &cds_msg)) { + cdf_mem_free(candidate_ind); + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + FL("Failed to post candidate ind to SME")); + } +} + +/** + * wma_roam_event_callback() - roam event callback + * @handle: wma handle + * @event_buf: event buffer + * @len: buffer length + * + * Handler for all events from roam engine in firmware + * + * Return: 0 for success or error code + */ +int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf, + uint32_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); + 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_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_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 + */ +CDF_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 CDF_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGI("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW"); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_scan_id() - Generates scan id + * @scan_id: Scan id + * + * This function generates the scan id. + * + * Return: CDF_STATUS + */ + +CDF_STATUS wma_get_scan_id(uint32_t *scan_id) +{ + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + + if (!scan_id) { + WMA_LOGE("Scan_id is NULL"); + return CDF_STATUS_E_FAULT; + } + + /* host need to cycle through the lower 12 bits to generate ids */ + *scan_id = cdf_atomic_inc_return(&wma->scan_id_counter) & + WMA_SCAN_ID_MASK; + /* + * Firmware expects the host scan request id appended + * by PREFIX 0xA000 + */ + *scan_id = *scan_id | WMI_HOST_SCAN_REQ_ID_PREFIX; + return CDF_STATUS_SUCCESS; +} + diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c new file mode 100644 index 000000000000..1411a3511e4e --- /dev/null +++ b/core/wma/src/wma_utils.c @@ -0,0 +1,3526 @@ +/* + * 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_utis.c + * This file contains utilities and stats related functions. + */ + +/* Header files */ + +#include "wma.h" +#include "wma_api.h" +#include "cds_api.h" +#include "wmi_unified_api.h" +#include "wlan_qct_sys.h" +#include "wni_api.h" +#include "ani_global.h" +#include "wmi_unified.h" +#include "wni_cfg.h" +#include "cfg_api.h" +#include "ol_txrx_ctrl_api.h" +#include "wlan_tgt_def_config.h" + +#include "cdf_nbuf.h" +#include "cdf_types.h" +#include "ol_txrx_api.h" +#include "cdf_memory.h" +#include "ol_txrx_types.h" +#include "ol_txrx_peer_find.h" + +#include "wma_types.h" +#include "lim_api.h" +#include "lim_session_utils.h" + +#include "cds_utils.h" + +#if !defined(REMOVE_PKT_LOG) +#include "pktlog_ac.h" +#endif /* REMOVE_PKT_LOG */ + +#include "dbglog_host.h" +#include "csr_api.h" +#include "ol_fw.h" + +#include "dfs.h" +#include "wma_internal.h" + +/* 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 +/* 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 */ + +#ifdef BIG_ENDIAN_HOST + +/* ############# function definitions ############ */ + +/** + * wma_swap_bytes() - swap bytes + * @pv: buffer + * @n: swap bytes + * + * Return: none + */ +void wma_swap_bytes(void *pv, uint32_t n) +{ + int32_t no_words; + int32_t i; + uint32_t *word_ptr; + + no_words = n / sizeof(uint32_t); + word_ptr = (uint32_t *) pv; + for (i = 0; i < no_words; i++) { + *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i)); + } +} + +#define SWAPME(x, len) wma_swap_bytes(&x, len); +#endif /* BIG_ENDIAN_HOST */ + +/** + * wma_get_mcs_idx() - get mcs index + * @maxRate: max rate + * @rate_flags: rate flags + * @nss: number of nss + * @mcsRateFlag: mcs rate flag + * + * Return: return mcs index + */ +static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags, + uint8_t nss, uint8_t *mcsRateFlag) +{ + uint8_t rateFlag = 0, curIdx = 0; + uint16_t curRate; + bool found = false; +#ifdef WLAN_FEATURE_11AC + struct index_vht_data_rate_type *supported_vht_mcs_rate; +#endif /* WLAN_FEATURE_11AC */ + struct index_data_rate_type *supported_mcs_rate; + + WMA_LOGD("%s rate:%d rate_flgs:%d", __func__, maxRate, rate_flags); +#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); +#endif /* WLAN_FEATURE_11AC */ + supported_mcs_rate = (struct index_data_rate_type *) + ((nss == 1) ? &supported_mcs_rate_nss1 : &supported_mcs_rate_nss2); + + *mcsRateFlag = rate_flags; + *mcsRateFlag &= ~eHAL_TX_RATE_SGI; +#ifdef WLAN_FEATURE_11AC + if (rate_flags & + (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_VHT80)) { + + if (rate_flags & eHAL_TX_RATE_VHT80) { + for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { + rateFlag = 0; + if (curIdx >= 7) { + if (rate_flags & eHAL_TX_RATE_SGI) + rateFlag |= 0x1; + } + + curRate = supported_vht_mcs_rate[curIdx].supported_VHT80_rate[rateFlag]; + if (curRate == maxRate) { + found = true; + break; + } + } + } + + if ((found == false) && + ((rate_flags & eHAL_TX_RATE_VHT80) || + (rate_flags & eHAL_TX_RATE_VHT40))) { + for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { + rateFlag = 0; + if (curIdx >= 7) { + if (rate_flags & eHAL_TX_RATE_SGI) + rateFlag |= 0x1; + } + + curRate = supported_vht_mcs_rate[curIdx].supported_VHT40_rate[rateFlag]; + if (curRate == maxRate) { + found = true; + *mcsRateFlag &= ~eHAL_TX_RATE_VHT80; + break; + } + } + } + + if ((found == false) && + ((rate_flags & eHAL_TX_RATE_VHT80) || + (rate_flags & eHAL_TX_RATE_VHT40) || + (rate_flags & eHAL_TX_RATE_VHT20))) { + for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { + rateFlag = 0; + if (curIdx >= 7) { + if (rate_flags & eHAL_TX_RATE_SGI) + rateFlag |= 0x1; + } + + curRate = supported_vht_mcs_rate[curIdx].supported_VHT20_rate[rateFlag]; + if (curRate == maxRate) { + found = true; + *mcsRateFlag &= + ~(eHAL_TX_RATE_VHT80 | + eHAL_TX_RATE_VHT40); + break; + } + } + } + } +#endif /* WLAN_FEATURE_11AC */ + if ((found == false) && + (rate_flags & (eHAL_TX_RATE_HT40 | eHAL_TX_RATE_HT20))) { + if (rate_flags & eHAL_TX_RATE_HT40) { + rateFlag = 0x1; + + for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) { + if (curIdx == 7) { + if (rate_flags & eHAL_TX_RATE_SGI) + rateFlag |= 0x2; + } + + curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag]; + if (curRate == maxRate) { + found = true; + *mcsRateFlag = eHAL_TX_RATE_HT40; + break; + } + } + } + + if (found == false) { + rateFlag = 0; + for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) { + if (curIdx == 7) { + if (rate_flags & eHAL_TX_RATE_SGI) + rateFlag |= 0x2; + } + + curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag]; + if (curRate == maxRate) { + found = true; + *mcsRateFlag = eHAL_TX_RATE_HT20; + break; + } + } + } + } + + /*SGI rates are used by firmware only for MCS >= 7 */ + if (found && (curIdx >= 7)) + *mcsRateFlag |= eHAL_TX_RATE_SGI; + + return found ? curIdx : INVALID_MCS_IDX; +} + +/** + * host_map_smps_mode() - map fw smps mode to tSmpsModeValue + * @fw_smps_mode: fw smps mode + * + * Return: return tSmpsModeValue + */ +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; +} + +#ifdef WLAN_FEATURE_STATS_EXT +/** + * wma_stats_ext_event_handler() - extended stats event handler + * @handle: wma handle + * @event_buf: event buffer received from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + WMI_STATS_EXT_EVENTID_param_tlvs *param_buf; + tSirStatsExtEvent *stats_ext_event; + wmi_stats_ext_event_fixed_param *stats_ext_info; + CDF_STATUS status; + cds_msg_t cds_msg; + uint8_t *buf_ptr; + uint32_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 = (uint8_t *) stats_ext_info; + + alloc_len = sizeof(tSirStatsExtEvent); + alloc_len += stats_ext_info->data_len; + + stats_ext_event = (tSirStatsExtEvent *) cdf_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; + cdf_mem_copy(stats_ext_event->event_data, + buf_ptr, stats_ext_event->event_data_len); + + cds_msg.type = eWNI_SME_STATS_EXT_EVENT; + cds_msg.bodyptr = (void *)stats_ext_event; + cds_msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SME, &cds_msg); + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("%s: Failed to post stats ext event to SME", __func__); + cdf_mem_free(stats_ext_event); + return -EFAULT; + } + + WMA_LOGD("%s: stats ext event Posted to SME", __func__); + return 0; +} +#endif /* WLAN_FEATURE_STATS_EXT */ + + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS + +/** + * wma_unified_link_peer_stats_event_handler() - peer stats event handler + * @handle: wma handle + * @cmd_param_info: data received with event from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +static int wma_unified_link_peer_stats_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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; + uint8_t *results, *t_peer_stats, *t_rate_stats; + uint32_t count, num_rates = 0; + uint32_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 = cds_get_context(CDF_MODULE_ID_PE); + + 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 = cdf_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); + + cdf_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; + + cdf_mem_copy(link_stats_results->results, + &fixed_param->num_peers, peer_stats_size); + + results = (uint8_t *) link_stats_results->results; + t_peer_stats = (uint8_t *) peer_stats; + t_rate_stats = (uint8_t *) rate_stats; + next_res_offset = peer_stats_size; + next_peer_offset = WMI_TLV_HDR_SIZE; + next_rate_offset = WMI_TLV_HDR_SIZE; + for (count = 0; count < fixed_param->num_peers; count++) { + WMA_LOGD("Peer Info:"); + WMA_LOGD("peer_type %u capabilities %u num_rates %u", + peer_stats->peer_type, peer_stats->capabilities, + peer_stats->num_rates); + + cdf_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++; + + cdf_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, + WMA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Peer Stats event posted to HDD", __func__); + cdf_mem_free(link_stats_results); + + return 0; +} + + +/** + * wma_unified_link_radio_stats_event_handler() - radio link stats event handler + * @handle: wma handle + * @cmd_param_info: data received with event from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +static int wma_unified_link_radio_stats_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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; + uint8_t *results, *t_radio_stats, *t_channel_stats; + uint32_t next_res_offset, next_chan_offset, count; + size_t radio_stats_size, chan_stats_size; + size_t link_stats_results_size; + + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + + 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 = cdf_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); + + cdf_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 = (uint8_t *) link_stats_results->results; + t_radio_stats = (uint8_t *) radio_stats; + t_channel_stats = (uint8_t *) channel_stats; + + cdf_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++; + + cdf_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, + WMA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Radio Stats event posted to HDD", __func__); + cdf_mem_free(link_stats_results); + + return 0; +} + +/** + * wma_register_ll_stats_event_handler() - register link layer stats related + * event handler + * @wma_handle: wma handle + * + * Return: none + */ +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; +} + + +/** + * wma_process_ll_stats_clear_req() - clear link layer stats + * @wma: wma handle + * @clearReq: ll stats clear request command params + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_process_ll_stats_clear_req + (tp_wma_handle wma, const tpSirLLStatsClearReq clearReq) +{ + wmi_clear_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + int ret; + + if (!clearReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Clear Link Layer Stats request sent successfully"); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_process_ll_stats_set_req() - link layer stats set request + * @wma: wma handle + * @setReq: ll stats set request command params + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_process_ll_stats_set_req + (tp_wma_handle wma, const tpSirLLStatsSetReq setReq) +{ + wmi_start_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + int ret; + + if (!setReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Set Link Layer Stats request sent successfully"); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_process_ll_stats_get_req() - link layer stats get request + * @wma:wma handle + * @getReq:ll stats get request command params + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_process_ll_stats_get_req + (tp_wma_handle wma, const tpSirLLStatsGetReq getReq) +{ + wmi_request_link_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + int ret; + + if (!getReq || !wma) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return CDF_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 CDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + cdf_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 CDF_STATUS_E_FAILURE; + } + + WMA_LOGD("Get Link Layer Stats request sent successfully"); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_unified_link_iface_stats_event_handler() - link iface stats event handler + * @wma:wma handle + * @cmd_param_info: data from event + * @len: length + * + * Return: 0 for success or error code + */ +int wma_unified_link_iface_stats_event_handler(void *handle, + uint8_t *cmd_param_info, + uint32_t len) +{ + 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; + uint8_t *results, *t_link_stats, *t_ac_stats; + uint32_t next_res_offset, next_ac_offset, count; + uint32_t roaming_offset, roaming_size; + size_t link_stats_size, ac_stats_size, iface_info_size; + size_t link_stats_results_size; + + tpAniSirGlobal pMac = cds_get_context(CDF_MODULE_ID_PE); + + 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 = cdf_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); + + cdf_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 = (uint8_t *) link_stats_results->results; + t_link_stats = (uint8_t *) link_stats; + t_ac_stats = (uint8_t *) ac_stats; + + /* Copy roaming state */ + roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming); + roaming_size = member_size(tSirWifiInterfaceInfo, roaming); + + cdf_mem_copy(results + roaming_offset, &link_stats->roam_state, + roaming_size); + + cdf_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++; + + cdf_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, + WMA_LINK_LAYER_STATS_RESULTS_RSP, + link_stats_results); + WMA_LOGD("%s: Iface Stats event posted to HDD", __func__); + cdf_mem_free(link_stats_results); + + return 0; +} + +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +/** + * wma_update_pdev_stats() - update pdev stats + * @wma: wma handle + * @pdev_stats: pdev stats + * + * Return: none + */ +static void wma_update_pdev_stats(tp_wma_handle wma, + wmi_pdev_stats *pdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + uint32_t temp_mask; + uint8_t *stats_buf; + tCsrGlobalClassAStatsInfo *classa_stats = NULL; + struct wma_txrx_node *node; + uint8_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 = (uint8_t *) (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_update_vdev_stats() - update vdev stats + * @wma: wma handle + * @vdev_stats: vdev stats + * + * Return: none + */ +static void wma_update_vdev_stats(tp_wma_handle wma, + wmi_vdev_stats *vdev_stats) +{ + tAniGetPEStatsRsp *stats_rsp_params; + tCsrSummaryStatsInfo *summary_stats = NULL; + uint8_t *stats_buf; + struct wma_txrx_node *node; + uint8_t i; + int8_t rssi = 0; + CDF_STATUS cdf_status; + tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq; + cds_msg_t sme_msg = { 0 }; + + node = &wma->interfaces[vdev_stats->vdev_id]; + stats_rsp_params = node->stats_rsp; + if (stats_rsp_params) { + stats_buf = (uint8_t *) (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. + */ + WMA_LOGE("Invalid SNR from firmware"); + + } 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); + } + + cdf_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("%s: Fail to post snr ind msg", __func__); + cdf_mem_free(p_snr_req); + } + + node->psnr_req = NULL; + } +} + +/** + * wma_post_stats() - update stats to PE + * @wma: wma handle + * @node: txrx node + * + * Return: none + */ +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, WMA_GET_STATISTICS_RSP, (void *)stats_rsp_params, 0); + node->stats_rsp = NULL; + node->fw_stats_set = 0; +} + +/** + * wma_update_peer_stats() - update peer stats + * @wma: wma handle + * @peer_stats: peer stats + * + * Return: none + */ +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; + uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags; + uint32_t 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 = (uint8_t *) (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); + } + } +} + +/** + * wma_post_link_status() - post link status to SME + * @pGetLinkStatus: SME Link status + * @link_status: Link status + * + * Return: none + */ +void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus, + uint8_t link_status) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("%s: Fail to post link status ind msg", __func__); + cdf_mem_free(pGetLinkStatus); + } +} + +/** + * wma_link_status_event_handler() - link status event handler + * @handle: wma handle + * @cmd_param_info: data from event + * @len: length + * + * Return: 0 for success or error code + */ +int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_vdev_rate_stats_event_fixed_param *event; + wmi_vdev_rate_ht_info *ht_info; + struct wma_txrx_node *intr = wma->interfaces; + uint8_t link_status = LINK_STATUS_LEGACY; + int i; + + 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 = (wmi_vdev_rate_stats_event_fixed_param *) param_buf->fixed_param; + ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info; + + 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; +} + +/** + * wma_stats_event_handler() - stats event handler + * @handle: wma handle + * @cmd_param_info: data from event + * @len: length + * + * Return: 0 for success or error code + */ +int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf; + wmi_stats_event_fixed_param *event; + wmi_pdev_stats *pdev_stats; + wmi_vdev_stats *vdev_stats; + wmi_peer_stats *peer_stats; + uint8_t i, *temp; + + + 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; + temp = (uint8_t *) param_buf->data; + + 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); + } + } + + if (event->num_peer_stats > 0) { + 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__); + return 0; +} + +/** + * wma_send_link_speed() - send link speed to SME + * @link_speed: link speed + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_send_link_speed(uint32_t link_speed) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cds_msg_t sme_msg = { 0 }; + tSirLinkSpeedInfo *ls_ind = + (tSirLinkSpeedInfo *) cdf_mem_malloc(sizeof(tSirLinkSpeedInfo)); + if (!ls_ind) { + WMA_LOGE("%s: Memory allocation failed.", __func__); + cdf_status = CDF_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; + + cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("%s: Fail to post linkspeed ind msg", + __func__); + cdf_mem_free(ls_ind); + } + } + return cdf_status; +} + +/** + * wma_link_speed_event_handler() - link speed event handler + * @handle: wma handle + * @cmd_param_info: event data + * @len: length + * + * Return: 0 for success or error code + */ +int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf; + wmi_peer_estimated_linkspeed_event_fixed_param *event; + CDF_STATUS cdf_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; + cdf_status = wma_send_link_speed(event->est_linkspeed_kbps); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + return -EINVAL; + } + return 0; +} + +/** + * wma_wni_cfg_dnld() - cfg download request + * @handle: wma handle + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle) +{ + CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + void *mac = cds_get_context(CDF_MODULE_ID_PE); + + WMA_LOGD("%s: Enter", __func__); + + if (NULL == mac) { + WMA_LOGP("%s: Invalid context", __func__); + CDF_ASSERT(0); + return CDF_STATUS_E_FAILURE; + } + + process_cfg_download_req(mac); + + WMA_LOGD("%s: Exit", __func__); + return cdf_status; +} + +/** + * wma_unified_debug_print_event_handler() - debug print event handler + * @handle: wma handle + * @datap: data pointer + * @len: length + * + * Return: 0 for success or error code + */ +int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap, + uint32_t len) +{ + WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_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 /* BIG_ENDIAN_HOST */ +} + +/** + * wma_check_scan_in_progress() - check scan is progress or not + * @handle: wma handle + * + * Return: true/false + */ +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; +} + +/** + * wma_is_sap_active() - check sap is active or not + * @handle: wma handle + * + * Return: true/false + */ +bool 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; +} + +/** + * wma_is_p2p_go_active() - check p2p go is active or not + * @handle: wma handle + * + * Return: true/false + */ +bool 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; +} + +/** + * wma_is_p2p_cli_active() - check p2p cli is active or not + * @handle: wma handle + * + * Return: true/false + */ +bool 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; +} + +/** + * wma_is_sta_active() - check sta is active or not + * @handle: wma handle + * + * Return: true/false + */ +bool 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_peer_phymode() - get phymode + * @nw_type: nw type + * @sta_type: sta type + * @is_ht: is ht supported + * @is_cw40: is channel width 40 supported + * @is_vht: is vht supported + * @is_cw_vht: is channel width 80 supported + * + * Return: WLAN_PHY_MODE + */ +WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type, + uint8_t is_ht, uint8_t ch_width, + uint8_t is_vht) +{ + WLAN_PHY_MODE phymode = MODE_UNKNOWN; + + switch (nw_type) { + case eSIR_11B_NW_TYPE: + phymode = MODE_11B; + if (is_ht || is_vht) + WMA_LOGE("HT/VHT is enabled with 11B NW type"); + break; + case eSIR_11G_NW_TYPE: + if (!(is_ht || is_vht)) { + phymode = MODE_11G; + break; + } + if (CH_WIDTH_40MHZ < ch_width) + WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz"); + if (ch_width) + phymode = (is_vht) ? + MODE_11AC_VHT40 : MODE_11NG_HT40; + else + phymode = (is_vht) ? + MODE_11AC_VHT20 : MODE_11NG_HT20; + break; + case eSIR_11A_NW_TYPE: + if (!(is_ht || is_vht)) { + phymode = MODE_11A; + break; + } + if (is_vht) { +#if CONFIG_160MHZ_SUPPORT != 0 + if (ch_width == CH_WIDTH_160MHZ) + phymode = MODE_11AC_VHT160; + else if (ch_width == CH_WIDTH_80P80MHZ) + phymode = MODE_11AC_VHT80_80; + else +#endif + if (ch_width == CH_WIDTH_80MHZ) + phymode = MODE_11AC_VHT80; + else + phymode = (ch_width) ? + MODE_11AC_VHT40 : MODE_11AC_VHT20; + } else + phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20; + break; + default: + WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type); + break; + } + WMA_LOGD("%s: nw_type %d is_ht %d ch_width %d is_vht %d phymode %d", + __func__, nw_type, is_ht, ch_width, is_vht, phymode); + + return phymode; +} + +/** + * wma_txrx_fw_stats_reset() - reset txrx fw statistics + * @wma_handle: wma handle + * @vdev_id: vdev id + * @value: value + * + * Return: 0 for success or return error + */ +int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle, + uint8_t vdev_id, uint32_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; + } + cdf_mem_zero(&req, sizeof(req)); + req.stats_type_reset_mask = value; + ol_txrx_fw_stats_get(vdev, &req); + + return 0; +} + +#ifdef HELIUMPLUS +#define SET_UPLOAD_MASK(_mask, _rate_info) \ + ((_mask) = 1 << (_rate_info ## _V2)) +#else /* !HELIUMPLUS */ +#define SET_UPLOAD_MASK(_mask, _rate_info) \ + ((_mask) = 1 << (_rate_info)) +#endif + +/** + * wma_set_txrx_fw_stats_level() - set txrx fw stats level + * @wma_handle: wma handle + * @vdev_id: vdev id + * @value: value + * + * Return: 0 for success or return error + */ +int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle, + uint8_t vdev_id, uint32_t value) +{ + struct ol_txrx_stats_req req; + ol_txrx_vdev_handle vdev; + uint32_t l_up_mask; + + vdev = wma_find_vdev_by_id(wma_handle, vdev_id); + if (!vdev) { + WMA_LOGE("%s:Invalid vdev handle", __func__); + return -EINVAL; + } + cdf_mem_zero(&req, sizeof(req)); + req.print.verbose = 1; + + switch (value) { + /* txrx_fw_stats 1 */ + case WMA_FW_PHY_STATS: + l_up_mask = 1 << HTT_DBG_STATS_WAL_PDEV_TXRX; + break; + + /* txrx_fw_stats 2 */ + case WMA_FW_RX_REORDER_STATS: + l_up_mask = 1 << HTT_DBG_STATS_RX_REORDER; + break; + + /* txrx_fw_stats 3 */ + case WMA_FW_RX_RC_STATS: + SET_UPLOAD_MASK(l_up_mask, HTT_DBG_STATS_RX_RATE_INFO); + break; + + /* txrx_fw_stats 5 */ + case WMA_FW_TX_CONCISE_STATS: + req.print.concise = 1; + /* No break here, since l_up_mask is same for + * both WMA_FW_TX_CONCISE_STATS & WMA_FW_TX_PPDU_STATS */ + + /* txrx_fw_stats 4 */ + case WMA_FW_TX_PPDU_STATS: + l_up_mask = 1 << HTT_DBG_STATS_TX_PPDU_LOG; + break; + + /* txrx_fw_stats 6 */ + case WMA_FW_TX_RC_STATS: + SET_UPLOAD_MASK(l_up_mask, HTT_DBG_STATS_TX_RATE_INFO); + break; + + /* txrx_fw_stats 12 */ + /* + * This is 1:1 correspondence with WMA defined value + * and the f/w bitmask. + */ + case WMA_FW_RX_REM_RING_BUF: + l_up_mask = 1 << HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO; + break; + + /* txrx_fw_stats 7 */ + case WMA_FW_TXBF_INFO_STATS: + l_up_mask = 1 << HTT_DBG_STATS_TXBF_INFO; + break; + + /* txrx_fw_stats 8 */ + case WMA_FW_SND_INFO_STATS: + l_up_mask = 1 << HTT_DBG_STATS_SND_INFO; + break; + + /* txrx_fw_stats 9 */ + case WMA_FW_ERROR_INFO_STATS: + l_up_mask = 1 << HTT_DBG_STATS_ERROR_INFO; + break; + + /* txrx_fw_stats 10 */ + case WMA_FW_TX_SELFGEN_INFO_STATS: + l_up_mask = 1 << HTT_DBG_STATS_TX_SELFGEN_INFO; + break; + + /* txrx_fw_stats 15 */ + /* + * This is 1:1 correspondence with WMA defined value + * and the f/w bitmask. + */ + case WMA_FW_RX_TXBF_MUSU_NDPA: + l_up_mask = 1 << HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT; + break; + + default: + cdf_print("%s %d Invalid value %d\n", + __func__, __LINE__, value); + return 0; + } + req.stats_type_upload_mask = l_up_mask; + + ol_txrx_fw_stats_get(vdev, &req); + + return 0; +} + +/** + * wmi_crash_inject() - inject fw crash + * @wma_handle: wma handle + * @type: type + * @delay_time_ms: delay time in ms + * + * Return: 0 for success or return error + */ +int wmi_crash_inject(wmi_unified_t wmi_handle, uint32_t type, + uint32_t delay_time_ms) +{ + int ret = 0; + WMI_FORCE_FW_HANG_CMD_fixed_param *cmd; + uint16_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_get_stats_rsp_buf() - fill get stats response buffer + * @get_stats_param: get stats parameters + * + * Return: stats response buffer + */ +static tAniGetPEStatsRsp *wma_get_stats_rsp_buf + (tAniGetPEStatsReq *get_stats_param) +{ + tAniGetPEStatsRsp *stats_rsp_params; + uint32_t 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 *) cdf_mem_malloc(len); + if (!stats_rsp_params) { + WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp"); + CDF_ASSERT(0); + return NULL; + } + + cdf_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 = WMA_GET_STATISTICS_RSP; + stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp); + stats_rsp_params->rc = CDF_STATUS_SUCCESS; + return stats_rsp_params; +} + +/** + * wma_get_stats_req() - get stats request + * @handle: wma handle + * @get_stats_param: stats params + * + * Return: none + */ +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; + uint8_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 { + cdf_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; + 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 = CDF_STATUS_E_FAILURE; + node->stats_rsp = NULL; + /* send response to UMAC */ + wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams, + 0); +end: + cdf_mem_free(get_stats_param); + WMA_LOGD("%s: Exit", __func__); + return; +} + +/** + * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID + * @vdev_id: vdev id + * @buffer_size: size of buffer + * + * Return: none + */ +void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size) +{ + tp_wma_handle wma; + struct beacon_info *beacon; + uint8_t *buf; + uint32_t buf_size; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + 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; + } + + cdf_spin_lock_bh(&beacon->lock); + + buf_size = cdf_nbuf_len(beacon->buf); + buf = cdf_mem_malloc(buf_size); + + if (!buf) { + cdf_spin_unlock_bh(&beacon->lock); + WMA_LOGE("%s: alloc failed for beacon buf", __func__); + return NULL; + } + + cdf_mem_copy(buf, cdf_nbuf_data(beacon->buf), buf_size); + + cdf_spin_unlock_bh(&beacon->lock); + + if (buffer_size) + *buffer_size = buf_size; + + return buf; +} + +/** + * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID + * @vdev_id: vdev id + * + * Return: mac address + */ +uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + 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; +} + +/** + * 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; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + 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; +} + +#if defined(QCA_WIFI_FTM) +/** + * wma_utf_rsp() - utf response + * @wma_handle: wma handle + * @payload: payload + * @len: length of payload + * + * Return: 0 for success or error code + */ +int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload, uint32_t *len) +{ + int ret = -1; + uint32_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 = (uint8_t *) cdf_mem_malloc((uint32_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; +} + +/** + * wma_post_ftm_response() - post ftm response to upper layer + * @wma_handle: wma handle + * + * Return: none + */ +static void wma_post_ftm_response(tp_wma_handle wma_handle) +{ + int ret; + uint8_t *payload; + uint32_t data_len; + cds_msg_t msg = { 0 }; + CDF_STATUS status; + + ret = wma_utf_rsp(wma_handle, &payload, &data_len); + + if (ret) { + return; + } + + sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg); + msg.bodyptr = payload; + msg.bodyval = 0; + + status = cds_mq_post_message(CDS_MQ_ID_SYS, &msg); + + if (status != CDF_STATUS_SUCCESS) { + WMA_LOGE("failed to post ftm response to SYS"); + cdf_mem_free(payload); + } +} + +/** + * wma_process_utf_event() - process utf event + * @handle: wma handle + * @datap: data buffer + * @dataplen: data length + * + * Return: 0 for success or error code + */ +static int +wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + SEG_HDR_INFO_STRUCT segHdrInfo; + uint8_t totalNumOfSegments, currentSeq; + WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_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; +} + +/** + * wma_utf_detach() - utf detach + * @wma_handle: wma handle + * + * Return: none + */ +void wma_utf_detach(tp_wma_handle wma_handle) +{ + if (wma_handle->utf_event_info.data) { + cdf_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); + } +} + +/** + * wma_utf_attach() - utf attach + * @wma_handle: wma handle + * + * Return: none + */ +void wma_utf_attach(tp_wma_handle wma_handle) +{ + int ret; + + wma_handle->utf_event_info.data = (unsigned char *) + cdf_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__); +} + +/** + * wmi_unified_pdev_utf_cmd() - send utf command to fw + * @wmi_handle: wmi handle + * @utf_payload: utf payload + * @len: length + * + * Return: 0 for success or error code + */ +static int +wmi_unified_pdev_utf_cmd(wmi_unified_t wmi_handle, uint8_t *utf_payload, + uint16_t len) +{ + wmi_buf_t buf; + uint8_t *cmd; + int ret = 0; + static uint8_t msgref = 1; + uint8_t segNumber = 0, segInfo, numSegments; + uint16_t chunk_len, total_bytes; + uint8_t *bufpos; + SEG_HDR_INFO_STRUCT segHdrInfo; + + bufpos = utf_payload; + total_bytes = len; + ASSERT(total_bytes / MAX_WMI_UTF_LEN == + (uint8_t) (total_bytes / MAX_WMI_UTF_LEN)); + numSegments = (uint8_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 -ENOMEM; + } + + cmd = (uint8_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; +} + +/** + * wma_utf_cmd() - utf command + * @wma_handle: wma handle + * @data: data + * @len: length + * + * Return: 0 for success or error code + */ +int wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data, uint16_t len) +{ + wma_handle->utf_event_info.length = 0; + return wmi_unified_pdev_utf_cmd(wma_handle->wmi_handle, data, len); +} + +/** + * wma_process_ftm_command() - process ftm command + * @wma_handle: wma handle + * @msg_buffer: message buffer + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS +wma_process_ftm_command(tp_wma_handle wma_handle, + struct ar6k_testmode_cmd_data *msg_buffer) +{ + uint8_t *data = NULL; + uint16_t len = 0; + int ret; + + if (!msg_buffer) + return CDF_STATUS_E_INVAL; + + if (cds_get_conparam() != CDF_FTM_MODE) { + WMA_LOGE("FTM command issued in non-FTM mode"); + cdf_mem_free(msg_buffer->data); + cdf_mem_free(msg_buffer); + return CDF_STATUS_E_NOSUPPORT; + } + + data = msg_buffer->data; + len = msg_buffer->len; + + ret = wma_utf_cmd(wma_handle, data, len); + + cdf_mem_free(msg_buffer->data); + cdf_mem_free(msg_buffer); + + if (ret) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} +#endif /* QCA_WIFI_FTM */ + +/** + * wma_get_wcnss_software_version() - get wcnss software version + * @p_cds_gctx: cds context + * @pVersion: version pointer + * @versionBufferSize: buffer size + * + * Return: CDF_STATUS_SUCCESS for success or error code + */ +CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx, + uint8_t *pVersion, + uint32_t versionBufferSize) +{ + tp_wma_handle wma_handle; + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wma_handle) { + WMA_LOGE("%s: Failed to get wma", __func__); + return CDF_STATUS_E_FAULT; + } + + snprintf(pVersion, versionBufferSize, "%x", + (unsigned int)wma_handle->target_fw_version); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_tx_rx_ss_from_config() - Get Tx/Rx spatial stream from HW mode config + * @mac_ss: Config which indicates the HW mode as per 'hw_mode_ss_config' + * @tx_ss: Contains the Tx spatial stream + * @rx_ss: Contains the Rx spatial stream + * + * Returns the number of spatial streams of Tx and Rx + * + * Return: None + */ +void wma_get_tx_rx_ss_from_config(enum hw_mode_ss_config mac_ss, + uint32_t *tx_ss, + uint32_t *rx_ss) +{ + switch (mac_ss) { + case HW_MODE_SS_0x0: + *tx_ss = 0; + *rx_ss = 0; + break; + case HW_MODE_SS_1x1: + *tx_ss = 1; + *rx_ss = 1; + break; + case HW_MODE_SS_2x2: + *tx_ss = 2; + *rx_ss = 2; + break; + case HW_MODE_SS_3x3: + *tx_ss = 3; + *rx_ss = 3; + break; + case HW_MODE_SS_4x4: + *tx_ss = 4; + *rx_ss = 4; + break; + default: + *tx_ss = 0; + *rx_ss = 0; + } +} + +/** + * wma_get_matching_hw_mode_index() - Get matching HW mode index + * @wma: WMA handle + * @mac0_tx_ss: Number of tx spatial streams of MAC0 + * @mac0_rx_ss: Number of rx spatial streams of MAC0 + * @mac0_bw: Bandwidth of MAC0 of type 'hw_mode_bandwidth' + * @mac1_tx_ss: Number of tx spatial streams of MAC1 + * @mac1_rx_ss: Number of rx spatial streams of MAC1 + * @mac1_bw: Bandwidth of MAC1 of type 'hw_mode_bandwidth' + * @dbs: DBS capability of type 'hw_mode_dbs_capab' + * @dfs: Agile DFS capability of type 'hw_mode_agile_dfs_capab' + * + * Fetches the HW mode index corresponding to the HW mode provided + * + * Return: Positive hw mode index in case a match is found or a negative + * value, otherwise + */ +static int8_t wma_get_matching_hw_mode_index(tp_wma_handle wma, + uint32_t mac0_tx_ss, uint32_t mac0_rx_ss, + enum hw_mode_bandwidth mac0_bw, + uint32_t mac1_tx_ss, uint32_t mac1_rx_ss, + enum hw_mode_bandwidth mac1_bw, + enum hw_mode_dbs_capab dbs, + enum hw_mode_agile_dfs_capab dfs) +{ + uint32_t i; + uint32_t t_mac0_tx_ss, t_mac0_rx_ss, t_mac0_bw; + uint32_t t_mac1_tx_ss, t_mac1_rx_ss, t_mac1_bw; + uint32_t dbs_mode, agile_dfs_mode; + int8_t found = -EINVAL; + + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return found; + } + + for (i = 0; i < wma->num_dbs_hw_modes; i++) { + t_mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac0_tx_ss != mac0_tx_ss) + continue; + + t_mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac0_rx_ss != mac0_rx_ss) + continue; + + t_mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac0_bw != mac0_bw) + continue; + + t_mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac1_tx_ss != mac1_tx_ss) + continue; + + t_mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac1_rx_ss != mac1_rx_ss) + continue; + + t_mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET( + wma->hw_mode.hw_mode_list[i]); + if (t_mac1_bw != mac1_bw) + continue; + + dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET( + wma->hw_mode.hw_mode_list[i]); + if (dbs_mode != dbs) + continue; + + agile_dfs_mode = WMI_DBS_HW_MODE_AGILE_DFS_GET( + wma->hw_mode.hw_mode_list[i]); + if (agile_dfs_mode != dfs) + continue; + + found = i; + WMA_LOGI("%s: hw_mode index %d found", + __func__, i); + break; + } + return found; +} + +/** + * wma_get_hw_mode_from_dbs_hw_list() - Get hw_mode index + * @mac0_ss: MAC0 spatial stream configuration + * @mac0_bw: MAC0 bandwidth configuration + * @mac1_ss: MAC1 spatial stream configuration + * @mac1_bw: MAC1 bandwidth configuration + * @dbs: HW DBS capability + * @dfs: HW Agile DFS capability + * + * Get the HW mode index corresponding to the HW modes spatial stream, + * bandwidth, DBS and Agile DFS capability + * + * Return: Index number if a match is found or -negative value if not found + */ +int8_t wma_get_hw_mode_idx_from_dbs_hw_list(enum hw_mode_ss_config mac0_ss, + enum hw_mode_bandwidth mac0_bw, + enum hw_mode_ss_config mac1_ss, + enum hw_mode_bandwidth mac1_bw, + enum hw_mode_dbs_capab dbs, + enum hw_mode_agile_dfs_capab dfs) +{ + tp_wma_handle wma; + uint32_t mac0_tx_ss, mac0_rx_ss; + uint32_t mac1_tx_ss, mac1_rx_ss; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return -EINVAL; + } + + wma_get_tx_rx_ss_from_config(mac0_ss, &mac0_tx_ss, &mac0_rx_ss); + wma_get_tx_rx_ss_from_config(mac1_ss, &mac1_tx_ss, &mac1_rx_ss); + + WMA_LOGI("%s: MAC0: TxSS=%d, RxSS=%d, BW=%d", + __func__, mac0_tx_ss, mac0_rx_ss, mac0_bw); + WMA_LOGI("%s: MAC1: TxSS=%d, RxSS=%d, BW=%d", + __func__, mac1_tx_ss, mac1_rx_ss, mac1_bw); + WMA_LOGI("%s: DBS capab=%d, Agile DFS capab=%d", + __func__, dbs, dfs); + + return wma_get_matching_hw_mode_index(wma, mac0_tx_ss, mac0_rx_ss, + mac0_bw, + mac1_tx_ss, mac1_rx_ss, + mac1_bw, + dbs, dfs); +} + +/** + * wma_get_hw_mode_from_idx() - Get HW mode based on index + * @idx: HW mode index + * @hw_mode: HW mode params + * + * Fetches the HW mode parameters + * + * Return: Success if hw mode is obtained and the hw mode params + */ +CDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx, + struct sir_hw_mode_params *hw_mode) +{ + tp_wma_handle wma; + uint32_t param; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (idx > wma->num_dbs_hw_modes) { + WMA_LOGE("%s: Invalid index", __func__); + return CDF_STATUS_E_FAILURE; + } + + param = wma->hw_mode.hw_mode_list[idx]; + + hw_mode->mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param); + hw_mode->mac0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param); + hw_mode->mac0_bw = WMI_DBS_HW_MODE_MAC0_BANDWIDTH_GET(param); + hw_mode->mac1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param); + hw_mode->mac1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param); + hw_mode->mac1_bw = WMI_DBS_HW_MODE_MAC1_BANDWIDTH_GET(param); + hw_mode->dbs_cap = WMI_DBS_HW_MODE_DBS_MODE_GET(param); + hw_mode->agile_dfs_cap = WMI_DBS_HW_MODE_AGILE_DFS_GET(param); + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_num_dbs_hw_modes() - Get number of HW mode + * + * Fetches the number of DBS HW modes returned by the FW + * + * Return: Negative value on error or returns the number of DBS HW modes + */ +int8_t wma_get_num_dbs_hw_modes(void) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return -EINVAL; + } + return wma->num_dbs_hw_modes; +} + +/** + * wma_is_hw_dbs_capable() - Check if HW is DBS capable + * + * Checks if the HW is DBS capable + * + * Return: true if the HW is DBS capable + */ +bool wma_is_hw_dbs_capable(void) +{ + tp_wma_handle wma; + uint32_t param, i, found = 0; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return false; + } + + if (!wma_is_dbs_enable()) { + WMA_LOGI("%s: DBS is disabled", __func__); + return false; + } + + WMA_LOGI("%s: DBS service bit map: %d", __func__, + WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)); + + /* The agreement with FW is that: To know if the target is DBS + * capable, DBS needs to be supported both in the HW mode list + * and in the service ready event + */ + if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT))) + return false; + + for (i = 0; i < wma->num_dbs_hw_modes; i++) { + param = wma->hw_mode.hw_mode_list[i]; + WMA_LOGI("%s: HW param: %x", __func__, param); + if (WMI_DBS_HW_MODE_DBS_MODE_GET(param)) { + WMA_LOGI("%s: HW (%d) is DBS capable", __func__, i); + found = 1; + break; + } + } + + if (found) + return true; + + return false; +} + +/** + * wma_is_hw_agile_dfs_capable() - Check if HW is agile DFS capable + * + * Checks if the HW is agile DFS capable + * + * Return: true if the HW is agile DFS capable + */ +bool wma_is_hw_agile_dfs_capable(void) +{ + tp_wma_handle wma; + uint32_t param, i, found = 0; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return false; + } + + if (!wma_is_agile_dfs_enable()) { + WMA_LOGI("%s: Agile DFS is disabled", __func__); + return false; + } + + WMA_LOGI("%s: DBS service bit map: %d", __func__, + WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT)); + + /* The agreement with FW is that to know if the target is Agile DFS + * capable, DBS needs to be supported in the service bit map and + * Agile DFS needs to be supported in the HW mode list + */ + if (!(WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT))) + return false; + + for (i = 0; i < wma->num_dbs_hw_modes; i++) { + param = wma->hw_mode.hw_mode_list[i]; + WMA_LOGI("%s: HW param: %x", __func__, param); + if (WMI_DBS_HW_MODE_AGILE_DFS_GET(param)) { + WMA_LOGI("%s: HW %d is agile DFS capable", + __func__, i); + found = 1; + break; + } + } + + if (found) + return true; + + return false; +} + +/** + * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev + * @vdev_id: VDEV whose MAC ID is required + * + * Get MAC id corresponding to a vdev id from the WMA structure + * + * Return: Negative value on failure and MAC id on success + */ +int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return -EINVAL; + } + + if (wma->interfaces) + return wma->interfaces[vdev_id].mac_id; + + return -EINVAL; +} + +/** + * wma_get_old_and_new_hw_index() - Get the old and new HW index + * @old_hw_mode_index: Value at this pointer contains the old HW mode index + * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX + * @new_hw_mode_index: Value at this pointer contains the new HW mode index + * Default value when not configured is WMA_DEFAULT_HW_MODE_INDEX + * + * Get the old and new HW index configured in the driver + * + * Return: Failure in case the HW mode indices cannot be fetched and Success + * otherwise. When no HW mode transition has happened the values of + * old_hw_mode_index and new_hw_mode_index will be the same. + */ +CDF_STATUS wma_get_old_and_new_hw_index(uint32_t *old_hw_mode_index, + uint32_t *new_hw_mode_index) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return CDF_STATUS_E_INVAL; + } + + *old_hw_mode_index = wma->old_hw_mode_index; + *new_hw_mode_index = wma->new_hw_mode_index; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_update_intf_hw_mode_params() - Update WMA params + * @vdev_id: VDEV id whose params needs to be updated + * @mac_id: MAC id to be updated + * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated + * + * Updates the MAC id, tx spatial stream, rx spatial stream in WMA + * + * Return: None + */ +void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id, + uint32_t cfgd_hw_mode_index) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return; + } + + if (!wma->interfaces) { + WMA_LOGE("%s: Interface is NULL", __func__); + return; + } + + wma->interfaces[vdev_id].mac_id = mac_id; + if (mac_id == 0) { + wma->interfaces[vdev_id].tx_streams = + WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(cfgd_hw_mode_index); + wma->interfaces[vdev_id].rx_streams = + WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(cfgd_hw_mode_index); + } else { + wma->interfaces[vdev_id].tx_streams = + WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(cfgd_hw_mode_index); + wma->interfaces[vdev_id].rx_streams = + WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(cfgd_hw_mode_index); + } +} + +/** + * wma_get_dbs_hw_modes() - Get the DBS HW modes for userspace + * @one_by_one_dbs: 1x1 DBS capability of HW + * @two_by_two_dbs: 2x2 DBS capability of HW + * + * Provides the DBS HW mode capability such as whether + * 1x1 DBS, 2x2 DBS is supported by the HW or not. + * + * Return: Failure in case of error and 0 on success + * one_by_one_dbs/two_by_two_dbs will be false, + * if they are not supported. + * one_by_one_dbs/two_by_two_dbs will be true, + * if they are supported. + * false values of one_by_one_dbs/two_by_two_dbs, + * indicate DBS is disabled + */ +CDF_STATUS wma_get_dbs_hw_modes(bool *one_by_one_dbs, bool *two_by_two_dbs) +{ + tp_wma_handle wma; + uint32_t i; + int8_t found_one_by_one = -EINVAL, found_two_by_two = -EINVAL; + uint32_t conf1_tx_ss, conf1_rx_ss; + uint32_t conf2_tx_ss, conf2_rx_ss; + + *one_by_one_dbs = false; + *two_by_two_dbs = false; + + if (wma_is_hw_dbs_capable() == false) { + WMA_LOGE("%s: HW is not DBS capable", __func__); + /* Caller will understand that DBS is disabled */ + return CDF_STATUS_SUCCESS; + + } + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return CDF_STATUS_E_FAILURE; + } + + /* To check 1x1 capability */ + wma_get_tx_rx_ss_from_config(HW_MODE_SS_1x1, + &conf1_tx_ss, &conf1_rx_ss); + /* To check 2x2 capability */ + wma_get_tx_rx_ss_from_config(HW_MODE_SS_2x2, + &conf2_tx_ss, &conf2_rx_ss); + + for (i = 0; i < wma->num_dbs_hw_modes; i++) { + uint32_t t_conf0_tx_ss, t_conf0_rx_ss; + uint32_t t_conf1_tx_ss, t_conf1_rx_ss; + uint32_t dbs_mode; + + t_conf0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + t_conf0_rx_ss = WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + t_conf1_tx_ss = WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + t_conf1_rx_ss = WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET( + wma->hw_mode.hw_mode_list[i]); + dbs_mode = WMI_DBS_HW_MODE_DBS_MODE_GET( + wma->hw_mode.hw_mode_list[i]); + + if (((((t_conf0_tx_ss == conf1_tx_ss) && + (t_conf0_rx_ss == conf1_rx_ss)) || + ((t_conf1_tx_ss == conf1_tx_ss) && + (t_conf1_rx_ss == conf1_rx_ss))) && + (dbs_mode == HW_MODE_DBS)) && + (found_one_by_one < 0)) { + found_one_by_one = i; + WMA_LOGI("%s: 1x1 hw_mode index %d found", + __func__, i); + /* Once an entry is found, need not check for 1x1 + * again + */ + continue; + } + + if (((((t_conf0_tx_ss == conf2_tx_ss) && + (t_conf0_rx_ss == conf2_rx_ss)) || + ((t_conf1_tx_ss == conf2_tx_ss) && + (t_conf1_rx_ss == conf2_rx_ss))) && + (dbs_mode == HW_MODE_DBS)) && + (found_two_by_two < 0)) { + found_two_by_two = i; + WMA_LOGI("%s: 2x2 hw_mode index %d found", + __func__, i); + /* Once an entry is found, need not check for 2x2 + * again + */ + continue; + } + } + + if (found_one_by_one >= 0) + *one_by_one_dbs = true; + if (found_two_by_two >= 0) + *two_by_two_dbs = true; + + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_current_hw_mode() - Get current HW mode params + * @hw_mode: HW mode parameters + * + * Provides the current HW mode parameters if the HW mode is initialized + * in the driver + * + * Return: Success if the current HW mode params are successfully populated + */ +CDF_STATUS wma_get_current_hw_mode(struct sir_hw_mode_params *hw_mode) +{ + CDF_STATUS status; + uint32_t old_hw_index = 0, new_hw_index = 0; + + WMA_LOGI("%s: Get the current hw mode", __func__); + + status = wma_get_old_and_new_hw_index(&old_hw_index, + &new_hw_index); + if (CDF_STATUS_SUCCESS != status) { + WMA_LOGE("%s: Failed to get HW mode index", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (new_hw_index == WMA_DEFAULT_HW_MODE_INDEX) { + WMA_LOGE("%s: HW mode is not yet initialized", __func__); + return CDF_STATUS_E_FAILURE; + } + + status = wma_get_hw_mode_from_idx(new_hw_index, hw_mode); + if (CDF_STATUS_SUCCESS != status) { + WMA_LOGE("%s: Failed to get HW mode index", __func__); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_is_dbs_enable() - Check if master DBS control is enabled + * + * Checks if the master DBS control is enabled. This will be used + * to override any other DBS capability + * + * Return: True if master DBS control is enabled + */ +bool wma_is_dbs_enable(void) +{ + tp_wma_handle wma; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return false; + } + + WMA_LOGD("%s: DBS=%d", __func__, + WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config)); + + if (WMI_DBS_FW_MODE_CFG_DBS_GET(wma->dual_mac_cfg.cur_fw_mode_config)) + return true; + + return false; +} + +/** + * wma_is_agile_dfs_enable() - Check if master Agile DFS control is enabled + * + * Checks if the master Agile DFS control is enabled. This will be used + * to override any other Agile DFS capability + * + * Return: True if master Agile DFS control is enabled + */ +bool wma_is_agile_dfs_enable(void) +{ + tp_wma_handle wma; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return false; + } + + WMA_LOGD("%s: DFS=%d Single mac with DFS=%d", __func__, + WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET( + wma->dual_mac_cfg.cur_fw_mode_config), + WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET( + wma->dual_mac_cfg.cur_scan_config)); + + if ((WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET( + wma->dual_mac_cfg.cur_fw_mode_config)) && + (WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET( + wma->dual_mac_cfg.cur_scan_config))) + return true; + + return false; +} + +/** + * wma_get_updated_scan_config() - Get the updated scan configuration + * @scan_config: Pointer containing the updated scan config + * @dbs_scan: 0 or 1 indicating if DBS scan needs to be enabled/disabled + * @dbs_plus_agile_scan: 0 or 1 indicating if DBS plus agile scan needs to be + * enabled/disabled + * @single_mac_scan_with_dfs: 0 or 1 indicating if single MAC scan with DFS + * needs to be enabled/disabled + * + * Takes the current scan configuration and set the necessary scan config + * bits to either 0/1 and provides the updated value to the caller who + * can use this to pass it on to the FW + * + * Return: 0 on success + */ +CDF_STATUS wma_get_updated_scan_config(uint32_t *scan_config, + bool dbs_scan, + bool dbs_plus_agile_scan, + bool single_mac_scan_with_dfs) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return CDF_STATUS_E_FAILURE; + } + *scan_config = wma->dual_mac_cfg.cur_scan_config; + + WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET(*scan_config, dbs_scan); + WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET(*scan_config, + dbs_plus_agile_scan); + WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET(*scan_config, + single_mac_scan_with_dfs); + + WMA_LOGD("%s: *scan_config:%x ", __func__, *scan_config); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_updated_fw_mode_config() - Get the updated fw mode configuration + * @fw_mode_config: Pointer containing the updated fw mode config + * @dbs: 0 or 1 indicating if DBS needs to be enabled/disabled + * @agile_dfs: 0 or 1 indicating if agile DFS needs to be enabled/disabled + * + * Takes the current fw mode configuration and set the necessary fw mode config + * bits to either 0/1 and provides the updated value to the caller who + * can use this to pass it on to the FW + * + * Return: 0 on success + */ +CDF_STATUS wma_get_updated_fw_mode_config(uint32_t *fw_mode_config, + bool dbs, + bool agile_dfs) +{ + tp_wma_handle wma; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return CDF_STATUS_E_FAILURE; + } + *fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config; + + WMI_DBS_FW_MODE_CFG_DBS_SET(*fw_mode_config, dbs); + WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET(*fw_mode_config, agile_dfs); + + WMA_LOGD("%s: *fw_mode_config:%x ", __func__, *fw_mode_config); + return CDF_STATUS_SUCCESS; +} + +/** + * wma_get_dbs_config() - Get DBS bit + * + * Gets the DBS bit of fw_mode_config_bits + * + * Return: 0 or 1 to indicate the DBS bit + */ +bool wma_get_dbs_config(void) +{ + tp_wma_handle wma; + uint32_t fw_mode_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config; + + return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config); +} + +/** + * wma_get_agile_dfs_config() - Get Agile DFS bit + * + * Gets the Agile DFS bit of fw_mode_config_bits + * + * Return: 0 or 1 to indicate the Agile DFS bit + */ +bool wma_get_agile_dfs_config(void) +{ + tp_wma_handle wma; + uint32_t fw_mode_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + fw_mode_config = wma->dual_mac_cfg.cur_fw_mode_config; + + return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config); +} + +/** + * wma_get_dbs_scan_config() - Get DBS scan bit + * + * Gets the DBS scan bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the DBS scan bit + */ +bool wma_get_dbs_scan_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.cur_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config); +} + +/** + * wma_get_dbs_plus_agile_scan_config() - Get DBS plus agile scan bit + * + * Gets the DBS plus agile scan bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the DBS plus agile scan bit + */ +bool wma_get_dbs_plus_agile_scan_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.cur_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config); +} + +/** + * wma_get_single_mac_scan_with_dfs_config() - Get Single MAC scan with DFS bit + * + * Gets the Single MAC scan with DFS bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the Single MAC scan with DFS bit + */ +bool wma_get_single_mac_scan_with_dfs_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.cur_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config); +} + +/** + * wma_is_dual_mac_disabled_in_ini() - Check if dual mac is disabled in INI + * + * Checks if the dual mac feature is disabled in INI + * + * Return: true if the dual mac feature is disabled from INI + */ +bool wma_is_dual_mac_disabled_in_ini(void) +{ + tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE); + + if (!mac) { + WMA_LOGE("%s: Invalid mac pointer", __func__); + return true; + } + + if (mac->dual_mac_feature_disable) + return true; + + return false; +} + +/** + * wma_get_prev_dbs_config() - Get prev DBS bit + * + * Gets the previous DBS bit of fw_mode_config_bits + * + * Return: 0 or 1 to indicate the DBS bit + */ +bool wma_get_prev_dbs_config(void) +{ + tp_wma_handle wma; + uint32_t fw_mode_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config; + + return WMI_DBS_FW_MODE_CFG_DBS_GET(fw_mode_config); +} + +/** + * wma_get_prev_agile_dfs_config() - Get prev Agile DFS bit + * + * Gets the previous Agile DFS bit of fw_mode_config_bits + * + * Return: 0 or 1 to indicate the Agile DFS bit + */ +bool wma_get_prev_agile_dfs_config(void) +{ + tp_wma_handle wma; + uint32_t fw_mode_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + fw_mode_config = wma->dual_mac_cfg.prev_fw_mode_config; + + return WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_mode_config); +} + +/** + * wma_get_prev_dbs_scan_config() - Get prev DBS scan bit + * + * Gets the previous DBS scan bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the DBS scan bit + */ +bool wma_get_prev_dbs_scan_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.prev_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config); +} + +/** + * wma_get_prev_dbs_plus_agile_scan_config() - Get prev DBS plus agile scan bit + * + * Gets the previous DBS plus agile scan bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the DBS plus agile scan bit + */ +bool wma_get_prev_dbs_plus_agile_scan_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.prev_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config); +} + +/** + * wma_get_prev_single_mac_scan_with_dfs_config() - Get prev Single MAC scan + * with DFS bit + * + * Gets the previous Single MAC scan with DFS bit of concurrent_scan_config_bits + * + * Return: 0 or 1 to indicate the Single MAC scan with DFS bit + */ +bool wma_get_prev_single_mac_scan_with_dfs_config(void) +{ + tp_wma_handle wma; + uint32_t scan_config; + + if (wma_is_dual_mac_disabled_in_ini()) + return false; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + /* We take that it is disabled and proceed */ + return false; + } + scan_config = wma->dual_mac_cfg.prev_scan_config; + + return WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config); +} + +/** + * wma_is_scan_simultaneous_capable() - Check if scan parallelization is + * supported or not + * + * currently scan parallelization feature support is dependent on DBS but + * it can be independent in future. + * + * Return: True if master DBS control is enabled + */ +bool wma_is_scan_simultaneous_capable(void) +{ + if (wma_is_hw_dbs_capable()) + return true; + + return false; +} diff --git a/core/wma/src/wma_utils_ut.c b/core/wma/src/wma_utils_ut.c new file mode 100644 index 000000000000..d36c6ca54c8f --- /dev/null +++ b/core/wma/src/wma_utils_ut.c @@ -0,0 +1,82 @@ +/* + * 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: wma_utils_ut.c + * This file contains utilities related to unit test framework + */ + +/* Header files */ + +#include "wma.h" + +/** + * wma_set_dbs_capability_ut() - Set DBS capability for UT framework + * @dbs: Value of DBS capability to be set + * + * Sets the DBS capability for unit test framework. If the HW mode is + * already sent by the FW, only the DBS capability needs to be set. If the + * FW did not send any HW mode list, a single entry is created and DBS mode + * is set in it. The DBS capability is also set in the service bit map. + * + * Return: None + */ +void wma_set_dbs_capability_ut(uint32_t dbs) +{ + tp_wma_handle wma; + uint32_t i; + + wma = cds_get_context(CDF_MODULE_ID_WMA); + if (!wma) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + return; + } + + /* DBS list was not configured by the FW, so + * for UT, we can configure a single entry + */ + if (wma->hw_mode.hw_mode_list == NULL) { + wma->num_dbs_hw_modes = 1; + wma->hw_mode.hw_mode_list = + cdf_mem_malloc(sizeof(*wma->hw_mode.hw_mode_list) * + wma->num_dbs_hw_modes); + if (!wma->hw_mode.hw_mode_list) { + WMA_LOGE("%s: Memory allocation failed for UT-DBS", + __func__); + return; + } + wma->hw_mode.hw_mode_list[0] = 0x0000; + } + + for (i = 0; i < wma->num_dbs_hw_modes; i++) { + WMI_DBS_HW_MODE_DBS_MODE_SET(wma->hw_mode.hw_mode_list[i], + dbs); + } + + WMI_SERVICE_ENABLE(wma->wmi_service_bitmap, + WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT); +} diff --git a/core/wmi/wmi_tlv_helper.c b/core/wmi/wmi_tlv_helper.c new file mode 100644 index 000000000000..0e35755536c3 --- /dev/null +++ b/core/wmi/wmi_tlv_helper.c @@ -0,0 +1,1190 @@ +/* + * 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. + */ + +/* 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 cmd_attr_list[] = { + WMITLV_ALL_CMD_LIST(WMITLV_GET_CMD_EVT_ATTRB_LIST) +}; + +A_UINT32 evt_attr_list[] = { + WMITLV_ALL_EVT_LIST(WMITLV_GET_CMD_EVT_ATTRB_LIST) +}; + +#ifdef NO_DYNAMIC_MEM_ALLOC +static wmitlv_cmd_param_info *g_wmi_static_cmd_param_info_buf = NULL; +A_UINT32 g_wmi_static_max_cmd_param_tlvs = 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_wmi_static_cmd_param_info_buf = param_tlv_buf; + g_wmi_static_max_cmd_param_tlvs = 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 = &cmd_attr_list[0]; + num_entries = CDF_ARRAY_SIZE(cmd_attr_list); + } else { + pAttrArrayList = &evt_attr_list[0]; + num_entries = CDF_ARRAY_SIZE(evt_attr_list); + } + + 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 < num_of_elems; + idx++) { + in_tlv_len = + WMITLV_GET_TLVLEN + (WMITLV_GET_HDR + (tlv_buf_ptr)); + if ((in_tlv_len + + WMI_TLV_HDR_SIZE) + != + attr_struct_ptr. + tag_struct_size) { + wmi_tlv_print_error + ("%s: ERROR: TLV has wrong length for Cmd=0x%x. Tag_order=%d Tag=%d, Given_Len:%zu Expected_Len=%d.\n", + __func__, + wmi_cmd_event_id, + tlv_index, + curr_tlv_tag, + (in_tlv_len + + + WMI_TLV_HDR_SIZE), + attr_struct_ptr. + tag_struct_size); + goto Error_wmitlv_check_tlv_params; + } + tlv_buf_ptr += + in_tlv_len + + WMI_TLV_HDR_SIZE; + } + } else + if ((curr_tlv_tag == + WMITLV_TAG_ARRAY_UINT32) + || (curr_tlv_tag == + WMITLV_TAG_ARRAY_BYTE) + || (curr_tlv_tag == + WMITLV_TAG_ARRAY_FIXED_STRUC)) + { + /* Nothing to verify here */ + } else { + wmi_tlv_print_error + ("%s ERROR Need to handle the Array tlv %d for variable length for Cmd=0x%x\n", + __func__, + attr_struct_ptr.tag_id, + wmi_cmd_event_id); + goto Error_wmitlv_check_tlv_params; + } + } + } + } else { + /* Non-array TLV. */ + + if ((curr_tlv_len + WMI_TLV_HDR_SIZE) != + attr_struct_ptr.tag_struct_size) { + wmi_tlv_print_error + ("%s: ERROR: TLV has wrong length for Cmd=0x%x. Given=%zu, Expected=%d.\n", + __func__, wmi_cmd_event_id, + (curr_tlv_len + WMI_TLV_HDR_SIZE), + attr_struct_ptr.tag_struct_size); + goto Error_wmitlv_check_tlv_params; + } + } + + /* Check TLV length is aligned to 4 bytes or not */ + if ((curr_tlv_len % sizeof(A_UINT32)) != 0) { + wmi_tlv_print_error + ("%s: ERROR: TLV length %d for Cmd=0x%x is not aligned to %zu bytes\n", + __func__, curr_tlv_len, wmi_cmd_event_id, + sizeof(A_UINT32)); + goto Error_wmitlv_check_tlv_params; + } + + tlv_index++; + buf_ptr += curr_tlv_len + WMI_TLV_HDR_SIZE; + buf_idx += curr_tlv_len + WMI_TLV_HDR_SIZE; + } + + if (tlv_index != expected_num_tlvs) { + wmi_tlv_print_verbose + ("%s: INFO: Less number of TLVs filled for Cmd=0x%x Filled %d Expected=%d\n", + __func__, wmi_cmd_event_id, tlv_index, expected_num_tlvs); + } + + return (0); +Error_wmitlv_check_tlv_params: + return (-1); +} + +/* + * Helper Function to vaidate the prepared TLV's for an WMI event to be sent + * Return 0 if success. + * <0 if failure. + */ +int +wmitlv_check_event_tlv_params(void *os_handle, void *param_struc_ptr, + A_UINT32 param_buf_len, A_UINT32 wmi_cmd_event_id) +{ + A_UINT32 is_cmd_id = 0; + return (wmitlv_check_tlv_params + (os_handle, param_struc_ptr, param_buf_len, is_cmd_id, + wmi_cmd_event_id)); +} + +/* + * Helper Function to vaidate the prepared TLV's for an WMI command to be sent + * Return 0 if success. + * <0 if failure. + */ +int +wmitlv_check_command_tlv_params(void *os_handle, void *param_struc_ptr, + A_UINT32 param_buf_len, + A_UINT32 wmi_cmd_event_id) +{ + A_UINT32 is_cmd_id = 1; + return (wmitlv_check_tlv_params + (os_handle, param_struc_ptr, param_buf_len, is_cmd_id, + wmi_cmd_event_id)); +} + +/* + * Helper Function to vaidate the TLV's coming for an event/command and also pads data to TLV's if necessary + * Return 0 if success. + <0 if failure. + */ +static int +wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr, + A_UINT32 param_buf_len, A_UINT32 is_cmd_id, + A_UINT32 wmi_cmd_event_id, void **wmi_cmd_struct_ptr) +{ + wmitlv_attributes_struc attr_struct_ptr; + A_UINT32 buf_idx = 0; + A_UINT32 tlv_index = 0; + A_UINT32 num_of_elems = 0; + int tlv_size_diff = 0; + A_UINT8 *buf_ptr = (unsigned char *)param_struc_ptr; + wmitlv_cmd_param_info *cmd_param_tlvs_ptr = NULL; + A_UINT32 remaining_expected_tlvs = 0xFFFFFFFF; + A_UINT32 len_wmi_cmd_struct_buf; + + /* 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); + return -1; + } + /* NOTE: the returned number of TLVs is in "attr_struct_ptr.cmd_num_tlv" */ + + /* Create base structure of format wmi_cmd_event_id##_param_tlvs */ + len_wmi_cmd_struct_buf = + attr_struct_ptr.cmd_num_tlv * sizeof(wmitlv_cmd_param_info); +#ifndef NO_DYNAMIC_MEM_ALLOC + /* Dynamic memory allocation supported */ + wmi_tlv_os_mem_alloc(os_handle, *wmi_cmd_struct_ptr, + len_wmi_cmd_struct_buf); +#else + /* Dynamic memory allocation is not supported. Use the buffer g_wmi_static_cmd_param_info_buf, which should be set using wmi_tlv_set_static_param_tlv_buf(), + for base structure of format wmi_cmd_event_id##_param_tlvs */ + *wmi_cmd_struct_ptr = g_wmi_static_cmd_param_info_buf; + if (attr_struct_ptr.cmd_num_tlv > g_wmi_static_max_cmd_param_tlvs) { + /* 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_wmi_static_max_cmd_param_tlvs); + 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; i < num_of_elems; i++) { + if (tlv_size_diff > 0) { + /* 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 < num_of_elems; i++) { + src_addr = + tlv_buf_ptr + in_tlv_len; + if (i != (num_of_elems - 1)) { + /* Need not move anything for last element in the array */ + dst_addr = + tlv_buf_ptr + + in_tlv_len + + num_padding_bytes; + buf_mov_len = + curr_tlv_len - + ((i + + 1) * in_tlv_len); + + wmi_tlv_OS_MEMMOVE + (dst_addr, src_addr, + buf_mov_len); + } + + /* Set the padding bytes to zeroes */ + wmi_tlv_OS_MEMZERO(src_addr, + num_padding_bytes); + + tlv_buf_ptr += + attr_struct_ptr. + tag_struct_size; + } + + /* Update the number of padding bytes to total number of bytes padded for all elements in the array */ + num_padding_bytes = + num_padding_bytes * num_of_elems; + + new_tlv_buf = buf_ptr; + } else { + /* Incoming structure size is greater than expected size then this needs shrinking for each element in the array */ + + /* Find amount of bytes to be shrinked for one element */ + num_padding_bytes = tlv_size_diff * -1; + + /* Move subsequent elements of array up by number of bytes to be shrinked for one element */ + tlv_buf_ptr = buf_ptr; + for (i = 0; i < (num_of_elems - 1); i++) { + src_addr = + tlv_buf_ptr + in_tlv_len; + dst_addr = + tlv_buf_ptr + in_tlv_len + + num_padding_bytes; + buf_mov_len = + curr_tlv_len - + ((i + 1) * in_tlv_len); + + wmi_tlv_OS_MEMMOVE(dst_addr, + src_addr, + buf_mov_len); + + tlv_buf_ptr += + attr_struct_ptr. + tag_struct_size; + } + + /* Move subsequent TLVs by number of bytes to be shrinked 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); + } + + /* 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; i < num_whitelist; i++) { + if (version_whitelist_table[i].major != my_major_vers) { + continue; /* skip */ + } + if ((version_whitelist_table[i].namespace_0 != + my_vers->abi_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/core/wmi/wmi_tlv_platform.c b/core/wmi/wmi_tlv_platform.c new file mode 100644 index 000000000000..f3c20be4f05b --- /dev/null +++ b/core/wmi/wmi_tlv_platform.c @@ -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. + */ + +/* + * LMAC offload interface functions for WMI TLV Interface + */ + +#include "ol_if_athvar.h" +#include /* cdf_mem_malloc,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 cdf_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 cdf_mem_free +#endif diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c new file mode 100644 index 000000000000..52a3ea5fedaa --- /dev/null +++ b/core/wmi/wmi_unified.c @@ -0,0 +1,1222 @@ +/* + * 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. + */ + +/* + * 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 "mac_trace.h" + +#define WMI_MIN_HEAD_ROOM 64 + +#ifdef WMI_INTERFACE_EVENT_LOGGING +/* WMI commands */ +uint32_t g_wmi_command_buf_idx = 0; +struct wmi_command_debug wmi_command_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +/* WMI commands TX completed */ +uint32_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 */ +uint32_t g_wmi_event_buf_idx = 0; +struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; + +/* WMI events when queued */ +uint32_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; \ + cdf_mem_copy(wmi_command_log_buffer[g_wmi_command_buf_idx].data, b, 16); \ + wmi_command_log_buffer[g_wmi_command_buf_idx].time = \ + cdf_get_log_timestamp(); \ + 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; \ + cdf_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 = \ + cdf_get_log_timestamp(); \ + 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; \ + cdf_mem_copy(wmi_event_log_buffer[g_wmi_event_buf_idx].data, b, 16); \ + wmi_event_log_buffer[g_wmi_event_buf_idx].time = \ + cdf_get_log_timestamp(); \ + 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; \ + cdf_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 = \ + cdf_get_log_timestamp(); \ + 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 */ + +#ifdef MEMORY_DEBUG +wmi_buf_t +wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, uint8_t *file_name, + uint32_t line_num) +{ + wmi_buf_t wmi_buf; + + if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) { + CDF_ASSERT(0); + return NULL; + } + + wmi_buf = cdf_nbuf_alloc_debug(NULL, + roundup(len + WMI_MIN_HEAD_ROOM, 4), + WMI_MIN_HEAD_ROOM, 4, false, file_name, + line_num); + + if (!wmi_buf) + return NULL; + + /* Clear the wmi buffer */ + OS_MEMZERO(cdf_nbuf_data(wmi_buf), len); + + /* + * Set the length of the buffer to match the allocation size. + */ + cdf_nbuf_set_pktlen(wmi_buf, len); + + return wmi_buf; +} + +void wmi_buf_free(wmi_buf_t net_buf) +{ + cdf_nbuf_free(net_buf); +} +#else +wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len) +{ + wmi_buf_t wmi_buf; + + if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) { + CDF_ASSERT(0); + return NULL; + } + + wmi_buf = cdf_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(cdf_nbuf_data(wmi_buf), len); + + /* + * Set the length of the buffer to match the allocation size. + */ + cdf_nbuf_set_pktlen(wmi_buf, len); + return wmi_buf; +} + +void wmi_buf_free(wmi_buf_t net_buf) +{ + cdf_nbuf_free(net_buf); +} +#endif + +/** + * 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; +} + +static uint8_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_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); + /* 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 QCA_WIFI_3_0_EMU +static inline void wma_log_cmd_id(WMI_CMD_ID cmd_id) +{ + WMA_LOGE("Send WMI command:%s command_id:%d", + get_wmi_cmd_string(cmd_id), cmd_id); +} +#else +static inline void wma_log_cmd_id(WMI_CMD_ID cmd_id) +{ + WMA_LOGD("Send WMI command:%s command_id:%d", + get_wmi_cmd_string(cmd_id), cmd_id); +} +#endif + +/* WMI command API */ +int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, + WMI_CMD_ID cmd_id) +{ + HTC_PACKET *pkt; + A_STATUS status; + struct ol_softc *scn; + + if (cdf_atomic_read(&wmi_handle->is_target_suspended) && + ((WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) && + (WMI_PDEV_RESUME_CMDID != cmd_id))) { + pr_err("%s: Target is suspended could not send WMI command\n", + __func__); + CDF_ASSERT(0); + return -EBUSY; + } + + /* Do sanity check on the TLV parameter structure */ + { + void *buf_ptr = (void *)cdf_nbuf_data(buf); + + if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id) + != 0) { + cdf_print + ("\nERROR: %s: Invalid WMI Parameter Buffer for Cmd:%d\n", + __func__, cmd_id); + return -1; + } + } + + if (cdf_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(cdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id); + + cdf_atomic_inc(&wmi_handle->pending_cmds); + if (cdf_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) { + scn = cds_get_context(CDF_MODULE_ID_HIF); + 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); */ + cdf_atomic_dec(&wmi_handle->pending_cmds); + pr_err("%s: MAX 1024 WMI Pending cmds reached.\n", __func__); + CDF_BUG(0); + return -EBUSY; + } + + pkt = cdf_mem_malloc(sizeof(*pkt)); + if (!pkt) { + cdf_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, + cdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR), + /* htt_host_data_dl_len(buf)+20 */ + wmi_handle->wmi_endpoint_id, 0 /*htc_tag */ ); + + SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf); + + wma_log_cmd_id(cmd_id); + +#ifdef WMI_INTERFACE_EVENT_LOGGING + cdf_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, ((uint32_t *) cdf_nbuf_data(buf) + 2)); + cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + + status = htc_send_pkt(wmi_handle->htc_handle, pkt); + + if (A_OK != status) { + cdf_atomic_dec(&wmi_handle->pending_cmds); + pr_err("%s %d, htc_send_pkt 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) +{ + uint32_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) +{ + uint32_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) +{ + uint32_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) +{ + uint32_t id; + uint8_t *event; + uint16_t len; + int status = -1; + uint32_t idx = 0; + + ASSERT(evt_buf != NULL); + + id = WMI_GET_FIELD(cdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + + if (cdf_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 = cdf_nbuf_data(evt_buf); + len = cdf_nbuf_len(evt_buf); + + /* Call the WMI registered event handler */ + status = wmi_handle->event_handler[idx] (wmi_handle->scn_handle, + event, len); + +end: + cdf_nbuf_free(evt_buf); + return status; +} +#endif /* 0 */ +/* + * Event process by below function will be in tasket context. + * Please use this method only for time sensitive functions. + */ +static void wmi_process_fw_event_tasklet_ctx(struct wmi_unified *wmi_handle, + HTC_PACKET *htc_packet) +{ + + wmi_buf_t evt_buf; + evt_buf = (wmi_buf_t) htc_packet->pPktContext; + + __wmi_control_rx(wmi_handle, evt_buf); + return; +} + +/* + * Event process by below function will be in mc_thread context. + * By default all event will be executed in mc_thread context. + * Use this method for all events which are processed by protocol stack. + * This method will reduce context switching and race conditions. + */ +static void wmi_process_fw_event_mc_thread_ctx(struct wmi_unified *wmi_handle, + HTC_PACKET *htc_packet) +{ + wmi_buf_t evt_buf; + evt_buf = (wmi_buf_t) htc_packet->pPktContext; + + wmi_handle->wma_process_fw_event_handler_cbk(wmi_handle, evt_buf); + return; +} + +/* + * Event process by below function will be in worker thread context. + * Use this method for events which are not critical and not + * handled in protocol stack. + */ +static void wmi_process_fw_event_worker_thread_ctx + (struct wmi_unified *wmi_handle, HTC_PACKET *htc_packet) +{ + wmi_buf_t evt_buf; + uint32_t id; + uint8_t *data; + + evt_buf = (wmi_buf_t) htc_packet->pPktContext; + id = WMI_GET_FIELD(cdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + data = cdf_nbuf_data(evt_buf); + + cdf_spin_lock_bh(&wmi_handle->wmi_record_lock); + /* Exclude 4 bytes of TLV header */ + WMI_RX_EVENT_RECORD(id, ((uint8_t *) data + 4)); + cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); + cdf_spin_lock_bh(&wmi_handle->eventq_lock); + cdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf); + cdf_spin_unlock_bh(&wmi_handle->eventq_lock); + schedule_work(&wmi_handle->rx_event_work); + return; +} + +/* + * 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; + uint32_t id; + + evt_buf = (wmi_buf_t) htc_packet->pPktContext; + id = WMI_GET_FIELD(cdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + switch (id) { + /*Event will be handled in tasklet ctx*/ + case WMI_TX_PAUSE_EVENTID: + case WMI_WOW_WAKEUP_HOST_EVENTID: + case WMI_PDEV_RESUME_EVENTID: + case WMI_D0_WOW_DISABLE_ACK_EVENTID: + wmi_process_fw_event_tasklet_ctx + (wmi_handle, htc_packet); + break; + /*Event will be handled in worker thread ctx*/ + case WMI_DEBUG_MESG_EVENTID: + case WMI_DFS_RADAR_EVENTID: + case WMI_PHYERR_EVENTID: + case WMI_PEER_STATE_EVENTID: + case WMI_MGMT_RX_EVENTID: + case WMI_ROAM_EVENTID: + wmi_process_fw_event_worker_thread_ctx + (wmi_handle, htc_packet); + break; + /*Event will be handled in mc_thread ctx*/ + default: + wmi_process_fw_event_mc_thread_ctx + (wmi_handle, htc_packet); + break; + } +} + +void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) +{ + __wmi_control_rx(wmi_handle, evt_buf); +} + +void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) +{ + uint32_t id; + uint8_t *data; + uint32_t len; + void *wmi_cmd_struct_ptr = NULL; + int tlv_ok_status = 0; + + id = WMI_GET_FIELD(cdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID); + + if (cdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL) + goto end; + + data = cdf_nbuf_data(evt_buf); + len = cdf_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; + } + + if (id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) { + uint32_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 + cdf_spin_lock_bh(&wmi_handle->wmi_record_lock); + /* Exclude 4 bytes of TLV header */ + WMI_EVENT_RECORD(id, ((uint8_t *) data + 4)); + cdf_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_SERVICE_READY_EXT_EVENTID: + WMA_LOGA("%s: WMI UNIFIED SERVICE READY Extended event", + __func__); + wma_rx_service_ready_ext_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); + cdf_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; + + cdf_spin_lock_bh(&wmi->eventq_lock); + buf = cdf_nbuf_queue_remove(&wmi->event_queue); + cdf_spin_unlock_bh(&wmi->eventq_lock); + while (buf) { + __wmi_control_rx(wmi, buf); + cdf_spin_lock_bh(&wmi->eventq_lock); + buf = cdf_nbuf_queue_remove(&wmi->event_queue); + cdf_spin_unlock_bh(&wmi->eventq_lock); + } +} + +/* WMI Initialization functions */ + +void *wmi_unified_attach(ol_scn_t scn_handle, + wma_process_fw_event_handler_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; + cdf_atomic_init(&wmi_handle->pending_cmds); + cdf_atomic_init(&wmi_handle->is_target_suspended); + cdf_spinlock_init(&wmi_handle->eventq_lock); + cdf_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 + cdf_spinlock_init(&wmi_handle->wmi_record_lock); +#endif + wmi_handle->wma_process_fw_event_handler_cbk = func; + return wmi_handle; +} + +void wmi_unified_detach(struct wmi_unified *wmi_handle) +{ + wmi_buf_t buf; + + cds_flush_work(&wmi_handle->rx_event_work); + cdf_spin_lock_bh(&wmi_handle->eventq_lock); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + while (buf) { + cdf_nbuf_free(buf); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + } + cdf_spin_unlock_bh(&wmi_handle->eventq_lock); + if (wmi_handle != NULL) { + OS_FREE(wmi_handle); + wmi_handle = NULL; + } +} + +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 + uint32_t cmd_id; +#endif + + ASSERT(wmi_cmd_buf); +#ifdef WMI_INTERFACE_EVENT_LOGGING + cmd_id = WMI_GET_FIELD(cdf_nbuf_data(wmi_cmd_buf), + WMI_CMD_HDR, COMMANDID); + +#ifdef QCA_WIFI_3_0_EMU + printk("\nSent WMI command:%s command_id:0x%x over dma and recieved tx complete interupt\n", + get_wmi_cmd_string(cmd_id), cmd_id); +#endif + + cdf_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, + ((uint32_t *) cdf_nbuf_data(wmi_cmd_buf) + + 2)); + cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); +#endif + cdf_nbuf_free(wmi_cmd_buf); + cdf_mem_free(htc_pkt); + cdf_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 = + htc_connect_service(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; + + htc_get_control_endpoint_tx_host_credits(wmi_handle->htc_handle, + &host_credits); + return host_credits; +} + +int wmi_get_pending_cmds(wmi_unified_t wmi_handle) +{ + return cdf_atomic_read(&wmi_handle->pending_cmds); +} + +void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val) +{ + cdf_atomic_set(&wmi_handle->is_target_suspended, val); +} + diff --git a/core/wmi/wmi_unified_api.h b/core/wmi/wmi_unified_api.h new file mode 100644 index 000000000000..5fc132206699 --- /dev/null +++ b/core/wmi/wmi_unified_api.h @@ -0,0 +1,160 @@ +/* + * 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 cdf_nbuf_t wmi_buf_t; +#define wmi_buf_data(_buf) cdf_nbuf_data(_buf) + +/** + * attach for unified WMI + * + * @param scn_handle : handle to SCN. + * @return opaque handle. + */ +void *wmi_unified_attach(void *scn_handle, + int (*func)(struct wmi_unified *, wmi_buf_t)); +/** + * detach for unified WMI + * + * @param wmi_handle : handle to WMI. + * @return void. + */ +void wmi_unified_detach(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. + */ +#ifdef MEMORY_DEBUG +#define wmi_buf_alloc(h, l) wmi_buf_alloc_debug(h, l, __FILE__, __LINE__) +wmi_buf_t +wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, + uint8_t *file_name, uint32_t line_num); +#else +wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len); +#endif + +/** + * generic function frees WMI net buffer + * + * @param net_buf : Pointer ot net_buf to be freed + */ +void wmi_buf_free(wmi_buf_t net_buf); + +/** + * 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); + +/** + * WMA Callback to process fw event. + */ +typedef int (*wma_process_fw_event_handler_cbk)(struct wmi_unified *wmi_handle, + wmi_buf_t evt_buf); + +void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf); +uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle); +#endif /* _WMI_UNIFIED_API_H_ */ diff --git a/core/wmi/wmi_unified_priv.h b/core/wmi/wmi_unified_priv.h new file mode 100644 index 000000000000..f0f87028530b --- /dev/null +++ b/core/wmi/wmi_unified_priv.h @@ -0,0 +1,95 @@ +/* + * 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 "cdf_atomic.h" + +#define WMI_UNIFIED_MAX_EVENT 0x100 +#define WMI_MAX_CMDS 1024 + +typedef cdf_nbuf_t wmi_buf_t; + +#ifdef WMI_INTERFACE_EVENT_LOGGING + +#define WMI_EVENT_DEBUG_MAX_ENTRY (1024) + +struct wmi_command_debug { + uint32_t command; + uint32_t data[4]; /*16 bytes of WMI cmd excluding TLV and WMI headers */ + uint64_t time; +}; + +struct wmi_event_debug { + uint32_t event; + uint32_t data[4]; /*16 bytes of WMI event data excluding TLV header */ + uint64_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 */ + cdf_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]; + uint32_t max_event_idx; + void *htc_handle; + cdf_spinlock_t eventq_lock; + cdf_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 + cdf_spinlock_t wmi_record_lock; +#endif /*WMI_INTERFACE_EVENT_LOGGING */ + + cdf_atomic_t is_target_suspended; + int (*wma_process_fw_event_handler_cbk)(struct wmi_unified *wmi_handle, + wmi_buf_t evt_buf); +}; +#endif diff --git a/core/wmi/wmi_version_whitelist.c b/core/wmi/wmi_version_whitelist.c new file mode 100644 index 000000000000..ccad7fbeabd4 --- /dev/null +++ b/core/wmi/wmi_version_whitelist.c @@ -0,0 +1,38 @@ +/* + * 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. + */ + +/* + * 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/target/inc/a_osapi.h b/target/inc/a_osapi.h new file mode 100644 index 000000000000..0eabec0a6244 --- /dev/null +++ b/target/inc/a_osapi.h @@ -0,0 +1,71 @@ +/* + * 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 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/target/inc/a_usb_defs.h b/target/inc/a_usb_defs.h new file mode 100644 index 000000000000..1664a0a15859 --- /dev/null +++ b/target/inc/a_usb_defs.h @@ -0,0 +1,97 @@ +/* + * 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/target/inc/apb_athr_wlan_map.h b/target/inc/apb_athr_wlan_map.h new file mode 100644 index 000000000000..3e48543f0de2 --- /dev/null +++ b/target/inc/apb_athr_wlan_map.h @@ -0,0 +1,59 @@ +/* + * 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 _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/target/inc/athdefs.h b/target/inc/athdefs.h new file mode 100644 index 000000000000..d1ee6cb6ab0b --- /dev/null +++ b/target/inc/athdefs.h @@ -0,0 +1,83 @@ +/* + * 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 __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)) + +#endif /* __ATHDEFS_H__ */ diff --git a/target/inc/athendpack.h b/target/inc/athendpack.h new file mode 100644 index 000000000000..977909eb6e9f --- /dev/null +++ b/target/inc/athendpack.h @@ -0,0 +1,35 @@ +/* + * 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 VXWORKS +#endif /* VXWORKS */ + +#if defined(LINUX) || defined(__linux__) +#endif /* LINUX */ + +#ifdef QNX +#endif /* QNX */ diff --git a/target/inc/bin_sig.h b/target/inc/bin_sig.h new file mode 100644 index 000000000000..b723acc2bd5a --- /dev/null +++ b/target/inc/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/target/inc/bmi_msg.h b/target/inc/bmi_msg.h new file mode 100644 index 000000000000..11982cfabe48 --- /dev/null +++ b/target/inc/bmi_msg.h @@ -0,0 +1,364 @@ +/* + * 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 __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; + */ +#ifdef FEATURE_BMI_2 +PREPACK struct bmi_target_info { + /* size of this structure */ + A_UINT32 target_info_byte_count; + A_UINT32 target_ver; + A_UINT32 target_type; + A_UINT32 flags; +} POSTPACK; +#else +PREPACK struct bmi_target_info { + /* size of this structure */ + A_UINT32 target_info_byte_count; + A_UINT32 target_ver; + A_UINT32 target_type; +} POSTPACK; +#endif +#define TARGET_VERSION_SENTINAL 0xffffffff +#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/target/inc/cepci.h b/target/inc/cepci.h new file mode 100644 index 000000000000..9cebbc590d71 --- /dev/null +++ b/target/inc/cepci.h @@ -0,0 +1,125 @@ +/* + * 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 __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 4 +#define MSI_NUM_REQUEST 1 /* (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; +}; + +/* + * HIA Map Definition + */ +struct host_interest_area_t { + uint32_t hi_interconnect_state; + uint32_t hi_early_alloc; + uint32_t hi_option_flag2; + uint32_t hi_board_data; + uint32_t hi_board_data_initialized; + uint32_t hi_failure_state; + uint32_t hi_rddi_msi_num; + uint32_t hi_pcie_perst_couple_en; + uint32_t hi_sw_protocol_version; +}; + +struct shadow_reg_cfg { + A_UINT16 ce_id; + A_UINT16 reg_offset; +}; + +#endif /* __CEPCI_H__ */ diff --git a/target/inc/dbglog.h b/target/inc/dbglog.h new file mode 100644 index 000000000000..94cf15430c7b --- /dev/null +++ b/target/inc/dbglog.h @@ -0,0 +1,168 @@ +/* + * 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 _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 */ +/* it is limited bcoz of limitations of corebsp MSG*() to accept max 9 arg */ +#define DBGLOG_NUM_ARGS_MAX 9 + +#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/target/inc/dbglog_id.h b/target/inc/dbglog_id.h new file mode 100644 index 000000000000..7ddea2d88a33 --- /dev/null +++ b/target/inc/dbglog_id.h @@ -0,0 +1,1586 @@ +/* + * 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_DBGID_DEFINITION_END 52 + +/* 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 + +/* 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_DBGID_DEFINITION_END 4 + +/* 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_END (NAN_DBGID_NAN_NOT_ALLOWED + 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/target/inc/efuse_reg.h b/target/inc/efuse_reg.h new file mode 100644 index 000000000000..2bff9f8a28a5 --- /dev/null +++ b/target/inc/efuse_reg.h @@ -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. + */ + +#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/target/inc/enet.h b/target/inc/enet.h new file mode 100644 index 000000000000..c3f0cd68fccf --- /dev/null +++ b/target/inc/enet.h @@ -0,0 +1,148 @@ +/* + * 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 _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/target/inc/epping_test.h b/target/inc/epping_test.h new file mode 100644 index 000000000000..b8e6d01785c6 --- /dev/null +++ b/target/inc/epping_test.h @@ -0,0 +1,124 @@ +/* + * 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/target/inc/htc.h b/target/inc/htc.h new file mode 100644 index 000000000000..19239abdf34f --- /dev/null +++ b/target/inc/htc.h @@ -0,0 +1,405 @@ +/* + * 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 __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 */ + +/* receive direction */ +#define HTC_FLAGS_RECV_UNUSED_0 (1 << 0) /* bit 0 unused */ +#define HTC_FLAGS_RECV_TRAILER (1 << 1) /* bit 1 trailer data present */ +#define HTC_FLAGS_RECV_UNUSED_2 (1 << 0) /* bit 2 unused */ +#define HTC_FLAGS_RECV_UNUSED_3 (1 << 0) /* bit 3 unused */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0) /* bits 7..4 */ +#define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 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, reserved : 16; +} 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_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/target/inc/htc_services.h b/target/inc/htc_services.h new file mode 100644 index 000000000000..bd43772ac53d --- /dev/null +++ b/target/inc/htc_services.h @@ -0,0 +1,95 @@ +/* + * 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 __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, + WDI_IPA_SERVICE_GROUP = 5, + 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) +#define WDI_IPA_TX_SVC MAKE_SERVICE_ID(WDI_IPA_SERVICE_GROUP,0) + +/* + * 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 - target to target */ +#define PIPEDIR_INOUT_H2H 4 /* bidirectional - host to host */ +#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/target/inc/htt.h b/target/inc/htt.h new file mode 100644 index 000000000000..d9a081e63668 --- /dev/null +++ b/target/inc/htt.h @@ -0,0 +1,7034 @@ +/* + * 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 + */ + +/* + * Note that in this macro A_UINT32 has been converted to + * uint32_t only to address checkpath errors caused by declaring + * var_name as A_UINT32. + */ +#define HTT_VAR_PADDR32(var_name) uint32_t (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. + * 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 hdr for v4*/ + +#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-b/w 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-b/w 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-b/w 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-b/w 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 { + /* + * align with LL case rx indication message,but + * reduced to 5 words + */ + A_UINT32 rx_ind_msg[HTT_RX_IND_HL_SIZE32]; +} 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 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 | | 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/target/inc/htt_common.h b/target/inc/htt_common.h new file mode 100644 index 000000000000..0e9d7c357d64 --- /dev/null +++ b/target/inc/htt_common.h @@ -0,0 +1,120 @@ +/* + * 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_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, + htt_sec_type_aes_ccmp_256, + htt_sec_type_aes_gcmp, + htt_sec_type_aes_gcmp_256, + + /* 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, + HTT_RX_IND_MPDU_STATUS_DECRYPT_ERR, + HTT_RX_IND_MPDU_STATUS_MPDU_LENGTH_ERR, + HTT_RX_IND_MPDU_STATUS_ENCRYPT_REQUIRED_ERR, + HTT_RX_IND_MPDU_STATUS_PRIVACY_ERR, + + /* + * MISC: discard for unspecified reasons. + * Leave this enum value last. + */ + HTT_RX_IND_MPDU_STATUS_ERR_MISC = 0xFF +}; + +#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 HTT_NON_QOS_TID +#define HTT_TX_EXT_TID_MGMT 17 +#define HTT_TX_EXT_TID_INVALID HTT_INVALID_TID +#define HTT_TX_EXT_TID_NONPAUSE 19 + + + +#define HTT_TX_L3_CKSUM_OFFLOAD 1 +#define HTT_TX_L4_CKSUM_OFFLOAD 2 + + +/** + * @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. + * The exception is the "mgmt" type, which specifies frame payload + * type rather than L2 header type. + */ +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, + htt_pkt_type_eth2 = 4, + + /* keep this last */ + htt_pkt_num_types +}; + +#define HTT_TX_HOST_MSDU_ID_SPACE_BEGIN 0 +#define HTT_TX_IPA_MSDU_ID_SPACE_BEGIN 3000 +#define TGT_RX2TX_MSDU_ID_SPACE_BEGIN 6000 + +#endif /* _HTT_COMMON_H_ */ diff --git a/target/inc/htt_isoc.h b/target/inc/htt_isoc.h new file mode 100644 index 000000000000..c149192211a7 --- /dev/null +++ b/target/inc/htt_isoc.h @@ -0,0 +1,1058 @@ +/* + * 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 */ + /* cdf_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/target/inc/ip_prot.h b/target/inc/ip_prot.h new file mode 100644 index 000000000000..a1722fe3eb4f --- /dev/null +++ b/target/inc/ip_prot.h @@ -0,0 +1,58 @@ +/* + * 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 _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/target/inc/ipv4.h b/target/inc/ipv4.h new file mode 100644 index 000000000000..67eb3375507d --- /dev/null +++ b/target/inc/ipv4.h @@ -0,0 +1,55 @@ +/* + * 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 _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/target/inc/ol_fw_tx_dbg.h b/target/inc/ol_fw_tx_dbg.h new file mode 100644 index 000000000000..35303b7ac390 --- /dev/null +++ b/target/inc/ol_fw_tx_dbg.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 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. + */ + +/** + * @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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_16 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_RATEFLAGS_16 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_16 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_16 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/target/inc/rtc_soc_reg.h b/target/inc/rtc_soc_reg.h new file mode 100644 index 000000000000..11e80b1f1f92 --- /dev/null +++ b/target/inc/rtc_soc_reg.h @@ -0,0 +1,1966 @@ +/* + * 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 _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/target/inc/targaddrs.h b/target/inc/targaddrs.h new file mode 100644 index 000000000000..7cf64d385ce2 --- /dev/null +++ b/target/inc/targaddrs.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. + */ + +#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 QCA6180_HOST_INTEREST_ADDRESS 0x005d96a0 +#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_ENABLED (1 << 0) /* ACS is enabled */ +#define HI_ACS_FLAGS_USE_WWAN (1 << 1) /* Use physical WWAN device */ +#define HI_ACS_FLAGS_TEST_VAP (1 << 2) /* Use test VAP */ + +/* 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/target/inc/targcfg.h b/target/inc/targcfg.h new file mode 100644 index 000000000000..52a8d41eaf62 --- /dev/null +++ b/target/inc/targcfg.h @@ -0,0 +1,53 @@ +/* + * 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 __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/target/inc/wal_rx_desc.h b/target/inc/wal_rx_desc.h new file mode 100644 index 000000000000..04cd50dda82d --- /dev/null +++ b/target/inc/wal_rx_desc.h @@ -0,0 +1,127 @@ +/* + * 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/target/inc/wlan_defs.h b/target/inc/wlan_defs.h new file mode 100644 index 000000000000..3588a3008ba2 --- /dev/null +++ b/target/inc/wlan_defs.h @@ -0,0 +1,800 @@ +/* + * 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__ + +/* A_COMPILE_TIME_ASSERT */ +#include +#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 +#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 != 0 + 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 != 0 +#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 { + /* 11a channels */ + REGDMN_MODE_11A = 0x00000001, + /* 11a turbo-only channels */ + REGDMN_MODE_TURBO = 0x00000002, + /* 11b channels */ + REGDMN_MODE_11B = 0x00000004, + /* 11g channels (OFDM only) */ + REGDMN_MODE_PUREG = 0x00000008, + /* XXX historical */ + REGDMN_MODE_11G = 0x00000008, + /* 11g+Turbo channels */ + REGDMN_MODE_108G = 0x00000020, + /* 11a+Turbo channels */ + REGDMN_MODE_108A = 0x00000040, + /* XR channels */ + REGDMN_MODE_XR = 0x00000100, + /* 11A half rate channels */ + REGDMN_MODE_11A_HALF_RATE = 0x00000200, + /* 11A quarter rate channels */ + REGDMN_MODE_11A_QUARTER_RATE = 0x00000400, + /* 11N-G HT20 channels */ + REGDMN_MODE_11NG_HT20 = 0x00000800, + /* 11N-A HT20 channels */ + REGDMN_MODE_11NA_HT20 = 0x00001000, + /* 11N-G HT40 + channels */ + REGDMN_MODE_11NG_HT40PLUS = 0x00002000, + /* 11N-G HT40 - channels */ + REGDMN_MODE_11NG_HT40MINUS = 0x00004000, + /* 11N-A HT40 + channels */ + REGDMN_MODE_11NA_HT40PLUS = 0x00008000, + /* 11N-A HT40 - channels */ + REGDMN_MODE_11NA_HT40MINUS = 0x00010000, + /* 5Ghz, VHT20 */ + REGDMN_MODE_11AC_VHT20 = 0x00020000, + /* 5Ghz, VHT40 + channels */ + REGDMN_MODE_11AC_VHT40PLUS = 0x00040000, + /* 5Ghz VHT40 - channels */ + REGDMN_MODE_11AC_VHT40MINUS = 0x00080000, + /* 5Ghz, VHT80 channels */ + REGDMN_MODE_11AC_VHT80 = 0x000100000, + 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 +/* default: support up through 80 MHz */ +#define NUM_DYN_BW 3 +#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_defsh + * 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; +#if defined(AR900B) + A_UINT32 rssi_chain3; +#endif +} wlan_dbg_rx_rate_info_t; + +typedef struct { + A_UINT32 mcs[10]; + A_UINT32 sgi[10]; +#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/target/inc/wlan_module_ids.h b/target/inc/wlan_module_ids.h new file mode 100644 index 000000000000..c650ef5a524c --- /dev/null +++ b/target/inc/wlan_module_ids.h @@ -0,0 +1,103 @@ +/* + * 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/target/inc/wlan_tgt_def_config.h b/target/inc/wlan_tgt_def_config.h new file mode 100644 index 000000000000..2bcf796f9efe --- /dev/null +++ b/target/inc/wlan_tgt_def_config.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __WLAN_TGT_DEF_CONFIG_H__ +#define __WLAN_TGT_DEF_CONFIG_H__ + +/* + * set of default target config , that can be over written by platform + */ + +/* + * default limit of 8 VAPs per device. + */ +/* Rome PRD support 3 vdevs */ +#define CFG_TGT_NUM_VDEV 3 + +/* + * We would need 1 AST entry per peer. Scale it by a factor of 2 to minimize hash collisions. + * TODO: This scaling factor would be taken care inside the WAL in the future. + */ +#define CFG_TGT_NUM_PEER_AST 2 + +/* # of WDS entries to support. + */ +#define CFG_TGT_WDS_ENTRIES 0 + +/* MAC DMA burst size. 0: 128B - default, 1: 256B, 2: 64B + */ +#define CFG_TGT_DEFAULT_DMA_BURST_SIZE 0 + +/* Fixed delimiters to be inserted after every MPDU + */ +#define CFG_TGT_DEFAULT_MAC_AGGR_DELIM 0 + +/* + * This value may need to be fine tuned, but a constant value will + * probably always be appropriate; it is probably not necessary to + * determine this value dynamically. + */ +#define CFG_TGT_AST_SKID_LIMIT 16 + +/* + * total number of peers per device. + */ +#define CFG_TGT_NUM_PEERS 14 + +/* + * In offload mode target supports features like WOW, chatter and other + * protocol offloads. In order to support them some functionalities like + * reorder buffering, PN checking need to be done in target. This determines + * maximum number of peers suported by target in offload mode + */ + +/* + * The current firmware implementation requires the number of offload peers + * should be (number of vdevs + 1). + + * The reason for this is the firmware clubbed the self peer and offload peer + * in the same pool. So if the firmware wanted to support n vdevs then the + * number of offload peer must be n+1 of which n buffers will be used for + * self peer and the remaining 1 is used for offload peer to support chatter + * mode for single STA. + + * Technically the macro should be 1 however the current firmware requires n+1. + + * TODO: This MACRO need to be modified in the future, if the firmware modified + * to allocate buffers for self peer and offload peer independently. + */ + +#define CFG_TGT_NUM_OFFLOAD_PEERS (CFG_TGT_NUM_VDEV+1) + +/* + * Number of reorder buffers used in offload mode + */ +#define CFG_TGT_NUM_OFFLOAD_REORDER_BUFFS 4 + +/* + * keys per peer node + */ +#define CFG_TGT_NUM_PEER_KEYS 2 +/* + * total number of data TX and RX TIDs + */ +#define CFG_TGT_NUM_TIDS (2 * (CFG_TGT_NUM_PEERS + CFG_TGT_NUM_VDEV + 2)) +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + */ +#define CFG_TGT_DEFAULT_TX_CHAIN_MASK 0x7 +/* + * set this to 0x7 (Peregrine = 3 chains). + * need to be set dynamically based on the HW capability. + */ +#define CFG_TGT_DEFAULT_RX_CHAIN_MASK 0x7 +/* 100 ms for video, best-effort, and background */ +#define CFG_TGT_RX_TIMEOUT_LO_PRI 100 +/* 40 ms for voice*/ +#define CFG_TGT_RX_TIMEOUT_HI_PRI 40 + +/* AR9888 unified is default in ethernet mode */ +#define CFG_TGT_RX_DECAP_MODE (0x2) +/* Decap to native Wifi header */ +#define CFG_TGT_RX_DECAP_MODE_NWIFI (0x1) + +/* maximum number of pending scan requests */ +#define CFG_TGT_DEFAULT_SCAN_MAX_REQS 0x4 + +/* maximum number of VDEV that could use BMISS offload */ +#define CFG_TGT_DEFAULT_BMISS_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of VDEV offload Roaming to support */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV 0x2 + +/* maximum number of AP profiles pushed to offload Roaming */ +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_PROFILES 0x8 + +/* maximum number of VDEV offload GTK to support */ +#define CFG_TGT_DEFAULT_GTK_OFFLOAD_MAX_VDEV 0x2 + +/* default: mcast->ucast disabled if ATH_SUPPORT_MCAST2UCAST not defined */ +#ifndef ATH_SUPPORT_MCAST2UCAST +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 0 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 0 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 0 /* disabled */ +#else +/* (for testing) small multicast group membership table enabled */ +#define CFG_TGT_DEFAULT_NUM_MCAST_GROUPS 4 +#define CFG_TGT_DEFAULT_NUM_MCAST_TABLE_ELEMS 16 +#define CFG_TGT_DEFAULT_MCAST2UCAST_MODE 2 +#endif + +#define CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES 5 +/* + * Specify how much memory the target should allocate for a debug log of + * tx PPDU meta-information (how large the PPDU was, when it was sent, + * whether it was successful, etc.) + * The size of the log records is configurable, from a minimum of 28 bytes + * to a maximum of about 300 bytes. A typical configuration would result + * in each log record being about 124 bytes. + * Thus, 1KB of log space can hold about 30 small records, 3 large records, + * or about 8 typical-sized records. + */ +#define CFG_TGT_DEFAULT_TX_DBG_LOG_SIZE 1024 /* bytes */ + +/* target based fragment timeout and MPDU duplicate detection */ +#define CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 0 + +/* Default VoW configuration + */ +#define CFG_TGT_DEFAULT_VOW_CONFIG 0 + +/* + * total number of descriptors to use in the target + */ +#define CFG_TGT_NUM_MSDU_DESC (1024 + 32) + +/* + * Maximum number of frag table entries + */ +#define CFG_TGT_MAX_FRAG_TABLE_ENTRIES 10 + +/* + * Maximum number of VDEV that beacon tx offload will support + */ +#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 2 + +/* + * number of vdevs that can support tdls + */ +#define CFG_TGT_NUM_TDLS_VDEVS 1 + +/* + * number of peers that each Tdls vdev can track + */ +#define CFG_TGT_NUM_TDLS_CONN_TABLE_ENTRIES 32 + +/* + * number of TDLS concurrent sleep STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_SLEEP_STAS 1 + +/* + * number of TDLS concurrent buffer STAs + */ +#define CFG_TGT_NUM_TDLS_CONC_BUFFER_STAS 1 + +/* + * ht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_HT_MASK 0x8080 +/* + * vht enable highest MCS by default + */ +#define CFG_TGT_DEFAULT_GTX_VHT_MASK 0x80200 +/* + * resv for furture use, bit 30 is used for fix tpc, bit0-3 for Power save balance + */ +#define CFG_TGT_DEFAULT_GTX_USR_CFG 0xa +/* + * threshold to enable GTX + */ +#define CFG_TGT_DEFAULT_GTX_PER_THRESHOLD 3 +/* + * margin to move back when per > margin + threshold + */ +#define CFG_TGT_DEFAULT_GTX_PER_MARGIN 2 +/* + * step for every move + */ +#define CFG_TGT_DEFAULT_GTX_TPC_STEP 1 +/* + * lowest TPC + */ +#define CFG_TGT_DEFAULT_GTX_TPC_MIN 0 +/* + * enable all BW 20/40/80/160 + */ +#define CFG_TGT_DEFAULT_GTX_BW_MASK 0xf + +/* + * number of vdevs that can support OCB + */ +#define CFG_TGT_NUM_OCB_VDEVS 1 + +/* + * maximum number of channels that can do OCB + */ +#define CFG_TGT_NUM_OCB_CHANNELS 2 + +/* + * maximum number of channels in an OCB schedule + */ +#define CFG_TGT_NUM_OCB_SCHEDULES 2 + +#endif /*__WLAN_TGT_DEF_CONFIG_H__ */ diff --git a/target/inc/wmi.h b/target/inc/wmi.h new file mode 100644 index 000000000000..6645ebac1975 --- /dev/null +++ b/target/inc/wmi.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2004-2010, 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 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/target/inc/wmi_services.h b/target/inc/wmi_services.h new file mode 100644 index 000000000000..b2b1dfa71eb4 --- /dev/null +++ b/target/inc/wmi_services.h @@ -0,0 +1,162 @@ +/* + * 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)*/ + + /* target will send ASSOC_CONF after ASSOC_CMD is processed */ + WMI_SERVICE_PEER_ASSOC_CONF, + + /* enhanced green ap support */ + WMI_SERVICE_EGAP, + /* FW supports 11W PMF Offload for STA */ + WMI_SERVICE_STA_PMF_OFFLOAD, + + WMI_MAX_SERVICE = 128 /* max service */ +} WMI_SERVICE; + +#define WMI_SERVICE_BM_SIZE ((WMI_MAX_SERVICE + sizeof(A_UINT32)- 1)/sizeof(A_UINT32)) + +/* + * depreciated the name WMI_SERVICE_ROAM_OFFLOAD, but here to help compiling + * with old host driver + */ +#define WMI_SERVICE_ROAM_OFFLOAD WMI_SERVICE_ROAM_SCAN_OFFLOAD + +/* + * 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/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h new file mode 100644 index 000000000000..081de734b295 --- /dev/null +++ b/target/inc/wmi_tlv_defs.h @@ -0,0 +1,2996 @@ +/* + * 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_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) +/* + * 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) + +/* 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 */ +#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); + +/* 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); + +/* flush debug messages */ +#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); + +/* Request for memory dump stats Cmd */ +#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); + +#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); + + +/* 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); + +/* 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); + +#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); + +/************************** 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); + +/* 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); + +/* 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 */ +#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*/ +#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*/ +#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*/ +#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); + +/* 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); + + +#ifdef __cplusplus +} +#endif +#endif /*_WMI_TLV_DEFS_H_*/ diff --git a/target/inc/wmi_tlv_helper.h b/target/inc/wmi_tlv_helper.h new file mode 100644 index 000000000000..7631e5df9ec0 --- /dev/null +++ b/target/inc/wmi_tlv_helper.h @@ -0,0 +1,160 @@ +/* + * 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 _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/target/inc/wmi_unified.h b/target/inc/wmi_unified.h new file mode 100644 index 000000000000..7684d33f6b46 --- /dev/null +++ b/target/inc/wmi_unified.h @@ -0,0 +1,12299 @@ +/* + * 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 config*/ + 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, + /* 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), + + /** 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, + + /* 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), + + /*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), + WMI_OEM_MEASUREMENT_REPORT_EVENTID, + WMI_OEM_ERROR_REPORT_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_MASK) >> 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 + * values from enum WMI_FW_SUB_FEAT_CAPS + */ + A_UINT32 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 { + /* TLV tag and len; tag equals + *WMITLV_TAG_STRUC_WMI_SERVICE_EXT_READY_EVENT + */ + A_UINT32 tlv_header; + /* 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_HWBD_NONE = 0, /* No hw board information is given */ + WMI_HWBD_QCA6174 = 1, /* Rome(AR6320) */ + WMI_HWBD_QCA2582 = 2, /* Killer 1525 */ +} WMI_HWBD_ID; + +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; + +#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; + +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; + /* 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 { + /* + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_wmi_mgmt_tx_send_cmd_fixed_param + */ + A_UINT32 tlv_header; + A_UINT32 vdev_id; + /* echoed in tx_compl_event */ + A_UINT32 desc_id; + /* MHz units */ + A_UINT32 chanfreq; + A_UINT32 paddr_lo; + A_UINT32 paddr_hi; + A_UINT32 frame_len; + /* Buffer length in bytes */ + A_UINT32 buf_len; + /* + * 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, +} 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_cmd_fixed_param + */ + A_UINT32 tlv_header; + /* vdev_id, where RSSI monitoring will take place */ + A_UINT32 vdev_id; + /* + * host will configure request_id and firmware echo + * this id in RSSI_BREACH_EVENT + */ + A_UINT32 request_id; + /* + * bit [0-2] = low_rssi_breach_enabled[0-2] + * enabled, bit [3-5] = hi_rssi_breach_enabled[0-2] + */ + A_UINT32 enabled_bitmap; + /* unit dBm. host driver to make sure [0] > [1] > [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. 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 lo_rssi_reenable_hysteresis; + /* + * 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 hi_rssi_reenable_histeresis; + /* + * After last event is generated, we wait + * until this interval to generate next event + */ + A_UINT32 min_report_interval; + /* this is to suppress number of event to be generated */ + A_UINT32 max_num_report; +} 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 uint32_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 { + /** + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_debug_mesg_flush_fixed_param + */ + A_UINT32 tlv_header; + /** placeholder for future */ + A_UINT32 reserved0; +} wmi_debug_mesg_flush_fixed_param; + +typedef struct { + /** + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_debug_mesg_flush_complete_fixed_param + */ + A_UINT32 tlv_header; + /** placeholder for future */ + A_UINT32 reserved0; +} wmi_debug_mesg_flush_complete_fixed_param; + + +typedef struct { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_rssi_breach_fixed_param + * vdev_id, where RSSI breach event occurred + */ + A_UINT32 tlv_header; + 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 { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_fw_mem_dump */ + A_UINT32 tlv_header; + /** 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 { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_get_fw_mem_dump_fixed_param */ + A_UINT32 tlv_header; + /** 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 { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_update_fw_mem_dump_fixed_param */ + A_UINT32 tlv_header; + /** 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_vdev_txrx_streams + */ + A_UINT32 tlv_header; + /* 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, +} 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 { + 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 { + /* + * PEER_RATE_REPORT_COND_FLAG_DELTA, + * PEER_RATE_REPORT_COND_FLAG_THRESHOLD + * Any of these two conditions or both of + * them can be set. + */ + A_UINT32 val_cond_flags; + rate_delta_t rate_delta; + /* + * 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 + */ + A_UINT32 rate_threshold[MAX_NUM_OF_RATE_THRESH]; +} 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_peer_rate_report_condtion_fixed_param + */ + A_UINT32 tlv_header; + /* 1= enable, 0=disable */ + A_UINT32 enable_rate_report; + 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 { + /** TLV tag and len; tag equals + *WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param */ + A_UINT32 tlv_header; + 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 */ + /** + * RSSI below which roam is kicked in by background scan + * although rssi is still good + */ + A_UINT32 good_rssi_threshold; +} 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; + +#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 */ + +/* + * These will be used in WMI_ROAM_SYNCH_EVENTID for passing the subnet change + * info. Once roaming happens, firmware checks if subnet has changed and + * populates roam_reason field in WMI_ROAM_SYNCH_EVENTID using the definitions + * below. + */ +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; + +/**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 { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_filter_list_fixed_param */ + A_UINT32 tlv_header; + /** Unique id identifying the VDEV on which roaming filter is adopted */ + A_UINT32 vdev_id; + A_UINT32 flags; /** flags for filter */ + /** 32 bit bitmap to be set on. + * bit0 = first param, + * bit 1 = second param...etc. Can be or'ed + */ + A_UINT32 op_bitmap; + /* number of blacklist in the TLV variable bssid_black_list */ + A_UINT32 num_bssid_black_list; + /* number of whitelist in the TLV variable ssid_white_list */ + A_UINT32 num_ssid_white_list; + /* only for lfr 3.0. number of preferred list & factor in the TLV */ + A_UINT32 num_bssid_preferred_list; + /** + * 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param + */ + A_UINT32 tlv_header; + /** 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 + +typedef enum pattern_type_e { + WOW_PATTERN_MIN = 0, + WOW_BITMAP_PATTERN = WOW_PATTERN_MIN, + WOW_IPV4_SYNC_PATTERN, + WOW_IPV6_SYNC_PATTERN, + WOW_WILD_CARD_PATTERN, + WOW_TIMER_PATTERN, + WOW_MAGIC_PATTERN, + WOW_IPV6_RA_PATTERN, + WOW_IOAC_PKT_PATTERN, + WOW_IOAC_TMR_PATTERN, + WOW_IOAC_SOCK_PATTERN, + WOW_PATTERN_MAX +} WOW_PATTERN_TYPE; + +typedef enum event_type_e { + WOW_BMISS_EVENT = 0, + WOW_BETTER_AP_EVENT, + WOW_DEAUTH_RECVD_EVENT, + WOW_MAGIC_PKT_RECVD_EVENT, + WOW_GTK_ERR_EVENT, + WOW_FOURWAY_HSHAKE_EVENT, + WOW_EAPOL_RECVD_EVENT, + WOW_NLO_DETECTED_EVENT, + WOW_DISASSOC_RECVD_EVENT, + WOW_PATTERN_MATCH_EVENT, + WOW_CSA_IE_EVENT, + WOW_PROBE_REQ_WPS_IE_EVENT, + WOW_AUTH_REQ_EVENT, + WOW_ASSOC_REQ_EVENT, + WOW_HTT_EVENT, + WOW_RA_MATCH_EVENT, + WOW_HOST_AUTO_SHUTDOWN_EVENT, + WOW_IOAC_MAGIC_EVENT, + WOW_IOAC_SHORT_EVENT, + WOW_IOAC_EXTEND_EVENT, + WOW_IOAC_TIMER_EVENT, + WOW_DFS_PHYERR_RADAR_EVENT, + WOW_BEACON_EVENT, + WOW_CLIENT_KICKOUT_EVENT, + WOW_NAN_EVENT, + WOW_EXTSCAN_EVENT, + WOW_IOAC_REV_KA_FAIL_EVENT, + WOW_IOAC_SOCK_EVENT, + WOW_NLO_SCAN_COMPLETE_EVENT, +} WOW_WAKE_EVENT_TYPE; + +typedef enum wake_reason_e { + WOW_REASON_UNSPECIFIED = -1, + WOW_REASON_NLOD = 0, + WOW_REASON_AP_ASSOC_LOST, + WOW_REASON_LOW_RSSI, + WOW_REASON_DEAUTH_RECVD, + WOW_REASON_DISASSOC_RECVD, + WOW_REASON_GTK_HS_ERR, + WOW_REASON_EAP_REQ, + WOW_REASON_FOURWAY_HS_RECV, + WOW_REASON_TIMER_INTR_RECV, + WOW_REASON_PATTERN_MATCH_FOUND, + WOW_REASON_RECV_MAGIC_PATTERN, + WOW_REASON_P2P_DISC, + WOW_REASON_WLAN_HB, + WOW_REASON_CSA_EVENT, + WOW_REASON_PROBE_REQ_WPS_IE_RECV, + WOW_REASON_AUTH_REQ_RECV, + WOW_REASON_ASSOC_REQ_RECV, + WOW_REASON_HTT_EVENT, + WOW_REASON_RA_MATCH, + WOW_REASON_HOST_AUTO_SHUTDOWN, + WOW_REASON_IOAC_MAGIC_EVENT, + WOW_REASON_IOAC_SHORT_EVENT, + WOW_REASON_IOAC_EXTEND_EVENT, + WOW_REASON_IOAC_TIMER_EVENT, + WOW_REASON_ROAM_HO, + WOW_REASON_DFS_PHYERR_RADADR_EVENT, + WOW_REASON_BEACON_RECV, + WOW_REASON_CLIENT_KICKOUT_EVENT, + WOW_REASON_NAN_EVENT, + WOW_REASON_EXTSCAN, + WOW_REASON_RSSI_BREACH_EVENT, + WOW_REASON_IOAC_REV_KA_FAIL_EVENT, + WOW_REASON_IOAC_SOCK_EVENT, + WOW_REASON_NLO_SCAN_COMPLETE, + WOW_REASON_PACKET_FILTER_MATCH, + WOW_REASON_ASSOC_RES_RECV, + WOW_REASON_REASSOC_REQ_RECV, + WOW_REASON_REASSOC_RES_RECV, + WOW_REASON_ACTION_FRAME_RECV, + WOW_REASON_DEBUG_TEST = 0xFF, +} WOW_WAKE_REASON_TYPE; + +typedef enum { + WOW_IFACE_PAUSE_ENABLED, + WOW_IFACE_PAUSE_DISABLED +} WOW_IFACE_STATUS; + +enum { + /* some win10 platfrom will not assert pcie_reset for wow.*/ + WMI_WOW_FLAG_IGNORE_PCIE_RESET = 0x00000001, +}; + + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wow_enable_cmd_fixed_param */ + A_UINT32 enable; + A_UINT32 pause_iface_config; + A_UINT32 flags; /* WMI_WOW_FLAG enums */ +} wmi_wow_enable_cmd_fixed_param; + +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param */ + /** Reserved for future use */ + A_UINT32 reserved0; +} wmi_wow_hostwakeup_from_sleep_cmd_fixed_param; + +#define WOW_ICMPV6_NA_FILTER_DISABLE 0 +#define WOW_ICMPV6_NA_FILTER_ENABLE 1 + +typedef struct { + /* TLV tag and len; + * tag equals WMITLV_TAG_STRUC_wmi_wow_enable_icmpv6_na_flt_cmd_fixed_param + */ + A_UINT32 tlv_header; + 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 { + /** + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_WOW_IOAC_SOCK_PATTERN_T + */ + A_UINT32 tlv_header; + 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]; +} 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_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 { + /* + * TLV tag and len; + * tag equals WMITLV_TAG_STRUC_WMI_WOW_UDP_SVC_OFLD_CMD_fixed_param + */ + A_UINT32 tlv_header; + 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: + * payload of UDP packet to be checked, network byte order + * A_UINT8 pattern[]; + * payload of UDP packet to be response, network byte order + * A_UINT8 response[]; + */ +} 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; + + /* 1: enable, 0: disable */ + A_UINT32 enable; + + /* pin for host wakeup */ + A_UINT32 pin; + + /* interval for keeping low voltage, unit: ms */ + A_UINT32 interval_low; + + /* interval for keeping high voltage, unit: ms */ + A_UINT32 interval_high; + + /* repeat times for pulse (0xffffffff means forever) */ + A_UINT32 repeat_cnt; +} 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 { + /* + * TLV tag and len; tag equals + * WOW_INITIAL_WAKEUP_EVENT_fixed_param + */ + A_UINT32 tlv_header; + 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]; + * size of ns_ext_tuples is based on num_ns_ext_tuples + * WMI_NS_OFFLOAD_TUPLE 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 bool 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 { + /* TLV tag and len; tag equals wmi_passpoint_config_cmd_fixed_param */ + A_UINT32 tlv_header; + /* (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; + /*null terminated UTF8 encoded realm, 0 if unspecified*/ + A_UINT8 realm[PASSPOINT_REALM_LEN]; + /*roaming consortium ids to match, 0s if unspecified*/ + A_UINT8 roaming_consortium_ids[PASSPOINT_ROAMING_CONSORTIUM_ID_NUM][PASSPOINT_ROAMING_CONSORTIUM_ID_LEN]; + /*This would be bytes-stream as same as defition of realm id in 802.11 standard*/ + /*PLMN id mcc/mnc combination as per rules, 0s if unspecified */ + A_UINT8 plmn[PASSPOINT_PLMN_ID_ALLOC_LEN]; +} 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 { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param + */ + A_UINT32 tlv_header; + 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 */ + /* gratuitous ARP req*/ + WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4, +} 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 /* end 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 /* sen 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 forwarding 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; + + /** For 4-byte aligment padding */ + A_UINT8 reserved; + + /** 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: whether roaming went to a new subnet; + * 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 { + /* Use Motion Sensor Detection */ + WMI_EXTSCAN_USE_MSD = 0x0001, + /* Extscan LPASS extended batching feature is supported and enabled */ + WMI_EXTSCAN_EXTENDED_BATCHING_EN = 0x0002, +} wmi_extscan_configuration_flags; +typedef enum { + /* + * Cache the results of bucket whose + * configuration flags has this bit set + */ + WMI_EXTSCAN_BUCKET_CACHE_RESULTS = 0x0001, +} 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 { + /* TLV tag and len; tag equals WMITLV_TAG_ARRAY_STRUC */ + A_UINT32 tlv_header; + /**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 { + /** + * TLV tag and len; tag equals + * MITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param + */ + A_UINT32 tlv_header; + /** 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 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 element 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 */ + /**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 { + /* TLV tag and len; tag equals + *WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param */ + A_UINT32 tlv_header; + /** 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_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 { + /** + * 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_INTERRUPTED = 1 +} 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_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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_sap_set_blacklist_param_cmd_fixed_param + */ + A_UINT32 tlv_header; + 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 id(interface)*/ + 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. + */ +/* 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) + +/** 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; + + /*VDEV Identifier*/ + A_UINT32 vdev_id; + + /** 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. + */ + /* see "ETSI TS 102 687" table above for units */ + A_UINT32 min_max_tx_power; + /** + * 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 + * buf_len: + * A_UINT8 ie_data[]; + */ +} wmi_vdev_set_ie_cmd_fixed_param; + +typedef struct { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_soc_set_pcl_cmd_fixed_param + * Set Preferred Channel List + */ + A_UINT32 tlv_header; + + /* # 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 { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_cmd_fixed_param + * Set Hardware Mode */ + A_UINT32 tlv_header; + + /* Hardware Mode Index */ + A_UINT32 hw_mode_index; +} wmi_soc_set_hw_mode_cmd_fixed_param; + +typedef struct { + /* + * TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_soc_set_dual_mac_config_cmd_fixed_param + * Set Dual MAC Firmware Configuration + */ + A_UINT32 tlv_header; + + /* 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 { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_soc_set_hw_mode_response_event_fixed_param + * Set Hardware Mode Response Event **/ + A_UINT32 tlv_header; + + /* 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_soc_hw_mode_transition_event_fixed_param + * Hardware Mode Transition Event + */ + A_UINT32 tlv_header; + /* 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 { + /* + * 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 + */ + A_UINT32 tlv_header; + + /* 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) */ + /* + * from start of the respective frame header ( + * units = bytes) + */ + A_UINT32 data_offset; + /* Data to compare, little-endian order */ + A_UINT32 compareData[WMI_PACKET_FILTER_COMPARE_DATA_LEN_DWORD]; + /* Mask to be applied on rcvd packet data before compare, little-endian order */ + A_UINT32 dataMask[WMI_PACKET_FILTER_COMPARE_DATA_LEN_DWORD]; +} 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; + +/* 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 +*/ +#ifdef __cplusplus +} +#endif +#endif /*_WMI_UNIFIED_H_*/ +/**@}*/ diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h new file mode 100644 index 000000000000..0c1b628cc3ac --- /dev/null +++ b/target/inc/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_ 173 + +/** 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/target/inc/wmix.h b/target/inc/wmix.h new file mode 100644 index 000000000000..e7c7934b6739 --- /dev/null +++ b/target/inc/wmix.h @@ -0,0 +1,182 @@ +/* + * 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 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/uapi/linux/a_debug.h b/uapi/linux/a_debug.h new file mode 100644 index 000000000000..62931060cf08 --- /dev/null +++ b/uapi/linux/a_debug.h @@ -0,0 +1,202 @@ +/* + * 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 _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 debug_dump_bytes(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) debug_dump_bytes(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 + +#if defined(__linux__) && !defined(LINUX_EMULATION) +#include "debug_linux.h" +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/uapi/linux/a_types.h b/uapi/linux/a_types.h new file mode 100644 index 000000000000..b47f4a83903c --- /dev/null +++ b/uapi/linux/a_types.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/* 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/uapi/linux/athstartpack.h b/uapi/linux/athstartpack.h new file mode 100644 index 000000000000..c6c051eb2912 --- /dev/null +++ b/uapi/linux/athstartpack.h @@ -0,0 +1,48 @@ +/* + * 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 _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/uapi/linux/dbglog_common.h b/uapi/linux/dbglog_common.h new file mode 100644 index 000000000000..152862fa661b --- /dev/null +++ b/uapi/linux/dbglog_common.h @@ -0,0 +1,142 @@ +/* + * 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 _DBGLOG_COMMON_H_ +#define _DBGLOG_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "dbglog_id.h" +#include "dbglog.h" + +#define MAX_DBG_MSGS 256 + +#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 + +#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 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 initialization- 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 */ + uint8_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 */ + uint8_t payload[0]; +} __packed; + +typedef struct event_report_s { + unsigned int diag_type; + unsigned short event_id; + unsigned short length; +} event_report_t; + +/* + * Custom 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); + +#ifdef __cplusplus +} +#endif + +#endif /* _DBGLOG_COMMON_H_ */ diff --git a/uapi/linux/debug_linux.h b/uapi/linux/debug_linux.h new file mode 100644 index 000000000000..57c3590efba4 --- /dev/null +++ b/uapi/linux/debug_linux.h @@ -0,0 +1,50 @@ +/* + * 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 _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 + +#endif /* _DEBUG_LINUX_H_ */ diff --git a/uapi/linux/osapi_linux.h b/uapi/linux/osapi_linux.h new file mode 100644 index 000000000000..e0420bc12e7f --- /dev/null +++ b/uapi/linux/osapi_linux.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. + */ + +/* + * 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 + +#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)) + +#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) + +/* + * Timer Functions + */ +#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; + +/* + * Wait Queue related functions + */ +#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 */ + +#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 + +/* + * Network buffer queue support + */ +typedef struct sk_buff_head A_NETBUF_QUEUE_T; + +#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 + */ +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); + +#ifdef QCA_PARTNER_PLATFORM +#include "ath_carr_pltfrm.h" +#endif /* QCA_PARTNER_PLATFORM */ + +#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)) + +#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/uapi/linux/pktlog_ac_fmt.h b/uapi/linux/pktlog_ac_fmt.h new file mode 100644 index 000000000000..bde0d3e6fea5 --- /dev/null +++ b/uapi/linux/pktlog_ac_fmt.h @@ -0,0 +1,267 @@ +/* + * 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 _PKTLOG_FMT_H_ +#define _PKTLOG_FMT_H_ + +#define CUR_PKTLOG_VER 10010 /* Packet log version */ +#define PKTLOG_MAGIC_NUM 7735225 + +#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 { + uint16_t flags; + uint16_t missed_cnt; + uint16_t log_type; + uint16_t size; + uint32_t timestamp; +#ifdef HELIUMPLUS + uint32_t type_specific_data; +#endif +} __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 +#define ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET 3 + +/** + * enum - Pktlog flag field details + * packet origin [1:0] + * 00 - Local + * 01 - Remote + * 10 - Unknown/Not applicable + * 11 - Reserved + * reserved [15:2] + */ +enum { + PKTLOG_FLG_FRM_TYPE_LOCAL_S = 0, + PKTLOG_FLG_FRM_TYPE_REMOTE_S, + PKTLOG_FLG_FRM_TYPE_CLONE_S, + PKTLOG_FLG_FRM_TYPE_CBF_S, + PKTLOG_FLG_FRM_TYPE_UNKNOWN_S +}; + +#define PHFLAGS_INTERRUPT_CONTEXT 0x80000000 + +/* 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 + +/* 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_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 { + uint16_t framectrl; /* frame control field from header */ + uint16_t seqctrl; /* frame control field from header */ + uint16_t bssid_tail; /* last two octets of bssid */ + uint16_t sa_tail; /* last two octets of SA */ + uint16_t da_tail; /* last two octets of DA */ + uint16_t resvd; +}; + +#if defined(HELIUMPLUS) +/* Peregrine 11ac based */ +#define MAX_PKT_INFO_MSDU_ID 1 +#else +/* Peregrine 11ac based */ +#define MAX_PKT_INFO_MSDU_ID 192 +#endif /* defined(HELIUMPLUS) */ + +/* + * msdu_id_info_t is defined for reference only + */ +struct msdu_id_info { + uint32_t num_msdu; + uint8_t bound_bmap[(MAX_PKT_INFO_MSDU_ID + 7)>>3]; + /* TODO: + * Convert the id's to uint32_t + * Reduces computation in the driver code + */ + uint16_t id[MAX_PKT_INFO_MSDU_ID]; +} __ATTRIB_PACK; +#define MSDU_ID_INFO_NUM_MSDU_OFFSET 0 /* char offset */ +#define MSDU_ID_INFO_BOUND_BM_OFFSET offsetof(struct msdu_id_info, bound_bmap) +#define MSDU_ID_INFO_ID_OFFSET offsetof(struct msdu_id_info, id) + + +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; + uint32_t txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS]; + /* uint32_t *proto_hdr; / * protocol header (variable length!) * / */ + /* uint32_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; + +#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 { + uint32_t magic_num; /* Used by post processing scripts */ + uint32_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 */ -- cgit v1.2.3 From 020896275ef04cb4862cf5db305a8fdff1fa4b78 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 20 Oct 2015 16:15:31 -0700 Subject: qcacld-3.0: Fix several SSR related issues qcacld-2.0 to qcacld-3.0 propagation - Kill wlan_tasklet before freeing TLshim free queue. This can avoid race condition between SSR and wlan_tasklet which is still processing Rx packets in the case of self-recovery when FW doesn't really crash. - In additional to connected state, add disconnected/disconnecting states to send notification to supplicant for re-issuing connect after SSR. This is to avoid corner cases that while FW crashes, disconnection is happening or disconnection fails because of FW crash, the HDD state is changed from connected to disconnecting/disconnected. Change-Id: I8ff295a443e946e8775354dcf4331ad024776cb7 CRs-fixed: 899479 --- core/hdd/src/wlan_hdd_driver_ops.c | 4 +++- core/hdd/src/wlan_hdd_main.c | 5 ++++- core/hdd/src/wlan_hdd_power.c | 2 -- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index d8a1f67364ce..ff39296ee733 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -228,8 +228,10 @@ static void wlan_hdd_shutdown(void) hddLog(LOGE, FL("Host is not ready for SSR, attempting anyway")); - if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + hif_disable_isr(hif_ctx); hdd_wlan_shutdown(); + } hif_disable(hif_ctx, HIF_DISABLE_TYPE_SHUTDOWN); hif_close(hif_ctx); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 64a72991cde3..68b9a8a26b7a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2967,7 +2967,10 @@ CDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) /* Indicate disconnect event to supplicant if associated previously */ if (eConnectionState_Associated == connState || - eConnectionState_IbssConnected == 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; diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index d7662e817147..cc5679ae3ba2 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1380,8 +1380,6 @@ CDF_STATUS hdd_wlan_shutdown(void) CDF_ASSERT(0); } - hif_disable_isr(((cds_context_type *) p_cds_context)->pHIFContext); - hddLog(CDF_TRACE_LEVEL_INFO, "%s: Flush Queues", __func__); /* Clean up message queues of TX, RX and MC thread */ cds_sched_flush_mc_mqs(cds_sched_context); -- cgit v1.2.3 From 4d366ff94db42da19b1b725d2fdc87c8c2e24c14 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 20 Oct 2015 18:12:45 -0700 Subject: qcacld-3.0: Recover if fail to receive HTC ACK from FW for PDEV suspend qcacld-2.0 to qcacld-3.0 propagation If self-recovery is enabled in ini file, recover if host driver fails to receive HTC ACK from FW for PDEV suspend, otherwise do VOS_BUG. Change-Id: Ieddb22c5806067ec1a1166b60e1642e6cdf74a4c CRs-fixed: 894187 --- core/wma/src/wma_features.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 065f2e300b12..adc553dc79e4 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5873,11 +5873,22 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) uint32_t len = sizeof(*cmd); struct ol_softc *scn; int ret; +#ifdef CONFIG_CNSS + tpAniSirGlobal pmac = cds_get_context(CDF_MODULE_ID_PE); +#endif if (!wma_handle || !wma_handle->wmi_handle) { WMA_LOGE("WMA is closed. can not issue suspend cmd"); return -EINVAL; } + +#ifdef CONFIG_CNSS + if (NULL == 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 @@ -5912,6 +5923,13 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) != CDF_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 (pmac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } +#endif return -EFAULT; } -- cgit v1.2.3 From ba532aaaf0ded38b4073de02ae34fab4676feb5c Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 20 Oct 2015 18:29:16 -0700 Subject: qcacld-3.0: Ignore VOS_BUG if recovery is already going on during suspend qcacld-2.0 to qcacld-3.0 propagation There is no need for host driver to do VOS_BUG if FW has already requested recovery during suspend. Change-Id: I0c77210316fea978fe686201f42b9501612e9a1e CRs-fixed: 904909 --- core/wma/src/wma_features.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index adc553dc79e4..b8d584e4d7d9 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3245,15 +3245,20 @@ CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle) WMA_LOGE("Credits:%d; Pending_Cmds: %d", wmi_get_host_credits(wma->wmi_handle), wmi_get_pending_cmds(wma->wmi_handle)); + if (!cds_is_logp_in_progress()) { #ifdef CONFIG_CNSS - if (pMac->sme.enableSelfRecovery) { - cds_trigger_recovery(); - } else { - CDF_BUG(0); - } + if (pMac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } #else - CDF_BUG(0); + CDF_BUG(0); #endif /* CONFIG_CNSS */ + } else { + WMA_LOGE("%s: LOGP is in progress, ignore!", __func__); + } + wmi_set_target_suspend(wma->wmi_handle, false); return CDF_STATUS_E_FAILURE; } @@ -5924,10 +5929,14 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) WMA_LOGE("Failed to get ACK from firmware for pdev suspend"); wmi_set_target_suspend(wma_handle->wmi_handle, false); #ifdef CONFIG_CNSS - if (pmac->sme.enableSelfRecovery) { - cds_trigger_recovery(); + if (!cds_is_logp_in_progress()) { + if (pmac->sme.enableSelfRecovery) { + cds_trigger_recovery(); + } else { + CDF_BUG(0); + } } else { - CDF_BUG(0); + WMA_LOGE("%s: LOGP is in progress, ignore!", __func__); } #endif return -EFAULT; -- cgit v1.2.3 From b6fcc9fb6a1a71503ce7cbac5c1c2429f5f685b8 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 20 Oct 2015 18:37:37 -0700 Subject: qcacld-3.0: CL 1359727 1369758 - update fw debug log file qcacld-2.0 to qcacld-3.0 propagation - ADD dbglog IDs for WMI TLV parsing. - Add ROAM_STA_KICKOUT_RECV dbglog ID. Change-Id: I3fdae0def4a99f75bbe9a8d772d7a61fa10ee7d5 CRs-fixed: 908561 --- target/inc/dbglog_id.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/target/inc/dbglog_id.h b/target/inc/dbglog_id.h index 7ddea2d88a33..8b46c4959f3a 100644 --- a/target/inc/dbglog_id.h +++ b/target/inc/dbglog_id.h @@ -123,7 +123,21 @@ extern "C" { #define WMI_DBGID_DCS_PARAM_CMD 49 #define WMI_SEND_EVENT_WRONG_TLV 50 #define WMI_SEND_EVENT_NO_TLV_DEF 51 -#define WMI_DBGID_DEFINITION_END 52 +#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 @@ -872,7 +886,9 @@ extern "C" { #define SWBMISS_ENABLED 1 #define SWBMISS_DISABLED 2 #define SWBMISS_UPDATE_BEACON_RSSI 3 -#define SWBMISS_DBGID_DEFINITION_END 4 +#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 -- cgit v1.2.3 From b9ea56ed9e1c276ea8297a81e39ac73cb5173361 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 20 Oct 2015 18:49:24 -0700 Subject: qcacld-3.0: Modify bus bandwidth vote criterion qcacld-2.0 to qcacld-3.0 propagation If total TX/RX packets are less than bus bandwidth low threshold, there is no need to vote separately from WLAN side. Change-Id: I02284d035e58471b3933a84c778d4d44bd6b19ba CRs-fixed: 918723 --- core/hdd/src/wlan_hdd_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 68b9a8a26b7a..fefe3c257834 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3951,8 +3951,10 @@ void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, next_vote_level = CNSS_BUS_WIDTH_HIGH; else if (total > hdd_ctx->config->busBandwidthMediumThreshold) next_vote_level = CNSS_BUS_WIDTH_MEDIUM; - else + else if (total > hdd_ctx->config->busBandwidthLowThreshold) next_vote_level = CNSS_BUS_WIDTH_LOW; + else + next_vote_level = CNSS_BUS_WIDTH_NONE; hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level = next_vote_level; -- cgit v1.2.3 From d8ed108d14a49a3ceac0f739a869494ade10bff6 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 27 Oct 2015 12:25:27 -0700 Subject: qcacld-3.0: Increase SSR timeout to 30 seconds qcacld-2.0 to qcacld-3.0 propagation Increase SSR timeout from 15 seconds to 30 seconds in order to handle some corner cases which may cause SSR to take longer time. E.g. CPU is busy/stuck with other tasks. Change-Id: I6837f2d5e87090ede15e514d1c4f978d34931f32 CRs-fixed: 927722 --- core/hdd/src/wlan_hdd_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index cc5679ae3ba2..d227d6c28273 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -70,7 +70,7 @@ #include "sme_power_save_api.h" /* Preprocessor definitions and constants */ -#define HDD_SSR_BRING_UP_TIME 15000 +#define HDD_SSR_BRING_UP_TIME 30000 /* Type declarations */ -- cgit v1.2.3 From c5535fcf15c36f3ee71486c170dc5dd9f3f09f1b Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 27 Oct 2015 12:42:40 -0700 Subject: qcacld-3.0: Do not update WLAN status to LPASS when disconnect during unload qcacld-2.0 to qcacld-3.0 propagation Host driver updates WLAN status to LPASS with connected false and WLAN on when disconnection happens. Host driver also updates WLAN status right after driver unload is triggered with connected false and WLAN off. There is a scenario that disconnection callback comes during driver unloading which causes LPASS misbehavior. Fix this by only updating disconnection status to LAPSS when driver is not unloading. Change-Id: Ie72ba094283a64c06e8c74523314d6de92a0f08b CRs-fixed: 928365 --- core/hdd/src/wlan_hdd_stats.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index a08f133213a2..4d3b35c3fb21 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1928,7 +1928,8 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, #ifdef WLAN_FEATURE_LPSS if (!pAdapter->rssi_send) { pAdapter->rssi_send = true; - wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1); + if (pHddCtx->isUnloadInProgress != true) + wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1); } #endif -- cgit v1.2.3 From 952ec474d8f6138338782dc332a3b48ce6b72739 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 26 Oct 2015 16:53:30 +0530 Subject: qcacld-3.0: synchronize concurrent access of shared variable qcacld-2.0 to qcacld-3.0 propagation Currently DFS variables are accessed in different context without protection leading to NULL pointer dereferences. Ensure lock is taken before accessing the DFS shared variable. Change-Id: Ie78dd50ff4b32ef52f78e2944d175a6c10577882 CRs-Fixed: 910586 --- core/sap/dfs/src/dfs.c | 2 ++ core/sap/dfs/src/dfs_fcc_bin5.c | 8 +++++++ core/sap/dfs/src/dfs_misc.c | 8 +++++++ core/sap/dfs/src/dfs_phyerr_tlv.c | 20 ++++++++++------ core/sap/dfs/src/dfs_process_phyerr.c | 39 +++++++++++++++++++++++++------ core/sap/dfs/src/dfs_process_radarevent.c | 8 +++++++ core/wma/inc/wma_dfs_interface.h | 2 +- core/wma/src/wma_dev_if.c | 8 ++----- core/wma/src/wma_features.c | 26 +++++++++++++-------- 9 files changed, 90 insertions(+), 31 deletions(-) diff --git a/core/sap/dfs/src/dfs.c b/core/sap/dfs/src/dfs.c index a9191517f5ec..dfc46026a07b 100644 --- a/core/sap/dfs/src/dfs.c +++ b/core/sap/dfs/src/dfs.c @@ -169,7 +169,9 @@ static os_timer_func(dfs_task) */ OS_CANCEL_TIMER(&dfs->ath_dfstesttimer); dfs->ath_dfstest = 1; + cdf_spin_lock_bh(&ic->chan_lock); dfs->ath_dfstest_ieeechan = ic->ic_curchan->ic_ieee; + cdf_spin_unlock_bh(&ic->chan_lock); dfs->ath_dfstesttime = 1; /* 1ms */ OS_SET_TIMER(&dfs->ath_dfstesttimer, dfs->ath_dfstesttime); diff --git a/core/sap/dfs/src/dfs_fcc_bin5.c b/core/sap/dfs/src/dfs_fcc_bin5.c index ccc9fe6d2b7c..d6f62542c0ce 100644 --- a/core/sap/dfs/src/dfs_fcc_bin5.c +++ b/core/sap/dfs/src/dfs_fcc_bin5.c @@ -99,9 +99,12 @@ dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, } /* Adjust the filter threshold for rssi in non TURBO mode */ + cdf_spin_lock_bh(&dfs->ic->chan_lock); if (!(dfs->ic->ic_curchan->ic_flags & CHANNEL_TURBO)) b5_rssithresh += br->br_pulse.b5_rssimargin; + cdf_spin_unlock_bh(&dfs->ic->chan_lock); + /* * Check if the pulse is within duration and rssi * thresholds. @@ -560,6 +563,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen, int same_sign; int temp; + cdf_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; @@ -590,6 +594,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen, upper_mag_byte = UPPER_MAG_BYTE_HT20; } + cdf_spin_unlock_bh(&dfs->ic->chan_lock); ptr = (uint8_t *) buf; /* * sanity check for FFT buffer @@ -625,6 +630,7 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen, max_index_upper[i] = (ptr[fft_start + upper_index_byte] >> 2) + num_subchan_bins; + cdf_spin_lock_bh(&dfs->ic->chan_lock); if (!IS_CHAN_HT40(dfs->ic->ic_curchan)) { /* * for HT20 mode indices are 6 bit signed number @@ -632,6 +638,8 @@ dfs_check_chirping_merlin(struct ath_dfs *dfs, void *buf, uint16_t datalen, max_index_lower[i] ^= 0x20; max_index_upper[i] = 0; } + + cdf_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. diff --git a/core/sap/dfs/src/dfs_misc.c b/core/sap/dfs/src/dfs_misc.c index 8cf4a2c8cd4a..e320e322b1af 100644 --- a/core/sap/dfs/src/dfs_misc.c +++ b/core/sap/dfs/src/dfs_misc.c @@ -107,7 +107,9 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, else pri_margin = DFS_DEFAULT_PRI_MARGIN; + cdf_spin_lock_bh(&dfs->ic->chan_lock); if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + cdf_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 = @@ -131,6 +133,8 @@ dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, adjust_pri_per_chan_busy(ext_chan_busy, pri_margin); pri_margin -= adjust_pri; + } else { + cdf_spin_unlock_bh(&dfs->ic->chan_lock); } return pri_margin; } @@ -146,7 +150,9 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, thresh = rf->rf_threshold; + cdf_spin_lock_bh(&dfs->ic->chan_lock); if (IS_CHAN_HT40(dfs->ic->ic_curchan)) { + cdf_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 = @@ -179,6 +185,8 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, rf->rf_pulseid, ext_chan_busy, adjust_thresh); thresh += adjust_thresh; + } else { + cdf_spin_unlock_bh(&dfs->ic->chan_lock); } return thresh; } diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c index 205c170873b3..89a6c0b471b4 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.c +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -228,6 +228,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, * Set pulse duration to 20 us */ + cdf_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; @@ -238,6 +239,7 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, rsu->pulse_duration = 20; } + cdf_spin_unlock_bh(&dfs->ic->chan_lock); } static void @@ -435,13 +437,16 @@ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?", __func__, dfs->ic); return 0; - /* - * For now, the only 11ac channel with freq1/freq2 setup is - * VHT80. - * - * XXX should have a flag macro to check this! - */ - } else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { + } + + cdf_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 */ /* @@ -477,6 +482,7 @@ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) chan_centre += (chan_offset / 2); } + cdf_spin_unlock_bh(&dfs->ic->chan_lock); /* * XXX half/quarter rate support! */ diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 1cabfd4dd9f2..8bf76f95bebf 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -72,6 +72,7 @@ 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) @@ -87,7 +88,7 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) * based on whether it's an upper or lower channel. */ chan_width = dfs_get_event_freqwidth(dfs); - + cdf_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)) @@ -95,6 +96,8 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) else chan_offset = 0; + cdf_spin_unlock_bh(&ic->chan_lock); + /* * Check for DC events first - the sowl code may just set all * the bits together.. @@ -103,22 +106,36 @@ dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) /* * XXX TODO: Should DC events be considered 40MHz wide here? */ - return ieee80211_chan2freq(ic, ic->ic_curchan) + + cdf_spin_lock_bh(&ic->chan_lock); + freq = ieee80211_chan2freq(ic, ic->ic_curchan) + (chan_offset / 2); + cdf_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) - return ieee80211_chan2freq(ic, ic->ic_curchan); + if (is_pri) { + cdf_spin_lock_bh(&ic->chan_lock); + freq = ieee80211_chan2freq(ic, ic->ic_curchan); + cdf_spin_unlock_bh(&ic->chan_lock); + return freq; + } - if (is_ext) - return ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width; + if (is_ext) { + cdf_spin_lock_bh(&ic->chan_lock); + freq = ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width; + cdf_spin_unlock_bh(&ic->chan_lock); + return freq; + } /* XXX shouldn't get here */ - return ieee80211_chan2freq(ic, ic->ic_curchan); + cdf_spin_lock_bh(&ic->chan_lock); + freq = ieee80211_chan2freq(ic, ic->ic_curchan); + cdf_spin_unlock_bh(&ic->chan_lock); + return freq; } /* @@ -497,13 +514,16 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, return; } + cdf_spin_lock_bh(&ic->chan_lock); if (IEEE80211_IS_CHAN_RADAR(chan)) { + cdf_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; } + cdf_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", @@ -691,7 +711,9 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, * for the adaptive radio (AR) pattern matching rather than * radar detection. */ + cdf_spin_lock_bh(&ic->chan_lock); if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) { + cdf_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__); @@ -732,6 +754,7 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, ATH_ARQ_UNLOCK(dfs); } else { if (IEEE80211_IS_CHAN_DFS(chan)) { + cdf_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", @@ -824,6 +847,8 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, ATH_DFSQ_LOCK(dfs); STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); ATH_DFSQ_UNLOCK(dfs); + } else { + cdf_spin_unlock_bh(&ic->chan_lock); } } diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index 789364899988..41ce9160f5e2 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -140,13 +140,17 @@ int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) return 0; } pl = dfs->pulses; + cdf_spin_lock_bh(&dfs->ic->chan_lock); if (!(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { + cdf_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; } + + cdf_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) { @@ -781,11 +785,15 @@ dfsfound: DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "Primary channel freq = %u flags=0x%x", chan->ic_freq, chan->ic_flagext); + cdf_spin_lock_bh(&dfs->ic->chan_lock); if ((dfs->ic->ic_curchan->ic_freq != thischan->ic_freq)) { + cdf_spin_unlock_bh(&dfs->ic->chan_lock); DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "Ext channel freq = %u flags=0x%x", thischan->ic_freq, thischan->ic_flagext); } + + cdf_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; diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 4bfc3fccad15..53d1cc4cb635 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -232,7 +232,7 @@ typedef struct ieee80211com { uint8_t vdev_id; uint8_t last_radar_found_chan; int32_t dfs_pri_multiplier; - cdf_mutex_t chan_lock; + cdf_spinlock_t chan_lock; } IEEE80211COM, *PIEEE80211COM; /** diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 587b327cf8ad..8bbcf7171452 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -2050,17 +2050,13 @@ CDF_STATUS wma_vdev_start(tp_wma_handle wma, return CDF_STATUS_E_FAILURE; } - cdf_mutex_acquire(&wma->dfs_ic->chan_lock); - if (wma->dfs_ic->ic_curchan) { - OS_FREE(wma->dfs_ic->ic_curchan); - wma->dfs_ic->ic_curchan = NULL; - } + cdf_spin_lock_bh(&wma->dfs_ic->chan_lock); /* provide the current channel to DFS */ wma->dfs_ic->ic_curchan = wma_dfs_configure_channel(wma->dfs_ic, chan, chanmode, req); - cdf_mutex_release(&wma->dfs_ic->chan_lock); + cdf_spin_unlock_bh(&wma->dfs_ic->chan_lock); wma_unified_dfs_phyerr_filter_offload_enable(wma); dfs->disable_dfs_ch_switch = diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index b8d584e4d7d9..f3945b94a26f 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1732,17 +1732,17 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle, radar_event = param_tlvs->fixed_param; - cdf_mutex_acquire(&ic->chan_lock); + cdf_spin_lock_bh(&ic->chan_lock); chan = ic->ic_curchan; if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) { WMA_LOGE ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS", __func__, chan->ic_ieee); - cdf_mutex_release(&ic->chan_lock); + cdf_spin_unlock_bh(&ic->chan_lock); return 0; } - cdf_mutex_release(&ic->chan_lock); + cdf_spin_unlock_bh(&ic->chan_lock); dfs->ath_dfs_stats.total_phy_errors++; if (dfs->dfs_caps.ath_chip_is_bb_tlv) { @@ -6625,7 +6625,7 @@ struct ieee80211com *wma_dfs_attach(struct ieee80211com *dfs_ic) * and shared DFS code */ dfs_ic->ic_dfs_notify_radar = ieee80211_mark_dfs; - cdf_mutex_init(&dfs_ic->chan_lock); + cdf_spinlock_init(&dfs_ic->chan_lock); /* Initializes DFS Data Structures and queues */ dfs_attach(dfs_ic); @@ -6642,7 +6642,7 @@ void wma_dfs_detach(struct ieee80211com *dfs_ic) { dfs_detach(dfs_ic); - cdf_mutex_destroy(&dfs_ic->chan_lock); + cdf_spinlock_destroy(&dfs_ic->chan_lock); if (NULL != dfs_ic->ic_curchan) { OS_FREE(dfs_ic->ic_curchan); dfs_ic->ic_curchan = NULL; @@ -6757,14 +6757,18 @@ struct ieee80211_channel *wma_dfs_configure_channel(struct ieee80211com *dfs_ic, WMA_LOGE("%s: DFS ic is Invalid", __func__); return NULL; } - dfs_ic->ic_curchan = (struct ieee80211_channel *)os_malloc(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; + 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; @@ -6916,6 +6920,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic, * But, when DFS test mode is enabled, allow multiple dfs * radar events to be posted on the same channel. */ + cdf_spin_lock_bh(&ic->chan_lock); if ((ichan->ic_ieee != (wma->dfs_ic->last_radar_found_chan)) || (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) { wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; @@ -6937,6 +6942,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic, wma_send_msg(wma, WMA_DFS_RADAR_IND, (void *)radar_event, 0); WMA_LOGE("%s:DFS- WMA_DFS_RADAR_IND Message Posted", __func__); } + cdf_spin_unlock_bh(&ic->chan_lock); return 0; } -- cgit v1.2.3 From 7cbbe596727424d10ea40cd1972d9bc665ecbb59 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 26 Oct 2015 17:06:23 +0530 Subject: qcacld-3.0: Optimize processing of DFS phy events qcacld-2.0 to qcacld-3.0 propagation Optimize by avoiding processing of DFS phy events in below scenario's 1)Once radar indication given to UMAC. 2)Vdev restart in SAP interface Change-Id: Ib175feed4a611a5c7185202e3d50abc3e84fc781 CRs-Fixed: 910586 --- core/sap/dfs/src/dfs_process_radarevent.c | 10 ++++++++++ core/wma/inc/wma_dfs_interface.h | 1 + core/wma/src/wma_dev_if.c | 8 ++++++++ core/wma/src/wma_features.c | 10 ++++++++++ 4 files changed, 29 insertions(+) diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index 41ce9160f5e2..a639d44d3d4a 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -224,6 +224,16 @@ int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) ATH_DFSEVENTQ_UNLOCK(dfs); found = 0; + cdf_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); + cdf_spin_unlock_bh(&dfs->ic->chan_lock); + continue; + } + + cdf_spin_unlock_bh(&dfs->ic->chan_lock); if (re.re_chanindex < DFS_NUM_RADAR_STATES) rs = &dfs->dfs_radar[re.re_chanindex]; else { diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 53d1cc4cb635..740e23a84caa 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -233,6 +233,7 @@ typedef struct ieee80211com { uint8_t last_radar_found_chan; int32_t dfs_pri_multiplier; cdf_spinlock_t chan_lock; + bool disable_phy_err_processing; } IEEE80211COM, *PIEEE80211COM; /** diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 8bbcf7171452..925fcdb98b19 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -766,6 +766,12 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, return -EINVAL; } + if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id)) { + cdf_spin_lock_bh(&wma->dfs_ic->chan_lock); + wma->dfs_ic->disable_phy_err_processing = false; + cdf_spin_unlock_bh(&wma->dfs_ic->chan_lock); + } + if (resp_event->status == CDF_STATUS_SUCCESS) { wma->interfaces[resp_event->vdev_id].tx_streams = resp_event->cfgd_tx_streams; @@ -2051,6 +2057,8 @@ CDF_STATUS wma_vdev_start(tp_wma_handle wma, } cdf_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 = diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index f3945b94a26f..9faaac67e454 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1734,6 +1734,13 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle, cdf_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__); + cdf_spin_unlock_bh(&ic->chan_lock); + return 0; + } + if (CHANNEL_STATE_DFS != cds_get_channel_state(chan->ic_ieee)) { WMA_LOGE ("%s: Invalid DFS Phyerror event. Channel=%d is Non-DFS", @@ -6921,6 +6928,9 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic, * radar events to be posted on the same channel. */ cdf_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 == true)) { wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; -- cgit v1.2.3 From 77ec98c2f912f88ae59bdce676a183d3bb024c92 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 16 Oct 2015 16:26:14 +0530 Subject: qcacld-3.0:IBSS:Update HT secondary channel offset from beacon in pStaDs qcacld-2.0 to qcacld-3.0 propagation While adding pStaDs for IBSS when peer beacon is received, HT secondary channel offset is not copied from beacon. This leads to false change capability indication while processing the same beacon and thus update cb mode is sent with staid 255(default), leading to crash. Update HT secondary channel offset from beacon and add a check in cbmode update to ignore update if staid is 255. CRs-Fixed: 885747 Change-Id: I66dedb38aadde473b99b2f8fc4a7a9b855a10b2a --- core/mac/src/pe/lim/lim_ibss_peer_mgmt.c | 2 ++ core/mac/src/pe/sch/sch_beacon_process.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c index c2c3dba5353a..4cdacb9aeb12 100644 --- a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c @@ -246,6 +246,8 @@ ibss_sta_caps_update(tpAniSirGlobal pMac, pStaDs->htGreenfield = pPeerNode->htGreenfield; pStaDs->htSupportedChannelWidthSet = pPeerNode->htSupportedChannelWidthSet; + pStaDs->htSecondaryChannelOffset = + pPeerNode->htSecondaryChannelOffset; pStaDs->htMIMOPSState = pPeerNode->htMIMOPSState; pStaDs->htMaxAmsduLength = pPeerNode->htMaxAmsduLength; pStaDs->htAMpduDensity = pPeerNode->htAMpduDensity; diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index a8f2a468b90b..459cb90bcb2c 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -538,7 +538,9 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx, pStaDs = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid, &session->dph.dphHashTable); if ((NULL == pStaDs) || - (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode)) + (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode) || + ((NULL != pStaDs) && + (STA_INVALID_IDX == pStaDs->staIndex))) return; if (session->vhtCapability && bcn->OperatingMode.present) { -- cgit v1.2.3 From 535fc9960d945ea1ab138a1d675d37615aa6f2eb Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 20:47:30 +0530 Subject: qcacld-3.0: Handle excessive logging during hostap select queue qcacld-2.0 to qcacld-3.0 propagation As a part of unload hdd is stopping the netdev queue. But still N/W layer 3 is calling the select queue netdev ops, where error print for sap context is Null appears excessively. As a part of this fix hostap select queue need to validate Hdd context to take care of SSR and load / unload cases. Change-Id: Id6d93a3a83de7d95a283ff57b6fa2c44f08a9ee3 CRs-Fixed: 857220 --- core/hdd/src/wlan_hdd_wmm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index cdc1863ff40e..0f5da4033e43 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -1786,6 +1786,13 @@ uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); bool is_eapol = false; + 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->config->WmmMode) { /* Get the user priority from IP header & corresponding AC */ -- cgit v1.2.3 From 711b9fa5125d29dbd23ad68cc78c302b8e12c42e Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 19:28:14 +0530 Subject: qcacld-3.0: Check priviledge permission for SET_BAND_CONFIG IOCTL qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing SET_BAND_CONFIG IOCTL, making sure user task has right permission to process the command. Change-Id: Ie8a36bfa07a7b21601364b27b3c4bc888a6a5b4e CRs-Fixed: 930952 --- core/hdd/src/wlan_hdd_wext.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 91076fe511b3..d20cf03b7df5 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -9362,6 +9362,12 @@ static int __iw_set_band_config(struct net_device *dev, ENTER(); + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + return hdd_set_band(dev, value[0]); } -- cgit v1.2.3 From 72ed1edcaaf38bb3bb8b7da31f59a70a494877dc Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 19:57:31 +0530 Subject: qcacld-3.0: Check privilege permission for QCSAP_IOCTL_SETWPSIE qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing QCSAP_IOCTL_SETWPSIE IOCTL, making sure user task has right permission to process the command. Change-Id: Ie1c945afb0f109892beda66bab25647d70cc62d7 CRs-Fixed: 930944 --- core/hdd/src/wlan_hdd_hostapd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 6024539d8b40..980c80f8bc22 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -4254,6 +4254,12 @@ __iw_softap_setwpsie(struct net_device *dev, ENTER(); + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) -- cgit v1.2.3 From 910bb98ca84904672fbe2ef8b31eb5dd841e9d0a Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 20:05:09 +0530 Subject: qcacld-3.0: Check privilege permission for SET_VAR_INTS_GETNONE qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing SET_VAR_INTS_GETNONE, making sure user task has right permission to process the command. Change-Id: Icbdfe69c18c1ab3b75d63e046d5251307a794817 CRs-Fixed: 930942 --- core/hdd/src/wlan_hdd_wext.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index d20cf03b7df5..4e1654d7037d 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7883,6 +7883,12 @@ static int iw_hdd_set_var_ints_getnone(struct net_device *dev, int apps_args[MAX_VAR_ARGS] = {0}; int ret, num_args; + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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; -- cgit v1.2.3 From 531361dfeab18c9852ee59eedf1fa26686681cfc Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 19:30:19 +0530 Subject: qcacld-3.0: Do not Update MC list in ftm mode qcacld-2.0 to qcacld-3.0 propagation Host should avoid to Update MC list in ftm mode because as a part of MC list updation, host will access the pMac roam sessions, as these sessions are not initialized in FTM mode which lead to Null data access. Change-Id: I2ac82e76c1c7de8d1bf0fd7e291bf5445e9d0f4b CRs-fixed: 897871 --- core/hdd/src/wlan_hdd_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fefe3c257834..c25c880ffba7 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1607,6 +1607,9 @@ static void __hdd_set_multicast_list(struct net_device *dev) static const uint8_t ipv6_router_solicitation[] = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; + if (CDF_FTM_MODE == hdd_get_conparam()) + return; + status = wlan_hdd_validate_context(hdd_ctx); if (0 != status) { hdd_err("hdd_ctx is not valid"); -- cgit v1.2.3 From 9f4dcdc97391bc2a8983f34f6d6d7252638e8fae Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 20:26:02 +0530 Subject: qcacld-3.0: Fix defects detected by Static code analyser qcacld-2.0 to qcacld-3.0 propagation Static code analyser detects uninitialized pointer/structure access and dereferencing a pointer without null check. As part of this fix host will initialize pointer/structure before accessing it and put a null check for pointer access. Change-Id: I5647b36a6ba0e84354d39799bf68a28df633cf20 CRs-Fixed: 836071 --- core/hdd/src/wlan_hdd_ipa.c | 2 +- core/hdd/src/wlan_hdd_wext.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index c7efbc12fd18..7f6ed0b45938 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -2596,6 +2596,7 @@ static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL; CDF_STATUS status = CDF_STATUS_SUCCESS; + iface_context = (struct hdd_ipa_iface_context *)priv; if (evt != IPA_RECEIVE) { skb = (cdf_nbuf_t) data; dev_kfree_skb_any(skb); @@ -2603,7 +2604,6 @@ static void hdd_ipa_i2w_cb(void *priv, enum ipa_dp_evt_type evt, return; } - iface_context = (struct hdd_ipa_iface_context *)priv; ipa_tx_desc = (struct ipa_rx_data *)data; hdd_ipa = iface_context->hdd_ipa; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 4e1654d7037d..659cc7d6539e 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -4898,6 +4898,7 @@ static int __iw_setint_getnone(struct net_device *dev, int enable_pbm, enable_mp; INIT_COMPLETION(pWextState->completion_var); + memset(&smeConfig, 0x00, sizeof(smeConfig)); hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); @@ -4910,7 +4911,6 @@ static int __iw_setint_getnone(struct net_device *dev, if ((ENABLE_11D == set_value) || (DISABLE_11D == set_value)) { - memset(&smeConfig, 0x00, sizeof(smeConfig)); sme_get_config_param(hHal, &smeConfig); smeConfig.csrConfig.Is11dSupportEnabled = (bool) set_value; @@ -5401,7 +5401,6 @@ static int __iw_setint_getnone(struct net_device *dev, nChannelBondingMode5GHz))) chwidth = true; - memset(&smeConfig, 0x00, sizeof(smeConfig)); sme_get_config_param(hHal, &smeConfig); switch (set_value) { case eHT_CHANNEL_WIDTH_20MHZ: @@ -7000,7 +6999,7 @@ static int __iw_get_char_setnone(struct net_device *dev, adapter_num++; } - if (pMac) { + if (hHal) { /* Printing Lim State starting with global lim states */ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, -- cgit v1.2.3 From b2468a0c9062cd22fb3fbdc49f7fbd00965c889d Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 19:49:13 +0530 Subject: qcacld-3.0: Check privilege permission for QCSAP_IOCTL_DISASSOC_STA qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing QCSAP_IOCTL_DISASSOC_STA IOCTL, making sure user task has right permission to process the command. Change-Id: I00919a56e93b8b49bce7a314b50f9f48039fbe6f CRs-Fixed: 930946 --- core/hdd/src/wlan_hdd_hostapd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 980c80f8bc22..2727e1286c44 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -3379,6 +3379,12 @@ static __iw_softap_disassoc_sta(struct net_device *dev, ENTER(); + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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) -- cgit v1.2.3 From b4a6bc0af877b95630da20e1d66b7439a6a62c11 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 20:22:30 +0530 Subject: qcacld-3.0: Check privilege permission for SET_CHAR_GET_NONE qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing SET_CHAR_GET_NONE IOCTLs, making sure user task has right permission to process the command. Change-Id: I7b060bcdc84f7016e8d301e994437a535533a260 CRs-Fixed: 930935 --- core/hdd/src/wlan_hdd_wext.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 659cc7d6539e..299ce46d243b 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -6121,6 +6121,12 @@ static int __iw_setchar_getnone(struct net_device *dev, #endif /* WLAN_FEATURE_VOWIFI */ struct iw_point s_priv_data; + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; -- cgit v1.2.3 From 14aa8ea2eef926eff0ff4e9ed6f2808f431c62b8 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 22:23:43 +0530 Subject: qcacld-3.0: SSR protection for linux/crda reg_notifier api qcacld-2.0 to qcacld-3.0 propagation if SSR trigger in middle of execution of linux_reg_notifier /crda_reg_notifier, driver may access uninitialized data. Hence Driver need to protect these function from SSR. Change-Id: I9bdc6851a44fecc8353e94b38eb1dd4f63e58604 CRs-Fixed: 798672 --- core/cds/src/cds_reg_service.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index f8d275113245..a0bed553ea06 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -1208,13 +1208,13 @@ static void restore_custom_reg_settings(struct wiphy *wiphy) #endif /** - * hdd_reg_notifier() - regulatory notifier + * __hdd_reg_notifier() - regulatory notifier * @wiphy: wiphy * @request: regulatory request * * Return: void or int */ -void hdd_reg_notifier(struct wiphy *wiphy, +void __hdd_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { hdd_context_t *hdd_ctx = wiphy_priv(wiphy); @@ -1359,6 +1359,21 @@ void hdd_reg_notifier(struct wiphy *wiphy, return; } +/** + * hdd_reg_notifier() - regulatory notifier + * @wiphy: wiphy + * @request: regulatory request + * + * Return: void or int + */ +void hdd_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + cds_ssr_protect(__func__); + __hdd_reg_notifier(wiphy, request); + cds_ssr_unprotect(__func__); +} + /** * cds_regulatory_init() - regulatory_init * Return: CDF_STATUS -- cgit v1.2.3 From 9f266d976488ff79f6319a8e5c185889deecc7ac Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 2 Nov 2015 20:16:31 +0530 Subject: qcacld-3.0: Check privilege permission for SET_PACKET_FILTER qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing SET_PACKET_FILTER IOCTL, making sure user task has right permission to process the command. Change-Id: Ib49c3223eacdc90dfe0d45af1aff7c74518990df CRs-Fixed: 930937 --- core/hdd/src/wlan_hdd_wext.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 299ce46d243b..9110a2b72093 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -8654,6 +8654,12 @@ static int __iw_set_packet_filter_params(struct net_device *dev, hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct pkt_filter_cfg *request = NULL; + if (!capable(CAP_NET_ADMIN)) { + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) -- cgit v1.2.3 From ac9d7ed0b46ed2feaf7fd2ace0c05fc64d99c97d Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Thu, 10 Sep 2015 18:16:21 -0700 Subject: qcacld-3.0: PNO Channel prediction Reduce the number of channels to scan in PNO mode based on the initial scan memory and the movement of the client STA using Tanimoto distance CRs-Fixed: 932355 Change-Id: I1b5448af801fb37324b77cd13c6009f1d859dd61 --- core/hdd/inc/wlan_hdd_cfg.h | 59 ++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 74 ++++++++++++++++++++++++++++++++++-- core/mac/inc/sir_api.h | 6 +++ core/sme/inc/csr_api.h | 6 +++ core/sme/inc/csr_internal.h | 6 +++ core/sme/inc/sme_api.h | 18 +++++++++ core/sme/inc/sme_power_save_api.h | 12 ++++-- core/sme/src/common/sme_api.c | 41 ++++++++++++++++++++ core/sme/src/common/sme_power_save.c | 33 +++++++++++++++- core/wma/inc/wma_internal.h | 15 ++++++-- core/wma/src/wma_scan_roam.c | 69 ++++++++++++++++++++++++++++++--- 11 files changed, 320 insertions(+), 19 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 9b8095a43e88..2f4be4dfd64a 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2654,6 +2654,51 @@ enum dot11p_mode { #define CFG_ROAM_SCAN_HI_RSSI_UB_MIN (-76) #define CFG_ROAM_SCAN_HI_RSSI_UB_MAX (-30) #define CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT (-45) +/* + * gPNOChannelPrediction will allow user to enable/disable the + * PNO channel prediction feature. + * In current PNO implementation, scan is always done until all configured + * channels are scanned. If we can determine DUT is stationary based on + * scanning a subset of channels, we may cancel the remaining channels. + * Hence, we can save additional power consumption. + */ +#define CFG_PNO_CHANNEL_PREDICTION_NAME "gPNOChannelPrediction" +#define CFG_PNO_CHANNEL_PREDICTION_MIN (0) +#define CFG_PNO_CHANNEL_PREDICTION_MAX (1) +#define CFG_PNO_CHANNEL_PREDICTION_DEFAULT (0) +/* + * The top K number of channels are used for tanimoto distance + * calculation. These are the top channels on which the probability + * of finding the AP's is extremely high. This number is intended + * for tweaking the internal algorithm for experiments. This should + * not be changed externally. + */ +#define CFG_TOP_K_NUM_OF_CHANNELS_NAME "gTopKNumOfChannels" +#define CFG_TOP_K_NUM_OF_CHANNELS_MIN (1) +#define CFG_TOP_K_NUM_OF_CHANNELS_MAX (5) +#define CFG_TOP_K_NUM_OF_CHANNELS_DEFAULT (3) +/* + * This is the threshold value to determine that the STA is + * stationary. If the tanimoto distance is less than this + * value, then the device is considered to be stationary. + * This parameter is intended to tweak the internal algorithm + * for experiments. This should not be changed externally. + */ +#define CFG_STATIONARY_THRESHOLD_NAME "gStationaryThreshold" +#define CFG_STATIONARY_THRESHOLD_MIN (0) +#define CFG_STATIONARY_THRESHOLD_MAX (100) +#define CFG_STATIONARY_THRESHOLD_DEFAULT (10) +/* + * The following parameter is the periodic timer upon which + * a full scan needs to be triggered when PNO channel prediction + * feature is enabled. This parameter is intended to tweak the + * internal algortihm for experiments. This should not be changed + * externally. + */ +#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME "gChPredictionFullScanMs" +#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MIN (30000) +#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX (0x7fffffff) +#define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT (60000) /*--------------------------------------------------------------------------- Type declarations @@ -3213,6 +3258,12 @@ struct hdd_config { bool tx_chain_mask_cck; uint8_t tx_chain_mask_1ss; uint16_t self_gen_frm_pwr; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_channel_prediction; + uint8_t top_k_num_of_channels; + uint8_t stationary_thresh; + uint32_t channel_prediction_full_scan; +#endif }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) @@ -3347,5 +3398,13 @@ CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, void hdd_cfg_print(hdd_context_t *pHddCtx); CDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss); +#ifdef FEATURE_WLAN_SCAN_PNO +void hdd_set_pno_channel_prediction_config( + tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx); +#else +static inline void hdd_set_pno_channel_prediction_config( + tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx) +{} +#endif #endif diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 734bd4ba4e5d..bf57226f1c2c 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3465,6 +3465,36 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_DUAL_MAC_FEATURE_DISABLE_DEFAULT, CFG_DUAL_MAC_FEATURE_DISABLE_MIN, CFG_DUAL_MAC_FEATURE_DISABLE_MAX), +#ifdef FEATURE_WLAN_SCAN_PNO + REG_VARIABLE(CFG_PNO_CHANNEL_PREDICTION_NAME, WLAN_PARAM_Integer, + struct hdd_config, pno_channel_prediction, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PNO_CHANNEL_PREDICTION_DEFAULT, + CFG_PNO_CHANNEL_PREDICTION_MIN, + CFG_PNO_CHANNEL_PREDICTION_MAX), + + REG_VARIABLE(CFG_TOP_K_NUM_OF_CHANNELS_NAME, WLAN_PARAM_Integer, + struct hdd_config, top_k_num_of_channels, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TOP_K_NUM_OF_CHANNELS_DEFAULT, + CFG_TOP_K_NUM_OF_CHANNELS_MIN, + CFG_TOP_K_NUM_OF_CHANNELS_MAX), + + REG_VARIABLE(CFG_STATIONARY_THRESHOLD_NAME, WLAN_PARAM_Integer, + struct hdd_config, stationary_thresh, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_STATIONARY_THRESHOLD_DEFAULT, + CFG_STATIONARY_THRESHOLD_MIN, + CFG_STATIONARY_THRESHOLD_MAX), + + REG_VARIABLE(CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME, + WLAN_PARAM_Integer, + struct hdd_config, channel_prediction_full_scan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT, + CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MIN, + CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX), +#endif REG_VARIABLE(CFG_TX_CHAIN_MASK_CCK, WLAN_PARAM_Integer, struct hdd_config, tx_chain_mask_cck, @@ -5006,6 +5036,20 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) "Name = [%s] value = [%u]", CFG_DUAL_MAC_FEATURE_DISABLE, pHddCtx->config->dual_mac_feature_disable); +#ifdef FEATURE_WLAN_SCAN_PNO + hddLog(LOGE, "Name = [%s] Value = [%u]", + CFG_PNO_CHANNEL_PREDICTION_NAME, + pHddCtx->config->pno_channel_prediction); + hddLog(LOGE, "Name = [%s] Value = [%u]", + CFG_TOP_K_NUM_OF_CHANNELS_NAME, + pHddCtx->config->top_k_num_of_channels); + hddLog(LOGE, "Name = [%s] Value = [%u]", + CFG_STATIONARY_THRESHOLD_NAME, + pHddCtx->config->stationary_thresh); + hddLog(LOGE, "Name = [%s] Value = [%u]", + CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME, + pHddCtx->config->channel_prediction_full_scan); +#endif } @@ -6088,7 +6132,31 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx) } return fStatus; } - +#ifdef FEATURE_WLAN_SCAN_PNO +/** + * hdd_set_pno_channel_prediction_config() - Set PNO configuration + * @sme_config: Config params from SME Context + * @hdd_ctx: Config params from HDD Context + * + * Copy the PNO Channel prediction feature configuration parameters + * from HDD context to SME context. + * + * Return: None + */ +void hdd_set_pno_channel_prediction_config( + tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx) +{ + sme_config->dual_mac_feature_disable = + hdd_ctx->config->dual_mac_feature_disable; + sme_config->pno_channel_prediction = + hdd_ctx->config->pno_channel_prediction; + sme_config->top_k_num_of_channels = + hdd_ctx->config->top_k_num_of_channels; + sme_config->stationary_thresh = hdd_ctx->config->stationary_thresh; + sme_config->channel_prediction_full_scan = + hdd_ctx->config->channel_prediction_full_scan; +} +#endif /** * hdd_set_sme_config() -initializes the sme configuration parameters * @@ -6392,9 +6460,7 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) /* Update 802.11p config */ smeConfig->csrConfig.enable_dot11p = (pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED); - - smeConfig->dual_mac_feature_disable = - pHddCtx->config->dual_mac_feature_disable; + hdd_set_pno_channel_prediction_config(smeConfig, pHddCtx); status = sme_update_config(pHddCtx->hHal, smeConfig); if (!CDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4be197e1b629..28b2e8a7b965 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2715,6 +2715,12 @@ typedef struct sSirPNOScanReq { uint8_t p24GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE]; uint16_t us5GProbeTemplateLen; uint8_t p5GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE]; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_channel_prediction; + uint8_t top_k_num_of_channels; + uint8_t stationary_thresh; + uint32_t channel_prediction_full_scan; +#endif } tSirPNOScanReq, *tpSirPNOScanReq; /* Preferred Network Found Indication */ diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 117240d9a75a..caa878751c4f 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1263,6 +1263,12 @@ typedef struct tagCsrConfigParam { /* 802.11p enable */ bool enable_dot11p; uint8_t max_scan_count; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_channel_prediction; + uint8_t top_k_num_of_channels; + uint8_t stationary_thresh; + uint32_t channel_prediction_full_scan; +#endif } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index e12fc255d23e..d06b9e23103a 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -645,6 +645,12 @@ typedef struct tagCsrConfig { uint8_t is_sta_connection_in_5gz_enabled; struct roam_ext_params roam_params; bool sendDeauthBeforeCon; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_channel_prediction; + uint8_t top_k_num_of_channels; + uint8_t stationary_thresh; + uint32_t channel_prediction_full_scan; +#endif } tCsrConfig; typedef struct tagCsrChannelPowerInfo { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 1da4dcf32876..7c20e05f5c92 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -84,6 +84,8 @@ /* Macro to indicate invalid no of tspecs */ #define INVALID_TSPEC 100 +#define SME_CONFIG_TO_ROAM_CONFIG 1 +#define ROAM_CONFIG_TO_SME_CONFIG 2 /*-------------------------------------------------------------------------- Type declarations @@ -122,6 +124,12 @@ typedef struct _smeConfigParams { bool policy_manager_enabled; uint32_t fine_time_meas_cap; uint32_t dual_mac_feature_disable; +#ifdef FEATURE_WLAN_SCAN_PNO + bool pno_channel_prediction; + uint8_t top_k_num_of_channels; + uint8_t stationary_thresh; + uint32_t channel_prediction_full_scan; +#endif } tSmeConfigParams, *tpSmeConfigParams; #ifdef FEATURE_WLAN_TDLS @@ -225,6 +233,16 @@ CDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId, void *pContext); CDF_STATUS sme_update_roam_params(tHalHandle hHal, uint8_t session_id, struct roam_ext_params roam_params_src, int update_param); +#ifdef FEATURE_WLAN_SCAN_PNO +void sme_update_roam_pno_channel_prediction_config( + tHalHandle hal, tpSmeConfigParams sme_config, + uint8_t copy_from_to); +#else +static inline void sme_update_roam_pno_channel_prediction_config( + tHalHandle hal, tpSmeConfigParams sme_config, + uint8_t copy_from_to) +{} +#endif CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams); diff --git a/core/sme/inc/sme_power_save_api.h b/core/sme/inc/sme_power_save_api.h index e4fa67b7e167..95a2db56b0ac 100644 --- a/core/sme/inc/sme_power_save_api.h +++ b/core/sme/inc/sme_power_save_api.h @@ -82,13 +82,19 @@ CDF_STATUS sme_ps_open_per_session(tHalHandle hal_ctx, uint32_t session_id); void sme_auto_ps_entry_timer_expired(void *ps_param); CDF_STATUS sme_ps_close(tHalHandle hal_ctx); CDF_STATUS sme_ps_close_per_session(tHalHandle hal_ctx, uint32_t sessionId); - +#ifdef FEATURE_WLAN_SCAN_PNO +void sme_set_pno_channel_prediction(tpSirPNOScanReq request_buf, + tpAniSirGlobal mac_ctx); CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, tpSirPNOScanReq request, uint8_t session_id, - preferred_network_found_ind_cb - callback_routine, + preferred_network_found_ind_cb callback_routine, void *callback_context); +#else +static inline void sme_set_pno_channel_prediction(void *request_buf, + tpAniSirGlobal mac_ctx) +{} +#endif CDF_STATUS sme_is_auto_ps_timer_running(tHalHandle hal_ctx, uint32_t session_id); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 98a1f2607fc9..111433369f9b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1347,6 +1347,8 @@ CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap; pMac->dual_mac_feature_disable = pSmeConfigParams->dual_mac_feature_disable; + sme_update_roam_pno_channel_prediction_config(pMac, pSmeConfigParams, + SME_CONFIG_TO_ROAM_CONFIG); return status; } @@ -4188,6 +4190,8 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) pParam->enable5gEBT = pMac->enable5gEBT; pParam->f_sta_miracast_mcc_rest_time_val = pMac->f_sta_miracast_mcc_rest_time_val; + sme_update_roam_pno_channel_prediction_config(pMac, pParam, + ROAM_CONFIG_TO_SME_CONFIG); sme_release_global_lock(&pMac->sme); } @@ -6722,6 +6726,43 @@ uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch, #endif #ifdef FEATURE_WLAN_SCAN_PNO +/** + * sme_update_roam_pno_channel_prediction_config() - Update PNO config + * @sme_config: config from SME context + * @hal: Global Hal handle + * @copy_from_to: Used to specify the source and destination + * + * Copy the PNO channel prediction configuration parameters from + * SME context to MAC context or vice-versa + * + * Return: None + */ +void sme_update_roam_pno_channel_prediction_config( + tHalHandle hal, tpSmeConfigParams sme_config, + uint8_t copy_from_to) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + if (copy_from_to == SME_CONFIG_TO_ROAM_CONFIG) { + mac_ctx->roam.configParam.pno_channel_prediction = + sme_config->pno_channel_prediction; + mac_ctx->roam.configParam.top_k_num_of_channels = + sme_config->top_k_num_of_channels; + mac_ctx->roam.configParam.stationary_thresh = + sme_config->stationary_thresh; + mac_ctx->roam.configParam.channel_prediction_full_scan = + sme_config->channel_prediction_full_scan; + } else if (copy_from_to == ROAM_CONFIG_TO_SME_CONFIG) { + sme_config->pno_channel_prediction = + mac_ctx->roam.configParam.pno_channel_prediction; + sme_config->top_k_num_of_channels = + mac_ctx->roam.configParam.top_k_num_of_channels; + sme_config->stationary_thresh = + mac_ctx->roam.configParam.stationary_thresh; + sme_config->channel_prediction_full_scan = + mac_ctx->roam.configParam.channel_prediction_full_scan; + } + +} /****************************************************************************** * * Name: sme_preferred_network_found_ind diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c index a08ce2bdb4ec..ba4ec34ea34c 100644 --- a/core/sme/src/common/sme_power_save.c +++ b/core/sme/src/common/sme_power_save.c @@ -744,7 +744,36 @@ sme_prepare_probe_req_template(tpAniSirGlobal mac_ctx, *pus_len = payload + sizeof(tSirMacMgmtHdr); return eSIR_SUCCESS; } /* End sme_prepare_probe_req_template. */ - +/** + * sme_set_pno_channel_prediction() - Prepare PNO buffer + * @request_buf: Buffer to be filled up to send to WMA + * @mac_ctx: MAC context + * + * Fill up the PNO buffer with the channel prediction configuration + * parameters and send them to WMA + * + * Return: None + **/ +void sme_set_pno_channel_prediction(tpSirPNOScanReq request_buf, + tpAniSirGlobal mac_ctx) +{ + request_buf->pno_channel_prediction = + mac_ctx->roam.configParam.pno_channel_prediction; + request_buf->top_k_num_of_channels = + mac_ctx->roam.configParam.top_k_num_of_channels; + request_buf->stationary_thresh = + mac_ctx->roam.configParam.stationary_thresh; + request_buf->channel_prediction_full_scan = + mac_ctx->roam.configParam.channel_prediction_full_scan; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("channel_prediction: %d, top_k_num_of_channels: %d"), + request_buf->pno_channel_prediction, + request_buf->top_k_num_of_channels); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("stationary_thresh: %d, ch_predict_full_scan: %d"), + request_buf->stationary_thresh, + request_buf->channel_prediction_full_scan); +} CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, tpSirPNOScanReq request, uint8_t session_id, @@ -877,7 +906,7 @@ CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, request_buf->sessionId = session_id; } - + sme_set_pno_channel_prediction(request_buf, mac_ctx); msg.type = WMA_SET_PNO_REQ; msg.reserved = 0; msg.bodyptr = request_buf; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index a737fa2f10ec..9e9ef25ba5f5 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -263,7 +263,17 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno); CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id); void wma_config_pno(tp_wma_handle wma, tpSirPNOScanReq pno); - +void wma_set_pno_channel_prediction(uint8_t *buf_ptr, + tpSirPNOScanReq pno); +void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId); +#else +static inline void wma_set_pno_channel_prediction(uint8_t *buf_ptr, + void *pno) +{ + WMA_LOGD("PNO Channel Prediction feature not supported"); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 0); +} +#endif #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm); @@ -272,9 +282,6 @@ CDF_STATUS wma_plm_stop(tp_wma_handle wma, const tpSirPlmReq plm); void wma_config_plm(tp_wma_handle wma, tpSirPlmReq plm); #endif -void wma_scan_cache_updated_ind(tp_wma_handle wma, uint8_t sessionId); -#endif - #ifdef WLAN_FEATURE_ROAM_OFFLOAD void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts); #endif diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 708202473f97..82627bc0757b 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3425,7 +3425,37 @@ send_resp: } #ifdef FEATURE_WLAN_SCAN_PNO - +/** + * wma_set_pno_channel_prediction() - Set PNO configuration + * @buf_ptr: Buffer passed by upper layers + * @pno: Buffer to be sent to the firmware + * + * Copy the PNO Channel prediction configuration parameters + * passed by the upper layers to a WMI format TLV and send it + * down to the firmware. + * + * Return: None + */ +void wma_set_pno_channel_prediction(uint8_t *buf_ptr, + tpSirPNOScanReq pno) +{ + nlo_channel_prediction_cfg *channel_prediction_cfg = + (nlo_channel_prediction_cfg *) buf_ptr; + WMITLV_SET_HDR(&channel_prediction_cfg->tlv_header, + WMITLV_TAG_ARRAY_BYTE, + WMITLV_GET_STRUCT_TLVLEN(nlo_channel_prediction_cfg)); + channel_prediction_cfg->enable = pno->pno_channel_prediction; + channel_prediction_cfg->top_k_num = pno->top_k_num_of_channels; + channel_prediction_cfg->stationary_threshold = pno->stationary_thresh; + channel_prediction_cfg->full_scan_period_ms = + pno->channel_prediction_full_scan; + buf_ptr += sizeof(nlo_channel_prediction_cfg); + WMA_LOGD("enable: %d, top_k_num: %d, stat_thresh: %d, full_scan: %d", + channel_prediction_cfg->enable, + channel_prediction_cfg->top_k_num, + channel_prediction_cfg->stationary_threshold, + channel_prediction_cfg->full_scan_period_ms); +} /** * wma_pno_start() - PNO start request * @wma: wma handle @@ -3447,13 +3477,19 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) 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_t channel_list */ + /* + * TLV place holder for array nlo_configured_parameters(nlo_list) + * TLV place holder for array of uint32_t channel_list + * TLV place holder for chnnl prediction cfg + */ + len = sizeof(*cmd) + + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE; len += sizeof(uint32_t) * CDF_MIN(pno->aNetworks[0].ucChannelCount, WMI_NLO_MAX_CHAN); len += sizeof(nlo_configured_parameters) * CDF_MIN(pno->ucNetworksCount, WMI_NLO_MAX_SSIDS); + len += sizeof(nlo_channel_prediction_cfg); buf = wmi_buf_alloc(wma->wmi_handle, len); if (!buf) { @@ -3540,7 +3576,11 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) WMA_LOGD("Ch[%d]: %d MHz", i, channel_list[i]); } buf_ptr += cmd->num_of_channels * sizeof(uint32_t); - + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(nlo_channel_prediction_cfg)); + buf_ptr += WMI_TLV_HDR_SIZE; + wma_set_pno_channel_prediction(buf_ptr, pno); + buf_ptr += WMI_TLV_HDR_SIZE; /* TODO: Discrete firmware doesn't have command/option to configure * App IE which comes from wpa_supplicant as of part PNO start request. */ @@ -3585,8 +3625,12 @@ CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id) 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_t channel_list */ + /* + * TLV place holder for array of structures nlo_configured_parameters + * TLV place holder for array of uint32_t channel_list + * TLV place holder for chnl prediction cfg + */ + len += WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE; buf = wmi_buf_alloc(wma->wmi_handle, len); if (!buf) { WMA_LOGE("%s: Failed allocate wmi buffer", __func__); @@ -3611,6 +3655,10 @@ CDF_STATUS wma_pno_stop(tp_wma_handle wma, uint8_t vdev_id) WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 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) { @@ -6198,6 +6246,8 @@ CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma, len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; len += sizeof(nlo_configured_parameters) * CDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS); + len += WMI_TLV_HDR_SIZE; /* TLV for channel_list */ + len += WMI_TLV_HDR_SIZE; /* TLV for channel prediction cfg*/ buf = wmi_buf_alloc(wma->wmi_handle, len); if (!buf) { @@ -6260,6 +6310,13 @@ CDF_STATUS wma_set_epno_network_list(tp_wma_handle wma, WMA_LOGD("Auth bit field (%u)", nlo_list[i].auth_type.auth_type); } + + buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); + buf_ptr += WMI_TLV_HDR_SIZE; + + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 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) { -- cgit v1.2.3 From c508f9919e96df9f710f6dd2ff3660e037415c29 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Mon, 28 Sep 2015 17:12:33 -0700 Subject: qcacld-3.0: Changes for early stop scan Early stop scan is a feature for roaming to stop the scans at an early stage as soon as we find a better AP to roam. This would make the roaming happen quickly. Apart from sending the configuration items, the host also has to send down the channel list in a sorted order to optimize the scans and meet the requirement of this feature. This feature is currently applicable only to roaming scans. However the sorted order of scan list will be the same used by all the scans. CRs-Fixed: 932431 Change-Id: I9c7300e4922cb0d517c248bcf60f681a5872a315 --- core/hdd/inc/wlan_hdd_cfg.h | 34 ++++++++++ core/hdd/src/wlan_hdd_cfg.c | 39 +++++++++++ core/mac/inc/sir_api.h | 3 + core/sme/inc/csr_api.h | 3 + core/sme/inc/csr_internal.h | 3 + core/sme/inc/sme_api.h | 3 + core/sme/src/common/sme_api.c | 12 ++++ core/sme/src/csr/csr_api_roam.c | 143 ++++++++++++++++++++++++++++++++++++++++ core/wma/src/wma_scan_roam.c | 24 +++++++ 9 files changed, 264 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 2f4be4dfd64a..4632a21a2cd4 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2700,6 +2700,37 @@ enum dot11p_mode { #define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_MAX (0x7fffffff) #define CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_DEFAULT (60000) +/* + * Early stop scan is a feature for roaming to stop the scans at + * an early stage as soon as we find a better AP to roam. This + * would make the roaming happen quickly. + */ +#define CFG_EARLY_STOP_SCAN_ENABLE "gEnableEarlyStopScan" +#define CFG_EARLY_STOP_SCAN_ENABLE_MIN (0) +#define CFG_EARLY_STOP_SCAN_ENABLE_MAX (1) +#define CFG_EARLY_STOP_SCAN_ENABLE_DEFAULT (0) +/* + * Early stop scan minimum threshold is the minimum threshold + * at which the candidate AP should be to be qualified as a + * potential roam candidate and good enough to stop the roaming scan + */ +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD "gEarlyStopScanMinThreshold" +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN (-60) +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX (-40) +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT (-45) +/* + * Early stop scan maximum threshold is the maximum threshold + * to be considered for stopping the scan. The algorithm starts + * with a scan on the greedy channel list with the minimum threshold + * and steps up the threshold by 20% for each further channel. + * It can step up on each channel but cannot exceed the maximum + * threshold. + */ +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD "gEarlyStopScanMaxThreshold" +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN (-80) +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX (-70) +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT (-78) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3264,6 +3295,9 @@ struct hdd_config { uint8_t stationary_thresh; uint32_t channel_prediction_full_scan; #endif + bool early_stop_scan_enable; + int8_t early_stop_scan_min_threshold; + int8_t early_stop_scan_max_threshold; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index bf57226f1c2c..4b13ed73b7f3 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3517,6 +3517,29 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_SELF_GEN_FRM_PWR_MIN, CFG_SELF_GEN_FRM_PWR_MAX), + REG_VARIABLE(CFG_EARLY_STOP_SCAN_ENABLE, WLAN_PARAM_Integer, + struct hdd_config, early_stop_scan_enable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EARLY_STOP_SCAN_ENABLE_DEFAULT, + CFG_EARLY_STOP_SCAN_ENABLE_MIN, + CFG_EARLY_STOP_SCAN_ENABLE_MAX), + + REG_VARIABLE(CFG_EARLY_STOP_SCAN_MIN_THRESHOLD, + WLAN_PARAM_SignedInteger, struct hdd_config, + early_stop_scan_min_threshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT, + CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN, + CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX), + + REG_VARIABLE(CFG_EARLY_STOP_SCAN_MAX_THRESHOLD, + WLAN_PARAM_SignedInteger, struct hdd_config, + early_stop_scan_max_threshold, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT, + CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN, + CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX), + }; @@ -5050,6 +5073,16 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CFG_CHANNEL_PREDICTION_FULL_SCAN_MS_NAME, pHddCtx->config->channel_prediction_full_scan); #endif + hddLog(LOGE, "Name = [%s] Value = [%d]", + CFG_EARLY_STOP_SCAN_ENABLE, + pHddCtx->config->early_stop_scan_enable); + hddLog(LOGE, "Name = [%s] Value = [%d]", + CFG_EARLY_STOP_SCAN_MIN_THRESHOLD, + pHddCtx->config->early_stop_scan_min_threshold); + hddLog(LOGE, "Name = [%s] Value = [%d]", + CFG_EARLY_STOP_SCAN_MAX_THRESHOLD, + pHddCtx->config->early_stop_scan_max_threshold); + } @@ -6462,6 +6495,12 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) (pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED); hdd_set_pno_channel_prediction_config(smeConfig, pHddCtx); + smeConfig->early_stop_scan_enable = + pHddCtx->config->early_stop_scan_enable; + smeConfig->early_stop_scan_min_threshold = + pHddCtx->config->early_stop_scan_min_threshold; + smeConfig->early_stop_scan_max_threshold = + pHddCtx->config->early_stop_scan_max_threshold; status = sme_update_config(pHddCtx->hHal, smeConfig); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(LOGE, "sme_update_config() return failure %d", diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 28b2e8a7b965..887901bc8bb0 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2900,6 +2900,9 @@ typedef struct sSirRoamOffloadScanReq { uint32_t hi_rssi_scan_rssi_delta; uint32_t hi_rssi_scan_delay; int32_t hi_rssi_scan_rssi_ub; + uint8_t early_stop_scan_enable; + int8_t early_stop_scan_min_threshold; + int8_t early_stop_scan_max_threshold; } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; typedef struct sSirRoamOffloadScanRsp { diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index caa878751c4f..365401784c6f 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1269,6 +1269,9 @@ typedef struct tagCsrConfigParam { uint8_t stationary_thresh; uint32_t channel_prediction_full_scan; #endif + bool early_stop_scan_enable; + int8_t early_stop_scan_min_threshold; + int8_t early_stop_scan_max_threshold; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index d06b9e23103a..f4def8f0e579 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -651,6 +651,9 @@ typedef struct tagCsrConfig { uint8_t stationary_thresh; uint32_t channel_prediction_full_scan; #endif + bool early_stop_scan_enable; + int8_t early_stop_scan_min_threshold; + int8_t early_stop_scan_max_threshold; } tCsrConfig; typedef struct tagCsrChannelPowerInfo { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 7c20e05f5c92..863ea995f3a9 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -130,6 +130,9 @@ typedef struct _smeConfigParams { uint8_t stationary_thresh; uint32_t channel_prediction_full_scan; #endif + bool early_stop_scan_enable; + int8_t early_stop_scan_min_threshold; + int8_t early_stop_scan_max_threshold; } tSmeConfigParams, *tpSmeConfigParams; #ifdef FEATURE_WLAN_TDLS diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 111433369f9b..c436ce546bab 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1349,6 +1349,12 @@ CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams pSmeConfigParams->dual_mac_feature_disable; sme_update_roam_pno_channel_prediction_config(pMac, pSmeConfigParams, SME_CONFIG_TO_ROAM_CONFIG); + pMac->roam.configParam.early_stop_scan_enable = + pSmeConfigParams->early_stop_scan_enable; + pMac->roam.configParam.early_stop_scan_min_threshold = + pSmeConfigParams->early_stop_scan_min_threshold; + pMac->roam.configParam.early_stop_scan_max_threshold = + pSmeConfigParams->early_stop_scan_max_threshold; return status; } @@ -4192,6 +4198,12 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) pMac->f_sta_miracast_mcc_rest_time_val; sme_update_roam_pno_channel_prediction_config(pMac, pParam, ROAM_CONFIG_TO_SME_CONFIG); + pParam->early_stop_scan_enable = + pMac->roam.configParam.early_stop_scan_enable; + pParam->early_stop_scan_min_threshold = + pMac->roam.configParam.early_stop_scan_min_threshold; + pParam->early_stop_scan_max_threshold = + pMac->roam.configParam.early_stop_scan_max_threshold; sme_release_global_lock(&pMac->sme); } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 9074f37cae7c..f4dfbbe4a956 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -474,6 +474,121 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * CDF_ASSERT(0); return 0; } +/** + * csr_roam_sort_channel_for_early_stop() - Sort the channels + * @chan_list: Original channel list from the upper layers + * @num_channel: Number of original channels + * + * For Early stop scan feature, the channel list should be in an order, + * where-in there is a maximum chance to detect an AP in the initial + * channels in the list so that the scanning can be stopped early as the + * feature demands. + * Below fixed greedy channel list has been provided + * based on most of the enterprise wifi installations across the globe. + * + * Identify all the greedy channels within the channel list from user space. + * Identify all the non-greedy channels in the user space channel list. + * Merge greedy channels followed by non-greedy channels back into the + * chan_list. + * + * Return: None + */ +void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list, + uint8_t num_channel) +{ + tSirUpdateChanList *chan_list_greedy, *chan_list_non_greedy; + uint8_t i, j; + static const uint8_t fixed_greedy_chan_list[] = {1, 6, 11, 36, 48, 40, + 44, 10, 2, 9, 149, 157, 161, 3, 4, 8, 153, 165, 7, 5, 136, 140, + 52, 116, 56, 104, 64, 60, 100, 120, 13, 14, 112, 132, 151, 155}; + uint8_t num_fixed_greedy_chan; + uint8_t num_greedy_chan = 0; + uint8_t num_non_greedy_chan = 0; + uint8_t match_found = false; + uint32_t buf_size; + + buf_size = sizeof(tSirUpdateChanList) + + (sizeof(tSirUpdateChanParam) * num_channel); + chan_list_greedy = cdf_mem_malloc(buf_size); + chan_list_non_greedy = cdf_mem_malloc(buf_size); + if (!chan_list_greedy || !chan_list_non_greedy) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Failed to allocate memory for tSirUpdateChanList"); + return; + } + cdf_mem_zero(chan_list_greedy, buf_size); + cdf_mem_zero(chan_list_non_greedy, buf_size); + /* + * fixed_greedy_chan_list is an evaluated channel list based on most of + * the enterprise wifi deployments and the order of the channels + * determines the highest possibility of finding an AP. + * chan_list is the channel list provided by upper layers based on the + * regulatory domain. + */ + num_fixed_greedy_chan = sizeof(fixed_greedy_chan_list)/sizeof(uint8_t); + /* + * Browse through the chan_list and put all the non-greedy channels + * into a seperate list by name chan_list_non_greedy + */ + for (i = 0; i < num_channel; i++) { + for (j = 0; j < num_fixed_greedy_chan; j++) { + if (chan_list->chanParam[i].chanId == + fixed_greedy_chan_list[j]) { + match_found = true; + break; + } + } + if (!match_found) { + cdf_mem_copy( + &chan_list_non_greedy->chanParam[num_non_greedy_chan], + &chan_list->chanParam[i], + sizeof(tSirUpdateChanParam)); + num_non_greedy_chan++; + } else { + match_found = false; + } + } + /* + * Browse through the fixed_greedy_chan_list and put all the greedy + * channels in the chan_list into a seperate list by name + * chan_list_greedy + */ + for (i = 0; i < num_fixed_greedy_chan; i++) { + for (j = 0; j < num_channel; j++) { + if (fixed_greedy_chan_list[i] == + chan_list->chanParam[j].chanId) { + cdf_mem_copy( + &chan_list_greedy->chanParam[num_greedy_chan], + &chan_list->chanParam[j], + sizeof(tSirUpdateChanParam)); + num_greedy_chan++; + break; + } + } + } + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_DEBUG, + "greedy=%d, non-greedy=%d, tot=%d", + num_greedy_chan, num_non_greedy_chan, num_channel); + if ((num_greedy_chan + num_non_greedy_chan) != num_channel) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "incorrect sorting of channels"); + goto scan_list_sort_error; + } + /* Copy the Greedy channels first */ + i = 0; + cdf_mem_copy(&chan_list->chanParam[i], + &chan_list_greedy->chanParam[i], + num_greedy_chan * sizeof(tSirUpdateChanParam)); + /* Copy the remaining Non Greedy channels */ + i = num_greedy_chan; + j = 0; + cdf_mem_copy(&chan_list->chanParam[i], + &chan_list_non_greedy->chanParam[j], + num_non_greedy_chan * sizeof(tSirUpdateChanParam)); +scan_list_sort_error: + cdf_mem_free(chan_list_greedy); + cdf_mem_free(chan_list_non_greedy); +} CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) { @@ -532,6 +647,11 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) else pChanList->chanParam[num_channel].dfsSet = true; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + "channel:%d, pwr=%d, DFS=%d\n", + pChanList->chanParam[num_channel].chanId, + pChanList->chanParam[num_channel].pwr, + pChanList->chanParam[num_channel].dfsSet); num_channel++; } } @@ -550,6 +670,11 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) } } } + if (pMac->roam.configParam.early_stop_scan_enable) + csr_roam_sort_channel_for_early_stop(pChanList, num_channel); + else + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("Early Stop Scan Feature not supported")); msg.type = WMA_UPDATE_CHAN_LIST_REQ; msg.reserved = 0; @@ -1869,6 +1994,13 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->sendDeauthBeforeCon; pMac->enable_dot11p = pParam->enable_dot11p; + pMac->roam.configParam.early_stop_scan_enable = + pParam->early_stop_scan_enable; + pMac->roam.configParam.early_stop_scan_min_threshold = + pParam->early_stop_scan_min_threshold; + pMac->roam.configParam.early_stop_scan_max_threshold = + pParam->early_stop_scan_max_threshold; + } return status; @@ -16773,6 +16905,17 @@ csr_create_roam_scan_offload_request(tpAniSirGlobal mac_ctx, session); req_buf->allowDFSChannelRoam = mac_ctx->roam.configParam.allowDFSChannelRoam; + req_buf->early_stop_scan_enable = + mac_ctx->roam.configParam.early_stop_scan_enable; + req_buf->early_stop_scan_min_threshold = + mac_ctx->roam.configParam.early_stop_scan_min_threshold; + req_buf->early_stop_scan_max_threshold = + mac_ctx->roam.configParam.early_stop_scan_max_threshold; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("EarlyStopFeature Enable=%d, MinThresh=%d, MaxThresh=%d"), + req_buf->early_stop_scan_enable, + req_buf->early_stop_scan_min_threshold, + req_buf->early_stop_scan_max_threshold); #ifdef WLAN_FEATURE_ROAM_OFFLOAD req_buf->RoamOffloadEnabled = csr_roamIsRoamOffloadEnabled(mac_ctx); req_buf->RoamKeyMgmtOffloadEnabled = session->RoamKeyMgmtOffloadEnabled; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 82627bc0757b..5716c52584ad 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1122,6 +1122,7 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, uint8_t *buf_ptr; wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp; wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL; + wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL; struct roam_ext_params *roam_params; int32_t good_rssi_threshold; uint32_t hirssi_scan_max_count; @@ -1139,6 +1140,8 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, 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); + len += WMI_TLV_HDR_SIZE; + len += sizeof(wmi_roam_earlystop_rssi_thres_param); buf = wmi_buf_alloc(wma_handle->wmi_handle, len); if (!buf) { WMA_LOGE("%s : wmi_buf_alloc failed", __func__); @@ -1209,6 +1212,27 @@ CDF_STATUS wma_roam_scan_offload_rssi_thresh(tp_wma_handle wma_handle, WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param, WMITLV_GET_STRUCT_TLVLEN (wmi_roam_scan_extended_threshold_param)); + buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_earlystop_rssi_thres_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *) buf_ptr; + early_stop_thresholds->roam_earlystop_thres_min = + roam_req->early_stop_scan_min_threshold - + WMA_NOISE_FLOOR_DBM_DEFAULT; + early_stop_thresholds->roam_earlystop_thres_max = + roam_req->early_stop_scan_max_threshold - + WMA_NOISE_FLOOR_DBM_DEFAULT; + WMITLV_SET_HDR(&early_stop_thresholds->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_earlystop_rssi_thres_param)); + WMA_LOGD("early_stop_thresholds en=%d, min=%d, max=%d", + roam_req->early_stop_scan_enable, + early_stop_thresholds->roam_earlystop_thres_min, + early_stop_thresholds->roam_earlystop_thres_max); + status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, WMI_ROAM_SCAN_RSSI_THRESHOLD); if (status != EOK) { -- cgit v1.2.3 From 362a597cc8bfa4aa00aeddedd48765c60abcf9d9 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Tue, 6 Oct 2015 19:33:42 -0700 Subject: qcacld-3.0: Add ACS support in 160MHz Add ACS support in SAP 160MHz mode. Change-Id: I4893fc25057c64ea13c0297f6d7734415bcadd23 CRs-Fixed: 919904 --- core/sap/src/sap_ch_select.c | 297 +++++++++++++++++++++++++++++++++++++------ core/sap/src/sap_ch_select.h | 17 ++- 2 files changed, 274 insertions(+), 40 deletions(-) diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index cb8e89fb8bbf..9132827f7719 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -210,6 +210,11 @@ sapAcsChannelInfo acs_ht80_channels[] = { {149, SAP_ACS_WEIGHT_MAX}, }; +sapAcsChannelInfo acs_vht160_channels[] = { + {36, SAP_ACS_WEIGHT_MAX}, + {100, SAP_ACS_WEIGHT_MAX}, +}; + sapAcsChannelInfo acs_ht40_channels24_g[] = { {1, SAP_ACS_WEIGHT_MAX}, {2, SAP_ACS_WEIGHT_MAX}, @@ -805,8 +810,21 @@ void sap_update_rssi_bsscount(tSapSpectChInfo *pSpectCh, int32_t offset, break; case -4: case 4: - rsssi_effect = - SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + rsssi_effect = sap_24g ? + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : + SAP_SUBBAND4_RSSI_EFFECT_PRIMARY; + break; + case -5: + case 5: + rsssi_effect = SAP_SUBBAND5_RSSI_EFFECT_PRIMARY; + break; + case -6: + case 6: + rsssi_effect = SAP_SUBBAND6_RSSI_EFFECT_PRIMARY; + break; + case -7: + case 7: + rsssi_effect = SAP_SUBBAND7_RSSI_EFFECT_PRIMARY; break; default: rsssi_effect = 0; @@ -840,7 +858,8 @@ void sap_upd_chan_spec_params(tSirProbeRespBeacon *pBeaconStruct, uint16_t *channelWidth, uint16_t *secondaryChannelOffset, uint16_t *vhtSupport, - uint16_t *centerFreq) + uint16_t *centerFreq, + uint16_t *centerFreq_2) { if (NULL == pBeaconStruct) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -850,21 +869,60 @@ void sap_upd_chan_spec_params(tSirProbeRespBeacon *pBeaconStruct, 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; - } + *secondaryChannelOffset = + pBeaconStruct->HTInfo.secondaryChannelOffset; + if (!pBeaconStruct->VHTOperation.present) + return; + *vhtSupport = pBeaconStruct->VHTOperation.present; + if (pBeaconStruct->VHTOperation.chanWidth) { + *centerFreq = + pBeaconStruct->VHTOperation.chanCenterFreqSeg1; + *centerFreq_2 = + pBeaconStruct->VHTOperation.chanCenterFreqSeg2; + /* + * LHS follows tSirMacHTChannelWidth, while RHS follows + * WNI_CFG_VHT_CHANNEL_WIDTH_X format hence following + * adjustment + */ + *channelWidth = + pBeaconStruct->VHTOperation.chanWidth + 1; + } } } +/** + * sap_update_rssi_bsscount_vht_5G() - updates bss count and rssi effect. + * + * @pSpectCh: Channel Information + * @offset: Channel Offset + * @num_ch: no.of channels + * + * sap_update_rssi_bsscount_vht_5G updates bss count and rssi effect based + * on the channel offset. + * + * Return: None. + */ + +void sap_update_rssi_bsscount_vht_5G(tSapSpectChInfo *spect_ch, int32_t offset, + uint16_t num_ch) +{ + int32_t ch_offset; + uint16_t i, cnt; + + if (!offset) + return; + if (offset > 0) + cnt = num_ch; + else + cnt = num_ch + 1; + for (i = 0; i < cnt; i++) { + ch_offset = offset + i; + if (ch_offset == 0) + continue; + sap_update_rssi_bsscount(spect_ch, ch_offset, false); + } +} /** * sap_interference_rssi_count_5G() - sap_interference_rssi_count * considers the Adjacent channel rssi and @@ -884,8 +942,12 @@ void sap_upd_chan_spec_params(tSirProbeRespBeacon *pBeaconStruct, void sap_interference_rssi_count_5G(tSapSpectChInfo *spect_ch, uint16_t chan_width, uint16_t sec_chan_offset, - uint16_t center_freq, uint8_t channel_id) + uint16_t center_freq, + uint16_t center_freq_2, + uint8_t channel_id) { + uint16_t num_ch; + int32_t offset = 0; if (NULL == spect_ch) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, FL("spect_ch is NULL")); @@ -900,6 +962,7 @@ void sap_interference_rssi_count_5G(tSapSpectChInfo *spect_ch, * chan_width == 0, HT20 * chan_width == 1, HT40 * chan_width == 2, VHT80 + * chan_width == 3, VHT160 */ switch (spect_ch->channelWidth) { @@ -908,36 +971,49 @@ void sap_interference_rssi_count_5G(tSapSpectChInfo *spect_ch, /* Above the Primary Channel */ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: sap_update_rssi_bsscount(spect_ch, 1, false); - break; + return; /* Below the Primary channel */ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: sap_update_rssi_bsscount(spect_ch, -1, false); - break; + return; } - break; + return; case eHT_CHANNEL_WIDTH_80MHZ: /* VHT80 */ + num_ch = 3; if ((center_freq - channel_id) == 6) { - sap_update_rssi_bsscount(spect_ch, 1, false); - sap_update_rssi_bsscount(spect_ch, 2, false); - sap_update_rssi_bsscount(spect_ch, 3, false); + offset = 1; } else if ((center_freq - channel_id) == 2) { - sap_update_rssi_bsscount(spect_ch, -1, false); - sap_update_rssi_bsscount(spect_ch, 1, false); - sap_update_rssi_bsscount(spect_ch, 2, false); + offset = -1; } else if ((center_freq - channel_id) == -2) { - sap_update_rssi_bsscount(spect_ch, -2, false); - sap_update_rssi_bsscount(spect_ch, -1, false); - sap_update_rssi_bsscount(spect_ch, 1, false); + offset = -2; } else if ((center_freq - channel_id) == -6) { - sap_update_rssi_bsscount(spect_ch, -1, false); - sap_update_rssi_bsscount(spect_ch, -2, false); - sap_update_rssi_bsscount(spect_ch, -3, false); + offset = -3; } break; - default: + case eHT_CHANNEL_WIDTH_160MHZ: /* VHT160 */ + num_ch = 7; + if ((center_freq - channel_id) == 14) + offset = 1; + else if ((center_freq - channel_id) == 10) + offset = -1; + else if ((center_freq - channel_id) == 6) + offset = -2; + else if ((center_freq - channel_id) == 2) + offset = -3; + else if ((center_freq - channel_id) == -2) + offset = -4; + else if ((center_freq - channel_id) == -6) + offset = -5; + else if ((center_freq - channel_id) == -10) + offset = -6; + else if ((center_freq - channel_id) == -14) + offset = -7; break; + default: + return; } + sap_update_rssi_bsscount_vht_5G(spect_ch, offset, num_ch); } /** @@ -1111,6 +1187,7 @@ void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, uint16_t channelWidth; uint16_t secondaryChannelOffset; uint16_t centerFreq; + uint16_t centerFreq_2 = 0; uint16_t vhtSupport; uint32_t ieLen = 0; tSirProbeRespBeacon *pBeaconStruct; @@ -1149,12 +1226,13 @@ void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, sizeof(tSirProbeRespBeacon), 0); if ((sir_parse_beacon_ie - (pMac, pBeaconStruct, - (uint8_t *) (pScanResult->BssDescriptor.ieFields), - ieLen)) == eSIR_SUCCESS) { + (pMac, pBeaconStruct, (uint8_t *) + (pScanResult->BssDescriptor.ieFields), + ieLen)) == eSIR_SUCCESS) { sap_upd_chan_spec_params(pBeaconStruct, &channelWidth, &secondaryChannelOffset, - &vhtSupport, ¢erFreq); + &vhtSupport, ¢erFreq, + ¢erFreq_2); } } /* Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list */ @@ -1188,7 +1266,9 @@ void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, case eCSR_DOT11_MODE_11a: sap_interference_rssi_count_5G( pSpectCh, channelWidth, - secondaryChannelOffset, centerFreq, + secondaryChannelOffset, + centerFreq, + centerFreq_2, channel_id); break; @@ -1199,7 +1279,9 @@ void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, case eCSR_DOT11_MODE_abg: sap_interference_rssi_count_5G( pSpectCh, channelWidth, - secondaryChannelOffset, centerFreq, + secondaryChannelOffset, + centerFreq, + centerFreq_2, channel_id); sap_interference_rssi_count(pSpectCh); break; @@ -1431,6 +1513,143 @@ void sap_sort_chl_weight_ht80(tSapChSelSpectInfo *pSpectInfoParams) } } +/** + * sap_sort_chl_weight_vht160() - to sort the channels with the least weight + * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure + * + * Funtion to sort the channels with the least weight first for VHT160 channels + * + * Return: none + */ +void sap_sort_chl_weight_vht160(tSapChSelSpectInfo *pSpectInfoParams) +{ + uint8_t i, j, n, idx; + tSapSpectChInfo *pSpectInfo; + uint8_t minIdx; + + pSpectInfo = pSpectInfoParams->pSpectCh; + /* for each VHT160 channel, calculate the combined weight of the + 8 20MHz weight */ + for (i = 0; i < ARRAY_SIZE(acs_vht160_channels); i++) { + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (pSpectInfo[j].chNum == + acs_vht160_channels[i].chStartNum) + break; + } + if (j == pSpectInfoParams->numSpectChans) + continue; + + 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) && + ((pSpectInfo[j].chNum + 16) == + pSpectInfo[j + 4].chNum) && + ((pSpectInfo[j].chNum + 20) == + pSpectInfo[j + 5].chNum) && + ((pSpectInfo[j].chNum + 24) == + pSpectInfo[j + 6].chNum) && + ((pSpectInfo[j].chNum + 28) == + pSpectInfo[j + 7].chNum))) { + /* + * some channels does not exist in pSectInfo array, + * skip this channel and those in the same VHT160 width + */ + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 4) == + pSpectInfo[j + 1].chNum) + pSpectInfo[j + 1].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 8) == + pSpectInfo[j + 2].chNum) + pSpectInfo[j + 2].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 12) == + pSpectInfo[j + 3].chNum) + pSpectInfo[j + 3].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 16) == + pSpectInfo[j + 4].chNum) + pSpectInfo[j + 4].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 20) == + pSpectInfo[j + 5].chNum) + pSpectInfo[j + 5].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 24) == + pSpectInfo[j + 6].chNum) + pSpectInfo[j + 6].weight = + SAP_ACS_WEIGHT_MAX * 8; + if ((pSpectInfo[j].chNum + 28) == + pSpectInfo[j + 7].chNum) + pSpectInfo[j + 7].weight = + SAP_ACS_WEIGHT_MAX * 8; + continue; + } + /*found the channel, add the 7 adjacent channels' weight */ + acs_vht160_channels[i].weight = pSpectInfo[j].weight + + pSpectInfo[j + 1].weight + pSpectInfo[j + 2].weight + + pSpectInfo[j + 3].weight + pSpectInfo[j + 4].weight + + pSpectInfo[j + 5].weight + pSpectInfo[j + 6].weight + + pSpectInfo[j + 7].weight; + + /* find best channel among 8 channels as the primary channel */ + if ((pSpectInfo[j].weight + pSpectInfo[j + 1].weight + + pSpectInfo[j + 2].weight + pSpectInfo[j + 3].weight) > + (pSpectInfo[j + 4].weight + pSpectInfo[j + 5].weight + + pSpectInfo[j + 6].weight + pSpectInfo[j + 7].weight)) + idx = 4; + else + idx = 0; + /* find best channel among 4 channels as the primary channel */ + if ((pSpectInfo[j + idx].weight + + pSpectInfo[j + idx + 1].weight) < + (pSpectInfo[j + idx + 2].weight + + pSpectInfo[j + idx + 3].weight)) { + /* lower 2 channels are better choice */ + if (pSpectInfo[j + idx].weight < + pSpectInfo[j + idx + 1].weight) + minIdx = 0 + idx; + else + minIdx = 1 + idx; + } else if (pSpectInfo[j + idx + 2].weight <= + pSpectInfo[j + idx + 3].weight) { + /* upper 2 channels are better choice */ + minIdx = 2 + idx; + } else { + minIdx = 3 + idx; + } + + /* + * set all 8 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 < 8; n++) + pSpectInfo[j + n].weight = SAP_ACS_WEIGHT_MAX * 8; + + pSpectInfo[j + minIdx].weight = acs_vht160_channels[i].weight; + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < pSpectInfoParams->numSpectChans; j++) { + if (CHANNEL_165 == pSpectInfo[j].chNum) { + pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 8; + break; + } + } + + pSpectInfo = pSpectInfoParams->pSpectCh; + for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Channel=%d Weight= %d rssi=%d bssCount=%d"), + pSpectInfo->chNum, pSpectInfo->weight, + pSpectInfo->rssiAgr, pSpectInfo->bssCount); + pSpectInfo++; + } +} + /** * sap_sort_chl_weight_ht40_24_g() - to sort channel with the least weight * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure @@ -1657,9 +1876,13 @@ void sap_sort_chl_weight_all(ptSapContext pSapCtx, break; case CH_WIDTH_80MHZ: + case CH_WIDTH_80P80MHZ: sap_sort_chl_weight_ht80(pSpectInfoParams); break; + case CH_WIDTH_160MHZ: + sap_sort_chl_weight_vht160(pSpectInfoParams); + break; case CH_WIDTH_20MHZ: default: /* Sorting the channels as per weights as 20MHz channels */ diff --git a/core/sap/src/sap_ch_select.h b/core/sap/src/sap_ch_select.h index abefd5266bec..692def6cbc08 100644 --- a/core/sap/src/sap_ch_select.h +++ b/core/sap/src/sap_ch_select.h @@ -68,9 +68,20 @@ #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 */ +/* In HT40/VHT80, Effect of primary Channel RSSi on Subband1 */ +#define SAP_SUBBAND1_RSSI_EFFECT_PRIMARY (-20) +/* In VHT80, Effect of primary Channel RSSI on Subband2 */ +#define SAP_SUBBAND2_RSSI_EFFECT_PRIMARY (-30) +/* In VHT80, Effect of Primary Channel RSSI on Subband3 */ +#define SAP_SUBBAND3_RSSI_EFFECT_PRIMARY (-40) +/* In VHT80, Effect of Primary Channel RSSI on Subband4 */ +#define SAP_SUBBAND4_RSSI_EFFECT_PRIMARY (-50) +/* In VHT80, Effect of Primary Channel RSSI on Subband5 */ +#define SAP_SUBBAND5_RSSI_EFFECT_PRIMARY (-60) +/* In VHT80, Effect of Primary Channel RSSI on Subband6 */ +#define SAP_SUBBAND6_RSSI_EFFECT_PRIMARY (-70) +/* In VHT80, Effect of Primary Channel RSSI on Subband7 */ +#define SAP_SUBBAND7_RSSI_EFFECT_PRIMARY (-80) #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 */ -- cgit v1.2.3 From d9e9b121932c31c31821ff16a8cb78cfcb713669 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Thu, 29 Oct 2015 18:45:24 +0530 Subject: qcacld-3.0: Support for CLI+SAP in the PCL tables for third connection Add support for CLI+SAP combination in the PCL tables which will be used before deciding the PCL for the third connection that is going to come up. CRs-Fixed: 932277 Change-Id: I87e0d6306a40129931268d869b09c5bf763fab95 --- core/cds/inc/cds_concurrency.h | 33 +++++ core/cds/src/cds_concurrency.c | 305 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 972941c07818..9cf3ec0226a0 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -300,6 +300,28 @@ enum cds_one_connection_mode { * MCC using 2x2@5 Ghz * @CDS_P2P_GO_SAP_DBS_1x1: P2P GO & SAP connection on DBS using * 1x1 + * @CDS_P2P_CLI_SAP_SCC_24_1x1: CLI & SAP connection on SCC using + * 1x1@2.4 Ghz + * @CDS_P2P_CLI_SAP_SCC_24_2x2: CLI & SAP connection on SCC using + * 2x2@2.4 Ghz + * @CDS_P2P_CLI_SAP_MCC_24_1x1: CLI & SAP connection on MCC using + * 1x1@2.4 Ghz + * @CDS_P2P_CLI_SAP_MCC_24_2x2: CLI & SAP connection on MCC using + * 2x2@2.4 Ghz + * @CDS_P2P_CLI_SAP_SCC_5_1x1: CLI & SAP connection on SCC using + * 1x1@5 Ghz + * @CDS_P2P_CLI_SAP_SCC_5_2x2: CLI & SAP connection on SCC using + * 2x2@5 Ghz + * @CDS_P2P_CLI_SAP_MCC_5_1x1: CLI & SAP connection on MCC using + * 1x1@5 Ghz + * @CDS_P2P_CLI_SAP_MCC_5_2x2: CLI & SAP connection on MCC using + * 2x2@5 Ghz + * @CDS_P2P_STA_SAP_MCC_24_5_1x1: CLI and SAP connecting on MCC + * in 2.4 and 5GHz 1x1 + * @CDS_P2P_STA_SAP_MCC_24_5_2x2: CLI and SAP connecting on MCC + in 2.4 and 5GHz 2x2 + * @CDS_P2P_CLI_SAP_DBS_1x1,: CLI & SAP connection on DBS using 1x1 + * @CDS_MAX_TWO_CONNECTION_MODE: Max place holder * * These are generic IDs that identify the various roles @@ -361,6 +383,17 @@ enum cds_two_connection_mode { CDS_P2P_GO_SAP_MCC_24_5_1x1, CDS_P2P_GO_SAP_MCC_24_5_2x2, CDS_P2P_GO_SAP_DBS_1x1, + CDS_P2P_CLI_SAP_SCC_24_1x1, + CDS_P2P_CLI_SAP_SCC_24_2x2, + CDS_P2P_CLI_SAP_MCC_24_1x1, + CDS_P2P_CLI_SAP_MCC_24_2x2, + CDS_P2P_CLI_SAP_SCC_5_1x1, + CDS_P2P_CLI_SAP_SCC_5_2x2, + CDS_P2P_CLI_SAP_MCC_5_1x1, + CDS_P2P_CLI_SAP_MCC_5_2x2, + CDS_P2P_CLI_SAP_MCC_24_5_1x1, + CDS_P2P_CLI_SAP_MCC_24_5_2x2, + CDS_P2P_CLI_SAP_DBS_1x1, CDS_MAX_TWO_CONNECTION_MODE }; diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 71a0464baa59..28c0d3b442b3 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -1032,6 +1032,131 @@ third_connection_pcl_dbs_table[CDS_MAX_TWO_CONNECTION_MODE] [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, #endif + [CDS_P2P_CLI_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_5G, CDS_5G_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_24G, CDS_24G, CDS_24G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH_5G, CDS_5G, CDS_5G}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#ifndef QCA_WIFI_3_0_EMU + [CDS_P2P_CLI_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24_5G, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#else + [CDS_P2P_CLI_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_SCC_ON_5_SCC_ON_24, CDS_NONE, CDS_SCC_ON_5_SCC_ON_24}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, +#endif + }; /** @@ -1553,6 +1678,120 @@ third_connection_pcl_nodbs_table[CDS_MAX_TWO_CONNECTION_MODE] CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + + [CDS_P2P_CLI_SAP_SCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_1x1] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_2x2] = { + [CDS_STA_MODE] = {CDS_5G_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_SCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_SCC_CH, CDS_SCC_CH, CDS_SCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_5_1x1] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_MCC_24_5_2x2] = { + [CDS_STA_MODE] = {CDS_MCC_CH, CDS_MCC_CH, CDS_MCC_CH}, + [CDS_SAP_MODE] = {CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + + [CDS_P2P_CLI_SAP_DBS_1x1] = { + [CDS_STA_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_SAP_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_CLIENT_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_P2P_GO_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE}, + [CDS_IBSS_MODE] = { + CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, + }; /** @@ -1655,6 +1894,18 @@ next_action_three_connection_table[CDS_MAX_TWO_CONNECTION_MODE] [CDS_P2P_GO_SAP_MCC_24_5_2x2] = { CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, [CDS_P2P_GO_SAP_DBS_1x1] = {CDS_NOP, CDS_NOP}, + [CDS_P2P_CLI_SAP_SCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_CLI_SAP_SCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_CLI_SAP_MCC_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_P2P_CLI_SAP_MCC_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_P2P_CLI_SAP_SCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_CLI_SAP_SCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_CLI_SAP_MCC_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_P2P_CLI_SAP_MCC_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, + [CDS_P2P_CLI_SAP_MCC_24_5_1x1] = {CDS_DBS, CDS_DBS}, + [CDS_P2P_CLI_SAP_MCC_24_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_DBS_DOWNGRADE}, + [CDS_P2P_CLI_SAP_DBS_1x1] = {CDS_NOP, CDS_NOP}, + }; /** @@ -4622,6 +4873,60 @@ enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( { enum cds_one_connection_mode index = CDS_MAX_TWO_CONNECTION_MODE; + /* P2P Client + SAP */ + if (((CDS_P2P_CLIENT_MODE == conc_connection_list[0].mode) && + (CDS_SAP_MODE == conc_connection_list[1].mode)) || + ((CDS_SAP_MODE == conc_connection_list[0].mode) && + (CDS_P2P_CLIENT_MODE == conc_connection_list[1].mode))) { + /* SCC */ + if (conc_connection_list[0].chan == + conc_connection_list[1].chan) { + if (CDS_IS_CHANNEL_24GHZ( + conc_connection_list[0].chan)) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_SAP_SCC_24_1x1; + else + index = CDS_P2P_CLI_SAP_SCC_24_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_SAP_SCC_5_1x1; + else + index = CDS_P2P_CLI_SAP_SCC_5_2x2; + } + /* MCC */ + } else if (conc_connection_list[0].mac == + conc_connection_list[1].mac) { + if ((CDS_IS_CHANNEL_24GHZ + (conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_24GHZ + (conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_SAP_MCC_24_1x1; + else + index = CDS_P2P_CLI_SAP_MCC_24_2x2; + } else if ((CDS_IS_CHANNEL_5GHZ( + conc_connection_list[0].chan)) && + (CDS_IS_CHANNEL_5GHZ( + conc_connection_list[1].chan))) { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_SAP_MCC_5_1x1; + else + index = CDS_P2P_CLI_SAP_MCC_5_2x2; + } else { + if (CDS_ONE_ONE == + conc_connection_list[0].chain_mask) + index = CDS_P2P_CLI_SAP_MCC_24_5_1x1; + else + index = CDS_P2P_CLI_SAP_MCC_24_5_2x2; + } + /* DBS */ + } else + index = CDS_P2P_CLI_SAP_DBS_1x1; + } else /* STA + SAP */ if (((CDS_STA_MODE == conc_connection_list[0].mode) && (CDS_SAP_MODE == conc_connection_list[1].mode)) || -- cgit v1.2.3 From 52bdc7504f78953389add747123a3430907e2960 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Tue, 20 Oct 2015 19:54:55 +0530 Subject: qcacld-3.0: Set HW mode before issuing connect for Hidden SSID Set the HW mode if needed before connecting to an SSID that is hidden. CRs-Fixed: 928208 Change-Id: Ibefd207327da1b85ae26a91afd27fc6baf98cf14 --- core/cds/inc/cds_concurrency.h | 16 +- core/cds/src/cds_concurrency.c | 184 +++++++++++++---- core/hdd/src/wlan_hdd_cfg80211.c | 13 +- core/hdd/src/wlan_hdd_hostapd.c | 4 +- core/hdd/src/wlan_hdd_wext.c | 19 +- core/mac/inc/sir_api.h | 26 +++ core/mac/src/pe/lim/lim_process_sme_req_messages.c | 1 + core/sme/inc/sme_internal.h | 1 + core/sme/src/common/sme_api.c | 44 ++++ core/sme/src/csr/csr_api_roam.c | 18 ++ core/sme/src/csr/csr_api_scan.c | 221 +++++++++++++++++++-- core/sme/src/csr/csr_inside_api.h | 5 + 12 files changed, 489 insertions(+), 63 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 9cf3ec0226a0..ff9f30b0940e 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -600,6 +600,9 @@ static inline bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, return true; } #endif /* FEATURE_WLAN_CH_AVOID */ +uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, + tCsrRoamProfile * roam_profile); +bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel); bool cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); #ifdef FEATURE_WLAN_FORCE_SAP_SCC @@ -681,8 +684,9 @@ CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, uint32_t vdev_id); CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, uint32_t vdev_id); -CDF_STATUS cds_current_connections_update( - hdd_context_t *hdd_ctx, uint8_t channel); +CDF_STATUS cds_current_connections_update(uint32_t session_id, + uint8_t channel, + enum cds_conn_update_reason); #ifdef MPC_UT_FRAMEWORK CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, @@ -738,16 +742,20 @@ enum cds_con_mode cds_convert_device_mode_to_hdd_type( device_mode_t device_mode); uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, enum hw_mode_bandwidth mac1_bw, enum hw_mode_dbs_capab dbs, - enum hw_mode_agile_dfs_capab dfs); + enum hw_mode_agile_dfs_capab dfs, + enum cds_conn_update_reason reason); enum cds_conc_next_action cds_need_opportunistic_upgrade( hdd_context_t *hdd_ctx); CDF_STATUS cds_next_actions( - hdd_context_t *hdd_ctx, enum cds_conc_next_action action); + hdd_context_t *hdd_ctx, uint32_t session_id, + enum cds_conc_next_action action, + enum cds_conn_update_reason reason); void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, uint8_t dbs_val, uint8_t dbs_plus_agile_scan_val, diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 28c0d3b442b3..6792d1122265 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2377,12 +2377,14 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, /** * cds_soc_set_hw_mode() - Set HW mode command to SME * @hdd_ctx: HDD context + * @session_id: Session ID * @mac0_ss: MAC0 spatial stream configuration * @mac0_bw: MAC0 bandwidth configuration * @mac1_ss: MAC1 spatial stream configuration * @mac1_bw: MAC1 bandwidth configuration * @dbs: HW DBS capability * @dfs: HW Agile DFS capability + * @reason: Reason for connection update * * Sends the set hw mode to the SME module which will pass on * this message to WMA layer @@ -2403,12 +2405,14 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, * Return: Success if the message made it down to the next layer */ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, + uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, enum hw_mode_bandwidth mac1_bw, enum hw_mode_dbs_capab dbs, - enum hw_mode_agile_dfs_capab dfs) + enum hw_mode_agile_dfs_capab dfs, + enum cds_conn_update_reason reason) { int8_t hw_mode_index; struct sir_hw_mode msg; @@ -2428,6 +2432,8 @@ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, msg.hw_mode_index = hw_mode_index; msg.set_hw_mode_cb = (void *)cds_soc_set_hw_mode_cb; + msg.reason = reason; + msg.session_id = session_id; cds_info("set hw mode to sme: hw_mode_index: %d", msg.hw_mode_index); @@ -3625,7 +3631,12 @@ void cds_dbs_opportunistic_timer_handler(void *data) action = cds_need_opportunistic_upgrade(hdd_ctx); if (action) { /* lets call for action */ - cds_next_actions(hdd_ctx, action); + /* session id is being used only + * in hidden ssid case for now. + * So, session id 0 is ok here. + */ + cds_next_actions(hdd_ctx, 0, action, + CDS_UPDATE_REASON_OPPORTUNISTIC); } cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -5240,8 +5251,9 @@ CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) * cds_current_connections_update() - initiates actions * needed on current connections once channel has been decided * for the new connection - * @hdd_ctx: HDD Context + * @session_id: Session id * @channel: Channel on which new connection will be + * @reason: Reason for which connection update is required * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5249,17 +5261,24 @@ CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) * * Return: CDF_STATUS enum */ -CDF_STATUS cds_current_connections_update( - hdd_context_t *hdd_ctx, - uint8_t channel) +CDF_STATUS cds_current_connections_update(uint32_t session_id, + uint8_t channel, + enum cds_conn_update_reason reason) { enum cds_conc_next_action next_action = CDS_NOP; uint32_t num_connections = 0; enum cds_one_connection_mode second_index = 0; enum cds_two_connection_mode third_index = 0; enum cds_band band; + hdd_context_t *hdd_ctx; CDF_STATUS status = CDF_STATUS_E_FAILURE; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return CDF_STATUS_E_FAILURE; + } + if (wma_is_hw_dbs_capable() == false) { cds_err("driver isn't dbs capable, no further action needed"); return CDF_STATUS_E_NOSUPPORT; @@ -5315,12 +5334,14 @@ CDF_STATUS cds_current_connections_update( } if (CDS_NOP != next_action) - status = cds_next_actions(hdd_ctx, next_action); + status = cds_next_actions(hdd_ctx, session_id, + next_action, reason); else status = CDF_STATUS_E_NOSUPPORT; - cds_debug("index2=%d index3=%d next_action=%d, band=%d status=%d", - second_index, third_index, next_action, band, status); + cds_debug("index2=%d index3=%d next_action=%d, band=%d status=%d reason=%d session_id=%d", + second_index, third_index, next_action, band, status, + reason, session_id); done: cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -5437,7 +5458,9 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, break; } if (!wait) - cds_next_actions(hdd_ctx, next_action); + cds_next_actions(hdd_ctx, vdev_id, + next_action, + CDS_UPDATE_REASON_NSS_UPDATE); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); return; } @@ -5450,6 +5473,8 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * @new_nss: the new nss value * @next_action: next action to happen at policy mgr after * beacon update + * @reason: Reason for connection update + * @session_id: Session id * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5458,7 +5483,9 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * Return: CDF_STATUS enum */ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, - uint8_t new_nss, uint8_t next_action) + uint8_t new_nss, uint8_t next_action, + enum cds_conn_update_reason reason, + uint32_t session_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t index = 0, count = 0; @@ -5518,7 +5545,8 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, index++; } if (!CDF_IS_STATUS_SUCCESS(status)) - status = cds_next_actions(hdd_ctx, next_action); + status = cds_next_actions(hdd_ctx, session_id, + next_action, reason); return status; } @@ -5528,7 +5556,9 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * connections once channel has been decided for the new * connection * @hdd_ctx: HDD Context + * @session_id: Session id * @action: action to be executed + * @reason: Reason for connection update * * This function initiates initiates actions * needed on current connections once channel has been decided @@ -5537,7 +5567,9 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * Return: CDF_STATUS enum */ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, - enum cds_conc_next_action action) + uint32_t session_id, + enum cds_conc_next_action action, + enum cds_conn_update_reason reason) { CDF_STATUS status = CDF_STATUS_E_FAILURE; struct sir_hw_mode_params hw_mode; @@ -5574,14 +5606,17 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * update the beacon template & notify FW. Once FW confirms * beacon updated, send down the HW mode change req */ - status = cds_complete_action(hdd_ctx, 1, CDS_DBS); + status = cds_complete_action(hdd_ctx, 1, CDS_DBS, reason, + session_id); break; case CDS_DBS: - status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + status = cds_soc_set_hw_mode(hdd_ctx, session_id, + HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, HW_MODE_DBS, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + reason); break; case CDS_MCC_UPGRADE: /* @@ -5589,14 +5624,17 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * intially. If yes, update the beacon template & notify FW. * Once FW confirms beacon updated, send the HW mode change req */ - status = cds_complete_action(hdd_ctx, 0, CDS_MCC); + status = cds_complete_action(hdd_ctx, 0, CDS_MCC, reason, + session_id); break; case CDS_MCC: - status = cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + status = cds_soc_set_hw_mode(hdd_ctx, session_id, + HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, HW_MODE_DBS_NONE, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + reason); break; default: /* err msg */ @@ -6118,30 +6156,73 @@ CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, } /** - * cds_handle_conc_multiport() - to handle multiport concurrency - * @session_id: Session ID - * @channel: Channel number + * cds_search_and_check_for_session_conc() - Checks if concurrecy is allowed + * @session_id: Session id + * @roam_profile: Pointer to the roam profile * - * This routine will handle STA side concurrency when policy manager - * is enabled. + * Searches and gets the channel number from the scan results and checks if + * concurrency is allowed for the given session ID * - * Return: true or false + * Non zero channel number if concurrency is allowed, zero otherwise */ -bool cds_handle_conc_multiport(uint8_t session_id, - uint8_t channel) +uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, + tCsrRoamProfile *roam_profile) { - bool ret = true; + uint8_t channel = 0; CDF_STATUS status; - p_cds_contextType cds_context; - hdd_adapter_t *adapter; hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + bool ret; - cds_context = cds_get_global_context(); - if (!cds_context) { - cds_err("Invalid CDS context"); - return false; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("Invalid HDD context"); + return channel; } + adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id); + if (!adapter) { + cds_err("Invalid HDD adapter"); + return channel; + } + + status = cds_get_channel_from_scan_result(adapter, + roam_profile, &channel); + if ((CDF_STATUS_SUCCESS != status) || (channel == 0)) { + cds_err("%s error %d %d", + __func__, status, channel); + return 0; + } + + /* Take care of 160MHz and 80+80Mhz later */ + ret = cds_allow_concurrency(hdd_ctx, + cds_convert_device_mode_to_hdd_type( + adapter->device_mode), + channel, HW_MODE_20_MHZ); + if (false == ret) { + cds_err("Connection failed due to conc check fail"); + return 0; + } + + return channel; +} + +/** + * cds_check_for_session_conc() - Check if concurrency is allowed for a session + * @session_id: Session ID + * @channel: Channel number + * + * Checks if connection is allowed for a given session_id + * + * True if the concurrency is allowed, false otherwise + */ +bool cds_check_for_session_conc(uint8_t session_id, + uint8_t channel) +{ + hdd_context_t *hdd_ctx; + hdd_adapter_t *adapter; + bool ret; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { cds_err("Invalid HDD context"); @@ -6158,6 +6239,7 @@ bool cds_handle_conc_multiport(uint8_t session_id, cds_err("Invalid channel number 0"); return false; } + /* Take care of 160MHz and 80+80Mhz later */ ret = cds_allow_concurrency(hdd_ctx, cds_convert_device_mode_to_hdd_type( @@ -6165,6 +6247,36 @@ bool cds_handle_conc_multiport(uint8_t session_id, channel, HW_MODE_20_MHZ); if (false == ret) { cds_err("Connection failed due to conc check fail"); + return 0; + } + + return true; +} + +/** + * cds_handle_conc_multiport() - to handle multiport concurrency + * @session_id: Session ID + * @channel: Channel number + * + * This routine will handle STA side concurrency when policy manager + * is enabled. + * + * Return: true or false + */ +bool cds_handle_conc_multiport(uint8_t session_id, + uint8_t channel) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return false; + } + + if (!cds_check_for_session_conc(session_id, channel)) { + cds_err("Conc not allowed for the session %d", session_id); return false; } @@ -6172,7 +6284,9 @@ bool cds_handle_conc_multiport(uint8_t session_id, if (!CDF_IS_STATUS_SUCCESS(status)) cds_err("clearing event failed"); - status = cds_current_connections_update(hdd_ctx, channel); + status = cds_current_connections_update(session_id, + channel, + CDS_UPDATE_REASON_NORMAL_STA); if (CDF_STATUS_E_FAILURE == status) { cds_err("connections update failed"); return false; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9012628af8b6..c78b8bf80282 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4107,7 +4107,8 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, 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); int ret = 0; enum cds_con_mode intf_mode; @@ -4165,8 +4166,9 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(ret)) hdd_err("clearing event failed"); - ret = cds_current_connections_update(hdd_ctx, - channel_hint); + ret = cds_current_connections_update(adapter->sessionId, + channel_hint, + CDS_UPDATE_REASON_SET_OPER_CHAN); if (CDF_STATUS_E_FAILURE == ret) { /* return in the failure case */ hdd_err("ERROR: connections update failed!!"); @@ -8807,8 +8809,9 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); - status = cds_current_connections_update(pHddCtx, - channelNum); + status = cds_current_connections_update(pAdapter->sessionId, + channelNum, + CDS_UPDATE_REASON_JOIN_IBSS); if (CDF_STATUS_E_FAILURE == status) { hdd_err("ERROR: connections update failed!!"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 2727e1286c44..437a5416430f 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -8241,7 +8241,9 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); - status = cds_current_connections_update(pHddCtx, channel); + status = cds_current_connections_update(pAdapter->sessionId, + channel, + CDS_UPDATE_REASON_START_AP); if (CDF_STATUS_E_FAILURE == status) { hdd_err("ERROR: connections update failed!!"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 9110a2b72093..1f7cc4985028 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7692,19 +7692,25 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, if (apps_args[0] == 0) { hddLog(LOGE, FL("set hw mode for single mac\n")); - cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_2x2, + cds_soc_set_hw_mode(hdd_ctx, + pAdapter->sessionId, + HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, HW_MODE_DBS_NONE, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + CDS_UPDATE_REASON_UT); } else if (apps_args[0] == 1) { hddLog(LOGE, FL("set hw mode for dual mac\n")); - cds_soc_set_hw_mode(hdd_ctx, HW_MODE_SS_1x1, + cds_soc_set_hw_mode(hdd_ctx, + pAdapter->sessionId, + HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, HW_MODE_DBS, - HW_MODE_AGILE_DFS_NONE); + HW_MODE_AGILE_DFS_NONE, + CDS_UPDATE_REASON_UT); } } break; @@ -7714,8 +7720,9 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, enum cds_conc_next_action action; hddLog(LOGE, FL(" is called\n")); - action = cds_current_connections_update(hdd_ctx, - apps_args[0]); + action = cds_current_connections_update(pAdapter->sessionId, + apps_args[0], + CDS_UPDATE_REASON_UT); pr_info("next action is %d {HDD_NOP = 0, HDD_DBS, HDD_DBS_DOWNGRADE, HDD_MCC, HDD_MCC_UPGRADE}", action); } break; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 887901bc8bb0..ba16dd997141 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -95,6 +95,28 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN]; /* This should not be greater than MAX_NUMBER_OF_CONC_CONNECTIONS */ #define MAX_VDEV_SUPPORTED 4 +/** + * enum cds_conn_update_reason: Reason for conc connection update + * @CDS_UPDATE_REASON_SET_OPER_CHAN: Set probable operating channel + * @CDS_UPDATE_REASON_JOIN_IBSS: Join IBSS + * @CDS_UPDATE_REASON_UT: Unit test related + * @CDS_UPDATE_REASON_START_AP: Start AP + * @CDS_UPDATE_REASON_NORMAL_STA: Connection to Normal STA + * @CDS_UPDATE_REASON_HIDDEN_STA: Connection to Hidden STA + * @CDS_UPDATE_REASON_OPPORTUNISTIC: Opportunistic HW mode update + * @CDS_UPDATE_REASON_NSS_UPDATE: NSS update + */ +enum cds_conn_update_reason { + CDS_UPDATE_REASON_SET_OPER_CHAN, + CDS_UPDATE_REASON_JOIN_IBSS, + CDS_UPDATE_REASON_UT, + CDS_UPDATE_REASON_START_AP, + CDS_UPDATE_REASON_NORMAL_STA, + CDS_UPDATE_REASON_HIDDEN_STA, + CDS_UPDATE_REASON_OPPORTUNISTIC, + CDS_UPDATE_REASON_NSS_UPDATE, +}; + typedef enum { eSIR_EXTSCAN_INVALID, eSIR_EXTSCAN_START_RSP, @@ -397,10 +419,14 @@ typedef struct sSirSmeReadyReq { * struct sir_hw_mode - Format of set HW mode * @hw_mode_index: Index of HW mode to be set * @set_hw_mode_cb: HDD set HW mode callback + * @reason: Reason for HW mode change + * @session_id: Session id */ struct sir_hw_mode { uint32_t hw_mode_index; void *set_hw_mode_cb; + enum cds_conn_update_reason reason; + uint32_t session_id; }; /** diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 0db6d07bfc33..b06e32d060fa 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -156,6 +156,7 @@ static CDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg) cdf_mem_zero(req_msg, len); req_msg->hw_mode_index = buf->set_hw.hw_mode_index; + req_msg->reason = buf->set_hw.reason; /* Other parameters are not needed for WMA */ cds_message.bodyptr = req_msg; diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 4ff54c72872b..adc01cbd96a9 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -218,6 +218,7 @@ typedef struct tagSmeStruct { void *dcc_stats_event_context; ocb_callback dcc_stats_event_callback; sme_set_thermal_level_callback set_thermal_level_cb; + void *saved_scan_cmd; } tSmeStruct, *tpSmeStruct; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index c436ce546bab..60c8729660a0 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -156,7 +156,10 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) bool found; hw_mode_cb callback = NULL; struct sir_set_hw_mode_resp *param; + enum cds_conn_update_reason reason; + tSmeCmd *saved_cmd; + sms_log(mac, LOG1, FL("%s"), __func__); param = (struct sir_set_hw_mode_resp *)msg; if (!param) { sms_log(mac, LOGE, FL("HW mode resp param is NULL")); @@ -184,10 +187,48 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) } callback = command->u.set_hw_mode_cmd.set_hw_mode_cb; + reason = command->u.set_hw_mode_cmd.reason; if (callback) { if (!param) { sms_log(mac, LOGE, FL("Callback failed since HW mode params is NULL")); + } else if (reason == CDS_UPDATE_REASON_HIDDEN_STA) { + /* In the case of hidden SSID, connection update + * (set hw mode) is done after the scan with reason + * code eCsrScanForSsid completes. The connect/failure + * needs to be handled after the response of set hw + * mode + */ + saved_cmd = (tSmeCmd *)mac->sme.saved_scan_cmd; + if (!saved_cmd) { + sms_log(mac, LOGP, + FL("saved cmd is NULL, Check this")); + goto end; + } + if (param->status == SET_HW_MODE_STATUS_OK) { + sms_log(mac, LOG1, + FL("search for ssid success")); + csr_scan_handle_search_for_ssid(mac, + saved_cmd); + } else { + sms_log(mac, LOG1, + FL("search for ssid failure")); + csr_scan_handle_search_for_ssid_failure(mac, + saved_cmd); + } + if (saved_cmd->u.roamCmd.pRoamBssEntry) + cdf_mem_free( + saved_cmd->u.roamCmd.pRoamBssEntry); + if (saved_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) + cdf_mem_free(saved_cmd->u.scanCmd.u. + scanRequest.SSIDs.SSIDList); + if (saved_cmd->u.scanCmd.pToRoamProfile) + cdf_mem_free(saved_cmd->u.scanCmd. + pToRoamProfile); + if (saved_cmd) { + cdf_mem_free(saved_cmd); + saved_cmd = NULL; + } } else { sms_log(mac, LOGE, FL("Calling HDD callback for HW mode response")); @@ -200,6 +241,7 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) sms_log(mac, LOGE, FL("Callback does not exist")); } +end: found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry, LL_ACCESS_LOCK); if (found) { @@ -14391,6 +14433,8 @@ CDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, cmd->command = e_sme_command_set_hw_mode; cmd->u.set_hw_mode_cmd.hw_mode_index = msg.hw_mode_index; cmd->u.set_hw_mode_cmd.set_hw_mode_cb = msg.set_hw_mode_cb; + cmd->u.set_hw_mode_cmd.reason = msg.reason; + cmd->u.set_hw_mode_cmd.session_id = msg.session_id; sms_log(mac, LOG1, FL("Queuing e_sme_command_set_hw_mode to CSR")); csr_queue_sme_command(mac, cmd, false); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f4dfbbe4a956..b6125f06dbcf 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -453,6 +453,10 @@ CDF_STATUS csr_close(tpAniSirGlobal pMac) csr_ll_close(&pMac->roam.statsClientReqList); csr_ll_close(&pMac->roam.peStatsReqList); csr_ll_close(&pMac->roam.roamCmdPendingList); + if (pMac->sme.saved_scan_cmd) { + cdf_mem_free(pMac->sme.saved_scan_cmd); + pMac->sme.saved_scan_cmd = NULL; + } /* DeInit Globals */ csr_roam_de_init_globals(pMac); return status; @@ -18818,11 +18822,25 @@ void csr_process_set_hw_mode(tpAniSirGlobal mac, tSmeCmd *command) goto fail; } + /* For hidden SSID case, if there is any scan command pending + * it needs to be cleared before issuing set HW mode + */ + if (command->u.set_hw_mode_cmd.reason == CDS_UPDATE_REASON_HIDDEN_STA) { + sms_log(mac, LOGE, FL("clear any pending scan command")); + status = csr_scan_abort_mac_scan_not_for_connect(mac, + command->u.set_hw_mode_cmd.session_id); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, FL("Failed to clear scan cmd")); + goto fail; + } + } + cdf_mem_set(cmd, len, 0); cmd->messageType = eWNI_SME_SET_HW_MODE_REQ; cmd->length = len; cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index; + cmd->set_hw.reason = command->u.set_hw_mode_cmd.reason; /* * Below callback and context info are not needed for PE as of now. * Storing the passed value in the same s_sir_set_hw_mode format. diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 68f0aeeef874..e66a5417202e 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2022,8 +2022,11 @@ csr_parse_scan_results(tpAniSirGlobal pMac, pNewIes = NULL; status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes, &fMatch, &uc, &mc, &auth); - if (!CDF_IS_STATUS_SUCCESS(status)) + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("save ies fail %d"), + status); break; + } /* * Modify the prefer value to honor PCL list */ @@ -2032,8 +2035,11 @@ csr_parse_scan_results(tpAniSirGlobal pMac, status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc, pNewIes, pRetList, count, uc, mc, &auth); - if (!CDF_IS_STATUS_SUCCESS(status)) + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOG1, FL("save entry fail %d"), + status); break; + } pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK); } /* while */ @@ -2055,14 +2061,17 @@ CDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac, csr_prefer_5ghz(pMac, pFilter); pRetList = cdf_mem_malloc(sizeof(tScanResultList)); - if (NULL == pRetList) + if (NULL == pRetList) { + sms_log(pMac, LOGE, FL("pRetList is NULL")); return CDF_STATUS_E_NOMEM; + } cdf_mem_set(pRetList, sizeof(tScanResultList), 0); csr_ll_open(pMac->hHdd, &pRetList->List); pRetList->pCurEntry = NULL; status = csr_parse_scan_results(pMac, pFilter, pRetList, &count); - sms_log(pMac, LOG2, FL("return %d BSS"), csr_ll_count(&pRetList->List)); + sms_log(pMac, LOG1, FL("return %d BSS %d"), + csr_ll_count(&pRetList->List), status); if (!CDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) { /* Fail or No one wants the result. */ csr_scan_result_purge(pMac, (tScanResultHandle) pRetList); @@ -3654,9 +3663,11 @@ void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand) eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac, tSmeCmd *pCommand, - bool fSuccess) + bool fSuccess, + uint8_t *chan) { eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing; + int8_t channel; switch (pCommand->u.scanCmd.reason) { case eCsrScan11d1: @@ -3688,9 +3699,35 @@ eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac, eCsrNextLostLinkScan3Failed; break; case eCsrScanForSsid: - NextCommand = - (fSuccess) ? eCsrNexteScanForSsidSuccess : - eCsrNexteScanForSsidFailure; + /* When policy manager is disabled: + * success: csr_scan_handle_search_for_ssid + * failure: csr_scan_handle_search_for_ssid_failure + * + * When policy manager is enabled: + * success: + * set hw_mode success -> csr_scan_handle_search_for_ssid + * set hw_mode fail -> csr_scan_handle_search_for_ssid_failure + * failure: csr_scan_handle_search_for_ssid_failure + */ + if (pMac->policy_manager_enabled) { + sms_log(pMac, LOG1, FL("Resp for eCsrScanForSsid")); + channel = cds_search_and_check_for_session_conc( + pCommand->sessionId, + pCommand->u.scanCmd.pToRoamProfile); + if ((!channel) || !fSuccess) { + NextCommand = eCsrNexteScanForSsidFailure; + sms_log(pMac, LOG1, + FL("next ScanForSsidFailure %d %d"), + channel, fSuccess); + } else { + NextCommand = eCsrNextCheckAllowConc; + *chan = channel; + sms_log(pMac, LOG1, FL("next CheckAllowConc")); + } + } else { + NextCommand = (fSuccess) ? eCsrNexteScanForSsidSuccess : + eCsrNexteScanForSsidFailure; + } break; default: NextCommand = eCsrNextScanNothing; @@ -3789,12 +3826,122 @@ csr_diag_scan_complete(tpAniSirGlobal pMac, } #endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ +/** + * csr_save_profile() - Save the profile info from sme command + * @mac_ctx: Global MAC context + * @save_cmd: Pointer where the command will be saved + * @command: Command from which the profile will be saved + * + * Saves the profile information from the SME's scan command + * + * Return: CDF_STATUS + */ +CDF_STATUS csr_save_profile(tpAniSirGlobal mac_ctx, + tSmeCmd *save_cmd, tSmeCmd *command) +{ + tCsrScanResult *scan_result; + tCsrScanResult *temp; + uint32_t bss_len; + CDF_STATUS status; + + save_cmd->u.scanCmd.pToRoamProfile = + cdf_mem_malloc(sizeof(tCsrRoamProfile)); + if (!save_cmd->u.scanCmd.pToRoamProfile) { + sms_log(mac_ctx, LOGE, FL("pToRoamProfile mem fail")); + goto error; + } + + status = csr_roam_copy_profile(mac_ctx, + save_cmd->u.scanCmd.pToRoamProfile, + command->u.scanCmd.pToRoamProfile); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("csr_roam_copy_profile fail")); + goto error; + } + + save_cmd->sessionId = command->sessionId; + save_cmd->u.scanCmd.roamId = command->u.scanCmd.roamId; + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs = + command->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs; + save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList = + cdf_mem_malloc( + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs * + sizeof(tCsrSSIDInfo)); + if (!save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) { + sms_log(mac_ctx, LOGE, FL("SSIDList mem fail")); + goto error; + } + + cdf_mem_copy(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList, + command->u.scanCmd.u.scanRequest.SSIDs.SSIDList, + save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs * + sizeof(tCsrSSIDInfo)); + + if (!command->u.roamCmd.pRoamBssEntry) + return CDF_STATUS_SUCCESS; + + scan_result = GET_BASE_ADDR(command->u.roamCmd.pRoamBssEntry, + tCsrScanResult, Link); + + bss_len = scan_result->Result.BssDescriptor.length + + sizeof(scan_result->Result.BssDescriptor.length); + + temp = cdf_mem_malloc(sizeof(tCsrScanResult) + bss_len); + if (!temp) { + sms_log(mac_ctx, LOGE, FL("bss mem fail")); + goto error; + } + + temp->AgingCount = scan_result->AgingCount; + temp->preferValue = scan_result->preferValue; + temp->capValue = scan_result->capValue; + temp->ucEncryptionType = scan_result->ucEncryptionType; + temp->mcEncryptionType = scan_result->mcEncryptionType; + temp->authType = scan_result->authType; + /* pvIes is unsued in success/failure */ + temp->Result.pvIes = NULL; + + cdf_mem_copy(temp->Result.pvIes, + scan_result->Result.pvIes, + sizeof(*scan_result->Result.pvIes)); + temp->Result.ssId.length = scan_result->Result.ssId.length; + cdf_mem_copy(temp->Result.ssId.ssId, + scan_result->Result.ssId.ssId, + sizeof(scan_result->Result.ssId.ssId)); + temp->Result.timer = scan_result->Result.timer; + cdf_mem_copy(&temp->Result.BssDescriptor, + &scan_result->Result.BssDescriptor, + sizeof(temp->Result.BssDescriptor)); + temp->Link.last = temp->Link.next = NULL; + save_cmd->u.roamCmd.pRoamBssEntry = (tListElem *)temp; + + return CDF_STATUS_SUCCESS; +error: + csr_scan_handle_search_for_ssid_failure(mac_ctx, + command); + if (save_cmd->u.roamCmd.pRoamBssEntry) + cdf_mem_free(save_cmd->u.roamCmd.pRoamBssEntry); + if (save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) + cdf_mem_free(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList); + if (save_cmd->u.scanCmd.pToRoamProfile) + cdf_mem_free(save_cmd->u.scanCmd.pToRoamProfile); + if (save_cmd) { + cdf_mem_free(save_cmd); + save_cmd = NULL; + } + + return CDF_STATUS_E_FAILURE; +} + static void csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, eCsrScanCompleteNextCommand *nxt_cmd, - bool *remove_cmd, uint32_t session_id) + bool *remove_cmd, uint32_t session_id, + uint8_t chan) { - CDF_STATUS status; + CDF_STATUS status, ret; + tSmeCmd *save_cmd = NULL; + switch (*nxt_cmd) { case eCsrNext11dScan1Success: case eCsrNext11dScan2Success: @@ -3852,6 +3999,54 @@ csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, case eCsrNexteScanForSsidFailure: csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand); break; + case eCsrNextCheckAllowConc: + ret = cds_current_connections_update(pCommand->sessionId, + chan, + CDS_UPDATE_REASON_HIDDEN_STA); + sms_log(mac_ctx, LOG1, FL("chan: %d session: %d status: %d"), + chan, pCommand->sessionId, ret); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + sms_log(mac_ctx, LOGE, + FL("memory should have been free. Check!")); + } + + save_cmd = (tSmeCmd *) cdf_mem_malloc(sizeof(*pCommand)); + if (!save_cmd) { + sms_log(mac_ctx, LOGE, FL("save_cmd mem fail")); + goto error; + } + + status = csr_save_profile(mac_ctx, save_cmd, pCommand); + if (!CDF_IS_STATUS_SUCCESS(status) || + !save_cmd) { + /* csr_save_profile should report error */ + sms_log(mac_ctx, LOGE, FL("profile save failed %d"), + status); + return; + } + + mac_ctx->sme.saved_scan_cmd = (void *)save_cmd; + + if (CDF_STATUS_E_FAILURE == ret) { +error: + sms_log(mac_ctx, LOGE, FL("conn update fail %d"), chan); + csr_scan_handle_search_for_ssid_failure(mac_ctx, + pCommand); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + } + } else if (CDF_STATUS_E_NOSUPPORT == ret) { + sms_log(mac_ctx, LOGE, FL("conn update not supported")); + csr_scan_handle_search_for_ssid(mac_ctx, pCommand); + if (mac_ctx->sme.saved_scan_cmd) { + cdf_mem_free(mac_ctx->sme.saved_scan_cmd); + mac_ctx->sme.saved_scan_cmd = NULL; + } + } + break; default: break; } @@ -3916,6 +4111,7 @@ bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) bool fRemoveCommand = true; bool fSuccess; uint32_t sessionId = 0; + uint8_t chan; csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry); if (!pEntry) { @@ -3966,10 +4162,11 @@ bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR csr_diag_scan_complete(pMac, pCommand, pScanRsp); #endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ - NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess); + NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess, + &chan); /* We reuse the command here instead reissue a new command */ csr_handle_nxt_cmd(pMac, pCommand, &NextCommand, - &fRemoveCommand, sessionId); + &fRemoveCommand, sessionId, chan); return fRemoveCommand; } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 16797840820a..0c7fef801057 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -123,6 +123,7 @@ typedef enum { eCsrNext11dScan2Success, eCsrNext11dScanComplete, eCsrNexteScanForSsidFailure, + eCsrNextCheckAllowConc, } eCsrScanCompleteNextCommand; @@ -1060,6 +1061,10 @@ void csr_clear_votes_for_country_info(tpAniSirGlobal pMac); CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, ePhyChanBondState cbMode, bool obssEnabled); #endif +CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal mac, + tSmeCmd *command); +CDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal mac, + tSmeCmd *command); tSirBssDescription* csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, tSirBssDescription *bss_descr); -- cgit v1.2.3 From fd1e7c760d4017114ad12b24ddd1ff174974733e Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Tue, 3 Nov 2015 21:23:25 -0800 Subject: Release 5.0.0.140 Release 5.0.0.140 Change-Id: I4f54ce6df92b097ad33f3d6f97f9352bac4bce28 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 1fa77d28e8d1..bb56633a04df 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 139 +#define QWLAN_VERSION_BUILD 140 -#define QWLAN_VERSIONSTR "5.0.0.139" +#define QWLAN_VERSIONSTR "5.0.0.140" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 97a6ce4bb3ef2aad4db3a89b918aa71241e24ce6 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Thu, 5 Nov 2015 19:31:02 +0530 Subject: qcacld-3.0: Check for concurrency rules before P2P CLI connection Ensure that concurrency rules are validated before initiating a P2P CLI connection. Change-Id: I6ee8d03f2bde9b419391551c0ca988b3672eb089 CRs-Fixed: 935783 --- core/sme/src/csr/csr_api_roam.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b6125f06dbcf..8d74236e35f1 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7246,7 +7246,8 @@ CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, if (CDF_IS_STATUS_SUCCESS(status)) { /* check if set hw mode needs to be done */ if ((pMac->policy_manager_enabled) && - (pScanFilter->csrPersona == CDF_STA_MODE)) { + ((pScanFilter->csrPersona == CDF_STA_MODE) || + (pScanFilter->csrPersona == CDF_P2P_CLIENT_MODE))) { csr_get_bssdescr_from_scan_handle(hBSSList, &first_ap_profile); if (!cds_handle_conc_multiport(sessionId, -- cgit v1.2.3 From 0b72dc6d4594d212d2fc852086ce10f1bd2e7122 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 3 Nov 2015 14:15:55 -0800 Subject: qcacld-3.0: Fix race condition between WMI control RX and driver unload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a qcacld-2.0 to qcacld-3.0 propagation Don’t unregister the event in LIM cleanup since it will be take care by WMI service close. Also in tlshim_mgmt_rx_wmi_handler, add driver load/unload check to avoid processing any WMI_MGMT_RX_EVENTID event even the handler is not NULL Change-Id: I72b53b614218f26e874c964a0d8b0affba6cda79 CRs-Fixed: 904490 --- core/mac/src/pe/lim/lim_api.c | 18 ++++-------------- core/wma/src/wma_mgmt.c | 5 +++++ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 1d0dc07bfc65..4c0efc8d6080 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -644,11 +644,10 @@ tSirRetStatus lim_initialize(tpAniSirGlobal pMac) void lim_cleanup(tpAniSirGlobal pMac) { - void *p_cds_gctx; - CDF_STATUS retStatus; - - /*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 + /* + * 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 */ struct mgmt_frm_reg_info *pLimMgmtRegistration = NULL; @@ -708,15 +707,6 @@ void lim_cleanup(tpAniSirGlobal pMac) /* Now, finally reset the deferred message queue pointers */ lim_reset_deferred_msg_q(pMac); - p_cds_gctx = cds_get_global_context(); - retStatus = wma_de_register_mgmt_frm_client(p_cds_gctx); - - if (retStatus != CDF_STATUS_SUCCESS) - PELOGE(lim_log - (pMac, LOGE, - FL - ("DeRegistering the PE Handle with wma has failed bailing out...")); - ) #if defined WLAN_FEATURE_VOWIFI rrm_cleanup(pMac); #endif diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index c6f0b3ab6b83..8544fa46e5c6 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3049,6 +3049,11 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, return -ENOMEM; } + if (cds_is_load_unload_in_progress()) { + WMA_LOGE("Load/Unload in progress"); + return -EINVAL; + } + cdf_mem_zero(rx_pkt, sizeof(*rx_pkt)); /* -- cgit v1.2.3 From 4263e0964944bc6c38566d95d8fd53e1280a534a Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 3 Nov 2015 11:05:57 -0800 Subject: qcacld-3.0: Set channel width for TDLS link on base channel This is qcacld-2.0 to qcacld-3.0 propagation The htSupportedChannelWidthSet of the TDLS link on base channel should be less than or equal to channel width of STA-AP link. The parameter pStaDs->htSupportedChannelWidthSet represents the channel width of TDLS link on base channel. psessionEntry->htSupportedChannelWidthSet represents the channel width set of STA-AP link. So fill the pStaDs->htSupportedChannelWidthSet from psessionEntry->htSupportedChannelWidthSet. Change-Id: I7fe3f2f449d83f5d6f01adce3a25d8031dfbeb48 CRs-Fixed: 800031 --- core/mac/src/pe/lim/lim_process_tdls.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index fa5a0ab3010c..2c883e1f1181 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2253,8 +2253,15 @@ static void lim_tdls_update_hash_node_info(tpAniSirGlobal pMac, if (htCaps->present) { pStaDs->mlmStaContext.htCapability = 1; pStaDs->htGreenfield = htCaps->greenField; + /* + * pStaDs->htSupportedChannelWidthSet should have the base + * channel capability. The htSupportedChannelWidthSet of the + * TDLS link on base channel should be less than or equal to + * channel width of STA-AP link. So take this setting from the + * psessionEntry. + */ pStaDs->htSupportedChannelWidthSet = - htCaps->supportedChannelWidthSet; + psessionEntry->htSupportedChannelWidthSet; pStaDs->htMIMOPSState = htCaps->mimoPowerSave; pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize; pStaDs->htAMpduDensity = htCaps->mpduDensity; -- cgit v1.2.3 From abb0de459cfb6c5f56c0087def9fed2fc6a30f1f Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 3 Nov 2015 14:33:25 -0800 Subject: qcacld-3.0: Do not advertise 80MHz/160MHz capabilities in 40/20MHz This is qcacld-2.0 to qcacld-3.0 propagation Do not advertise the short GI capability for 80MHz and 160MHz if the operating channel width is 20MHz or 40MHz. Change-Id: I93f0b2e94e27b50fa0baa2a263fc866ba3807fb3 CRs-Fixed: 908743 --- core/mac/src/pe/lim/lim_prop_exts_utils.c | 2 ++ core/mac/src/sys/legacy/src/utils/src/parser_api.c | 37 ++++++++++++++-------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index d5349059edc6..f47dd34caff2 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -126,6 +126,8 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, beacon_struct->VHTOperation.present && session->vhtCapability) { session->vhtCapabilityPresentInBeacon = 1; + session->vhtTxChannelWidthSet = + beacon_struct->VHTOperation.chanWidth; if (((beacon_struct->Vendor1IEPresent && beacon_struct->vendor2_ie.present && beacon_struct->Vendor3IEPresent)) && diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 7dea42c89d37..16bd125f1f88 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -915,21 +915,30 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac, 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); + } - nCfgValue = 0; - if (psessionEntry->htConfig.ht_sgi) - CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_SHORT_GI_80MHZ, - nCfgValue); - - pDot11f->shortGI80MHz = (nCfgValue & 0x0001); - - 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); + 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) -- cgit v1.2.3 From 07fc09dbabf1cb12921686aea19f49a18d7155eb Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 3 Nov 2015 10:21:45 -0800 Subject: qcacld-3.0: Allow minimum value for dwell time for Ext Scan to be 0 This is qcacld-2.0 to qcacld-3.0 propagation Currently min time for dwell time for ext scan is non-zero while it is zero for all other type of scan. This patch makes min value for dwell time for ext scan as zero and consistent with other scans. Change-Id: I7b6f3681c56918af7cdc381d25d6b625a5bdbda3 CRs-Fixed: 923458 --- core/hdd/inc/wlan_hdd_cfg.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 4632a21a2cd4..b9cbef6e761c 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2599,22 +2599,22 @@ enum dot11p_mode { #ifdef FEATURE_WLAN_EXTSCAN #define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_NAME "gExtScanPassiveMaxChannelTime" -#define CFG_EXTSCAN_PASSIVE_MAX_CHANNEL_TIME_MIN (110) +#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 (60) +#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 (40) +#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 (20) +#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 -- cgit v1.2.3 From 3f798190b8c06f5b45397a89945cadff73a0886e Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 23 Oct 2015 17:11:35 +0530 Subject: qcacld-3.0: Fix STA state handling in case of WEP qcacld-2.0 to qcacld-3.0 propagation Handle STA State in hdd_RoamSetKeyCompleteHandler for WEP case. In WEP case Key are set in following order. 1)Group key 2)Unicast Key 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 STA state will be moved to AUTHENTICATED after we set the unicast and group key in WEP case. Change-Id: I7471bc76b10be31c4a2dbb52286c7f808fa27306 CRs-Fixed: 906555 --- core/hdd/inc/wlan_hdd_assoc.h | 4 ++ core/hdd/src/wlan_hdd_assoc.c | 145 ++++++++++++++++++++++++++++-------------- 2 files changed, 102 insertions(+), 47 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index cf136b4325dc..d9012e5e5cda 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -106,6 +106,8 @@ typedef enum { * @uIsAuthenticated: Remembers authenticated state * @dot11Mode: dot11Mode * @proxyARPService: proxy arp service + * @ptk_installed: ptk installed state + * @gtk_installed: gtk installed state */ typedef struct connection_info_s { eConnectionState connState; @@ -122,6 +124,8 @@ typedef struct connection_info_s { uint8_t uIsAuthenticated; uint32_t dot11Mode; uint8_t proxyARPService; + bool ptk_installed; + bool gtk_installed; } connection_info_t; /* Forward declarations */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index ea597dbe04bd..cefae85899dd 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1442,6 +1442,64 @@ done: 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_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 = hdd_change_peer_state(adapter, + hddstactx->conn_info.staId[0], + ol_txrx_peer_state_auth, + hdd_is_roam_sync_in_progress(roaminfo)); + hdd_conn_set_authenticated(adapter, true); + if ((WLAN_HDD_INFRA_STATION == adapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == adapter->device_mode)) { + sme_ps_enable_auto_ps_timer( + WLAN_HDD_GET_HAL_CTX(adapter), + adapter->sessionId, + hddstactx->hdd_ReassocScenario); + } + + return ret; +} + /** * hdd_roam_set_key_complete_handler() - Update the security parameters * @pAdapter: pointer to adapter @@ -1503,59 +1561,52 @@ static CDF_STATUS hdd_roam_set_key_complete_handler(hdd_adapter_t *pAdapter, } 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 + * 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; + 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. */ - cdf_status = - hdd_change_peer_state(pAdapter, pHddStaCtx->conn_info.staId[0], - ol_txrx_peer_state_auth, -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - pRoamInfo->roamSynchInProgress -#else - false -#endif - ); - hdd_conn_set_authenticated(pAdapter, true); - if ((eCSR_ROAM_RESULT_AUTHENTICATED == roamResult) && - (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired) { - hddLog(LOG3, - "Key set for StaId= %d. Changing TL state to AUTHENTICATED", - pHddStaCtx->conn_info.staId[0]); - - /* - * Connections that do not need Upper layer - * authentication, transition TL to - * 'Authenticated' state after the keys are set. - */ + 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) + cdf_status = + hdd_change_sta_state_authenticated(pAdapter, + pRoamInfo); + } else if (pHddStaCtx->conn_info.ptk_installed) { cdf_status = - hdd_change_peer_state(pAdapter, - pHddStaCtx->conn_info.staId[0], - ol_txrx_peer_state_auth, -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - pRoamInfo->roamSynchInProgress -#else - false -#endif - ); + hdd_change_sta_state_authenticated(pAdapter, + pRoamInfo); + } - hdd_conn_set_authenticated(pAdapter, true); - if ((WLAN_HDD_INFRA_STATION == - pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == - pAdapter->device_mode)) { - sme_ps_enable_auto_ps_timer - (WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, - pHddStaCtx->hdd_ReassocScenario); - } + 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; + HDD_ROAM_STATE_NONE; } } else { /* -- cgit v1.2.3 From 8829c51c1f006df568527cdc37fb41e8add2bf74 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Tue, 3 Nov 2015 16:20:02 +0530 Subject: qcacld-3.0: debug info for full reorder offload qcacld-2.0 to qcacld-3.0 propagation Log last 1K physical addresses and corresponding virtual addresses of the Rx buffers. Change-Id: I2bb4502fdd92b362199b579ec3cceaa691d4691f CRs-Fixed: 864569 --- core/cdf/src/i_cdf_nbuf.h | 7 ++++ core/dp/htt/htt_internal.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++ core/dp/htt/htt_rx.c | 3 ++ core/dp/htt/htt_types.h | 4 ++ 4 files changed, 108 insertions(+) diff --git a/core/cdf/src/i_cdf_nbuf.h b/core/cdf/src/i_cdf_nbuf.h index 75536f09ff84..9a83a1086275 100644 --- a/core/cdf/src/i_cdf_nbuf.h +++ b/core/cdf/src/i_cdf_nbuf.h @@ -102,6 +102,9 @@ struct cvg_nbuf_cb { * provided by the OS. */ uint32_t mapped_paddr_lo[CVG_NBUF_MAX_OS_FRAGS]; +#ifdef DEBUG_RX_RING_BUFFER + uint32_t map_index; +#endif /* store extra tx fragments provided by the driver */ struct { @@ -137,6 +140,10 @@ wordstream_flags:CVG_NBUF_MAX_EXTRA_FRAGS + 1; unsigned char tx_htt2_reserved:7; #endif /* QCA_TX_HTT2_SUPPORT */ }; +#ifdef DEBUG_RX_RING_BUFFER +#define NBUF_MAP_ID(skb) \ + (((struct cvg_nbuf_cb *)((skb)->cb))->map_index) +#endif #define NBUF_OWNER_ID(skb) \ (((struct cvg_nbuf_cb *)((skb)->cb))->owner_id) #define NBUF_OWNER_PRIV_DATA(skb) \ diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index 1bc710f7366d..d140f028f2b6 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -125,6 +125,14 @@ struct htt_host_rx_desc_base { (HTT_RX_STD_DESC_RESERVATION >> 2) #define HTT_RX_DESC_ALIGN_MASK 7 /* 8-byte alignment */ +#ifdef DEBUG_RX_RING_BUFFER +#define HTT_RX_RING_BUFF_DBG_LIST 1024 +struct rx_buf_debug { + uint32_t paddr; + void *vaddr; + bool in_use; +}; +#endif static inline struct htt_host_rx_desc_base *htt_rx_desc(cdf_nbuf_t msdu) { return (struct htt_host_rx_desc_base *) @@ -497,4 +505,90 @@ static inline int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) return 0; } #endif /* IPA_OFFLOAD */ +#ifdef DEBUG_RX_RING_BUFFER +/** + * htt_rx_dbg_rxbuf_init() - init debug rx buff list + * @pdev: pdev handle + * + * Return: none + */ +static inline +void htt_rx_dbg_rxbuf_init(struct htt_pdev_t *pdev) +{ + pdev->rx_buff_list = cdf_mem_malloc( + HTT_RX_RING_BUFF_DBG_LIST * + sizeof(struct rx_buf_debug)); + if (!pdev->rx_buff_list) { + cdf_print("HTT: debug RX buffer allocation failed\n"); + CDF_ASSERT(0); + } +} +/** + * htt_rx_dbg_rxbuf_set() - set element of rx buff list + * @pdev: pdev handle + * @paddr: physical address of netbuf + * @rx_netbuf: received netbuf + * + * Return: none + */ +static inline +void htt_rx_dbg_rxbuf_set(struct htt_pdev_t *pdev, + uint32_t paddr, + cdf_nbuf_t rx_netbuf) +{ + 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; + } +} +/** + * htt_rx_dbg_rxbuf_set() - reset element of rx buff list + * @pdev: pdev handle + * @netbuf: rx sk_buff + * Return: none + */ +static inline +void htt_rx_dbg_rxbuf_reset(struct htt_pdev_t *pdev, + cdf_nbuf_t netbuf) +{ + uint32_t index; + + 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; + pdev->rx_buff_list[index].paddr = 0; + pdev->rx_buff_list[index].vaddr = NULL; + } + } +} +#else +static inline +void htt_rx_dbg_rxbuf_init(struct htt_pdev_t *pdev) +{ + return; +} +static inline +void htt_rx_dbg_rxbuf_set(struct htt_pdev_t *pdev, + uint32_t paddr, + cdf_nbuf_t rx_netbuf) +{ + return; +} +static inline +void htt_rx_dbg_rxbuf_reset(struct htt_pdev_t *pdev, + cdf_nbuf_t netbuf) +{ + return; +} +#endif #endif /* _HTT_INTERNAL__H_ */ diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 697763d09144..bd39345e9efb 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -311,6 +311,7 @@ void htt_rx_ring_fill_n(struct htt_pdev_t *pdev, int num) cdf_nbuf_free(rx_netbuf); goto fail; } + htt_rx_dbg_rxbuf_set(pdev, paddr, rx_netbuf); } else { pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf; } @@ -2031,6 +2032,7 @@ cdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr) else cdf_mem_free(hash_entry); + htt_rx_dbg_rxbuf_reset(pdev, netbuf); break; } } @@ -2232,6 +2234,7 @@ int htt_rx_attach(struct htt_pdev_t *pdev) pdev->rx_ring.rx_reset = 0; pdev->rx_ring.htt_rx_restore = 0; #endif + htt_rx_dbg_rxbuf_init(pdev); htt_rx_ring_fill_n(pdev, pdev->rx_ring.fill_level); if (pdev->cfg.is_full_reorder_offload) { diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h index 4082a850e210..2f2e89e5b2ed 100644 --- a/core/dp/htt/htt_types.h +++ b/core/dp/htt/htt_types.h @@ -357,6 +357,10 @@ struct htt_pdev_t { struct htt_ipa_uc_tx_resource_t ipa_uc_tx_rsc; struct htt_ipa_uc_rx_resource_t ipa_uc_rx_rsc; +#ifdef DEBUG_RX_RING_BUFFER + struct rx_buf_debug *rx_buff_list; + int rx_buff_index; +#endif }; #define HTT_EPID_GET(_htt_pdev_hdl) \ -- cgit v1.2.3 From 0239fe881dfc37f8c9bf2d5524768c0da0612241 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 26 Oct 2015 14:32:43 +0530 Subject: qcacld-3.0: Free rx_buff_list in htt_detach qcacld-2.0 to qcacld-3.0 propagation rx_buff_list is not getting freed in htt_detach and causing memory leak. Change-Id: Ia9d6660674c5b4570d337cb66995fc2449145d59 CRs-Fixed: 918223 --- core/dp/htt/htt.c | 1 + core/dp/htt/htt_internal.h | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index 06d0a7ea1eba..be9ece92cfdb 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -350,6 +350,7 @@ void htt_detach(htt_pdev_handle pdev) #endif HTT_TX_MUTEX_DESTROY(&pdev->htt_tx_mutex); HTT_TX_NBUF_QUEUE_MUTEX_DESTROY(pdev); + htt_rx_dbg_rxbuf_deinit(pdev); } /** diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index d140f028f2b6..9e9e672af27f 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -571,6 +571,18 @@ void htt_rx_dbg_rxbuf_reset(struct htt_pdev_t *pdev, } } } +/** + * htt_rx_dbg_rxbuf_deinit() - deinit debug rx buff list + * @pdev: pdev handle + * + * Return: none + */ +static inline +void htt_rx_dbg_rxbuf_deinit(struct htt_pdev_t *pdev) +{ + if (pdev->rx_buff_list) + cdf_mem_free(pdev->rx_buff_list); +} #else static inline void htt_rx_dbg_rxbuf_init(struct htt_pdev_t *pdev) @@ -590,5 +602,10 @@ void htt_rx_dbg_rxbuf_reset(struct htt_pdev_t *pdev, { return; } +static inline +void htt_rx_dbg_rxbuf_deinit(struct htt_pdev_t *pdev) +{ + return; +} #endif #endif /* _HTT_INTERNAL__H_ */ -- cgit v1.2.3 From bf50064109dbfb577777718d7a93085cd890a7c5 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Fri, 30 Oct 2015 11:55:40 +0530 Subject: qcacld-3.0: Change to address memory leak qcacld-2.0 to qcacld-3.0 propagation As per the current implementation during join timer start failure scenario, pMlmJoinReq assigned to NULL with out freeing the memory resulting in memory leak. change made to release the memory in failure scenario. Change-Id: I3f37f45129baec76671caff09790bfb70bf01208 CRs-Fixed: 930553 --- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 4450acd6992a..f256fb2fadb0 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -3551,7 +3551,6 @@ static void lim_process_switch_channel_join_req( MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session_entry->peSessionId, mac_ctx->lim.gLimMlmState)); - session_entry->pLimMlmJoinReq = NULL; goto error; } /* include additional IE if there is */ -- cgit v1.2.3 From 3f212eb58628273f6b834b49256c5bd9934e81c4 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Fri, 30 Oct 2015 11:53:26 +0530 Subject: qcacld-3.0: Properly update specturum channel list qcacld-2.0 to qcacld-3.0 propagation Currently for ACS,one to one correspondence between channel number and index of Sap specturum structure is desired. But the correspondence is broken in case of channel in NOL list or if the DFS channels are not allowed. In case of channel in NOL list or if DFS channel not allowed, channel number is incremented but index of structure doesn't change. As a part of fix, made sure that one to one correspondence is maintained. Change-Id: I05cbe92e2657d96e271b402b9fdbe41a32c7080d CRs-Fixed: 922865 --- core/sap/src/sap_ch_select.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index 9132827f7719..9e7aabc01787 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -659,7 +659,7 @@ bool sap_chan_sel_init(tHalHandle halHandle, /* Fill the channel number in the spectrum in the operating freq band */ for (channelnum = 0; channelnum < pSpectInfoParams->numSpectChans; - channelnum++, pChans++) { + channelnum++, pChans++, pSpectCh++) { chSafe = true; /* check if the channel is in NOL blacklist */ @@ -700,7 +700,6 @@ bool sap_chan_sel_init(tHalHandle halHandle, /* OFDM rates are not supported on channel 14 */ if (*pChans == 14 && eCSR_DOT11_MODE_11b != pSapCtx->csr_roamProfile.phyMode) { - pSpectCh++; continue; } @@ -710,7 +709,6 @@ bool sap_chan_sel_init(tHalHandle halHandle, pSpectCh->rssiAgr = SOFTAP_MIN_RSSI; /* Initialise for all channels */ pSpectCh->channelWidth = SOFTAP_HT20_CHANNELWIDTH; /* Initialise 20MHz for all the Channels */ } - pSpectCh++; } return eSAP_TRUE; } -- cgit v1.2.3 From e0c65cae259a840a8cd20b81d00f299ab0897a14 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Fri, 30 Oct 2015 11:48:42 +0530 Subject: qcacld-3.0: Avoid calling memory allocation function for allocation size 0 qcacld-2.0 to qcacld-3.0 propagation Currently we are calling memory allocation function to allocate memory for FT ies even though FT ies length is 0. Due to above behavior we are seeing unnecessary memory allocation failure error prints. Change made to check for FT ies length before calling memory allocation function. Change-Id: I3f9ddee1d66f51088526f6d370c83697178be925 CRs-Fixed: 930118 --- core/sme/src/csr/csr_api_roam.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 8d74236e35f1..41f33bf50486 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17922,6 +17922,9 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, pSession->ftSmeContext.reassoc_ft_ies = NULL; } + if (!ft_ies_length) + return; + pSession->ftSmeContext.reassoc_ft_ies = cdf_mem_malloc(ft_ies_length); if (NULL == pSession->ftSmeContext.reassoc_ft_ies) { -- cgit v1.2.3 From ae9c3b2373cb674268d8ac75d4960496fc8352c5 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Thu, 5 Nov 2015 12:00:36 -0800 Subject: Release 5.0.0.141 Release 5.0.0.141 Change-Id: I210e5344c902caf66eb4debde39c17441d1e521d CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index bb56633a04df..ddf24da4153b 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 140 +#define QWLAN_VERSION_BUILD 141 -#define QWLAN_VERSIONSTR "5.0.0.140" +#define QWLAN_VERSIONSTR "5.0.0.141" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 1d254e9e8737b1e49f79aff62a7852e764b6f894 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Sun, 8 Nov 2015 02:56:05 -0800 Subject: Revert "qcacld-3.0: HT20 Protection Mode" This reverts commit e85300d7533a347dd7e45919293285038db00a82. Change-Id: Ief91957c0ba7ee1c2efc155f2335d73c37f73c6c --- core/mac/src/pe/lim/lim_utils.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index d34c2a30d0af..0b9df621ecad 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -4256,10 +4256,9 @@ static void lim_handle_ht20protection_enabled(tpAniSirGlobal mac_ctx, } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { session_entry->gLimHt20Params.protectionEnabled = true; if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) { - if (session_entry->htSupportedChannelWidthSet != - eHT_CHANNEL_WIDTH_20MHZ) - session_entry->htOperMode = - eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; + lim_enable_ht_rifs_protection(mac_ctx, false, overlap, beaconparams, session_entry); lim_enable_ht_obss_protection(mac_ctx, false, -- cgit v1.2.3 From 58c6f5e778d74e3f0f1b827f66d2f50489f8c96d Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Sun, 8 Nov 2015 03:02:08 -0800 Subject: Revert "qcacld-3.0: Enable gEnableTxSUBeamformer by default" This reverts commit bff91464a2c38ed4ed0d3aa537d24372a6dd984a. Change-Id: I84c07c9b2214a2d59cf35d9f0ee2deb5e838caf8 --- config/WCNSS_qcom_cfg.ini | 2 +- core/hdd/inc/wlan_hdd_cfg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 3deddd75a766..dd5a17fada16 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -375,7 +375,7 @@ gTxBFEnable=1 gEnableTxBFin20MHz=1 #Enable/Disable SU Tx beamformer support. -gEnableTxSUBeamformer=1 +gEnableTxSUBeamfomer=0 #Enable Scan Results Aging based on timer #Timer value is in seconds diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index b9cbef6e761c..10ddd163acff 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1676,7 +1676,7 @@ typedef enum { #define CFG_VHT_ENABLE_TXBF_IN_20MHZ_MAX (1) #define CFG_VHT_ENABLE_TXBF_IN_20MHZ_DEFAULT (0) -#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER "gEnableTxSUBeamformer" +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER "gEnableTxSUBeamfomer" #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MIN (0) #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MAX (1) #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_DEFAULT (0) -- cgit v1.2.3 From f08b650d384894fd38479cfba38cf5f3f05fab14 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Sun, 8 Nov 2015 15:01:59 -0800 Subject: Release 5.0.0.142 Release 5.0.0.142 Change-Id: Ia33b8a91e1cbbba1b620c838e55fcf1b7f464dde CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index ddf24da4153b..6a2fe346f0a9 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 141 +#define QWLAN_VERSION_BUILD 142 -#define QWLAN_VERSIONSTR "5.0.0.141" +#define QWLAN_VERSIONSTR "5.0.0.142" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From f750df3828ceb40ad7076fbe6221d010dbce51e3 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 20:35:35 +0530 Subject: qcacld-3.0: Handle excessive logging during sta select queue qcacld-2.0 to qcacld-3.0 propagation As a part of unload hdd is stopping the netdev queue. But still N/W layer 3 is calling the select queue netdev ops, where error print appears excessively. As a part of this fix sta select queue netdev ops need to validate Hdd context to take care of SSR and load / unload cases. Change-Id: I087f50ac9e59c3e181bde54f2041f9dda3177266 CRs-Fixed: 857429 --- core/hdd/src/wlan_hdd_wmm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index 0f5da4033e43..d25a71849eae 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -1821,6 +1821,14 @@ uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) uint16_t queueIndex; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); bool is_eapol = false; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + int status; + + status = wlan_hdd_validate_context(hdd_ctx); + 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 opportuniy to transmit data frames. */ -- cgit v1.2.3 From 99828e23c85ba6b16cd2a23a3a057488626b9045 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 30 Oct 2015 21:26:40 +0530 Subject: qcacld-3.0: Prevent null data access qcacld-2.0 to qcacld-3.0 propagation In DFS mode, scan req completed through work item which is async method and may lead to null pointer access during driver unload. So as part of fix null check are put in place to avoid null data access. Change-Id: I1f2255c1ad6e3e881626a32384b9badde1b255fc CRs-Fixed: 894741 --- core/hdd/src/wlan_hdd_scan.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 2804c59f2f69..586c50f56334 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1192,15 +1192,23 @@ 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 = adapter->request; + struct cfg80211_scan_request *request; + if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { + hddLog(LOGE, + "%s: HDD adapter context is invalid", __func__); + return; + } - request->n_ssids = 0; - request->n_channels = 0; + request = adapter->request; + if (request) { + request->n_ssids = 0; + request->n_channels = 0; - hddLog(LOGE, - FL("##In DFS Master mode. Scan aborted. Null result sent")); - cfg80211_scan_done(request, true); - adapter->request = NULL; + hddLog(LOGE, + FL("##In DFS Master mode. Scan aborted. Null result sent")); + cfg80211_scan_done(request, true); + adapter->request = NULL; + } } /** -- cgit v1.2.3 From 4c22aa8745159ef9ce3982b95e9e4bb415814bed Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Sun, 1 Nov 2015 07:57:39 -0800 Subject: qcacld-3.0: Cleanup logging qcacld-2.0 to qcacld-3.0 propagation Some of the logs are misleading to believe that there are some memory related issue which infact is not. Cleanup the logs to convey the exact message that has to be conveyed for those scenarios CRs-Fixed: 907715 Change-Id: Iaab688eb9b8b19705b3d87c4efe1c7ef29ccf613 --- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 50 +++++++++++++---------- core/mac/src/pe/lim/lim_send_management_frames.c | 33 +++++++-------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index e4c672be0e35..75e2e45f175f 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -347,20 +347,24 @@ static void lim_update_ric_data(tpAniSirGlobal mac_ctx, if (assoc_rsp->ricPresent) { session_entry->RICDataLen = assoc_rsp->num_RICData * sizeof(tDot11fIERICDataDesc); - session_entry->ricData = - cdf_mem_malloc(session_entry->RICDataLen); - if (NULL == session_entry->ricData) { - lim_log(mac_ctx, LOGE, - FL("Assoc res/RIC: Unable to allocate memory")); - session_entry->RICDataLen = 0; + if (session_entry->RICDataLen) { + session_entry->ricData = + cdf_mem_malloc(session_entry->RICDataLen); + if (NULL == session_entry->ricData) { + lim_log(mac_ctx, LOGE, + FL("No memory for RIC data")); + session_entry->RICDataLen = 0; + } else { + cdf_mem_copy(session_entry->ricData, + &assoc_rsp->RICData[0], + session_entry->RICDataLen); + } } else { - cdf_mem_copy(session_entry->ricData, - &assoc_rsp->RICData[0], - session_entry->RICDataLen); + lim_log(mac_ctx, LOGE, FL("RIC data not present")); } } else { lim_log(mac_ctx, LOG1, - FL("Ric is not present,Set RICDataLen & RicData to 0")); + FL("Ric is not present")); session_entry->RICDataLen = 0; session_entry->ricData = NULL; } @@ -389,25 +393,29 @@ static void lim_update_ese_tspec(tpAniSirGlobal mac_ctx, session_entry->tspecIes = NULL; } if (assoc_rsp->tspecPresent) { + lim_log(mac_ctx, LOG1, FL("Tspec EID present in assoc rsp")); session_entry->tspecLen = assoc_rsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC); - session_entry->tspecIes = - cdf_mem_malloc(session_entry->tspecLen); - if (NULL == session_entry->tspecIes) { - lim_log(mac_ctx, LOGE, - FL("Assoc Rsp/Tspec:Fail to allocate memory")); - session_entry->tspecLen = 0; + if (session_entry->tspecLen) { + session_entry->tspecIes = + cdf_mem_malloc(session_entry->tspecLen); + if (NULL == session_entry->tspecIes) { + lim_log(mac_ctx, LOGE, + FL("Tspec IE:Fail to allocate memory")); + session_entry->tspecLen = 0; + } else { + cdf_mem_copy(session_entry->tspecIes, + &assoc_rsp->TSPECInfo[0], + session_entry->tspecLen); + } } else { - cdf_mem_copy(session_entry->tspecIes, - &assoc_rsp->TSPECInfo[0], - session_entry->tspecLen); + lim_log(mac_ctx, LOGE, FL("TSPEC has Zero length")); } - lim_log(mac_ctx, LOG1, FL(" Tspec EID present in assoc rsp ")); } else { session_entry->tspecLen = 0; session_entry->tspecIes = NULL; lim_log(mac_ctx, LOG1, - FL(" Tspec EID *NOT* present in assoc rsp ")); + FL("Tspec EID *NOT* present in assoc rsp")); } return; } diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index c7f422052b87..4edbce10f6a5 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -2359,19 +2359,23 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, cdf_mem_free(pe_session->assocReq); pe_session->assocReq = NULL; } - - pe_session->assocReq = cdf_mem_malloc(ft_ies_length); - if (NULL == pe_session->assocReq) { - lim_log(mac_ctx, LOGE, FL("Failed to alloc memory")); - pe_session->assocReqLen = 0; + if (ft_ies_length) { + pe_session->assocReq = cdf_mem_malloc(ft_ies_length); + if (NULL == pe_session->assocReq) { + lim_log(mac_ctx, + LOGE, FL("Failed to alloc memory for FT IEs")); + pe_session->assocReqLen = 0; + } else { + /* + * Store the FT IEs. This is sent to csr/hdd in + * join cnf response. + */ + cdf_mem_copy(pe_session->assocReq, + ft_sme_context->reassoc_ft_ies, ft_ies_length); + pe_session->assocReqLen = ft_ies_length; + } } else { - /* - * Store the Assoc request. This is sent to csr/hdd in - * join cnf response. - */ - cdf_mem_copy(pe_session->assocReq, - ft_sme_context->reassoc_ft_ies, (ft_ies_length)); - pe_session->assocReqLen = (ft_ies_length); + lim_log(mac_ctx, LOG1, FL("FT IEs not present")); } #ifdef FEATURE_WLAN_DIAG_SUPPORT @@ -2692,10 +2696,7 @@ lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, psessionEntry->assocReq = cdf_mem_malloc(nPayload); if (NULL == psessionEntry->assocReq) { - PELOGE(lim_log - (pMac, LOGE, - FL("Unable to allocate memory to store assoc request")); - ) + lim_log(pMac, LOGE, FL("Unable to allocate mem for assoc req")); } else { /* Store the Assoc request. This is sent to csr/hdd in join cnf response. */ cdf_mem_copy(psessionEntry->assocReq, -- cgit v1.2.3 From 3be1a7e7c5ccfff0024f089c6f458c540f747083 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Sun, 1 Nov 2015 08:18:32 -0800 Subject: qcacld-3.0: Avoid PMKID and send correct MIC for CCKM+RSN scenario qcacld-2.0 to qcacld-3.0 propagation In the current design, PMKID is sent in RSN IE in reassoc req for CCKM roaming.When AP receives CCKM IE and PMKID, it gets confused and rejects the reassociation.So in case of CCKM+RSN, don't send PMKID. Also, in reassoc request, MIC was going 0 in CCKMIE.This MIC is calculated by calling platform driver API.When this API returns SUCCESS then result is copied in MIC buffer but if this API returns EINPROGRESS/EBUSY, then driver wait for the event and once the event is completed it does not copy the result in MIC buffer. So changes are done to copy this result in MIC buffer in case of BUSY/INPROGRESS status. Change-Id: Ide74db250aa5c129fa223582be830c15f34cfb16 CRs-Fixed: 763969 --- core/cds/src/cds_utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/cds/src/cds_utils.c b/core/cds/src/cds_utils.c index fd186ae6bbf7..22f1a9453b7d 100644 --- a/core/cds/src/cds_utils.c +++ b/core/cds/src/cds_utils.c @@ -680,6 +680,8 @@ hmac_sha1(uint8_t *key, uint8_t ksize, char *plaintext, uint8_t psize, 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 { -- cgit v1.2.3 From ede6bbb04dec1f8d215f0156a4a5672dcef168f9 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Tue, 3 Nov 2015 16:59:57 -0800 Subject: qcacld-3.0: In FTM mode stopping the MAC is not needed qcacld-2.0 to qcacld-3.0 propagation The MAC is not started upon FTM start. Similarly stopping is not needed during FTM stop. CRs-Fixed: 917306 Change-Id: I72ee4a58c88b54c1dad1b82f749274e0c2e8a9ce --- core/hdd/src/wlan_hdd_ftm.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ftm.c b/core/hdd/src/wlan_hdd_ftm.c index c002991115bc..bf285c00975d 100644 --- a/core/hdd/src/wlan_hdd_ftm.c +++ b/core/hdd/src/wlan_hdd_ftm.c @@ -620,41 +620,17 @@ err_adapter_open_failure: * @hdd_ctx: pointer to HDD context * * This function stops the following modules - * 1. MAC - * 2. WMA + * WMA * * Return: 0 on success, non-zero on failure */ static int wlan_ftm_stop(hdd_context_t *hdd_ctx) { - CDF_STATUS cdf_status; - if (hdd_ctx->ftm.ftm_state != WLAN_FTM_STARTED) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, - "%s:Ftm has not started. Please start the ftm. ", - __func__); + hddLog(LOGP, FL("FTM has not started. No need to stop")); return -EPERM; } - - { - /* STOP MAC only */ - void *hHal; - hHal = cds_get_context(CDF_MODULE_ID_SME); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: NULL hHal", __func__); - } else { - cdf_status = - mac_stop(hHal, HAL_STOP_TYPE_SYS_DEEP_SLEEP); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { - CDF_TRACE(CDF_MODULE_ID_CDF, - CDF_TRACE_LEVEL_ERROR, - "%s: Failed to stop SYS", __func__); - CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); - } - } - wma_stop(hdd_ctx->pcds_context, HAL_STOP_TYPE_RF_KILL); - } + wma_stop(hdd_ctx->pcds_context, HAL_STOP_TYPE_RF_KILL); return 0; } -- cgit v1.2.3 From e835cbf9b8b825920841123aedb7de35d7489da7 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Tue, 3 Nov 2015 17:10:30 -0800 Subject: qcacld-3.0: Enable HI_RSSI feature qcacld-2.0 to qcacld-3.0 propagation Enable the HI_RSSI feature from the code instead of WCNSS_qcom_cfg.ini. CRs-Fixed: 822475 Change-Id: Ic48e49e7042c06b1f0b2bf09d2d7ccae2d7cd9ad --- core/hdd/inc/wlan_hdd_cfg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 10ddd163acff..58da4538afbe 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2641,7 +2641,7 @@ enum dot11p_mode { #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 (0) +#define CFG_ROAM_SCAN_HI_RSSI_DELTA_DEFAULT (10) /* Delay between consecutive scans in milliseconds */ #define CFG_ROAM_SCAN_HI_RSSI_DELAY_NAME "gRoamScanHiRssiDelay" -- cgit v1.2.3 From 47782612ee407d8f765155a173859365549825c7 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Tue, 3 Nov 2015 17:30:43 -0800 Subject: qcacld-3.0: Enable HI_RSSI feature only when connected to 2.4GHz AP qcacld-2.0 to qcacld-3.0 propagation 1) Enable the feature only when connected to 2.4 GHz AP. 2) Modify the default values to reduce the scans and not impact power CRs-Fixed: 817919 Change-Id: Idaff886cec558a06cf9341e47a8ce17b348ad72b --- core/hdd/inc/wlan_hdd_cfg.h | 12 ++++++------ core/sme/src/csr/csr_api_roam.c | 24 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 58da4538afbe..4af4a4f258a6 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2635,7 +2635,7 @@ enum dot11p_mode { #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 (5) +#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" @@ -2646,14 +2646,14 @@ enum dot11p_mode { /* 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 (15000) -#define CFG_ROAM_SCAN_HI_RSSI_DELAY_DEFAULT (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 (-76) -#define CFG_ROAM_SCAN_HI_RSSI_UB_MAX (-30) -#define CFG_ROAM_SCAN_HI_RSSI_UB_DEFAULT (-45) +#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) /* * gPNOChannelPrediction will allow user to enable/disable the * PNO channel prediction feature. diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 41f33bf50486..af5b058be58d 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17062,6 +17062,7 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, struct roam_ext_params *roam_params_dst; struct roam_ext_params *roam_params_src; uint8_t i; + uint8_t op_channel; if (NULL == session) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, @@ -17188,14 +17189,33 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, roam_params_dst->bssid_favored_factor[i]); } + op_channel = session->connectedProfile.operationChannel; req_buf->hi_rssi_scan_max_count = roam_info->cfgParams.hi_rssi_scan_max_count; - req_buf->hi_rssi_scan_rssi_delta = - roam_info->cfgParams.hi_rssi_scan_rssi_delta; req_buf->hi_rssi_scan_delay = roam_info->cfgParams.hi_rssi_scan_delay; req_buf->hi_rssi_scan_rssi_ub = roam_info->cfgParams.hi_rssi_scan_rssi_ub; + /* + * 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 (CDS_IS_CHANNEL_5GHZ(op_channel)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "Disabling HI_RSSI feature as connected AP is 5GHz"); + req_buf->hi_rssi_scan_rssi_delta = 0; + } else { + req_buf->hi_rssi_scan_rssi_delta = + roam_info->cfgParams.hi_rssi_scan_rssi_delta; + } + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + "hi_rssi:delta=%d, max_count=%d, delay=%d, ub=%d", + req_buf->hi_rssi_scan_rssi_delta, + req_buf->hi_rssi_scan_max_count, + req_buf->hi_rssi_scan_delay, + req_buf->hi_rssi_scan_rssi_ub); msg.type = WMA_ROAM_SCAN_OFFLOAD_REQ; msg.reserved = 0; -- cgit v1.2.3 From 6374503b6ef729a050e479561d3e331b49439586 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Tue, 3 Nov 2015 17:34:30 -0800 Subject: qcacld-3.0: Increase the Wait for key timer value qcacld-2.0 to qcacld-3.0 propagation The wait for key timer value in the driver should be greater than that of supplicant. Hence increasing it to 15 seconds. CRs-Fixed: 919403 Change-Id: I5d6e8d445ab9dcef73b923595f41564e0a6e3c6e --- core/sme/src/csr/csr_api_roam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index af5b058be58d..677b88aa967d 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -61,7 +61,7 @@ #define CSR_NUM_IBSS_START_CHANNELS_50 4 #define CSR_NUM_IBSS_START_CHANNELS_24 3 /* 5 seconds, for WPA, WPA2, CCKM */ -#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (5 * CDF_MC_TIMER_TO_SEC_UNIT) +#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (15 * CDF_MC_TIMER_TO_SEC_UNIT) /* 120 seconds, for WPS */ #define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * CDF_MC_TIMER_TO_SEC_UNIT) -- cgit v1.2.3 From 2af97f8b9970fdfc3c5b1f0c385dfd48ab22279a Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Thu, 22 Jan 2015 11:09:55 -0800 Subject: qcacld-3.0: modifications to SETDFSSCANMODE command This is qcacld-2.0 to qcacld-3.0 propagation When SETDFSSCANMODE is set to 0, it should now avoid DFS channels altogether. Original implementation avoided DFS channel in roaming. Now host code will first disable DFS channels and then follow the original path. Modifications to wlan_hdd_cfg80211_disable_dfs_chan_scan() - Keep validation of vendor command from NL. - Moved the DFS channel manipulation code to wlan_hdd_disable_dfs_chan_scan() Call wlan_hdd_disable_dfs_chan_scan() in SETDFSSCANMODE processing. CRs-Fixed: 778613 Change-Id: Ia2c00a6eb8d50e7962224375562a5b6417ba8bb2 --- core/hdd/src/wlan_hdd_cfg80211.c | 117 +++++++++++++++++++++++---------------- core/hdd/src/wlan_hdd_cfg80211.h | 6 +- core/hdd/src/wlan_hdd_ioctl.c | 12 ++++ 3 files changed, 85 insertions(+), 50 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c78b8bf80282..e29a422fe57f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -2513,60 +2513,25 @@ static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx, } /** - * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration - * @wiphy: corestack handler - * @wdev: wireless device - * @data: data - * @data_len: data length - * Return: success(0) or reason code for failure + * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels + * @hdd_ctx: HDD context within host driver + * @adapter: 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: 0 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 wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + uint32_t no_dfs_flag) { - struct net_device *dev = wdev->netdev; - hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter); - hdd_context_t *hdd_ctx = wiphy_priv(wiphy); - struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1]; CDF_STATUS status; int ret_val = -EPERM; - uint32_t no_dfs_flag = 0; - - if (CDF_FTM_MODE == hdd_get_conparam()) { - hdd_err("Command not allowed in FTM mode"); - return -EPERM; - } - - if (wlan_hdd_validate_context(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("HDD context is not valid")); - return -EINVAL; - } - - 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(CDF_TRACE_LEVEL_ERROR, FL("invalid attr")); - return -EINVAL; - } - - if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("attr dfs flag failed")); - return -EINVAL; - } - - no_dfs_flag = nla_get_u32( - tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]); - - hddLog(CDF_TRACE_LEVEL_INFO, FL(" DFS flag = %d"), - no_dfs_flag); - - if (no_dfs_flag > 1) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("invalid value of dfs flag")); - return -EINVAL; - } if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) { if (no_dfs_flag) { @@ -2613,7 +2578,61 @@ static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy, FL(" the DFS flag has not changed")); ret_val = 0; } + return ret_val; +} + +/** + * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration + * @wiphy: corestack handler + * @wdev: wireless device + * @data: data + * @data_len: data length + * Return: success(0) or reason code for failure + */ +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 *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1]; + int ret_val; + uint32_t no_dfs_flag = 0; + + ENTER(); + ret_val = wlan_hdd_validate_context(hdd_ctx); + + if (ret_val) { + hdd_err("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)) { + hdd_err("invalid attr"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) { + hdd_err("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(hdd_ctx, adapter, + no_dfs_flag); return ret_val; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 7357451f4ca1..f8cdd9001751 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2275,5 +2275,9 @@ int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter); enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type( enum nl80211_iftype type); -#endif +int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + uint32_t no_dfs_flag); + +#endif diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 43c213ffa348..53afb626ddc2 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5080,6 +5080,18 @@ static int drv_cmd_set_dfs_scan_mode(hdd_adapter_t *adapter, "%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(hdd_ctx, adapter, + (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; + } + hdd_ctx->config->allowDFSChannelRoam = dfsScanMode; sme_update_dfs_scan_mode(hdd_ctx->hHal, adapter->sessionId, dfsScanMode); -- cgit v1.2.3 From c2579efc8ee110825326d0b269d1988af70b9f6c Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 29 Oct 2015 11:26:02 -0700 Subject: qcacld-3.0: Avoid buffer overflow during extscan bucket fill This is a qcacld-2.0 to qcacld-3.0 propagation. Function hdd_extscan_start_fill_bucket_channel_spec() is used to transfer EXTSCAN bucket parameters from a netlink message to an internal representation. A code analysis tool identified a potential buffer overflow of the per-bucket channel list in this function. In reality this is a false positive since there is other logic which limits the total number of channels across all buckets, and this logic will prevent overflow of the channel list for a single bucket since they use the same limit. However this presents a code maintenance issue since a potential overflow could be introduced in the future if a change is made to allow the total number of channels across all buckets to exceed the number of channels allowed in a single bucket. To protect against this possibility, as well as make the code analysis tool happy, add an additional check to make sure the per-bucket channel list does not overflow. Change-Id: Ifdf2de918d8b2c5a907e833e7bc42315b607e5a5 CRs-Fixed: 922047 --- core/hdd/src/wlan_hdd_ext_scan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index e5cf724e4560..e692ab71f666 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -2905,6 +2905,11 @@ static int hdd_extscan_start_fill_bucket_channel_spec( j = 0; nla_for_each_nested(channels, bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) { + if ((j >= req_msg->buckets[bkt_index].numChannels) || + hdd_extscan_channel_max_reached(req_msg, + total_channels)) + break; + if (nla_parse(channel, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, nla_data(channels), nla_len(channels), @@ -2913,10 +2918,6 @@ static int hdd_extscan_start_fill_bucket_channel_spec( return -EINVAL; } - if (hdd_extscan_channel_max_reached(req_msg, - total_channels)) - break; - /* Parse and fetch channel */ if (!channel[ QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) { -- cgit v1.2.3 From 36d282b5d533d444a388d015d7d11130b4f11bf0 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 3 Nov 2015 14:10:13 -0800 Subject: qcacld-3.0: Add length sanity check in iw_set_keepalive_params Propagation from qcacld-2.0 to qcacld-3.0 Add length sanity check in iw_set_keepalive_params to avoid stack over flow. Change-Id: If59794d1b5f8efad2fe54844fab0e7cea9b1b983 CRs-Fixed: 932466 --- core/hdd/inc/wlan_hdd_wext.h | 10 ------- core/hdd/src/wlan_hdd_wext.c | 67 ++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 49 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index de61e903e6ae..1f78e4916586 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -283,16 +283,6 @@ typedef struct ccp_freq_chan_map_s { #define WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 #define WLAN_KEEP_ALIVE_NULL_PKT 1 -/* Offload request. */ -typedef struct { - uint8_t packetType; - uint32_t timePeriod; - uint8_t hostIpv4Addr[4]; - uint8_t destIpv4Addr[4]; - uint8_t destMacAddr[ETH_ALEN]; - uint8_t bssIdx; -} tKeepAliveRequest, *tpKeepAliveRequest; - #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) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 1f7cc4985028..6f7a9ace6efd 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -8434,8 +8434,7 @@ static int __iw_set_keepalive_params(struct net_device *dev, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tpKeepAliveRequest pRequest = (tpKeepAliveRequest) extra; - tSirKeepAliveReq keepaliveRequest; + tpSirKeepAliveReq request = (tpSirKeepAliveReq) extra; hdd_context_t *hdd_ctx; int ret; @@ -8444,61 +8443,51 @@ static int __iw_set_keepalive_params(struct net_device *dev, if (0 != ret) return ret; - if (pRequest->timePeriod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) { - hddLog(LOGE, FL("Value of timePeriod %d exceed Max limit %d"), - pRequest->timePeriod, + if (wrqu->data.length != sizeof(*request)) { + hdd_err("Invalid length %d", wrqu->data.length); + return -EINVAL; + } + + if (request->timePeriod > WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX) { + hdd_err("Value of timePeriod %d exceed Max limit %d", + request->timePeriod, WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STAMAX); return -EINVAL; } /* Debug display of request components. */ - hddLog(CDF_TRACE_LEVEL_INFO, - "%s: Set Keep Alive Request : TimePeriod %d size %zu", - __func__, pRequest->timePeriod, sizeof(tKeepAliveRequest)); + hdd_info("Set Keep Alive Request : TimePeriod %d size %zu", + request->timePeriod, sizeof(tSirKeepAliveReq)); - switch (pRequest->packetType) { + switch (request->packetType) { case WLAN_KEEP_ALIVE_NULL_PKT: - hddLog(CDF_TRACE_LEVEL_WARN, "%s: Keep Alive Request: Tx NULL", - __func__); + hdd_info("Keep Alive Request: Tx NULL"); break; case WLAN_KEEP_ALIVE_UNSOLICIT_ARP_RSP: - hddLog(CDF_TRACE_LEVEL_INFO_HIGH, - "%s: Keep Alive Request: Tx UnSolicited ARP RSP", - __func__); + hdd_info("Keep Alive Request: Tx UnSolicited ARP RSP"); - hddLog(CDF_TRACE_LEVEL_WARN, " Host IP address: %d.%d.%d.%d", - pRequest->hostIpv4Addr[0], pRequest->hostIpv4Addr[1], - pRequest->hostIpv4Addr[2], pRequest->hostIpv4Addr[3]); + hdd_info("Host IP address: %d.%d.%d.%d", + request->hostIpv4Addr[0], request->hostIpv4Addr[1], + request->hostIpv4Addr[2], request->hostIpv4Addr[3]); - hddLog(CDF_TRACE_LEVEL_WARN, " Dest IP address: %d.%d.%d.%d", - pRequest->destIpv4Addr[0], pRequest->destIpv4Addr[1], - pRequest->destIpv4Addr[2], pRequest->destIpv4Addr[3]); + hdd_info("Dest IP address: %d.%d.%d.%d", + request->destIpv4Addr[0], request->destIpv4Addr[1], + request->destIpv4Addr[2], request->destIpv4Addr[3]); - hddLog(CDF_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]); + hdd_info("Dest MAC address: %d:%d:%d:%d:%d:%d", + request->destMacAddr[0], request->destMacAddr[1], + request->destMacAddr[2], request->destMacAddr[3], + request->destMacAddr[4], request->destMacAddr[5]); break; } - /* Execute keep alive 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(&keepaliveRequest, pRequest, wrqu->data.length); - - hddLog(CDF_TRACE_LEVEL_ERROR, "set Keep: TP before SME %d", - keepaliveRequest.timePeriod); + hdd_info("Keep alive period %d", request->timePeriod); if (CDF_STATUS_SUCCESS != sme_set_keep_alive(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, &keepaliveRequest)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - "%s: Failure to execute Keep Alive", __func__); + pAdapter->sessionId, request)) { + hdd_err("Failure to execute Keep Alive"); return -EINVAL; } @@ -10559,7 +10548,7 @@ static const struct iw_priv_args we_private_args[] = { { WLAN_SET_KEEPALIVE_PARAMS, - IW_PRIV_TYPE_BYTE | WE_MAX_STR_LEN, + sizeof(tSirKeepAliveReq) | IW_PRIV_SIZE_FIXED, 0, "setKeepAlive" } -- cgit v1.2.3 From bee32255a3ebd288cbf666fffb81d9126511cfba Mon Sep 17 00:00:00 2001 From: Leo Chang Date: Mon, 26 Oct 2015 20:07:13 -0700 Subject: qcacld-3.0: ipa hw pipe force shutdown qcacld-2.0 to qcacld-3.0 propagation When the driver is in SoftAP mode when it is unloaded, and if many clients are connected, sometimes not all clients can gracefully disconnect. In this case the IPA HW pipes are not cleaned up properly, and subsequent pipe setup will usually fail. To avoid a bad pipe configuration, before unloading driver, check the pipe status and if the pipes are not closed properly, shutdown the pipes forcefully. Change-Id: Icc0543567423cc4b625140280be13ef733d7d67d CRs-fixed: 886229 --- core/hdd/inc/wlan_hdd_ipa.h | 13 ++++++----- core/hdd/src/wlan_hdd_ipa.c | 53 +++++++++++++++++++++++++++++++++++++++++--- core/hdd/src/wlan_hdd_main.c | 2 ++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h index a2f5fb32e1c1..d4189bee05ab 100644 --- a/core/hdd/inc/wlan_hdd_ipa.h +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -56,6 +56,9 @@ void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, uint8_t reason); bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx); bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx); int hdd_ipa_send_mcc_scc_msg(hdd_context_t *pHddCtx, bool mcc_mode); +int hdd_ipa_uc_ssr_reinit(void); +int hdd_ipa_uc_ssr_deinit(void); +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx); #else static inline CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) { @@ -131,12 +134,6 @@ static inline bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx) { return false; } -#endif /* IPA_OFFLOAD */ - -#ifdef IPA_UC_OFFLOAD -int hdd_ipa_uc_ssr_reinit(void); -int hdd_ipa_uc_ssr_deinit(void); -#else static inline int hdd_ipa_uc_ssr_reinit(void) { return false; @@ -146,6 +143,10 @@ static inline int hdd_ipa_uc_ssr_deinit(void) { return false; } +static inline void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) +{ + return; +} #endif #endif /* #ifndef HDD_IPA_H__ */ diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 7f6ed0b45938..236dd036d23d 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -397,6 +397,7 @@ struct hdd_ipa_priv { struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT]; cdf_list_t pending_event; cdf_mutex_t event_lock; + bool ipa_pipes_down; uint32_t ipa_tx_packets_diff; uint32_t ipa_rx_packets_diff; uint32_t ipa_p_tx_packets; @@ -1005,7 +1006,7 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) return result; } ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, false); - + hdd_ipa->ipa_pipes_down = false; return 0; } @@ -1019,6 +1020,8 @@ static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa) { int result; + hdd_ipa->ipa_pipes_down = true; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable RX PIPE", __func__); result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle); if (result) { @@ -1754,7 +1757,37 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) return CDF_STATUS_SUCCESS; } -#ifdef IPA_UC_OFFLOAD +/** + * 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(CDF_TRACE_LEVEL_ERROR, + "IPA pipes are not down yet, force shutdown"); + hdd_ipa_uc_disable_pipes(hdd_ipa); + } else { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "IPA pipes are down, do nothing"); + } + + return; +} + /** * hdd_ipa_uc_ssr_deinit() - handle ipa deinit for SSR * @@ -1763,6 +1796,7 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) * * Return: 0 - Success */ +#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_deinit(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; @@ -1798,6 +1832,13 @@ int hdd_ipa_uc_ssr_deinit(void) */ return 0; } +#else +int hdd_ipa_uc_ssr_deinit(void) +{ + return 0; +} +#endif + /** * hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR @@ -1807,6 +1848,7 @@ int hdd_ipa_uc_ssr_deinit(void) * * Return: 0 - Success */ +#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_reinit(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; @@ -1821,6 +1863,11 @@ int hdd_ipa_uc_ssr_reinit(void) */ return 0; } +#else +int hdd_ipa_uc_ssr_reinit(void) +{ + return 0; +} #endif /** @@ -3813,7 +3860,7 @@ CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) hdd_ipa->resource_loading = false; hdd_ipa->resource_unloading = false; hdd_ipa->sta_connected = 0; - + hdd_ipa->ipa_pipes_down = true; /* Setup IPA sys_pipe for MCC */ if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { ret = hdd_ipa_setup_sys_pipe(hdd_ipa); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c25c880ffba7..85e62e6a441f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5672,6 +5672,8 @@ static void hdd_driver_exit(void) hddLog(CDF_TRACE_LEVEL_FATAL, FL("module exit called before probe")); } else { + /* Check IPA HW Pipe shutdown */ + hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); #ifdef QCA_PKT_PROTO_TRACE cds_pkt_proto_trace_close(); #endif /* QCA_PKT_PROTO_TRACE */ -- cgit v1.2.3 From af1f78ce9c9934a1dcedd1dd58b20af063e81f1a Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Fri, 6 Nov 2015 15:22:46 +0530 Subject: qcacld-3.0: Issue connect immediately if system is in required hw mode Issue the connect command immediately when the system is already in the required hw mode. Currently the connect command is issued immediately only when the concurrent connection update succeeds, i.e., only when a set hw mode succeeds. But, when the driver is already in the required hw mode, the return value would not be success and the connect command is not getting issued immediately. Fixed this by checking the return value which indicates that the driver is already in the required hw mode, and issuing the connect command immediately. Change-Id: I1ef2adf4d92953f47d36bdae41a9d7d8d559a203 CRs-Fixed: 936268 --- core/sme/src/csr/csr_api_scan.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index e66a5417202e..806d5b5f4569 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -4038,14 +4038,18 @@ error: cdf_mem_free(mac_ctx->sme.saved_scan_cmd); mac_ctx->sme.saved_scan_cmd = NULL; } - } else if (CDF_STATUS_E_NOSUPPORT == ret) { - sms_log(mac_ctx, LOGE, FL("conn update not supported")); + } else if ((CDF_STATUS_E_NOSUPPORT == ret) || + (CDF_STATUS_E_ALREADY == ret)) { + sms_log(mac_ctx, LOGE, FL("conn update ret %d"), ret); csr_scan_handle_search_for_ssid(mac_ctx, pCommand); if (mac_ctx->sme.saved_scan_cmd) { cdf_mem_free(mac_ctx->sme.saved_scan_cmd); mac_ctx->sme.saved_scan_cmd = NULL; } } + /* Else: Set hw mode was issued and the saved connect would + * be issued after set hw mode response + */ break; default: break; -- cgit v1.2.3 From 2af79f7c44b7d995fea6131f559406eeefbec3b3 Mon Sep 17 00:00:00 2001 From: Bhargav Shah Date: Wed, 8 Jul 2015 10:21:37 +0530 Subject: qcacld-3.0: Variable over written in hdd_set_app_type2_parser. qcacld-2.0 to qcacld-3.0 propagation Currently in hdd_set_app_type2_parser, sscanf writes 4 bytes of data in tcp_src_port and tcp_dst_port variable. The original size of variable is 2 byte. Update code to write appropriate size of data in variable. Change-Id: Ifdbfa06da6cb7d0bfef4f4e105a6911950f1d6ad CRs-Fixed: 859493 --- core/hdd/src/wlan_hdd_ioctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 53afb626ddc2..1c8f70ac4738 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1794,14 +1794,14 @@ static int hdd_set_app_type2_parser(hdd_adapter_t *adapter, memset(¶ms, 0, sizeof(tSirAppType2Params)); - ret = sscanf(arg, "%17s %16s %x %x %x %u %u %u %u %u %u %u %u %u %u", + 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, - (unsigned int *)¶ms.tcp_src_port, - (unsigned int *)¶ms.tcp_dst_port, + (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, -- cgit v1.2.3 From 14bbceda681dbf56dab84f5b5da75f0b46eee9a1 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Wed, 4 Nov 2015 14:30:43 -0800 Subject: qcacld-3.0: Remove wma_update_intf_hw_mode_params from vdev start rsp The Tx & Rx SS & mac id update already been done by wma_vdev_start_resp_handler. So, no need to update again by calling wma_update_intf_hw_mode_params. Change-Id: Ib9804bf0d30c75d95b14925a902fe167fa681be0 CRs-fixed: 935341 --- core/wma/src/wma_dev_if.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 925fcdb98b19..79e17be2c54c 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -662,13 +662,6 @@ static void wma_vdev_start_rsp(tp_wma_handle wma, add_bss->nss = 1; } add_bss->smpsMode = host_map_smps_mode(resp_event->smps_mode); - if (WMA_DEFAULT_HW_MODE_INDEX == wma->new_hw_mode_index) { - WMA_LOGE("%s: Invalid index to update for vdev_id %d", - __func__, resp_event->vdev_id); - } else { - wma_update_intf_hw_mode_params(resp_event->vdev_id, - resp_event->mac_id, wma->new_hw_mode_index); - } send_fail_resp: WMA_LOGD("%s: Sending add bss rsp to umac(vdev %d status %d)", __func__, resp_event->vdev_id, add_bss->status); -- cgit v1.2.3 From 812a89262a4bf36ab67c4269edd1f2df11d14d98 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Wed, 4 Nov 2015 18:23:18 -0800 Subject: qcacld-3.0: dump the 3 port connection topology with new logs The existing log for dumping concurrency information doesn't consider DBS & also doesn't cover for various new combinations added newly. Update logic for dumping DBS info & cover the new concurrency cases. Change-Id: Id898bdc2c8aabfa70c99e6193c52f2723ded5c65 CRs-fixed: 935453 --- core/cds/src/cds_concurrency.c | 86 ++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 6792d1122265..48a99f33706b 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -73,7 +73,7 @@ static struct cds_conc_connection_info ((MAX_NUMBER_OF_CONC_CONNECTIONS > index) && \ (conc_connection_list[index].in_use)) -#define CDS_MAX_CON_STRING_LEN 50 +#define CDS_MAX_CON_STRING_LEN 100 /** * first_connection_pcl_table - table which provides PCL for the * very first connection in the system @@ -2708,62 +2708,49 @@ static uint32_t cds_dump_current_concurrency_three_connection( */ static void cds_dump_dbs_concurrency(char *cc_mode, uint32_t length) { + char buf[4] = {0}; + uint8_t mac = 0; + strlcat(cc_mode, " DBS", length); if (conc_connection_list[0].mac == conc_connection_list[1].mac) { if (conc_connection_list[0].chan == - conc_connection_list[1].chan) { - if (0 == conc_connection_list[0].mac) - strlcat(cc_mode, " with SCC on mac0", - length); - else - strlcat(cc_mode, " with SCC on mac1", - length); - } else { - if (0 == conc_connection_list[0].mac) - strlcat(cc_mode, " with MCC on mac0", - length); - else - strlcat(cc_mode, " with MCC on mac1", - length); - } + conc_connection_list[1].chan) + strlcat(cc_mode, + " with SCC for 1st two connections on mac ", + length); + else + strlcat(cc_mode, + " with MCC for 1st two connections on mac ", + length); + mac = conc_connection_list[0].mac; } if (conc_connection_list[0].mac == conc_connection_list[2].mac) { if (conc_connection_list[0].chan == - conc_connection_list[2].chan) { - if (0 == conc_connection_list[0].mac) - strlcat(cc_mode, " with SCC on mac0", - length); - else - strlcat(cc_mode, " with SCC on mac1", - length); - } else { - if (0 == conc_connection_list[0].mac) - strlcat(cc_mode, " with MCC on mac0", - length); - else - strlcat(cc_mode, " with MCC on mac1", - length); - } + conc_connection_list[2].chan) + strlcat(cc_mode, + " with SCC for 1st & 3rd connections on mac ", + length); + else + strlcat(cc_mode, + " with MCC for 1st & 3rd connections on mac ", + length); + mac = conc_connection_list[0].mac; } if (conc_connection_list[1].mac == conc_connection_list[2].mac) { if (conc_connection_list[1].chan == - conc_connection_list[2].chan) { - if (0 == conc_connection_list[1].mac) - strlcat(cc_mode, " with SCC on mac0", - length); - else - strlcat(cc_mode, " with SCC on mac1", - length); - } else { - if (0 == conc_connection_list[1].mac) - strlcat(cc_mode, " with MCC on mac0", - length); - else - strlcat(cc_mode, " with MCC on mac1", - length); - } + conc_connection_list[2].chan) + strlcat(cc_mode, + " with SCC for 2nd & 3rd connections on mac ", + length); + else + strlcat(cc_mode, + " with MCC for 2nd & 3rd connections on mac ", + length); + mac = conc_connection_list[1].mac; } + snprintf(buf, sizeof(buf), "%d ", mac); + strlcat(cc_mode, buf, length); } /** @@ -3836,6 +3823,13 @@ CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, wma_conn_table_entry->tx_streams, wma_conn_table_entry->rx_streams, wma_conn_table_entry->nss, vdev_id, true); + cds_info("Add at idx:%d vdev %d tx ss=%d rx ss=%d chainmask=%d mac=%d", + conn_index, vdev_id, + wma_conn_table_entry->tx_streams, + wma_conn_table_entry->rx_streams, + wma_conn_table_entry->chain_mask, + wma_conn_table_entry->mac_id); + return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From dfb8df95fd5d82ea1c563f7c7dd87c2fdbeafd0f Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Fri, 7 Aug 2015 19:03:17 -0700 Subject: qcacld-3.0: Unmap HTT Receive Buffers qcacld-2.0 to qcacld-3.0 propagation In the HTT hash de-init function, the network buffers (skb) need to be unmapped before they are freed. Change-Id: I879de6671d788f1ab99f7645ab424d56eafdbfd1 CRs-Fixed: 815265 --- core/dp/htt/htt_rx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index bd39345e9efb..c82f7a106517 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -126,6 +126,13 @@ void htt_rx_hash_deinit(struct htt_pdev_t *pdev) pdev->rx_ring. listnode_offset); if (hash_entry->netbuf) { +#ifdef DEBUG_DMA_DONE + cdf_nbuf_unmap(pdev->osdev, hash_entry->netbuf, + CDF_DMA_BIDIRECTIONAL); +#else + cdf_nbuf_unmap(pdev->osdev, hash_entry->netbuf, + CDF_DMA_FROM_DEVICE); +#endif cdf_nbuf_free(hash_entry->netbuf); hash_entry->paddr = 0; } -- cgit v1.2.3 From 0ed31b0b8f7d354945c03ec5a093504907ad6b1a Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Mon, 9 Nov 2015 15:06:16 -0800 Subject: qcacld-3.0: Replace panic with BUG_ON qcacld-2.0 to qcacld-3.0 propagation Register values are captured in the crash dump with BUG_ON. Change-Id: I33500aea0769879d63b2e684dc898ba0e3b0b5a2 CRs-Fixed: 813402 --- core/cdf/src/i_cdf_util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/cdf/src/i_cdf_util.h b/core/cdf/src/i_cdf_util.h index db2f11fa7e62..1ca6b1d6e421 100644 --- a/core/cdf/src/i_cdf_util.h +++ b/core/cdf/src/i_cdf_util.h @@ -95,7 +95,7 @@ static inline int __cdf_status_to_os_return(CDF_STATUS status) pr_err("Assertion failed! %s:%s %s:%d\n", \ # expr, __func__, __FILE__, __LINE__); \ dump_stack(); \ - panic("Take care of the assert first\n"); \ + BUG_ON(1); \ } \ } while (0) -- cgit v1.2.3 From faba5ff68bfb929ba35705f99a21f9e50fd1ba32 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 28 Sep 2015 15:01:49 +0530 Subject: qcacld-3.0: LLStats- Don't wait for peerstats if there is no peer qcacld-2.0 to qcacld-3.0 propagation Firmware indicates the number of peers connected as part of iface stats. If there are no peers connected, don't wait for the peerstats and indicate the stats to host. Change-Id: I32d04a5711adb5f924d120ee61064a178e753549 CRs-Fixed: 847743 --- core/hdd/src/wlan_hdd_stats.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 4d3b35c3fb21..e335fcaf84d6 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1226,6 +1226,14 @@ static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, linkLayerStatsResults->num_peers); spin_lock(&context->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 middleware 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(&context->context_lock); -- cgit v1.2.3 From 11e3438ce35948db0ae518bf437b5f6600b0792e Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Mon, 9 Nov 2015 17:12:25 -0800 Subject: Release 5.0.0.143 Release 5.0.0.143 Change-Id: I404e40080c263ce09755299a40ab3642d894cfcf CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 6a2fe346f0a9..7f5e734fe776 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 142 +#define QWLAN_VERSION_BUILD 143 -#define QWLAN_VERSIONSTR "5.0.0.142" +#define QWLAN_VERSIONSTR "5.0.0.143" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 7b85470fddc924ef18682ad75986ddda20bd2702 Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Tue, 10 Nov 2015 09:37:24 -0800 Subject: qcald-3.0: tweak sys params during high tx bandwidth case qcacld-2.0 to qcacld-3.0 propagation In hdd_cnss_request_bus_bandwidth function, the overall bus bandwidth and rx bandwidth requirements are being determined based on tx and rx packets. This change detects tx bandwidth required (high or low) and sends WLAN_SVC_WLAN_TP_TX_IND indication to cnss-daemon which can tweak system parameters depending upon TX bandwidth needed. Change-Id: I3eec2e3f95fa32b191d905209a38cb6d48837c33 CRs-Fixed: 918529 --- core/hdd/inc/wlan_hdd_cfg.h | 13 ++++++++ core/hdd/inc/wlan_hdd_main.h | 23 ++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 13 ++++++++ core/hdd/src/wlan_hdd_main.c | 54 ++++++++++++++++++++++++-------- core/utils/nlink/inc/wlan_nlink_common.h | 22 ++++++++++++- 5 files changed, 111 insertions(+), 14 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 4af4a4f258a6..82c99e896b6c 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2181,6 +2181,18 @@ typedef enum { #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 @@ -3172,6 +3184,7 @@ struct hdd_config { uint32_t busBandwidthComputeInterval; uint32_t tcpDelackThresholdHigh; uint32_t tcpDelackThresholdLow; + uint32_t tcp_tx_high_tput_thres; #endif /* MSM_PLATFORM */ /* FW debug log parameters */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3e4ad444ec1c..103082ca7d83 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -317,6 +317,26 @@ extern spinlock_t hdd_context_lock; #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_tx: # 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; @@ -324,6 +344,7 @@ struct hdd_tx_rx_histogram { 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 { @@ -1215,6 +1236,8 @@ struct hdd_context_s { spinlock_t bus_bw_lock; int cur_rx_level; uint64_t prev_rx; + int cur_tx_level; + uint64_t prev_tx; #endif /* VHT80 allowed */ bool isVHT80Allowed; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 4b13ed73b7f3..1ba3b80c8444 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -2973,6 +2973,14 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, + struct hdd_config, 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, @@ -4913,6 +4921,11 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [gTcpDelAckThresholdLow] Value = [%u] ", pHddCtx->config->tcpDelackThresholdLow); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] Value = [%u] ", + CFG_TCP_TX_HIGH_TPUT_THRESHOLD_NAME, + pHddCtx->config->tcp_tx_high_tput_thres); + #endif CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 85e62e6a441f..0c242fed3e57 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3942,14 +3942,17 @@ static CDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx) #ifdef MSM_PLATFORM void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, - uint64_t tx_packets, uint64_t rx_packets) + 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; + - uint64_t temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2; - enum cnss_bus_width_type next_rx_level = CNSS_BUS_WIDTH_NONE; if (total > hdd_ctx->config->busBandwidthHighThreshold) next_vote_level = CNSS_BUS_WIDTH_HIGH; else if (total > hdd_ctx->config->busBandwidthMediumThreshold) @@ -3959,8 +3962,8 @@ void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, else next_vote_level = CNSS_BUS_WIDTH_NONE; - hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level - = next_vote_level; + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level = + next_vote_level; if (hdd_ctx->cur_vote_level != next_vote_level) { hddLog(CDF_TRACE_LEVEL_DEBUG, @@ -3971,14 +3974,18 @@ void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, hdd_ctx->cur_vote_level = next_vote_level; cnss_request_bus_bandwidth(next_vote_level); } + + /* fine-tuning parameters for RX Flows */ + temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2; + hdd_ctx->prev_rx = rx_packets; if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) - next_rx_level = CNSS_BUS_WIDTH_HIGH; + next_rx_level = WLAN_SVC_TP_HIGH; else - next_rx_level = CNSS_BUS_WIDTH_LOW; + next_rx_level = WLAN_SVC_TP_LOW; - hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level - = next_rx_level; + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level = + next_rx_level; if (hdd_ctx->cur_rx_level != next_rx_level) { hddLog(CDF_TRACE_LEVEL_DEBUG, @@ -3990,6 +3997,25 @@ void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx, sizeof(next_rx_level)); } + /* fine-tuning parameters for TX Flows */ + temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2; + hdd_ctx->prev_tx = tx_packets; + if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres) + next_tx_level = WLAN_SVC_TP_HIGH; + else + next_tx_level = WLAN_SVC_TP_LOW; + + if (hdd_ctx->cur_tx_level != next_tx_level) { + hdd_debug("change TCP TX trigger level %d, average_tx: %llu", + next_tx_level, temp_tx); + hdd_ctx->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)); + } + + hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level = + next_tx_level; hdd_ctx->hdd_txrx_hist_idx++; hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; #endif @@ -4097,18 +4123,19 @@ void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx) hdd_ctx->config->tcpDelackThresholdLow); #endif - hddLog(CDF_TRACE_LEVEL_ERROR, "index, total_rx, interval_rx," - "total_tx, interval_tx, next_vote_level, next_rx_level"); + hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, - "%d: %llu, %llu, %llu, %llu, %d, %d", + "%d: %llu, %llu, %llu, %llu, %d, %d, %d", i, hdd_ctx->hdd_txrx_hist[i].total_rx, hdd_ctx->hdd_txrx_hist[i].interval_rx, hdd_ctx->hdd_txrx_hist[i].total_tx, hdd_ctx->hdd_txrx_hist[i].interval_tx, hdd_ctx->hdd_txrx_hist[i].next_vote_level, - hdd_ctx->hdd_txrx_hist[i].next_rx_level); + hdd_ctx->hdd_txrx_hist[i].next_rx_level, + hdd_ctx->hdd_txrx_hist[i].next_tx_level); } return; } @@ -6158,6 +6185,7 @@ void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len) 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: ani_hdr->length = len; nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len)); nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr); diff --git a/core/utils/nlink/inc/wlan_nlink_common.h b/core/utils/nlink/inc/wlan_nlink_common.h index 7dc7646832c7..399de6e2ccd5 100644 --- a/core/utils/nlink/inc/wlan_nlink_common.h +++ b/core/utils/nlink/inc/wlan_nlink_common.h @@ -79,7 +79,7 @@ #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_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 @@ -136,4 +136,24 @@ struct wlan_dfs_info { uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN]; }; +/** + * enum wlan_tp_level - indicates wlan 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 + * + * 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. + */ +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__ */ -- cgit v1.2.3 From f6aae8b0fcd0dd4d559e0730c0738b9cf676e57f Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Tue, 10 Nov 2015 11:32:49 -0800 Subject: qcacld-3.0: Increase default tx_queue_len for WLAN netdevice qcacld-2.0 to qcacld-3.0 propagation An increase in tx_queue_len of netdev to 3000 is giving us better TCP TX performance. Hence, increasing its value from its default (1000). This gives us about 30 - 40 Mbps of boost. Change-Id: I68f26ac0f4a040b0bbf10dd571dae8e5316f16b3 CRs-Fixed: 927673 --- core/hdd/inc/wlan_hdd_main.h | 4 ++++ core/hdd/src/wlan_hdd_hostapd.c | 1 + core/hdd/src/wlan_hdd_main.c | 1 + 3 files changed, 6 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 103082ca7d83..61a5f786ba22 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -75,6 +75,10 @@ #else #define NUM_TX_QUEUES 4 #endif + +/** Length of the TX queue for the netdev */ +#define HDD_NETDEV_TX_QUEUE_LEN (3000) + /** Bytes to reserve in the headroom */ #define LIBRA_HW_NEEDED_HEADROOM 128 /** Hdd Tx Time out value */ diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 437a5416430f..0138c20de28c 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -5935,6 +5935,7 @@ hdd_adapter_t *hdd_wlan_create_ap_dev(hdd_context_t *pHddCtx, pWlanHostapdDev->watchdog_timeo = HDD_TX_TIMEOUT; pWlanHostapdDev->mtu = HDD_DEFAULT_MTU; + pWlanHostapdDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN; cdf_mem_copy(pWlanHostapdDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr)); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0c242fed3e57..c0dbf04009be 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1812,6 +1812,7 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, pWlanDev->destructor = free_netdev; pWlanDev->ieee80211_ptr = &adapter->wdev; + pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN; adapter->wdev.wiphy = hdd_ctx->wiphy; adapter->wdev.netdev = pWlanDev; /* set pWlanDev's parent to underlying device */ -- cgit v1.2.3 From 65b4dcbffddb2cede04850180ae7e25d4c0641d9 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Thu, 5 Nov 2015 10:38:49 +0530 Subject: qcacld-3.0: Fix namespace collision in DFS module Fix namespace collision of the DFS module with userspace. Change-Id: I4ca582e9cb5713238cbae3060005375682fc8806 CRs-Fixed: 935515 --- core/sap/dfs/inc/dfs.h | 11 +++++----- core/sap/dfs/src/dfs.c | 4 ++-- core/sap/dfs/src/dfs_misc.c | 6 +++--- core/sap/dfs/src/dfs_nol.c | 4 ++-- core/sap/dfs/src/dfs_process_phyerr.c | 2 +- core/sap/dfs/src/dfs_process_radarevent.c | 5 +++-- core/wma/inc/wma.h | 6 +++--- core/wma/inc/wma_dfs_interface.h | 36 +++++++++++++++---------------- core/wma/inc/wma_internal.h | 11 +++++----- core/wma/src/wma_dfs_interface.c | 8 +++---- core/wma/src/wma_features.c | 33 +++++++++++++++------------- 11 files changed, 66 insertions(+), 60 deletions(-) diff --git a/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h index 18087207e094..64bc046fa04f 100644 --- a/core/sap/dfs/inc/dfs.h +++ b/core/sap/dfs/inc/dfs.h @@ -409,7 +409,7 @@ struct dfs_filtertype { }; struct dfs_state { - struct ieee80211_channel rs_chan; /* Channel info */ + struct dfs_ieee80211_channel rs_chan; /* Channel info */ uint8_t rs_chanindex; /* Channel index in radar structure */ uint32_t rs_numradarevents; /* Number of radar events */ @@ -728,10 +728,11 @@ int dfs_set_thresholds(struct ieee80211com *ic, const uint32_t threshtype, const uint32_t value); /* PHY error and radar event handling */ -int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan); +int dfs_process_radarevent(struct ath_dfs *dfs, + struct dfs_ieee80211_channel *chan); /* Non occupancy (NOL) handling prototypes */ -void dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, +void dfs_nol_addchan(struct ath_dfs *dfs, struct dfs_ieee80211_channel *chan, uint32_t dfs_nol_timeout); void dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int *nchan); @@ -803,7 +804,7 @@ int dfs_get_filter_threshold(struct ath_dfs *dfs, struct dfs_filter *rf, /* 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); + * struct dfs_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 @@ -819,6 +820,6 @@ void dfs_reset_ar(struct ath_dfs *dfs); * void dfs_reset_arq(struct ath_dfs *dfs); */ -struct ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic); +struct dfs_ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic); #endif /* _DFS_H_ */ diff --git a/core/sap/dfs/src/dfs.c b/core/sap/dfs/src/dfs.c index dfc46026a07b..2d0a81a3c55d 100644 --- a/core/sap/dfs/src/dfs.c +++ b/core/sap/dfs/src/dfs.c @@ -85,7 +85,7 @@ uint32_t dfs_debug_level = ATH_DEBUG_DFS; * both the primary and extension. */ static void -dfs_channel_mark_radar(struct ath_dfs *dfs, struct ieee80211_channel *chan) +dfs_channel_mark_radar(struct ath_dfs *dfs, struct dfs_ieee80211_channel *chan) { struct ieee80211_channel_list chan_info; int i; @@ -535,7 +535,7 @@ int dfs_radar_enable(struct ieee80211com *ic, /* uint32_t rfilt; */ struct ath_dfs *dfs; struct dfs_state *rs_pri, *rs_ext; - struct ieee80211_channel *chan = ic->ic_curchan, *ext_ch = NULL; + struct dfs_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; diff --git a/core/sap/dfs/src/dfs_misc.c b/core/sap/dfs/src/dfs_misc.c index e320e322b1af..c6b8834a8b6e 100644 --- a/core/sap/dfs/src/dfs_misc.c +++ b/core/sap/dfs/src/dfs_misc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2002-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -205,7 +205,7 @@ uint32_t dfs_round(int32_t val) return (ival + 1); } -struct ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic) +struct dfs_ieee80211_channel *ieee80211_get_extchan(struct ieee80211com *ic) { int chan_offset = 0; if (IEEE80211_IS_CHAN_HT40PLUS_CAPABLE(ic->ic_curchan)) { @@ -228,7 +228,7 @@ struct dfs_state *dfs_getchanstate(struct ath_dfs *dfs, uint8_t *index, { struct dfs_state *rs = NULL; int i; - struct ieee80211_channel *cmp_ch; + struct dfs_ieee80211_channel *cmp_ch; if (dfs == NULL) { printk("%s[%d]: sc_dfs is NULL\n", __func__, __LINE__); diff --git a/core/sap/dfs/src/dfs_nol.c b/core/sap/dfs/src/dfs_nol.c index 5a5ec795bc3f..278bc31bc452 100644 --- a/core/sap/dfs/src/dfs_nol.c +++ b/core/sap/dfs/src/dfs_nol.c @@ -149,7 +149,7 @@ void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) { #define TIME_IN_MS 1000 uint32_t nol_time_left_ms; - struct ieee80211_channel chan; + struct dfs_ieee80211_channel chan; int i; if (dfs == NULL) { @@ -177,7 +177,7 @@ void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) } void -dfs_nol_addchan(struct ath_dfs *dfs, struct ieee80211_channel *chan, +dfs_nol_addchan(struct ath_dfs *dfs, struct dfs_ieee80211_channel *chan, uint32_t dfs_nol_timeout) { #define TIME_IN_MS 1000 diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 8bf76f95bebf..38a49deb3766 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -474,7 +474,7 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, uint64_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_ieee80211_channel *chan = ic->ic_curchan; struct dfs_event *event; struct dfs_phy_err e; int empty; diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index a639d44d3d4a..c5a586c10341 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -112,7 +112,8 @@ static inline uint8_t dfs_process_pulse_dur(struct ath_dfs *dfs, uint8_t re_dur) * 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) +int dfs_process_radarevent(struct ath_dfs *dfs, + struct dfs_ieee80211_channel *chan) { /* commenting for now to validate radar indication msg to SAP */ /* #if 0 */ @@ -124,7 +125,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, struct ieee80211_channel *chan) int events_processed = 0; uint32_t tabledepth, index; uint64_t deltafull_ts = 0, this_ts, deltaT; - struct ieee80211_channel *thischan; + struct dfs_ieee80211_channel *thischan; struct dfs_pulseline *pl; static uint32_t test_ts = 0; static uint32_t diff_ts = 0; diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 9eec65bdadd8..d86c8f1d5d20 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1900,7 +1900,7 @@ A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr); int ol_if_dfs_attach(struct ieee80211com *ic, void *ptr, void *radar_info); uint64_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, +struct dfs_ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, int freq, uint32_t flags); int ol_if_dfs_enable(struct ieee80211com *ic, int *is_fastclk, void *pe); uint32_t ieee80211_ieee2mhz(uint32_t chan, uint32_t flags); @@ -1910,9 +1910,9 @@ int ol_if_dfs_get_mib_cycle_counts_pct(struct ieee80211com *ic, uint32_t *txf_pcnt); uint16_t ol_if_dfs_usenol(struct ieee80211com *ic); void ieee80211_mark_dfs(struct ieee80211com *ic, - struct ieee80211_channel *ichan); + struct dfs_ieee80211_channel *ichan); int wma_dfs_indicate_radar(struct ieee80211com *ic, - struct ieee80211_channel *ichan); + struct dfs_ieee80211_channel *ichan); uint16_t dfs_usenol(struct ieee80211com *ic); CDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_t vdev_id, diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 740e23a84caa..63d069bea3cf 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -49,8 +49,6 @@ #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 */ @@ -75,9 +73,9 @@ #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 DFS_IEEE80211_CHAN_ANY (-1) +#define DFS_IEEE80211_CHAN_ANYC \ + ((struct dfs_ieee80211_channel *) DFS_IEEE80211_CHAN_ANY) #define IEEE80211_IS_CHAN_11N_HT40MINUS(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) != 0) @@ -102,7 +100,7 @@ #define IEE80211_MAX_20M_SUB_CH 8 /** - * struct ieee80211_channel - channel info + * struct dfs_ieee80211_channel - channel info * @ic_freq: frequency in MHz * @ic_flags: channel flags * @ic_flagext: flags extension @@ -116,7 +114,7 @@ * @ic_vhtop_ch_freq_seg2: Channel Center frequency applicable * @ic_pri_freq_center_freq_mhz_separation: separation b/w pri and center freq */ -struct ieee80211_channel { +struct dfs_ieee80211_channel { uint32_t ic_freq; uint32_t ic_flags; uint8_t ic_flagext; @@ -138,7 +136,7 @@ struct ieee80211_channel { */ struct ieee80211_channel_list { int cl_nchans; - struct ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH]; + struct dfs_ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH]; }; /** @@ -157,8 +155,8 @@ struct ieee80211_dfs_state { os_timer_t nol_timer; os_timer_t cac_timer; int cureps; - const struct ieee80211_channel *lastchan; - struct ieee80211_channel *newchan; + const struct dfs_ieee80211_channel *lastchan; + struct dfs_ieee80211_channel *newchan; int cac_timeout_override; uint8_t enable : 1, cac_timer_running : 1, ignore_dfs : 1, ignore_cac : 1; }; @@ -180,13 +178,13 @@ typedef struct ieee80211com { void (*ic_get_ext_chan_info)(struct ieee80211com *ic, struct ieee80211_channel_list *chan); enum ieee80211_opmode ic_opmode; - struct ieee80211_channel *(*ic_find_channel)(struct ieee80211com *ic, - int freq, uint32_t flags); + struct dfs_ieee80211_channel *(*ic_find_channel) + (struct ieee80211com *ic, int freq, uint32_t flags); uint64_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]; + struct dfs_ieee80211_channel ic_channels[IEEE80211_CHAN_MAX + 1]; int ic_nchans; - struct ieee80211_channel *ic_curchan; + struct dfs_ieee80211_channel *ic_curchan; uint8_t ic_isdfsregdomain; int (*ic_get_dfsdomain)(struct ieee80211com *); uint16_t (*ic_dfs_usenol)(struct ieee80211com *ic); @@ -222,9 +220,9 @@ typedef struct ieee80211com { 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); + struct dfs_ieee80211_channel *chan); void (*ic_dfs_unmark_radar)(struct ieee80211com *ic, - struct ieee80211_channel *chan); + struct dfs_ieee80211_channel *chan); int (*ic_dfs_control)(struct ieee80211com *ic, u_int id, void *indata, uint32_t insize, void *outdata, uint32_t *outsize); @@ -244,10 +242,12 @@ typedef struct ieee80211com { * Return: freqency in MHz */ static INLINE u_int -ieee80211_chan2freq(struct ieee80211com *ic, const struct ieee80211_channel *c) +ieee80211_chan2freq(struct ieee80211com *ic, + const struct dfs_ieee80211_channel *c) { if (c == NULL) { return 0; } - return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_freq); + return (c == DFS_IEEE80211_CHAN_ANYC) ? + DFS_IEEE80211_CHAN_ANY : c->ic_freq; } diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 9e9ef25ba5f5..b6375a114add 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1062,11 +1062,12 @@ void wma_dfs_detach(struct ieee80211com *dfs_ic); void wma_dfs_configure(struct ieee80211com *ic); -struct ieee80211_channel *wma_dfs_configure_channel(struct ieee80211com *dfs_ic, - wmi_channel *chan, - WLAN_PHY_MODE chanmode, - struct wma_vdev_start_req - *req); +struct dfs_ieee80211_channel *wma_dfs_configure_channel( + struct ieee80211com *dfs_ic, + wmi_channel *chan, + WLAN_PHY_MODE chanmode, + struct wma_vdev_start_req + *req); void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id); #ifdef REMOVE_PKT_LOG diff --git a/core/wma/src/wma_dfs_interface.c b/core/wma/src/wma_dfs_interface.c index 8c0fcd4ccb2e..a9bc97b85711 100644 --- a/core/wma/src/wma_dfs_interface.c +++ b/core/wma/src/wma_dfs_interface.c @@ -104,12 +104,12 @@ int ol_if_dfs_disable(struct ieee80211com *ic) * This verifies that found channels have not been * excluded because of 11d. * - * Return: returns ieee80211_channel or NULL for error + * Return: returns dfs_ieee80211_channel or NULL for error */ -struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, +struct dfs_ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, int freq, uint32_t flags) { - struct ieee80211_channel *c; + struct dfs_ieee80211_channel *c; int i; flags &= IEEE80211_CHAN_ALLTURBO; @@ -238,7 +238,7 @@ uint16_t ol_if_dfs_usenol(struct ieee80211com *ic) * Return: none */ void -ieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan) +ieee80211_mark_dfs(struct ieee80211com *ic, struct dfs_ieee80211_channel *ichan) { int status; status = wma_dfs_indicate_radar(ic, ichan); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 9faaac67e454..d7f54aada7d5 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1694,7 +1694,7 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle, struct ieee80211com *ic; struct ath_dfs *dfs; struct dfs_event *event; - struct ieee80211_channel *chan; + struct dfs_ieee80211_channel *chan; int empty; int do_check_chirp = 0; int is_hw_chirp = 0; @@ -6752,13 +6752,14 @@ void wma_dfs_configure(struct ieee80211com *ic) * Also,configure the DFS radar filters for * matching the DFS phyerrors. * - * Return: ieee80211 channel / NULL for error + * Return: dfs_ieee80211_channel / NULL for error */ -struct ieee80211_channel *wma_dfs_configure_channel(struct ieee80211com *dfs_ic, - wmi_channel *chan, - WLAN_PHY_MODE chanmode, - struct wma_vdev_start_req - *req) +struct dfs_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__); @@ -6766,17 +6767,19 @@ struct ieee80211_channel *wma_dfs_configure_channel(struct ieee80211com *dfs_ic, } if (!dfs_ic->ic_curchan) { - dfs_ic->ic_curchan = (struct ieee80211_channel *)os_malloc(NULL, - sizeof(struct ieee80211_channel), - GFP_ATOMIC); + dfs_ic->ic_curchan = (struct dfs_ieee80211_channel *)os_malloc( + NULL, + sizeof(struct dfs_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)); + WMA_LOGE( + "%s: allocation of dfs_ic->ic_curchan failed %zu", + __func__, sizeof(struct dfs_ieee80211_channel)); return NULL; } } - OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct ieee80211_channel)); + OS_MEMZERO(dfs_ic->ic_curchan, sizeof(struct dfs_ieee80211_channel)); dfs_ic->ic_curchan->ic_ieee = req->chan; dfs_ic->ic_curchan->ic_freq = chan->mhz; @@ -6853,7 +6856,7 @@ void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region) * * Return: return number of channels */ -int wma_get_channels(struct ieee80211_channel *ichan, +int wma_get_channels(struct dfs_ieee80211_channel *ichan, struct wma_dfs_radar_channel_list *chan_list) { uint8_t center_chan = cds_freq_to_chan(ichan->ic_vhtop_ch_freq_seg1); @@ -6888,7 +6891,7 @@ int wma_get_channels(struct ieee80211_channel *ichan, * Return: 0 for success or error code */ int wma_dfs_indicate_radar(struct ieee80211com *ic, - struct ieee80211_channel *ichan) + struct dfs_ieee80211_channel *ichan) { tp_wma_handle wma; void *hdd_ctx; -- cgit v1.2.3 From 681d137dabd7162789a21262589da9dc943a062c Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Thu, 5 Nov 2015 10:42:48 +0530 Subject: qcacld-3.0: Move cds_get_bin.c to concurrency management files cds_get_bin.h and cds_get_bin.c were derived from qcacld-2.0 vos_get_bin.h and vos_get_bin.c. These files got their names since at one time they housed the wrappers used to retrieve binary files nv.bin, cfg.dat, and firmware. But over time the functionality to actually retrieve binary files (get_bin) has been removed, and almost all that is left is concurrency management functions. So, moving the .[ch] functionality to the right files. CRs-Fixed: 932777 Change-Id: I4a26c304cc6b6224d0839c365e4006fd32270961 --- Kbuild | 1 - core/bmi/src/ol_fw.c | 1 + core/cds/inc/cds_api.h | 1 - core/cds/inc/cds_concurrency.h | 16 ++++ core/cds/inc/cds_crypto.h | 1 - core/cds/inc/cds_get_bin.h | 75 ---------------- core/cds/src/cds_concurrency.c | 152 ++++++++++++++++++++++++++++++++ core/cds/src/cds_get_bin.c | 166 ----------------------------------- core/hdd/src/wlan_hdd_driver_ops.c | 1 + core/hdd/src/wlan_hdd_power.c | 1 + core/hif/src/ce/ce_bmi.c | 1 - core/hif/src/ce/ce_diag.c | 2 +- core/hif/src/ce/ce_main.c | 2 +- core/hif/src/ce/ce_service.c | 2 +- core/hif/src/hif_main.c | 3 +- core/hif/src/pcie/if_pci.c | 1 + core/htc/htc.c | 2 +- core/htc/htc_recv.c | 3 +- core/htc/htc_send.c | 1 - core/mac/src/pe/lim/lim_api.c | 1 + core/sap/src/sap_module.c | 1 + core/sme/src/csr/csr_neighbor_roam.c | 1 + core/utils/epping/src/epping_main.c | 1 + core/wma/src/wma_main.c | 1 + core/wma/src/wma_mgmt.c | 1 + core/wma/src/wma_utils.c | 1 + 26 files changed, 186 insertions(+), 253 deletions(-) delete mode 100644 core/cds/inc/cds_get_bin.h delete mode 100644 core/cds/src/cds_get_bin.c diff --git a/Kbuild b/Kbuild index 0ad05d87faa4..2f9098131c6b 100644 --- a/Kbuild +++ b/Kbuild @@ -604,7 +604,6 @@ CDS_INC := -I$(WLAN_ROOT)/$(CDS_INC_DIR) \ -I$(WLAN_ROOT)/$(CDS_SRC_DIR) CDS_OBJS := $(CDS_SRC_DIR)/cds_api.o \ - $(CDS_SRC_DIR)/cds_get_bin.o \ $(CDS_SRC_DIR)/cds_reg_service.o \ $(CDS_SRC_DIR)/cds_mq.o \ $(CDS_SRC_DIR)/cds_packet.o \ diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c index 94488b922986..1607010d7dad 100644 --- a/core/bmi/src/ol_fw.c +++ b/core/bmi/src/ol_fw.c @@ -42,6 +42,7 @@ #include "i_bmi.h" #include "qwlan_version.h" +#include "cds_concurrency.h" #ifdef FEATURE_SECURE_FIRMWARE static struct hash_fw fw_hash; diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 01618a578322..c88068f0e61f 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index ff9f30b0940e..8d88e7f8b9da 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -770,4 +770,20 @@ bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE *old_mode, enum cds_con_mode *new_mode); CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint8_t *channel); + +tCDF_CON_MODE cds_get_conparam(void); +bool cds_concurrent_open_sessions_running(void); +bool cds_max_concurrent_connections_reached(void); +void cds_clear_concurrent_session_count(void); +bool cds_is_multiple_active_sta_sessions(void); +bool cds_is_sta_active_connection_exists(void); + +#ifdef WLAN_FEATURE_MBSSID +bool cds_concurrent_beaconing_sessions_running(void); +#else +static inline bool cds_concurrent_beaconing_sessions_running(void) +{ + return true; +} +#endif #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/inc/cds_crypto.h b/core/cds/inc/cds_crypto.h index 7df3b7dd7076..25fbfdfd7bc7 100644 --- a/core/cds/inc/cds_crypto.h +++ b/core/cds/inc/cds_crypto.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/core/cds/inc/cds_get_bin.h b/core/cds/inc/cds_get_bin.h deleted file mode 100644 index a561e955148c..000000000000 --- a/core/cds/inc/cds_get_bin.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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( __CDS_GETBIN_H ) -#define __CDS_GETBIN_H - -/**========================================================================= - - \file cds_getBin.h - - \brief Connectivity driver services (CDS) 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. - - ========================================================================*/ - -/*-------------------------------------------------------------------------- - Include Files - ------------------------------------------------------------------------*/ -#include -#include - -/*-------------------------------------------------------------------------- - Preprocessor definitions and constants - ------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------- - Type declarations - ------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------- - Function declarations and documenation - ------------------------------------------------------------------------*/ - -/**---------------------------------------------------------------------------- - \brief cds_get_conparam()- function to read the insmod parameters - -----------------------------------------------------------------------------*/ -tCDF_CON_MODE cds_get_conparam(void); -bool cds_concurrent_open_sessions_running(void); -bool cds_max_concurrent_connections_reached(void); -void cds_clear_concurrent_session_count(void); -bool cds_is_multiple_active_sta_sessions(void); -bool cds_is_sta_active_connection_exists(void); - -#ifdef WLAN_FEATURE_MBSSID -bool cds_concurrent_beaconing_sessions_running(void); -#endif -#endif /* !defined __CDS_GETBIN_H */ diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 48a99f33706b..21d7dd544a93 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -7234,3 +7234,155 @@ enum cds_con_mode cds_convert_device_mode_to_hdd_type( } return mode; } + +/** + * cds_get_conparam() - Get the connection mode parameters + * + * Return the connection mode parameter set by insmod or set during statically + * linked driver + * + * Return: tCDF_CON_MODE + */ +tCDF_CON_MODE cds_get_conparam(void) +{ + tCDF_CON_MODE con_mode; + con_mode = hdd_get_conparam(); + return con_mode; +} + +/** + * cds_concurrent_open_sessions_running() - Checks for concurrent open session + * + * Checks if more than one open session is running for all the allowed modes + * in the driver + * + * Return: True if more than one open session exists, False otherwise + */ +bool cds_concurrent_open_sessions_running(void) +{ + uint8_t i = 0; + uint8_t j = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) + j += pHddCtx->no_of_open_sessions[i]; + } + + return j > 1; +} + +#ifdef WLAN_FEATURE_MBSSID +/** + * cds_concurrent_beaconing_sessions_running() - Checks for concurrent beaconing + * entities + * + * Checks if multiple beaconing sessions are running i.e., if SAP or GO or IBSS + * are beaconing together + * + * Return: True if multiple entities are beaconing together, False otherwise + */ +bool cds_concurrent_beaconing_sessions_running(void) +{ + uint8_t i = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + i = pHddCtx->no_of_open_sessions[CDF_SAP_MODE] + + pHddCtx->no_of_open_sessions[CDF_P2P_GO_MODE] + + pHddCtx->no_of_open_sessions[CDF_IBSS_MODE]; + } + return i > 1; +} +#endif + +/** + * cds_max_concurrent_connections_reached() - Check if max conccurrency is + * reached + * + * Checks for presence of concurrency where more than one connection exists + * + * Return: True if the max concurrency is reached, False otherwise + * + * 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 + * + */ +bool cds_max_concurrent_connections_reached(void) +{ + uint8_t i = 0, j = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) + j += pHddCtx->no_of_active_sessions[i]; + return j > + (pHddCtx->config-> + gMaxConcurrentActiveSessions - 1); + } + + return false; +} + +/** + * cds_clear_concurrent_session_count() - Clear active session count + * + * Clears the active session count for all modes + * + * Return: None + */ +void cds_clear_concurrent_session_count(void) +{ + uint8_t i = 0; + hdd_context_t *pHddCtx; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) { + for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) + pHddCtx->no_of_active_sessions[i] = 0; + } +} + +/** + * cds_is_multiple_active_sta_sessions() - Check for multiple STA connections + * + * Checks if multiple active STA connection are in the driver + * + * Return: True if multiple STA sessions are present, False otherwise + * + */ +bool cds_is_multiple_active_sta_sessions(void) +{ + hdd_context_t *pHddCtx; + uint8_t j = 0; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) + j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; + + return j > 1; +} + +/** + * cds_is_sta_active_connection_exists() - Check if a STA connection is active + * + * Checks if there is atleast one active STA connection in the driver + * + * Return: True if an active STA session is present, False otherwise + */ +bool cds_is_sta_active_connection_exists(void) +{ + hdd_context_t *pHddCtx; + uint8_t j = 0; + + pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); + if (NULL != pHddCtx) + j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; + + return j ? true : false; +} diff --git a/core/cds/src/cds_get_bin.c b/core/cds/src/cds_get_bin.c deleted file mode 100644 index ac87dd5db866..000000000000 --- a/core/cds/src/cds_get_bin.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include -#include - -tCDF_CON_MODE cds_get_conparam(void) -{ - tCDF_CON_MODE con_mode; - con_mode = hdd_get_conparam(); - return con_mode; -} - -bool cds_concurrent_open_sessions_running(void) -{ - uint8_t i = 0; - uint8_t j = 0; - hdd_context_t *pHddCtx; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) { - for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) { - j += pHddCtx->no_of_open_sessions[i]; - } - } - - return j > 1; -} - -#ifdef WLAN_FEATURE_MBSSID -bool cds_concurrent_beaconing_sessions_running(void) -{ - uint8_t i = 0; - hdd_context_t *pHddCtx; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) { - i = pHddCtx->no_of_open_sessions[CDF_SAP_MODE] + - pHddCtx->no_of_open_sessions[CDF_P2P_GO_MODE] + - pHddCtx->no_of_open_sessions[CDF_IBSS_MODE]; - } - return i > 1; -} -#endif - -/**--------------------------------------------------------------------------- -* -* \brief cds_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 - true or false -* -* --------------------------------------------------------------------------*/ -bool cds_max_concurrent_connections_reached(void) -{ - uint8_t i = 0, j = 0; - hdd_context_t *pHddCtx; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) { - for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) - j += pHddCtx->no_of_active_sessions[i]; - return j > - (pHddCtx->config-> - gMaxConcurrentActiveSessions - 1); - } - - return false; -} - -void cds_clear_concurrent_session_count(void) -{ - uint8_t i = 0; - hdd_context_t *pHddCtx; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) { - for (i = 0; i < CDF_MAX_NO_OF_MODE; i++) - pHddCtx->no_of_active_sessions[i] = 0; - } -} - -/**--------------------------------------------------------------------------- -* -* \brief cds_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 -* -* --------------------------------------------------------------------------*/ -bool cds_is_multiple_active_sta_sessions(void) -{ - hdd_context_t *pHddCtx; - uint8_t j = 0; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) - j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; - - return j > 1; -} - -/**--------------------------------------------------------------------------- -* -* \brief cds_is_sta_active_connection_exists() -* -* This function checks for the presence of active sta connection -* and it returns true if exists. -* -* \param - None -* -* \return - true or false -* -* --------------------------------------------------------------------------*/ -bool cds_is_sta_active_connection_exists(void) -{ - hdd_context_t *pHddCtx; - uint8_t j = 0; - - pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL != pHddCtx) - j = pHddCtx->no_of_active_sessions[CDF_STA_MODE]; - - return j ? true : false; -} diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index ff39296ee733..49432f6ab882 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -46,6 +46,7 @@ #include "wlan_logging_sock_svc.h" #include "wma_api.h" #include "wlan_hdd_napi.h" +#include "cds_concurrency.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index d227d6c28273..5433c368961e 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -68,6 +68,7 @@ #include #include "hif.h" #include "sme_power_save_api.h" +#include "cds_concurrency.h" /* Preprocessor definitions and constants */ #define HDD_SSR_BRING_UP_TIME 30000 diff --git a/core/hif/src/ce/ce_bmi.c b/core/hif/src/ce/ce_bmi.c index b2d541d2d2f4..edf1d46d059d 100644 --- a/core/hif/src/ce/ce_bmi.c +++ b/core/hif/src/ce/ce_bmi.c @@ -49,7 +49,6 @@ #else #include "cnss_stub.h" #endif -#include #include "epping_main.h" #include "hif_debug.h" diff --git a/core/hif/src/ce/ce_diag.c b/core/hif/src/ce/ce_diag.c index c078f218b01a..f524702503cc 100644 --- a/core/hif/src/ce/ce_diag.c +++ b/core/hif/src/ce/ce_diag.c @@ -47,9 +47,9 @@ #ifdef CONFIG_CNSS #include #endif -#include #include "hif_debug.h" #include "epping_main.h" +#include "cds_concurrency.h" void hif_dump_target_memory(struct ol_softc *scn, void *ramdump_base, uint32_t address, uint32_t size) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 8cf00f13e9bb..452fcc6b2782 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -49,7 +49,6 @@ #ifdef CONFIG_CNSS #include #endif -#include #include "epping_main.h" #include "hif_debug.h" #include "ce_internal.h" @@ -62,6 +61,7 @@ #include #endif #include "qwlan_version.h" +#include "cds_concurrency.h" #define CE_POLL_TIMEOUT 10 /* ms */ diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index d27ca6b1a848..a898d0b63104 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -37,10 +37,10 @@ #include "ce_reg.h" #include "cdf_lock.h" #include "regtable.h" -#include #include "epping_main.h" #include "hif_main.h" #include "hif_debug.h" +#include "cds_concurrency.h" #ifdef IPA_OFFLOAD #ifdef QCA_WIFI_3_0 diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index bbfde23c236b..7dbc3698fea4 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -51,7 +51,6 @@ #ifdef CONFIG_CNSS #include #endif -#include #include "epping_main.h" #include "hif_debug.h" #include "mp_dev.h" @@ -65,6 +64,8 @@ #include "pktlog_ac.h" #endif +#include "cds_concurrency.h" + #define AGC_DUMP 1 #define CHANINFO_DUMP 2 #define BB_WATCHDOG_DUMP 3 diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 6efb418ee8d9..91cff6a8835f 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -68,6 +68,7 @@ #include "if_pci_internal.h" #include "icnss_stub.h" #include "ce_tasklet.h" +#include "cds_concurrency.h" /* Maximum ms timeout for host to wake up target */ #define PCIE_WAKE_TIMEOUT 1000 diff --git a/core/htc/htc.c b/core/htc/htc.c index bbabee1f2575..607e825e0b31 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -31,9 +31,9 @@ #include /* cdf_nbuf_t */ #include /* cdf_print */ #include -#include #include "epping_main.h" #include "hif_io32.h" +#include "cds_concurrency.h" #ifdef DEBUG static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = { diff --git a/core/htc/htc_recv.c b/core/htc/htc_recv.c index dd8719e2649e..3418aac136fe 100644 --- a/core/htc/htc_recv.c +++ b/core/htc/htc_recv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -29,7 +29,6 @@ #include "htc_internal.h" #include "cds_api.h" #include /* cdf_nbuf_t */ -#include #include "epping_main.h" #ifdef DEBUG diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index e011538de1a9..48d55709c1f3 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -29,7 +29,6 @@ #include "htc_internal.h" #include /* cdf_nbuf_t */ #include /* cdf_mem_malloc */ -#include #include "epping_main.h" /* #define USB_HIF_SINGLE_PIPE_DATA_SCHED */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 4c0efc8d6080..761bc7e5cf2c 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -72,6 +72,7 @@ #include "cds_packet.h" #include "cds_utils.h" #include "sys_startup.h" +#include "cds_concurrency.h" static void __lim_init_scan_vars(tpAniSirGlobal pMac) { diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 5b0e28b4e072..8969d4b94116 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -53,6 +53,7 @@ #include "sme_inside.h" #include "cds_ieee80211_common_i.h" #include "cds_regdomain_common.h" +#include "cds_concurrency.h" /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 5aef6cf3e0f8..7e36d27a1ae8 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -47,6 +47,7 @@ #include "sme_api.h" #include "csr_neighbor_roam.h" #include "mac_trace.h" +#include "cds_concurrency.h" #define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c index dd0c463e1793..c222c557d938 100644 --- a/core/utils/epping/src/epping_main.c +++ b/core/utils/epping/src/epping_main.c @@ -53,6 +53,7 @@ #include "hif.h" #include "epping_main.h" #include "epping_internal.h" +#include "cds_concurrency.h" #ifdef TIMER_MANAGER #define TIMER_MANAGER_STR " +TIMER_MANAGER" diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 0676686d68e0..86868bf3885d 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -76,6 +76,7 @@ #include "wma_internal.h" #include "wma_ocb.h" +#include "cds_concurrency.h" #define WMA_LOG_COMPLETION_TIMER 10000 /* 10 seconds */ #define WMA_SERVICE_READY_EXT_TIMEOUT 2000 /* 2 seconds */ diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 8544fa46e5c6..4ba24036b7a5 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -68,6 +68,7 @@ #include "ol_fw.h" #include "dfs.h" #include "wma_internal.h" +#include "cds_concurrency.h" /** * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 1411a3511e4e..b2f1fa5b7842 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -68,6 +68,7 @@ #include "dfs.h" #include "wma_internal.h" +#include "cds_concurrency.h" /* MCS Based rate table */ /* HT MCS parameters with Nss = 1 */ -- cgit v1.2.3 From d4ddf7866a7c8dbdfaeaca5b48632cccdeb4c826 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Mon, 16 Nov 2015 15:38:53 +0530 Subject: qcacld-3.0: Add CDS APIs to manipulate connection update event Add CDS connection manager APIs to manipulate the connection update event. These APIs can be used to initialize, reset, set and wait for connection update event. Change-Id: I5689711d4bdc0e39b2456573158943ebda9cbc2a CRs-Fixed: 939026 --- core/cds/inc/cds_concurrency.h | 6 ++ core/cds/src/cds_concurrency.c | 145 ++++++++++++++++++++++++++++++++------- core/hdd/src/wlan_hdd_cfg80211.c | 29 ++------ core/hdd/src/wlan_hdd_hostapd.c | 15 +--- 4 files changed, 131 insertions(+), 64 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 8d88e7f8b9da..09a4abbfcf72 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -41,6 +41,7 @@ #define MAX_NUMBER_OF_CONC_CONNECTIONS 3 #define MAX_NUM_CHAN 128 #define DBS_OPPORTUNISTIC_TIME 10 +#define CONNECTION_UPDATE_TIMEOUT 500 /** * enum cds_chain_mode - Chain Mask tx & rx combination. @@ -786,4 +787,9 @@ static inline bool cds_concurrent_beaconing_sessions_running(void) return true; } #endif + +CDF_STATUS cdf_wait_for_connection_update(void); +CDF_STATUS cdf_reset_connection_update(void); +CDF_STATUS cdf_set_connection_update(void); +CDF_STATUS cdf_init_connection_update(void); #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 21d7dd544a93..c3fc11dc1a19 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2269,13 +2269,6 @@ static void cds_soc_set_hw_mode_cb(uint32_t status, CDF_STATUS ret; struct sir_hw_mode_params hw_mode; uint32_t i; - p_cds_contextType cds_context; - - cds_context = cds_get_global_context(); - if (!cds_context) { - cds_err("Invalid CDS context"); - return; - } if (status != SET_HW_MODE_STATUS_OK) { cds_err("Set HW mode failed with status %d", status); @@ -2312,7 +2305,7 @@ static void cds_soc_set_hw_mode_cb(uint32_t status, vdev_mac_map, hw_mode); - ret = cdf_event_set(&cds_context->connection_update_done_evt); + ret = cdf_set_connection_update(); if (!CDF_IS_STATUS_SUCCESS(ret)) cds_err("ERROR: set connection_update_done event failed"); @@ -3641,16 +3634,9 @@ void cds_dbs_opportunistic_timer_handler(void *data) CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) { CDF_STATUS status; - p_cds_contextType p_cds_context; cds_debug("Initializing the policy manager"); - p_cds_context = cds_get_global_context(); - if (!p_cds_context) { - cds_err("Invalid CDS context"); - return CDF_STATUS_E_FAILURE; - } - /* init conc_connection_list */ cdf_mem_zero(conc_connection_list, sizeof(conc_connection_list)); @@ -3672,7 +3658,7 @@ CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) return status; } - status = cdf_event_init(&p_cds_context->connection_update_done_evt); + status = cdf_init_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) { cds_err("connection_update_done_evt init failed"); return status; @@ -6261,20 +6247,13 @@ bool cds_handle_conc_multiport(uint8_t session_id, uint8_t channel) { CDF_STATUS status; - p_cds_contextType cds_context; - - cds_context = cds_get_global_context(); - if (!cds_context) { - cds_err("Invalid CDS context"); - return false; - } if (!cds_check_for_session_conc(session_id, channel)) { cds_err("Conc not allowed for the session %d", session_id); return false; } - status = cdf_event_reset(&cds_context->connection_update_done_evt); + status = cdf_reset_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) cds_err("clearing event failed"); @@ -6290,8 +6269,7 @@ bool cds_handle_conc_multiport(uint8_t session_id, * will return success only in case if DBS update is required. */ if (CDF_STATUS_SUCCESS == status) { - status = cdf_wait_single_event( - &cds_context->connection_update_done_evt, 500); + status = cdf_wait_for_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) { cds_err("wait for event failed"); return false; @@ -7386,3 +7364,118 @@ bool cds_is_sta_active_connection_exists(void) return j ? true : false; } + +/** + * cdf_wait_for_connection_update() - Wait for hw mode command to get processed + * + * Waits for CONNECTION_UPDATE_TIMEOUT duration until the set hw mode + * response sets the event connection_update_done_evt + * + * Return: CDF_STATUS + */ +CDF_STATUS cdf_wait_for_connection_update(void) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return CDF_STATUS_E_FAILURE; + } + + status = cdf_wait_single_event( + &cds_context->connection_update_done_evt, + CONNECTION_UPDATE_TIMEOUT); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("wait for event failed"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_reset_connection_update() - Reset connection update event + * + * Resets the concurrent connection update event + * + * Return: CDF_STATUS + */ +CDF_STATUS cdf_reset_connection_update(void) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return CDF_STATUS_E_FAILURE; + } + + status = cdf_event_reset(&cds_context->connection_update_done_evt); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("clear event failed"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_set_connection_update() - Set connection update event + * + * Sets the concurrent connection update event + * + * Return: CDF_STATUS + */ +CDF_STATUS cdf_set_connection_update(void) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return CDF_STATUS_E_FAILURE; + } + + status = cdf_event_set(&cds_context->connection_update_done_evt); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("set event failed"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_init_connection_update() - Initialize connection update event + * + * Initializes the concurrent connection update event + * + * Return: CDF_STATUS + */ +CDF_STATUS cdf_init_connection_update(void) +{ + CDF_STATUS status; + p_cds_contextType cds_context; + + cds_context = cds_get_global_context(); + if (!cds_context) { + cds_err("Invalid CDS context"); + return CDF_STATUS_E_FAILURE; + } + + status = cdf_event_init(&cds_context->connection_update_done_evt); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("init event failed"); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e29a422fe57f..d6a5143e8fc3 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -136,7 +136,6 @@ #endif #define HDD_CHANNEL_14 14 -#define CONNECTION_UPDATE_TIMEOUT 500 static const u32 hdd_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, @@ -4133,18 +4132,11 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, enum cds_con_mode intf_mode; struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1]; uint32_t channel_hint; - p_cds_contextType p_cds_context; ret = wlan_hdd_validate_context(hdd_ctx); if (ret) return ret; - p_cds_context = cds_get_global_context(); - if (!p_cds_context) { - hdd_err("Invalid CDS context"); - return -EINVAL; - } - if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX, data, data_len, NULL)) { hdd_err("Invalid ATTR"); @@ -4180,8 +4172,7 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, } if (hdd_ctx->config->policy_manager_enabled) { - ret = cdf_event_reset( - &p_cds_context->connection_update_done_evt); + ret = cdf_reset_connection_update(); if (!CDF_IS_STATUS_SUCCESS(ret)) hdd_err("clearing event failed"); @@ -4201,9 +4192,7 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, * For any other return value it should be a pass * through */ - ret = cdf_wait_single_event( - &p_cds_context->connection_update_done_evt, - CONNECTION_UPDATE_TIMEOUT); + ret = cdf_wait_for_connection_update(); if (!CDF_IS_STATUS_SUCCESS(ret)) { hdd_err("ERROR: cdf wait for event failed!!"); return -EINVAL; @@ -8745,16 +8734,9 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); struct cdf_mac_addr bssid; u8 channelNum = 0; - p_cds_contextType p_cds_context; ENTER(); - p_cds_context = cds_get_global_context(); - if (!p_cds_context) { - hdd_err("Invalid CDS context"); - return -EINVAL; - } - if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -8823,8 +8805,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, return -ECONNREFUSED; } if (pHddCtx->config->policy_manager_enabled) { - status = cdf_event_reset( - &p_cds_context->connection_update_done_evt); + status = cdf_reset_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); @@ -8837,9 +8818,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, } if (CDF_STATUS_SUCCESS == status) { - status = cdf_wait_single_event( - &p_cds_context->connection_update_done_evt, - CONNECTION_UPDATE_TIMEOUT); + status = cdf_wait_for_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) { hdd_err("ERROR: cdf wait for event failed!!"); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 0138c20de28c..c5b595569446 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -94,7 +94,6 @@ #define SAP_24GHZ_CH_COUNT (14) #define ACS_SCAN_EXPIRY_TIMEOUT_S 4 -#define CONNECTION_UPDATE_TIMEOUT 500 #define DUMP_DP_TRACE 0 @@ -8184,16 +8183,9 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, tSirWifiChannelWidth channel_width; int status; uint8_t channel; - p_cds_contextType p_cds_context; ENTER(); - p_cds_context = cds_get_global_context(); - if (!p_cds_context) { - hdd_err("Invalid CDS context"); - return -EINVAL; - } - if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -8237,8 +8229,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, return -EINVAL; } if (pHddCtx->config->policy_manager_enabled) { - status = cdf_event_reset( - &p_cds_context->connection_update_done_evt); + status = cdf_reset_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) hdd_err("ERR: clear event failed"); @@ -8251,9 +8242,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, } if (CDF_STATUS_SUCCESS == status) { - status = cdf_wait_single_event( - &p_cds_context->connection_update_done_evt, - CONNECTION_UPDATE_TIMEOUT); + status = cdf_wait_for_connection_update(); if (!CDF_IS_STATUS_SUCCESS(status)) { hdd_err("ERROR: cdf wait for event failed!!"); return -EINVAL; -- cgit v1.2.3 From 68f1b8f299c466466735dd08d6884941f52c5f21 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Mon, 16 Nov 2015 16:28:30 +0530 Subject: qcacld-3.0: Avoid waiting for SME messages while holding SME global lock Avoid waiting for SME response messages while holding the SME global lock. Currently a wait for 500ms happens in cds_handle_conc_multiport after the holding the SME global lock. Because of this, the set hw mode response posted by LIM is not processed by SME as SME would be waiting for the lock. Change-Id: Ib7890cb7124f5879316f46b1bf9f0ad3fb225665 CRs-Fixed: 939026 --- core/cds/inc/cds_concurrency.h | 2 +- core/cds/src/cds_concurrency.c | 22 ++++++--------------- core/sme/inc/csr_internal.h | 2 ++ core/sme/src/csr/csr_api_roam.c | 14 +++++++++++--- core/sme/src/csr/csr_util.c | 43 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 09a4abbfcf72..261b97460d3d 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -604,7 +604,7 @@ static inline bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, tCsrRoamProfile * roam_profile); bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel); -bool cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); +CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); #ifdef FEATURE_WLAN_FORCE_SAP_SCC void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result); diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index c3fc11dc1a19..a7ef23f9fc88 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -6241,16 +6241,16 @@ bool cds_check_for_session_conc(uint8_t session_id, * This routine will handle STA side concurrency when policy manager * is enabled. * - * Return: true or false + * Return: CDF_STATUS */ -bool cds_handle_conc_multiport(uint8_t session_id, +CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, uint8_t channel) { CDF_STATUS status; if (!cds_check_for_session_conc(session_id, channel)) { cds_err("Conc not allowed for the session %d", session_id); - return false; + return CDF_STATUS_E_FAILURE; } status = cdf_reset_connection_update(); @@ -6262,20 +6262,10 @@ bool cds_handle_conc_multiport(uint8_t session_id, CDS_UPDATE_REASON_NORMAL_STA); if (CDF_STATUS_E_FAILURE == status) { cds_err("connections update failed"); - return false; - } - /* - * wait only if status is successful. connection update API - * will return success only in case if DBS update is required. - */ - if (CDF_STATUS_SUCCESS == status) { - status = cdf_wait_for_connection_update(); - if (!CDF_IS_STATUS_SUCCESS(status)) { - cds_err("wait for event failed"); - return false; - } + return status; } - return true; + + return status; } #ifdef FEATURE_WLAN_FORCE_SAP_SCC diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index f4def8f0e579..a653df29f9d7 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -1409,4 +1409,6 @@ CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal pMac, tSirBssDescription *pSirBssDescription, uint32_t scan_id, uint32_t flags); +bool csr_wait_for_connection_update(tpAniSirGlobal mac, + bool do_release_reacquire_lock); #endif diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 677b88aa967d..7a12c66dced2 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7250,9 +7250,17 @@ CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, (pScanFilter->csrPersona == CDF_P2P_CLIENT_MODE))) { csr_get_bssdescr_from_scan_handle(hBSSList, &first_ap_profile); - if (!cds_handle_conc_multiport(sessionId, - first_ap_profile.channelId)) { - sms_log(pMac, LOG1, FL("conc multiport error")); + status = cds_handle_conc_multiport(sessionId, + first_ap_profile.channelId); + if ((CDF_IS_STATUS_SUCCESS(status)) && + (!csr_wait_for_connection_update(pMac, true))) { + sms_log(pMac, LOG1, + FL("conn update error")); + csr_scan_result_purge(pMac, hBSSList); + fCallCallback = true; + goto error; + } else if (status == CDF_STATUS_E_FAILURE) { + sms_log(pMac, LOG1, FL("conn update error")); csr_scan_result_purge(pMac, hBSSList); fCallCallback = true; goto error; diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index eea8cbd2fb27..59d7662ef06a 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -41,6 +41,7 @@ #include "sme_qos_internal.h" #include "wma_types.h" #include "cds_utils.h" +#include "cds_concurrency.h" uint8_t csr_wpa_oui[][CSR_WPA_OUI_SIZE] = { @@ -5624,3 +5625,45 @@ void csr_diag_event_report(tpAniSirGlobal pmac, uint16_t event_type, return; } #endif + +/** + * csr_wait_for_connection_update() - Wait for hw mode update + * @mac: Pointer to the MAC context + * @do_release_reacquire_lock: Indicates whether release and + * re-acquisition of SME global lock is required. + * + * Waits for CONNECTION_UPDATE_TIMEOUT time so that the + * hw mode update can get processed. + * + * Return: True if the wait was successful, false otherwise + */ +bool csr_wait_for_connection_update(tpAniSirGlobal mac, + bool do_release_reacquire_lock) +{ + CDF_STATUS status, ret; + + if (do_release_reacquire_lock == true) { + ret = sme_release_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + cds_err("lock release fail %d", ret); + return false; + } + } + + status = cdf_wait_for_connection_update(); + + if (do_release_reacquire_lock == true) { + ret = sme_acquire_global_lock(&mac->sme); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + cds_err("lock acquire fail %d", ret); + return false; + } + } + + if (!CDF_IS_STATUS_SUCCESS(status)) { + cds_err("wait for event failed"); + return false; + } + + return true; +} -- cgit v1.2.3 From 0a763f89ca81fcbff38b6277ddbdc572af1b5683 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Fri, 13 Nov 2015 12:50:04 +0530 Subject: qcacld-3.0: Fix misspelled entry in the enum wifi_logging_ring_id This is qcacld-2.0 to qcacld-3.0 propagation Fix the misspelled entry RIND_ID_DRIVER_DEBUG to RING_ID_DRIVER_DEBUG in the enum wifi_logging_ring_id CRs-Fixed: 938286 Change-Id: I0d33128c6d11ecc9ff3d403931bfd6bfdbbb2b4a --- core/cds/src/cds_api.c | 4 ++-- core/mac/inc/ani_global.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index ffcb5edb7513..b5af587fd75e 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1807,7 +1807,7 @@ void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level) } else if (ring_id == RING_ID_PER_PACKET_STATS) { p_cds_context->packet_stats_log_level = log_val; return; - } else if (ring_id == RIND_ID_DRIVER_DEBUG) { + } else if (ring_id == RING_ID_DRIVER_DEBUG) { p_cds_context->driver_debug_log_level = log_val; return; } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { @@ -1841,7 +1841,7 @@ enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id) return p_cds_context->connectivity_log_level; else if (ring_id == RING_ID_PER_PACKET_STATS) return p_cds_context->packet_stats_log_level; - else if (ring_id == RIND_ID_DRIVER_DEBUG) + else if (ring_id == RING_ID_DRIVER_DEBUG) return p_cds_context->driver_debug_log_level; else if (ring_id == RING_ID_FIRMWARE_DEBUG) return p_cds_context->fw_debug_log_level; diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index f3bee2ad088e..e4e7bbdefcdc 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -232,7 +232,7 @@ enum wifi_driver_log_level { * @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_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 @@ -241,7 +241,7 @@ enum wifi_logging_ring_id { RING_ID_WAKELOCK, RING_ID_CONNECTIVITY, RING_ID_PER_PACKET_STATS, - RIND_ID_DRIVER_DEBUG, + RING_ID_DRIVER_DEBUG, RING_ID_FIRMWARE_DEBUG, }; -- cgit v1.2.3 From b1fcd261a2330954cb88a82dd88b63584e8f06d0 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Wed, 11 Nov 2015 14:55:43 -0800 Subject: qcacld-3.0: Reduce PM QOS latency tolerance time to minimum qcacld-2.0 to qcacld-3.0 propagation In order to improve driver load time, reduce PM QOS latency tolerance time to minimum to avoid CPU enters aggressive PS during loading driver. Change-Id: Ibacf933d379f37063d900d444de20493b94ebd90 CRs-fixed: 935267 --- core/hdd/src/wlan_hdd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c0dbf04009be..24741051cb8c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -122,7 +122,7 @@ extern int hdd_hostapd_stop(struct net_device *dev); #define MEMORY_DEBUG_STR "" #endif -#define DISABLE_KRAIT_IDLE_PS_VAL 200 +#define DISABLE_KRAIT_IDLE_PS_VAL 1 /* the Android framework expects this param even though we don't use it */ #define BUF_LEN 20 static char fwpath_buffer[BUF_LEN]; -- cgit v1.2.3 From 8e1160ea072e5fd679116b07332f20e53f7e1191 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Thu, 12 Nov 2015 15:57:28 -0800 Subject: qcacld-3.0: CL 1414446 - update fw debug log file qcacld-2.0 to qcacld-3.0 propagation Add NAN feature follow up TX related dbglog IDs. Change-Id: Id015d185837e917b3bf026a4a39528e7d80b2588 CRs-fixed: 938151 --- target/inc/dbglog_id.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/inc/dbglog_id.h b/target/inc/dbglog_id.h index 8b46c4959f3a..79b56fec795a 100644 --- a/target/inc/dbglog_id.h +++ b/target/inc/dbglog_id.h @@ -1434,8 +1434,10 @@ extern "C" { #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_NOT_ALLOWED + 1) +#define NAN_DBGID_END (NAN_DBGID_NAN_TX_FOLLOWUP_RESP_TR_ID + 1) /* IBSS PS module DBGIDs*/ #define IBSS_PS_DBGID_DEFINITION_START 0 -- cgit v1.2.3 From 3c5500cbfa50bd67d06defaf31433ca01085eecd Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 27 Oct 2015 11:48:27 -0700 Subject: qcacld-3.0: Fix the usage of struct list_head for vdev_resp_queue Fix the usage of linux-specific structures and functions by replacing them with OS-abstracted types for vdev_resp_queue. Change-Id: If2d4a9a1dffd59ec1db4b4aa572dfa453bfd0167 CRs-Fixed: 931094 --- core/cdf/inc/cdf_list.h | 2 ++ core/cdf/src/cdf_list.c | 11 ++++++++++ core/wma/inc/wma.h | 2 +- core/wma/inc/wma_internal.h | 2 ++ core/wma/src/wma_dev_if.c | 50 +++++++++++++++++++++++++++++++++++---------- core/wma/src/wma_main.c | 31 +++++++++++++++++++++------- 6 files changed, 79 insertions(+), 19 deletions(-) diff --git a/core/cdf/inc/cdf_list.h b/core/cdf/inc/cdf_list.h index d4b793e39c9d..2076e1c3988e 100644 --- a/core/cdf/inc/cdf_list.h +++ b/core/cdf/inc/cdf_list.h @@ -107,4 +107,6 @@ CDF_STATUS cdf_list_peek_next(cdf_list_t *p_list, cdf_list_node_t *p_node, CDF_STATUS cdf_list_remove_node(cdf_list_t *p_list, cdf_list_node_t *p_node_to_remove); +bool cdf_list_empty(cdf_list_t *list); + #endif /* __CDF_LIST_H */ diff --git a/core/cdf/src/cdf_list.c b/core/cdf/src/cdf_list.c index 1d60f9e21027..9171f22c195c 100644 --- a/core/cdf/src/cdf_list.c +++ b/core/cdf/src/cdf_list.c @@ -223,3 +223,14 @@ CDF_STATUS cdf_list_peek_next(cdf_list_t *pList, cdf_list_node_t *pNode, return CDF_STATUS_SUCCESS; } + +/** + * cdf_list_empty() - check if the list is empty + * @list: pointer to the list + * + * Return: true if the list is empty and false otherwise. + */ +bool cdf_list_empty(cdf_list_t *list) +{ + return list_empty(&list->anchor); +} diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index d86c8f1d5d20..956c97c9b57f 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1239,7 +1239,7 @@ typedef struct { uint32_t scan_id; struct wma_txrx_node *interfaces; pdev_cli_config_t pdevconfig; - struct list_head vdev_resp_queue; + cdf_list_t vdev_resp_queue; cdf_spinlock_t vdev_respq_lock; cdf_list_t wma_hold_req_queue; cdf_spinlock_t wma_hold_req_q_lock; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index b6375a114add..c455e12b77a8 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -104,6 +104,8 @@ #define LINK_RATE_VHT 0x3 #define MAX_ENTRY_HOLD_REQ_QUEUE 2 +#define MAX_ENTRY_VDEV_RESP_QUEUE 10 + /** * struct index_data_rate_type - non vht data rate type * @beacon_rate_index: Beacon rate index diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 79e17be2c54c..e847cced08cb 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -337,14 +337,13 @@ static struct wma_target_req *wma_find_req(tp_wma_handle wma, cdf_list_peek_next(&wma->wma_hold_req_queue, node1, &node2)); + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); if (!found) { - cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); WMA_LOGE(FL("target request not found for vdev_id %d type %d"), vdev_id, type); return NULL; } - cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); WMA_LOGD(FL("target request found for vdev id: %d type %d"), vdev_id, type); @@ -362,28 +361,48 @@ static struct wma_target_req *wma_find_req(tp_wma_handle wma, static struct wma_target_req *wma_find_vdev_req(tp_wma_handle wma, uint8_t vdev_id, uint8_t type) { - struct wma_target_req *req_msg = NULL, *tmp; + struct wma_target_req *req_msg = NULL; bool found = false; + cdf_list_node_t *node1 = NULL, *node2 = NULL; + CDF_STATUS status; cdf_spin_lock_bh(&wma->vdev_respq_lock); - list_for_each_entry_safe(req_msg, tmp, &wma->vdev_resp_queue, node) { + if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->vdev_resp_queue, + &node2)) { + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + WMA_LOGE(FL("unable to get target req from vdev resp queue")); + return NULL; + } + + do { + node1 = node2; + req_msg = cdf_container_of(node1, struct wma_target_req, node); if (req_msg->vdev_id != vdev_id) continue; if (req_msg->type != type) continue; found = true; - list_del(&req_msg->node); + status = cdf_list_remove_node(&wma->vdev_resp_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + WMA_LOGD(FL("Failed to target req for vdev_id %d type %d"), + vdev_id, type); + return NULL; + } break; - } + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&wma->vdev_resp_queue, + node1, &node2)); + cdf_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); + WMA_LOGP(FL("target request not found for vdev_id %d type %d"), + 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); + WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"), + vdev_id, type, req_msg->msg_type); return req_msg; } @@ -2619,6 +2638,7 @@ struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, void *params, uint32_t timeout) { struct wma_target_req *req; + CDF_STATUS status; req = cdf_mem_malloc(sizeof(*req)); if (!req) { @@ -2636,7 +2656,15 @@ struct wma_target_req *wma_fill_vdev_req(tp_wma_handle wma, wma_vdev_resp_timer, req); cdf_mc_timer_start(&req->event_timeout, timeout); cdf_spin_lock_bh(&wma->vdev_respq_lock); - list_add_tail(&req->node, &wma->vdev_resp_queue); + status = cdf_list_insert_back(&wma->vdev_resp_queue, &req->node); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + WMA_LOGE(FL("Failed add request in queue for vdev_id %d type %d"), + vdev_id, type); + cdf_mem_free(req); + return NULL; + } + cdf_spin_unlock_bh(&wma->vdev_respq_lock); return req; } diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 86868bf3885d..94ee880aaab0 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1687,7 +1687,8 @@ CDF_STATUS wma_open(void *cds_context, goto err_event_init; } - INIT_LIST_HEAD(&wma_handle->vdev_resp_queue); + cdf_list_init(&wma_handle->vdev_resp_queue, + MAX_ENTRY_VDEV_RESP_QUEUE); cdf_spinlock_init(&wma_handle->vdev_respq_lock); cdf_list_init(&wma_handle->wma_hold_req_queue, MAX_ENTRY_HOLD_REQ_QUEUE); @@ -2769,7 +2770,7 @@ static void wma_cleanup_hold_req(tp_wma_handle wma) do { node1 = node2; - req_msg = (struct wma_target_req *)node1; + req_msg = cdf_container_of(node1, struct wma_target_req, node); status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); if (CDF_STATUS_SUCCESS != status) { cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); @@ -2795,13 +2796,29 @@ static void wma_cleanup_hold_req(tp_wma_handle wma) */ static void wma_cleanup_vdev_resp(tp_wma_handle wma) { - struct wma_target_req *msg, *tmp; + struct wma_target_req *req_msg = NULL; + cdf_list_node_t *node1 = NULL; + CDF_STATUS status; cdf_spin_lock_bh(&wma->vdev_respq_lock); - list_for_each_entry_safe(msg, tmp, &wma->vdev_resp_queue, node) { - list_del(&msg->node); - cdf_mc_timer_destroy(&msg->event_timeout); - cdf_mem_free(msg); + if (cdf_list_empty(&wma->vdev_resp_queue)) { + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + WMA_LOGI(FL("request queue maybe empty")); + return; + } + + while (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->vdev_resp_queue, + &node1)) { + req_msg = cdf_container_of(node1, struct wma_target_req, node); + status = cdf_list_remove_node(&wma->vdev_resp_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->vdev_respq_lock); + WMA_LOGE(FL("Failed to remove request for vdev_id %d type %d"), + req_msg->vdev_id, req_msg->type); + return; + } + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); } cdf_spin_unlock_bh(&wma->vdev_respq_lock); } -- cgit v1.2.3 From 9355399b46f130bd01ececdf5bdedd52ebaed503 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Mon, 9 Nov 2015 16:57:40 -0800 Subject: qcacld-3.0: Fix the incorrect usage of node in wma_cleanup_hold_req Fix the usage of list node which was deleted before the usage in wma_cleanup_hold_req function. Change-Id: I8ee243fda511de71083ce7e631a21497f4f153c1 CRs-Fixed: 937267 --- core/wma/src/wma_main.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 94ee880aaab0..c2eafde3feaa 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2757,19 +2757,18 @@ end: static void wma_cleanup_hold_req(tp_wma_handle wma) { struct wma_target_req *req_msg = NULL; - cdf_list_node_t *node1 = NULL, *node2 = NULL; + cdf_list_node_t *node1 = NULL; CDF_STATUS status; cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); - if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->wma_hold_req_queue, - &node2)) { + if (cdf_list_empty(&wma->wma_hold_req_queue)) { cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); - WMA_LOGI(FL("request queue maybe empty")); + WMA_LOGI(FL("request queue is empty")); return; } - do { - node1 = node2; + while (CDF_STATUS_SUCCESS != + cdf_list_peek_front(&wma->wma_hold_req_queue, &node1)) { req_msg = cdf_container_of(node1, struct wma_target_req, node); status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); if (CDF_STATUS_SUCCESS != status) { @@ -2777,14 +2776,10 @@ static void wma_cleanup_hold_req(tp_wma_handle wma) WMA_LOGE(FL("Failed to remove request for vdev_id %d type %d"), req_msg->vdev_id, req_msg->type); return; - } else { - cdf_mc_timer_destroy(&req_msg->event_timeout); - cdf_mem_free(req_msg); } - } while (CDF_STATUS_SUCCESS == - cdf_list_peek_next(&wma->wma_hold_req_queue, node1, - &node2)); - + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + } cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); } -- cgit v1.2.3 From e6e6ea9d84680870beda8d386a1473c2c2b63a86 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 10 Nov 2015 14:56:16 -0800 Subject: qcacld-3.0: Fix inappropriate use of linux-specific code Fix inappropriate use of Linux-specific workqueue code and data structures in WMA. WMA is supposed to be os-agnostic code but it currently has Linux-specific data declarations and code for ack_cmp_work. This change set will convert the existing code to os-agnostic representation. Change-Id: I3260fa3b4b482c10272ac94ab10e14e40b8950f9 CRs-Fixed: 924421 --- core/wma/inc/wma.h | 2 +- core/wma/src/wma_data.c | 39 +++++++++++++++++---------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 956c97c9b57f..f15e51819f09 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1442,7 +1442,7 @@ struct wma_tx_ack_work_ctx { tp_wma_handle wma_handle; uint16_t sub_type; int32_t status; - struct work_struct ack_cmp_work; + cdf_work_t ack_cmp_work; }; /** diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 872863abd58b..7e2cafbd86d3 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -800,7 +800,7 @@ int32_t wmi_unified_send_txbf(tp_wma_handle wma, tpAddStaParams params) * * Return: none */ -static void wma_data_tx_ack_work_handler(struct work_struct *ack_work) +static void wma_data_tx_ack_work_handler(void *ack_work) { struct wma_tx_ack_work_ctx *work; tp_wma_handle wma_handle; @@ -811,7 +811,8 @@ static void wma_data_tx_ack_work_handler(struct work_struct *ack_work) return; } - work = container_of(ack_work, struct wma_tx_ack_work_ctx, ack_cmp_work); + work = (struct wma_tx_ack_work_ctx *)ack_work; + wma_handle = work->wma_handle; ack_cb = wma_handle->umac_data_ota_ack_cb; @@ -883,19 +884,15 @@ wma_data_tx_ack_comp_hdlr(void *wma_context, cdf_nbuf_t netbuf, int32_t status) ack_work = cdf_mem_malloc(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 /* CONFIG_CNSS */ 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); + cdf_create_work(0, &ack_work->ack_cmp_work, + wma_data_tx_ack_work_handler, + ack_work); + /* Schedule the Work */ + cdf_sched_work(0, &ack_work->ack_cmp_work); } } @@ -1478,7 +1475,7 @@ CDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, * * Return: none */ -static void wma_mgmt_tx_ack_work_handler(struct work_struct *ack_work) +static void wma_mgmt_tx_ack_work_handler(void *ack_work) { struct wma_tx_ack_work_ctx *work; tp_wma_handle wma_handle; @@ -1489,7 +1486,8 @@ static void wma_mgmt_tx_ack_work_handler(struct work_struct *ack_work) return; } - work = container_of(ack_work, struct wma_tx_ack_work_ctx, ack_cmp_work); + work = (struct wma_tx_ack_work_ctx *)ack_work; + wma_handle = work->wma_handle; ack_cb = wma_handle->umac_ota_ack_cb[work->sub_type]; @@ -1561,19 +1559,16 @@ wma_mgmt_tx_ack_comp_hdlr(void *wma_context, cdf_nbuf_t netbuf, int32_t status) cdf_mem_malloc(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 /* CONFIG_CNSS */ 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); + cdf_create_work(0, &ack_work->ack_cmp_work, + wma_mgmt_tx_ack_work_handler, + ack_work); + + /* Schedule the Work */ + cdf_sched_work(0, &ack_work->ack_cmp_work); } } } -- cgit v1.2.3 From a1585b7253c7d8dfdb9d9d110d1debd402fdea06 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Mon, 28 Sep 2015 15:32:55 -0700 Subject: qcacld-3.0: Fix layering violation in hdd_update_tgt_services Fix layering violation in hdd_update_tgt_services by not accessing pMac structure directly from HDD. New SME API - sme_update_tgt_services() introducted to configure the parameters in pMAC structure. Change-Id: I7310e51001c5e17ed63730d7a86445548aa3d246 CRs-Fixed: 915267 --- core/hdd/src/wlan_hdd_main.c | 4 +--- core/sme/inc/sme_api.h | 2 ++ core/sme/src/common/sme_api.c | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 24741051cb8c..12d462acf2e2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -668,7 +668,6 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, struct wma_tgt_services *cfg) { struct hdd_config *config = hdd_ctx->config; - tpAniSirGlobal pMac = PMAC_STRUCT(hdd_ctx->hHal); /* Set up UAPSD */ config->apUapsdEnabled &= cfg->uapsd; @@ -690,7 +689,6 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, if (cfg->pno_offload) config->PnoOffload = true; #endif - pMac->lteCoexAntShare = cfg->lte_coex_ant_share; #ifdef FEATURE_WLAN_TDLS config->fEnableTDLSSupport &= cfg->en_tdls; config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan; @@ -701,10 +699,10 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, config->fEnableTDLSSleepSta = false; } #endif - pMac->beacon_offload = cfg->beacon_offload; #ifdef WLAN_FEATURE_ROAM_OFFLOAD config->isRoamOffloadEnabled &= cfg->en_roam_offload; #endif + sme_update_tgt_services(hdd_ctx->hHal, cfg); } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 863ea995f3a9..e81aac929972 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -46,6 +46,7 @@ #include "p2p_api.h" #include "cds_regdomain.h" #include "sme_internal.h" +#include "wma_tgt_cfg.h" #ifdef FEATURE_OEM_DATA_SUPPORT #include "oem_data_api.h" @@ -1045,4 +1046,5 @@ CDF_STATUS sme_register_for_dcc_stats_event(tHalHandle hHal, void *context, void sme_add_set_thermal_level_callback(tHalHandle hal, sme_set_thermal_level_callback callback); +void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 60c8729660a0..6e5632dab844 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14705,3 +14705,21 @@ CDF_STATUS sme_update_roam_scan_hi_rssi_scan_params(tHalHandle hal_handle, return status; } +/** + * sme_update_tgt_services() - update the target services config. + * @hal: HAL pointer. + * @cfg: wma_tgt_services parameters. + * + * update the target services config. + * + * Return: None. + */ +void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + + mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share; + mac_ctx->beacon_offload = cfg->beacon_offload; + + return; +} -- cgit v1.2.3 From 4098e35c2002b843a5eeaffda051cbbd2f6f8a0e Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Wed, 11 Nov 2015 17:19:42 -0800 Subject: qcacld-3.0: Avoid NULL skb dereference during softap TX Change "qcacld-3.0: Record data in DP Trace" introduced skb tracing functionity to the driver. In hdd_softap_hard_start_xmit() logic was added to trace the skb contents, including logic to trace the skb contents when an skb was dropped. However some of the code paths to this "drop_pkt" tracing have a NULL skb. Therefore we must bypass the dropped skb content tracing when the skb is NULL. Change-Id: I485c92647355a0f7f420f40640b697a1d3eb5fb0 CRs-Fixed: 938254 --- core/hdd/src/wlan_hdd_softap_tx_rx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index 6626ca211f83..8f98dcf84366 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -288,7 +288,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Check if the buffer has enough header room */ skb = skb_unshare(skb, GFP_ATOMIC); if (!skb) - goto drop_pkt; + goto drop_pkt_accounting; if (skb_headroom(skb) < dev->hard_header_len) { struct sk_buff *tmp; @@ -296,7 +296,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) skb = skb_realloc_headroom(tmp, dev->hard_header_len); dev_kfree_skb(tmp); if (!skb) - goto drop_pkt; + goto drop_pkt_accounting; } #if defined (IPA_OFFLOAD) } @@ -357,10 +357,11 @@ drop_pkt: DPTRACE(cdf_dp_trace(skb, CDF_DP_TRACE_DROP_PACKET_RECORD, (uint8_t *)&skb->data[CDF_DP_TRACE_RECORD_SIZE], (cdf_nbuf_len(skb)-CDF_DP_TRACE_RECORD_SIZE))); + kfree_skb(skb); +drop_pkt_accounting: ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; - kfree_skb(skb); return NETDEV_TX_OK; } -- cgit v1.2.3 From 4d92972e6cf2ede932e82317d8c83593d6ac16af Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Thu, 12 Nov 2015 10:54:30 -0800 Subject: qcacld-3.0: Fix to honor try again later value only if conn is pmf qcacld-2.0 to qcacld-3.0 propagation Current driver is honoring association response with try again later as reason code without connection being PMF. Driver has been designed to handle try again later reason only for PMF connection. For non-pmf case it should report as failure to upper layer just like any other failures. To fix this situation, honor try again later reason code only if the connection is PMF. Change-Id: I4b37d072bc92e003fcfe62ffe8f93f7c185eb6c7 CRs-Fixed: 919203 --- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 75e2e45f175f..24caac92cd92 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -795,7 +795,8 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, if (assoc_rsp->statusCode != eSIR_MAC_SUCCESS_STATUS #ifdef WLAN_FEATURE_11W - && assoc_rsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER + && (session_entry->limRmfEnabled || + assoc_rsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER) #endif ) { /* @@ -838,7 +839,8 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, * lim_process_mlm_assoc_req */ #ifdef WLAN_FEATURE_11W - if (assoc_rsp->statusCode == eSIR_MAC_TRY_AGAIN_LATER) { + if (session_entry->limRmfEnabled && + assoc_rsp->statusCode == eSIR_MAC_TRY_AGAIN_LATER) { if (assoc_rsp->TimeoutInterval.present && (assoc_rsp->TimeoutInterval.timeoutType == SIR_MAC_TI_TYPE_ASSOC_COMEBACK)) { -- cgit v1.2.3 From 2b3ea77996306b73cce3039fcea981a6f4d8f9e0 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Mon, 2 Nov 2015 18:41:08 -0800 Subject: qcacld-3.0: Fix PMF configuration for LFR2 and LFR3 roaming This commit will fix the incorrect pmf config param for STA DUT in-case of LFR2/3 roaming scenario. Change-Id: Ic0d6d4632cfeaa0589b435a6710f3c2380cf5883 CRs-Fixed: 935947 --- core/sme/src/csr/csr_api_roam.c | 15 +++++++++++++++ core/sme/src/csr/csr_neighbor_roam.c | 20 ++++++++++++++------ core/sme/src/csr/csr_util.c | 9 +++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7a12c66dced2..45b2b495ba20 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -974,6 +974,11 @@ CDF_STATUS csr_roam_copy_connect_profile(tpAniSirGlobal pMac, pProfile->eseCckmInfo.krk_plumbed = connected_prof->eseCckmInfo.krk_plumbed; } +#endif +#ifdef WLAN_FEATURE_11W + pProfile->MFPEnabled = connected_prof->MFPEnabled; + pProfile->MFPRequired = connected_prof->MFPRequired; + pProfile->MFPCapable = connected_prof->MFPCapable; #endif } return status; @@ -6932,6 +6937,11 @@ CDF_STATUS csr_roam_copy_connected_profile(tpAniSirGlobal pMac, pSrcProfile->MDID.mobilityDomain; } #endif +#ifdef WLAN_FEATURE_11W + pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled; + pDstProfile->MFPRequired = pSrcProfile->MFPRequired; + pDstProfile->MFPCapable = pSrcProfile->MFPCapable; +#endif end: if (!CDF_IS_STATUS_SUCCESS(status)) { @@ -13261,6 +13271,11 @@ csr_roam_remove_connected_bss_from_scan_cache(tpAniSirGlobal pMac, pScanFilter->bOSENAssociation = false; pScanFilter->countryCode[0] = 0; pScanFilter->phyMode = eCSR_DOT11_MODE_AUTO; +#ifdef WLAN_FEATURE_11W + pScanFilter->MFPEnabled = pConnProfile->MFPEnabled; + pScanFilter->MFPRequired = pConnProfile->MFPRequired; + pScanFilter->MFPCapable = pConnProfile->MFPCapable; +#endif csr_ll_lock(&pMac->scan.scanResultList); pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); while (pEntry) { diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 7e36d27a1ae8..13a9bc8b89e1 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -2056,20 +2056,28 @@ bool csr_neighbor_roam_is_ssid_and_security_match(tpAniSirGlobal pMac, pIes->SSID.ssid, pIes->SSID.num_ssid, true); if (true == fMatch) { +#ifdef WLAN_FEATURE_11W /* - * 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. + * We are sending current connected APs profile setting + * if other AP doesn't have the same PMF setting as currently + * connected AP then we will have some issues in roaming. * - * Once roaming scenario is defined, we should re-visit - * this section and remove this comment. + * Make sure all the APs have same PMF settings to avoid + * any corner cases. */ + fMatch = csr_is_security_match(pMac, &authType, + &uCEncryptionType, &mCEncryptionType, + &pCurProfile->MFPEnabled, + &pCurProfile->MFPRequired, + &pCurProfile->MFPCapable, + pBssDesc, pIes, NULL, NULL, NULL); +#else fMatch = csr_is_security_match(pMac, &authType, &uCEncryptionType, &mCEncryptionType, NULL, NULL, NULL, pBssDesc, pIes, NULL, NULL, NULL); +#endif return fMatch; } else { return fMatch; diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 59d7662ef06a..5c0670414a10 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -4867,9 +4867,18 @@ bool csr_match_connected_bss_security(tpAniSirGlobal pMac, authList.numEntries = 1; authList.authType[0] = pProfile->AuthType; +#ifdef WLAN_FEATURE_11W + return csr_is_security_match(pMac, &authList, &ucEncryptionList, + &mcEncryptionList, + &pProfile->MFPEnabled, + &pProfile->MFPRequired, + &pProfile->MFPCapable, + pBssDesc, pIes, NULL, NULL, NULL); +#else return csr_is_security_match(pMac, &authList, &ucEncryptionList, &mcEncryptionList, NULL, NULL, NULL, pBssDesc, pIes, NULL, NULL, NULL); +#endif } -- cgit v1.2.3 From 4763872e067f802c1538161d1518eed56f8a5ad9 Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Mon, 9 Nov 2015 14:51:26 -0800 Subject: qcacld-3.0: Remove excessive logging in the OL tx path This change is to address a watchdog bite that is seen when a peer corresponding to the transmit frame is not found in the OL TXRX transmit path. The change is to log the error using a CDF trace warning message. Change-Id: I8792da5539c75a3041c3c85f5a7e29714b721502 CRs-Fixed: 936374 --- core/dp/txrx/ol_tx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index f1941c2cba46..fa6a6e516489 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -129,33 +129,33 @@ cdf_nbuf_t ol_tx_send_data_frame(uint8_t sta_id, cdf_nbuf_t skb, CDF_STATUS status; if (cdf_unlikely(!pdev)) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s:pdev is null", __func__); return skb; } if (sta_id >= WLAN_MAX_STA_COUNT) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s:Invalid sta id", __func__); return skb; } peer = ol_txrx_peer_find_by_local_id(pdev, sta_id); if (!peer) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s:Invalid peer", __func__); return skb; } if (peer->state < ol_txrx_peer_state_conn) { - TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s: station to be yet registered..dropping pkt", __func__); return skb; } status = cdf_nbuf_map_single(cdf_ctx, skb, CDF_DMA_TO_DEVICE); if (cdf_unlikely(status != CDF_STATUS_SUCCESS)) { - TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s: nbuf map failed", __func__); return skb; } @@ -171,7 +171,7 @@ cdf_nbuf_t ol_tx_send_data_frame(uint8_t sta_id, cdf_nbuf_t skb, cdf_nbuf_set_next(skb, NULL); ret = OL_TX_LL(peer->vdev, skb); if (ret) { - TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, "%s: Failed to tx", __func__); cdf_nbuf_unmap_single(cdf_ctx, ret, CDF_DMA_TO_DEVICE); return ret; -- cgit v1.2.3 From 65b674fb9e3746e103ee636fb84603534c2378b3 Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Fri, 30 Oct 2015 15:12:03 -0700 Subject: qcacld-3.0: LRO - Fix LRO disable crash - Fix a crash seen due to memory being freed twice - Deregister the LRO flush callback during LRO disable CRs-Fixed: 933123 Change-Id: I18edadc620da04b9a571da6e1b143c099c308d90 --- core/dp/ol/inc/ol_txrx_osif_api.h | 1 + core/dp/txrx/ol_txrx.c | 55 ++++++++++++++++++++++++++++++++++- core/hdd/src/wlan_hdd_lro.c | 31 ++++++++------------ core/hif/src/ce/ce_api.h | 1 + core/hif/src/ce/ce_main.c | 61 +++++++++++++++++++++++++++++++++++++-- core/hif/src/ce/ce_tasklet.c | 3 +- core/hif/src/hif_napi.c | 8 +++++ 7 files changed, 135 insertions(+), 25 deletions(-) diff --git a/core/dp/ol/inc/ol_txrx_osif_api.h b/core/dp/ol/inc/ol_txrx_osif_api.h index 69b6dcf6d1c5..1bc73d28a550 100644 --- a/core/dp/ol/inc/ol_txrx_osif_api.h +++ b/core/dp/ol/inc/ol_txrx_osif_api.h @@ -279,5 +279,6 @@ void ol_txrx_flush_rx_frames(struct ol_txrx_peer_t *peer, #if defined(FEATURE_LRO) void ol_register_lro_flush_cb(void (handler)(void *), void *data); +void ol_deregister_lro_flush_cb(void); #endif #endif /* _OL_TXRX_OSIF_API__H_ */ diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 566a5ced1607..528b121763b1 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -3112,6 +3112,18 @@ CDF_STATUS ol_txrx_register_pause_cb(ol_tx_pause_callback_fp pause_cb) #endif #if defined(FEATURE_LRO) +/** + * ol_txrx_lro_flush_handler() - LRO flush handler + * @context: dev handle + * @rxpkt: rx data + * @staid: station id + * + * This function handles an LRO flush indication. + * If the rx thread is enabled, it will be invoked by the rx + * thread else it will be called in the tasklet context + * + * Return: none + */ void ol_txrx_lro_flush_handler(void *context, void *rxpkt, uint16_t staid) @@ -3132,6 +3144,15 @@ void ol_txrx_lro_flush_handler(void *context, "%s: lro_flush_cb NULL", __func__); } +/** + * ol_txrx_lro_flush() - LRO flush callback + * @data: opaque data pointer + * + * This is the callback registered with CE to trigger + * an LRO flush + * + * Return: none + */ void ol_txrx_lro_flush(void *data) { p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); @@ -3151,7 +3172,8 @@ void ol_txrx_lro_flush(void *data) return; } - pkt->callback = (cds_ol_rx_thread_cb) ol_txrx_lro_flush_handler; + pkt->callback = + (cds_ol_rx_thread_cb) ol_txrx_lro_flush_handler; pkt->context = pdev; pkt->Rxpkt = NULL; pkt->staId = 0; @@ -3159,6 +3181,16 @@ void ol_txrx_lro_flush(void *data) } } +/** + * ol_register_lro_flush_cb() - register the LRO flush callback + * @handler: callback function + * @data: opaque data pointer to be passed back + * + * Store the LRO flush callback provided and in turn + * register OL's LRO flush handler with CE + * + * Return: none + */ void ol_register_lro_flush_cb(void (handler)(void *), void *data) { struct ol_softc *hif_device = @@ -3170,4 +3202,25 @@ void ol_register_lro_flush_cb(void (handler)(void *), void *data) ce_lro_flush_cb_register(hif_device, ol_txrx_lro_flush, pdev); } + +/** + * ol_deregister_lro_flush_cb() - deregister the LRO flush + * callback + * + * Remove the LRO flush callback provided and in turn + * deregister OL's LRO flush handler with CE + * + * Return: none + */ +void ol_deregister_lro_flush_cb(void) +{ + struct ol_softc *hif_device = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + ce_lro_flush_cb_deregister(hif_device); + + pdev->lro_info.lro_flush_cb = NULL; + pdev->lro_info.lro_data = NULL; +} #endif /* FEATURE_LRO */ diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c index 14b9be616658..a84e839b6967 100644 --- a/core/hdd/src/wlan_hdd_lro.c +++ b/core/hdd/src/wlan_hdd_lro.c @@ -138,14 +138,7 @@ static void hdd_lro_desc_info_init(struct hdd_lro_s *hdd_info) */ static void hdd_lro_desc_pool_deinit(struct hdd_lro_desc_pool *lro_desc_pool) { - - if (lro_desc_pool->lro_desc_array) { - cdf_mem_free(lro_desc_pool->lro_desc_array); - lro_desc_pool->lro_desc_array = NULL; - } - INIT_LIST_HEAD(&lro_desc_pool->lro_free_list_head); - cdf_spinlock_destroy(&lro_desc_pool->lro_pool_lock); } @@ -161,19 +154,10 @@ static void hdd_lro_desc_pool_deinit(struct hdd_lro_desc_pool *lro_desc_pool) */ static void hdd_lro_desc_info_deinit(struct hdd_lro_s *hdd_info) { - int i; struct hdd_lro_desc_info *desc_info = &hdd_info->lro_desc_info; - cdf_mem_free(hdd_info->lro_mgr->lro_arr); - hdd_info->lro_mgr->lro_arr = NULL; hdd_lro_desc_pool_deinit(&desc_info->lro_desc_pool); - /* Free the a list of LRO desc for each entry of the hash table */ - for (i = 0; i < LRO_DESC_TABLE_SZ; i++) - INIT_LIST_HEAD(&desc_info->lro_hash_table[i].lro_desc_list); - cdf_spinlock_destroy(&desc_info->lro_hash_lock); - cdf_mem_free(desc_info->lro_hash_table); - desc_info->lro_hash_table = NULL; } /** @@ -605,9 +589,18 @@ void hdd_lro_disable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) NL80211_IFTYPE_STATION != adapter->wdev.iftype) return; - hdd_lro_desc_info_deinit(&adapter->lro_info); - cdf_mem_free(adapter->lro_info.lro_mgr); - adapter->lro_info.lro_mgr = NULL; + /* Deregister the flush callback */ + ol_deregister_lro_flush_cb(); + + if (adapter->lro_info.lro_mgr) { + hdd_lro_desc_info_deinit(&adapter->lro_info); + cdf_mem_free(adapter->lro_info.lro_mgr); + adapter->lro_info.lro_mgr = NULL; + adapter->lro_info.lro_desc_info. + lro_desc_pool.lro_desc_array = NULL; + adapter->lro_info.lro_desc_info. + lro_hash_table = NULL; + } return; } diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h index 8bde74dba5d7..2b8565982d02 100644 --- a/core/hif/src/ce/ce_api.h +++ b/core/hif/src/ce/ce_api.h @@ -467,5 +467,6 @@ bool ce_check_rx_pending(struct ol_softc *scn, int ce_id); #if defined(FEATURE_LRO) void ce_lro_flush_cb_register(struct ol_softc *scn, void (handler)(void *), void *data); +void ce_lro_flush_cb_deregister(struct ol_softc *scn); #endif #endif /* __COPY_ENGINE_API_H__ */ diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 452fcc6b2782..d79ba203e761 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -2584,10 +2584,65 @@ u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) } #endif +#if defined(FEATURE_LRO) +/** + * ce_lro_flush_cb_register() - register the LRO flush + * callback + * @scn: HIF context + * @handler: callback function + * @data: opaque data pointer to be passed back + * + * Store the LRO flush callback provided + * + * Return: none + */ void ce_lro_flush_cb_register(struct ol_softc *scn, void (handler)(void *), void *data) { - struct CE_state *ce_state = scn->ce_id_to_state[CE_HTT_T2H_MSG]; - ce_state->lro_flush_cb = handler; - ce_state->lro_data = data; + uint8_t ul, dl; + int ul_polled, dl_polled; + + CDF_ASSERT(scn != NULL); + + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(scn, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + printk("%s cannot map service to pipe\n", __FUNCTION__); + return; + } else { + struct CE_state *ce_state; + ce_state = scn->ce_id_to_state[dl]; + ce_state->lro_flush_cb = handler; + ce_state->lro_data = data; + } +} + +/** + * ce_lro_flush_cb_deregister() - deregister the LRO flush + * callback + * @scn: HIF context + * + * Remove the LRO flush callback + * + * Return: none + */ +void ce_lro_flush_cb_deregister(struct ol_softc *scn) +{ + uint8_t ul, dl; + int ul_polled, dl_polled; + + CDF_ASSERT(scn != NULL); + + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(scn, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + printk("%s cannot map service to pipe\n", __FUNCTION__); + return; + } else { + struct CE_state *ce_state; + ce_state = scn->ce_id_to_state[dl]; + ce_state->lro_flush_cb = NULL; + ce_state->lro_data = NULL; + } } +#endif diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c index 6bb550e3c8c9..420905909a2b 100644 --- a/core/hif/src/ce/ce_tasklet.c +++ b/core/hif/src/ce/ce_tasklet.c @@ -214,8 +214,7 @@ static void ce_tasklet(unsigned long data) ce_per_engine_service(scn, tasklet_entry->ce_id); - if (tasklet_entry->ce_id == CE_HTT_T2H_MSG && - CE_state->lro_flush_cb != NULL) { + if (CE_state->lro_flush_cb != NULL) { CE_state->lro_flush_cb(CE_state->lro_data); } diff --git a/core/hif/src/hif_napi.c b/core/hif/src/hif_napi.c index f33fb8747bc3..8b194c812388 100644 --- a/core/hif/src/hif_napi.c +++ b/core/hif/src/hif_napi.c @@ -38,6 +38,7 @@ #include #include #include +#include enum napi_decision_vector { HIF_NAPI_NOEVENT = 0, @@ -399,6 +400,7 @@ int hif_napi_poll(struct napi_struct *napi, int budget) int cpu = smp_processor_id(); struct ol_softc *hif; struct qca_napi_info *napi_info; + struct CE_state *ce_state; NAPI_DEBUG("%s -->(.., budget=%d)\n", budget); @@ -413,6 +415,12 @@ int hif_napi_poll(struct napi_struct *napi, int budget) __func__, rc); napi_info->stats[cpu].napi_workdone += rc; normalized = (rc / napi_info->scale); + + ce_state = hif->ce_id_to_state[NAPI_ID2PIPE(napi_info->id)]; + if (ce_state->lro_flush_cb != NULL) { + ce_state->lro_flush_cb(ce_state->lro_data); + } + /* do not return 0, if there was some work done, even if it is below the scale */ if (rc) -- cgit v1.2.3 From b976119f9b2c36bd54bf33db9cd04d2c69ad3e8d Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Thu, 5 Nov 2015 11:16:21 -0800 Subject: qcacld-3.0: Fix compilation issue for ROAM_OFFLOAD feature Fix compilation issue when ROAM_OFFLOAD is not enabled. There are issues with ROAM_OFFLOAD feature conditional compilation. Change-Id: I068245885ab9f054b4c03307a9ecc0066bc88ebe CRs-fixed: 784982 --- core/hdd/src/wlan_hdd_assoc.c | 26 +++++++++++--------------- core/hdd/src/wlan_hdd_cfg80211.c | 6 +++++- core/hdd/src/wlan_hdd_cfg80211.h | 14 +++++++++++--- core/mac/src/pe/lim/lim_admit_control.c | 5 ++--- core/sme/src/common/sme_api.c | 2 +- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index cefae85899dd..90441b05d714 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1429,12 +1429,9 @@ static void hdd_send_re_assoc_event(struct net_device *dev, final_req_ie, (ssid_ie_len + reqRsnLength), rspRsnIe, rspRsnLength, GFP_KERNEL); - if (pHddCtx->config->isRoamOffloadEnabled && - pCsrRoamInfo->roamSynchInProgress) - wlan_hdd_send_roam_auth_event(pHddCtx, - pCsrRoamInfo->bssid.bytes, - reqRsnIe, reqRsnLength, rspRsnIe, - rspRsnLength, pCsrRoamInfo); + wlan_hdd_send_roam_auth_event(pHddCtx, pCsrRoamInfo->bssid.bytes, + reqRsnIe, reqRsnLength, rspRsnIe, rspRsnLength, + pCsrRoamInfo); done: sme_roam_free_connect_profile(hal_handle, &roam_profile); if (final_req_ie) @@ -1945,15 +1942,14 @@ defined(FEATURE_WLAN_LFR) pFTAssocRsp, assocRsplen, GFP_KERNEL); - if (pRoamInfo->roamSynchInProgress) - wlan_hdd_send_roam_auth_event( - pHddCtx, - pRoamInfo->bssid.bytes, - pFTAssocReq, - assocReqlen, - pFTAssocRsp, - assocRsplen, - pRoamInfo); + wlan_hdd_send_roam_auth_event( + pHddCtx, + pRoamInfo->bssid.bytes, + pFTAssocReq, + assocReqlen, + pFTAssocRsp, + assocRsplen, + pRoamInfo); } if (sme_get_ftptk_state (WLAN_HDD_GET_HAL_CTX(pAdapter), diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index d6a5143e8fc3..3ae8264033e6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -2975,6 +2975,10 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, return -EINVAL; } + if (!hdd_ctx_ptr->config->isRoamOffloadEnabled || + !roam_info_ptr->roamSynchInProgress) + return 0; + skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy, NULL, ETH_ALEN + req_rsn_len + rsp_rsn_len + @@ -3032,7 +3036,7 @@ nla_put_failure: kfree_skb(skb); return -EINVAL; } -#endif +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ static const struct nla_policy wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = { diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index f8cdd9001751..23e604a56c77 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2253,9 +2253,17 @@ 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); + 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_cfg80211_update_apies(hdd_adapter_t *adapter); diff --git a/core/mac/src/pe/lim/lim_admit_control.c b/core/mac/src/pe/lim/lim_admit_control.c index b217c402ee96..2f13a411640d 100644 --- a/core/mac/src/pe/lim/lim_admit_control.c +++ b/core/mac/src/pe/lim/lim_admit_control.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -917,7 +917,6 @@ lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, tSirMsgQ msg; tpAddTsParams pAddTsParam; -#ifdef WLAN_FEATURE_ROAM_OFFLOAD tpPESession psessionEntry = pe_find_session_by_session_id(pMac, sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGP, @@ -925,7 +924,7 @@ lim_send_hal_msg_add_ts(tpAniSirGlobal pMac, sessionId); return eSIR_FAILURE; } -#endif + pAddTsParam = cdf_mem_malloc(sizeof(tAddTsParams)); if (NULL == pAddTsParam) { PELOGW(lim_log(pMac, LOGW, FL("AllocateMemory() failed"));) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6e5632dab844..a2b0eec48634 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -13514,6 +13514,7 @@ CDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hHal, return status; } +#endif /* --------------------------------------------------------------------------- \fn sme_get_temperature @@ -13589,7 +13590,6 @@ CDF_STATUS sme_set_scanning_mac_oui(tHalHandle hHal, tSirScanMacOui *pScanMacOui } return status; } -#endif #ifdef DHCP_SERVER_OFFLOAD /* --------------------------------------------------------------------------- -- cgit v1.2.3 From 5304757ef59191615a27729cf4907e23b394dea2 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Thu, 5 Nov 2015 11:43:17 -0800 Subject: qcacld-3.0: htc: Fix race while processing HTC control messages HTC control messages ready and connect service indications use CtrlResponseBuffer for processing the HTC messages. Flag CtrlResponseProcessing is used to protect this buffer from overwriting before processing. Current implementation has race condition as setting the flag happens on waiting thread context instead of receive thread context so this could lead to overwriting the CtrlResponseBuffer if waiting thread doesn't get chance to run because of may be another RX interrupt. Also to catch this kind of issues, add CDF_BUG so that it is easier to triage the cause for the malformed packet which is not expected. CRs-fixed: 881504 Change-Id: Ia279e08c761a3432cf01d4dc129f7b5439d04680 --- core/htc/htc_recv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/htc/htc_recv.c b/core/htc/htc_recv.c index 3418aac136fe..38f13768f1dd 100644 --- a/core/htc/htc_recv.c +++ b/core/htc/htc_recv.c @@ -418,6 +418,7 @@ CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTC Rx Ctrl still processing\n")); status = CDF_STATUS_E_FAILURE; + CDF_BUG(false); break; } @@ -427,6 +428,9 @@ CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, HTC_MAX_CONTROL_MESSAGE_LENGTH); A_MEMCPY(target->CtrlResponseBuffer, netdata, target->CtrlResponseLength); + + /* Requester will clear this flag */ + target->CtrlResponseProcessing = true; UNLOCK_HTC_RX(target); cdf_semaphore_release(target->osdev, -- cgit v1.2.3 From 81060a8af3175110a504f869b5264c43f89450cb Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 3 Nov 2015 10:42:34 -0800 Subject: qcacld-3.0: Fix for CCKM fast roaming failure. This is qcacld-2.0 to qcacld-3.0 propagation Due to cleanup in function limSendReassocReqWithFTIEsMgmtFrame() assocReqLen was not being set to zero when the corresponding buffer was NULL. This caused memory copy in buffers being passed between PE and SME and HDD to be improper. HDD when reading the buffer wrongly read it from wrong offset and hence RSN IEs being passed to supplicant are all zeros. This patch fixes this by setting assocReqLen = 0 when AssocReq buff is NULL Change-Id: I0edaff93fcdbb2d5ae80478a76f07cb4dee8aceb CRs-Fixed: 929797 --- core/mac/src/pe/lim/lim_send_management_frames.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 4edbce10f6a5..353f4c373a30 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1903,6 +1903,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, if (pe_session->assocReq != NULL) { cdf_mem_free(pe_session->assocReq); pe_session->assocReq = NULL; + pe_session->assocReqLen = 0; } if (add_ie_len) { @@ -2312,6 +2313,7 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, if (pe_session->assocReq != NULL) { cdf_mem_free(pe_session->assocReq); pe_session->assocReq = NULL; + pe_session->assocReqLen = 0; } if (add_ie_len) { @@ -2376,6 +2378,7 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, } } else { lim_log(mac_ctx, LOG1, FL("FT IEs not present")); + pe_session->assocReqLen = 0; } #ifdef FEATURE_WLAN_DIAG_SUPPORT @@ -2686,6 +2689,7 @@ lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, if (psessionEntry->assocReq != NULL) { cdf_mem_free(psessionEntry->assocReq); psessionEntry->assocReq = NULL; + psessionEntry->assocReqLen = 0; } if (nAddIELen) { -- cgit v1.2.3 From 0e478c6829c7964d10a3ebce6fc65fa5d893e41f Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Tue, 10 Nov 2015 15:20:06 -0800 Subject: qcacld-3.0: wma_update_intf_hw_mode_params to call tx & rx ss macros correctly The Tx & Rx SS macros aren't called with correct parameter in wma_update_intf_hw_mode_params. Fix the calls to get the Tx & Rx SS values correctly. Change-Id: I4df4db549d4bb0c7d00a521de55165bfccf16a65 CRs-fixed: 935341 --- core/wma/src/wma_utils.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index b2f1fa5b7842..fd34f803a920 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -2925,6 +2925,7 @@ void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id, uint32_t cfgd_hw_mode_index) { tp_wma_handle wma; + uint32_t param; wma = cds_get_context(CDF_MODULE_ID_WMA); if (!wma) { @@ -2937,17 +2938,23 @@ void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id, return; } + if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) { + WMA_LOGE("%s: Invalid index", __func__); + return; + } + + param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index]; wma->interfaces[vdev_id].mac_id = mac_id; if (mac_id == 0) { wma->interfaces[vdev_id].tx_streams = - WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(cfgd_hw_mode_index); + WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param); wma->interfaces[vdev_id].rx_streams = - WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(cfgd_hw_mode_index); + WMI_DBS_HW_MODE_MAC0_RX_STREAMS_GET(param); } else { wma->interfaces[vdev_id].tx_streams = - WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(cfgd_hw_mode_index); + WMI_DBS_HW_MODE_MAC1_TX_STREAMS_GET(param); wma->interfaces[vdev_id].rx_streams = - WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(cfgd_hw_mode_index); + WMI_DBS_HW_MODE_MAC1_RX_STREAMS_GET(param); } } -- cgit v1.2.3 From 941cca36d8013dda3d14dd9aceb0908fa840c508 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Mon, 9 Nov 2015 13:34:07 -0800 Subject: qcacld-3.0: Change cdf_trace_hex_dump to use hex_dump_to_buffer qcacld-2.0 to qcacld-3.0 propagation Change cdf_trace_hex_dump to use hex_dump_to_buffer. This will print one line even if buffer size is less than 16 bytes. Change-Id: I2dec78048d52f96d494c9e0ce133c4c18f48e954 CRs-fixed: 933157 --- core/cdf/src/cdf_trace.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/core/cdf/src/cdf_trace.c b/core/cdf/src/cdf_trace.c index 3d59c53d272f..dfacdd45cb20 100644 --- a/core/cdf/src/cdf_trace.c +++ b/core/cdf/src/cdf_trace.c @@ -355,6 +355,10 @@ void cdf_trace_display(void) } } +#define ROW_SIZE 16 +/* Buffer size = data bytes(2 hex chars plus space) + NULL */ +#define BUFFER_SIZE ((ROW_SIZE * 3) + 1) + /** * cdf_trace_hex_dump() - externally called hex dump function * @module : Module identifier a member of the CDF_MODULE_ID enumeration that @@ -372,35 +376,23 @@ void cdf_trace_display(void) void cdf_trace_hex_dump(CDF_MODULE_ID module, CDF_TRACE_LEVEL level, void *data, int buf_len) { - char *buf = (char *)data; - int i; + const u8 *ptr = data; + int i, linelen, remaining = buf_len; + unsigned char linebuf[BUFFER_SIZE]; if (!(g_cdf_trace_info[module].moduleTraceLevel & - CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level))) + CDF_TRACE_LEVEL_TO_MODULE_BITMASK(level))) return; - for (i = 0; (i + 15) < buf_len; i += 16) { - cdf_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]); - } + for (i = 0; i < buf_len; i += ROW_SIZE) { + linelen = min(remaining, ROW_SIZE); + remaining -= ROW_SIZE; - /* Dump the bytes in the last line */ - for (; i < buf_len; i++) - cdf_trace_msg(module, level, "%02x ", buf[i]); + hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1, + linebuf, sizeof(linebuf), false); + + cdf_trace_msg(module, level, "%.8x: %s", i, linebuf); + } } #endif -- cgit v1.2.3 From 9e8718ef199481eab662473b014706c5c72068b9 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Mon, 9 Nov 2015 13:19:06 -0800 Subject: qcacld-3.0: Change event_lock for HDD IPA resources with ipa_lock qcacld-2.0 to qcacld-3.0 propagation HDD IPA event_lock was originally introduced to protect IPA resources between HDD_IPA events, but this also used to protect HDD IPA internal struct now. So, this could cause an unexpected deadlock by guarding too wide resources. This change is to separate a lock for IPA resources. Change-Id: Ie9b676e5d4775e54bddf141b841e0f0daeb22731 CRs-fixed: 934723 --- core/hdd/src/wlan_hdd_ipa.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 236dd036d23d..f56d2f0387f2 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -413,6 +413,7 @@ struct hdd_ipa_priv { unsigned int rt_buf_fill_index; cdf_mc_timer_t rt_debug_fill_timer; cdf_mutex_t rt_debug_lock; + cdf_mutex_t ipa_lock; }; #define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr) @@ -857,7 +858,7 @@ void hdd_ipa_uc_stat_query(hdd_context_t *pHddCtx, return; } - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_acquire(&hdd_ipa->ipa_lock); if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && (false == hdd_ipa->resource_loading)) { *ipa_tx_diff = hdd_ipa->ipa_tx_packets_diff; @@ -865,7 +866,7 @@ void hdd_ipa_uc_stat_query(hdd_context_t *pHddCtx, HDD_IPA_LOG(LOG1, "STAT Query TX DIFF %d, RX DIFF %d", *ipa_tx_diff, *ipa_rx_diff); } - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); return; } @@ -893,7 +894,7 @@ void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, uint8_t reason) } HDD_IPA_LOG(LOG1, "STAT REQ Reason %d", reason); - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_acquire(&hdd_ipa->ipa_lock); if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) && (false == hdd_ipa->resource_loading)) { hdd_ipa->stat_req_reason = reason; @@ -902,7 +903,7 @@ void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, uint8_t reason) (int)WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID, 0, VDEV_CMD); } - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); } /** @@ -1147,12 +1148,12 @@ hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event) case IPA_RM_RESOURCE_GRANTED: /* Differed RM Granted */ hdd_ipa_uc_enable_pipes(hdd_ipa); - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_acquire(&hdd_ipa->ipa_lock); if ((false == hdd_ipa->resource_unloading) && (!hdd_ipa->activated_fw_pipe)) { hdd_ipa_uc_enable_pipes(hdd_ipa); } - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); if (hdd_ipa->pending_cons_req) { ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED, IPA_RM_RESOURCE_WLAN_CONS); @@ -1288,18 +1289,18 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) if ((HDD_IPA_UC_OPCODE_TX_RESUME == msg->op_code) || (HDD_IPA_UC_OPCODE_RX_RESUME == msg->op_code)) { - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_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 = false; hdd_ipa_uc_proc_pending_event(hdd_ipa); } - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); } if ((HDD_IPA_UC_OPCODE_TX_SUSPEND == msg->op_code) || (HDD_IPA_UC_OPCODE_RX_SUSPEND == msg->op_code)) { - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_acquire(&hdd_ipa->ipa_lock); hdd_ipa->activated_fw_pipe--; if (!hdd_ipa->activated_fw_pipe) { hdd_ipa_uc_disable_pipes(hdd_ipa); @@ -1314,7 +1315,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) hdd_ipa_uc_proc_pending_event(hdd_ipa); } } - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); } if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) && @@ -1498,7 +1499,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) /* STATs from FW */ uc_fw_stat = (struct ipa_uc_fw_stats *) ((uint8_t *)op_msg + sizeof(struct op_msg_type)); - cdf_mutex_acquire(&hdd_ipa->event_lock); + cdf_mutex_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); @@ -1513,7 +1514,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) (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); - cdf_mutex_release(&hdd_ipa->event_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); } else { HDD_IPA_LOG(LOGE, "INVALID REASON %d", hdd_ipa->stat_req_reason); @@ -1667,6 +1668,7 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) cdf_list_init(&ipa_ctxt->pending_event, 1000); cdf_mutex_init(&ipa_ctxt->event_lock); + cdf_mutex_init(&ipa_ctxt->ipa_lock); /* TX PIPE */ pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; @@ -1820,12 +1822,12 @@ int hdd_ipa_uc_ssr_deinit(void) */ hdd_ipa_uc_disable_pipes(hdd_ipa); - cdf_wake_lock_acquire(&hdd_ipa->event_lock); + cdf_wake_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; } - cdf_wake_lock_release(&hdd_ipa->event_lock); + cdf_wake_lock_release(&hdd_ipa->ipa_lock); /* Full IPA driver cleanup not required since wlan driver is now * unloaded and reloaded after SSR. @@ -3964,6 +3966,7 @@ CDF_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) "%s: Disconnect RX PIPE", __func__); ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle); cdf_mutex_destroy(&hdd_ipa->event_lock); + cdf_mutex_destroy(&hdd_ipa->ipa_lock); cdf_list_destroy(&hdd_ipa->pending_event); #ifdef WLAN_OPEN_SOURCE -- cgit v1.2.3 From 2c385d928f758e35e7185cfb22cd774070c68d44 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Fri, 13 Nov 2015 08:11:43 -0800 Subject: qcacld-3.0: Change the range of values for Early Stop Scan feature Change the range of values for early stop scan feature configuration items as per firmware expectations. CRs-Fixed: 939185 Change-Id: I7d893cd1ed44a71bffaab22121f052288b14b640 --- core/hdd/inc/wlan_hdd_cfg.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 82c99e896b6c..0e2e2fd236c3 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2723,25 +2723,25 @@ enum dot11p_mode { #define CFG_EARLY_STOP_SCAN_ENABLE_DEFAULT (0) /* * Early stop scan minimum threshold is the minimum threshold - * at which the candidate AP should be to be qualified as a - * potential roam candidate and good enough to stop the roaming scan + * to be considered for stopping the scan. The algorithm starts + * with a scan on the greedy channel list with the maximum threshold + * and steps down the threshold by 20% for each further channel. + * It can step down on each channel but cannot go lower than the minimum + * threshold. */ #define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD "gEarlyStopScanMinThreshold" -#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN (-60) -#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX (-40) -#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT (-45) +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MIN (-80) +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_MAX (-70) +#define CFG_EARLY_STOP_SCAN_MIN_THRESHOLD_DEFAULT (-78) /* * Early stop scan maximum threshold is the maximum threshold - * to be considered for stopping the scan. The algorithm starts - * with a scan on the greedy channel list with the minimum threshold - * and steps up the threshold by 20% for each further channel. - * It can step up on each channel but cannot exceed the maximum - * threshold. + * at which the candidate AP should be to be qualified as a + * potential roam candidate and good enough to stop the roaming scan */ #define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD "gEarlyStopScanMaxThreshold" -#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN (-80) -#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX (-70) -#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT (-78) +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN (-60) +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX (-40) +#define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT (-45) /*--------------------------------------------------------------------------- Type declarations -- cgit v1.2.3 From ec0e44f63ca6a74625f052a06c4dff3efb47110e Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Kalikot Veetil Date: Fri, 6 Nov 2015 14:27:28 -0800 Subject: qcacld-2.0: Fix intra-BSS forwarding qcacld-2.0 to qcacld-3.0 propagation When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send all Rx packets to IPA uC, which needs to be forwarded to other interfaces. IPA driver will send back non-IP, broadcast and multicast packets to WLAN host driver in exception pipe with fw_desc field set by FW as: - FW_RX_DESC_FORWARD_M bit: Forward the packet to TX - FW_RX_DESC_DISCARD_M bit: Do not send the packet to network stack, which will be set of for intrabss unicast. Change-Id: Ie2826c8c7b578e3684133a2554ed086e721f67ae CRs-Fixed: 895662 --- core/hdd/src/wlan_hdd_ipa.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index f56d2f0387f2..10d1acb16bde 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -2444,12 +2444,6 @@ static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, */ fw_desc = (uint8_t)skb->cb[1]; - if (fw_desc & FW_RX_DESC_DISCARD_M) { - HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); - hdd_ipa->ipa_rx_discard++; - cdf_nbuf_free(skb); - break; - } if (fw_desc & FW_RX_DESC_FORWARD_M) { HDD_IPA_LOG( @@ -2473,6 +2467,14 @@ static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, } } } + + if (fw_desc & FW_RX_DESC_DISCARD_M) { + HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); + hdd_ipa->ipa_rx_discard++; + cdf_nbuf_free(skb); + break; + } + } else { HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "Intra-BSS FWD is disabled-skip forward to Tx"); -- cgit v1.2.3 From c319c82a4d6ce23e7fb5a4f43044e05860f1dcf4 Mon Sep 17 00:00:00 2001 From: Sanjay Devnani Date: Fri, 6 Nov 2015 16:44:28 -0800 Subject: qcacld-3.0: Remove redundancy in svc to ce map Map was replicated at 2 places. Deleting the second one to use only one. Change-Id: Ie3a6f0882cbaf2988f8e456b989d3fed9d631de0 CRs-Fixed: 936404 --- core/hif/inc/hif.h | 6 +- core/hif/src/ce/ce_main.c | 137 ++++++++++++++++++++-------------------------- 2 files changed, 62 insertions(+), 81 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 0c9a41318a7d..aa0b60555d66 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -609,9 +609,9 @@ void hif_send_complete_check(struct ol_softc *scn, uint8_t PipeID, void hif_cancel_deferred_target_sleep(struct ol_softc *scn); void hif_get_default_pipe(struct ol_softc *scn, uint8_t *ULPipe, uint8_t *DLPipe); -int hif_map_service_to_pipe(struct ol_softc *scn, uint16_t ServiceId, - uint8_t *ULPipe, uint8_t *DLPipe, - int *ul_is_polled, int *dl_is_polled); +int hif_map_service_to_pipe(struct ol_softc *scn, uint16_t svc_id, + uint8_t *ul_pipe, uint8_t *dl_pipe, int *ul_is_polled, + int *dl_is_polled); uint16_t hif_get_free_queue_number(struct ol_softc *scn, uint8_t PipeID); void *hif_get_targetdef(struct ol_softc *scn); void hi_fsuspendwow(struct ol_softc *scn); diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index d79ba203e761..abeb6a38b7a0 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1219,84 +1219,6 @@ hif_get_default_pipe(struct ol_softc *scn, uint8_t *ULPipe, uint8_t *DLPipe) ULPipe, DLPipe, &ul_is_polled, &dl_is_polled); } -/* TBDXXX - temporary mapping while we have too few CE's */ -int -hif_map_service_to_pipe(struct ol_softc *scn, uint16_t ServiceId, - uint8_t *ULPipe, uint8_t *DLPipe, int *ul_is_polled, - int *dl_is_polled) -{ - int status = CDF_STATUS_SUCCESS; - - *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: - *ULPipe = 0; - *DLPipe = 2; - break; - - 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 = 2; - 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(cds_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; - - case WDI_IPA_TX_SVC: - *ULPipe = 5; - break; - - /* pipe 5 unused */ - /* pipe 6 reserved */ - /* pipe 7 reserved */ - - default: - status = CDF_STATUS_E_INVAL; - break; - } - *ul_is_polled = - (host_ce_config[*ULPipe].flags & CE_ATTR_DISABLE_INTR) != 0; - - return status; -} - /** * hif_dump_pipe_debug_count() - Log error count * @scn: ol_softc pointer. @@ -2646,3 +2568,62 @@ void ce_lro_flush_cb_deregister(struct ol_softc *scn) } } #endif + +/** + * hif_map_service_to_pipe() - returns the ce ids pertaining to + * this service + * @scn: ol_softc pointer. + * @svc_id: Service ID for which the mapping is needed. + * @ul_pipe: address of the container in which ul pipe is returned. + * @dl_pipe: address of the container in which dl pipe is returned. + * @ul_is_polled: address of the container in which a bool + * indicating if the UL CE for this service + * is polled is returned. + * @dl_is_polled: address of the container in which a bool + * indicating if the DL CE for this service + * is polled is returned. + * + * Return: Indicates whether this operation was successful. + */ + +int hif_map_service_to_pipe(struct ol_softc *scn, uint16_t svc_id, + uint8_t *ul_pipe, uint8_t *dl_pipe, int *ul_is_polled, + int *dl_is_polled) +{ + int status = CDF_STATUS_SUCCESS; + + unsigned int i; + struct service_to_pipe element; + + struct service_to_pipe *tgt_svc_map_to_use; + size_t sz_tgt_svc_map_to_use; + + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + tgt_svc_map_to_use = target_service_to_ce_map_wlan_epping; + sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_wlan_epping); + } else { + tgt_svc_map_to_use = target_service_to_ce_map_wlan; + sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_wlan); + } + + *dl_is_polled = 0; /* polling for received messages not supported */ + + for (i = 0; i < (sz_tgt_svc_map_to_use/sizeof(element)); i++) { + + memcpy(&element, &tgt_svc_map_to_use[i], sizeof(element)); + if (element.service_id == svc_id) { + + if (element.pipedir == PIPEDIR_OUT) + *ul_pipe = element.pipenum; + + else if (element.pipedir == PIPEDIR_IN) + *dl_pipe = element.pipenum; + } + } + + *ul_is_polled = + (host_ce_config[*ul_pipe].flags & CE_ATTR_DISABLE_INTR) != 0; + + return status; +} -- cgit v1.2.3 From 9ce15778e14c937ee8bfaa1dc69fcda22a43a729 Mon Sep 17 00:00:00 2001 From: Sanjay Devnani Date: Thu, 12 Nov 2015 14:08:57 -0800 Subject: qcacld-3.0: Enable all 12 Copy Engines Facilitates faster data transfers. This provides a basis to start using the other 4 CEs for additional services. Only adding structure elements to enable these CEs not really using them yet. Change-Id: I4be07413de409195ccc717765c75806a1470941e CRs-Fixed: 938752 --- core/hif/inc/hif.h | 4 ++++ core/hif/src/adrastea_reg_def.h | 2 +- core/hif/src/ce/ce_assignment.h | 12 +++++++++++- core/hif/src/ce/ce_service.c | 8 ++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index aa0b60555d66..dd2c89832867 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -85,7 +85,11 @@ typedef void __iomem *A_target_id_t; #define TARGET_TYPE_ADRASTEA 16 struct CE_state; +#ifdef QCA_WIFI_3_0_ADRASTEA +#define CE_COUNT_MAX 12 +#else #define CE_COUNT_MAX 8 +#endif /* These numbers are selected so that the product is close to current higher limit of packets HIF services at one shot (1000) */ diff --git a/core/hif/src/adrastea_reg_def.h b/core/hif/src/adrastea_reg_def.h index 743d22ef5c28..a87884a784c5 100644 --- a/core/hif/src/adrastea_reg_def.h +++ b/core/hif/src/adrastea_reg_def.h @@ -2159,7 +2159,7 @@ struct hostdef_s adrastea_hostdef = { .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, - .d_HOST_CE_COUNT = 8, + .d_HOST_CE_COUNT = ADRASTEA_CE_COUNT, .d_ENABLE_MSI = 0, .d_MUX_ID_MASK = 0xf000, .d_TRANSACTION_ID_MASK = 0x0fff, diff --git a/core/hif/src/ce/ce_assignment.h b/core/hif/src/ce/ce_assignment.h index b493d55502cd..9ff907f23fbf 100644 --- a/core/hif/src/ce/ce_assignment.h +++ b/core/hif/src/ce/ce_assignment.h @@ -92,6 +92,12 @@ static struct CE_attr host_ce_config_wlan[] = { /* ce_diag, the Diagnostic Window */ { /* CE7 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, + /* Target to uMC */ + { /* CE8 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /*The following CEs are not being used yet */ + { /* CE9 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + { /* CE10 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + { /* CE11 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, }; static struct CE_pipe_config target_ce_config_wlan[] = { @@ -116,7 +122,11 @@ static struct CE_pipe_config target_ce_config_wlan[] = { { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, /* CE8 used only by IPA */ - { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,} + { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /*The following CEs are not being used yet*/ + { /* CE9 */ 9, PIPEDIR_IN, 0, 0, CE_ATTR_FLAGS, 0,}, + { /* CE10 */ 9, PIPEDIR_IN, 0, 0, CE_ATTR_FLAGS, 0,}, + { /* CE11 */ 9, PIPEDIR_IN, 0, 0, CE_ATTR_FLAGS, 0,}, }; static struct CE_attr host_ce_config_wlan_epping_poll[] = { diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index a898d0b63104..4b6c37bc7ccc 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1509,6 +1509,10 @@ ce_send_cb_register(struct CE_handle *copyeng, { struct CE_state *CE_state = (struct CE_state *)copyeng; + if (CE_state == NULL) { + pr_err("%s: Error CE state = NULL\n", __func__); + return; + } cdf_spin_lock(&CE_state->scn->target_lock); CE_state->send_cb = fn_ptr; CE_state->send_context = ce_send_context; @@ -1523,6 +1527,10 @@ ce_recv_cb_register(struct CE_handle *copyeng, { struct CE_state *CE_state = (struct CE_state *)copyeng; + if (CE_state == NULL) { + pr_err("%s: ERROR CE state = NULL\n", __func__); + return; + } cdf_spin_lock(&CE_state->scn->target_lock); CE_state->recv_cb = fn_ptr; CE_state->recv_context = CE_recv_context; -- cgit v1.2.3 From b925d7efccac892001fa0ebffa606d24c2498043 Mon Sep 17 00:00:00 2001 From: Sanjay Devnani Date: Thu, 12 Nov 2015 14:43:58 -0800 Subject: qcacld-3.0: enable srri/drri on ddr The SRRI/DRRI can be read from DDR instead of doing an actual hardware read. This mechanism is compiled out by default. Change-Id: I8fc6c8817b5958f3d00b47ccd3dba36b354097e8 CRs-Fixed: 932344 --- Kbuild | 1 + core/hif/inc/hif.h | 1 + core/hif/inc/regtable_ce.h | 5 +- core/hif/src/adrastea_reg_def.h | 31 +++++++-- core/hif/src/ce/ce_main.c | 150 +++++++++++++++++++++++++++++++++++++++- core/hif/src/ce/ce_reg.h | 92 +++++++++++++++++++----- core/hif/src/qca6180def.h | 4 +- 7 files changed, 255 insertions(+), 29 deletions(-) diff --git a/Kbuild b/Kbuild index 2f9098131c6b..44cd18ab92d2 100644 --- a/Kbuild +++ b/Kbuild @@ -909,6 +909,7 @@ endif ifeq (y,$(filter y,$(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) CDEFINES += -DQCA_WIFI_3_0_ADRASTEA CDEFINES += -DADRASTEA_SHADOW_REGISTERS +CDEFINES += -DADRASTEA_RRI_ON_DDR endif ifeq ($(CONFIG_WLAN_FASTPATH), y) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index dd2c89832867..ab99b62c1c1d 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -314,6 +314,7 @@ struct ol_softc { cdf_spinlock_t irq_lock; uint32_t ce_irq_summary; #endif + uint32_t *vaddr_rri_on_ddr; }; typedef enum { diff --git a/core/hif/inc/regtable_ce.h b/core/hif/inc/regtable_ce.h index e5f5a9f10cca..5261bac0b070 100644 --- a/core/hif/inc/regtable_ce.h +++ b/core/hif/inc/regtable_ce.h @@ -208,8 +208,8 @@ struct ce_reg_def { uint32_t d_HOST_IS_COPY_COMPLETE_MASK; uint32_t d_CE_WRAPPER_BASE_ADDRESS; uint32_t d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS; - uint32_t d_CE_WRAPPER_INDEX_BASE_LOW; - uint32_t d_CE_WRAPPER_INDEX_BASE_HIGH; + uint32_t d_CE_DDR_ADDRESS_FOR_RRI_LOW; + uint32_t d_CE_DDR_ADDRESS_FOR_RRI_HIGH; uint32_t d_HOST_IE_ADDRESS; uint32_t d_HOST_IE_COPY_COMPLETE_MASK; uint32_t d_SR_BA_ADDRESS; @@ -243,6 +243,7 @@ struct ce_reg_def { uint32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK; uint32_t d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB; uint32_t d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB; + uint32_t d_CE_CTRL1_IDX_UPD_EN_MASK; uint32_t d_CE_WRAPPER_DEBUG_OFFSET; uint32_t d_CE_WRAPPER_DEBUG_SEL_MSB; uint32_t d_CE_WRAPPER_DEBUG_SEL_LSB; diff --git a/core/hif/src/adrastea_reg_def.h b/core/hif/src/adrastea_reg_def.h index a87884a784c5..c7fa92c47a48 100644 --- a/core/hif/src/adrastea_reg_def.h +++ b/core/hif/src/adrastea_reg_def.h @@ -1190,6 +1190,9 @@ /* End auto-generated headers from register parser */ +#define A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_INDEX_BASE_LOW 0x0024C004 +#define A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_INDEX_BASE_HIGH 0x0024C008 + #define MISSING 0 #define MISSING_FOR_ADRASTEA MISSING #define ADRASTEA_PCIE_LOCAL_REG_BASE_ADDRESS 0 @@ -1385,9 +1388,21 @@ #define ADRASTEA_HOST_IS_COPY_COMPLETE_MASK \ ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IS__COPY_COMPLETE___M -#define ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 -#define ADRASTEA_CE_WRAPPER_INDEX_BASE_LOW 0x0004 -#define ADRASTEA_CE_WRAPPER_INDEX_BASE_HIGH 0x0008 +#define ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS_OFFSET \ + (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_HOST_INTERRUPT_SUMMARY\ + - ADRASTEA_CE_WRAPPER_BASE_ADDRESS) + +/* + * Base address where the CE source and destination ring read + * indices are written to be viewed by host. + */ + +#define ADRASTEA_CE_DDR_ADDRESS_FOR_RRI_LOW \ + (A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_INDEX_BASE_LOW\ + - ADRASTEA_CE_WRAPPER_BASE_ADDRESS) + +#define ADRASTEA_CE_DDR_ADDRESS_FOR_RRI_HIGH \ + (A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE_COMMON_WRAPPER_CE_WRAPPER_INDEX_BASE_HIGH - ADRASTEA_CE_WRAPPER_BASE_ADDRESS) #define ADRASTEA_HOST_IE_OFFSET (ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_HOST_IE\ - ADRASTEA_CE0_BASE_ADDRESS) @@ -2191,9 +2206,11 @@ struct ce_reg_def adrastea_ce_targetdef = { .d_HOST_IS_COPY_COMPLETE_MASK = ADRASTEA_HOST_IS_COPY_COMPLETE_MASK, .d_CE_WRAPPER_BASE_ADDRESS = ADRASTEA_CE_WRAPPER_BASE_ADDRESS, .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = - ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, - .d_CE_WRAPPER_INDEX_BASE_LOW = ADRASTEA_CE_WRAPPER_INDEX_BASE_LOW, - .d_CE_WRAPPER_INDEX_BASE_HIGH = ADRASTEA_CE_WRAPPER_INDEX_BASE_HIGH, + ADRASTEA_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS_OFFSET, + .d_CE_DDR_ADDRESS_FOR_RRI_LOW = + ADRASTEA_CE_DDR_ADDRESS_FOR_RRI_LOW, + .d_CE_DDR_ADDRESS_FOR_RRI_HIGH = + ADRASTEA_CE_DDR_ADDRESS_FOR_RRI_HIGH, .d_HOST_IE_ADDRESS = ADRASTEA_HOST_IE_OFFSET, .d_HOST_IE_COPY_COMPLETE_MASK = ADRASTEA_HOST_IE_COPY_COMPLETE_MASK, .d_SR_BA_ADDRESS = ADRASTEA_SR_BA_OFFSET, @@ -2233,6 +2250,8 @@ struct ce_reg_def adrastea_ce_targetdef = { ADRASTEA_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB, .d_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB = ADRASTEA_CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB, + .d_CE_CTRL1_IDX_UPD_EN_MASK = + ADRASTEA_A_WCSS_HM_A_WIFI_APB_1_A_WFSS_CE0_CE_CTRL1__IDX_UPD_EN___M, .d_CE_WRAPPER_DEBUG_OFFSET = ADRASTEA_CE_WRAPPER_DEBUG_OFFSET, .d_CE_WRAPPER_DEBUG_SEL_MSB = ADRASTEA_CE_WRAPPER_DEBUG_SEL_MSB, .d_CE_WRAPPER_DEBUG_SEL_LSB = ADRASTEA_CE_WRAPPER_DEBUG_SEL_LSB, diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index abeb6a38b7a0..4c0a162f4da9 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -77,6 +77,7 @@ static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info); static int hif_post_recv_buffers(struct ol_softc *scn); +static void hif_config_rri_on_ddr(struct ol_softc *scn); static void ce_poll_timeout(void *arg) { @@ -2244,6 +2245,8 @@ int hif_config_ce(hif_handle_t hif_hdl) #endif #endif + hif_config_rri_on_ddr(scn); + /* During CE initializtion */ scn->ce_count = HOST_CE_COUNT; A_TARGET_ACCESS_LIKELY(scn); @@ -2471,7 +2474,7 @@ u32 shadow_sr_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) addr = SHADOW_VALUE7; break; default: - printk("invalid CE ctrl_addr\n"); + HIF_ERROR("invalid CE ctrl_addr\n"); CDF_ASSERT(0); } @@ -2497,7 +2500,7 @@ u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) addr = SHADOW_VALUE20; break; default: - printk("invalid CE ctrl_addr\n"); + HIF_ERROR("invalid CE ctrl_addr\n"); CDF_ASSERT(0); } @@ -2627,3 +2630,146 @@ int hif_map_service_to_pipe(struct ol_softc *scn, uint16_t svc_id, return status; } + +#ifdef SHADOW_REG_DEBUG +inline uint32_t DEBUG_CE_SRC_RING_READ_IDX_GET(struct ol_softc *scn, + uint32_t CE_ctrl_addr) +{ + uint32_t read_from_hw, srri_from_ddr = 0; + + read_from_hw = A_TARGET_READ(scn, CE_ctrl_addr + CURRENT_SRRI_ADDRESS); + + srri_from_ddr = SRRI_FROM_DDR_ADDR(VADDR_FOR_CE(scn, CE_ctrl_addr)); + + if (read_from_hw != srri_from_ddr) { + HIF_ERROR("error: read from ddr = %d actual read from register = %d, CE_MISC_INT_STATUS_GET = 0x%x\n", + srri_from_ddr, read_from_hw, + CE_MISC_INT_STATUS_GET(scn, CE_ctrl_addr)); + CDF_ASSERT(0); + } + return srri_from_ddr; +} + + +inline uint32_t DEBUG_CE_DEST_RING_READ_IDX_GET(struct ol_softc *scn, + uint32_t CE_ctrl_addr) +{ + uint32_t read_from_hw, drri_from_ddr = 0; + + read_from_hw = A_TARGET_READ(scn, CE_ctrl_addr + CURRENT_DRRI_ADDRESS); + + drri_from_ddr = DRRI_FROM_DDR_ADDR(VADDR_FOR_CE(scn, CE_ctrl_addr)); + + if (read_from_hw != drri_from_ddr) { + HIF_ERROR("error: read from ddr = %d actual read from register = %d, CE_MISC_INT_STATUS_GET = 0x%x\n", + drri_from_ddr, read_from_hw, + CE_MISC_INT_STATUS_GET(scn, CE_ctrl_addr)); + CDF_ASSERT(0); + } + return drri_from_ddr; +} + +#endif + +/** + * hif_get_src_ring_read_index(): Called to get the SRRI + * + * @scn: ol_softc pointer + * @CE_ctrl_addr: base address of the CE whose RRI is to be read + * + * This function returns the SRRI to the caller. For CEs that + * dont have interrupts enabled, we look at the DDR based SRRI + * + * Return: SRRI + */ +inline unsigned int hif_get_src_ring_read_index(struct ol_softc *scn, + uint32_t CE_ctrl_addr) +{ + struct CE_attr attr; + + attr = host_ce_config[COPY_ENGINE_ID(CE_ctrl_addr)]; + if (attr.flags & CE_ATTR_DISABLE_INTR) + return CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr); + else + return A_TARGET_READ(scn, + (CE_ctrl_addr) + CURRENT_SRRI_ADDRESS); +} + +/** + * hif_get_dst_ring_read_index(): Called to get the DRRI + * + * @scn: ol_softc pointer + * @CE_ctrl_addr: base address of the CE whose RRI is to be read + * + * This function returns the DRRI to the caller. For CEs that + * dont have interrupts enabled, we look at the DDR based DRRI + * + * Return: DRRI + */ +inline unsigned int hif_get_dst_ring_read_index(struct ol_softc *scn, + uint32_t CE_ctrl_addr) +{ + struct CE_attr attr; + + attr = host_ce_config[COPY_ENGINE_ID(CE_ctrl_addr)]; + + if (attr.flags & CE_ATTR_DISABLE_INTR) + return CE_DEST_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr); + else + return A_TARGET_READ(scn, + (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS); +} + +#ifdef ADRASTEA_RRI_ON_DDR +/** + * hif_config_rri_on_ddr(): Configure the RRI on DDR mechanism + * + * @scn: ol_softc pointer + * + * This function allocates non cached memory on ddr and sends + * the physical address of this memory to the CE hardware. The + * hardware updates the RRI on this particular location. + * + * Return: None + */ +static inline void hif_config_rri_on_ddr(struct ol_softc *scn) +{ + unsigned int i; + cdf_dma_addr_t paddr_rri_on_ddr; + uint32_t high_paddr, low_paddr; + scn->vaddr_rri_on_ddr = + (uint32_t *)cdf_os_mem_alloc_consistent(scn->cdf_dev, + (CE_COUNT*sizeof(uint32_t)), &paddr_rri_on_ddr, 0); + + low_paddr = BITS0_TO_31(paddr_rri_on_ddr); + high_paddr = BITS32_TO_35(paddr_rri_on_ddr); + + HIF_ERROR("%s using srri and drri from DDR\n", __func__); + + WRITE_CE_DDR_ADDRESS_FOR_RRI_LOW(scn, low_paddr); + WRITE_CE_DDR_ADDRESS_FOR_RRI_HIGH(scn, high_paddr); + + for (i = 0; i < CE_COUNT; i++) + CE_IDX_UPD_EN_SET(scn, CE_BASE_ADDRESS(i)); + + cdf_mem_zero(scn->vaddr_rri_on_ddr, CE_COUNT*sizeof(uint32_t)); + + return; +} +#else + +/** + * hif_config_rri_on_ddr(): Configure the RRI on DDR mechanism + * + * @scn: ol_softc pointer + * + * This is a dummy implementation for platforms that don't + * support this functionality. + * + * Return: None + */ +static inline void hif_config_rri_on_ddr(struct ol_softc *scn) +{ + return; +} +#endif diff --git a/core/hif/src/ce/ce_reg.h b/core/hif/src/ce/ce_reg.h index cb7439421dbb..5e4c815d3b8e 100644 --- a/core/hif/src/ce/ce_reg.h +++ b/core/hif/src/ce/ce_reg.h @@ -28,6 +28,9 @@ #ifndef __CE_REG_H__ #define __CE_REG_H__ +#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \ + - CE0_BASE_ADDRESS)/(CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) + #define DST_WR_INDEX_ADDRESS (scn->target_ce_def->d_DST_WR_INDEX_ADDRESS) #define SRC_WATERMARK_ADDRESS (scn->target_ce_def->d_SRC_WATERMARK_ADDRESS) #define SRC_WATERMARK_LOW_MASK (scn->target_ce_def->d_SRC_WATERMARK_LOW_MASK) @@ -102,10 +105,10 @@ #define CE_WRAPPER_BASE_ADDRESS (scn->target_ce_def->d_CE_WRAPPER_BASE_ADDRESS) #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS \ (scn->target_ce_def->d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS) -#define CE_WRAPPER_INDEX_BASE_LOW \ - (scn->target_ce_def->d_CE_WRAPPER_INDEX_BASE_LOW) -#define CE_WRAPPER_INDEX_BASE_HIGH \ - (scn->target_ce_def->d_CE_WRAPPER_INDEX_BASE_HIGH) +#define CE_DDR_ADDRESS_FOR_RRI_LOW \ + (scn->target_ce_def->d_CE_DDR_ADDRESS_FOR_RRI_LOW) +#define CE_DDR_ADDRESS_FOR_RRI_HIGH \ + (scn->target_ce_def->d_CE_DDR_ADDRESS_FOR_RRI_HIGH) #define HOST_IE_COPY_COMPLETE_MASK \ (scn->target_ce_def->d_HOST_IE_COPY_COMPLETE_MASK) #define SR_BA_ADDRESS (scn->target_ce_def->d_SR_BA_ADDRESS) @@ -143,6 +146,7 @@ #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ (scn->target_ce_def->d_CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) #define CE_CTRL1_DMAX_LENGTH_LSB (scn->target_ce_def->d_CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_IDX_UPD_EN (scn->target_ce_def->d_CE_CTRL1_IDX_UPD_EN_MASK) #define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK \ (scn->target_ce_def->d_CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) #define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK \ @@ -243,8 +247,52 @@ #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) +uint32_t DEBUG_CE_SRC_RING_READ_IDX_GET(struct ol_softc *scn, + uint32_t CE_ctrl_addr); +uint32_t DEBUG_CE_DEST_RING_READ_IDX_GET(struct ol_softc *scn, + uint32_t CE_ctrl_addr); + +#define BITS0_TO_31(val) ((uint32_t)((uint64_t)(paddr_rri_on_ddr)\ + & (uint64_t)(0xFFFFFFFF))) +#define BITS32_TO_35(val) ((uint32_t)(((uint64_t)(paddr_rri_on_ddr)\ + & (uint64_t)(0xF00000000))>>32)) + +#define VADDR_FOR_CE(scn, CE_ctrl_addr)\ + ((uint32_t *)((uint64_t)(scn->vaddr_rri_on_ddr) + \ + COPY_ENGINE_ID(CE_ctrl_addr)*sizeof(uint32_t))) + +#define SRRI_FROM_DDR_ADDR(addr) ((*(addr)) & 0xFFFF) +#define DRRI_FROM_DDR_ADDR(addr) (((*(addr))>>16) & 0xFFFF) + +#ifdef SHADOW_REG_DEBUG +#define CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ + DEBUG_CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr) +#define CE_DEST_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ + DEBUG_CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr) +#else +#define CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ + SRRI_FROM_DDR_ADDR(VADDR_FOR_CE(scn, CE_ctrl_addr)) +#define CE_DEST_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ + DRRI_FROM_DDR_ADDR(VADDR_FOR_CE(scn, CE_ctrl_addr)) +#endif + + +unsigned int hif_get_src_ring_read_index(struct ol_softc *scn, + uint32_t CE_ctrl_addr); +unsigned int hif_get_dst_ring_read_index(struct ol_softc *scn, + uint32_t CE_ctrl_addr); + +#ifdef ADRASTEA_RRI_ON_DDR +#define CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ + hif_get_src_ring_read_index(scn, CE_ctrl_addr) +#define CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ + hif_get_dst_ring_read_index(scn, CE_ctrl_addr) +#else #define CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr) \ A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_SRRI_ADDRESS) +#define CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ + A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS) +#endif #define CE_SRC_RING_BASE_ADDR_SET(scn, CE_ctrl_addr, addr) \ A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_BA_ADDRESS, (addr)) @@ -264,6 +312,11 @@ CE_CTRL1_ADDRESS) & ~CE_CTRL1_DMAX_LENGTH_MASK) | \ CE_CTRL1_DMAX_LENGTH_SET(n)) +#define CE_IDX_UPD_EN_SET(scn, CE_ctrl_addr) \ + A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS, \ + (A_TARGET_READ(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS) \ + | CE_CTRL1_IDX_UPD_EN)) + #define CE_CMD_REGISTER_GET(scn, CE_ctrl_addr) \ A_TARGET_READ(scn, (CE_ctrl_addr) + CE_CMD_REGISTER) @@ -299,8 +352,6 @@ & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) | \ CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n)) -#define CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr) \ - A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS) #define CE_DEST_RING_BASE_ADDR_SET(scn, CE_ctrl_addr, addr) \ A_TARGET_WRITE(scn, (CE_ctrl_addr) + DR_BA_ADDRESS, (addr)) @@ -384,14 +435,6 @@ #define CE_ENGINE_INT_STATUS_CLEAR(scn, CE_ctrl_addr, mask) \ A_TARGET_WRITE(scn, (CE_ctrl_addr) + HOST_IS_ADDRESS, (mask)) -#define CE_WRAPPER_INDEX_BASE_LOW_SET(scn, n) \ - A_TARGET_WRITE(scn, \ - CE_WRAPPER_INDEX_BASE_LOW + CE_WRAPPER_BASE_ADDRESS, n) - -#define CE_WRAPPER_INDEX_BASE_HIGH_SET(scn, n) \ - A_TARGET_WRITE(scn, \ - CE_WRAPPER_INDEX_BASE_HIGH + CE_WRAPPER_BASE_ADDRESS, n) - #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 | \ @@ -424,6 +467,24 @@ A_TARGET_READ(scn, CE_WRAPPER_BASE_ADDRESS + \ CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) +#define READ_CE_DDR_ADDRESS_FOR_RRI_LOW(scn) \ + (A_TARGET_READ(scn, \ + CE_WRAPPER_BASE_ADDRESS + CE_DDR_ADDRESS_FOR_RRI_LOW)) + +#define READ_CE_DDR_ADDRESS_FOR_RRI_HIGH(scn) \ + (A_TARGET_READ(scn, \ + CE_WRAPPER_BASE_ADDRESS + CE_DDR_ADDRESS_FOR_RRI_HIGH)) + +#define WRITE_CE_DDR_ADDRESS_FOR_RRI_LOW(scn, val) \ + (A_TARGET_WRITE(scn, \ + CE_WRAPPER_BASE_ADDRESS + CE_DDR_ADDRESS_FOR_RRI_LOW, \ + val)) + +#define WRITE_CE_DDR_ADDRESS_FOR_RRI_HIGH(scn, val) \ + (A_TARGET_WRITE(scn, \ + CE_WRAPPER_BASE_ADDRESS + CE_DDR_ADDRESS_FOR_RRI_HIGH, \ + val)) + /*Macro to increment CE packet errors*/ #define OL_ATH_CE_PKT_ERROR_COUNT_INCR(_scn, _ce_ecode) \ do { if (_ce_ecode == CE_RING_DELTA_FAIL) \ @@ -442,9 +503,6 @@ #define NUM_SHADOW_REGISTERS 24 -#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \ - - CE0_BASE_ADDRESS)/(CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) - u32 shadow_sr_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr); u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr); #define CE_SRC_RING_WRITE_IDX_SET(scn, CE_ctrl_addr, n) \ diff --git a/core/hif/src/qca6180def.h b/core/hif/src/qca6180def.h index cdfc2a325665..155f4d8e9a88 100644 --- a/core/hif/src/qca6180def.h +++ b/core/hif/src/qca6180def.h @@ -899,8 +899,8 @@ struct ce_reg_def qca6180_ce_targetdef = { .d_CE_WRAPPER_BASE_ADDRESS = QCA6180_CE_WRAPPER_BASE_ADDRESS, .d_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS = QCA6180_CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS, - .d_CE_WRAPPER_INDEX_BASE_LOW = QCA6180_CE_WRAPPER_INDEX_BASE_LOW, - .d_CE_WRAPPER_INDEX_BASE_HIGH = QCA6180_CE_WRAPPER_INDEX_BASE_HIGH, + .d_CE_DDR_ADDRESS_FOR_RRI_LOW = QCA6180_CE_WRAPPER_INDEX_BASE_LOW, + .d_CE_DDR_ADDRESS_FOR_RRI_HIGH = QCA6180_CE_WRAPPER_INDEX_BASE_HIGH, .d_HOST_IE_ADDRESS = QCA6180_HOST_IE_ADDRESS, .d_HOST_IE_COPY_COMPLETE_MASK = QCA6180_HOST_IE_COPY_COMPLETE_MASK, .d_SR_BA_ADDRESS = QCA6180_SR_BA_ADDRESS, -- cgit v1.2.3 From c42f2dec12e25c11ffb2885b261e7e5eae4b0b21 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Mon, 2 Nov 2015 10:16:05 -0800 Subject: qcacld-3.0: Report roaming events to diag module In case of LFR3.0, report the critical roaming events such as receiving the roam synch indication from firmware, sending the roam synch complete to the firmware, sending Hand Over failure event to the firmware to the DIAG modules for better debug capabilities. CRs-Fixed: 938002 Change-Id: Icfb4972d59dc3b734ed5af37d70834fea470d741 --- core/sme/inc/csr_internal.h | 14 ++++++++++- core/sme/src/csr/csr_api_roam.c | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index a653df29f9d7..f335b0d99c57 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -265,6 +265,9 @@ typedef enum { eCSR_REASON_DISASSOC, eCSR_REASON_DEAUTH, eCSR_REASON_HANDOFF, + eCSR_REASON_ROAM_SYNCH_IND, + eCSR_REASON_ROAM_SYNCH_CNF, + eCSR_REASON_ROAM_HO_FAIL, } eCsrDiagWlanStatusEventReason; @@ -1363,7 +1366,16 @@ csr_roam_modify_add_ies(tpAniSirGlobal pMac, CDF_STATUS csr_roam_update_add_ies(tpAniSirGlobal pMac, tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType); - +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +void csr_roaming_report_diag_event(tpAniSirGlobal mac_ctx, + roam_offload_synch_ind *roam_synch_ind_ptr, + eCsrDiagWlanStatusEventReason reason); +#else +static inline void csr_roaming_report_diag_event(tpAniSirGlobal mac_ctx, + roam_offload_synch_ind *roam_synch_ind_ptr, + eCsrDiagWlanStatusEventReason reason) +{} +#endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD void csr_process_roam_offload_synch_ind(tHalHandle hHal, roam_offload_synch_ind * roam_synch_ind_ptr); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 45b2b495ba20..2860c034a1ed 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -5572,6 +5572,7 @@ CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, uint8_t sessionI false; return CDF_STATUS_E_FAILURE; } + csr_roaming_report_diag_event(pMac, NULL, eCSR_REASON_ROAM_SYNCH_CNF); pSession->roamOffloadSynchParams.bRoamSynchInProgress = false; return CDF_STATUS_SUCCESS; } @@ -18377,6 +18378,52 @@ csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx, return status; } +#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR +/** + * csr_roaming_report_diag_event() - Diag events for LFR3 + * @mac_ctx: MAC context + * @roam_synch_ind_ptr: Roam Synch Indication Pointer + * @reason: Reason for this event to happen + * + * The major events in the host for LFR3 roaming such as + * roam synch indication, roam synch completion and + * roam synch handoff fail will be indicated to the + * diag framework using this API. + * + * Return: None + */ +void csr_roaming_report_diag_event(tpAniSirGlobal mac_ctx, + roam_offload_synch_ind *roam_synch_ind_ptr, + eCsrDiagWlanStatusEventReason reason) +{ + WLAN_HOST_DIAG_EVENT_DEF(roam_connection, + host_event_wlan_status_payload_type); + cdf_mem_set(&roam_connection, + sizeof(host_event_wlan_status_payload_type), 0); + switch (reason) { + case eCSR_REASON_ROAM_SYNCH_IND: + roam_connection.eventId = eCSR_WLAN_STATUS_CONNECT; + if (roam_synch_ind_ptr) { + roam_connection.rssi = roam_synch_ind_ptr->rssi; + roam_connection.channel = + cds_freq_to_chan(roam_synch_ind_ptr->chan_freq); + } + break; + case eCSR_REASON_ROAM_SYNCH_CNF: + roam_connection.eventId = eCSR_WLAN_STATUS_CONNECT; + break; + case eCSR_REASON_ROAM_HO_FAIL: + roam_connection.eventId = eCSR_WLAN_STATUS_DISCONNECT; + break; + default: + sms_log(mac_ctx, LOGE, + FL("LFR3: Unsupported reason %d"), reason); + return; + } + roam_connection.reason = reason; + WLAN_HOST_DIAG_EVENT_REPORT(&roam_connection, EVENT_WLAN_STATUS); +} +#endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD /*---------------------------------------------------------------------------- @@ -18405,6 +18452,9 @@ void csr_process_roam_offload_synch_ind(tHalHandle hHal, "fail to save roam offload AP to scan cache"); goto err_synch_rsp; } + + csr_roaming_report_diag_event(pMac, roam_synch_ind_ptr, + eCSR_REASON_ROAM_SYNCH_IND); session_ptr->roamOffloadSynchParams.rssi = roam_synch_ind_ptr->rssi; session_ptr->roamOffloadSynchParams.roamReason = roam_synch_ind_ptr->roamReason; @@ -18489,6 +18539,8 @@ void csr_process_ho_fail_ind(tpAniSirGlobal pMac, void *pMsgBuf) return; } csr_roam_synch_clean_up(pMac, sessionId); + csr_roaming_report_diag_event(pMac, NULL, + eCSR_REASON_ROAM_HO_FAIL); CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "LFR3:Issue Disconnect on session %d", sessionId); csr_roam_disconnect(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); -- cgit v1.2.3 From a7776a9fdde47dc79e146c6f92adfe1d507f7ffc Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 3 Nov 2015 11:44:03 -0800 Subject: qcacld-3.0: Support to configure RM enabled capability IE qcacld-2.0 to qcacld-3.0 propagation Add support to configure RM enabled capbility information element through INI. Using the introduced INI config option(rm_capability), we can set or unset any bit in the IE. Default value for the config parameter is set based on rrmInitialize routine. Change-Id: Ia2a4352760db77ab71dad4757eb603d7539ffefa CRs-Fixed: 918667 --- core/hdd/inc/wlan_hdd_cfg.h | 17 +++ core/hdd/src/wlan_hdd_cfg.c | 119 ++++++++++++-------- core/mac/inc/sir_api.h | 9 ++ core/mac/src/pe/include/rrm_api.h | 13 ++- core/mac/src/pe/include/rrm_global.h | 123 +++++++++++++++++++++ core/mac/src/pe/lim/lim_process_cfg_updates.c | 3 - core/mac/src/pe/lim/lim_process_sme_req_messages.c | 36 ++---- core/mac/src/pe/rrm/rrm_api.c | 73 ++++-------- core/mac/src/sys/legacy/src/utils/src/parser_api.c | 5 + core/sme/inc/sme_api.h | 2 +- core/sme/inc/sme_rrm_api.h | 2 +- core/sme/inc/sme_rrm_internal.h | 7 +- core/sme/src/csr/csr_api_roam.c | 5 + core/sme/src/rrm/sme_rrm.c | 10 +- 14 files changed, 285 insertions(+), 139 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 0e2e2fd236c3..198a5a0e3675 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -818,6 +818,18 @@ typedef enum { #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" @@ -2808,6 +2820,8 @@ struct hdd_config { uint8_t nInChanMeasMaxDuration; uint8_t nOutChanMeasMaxDuration; uint16_t nRrmRandnIntvl; + /* length includes separator */ + char rm_capability[3 * DOT11F_IE_RRMENABLEDCAP_MAX_LEN]; #endif #ifdef WLAN_FEATURE_VOWIFI_11R @@ -3442,6 +3456,9 @@ void hdd_dfs_indicate_radar(void *context, void *param); CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, uint8_t intArrayMaxLen); +CDF_STATUS hdd_hex_string_to_u16_array(char *str, uint16_t *int_array, + uint8_t *len, uint8_t int_array_max_len); + void hdd_cfg_print(hdd_context_t *pHddCtx); CDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss); diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 1ba3b80c8444..da08ff7e621e 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1333,6 +1333,11 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, + struct hdd_config, rm_capability, + VAR_FLAGS_OPTIONAL, + (void *) CFG_RM_CAPABILITY_DEFAULT), #endif #ifdef WLAN_FEATURE_VOWIFI_11R @@ -5403,40 +5408,85 @@ static void hdd_set_fine_time_meas_cap(hdd_context_t *hdd_ctx, } /** - * hdd_string_to_u8_array() - scan the string and convert to u8 array - * @str: the pointer to the string - * @intArray: the pointer of buffer to store the u8 value - * @len: size of the buffer + * 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: CDF_STATUS_SUCCESS if the conversion is done, - * otherwise CDF_STATUS_E_INVAL + * Return: CDF_STATUS */ -CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, - uint8_t intArrayMaxLen) + +static CDF_STATUS hdd_convert_string_to_array(char *str, uint8_t *array, + uint8_t *len, uint8_t array_max_len, bool to_hex) { - char *s = str; + char *format, *s = str; - if (str == NULL || intArray == NULL || len == NULL) { + if (str == NULL || array == NULL || len == NULL) return CDF_STATUS_E_INVAL; - } - *len = 0; - while ((s != NULL) && (*len < intArrayMaxLen)) { + format = (to_hex) ? "%02x" : "%d"; + + *len = 0; + while ((s != NULL) && (*len < array_max_len)) { int val; - /* Increment length only if sscanf succesfully extracted one element. - * Any other return value means error. Ignore it. - */ - if (sscanf(s, "%d", &val) == 1) { - intArray[*len] = (uint8_t) 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] = (uint8_t) val; *len += 1; } + s = strpbrk(s, ","); if (s) s++; } return CDF_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: CDF_STATUS + */ +CDF_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: CDF_STATUS + */ +CDF_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); } /** @@ -5636,31 +5686,6 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx) } #if defined WLAN_FEATURE_VOWIFI - if (sme_cfg_set_int - (pHddCtx->hHal, WNI_CFG_RRM_ENABLED, pConfig->fRrmEnable) - == CDF_STATUS_E_FAILURE) { - fStatus = false; - hddLog(LOGE, - "Could not pass on WNI_CFG_RRM_ENABLE to CFG"); - } - - if (sme_cfg_set_int - (pHddCtx->hHal, WNI_CFG_RRM_OPERATING_CHAN_MAX, - pConfig->nInChanMeasMaxDuration) == CDF_STATUS_E_FAILURE) { - fStatus = false; - hddLog(LOGE, - "Could not pass on WNI_CFG_RRM_OPERATING_CHAN_MAX to CFG"); - } - - if (sme_cfg_set_int - (pHddCtx->hHal, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, - pConfig->nOutChanMeasMaxDuration) == - CDF_STATUS_E_FAILURE) { - fStatus = false; - hddLog(LOGE, - "Could not pass on WNI_CFG_RRM_OUT_CHAN_MAX to CFG"); - } - if (sme_cfg_set_int (pHddCtx->hHal, WNI_CFG_MCAST_BCAST_FILTER_SETTING, pConfig->mcastBcastFilterSetting) == CDF_STATUS_E_FAILURE) @@ -6215,6 +6240,7 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) { CDF_STATUS status = CDF_STATUS_SUCCESS; tSmeConfigParams *smeConfig; + uint8_t rrm_capab_len; struct hdd_config *pConfig = pHddCtx->config; @@ -6299,8 +6325,11 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) smeConfig->csrConfig.WMMSupportMode = pConfig->WmmMode; #if defined WLAN_FEATURE_VOWIFI - smeConfig->rrmConfig.rrmEnabled = pConfig->fRrmEnable; - smeConfig->rrmConfig.maxRandnInterval = pConfig->nRrmRandnIntvl; + 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. diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index ba16dd997141..7f1f5232bb0c 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -278,6 +278,14 @@ typedef enum eSirResultCodes { 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_TAURUS = 0, @@ -973,6 +981,7 @@ typedef struct sSirSmeJoinReq { tAniBool isWMEenabled; tAniBool isQosEnabled; tAniBool isOSENConnection; + struct rrm_config_param rrm_config; tAniBool spectrumMgtIndicator; tSirMacPowerCapInfo powerCap; tSirSupChnl supportedChannels; diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h index 05466c00423c..849fa5c17919 100644 --- a/core/mac/src/pe/include/rrm_api.h +++ b/core/mac/src/pe/include/rrm_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -38,6 +38,7 @@ #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 @@ -86,8 +87,6 @@ extern void rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, extern tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry); -extern void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry); - extern void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF); extern void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2]); @@ -101,4 +100,12 @@ rrm_process_neighbor_report_req(tpAniSirGlobal pMac, extern tSirRetStatus rrm_process_beacon_report_xmit(tpAniSirGlobal pMac, tpSirBeaconReportXmitInd pBcnReport); +extern void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, + tpSirSmeJoinReq join_req); +#else +void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, + tpSirSmeJoinReq join_req) +{ +} +#endif #endif diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h index 053848d1f0c5..a1db83544444 100644 --- a/core/mac/src/pe/include/rrm_global.h +++ b/core/mac/src/pe/include/rrm_global.h @@ -225,4 +225,127 @@ typedef struct sRrmPEContext { #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/core/mac/src/pe/lim/lim_process_cfg_updates.c b/core/mac/src/pe/lim/lim_process_cfg_updates.c index e1a645e1ac8c..ae1cf2a3c804 100644 --- a/core/mac/src/pe/lim/lim_process_cfg_updates.c +++ b/core/mac/src/pe/lim/lim_process_cfg_updates.c @@ -641,8 +641,5 @@ static void lim_update_config(tpAniSirGlobal pMac, tpPESession psessionEntry) } pMac->lim.gLimAssocStaLimit = (uint16_t) val; -#if defined WLAN_FEATURE_VOWIFI - rrm_update_config(pMac, psessionEntry); -#endif PELOG1(lim_log(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));) } diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index b06e32d060fa..6bae1ccd9b32 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -56,12 +56,10 @@ #include "lim_api.h" #include "wmm_apsd.h" #include "sir_mac_prot_def.h" +#include "rrm_api.h" #include "sap_api.h" -#if defined WLAN_FEATURE_VOWIFI -#include "rrm_api.h" -#endif #if defined WLAN_FEATURE_VOWIFI_11R #include @@ -1575,23 +1573,6 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) #endif /* FEATURE_WLAN_DIAG_SUPPORT */ lim_log(mac_ctx, LOG1, FL("Received SME_JOIN_REQ")); -#ifdef WLAN_FEATURE_VOWIFI - /* - * Need to read the CFG here itself as this is - * used in limExtractAPCapability() below. - * This CFG is actually read in rrm_update_config() - * which is called later. Because this is not - * read, RRM related path before calling rrm_update_config() - * is not getting executed causing issues - * like not honoring power constraint on 1st association - * after driver loading. - */ - if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RRM_ENABLED, &val) != - eSIR_SUCCESS) - lim_log(mac_ctx, LOGP, FL("cfg get rrm enabled failed")); - mac_ctx->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; - val = 0; -#endif /* WLAN_FEATURE_VOWIFI */ /* * Expect Join request in idle state. @@ -1624,9 +1605,16 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) goto end; } + /* + * Update the capability here itself as this is used in + * lim_extract_ap_capability() below. If not updated issues + * like not honoring power constraint on 1st association after + * driver loading might occur. + */ + lim_update_rrm_capability(mac_ctx, sme_join_req); + bss_desc = sme_join_req->bssDescription; /* check for the existence of start BSS session */ - session = pe_find_session_by_bssid(mac_ctx, bss_desc.bssId, &session_id); @@ -4497,10 +4485,10 @@ void __lim_process_report_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) rrm_process_neighbor_report_req(pMac, pMsg->bodyptr); break; case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: - { rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr); - } - break; + break; + default: + lim_log(pMac, LOGE, FL("Invalid msg type:%d"), pMsg->type); } #endif } diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index 5b85bf9a73c8..3f2f96f26c4f 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -1334,57 +1334,6 @@ tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry) return &pMac->rrm.rrmPEContext.rrmEnabledCaps; } -/* -------------------------------------------------------------------- */ -/** - * rrm_update_config - * - * FUNCTION: - * Update the configuration. This is called from lim_update_config. - * - * LOGIC: - * - * ASSUMPTIONS: - * - * NOTE: - * - * @param pSessionEntry - * @return pointer to tRRMCaps - */ -void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry) -{ - uint32_t val; - tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; - - if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) { - lim_log(pMac, LOGP, FL("cfg get rrm enabled failed")); - return; - } - pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; - - if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_OPERATING_CHAN_MAX, &val) != - eSIR_SUCCESS) { - lim_log(pMac, LOGP, - FL - ("cfg get rrm operating channel max measurement duration failed")); - return; - } - pRRMCaps->operatingChanMax = (uint8_t) val; - - if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, &val) != - eSIR_SUCCESS) { - lim_log(pMac, LOGP, - FL - ("cfg get rrm non-operating channel max measurement duration failed")); - return; - } - pRRMCaps->nonOperatingChanMax = (uint8_t) val; - - lim_log(pMac, LOG1, - "RRM enabled = %d OperatingChanMax = %d NonOperatingMax = %d", - pMac->rrm.rrmPEContext.rrmEnable, - pRRMCaps->operatingChanMax, pRRMCaps->nonOperatingChanMax); -} - /* -------------------------------------------------------------------- */ /** * rrm_initialize @@ -1488,8 +1437,30 @@ void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr); break; + default: + lim_log(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; + cdf_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps, + &join_req->rrm_config.rm_capability, + RMENABLEDCAP_MAX_LEN); + + return; +} + #endif diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 16bd125f1f88..3062e7561d05 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -5492,6 +5492,7 @@ tSirRetStatus populate_dot11f_rrm_ie(tpAniSirGlobal pMac, tpPESession psessionEntry) { tpRRMCaps pRrmCaps; + uint8_t *bytes; pRrmCaps = rrm_get_capabilities(pMac, psessionEntry); @@ -5527,6 +5528,10 @@ tSirRetStatus populate_dot11f_rrm_ie(tpAniSirGlobal pMac, pDot11f->lci_capability = pRrmCaps->lci_capability; pDot11f->reserved = pRrmCaps->reserved; + bytes = (uint8_t *) pDot11f + 1; /* ignore present field */ + lim_log(pMac, LOG1, FL("RRM Enabled Cap IE: %02x %02x %02x %02x %02x"), + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]); + pDot11f->present = 1; return eSIR_SUCCESS; } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index e81aac929972..43a6e8d8b1d9 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -95,7 +95,7 @@ typedef void (*hdd_ftm_msg_processor)(void *); typedef struct _smeConfigParams { tCsrConfigParam csrConfig; #if defined WLAN_FEATURE_VOWIFI - tRrmConfigParam rrmConfig; + struct rrm_config_param rrmConfig; #endif #if defined FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; diff --git a/core/sme/inc/sme_rrm_api.h b/core/sme/inc/sme_rrm_api.h index 743c77e8b23a..d0098447014a 100644 --- a/core/sme/inc/sme_rrm_api.h +++ b/core/sme/inc/sme_rrm_api.h @@ -52,7 +52,7 @@ CDF_STATUS rrm_close(tpAniSirGlobal pMac); CDF_STATUS rrm_ready(tpAniSirGlobal pMac); CDF_STATUS rrm_open(tpAniSirGlobal pMac); CDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, - tpRrmConfigParam pRrmConfig); + struct rrm_config_param *rrm_config); CDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t sessionId, tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo); diff --git a/core/sme/inc/sme_rrm_internal.h b/core/sme/inc/sme_rrm_internal.h index 76415d5c84ff..e3926374f702 100644 --- a/core/sme/inc/sme_rrm_internal.h +++ b/core/sme/inc/sme_rrm_internal.h @@ -46,11 +46,6 @@ /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ -typedef struct sRrmConfigParam { - uint8_t rrmEnabled; - uint8_t maxRandnInterval; -} tRrmConfigParam, *tpRrmConfigParam; - typedef struct sRrmNeighborReportDesc { tListElem List; tSirNeighborBssDescription *pNeighborBssDescription; @@ -88,7 +83,7 @@ typedef struct sRrmSMEContext { uint16_t randnIntvl; uint16_t duration[SIR_ESE_MAX_MEAS_IE_REQS]; uint8_t measMode[SIR_ESE_MAX_MEAS_IE_REQS]; - tRrmConfigParam rrmConfig; + struct rrm_config_param rrmConfig; cdf_mc_timer_t IterMeasTimer; tDblLinkList neighborReportCache; tRrmNeighborRequestControlInfo neighborReqControlInfo; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 2860c034a1ed..22df06520af6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -13976,6 +13976,11 @@ CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, else csr_join_req->isOSENConnection = false; + /* Fill rrm config parameters */ + cdf_mem_copy(&csr_join_req->rrm_config, + &pMac->rrm.rrmSmeContext.rrmConfig, + sizeof(struct rrm_config_param)); + pAP_capabilityInfo = (tSirMacCapabilityInfo *) &pBssDescription->capabilityInfo; diff --git a/core/sme/src/rrm/sme_rrm.c b/core/sme/src/rrm/sme_rrm.c index a68f71c09d68..88168bf5afc6 100644 --- a/core/sme/src/rrm/sme_rrm.c +++ b/core/sme/src/rrm/sme_rrm.c @@ -906,7 +906,7 @@ CDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, void *pMsg pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass; pSmeRrmContext->randnIntvl = CDF_MAX(pBeaconReq->randomizationInterval, - pSmeRrmContext->rrmConfig.maxRandnInterval); + pSmeRrmContext->rrmConfig.max_randn_interval); pSmeRrmContext->currentIndex = 0; pSmeRrmContext->msgSource = pBeaconReq->msgSource; cdf_mem_copy((uint8_t *) &pSmeRrmContext->measMode, @@ -1357,7 +1357,7 @@ CDF_STATUS rrm_open(tpAniSirGlobal pMac) tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; - pSmeRrmContext->rrmConfig.maxRandnInterval = 50; /* ms */ + pSmeRrmContext->rrmConfig.max_randn_interval = 50; /* ms */ cdf_status = cdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer, CDF_TIMER_TYPE_SW, @@ -1491,10 +1491,10 @@ CDF_STATUS rrm_ready(tpAniSirGlobal pMac) ---------------------------------------------------------------------------*/ CDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, - tpRrmConfigParam pRrmConfig) + struct rrm_config_param *rrm_config) { - cdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, pRrmConfig, - sizeof(tRrmConfigParam)); + cdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, rrm_config, + sizeof(struct rrm_config_param)); return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From 3e032e9a3d777539f6a82fc7365468051fa93386 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 3 Nov 2015 11:49:03 -0800 Subject: qcacld-3.0: Set RM capability independent of AP's capability qcacld-2.0 to qcacld-3.0 propagation Remove check for AP's capability information to set station's radio measurement(RM) capability in Capability Information element. Change-Id: I6047d4dec19e7cd32d6733e4da773875bbbb31aa CRs-Fixed: 924420 --- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 9 +++++---- core/mac/src/pe/lim/lim_send_management_frames.c | 11 +++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index f256fb2fadb0..5a756e77cd61 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -436,10 +436,11 @@ void lim_send_mlm_assoc_req(tpAniSirGlobal mac_ctx, */ caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK); - /* Clear rrm bit if AP doesn't support it */ - if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo - & LIM_RRM_BIT_MASK)) - caps &= (~LIM_RRM_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 (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo & diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 353f4c373a30..74c9cbf7e0ca 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1713,8 +1713,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, pe_session); #if defined WLAN_FEATURE_VOWIFI - if (mac_ctx->rrm.rrmPEContext.rrmEnable && - SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) + if (mac_ctx->rrm.rrmPEContext.rrmEnable) populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap, pe_session); #endif @@ -2091,10 +2090,8 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, pe_session); #if defined WLAN_FEATURE_VOWIFI - if (mac_ctx->rrm.rrmPEContext.rrmEnable && - SIR_MAC_GET_RRM(pe_session->limReassocBssCaps)) { + if (mac_ctx->rrm.rrmPEContext.rrmEnable) populate_dot11f_rrm_ie(mac_ctx, &frm.RRMEnabledCap, pe_session); - } #endif /* @@ -2563,10 +2560,8 @@ lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, &frm.ExtSuppRates, psessionEntry); #if defined WLAN_FEATURE_VOWIFI - if (pMac->rrm.rrmPEContext.rrmEnable && - SIR_MAC_GET_RRM(psessionEntry->limReassocBssCaps)) { + if (pMac->rrm.rrmPEContext.rrmEnable) populate_dot11f_rrm_ie(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 */ -- cgit v1.2.3 From c2dff547013f1cec083f1744f469fa3e7e701f4c Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 3 Nov 2015 12:09:00 -0800 Subject: qcacld-3.0: Remove Radio measurement related cfg entries qcacld-2.0 to qcacld-3.0 propagation Remove cfg entries related to radio measurement(RM). We have support to enable/disable RM capability through INI config. We also had entry in cfg static table(cfg.dat). This change set will remove entries related to RM. Change-Id: Ic56cc34628cd1c0fb10512069ef6dc5f0eebb887 CRs-Fixed: 924420 --- core/mac/inc/wni_cfg.h | 19 ++----------------- core/mac/src/cfg/cfg_api.c | 13 ++----------- core/mac/src/cfg/cfg_param_name.c | 3 --- core/mac/src/cfg/cfg_proc_msg.c | 15 --------------- core/wma/src/wma_scan_roam.c | 10 +++------- 5 files changed, 7 insertions(+), 53 deletions(-) diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 76583d0d3ab7..e151fa5adab9 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -273,9 +273,6 @@ enum { WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG, WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS, WNI_CFG_SINGLE_TID_RC, - WNI_CFG_RRM_ENABLED, - WNI_CFG_RRM_OPERATING_CHAN_MAX, - WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, WNI_CFG_TX_PWR_CTRL_ENABLE, WNI_CFG_MCAST_BCAST_FILTER_SETTING, WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK, @@ -1367,18 +1364,6 @@ enum { #define WNI_CFG_SINGLE_TID_RC_STAMAX 1 #define WNI_CFG_SINGLE_TID_RC_STADEF 1 -#define WNI_CFG_RRM_ENABLED_STAMIN 0 -#define WNI_CFG_RRM_ENABLED_STAMAX 1 -#define WNI_CFG_RRM_ENABLED_STADEF 0 - -#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMIN 0 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMAX 8 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX_STADEF 0 - -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMIN 0 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMAX 8 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STADEF 0 - #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 @@ -1563,8 +1548,8 @@ enum { #define WNI_CFG_TDLS_WMM_MODE_ENABLED_STAMAX 1 #define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 -#define CFG_PARAM_MAX_NUM 289 -#define CFG_STA_IBUF_MAX_SIZE 237 +#define CFG_PARAM_MAX_NUM 286 +#define CFG_STA_IBUF_MAX_SIZE 234 #define CFG_STA_SBUF_MAX_SIZE 3199 #define CFG_STA_MAGIC_DWORD 0xbeefbeef diff --git a/core/mac/src/cfg/cfg_api.c b/core/mac/src/cfg/cfg_api.c index 3a0d689e29ee..a91f5df8ffd8 100644 --- a/core/mac/src/cfg/cfg_api.c +++ b/core/mac/src/cfg/cfg_api.c @@ -770,19 +770,10 @@ tSirRetStatus cfg_get_capability_info(tpAniSirGlobal pMac, uint16_t *pCap, pCapInfo->apsd = 1; #if defined WLAN_FEATURE_VOWIFI - if (LIM_IS_STA_ROLE(sessionEntry)) { - if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != - eSIR_SUCCESS) { - cfg_log(pMac, LOGP, - FL("cfg get WNI_CFG_RRM_ENABLED failed")); - return eSIR_FAILURE; - } + pCapInfo->rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; #if defined WLAN_VOWIFI_DEBUG - PELOGE(cfg_log(pMac, LOGE, "RRM = %d", val);) + cfg_log(pMac, LOGE, FL("RRM = %d"), pCapInfo->rrm); #endif - if (val) - pCapInfo->rrm = 1; - } #endif /* DSSS-OFDM */ /* FIXME : no config defined yet. */ diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c index 00be55d6492e..f3e662bff0ff 100644 --- a/core/mac/src/cfg/cfg_param_name.c +++ b/core/mac/src/cfg/cfg_param_name.c @@ -274,9 +274,6 @@ unsigned char *g_cfg_param_name[] = { (unsigned char *)"RPE_AGING_THRESHOLD_FOR_AC3_REG", (unsigned char *)"NO_OF_ONCHIP_REORDER_SESSIONS", (unsigned char *)"SINGLE_TID_RC", - (unsigned char *)"RRM_ENABLED", - (unsigned char *)"RRM_OPERATING_CHAN_MAX", - (unsigned char *)"RRM_NON_OPERATING_CHAN_MAX", (unsigned char *)"TX_PWR_CTRL_ENABLE", (unsigned char *)"MCAST_BCAST_FILTER_SETTING", (unsigned char *)"BTC_DHCP_BT_SLOTS_TO_BLOCK", diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c index 0a477d0b805e..dc29f0aba022 100644 --- a/core/mac/src/cfg/cfg_proc_msg.c +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -1266,21 +1266,6 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { WNI_CFG_SINGLE_TID_RC_STAMIN, WNI_CFG_SINGLE_TID_RC_STAMAX, WNI_CFG_SINGLE_TID_RC_STADEF}, - {WNI_CFG_RRM_ENABLED, - CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, - WNI_CFG_RRM_ENABLED_STAMIN, - WNI_CFG_RRM_ENABLED_STAMAX, - WNI_CFG_RRM_ENABLED_STADEF}, - {WNI_CFG_RRM_OPERATING_CHAN_MAX, - CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, - WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMIN, - WNI_CFG_RRM_OPERATING_CHAN_MAX_STAMAX, - WNI_CFG_RRM_OPERATING_CHAN_MAX_STADEF}, - {WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, - CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, - WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMIN, - WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_STAMAX, - WNI_CFG_RRM_NON_OPERATING_CHAN_MAX_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, diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 5716c52584ad..bc08c24c6756 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -2949,13 +2949,9 @@ CDF_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle, } if (val) selfCaps.apsd = 1; - if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) { - CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, - "Failed to get WNI_CFG_RRM_ENABLED"); - return CDF_STATUS_E_FAILURE; - } - if (val) - selfCaps.rrm = 1; + + selfCaps.rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; + if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != eSIR_SUCCESS) { CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, -- cgit v1.2.3 From c25d3338b6bceacb0b83d17442f93ac026d63862 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Thu, 5 Nov 2015 14:40:52 -0800 Subject: qcacld-3.0: Enable fastpath INI variable Enable the fastpath for data traffic. Change-Id: I77dab02c579a48862287dba629785e3c8bb6b6ac CRs-Fixed: 935974 --- config/WCNSS_qcom_cfg.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index dd5a17fada16..a2f906b94325 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -585,6 +585,11 @@ gEnableTDLSOffChannel=1 # 1=Enable, 0=Disable (default) gEnableMacAddrSpoof=0 +# Enable(Tx) fastpath for data traffic. +# 0 - disable +# 1 - enable +gEnableFastPath=1 + END # Note: Configuration parser would not read anything past the END marker -- cgit v1.2.3 From e8d85ee2fce46671afecd09546a9e20595b4ab61 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Mon, 16 Nov 2015 12:56:15 -0800 Subject: Release 5.0.0.144 Release 5.0.0.144 Change-Id: I1e50bb41f68810fd11d60b82877a1d7c1745505e CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 7f5e734fe776..129fbe5c3d32 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 143 +#define QWLAN_VERSION_BUILD 144 -#define QWLAN_VERSIONSTR "5.0.0.143" +#define QWLAN_VERSIONSTR "5.0.0.144" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 910da118e4f81ca9509bc0a473cf0727d9726978 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Tue, 26 May 2015 19:26:16 +0530 Subject: qcacld-3.0: Add debug code to rootcause command timeout issue. qcacld-2.0 to qcacld-3.0 propagation when EXIT_BMPS is pending in activeList, it causes crash with excess logging for RoamPending list. In this scenario gTraceTbl has lost SME details due to other MTRACE commands. Because of which, the issue is not rootcaused. Add below changes to rootcause if the issue appears again: 1. print only first 5 commands from roamPendingList 2. Bug_on if the commandlist is full 3. Add MTRACE for PMC commands CRs-Fixed: 833261 Change-Id: Id5bb399c4a8c8e84ddfa121a66881e3ecb901b05 --- core/sme/src/common/sme_api.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a2b0eec48634..f4cc8df95029 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -546,29 +546,37 @@ tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac) csr_ll_next(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK); } - /* Increment static variable so that it prints - * pending command only once - */ - sme_command_queue_full++; - csr_ll_unlock(&pMac->sme.smeCmdPendingList); + idx = 1; /* There may be some more command in CSR's own pending queue */ csr_ll_lock(&pMac->roam.roamCmdPendingList); pEntry = csr_ll_peek_head(&pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK); - while (pEntry) { + while (pEntry && !sme_command_queue_full) { pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link); - sms_log(pMac, LOGE, - "Out of command buffer.... CSR pending command #%d (0x%X)", - idx++, pTempCmd->command); + /* Print only 1st five commands from CSR pending queue */ + if (idx <= 5) + sms_log(pMac, LOGE, + "Out of command buffer.... " + "CSR roamCmdPendingList command #%d (0x%X)", + idx, pTempCmd->command); + idx++; dump_csr_command_info(pMac, pTempCmd); pEntry = csr_ll_next(&pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK); } + + /* Increment static variable so that it prints + * pending command only once + */ + sme_command_queue_full++; csr_ll_unlock(&pMac->roam.roamCmdPendingList); + + /* panic with out-of-command */ + CDF_BUG(0); } /* memset to zero */ -- cgit v1.2.3 From 61adec9d5d23e3338a64c6f5eb8455aa58528e87 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Mon, 4 May 2015 16:31:07 +0530 Subject: qcacld-3.0: Reduce the log level for debug print in softap_xmit qcacld-2.0 to qcacld-3.0 propagation Reduce the error log level for LOGP in Progress in hdd_softap_hard_start_xmit to avoid WD bark Change-Id: I1be5db2eb9b59f22f735f9c21eeac9a81bb246f5 CRs-Fixed: 824309 --- core/hdd/src/wlan_hdd_softap_tx_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index 8f98dcf84366..bb85d1703a0e 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -206,7 +206,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * lead to a crash. */ if (pHddCtx->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO_HIGH, "%s: LOGP in Progress. Ignore!!!", __func__); goto drop_pkt; } -- cgit v1.2.3 From d11e84cc72cf759dd32876aa6064b655b1f1bbe8 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Fri, 29 May 2015 11:38:47 +0530 Subject: qcacld-3.0: Print signature on kernel logs when user triggers SSR by iwpriv qcacld-2.0 to qcacld-3.0 propagation Currently driver logs are routed as messages to CNSS_DIAG so the Kernel does not print them into the Kernel log. Add a debug print to display in kernel log when ever the SSR is triggered using iwpriv. In dog-food testing, this print would help to separate out the user-triggered SSR scenarios. Change-Id: I58f247a26e802bced0c226ee92052ca0d69e1554 CRs-Fixed: 844938 --- core/hdd/src/wlan_hdd_wext.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 6f7a9ace6efd..4e68ecb6c9bd 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -9424,6 +9424,8 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, 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]); ret = wma_cli_set2_command(pAdapter->sessionId, GEN_PARAM_CRASH_INJECT, value[1], value[2], GEN_CMD); -- cgit v1.2.3 From 7a003f67bddabeb69e063fa843ab1a40c7b3e7c8 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Thu, 19 Mar 2015 13:38:33 +0530 Subject: qcacld-3.0: apply vos_assert in vostimer APIs, in uninitialized case qcacld-2.0 to qcacld-3.0 propagation As a debug enhancement, call vos_assert in vos timer APIs, when API fails because of unintialization. Change-Id: Ib7d4c7995a60b23413eead4603b38ff89ff48715 CRs-Fixed: 810282 --- core/cdf/src/cdf_mc_timer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/cdf/src/cdf_mc_timer.c b/core/cdf/src/cdf_mc_timer.c index cefdfccd7fba..0edc8f3d54d1 100644 --- a/core/cdf/src/cdf_mc_timer.c +++ b/core/cdf/src/cdf_mc_timer.c @@ -655,8 +655,7 @@ CDF_STATUS cdf_mc_timer_start(cdf_mc_timer_t *timer, uint32_t expirationTime) if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Cannot start uninitialized timer", __func__); - if (LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie) - CDF_ASSERT(0); + CDF_ASSERT(0); return CDF_STATUS_E_INVAL; } @@ -738,8 +737,7 @@ CDF_STATUS cdf_mc_timer_stop(cdf_mc_timer_t *timer) if (LINUX_TIMER_COOKIE != timer->platformInfo.cookie) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Cannot stop uninitialized timer", __func__); - if (LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie) - CDF_ASSERT(0); + CDF_ASSERT(0); return CDF_STATUS_E_INVAL; } -- cgit v1.2.3 From 88a8cf28176c8fd1443669b76d5bb63c95d7f457 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Tue, 17 Mar 2015 11:55:50 +0530 Subject: qcacld-3.0: Set tfm to NULL to avoid freeing in crypto_free_cipher qcacld-2.0 to qcacld-3.0 propagation tfm is invalid when alloc fails. Set tfm to NULL to avoid freeing the crypto transform in crypto_free_cipher()->crypto_destroy_tfm. Change-Id: I3261377f3a7b6ab5740d4144be9e84a1a3a07e42 CRs-Fixed: 809085 --- core/cds/src/cds_utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/cds/src/cds_utils.c b/core/cds/src/cds_utils.c index 22f1a9453b7d..cec62590eb18 100644 --- a/core/cds/src/cds_utils.c +++ b/core/cds/src/cds_utils.c @@ -387,6 +387,7 @@ cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id, tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { ret = PTR_ERR(tfm); + tfm = NULL; CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: crypto_alloc_cipher failed (%d)", __func__, ret); goto err_tfm; @@ -497,6 +498,7 @@ cds_is_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm, uint8_t *efrm) tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { ret = PTR_ERR(tfm); + tfm = NULL; CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "crypto_alloc_cipher failed (%d)", ret); goto err_tfm; -- cgit v1.2.3 From f66ffc8d7811921bafd0b43125a415fd6f689b2d Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Thu, 14 May 2015 18:44:59 +0530 Subject: qcacld-3.0: debug check for l_rx_defrag_waitlist_remove qcacld-2.0 to qcacld-3.0 propagation while wlan disconnection is happening, in the process of peer-cleanup check for tqu->prev to be non-null before calling TAILQ_REMOVE. Change-Id: I5841dfe80b954bdfac5147f5e3e3661cc85ba4b1 CRs-Fixed: 836447 --- core/dp/txrx/ol_rx_defrag.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index 4fb2cbc2e48e..7f1db54e6da9 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -393,14 +393,18 @@ 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_next != NULL || - rx_reorder->defrag_waitlist_elem.tqe_prev != NULL) { + if (rx_reorder->defrag_waitlist_elem.tqe_next != 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 { + TXRX_PRINT(TXRX_PRINT_LEVEL_FATAL_ERR, + "waitlist->tqe_prv = NULL\n"); + CDF_ASSERT(0); + rx_reorder->defrag_waitlist_elem.tqe_next = NULL; } } -- cgit v1.2.3 From ad98bf17dced46c31e679340c2560857f52cf9e4 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 17 Nov 2015 21:30:21 -0800 Subject: qcacld-3.0: Route logging through CDF_TRACE AR_print and cdf_print macros were not logging to the driver log. Change-Id: I11bc86f6c8ee91866c8e27903eaa15966111ce62 CRs-Fixed: 940770 --- core/cdf/inc/cdf_types.h | 9 +++++---- uapi/linux/osapi_linux.h | 29 +++++------------------------ 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/core/cdf/inc/cdf_types.h b/core/cdf/inc/cdf_types.h index 49099450ce5c..27151417bd03 100644 --- a/core/cdf/inc/cdf_types.h +++ b/core/cdf/inc/cdf_types.h @@ -200,10 +200,6 @@ typedef bool (*cdf_irqlocked_func_t)(void *); /* Prototype of timer function */ typedef void (*cdf_softirq_timer_func_t)(void *); -#define cdf_print __cdf_print -#define cdf_vprint __cdf_vprint -#define cdf_snprint __cdf_snprint - #define cdf_offsetof(type, field) offsetof(type, field) /** @@ -264,6 +260,11 @@ typedef enum { CDF_MODULE_ID_MAX } CDF_MODULE_ID; +#define cdf_print(args...) \ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, ## args) +#define cdf_vprint __cdf_vprint +#define cdf_snprint __cdf_snprint + /** * typedef enum tCDF_CON_MODE - Concurrency role. * diff --git a/uapi/linux/osapi_linux.h b/uapi/linux/osapi_linux.h index e0420bc12e7f..4fa05bbb57e9 100644 --- a/uapi/linux/osapi_linux.h +++ b/uapi/linux/osapi_linux.h @@ -71,31 +71,12 @@ #define A_MEMSET(addr, value, size) memset((addr), (value), (size)) #define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) -#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) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, ## args) +#define A_PRINTF(args ...) \ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, ## args) +#define A_PRINTF_LOG(args ...) \ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, ## args) #define A_SNPRINTF(buf, len, args ...) snprintf (buf, len, args) /* -- cgit v1.2.3 From ab1ce349fd42c7813f04829e6c0ee350dd3cc42a Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 17 Nov 2015 23:12:57 -0800 Subject: qcacld-3.0: Record log timestamp type Log timestamp can come from Qtimer or the system timer. Record the source in a global variable that will be dumped with the logs. Change-Id: Ib168cfdc874426e48b12aac89f00d81ffe9e7fa6 CRs-Fixed: 940773 --- core/cdf/inc/cdf_time.h | 18 ++++++++++++++++++ core/cdf/src/cdf_trace.c | 2 ++ 2 files changed, 20 insertions(+) diff --git a/core/cdf/inc/cdf_time.h b/core/cdf/inc/cdf_time.h index 6f5d1f5214df..58314c18106a 100644 --- a/core/cdf/inc/cdf_time.h +++ b/core/cdf/inc/cdf_time.h @@ -125,6 +125,24 @@ static inline void cdf_mdelay(int msecs) /* Check if _a atleast as recent as _b, if not later */ #define cdf_system_time_after_eq(_a, _b) __cdf_system_time_after_eq(_a, _b) +/** + * enum cdf_timestamp_unit - what unit the cdf timestamp is in + * @KERNEL_LOG: boottime time in uS (micro seconds) + * @KERNEL_LOG: QTIME in (1/19200)S + * + * This enum is used to distinguish which timer source is used. + */ +enum cdf_timestamp_unit { + KERNEL_LOG, + QTIMER, +}; + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define CDF_LOG_TIMESTAMP_UNIT QTIMER +#else +#define CDF_LOG_TIMESTAMP_UNIT KERNEL_LOG +#endif + #ifdef QCA_WIFI_3_0_ADRASTEA /** * cdf_get_log_timestamp() - get time stamp for logging diff --git a/core/cdf/src/cdf_trace.c b/core/cdf/src/cdf_trace.c index dfacdd45cb20..7982d6518d58 100644 --- a/core/cdf/src/cdf_trace.c +++ b/core/cdf/src/cdf_trace.c @@ -43,6 +43,8 @@ #define CDF_TRACE_BUFFER_SIZE (512) +enum cdf_timestamp_unit cdf_log_timestamp_type = CDF_LOG_TIMESTAMP_UNIT; + /* macro to map cdf trace levels into the bitmask */ #define CDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level))) -- cgit v1.2.3 From f388897d373fed854fbc2b8d44c560eed413cd7c Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Thu, 8 Oct 2015 16:38:37 +0530 Subject: qcacld-3.0: IPv6 packets classification support Enable classification of IPv6 frames based on the traffic class field in the IPv6 header. Change-Id: I4114cb972f61b75da35a225c07f7628d748a744c CRs-Fixed: 921955 --- core/hdd/inc/wlan_hdd_cfg.h | 6 -- core/hdd/src/wlan_hdd_cfg.c | 9 -- core/hdd/src/wlan_hdd_wmm.c | 252 ++++++++++++++++++-------------------------- 3 files changed, 101 insertions(+), 166 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 198a5a0e3675..f25b9131962e 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -684,11 +684,6 @@ typedef enum { #define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX (1) #define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT (1) -#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) @@ -2918,7 +2913,6 @@ struct hdd_config { bool isOkcIniFeatureEnabled; #endif bool isRoamOffloadScanEnabled; - hdd_wmm_classification_t PktClassificationBasis; /* DSCP or 802.1Q */ bool bImplicitQosEnabled; /* default TSPEC parameters for AC_VO */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index da08ff7e621e..e31103f60a03 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1095,12 +1095,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN, CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX, cb_notify_update_roam_scan_offload_enabled, 0), - REG_VARIABLE(CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME, WLAN_PARAM_Integer, - struct hdd_config, 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, struct hdd_config, InfraDirAcVo, @@ -4472,9 +4466,6 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [UapsdMask] Value = [0x%x] ", pHddCtx->config->UapsdMask); - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, - "Name = [PktClassificationBasis] Value = [%u] ", - pHddCtx->config->PktClassificationBasis); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [ImplicitQosIsEnabled] Value = [%u]", (int)pHddCtx->config->bImplicitQosEnabled); diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index d25a71849eae..f2699f1ab4e3 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -1548,29 +1549,27 @@ CDF_STATUS hdd_wmm_adapter_close(hdd_adapter_t *pAdapter) /** * hdd_wmm_classify_pkt() - Function which will classify an OS packet - * into a WMM AC based on either 802.1Q or DSCP + * into a WMM AC based on DSCP * - * @pAdapter: [in] adapter upon which the packet is being transmitted - * @skb: [in] the actual OS packet (sk_buff) being transmitted - * @pAcType: [out] WMM AC type of the OS packet - * @pUserPri: [out] User Priority of the OS packet + * @adapter: adapter upon which the packet is being transmitted + * @skb: pointer to network buffer + * @user_pri: user priority of the OS packet + * @is_eapol: eapol packet flag * * Return: None */ static -void hdd_wmm_classify_pkt(hdd_adapter_t *pAdapter, +void hdd_wmm_classify_pkt(hdd_adapter_t *adapter, struct sk_buff *skb, - sme_ac_enum_type *pAcType, - sme_QosWmmUpType *pUserPri, + sme_QosWmmUpType *user_pri, bool *is_eapol) { - unsigned char *pPkt; - union generic_ethhdr *pHdr; - struct iphdr *pIpHdr; - unsigned char tos; unsigned char dscp; - sme_QosWmmUpType userPri; - sme_ac_enum_type acType; + unsigned char tos; + union generic_ethhdr *eth_hdr; + struct iphdr *ip_hdr; + struct ipv6hdr *ipv6hdr; + unsigned char *pkt; /* this code is executed for every packet therefore * all debug code is kept conditional @@ -1581,158 +1580,118 @@ void hdd_wmm_classify_pkt(hdd_adapter_t *pAdapter, "%s: Entered", __func__); #endif /* HDD_WMM_DEBUG */ - pPkt = skb->data; - pHdr = (union generic_ethhdr *)pPkt; + pkt = skb->data; + eth_hdr = (union generic_ethhdr *)pkt; #ifdef HDD_WMM_DEBUG CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: proto/length is 0x%04x", __func__, pHdr->eth_II.h_proto); + "%s: proto is 0x%04x", __func__, skb->protocol); #endif /* HDD_WMM_DEBUG */ - if (HDD_WMM_CLASSIFICATION_DSCP == - (WLAN_HDD_GET_CTX(pAdapter))->config->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; + if (eth_hdr->eth_II.h_proto == htons(ETH_P_IP)) { + /* case 1: Ethernet II IP packet */ + ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_II)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: Ethernet II IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_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; + } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_IPV6)) { + ipv6hdr = ipv6_hdr(skb); + tos = ntohs(*(const __be16 *)ipv6hdr) >> 4; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: 802.3 LLC/SNAP IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II IPv6 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; + } else if ((ntohs(eth_hdr->eth_II.h_proto) < WLAN_MIN_PROTO) && + (eth_hdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) && + (eth_hdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) && + (eth_hdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) && + (eth_hdr->eth_8023.h_proto == htons(ETH_P_IP))) { + /* case 2: 802.3 LLC/SNAP IP packet */ + ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_8023)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_INFO_LOW, - "%s: Ethernet II VLAN tagged IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_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 ((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; + } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_8021Q)) { + /* VLAN tagged */ + + if (eth_hdr->eth_IIv.h_vlan_encapsulated_proto == + htons(ETH_P_IP)) { + /* case 3: Ethernet II vlan-tagged IP packet */ + ip_hdr = + (struct iphdr *) + &pkt[sizeof(eth_hdr->eth_IIv)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_INFO_LOW, - "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_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 { - /* default */ + } else + if ((ntohs(eth_hdr->eth_IIv.h_vlan_encapsulated_proto) + < WLAN_MIN_PROTO) + && (eth_hdr->eth_8023v.h_snap.dsap == + WLAN_SNAP_DSAP) + && (eth_hdr->eth_8023v.h_snap.ssap == + WLAN_SNAP_SSAP) + && (eth_hdr->eth_8023v.h_snap.ctrl == + WLAN_SNAP_CTRL) + && (eth_hdr->eth_8023v.h_proto == + htons(ETH_P_IP))) { + /* case 4: 802.3 LLC/SNAP vlan-tagged IP packet */ + ip_hdr = + (struct iphdr *) + &pkt[sizeof(eth_hdr->eth_8023v)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_WARN, - "%s: VLAN tagged Unhandled Protocol, using default tos", - __func__); + CDF_TRACE(CDF_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 */ - tos = 0; - } } else { /* default */ #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_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; - *is_eapol = true; - } else - tos = 0; - } - - dscp = (tos >> 2) & 0x3f; - userPri = pAdapter->hddWmmDscpToUpMap[dscp]; - -#ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_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))->config-> - 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 - CDF_TRACE(CDF_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 - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, - "%s: Untagged frame, using default UP", - __func__); + CDF_TRACE(CDF_MODULE_ID_HDD, + WMM_TRACE_LEVEL_WARN, + "%s: VLAN tagged 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)) { - userPri = SME_QOS_WMM_UP_VO; - *is_eapol = true; - } else - userPri = SME_QOS_WMM_UP_BE; + tos = 0; } } else { /* default */ #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: Unknown classification scheme, using default UP", - __func__); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, + "%s: Unhandled Protocol, using default tos", + __func__); #endif /* HDD_WMM_DEBUG */ - userPri = SME_QOS_WMM_UP_BE; + /* Give the highest priority to 802.1x packet */ + if (eth_hdr->eth_II.h_proto == + htons(HDD_ETHERTYPE_802_1_X)) { + tos = 0xC0; + *is_eapol = true; + } else + tos = 0; } - acType = hdd_wmm_up_to_ac_map[userPri]; + dscp = (tos >> 2) & 0x3f; + *user_pri = adapter->hddWmmDscpToUpMap[dscp]; #ifdef HDD_WMM_DEBUG CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, - "%s: UP is %d, AC is %d", __func__, userPri, acType); + "%s: tos is %d, dscp is %d, up is %d", + __func__, tos, dscp, *user_pri); #endif /* HDD_WMM_DEBUG */ - *pUserPri = userPri; - *pAcType = acType; - return; } @@ -1780,25 +1739,21 @@ uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb ) { - sme_ac_enum_type ac; sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; uint16_t queueIndex; - hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_t *adapter = (hdd_adapter_t *) netdev_priv(dev); + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(adapter); bool is_eapol = false; int status = 0; - status = wlan_hdd_validate_context(pHddCtx); + status = wlan_hdd_validate_context(hddctx); if (status != 0) { skb->priority = SME_QOS_WMM_UP_BE; return HDD_LINUX_AC_BE; } - if (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->config->WmmMode) { - /* Get the user priority from IP header & corresponding AC */ - hdd_wmm_classify_pkt(pAdapter, skb, &ac, &up, &is_eapol); - } - + /* Get the user priority from IP header */ + hdd_wmm_classify_pkt(adapter, skb, &up, &is_eapol); skb->priority = up; queueIndex = hdd_get_queue_index(skb->priority, is_eapol); @@ -1816,7 +1771,6 @@ uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb */ uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) { - sme_ac_enum_type ac; sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; uint16_t queueIndex; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -1830,15 +1784,11 @@ uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) return HDD_LINUX_AC_BE; } - /* if we don't want QoS or the AP doesn't support Qos */ - /* All traffic will get equal opportuniy 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, &is_eapol); - } - + /* Get the user priority from IP header */ + hdd_wmm_classify_pkt(pAdapter, skb, &up, &is_eapol); skb->priority = up; queueIndex = hdd_get_queue_index(skb->priority, is_eapol); + return queueIndex; } -- cgit v1.2.3 From 8f88538e87abdd6d964458a197059850c75501b4 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 12 Oct 2015 17:11:14 +0530 Subject: qcacld-3.0: Add FW Profiling support Add Profiling stats support in HOST driver to have CPU based profiling for critical data path functions in FW. Change-Id: Ib6d4f0b220f622cf304536c8e538d4dc34c6434b CRs-Fixed: 921950 --- core/hdd/inc/qc_sap_ioctl.h | 5 ++ core/hdd/inc/wlan_hdd_wext.h | 2 + core/hdd/src/wlan_hdd_hostapd.c | 95 ++++++++++++++++++++++++----- core/hdd/src/wlan_hdd_wext.c | 108 +++++++++++++++++++++++++++++++-- core/wma/inc/wma.h | 22 +++++++ core/wma/inc/wma_internal.h | 6 ++ core/wma/src/wma_features.c | 131 ++++++++++++++++++++++++++++++++++++++++ core/wma/src/wma_main.c | 50 +++++++++++++++ core/wma/src/wma_utils.c | 72 ++++++++++++++++++++++ 9 files changed, 471 insertions(+), 20 deletions(-) diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h index 5fee04fcc6e3..6983a7a96ff1 100644 --- a/core/hdd/inc/qc_sap_ioctl.h +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -147,6 +147,7 @@ typedef struct { /* Private ioctls and their sub-ioctls */ #define QCSAP_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 13) #define QCSAP_GET_STATS 1 +#define QCSAP_LIST_FW_PROFILE 2 #define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV+14) #define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15) @@ -171,6 +172,8 @@ typedef struct { #define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 #endif #define QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL 2 +#define QCSAP_ENABLE_FW_PROFILE 3 +#define QCSAP_SET_FW_PROFILE_HIST_INTVL 4 #define MAX_VAR_ARGS 7 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) @@ -237,6 +240,8 @@ enum { QCASAP_DUMP_STATS, QCASAP_CLEAR_STATS, QCASAP_SET_RADAR_DBG, + QCSAP_GET_FW_PROFILE_DATA, + QCSAP_START_FW_PROFILING }; int iw_softap_get_channel_list(struct net_device *dev, diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 1f78e4916586..7bb8606eeac1 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -306,6 +306,8 @@ extern void hdd_wlan_get_version(hdd_adapter_t *pAdapter, extern void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, char *buffer, uint16_t buf_len); +extern void hdd_wlan_list_fw_profile(uint16_t *length, + char *buffer, uint16_t buf_len); extern int iw_set_essid(struct net_device *dev, struct iw_request_info *info, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index c5b595569446..ed0119529662 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2032,29 +2032,36 @@ static iw_softap_get_ini_cfg(struct net_device *dev, return ret; } +/** + * iw_softap_set_two_ints_getnone() - Generic "set two integer" 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_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; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + int ret; int *value = (int *)extra; int sub_cmd = value[0]; - int ret = 0; + hdd_context_t *hdd_ctx; - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); - if (ret != 0) { - hddLog(LOGE, FL("HDD context is not valid!")); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) 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]); - ret = wma_cli_set2_command(pAdapter->sessionId, + ret = wma_cli_set2_command(adapter->sessionId, GEN_PARAM_CRASH_INJECT, value[1], value[2], GEN_CMD); @@ -2066,6 +2073,19 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, if (value[1] == DUMP_DP_TRACE) cdf_dp_trace_dump_all(value[2]); break; + case QCSAP_ENABLE_FW_PROFILE: + hddLog(LOG1, "QCSAP_ENABLE_FW_PROFILE: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(adapter->sessionId, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + value[1], value[2], DBG_CMD); + break; + case QCSAP_SET_FW_PROFILE_HIST_INTVL: + hddLog(LOG1, "QCSAP_SET_FW_PROFILE_HIST_INTVL: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(adapter->sessionId, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + value[1], value[2], DBG_CMD); default: hddLog(LOGE, FL("Invalid IOCTL command %d"), sub_cmd); break; @@ -2793,6 +2813,12 @@ static __iw_softap_setparam(struct net_device *dev, } break; } + case QCSAP_START_FW_PROFILING: + hddLog(LOG1, "QCSAP_START_FW_PROFILING %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + set_value, DBG_CMD); + break; default: hddLog(LOGE, FL("Invalid setparam command %d value %d"), sub_cmd, set_value); @@ -3007,6 +3033,12 @@ static __iw_softap_getparam(struct net_device *dev, ret = wlan_hdd_get_temperature(pHostapdAdapter, value); break; } + case QCSAP_GET_FW_PROFILE_DATA: + hddLog(LOG1, "QCSAP_GET_FW_PROFILE_DATA"); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, DBG_CMD); + break; default: hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd); ret = -EINVAL; @@ -3415,31 +3447,44 @@ static iw_softap_disassoc_sta(struct net_device *dev, return ret; } +/** + * iw_get_char_setnone() - Generic "get char" private 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_char_setnone(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); - CDF_STATUS status; + int ret; int sub_cmd = wrqu->data.flags; hdd_context_t *hdd_ctx; ENTER(); hdd_ctx = WLAN_HDD_GET_CTX(adapter); - status = wlan_hdd_validate_context(hdd_ctx); - if (status != 0) - return status; + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return ret; switch (sub_cmd) { case QCSAP_GET_STATS: hdd_wlan_get_stats(adapter, &(wrqu->data.length), extra, WE_MAX_STR_LEN); break; + case QCSAP_LIST_FW_PROFILE: + hdd_wlan_list_fw_profile(&(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; } EXIT(); - return status; + return ret; } static int iw_get_char_setnone(struct net_device *dev, @@ -5464,6 +5509,10 @@ static const struct iw_priv_args hostapd_private_args[] = { QCASAP_CLEAR_STATS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "clearStats" + }, { + QCSAP_START_FW_PROFILING, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "startProfile" }, { QCSAP_IOCTL_GETPARAM, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" @@ -5529,6 +5578,9 @@ static const struct iw_priv_args hostapd_private_args[] = { }, { QCASAP_GET_TEMP_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp" + }, { + QCSAP_GET_FW_PROFILE_DATA, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getProfileData" }, { QCSAP_IOCTL_GET_STAWPAIE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, @@ -5571,6 +5623,10 @@ static const struct iw_priv_args hostapd_private_args[] = { QCSAP_GET_STATS, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats" } + , { + QCSAP_LIST_FW_PROFILE, 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "listProfile" + } , { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, @@ -5677,6 +5733,17 @@ static const struct iw_priv_args hostapd_private_args[] = { 0, "dump_dp_trace" } , + { + QCSAP_ENABLE_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "enableProfile" + } + , + { + QCSAP_SET_FW_PROFILE_HIST_INTVL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_hist_intvl" + } }; static const iw_handler hostapd_private[] = { diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 4e68ecb6c9bd..047131f20456 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -213,6 +213,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_SET_CTS_CBW 84 #define WE_DUMP_STATS 85 #define WE_CLEAR_STATS 86 +/* Private sub ioctl for starting/stopping the profiling */ +#define WE_START_FW_PROFILE 87 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -314,6 +316,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_GET_OEM_DATA_CAP 13 #endif #define WE_GET_SNR 14 +#define WE_LIST_FW_PROFILE 15 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) @@ -328,6 +331,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_DUMP_PCIE_LOG 16 #endif #define WE_GET_RECOVERY_STAT 17 +#define WE_GET_FW_PROFILE_DATA 18 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7) @@ -424,6 +428,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #endif #define WE_DUMP_DP_TRACE_LEVEL 3 #define DUMP_DP_TRACE 0 +/* Private sub ioctl for enabling and setting histogram interval of profiling */ +#define WE_ENABLE_FW_PROFILE 4 +#define WE_SET_FW_PROFILE_HIST_INTVL 5 /* (SIOCIWFIRSTPRIV + 29) is currently unused */ @@ -647,6 +654,41 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, *length = len + 1; } +/** + * hdd_wlan_list_fw_profile() - Get fw profiling points + * @length: Size of the data copied + * @buffer: Pointer to char buffer. + * @buf_len: Length of the char buffer. + * + * This function called when the "iwpriv wlan0 listProfile" command is given. + * It is used to get the supported profiling points in FW. + * + * Return - none + */ +void hdd_wlan_list_fw_profile(uint16_t *length, + char *buffer, uint16_t buf_len) +{ + uint32_t len = 0; + + len = scnprintf(buffer, buf_len, + "PROF_CPU_IDLE: %u\n" + "PROF_PPDU_PROC: %u\n" + "PROF_PPDU_POST: %u\n" + "PROF_HTT_TX_INPUT: %u\n" + "PROF_MSDU_ENQ: %u\n" + "PROF_PPDU_POST_HAL: %u\n" + "PROF_COMPUTE_TX_TIME: %u\n", + PROF_CPU_IDLE, + PROF_PPDU_PROC, + PROF_PPDU_POST, + PROF_HTT_TX_INPUT, + PROF_MSDU_ENQ, + PROF_PPDU_POST_HAL, + PROF_COMPUTE_TX_TIME); + + *length = len + 1; +} + /** * hdd_wlan_dump_stats() - display dump Stats * @adapter: adapter handle @@ -6072,6 +6114,14 @@ static int __iw_setint_getnone(struct net_device *dev, sme_set_scan_disable(WLAN_HDD_GET_HAL_CTX(pAdapter), set_value); break; } + case WE_START_FW_PROFILE: + { + hddLog(LOG1, "WE_START_FW_PROFILE %d", set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + set_value, DBG_CMD); + break; + } default: { hddLog(LOGE, "%s: Invalid sub command %d", __func__, @@ -6896,6 +6946,11 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } + case WE_LIST_FW_PROFILE: + hdd_wlan_list_fw_profile(&(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + /* The case prints the current state of the HDD, SME, CSR, PE, * TL it can be extended for WDI Global State as well. And * currently it only checks P2P_CLIENT adapter. P2P_DEVICE @@ -7409,6 +7464,12 @@ static int __iw_setnone_getnone(struct net_device *dev, break; } + case WE_GET_FW_PROFILE_DATA: + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, DBG_CMD); + break; + case WE_SET_REASSOC_TRIGGER: { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -9431,6 +9492,20 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, value[1], value[2], GEN_CMD); break; #endif + case WE_ENABLE_FW_PROFILE: + hddLog(LOGE, "WE_ENABLE_FW_PROFILE: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + value[1], value[2], DBG_CMD); + break; + case WE_SET_FW_PROFILE_HIST_INTVL: + hddLog(LOGE, "WE_SET_FW_PROFILE_HIST_INTVL: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + value[1], value[2], DBG_CMD); + break; case WE_SET_DUAL_MAC_FW_MODE_CONFIG: hdd_debug("Ioctl to set dual fw mode config"); if (hdd_ctx->config->dual_mac_feature_disable) { @@ -9986,6 +10061,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "clearStats"}, + {WE_START_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "startProfile"}, + {WLAN_PRIV_SET_NONE_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -10322,6 +10401,10 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats"}, + {WE_LIST_FW_PROFILE, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "listProfile"}, {WE_GET_STATES, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, @@ -10388,12 +10471,17 @@ static const struct iw_priv_args we_private_args[] = { 0, 0, "getRecoverStat"}, - { - WE_SET_REASSOC_TRIGGER, - 0, - 0, - "reassoc" - }, + + {WE_GET_FW_PROFILE_DATA, + 0, + 0, + "getProfileData"}, + + {WE_SET_REASSOC_TRIGGER, + 0, + 0, + "reassoc"}, + {WE_DUMP_AGC_START, 0, 0, @@ -10608,6 +10696,14 @@ static const struct iw_priv_args we_private_args[] = { 0, "crash_inject"} , #endif + {WE_ENABLE_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "enableProfile"} + , + {WE_SET_FW_PROFILE_HIST_INTVL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_hist_intvl"} + , {WE_SET_DUAL_MAC_FW_MODE_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_fw_mode_cfg"} diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index f15e51819f09..b72d9fc433d1 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1630,6 +1630,28 @@ enum uapsd_peer_param_enabled_ac { UAPSD_BE_ENABLED = 0x08 }; +/** + * enum profile_id_t - Firmware profiling index + * @PROF_CPU_IDLE: cpu idle profile + * @PROF_PPDU_PROC: ppdu processing profile + * @PROF_PPDU_POST: ppdu post profile + * @PROF_HTT_TX_INPUT: htt tx input profile + * @PROF_MSDU_ENQ: msdu enqueue profile + * @PROF_PPDU_POST_HAL: ppdu post profile + * @PROF_COMPUTE_TX_TIME: tx time profile + * @PROF_MAX_ID: max profile index + */ +enum profile_id_t { + PROF_CPU_IDLE, + PROF_PPDU_PROC, + PROF_PPDU_POST, + PROF_HTT_TX_INPUT, + PROF_MSDU_ENQ, + PROF_PPDU_POST_HAL, + PROF_COMPUTE_TX_TIME, + PROF_MAX_ID, +}; + /** * struct p2p_ie - P2P IE structural definition. * @p2p_id: p2p id diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index c455e12b77a8..d927a7613984 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -868,6 +868,12 @@ int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, uint32_t value); #endif +int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, + uint32_t len); + +int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle, + uint32_t cmd, uint32_t value1, uint32_t value2); + void wma_wow_tx_complete(void *wma); int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index d7f54aada7d5..c1e7df5054bc 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1025,6 +1025,137 @@ int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, } #endif /* FEATURE_GREEN_AP */ +/** + * wmi_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW + * @wma: wma handle + * @cmd: Profiling command index + * @value1: parameter1 value + * @value2: parameter2 value + * + * Return: 0 for success else error code + */ +int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle, + uint32_t cmd, uint32_t value1, uint32_t value2) +{ + wmi_buf_t buf; + int32_t len = 0; + int ret; + wmi_wlan_profile_trigger_cmd_fixed_param *prof_trig_cmd; + wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *hist_intvl_cmd; + wmi_wlan_profile_enable_profile_id_cmd_fixed_param *profile_enable_cmd; + wmi_wlan_profile_get_prof_data_cmd_fixed_param *profile_getdata_cmd; + + switch (cmd) { + case WMI_WLAN_PROFILE_TRIGGER_CMDID: + len = sizeof(wmi_wlan_profile_trigger_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + prof_trig_cmd = + (wmi_wlan_profile_trigger_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&prof_trig_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_trigger_cmd_fixed_param)); + prof_trig_cmd->enable = value1; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_TRIGGER_CMDID); + if (ret) { + WMA_LOGE("PROFILE_TRIGGER cmd Failed with value %d", + value1); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID: + len = sizeof(wmi_wlan_profile_get_prof_data_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + profile_getdata_cmd = + (wmi_wlan_profile_get_prof_data_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&profile_getdata_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_get_prof_data_cmd_fixed_param)); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID); + if (ret) { + WMA_LOGE("PROFILE_DATA cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID: + len = sizeof(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + hist_intvl_cmd = + (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&hist_intvl_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param)); + hist_intvl_cmd->profile_id = value1; + hist_intvl_cmd->value = value2; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID); + if (ret) { + WMA_LOGE("HIST_INTVL cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID: + len = + sizeof(wmi_wlan_profile_enable_profile_id_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + profile_enable_cmd = + (wmi_wlan_profile_enable_profile_id_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&profile_enable_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_enable_profile_id_cmd_fixed_param)); + profile_enable_cmd->profile_id = value1; + profile_enable_cmd->enable = value2; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID); + if (ret) { + WMA_LOGE("enable cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + default: + WMA_LOGD("%s: invalid profiling command", __func__); + break; + } + + return 0; +} + #ifdef FEATURE_WLAN_LPHB /** * wma_lphb_handler() - send LPHB indication to SME diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index c2eafde3feaa..e9c6bd96bc47 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -955,6 +955,52 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, WMA_LOGE("dbglog_report_enable failed ret %d", ret); break; + case WMI_WLAN_PROFILE_TRIGGER_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + privcmd->param_value, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_TRIGGER_CMDID, ret); + break; + case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + privcmd->param_value, + privcmd->param_sec_value); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + privcmd->param_value, + privcmd->param_sec_value); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + 0, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + ret); + break; #ifdef FEATURE_GREEN_AP case WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID: /* Set the Green AP */ @@ -1640,6 +1686,10 @@ CDF_STATUS wma_open(void *cds_context, wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_DEBUG_PRINT_EVENTID, wma_unified_debug_print_event_handler); + /* Register profiling event Handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_WLAN_PROFILE_DATA_EVENTID, + wma_profile_data_report_event_handler); wma_handle->tgt_cfg_update_cb = tgt_cfg_cb; wma_handle->dfs_radar_indication_cb = radar_ind_cb; diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index fd34f803a920..a8f81d5ece69 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -381,6 +381,78 @@ int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf, } #endif /* WLAN_FEATURE_STATS_EXT */ +/** + * wma_profile_data_report_event_handler() - fw profiling handler + * @handle: wma handle + * @event_buf: event buffer received from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf; + wmi_wlan_profile_ctx_t *profile_ctx; + wmi_wlan_profile_t *profile_data; + uint32_t i = 0; + uint32_t entries; + uint8_t *buf_ptr; + param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf; + + if (!param_buf) { + WMA_LOGE("%s: Invalid profile data event buf", __func__); + return -EINVAL; + } + profile_ctx = param_buf->profile_ctx; + buf_ptr = (uint8_t *)profile_ctx; + buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE; + profile_data = (wmi_wlan_profile_t *) buf_ptr; + entries = profile_ctx->bin_count; + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Profile data stats\n"); + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "TOT: %d\n" + "tx_msdu_cnt: %d\n" + "tx_mpdu_cnt: %d\n" + "tx_ppdu_cnt: %d\n" + "rx_msdu_cnt: %d\n" + "rx_mpdu_cnt: %d\n" + "bin_count: %d\n", + profile_ctx->tot, + profile_ctx->tx_msdu_cnt, + profile_ctx->tx_mpdu_cnt, + profile_ctx->tx_ppdu_cnt, + profile_ctx->rx_msdu_cnt, + profile_ctx->rx_mpdu_cnt, + profile_ctx->bin_count); + + for (i = 0; i < entries; i++) { + if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT) + break; + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Profile ID: %d\n" + "Profile Count: %d\n" + "Profile TOT: %d\n" + "Profile Min: %d\n" + "Profile Max: %d\n" + "Profile hist_intvl: %d\n" + "Profile hist[0]: %d\n" + "Profile hist[1]: %d\n" + "Profile hist[2]: %d\n", + profile_data[i].id, + profile_data[i].cnt, + profile_data[i].tot, + profile_data[i].min, + profile_data[i].max, + profile_data[i].hist_intvl, + profile_data[i].hist[0], + profile_data[i].hist[1], + profile_data[i].hist[2]); + } + + return 0; +} #ifdef WLAN_FEATURE_LINK_LAYER_STATS -- cgit v1.2.3 From 294a83162a24124d20f93d00b32924883dc4bb05 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Thu, 22 Oct 2015 13:59:32 -0700 Subject: qcacld-3.0: IPA uC: Return EPERM for RM CONS REQ only during unloading qcacld-2.0 to qcacld-3.0 propagation Change to return -EINPROGRESS if WLAN unable to grant IPA CONS resource due to IPA resource loading is in progress. Return -EPERM only if WLAN unable to grant IPA CONS resource due to IPA resource unloading is in progress. Change-Id: Iea4d804d3f81b086e723230fb8eddc7d9561d7d1 CRs-Fixed: 926880 --- core/hdd/src/wlan_hdd_ipa.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 10d1acb16bde..ee5fb7afd81c 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -2100,14 +2100,23 @@ static int hdd_ipa_rm_cons_release(void) */ static int hdd_ipa_rm_cons_request(void) { - if ((ghdd_ipa->resource_loading) || (ghdd_ipa->resource_unloading)) { + int ret = 0; + + if (ghdd_ipa->resource_loading) { HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, - "%s: ipa resource loading/unloading in progress", + "%s: IPA resource loading in progress", __func__); ghdd_ipa->pending_cons_req = true; - return -EPERM; + ret = -EINPROGRESS; + } else if (ghdd_ipa->resource_unloading) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, + "%s: IPA resource unloading in progress", + __func__); + ghdd_ipa->pending_cons_req = true; + ret = -EPERM; } - return 0; + + return ret; } /** -- cgit v1.2.3 From 6532aa21c51255673ba0515d880404bfa820a129 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Tue, 17 Nov 2015 15:25:12 -0800 Subject: qcacld-3.0:IPA-uC: Check IPA pipes are up before disable it when SSR deinit qcacld-2.0 to qcacld-3.0 propagation When SSR happens, IPA WDI pipes may not be enabled yet, so need to check if it up before disable it. Change-Id: I5ff643fcf9804dc0933105079f0653884f7d63dc CRs-Fixed: 938605 --- core/hdd/src/wlan_hdd_ipa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index ee5fb7afd81c..61a61a0ed1d3 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1820,7 +1820,8 @@ int hdd_ipa_uc_ssr_deinit(void) * 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); + if (!hdd_ipa->ipa_pipes_down) + hdd_ipa_uc_disable_pipes(hdd_ipa); cdf_wake_lock_acquire(&hdd_ipa->ipa_lock); for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) { -- cgit v1.2.3 From 2570c563c85da85478b41c028edaa834672c1b92 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Tue, 27 Oct 2015 11:43:40 -0700 Subject: qcacld-3.0: Fix WDI pipe enable failure due to double invoke qcacld-2.0 to qcacld-3.0 propagation Fix an issue which enables WDI pipes even when RM resource request failed, which will cause to invoke WDI pipe enable twice when RM_ RESOURCE_GRANTED notification arrives later. Also fixed a possible discrapancy between connected client stat count and actual number of connected clients. Change-Id: Ibb86ef6ada398fcc669e3a894daadc09e6096b0f CRs-fixed: 927581 --- core/hdd/src/wlan_hdd_ipa.c | 52 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 61a61a0ed1d3..422a448e9e59 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -973,7 +973,9 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) p_cds_contextType cds_ctx = hdd_ipa->hdd_ctx->pcds_context; /* ACTIVATE TX PIPE */ - HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Enable TX PIPE", __func__); + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, @@ -991,7 +993,9 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, true); /* ACTIVATE RX PIPE */ - HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Enable RX PIPE", __func__); + HDD_IPA_LOG(CDF_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(CDF_TRACE_LEVEL_ERROR, @@ -1068,32 +1072,39 @@ static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa) { hdd_ipa->activated_fw_pipe = 0; hdd_ipa->resource_loading = true; + /* If RM feature enabled * Request PROD Resource first * PROD resource may return sync or async manners */ - if ((hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) && - (!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(CDF_TRACE_LEVEL_ERROR, - "%s: IPA WDI Pipes activate fail", - __func__); - hdd_ipa->resource_loading = false; - return -EBUSY; + if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) { + 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(CDF_TRACE_LEVEL_ERROR, + "%s: IPA WDI Pipe activation failed", + __func__); + hdd_ipa->resource_loading = false; + return -EBUSY; + } } } else { /* RM Disabled - * Just enabled all the PIPEs */ + * Just enabled all the PIPEs + */ if (hdd_ipa_uc_enable_pipes(hdd_ipa)) { HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, - "%s: IPA WDI Pipes activate fail", + "%s: IPA WDI Pipe activation failed", __func__); hdd_ipa->resource_loading = false; return -EBUSY; } hdd_ipa->resource_loading = false; } + + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "%s: IPA WDI Pipes activated successfully", __func__); return 0; } @@ -3520,11 +3531,10 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, (!hdd_ipa->sta_connected)) { /* Enable IPA UC TX PIPE when STA connected */ ret = hdd_ipa_uc_handle_first_con(hdd_ipa); - if (!ret) { + if (ret) { + cdf_mutex_release(&hdd_ipa->event_lock); HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, "handle 1st con ret %d", ret); - } else { - cdf_mutex_release(&hdd_ipa->event_lock); hdd_ipa_uc_offload_enable_disable(adapter, SIR_STA_RX_DATA_OFFLOAD, 0); goto end; @@ -3672,8 +3682,6 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, cdf_mutex_release(&hdd_ipa->event_lock); return 0; } - hdd_ipa->sap_num_connected_sta++; - hdd_ipa->pending_cons_req = false; cdf_mutex_release(&hdd_ipa->event_lock); meta.msg_type = type; @@ -3712,7 +3720,7 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, cdf_mutex_acquire(&hdd_ipa->event_lock); /* Enable IPA UC Data PIPEs when first STA connected */ - if ((1 == hdd_ipa->sap_num_connected_sta) + if ((0 == hdd_ipa->sap_num_connected_sta) && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) || !hdd_ipa->sta_connected)) { ret = hdd_ipa_uc_handle_first_con(hdd_ipa); @@ -3724,6 +3732,10 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, return ret; } } + + hdd_ipa->sap_num_connected_sta++; + hdd_ipa->pending_cons_req = false; + cdf_mutex_release(&hdd_ipa->event_lock); return ret; -- cgit v1.2.3 From 2027e1dc9db817c0e6ce9b410e105d22e1573337 Mon Sep 17 00:00:00 2001 From: Bhargav Shah Date: Wed, 4 Nov 2015 11:58:27 +0530 Subject: wlan: Fix for redundant TDLS log during scan_done callback qcacld-2.0 to qcacld-3.0 propagation In wlan_hdd_tdls_check_bmps(), NULL check for pHddTdlsCtx will be TRUE if TDLS support is not enabled. This leads to redundant logs, as this is called for every scan_done callback. Call wlan_hdd_tdls_scan_done_callback() only when TDLS support is enabled. Change-Id: Ice6f8fb1dc64f0669c19a9b5f5ce3d23c8cdc11c CRs-Fixed: 672099 --- core/hdd/src/wlan_hdd_scan.c | 4 ++++ core/hdd/src/wlan_hdd_tdls.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 586c50f56334..715cf884ee2b 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1107,6 +1107,10 @@ static CDF_STATUS hdd_cfg80211_scan_done_callback(tHalHandle halHandle, uint32_t scan_time; uint32_t size = 0; + ret = wlan_hdd_validate_context(hddctx); + if (0 != ret) + return CDF_STATUS_E_INVAL; + hddLog(CDF_TRACE_LEVEL_INFO, "%s called with hal = %p, pContext = %p, ID = %d, status = %d", __func__, halHandle, pContext, (int)scanId, (int)status); diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 459724608f9b..b3a1e0e88d19 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -2751,6 +2751,11 @@ void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) return; } + if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) { + hdd_info("TDLS mode is disabled OR not enabled"); + return; + } + /* free allocated memory at scan time */ wlan_hdd_tdls_free_scan_request(&pHddCtx->tdls_scan_ctxt); -- cgit v1.2.3 From b557ad865d909c1b5406c4aff6e32fee3630f5b0 Mon Sep 17 00:00:00 2001 From: Bhargav Shah Date: Wed, 24 Jun 2015 15:10:14 +0530 Subject: qcacld: Add support to enable/disable logging for all missing modules. qcacld-2.0 -> qcacld-3.0 propagation Add support to enable and disable logging for all missing modules from INI. Change-Id: I1677a2db48193b1130e0fc07e8bdfc42823d3567 CRs-Fixed: 855168 --- core/hdd/inc/wlan_hdd_cfg.h | 16 +++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_main.c | 17 ++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index f25b9131962e..ae1a7c01da15 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1287,6 +1287,14 @@ typedef enum { #define CFG_CDF_TRACE_ENABLE_SAP_NAME "cdf_trace_enable_sap" #define CFG_CDF_TRACE_ENABLE_HDD_SAP_NAME "cdf_trace_enable_hdd_sap" #define CFG_CDF_TRACE_ENABLE_BMI_NAME "cdf_trace_enable_bmi" +#define CFG_CDF_TRACE_ENABLE_CFG_NAME "cdf_trace_enable_cfg" +#define CFG_CDF_TRACE_ENABLE_EPPING "cdf_trace_enable_epping" +#define CFG_CDF_TRACE_ENABLE_CDF_DEVICES "cdf_trace_enable_cdf_devices" +#define CFG_CDF_TRACE_ENABLE_TXRX_NAME "cfd_trace_enable_txrx" +#define CFG_CDF_TRACE_ENABLE_HTC_NAME "cdf_trace_enable_htc" +#define CFG_CDF_TRACE_ENABLE_HIF_NAME "cdf_trace_enable_hif" +#define CFG_CDR_TRACE_ENABLE_HDD_SAP_DATA_NAME "cdf_trace_enable_hdd_sap_data" +#define CFG_CDF_TRACE_ENABLE_HDD_DATA_NAME "cdf_trace_enable_hdd_data" #define CFG_CDF_TRACE_ENABLE_MIN (0) #define CFG_CDF_TRACE_ENABLE_MAX (0xff) @@ -2992,6 +3000,14 @@ struct hdd_config { uint16_t cdf_trace_enable_sap; uint16_t cdf_trace_enable_hdd_sap; uint16_t cdf_trace_enable_bmi; + uint16_t cdf_trace_enable_cfg; + uint16_t cfd_trace_enable_txrx; + uint16_t cdf_trace_enable_htc; + uint16_t cdf_trace_enable_hif; + uint16_t cdf_trace_enable_hdd_sap_data; + uint16_t cdf_trace_enable_hdd_data; + uint16_t cdf_trace_enable_epping; + uint16_t cdf_trace_enable_cdf_devices; uint16_t nTeleBcnTransListenInterval; uint16_t nTeleBcnMaxListenInterval; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index e31103f60a03..95bdb0722650 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1741,6 +1741,62 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_CDF_TRACE_ENABLE_MIN, CFG_CDF_TRACE_ENABLE_MAX), + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_CFG_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_cfg, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_TXRX_NAME, WLAN_PARAM_Integer, + struct hdd_config, cfd_trace_enable_txrx, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_HTC_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_htc, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_HIF_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_hif, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDR_TRACE_ENABLE_HDD_SAP_DATA_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_hdd_sap_data, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_HDD_DATA_NAME, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_hdd_data, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_EPPING, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_epping, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + + REG_VARIABLE(CFG_CDF_TRACE_ENABLE_CDF_DEVICES, WLAN_PARAM_Integer, + struct hdd_config, cdf_trace_enable_cdf_devices, + VAR_FLAGS_OPTIONAL, + CFG_CDF_TRACE_ENABLE_DEFAULT, + CFG_CDF_TRACE_ENABLE_MIN, + CFG_CDF_TRACE_ENABLE_MAX), + REG_VARIABLE(CFG_TELE_BCN_TRANS_LI_NAME, WLAN_PARAM_Integer, struct hdd_config, nTeleBcnTransListenInterval, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 12d462acf2e2..669943275857 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4864,6 +4864,23 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_ctx->config->cdf_trace_enable_hdd_sap); hdd_cdf_trace_enable(CDF_MODULE_ID_BMI, hdd_ctx->config->cdf_trace_enable_bmi); + hdd_cdf_trace_enable(CDF_MODULE_ID_CFG, + hdd_ctx->config->cdf_trace_enable_cfg); + hdd_cdf_trace_enable(CDF_MODULE_ID_EPPING, + hdd_ctx->config->cdf_trace_enable_epping); + hdd_cdf_trace_enable(CDF_MODULE_ID_CDF_DEVICE, + hdd_ctx->config->cdf_trace_enable_cdf_devices); + hdd_cdf_trace_enable(CDF_MODULE_ID_TXRX, + hdd_ctx->config->cfd_trace_enable_txrx); + hdd_cdf_trace_enable(CDF_MODULE_ID_HTC, + hdd_ctx->config->cdf_trace_enable_htc); + hdd_cdf_trace_enable(CDF_MODULE_ID_HIF, + hdd_ctx->config->cdf_trace_enable_hif); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SAP_DATA, + hdd_ctx->config->cdf_trace_enable_hdd_sap_data); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_DATA, + hdd_ctx->config->cdf_trace_enable_hdd_data); + hdd_cfg_print(hdd_ctx); if (CDF_FTM_MODE == hdd_get_conparam()) -- cgit v1.2.3 From 832d18d6a74d6786bc4b2d9be06ddab9cfdefdae Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Thu, 12 Nov 2015 16:37:44 -0800 Subject: qcacld-3.0: Fix second P2P-GO interface fail to startup issue For P2P GO + GO concurrency cases, the second P2P GO interface failed to startup due to the incorrect checkings in the driver code for GO interface. This fixes the condition checking logic. Change-Id: I1a8a1b3dd4eed9dd8c824241d7b1759751e53a18 CRs-fixed: 938850 --- core/hdd/src/wlan_hdd_p2p.c | 16 ++++++++++------ core/sme/src/csr/csr_util.c | 5 ++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index a6d5accaad6c..dbfe8b964322 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -2124,6 +2124,7 @@ struct net_device *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, hdd_adapter_t *pAdapter = NULL; hdd_scaninfo_t *scan_info = NULL; int ret; + uint8_t session_type; ENTER(); @@ -2141,15 +2142,18 @@ struct net_device *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, MTRACE(cdf_trace(CDF_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. + * Allow addition multiple interfaces for WLAN_HDD_P2P_GO, + * WLAN_HDD_SOFTAP, WLAN_HDD_P2P_CLIENT and WLAN_HDD_INFRA_STATION + * session type. */ - if ((hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL) + session_type = wlan_hdd_get_session_type(type); + if ((hdd_get_adapter(pHddCtx, session_type) != NULL) #ifdef WLAN_FEATURE_MBSSID - && WLAN_HDD_SOFTAP != wlan_hdd_get_session_type(type) + && WLAN_HDD_SOFTAP != session_type + && WLAN_HDD_P2P_GO != session_type #endif - && WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) - && WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type)) { + && WLAN_HDD_P2P_CLIENT != session_type + && WLAN_HDD_INFRA_STATION != session_type) { hddLog(LOGE, "%s: Interface type %d already exists. " "Two interfaces of same type are not supported currently.", diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 5c0670414a10..42e351a91029 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1904,6 +1904,7 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, case CDF_P2P_GO_MODE: temp = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; +#ifndef WLAN_FEATURE_MBSSID if ((bss_persona == CDF_P2P_GO_MODE) && (connect_state != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { @@ -1911,7 +1912,9 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, CDF_TRACE_LEVEL_ERROR, FL("GO mode already exists")); return CDF_STATUS_E_FAILURE; - } else if ((bss_persona == CDF_IBSS_MODE) + } +#endif + if ((bss_persona == CDF_IBSS_MODE) && (connect_state != temp)) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, -- cgit v1.2.3 From f61614c1346049f8aecef0ace1154b7d9f92f62e Mon Sep 17 00:00:00 2001 From: Ratnam Rachuri Date: Fri, 14 Aug 2015 17:35:21 +0530 Subject: qcacld-3.0: Reduce log level from pr_err to pr_info qcacld-2.0 to qcacld-3.0 propagation Reduce log level from pr_err to pr_info to avoid excessive logging in wlan_queue_logmsg_for_app fn. Change-Id: I10b728d9fc0c46ca4b4a38a6b060f25cad124207 CRs-Fixed: 840477 --- core/utils/logging/src/wlan_logging_sock_svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index d82e008ce47c..59033f384233 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -235,7 +235,7 @@ static int wlan_queue_logmsg_for_app(void) /* print every 64th drop count */ if (cds_is_multicast_logging() && (!(gwlan_logging.drop_count % 0x40))) { - pr_err + pr_info ("%s: drop_count = %u index = %d filled_length = %d\n", __func__, gwlan_logging.drop_count, gwlan_logging.pcur_node->index, -- cgit v1.2.3 From 20902cacbd5cb54a9c428e568ac0c259f4e1db27 Mon Sep 17 00:00:00 2001 From: Ratnam Rachuri Date: Wed, 12 Aug 2015 12:20:18 +0530 Subject: qcacld-3.0: Code refactoring in SAP start qcacld-2.0 to qcacld-3.0 propagation This fix removes redundant cdf_mem_zero and cdf_mem_copy Change-Id: I757a2e14358403b7950868fd81d8e58ab3f829df CRs-Fixed: 796971 --- core/sap/src/sap_module.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 8969d4b94116..b2df4dc49de9 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -143,7 +143,6 @@ wlansap_open(void *p_cds_gctx) { #endif } - cdf_mem_zero(pSapCtx, sizeof(tSapContext)); /*------------------------------------------------------------------------ Clean up SAP control block, initialize all values @@ -526,9 +525,6 @@ wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig, * from HDD */ psap_ctx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; - cdf_mem_copy(psap_ctx->csr_roamProfile.BSSIDs.bssid, - psap_ctx->self_mac_addr, - sizeof(struct cdf_mac_addr)); /* * Save a copy to SAP context -- cgit v1.2.3 From afc06d5699b835d273dd6804dd8e30906e7ee59f Mon Sep 17 00:00:00 2001 From: Ratnam Rachuri Date: Fri, 14 Aug 2015 15:18:46 +0530 Subject: qcacld-3.0: make non-interruptable wait for Tlshim Rx shutdown qcacld-2.0 to qcacld-3.0 propagation replace wait_for_completion_interruptible with wait_for_completion to do Tlshim Rx shutdown with non-interruptible call. Change-Id: I09a70fd2818db42401ba2ca91a75244c1f07557e CRs-Fixed: 820482 --- core/cds/src/cds_sched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 07c8df060a53..873555d5d21c 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -926,8 +926,7 @@ CDF_STATUS cds_sched_close(void *p_cds_context) set_bit(RX_SHUTDOWN_EVENT_MASK, &gp_cds_sched_context->ol_rx_event_flag); set_bit(RX_POST_EVENT_MASK, &gp_cds_sched_context->ol_rx_event_flag); wake_up_interruptible(&gp_cds_sched_context->ol_rx_wait_queue); - wait_for_completion_interruptible - (&gp_cds_sched_context->ol_rx_shutdown); + wait_for_completion(&gp_cds_sched_context->ol_rx_shutdown); gp_cds_sched_context->ol_rx_thread = NULL; cds_drop_rxpkt_by_staid(gp_cds_sched_context, WLAN_MAX_STA_COUNT); cds_free_ol_rx_pkt_freeq(gp_cds_sched_context); -- cgit v1.2.3 From 19c6cb52825a7214d7eea7387b9198dacdecc39f Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Thu, 19 Nov 2015 09:57:58 +0530 Subject: qcacld-3.0: Reset global saved command to avoid double free Reset the global saved scan command to avoid double free. In sme_process_set_hw_mode_resp(), after freeing the local saved_cmd pointer, the global mac->sme.saved_scan_cmd is not reset to NULL. This ends up in double free in csr_scan_complete()->csr_handle_nxt_cmd() where we are still holding a stale pointer. CRs-Fixed: 941130 Change-Id: Ibb93b8d8e601936c7996518f21646e2c140cbd20 --- core/sme/src/common/sme_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index f4cc8df95029..f91b44ca8982 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -228,6 +228,7 @@ static CDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) if (saved_cmd) { cdf_mem_free(saved_cmd); saved_cmd = NULL; + mac->sme.saved_scan_cmd = NULL; } } else { sms_log(mac, LOGE, -- cgit v1.2.3 From ceec5c5784ced1a535919a4a58ae074a56d118c5 Mon Sep 17 00:00:00 2001 From: Prakash Dhavali Date: Mon, 16 Nov 2015 13:20:59 -0800 Subject: Enable WLAN driver build from qcacld-3.0 oss path Enable WLAN driver build from qcacld-3.0 oss path. Change-Id: Ibe10a8a0b5fc45551fdb2fed82f4eea4b48c9c56 --- Android.mk | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Android.mk b/Android.mk index 3bbcfe93ea9e..0f020f36a5fc 100644 --- a/Android.mk +++ b/Android.mk @@ -45,7 +45,11 @@ endif # Build wlan.ko as $(WLAN_CHIPSET)_wlan.ko ########################################################### # This is set once per LOCAL_PATH, not per (kernel) module -KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-new +ifeq ($(WLAN_PROPRIETARY),1) + KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-new +else + KBUILD_OPTIONS := WLAN_ROOT=../$(WLAN_BLD_DIR)/qcacld-3.0 +endif # WLAN_PROPRIETARY # We are actually building wlan.ko here, as per the # requirement we are specifying _wlan.ko as LOCAL_MODULE. # This means we need to rename the module to _wlan.ko @@ -55,7 +59,11 @@ KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(WLAN_SELECT) include $(CLEAR_VARS) -LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko +ifeq ($(WLAN_PROPRIETARY),1) + LOCAL_MODULE := proprietary_$(WLAN_CHIPSET)_wlan.ko +else + LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko +endif # WLAN_PROPRIETARY LOCAL_MODULE_KBUILD_NAME := wlan.ko LOCAL_MODULE_TAGS := debug LOCAL_MODULE_DEBUG_ENABLE := true -- cgit v1.2.3 From 3db7cbb316abd21e3f5cb1cef344024bf460e245 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Thu, 19 Nov 2015 21:52:30 -0800 Subject: Release 5.0.0.145 Release 5.0.0.145 Change-Id: Ie54534d6ea7b031527ab261ac97025d6728714cd CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 129fbe5c3d32..2eff3e8a0a40 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 144 +#define QWLAN_VERSION_BUILD 145 -#define QWLAN_VERSIONSTR "5.0.0.144" +#define QWLAN_VERSIONSTR "5.0.0.145" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 6605951f42ac05a9341e560f823095e3dcb37264 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 09:43:11 -0800 Subject: qcacld-3.0: Fix for hidden SSID iwpriv command. This is qcacld-2.0 to qcacld-3.0 propagation In lim function to process hidden SSID, current code was treating SME sessionID as PE sessionID and hence find session entry for that was failing. This patch fixes this by using correct "find pe session" API, that finds PE session by using SME session ID. Change-Id: I72286cd54a41ae9c01bd916bb0156dd3131eb71c CRs-Fixed: 934870 --- core/mac/src/pe/include/lim_session.h | 2 -- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index f027fa01a69e..5d27af28a009 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -594,7 +594,6 @@ tpPESession pe_find_session_by_sta_id(tpAniSirGlobal pMac, uint8_t staid, void pe_delete_session(tpAniSirGlobal pMac, tpPESession psessionEntry); -#ifdef FEATURE_AP_MCC_CH_AVOIDANCE /** * pe_find_session_by_sme_session_id() - looks up the PE session for given sme * session id @@ -607,6 +606,5 @@ void pe_delete_session(tpAniSirGlobal pMac, tpPESession psessionEntry); */ tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx, uint8_t sme_session_id); -#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx); #endif /* #if !defined( __LIM_SESSION_H ) */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 6bae1ccd9b32..811a24f94990 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4207,7 +4207,7 @@ static void __lim_process_sme_hide_ssid(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pUpdateParams = (tpSirUpdateParams) pMsgBuf; - psessionEntry = pe_find_session_by_session_id(pMac, + psessionEntry = pe_find_session_by_sme_session_id(pMac, pUpdateParams->sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGW, -- cgit v1.2.3 From a56fcffaca6ccfb9bf52dee5a3b1b34d6918fb0a Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 17 Nov 2015 11:50:40 -0800 Subject: qcacld-3.0: HT20 Protection Mode HT_PURE mode indicates either only HT20 STAs are connected to a HT20 only SAP or HT20/40 STAs are connected to HT20/40 SAP. Otherwise its HT20 protection mode. This patch fixes code to work accroding to this condition correctly. Change-Id: Ib431209f5dfc8800d0932752a282c954f0228503 CRs-Fixed: 866447 --- core/mac/src/pe/lim/lim_utils.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 0b9df621ecad..d34c2a30d0af 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -4256,9 +4256,10 @@ static void lim_handle_ht20protection_enabled(tpAniSirGlobal mac_ctx, } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { session_entry->gLimHt20Params.protectionEnabled = true; if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) { - session_entry->htOperMode = - eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; - + if (session_entry->htSupportedChannelWidthSet != + eHT_CHANNEL_WIDTH_20MHZ) + session_entry->htOperMode = + eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; lim_enable_ht_rifs_protection(mac_ctx, false, overlap, beaconparams, session_entry); lim_enable_ht_obss_protection(mac_ctx, false, -- cgit v1.2.3 From a4215acb603b28a77c60b938d7bf9b9cd58dad4c Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 16:15:25 -0800 Subject: qcacld: Fix layering violation in __wlan_hdd_cfg80211_ocb_start_timing_advert() This is qcacld-2.0 to qcacld-3.0 propagation HDD directly calls in to MAC layer function with mac context as one of the parameters which is a software layering violation. Fix the issue by introducing a SME api which accepts hal handle as one of the parameters instead of mac context and call the SME function from HDD, which calls the MAC api with correct function parameters. Change-Id: Iaac4ad7b67b0cb0f7b8b0d08e32904833afad707 CRs-Fixed: 913015 --- core/hdd/src/wlan_hdd_ocb.c | 3 +-- core/sme/inc/sme_api.h | 4 ++++ core/sme/src/common/sme_api.c | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index a34959d2f292..10674cbfcff0 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -1202,7 +1202,6 @@ __wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, 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; @@ -1256,7 +1255,7 @@ __wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE]); timing_advert->template_length = - sch_gen_timing_advert_frame(mac_ctx, + sme_ocb_gen_timing_advert_frame(hdd_ctx->hHal, *(tSirMacAddr *)&adapter->macAddressCurrent.bytes, &timing_advert->template_value, &timing_advert->timestamp_offset, diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 43a6e8d8b1d9..c8e1e361e4e1 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1026,6 +1026,10 @@ CDF_STATUS sme_ocb_start_timing_advert(tHalHandle hHal, CDF_STATUS sme_ocb_stop_timing_advert(tHalHandle hHal, struct sir_ocb_timing_advert *timing_advert); +int sme_ocb_gen_timing_advert_frame(tHalHandle hHal, tSirMacAddr self_addr, + uint8_t **buf, uint32_t *timestamp_offset, + uint32_t *time_value_offset); + CDF_STATUS sme_ocb_get_tsf_timer(tHalHandle hHal, void *context, ocb_callback callback, struct sir_ocb_get_tsf_timer *request); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index f91b44ca8982..ac42abd8e347 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -58,6 +58,7 @@ #include "cfg_api.h" #include "sme_power_save_api.h" #include "wma.h" +#include "sch_api.h" extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb); @@ -10935,6 +10936,29 @@ end: return status; } +/** + * sme_ocb_gen_timing_advert_frame() - generate TA frame and populate the buffer + * @hal_handle: reference to the HAL + * @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 sme_ocb_gen_timing_advert_frame(tHalHandle hal_handle, + tSirMacAddr self_addr, uint8_t **buf, + uint32_t *timestamp_offset, + uint32_t *time_value_offset) +{ + int template_length; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle); + + template_length = sch_gen_timing_advert_frame(mac_ctx, self_addr, buf, + timestamp_offset, + time_value_offset); + return template_length; +} /** * sme_ocb_get_tsf_timer() - Get the TSF timer value * @hHal: reference to the HAL -- cgit v1.2.3 From 01213a4d2a7396af57f89b6292026ff6ce217b2f Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 25 Sep 2015 09:40:47 -0700 Subject: qcacld-3.0: Allocate for cfg int and str buffer dynamically This is pass 2 of cfg mechanism enahancement. With this patch cfg int and cfg str buffer are allocated dynamically so no need to maintain CFG_STA_IBUF_MAX_SIZE and CFG_STA_SBUF_MAX_SIZE manually. Change-Id: I0f8cb942e93236546aad9963c9451e0399a251ac CRs-Fixed: 914157 --- core/mac/inc/wni_cfg.h | 2 -- core/mac/src/cfg/cfg_api.c | 63 +++++++++++++++++++++++++++++++++------ core/mac/src/cfg/cfg_proc_msg.c | 8 +---- core/mac/src/include/cfg_global.h | 5 ++-- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index e151fa5adab9..5bc0476e97e3 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -1549,8 +1549,6 @@ enum { #define WNI_CFG_TDLS_WMM_MODE_ENABLED_STADEF 0 #define CFG_PARAM_MAX_NUM 286 -#define CFG_STA_IBUF_MAX_SIZE 234 -#define CFG_STA_SBUF_MAX_SIZE 3199 #define CFG_STA_MAGIC_DWORD 0xbeefbeef diff --git a/core/mac/src/cfg/cfg_api.c b/core/mac/src/cfg/cfg_api.c index a91f5df8ffd8..6e3d63e8f343 100644 --- a/core/mac/src/cfg/cfg_api.c +++ b/core/mac/src/cfg/cfg_api.c @@ -46,10 +46,6 @@ /* Static Variables */ /* ---------------------------------------------------------------------- */ static tCfgCtl __g_cfg_entry[CFG_PARAM_MAX_NUM]; -static uint32_t __g_cfg_i_buf_min[CFG_STA_IBUF_MAX_SIZE]; -static uint32_t __g_cfg_i_buf_max[CFG_STA_IBUF_MAX_SIZE]; -static uint32_t __g_cfg_i_buf[CFG_STA_IBUF_MAX_SIZE]; -static uint8_t __g_cfg_s_buf[CFG_STA_SBUF_MAX_SIZE]; static uint8_t __g_s_buffer[CFG_MAX_STR_LEN]; static uint32_t __g_param_list[WNI_CFG_MAX_PARAM_NUM + WNI_CFG_GET_PER_STA_STAT_RSP_NUM]; @@ -104,10 +100,11 @@ uint32_t cfg_need_reload(tpAniSirGlobal pMac, uint16_t cfgId) tSirRetStatus cfg_init(tpAniSirGlobal pMac) { uint16_t i = 0; - pMac->cfg.gCfgIBufMin = __g_cfg_i_buf_min; - pMac->cfg.gCfgIBufMax = __g_cfg_i_buf_max; - pMac->cfg.gCfgIBuf = __g_cfg_i_buf; - pMac->cfg.gCfgSBuf = __g_cfg_s_buf; + uint16_t combined_buff_size = 0; + uint32_t max_i_count = 0; + uint32_t max_s_count = 0; + cfgstatic_string *str_cfg; + pMac->cfg.gSBuffer = __g_s_buffer; pMac->cfg.gCfgEntry = __g_cfg_entry; pMac->cfg.gParamList = __g_param_list; @@ -119,12 +116,60 @@ tSirRetStatus cfg_init(tpAniSirGlobal pMac) cfg_static[i].pStrData = NULL; } } + + for (i = 0; i < CFG_PARAM_MAX_NUM ; i++) { + if (cfg_static[i].control & CFG_CTL_INT) { + max_i_count++; + } else { + str_cfg = (cfgstatic_string *)cfg_static[i].pStrData; + if (str_cfg == NULL) { + cfg_log(pMac, LOGE, + FL("pStrCfg is NULL for CfigID : %d"), + i); + continue; + } + /* + 2 to include len field and max len field */ + max_s_count += str_cfg->maxLen + 2; + } + } + + pMac->cfg.gCfgMaxIBufSize = max_i_count; + pMac->cfg.gCfgMaxSBufSize = max_s_count; + + /* Allocate a combined memory */ + combined_buff_size = max_s_count + (3 * sizeof(uint32_t) * max_i_count); + + cfg_log(pMac, LOGE, FL("Size of cfg I buffer:%d S buffer: %d"), + max_i_count, max_s_count); + + cfg_log(pMac, LOGE, FL("Allocation for cfg buffers: %d bytes"), + combined_buff_size); + + if (combined_buff_size > 4 * PAGE_SIZE) { + cfg_log(pMac, LOGE, FL("Mem alloc request too big")); + return eSIR_MEM_ALLOC_FAILED; + } + /* at this point pMac->cfg.gCfgSBuf starts */ + pMac->cfg.gCfgSBuf = cdf_mem_malloc(combined_buff_size); + if (NULL == pMac->cfg.gCfgSBuf) { + cfg_log(pMac, LOGE, + FL("Failed to allocate memory for cfg array")); + return eSIR_MEM_ALLOC_FAILED; + } + /* at offset max_s_count, pMac->cfg.gCfgIBuf starts */ + pMac->cfg.gCfgIBuf = (uint32_t *)&pMac->cfg.gCfgSBuf[max_s_count]; + /* after max_i_count integers, pMac->cfg.gCfgIBufMin starts */ + pMac->cfg.gCfgIBufMin = &pMac->cfg.gCfgIBuf[max_i_count]; + /* after max_i_count integers, pMac->cfg.gCfgIBufMax starts */ + pMac->cfg.gCfgIBufMax = &pMac->cfg.gCfgIBufMin[max_i_count]; + return (eSIR_SUCCESS); } /* ---------------------------------------------------------------------- */ void cfg_de_init(tpAniSirGlobal pMac) { + cdf_mem_free(pMac->cfg.gCfgSBuf); pMac->cfg.gCfgIBufMin = NULL; pMac->cfg.gCfgIBufMax = NULL; pMac->cfg.gCfgIBuf = NULL; @@ -176,7 +221,7 @@ tSirRetStatus cfg_check_valid(tpAniSirGlobal pMac, uint16_t cfgId, *index = control & CFG_BUF_INDX_MASK; - if (*index >= CFG_STA_SBUF_MAX_SIZE) { + if (*index >= pMac->cfg.gCfgMaxSBufSize) { PELOGE(cfg_log(pMac, LOGE, FL("cfg index out of bounds %d"), *index);) return eSIR_CFG_INVALID_ID; diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c index dc29f0aba022..97ee82f9fc83 100644 --- a/core/mac/src/cfg/cfg_proc_msg.c +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -1886,12 +1886,6 @@ static void proc_dnld_rsp(tpAniSirGlobal pMac, uint16_t length, uint32_t *pParam 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); @@ -2554,7 +2548,7 @@ process_cfg_download_req(tpAniSirGlobal pMac) uint8_t maxSavedLen; if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0) continue; - if (index >= CFG_STA_SBUF_MAX_SIZE) + if (index >= pMac->cfg.gCfgMaxSBufSize) continue; pDstTest = &pMac->cfg.gCfgSBuf[index]; diff --git a/core/mac/src/include/cfg_global.h b/core/mac/src/include/cfg_global.h index 8678f27daf4e..960efac0bf5b 100644 --- a/core/mac/src/include/cfg_global.h +++ b/core/mac/src/include/cfg_global.h @@ -77,10 +77,11 @@ typedef struct sAniSirCfg { uint8_t gCfgStatus; tCfgCtl *gCfgEntry; + + uint8_t *gCfgSBuf; + uint32_t *gCfgIBuf; uint32_t *gCfgIBufMin; uint32_t *gCfgIBufMax; - uint32_t *gCfgIBuf; - uint8_t *gCfgSBuf; uint16_t gCfgMaxIBufSize; uint16_t gCfgMaxSBufSize; -- cgit v1.2.3 From e8df7b2e33315a5ff84c70c9063e9024f7f24482 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 06:57:32 -0800 Subject: qcacld-3.0: Allow dwell time for PNO scan control through config.ini This is qcacld-2.0 to qcacld-3.0 propagation Currently dwell time for PNO scan is passed as 0 to FW irrespective of values set in config.ini. This patch allows active/passive dwell time for PNO scan to be controlled by config.ini param. Change-Id: I5562ed7e176af04ac8f38aa5af97257b9244cdc1 CRs-Fixed: 922054 --- core/mac/inc/sir_api.h | 5 +++++ core/sme/src/common/sme_power_save.c | 22 ++++++++++++++++++++++ core/wma/src/wma_scan_roam.c | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 7f1f5232bb0c..22d3c253b120 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2746,6 +2746,11 @@ typedef struct sSirPNOScanReq { tSirScanTimersType scanTimers; uint8_t sessionId; + 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; diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c index ba4ec34ea34c..be463897a2f8 100644 --- a/core/sme/src/common/sme_power_save.c +++ b/core/sme/src/common/sme_power_save.c @@ -907,6 +907,28 @@ CDF_STATUS sme_set_ps_preferred_network_list(tHalHandle hal_ctx, request_buf->sessionId = session_id; } sme_set_pno_channel_prediction(request_buf, mac_ctx); + + if (csr_is_p2p_session_connected(mac_ctx)) { + /* if AP-STA concurrency is active */ + request_buf->active_max_time = + mac_ctx->roam.configParam.nActiveMaxChnTimeConc; + request_buf->active_min_time = + mac_ctx->roam.configParam.nActiveMinChnTimeConc; + request_buf->passive_max_time = + mac_ctx->roam.configParam.nPassiveMaxChnTimeConc; + request_buf->passive_min_time = + mac_ctx->roam.configParam.nPassiveMinChnTimeConc; + } else { + request_buf->active_max_time = + mac_ctx->roam.configParam.nActiveMaxChnTime; + request_buf->active_min_time = + mac_ctx->roam.configParam.nActiveMinChnTime; + request_buf->passive_max_time = + mac_ctx->roam.configParam.nPassiveMaxChnTime; + request_buf->passive_min_time = + mac_ctx->roam.configParam.nPassiveMinChnTime; + } + msg.type = WMA_SET_PNO_REQ; msg.reserved = 0; msg.bodyptr = request_buf; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index bc08c24c6756..a3a98f390d24 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3527,6 +3527,10 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) 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; + /* Copy scan interval */ if (pno->scanTimers.ucScanTimersCount) { cmd->fast_scan_period = -- cgit v1.2.3 From 07acefecec0d0d3e7fba65e7a88217137a455267 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 19 Oct 2015 17:42:01 +0530 Subject: qcacld-3.0: Implement ECSA Action Frame qcacld-2.0 to qcacld-3.0 propagation. Implement: 1. Send & receive logic of ECSA action frame from P2P-CLI/GO 2. Trigger channel change on P2P GO side once ECSA action frame is received by, i) Adding CSA & ESCA IE in beacon template and updating FW to send it out ii) Notifying supplicant of channel change for P2P GO. This change include UMAC changes. CRs-fixed: 895240 Change-Id: Ie6c9154fb44ec75c699e37aaba660c637869c099 --- core/mac/inc/sir_api.h | 24 + core/mac/inc/sir_mac_prot_def.h | 6 + core/mac/inc/wni_api.h | 2 + core/mac/src/cfg/cfgUtil/dot11f.frms | 16 + core/mac/src/include/dot11f.h | 56 +- core/mac/src/pe/lim/lim_process_action_frame.c | 111 +- core/mac/src/pe/lim/lim_process_message_queue.c | 1 + core/mac/src/pe/lim/lim_process_sme_req_messages.c | 106 ++ core/mac/src/pe/lim/lim_send_management_frames.c | 133 ++ core/mac/src/pe/lim/lim_types.h | 4 + core/mac/src/pe/sch/sch_beacon_gen.c | 9 + core/mac/src/sys/legacy/src/utils/src/dot11f.c | 1866 ++++++++++---------- core/sap/inc/sap_api.h | 12 +- core/sap/src/sap_api_link_cntl.c | 10 + core/sap/src/sap_fsm.c | 9 +- core/sap/src/sap_module.c | 10 +- core/sme/inc/csr_api.h | 4 + core/sme/inc/sme_api.h | 2 + core/sme/src/common/sme_api.c | 85 + core/sme/src/csr/csr_api_roam.c | 30 + core/sme/src/csr/csr_inside_api.h | 2 + 21 files changed, 1603 insertions(+), 895 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 22d3c253b120..3fc95da65826 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5396,4 +5396,28 @@ enum powersave_mode { PS_DUTY_CYCLING_QPOWER = 5 }; +/** + * 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; +}; + #endif /* __SIR_API_H */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index ccc2dcefbfad..20c1516cf503 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -214,6 +214,8 @@ /* 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 */ @@ -355,6 +357,10 @@ #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_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 diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 9c279eada39e..ca7bf580ecf1 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -247,6 +247,8 @@ enum eWniMsgTypes { eWNI_SME_ROC_CMD, eWNI_SME_SET_THERMAL_LEVEL_IND, eWNI_SME_SET_IE_REQ, + eWNI_SME_EXT_CHANGE_CHANNEL, + eWNI_SME_EXT_CHANGE_CHANNEL_IND, eWNI_SME_MSG_TYPES_END }; diff --git a/core/mac/src/cfg/cfgUtil/dot11f.frms b/core/mac/src/cfg/cfgUtil/dot11f.frms index 04165e7907e4..3c9004a007ae 100644 --- a/core/mac/src/cfg/cfgUtil/dot11f.frms +++ b/core/mac/src/cfg/cfgUtil/dot11f.frms @@ -390,6 +390,15 @@ 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 // @@ -3600,6 +3609,13 @@ FRAME TimingAdvertisementFrame // 8.3.3.15 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 diff --git a/core/mac/src/include/dot11f.h b/core/mac/src/include/dot11f.h index 0258abdf8f06..09dfde671127 100644 --- a/core/mac/src/include/dot11f.h +++ b/core/mac/src/include/dot11f.h @@ -35,7 +35,7 @@ * * * This file was automatically generated by 'framesc' - * Wed Oct 14 10:14:42 2015 from the following file(s): + * Mon Nov 16 10:55:21 2015 from the following file(s): * * dot11f.frms * @@ -544,6 +544,32 @@ void dot11f_pack_ff_vht_user_position_array(tpAniSirGlobal, uint8_t *); +typedef struct sDot11fFfext_chan_switch_ann_action { + uint32_t switch_mode:8; + uint32_t op_class:8; + uint32_t new_channel:8; + uint32_t switch_count:8; +} tDot11fFfext_chan_switch_ann_action; + +#define DOT11F_FF_EXT_CHAN_SWITCH_ANN_ACTION_LEN (4) + +void dot11f_unpack_ff_ext_chan_switch_ann_action(tpAniSirGlobal, uint8_t *, + tDot11fFfext_chan_switch_ann_action *); + +void dot11f_pack_ff_ext_chan_switch_ann_action(tpAniSirGlobal, + tDot11fFfext_chan_switch_ann_action *, + uint8_t *); + + +#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 * ********************************************************************/ @@ -8890,6 +8916,32 @@ uint32_t dot11f_get_packed_wmm_del_ts_size(tpAniSirGlobal pCtx, } /* 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 (46) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ + +uint32_t dot11f_unpack_ext_channel_switch_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fext_channel_switch_action_frame * pFrm); +uint32_t dot11f_pack_ext_channel_switch_action_frame(tpAniSirGlobal pCtx, + tDot11fext_channel_switch_action_frame *pFrm, uint8_t *pBuf, + uint32_t nBuf, uint32_t *pnConsumed); +uint32_t dot11f_get_packed_ext_channel_switch_action_frame_size(tpAniSirGlobal pCtx, + tDot11fext_channel_switch_action_frame *pFrm, + uint32_t *pnNeeded); + +#ifdef __cplusplus +} /* End extern "C". */ +#endif /* C++ */ + typedef struct sDot11fht2040_bss_coexistence_mgmt_action_frame{ tDot11fFfCategory Category; tDot11fFfAction Action; @@ -8897,7 +8949,7 @@ typedef struct sDot11fht2040_bss_coexistence_mgmt_action_frame{ tDot11fIEht2040_bss_intolerant_report ht2040_bss_intolerant_report; } tDot11fht2040_bss_coexistence_mgmt_action_frame; -#define DOT11F_HT2040_BSS_COEXISTENCE_MGMT_ACTION_FRAME (46) +#define DOT11F_HT2040_BSS_COEXISTENCE_MGMT_ACTION_FRAME (47) #ifdef __cplusplus extern "C" { diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index c77ae536ae93..15d039276b4d 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -56,7 +56,7 @@ #include "rrm_api.h" #endif #include "lim_session_utils.h" - +#include "cds_concurrency.h" #include "wma_types.h" @@ -338,6 +338,110 @@ static void __lim_process_channel_switch_action_frame(tpAniSirGlobal mac_ctx, return; } +/** + * 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 = WMA_GET_RX_MAC_HEADER(rx_packet_info); + body = WMA_GET_RX_MPDU_DATA(rx_packet_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info); + + lim_log(mac_ctx, LOG1, FL("Received EXT Channel switch action frame")); + + ext_channel_switch_frame = + cdf_mem_malloc(sizeof(*ext_channel_switch_frame)); + if (NULL == ext_channel_switch_frame) { + lim_log(mac_ctx, LOGE, FL("AllocateMemory failed")); + return; + } + + /* Unpack channel switch frame */ + status = dot11f_unpack_ext_channel_switch_action_frame(mac_ctx, + body, frame_len, ext_channel_switch_frame); + + if (DOT11F_FAILED(status)) { + + lim_log(mac_ctx, LOGE, + FL("Failed to parse CHANSW action frame (0x%08x, len %d):"), + status, frame_len); + cdf_mem_free(ext_channel_switch_frame); + return; + } else if (DOT11F_WARNED(status)) { + + lim_log(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 */ + cdf_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) && + ((cds_get_channel_state(target_channel) + == CHANNEL_STATE_ENABLE) || + (cds_get_channel_state(target_channel) == CHANNEL_STATE_DFS && + !cds_concurrent_open_sessions_running())))) { + lim_log(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 = cdf_mem_malloc(sizeof(*ext_cng_chan_ind)); + if (NULL == ext_cng_chan_ind) { + lim_log(mac_ctx, LOGP, + FL("AllocateMemory failed for ext_cng_chan_ind")); + return; + } + + cdf_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; + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); + } + return; +} /*** end lim_process_ext_channel_switch_action_frame() ***/ + #ifdef WLAN_FEATURE_11AC /** * __lim_process_operating_mode_action_frame() - To process op mode frames @@ -1943,7 +2047,10 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, WMA_GET_RX_CH(rx_pkt_info), session, rssi); break; #endif - + case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID: + lim_process_ext_channel_switch_action_frame(mac_ctx, + rx_pkt_info, session); + break; default: lim_log(mac_ctx, LOGE, FL("Unhandled public action frame -- %x "), diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 25e7ed1a5c06..bdd66b31434a 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1353,6 +1353,7 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) #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: /* These messages are from HDD.No need to respond to HDD */ lim_process_normal_hdd_msg(mac_ctx, msg, false); break; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 811a24f94990..b0b85524b5fb 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -64,6 +64,7 @@ #if defined WLAN_FEATURE_VOWIFI_11R #include #endif +#include "cds_regdomain_common.h" /* * This overhead is time for sending NOA start to host in case of GO/sending @@ -114,6 +115,10 @@ static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg); extern void pe_register_wma_handle(tpAniSirGlobal pMac); +static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, + uint32_t *msg); + + /** * lim_process_set_hw_mode() - Send set HW mode command to WMA * @mac: Globacl MAC pointer @@ -4988,6 +4993,9 @@ bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_SET_IE_REQ: lim_process_set_ie_req(pMac, pMsgBuf); break; + case eWNI_SME_EXT_CHANGE_CHANNEL: + lim_process_ext_change_channel(pMac, pMsgBuf); + break; default: cdf_mem_free((void *)pMsg->bodyptr); pMsg->bodyptr = NULL; @@ -5464,6 +5472,58 @@ end: update_ie->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 = cds_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 == 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); + } + +} + /** * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req * @@ -5595,9 +5655,55 @@ skip_vht: lim_send_beacon_ind(mac_ctx, session_entry); lim_log(mac_ctx, LOG1, FL("Updated CSA IE, IE COUNT = %d"), session_entry->gLimChannelSwitch.switchCount); + /* Send ECSA Action frame after updating the beacon */ + send_extended_chan_switch_action_frame(mac_ctx, + session_entry->gLimChannelSwitch.primaryChannel, + session_entry->gLimChannelSwitch.ch_width, + session_entry); session_entry->gLimChannelSwitch.switchCount--; } +/** + * 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) { + lim_log(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) { + lim_log(mac_ctx, LOGE, + FL("Session not found for given session %d"), + ext_chng_channel->session_id); + return; + } + if (LIM_IS_AP_ROLE(session_entry)) { + lim_log(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); +} + /** * lim_process_nss_update_request() - process sme nss update req * diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 74c9cbf7e0ca..484a5d7ac332 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -4092,6 +4092,139 @@ lim_send_channel_switch_mgmt_frame(tpAniSirGlobal pMac, } /* End lim_send_channel_switch_mgmt_frame. */ +/** + * 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; + tpSirMacMgmtHdr mac_hdr; + uint32_t num_bytes, n_payload, status; + void *packet; + CDF_STATUS cdf_status; + uint8_t txFlag = 0; + uint8_t sme_session_id = 0; + + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, FL("Session entry is NULL!!!")); + return eSIR_FAILURE; + } + + sme_session_id = session_entry->smeSessionId; + + cdf_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 = dot11f_get_packed_ext_channel_switch_action_frame_size(mac_ctx, + &frm, &n_payload); + if (DOT11F_FAILED(status)) { + lim_log(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)) { + lim_log(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); + + cdf_status = cds_packet_alloc((uint16_t)num_bytes, + (void **) &frame, (void **) &packet); + + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGP, + FL("Failed to allocate %d bytes for a Ext Channel Switch."), + num_bytes); + return eSIR_FAILURE; + } + + /* Paranoia*/ + cdf_mem_set(frame, num_bytes, 0); + + /* Next, we fill out the buffer descriptor */ + lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer, session_entry->selfMacAddr); + mac_hdr = (tpSirMacMgmtHdr) frame; + cdf_mem_copy((uint8_t *) mac_hdr->bssId, + (uint8_t *) session_entry->bssId, + sizeof(tSirMacAddr)); + + status = dot11f_pack_ext_channel_switch_action_frame(mac_ctx, &frm, + frame + sizeof(tSirMacMgmtHdr), n_payload, &n_payload); + if (DOT11F_FAILED(status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to pack a Channel Switch 0x%08x."), + status); + cds_packet_free((void *)packet); + return eSIR_FAILURE; + } else if (DOT11F_WARNED(status)) { + lim_log(mac_ctx, LOGW, + FL("There were warnings while packing a Channel Switch 0x%08x."), + status); + } + + if ((SIR_BAND_5_GHZ == + lim_get_rf_band(session_entry->currentOperChannel)) || + (session_entry->pePersona == CDF_P2P_CLIENT_MODE) || + (session_entry->pePersona == CDF_P2P_GO_MODE)) { + txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; + } + + lim_log(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(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, + session_entry->peSessionId, mac_hdr->fc.subType)); + cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) num_bytes, + TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7, + lim_tx_complete, frame, + txFlag, sme_session_id, 0); + MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, + session_entry->peSessionId, cdf_status)); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + lim_log(mac_ctx, LOGE, + FL("Failed to send a Ext Channel Switch %X!"), + cdf_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 lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 715e7751e7ae..a61a9cadba00 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -496,6 +496,10 @@ tSirRetStatus lim_send_channel_switch_mgmt_frame(tpAniSirGlobal, tSirMacAddr, uint8_t, uint8_t, uint8_t, 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 lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, tSirMacAddr peer, uint8_t nMode, diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 365b3492fa01..7e0b23cbf2d9 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -573,6 +573,15 @@ void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac, } + /* EXT Channel Switch Announcement CHNL_EXTENDED_SWITCH_ANN_EID*/ + if (beacon2->ext_chan_switch_ann.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID); + cdf_mem_copy((void *)&prb_rsp->ext_chan_switch_ann, + (void *)&beacon2->ext_chan_switch_ann, + sizeof(beacon2->ext_chan_switch_ann)); + } + #ifdef FEATURE_AP_MCC_CH_AVOIDANCE if (beacon2->QComVendorIE.present) { set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, diff --git a/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/core/mac/src/sys/legacy/src/utils/src/dot11f.c index 6286a019287e..aed4bd917005 100644 --- a/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -33,7 +33,7 @@ * * * This file was automatically generated by 'framesc' - * Wed Oct 14 10:14:42 2015 from the following file(s): + * Mon Nov 16 10:55:21 2015 from the following file(s): * * dot11f.frms * @@ -767,6 +767,21 @@ void dot11f_unpack_ff_vht_user_position_array(tpAniSirGlobal pCtx, #define SigFfVhtUserPositionArray (0x001e) +void dot11f_unpack_ff_ext_chan_switch_ann_action(tpAniSirGlobal pCtx, + uint8_t *pBuf, + tDot11fFfext_chan_switch_ann_action *pDst) +{ + uint32_t tmp4__; + framesntohl(pCtx, &tmp4__, pBuf, 0); + pDst->switch_mode = tmp4__ >> 0 & 0xff; + pDst->op_class = tmp4__ >> 8 & 0xff; + pDst->new_channel = tmp4__ >> 16 & 0xff; + pDst->switch_count = tmp4__ >> 24 & 0xff; + (void)pCtx; +} /* End dot11f_unpack_ff_ext_chan_switch_ann_action. */ + +#define SigFfext_chan_switch_ann_action (0x001f) + uint32_t dot11f_unpack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx, uint8_t *pBuf, uint16_t tlvlen, @@ -793,13 +808,13 @@ uint32_t dot11f_unpack_tlv_version2(tpAniSirGlobal pCtx, tDot11fTLVVersion2 *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp4__; + uint8_t tmp5__; pDst->present = 1; - tmp4__ = *pBuf; + tmp5__ = *pBuf; pBuf += 1; tlvlen -= 1; - pDst->minor = tmp4__ >> 0 & 0xf; - pDst->major = tmp4__ >> 4 & 0xf; + pDst->minor = tmp5__ >> 0 & 0xf; + pDst->major = tmp5__ >> 4 & 0xf; (void)pCtx; return status; } /* End dot11f_unpack_tlv_version2. */ @@ -1268,13 +1283,13 @@ uint32_t dot11f_unpack_tlv_version(tpAniSirGlobal pCtx, tDot11fTLVVersion *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp5__; + uint8_t tmp6__; pDst->present = 1; - tmp5__ = *pBuf; + tmp6__ = *pBuf; pBuf += 1; tlvlen -= 1; - pDst->minor = tmp5__ >> 0 & 0xf; - pDst->major = tmp5__ >> 4 & 0xf; + pDst->minor = tmp6__ >> 0 & 0xf; + pDst->major = tmp6__ >> 4 & 0xf; (void)pCtx; return status; } /* End dot11f_unpack_tlv_version. */ @@ -1329,16 +1344,16 @@ uint32_t dot11f_unpack_ie_gtk(tpAniSirGlobal pCtx, tDot11fIEGTK *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp6__; + uint16_t tmp7__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohs(pCtx, &tmp6__, pBuf, 0); + framesntohs(pCtx, &tmp7__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->keyId = tmp6__ >> 0 & 0x3; - pDst->reserved = tmp6__ >> 2 & 0x3feb; + pDst->keyId = tmp7__ >> 0 & 0x3; + pDst->reserved = tmp7__ >> 2 & 0x3feb; pDst->keyLength = *pBuf; pBuf += 1; ielen -= (uint8_t)1; @@ -1635,59 +1650,59 @@ uint32_t dot11f_unpack_ie_rrm_enabled_cap(tpAniSirGlobal pCtx, tDot11fIERRMEnabledCap *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp7__; uint8_t tmp8__; uint8_t tmp9__; uint8_t tmp10__; uint8_t tmp11__; + uint8_t tmp12__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp7__ = *pBuf; - pBuf += 1; - ielen -= 1; - pDst->LinkMeasurement = tmp7__ >> 0 & 0x1; - pDst->NeighborRpt = tmp7__ >> 1 & 0x1; - pDst->parallel = tmp7__ >> 2 & 0x1; - pDst->repeated = tmp7__ >> 3 & 0x1; - pDst->BeaconPassive = tmp7__ >> 4 & 0x1; - pDst->BeaconActive = tmp7__ >> 5 & 0x1; - pDst->BeaconTable = tmp7__ >> 6 & 0x1; - pDst->BeaconRepCond = tmp7__ >> 7 & 0x1; tmp8__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->FrameMeasurement = tmp8__ >> 0 & 0x1; - pDst->ChannelLoad = tmp8__ >> 1 & 0x1; - pDst->NoiseHistogram = tmp8__ >> 2 & 0x1; - pDst->statistics = tmp8__ >> 3 & 0x1; - pDst->LCIMeasurement = tmp8__ >> 4 & 0x1; - pDst->LCIAzimuth = tmp8__ >> 5 & 0x1; - pDst->TCMCapability = tmp8__ >> 6 & 0x1; - pDst->triggeredTCM = tmp8__ >> 7 & 0x1; + pDst->LinkMeasurement = tmp8__ >> 0 & 0x1; + pDst->NeighborRpt = tmp8__ >> 1 & 0x1; + pDst->parallel = tmp8__ >> 2 & 0x1; + pDst->repeated = tmp8__ >> 3 & 0x1; + pDst->BeaconPassive = tmp8__ >> 4 & 0x1; + pDst->BeaconActive = tmp8__ >> 5 & 0x1; + pDst->BeaconTable = tmp8__ >> 6 & 0x1; + pDst->BeaconRepCond = tmp8__ >> 7 & 0x1; tmp9__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->APChanReport = tmp9__ >> 0 & 0x1; - pDst->RRMMIBEnabled = tmp9__ >> 1 & 0x1; - pDst->operatingChanMax = tmp9__ >> 2 & 0x7; - pDst->nonOperatinChanMax = tmp9__ >> 5 & 0x7; + pDst->FrameMeasurement = tmp9__ >> 0 & 0x1; + pDst->ChannelLoad = tmp9__ >> 1 & 0x1; + pDst->NoiseHistogram = tmp9__ >> 2 & 0x1; + pDst->statistics = tmp9__ >> 3 & 0x1; + pDst->LCIMeasurement = tmp9__ >> 4 & 0x1; + pDst->LCIAzimuth = tmp9__ >> 5 & 0x1; + pDst->TCMCapability = tmp9__ >> 6 & 0x1; + pDst->triggeredTCM = tmp9__ >> 7 & 0x1; tmp10__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->MeasurementPilot = tmp10__ >> 0 & 0x7; - pDst->MeasurementPilotEnabled = tmp10__ >> 3 & 0x1; - pDst->NeighborTSFOffset = tmp10__ >> 4 & 0x1; - pDst->RCPIMeasurement = tmp10__ >> 5 & 0x1; - pDst->RSNIMeasurement = tmp10__ >> 6 & 0x1; - pDst->BssAvgAccessDelay = tmp10__ >> 7 & 0x1; + pDst->APChanReport = tmp10__ >> 0 & 0x1; + pDst->RRMMIBEnabled = tmp10__ >> 1 & 0x1; + pDst->operatingChanMax = tmp10__ >> 2 & 0x7; + pDst->nonOperatinChanMax = tmp10__ >> 5 & 0x7; tmp11__ = *pBuf; - pDst->BSSAvailAdmission = tmp11__ >> 0 & 0x1; - pDst->AntennaInformation = tmp11__ >> 1 & 0x1; - pDst->fine_time_meas_rpt = tmp11__ >> 2 & 0x1; - pDst->lci_capability = tmp11__ >> 3 & 0x1; - pDst->reserved = tmp11__ >> 4 & 0xf; + pBuf += 1; + ielen -= 1; + pDst->MeasurementPilot = tmp11__ >> 0 & 0x7; + pDst->MeasurementPilotEnabled = tmp11__ >> 3 & 0x1; + pDst->NeighborTSFOffset = tmp11__ >> 4 & 0x1; + pDst->RCPIMeasurement = tmp11__ >> 5 & 0x1; + pDst->RSNIMeasurement = tmp11__ >> 6 & 0x1; + pDst->BssAvgAccessDelay = tmp11__ >> 7 & 0x1; + tmp12__ = *pBuf; + pDst->BSSAvailAdmission = tmp12__ >> 0 & 0x1; + pDst->AntennaInformation = tmp12__ >> 1 & 0x1; + pDst->fine_time_meas_rpt = tmp12__ >> 2 & 0x1; + pDst->lci_capability = tmp12__ >> 3 & 0x1; + pDst->reserved = tmp12__ >> 4 & 0xf; (void)pCtx; return status; } /* End dot11f_unpack_ie_rrm_enabled_cap. */ @@ -1746,18 +1761,18 @@ uint32_t dot11f_unpack_ie_schedule(tpAniSirGlobal pCtx, tDot11fIESchedule *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp12__; + uint16_t tmp13__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohs(pCtx, &tmp12__, pBuf, 0); + framesntohs(pCtx, &tmp13__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->aggregation = tmp12__ >> 0 & 0x1; - pDst->tsid = tmp12__ >> 1 & 0xf; - pDst->direction = tmp12__ >> 5 & 0x3; - pDst->reserved = tmp12__ >> 7 & 0x1ff; + pDst->aggregation = tmp13__ >> 0 & 0x1; + pDst->tsid = tmp13__ >> 1 & 0xf; + pDst->direction = tmp13__ >> 5 & 0x3; + pDst->reserved = tmp13__ >> 7 & 0x1ff; framesntohl(pCtx, &pDst->service_start_time, pBuf, 0); pBuf += 4; ielen -= (uint8_t)4; @@ -1893,34 +1908,34 @@ uint32_t dot11f_unpack_ie_tspec(tpAniSirGlobal pCtx, tDot11fIETSPEC *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp13__; - uint8_t tmp14__; - uint16_t tmp15__; + uint16_t tmp14__; + uint8_t tmp15__; + uint16_t tmp16__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohs(pCtx, &tmp13__, pBuf, 0); + framesntohs(pCtx, &tmp14__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->traffic_type = tmp13__ >> 0 & 0x1; - pDst->tsid = tmp13__ >> 1 & 0xf; - pDst->direction = tmp13__ >> 5 & 0x3; - pDst->access_policy = tmp13__ >> 7 & 0x3; - pDst->aggregation = tmp13__ >> 9 & 0x1; - pDst->psb = tmp13__ >> 10 & 0x1; - pDst->user_priority = tmp13__ >> 11 & 0x7; - pDst->tsinfo_ack_pol = tmp13__ >> 14 & 0x3; - tmp14__ = *pBuf; + pDst->traffic_type = tmp14__ >> 0 & 0x1; + pDst->tsid = tmp14__ >> 1 & 0xf; + pDst->direction = tmp14__ >> 5 & 0x3; + pDst->access_policy = tmp14__ >> 7 & 0x3; + pDst->aggregation = tmp14__ >> 9 & 0x1; + pDst->psb = tmp14__ >> 10 & 0x1; + pDst->user_priority = tmp14__ >> 11 & 0x7; + pDst->tsinfo_ack_pol = tmp14__ >> 14 & 0x3; + tmp15__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->schedule = tmp14__ >> 0 & 0x1; - pDst->unused = tmp14__ >> 1 & 0x7f; - framesntohs(pCtx, &tmp15__, pBuf, 0); + pDst->schedule = tmp15__ >> 0 & 0x1; + pDst->unused = tmp15__ >> 1 & 0x7f; + framesntohs(pCtx, &tmp16__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->size = tmp15__ >> 0 & 0x7fff; - pDst->fixed = tmp15__ >> 15 & 0x1; + pDst->size = tmp16__ >> 0 & 0x7fff; + pDst->fixed = tmp16__ >> 15 & 0x1; framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; @@ -1974,50 +1989,50 @@ uint32_t dot11f_unpack_ie_vht_caps(tpAniSirGlobal pCtx, tDot11fIEVHTCaps *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint32_t tmp16__; - uint16_t tmp17__; + uint32_t tmp17__; uint16_t tmp18__; + uint16_t tmp19__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohl(pCtx, &tmp16__, pBuf, 0); + framesntohl(pCtx, &tmp17__, pBuf, 0); pBuf += 4; ielen -= 4; - pDst->maxMPDULen = tmp16__ >> 0 & 0x3; - pDst->supportedChannelWidthSet = tmp16__ >> 2 & 0x3; - pDst->ldpcCodingCap = tmp16__ >> 4 & 0x1; - pDst->shortGI80MHz = tmp16__ >> 5 & 0x1; - pDst->shortGI160and80plus80MHz = tmp16__ >> 6 & 0x1; - pDst->txSTBC = tmp16__ >> 7 & 0x1; - pDst->rxSTBC = tmp16__ >> 8 & 0x7; - pDst->suBeamFormerCap = tmp16__ >> 11 & 0x1; - pDst->suBeamformeeCap = tmp16__ >> 12 & 0x1; - pDst->csnofBeamformerAntSup = tmp16__ >> 13 & 0x7; - pDst->numSoundingDim = tmp16__ >> 16 & 0x7; - pDst->muBeamformerCap = tmp16__ >> 19 & 0x1; - pDst->muBeamformeeCap = tmp16__ >> 20 & 0x1; - pDst->vhtTXOPPS = tmp16__ >> 21 & 0x1; - pDst->htcVHTCap = tmp16__ >> 22 & 0x1; - pDst->maxAMPDULenExp = tmp16__ >> 23 & 0x7; - pDst->vhtLinkAdaptCap = tmp16__ >> 26 & 0x3; - pDst->rxAntPattern = tmp16__ >> 28 & 0x1; - pDst->txAntPattern = tmp16__ >> 29 & 0x1; - pDst->reserved1 = tmp16__ >> 30 & 0x3; + pDst->maxMPDULen = tmp17__ >> 0 & 0x3; + pDst->supportedChannelWidthSet = tmp17__ >> 2 & 0x3; + pDst->ldpcCodingCap = tmp17__ >> 4 & 0x1; + pDst->shortGI80MHz = tmp17__ >> 5 & 0x1; + pDst->shortGI160and80plus80MHz = tmp17__ >> 6 & 0x1; + pDst->txSTBC = tmp17__ >> 7 & 0x1; + pDst->rxSTBC = tmp17__ >> 8 & 0x7; + pDst->suBeamFormerCap = tmp17__ >> 11 & 0x1; + pDst->suBeamformeeCap = tmp17__ >> 12 & 0x1; + pDst->csnofBeamformerAntSup = tmp17__ >> 13 & 0x7; + pDst->numSoundingDim = tmp17__ >> 16 & 0x7; + pDst->muBeamformerCap = tmp17__ >> 19 & 0x1; + pDst->muBeamformeeCap = tmp17__ >> 20 & 0x1; + pDst->vhtTXOPPS = tmp17__ >> 21 & 0x1; + pDst->htcVHTCap = tmp17__ >> 22 & 0x1; + pDst->maxAMPDULenExp = tmp17__ >> 23 & 0x7; + pDst->vhtLinkAdaptCap = tmp17__ >> 26 & 0x3; + pDst->rxAntPattern = tmp17__ >> 28 & 0x1; + pDst->txAntPattern = tmp17__ >> 29 & 0x1; + pDst->reserved1 = tmp17__ >> 30 & 0x3; framesntohs(pCtx, &pDst->rxMCSMap, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - framesntohs(pCtx, &tmp17__, pBuf, 0); + framesntohs(pCtx, &tmp18__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->rxHighSupDataRate = tmp17__ >> 0 & 0x1fff; - pDst->reserved2 = tmp17__ >> 13 & 0x7; + pDst->rxHighSupDataRate = tmp18__ >> 0 & 0x1fff; + pDst->reserved2 = tmp18__ >> 13 & 0x7; framesntohs(pCtx, &pDst->txMCSMap, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - framesntohs(pCtx, &tmp18__, pBuf, 0); - pDst->txSupDataRate = tmp18__ >> 0 & 0x1fff; - pDst->reserved3 = tmp18__ >> 13 & 0x7; + framesntohs(pCtx, &tmp19__, pBuf, 0); + pDst->txSupDataRate = tmp19__ >> 0 & 0x1fff; + pDst->reserved3 = tmp19__ >> 13 & 0x7; (void)pCtx; return status; } /* End dot11f_unpack_ie_vht_caps. */ @@ -2058,7 +2073,7 @@ uint32_t dot11f_unpack_ie_wmm_schedule(tpAniSirGlobal pCtx, tDot11fIEWMMSchedule *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp19__; + uint16_t tmp20__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -2070,13 +2085,13 @@ uint32_t dot11f_unpack_ie_wmm_schedule(tpAniSirGlobal pCtx, pDst->present = 0; return status | DOT11F_BAD_FIXED_VALUE; } - framesntohs(pCtx, &tmp19__, pBuf, 0); + framesntohs(pCtx, &tmp20__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->aggregation = tmp19__ >> 0 & 0x1; - pDst->tsid = tmp19__ >> 1 & 0xf; - pDst->direction = tmp19__ >> 5 & 0x3; - pDst->reserved = tmp19__ >> 7 & 0x1ff; + 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 -= (uint8_t)4; @@ -2248,9 +2263,9 @@ uint32_t dot11f_unpack_ie_wmmtspec(tpAniSirGlobal pCtx, tDot11fIEWMMTSPEC *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp20__; - uint8_t tmp21__; - uint16_t tmp22__; + uint16_t tmp21__; + uint8_t tmp22__; + uint16_t tmp23__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -2262,27 +2277,27 @@ uint32_t dot11f_unpack_ie_wmmtspec(tpAniSirGlobal pCtx, pDst->present = 0; return status | DOT11F_BAD_FIXED_VALUE; } - framesntohs(pCtx, &tmp20__, pBuf, 0); + framesntohs(pCtx, &tmp21__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->traffic_type = tmp20__ >> 0 & 0x1; - pDst->tsid = tmp20__ >> 1 & 0xf; - pDst->direction = tmp20__ >> 5 & 0x3; - pDst->access_policy = tmp20__ >> 7 & 0x3; - pDst->aggregation = tmp20__ >> 9 & 0x1; - pDst->psb = tmp20__ >> 10 & 0x1; - pDst->user_priority = tmp20__ >> 11 & 0x7; - pDst->tsinfo_ack_pol = tmp20__ >> 14 & 0x3; - tmp21__ = *pBuf; + 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 = tmp21__ >> 0 & 0x7f; - pDst->burst_size_defn = tmp21__ >> 7 & 0x1; - framesntohs(pCtx, &tmp22__, pBuf, 0); + pDst->tsinfo_rsvd = tmp22__ >> 0 & 0x7f; + pDst->burst_size_defn = tmp22__ >> 7 & 0x1; + framesntohs(pCtx, &tmp23__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->size = tmp22__ >> 0 & 0x7fff; - pDst->fixed = tmp22__ >> 15 & 0x1; + pDst->size = tmp23__ >> 0 & 0x7fff; + pDst->fixed = tmp23__ >> 15 & 0x1; framesntohs(pCtx, &pDst->max_msdu_size, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; @@ -2524,7 +2539,6 @@ uint32_t dot11f_unpack_ie_edca_param_set(tpAniSirGlobal pCtx, tDot11fIEEDCAParamSet *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp23__; uint8_t tmp24__; uint8_t tmp25__; uint8_t tmp26__; @@ -2532,6 +2546,7 @@ uint32_t dot11f_unpack_ie_edca_param_set(tpAniSirGlobal pCtx, uint8_t tmp28__; uint8_t tmp29__; uint8_t tmp30__; + uint8_t tmp31__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -2542,63 +2557,63 @@ uint32_t dot11f_unpack_ie_edca_param_set(tpAniSirGlobal pCtx, pDst->reserved = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp23__ = *pBuf; + tmp24__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbe_aifsn = tmp23__ >> 0 & 0xf; - pDst->acbe_acm = tmp23__ >> 4 & 0x1; - pDst->acbe_aci = tmp23__ >> 5 & 0x3; - pDst->unused1 = tmp23__ >> 7 & 0x1; - tmp24__ = *pBuf; + 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 = tmp24__ >> 0 & 0xf; - pDst->acbe_acwmax = tmp24__ >> 4 & 0xf; + pDst->acbe_acwmin = tmp25__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp25__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp25__ = *pBuf; + tmp26__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbk_aifsn = tmp25__ >> 0 & 0xf; - pDst->acbk_acm = tmp25__ >> 4 & 0x1; - pDst->acbk_aci = tmp25__ >> 5 & 0x3; - pDst->unused2 = tmp25__ >> 7 & 0x1; - tmp26__ = *pBuf; + 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 = tmp26__ >> 0 & 0xf; - pDst->acbk_acwmax = tmp26__ >> 4 & 0xf; + pDst->acbk_acwmin = tmp27__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp27__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp27__ = *pBuf; + tmp28__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvi_aifsn = tmp27__ >> 0 & 0xf; - pDst->acvi_acm = tmp27__ >> 4 & 0x1; - pDst->acvi_aci = tmp27__ >> 5 & 0x3; - pDst->unused3 = tmp27__ >> 7 & 0x1; - tmp28__ = *pBuf; + 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 = tmp28__ >> 0 & 0xf; - pDst->acvi_acwmax = tmp28__ >> 4 & 0xf; + pDst->acvi_acwmin = tmp29__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp29__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp29__ = *pBuf; + tmp30__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvo_aifsn = tmp29__ >> 0 & 0xf; - pDst->acvo_acm = tmp29__ >> 4 & 0x1; - pDst->acvo_aci = tmp29__ >> 5 & 0x3; - pDst->unused4 = tmp29__ >> 7 & 0x1; - tmp30__ = *pBuf; + 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 = tmp30__ >> 0 & 0xf; - pDst->acvo_acwmax = tmp30__ >> 4 & 0xf; + pDst->acvo_acwmin = tmp31__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp31__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); (void)pCtx; return status; @@ -2613,16 +2628,16 @@ uint32_t dot11f_unpack_ie_erp_info(tpAniSirGlobal pCtx, tDot11fIEERPInfo *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp31__; + uint8_t tmp32__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp31__ = *pBuf; - pDst->non_erp_present = tmp31__ >> 0 & 0x1; - pDst->use_prot = tmp31__ >> 1 & 0x1; - pDst->barker_preamble = tmp31__ >> 2 & 0x1; - pDst->unused = tmp31__ >> 3 & 0x1f; + 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 dot11f_unpack_ie_erp_info. */ @@ -2660,7 +2675,7 @@ uint32_t dot11f_unpack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, tDot11fIEESERadMgmtCap *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp32__; + uint8_t tmp33__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -2668,9 +2683,9 @@ uint32_t dot11f_unpack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, pDst->mgmt_state = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp32__ = *pBuf; - pDst->mbssid_mask = tmp32__ >> 0 & 0x7; - pDst->reserved = tmp32__ >> 3 & 0x1f; + tmp33__ = *pBuf; + pDst->mbssid_mask = tmp33__ >> 0 & 0x7; + pDst->reserved = tmp33__ >> 3 & 0x1f; (void)pCtx; return status; } /* End dot11f_unpack_ie_ese_rad_mgmt_cap. */ @@ -2937,16 +2952,16 @@ uint32_t dot11f_unpack_ie_ft_info(tpAniSirGlobal pCtx, tDot11fIEFTInfo *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp33__; + uint16_t tmp34__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohs(pCtx, &tmp33__, pBuf, 0); + framesntohs(pCtx, &tmp34__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->reserved = tmp33__ >> 0 & 0xff; - pDst->IECount = tmp33__ >> 8 & 0xff; + pDst->reserved = tmp34__ >> 0 & 0xff; + pDst->IECount = tmp34__ >> 8 & 0xff; DOT11F_MEMCPY(pCtx, pDst->MIC, pBuf, 16); pBuf += 16; ielen -= (uint8_t)16; @@ -2976,79 +2991,79 @@ uint32_t dot11f_unpack_ie_ht_caps(tpAniSirGlobal pCtx, tDot11fIEHTCaps *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp34__; - uint8_t tmp35__; - uint16_t tmp36__; - uint32_t tmp37__; - uint8_t tmp38__; + uint16_t tmp35__; + uint8_t tmp36__; + uint16_t tmp37__; + uint32_t tmp38__; + uint8_t tmp39__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - framesntohs(pCtx, &tmp34__, pBuf, 0); + framesntohs(pCtx, &tmp35__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->advCodingCap = tmp34__ >> 0 & 0x1; - pDst->supportedChannelWidthSet = tmp34__ >> 1 & 0x1; - pDst->mimoPowerSave = tmp34__ >> 2 & 0x3; - pDst->greenField = tmp34__ >> 4 & 0x1; - pDst->shortGI20MHz = tmp34__ >> 5 & 0x1; - pDst->shortGI40MHz = tmp34__ >> 6 & 0x1; - pDst->txSTBC = tmp34__ >> 7 & 0x1; - pDst->rxSTBC = tmp34__ >> 8 & 0x3; - pDst->delayedBA = tmp34__ >> 10 & 0x1; - pDst->maximalAMSDUsize = tmp34__ >> 11 & 0x1; - pDst->dsssCckMode40MHz = tmp34__ >> 12 & 0x1; - pDst->psmp = tmp34__ >> 13 & 0x1; - pDst->stbcControlFrame = tmp34__ >> 14 & 0x1; - pDst->lsigTXOPProtection = tmp34__ >> 15 & 0x1; - tmp35__ = *pBuf; + pDst->advCodingCap = tmp35__ >> 0 & 0x1; + pDst->supportedChannelWidthSet = tmp35__ >> 1 & 0x1; + pDst->mimoPowerSave = tmp35__ >> 2 & 0x3; + pDst->greenField = tmp35__ >> 4 & 0x1; + pDst->shortGI20MHz = tmp35__ >> 5 & 0x1; + pDst->shortGI40MHz = tmp35__ >> 6 & 0x1; + pDst->txSTBC = tmp35__ >> 7 & 0x1; + pDst->rxSTBC = tmp35__ >> 8 & 0x3; + pDst->delayedBA = tmp35__ >> 10 & 0x1; + pDst->maximalAMSDUsize = tmp35__ >> 11 & 0x1; + pDst->dsssCckMode40MHz = tmp35__ >> 12 & 0x1; + pDst->psmp = tmp35__ >> 13 & 0x1; + pDst->stbcControlFrame = tmp35__ >> 14 & 0x1; + pDst->lsigTXOPProtection = tmp35__ >> 15 & 0x1; + tmp36__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->maxRxAMPDUFactor = tmp35__ >> 0 & 0x3; - pDst->mpduDensity = tmp35__ >> 2 & 0x7; - pDst->reserved1 = tmp35__ >> 5 & 0x7; + pDst->maxRxAMPDUFactor = tmp36__ >> 0 & 0x3; + pDst->mpduDensity = tmp36__ >> 2 & 0x7; + pDst->reserved1 = tmp36__ >> 5 & 0x7; DOT11F_MEMCPY(pCtx, pDst->supportedMCSSet, pBuf, 16); pBuf += 16; ielen -= (uint8_t)16; - framesntohs(pCtx, &tmp36__, pBuf, 0); + framesntohs(pCtx, &tmp37__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->pco = tmp36__ >> 0 & 0x1; - pDst->transitionTime = tmp36__ >> 1 & 0x3; - pDst->reserved2 = tmp36__ >> 3 & 0x1f; - pDst->mcsFeedback = tmp36__ >> 8 & 0x3; - pDst->reserved3 = tmp36__ >> 10 & 0x3f; - framesntohl(pCtx, &tmp37__, pBuf, 0); + pDst->pco = tmp37__ >> 0 & 0x1; + pDst->transitionTime = tmp37__ >> 1 & 0x3; + pDst->reserved2 = tmp37__ >> 3 & 0x1f; + pDst->mcsFeedback = tmp37__ >> 8 & 0x3; + pDst->reserved3 = tmp37__ >> 10 & 0x3f; + framesntohl(pCtx, &tmp38__, pBuf, 0); pBuf += 4; ielen -= 4; - pDst->txBF = tmp37__ >> 0 & 0x1; - pDst->rxStaggeredSounding = tmp37__ >> 1 & 0x1; - pDst->txStaggeredSounding = tmp37__ >> 2 & 0x1; - pDst->rxZLF = tmp37__ >> 3 & 0x1; - pDst->txZLF = tmp37__ >> 4 & 0x1; - pDst->implicitTxBF = tmp37__ >> 5 & 0x1; - pDst->calibration = tmp37__ >> 6 & 0x3; - pDst->explicitCSITxBF = tmp37__ >> 8 & 0x1; - pDst->explicitUncompressedSteeringMatrix = tmp37__ >> 9 & 0x1; - pDst->explicitBFCSIFeedback = tmp37__ >> 10 & 0x7; - pDst->explicitUncompressedSteeringMatrixFeedback = tmp37__ >> 13 & 0x7; - pDst->explicitCompressedSteeringMatrixFeedback = tmp37__ >> 16 & 0x7; - pDst->csiNumBFAntennae = tmp37__ >> 19 & 0x3; - pDst->uncompressedSteeringMatrixBFAntennae = tmp37__ >> 21 & 0x3; - pDst->compressedSteeringMatrixBFAntennae = tmp37__ >> 23 & 0x3; - pDst->reserved4 = tmp37__ >> 25 & 0x7f; - tmp38__ = *pBuf; + pDst->txBF = tmp38__ >> 0 & 0x1; + pDst->rxStaggeredSounding = tmp38__ >> 1 & 0x1; + pDst->txStaggeredSounding = tmp38__ >> 2 & 0x1; + pDst->rxZLF = tmp38__ >> 3 & 0x1; + pDst->txZLF = tmp38__ >> 4 & 0x1; + pDst->implicitTxBF = tmp38__ >> 5 & 0x1; + pDst->calibration = tmp38__ >> 6 & 0x3; + pDst->explicitCSITxBF = tmp38__ >> 8 & 0x1; + pDst->explicitUncompressedSteeringMatrix = tmp38__ >> 9 & 0x1; + pDst->explicitBFCSIFeedback = tmp38__ >> 10 & 0x7; + pDst->explicitUncompressedSteeringMatrixFeedback = tmp38__ >> 13 & 0x7; + pDst->explicitCompressedSteeringMatrixFeedback = tmp38__ >> 16 & 0x7; + pDst->csiNumBFAntennae = tmp38__ >> 19 & 0x3; + pDst->uncompressedSteeringMatrixBFAntennae = tmp38__ >> 21 & 0x3; + pDst->compressedSteeringMatrixBFAntennae = tmp38__ >> 23 & 0x3; + pDst->reserved4 = tmp38__ >> 25 & 0x7f; + tmp39__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->antennaSelection = tmp38__ >> 0 & 0x1; - pDst->explicitCSIFeedbackTx = tmp38__ >> 1 & 0x1; - pDst->antennaIndicesFeedbackTx = tmp38__ >> 2 & 0x1; - pDst->explicitCSIFeedback = tmp38__ >> 3 & 0x1; - pDst->antennaIndicesFeedback = tmp38__ >> 4 & 0x1; - pDst->rxAS = tmp38__ >> 5 & 0x1; - pDst->txSoundingPPDUs = tmp38__ >> 6 & 0x1; - pDst->reserved5 = tmp38__ >> 7 & 0x1; + pDst->antennaSelection = tmp39__ >> 0 & 0x1; + pDst->explicitCSIFeedbackTx = tmp39__ >> 1 & 0x1; + pDst->antennaIndicesFeedbackTx = tmp39__ >> 2 & 0x1; + pDst->explicitCSIFeedback = tmp39__ >> 3 & 0x1; + pDst->antennaIndicesFeedback = tmp39__ >> 4 & 0x1; + pDst->rxAS = tmp39__ >> 5 & 0x1; + pDst->txSoundingPPDUs = tmp39__ >> 6 & 0x1; + pDst->reserved5 = tmp39__ >> 7 & 0x1; pDst->num_rsvd = (uint8_t)(ielen); if (ielen > 32) { pDst->present = 0; @@ -3069,9 +3084,9 @@ uint32_t dot11f_unpack_ie_ht_info(tpAniSirGlobal pCtx, tDot11fIEHTInfo *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp39__; - uint16_t tmp40__; + uint8_t tmp40__; uint16_t tmp41__; + uint16_t tmp42__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -3079,32 +3094,32 @@ uint32_t dot11f_unpack_ie_ht_info(tpAniSirGlobal pCtx, pDst->primaryChannel = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp39__ = *pBuf; + tmp40__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->secondaryChannelOffset = tmp39__ >> 0 & 0x3; - pDst->recommendedTxWidthSet = tmp39__ >> 2 & 0x1; - pDst->rifsMode = tmp39__ >> 3 & 0x1; - pDst->controlledAccessOnly = tmp39__ >> 4 & 0x1; - pDst->serviceIntervalGranularity = tmp39__ >> 5 & 0x7; - framesntohs(pCtx, &tmp40__, pBuf, 0); + pDst->secondaryChannelOffset = tmp40__ >> 0 & 0x3; + pDst->recommendedTxWidthSet = tmp40__ >> 2 & 0x1; + pDst->rifsMode = tmp40__ >> 3 & 0x1; + pDst->controlledAccessOnly = tmp40__ >> 4 & 0x1; + pDst->serviceIntervalGranularity = tmp40__ >> 5 & 0x7; + framesntohs(pCtx, &tmp41__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->opMode = tmp40__ >> 0 & 0x3; - pDst->nonGFDevicesPresent = tmp40__ >> 2 & 0x1; - pDst->transmitBurstLimit = tmp40__ >> 3 & 0x1; - pDst->obssNonHTStaPresent = tmp40__ >> 4 & 0x1; - pDst->reserved = tmp40__ >> 5 & 0x7ff; - framesntohs(pCtx, &tmp41__, pBuf, 0); + pDst->opMode = tmp41__ >> 0 & 0x3; + pDst->nonGFDevicesPresent = tmp41__ >> 2 & 0x1; + pDst->transmitBurstLimit = tmp41__ >> 3 & 0x1; + pDst->obssNonHTStaPresent = tmp41__ >> 4 & 0x1; + pDst->reserved = tmp41__ >> 5 & 0x7ff; + framesntohs(pCtx, &tmp42__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->basicSTBCMCS = tmp41__ >> 0 & 0x7f; - pDst->dualCTSProtection = tmp41__ >> 7 & 0x1; - pDst->secondaryBeacon = tmp41__ >> 8 & 0x1; - pDst->lsigTXOPProtectionFullSupport = tmp41__ >> 9 & 0x1; - pDst->pcoActive = tmp41__ >> 10 & 0x1; - pDst->pcoPhase = tmp41__ >> 11 & 0x1; - pDst->reserved2 = tmp41__ >> 12 & 0xf; + pDst->basicSTBCMCS = tmp42__ >> 0 & 0x7f; + pDst->dualCTSProtection = tmp42__ >> 7 & 0x1; + pDst->secondaryBeacon = tmp42__ >> 8 & 0x1; + pDst->lsigTXOPProtectionFullSupport = tmp42__ >> 9 & 0x1; + pDst->pcoActive = tmp42__ >> 10 & 0x1; + pDst->pcoPhase = tmp42__ >> 11 & 0x1; + pDst->reserved2 = tmp42__ >> 12 & 0xf; DOT11F_MEMCPY(pCtx, pDst->basicMCSSet, pBuf, 16); pBuf += 16; ielen -= (uint8_t)16; @@ -3183,9 +3198,9 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx, tDot11fIEMeasurementReport *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp42__; uint8_t tmp43__; uint8_t tmp44__; + uint8_t tmp45__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -3193,13 +3208,13 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx, pDst->token = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp42__ = *pBuf; + tmp43__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->late = tmp42__ >> 0 & 0x1; - pDst->incapable = tmp42__ >> 1 & 0x1; - pDst->refused = tmp42__ >> 2 & 0x1; - pDst->unused = tmp42__ >> 3 & 0x1f; + pDst->late = tmp43__ >> 0 & 0x1; + pDst->incapable = tmp43__ >> 1 & 0x1; + pDst->refused = tmp43__ >> 2 & 0x1; + pDst->unused = tmp43__ >> 3 & 0x1f; pDst->type = *pBuf; pBuf += 1; ielen -= (uint8_t)1; @@ -3217,15 +3232,15 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx, framesntohs(pCtx, &pDst->report.Basic.meas_duration, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp43__ = *pBuf; + tmp44__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->report.Basic.bss = tmp43__ >> 0 & 0x1; - pDst->report.Basic.ofdm_preamble = tmp43__ >> 1 & 0x1; - pDst->report.Basic.unid_signal = tmp43__ >> 2 & 0x1; - pDst->report.Basic.rader = tmp43__ >> 3 & 0x1; - pDst->report.Basic.unmeasured = tmp43__ >> 4 & 0x1; - pDst->report.Basic.unused = tmp43__ >> 5 & 0x7; + pDst->report.Basic.bss = tmp44__ >> 0 & 0x1; + pDst->report.Basic.ofdm_preamble = tmp44__ >> 1 & 0x1; + pDst->report.Basic.unid_signal = tmp44__ >> 2 & 0x1; + pDst->report.Basic.rader = tmp44__ >> 3 & 0x1; + pDst->report.Basic.unmeasured = tmp44__ >> 4 & 0x1; + pDst->report.Basic.unused = tmp44__ >> 5 & 0x7; break; case 1: pDst->report.CCA.channel = *pBuf; @@ -3289,11 +3304,11 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx, framesntohs(pCtx, &pDst->report.Beacon.meas_duration, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp44__ = *pBuf; + tmp45__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->report.Beacon.condensed_PHY = tmp44__ >> 0 & 0x7f; - pDst->report.Beacon.reported_frame_type = tmp44__ >> 7 & 0x1; + pDst->report.Beacon.condensed_PHY = tmp45__ >> 0 & 0x7f; + pDst->report.Beacon.reported_frame_type = tmp45__ >> 7 & 0x1; pDst->report.Beacon.RCPI = *pBuf; pBuf += 1; ielen -= (uint8_t)1; @@ -3362,7 +3377,7 @@ uint32_t dot11f_unpack_ie_measurement_request(tpAniSirGlobal pCtx, tDot11fIEMeasurementRequest *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp45__; + uint8_t tmp46__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -3370,15 +3385,15 @@ uint32_t dot11f_unpack_ie_measurement_request(tpAniSirGlobal pCtx, pDst->measurement_token = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp45__ = *pBuf; + tmp46__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->parallel = tmp45__ >> 0 & 0x1; - pDst->enable = tmp45__ >> 1 & 0x1; - pDst->request = tmp45__ >> 2 & 0x1; - pDst->report = tmp45__ >> 3 & 0x1; - pDst->durationMandatory = tmp45__ >> 4 & 0x1; - pDst->unused = tmp45__ >> 5 & 0x7; + pDst->parallel = tmp46__ >> 0 & 0x1; + pDst->enable = tmp46__ >> 1 & 0x1; + pDst->request = tmp46__ >> 2 & 0x1; + pDst->report = tmp46__ >> 3 & 0x1; + pDst->durationMandatory = tmp46__ >> 4 & 0x1; + pDst->unused = tmp46__ >> 5 & 0x7; pDst->measurement_type = *pBuf; pBuf += 1; ielen -= (uint8_t)1; @@ -3457,7 +3472,7 @@ uint32_t dot11f_unpack_ie_mobility_domain(tpAniSirGlobal pCtx, tDot11fIEMobilityDomain *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp46__; + uint8_t tmp47__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -3465,10 +3480,10 @@ uint32_t dot11f_unpack_ie_mobility_domain(tpAniSirGlobal pCtx, framesntohs(pCtx, &pDst->MDID, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp46__ = *pBuf; - pDst->overDSCap = tmp46__ >> 0 & 0x1; - pDst->resourceReqCap = tmp46__ >> 1 & 0x1; - pDst->reserved = tmp46__ >> 2 & 0x3f; + tmp47__ = *pBuf; + pDst->overDSCap = tmp47__ >> 0 & 0x1; + pDst->resourceReqCap = tmp47__ >> 1 & 0x1; + pDst->reserved = tmp47__ >> 2 & 0x3f; (void)pCtx; return status; } /* End dot11f_unpack_ie_mobility_domain. */ @@ -3509,8 +3524,8 @@ uint32_t dot11f_unpack_ie_neighbor_report(tpAniSirGlobal pCtx, tDot11fIENeighborReport *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp47__; uint8_t tmp48__; + uint8_t tmp49__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -3518,23 +3533,23 @@ uint32_t dot11f_unpack_ie_neighbor_report(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pDst->bssid, pBuf, 6); pBuf += 6; ielen -= (uint8_t)6; - tmp47__ = *pBuf; + tmp48__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->APReachability = tmp47__ >> 0 & 0x3; - pDst->Security = tmp47__ >> 2 & 0x1; - pDst->KeyScope = tmp47__ >> 3 & 0x1; - pDst->SpecMgmtCap = tmp47__ >> 4 & 0x1; - pDst->QosCap = tmp47__ >> 5 & 0x1; - pDst->apsd = tmp47__ >> 6 & 0x1; - pDst->rrm = tmp47__ >> 7 & 0x1; - tmp48__ = *pBuf; + pDst->APReachability = tmp48__ >> 0 & 0x3; + pDst->Security = tmp48__ >> 2 & 0x1; + pDst->KeyScope = tmp48__ >> 3 & 0x1; + pDst->SpecMgmtCap = tmp48__ >> 4 & 0x1; + pDst->QosCap = tmp48__ >> 5 & 0x1; + pDst->apsd = tmp48__ >> 6 & 0x1; + pDst->rrm = tmp48__ >> 7 & 0x1; + tmp49__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->DelayedBA = tmp48__ >> 0 & 0x1; - pDst->ImmBA = tmp48__ >> 1 & 0x1; - pDst->MobilityDomain = tmp48__ >> 2 & 0x1; - pDst->reserved = tmp48__ >> 3 & 0x1f; + pDst->DelayedBA = tmp49__ >> 0 & 0x1; + pDst->ImmBA = tmp49__ >> 1 & 0x1; + pDst->MobilityDomain = tmp49__ >> 2 & 0x1; + pDst->reserved = tmp49__ >> 3 & 0x1f; framesntohs(pCtx, &pDst->reserved1, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; @@ -3603,16 +3618,16 @@ uint32_t dot11f_unpack_ie_operating_mode(tpAniSirGlobal pCtx, tDot11fIEOperatingMode *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp49__; + uint8_t tmp50__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp49__ = *pBuf; - pDst->chanWidth = tmp49__ >> 0 & 0x3; - pDst->reserved = tmp49__ >> 2 & 0x3; - pDst->rxNSS = tmp49__ >> 4 & 0x7; - pDst->rxNSSType = tmp49__ >> 7 & 0x1; + tmp50__ = *pBuf; + pDst->chanWidth = tmp50__ >> 0 & 0x3; + pDst->reserved = tmp50__ >> 2 & 0x3; + pDst->rxNSS = tmp50__ >> 4 & 0x7; + pDst->rxNSSType = tmp50__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_operating_mode. */ @@ -3928,17 +3943,17 @@ uint32_t dot11f_unpack_ie_pu_buffer_status(tpAniSirGlobal pCtx, tDot11fIEPUBufferStatus *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp50__; + uint8_t tmp51__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp50__ = *pBuf; - pDst->ac_bk_traffic_aval = tmp50__ >> 0 & 0x1; - pDst->ac_be_traffic_aval = tmp50__ >> 1 & 0x1; - pDst->ac_vi_traffic_aval = tmp50__ >> 2 & 0x1; - pDst->ac_vo_traffic_aval = tmp50__ >> 3 & 0x1; - pDst->reserved = tmp50__ >> 4 & 0xf; + tmp51__ = *pBuf; + pDst->ac_bk_traffic_aval = tmp51__ >> 0 & 0x1; + pDst->ac_be_traffic_aval = tmp51__ >> 1 & 0x1; + pDst->ac_vi_traffic_aval = tmp51__ >> 2 & 0x1; + pDst->ac_vo_traffic_aval = tmp51__ >> 3 & 0x1; + pDst->reserved = tmp51__ >> 4 & 0xf; (void)pCtx; return status; } /* End dot11f_unpack_ie_pu_buffer_status. */ @@ -4036,17 +4051,17 @@ uint32_t dot11f_unpack_ie_qos_caps_ap(tpAniSirGlobal pCtx, tDot11fIEQOSCapsAp *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp51__; + uint8_t tmp52__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp51__ = *pBuf; - pDst->count = tmp51__ >> 0 & 0xf; - pDst->qack = tmp51__ >> 4 & 0x1; - pDst->qreq = tmp51__ >> 5 & 0x1; - pDst->txopreq = tmp51__ >> 6 & 0x1; - pDst->reserved = tmp51__ >> 7 & 0x1; + tmp52__ = *pBuf; + pDst->count = tmp52__ >> 0 & 0xf; + pDst->qack = tmp52__ >> 4 & 0x1; + pDst->qreq = tmp52__ >> 5 & 0x1; + pDst->txopreq = tmp52__ >> 6 & 0x1; + pDst->reserved = tmp52__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_qos_caps_ap. */ @@ -4060,19 +4075,19 @@ uint32_t dot11f_unpack_ie_qos_caps_station(tpAniSirGlobal pCtx, tDot11fIEQOSCapsStation *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp52__; + uint8_t tmp53__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp52__ = *pBuf; - pDst->acvo_uapsd = tmp52__ >> 0 & 0x1; - pDst->acvi_uapsd = tmp52__ >> 1 & 0x1; - pDst->acbk_uapsd = tmp52__ >> 2 & 0x1; - pDst->acbe_uapsd = tmp52__ >> 3 & 0x1; - pDst->qack = tmp52__ >> 4 & 0x1; - pDst->max_sp_length = tmp52__ >> 5 & 0x3; - pDst->more_data_ack = tmp52__ >> 7 & 0x1; + tmp53__ = *pBuf; + pDst->acvo_uapsd = tmp53__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp53__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp53__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp53__ >> 3 & 0x1; + pDst->qack = tmp53__ >> 4 & 0x1; + pDst->max_sp_length = tmp53__ >> 5 & 0x3; + pDst->more_data_ack = tmp53__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_qos_caps_station. */ @@ -4622,7 +4637,7 @@ uint32_t dot11f_unpack_ie_wapi(tpAniSirGlobal pCtx, tDot11fIEWAPI *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint16_t tmp53__; + uint16_t tmp54__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -4659,11 +4674,11 @@ uint32_t dot11f_unpack_ie_wapi(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pDst->multicast_cipher_suite, pBuf, 4); pBuf += 4; ielen -= (uint8_t)4; - framesntohs(pCtx, &tmp53__, pBuf, 0); + framesntohs(pCtx, &tmp54__, pBuf, 0); pBuf += 2; ielen -= 2; - pDst->preauth = tmp53__ >> 0 & 0x1; - pDst->reserved = tmp53__ >> 1 & 0x7fff; + pDst->preauth = tmp54__ >> 0 & 0x1; + pDst->reserved = tmp54__ >> 1 & 0x7fff; if (!ielen) { pDst->bkid_count = 0U; return 0U; @@ -4760,7 +4775,7 @@ uint32_t dot11f_unpack_ie_wmm_caps(tpAniSirGlobal pCtx, tDot11fIEWMMCaps *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp54__; + uint8_t tmp55__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -4772,12 +4787,12 @@ uint32_t dot11f_unpack_ie_wmm_caps(tpAniSirGlobal pCtx, pDst->present = 0; return status | DOT11F_BAD_FIXED_VALUE; } - tmp54__ = *pBuf; - pDst->reserved = tmp54__ >> 0 & 0xf; - pDst->qack = tmp54__ >> 4 & 0x1; - pDst->queue_request = tmp54__ >> 5 & 0x1; - pDst->txop_request = tmp54__ >> 6 & 0x1; - pDst->more_ack = tmp54__ >> 7 & 0x1; + tmp55__ = *pBuf; + pDst->reserved = tmp55__ >> 0 & 0xf; + pDst->qack = tmp55__ >> 4 & 0x1; + pDst->queue_request = tmp55__ >> 5 & 0x1; + pDst->txop_request = tmp55__ >> 6 & 0x1; + pDst->more_ack = tmp55__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_wmm_caps. */ @@ -4791,7 +4806,7 @@ uint32_t dot11f_unpack_ie_wmm_info_ap(tpAniSirGlobal pCtx, tDot11fIEWMMInfoAp *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp55__; + uint8_t tmp56__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -4799,10 +4814,10 @@ uint32_t dot11f_unpack_ie_wmm_info_ap(tpAniSirGlobal pCtx, pDst->version = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp55__ = *pBuf; - pDst->param_set_count = tmp55__ >> 0 & 0xf; - pDst->reserved = tmp55__ >> 4 & 0x7; - pDst->uapsd = tmp55__ >> 7 & 0x1; + tmp56__ = *pBuf; + pDst->param_set_count = tmp56__ >> 0 & 0xf; + pDst->reserved = tmp56__ >> 4 & 0x7; + pDst->uapsd = tmp56__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_wmm_info_ap. */ @@ -4816,7 +4831,7 @@ uint32_t dot11f_unpack_ie_wmm_info_station(tpAniSirGlobal pCtx, tDot11fIEWMMInfoStation *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp56__; + uint8_t tmp57__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -4824,14 +4839,14 @@ uint32_t dot11f_unpack_ie_wmm_info_station(tpAniSirGlobal pCtx, pDst->version = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp56__ = *pBuf; - pDst->acvo_uapsd = tmp56__ >> 0 & 0x1; - pDst->acvi_uapsd = tmp56__ >> 1 & 0x1; - pDst->acbk_uapsd = tmp56__ >> 2 & 0x1; - pDst->acbe_uapsd = tmp56__ >> 3 & 0x1; - pDst->reserved1 = tmp56__ >> 4 & 0x1; - pDst->max_sp_length = tmp56__ >> 5 & 0x3; - pDst->reserved2 = tmp56__ >> 7 & 0x1; + tmp57__ = *pBuf; + pDst->acvo_uapsd = tmp57__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp57__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp57__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp57__ >> 3 & 0x1; + pDst->reserved1 = tmp57__ >> 4 & 0x1; + pDst->max_sp_length = tmp57__ >> 5 & 0x3; + pDst->reserved2 = tmp57__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11f_unpack_ie_wmm_info_station. */ @@ -4845,7 +4860,6 @@ uint32_t dot11f_unpack_ie_wmm_params(tpAniSirGlobal pCtx, tDot11fIEWMMParams *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp57__; uint8_t tmp58__; uint8_t tmp59__; uint8_t tmp60__; @@ -4853,6 +4867,7 @@ uint32_t dot11f_unpack_ie_wmm_params(tpAniSirGlobal pCtx, uint8_t tmp62__; uint8_t tmp63__; uint8_t tmp64__; + uint8_t tmp65__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; @@ -4870,63 +4885,63 @@ uint32_t dot11f_unpack_ie_wmm_params(tpAniSirGlobal pCtx, pDst->reserved2 = *pBuf; pBuf += 1; ielen -= (uint8_t)1; - tmp57__ = *pBuf; + tmp58__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbe_aifsn = tmp57__ >> 0 & 0xf; - pDst->acbe_acm = tmp57__ >> 4 & 0x1; - pDst->acbe_aci = tmp57__ >> 5 & 0x3; - pDst->unused1 = tmp57__ >> 7 & 0x1; - tmp58__ = *pBuf; + pDst->acbe_aifsn = tmp58__ >> 0 & 0xf; + pDst->acbe_acm = tmp58__ >> 4 & 0x1; + pDst->acbe_aci = tmp58__ >> 5 & 0x3; + pDst->unused1 = tmp58__ >> 7 & 0x1; + tmp59__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbe_acwmin = tmp58__ >> 0 & 0xf; - pDst->acbe_acwmax = tmp58__ >> 4 & 0xf; + pDst->acbe_acwmin = tmp59__ >> 0 & 0xf; + pDst->acbe_acwmax = tmp59__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acbe_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp59__ = *pBuf; + tmp60__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbk_aifsn = tmp59__ >> 0 & 0xf; - pDst->acbk_acm = tmp59__ >> 4 & 0x1; - pDst->acbk_aci = tmp59__ >> 5 & 0x3; - pDst->unused2 = tmp59__ >> 7 & 0x1; - tmp60__ = *pBuf; + pDst->acbk_aifsn = tmp60__ >> 0 & 0xf; + pDst->acbk_acm = tmp60__ >> 4 & 0x1; + pDst->acbk_aci = tmp60__ >> 5 & 0x3; + pDst->unused2 = tmp60__ >> 7 & 0x1; + tmp61__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acbk_acwmin = tmp60__ >> 0 & 0xf; - pDst->acbk_acwmax = tmp60__ >> 4 & 0xf; + pDst->acbk_acwmin = tmp61__ >> 0 & 0xf; + pDst->acbk_acwmax = tmp61__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acbk_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp61__ = *pBuf; + tmp62__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvi_aifsn = tmp61__ >> 0 & 0xf; - pDst->acvi_acm = tmp61__ >> 4 & 0x1; - pDst->acvi_aci = tmp61__ >> 5 & 0x3; - pDst->unused3 = tmp61__ >> 7 & 0x1; - tmp62__ = *pBuf; + pDst->acvi_aifsn = tmp62__ >> 0 & 0xf; + pDst->acvi_acm = tmp62__ >> 4 & 0x1; + pDst->acvi_aci = tmp62__ >> 5 & 0x3; + pDst->unused3 = tmp62__ >> 7 & 0x1; + tmp63__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvi_acwmin = tmp62__ >> 0 & 0xf; - pDst->acvi_acwmax = tmp62__ >> 4 & 0xf; + pDst->acvi_acwmin = tmp63__ >> 0 & 0xf; + pDst->acvi_acwmax = tmp63__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acvi_txoplimit, pBuf, 0); pBuf += 2; ielen -= (uint8_t)2; - tmp63__ = *pBuf; + tmp64__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvo_aifsn = tmp63__ >> 0 & 0xf; - pDst->acvo_acm = tmp63__ >> 4 & 0x1; - pDst->acvo_aci = tmp63__ >> 5 & 0x3; - pDst->unused4 = tmp63__ >> 7 & 0x1; - tmp64__ = *pBuf; + pDst->acvo_aifsn = tmp64__ >> 0 & 0xf; + pDst->acvo_acm = tmp64__ >> 4 & 0x1; + pDst->acvo_aci = tmp64__ >> 5 & 0x3; + pDst->unused4 = tmp64__ >> 7 & 0x1; + tmp65__ = *pBuf; pBuf += 1; ielen -= 1; - pDst->acvo_acwmin = tmp64__ >> 0 & 0xf; - pDst->acvo_acwmax = tmp64__ >> 4 & 0xf; + pDst->acvo_acwmin = tmp65__ >> 0 & 0xf; + pDst->acvo_acwmax = tmp65__ >> 4 & 0xf; framesntohs(pCtx, &pDst->acvo_txoplimit, pBuf, 0); (void)pCtx; return status; @@ -5550,18 +5565,18 @@ uint32_t dot11f_unpack_ie_ht2040_bss_coexistence(tpAniSirGlobal pCtx, tDot11fIEht2040_bss_coexistence *pDst) { uint32_t status = DOT11F_PARSE_SUCCESS; - uint8_t tmp65__; + uint8_t tmp66__; (void) pBuf; (void)ielen; /* Shutup the compiler */ if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; - tmp65__ = *pBuf; - pDst->info_request = tmp65__ >> 0 & 0x1; - pDst->forty_mhz_intolerant = tmp65__ >> 1 & 0x1; - pDst->twenty_mhz_bsswidth_req = tmp65__ >> 2 & 0x1; - pDst->obss_scan_exemption_req = tmp65__ >> 3 & 0x1; - pDst->obss_scan_exemption_grant = tmp65__ >> 4 & 0x1; - pDst->unused = tmp65__ >> 5 & 0x7; + tmp66__ = *pBuf; + pDst->info_request = tmp66__ >> 0 & 0x1; + pDst->forty_mhz_intolerant = tmp66__ >> 1 & 0x1; + pDst->twenty_mhz_bsswidth_req = tmp66__ >> 2 & 0x1; + pDst->obss_scan_exemption_req = tmp66__ >> 3 & 0x1; + pDst->obss_scan_exemption_grant = tmp66__ >> 4 & 0x1; + pDst->unused = tmp66__ >> 5 & 0x7; (void)pCtx; return status; } /* End dot11f_unpack_ie_ht2040_bss_coexistence. */ @@ -8391,6 +8406,36 @@ uint32_t dot11f_unpack_wmm_del_ts(tpAniSirGlobal pCtx, } /* End dot11f_unpack_wmm_del_ts. */ +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, },}; + +uint32_t dot11f_unpack_ext_channel_switch_action_frame(tpAniSirGlobal pCtx, + uint8_t *pBuf, uint32_t nBuf, + tDot11fext_channel_switch_action_frame *pFrm) +{ + uint32_t i = 0; + uint32_t status = 0; + status = unpack_core(pCtx, pBuf, nBuf, + FFS_ext_channel_switch_action_frame, IES_ext_channel_switch_action_frame, + (uint8_t *)pFrm, sizeof(*pFrm)); + + (void)i; + return status; + +} /* End dot11f_unpack_ext_channel_switch_action_frame. */ + static const tFFDefn FFS_ht2040_bss_coexistence_mgmt_action_frame[] = { { "Category", offsetof(tDot11fht2040_bss_coexistence_mgmt_action_frame, Category), SigFfCategory, DOT11F_FF_CATEGORY_LEN, }, @@ -8625,6 +8670,11 @@ static uint32_t unpack_core(tpAniSirGlobal pCtx, pBufRemaining, (tDot11fFfVhtUserPositionArray *) (pFrm + pFf->offset)); break; + case SigFfext_chan_switch_ann_action: + dot11f_unpack_ff_ext_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 " @@ -11374,6 +11424,16 @@ uint32_t dot11f_get_packed_wmm_del_ts_size(tpAniSirGlobal pCtx, return status; } /* End dot11f_get_packed_wmm_del_ts_size. */ +uint32_t dot11f_get_packed_ext_channel_switch_action_frame_size(tpAniSirGlobal pCtx, + tDot11fext_channel_switch_action_frame *pFrm, uint32_t *pnNeeded) +{ + uint32_t status = 0; + *pnNeeded = 6; + status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded, + IES_ext_channel_switch_action_frame); + return status; +} /* End dot11f_get_packed_ext_channel_switch_action_frame_size. */ + uint32_t dot11f_get_packed_ht2040_bss_coexistence_mgmt_action_frameSize(tpAniSirGlobal pCtx, tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, uint32_t *pnNeeded) { @@ -12625,25 +12685,25 @@ void dot11f_pack_ff_capabilities(tpAniSirGlobal pCtx, tDot11fFfCapabilities *pSrc, uint8_t *pBuf) { - uint16_t tmp66__; - tmp66__ = 0U; - tmp66__ |= (pSrc->ess << 0); - tmp66__ |= (pSrc->ibss << 1); - tmp66__ |= (pSrc->cfPollable << 2); - tmp66__ |= (pSrc->cfPollReq << 3); - tmp66__ |= (pSrc->privacy << 4); - tmp66__ |= (pSrc->shortPreamble << 5); - tmp66__ |= (pSrc->pbcc << 6); - tmp66__ |= (pSrc->channelAgility << 7); - tmp66__ |= (pSrc->spectrumMgt << 8); - tmp66__ |= (pSrc->qos << 9); - tmp66__ |= (pSrc->shortSlotTime << 10); - tmp66__ |= (pSrc->apsd << 11); - tmp66__ |= (pSrc->rrm << 12); - tmp66__ |= (pSrc->dsssOfdm << 13); - tmp66__ |= (pSrc->delayedBA << 14); - tmp66__ |= (pSrc->immediateBA << 15); - frameshtons(pCtx, pBuf, tmp66__, 0); + uint16_t tmp67__; + tmp67__ = 0U; + tmp67__ |= (pSrc->ess << 0); + tmp67__ |= (pSrc->ibss << 1); + tmp67__ |= (pSrc->cfPollable << 2); + tmp67__ |= (pSrc->cfPollReq << 3); + tmp67__ |= (pSrc->privacy << 4); + tmp67__ |= (pSrc->shortPreamble << 5); + tmp67__ |= (pSrc->pbcc << 6); + tmp67__ |= (pSrc->channelAgility << 7); + tmp67__ |= (pSrc->spectrumMgt << 8); + tmp67__ |= (pSrc->qos << 9); + tmp67__ |= (pSrc->shortSlotTime << 10); + tmp67__ |= (pSrc->apsd << 11); + tmp67__ |= (pSrc->rrm << 12); + tmp67__ |= (pSrc->dsssOfdm << 13); + tmp67__ |= (pSrc->delayedBA << 14); + tmp67__ |= (pSrc->immediateBA << 15); + frameshtons(pCtx, pBuf, tmp67__, 0); (void)pCtx; } /* End dot11f_pack_ff_capabilities. */ @@ -12707,13 +12767,13 @@ void dot11f_pack_ff_operating_mode(tpAniSirGlobal pCtx, tDot11fFfOperatingMode *pSrc, uint8_t *pBuf) { - uint8_t tmp67__; - tmp67__ = 0U; - tmp67__ |= (pSrc->chanWidth << 0); - tmp67__ |= (pSrc->reserved << 2); - tmp67__ |= (pSrc->rxNSS << 4); - tmp67__ |= (pSrc->rxNSSType << 7); - *pBuf = tmp67__; + uint8_t tmp68__; + tmp68__ = 0U; + tmp68__ |= (pSrc->chanWidth << 0); + tmp68__ |= (pSrc->reserved << 2); + tmp68__ |= (pSrc->rxNSS << 4); + tmp68__ |= (pSrc->rxNSSType << 7); + *pBuf = tmp68__; (void)pCtx; } /* End dot11f_pack_ff_operating_mode. */ @@ -12753,12 +12813,12 @@ void dot11f_pack_ff_sm_power_mode_set(tpAniSirGlobal pCtx, tDot11fFfSMPowerModeSet *pSrc, uint8_t *pBuf) { - uint8_t tmp68__; - tmp68__ = 0U; - tmp68__ |= (pSrc->PowerSave_En << 0); - tmp68__ |= (pSrc->Mode << 1); - tmp68__ |= (pSrc->reserved << 2); - *pBuf = tmp68__; + uint8_t tmp69__; + tmp69__ = 0U; + tmp69__ |= (pSrc->PowerSave_En << 0); + tmp69__ |= (pSrc->Mode << 1); + tmp69__ |= (pSrc->reserved << 2); + *pBuf = tmp69__; (void)pCtx; } /* End dot11f_pack_ff_sm_power_mode_set. */ @@ -12798,19 +12858,19 @@ void dot11f_pack_ff_ts_info(tpAniSirGlobal pCtx, tDot11fFfTSInfo *pSrc, uint8_t *pBuf) { - uint32_t tmp69__; - tmp69__ = 0U; - tmp69__ |= (pSrc->traffic_type << 0); - tmp69__ |= (pSrc->tsid << 1); - tmp69__ |= (pSrc->direction << 5); - tmp69__ |= (pSrc->access_policy << 7); - tmp69__ |= (pSrc->aggregation << 9); - tmp69__ |= (pSrc->psb << 10); - tmp69__ |= (pSrc->user_priority << 11); - tmp69__ |= (pSrc->tsinfo_ack_pol << 14); - tmp69__ |= (pSrc->schedule << 16); - tmp69__ |= (pSrc->unused << 17); - frameshtonl(pCtx, pBuf, tmp69__, 0); + uint32_t tmp70__; + tmp70__ = 0U; + tmp70__ |= (pSrc->traffic_type << 0); + tmp70__ |= (pSrc->tsid << 1); + tmp70__ |= (pSrc->direction << 5); + tmp70__ |= (pSrc->access_policy << 7); + tmp70__ |= (pSrc->aggregation << 9); + tmp70__ |= (pSrc->psb << 10); + tmp70__ |= (pSrc->user_priority << 11); + tmp70__ |= (pSrc->tsinfo_ack_pol << 14); + tmp70__ |= (pSrc->schedule << 16); + tmp70__ |= (pSrc->unused << 17); + frameshtonl(pCtx, pBuf, tmp70__, 0); (void)pCtx; } /* End dot11f_pack_ff_ts_info. */ @@ -12862,6 +12922,20 @@ void dot11f_pack_ff_vht_user_position_array(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11f_pack_ff_vht_user_position_array. */ +void dot11f_pack_ff_ext_chan_switch_ann_action(tpAniSirGlobal pCtx, + tDot11fFfext_chan_switch_ann_action *pSrc, + uint8_t *pBuf) +{ + uint32_t tmp71__; + tmp71__ = 0U; + tmp71__ |= (pSrc->switch_mode << 0); + tmp71__ |= (pSrc->op_class << 8); + tmp71__ |= (pSrc->new_channel << 16); + tmp71__ |= (pSrc->switch_count << 24); + frameshtonl(pCtx, pBuf, tmp71__, 0); + (void)pCtx; +} /* End dot11f_pack_ff_ext_chan_switch_ann_action. */ + uint32_t dot11f_pack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx, tDot11fTLVAuthorizedMACs *pSrc, uint8_t *pBuf, @@ -12929,7 +13003,7 @@ uint32_t dot11f_pack_tlv_version2(tpAniSirGlobal pCtx, uint8_t *pTlvLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp70__; + uint8_t tmp72__; nNeeded += 3; if (nNeeded > nBuf) return DOT11F_BUFFER_OVERFLOW; @@ -12938,10 +13012,10 @@ uint32_t dot11f_pack_tlv_version2(tpAniSirGlobal pCtx, pBuf += 1; *pnConsumed += 1; pTlvLen = pBuf; pBuf += 1; *pnConsumed += 1; - tmp70__ = 0U; - tmp70__ |= (pSrc->minor << 0); - tmp70__ |= (pSrc->major << 4); - *pBuf = tmp70__; + tmp72__ = 0U; + tmp72__ |= (pSrc->minor << 0); + tmp72__ |= (pSrc->major << 4); + *pBuf = tmp72__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -13898,7 +13972,7 @@ uint32_t dot11f_pack_tlv_version(tpAniSirGlobal pCtx, uint8_t *pTlvLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp71__; + uint8_t tmp73__; nNeeded += 5; if (nNeeded > nBuf) return DOT11F_BUFFER_OVERFLOW; @@ -13907,10 +13981,10 @@ uint32_t dot11f_pack_tlv_version(tpAniSirGlobal pCtx, pBuf += 2; *pnConsumed += 2; pTlvLen = pBuf; pBuf += 2; *pnConsumed += 2; - tmp71__ = 0U; - tmp71__ |= (pSrc->minor << 0); - tmp71__ |= (pSrc->major << 4); - *pBuf = tmp71__; + tmp73__ = 0U; + tmp73__ |= (pSrc->minor << 0); + tmp73__ |= (pSrc->major << 4); + *pBuf = tmp73__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -14048,7 +14122,7 @@ uint32_t dot11f_pack_ie_gtk(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp72__; + uint16_t tmp74__; nNeeded += (pSrc->num_key + 11); while (pSrc->present) { if (nNeeded > nBuf) @@ -14057,10 +14131,10 @@ uint32_t dot11f_pack_ie_gtk(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp72__ = 0U; - tmp72__ |= (pSrc->keyId << 0); - tmp72__ |= (pSrc->reserved << 2); - frameshtons(pCtx, pBuf, tmp72__, 0); + tmp74__ = 0U; + tmp74__ |= (pSrc->keyId << 0); + tmp74__ |= (pSrc->reserved << 2); + frameshtons(pCtx, pBuf, tmp74__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -14472,11 +14546,11 @@ uint32_t dot11f_pack_ie_rrm_enabled_cap(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp73__; - uint8_t tmp74__; uint8_t tmp75__; uint8_t tmp76__; uint8_t tmp77__; + uint8_t tmp78__; + uint8_t tmp79__; nNeeded += 5; while (pSrc->present) { if (nNeeded > nBuf) @@ -14485,60 +14559,60 @@ uint32_t dot11f_pack_ie_rrm_enabled_cap(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp73__ = 0U; - tmp73__ |= (pSrc->LinkMeasurement << 0); - tmp73__ |= (pSrc->NeighborRpt << 1); - tmp73__ |= (pSrc->parallel << 2); - tmp73__ |= (pSrc->repeated << 3); - tmp73__ |= (pSrc->BeaconPassive << 4); - tmp73__ |= (pSrc->BeaconActive << 5); - tmp73__ |= (pSrc->BeaconTable << 6); - tmp73__ |= (pSrc->BeaconRepCond << 7); - *pBuf = tmp73__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; - tmp74__ = 0U; - tmp74__ |= (pSrc->FrameMeasurement << 0); - tmp74__ |= (pSrc->ChannelLoad << 1); - tmp74__ |= (pSrc->NoiseHistogram << 2); - tmp74__ |= (pSrc->statistics << 3); - tmp74__ |= (pSrc->LCIMeasurement << 4); - tmp74__ |= (pSrc->LCIAzimuth << 5); - tmp74__ |= (pSrc->TCMCapability << 6); - tmp74__ |= (pSrc->triggeredTCM << 7); - *pBuf = tmp74__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; tmp75__ = 0U; - tmp75__ |= (pSrc->APChanReport << 0); - tmp75__ |= (pSrc->RRMMIBEnabled << 1); - tmp75__ |= (pSrc->operatingChanMax << 2); - tmp75__ |= (pSrc->nonOperatinChanMax << 5); + tmp75__ |= (pSrc->LinkMeasurement << 0); + tmp75__ |= (pSrc->NeighborRpt << 1); + tmp75__ |= (pSrc->parallel << 2); + tmp75__ |= (pSrc->repeated << 3); + tmp75__ |= (pSrc->BeaconPassive << 4); + tmp75__ |= (pSrc->BeaconActive << 5); + tmp75__ |= (pSrc->BeaconTable << 6); + tmp75__ |= (pSrc->BeaconRepCond << 7); *pBuf = tmp75__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp76__ = 0U; - tmp76__ |= (pSrc->MeasurementPilot << 0); - tmp76__ |= (pSrc->MeasurementPilotEnabled << 3); - tmp76__ |= (pSrc->NeighborTSFOffset << 4); - tmp76__ |= (pSrc->RCPIMeasurement << 5); - tmp76__ |= (pSrc->RSNIMeasurement << 6); - tmp76__ |= (pSrc->BssAvgAccessDelay << 7); + tmp76__ |= (pSrc->FrameMeasurement << 0); + tmp76__ |= (pSrc->ChannelLoad << 1); + tmp76__ |= (pSrc->NoiseHistogram << 2); + tmp76__ |= (pSrc->statistics << 3); + tmp76__ |= (pSrc->LCIMeasurement << 4); + tmp76__ |= (pSrc->LCIAzimuth << 5); + tmp76__ |= (pSrc->TCMCapability << 6); + tmp76__ |= (pSrc->triggeredTCM << 7); *pBuf = tmp76__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp77__ = 0U; - tmp77__ |= (pSrc->BSSAvailAdmission << 0); - tmp77__ |= (pSrc->AntennaInformation << 1); - tmp77__ |= (pSrc->fine_time_meas_rpt << 2); - tmp77__ |= (pSrc->lci_capability << 3); - tmp77__ |= (pSrc->reserved << 4); + tmp77__ |= (pSrc->APChanReport << 0); + tmp77__ |= (pSrc->RRMMIBEnabled << 1); + tmp77__ |= (pSrc->operatingChanMax << 2); + tmp77__ |= (pSrc->nonOperatinChanMax << 5); *pBuf = tmp77__; *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp78__ = 0U; + tmp78__ |= (pSrc->MeasurementPilot << 0); + tmp78__ |= (pSrc->MeasurementPilotEnabled << 3); + tmp78__ |= (pSrc->NeighborTSFOffset << 4); + tmp78__ |= (pSrc->RCPIMeasurement << 5); + tmp78__ |= (pSrc->RSNIMeasurement << 6); + tmp78__ |= (pSrc->BssAvgAccessDelay << 7); + *pBuf = tmp78__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp79__ = 0U; + tmp79__ |= (pSrc->BSSAvailAdmission << 0); + tmp79__ |= (pSrc->AntennaInformation << 1); + tmp79__ |= (pSrc->fine_time_meas_rpt << 2); + tmp79__ |= (pSrc->lci_capability << 3); + tmp79__ |= (pSrc->reserved << 4); + *pBuf = tmp79__; + *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; break; @@ -14617,7 +14691,7 @@ uint32_t dot11f_pack_ie_schedule(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp78__; + uint16_t tmp80__; nNeeded += 14; while (pSrc->present) { if (nNeeded > nBuf) @@ -14626,12 +14700,12 @@ uint32_t dot11f_pack_ie_schedule(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp78__ = 0U; - tmp78__ |= (pSrc->aggregation << 0); - tmp78__ |= (pSrc->tsid << 1); - tmp78__ |= (pSrc->direction << 5); - tmp78__ |= (pSrc->reserved << 7); - frameshtons(pCtx, pBuf, tmp78__, 0); + tmp80__ = 0U; + tmp80__ |= (pSrc->aggregation << 0); + tmp80__ |= (pSrc->tsid << 1); + tmp80__ |= (pSrc->direction << 5); + tmp80__ |= (pSrc->reserved << 7); + frameshtons(pCtx, pBuf, tmp80__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -14826,9 +14900,9 @@ uint32_t dot11f_pack_ie_tspec(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp79__; - uint8_t tmp80__; uint16_t tmp81__; + uint8_t tmp82__; + uint16_t tmp83__; nNeeded += 55; while (pSrc->present) { if (nNeeded > nBuf) @@ -14837,30 +14911,30 @@ uint32_t dot11f_pack_ie_tspec(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp79__ = 0U; - tmp79__ |= (pSrc->traffic_type << 0); - tmp79__ |= (pSrc->tsid << 1); - tmp79__ |= (pSrc->direction << 5); - tmp79__ |= (pSrc->access_policy << 7); - tmp79__ |= (pSrc->aggregation << 9); - tmp79__ |= (pSrc->psb << 10); - tmp79__ |= (pSrc->user_priority << 11); - tmp79__ |= (pSrc->tsinfo_ack_pol << 14); - frameshtons(pCtx, pBuf, tmp79__, 0); + tmp81__ = 0U; + tmp81__ |= (pSrc->traffic_type << 0); + tmp81__ |= (pSrc->tsid << 1); + tmp81__ |= (pSrc->direction << 5); + tmp81__ |= (pSrc->access_policy << 7); + tmp81__ |= (pSrc->aggregation << 9); + tmp81__ |= (pSrc->psb << 10); + tmp81__ |= (pSrc->user_priority << 11); + tmp81__ |= (pSrc->tsinfo_ack_pol << 14); + frameshtons(pCtx, pBuf, tmp81__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp80__ = 0U; - tmp80__ |= (pSrc->schedule << 0); - tmp80__ |= (pSrc->unused << 1); - *pBuf = tmp80__; + tmp82__ = 0U; + tmp82__ |= (pSrc->schedule << 0); + tmp82__ |= (pSrc->unused << 1); + *pBuf = tmp82__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp81__ = 0U; - tmp81__ |= (pSrc->size << 0); - tmp81__ |= (pSrc->fixed << 15); - frameshtons(pCtx, pBuf, tmp81__, 0); + tmp83__ = 0U; + tmp83__ |= (pSrc->size << 0); + tmp83__ |= (pSrc->fixed << 15); + frameshtons(pCtx, pBuf, tmp83__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -14924,9 +14998,9 @@ uint32_t dot11f_pack_ie_vht_caps(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint32_t tmp82__; - uint16_t tmp83__; - uint16_t tmp84__; + uint32_t tmp84__; + uint16_t tmp85__; + uint16_t tmp86__; nNeeded += 12; while (pSrc->present) { if (nNeeded > nBuf) @@ -14935,48 +15009,48 @@ uint32_t dot11f_pack_ie_vht_caps(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp82__ = 0U; - tmp82__ |= (pSrc->maxMPDULen << 0); - tmp82__ |= (pSrc->supportedChannelWidthSet << 2); - tmp82__ |= (pSrc->ldpcCodingCap << 4); - tmp82__ |= (pSrc->shortGI80MHz << 5); - tmp82__ |= (pSrc->shortGI160and80plus80MHz << 6); - tmp82__ |= (pSrc->txSTBC << 7); - tmp82__ |= (pSrc->rxSTBC << 8); - tmp82__ |= (pSrc->suBeamFormerCap << 11); - tmp82__ |= (pSrc->suBeamformeeCap << 12); - tmp82__ |= (pSrc->csnofBeamformerAntSup << 13); - tmp82__ |= (pSrc->numSoundingDim << 16); - tmp82__ |= (pSrc->muBeamformerCap << 19); - tmp82__ |= (pSrc->muBeamformeeCap << 20); - tmp82__ |= (pSrc->vhtTXOPPS << 21); - tmp82__ |= (pSrc->htcVHTCap << 22); - tmp82__ |= (pSrc->maxAMPDULenExp << 23); - tmp82__ |= (pSrc->vhtLinkAdaptCap << 26); - tmp82__ |= (pSrc->rxAntPattern << 28); - tmp82__ |= (pSrc->txAntPattern << 29); - tmp82__ |= (pSrc->reserved1 << 30); - frameshtonl(pCtx, pBuf, tmp82__, 0); + tmp84__ = 0U; + tmp84__ |= (pSrc->maxMPDULen << 0); + tmp84__ |= (pSrc->supportedChannelWidthSet << 2); + tmp84__ |= (pSrc->ldpcCodingCap << 4); + tmp84__ |= (pSrc->shortGI80MHz << 5); + tmp84__ |= (pSrc->shortGI160and80plus80MHz << 6); + tmp84__ |= (pSrc->txSTBC << 7); + tmp84__ |= (pSrc->rxSTBC << 8); + tmp84__ |= (pSrc->suBeamFormerCap << 11); + tmp84__ |= (pSrc->suBeamformeeCap << 12); + tmp84__ |= (pSrc->csnofBeamformerAntSup << 13); + tmp84__ |= (pSrc->numSoundingDim << 16); + tmp84__ |= (pSrc->muBeamformerCap << 19); + tmp84__ |= (pSrc->muBeamformeeCap << 20); + tmp84__ |= (pSrc->vhtTXOPPS << 21); + tmp84__ |= (pSrc->htcVHTCap << 22); + tmp84__ |= (pSrc->maxAMPDULenExp << 23); + tmp84__ |= (pSrc->vhtLinkAdaptCap << 26); + tmp84__ |= (pSrc->rxAntPattern << 28); + tmp84__ |= (pSrc->txAntPattern << 29); + tmp84__ |= (pSrc->reserved1 << 30); + frameshtonl(pCtx, pBuf, tmp84__, 0); *pnConsumed += 4; pBuf += 4; nBuf -= 4 ; frameshtons(pCtx, pBuf, pSrc->rxMCSMap, 0); *pnConsumed += 2; pBuf += 2; - tmp83__ = 0U; - tmp83__ |= (pSrc->rxHighSupDataRate << 0); - tmp83__ |= (pSrc->reserved2 << 13); - frameshtons(pCtx, pBuf, tmp83__, 0); + tmp85__ = 0U; + tmp85__ |= (pSrc->rxHighSupDataRate << 0); + tmp85__ |= (pSrc->reserved2 << 13); + frameshtons(pCtx, pBuf, tmp85__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; frameshtons(pCtx, pBuf, pSrc->txMCSMap, 0); *pnConsumed += 2; pBuf += 2; - tmp84__ = 0U; - tmp84__ |= (pSrc->txSupDataRate << 0); - tmp84__ |= (pSrc->reserved3 << 13); - frameshtons(pCtx, pBuf, tmp84__, 0); + tmp86__ = 0U; + tmp86__ |= (pSrc->txSupDataRate << 0); + tmp86__ |= (pSrc->reserved3 << 13); + frameshtons(pCtx, pBuf, tmp86__, 0); *pnConsumed += 2; /* fieldsEndFlag = 1 */ nBuf -= 2 ; @@ -15036,7 +15110,7 @@ uint32_t dot11f_pack_ie_wmm_schedule(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp85__; + uint16_t tmp87__; nNeeded += 15; while (pSrc->present) { if (nNeeded > nBuf) @@ -15058,12 +15132,12 @@ uint32_t dot11f_pack_ie_wmm_schedule(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp85__ = 0U; - tmp85__ |= (pSrc->aggregation << 0); - tmp85__ |= (pSrc->tsid << 1); - tmp85__ |= (pSrc->direction << 5); - tmp85__ |= (pSrc->reserved << 7); - frameshtons(pCtx, pBuf, tmp85__, 0); + tmp87__ = 0U; + tmp87__ |= (pSrc->aggregation << 0); + tmp87__ |= (pSrc->tsid << 1); + tmp87__ |= (pSrc->direction << 5); + tmp87__ |= (pSrc->reserved << 7); + frameshtons(pCtx, pBuf, tmp87__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -15297,9 +15371,9 @@ uint32_t dot11f_pack_ie_wmmtspec(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp86__; - uint8_t tmp87__; uint16_t tmp88__; + uint8_t tmp89__; + uint16_t tmp90__; nNeeded += 38; while (pSrc->present) { if (nNeeded > nBuf) @@ -15321,30 +15395,30 @@ uint32_t dot11f_pack_ie_wmmtspec(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp86__ = 0U; - tmp86__ |= (pSrc->traffic_type << 0); - tmp86__ |= (pSrc->tsid << 1); - tmp86__ |= (pSrc->direction << 5); - tmp86__ |= (pSrc->access_policy << 7); - tmp86__ |= (pSrc->aggregation << 9); - tmp86__ |= (pSrc->psb << 10); - tmp86__ |= (pSrc->user_priority << 11); - tmp86__ |= (pSrc->tsinfo_ack_pol << 14); - frameshtons(pCtx, pBuf, tmp86__, 0); + tmp88__ = 0U; + tmp88__ |= (pSrc->traffic_type << 0); + tmp88__ |= (pSrc->tsid << 1); + tmp88__ |= (pSrc->direction << 5); + tmp88__ |= (pSrc->access_policy << 7); + tmp88__ |= (pSrc->aggregation << 9); + tmp88__ |= (pSrc->psb << 10); + tmp88__ |= (pSrc->user_priority << 11); + tmp88__ |= (pSrc->tsinfo_ack_pol << 14); + frameshtons(pCtx, pBuf, tmp88__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp87__ = 0U; - tmp87__ |= (pSrc->tsinfo_rsvd << 0); - tmp87__ |= (pSrc->burst_size_defn << 7); - *pBuf = tmp87__; + tmp89__ = 0U; + tmp89__ |= (pSrc->tsinfo_rsvd << 0); + tmp89__ |= (pSrc->burst_size_defn << 7); + *pBuf = tmp89__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp88__ = 0U; - tmp88__ |= (pSrc->size << 0); - tmp88__ |= (pSrc->fixed << 15); - frameshtons(pCtx, pBuf, tmp88__, 0); + tmp90__ = 0U; + tmp90__ |= (pSrc->size << 0); + tmp90__ |= (pSrc->fixed << 15); + frameshtons(pCtx, pBuf, tmp90__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -15678,14 +15752,14 @@ uint32_t dot11f_pack_ie_edca_param_set(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp89__; - uint8_t tmp90__; uint8_t tmp91__; uint8_t tmp92__; uint8_t tmp93__; uint8_t tmp94__; uint8_t tmp95__; uint8_t tmp96__; + uint8_t tmp97__; + uint8_t tmp98__; nNeeded += 18; while (pSrc->present) { if (nNeeded > nBuf) @@ -15700,79 +15774,79 @@ uint32_t dot11f_pack_ie_edca_param_set(tpAniSirGlobal pCtx, *pBuf = pSrc->reserved; *pnConsumed += 1; pBuf += 1; - tmp89__ = 0U; - tmp89__ |= (pSrc->acbe_aifsn << 0); - tmp89__ |= (pSrc->acbe_acm << 4); - tmp89__ |= (pSrc->acbe_aci << 5); - tmp89__ |= (pSrc->unused1 << 7); - *pBuf = tmp89__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; - tmp90__ = 0U; - tmp90__ |= (pSrc->acbe_acwmin << 0); - tmp90__ |= (pSrc->acbe_acwmax << 4); - *pBuf = tmp90__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp91__ = 0U; - tmp91__ |= (pSrc->acbk_aifsn << 0); - tmp91__ |= (pSrc->acbk_acm << 4); - tmp91__ |= (pSrc->acbk_aci << 5); - tmp91__ |= (pSrc->unused2 << 7); + tmp91__ |= (pSrc->acbe_aifsn << 0); + tmp91__ |= (pSrc->acbe_acm << 4); + tmp91__ |= (pSrc->acbe_aci << 5); + tmp91__ |= (pSrc->unused1 << 7); *pBuf = tmp91__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp92__ = 0U; - tmp92__ |= (pSrc->acbk_acwmin << 0); - tmp92__ |= (pSrc->acbk_acwmax << 4); + tmp92__ |= (pSrc->acbe_acwmin << 0); + tmp92__ |= (pSrc->acbe_acwmax << 4); *pBuf = tmp92__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); *pnConsumed += 2; pBuf += 2; tmp93__ = 0U; - tmp93__ |= (pSrc->acvi_aifsn << 0); - tmp93__ |= (pSrc->acvi_acm << 4); - tmp93__ |= (pSrc->acvi_aci << 5); - tmp93__ |= (pSrc->unused3 << 7); + tmp93__ |= (pSrc->acbk_aifsn << 0); + tmp93__ |= (pSrc->acbk_acm << 4); + tmp93__ |= (pSrc->acbk_aci << 5); + tmp93__ |= (pSrc->unused2 << 7); *pBuf = tmp93__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp94__ = 0U; - tmp94__ |= (pSrc->acvi_acwmin << 0); - tmp94__ |= (pSrc->acvi_acwmax << 4); + tmp94__ |= (pSrc->acbk_acwmin << 0); + tmp94__ |= (pSrc->acbk_acwmax << 4); *pBuf = tmp94__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); *pnConsumed += 2; pBuf += 2; tmp95__ = 0U; - tmp95__ |= (pSrc->acvo_aifsn << 0); - tmp95__ |= (pSrc->acvo_acm << 4); - tmp95__ |= (pSrc->acvo_aci << 5); - tmp95__ |= (pSrc->unused4 << 7); + tmp95__ |= (pSrc->acvi_aifsn << 0); + tmp95__ |= (pSrc->acvi_acm << 4); + tmp95__ |= (pSrc->acvi_aci << 5); + tmp95__ |= (pSrc->unused3 << 7); *pBuf = tmp95__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp96__ = 0U; - tmp96__ |= (pSrc->acvo_acwmin << 0); - tmp96__ |= (pSrc->acvo_acwmax << 4); + tmp96__ |= (pSrc->acvi_acwmin << 0); + tmp96__ |= (pSrc->acvi_acwmax << 4); *pBuf = tmp96__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp97__ = 0U; + tmp97__ |= (pSrc->acvo_aifsn << 0); + tmp97__ |= (pSrc->acvo_acm << 4); + tmp97__ |= (pSrc->acvo_aci << 5); + tmp97__ |= (pSrc->unused4 << 7); + *pBuf = tmp97__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp98__ = 0U; + tmp98__ |= (pSrc->acvo_acwmin << 0); + tmp98__ |= (pSrc->acvo_acwmax << 4); + *pBuf = tmp98__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); *pnConsumed += 2; /* fieldsEndFlag = 1 */ @@ -15794,7 +15868,7 @@ uint32_t dot11f_pack_ie_erp_info(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp97__; + uint8_t tmp99__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -15803,12 +15877,12 @@ uint32_t dot11f_pack_ie_erp_info(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp97__ = 0U; - tmp97__ |= (pSrc->non_erp_present << 0); - tmp97__ |= (pSrc->use_prot << 1); - tmp97__ |= (pSrc->barker_preamble << 2); - tmp97__ |= (pSrc->unused << 3); - *pBuf = tmp97__; + tmp99__ = 0U; + tmp99__ |= (pSrc->non_erp_present << 0); + tmp99__ |= (pSrc->use_prot << 1); + tmp99__ |= (pSrc->barker_preamble << 2); + tmp99__ |= (pSrc->unused << 3); + *pBuf = tmp99__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -15867,7 +15941,7 @@ uint32_t dot11f_pack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp98__; + uint8_t tmp100__; nNeeded += 2; while (pSrc->present) { if (nNeeded > nBuf) @@ -15887,10 +15961,10 @@ uint32_t dot11f_pack_ie_ese_rad_mgmt_cap(tpAniSirGlobal pCtx, *pBuf = pSrc->mgmt_state; *pnConsumed += 1; pBuf += 1; - tmp98__ = 0U; - tmp98__ |= (pSrc->mbssid_mask << 0); - tmp98__ |= (pSrc->reserved << 3); - *pBuf = tmp98__; + tmp100__ = 0U; + tmp100__ |= (pSrc->mbssid_mask << 0); + tmp100__ |= (pSrc->reserved << 3); + *pBuf = tmp100__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -16241,7 +16315,7 @@ uint32_t dot11f_pack_ie_ft_info(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp99__; + uint16_t tmp101__; uint32_t status = DOT11F_PARSE_SUCCESS; status = dot11f_get_packed_ieft_info(pCtx, pSrc, &nNeeded); if (!DOT11F_SUCCEEDED(status)) @@ -16253,10 +16327,10 @@ uint32_t dot11f_pack_ie_ft_info(tpAniSirGlobal pCtx, ++pBuf; --nBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; --nBuf; ++(*pnConsumed); - tmp99__ = 0U; - tmp99__ |= (pSrc->reserved << 0); - tmp99__ |= (pSrc->IECount << 8); - frameshtons(pCtx, pBuf, tmp99__, 0); + tmp101__ = 0U; + tmp101__ |= (pSrc->reserved << 0); + tmp101__ |= (pSrc->IECount << 8); + frameshtons(pCtx, pBuf, tmp101__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -16294,11 +16368,11 @@ uint32_t dot11f_pack_ie_ht_caps(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp100__; - uint8_t tmp101__; uint16_t tmp102__; - uint32_t tmp103__; - uint8_t tmp104__; + uint8_t tmp103__; + uint16_t tmp104__; + uint32_t tmp105__; + uint8_t tmp106__; nNeeded += (pSrc->num_rsvd + 26); while (pSrc->present) { if (nNeeded > nBuf) @@ -16307,77 +16381,77 @@ uint32_t dot11f_pack_ie_ht_caps(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp100__ = 0U; - tmp100__ |= (pSrc->advCodingCap << 0); - tmp100__ |= (pSrc->supportedChannelWidthSet << 1); - tmp100__ |= (pSrc->mimoPowerSave << 2); - tmp100__ |= (pSrc->greenField << 4); - tmp100__ |= (pSrc->shortGI20MHz << 5); - tmp100__ |= (pSrc->shortGI40MHz << 6); - tmp100__ |= (pSrc->txSTBC << 7); - tmp100__ |= (pSrc->rxSTBC << 8); - tmp100__ |= (pSrc->delayedBA << 10); - tmp100__ |= (pSrc->maximalAMSDUsize << 11); - tmp100__ |= (pSrc->dsssCckMode40MHz << 12); - tmp100__ |= (pSrc->psmp << 13); - tmp100__ |= (pSrc->stbcControlFrame << 14); - tmp100__ |= (pSrc->lsigTXOPProtection << 15); - frameshtons(pCtx, pBuf, tmp100__, 0); + tmp102__ = 0U; + tmp102__ |= (pSrc->advCodingCap << 0); + tmp102__ |= (pSrc->supportedChannelWidthSet << 1); + tmp102__ |= (pSrc->mimoPowerSave << 2); + tmp102__ |= (pSrc->greenField << 4); + tmp102__ |= (pSrc->shortGI20MHz << 5); + tmp102__ |= (pSrc->shortGI40MHz << 6); + tmp102__ |= (pSrc->txSTBC << 7); + tmp102__ |= (pSrc->rxSTBC << 8); + tmp102__ |= (pSrc->delayedBA << 10); + tmp102__ |= (pSrc->maximalAMSDUsize << 11); + tmp102__ |= (pSrc->dsssCckMode40MHz << 12); + tmp102__ |= (pSrc->psmp << 13); + tmp102__ |= (pSrc->stbcControlFrame << 14); + tmp102__ |= (pSrc->lsigTXOPProtection << 15); + frameshtons(pCtx, pBuf, tmp102__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp101__ = 0U; - tmp101__ |= (pSrc->maxRxAMPDUFactor << 0); - tmp101__ |= (pSrc->mpduDensity << 2); - tmp101__ |= (pSrc->reserved1 << 5); - *pBuf = tmp101__; + tmp103__ = 0U; + tmp103__ |= (pSrc->maxRxAMPDUFactor << 0); + tmp103__ |= (pSrc->mpduDensity << 2); + tmp103__ |= (pSrc->reserved1 << 5); + *pBuf = tmp103__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; DOT11F_MEMCPY(pCtx, pBuf, pSrc->supportedMCSSet, 16); *pnConsumed += 16; pBuf += 16; - tmp102__ = 0U; - tmp102__ |= (pSrc->pco << 0); - tmp102__ |= (pSrc->transitionTime << 1); - tmp102__ |= (pSrc->reserved2 << 3); - tmp102__ |= (pSrc->mcsFeedback << 8); - tmp102__ |= (pSrc->reserved3 << 10); - frameshtons(pCtx, pBuf, tmp102__, 0); + tmp104__ = 0U; + tmp104__ |= (pSrc->pco << 0); + tmp104__ |= (pSrc->transitionTime << 1); + tmp104__ |= (pSrc->reserved2 << 3); + tmp104__ |= (pSrc->mcsFeedback << 8); + tmp104__ |= (pSrc->reserved3 << 10); + frameshtons(pCtx, pBuf, tmp104__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp103__ = 0U; - tmp103__ |= (pSrc->txBF << 0); - tmp103__ |= (pSrc->rxStaggeredSounding << 1); - tmp103__ |= (pSrc->txStaggeredSounding << 2); - tmp103__ |= (pSrc->rxZLF << 3); - tmp103__ |= (pSrc->txZLF << 4); - tmp103__ |= (pSrc->implicitTxBF << 5); - tmp103__ |= (pSrc->calibration << 6); - tmp103__ |= (pSrc->explicitCSITxBF << 8); - tmp103__ |= (pSrc->explicitUncompressedSteeringMatrix << 9); - tmp103__ |= (pSrc->explicitBFCSIFeedback << 10); - tmp103__ |= (pSrc->explicitUncompressedSteeringMatrixFeedback << 13); - tmp103__ |= (pSrc->explicitCompressedSteeringMatrixFeedback << 16); - tmp103__ |= (pSrc->csiNumBFAntennae << 19); - tmp103__ |= (pSrc->uncompressedSteeringMatrixBFAntennae << 21); - tmp103__ |= (pSrc->compressedSteeringMatrixBFAntennae << 23); - tmp103__ |= (pSrc->reserved4 << 25); - frameshtonl(pCtx, pBuf, tmp103__, 0); + tmp105__ = 0U; + tmp105__ |= (pSrc->txBF << 0); + tmp105__ |= (pSrc->rxStaggeredSounding << 1); + tmp105__ |= (pSrc->txStaggeredSounding << 2); + tmp105__ |= (pSrc->rxZLF << 3); + tmp105__ |= (pSrc->txZLF << 4); + tmp105__ |= (pSrc->implicitTxBF << 5); + tmp105__ |= (pSrc->calibration << 6); + tmp105__ |= (pSrc->explicitCSITxBF << 8); + tmp105__ |= (pSrc->explicitUncompressedSteeringMatrix << 9); + tmp105__ |= (pSrc->explicitBFCSIFeedback << 10); + tmp105__ |= (pSrc->explicitUncompressedSteeringMatrixFeedback << 13); + tmp105__ |= (pSrc->explicitCompressedSteeringMatrixFeedback << 16); + tmp105__ |= (pSrc->csiNumBFAntennae << 19); + tmp105__ |= (pSrc->uncompressedSteeringMatrixBFAntennae << 21); + tmp105__ |= (pSrc->compressedSteeringMatrixBFAntennae << 23); + tmp105__ |= (pSrc->reserved4 << 25); + frameshtonl(pCtx, pBuf, tmp105__, 0); *pnConsumed += 4; pBuf += 4; nBuf -= 4 ; - tmp104__ = 0U; - tmp104__ |= (pSrc->antennaSelection << 0); - tmp104__ |= (pSrc->explicitCSIFeedbackTx << 1); - tmp104__ |= (pSrc->antennaIndicesFeedbackTx << 2); - tmp104__ |= (pSrc->explicitCSIFeedback << 3); - tmp104__ |= (pSrc->antennaIndicesFeedback << 4); - tmp104__ |= (pSrc->rxAS << 5); - tmp104__ |= (pSrc->txSoundingPPDUs << 6); - tmp104__ |= (pSrc->reserved5 << 7); - *pBuf = tmp104__; + tmp106__ = 0U; + tmp106__ |= (pSrc->antennaSelection << 0); + tmp106__ |= (pSrc->explicitCSIFeedbackTx << 1); + tmp106__ |= (pSrc->antennaIndicesFeedbackTx << 2); + tmp106__ |= (pSrc->explicitCSIFeedback << 3); + tmp106__ |= (pSrc->antennaIndicesFeedback << 4); + tmp106__ |= (pSrc->rxAS << 5); + tmp106__ |= (pSrc->txSoundingPPDUs << 6); + tmp106__ |= (pSrc->reserved5 << 7); + *pBuf = tmp106__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -16402,9 +16476,9 @@ uint32_t dot11f_pack_ie_ht_info(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp105__; - uint16_t tmp106__; - uint16_t tmp107__; + uint8_t tmp107__; + uint16_t tmp108__; + uint16_t tmp109__; nNeeded += (pSrc->num_rsvd + 22); while (pSrc->present) { if (nNeeded > nBuf) @@ -16416,35 +16490,35 @@ uint32_t dot11f_pack_ie_ht_info(tpAniSirGlobal pCtx, *pBuf = pSrc->primaryChannel; *pnConsumed += 1; pBuf += 1; - tmp105__ = 0U; - tmp105__ |= (pSrc->secondaryChannelOffset << 0); - tmp105__ |= (pSrc->recommendedTxWidthSet << 2); - tmp105__ |= (pSrc->rifsMode << 3); - tmp105__ |= (pSrc->controlledAccessOnly << 4); - tmp105__ |= (pSrc->serviceIntervalGranularity << 5); - *pBuf = tmp105__; + tmp107__ = 0U; + tmp107__ |= (pSrc->secondaryChannelOffset << 0); + tmp107__ |= (pSrc->recommendedTxWidthSet << 2); + tmp107__ |= (pSrc->rifsMode << 3); + tmp107__ |= (pSrc->controlledAccessOnly << 4); + tmp107__ |= (pSrc->serviceIntervalGranularity << 5); + *pBuf = tmp107__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp106__ = 0U; - tmp106__ |= (pSrc->opMode << 0); - tmp106__ |= (pSrc->nonGFDevicesPresent << 2); - tmp106__ |= (pSrc->transmitBurstLimit << 3); - tmp106__ |= (pSrc->obssNonHTStaPresent << 4); - tmp106__ |= (pSrc->reserved << 5); - frameshtons(pCtx, pBuf, tmp106__, 0); + tmp108__ = 0U; + tmp108__ |= (pSrc->opMode << 0); + tmp108__ |= (pSrc->nonGFDevicesPresent << 2); + tmp108__ |= (pSrc->transmitBurstLimit << 3); + tmp108__ |= (pSrc->obssNonHTStaPresent << 4); + tmp108__ |= (pSrc->reserved << 5); + frameshtons(pCtx, pBuf, tmp108__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp107__ = 0U; - tmp107__ |= (pSrc->basicSTBCMCS << 0); - tmp107__ |= (pSrc->dualCTSProtection << 7); - tmp107__ |= (pSrc->secondaryBeacon << 8); - tmp107__ |= (pSrc->lsigTXOPProtectionFullSupport << 9); - tmp107__ |= (pSrc->pcoActive << 10); - tmp107__ |= (pSrc->pcoPhase << 11); - tmp107__ |= (pSrc->reserved2 << 12); - frameshtons(pCtx, pBuf, tmp107__, 0); + tmp109__ = 0U; + tmp109__ |= (pSrc->basicSTBCMCS << 0); + tmp109__ |= (pSrc->dualCTSProtection << 7); + tmp109__ |= (pSrc->secondaryBeacon << 8); + tmp109__ |= (pSrc->lsigTXOPProtectionFullSupport << 9); + tmp109__ |= (pSrc->pcoActive << 10); + tmp109__ |= (pSrc->pcoPhase << 11); + tmp109__ |= (pSrc->reserved2 << 12); + frameshtons(pCtx, pBuf, tmp109__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -16536,9 +16610,9 @@ uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp108__; - uint8_t tmp109__; uint8_t tmp110__; + uint8_t tmp111__; + uint8_t tmp112__; uint32_t status = DOT11F_PARSE_SUCCESS; status = dot11f_get_packed_ie_measurement_report(pCtx, pSrc, &nNeeded); if (!DOT11F_SUCCEEDED(status)) @@ -16553,12 +16627,12 @@ uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx, *pBuf = pSrc->token; *pnConsumed += 1; pBuf += 1; - tmp108__ = 0U; - tmp108__ |= (pSrc->late << 0); - tmp108__ |= (pSrc->incapable << 1); - tmp108__ |= (pSrc->refused << 2); - tmp108__ |= (pSrc->unused << 3); - *pBuf = tmp108__; + tmp110__ = 0U; + tmp110__ |= (pSrc->late << 0); + tmp110__ |= (pSrc->incapable << 1); + tmp110__ |= (pSrc->refused << 2); + tmp110__ |= (pSrc->unused << 3); + *pBuf = tmp110__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -16577,14 +16651,14 @@ uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->report.Basic.meas_duration, 0); *pnConsumed += 2; pBuf += 2; - tmp109__ = 0U; - tmp109__ |= (pSrc->report.Basic.bss << 0); - tmp109__ |= (pSrc->report.Basic.ofdm_preamble << 1); - tmp109__ |= (pSrc->report.Basic.unid_signal << 2); - tmp109__ |= (pSrc->report.Basic.rader << 3); - tmp109__ |= (pSrc->report.Basic.unmeasured << 4); - tmp109__ |= (pSrc->report.Basic.unused << 5); - *pBuf = tmp109__; + tmp111__ = 0U; + tmp111__ |= (pSrc->report.Basic.bss << 0); + tmp111__ |= (pSrc->report.Basic.ofdm_preamble << 1); + tmp111__ |= (pSrc->report.Basic.unid_signal << 2); + tmp111__ |= (pSrc->report.Basic.rader << 3); + tmp111__ |= (pSrc->report.Basic.unmeasured << 4); + tmp111__ |= (pSrc->report.Basic.unused << 5); + *pBuf = tmp111__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -16651,10 +16725,10 @@ uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->report.Beacon.meas_duration, 0); *pnConsumed += 2; pBuf += 2; - tmp110__ = 0U; - tmp110__ |= (pSrc->report.Beacon.condensed_PHY << 0); - tmp110__ |= (pSrc->report.Beacon.reported_frame_type << 7); - *pBuf = tmp110__; + tmp112__ = 0U; + tmp112__ |= (pSrc->report.Beacon.condensed_PHY << 0); + tmp112__ |= (pSrc->report.Beacon.reported_frame_type << 7); + *pBuf = tmp112__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -16703,7 +16777,7 @@ uint32_t dot11f_pack_ie_measurement_request(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp111__; + uint8_t tmp113__; uint32_t status = DOT11F_PARSE_SUCCESS; status = dot11f_get_packed_ie_measurement_request(pCtx, pSrc, &nNeeded); if (!DOT11F_SUCCEEDED(status)) @@ -16718,14 +16792,14 @@ uint32_t dot11f_pack_ie_measurement_request(tpAniSirGlobal pCtx, *pBuf = pSrc->measurement_token; *pnConsumed += 1; pBuf += 1; - tmp111__ = 0U; - tmp111__ |= (pSrc->parallel << 0); - tmp111__ |= (pSrc->enable << 1); - tmp111__ |= (pSrc->request << 2); - tmp111__ |= (pSrc->report << 3); - tmp111__ |= (pSrc->durationMandatory << 4); - tmp111__ |= (pSrc->unused << 5); - *pBuf = tmp111__; + tmp113__ = 0U; + tmp113__ |= (pSrc->parallel << 0); + tmp113__ |= (pSrc->enable << 1); + tmp113__ |= (pSrc->request << 2); + tmp113__ |= (pSrc->report << 3); + tmp113__ |= (pSrc->durationMandatory << 4); + tmp113__ |= (pSrc->unused << 5); + *pBuf = tmp113__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -16812,7 +16886,7 @@ uint32_t dot11f_pack_ie_mobility_domain(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp112__; + uint8_t tmp114__; nNeeded += 3; while (pSrc->present) { if (nNeeded > nBuf) @@ -16824,11 +16898,11 @@ uint32_t dot11f_pack_ie_mobility_domain(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->MDID, 0); *pnConsumed += 2; pBuf += 2; - tmp112__ = 0U; - tmp112__ |= (pSrc->overDSCap << 0); - tmp112__ |= (pSrc->resourceReqCap << 1); - tmp112__ |= (pSrc->reserved << 2); - *pBuf = tmp112__; + tmp114__ = 0U; + tmp114__ |= (pSrc->overDSCap << 0); + tmp114__ |= (pSrc->resourceReqCap << 1); + tmp114__ |= (pSrc->reserved << 2); + *pBuf = tmp114__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -16850,8 +16924,8 @@ uint32_t dot11f_pack_ie_neighbor_report(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp113__; - uint8_t tmp114__; + uint8_t tmp115__; + uint8_t tmp116__; uint32_t status = DOT11F_PARSE_SUCCESS; status = dot11f_get_packed_ie_neighbor_report(pCtx, pSrc, &nNeeded); if (!DOT11F_SUCCEEDED(status)) @@ -16866,24 +16940,24 @@ uint32_t dot11f_pack_ie_neighbor_report(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pBuf, pSrc->bssid, 6); *pnConsumed += 6; pBuf += 6; - tmp113__ = 0U; - tmp113__ |= (pSrc->APReachability << 0); - tmp113__ |= (pSrc->Security << 2); - tmp113__ |= (pSrc->KeyScope << 3); - tmp113__ |= (pSrc->SpecMgmtCap << 4); - tmp113__ |= (pSrc->QosCap << 5); - tmp113__ |= (pSrc->apsd << 6); - tmp113__ |= (pSrc->rrm << 7); - *pBuf = tmp113__; + tmp115__ = 0U; + tmp115__ |= (pSrc->APReachability << 0); + tmp115__ |= (pSrc->Security << 2); + tmp115__ |= (pSrc->KeyScope << 3); + tmp115__ |= (pSrc->SpecMgmtCap << 4); + tmp115__ |= (pSrc->QosCap << 5); + tmp115__ |= (pSrc->apsd << 6); + tmp115__ |= (pSrc->rrm << 7); + *pBuf = tmp115__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp114__ = 0U; - tmp114__ |= (pSrc->DelayedBA << 0); - tmp114__ |= (pSrc->ImmBA << 1); - tmp114__ |= (pSrc->MobilityDomain << 2); - tmp114__ |= (pSrc->reserved << 3); - *pBuf = tmp114__; + tmp116__ = 0U; + tmp116__ |= (pSrc->DelayedBA << 0); + tmp116__ |= (pSrc->ImmBA << 1); + tmp116__ |= (pSrc->MobilityDomain << 2); + tmp116__ |= (pSrc->reserved << 3); + *pBuf = tmp116__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -16971,7 +17045,7 @@ uint32_t dot11f_pack_ie_operating_mode(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp115__; + uint8_t tmp117__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -16980,12 +17054,12 @@ uint32_t dot11f_pack_ie_operating_mode(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp115__ = 0U; - tmp115__ |= (pSrc->chanWidth << 0); - tmp115__ |= (pSrc->reserved << 2); - tmp115__ |= (pSrc->rxNSS << 4); - tmp115__ |= (pSrc->rxNSSType << 7); - *pBuf = tmp115__; + tmp117__ = 0U; + tmp117__ |= (pSrc->chanWidth << 0); + tmp117__ |= (pSrc->reserved << 2); + tmp117__ |= (pSrc->rxNSS << 4); + tmp117__ |= (pSrc->rxNSSType << 7); + *pBuf = tmp117__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -17460,7 +17534,7 @@ uint32_t dot11f_pack_ie_pu_buffer_status(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp116__; + uint8_t tmp118__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -17469,13 +17543,13 @@ uint32_t dot11f_pack_ie_pu_buffer_status(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp116__ = 0U; - tmp116__ |= (pSrc->ac_bk_traffic_aval << 0); - tmp116__ |= (pSrc->ac_be_traffic_aval << 1); - tmp116__ |= (pSrc->ac_vi_traffic_aval << 2); - tmp116__ |= (pSrc->ac_vo_traffic_aval << 3); - tmp116__ |= (pSrc->reserved << 4); - *pBuf = tmp116__; + tmp118__ = 0U; + tmp118__ |= (pSrc->ac_bk_traffic_aval << 0); + tmp118__ |= (pSrc->ac_be_traffic_aval << 1); + tmp118__ |= (pSrc->ac_vi_traffic_aval << 2); + tmp118__ |= (pSrc->ac_vo_traffic_aval << 3); + tmp118__ |= (pSrc->reserved << 4); + *pBuf = tmp118__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -17631,7 +17705,7 @@ uint32_t dot11f_pack_ie_qos_caps_ap(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp117__; + uint8_t tmp119__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -17640,13 +17714,13 @@ uint32_t dot11f_pack_ie_qos_caps_ap(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp117__ = 0U; - tmp117__ |= (pSrc->count << 0); - tmp117__ |= (pSrc->qack << 4); - tmp117__ |= (pSrc->qreq << 5); - tmp117__ |= (pSrc->txopreq << 6); - tmp117__ |= (pSrc->reserved << 7); - *pBuf = tmp117__; + tmp119__ = 0U; + tmp119__ |= (pSrc->count << 0); + tmp119__ |= (pSrc->qack << 4); + tmp119__ |= (pSrc->qreq << 5); + tmp119__ |= (pSrc->txopreq << 6); + tmp119__ |= (pSrc->reserved << 7); + *pBuf = tmp119__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -17668,7 +17742,7 @@ uint32_t dot11f_pack_ie_qos_caps_station(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp118__; + uint8_t tmp120__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -17677,15 +17751,15 @@ uint32_t dot11f_pack_ie_qos_caps_station(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp118__ = 0U; - tmp118__ |= (pSrc->acvo_uapsd << 0); - tmp118__ |= (pSrc->acvi_uapsd << 1); - tmp118__ |= (pSrc->acbk_uapsd << 2); - tmp118__ |= (pSrc->acbe_uapsd << 3); - tmp118__ |= (pSrc->qack << 4); - tmp118__ |= (pSrc->max_sp_length << 5); - tmp118__ |= (pSrc->more_data_ack << 7); - *pBuf = tmp118__; + tmp120__ = 0U; + tmp120__ |= (pSrc->acvo_uapsd << 0); + tmp120__ |= (pSrc->acvi_uapsd << 1); + tmp120__ |= (pSrc->acbk_uapsd << 2); + tmp120__ |= (pSrc->acbe_uapsd << 3); + tmp120__ |= (pSrc->qack << 4); + tmp120__ |= (pSrc->max_sp_length << 5); + tmp120__ |= (pSrc->more_data_ack << 7); + *pBuf = tmp120__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -18322,7 +18396,7 @@ uint32_t dot11f_pack_ie_wapi(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint16_t tmp119__; + uint16_t tmp121__; uint32_t status = DOT11F_PARSE_SUCCESS; status = dot11f_get_packed_iewapi(pCtx, pSrc, &nNeeded); if (!DOT11F_SUCCEEDED(status)) @@ -18352,10 +18426,10 @@ uint32_t dot11f_pack_ie_wapi(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pBuf, pSrc->multicast_cipher_suite, 4); *pnConsumed += 4; pBuf += 4; - tmp119__ = 0U; - tmp119__ |= (pSrc->preauth << 0); - tmp119__ |= (pSrc->reserved << 1); - frameshtons(pCtx, pBuf, tmp119__, 0); + tmp121__ = 0U; + tmp121__ |= (pSrc->preauth << 0); + tmp121__ |= (pSrc->reserved << 1); + frameshtons(pCtx, pBuf, tmp121__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -18495,7 +18569,7 @@ uint32_t dot11f_pack_ie_wmm_caps(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp120__; + uint8_t tmp122__; nNeeded += 2; while (pSrc->present) { if (nNeeded > nBuf) @@ -18517,13 +18591,13 @@ uint32_t dot11f_pack_ie_wmm_caps(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp120__ = 0U; - tmp120__ |= (pSrc->reserved << 0); - tmp120__ |= (pSrc->qack << 4); - tmp120__ |= (pSrc->queue_request << 5); - tmp120__ |= (pSrc->txop_request << 6); - tmp120__ |= (pSrc->more_ack << 7); - *pBuf = tmp120__; + tmp122__ = 0U; + tmp122__ |= (pSrc->reserved << 0); + tmp122__ |= (pSrc->qack << 4); + tmp122__ |= (pSrc->queue_request << 5); + tmp122__ |= (pSrc->txop_request << 6); + tmp122__ |= (pSrc->more_ack << 7); + *pBuf = tmp122__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -18545,7 +18619,7 @@ uint32_t dot11f_pack_ie_wmm_info_ap(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp121__; + uint8_t tmp123__; nNeeded += 2; while (pSrc->present) { if (nNeeded > nBuf) @@ -18567,11 +18641,11 @@ uint32_t dot11f_pack_ie_wmm_info_ap(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp121__ = 0U; - tmp121__ |= (pSrc->param_set_count << 0); - tmp121__ |= (pSrc->reserved << 4); - tmp121__ |= (pSrc->uapsd << 7); - *pBuf = tmp121__; + tmp123__ = 0U; + tmp123__ |= (pSrc->param_set_count << 0); + tmp123__ |= (pSrc->reserved << 4); + tmp123__ |= (pSrc->uapsd << 7); + *pBuf = tmp123__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -18593,7 +18667,7 @@ uint32_t dot11f_pack_ie_wmm_info_station(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp122__; + uint8_t tmp124__; nNeeded += 2; while (pSrc->present) { if (nNeeded > nBuf) @@ -18615,15 +18689,15 @@ uint32_t dot11f_pack_ie_wmm_info_station(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp122__ = 0U; - tmp122__ |= (pSrc->acvo_uapsd << 0); - tmp122__ |= (pSrc->acvi_uapsd << 1); - tmp122__ |= (pSrc->acbk_uapsd << 2); - tmp122__ |= (pSrc->acbe_uapsd << 3); - tmp122__ |= (pSrc->reserved1 << 4); - tmp122__ |= (pSrc->max_sp_length << 5); - tmp122__ |= (pSrc->reserved2 << 7); - *pBuf = tmp122__; + tmp124__ = 0U; + tmp124__ |= (pSrc->acvo_uapsd << 0); + tmp124__ |= (pSrc->acvi_uapsd << 1); + tmp124__ |= (pSrc->acbk_uapsd << 2); + tmp124__ |= (pSrc->acbe_uapsd << 3); + tmp124__ |= (pSrc->reserved1 << 4); + tmp124__ |= (pSrc->max_sp_length << 5); + tmp124__ |= (pSrc->reserved2 << 7); + *pBuf = tmp124__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -18645,14 +18719,14 @@ uint32_t dot11f_pack_ie_wmm_params(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp123__; - uint8_t tmp124__; uint8_t tmp125__; uint8_t tmp126__; uint8_t tmp127__; uint8_t tmp128__; uint8_t tmp129__; uint8_t tmp130__; + uint8_t tmp131__; + uint8_t tmp132__; nNeeded += 19; while (pSrc->present) { if (nNeeded > nBuf) @@ -18680,79 +18754,79 @@ uint32_t dot11f_pack_ie_wmm_params(tpAniSirGlobal pCtx, *pBuf = pSrc->reserved2; *pnConsumed += 1; pBuf += 1; - tmp123__ = 0U; - tmp123__ |= (pSrc->acbe_aifsn << 0); - tmp123__ |= (pSrc->acbe_acm << 4); - tmp123__ |= (pSrc->acbe_aci << 5); - tmp123__ |= (pSrc->unused1 << 7); - *pBuf = tmp123__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; - tmp124__ = 0U; - tmp124__ |= (pSrc->acbe_acwmin << 0); - tmp124__ |= (pSrc->acbe_acwmax << 4); - *pBuf = tmp124__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp125__ = 0U; - tmp125__ |= (pSrc->acbk_aifsn << 0); - tmp125__ |= (pSrc->acbk_acm << 4); - tmp125__ |= (pSrc->acbk_aci << 5); - tmp125__ |= (pSrc->unused2 << 7); + tmp125__ |= (pSrc->acbe_aifsn << 0); + tmp125__ |= (pSrc->acbe_acm << 4); + tmp125__ |= (pSrc->acbe_aci << 5); + tmp125__ |= (pSrc->unused1 << 7); *pBuf = tmp125__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp126__ = 0U; - tmp126__ |= (pSrc->acbk_acwmin << 0); - tmp126__ |= (pSrc->acbk_acwmax << 4); + tmp126__ |= (pSrc->acbe_acwmin << 0); + tmp126__ |= (pSrc->acbe_acwmax << 4); *pBuf = tmp126__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); *pnConsumed += 2; pBuf += 2; tmp127__ = 0U; - tmp127__ |= (pSrc->acvi_aifsn << 0); - tmp127__ |= (pSrc->acvi_acm << 4); - tmp127__ |= (pSrc->acvi_aci << 5); - tmp127__ |= (pSrc->unused3 << 7); + tmp127__ |= (pSrc->acbk_aifsn << 0); + tmp127__ |= (pSrc->acbk_acm << 4); + tmp127__ |= (pSrc->acbk_aci << 5); + tmp127__ |= (pSrc->unused2 << 7); *pBuf = tmp127__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp128__ = 0U; - tmp128__ |= (pSrc->acvi_acwmin << 0); - tmp128__ |= (pSrc->acvi_acwmax << 4); + tmp128__ |= (pSrc->acbk_acwmin << 0); + tmp128__ |= (pSrc->acbk_acwmax << 4); *pBuf = tmp128__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); *pnConsumed += 2; pBuf += 2; tmp129__ = 0U; - tmp129__ |= (pSrc->acvo_aifsn << 0); - tmp129__ |= (pSrc->acvo_acm << 4); - tmp129__ |= (pSrc->acvo_aci << 5); - tmp129__ |= (pSrc->unused4 << 7); + tmp129__ |= (pSrc->acvi_aifsn << 0); + tmp129__ |= (pSrc->acvi_acm << 4); + tmp129__ |= (pSrc->acvi_aci << 5); + tmp129__ |= (pSrc->unused3 << 7); *pBuf = tmp129__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp130__ = 0U; - tmp130__ |= (pSrc->acvo_acwmin << 0); - tmp130__ |= (pSrc->acvo_acwmax << 4); + tmp130__ |= (pSrc->acvi_acwmin << 0); + tmp130__ |= (pSrc->acvi_acwmax << 4); *pBuf = tmp130__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; + tmp131__ = 0U; + tmp131__ |= (pSrc->acvo_aifsn << 0); + tmp131__ |= (pSrc->acvo_acm << 4); + tmp131__ |= (pSrc->acvo_aci << 5); + tmp131__ |= (pSrc->unused4 << 7); + *pBuf = tmp131__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp132__ = 0U; + tmp132__ |= (pSrc->acvo_acwmin << 0); + tmp132__ |= (pSrc->acvo_acwmax << 4); + *pBuf = tmp132__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); *pnConsumed += 2; /* fieldsEndFlag = 1 */ @@ -19344,7 +19418,7 @@ uint32_t dot11f_pack_ie_ht2040_bss_coexistence(tpAniSirGlobal pCtx, uint8_t *pIeLen = 0; uint32_t nConsumedOnEntry = *pnConsumed; uint32_t nNeeded = 0U; - uint8_t tmp131__; + uint8_t tmp133__; nNeeded += 1; while (pSrc->present) { if (nNeeded > nBuf) @@ -19353,14 +19427,14 @@ uint32_t dot11f_pack_ie_ht2040_bss_coexistence(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp131__ = 0U; - tmp131__ |= (pSrc->info_request << 0); - tmp131__ |= (pSrc->forty_mhz_intolerant << 1); - tmp131__ |= (pSrc->twenty_mhz_bsswidth_req << 2); - tmp131__ |= (pSrc->obss_scan_exemption_req << 3); - tmp131__ |= (pSrc->obss_scan_exemption_grant << 4); - tmp131__ |= (pSrc->unused << 5); - *pBuf = tmp131__; + tmp133__ = 0U; + tmp133__ |= (pSrc->info_request << 0); + tmp133__ |= (pSrc->forty_mhz_intolerant << 1); + tmp133__ |= (pSrc->twenty_mhz_bsswidth_req << 2); + tmp133__ |= (pSrc->obss_scan_exemption_req << 3); + tmp133__ |= (pSrc->obss_scan_exemption_grant << 4); + tmp133__ |= (pSrc->unused << 5); + *pBuf = tmp133__; *pnConsumed += 1; /* fieldsEndFlag = 1 */ nBuf -= 1 ; @@ -20157,6 +20231,21 @@ uint32_t dot11f_pack_wmm_del_ts(tpAniSirGlobal pCtx, } /* End dot11f_unpack_wmm_del_ts. */ +uint32_t dot11f_pack_ext_channel_switch_action_frame(tpAniSirGlobal pCtx, + tDot11fext_channel_switch_action_frame *pFrm, + uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) +{ + uint32_t i = 0; + uint32_t status = 0; + (void)i; + *pnConsumed = 0U; + status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed, + FFS_ext_channel_switch_action_frame, IES_ext_channel_switch_action_frame); + + return status; + +} /* End dot11f_unpack_ext_channel_switch_action_frame. */ + uint32_t dot11f_pack_ht2040_bss_coexistence_mgmt_action_frame(tpAniSirGlobal pCtx, tDot11fht2040_bss_coexistence_mgmt_action_frame *pFrm, uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed) @@ -20357,6 +20446,11 @@ static uint32_t pack_core(tpAniSirGlobal pCtx, pCtx, (tDot11fFfVhtUserPositionArray *) (pSrc + pFf->offset), pBufRemaining); break; + case SigFfext_chan_switch_ann_action: + dot11f_pack_ff_ext_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" diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index dc450e22abe8..50a42391ee24 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -187,6 +187,7 @@ typedef enum { eSAP_ACS_SCAN_SUCCESS_EVENT, #endif eSAP_ACS_CHANNEL_SELECTED, + eSAP_ECSA_CHANGE_CHAN_IND, } eSapHddEvent; typedef enum { @@ -407,6 +408,15 @@ struct sap_ch_selected_s { struct sap_roc_ready_ind_s { uint32_t scan_id; }; + +/** + * 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_start_bss call The event id corresponding to @@ -450,7 +460,7 @@ typedef struct sap_Event_s { tSap_DfsNolInfo sapDfsNolInfo; struct sap_ch_selected_s sap_ch_selected; struct sap_roc_ready_ind_s sap_roc_ind; - + struct sap_ch_change_ind sap_chan_cng_ind; } sapevt; } tSap_Event, *tpSap_Event; diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index 4ea65dcec7ed..381f444d640b 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -974,6 +974,10 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, FL("Received set channel response")); break; + case eCSR_ROAM_EXT_CHG_CHNL_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + FL("Received set channel Indication")); + break; default: CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, FL("CSR roam_status not handled roam_status = %s (%d)\n"), @@ -1198,6 +1202,12 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, sap_ctx->sapsMachine = eSAP_DISCONNECTED; /* Inform cfg80211 and hostapd that BSS is not alive anymore */ break; + case eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND: + cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info, + eSAP_ECSA_CHANGE_CHAN_IND, NULL); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + cdf_ret_status = CDF_STATUS_E_FAILURE; + break; default: CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, FL("CSR roam_result = %s (%d) not handled\n"), diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 3d2021e6de66..1ca439e69cda 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2814,7 +2814,14 @@ CDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx, sap_ap_event.sapevt.sapDfsNolInfo.pDfsList = (void *) (&mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList[0]); break; - + case eSAP_ECSA_CHANGE_CHAN_IND: + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "In %s, SAP event callback event = %s", + __func__, "eSAP_ECSA_CHANGE_CHAN_IND"); + sap_ap_event.sapHddEventCode = eSAP_ECSA_CHANGE_CHAN_IND; + sap_ap_event.sapevt.sap_chan_cng_ind.new_chan = + csr_roaminfo->target_channel; + break; default: CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, FL("SAP Unknown callback event = %d"), diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index b2df4dc49de9..b54f6563e4e0 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -2179,7 +2179,7 @@ CDF_STATUS wlansap_de_register_mgmt_frame SIDE EFFECTS ============================================================================*/ CDF_STATUS -wlansap_channel_change_request(void *pSapCtx, uint8_t targetChannel) +wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel) { ptSapContext sapContext = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; @@ -2205,7 +2205,7 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t targetChannel) } mac_ctx = PMAC_STRUCT(hHal); phy_mode = sapContext->csr_roamProfile.phyMode; - sapContext->csr_roamProfile.ChannelInfo.ChannelList[0] = targetChannel; + sapContext->csr_roamProfile.ChannelInfo.ChannelList[0] = target_channel; /* * We are getting channel bonding mode from sapDfsInfor structure * because we've implemented channel width fallback mechanism for DFS @@ -2214,8 +2214,12 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t targetChannel) cb_mode = mac_ctx->sap.SapDfsInfo.new_cbMode; vht_channel_width = mac_ctx->sap.SapDfsInfo.new_chanWidth; ch_params.ch_width = vht_channel_width; - sme_set_ch_params(hHal, phy_mode, targetChannel, 0, &ch_params); + sme_set_ch_params(hHal, phy_mode, target_channel, 0, &ch_params); sapContext->ch_params.ch_width = vht_channel_width; + /* Update the channel as this will be used to + * send event to supplicant + */ + sapContext->channel = target_channel; sapContext->csr_roamProfile.ch_params.ch_width = vht_channel_width; cdf_ret_status = sme_roam_channel_change_req(hHal, sapContext->bssid, cb_mode, &sapContext->csr_roamProfile); diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 365401784c6f..88dead78f1ce 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -528,6 +528,7 @@ typedef enum { /* Channel sw update notification */ eCSR_ROAM_DFS_CHAN_SW_NOTIFY, + eCSR_ROAM_EXT_CHG_CHNL_IND, } eRoamCmdStatus; /* comment inside indicates what roaming callback gets */ @@ -636,6 +637,7 @@ typedef enum { 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; /*---------------------------------------------------------------------------- @@ -1374,6 +1376,7 @@ typedef struct tagCsrRoamInfo { uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; #endif tSirSmeChanInfo chan_info; + uint8_t target_channel; } tCsrRoamInfo; typedef struct tagCsrFreqScanInfo { @@ -1400,6 +1403,7 @@ typedef struct sSirSmeAssocIndToUpperLayerCnf { /* Timing and fine Timing measurement capability clubbed together */ uint8_t timingMeasCap; tSirSmeChanInfo chan_info; + uint8_t target_channel; } tSirSmeAssocIndToUpperLayerCnf, *tpSirSmeAssocIndToUpperLayerCnf; typedef struct tagCsrSummaryStatsInfo { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index c8e1e361e4e1..b931dc43f43d 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -946,6 +946,8 @@ CDF_STATUS sme_set_led_flashing(tHalHandle hHal, uint8_t type, CDF_STATUS sme_handle_dfs_chan_scan(tHalHandle hHal, uint8_t dfs_flag); CDF_STATUS sme_set_mas(uint32_t val); CDF_STATUS sme_set_miracast(tHalHandle hal, uint8_t filter_type); +CDF_STATUS sme_ext_change_channel(tHalHandle hHal, uint32_t channel, + uint8_t session_id); CDF_STATUS sme_configure_modulated_dtim(tHalHandle hal, uint8_t session_id, uint32_t modulated_dtim); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index ac42abd8e347..4bfb7d992d3f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1919,6 +1919,48 @@ CDF_STATUS dfs_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, void *pMsgBu 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 CDF_STATUS sme_extended_change_channel_ind(tpAniSirGlobal mac_ctx, + void *msg_buf) +{ + struct sir_sme_ext_cng_chan_ind *ext_chan_ind; + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint32_t session_id = 0; + tCsrRoamInfo roamInfo = {0}; + eRoamCmdStatus roam_status; + eCsrRoamResult roam_result; + + + ext_chan_ind = msg_buf; + if (NULL == ext_chan_ind) { + sms_log(mac_ctx, LOGE, + FL("pMsg is NULL for eWNI_SME_EXT_CHANGE_CHANNEL_IND")); + return CDF_STATUS_E_FAILURE; + } + session_id = ext_chan_ind->session_id; + roamInfo.target_channel = ext_chan_ind->new_channel; + roam_status = eCSR_ROAM_EXT_CHG_CHNL_IND; + roam_result = eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND; + sms_log(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 */ + csr_roam_call_callback(mac_ctx, session_id, &roamInfo, 0, + roam_status, roam_result); + return status; +} + #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) /*------------------------------------------------------------------ * @@ -2681,6 +2723,10 @@ CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) pMac->sme.set_thermal_level_cb(pMac->hHdd, pMsg->bodyval); break; + case eWNI_SME_EXT_CHANGE_CHANNEL_IND: + status = sme_extended_change_channel_ind(pMac, pMsg->bodyptr); + cdf_mem_free(pMsg->bodyptr); + break; default: if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) @@ -8078,6 +8124,45 @@ CDF_STATUS sme_update_roam_scan_home_away_time(tHalHandle hHal, 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 + */ +CDF_STATUS sme_ext_change_channel(tHalHandle h_hal, uint32_t channel, + uint8_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal); + uint8_t channel_state; + + sms_log(mac_ctx, LOGE, FL(" Set Channel %d "), channel); + channel_state = + cds_get_channel_state(channel); + + if (CHANNEL_STATE_DISABLE == channel_state) { + sms_log(mac_ctx, LOGE, FL(" Invalid channel %d "), channel); + return CDF_STATUS_E_INVAL; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + + if (CDF_STATUS_SUCCESS == status) { + /* update the channel list to the firmware */ + status = csr_send_ext_change_channel(mac_ctx, + channel, session_id); + sme_release_global_lock(&mac_ctx->sme); + } + + return status; +} + /* --------------------------------------------------------------------------- \fn sme_get_roam_intra_band \brief get Intra band roaming diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 22df06520af6..d860d6f1c870 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18344,6 +18344,36 @@ csr_roam_update_add_ies(tpAniSirGlobal pMac, 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 + */ +CDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t channel, + uint8_t session_id) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + struct sir_sme_ext_cng_chan_req *msg; + + msg = cdf_mem_malloc(sizeof(*msg)); + if (NULL == msg) + return CDF_STATUS_E_NOMEM; + + cdf_mem_zero(msg, sizeof(*msg)); + msg->message_type = eWNI_SME_EXT_CHANGE_CHANNEL; + msg->length = sizeof(*msg); + msg->new_channel = channel; + msg->session_id = session_id; + status = cds_send_mb_message_to_mac(msg); + return status; +} + /** * csr_roam_send_chan_sw_ie_request() - Request to transmit CSA IE * @mac_ctx: Global MAC context diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 0c7fef801057..0f21bec8a2b7 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1056,6 +1056,8 @@ void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode); void csr_clear_votes_for_country_info(tpAniSirGlobal pMac); #endif +CDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, + uint32_t channel, uint8_t session_id); #ifdef QCA_HT_2040_COEX CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, -- cgit v1.2.3 From 2a8a65d91964b58b176ae3fbd549dee784aefa77 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 16 Oct 2015 16:24:19 +0530 Subject: qcacld-3.0: Implement ECSA Action Frame qcacld-2.0 to qcacld-3.0 propagation Implement: 1. Send & receive logic of ECSA action frame from P2P-CLI/GO 2. Trigger channel change on P2P GO side once ECSA action frame is received by, i) Adding CSA & ESCA IE in beacon template and updating FW to send it out . ii) Notifying supplicant of channel change for P2P GO. This change include HDD changes CRs-fixed: 895240 Change-Id: Iea66ddbbb8946443d5e701e3c14b2f33c6bb6bf8 --- core/hdd/src/wlan_hdd_cfg80211.c | 92 ++++++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 5 +++ core/hdd/src/wlan_hdd_hostapd.c | 17 ++++++-- core/hdd/src/wlan_hdd_hostapd.h | 3 ++ core/hdd/src/wlan_hdd_wext.c | 31 ++++++++++++++ 5 files changed, 144 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3ae8264033e6..880fee967b5b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -624,6 +624,27 @@ static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { #define PARAM_TDLS_FEATURE_SUPPORT \ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED +/** + * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported + * @flags: Pointer to the flags to Add channel switch flag. + * + * This Function adds Channel Switch support flag, if channel switch is + * supported by kernel. + * Return: void. + */ +#ifdef CHANNEL_SWITCH_SUPPORTED +static inline void hdd_add_channel_switch_support(uint32_t *flags) +{ + flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + return; +} +#else +static inline void hdd_add_channel_switch_support(uint32_t *flags) +{ + return; +} +#endif + /** * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites. * @wiphy: WIPHY structure pointer @@ -4956,6 +4977,8 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; #endif + hdd_add_channel_switch_support(&wiphy->flags); + EXIT(); return 0; } @@ -10551,6 +10574,72 @@ wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy, } #endif +#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; + uint8_t channel; + uint16_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 = cds_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; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params); + cds_ssr_unprotect(__func__); + return ret; +} +#endif + /** * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type * translation from NL to policy manager type @@ -10708,4 +10797,7 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .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/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 23e604a56c77..28fc309011fd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -101,6 +101,11 @@ #define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) #define MAX_SCAN_SSID 10 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) \ + || defined(BACKPORTED_CHANNEL_SWITCH_PRESENT) +#define CHANNEL_SWITCH_SUPPORTED +#endif + /** * typedef struct qcom_ie_age - age ie * diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index ed0119529662..17859ba9f50f 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1693,6 +1693,16 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, if (!pHddCtx->config->force_sap_acs) wlan_hdd_cfg80211_acs_ch_select_evt(pHostapdAdapter); return CDF_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 CDF_STATUS_E_FAILURE; + else + return CDF_STATUS_SUCCESS; + default: hddLog(LOG1, "SAP message is not handled"); goto stopbss; @@ -1883,7 +1893,6 @@ int hdd_softap_unpack_ie(tHalHandle halHandle, * * Return: 0 for success, non zero for failure */ -static int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) { CDF_STATUS status; @@ -1900,7 +1909,6 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) ret = wlan_hdd_validate_context(pHddCtx); if (ret) { hddLog(LOGE, FL("invalid HDD context")); - ret = -EBUSY; return ret; } @@ -2251,9 +2259,10 @@ static __iw_softap_setparam(struct net_device *dev, break; case QCSAP_PARAM_SET_CHANNEL_CHANGE: - if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { + if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) { hddLog(LOG1, - "SET SAP Channel Change to new channel= %d", + "SET Channel Change to new channel= %d", set_value); ret = hdd_softap_set_channel_change(dev, set_value); } else { diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h index 02965d8457f7..f4f72c82d658 100644 --- a/core/hdd/src/wlan_hdd_hostapd.h +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -57,6 +57,9 @@ CDF_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held); eCsrAuthType hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]); +int hdd_softap_set_channel_change(struct net_device *dev, + int target_channel); + eCsrEncryptionType hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 047131f20456..bd22dcb139f8 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -215,6 +215,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_CLEAR_STATS 86 /* Private sub ioctl for starting/stopping the profiling */ #define WE_START_FW_PROFILE 87 +#define WE_SET_CHANNEL 88 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -4938,6 +4939,7 @@ static int __iw_setint_getnone(struct net_device *dev, int set_value = value[1]; int ret; int enable_pbm, enable_mp; + CDF_STATUS status; INIT_COMPLETION(pWextState->completion_var); memset(&smeConfig, 0x00, sizeof(smeConfig)); @@ -6122,6 +6124,31 @@ static int __iw_setint_getnone(struct net_device *dev, set_value, DBG_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(hHal, + set_value, pAdapter->sessionId); + if (status != CDF_STATUS_SUCCESS) { + hddLog(LOGE, + FL("Error in change channel status %d"), + status); + ret = -EINVAL; + } + } else { + hddLog(LOGE, + FL("change channel not supported for device mode %d"), + pAdapter->device_mode); + ret = -EINVAL; + } + break; + } + default: { hddLog(LOGE, "%s: Invalid sub command %d", __func__, @@ -10065,6 +10092,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "startProfile"}, + {WE_SET_CHANNEL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setChanChange" }, + {WLAN_PRIV_SET_NONE_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, -- cgit v1.2.3 From d844bd8733687eee6fc13295b3f3c2856ef5de09 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Fri, 23 Oct 2015 14:03:14 +0530 Subject: qcacld-3.0: prevent double free of ft pre auth response Propagation qcacld-2.0 to qcacld-3.0 while processing ft pre auth response, if memory allocation fails then host is not setting psavedFTPreAuthRsp to null. Later sme is freeing same memory as freeing pMsg->bodyptr. Hence on next disconnect, sme_FtReset try to free psavedFTPreAuthRsp which is already free. As a part of this fix, host ensure to set psavedFTPreAuthRsp Null in all cases. Change-Id: I144786cd4206bf273d2ffa63889af109cd2744dd CRs-Fixed: 916416 --- core/sme/src/csr/csr_api_roam.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index d860d6f1c870..a05739f94842 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17959,6 +17959,10 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, pMac->roam.roamSession[sessionId].connectedProfile.AuthType; pSession->ftSmeContext.addMDIE = false; + + /* Done with it, init it. */ + pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; + if (csr_roam_is11r_assoc(pMac, pFTPreAuthRsp->smeSessionId) && (conn_Auth_type == eCSR_AUTH_TYPE_OPEN_SYSTEM)) { uint16_t ft_ies_length; @@ -17991,8 +17995,6 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, pSession->ftSmeContext.addMDIE = true; } } - /* Done with it, init it. */ - pSession->ftSmeContext.psavedFTPreAuthRsp = NULL; } #endif -- cgit v1.2.3 From 6cd54a3db6947917cff397b69d122bf529141eb2 Mon Sep 17 00:00:00 2001 From: Karthick S Date: Wed, 14 Oct 2015 18:39:56 +0530 Subject: qcacld-3.0: set proc_dir to NULL qcacld-2.0 to qcacld-3.0 propagation In athdiag_procfs_remove, set proc_dir to NULL after removing the directory. This is to avoid trying to remove the directory which is already removed. Change-Id: I01526f4b59ccc991d157c1028d4df5904338f182 CRs-Fixed: 868965 --- core/hif/src/ath_procfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/hif/src/ath_procfs.c b/core/hif/src/ath_procfs.c index 48b3021e146b..941d2e598981 100644 --- a/core/hif/src/ath_procfs.c +++ b/core/hif/src/ath_procfs.c @@ -187,10 +187,13 @@ int athdiag_procfs_init(void *scn) */ void athdiag_procfs_remove(void) { - remove_proc_entry(PROCFS_NAME, proc_dir); - HIF_DBG("/proc/%s/%s removed", PROCFS_DIR, PROCFS_NAME); - remove_proc_entry(PROCFS_DIR, NULL); - HIF_DBG("/proc/%s removed", PROCFS_DIR); + if (proc_dir != NULL) { + remove_proc_entry(PROCFS_NAME, proc_dir); + HIF_DBG("/proc/%s/%s removed", PROCFS_DIR, PROCFS_NAME); + remove_proc_entry(PROCFS_DIR, NULL); + HIF_DBG("/proc/%s removed", PROCFS_DIR); + proc_dir = NULL; + } } #else int athdiag_procfs_init(void *scn) -- cgit v1.2.3 From dc40a35fec0812e4945fc3fc33407648aa413560 Mon Sep 17 00:00:00 2001 From: Karthick S Date: Wed, 14 Oct 2015 18:14:15 +0530 Subject: qcacld-3.0: Add NULL sanity check for HTC_HANDLE qcacld-2.0 to qcacld-3.0 propagation System crash happened due to accessing NULL pointer in HTCSendPkt. so added null sanity check to prevent this scenario. Change-Id: I4c07840eb176847c4a66efc42cd810213e1369b0 CRs-Fixed: 838998 --- core/htc/htc_send.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index 48d55709c1f3..bb0ff387837d 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -1221,6 +1221,10 @@ A_STATUS htc_send_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) { HTC_PACKET_QUEUE queue; + if (HTCHandle == NULL || pPacket == NULL) { + return A_ERROR; + } + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+-htc_send_pkt: Enter endPointId: %d, buffer: %p, length: %d \n", pPacket->Endpoint, pPacket->pBuffer, -- cgit v1.2.3 From d86f09fcf8e51eb41695a9c71995b2ee13cfb82e Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Mon, 26 Oct 2015 12:54:44 +0530 Subject: qcacld-3.0: Avoid SSR injection when driver load is in progress Propagation qcacld-2.0 to qcacld-3.0 Host avoid SSR injection ioctl using hdd->isLoadInProgress, But ol_target_failure handler checks for the cds_set_load_unload_in_progress. As these two flags are not set back to back so there is possible time window in which SSR ioctl is allowed but ol target failure handling is not allowed. Change-Id: Ib97d3693f82f6ca94fa048a8120786065e99087a CRs-Fixed: 913741 --- core/hdd/src/wlan_hdd_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 669943275857..0a81fc36d9de 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5265,8 +5265,6 @@ ftm_processing: mutex_init(&hdd_ctx->sap_lock); - hdd_ctx->isLoadInProgress = false; - #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) if (rtnl_lock_enable == true) { rtnl_lock_enable = false; @@ -5289,8 +5287,6 @@ ftm_processing: hdd_hostapd_channel_wakelock_init(hdd_ctx); - cds_set_load_unload_in_progress(false); - hdd_set_idle_ps_config(hdd_ctx, true); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN if (hdd_ctx->config->WlanAutoShutdown != 0) @@ -5435,7 +5431,8 @@ ftm_processing: } hif_enable_power_gating(hif_sc); - + hdd_ctx->isLoadInProgress = false; + cds_set_load_unload_in_progress(false); complete(&wlan_start_comp); goto success; -- cgit v1.2.3 From c3a7a0c1c16f5bc34fccccfa3f09914c93726c20 Mon Sep 17 00:00:00 2001 From: Karthick S Date: Wed, 14 Oct 2015 17:56:55 +0530 Subject: qcacld-3.0: Stop HIF service before HTC cleanup HIFStart is called from HTCWaitTarget in the vos_open function. If vos_open fails later, the HIFStop is not called to cleanup what is done in the HIFStart. This change fixes this issue. qcacld-2.0 to qcacld-3.0 propagation Git-commit:98808985fb6037c6f33af396aae38224f91c8b4d Change-Id: Id30f41d953e4582db57a98fff14e3f68447239f1 CRs-Fixed: 831608 --- core/htc/htc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/htc/htc.c b/core/htc/htc.c index 607e825e0b31..967c7c24d028 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -277,6 +277,7 @@ void htc_destroy(HTC_HANDLE HTCHandle) HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_destroy .. Destroying :0x%p\n", target)); + hif_stop(htc_get_hif_device(HTCHandle)); if (target) htc_cleanup(target); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n")); -- cgit v1.2.3 From 2cd8292741a5cd874c7f3bc71e5147d0d5285e9a Mon Sep 17 00:00:00 2001 From: Karthick S Date: Wed, 14 Oct 2015 16:12:48 +0530 Subject: qcacld-3.0: Free protection_fields_reset_timer qcacld-2.0 to qcacld-3.0 propagation Free protection_fields_reset_timer in the beginning of peDeleteSession function to avoid the null defreference caused due to the race condition between peDeleteSession and pe_reset_protection_callback. Change-Id: I1b83977bb3683d6dd87ec94a992ac51f39cd97db CRs-Fixed: 815796 --- core/mac/src/pe/lim/lim_session.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 6c73b4ce2b2f..d6914543e697 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -539,6 +539,11 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) tx_timer_deactivate(timer_ptr); } + if (LIM_IS_AP_ROLE(session)) { + cdf_mc_timer_stop(&session->protection_fields_reset_timer); + cdf_mc_timer_destroy(&session->protection_fields_reset_timer); + } + #if defined (WLAN_FEATURE_VOWIFI_11R) /* Delete FT related information */ lim_ft_cleanup(mac_ctx, session); @@ -664,12 +669,6 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) if (session->limRmfEnabled) cdf_mc_timer_destroy(&session->pmfComebackTimer); #endif - - if (LIM_IS_AP_ROLE(session)) { - cdf_mc_timer_stop(&session->protection_fields_reset_timer); - cdf_mc_timer_destroy(&session->protection_fields_reset_timer); - } - session->valid = false; if (LIM_IS_AP_ROLE(session)) -- cgit v1.2.3 From 52fd87a38d0709aeafa01e921a6ed70ae7b11864 Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Mon, 19 Oct 2015 19:16:19 +0530 Subject: qcacld-3.0: Fix static code analysis errors Propagation from qcacld-2.0 to qcacld-3.0 Updated the wma, pe module to address the issues reported by static code analysis. Change-Id: I8666adf161225014108c189cbcffced9450ae0c4 CRs-Fixed: 889019 --- core/wma/src/wma_mgmt.c | 5 ++++- core/wma/src/wma_ocb.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 4ba24036b7a5..10011aa2f2f3 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1995,7 +1995,10 @@ CDF_STATUS wma_process_update_edca_param_req(WMA_HANDLE handle, goto fail; pdev = cds_get_context(CDF_MODULE_ID_TXRX); - ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param); + if (pdev) + ol_txrx_set_wmm_param(pdev, ol_tx_wmm_param); + else + CDF_ASSERT(0); return CDF_STATUS_SUCCESS; diff --git a/core/wma/src/wma_ocb.c b/core/wma/src/wma_ocb.c index 15d321202aab..1fde2f276829 100644 --- a/core/wma/src/wma_ocb.c +++ b/core/wma/src/wma_ocb.c @@ -64,6 +64,8 @@ int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status) req->channel_count; vdev->ocb_channel_info = cdf_mem_malloc(buf_size); + if (!vdev->ocb_channel_info) + return -ENOMEM; cdf_mem_zero(vdev->ocb_channel_info, buf_size); for (i = 0; i < req->channel_count; i++) { vdev->ocb_channel_info[i].chan_freq = -- cgit v1.2.3 From 8511851272c5d7decd1e9fc8c4b5da30b0d62ec9 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 14:17:11 -0700 Subject: qcacld-3.0: Bypass hif_completion_thread in send We want to process the completions in parallel. Upper layer should take care of its own thread safety. hif_completion_thread is a legacy function that does in context serialization of hif completions. Bypass it. Change-Id: I19660327ebb4a3cbb9908ce562ab6c72a6282e95 CRs-Fixed: 941358 --- core/hif/src/ce/ce_main.c | 78 +++++++---------------------------------------- 1 file changed, 11 insertions(+), 67 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 4c0a162f4da9..68ce9345f6b6 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -692,87 +692,31 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, 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; unsigned int sw_idx = sw_index, hw_idx = hw_index; + struct hif_msg_callbacks *msg_callbacks = + &hif_state->msg_callbacks_current; - 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. + * The upper layer callback will be triggered + * when last fragment is complteted. */ - if (transfer_context == CE_SENDLIST_ITEM_CTXT) { - cdf_spin_lock(&pipe_info->completion_freeq_lock); - pipe_info->num_sends_allowed++; - cdf_spin_unlock(&pipe_info->completion_freeq_lock); - continue; + if (transfer_context != CE_SENDLIST_ITEM_CTXT) { + + msg_callbacks->txCompletionHandler( + msg_callbacks->Context, + transfer_context, transfer_id, + toeplitz_hash_result); } cdf_spin_lock(&pipe_info->completion_freeq_lock); - compl_state = pipe_info->completion_freeq_head; - if (!compl_state) { - cdf_spin_unlock(&pipe_info->completion_freeq_lock); - HIF_ERROR("%s: ce_id:%d num_allowed:%d pipe_info:%p", - __func__, pipe_info->pipe_num, - pipe_info->num_sends_allowed, - pipe_info); - ASSERT(0); - break; - } - pipe_info->completion_freeq_head = compl_state->next; + pipe_info->num_sends_allowed++; cdf_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; - compl_state->toeplitz_hash_result = toeplitz_hash_result; - - /* 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, &toeplitz_hash_result) == CDF_STATUS_SUCCESS); - - 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; - } - - cdf_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; - cdf_spin_unlock(&hif_state->completion_pendingq_lock); - } else { - hif_state->completion_pendingq_head = compl_queue_head; - hif_state->completion_pendingq_tail = compl_queue_tail; - cdf_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. */ -- cgit v1.2.3 From 0dad509ed3f2302773074d23fcdd48a19154f651 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 16:25:51 -0700 Subject: qcacld-3.0: Bypass hif_completion_thread in fw event We want to process the completions in parallel. Upper layer should take care of its own thread safety. hif_completion_thread is a legacy function that does in context serialization of hif completions. Bypass it. Change-Id: I73b8518d87645d827814cd1345eb68370de30d1f CRs-Fixed: 941358 --- core/hif/src/hif_main.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 7dbc3698fea4..ea96078ab331 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -194,6 +194,19 @@ bool hif_target_forced_awake(struct ol_softc *scn) return awake && forced_awake; } + +static inline void hif_fw_event_handler(struct HIF_CE_state *hif_state) +{ + struct hif_msg_callbacks *msg_callbacks = + &hif_state->msg_callbacks_current; + + if (!msg_callbacks->fwEventHandler) + return; + + msg_callbacks->fwEventHandler(msg_callbacks->Context, + CDF_STATUS_E_FAILURE); +} + /** * hif_fw_interrupt_handler(): FW interrupt handler * @@ -224,9 +237,7 @@ irqreturn_t hif_fw_interrupt_handler(int irq, void *arg) A_TARGET_ACCESS_END_RET(scn); if (hif_state->started) { - /* Alert the Host-side service thread */ - atomic_set(&hif_state->fw_event_pending, 1); - hif_completion_thread(hif_state); + hif_fw_event_handler(hif_state); } else { /* * Probable Target failure before we're prepared -- cgit v1.2.3 From 9a863a45193ad10f4ed658db92859aa91e7ad5e6 Mon Sep 17 00:00:00 2001 From: Xun Luo Date: Tue, 10 Nov 2015 08:24:45 -0800 Subject: qcacld-3.0: clear WMI work queue before bus context destruction qcacld-2.0 to qcacld-3.0 propagation All WMI work queue should be cleared and processing stopped before bus context destruction. This change enforces this rule. Change-Id: I2e12f3f08424f718ec66fe257060ce13de17ee4e CRs-Fixed: 840422 --- core/cds/src/cds_api.c | 14 ++++++++++++++ core/wma/inc/wma_api.h | 2 ++ core/wma/src/wma_main.c | 36 ++++++++++++++++++++++++++++++++++++ core/wmi/wmi_unified.c | 30 ++++++++++++++++++++++++++++++ core/wmi/wmi_unified_api.h | 3 +++ 5 files changed, 85 insertions(+) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index b5af587fd75e..6a3d0391ea6f 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -827,6 +827,13 @@ CDF_STATUS cds_close(v_CONTEXT_t cds_context) { CDF_STATUS cdf_status; + cdf_status = wma_wmi_work_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work", __func__); + CDF_ASSERT(0); + } + if (gp_cds_context->htc_ctx) { htc_stop(gp_cds_context->htc_ctx); htc_destroy(gp_cds_context->htc_ctx); @@ -1534,6 +1541,13 @@ CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context) } } + cdf_status = wma_wmi_work_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work!", __func__); + CDF_ASSERT(0); + } + if (gp_cds_context->htc_ctx) { htc_stop(gp_cds_context->htc_ctx); htc_destroy(gp_cds_context->htc_ctx); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index ad78989f38ea..0e9b5f5bc559 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -90,6 +90,8 @@ CDF_STATUS wma_close(void *cds_context); CDF_STATUS wma_wmi_service_close(void *cds_context); +CDF_STATUS wma_wmi_work_close(void *cds_context); + void wma_rx_ready_event(WMA_HANDLE handle, void *ev); void wma_rx_service_ready_event(WMA_HANDLE handle, void *ev); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index e9c6bd96bc47..9f4c36117018 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2929,6 +2929,42 @@ CDF_STATUS wma_wmi_service_close(void *cds_ctx) return CDF_STATUS_SUCCESS; } +/** + * wma_wmi_work_close() - close the work queue items associated with WMI + * @cds_ctx: Pointer to cds context + * + * This function closes work queue items associated with WMI, but not fully + * closes WMI service. + * + * Return: CDF_STATUS_SUCCESS if work close is successful. Otherwise + * proper error codes. + */ +CDF_STATUS wma_wmi_work_close(void *cds_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* remove the wmi work */ + WMA_LOGD("calling wmi_unified_remove_work"); + wmi_unified_remove_work(wma_handle->wmi_handle); + + return CDF_STATUS_SUCCESS; +} /** diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 52a3ea5fedaa..c534fe508dd6 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -1128,6 +1128,36 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle) } } +/** + * 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: None + */ +void +wmi_unified_remove_work(struct wmi_unified *wmi_handle) +{ + wmi_buf_t buf; + + CDF_TRACE(CDF_MODULE_ID_WMI, CDF_TRACE_LEVEL_INFO, + "Enter: %s", __func__); + cds_flush_work(&wmi_handle->rx_event_work); + cdf_spin_lock_bh(&wmi_handle->eventq_lock); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + while (buf) { + cdf_nbuf_free(buf); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + } + cdf_spin_unlock_bh(&wmi_handle->eventq_lock); + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_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; diff --git a/core/wmi/wmi_unified_api.h b/core/wmi/wmi_unified_api.h index 5fc132206699..bcac971aa79e 100644 --- a/core/wmi/wmi_unified_api.h +++ b/core/wmi/wmi_unified_api.h @@ -57,6 +57,9 @@ void *wmi_unified_attach(void *scn_handle, */ 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 * -- cgit v1.2.3 From 572fe59f7eb546d823f006d043e14b7172b5c623 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 26 Oct 2015 16:50:38 +0530 Subject: qcacld-3.0: clean up of ERROR logs qcacld-2.0 to qcacld-3.0 propagation Misleading error logs are removed as part of this fix CRs-Fixed: 929840 Change-Id: Ifdc10b79359863a4f3c2009403ee5f6c7ab18110 --- core/sme/src/csr/csr_api_roam.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a05739f94842..39139da7c8b8 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18051,8 +18051,6 @@ bool csr_roam_is_sta_mode(tpAniSirGlobal pMac, uint32_t sessionId) if (pSession->pCurRoamProfile->csrPersona == CDF_STA_MODE) { return true; } else { - sms_log(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), - __func__); return false; } } -- cgit v1.2.3 From a60672fa1cd2c4bfeea229a2e2968fe2b5f27fbd Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 18 Nov 2015 17:29:12 +0530 Subject: qcacld-3.0: Fix static code analysis errors qcacld-2.0 to qcacld-3.0 propagation Updated the wma, htt modules to address the issues reported by static code analysis. CRs-Fixed: 933728 Change-Id: I3437f7d9a12475f4a854412d9f34f48ed7553848 --- core/wma/src/wma_mgmt.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 10011aa2f2f3..b85b51a9faef 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -651,6 +651,15 @@ void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, 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); + cdf_nbuf_free(buf); + return; + } cmd->method = WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE; cdf_mem_copy(&arp_rsp->sender_prot_addr, hostv4addr, SIR_IPV4_ADDR_LEN); -- cgit v1.2.3 From 24c726c6f5fb0ea80c8276f219734a67deea4bf2 Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Thu, 5 Nov 2015 10:59:21 +0530 Subject: qcacld-3.0: Check priviledge permission for SET_CHANNEL_RANGE qcacld-2.0 to qcacld-3.0 propagation Kernel assumes all SET IOCTL commands are assigned with even numbers. But in our WLAN driver, some SET IOCTLS are assigned with odd numbers. This leads kernel fail to check, for some SET IOCTLs, whether user has the right permission to do SET operation. Hence, in driver, before processing SET_CHANNEL_RANGE IOCTL, making sure user task has right permission to process the command. Change-Id: I48bcd55bee45203667bcc679db4ad96aa9e04b7c CRs-Fixed: 930555 --- core/hdd/src/wlan_hdd_hostapd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 17859ba9f50f..1a8727a72662 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -3517,6 +3517,11 @@ static int wlan_hdd_set_force_acs_ch_range(struct net_device *dev, hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); int *value = (int *)extra; + if (!capable(CAP_NET_ADMIN)) { + hddLog(LOGE, FL("permission check failed")); + return -EPERM; + } + if (wlan_hdd_validate_operation_channel(adapter, value[0]) != CDF_STATUS_SUCCESS || wlan_hdd_validate_operation_channel(adapter, value[1]) != -- cgit v1.2.3 From 104e1a73b705d3768c91154a7326741f87838b7e Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Wed, 29 Jul 2015 13:51:12 +0530 Subject: qcacld-3.0: Return NULL if zero is passed as argument to allocate memory qcacld-2.0 to qcacld-3.0 propagation While allocating memory if zero is passed as argument then kernel will return address ZERO_SIZE_PTR(0x10) leading to pass NULL check, which is usually done after every memory allocation. Hence when zero is passed to allocate memory then return NULL without calling kmalloc. While initializing neighbor roam data structure, don't allocate memory if neighbor roam channel list is empty. Change-Id: I50bdb99a0cd8ccbc2d764b8ac21f66bba8a8fdc4 CRs-Fixed: 815664 --- core/cdf/src/cdf_memory.c | 8 ++++---- core/sme/src/csr/csr_neighbor_roam.c | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c index 732d1e59c9ff..2aba419f6477 100644 --- a/core/cdf/src/cdf_memory.c +++ b/core/cdf/src/cdf_memory.c @@ -195,9 +195,9 @@ void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum) uint32_t new_size; int flags = GFP_KERNEL; - if (size > (1024 * 1024)) { + if (size > (1024 * 1024) || size == 0) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: called with arg > 1024K; passed in %zu !!!", + "%s: called with invalid arg; passed in %zu !!!", __func__, size); return NULL; } @@ -327,9 +327,9 @@ void *cdf_mem_malloc(size_t size) #ifdef CONFIG_WCNSS_MEM_PRE_ALLOC void *pmem; #endif - if (size > (1024 * 1024)) { + if (size > (1024 * 1024) || size == 0) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: called with arg > 1024K; passed in %zu !!", + "%s: called with invalid arg; passed in %zu !!", __func__, size); return NULL; } diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 13a9bc8b89e1..31cae0c215ba 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -2763,15 +2763,21 @@ CDF_STATUS csr_neighbor_roam_init(tpAniSirGlobal pMac, uint8_t sessionId) pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = pMac->roam.configParam.neighborRoamConfig.neighborScanChanList. numChannels; - - pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = + if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels != 0) { + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = cdf_mem_malloc(pMac->roam.configParam.neighborRoamConfig. - neighborScanChanList.numChannels); - - if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { - sms_log(pMac, LOGE, + neighborScanChanList.numChannels); + if (NULL == + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { + sms_log(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed")); - return CDF_STATUS_E_NOMEM; + return CDF_STATUS_E_NOMEM; + } + } else { + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + sms_log(pMac, LOGE, + FL("invalid neighbor roam channel list: %u"), + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels); } /* Update the roam global structure from CFG */ -- cgit v1.2.3 From 7cc833c783825abaea6c9f47ca95675134bef926 Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Thu, 1 Oct 2015 14:14:46 +0530 Subject: qcacld-3.0: Update MCS index appropriately qcacld-2.0 to qcacld-3.0 propagation When AP is configured with MCS index less than 4(43Mbps) then Host reports invalid MCS Index to upper-layer, leading to display invalid link speed on GUI. Updating MCS index with valid value and thereby updating correct MCS index to upper-layer Change-Id: Ibd1503be3825c879b7fa52bdfb6ff07423c39023 CRs-Fixed: 855022 --- core/hdd/src/wlan_hdd_stats.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index e335fcaf84d6..47fc6512e338 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -2181,6 +2181,9 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, supported_mcs_rate[j]. supported_rate [rateFlag]; + maxMCSIdx = + supported_mcs_rate[j]. + beacon_rate_index; break; } } @@ -2188,11 +2191,8 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, if ((j < MAX_HT_MCS_IDX) && (currentRate > maxRate)) { maxRate = currentRate; - maxSpeedMCS = 1; - maxMCSIdx = - supported_mcs_rate[j]. - beacon_rate_index; } + maxSpeedMCS = 1; } } } -- cgit v1.2.3 From 4fbb620fa1a03e8dd44c94ad463a370623fcbb51 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 5 Nov 2015 10:53:18 +0530 Subject: qcacld-3.0: CL 1407588 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation WMI_ROAM_SYNCH_EVENT cleanup CRs-Fixed: 932665 Change-Id: Iaf25497b2f511e03823894084b6920be79ca2dba --- target/inc/wmi_unified.h | 28 ++++++++++++++++++++-------- target/inc/wmi_version.h | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 7684d33f6b46..dc143533e9f6 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -6223,6 +6223,7 @@ typedef struct { } 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 */ @@ -6232,19 +6233,29 @@ typedef struct { 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 */ -/* - * These will be used in WMI_ROAM_SYNCH_EVENTID for passing the subnet change - * info. Once roaming happens, firmware checks if subnet has changed and - * populates roam_reason field in WMI_ROAM_SYNCH_EVENTID using the definitions - * below. - */ +/* 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 */ @@ -9591,8 +9602,9 @@ typedef struct { /** auth_status: connected or authorized */ A_UINT32 auth_status; /* - * roam_reason: whether roaming went to a new subnet; - * see WMI_ROAM_SUBNET_CHANGE_STATUS_XXX + * 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 */ diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 0c1b628cc3ac..c036502483fa 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 173 +#define __WMI_REVISION_ 174 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From ea4b2e080af7d7634773b51bb9b4a777190e93a6 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 19 Nov 2015 18:21:15 +0530 Subject: qcacld-3.0: Do not lock to free all packets to avoid watchdog bark Propagation from qcacld-2.0 to qcacld-3.0 Do not take single lock to free all TLSHIM packets to avoid watchdog bark during driver unload. CRs-Fixed: 934555 Change-Id: Iebfb449bd8174bc27207d33073c84a8f11d6e490 --- core/cds/src/cds_sched.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 873555d5d21c..9e6d746f8f33 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -600,11 +600,12 @@ static int cds_mc_thread(void *Arg) */ void cds_free_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext) { - struct cds_ol_rx_pkt *pkt, *tmp; + struct cds_ol_rx_pkt *pkt; spin_lock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); - list_for_each_entry_safe(pkt, tmp, &pSchedContext->cds_ol_rx_pkt_freeq, - list) { + while (!list_empty(&pSchedContext->cds_ol_rx_pkt_freeq)) { + pkt = list_entry((&pSchedContext->cds_ol_rx_pkt_freeq)->next, + typeof(*pkt), list); list_del(&pkt->list); spin_unlock_bh(&pSchedContext->cds_ol_rx_pkt_freeq_lock); cdf_mem_free(pkt); -- cgit v1.2.3 From 31371be5cf382c9190bc3ad20663c6fbe12362a0 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 5 Nov 2015 11:15:54 +0530 Subject: qcacld-3.0: CL 1408339 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Adding PDEV Param to Enable/Disable CTS2Self for P2P GO when Non-P2P Client is connected. CRs-Fixed: 934124 Change-Id: Ib85e7e5f076db54203b170d34992c439d52983a2 --- target/inc/wmi_unified.h | 2 ++ target/inc/wmi_version.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index dc143533e9f6..6ad5506d2dce 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -2949,6 +2949,8 @@ typedef enum { 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, } WMI_PDEV_PARAM; typedef enum { diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index c036502483fa..cbdbb2d811c5 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 174 +#define __WMI_REVISION_ 175 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 1c7b42fcb70014ecec52dccbdbad12d00c38c6b4 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 5 Nov 2015 11:21:08 +0530 Subject: qcacld-3.0: CL 1409457 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add WMI_PDEV_PARAM_TXPOWER_DECR_DB, WMI_VDEV_PARAM_TXPOWER_SCALE, and WMI_VDEV_PARAM_TXPOWER_SCALE_DECR_DB CRs-Fixed: 934137 Change-Id: I0468afc4cb89d21bda82a6a8b14eac66ed7cc6cb --- target/inc/wmi_unified.h | 20 ++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 6ad5506d2dce..cbb3cc452e8a 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -2951,6 +2951,11 @@ typedef enum { 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 { @@ -4486,6 +4491,21 @@ typedef enum { * 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 */ diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index cbdbb2d811c5..41d427807687 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 175 +#define __WMI_REVISION_ 176 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 81230dddfc4b4cf9adda66d8b73d3c398ee758d5 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Mon, 14 Sep 2015 10:47:10 +0530 Subject: qcacld-3.0: remove misprint in ol_txrx_peer_find_add_id() qcacld-2.0 to qcacld-3.0 propagation During create peer, 'delete peer' print is coming from ol_txrx_peer_find_add_id(). Peer deletion is not happened when ol_txrx_peer_find_add_id() calls ol_txrx_peer_unref_delete(). Actual peer deletion is happening in ol_rx_peer_unmap_handler(). So, remove 'delete peer' print in ol_txrx_peer_find_add_id(). Change-Id: If37a573f6ff734743c3901b96c7134c81b35e4c7 CRs-Fixed: 902463 --- core/dp/txrx/ol_txrx_peer_find.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/dp/txrx/ol_txrx_peer_find.c b/core/dp/txrx/ol_txrx_peer_find.c index 1c743f7d5c33..6422ed4433a0 100644 --- a/core/dp/txrx/ol_txrx_peer_find.c +++ b/core/dp/txrx/ol_txrx_peer_find.c @@ -355,8 +355,6 @@ ol_txrx_peer_find_add_id(struct ol_txrx_pdev_t *pdev, * Peregrine/Rome has two peer id for each peer. */ if (peer->peer_ids[0] == HTT_INVALID_PEER) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "%s: Delete Peer %p\n", - __func__, peer); ol_txrx_peer_unref_delete(peer); } if (ol_txrx_peer_find_add_id_to_obj(peer, peer_id)) { -- cgit v1.2.3 From 42df87addb760c74723130b52be3a24e6b1670af Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Wed, 2 Sep 2015 15:18:32 +0530 Subject: qcacld-3.0: wlan: Deregister all the peers from TL during IBSS leave qcacld-2.0 to qcacld-3.0 propagation If user change the BSSID/SSID and restart the IBSS network, during IBSS leave the driver deletes only the 1st peer and all other entries are not deleted. Now when the IBSS restarts and try to register a sta with the staID which is already present in the stale entries, the registeration fails and thus the BSSID values in TL are not updated for all these stale peers. Due to this the data to these peers uses the old BSSID. This change take care of Deregistering all the active IBSS peers during IBSS leave. Change-Id: Id1ce0ffd880b8c2c8afd46414a59ba7bb87d5b6f CRs-Fixed: 841565 --- core/hdd/src/wlan_hdd_assoc.c | 48 ++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 90441b05d714..c6223a35cbbd 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1087,6 +1087,7 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, sme_ft_reset(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId); #endif if (eCSR_ROAM_IBSS_LEAVE == roamStatus) { + uint8_t i; sta_id = IBSS_BROADCAST_STAID; vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); if (!CDF_IS_STATUS_SUCCESS(vstatus)) { @@ -1096,19 +1097,42 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, status = CDF_STATUS_E_FAILURE; } pHddCtx->sta_to_adapter[sta_id] = NULL; + /* Clear all the peer sta register with TL. */ + for (i = 0; i < MAX_IBSS_PEERS; i++) { + if (0 == pHddStaCtx->conn_info.staId[i]) + continue; + sta_id = pHddStaCtx->conn_info.staId[i]; + hddLog(LOG1, FL("Deregister StaID %d"), sta_id); + vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(LOGE, + FL("hdd_roamDeregisterSTA() failed to for staID %d. Status= %d [0x%x]"), + sta_id, status, status); + status = CDF_STATUS_E_FAILURE; + } + /* set the staid and peer mac as 0, all other + * reset are done in hdd_connRemoveConnectInfo. + */ + pHddStaCtx->conn_info.staId[i] = 0; + cdf_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[i], + sizeof(struct cdf_mac_addr)); + 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_roam_deregister_sta(pAdapter, sta_id); + if (!CDF_IS_STATUS_SUCCESS(vstatus)) { + hddLog(LOGE, + FL("hdd_roam_deregister_sta() failed to for staID %d. Status= %d [0x%x]"), + sta_id, status, status); + status = CDF_STATUS_E_FAILURE; + } + pHddCtx->sta_to_adapter[sta_id] = NULL; } - sta_id = pHddStaCtx->conn_info.staId[0]; - - /* We should clear all sta register with TL, for now, only one. */ - vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); - if (!CDF_IS_STATUS_SUCCESS(vstatus)) { - hddLog(LOGE, - "hdd_roam_deregister_sta() failed to for staID %d. Status= %d [0x%x]", - sta_id, status, status); - status = CDF_STATUS_E_FAILURE; - } - - pHddCtx->sta_to_adapter[sta_id] = NULL; /* Clear saved connection information in HDD */ hdd_conn_remove_connect_info(pHddStaCtx); hddLog(LOG1, FL("Set HDD connState to eConnectionState_NotConnected")); -- cgit v1.2.3 From a0acf2ea9e554a144a0ceee45f13341cbb768e45 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Fri, 25 Sep 2015 10:58:15 +0530 Subject: qcacld-3.0: wlan: Remove redundant validation of pAdapter qcacld-2.0 to qcacld-3.0 propagation Validation of pAdapter done in starting of hdd_smeRoamCallback(). Remove redundant pAdapter validation under flag eCSR_ROAM_SESSION_OPENED. Change-Id: I1619bc929e484a60a930779a2acae071a710453a CRs-Fixed: 898391 --- core/hdd/src/wlan_hdd_assoc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index c6223a35cbbd..c534d7e72d95 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3831,10 +3831,8 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, switch (roamStatus) { case eCSR_ROAM_SESSION_OPENED: - if (pAdapter != NULL) { - set_bit(SME_SESSION_OPENED, &pAdapter->event_flags); - complete(&pAdapter->session_open_comp_var); - } + 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) || \ -- cgit v1.2.3 From 14b3b9903c688fec40595649804b9d694b6133e6 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Mon, 7 Sep 2015 12:10:39 +0530 Subject: qcacld-3.0: Add MTRACE logs for missing cfg80211_ops callbacks qcacld-2.0 to qcacld-3.0 propagation Currently, MTRACE logs are not captured for few cfg80211_ops callbacks and SME functions. Add missing MTRACE logs in cfg80211_ops callbacks before calling SME function and also in few SME functions. Change-Id: Iced4b80de60f9640cad0342afac57f9a17c2a3e2 CRs-Fixed: 859961 --- core/hdd/inc/wlan_hdd_trace.h | 10 +++++++++- core/hdd/src/wlan_hdd_cfg80211.c | 9 +++++++++ core/hdd/src/wlan_hdd_power.c | 10 +++++++++- core/hdd/src/wlan_hdd_scan.c | 6 ++++++ core/hdd/src/wlan_hdd_stats.c | 4 ++++ core/sme/inc/sme_trace.h | 14 ++++++++++++++ core/sme/src/common/sme_api.c | 32 ++++++++++++++++++++++++++++++++ core/sme/src/common/sme_trace.c | 15 +++++++++++++++ 8 files changed, 98 insertions(+), 2 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_trace.h b/core/hdd/inc/wlan_hdd_trace.h index 52208168d01e..12e25d5b1a46 100644 --- a/core/hdd/inc/wlan_hdd_trace.h +++ b/core/hdd/inc/wlan_hdd_trace.h @@ -81,6 +81,8 @@ ENUM(TRACE_CODE_HDD_CHANGE_STATION) \ ENUM(TRACE_CODE_HDD_CFG80211_UPDATE_BSS) \ ENUM(TRACE_CODE_HDD_CFG80211_SCAN) \ + ENUM(TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START) \ + ENUM(TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP) \ ENUM(TRACE_CODE_HDD_REMAIN_ON_CHANNEL) \ ENUM(TRACE_CODE_HDD_REMAINCHANREADYHANDLER) \ ENUM(TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL) \ @@ -91,6 +93,7 @@ ENUM(TRACE_CODE_HDD_CFG80211_DEL_STA) \ ENUM(TRACE_CODE_HDD_CFG80211_ADD_STA) \ ENUM(TRACE_CODE_HDD_CFG80211_SET_PMKSA) \ + ENUM(TRACE_CODE_HDD_CFG80211_DEL_PMKSA) \ ENUM(TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES) \ ENUM(TRACE_CODE_HDD_CFG80211_TDLS_MGMT) \ ENUM(TRACE_CODE_HDD_CFG80211_TDLS_OPER) \ @@ -100,7 +103,12 @@ ENUM(TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL) \ ENUM(TRACE_CODE_HDD_STORE_JOIN_REQ) \ ENUM(TRACE_CODE_HDD_CLEAR_JOIN_REQ) \ - ENUM(TRACE_CODE_HDD_ISSUE_JOIN_REQ) + ENUM(TRACE_CODE_HDD_ISSUE_JOIN_REQ) \ + ENUM(TRACE_CODE_HDD_CFG80211_RESUME_WLAN) \ + ENUM(TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN) \ + ENUM(TRACE_CODE_HDD_CFG80211_SET_MAC_ACL) \ + ENUM(TRACE_CODE_HDD_CFG80211_TESTMODE) \ + ENUM(TRACE_CODE_HDD_CFG80211_DUMP_SURVEY) enum { #undef ENUM diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 880fee967b5b..939550454589 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -9730,6 +9730,9 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_DEL_PMKSA, + pAdapter->sessionId, 0)); /* Delete the PMKID CSR cache */ if (CDF_STATUS_SUCCESS != sme_roam_del_pmkid_from_cache(halHandle, @@ -10126,6 +10129,9 @@ static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy, params->n_acl_entries); + MTRACE(cdf_trace(CDF_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; @@ -10309,6 +10315,9 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, return -EINVAL; } + MTRACE(cdf_trace(CDF_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 */ diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 5433c368961e..1c9ede2ffd21 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1765,6 +1765,9 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) #endif hdd_resume_wlan(); + MTRACE(cdf_trace(CDF_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) { @@ -2026,7 +2029,9 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, } pHddCtx->is_ol_rx_thread_suspended = true; #endif - + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN, + NO_SESSION, pHddCtx->isWiphySuspended)); pHddCtx->isWiphySuspended = true; #ifdef CONFIG_CNSS @@ -2306,6 +2311,9 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return -ENOENT; } + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_GET_TXPOWER, + pAdapter->sessionId, pAdapter->device_mode)); wlan_hdd_get_class_astats(pAdapter); *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr; diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 715cf884ee2b..b587d60eced4 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -2073,6 +2073,9 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, return -EBUSY; } + MTRACE(cdf_trace(CDF_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 @@ -2382,6 +2385,9 @@ static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, pPnoRequest->enable = 0; /* Disable PNO */ pPnoRequest->ucNetworksCount = 0; + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP, + pAdapter->sessionId, pAdapter->device_mode)); status = sme_set_preferred_network_list(hHal, pPnoRequest, pAdapter->sessionId, NULL, pAdapter); diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 47fc6512e338..92033a9fb957 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -2447,6 +2447,10 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, wlan_hdd_get_snr(pAdapter, &snr); wlan_hdd_get_rssi(pAdapter, &rssi); + MTRACE(cdf_trace(CDF_MODULE_ID_HDD, + TRACE_CODE_HDD_CFG80211_DUMP_SURVEY, + pAdapter->sessionId, pAdapter->device_mode)); + sme_get_operation_channel(halHandle, &channel, pAdapter->sessionId); hdd_wlan_get_freq(channel, &freq); diff --git a/core/sme/inc/sme_trace.h b/core/sme/inc/sme_trace.h index 7bd1fecdd9c9..67504b657543 100644 --- a/core/sme/inc/sme_trace.h +++ b/core/sme/inc/sme_trace.h @@ -58,6 +58,7 @@ enum { 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, @@ -131,6 +132,19 @@ enum { 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 sme_trace_init(tpAniSirGlobal pMac); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 4bfb7d992d3f..baf6afd3c260 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -3806,6 +3806,9 @@ CDF_STATUS sme_roam_deauth_sta(tHalHandle hHal, uint8_t sessionId, return status; } + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA, + sessionId, pDelStaParams->reason_code)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { if (CSR_IS_SESSION_VALID(pMac, sessionId)) { @@ -4074,6 +4077,10 @@ CDF_STATUS sme_roam_del_pmkid_from_cache(tHalHandle hHal, uint8_t sessionId, { CDF_STATUS status = CDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE, + sessionId, flush_cache)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { if (CSR_IS_SESSION_VALID(pMac, sessionId)) { @@ -6020,6 +6027,9 @@ CDF_STATUS sme_set_preferred_network_list(tHalHandle hHal, tpAniSirGlobal pMac = PMAC_STRUCT(hHal); CDF_STATUS status; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_PREF_NET_LIST, + sessionId, request->ucNetworksCount)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { sme_set_ps_preferred_network_list(hHal, request, sessionId, @@ -9713,6 +9723,10 @@ CDF_STATUS sme_send_tdls_link_establish_params(tHalHandle hHal, CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_LINK_ESTABLISH_PARAM, + sessionId, + tdlsLinkEstablishParams->isOffChannelSupported)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { @@ -9748,6 +9762,9 @@ CDF_STATUS sme_send_tdls_mgmt_frame(tHalHandle hHal, uint8_t sessionId, tCsrTdlsSendMgmt sendTdlsReq = { {0} }; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_SEND_MGMT_FRAME, + sessionId, statusCode)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_copy(sendTdlsReq.peerMac, peerMac, sizeof(tSirMacAddr)); @@ -9788,6 +9805,9 @@ CDF_STATUS sme_change_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, "%s :pstaParams is NULL", __func__); return CDF_STATUS_E_FAILURE; } + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_CHANGE_PEER_STA, + sessionId, pstaParams->capability)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { status = csr_tdls_change_peer_sta(hHal, sessionId, peerMac, @@ -9813,6 +9833,9 @@ CDF_STATUS sme_add_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_ADD_PEER_STA, + sessionId, 0)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { status = csr_tdls_add_peer_sta(hHal, sessionId, peerMac); @@ -9837,6 +9860,9 @@ CDF_STATUS sme_delete_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId, CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_DEL_PEER_STA, + sessionId, 0)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { status = csr_tdls_del_peer_sta(hHal, sessionId, peerMac); @@ -10095,6 +10121,9 @@ CDF_STATUS sme_send_tdls_chan_switch_req(tHalHandle hal, tdls_chan_switch_params *chan_switch_params = NULL; cds_msg_t cds_message; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_TDLS_CHAN_SWITCH_REQ, + NO_SESSION, ch_switch_params->tdls_off_channel)); status = sme_acquire_global_lock(&mac->sme); if (CDF_STATUS_SUCCESS != status) return status; @@ -10574,6 +10603,9 @@ CDF_STATUS sme_lphb_config_req tpAniSirGlobal pMac = PMAC_STRUCT(hHal); cds_msg_t cds_message; + MTRACE(cdf_trace(CDF_MODULE_ID_SME, + TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ, + NO_SESSION, lphdReq->cmd)); status = sme_acquire_global_lock(&pMac->sme); if (CDF_STATUS_SUCCESS == status) { if ((LPHB_SET_EN_PARAMS_INDID == lphdReq->cmd) && diff --git a/core/sme/src/common/sme_trace.c b/core/sme/src/common/sme_trace.c index d6d85fd44409..afedac29ed1f 100644 --- a/core/sme/src/common/sme_trace.c +++ b/core/sme/src/common/sme_trace.c @@ -75,6 +75,7 @@ static uint8_t *sme_trace_get_rx_msg_string(uint32_t code) 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); @@ -149,6 +150,20 @@ static uint8_t *sme_trace_get_rx_msg_string(uint32_t code) 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"; -- cgit v1.2.3 From 6b06628b51ca8a63f685daea9afa6db4ac65db8a Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Mon, 14 Sep 2015 10:58:03 +0530 Subject: qcacld-3.0: Add DS param IE in probe req frame qcacld-2.0 to qcacld-3.0 propagation Currently DS param IE is not present in probe req frames. Set bit11 in scan_ctrl_flags to add DS param IE in probe req. Change-Id: I57f79bd6dc5bd452987cb7d09cafa425ea2bbff4 CRs-Fixed: 905421 --- core/wma/src/wma_scan_roam.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index a3a98f390d24..f5c2ff56ec69 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -295,6 +295,9 @@ CDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, /* 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; @@ -1636,7 +1639,8 @@ void wma_roam_scan_fill_scan_params(tp_wma_handle wma_handle, cdf_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_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" @@ -5361,7 +5365,9 @@ CDF_STATUS wma_get_buf_extscan_start_cmd(tp_wma_handle wma_handle, 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_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; -- cgit v1.2.3 From 7b22d1f5899b94fa00fb20e73cc57bb5344281fc Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Mon, 23 Nov 2015 10:48:33 +0530 Subject: qcacld-3.0: wlan: Cleanup North-Bound load/unload logs qcacld-2.0 to qcacld-3.0 propagation If IOCTLs or CFG callbacks are issued continuously during driver load/unload or during SSR, observing stability issues because of excessive logging. Hence move log level to INFO from ERROR in wlan_hdd_validate_context function and don't print return status in its caller functions. Change-Id: I8fd9b25e0c774e1e12b01128eb86783c9dec2ab7 CRs-Fixed: 800631 --- core/hdd/src/wlan_hdd_cfg80211.c | 157 ++++++++++++++++----------------------- core/hdd/src/wlan_hdd_debugfs.c | 12 ++- core/hdd/src/wlan_hdd_ext_scan.c | 146 ++++++++++++++++++------------------ core/hdd/src/wlan_hdd_hostapd.c | 61 ++++++++------- core/hdd/src/wlan_hdd_ioctl.c | 13 ++-- core/hdd/src/wlan_hdd_main.c | 13 ++-- core/hdd/src/wlan_hdd_p2p.c | 38 +++++----- core/hdd/src/wlan_hdd_power.c | 47 ++++++------ core/hdd/src/wlan_hdd_scan.c | 18 ++--- core/hdd/src/wlan_hdd_stats.c | 54 +++++++------- core/hdd/src/wlan_hdd_tdls.c | 135 +++++++++++++++++---------------- core/hdd/src/wlan_hdd_wext.c | 61 ++++++++++++--- 12 files changed, 379 insertions(+), 376 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 939550454589..e2b4d893ce56 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1791,16 +1791,16 @@ __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, uint32_t fset = 0; int ret; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("Hdd context not valid")); + if (0 != ret) return -EINVAL; - } if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { hddLog(LOG1, FL("Infra Station mode is supported by driver")); @@ -1877,7 +1877,9 @@ __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, hddLog(LOGE, FL("nla put fail")); goto nla_put_failure; } - return cfg80211_vendor_cmd_reply(skb); + ret = cfg80211_vendor_cmd_reply(skb); + EXIT(); + return ret; nla_put_failure: kfree_skb(skb); return -EINVAL; @@ -1938,10 +1940,8 @@ __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } if (false == pHddCtx->config->enable_mac_spoofing) { hddLog(LOGW, FL("MAC address spoofing is not enabled")); @@ -3741,10 +3741,8 @@ __wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy, } ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) { hddLog(LOGE, @@ -3854,10 +3852,8 @@ __wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, ENTER(); ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return -EINVAL; - } if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { hddLog(LOGE, FL("Not in Connected state!")); @@ -3975,9 +3971,10 @@ void hdd_rssi_threshold_breached(void *hddctx, ENTER(); - if (wlan_hdd_validate_context(hdd_ctx) || !data) { - hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), - data); + if (wlan_hdd_validate_context(hdd_ctx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -5356,10 +5353,8 @@ static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != ret) return ret; - } if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || pAdapter->device_mode == WLAN_HDD_P2P_GO)) { @@ -5503,10 +5498,8 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_CHANGE_IFACE, @@ -5824,10 +5817,8 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != ret) return ret; - } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -6109,11 +6100,8 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is not valid", __func__); + if (0 != status) return status; - } hddLog(LOG1, FL("Device_mode %s(%d)"), hdd_device_mode_to_string(pAdapter->device_mode), @@ -6397,7 +6385,7 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, } } } - + EXIT(); return 0; } @@ -6608,10 +6596,8 @@ static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { @@ -6819,12 +6805,12 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, struct timespec ts; #endif + ENTER(); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return NULL; - } mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL); if (!mgmt) { @@ -6930,6 +6916,7 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi, GFP_KERNEL); kfree(mgmt); + EXIT(); return bss_status; } @@ -6997,10 +6984,8 @@ int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } /* start getting scan results and populate cgf80211 BSS database */ status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult); @@ -7319,11 +7304,8 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (status) { - hddLog(LOGE, - FL("HDD context is not valid!")); + if (status) return status; - } if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) { hddLog(LOGE, FL("wrong SSID len")); @@ -8338,10 +8320,8 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if (req->channel) { if (!cds_allow_concurrency(pHddCtx, cds_convert_device_mode_to_hdd_type( @@ -8448,13 +8428,12 @@ int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ENTER(); + status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, - FL("HDD context is not valid")); + if (0 != status) return status; - } /*stop tx queues */ hddLog(LOG1, FL("Disabling queues")); @@ -8543,10 +8522,8 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } /* Issue disconnect request to SME, if station is in connected state */ if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) || @@ -8778,10 +8755,8 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if (NULL != #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) @@ -8938,7 +8913,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, hddLog(LOGE, FL("connect failed")); return status; } - + EXIT(); return 0; } @@ -8996,10 +8971,8 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, pAdapter->sessionId, eCSR_DISCONNECT_REASON_IBSS_LEAVE)); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } hddLog(LOG1, FL("Device_mode %s(%d)"), hdd_device_mode_to_string(pAdapter->device_mode), @@ -9029,7 +9002,7 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, hal_status); return -EAGAIN; } - + EXIT(); return 0; } @@ -9083,11 +9056,8 @@ static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, NO_SESSION, wiphy->rts_threshold)); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, - FL("HDD context is not valid")); + if (0 != status) return status; - } if (changed & WIPHY_PARAM_RTS_THRESHOLD) { u32 rts_threshold = (wiphy->rts_threshold == -1) ? @@ -9172,7 +9142,7 @@ static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, FL("set short retry count %hu"), retry_value); } } - + EXIT(); return 0; } @@ -9334,10 +9304,8 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes; @@ -9553,10 +9521,8 @@ static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, TRACE_CODE_HDD_CFG80211_ADD_STA, pAdapter->sessionId, params->listen_interval)); - if (0 != wlan_hdd_validate_context(pHddCtx)) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != wlan_hdd_validate_context(pHddCtx)) return -EINVAL; - } mask = params->sta_flags_mask; @@ -9572,6 +9538,7 @@ static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, } } #endif + EXIT(); return status; } @@ -9623,6 +9590,8 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, int status; tPmkidCacheInfo pmk_id; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -9644,10 +9613,8 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -9662,6 +9629,7 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, TRACE_CODE_HDD_CFG80211_SET_PMKSA, pAdapter->sessionId, result)); + EXIT(); return CDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL; } @@ -9703,6 +9671,8 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, tHalHandle halHandle; int status = 0; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -9723,10 +9693,8 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -9742,7 +9710,7 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, MAC_ADDR_ARRAY(pmksa->bssid)); status = -EINVAL; } - + EXIT(); return status; } @@ -9783,6 +9751,8 @@ static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, tHalHandle halHandle; int status = 0; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -9793,10 +9763,8 @@ static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } /* Retrieve halHandle */ halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -9808,7 +9776,7 @@ static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, hddLog(LOGE, FL("Cannot flush PMKIDCache")); status = -EINVAL; } - + EXIT(); return status; } @@ -9851,6 +9819,8 @@ __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); int status; + ENTER(); + status = wlan_hdd_validate_context(hdd_ctx); if (status) return status; @@ -9878,6 +9848,7 @@ __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, /* Pass the received FT IEs to SME */ sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, (const u8 *)ftie->ie, ftie->ie_len); + EXIT(); return 0; } @@ -9997,10 +9968,8 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, result = wlan_hdd_validate_context(pHddCtx); - if (0 != result) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != result) return result; - } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -10049,7 +10018,7 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, hddLog(LOG1, FL("wlan not suspended GTKOffload request is stored")); } - + EXIT(); return result; } @@ -10113,10 +10082,8 @@ static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } p_cds_context = pHddCtx->pcds_context; pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); @@ -10201,7 +10168,7 @@ static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, pAdapter->device_mode); return -EINVAL; } - + EXIT(); return 0; } @@ -10243,10 +10210,8 @@ void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd) hddLog(LOGE, FL("LPHB indication arrived")); - if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx)) { - hddLog(LOGE, FL("invalid argument pHddCtx")); + if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx)) return; - } if (NULL == lphbInd) { hddLog(LOGE, FL("invalid argument lphbInd")); @@ -10299,6 +10264,8 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, int err; hdd_context_t *pHddCtx = wiphy_priv(wiphy); + ENTER(); + err = wlan_hdd_validate_context(pHddCtx); if (err) return err; @@ -10394,7 +10361,7 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])); return -EOPNOTSUPP; } - + EXIT(); return err; } diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c index cf7747ee45fa..f4732d546dd2 100644 --- a/core/hdd/src/wlan_hdd_debugfs.c +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -65,6 +65,8 @@ static ssize_t __wcnss_wowenable_write(struct file *file, uint8_t wow_pbm = 0; int ret; + ENTER(); + pAdapter = (hdd_adapter_t *)file->private_data; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, @@ -145,7 +147,7 @@ static ssize_t __wcnss_wowenable_write(struct file *file, return -EFAULT; } - + EXIT(); return count; } @@ -194,6 +196,8 @@ static ssize_t __wcnss_wowpattern_write(struct file *file, char *pattern_mask; int ret; + ENTER(); + if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", @@ -267,7 +271,7 @@ static ssize_t __wcnss_wowpattern_write(struct file *file, hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset, pattern_buf, pattern_mask); - + EXIT(); return count; } @@ -320,6 +324,7 @@ static ssize_t __wcnss_patterngen_write(struct file *file, CDF_STATUS status; int ret; + ENTER(); pAdapter = (hdd_adapter_t *)file->private_data; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { @@ -493,6 +498,7 @@ static ssize_t __wcnss_patterngen_write(struct file *file, } cdf_mem_free(cmd); cdf_mem_free(addPeriodicTxPtrnParams); + EXIT(); return count; failure: @@ -552,7 +558,7 @@ static int __wcnss_debugfs_open(struct inode *inode, struct file *file) ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; - + EXIT(); return 0; } diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index e692ab71f666..4071f771848c 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -158,9 +158,10 @@ wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx, ENTER(); - if (wlan_hdd_validate_context(hdd_ctx) || !data) { - hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), - data); + if (wlan_hdd_validate_context(hdd_ctx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -290,8 +291,10 @@ wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !data) { - hddLog(LOGE, FL("HDD ctx invalid or data(%p) is null"), data); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -479,6 +482,7 @@ wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx, complete(&context->response_event); spin_unlock(&context->context_lock); } + EXIT(); return; fail: @@ -509,8 +513,10 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !data) { - hddLog(LOGE, FL("HDD ctx invalid or data(%p) is null"), data); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -613,6 +619,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, } cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); return; fail: @@ -641,8 +648,10 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !pData) { - hddLog(LOGE, FL("HDD ctx invalid or pData(%p) is null"), pData); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(LOGE, FL("pData is null")); return; } @@ -758,8 +767,10 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !pData) { - hddLog(LOGE, FL("HDD ctx invalid or pData(%p) is null"), pData); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(LOGE, FL("pData is null")); return; } @@ -857,6 +868,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, } cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); return; nla_put_failure: @@ -881,8 +893,10 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event( ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !pData) { - hddLog(LOGE, FL("HDD ctx invalid or pData(%p) is null"), pData); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(LOGE, FL("pData is null")); return; } @@ -911,6 +925,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event( } cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); return; nla_put_failure: @@ -935,8 +950,10 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !pData) { - hddLog(LOGE, FL("HDD ctx invalid or pData(%p) is null"), pData); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!pData) { + hddLog(LOGE, FL("pData is null")); return; } @@ -967,6 +984,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, } cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); return; nla_put_failure: @@ -994,9 +1012,10 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !data) { - hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), - data); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -1106,9 +1125,10 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx, ENTER(); - if (wlan_hdd_validate_context(pHddCtx) || !data) { - hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), - data); + if (wlan_hdd_validate_context(pHddCtx)) + return; + if (!data) { + hddLog(LOGE, FL("data is null")); return; } @@ -1235,10 +1255,10 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, ENTER(); - if (wlan_hdd_validate_context(hdd_ctx) || !event) { - hddLog(LOGE, - FL("HDD context is not valid or event(%p) is null"), - event); + if (wlan_hdd_validate_context(hdd_ctx)) + return; + if (!event) { + hddLog(LOGE, FL("event is null")); return; } @@ -1411,10 +1431,10 @@ void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType, { hdd_context_t *pHddCtx = (hdd_context_t *) ctx; - if (wlan_hdd_validate_context(pHddCtx)) { - hddLog(LOGE, FL("HDD ctx invalid received event: %d"), evType); + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) return; - } hddLog(LOG1, FL("Rcvd Event %d"), evType); @@ -1489,6 +1509,7 @@ void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType, hddLog(LOGE, FL("Unknown event type %u"), evType); break; } + EXIT(); } /* @@ -1538,10 +1559,8 @@ static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx) uint32_t nl_buf_len; ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) { - hddLog(LOGE, FL("hdd_context is invalid")); + if (0 != ret) return ret; - } data = &(ext_scan_context.capability_response); @@ -1678,10 +1697,8 @@ static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -1731,7 +1748,7 @@ static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, 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: cdf_mem_free(pReqMsg); @@ -1814,10 +1831,8 @@ static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != retval) return -EINVAL; - } if (nla_parse(tb, PARAM_MAX, data, data_len, wlan_hdd_extscan_config_policy)) { @@ -1877,7 +1892,7 @@ static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, retval = context->response_status; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -1964,10 +1979,8 @@ __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -2092,7 +2105,7 @@ __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -2163,10 +2176,8 @@ __wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -2314,7 +2325,7 @@ __wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -2447,10 +2458,8 @@ __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -2526,8 +2535,9 @@ __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, kfree_skb(reply_skb); return -EINVAL; } - - return cfg80211_vendor_cmd_reply(reply_skb); + ret = cfg80211_vendor_cmd_reply(reply_skb); + EXIT(); + return ret; } hddLog(LOGE, FL("valid channels: buffer alloc fail")); @@ -3113,10 +3123,8 @@ __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != retval) return -EINVAL; - } if (nla_parse(tb, PARAM_MAX, data, data_len, wlan_hdd_extscan_config_policy)) { @@ -3240,7 +3248,7 @@ __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -3325,10 +3333,8 @@ __wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != retval) return -EINVAL; - } if (nla_parse(tb, PARAM_MAX, data, data_len, wlan_hdd_extscan_config_policy)) { @@ -3381,7 +3387,7 @@ __wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -3454,10 +3460,8 @@ __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -3512,7 +3516,7 @@ __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -3581,10 +3585,8 @@ __wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy } retval = wlan_hdd_validate_context(pHddCtx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + 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)) { @@ -3640,7 +3642,7 @@ __wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy retval = -EINVAL; spin_unlock(&context->context_lock); } - + EXIT(); return retval; fail: @@ -4247,10 +4249,8 @@ __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(hdd_ctx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != retval) return -EINVAL; - } if (nla_parse(tb, PARAM_MAX, data, data_len, @@ -4469,10 +4469,8 @@ __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, } retval = wlan_hdd_validate_context(hdd_ctx); - if (0 != retval) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != retval) return -EINVAL; - } if (nla_parse(tb, PARAM_MAX, data, data_len, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 1a8727a72662..a796d956f781 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -539,10 +539,8 @@ static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter, pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { #ifdef WLAN_FEATURE_MBSSID @@ -2202,12 +2200,12 @@ static __iw_softap_setparam(struct net_device *dev, v_CONTEXT_t p_cds_context; hdd_context_t *hdd_ctx; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid ret:%d"), ret); + if (0 != ret) return -EINVAL; - } hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); if (!hHal) { @@ -2834,7 +2832,7 @@ static __iw_softap_setparam(struct net_device *dev, ret = -EINVAL; break; } - + EXIT(); return ret; } @@ -2865,6 +2863,8 @@ static __iw_softap_getparam(struct net_device *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) @@ -3054,7 +3054,7 @@ static __iw_softap_getparam(struct net_device *dev, break; } - + EXIT(); return ret; } @@ -3176,6 +3176,8 @@ static __iw_softap_getchannel(struct net_device *dev, int *value = (int *)extra; int ret; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -3185,6 +3187,7 @@ static __iw_softap_getchannel(struct net_device *dev, if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) *value = (WLAN_HDD_GET_AP_CTX_PTR( pHostapdAdapter))->operatingChannel; + EXIT(); return 0; } @@ -3216,6 +3219,8 @@ static __iw_softap_set_max_tx_power(struct net_device *dev, tSirMacAddr selfMac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int ret; + ENTER(); + if (NULL == value) return -ENOMEM; @@ -3236,7 +3241,7 @@ static __iw_softap_set_max_tx_power(struct net_device *dev, hddLog(LOGE, FL("Setting maximum tx power failed")); return -EIO; } - + EXIT(); return 0; } @@ -3267,6 +3272,8 @@ static __iw_softap_set_tx_power(struct net_device *dev, tSirMacAddr bssid; int ret; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -3285,7 +3292,7 @@ static __iw_softap_set_tx_power(struct net_device *dev, hddLog(LOGE, FL("Setting tx power failed")); return -EIO; } - + EXIT(); return 0; } @@ -3320,6 +3327,8 @@ static __iw_softap_getassoc_stamacaddr(struct net_device *dev, /* maclist_index must be u32 to match userspace */ u32 maclist_index; + ENTER(); + /* * NOTE WELL: this is a "get" ioctl but it uses an even ioctl * number, and even numbered iocts are supposed to have "set" @@ -3377,6 +3386,7 @@ static __iw_softap_getassoc_stamacaddr(struct net_device *dev, ret = -EFAULT; } kfree(buf); + EXIT(); return ret; } @@ -3649,7 +3659,6 @@ int __iw_get_genie(struct net_device *dev, } #endif - hddLog(LOG1, FL("getGEN_IE ioctl")); /* * Actually retrieve the RSN IE from CSR. * (We previously sent it down in the CSR Roam Profile.) @@ -3992,7 +4001,7 @@ static int __iw_set_ap_encodeext(struct net_device *dev, vstatus); ret = -EINVAL; } - + EXIT(); return ret; } @@ -4219,6 +4228,7 @@ static int __iw_get_ap_freq(struct net_device *dev, fwrq->e = MHZ; } } + EXIT(); return 0; } @@ -5000,6 +5010,8 @@ CDF_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, uint8_t *pBuf, const char sta_info_header[] = "staId staAddress"; hdd_context_t *hdd_ctx; + ENTER(); + if (NULL == pAdapter) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__); @@ -5036,6 +5048,7 @@ CDF_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, uint8_t *pBuf, break; } } + EXIT(); return CDF_STATUS_SUCCESS; } @@ -5195,6 +5208,8 @@ int __iw_get_softap_linkspeed(struct net_device *dev, CDF_STATUS status = CDF_STATUS_E_FAILURE; int rc, valid, i; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); valid = wlan_hdd_validate_context(hdd_ctx); if (0 != valid) @@ -5254,7 +5269,7 @@ int __iw_get_softap_linkspeed(struct net_device *dev, hddLog(LOGE, FL("Unable to encode link speed")); return -EIO; } - + EXIT(); return 0; } @@ -7813,10 +7828,8 @@ static int __wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if (!cds_allow_concurrency(pHddCtx, cds_convert_device_mode_to_hdd_type( @@ -7916,10 +7929,8 @@ static int __wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO)) { @@ -8022,10 +8033,8 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || pAdapter->device_mode == WLAN_HDD_P2P_GO)) { @@ -8283,10 +8292,8 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } hddLog(LOG2, FL("pAdapter = %p, Device mode %s(%d)"), pAdapter, hdd_device_mode_to_string(pAdapter->device_mode), @@ -8450,10 +8457,8 @@ static int __wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP || pAdapter->device_mode == WLAN_HDD_P2P_GO)) { diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 1c8f70ac4738..8c8ecf43811b 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -6134,6 +6134,8 @@ static int hdd_driver_command(hdd_adapter_t *adapter, uint8_t *command = NULL; int ret = 0; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -6176,7 +6178,7 @@ static int hdd_driver_command(hdd_adapter_t *adapter, exit: if (command) kfree(command); - + EXIT(); return ret; } @@ -6256,6 +6258,8 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) hdd_context_t *hdd_ctx; int ret; + ENTER(); + if (dev != adapter->dev) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, "%s: HDD adapter/dev inconsistency", __func__); @@ -6280,12 +6284,8 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); - if (ret) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: invalid context", __func__); - ret = -EBUSY; + if (ret) goto exit; - } switch (cmd) { case (SIOCDEVPRIVATE + 1): @@ -6301,6 +6301,7 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } exit: + EXIT(); return ret; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0a81fc36d9de..15aa4834ccf5 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -404,8 +404,6 @@ static void hdd_cdf_trace_enable(CDF_MODULE_ID moduleId, uint32_t bitmask) */ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx) { - ENTER(); - if (NULL == hdd_ctx || NULL == hdd_ctx->config) { hddLog(LOGE, FL("HDD context is Null")); return -ENODEV; @@ -1380,10 +1378,8 @@ static int __hdd_stop(struct net_device *dev) adapter->sessionId, adapter->device_mode)); ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } /* Nothing to be done if the interface is not opened */ if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) { @@ -1608,11 +1604,11 @@ static void __hdd_set_multicast_list(struct net_device *dev) if (CDF_FTM_MODE == hdd_get_conparam()) return; + ENTER(); + status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) { - hdd_err("hdd_ctx is not valid"); + if (0 != status) return; - } if (dev->flags & IFF_ALLMULTI) { hddLog(CDF_TRACE_LEVEL_INFO, @@ -1669,6 +1665,7 @@ static void __hdd_set_multicast_list(struct net_device *dev) } else { hdd_info("skip mc filtering enable it during cfg80211 suspend"); } + EXIT(); return; } diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index dbfe8b964322..f41d4d97fdd9 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -845,6 +845,8 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, int ret; int status = 0; + ENTER(); + hddLog(LOG1, FL("Device_mode %s(%d)"), hdd_device_mode_to_string(pAdapter->device_mode), pAdapter->device_mode); @@ -859,10 +861,8 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, #endif pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } if (cds_is_connection_in_progress( (hdd_context_t *) pAdapter->pHddCtx)) { hddLog(LOGE, FL("Connection is in progress")); @@ -950,6 +950,7 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, hdd_debug("scheduling delayed work: no connection/roc active"); schedule_delayed_work(&pHddCtx->roc_req_work, 0); } + EXIT(); return 0; } @@ -973,6 +974,8 @@ int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, 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) @@ -986,12 +989,14 @@ int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_REMAIN_ON_CHANNEL, pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST)); - return wlan_hdd_request_remain_on_channel(wiphy, dev, chan, + ret = wlan_hdd_request_remain_on_channel(wiphy, dev, chan, #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) channel_type, #endif duration, cookie, REMAIN_ON_CHANNEL_REQUEST); + EXIT(); + return ret; } int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, @@ -1163,7 +1168,7 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, cdf_list_node_t *tmp, *q; hdd_roc_req_t *curr_roc_req; - hddLog(LOG1, "Cancel remain on channel"); + ENTER(); if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); @@ -1172,11 +1177,8 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is not valid", __func__); + if (0 != status) return status; - } cdf_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); @@ -1287,6 +1289,7 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, __func__); } hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC); + EXIT(); return 0; } @@ -1355,6 +1358,8 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, hdd_adapter_t *goAdapter; uint16_t current_freq; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -1365,11 +1370,8 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, pAdapter->device_mode)); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is not valid", __func__); + if (0 != status) return status; - } hddLog(LOG1, FL("Device_mode %s(%d) type: %d"), hdd_device_mode_to_string(pAdapter->device_mode), @@ -1717,6 +1719,7 @@ err_rem_channel: pAdapter->dev, #endif *cookie, buf, len, false, GFP_KERNEL); + EXIT(); return 0; } @@ -2134,10 +2137,8 @@ struct net_device *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != ret) return ERR_PTR(ret); - } MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type)); @@ -2278,11 +2279,8 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is not valid", __func__); + if (0 != status) return status; - } wlan_hdd_release_intf_addr(pHddCtx, pVirtAdapter->macAddressCurrent.bytes); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 1c9ede2ffd21..1f97634cfd7b 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -214,6 +214,8 @@ static int __wlan_hdd_ipv6_changed(struct notifier_block *nb, hdd_context_t *pHddCtx; int status; + ENTER(); + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { hddLog(LOGE, FL("Adapter context is invalid %p"), pAdapter); return -EINVAL; @@ -224,14 +226,12 @@ static int __wlan_hdd_ipv6_changed(struct notifier_block *nb, pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is invalid")); + if (0 != status) return NOTIFY_DONE; - } schedule_work(&pAdapter->ipv6NotifierWorkQueue); } - + EXIT(); return NOTIFY_DONE; } @@ -436,14 +436,12 @@ void __hdd_ipv6_notifier_work_queue(struct work_struct *work) hdd_context_t *pHddCtx; int status; - hddLog(LOG1, FL("Reconfiguring NS Offload")); + ENTER(); pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is invalid")); + if (0 != status) return; - } if (!pHddCtx->config->active_mode_offload) { hdd_err("Active mode offload is disabled"); @@ -460,6 +458,7 @@ void __hdd_ipv6_notifier_work_queue(struct work_struct *work) (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) if (pHddCtx->config->fhostNSOffload) hdd_conf_ns_offload(pAdapter, true); + EXIT(); } /** @@ -489,6 +488,8 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) { hdd_context_t *pHddCtx; + ENTER(); + hdd_info("Configuring offloads with flag: %d", fenable); /* Get the HDD context. */ @@ -519,6 +520,8 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) if (pHddCtx->config->fhostNSOffload) hdd_conf_ns_offload(pAdapter, fenable); } + EXIT(); + EXIT(); return; } #endif @@ -603,6 +606,8 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, hdd_context_t *pHddCtx; int status; + ENTER(); + if ((pAdapter == NULL) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { hddLog(LOGE, FL("Adapter context is invalid %p"), pAdapter); return -EINVAL; @@ -614,10 +619,8 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is invalid")); + if (0 != status) return NOTIFY_DONE; - } if (!pHddCtx->config->fhostArpOffload) { hddLog(LOG1, @@ -640,7 +643,7 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, schedule_work(&pAdapter->ipv4NotifierWorkQueue); } } - + EXIT(); return NOTIFY_DONE; } @@ -1743,10 +1746,8 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) } result = wlan_hdd_validate_context(pHddCtx); - if (0 != result) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != result) return result; - } #ifdef CONFIG_CNSS cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_MEDIUM); #endif @@ -1803,7 +1804,7 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) hddLog(LOG1, FL("cfg80211 scan result database updated")); - + EXIT(); return result; } status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); @@ -1811,6 +1812,7 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) } hddLog(LOG1, FL("Failed to find Adapter")); + EXIT(); return result; } @@ -1880,10 +1882,8 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, } rc = wlan_hdd_validate_context(pHddCtx); - if (0 != rc) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != rc) return rc; - } /* 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 @@ -2108,10 +2108,8 @@ static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } if ((DRIVER_POWER_MODE_AUTO == !mode) && (true == pHddCtx->hdd_wlan_suspended) && @@ -2203,10 +2201,8 @@ static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, NO_SESSION, type)); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } hHal = pHddCtx->hHal; @@ -2300,7 +2296,6 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); *dbm = 0; return status; } diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index b587d60eced4..1b73597b242f 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -723,9 +723,6 @@ static int __iw_set_scan(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: enter !!!", - __func__); - /* 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) { @@ -850,8 +847,6 @@ error: if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len)) cdf_mem_free(scanRequest.SSIDs.SSIDList); EXIT(); - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: exit !!!", - __func__); return status; } @@ -950,9 +945,9 @@ static int __iw_get_scan(struct net_device *dev, sme_scan_result_purge(hHal, pResult); - EXIT(); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!", __func__, i); + EXIT(); return status; } @@ -1266,10 +1261,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } cfg_param = pHddCtx->config; pScanInfo = &pAdapter->scan_info; @@ -2043,6 +2036,8 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, struct hdd_config *config = NULL; uint32_t num_ignore_dfs_ch = 0; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -2051,10 +2046,8 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != ret) return ret; - } config = pHddCtx->config; hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -2294,6 +2287,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, error: cdf_mem_free(pPnoRequest); + EXIT(); return ret; } diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 92033a9fb957..ccee1b921801 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -631,13 +631,13 @@ static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter, struct nlattr *peers; int numRate; + ENTER(); + pWifiPeerStat = pData; status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return; - } hddLog(CDF_TRACE_LEVEL_INFO, "LL_STATS_PEER_ALL : numPeers %u, more data = %u", @@ -779,6 +779,7 @@ static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter, nla_nest_end(vendor_event, peerInfo); } cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); return; } @@ -804,13 +805,13 @@ static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter, int status; int i; + ENTER(); + pWifiIfaceStat = pData; status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return; - } /* * Allocate a size of 4096 for the interface stats comprising @@ -931,6 +932,7 @@ static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter, } cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); return; } @@ -958,12 +960,12 @@ static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter, 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) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return; - } hddLog(CDF_TRACE_LEVEL_INFO, "LL_STATS_RADIO" @@ -1126,6 +1128,7 @@ static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter, nla_nest_end(vendor_event, chList); } cfg80211_vendor_cmd_reply(vendor_event); + EXIT(); return; } @@ -1312,16 +1315,16 @@ __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = wiphy_priv(wiphy); + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return -EINVAL; - } if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX, (struct nlattr *)data, @@ -1376,7 +1379,7 @@ __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, } pAdapter->isLinkLayerStatsSet = 1; - + EXIT(); return 0; } @@ -1443,16 +1446,16 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); int status; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return -EINVAL; - } if (!pAdapter->isLinkLayerStatsSet) { hddLog(CDF_TRACE_LEVEL_FATAL, @@ -1517,7 +1520,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, context->request_id, context->request_bitmap); return -ETIMEDOUT; } - + EXIT(); return 0; } @@ -1578,16 +1581,16 @@ __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, int status; struct sk_buff *temp_skbuff; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return -EINVAL; - } if (!pAdapter->isLinkLayerStatsSet) { hddLog(CDF_TRACE_LEVEL_FATAL, @@ -1668,6 +1671,7 @@ __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, return cfg80211_vendor_cmd_reply(temp_skbuff); } + EXIT(); return -ENOMEM; } @@ -1925,10 +1929,8 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } wlan_hdd_get_rssi(pAdapter, &sinfo->signal); sinfo->filled |= STATION_INFO_SIGNAL; @@ -2415,10 +2417,8 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, pHddCtx = WLAN_HDD_GET_CTX(pAdapter); status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + if (0 != status) return status; - } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -2484,7 +2484,7 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, pAdapter->survey_idx = 0; return -ENONET; } - + EXIT(); return 0; } diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index b3a1e0e88d19..19da47f69030 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -286,6 +286,8 @@ static void wlan_hdd_tdls_discovery_timeout_peer_cb(void *userData) tdlsCtx_t *pHddTdlsCtx; hdd_context_t *pHddCtx; + ENTER(); + pHddTdlsCtx = (tdlsCtx_t *) userData; if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter)) { @@ -300,13 +302,7 @@ static void wlan_hdd_tdls_discovery_timeout_peer_cb(void *userData) } pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); - return; - } - - if (NULL == pHddCtx) + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; mutex_lock(&pHddCtx->tdls_lock); @@ -333,7 +329,7 @@ static void wlan_hdd_tdls_discovery_timeout_peer_cb(void *userData) wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); mutex_unlock(&pHddCtx->tdls_lock); - + EXIT(); return; } @@ -831,11 +827,8 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac) tdlsCtx_t *pHddTdlsCtx; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + if (0 != (wlan_hdd_validate_context(pHddCtx))) return NULL; - } /* if already there, just update */ peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); @@ -1027,6 +1020,8 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); hdd_context_t *pHddCtx; + ENTER(); + if (NULL == pHddTdlsCtx) { hddLog(LOGE, FL("pHddTdlsCtx is NULL")); return -EINVAL; @@ -1034,10 +1029,8 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - hddLog(LOGE, FL("pHddCtx is not valid")); + if (0 != (wlan_hdd_validate_context(pHddCtx))) return -EINVAL; - } curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); if (NULL == curr_peer) { @@ -1102,6 +1095,7 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, } curr_peer->tdls_support = eTDLS_CAP_SUPPORTED; + EXIT(); return 0; } @@ -1465,13 +1459,12 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter; tdlsCtx_t *pHddTdlsCtx; + ENTER(); + hddLog(LOG1, "%s mode %d", __func__, (int)tdls_mode); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; - } mutex_lock(&pHddCtx->tdls_lock); @@ -1505,6 +1498,7 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, pHddCtx->tdls_mode = tdls_mode; mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); } /** @@ -1872,11 +1866,10 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, tdlsCtx_t *pHddTdlsCtx; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return NULL; - } if (mutexLock) { mutex_lock(&pHddCtx->tdls_lock); @@ -1905,6 +1898,7 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, } if (mutexLock) mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); return NULL; } @@ -2042,11 +2036,10 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) tdlsCtx_t *pHddTdlsCtx; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return 0; - } init_len = buflen; len = scnprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", @@ -2087,6 +2080,7 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) } } mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); return init_len - buflen; } @@ -2189,11 +2183,10 @@ void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; - } mutex_lock(&pHddCtx->tdls_lock); @@ -2204,6 +2197,7 @@ void wlan_hdd_tdls_increment_peer_count(hdd_adapter_t *pAdapter) __func__, pHddCtx->connected_peer_count); mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); } /** @@ -2216,11 +2210,10 @@ void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; - } mutex_lock(&pHddCtx->tdls_lock); @@ -2232,7 +2225,7 @@ void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter) __func__, pHddCtx->connected_peer_count); mutex_unlock(&pHddCtx->tdls_lock); - + EXIT(); } @@ -2342,6 +2335,8 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) int status; tSirMacAddr peer_mac; + ENTER(); + if (NULL == pHddTdlsCtx) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, FL("pHddTdlsCtx is NULL")); @@ -2357,11 +2352,8 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; - } mutex_lock(&pHddCtx->tdls_lock); @@ -2469,6 +2461,7 @@ done: pHddTdlsCtx->curr_candidate = NULL; pHddTdlsCtx->magic = 0; mutex_unlock(&pHddCtx->tdls_lock); + EXIT(); return; } @@ -2505,10 +2498,10 @@ int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, { tdls_scan_context_t *scan_ctx; - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - hddLog(LOGE, FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return -EINVAL; - } scan_ctx = &pHddCtx->tdls_scan_ctxt; @@ -2518,6 +2511,7 @@ int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, #endif scan_ctx->scan_request = request; + EXIT(); return 0; } @@ -2574,6 +2568,8 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, unsigned long delay; int ret; + ENTER(); + ret = wlan_hdd_validate_context(pHddCtx); if (ret) return ret; @@ -2732,6 +2728,7 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, "%s: tdls_mode %d, and no tdls connection. scan allowed", __func__, pHddCtx->tdls_mode); } + EXIT(); return 1; } @@ -2745,11 +2742,10 @@ void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (0 != (wlan_hdd_validate_context(pHddCtx))) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("pHddCtx is not valid")); + ENTER(); + + if (0 != (wlan_hdd_validate_context(pHddCtx))) return; - } if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) { hdd_info("TDLS mode is disabled OR not enabled"); @@ -2768,6 +2764,7 @@ void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) wlan_hdd_tdls_set_mode(pHddCtx, pHddCtx->tdls_mode_last, false); } + EXIT(); } /** @@ -2980,15 +2977,16 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, uint32_t channel = 0; struct sk_buff *skb = NULL; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } ret = wlan_hdd_validate_context(pHddCtx); - if (0 != ret) { + if (0 != ret) return -EINVAL; - } if (pHddCtx->config->fTDLSExternalControl == false) { return -ENOTSUPP; } @@ -3036,7 +3034,9 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); goto nla_put_failure; } - return cfg80211_vendor_cmd_reply(skb); + ret = cfg80211_vendor_cmd_reply(skb); + EXIT(); + return ret; nla_put_failure: kfree_skb(skb); return -EINVAL; @@ -3084,10 +3084,11 @@ static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac, struct sk_buff *skb = NULL; uint32_t global_operating_class = 0; uint32_t channel = 0; - if (wlan_hdd_validate_context(pHddCtx)) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid ")); + + ENTER(); + + if (wlan_hdd_validate_context(pHddCtx)) return -EINVAL; - } if (pHddCtx->config->fTDLSExternalControl == false) { return -ENOTSUPP; } @@ -3119,6 +3120,7 @@ static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac, goto nla_put_failure; } cfg80211_vendor_event(skb, GFP_KERNEL); + EXIT(); return 0; nla_put_failure: kfree_skb(skb); @@ -3151,6 +3153,9 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX + 1]; CDF_STATUS status; tdls_req_params_t pReqMsg = { 0 }; + int ret; + + ENTER(); if (CDF_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); @@ -3158,10 +3163,8 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return -EINVAL; - } if (pHddCtx->config->fTDLSExternalControl == false) { hddLog(CDF_TRACE_LEVEL_ERROR, FL("TDLS External Control is not enabled")); @@ -3213,7 +3216,7 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]); hddLog(CDF_TRACE_LEVEL_INFO, FL("Bandwidth (%d)"), pReqMsg.min_bandwidth_kbps); - return wlan_hdd_tdls_extctrl_config_peer( + ret = wlan_hdd_tdls_extctrl_config_peer( pAdapter, peer, wlan_hdd_cfg80211_exttdls_callback, @@ -3222,6 +3225,8 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, pReqMsg. global_operating_class, pReqMsg.min_bandwidth_kbps); + EXIT(); + return ret; } /** @@ -3277,10 +3282,8 @@ static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, } status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != status) return -EINVAL; - } if (pHddCtx->config->fTDLSExternalControl == false) { return -ENOTSUPP; } @@ -3296,7 +3299,9 @@ static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, memcpy(peer, nla_data(tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]), sizeof(peer)); hddLog(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); - return wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); + status = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer); + EXIT(); + return status; } /** @@ -4014,6 +4019,8 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; hddTdlsPeer_t *pTdlsPeer; + ENTER(); + if (CDF_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; @@ -4030,11 +4037,8 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is not valid", __func__); + if (0 != status) return status; - } /* QCA 2.0 Discrete ANDs feature capability in HDD config with that * received from target, so HDD config gives combined intersected result @@ -4373,6 +4377,7 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, "%s: unsupported event", __func__); return -ENOTSUPP; } + EXIT(); return 0; } diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index bd22dcb139f8..bb16e8f222ad 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1191,6 +1191,8 @@ CDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr) unsigned long rc; int valid; + ENTER(); + if (NULL == pAdapter) { hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid context, pAdapter", __func__); @@ -1200,10 +1202,8 @@ CDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr) pHddCtx = WLAN_HDD_GET_CTX(pAdapter); valid = wlan_hdd_validate_context(pHddCtx); - if (0 != valid) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + if (0 != valid) return CDF_STATUS_E_FAULT; - } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -1248,7 +1248,7 @@ CDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr) spin_unlock(&hdd_context_lock); *snr = pAdapter->snr; - + EXIT(); return CDF_STATUS_SUCCESS; } @@ -3564,6 +3564,8 @@ static int __iw_get_linkspeed(struct net_device *dev, hdd_context_t *hdd_ctx; int rc, valid; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); valid = wlan_hdd_validate_context(hdd_ctx); if (0 != valid) @@ -3584,6 +3586,7 @@ static int __iw_get_linkspeed(struct net_device *dev, return -EIO; } + EXIT(); /* a value is being successfully returned */ return 0; } @@ -4941,6 +4944,8 @@ static int __iw_setint_getnone(struct net_device *dev, int enable_pbm, enable_mp; CDF_STATUS status; + ENTER(); + INIT_COMPLETION(pWextState->completion_var); memset(&smeConfig, 0x00, sizeof(smeConfig)); @@ -6157,6 +6162,7 @@ static int __iw_setint_getnone(struct net_device *dev, break; } } + EXIT(); return ret; } @@ -6204,6 +6210,8 @@ static int __iw_setchar_getnone(struct net_device *dev, return -EPERM; } + ENTER(); + ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; @@ -6301,6 +6309,7 @@ static int __iw_setchar_getnone(struct net_device *dev, } } kfree(pBuffer); + EXIT(); return ret; } @@ -6337,6 +6346,8 @@ static int __iw_setnone_getint(struct net_device *dev, 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) @@ -6812,7 +6823,7 @@ static int __iw_setnone_getint(struct net_device *dev, break; } } - + EXIT(); return ret; } @@ -6848,6 +6859,8 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, int ret; hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + ENTER(); + ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; @@ -6892,6 +6905,7 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, break; } + EXIT(); return ret; } @@ -6954,6 +6968,8 @@ static int __iw_get_char_setnone(struct net_device *dev, 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) @@ -7423,7 +7439,7 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } } - + EXIT(); return 0; } @@ -7458,6 +7474,8 @@ static int __iw_setnone_getnone(struct net_device *dev, int ret; int sub_cmd; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -7578,7 +7596,7 @@ static int __iw_setnone_getnone(struct net_device *dev, break; } } - + EXIT(); return ret; } @@ -7620,6 +7638,8 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, hdd_context_t *hdd_ctx; int ret, num_args; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -7961,7 +7981,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, } break; } - + EXIT(); return 0; } @@ -8062,6 +8082,8 @@ static int __iw_add_tspec(struct net_device *dev, struct iw_request_info *info, 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) @@ -8196,6 +8218,7 @@ static int __iw_add_tspec(struct net_device *dev, struct iw_request_info *info, } *pStatus = hdd_wmm_addts(pAdapter, handle, &tSpec); + EXIT(); return 0; } @@ -8231,6 +8254,8 @@ static int __iw_del_tspec(struct net_device *dev, struct iw_request_info *info, uint32_t handle; int ret; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -8257,6 +8282,7 @@ static int __iw_del_tspec(struct net_device *dev, struct iw_request_info *info, } *pStatus = hdd_wmm_delts(pAdapter, handle); + EXIT(); return 0; } @@ -8292,6 +8318,8 @@ static int __iw_get_tspec(struct net_device *dev, struct iw_request_info *info, uint32_t handle; int ret; + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -8310,6 +8338,7 @@ static int __iw_get_tspec(struct net_device *dev, struct iw_request_info *info, } *pStatus = hdd_wmm_checkts(pAdapter, handle); + EXIT(); return 0; } @@ -8348,6 +8377,8 @@ static int __iw_set_fties(struct net_device *dev, struct iw_request_info *info, 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) @@ -8376,7 +8407,7 @@ static int __iw_set_fties(struct net_device *dev, struct iw_request_info *info, /* Pass the received FT IEs to SME */ sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, extra, wrqu->data.length); - + EXIT(); return 0; } @@ -8413,6 +8444,8 @@ static int __iw_set_host_offload(struct net_device *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) @@ -8491,7 +8524,7 @@ static int __iw_set_host_offload(struct net_device *dev, "%s: Failure to execute host offload request", __func__); return -EINVAL; } - + EXIT(); return 0; } @@ -8526,6 +8559,8 @@ static int __iw_set_keepalive_params(struct net_device *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) @@ -8578,7 +8613,7 @@ static int __iw_set_keepalive_params(struct net_device *dev, hdd_err("Failure to execute Keep Alive"); return -EINVAL; } - + EXIT(); return 0; } @@ -8744,6 +8779,8 @@ static int __iw_set_packet_filter_params(struct net_device *dev, return -EPERM; } + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) @@ -8771,7 +8808,7 @@ static int __iw_set_packet_filter_params(struct net_device *dev, ret = wlan_hdd_set_filter(hdd_ctx, request, adapter->sessionId); kfree(request); - + EXIT(); return ret; } -- cgit v1.2.3 From dd74987a0c179903a273dbab9cfef440513e223c Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Tue, 3 Nov 2015 16:30:32 +0530 Subject: qcacld-3.0: Remove redundant code in __wlan_hdd_cfg80211_connect() qcacld-2.0 to qcacld-3.0 propagation Make changes to invoke wlan_hdd_cfg80211_connect_start() one time instead of two instances of invoking the same function using local variables. Change-Id: I2aba87645296414f340c89b6bd2f556b05f05115 CRs-Fixed: 898565 --- core/hdd/src/wlan_hdd_cfg80211.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e2b4d893ce56..9332e403d936 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8288,6 +8288,12 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, struct cfg80211_connect_params *req) { int status; + u16 channel; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + const u8 *bssid_hint = req->bssid_hint; +#else + const u8 *bssid_hint = NULL; +#endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev); hdd_context_t *pHddCtx; @@ -8359,31 +8365,13 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, return status; } - if (req->channel) { - status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, - req->ssid_len, - req->bssid, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \ - defined(CFG80211_BSSID_HINT_BACKPORT) - req->bssid_hint, -#else - NULL, -#endif - req->channel-> - hw_value); - } else { - status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, - req->ssid_len, - req->bssid, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \ - defined(CFG80211_BSSID_HINT_BACKPORT) - req->bssid_hint, -#else - NULL, -#endif - 0); - } - + 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) { hddLog(LOGE, FL("connect failed")); return status; -- cgit v1.2.3 From 79c99b24f4726feba792ad537ce16b9f474d4be5 Mon Sep 17 00:00:00 2001 From: Sanjay Devnani Date: Mon, 23 Nov 2015 11:42:35 -0800 Subject: qcacld-3.0: Check if unload is in progress during suspend If unload in progress, abort suspend. causes null pointer ref otherwise Change-Id: I7028b6f0efc9da62352b561e9def90ff9bffd5e6 CRs-Fixed: 878755 --- core/cds/inc/cds_api.h | 2 ++ core/cds/src/cds_api.c | 25 +++++++++++++++++++++++++ core/hif/src/ce/ce_main.c | 3 +++ 3 files changed, 30 insertions(+) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index c88068f0e61f..cb30c6eb0e2b 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -81,6 +81,8 @@ uint8_t cds_is_logp_in_progress(void); void cds_set_logp_in_progress(uint8_t value); uint8_t cds_is_load_unload_in_progress(void); +uint8_t cds_is_unload_in_progress(void); + void cds_set_load_unload_in_progress(uint8_t value); CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 6a3d0391ea6f..188bd2a04701 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1089,6 +1089,31 @@ uint8_t cds_is_load_unload_in_progress(void) return gp_cds_context->isLoadUnloadInProgress; } +/** + * cds_is_unload_in_progress() - check if driver unload in + * progress + * + * Return: true if unload is going on else false + */ +uint8_t cds_is_unload_in_progress(void) +{ + hdd_context_t *hdd_ctx = NULL; + if (gp_cds_context == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: global cds context is NULL", __func__); + return 0; + } + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + + if (hdd_ctx == NULL) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: HDD context is NULL", __func__); + return 0; + } + + return hdd_ctx->isUnloadInProgress; +} + /** * cds_set_load_unload_in_progress() - set load/unload in progress * @value: value to set diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 68ce9345f6b6..db5884017770 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1772,6 +1772,9 @@ static void hif_sleep_entry(void *arg) if (scn->recovery) return; + if (cds_is_unload_in_progress()) + return; + cdf_spin_lock_irqsave(&hif_state->keep_awake_lock); if (hif_state->verified_awake == false) { idle_ms = cdf_system_ticks_to_msecs(cdf_system_ticks() -- cgit v1.2.3 From 91ca9d5ee16fe60dacb8017a95cb0947228c7a5a Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Mon, 16 Nov 2015 13:33:07 -0800 Subject: qcacld-3.0: Enable full rx reorder offload for adrastea - In current qcacld-3.0 driver full rx reorder offload is dependent on HIF_PCI feature flag. - HIF_PCI feature flag is compiled out for SNOC devices like adrastea. - Because of RX reorder dependency on HIF_PCI host data path is broken on adrastea. - Enable rx reorder offload for SNOC devices(adrastea). Change-Id: I445afa57fb5fc45363ca644a35ae15e4af5bf94a CRs-Fixed: 939890 --- Kbuild | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Kbuild b/Kbuild index 44cd18ab92d2..79c831f5eb76 100644 --- a/Kbuild +++ b/Kbuild @@ -1270,6 +1270,12 @@ ifeq ($(CONFIG_LINUX_QCMBR),y) CDEFINES += -DLINUX_QCMBR endif + +# Enable full rx re-order offload for adrastea +ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) +CDEFINES += -DWLAN_FEATURE_RX_FULL_REORDER_OL +endif + # NOTE: CONFIG_64BIT_PADDR requires CONFIG_HELIUMPLUS ifeq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) CONFIG_HELIUMPLUS := y -- cgit v1.2.3 From e9a034ded21e83c622f0df9f39cb3f79b092d248 Mon Sep 17 00:00:00 2001 From: mukul sharma Date: Fri, 4 Sep 2015 17:02:01 +0530 Subject: qcacld-3.0: Add support for 11w offload feature This change Adds 11w offload feature, This change includes: 1. SA Query time out Kickout reason handling 2. Add a new service bit map for 11w offload and cache it to pMAc 3. Error logging in following unexpected case a) Unprotected deauth / diasssoc from peer AP, b) reception of SA query action frame in SAP / STA vde mode 4. Configure sta sa query related parameters as a part of sta vdev attach 5. Trim mmie for pmf bcast/mcast mgmt frames Change-Id: If119e9a79185552e163834f7c6c3a14288fe2761 CRs-Fixed: 931630 --- core/mac/inc/ani_global.h | 1 + core/mac/src/pe/lim/lim_process_action_frame.c | 8 ++ core/mac/src/pe/lim/lim_process_deauth_frame.c | 12 ++ core/mac/src/pe/lim/lim_process_disassoc_frame.c | 12 ++ core/sme/src/common/sme_api.c | 3 + core/wma/inc/wma_internal.h | 5 + core/wma/inc/wma_tgt_cfg.h | 1 + core/wma/src/wma_dev_if.c | 7 ++ core/wma/src/wma_main.c | 4 + core/wma/src/wma_mgmt.c | 145 +++++++++++++++++++---- 10 files changed, 173 insertions(+), 25 deletions(-) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index e4e7bbdefcdc..1c98232e7e81 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1021,6 +1021,7 @@ typedef struct sAniSirGlobal { void *readyToSuspendContext; uint8_t lteCoexAntShare; uint8_t beacon_offload; + bool pmf_offload; uint32_t fEnableDebugLog; uint16_t mgmtSeqNum; bool enable5gEBT; diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 15d039276b4d..a7b1b88a5d64 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1534,6 +1534,14 @@ static void __lim_process_sa_query_request_action_frame(tpAniSirGlobal pMac, if (pHdr->fc.wep == 0) return; + /* 11w offload is enabled then firmware should not fwd this frame */ + if (pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enabled, SA Query request is not expected ") + ); + 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: diff --git a/core/mac/src/pe/lim/lim_process_deauth_frame.c b/core/mac/src/pe/lim/lim_process_deauth_frame.c index e64058d28342..2cca55d9f6bd 100644 --- a/core/mac/src/pe/lim/lim_process_deauth_frame.c +++ b/core/mac/src/pe/lim/lim_process_deauth_frame.c @@ -138,6 +138,18 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, (pMac, LOGE, FL("received an unprotected deauth from AP")); ) + + /* + * When 11w offload is enabled then + * firmware should not fwd this frame + */ + if (LIM_IS_STA_ROLE(psessionEntry) && pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enable,unprotected deauth is not expected") + ); + return; + } + /* If the frame received is unprotected, forward it to the supplicant to initiate */ /* an SA query */ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); diff --git a/core/mac/src/pe/lim/lim_process_disassoc_frame.c b/core/mac/src/pe/lim/lim_process_disassoc_frame.c index 33a1c089d232..70a9a8d86c72 100644 --- a/core/mac/src/pe/lim/lim_process_disassoc_frame.c +++ b/core/mac/src/pe/lim/lim_process_disassoc_frame.c @@ -134,6 +134,18 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, (pMac, LOGE, FL("received an unprotected disassoc from AP")); ) + + /* + * When 11w offload is enabled then + * firmware should not fwd this frame + */ + if (LIM_IS_STA_ROLE(psessionEntry) && pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enable,unprotected disassoc is not expected") + ); + return; + } + /* If the frame received is unprotected, forward it to the supplicant to initiate */ /* an SA query */ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index baf6afd3c260..4cfe7d661154 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14870,6 +14870,9 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share; mac_ctx->beacon_offload = cfg->beacon_offload; + mac_ctx->pmf_offload = cfg->pmf_offload; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload); return; } diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d927a7613984..d204979b4e0c 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -44,6 +44,9 @@ WMI_SCAN_EVENT_DEQUEUED) /* default value */ #define DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD 20 +#define DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT (5) +#define DEFAULT_STA_SA_QUERY_RETRY_INTERVAL (200) + /* pdev vdev and peer stats*/ #define FW_PDEV_STATS_SET 0x1 #define FW_VDEV_STATS_SET 0x2 @@ -569,6 +572,8 @@ int wma_unified_bcntx_status_event_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +void wma_set_sta_sa_query_param(tp_wma_handle wma, + uint8_t vdev_id); void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, uint32_t method, uint32_t timeperiod, diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index eab91f69a892..5efa9545d822 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -56,6 +56,7 @@ struct wma_tgt_services { bool pno_offload; #endif /* FEATURE_WLAN_SCAN_PNO */ bool beacon_offload; + bool pmf_offload; uint32_t lte_coex_ant_share; #ifdef FEATURE_WLAN_TDLS bool en_tdls; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index e847cced08cb..b15eb9a32560 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1762,6 +1762,13 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, self_sta_req->session_id, SIR_KEEP_ALIVE_NULL_PKT, cfg_val, NULL, NULL, NULL); + + /* offload STA SA query related params to fwr */ + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_STA_PMF_OFFLOAD)) { + wma_set_sta_sa_query_param(wma_handle, + self_sta_req->session_id); + } break; } diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 9f4c36117018..319e076a975f 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3258,6 +3258,9 @@ static inline void wma_update_target_services(tp_wma_handle wh, if (WMI_SERVICE_IS_ENABLED (wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) cfg->beacon_offload = true; + if (WMI_SERVICE_IS_ENABLED + (wh->wmi_service_bitmap, WMI_SERVICE_STA_PMF_OFFLOAD)) + cfg->pmf_offload = true; #ifdef WLAN_FEATURE_ROAM_OFFLOAD /* Enable Roam Offload */ cfg->en_roam_offload = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, @@ -3385,6 +3388,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) struct wma_tgt_cfg tgt_cfg; void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + cdf_mem_zero(&tgt_cfg, sizeof(struct wma_tgt_cfg)); tgt_cfg.reg_domain = wma_handle->reg_cap.eeprom_rd; tgt_cfg.eeprom_rd_ext = wma_handle->reg_cap.eeprom_rd_ext; diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index b85b51a9faef..89a9e728cb55 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -419,6 +419,8 @@ int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) break; case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY: + /* Handle SA query kickout is same as inactivity kickout */ + case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT: default: break; } @@ -594,6 +596,69 @@ void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id) min_inactive_time, max_inactive_time, max_unresponsive_time); } +/** + * wma_set_sta_sa_query_param() - set sta sa query parameters + * @wma: wma handle + * @vdev_id: vdev id + + * This function sets sta query related parameters in fw. + * + * Return: none + */ + +void wma_set_sta_sa_query_param(tp_wma_handle wma, + uint8_t vdev_id) +{ + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + uint32_t max_retries, retry_interval; + wmi_buf_t buf; + WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *cmd; + int len; + + WMA_LOGD(FL("Enter:")); + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return; + } + + cmd = (WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param)); + + if (wlan_cfg_get_int + (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &max_retries) != eSIR_SUCCESS) { + max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT; + WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES")); + } + if (wlan_cfg_get_int + (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retry_interval) != eSIR_SUCCESS) { + retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL; + WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL")); + } + + cmd->vdev_id = vdev_id; + cmd->sa_query_max_retry_count = max_retries; + cmd->sa_query_retry_interval = retry_interval; + + WMA_LOGD(FL("STA sa query: vdev_id:%d interval:%u retry count:%d"), + vdev_id, retry_interval, max_retries); + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID)) { + WMA_LOGE(FL("Failed to offload STA SA Query")); + cdf_nbuf_free(buf); + } + + WMA_LOGD(FL("Exit :")); + return; +} + /** * wma_set_sta_keep_alive() - set sta keep alive parameters * @wma: wma handle @@ -2914,6 +2979,56 @@ wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh, return false; } +/** + * wma_process_bip() - process mmie in rmf frame + * @wma_handle: wma handle + * @iface: txrx node + * @wh: 80211 frame + * @wbuf: Buffer + * + * Return: 0 for success or error code + */ + +static +int wma_process_bip(tp_wma_handle wma_handle, + struct wma_txrx_node *iface, + struct ieee80211_frame *wh, + cdf_nbuf_t wbuf +) +{ + uint16_t key_id; + uint8_t *efrm; + + efrm = cdf_nbuf_data(wbuf) + cdf_nbuf_len(wbuf); + key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2); + + if (!((key_id == WMA_IGTK_KEY_INDEX_4) + || (key_id == WMA_IGTK_KEY_INDEX_5))) { + WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id); + return -EINVAL; + } + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_STA_PMF_OFFLOAD)) { + /* + * if 11w offload is enabled then mmie validation is performed + * in firmware, host just need to trim the mmie. + */ + cdf_nbuf_trim_tail(wbuf, cds_get_mmie_size()); + } else { + if (cds_is_mmie_valid(iface->key.key, + iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, + (uint8_t *) wh, efrm)) { + WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful")); + /* Remove MMIE */ + cdf_nbuf_trim_tail(wbuf, cds_get_mmie_size()); + } else { + WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame")); + return -EINVAL; + } + } + return 0; +} + /** * wma_process_rmf_frame() - process rmf frame * @wma_handle: wma handle @@ -2931,8 +3046,7 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, cds_pkt_t *rx_pkt, cdf_nbuf_t wbuf) { - uint8_t *efrm, *orig_hdr; - uint16_t key_id; + uint8_t *orig_hdr; uint8_t *ccmp; if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) { @@ -2979,29 +3093,10 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, } else { if (IEEE80211_IS_BROADCAST(wh->i_addr1) || IEEE80211_IS_MULTICAST(wh->i_addr1)) { - efrm = cdf_nbuf_data(wbuf) + - cdf_nbuf_len(wbuf); - - key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2); - if (!((key_id == WMA_IGTK_KEY_INDEX_4) - || (key_id == WMA_IGTK_KEY_INDEX_5))) { - WMA_LOGE("Invalid KeyID(%d) dropping the frame", key_id); - cds_pkt_return_packet(rx_pkt); - return -EINVAL; - } - - if (cds_is_mmie_valid(iface->key.key, - iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, - (uint8_t *) wh, efrm)) { - WMA_LOGE("Protected BC/MC frame MMIE validation successful"); - /* Remove MMIE */ - cdf_nbuf_trim_tail(wbuf, - cds_get_mmie_size()); - } else { - WMA_LOGE("BC/MC MIC error or MMIE not present, dropping the frame"); - cds_pkt_return_packet(rx_pkt); - return -EINVAL; - } + if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) { + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } } else { WMA_LOGE("Rx unprotected unicast mgmt frame"); rx_pkt->pkt_meta.dpuFeedback = -- cgit v1.2.3 From d9082edf70143d0c37a6e6a7e7032dd356a152fc Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Fri, 20 Nov 2015 16:47:45 +0530 Subject: qcacld-3.0: Fix channel width assignment to improper enum value Fix the channel width of type 'enum hw_mode_bandwidth' getting wrongly assigned to enum of type 'tSirWifiChannelWidth'. The tag values of each of these enums are different. CRs-Fixed: 942090 Change-Id: Ic3610e6fcb7c89f0aeed829b83869169f4596ce8 --- core/hdd/src/wlan_hdd_hostapd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index a796d956f781..14a01260702d 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -8270,7 +8270,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx; - tSirWifiChannelWidth channel_width; + enum hw_mode_bandwidth channel_width; int status; uint8_t channel; -- cgit v1.2.3 From 06158912886ea3d82066642caae518a20fe06961 Mon Sep 17 00:00:00 2001 From: Orhan K AKYILDIZ Date: Wed, 11 Nov 2015 18:01:15 -0800 Subject: cld-3.0: Remove warnings issued by static analysis Some of these are very remote scenarios (like HIF not being initialized at the time of the calls, which could then dereference a NULL pointer). There are a few cases of looping beyond boundaries. The scope of this update is limited to NAPI related code. Change-Id: I60229406d5ab514d5465ef2569324d3d4eb430d4 CRs-Fixed: 938253 --- core/dp/txrx/ol_tx.c | 5 ++ core/hdd/src/wlan_hdd_driver_ops.c | 3 +- core/hdd/src/wlan_hdd_ioctl.c | 32 ++++++---- core/hdd/src/wlan_hdd_napi.c | 115 +++++++++++++++++++---------------- core/hif/src/ce/ce_tasklet.c | 11 ++-- core/hif/src/hif_napi.c | 50 +++++++++------ core/hif/src/icnss_stub/icnss_stub.c | 4 +- 7 files changed, 130 insertions(+), 90 deletions(-) diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index fa6a6e516489..42a13c328901 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -133,6 +133,11 @@ cdf_nbuf_t ol_tx_send_data_frame(uint8_t sta_id, cdf_nbuf_t skb, "%s:pdev is null", __func__); return skb; } + if (cdf_unlikely(!cdf_ctx)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s:cdf_ctx is null", __func__); + return skb; + } if (sta_id >= WLAN_MAX_STA_COUNT) { CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_WARN, diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 49432f6ab882..1460850dc538 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -113,7 +113,8 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, if (status <= 0) { hdd_err("NAPI creation error, rc: 0x%x, reinit = %d", status, reinit); - return -EFAULT; + ret = -EFAULT; + goto end; } } diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 8c8ecf43811b..3273d6aab369 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5361,9 +5361,10 @@ static int drv_cmd_get_rssi(hdd_adapter_t *adapter, uint8_t command_len, hdd_priv_data_t *priv_data) { - int ret; + int ret = 0; int8_t rssi = 0; char extra[32]; + uint8_t len = 0; wlan_hdd_get_rssi(adapter, &rssi); @@ -5484,13 +5485,15 @@ int hdd_napi_stats(char *buf, NAPI_DEBUG("-->\n"); + if (NULL == napid) + return n; if (NULL == indp) { from = 0; - to = sizeof(uint32_t) * CE_COUNT_MAX; + to = CE_COUNT_MAX; } else { if (0 > kstrtoint(indp, 10, &to)) { from = 0; - to = sizeof(uint32_t) * CE_COUNT_MAX; + to = CE_COUNT_MAX; } else from = to; } @@ -5534,9 +5537,10 @@ static void napi_set_scale(uint8_t sc) struct qca_napi_data *napi_data; napi_data = hdd_napi_get_all(); - for (i = 0; i < sizeof(uint32_t)*8; i++) - if (napi_data->ce_map & (0x01 << i)) - napi_data->napis[i].scale = sc; + if (likely(NULL != napi_data)) + for (i = 0; i < CE_COUNT_MAX; i++) + if (napi_data->ce_map & (0x01 << i)) + napi_data->napis[i].scale = sc; return; } @@ -5557,7 +5561,7 @@ static void napi_set_scale(uint8_t sc) * NAPI STATS [] : get the stats for a given NAPI instance * NAPI SCALE : set the scale factor * - * Return: 0: success; 0>: failure + * Return: 0: success; !0: failure */ static int drv_cmd_napi(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, @@ -5632,12 +5636,14 @@ static int drv_cmd_napi(hdd_adapter_t *adapter, struct qca_napi_data *napi_data; napi_data = hdd_napi_get_all(); + if (unlikely(NULL == napi_data)) + goto status_end; n += scnprintf(reply+n, MAX_USER_COMMAND_SIZE - n, "NAPI state: 0x%08x map: 0x%08x\n", napi_data->state, napi_data->ce_map); - for (i = 0; i < sizeof(uint32_t)*8; i++) + for (i = 0; i < CE_COUNT_MAX; i++) if (napi_data->ce_map & (0x01 << i)) { n += scnprintf( reply + n, @@ -5647,6 +5653,7 @@ static int drv_cmd_napi(hdd_adapter_t *adapter, napi_data->napis[i].id, napi_data->napis[i].scale); } + status_end: hdd_info("wlan: STATUS DATA:\n%s", reply); if (copy_to_user(priv_data->buf, reply, CDF_MIN(n, priv_data->total_len))) @@ -5656,10 +5663,11 @@ static int drv_cmd_napi(hdd_adapter_t *adapter, struct qca_napi_data *napi_data; napi_data = hdd_napi_get_all(); - n = hdd_napi_stats(reply, MAX_USER_COMMAND_SIZE, - aux, napi_data); - NAPI_DEBUG("STATS: returns %d\n", n); - + if (NULL != napi_data) { + n = hdd_napi_stats(reply, MAX_USER_COMMAND_SIZE, + aux, napi_data); + NAPI_DEBUG("STATS: returns %d\n", n); + } if (n > 0) { if (copy_to_user(priv_data->buf, reply, CDF_MIN(priv_data->total_len, diff --git a/core/hdd/src/wlan_hdd_napi.c b/core/hdd/src/wlan_hdd_napi.c index 4bca8b9a22a3..9f6e64dd8275 100644 --- a/core/hdd/src/wlan_hdd_napi.c +++ b/core/hdd/src/wlan_hdd_napi.c @@ -53,14 +53,16 @@ static struct qca_napi_data *hdd_napi_ctx; */ struct qca_napi_data *hdd_napi_get_all(void) { - struct qca_napi_data *rp; + struct qca_napi_data *rp = NULL; struct ol_softc *hif; NAPI_DEBUG("-->\n"); hif = cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif != NULL); - rp = hif_napi_get_all(hif); + if (unlikely(NULL == hif)) + CDF_ASSERT(NULL != hif); /* WARN */ + else + rp = hif_napi_get_all(hif); NAPI_DEBUG("<-- [addr=%p]\n", rp); return rp; @@ -74,13 +76,14 @@ struct qca_napi_data *hdd_napi_get_all(void) */ static uint32_t hdd_napi_get_map(void) { - uint32_t map; + uint32_t map = 0; NAPI_DEBUG("-->\n"); /* cache once, use forever */ if (hdd_napi_ctx == NULL) hdd_napi_ctx = hdd_napi_get_all(); - map = hdd_napi_ctx->ce_map; + if (hdd_napi_ctx != NULL) + map = hdd_napi_ctx->ce_map; NAPI_DEBUG("<--[map=0x%08x]\n", map); return map; @@ -105,35 +108,36 @@ int hdd_napi_create(void) int ul_polled, dl_polled; int rc = 0; - hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif_ctx != NULL); - NAPI_DEBUG("-->\n"); - /* - * hif_service_to_pipe currently returns one pipe id per service. - * However for Adrestea, we will need to figure out how to map - * DATA service to multiple pipes. Either we will need to create - * family of services, or this function may return a bitmap (of - * at least #MAX_CEs bits) and then we will need to iterate on - * the bitmap for hif_napi_create() calls. - * For Rome, there is only one service, so there is a single call - * TODO: clarify for multi-queue/Adrestea - */ - if (CDF_STATUS_SUCCESS != - hif_map_service_to_pipe(hif_ctx, HTT_DATA_MSG_SVC, - &ul, &dl, &ul_polled, &dl_polled)) { - hdd_err("cannot map service to pipe"); - rc = -EINVAL; + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + if (unlikely(NULL == hif_ctx)) { + CDF_ASSERT(NULL != hif_ctx); + rc = -EFAULT; } else { - rc = hif_napi_create(hif_ctx, dl, hdd_napi_poll, - QCA_NAPI_BUDGET, QCA_NAPI_DEF_SCALE); - if (rc < 0) - hdd_err("ERR(%d) creating NAPI on pipe %d", rc, dl); - else { - hdd_info("napi instance %d created on pipe %d", - rc, dl); - /* rc = (0x01 << rc); -- phase 2 */ + /* + * Note: hif_service_to_pipe returns one pipe id per service. + * For multi-queue NAPI for Adrastea, we will use multiple + * services/calls. + * For Rome, there is only one service, hence a single call + */ + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(hif_ctx, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + hdd_err("cannot map service to pipe"); + rc = -EINVAL; + } else { + rc = hif_napi_create(hif_ctx, dl, hdd_napi_poll, + QCA_NAPI_BUDGET, + QCA_NAPI_DEF_SCALE); + if (rc < 0) + hdd_err("ERR(%d) creating NAPI on pipe %d", + rc, dl); + else { + hdd_info("napi instance %d created on pipe %d", + rc, dl); + /* rc = (0x01 << rc); -- phase 2 */ + } } } NAPI_DEBUG("<-- [rc=%d]\n", rc); @@ -163,19 +167,21 @@ int hdd_napi_destroy(int force) struct ol_softc *hif_ctx; hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif_ctx != NULL); - - for (i = 0; i < (sizeof(uint32_t)*8); i++) - if (hdd_napi_map & (0x01 << i)) { - if (0 <= hif_napi_destroy(hif_ctx, - NAPI_PIPE2ID(i), - force)) { - rc++; - hdd_napi_map &= ~(0x01 << i); - } else - hdd_err("cannot destroy napi inst %d: (pipe:%d), f=%d\n", - i, NAPI_PIPE2ID(i), force); - } + if (unlikely(NULL == hif_ctx)) + CDF_ASSERT(NULL != hif_ctx); + else + for (i = 0; i < CE_COUNT_MAX; i++) + if (hdd_napi_map & (0x01 << i)) { + if (0 <= hif_napi_destroy( + hif_ctx, + NAPI_PIPE2ID(i), force)) { + rc++; + hdd_napi_map &= ~(0x01 << i); + } else + hdd_err("cannot destroy napi %d: (pipe:%d), f=%d\n", + i, + NAPI_PIPE2ID(i), force); + } } /* if all instances are removed, it is likely that hif_context has been @@ -199,16 +205,19 @@ int hdd_napi_destroy(int force) * int: 0 = false (NOT enabled) * !0 = true (enabbled) */ -inline int hdd_napi_enabled(int id) +int hdd_napi_enabled(int id) { struct ol_softc *hif; + int rc = 0; /* NOT enabled */ hif = cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif != NULL); - if (-1 == id) - return hif_napi_enabled(hif, id); + if (unlikely(NULL == hif)) + CDF_ASSERT(hif != NULL); /* WARN_ON; rc = 0 */ + else if (-1 == id) + rc = hif_napi_enabled(hif, id); else - return hif_napi_enabled(hif, NAPI_ID2PIPE(id)); + rc = hif_napi_enabled(hif, NAPI_ID2PIPE(id)); + return rc; } /** @@ -229,14 +238,16 @@ inline int hdd_napi_enabled(int id) */ int hdd_napi_event(enum qca_napi_event event, void *data) { - int rc; + int rc = -EFAULT; /* assume err */ struct ol_softc *hif; NAPI_DEBUG("-->(event=%d, aux=%p)\n", event, data); hif = cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif != NULL); - rc = hif_napi_event(hif, event, data); + if (unlikely(NULL == hif)) + CDF_ASSERT(hif != NULL); + else + rc = hif_napi_event(hif, event, data); NAPI_DEBUG("<--[rc=%d]\n", rc); return rc; diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c index 420905909a2b..06501d5e42f6 100644 --- a/core/hif/src/ce/ce_tasklet.c +++ b/core/hif/src/ce/ce_tasklet.c @@ -170,7 +170,7 @@ void init_tasklet_workers(void) */ static inline void ce_schedule_tasklet(struct ce_tasklet_entry *tasklet_entry) { - if (work_initialized && (tasklet_entry->ce_id <= CE_ID_MAX)) + if (work_initialized && (tasklet_entry->ce_id < CE_ID_MAX)) schedule_work(&tasklet_workers[tasklet_entry->ce_id].work); else HIF_ERROR("%s: work_initialized = %d, ce_id = %d", @@ -285,16 +285,19 @@ static irqreturn_t ce_irq_handler(int irq, void *context) struct ce_tasklet_entry *tasklet_entry = context; struct HIF_CE_state *hif_ce_state = tasklet_entry->hif_ce_state; struct ol_softc *scn = hif_ce_state->scn; - int ce_id = icnss_get_ce_id(irq); uint32_t host_status; - + int ce_id = icnss_get_ce_id(irq); if (tasklet_entry->ce_id != ce_id) { HIF_ERROR("%s: ce_id (expect %d, received %d) does not match", __func__, tasklet_entry->ce_id, ce_id); return IRQ_NONE; } - + if (unlikely(ce_id >= CE_COUNT_MAX)) { + HIF_ERROR("%s: ce_id=%d > CE_COUNT_MAX=%d", + __func__, tasklet_entry->ce_id, CE_COUNT_MAX); + return IRQ_NONE; + } #ifndef HIF_PCI disable_irq_nosync(irq); #endif diff --git a/core/hif/src/hif_napi.c b/core/hif/src/hif_napi.c index 8b194c812388..2ef3dfd7c3bb 100644 --- a/core/hif/src/hif_napi.c +++ b/core/hif/src/hif_napi.c @@ -113,7 +113,8 @@ int hif_napi_create(struct ol_softc *hif, napid->netdev.napi_list.prev, napid->netdev.napi_list.next); /* It is OK to change the state variable below without protection - as there should be no-one around yet */ + * as there should be no-one around yet + */ napid->ce_map |= (0x01 << pipe_id); HIF_INFO("%s: NAPI id %d created for pipe %d\n", __func__, napii->id, pipe_id); @@ -162,6 +163,7 @@ int hif_napi_destroy(struct ol_softc *hif, } else { struct qca_napi_data *napid; struct qca_napi_info *napii; + napid = &(hif->napi_data); napii = &(napid->napis[ce]); @@ -193,8 +195,9 @@ int hif_napi_destroy(struct ol_softc *hif, HIF_INFO("%s: NAPI %d destroyed\n", __func__, id); /* if there are no active instances and - if they are all destroyed, - set the whole structure to uninitialized state */ + * if they are all destroyed, + * set the whole structure to uninitialized state + */ if (napid->ce_map == 0) { /* hif->napi_data.state = 0; */ memset(napid, @@ -258,6 +261,7 @@ int hif_napi_event(struct ol_softc *hif, enum qca_napi_event event, void *data) case NAPI_EVT_INI_FILE: case NAPI_EVT_CMD_STATE: { int on = (data != ((void *)0)); + HIF_INFO("%s: received evnt: CONF %s; v = %d (state=0x%0x)\n", __func__, (event == NAPI_EVT_INI_FILE)?".ini file":"cmd", @@ -328,9 +332,10 @@ int hif_napi_event(struct ol_softc *hif, enum qca_napi_event event, void *data) * * Return: bool */ -inline int hif_napi_enabled(struct ol_softc *hif, int ce) +int hif_napi_enabled(struct ol_softc *hif, int ce) { int rc; + if (-1 == ce) rc = ((hif->napi_data.state == ENABLE_NAPI_MASK)); else @@ -350,7 +355,6 @@ inline int hif_napi_enabled(struct ol_softc *hif, int ce) inline void hif_napi_enable_irq(struct ol_softc *hif, int id) { ce_irq_enable(hif, NAPI_ID2PIPE(id)); - return; } @@ -396,7 +400,8 @@ int hif_napi_schedule(struct ol_softc *scn, int ce_id) */ int hif_napi_poll(struct napi_struct *napi, int budget) { - int rc, normalized, bucket; + int rc = 0; /* default: no work done, also takes care of error */ + int normalized, bucket; int cpu = smp_processor_id(); struct ol_softc *hif; struct qca_napi_info *napi_info; @@ -409,27 +414,32 @@ int hif_napi_poll(struct napi_struct *napi, int budget) napi_info->stats[cpu].napi_polls++; hif = (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); - CDF_ASSERT(hif != NULL); - rc = ce_per_engine_service(hif, NAPI_ID2PIPE(napi_info->id)); - HIF_INFO_HI("%s: ce_per_engine_service reports %d msgs processed", - __func__, rc); + if (unlikely(NULL == hif)) + CDF_ASSERT(hif != NULL); /* emit a warning if hif NULL */ + else { + rc = ce_per_engine_service(hif, NAPI_ID2PIPE(napi_info->id)); + HIF_INFO_HI("%s: ce_per_engine_service processed %d msgs", + __func__, rc); + } napi_info->stats[cpu].napi_workdone += rc; normalized = (rc / napi_info->scale); - ce_state = hif->ce_id_to_state[NAPI_ID2PIPE(napi_info->id)]; - if (ce_state->lro_flush_cb != NULL) { - ce_state->lro_flush_cb(ce_state->lro_data); + if (NULL != hif) { + ce_state = hif->ce_id_to_state[NAPI_ID2PIPE(napi_info->id)]; + if (ce_state->lro_flush_cb != NULL) { + ce_state->lro_flush_cb(ce_state->lro_data); + } } /* do not return 0, if there was some work done, - even if it is below the scale */ + * even if it is below the scale + */ if (rc) normalized++; bucket = (normalized / QCA_NAPI_DEF_SCALE); napi_info->stats[cpu].napi_budget_uses[bucket]++; - /* if ce_per engine reports 0, then we should make sure - poll is terminated */ + /* if ce_per engine reports 0, then poll should be terminated */ if (0 == rc) NAPI_DEBUG("%s:%d: nothing processed by CE. Completing NAPI\n", __func__, __LINE__); @@ -438,10 +448,12 @@ int hif_napi_poll(struct napi_struct *napi, int budget) napi_info->stats[cpu].napi_completes++; /* enable interrupts */ napi_complete(napi); - hif_napi_enable_irq(hif, napi_info->id); + if (NULL != hif) { + hif_napi_enable_irq(hif, napi_info->id); - /* support suspend/resume */ - cdf_atomic_dec(&(hif->active_tasklet_cnt)); + /* support suspend/resume */ + cdf_atomic_dec(&(hif->active_tasklet_cnt)); + } NAPI_DEBUG("%s:%d: napi_complete + enabling the interrupts\n", __func__, __LINE__); diff --git a/core/hif/src/icnss_stub/icnss_stub.c b/core/hif/src/icnss_stub/icnss_stub.c index 956b4569406d..484d1e2cb738 100644 --- a/core/hif/src/icnss_stub/icnss_stub.c +++ b/core/hif/src/icnss_stub/icnss_stub.c @@ -323,7 +323,7 @@ int icnss_get_soc_info(struct icnss_soc_info *info) */ static int icnss_get_irq_num(int ce_id) { - if (ce_id <= ICNSS_MAX_IRQ_REGISTRATIONS && ce_id >= 0) + if (ce_id < CE_COUNT_MAX && ce_id >= 0) return ce_id + 100; pr_err("icnss: No irq registered for CE id %d\n", ce_id); @@ -333,7 +333,7 @@ static int icnss_get_irq_num(int ce_id) int icnss_get_ce_id(int irq) { int ce_id = irq - 100; - if (ce_id <= ICNSS_MAX_IRQ_REGISTRATIONS && ce_id >= 0) + if (ce_id < CE_COUNT_MAX && ce_id >= 0) return ce_id; pr_err("icnss: No matching CE id for irq %d\n", irq); -- cgit v1.2.3 From 98c0a9557c304407f32ba1b4ef409a935fb753fc Mon Sep 17 00:00:00 2001 From: Sushant Kaushik Date: Wed, 22 Jul 2015 12:40:45 +0530 Subject: qcacld-3.0: Allow addTspec in 11b mode. qcacld-2.0 to qcacld-3.0 propagation Currently if sta is connected to an AP which only supports 11b, lim doesn't send addTspec request to that AP. Specs doesn't restrict Tspec in 11b. As a part of fix, allow addTspec in 11b. CRs-Fixed: 847755 Change-Id: I57c2d5139f9861140ab3bbe8314a1a3fe3e80e19 --- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index b0b85524b5fb..537e9223c152 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3762,17 +3762,6 @@ static void __lim_process_sme_addts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) smesessionId, smetransactionId); return; } - /* Ignore the request if STA is in 11B mode. */ - if (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) { - PELOGE(lim_log - (pMac, LOGE, - "AddTS received while Dot11Mode is 11B - ignoring"); - ) - lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, - psessionEntry, pSirAddts->req.tspec, - smesessionId, smetransactionId); - return; - } pStaDs = dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, -- cgit v1.2.3 From ca91b29e62c819eec490f1c859516bce49183802 Mon Sep 17 00:00:00 2001 From: Sachin Ahuja Date: Mon, 16 Nov 2015 15:15:49 +0530 Subject: qcacld-3.0: Avoid sending positive RSSI value to framework. qcacld-2.0 to qcacld-3.0 propagation Currently if STA is very near to connected AP, it sends the positive value of RSSI to framework. Framework checks this RSSI and if positive(greater than 0) then it consider RSSI as -127dbm which may lead to disconnection. So changes are done to avoid sending the positive RSSI value greater than 0. Change-Id: Ib417f48345e3f78dba54d68969fa15d294f313b9 CRs-Fixed: 842243 --- core/hdd/src/wlan_hdd_wext.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index bb16e8f222ad..064dbdceb654 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1014,6 +1014,9 @@ static void hdd_get_rssi_cb(int8_t rssi, uint32_t staId, void *pContext) /* copy over the rssi */ pAdapter->rssi = rssi; + if (pAdapter->rssi > 0) + pAdapter->rssi = 0; + /* notify the caller */ complete(&pStatsContext->completion); -- cgit v1.2.3 From 8ffa61779e07c72c551331857bac8de75507d275 Mon Sep 17 00:00:00 2001 From: Sachin Ahuja Date: Mon, 16 Nov 2015 15:11:39 +0530 Subject: qcacld-3.0: Increase the rate array for extended rate set. qcacld-2.0 to qcacld-3.0 propagation Currently while populating ext rate set, local rate array has size as 8.But max 12 ext rates can be copied in this local rate array.If it is greater than 8, then it leads to crash. To resolve this issue, increase the local rate array from 8 to 12. Change-Id: I2097cc4feb7fa669a970de5463130bb4bbf6401c CRs-Fixed: 903816 --- core/mac/src/sys/legacy/src/utils/src/parser_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 3062e7561d05..42e618d60671 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -568,7 +568,7 @@ populate_dot11f_ext_supp_rates(tpAniSirGlobal pMac, uint8_t nChannelNum, { tSirRetStatus nSirStatus; uint32_t nRates = 0; - uint8_t rates[WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN]; + uint8_t 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 -- cgit v1.2.3 From 2ffb5ebb6cb7c88c9bf0ce0a7fc4b8f3e71500eb Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Mon, 23 Nov 2015 16:28:38 -0800 Subject: Release 5.0.0.146 Release 5.0.0.146 Change-Id: Iaf2bfeee2b5ca2b66165808d9a69ecd2472a09cd CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 2eff3e8a0a40..418a536c9977 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 145 +#define QWLAN_VERSION_BUILD 146 -#define QWLAN_VERSIONSTR "5.0.0.145" +#define QWLAN_VERSIONSTR "5.0.0.146" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 3031a86c694c8c3854fcaa9c90ee89c9bbf207bd Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 25 Nov 2015 19:57:38 -0800 Subject: qcacld-3.0: Add compilation flag for qcacld3.0 Add compilation flag for qcacld3.0 Change-Id: Ic779d6d133c6bb7ca51f7806e1c2694ff537bbae CRs-Fixed: 894947 --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 0f020f36a5fc..791ae84cfd46 100644 --- a/Android.mk +++ b/Android.mk @@ -7,7 +7,7 @@ ifeq ($(BOARD_HAS_QCOM_WLAN), true) # Build/Package options for 8084/8092/8960/8992/8994 target ifeq ($(call is-board-platform-in-list, apq8084 mpq8092 msm8960 msm8992 msm8994 msm8996 msm8998),true) - WLAN_CHIPSET := qca_cld + WLAN_CHIPSET := qca_cld3 WLAN_SELECT := CONFIG_QCA_CLD_WLAN=m endif # platform -- cgit v1.2.3 From 19a7dd28f5fa7834285597278564da240b15f941 Mon Sep 17 00:00:00 2001 From: Leo Chang Date: Fri, 13 Nov 2015 13:35:15 -0800 Subject: qcacld-3.0: qcacld-2.0: replace semaphore to completion qcacld-2.0 to qcacld-3.0 propagation HTC RX event wait semaphore waiting event infinte. Infinte waiting will hang device and cannot getting out from system hang. To collect FW RAM dump and make correct panic, semaphore should be replaced with time limitted compeletion Change-Id: Idabfc7916676c9e986e953b50108653a5b394278 CRs-fixed: 924387 --- core/htc/htc_internal.h | 2 +- core/htc/htc_recv.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/htc/htc_internal.h b/core/htc/htc_internal.h index 2e48b790d4c2..b7a526ec6464 100644 --- a/core/htc/htc_internal.h +++ b/core/htc/htc_internal.h @@ -162,7 +162,7 @@ typedef struct _HTC_TARGET { HTC_PACKET_QUEUE ControlBufferTXFreeList; A_UINT8 CtrlResponseBuffer[HTC_MAX_CONTROL_MESSAGE_LENGTH]; int CtrlResponseLength; - cdf_semaphore_t CtrlResponseValid; + cdf_event_t ctrl_response_valid; A_BOOL CtrlResponseProcessing; int TotalTransmitCredits; HTC_SERVICE_TX_CREDIT_ALLOCATION diff --git a/core/htc/htc_recv.c b/core/htc/htc_recv.c index 38f13768f1dd..ad0644ce69ab 100644 --- a/core/htc/htc_recv.c +++ b/core/htc/htc_recv.c @@ -31,6 +31,9 @@ #include /* cdf_nbuf_t */ #include "epping_main.h" +/* HTC Control message receive timeout msec */ +#define HTC_CONTROL_RX_TIMEOUT 3000 + #ifdef DEBUG void debug_dump_bytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) { @@ -433,9 +436,7 @@ CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, target->CtrlResponseProcessing = true; UNLOCK_HTC_RX(target); - cdf_semaphore_release(target->osdev, - &target-> - CtrlResponseValid); + cdf_event_set(&target->ctrl_response_valid); break; case HTC_MSG_SEND_SUSPEND_COMPLETE: wow_nack = 0; @@ -599,9 +600,8 @@ void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint) void htc_recv_init(HTC_TARGET *target) { - /* Initialize CtrlResponseValid to block */ - cdf_semaphore_init(&target->CtrlResponseValid); - cdf_semaphore_acquire(target->osdev, &target->CtrlResponseValid); + /* Initialize ctrl_response_valid to block */ + cdf_event_init(&target->ctrl_response_valid); } /* polling routine to wait for a control packet to be received */ @@ -612,7 +612,10 @@ A_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target) AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCWaitCtrlMessageRecv\n")); /* Wait for BMI request/response transaction to complete */ - while (cdf_semaphore_acquire(target->osdev, &target->CtrlResponseValid)) { + if (cdf_wait_single_event(&target->ctrl_response_valid, + cdf_system_msecs_to_ticks(HTC_CONTROL_RX_TIMEOUT))) { + CDF_BUG(0); + return A_ERROR; } LOCK_HTC_RX(target); -- cgit v1.2.3 From f24b357bf8122b7ab4a0cb8d6f8bc68e11088eb0 Mon Sep 17 00:00:00 2001 From: Leo Chang Date: Fri, 23 Oct 2015 14:19:02 -0700 Subject: qcacld-3.0: optimize data path memory allocation When allocate HTT descriptor, instead of allocating large single chunk of memory, allocate small sized multiple chunk of memory. Then not need to allocate order 5 memory. Will have less chance to have memory alloc fail problem. HTT descriptor. Frag descriptor. OL descriptor. TSO descriptor Change-Id: Ib9d4a3f10adbc0656e1418cf3a67429322bb7164 CRs-fixed: 845666 --- core/cdf/inc/cdf_memory.h | 37 ++++ core/cdf/inc/cdf_util.h | 30 +++ core/cdf/src/cdf_memory.c | 149 ++++++++++++++ core/dp/htt/htt_h2t.c | 6 +- core/dp/htt/htt_rx.c | 20 +- core/dp/htt/htt_tx.c | 444 +++++++++++++++++++++++++++++------------ core/dp/htt/htt_types.h | 10 +- core/dp/ol/inc/ol_htt_tx_api.h | 28 ++- core/dp/txrx/ol_tx.c | 45 ++--- core/dp/txrx/ol_tx.h | 10 + core/dp/txrx/ol_tx_desc.c | 12 +- core/dp/txrx/ol_tx_desc.h | 18 +- core/dp/txrx/ol_tx_send.c | 22 +- core/dp/txrx/ol_txrx.c | 208 ++++++++++--------- core/dp/txrx/ol_txrx_types.h | 13 +- 15 files changed, 726 insertions(+), 326 deletions(-) diff --git a/core/cdf/inc/cdf_memory.h b/core/cdf/inc/cdf_memory.h index 7380089214ea..e6c77cfebd66 100644 --- a/core/cdf/inc/cdf_memory.h +++ b/core/cdf/inc/cdf_memory.h @@ -37,6 +37,32 @@ /* Include Files */ #include +/** + * struct cdf_mem_dma_page_t - Allocated dmaable page + * @page_v_addr_start: Page start virtual address + * @page_v_addr_end: Page end virtual address + * @page_p_addr: Page start physical address + */ +struct cdf_mem_dma_page_t { + char *page_v_addr_start; + char *page_v_addr_end; + cdf_dma_addr_t page_p_addr; +}; + +/** + * struct cdf_mem_multi_page_t - multiple page allocation information storage + * @num_element_per_page: Number of element in single page + * @num_pages: Number of allocation needed pages + * @dma_pages: page information storage in case of coherent memory + * @cacheable_pages: page information storage in case of cacheable memory + */ +struct cdf_mem_multi_page_t { + uint16_t num_element_per_page; + uint16_t num_pages; + struct cdf_mem_dma_page_t *dma_pages; + void **cacheable_pages; +}; + /* Preprocessor definitions and constants */ #ifdef MEMORY_DEBUG @@ -222,4 +248,15 @@ static inline int32_t cdf_str_len(const char *str) return strlen(str); } +void cdf_mem_multi_pages_alloc(cdf_device_t osdev, + struct cdf_mem_multi_page_t *pages, + size_t element_size, + uint16_t element_num, + cdf_dma_context_t memctxt, + bool cacheable); + +void cdf_mem_multi_pages_free(cdf_device_t osdev, + struct cdf_mem_multi_page_t *pages, + cdf_dma_context_t memctxt, + bool cacheable); #endif /* __CDF_MEMORY_H */ diff --git a/core/cdf/inc/cdf_util.h b/core/cdf/inc/cdf_util.h index c00ac564833f..2318d6651a6e 100644 --- a/core/cdf/inc/cdf_util.h +++ b/core/cdf/inc/cdf_util.h @@ -106,6 +106,14 @@ CDF_INLINE_FN int cdf_status_to_os_return(CDF_STATUS status) #define cdf_container_of(ptr, type, member) \ __cdf_container_of(ptr, type, member) +/** + * cdf_is_pwr2 - test input value is power of 2 integer + * + * @value: input integer + * + */ +#define CDF_IS_PWR2(value) (((value) ^ ((value)-1)) == ((value) << 1) - 1) + /** * cdf_is_macaddr_equal() - compare two CDF MacAddress * @pMacAddr1: Pointer to one cdf MacAddress to compare @@ -322,4 +330,26 @@ CDF_INLINE_FN uint8_t *cdf_get_u32(uint8_t *ptr, uint32_t *pValue) return ptr + 4; } +/** + * cdf_get_pwr2() - get next power of 2 integer from input value + * @value: input value to find next power of 2 integer + * + * Get next power of 2 integer from input value + * + * Return: Power of 2 integer + */ +CDF_INLINE_FN int cdf_get_pwr2(int value) +{ + int log2; + if (CDF_IS_PWR2(value)) + return value; + + log2 = 0; + while (value) { + value >>= 1; + log2++; + } + return 1 << log2; +} + #endif /*_CDF_UTIL_H*/ diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c index 2aba419f6477..71dd46181d40 100644 --- a/core/cdf/src/cdf_memory.c +++ b/core/cdf/src/cdf_memory.c @@ -374,6 +374,154 @@ void cdf_mem_free(void *ptr) } #endif +/** + * cdf_mem_multi_pages_alloc() - allocate large size of kernel memory + * @osdev: OS device handle pointer + * @pages: Multi page information storage + * @element_size: Each element size + * @element_num: Total number of elements should be allocated + * @memctxt: Memory context + * @cacheable: Coherent memory or cacheable memory + * + * This function will allocate large size of memory over multiple pages. + * Large size of contiguous memory allocation will fail frequentely, then + * instead of allocate large memory by one shot, allocate through multiple, non + * contiguous memory and combine pages when actual usage + * + * Return: None + */ +void cdf_mem_multi_pages_alloc(cdf_device_t osdev, + struct cdf_mem_multi_page_t *pages, + size_t element_size, + uint16_t element_num, + cdf_dma_context_t memctxt, + bool cacheable) +{ + uint16_t page_idx; + struct cdf_mem_dma_page_t *dma_pages; + void **cacheable_pages = NULL; + uint16_t i; + + pages->num_element_per_page = PAGE_SIZE / element_size; + if (!pages->num_element_per_page) { + cdf_print("Invalid page %d or element size %d", + (int)PAGE_SIZE, (int)element_size); + goto out_fail; + } + + pages->num_pages = element_num / pages->num_element_per_page; + if (element_num % pages->num_element_per_page) + pages->num_pages++; + + if (cacheable) { + /* Pages information storage */ + pages->cacheable_pages = cdf_mem_malloc( + pages->num_pages * sizeof(pages->cacheable_pages)); + if (!pages->cacheable_pages) { + cdf_print("Cacheable page storage alloc fail"); + goto out_fail; + } + + cacheable_pages = pages->cacheable_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + cacheable_pages[page_idx] = cdf_mem_malloc(PAGE_SIZE); + if (!cacheable_pages[page_idx]) { + cdf_print("cacheable page alloc fail, pi %d", + page_idx); + goto page_alloc_fail; + } + } + pages->dma_pages = NULL; + } else { + pages->dma_pages = cdf_mem_malloc( + pages->num_pages * sizeof(struct cdf_mem_dma_page_t)); + if (!pages->dma_pages) { + cdf_print("dmaable page storage alloc fail"); + goto out_fail; + } + + dma_pages = pages->dma_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + dma_pages->page_v_addr_start = + cdf_os_mem_alloc_consistent(osdev, PAGE_SIZE, + &dma_pages->page_p_addr, memctxt); + if (!dma_pages->page_v_addr_start) { + cdf_print("dmaable page alloc fail pi %d", + page_idx); + goto page_alloc_fail; + } + dma_pages->page_v_addr_end = + dma_pages->page_v_addr_start + PAGE_SIZE; + dma_pages++; + } + pages->cacheable_pages = NULL; + } + return; + +page_alloc_fail: + if (cacheable) { + for (i = 0; i < page_idx; i++) + cdf_mem_free(pages->cacheable_pages[i]); + cdf_mem_free(pages->cacheable_pages); + } else { + dma_pages = pages->dma_pages; + for (i = 0; i < page_idx; i++) { + cdf_os_mem_free_consistent(osdev, PAGE_SIZE, + dma_pages->page_v_addr_start, + dma_pages->page_p_addr, memctxt); + dma_pages++; + } + cdf_mem_free(pages->dma_pages); + } + +out_fail: + pages->cacheable_pages = NULL; + pages->dma_pages = NULL; + pages->num_pages = 0; + return; +} + +/** + * cdf_mem_multi_pages_free() - free large size of kernel memory + * @osdev: OS device handle pointer + * @pages: Multi page information storage + * @memctxt: Memory context + * @cacheable: Coherent memory or cacheable memory + * + * This function will free large size of memory over multiple pages. + * + * Return: None + */ +void cdf_mem_multi_pages_free(cdf_device_t osdev, + struct cdf_mem_multi_page_t *pages, + cdf_dma_context_t memctxt, + bool cacheable) +{ + unsigned int page_idx; + struct cdf_mem_dma_page_t *dma_pages; + + if (cacheable) { + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) + cdf_mem_free(pages->cacheable_pages[page_idx]); + cdf_mem_free(pages->cacheable_pages); + } else { + dma_pages = pages->dma_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + cdf_os_mem_free_consistent(osdev, PAGE_SIZE, + dma_pages->page_v_addr_start, + dma_pages->page_p_addr, memctxt); + dma_pages++; + } + cdf_mem_free(pages->dma_pages); + } + + pages->cacheable_pages = NULL; + pages->dma_pages = NULL; + pages->num_pages = 0; + return; +} + + /** * cdf_mem_set() - set (fill) memory with a specified byte value. * @pMemory: Pointer to memory that will be set @@ -629,3 +777,4 @@ cdf_os_mem_dma_sync_single_for_device(cdf_device_t osdev, { dma_sync_single_for_device(osdev->dev, bus_addr, size, direction); } + diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index 437460ca0d27..d5dcc8de835a 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -154,10 +154,12 @@ A_STATUS htt_h2t_frag_desc_bank_cfg_msg(struct htt_pdev_t *pdev) /** Bank specific data structure.*/ #if HTT_PADDR64 - bank_cfg->bank_base_address[0].lo = pdev->frag_descs.pool_paddr; + bank_cfg->bank_base_address[0].lo = + pdev->frag_descs.desc_pages.dma_pages->page_p_addr; bank_cfg->bank_base_address[0].hi = 0; #else /* ! HTT_PADDR64 */ - bank_cfg->bank_base_address[0] = pdev->frag_descs.pool_paddr; + bank_cfg->bank_base_address[0] = + pdev->frag_descs.desc_pages.dma_pages->page_p_addr; #endif /* HTT_PADDR64 */ /* Logical Min index */ HTT_H2T_FRAG_DESC_BANK_MIN_IDX_SET(bank_cfg->bank_info[0], 0); diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index c82f7a106517..cabd1633edbf 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -149,20 +149,6 @@ void htt_rx_hash_deinit(struct htt_pdev_t *pdev) pdev->rx_ring.hash_table = NULL; } -static int ceil_pwr2(int value) -{ - int log2; - if (IS_PWR2(value)) - return value; - - log2 = 0; - while (value) { - value >>= 1; - log2++; - } - return 1 << log2; -} - static bool htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc) { @@ -206,7 +192,7 @@ static int htt_rx_ring_size(struct htt_pdev_t *pdev) else if (size > HTT_RX_RING_SIZE_MAX) size = HTT_RX_RING_SIZE_MAX; - size = ceil_pwr2(size); + size = cdf_get_pwr2(size); return size; } @@ -2064,7 +2050,7 @@ int htt_rx_hash_init(struct htt_pdev_t *pdev) { int i, j; - HTT_ASSERT2(IS_PWR2(RX_NUM_HASH_BUCKETS)); + HTT_ASSERT2(CDF_IS_PWR2(RX_NUM_HASH_BUCKETS)); pdev->rx_ring.hash_table = cdf_mem_malloc(RX_NUM_HASH_BUCKETS * @@ -2150,7 +2136,7 @@ int htt_rx_attach(struct htt_pdev_t *pdev) uint32_t ring_elem_size = sizeof(uint32_t); #endif /* HTT_PADDR64 */ pdev->rx_ring.size = htt_rx_ring_size(pdev); - HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size)); + HTT_ASSERT2(CDF_IS_PWR2(pdev->rx_ring.size)); pdev->rx_ring.size_mask = pdev->rx_ring.size - 1; /* diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index dc25cbc2e000..3b278036a5c0 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -48,6 +48,7 @@ #include /* ol_cfg_netbuf_frags_max, etc. */ #include /* HTT_TX_DESC_VADDR_OFFSET */ #include /* ol_tx_msdu_id_storage */ +#include #include /* IPA Micro controler TX data packet HTT Header Preset */ @@ -65,25 +66,42 @@ */ #define HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT 0x07C04001 +#if HTT_PADDR64 +#define HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(frag_filed_ptr) \ +do { \ + frag_filed_ptr++; \ + /* frags_desc_ptr.hi */ \ + *frag_filed_ptr = 0; \ +} while (0) +#else +#define HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(frag_filed_ptr) {} +#endif + /*--- setup / tear-down functions -------------------------------------------*/ #ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS uint32_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, pool_size; - uint32_t **p; - cdf_dma_addr_t pool_paddr; +static cdf_dma_addr_t htt_tx_get_paddr(htt_pdev_handle pdev, + char *target_vaddr); -#if defined(HELIUMPLUS_PADDR64) +#ifdef HELIUMPLUS +/** + * htt_tx_desc_get_size() - get tx descripotrs size + * @pdev: htt device instance pointer + * + * This function will get HTT TX descriptor size and fragment descriptor size + * + * Return: None + */ +static void htt_tx_desc_get_size(struct htt_pdev_t *pdev) +{ pdev->tx_descs.size = sizeof(struct htt_host_tx_desc_t); - if (HTT_WIFI_IP_VERSION(pdev->wifi_ip_ver.major, 0x2)) { /* - * sizeof MSDU_EXT/Fragmentation descriptor. - */ + * sizeof MSDU_EXT/Fragmentation descriptor. + */ pdev->frag_descs.size = sizeof(struct msdu_ext_desc_t); } else { /* @@ -96,7 +114,130 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev)+1) * 8 + 4; } -#else /* ! defined(HELIUMPLUS_PADDR64) */ +} + +/** + * htt_tx_frag_desc_field_update() - Update fragment descriptor field + * @pdev: htt device instance pointer + * @fptr: Fragment descriptor field pointer + * @index: Descriptor index to find page and offset + * @desc_v_ptr: descriptor virtual pointot to find offset + * + * This function will update fragment descriptor field with actual fragment + * descriptor stating physical pointer + * + * Return: None + */ +static void htt_tx_frag_desc_field_update(struct htt_pdev_t *pdev, + uint32_t *fptr, unsigned int index, + struct htt_tx_msdu_desc_t *desc_v_ptr) +{ + unsigned int target_page; + unsigned int offset; + struct cdf_mem_dma_page_t *dma_page; + + target_page = index / pdev->frag_descs.desc_pages.num_element_per_page; + offset = index % pdev->frag_descs.desc_pages.num_element_per_page; + dma_page = &pdev->frag_descs.desc_pages.dma_pages[target_page]; + *fptr = (uint32_t)(dma_page->page_p_addr + + offset * pdev->frag_descs.size); + HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(fptr); + return; +} + +/** + * htt_tx_frag_desc_attach() - Attach fragment descriptor + * @pdev: htt device instance pointer + * @desc_pool_elems: Number of fragment descriptor + * + * This function will allocate fragment descriptor + * + * Return: 0 success + */ +static int htt_tx_frag_desc_attach(struct htt_pdev_t *pdev, + uint16_t desc_pool_elems) +{ + pdev->frag_descs.pool_elems = desc_pool_elems; + cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->frag_descs.desc_pages, + pdev->frag_descs.size, desc_pool_elems, + cdf_get_dma_mem_context((&pdev->frag_descs), memctx), false); + if ((0 == pdev->frag_descs.desc_pages.num_pages) || + (NULL == pdev->frag_descs.desc_pages.dma_pages)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "FRAG descriptor alloc fail"); + return -ENOBUFS; + } + return 0; +} + +/** + * htt_tx_frag_desc_detach() - Detach fragment descriptor + * @pdev: htt device instance pointer + * + * This function will free fragment descriptor + * + * Return: None + */ +static void htt_tx_frag_desc_detach(struct htt_pdev_t *pdev) +{ + cdf_mem_multi_pages_free(pdev->osdev, &pdev->frag_descs.desc_pages, + cdf_get_dma_mem_context((&pdev->frag_descs), memctx), false); +} + +/** + * htt_tx_frag_alloc() - Allocate single fragment descriptor from the pool + * @pdev: htt device instance pointer + * @index: Descriptor index + * @frag_paddr_lo: Fragment descriptor physical address + * @frag_ptr: Fragment descriptor virtual address + * + * This function will free fragment descriptor + * + * Return: None + */ +int htt_tx_frag_alloc(htt_pdev_handle pdev, + u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr) +{ + uint16_t frag_page_index; + uint16_t frag_elem_index; + struct cdf_mem_dma_page_t *dma_page; + + /** Index should never be 0, since its used by the hardware + to terminate the link. */ + if (index >= pdev->tx_descs.pool_elems) { + *frag_ptr = NULL; + return 1; + } + + frag_page_index = index / + pdev->frag_descs.desc_pages.num_element_per_page; + frag_elem_index = index % + pdev->frag_descs.desc_pages.num_element_per_page; + dma_page = &pdev->frag_descs.desc_pages.dma_pages[frag_page_index]; + + *frag_ptr = dma_page->page_v_addr_start + + frag_elem_index * pdev->frag_descs.size; + if (((char *)(*frag_ptr) < dma_page->page_v_addr_start) || + ((char *)(*frag_ptr) > dma_page->page_v_addr_end)) { + *frag_ptr = NULL; + return 1; + } + + *frag_paddr_lo = dma_page->page_p_addr + + frag_elem_index * pdev->frag_descs.size; + return 0; +} +#else +/** + * htt_tx_desc_get_size() - get tx descripotrs size + * @pdev: htt device instance pointer + * + * This function will get HTT TX descriptor size and fragment descriptor size + * + * Return: None + */ +static inline void htt_tx_desc_get_size(struct htt_pdev_t *pdev) +{ /* * Start with the size of the base struct * that actually gets downloaded. @@ -111,10 +252,74 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) + (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev) + 1) * 8 /* 2x uint32_t */ + 4; /* uint32_t fragmentation list terminator */ - if (pdev->tx_descs.size < sizeof(uint32_t *)) pdev->tx_descs.size = sizeof(uint32_t *); -#endif /* defined(HELIUMPLUS_PADDR64) */ +} + +/** + * htt_tx_frag_desc_field_update() - Update fragment descriptor field + * @pdev: htt device instance pointer + * @fptr: Fragment descriptor field pointer + * @index: Descriptor index to find page and offset + * @desc_v_ptr: descriptor virtual pointot to find offset + * + * This function will update fragment descriptor field with actual fragment + * descriptor stating physical pointer + * + * Return: None + */ +static void htt_tx_frag_desc_field_update(struct htt_pdev_t *pdev, + uint32_t *fptr, unsigned int index, + struct htt_tx_msdu_desc_t *desc_v_ptr) +{ + *fptr = (uint32_t)htt_tx_get_paddr(pdev, (char *)desc_v_ptr) + + HTT_TX_DESC_LEN; +} + +/** + * htt_tx_frag_desc_attach() - Attach fragment descriptor + * @pdev: htt device instance pointer + * @desc_pool_elems: Number of fragment descriptor + * + * This function will allocate fragment descriptor + * + * Return: 0 success + */ +static inline int htt_tx_frag_desc_attach(struct htt_pdev_t *pdev, + int desc_pool_elems) +{ + return 0; +} + +/** + * htt_tx_frag_desc_detach() - Detach fragment descriptor + * @pdev: htt device instance pointer + * + * This function will free fragment descriptor + * + * Return: None + */ +static void htt_tx_frag_desc_detach(struct htt_pdev_t *pdev) {} +#endif /* HELIUMPLUS */ + +/** + * htt_tx_attach() - Attach HTT device instance + * @pdev: htt device instance pointer + * @desc_pool_elems: Number of TX descriptors + * + * This function will allocate HTT TX resources + * + * Return: 0 Success + */ +int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) +{ + int i, i_int, pool_size; + uint32_t **p; + struct cdf_mem_dma_page_t *page_info; + uint32_t num_link = 0; + uint16_t num_page, num_desc_per_page; + + htt_tx_desc_get_size(pdev); /* * Make sure tx_descs.size is a multiple of 4-bytes. * It should be, but round up just to be sure. @@ -123,94 +328,120 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) 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; - - pdev->tx_descs.pool_vaddr = - cdf_os_mem_alloc_consistent( - pdev->osdev, pool_size, - &pool_paddr, - cdf_get_dma_mem_context((&pdev->tx_descs), memctx)); - - pdev->tx_descs.pool_paddr = pool_paddr; - - if (!pdev->tx_descs.pool_vaddr) - return -ENOBUFS; /* failure */ - - cdf_print("%s:htt_desc_start:0x%p htt_desc_end:0x%p\n", __func__, - pdev->tx_descs.pool_vaddr, - (uint32_t *) (pdev->tx_descs.pool_vaddr + pool_size)); - -#if defined(HELIUMPLUS_PADDR64) - pdev->frag_descs.pool_elems = desc_pool_elems; - /* - * Allocate space for MSDU extension descriptor - * H/W expects this in contiguous memory - */ - pool_size = pdev->frag_descs.pool_elems * pdev->frag_descs.size; - - pdev->frag_descs.pool_vaddr = cdf_os_mem_alloc_consistent( - pdev->osdev, pool_size, &pool_paddr, - cdf_get_dma_mem_context((&pdev->frag_descs), memctx)); - - if (!pdev->frag_descs.pool_vaddr) - return -ENOBUFS; /* failure */ - - pdev->frag_descs.pool_paddr = pool_paddr; - - cdf_print("%s:MSDU Ext.Table Start:0x%p MSDU Ext.Table End:0x%p\n", - __func__, pdev->frag_descs.pool_vaddr, - (u_int32_t *) (pdev->frag_descs.pool_vaddr + pool_size)); -#endif /* defined(HELIUMPLUS_PADDR64) */ - -#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS - g_dbg_htt_desc_end_addr = (uint32_t *) - (pdev->tx_descs.pool_vaddr + pool_size); - g_dbg_htt_desc_start_addr = (uint32_t *) pdev->tx_descs.pool_vaddr; -#endif + cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->tx_descs.desc_pages, + pdev->tx_descs.size, pdev->tx_descs.pool_elems, + cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false); + if ((0 == pdev->tx_descs.desc_pages.num_pages) || + (NULL == pdev->tx_descs.desc_pages.dma_pages)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "HTT desc alloc fail"); + goto out_fail; + } + num_page = pdev->tx_descs.desc_pages.num_pages; + num_desc_per_page = pdev->tx_descs.desc_pages.num_element_per_page; /* link tx descriptors into a freelist */ - pdev->tx_descs.freelist = (uint32_t *) pdev->tx_descs.pool_vaddr; + page_info = pdev->tx_descs.desc_pages.dma_pages; + pdev->tx_descs.freelist = (uint32_t *)page_info->page_v_addr_start; p = (uint32_t **) pdev->tx_descs.freelist; - for (i = 0; i < desc_pool_elems - 1; i++) { - *p = (uint32_t *) (((char *)p) + pdev->tx_descs.size); - p = (uint32_t **) *p; + for (i = 0; i < num_page; i++) { + for (i_int = 0; i_int < num_desc_per_page; i_int++) { + if (i_int == (num_desc_per_page - 1)) { + /* + * Last element on this page, + * should pint next page */ + if (!page_info->page_v_addr_start) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "over flow num link %d\n", + num_link); + goto free_htt_desc; + } + 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; - return 0; /* success */ + if (htt_tx_frag_desc_attach(pdev, desc_pool_elems)) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "HTT Frag descriptor alloc fail"); + goto free_htt_desc; + } + + /* success */ + return 0; + +free_htt_desc: + cdf_mem_multi_pages_free(pdev->osdev, &pdev->tx_descs.desc_pages, + cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false); +out_fail: + return -ENOBUFS; } void htt_tx_detach(struct htt_pdev_t *pdev) { - if (pdev) { - cdf_os_mem_free_consistent( - pdev->osdev, - /* pool_size */ - pdev->tx_descs.pool_elems * pdev->tx_descs.size, - pdev->tx_descs.pool_vaddr, - pdev->tx_descs.pool_paddr, - cdf_get_dma_mem_context((&pdev->tx_descs), memctx)); -#if defined(HELIUMPLUS_PADDR64) - cdf_os_mem_free_consistent( - pdev->osdev, - /* pool_size */ - pdev->frag_descs.pool_elems * - pdev->frag_descs.size, - pdev->frag_descs.pool_vaddr, - pdev->frag_descs.pool_paddr, - cdf_get_dma_mem_context((&pdev->frag_descs), memctx)); -#endif /* defined(HELIUMPLUS_PADDR64) */ + if (!pdev) { + cdf_print("htt tx detach invalid instance"); + return; + } + + htt_tx_frag_desc_detach(pdev); + cdf_mem_multi_pages_free(pdev->osdev, &pdev->tx_descs.desc_pages, + cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false); +} + +/** + * 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 + */ +static cdf_dma_addr_t htt_tx_get_paddr(htt_pdev_handle pdev, + char *target_vaddr) +{ + uint16_t i; + struct cdf_mem_dma_page_t *page_info = NULL; + uint64_t offset; + + for (i = 0; i < pdev->tx_descs.desc_pages.num_pages; i++) { + page_info = pdev->tx_descs.desc_pages.dma_pages + i; + if (!page_info->page_v_addr_start) { + cdf_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) { + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "invalid page_info"); + return 0; } + + offset = (uint64_t)(target_vaddr - page_info->page_v_addr_start); + return page_info->page_p_addr + offset; } /*--- descriptor allocation functions ---------------------------------------*/ -void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo) +void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo, + uint16_t index) { struct htt_host_tx_desc_t *htt_host_tx_desc; /* includes HTC hdr */ struct htt_tx_msdu_desc_t *htt_tx_desc; /* doesn't include HTC hdr */ - uint16_t index; uint32_t *fragmentation_descr_field_ptr; htt_host_tx_desc = (struct htt_host_tx_desc_t *)pdev->tx_descs.freelist; @@ -234,44 +465,20 @@ void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo) fragmentation_descr_field_ptr = (uint32_t *) ((uint32_t *) htt_tx_desc) + HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD; - - index = ((char *)htt_host_tx_desc - - (char *)(((struct htt_host_tx_desc_t *) - pdev->tx_descs.pool_vaddr))) / - pdev->tx_descs.size; /* * The fragmentation descriptor is allocated from consistent * memory. Therefore, we can use the address directly rather * than having to map it from a virtual/CPU address to a * physical/bus address. */ -#if defined(HELIUMPLUS_PADDR64) -#if HTT_PADDR64 - /* this is: frags_desc_ptr.lo */ - *fragmentation_descr_field_ptr = (uint32_t) - (pdev->frag_descs.pool_paddr + - (pdev->frag_descs.size * index)); - fragmentation_descr_field_ptr++; - /* frags_desc_ptr.hi */ - *fragmentation_descr_field_ptr = 0; -#else /* ! HTT_PADDR64 */ - *fragmentation_descr_field_ptr = (uint32_t) - (pdev->frag_descs.pool_paddr + - (pdev->frag_descs.size * index)); - cdf_print("%s %d: i %d frag_paddr 0x%x\n", - __func__, __LINE__, index, - (*fragmentation_descr_field_ptr)); -#endif /* HTT_PADDR64 */ -#else /* !HELIUMPLUS_PADDR64 */ - *fragmentation_descr_field_ptr = - HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN; -#endif /* HELIUMPLUS_PADDR64 */ + htt_tx_frag_desc_field_update(pdev, fragmentation_descr_field_ptr, + index, htt_tx_desc); /* * Include the headroom for the HTC frame header when specifying the * physical address for the HTT tx descriptor. */ - *paddr_lo = (uint32_t) HTT_TX_DESC_PADDR(pdev, htt_host_tx_desc); + *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 @@ -312,32 +519,13 @@ void htt_tx_desc_frags_table_set(htt_pdev_handle pdev, *fragmentation_descr_field_ptr = frag_desc_paddr_lo; #else *fragmentation_descr_field_ptr = - HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN; + htt_tx_get_paddr(pdev, htt_tx_desc) + HTT_TX_DESC_LEN; #endif } else { *fragmentation_descr_field_ptr = paddr; } } -#if defined(HELIUMPLUS_PADDR64) -void * -htt_tx_frag_alloc(htt_pdev_handle pdev, - u_int16_t index, - u_int32_t *frag_paddr_lo) -{ - /** Index should never be 0, since its used by the hardware - to terminate the link. */ - if (index >= pdev->tx_descs.pool_elems) - return NULL; - - *frag_paddr_lo = (uint32_t) - (pdev->frag_descs.pool_paddr + (pdev->frag_descs.size * index)); - - return ((char *) pdev->frag_descs.pool_vaddr) + - (pdev->frag_descs.size * index); -} -#endif /* defined(HELIUMPLUS_PADDR64) */ - /* PUT THESE AS INLINE IN ol_htt_tx_api.h */ void htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc) diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h index 2f2e89e5b2ed..67447506c744 100644 --- a/core/dp/htt/htt_types.h +++ b/core/dp/htt/htt_types.h @@ -324,10 +324,9 @@ struct htt_pdev_t { struct { int size; /* of each HTT tx desc */ - int pool_elems; - int alloc_cnt; - char *pool_vaddr; - uint32_t pool_paddr; + uint16_t pool_elems; + uint16_t alloc_cnt; + struct cdf_mem_multi_page_t desc_pages; uint32_t *freelist; cdf_dma_mem_context(memctx); } tx_descs; @@ -335,8 +334,7 @@ struct htt_pdev_t { struct { int size; /* of each Fragment/MSDU-Ext descriptor */ int pool_elems; - char *pool_vaddr; - uint32_t pool_paddr; + struct cdf_mem_multi_page_t desc_pages; cdf_dma_mem_context(memctx); } frag_descs; #endif /* defined(HELIUMPLUS_PADDR64) */ diff --git a/core/dp/ol/inc/ol_htt_tx_api.h b/core/dp/ol/inc/ol_htt_tx_api.h index 58ebabc47c49..baacfdb5848f 100644 --- a/core/dp/ol/inc/ol_htt_tx_api.h +++ b/core/dp/ol/inc/ol_htt_tx_api.h @@ -357,7 +357,8 @@ uint16_t htt_tx_compl_desc_id(void *iterator, int num); * @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, uint32_t *paddr_lo); +void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo, + uint16_t index); /** * @brief Free a HTT abstract tx descriptor. @@ -368,17 +369,26 @@ void *htt_tx_desc_alloc(htt_pdev_handle htt_pdev, uint32_t *paddr_lo); void htt_tx_desc_free(htt_pdev_handle htt_pdev, void *htt_tx_desc); #if defined(HELIUMPLUS_PADDR64) -/* TODO: oka: use kernel-doc format */ /** - * @brief Free a HTT abstract tx descriptor. + * @brief Allocate TX frag descriptor + * @details + * Allocate TX frag descriptor * - * @param htt_pdev - handle to the HTT instance that made the allocation - * @param htt_tx_desc - the descriptor to free + * @param pdev - handle to the HTT instance that made the allocation + * @param index - tx descriptor index + * @param frag_paddr_lo - fragment descriptor physical address lower 32bits + * @param frag_ptr - fragment descriptor hlos pointe + * @return success 0 */ -void * -htt_tx_frag_alloc(htt_pdev_handle pdev, - u_int16_t index, - u_int32_t *frag_paddr_lo); +int htt_tx_frag_alloc(htt_pdev_handle pdev, + u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr); +#else +static inline int htt_tx_frag_alloc(htt_pdev_handle pdev, + u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr) +{ + *frag_ptr = NULL; + return 0; +} #endif /* defined(HELIUMPLUS_PADDR64) */ /** * @brief Discard all tx frames in the process of being downloaded. diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index 42a13c328901..0f718389d702 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -1159,7 +1159,7 @@ void dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc) int i; cdf_print("OL TX Descriptor 0x%p msdu_id %d\n", - tx_desc, tx_desc->index); + tx_desc, tx_desc->id); cdf_print("HTT TX Descriptor vaddr: 0x%p paddr: 0x%x\n", tx_desc->htt_tx_desc, tx_desc->htt_tx_desc_paddr); cdf_print("%s %d: Fragment Descriptor 0x%p\n", @@ -1329,35 +1329,34 @@ cdf_nbuf_t ol_tx_reinject(struct ol_txrx_vdev_t *vdev, void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg) { int i; - pdev->tso_seg_pool.pool_size = num_seg; - pdev->tso_seg_pool.num_free = num_seg; - - pdev->tso_seg_pool.array = NULL; - pdev->tso_seg_pool.array = cdf_mem_malloc(num_seg * - sizeof(struct cdf_tso_seg_elem_t)); - if (!pdev->tso_seg_pool.array) { - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, - "%s Could not allocate TSO array!\n", __func__); - return; + struct cdf_tso_seg_elem_t *c_element; + + c_element = cdf_mem_malloc(sizeof(struct cdf_tso_seg_elem_t)); + pdev->tso_seg_pool.freelist = c_element; + for (i = 0; i < (num_seg - 1); i++) { + c_element->next = + cdf_mem_malloc(sizeof(struct cdf_tso_seg_elem_t)); + c_element = c_element->next; + c_element->next = NULL; } - - pdev->tso_seg_pool.freelist = &pdev->tso_seg_pool.array[0]; - - for (i = 0; i < (num_seg - 1); i++) - pdev->tso_seg_pool.array[i].next = - &pdev->tso_seg_pool.array[i + 1]; - - pdev->tso_seg_pool.array[i].next = NULL; - + pdev->tso_seg_pool.pool_size = num_seg; cdf_spinlock_init(&pdev->tso_seg_pool.tso_mutex); } void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev) { + int i; + struct cdf_tso_seg_elem_t *c_element; + struct cdf_tso_seg_elem_t *temp; + cdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); - if (pdev->tso_seg_pool.array) { - cdf_mem_free(pdev->tso_seg_pool.array); - pdev->tso_seg_pool.array = NULL; + c_element = pdev->tso_seg_pool.freelist; + for (i = 0; i < pdev->tso_seg_pool.pool_size; i++) { + temp = c_element->next; + cdf_mem_free(c_element); + c_element = temp; + if (!c_element) + break; } pdev->tso_seg_pool.freelist = NULL; diff --git a/core/dp/txrx/ol_tx.h b/core/dp/txrx/ol_tx.h index 8f4bbfe3a5a3..77ae56d1ae6b 100644 --- a/core/dp/txrx/ol_tx.h +++ b/core/dp/txrx/ol_tx.h @@ -78,5 +78,15 @@ void ol_txrx_mgmt_tx_complete(void *ctxt, cdf_nbuf_t netbuf, int err); #if defined(FEATURE_TSO) void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg); void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev); +#else +static inline void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, + uint32_t num_seg) +{ + return; +} +static inline void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev) +{ + return; +} #endif #endif /* _OL_TX__H_ */ diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 3395b9103a22..1fa78723aa24 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -127,7 +127,6 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, pdev->tx_desc.freelist = pdev->tx_desc.freelist->next; ol_tx_desc_sanity_checks(pdev, tx_desc); ol_tx_desc_compute_delay(tx_desc); - } cdf_spin_unlock_bh(&pdev->tx_mutex); if (!tx_desc) @@ -231,13 +230,6 @@ ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev, #endif #endif -/* TBD: make this inline in the .h file? */ -struct ol_tx_desc_t *ol_tx_desc_find(struct ol_txrx_pdev_t *pdev, - uint16_t tx_desc_id) -{ - return &pdev->tx_desc.array[tx_desc_id].tx_desc; -} - #ifndef QCA_LL_TX_FLOW_CONTROL_V2 /** * ol_tx_desc_free() - put descriptor to freelist @@ -537,7 +529,7 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev, */ #if defined(HELIUMPLUS_DEBUG) cdf_print("%s %d: Frag Descriptor Reset [%d] to 0x%x\n", - __func__, __LINE__, tx_desc->index, + __func__, __LINE__, tx_desc->id, frag_desc_paddr_lo); #endif /* HELIUMPLUS_DEBUG */ #endif /* HELIUMPLUS_PADDR64 */ @@ -591,8 +583,6 @@ struct cdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev) pdev->tso_seg_pool.freelist = pdev->tso_seg_pool.freelist->next; } cdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); - if (!tso_seg) - return NULL; return tso_seg; } diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h index 5094c4236cf9..392e192249e8 100644 --- a/core/dp/txrx/ol_tx_desc.h +++ b/core/dp/txrx/ol_tx_desc.h @@ -73,8 +73,16 @@ struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev, * @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, - uint16_t tx_desc_id); +static inline struct ol_tx_desc_t *ol_tx_desc_find( + struct ol_txrx_pdev_t *pdev, uint16_t tx_desc_id) +{ + void **td_base = (void **)pdev->tx_desc.desc_pages.cacheable_pages; + + return &((union ol_tx_desc_list_elem_t *) + (td_base[tx_desc_id >> pdev->tx_desc.page_divider] + + (pdev->tx_desc.desc_reserved_size * + (tx_desc_id & pdev->tx_desc.offset_filter))))->tx_desc; +} /** * @brief Free a list of tx descriptors and the tx frames they refer to. @@ -125,10 +133,8 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev, static inline uint16_t ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) { - TXRX_ASSERT2(((union ol_tx_desc_list_elem_t *)tx_desc - - pdev->tx_desc.array) < pdev->tx_desc.pool_size); - return (uint16_t) - ((union ol_tx_desc_list_elem_t *)tx_desc - pdev->tx_desc.array); + TXRX_ASSERT2(tx_desc->id < pdev->tx_desc.pool_size); + return tx_desc->id; } /* diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index b4ba774bd2c6..f6dc650cb837 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -442,8 +442,10 @@ ol_tx_delay_compute(struct ol_txrx_pdev_t *pdev, void ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev) { int i = 0; - for (i = 0; i < pdev->tx_desc.pool_size; i++) { + struct ol_tx_desc_t *tx_desc; + for (i = 0; i < pdev->tx_desc.pool_size; i++) { + tx_desc = ol_tx_desc_find(pdev, i); /* * Confirm that each tx descriptor is "empty", i.e. it has * no tx frame attached. @@ -451,12 +453,11 @@ void ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev) * been given to the target to transmit, for which the * target has never provided a response. */ - if (cdf_atomic_read(&pdev->tx_desc.array[i].tx_desc.ref_cnt)) { + if (cdf_atomic_read(&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); } } @@ -487,7 +488,6 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, char *trace_str; uint32_t byte_cnt = 0; - union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; cdf_nbuf_t netbuf; union ol_tx_desc_list_elem_t *lcl_freelist = NULL; @@ -500,7 +500,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, 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 = ol_tx_desc_find(pdev, tx_desc_id); tx_desc->status = status; netbuf = tx_desc->netbuf; @@ -560,10 +560,9 @@ ol_tx_single_completion_handler(ol_txrx_pdev_handle pdev, enum htt_tx_status status, uint16_t tx_desc_id) { struct ol_tx_desc_t *tx_desc; - union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; cdf_nbuf_t netbuf; - tx_desc = &td_array[tx_desc_id].tx_desc; + tx_desc = ol_tx_desc_find(pdev, tx_desc_id); tx_desc->status = status; netbuf = tx_desc->netbuf; @@ -597,7 +596,6 @@ ol_tx_inspect_handler(ol_txrx_pdev_handle pdev, uint16_t *desc_ids = (uint16_t *) tx_desc_id_iterator; uint16_t tx_desc_id; struct ol_tx_desc_t *tx_desc; - union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array; union ol_tx_desc_list_elem_t *lcl_freelist = NULL; union ol_tx_desc_list_elem_t *tx_desc_last = NULL; cdf_nbuf_t netbuf; @@ -606,7 +604,7 @@ ol_tx_inspect_handler(ol_txrx_pdev_handle pdev, for (i = 0; i < num_msdus; i++) { tx_desc_id = desc_ids[i]; - tx_desc = &td_array[tx_desc_id].tx_desc; + tx_desc = ol_tx_desc_find(pdev, tx_desc_id); netbuf = tx_desc->netbuf; /* find the "vdev" this tx_desc belongs to */ @@ -848,7 +846,7 @@ ol_tx_delay_tid_from_l3_hdr(struct ol_txrx_pdev_t *pdev, static int ol_tx_delay_category(struct ol_txrx_pdev_t *pdev, uint16_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; + struct ol_tx_desc_t *tx_desc = ol_tx_desc_find(pdev, msdu_id); uint8_t tid; cdf_nbuf_t msdu = tx_desc->netbuf; @@ -939,9 +937,9 @@ ol_tx_delay_compute(struct ol_txrx_pdev_t *pdev, pdev->tx_delay.tx_compl_timestamp_ticks = now_ticks; for (i = 0; i < num_msdus; i++) { - uint16_t id = desc_ids[i]; - struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.array[id].tx_desc; int bin; + uint16_t id = desc_ids[i]; + struct ol_tx_desc_t *tx_desc = ol_tx_desc_find(pdev, id); tx_delay_queue_ticks = now_ticks - tx_desc->entry_timestamp_ticks; diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 528b121763b1..cf249ca11eb6 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -258,29 +258,11 @@ setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev) } -/** - * init_txdesc_id() initialize Tx desc with id - * - * @pdev: handle OL pdev - * @desc_num: Tx descriptor number - * - * Return: void - */ -static inline void -init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num) -{ - pdev->tx_desc.array[desc_num].tx_desc.id = desc_num; - cdf_atomic_init(&pdev->tx_desc.array[desc_num].tx_desc.ref_cnt); -} #else /* not WLAN_FEATURE_FASTPATH */ static inline void setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev) { } -static inline void -init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num) -{ -} #endif /* WLAN_FEATURE_FASTPATH */ #ifdef QCA_LL_TX_FLOW_CONTROL_V2 @@ -391,14 +373,20 @@ fail0: int ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) { - int i; + uint16_t i; + uint16_t fail_idx = 0; int ret = 0; uint16_t desc_pool_size; struct ol_softc *osc = cds_get_context(CDF_MODULE_ID_HIF); + uint16_t desc_element_size = sizeof(union ol_tx_desc_list_elem_t); + union ol_tx_desc_list_elem_t *c_element; + unsigned int sig_bit; + uint16_t desc_per_page; + if (!osc) { ret = -EINVAL; - goto fail0; + goto ol_attach_fail; } /* @@ -428,7 +416,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) ret = htt_attach(pdev->htt_pdev, desc_pool_size); if (ret) - goto fail0; + goto ol_attach_fail; /* Update CE's pkt download length */ ce_pkt_dl_len_set((void *)osc, htt_pkt_dl_len_get(pdev->htt_pdev)); @@ -436,15 +424,32 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) /* Attach micro controller data path offload resource */ if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) if (htt_ipa_uc_attach(pdev->htt_pdev)) - goto fail1; - - pdev->tx_desc.array = - cdf_mem_malloc(desc_pool_size * - sizeof(union ol_tx_desc_list_elem_t)); - if (!pdev->tx_desc.array) - goto fail2; - cdf_mem_set(pdev->tx_desc.array, - desc_pool_size * sizeof(union ol_tx_desc_list_elem_t), 0); + goto uc_attach_fail; + + /* Calculate single element reserved size power of 2 */ + pdev->tx_desc.desc_reserved_size = cdf_get_pwr2(desc_element_size); + cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->tx_desc.desc_pages, + pdev->tx_desc.desc_reserved_size, desc_pool_size, 0, true); + if ((0 == pdev->tx_desc.desc_pages.num_pages) || + (NULL == pdev->tx_desc.desc_pages.cacheable_pages)) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "Page alloc fail"); + goto page_alloc_fail; + } + desc_per_page = pdev->tx_desc.desc_pages.num_element_per_page; + pdev->tx_desc.offset_filter = desc_per_page - 1; + /* Calculate page divider to find page number */ + sig_bit = 0; + while (desc_per_page) { + sig_bit++; + desc_per_page = desc_per_page >> 1; + } + pdev->tx_desc.page_divider = (sig_bit - 1); + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "page_divider 0x%x, offset_filter 0x%x num elem %d, ol desc num page %d, ol desc per page %d", + pdev->tx_desc.page_divider, pdev->tx_desc.offset_filter, + desc_pool_size, pdev->tx_desc.desc_pages.num_pages, + pdev->tx_desc.desc_pages.num_element_per_page); /* * Each SW tx desc (used only within the tx datapath SW) has a @@ -453,79 +458,74 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) * desc now, to avoid doing it during time-critical transmit. */ pdev->tx_desc.pool_size = desc_pool_size; + pdev->tx_desc.freelist = + (union ol_tx_desc_list_elem_t *) + (*pdev->tx_desc.desc_pages.cacheable_pages); + c_element = pdev->tx_desc.freelist; for (i = 0; i < desc_pool_size; i++) { void *htt_tx_desc; -#if defined(HELIUMPLUS_PADDR64) - void *htt_frag_desc; - uint32_t frag_paddr_lo; -#endif /* defined(HELIUMPLUS_PADDR64) */ + void *htt_frag_desc = NULL; + uint32_t frag_paddr_lo = 0; uint32_t paddr_lo; - htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo); + if (i == (desc_pool_size - 1)) + c_element->next = NULL; + else + c_element->next = (union ol_tx_desc_list_elem_t *) + ol_tx_desc_find(pdev, i + 1); + + htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo, i); if (!htt_tx_desc) { CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL, "%s: failed to alloc HTT tx desc (%d of %d)", __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 fail3; + fail_idx = i; + goto desc_alloc_fail; } - 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; - -#if defined(HELIUMPLUS_PADDR64) - htt_frag_desc = htt_tx_frag_alloc(pdev->htt_pdev, i, - &frag_paddr_lo); - if (!htt_frag_desc) { - cdf_print("%s: failed to alloc HTT frag dsc (%d/%d)\n", - __func__, i, desc_pool_size); + + c_element->tx_desc.htt_tx_desc = htt_tx_desc; + c_element->tx_desc.htt_tx_desc_paddr = paddr_lo; + ret = htt_tx_frag_alloc(pdev->htt_pdev, + i, &frag_paddr_lo, &htt_frag_desc); + if (ret) { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: failed to alloc HTT frag dsc (%d/%d)", + __func__, i, desc_pool_size); /* Is there a leak here, is this handling correct? */ - goto fail3; + fail_idx = i; + goto desc_alloc_fail; } - /* Initialize the first 6 words (TSO flags) - of the frag descriptor */ - memset(htt_frag_desc, 0, 6*sizeof(uint32_t)); - - pdev->tx_desc.array[i].tx_desc.htt_frag_desc = htt_frag_desc; -#if defined(HELIUMPLUS_DEBUG) - cdf_print("%s:%d %d %p\n", __func__, __LINE__, - i, pdev->tx_desc.array[i].tx_desc.htt_frag_desc); -#endif /* HELIUMPLUS_DEBUG */ - pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr = - frag_paddr_lo; -#if defined(HELIUMPLUS_DEBUG) - cdf_print("%s:%d - %d FRAG VA 0x%p FRAG PA 0x%x\n", + if (!ret && htt_frag_desc) { + /* Initialize the first 6 words (TSO flags) + of the frag descriptor */ + memset(htt_frag_desc, 0, 6 * sizeof(uint32_t)); + c_element->tx_desc.htt_frag_desc = htt_frag_desc; + c_element->tx_desc.htt_frag_desc_paddr = frag_paddr_lo; + } + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW, + "%s:%d - %d FRAG VA 0x%p FRAG PA 0x%x", __func__, __LINE__, i, - pdev->tx_desc.array[i].tx_desc.htt_frag_desc, - pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr); -#endif /* HELIUMPLUS_DEBUG */ -#endif /* defined(HELIUMPLUS_PADDR64) */ - - pdev->tx_desc.array[i].tx_desc.index = i; + c_element->tx_desc.htt_frag_desc, + c_element->tx_desc.htt_frag_desc_paddr); #ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS - pdev->tx_desc.array[i].tx_desc.pkt_type = 0xff; + c_element->tx_desc.pkt_type = 0xff; #ifdef QCA_COMPUTE_TX_DELAY - pdev->tx_desc.array[i].tx_desc.entry_timestamp_ticks = + c_element->tx_desc.entry_timestamp_ticks = 0xffffffff; #endif #endif - init_txdesc_id(pdev, i); + c_element->tx_desc.id = i; + cdf_atomic_init(&c_element->tx_desc.ref_cnt); + c_element = c_element->next; + fail_idx = 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__, (uint32_t *) pdev->tx_desc.freelist, (uint32_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); @@ -540,7 +540,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, "%s Invalid standard frame type: %d", __func__, pdev->frame_format); - goto fail4; + goto control_init_fail; } /* setup the global rx defrag waitlist */ @@ -608,7 +608,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) "Invalid std frame type; [en/de]cap: f:%x t:%x r:%x", pdev->frame_format, pdev->target_tx_tran_caps, pdev->target_rx_tran_caps); - goto fail4; + goto control_init_fail; } #endif @@ -658,7 +658,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) CDF_TRACE_LEVEL_ERROR, "%s: %s", __func__, TRACESTR01); #undef TRACESTR01 - goto fail4; + goto control_init_fail; } } else { /* PN check done on target */ @@ -686,10 +686,10 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) OL_TXRX_PEER_STATS_MUTEX_INIT(pdev); if (OL_RX_REORDER_TRACE_ATTACH(pdev) != A_OK) - goto fail5; + goto reorder_trace_attach_fail; if (OL_RX_PN_TRACE_ATTACH(pdev) != A_OK) - goto fail6; + goto pn_trace_attach_fail; #ifdef PERE_IP_HDR_ALIGNMENT_WAR pdev->host_80211_enable = ol_scn_host_80211_enable_get(pdev->ctrl_pdev); @@ -791,45 +791,39 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev) } #endif /* QCA_COMPUTE_TX_DELAY */ -#ifdef QCA_SUPPORT_TX_THROTTLE /* Thermal Mitigation */ ol_tx_throttle_init(pdev); -#endif - - -#if defined(FEATURE_TSO) ol_tso_seg_list_init(pdev, desc_pool_size); -#endif - ol_tx_register_flow_control(pdev); return 0; /* success */ -fail6: +pn_trace_attach_fail: OL_RX_REORDER_TRACE_DETACH(pdev); -fail5: +reorder_trace_attach_fail: cdf_spinlock_destroy(&pdev->tx_mutex); cdf_spinlock_destroy(&pdev->peer_ref_mutex); cdf_spinlock_destroy(&pdev->rx.mutex); cdf_spinlock_destroy(&pdev->last_real_peer_mutex); OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev); -fail4: - for (i = 0; i < desc_pool_size; i++) +control_init_fail: +desc_alloc_fail: + for (i = 0; i < fail_idx; i++) htt_tx_desc_free(pdev->htt_pdev, - pdev->tx_desc.array[i].tx_desc.htt_tx_desc); + (ol_tx_desc_find(pdev, i))->htt_tx_desc); -fail3: - cdf_mem_free(pdev->tx_desc.array); + cdf_mem_multi_pages_free(pdev->osdev, + &pdev->tx_desc.desc_pages, 0, true); -fail2: +page_alloc_fail: if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) htt_ipa_uc_detach(pdev->htt_pdev); -fail1: +uc_attach_fail: htt_detach(pdev->htt_pdev); -fail0: +ol_attach_fail: return ret; /* fail */ } @@ -841,6 +835,7 @@ A_STATUS ol_txrx_pdev_attach_target(ol_txrx_pdev_handle pdev) void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force) { int i; + /*checking to ensure txrx pdev structure is not NULL */ if (!pdev) { TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "NULL pdev passed to %s\n", __func__); @@ -863,7 +858,7 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force) cdf_softirq_timer_free(&pdev->tx_throttle.tx_timer); #endif #endif - + ol_tso_seg_list_deinit(pdev); ol_tx_deregister_flow_control(pdev); if (force) { @@ -889,7 +884,9 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force) for (i = 0; i < pdev->tx_desc.pool_size; i++) { void *htt_tx_desc; + struct ol_tx_desc_t *tx_desc; + tx_desc = ol_tx_desc_find(pdev, i); /* * Confirm that each tx descriptor is "empty", i.e. it has * no tx frame attached. @@ -897,18 +894,19 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force) * been given to the target to transmit, for which the * target has never provided a response. */ - if (cdf_atomic_read(&pdev->tx_desc.array[i].tx_desc.ref_cnt)) { + if (cdf_atomic_read(&tx_desc->ref_cnt)) { TXRX_PRINT(TXRX_PRINT_LEVEL_WARN, "Warning: freeing tx frame (no compltn)\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 = tx_desc->htt_tx_desc; htt_tx_desc_free(pdev->htt_pdev, htt_tx_desc); } - cdf_mem_free(pdev->tx_desc.array); + cdf_mem_multi_pages_free(pdev->osdev, + &pdev->tx_desc.desc_pages, 0, true); + pdev->tx_desc.freelist = NULL; /* Detach micro controller data path offload resource */ if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev)) diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 50a4bd9eeb19..aee96852fe5b 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -33,6 +33,7 @@ #define _OL_TXRX_TYPES__H_ #include /* cdf_nbuf_t */ +#include #include /* TAILQ */ #include /* A_UINT8 */ #include /* htt_sec_type, htt_pkt_type, etc. */ @@ -131,15 +132,10 @@ enum ol_tx_frm_type { struct ol_tx_desc_t { cdf_nbuf_t netbuf; void *htt_tx_desc; -#ifdef WLAN_FEATURE_FASTPATH uint16_t id; -#endif /* WLAN_FEATURE_FASTPATH */ uint32_t htt_tx_desc_paddr; -#if defined(HELIUMPLUS_PADDR64) void *htt_frag_desc; /* struct msdu_ext_desc_t * */ uint32_t htt_frag_desc_paddr; -#endif /* defined(HELIUMPLUS_PADDR64) */ - uint32_t index; cdf_atomic_t ref_cnt; enum htt_tx_status status; @@ -565,13 +561,17 @@ struct ol_txrx_pdev_t { struct { uint16_t pool_size; uint16_t num_free; - union ol_tx_desc_list_elem_t *array; union ol_tx_desc_list_elem_t *freelist; #ifdef QCA_LL_TX_FLOW_CONTROL_V2 uint8_t num_invalid_bin; cdf_spinlock_t flow_pool_list_lock; TAILQ_HEAD(flow_pool_list_t, ol_tx_flow_pool_t) flow_pool_list; #endif + uint32_t page_size; + uint16_t desc_reserved_size; + uint8_t page_divider; + uint32_t offset_filter; + struct cdf_mem_multi_page_t desc_pages; } tx_desc; #if defined(QCA_LL_TX_FLOW_CONTROL_V2) @@ -761,7 +761,6 @@ struct ol_txrx_pdev_t { struct { uint16_t pool_size; uint16_t num_free; - struct cdf_tso_seg_elem_t *array; struct cdf_tso_seg_elem_t *freelist; /* tso mutex */ OL_TX_MUTEX_TYPE tso_mutex; -- cgit v1.2.3 From 9ffa9afe8db066e8e7e4cf17cb50ffaba5400447 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Sat, 16 May 2015 08:53:02 +0530 Subject: qcacld-3.0: debug check for l_rx_defrag_waitlist_remove(2) qcacld-2.0 to qcacld-3.0 propagation Add extra check for tqe->next!= NULL, to assert in only error scenario Change-Id: I12e8ca5d5133ee0480d9c7c7c208854630272c89 CRs-Fixed: 839312 --- core/dp/txrx/ol_rx_defrag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index 7f1db54e6da9..33e829ed5ebf 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -400,7 +400,7 @@ void ol_rx_defrag_waitlist_remove(struct ol_txrx_peer_t *peer, unsigned tid) rx_reorder->defrag_waitlist_elem.tqe_next = NULL; rx_reorder->defrag_waitlist_elem.tqe_prev = NULL; - } else { + } else if (rx_reorder->defrag_waitlist_elem.tqe_next != NULL) { TXRX_PRINT(TXRX_PRINT_LEVEL_FATAL_ERR, "waitlist->tqe_prv = NULL\n"); CDF_ASSERT(0); -- cgit v1.2.3 From 580ee5b5c3e3371fa847625cd80ce41a03e9191e Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 16 Nov 2015 11:33:16 +0530 Subject: qcacld-3.0: Properly handle channel switch through ioctl qcacld-2.0 to qcacld-3.0 propagation. 1)Validate channel switch w.r.t concurrency rules set and switch channel only if there is no channel interference. 2)Disable channel bonding in 2.4Ghz on switching channel to 2.4Ghz band to avoid violating OBSS feature. Change-Id: I81992b2c2876a32eba52010e72c4300608067e58 CRs-Fixed: 809527 --- core/hdd/src/wlan_hdd_hostapd.c | 17 +++++++++++ core/sap/src/sap_module.c | 62 +++++++++++++++++++++++++++++++++++++++++ core/sme/inc/csr_internal.h | 1 + core/sme/inc/sme_api.h | 3 ++ core/sme/src/common/sme_api.c | 42 ++++++++++++++++++++++++++++ core/sme/src/csr/csr_util.c | 3 ++ 6 files changed, 128 insertions(+) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 14a01260702d..30425346521f 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1897,6 +1897,8 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) int ret = 0; hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); hdd_context_t *pHddCtx = NULL; + hdd_adapter_t *sta_adapter; + hdd_station_ctx_t *sta_ctx; #ifndef WLAN_FEATURE_MBSSID v_CONTEXT_t p_cds_context = @@ -1910,6 +1912,21 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) 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->config->conc_custom_rule1) { + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter); + if (hdd_conn_is_connected(sta_ctx)) { + hdd_err("Channel switch not allowed after STA connection with conc_custom_rule1 enabled"); + return -EBUSY; + } + } + if (pHddCtx->dfs_radar_found == true) { hddLog(LOGE, FL("Channel switch in progress!!")); return -EBUSY; diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index b54f6563e4e0..dd4d05fd4ecf 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -598,6 +598,33 @@ void wlan_sap_set_vht_ch_width(void *ctx, uint32_t vht_channel_width) sap_ctx->ch_params.ch_width = vht_channel_width; } +/** + * wlan_sap_validate_channel_switch() - validate target channel switch w.r.t + * concurreny rules set to avoid channel interference. + * @hal - Hal context + * @sap_ch - channel to switch + * @sap_context - sap session context + * + * Return: true if there is no channel interference else return false + */ +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +static bool wlan_sap_validate_channel_switch(tHalHandle hal, uint16_t sap_ch, + ptSapContext sap_context) +{ + return sme_validate_sap_channel_switch( + hHal, + sap_ch, + sap_context->csr_roamProfile.phyMode, + sap_context->cc_switch_mode, + sap_context->sessionId); +} +#else +static inline bool wlan_sap_validate_channel_switch(tHalHandle hal, + uint16_t sap_ch, ptSapContext sap_context) +{ + return true; +} +#endif /** * wlansap_start_bss() - start BSS * @pCtx: Pointer to the global cds context; a handle to SAP's control block @@ -1399,6 +1426,8 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) tWLAN_SAPEvent sapEvent; tpAniSirGlobal pMac = NULL; void *hHal = NULL; + bool valid; + tSmeConfigParams *sme_config; sapContext = CDS_GET_SAP_CB(p_cds_gctx); if (NULL == sapContext) { @@ -1425,6 +1454,18 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) (cds_get_channel_state(targetChannel) == CHANNEL_STATE_DFS && !cds_concurrent_open_sessions_running()))) { + /* + * validate target channel switch w.r.t various concurrency + * rules set. + */ + valid = wlan_sap_validate_channel_switch(hHal, targetChannel, + sapContext); + if (!valid) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("Channel switch to %u is not allowed due to concurrent channel interference"), + targetChannel); + return CDF_STATUS_E_FAULT; + } /* * Post a CSA IE request to SAP state machine with * target channel information and also CSA IE required @@ -1432,6 +1473,27 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) * 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_config = + cdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_ERROR, + FL("memory allocation failed for sme_config")); + return CDF_STATUS_E_NOMEM; + } + sme_get_config_param(pMac, sme_config); + sme_config->csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + sme_update_config(pMac, sme_config); + cdf_mem_free(sme_config); + } + /* * Copy the requested target channel * to sap context. diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index f335b0d99c57..aa8eba8c7185 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -990,6 +990,7 @@ typedef struct tagCsrRoamSession { /* This count represents the number of bssid's we try to join. */ uint8_t join_bssid_count; struct csr_roam_stored_profile stored_roam_profile; + bool ch_switch_in_progress; } tCsrRoamSession; typedef struct tagCsrRoamStruct { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index b931dc43f43d..b80ae17a0ed6 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1053,4 +1053,7 @@ void sme_add_set_thermal_level_callback(tHalHandle hal, sme_set_thermal_level_callback callback); void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg); +bool sme_validate_sap_channel_switch(tHalHandle hal, + uint16_t sap_ch, eCsrPhyMode sap_phy_mode, + uint8_t cc_switch_mode, uint8_t session_id); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 4cfe7d661154..5ef7f247f385 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -13862,6 +13862,48 @@ CDF_STATUS sme_handle_dfs_chan_scan(tHalHandle h_hal, uint8_t dfs_flag) return status; } +#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_ch - channel to switch + * @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, + uint8_t session_id) +{ + CDF_STATUS status = CDF_STATUS_E_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_acquire_global_lock(&mac->sme); + if (CDF_IS_STATUS_SUCCESS(status)) { + intf_channel = csr_check_concurrent_channel_overlap(mac, sap_ch, + sap_phy_mode, + cc_switch_mode); + sme_release_global_lock(&mac->sme); + } else { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock 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 diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 42e351a91029..a6796d9adc92 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -704,6 +704,9 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, CDF_SAP_MODE)) && (session->connectState != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + if (pSession->ch_switch_in_progress) + continue; + csr_handle_conc_chnl_overlap_for_sap_go(mac_ctx, session, &sap_ch, &sap_hbw, &sap_cfreq, &intf_ch, &intf_hbw, &intf_cfreq); -- cgit v1.2.3 From a4fe619f12c49e27e68c2774871c940b1c50235e Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 19 Oct 2015 12:06:20 +0530 Subject: qcacld-3.0: Protect dfs_radar_found global variable using lock qcacld-2.0 to qcacld-3.0 propagation dfs_radar_found variable will be accessed in different context so protect the same with mutex lock and synchronize the channel switch triggered by application and dfs module. Change-Id: I724d22cde9a77c187a17dffef13a9b4c9b2c27da CRs-Fixed: 809527 --- core/hdd/inc/wlan_hdd_cfg.h | 2 +- core/hdd/inc/wlan_hdd_main.h | 6 ++++++ core/hdd/src/wlan_hdd_hostapd.c | 14 ++++++++++++-- core/hdd/src/wlan_hdd_main.c | 30 +++++++++++++++++++----------- core/sap/src/sap_module.c | 3 +++ core/wma/inc/wma_types.h | 2 +- core/wma/src/wma_features.c | 14 ++++++++++++-- 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index ae1a7c01da15..90a14b49ea72 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -3462,7 +3462,7 @@ bool hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx); CDF_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, uint32_t val); void hdd_update_tgt_cfg(void *context, void *param); -void hdd_dfs_indicate_radar(void *context, void *param); +bool hdd_dfs_indicate_radar(void *context, void *param); CDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *intArray, uint8_t *len, uint8_t intArrayMaxLen); diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 61a5f786ba22..dbe70b7da274 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1346,6 +1346,12 @@ struct hdd_context_s { uint16_t hdd_txrx_hist_idx; struct hdd_tx_rx_histogram hdd_txrx_hist[NUM_TX_RX_HISTOGRAM]; + /* + * Dfs lock used to syncronize on sap channel switch during + * radar found indication and application triggered channel + * switch. + */ + struct mutex dfs_lock; }; /*--------------------------------------------------------------------------- diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 30425346521f..658c636eb9d5 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -955,7 +955,10 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, } } + mutex_lock(&pHddCtx->dfs_lock); pHddCtx->dfs_radar_found = false; + mutex_unlock(&pHddCtx->dfs_lock); + wlansap_get_dfs_ignore_cac(pHddCtx->hHal, &ignoreCAC); /* DFS requirement: DO NOT transmit during CAC. */ @@ -1062,6 +1065,10 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, } else { hdd_info("Sent CAC start to user space"); } + + mutex_lock(&pHddCtx->dfs_lock); + pHddCtx->dfs_radar_found = false; + mutex_unlock(&pHddCtx->dfs_lock); break; case eSAP_DFS_CAC_INTERRUPTED: /* @@ -1927,7 +1934,9 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) } } + mutex_lock(&pHddCtx->dfs_lock); if (pHddCtx->dfs_radar_found == true) { + mutex_unlock(&pHddCtx->dfs_lock); hddLog(LOGE, FL("Channel switch in progress!!")); return -EBUSY; } @@ -1941,7 +1950,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) * post eSAP_START_BSS_EVENT success event to HDD. */ pHddCtx->dfs_radar_found = true; - + mutex_unlock(&pHddCtx->dfs_lock); /* * Post the Channel Change request to SAP. */ @@ -1964,8 +1973,9 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) * radar found flag and also restart the netif * queues. */ - + mutex_lock(&pHddCtx->dfs_lock); pHddCtx->dfs_radar_found = false; + mutex_unlock(&pHddCtx->dfs_lock); ret = -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 15aa4834ccf5..da721d1316f2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1227,9 +1227,9 @@ void hdd_update_tgt_cfg(void *context, void *param) * Actions: Stop the netif Tx queues,Indicate Radar present * in HDD context for future usage. * - * Return: None + * Return: true to allow radar indication to host else false */ -void hdd_dfs_indicate_radar(void *context, void *param) +bool hdd_dfs_indicate_radar(void *context, void *param) { hdd_context_t *hdd_ctx = (hdd_context_t *) context; struct wma_dfs_radar_ind *hdd_radar_event = @@ -1238,17 +1238,23 @@ void hdd_dfs_indicate_radar(void *context, void *param) hdd_adapter_t *adapter; CDF_STATUS status; - if (hdd_ctx == NULL) - return; - - if (hdd_radar_event == NULL) - return; - - if (hdd_ctx->config->disableDFSChSwitch) - return; + if (!hdd_ctx || !hdd_radar_event || + hdd_ctx->config->disableDFSChSwitch) + return true; if (true == hdd_radar_event->dfs_radar_status) { + mutex_lock(&hdd_ctx->dfs_lock); + if (hdd_ctx->dfs_radar_found) { + /* + * Application already triggered channel switch + * on current channel, so return here. + */ + mutex_unlock(&hdd_ctx->dfs_lock); + return false; + } + hdd_ctx->dfs_radar_found = true; + mutex_unlock(&hdd_ctx->dfs_lock); status = hdd_get_front_adapter(hdd_ctx, &adapterNode); while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { @@ -1265,6 +1271,8 @@ void hdd_dfs_indicate_radar(void *context, void *param) adapterNode = pNext; } } + + return true; } #endif @@ -4771,7 +4779,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) */ mutex_init(&hdd_ctx->tdls_lock); #endif - + mutex_init(&hdd_ctx->dfs_lock); /* store target type and target version info in hdd ctx */ hdd_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type; hdd_init_offloaded_packets_ctx(hdd_ctx); diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index dd4d05fd4ecf..8fe4ccb60d22 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1520,6 +1520,9 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) * request was issued. */ pMac->sap.SapDfsInfo.sap_radar_found_status = true; + pMac->sap.SapDfsInfo.cac_state = + eSAP_DFS_DO_NOT_SKIP_CAC; + sap_cac_reset_notify(hHal); /* * Post the eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 5f0a1883caa9..17caf8f1de75 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -585,7 +585,7 @@ typedef void (*wma_tgt_cfg_cb)(void *context, void *param); * to stop accepting data Tx packets from netif as radar is * found on the current operating channel */ -typedef void (*wma_dfs_radar_indication_cb)(void *context, void *param); +typedef bool (*wma_dfs_radar_indication_cb)(void *context, void *param); /** * struct wma_cli_set_cmd_t - set command parameters diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index c1e7df5054bc..3a0ca154f4f3 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -7029,6 +7029,7 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic, struct wma_dfs_radar_indication *radar_event; struct wma_dfs_radar_ind wma_radar_event; tpAniSirGlobal pmac = NULL; + bool indication_status; wma = cds_get_context(CDF_MODULE_ID_WMA); if (wma == NULL) { @@ -7069,12 +7070,21 @@ int wma_dfs_indicate_radar(struct ieee80211com *ic, (pmac->sap.SapDfsInfo.disable_dfs_ch_switch == true)) { wma->dfs_ic->last_radar_found_chan = ichan->ic_ieee; /* Indicate the radar event to HDD to stop the netif Tx queues */ - wma_radar_event.ieee_chan_number = ichan->ic_ieee; wma_radar_event.chan_freq = ichan->ic_freq; wma_radar_event.dfs_radar_status = WMA_DFS_RADAR_FOUND; - wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event); + indication_status = + wma->dfs_radar_indication_cb(hdd_ctx, &wma_radar_event); + if (indication_status == false) { + WMA_LOGE("%s:Application triggered channel switch in progress!.. drop radar event indiaction to SAP", + __func__); + cdf_mem_free(radar_event); + cdf_spin_unlock_bh(&ic->chan_lock); + return 0; + } + WMA_LOGE("%s:DFS- RADAR INDICATED TO HDD", __func__); + wma_radar_event.ieee_chan_number = ichan->ic_ieee; /* * Indicate to the radar event to SAP to * select a new channel and set CSA IE -- cgit v1.2.3 From 5324ec881e8d1c7a44ea6b014d9f48d2473032a5 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 16 Nov 2015 14:32:33 +0530 Subject: qcacld-3.0: Changes to add supported operating class IE qcacld-2.0 to qcacld-3.0 propagation Add supported class IE in beacon and probe response frames. Change-Id: Ife4cb1b3db0119a9472cad0f861887c487b147d3 CRs-Fixed: 941466 --- core/mac/inc/sir_mac_prot_def.h | 3 ++ core/mac/src/cfg/cfgUtil/dot11f.frms | 4 ++ core/mac/src/include/dot11f.h | 6 ++- core/mac/src/include/parser_api.h | 4 ++ core/mac/src/pe/sch/sch_beacon_gen.c | 11 +++++ core/mac/src/sys/legacy/src/utils/src/dot11f.c | 16 +++++++ core/mac/src/sys/legacy/src/utils/src/parser_api.c | 56 ++++++++++++++++++++++ core/sme/src/csr/csr_api_roam.c | 38 ++++++++------- 8 files changed, 121 insertions(+), 17 deletions(-) diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 20c1516cf503..8ea6dceed498 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -361,6 +361,9 @@ #define SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_EID_MIN 0 #define SIR_MAC_CHNL_EXTENDED_SWITCH_ANN_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 /* reserved 51-69 */ #define SIR_MAC_RM_ENABLED_CAPABILITY_EID 70 #define SIR_MAC_RM_ENABLED_CAPABILITY_EID_MIN 5 diff --git a/core/mac/src/cfg/cfgUtil/dot11f.frms b/core/mac/src/cfg/cfgUtil/dot11f.frms index 3c9004a007ae..5f50801751f5 100644 --- a/core/mac/src/cfg/cfgUtil/dot11f.frms +++ b/core/mac/src/cfg/cfgUtil/dot11f.frms @@ -2815,6 +2815,7 @@ FRAME Beacon // C.f. Sec. 7.2.3.1 OPTIE PowerConstraints; OPTIE ChanSwitchAnn; OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; OPTIE Quiet; OPTIE TPCReport; OPTIE ERPInfo; @@ -2904,6 +2905,7 @@ FRAME Beacon2 OPTIE PowerConstraints; OPTIE ChanSwitchAnn; OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; OPTIE Quiet; OPTIE TPCReport; OPTIE ERPInfo; @@ -2963,6 +2965,7 @@ FRAME BeaconIEs OPTIE PowerConstraints; OPTIE ChanSwitchAnn; OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; OPTIE Quiet; OPTIE TPCReport; OPTIE ERPInfo; @@ -3178,6 +3181,7 @@ FRAME ProbeResponse // 7.2.3.9 OPTIE PowerConstraints; OPTIE ChanSwitchAnn; OPTIE ext_chan_switch_ann; + OPTIE SuppOperatingClasses; OPTIE Quiet; OPTIE TPCReport; OPTIE ERPInfo; diff --git a/core/mac/src/include/dot11f.h b/core/mac/src/include/dot11f.h index 09dfde671127..a174f5e35f9e 100644 --- a/core/mac/src/include/dot11f.h +++ b/core/mac/src/include/dot11f.h @@ -35,7 +35,7 @@ * * * This file was automatically generated by 'framesc' - * Mon Nov 16 10:55:21 2015 from the following file(s): + * Mon Nov 16 14:10:10 2015 from the following file(s): * * dot11f.frms * @@ -7533,6 +7533,7 @@ typedef struct sDot11fBeacon{ tDot11fIEPowerConstraints PowerConstraints; tDot11fIEChanSwitchAnn ChanSwitchAnn; tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; tDot11fIEQuiet Quiet; tDot11fIETPCReport TPCReport; tDot11fIEERPInfo ERPInfo; @@ -7627,6 +7628,7 @@ typedef struct sDot11fBeacon2{ tDot11fIEPowerConstraints PowerConstraints; tDot11fIEChanSwitchAnn ChanSwitchAnn; tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; tDot11fIEQuiet Quiet; tDot11fIETPCReport TPCReport; tDot11fIEERPInfo ERPInfo; @@ -7698,6 +7700,7 @@ typedef struct sDot11fBeaconIEs{ tDot11fIEPowerConstraints PowerConstraints; tDot11fIEChanSwitchAnn ChanSwitchAnn; tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; tDot11fIEQuiet Quiet; tDot11fIETPCReport TPCReport; tDot11fIEERPInfo ERPInfo; @@ -8110,6 +8113,7 @@ typedef struct sDot11fProbeResponse{ tDot11fIEPowerConstraints PowerConstraints; tDot11fIEChanSwitchAnn ChanSwitchAnn; tDot11fIEext_chan_switch_ann ext_chan_switch_ann; + tDot11fIESuppOperatingClasses SuppOperatingClasses; tDot11fIEQuiet Quiet; tDot11fIETPCReport TPCReport; tDot11fIEERPInfo ERPInfo; diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index afbfd5e339e6..42f016a09163 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -109,6 +109,7 @@ typedef struct sSirProbeRespBeacon { 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; @@ -124,6 +125,7 @@ typedef struct sSirProbeRespBeacon { uint8_t ssidPresent; uint8_t suppRatesPresent; uint8_t extendedRatesPresent; + uint8_t supp_operating_class_present; uint8_t cfPresent; uint8_t dsParamsPresent; uint8_t timPresent; @@ -961,5 +963,7 @@ populate_dot11f_avoid_channel_ie(tpAniSirGlobal mac_ctx, tSirRetStatus populate_dot11f_timing_advert_frame(tpAniSirGlobal pMac, tDot11fTimingAdvertisementFrame *frame); +void populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr, + tDot11fIESuppOperatingClasses *dot_11_ptr, tpPESession session_entry); #endif /* __PARSE_H__ */ diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 7e0b23cbf2d9..28d19414a107 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -293,6 +293,8 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session) &bcn_2->ext_chan_switch_ann, session); + populate_dot11_supp_operating_classes(mac_ctx, + &bcn_2->SuppOperatingClasses, session); populate_dot11f_country(mac_ctx, &bcn_2->Country, session); if (bcn_1->Capabilities.qos) populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet, @@ -582,6 +584,15 @@ void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac, sizeof(beacon2->ext_chan_switch_ann)); } + /* Supported operating class */ + if (beacon2->SuppOperatingClasses.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + SIR_MAC_OPERATING_CLASS_EID); + cdf_mem_copy((void *)&prb_rsp->SuppOperatingClasses, + (void *)&beacon2->SuppOperatingClasses, + sizeof(beacon2->SuppOperatingClasses)); + } + #ifdef FEATURE_AP_MCC_CH_AVOIDANCE if (beacon2->QComVendorIE.present) { set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, diff --git a/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/core/mac/src/sys/legacy/src/utils/src/dot11f.c index aed4bd917005..3cbbf29ae9e1 100644 --- a/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -6136,6 +6136,10 @@ static const tIEDefn IES_Beacon[] = { 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, @@ -6331,6 +6335,10 @@ static const tIEDefn IES_Beacon2[] = { 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, @@ -6507,6 +6515,10 @@ static const tIEDefn IES_BeaconIEs[] = { 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, @@ -7115,6 +7127,10 @@ static const tIEDefn IES_ProbeResponse[] = { 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, }, diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 42e618d60671..f7cfb78f38bb 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -275,6 +275,48 @@ populate_dot11f_chan_switch_ann(tpAniSirGlobal pMac, pDot11f->present = 1; } +/** + * populate_dot11_supp_operating_classes() - Function to populate supported + * operating class IE + * @mac_ptr: Pointer to PMAC structure + * @dot_11_ptr: Operating class element + * @session_entry: PE session entry + * + * Return: None + */ +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; + } + } + + cds_regdm_get_curr_opclasses(&dot_11_ptr->num_classes, + &dot_11_ptr->classes[1]); + dot_11_ptr->classes[0] = cds_regdm_get_opclass_from_channel( + mac_ptr->scan.countryCodeCurrent, + session_entry->currentOperChannel, + ch_bandwidth); + dot_11_ptr->num_classes++; + dot_11_ptr->present = 1; +} + void populate_dot11f_chan_switch_wrapper(tpAniSirGlobal pMac, tDot11fIEChannelSwitchWrapper *pDot11f, @@ -2293,6 +2335,13 @@ tSirRetStatus sir_convert_probe_frame2_struct(tpAniSirGlobal pMac, sizeof(tDot11fIEext_chan_switch_ann)); } + if (pr->SuppOperatingClasses.present) { + pProbeResp->supp_operating_class_present = 1; + cdf_mem_copy(&pProbeResp->supp_operating_classes, + &pr->SuppOperatingClasses, + sizeof(tDot11fIESuppOperatingClasses)); + } + if (pr->sec_chan_offset_ele.present) { pProbeResp->sec_chan_offset_present = 1; cdf_mem_copy(&pProbeResp->sec_chan_offset, @@ -3484,6 +3533,13 @@ sir_parse_beacon_ie(tpAniSirGlobal pMac, sizeof(pBeaconStruct->channelSwitchIE)); } + if (pBies->SuppOperatingClasses.present) { + pBeaconStruct->supp_operating_class_present = 1; + cdf_mem_copy(&pBeaconStruct->supp_operating_classes, + &pBies->SuppOperatingClasses, + sizeof(tDot11fIESuppOperatingClasses)); + } + if (pBies->ext_chan_switch_ann.present) { pBeaconStruct->ext_chan_switch_present = 1; cdf_mem_copy(&pBeaconStruct->ext_chan_switch, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 39139da7c8b8..f9d06bd146d9 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18602,6 +18602,7 @@ csr_update_op_class_array(tpAniSirGlobal mac_ctx, uint8_t j = 0, idx = 0, class = 0; bool found = false; uint8_t num_channels = channel_info->numChannels; + uint8_t ch_bandwidth; sms_log(mac_ctx, LOG1, FL("Num of %s channels, %d"), @@ -18609,23 +18610,28 @@ csr_update_op_class_array(tpAniSirGlobal mac_ctx, for (idx = 0; idx < num_channels && *i < (SIR_MAC_MAX_SUPP_OPER_CLASSES - 1); idx++) { - class = cds_regdm_get_opclass_from_channel( - mac_ctx->scan.countryCodeCurrent, - channel_info->channelList[idx], - BWALL); - sms_log(mac_ctx, LOG4, FL("for chan %d, op class: %d"), - channel_info->channelList[idx], class); - - found = false; - for (j = 0; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; j++) { - if (op_classes[j] == class) { - found = true; - break; + for (ch_bandwidth = BW20; ch_bandwidth < BWALL; + ch_bandwidth++) { + class = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel_info->channelList[idx], + ch_bandwidth); + sms_log(mac_ctx, LOG4, FL("for chan %d, op class: %d"), + channel_info->channelList[idx], class); + + found = false; + for (j = 0; j < SIR_MAC_MAX_SUPP_OPER_CLASSES - 1; + j++) { + if (op_classes[j] == class) { + found = true; + break; + } + } + + if (!found) { + op_classes[*i] = class; + *i = *i + 1; } - } - if (!found) { - op_classes[*i] = class; - *i = *i + 1; } } } -- cgit v1.2.3 From c485936127826d20c17259c6f45110b9cfc95dcb Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Tue, 24 Nov 2015 17:19:48 -0800 Subject: qcacld-3.0: unlock the sme scan active list Sme is stuck due to scan active list mutex lock. Release the sme scan active list lock if the active list is empty. Change-Id: Id05c642fe6fad30e40efa18a213158c331b5a502 CRs-Fixed: 943583 --- core/sme/src/csr/csr_api_scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 806d5b5f4569..6bfda4cccdd1 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -4082,6 +4082,7 @@ CDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac_ctx, LL_ACCESS_NOLOCK)) { sms_log(mac_ctx, LOGE, FL(" Active list Empty scanId: %d"), scan_id); + csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList); return CDF_STATUS_SUCCESS; } localentry = csr_ll_peek_head(&mac_ctx->sme.smeScanCmdActiveList, -- cgit v1.2.3 From d580e0662b7768f54cae530d56ca70b7dc4eeb10 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Wed, 14 Oct 2015 11:19:00 +0530 Subject: qcacld-3.0: Restore service ready extended event Restore the support for service ready extended event since the required FW support is in place. Without the service ready extended event, the FW mode configuration and scan mode configuration in the driver would be initialized to zero i.e., all the dual mac features would be disabled. Otherwise, the default values of these two params would be set based on the default values present in this extended event, which is set by the FW. CRs-Fixed: 923182 Change-Id: I31aa6420f3076f61008a809fe134b99f9b0dbc08 --- core/wma/inc/wma.h | 13 +++- core/wma/src/wma_main.c | 157 +++++++++++++++++++++++++++++++++++------------- core/wmi/wmi_unified.c | 10 ++- 3 files changed, 137 insertions(+), 43 deletions(-) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index b72d9fc433d1..c2204a5d1213 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -57,6 +57,7 @@ #ifndef QCA_WIFI_3_0_EMU #define WMA_READY_EVENTID_TIMEOUT 2000 +#define WMA_SERVICE_READY_EXT_TIMEOUT 2000 #define WMA_TGT_SUSPEND_COMPLETE_TIMEOUT 6000 #define WMA_WAKE_LOCK_TIMEOUT 1000 #define WMA_MAX_RESUME_RETRY 1000 @@ -66,6 +67,7 @@ #else #define WMA_READY_EVENTID_TIMEOUT 200000 +#define WMA_SERVICE_READY_EXT_TIMEOUT 200000 #define WMA_TGT_SUSPEND_COMPLETE_TIMEOUT 300000 #define WMA_WAKE_LOCK_TIMEOUT 1000 #define WMA_MAX_RESUME_RETRY 1000 @@ -1348,9 +1350,18 @@ typedef struct { } wmi_desc_pool; uint8_t max_scan; struct wmi_init_cmd saved_wmi_init_cmd; - cdf_event_t service_ready_ext_evt; uint16_t self_gen_frm_pwr; bool tx_chain_mask_cck; + /* Going with a timer instead of wait event because on receiving the + * service ready event, we will be waiting on the MC thread for the + * service extended ready event which is also processed in MC thread. + * This leads to MC thread being stuck. Alternative was to process + * these events in tasklet/workqueue context. But, this leads to + * race conditions when the events are processed in two different + * context. So, processing ready event and extended ready event in + * the serialized MC thread context with a timer. + */ + cdf_mc_timer_t service_ready_ext_timer; } t_wma_handle, *tp_wma_handle; /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 319e076a975f..f37d14f34d8d 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -79,7 +79,6 @@ #include "cds_concurrency.h" #define WMA_LOG_COMPLETION_TIMER 10000 /* 10 seconds */ -#define WMA_SERVICE_READY_EXT_TIMEOUT 2000 /* 2 seconds */ static uint32_t g_fw_wlan_feat_caps; @@ -94,6 +93,38 @@ uint8_t wma_get_fw_wlan_feat_caps(uint8_t featEnumValue) return (g_fw_wlan_feat_caps & (1 << featEnumValue)) ? true : false; } +/** + * wma_service_ready_ext_evt_timeout() - Service ready extended event timeout + * @data: Timeout handler data + * + * This function is called when the FW fails to send WMI_SERVICE_READY_EXT_EVENT + * message + * + * Return: None + */ +static void wma_service_ready_ext_evt_timeout(void *data) +{ + tp_wma_handle wma_handle; + + WMA_LOGA("%s: Timeout waiting for WMI_SERVICE_READY_EXT_EVENT", + __func__); + + wma_handle = (tp_wma_handle) data; + + if (!wma_handle) { + WMA_LOGE("%s: Invalid WMA handle", __func__); + goto end; + } + + if (wma_handle->saved_wmi_init_cmd.buf) { + wmi_buf_free(wma_handle->saved_wmi_init_cmd.buf); + wma_handle->saved_wmi_init_cmd.buf = NULL; + } +end: + /* Panic so that we can debug why FW is not responding */ + CDF_BUG(0); +} + /** * wma_set_default_tgt_config() - set default tgt config * @wma_handle: wma handle @@ -1702,6 +1733,16 @@ CDF_STATUS wma_open(void *cds_context, WMA_LOGP("%s: wma_ready_event initialization failed", __func__); goto err_event_init; } + + cdf_status = cdf_mc_timer_init(&wma_handle->service_ready_ext_timer, + CDF_TIMER_TYPE_SW, + wma_service_ready_ext_evt_timeout, + wma_handle); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + WMA_LOGE("Failed to initialize service ready ext timeout"); + goto err_event_init; + } + cdf_status = cdf_event_init(&wma_handle->target_suspend); if (cdf_status != CDF_STATUS_SUCCESS) { WMA_LOGP("%s: target suspend event initialization failed", @@ -2711,12 +2752,6 @@ CDF_STATUS wma_start(void *cds_ctx) goto end; } - cdf_status = cdf_event_init(&wma_handle->service_ready_ext_evt); - if (CDF_STATUS_SUCCESS != cdf_status) { - WMA_LOGE("Unable to init service_ready_ext_evt"); - goto end; - } - end: WMA_LOGD("%s: Exit", __func__); return cdf_status; @@ -2787,12 +2822,6 @@ CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) goto end; } - cdf_status = cdf_event_destroy(&wma_handle->service_ready_ext_evt); - if (cdf_status != CDF_STATUS_SUCCESS) { - WMA_LOGE("Failed to destroy service_ready_ext_evt"); - goto end; - } - end: WMA_LOGD("%s: Exit", __func__); return cdf_status; @@ -3031,6 +3060,11 @@ CDF_STATUS wma_close(void *cds_ctx) /* close the cdf events */ cdf_event_destroy(&wma_handle->wma_ready_event); + cdf_status = cdf_mc_timer_destroy(&wma_handle->service_ready_ext_timer); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) + WMA_LOGP("%s: Failed to destroy service ready ext event timer", + __func__); + cdf_event_destroy(&wma_handle->target_suspend); cdf_event_destroy(&wma_handle->wma_resume_event); cdf_event_destroy(&wma_handle->recovery_event); @@ -3593,13 +3627,17 @@ void wma_dump_dbs_hw_mode(tp_wma_handle wma_handle) /** * wma_init_scan_fw_mode_config() - Initialize scan/fw mode config * @wma_handle: WMA handle + * @scan_config: Scam mode configuration + * @fw_config: FW mode configuration * * Enables all the valid bits of concurrent_scan_config_bits and * fw_mode_config_bits. * * Return: None */ -void wma_init_scan_fw_mode_config(tp_wma_handle wma_handle) +void wma_init_scan_fw_mode_config(tp_wma_handle wma_handle, + uint32_t scan_config, + uint32_t fw_config) { tpAniSirGlobal mac = cds_get_context(CDF_MODULE_ID_PE); @@ -3627,28 +3665,24 @@ void wma_init_scan_fw_mode_config(tp_wma_handle wma_handle) goto done; } - /* The input from FW team is that, by default all the - * bits of concurrent_scan_config_bits and - * FW_mode_config_bits will be enabled. So, - * enabling all the bits here. Adding this API so that - * in the future/variant chipsets, when not all bits are - * enabled, FW can send the initial configuration of the above - * two parameters using the service ready event and they - * can be initialized here. - */ - /* Initialize concurrent_scan_config_bits */ + /* Initialize concurrent_scan_config_bits with default FW value */ WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_SET( - wma_handle->dual_mac_cfg.cur_scan_config, 1); + wma_handle->dual_mac_cfg.cur_scan_config, + WMI_DBS_CONC_SCAN_CFG_DBS_SCAN_GET(scan_config)); WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_SET( - wma_handle->dual_mac_cfg.cur_scan_config, 1); + wma_handle->dual_mac_cfg.cur_scan_config, + WMI_DBS_CONC_SCAN_CFG_AGILE_SCAN_GET(scan_config)); WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_SET( - wma_handle->dual_mac_cfg.cur_scan_config, 1); + wma_handle->dual_mac_cfg.cur_scan_config, + WMI_DBS_CONC_SCAN_CFG_AGILE_DFS_SCAN_GET(scan_config)); - /* Initialize FW_mode_config_bits */ + /* Initialize fw_mode_config_bits with default FW value */ WMI_DBS_FW_MODE_CFG_DBS_SET( - wma_handle->dual_mac_cfg.cur_fw_mode_config, 1); + wma_handle->dual_mac_cfg.cur_fw_mode_config, + WMI_DBS_FW_MODE_CFG_DBS_GET(fw_config)); WMI_DBS_FW_MODE_CFG_AGILE_DFS_SET( - wma_handle->dual_mac_cfg.cur_fw_mode_config, 1); + wma_handle->dual_mac_cfg.cur_fw_mode_config, + WMI_DBS_FW_MODE_CFG_AGILE_DFS_GET(fw_config)); done: /* Initialize the previous scan/fw mode config */ wma_handle->dual_mac_cfg.prev_scan_config = @@ -3680,6 +3714,7 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) wmi_service_ready_event_fixed_param *ev; int status; uint32_t *ev_wlan_dbs_hw_mode_list; + CDF_STATUS ret; WMA_LOGD("%s: Enter", __func__); @@ -3713,7 +3748,13 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) wma_dump_dbs_hw_mode(wma_handle); - wma_init_scan_fw_mode_config(wma_handle); + /* Initializes the fw_mode and scan_config to zero. + * If ext service ready event is present it will set + * the actual values of these two params. + * This is to ensure that no garbage values would be + * present in the absence of ext service ready event. + */ + wma_init_scan_fw_mode_config(wma_handle, 0, 0); wma_handle->phy_capability = ev->phy_capability; wma_handle->max_frag_entry = ev->max_frag_entry; @@ -3872,13 +3913,40 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) 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; + /* A host, which supports WMI_SERVICE_READY_EXT_EVENTID, would need to + * check the WMI_SERVICE_READY message for an "extension" flag, and if + * this flag is set, then hold off on sending the WMI_INIT message until + * WMI_SERVICE_READY_EXT_EVENTID is received. + */ + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_EXT_MSG)) { + /* No service extended message support. + * Send INIT command immediately + */ + 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; + } + } else { + /* Need to save and send the WMI INIT command only after + * processing service ready extended event + */ + wma_handle->saved_wmi_init_cmd.buf = buf; + wma_handle->saved_wmi_init_cmd.buf_len = len; + /* The saved 'buf' will be freed after sending INIT command or + * in other cases as required + */ + ret = cdf_mc_timer_start(&wma_handle->service_ready_ext_timer, + WMA_SERVICE_READY_EXT_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(ret)) + WMA_LOGP("Failed to start the service ready ext timer"); + + WMA_LOGA("%s: WMA waiting for WMI_SERVICE_READY_EXT_EVENTID", + __func__); } } @@ -3923,9 +3991,13 @@ void wma_rx_service_ready_ext_event(WMA_HANDLE handle, void *event) return; } - ret = cdf_event_set(&wma_handle->service_ready_ext_evt); - if (CDF_STATUS_SUCCESS != ret) { - WMA_LOGP("Failed to set service_ready_ext_evt"); + WMA_LOGA("%s: Defaults: scan config:%x FW mode config:%x", + __func__, ev->default_conc_scan_config_bits, + ev->default_fw_config_bits); + + ret = cdf_mc_timer_stop(&wma_handle->service_ready_ext_timer); + if (!CDF_IS_STATUS_SUCCESS(ret)) { + WMA_LOGP("Failed to stop the service ready ext timer"); return; } @@ -3944,6 +4016,9 @@ void wma_rx_service_ready_ext_event(WMA_HANDLE handle, void *event) } wma_handle->saved_wmi_init_cmd.buf = NULL; + wma_init_scan_fw_mode_config(wma_handle, + ev->default_conc_scan_config_bits, + ev->default_fw_config_bits); } /** diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index c534fe508dd6..79fe92f46b6d 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -1014,7 +1014,15 @@ void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) goto end; } - if (id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) { + if ((id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) && + /* WMI_SERVICE_READY_EXT_EVENTID is supposed to be part of the + * WMI_GRP_START group. Since the group is out of space, FW + * has accomodated this in WMI_GRP_VDEV. + * WMI_SERVICE_READY_EXT_EVENTID does not have any specific + * event handler registered. So, we do not want to go through + * the WMI registered event handler path for this event. + */ + (id != WMI_SERVICE_READY_EXT_EVENTID)) { uint32_t idx = 0; idx = wmi_unified_get_event_handler_ix(wmi_handle, id); -- cgit v1.2.3 From e54e4bc2ff25b2c890cf413c2a71fc26b0ff0d5b Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Mon, 23 Nov 2015 11:28:58 -0800 Subject: qcacld-3.0: Do not allow NoA setting in non P2P GO mode Propagation from qcacld-2.0 to qcacld-3.0 - FW asserts after receiving P2P NOA parameter in non P2P GO mode - Add P2P GO mode check in set NOA IOCTL and do not allow this command in non P2P GO modes Change-Id: Ie786dcf33fc50eacadb407d74ae5638da68cf0d2 CRs-Fixed: 919889 --- core/hdd/src/wlan_hdd_wext.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 064dbdceb654..245519f8501d 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -7664,6 +7664,14 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, { p2p_app_setP2pPs_t p2pNoA; + if (pAdapter->device_mode != WLAN_HDD_P2P_GO) { + hdd_err("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]; -- cgit v1.2.3 From 04475348cd38bf76d9d773580426fe44f59c05b7 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Mon, 23 Nov 2015 11:36:53 -0800 Subject: qcacld-3.0: Fix agc registers dump logic to avoid fw assert Propagation from qcacld-2.0 to qcacld-3.0 - Current AGC registers dump logic is not correct and its not reading correct target registers - Add correct AGC register read recipe to read correct AGC data - Wake up SoC before reading any target register Change-Id: I38016f91bf3d124e93e304522058e97daa711f4a CRs-Fixed: 911554 --- core/hif/src/mp_dev.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/core/hif/src/mp_dev.c b/core/hif/src/mp_dev.c index 276e60ae1ab1..6d261735c580 100644 --- a/core/hif/src/mp_dev.c +++ b/core/hif/src/mp_dev.c @@ -60,6 +60,14 @@ #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 { uint32_t chaninfo_ctrl_orig; uint32_t gain_min_offsets_orig; @@ -253,6 +261,8 @@ void priv_dump_agc(struct ol_softc *scn) int i, len = 30; /* check this value for Rome and Peregrine */ uint32_t chain0, chain1, chain_mask, val; + A_TARGET_ACCESS_BEGIN(scn); + chain_mask = get_target_reg_bits(scn->mem, BB_multichain_enable, MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK); @@ -268,9 +278,11 @@ void priv_dump_agc(struct ol_softc *scn) HIF_TRACE("%s: AGC history buffer dump: E", __func__); if (chain0) { for (i = 0; i < len; i++) { - val = - hif_read32_mb(scn->mem + BB_chaninfo_tab_b0 + - i * 4); + hif_write32_mb(scn->mem + + PHY_BB_CHN_TABLES_INTF_ADDR, + BB_chaninfo_tab_b0 + i * 4); + val = hif_read32_mb(scn->mem + + PHY_BB_CHN_TABLES_INTF_DATA); cdf_print("0x%x\t", val); if (i % 4 == 0) cdf_print("\n"); @@ -278,9 +290,11 @@ void priv_dump_agc(struct ol_softc *scn) } if (chain1) { for (i = 0; i < len; i++) { - val = - hif_read32_mb(scn->mem + BB_chaninfo_tab_b1 + - i * 4); + hif_write32_mb(scn->mem + + PHY_BB_CHN1_TABLES_INTF_ADDR, + BB_chaninfo_tab_b0 + i * 4); + val = hif_read32_mb(scn->mem + + PHY_BB_CHN1_TABLES_INTF_DATA); cdf_print("0x%x\t", val); if (i % 4 == 0) cdf_print("\n"); @@ -290,6 +304,9 @@ void priv_dump_agc(struct ol_softc *scn) /* restore original value */ hif_write32_mb(scn->mem + BB_gains_min_offsets, g_priv_dump_ctx.gain_min_offsets_orig); + + A_TARGET_ACCESS_END(scn); + return; } -- cgit v1.2.3 From 743205e1fa5709ba7ef43c2a268f67caa1a8ce11 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 10:58:51 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirRemainOnChnReq Replace tSirMacAddr with cdf_mac_addr in sSirRemainOnChnReq. Change-Id: I75594fc51ae1a82ef08b3e0b43c2a8733387b9af CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_p2p.c | 6 +++--- core/sme/src/p2p/p2p_api.c | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3fc95da65826..72f993d1957f 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -370,7 +370,7 @@ typedef struct sSirRemainOnChnReq { uint16_t messageType; uint16_t length; uint8_t sessionId; - tSirMacAddr selfMacAddr; + struct cdf_mac_addr selfMacAddr; uint8_t chnNum; uint8_t phyMode; uint32_t duration; diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c index 7f29157ddfcd..1bd354293c53 100644 --- a/core/mac/src/pe/lim/lim_p2p.c +++ b/core/mac/src/pe/lim/lim_p2p.c @@ -101,8 +101,8 @@ static CDF_STATUS lim_send_hal_req_remain_on_chan_offload(tpAniSirGlobal pMac, msg.bodyval = 0; cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr, - (uint8_t *) pRemOnChnReq->selfMacAddr, - sizeof(tSirMacAddr)); + (uint8_t *) pRemOnChnReq->selfMacAddr.bytes, + CDF_MAC_ADDR_SIZE); cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId, (uint8_t *) bssid, sizeof(tSirMacAddr)); @@ -347,7 +347,7 @@ void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *dat /* delete the session */ if ((psessionEntry = pe_find_session_by_bssid(pMac, MsgRemainonChannel-> - selfMacAddr, + selfMacAddr.bytes, &sessionId)) != NULL) { if (LIM_IS_P2P_DEVICE_ROLE(psessionEntry)) { pe_delete_session(pMac, psessionEntry); diff --git a/core/sme/src/p2p/p2p_api.c b/core/sme/src/p2p/p2p_api.c index ec8b742263c8..36c17d435651 100644 --- a/core/sme/src/p2p/p2p_api.c +++ b/core/sme/src/p2p/p2p_api.c @@ -79,8 +79,7 @@ CDF_STATUS p2p_process_remain_on_channel_cmd(tpAniSirGlobal pMac, cdf_mem_set(pMsg, sizeof(tSirRemainOnChnReq), 0); pMsg->messageType = eWNI_SME_REMAIN_ON_CHANNEL_REQ; pMsg->length = (uint16_t) len; - cdf_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->selfMacAddr, &pSession->selfMacAddr); pMsg->chnNum = p2pRemainonChn->u.remainChlCmd.chn; pMsg->phyMode = p2pRemainonChn->u.remainChlCmd.phyMode; pMsg->duration = p2pRemainonChn->u.remainChlCmd.duration; -- cgit v1.2.3 From 1d999304e626db1daa5c1606ce54653fdce2733b Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 11:20:22 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirScanOffloadReq Replace tSirMacAddr with cdf_mac_addr in sSirScanOffloadReq. Change-Id: Ia42f230491b0500f612c983c5769401249b6d961 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_p2p.c | 10 +++------- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 8 ++++---- core/wma/src/wma_scan_roam.c | 2 +- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 72f993d1957f..6f639a8ca7f8 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3497,11 +3497,11 @@ typedef struct sAniHandoffReq { typedef struct sSirScanOffloadReq { uint8_t sessionId; - tSirMacAddr bssId; + struct cdf_mac_addr bssId; uint8_t numSsid; tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; uint8_t hiddenSsid; - tSirMacAddr selfMacAddr; + struct cdf_mac_addr selfMacAddr; tSirBssType bssType; uint8_t dot11mode; tSirScanType scanType; diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c index 1bd354293c53..08ed8fce3ce3 100644 --- a/core/mac/src/pe/lim/lim_p2p.c +++ b/core/mac/src/pe/lim/lim_p2p.c @@ -84,8 +84,6 @@ static CDF_STATUS lim_send_hal_req_remain_on_chan_offload(tpAniSirGlobal pMac, tSirScanOffloadReq *pScanOffloadReq; tSirMsgQ msg; tSirRetStatus rc = eSIR_SUCCESS; - uint8_t bssid[CDF_MAC_ADDR_SIZE] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; pScanOffloadReq = cdf_mem_malloc(sizeof(tSirScanOffloadReq)); if (NULL == pScanOffloadReq) { @@ -100,12 +98,10 @@ static CDF_STATUS lim_send_hal_req_remain_on_chan_offload(tpAniSirGlobal pMac, msg.bodyptr = pScanOffloadReq; msg.bodyval = 0; - cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr, - (uint8_t *) pRemOnChnReq->selfMacAddr.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pScanOffloadReq->selfMacAddr, + &pRemOnChnReq->selfMacAddr); - cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId, - (uint8_t *) bssid, sizeof(tSirMacAddr)); + cdf_set_macaddr_broadcast(&pScanOffloadReq->bssId); pScanOffloadReq->scanType = eSIR_PASSIVE_SCAN; pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_LISTEN; pScanOffloadReq->minChannelTime = pRemOnChnReq->duration; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 537e9223c152..7569b20b2069 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1279,8 +1279,8 @@ static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, msg.bodyptr = pScanOffloadReq; msg.bodyval = 0; - cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId, - (uint8_t *) pScanReq->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId.bytes, + (uint8_t *) pScanReq->bssId, CDF_MAC_ADDR_SIZE); if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) { lim_log(pMac, LOGE, @@ -1299,8 +1299,8 @@ static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, } pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid; - cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr, - (uint8_t *) pScanReq->selfMacAddr, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr.bytes, + (uint8_t *) pScanReq->selfMacAddr, CDF_MAC_ADDR_SIZE); pScanOffloadReq->bssType = pScanReq->bssType; pScanOffloadReq->dot11mode = pScanReq->dot11mode; pScanOffloadReq->scanType = pScanReq->scanType; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index f5c2ff56ec69..2956990872be 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -507,7 +507,7 @@ CDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, 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); + WMI_CHAR_ARRAY_TO_MAC_ADDR(scan_req->bssId.bytes, bssid); buf_ptr += WMI_TLV_HDR_SIZE + (cmd->num_bssid * sizeof(wmi_mac_addr)); cmd->ie_len = scan_req->uIEFieldLen; -- cgit v1.2.3 From b908e1b656793c8739e88165813cdaf871f54e98 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 11:43:31 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeScanReq Replace tSirMacAddr with cdf_mac_addr in sSirSmeScanReq. Change-Id: I805e32462c89d72bd8a038eaef0379f7b58b33c3 CRs-Fixed: 898864 --- core/cdf/inc/cdf_util.h | 2 +- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 9 ++++---- core/mac/src/pe/lim/lim_sme_req_utils.c | 3 ++- core/sme/src/csr/csr_api_scan.c | 25 +++++++++------------- 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/core/cdf/inc/cdf_util.h b/core/cdf/inc/cdf_util.h index 2318d6651a6e..7d9e16a60c03 100644 --- a/core/cdf/inc/cdf_util.h +++ b/core/cdf/inc/cdf_util.h @@ -189,7 +189,7 @@ CDF_INLINE_FN bool cdf_is_macaddr_group(struct cdf_mac_addr *pMacAddr) * @pMacAddr: Pointer to the cdf MacAddress to check * * Return: true if the input MacAddress is a broadcast address - * flase if the input MacAddress is not a broadcast address + * false if the input MacAddress is not a broadcast address */ CDF_INLINE_FN bool cdf_is_macaddr_broadcast(struct cdf_mac_addr *pMacAddr) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 6f639a8ca7f8..290e3c42725a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -745,9 +745,9 @@ typedef struct sSirSmeScanReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; + struct cdf_mac_addr bssId; tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID]; - tSirMacAddr selfMacAddr; /* Added For BT-AMP Support */ + struct cdf_mac_addr selfMacAddr; /* Added For BT-AMP Support */ tSirBssType bssType; uint8_t dot11mode; tSirScanType scanType; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 7569b20b2069..1e9aa2c76a29 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1279,8 +1279,7 @@ static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, msg.bodyptr = pScanOffloadReq; msg.bodyval = 0; - cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId.bytes, - (uint8_t *) pScanReq->bssId, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pScanOffloadReq->bssId, &pScanReq->bssId); if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) { lim_log(pMac, LOGE, @@ -1299,8 +1298,7 @@ static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, } pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid; - cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr.bytes, - (uint8_t *) pScanReq->selfMacAddr, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pScanOffloadReq->selfMacAddr, &pScanReq->selfMacAddr); pScanOffloadReq->bssType = pScanReq->bssType; pScanOffloadReq->dot11mode = pScanReq->dot11mode; pScanOffloadReq->scanType = pScanReq->scanType; @@ -1424,7 +1422,8 @@ static void __lim_process_sme_scan_req(tpAniSirGlobal mac_ctx, * copy the Self MAC address from SmeReq to the globalplace, * used for sending probe req */ - sir_copy_mac_addr(mac_ctx->lim.gSelfMacAddr, scan_req->selfMacAddr); + sir_copy_mac_addr(mac_ctx->lim.gSelfMacAddr, + scan_req->selfMacAddr.bytes); valid_req = lim_is_sme_scan_req_valid(mac_ctx, scan_req); if (!valid_req || mac_ctx->lim.scan_disabled) { diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c index 550231ff03da..f0f660fdfd11 100644 --- a/core/mac/src/pe/lim/lim_sme_req_utils.c +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -698,7 +698,8 @@ uint8_t lim_is_sme_scan_req_valid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq) lim_log(pMac, LOGE, FL("Invalid BSS Type")); valid = false; } - if (lim_is_group_addr(pScanReq->bssId) && !lim_is_addr_bc(pScanReq->bssId)) { + if (cdf_is_macaddr_group(&pScanReq->bssId) && + !cdf_is_macaddr_broadcast(&pScanReq->bssId)) { valid = false; lim_log(pMac, LOGE, FL("BSSID is group addr and is not Broadcast Addr")); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 6bfda4cccdd1..37e197600c83 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -4856,8 +4856,7 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, uint32_t minChnTime; /* in units of milliseconds */ uint32_t maxChnTime; /* in units of milliseconds */ uint32_t i; - uint8_t selfMacAddr[CDF_MAC_ADDR_SIZE]; - uint8_t *pSelfMac = NULL; + struct cdf_mac_addr selfmac; msgLen = (uint16_t) (sizeof(tSirSmeScanReq) - sizeof(pMsg->channelList.channelNumber) + @@ -4904,8 +4903,8 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, pMsg->bssType = csr_translate_bsstype_to_mac_type(pScanReq->BSSType); if (CSR_IS_SESSION_VALID(pMac, sessionId)) { - pSelfMac = (uint8_t *) - &pMac->roam.roamSession[sessionId].selfMacAddr; + cdf_copy_macaddr(&selfmac, + &pMac->roam.roamSession[sessionId].selfMacAddr); } else { /* * Since we don't have session for the scanning, we find a valid @@ -4913,16 +4912,15 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, */ for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { if (CSR_IS_SESSION_VALID(pMac, i)) { - pSelfMac = (uint8_t *) - &pMac->roam.roamSession[i].selfMacAddr; + cdf_copy_macaddr(&selfmac, + &pMac->roam.roamSession[i].selfMacAddr); break; } } if (CSR_ROAM_SESSION_MAX == i) { uint32_t len = CDF_MAC_ADDR_SIZE; - pSelfMac = selfMacAddr; status = wlan_cfg_get_str(pMac, WNI_CFG_STA_ID, - pSelfMac, &len); + selfmac.bytes, &len); if (!CDF_IS_STATUS_SUCCESS(status) || (len < CDF_MAC_ADDR_SIZE)) { sms_log(pMac, LOGE, @@ -4934,16 +4932,13 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, } } } - cdf_mem_copy((uint8_t *) pMsg->selfMacAddr, - pSelfMac, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->selfMacAddr, &selfmac); - /* sir_copy_mac_addr */ - cdf_mem_copy(pMsg->bssId, &pScanReq->bssid, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssId, &pScanReq->bssid); if (cdf_is_macaddr_zero(&pScanReq->bssid)) - cdf_mem_set(pMsg->bssId, sizeof(tSirMacAddr), 0xff); + cdf_set_macaddr_broadcast(&pMsg->bssId); else - cdf_mem_copy(pMsg->bssId, pScanReq->bssid.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->bssId, &pScanReq->bssid); minChnTime = pScanReq->minChnTime; maxChnTime = pScanReq->maxChnTime; -- cgit v1.2.3 From 79c1ba9afaeaa7057ff472c291e3f706ab832a89 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 12:26:28 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sMaxTxPowerParams Replace tSirMacAddr with cdf_mac_addr in sMaxTxPowerParams. Change-Id: Ia9f66cfd3a520019a83d671b7869d49558856698 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_hostapd.c | 15 ++++++--------- core/hdd/src/wlan_hdd_ioctl.c | 22 ++++++++++------------ core/hdd/src/wlan_hdd_power.c | 4 ++-- core/hdd/src/wlan_hdd_wext.c | 15 ++++++--------- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 9 +++++---- core/mac/src/pe/rrm/rrm_api.c | 17 +++++++++-------- core/sme/inc/sme_api.h | 6 +++--- core/sme/src/common/sme_api.c | 14 +++++++------- core/wma/inc/wma_if.h | 4 ++-- core/wma/src/wma_power.c | 18 +++++++++++------- 10 files changed, 61 insertions(+), 63 deletions(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 658c636eb9d5..59305a12b05d 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -3242,9 +3242,9 @@ static __iw_softap_set_max_tx_power(struct net_device *dev, 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; + struct cdf_mac_addr bssid = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + struct cdf_mac_addr selfMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER; ENTER(); @@ -3257,10 +3257,8 @@ static __iw_softap_set_max_tx_power(struct net_device *dev, return ret; /* Assign correct slef MAC address */ - cdf_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); - cdf_mem_copy(selfMac, pHostapdAdapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, &pHostapdAdapter->macAddressCurrent); + cdf_copy_macaddr(&selfMac, &pHostapdAdapter->macAddressCurrent); set_value = value[0]; if (CDF_STATUS_SUCCESS != @@ -3296,7 +3294,7 @@ static __iw_softap_set_tx_power(struct net_device *dev, hdd_context_t *hdd_ctx; int *value = (int *)extra; int set_value; - tSirMacAddr bssid; + struct cdf_mac_addr bssid; int ret; ENTER(); @@ -3309,8 +3307,7 @@ static __iw_softap_set_tx_power(struct net_device *dev, if (NULL == value) return -ENOMEM; - cdf_mem_copy(bssid, pHostapdAdapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, &pHostapdAdapter->macAddressCurrent); set_value = value[0]; if (CDF_STATUS_SUCCESS != diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 3273d6aab369..1e8db571ff9e 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -4982,8 +4982,8 @@ static int drv_cmd_max_tx_power(hdd_adapter_t *adapter, CDF_STATUS cdf_status; CDF_STATUS smeStatus; uint8_t *value = command; - tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - tSirMacAddr selfMac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + struct cdf_mac_addr bssid = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + struct cdf_mac_addr selfMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER; hdd_adapter_list_node_t *pAdapterNode = NULL; hdd_adapter_list_node_t *pNext = NULL; @@ -5001,21 +5001,19 @@ static int drv_cmd_max_tx_power(hdd_adapter_t *adapter, && CDF_STATUS_SUCCESS == cdf_status) { adapter = pAdapterNode->pAdapter; /* Assign correct self MAC address */ - cdf_mem_copy(bssid, - adapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); - cdf_mem_copy(selfMac, - adapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, + &adapter->macAddressCurrent); + cdf_copy_macaddr(&selfMac, + &adapter->macAddressCurrent); hddLog(CDF_TRACE_LEVEL_INFO, "Device mode %d max tx power %d selfMac: " MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ", adapter->device_mode, txPower, - MAC_ADDR_ARRAY(selfMac), - MAC_ADDR_ARRAY(bssid)); + MAC_ADDR_ARRAY(selfMac.bytes), + MAC_ADDR_ARRAY(bssid.bytes)); - smeStatus = sme_set_max_tx_power((tHalHandle)(hdd_ctx->hHal), - bssid, selfMac, txPower); + smeStatus = sme_set_max_tx_power(hdd_ctx->hHal, + bssid, selfMac, txPower); if (CDF_STATUS_SUCCESS != status) { hddLog(CDF_TRACE_LEVEL_ERROR, "%s:Set max tx power failed", diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 1f97634cfd7b..be764693bf76 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -2185,8 +2185,8 @@ static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, { 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 }; + struct cdf_mac_addr bssid = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + struct cdf_mac_addr selfMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER; int status; ENTER(); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 245519f8501d..2448ddf5605a 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -5080,10 +5080,9 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_TX_POWER: { - tSirMacAddr bssid; + struct cdf_mac_addr bssid; - cdf_mem_copy(bssid, pHddStaCtx->conn_info.bssId.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, &pHddStaCtx->conn_info.bssId); if (sme_set_tx_power (hHal, pAdapter->sessionId, bssid, pAdapter->device_mode, @@ -5096,16 +5095,14 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_MAX_TX_POWER: { - tSirMacAddr bssid; - tSirMacAddr selfMac; + struct cdf_mac_addr bssid; + struct cdf_mac_addr selfMac; hddLog(CDF_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm", __func__, set_value); - cdf_mem_copy(bssid, pHddStaCtx->conn_info.bssId.bytes, - CDF_MAC_ADDR_SIZE); - cdf_mem_copy(selfMac, pHddStaCtx->conn_info.bssId.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, &pHddStaCtx->conn_info.bssId); + cdf_copy_macaddr(&selfMac, &pHddStaCtx->conn_info.bssId); if (sme_set_max_tx_power(hHal, bssid, selfMac, set_value) != CDF_STATUS_SUCCESS) { diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 1e9aa2c76a29..88d18497ea58 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4535,10 +4535,11 @@ lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, return eSIR_FAILURE; } pMaxTxParams->power = txPower; - cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId, - sizeof(tSirMacAddr)); - cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMaxTxParams->bssId.bytes, pSessionEntry->bssId, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes, + pSessionEntry->selfMacAddr, + CDF_MAC_ADDR_SIZE); msgQ.type = WMA_SET_MAX_TX_POWER_REQ; msgQ.bodyptr = pMaxTxParams; diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index 3f2f96f26c4f..38f748a0d478 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -165,10 +165,11 @@ rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, } /* Allocated memory for pMaxTxParams...will be freed in other module */ pMaxTxParams->power = txPower; - cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId, - sizeof(tSirMacAddr)); - cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMaxTxParams->bssId.bytes, pSessionEntry->bssId, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes, + pSessionEntry->selfMacAddr, + CDF_MAC_ADDR_SIZE); msgQ.type = WMA_SET_MAX_TX_POWER_REQ; msgQ.reserved = 0; @@ -213,9 +214,8 @@ tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; tpPESession pSessionEntry; uint8_t sessionId, i; - tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if (cdf_mem_compare(bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) { + if (cdf_is_macaddr_broadcast(&pMaxTxParams->bssId)) { for (i = 0; i < pMac->lim.maxBssId; i++) { if ((pMac->lim.gpSession[i].valid == true)) { pSessionEntry = &pMac->lim.gpSession[i]; @@ -225,8 +225,9 @@ tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) } } else { if ((pSessionEntry = - pe_find_session_by_bssid(pMac, pMaxTxParams->bssId, - &sessionId)) == NULL) { + pe_find_session_by_bssid(pMac, + pMaxTxParams->bssId.bytes, + &sessionId)) == NULL) { PELOGE(lim_log (pMac, LOGE, FL("Unable to find session:")); ) diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index b80ae17a0ed6..ec368086c3cc 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -553,11 +553,11 @@ CDF_STATUS sme_get_gtk_offload(tHalHandle hal_ctx, #endif /* WLAN_FEATURE_GTK_OFFLOAD */ uint16_t sme_chn_to_freq(uint8_t chanNum); bool sme_is_channel_valid(tHalHandle hHal, uint8_t channel); -CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, tSirMacAddr pBssid, - tSirMacAddr pSelfMacAddress, int8_t dB); +CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, struct cdf_mac_addr pBssid, + struct cdf_mac_addr pSelfMacAddress, int8_t dB); CDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t db); CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, - tSirMacAddr pBSSId, + struct cdf_mac_addr bssid, tCDF_CON_MODE dev_mode, int power); CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr); CDF_STATUS sme_hide_ssid(tHalHandle hHal, uint8_t sessionId, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 5ef7f247f385..0a767e8f4242 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -7720,8 +7720,8 @@ CDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t dB) \- return CDF_STATUS -------------------------------------------------------------------------------*/ -CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, tSirMacAddr pBssid, - tSirMacAddr pSelfMacAddress, int8_t dB) +CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, struct cdf_mac_addr pBssid, + struct cdf_mac_addr pSelfMacAddress, int8_t dB) { cds_msg_t msg; tpMaxTxPowerParams pMaxTxParams = NULL; @@ -7736,9 +7736,8 @@ CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, tSirMacAddr pBssid, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(pMaxTxParams->bssId, pBssid, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSelfMacAddress, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMaxTxParams->bssId, &pBssid); + cdf_copy_macaddr(&pMaxTxParams->selfStaMacAddr, &pSelfMacAddress); pMaxTxParams->power = dB; msg.type = WMA_SET_MAX_TX_POWER_REQ; @@ -7806,7 +7805,8 @@ CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr) \- return CDF_STATUS ---------------------------------------------------------------------------*/ CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, - tSirMacAddr pBSSId, tCDF_CON_MODE dev_mode, int dBm) + struct cdf_mac_addr pBSSId, + tCDF_CON_MODE dev_mode, int dBm) { cds_msg_t msg; tpMaxTxPowerParams pTxParams = NULL; @@ -7830,7 +7830,7 @@ CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(pTxParams->bssId, pBSSId, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pTxParams->bssId, &pBSSId); pTxParams->power = power; /* unit is dBm */ pTxParams->dev_mode = dev_mode; msg.type = WMA_SET_TX_POWER_REQ; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 75c50f84ee03..b7ee6974e49c 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1148,8 +1148,8 @@ typedef struct sControlTxParams { * Request Type = SIR_HAL_SET_MAX_TX_POWER_REQ */ typedef struct sMaxTxPowerParams { - tSirMacAddr bssId; - tSirMacAddr selfStaMacAddr; + struct cdf_mac_addr bssId; + struct cdf_mac_addr selfStaMacAddr; /* In request, * power == MaxTx power to be used. * In response, diff --git a/core/wma/src/wma_power.c b/core/wma/src/wma_power.c index 59e79759b011..72d77b800d97 100644 --- a/core/wma/src/wma_power.c +++ b/core/wma/src/wma_power.c @@ -418,21 +418,23 @@ void wma_set_tx_power(WMA_HANDLE handle, if (tx_pwr_params->dev_mode == CDF_SAP_MODE || tx_pwr_params->dev_mode == CDF_P2P_GO_MODE) { pdev = wma_find_vdev_by_addr(wma_handle, - tx_pwr_params->bssId, &vdev_id); + tx_pwr_params->bssId.bytes, + &vdev_id); } else { pdev = wma_find_vdev_by_bssid(wma_handle, - tx_pwr_params->bssId, &vdev_id); + tx_pwr_params->bssId.bytes, + &vdev_id); } if (!pdev) { WMA_LOGE("vdev handle is invalid for %pM", - tx_pwr_params->bssId); + tx_pwr_params->bssId.bytes); cdf_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); + tx_pwr_params->bssId.bytes); cdf_mem_free(tx_pwr_params); return; } @@ -490,15 +492,17 @@ void wma_set_max_tx_power(WMA_HANDLE handle, void *pdev; tPowerdBm prev_max_power; - pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId, &vdev_id); + pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId.bytes, + &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); + tx_pwr_params->bssId.bytes, + &vdev_id); } if (!pdev) { WMA_LOGE("vdev handle is invalid for %pM", - tx_pwr_params->bssId); + tx_pwr_params->bssId.bytes); cdf_mem_free(tx_pwr_params); return; } -- cgit v1.2.3 From 62b92ecbdafea8a797b96e98a16f2476cc9f0f99 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 12:31:51 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirNewIbssPeerInfo Replace tSirMacAddr with cdf_mac_addr in sSirNewIbssPeerInfo. Change-Id: I16cf3439fba77755429627baa26b5f87988cd81e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 290e3c42725a..a429a168d8d1 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -509,7 +509,7 @@ typedef enum eSirNwType { /* / Definition for new iBss peer info */ typedef struct sSirNewIbssPeerInfo { - tSirMacAddr peerAddr; + struct cdf_mac_addr peerAddr; uint16_t aid; } tSirNewIbssPeerInfo, *tpSirNewIbssPeerInfo; -- cgit v1.2.3 From a85d8ddcf92d7d2d579a4c3b0dd33bed6b866c61 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 14:03:29 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sLimMlmOemDataReq Replace tSirMacAddr with cdf_mac_addr in sLimMlmOemDataReq. Change-Id: I4589769f9d875347a4a5c10cd755c931b98fa8f7 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/include/lim_global.h | 2 +- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 5 ++--- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 4 ++-- core/sme/src/oem_data/oem_data_api.c | 4 ++-- core/wma/inc/wma_if.h | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a429a168d8d1..5d280162b06b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -871,7 +871,7 @@ typedef struct sSirSmeScanChanReq { typedef struct sSirOemDataReq { uint16_t messageType; /* eWNI_SME_OEM_DATA_REQ */ uint16_t messageLen; - tSirMacAddr selfMacAddr; + struct cdf_mac_addr selfMacAddr; uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; } tSirOemDataReq, *tpSirOemDataReq; diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index 5ddb01c6320c..c40bb1cef5dd 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -306,7 +306,7 @@ struct tLimScanResultNode { /* OEM Data related structure definitions */ typedef struct sLimMlmOemDataReq { - tSirMacAddr selfMacAddr; + struct cdf_mac_addr selfMacAddr; uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; } tLimMlmOemDataReq, *tpLimMlmOemDataReq; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 73f4bf0294ea..455e1031df9f 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -386,9 +386,8 @@ void lim_send_hal_oem_data_req(tpAniSirGlobal mac_ctx) cdf_mem_set((uint8_t *) (start_oem_data_req), reqlen, 0); /* Now copy over the information to the OEM DATA REQ to HAL */ - cdf_mem_copy(start_oem_data_req->selfMacAddr, - mac_ctx->lim.gpLimMlmOemDataReq->selfMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&start_oem_data_req->selfMacAddr, + &mac_ctx->lim.gpLimMlmOemDataReq->selfMacAddr); cdf_mem_copy(start_oem_data_req->oemDataReq, mac_ctx->lim.gpLimMlmOemDataReq->oemDataReq, diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 88d18497ea58..764432accafc 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1503,8 +1503,8 @@ static void __lim_process_sme_oem_data_req(tpAniSirGlobal pMac, uint32_t *pMsgBu /* Initialize this buffer */ cdf_mem_set(pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0); - cdf_mem_copy(pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMlmOemDataReq->selfMacAddr, + &pOemDataReq->selfMacAddr); cdf_mem_copy(pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE); diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c index aeb0a0db450b..385b77d4bc32 100644 --- a/core/sme/src/oem_data/oem_data_api.c +++ b/core/sme/src/oem_data/oem_data_api.c @@ -38,6 +38,7 @@ #include "cds_mq.h" #include "sme_inside.h" #include "sms_debug.h" +#include "cdf_util.h" #include "csr_support.h" @@ -222,8 +223,7 @@ CDF_STATUS oem_data_send_mb_oem_data_req(tpAniSirGlobal pMac, cdf_mem_set(pMsg, msgLen, 0); pMsg->messageType = eWNI_SME_OEM_DATA_REQ; pMsg->messageLen = msgLen; - cdf_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->selfMacAddr, &pSession->selfMacAddr); cdf_mem_copy(pMsg->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE); sms_log(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index b7ee6974e49c..6ab2a52cb66b 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -674,7 +674,7 @@ typedef struct { * @oemDataReq: OEM Data request */ typedef struct { - tSirMacAddr selfMacAddr; + struct cdf_mac_addr selfMacAddr; CDF_STATUS status; uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; } tStartOemDataReq, *tpStartOemDataReq; -- cgit v1.2.3 From dc10160f0165811a294759e069bdc47f3027435d Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 14:23:01 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeNewBssInfo Replace tSirMacAddr with cdf_mac_addr in sSirSmeNewBssInfo. Change-Id: I5c27589009ee2f517c8a99ed0909c8cb5620293e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_ibss_peer_mgmt.c | 2 +- core/sme/src/csr/csr_api_roam.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 5d280162b06b..3eeffea51bbe 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1127,7 +1127,7 @@ typedef enum eSirSmeStatusChangeCode { } tSirSmeStatusChangeCode; typedef struct sSirSmeNewBssInfo { - tSirMacAddr bssId; + struct cdf_mac_addr bssId; uint8_t channelNumber; uint8_t reserved; tSirMacSSid ssId; diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c index 4cdacb9aeb12..b2c974cad41a 100644 --- a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c @@ -1179,7 +1179,7 @@ void lim_ibss_add_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg, sizeof(uint8_t) + pBeacon->ssId.length + 1; cdf_mem_set((void *)&newBssInfo, sizeof(newBssInfo), 0); - cdf_mem_copy(newBssInfo.bssId, pHdr->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(newBssInfo.bssId.bytes, pHdr->bssId, CDF_MAC_ADDR_SIZE); newBssInfo.channelNumber = (tSirMacChanNum) pAddBss->currentOperChannel; cdf_mem_copy((uint8_t *) &newBssInfo.ssId, (uint8_t *) &pBeacon->ssId, pBeacon->ssId.length + 1); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f9d06bd146d9..7789573af980 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10460,7 +10460,8 @@ csr_roam_diag_joined_new_bss(tpAniSirGlobal mac_ctx, return; pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING; if (pNewBss) { - cdf_mem_copy(pIbssLog->bssid, pNewBss->bssId, 6); + cdf_mem_copy(pIbssLog->bssid, pNewBss->bssId.bytes, + CDF_MAC_ADDR_SIZE); if (pNewBss->ssId.length) cdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId, pNewBss->ssId.length); -- cgit v1.2.3 From 999106b34da1e54fcea11522285f0e482e07f1b2 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 15:12:09 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeApNewCaps Replace tSirMacAddr with cdf_mac_addr in sSirSmeApNewCaps. Change-Id: I785b2631e149e44835e2cf53d997673b9c5515c0 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_api.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3eeffea51bbe..bc177b988882 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1135,7 +1135,7 @@ typedef struct sSirSmeNewBssInfo { typedef struct sSirSmeApNewCaps { uint16_t capabilityInfo; - tSirMacAddr bssId; + struct cdf_mac_addr bssId; uint8_t channelId; uint8_t reserved[3]; tSirMacSSid ssId; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 761bc7e5cf2c..2ed29da641de 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1587,8 +1587,8 @@ lim_detect_change_in_ap_capabilities(tpAniSirGlobal pMac, len = sizeof(tSirMacCapabilityInfo) + sizeof(tSirMacAddr) + sizeof(uint8_t) + 3 * sizeof(uint8_t) + /* reserved fields */ pBeacon->ssId.length + 1; - cdf_mem_copy(apNewCaps.bssId, - psessionEntry->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(apNewCaps.bssId.bytes, + psessionEntry->bssId, CDF_MAC_ADDR_SIZE); if (newChannel != psessionEntry->currentOperChannel) { PELOGE(lim_log (pMac, LOGE, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7789573af980..7fff5bf72698 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -9965,7 +9965,8 @@ void csr_send_ese_adjacent_ap_rep_ind(tpAniSirGlobal pMac, tCsrRoamSession *pSes } #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ -CDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, tSirMacAddr *bssId) +static CDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, + struct cdf_mac_addr *bssId) { tpSirResetAPCapsChange pMsg; uint16_t len; @@ -9982,7 +9983,7 @@ CDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, tSirMacAddr *bssI cdf_mem_set(pMsg, sizeof(tSirResetAPCapsChange), 0); pMsg->messageType = eWNI_SME_RESET_AP_CAPS_CHANGED; pMsg->length = len; - cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->bssId, bssId->bytes, CDF_MAC_ADDR_SIZE); sms_log(pMac, LOG1, FL("CSR reset caps change for Bssid= " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssId)); @@ -10588,7 +10589,7 @@ csr_roam_chk_lnk_wm_status_change_ntf(tpAniSirGlobal mac_ctx, sms_log(mac_ctx, LOGW, FL("CSR handling eSIR_SME_AP_CAPS_CHANGED")); status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *)pApNewCaps->bssId, &sessionId); + &pApNewCaps->bssId, &sessionId); if (!CDF_IS_STATUS_SUCCESS(status)) break; if (eCSR_ROAMING_STATE_JOINED == -- cgit v1.2.3 From 25c5b6cadcd60ec1c9b2c5fd30ffa81b10f06995 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 15:17:25 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirResetAPCapsChange Replace tSirMacAddr with cdf_mac_addr in sSirResetAPCapsChange. Change-Id: Ife3e49f1902baafaddf5f304dd423451319f2783 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 3 ++- core/sme/src/csr/csr_api_roam.c | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index bc177b988882..15e727dd954c 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3463,7 +3463,7 @@ typedef struct sSirActiveModeSetBcnFilterReq { typedef struct sSirResetAPCapsChange { uint16_t messageType; uint16_t length; - tSirMacAddr bssId; + struct cdf_mac_addr bssId; } tSirResetAPCapsChange, *tpSirResetAPCapsChange; /* / Definition for Candidate found indication from FW */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 764432accafc..9a02530c3044 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4735,7 +4735,8 @@ __lim_process_sme_reset_ap_caps_change(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pResetCapsChange = (tpSirResetAPCapsChange) pMsgBuf; psessionEntry = - pe_find_session_by_bssid(pMac, pResetCapsChange->bssId, &sessionId); + pe_find_session_by_bssid(pMac, pResetCapsChange->bssId.bytes, + &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, FL("Session does not exist for given BSSID")); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7fff5bf72698..0d93d573c088 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -9979,17 +9979,18 @@ static CDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac, status = CDF_STATUS_E_NOMEM; else status = CDF_STATUS_SUCCESS; + if (CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_set(pMsg, sizeof(tSirResetAPCapsChange), 0); pMsg->messageType = eWNI_SME_RESET_AP_CAPS_CHANGED; pMsg->length = len; - cdf_mem_copy(pMsg->bssId, bssId->bytes, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->bssId, bssId); sms_log(pMac, LOG1, FL("CSR reset caps change for Bssid= " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pMsg->bssId)); + MAC_ADDR_ARRAY(pMsg->bssId.bytes)); status = cds_send_mb_message_to_mac(pMsg); } else { - sms_log(pMac, LOGE, FL("Memory allocation failed\n")); + sms_log(pMac, LOGE, FL("Memory allocation failed")); } return status; } -- cgit v1.2.3 From b9a932bcbf93f8fe93a14bd3501c18ca18925ee0 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 15:21:36 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeWmStatusChangeNtf Replace tSirMacAddr with cdf_mac_addr in sSirSmeWmStatusChangeNtf. Change-Id: I13de201aa76556db36f256066482104d2ffb34ef CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 15e727dd954c..4c66990e7ca1 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1171,7 +1171,7 @@ typedef struct sSirSmeWmStatusChangeNtf { uint16_t length; uint8_t sessionId; /* Session ID */ tSirSmeStatusChangeCode statusChangeCode; - tSirMacAddr bssId; /* Self BSSID */ + struct cdf_mac_addr bssid; /* Self BSSID */ union { uint16_t deAuthReasonCode; /* eSIR_SME_DEAUTH_FROM_PEER */ /* eSIR_SME_DISASSOC_FROM_PEER */ -- cgit v1.2.3 From b26d70de2ec4fa246d25b13b121d57e77b604e65 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 15:57:40 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeTkipCntrMeasReq Replace tSirMacAddr with cdf_mac_addr in sSirSmeTkipCntrMeasReq. Change-Id: I404f7b7976b8d3096e9a8963710a019e8671b1fe CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 3 +- core/sme/src/csr/csr_api_roam.c | 55 +++++++++++----------- core/sme/src/csr/csr_inside_api.h | 4 -- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4c66990e7ca1..177290de5e80 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1208,7 +1208,7 @@ typedef struct sSirSmeTkipCntrMeasReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; /* Peer BSSID */ + struct cdf_mac_addr bssId; /* Peer BSSID */ bool bEnable; /* Start/stop countermeasures */ } cdf_packed tSirSmeTkipCntrMeasReq, *tpSirSmeTkipCntrMeasReq; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 9a02530c3044..0494579e128b 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3354,8 +3354,7 @@ void lim_process_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t *pMsgBuf) sizeof(struct sSirSmeTkipCntrMeasReq)); psessionEntry = pe_find_session_by_bssid(pMac, - tkipCntrMeasReq.bssId, - &sessionId); + tkipCntrMeasReq.bssId.bytes, &sessionId); if (NULL == psessionEntry) { lim_log(pMac, LOGE, FL("session does not exist for given BSSID ")); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 0d93d573c088..9cc469da3366 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3061,6 +3061,33 @@ CDF_STATUS csr_roam_issue_deauth_sta_cmd(tpAniSirGlobal pMac, return status; } +static CDF_STATUS +csr_send_mb_tkip_counter_measures_req_msg(tpAniSirGlobal pMac, + uint32_t sessionId, bool bEnable, + struct cdf_mac_addr *bssId) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + tSirSmeTkipCntrMeasReq *pMsg; + do { + pMsg = cdf_mem_malloc(sizeof(tSirSmeTkipCntrMeasReq)); + if (NULL == pMsg) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) + break; + cdf_mem_set(pMsg, sizeof(tSirSmeTkipCntrMeasReq), 0); + pMsg->messageType = eWNI_SME_TKIP_CNTR_MEAS_REQ; + pMsg->length = sizeof(tSirSmeTkipCntrMeasReq); + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; + cdf_copy_macaddr(&pMsg->bssId, bssId); + pMsg->bEnable = bEnable; + status = cds_send_mb_message_to_mac(pMsg); + } while (0); + return status; +} + CDF_STATUS csr_roam_issue_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t sessionId, bool bEnable) @@ -3086,7 +3113,7 @@ csr_roam_issue_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t sessionId, ", Enable = %d", MAC_ADDR_ARRAY(bssId.bytes), bEnable); status = csr_send_mb_tkip_counter_measures_req_msg(pMac, sessionId, - bEnable, bssId.bytes); + bEnable, &bssId); return status; } @@ -14155,32 +14182,6 @@ CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, return cds_send_mb_message_to_mac(pMsg); } -CDF_STATUS csr_send_mb_tkip_counter_measures_req_msg(tpAniSirGlobal pMac, - uint32_t sessionId, bool bEnable, - tSirMacAddr bssId) -{ - CDF_STATUS status = CDF_STATUS_SUCCESS; - tSirSmeTkipCntrMeasReq *pMsg; - do { - pMsg = cdf_mem_malloc(sizeof(tSirSmeTkipCntrMeasReq)); - if (NULL == pMsg) - status = CDF_STATUS_E_NOMEM; - else - status = CDF_STATUS_SUCCESS; - if (!CDF_IS_STATUS_SUCCESS(status)) - break; - cdf_mem_set(pMsg, sizeof(tSirSmeTkipCntrMeasReq), 0); - pMsg->messageType = eWNI_SME_TKIP_CNTR_MEAS_REQ; - pMsg->length = sizeof(tSirSmeTkipCntrMeasReq); - pMsg->sessionId = sessionId; - pMsg->transactionId = 0; - cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); - pMsg->bEnable = bEnable; - status = cds_send_mb_message_to_mac(pMsg); - } while (0); - return status; -} - CDF_STATUS csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, CDF_MODULE_ID modId, tSirMacAddr bssId, diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 0f21bec8a2b7..3896db080f46 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -956,10 +956,6 @@ CDF_STATUS csr_roam_issue_deauth_sta_cmd(tpAniSirGlobal pMac, CDF_STATUS csr_roam_issue_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t sessionId, bool bEnable); -CDF_STATUS csr_send_mb_tkip_counter_measures_req_msg(tpAniSirGlobal pMac, - uint32_t sessinId, bool bEnable, - tSirMacAddr bssId); - /* --------------------------------------------------------------------------- \fn csr_roam_get_associated_stas \brief csr function that HDD calls to get list of associated stations based on module ID -- cgit v1.2.3 From 103097ef12f625046d8022662b652ce4f384cf25 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 16:14:15 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeMicFailureInd Replace tSirMacAddr with cdf_mac_addr in sSirSmeMicFailureInd. Change-Id: I65371e094fc8fb02a400960aca192b5bf7034413 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/sme/src/csr/csr_api_roam.c | 2 +- core/wma/src/wma_data.c | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 177290de5e80..d3309e5090bb 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1441,7 +1441,7 @@ typedef struct sSirSmeMicFailureInd { uint16_t messageType; /* eWNI_SME_MIC_FAILURE_IND */ uint16_t length; uint8_t sessionId; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssId; tSirMicFailureInfo info; } tSirSmeMicFailureInd, *tpSirSmeMicFailureInd; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 9cc469da3366..35a9fca59d43 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10437,7 +10437,7 @@ csr_roam_chk_lnk_mic_fail_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) cdf_mem_set(&roam_info, sizeof(roam_info), 0); status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *) pMicInd->bssId, &sessionId); + &pMicInd->bssId, &sessionId); if (CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); roam_info.u.pMICFailureInfo = &pMicInd->info; diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 7e2cafbd86d3..d334879cad0c 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -2922,9 +2922,8 @@ void ol_rx_err(ol_pdev_handle pdev, uint8_t vdev_id, mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND; mic_err_ind->length = sizeof(*mic_err_ind); mic_err_ind->sessionId = vdev_id; - cdf_mem_copy(mic_err_ind->bssId, - (struct cdf_mac_addr *) wma->interfaces[vdev_id].bssid, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mic_err_ind->bssId, + (struct cdf_mac_addr *) &wma->interfaces[vdev_id].bssid); cdf_mem_copy(mic_err_ind->info.taMacAddr, (struct cdf_mac_addr *) peer_mac_addr, sizeof(tSirMacAddr)); -- cgit v1.2.3 From de9d9d39851dd2efc3bbf1b9048f11e3d22651b7 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 16:19:14 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sAniGetTsmStatsReq Replace tSirMacAddr with cdf_mac_addr in sAniGetTsmStatsReq. Change-Id: I1f98fdfdaddf79af848c927d1443dcf6e52bcb54 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 +++- core/sme/src/csr/csr_api_roam.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d3309e5090bb..c0fc77e058ab 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1679,17 +1679,19 @@ typedef struct sAniTrafStrmMetrics { uint8_t RoamingCount; uint16_t RoamingDly; } tAniTrafStrmMetrics, *tpAniTrafStrmMetrics; + typedef struct sAniGetTsmStatsReq { /* Common for all types are requests */ uint16_t msgType; /* message type is same as the request type */ uint16_t msgLen; /* length of the entire request */ uint8_t staId; uint8_t tid; /* traffic id */ - tSirMacAddr bssId; + struct cdf_mac_addr bssId; void *tsmStatsCallback; void *pDevContext; /* device context */ void *p_cds_context; /* cds context */ } tAniGetTsmStatsReq, *tpAniGetTsmStatsReq; + typedef struct sAniGetTsmStatsRsp { /* Common for all types are responses */ uint16_t msgType; /* diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 35a9fca59d43..1c703735c3a2 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -16043,7 +16043,7 @@ CDF_STATUS csr_get_tsm_stats(tpAniSirGlobal pMac, pMsg->msgLen = (uint16_t) sizeof(tAniGetTsmStatsReq); pMsg->staId = staId; pMsg->tid = tid; - cdf_mem_copy(pMsg->bssId, bssId.bytes, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssId, &bssId); pMsg->tsmStatsCallback = callback; pMsg->pDevContext = pContext; pMsg->p_cds_context = p_cds_context; -- cgit v1.2.3 From 43f63cdbb54885869775ad13d860a8cb0eb7cd12 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 24 Sep 2015 16:31:16 -0700 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sAniDHCPStopInd Replace tSirMacAddr with cdf_mac_addr in sAniDHCPStopInd. Change-Id: I56dfa86947e9711c8727d4e3d025f0f03fc39d3c CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 19 +++++++++++++------ core/sme/src/common/sme_api.c | 18 ++++++++---------- core/wma/src/wma_features.c | 7 ++++--- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c0fc77e058ab..de8250080530 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1800,13 +1800,20 @@ typedef struct sAniGenericChangeCountryCodeReq { uint16_t domain_index; } tAniGenericChangeCountryCodeReq, *tpAniGenericChangeCountryCodeReq; +/** + * struct sAniDHCPStopInd - DHCP Stop indication message + * @msgType: message type is same as the request type + * @msgLen: length of the entire request + * @device_mode: Mode of the device(ex:STA, AP) + * @adapterMacAddr: MAC address of the adapter + * @peerMacAddr: MAC address of the connected peer + */ typedef struct sAniDHCPStopInd { - uint16_t msgType; /* message type is same as the request type */ - uint16_t msgLen; /* length of the entire request */ - uint8_t device_mode; /* Mode of the device(ex:STA, AP) */ - tSirMacAddr adapterMacAddr; /* MAC address of the adapter */ - tSirMacAddr peerMacAddr; /* MAC address of the connected peer */ - + uint16_t msgType; + uint16_t msgLen; + uint8_t device_mode; + struct cdf_mac_addr adapterMacAddr; + struct cdf_mac_addr peerMacAddr; } tAniDHCPInd, *tpAniDHCPInd; typedef enum eTxRateInfo { diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0a767e8f4242..81f59e15038a 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -5239,11 +5239,10 @@ CDF_STATUS sme_dhcp_start_ind(tHalHandle hHal, pMsg->msgType = WMA_DHCP_START_IND; pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); pMsg->device_mode = device_mode; - cdf_mem_copy(pMsg->adapterMacAddr, macAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(pMsg->peerMacAddr, - pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr, + CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->peerMacAddr, + &pSession->connectedProfile.bssid); cds_message.type = WMA_DHCP_START_IND; cds_message.bodyptr = pMsg; @@ -5311,11 +5310,10 @@ CDF_STATUS sme_dhcp_stop_ind(tHalHandle hHal, pMsg->msgType = WMA_DHCP_STOP_IND; pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd); pMsg->device_mode = device_mode; - cdf_mem_copy(pMsg->adapterMacAddr, macAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(pMsg->peerMacAddr, - pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr, + CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->peerMacAddr, + &pSession->connectedProfile.bssid); cds_message.type = WMA_DHCP_STOP_IND; cds_message.bodyptr = pMsg; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 3a0ca154f4f3..775785cf0f2c 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -782,7 +782,8 @@ CDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle, return CDF_STATUS_E_FAILURE; } - if (!wma_find_vdev_by_addr(wma_handle, ta_dhcp_ind->adapterMacAddr, + if (!wma_find_vdev_by_addr(wma_handle, + ta_dhcp_ind->adapterMacAddr.bytes, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for DHCP indication", __func__); @@ -796,7 +797,7 @@ CDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle, ta_dhcp_ind->msgType == WMA_DHCP_START_IND ? "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND", ta_dhcp_ind->device_mode, - MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr)); + MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes)); buf = wmi_buf_alloc(wma_handle->wmi_handle, len); if (!buf) { @@ -818,7 +819,7 @@ CDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle, 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, + WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes, &peer_set_param_fp->peer_macaddr); status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, -- cgit v1.2.3 From d0c5afc16294ea872f4b4f3a68edccc02013ab06 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 16 Nov 2015 12:33:45 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sir_ocb_config_channel Replace tSirMacAddr with cdf_mac_addr in struct sir_ocb_config_channel. Change-Id: I0f22ba3b3b63f8d56d3285522c0d8d1303e2f89c CRs-Fixed: 898864 --- core/hdd/inc/wlan_hdd_main.h | 2 +- core/hdd/src/wlan_hdd_ocb.c | 32 +++++++++++++------------------- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_ocb.c | 5 +++-- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index dbe70b7da274..f77605e9759c 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1002,7 +1002,7 @@ struct hdd_adapter_s { struct sir_dcc_update_ndl_response dcc_update_ndl_resp; /* MAC addresses used for OCB interfaces */ - tSirMacAddr ocb_mac_address[CDF_MAX_CONCURRENCY_PERSONA]; + struct cdf_mac_addr ocb_mac_address[CDF_MAX_CONCURRENCY_PERSONA]; int ocb_mac_addr_count; /* BITMAP indicating pause reason */ diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index 10674cbfcff0..881859a074b8 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -611,7 +611,7 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, /* 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_address[i].bytes); } adapter->ocb_mac_addr_count = 0; @@ -639,9 +639,8 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, * First channel uses the adapter's address. */ if (i == 0) { - cdf_mem_copy(curr_chan->mac_address, - adapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&curr_chan->mac_address, + &adapter->macAddressCurrent); } else { mac_addr = wlan_hdd_get_intf_addr(adapter->pHddCtx); if (mac_addr == NULL) { @@ -650,14 +649,12 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, goto fail; } cdf_mem_copy(config->channels[ - config->channel_count].mac_address, + config->channel_count].mac_address.bytes, mac_addr, sizeof(tSirMacAddr)); /* Save the mac address to release later */ cdf_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].bytes, + mac_addr, CDF_MAC_ADDR_SIZE); adapter->ocb_mac_addr_count++; } @@ -978,7 +975,7 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, /* 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_address[i].bytes); } adapter->ocb_mac_addr_count = 0; @@ -988,23 +985,20 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, */ for (i = 0; i < config->channel_count; i++) { if (i == 0) { - cdf_mem_copy(config->channels[i].mac_address, - adapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&config->channels[i].mac_address, + &adapter->macAddressCurrent); } else { mac_addr = wlan_hdd_get_intf_addr(adapter->pHddCtx); if (mac_addr == NULL) { hddLog(LOGE, FL("Cannot obtain mac address")); goto fail; } - cdf_mem_copy(config->channels[i].mac_address, - mac_addr, sizeof(tSirMacAddr)); + cdf_mem_copy(config->channels[i].mac_address.bytes, + mac_addr, CDF_MAC_ADDR_SIZE); /* Save the mac address to release later */ - cdf_mem_copy(adapter->ocb_mac_address[ + cdf_copy_macaddr(&adapter->ocb_mac_address[ adapter->ocb_mac_addr_count], - config->channels[i].mac_address, - sizeof(adapter->ocb_mac_address[ - adapter->ocb_mac_addr_count])); + &config->channels[i].mac_address); adapter->ocb_mac_addr_count++; } } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index de8250080530..a6b481ba3ada 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5197,7 +5197,7 @@ typedef void (*dcc_stats_event_callback_t)(void *hdd_ctx, uint32_t vdev_id, struct sir_ocb_config_channel { uint32_t chan_freq; uint32_t bandwidth; - tSirMacAddr mac_address; + struct cdf_mac_addr mac_address; struct sir_qos_params qos_params[MAX_NUM_AC]; uint32_t max_pwr; uint32_t min_pwr; diff --git a/core/wma/src/wma_ocb.c b/core/wma/src/wma_ocb.c index 1fde2f276829..260a8273b44c 100644 --- a/core/wma/src/wma_ocb.c +++ b/core/wma/src/wma_ocb.c @@ -343,8 +343,9 @@ int wma_ocb_set_config(tp_wma_handle wma_handle, struct sir_ocb_config *config) 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); + WMI_CHAR_ARRAY_TO_MAC_ADDR( + config->channels[i].mac_address.bytes, + &ocb_chan->mac_address); buf_ptr += sizeof(*ocb_chan); } -- cgit v1.2.3 From 34a80af90d6894e940687c1da61805bfbf038eec Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 16 Nov 2015 17:18:40 -0800 Subject: qcacld-3.0: Increase MAX_CFG_INI_ITEMS to 1024 This is a qcacld-2.0 to qcacld-3.0 propagation. Increase the maximum config ini items from 512 to 1024. Change-Id: I5c4958d5c743f1e0b03a4f7b41e21ff9787ccd07 CRs-Fixed: 914336 --- core/hdd/inc/wlan_hdd_cfg.h | 2 +- core/hdd/src/wlan_hdd_cfg.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 90a14b49ea72..3777d8425bd4 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -53,7 +53,7 @@ #endif /* Number of items that can be configured */ -#define MAX_CFG_INI_ITEMS 512 +#define MAX_CFG_INI_ITEMS 1024 /* Defines for all of the things we read from the configuration (registry). */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 95bdb0722650..d3fd27f3f279 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3916,11 +3916,10 @@ static CDF_STATUS hdd_apply_cfg_ini(hdd_context_t *pHddCtx, int i; int rv; - /* sanity test */ if (MAX_CFG_INI_ITEMS < cRegTableEntries) { - hddLog(LOGE, - "%s: MAX_CFG_INI_ITEMS too small, must be at least %ld", - __func__, 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++) { -- cgit v1.2.3 From 23df68c16d90d899f34a34acb4ca64aaa891f944 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 16 Nov 2015 18:20:46 -0800 Subject: qcacld-3.0: WLAN logs cleanup This is a qcacld-2.0 to qcacld-3.0 propagation. 1. Add log to print ssid, bssid, rssi, channel and country code while connecting to an AP. 2. Add log to print disconnect reason when disconnect request is received from user space. 3. Cleanup some of the logs moving it to appropriate log level which are showing up as ERROR level in bug report. Change-Id: Id8ea69a14a18565c226f89a8a5e10be46741d76d CRs-Fixed: 914336 --- core/cds/src/cds_concurrency.c | 29 ++------ core/cds/src/cds_reg_service.c | 5 +- core/hdd/src/wlan_hdd_cfg80211.c | 87 ++++++++++++++++++---- core/hdd/src/wlan_hdd_ioctl.c | 4 +- core/hdd/src/wlan_hdd_main.c | 6 +- core/hdd/src/wlan_hdd_stats.c | 8 +- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 4 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 3 +- core/mac/src/pe/lim/lim_send_management_frames.c | 2 +- core/sme/src/common/sme_api.c | 8 +- core/sme/src/csr/csr_api_roam.c | 8 ++ core/wma/src/wma_dev_if.c | 6 +- core/wma/src/wma_features.c | 2 +- core/wma/src/wma_scan_roam.c | 2 +- 14 files changed, 105 insertions(+), 69 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index a7ef23f9fc88..8f5ec4036372 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3060,11 +3060,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) ol_txrx_ll_set_tx_pause_q_depth( adapter->sessionId, hdd_ctx->config->TxFlowMaxQueueDepth); - /* Temporary set log level as error - * TX Flow control feature settled down, - * will lower log level - */ - cds_err("MODE %d,CH %d,LWM %d,HWM %d,TXQDEP %d", + cds_info("MODE %d,CH %d,LWM %d,HWM %d,TXQDEP %d", adapter->device_mode, targetChannel, adapter->tx_flow_low_watermark, @@ -3090,7 +3086,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) adapter->sessionId, hdd_ctx->config-> TxHbwFlowMaxQueueDepth); - cds_err("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + cds_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", hdd_device_mode_to_string( adapter->device_mode), adapter->device_mode, @@ -3116,12 +3112,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) preAdapterContext->sessionId, hdd_ctx->config-> TxHbwFlowMaxQueueDepth); - /* - * Temporary set log level as error - * TX Flow control feature settled down, - * will lower log level - */ - cds_err("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + cds_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", hdd_device_mode_to_string( preAdapterContext->device_mode ), @@ -3171,12 +3162,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) adapter5->sessionId, hdd_ctx->config-> TxHbwFlowMaxQueueDepth); - /* - * Temporary set log level as error - * TX Flow control feature settled down, - * will lower log level - */ - cds_err("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + cds_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", hdd_device_mode_to_string( adapter5->device_mode), adapter5->device_mode, @@ -3204,12 +3190,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) adapter2_4->sessionId, hdd_ctx->config-> TxLbwFlowMaxQueueDepth); - /* - * Temporary set log level as error - * TX Flow control feature settled down, - * will lower log level - */ - cds_err("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", + cds_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d", hdd_device_mode_to_string( adapter2_4->device_mode), adapter2_4->device_mode, diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index a0bed553ea06..836ff93308b6 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -1005,11 +1005,8 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, && band_capability == eCSR_BAND_24) continue; - if (wiphy->bands[i] == NULL) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "error: wiphy->bands is NULL, i = %d", i); + if (wiphy->bands[i] == NULL) continue; - } if (i == 0) m = 0; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9332e403d936..97b3fef55d41 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3241,7 +3241,7 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, } start_log.ring_id = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]); - hddLog(LOGE, FL("Ring ID=%d"), start_log.ring_id); + hdd_info("Ring ID=%d", start_log.ring_id); /* Parse and fetch verbose level */ if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) { @@ -3250,7 +3250,7 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, } start_log.verbose_level = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]); - hddLog(LOGE, FL("verbose_level=%d"), start_log.verbose_level); + hdd_info("verbose_level=%d", start_log.verbose_level); /* Parse and fetch flag */ if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) { @@ -3259,7 +3259,7 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, } start_log.flag = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]); - hddLog(LOGE, FL("flag=%d"), start_log.flag); + hdd_info("flag=%d", start_log.flag); cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level); @@ -4705,12 +4705,8 @@ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - if (NULL == wiphy->bands[i]) { - hddLog(CDF_TRACE_LEVEL_ERROR, - "%s: wiphy->bands[i] is NULL, i = %d", __func__, - 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]; @@ -4911,12 +4907,8 @@ int wlan_hdd_cfg80211_init(struct device *dev, for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - if (NULL == wiphy->bands[i]) { - hddLog(CDF_TRACE_LEVEL_ERROR, - "%s: wiphy->bands[i] is NULL, i = %d", __func__, - 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]; @@ -7690,8 +7682,7 @@ static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter, ENTER(); if (!cipher) { - hddLog(LOGE, - FL("received cipher %d - considering none"), cipher); + hdd_info("received cipher %d - considering none", cipher); encryptionType = eCSR_ENCRYPT_TYPE_NONE; } else { @@ -8473,6 +8464,70 @@ disconnected: 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"; + } +} + /** * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api * @wiphy: Pointer to wiphy @@ -8584,6 +8639,8 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, #endif hddLog(LOG1, FL("Disconnecting with reasoncode:%u"), reasonCode); + hdd_info("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(LOGE, diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 1e8db571ff9e..39192ef4ddd4 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5762,7 +5762,7 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, adapter->mc_addr_list.addr[i], sizeof(adapter->mc_addr_list.addr[i])); filter->ulMulticastAddrCnt++; - hdd_err("%s RX filter : addr =" + hdd_info("%s RX filter : addr =" MAC_ADDRESS_STR, action ? "setting" : "clearing", MAC_ADDR_ARRAY(filter->multicastAddr[i])); @@ -5772,7 +5772,7 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, sme_8023_multicast_list(handle, adapter->sessionId, filter); cdf_mem_free(filter); } else { - hdd_err("mode %d mc_cnt %d", + hdd_info("mode %d mc_cnt %d", adapter->device_mode, adapter->mc_addr_list.mc_cnt); } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index da721d1316f2..8cdc4c40d8a3 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1651,7 +1651,7 @@ static void __hdd_set_multicast_list(struct net_device *dev) ETH_ALEN)) || (adapter->addr_filter_pattern && (!memcmp(ha->addr, &adapter->addr_filter_pattern, 1)))) { - hdd_err("MC/BC filtering Skip addr ="MAC_ADDRESS_STR, + hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR, MAC_ADDR_ARRAY(ha->addr)); adapter->mc_addr_list.mc_cnt--; continue; @@ -3349,7 +3349,7 @@ static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) if (ret) hddLog(LOGE, FL("Failed to register IPv6 notifier")); else - hddLog(LOGE, FL("Registered IPv6 notifier")); + hdd_info("Registered IPv6 notifier"); return; } @@ -5423,7 +5423,7 @@ ftm_processing: if (ret) hddLog(LOGE, FL("Failed to register IPv4 notifier")); else - hddLog(LOGE, FL("Registered IPv4 notifier")); + hdd_info("Registered IPv4 notifier"); wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx); diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index ccee1b921801..549b3dedbba7 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1458,9 +1458,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, return -EINVAL; if (!pAdapter->isLinkLayerStatsSet) { - hddLog(CDF_TRACE_LEVEL_FATAL, - "%s: isLinkLayerStatsSet : %d", - __func__, pAdapter->isLinkLayerStatsSet); + hdd_warn("isLinkLayerStatsSet : %d", pAdapter->isLinkLayerStatsSet); return -EINVAL; } @@ -2455,10 +2453,8 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, hdd_wlan_get_freq(channel, &freq); for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - if (NULL == wiphy->bands[i]) { - hddLog(LOG1, FL("wiphy->bands[i] is NULL, i = %d"), 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]; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 455e1031df9f..fcee43b85190 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -2452,9 +2452,7 @@ static void lim_process_join_failure_timeout(tpAniSirGlobal mac_ctx) eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); /* Issue MLM join confirm with timeout reason code */ lim_log(mac_ctx, LOGE, - FL("In state eLIM_MLM_WT_JOIN_BEACON_STATE.")); - lim_log(mac_ctx, LOGE, - FL("Join Failure Timeout occurred for session %d with BSS " + FL("Join Failure Timeout, In eLIM_MLM_WT_JOIN_BEACON_STATE session:%d " MAC_ADDRESS_STR), session->peSessionId, MAC_ADDR_ARRAY(session->bssId)); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 0494579e128b..f06d2e302032 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1713,8 +1713,7 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) ((uint8_t *)&bss_desc.ieFields), ie_len); if (NULL != vendor_ie) { - lim_log(mac_ctx, LOGE, - FL("DUT is trying to connect to Cisco AP")); + lim_log(mac_ctx, LOG1, FL("Cisco vendor OUI present")); session->isCiscoVendorAP = true; } else { session->isCiscoVendorAP = false; diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 484a5d7ac332..80bd967983ad 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -3159,7 +3159,7 @@ CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx) (pe_session->is11Rconnection)) && (disassoc_req->reasonCode != eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("FT Preauth Session (%p,%d) Clean up"), pe_session, pe_session->peSessionId); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 81f59e15038a..37ff4d100a70 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -2485,7 +2485,7 @@ CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) /* channel avoid message arrived, send IND to client */ case eWNI_SME_CH_AVOID_IND: if (pMac->sme.pChAvoidNotificationCb) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, FL("CH avoid notification")); pMac->sme.pChAvoidNotificationCb(pMac->hHdd, pMsg->bodyptr); @@ -7396,8 +7396,8 @@ CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, } if (pSession == NULL) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: Unable to find " "the session Id: %d", __func__, + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, + "%s: Unable to find the session Id: %d", __func__, sessionId); return CDF_STATUS_E_FAILURE; } @@ -12630,7 +12630,7 @@ CDF_STATUS sme_update_dsc_pto_up_mapping(tHalHandle hHal, } if (!pSession->QosMapSet.present) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_WARN, FL("QOS Mapping IE not present")); sme_release_global_lock(&pMac->sme); return CDF_STATUS_E_FAILURE; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 1c703735c3a2..051154915628 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -13539,6 +13539,14 @@ CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, csr_join_req->ssId.length = 0; cdf_mem_copy(&csr_join_req->selfMacAddr, &pSession->selfMacAddr, sizeof(tSirMacAddr)); + sms_log(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]); /* bsstype */ dwTmp = csr_translate_bsstype_to_mac_type (pProfile->BSSType); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index b15eb9a32560..c1de651644a1 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -529,7 +529,7 @@ CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, goto out; } - WMA_LOGA("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); + 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); @@ -545,7 +545,7 @@ CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, status = CDF_STATUS_E_NOMEM; goto out; } - WMA_LOGE("Call txrx detach with callback for vdev %d", vdev_id); + WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); wma_vdev_detach_callback(iface); return status; @@ -1711,7 +1711,7 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, txrx_vdev_type); wma_handle->interfaces[self_sta_req->session_id].pause_bitmap = 0; - WMA_LOGA("vdev_id %hu, txrx_vdev_handle = %p", self_sta_req->session_id, + WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %p", self_sta_req->session_id, txrx_vdev_handle); if (NULL == txrx_vdev_handle) { diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 775785cf0f2c..5c8fc2fc81d7 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4551,7 +4551,7 @@ CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, int i; if (mcbc_param->ulMulticastAddrCnt <= 0) { - WMA_LOGE("Number of multicast addresses is 0"); + WMA_LOGW("Number of multicast addresses is 0"); return CDF_STATUS_E_FAILURE; } diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 2956990872be..e7f83f1cb6e0 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -4926,7 +4926,7 @@ int wma_extscan_cached_results_event_handler(void *handle, event->first_entry_index); WMA_LOGI("num_entries_in_page %d", numap); if (!src_hotlist || !src_rssi || !numap) { - WMA_LOGE("%s: Cached results empty, send 0 results", __func__); + WMA_LOGW("%s: Cached results empty, send 0 results", __func__); goto noresults; } if (event->first_entry_index + -- cgit v1.2.3 From abd7f6717b8b90d34c159a0381e9d9d80edd9d58 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 23 Nov 2015 11:33:57 -0800 Subject: qcacld-3.0: Add support for wakeable NLO_SCAN_COMPLETE_EVENT This is a qcacld-2.0 to qcacld-3.0 propagation. With RunTime PM feature enabled, after receiving the PNO matched event RunTime PM puts the host back in WoW suspend after 500ms (default). Since WMI_NLO_SCAN_COMPLETE_EVENTID is not a wakeable event, this event does not wakeup the host hence PNO scan not completed and PNO is broken. Fix this by making NLO_SCAN_COMPLETE_EVENT a wakeable event. Host driver configures this WoW event only after PNO match is received. Change-Id: I81cccc86942fc75bc63235038c50ba6edb0fee8b CRs-Fixed: 884211 --- core/wma/src/wma_features.c | 32 ++++++++++++++++++++++++++++++++ core/wma/src/wma_scan_roam.c | 3 +-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 5c8fc2fc81d7..68ab3d774e6a 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -102,6 +102,10 @@ static const uint8_t arp_mask[] = {0xff, 0xff}; static const uint8_t ns_ptrn[] = {0x86, 0xDD}; static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; +static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, + uint32_t vdev_id, + uint32_t bitmap, + bool enable); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN /** @@ -2464,6 +2468,8 @@ static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason) #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"; } @@ -2674,11 +2680,37 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD); node = &wma->interfaces[wake_info->vdev_id]; if (node) { + CDF_STATUS ret = CDF_STATUS_SUCCESS; WMA_LOGD("NLO match happened"); node->nlo_match_evt_received = true; cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, WIFI_POWER_EVENT_WAKELOCK_PNO); + /* Configure pno scan complete wakeup */ + ret = wma_add_wow_wakeup_event(wma, wake_info->vdev_id, + (1 << WOW_NLO_SCAN_COMPLETE_EVENT), + true); + if (ret != CDF_STATUS_SUCCESS) + WMA_LOGE("Failed to configure pno scan complete wakeup"); + else + WMA_LOGD("PNO scan complete wakeup is enabled in fw"); + } + break; + + case WOW_REASON_NLO_SCAN_COMPLETE: + { + WMI_NLO_SCAN_COMPLETE_EVENTID_param_tlvs param; + + 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 /* FEATURE_WLAN_SCAN_PNO */ diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index e7f83f1cb6e0..46f474eee369 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -4193,8 +4193,7 @@ int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event, /* Handle scan completion event only after NLO match event. */ if (!node || !node->nlo_match_evt_received) { - - WMA_LOGD("NLO match not recieved skipping PNO complete ind for vdev %d", + WMA_LOGD("NLO match not received skip PNO complete ind for vdev %d", nlo_event->vdev_id); goto skip_pno_cmp_ind; } -- cgit v1.2.3 From c9a9792291ad9b25418036a5fc3e1f655d2ab11e Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 23 Nov 2015 11:39:24 -0800 Subject: qcacld-3.0: Cleanup WOW_NLO_SCAN_COMPLETE_EVENT This is a qcacld-2.0 to qcacld-3.0 propagation. Currently WOW_NLO_SCAN_COMPLETE_EVENT is enabled on receiving PNO match found event, but it is never cleared. This is causing regular host wake ups with the reason WOW_REASON_NLO_SCAN_COMPLETE even if pno match is not found in the next successive iterations. Fix this by enabling/disabling WOW_NLO_SCAN_COMPLETE_EVENT before suspend based on the flag pno match is found. Change-Id: I21d73de0c03e0c09b5a91a521d848e71eaf359e0 CRs-Fixed: 888964 --- core/wma/src/wma_features.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 68ab3d774e6a..c3085b9bf1be 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -102,10 +102,6 @@ static const uint8_t arp_mask[] = {0xff, 0xff}; static const uint8_t ns_ptrn[] = {0x86, 0xDD}; static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; -static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, - uint32_t vdev_id, - uint32_t bitmap, - bool enable); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN /** @@ -2680,20 +2676,11 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD); node = &wma->interfaces[wake_info->vdev_id]; if (node) { - CDF_STATUS ret = CDF_STATUS_SUCCESS; WMA_LOGD("NLO match happened"); node->nlo_match_evt_received = true; cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, WIFI_POWER_EVENT_WAKELOCK_PNO); - /* Configure pno scan complete wakeup */ - ret = wma_add_wow_wakeup_event(wma, wake_info->vdev_id, - (1 << WOW_NLO_SCAN_COMPLETE_EVENT), - true); - if (ret != CDF_STATUS_SUCCESS) - WMA_LOGE("Failed to configure pno scan complete wakeup"); - else - WMA_LOGD("PNO scan complete wakeup is enabled in fw"); } break; @@ -3746,8 +3733,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) { struct wma_txrx_node *iface; bool connected = false, pno_in_progress = false; - uint8_t i; - bool extscan_in_progress = false; + uint8_t i, vdev_id = 0; + bool extscan_in_progress = false, pno_matched = false; wma->no_of_suspend_ind++; @@ -3821,6 +3808,9 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) if (wma->interfaces[i].pno_in_progress) { WMA_LOGD("PNO is in progress, enabling wow"); pno_in_progress = true; + vdev_id = i; + if (wma->interfaces[i].nlo_match_evt_received) + pno_matched = true; break; } #endif /* FEATURE_WLAN_SCAN_PNO */ @@ -3866,6 +3856,11 @@ enable_wow: } #endif /* FEATURE_WLAN_LPHB */ + if (pno_matched) + wma_enable_disable_wakeup_event(wma, vdev_id, + (1 << WOW_NLO_SCAN_COMPLETE_EVENT), + pno_matched); + wma->wow.wow_enable = true; wma->wow.wow_enable_cmd_sent = false; -- cgit v1.2.3 From 159edf88bbe412d2fd19158386a2a89c8137cdb2 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 23 Nov 2015 11:43:10 -0800 Subject: qcacld-3.0: Find extscan_in_progress irrespective of connected or pno This is a qcacld-2.0 to qcacld-3.0 propagation. The problem with the current code is we are finding whether connected or pno_in_progress or extscan_in_progress in the same for loop and whenever one of them matches, we break out of loop. It makes sense to keep connected flag and pno_in_progress inside the for loop because both are mutually exclusive. But same is not the case with extscan_in_progress, this flag can be set to true or false irrespective of connected or pno_in_progress. Hence the fix is to move finding extscan_in_progress to a separate for loop. Change-Id: Ie72ff7f7382adaea5626c0808a206d18c2916e0d CRs-Fixed: 899322 --- core/wma/src/wma_features.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index c3085b9bf1be..e47b1e4aeb5e 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3722,6 +3722,33 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) return CDF_STATUS_SUCCESS; } +#ifdef FEATURE_WLAN_EXTSCAN +/** + * wma_is_extscan_in_progress(): check if extscan is in progress + * @wma: wma handle + * + * Return: true is extscan in progress, false otherwise. + */ +static bool wma_is_extscan_in_progress(tp_wma_handle wma) +{ + int i; + + for (i = 0; i < wma->max_bssid; i++) { + if (wma->interfaces[i].extscan_in_progress) { + WMA_LOGD("Extscan is in progress, enabling wow"); + return true; + } + } + + return false; +} +#else +static bool wma_is_extscan_in_progress(tp_wma_handle wma) +{ + return false; +} +#endif + /** * wma_suspend_req() - Handles suspend indication request received from umac. * @wma: wma handle @@ -3814,14 +3841,9 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) break; } #endif /* FEATURE_WLAN_SCAN_PNO */ -#ifdef FEATURE_WLAN_EXTSCAN - if (wma->interfaces[i].extscan_in_progress) { - WMA_LOGD("Extscan is in progress, enabling wow"); - extscan_in_progress = true; - break; - } -#endif } + extscan_in_progress = wma_is_extscan_in_progress(wma); + 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, -- cgit v1.2.3 From 4a2f72d5931ac298b7a88e9eddba3d9908fb7fc1 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 22:14:34 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirUpdateIE Replace tSirMacAddr with cdf_mac_addr in sSirUpdateIE. Change-Id: Id190e74be5063ecd7792380c6f25ba8de1461c51 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_hostapd.c | 6 ++---- core/hdd/src/wlan_hdd_main.c | 13 ++++++------- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 3 +-- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 59305a12b05d..342051413f74 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -6828,8 +6828,7 @@ int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *adapter) WLAN_EID_OVERLAP_BSS_SCAN_PARAM); } #endif - cdf_mem_copy(updateIE.bssid, adapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&updateIE.bssid, &adapter->macAddressCurrent); updateIE.smeSessionId = adapter->sessionId; if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { @@ -8168,8 +8167,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, return -EINVAL; } - cdf_mem_copy(updateIE.bssid, pAdapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&updateIE.bssid, &pAdapter->macAddressCurrent); updateIE.smeSessionId = pAdapter->sessionId; updateIE.ieBufferlength = 0; updateIE.pAdditionIEBuffer = NULL; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 8cdc4c40d8a3..88131479cd58 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2629,7 +2629,7 @@ CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx) void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter) { - uint8_t *bssid = NULL; + struct cdf_mac_addr *bssid = NULL; tSirUpdateIE updateIE; switch (pHostapdAdapter->device_mode) { case WLAN_HDD_INFRA_STATION: @@ -2637,14 +2637,14 @@ void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter); - bssid = (uint8_t *) &pHddStaCtx->conn_info.bssId; + bssid = &pHddStaCtx->conn_info.bssId; break; } case WLAN_HDD_SOFTAP: case WLAN_HDD_P2P_GO: case WLAN_HDD_IBSS: { - bssid = pHostapdAdapter->macAddressCurrent.bytes; + bssid = &pHostapdAdapter->macAddressCurrent; break; } case WLAN_HDD_FTM: @@ -2660,7 +2660,7 @@ void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter) return; } - cdf_mem_copy(updateIE.bssid, bssid, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&updateIE.bssid, bssid); updateIE.smeSessionId = pHostapdAdapter->sessionId; updateIE.ieBufferlength = 0; updateIE.pAdditionIEBuffer = NULL; @@ -2835,9 +2835,8 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, adapter->device_mode, adapter->sessionId); - cdf_mem_copy(updateIE.bssid, - adapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&updateIE.bssid, + &adapter->macAddressCurrent); updateIE.smeSessionId = adapter->sessionId; updateIE.ieBufferlength = 0; updateIE.pAdditionIEBuffer = NULL; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a6b481ba3ada..a7a93062a906 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3850,7 +3850,7 @@ typedef struct sSirModifyIEsInd { /* Message format for Update IE message sent to PE */ typedef struct sSirUpdateIE { - tSirMacAddr bssid; + struct cdf_mac_addr bssid; uint16_t smeSessionId; bool append; bool notify; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index f06d2e302032..2cba642cca56 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -5362,12 +5362,12 @@ static void lim_process_update_add_ies(tpAniSirGlobal mac_ctx, update_ie = &update_add_ies->updateIE; /* incoming message has smeSession, use BSSID to find PE session */ session_entry = pe_find_session_by_bssid(mac_ctx, - update_ie->bssid, &session_id); + update_ie->bssid.bytes, &session_id); if (NULL == session_entry) { lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(update_ie->bssid)); + MAC_ADDR_ARRAY(update_ie->bssid.bytes)); goto end; } addn_ie = &session_entry->addIeParams; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 051154915628..be2369ed7001 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18335,8 +18335,7 @@ csr_roam_update_add_ies(tpAniSirGlobal pMac, pUpdateAddIEs->msgType = eWNI_SME_UPDATE_ADDITIONAL_IES; pUpdateAddIEs->msgLen = sizeof(tSirUpdateIEsInd); - cdf_mem_copy(pUpdateAddIEs->updateIE.bssid, pUpdateIE->bssid, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pUpdateAddIEs->updateIE.bssid, &pUpdateIE->bssid); pUpdateAddIEs->updateIE.smeSessionId = pUpdateIE->smeSessionId; pUpdateAddIEs->updateIE.append = pUpdateIE->append; -- cgit v1.2.3 From c15ea962e82a69337c7a306dac591b73727dc4a3 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 22:22:01 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirModifyIE Replace tSirMacAddr with cdf_mac_addr in sSirModifyIE. Change-Id: I36783326eb35bd6c9c4987ae0655b0313f398886 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a7a93062a906..dd57d2c4d4ff 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3830,7 +3830,7 @@ typedef enum tUpdateIEsType { /* Modify particular IE in addition IE for prob resp Bcn */ typedef struct sSirModifyIE { - tSirMacAddr bssid; + struct cdf_mac_addr bssid; uint16_t smeSessionId; bool notify; uint8_t ieID; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 2cba642cca56..541e42e863e5 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -5282,12 +5282,12 @@ static void lim_process_modify_add_ies(tpAniSirGlobal mac_ctx, modify_add_ies = (tpSirModifyIEsInd)msg_buf; /* Incoming message has smeSession, use BSSID to find PE session */ session_entry = pe_find_session_by_bssid(mac_ctx, - modify_add_ies->modifyIE.bssid, &session_id); + modify_add_ies->modifyIE.bssid.bytes, &session_id); if (NULL == session_entry) { lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(modify_add_ies->modifyIE.bssid)); + MAC_ADDR_ARRAY(modify_add_ies->modifyIE.bssid.bytes)); goto end; } if ((0 == modify_add_ies->modifyIE.ieBufferlength) || diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index be2369ed7001..a0f40ae07185 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18268,8 +18268,7 @@ csr_roam_modify_add_ies(tpAniSirGlobal pMac, pModifyAddIEInd->msgType = eWNI_SME_MODIFY_ADDITIONAL_IES; pModifyAddIEInd->msgLen = sizeof(tSirModifyIEsInd); - cdf_mem_copy(pModifyAddIEInd->modifyIE.bssid, pModifyIE->bssid, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pModifyAddIEInd->modifyIE.bssid, &pModifyIE->bssid); pModifyAddIEInd->modifyIE.smeSessionId = pModifyIE->smeSessionId; pModifyAddIEInd->modifyIE.notify = pModifyIE->notify; -- cgit v1.2.3 From 2efd47f35d3ea15706207bda2d4879082dd15f95 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 22:36:12 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirRateUpdateInd Replace tSirMacAddr with cdf_mac_addr in sSirRateUpdateInd. Change-Id: I28dc76e07721f6472bbc1ec5c107cd12b2123a8f CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_hostapd.c | 5 ++--- core/hdd/src/wlan_hdd_ioctl.c | 5 ++--- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_data.c | 7 ++++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 342051413f74..2afa2c746f89 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2349,9 +2349,8 @@ static __iw_softap_setparam(struct net_device *dev, struct hdd_config *pConfig = hdd_ctx->config; hddLog(LOG1, "MC Target rate %d", set_value); - memcpy(rateUpdate.bssid, - pHostapdAdapter->macAddressCurrent.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&rateUpdate.bssid, + &pHostapdAdapter->macAddressCurrent); rateUpdate.nss = (pConfig->enable2x2 == 0) ? 0 : 1; rateUpdate.dev_mode = pHostapdAdapter->device_mode; rateUpdate.mcastDataRate24GHz = set_value; diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 39192ef4ddd4..d2218c541b8f 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -2444,11 +2444,10 @@ int wlan_hdd_set_mc_rate(hdd_adapter_t *pAdapter, int targetRate) rateUpdate.mcastDataRate24GHzTxFlag = 1; rateUpdate.mcastDataRate5GHz = targetRate; rateUpdate.bcastDataRate = -1; - memcpy(rateUpdate.bssid, pAdapter->macAddressCurrent.bytes, - sizeof(rateUpdate.bssid)); + cdf_copy_macaddr(&rateUpdate.bssid, &pAdapter->macAddressCurrent); hddLog(LOG1, FL("MC Target rate %d, mac = %pM, dev_mode %s(%d)"), - rateUpdate.mcastDataRate24GHz, rateUpdate.bssid, + rateUpdate.mcastDataRate24GHz, rateUpdate.bssid.bytes, hdd_device_mode_to_string(pAdapter->device_mode), pAdapter->device_mode); status = sme_send_rate_update_ind(pHddCtx->hHal, &rateUpdate); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index dd57d2c4d4ff..486e7023e698 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3717,7 +3717,7 @@ typedef struct { #endif typedef struct sSirRateUpdateInd { uint8_t nss; /* 0: 1x1, 1: 2x2 */ - tSirMacAddr bssid; + struct cdf_mac_addr bssid; tCDF_CON_MODE dev_mode; int32_t bcastDataRate; /* bcast rate unit Mbpsx10, -1:not used */ /* diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index d334879cad0c..2c373c0308e9 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -1407,10 +1407,11 @@ CDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, struct wma_txrx_node *intr = wma->interfaces; /* Get the vdev id */ - pdev = wma_find_vdev_by_addr(wma, pRateUpdateParams->bssid, &vdev_id); + pdev = wma_find_vdev_by_addr(wma, pRateUpdateParams->bssid.bytes, + &vdev_id); if (!pdev) { WMA_LOGE("vdev handle is invalid for %pM", - pRateUpdateParams->bssid); + pRateUpdateParams->bssid.bytes); cdf_mem_free(pRateUpdateParams); return CDF_STATUS_E_INVAL; } @@ -1440,7 +1441,7 @@ CDF_STATUS wma_process_rate_update_indicate(tp_wma_handle wma, 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, + pRateUpdateParams->dev_mode, pRateUpdateParams->bssid.bytes, 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, -- cgit v1.2.3 From 4f80b87db9edc928ba8896f9f6319d3737900cba Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 14:38:02 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirLPHBUdpParamStruct Replace tSirMacAddr with cdf_mac_addr in sSirLPHBUdpParamStruct Change-Id: I6439494feb18824cc9054c66ae426646c055f3d4 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 486e7023e698..c4a979b4bdf7 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3645,7 +3645,7 @@ typedef struct sSirLPHBUdpParamStruct { uint16_t interval; uint16_t timeout; uint8_t session; - tSirMacAddr gateway_mac; + struct cdf_mac_addr gateway_mac; } tSirLPHBUdpParamStruct; typedef struct sSirLPHBUdpFilterStruct { diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index e47b1e4aeb5e..09353523be5c 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -586,16 +586,12 @@ CDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle, 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__, + "gateway_mac="MAC_ADDRESS_STR, __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]); + ts_lphb_udp_param->session, + MAC_ADDR_ARRAY(ts_lphb_udp_param->gateway_mac.bytes)); buf = wmi_buf_alloc(wma_handle->wmi_handle, len); if (!buf) { @@ -619,7 +615,7 @@ CDF_STATUS wma_lphb_conf_udp_params(tp_wma_handle wma_handle, 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, + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes, &hb_udp_params_fp->gateway_mac); status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, -- cgit v1.2.3 From d474785bbe1947b8a8bde3498efbbbaac6ce400d Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 14:47:04 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirLPHBTcpParamStruct Replace tSirMacAddr with cdf_mac_addr in sSirLPHBTcpParamStruct Change-Id: I55cbe3c441c2b1540e946e52c815bc5518935964 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c4a979b4bdf7..99a08ba194b8 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3625,7 +3625,7 @@ typedef struct sSirLPHBTcpParamStruct { uint16_t dst_port; uint16_t timeout; uint8_t session; - tSirMacAddr gateway_mac; + struct cdf_mac_addr gateway_mac; uint16_t timePeriodSec; /* in seconds */ uint32_t tcpSn; } tSirLPHBTcpParamStruct; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 09353523be5c..cff570c39ce4 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -438,17 +438,14 @@ CDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle, } 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, + 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="MAC_ADDRESS_STR", 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->session, + MAC_ADDR_ARRAY(ts_lphb_tcp_param->gateway_mac.bytes), ts_lphb_tcp_param->timePeriodSec, ts_lphb_tcp_param->tcpSn); buf = wmi_buf_alloc(wma_handle->wmi_handle, len); @@ -474,7 +471,7 @@ CDF_STATUS wma_lphb_conf_tcp_params(tp_wma_handle wma_handle, 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, + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes, &hb_tcp_params_fp->gateway_mac); status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, -- cgit v1.2.3 From ebf2dedb26f572361865c44058b78b1e9f6eefdf Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 14:59:18 -0800 Subject: qcacld-3.0: Remove obsolete struct sSirPsReqData Remove obsolete struct sSirPsReqData. Change-Id: I262fcd2e9e5a7258bc516533f1bafe6a54011065 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 99a08ba194b8..4090dc05c20e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3591,15 +3591,6 @@ typedef enum eSirAddonPsReq { 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 -- cgit v1.2.3 From 6b5efdd5db003462ab375ffdeae6232ffc6d7052 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 15:40:20 -0800 Subject: qcacld-3.0: Remove obsolete struct sSirTdlsDisappearAPInd Remove obsolete struct sSirTdlsDisappearAPInd Change-Id: Ia9823cddc401374b0e411f50c9618a8aceee56af CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4090dc05c20e..4909cde14724 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3438,15 +3438,6 @@ typedef struct sSirTdlsDelAllPeerInd { uint16_t length; uint8_t sessionId; /* Session ID */ } tSirTdlsDelAllPeerInd, *tpSirTdlsDelAllPeerInd; -#ifdef FEATURE_WLAN_TDLS_DISAPPEAR_AP -typedef struct sSirTdlsDisappearAPInd { - uint16_t messageType; - uint16_t length; - uint8_t sessionId; /* Session ID */ - uint16_t staId; - tSirMacAddr staAddr; -} tSirTdlsDisappearAPInd, *tpSirTdlsDisappearAPInd; -#endif typedef struct sSirMgmtTxCompletionInd { uint16_t messageType; uint16_t length; -- cgit v1.2.3 From 7ddd15b14a73b8a804a3e47603eb192bd5b09dd1 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 20 Nov 2015 20:58:13 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirTdlsLinkEstablish Req/Rsp Replace tSirMacAddr with cdf_mac_addr in tSirTdlsLinkEstablish Req/Rsp. Change-Id: I089e9835e08aa029b25113f260b4ba3088599075 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +++--- core/mac/src/pe/lim/lim_process_tdls.c | 19 ++++++++++--------- core/mac/src/pe/lim/lim_send_sme_rsp_messages.h | 2 +- core/sme/inc/sme_inside.h | 2 +- core/sme/src/csr/csr_tdls_process.c | 12 ++++++------ 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4909cde14724..4af72143def8 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3387,8 +3387,8 @@ typedef struct { uint8_t isOffChannelSupported; uint8_t isResponder; /* Is Peer a responder. */ /* For multi-session, for PE to locate peSession ID */ - tSirMacAddr bssid; - tSirMacAddr peerMac; + struct cdf_mac_addr bssid; + struct cdf_mac_addr peermac; uint8_t supportedChannelsLen; uint8_t supportedChannels[SIR_MAC_MAX_SUPP_CHANNELS]; uint8_t supportedOperClassesLen; @@ -3402,7 +3402,7 @@ typedef struct { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ tSirResultCodes statusCode; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; } tSirTdlsLinkEstablishReqRsp, *tpSirTdlsLinkEstablishReqRsp; /* TDLS Request struct SME-->PE */ diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 2c883e1f1181..7afba538ce76 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2842,7 +2842,8 @@ lim_tdls_send_mgmt_error: * Send Response to Link Establish Request to SME */ void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, - uint8_t sessionId, tSirMacAddr peerMac, + uint8_t sessionId, + struct cdf_mac_addr *peermac, tDphHashNode *pStaDs, uint8_t status) { tSirMsgQ mmhMsg = { 0 }; @@ -2856,10 +2857,9 @@ void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, return; } pTdlsLinkEstablishReqRsp->statusCode = status; - if (peerMac) { - cdf_mem_copy(pTdlsLinkEstablishReqRsp->peerMac, peerMac, - sizeof(tSirMacAddr)); - } + if (peermac) + cdf_copy_macaddr(&pTdlsLinkEstablishReqRsp->peermac, peermac); + pTdlsLinkEstablishReqRsp->sessionId = sessionId; mmhMsg.type = eWNI_SME_TDLS_LINK_ESTABLISH_RSP; mmhMsg.bodyptr = pTdlsLinkEstablishReqRsp; @@ -3101,14 +3101,14 @@ tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal mac_ctx, CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, FL("Send Mgmt Recieved")); - session_entry = pe_find_session_by_bssid(mac_ctx, tdls_req->bssid, + session_entry = pe_find_session_by_bssid(mac_ctx, tdls_req->bssid.bytes, &session_id); if (NULL == session_entry) { CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, FL("PE Session does not exist for sme session_id %d"), tdls_req->sessionId); lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, - tdls_req->sessionId, tdls_req->peerMac, NULL, + tdls_req->sessionId, &tdls_req->peermac, NULL, eSIR_FAILURE); return eSIR_FAILURE; } @@ -3133,7 +3133,8 @@ tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal mac_ctx, goto lim_tdls_link_establish_error; } - stads = dph_lookup_hash_entry(mac_ctx, tdls_req->peerMac, &peer_idx, + stads = dph_lookup_hash_entry(mac_ctx, tdls_req->peermac.bytes, + &peer_idx, &session_entry->dph.dphHashTable); if (NULL == stads) { lim_log(mac_ctx, LOGE, FL("stads is NULL")); @@ -3207,7 +3208,7 @@ send_tdls_establish_request: lim_tdls_link_establish_error: lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, - session_entry->smeSessionId, tdls_req->peerMac, NULL, + session_entry->smeSessionId, &tdls_req->peermac, NULL, eSIR_FAILURE); return eSIR_SUCCESS; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h index e707481ad6c3..260b128e9b47 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h @@ -109,7 +109,7 @@ void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMa uint8_t smesessionId); #ifdef FEATURE_WLAN_TDLS void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, uint8_t sessionId, - tSirMacAddr peerMac, + struct cdf_mac_addr *peermac, tDphHashNode *pStaDs, uint8_t status); void lim_send_sme_tdls_event_notify(tpAniSirGlobal pMac, uint16_t msgType, void *events); diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index 396166f202b0..e1db6a871d4a 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -105,7 +105,7 @@ typedef struct TdlsSendMgmtInfo { } tTdlsSendMgmtCmdInfo; typedef struct TdlsLinkEstablishInfo { - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint8_t uapsdQueues; uint8_t maxSp; uint8_t isBufSta; diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index 30fadcd205cd..cb4694279539 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -232,8 +232,8 @@ CDF_STATUS csr_tdls_send_link_establish_params(tHalHandle hHal, tdlsLinkEstablishCmd->sessionId = sessionId; - cdf_mem_copy(tdlsLinkEstablishCmdInfo->peerMac, - peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsLinkEstablishCmdInfo->peermac.bytes, + peerMac, CDF_MAC_ADDR_SIZE); tdlsLinkEstablishCmdInfo->isBufSta = tdlsLinkEstablishParams->isBufSta; tdlsLinkEstablishCmdInfo->isResponder = @@ -637,10 +637,10 @@ CDF_STATUS csr_tdls_process_link_establish(tpAniSirGlobal pMac, tSmeCmd *cmd) tdlsLinkEstablishReq->sessionId = cmd->sessionId; /* Using dialog as transactionId. This can be used to match response with request */ tdlsLinkEstablishReq->transactionId = 0; - cdf_mem_copy(tdlsLinkEstablishReq->peerMac, - tdlsLinkEstablishCmdInfo->peerMac, sizeof(tSirMacAddr)); - cdf_mem_copy(tdlsLinkEstablishReq->bssid, - pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&tdlsLinkEstablishReq->peermac, + &tdlsLinkEstablishCmdInfo->peermac); + cdf_mem_copy(tdlsLinkEstablishReq->bssid.bytes, + pSession->pConnectBssDesc->bssId, CDF_MAC_ADDR_SIZE); cdf_mem_copy(tdlsLinkEstablishReq->supportedChannels, tdlsLinkEstablishCmdInfo->supportedChannels, tdlsLinkEstablishCmdInfo->supportedChannelsLen); -- cgit v1.2.3 From 8f62ad017af1aa2f8d780221e671904be224d7f8 Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Tue, 24 Nov 2015 11:06:32 -0800 Subject: qcacld-3.0: Remove unused LRO logging function Remove LRO logging function that is not used CRs-Fixed: 943482 Change-Id: Ia0c3dd93d02183ae7ace2d930fb874ca01b4397e --- core/cdf/src/i_cdf_nbuf.h | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/core/cdf/src/i_cdf_nbuf.h b/core/cdf/src/i_cdf_nbuf.h index 9a83a1086275..c174435aa3b0 100644 --- a/core/cdf/src/i_cdf_nbuf.h +++ b/core/cdf/src/i_cdf_nbuf.h @@ -241,41 +241,6 @@ struct nbuf_rx_cb { (((struct nbuf_rx_cb *)((skb)->cb))->tcp_win) #define NBUF_FLOW_ID_TOEPLITZ(skb) \ (((struct nbuf_rx_cb *)((skb)->cb))->flow_id_toeplitz) - -/** - * cdf_print_lro_info() - prints the LRO information - * @skb : network buffer - * - * This function prints out the LRO related fields in the rx - * descriptor - * - * Return: none - */ -static inline void cdf_print_lro_info(struct sk_buff *skb) -{ - cdf_print("NBUF_LRO_ELIGIBLE 0x%x\n" - "NBUF_TCP_PROTO 0x%x\n" - "NBUF_TCP_PURE_ACK 0x%x\n" - "NBUF_TCP_CHKSUM 0x%x\n" - "NBUF_IPV6_PROTO 0x%x\n" - "NBUF_IP_OFFSET 0x%x\n" - "NBUF_TCP_OFFSET 0x%x\n" - "NBUF_TCP_SEQ_NUM 0x%x\n" - "NBUF_TCP_ACK_NUM 0x%x\n" - "NBUF_TCP_WIN 0x%x\n" - "NBUF_FLOW_ID_TOEPLITZ 0x%x\n", - NBUF_LRO_ELIGIBLE(skb), - NBUF_TCP_PROTO(skb), - NBUF_TCP_PURE_ACK(skb), - NBUF_TCP_CHKSUM(skb), - NBUF_IPV6_PROTO(skb), - NBUF_IP_OFFSET(skb), - NBUF_TCP_OFFSET(skb), - NBUF_TCP_SEQ_NUM(skb), - NBUF_TCP_ACK_NUM(skb), - NBUF_TCP_WIN(skb), - NBUF_FLOW_ID_TOEPLITZ(skb)); -} #endif /* FEATURE_LRO */ #define NBUF_SET_PACKET_STATE(skb, pkt_state) \ -- cgit v1.2.3 From 20dc9d2d4931f1c46a4df1210f4993afca3fe7c8 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 25 Nov 2015 12:24:47 -0800 Subject: Release 5.0.0.147 Release 5.0.0.147 Change-Id: Ib90ae6900b75fa0626f1c32f84a1f65abd1dda6c CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 418a536c9977..7460f129d854 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 146 +#define QWLAN_VERSION_BUILD 147 -#define QWLAN_VERSIONSTR "5.0.0.146" +#define QWLAN_VERSIONSTR "5.0.0.147" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From b8fd9a7c29bc308453241db93b3f913fe592868b Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 5 Nov 2015 11:47:20 +0530 Subject: qcacld-3.0: CL 1411038 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation add WMI_TRANSFER_TO_FLASH message defs. CRs-Fixed: 935128 Change-Id: I21c55e7aee54c4f6beb6f455a395d1e2a233c9d9 --- core/wmi/wmi_unified.c | 1 + target/inc/wmi_tlv_defs.h | 16 ++++++++++++++-- target/inc/wmi_unified.h | 30 ++++++++++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 79fe92f46b6d..84dab33e89e4 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -529,6 +529,7 @@ static uint8_t *get_wmi_cmd_string(WMI_CMD_ID wmi_command) 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); diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 081de734b295..11a30222d7de 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -600,6 +600,8 @@ typedef enum { 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_ID; /* @@ -837,7 +839,8 @@ typedef enum { 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_PMF_OFFLOAD_SET_SA_QUERY_CMDID) \ + OP(WMI_TRANSFER_DATA_TO_FLASH_CMDID) /* * IMPORTANT: Please add _ALL_ WMI Events Here. * Otherwise, these WMI TLV Functions will be process them. @@ -952,7 +955,8 @@ typedef enum { 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_AP_PS_EGAP_INFO_EVENTID) \ + OP(WMI_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID) /* TLV definitions of WMI commands */ @@ -2186,6 +2190,10 @@ WMITLV_CREATE_PARAM_STRUC(WMI_SET_ANTENNA_DIVERSITY_CMDID); 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) \ @@ -2616,6 +2624,10 @@ WMITLV_CREATE_PARAM_STRUC(WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID); 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) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index cbb3cc452e8a..1511fe3d94d0 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -701,6 +701,8 @@ typedef enum { /* 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, @@ -1118,6 +1120,8 @@ typedef enum { 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, /* GPIO Event */ WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), @@ -12262,6 +12266,32 @@ typedef struct { 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 { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_cmd_fixed_param + */ + A_UINT32 tlv_header; + /* flash offset to write, starting from 0 */ + A_UINT32 offset; + /* vaild data length in buffer, unit: byte */ + A_UINT32 length; +} wmi_transfer_data_to_flash_cmd_fixed_param; + +typedef struct { + /* + * TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_transfer_data_to_flash_complete_event_fixed_param + */ + A_UINT32 tlv_header; + /* Return status. 0 for success, non-zero otherwise */ + A_UINT32 status; +} wmi_transfer_data_to_flash_complete_event_fixed_param; + /* ADD NEW DEFS HERE */ /***************************************************************************** diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 41d427807687..9c62d2d3092e 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 176 +#define __WMI_REVISION_ 177 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From c6229d2b6f91a770c9614cfe0498c0ab3ec60306 Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Fri, 9 Oct 2015 19:39:47 +0530 Subject: qcacld-3.0: Fix race condition between disassoc/deauth from peer qcacld-2.0 to qcacld-3.0 propagation When disassoc request is received from peer and at the same time if deauth request is received from supplicant, LIM cleanup may not happen properly as there is a chance of session deletion in limSendSmeDeauthNtf while cleanup in progress from limProcessSmeDisassocCnf. This can result in not sending delbss to FW. Hence, FW can crash when config bss is sent for new connection. Following changes are added to handle this. 1. Add state eLIM_SME_WT_DISASSOC_STATE in __limProcessSmeDeauthReq and allow host to post LIM_MLM_DEAUTH_REQ instead of invoking limSendSmeDeauthNtf, where session is deleted. 2. Send eWNI_SME_DEAUTH_RSP if cleanup is already in progress to avoid cleanup again. If mlm state is not eLIM_MLM_LINK_ESTABLISHED_STATE, then it means cleanup is already in progress. 3. Return from __limProcessSmeDisassocCnf if cleanup is already in progress. 4. Add check in limProcessMlmDeauthCnf to send deauth confirmation even if state is eLIM_SME_WT_DISASSOC_STATE. 5. Add similar checks in limProcessMlmDisassocReqNtf to handle disassoc from peer and supplicant simultaneously. Change-Id: Ie19a7b79d835a5e5a77ef48f9379c1cf90dc38d7 CRs-Fixed: 878334 --- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 79 +++++++++++++++++++--- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 4 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 12 ++++ core/mac/src/pe/lim/lim_types.h | 2 + 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index fcee43b85190..7cd873d4fbfa 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1569,6 +1569,7 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, tpPESession session; extern bool send_disassoc_frame; tLimMlmStates mlm_state; + tSirSmeDisassocRsp *sme_disassoc_rsp; if (CDF_STATUS_SUCCESS != suspend_status) lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"), @@ -1605,10 +1606,39 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, lim_print_mac_addr(mac_ctx, mlm_disassocreq->peerMacAddr, LOGW); - /* Prepare and Send LIM_MLM_DISASSOC_CNF */ - mlm_disassoccnf.resultCode = - eSIR_SME_INVALID_PARAMETERS; - goto end; + /* + * Disassociation response due to host triggered + * disassociation + */ + sme_disassoc_rsp = + cdf_mem_malloc(sizeof(tSirSmeDisassocRsp)); + if (NULL == sme_disassoc_rsp) { + lim_log(mac_ctx, LOGP, + FL("memory allocation failed for disassoc rsp")); + return; + } + + lim_log(mac_ctx, LOG1, + FL("send disassoc rsp with ret code %d for" MAC_ADDRESS_STR), + eSIR_SME_DEAUTH_STATUS, + MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + + sme_disassoc_rsp->messageType = eWNI_SME_DISASSOC_RSP; + sme_disassoc_rsp->length = sizeof(tSirSmeDisassocRsp); + sme_disassoc_rsp->sessionId = + mlm_disassocreq->sessionId; + sme_disassoc_rsp->transactionId = 0; + sme_disassoc_rsp->statusCode = eSIR_SME_DEAUTH_STATUS; + + cdf_mem_copy(sme_disassoc_rsp->peerMacAddr, + mlm_disassocreq->peerMacAddr, + sizeof(tSirMacAddr)); + msg = (uint32_t *)sme_disassoc_rsp; + + lim_send_sme_disassoc_deauth_ntf(mac_ctx, + CDF_STATUS_SUCCESS, msg); + return; + } break; case eLIM_STA_IN_IBSS_ROLE: @@ -1909,6 +1939,7 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, tLimMlmDeauthReq *mlm_deauth_req; tLimMlmDeauthCnf mlm_deauth_cnf; tpPESession session; + tSirSmeDeauthRsp *sme_deauth_rsp; if (CDF_STATUS_SUCCESS != suspend_status) lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"), @@ -1955,10 +1986,42 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, MAC_ADDR_ARRAY( mlm_deauth_req->peerMacAddr), MAC_ADDR_ARRAY(curr_bssId)); - /* Prepare and Send LIM_MLM_DEAUTH_CNF */ - mlm_deauth_cnf.resultCode = - eSIR_SME_INVALID_PARAMETERS; - goto end; + /* + * Deauthentication response to host triggered + * deauthentication + */ + sme_deauth_rsp = + cdf_mem_malloc(sizeof(tSirSmeDeauthRsp)); + if (NULL == sme_deauth_rsp) { + lim_log(mac_ctx, LOGP, + FL("memory allocation failed for deauth rsp")); + return; + } + + lim_log(mac_ctx, LOG1, + FL("send deauth rsp with ret code %d for" MAC_ADDRESS_STR), + eSIR_SME_DEAUTH_STATUS, + MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + + sme_deauth_rsp->messageType = + eWNI_SME_DEAUTH_RSP; + sme_deauth_rsp->length = + sizeof(tSirSmeDeauthRsp); + sme_deauth_rsp->statusCode = + eSIR_SME_DEAUTH_STATUS; + sme_deauth_rsp->sessionId = + mlm_deauth_req->sessionId; + sme_deauth_rsp->transactionId = 0; + + cdf_mem_copy(sme_deauth_rsp->peerMacAddr, + mlm_deauth_req->peerMacAddr, + sizeof(tSirMacAddr)); + + msg_buf = (uint32_t *)sme_deauth_rsp; + + lim_send_sme_disassoc_deauth_ntf(mac_ctx, + CDF_STATUS_SUCCESS, msg_buf); + return; } if ((session->limMlmState == diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 5a756e77cd61..c7c4f5aa1f75 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1299,7 +1299,9 @@ void lim_process_mlm_deauth_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) if (LIM_IS_STA_ROLE(psessionEntry) || LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { /* Deauth Confirm from MLM */ - if (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE) { + 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. diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 541e42e863e5..6241c06af150 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2741,6 +2741,18 @@ static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBu MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr)); return; } + + if ((pStaDs->mlmStaContext.mlmState == + eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (pStaDs->mlmStaContext.mlmState == + eLIM_MLM_WT_DEL_STA_RSP_STATE)) { + lim_log(pMac, LOGE, + FL("No need of 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 */ lim_ft_cleanup_pre_auth_info(pMac, psessionEntry); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index a61a9cadba00..8bffe8b8e244 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -854,6 +854,8 @@ void lim_process_rx_scan_event(tpAniSirGlobal mac, void *buf); int lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg); void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data); +void lim_send_sme_disassoc_deauth_ntf(tpAniSirGlobal mac_ctx, + CDF_STATUS status, uint32_t *ctx); /* / Bit value data structure */ typedef enum sHalBitVal /* For Bit operations */ -- cgit v1.2.3 From 0c68510e8c05678edd534381b61c6052c91d2411 Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Wed, 25 Nov 2015 15:41:10 +0530 Subject: qcacld-4.0: TDLS: provide operating class and channel to HAL qcacld-2.0 to qcacld-3.0 propagation 1.Provide off channel and operating class info to user space in HAL API wifi_get_tdls_status. If off channel is not enabled then provide base channel info and in that case pass opclass as 0. 2.Provide correct tdls state based on tdls off channel configuration. Change-Id: Ic60500b95ebddcb88b4e03f29178068c5322b2b9 CRs-Fixed: 838167 --- core/hdd/inc/wlan_hdd_main.h | 4 + core/hdd/inc/wlan_hdd_tdls.h | 7 +- core/hdd/src/wlan_hdd_main.c | 19 +++ core/hdd/src/wlan_hdd_tdls.c | 267 +++++++++++++++++++++++++++++------------- core/sme/inc/sme_api.h | 14 ++- core/sme/src/common/sme_api.c | 122 ++++++++----------- 6 files changed, 274 insertions(+), 159 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index f77605e9759c..c4762ba8eb34 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1184,6 +1184,7 @@ struct hdd_context_s { struct mutex tdls_lock; uint8_t tdls_off_channel; uint16_t tdls_channel_offset; + int32_t tdls_fw_off_chan_mode; #endif #ifdef IPA_OFFLOAD @@ -1559,4 +1560,7 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx); void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx); const char *hdd_get_fwpath(void); +uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, + uint8_t bw_offset); + #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 285bb7856769..33557fc20901 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -228,6 +228,8 @@ typedef enum { } tdls_state_t; typedef int (*cfg80211_exttdls_callback)(const uint8_t *mac, + uint32_t opclass, + uint32_t channel, uint32_t state, int32_t reason, void *ctx); @@ -531,10 +533,11 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, uint32_t op_class, uint32_t min_bandwidth); int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, - const uint8_t *mac, int32_t *state, + const uint8_t *mac, uint32_t *opclass, + uint32_t *channel, uint32_t *state, int32_t *reason); void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, - int32_t *state, int32_t *reason); + uint32_t *state, int32_t *reason); int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, cfg80211_exttdls_callback callback); void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 88131479cd58..645f0e64fd72 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -86,6 +86,7 @@ #ifdef CONFIG_CNSS #include #endif +#include "cds_regdomain.h" #include "wlan_hdd_ocb.h" @@ -359,6 +360,24 @@ static int con_mode; static int curr_con_mode; #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; +} + /** * hdd_cdf_trace_enable() - configure initial CDF Trace enable * @moduleId: Module whose trace level is being configured diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 19da47f69030..aa0e442bdd5d 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -51,6 +51,40 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx); int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac); static void wlan_hdd_tdls_pre_setup(struct work_struct *work); +/* + * 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->config->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; + } +} + /** * wlan_hdd_tdls_hash_key() - calculate tdls hash key given mac address * @mac: mac address @@ -648,8 +682,12 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddTdlsCtx->threshold_config.rssi_teardown_threshold; tInfo->rssi_delta = pHddTdlsCtx->threshold_config.rssi_delta; tInfo->tdls_options = 0; - if (pHddCtx->config->fEnableTDLSOffChannel) + + if (pHddCtx->config->fEnableTDLSOffChannel) { tInfo->tdls_options |= ENA_TDLS_OFFCHAN; + pHddCtx->tdls_fw_off_chan_mode = ENABLE_CHANSWITCH; + } + if (pHddCtx->config->fEnableTDLSBufferSta) tInfo->tdls_options |= ENA_TDLS_BUFFER_STA; if (pHddCtx->config->fEnableTDLSSleepSta) @@ -862,6 +900,9 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac) cdf_mem_copy(peer->peerMac, mac, sizeof(peer->peerMac)); peer->pHddTdlsCtx = pHddTdlsCtx; peer->pref_off_chan_num = pHddCtx->config->fTDLSPrefOffChanNum; + peer->op_class_for_pref_off_chan = + wlan_hdd_find_opclass(pHddCtx->hHal, peer->pref_off_chan_num, + pHddCtx->config->fTDLSPrefOffChanBandwidth); list_add_tail(&peer->node, head); mutex_unlock(&pHddCtx->tdls_lock); @@ -905,7 +946,7 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, tTDLSLinkStatus status, tTDLSLinkReason reason) { - int32_t state = 0; + uint32_t state = 0; int32_t res = 0; hdd_context_t *pHddCtx; if (curr_peer == NULL) { @@ -941,13 +982,19 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer, 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; 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, - state, - res, - curr_peer-> - pHddTdlsCtx->pAdapter); + opclass, channel, + state, res, adapter); } return; } @@ -966,7 +1013,7 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, tTDLSLinkStatus linkStatus, tTDLSLinkReason reason) { - int32_t state = 0; + uint32_t state = 0; int32_t res = 0; hddTdlsPeer_t *curr_peer; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); @@ -994,13 +1041,18 @@ void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter, } 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; + 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, - state, - res, - curr_peer->pHddTdlsCtx-> - pAdapter); + (curr_peer->state_change_notification)(mac, opclass, channel, + state, res, adapter); } return; @@ -1808,11 +1860,6 @@ int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, const uint8_t *mac, curr_peer->op_class_for_pref_off_chan = (uint8_t) op_class; curr_peer->pref_off_chan_num = (uint8_t) chan; - if (curr_peer->op_class_for_pref_off_chan) - curr_peer->op_class_for_pref_off_chan_is_set = 1; - else - curr_peer->op_class_for_pref_off_chan_is_set = 0; - mutex_unlock(&pHddCtx->tdls_lock); return 0; } @@ -1960,6 +2007,22 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac) return -EINVAL; } + /* + * 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->config->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->config->fTDLSPrefOffChanBandwidth); + } + wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE, eTDLS_LINK_UNSPECIFIED); @@ -2854,9 +2917,24 @@ int wlan_hdd_set_callback(hddTdlsPeer_t *curr_peer, * Return: Void */ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, - int32_t *state, int32_t *reason) + uint32_t *state, int32_t *reason) { + hdd_context_t *hddctx; + hdd_adapter_t *adapter; + + if (!curr_peer) { + hdd_err("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: @@ -2867,7 +2945,11 @@ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, *state = QCA_WIFI_HAL_TDLS_ENABLED; break; case eTDLS_LINK_CONNECTED: - *state = QCA_WIFI_HAL_TDLS_ESTABLISHED; + if ((hddctx->config->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; @@ -2885,32 +2967,38 @@ void wlan_hdd_tdls_get_wifi_hal_state(hddTdlsPeer_t *curr_peer, * Return: 0 if success; negative errno otherwise */ int wlan_hdd_tdls_get_status(hdd_adapter_t *pAdapter, - const uint8_t *mac, int32_t *state, + const uint8_t *mac, uint32_t *opclass, + uint32_t *channel, uint32_t *state, int32_t *reason) { hddTdlsPeer_t *curr_peer; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true); + if (0 != (wlan_hdd_validate_context(pHddCtx))) + return -EINVAL; + + mutex_lock(&pHddCtx->tdls_lock); + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac, false); if (curr_peer == NULL) { + mutex_unlock(&pHddCtx->tdls_lock); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, FL("curr_peer is NULL")); *state = QCA_WIFI_HAL_TDLS_DISABLED; *reason = eTDLS_LINK_UNSPECIFIED; + return -EINVAL; + } + if (pHddCtx->config->fTDLSExternalControl && + (false == curr_peer->isForcedPeer)) { + hdd_err("curr_peer is not Forced"); + *state = QCA_WIFI_HAL_TDLS_DISABLED; + *reason = eTDLS_LINK_UNSPECIFIED; } else { - if (pHddCtx->config->fTDLSExternalControl && - (false == curr_peer->isForcedPeer)) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("curr_peer is not Forced")); - *state = QCA_WIFI_HAL_TDLS_DISABLED; - *reason = eTDLS_LINK_UNSPECIFIED; - } else { - wlan_hdd_tdls_get_wifi_hal_state(curr_peer, - state, reason); - } + wlan_hdd_tdls_determine_channel_opclass(pHddCtx, pAdapter, + curr_peer, channel, opclass); + wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason); } + mutex_unlock(&pHddCtx->tdls_lock); - wlan_hdd_tdls_get_wifi_hal_state(curr_peer, state, reason); return 0; } @@ -2919,12 +3007,12 @@ 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_CHANNEL] = {.type = NLA_U32}, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = {.type = - NLA_S32}, - [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_S32}, + NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_U32}, [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type = - NLA_S32}, + NLA_U32}, }; static const struct nla_policy wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + @@ -3003,7 +3091,8 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, nla_data(tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]), sizeof(peer)); hddLog(CDF_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peer)); - ret = wlan_hdd_tdls_get_status(pAdapter, peer, &state, &reason); + ret = wlan_hdd_tdls_get_status(pAdapter, peer, &global_operating_class, + &channel, &state, &reason); if (0 != ret) { hddLog(CDF_TRACE_LEVEL_ERROR, FL("get status Failed")); return -EINVAL; @@ -3076,14 +3165,14 @@ int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, * Return: 0 for success; negative errno otherwise */ static int wlan_hdd_cfg80211_exttdls_callback(const uint8_t *mac, + uint32_t global_operating_class, + uint32_t channel, uint32_t state, int32_t 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; - uint32_t global_operating_class = 0; - uint32_t channel = 0; ENTER(); @@ -4171,21 +4260,15 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, prefOffChanBandwidth = pHddCtx->config-> fTDLSPrefOffChanBandwidth; - if (pTdlsPeer-> - op_class_for_pref_off_chan_is_set) { - smeTdlsPeerStateParams.peerCap. - opClassForPrefOffChanIsSet = - pTdlsPeer-> - op_class_for_pref_off_chan_is_set; - smeTdlsPeerStateParams.peerCap. + smeTdlsPeerStateParams.peerCap. opClassForPrefOffChan = pTdlsPeer-> op_class_for_pref_off_chan; - } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_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_is_set: %d, op_class_for_pref_off_chan: %d", + "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, @@ -4214,8 +4297,6 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, smeTdlsPeerStateParams. peerCap.prefOffChanBandwidth, pTdlsPeer-> - op_class_for_pref_off_chan_is_set, - pTdlsPeer-> op_class_for_pref_off_chan); for (i = 0; @@ -4596,6 +4677,7 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); sme_tdls_chan_switch_params chan_switch_params; + CDF_STATUS status = CDF_STATUS_E_FAILURE; if (offchanmode < ENABLE_CHANSWITCH || offchanmode > DISABLE_CHANSWITCH) { @@ -4626,46 +4708,24 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) FL("TDLS Connection not supported")); return -ENOTSUPP; } + hddLog(LOG1, - FL("TDLS Channel Switch in swmode=%d"), - offchanmode); + FL("TDLS Channel Switch in swmode=%d tdls_off_channel %d offchanoffset %d"), + offchanmode, hdd_ctx->tdls_off_channel, + hdd_ctx->tdls_channel_offset); switch (offchanmode) { case ENABLE_CHANSWITCH: - case DISABLE_CHANSWITCH: - hddLog(LOG1, - FL( - "change tdls off channel mode %d tdls_off_channel %d offchanoffset %d" - ), - offchanmode, hdd_ctx->tdls_off_channel, - hdd_ctx->tdls_channel_offset); - if (hdd_ctx->tdls_off_channel && hdd_ctx->tdls_channel_offset) { - chan_switch_params.vdev_id = adapter->sessionId; + if (hdd_ctx->tdls_off_channel && + hdd_ctx->tdls_channel_offset) { chan_switch_params.tdls_off_channel = hdd_ctx->tdls_off_channel; chan_switch_params.tdls_off_ch_bw_offset = hdd_ctx->tdls_channel_offset; - chan_switch_params.tdls_off_ch_mode = offchanmode; - chan_switch_params.is_responder = - conn_peer->is_responder; - cdf_mem_copy(&chan_switch_params.peer_mac_addr, - &conn_peer->peerMac, - sizeof(tSirMacAddr)); - hddLog(LOG1, - FL("Peer " MAC_ADDRESS_STR - " vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d" - ), - MAC_ADDR_ARRAY(chan_switch_params. - peer_mac_addr), - chan_switch_params.vdev_id, - chan_switch_params.tdls_off_channel, - chan_switch_params.tdls_off_ch_bw_offset, - chan_switch_params.tdls_off_ch_mode, - chan_switch_params.is_responder); - - sme_send_tdls_chan_switch_req( - WLAN_HDD_GET_HAL_CTX(adapter), - &chan_switch_params); + chan_switch_params.opclass = + wlan_hdd_find_opclass(WLAN_HDD_GET_HAL_CTX(adapter), + chan_switch_params.tdls_off_channel, + chan_switch_params.tdls_off_ch_bw_offset); } else { hddLog(LOGE, FL( @@ -4674,6 +4734,11 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) return -EINVAL; } break; + case DISABLE_CHANSWITCH: + chan_switch_params.tdls_off_channel = 0; + chan_switch_params.tdls_off_ch_bw_offset = 0; + chan_switch_params.opclass = 0; + break; default: hddLog(LOGE, FL( @@ -4681,8 +4746,44 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) ), offchanmode, hdd_ctx->tdls_off_channel, hdd_ctx->tdls_channel_offset); - break; + return -EINVAL; } /* end switch */ + + chan_switch_params.vdev_id = adapter->sessionId; + chan_switch_params.tdls_off_ch_mode = offchanmode; + chan_switch_params.is_responder = + conn_peer->is_responder; + cdf_mem_copy(&chan_switch_params.peer_mac_addr, + &conn_peer->peerMac, + sizeof(tSirMacAddr)); + hdd_log(LOG1, + FL("Peer " MAC_ADDRESS_STR + " vdevId: %d, off channel: %d, offset: %d, mode: %d, is_responder: %d"), + MAC_ADDR_ARRAY(chan_switch_params.peer_mac_addr), + chan_switch_params.vdev_id, + chan_switch_params.tdls_off_channel, + chan_switch_params.tdls_off_ch_bw_offset, + chan_switch_params.tdls_off_ch_mode, + chan_switch_params.is_responder); + + status = sme_send_tdls_chan_switch_req(WLAN_HDD_GET_HAL_CTX(adapter), + &chan_switch_params); + + if (status != CDF_STATUS_SUCCESS) { + hdd_log(LOG1, + FL("Failed to send channel switch request to sme")); + return -EINVAL; + } + + hdd_ctx->tdls_fw_off_chan_mode = offchanmode; + + if (ENABLE_CHANSWITCH == offchanmode) { + conn_peer->pref_off_chan_num = + chan_switch_params.tdls_off_channel; + conn_peer->op_class_for_pref_off_chan = + chan_switch_params.opclass; + } + return 0; } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index ec368086c3cc..9fb0305989ab 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -155,7 +155,6 @@ typedef struct _smeTdlsPeerCapParams { uint8_t prefOffChanNum; uint8_t prefOffChanBandwidth; uint8_t opClassForPrefOffChan; - uint8_t opClassForPrefOffChanIsSet; } tSmeTdlsPeerCapParams; typedef enum { @@ -184,6 +183,7 @@ typedef struct sme_tdls_chan_switch_params_struct { uint8_t tdls_off_channel; /* Target Off Channel */ uint8_t tdls_off_ch_mode; /* TDLS Off Channel Mode */ uint8_t is_responder; /* is peer responder or initiator */ + uint8_t opclass; /* tdls operating class */ } sme_tdls_chan_switch_params; #endif /* FEATURE_WLAN_TDLS */ @@ -1056,4 +1056,16 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg); bool sme_validate_sap_channel_switch(tHalHandle hal, uint16_t sap_ch, eCsrPhyMode sap_phy_mode, uint8_t cc_switch_mode, uint8_t session_id); + +#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 + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 37ff4d100a70..e1651637af84 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -10045,49 +10045,9 @@ CDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal, peerStateParams->peerCap.prefOffChanNum; peer_cap->prefOffChanBandwidth = peerStateParams->peerCap.prefOffChanBandwidth; + peer_cap->opClassForPrefOffChan = + peerStateParams->peerCap.opClassForPrefOffChan; - if (peerStateParams->peerCap.opClassForPrefOffChanIsSet) { - peer_cap->opClassForPrefOffChan = - peerStateParams->peerCap.opClassForPrefOffChan; - } else { - /* - * 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 (peer_cap->prefOffChanBandwidth & - (1 << BW_40_OFFSET_BIT)) { - peer_cap->opClassForPrefOffChan = - cds_regdm_get_opclass_from_channel( - pMac->scan.countryCodeCurrent, - peer_cap->prefOffChanNum, - BW40_LOW_PRIMARY); - if (!peer_cap->opClassForPrefOffChan) { - peer_cap->opClassForPrefOffChan = - cds_regdm_get_opclass_from_channel( - pMac->scan.countryCodeCurrent, - peer_cap->prefOffChanNum, - BW40_HIGH_PRIMARY); - } - } else if (peer_cap->prefOffChanBandwidth & - (1 << BW_20_OFFSET_BIT)) { - peer_cap->opClassForPrefOffChan = - cds_regdm_get_opclass_from_channel( - pMac->scan.countryCodeCurrent, - peer_cap->prefOffChanNum, - BW20); - } else { - peer_cap->opClassForPrefOffChan = - cds_regdm_get_opclass_from_channel( - pMac->scan.countryCodeCurrent, - peer_cap->prefOffChanNum, - BWALL); - } - } cds_message.type = WMA_UPDATE_TDLS_PEER_STATE; cds_message.reserved = 0; cds_message.bodyptr = pTdlsPeerStateParams; @@ -10159,37 +10119,7 @@ CDF_STATUS sme_send_tdls_chan_switch_req(tHalHandle hal, chan_switch_params->tdls_off_ch_bw_offset = ch_switch_params->tdls_off_ch_bw_offset; chan_switch_params->is_responder = ch_switch_params->is_responder; - - switch (chan_switch_params->tdls_off_ch_bw_offset) { - case (1 << BW_20_OFFSET_BIT): - chan_switch_params->oper_class = - cds_regdm_get_opclass_from_channel( - mac->scan.countryCodeCurrent, - chan_switch_params->tdls_off_ch, - BW20); - break; - case (1 << BW_40_OFFSET_BIT): - chan_switch_params->oper_class = - cds_regdm_get_opclass_from_channel( - mac->scan.countryCodeCurrent, - chan_switch_params->tdls_off_ch, - BW40_LOW_PRIMARY); - if (!chan_switch_params->oper_class) { - chan_switch_params->oper_class = - cds_regdm_get_opclass_from_channel( - mac->scan.countryCodeCurrent, - chan_switch_params->tdls_off_ch, - BW40_HIGH_PRIMARY); - } - break; - default: - chan_switch_params->oper_class = - cds_regdm_get_opclass_from_channel( - mac->scan.countryCodeCurrent, - chan_switch_params->tdls_off_ch, - BWALL); - break; - } /* end switch */ + chan_switch_params->oper_class = ch_switch_params->opclass; CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, FL("Country Code=%s, Req offset=%d, Selected Operate Class=%d"), @@ -14916,3 +14846,49 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) return; } + +#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 = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, BW40_LOW_PRIMARY); + if (!(*opclass)) { + *opclass = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, BW40_HIGH_PRIMARY); + } + } else if (bw_offset & (1 << BW_20_OFFSET_BIT)) { + *opclass = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, BW20); + } else { + *opclass = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, BWALL); + } +} +#endif -- cgit v1.2.3 From 3f50cd3ff68ab404cdcfcd4d39621092f309d24c Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Mon, 2 Nov 2015 11:13:42 +0530 Subject: qcacld-3.0: Fix memory leak in tx flow control timer qcacld-2.0 to qcacld-3.0 propagation TX flow control timer initialized when STATION interface is created. During IBSS startup, STATION interface is changed to ADHOC type. TX flow control timer is not required, so close tx flow control and destroy timer. Change-Id: Id9c440638964fb3ab0e95d8a7c747708886a94ff CRs-Fixed: 882821 --- core/hdd/src/wlan_hdd_cfg80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 97b3fef55d41..b392482b3900 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5540,6 +5540,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, case NL80211_IFTYPE_ADHOC: wlan_hdd_tdls_exit(pAdapter); + hdd_deregister_tx_flow_control(pAdapter); hddLog(LOG1, FL("Setting interface Type to ADHOC")); wlan_hdd_change_iface_to_adhoc(ndev, pRoamProfile, type); -- cgit v1.2.3 From c8669318e830607c4f6ba6b07819c62f6001e2d3 Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Mon, 10 Aug 2015 11:11:24 +0530 Subject: qcacld-3.0: Send assoc response for duplicate assoc request frames qcacld-2.0 to qcacld-3.0 propagation Few STA/P2P-client's are sending assoc req frame and waiting for 300-500ms. If they don't receive the assoc resp frame within this time then they resending the assoc req frame. These frames are not going to have retry bit set. In the current design host driver is not handling these duplicate assoc req frames without retry bit set. To mitigate this issue, while processing assoc request frame, if pStaDs entry already exists then send assoc response with same tid and stop processing the assoc req further. Change-Id: I6d67f4cd352bbee422301b832742e7386666037f CRs-Fixed: 868736 --- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 33 ++++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 1972461f0350..02b092312dc2 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -280,13 +280,32 @@ lim_process_assoc_req_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, */ pStaDs = dph_lookup_hash_entry(pMac, pHdr->sa, &assoc_id, &psessionEntry->dph.dphHashTable); - if ((NULL != pStaDs) && (pHdr->fc.retry > 0)) { - lim_log(pMac, LOGE, - FL("STA is initiating Assoc Req after ACK lost. Do not process" - " 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)); + if ((NULL != pStaDs)) { + if (pHdr->fc.retry > 0) { + lim_log(pMac, LOGE, + FL("STA is initiating Assoc Req after ACK lost. Do not process" + " 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)); + } else { + /* + * STA might have missed the assoc response, + * so it is sending assoc request frame again. + */ + lim_send_assoc_rsp_mgmt_frame(pMac, eSIR_SUCCESS, + pStaDs->assocId, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, pStaDs, + psessionEntry); + lim_log(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; } -- cgit v1.2.3 From a797903ac9014edd350fef08166a4fcac5ebfdfe Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Mon, 2 Nov 2015 12:03:50 +0530 Subject: qcacld-3.0: Delete all TDLS peers on receiving CSA from AP qcacld-2.0 to qcacld-3.0 propagation On receiving channel switch announcement from AP delete all TDLS peers before leaving BSS and proceed for channel switch. Change-Id: I898f501d9d0afbbfef3a553ed63b52da5cd8f978 CRs-Fixed: 914129 --- core/mac/src/pe/lim/lim_process_probe_rsp_frame.c | 7 +++++++ core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 6 ++++++ core/mac/src/pe/lim/lim_types.h | 10 ++++++++-- core/mac/src/pe/sch/sch_beacon_process.c | 8 ++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c index d3df1d31eba3..0096b48cab36 100644 --- a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c @@ -211,6 +211,13 @@ lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info, } if (LIM_IS_STA_ROLE(session_entry)) { if (probe_rsp->channelSwitchPresent) { + /* + * on receiving channel switch announcement + * from AP, delete all TDLS peers before + * leaving BSS and proceed for channel switch + */ + lim_delete_tdls_peers(mac_ctx, session_entry); + lim_update_channel_switch(mac_ctx, probe_rsp, session_entry); diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index e27113cd52da..10a7032ce8a3 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1984,6 +1984,12 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) } if (LIM_IS_STA_ROLE(session_entry)) { + /* + * on receiving channel switch announcement from AP, delete all + * TDLS peers before leaving BSS and proceed for channel switch + */ + lim_delete_tdls_peers(mac_ctx, session_entry); + session_entry->gLimChannelSwitch.switchMode = csa_params->switchmode; /* timer already started by firmware, switch immediately */ diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 8bffe8b8e244..e03973065135 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -539,14 +539,20 @@ void lim_send_sme_tdls_delete_all_peer_ind(tpAniSirGlobal pMac, tpPESession psessionEntry); void lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac, tpPESession psessionEntry, uint32_t txCompleteStatus); -tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal pMac, - tpPESession psessionEntry); +tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, + tpPESession session_entry); CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession); tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, tSirMacAddr peerMac, uint16_t reason, uint8_t responder, tpPESession psessionEntry, uint8_t *addIe, uint16_t addIeLen); +#else +static inline tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, + tpPESession session_entry) +{ + return eSIR_SUCCESS; +} #endif /* Algorithms & Link Monitoring related functions */ diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index 459cb90bcb2c..66c7a71ad4ee 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -739,6 +739,14 @@ static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, || LIM_IS_IBSS_ROLE(session)) { /* Channel Switch information element updated */ if (bcn->channelSwitchPresent) { + /* + * on receiving channel switch announcement from AP, + * delete all TDLS peers before leaving BSS and proceed + * for channel switch + */ + if (LIM_IS_STA_ROLE(session)) + lim_delete_tdls_peers(mac_ctx, session); + lim_update_channel_switch(mac_ctx, bcn, session); } else if (session->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) { -- cgit v1.2.3 From 25b19528660b69536e1aacfd80e2345747dac494 Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Fri, 9 Oct 2015 11:20:50 +0530 Subject: qcacld-3.0: channel bonding is not valid for channel 14 qcacld-2.0 to qcacld-3.0 propagation Channel bonding mode in not valid for channel 14. So don't consider it while deriving the channel bonding mode. Change-Id: I7ceae149cdd9e2f3c75f937c56cc5e93455fa8ee CRs-Fixed: 908439 --- core/cds/src/cds_reg_service.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index 836ff93308b6..f439c5971efc 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -747,7 +747,11 @@ enum channel_width cds_get_max_channel_bw(uint32_t chan_num) static int cds_bw20_ch_index_to_bw40_ch_index(int k) { int m = -1; - if (k >= RF_CHAN_1 && k <= RF_CHAN_14) { + if (k >= RF_CHAN_1 && k <= RF_CHAN_13) { + /* + * Channel bonding is not valid for channel 14, + * Hence don't consider it + */ m = k - RF_CHAN_1 + RF_CHAN_BOND_3; if (m > RF_CHAN_BOND_11) m = RF_CHAN_BOND_11; -- cgit v1.2.3 From 146af2ac0997d693e96943c160c436663b9844cb Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Tue, 25 Aug 2015 10:22:46 +0530 Subject: qcacld-3.0: free cfgState->buf in failure cases. qcacld-2.0 to qcacld-3.0 propagation As part of cleaning up pending action frame, if timeout happens for tx cnf event then indicate tx failure status as FAIL and free cfgState->buf to avoid memory leak. Change-Id: I6caaa8efeab769cce8c4cdfcc868101e63fd8e76 CRs-Fixed: 880779 --- core/hdd/src/wlan_hdd_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 645f0e64fd72..c52b861fa490 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2081,6 +2081,11 @@ void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) if (!rc) { hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD Wait for Action Confirmation Failed!!")); + /* + * Inform tx status as FAILURE to upper layer and free + * cfgState->buf + */ + hdd_send_action_cnf(adapter, false); } } return; -- cgit v1.2.3 From 544c67ff9f164dc691a823ff43b6232ba49d35d8 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Thu, 5 Nov 2015 14:27:37 -0800 Subject: qcacld-3.0: Fix UL TPUT issue when connected to 160MHz AP This is qcacld-2.0 to qcacld-3.0 propagation When STA is connected to 160MHz AP, channel width is updated to 20MHz since the 160MHz channel width is not handled. Add support to handle the 160MHz BW in beacon IEs. Change-Id: Id13164762d6da142093f049121440ce976cecfc1 CRs-Fixed: 924219 --- core/mac/src/pe/lim/lim_assoc_utils.c | 23 ++- core/mac/src/pe/lim/lim_process_action_frame.c | 31 +++- core/mac/src/pe/lim/lim_prop_exts_utils.c | 31 +++- core/mac/src/pe/lim/lim_utils.c | 30 ++++ core/mac/src/pe/lim/lim_utils.h | 1 + core/mac/src/pe/sch/sch_beacon_process.c | 193 +++++++++++++------------ core/wma/inc/wma.h | 1 + core/wma/src/wma_utils.c | 25 ++++ 8 files changed, 222 insertions(+), 113 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index a1680d6bab13..e88adf911292 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -4033,11 +4033,14 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, lim_log(pMac, LOG1, FL( "VHT Op IE is in vendor Specfic IE")); } - if ((vht_oper != NULL) && - pAddBssParams->staContext.vhtCapable && - vht_oper->chanWidth) - pAddBssParams->staContext.ch_width = - vht_oper->chanWidth + 1; + /* + * in limExtractApCapability function intersection of FW + * advertised channel width and AP advertised channel + * width has been taken into account for calculating + * psessionEntry->ch_width + */ + pAddBssParams->staContext.ch_width = + psessionEntry->ch_width; lim_log(pMac, LOGE, FL( "StaCtx: vhtCap %d ChBW %d TxBF %d"), @@ -4480,13 +4483,19 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update if ((vht_oper != NULL) && vht_oper->chanWidth && chanWidthSupp) { - pAddBssParams->ch_width = - vht_oper->chanWidth + 1; pAddBssParams->ch_center_freq_seg0 = vht_oper->chanCenterFreqSeg1; pAddBssParams->ch_center_freq_seg1 = vht_oper->chanCenterFreqSeg2; } + /* + * in limExtractApCapability function intersection of FW + * advertised channel width and AP advertised channel width has + * been taken into account for calculating + * psessionEntry->ch_width + */ + pAddBssParams->ch_width = + psessionEntry->ch_width; pAddBssParams->staContext.maxAmpduSize = SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( pAddBssParams->staContext.vht_caps); diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index a7b1b88a5d64..99526f774385 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -58,7 +58,7 @@ #include "lim_session_utils.h" #include "cds_concurrency.h" #include "wma_types.h" - +#include "wma.h" #define BA_DEFAULT_TX_BUFFER_SIZE 64 @@ -466,6 +466,8 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx, uint16_t aid; uint8_t oper_mode; uint8_t cb_mode; + uint8_t ch_bw = 0; + uint8_t skip_opmode_update = false; mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info); @@ -514,7 +516,16 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx, } else { oper_mode = eHT_CHANNEL_WIDTH_20MHZ; } - if (oper_mode != operating_mode_frm->OperatingMode.chanWidth) { + + if ((oper_mode == eHT_CHANNEL_WIDTH_80MHZ) && + (operating_mode_frm->OperatingMode.chanWidth > + eHT_CHANNEL_WIDTH_80MHZ)) + skip_opmode_update = true; + + if (!skip_opmode_update && (oper_mode != + operating_mode_frm->OperatingMode.chanWidth)) { + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + lim_log(mac_ctx, LOGE, FL(" received Chanwidth %d, staIdx = %d"), (operating_mode_frm->OperatingMode.chanWidth), @@ -525,34 +536,38 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx, mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2], mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]); - if (operating_mode_frm->OperatingMode.chanWidth == - eHT_CHANNEL_WIDTH_160MHZ) { + if (operating_mode_frm->OperatingMode.chanWidth >= + eHT_CHANNEL_WIDTH_160MHZ + && (fw_vht_ch_wd >= eHT_CHANNEL_WIDTH_160MHZ)) { sta_ptr->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; sta_ptr->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; - } else if (operating_mode_frm->OperatingMode.chanWidth == + ch_bw = eHT_CHANNEL_WIDTH_160MHZ; + } else if (operating_mode_frm->OperatingMode.chanWidth >= eHT_CHANNEL_WIDTH_80MHZ) { sta_ptr->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; sta_ptr->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + ch_bw = eHT_CHANNEL_WIDTH_80MHZ; } else if (operating_mode_frm->OperatingMode.chanWidth == eHT_CHANNEL_WIDTH_40MHZ) { sta_ptr->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; sta_ptr->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; + ch_bw = eHT_CHANNEL_WIDTH_40MHZ; } else if (operating_mode_frm->OperatingMode.chanWidth == eHT_CHANNEL_WIDTH_20MHZ) { sta_ptr->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; sta_ptr->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; + ch_bw = eHT_CHANNEL_WIDTH_20MHZ; } - lim_check_vht_op_mode_change(mac_ctx, session, - operating_mode_frm->OperatingMode.chanWidth, - sta_ptr->staIndex, mac_hdr->sa); + lim_check_vht_op_mode_change(mac_ctx, session, ch_bw, + sta_ptr->staIndex, mac_hdr->sa); } if (sta_ptr->vhtSupportedRxNss != diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index f47dd34caff2..c45da30c1b61 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -55,6 +55,8 @@ #include "lim_ft_defs.h" #endif #include "lim_session.h" +#include "wma.h" + #define LIM_GET_NOISE_MAX_TRY 5 /** * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability @@ -140,6 +142,7 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, } else { session->vhtCapabilityPresentInBeacon = 0; } + if (session->vhtCapabilityPresentInBeacon == 1 && session->txBFIniFeatureEnabled == 0) { cfg_set_status = cfg_set_int(mac_ctx, @@ -159,12 +162,28 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, session->txBFIniFeatureEnabled = 0; } else if (session->vhtCapabilityPresentInBeacon == 1 && beacon_struct->VHTOperation.chanWidth) { - session->ch_center_freq_seg0 = - beacon_struct->VHTOperation.chanCenterFreqSeg1; - session->ch_center_freq_seg1 = - beacon_struct->VHTOperation.chanCenterFreqSeg2; - session->ch_width = - beacon_struct->VHTOperation.chanWidth + 1; + /* 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 = CDF_MIN(fw_vht_ch_wd, + beacon_struct->VHTOperation.chanWidth); + if (vht_ch_wd == beacon_struct->VHTOperation.chanWidth + || vht_ch_wd >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { + /* + * This block covers 2 cases: + * 1) AP and STA both have same vht capab + * 2) AP is 160 (80+80), we are 160 only + */ + session->ch_center_freq_seg0 = + beacon_struct->VHTOperation.chanCenterFreqSeg1; + session->ch_center_freq_seg1 = + beacon_struct->VHTOperation.chanCenterFreqSeg2; + } else { + /* when AP was 160 but we were 80 only */ + session->ch_center_freq_seg0 = + lim_get_80Mhz_center_channel( + beacon_struct->channelNumber); + } + session->ch_width = vht_ch_wd + 1; if (CH_WIDTH_80MHZ < session->ch_width) { session->enable_su_tx_bformer = 0; session->nss = 1; diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index d34c2a30d0af..28f4a84b0e55 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7143,3 +7143,33 @@ void lim_merge_extcap_struct(tDot11fIEExtCap *dst, } } +/** + * 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 INVALID_CHANNEL_ID; +} diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 76b000cdd342..f551109e1296 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -588,4 +588,5 @@ tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst); void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src); +uint8_t lim_get_80Mhz_center_channel(uint8_t primary_channel); #endif /* __LIM_UTILS_H */ diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index 66c7a71ad4ee..059a58712a36 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -58,6 +58,7 @@ #include "host_diag_core_log.h" #endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#include "wma.h" /** * Number of bytes of variation in beacon length from the last beacon * to trigger reprogramming of rx delay register @@ -529,6 +530,8 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx, uint8_t operMode; uint8_t chWidth = 0; uint8_t cb_mode; + uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); + bool skip_opmode_update = false; if (RF_CHAN_14 >= session->currentOperChannel) cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz; @@ -545,55 +548,63 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx, if (session->vhtCapability && bcn->OperatingMode.present) { operMode = get_operating_channel_width(pStaDs); - if (operMode == bcn->OperatingMode.chanWidth) - return; - - PELOGE(sch_log(mac_ctx, LOGE, - FL("received OpMode Chanwidth %d, staIdx = %d"), - bcn->OperatingMode.chanWidth, pStaDs->staIndex);) - PELOGE(sch_log(mac_ctx, LOGE, - 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 ((operMode == eHT_CHANNEL_WIDTH_80MHZ) && + (bcn->OperatingMode.chanWidth > eHT_CHANNEL_WIDTH_80MHZ)) + skip_opmode_update = true; - if (bcn->OperatingMode.chanWidth == - eHT_CHANNEL_WIDTH_160MHZ) { + if (!skip_opmode_update && + (operMode != bcn->OperatingMode.chanWidth)) { PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 160MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; - pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_40MHZ; - } else if (bcn->OperatingMode.chanWidth == - eHT_CHANNEL_WIDTH_80MHZ) { + FL("received OpMode Chanwidth %d, staIdx = %d"), + bcn->OperatingMode.chanWidth, pStaDs->staIndex);) PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 80MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; - pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_40MHZ; - } else if (bcn->OperatingMode.chanWidth == - eHT_CHANNEL_WIDTH_40MHZ) { - PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 40MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; - pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_40MHZ; - } else if (bcn->OperatingMode.chanWidth == - eHT_CHANNEL_WIDTH_20MHZ) { - PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 20MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; - pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_20MHZ; + 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 ((bcn->OperatingMode.chanWidth >= + eHT_CHANNEL_WIDTH_160MHZ) && + (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 160MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + } else if (bcn->OperatingMode.chanWidth >= + eHT_CHANNEL_WIDTH_80MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + 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 (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_40MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + 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 (bcn->OperatingMode.chanWidth == + eHT_CHANNEL_WIDTH_20MHZ) { + PELOGE(sch_log(mac_ctx, LOGE, + 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; + } + lim_check_vht_op_mode_change(mac_ctx, session, + chWidth, pStaDs->staIndex, pMh->sa); + update_nss(mac_ctx, pStaDs, bcn, session, pMh); } - lim_check_vht_op_mode_change(mac_ctx, session, - bcn->OperatingMode.chanWidth, - pStaDs->staIndex, pMh->sa); - update_nss(mac_ctx, pStaDs, bcn, session, pMh); return; } @@ -601,63 +612,61 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx, return; operMode = pStaDs->vhtSupportedChannelWidthSet; - if (operMode == bcn->VHTOperation.chanWidth) - return; + if ((operMode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) && + (operMode < bcn->VHTOperation.chanWidth)) + skip_opmode_update = true; - PELOGE(sch_log(mac_ctx, LOGE, - FL("received VHTOP CHWidth %d staIdx = %d"), - bcn->VHTOperation.chanWidth, pStaDs->staIndex);) - PELOGE(sch_log(mac_ctx, LOGE, - 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 (bcn->VHTOperation.chanWidth == - WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { - PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 160MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; - pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_40MHZ; - chWidth = eHT_CHANNEL_WIDTH_160MHZ; - } else if (bcn->VHTOperation.chanWidth == - WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) { + if (!skip_opmode_update && + (operMode != bcn->VHTOperation.chanWidth)) { PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 160MHz"));) - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; - pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; - chWidth = eHT_CHANNEL_WIDTH_160MHZ; - } else if (bcn->VHTOperation.chanWidth == - WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + FL("received VHTOP CHWidth %d staIdx = %d"), + bcn->VHTOperation.chanWidth, pStaDs->staIndex);) PELOGE(sch_log(mac_ctx, LOGE, - 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 (bcn->VHTOperation.chanWidth == - WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { - pStaDs->vhtSupportedChannelWidthSet = - WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; - if (bcn->HTCaps.supportedChannelWidthSet) { + 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 ((bcn->VHTOperation.chanWidth >= + WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) && + (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 40MHz"));) + FL("Updating the CH Width to 160MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + bcn->VHTOperation.chanWidth; pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; - chWidth = eHT_CHANNEL_WIDTH_40MHZ; - } else { + chWidth = eHT_CHANNEL_WIDTH_160MHZ; + } else if (bcn->VHTOperation.chanWidth >= + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { PELOGE(sch_log(mac_ctx, LOGE, - FL("Updating the CH Width to 20MHz"));) + FL("Updating the CH Width to 80MHz"));) + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; pStaDs->htSupportedChannelWidthSet = - eHT_CHANNEL_WIDTH_20MHZ; - chWidth = eHT_CHANNEL_WIDTH_20MHZ; + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_80MHZ; + } else if (bcn->VHTOperation.chanWidth == + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { + pStaDs->vhtSupportedChannelWidthSet = + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; + if (bcn->HTCaps.supportedChannelWidthSet) { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 40MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_40MHZ; + chWidth = eHT_CHANNEL_WIDTH_40MHZ; + } else { + PELOGE(sch_log(mac_ctx, LOGE, + FL("Updating the CH Width to 20MHz"));) + pStaDs->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; + chWidth = eHT_CHANNEL_WIDTH_20MHZ; + } } + lim_check_vht_op_mode_change(mac_ctx, session, chWidth, + pStaDs->staIndex, pMh->sa); } - lim_check_vht_op_mode_change(mac_ctx, session, chWidth, - pStaDs->staIndex, pMh->sa); return; } diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index c2204a5d1213..2993a9fcd0e7 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2000,6 +2000,7 @@ void wmi_desc_put(tp_wma_handle wma_handle, struct wmi_desc_t *wmi_desc); int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params, uint32_t len); void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region); +uint32_t wma_get_vht_ch_width(void); #if defined(FEATURE_LRO) CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle, diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index a8f81d5ece69..cb1cc1ef84c3 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -70,6 +70,8 @@ #include "wma_internal.h" #include "cds_concurrency.h" +#include "linux/ieee80211.h" + /* MCS Based rate table */ /* HT MCS parameters with Nss = 1 */ static struct index_data_rate_type supported_mcs_rate_nss1[] = { @@ -3604,3 +3606,26 @@ bool wma_is_scan_simultaneous_capable(void) 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; + tp_wma_handle wm_hdl = cds_get_context(CDF_MODULE_ID_WMA); + + if (NULL == wm_hdl) + return fw_ch_wd; + + if (wm_hdl->vht_cap_info & + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) + fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; + else if (wm_hdl->vht_cap_info & + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) + fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; + + return fw_ch_wd; +} -- cgit v1.2.3 From d457067574c103df35c7e889b1c302aab27b476b Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 09:58:27 -0800 Subject: qcacld-3.0: Add support for FST Action frames This is qcacld-2.0 to qcacld-3.0 propagation Currently driver drops the action frame category 18 - FST action frames. This patch adds support for these frames in wlan host code. Change-Id: I7021e328b7ebe9a1e46f526e3928c7d1279e1ad7 CRs-Fixed: 921117 --- core/mac/inc/sir_mac_prot_def.h | 1 + core/mac/src/pe/lim/lim_process_action_frame.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 8ea6dceed498..bf90279c001f 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -141,6 +141,7 @@ #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 */ diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 99526f774385..2c23c83f8586 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -2130,6 +2130,23 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, } break; #endif + case SIR_MAC_ACTION_FST: { + tpSirMacMgmtHdr hdr; + uint32_t frame_len; + + hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + + lim_log(mac_ctx, LOG1, FL("Received FST MGMT action frame")); + /* Forward to the SME to HDD */ + lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType, + (uint8_t *)hdr, + frame_len + sizeof(tSirMacMgmtHdr), + session->smeSessionId, + WMA_GET_RX_CH(rx_pkt_info), + session, 0); + break; + } default: lim_log(mac_ctx, LOGE, FL("Action category %d not handled"), -- cgit v1.2.3 From 21c4003a06f2b3dae5c0c91aa17494cd4d8b6e20 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Fri, 13 Nov 2015 12:01:43 -0800 Subject: qcacld-3.0: Increase SME cmd queue to support max clients connected This is qcacld-2.0 to qcacld-3.0 propagation Currently in SAP mode, if max STA connected a operation to turn off SAP will result in more than SME queue length cmds being enqueued. To fix, this patch: 1) Makes the SME cmd queue length, 3 times the max STA. 2) Because of increased SME cmds, the allocation for all cmds together will fail, hence allocate each SME cmd individually and free them accordingly. Change-Id: Ia1dfc5b00eacd9bdb503ce18927c62f1edd15320 CRs-Fixed: 928840 --- core/sme/inc/sme_inside.h | 8 ++++-- core/sme/inc/sme_internal.h | 3 +- core/sme/src/common/sme_api.c | 64 +++++++++++++++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index e1db6a871d4a..1d5f28bdeada 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -59,8 +59,12 @@ ePhyChanBondState csr_convert_cb_ini_value_to_phy_cb_state(uint32_t cbIniValue); /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ - -#define SME_TOTAL_COMMAND 40 +/* + * 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 { uint32_t size; /* sizeof the data in the union, if any */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index adc01cbd96a9..eb1915f10fb8 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -143,7 +143,8 @@ typedef struct tagSmeStruct { eSmeState state; cdf_mutex_t lkSmeGlobalLock; uint32_t totalSmeCmd; - void *pSmeCmdBufAddr; + /* following pointer contains array of pointers for tSmeCmd* */ + void **pSmeCmdBufAddr; tDblLinkList smeCmdActiveList; tDblLinkList smeCmdPendingList; tDblLinkList smeCmdFreeList; /* preallocated roam cmd list */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index e1651637af84..b0337adde444 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -286,6 +286,27 @@ static CDF_STATUS sme_process_hw_mode_trans_ind(tpAniSirGlobal mac, return CDF_STATUS_SUCCESS; } +/** + * 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++) + cdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]); + + cdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr); + mac_ctx->sme.pSmeCmdBufAddr = NULL; +} + static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) { CDF_STATUS status; @@ -293,6 +314,7 @@ static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) uint32_t cmd_idx; CDF_STATUS cdf_status; cdf_mc_timer_t *cmdTimeoutTimer = NULL; + uint32_t sme_cmd_ptr_ary_sz; pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND; @@ -316,19 +338,36 @@ static CDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac) if (!CDF_IS_STATUS_SUCCESS(status)) goto end; - pCmd = cdf_mem_malloc(sizeof(tSmeCmd) * pMac->sme.totalSmeCmd); - if (NULL == pCmd) + /* following pointer contains array of pointers for tSmeCmd* */ + sme_cmd_ptr_ary_sz = sizeof(void *) * pMac->sme.totalSmeCmd; + pMac->sme.pSmeCmdBufAddr = cdf_mem_malloc(sme_cmd_ptr_ary_sz); + if (NULL == pMac->sme.pSmeCmdBufAddr) { status = CDF_STATUS_E_NOMEM; - else { - status = CDF_STATUS_SUCCESS; - - cdf_mem_set(pCmd, sizeof(tSmeCmd) * pMac->sme.totalSmeCmd, 0); - pMac->sme.pSmeCmdBufAddr = pCmd; + goto end; + } - for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) { - csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, - &pCmd[cmd_idx].Link, LL_ACCESS_LOCK); + status = CDF_STATUS_SUCCESS; + cdf_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] = + cdf_mem_malloc(sizeof(tSmeCmd)); + if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) { + status = CDF_STATUS_E_NOMEM; + free_sme_cmds(pMac); + goto end; } + pCmd = (tSmeCmd *)pMac->sme.pSmeCmdBufAddr[cmd_idx]; + csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, + &pCmd->Link, LL_ACCESS_LOCK); } /* This timer is only to debug the active list command timeout */ @@ -449,10 +488,7 @@ static CDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac) goto done; } - if (NULL != pMac->sme.pSmeCmdBufAddr) { - cdf_mem_free(pMac->sme.pSmeCmdBufAddr); - pMac->sme.pSmeCmdBufAddr = NULL; - } + free_sme_cmds(pMac); status = cdf_mutex_release(&pMac->sme.lkSmeGlobalLock); if (status != CDF_STATUS_SUCCESS) { -- cgit v1.2.3 From bce8774ba0689019f2c18706b09642107b251081 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 1 Dec 2015 12:08:45 -0800 Subject: qcacld-3.0: Enable gEnableTxSUBeamformer by default This patch enables gEnableTxSUBeamformer by default in config ini which will help to uncover some of the bugs in default DEV testing. Change-Id: Ib64d53d307aced8f5384d691a3d7f4b383d52a0f CRs-Fixed: 930322 --- config/WCNSS_qcom_cfg.ini | 2 +- core/hdd/inc/wlan_hdd_cfg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index a2f906b94325..c652d36db4d0 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -375,7 +375,7 @@ gTxBFEnable=1 gEnableTxBFin20MHz=1 #Enable/Disable SU Tx beamformer support. -gEnableTxSUBeamfomer=0 +gEnableTxSUBeamformer=1 #Enable Scan Results Aging based on timer #Timer value is in seconds diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 3777d8425bd4..9fc774217036 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1691,7 +1691,7 @@ typedef enum { #define CFG_VHT_ENABLE_TXBF_IN_20MHZ_MAX (1) #define CFG_VHT_ENABLE_TXBF_IN_20MHZ_DEFAULT (0) -#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER "gEnableTxSUBeamfomer" +#define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER "gEnableTxSUBeamformer" #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MIN (0) #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_MAX (1) #define CFG_VHT_ENABLE_TX_SU_BEAM_FORMER_DEFAULT (0) -- cgit v1.2.3 From 18c7fc529e521cd0f09e6e8bb4f511b3cc5bbade Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 2 Sep 2015 11:44:42 -0700 Subject: qcacld-3.0: Move force break to CE_state Removing references to global data in the processing of copy engine interupts. Change-Id: I4d18198c392aab8c46aa755e2007ba2da0c47a57 CRs-Fixed: 941355 --- core/hif/inc/hif.h | 2 -- core/hif/src/ce/ce_internal.h | 2 ++ core/hif/src/ce/ce_main.c | 3 ++- core/hif/src/ce/ce_service.c | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index ab99b62c1c1d..78f82d60dcce 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -292,8 +292,6 @@ struct ol_softc { */ cdf_spinlock_t target_lock; unsigned int ce_count; /* Number of Copy Engines supported */ - 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 */ diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index b3fa70737007..7e5a039d704d 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -129,6 +129,8 @@ struct CE_state { struct CE_ring_state *src_ring; struct CE_ring_state *dest_ring; atomic_t rx_pending; + bool force_break; /* Flag to indicate whether to + * break out the DPC context */ /* epping */ bool timer_inited; diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index db5884017770..f27ab12125fe 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -729,6 +729,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, 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 CE_state *ce_state = (struct CE_state *) copyeng; struct ol_softc *scn = hif_state->scn; struct HIF_CE_completion_state *compl_state; struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail; @@ -780,7 +781,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, scn->receive_count++; if (cdf_unlikely(hif_max_num_receives_reached( scn->receive_count))) { - scn->force_break = 1; + ce_state->force_break = 1; break; } } while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context, diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 4b6c37bc7ccc..6bf9e616fe66 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1182,7 +1182,7 @@ int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id) /* NAPI: scn variables- thread/multi-processing safety? */ scn->receive_count = 0; - scn->force_break = 0; + CE_state->force_break = 0; more_completions: if (CE_state->recv_cb) { @@ -1215,7 +1215,7 @@ more_completions: /* Break the receive processes by * force if force_break set up */ - if (cdf_unlikely(scn->force_break)) { + if (cdf_unlikely(CE_state->force_break)) { cdf_atomic_set(&CE_state->rx_pending, 1); CE_ENGINE_INT_STATUS_CLEAR(scn, ctrl_addr, HOST_IS_COPY_COMPLETE_MASK); -- cgit v1.2.3 From 910c626231b00d4217e680323ce153056c5b62e8 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 12:56:25 -0700 Subject: qcacld-3.0: Bypass hif_completion_thread in recv We want to process the completions in parallel. Upper layer should take care of its own thread safety. hif_completion_thread is a legacy function that does in context serialization of hif completions. Bypass it. Change-Id: I7953545b55dae093931741359bbf985e2fb9faca CRs-Fixed: 941358 --- core/hif/src/ce/ce_main.c | 88 ++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index f27ab12125fe..683f86d4d183 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -719,6 +719,33 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, &toeplitz_hash_result) == CDF_STATUS_SUCCESS); } +/** + * hif_ce_do_recv(): send message from copy engine to upper layers + * @msg_callbacks: structure containing callback and callback context + * @netbuff: skb containing message + * @nbytes: number of bytes in the message + * @pipe_info: used for the pipe_number info + * + * Checks the packet length, configures the lenght in the netbuff, + * and calls the upper layer callback. + * + * return: None + */ +static inline void hif_ce_do_recv(struct hif_msg_callbacks *msg_callbacks, + cdf_nbuf_t netbuf, int nbytes, + struct HIF_CE_pipe_info *pipe_info) { + if (nbytes <= pipe_info->buf_sz) { + cdf_nbuf_set_pktlen(netbuf, nbytes); + msg_callbacks-> + rxCompletionHandler(msg_callbacks->Context, + netbuf, pipe_info->pipe_num); + } else { + HIF_ERROR("%s: Invalid Rx msg buf:%p nbytes:%d", + __func__, netbuf, nbytes); + cdf_nbuf_free(netbuf); + } +} + /* 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, @@ -731,50 +758,18 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state; struct CE_state *ce_state = (struct CE_state *) copyeng; struct ol_softc *scn = hif_state->scn; - struct HIF_CE_completion_state *compl_state; - struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail; + struct hif_msg_callbacks *msg_callbacks = + &hif_state->msg_callbacks_current; - compl_queue_head = compl_queue_tail = NULL; do { - cdf_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; - cdf_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; - cdf_nbuf_unmap_single(scn->cdf_dev, (cdf_nbuf_t) transfer_context, CDF_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 - */ + atomic_inc(&pipe_info->recv_bufs_needed); + hif_post_recv_buffers_for_pipe(pipe_info); + hif_ce_do_recv(msg_callbacks, transfer_context, nbytes, + pipe_info); /* Set up force_break flag if num of receices reaches * MAX_NUM_OF_RECEIVES */ @@ -787,23 +782,6 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, } while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context, &CE_data, &nbytes, &transfer_id, &flags) == CDF_STATUS_SUCCESS); - - cdf_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; - cdf_spin_unlock(&hif_state->completion_pendingq_lock); - } else { - hif_state->completion_pendingq_head = compl_queue_head; - hif_state->completion_pendingq_tail = compl_queue_tail; - cdf_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 */ -- cgit v1.2.3 From 5bf441a4956430d886980119bca324a1e23b4d46 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 2 Sep 2015 11:52:10 -0700 Subject: qcacld-3.0: Move recieve count to CE_state Removing references to global data in the processing of copy engine interupts. Change-Id: I1ecc2ee67526498a56680870969ec529f0ac6e95 CRs-Fixed: 941355 --- core/hif/inc/hif.h | 3 --- core/hif/src/ce/ce_internal.h | 3 +++ core/hif/src/ce/ce_main.c | 4 ++-- core/hif/src/ce/ce_service.c | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 78f82d60dcce..948f389b1be4 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -292,9 +292,6 @@ struct ol_softc { */ cdf_spinlock_t target_lock; unsigned int ce_count; /* Number of Copy Engines supported */ - unsigned int receive_count; /* count Num Of Receive Buffers - * handled for one interrupt - * DPC routine */ struct CE_state *ce_id_to_state[CE_COUNT_MAX]; /* CE id to CE_state */ #ifdef FEATURE_NAPI struct qca_napi_data napi_data; diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index 7e5a039d704d..8d1e9d503413 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -132,6 +132,9 @@ struct CE_state { 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 */ /* epping */ bool timer_inited; cdf_softirq_timer_t poll_timer; diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 683f86d4d183..7d4452adbc54 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -773,9 +773,9 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, /* Set up force_break flag if num of receices reaches * MAX_NUM_OF_RECEIVES */ - scn->receive_count++; + ce_state->receive_count++; if (cdf_unlikely(hif_max_num_receives_reached( - scn->receive_count))) { + ce_state->receive_count))) { ce_state->force_break = 1; break; } diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 6bf9e616fe66..3ed402bc572f 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1181,7 +1181,7 @@ int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id) /* Clear force_break flag and re-initialize receive_count to 0 */ /* NAPI: scn variables- thread/multi-processing safety? */ - scn->receive_count = 0; + CE_state->receive_count = 0; CE_state->force_break = 0; more_completions: if (CE_state->recv_cb) { @@ -1221,8 +1221,8 @@ more_completions: HOST_IS_COPY_COMPLETE_MASK); if (Q_TARGET_ACCESS_END(scn) < 0) HIF_ERROR("<--[premature rc=%d]\n", - scn->receive_count); - return scn->receive_count; + CE_state->receive_count); + return CE_state->receive_count; } cdf_spin_lock(&scn->target_lock); } @@ -1360,8 +1360,8 @@ more_watermarks: cdf_atomic_set(&CE_state->rx_pending, 0); if (Q_TARGET_ACCESS_END(scn) < 0) - HIF_ERROR("<--[premature rc=%d]\n", scn->receive_count); - return scn->receive_count; + HIF_ERROR("<--[premature rc=%d]\n", CE_state->receive_count); + return CE_state->receive_count; } /* -- cgit v1.2.3 From 233e909cbd53d17831165eeddfed1c62621a84c5 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 2 Sep 2015 13:37:21 -0700 Subject: qcacld-3.0: Remove spinlocks from ce_init ce_init should happen before interupts are enabled. Therefore we should be single threaded here and don't need to protect access with a spin lock. Change-Id: I5e1cfd32860eeda8a403744cf1589e35c57ee6df CRs-Fixed: 941355 --- core/hif/src/ce/ce_main.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 7d4452adbc54..40e462ac0994 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -113,6 +113,9 @@ static unsigned int roundup_pwr2(unsigned int n) * 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. + * + * This should be called durring the initialization sequence before + * interupts are enabled, so we don't have to worry about thread safety. */ struct CE_handle *ce_init(struct ol_softc *scn, unsigned int CE_id, struct CE_attr *attr) @@ -126,41 +129,25 @@ struct CE_handle *ce_init(struct ol_softc *scn, CDF_ASSERT(CE_id < scn->ce_count); ctrl_addr = CE_BASE_ADDRESS(CE_id); - cdf_spin_lock(&scn->target_lock); CE_state = scn->ce_id_to_state[CE_id]; if (!CE_state) { - cdf_spin_unlock(&scn->target_lock); CE_state = (struct CE_state *)cdf_mem_malloc(sizeof(*CE_state)); if (!CE_state) { HIF_ERROR("%s: CE_state has no mem", __func__); return NULL; - } else - malloc_CE_state = true; - cdf_mem_zero(CE_state, sizeof(*CE_state)); - cdf_spin_lock(&scn->target_lock); - if (!scn->ce_id_to_state[CE_id]) { /* re-check under lock */ - scn->ce_id_to_state[CE_id] = CE_state; - - CE_state->id = CE_id; - CE_state->ctrl_addr = ctrl_addr; - CE_state->state = CE_RUNNING; - CE_state->attr_flags = attr->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). - */ - cdf_mem_free(CE_state); - malloc_CE_state = false; - CE_state = scn->ce_id_to_state[CE_id]; } + malloc_CE_state = true; + cdf_mem_zero(CE_state, sizeof(*CE_state)); + scn->ce_id_to_state[CE_id] = CE_state; + + CE_state->id = CE_id; + CE_state->ctrl_addr = ctrl_addr; + CE_state->state = CE_RUNNING; + CE_state->attr_flags = attr->flags; } CE_state->scn = scn; - cdf_spin_unlock(&scn->target_lock); cdf_atomic_init(&CE_state->rx_pending); if (attr == NULL) { @@ -200,9 +187,7 @@ struct CE_handle *ce_init(struct ol_softc *scn, HIF_ERROR("%s: src ring has no mem", __func__); if (malloc_CE_state) { /* allocated CE_state locally */ - cdf_spin_lock(&scn->target_lock); scn->ce_id_to_state[CE_id] = NULL; - cdf_spin_unlock(&scn->target_lock); cdf_mem_free(CE_state); malloc_CE_state = false; } @@ -344,9 +329,7 @@ struct CE_handle *ce_init(struct ol_softc *scn, } if (malloc_CE_state) { /* allocated CE_state locally */ - cdf_spin_lock(&scn->target_lock); scn->ce_id_to_state[CE_id] = NULL; - cdf_spin_unlock(&scn->target_lock); cdf_mem_free(CE_state); malloc_CE_state = false; } -- cgit v1.2.3 From 8ed92e578c0ea566b66d1aae89d9aaa22d262ce5 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 2 Sep 2015 14:49:48 -0700 Subject: qcacld-3.0: Remove spinlocks from ce_enable_msi ce_enable_msi should happen before interupts are enabled. Therefore we should be single threaded here and don't need to protect access with a spin lock. Change-Id: I24feec02003bdb402201d71d1cd5254dacae0b72 CRs-Fixed: 941355 --- core/hif/src/ce/ce_service.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 3ed402bc572f..14753d2993dc 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1610,6 +1610,17 @@ bool ce_check_rx_pending(struct ol_softc *scn, int ce_id) else return false; } + +/** + * ce_enable_msi(): write the msi configuration to the target + * @scn: hif context + * @CE_id: which copy engine will be configured for msi interupts + * @msi_addr_lo: Hardware will write to this address to generate an interrupt + * @msi_addr_hi: Hardware will write to this address to generate an interrupt + * @msi_data: Hardware will write this data to generate an interrupt + * + * should be done in the initialization sequence so no locking would be needed + */ void ce_enable_msi(struct ol_softc *scn, unsigned int CE_id, uint32_t msi_addr_lo, uint32_t msi_addr_hi, uint32_t msi_data) @@ -1620,11 +1631,9 @@ void ce_enable_msi(struct ol_softc *scn, unsigned int CE_id, u_int32_t ctrl_addr; uint32_t tmp; - adf_os_spin_lock(&scn->target_lock); CE_state = scn->ce_id_to_state[CE_id]; if (!CE_state) { HIF_ERROR("%s: error - CE_state = NULL", __func__); - adf_os_spin_unlock(&scn->target_lock); return; } targid = TARGID(sc); @@ -1635,7 +1644,6 @@ void ce_enable_msi(struct ol_softc *scn, unsigned int CE_id, tmp = CE_CTRL_REGISTER1_GET(scn, ctrl_addr); tmp |= (1 << CE_MSI_ENABLE_BIT); CE_CTRL_REGISTER1_SET(scn, ctrl_addr, tmp); - adf_os_spin_unlock(&scn->target_lock); #endif } -- cgit v1.2.3 From 9c12f7fe03407da0f184ff6097ed286ff6546613 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 16:52:14 -0700 Subject: qcacld-3.0: Remove hif_completion_thread Remove hif_completion_thread serialization mechanism. Allow for parralel processing of copy engine transactions. Change-Id: I8ecd325314542c2950294fd769a7f127d319df8f CRs-Fixed: 941358 --- core/hif/src/ce/ce_api.h | 1 - core/hif/src/ce/ce_main.c | 284 ++-------------------------------------------- core/hif/src/ce/ce_main.h | 35 +----- 3 files changed, 13 insertions(+), 307 deletions(-) diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h index 2b8565982d02..61038e61b27a 100644 --- a/core/hif/src/ce/ce_api.h +++ b/core/hif/src/ce/ce_api.h @@ -462,7 +462,6 @@ static inline void ce_pkt_error_count_incr( += 1; } -int hif_completion_thread(struct HIF_CE_state *hif_state); bool ce_check_rx_pending(struct ol_softc *scn, int ce_id); #if defined(FEATURE_LRO) void ce_lro_flush_cb_register(struct ol_softc *scn, diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 40e462ac0994..79504ec0fb3c 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -784,109 +784,38 @@ hif_post_init(struct ol_softc *scn, void *unused, } -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; - cdf_mem_free(tmp_list); - } -} - -static int hif_alloc_complete_state_list( - struct HIF_CE_pipe_info *pipe_info, - int completions_needed) -{ - 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 *) - cdf_mem_malloc(len); - if (!tmp_list) { - HIF_ERROR("%s: compl_state has no mem", __func__); - hif_pci_free_complete_state(pipe_info); - return -1; - } - cdf_mem_zero(tmp_list, len); - 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; - } - } - cdf_spinlock_init(&pipe_info->completion_freeq_lock); - return 0; -} int hif_completion_thread_startup(struct HIF_CE_state *hif_state) { struct CE_handle *ce_diag = hif_state->ce_diag; int pipe_num; struct ol_softc *scn = hif_state->scn; + struct hif_msg_callbacks *hif_msg_callbacks = + &hif_state->msg_callbacks_current; /* daemonize("hif_compl_thread"); */ - cdf_spinlock_init(&hif_state->completion_pendingq_lock); - hif_state->completion_pendingq_head = - hif_state->completion_pendingq_tail = NULL; - if (scn->ce_count == 0) { HIF_ERROR("%s: Invalid ce_count\n", __func__); return -EINVAL; } + + if (!hif_msg_callbacks || + !hif_msg_callbacks->rxCompletionHandler || + !hif_msg_callbacks->txCompletionHandler) { + HIF_ERROR("%s: no completion handler registered", __func__); + return -EFAULT; + } + A_TARGET_ACCESS_LIKELY(scn); for (pipe_num = 0; pipe_num < scn->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 */ HIF_INFO_MED("%s: pipe_num:%d pipe_info:0x%p", @@ -894,7 +823,6 @@ int hif_completion_thread_startup(struct HIF_CE_state *hif_state) 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) { @@ -902,190 +830,12 @@ int hif_completion_thread_startup(struct HIF_CE_state *hif_state) 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) { - int ret; - - ret = hif_alloc_complete_state_list(pipe_info, - completions_needed); - if (ret != 0) { - HIF_ERROR("%s: ce_id = %d, no mem", - __func__, pipe_info->pipe_num); - return ret; - } } } A_TARGET_ACCESS_UNLIKELY(scn); 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 ol_softc *scn = hif_state->scn; - 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) { - cdf_nbuf_t netbuf; - - netbuf = (cdf_nbuf_t) compl_state->transfer_context; - cdf_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 < scn->ce_count; pipe_num++) { - pipe_info = &hif_state->pipe_info[pipe_num]; - hif_pci_free_complete_state(pipe_info); - cdf_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) -{ - struct hif_msg_callbacks *msg_callbacks = - &hif_state->msg_callbacks_current; - struct HIF_CE_completion_state *compl_state; - - /* 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 (!cdf_atomic_dec_and_test(&hif_state->hif_thread_idle)) { - /* We were not the lucky one */ - cdf_atomic_inc(&hif_state->hif_thread_idle); - return 0; - } - - 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, - CDF_STATUS_E_FAILURE); - } - - if (hif_state->scn->target_status == OL_TRGET_STATUS_RESET) - return 0; - - for (;; ) { - struct HIF_CE_pipe_info *pipe_info; - int send_done = 0; - - cdf_spin_lock(&hif_state->completion_pendingq_lock); - - if (!hif_state->completion_pendingq_head) { - /* We are atomically sure that - * there is no pending work */ - cdf_atomic_inc(&hif_state->hif_thread_idle); - cdf_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; - cdf_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, - compl_state->toeplitz_hash_result); - send_done = 1; - } else { - /* compl_state->send_or_recv == HIF_CE_COMPLETE_RECV */ - cdf_nbuf_t netbuf; - unsigned int nbytes; - - atomic_inc(&pipe_info->recv_bufs_needed); - hif_post_recv_buffers(hif_state->scn); - - netbuf = (cdf_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 - */ - HIF_DBG("%s: netbuf=%p, nbytes=%d", - __func__, netbuf, nbytes); - if (nbytes <= pipe_info->buf_sz) { - cdf_nbuf_set_pktlen(netbuf, nbytes); - msg_callbacks-> - rxCompletionHandler(msg_callbacks->Context, - netbuf, - pipe_info->pipe_num); - } else { - HIF_ERROR( - "%s: Invalid Rx msg buf:%p nbytes:%d", - __func__, netbuf, nbytes); - cdf_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; - cdf_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; - cdf_spin_unlock(&pipe_info->completion_freeq_lock); - } - - return 0; -} - /* * Install pending msg callbacks. * @@ -1300,11 +1050,11 @@ CDF_STATUS hif_start(struct ol_softc *scn) { struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; + hif_msg_callbacks_install(scn); + if (hif_completion_thread_startup(hif_state)) return CDF_STATUS_E_FAILURE; - hif_msg_callbacks_install(scn); - /* Post buffers once to start things off. */ (void)hif_post_recv_buffers(scn); @@ -1449,13 +1199,6 @@ void hif_stop(struct ol_softc *scn) int pipe_num; scn->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, @@ -2134,9 +1877,6 @@ int hif_config_ce(hif_handle_t hif_hdl) cdf_spinlock_init(&hif_state->keep_awake_lock); - cdf_atomic_init(&hif_state->hif_thread_idle); - cdf_atomic_inc(&hif_state->hif_thread_idle); - hif_state->keep_awake_count = 0; hif_state->fake_sleep = false; diff --git a/core/hif/src/ce/ce_main.h b/core/hif/src/ce/ce_main.h index 570fd41fd799..bd3b3ef6cfac 100644 --- a/core/hif/src/ce/ce_main.h +++ b/core/hif/src/ce/ce_main.h @@ -55,33 +55,12 @@ enum ce_id_type { CE_ID_11, CE_ID_MAX }; -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; - cdf_dma_addr_t data; - unsigned int nbytes; - unsigned int transfer_id; - unsigned int flags; - uint32_t toeplitz_hash_result; -}; - -/* 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 { @@ -102,9 +81,7 @@ struct HIF_CE_pipe_info { cdf_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; @@ -139,16 +116,6 @@ struct HIF_CE_state { cdf_softirq_timer_t sleep_timer; bool sleep_timer_init; unsigned long sleep_ticks; - cdf_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; - cdf_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]; -- cgit v1.2.3 From 9c0f80a85b05616a05ad7e8fc6b1bd1fe74080e0 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 18:36:36 -0700 Subject: qcacld-3.0: Check for SSR before sending messages to upper layers FW is asserted, dont service the messages. The hif completion thread used to prevent processing of messages when firmware crashed. Change-Id: I42a5a285056e989d302e766f2922bb7c114634dc CRs-Fixed: 941358 --- core/hif/src/ce/ce_main.c | 10 ++++++++-- core/hif/src/ce/ce_tasklet.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 79504ec0fb3c..9ea21085f7fd 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -685,6 +685,9 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, * when last fragment is complteted. */ if (transfer_context != CE_SENDLIST_ITEM_CTXT) { + if (hif_state->scn->target_status + == OL_TRGET_STATUS_RESET) + return; msg_callbacks->txCompletionHandler( msg_callbacks->Context, @@ -751,8 +754,11 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, atomic_inc(&pipe_info->recv_bufs_needed); hif_post_recv_buffers_for_pipe(pipe_info); - hif_ce_do_recv(msg_callbacks, transfer_context, nbytes, - pipe_info); + if (hif_state->scn->target_status == OL_TRGET_STATUS_RESET) + return; + + hif_ce_do_recv(msg_callbacks, transfer_context, + nbytes, pipe_info); /* Set up force_break flag if num of receices reaches * MAX_NUM_OF_RECEIVES */ diff --git a/core/hif/src/ce/ce_tasklet.h b/core/hif/src/ce/ce_tasklet.h index c4147709c8cb..bcfd75cc3e1c 100644 --- a/core/hif/src/ce/ce_tasklet.h +++ b/core/hif/src/ce/ce_tasklet.h @@ -27,6 +27,7 @@ #ifndef __CE_TASKLET_H__ #define __CE_TASKLET_H__ +#include "ce_main.h" void init_tasklet_workers(void); void ce_tasklet_init(struct HIF_CE_state *hif_ce_state, uint32_t mask); void ce_tasklet_kill(struct HIF_CE_state *hif_ce_state); -- cgit v1.2.3 From a5e74c1180e3950d9e90d2098b264bb4a0238db5 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 2 Sep 2015 18:06:28 -0700 Subject: qcacld-3.0: Remove target_lock from ce_pkt_dl_len_set Download length should be set before messages are recieved, so no race condition should exist. Change-Id: I92de4b3c4077f23032df45ceca6e169616351b8b CRs-Fixed: 941355 --- core/hif/src/ce/ce_service.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 14753d2993dc..99afda9bd98c 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -500,8 +500,11 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, /* get actual packet length */ frag_len = cdf_nbuf_get_frag_len(msdu, 1); - shadow_src_desc->nbytes = frag_len > ce_state->download_len ? - ce_state->download_len : frag_len; + + /* only read download_len once */ + shadow_src_desc->nbytes = ce_state->download_len; + if (shadow_src_desc->nbytes > frag_len) + shadow_src_desc->nbytes = frag_len; /* Data packet is a byte stream, so disable byte swap */ shadow_src_desc->byte_swap = 0; @@ -1569,9 +1572,7 @@ void ce_pkt_dl_len_set(void *hif_sc, u_int32_t pkt_download_len) cdf_assert_always(ce_state); - cdf_spin_lock_bh(&sc->target_lock); ce_state->download_len = pkt_download_len; - cdf_spin_unlock_bh(&sc->target_lock); cdf_print("%s CE %d Pkt download length %d\n", __func__, ce_state->id, ce_state->download_len); -- cgit v1.2.3 From a837c9a3f86f8f30cfc659e265be7ea90d22a0fc Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 12:47:01 -0700 Subject: qcacld-3.0: Remove target_lock from cb regsitration Send and recv callback registration currently occurs durring init and after bmi download is complete. In either case no transactions are in progress and no race condition can exist. Similarly watermark callback registration would happen at the same time if it were used. Change-Id: Ia77bf30fb3bcefa500465cea9ad9927990bb7ced CRs-Fixed: 941355 --- core/hif/src/ce/ce_service.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 99afda9bd98c..710b4149b49d 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1505,6 +1505,20 @@ void ce_enable_any_copy_compl_intr(struct ol_softc *scn) cdf_spin_unlock(&scn->target_lock); } +/** + * ce_send_cb_register(): register completion handler + * @copyeng: CE_state representing the ce we are adding the behavior to + * @fn_ptr: callback that the ce should use when processing tx completions + * @disable_interrupts: if the interupts should be enabled or not. + * + * Caller should guarantee that no transactions are in progress before + * switching the callback function. + * + * Registers the send context before the fn pointer so that if the cb is valid + * the context should be valid. + * + * Beware that currently this function will enable completion interrupts. + */ void ce_send_cb_register(struct CE_handle *copyeng, ce_send_cb fn_ptr, @@ -1516,13 +1530,23 @@ ce_send_cb_register(struct CE_handle *copyeng, pr_err("%s: Error CE state = NULL\n", __func__); return; } - cdf_spin_lock(&CE_state->scn->target_lock); - CE_state->send_cb = fn_ptr; CE_state->send_context = ce_send_context; + CE_state->send_cb = fn_ptr; ce_per_engine_handler_adjust(CE_state, disable_interrupts); - cdf_spin_unlock(&CE_state->scn->target_lock); } +/** + * ce_recv_cb_register(): register completion handler + * @copyeng: CE_state representing the ce we are adding the behavior to + * @fn_ptr: callback that the ce should use when processing rx completions + * @disable_interrupts: if the interupts should be enabled or not. + * + * Registers the send context before the fn pointer so that if the cb is valid + * the context should be valid. + * + * Caller should guarantee that no transactions are in progress before + * switching the callback function. + */ void ce_recv_cb_register(struct CE_handle *copyeng, CE_recv_cb fn_ptr, @@ -1534,27 +1558,31 @@ ce_recv_cb_register(struct CE_handle *copyeng, pr_err("%s: ERROR CE state = NULL\n", __func__); return; } - cdf_spin_lock(&CE_state->scn->target_lock); - CE_state->recv_cb = fn_ptr; CE_state->recv_context = CE_recv_context; + CE_state->recv_cb = fn_ptr; ce_per_engine_handler_adjust(CE_state, disable_interrupts); - cdf_spin_unlock(&CE_state->scn->target_lock); } +/** + * ce_watermark_cb_register(): register completion handler + * @copyeng: CE_state representing the ce we are adding the behavior to + * @fn_ptr: callback that the ce should use when processing watermark events + * + * Caller should guarantee that no watermark events are being processed before + * switching the callback function. + */ 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; - cdf_spin_lock(&CE_state->scn->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; } - cdf_spin_unlock(&CE_state->scn->target_lock); } #ifdef WLAN_FEATURE_FASTPATH -- cgit v1.2.3 From ff2eb0c907a1ce0f87115a92c383d23ef48d1251 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 13:51:30 -0700 Subject: qcacld-3.0: Remove ce_disable_any_copy_compl_intr Remove ce_disable_any_copy_compl_intr and ce_enable_any_copy_compl_intr since they aren't used and give a false sense of thread safety. Modifying copy complete interrupt currently needs to be synchronized with completion handling. Change-Id: Ieb27a8c71363ebd56f16eda9e1037a161a5eeb62 CRs-Fixed: 941355 --- core/hif/src/ce/ce_api.h | 2 -- core/hif/src/ce/ce_service.c | 15 --------------- 2 files changed, 17 deletions(-) diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h index 61038e61b27a..473e383b324b 100644 --- a/core/hif/src/ce/ce_api.h +++ b/core/hif/src/ce/ce_api.h @@ -376,8 +376,6 @@ int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id); void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id); /*===================CE cmpl interrupt Enable/Disable =======================*/ -void ce_disable_any_copy_compl_intr(struct ol_softc *scn); -void ce_enable_any_copy_compl_intr(struct ol_softc *scn); void ce_disable_any_copy_compl_intr_nolock(struct ol_softc *scn); void ce_enable_any_copy_compl_intr_nolock(struct ol_softc *scn); diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 710b4149b49d..1636c14930eb 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1490,21 +1490,6 @@ void ce_enable_any_copy_compl_intr_nolock(struct ol_softc *scn) A_TARGET_ACCESS_END(scn); } -void ce_disable_any_copy_compl_intr(struct ol_softc *scn) -{ - cdf_spin_lock(&scn->target_lock); - ce_disable_any_copy_compl_intr_nolock(scn); - cdf_spin_unlock(&scn->target_lock); -} - -/*Re-enable the copy compl interrupt if it has not been disabled before.*/ -void ce_enable_any_copy_compl_intr(struct ol_softc *scn) -{ - cdf_spin_lock(&scn->target_lock); - ce_enable_any_copy_compl_intr_nolock(scn); - cdf_spin_unlock(&scn->target_lock); -} - /** * ce_send_cb_register(): register completion handler * @copyeng: CE_state representing the ce we are adding the behavior to -- cgit v1.2.3 From 9a831ef180dede7435475a149e0b212290345bec Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 14:42:40 -0700 Subject: qcacld-3.0: Remove target_lock from ce_h2t_tx_ce_cleanup No other thread should modify the copy engine indexes while we are cleaning up the data structures. Change-Id: I324286c3a8eed24ddd94aa868dbaac425cc30dbf CRs-Fixed: 941355 --- core/hif/src/ce/ce_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 9ea21085f7fd..e425fd8f1cc2 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -458,6 +458,11 @@ error_no_dma_mem: * @ce_hdl: Cope engine handle * Using an assert, this function makes sure that, * the TX CE has been processed completely. + * + * This is called while dismantling CE structures. No other thread + * should be using these structures while dismantling is occuring + * therfore no locking is needed. + * * Return: none */ void @@ -471,10 +476,8 @@ ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl) if (sc->fastpath_mode_on && (ce_state->id == CE_HTT_H2T_MSG)) { HIF_INFO("%s %d Fastpath mode ON, Cleaning up HTT Tx CE\n", __func__, __LINE__); - cdf_spin_lock_bh(&sc->target_lock); sw_index = src_ring->sw_index; write_index = src_ring->sw_index; - cdf_spin_unlock_bh(&sc->target_lock); /* At this point Tx CE should be clean */ cdf_assert_always(sw_index == write_index); -- cgit v1.2.3 From 2893aff03f059cce4827f43fda5ddc238a0bb23b Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 15:45:12 -0700 Subject: qcacld-3.0: Remove target_lock from watermarks_set functions If watermarks are going to be used, the should be set as part of a single threaded initialization sequence. Change-Id: I3e1e9cd0f55f46d9f46718c139963931311fe8ae CRs-Fixed: 941355 --- core/hif/src/ce/ce_service.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 1636c14930eb..d5d3dc3bf08f 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -607,10 +607,8 @@ ce_send_watermarks_set(struct CE_handle *copyeng, uint32_t ctrl_addr = CE_state->ctrl_addr; struct ol_softc *scn = CE_state->scn; - cdf_spin_lock(&scn->target_lock); CE_SRC_RING_LOWMARK_SET(scn, ctrl_addr, low_alert_nentries); CE_SRC_RING_HIGHMARK_SET(scn, ctrl_addr, high_alert_nentries); - cdf_spin_unlock(&scn->target_lock); } void @@ -622,12 +620,10 @@ ce_recv_watermarks_set(struct CE_handle *copyeng, uint32_t ctrl_addr = CE_state->ctrl_addr; struct ol_softc *scn = CE_state->scn; - cdf_spin_lock(&scn->target_lock); CE_DEST_RING_LOWMARK_SET(scn, ctrl_addr, low_alert_nentries); CE_DEST_RING_HIGHMARK_SET(scn, ctrl_addr, high_alert_nentries); - cdf_spin_unlock(&scn->target_lock); } unsigned int ce_send_entries_avail(struct CE_handle *copyeng) -- cgit v1.2.3 From 19671a707b3c981b82bcb422a805c84ba1c0ff5b Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 17:12:50 -0700 Subject: qcacld-3.0: Remove target_lock from hif_crash_shutdown This is called by the platform driver in case of kernel panic. Replacement syncronization might be needed here if the kernel panic doesn't stop the other host cpus before the platform driver calls this. Change-Id: Ic6d4eb1cb08f6363029463994ec7e3837212e271 CRs-Fixed: 941355 --- core/hif/src/hif_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index ea96078ab331..8e573adb9fd0 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -788,8 +788,6 @@ void hif_crash_shutdown(void *hif_ctx) return; } - cdf_spin_lock_irqsave(&scn->target_lock); - hif_crash_shutdown_dump_ce_register(hif_ctx); if (ol_copy_ramdump(scn)) @@ -798,7 +796,6 @@ void hif_crash_shutdown(void *hif_ctx) HIF_INFO_MED("%s: RAM dump collecting completed!", __func__); out: - cdf_spin_unlock_irqrestore(&scn->target_lock); return; } #else -- cgit v1.2.3 From 44b7e4abb00f7842f125506c22ebc35f5686fb49 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Sep 2015 17:01:22 -0700 Subject: qcacld-3.0: Replace target_lock with ce_index_lock Target_lock was a global lock for all target and copy engine data structure access. Replacing target_lock with a per copy engine lock permits paralel completion handling for different copy engines. Change-Id: I9c09d557c85f9e48beafe5e3f936e105183ddd3f CRs-Fixed: 941355 --- core/hif/inc/hif.h | 1 - core/hif/src/ce/ce_internal.h | 2 + core/hif/src/ce/ce_main.c | 1 + core/hif/src/ce/ce_service.c | 92 +++++++++++++++++++++---------------------- core/hif/src/hif_main.c | 1 - 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 948f389b1be4..c96f29179e0d 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -290,7 +290,6 @@ struct ol_softc { * Guard changes to Target HW state and to software * structures that track hardware state. */ - cdf_spinlock_t target_lock; unsigned int ce_count; /* Number of Copy Engines supported */ struct CE_state *ce_id_to_state[CE_COUNT_MAX]; /* CE id to CE_state */ #ifdef FEATURE_NAPI diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index 8d1e9d503413..fb600808909c 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -129,6 +129,8 @@ struct CE_state { struct CE_ring_state *src_ring; struct CE_ring_state *dest_ring; atomic_t rx_pending; + + cdf_spinlock_t ce_index_lock; bool force_break; /* Flag to indicate whether to * break out the DPC context */ diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index e425fd8f1cc2..bc90ab91c8b5 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -141,6 +141,7 @@ struct CE_handle *ce_init(struct ol_softc *scn, malloc_CE_state = true; cdf_mem_zero(CE_state, sizeof(*CE_state)); scn->ce_id_to_state[CE_id] = CE_state; + cdf_spinlock_init(&CE_state->ce_index_lock); CE_state->id = CE_id; CE_state->ctrl_addr = ctrl_addr; diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index d5d3dc3bf08f..cd6b40f782fe 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -261,10 +261,10 @@ ce_send(struct CE_handle *copyeng, struct CE_state *CE_state = (struct CE_state *)copyeng; int status; - cdf_spin_lock_bh(&CE_state->scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); status = ce_send_nolock(copyeng, per_transfer_context, buffer, nbytes, transfer_id, flags, user_flag); - cdf_spin_unlock_bh(&CE_state->scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return status; } @@ -322,7 +322,7 @@ ce_sendlist_send(struct CE_handle *copyeng, CDF_ASSERT((num_items > 0) && (num_items < src_ring->nentries)); - cdf_spin_lock_bh(&CE_state->scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); sw_index = src_ring->sw_index; write_index = src_ring->write_index; @@ -367,7 +367,7 @@ ce_sendlist_send(struct CE_handle *copyeng, * the entire request at once, punt it back to the caller. */ } - cdf_spin_unlock_bh(&CE_state->scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return status; } @@ -427,12 +427,7 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, uint64_t dma_addr; uint32_t user_flags = 0; - /* - * This lock could be more fine-grained, one per CE, - * TODO : Add this lock now. - * That is the next step of optimization. - */ - cdf_spin_lock_bh(&scn->target_lock); + cdf_spin_lock_bh(&ce_state->ce_index_lock); sw_index = src_ring->sw_index; write_index = src_ring->write_index; @@ -524,7 +519,7 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index); } - cdf_spin_unlock_bh(&scn->target_lock); + cdf_spin_unlock_bh(&ce_state->ce_index_lock); /* * If all packets in the array are transmitted, @@ -551,13 +546,13 @@ ce_recv_buf_enqueue(struct CE_handle *copyeng, uint64_t dma_addr = buffer; struct ol_softc *scn = CE_state->scn; - cdf_spin_lock_bh(&scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); write_index = dest_ring->write_index; sw_index = dest_ring->sw_index; A_TARGET_ACCESS_BEGIN_RET_EXT(scn, val); if (val == -1) { - cdf_spin_unlock_bh(&scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return val; } @@ -589,11 +584,11 @@ ce_recv_buf_enqueue(struct CE_handle *copyeng, } A_TARGET_ACCESS_END_RET_EXT(scn, val); if (val == -1) { - cdf_spin_unlock_bh(&scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return val; } - cdf_spin_unlock_bh(&scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return status; } @@ -634,10 +629,10 @@ unsigned int ce_send_entries_avail(struct CE_handle *copyeng) unsigned int sw_index; unsigned int write_index; - cdf_spin_lock(&CE_state->scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); sw_index = src_ring->sw_index; write_index = src_ring->write_index; - cdf_spin_unlock(&CE_state->scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); } @@ -650,10 +645,10 @@ unsigned int ce_recv_entries_avail(struct CE_handle *copyeng) unsigned int sw_index; unsigned int write_index; - cdf_spin_lock(&CE_state->scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); sw_index = dest_ring->sw_index; write_index = dest_ring->write_index; - cdf_spin_unlock(&CE_state->scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); } @@ -683,9 +678,9 @@ unsigned int ce_send_entries_done(struct CE_handle *copyeng) struct CE_state *CE_state = (struct CE_state *)copyeng; unsigned int nentries; - cdf_spin_lock(&CE_state->scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); nentries = ce_send_entries_done_nolock(CE_state->scn, CE_state); - cdf_spin_unlock(&CE_state->scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return nentries; } @@ -715,9 +710,9 @@ unsigned int ce_recv_entries_done(struct CE_handle *copyeng) struct CE_state *CE_state = (struct CE_state *)copyeng; unsigned int nentries; - cdf_spin_lock(&CE_state->scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); nentries = ce_recv_entries_done_nolock(CE_state->scn, CE_state); - cdf_spin_unlock(&CE_state->scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return nentries; } @@ -807,12 +802,12 @@ ce_completed_recv_next(struct CE_handle *copyeng, struct CE_state *CE_state = (struct CE_state *)copyeng; int status; - cdf_spin_lock_bh(&CE_state->scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); status = ce_completed_recv_next_nolock(CE_state, per_CE_contextp, per_transfer_contextp, bufferp, nbytesp, transfer_idp, flagsp); - cdf_spin_unlock_bh(&CE_state->scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return status; } @@ -838,7 +833,7 @@ ce_revoke_recv_next(struct CE_handle *copyeng, } scn = CE_state->scn; - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); nentries_mask = dest_ring->nentries_mask; sw_index = dest_ring->sw_index; write_index = dest_ring->write_index; @@ -870,7 +865,7 @@ ce_revoke_recv_next(struct CE_handle *copyeng, } else { status = CDF_STATUS_E_FAILURE; } - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return status; } @@ -984,7 +979,7 @@ ce_cancel_send_next(struct CE_handle *copyeng, } scn = CE_state->scn; - cdf_spin_lock(&CE_state->scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; write_index = src_ring->write_index; @@ -1023,7 +1018,7 @@ ce_cancel_send_next(struct CE_handle *copyeng, } else { status = CDF_STATUS_E_FAILURE; } - cdf_spin_unlock(&CE_state->scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); return status; } @@ -1045,13 +1040,13 @@ ce_completed_send_next(struct CE_handle *copyeng, struct CE_state *CE_state = (struct CE_state *)copyeng; int status; - cdf_spin_lock_bh(&CE_state->scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); status = ce_completed_send_next_nolock(CE_state, per_CE_contextp, per_transfer_contextp, bufferp, nbytesp, transfer_idp, sw_idx, hw_idx, toeplitz_hash_result); - cdf_spin_unlock_bh(&CE_state->scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); return status; } @@ -1092,7 +1087,7 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) * addressed by change spin_lock to spin_lock_bh also. */ - cdf_spin_lock_bh(&scn->target_lock); + cdf_spin_lock_bh(&CE_state->ce_index_lock); if (CE_state->send_cb) { { @@ -1106,14 +1101,16 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { if (CE_id != CE_HTT_H2T_MSG) { - cdf_spin_unlock_bh(&scn->target_lock); - CE_state-> - send_cb((struct CE_handle *) + cdf_spin_unlock_bh( + &CE_state->ce_index_lock); + CE_state->send_cb( + (struct CE_handle *) CE_state, CE_context, transfer_context, buf, nbytes, id, sw_idx, hw_idx, toeplitz_hash_result); - cdf_spin_lock_bh(&scn->target_lock); + cdf_spin_lock_bh( + &CE_state->ce_index_lock); } else { struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *) @@ -1129,7 +1126,7 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) } } - cdf_spin_unlock_bh(&scn->target_lock); + cdf_spin_unlock_bh(&CE_state->ce_index_lock); A_TARGET_ACCESS_END(scn); } @@ -1175,7 +1172,7 @@ int ce_per_engine_service(struct ol_softc *scn, unsigned int CE_id) return 0; /* no work done */ } - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); /* Clear force_break flag and re-initialize receive_count to 0 */ @@ -1192,7 +1189,7 @@ more_completions: (CE_state, &CE_context, &transfer_context, &buf, &nbytes, &id, &flags) == CDF_STATUS_SUCCESS) { - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); CE_state->recv_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, flags); @@ -1223,7 +1220,7 @@ more_completions: CE_state->receive_count); return CE_state->receive_count; } - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); } } @@ -1247,12 +1244,12 @@ more_completions: if (CE_id != CE_HTT_H2T_MSG || WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); CE_state->send_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, sw_idx, hw_idx, toeplitz_hash_result); - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); } else { struct HIF_CE_pipe_info *pipe_info = (struct HIF_CE_pipe_info *)CE_context; @@ -1270,12 +1267,12 @@ more_completions: &transfer_context, &buf, &nbytes, &id, &sw_idx, &hw_idx, &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); CE_state->send_cb((struct CE_handle *)CE_state, CE_context, transfer_context, buf, nbytes, id, sw_idx, hw_idx, toeplitz_hash_result); - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); } #endif /*ATH_11AC_TXCOMPACT */ } @@ -1285,8 +1282,7 @@ more_watermarks: CE_int_status = CE_ENGINE_INT_STATUS_GET(scn, ctrl_addr); if (CE_int_status & CE_WATERMARK_MASK) { if (CE_state->watermark_cb) { - - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); /* Convert HW IS bits to software flags */ flags = (CE_int_status & CE_WATERMARK_MASK) >> @@ -1295,7 +1291,7 @@ more_watermarks: CE_state-> watermark_cb((struct CE_handle *)CE_state, CE_state->wm_context, flags); - cdf_spin_lock(&scn->target_lock); + cdf_spin_lock(&CE_state->ce_index_lock); } } } @@ -1355,7 +1351,7 @@ more_watermarks: } } - cdf_spin_unlock(&scn->target_lock); + cdf_spin_unlock(&CE_state->ce_index_lock); cdf_atomic_set(&CE_state->rx_pending, 0); if (Q_TARGET_ACCESS_END(scn) < 0) diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 8e573adb9fd0..100805f9100b 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -535,7 +535,6 @@ CDF_STATUS hif_open(void) cdf_atomic_init(&scn->link_suspended); cdf_atomic_init(&scn->tasklet_from_intr); init_waitqueue_head(&scn->aps_osdev.event_queue); - cdf_spinlock_init(&scn->target_lock); scn->linkstate_vote = 0; return status; } -- cgit v1.2.3 From e9afdc129898097a77f1dcba1ab42e04501b968e Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 18 Nov 2015 19:41:52 -0800 Subject: qcacld-3.0: Remove from_irq From irq variable is not serving a good purpose. Change-Id: I362e4fa8c5202e748fac455fb76ce676bd1ea31b CRs-Fixed: 941355 --- core/hif/src/ce/ce_main.h | 1 - core/hif/src/ce/ce_tasklet.c | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/core/hif/src/ce/ce_main.h b/core/hif/src/ce/ce_main.h index bd3b3ef6cfac..1e82e58d045f 100644 --- a/core/hif/src/ce/ce_main.h +++ b/core/hif/src/ce/ce_main.h @@ -102,7 +102,6 @@ struct ce_tasklet_entry { enum ce_id_type ce_id; bool inited; void *hif_ce_state; - bool from_irq; }; struct HIF_CE_state { diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c index 06501d5e42f6..2ca61ca34a2e 100644 --- a/core/hif/src/ce/ce_tasklet.c +++ b/core/hif/src/ce/ce_tasklet.c @@ -203,9 +203,6 @@ static void ce_tasklet(unsigned long data) struct ol_softc *scn = hif_ce_state->scn; struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id]; - if (tasklet_entry->from_irq) - tasklet_entry->from_irq = false; - if (cdf_atomic_read(&scn->link_suspended)) { HIF_ERROR("%s: ce %d tasklet fired after link suspend.", __func__, tasklet_entry->ce_id); @@ -306,10 +303,9 @@ static irqreturn_t ce_irq_handler(int irq, void *context) cdf_atomic_inc(&scn->active_tasklet_cnt); if (hif_napi_enabled(scn, ce_id)) hif_napi_schedule(scn, ce_id); - else { - tasklet_entry->from_irq = true; + else tasklet_schedule(&tasklet_entry->intr_tq); - } + return IRQ_HANDLED; } -- cgit v1.2.3 From bad3922b755b391d19d7f3880f1d3ff37d168ed3 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Tue, 17 Nov 2015 21:33:53 -0800 Subject: qcacld-3.0: Fix Static Analysis Issues 1) Check for bssid if it is NULL, before dereferencing it. 2) Check for hal_ctx if it is NULL, before dereferencing it. CRs-Fixed: 940721 Change-Id: I836416a4717b15902e8b8f27fa2e5e5e7935c12f --- core/sme/src/csr/csr_api_scan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 37e197600c83..d79e148f481a 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1415,7 +1415,7 @@ static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi, * preferred score */ cdf_mem_zero(&fav_bssid.bytes, CDF_MAC_ADDR_SIZE); - if (roam_params->num_bssid_favored) { + if (bssid && roam_params->num_bssid_favored) { for (i = 0; i < roam_params->num_bssid_favored; i++) { cdf_mem_copy(fav_bssid.bytes, &roam_params->bssid_favored[i], @@ -7110,6 +7110,11 @@ void csr_scan_active_list_timeout_handle(void *userData) FL("Scan Timeout: Scan command is NULL")); return; } + if (hal_ctx == NULL) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("HAL Context is NULL")); + return; + } mac_ctx = PMAC_STRUCT(hal_ctx); scan_id = scan_cmd->u.scanCmd.scanID; sms_log(mac_ctx, LOGE, -- cgit v1.2.3 From 8784091b26d6ccacdc1c53fa498b707470049ff0 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Sat, 21 Nov 2015 22:03:40 -0800 Subject: qcacld-3.0: Create configuration item gfirst_scan_bucket_threshold qcacld-2.0 to qcacld-3.0 propagation Create a configuration item to program the first bucket threshold of the scan results to have the flexibility to adjust the first bucket threshold. CRs-Fixed: 922979 Change-Id: I6fad27a2990f7555173e4735131e8392d0277009 --- core/hdd/inc/wlan_hdd_cfg.h | 14 ++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 14 +++++++++++++- core/mac/inc/ani_global.h | 1 + core/sme/inc/csr_api.h | 1 + core/sme/inc/sme_api.h | 1 + core/sme/src/csr/csr_api_roam.c | 13 ++++++++++--- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 9fc774217036..d90e46a77737 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2758,6 +2758,19 @@ enum dot11p_mode { #define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX (-40) #define CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_DEFAULT (-45) +/* + * 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 "gFirstScanBucketThreshold" +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MIN (-50) +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX (-30) +#define CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT (-30) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3335,6 +3348,7 @@ struct hdd_config { bool early_stop_scan_enable; int8_t early_stop_scan_min_threshold; int8_t early_stop_scan_max_threshold; + int8_t first_scan_bucket_threshold; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index d3fd27f3f279..434c45916432 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3603,6 +3603,14 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MIN, CFG_EARLY_STOP_SCAN_MAX_THRESHOLD_MAX), + REG_VARIABLE(CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME, + WLAN_PARAM_SignedInteger, + struct hdd_config, 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), + }; @@ -5146,7 +5154,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hddLog(LOGE, "Name = [%s] Value = [%d]", CFG_EARLY_STOP_SCAN_MAX_THRESHOLD, pHddCtx->config->early_stop_scan_max_threshold); - + hddLog(LOGE, "Name = [%s] Value = [%d]", + CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME, + pHddCtx->config->first_scan_bucket_threshold); } @@ -6589,6 +6599,8 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) pHddCtx->config->early_stop_scan_min_threshold; smeConfig->early_stop_scan_max_threshold = pHddCtx->config->early_stop_scan_max_threshold; + smeConfig->csrConfig.first_scan_bucket_threshold = + pHddCtx->config->first_scan_bucket_threshold; status = sme_update_config(pHddCtx->hHal, smeConfig); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(LOGE, "sme_update_config() return failure %d", diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 1c98232e7e81..d89063e831b6 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1043,6 +1043,7 @@ typedef struct sAniSirGlobal { uint32_t dual_mac_feature_disable; bool first_scan_done; + int8_t first_scan_bucket_threshold; } tAniSirGlobal; typedef enum { diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 88dead78f1ce..a4194e8c96ef 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1274,6 +1274,7 @@ typedef struct tagCsrConfigParam { bool early_stop_scan_enable; int8_t early_stop_scan_min_threshold; int8_t early_stop_scan_max_threshold; + int8_t first_scan_bucket_threshold; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9fb0305989ab..39ae9660884f 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -134,6 +134,7 @@ typedef struct _smeConfigParams { bool early_stop_scan_enable; int8_t early_stop_scan_min_threshold; int8_t early_stop_scan_max_threshold; + int8_t first_scan_bucket_threshold; } tSmeConfigParams, *tpSmeConfigParams; #ifdef FEATURE_WLAN_TDLS diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a0f40ae07185..72711d2cc877 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1189,6 +1189,8 @@ void csr_assign_rssi_for_category(tpAniSirGlobal pMac, int8_t bestApRssi, uint8_t catOffset) { int i; + sms_log(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++) { @@ -1238,7 +1240,7 @@ static void init_config_param(tpAniSirGlobal pMac) pMac->roam.configParam.BssPreferValue[i] = i; } csr_assign_rssi_for_category(pMac, CSR_BEST_RSSI_VALUE, - CSR_DEFAULT_RSSI_DB_GAP); + CSR_DEFAULT_RSSI_DB_GAP); pMac->roam.configParam.nRoamingTime = CSR_DEFAULT_ROAMING_TIME; pMac->roam.configParam.fSupplicantCountryCodeHasPriority = false; pMac->roam.configParam.nActiveMaxChnTime = CSR_ACTIVE_MAX_CHANNEL_TIME; @@ -1821,8 +1823,11 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->scanAgeTimeCPS; } - csr_assign_rssi_for_category(pMac, CSR_BEST_RSSI_VALUE, - pParam->bCatRssiOffset); + pMac->first_scan_bucket_threshold = + pParam->first_scan_bucket_threshold; + csr_assign_rssi_for_category(pMac, + pMac->first_scan_bucket_threshold, + pParam->bCatRssiOffset); pMac->roam.configParam.nRoamingTime = pParam->nRoamingTime; pMac->roam.configParam.fSupplicantCountryCodeHasPriority = pParam->fSupplicantCountryCodeHasPriority; @@ -2158,6 +2163,8 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->sendDeauthBeforeCon = cfg_params->sendDeauthBeforeCon; pParam->max_scan_count = pMac->scan.max_scan_count; + pParam->first_scan_bucket_threshold = + pMac->first_scan_bucket_threshold; return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From 754d036bb5b3c4d6b89f5151864ae4c026d0681c Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Mon, 19 Oct 2015 18:05:15 +0530 Subject: qcacld-3.0: Cleanup checks in the driver exit path Propagation from qcacld-2.0 to qcacld-3.0 Added sanity checks for below variable before accessing in the driver exit path. nl_srv_sock pdev_txrx_ctx Change-Id: I793db21e1a6d1eded027ecbd2805494ea7610852 CRs-Fixed: 846457 --- core/utils/nlink/src/wlan_nlink_srv.c | 13 +++++++------ core/wma/src/wma_data.c | 13 ++++++++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c index 8ed084b8784b..8cd8c45a39c2 100644 --- a/core/utils/nlink/src/wlan_nlink_srv.c +++ b/core/utils/nlink/src/wlan_nlink_srv.c @@ -149,7 +149,7 @@ 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 err; + int err = 0; #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) NETLINK_CB(skb).pid = 0; /* sender's pid */ @@ -158,7 +158,8 @@ int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag) #endif NETLINK_CB(skb).dst_group = 0; /* not multicast */ - err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag); + if (nl_srv_sock) + err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag); if (err < 0) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, @@ -174,7 +175,7 @@ int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag) */ int nl_srv_bcast(struct sk_buff *skb) { - int err; + int err = 0; int flags = GFP_KERNEL; if (in_interrupt() || irqs_disabled() || in_atomic()) @@ -187,9 +188,9 @@ int nl_srv_bcast(struct sk_buff *skb) #endif NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */ - err = - netlink_broadcast(nl_srv_sock, skb, 0, WLAN_NLINK_MCAST_GRP_ID, - flags); + if (nl_srv_sock) + err = netlink_broadcast(nl_srv_sock, skb, 0, + WLAN_NLINK_MCAST_GRP_ID, flags); if (err < 0) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_WARN, diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 2c373c0308e9..286df551ed02 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -1668,11 +1668,14 @@ CDF_STATUS wma_tx_detach(tp_wma_handle wma_handle) ol_txrx_pdev_handle txrx_pdev = (ol_txrx_pdev_handle) (cds_handle->pdev_txrx_ctx); - /* Deregister with TxRx for Tx Mgmt completion call back */ - for (frame_index = 0; frame_index < FRAME_INDEX_MAX; frame_index++) - ol_txrx_mgmt_tx_cb_set(txrx_pdev, frame_index, NULL, NULL, - txrx_pdev); - + if (txrx_pdev) { + /* Deregister with TxRx for Tx Mgmt completion call back */ + for (frame_index = 0; frame_index < FRAME_INDEX_MAX; + frame_index++) { + ol_txrx_mgmt_tx_cb_set(txrx_pdev, frame_index, NULL, + NULL, txrx_pdev); + } + } /* Destroy Tx Frame Complete event */ cdf_event_destroy(&wma_handle->tx_frm_download_comp_event); -- cgit v1.2.3 From 68505a10fd94d7d675ce4e511904bc2b32d5749b Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 30 Nov 2015 18:06:54 +0530 Subject: qcacld-3.0: Fix Static analysis error. qcacld-2.0 to qcacld-3.0 propagation Fix Static analysis errors as below: 1) Memory leak in limHandleDelBssInReAssocContext Change-Id: I9dc0c630d62c06fb55e953f9506b04dbeff9bd51 CRs-Fixed: 919502 --- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index c7c4f5aa1f75..366b79e36f6e 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -3759,6 +3759,7 @@ lim_handle_del_bss_in_re_assoc_context(tpAniSirGlobal pMac, tpDphHashNode pStaDs mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; + cdf_mem_free(beacon_struct); goto error; } /* -- cgit v1.2.3 From 8938591f3e43ee643a32306773036d393548c8f8 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 1 Dec 2015 15:25:20 +0530 Subject: qcacld-3.0: Lower the log level of mtrace to Info to avoid WD bark qcacld-2.0 to qcacld-3.0 propagation. Too many log prints are seen if mtrace are dumped and this cause WD bark. To avoid this lower the log level of mtrace to Info. Change-Id: I05d3fa8b3494785a1933f159280b6c9ba6923c0d CRs-Fixed: 926416 --- core/cdf/src/cdf_trace.c | 2 +- core/hdd/src/wlan_hdd_trace.c | 2 +- core/mac/src/pe/lim/lim_trace.c | 72 ++++++++++++++++++++--------------------- core/sme/src/common/sme_trace.c | 4 +-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/core/cdf/src/cdf_trace.c b/core/cdf/src/cdf_trace.c index 7982d6518d58..f159b124c59d 100644 --- a/core/cdf/src/cdf_trace.c +++ b/core/cdf/src/cdf_trace.c @@ -612,7 +612,7 @@ void cdf_trace_dump_all(void *pMac, uint8_t code, uint8_t session, return; } - CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, "Total Records: %d, Head: %d, Tail: %d", g_cdf_trace_data.num, g_cdf_trace_data.head, g_cdf_trace_data.tail); diff --git a/core/hdd/src/wlan_hdd_trace.c b/core/hdd/src/wlan_hdd_trace.c index ff25fb2bb455..f89bfb04ceb9 100644 --- a/core/hdd/src/wlan_hdd_trace.c +++ b/core/hdd/src/wlan_hdd_trace.c @@ -50,7 +50,7 @@ static void hdd_trace_dump(void *mac, tp_cdf_trace_record record, uint16_t index) { - hddLog(LOGE, "%04d %012llu S%d %-14s %-30s(0x%x) ", + hddLog(LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", index, record->time, record->session, "HDD Event:", hdd_trace_event_string(record->code), record->data); diff --git a/core/mac/src/pe/lim/lim_trace.c b/core/mac/src/pe/lim/lim_trace.c index 3847127120e5..d82e022021c2 100644 --- a/core/mac/src/pe/lim/lim_trace.c +++ b/core/mac/src/pe/lim/lim_trace.c @@ -135,22 +135,22 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, switch (pRecord->code) { case TRACE_CODE_MLM_STATE: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "MLM State:", lim_trace_get_mlm_state_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_SME_STATE: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "SME State:", lim_trace_get_sme_state_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_TX_MGMT: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "TX Mgmt:", frameSubtypeStr[pRecord->data], pRecord->data); break; @@ -158,11 +158,11 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, case TRACE_CODE_RX_MGMT: if (LIM_TRACE_MAX_SUBTYPES <= LIM_TRACE_GET_SUBTYPE(pRecord->data)) { - lim_log(pMac, LOGE, "Wrong Subtype - %d", + lim_log(pMac, LOG1, "Wrong Subtype - %d", LIM_TRACE_GET_SUBTYPE(pRecord->data)); } else { - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(%d) SN: %d ", + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(%d) SN: %d", recIndex, pRecord->time, pRecord->session, "RX Mgmt:", frameSubtypeStr[LIM_TRACE_GET_SUBTYPE @@ -172,7 +172,7 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, } break; case TRACE_CODE_RX_MGMT_DROP: - lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(%d) ", + lim_log(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(%d)", recIndex, pRecord->time, pRecord->session, "Drop RX Mgmt:", __lim_trace_get_mgmt_drop_reason_string((uint16_t) pRecord-> @@ -180,28 +180,28 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, break; case TRACE_CODE_RX_MGMT_TSF: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s0x%x(%d) ", + lim_log(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: - lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %d ", recIndex, + lim_log(pMac, LOG1, "%04d %012llu S%d %-14s %d", recIndex, pRecord->time, pRecord->session, "TX Complete", pRecord->data); break; case TRACE_CODE_TX_SME_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "TX SME Msg:", mac_trace_get_sme_msg_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_RX_SME_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(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:" @@ -211,16 +211,16 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, break; case TRACE_CODE_TX_WMA_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "TX WMA Msg:", mac_trace_get_wma_msg_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_RX_WMA_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(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:" @@ -230,15 +230,15 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, break; case TRACE_CODE_TX_LIM_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "TX LIM Msg:", mac_trace_get_lim_msg_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_RX_LIM_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(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:" @@ -247,15 +247,15 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, pRecord->data); break; case TRACE_CODE_TX_CFG_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX CFG Msg:", mac_trace_get_cfg_msg_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_RX_CFG_MSG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(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:" @@ -267,30 +267,30 @@ void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, break; case TRACE_CODE_TIMER_ACTIVATE: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "Timer Actvtd", __lim_trace_get_timer_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_TIMER_DEACTIVATE: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex, + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "Timer DeActvtd", __lim_trace_get_timer_string((uint16_t) pRecord->data), pRecord->data); break; case TRACE_CODE_INFO_LOG: - lim_log(pMac, LOGE, - "%04d %012llu S%d %-14s %-30s(0x%x) \n", + lim_log(pMac, LOG1, + "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "INFORMATION_LOG", mac_trace_get_info_log_string((uint16_t) pRecord->data), pRecord->data); break; default: - lim_log(pMac, LOGE, "%04d %012llu S%d %-14s(%d) (0x%x) ", + lim_log(pMac, LOG1, "%04d %012llu S%d %-14s(%d) (0x%x)", recIndex, pRecord->time, pRecord->session, "Unknown Code", pRecord->code, pRecord->data); break; diff --git a/core/sme/src/common/sme_trace.c b/core/sme/src/common/sme_trace.c index afedac29ed1f..07562c601e2a 100644 --- a/core/sme/src/common/sme_trace.c +++ b/core/sme/src/common/sme_trace.c @@ -206,12 +206,12 @@ static void sme_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord, uint16_t recIndex) { if (TRACE_CODE_SME_COMMAND == pRecord->code) { - sms_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(0x%x)", + sms_log(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "SME COMMAND:", sme_trace_get_command_string(pRecord->data), pRecord->data); } else { - sms_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(0x%x)", + sms_log(pMac, LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", recIndex, pRecord->time, pRecord->session, "RX HDD MSG:", sme_trace_get_rx_msg_string(pRecord->code), pRecord->data); } -- cgit v1.2.3 From 86669b3bbcb609ca9ba32df10d848dba2e9f0c29 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Wed, 25 Nov 2015 19:28:12 +0530 Subject: qcacld-3.0: Properly update channel width and bonding parameters Currently as part of application triggered channel switch both the channel bandwith and bonding mode are limited to 20MHz. Change made to properly update the channel width and bonding parameters. Change-Id: I48297eed74c9e3bfed6fefa67f664f3503fac1f6 CRs-Fixed: 944647 --- core/sap/src/sap_module.c | 161 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 28 deletions(-) diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 8fe4ccb60d22..f1b02349696a 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1394,6 +1394,133 @@ CDF_STATUS wlansap_deauth_sta(void *pCtx, return cdf_status; } +/** + * wlansap_update_bw80_cbmode() - fucntion to update channel bonding mode for + * VHT80 channel. + * @channel: target channel + * @sme_config: sme configuration context + * + * Return: none + */ +static inline void wlansap_update_bw80_cbmode(uint32_t channel, + tSmeConfigParams *sme_config) +{ + if (channel == 36 || channel == 52 || channel == 100 || + channel == 116 || channel == 149 || channel == 132) { + sme_config->csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW; + } else if (channel == 40 || channel == 56 || channel == 104 || + channel == 120 || channel == 153 || channel == 136) { + sme_config->csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW; + } else if (channel == 44 || channel == 60 || channel == 108 || + channel == 124 || channel == 157 || channel == 140) { + sme_config->csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; + } else if (channel == 48 || channel == 64 || channel == 112 || + channel == 128 || channel == 144 || channel == 161) { + sme_config->csrConfig.channelBondingMode5GHz = + eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; + } +} + +/** + * wlansap_update_csa_channel_params() - fucntion to populate channel width and + * bonding modes. + * @sap_context: sap adapter context + * @channel: target channel + * + * Return: The CDF_STATUS code associated with performing the operation + */ +static CDF_STATUS wlansap_update_csa_channel_params(ptSapContext sap_context, + uint32_t channel) +{ + void *hal; + tpAniSirGlobal mac_ctx; + tSmeConfigParams *sme_config; + uint8_t bw; + + hal = CDS_GET_HAL_CB(sap_context->p_cds_gctx); + if (!hal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hal pointer from p_cds_gctx", __func__); + return CDF_STATUS_E_FAULT; + } + + mac_ctx = PMAC_STRUCT(hal); + + sme_config = cdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + FL("memory allocation failed for sme_config")); + return CDF_STATUS_E_NOMEM; + } + + sme_get_config_param(mac_ctx, sme_config); + if (channel <= RF_CHAN_14) { + /* + * 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. + */ + sme_config->csrConfig.channelBondingMode24GHz = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + mac_ctx->sap.SapDfsInfo.new_cbMode = 0; + mac_ctx->sap.SapDfsInfo.new_chanWidth = 0; + + } else { + + if (sap_context->ch_width_orig >= CH_WIDTH_80MHZ) + bw = BW80; + else if (sap_context->ch_width_orig == CH_WIDTH_40MHZ) + bw = BW40_HIGH_PRIMARY; + else + bw = BW20; + + for (; bw >= BW20; bw--) { + uint16_t op_class; + + op_class = cds_regdm_get_opclass_from_channel( + mac_ctx->scan.countryCodeCurrent, + channel, bw); + if (!op_class) + continue; + + if (bw == BW80) { + wlansap_update_bw80_cbmode(channel, sme_config); + mac_ctx->sap.SapDfsInfo.new_cbMode = + sme_config->csrConfig.channelBondingMode5GHz; + mac_ctx->sap.SapDfsInfo.new_chanWidth = + CH_WIDTH_80MHZ; + } else if (bw == BW40_HIGH_PRIMARY) { + mac_ctx->sap.SapDfsInfo.new_chanWidth = + CH_WIDTH_40MHZ; + sme_config->csrConfig.channelBondingMode5GHz = + mac_ctx->sap.SapDfsInfo.new_cbMode = + eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; + } else if (bw == BW40_LOW_PRIMARY) { + mac_ctx->sap.SapDfsInfo.new_chanWidth = + CH_WIDTH_40MHZ; + sme_config->csrConfig.channelBondingMode5GHz = + mac_ctx->sap.SapDfsInfo.new_cbMode = + eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; + } else { + mac_ctx->sap.SapDfsInfo.new_chanWidth = + CH_WIDTH_20MHZ; + sme_config->csrConfig.channelBondingMode5GHz = + mac_ctx->sap.SapDfsInfo.new_cbMode = + eCSR_INI_SINGLE_CHANNEL_CENTERED; + } + break; + } + + } + + sme_update_config(mac_ctx, sme_config); + cdf_mem_free(sme_config); + return CDF_STATUS_SUCCESS; +} + /*========================================================================== FUNCTION wlansap_set_channel_change_with_csa @@ -1427,7 +1554,7 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) tpAniSirGlobal pMac = NULL; void *hHal = NULL; bool valid; - tSmeConfigParams *sme_config; + CDF_STATUS status; sapContext = CDS_GET_SAP_CB(p_cds_gctx); if (NULL == sapContext) { @@ -1436,6 +1563,7 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) return CDF_STATUS_E_FAULT; } + hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); if (NULL == hHal) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -1473,39 +1601,16 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) * 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_config = - cdf_mem_malloc(sizeof(*sme_config)); - if (!sme_config) { - CDF_TRACE(CDF_MODULE_ID_SAP, - CDF_TRACE_LEVEL_ERROR, - FL("memory allocation failed for sme_config")); - return CDF_STATUS_E_NOMEM; - } - sme_get_config_param(pMac, sme_config); - sme_config->csrConfig.channelBondingMode24GHz = - eCSR_INI_SINGLE_CHANNEL_CENTERED; - sme_update_config(pMac, sme_config); - cdf_mem_free(sme_config); - } + status = wlansap_update_csa_channel_params(sapContext, + targetChannel); + if (status != CDF_STATUS_SUCCESS) + return status; /* * Copy the requested target channel * to sap context. */ pMac->sap.SapDfsInfo.target_channel = targetChannel; - /* - * TODO: need to identify the allowed channel width and - * bonding mode. - */ - pMac->sap.SapDfsInfo.new_chanWidth = 0; - pMac->sap.SapDfsInfo.new_cbMode = 0; - /* * Set the CSA IE required flag. */ -- cgit v1.2.3 From 94a6364efdb72624531fe786ee6186f59f48a55b Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Fri, 20 Nov 2015 10:14:13 +0530 Subject: qcacld-3.0: Honor NL80211_SCAN_FLAG_FLUSH scan flag qcacld-2.0 to qcacld-3.0 propagation Honor NL80211_SCAN_FLAG_FLUSH scan flag by flushing sme and lim scan cache entries. Change-Id: I1ff59e583f815bfec2df458c58a40b30b7bffa00 CRs-Fixed: 934979 --- core/hdd/src/wlan_hdd_scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 1b73597b242f..4e155d0d2121 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1550,7 +1550,10 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, scan_req.requestType, scan_req.scanType, scan_req.minChnTime, scan_req.maxChnTime, scan_req.p2pSearch, scan_req.skipDfsChnlInP2pSearch); - +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0)) + if (request->flags & NL80211_SCAN_FLAG_FLUSH) + sme_scan_flush_result(WLAN_HDD_GET_HAL_CTX(pAdapter)); +#endif status = sme_scan_request(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &scan_req, &hdd_cfg80211_scan_done_callback, dev); -- cgit v1.2.3 From 29b53f710e4cc1c899cf82c5a832dced2338e599 Mon Sep 17 00:00:00 2001 From: "Edhar, Mahesh Kumar" Date: Mon, 16 Nov 2015 12:03:45 +0530 Subject: qcacld-3.0: synchronize PE and HDD initiated disconnects qcacld-2.0 to qcacld-3.0 propagation PE generated disassoc request is not serialized in SME queue. This results in corrupting 'lim.limDisassocDeauthCnfReq.pMlmDisassocReq' which is a global context to save disassoc request. Address the above by indicating all the PE generated disassoc requests to SME and process disconnection request only after receiving eWNI_SME_DISASSOC_CNF from SME(similar to that of processing disassoc request from peer). Change-Id: I2b93925ba64c4d9ff22b071dd2e5c7681be59e15 CRs-Fixed: 934183 --- core/mac/src/pe/lim/lim_assoc_utils.c | 22 ++-- core/mac/src/pe/lim/lim_link_monitoring_algo.c | 121 +++++++-------------- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 29 ++--- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 12 +- 4 files changed, 61 insertions(+), 123 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index e88adf911292..acb078cd5de0 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -742,13 +742,21 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, 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_LINK_MONITORING_DISASSOC) || - (mlmStaContext.cleanupTrigger == eLIM_PROMISCUOUS_MODE_DISASSOC)) { + eLIM_HOST_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_LINK_MONITORING_DISASSOC) || + (mlmStaContext.cleanupTrigger == + eLIM_PROMISCUOUS_MODE_DISASSOC)) { /** * Host or LMM driven Disassociation. * Issue Disassoc Confirm to SME. @@ -768,9 +776,9 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, LIM_MLM_DISASSOC_CNF, (uint32_t *) &mlmDisassocCnf); } else if ((mlmStaContext.cleanupTrigger == - eLIM_HOST_DEAUTH) || - (mlmStaContext.cleanupTrigger == - eLIM_LINK_MONITORING_DEAUTH)) { + eLIM_HOST_DEAUTH) || + (mlmStaContext.cleanupTrigger == + eLIM_LINK_MONITORING_DEAUTH)) { /** * Host or LMM driven Deauthentication. * Issue Deauth Confirm to SME. diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c index 2ce55b062a11..c4626c66c037 100644 --- a/core/mac/src/pe/lim/lim_link_monitoring_algo.c +++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -127,6 +127,9 @@ static void lim_delete_sta_util(tpAniSirGlobal mac_ctx, tpDeleteStaContext msg, cdf_mem_free(msg); return; } else { + lim_send_disassoc_mgmt_frame(mac_ctx, + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON, + stads->staAddr, session_entry, false); lim_trigger_sta_deletion(mac_ctx, stads, session_entry); } } else { @@ -252,101 +255,51 @@ void lim_delete_sta_context(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg) } /** - * lim_trigger_sta_deletion() + * lim_trigger_sta_deletion() - + * This function is called to trigger STA context deletion. * - ***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 + * @param mac_ctx - Pointer to global MAC structure + * @param sta_ds - Pointer to internal STA Datastructure + * @session_entry: PE session entry + * @return None */ void -lim_trigger_sta_deletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs, - tpPESession psessionEntry) +lim_trigger_sta_deletion(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, + tpPESession session_entry) { - tSirSmeDeauthReq *pSmeDeauthReq; - uint8_t *pBuf; - uint8_t *pLen; - uint16_t msgLength = 0; - - if (!pStaDs) { - PELOGW(lim_log - (pMac, LOGW, FL("Skip STA deletion (invalid STA)")); - ) + tLimMlmDisassocInd mlm_disassoc_ind; + + if (!sta_ds) { + lim_log(mac_ctx, LOGW, FL("Skip STA deletion (invalid STA)")); return; } - /** - * MAC based Authentication was used. Trigger - * Deauthentication frame to peer since it will - * take care of disassociation as well. - */ - pSmeDeauthReq = cdf_mem_malloc(sizeof(tSirSmeDeauthReq)); - if (NULL == pSmeDeauthReq) { - lim_log(pMac, LOGP, - FL("AllocateMemory failed for eWNI_SME_DEAUTH_REQ ")); + if ((sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || + (sta_ds->mlmStaContext.mlmState == + eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { + /* Already in the process of deleting context for the peer */ + lim_log(mac_ctx, LOGE, + FL("Deletion is in progress for peer:%pM"), + sta_ds->staAddr); return; } - pBuf = (uint8_t *) &pSmeDeauthReq->messageType; - - /* messageType */ - lim_copy_u16((uint8_t *) pBuf, eWNI_SME_DISASSOC_REQ); - pBuf += sizeof(uint16_t); - msgLength += sizeof(uint16_t); - - /* length */ - pLen = pBuf; - pBuf += sizeof(uint16_t); - msgLength += sizeof(uint16_t); - - /* sessionId */ - *pBuf = psessionEntry->smeSessionId; - pBuf++; - msgLength++; - - /* transactionId */ - lim_copy_u16((uint8_t *) pBuf, psessionEntry->transactionId); - pBuf += sizeof(uint16_t); - msgLength += sizeof(uint16_t); - - /* bssId */ - cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); - pBuf += sizeof(tSirMacAddr); - msgLength += sizeof(tSirMacAddr); - - /* peerMacAddr */ - cdf_mem_copy(pBuf, pStaDs->staAddr, sizeof(tSirMacAddr)); - pBuf += sizeof(tSirMacAddr); - msgLength += sizeof(tSirMacAddr); - - /* reasonCode */ - lim_copy_u16((uint8_t *) pBuf, (uint16_t) eLIM_LINK_MONITORING_DISASSOC); - pBuf += sizeof(uint16_t); - msgLength += sizeof(uint16_t); - - /* Do not send disassoc OTA */ - /* pBuf[0] = 1 means do not send the disassoc frame over the air */ - /* pBuf[0] = 0 means send the disassoc frame over the air */ - pBuf[0] = 0; - pBuf += sizeof(uint8_t); - msgLength += sizeof(uint8_t); - - /* Fill in length */ - lim_copy_u16((uint8_t *) pLen, msgLength); - - lim_post_sme_message(pMac, eWNI_SME_DISASSOC_REQ, - (uint32_t *) pSmeDeauthReq); - cdf_mem_free(pSmeDeauthReq); - + sta_ds->mlmStaContext.disassocReason = + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + sta_ds->mlmStaContext.cleanupTrigger = eLIM_LINK_MONITORING_DISASSOC; + cdf_mem_copy(&mlm_disassoc_ind.peerMacAddr, sta_ds->staAddr, + sizeof(tSirMacAddr)); + mlm_disassoc_ind.reasonCode = + eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; + mlm_disassoc_ind.disassocTrigger = eLIM_LINK_MONITORING_DISASSOC; + + /* Update PE session Id */ + mlm_disassoc_ind.sessionId = session_entry->peSessionId; + lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_IND, + (uint32_t *) &mlm_disassoc_ind); + /* Issue Disassoc Indication to SME */ + lim_send_sme_disassoc_ind(mac_ctx, sta_ds, session_entry); } /*** end lim_trigger_st_adeletion() ***/ /** diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 7cd873d4fbfa..8693bd801f20 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1711,30 +1711,15 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, */ stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + lim_send_disassoc_mgmt_frame(mac_ctx, + mlm_disassocreq->reasonCode, + mlm_disassocreq->peerMacAddr, session, true); /* - * If the reason for disassociation is inactivity of STA, then - * dont wait for acknowledgement + * Abort Tx so that data frames won't be sent to the AP + * after sending Disassoc. */ - if ((mlm_disassocreq->reasonCode == - eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON) && - LIM_IS_AP_ROLE(session)) { - lim_send_disassoc_mgmt_frame(mac_ctx, - mlm_disassocreq->reasonCode, - mlm_disassocreq->peerMacAddr, session, false); - - /* Send Disassoc CNF and receive path cleanup */ - lim_send_disassoc_cnf(mac_ctx); - } else { - lim_send_disassoc_mgmt_frame(mac_ctx, - mlm_disassocreq->reasonCode, - mlm_disassocreq->peerMacAddr, session, true); - /* - * Abort Tx so that data frames won't be sent to the AP - * after sending Disassoc. - */ - if (LIM_IS_STA_ROLE(session)) - wma_tx_abort(session->smeSessionId); - } + if (LIM_IS_STA_ROLE(session)) + wma_tx_abort(session->smeSessionId); } else { /* Disassoc frame is not sent OTA */ send_disassoc_frame = 1; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 6241c06af150..a54ed927ce89 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2591,16 +2591,8 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu goto sendDisassoc; } /* end switch (pMac->lim.gLimSystemRole) */ - if (smeDisassocReq.reasonCode == eLIM_LINK_MONITORING_DISASSOC) { - /* / Disassociation is triggered by Link Monitoring */ - lim_log(pMac, LOG1, - FL("Sending Disasscoc with reason Link Monitoring")); - disassocTrigger = eLIM_LINK_MONITORING_DISASSOC; - reasonCode = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON; - } else { - disassocTrigger = eLIM_HOST_DISASSOC; - reasonCode = smeDisassocReq.reasonCode; - } + disassocTrigger = eLIM_HOST_DISASSOC; + reasonCode = smeDisassocReq.reasonCode; if (smeDisassocReq.doNotSendOverTheAir) { lim_log(pMac, LOG1, FL("do not send dissoc over the air")); -- cgit v1.2.3 From a9185266f076a733dbdbd65aa5191890f5086ea6 Mon Sep 17 00:00:00 2001 From: Ratnam Rachuri Date: Wed, 2 Dec 2015 16:11:02 +0530 Subject: qcacld-3.0: avoid conditional compilation for HEADROOM_SIZE macro qcacld-2.0 to qcacld-3.0 propagation In hdd_alloc_station_adapter, deleted pWlanDev->hard_header_len updating code. Change-Id: I7a3ead434a910dd522f9a02a24cd6ad8669e3fc8 CRs-Fixed: 853305 --- core/hdd/inc/wlan_hdd_main.h | 2 -- core/hdd/src/wlan_hdd_main.c | 1 - 2 files changed, 3 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index c4762ba8eb34..e0a8bc114c3e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -79,8 +79,6 @@ /** Length of the TX queue for the netdev */ #define HDD_NETDEV_TX_QUEUE_LEN (3000) -/** Bytes to reserve in the headroom */ -#define LIBRA_HW_NEEDED_HEADROOM 128 /** Hdd Tx Time out value */ #ifdef LIBRA_LINUX_PC #define HDD_TX_TIMEOUT (8000) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c52b861fa490..f134d8d71928 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1815,7 +1815,6 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, cdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr)); pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT; - pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM; if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload) pWlanDev->features |= -- cgit v1.2.3 From 0809047cdff78070eb8ce4a77bb81c2ff8018cd4 Mon Sep 17 00:00:00 2001 From: "Kanchanapally, Vidyullatha" Date: Fri, 22 May 2015 17:28:57 +0530 Subject: qcacld-3.0: Add new vendor command to get link properties qcacld-2.0 to qcacld-3.0 propagation Add support in driver for a new vendor command to get the link properties nss, rate flags and operating frequency. Change-Id: Ie3b8d5b2c3886055d303441c5d8b2f2a0a2719bd CRs-Fixed: 834199 --- core/hdd/inc/wlan_hdd_assoc.h | 4 + core/hdd/inc/wlan_hdd_main.h | 6 + core/hdd/src/wlan_hdd_assoc.c | 5 + core/hdd/src/wlan_hdd_cfg80211.c | 199 +++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 32 ++++ core/hdd/src/wlan_hdd_hostapd.c | 13 ++ core/mac/inc/sir_api.h | 6 + core/mac/src/include/dph_global.h | 4 +- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 3 + core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 58 ++++-- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 5 +- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 52 ++++++ core/mac/src/pe/lim/lim_utils.h | 1 + core/sap/src/sap_fsm.c | 2 + core/sme/src/csr/csr_api_roam.c | 3 + core/wma/inc/wma_if.h | 2 + core/wma/src/wma_dev_if.c | 6 +- 17 files changed, 386 insertions(+), 15 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index d9012e5e5cda..190e756a7cb8 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -108,6 +108,8 @@ typedef enum { * @proxyARPService: proxy arp service * @ptk_installed: ptk installed state * @gtk_installed: gtk installed state + * @nss: number of spatial streams negotiated + * @rate_flags: rate flags for current connection */ typedef struct connection_info_s { eConnectionState connState; @@ -126,6 +128,8 @@ typedef struct connection_info_s { uint8_t proxyARPService; bool ptk_installed; bool gtk_installed; + uint8_t nss; + uint32_t rate_flags; } connection_info_t; /* Forward declarations */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index e0a8bc114c3e..e069bd21212b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -704,6 +704,12 @@ typedef struct { /** The station entry for which Deauth is in progress */ bool 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 { diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index c534d7e72d95..e65ecd644d11 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -388,6 +388,11 @@ hdd_conn_save_connect_info(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, 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 */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b392482b3900..3ac951bc4291 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4250,6 +4250,197 @@ static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, return ret; } +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() - Get link properties + * @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 get link properties like nss, rate flags and + * operating frequency for the active connection with the given peer. + * + * 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[CDF_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; + + ENTER(); + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, + qca_wlan_vendor_attr_policy)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid attribute")); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("Attribute peerMac not provided for mode=%d"), + adapter->device_mode); + return -EINVAL; + } + + cdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]), + CDF_MAC_ADDR_SIZE); + hddLog(CDF_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) || + !cdf_mem_compare(hdd_sta_ctx->conn_info.bssId.bytes, + peer_mac, CDF_MAC_ADDR_SIZE)) { + hddLog(CDF_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 = cds_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 && + !cdf_is_macaddr_broadcast( + &adapter->aStaInfo[sta_id].macAddrSTA) && + cdf_mem_compare( + &adapter->aStaInfo[sta_id].macAddrSTA.bytes, + peer_mac, CDF_MAC_ADDR_SIZE)) + break; + } + + if (WLAN_MAX_STA_COUNT == sta_id) { + hddLog(CDF_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 = cds_chan_to_freq( + (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel); + rate_flags = adapter->aStaInfo[sta_id].rate_flags; + } else { + hddLog(CDF_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(CDF_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(CDF_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() - Wrapper function to get link + * properties. + * @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 get link properties like nss, rate flags and + * operating frequency for the active connection with the given peer. + * + * 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 = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_link_properties(wiphy, + wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -4663,6 +4854,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { 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_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 + }, }; /* diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 28fc309011fd..df5e5aa91e56 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -245,6 +245,7 @@ typedef enum { * @QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION: set wifi config * @QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION: get wifi config * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: get logging features + * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: get link properties * @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete */ @@ -346,6 +347,9 @@ enum qca_nl80211_vendor_subcmds { 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, + /* DBS subcommands */ QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103, QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104, @@ -604,6 +608,8 @@ enum qca_wlan_vendor_attr_get_tdls_capabilities { * @QCA_WLAN_VENDOR_ATTR_STATS_EXT: Ext stats attribute which is used by * QCA_NL80211_VENDOR_SUBCMD_STATS_EXT * @QCA_WLAN_VENDOR_ATTR_IFINDEX: After IFINDEX + * @QCA_WLAN_VENDOR_ATTR_MAC_ADDR: MAC Address attribute which is used by + * QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES * @QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS: Supported Features * @QCA_WLAN_VENDOR_ATTR_AFTER_LAST: After last * @QCA_WLAN_VENDOR_ATTR_MAX: Max value @@ -614,6 +620,7 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_NAN = 2, QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, + QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7, QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA = 9, QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, @@ -1804,6 +1811,31 @@ enum qca_wlan_vendor_attr_get_logger_features { QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_link_properties - link properties + * + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID: Invalid initial value + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS: Unsigned 8-bit value to + * specify the number of spatial streams negotiated + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS: Unsigned 8-bit value + * to specify negotiated rate flags i.e. ht, vht and channel width + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ: Unsigned 32bit value to + * specify the operating frequency + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAX: max value + */ +enum qca_wlan_vendor_attr_link_properties { + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS = 1, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS = 2, + 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 diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 2afa2c746f89..fadaeddce7f1 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1232,6 +1232,19 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); } + staId = + pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId; + if (CDF_IS_STATUS_SUCCESS(cdf_status)) { + pHostapdAdapter->aStaInfo[staId].nss = + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + chan_info.nss; + pHostapdAdapter->aStaInfo[staId].rate_flags = + pSapEvent->sapevt. + sapStationAssocReassocCompleteEvent. + chan_info.rate_flags; + } + if (hdd_ipa_is_enabled(pHddCtx)) { status = hdd_ipa_wlan_evt(pHostapdAdapter, pSapEvent->sapevt. diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4af72143def8..bae0b4c5f8f5 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1034,6 +1034,9 @@ typedef struct sSirSmeJoinRsp { 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 @@ -1057,7 +1060,10 @@ typedef struct sSirSmeChanInfo { uint32_t info; uint32_t reg_info_1; uint32_t reg_info_2; + uint8_t nss; + uint32_t rate_flags; } tSirSmeChanInfo, *tpSirSmeChanInfo; + /* / Definition for Association indication from peer */ /* / MAC ---> */ typedef struct sSirSmeAssocInd { diff --git a/core/mac/src/include/dph_global.h b/core/mac/src/include/dph_global.h index ae590db66603..abeacf4f521c 100644 --- a/core/mac/src/include/dph_global.h +++ b/core/mac/src/include/dph_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -238,6 +238,8 @@ typedef struct sDphHashNode { /* key installed for this STA or not in the firmware */ uint8_t is_key_installed; uint8_t is_disassoc_deauth_in_progress; + + 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 diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 02b092312dc2..8e23a4e9d21f 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1929,6 +1929,9 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, (session_entry->maxTxPower << 16); assoc_ind->chan_info.reg_info_2 = (session_entry->maxTxPower << 8); + assoc_ind->chan_info.nss = sta_ds->nss; + assoc_ind->chan_info.rate_flags = + lim_get_max_rate_flags(mac_ctx, sta_ds); /* updates VHT information in assoc indication */ lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req, assoc_ind); diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 24caac92cd92..c11cecc56d39 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -61,6 +61,7 @@ extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac, * @mac_ctx: Pointer to Global MAC structure * @sta_ds: Station Descriptor in DPH * @assoc_rsp: Pointer to Association Response Structure + * @session_entry : PE session Entry * * This function is called to Update the HT capabilities in * Station Descriptor (dph) Details from @@ -69,20 +70,27 @@ extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac, * Return: None */ static void lim_update_stads_htcap(tpAniSirGlobal mac_ctx, - tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp) + tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, + tpPESession session_entry) { uint16_t highest_rxrate = 0; tDot11fIEHTCaps *ht_caps; + uint32_t shortgi_20mhz_support; + uint32_t shortgi_40mhz_support; ht_caps = &assoc_rsp->HTCaps; sta_ds->mlmStaContext.htCapability = assoc_rsp->HTCaps.present; if (assoc_rsp->HTCaps.present) { sta_ds->htGreenfield = (uint8_t) ht_caps->greenField; - sta_ds->htSupportedChannelWidthSet = - (uint8_t) (ht_caps->supportedChannelWidthSet ? - assoc_rsp->HTInfo.recommendedTxWidthSet : - ht_caps->supportedChannelWidthSet); + if (session_entry->htSupportedChannelWidthSet) { + sta_ds->htSupportedChannelWidthSet = + (uint8_t) (ht_caps->supportedChannelWidthSet ? + assoc_rsp->HTInfo.recommendedTxWidthSet : + ht_caps->supportedChannelWidthSet); + } else + sta_ds->htSupportedChannelWidthSet = + eHT_CHANNEL_WIDTH_20MHZ; sta_ds->htLsigTXOPProtection = (uint8_t) ht_caps->lsigTXOPProtection; sta_ds->htMIMOPSState = @@ -92,10 +100,6 @@ static void lim_update_stads_htcap(tpAniSirGlobal mac_ctx, sta_ds->htAMpduDensity = ht_caps->mpduDensity; sta_ds->htDsssCckRate40MHzSupport = (uint8_t) ht_caps->dsssCckMode40MHz; - sta_ds->htShortGI20Mhz = - (uint8_t) ht_caps->shortGI20MHz; - sta_ds->htShortGI40Mhz = - (uint8_t) ht_caps->shortGI40MHz; sta_ds->htMaxRxAMpduFactor = ht_caps->maxRxAMPDUFactor; lim_fill_rx_highest_supported_rate(mac_ctx, &highest_rxrate, @@ -115,6 +119,39 @@ static void lim_update_stads_htcap(tpAniSirGlobal mac_ctx, * For now, it is IMMEDIATE BA only on ALL TID's */ sta_ds->baPolicyFlag = 0xFF; + + /* Check if we have support for gShortGI20Mhz and + * gShortGI40Mhz from ini file + */ + if (eSIR_SUCCESS == wlan_cfg_get_int(mac_ctx, + WNI_CFG_SHORT_GI_20MHZ, + &shortgi_20mhz_support)) { + if (true == shortgi_20mhz_support) + sta_ds->htShortGI20Mhz = + (uint8_t)assoc_rsp->HTCaps.shortGI20MHz; + else + sta_ds->htShortGI20Mhz = false; + } else { + lim_log(mac_ctx, LOGE, + FL("could not retrieve shortGI 20Mhz CFG, setting value to default")); + sta_ds->htShortGI20Mhz = + WNI_CFG_SHORT_GI_20MHZ_STADEF; + } + + if (eSIR_SUCCESS == wlan_cfg_get_int(mac_ctx, + WNI_CFG_SHORT_GI_40MHZ, + &shortgi_40mhz_support)) { + if (true == shortgi_40mhz_support) + sta_ds->htShortGI40Mhz = + (uint8_t)assoc_rsp->HTCaps.shortGI40MHz; + else + sta_ds->htShortGI40Mhz = false; + } else { + lim_log(mac_ctx, LOGE, + FL("could not retrieve shortGI 40Mhz CFG,setting value to default")); + sta_ds->htShortGI40Mhz = + WNI_CFG_SHORT_GI_40MHZ_STADEF; + } } } @@ -150,7 +187,8 @@ void lim_update_assoc_sta_datas(tpAniSirGlobal mac_ctx, /* Update HT Capabilites only when the self mode supports HT */ if (IS_DOT11_MODE_HT(session_entry->dot11mode)) - lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp); + lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp, + session_entry); #ifdef WLAN_FEATURE_11AC if (assoc_rsp->VHTCaps.present) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 366b79e36f6e..41282b7fab64 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1762,9 +1762,11 @@ void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx, sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, &session_entry->dph.dphHashTable); - if (NULL != sta_ds) + if (NULL != sta_ds) { sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + sta_ds->nss = add_sta_params->nss; + } else lim_log(mac_ctx, LOGW, FL("Fail to get DPH Hash Entry for AID - %d"), @@ -2258,6 +2260,7 @@ void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, } 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; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 10a7032ce8a3..bde6cba7038f 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -167,6 +167,55 @@ lim_send_sme_roc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, } +/** + * lim_get_max_rate_flags() - Get rate flags + * @mac_ctx: Pointer to global MAC structure + * @sta_ds: Pointer to station ds structure + * + * 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. + * + * Return: Returns the populated rate_flags + */ +uint32_t lim_get_max_rate_flags(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds) +{ + uint32_t rate_flags = 0; + + if (sta_ds == NULL) { + lim_log(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; +} + /** * lim_send_sme_join_reassoc_rsp_after_resume() - Send Response to SME * @mac_ctx Pointer to Global MAC structure @@ -430,6 +479,9 @@ lim_send_sme_join_reassoc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type, sme_join_rsp->tdls_chan_swit_prohibited = session_entry->tdls_chan_swit_prohibited; #endif + sme_join_rsp->nss = sta_ds->nss; + sme_join_rsp->max_rate_flags = + lim_get_max_rate_flags(mac_ctx, sta_ds); } } sme_join_rsp->beaconLength = 0; diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index f551109e1296..cd9d6a1a1bf3 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -444,6 +444,7 @@ uint8_t lim_build_p2p_ie(tpAniSirGlobal pMac, uint8_t *ie, uint8_t *data, bool lim_is_noa_insert_reqd(tpAniSirGlobal pMac); bool lim_isconnected_on_dfs_channel(uint8_t currentChannel); uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac); +uint32_t lim_get_max_rate_flags(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds); #ifdef WLAN_FEATURE_11AC bool lim_check_vht_op_mode_change(tpAniSirGlobal pMac, diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 1ca439e69cda..b14deb41f103 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2665,6 +2665,8 @@ CDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx, csr_roaminfo->chan_info.reg_info_1; chaninfo->reg_info_2 = csr_roaminfo->chan_info.reg_info_2; + chaninfo->nss = csr_roaminfo->chan_info.nss; + chaninfo->rate_flags = csr_roaminfo->chan_info.rate_flags; reassoc_complete->wmmEnabled = csr_roaminfo->wmmEnabledSta; reassoc_complete->status = (eSapStatus) context; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 72711d2cc877..7c627c004063 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6398,6 +6398,9 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, roam_info.ucastSig = (uint8_t) join_rsp->ucastSig; roam_info.bcastSig = (uint8_t) join_rsp->bcastSig; roam_info.timingMeasCap = join_rsp->timingMeasCap; + roam_info.chan_info.nss = join_rsp->nss; + roam_info.chan_info.rate_flags = + join_rsp->max_rate_flags; #ifdef FEATURE_WLAN_TDLS roam_info.tdls_prohibited = join_rsp->tdls_prohibited; roam_info.tdls_chan_swit_prohibited = diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 6ab2a52cb66b..63dd5e3374bc 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -224,6 +224,7 @@ typedef struct sAniProbeRspStruct { * @maxTxPower: max tx power * @atimIePresent: Peer Atim Info * @peerAtimWindowLength: peer ATIM Window length + * @nss: Return the number of spatial streams supported * * This structure contains parameter required for * add sta request of upper layer. @@ -320,6 +321,7 @@ typedef struct { uint8_t atimIePresent; uint32_t peerAtimWindowLength; uint8_t nonRoamReassoc; + uint32_t nss; } tAddStaParams, *tpAddStaParams; /** diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index c1de651644a1..2fa2461ac8ab 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -3502,9 +3502,7 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) uint8_t peer_id; CDF_STATUS status; int32_t ret; -#ifdef WLAN_FEATURE_11W struct wma_txrx_node *iface = NULL; -#endif /* WLAN_FEATURE_11W */ struct wma_target_req *msg; bool peer_assoc_cnf = false; @@ -3535,6 +3533,7 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) 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); @@ -3633,7 +3632,6 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) * per STA for SAP case * We will isolate the ifaces based on vdevid */ - iface = &wma->interfaces[vdev->vdev_id]; iface->rmfEnabled = add_sta->rmfEnabled; /* * when 802.11w PMF is enabled for hw encr/decr @@ -3669,6 +3667,7 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) 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 = CDF_STATUS_SUCCESS; send_rsp: /* Do not send add stat resp when peer assoc cnf is enabled */ @@ -4042,6 +4041,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) wma_set_ppsconfig(params->smesessionId, WMA_VHT_PPS_DELIM_CRC_FAIL, 1); iface->aid = params->assocId; + params->nss = iface->nss; out: /* Do not send add stat resp when peer assoc cnf is enabled */ if (peer_assoc_cnf) -- cgit v1.2.3 From 14f4c4cfd5f95506e8ad0850566c16daa720b177 Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Tue, 17 Nov 2015 15:25:16 +0530 Subject: qcacld-3.0: Resolve invalid memory access while processing GET STATES IOCTL qcacld-2.0 to qcacld-3.0 propagation While processing GET STATES IOCTL, in a while loop, HOST prints PE, LIM and MLM states of each session. Normally while loading, HOST allocates memory for five sessions, but while processing this IOCTL, it iterating in a loop assuming there are 255 sessions allocated, leading to crash because of invalid memory access. Hence while printing PE, LIM and MLM states iterate only for allocated number of sessions. Change-Id: I29c9a627615a1983d23831578f45aefe116dac25 CRs-Fixed: 879950 --- core/sme/src/common/sme_api.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index b0337adde444..6c8ef59444b1 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -9333,6 +9333,10 @@ uint32_t sme_get_lim_mlm_state(tHalHandle hHal) bool sme_is_lim_session_valid(tHalHandle hHal, uint8_t sessionId) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if (sessionId > pMac->lim.maxBssId) + return false; + return pMac->lim.gpSession[sessionId].valid; } -- cgit v1.2.3 From b46e9f94e46d122be7e7686f835b5aa15e248d77 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Fri, 9 Oct 2015 10:15:46 -0700 Subject: qcacld-3.0: Fix the PNO WoW is not configured in concurrency case qcacld-2.0 to qcacld-3.0 propagation In the case of SAP + STA mode we fail to enable PNO on the STA interface, and as a result the PNO feature will fail to find a network and wake the host. Fix this by making sure PNO is configured in all appropriate concurrency cases. Change-Id: I97084cfde73025f0d09b60616959c9530ba82c80 CRs-fixed: 921150 --- core/wma/src/wma_features.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index cff570c39ce4..ffe4771826b7 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3752,9 +3752,10 @@ static bool wma_is_extscan_in_progress(tp_wma_handle wma) CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) { struct wma_txrx_node *iface; - bool connected = false, pno_in_progress = false; + bool pno_in_progress = false; uint8_t i, vdev_id = 0; bool extscan_in_progress = false, pno_matched = false; + bool enable_wow = false; wma->no_of_suspend_ind++; @@ -3816,17 +3817,16 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) WMI_SERVICE_BEACON_OFFLOAD)) { WMA_LOGD("vdev %d is in beaconning mode, enabling wow", i); - goto enable_wow; + enable_wow = true; } } for (i = 0; i < wma->max_bssid; i++) { - if (wma->interfaces[i].conn_state) { - connected = true; - break; - } + 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"); + enable_wow = true; pno_in_progress = true; vdev_id = i; if (wma->interfaces[i].nlo_match_evt_received) @@ -3836,6 +3836,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) #endif /* FEATURE_WLAN_SCAN_PNO */ } extscan_in_progress = wma_is_extscan_in_progress(wma); + if (extscan_in_progress) + enable_wow = true; for (i = 0; i < wma->max_bssid; i++) { wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i]; @@ -3843,13 +3845,12 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable); } - if (!connected && !pno_in_progress && !extscan_in_progress) { + if (!enable_wow) { WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); cdf_mem_free(info); goto send_ready_to_suspend; } -enable_wow: WMA_LOGE("WOW Suspend"); /* -- cgit v1.2.3 From 70c1fb9602a5ba00cd94e0a62f38f7a5882e97c2 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Wed, 2 Dec 2015 16:56:48 -0800 Subject: qcacld-3.0: Fix the issue observed in static code analysis Fix the issue observed in static code analysis. Change-Id: I3ec4abc3b51d3b36350e1f2d592ae59a21d8aa62 CRs-Fixed: 928208 --- core/sme/src/csr/csr_api_scan.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index d79e148f481a..1c3669341d2e 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -3925,10 +3925,6 @@ error: cdf_mem_free(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList); if (save_cmd->u.scanCmd.pToRoamProfile) cdf_mem_free(save_cmd->u.scanCmd.pToRoamProfile); - if (save_cmd) { - cdf_mem_free(save_cmd); - save_cmd = NULL; - } return CDF_STATUS_E_FAILURE; } @@ -4019,11 +4015,11 @@ csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand, } status = csr_save_profile(mac_ctx, save_cmd, pCommand); - if (!CDF_IS_STATUS_SUCCESS(status) || - !save_cmd) { + if (!CDF_IS_STATUS_SUCCESS(status)) { /* csr_save_profile should report error */ sms_log(mac_ctx, LOGE, FL("profile save failed %d"), status); + cdf_mem_free(save_cmd); return; } -- cgit v1.2.3 From 08364cec610c145e0e4a266e9ddb3363b92032cb Mon Sep 17 00:00:00 2001 From: Yun Park Date: Fri, 20 Nov 2015 11:34:27 -0800 Subject: qcacldi-3.0:IPA-uC: Cleanup IPA pending event list when driver unload qcacld-2.0 to qcacld-3.0 propagation IPA pending_event list keeps IPA events arrived while IPA resource loading/unloading. This list is freed only when TX/Rx resume/suspend OP code from FW. This change is to limit the pending event list size and free up the pending event list when WLAN driver is unloaded. Change-Id: Id0489a59bd3c2b04d2faba1069df7b2244a2a730 CRs-Fixed: 937765 --- core/hdd/src/wlan_hdd_ipa.c | 64 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 422a448e9e59..b5bc954bec43 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -83,6 +83,8 @@ #define HDD_IPA_UC_STA_ENABLE_MASK BIT(6) #define HDD_IPA_REAL_TIME_DEBUGGING BIT(8) +#define HDD_IPA_MAX_PENDING_EVENT_COUNT 20 + typedef enum { HDD_IPA_UC_OPCODE_TX_SUSPEND = 0, HDD_IPA_UC_OPCODE_TX_RESUME = 1, @@ -3484,25 +3486,41 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) && ((hdd_ipa->resource_loading) || (hdd_ipa->resource_unloading))) { - struct ipa_uc_pending_event *pending_evet = NULL; + unsigned int pending_event_count; + struct ipa_uc_pending_event *pending_event = NULL; - HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, - "%s, RL/RUL inprogress", __func__); - pending_evet = (struct ipa_uc_pending_event *)cdf_mem_malloc( - sizeof(struct ipa_uc_pending_event)); - if (!pending_evet) { - HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, - "Pending event memory alloc fail"); + hdd_err("IPA resource %s inprogress", + hdd_ipa->resource_loading ? "load":"unload"); + + cdf_mutex_acquire(&hdd_ipa->event_lock); + + cdf_list_size(&hdd_ipa->pending_event, &pending_event_count); + if (pending_event_count >= HDD_IPA_MAX_PENDING_EVENT_COUNT) { + hdd_notice("Reached max pending event count"); + cdf_list_remove_front(&hdd_ipa->pending_event, + (cdf_list_node_t **)&pending_event); + } else { + pending_event = + (struct ipa_uc_pending_event *)cdf_mem_malloc( + sizeof(struct ipa_uc_pending_event)); + } + + if (!pending_event) { + hdd_err("Pending event memory alloc fail"); + cdf_mutex_release(&hdd_ipa->event_lock); return -ENOMEM; } - pending_evet->adapter = adapter; - pending_evet->sta_id = sta_id; - pending_evet->type = type; - cdf_mem_copy(pending_evet->mac_addr, + + pending_event->adapter = adapter; + pending_event->sta_id = sta_id; + pending_event->type = type; + cdf_mem_copy(pending_event->mac_addr, mac_addr, CDF_MAC_ADDR_SIZE); cdf_list_insert_back(&hdd_ipa->pending_event, - &pending_evet->node); + &pending_event->node); + + cdf_mutex_release(&hdd_ipa->event_lock); return 0; } @@ -3911,6 +3929,24 @@ fail_setup_rm: return CDF_STATUS_E_FAILURE; } +/** + * hdd_ipa_cleanup_pending_event() - Cleanup IPA pending event list + * @hdd_ipa: 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 (cdf_list_remove_front(&hdd_ipa->pending_event, + (cdf_list_node_t **)&pending_event) == CDF_STATUS_SUCCESS) { + cdf_mem_free(pending_event); + } + + cdf_list_destroy(&hdd_ipa->pending_event); +} + /** * hdd_ipa_cleanup - IPA cleanup function * @hdd_ctx: HDD global context @@ -3991,7 +4027,7 @@ CDF_STATUS hdd_ipa_cleanup(hdd_context_t *hdd_ctx) ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle); cdf_mutex_destroy(&hdd_ipa->event_lock); cdf_mutex_destroy(&hdd_ipa->ipa_lock); - cdf_list_destroy(&hdd_ipa->pending_event); + hdd_ipa_cleanup_pending_event(hdd_ipa); #ifdef WLAN_OPEN_SOURCE for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) { -- cgit v1.2.3 From 1ca69bd2d920a0b1a6606a43b2d734447061c4cc Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Thu, 3 Dec 2015 15:22:34 -0800 Subject: Release 5.0.0.148 Release 5.0.0.148 Change-Id: Ibc96af71bdcabbd54a325220429b38fa29e72f2e CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 7460f129d854..1005dd0a6c08 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 147 +#define QWLAN_VERSION_BUILD 148 -#define QWLAN_VERSIONSTR "5.0.0.147" +#define QWLAN_VERSIONSTR "5.0.0.148" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From d85f78d03d6216bcf4255c7c3a3d6828eb62e96a Mon Sep 17 00:00:00 2001 From: Leo Chang Date: Fri, 13 Nov 2015 10:55:34 -0800 Subject: qcacld-3.0: wdi2.0 feature enable, dp hif wdi20 enable implementation for hsoffload. Large physical address support and wdi20 interface propagate to IPA. This is part of HIF and DP. Change-Id: If898f03a8a75689c98c70d1e55910f476d8fe329 CRs-fixed: 941041 --- core/dp/htt/htt.c | 76 ++++++++++++++---- core/dp/htt/htt_h2t.c | 42 +++++++--- core/dp/htt/htt_internal.h | 16 ++++ core/dp/htt/htt_rx.c | 23 +++--- core/dp/htt/htt_tx.c | 13 ++- core/dp/htt/htt_types.h | 25 ++++-- core/dp/ol/inc/ol_htt_api.h | 145 ++++++++++++++++++---------------- core/dp/ol/inc/ol_txrx_ctrl_api.h | 161 +++++++++++++++++++++----------------- core/dp/txrx/ol_txrx.c | 91 +++++++++++++++++++-- core/hif/inc/hif.h | 22 ++++-- core/hif/src/ce/ce_api.h | 26 +++--- core/hif/src/ce/ce_main.c | 15 +++- core/hif/src/ce/ce_service.c | 23 ++++-- core/htc/htc.c | 11 ++- core/htc/htc_api.h | 2 +- 15 files changed, 474 insertions(+), 217 deletions(-) diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index be9ece92cfdb..3c4d6fd74774 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -471,8 +471,12 @@ void htt_htc_disable_aspm(void) } #ifdef IPA_OFFLOAD -/* - * Attach resource for micro controller data path +/** + * htt_ipa_uc_attach() - Allocate UC data path resources + * @pdev: handle to the HTT instance + * + * Return: 0 success + * none 0 fail */ int htt_ipa_uc_attach(struct htt_pdev_t *pdev) { @@ -504,6 +508,12 @@ int htt_ipa_uc_attach(struct htt_pdev_t *pdev) return 0; /* success */ } +/** + * htt_ipa_uc_attach() - Remove UC data path resources + * @pdev: handle to the HTT instance + * + * Return: None + */ void htt_ipa_uc_detach(struct htt_pdev_t *pdev) { /* TX IPA micro controller detach */ @@ -513,32 +523,63 @@ void htt_ipa_uc_detach(struct htt_pdev_t *pdev) htt_rx_ipa_uc_detach(pdev); } -/* - * Distribute micro controller resource to control module +/** + * htt_ipa_uc_get_resource() - Get uc resource from htt and lower layer + * @pdev: handle to the HTT instance + * @ce_sr_base_paddr: copy engine source ring base physical address + * @ce_sr_ring_size: copy engine source ring size + * @ce_reg_paddr: copy engine register physical address + * @tx_comp_ring_base_paddr: tx comp ring base physical address + * @tx_comp_ring_size: tx comp ring size + * @tx_num_alloc_buffer: number of allocated tx buffer + * @rx_rdy_ring_base_paddr: rx ready ring base physical address + * @rx_rdy_ring_size: rx ready ring size + * @rx_proc_done_idx_paddr: rx process done index physical address + * @rx_proc_done_idx_vaddr: rx process done index virtual address + * @rx2_rdy_ring_base_paddr: rx done ring base physical address + * @rx2_rdy_ring_size: rx done ring size + * @rx2_proc_done_idx_paddr: rx done index physical address + * @rx2_proc_done_idx_vaddr: rx done index virtual address + * + * Return: 0 success */ int htt_ipa_uc_get_resource(htt_pdev_handle pdev, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr) + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx_paddr, + void **rx2_proc_done_idx_vaddr) { /* Release allocated resource to client */ *tx_comp_ring_base_paddr = - (uint32_t) pdev->ipa_uc_tx_rsc.tx_comp_base.paddr; + pdev->ipa_uc_tx_rsc.tx_comp_base.paddr; *tx_comp_ring_size = (uint32_t) ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev); *tx_num_alloc_buffer = (uint32_t) pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt; *rx_rdy_ring_base_paddr = - (uint32_t) pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr; + pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr; *rx_rdy_ring_size = (uint32_t) pdev->ipa_uc_rx_rsc.rx_ind_ring_size; *rx_proc_done_idx_paddr = - (uint32_t) pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr; + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr; + *rx_proc_done_idx_vaddr = + (void *)pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr; + *rx2_rdy_ring_base_paddr = + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr; + *rx2_rdy_ring_size = (uint32_t) pdev->ipa_uc_rx_rsc.rx2_ind_ring_size; + *rx2_proc_done_idx_paddr = + pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr; + *rx2_proc_done_idx_vaddr = + (void *)pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr; /* Get copy engine, bus resource */ htc_ipa_get_ce_resource(pdev->htc_pdev, @@ -548,13 +589,18 @@ htt_ipa_uc_get_resource(htt_pdev_handle pdev, return 0; } -/* - * Distribute micro controller doorbell register to firmware +/** + * htt_ipa_uc_set_doorbell_paddr() - Propagate IPA doorbell address + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: TX doorbell base physical address + * @ipa_uc_rx_doorbell_paddr: RX doorbell base physical address + * + * Return: 0 success */ int htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, - uint32_t ipa_uc_tx_doorbell_paddr, - uint32_t ipa_uc_rx_doorbell_paddr) + cdf_dma_addr_t ipa_uc_tx_doorbell_paddr, + cdf_dma_addr_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; diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index d5dcc8de835a..ca5f7353cb24 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -641,6 +641,13 @@ htt_h2t_aggr_cfg_msg(struct htt_pdev_t *pdev, } #ifdef IPA_OFFLOAD +/** + * htt_h2t_ipa_uc_rsc_cfg_msg() - Send WDI IPA config message to firmware + * @pdev: handle to the HTT instance + * + * Return: 0 success + * A_NO_MEMORY No memory fail + */ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; @@ -649,7 +656,7 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) pkt = htt_htc_pkt_alloc(pdev); if (!pkt) - return A_NO_MEMORY; + return -A_NO_MEMORY; /* show that this is not a tx frame download * (not required, but helpful) @@ -663,7 +670,7 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) false); if (!msg) { htt_htc_pkt_free(pdev, pkt); - return A_NO_MEMORY; + return -A_NO_MEMORY; } /* set the length of the message */ cdf_nbuf_put_tail(msg, HTT_WDI_IPA_CFG_SZ); @@ -756,7 +763,7 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_LO_SET(*msg_word, - (unsigned int)pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr); + (unsigned int)pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_RING2_RD_IDX_ADDR_HI_SET(*msg_word, @@ -765,15 +772,12 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_LO_SET(*msg_word, - (unsigned int)pdev->ipa_uc_rx_rsc.rx2_rdy_idx_paddr); + (unsigned int)pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_RING2_WR_IDX_ADDR_HI_SET(*msg_word, 0); - cdf_trace_hex_dump(CDF_MODULE_ID_HTT, CDF_TRACE_LEVEL_FATAL, - (void *)cdf_nbuf_data(msg), 40); - SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, cdf_nbuf_data(msg), @@ -788,6 +792,15 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) return A_OK; } +/** + * htt_h2t_ipa_uc_set_active() - Propagate WDI path enable/disable to firmware + * @pdev: handle to the HTT instance + * @uc_active: WDI UC path enable or not + * @is_tx: TX path or RX path + * + * Return: 0 success + * A_NO_MEMORY No memory fail + */ int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, bool uc_active, bool is_tx) { @@ -798,7 +811,7 @@ int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, pkt = htt_htc_pkt_alloc(pdev); if (!pkt) - return A_NO_MEMORY; + return -A_NO_MEMORY; /* show that this is not a tx frame download * (not required, but helpful) @@ -813,7 +826,7 @@ int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, false); if (!msg) { htt_htc_pkt_free(pdev, pkt); - return A_NO_MEMORY; + return -A_NO_MEMORY; } /* set the length of the message */ cdf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); @@ -851,6 +864,13 @@ int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, return A_OK; } +/** + * htt_h2t_ipa_uc_get_stats() - WDI UC state query request to firmware + * @pdev: handle to the HTT instance + * + * Return: 0 success + * A_NO_MEMORY No memory fail + */ int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; @@ -859,7 +879,7 @@ int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) pkt = htt_htc_pkt_alloc(pdev); if (!pkt) - return A_NO_MEMORY; + return -A_NO_MEMORY; /* show that this is not a tx frame download * (not required, but helpful) @@ -874,7 +894,7 @@ int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) false); if (!msg) { htt_htc_pkt_free(pdev, pkt); - return A_NO_MEMORY; + return -A_NO_MEMORY; } /* set the length of the message */ cdf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index 9e9e672af27f..5ab0b1a680b0 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -480,6 +480,15 @@ int htt_tx_ipa_uc_detach(struct htt_pdev_t *pdev); int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev); #else +/** + * htt_tx_ipa_uc_attach() - attach htt ipa uc tx resource + * @pdev: htt context + * @uc_tx_buf_sz: single tx buffer size + * @uc_tx_buf_cnt: total tx buffer count + * @uc_tx_partition_base: tx buffer partition start + * + * Return: 0 success + */ static inline int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, unsigned int uc_tx_buf_sz, @@ -489,6 +498,13 @@ htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, return 0; } +/** + * htt_rx_ipa_uc_attach() - attach htt ipa uc rx resource + * @pdev: htt context + * @rx_ind_ring_size: rx ring size + * + * Return: 0 success + */ static inline int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, unsigned int rx_ind_ring_size) { diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index cabd1633edbf..80a1b8c915d8 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -2288,14 +2288,16 @@ fail1: } #ifdef IPA_OFFLOAD +/** + * htt_rx_ipa_uc_attach() - attach htt ipa uc rx resource + * @pdev: htt context + * @rx_ind_ring_size: rx ring size + * + * Return: 0 success + */ 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 = cdf_os_mem_alloc_consistent( pdev->osdev, @@ -2339,16 +2341,11 @@ int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, } cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr, 4); - /* Allocate RX2 indication ring */ - /* RX2 IND ring element - * 4bytes: pointer - * 2bytes: VDEV ID - * 2bytes: length */ pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr = cdf_os_mem_alloc_consistent( pdev->osdev, rx_ind_ring_elements * - sizeof(struct ipa_uc_rx_ring_elem_t), + sizeof(cdf_dma_addr_t), &pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. rx2_ind_ring_base), @@ -2360,7 +2357,7 @@ int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, /* RX indication ring size, by bytes */ pdev->ipa_uc_rx_rsc.rx2_ind_ring_size = - rx_ind_ring_elements * sizeof(struct ipa_uc_rx_ring_elem_t); + rx_ind_ring_elements * sizeof(cdf_dma_addr_t); cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, pdev->ipa_uc_rx_rsc.rx2_ind_ring_size); @@ -2432,7 +2429,7 @@ int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) rx_ipa_prc_done_idx.vaddr, pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx_ipa_prc_done_idx), + rx2_ipa_prc_done_idx), memctx)); } return 0; diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index 3b278036a5c0..57cd62a8c6dc 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -833,6 +833,16 @@ void htt_tx_desc_display(void *tx_desc) #endif #ifdef IPA_OFFLOAD +/** + * htt_tx_ipa_uc_attach() - attach htt ipa uc tx resource + * @pdev: htt context + * @uc_tx_buf_sz: single tx buffer size + * @uc_tx_buf_cnt: total tx buffer count + * @uc_tx_partition_base: tx buffer partition start + * + * Return: 0 success + * ENOBUFS No memory fail + */ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, unsigned int uc_tx_buf_sz, unsigned int uc_tx_buf_cnt, @@ -840,7 +850,7 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, { unsigned int tx_buffer_count; cdf_nbuf_t buffer_vaddr; - uint32_t buffer_paddr; + cdf_dma_addr_t buffer_paddr; uint32_t *header_ptr; uint32_t *ring_vaddr; int return_code = 0; @@ -929,6 +939,7 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, /* chanreq, peerid */ *header_ptr = 0xFFFFFFFF; + header_ptr++; /* FRAG Header */ /* 6 words TSO header */ diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h index 67447506c744..b30f722e7d2d 100644 --- a/core/dp/htt/htt_types.h +++ b/core/dp/htt/htt_types.h @@ -137,8 +137,17 @@ struct htt_ipa_uc_tx_resource_t { uint32_t alloc_tx_buf_cnt; }; -/* Micro controller datapath offload - * WLAN RX resources */ +/** + * struct htt_ipa_uc_rx_resource_t + * @rx_rdy_idx_paddr: rx ready index physical address + * @rx_ind_ring_base: rx indication ring base memory info + * @rx_ipa_prc_done_idx: rx process done index memory info + * @rx_ind_ring_size: rx process done ring size + * @rx2_rdy_idx_paddr: rx process done index physical address + * @rx2_ind_ring_base: rx process done indication ring base memory info + * @rx2_ipa_prc_done_idx: rx process done index memory info + * @rx2_ind_ring_size: rx process done ring size + */ struct htt_ipa_uc_rx_resource_t { cdf_dma_addr_t rx_rdy_idx_paddr; struct uc_shared_mem_t rx_ind_ring_base; @@ -152,10 +161,16 @@ struct htt_ipa_uc_rx_resource_t { uint32_t rx2_ind_ring_size; }; +/** + * struct ipa_uc_rx_ring_elem_t + * @rx_packet_paddr: rx packet physical address + * @vdev_id: virtual interface id + * @rx_packet_leng: packet length + */ struct ipa_uc_rx_ring_elem_t { - uint32_t rx_packet_paddr; - uint16_t vdev_id; - uint16_t rx_packet_leng; + cdf_dma_addr_t rx_packet_paddr; + uint32_t vdev_id; + uint32_t rx_packet_leng; }; #if defined(HELIUMPLUS_PADDR64) diff --git a/core/dp/ol/inc/ol_htt_api.h b/core/dp/ol/inc/ol_htt_api.h index 4e9e58f1a004..d8d2272f4643 100644 --- a/core/dp/ol/inc/ol_htt_api.h +++ b/core/dp/ol/inc/ol_htt_api.h @@ -214,111 +214,98 @@ void htt_display(htt_pdev_handle pdev, int indent); #define htt_rx_reorder_log_print(pdev) #ifdef IPA_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, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr); + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx_paddr, + void **rx2_proc_done_idx_vaddr); -/** - * @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, - uint32_t ipa_uc_tx_doorbell_paddr, - uint32_t ipa_uc_rx_doorbell_paddr); + cdf_dma_addr_t ipa_uc_tx_doorbell_paddr, + cdf_dma_addr_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, bool uc_active, bool 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); +void htt_ipa_uc_detach(struct htt_pdev_t *pdev); +#else /** - * @brief detach IPA UC data path + * htt_h2t_ipa_uc_rsc_cfg_msg() - Send WDI IPA config message to firmware + * @pdev: handle to the HTT instance * - * @param pdev - handle to the HTT instance + * Return: 0 success */ -void htt_ipa_uc_detach(struct htt_pdev_t *pdev); -#else static inline int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) { return 0; } +/** + * htt_ipa_uc_get_resource() - Get uc resource from htt and lower layer + * @pdev: handle to the HTT instance + * @ce_sr_base_paddr: copy engine source ring base physical address + * @ce_sr_ring_size: copy engine source ring size + * @ce_reg_paddr: copy engine register physical address + * @tx_comp_ring_base_paddr: tx comp ring base physical address + * @tx_comp_ring_size: tx comp ring size + * @tx_num_alloc_buffer: number of allocated tx buffer + * @rx_rdy_ring_base_paddr: rx ready ring base physical address + * @rx_rdy_ring_size: rx ready ring size + * @rx_proc_done_idx_paddr: rx process done index physical address + * @rx_proc_done_idx_vaddr: rx process done index virtual address + * @rx2_rdy_ring_base_paddr: rx done ring base physical address + * @rx2_rdy_ring_size: rx done ring size + * @rx2_proc_done_idx_paddr: rx done index physical address + * @rx2_proc_done_idx_vaddr: rx done index virtual address + * + * Return: 0 success + */ static inline int htt_ipa_uc_get_resource(htt_pdev_handle pdev, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr) + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx_paddr, + void **rx2_proc_done_idx_vaddr) { return 0; } +/** + * htt_ipa_uc_set_doorbell_paddr() - Propagate IPA doorbell address + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: TX doorbell base physical address + * @ipa_uc_rx_doorbell_paddr: RX doorbell base physical address + * + * Return: 0 success + */ static inline int htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, uint32_t ipa_uc_tx_doorbell_paddr, @@ -327,6 +314,14 @@ htt_ipa_uc_set_doorbell_paddr(htt_pdev_handle pdev, return 0; } +/** + * htt_h2t_ipa_uc_set_active() - Propagate WDI path enable/disable to firmware + * @pdev: handle to the HTT instance + * @uc_active: WDI UC path enable or not + * @is_tx: TX path or RX path + * + * Return: 0 success + */ static inline int htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, bool uc_active, bool is_tx) @@ -334,16 +329,34 @@ htt_h2t_ipa_uc_set_active(struct htt_pdev_t *pdev, bool uc_active, return 0; } +/** + * htt_h2t_ipa_uc_get_stats() - WDI UC state query request to firmware + * @pdev: handle to the HTT instance + * + * Return: 0 success + */ static inline int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) { return 0; } +/** + * htt_ipa_uc_attach() - Allocate UC data path resources + * @pdev: handle to the HTT instance + * + * Return: 0 success + */ static inline int htt_ipa_uc_attach(struct htt_pdev_t *pdev) { return 0; } +/** + * htt_ipa_uc_attach() - Remove UC data path resources + * @pdev: handle to the HTT instance + * + * Return: 0 success + */ static inline void htt_ipa_uc_detach(struct htt_pdev_t *pdev) { return; diff --git a/core/dp/ol/inc/ol_txrx_ctrl_api.h b/core/dp/ol/inc/ol_txrx_ctrl_api.h index 44d5cf100dd7..4a01d3ec0eb8 100644 --- a/core/dp/ol/inc/ol_txrx_ctrl_api.h +++ b/core/dp/ol/inc/ol_txrx_ctrl_api.h @@ -1090,119 +1090,115 @@ void ol_vdev_rx_set_intrabss_fwd(ol_txrx_vdev_handle vdev, bool val); #ifdef IPA_OFFLOAD -/** - * @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 - */ void ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr); + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx_paddr, + void **rx2_proc_done_idx_vaddr); + -/** - * @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, - uint32_t ipa_tx_uc_doorbell_paddr, - uint32_t ipa_rx_uc_doorbell_paddr); + cdf_dma_addr_t ipa_tx_uc_doorbell_paddr, + cdf_dma_addr_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, bool uc_active, bool 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, uint8_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)(uint8_t *op_msg, void *osif_ctxt), void *osif_dev); +void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev); +#else /** - * @brief query uc data path stats - * @details - * Query uc data path stats from firmware + * ol_txrx_ipa_uc_get_resource() - Client request resource information + * @pdev: handle to the HTT instance + * @ce_sr_base_paddr: copy engine source ring base physical address + * @ce_sr_ring_size: copy engine source ring size + * @ce_reg_paddr: copy engine register physical address + * @tx_comp_ring_base_paddr: tx comp ring base physical address + * @tx_comp_ring_size: tx comp ring size + * @tx_num_alloc_buffer: number of allocated tx buffer + * @rx_rdy_ring_base_paddr: rx ready ring base physical address + * @rx_rdy_ring_size: rx ready ring size + * @rx_proc_done_idx_paddr: rx process done index physical address + * @rx_proc_done_idx_vaddr: rx process done index virtual address + * @rx2_rdy_ring_base_paddr: rx done ring base physical address + * @rx2_rdy_ring_size: rx done ring size + * @rx2_proc_done_idx_paddr: rx done index physical address + * @rx2_proc_done_idx_vaddr: rx done index virtual address * - * @param pdev - handle to the HTT instance + * 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 + * + * Return: none */ -void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev); -#else static inline void ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr) + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx_paddr, + void **rx2_proc_done_idx_vaddr) { return; } +/** + * ol_txrx_ipa_uc_set_doorbell_paddr() - Client set IPA UC doorbell register + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address + * @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address + * + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * Return: none + */ static inline void ol_txrx_ipa_uc_set_doorbell_paddr(ol_txrx_pdev_handle pdev, - uint32_t ipa_tx_uc_doorbell_paddr, - uint32_t ipa_rx_uc_doorbell_paddr) + cdf_dma_addr_t ipa_tx_uc_doorbell_paddr, + cdf_dma_addr_t ipa_rx_uc_doorbell_paddr) { return; } +/** + * ol_txrx_ipa_uc_set_active() - Client notify IPA UC data path active or not + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address + * @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address + * + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * Return: none + */ static inline void ol_txrx_ipa_uc_set_active(ol_txrx_pdev_handle pdev, bool uc_active, bool is_tx) @@ -1210,12 +1206,27 @@ ol_txrx_ipa_uc_set_active(ol_txrx_pdev_handle pdev, return; } +/** + * ol_txrx_ipa_uc_op_response() - Handle OP command response from firmware + * @pdev: handle to the HTT instance + * @op_msg: op response message from firmware + * + * Return: none + */ static inline void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) { return; } +/** + * ol_txrx_ipa_uc_register_op_cb() - Register OP handler function + * @pdev: handle to the HTT instance + * @op_cb: handler function pointer + * @osif_dev: register client context + * + * Return: none + */ static inline void ol_txrx_ipa_uc_register_op_cb(ol_txrx_pdev_handle pdev, void (*ipa_uc_op_cb_type)(uint8_t *op_msg, @@ -1225,6 +1236,12 @@ ol_txrx_ipa_uc_register_op_cb(ol_txrx_pdev_handle pdev, return; } +/** + * ol_txrx_ipa_uc_get_stat() - Get firmware wdi status + * @pdev: handle to the HTT instance + * + * Return: none + */ static inline void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev) { return; diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index cf249ca11eb6..ae164368f698 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2585,17 +2585,46 @@ inline void ol_txrx_flow_control_cb(ol_txrx_vdev_handle vdev, #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ #ifdef IPA_OFFLOAD +/** + * ol_txrx_ipa_uc_get_resource() - Client request resource information + * @pdev: handle to the HTT instance + * @ce_sr_base_paddr: copy engine source ring base physical address + * @ce_sr_ring_size: copy engine source ring size + * @ce_reg_paddr: copy engine register physical address + * @tx_comp_ring_base_paddr: tx comp ring base physical address + * @tx_comp_ring_size: tx comp ring size + * @tx_num_alloc_buffer: number of allocated tx buffer + * @rx_rdy_ring_base_paddr: rx ready ring base physical address + * @rx_rdy_ring_size: rx ready ring size + * @rx_proc_done_idx_paddr: rx process done index physical address + * @rx_proc_done_idx_vaddr: rx process done index virtual address + * @rx2_rdy_ring_base_paddr: rx done ring base physical address + * @rx2_rdy_ring_size: rx done ring size + * @rx2_proc_done_idx_paddr: rx done index physical address + * @rx2_proc_done_idx_vaddr: rx done index virtual address + * + * 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 + * + * Return: none + */ void ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr, - uint32_t *tx_comp_ring_base_paddr, + cdf_dma_addr_t *tx_comp_ring_base_paddr, uint32_t *tx_comp_ring_size, uint32_t *tx_num_alloc_buffer, - uint32_t *rx_rdy_ring_base_paddr, + cdf_dma_addr_t *rx_rdy_ring_base_paddr, uint32_t *rx_rdy_ring_size, - uint32_t *rx_proc_done_idx_paddr) + cdf_dma_addr_t *rx_proc_done_idx_paddr, + void **rx_proc_done_idx_vaddr, + cdf_dma_addr_t *rx2_rdy_ring_base_paddr, + uint32_t *rx2_rdy_ring_size, + cdf_dma_addr_t *rx2_proc_done_idx2_paddr, + void **rx2_proc_done_idx2_vaddr) { htt_ipa_uc_get_resource(pdev->htt_pdev, ce_sr_base_paddr, @@ -2605,19 +2634,45 @@ ol_txrx_ipa_uc_get_resource(ol_txrx_pdev_handle pdev, tx_comp_ring_size, tx_num_alloc_buffer, rx_rdy_ring_base_paddr, - rx_rdy_ring_size, rx_proc_done_idx_paddr); + rx_rdy_ring_size, rx_proc_done_idx_paddr, + rx_proc_done_idx_vaddr, + rx2_rdy_ring_base_paddr, + rx2_rdy_ring_size, rx2_proc_done_idx2_paddr, + rx2_proc_done_idx2_vaddr); } +/** + * ol_txrx_ipa_uc_set_doorbell_paddr() - Client set IPA UC doorbell register + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address + * @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address + * + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * Return: none + */ void ol_txrx_ipa_uc_set_doorbell_paddr(ol_txrx_pdev_handle pdev, - uint32_t ipa_tx_uc_doorbell_paddr, - uint32_t ipa_rx_uc_doorbell_paddr) + cdf_dma_addr_t ipa_tx_uc_doorbell_paddr, + cdf_dma_addr_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); } +/** + * ol_txrx_ipa_uc_set_active() - Client notify IPA UC data path active or not + * @pdev: handle to the HTT instance + * @ipa_uc_tx_doorbell_paddr: tx comp doorbell physical address + * @ipa_uc_rx_doorbell_paddr: rx ready doorbell physical address + * + * IPA UC let know doorbell register physical address + * WLAN firmware will use this physical address to notify IPA UC + * + * Return: none + */ void ol_txrx_ipa_uc_set_active(ol_txrx_pdev_handle pdev, bool uc_active, bool is_tx) { @@ -2651,7 +2706,13 @@ void ol_txrx_ipa_uc_fw_op_event_handler(void *context, "%s: ipa_uc_op_cb NULL", __func__); } - +/** + * ol_txrx_ipa_uc_op_response() - Handle OP command response from firmware + * @pdev: handle to the HTT instance + * @op_msg: op response message from firmware + * + * Return: none + */ void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) { p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); @@ -2674,6 +2735,14 @@ void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) cds_indicate_rxpkt(sched_ctx, pkt); } +/** + * ol_txrx_ipa_uc_register_op_cb() - Register OP handler function + * @pdev: handle to the HTT instance + * @op_cb: handler function pointer + * @osif_dev: register client context + * + * Return: none + */ void ol_txrx_ipa_uc_register_op_cb(ol_txrx_pdev_handle pdev, ipa_uc_op_cb_type op_cb, void *osif_dev) { @@ -2681,6 +2750,12 @@ void ol_txrx_ipa_uc_register_op_cb(ol_txrx_pdev_handle pdev, pdev->osif_dev = osif_dev; } +/** + * ol_txrx_ipa_uc_get_stat() - Get firmware wdi status + * @pdev: handle to the HTT instance + * + * Return: none + */ void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev) { htt_h2t_ipa_uc_get_stats(pdev->htt_pdev); diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index c96f29179e0d..cc7a66fd7fad 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -535,18 +535,26 @@ void hif_enable_fastpath(struct ol_softc *hif_dev); #endif #ifdef IPA_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 hif_ipa_get_ce_resource(struct ol_softc *scn, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr); #else +/** + * hif_ipa_get_ce_resource() - get uc resource on hif + * @scn: bus context + * @ce_sr_base_paddr: copyengine source ring base physical address + * @ce_sr_ring_size: copyengine source ring size + * @ce_reg_paddr: copyengine register physical address + * + * 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 + * + * Return: None + */ static inline void hif_ipa_get_ce_resource(struct ol_softc *scn, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h index 473e383b324b..ddd82e357b11 100644 --- a/core/hif/src/ce/ce_api.h +++ b/core/hif/src/ce/ce_api.h @@ -430,20 +430,28 @@ struct ce_sendlist { #define ATH_ISR_NOTMINE 0x0002 /* for shared IRQ's */ #ifdef IPA_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_ipa_get_resource(struct CE_handle *ce, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr); #else +/** + * ce_ipa_get_resource() - get uc resource on copyengine + * @ce: copyengine context + * @ce_sr_base_paddr: copyengine source ring base physical address + * @ce_sr_ring_size: copyengine source ring size + * @ce_reg_paddr: copyengine register physical address + * + * 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 + * + * Return: None + */ static inline void ce_ipa_get_resource(struct CE_handle *ce, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index bc90ab91c8b5..6e6f8b0b8212 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -2025,8 +2025,21 @@ err: #ifdef IPA_OFFLOAD +/** + * hif_ipa_get_ce_resource() - get uc resource on hif + * @scn: bus context + * @ce_sr_base_paddr: copyengine source ring base physical address + * @ce_sr_ring_size: copyengine source ring size + * @ce_reg_paddr: copyengine register physical address + * + * 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 + * + * Return: None + */ void hif_ipa_get_ce_resource(struct ol_softc *scn, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index cd6b40f782fe..9da63611d36a 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1654,15 +1654,23 @@ void ce_enable_msi(struct ol_softc *scn, unsigned int CE_id, } #ifdef IPA_OFFLOAD -/* +/** + * ce_ipa_get_resource() - get uc resource on copyengine + * @ce: copyengine context + * @ce_sr_base_paddr: copyengine source ring base physical address + * @ce_sr_ring_size: copyengine source ring size + * @ce_reg_paddr: copyengine register physical address + * * 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 + * - Copy engine source descriptor base address + * - Copy engine source descriptor size + * - PCI BAR address to access copy engine regiser + * + * Return: None */ void ce_ipa_get_resource(struct CE_handle *ce, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { @@ -1690,8 +1698,9 @@ void ce_ipa_get_resource(struct CE_handle *ce, /* Get BAR address */ hif_read_phy_mem_base(CE_state->scn, &phy_mem_base); - *ce_sr_base_paddr = (uint32_t) CE_state->src_ring->base_addr_CE_space; - *ce_sr_ring_size = (uint32_t) CE_state->src_ring->nentries; + *ce_sr_base_paddr = CE_state->src_ring->base_addr_CE_space; + *ce_sr_ring_size = (uint32_t) (CE_state->src_ring->nentries * + sizeof(struct CE_src_desc)); *ce_reg_paddr = phy_mem_base + CE_BASE_ADDRESS(CE_state->id) + SR_WR_INDEX_ADDRESS; return; diff --git a/core/htc/htc.c b/core/htc/htc.c index 967c7c24d028..a22244f0f21a 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -801,8 +801,17 @@ void htc_cancel_deferred_target_sleep(void *context) } #ifdef IPA_OFFLOAD +/** + * htc_ipa_get_ce_resource() - get uc resource on lower layer + * @htc_handle: htc context + * @ce_sr_base_paddr: copyengine source ring base physical address + * @ce_sr_ring_size: copyengine source ring size + * @ce_reg_paddr: copyengine register physical address + * + * Return: None + */ void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr) { diff --git a/core/htc/htc_api.h b/core/htc/htc_api.h index 937d326ba7f6..75c83d7d8414 100644 --- a/core/htc/htc_api.h +++ b/core/htc/htc_api.h @@ -700,7 +700,7 @@ void htc_disable_aspm(void); #ifdef IPA_OFFLOAD void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, - uint32_t *ce_sr_base_paddr, + cdf_dma_addr_t *ce_sr_base_paddr, uint32_t *ce_sr_ring_size, cdf_dma_addr_t *ce_reg_paddr); #else -- cgit v1.2.3 From e8fed533e68b12fa817c9a4f4bf317cc155ef347 Mon Sep 17 00:00:00 2001 From: Leo Chang Date: Fri, 13 Nov 2015 10:59:47 -0800 Subject: qcacld-3.0: wdi2.0 feature enable, hdd cds wdi20 enable implementation for hsoffload. Large physical address support and wdi20 interface propagate to IPA. part of HDD and CDS Change-Id: Iaccab3ae233e0b9a8e4942bee0ebaa40ce94fc16 CRs-fixed: 941041 --- core/cds/src/cds_api.c | 45 -------- core/hdd/inc/wlan_hdd_ipa.h | 23 +++- core/hdd/inc/wlan_hdd_main.h | 20 ---- core/hdd/src/wlan_hdd_ipa.c | 255 +++++++++++++++++++++++++++++++------------ 4 files changed, 209 insertions(+), 134 deletions(-) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 188bd2a04701..1fcdf449d19c 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -67,40 +67,6 @@ /* Maximum number of cds message queue get wrapper failures to cause panic */ #define CDS_WRAPPER_MAX_FAIL_COUNT (CDS_CORE_MAX_MESSAGES * 3) -#ifdef IPA_OFFLOAD -#define CDS_IPA_CE_SR_BASE_PADDR \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_base_paddr) -#define CDS_IPA_CE_RING_SIZE \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_ring_size) -#define CDS_IPA_CE_REG_PADDR \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_reg_paddr) -#define CDS_IPA_TX_COMP_BASE_PADDR \ - (&((hdd_context_t *) \ - (gp_cds_context->pHDDContext))->tx_comp_ring_base_paddr) -#define CDS_IPA_TX_COMP_RING_SIZE \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_comp_ring_size) -#define CDS_IPA_TX_NUM_BUFF \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_num_alloc_buffer) -#define CDS_IPA_RX_RDY_RING_BASE_PADDR \ - (&((hdd_context_t *) \ - (gp_cds_context->pHDDContext))->rx_rdy_ring_base_paddr) -#define CDS_IPA_RX_RDY_RING_SIZE \ - (&((hdd_context_t *)(gp_cds_context->pHDDContext))->rx_rdy_ring_size) -#define CDS_IPA_RX_PROC_DONE_IDX_PADDR \ - (&((hdd_context_t *) \ - (gp_cds_context->pHDDContext))->rx_proc_done_idx_paddr) -#else -#define CDS_IPA_CE_SR_BASE_PADDR (NULL) -#define CDS_IPA_CE_RING_SIZE (NULL) -#define CDS_IPA_CE_REG_PADDR (NULL) -#define CDS_IPA_TX_COMP_BASE_PADDR (NULL) -#define CDS_IPA_TX_COMP_RING_SIZE (NULL) -#define CDS_IPA_TX_NUM_BUFF (NULL) -#define CDS_IPA_RX_RDY_RING_BASE_PADDR (NULL) -#define CDS_IPA_RX_RDY_RING_SIZE (NULL) -#define CDS_IPA_RX_PROC_DONE_IDX_PADDR (NULL) -#endif /* IPA_OFFLOAD */ - /* Data definitions */ static cds_context_type g_cds_context; static p_cds_contextType gp_cds_context; @@ -493,17 +459,6 @@ CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize) goto err_sme_close; } - ol_txrx_ipa_uc_get_resource(gp_cds_context->pdev_txrx_ctx, - CDS_IPA_CE_SR_BASE_PADDR, - CDS_IPA_CE_RING_SIZE, - CDS_IPA_CE_REG_PADDR, - CDS_IPA_TX_COMP_BASE_PADDR, - CDS_IPA_TX_COMP_RING_SIZE, - CDS_IPA_TX_NUM_BUFF, - CDS_IPA_RX_RDY_RING_BASE_PADDR, - CDS_IPA_RX_RDY_RING_SIZE, - CDS_IPA_RX_PROC_DONE_IDX_PADDR); - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS successfully Opened", __func__); diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h index d4189bee05ab..45e29b431a0a 100644 --- a/core/hdd/inc/wlan_hdd_ipa.h +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -59,6 +59,8 @@ int hdd_ipa_send_mcc_scc_msg(hdd_context_t *pHddCtx, bool mcc_mode); int hdd_ipa_uc_ssr_reinit(void); int hdd_ipa_uc_ssr_deinit(void); void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx); +struct sk_buff *hdd_ipa_tx_packet_ipa(hdd_context_t *hdd_ctx, + struct sk_buff *skb, uint8_t session_id); #else static inline CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) { @@ -120,7 +122,7 @@ static inline void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, return; } -static void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx) +static inline void hdd_ipa_uc_rt_debug_host_dump(hdd_context_t *hdd_ctx) { return; } @@ -147,6 +149,23 @@ static inline void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) { return; } -#endif +/** + * hdd_ipa_tx_packet_ipa() - send packet to IPA + * @hdd_ctx: Global HDD context + * @skb: skb sent to IPA + * @session_id: send packet instance session id + * + * Send TX packet which generated by system to IPA. + * This routine only will be used for function verification + * + * Return: NULL packet sent to IPA properly + * skb packet not sent to IPA. legacy data path should handle + */ +static inline struct sk_buff *hdd_ipa_tx_packet_ipa(hdd_context_t *hdd_ctx, + struct sk_buff *skb, uint8_t session_id) +{ + return skb; +} +#endif /* IPA_OFFLOAD */ #endif /* #ifndef HDD_IPA_H__ */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index e069bd21212b..45079ecc7d9b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1191,27 +1191,7 @@ struct hdd_context_s { int32_t tdls_fw_off_chan_mode; #endif -#ifdef IPA_OFFLOAD void *hdd_ipa; - /* CE resources */ - uint32_t ce_sr_base_paddr; - uint32_t ce_sr_ring_size; - cdf_dma_addr_t ce_reg_paddr; - - /* WLAN TX:IPA->WLAN */ - uint32_t tx_comp_ring_base_paddr; - uint32_t tx_comp_ring_size; - uint32_t tx_num_alloc_buffer; - - /* WLAN RX:WLAN->IPA */ - uint32_t rx_rdy_ring_base_paddr; - uint32_t rx_rdy_ring_size; - uint32_t rx_proc_done_idx_paddr; - - /* IPA UC doorbell registers paddr */ - uint32_t tx_comp_doorbell_paddr; - uint32_t rx_ready_doorbell_paddr; -#endif /* IPA_OFFLOAD */ /* MC/BC Filter state variable * This always contains the value that is currently diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index b5bc954bec43..ba20b1f4d07b 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -127,24 +127,49 @@ struct llc_snap_hdr { __be16 eth_type; } __packed; +/** + * struct hdd_ipa_tx_hdr - header type which IPA should handle to TX packet + * @eth: ether II header + * @llc_snap: LLC snap header + * + */ struct hdd_ipa_tx_hdr { struct ethhdr eth; struct llc_snap_hdr llc_snap; } __packed; +/** + * struct frag_header - fragment header type registered to IPA hardware + * @length: fragment length + * @reserved1: Reserved not used + * @reserved2: Reserved not used + * + */ struct frag_header { - uint32_t - length:16, /* length field is LSB of the FRAG DESC */ - reserved16:16; - uint32_t reserved32; + uint16_t length; + uint32_t reserved1; + uint32_t reserved2; } __packed; +/** + * struct ipa_header - ipa header type registered to IPA hardware + * @vdev_id: vdev id + * @reserved: Reserved not used + * + */ struct ipa_header { uint32_t vdev_id:8, /* vdev_id field is LSB of IPA DESC */ reserved:24; } __packed; +/** + * struct hdd_ipa_uc_tx_hdr - full tx header registered to IPA hardware + * @frag_hd: fragment header + * @ipa_hd: ipa header + * @eth: ether II header + * + */ struct hdd_ipa_uc_tx_hdr { struct frag_header frag_hd; struct ipa_header ipa_hd; @@ -416,6 +441,32 @@ struct hdd_ipa_priv { cdf_mc_timer_t rt_debug_fill_timer; cdf_mutex_t rt_debug_lock; cdf_mutex_t ipa_lock; + + /* CE resources */ + cdf_dma_addr_t ce_sr_base_paddr; + uint32_t ce_sr_ring_size; + cdf_dma_addr_t ce_reg_paddr; + + /* WLAN TX:IPA->WLAN */ + cdf_dma_addr_t tx_comp_ring_base_paddr; + uint32_t tx_comp_ring_size; + uint32_t tx_num_alloc_buffer; + + /* WLAN RX:WLAN->IPA */ + cdf_dma_addr_t rx_rdy_ring_base_paddr; + uint32_t rx_rdy_ring_size; + cdf_dma_addr_t rx_proc_done_idx_paddr; + void *rx_proc_done_idx_vaddr; + + /* WLAN RX2:WLAN->IPA */ + cdf_dma_addr_t rx2_rdy_ring_base_paddr; + uint32_t rx2_rdy_ring_size; + cdf_dma_addr_t rx2_proc_done_idx_paddr; + void *rx2_proc_done_idx_vaddr; + + /* IPA UC doorbell registers paddr */ + cdf_dma_addr_t tx_comp_doorbell_paddr; + cdf_dma_addr_t rx_ready_doorbell_paddr; }; #define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr) @@ -425,6 +476,9 @@ struct hdd_ipa_priv { #define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr) #define HDD_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_uc_rx_hdr) +#define HDD_IPA_FW_RX_DESC_DISCARD_M 0x1 +#define HDD_IPA_FW_RX_DESC_FORWARD_M 0x2 + #define HDD_IPA_GET_IFACE_ID(_data) \ (((struct hdd_ipa_cld_hdr *) (_data))->iface_id) @@ -451,6 +505,21 @@ struct hdd_ipa_priv { } while (0) #define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) +/* Temporary macro to make a build without IPA V2 */ +#ifdef IPA_V2 +#define HDD_IPA_WDI2_SET(pipe_in, ipa_ctxt) \ +do { \ + pipe_in.u.ul.rdy_ring_rp_va = ipa_ctxt->rx_proc_done_idx_vaddr; \ + pipe_in.u.ul.rdy_comp_ring_base_pa = ipa_ctxt->rx2_rdy_ring_base_paddr;\ + pipe_in.u.ul.rdy_comp_ring_size = ipa_ctxt->rx2_rdy_ring_size; \ + pipe_in.u.ul.rdy_comp_ring_wp_pa = ipa_ctxt->rx2_proc_done_idx_paddr; \ + pipe_in.u.ul.rdy_comp_ring_wp_va = ipa_ctxt->rx2_proc_done_idx_vaddr; \ +} while (0) +#else +/* Do nothing */ +#define HDD_IPA_WDI2_SET(pipe_in, ipa_ctxt) +#endif /* IPA_V2 */ + static struct hdd_ipa_adapter_2_client { enum ipa_client_type cons_client; enum ipa_client_type prod_client; @@ -467,6 +536,7 @@ static struct hdd_ipa_adapter_2_client { /* For Tx pipes, use Ethernet-II Header format */ struct hdd_ipa_uc_tx_hdr ipa_uc_tx_hdr = { { + 0x0000, 0x00000000, 0x00000000 }, @@ -1337,35 +1407,35 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) /* STATs from host */ CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST CE ====\n" - "CE RING BASE: 0x%x\n" + "CE RING BASE: 0x%llx\n" "CE RING SIZE: %d\n" "CE REG ADDR : 0x%llx", - hdd_ctx->ce_sr_base_paddr, - hdd_ctx->ce_sr_ring_size, - (uint64_t) hdd_ctx->ce_reg_paddr); + hdd_ipa->ce_sr_base_paddr, + hdd_ipa->ce_sr_ring_size, + hdd_ipa->ce_reg_paddr); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST TX ====\n" - "COMP RING BASE: 0x%x\n" + "COMP RING BASE: 0x%llx\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); + "COMP RING DBELL : 0x%llx", + hdd_ipa->tx_comp_ring_base_paddr, + hdd_ipa->tx_comp_ring_size, + hdd_ipa->tx_num_alloc_buffer, + hdd_ipa->tx_comp_doorbell_paddr); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST RX ====\n" - "IND RING BASE: 0x%x\n" + "IND RING BASE: 0x%llx\n" "IND RING SIZE: %d\n" - "IND RING DBELL : 0x%x\n" - "PROC DONE IND ADDR : 0x%x\n" + "IND RING DBELL : 0x%llx\n" + "PROC DONE IND ADDR : 0x%llx\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->rx_rdy_ring_base_paddr, + hdd_ipa->rx_rdy_ring_size, + hdd_ipa->rx_ready_doorbell_paddr, + hdd_ipa->rx_proc_done_idx_paddr, hdd_ipa->stats.num_rx_excep, hdd_ipa->stats.num_tx_bcmc, hdd_ipa->stats.num_tx_bcmc_err); @@ -1702,17 +1772,18 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) 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; + pipe_in.u.dl.comp_ring_base_pa = ipa_ctxt->tx_comp_ring_base_paddr; + pipe_in.u.dl.comp_ring_size = + ipa_ctxt->tx_comp_ring_size * sizeof(cdf_dma_addr_t); + pipe_in.u.dl.ce_ring_base_pa = ipa_ctxt->ce_sr_base_paddr; + pipe_in.u.dl.ce_door_bell_pa = ipa_ctxt->ce_reg_paddr; + pipe_in.u.dl.ce_ring_size = ipa_ctxt->ce_sr_ring_size; + pipe_in.u.dl.num_tx_buffers = ipa_ctxt->tx_num_alloc_buffer; /* Connect WDI IPA PIPE */ ipa_connect_wdi_pipe(&pipe_in, &pipe_out); /* Micro Controller Doorbell register */ - hdd_ctx->tx_comp_doorbell_paddr = (uint32_t) pipe_out.uc_door_bell_pa; + ipa_ctxt->tx_comp_doorbell_paddr = pipe_out.uc_door_bell_pa; /* WLAN TX PIPE Handle */ ipa_ctxt->tx_pipe_handle = pipe_out.clnt_hdl; HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO_HIGH, @@ -1724,7 +1795,7 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) (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); + (unsigned int)ipa_ctxt->tx_comp_doorbell_paddr); /* RX PIPE */ pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT; @@ -1742,23 +1813,23 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) 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; - + pipe_in.u.ul.rdy_ring_base_pa = ipa_ctxt->rx_rdy_ring_base_paddr; + pipe_in.u.ul.rdy_ring_size = ipa_ctxt->rx_rdy_ring_size; + pipe_in.u.ul.rdy_ring_rp_pa = ipa_ctxt->rx_proc_done_idx_paddr; + HDD_IPA_WDI2_SET(pipe_in, ipa_ctxt); ipa_connect_wdi_pipe(&pipe_in, &pipe_out); - hdd_ctx->rx_ready_doorbell_paddr = pipe_out.uc_door_bell_pa; + ipa_ctxt->rx_ready_doorbell_paddr = pipe_out.uc_door_bell_pa; ipa_ctxt->rx_pipe_handle = pipe_out.clnt_hdl; HDD_IPA_LOG(CDF_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); + (unsigned int)ipa_ctxt->rx_ready_doorbell_paddr); ol_txrx_ipa_uc_set_doorbell_paddr(cds_ctx->pdev_txrx_ctx, - (uint32_t) hdd_ctx->tx_comp_doorbell_paddr, - (uint32_t) hdd_ctx->rx_ready_doorbell_paddr); + ipa_ctxt->tx_comp_doorbell_paddr, + ipa_ctxt->rx_ready_doorbell_paddr); ol_txrx_ipa_uc_register_op_cb(cds_ctx->pdev_txrx_ctx, hdd_ipa_uc_op_event_handler, (void *)hdd_ctx); @@ -1811,14 +1882,13 @@ void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) * * Return: 0 - Success */ -#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_deinit(void) { 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)) + if ((!hdd_ipa) || (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx))) return 0; /* Clean up HDD IPA interfaces */ @@ -1836,25 +1906,18 @@ int hdd_ipa_uc_ssr_deinit(void) if (!hdd_ipa->ipa_pipes_down) hdd_ipa_uc_disable_pipes(hdd_ipa); - cdf_wake_lock_acquire(&hdd_ipa->ipa_lock); + cdf_mutex_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; } - cdf_wake_lock_release(&hdd_ipa->ipa_lock); + cdf_mutex_release(&hdd_ipa->ipa_lock); /* Full IPA driver cleanup not required since wlan driver is now * unloaded and reloaded after SSR. */ return 0; } -#else -int hdd_ipa_uc_ssr_deinit(void) -{ - return 0; -} -#endif - /** * hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR @@ -1864,13 +1927,8 @@ int hdd_ipa_uc_ssr_deinit(void) * * Return: 0 - Success */ -#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_reinit(void) { - 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 @@ -1879,12 +1937,52 @@ int hdd_ipa_uc_ssr_reinit(void) */ return 0; } -#else -int hdd_ipa_uc_ssr_reinit(void) + +/** + * hdd_ipa_tx_packet_ipa() - send packet to IPA + * @hdd_ctx: Global HDD context + * @skb: skb sent to IPA + * @session_id: send packet instance session id + * + * Send TX packet which generated by system to IPA. + * This routine only will be used for function verification + * + * Return: NULL packet sent to IPA properly + * NULL invalid packet drop + * skb packet not sent to IPA. legacy data path should handle + */ +struct sk_buff *hdd_ipa_tx_packet_ipa(hdd_context_t *hdd_ctx, + struct sk_buff *skb, uint8_t session_id) { - return 0; + struct ipa_header *ipa_header; + struct frag_header *frag_header; + + if (!hdd_ipa_uc_is_enabled(hdd_ctx)) + return skb; + + ipa_header = (struct ipa_header *) skb_push(skb, + sizeof(struct ipa_header)); + if (!ipa_header) { + /* No headroom, legacy */ + return skb; + } + memset(ipa_header, 0, sizeof(*ipa_header)); + ipa_header->vdev_id = 0; + + frag_header = (struct frag_header *) skb_push(skb, + sizeof(struct frag_header)); + if (!frag_header) { + /* No headroom, drop */ + kfree_skb(skb); + return NULL; + } + memset(frag_header, 0, sizeof(*frag_header)); + frag_header->length = skb->len - sizeof(struct frag_header) + - sizeof(struct ipa_header); + + ipa_tx_dp(IPA_CLIENT_WLAN1_CONS, skb, NULL); + return NULL; } -#endif /** * hdd_ipa_wake_lock_timer_func() - Wake lock work handler @@ -2386,9 +2484,6 @@ static void hdd_ipa_send_skb_to_network(cdf_nbuf_t skb, adapter->dev->last_rx = jiffies; } -#define FW_RX_DESC_DISCARD_M 0x1 -#define FW_RX_DESC_FORWARD_M 0x2 - /** * hdd_ipa_w2i_cb() - WLAN to IPA callback handler * @priv: pointer to private data registered with IPA (we register a @@ -2467,8 +2562,7 @@ static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, */ fw_desc = (uint8_t)skb->cb[1]; - - if (fw_desc & FW_RX_DESC_FORWARD_M) { + if (fw_desc & HDD_IPA_FW_RX_DESC_FORWARD_M) { HDD_IPA_LOG( CDF_TRACE_LEVEL_DEBUG, "Forward packet to Tx (fw_desc=%d)", @@ -2491,7 +2585,7 @@ static void hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, } } - if (fw_desc & FW_RX_DESC_DISCARD_M) { + if (fw_desc & HDD_IPA_FW_RX_DESC_DISCARD_M) { HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); hdd_ipa->ipa_rx_discard++; cdf_nbuf_free(skb); @@ -3526,6 +3620,7 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, hdd_ipa->stats.event[type]++; + meta.msg_type = type; switch (type) { case WLAN_STA_CONNECT: /* STA already connected and without disconnect, connect again @@ -3860,13 +3955,36 @@ CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) hdd_ipa = cdf_mem_malloc(sizeof(*hdd_ipa)); if (!hdd_ipa) { HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed"); - goto fail_setup_rm; + goto fail_return; } hdd_ctx->hdd_ipa = hdd_ipa; ghdd_ipa = hdd_ipa; hdd_ipa->hdd_ctx = hdd_ctx; hdd_ipa->num_iface = 0; + ol_txrx_ipa_uc_get_resource(cds_get_context(CDF_MODULE_ID_TXRX), + &hdd_ipa->ce_sr_base_paddr, + &hdd_ipa->ce_sr_ring_size, + &hdd_ipa->ce_reg_paddr, + &hdd_ipa->tx_comp_ring_base_paddr, + &hdd_ipa->tx_comp_ring_size, + &hdd_ipa->tx_num_alloc_buffer, + &hdd_ipa->rx_rdy_ring_base_paddr, + &hdd_ipa->rx_rdy_ring_size, + &hdd_ipa->rx_proc_done_idx_paddr, + &hdd_ipa->rx_proc_done_idx_vaddr, + &hdd_ipa->rx2_rdy_ring_base_paddr, + &hdd_ipa->rx2_rdy_ring_size, + &hdd_ipa->rx2_proc_done_idx_paddr, + &hdd_ipa->rx2_proc_done_idx_vaddr); + if ((0 == hdd_ipa->ce_sr_base_paddr) || + (0 == hdd_ipa->tx_comp_ring_base_paddr) || + (0 == hdd_ipa->rx_rdy_ring_base_paddr) || + (0 == hdd_ipa->rx2_rdy_ring_base_paddr)) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_FATAL, + "IPA UC resource alloc fail"); + goto fail_get_resource; + } /* Create the interface context */ for (i = 0; i < HDD_IPA_MAX_IFACE; i++) { @@ -3923,9 +4041,12 @@ CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) fail_create_sys_pipe: hdd_ipa_destroy_rm_resource(hdd_ipa); fail_setup_rm: - if (hdd_ipa) - cdf_mem_free(hdd_ipa); - + cdf_spinlock_destroy(&hdd_ipa->pm_lock); +fail_get_resource: + cdf_mem_free(hdd_ipa); + hdd_ctx->hdd_ipa = NULL; + ghdd_ipa = NULL; +fail_return: return CDF_STATUS_E_FAILURE; } -- cgit v1.2.3 From a765ad7c95a367c287035746aad0e1dfe9e0f54a Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:16:25 +0530 Subject: qcacld-3.0: Update the status code in Re/assoc rsp for failure qcacld-2.0 to qcacld-3.0 propagation If deauth is received just after Assoc rsp from AP in addSTA response Re/assoc confirm is sent with status failure. But protStatusCode in assoc confirm is not updated and thus the pRoamInfo->reasonCode may have garbage value. In case of Wep connection failure reason code, pRoamInfo->reasonCode, is sent to the supplicant in connect result. Now if pRoamInfo->reasonCode is 0 supplicant receives connection success though connection have actually failed. To avoid this update protStatusCode, before sending Re/assoc failure. Also properly derive if connection is WEP from roamProfile before clearing it. CRs-Fixed: 926572 Change-Id: I5ae0832d37746be16696f521bddd5b67307b1ee4 --- core/hdd/src/wlan_hdd_assoc.c | 38 ++++++++++++++-------- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 4 +++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index e65ecd644d11..0c87577ea7fd 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2053,7 +2053,7 @@ defined(FEATURE_WLAN_LFR) hddLog(LOG1, FL("sending connect indication to nl80211:for bssid " MAC_ADDRESS_STR - " reason:%d and Status:%d"), + " result:%d and Status:%d"), MAC_ADDR_ARRAY (pRoamInfo->bssid.bytes), roamResult, roamStatus); @@ -2185,12 +2185,12 @@ defined(FEATURE_WLAN_LFR) WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); if (pRoamInfo) pr_info("wlan: connection failed with " MAC_ADDRESS_STR - " reason:%d and Status:%d\n", + " result:%d and Status:%d\n", MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes), roamResult, roamStatus); else pr_info("wlan: connection failed with " MAC_ADDRESS_STR - " reason:%d and Status:%d\n", + " result:%d and Status:%d\n", MAC_ADDR_ARRAY(pWextState->req_bssId.bytes), roamResult, roamStatus); @@ -2204,19 +2204,18 @@ defined(FEATURE_WLAN_LFR) hddLog(LOGE, FL("send connect failure to nl80211: for bssid " MAC_ADDRESS_STR - " reason:%d and Status:%d "), + " result:%d and Status:%d reasoncode %d"), MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes), - roamResult, roamStatus); + roamResult, roamStatus, + pRoamInfo->reasonCode); else hddLog(LOGE, FL("connect failed: for bssid " MAC_ADDRESS_STR - " reason:%d and Status:%d "), + " result:%d and Status:%d "), MAC_ADDR_ARRAY(pWextState->req_bssId.bytes), roamResult, roamStatus); - hdd_clear_roam_profile_ie(pAdapter); - /* inform association failure event to nl80211 */ if (eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == roamResult) { @@ -2237,12 +2236,22 @@ defined(FEATURE_WLAN_LFR) eCsrAuthType authType = pWextState->roamProfile.AuthType. authType[0]; + eCsrEncryptionType encryption_type = + pWextState->roamProfile. + EncryptionType.encryptionType[0]; bool isWep = + (((authType == + eCSR_AUTH_TYPE_OPEN_SYSTEM) || (authType == - eCSR_AUTH_TYPE_OPEN_SYSTEM) - || (authType == - eCSR_AUTH_TYPE_SHARED_KEY); - + eCSR_AUTH_TYPE_SHARED_KEY)) && + ((encryption_type == + eCSR_ENCRYPT_TYPE_WEP40) || + (encryption_type == + eCSR_ENCRYPT_TYPE_WEP104) || + (encryption_type == + eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) || + (encryption_type == + eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))); /* * In case of OPEN-WEP or SHARED-WEP * authentication, send exact protocol @@ -2253,7 +2262,9 @@ defined(FEATURE_WLAN_LFR) cfg80211_connect_result(dev, pRoamInfo->bssid.bytes, NULL, 0, NULL, 0, - isWep ? pRoamInfo->reasonCode : + (isWep && + pRoamInfo->reasonCode) ? + pRoamInfo->reasonCode : WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); } else @@ -2263,6 +2274,7 @@ defined(FEATURE_WLAN_LFR) WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); } + hdd_clear_roam_profile_ie(pAdapter); } if (pRoamInfo) { diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 41282b7fab64..0fe37fe6da02 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1722,6 +1722,8 @@ void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx, */ mlm_assoc_cnf.resultCode = eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA; + mlm_assoc_cnf.protStatusCode = + eSIR_MAC_UNSPEC_FAILURE_STATUS; session_entry->staId = add_sta_params->staIdx; goto end; } @@ -1805,6 +1807,7 @@ void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx, else mlm_assoc_cnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; } end: if (NULL != msg->bodyptr) { @@ -3044,6 +3047,7 @@ lim_process_sta_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx, } else { lim_log(mac_ctx, LOGP, FL("SessionId:%d ADD_BSS failed!"), session_entry->peSessionId); + mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; /* Return Assoc confirm to SME with failure */ if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE == session_entry->limMlmState) -- cgit v1.2.3 From 45ed3f8f1446ed4b2f172b0186e5cdf14dcd7fcf Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 30 Nov 2015 17:26:54 +0530 Subject: qcacld-3.0: IBSS: Handle IBSS mode in stop adapter properly qcacld-2.0 to qcacld-3.0 propagation In Stop Adapter IBSS mode is not handled properly and no DEL BSS is sent for the connected IBSS before DEL SELF STA. This may lead to crash in FW. As part of fix handle the IBSS mode and send DEL BSS if IBSS is connected. Change-Id: Ice1304aced1a158c7b589a95337412cda0183a04 CRs-Fixed: 908990 --- core/hdd/src/wlan_hdd_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index f134d8d71928..3edc5ad318c5 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2713,6 +2713,7 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, switch (adapter->device_mode) { case WLAN_HDD_INFRA_STATION: case WLAN_HDD_P2P_CLIENT: + case WLAN_HDD_IBSS: case WLAN_HDD_P2P_DEVICE: if (hdd_conn_is_connected( WLAN_HDD_GET_STATION_CTX_PTR(adapter)) || @@ -2756,9 +2757,7 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, hdd_abort_mac_scan(hdd_ctx, adapter->sessionId, eCSR_SCAN_ABORT_DEFAULT); } - - if (adapter->device_mode != WLAN_HDD_INFRA_STATION) - wlan_hdd_cleanup_remain_on_channel_ctx(adapter); + wlan_hdd_cleanup_remain_on_channel_ctx(adapter); #ifdef WLAN_OPEN_SOURCE cancel_work_sync(&adapter->ipv4NotifierWorkQueue); -- cgit v1.2.3 From 319ae5cd1ac76c9a34af5eef660216fbebc01c64 Mon Sep 17 00:00:00 2001 From: Sushant Kaushik Date: Mon, 2 Nov 2015 13:31:21 +0530 Subject: qcacld-3.0: Remove LL stats redundant logs qcacld-2.0 to qcacld-3.0 propagation Currently there are many LL stats related logs which doesn't provide any useful information. As a part of fix, remove all those redundant logs. Change-Id: Id1a89f209cfb57646828c5ee059f6f3790aac1c0 CRs-Fixed: 903941 --- core/hdd/src/wlan_hdd_stats.c | 225 ++++-------------------------------------- 1 file changed, 21 insertions(+), 204 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 549b3dedbba7..1f6030c81859 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -623,11 +623,10 @@ static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter, tpSirWifiPeerStat pData) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - tpSirWifiRateStat pWifiRateStat; tpSirWifiPeerStat pWifiPeerStat; tpSirWifiPeerInfo pWifiPeerInfo; struct sk_buff *vendor_event; - int status, i, j; + int status, i; struct nlattr *peers; int numRate; @@ -643,63 +642,6 @@ static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter, "LL_STATS_PEER_ALL : numPeers %u, more data = %u", pWifiPeerStat->numPeers, more_data); - for (i = 0; i < pWifiPeerStat->numPeers; i++) { - pWifiPeerInfo = (tpSirWifiPeerInfo) - ((uint8_t *) pWifiPeerStat->peerInfo + - (i * sizeof(tSirWifiPeerInfo))); - - if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) - pWifiPeerInfo->type = WIFI_PEER_AP; - - if (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) - pWifiPeerInfo->type = WIFI_PEER_P2P_GO; - - hddLog(CDF_TRACE_LEVEL_INFO, - " %d) LL_STATS Channel Stats " - " Peer Type %u " - " peerMacAddress %pM " - " capabilities 0x%x " - " numRate %u ", - i, - pWifiPeerInfo->type, - pWifiPeerInfo->peerMacAddress.bytes, - pWifiPeerInfo->capabilities, pWifiPeerInfo->numRate); - { - for (j = 0; j < pWifiPeerInfo->numRate; j++) { - pWifiRateStat = (tpSirWifiRateStat) - ((uint8_t *) pWifiPeerInfo->rateStats + - (j * sizeof(tSirWifiRateStat))); - - hddLog(CDF_TRACE_LEVEL_INFO, - " peer Rate Stats " - " preamble %u " - " nss %u " - " bw %u " - " rateMcsIdx %u " - " reserved %u " - " bitrate %u " - " txMpdu %u " - " rxMpdu %u " - " mpduLost %u " - " retries %u " - " retriesShort %u " - " retriesLong %u", - pWifiRateStat->rate.preamble, - pWifiRateStat->rate.nss, - pWifiRateStat->rate.bw, - pWifiRateStat->rate.rateMcsIdx, - pWifiRateStat->rate.reserved, - pWifiRateStat->rate.bitrate, - pWifiRateStat->txMpdu, - pWifiRateStat->rxMpdu, - pWifiRateStat->mpduLost, - pWifiRateStat->retries, - pWifiRateStat->retriesShort, - pWifiRateStat->retriesLong); - } - } - } - /* * Allocate a size of 4096 for the peer stats comprising * each of size = sizeof (tSirWifiPeerInfo) + numRate * @@ -803,7 +745,6 @@ static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter, struct sk_buff *vendor_event; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); int status; - int i; ENTER(); @@ -838,92 +779,6 @@ static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter, return; } - hddLog(CDF_TRACE_LEVEL_INFO, - " Num peers %u " - "LL_STATS_IFACE: " - " Mode %u " - " MAC %pM " - " State %u " - " Roaming %u " - " capabilities 0x%x " - " SSID %s " - " BSSID %pM", - num_peers, - pWifiIfaceStat->info.mode, - pWifiIfaceStat->info.macAddr.bytes, - pWifiIfaceStat->info.state, - pWifiIfaceStat->info.roaming, - pWifiIfaceStat->info.capabilities, - pWifiIfaceStat->info.ssid, pWifiIfaceStat->info.bssid.bytes); - - hddLog(CDF_TRACE_LEVEL_INFO, - " AP country str: %c%c%c", - pWifiIfaceStat->info.apCountryStr[0], - pWifiIfaceStat->info.apCountryStr[1], - pWifiIfaceStat->info.apCountryStr[2]); - - hddLog(CDF_TRACE_LEVEL_INFO, - " Country Str Association: %c%c%c", - pWifiIfaceStat->info.countryStr[0], - pWifiIfaceStat->info.countryStr[1], - pWifiIfaceStat->info.countryStr[2]); - - hddLog(CDF_TRACE_LEVEL_INFO, - " beaconRx %u " - " mgmtRx %u " - " mgmtActionRx %u " - " mgmtActionTx %u " - " rssiMgmt %u " - " rssiData %u " - " rssiAck %u " - " avg_bcn_spread_offset_high %u" - " avg_bcn_spread_offset_low %u" - " is leaky_ap %u" - " avg_rx_frms_leaked %u" - " rx_leak_window %u", - pWifiIfaceStat->beaconRx, - pWifiIfaceStat->mgmtRx, - pWifiIfaceStat->mgmtActionRx, - pWifiIfaceStat->mgmtActionTx, - pWifiIfaceStat->rssiMgmt, - pWifiIfaceStat->rssiData, - pWifiIfaceStat->rssiAck, - pWifiIfaceStat->avg_bcn_spread_offset_high, - pWifiIfaceStat->avg_bcn_spread_offset_low, - pWifiIfaceStat->is_leaky_ap, - pWifiIfaceStat->avg_rx_frms_leaked, - pWifiIfaceStat->rx_leak_window); - - for (i = 0; i < WIFI_AC_MAX; i++) { - hddLog(CDF_TRACE_LEVEL_INFO, - " %d) LL_STATS IFACE: " - " ac: %u txMpdu: %u " - " rxMpdu: %u txMcast: %u " - " rxMcast: %u rxAmpdu: %u " - " txAmpdu: %u mpduLost: %u " - " retries: %u retriesShort: %u " - " retriesLong: %u contentionTimeMin: %u " - " contentionTimeMax: %u contentionTimeAvg: %u " - " contentionNumSamples: %u", - i, - pWifiIfaceStat->AccessclassStats[i].ac, - pWifiIfaceStat->AccessclassStats[i].txMpdu, - pWifiIfaceStat->AccessclassStats[i].rxMpdu, - pWifiIfaceStat->AccessclassStats[i].txMcast, - pWifiIfaceStat->AccessclassStats[i].rxMcast, - pWifiIfaceStat->AccessclassStats[i].rxAmpdu, - pWifiIfaceStat->AccessclassStats[i].txAmpdu, - pWifiIfaceStat->AccessclassStats[i].mpduLost, - pWifiIfaceStat->AccessclassStats[i].retries, - pWifiIfaceStat->AccessclassStats[i].retriesShort, - pWifiIfaceStat->AccessclassStats[i].retriesLong, - pWifiIfaceStat->AccessclassStats[i].contentionTimeMin, - pWifiIfaceStat->AccessclassStats[i].contentionTimeMax, - pWifiIfaceStat->AccessclassStats[i].contentionTimeAvg, - pWifiIfaceStat->AccessclassStats[i]. - contentionNumSamples); - } - if (false == put_wifi_iface_stats(pWifiIfaceStat, num_peers, vendor_event)) { hddLog(CDF_TRACE_LEVEL_ERROR, FL("put_wifi_iface_stats fail")); @@ -1075,22 +930,6 @@ static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter, sizeof (tSirWifiChannelStats))); - hddLog(CDF_TRACE_LEVEL_INFO, - " %d) Channel Info" - " width is %u " - " CenterFreq %u " - " CenterFreq0 %u " - " CenterFreq1 %u " - " onTime %u " - " ccaBusyTime %u", - i, - pWifiChannelStats->channel.width, - pWifiChannelStats->channel.centerFreq, - pWifiChannelStats->channel.centerFreq0, - pWifiChannelStats->channel.centerFreq1, - pWifiChannelStats->onTime, - pWifiChannelStats->ccaBusyTime); - chInfo = nla_nest_start(vendor_event, i); if (chInfo == NULL) { hddLog(LOGE, FL("nla_nest_start failed")); @@ -1176,25 +1015,13 @@ static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, case SIR_HAL_LL_STATS_RESULTS_RSP: { hddLog(CDF_TRACE_LEVEL_INFO, - FL("RESPONSE SIR_HAL_LL_STATS_RESULTS_RSP")); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE paramID = 0x%x", - linkLayerStatsResults->paramId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE ifaceId = %u", - linkLayerStatsResults->ifaceId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE respId = %u", - linkLayerStatsResults->rspId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE more data = %u", - linkLayerStatsResults->moreResultToFollow); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE num radio = %u", - linkLayerStatsResults->num_radio); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS RESULTS RESPONSE result = %p", - linkLayerStatsResults->results); + "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); context = &ll_stats_context; spin_lock(&context->context_lock); @@ -1361,15 +1188,10 @@ __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, LinkLayerStatsSetReq.staId = pAdapter->sessionId; hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_SET reqId = %d", LinkLayerStatsSetReq.reqId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_SET staId = %d", LinkLayerStatsSetReq.staId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_SET mpduSizeThreshold = %d", - LinkLayerStatsSetReq.mpduSizeThreshold); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_SET aggressive Statistics Gathering = %d", - LinkLayerStatsSetReq.aggressiveStatisticsGathering); + "LL_STATS_SET reqId = %d, staId = %d, mpduSizeThreshold = %d, Statistics Gathering = %d", + LinkLayerStatsSetReq.reqId, LinkLayerStatsSetReq.staId, + LinkLayerStatsSetReq.mpduSizeThreshold, + LinkLayerStatsSetReq.aggressiveStatisticsGathering); if (CDF_STATUS_SUCCESS != sme_ll_stats_set_req(pHddCtx->hHal, &LinkLayerStatsSetReq)) { @@ -1488,12 +1310,10 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, LinkLayerStatsGetReq.staId = pAdapter->sessionId; - hddLog(LOG1, - FL("LL_STATS_GET reqId = %d"), LinkLayerStatsGetReq.reqId); - hddLog(LOG1, - FL("LL_STATS_GET staId = %d"), LinkLayerStatsGetReq.staId); - hddLog(LOG1, - FL("LL_STATS_GET paramIdMask = %d"), + hddLog(CDF_TRACE_LEVEL_INFO, + "LL_STATS_GET reqId = %d, staId = %d, paramIdMask = %d", + LinkLayerStatsGetReq.reqId, + LinkLayerStatsGetReq.staId, LinkLayerStatsGetReq.paramIdMask); context = &ll_stats_context; @@ -1628,14 +1448,11 @@ __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, LinkLayerStatsClearReq.staId = pAdapter->sessionId; hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_CLEAR reqId = %d", LinkLayerStatsClearReq.reqId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_CLEAR staId = %d", LinkLayerStatsClearReq.staId); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_CLEAR statsClearReqMask = 0x%X", - LinkLayerStatsClearReq.statsClearReqMask); - hddLog(CDF_TRACE_LEVEL_INFO, - "LL_STATS_CLEAR stopReq = %d", LinkLayerStatsClearReq.stopReq); + "LL_STATS_CLEAR reqId = %d, staId = %d, statsClearReqMask = 0x%X, stopReq = %d", + LinkLayerStatsClearReq.reqId, + LinkLayerStatsClearReq.staId, + LinkLayerStatsClearReq.statsClearReqMask, + LinkLayerStatsClearReq.stopReq); if (CDF_STATUS_SUCCESS == sme_ll_stats_clear_req(pHddCtx->hHal, &LinkLayerStatsClearReq)) { -- cgit v1.2.3 From 0d766872cb43f7745b8ba45c7e773d2c7751c93e Mon Sep 17 00:00:00 2001 From: "Gupta, Kapil" Date: Wed, 25 Nov 2015 19:21:29 +0530 Subject: qcacld-3.0: Support for handling of op class in xcsa action frame qcacld-2.0 to qcacld-3.0 propagation Add support to parse operating class from xcsa frame and select channel bandwidth on basis of new operating class. Change-Id: I33d794e77220ef82cca793767d459979eb940669 CRs-Fixed: 942104 --- core/cds/inc/cds_regdomain_common.h | 2 + core/cds/src/cds_regdomain.c | 44 ++++++++++ core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 107 +++++++++++++++++++++++- core/mac/src/pe/lim/lim_utils.h | 53 ++++++++++++ core/wma/inc/wma_if.h | 1 + core/wma/src/wma_features.c | 1 + 6 files changed, 206 insertions(+), 2 deletions(-) diff --git a/core/cds/inc/cds_regdomain_common.h b/core/cds/inc/cds_regdomain_common.h index 7feaf55c3928..36c480b9a309 100644 --- a/core/cds/inc/cds_regdomain_common.h +++ b/core/cds/inc/cds_regdomain_common.h @@ -2214,5 +2214,7 @@ typedef struct _regdm_supp_op_classes { uint16_t cds_regdm_get_opclass_from_channel(uint8_t *country, uint8_t channel, uint8_t offset); +uint16_t cds_regdm_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel, + uint8_t opclass); uint16_t cds_regdm_set_curr_opclasses(uint8_t num_classes, uint8_t *class); uint16_t cds_regdm_get_curr_opclasses(uint8_t *num_classes, uint8_t *class); diff --git a/core/cds/src/cds_regdomain.c b/core/cds/src/cds_regdomain.c index 3a935293c289..e3c897c81c82 100644 --- a/core/cds/src/cds_regdomain.c +++ b/core/cds/src/cds_regdomain.c @@ -622,6 +622,50 @@ uint16_t cds_get_regdmn_5g(uint32_t reg_dmn) return 0; } +/** + * cds_regdm_get_chanwidth_from_opclass() - return chan width based on opclass + * @country: country name + * @channel: operating channel + * @opclass: operating class + * + * Given a value of country, channel and opclass this API will return value of + * channel width. + * + * Return: channel width + * + */ +uint16_t cds_regdm_get_chanwidth_from_opclass(uint8_t *country, + uint8_t channel, + uint8_t opclass) +{ + regdm_op_class_map_t *class; + uint16_t i; + + if (true == cdf_mem_compare(country, "US", 2)) + class = us_op_class; + else if (true == cdf_mem_compare(country, "EU", 2)) + class = euro_op_class; + else if (true == cdf_mem_compare(country, "JP", 2)) + class = japan_op_class; + else + class = global_op_class; + + while (class->op_class) { + if (opclass == class->op_class) { + for (i = 0; + (i < MAX_CHANNELS_PER_OPERATING_CLASS && + class->channels[i]); + i++) { + if (channel == class->channels[i]) + return class->ch_spacing; + } + } + class++; + } + return 0; +} + + /* * Get operating class for a given channel */ diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index bde6cba7038f..eee97bae7934 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -55,6 +55,8 @@ #include "lim_session_utils.h" #include "lim_types.h" #include "sir_api.h" +#include "cds_regdomain_common.h" +#include "lim_send_messages.h" static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, tpPESession session_entry, tSirResultCodes result_code, @@ -2010,6 +2012,9 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) tpDphHashNode sta_ds = NULL; uint8_t session_id; uint16_t aid = 0; + uint16_t chan_space = 0; + int cb_mode = 0; + tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL; if (!csa_params) { @@ -2052,10 +2057,13 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ; + session_entry->gLimChannelSwitch.ch_center_freq_seg0 = 0; + session_entry->gLimChannelSwitch.ch_center_freq_seg1 = 0; + chnl_switch_info = + &session_entry->gLimWiderBWChannelSwitch; + if (session_entry->vhtCapability && session_entry->htSupportedChannelWidthSet) { - chnl_switch_info = - &session_entry->gLimWiderBWChannelSwitch; if (csa_params->ies_present_flag & lim_wbw_ie_present) { chnl_switch_info->newChanWidth = csa_params->new_ch_width; @@ -2067,8 +2075,103 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; session_entry->gLimChannelSwitch.ch_width = csa_params->new_ch_width + 1; + } else if (csa_params->ies_present_flag + & lim_xcsa_ie_present) { + chan_space = + cds_regdm_get_chanwidth_from_opclass( + mac_ctx->scan.countryCodeCurrent, + csa_params->channel, + csa_params->new_op_class); + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + + if (chan_space == 80) { + chnl_switch_info->newChanWidth = + CH_WIDTH_80MHZ; + } else if (chan_space == 40) { + chnl_switch_info->newChanWidth = + CH_WIDTH_40MHZ; + } else { + chnl_switch_info->newChanWidth = + CH_WIDTH_20MHZ; + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + } + + cb_mode = lim_select_cb_mode_for_sta( + session_entry, + csa_params->channel, + chan_space); + + chnl_switch_info->newCenterChanFreq0 = + lim_get_center_channel(mac_ctx, + csa_params->channel, + cb_mode, + chnl_switch_info->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 offrequency segment 1. + */ + chnl_switch_info->newCenterChanFreq1 = 0; + } + session_entry->gLimChannelSwitch.ch_center_freq_seg0 = + chnl_switch_info->newCenterChanFreq0; + session_entry->gLimChannelSwitch.ch_center_freq_seg1 = + chnl_switch_info->newCenterChanFreq1; + session_entry->gLimChannelSwitch.ch_width = + chnl_switch_info->newChanWidth; + } else if (session_entry->htSupportedChannelWidthSet) { + if (csa_params->ies_present_flag + & lim_xcsa_ie_present) { + chan_space = + cds_regdm_get_chanwidth_from_opclass( + mac_ctx->scan.countryCodeCurrent, + csa_params->channel, + csa_params->new_op_class); + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; + if (chan_space == 40) { + session_entry-> + gLimChannelSwitch.ch_width = + CH_WIDTH_40MHZ; + chnl_switch_info->newChanWidth = + CH_WIDTH_40MHZ; + cb_mode = lim_select_cb_mode_for_sta( + session_entry, + csa_params->channel, + chan_space); + if (cb_mode == + PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + session_entry-> + gLimChannelSwitch. + ch_center_freq_seg0 = + csa_params->channel + 2; + } else if (cb_mode == + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) { + session_entry-> + gLimChannelSwitch. + ch_center_freq_seg0 = + csa_params->channel - 2; + } + + } else { + session_entry-> + gLimChannelSwitch.ch_width = + CH_WIDTH_20MHZ; + chnl_switch_info->newChanWidth = + CH_WIDTH_40MHZ; + session_entry->gLimChannelSwitch.state = + eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + } + + + } + if (csa_params->sec_chan_offset) { session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_40MHZ; diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index cd9d6a1a1bf3..42a5eab8e451 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -294,6 +294,59 @@ is_entering_mimo_ps(tSirMacHTMIMOPowerSaveState curState, return false; } +/** + * lim_select_cb_mode_for_sta() - return cb_mode based on current session + * @session_entry: Session entry + * @channel: channel + * @chan_bw: channel bandwidth + * + * Given a value of channel and bandwidth this API will return the value of + * cb_mode on basis of channel, bandwidth ht/vht capabilities + * + * Return: cb_mode + * + */ + +static inline int lim_select_cb_mode_for_sta(tpPESession session_entry, + uint8_t channel, uint8_t chan_bw) +{ + if (session_entry->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 (session_entry->htSupportedChannelWidthSet) { + 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; +} + + static inline int lim_select_cb_mode(tDphHashNode *pStaDs, tpPESession psessionEntry, uint8_t channel, uint8_t chan_bw) diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 63dd5e3374bc..52e313908ff6 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -940,6 +940,7 @@ typedef struct CSAOffloadParams { uint8_t switchmode; uint8_t sec_chan_offset; uint8_t new_ch_width; + uint8_t new_op_class; uint8_t new_ch_freq_seg1; uint8_t new_ch_freq_seg2; uint32_t ies_present_flag; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index ffe4771826b7..f8f2736e39d9 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1492,6 +1492,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) (&csa_event->xcsa_ie[0]); csa_offload_event->channel = xcsa_ie->newchannel; csa_offload_event->switchmode = xcsa_ie->switchmode; + csa_offload_event->new_op_class = xcsa_ie->newClass; } else { WMA_LOGE("CSA Event error: No CSA IE present"); cdf_mem_free(csa_offload_event); -- cgit v1.2.3 From dd4ff90827642ea6a8ca28cbec7ac3f95cecf758 Mon Sep 17 00:00:00 2001 From: "Gupta, Kapil" Date: Mon, 26 Oct 2015 14:56:30 +0530 Subject: qcacld-3.0: Stop overwriting pnoOffload value with dummy value. qcacld-2.0 to qcacld-3.0 propagation Currently tpAniSirGlobal pnoOffload value is initialized with FW caps first time only and resetting to 0 while starting a bss in go mode. Existing value of pnoOffload is not retained while getting config for tSmeConfigParams. Added changes to retain current value of pnoOffload from tpAniSirGlobal while getting config for new tSmeConfigParams. Change-Id: I0eda12ec1c69aeca4465d41f3e3ba96b8e1944cb CRs-Fixed: 913994 --- core/sme/src/common/sme_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6c8ef59444b1..a4f8c06ea19f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -4325,6 +4325,7 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ pParam->max_intf_count = pMac->sme.max_intf_count; pParam->enableSelfRecovery = pMac->sme.enableSelfRecovery; + pParam->pnoOffload = pMac->pnoOffload; pParam->f_prefer_non_dfs_on_radar = pMac->f_prefer_non_dfs_on_radar; pParam->policy_manager_enabled = pMac->policy_manager_enabled; -- cgit v1.2.3 From ba77b1f9fd031e4a507d85a404196335ab114af9 Mon Sep 17 00:00:00 2001 From: Sushant Kaushik Date: Mon, 2 Nov 2015 11:38:25 +0530 Subject: qcacld-3.0: Enable Tx beamformee by default qcacld-2.0 to qcacld-3.0 propagation Default value of Tx beamformee is 0. As as part of fix, enable the default value of Tx beamformee. Change-Id: Ib4b30f2a925e95cd96cc789ac7bc223274fa6a67 CRs-Fixed: 921834 --- core/mac/inc/wni_cfg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 5bc0476e97e3..53a1c8b77f4c 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -1059,7 +1059,7 @@ enum { #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 0 +#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 -- cgit v1.2.3 From b36f3d52a67285beb1465df1f0d5dbe4ed828b51 Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Tue, 1 Dec 2015 15:59:56 -0800 Subject: qcacld-3.0: Don't allow two P2P GO interfaces on the same band In P2P GO + GO concurrency case, only DBS mode is supported for the two interfaces. Second P2P GO interface startup is blocked if its channel is on the same band as the first P2P GO interface. Change-Id: Ic85bd8f92983c8c08f61fdaf09be1ad13a17cd8f CRs-fixed: 945804 --- core/cds/src/cds_concurrency.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 8f5ec4036372..afd6f9160d9e 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -164,7 +164,7 @@ second_connection_pcl_dbs_table[CDS_MAX_ONE_CONNECTION_MODE] [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, - [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_5G, CDS_5G}, [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, @@ -172,7 +172,7 @@ second_connection_pcl_dbs_table[CDS_MAX_ONE_CONNECTION_MODE] [CDS_STA_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, [CDS_SAP_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, [CDS_P2P_CLIENT_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, - [CDS_P2P_GO_MODE] = {CDS_5G_SCC_CH, CDS_5G_SCC_CH, CDS_5G_SCC_CH}, + [CDS_P2P_GO_MODE] = {CDS_5G, CDS_5G, CDS_5G}, [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, @@ -181,7 +181,7 @@ second_connection_pcl_dbs_table[CDS_MAX_ONE_CONNECTION_MODE] [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, [CDS_P2P_CLIENT_MODE] = { CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, - [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_24G, CDS_24G, CDS_24G}, [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, @@ -190,7 +190,7 @@ second_connection_pcl_dbs_table[CDS_MAX_ONE_CONNECTION_MODE] [CDS_SAP_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, [CDS_P2P_CLIENT_MODE] = { CDS_SCC_CH_24G, CDS_24G_SCC_CH, CDS_SCC_CH_24G}, - [CDS_P2P_GO_MODE] = {CDS_SCC_CH_24G, CDS_SCC_CH_24G, CDS_SCC_CH_24G}, + [CDS_P2P_GO_MODE] = {CDS_24G, CDS_24G, CDS_24G}, [CDS_IBSS_MODE] = { CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE, CDS_MAX_PCL_TYPE} }, @@ -4714,6 +4714,22 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, cds_err("No VHT160, we have one connection already"); goto done; } + + /* don't allow two P2P GO on same band */ + if (channel && (mode == CDS_P2P_GO_MODE) && num_connections) { + index = 0; + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_P2P_GO_MODE, list); + while (index < count) { + if (CDS_IS_SAME_BAND_CHANNELS(channel, + conc_connection_list[list[index]].chan)) { + cds_err("Don't allow P2P GO on same band"); + goto done; + } + index++; + } + } + status = true; done: -- cgit v1.2.3 From 18d1ddb1aa8aee8eca0d9c1357dc21dac2e6ca9c Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Fri, 20 Nov 2015 13:54:08 -0800 Subject: qcacld-3.0: Increase max vdev number in target config Currently the max vdev value for roaming, beacon offload and beacon miss offload is 2, this causes crash when creating multiple vdev interfaces as now DBS concurrency is supported. Change the max vdev value to 3 for various offload features and change the max vdev supported value to 4. Change-Id: I57ddfa384bdba3ae7f9207551d28be75d500e7bf CRs-fixed: 938798 --- target/inc/wlan_tgt_def_config.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/inc/wlan_tgt_def_config.h b/target/inc/wlan_tgt_def_config.h index 2bcf796f9efe..0a142008cde2 100644 --- a/target/inc/wlan_tgt_def_config.h +++ b/target/inc/wlan_tgt_def_config.h @@ -35,8 +35,8 @@ /* * default limit of 8 VAPs per device. */ -/* Rome PRD support 3 vdevs */ -#define CFG_TGT_NUM_VDEV 3 +/* Rome PRD support 4 vdevs */ +#define CFG_TGT_NUM_VDEV 4 /* * We would need 1 AST entry per peer. Scale it by a factor of 2 to minimize hash collisions. @@ -130,16 +130,16 @@ #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 +#define CFG_TGT_DEFAULT_BMISS_OFFLOAD_MAX_VDEV 0x3 /* maximum number of VDEV offload Roaming to support */ -#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV 0x2 +#define CFG_TGT_DEFAULT_ROAM_OFFLOAD_MAX_VDEV 0x3 /* 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 +#define CFG_TGT_DEFAULT_GTK_OFFLOAD_MAX_VDEV 0x3 /* default: mcast->ucast disabled if ATH_SUPPORT_MCAST2UCAST not defined */ #ifndef ATH_SUPPORT_MCAST2UCAST @@ -186,7 +186,7 @@ /* * Maximum number of VDEV that beacon tx offload will support */ -#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 2 +#define CFG_TGT_DEFAULT_BEACON_TX_OFFLOAD_MAX_VDEV 3 /* * number of vdevs that can support tdls -- cgit v1.2.3 From f5d767f6a3114bf531e75431aa7ac74eec459da9 Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Thu, 24 Sep 2015 16:34:17 -0700 Subject: qcacld-3.0: Dynamic OTA test mode enable For OEM to do OTA tests, power save, background scan, and low RSSI scanning need to be disabled and it should be done dynamically. Implement a vendor command to enable and disable OTA test mode. CRs-fixed: 941776 Change-Id: Ic9da11cf5f4bb19a01d9b55c50c0aea196abbfb6 --- core/hdd/src/wlan_hdd_cfg80211.c | 123 +++++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 22 +++++++ 2 files changed, 145 insertions(+) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3ac951bc4291..e3c3a8ab8e30 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -52,6 +52,7 @@ #include "wlan_hdd_assoc.h" #include "wlan_hdd_wext.h" #include "sme_api.h" +#include "sme_power_save_api.h" #include "wlan_hdd_p2p.h" #include "wlan_hdd_cfg80211.h" #include "wlan_hdd_hostapd.h" @@ -4441,6 +4442,121 @@ static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, return ret; } +static const struct +nla_policy +qca_wlan_vendor_ota_test_policy +[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 }, +}; + +/** + * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test + * @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_set_ota_test(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); + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1]; + uint8_t ota_enable = 0; + CDF_STATUS status; + uint32_t current_roam_state; + + if (CDF_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX, + data, data_len, + qca_wlan_vendor_ota_test_policy)) { + hdd_err("invalid attr"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) { + hdd_err("attr ota test failed"); + return -EINVAL; + } + + ota_enable = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]); + + hdd_info(" OTA test enable = %d", ota_enable); + if (ota_enable != 1) { + hdd_err("Invalid value, only enable test mode is supported!"); + return -EINVAL; + } + + current_roam_state = + sme_get_current_roam_state(hal, adapter->sessionId); + status = sme_stop_roaming(hal, adapter->sessionId, + eCsrHddIssued); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("Enable/Disable roaming failed"); + return -EINVAL; + } + + status = sme_ps_enable_disable(hal, adapter->sessionId, + SME_PS_DISABLE); + if (status != CDF_STATUS_SUCCESS) { + hdd_err("Enable/Disable power save failed"); + /* restore previous roaming setting */ + if (current_roam_state == eCSR_ROAMING_STATE_JOINING || + current_roam_state == eCSR_ROAMING_STATE_JOINED) + status = sme_start_roaming(hal, adapter->sessionId, + eCsrHddIssued); + else if (current_roam_state == eCSR_ROAMING_STATE_STOP || + current_roam_state == eCSR_ROAMING_STATE_IDLE) + status = sme_stop_roaming(hal, adapter->sessionId, + eCsrHddIssued); + + if (status != CDF_STATUS_SUCCESS) + hdd_err("Restoring roaming state failed"); + + return -EINVAL; + } + + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test + * @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_set_ota_test(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -4862,6 +4978,13 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_get_link_properties }, + { + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_ota_test + }, }; /* diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index df5e5aa91e56..34275409f0bd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -248,6 +248,7 @@ typedef enum { * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: get link properties * @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete + * @QCA_NL80211_VENDOR_SUBCMD_OTA_TEST: enable OTA test */ enum qca_nl80211_vendor_subcmds { @@ -357,6 +358,10 @@ enum qca_nl80211_vendor_subcmds { /* Vendor scan commands */ QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN = 106, QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE = 107, + + /* OTA test subcommand */ + QCA_NL80211_VENDOR_SUBCMD_OTA_TEST = 108, + }; /** @@ -2172,6 +2177,23 @@ enum drv_dbs_capability { DRV_DBS_CAPABILITY_2X2, }; +/** + * enum qca_vendor_attr_ota_test - Enable OTA test + * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_INVALID: invalid value + * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE: enable OTA test + * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST: after last + * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX: max + */ +enum qca_vendor_attr_ota_test { + QCA_WLAN_VENDOR_ATTR_OTA_TEST_INVALID, + /* 8-bit unsigned value to indicate if OTA test is enabled */ + QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX = + QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST - 1 +}; + struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo); -- cgit v1.2.3 From 60073371b3f3556787d36d6ed9c198fc60111aed Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Mon, 7 Dec 2015 12:51:58 +0530 Subject: qcacld-3.0: Avoid taking lock for vfree API during driver load/unload This is qcacld-2.0 to qcacld-3.0 propagation Avoid invoking vfree inside spinlock during logging service activation and deactivation. Since vfree is prone to sleep, this disables the IRQs for duration longer than the acceptable limit. vfree can be done without spin lock here, as there is no synchronization issue in this scenario. CRs-Fixed: 914363 Change-Id: I4d69431a98a4e4301dfc1e2b3b4c40c408a7ef99 --- core/utils/logging/src/wlan_logging_sock_svc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index 59033f384233..507b5847e939 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -701,10 +701,10 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf) 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); + vfree(gplog_msg); + gplog_msg = NULL; return -ENOMEM; } wake_up_process(gwlan_logging.thread); @@ -740,10 +740,10 @@ int wlan_logging_sock_deactivate_svc(void) 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); + vfree(gplog_msg); + gplog_msg = NULL; pr_info("%s: Deactivate wlan_logging svc\n", __func__); -- cgit v1.2.3 From c55b62f0442d3e2f85b79e5d6d861be0f95506ac Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Mon, 23 Nov 2015 15:04:05 +0530 Subject: Revert "qcacld-3.0: After DELTS, revert to UAPSD related intervals in ini" qcacld-2.0 to qcacld-3.0 propagation This reverts Change-Id I858cd3cbd536ec189ea808c5d637abffe388f7aa. With change id I858cd3cbd536ec189ea808c5d637abffe388f7aa, host is not sending WMI_STA_UAPSD_AUTO_TRIG_CMDID command to firmware during disable UAPSD per AC. Change-Id: Ifdbcd6926ca86b1baeeadcf7a4720e460d41a6e5 CRs-Fixed: 911229 --- core/hdd/src/wlan_hdd_wmm.c | 78 +++++++++---------------------------------- core/sme/inc/sme_api.h | 2 -- core/sme/inc/sme_qos_api.h | 3 +- core/sme/src/qos/sme_qos.c | 80 --------------------------------------------- 4 files changed, 17 insertions(+), 146 deletions(-) diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index f2699f1ab4e3..9b93e2711fa1 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -248,72 +248,26 @@ static void hdd_wmm_disable_tl_uapsd(hdd_wmm_qos_context_t *pQosContext) sme_ac_enum_type acType = pQosContext->acType; hdd_wmm_ac_status_t *pAc = &pAdapter->hddWmmStatus.wmmAcStatus[acType]; CDF_STATUS status; - uint32_t service_interval; - uint32_t suspension_interval; - uint8_t uapsd_mask; - uint8_t active_tspec = INVALID_TSPEC; - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); - struct hdd_config *cfg = hdd_ctx->config; /* have we previously enabled UAPSD? */ if (pAc->wmmAcUapsdInfoValid == true) { - uapsd_mask = cfg->UapsdMask; - /* Finding uapsd_mask as per AC */ - uapsd_mask = uapsd_mask & (1 << (SME_AC_VO - acType)); - - sme_qos_tspec_active( - (tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), acType, - pAdapter->sessionId, &active_tspec); - - /* Call sme_enable_uapsd_for_ac only when static uapsd mask - * is present and no active tspecs. - */ - - if (uapsd_mask && !active_tspec) { - switch (acType) { - case SME_AC_VO: - service_interval = cfg->InfraUapsdVoSrvIntv; - suspension_interval = cfg->InfraUapsdVoSuspIntv; - break; - case SME_AC_VI: - service_interval = cfg->InfraUapsdViSrvIntv; - suspension_interval = cfg->InfraUapsdViSuspIntv; - break; - case SME_AC_BE: - service_interval = cfg->InfraUapsdBeSrvIntv; - suspension_interval = cfg->InfraUapsdBeSuspIntv; - break; - case SME_AC_BK: - service_interval = cfg->InfraUapsdBkSrvIntv; - suspension_interval = cfg->InfraUapsdBkSuspIntv; - break; - default: - return; - } + status = + sme_disable_uapsd_for_ac((WLAN_HDD_GET_CTX(pAdapter))-> + pcds_context, + (WLAN_HDD_GET_STATION_CTX_PTR + (pAdapter))->conn_info.staId[0], + acType, pAdapter->sessionId); - /* restore the UAPSD intervals configuration */ - status = sme_enable_uapsd_for_ac(hdd_ctx->pcds_context, - (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, - pAc->wmmAcTspecInfo.ts_info.direction, - pAc->wmmAcTspecInfo.ts_info.psb, - pAdapter->sessionId, - cfg->DelayedTriggerFrmInt); - - if (!CDF_IS_STATUS_SUCCESS(status)) { - hdd_err("Failed to set U-APSD for AC=%d", - acType); - } else { - /* TL no longer has valid UAPSD info */ - pAc->wmmAcUapsdInfoValid = false; - hdd_err("Disabled UAPSD in TL for AC=%d", - acType); - } + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_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 = false; + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, + "%s: Disabled UAPSD in TL for AC=%d", + __func__, acType); } } } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 39ae9660884f..15d3d864c9ac 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -83,8 +83,6 @@ reg_info_2 |= ((val & 0xff) << 8); \ } while (0) -/* Macro to indicate invalid no of tspecs */ -#define INVALID_TSPEC 100 #define SME_CONFIG_TO_ROAM_CONFIG 1 #define ROAM_CONFIG_TO_SME_CONFIG 2 diff --git a/core/sme/inc/sme_qos_api.h b/core/sme/inc/sme_qos_api.h index 2dd02de6511a..c9fd0cfed011 100644 --- a/core/sme/inc/sme_qos_api.h +++ b/core/sme/inc/sme_qos_api.h @@ -251,7 +251,6 @@ CDF_STATUS sme_offload_qos_process_out_of_uapsd_mode(tpAniSirGlobal mac_ctx, uint32_t session_id); CDF_STATUS sme_offload_qos_process_into_uapsd_mode(tpAniSirGlobal mac_ctx, uint32_t session_id); -bool sme_qos_tspec_active(tpAniSirGlobal pMac, sme_ac_enum_type ac, - uint8_t sessionId, uint8_t *pActiveTspec); + #endif /* #if !defined( __SME_QOSAPI_H ) */ diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 7506fab4864d..8d127fe29302 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -7751,84 +7751,4 @@ static uint8_t sme_qos_assign_dialog_token(void) } return token; } - -/** - * sme_qos_tspec_active() - API exposed to HDD to check no of active Tspecs - * - * @pMac: The handle returned by macOpen - * @ac: Determines type of Access Category - * @sessionId: sessionId returned by sme_OpenSession - * @pActiveTspec: return the number of active Tspecs - * - * Return: true if success, otherwise false - */ -bool sme_qos_tspec_active(tpAniSirGlobal pMac, sme_ac_enum_type ac, - uint8_t sessionId, uint8_t *pActiveTspec) -{ - sme_QosSessionInfo *pSession = NULL; - sme_QosACInfo *pACInfo = NULL; - - if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: %d: Session Id %d is invalid", - __func__, __LINE__, sessionId); - return false; - } - - pSession = &sme_qos_cb.sessionInfo[sessionId]; - - if (NULL == pSession) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: %d pSession not found sessionId:%d", - __func__, __LINE__, sessionId); - return false; - } - - if (!pSession->sessionActive) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: %d: Session %d is inactive", - __func__, __LINE__, sessionId); - return false; - } - - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: %d: Session %d is active", - __func__, __LINE__, sessionId); - - 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 */ - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: %d: On session %d AC %d has QoS active", - __func__, __LINE__, sessionId, ac); - - /* Are any TSPECs active? */ - if (pACInfo->tspec_mask_status) { - /* 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 */ - *pActiveTspec = 2; - } else { - /* only one TSPEC is active */ - *pActiveTspec = 1; - } - } else { - *pActiveTspec = 0; - } - } else { - /* Hardcoding value to INVALID_TSPEC to indicate the caller - * not to update UAPSD parameters as QOS is not active - */ - *pActiveTspec = INVALID_TSPEC; - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: %d: On session %d AC %d has no QoS active", - __func__, __LINE__, sessionId, ac); - } - - return true; -} - #endif /* WLAN_MDM_CODE_REDUCTION_OPT */ -- cgit v1.2.3 From 43c7125ad8f4c24f1e48d6a261aa91fcca814e14 Mon Sep 17 00:00:00 2001 From: "Konamki, Sreelakshmi" Date: Wed, 8 Jul 2015 10:16:27 +0530 Subject: qcacld-3.0: STA is disconnected with specific AP IPTIME N904NS-second qcacld-2.0 to qcacld-3.0 propagation STA gets disconnected with AP IPTIME N904NS when AP is configured for WPA1 + TKIP on CH 161. Change-Id: Ifa30ed624c1f9f3c549def45cdb9e5f8ebfae233 CRs-Fixed: 627650 --- core/sme/src/csr/csr_api_roam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7c627c004063..faf9b032fc7d 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -12084,7 +12084,7 @@ static ePhyChanBondState csr_get_cb_mode_from_ies(tpAniSirGlobal pMac, (pIes->WPA.unicast_cipher_count == 1)) && ((NULL != &(pIes->WPA.unicast_ciphers[0])) && !memcmp(&(pIes->WPA.unicast_ciphers[0]), - "\x00\x0f\xac\x02", 4)))) { + "\x00\x50\xf2\x02", 4)))) { sms_log(pMac, LOGW, " No channel bonding in TKIP mode "); return PHY_SINGLE_CHANNEL_CENTERED; -- cgit v1.2.3 From b3e26c9acf4b3878032aece6a23a20300409f5f6 Mon Sep 17 00:00:00 2001 From: Hema Aparna Medicharla Date: Mon, 24 Aug 2015 11:22:29 +0530 Subject: qcacld-3.0: Donot defer Rx frames processing if ADD TS request sent qcacld-2.0 to qcacld-3.0 propagation Current implementation defers all the received frames when ADD TS request is sent out over the air. This, in addition, to check for pMac->lim.gLimAddtsSent incurs delay, till ADD TS response timeout, in processing of the ADD TS response received if SET_LIM_PROCESS_DEFD_MESGS is set to FALSE. As there is no rationale defer processing of Rx frames while waiting for ADDTS response, changes are made to not defer processing of RX frames for the same. Change-Id: I1d1a41a0e3555ae19548a0cabf3b9569af775f72 CRs-Fixed: 839546 --- core/mac/src/pe/lim/lim_process_message_queue.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index bdd66b31434a..bacb031ed16c 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -287,7 +287,14 @@ uint8_t static def_msg_decision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #ifdef FEATURE_OEM_DATA_SUPPORT (limMsg->type != WMA_START_OEM_DATA_RSP) && #endif - (limMsg->type != WMA_ADD_TS_RSP)) { + (limMsg->type != WMA_ADD_TS_RSP) && + /* Allow processing of RX frames while awaiting reception + * of ADD TS response over the air. This logic particularly + * handles the case when host sends ADD BA request to FW + * after ADD TS request is sent over the air and + * ADD TS response received over the air */ + !(limMsg->type == SIR_BB_XPORT_MGMT_MSG && + pMac->lim.gLimAddtsSent)) { PELOG1(lim_log (pMac, LOG1, FL @@ -1890,7 +1897,8 @@ void lim_process_deferred_message_queue(tpAniSirGlobal pMac) if ((lim_is_system_in_scan_state(pMac)) || (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) - || (pMac->lim.gLimSystemInScanLearnMode)) + || (pMac->lim.gLimSystemInScanLearnMode) + || pMac->lim.gLimAddtsSent) break; } } -- cgit v1.2.3 From e7f859906a31a8890292cd2fbc72d50a44a9adac Mon Sep 17 00:00:00 2001 From: "Konamki, Sreelakshmi" Date: Wed, 15 Jul 2015 12:43:29 +0530 Subject: qcacld-3.0: STA is disconnected with specific AP IPTIME N904NS-second qcacld-2.0 to qcacld-3.0 propagation STA gets disconnected with AP IPTIME N904NS when AP is configured for WPA1 + TKIP on CH 161. Return value of memcmp function must be checked with NOT operation. Change-Id: Ic866a70917c1e713855c28a8f156ffe7c381fa07 CRs-Fixed: 642070 --- core/sme/src/csr/csr_api_roam.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index faf9b032fc7d..d4c39e4ef4b2 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -12075,16 +12075,16 @@ static ePhyChanBondState csr_get_cb_mode_from_ies(tpAniSirGlobal pMac, return PHY_SINGLE_CHANNEL_CENTERED; } - /* Check set as TKIP or not. */ - if (((NULL != &(pIes->RSN.pwise_cipher_suites[0][0]) && - (pIes->RSN.pwise_cipher_suite_count == 1)) && + /* 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)) - || (((NULL != &(pIes->WPA)) && - (pIes->WPA.unicast_cipher_count == 1)) - && ((NULL != &(pIes->WPA.unicast_ciphers[0])) - && !memcmp(&(pIes->WPA.unicast_ciphers[0]), - "\x00\x50\xf2\x02", 4)))) { + "\x00\x0f\xac\x02", 4)) + /* In Case WPA1 and TKIP is the only one cipher suite + * in Unicast. + */ + || (pIes->WPA.present && (pIes->WPA.unicast_cipher_count == 1) + && !memcmp(&(pIes->WPA.unicast_ciphers[0][0]), + "\x00\x50\xf2\x02", 4))) { sms_log(pMac, LOGW, " No channel bonding in TKIP mode "); return PHY_SINGLE_CHANNEL_CENTERED; -- cgit v1.2.3 From e428c4c07e0b8ba56f492436384d6f1c47bcfe9d Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Fri, 13 Mar 2015 19:15:00 +0530 Subject: qcacld-3.0: initialize SendFlags in HTT before downloading to FW qcacld-2.0 to qcacld-3.0 propagation In Low-latency interface, to avoid 1d2 happening during roaming test, host need to send HTC header to fw, by setting SendFlags to zero to avoid deadlock situation.1d2 happened during roaming test. Change-Id: Ib3d16deadf038708fb75bcba692bd6adf3959c4e CRs-Fixed: 807505 --- core/htc/htc_packet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/core/htc/htc_packet.h b/core/htc/htc_packet.h index c30d5114434b..34707e5c6e8a 100644 --- a/core/htc/htc_packet.h +++ b/core/htc/htc_packet.h @@ -149,6 +149,7 @@ typedef struct _HTC_PACKET { (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) \ -- cgit v1.2.3 From 90ff56fb05870e7a15b5998e759461486c167d25 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Thu, 29 Jan 2015 19:55:14 +0530 Subject: qcacld-3.0: disable pn check for ibss network, in security mode qcacld-2.0 to qcacld-3.0 propagation Multicast packets using different sequence number space gets dropped on the host due to the existing logic of running duplicate detection check and out-of-order packet check on all non-aggregation (legacy) TIDs, since f/w uses a special (non-aggregation) TID (18) to indicate these packets to the host, irrespective of sequence number space. The fix is in 2 parts: 1) Do only duplicate detection on mcast packets & not out-of-order check (Also do dup-detection only if retry bit is set) 2) Instead of using mcast TID indicated by f/w, use the actual packet TID from the Rx descriptor to perform the duplicate detection and use a separate (new) field in rx_reorder_array to store the last successful mcast sequence number. On the next mcast packet perform the duplicate detection against mcast sequence number, rather than the ucast sequence number. Change-Id: I4c3542e82a1917b4ed27513e9244702bb212df88 CRs-FIXED: 788954 --- core/dp/txrx/ol_rx_pn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_pn.c b/core/dp/txrx/ol_rx_pn.c index 362616c71f2d..74ffdda985e9 100644 --- a/core/dp/txrx/ol_rx_pn.c +++ b/core/dp/txrx/ol_rx_pn.c @@ -96,8 +96,10 @@ ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev, int last_pn_valid; /* Make sure host pn check is not redundant */ - if (cdf_atomic_read(&peer->fw_pn_check)) + if ((cdf_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); -- cgit v1.2.3 From 869169a4a236de1fc29afef567c1d2bb107bb83a Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Tue, 1 Dec 2015 16:16:36 +0530 Subject: qcacld-3.0: cleanup tx-queue during SSR qcacld-2.0 to qcacld-3.0 propagation During SSR, Host is sending packets to firmware before WMI_READY_EVENT. Fix is to avoid sending tx when logp_in_progress & clean ll-queue packets in shutdown. Change-Id: Ib6b9f4d51f2aa7f85d384831818b45763c702c88 CRs-Fixed: 834887 --- core/hdd/src/wlan_hdd_tx_rx.c | 8 ++++++++ core/wma/src/wma_main.c | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 3ea2d855eda8..0f6c3b9c13db 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -338,6 +338,14 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; + if (cds_is_logp_in_progress()) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_WARN, + "LOPG in progress, dropping the packet"); + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + kfree_skb(skb); + return NETDEV_TX_OK; + } if (WLAN_HDD_IBSS == pAdapter->device_mode) { struct cdf_mac_addr *pDestMacAddress = diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index f37d14f34d8d..2fc74131c6ed 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2769,7 +2769,7 @@ CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) { tp_wma_handle wma_handle; CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; - + int i; wma_handle = cds_get_context(CDF_MODULE_ID_WMA); WMA_LOGD("%s: Enter", __func__); @@ -2816,6 +2816,13 @@ CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) #endif /* HIF_USB */ } + /* 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); + } + } cdf_status = wma_tx_detach(wma_handle); if (cdf_status != CDF_STATUS_SUCCESS) { WMA_LOGP("%s: Failed to deregister tx management", __func__); -- cgit v1.2.3 From 363af840d6e6882afadd3cef60837d060e7ce34f Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Fri, 4 Dec 2015 11:43:46 -0800 Subject: qcacld-3.0: Fix incorrect reference to wiphy flags Fix incorrect reference of wiphy flags while setting WIPHY_FLAG_HAS_CHANNEL_SWITCH. Change-Id: Ifebaa9a8452a8564f60f29015f240d5a43bb9afb CRs-Fixed: 947551 --- core/hdd/src/wlan_hdd_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e3c3a8ab8e30..838b627ae40e 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -636,7 +636,7 @@ static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { #ifdef CHANNEL_SWITCH_SUPPORTED static inline void hdd_add_channel_switch_support(uint32_t *flags) { - flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; return; } #else -- cgit v1.2.3 From 9bd2d2db838fb22b93da3bc9af9de1573eb9aeec Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Mon, 19 Oct 2015 11:52:47 -0700 Subject: qcacld-3.0: Fix mangled function names Fix mangled APIs sme_configure_ext_wo_w, sme_process_ready_to_ext_wo_w and lim_remove_timeout_pbc_sessions which were introduced while converting the names programmatically. Change-Id: Ie0a79b476a99bf1be0411dae0542359e7d58141a CRs-Fixed: 882962 --- core/hdd/src/wlan_hdd_ioctl.c | 4 +- core/mac/src/pe/lim/lim_process_probe_req_frame.c | 27 ++++------- core/sme/inc/sme_api.h | 2 +- core/sme/src/common/sme_api.c | 58 ++++++++++------------- 4 files changed, 36 insertions(+), 55 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index d2218c541b8f..885817a58d00 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1602,12 +1602,12 @@ static int hdd_enable_ext_wow(hdd_adapter_t *adapter, INIT_COMPLETION(hdd_ctx->ready_to_extwow); - cdf_ret_status = sme_configure_ext_wo_w(hHal, ¶ms, + cdf_ret_status = sme_configure_ext_wow(hHal, ¶ms, &wlan_hdd_ready_to_extwow, hdd_ctx); if (CDF_STATUS_SUCCESS != cdf_ret_status) { hddLog(CDF_TRACE_LEVEL_ERROR, - FL("sme_configure_ext_wo_w returned failure %d"), + FL("sme_configure_ext_wow returned failure %d"), cdf_ret_status); return -EPERM; } diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index ccc87123e169..1ed186ec59c5 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -113,25 +113,16 @@ void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, } /** - * lim_remove_timeout_pb_csessions + * lim_remove_timeout_pbc_sessions() - remove pbc probe req entries. + * @pMac - Pointer to Global MAC structure + * @pbc - The beginning entry in WPS PBC probe request link list * - ***FUNCTION: - * This function is called to remove the WPS PBC probe request entires from specific entry to end. - * - ***LOGIC: - * - * - ***ASSUMPTIONS: + * This function is called to remove the WPS PBC probe request entries from + * specific entry to end. * - * - ***NOTE: - * - * @param pMac Pointer to Global MAC structure - * @param pbc The beginning entry in WPS PBC probe request link list - * - * @return None + * Return - None */ -static void lim_remove_timeout_pb_csessions(tpAniSirGlobal pMac, +static void lim_remove_timeout_pbc_sessions(tpAniSirGlobal pMac, tSirWPSPBCSession *pbc) { tSirWPSPBCSession *prev; @@ -267,7 +258,7 @@ static void lim_update_pbc_session_entry(tpAniSirGlobal pMac, while (pbc) { if (curTime > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) { prev->next = NULL; - lim_remove_timeout_pb_csessions(pMac, pbc); + lim_remove_timeout_pbc_sessions(pMac, pbc); break; } prev = pbc; @@ -298,7 +289,7 @@ static void lim_update_pbc_session_entry(tpAniSirGlobal pMac, void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry) { - lim_remove_timeout_pb_csessions(pMac, psessionEntry->pAPWPSPBCSession); + lim_remove_timeout_pbc_sessions(pMac, psessionEntry->pAPWPSPBCSession); } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 15d3d864c9ac..b4af548b7f9d 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -498,7 +498,7 @@ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, CDF_STATUS sme_configure_resume_req(tHalHandle hHal, tpSirWlanResumeParam wlanResumeParam); #ifdef WLAN_FEATURE_EXTWOW_SUPPORT -CDF_STATUS sme_configure_ext_wo_w(tHalHandle hHal, +CDF_STATUS sme_configure_ext_wow(tHalHandle hHal, tpSirExtWoWParams wlanExtParams, csr_readyToSuspendCallback callback, void *callbackContext); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a4f8c06ea19f..54ac7f07500e 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1590,23 +1590,19 @@ void sme_process_ready_to_suspend(tHalHandle hHal, } #ifdef WLAN_FEATURE_EXTWOW_SUPPORT -/*-------------------------------------------------------------------------- - - \fn - sme_process_ready_to_ext_wo_w - \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 mac_open. - pReadyToExtWoW - Parameter received along with ready to Ext WoW - indication from WMA. - - \return None - - \sa - --------------------------------------------------------------------------*/ -void sme_process_ready_to_ext_wo_w(tHalHandle hHal, +/** + * sme_process_ready_to_ext_wow() - inform ready to ExtWoW indication. + * @hHal - Handle returned by mac_open. + * @pReadyToExtWoW - Parameter received along with ready to Ext WoW + * indication from WMA. + * + * On getting ready to Ext WoW indication, this function calls callback + * registered (HDD callback)with SME to inform ready to ExtWoW indication. + * + * Return: None + */ +void sme_process_ready_to_ext_wow(tHalHandle hHal, tpSirReadyToExtWoWInd pReadyToExtWoW) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -2509,7 +2505,7 @@ CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) #ifdef WLAN_FEATURE_EXTWOW_SUPPORT case eWNI_SME_READY_TO_EXTWOW_IND: if (pMsg->bodyptr) { - sme_process_ready_to_ext_wo_w(pMac, pMsg->bodyptr); + sme_process_ready_to_ext_wow(pMac, pMsg->bodyptr); cdf_mem_free(pMsg->bodyptr); } else { sms_log(pMac, LOGE, FL("Empty message for %d"), @@ -6619,23 +6615,17 @@ CDF_STATUS sme_configure_resume_req(tHalHandle hHal, } #ifdef WLAN_FEATURE_EXTWOW_SUPPORT -/* --------------------------------------------------------------------------- - - \fn sme_configure_ext_wo_w - - \brief - SME will pass this request to lower mac to configure Extr WoW - - \param - - hHal - The handle returned by mac_open. - - wlanExtParams- Depicts the wlan Ext params - - \return CDF_STATUS - - --------------------------------------------------------------------------- */ -CDF_STATUS sme_configure_ext_wo_w(tHalHandle hHal, +/** + * sme_configure_ext_wow() - configure Extr WoW + * @hHal - The handle returned by mac_open. + * @wlanExtParams - Depicts the wlan Ext params. + * @callback - ext_wow callback to be registered. + * @callback_context - ext_wow callback context + * + * SME will pass this request to lower mac to configure Extr WoW + * Return: CDF_STATUS + */ +CDF_STATUS sme_configure_ext_wow(tHalHandle hHal, tpSirExtWoWParams wlanExtParams, csr_readyToExtWoWCallback callback, void *callback_context) -- cgit v1.2.3 From f7cbf85ea9c25c196c8d649c58274a4778557432 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Thu, 19 Nov 2015 16:04:32 -0800 Subject: qcacld-3.0: CL 1412709 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add wmi interface changes related to enhanced ioac feature. Change-Id: Ia45ef032bd6e01242e28123cfc402cac9ae8a22d CRs-Fixed: 865207 --- target/inc/wmi_unified.h | 9 +++++++++ target/inc/wmi_version.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 1511fe3d94d0..b3994f0d5760 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -6727,6 +6727,8 @@ typedef struct { #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, @@ -6909,6 +6911,11 @@ typedef struct ioac_sock_pattern_s { 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 { @@ -6957,6 +6964,8 @@ typedef struct ioac_keepalive_s { 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 { diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 9c62d2d3092e..b9d773ba8a71 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 177 +#define __WMI_REVISION_ 178 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 93e2b6ca5fdffdb070789632a9eef1889fc4685a Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Thu, 19 Nov 2015 16:08:00 -0800 Subject: qcacld-3.0: CL 1412803 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add service bit for Unified WOW. Change-Id: If23dbd048fab5032200901d263a71fb49c8203e4 CRs-Fixed: 865207 --- target/inc/wmi_services.h | 2 ++ target/inc/wmi_version.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/inc/wmi_services.h b/target/inc/wmi_services.h index b2b1dfa71eb4..6a447e17212b 100644 --- a/target/inc/wmi_services.h +++ b/target/inc/wmi_services.h @@ -129,6 +129,8 @@ typedef enum { WMI_SERVICE_EGAP, /* FW supports 11W PMF Offload for STA */ WMI_SERVICE_STA_PMF_OFFLOAD, + /* FW supports unified D0 and D3 wow */ + WMI_SERVICE_UNIFIED_WOW_CAPABILITY, WMI_MAX_SERVICE = 128 /* max service */ } WMI_SERVICE; diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index b9d773ba8a71..11ab52daeff5 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 178 +#define __WMI_REVISION_ 179 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 96dd7c7629e9d329599c7712b5a2ffc8044bce2c Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Thu, 19 Nov 2015 16:16:20 -0800 Subject: qcacld-3.0: CL 1413998 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add new RTT related wmi interface changes to support TLV based messaging. Change-Id: I0591907984c3c58039a06ce123dca777d24c590f CRs-Fixed: 865207 --- core/wmi/wmi_unified.c | 1 + target/inc/wmi_tlv_defs.h | 26 +++++++++++++++++++------- target/inc/wmi_unified.h | 11 +++++++---- target/inc/wmi_version.h | 2 +- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 84dab33e89e4..6e908a3f866a 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -605,6 +605,7 @@ static uint8_t *get_wmi_cmd_string(WMI_CMD_ID wmi_command) 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 */ diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 11a30222d7de..47686f1e957d 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -840,7 +840,8 @@ typedef enum { 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_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. @@ -956,7 +957,8 @@ typedef enum { 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_TRANSFER_DATA_TO_FLASH_COMPLETE_EVENTID) \ + OP(WMI_OEM_RESPONSE_EVENTID) /* TLV definitions of WMI commands */ @@ -1413,12 +1415,17 @@ WMITLV_CREATE_PARAM_STRUC(WMI_RTT_MEASREQ_CMDID); 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 */ +/*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) @@ -2661,26 +2668,31 @@ WMITLV_CREATE_PARAM_STRUC(WMI_PDEV_UTF_EVENTID); 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 */ +/* 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*/ +/* 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*/ +/* 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*/ +/* 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) \ diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index b3994f0d5760..9c5657d81e20 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -781,7 +781,8 @@ typedef enum { /*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), + 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), @@ -1147,9 +1148,11 @@ typedef enum { /*batch scan result */ WMI_BATCH_SCAN_RESULT_EVENTID, /* OEM Event */ - WMI_OEM_CAPABILITY_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_OEM), - WMI_OEM_MEASUREMENT_REPORT_EVENTID, - WMI_OEM_ERROR_REPORT_EVENTID, + WMI_OEM_CAPABILITY_EVENTID = /* DEPRECATED */ + WMI_EVT_GRP_START_ID(WMI_GRP_OEM), + 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), diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 11ab52daeff5..7c37caa521e1 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 179 +#define __WMI_REVISION_ 180 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 49b9ab9a03e8b0a6816b6f0d8a1c7d67df8ee370 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Thu, 19 Nov 2015 16:24:50 -0800 Subject: qcacld-3.0: CL 1414893 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add wmi interface changes related to SCPC implementation. Change-Id: I493f03d14dfb54fb152e142c0ec4df69bcb65721 CRs-Fixed: 865207 --- target/inc/wmi_tlv_defs.h | 10 +++++++++- target/inc/wmi_unified.h | 23 +++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 47686f1e957d..04fb12fe0a17 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -602,6 +602,7 @@ typedef enum { 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_ID; /* @@ -958,7 +959,8 @@ typedef enum { 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_OEM_RESPONSE_EVENTID) \ + OP(WMI_PDEV_UTF_SCPC_EVENTID) /* TLV definitions of WMI commands */ @@ -2663,6 +2665,12 @@ WMITLV_CREATE_PARAM_STRUC(WMI_WLAN_PROFILE_DATA_EVENTID); 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) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 9c5657d81e20..4f2e67fffa7a 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -1124,6 +1124,9 @@ typedef enum { /* 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 @@ -12304,6 +12307,26 @@ typedef struct { 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 { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_scpc_event_fixed_param + */ + A_UINT32 tlv_header; + /* 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; + /* ADD NEW DEFS HERE */ /***************************************************************************** diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 7c37caa521e1..8ee372b69459 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 180 +#define __WMI_REVISION_ 181 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 777a2cd3354e9b5b2a5edd9eaf78db2efe13e1fa Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Thu, 19 Nov 2015 16:45:59 -0800 Subject: qcacld-3.0: CL 1417063 - update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add rsPhyErrMask fields to WMI COMB_PHYERR_RX. Change-Id: Ib64bb9b21d381863ef60e17e93886d070a6a7617 CRs-Fixed: 865207 --- target/inc/wmi_unified.h | 22 ++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 4f2e67fffa7a..d7e689ddbf44 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -2576,6 +2576,24 @@ typedef struct { 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 */ @@ -2584,6 +2602,10 @@ typedef struct { 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... diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 8ee372b69459..87ad33b1f415 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 181 +#define __WMI_REVISION_ 182 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 9dde763ecfcdadc2e9d2edf850848a349e6a5d5d Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 16:51:16 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeStartBssReq Replace tSirMacAddr with cdf_mac_addr in struct sSirSmeStartBssReq. Change-Id: I76c09e0c865ada1fe53a9e4779a32b19291fbfda CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 6 +++--- core/sme/src/csr/csr_api_roam.c | 6 ++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index bae0b4c5f8f5..0bd15f70b7fc 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -557,8 +557,8 @@ typedef struct sSirSmeStartBssReq { uint16_t length; uint8_t sessionId; /* Added for BT-AMP Support */ uint16_t transactionId; /* Added for BT-AMP Support */ - tSirMacAddr bssId; /* Added for BT-AMP Support */ - tSirMacAddr selfMacAddr; /* Added for BT-AMP Support */ + struct cdf_mac_addr bssid; /* Added for BT-AMP Support */ + struct cdf_mac_addr self_macaddr; /* Added for BT-AMP Support */ uint16_t beaconInterval; /* Added for BT-AMP Support */ uint8_t dot11mode; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index a54ed927ce89..3846b8bba891 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -669,7 +669,7 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) * If session is not existed, then create a new session */ session = pe_find_session_by_bssid(mac_ctx, - sme_start_bss_req->bssId, &session_id); + sme_start_bss_req->bssid.bytes, &session_id); if (session != NULL) { lim_log(mac_ctx, LOGW, FL("Session Already exists for given BSSID")); @@ -678,7 +678,7 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) goto free; } else { session = pe_create_session(mac_ctx, - sme_start_bss_req->bssId, + sme_start_bss_req->bssid.bytes, &session_id, mac_ctx->lim.maxStation, sme_start_bss_req->bssType); if (session == NULL) { @@ -726,7 +726,7 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) sizeof(session->htConfig)); sir_copy_mac_addr(session->selfMacAddr, - sme_start_bss_req->selfMacAddr); + sme_start_bss_req->self_macaddr.bytes); /* Copy SSID to session table */ cdf_mem_copy((uint8_t *) &session->ssId, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index d4c39e4ef4b2..fdc18bd2f3a9 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14687,11 +14687,9 @@ CDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId pMsg->sessionId = sessionId; pMsg->length = sizeof(tSirSmeStartBssReq); pMsg->transactionId = 0; - cdf_mem_copy(pMsg->bssId, pParam->bssid.bytes, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssid, &pParam->bssid); /* selfMacAddr */ - cdf_mem_copy(pMsg->selfMacAddr, - pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->self_macaddr, &pSession->selfMacAddr); /* beaconInterval */ if (pBssDesc && pBssDesc->beaconInterval) wTmp = pBssDesc->beaconInterval; -- cgit v1.2.3 From d4ff8b4e79f149e6490fb5851f5af268f5196b0d Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 17:00:40 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeProbereq Replace tSirMacAddr with cdf_mac_addr in sSirSmeProbereq. Change-Id: I86622c1bca4bdcd0aad5b7a44ff490e11e8c142d CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 0bd15f70b7fc..2c5900f1c66a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1048,7 +1048,7 @@ typedef struct sSirSmeProbereq { uint16_t messageType; uint16_t length; uint8_t sessionId; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint16_t devicePasswdId; } tSirSmeProbeReq, *tpSirSmeProbeReq; -- cgit v1.2.3 From 0f63c870ea66176c297527c58106ca70eb94a5f9 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 21:31:17 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sTSMStats Replace tSirMacAddr with cdf_mac_addr in sTSMStats. Change-Id: Ib7a00874a5ad1c90ac2ab332015b136efc73cdc9 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 2c5900f1c66a..7bbc7236ec16 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1908,7 +1908,7 @@ typedef struct sSirMacESETSMIE { } tSirMacESETSMIE; typedef struct sTSMStats { uint8_t tid; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; tTrafStrmMetrics tsmMetrics; } tTSMStats, *tpTSMStats; typedef struct sEseTSMContext { -- cgit v1.2.3 From 6982d8260341d9e6f9d70de118e2f7ad4f96e7da Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 21:46:48 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirPlmReq Replace tSirMacAddr with cdf_mac_addr in sSirPlmReq. Change-Id: I21df91d980bc081af28f67a344d138b3c54eaf14 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_ioctl.c | 6 +++--- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_scan_roam.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 885817a58d00..cdf13f9cf7bb 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1510,11 +1510,11 @@ CDF_STATUS hdd_parse_plm_cmd(uint8_t *pValue, tSirPlmReq *pPlmRequest) if (ret < 0) return CDF_STATUS_E_FAILURE; - pPlmRequest->macAddr[count] = content; + pPlmRequest->mac_addr.bytes[count] = content; } - hddLog(CDF_TRACE_LEVEL_DEBUG, "MC addr " MAC_ADDRESS_STR, - MAC_ADDR_ARRAY(pPlmRequest->macAddr)); + hdd_debug("MC addr " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(pPlmRequest->mac_addr.bytes)); cmdPtr = strpbrk(cmdPtr, " "); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 7bbc7236ec16..d6a7841ebc7a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2021,7 +2021,7 @@ typedef struct sSirPlmReq { /* no of times the STA should cycle through PLM ch list */ uint8_t burstLen; tPowerdBm desiredTxPwr; /* desired tx power */ - tSirMacAddr macAddr; /* MC dest addr */ + struct cdf_mac_addr mac_addr; /* MC dest addr */ /* no of channels */ uint8_t plmNumCh; /* channel numbers */ diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 46f474eee369..699e49c65074 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3780,7 +3780,7 @@ CDF_STATUS wma_plm_start(tp_wma_handle wma, const tpSirPlmReq plm) 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); + WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->mac_addr.bytes, &cmd->dest_mac); cmd->num_chans = plm->plmNumCh; buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param); -- cgit v1.2.3 From 835366721736d1ee894f47feb30b64040e0091eb Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 16:28:05 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirTdlsDelSta Req/Rsp/Ind Replace tSirMacAddr with cdf_mac_addr in sSirTdlsDelSta Req/Rsp/Ind. Change-Id: I98264dea13b7bc596c092461da0ecf865332095e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 8 ++++---- core/mac/src/pe/lim/lim_process_tdls.c | 22 +++++++++++----------- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 4 ++-- core/sme/src/csr/csr_tdls_process.c | 16 +++++++--------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d6a7841ebc7a..3d5d6cbd9f3e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3418,8 +3418,8 @@ typedef struct sSirTdlsDelStaReq { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ /* For multi-session, for PE to locate peSession ID */ - tSirMacAddr bssid; - tSirMacAddr peerMac; + struct cdf_mac_addr bssid; + struct cdf_mac_addr peermac; } tSirTdlsDelStaReq, *tpSirSmeTdlsDelStaReq; /* TDLS Response struct PE-->SME */ typedef struct sSirTdlsDelStaRsp { @@ -3427,7 +3427,7 @@ typedef struct sSirTdlsDelStaRsp { uint16_t length; uint8_t sessionId; /* Session ID */ tSirResultCodes statusCode; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint16_t staId; } tSirTdlsDelStaRsp, *tpSirTdlsDelStaRsp; /* TDLS Delete Indication struct PE-->SME */ @@ -3435,7 +3435,7 @@ typedef struct sSirTdlsDelStaInd { uint16_t messageType; uint16_t length; uint8_t sessionId; /* Session ID */ - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint16_t staId; uint16_t reasonCode; } tSirTdlsDelStaInd, *tpSirTdlsDelStaInd; diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 7afba538ce76..a7b47eac1340 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2437,14 +2437,15 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, /* * Del STA, after Link is teardown or discovery response sent on direct link */ -static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac, tSirMacAddr peerMac, +static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac, + struct cdf_mac_addr peerMac, tpPESession psessionEntry) { tSirRetStatus status = eSIR_SUCCESS; uint16_t peerIdx = 0; tpDphHashNode pStaDs = NULL; - pStaDs = dph_lookup_hash_entry(pMac, peerMac, &peerIdx, + pStaDs = dph_lookup_hash_entry(pMac, peerMac.bytes, &peerIdx, &psessionEntry->dph.dphHashTable); if (pStaDs) { @@ -2874,7 +2875,7 @@ void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, */ static CDF_STATUS lim_send_sme_tdls_del_sta_rsp(tpAniSirGlobal pMac, uint8_t sessionId, - tSirMacAddr peerMac, + struct cdf_mac_addr peerMac, tDphHashNode *pStaDs, uint8_t status) { tSirMsgQ mmhMsg = { 0 }; @@ -2894,9 +2895,7 @@ static CDF_STATUS lim_send_sme_tdls_del_sta_rsp(tpAniSirGlobal pMac, } else pDelSta->staId = STA_INVALID_IDX; - if (peerMac) { - cdf_mem_copy(pDelSta->peerMac, peerMac, sizeof(tSirMacAddr)); - } + cdf_copy_macaddr(&pDelSta->peermac, &peerMac); pDelSta->length = sizeof(tSirTdlsDelStaRsp); pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP; @@ -2985,7 +2984,8 @@ tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, lim_log(pMac, LOG1, FL("TDLS Delete STA Request Recieved")); psessionEntry = - pe_find_session_by_bssid(pMac, pDelStaReq->bssid, &sessionId); + pe_find_session_by_bssid(pMac, pDelStaReq->bssid.bytes, + &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, FL( @@ -2993,7 +2993,7 @@ tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, ), pDelStaReq->sessionId); lim_send_sme_tdls_del_sta_rsp(pMac, pDelStaReq->sessionId, - pDelStaReq->peerMac, NULL, + pDelStaReq->peermac, NULL, eSIR_FAILURE); return eSIR_FAILURE; } @@ -3019,13 +3019,13 @@ tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, goto lim_tdls_del_sta_error; } - pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peerMac, psessionEntry); + pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peermac, psessionEntry); /* now send indication to SME-->HDD->TL to remove STA from TL */ if (pStaDs) { lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId, - pDelStaReq->peerMac, pStaDs, + pDelStaReq->peermac, pStaDs, eSIR_SUCCESS); lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry); @@ -3041,7 +3041,7 @@ tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac, lim_tdls_del_sta_error: lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId, - pDelStaReq->peerMac, NULL, eSIR_FAILURE); + pDelStaReq->peermac, NULL, eSIR_FAILURE); return eSIR_SUCCESS; } diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index eee97bae7934..c7d1517d2523 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1182,8 +1182,8 @@ lim_send_sme_tdls_del_sta_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, pSirTdlsDelStaInd->sessionId = psessionEntry->smeSessionId; /* peerMacAddr */ - cdf_mem_copy(pSirTdlsDelStaInd->peerMac, pStaDs->staAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirTdlsDelStaInd->peermac.bytes, pStaDs->staAddr, + CDF_MAC_ADDR_SIZE); /* staId */ lim_copy_u16((uint8_t *) (&pSirTdlsDelStaInd->staId), diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index cb4694279539..632356955e88 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -545,11 +545,11 @@ CDF_STATUS csr_tdls_process_del_sta(tpAniSirGlobal pMac, tSmeCmd *cmd) /* Using dialog as transactionId. This can be used to match response with request */ tdlsDelStaReq->transactionId = 0; - cdf_mem_copy(tdlsDelStaReq->bssid, - pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsDelStaReq->bssid.bytes, + pSession->pConnectBssDesc->bssId, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(tdlsDelStaReq->peerMac, - tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsDelStaReq->peermac.bytes, + tdlsDelStaCmdInfo->peerMac, CDF_MAC_ADDR_SIZE); /* Send the request to PE. */ sms_log(pMac, LOG1, @@ -717,8 +717,7 @@ CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsAddPeer); break; case eWNI_SME_TDLS_DEL_STA_RSP: - cdf_mem_copy(&roamInfo.peerMac, delStaRsp->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, &delStaRsp->peermac); roamInfo.staId = delStaRsp->staId; roamInfo.statusCode = delStaRsp->statusCode; /* @@ -733,9 +732,8 @@ CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsDelPeer); break; case eWNI_SME_TDLS_DEL_STA_IND: - cdf_mem_copy(&roamInfo.peerMac, - pSirTdlsDelStaInd->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, + &pSirTdlsDelStaInd->peermac); roamInfo.staId = pSirTdlsDelStaInd->staId; roamInfo.reasonCode = pSirTdlsDelStaInd->reasonCode; -- cgit v1.2.3 From fba8196ce53d5c52e73092779569750bf90bc819 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 19:38:00 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirTdlsAddSta Req/Rsp Replace tSirMacAddr with cdf_mac_addr in tSirTdlsAddSta Req/Rsp. Change-Id: Ie10b69ce99645f7ace3d772dc8c8de87ad86f2bc CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +++--- core/mac/src/pe/lim/lim_process_tdls.c | 21 +++++++++++---------- core/sme/inc/sme_inside.h | 4 ++-- core/sme/src/csr/csr_tdls_process.c | 29 ++++++++++++++--------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3d5d6cbd9f3e..f092bf50b845 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3351,9 +3351,9 @@ typedef struct sSirTdlsAddStaReq { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ /* For multi-session, for PE to locate peSession ID */ - tSirMacAddr bssid; + struct cdf_mac_addr bssid; eTdlsAddOper tdlsAddOper; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint16_t capability; uint8_t extn_capability[SIR_MAC_MAX_EXTN_CAP]; uint8_t supported_rates_length; @@ -3371,7 +3371,7 @@ typedef struct sSirTdlsAddStaRsp { uint16_t messageType; uint16_t length; tSirResultCodes statusCode; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint8_t sessionId; /* Session ID */ uint16_t staId; uint16_t staType; diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index a7b47eac1340..b440f1684a2b 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2379,7 +2379,7 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, tSirRetStatus status = eSIR_SUCCESS; uint16_t aid = 0; - pStaDs = dph_lookup_hash_entry(pMac, pAddStaReq->peerMac, &aid, + pStaDs = dph_lookup_hash_entry(pMac, pAddStaReq->peermac.bytes, &aid, &psessionEntry->dph.dphHashTable); if (NULL == pStaDs) { aid = lim_assign_peer_idx(pMac, psessionEntry); @@ -2388,7 +2388,7 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, lim_log(pMac, LOGE, FL("No more free AID for peer " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pAddStaReq->peerMac)); + MAC_ADDR_ARRAY(pAddStaReq->peermac.bytes)); return eSIR_FAILURE; } @@ -2396,7 +2396,7 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, SET_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, aid); lim_log(pMac, LOG1, FL("Aid = %d, for peer =" MAC_ADDRESS_STR), - aid, MAC_ADDR_ARRAY(pAddStaReq->peerMac)); + aid, MAC_ADDR_ARRAY(pAddStaReq->peermac.bytes)); pStaDs = dph_get_hash_entry(pMac, aid, &psessionEntry->dph.dphHashTable); @@ -2408,8 +2408,8 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, psessionEntry); } - pStaDs = dph_add_hash_entry(pMac, pAddStaReq->peerMac, aid, - &psessionEntry->dph.dphHashTable); + pStaDs = dph_add_hash_entry(pMac, pAddStaReq->peermac.bytes, + aid, &psessionEntry->dph.dphHashTable); if (NULL == pStaDs) { lim_log(pMac, LOGE, FL("add hash entry failed")); @@ -2490,8 +2490,8 @@ static CDF_STATUS lim_send_sme_tdls_add_sta_rsp(tpAniSirGlobal pMac, addStaRsp->bcastSig = pStaDs->ucBcastSig; } if (peerMac) { - cdf_mem_copy(addStaRsp->peerMac, - (uint8_t *) peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(addStaRsp->peermac.bytes, + (uint8_t *) peerMac, CDF_MAC_ADDR_SIZE); } if (updateSta) addStaRsp->tdlsAddOper = TDLS_OPER_UPDATE; @@ -2506,7 +2506,6 @@ static CDF_STATUS lim_send_sme_tdls_add_sta_rsp(tpAniSirGlobal pMac, lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); return CDF_STATUS_SUCCESS; - } /* @@ -2921,7 +2920,8 @@ tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac, lim_log(pMac, LOG1, FL("TDLS Add STA Request Recieved")); psessionEntry = - pe_find_session_by_bssid(pMac, pAddStaReq->bssid, &sessionId); + pe_find_session_by_bssid(pMac, pAddStaReq->bssid.bytes, + &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, FL( @@ -2963,7 +2963,8 @@ tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac, return eSIR_SUCCESS; lim_tdls_add_sta_error: lim_send_sme_tdls_add_sta_rsp(pMac, - pAddStaReq->sessionId, pAddStaReq->peerMac, + pAddStaReq->sessionId, + pAddStaReq->peermac.bytes, (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE), NULL, eSIR_FAILURE); diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index 1d5f28bdeada..4994c30a34bb 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -123,7 +123,7 @@ typedef struct TdlsLinkEstablishInfo { typedef struct TdlsAddStaInfo { eTdlsAddOper tdlsAddOper; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint16_t capability; uint8_t extnCapability[SIR_MAC_MAX_EXTN_CAP]; uint8_t supportedRatesLen; @@ -137,7 +137,7 @@ typedef struct TdlsAddStaInfo { } tTdlsAddStaCmdInfo; typedef struct TdlsDelStaInfo { - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; } tTdlsDelStaCmdInfo; /* * TDLS cmd info, CMD from SME to PE. diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index 632356955e88..72d0330e302c 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -158,8 +158,8 @@ CDF_STATUS csr_tdls_change_peer_sta(tHalHandle hHal, uint8_t sessionId, tdlsAddStaCmd->sessionId = sessionId; - cdf_mem_copy(tdlsAddStaCmdInfo->peerMac, - peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsAddStaCmdInfo->peermac.bytes, + peerMac, CDF_MAC_ADDR_SIZE); tdlsAddStaCmdInfo->capability = pstaParams->capability; tdlsAddStaCmdInfo->uapsdQueues = pstaParams->uapsd_queues; @@ -300,8 +300,8 @@ CDF_STATUS csr_tdls_add_peer_sta(tHalHandle hHal, uint8_t sessionId, tdlsAddStaCmd->sessionId = sessionId; tdlsAddStaCmdInfo->tdlsAddOper = TDLS_OPER_ADD; - cdf_mem_copy(tdlsAddStaCmdInfo->peerMac, - peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsAddStaCmdInfo->peermac.bytes, + peerMac, CDF_MAC_ADDR_SIZE); tdlsAddStaCmd->command = eSmeCommandTdlsAddPeer; tdlsAddStaCmd->u.tdlsCmd.size = @@ -336,8 +336,8 @@ CDF_STATUS csr_tdls_del_peer_sta(tHalHandle hHal, uint8_t sessionId, tdlsDelStaCmd->sessionId = sessionId; - cdf_mem_copy(tdlsDelStaCmdInfo->peerMac, - peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsDelStaCmdInfo->peermac.bytes, + peerMac, CDF_MAC_ADDR_SIZE); tdlsDelStaCmd->command = eSmeCommandTdlsDelPeer; tdlsDelStaCmd->u.tdlsCmd.size = @@ -475,11 +475,11 @@ CDF_STATUS csr_tdls_process_add_sta(tpAniSirGlobal pMac, tSmeCmd *cmd) /* Using dialog as transactionId. This can be used to match response with request */ tdlsAddStaReq->transactionId = 0; - cdf_mem_copy(tdlsAddStaReq->bssid, - pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsAddStaReq->bssid.bytes, + pSession->pConnectBssDesc->bssId, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(tdlsAddStaReq->peerMac, - tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&tdlsAddStaReq->peermac, + &tdlsAddStaCmdInfo->peermac); tdlsAddStaReq->capability = tdlsAddStaCmdInfo->capability; tdlsAddStaReq->uapsd_queues = tdlsAddStaCmdInfo->uapsdQueues; @@ -548,13 +548,13 @@ CDF_STATUS csr_tdls_process_del_sta(tpAniSirGlobal pMac, tSmeCmd *cmd) cdf_mem_copy(tdlsDelStaReq->bssid.bytes, pSession->pConnectBssDesc->bssId, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(tdlsDelStaReq->peermac.bytes, - tdlsDelStaCmdInfo->peerMac, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&tdlsDelStaReq->peermac, + &tdlsDelStaCmdInfo->peermac); /* Send the request to PE. */ sms_log(pMac, LOG1, "sending TDLS Del Sta " MAC_ADDRESS_STR " req to PE", - MAC_ADDR_ARRAY(tdlsDelStaCmdInfo->peerMac)); + MAC_ADDR_ARRAY(tdlsDelStaCmdInfo->peermac.bytes)); status = tdls_send_message(pMac, eWNI_SME_TDLS_DEL_STA_REQ, (void *)tdlsDelStaReq, sizeof(tSirTdlsDelStaReq)); @@ -695,8 +695,7 @@ CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsSendMgmt); break; case eWNI_SME_TDLS_ADD_STA_RSP: - cdf_mem_copy(&roamInfo.peerMac, addStaRsp->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, &addStaRsp->peermac); roamInfo.staId = addStaRsp->staId; roamInfo.ucastSig = addStaRsp->ucastSig; roamInfo.bcastSig = addStaRsp->bcastSig; -- cgit v1.2.3 From 906d66bb82116b8f9f237ab3e6a1971af24eecdf Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 20 Nov 2015 17:10:11 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in GtkOffload Req/Rsp Replace tSirMacAddr with cdf_mac_addr in GtkOffload Req/Rsp. Change-Id: Ib5a20b5741d08bd86cd8674d8e9724392093b706 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_cfg80211.c | 7 ++++--- core/hdd/src/wlan_hdd_power.c | 5 ++--- core/mac/inc/sir_api.h | 34 +++++++++++++++++----------------- core/sme/src/common/sme_api.c | 10 +++++----- core/wma/src/wma_features.c | 13 +++++++------ 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 838b627ae40e..7cdcb10337d6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -10297,7 +10297,8 @@ void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext, } /* Update replay counter to NL */ - cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId, + cfg80211_gtk_rekey_notify(pAdapter->dev, + pGtkOffloadGetInfoRsp->bssid.bytes, tempReplayCounter, GFP_KERNEL); } @@ -10351,8 +10352,8 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, NL80211_KCK_LEN); memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN); - memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, - &pHddStaCtx->conn_info.bssId, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid, + &pHddStaCtx->conn_info.bssId); { /* changing from big to little endian since driver * works on little endian format diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index be764693bf76..bf98cdbb093d 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -135,9 +135,8 @@ static void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, bool fenable) } else { if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) - && (0 == - memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId, - &pHddStaCtx->conn_info.bssId, CDF_MAC_ADDR_SIZE)) + && (cdf_is_macaddr_equal(&pHddStaCtx->gtkOffloadReqParams.bssid, + &pHddStaCtx->conn_info.bssId)) && (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags)) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index f092bf50b845..ecff9145eff2 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3090,9 +3090,25 @@ typedef struct { uint8_t aKCK[16]; /* Key confirmation key */ uint8_t aKEK[16]; /* key encryption key */ uint64_t ullKeyReplayCounter; /* replay counter */ - tSirMacAddr bssId; + struct cdf_mac_addr bssid; } tSirGtkOffloadParams, *tpSirGtkOffloadParams; +/*--------------------------------------------------------------------------- +* WMA_GTK_OFFLOAD_GETINFO_REQ +*--------------------------------------------------------------------------*/ +typedef struct { + uint16_t mesgType; + uint16_t mesgLen; + + uint32_t ulStatus; /* success or failure */ + uint64_t ullKeyReplayCounter; /* current replay counter value */ + uint32_t ulTotalRekeyCount; /* total rekey attempts */ + uint32_t ulGTKRekeyCount; /* successful GTK rekeys */ + uint32_t ulIGTKRekeyCount; /* successful iGTK rekeys */ + struct cdf_mac_addr bssid; +} tSirGtkOffloadGetInfoRspParams, *tpSirGtkOffloadGetInfoRspParams; +#endif /* WLAN_FEATURE_GTK_OFFLOAD */ + /** * struct sir_wifi_start_log - Structure to store the params sent to start/ * stop logging @@ -3273,22 +3289,6 @@ struct sir_dual_mac_config_resp { uint32_t status; }; -/*--------------------------------------------------------------------------- -* WMA_GTK_OFFLOAD_GETINFO_REQ -*--------------------------------------------------------------------------*/ -typedef struct { - uint16_t mesgType; - uint16_t mesgLen; - - uint32_t ulStatus; /* success or failure */ - uint64_t ullKeyReplayCounter; /* current replay counter value */ - uint32_t ulTotalRekeyCount; /* total rekey attempts */ - uint32_t ulGTKRekeyCount; /* successful GTK rekeys */ - uint32_t ulIGTKRekeyCount; /* successful iGTK rekeys */ - tSirMacAddr bssId; -} tSirGtkOffloadGetInfoRspParams, *tpSirGtkOffloadGetInfoRspParams; -#endif /* WLAN_FEATURE_GTK_OFFLOAD */ - #ifdef WLAN_WAKEUP_EVENTS /*--------------------------------------------------------------------------- tSirWakeReasonInd diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 54ac7f07500e..7161c9feced2 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -5899,8 +5899,8 @@ CDF_STATUS sme_set_gtk_offload(tHalHandle hHal, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pGtkOffload->bssid, + &pSession->connectedProfile.bssid); *request_buf = *pGtkOffload; @@ -5941,7 +5941,7 @@ CDF_STATUS sme_get_gtk_offload(tHalHandle hHal, if (NULL == pSession) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: Session not found ", __func__); + "%s: Session not found", __func__); return CDF_STATUS_E_FAILURE; } @@ -5952,8 +5952,8 @@ CDF_STATUS sme_get_gtk_offload(tHalHandle hHal, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(request_buf->bssId, pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&request_buf->bssid, + &pSession->connectedProfile.bssid); msg.type = WMA_GTK_OFFLOAD_GETINFO_REQ; msg.reserved = 0; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index f8f2736e39d9..cd8e7d3521a8 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4675,7 +4675,7 @@ int wma_gtk_offload_status_event(void *handle, uint8_t *event, cdf_mem_copy(&resp->ullKeyReplayCounter, &status->replay_counter, GTK_REPLAY_COUNTER_BYTES); - cdf_mem_copy(resp->bssId, bssid, IEEE80211_ADDR_LEN); + cdf_mem_copy(resp->bssid.bytes, bssid, IEEE80211_ADDR_LEN); #ifdef IGTK_OFFLOAD /* TODO: Is the refresh count same for GTK and IGTK? */ @@ -4792,15 +4792,16 @@ CDF_STATUS wma_process_gtk_offload_req(tp_wma_handle wma, 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); + if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes); status = CDF_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); + WMA_LOGE("invalid vdev_id %d for %pM", vdev_id, + params->bssid.bytes); status = CDF_STATUS_E_INVAL; goto out; } @@ -4845,8 +4846,8 @@ CDF_STATUS wma_process_gtk_offload_getinfo_req(tp_wma_handle wma, 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); + if (!wma_find_vdev_by_bssid(wma, params->bssid.bytes, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", params->bssid.bytes); status = CDF_STATUS_E_INVAL; goto out; } -- cgit v1.2.3 From 003f0548016482e3eca524ff6d96b1ea61c11f59 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 20 Nov 2015 17:39:24 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirRcvFltPkt Replace tSirMacAddr with cdf_mac_addr in tSirRcvFltPkt group of structures. 1. tSirRcvPktFilterCfgType 2. tSirRcvFltPktClearParam 3. tSirRcvFltMcAddrList 4. tSirRcvFltPktMatchRsp Change-Id: I7c0dabc5c4643eee6dfe69dad76fb7363b40dce6 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_ioctl.c | 4 ++-- core/hdd/src/wlan_hdd_power.c | 11 +++++------ core/mac/inc/sir_api.h | 16 ++++++++-------- core/sme/src/common/sme_api.c | 39 ++++++++++++++++++--------------------- core/wma/src/wma_features.c | 29 ++++++++++++++++------------- 5 files changed, 49 insertions(+), 50 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index cdf13f9cf7bb..c593a6a00d1a 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5757,14 +5757,14 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, for (i = 0; i < adapter->mc_addr_list.mc_cnt; i++) { if (!memcmp(adapter->mc_addr_list.addr[i], &pattern, 1)) { - memcpy(filter->multicastAddr[i], + memcpy(filter->multicastAddr[i].bytes, adapter->mc_addr_list.addr[i], sizeof(adapter->mc_addr_list.addr[i])); filter->ulMulticastAddrCnt++; hdd_info("%s RX filter : addr =" MAC_ADDRESS_STR, action ? "setting" : "clearing", - MAC_ADDR_ARRAY(filter->multicastAddr[i])); + MAC_ADDR_ARRAY(filter->multicastAddr[i].bytes)); } } /* Set rx filter */ diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index bf98cdbb093d..df5620b51252 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -923,16 +923,15 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) pAdapter->mc_addr_list.mc_cnt; for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) { - memcpy(pMulticastAddrs->multicastAddr[i], + memcpy(pMulticastAddrs->multicastAddr[i].bytes, pAdapter->mc_addr_list.addr[i], sizeof(pAdapter->mc_addr_list. addr[i])); - hddLog(CDF_TRACE_LEVEL_INFO, - "%s: %s multicast filter: addr =" - MAC_ADDRESS_STR, __func__, + hdd_info("%s multicast filter: addr =" + MAC_ADDRESS_STR, set ? "setting" : "clearing", MAC_ADDR_ARRAY(pMulticastAddrs-> - multicastAddr[i])); + multicastAddr[i].bytes)); } /* Set multicast filter */ sme_8023_multicast_list(hHal, pAdapter->sessionId, @@ -945,7 +944,7 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) pAdapter->mc_addr_list.mc_cnt; for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) { - memcpy(pMulticastAddrs->multicastAddr[i], + memcpy(pMulticastAddrs->multicastAddr[i].bytes, pAdapter->mc_addr_list.addr[i], sizeof(pAdapter->mc_addr_list. addr[i])); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index ecff9145eff2..459499f441a0 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3026,8 +3026,8 @@ typedef struct sSirRcvPktFilterCfg { eSirReceivePacketFilterType filterType; uint32_t numFieldParams; uint32_t coalesceTime; - tSirMacAddr selfMacAddr; - tSirMacAddr bssId; /* Bssid of the connected AP */ + struct cdf_mac_addr self_macaddr; + struct cdf_mac_addr bssid; /* Bssid of the connected AP */ tSirRcvPktFilterFieldParams paramsData[SIR_MAX_NUM_TESTS_PER_FILTER]; } tSirRcvPktFilterCfgType, *tpSirRcvPktFilterCfgType; @@ -3046,7 +3046,7 @@ typedef struct sSirRcvFltPktMatchRsp { /* Success or Failure */ uint32_t status; tSirRcvFltPktMatchCnt filterMatchCnt[SIR_MAX_NUM_FILTERS]; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; } tSirRcvFltPktMatchRsp, *tpSirRcvFltPktMatchRsp; /* */ @@ -3055,8 +3055,8 @@ typedef struct sSirRcvFltPktMatchRsp { typedef struct sSirRcvFltPktClearParam { uint32_t status; /* only valid for response message */ uint8_t filterId; - tSirMacAddr selfMacAddr; - tSirMacAddr bssId; + struct cdf_mac_addr self_macaddr; + struct cdf_mac_addr bssid; } tSirRcvFltPktClearParam, *tpSirRcvFltPktClearParam; /* */ @@ -3064,9 +3064,9 @@ typedef struct sSirRcvFltPktClearParam { /* */ typedef struct sSirRcvFltMcAddrList { uint32_t ulMulticastAddrCnt; - tSirMacAddr multicastAddr[SIR_MAX_NUM_MULTICAST_ADDRESS]; - tSirMacAddr selfMacAddr; - tSirMacAddr bssId; + struct cdf_mac_addr multicastAddr[SIR_MAX_NUM_MULTICAST_ADDRESS]; + struct cdf_mac_addr self_macaddr; + struct cdf_mac_addr bssid; uint8_t action; } tSirRcvFltMcAddrList, *tpSirRcvFltMcAddrList; #endif /* WLAN_FEATURE_PACKET_FILTERING */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 7161c9feced2..948f8bb74e71 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -7412,7 +7412,7 @@ CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: " "ulMulticastAddrCnt=%d, multicastAddr[0]=%p", __func__, pMulticastAddrs->ulMulticastAddrCnt, - pMulticastAddrs->multicastAddr[0]); + pMulticastAddrs->multicastAddr[0].bytes); /* *Find the connected Infra / P2P_client connected session @@ -7449,10 +7449,9 @@ CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, cdf_mem_copy(request_buf, pMulticastAddrs, sizeof(tSirRcvFltMcAddrList)); - cdf_mem_copy(request_buf->selfMacAddr, pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); - cdf_mem_copy(request_buf->bssId, pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&request_buf->self_macaddr, &pSession->selfMacAddr); + cdf_copy_macaddr(&request_buf->bssid, + &pSession->connectedProfile.bssid); msg.type = WMA_8023_MULTICAST_LIST_REQ; msg.reserved = 0; @@ -7503,11 +7502,10 @@ CDF_STATUS sme_receive_filter_set_filter(tHalHandle hHal, return CDF_STATUS_E_FAILURE; } - cdf_mem_copy(pRcvPktFilterCfg->selfMacAddr, pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); - cdf_mem_copy(pRcvPktFilterCfg->bssId, - pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pRcvPktFilterCfg->self_macaddr, + &pSession->selfMacAddr); + cdf_copy_macaddr(&pRcvPktFilterCfg->bssid, + &pSession->connectedProfile.bssid); cdf_mem_copy(request_buf, pRcvPktFilterCfg, allocSize); msg.type = WMA_RECEIVE_FILTER_SET_FILTER_REQ; @@ -7578,6 +7576,12 @@ CDF_STATUS sme_receive_filter_clear_filter(tHalHandle hHal, CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: filterId = %d", __func__, pRcvFltPktClearParam->filterId); + if (NULL == pSession) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Session Not found", __func__); + return CDF_STATUS_E_FAILURE; + } + request_buf = cdf_mem_malloc(sizeof(tSirRcvFltPktClearParam)); if (NULL == request_buf) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, @@ -7585,18 +7589,11 @@ CDF_STATUS sme_receive_filter_clear_filter(tHalHandle hHal, "Clear Filter request", __func__); return CDF_STATUS_E_NOMEM; } - if (NULL == pSession) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "%s: Session Not find ", __func__); - cdf_mem_free(request_buf); - return CDF_STATUS_E_FAILURE; - } - cdf_mem_copy(pRcvFltPktClearParam->selfMacAddr, - pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); - cdf_mem_copy(pRcvFltPktClearParam->bssId, - pSession->connectedProfile.bssid.bytes, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pRcvFltPktClearParam->self_macaddr, + &pSession->selfMacAddr); + cdf_copy_macaddr(&pRcvFltPktClearParam->bssid, + &pSession->connectedProfile.bssid); cdf_mem_copy(request_buf, pRcvFltPktClearParam, sizeof(tSirRcvFltPktClearParam)); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index cd8e7d3521a8..79005414eb3b 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4402,9 +4402,10 @@ int wma_process_receive_filter_set_filter_req(tp_wma_handle wma, uint8_t vdev_id; /* Get the vdev id */ - if (!wma_find_vdev_by_bssid(wma, rcv_filter_param->bssId, &vdev_id)) { + if (!wma_find_vdev_by_bssid(wma, + rcv_filter_param->bssid.bytes, &vdev_id)) { WMA_LOGE("vdev handle is invalid for %pM", - rcv_filter_param->bssId); + rcv_filter_param->bssid.bytes); return -EINVAL; } @@ -4428,8 +4429,10 @@ int wma_process_receive_filter_clear_filter_req(tp_wma_handle wma, uint8_t vdev_id; /* Get the vdev id */ - if (!wma_find_vdev_by_bssid(wma, rcv_clear_param->bssId, &vdev_id)) { - WMA_LOGE("vdev handle is invalid for %pM", rcv_clear_param->bssId); + if (!wma_find_vdev_by_bssid(wma, + rcv_clear_param->bssid.bytes, &vdev_id)) { + WMA_LOGE("vdev handle is invalid for %pM", + rcv_clear_param->bssid.bytes); return -EINVAL; } @@ -4542,7 +4545,8 @@ CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, * Return: 0 for success or error code */ static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id, - tSirMacAddr multicastAddr, bool clearList) + struct cdf_mac_addr multicast_addr, + bool clearList) { WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd; wmi_buf_t buf; @@ -4564,7 +4568,7 @@ static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id, 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); + WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr); err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, sizeof(*cmd), WMI_SET_MCASTBCAST_FILTER_CMDID); @@ -4573,11 +4577,10 @@ static int wma_add_clear_mcbc_filter(tp_wma_handle wma_handle, uint8_t vdev_id, cdf_mem_free(buf); return -EIO; } - WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d\n", + WMA_LOGD("Action:%d; vdev_id:%d; clearList:%d", 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]); + WMA_LOGD("MCBC MAC Addr: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(multicast_addr.bytes)); return 0; } @@ -4599,10 +4602,10 @@ CDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, return CDF_STATUS_E_FAILURE; } - if (!wma_find_vdev_by_addr - (wma_handle, mcbc_param->selfMacAddr, &vdev_id)) { + if (!wma_find_vdev_by_addr(wma_handle, + mcbc_param->self_macaddr.bytes, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for %pM", __func__, - mcbc_param->bssId); + mcbc_param->bssid.bytes); return CDF_STATUS_E_FAILURE; } /* set mcbc_param->action to clear MCList and reset -- cgit v1.2.3 From c9a5f01c0adc13428051f5b7e184325f3f9b33d5 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 15:10:27 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirWlanExcludeUnencryptParam Replace tSirMacAddr with cdf_mac_addr in sSirWlanExcludeUnencryptParam Change-Id: Ie6b3172757826d579ac44027b1d023be62b3292f CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_send_messages.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 459499f441a0..b5be232dac15 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3482,7 +3482,7 @@ typedef struct sSirSmeCandidateFoundInd { #ifdef WLAN_FEATURE_11W typedef struct sSirWlanExcludeUnencryptParam { bool excludeUnencrypt; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; } tSirWlanExcludeUnencryptParam, *tpSirWlanExcludeUnencryptParam; #endif diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c index e47bf2fbc3a7..3e6f53b6ad76 100644 --- a/core/mac/src/pe/lim/lim_send_messages.c +++ b/core/mac/src/pe/lim/lim_send_messages.c @@ -833,7 +833,8 @@ tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac, } pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc; - sir_copy_mac_addr(pExcludeUnencryptParam->bssId, psessionEntry->bssId); + cdf_mem_copy(pExcludeUnencryptParam->bssid.bytes, psessionEntry->bssId, + CDF_MAC_ADDR_SIZE); msgQ.type = WMA_EXCLUDE_UNENCRYPTED_IND; msgQ.reserved = 0; -- cgit v1.2.3 From e2d1c1a5c7f31e5eb63272cbe849959a884e9cce Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 15:33:42 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirTdlsEventnotify Replace tSirMacAddr with cdf_mac_addr in sSirTdlsEventnotify Change-Id: Ia78eeffd98821ea075df0838dc7ff4367ce0ca36 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/sme/src/csr/csr_tdls_process.c | 15 ++++++--------- core/wma/src/wma_features.c | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b5be232dac15..b3f5418c5f3e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3453,7 +3453,7 @@ typedef struct sSirMgmtTxCompletionInd { typedef struct sSirTdlsEventnotify { uint8_t sessionId; - tSirMacAddr peerMac; + struct cdf_mac_addr peermac; uint16_t messageType; uint32_t peer_reason; } tSirTdlsEventnotify; diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index 72d0330e302c..802f7cb6e00e 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -770,39 +770,36 @@ CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, csr_tdls_remove_sme_cmd(pMac, eSmeCommandTdlsLinkEstablish); break; case eWNI_SME_TDLS_SHOULD_DISCOVER: - cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, &tevent->peermac); roamInfo.reasonCode = tevent->peer_reason; CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: eWNI_SME_TDLS_SHOULD_DISCOVER for peer mac: " MAC_ADDRESS_STR " peer_reason: %d", - __func__, MAC_ADDR_ARRAY(tevent->peerMac), + __func__, MAC_ADDR_ARRAY(tevent->peermac.bytes), tevent->peer_reason); csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, 0, eCSR_ROAM_TDLS_STATUS_UPDATE, eCSR_ROAM_RESULT_TDLS_SHOULD_DISCOVER); break; case eWNI_SME_TDLS_SHOULD_TEARDOWN: - cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, &tevent->peermac); roamInfo.reasonCode = tevent->peer_reason; CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: eWNI_SME_TDLS_SHOULD_TEARDOWN for peer mac: " MAC_ADDRESS_STR " peer_reason: %d", - __func__, MAC_ADDR_ARRAY(tevent->peerMac), + __func__, MAC_ADDR_ARRAY(tevent->peermac.bytes), tevent->peer_reason); csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, 0, eCSR_ROAM_TDLS_STATUS_UPDATE, eCSR_ROAM_RESULT_TDLS_SHOULD_TEARDOWN); break; case eWNI_SME_TDLS_PEER_DISCONNECTED: - cdf_mem_copy(&roamInfo.peerMac, tevent->peerMac, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, &tevent->peermac); roamInfo.reasonCode = tevent->peer_reason; CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "%s: eWNI_SME_TDLS_PEER_DISCONNECTED for peer mac: " MAC_ADDRESS_STR " peer_reason: %d", - __func__, MAC_ADDR_ARRAY(tevent->peerMac), + __func__, MAC_ADDR_ARRAY(tevent->peermac.bytes), tevent->peer_reason); csr_roam_call_callback(pMac, tevent->sessionId, &roamInfo, 0, eCSR_ROAM_TDLS_STATUS_UPDATE, diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 79005414eb3b..30fa789fbc36 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -6319,7 +6319,7 @@ int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len) tdls_event->sessionId = peer_event->vdev_id; WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_event->peer_macaddr, - tdls_event->peerMac); + tdls_event->peermac.bytes); switch (peer_event->peer_status) { case WMI_TDLS_SHOULD_DISCOVER: @@ -6369,7 +6369,7 @@ int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len) WMA_LOGD("%s: sending msg to umac, messageType: 0x%x, " "for peer: %pM, reason: %d, smesessionId: %d", - __func__, tdls_event->messageType, tdls_event->peerMac, + __func__, tdls_event->messageType, tdls_event->peermac.bytes, tdls_event->peer_reason, tdls_event->sessionId); wma_send_msg(wma, tdls_event->messageType, (void *)tdls_event, 0); -- cgit v1.2.3 From d837ce0d7f96f543676905973939c11fdad9f6e6 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 22:44:36 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirDelPeriodicTxPtrn Replace tSirMacAddr with cdf_mac_addr in sSirDelPeriodicTxPtrn. Change-Id: I0445b5c7ec7d1e361b5ab7d72d2c607c6b8121c0 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_cfg80211.c | 5 ++--- core/hdd/src/wlan_hdd_debugfs.c | 4 ++-- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 7cdcb10337d6..3ab1dbe003e6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3679,9 +3679,8 @@ wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, return -ENOMEM; } - cdf_mem_copy(del_req->macAddress, adapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); - hddLog(LOG1, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->macAddress)); + cdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent); + hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes)); del_req->ucPtrnId = pattern_id; hddLog(LOG1, FL("Request Id: %u Pattern id: %d"), request_id, del_req->ucPtrnId); diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c index f4732d546dd2..54259162475f 100644 --- a/core/hdd/src/wlan_hdd_debugfs.c +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -405,8 +405,8 @@ static ssize_t __wcnss_patterngen_write(struct file *file, } delPeriodicTxPtrnParams->ucPtrnId = pattern_idx; delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; - cdf_mem_copy(delPeriodicTxPtrnParams->macAddress, - pAdapter->macAddressCurrent.bytes, 6); + cdf_copy_macaddr(&delPeriodicTxPtrnParams->mac_address, + &pAdapter->macAddressCurrent); /* Delete pattern */ status = sme_del_periodic_tx_ptrn(pHddCtx->hHal, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b3f5418c5f3e..41c3de92b291 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3685,7 +3685,7 @@ typedef struct sSirAddPeriodicTxPtrn { typedef struct sSirDelPeriodicTxPtrn { /* MAC Address for the adapter */ - tSirMacAddr macAddress; + struct cdf_mac_addr mac_address; /* Bitmap of pattern IDs that need to be deleted */ uint32_t ucPatternIdBitmap; uint8_t ucPtrnId; /* Pattern ID */ diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 30fa789fbc36..74ede3e6d92d 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5213,10 +5213,10 @@ CDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle, return CDF_STATUS_E_NOMEM; } if (!wma_find_vdev_by_addr(wma_handle, - pDelPeriodicTxPtrnParams->macAddress, + pDelPeriodicTxPtrnParams->mac_address.bytes, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for %pM", __func__, - pDelPeriodicTxPtrnParams->macAddress); + pDelPeriodicTxPtrnParams->mac_address.bytes); cdf_nbuf_free(wmi_buf); return CDF_STATUS_E_INVAL; } -- cgit v1.2.3 From 92f68ebe74b86ae89cff81ac6d73219e012dc2de Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 18 Nov 2015 22:59:52 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirAddPeriodicTxPtrn Replace tSirMacAddr with cdf_mac_addr in sSirAddPeriodicTxPtrn. Change-Id: Idc7db873b0b1d5088465511eb7852fee40339c49 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_cfg80211.c | 12 ++++++------ core/hdd/src/wlan_hdd_debugfs.c | 4 ++-- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3ab1dbe003e6..75944d45d1b7 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3559,14 +3559,14 @@ wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, hddLog(LOGE, FL("attr source mac address failed")); goto fail; } - nla_memcpy(add_req->macAddress, tb[PARAM_SRC_MAC_ADDR], + nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR], CDF_MAC_ADDR_SIZE); hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR, - MAC_ADDR_ARRAY(add_req->macAddress)); + MAC_ADDR_ARRAY(add_req->mac_address.bytes)); - if (memcmp(add_req->macAddress, adapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE)) { - hddLog(LOGE, FL("input src mac address and connected ap bssid are different")); + if (!cdf_is_macaddr_equal(&add_req->mac_address, + &adapter->macAddressCurrent)) { + hdd_err("input src mac address and connected ap bssid are different"); goto fail; } @@ -3596,7 +3596,7 @@ wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx, len = 0; cdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, CDF_MAC_ADDR_SIZE); len += CDF_MAC_ADDR_SIZE; - cdf_mem_copy(&add_req->ucPattern[len], add_req->macAddress, + cdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes, CDF_MAC_ADDR_SIZE); len += CDF_MAC_ADDR_SIZE; cdf_mem_copy(&add_req->ucPattern[len], ð_type, 2); diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c index 54259162475f..7cb79d309206 100644 --- a/core/hdd/src/wlan_hdd_debugfs.c +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -473,8 +473,8 @@ static ssize_t __wcnss_patterngen_write(struct file *file, addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; - cdf_mem_copy(addPeriodicTxPtrnParams->macAddress, - pAdapter->macAddressCurrent.bytes, 6); + cdf_copy_macaddr(&addPeriodicTxPtrnParams->mac_address, + &pAdapter->macAddressCurrent); /* Extract the pattern */ for (i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 41c3de92b291..5278c2b76e40 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3676,7 +3676,7 @@ typedef struct sSirLinkSpeedInfo { typedef struct sSirAddPeriodicTxPtrn { /* MAC Address for the adapter */ - tSirMacAddr macAddress; + struct cdf_mac_addr mac_address; uint8_t ucPtrnId; /* Pattern ID */ uint16_t ucPtrnSize; /* Pattern size */ uint32_t usPtrnIntervalMs; /* In msec */ diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 74ede3e6d92d..9c8e23917232 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5142,10 +5142,10 @@ CDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle, return CDF_STATUS_E_NOMEM; } if (!wma_find_vdev_by_addr(wma_handle, - pAddPeriodicTxPtrnParams->macAddress, + pAddPeriodicTxPtrnParams->mac_address.bytes, &vdev_id)) { WMA_LOGE("%s: Failed to find vdev id for %pM", __func__, - pAddPeriodicTxPtrnParams->macAddress); + pAddPeriodicTxPtrnParams->mac_address.bytes); cdf_nbuf_free(wmi_buf); return CDF_STATUS_E_INVAL; } -- cgit v1.2.3 From a6d668dc91f9326f3e618f57012c0834c7341fbc Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 19 Nov 2015 14:31:14 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirLinkSpeedInfo Replace tSirMacAddr with cdf_mac_addr in sSirLinkSpeedInfo Change-Id: Ieaac1d3bb7f632eeaa848e19dadb4f3013a272e4 CRs-Fixed: 898864 --- core/hdd/inc/wlan_hdd_wext.h | 2 +- core/hdd/src/wlan_hdd_hostapd.c | 8 ++++---- core/hdd/src/wlan_hdd_wext.c | 10 ++++------ core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 4 ++-- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 7bb8606eeac1..0636c3262fe4 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -345,7 +345,7 @@ extern int hdd_priv_get_data(struct iw_point *p_priv_data, extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len); extern CDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, - tSirMacAddr macAddress); + struct cdf_mac_addr mac_address); void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter); uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index fadaeddce7f1..357c6be68f7e 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -5239,7 +5239,7 @@ int __iw_get_softap_linkspeed(struct net_device *dev, char *pLinkSpeed = (char *)extra; uint32_t link_speed = 0; int len = sizeof(uint32_t) + 1; - tSirMacAddr macAddress; + struct cdf_mac_addr macAddress; char pmacAddress[MAC_ADDRESS_STR_LEN + 1]; CDF_STATUS status = CDF_STATUS_E_FAILURE; int rc, valid, i; @@ -5261,7 +5261,7 @@ int __iw_get_softap_linkspeed(struct net_device *dev, } pmacAddress[MAC_ADDRESS_STR_LEN] = '\0'; - if (!mac_pton(pmacAddress, macAddress)) { + if (!mac_pton(pmacAddress, macAddress.bytes)) { hddLog(LOGE, FL("String to Hex conversion Failed")); return -EINVAL; } @@ -5275,8 +5275,8 @@ int __iw_get_softap_linkspeed(struct net_device *dev, (!cdf_is_macaddr_broadcast (&pHostapdAdapter->aStaInfo[i].macAddrSTA))) { cdf_copy_macaddr( - (struct cdf_mac_addr *) macAddress, - &pHostapdAdapter->aStaInfo[i]. + &macAddress, + &pHostapdAdapter->aStaInfo[i]. macAddrSTA); status = CDF_STATUS_SUCCESS; break; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 2448ddf5605a..e1983bd8a1ff 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1336,7 +1336,7 @@ hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext) * otherwise a CDF_STATUS_E_* error. */ CDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, - tSirMacAddr macAddress) { + struct cdf_mac_addr macAddress) { CDF_STATUS status; unsigned long rc; struct linkspeedContext context; @@ -1356,8 +1356,7 @@ CDF_STATUS wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter, context.pAdapter = pAdapter; context.magic = LINK_CONTEXT_MAGIC; - cdf_mem_copy(linkspeed_req->peer_macaddr, macAddress, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&linkspeed_req->peer_macaddr, &macAddress); status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter), linkspeed_req, &context, hdd_get_link_speed_cb); @@ -1426,10 +1425,9 @@ int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed) *link_speed = 0; } else { CDF_STATUS status; - tSirMacAddr bssid; + struct cdf_mac_addr bssid; - cdf_mem_copy(bssid, hdd_stactx->conn_info.bssId.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId); status = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid); if (!CDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 5278c2b76e40..f4a48b6320d7 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3670,7 +3670,7 @@ typedef struct sSirChAvoidUpdateReq { typedef struct sSirLinkSpeedInfo { /* MAC Address for the peer */ - tSirMacAddr peer_macaddr; + struct cdf_mac_addr peer_macaddr; uint32_t estLinkSpeed; /* Linkspeed from firmware */ } tSirLinkSpeedInfo, *tpSirLinkSpeedInfo; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 9c8e23917232..32b3bc4f356e 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -959,12 +959,12 @@ CDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed) (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, + WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes, &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, + __func__, pLinkSpeed->peer_macaddr.bytes, cmd->peer_macaddr.mac_addr31to0, cmd->peer_macaddr.mac_addr47to32); -- cgit v1.2.3 From 2a85ce72a20595fe7990d93b26a2b05fb2e2a162 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 17 Sep 2015 11:06:07 -0700 Subject: qcacld-3.0: Add support for telescopic PNO This is a qcacld-2.0 to qcacld-3.0 propagation. QCACLD firmware already addresses power concern during PNO scanning by extending fast_scan_period, slow_scan_period and fast_scan_max_cycles configuration which need to be set by the host driver. Add the host driver support to do the same. Description: 1. fast_scan_period: This is the fast PNO scan period. The scan interval time sent down by the supplicant is assigned to this. 2. fast_scan_max_cycles: This parameter tells firmware to switch from fast to slow scan period after this many number of fast_scan_periods has elapsed. 3. slow_scan_period: This is slow PNO scan period with which scan happens less frequently to save power. Once the FW switches from fast to slow period, it remains in slow scan period until next PNO Start. cfg.ini items: 1. Repurpose gPNOScanTimerRepeatValue to fast_scan_max_cycles. 2. Introduce new cfg.ini gPNOSlowScanMultiplier to act as multiplier of fast_scan_period. Change-Id: I453f09d42be3228ecc9c5023eca26eae1e589d6a CRs-Fixed: 902381 --- core/hdd/inc/wlan_hdd_cfg.h | 8 ++++++- core/hdd/inc/wlan_hdd_main.h | 6 ------ core/hdd/src/wlan_hdd_cfg.c | 10 +++++++++ core/hdd/src/wlan_hdd_scan.c | 51 ++++++++++++++++---------------------------- core/hdd/src/wlan_hdd_wext.c | 49 ------------------------------------------ core/mac/inc/sir_api.h | 30 +++++++++++++++----------- core/wma/src/wma_scan_roam.c | 13 ++++++----- 7 files changed, 59 insertions(+), 108 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index d90e46a77737..56522889e4c4 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1783,9 +1783,14 @@ typedef enum { #define CFG_PNO_SCAN_SUPPORT_DEFAULT (1) #define CFG_PNO_SCAN_TIMER_REPEAT_VALUE "gPNOScanTimerRepeatValue" -#define CFG_PNO_SCAN_TIMER_REPEAT_VALUE_DEFAULT (6) +#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_AMSDU_SUPPORT_IN_AMPDU_NAME "gAmsduSupportInAMPDU" @@ -3127,6 +3132,7 @@ struct hdd_config { #ifdef FEATURE_WLAN_SCAN_PNO bool configPNOScanSupport; uint32_t configPNOScanTimerRepeatValue; + uint32_t pno_slow_scan_multiplier; #endif uint8_t isAmsduSupportInAMPDU; uint8_t nSelect5GHzMargin; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 45079ecc7d9b..48a27c97e7ea 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -224,12 +224,6 @@ #define GTK_OFFLOAD_DISABLE 1 #endif -#ifdef FEATURE_WLAN_SCAN_PNO -#define HDD_PNO_SCAN_TIMERS_SET_ONE 1 -/* value should not be greater than PNO_MAX_SCAN_TIMERS */ -#define HDD_PNO_SCAN_TIMERS_SET_MULTIPLE 6 -#endif - #define MAX_USER_COMMAND_SIZE 4096 #define HDD_MIN_TX_POWER (-100) /* minimum tx power */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 434c45916432..b0d7e88e7ae3 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -2541,6 +2541,13 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, + struct hdd_config, 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_AMSDU_SUPPORT_IN_AMPDU_NAME, WLAN_PARAM_Integer, struct hdd_config, isAmsduSupportInAMPDU, @@ -4602,6 +4609,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [configPNOScanTimerRepeatValue] Value = [%u] ", pHddCtx->config->configPNOScanTimerRepeatValue); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gPNOSlowScanMultiplier] Value = [%u] ", + pHddCtx->config->pno_slow_scan_multiplier); #endif #ifdef FEATURE_WLAN_TDLS CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 4e155d0d2121..99b6db2b1411 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -2029,7 +2029,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, tpSirPNOScanReq pPnoRequest = NULL; hdd_context_t *pHddCtx; tHalHandle hHal; - uint32_t i, indx, num_ch, tempInterval, j; + uint32_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 }; uint32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN; @@ -2237,43 +2237,28 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, pPnoRequest->us5GProbeTemplateLen); } - /* Driver gets only one time interval which is hardcoded in - * supplicant for 10000ms. Taking power consumption into account 6 timers - * will be used, Timervalue is increased exponentially i.e 10,20,40, - * 80,160,320 secs. And number of scan cycle for each timer - * is configurable through INI param gPNOScanTimerRepeatValue. - * If it is set to 0 only one timer will be used and PNO scan cycle - * will be repeated after each interval specified by supplicant - * till PNO is disabled. + /* + * 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. */ - if (0 == pHddCtx->config->configPNOScanTimerRepeatValue) - pPnoRequest->scanTimers.ucScanTimersCount = - HDD_PNO_SCAN_TIMERS_SET_ONE; - else - pPnoRequest->scanTimers.ucScanTimersCount = - HDD_PNO_SCAN_TIMERS_SET_MULTIPLE; + pPnoRequest->fast_scan_period = request->interval; + pPnoRequest->fast_scan_max_cycles = + config->configPNOScanTimerRepeatValue; + pPnoRequest->slow_scan_period = + config->pno_slow_scan_multiplier * + pPnoRequest->fast_scan_period; - tempInterval = (request->interval) / 1000; - hddLog(LOG1, - FL("Base scan interval = %d PNOScanTimerRepeatValue = %d"), - tempInterval, pHddCtx->config->configPNOScanTimerRepeatValue); - for (i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++) { - pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat = - pHddCtx->config->configPNOScanTimerRepeatValue; - pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = - tempInterval; - tempInterval *= 2; - } - /* Repeat last timer until pno disabled. */ - pPnoRequest->scanTimers.aTimerValues[i - 1].uTimerRepeat = 0; + hdd_info("Base scan interval: %d sec PNOScanTimerRepeatValue: %d", + (request->interval / 1000), + config->configPNOScanTimerRepeatValue); pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE; - hddLog(LOG1, - FL("SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d"), - pAdapter->sessionId, pPnoRequest->enable, - pPnoRequest->modePNO, - pPnoRequest->scanTimers.ucScanTimersCount); + hdd_info("SessionId %d, enable %d, modePNO %d", + pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO); status = sme_set_preferred_network_list(WLAN_HDD_GET_HAL_CTX(pAdapter), pPnoRequest, diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index e1983bd8a1ff..153663ee8b0c 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -9256,55 +9256,6 @@ static int __iw_set_pno(struct net_device *dev, ptr += offset; } /* For ucNetworkCount */ - params = sscanf(ptr, "%hhu %n", - &(request.scanTimers.ucScanTimersCount), &offset); - - /* Read the scan timers */ - if ((1 == params) && (request.scanTimers.ucScanTimersCount > 0)) { - ptr += offset; - - hdd_notice("Scan timer count %d offset %d", - request.scanTimers.ucScanTimersCount, offset); - - if (SIR_PNO_MAX_SCAN_TIMERS < - request.scanTimers.ucScanTimersCount) { - hdd_err("Incorrect cmd - too many scan timers"); - return -EINVAL; - } - - for (i = 0; i < request.scanTimers.ucScanTimersCount; i++) { - params = sscanf(ptr, "%u %u %n", - &(request.scanTimers. - aTimerValues[i].uTimerValue), - &(request.scanTimers. - aTimerValues[i].uTimerRepeat), - &offset); - - if (2 != params) { - hdd_err("Incorrect cmd - diff params then expected %d", - params); - return -EINVAL; - } - - hdd_notice("PNO Timer value %d Timer repeat %d offset %d", - request.scanTimers.aTimerValues[i]. - uTimerValue, - request.scanTimers.aTimerValues[i]. - uTimerRepeat, offset); - - ptr += offset; - } - - } else { - hdd_notice("No scan timers provided param count %d scan timers %d", - params, request.scanTimers.ucScanTimersCount); - - /* Scan timers defaults to 5 minutes */ - request.scanTimers.ucScanTimersCount = 1; - request.scanTimers.aTimerValues[0].uTimerValue = 60; - request.scanTimers.aTimerValues[0].uTimerRepeat = 0; - } - params = sscanf(ptr, "%hhu %n", &(mode), &offset); request.modePNO = mode; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index f4a48b6320d7..6753bf860b9e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2715,7 +2715,6 @@ typedef struct sAniIbssRouteTable { #define SIR_PNO_MAX_NETW_CHANNELS 26 #define SIR_PNO_MAX_NETW_CHANNELS_EX 60 #define SIR_PNO_MAX_SUPP_NETWORKS 16 -#define SIR_PNO_MAX_SCAN_TIMERS 10 /* * size based of dot11 declaration without extra IEs as we will not carry those @@ -2743,23 +2742,30 @@ typedef struct { int32_t rssiThreshold; } tSirNetworkType; -typedef struct { - uint32_t uTimerValue; - uint32_t uTimerRepeat; -} tSirScanTimer; - -typedef struct { - uint8_t ucScanTimersCount; - tSirScanTimer aTimerValues[SIR_PNO_MAX_SCAN_TIMERS]; -} tSirScanTimersType; - +/** + * struct sSirPNOScanReq - PNO Scan request structure + * @enable: flag to enable or disable + * @modePNO: PNO Mode + * @ucNetworksCount: Number of networks + * @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 + * @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; uint8_t ucNetworksCount; tSirNetworkType aNetworks[SIR_PNO_MAX_SUPP_NETWORKS]; - tSirScanTimersType scanTimers; 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; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 699e49c65074..0156f9ac7f31 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3536,13 +3536,12 @@ CDF_STATUS wma_pno_start(tp_wma_handle wma, tpSirPNOScanReq pno) cmd->passive_dwell_time = pno->passive_max_time; /* Copy scan interval */ - if (pno->scanTimers.ucScanTimersCount) { - cmd->fast_scan_period = - WMA_SEC_TO_MSEC(pno->scanTimers.aTimerValues[0]. - uTimerValue); - cmd->slow_scan_period = cmd->fast_scan_period; - WMA_LOGD("Scan period : %d msec", cmd->slow_scan_period); - } + 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); -- cgit v1.2.3 From 0dd9904c14be77da19978b83045bd232b893478f Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Mon, 28 Sep 2015 11:09:09 -0700 Subject: qcacld-3.0: Enable enahnced flow control a) Enabled flow control b) Add small helper functions to avoid duplication of code. c) Fix thermal mitigation unpause issue with flow control. CRs-Fixed: 916716 Change-Id: Ic02b66d1c23768a1c71dc08ed50dcedd02b647ce --- Kbuild | 6 ++- core/dp/txrx/ol_tx_desc.c | 19 +++------- core/dp/txrx/ol_tx_desc.h | 76 +++++++++++++++++++++++++++++++++++++ core/dp/txrx/ol_tx_queue.c | 3 +- core/dp/txrx/ol_txrx.c | 3 +- core/dp/txrx/ol_txrx_flow_control.c | 30 +++------------ 6 files changed, 95 insertions(+), 42 deletions(-) diff --git a/Kbuild b/Kbuild index 79c831f5eb76..825909f521cd 100644 --- a/Kbuild +++ b/Kbuild @@ -116,7 +116,11 @@ ifeq ($(KERNEL_BUILD), 0) CONFIG_WLAN_NAPI_DEBUG := n # Flag to enable FW based TX Flow control - CONFIG_WLAN_TX_FLOW_CONTROL_V2 := n + ifeq ($(CONFIG_CNSS_EOS),y) + CONFIG_WLAN_TX_FLOW_CONTROL_V2 := y + else + CONFIG_WLAN_TX_FLOW_CONTROL_V2 := n + endif # Flag to enable LRO (Large Receive Offload) ifeq ($(CONFIG_CNSS_EOS), y) diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 1fa78723aa24..4b80f5c37555 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -122,9 +122,7 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, cdf_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; + tx_desc = ol_tx_get_desc_global_pool(pdev); ol_tx_desc_sanity_checks(pdev, tx_desc); ol_tx_desc_compute_delay(tx_desc); } @@ -175,9 +173,8 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, if (pool) { cdf_spin_lock_bh(&pool->flow_pool_lock); if (pool->avail_desc) { - tx_desc = &pool->freelist->tx_desc; - pool->freelist = pool->freelist->next; - if (cdf_unlikely(--pool->avail_desc < pool->stop_th)) { + tx_desc = ol_tx_get_desc_flow_pool(pool); + if (cdf_unlikely(pool->avail_desc < pool->stop_th)) { pool->status = FLOW_POOL_ACTIVE_PAUSED; cdf_spin_unlock_bh(&pool->flow_pool_lock); /* pause network queues */ @@ -253,10 +250,7 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) ol_tx_desc_reset_pkt_type(tx_desc); ol_tx_desc_reset_timestamp(tx_desc); - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - pdev->tx_desc.freelist; - pdev->tx_desc.freelist = (union ol_tx_desc_list_elem_t *)tx_desc; - pdev->tx_desc.num_free++; + ol_tx_put_desc_global_pool(pdev, tx_desc); #if defined(CONFIG_PER_VDEV_TX_DESC_POOL) #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL if ((cdf_atomic_read(&tx_desc->vdev->os_q_paused)) && @@ -298,10 +292,7 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) ol_tx_desc_reset_timestamp(tx_desc); cdf_spin_lock_bh(&pool->flow_pool_lock); - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - pool->freelist; - pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; - pool->avail_desc++; + ol_tx_put_desc_flow_pool(pool, tx_desc); switch (pool->status) { case FLOW_POOL_ACTIVE_PAUSED: if (pool->avail_desc > pool->start_th) { diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h index 392e192249e8..c96c47a05241 100644 --- a/core/dp/txrx/ol_tx_desc.h +++ b/core/dp/txrx/ol_tx_desc.h @@ -165,8 +165,84 @@ void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev, struct cdf_tso_seg_elem_t *tso_seg); #endif +/** + * ol_tx_get_desc_global_pool() - get descriptor from global pool + * @pdev: pdev handler + * + * Caller needs to take lock and do sanity checks. + * + * Return: tx descriptor + */ +static inline +struct ol_tx_desc_t *ol_tx_get_desc_global_pool(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.freelist->tx_desc; + pdev->tx_desc.freelist = pdev->tx_desc.freelist->next; + pdev->tx_desc.num_free--; + return tx_desc; +} + +/** + * ol_tx_put_desc_global_pool() - put descriptor to global pool freelist + * @pdev: pdev handle + * @tx_desc: tx descriptor + * + * Caller needs to take lock and do sanity checks. + * + * Return: none + */ +static inline +void ol_tx_put_desc_global_pool(struct ol_txrx_pdev_t *pdev, + struct ol_tx_desc_t *tx_desc) +{ + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = + pdev->tx_desc.freelist; + pdev->tx_desc.freelist = + (union ol_tx_desc_list_elem_t *)tx_desc; + pdev->tx_desc.num_free++; + return; +} + + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool); +/** + * ol_tx_get_desc_flow_pool() - get descriptor from flow pool + * @pool: flow pool + * + * Caller needs to take lock and do sanity checks. + * + * Return: tx descriptor + */ +static inline +struct ol_tx_desc_t *ol_tx_get_desc_flow_pool(struct ol_tx_flow_pool_t *pool) +{ + struct ol_tx_desc_t *tx_desc = &pool->freelist->tx_desc; + pool->freelist = pool->freelist->next; + pool->avail_desc--; + return tx_desc; +} + +/** + * ol_tx_put_desc_flow_pool() - put descriptor to flow pool freelist + * @pool: flow pool + * @tx_desc: tx descriptor + * + * Caller needs to take lock and do sanity checks. + * + * Return: none + */ +static inline +void ol_tx_put_desc_flow_pool(struct ol_tx_flow_pool_t *pool, + struct ol_tx_desc_t *tx_desc) +{ + tx_desc->pool = pool; + ((union ol_tx_desc_list_elem_t *)tx_desc)->next = pool->freelist; + pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; + pool->avail_desc++; + return; +} + #else static inline int ol_tx_free_invalid_flow_pool(void *pool) { diff --git a/core/dp/txrx/ol_tx_queue.c b/core/dp/txrx/ol_tx_queue.c index d24ae0bb2f0e..a894b1c30cb3 100644 --- a/core/dp/txrx/ol_tx_queue.c +++ b/core/dp/txrx/ol_tx_queue.c @@ -219,7 +219,7 @@ void ol_txrx_pdev_unpause(struct ol_txrx_pdev_t *pdev, uint32_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_vdev_unpause(vdev, reason); } } @@ -357,6 +357,7 @@ void ol_tx_throttle_set_level(struct ol_txrx_pdev_t *pdev, int level) /* Reset the phase */ pdev->tx_throttle.current_throttle_phase = THROTTLE_PHASE_OFF; + ol_txrx_thermal_unpause(pdev); /* Start with the new time */ ms = pdev->tx_throttle. diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index ae164368f698..02ab1793afbd 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -272,7 +272,6 @@ setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev) * * Return: none */ -inline void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc) { struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); @@ -281,6 +280,8 @@ void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc) return; } pdev->num_msdu_desc = num_msdu_desc + TX_FLOW_MGMT_POOL_SIZE; + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global pool size: %d = %d + %d\n", + pdev->num_msdu_desc, num_msdu_desc, TX_FLOW_MGMT_POOL_SIZE); return; } diff --git a/core/dp/txrx/ol_txrx_flow_control.c b/core/dp/txrx/ol_txrx_flow_control.c index fd759baee8dc..82785837ac22 100644 --- a/core/dp/txrx/ol_txrx_flow_control.c +++ b/core/dp/txrx/ol_txrx_flow_control.c @@ -51,12 +51,9 @@ #include #include -#define TX_FLOW_START_TH 25 -#define TX_FLOW_STOP_TH 10 #define INVALID_FLOW_ID 0xFF #define MAX_INVALID_BIN 3 - #ifdef QCA_LL_TX_FLOW_GLOBAL_MGMT_POOL #define TX_FLOW_MGMT_POOL_ID 0xEF #define TX_FLOW_MGMT_POOL_SIZE 32 @@ -232,9 +229,7 @@ static int ol_tx_move_desc_n(struct ol_tx_flow_pool_t *src_pool, /* Take descriptors from source pool and put it in temp_list */ cdf_spin_lock_bh(&src_pool->flow_pool_lock); for (i = 0; i < desc_move_count; i++) { - tx_desc = &src_pool->freelist->tx_desc; - src_pool->freelist = src_pool->freelist->next; - src_pool->avail_desc--; + tx_desc = ol_tx_get_desc_flow_pool(src_pool); ((union ol_tx_desc_list_elem_t *)tx_desc)->next = temp_list; temp_list = (union ol_tx_desc_list_elem_t *)tx_desc; @@ -250,11 +245,7 @@ static int ol_tx_move_desc_n(struct ol_tx_flow_pool_t *src_pool, break; tx_desc = &temp_list->tx_desc; temp_list = temp_list->next; - tx_desc->pool = dst_pool; - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - dst_pool->freelist; - dst_pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; - dst_pool->avail_desc++; + ol_tx_put_desc_flow_pool(dst_pool, tx_desc); count++; } cdf_spin_unlock_bh(&dst_pool->flow_pool_lock); @@ -264,11 +255,7 @@ static int ol_tx_move_desc_n(struct ol_tx_flow_pool_t *src_pool, while (temp_list) { tx_desc = &temp_list->tx_desc; temp_list = temp_list->next; - tx_desc->pool = src_pool; - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - src_pool->freelist; - src_pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc; - src_pool->avail_desc++; + ol_tx_put_desc_flow_pool(src_pool, tx_desc); } cdf_spin_unlock_bh(&src_pool->flow_pool_lock); @@ -370,9 +357,7 @@ struct ol_tx_flow_pool_t *ol_tx_create_flow_pool(uint8_t flow_pool_id, size = pdev->tx_desc.num_free; for (i = 0; i < size; i++) { - pdev->tx_desc.num_free--; - tx_desc = &pdev->tx_desc.freelist->tx_desc; - pdev->tx_desc.freelist = pdev->tx_desc.freelist->next; + tx_desc = ol_tx_get_desc_global_pool(pdev); tx_desc->pool = pool; ((union ol_tx_desc_list_elem_t *)tx_desc)->next = temp_list; temp_list = (union ol_tx_desc_list_elem_t *)tx_desc; @@ -458,12 +443,7 @@ int ol_tx_delete_flow_pool(struct ol_tx_flow_pool_t *pool) tx_desc = &temp_list->tx_desc; temp_list = temp_list->next; - ((union ol_tx_desc_list_elem_t *)tx_desc)->next = - pdev->tx_desc.freelist; - pdev->tx_desc.freelist = - (union ol_tx_desc_list_elem_t *)tx_desc; - pdev->tx_desc.num_free++; - + ol_tx_put_desc_global_pool(pdev, tx_desc); } cdf_spin_unlock_bh(&pdev->tx_mutex); -- cgit v1.2.3 From 11dbd38e50d3cdd0d3a614050d9f9e2c43026230 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Mon, 28 Sep 2015 11:17:04 -0700 Subject: qcacld-3.0: Remove per vdev tx descriptor pool Remove per vdev tx descriptor pool feature as it is applicable only for High Latency. CRs-Fixed: 916724 Change-Id: I22ab3dd187518790694356bdde8475b194845bf5 --- Kbuild | 14 -------------- core/dp/txrx/ol_tx_desc.c | 21 --------------------- core/dp/txrx/ol_txrx.c | 3 --- core/dp/txrx/ol_txrx.h | 4 ---- core/dp/txrx/ol_txrx_types.h | 7 ------- core/hdd/src/wlan_hdd_softap_tx_rx.c | 24 ------------------------ core/hdd/src/wlan_hdd_tx_rx.c | 26 -------------------------- 7 files changed, 99 deletions(-) diff --git a/Kbuild b/Kbuild index 825909f521cd..e21632faec12 100644 --- a/Kbuild +++ b/Kbuild @@ -164,15 +164,6 @@ ifeq ($(CONFIG_ROME_IF),usb) 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 - - #Enable OS specific IRQ abstraction CONFIG_ATH_SUPPORT_SHARED_IRQ := 1 @@ -1072,11 +1063,6 @@ 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 OS specific IRQ abstraction ifeq ($(CONFIG_ATH_SUPPORT_SHARED_IRQ), 1) CDEFINES += -DATH_SUPPORT_SHARED_IRQ diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 4b80f5c37555..591b66026bfc 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -127,14 +127,6 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev, ol_tx_desc_compute_delay(tx_desc); } cdf_spin_unlock_bh(&pdev->tx_mutex); - if (!tx_desc) - return NULL; - -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - tx_desc->vdev = vdev; - cdf_atomic_inc(&vdev->tx_desc_count); -#endif - return tx_desc; } @@ -251,19 +243,6 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) ol_tx_desc_reset_timestamp(tx_desc); ol_tx_put_desc_global_pool(pdev, tx_desc); -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) -#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL - if ((cdf_atomic_read(&tx_desc->vdev->os_q_paused)) && - (cdf_atomic_read(&tx_desc->vdev->tx_desc_count) < - TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK)) { - /* wakeup netif_queue */ - cdf_atomic_set(&tx_desc->vdev->os_q_paused, 0); - ol_txrx_flow_control_cb(tx_desc->vdev, true); - } -#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ - cdf_atomic_dec(&tx_desc->vdev->tx_desc_count); - tx_desc->vdev = NULL; -#endif cdf_spin_unlock_bh(&pdev->tx_mutex); } diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 02ab1793afbd..37694a8e78dd 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -965,9 +965,6 @@ ol_txrx_vdev_attach(ol_txrx_pdev_handle pdev, vdev->safemode = 0; vdev->drop_unenc = 1; vdev->num_filters = 0; -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - cdf_atomic_init(&vdev->tx_desc_count); -#endif cdf_mem_copy(&vdev->mac_addr.raw[0], vdev_mac_addr, OL_TXRX_MAC_ADDR_LEN); diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index 01590093520f..4e77867ce37f 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -39,10 +39,6 @@ void ol_txrx_peer_unref_delete(struct ol_txrx_peer_t *peer); #define OL_TX_AVG_FRM_BYTES 1000 #endif -#ifdef CONFIG_PER_VDEV_TX_DESC_POOL -#define TXRX_HL_TX_FLOW_CTRL_VDEV_LOW_WATER_MARK 400 -#endif - /** * ol_txrx_get_vdev_from_vdev_id() - get vdev from vdev_id * @vdev_id: vdev_id diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index aee96852fe5b..118d9d97bbee 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -162,9 +162,6 @@ struct ol_tx_desc_t { after tx complete */ uint8_t orig_l2_hdr_bytes; #endif -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - struct ol_txrx_vdev_t *vdev; -#endif #ifdef QCA_LL_TX_FLOW_CONTROL_V2 struct ol_tx_flow_pool_t *pool; #endif @@ -852,10 +849,6 @@ struct ol_txrx_vdev_t { cdf_spinlock_t flow_control_lock; ol_txrx_tx_flow_control_fp osif_flow_control_cb; void *osif_fc_ctx; - -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - cdf_atomic_t tx_desc_count; -#endif uint16_t wait_on_peer_id; cdf_event_t wait_delete_comp; #if defined(FEATURE_TSO) diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index bb85d1703a0e..f50b582a6499 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -148,30 +148,6 @@ void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume) WLAN_WAKE_ALL_NETIF_QUEUE, WLAN_DATA_FLOW_CONTROL); } -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - else if (false == tx_resume) { /* Pause TX */ - hddLog(LOG1, FL("Disabling queues")); - wlan_hdd_netif_queue_control(pAdapter, - WLAN_STOP_ALL_NETIF_QUEUE, - WLAN_DATA_FLOW_CONTROL); - if (CDF_TIMER_STATE_STOPPED == - cdf_mc_timer_get_current_state(&pAdapter-> - tx_flow_control_timer)) { - CDF_STATUS status; - status = - cdf_mc_timer_start(&pAdapter->tx_flow_control_timer, - WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); - if (!CDF_IS_STATUS_SUCCESS(status)) - CDF_TRACE(CDF_MODULE_ID_HDD, - CDF_TRACE_LEVEL_ERROR, - "%s: Failed to start tx_flow_control_timer", - __func__); - else - pAdapter->hdd_stats.hddTxRxStats.txflow_timer_cnt++; - } - } -#endif - return; } #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 0f6c3b9c13db..f5e9c32584ca 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -142,32 +142,6 @@ void hdd_tx_resume_cb(void *adapter_context, bool tx_resume) WLAN_WAKE_ALL_NETIF_QUEUE, WLAN_DATA_FLOW_CONTROL); } -#if defined(CONFIG_PER_VDEV_TX_DESC_POOL) - else if (false == tx_resume) { /* Pause TX */ - hddLog(LOG1, FL("Disabling queues")); - wlan_hdd_netif_queue_control(pAdapter, - WLAN_STOP_ALL_NETIF_QUEUE, - WLAN_DATA_FLOW_CONTROL); - if (CDF_TIMER_STATE_STOPPED == - cdf_mc_timer_get_current_state(&pAdapter-> - tx_flow_control_timer)) { - CDF_STATUS status; - status = - cdf_mc_timer_start(&pAdapter->tx_flow_control_timer, - WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); - if (!CDF_IS_STATUS_SUCCESS(status)) - CDF_TRACE(CDF_MODULE_ID_HDD, - CDF_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; } -- cgit v1.2.3 From 2881312e10e57a71b7a495533ed7c2ca4593a37e Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Tue, 24 Nov 2015 19:11:58 +0530 Subject: qcacld-3.0: Use appropriate list API Use list_for_each_entry_safe API to traverse list while deleting list entry in cds_drop_rxpkt_by_staid to avoid crash. CRs-Fixed: 943767 Change-Id: I4d09fd88f0faefacfc886866d9045b09feeb4432 --- core/cds/src/cds_sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 9e6d746f8f33..82dfbbc64ce2 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -750,7 +750,7 @@ void cds_drop_rxpkt_by_staid(p_cds_sched_context pSchedContext, uint16_t staId) } spin_unlock_bh(&pSchedContext->ol_rx_queue_lock); - list_for_each_entry(pkt, &local_list, list) { + list_for_each_entry_safe(pkt, tmp, &local_list, list) { list_del(&pkt->list); buf = pkt->Rxpkt; while (buf) { -- cgit v1.2.3 From 600a296834a438dc93a57be3c979679d39c47231 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 10 Dec 2015 15:39:48 +0530 Subject: qcacld-3.0: Do not reserve mgmt descriptors Do not reserve tx descriptors for management packets if management over WMI is enabled. Change-Id: Iafe758d91d11f4875e3152d92538055784490a14 CRs-Fixed: 949917 --- core/dp/ol/inc/ol_txrx_ctrl_api.h | 3 +++ core/dp/txrx/ol_txrx.c | 34 ++++++++++++++++++++++++++++++++++ core/dp/txrx/ol_txrx_flow_control.c | 6 ++++-- core/dp/txrx/ol_txrx_types.h | 1 + core/wma/src/wma_main.c | 5 +++++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/core/dp/ol/inc/ol_txrx_ctrl_api.h b/core/dp/ol/inc/ol_txrx_ctrl_api.h index 4a01d3ec0eb8..700dcf4a0626 100644 --- a/core/dp/ol/inc/ol_txrx_ctrl_api.h +++ b/core/dp/ol/inc/ol_txrx_ctrl_api.h @@ -1261,6 +1261,9 @@ void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, bool ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer); +void ol_tx_set_is_mgmt_over_wmi_enabled(uint8_t value); +uint8_t ol_tx_get_is_mgmt_over_wmi_enabled(void); + /* TX FLOW Control related functions */ #ifdef QCA_LL_TX_FLOW_CONTROL_V2 #define TX_FLOW_MGMT_POOL_ID 0xEF diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 37694a8e78dd..fa9f7d8fd369 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -76,6 +76,40 @@ /*=== function definitions ===*/ +/** + * ol_tx_set_is_mgmt_over_wmi_enabled() - set flag to indicate that mgmt over + * wmi is enabled or not. + * @value: 1 for enabled/ 0 for disable + * + * Return: None + */ +void ol_tx_set_is_mgmt_over_wmi_enabled(uint8_t value) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + cdf_print("%s: pdev is NULL\n", __func__); + return; + } + pdev->is_mgmt_over_wmi_enabled = value; + return; +} + +/** + * ol_tx_get_is_mgmt_over_wmi_enabled() - get value of is_mgmt_over_wmi_enabled + * + * Return: is_mgmt_over_wmi_enabled + */ +uint8_t ol_tx_get_is_mgmt_over_wmi_enabled(void) +{ + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (!pdev) { + cdf_print("%s: pdev is NULL\n", __func__); + return 0; + } + return pdev->is_mgmt_over_wmi_enabled; +} + + #ifdef QCA_SUPPORT_TXRX_LOCAL_PEER_ID ol_txrx_peer_handle ol_txrx_find_peer_by_addr_and_vdev(ol_txrx_pdev_handle pdev, diff --git a/core/dp/txrx/ol_txrx_flow_control.c b/core/dp/txrx/ol_txrx_flow_control.c index 82785837ac22..21d49908053f 100644 --- a/core/dp/txrx/ol_txrx_flow_control.c +++ b/core/dp/txrx/ol_txrx_flow_control.c @@ -112,7 +112,8 @@ void ol_tx_register_flow_control(struct ol_txrx_pdev_t *pdev) cdf_spinlock_init(&pdev->tx_desc.flow_pool_list_lock); TAILQ_INIT(&pdev->tx_desc.flow_pool_list); - ol_tx_register_global_mgmt_pool(pdev); + if (!ol_tx_get_is_mgmt_over_wmi_enabled()) + ol_tx_register_global_mgmt_pool(pdev); } /** @@ -123,7 +124,8 @@ void ol_tx_register_flow_control(struct ol_txrx_pdev_t *pdev) */ void ol_tx_deregister_flow_control(struct ol_txrx_pdev_t *pdev) { - ol_tx_deregister_global_mgmt_pool(pdev); + if (!ol_tx_get_is_mgmt_over_wmi_enabled()) + ol_tx_deregister_global_mgmt_pool(pdev); cdf_spinlock_destroy(&pdev->tx_desc.flow_pool_list_lock); if (!TAILQ_EMPTY(&pdev->tx_desc.flow_pool_list)) { diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 118d9d97bbee..3fc470bd107e 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -571,6 +571,7 @@ struct ol_txrx_pdev_t { struct cdf_mem_multi_page_t desc_pages; } tx_desc; + uint8_t is_mgmt_over_wmi_enabled; #if defined(QCA_LL_TX_FLOW_CONTROL_V2) struct ol_txrx_pool_stats pool_stats; uint32_t num_msdu_desc; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 2fc74131c6ed..f36fd45a7d94 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3806,6 +3806,11 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) cdf_mem_copy(wma_handle->wmi_service_bitmap, param_buf->wmi_service_bitmap, sizeof(wma_handle->wmi_service_bitmap)); + + ol_tx_set_is_mgmt_over_wmi_enabled( + WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_MGMT_TX_WMI)); + /* SWBA event handler for beacon transmission */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_HOST_SWBA_EVENTID, -- cgit v1.2.3 From b4a4258557b7192b25d1f165efbff1d824a14953 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 10 Dec 2015 15:42:17 +0530 Subject: qcacld-3.0: Ignore HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND from FW Ignore HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND from firmware if management over WMI is enabled. Change-Id: Ic196d17526c251ae26dd59ca2f42b7bff9a46ffe CRs-Fixed: 949946 --- core/dp/htt/htt_t2h.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 92d847285c02..3ef8cdd8c6f7 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -283,10 +283,14 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) compl_msg = (struct htt_mgmt_tx_compl_ind *)(msg_word + 1); - ol_tx_single_completion_handler(pdev->txrx_pdev, - compl_msg->status, - compl_msg->desc_id); - HTT_TX_SCHED(pdev); + if (!ol_tx_get_is_mgmt_over_wmi_enabled()) { + ol_tx_single_completion_handler(pdev->txrx_pdev, + compl_msg->status, + compl_msg->desc_id); + HTT_TX_SCHED(pdev); + } else { + cdf_print("Ignoring HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND indication\n"); + } break; } case HTT_T2H_MSG_TYPE_STATS_CONF: -- cgit v1.2.3 From 3044c6e30f3211e4b5223c3d0a398df91a871c19 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Fri, 4 Dec 2015 00:08:58 -0800 Subject: qcacld-3.0: add retry logic if htc_issue_packets fails Fix WMI command path Tx failure case: 1) Current WMI command path frees the packet with dummy completion when hif fails to send the packet down. Fix it by putting back cmd to endpoint Tx queue for retry. 2) Also separate WMI mgmt command/event log buffer from control path command logs Change-Id: Icc3f7fde10a592de3c5354ba720d6810ce1b635a CRs-Fixed: 940100 --- core/htc/htc_send.c | 26 ++++++++-------- core/wmi/wmi_unified.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 18 deletions(-) diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index bb0ff387837d..b60abc9736f8 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -586,18 +586,9 @@ static A_STATUS htc_issue_packets(HTC_TARGET *target, pEndpoint->TxCredits += pPacket->PktInfo.AsTx.CreditsUsed; #endif - while (!HTC_QUEUE_EMPTY(pPktQueue)) { - if (status != A_NO_RESOURCE) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("htc_issue_packets, failed pkt:0x%p status:%d \n", - pPacket, status)); - } - pPacket = htc_packet_dequeue(pPktQueue); - if (pPacket) { - pPacket->Status = status; - send_packet_completion(target, pPacket); - } - } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("htc_issue_packets, failed pkt:0x%p status:%d", + pPacket, status)); } AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets \n")); @@ -997,7 +988,16 @@ static HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target, UNLOCK_HTC_TX(target); /* send what we can */ - htc_issue_packets(target, pEndpoint, &sendQueue); + result = htc_issue_packets(target, pEndpoint, &sendQueue); + if (result) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue", + result)); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, + &sendQueue); + LOCK_HTC_TX(target); + break; + } if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { tx_resources = diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 6e908a3f866a..d1980c73f567 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -104,6 +104,60 @@ struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY]; cdf_get_log_timestamp(); \ g_wmi_rx_event_buf_idx++; \ } +/* wmi_mgmt commands */ +#define WMI_MGMT_EVENT_DEBUG_MAX_ENTRY (256) + +uint32_t g_wmi_mgmt_command_buf_idx = 0; +struct +wmi_command_debug wmi_mgmt_command_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; + +/* wmi_mgmt commands TX completed */ +uint32_t g_wmi_mgmt_command_tx_cmp_buf_idx = 0; +struct wmi_command_debug +wmi_mgmt_command_tx_cmp_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; + +/* wmi_mgmt events when processed */ +uint32_t g_wmi_mgmt_event_buf_idx = 0; +struct wmi_event_debug +wmi_mgmt_event_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY]; + +#define WMI_MGMT_COMMAND_RECORD(a, b) { \ + if (WMI_MGMT_EVENT_DEBUG_MAX_ENTRY <= \ + g_wmi_mgmt_command_buf_idx) \ + g_wmi_mgmt_command_buf_idx = 0; \ + wmi_mgmt_command_log_buffer[g_wmi_mgmt_command_buf_idx].command = a; \ + cdf_mem_copy( \ + wmi_mgmt_command_log_buffer[g_wmi_mgmt_command_buf_idx].data,\ + b, 16); \ + wmi_mgmt_command_log_buffer[g_wmi_mgmt_command_buf_idx].time = \ + cdf_get_log_timestamp(); \ + g_wmi_mgmt_command_buf_idx++; \ +} + +#define WMI_MGMT_COMMAND_TX_CMP_RECORD(a, b) { \ + if (WMI_MGMT_EVENT_DEBUG_MAX_ENTRY <= \ + g_wmi_mgmt_command_tx_cmp_buf_idx) \ + g_wmi_mgmt_command_tx_cmp_buf_idx = 0; \ + wmi_mgmt_command_tx_cmp_log_buffer[g_wmi_mgmt_command_tx_cmp_buf_idx].\ + command = a; \ + cdf_mem_copy(wmi_mgmt_command_tx_cmp_log_buffer \ + [g_wmi_mgmt_command_tx_cmp_buf_idx].data, b, 16); \ + wmi_mgmt_command_tx_cmp_log_buffer[g_wmi_mgmt_command_tx_cmp_buf_idx].\ + time =\ + cdf_get_log_timestamp(); \ + g_wmi_mgmt_command_tx_cmp_buf_idx++; \ +} + +#define WMI_MGMT_EVENT_RECORD(a, b) { \ + if (WMI_MGMT_EVENT_DEBUG_MAX_ENTRY <= g_wmi_mgmt_event_buf_idx) \ + g_wmi_mgmt_event_buf_idx = 0; \ + wmi_mgmt_event_log_buffer[g_wmi_mgmt_event_buf_idx].event = a; \ + cdf_mem_copy(wmi_mgmt_event_log_buffer[g_wmi_mgmt_event_buf_idx].data,\ + b, 16); \ + wmi_mgmt_event_log_buffer[g_wmi_mgmt_event_buf_idx].time = \ + cdf_get_log_timestamp(); \ + g_wmi_mgmt_event_buf_idx++; \ +} #endif /*WMI_INTERFACE_EVENT_LOGGING */ @@ -780,7 +834,14 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, #ifdef WMI_INTERFACE_EVENT_LOGGING cdf_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, ((uint32_t *) cdf_nbuf_data(buf) + 2)); + if (cmd_id == WMI_MGMT_TX_SEND_CMDID) { + WMI_MGMT_COMMAND_RECORD(cmd_id, + ((uint32_t *)cdf_nbuf_data(buf) + 2)); + } else { + WMI_COMMAND_RECORD(cmd_id, ((uint32_t *) cdf_nbuf_data(buf) + + 2)); + } + cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); #endif @@ -1037,7 +1098,11 @@ void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) #ifdef WMI_INTERFACE_EVENT_LOGGING cdf_spin_lock_bh(&wmi_handle->wmi_record_lock); /* Exclude 4 bytes of TLV header */ - WMI_EVENT_RECORD(id, ((uint8_t *) data + 4)); + if (id == WMI_MGMT_TX_COMPLETION_EVENTID) { + WMI_MGMT_EVENT_RECORD(id, ((uint8_t *) data + 4)); + } else { + WMI_EVENT_RECORD(id, ((uint8_t *) data + 4)); + } cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); #endif /* Call the WMI registered event handler */ @@ -1189,9 +1254,14 @@ void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt) cdf_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, - ((uint32_t *) cdf_nbuf_data(wmi_cmd_buf) + - 2)); + if (cmd_id == WMI_MGMT_TX_SEND_CMDID) { + WMI_MGMT_COMMAND_TX_CMP_RECORD(cmd_id, + ((uint32_t *) cdf_nbuf_data(wmi_cmd_buf) + 2)); + } else { + WMI_COMMAND_TX_CMP_RECORD(cmd_id, + ((uint32_t *) cdf_nbuf_data(wmi_cmd_buf) + 2)); + } + cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock); #endif cdf_nbuf_free(wmi_cmd_buf); -- cgit v1.2.3 From 3d0cda898de030317b011825610135cb7b3febd9 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 3 Dec 2015 13:25:05 -0800 Subject: qcacld-3.0: Enable emergency reaping for wmi pipe. Since management frames have been added to the wmi pipe, the wmi pipe may fill up before the driver schedules the tx completion processing. Make tx completion processing use the DDR ce index to avoid register access durring reaping. Change-Id: I213aa0274d3c66e583bcdb700ced1133c2c30ebc CRs-Fixed: 945831 --- core/hif/src/ce/ce_main.c | 2 +- core/hif/src/ce/ce_reg.h | 12 ++++++++++-- core/hif/src/ce/ce_service.c | 2 +- core/htc/htc_send.c | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 6e6f8b0b8212..0d2e40e3e0c1 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -2343,6 +2343,7 @@ inline uint32_t DEBUG_CE_DEST_RING_READ_IDX_GET(struct ol_softc *scn, #endif +#ifdef ADRASTEA_RRI_ON_DDR /** * hif_get_src_ring_read_index(): Called to get the SRRI * @@ -2392,7 +2393,6 @@ inline unsigned int hif_get_dst_ring_read_index(struct ol_softc *scn, (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS); } -#ifdef ADRASTEA_RRI_ON_DDR /** * hif_config_rri_on_ddr(): Configure the RRI on DDR mechanism * diff --git a/core/hif/src/ce/ce_reg.h b/core/hif/src/ce/ce_reg.h index 5e4c815d3b8e..dc4ea6289409 100644 --- a/core/hif/src/ce/ce_reg.h +++ b/core/hif/src/ce/ce_reg.h @@ -264,6 +264,7 @@ uint32_t DEBUG_CE_DEST_RING_READ_IDX_GET(struct ol_softc *scn, #define SRRI_FROM_DDR_ADDR(addr) ((*(addr)) & 0xFFFF) #define DRRI_FROM_DDR_ADDR(addr) (((*(addr))>>16) & 0xFFFF) +#ifdef ADRASTEA_RRI_ON_DDR #ifdef SHADOW_REG_DEBUG #define CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ DEBUG_CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr) @@ -276,13 +277,11 @@ uint32_t DEBUG_CE_DEST_RING_READ_IDX_GET(struct ol_softc *scn, DRRI_FROM_DDR_ADDR(VADDR_FOR_CE(scn, CE_ctrl_addr)) #endif - unsigned int hif_get_src_ring_read_index(struct ol_softc *scn, uint32_t CE_ctrl_addr); unsigned int hif_get_dst_ring_read_index(struct ol_softc *scn, uint32_t CE_ctrl_addr); -#ifdef ADRASTEA_RRI_ON_DDR #define CE_SRC_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ hif_get_src_ring_read_index(scn, CE_ctrl_addr) #define CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ @@ -292,6 +291,15 @@ unsigned int hif_get_dst_ring_read_index(struct ol_softc *scn, A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_SRRI_ADDRESS) #define CE_DEST_RING_READ_IDX_GET(scn, CE_ctrl_addr)\ A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_DRRI_ADDRESS) + +/** + * if RRI on DDR is not enabled, get idx from ddr defaults to + * using the register value & force wake must be used for + * non interrupt processing. + */ +#define CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, CE_ctrl_addr)\ + A_TARGET_READ(scn, (CE_ctrl_addr) + CURRENT_SRRI_ADDRESS) + #endif #define CE_SRC_RING_BASE_ADDR_SET(scn, CE_ctrl_addr, addr) \ diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 9da63611d36a..f5e07c9164c8 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -903,7 +903,7 @@ ce_completed_send_next_nolock(struct CE_state *CE_state, */ A_TARGET_ACCESS_BEGIN_RET(scn); src_ring->hw_index = - CE_SRC_RING_READ_IDX_GET(scn, ctrl_addr); + CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, ctrl_addr); A_TARGET_ACCESS_END_RET(scn); } read_index = src_ring->hw_index; diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index b60abc9736f8..cb3c57d642f8 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -532,6 +532,7 @@ static A_STATUS htc_issue_packets(HTC_TARGET *target, pEndpoint->ul_outstanding_cnt++; UNLOCK_HTC_TX(target); + hif_send_complete_check(target->hif_dev, pEndpoint->UL_PipeID, false); status = hif_send_head(target->hif_dev, pEndpoint->UL_PipeID, pEndpoint->Id, HTC_HDR_LENGTH + pPacket->ActualLength, -- cgit v1.2.3 From a2bff83970ad6e076d6ad766ec3d3d103a69f5b2 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 9 Dec 2015 17:12:08 -0800 Subject: Release 5.0.0.149 Release 5.0.0.149 Change-Id: I780e387e2df3e2b5f64cf193c81624efab4e92cd CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 1005dd0a6c08..84ac7fee464b 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 148 +#define QWLAN_VERSION_BUILD 149 -#define QWLAN_VERSIONSTR "5.0.0.148" +#define QWLAN_VERSIONSTR "5.0.0.149" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 9cfd7d0f03ece2ac17b9f6766060ada2a2478c80 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:09:38 +0530 Subject: qcacld-3.0: Add disconnect to the head of sme pending command list qcacld-2.0 to qcacld-3.0 propagation If connect is received and queued to sme pending list while scan is in progress in sme, once scan is completed, again scan is queued to get the scanned channel info with reason eCsrScanGetScanChnInfo behind connect command. Connect is executed next with scan command in pending queue. Now if disconnect is received from hdd it is also queued in sme pending cmd list behind scan. Once connect is executed the wait for key state is set and wait key timer is started. As only disconnect and set key command are allowed in wait for key state, the pending cmd queue is not executed with scan command at the head and thus the disconnect is not executed. Also as supplicant has issued disconnect, no keys will be set and pending command queue will not be processed till wait for key timer expires. If during this time unload starts all the commands including the disconnect command sme pending queue are flushed and thus no DEL BSS is sent to firmware before HAL STOP which leads to crash. To avoid this add disconnect to the head of sme pending command list so that disconnect can be processed after connect during wait for key state. Change-Id: I333e7b103ac10e368d34b5bf8b87cc360650cd50 CRs-Fixed: 930713 --- core/sme/src/csr/csr_api_roam.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index fdc18bd2f3a9..8c6f830ab4bc 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7681,7 +7681,6 @@ CDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t session { CDF_STATUS status = CDF_STATUS_SUCCESS; tSmeCmd *pCommand; - bool fHighPriority = false; do { pCommand = csr_get_command_buffer(pMac); if (!pCommand) { @@ -7709,7 +7708,6 @@ CDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t session pCommand->u.roamCmd.roamReason = eCsrForcedDeauth; break; case eCSR_DISCONNECT_REASON_HANDOFF: - fHighPriority = true; pCommand->u.roamCmd.roamReason = eCsrSmeIssuedDisassocForHandoff; break; @@ -7735,7 +7733,7 @@ CDF_STATUS csr_roam_issue_disassociate_cmd(tpAniSirGlobal pMac, uint32_t session default: break; } - status = csr_queue_sme_command(pMac, pCommand, fHighPriority); + status = csr_queue_sme_command(pMac, pCommand, true); if (!CDF_IS_STATUS_SUCCESS(status)) { sms_log(pMac, LOGE, FL(" fail to send message status = %d"), status); -- cgit v1.2.3 From 67f5d198a8822c864c63c6014e2e17be400fefdf Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:08:21 +0530 Subject: qcacld-3.0: Lower the log level for unhandled Action frame logs qcacld-2.0 to qcacld-3.0 propagation Too many log prints are seen by default if unhandled action frame are received. This change lowers the log level for unhandled Action frame logs. Change-Id: I4af258eed12c2f352f97df0f73e9ab0c6278a437 CRs-Fixed: 924661 --- core/mac/src/pe/lim/lim_process_action_frame.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 2c23c83f8586..dd041c448135 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1784,7 +1784,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, session); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Qos action %d not handled"), action_hdr->actionID); break; @@ -1821,7 +1821,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, mac_ctx, rx_pkt_info, session); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Spectrum mgmt action id %d not handled"), action_hdr->actionID); break; @@ -1857,7 +1857,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("WME action %d not handled"), action_hdr->actionID); break; @@ -1874,7 +1874,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, session); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Action ID %d not handled in HT category"), action_hdr->actionID); break; @@ -1884,7 +1884,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, case SIR_MAC_ACTION_WNM: #ifdef WLAN_FEATURE_11W if ((session->limRmfEnabled) && (mac_hdr_11w->fc.wep == 0)) { - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Dropping unprot action %d frm (PMF on)"), action_hdr->category); break; @@ -1911,7 +1911,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, session, rssi); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Action ID %d not handled in WNM category"), action_hdr->actionID); break; @@ -1943,7 +1943,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, session); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Action ID %d not handled in RRM"), action_hdr->actionID); break; @@ -1951,7 +1951,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, } } else { /* Else we will just ignore the RRM messages. */ - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("RRM frm ignored, it is disabled in cfg")); } break; @@ -1990,7 +1990,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, WMA_GET_RX_CH(rx_pkt_info), session, 0); } else { - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Dropping the vendor specific action frame" "beacause of (WES Mode not enabled " "(WESMODE = %d) or OUI mismatch " @@ -2031,7 +2031,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, WMA_GET_RX_CH(rx_pkt_info), session, 0); } else { - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"), pub_action->Oui[0], pub_action->Oui[1], pub_action->Oui[2], pub_action->Oui[3]); @@ -2075,7 +2075,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, rx_pkt_info, session); break; default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Unhandled public action frame -- %x "), action_hdr->actionID); break; @@ -2148,7 +2148,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, break; } default: - lim_log(mac_ctx, LOGE, + lim_log(mac_ctx, LOG1, FL("Action category %d not handled"), action_hdr->category); break; @@ -2209,7 +2209,7 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) WMA_GET_RX_CH (pBd), NULL, 0); } else { - lim_log(pMac, LOGE, + lim_log(pMac, LOG1, FL ("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"), pActionHdr->Oui[0], @@ -2221,7 +2221,7 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd) break; default: PELOGE(lim_log - (pMac, LOGE, + (pMac, LOG1, FL("Unhandled public action frame -- %x "), pActionHdr->actionID); ) -- cgit v1.2.3 From 72e748efa92aa1746cd5aa3bbf744199d40404d6 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:10:39 +0530 Subject: qcacld-3.0: Add log in vos_mem_alloc if kzalloc takes more than 3 seconds qcacld-2.0 to qcacld-3.0 propagation Sometime the thread sleeps in kzalloc for long time, resulting in thread stuck. This change prints time taken by kzalloc, if time taken is more than 3 seconds. Change-Id: I027ab2ad4e93f8a02ba9e48e47d7aa3123785a31 CRs-Fixed: 926479 --- core/cdf/src/cdf_memory.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c index 71dd46181d40..197de54069dc 100644 --- a/core/cdf/src/cdf_memory.c +++ b/core/cdf/src/cdf_memory.c @@ -36,6 +36,7 @@ #include "cdf_nbuf.h" #include "cdf_trace.h" #include "cdf_lock.h" +#include "cdf_mc_timer.h" #if defined(CONFIG_CNSS) #include @@ -66,6 +67,7 @@ struct s_cdf_mem_struct { #endif /* Preprocessor Definitions and Constants */ +#define CDF_GET_MEMORY_TIME_THRESHOLD 3000 /* Type Declarations */ @@ -194,6 +196,7 @@ void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum) void *memPtr = NULL; uint32_t new_size; int flags = GFP_KERNEL; + unsigned long time_before_kzalloc; if (size > (1024 * 1024) || size == 0) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, @@ -217,8 +220,19 @@ void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum) flags = GFP_ATOMIC; new_size = size + sizeof(struct s_cdf_mem_struct) + 8; - + time_before_kzalloc = cdf_mc_timer_get_system_time(); memStruct = (struct s_cdf_mem_struct *)kzalloc(new_size, flags); + /** + * If time taken by kmalloc is greater than + * CDF_GET_MEMORY_TIME_THRESHOLD msec + */ + if (cdf_mc_timer_get_system_time() - time_before_kzalloc >= + CDF_GET_MEMORY_TIME_THRESHOLD) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: kzalloc took %lu msec for size %zu called from %pS at line %d", + __func__, + cdf_mc_timer_get_system_time() - time_before_kzalloc, + size, (void *)_RET_IP_, lineNum); if (memStruct != NULL) { CDF_STATUS cdf_status; @@ -327,6 +341,9 @@ void *cdf_mem_malloc(size_t size) #ifdef CONFIG_WCNSS_MEM_PRE_ALLOC void *pmem; #endif + void *memPtr = NULL; + unsigned long time_before_kzalloc; + if (size > (1024 * 1024) || size == 0) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: called with invalid arg; passed in %zu !!", @@ -346,8 +363,20 @@ void *cdf_mem_malloc(size_t size) if (in_interrupt() || irqs_disabled() || in_atomic()) flags = GFP_ATOMIC; - - return kzalloc(size, flags); + time_before_kzalloc = cdf_mc_timer_get_system_time(); + memPtr = kzalloc(size, flags); + /** + * If time taken by kmalloc is greater than + * CDF_GET_MEMORY_TIME_THRESHOLD msec + */ + if (cdf_mc_timer_get_system_time() - time_before_kzalloc >= + CDF_GET_MEMORY_TIME_THRESHOLD) + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: kzalloc took %lu msec for size %zu called from %pS", + __func__, + cdf_mc_timer_get_system_time() - time_before_kzalloc, + size, (void *)_RET_IP_); + return memPtr; } /** -- cgit v1.2.3 From 67e19cac73049bc250f7ad62f07751b7b2c5e76e Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Mon, 7 Dec 2015 11:38:51 -0800 Subject: qcacld-3.0: Remove support of power gating parameters Propagation from qcacld-2.0 to qcacld-3.0 - WLAN firmware does not support get/set operations for power gating VDEV parameters - Remove support for power gating VDEV parameters from WLAN host driver Change-Id: I5b262b71364c11f648b579a8bdb6fa993ecb4a81 CRs-Fixed: 880180 --- core/hdd/src/wlan_hdd_wext.c | 33 ++------------------------------- core/wma/inc/wma.h | 2 -- core/wma/src/wma_main.c | 6 ------ 3 files changed, 2 insertions(+), 39 deletions(-) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 153663ee8b0c..3b50abf90b2f 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -160,7 +160,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_TXRX_FWSTATS_RESET 41 #define WE_SET_MAX_TX_POWER_2_4 42 #define WE_SET_MAX_TX_POWER_5_0 43 -#define WE_SET_POWER_GATING 44 +/* 44 is unused */ /* Private ioctl for packet powe save */ #define WE_PPS_PAID_MATCH 45 #define WE_PPS_GID_MATCH 46 @@ -247,7 +247,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_GET_AMSDU 28 #define WE_GET_TXPOW_2G 29 #define WE_GET_TXPOW_5G 30 -#define WE_GET_POWER_GATING 31 +/* 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 @@ -5698,16 +5698,6 @@ static int __iw_setint_getnone(struct net_device *dev, break; } - case WE_SET_POWER_GATING: - { - hddLog(LOG1, "WMI_PDEV_PARAM_POWER_GATING_SLEEP val %d", - set_value); - ret = wma_cli_set_command(pAdapter->sessionId, - WMI_PDEV_PARAM_POWER_GATING_SLEEP, - (set_value) ? true : false, PDEV_CMD); - break; - } - /* Firmware debug log */ case WE_DBGLOG_LOG_LEVEL: { @@ -6681,15 +6671,6 @@ static int __iw_setnone_getint(struct net_device *dev, break; } - case WE_GET_POWER_GATING: - { - hddLog(LOG1, "GET WMI_PDEV_PARAM_POWER_GATING_SLEEP"); - *value = wma_cli_get_command(pAdapter->sessionId, - WMI_PDEV_PARAM_POWER_GATING_SLEEP, - PDEV_CMD); - break; - } - case WE_GET_PPS_PAID_MATCH: { hddLog(LOG1, "GET WMI_VDEV_PPS_PAID_MATCH"); @@ -9917,11 +9898,6 @@ static const struct iw_priv_args we_private_args[] = { 0, "txpow5g"}, - {WE_SET_POWER_GATING, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, - "pwrgating"}, - /* Sub-cmds DBGLOG specific commands */ {WE_DBGLOG_LOG_LEVEL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -10275,11 +10251,6 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_txpow5g"}, - {WE_GET_POWER_GATING, - 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_pwrgating"}, - {WE_GET_PPS_PAID_MATCH, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 2993a9fcd0e7..3028688cb682 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -638,7 +638,6 @@ typedef struct { * @rxchainmask: rx chain mask * @txpow2g: tx power limit for 2GHz * @txpow5g: tx power limit for 5GHz - * @pwrgating: enable/disable power gating sleep * @burst_enable: is burst enable/disable * @burst_dur: burst duration * @@ -658,7 +657,6 @@ typedef struct { uint32_t rxchainmask; uint32_t txpow2g; uint32_t txpow5g; - uint32_t pwrgating; uint32_t burst_enable; uint32_t burst_dur; } pdev_cli_config_t; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index f36fd45a7d94..9ecbdecc7637 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -322,9 +322,6 @@ int wma_cli_get_command(int vdev_id, int param_id, int vpdev) case WMI_PDEV_PARAM_TXPOWER_LIMIT5G: ret = wma->pdevconfig.txpow5g; break; - case WMI_PDEV_PARAM_POWER_GATING_SLEEP: - ret = wma->pdevconfig.pwrgating; - break; case WMI_PDEV_PARAM_BURST_ENABLE: ret = wma->pdevconfig.burst_enable; break; @@ -1361,9 +1358,6 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, case WMI_PDEV_PARAM_BURST_DUR: wma->pdevconfig.burst_dur = privcmd->param_value; break; - case WMI_PDEV_PARAM_POWER_GATING_SLEEP: - wma->pdevconfig.pwrgating = privcmd->param_value; - break; case WMI_PDEV_PARAM_TXPOWER_LIMIT2G: wma->pdevconfig.txpow2g = privcmd->param_value; if ((pMac->roam.configParam.bandCapability == -- cgit v1.2.3 From f7fae4873233f0011977bb66885657c67457fc7d Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 8 Dec 2015 12:54:46 -0800 Subject: qcacld-3.0: Enable athdiag debug support for SNOC devices - Athdiag debug support is enabled for PCIe devices but disabled for integrated SNOC devices like iHelium. - Enable athdiag debug feature support for SNOC devices as well. Change-Id: I73ce74286bf59147e45868e424de4ee1bc858ca0 CRs-Fixed: 948890 --- Kbuild | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Kbuild b/Kbuild index e21632faec12..23c60360a9e3 100644 --- a/Kbuild +++ b/Kbuild @@ -1266,6 +1266,11 @@ ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) CDEFINES += -DWLAN_FEATURE_RX_FULL_REORDER_OL endif +# Enable athdiag procfs debug support for adrastea +ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) +CDEFINES += -DCONFIG_ATH_PROCFS_DIAG_SUPPORT +endif + # NOTE: CONFIG_64BIT_PADDR requires CONFIG_HELIUMPLUS ifeq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) CONFIG_HELIUMPLUS := y -- cgit v1.2.3 From 9db84666c145e42d99b4ea7d623ecdcd3e23de6f Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 9 Nov 2015 15:15:01 -0800 Subject: qcacld-3.0: Convert wlan_hdd_green_ap.c to unified logging Currently the HDD code uses a variety of logging APIs. In qcacld-3.0 HDD should converge on a unified set of logging APIs. Update wlan_hdd_green_ap.c to use the unified set of APIs. Change-Id: If58683a833b1650a6cbea147debcead2551697da CRs-Fixed: 937202 --- core/hdd/src/wlan_hdd_green_ap.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/core/hdd/src/wlan_hdd_green_ap.c b/core/hdd/src/wlan_hdd_green_ap.c index 7cf2c23212f6..9cc9117dac6b 100644 --- a/core/hdd/src/wlan_hdd_green_ap.c +++ b/core/hdd/src/wlan_hdd_green_ap.c @@ -26,6 +26,9 @@ * */ +/* denote that this file does not allow legacy hddLog */ +#define HDD_DISALLOW_LEGACY_HDDLOG 1 + /* Include Files */ #include #include @@ -120,7 +123,7 @@ static int hdd_wlan_green_ap_enable(hdd_adapter_t *adapter, { int ret; - hddLog(LOG1, FL("Set Green-AP val: %d"), enable); + hdd_notice("Set Green-AP val: %d", enable); ret = wma_cli_set_command(adapter->sessionId, WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, @@ -146,8 +149,8 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, if (green_ap == NULL) return; - hddLog(LOG1, FL("Green-AP event: %d, state: %d, num_nodes: %d"), - event, green_ap->ps_state, green_ap->num_nodes); + hdd_notice("Green-AP event: %d, state: %d, num_nodes: %d", + event, green_ap->ps_state, green_ap->num_nodes); /* handle the green ap ps event */ switch (event) { @@ -174,13 +177,13 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, break; default: - hddLog(LOGE, FL("invalid event %d"), event); + hdd_err("invalid event %d", event); break; } /* Confirm that power save is enabled before doing state transitions */ if (!green_ap->ps_enable) { - hddLog(CDF_TRACE_LEVEL_INFO, FL("Green-AP is disabled")); + hdd_notice("Green-AP is disabled"); hdd_wlan_green_ap_update(hdd_ctx, GREEN_AP_PS_IDLE_STATE, GREEN_AP_PS_WAIT_EVENT); @@ -189,7 +192,7 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); if (adapter == NULL) { - hddLog(LOGE, FL("Green-AP no SAP adapter")); + hdd_err("Green-AP no SAP adapter"); goto done; } @@ -236,7 +239,7 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, case GREEN_AP_PS_ON_STATE: if (green_ap->num_nodes) { if (hdd_wlan_green_ap_enable(adapter, 0)) { - hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + hdd_err("FAILED TO SET GREEN-AP mode"); goto done; } hdd_wlan_green_ap_update(hdd_ctx, @@ -251,7 +254,7 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, GREEN_AP_PS_ON_EVENT); if (hdd_wlan_green_ap_enable(adapter, 0)) { - hddLog(LOGE, FL("FAILED TO SET GREEN-AP mode")); + hdd_err("FAILED TO SET GREEN-AP mode"); goto done; } @@ -261,7 +264,7 @@ static void hdd_wlan_green_ap_mc(struct hdd_context_s *hdd_ctx, break; default: - hddLog(LOGE, FL("invalid state %d"), green_ap->ps_state); + hdd_err("invalid state %d", green_ap->ps_state); hdd_wlan_green_ap_update(hdd_ctx, GREEN_AP_PS_OFF_STATE, GREEN_AP_PS_WAIT_EVENT); break; @@ -283,7 +286,7 @@ static void hdd_wlan_green_ap_timer_fn(void *ctx) struct hdd_green_ap_ctx *green_ap; if (0 != wlan_hdd_validate_context(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + hdd_err("HDD context is not valid"); return; } @@ -307,7 +310,7 @@ static CDF_STATUS hdd_wlan_green_ap_attach(struct hdd_context_s *hdd_ctx) green_ap = cdf_mem_malloc(sizeof(*green_ap)); if (!green_ap) { - hddLog(LOGP, FL("Memory allocation for Green-AP failed!")); + hdd_alert("Memory allocation for Green-AP failed!"); status = CDF_STATUS_E_NOMEM; goto error; } @@ -344,7 +347,7 @@ static CDF_STATUS hdd_wlan_green_ap_deattach(struct hdd_context_s *hdd_ctx) ENTER(); if (green_ap == NULL) { - hddLog(LOG1, FL("Green-AP is not enabled")); + hdd_notice("Green-AP is not enabled"); status = CDF_STATUS_E_NOSUPPORT; goto done; } @@ -356,7 +359,7 @@ static CDF_STATUS hdd_wlan_green_ap_deattach(struct hdd_context_s *hdd_ctx) /* Destroy the Green AP timer */ if (!CDF_IS_STATUS_SUCCESS(cdf_mc_timer_destroy(&green_ap->ps_timer))) - hddLog(LOG1, FL("Cannot deallocate Green-AP's timer")); + hdd_notice("Cannot deallocate Green-AP's timer"); /* release memory */ cdf_mem_zero(green_ap, sizeof(*green_ap)); @@ -378,7 +381,7 @@ done: void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx) { if (!CDF_IS_STATUS_SUCCESS(hdd_wlan_green_ap_attach(hdd_ctx))) - hddLog(LOGE, FL("Failed to allocate Green-AP resource")); + hdd_err("Failed to allocate Green-AP resource"); } /** @@ -390,7 +393,7 @@ void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx) void hdd_wlan_green_ap_deinit(struct hdd_context_s *hdd_ctx) { if (!CDF_IS_STATUS_SUCCESS(hdd_wlan_green_ap_deattach(hdd_ctx))) - hddLog(LOGE, FL("Cannot deallocate Green-AP resource")); + hdd_err("Cannot deallocate Green-AP resource"); } /** @@ -408,10 +411,9 @@ void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_START_EVENT); } else { hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT); - hddLog(LOG1, - "Green-AP: is disabled, due to sta_concurrency: %d, enable2x2: %d, enableGreenAP: %d", - CDF_STA_MASK & hdd_ctx->concurrency_mode, - cfg->enable2x2, cfg->enableGreenAP); + hdd_notice("Green-AP: is disabled, due to sta_concurrency: %d, enable2x2: %d, enableGreenAP: %d", + CDF_STA_MASK & hdd_ctx->concurrency_mode, + cfg->enable2x2, cfg->enableGreenAP); } } -- cgit v1.2.3 From 535f45dacad6adc1abe51567ba7a539a81cde246 Mon Sep 17 00:00:00 2001 From: Kabilan Kannan Date: Mon, 23 Nov 2015 01:56:12 -0800 Subject: qcacld-3.0: Pass TDLS teardown notification interval to target qcacld-2.0 to qcacld-3.0 propagation. Firmware uses same notification interval to send trigger to the driver for both TDLS setup and TDLS teardown operations. In ideal scenario firmware needs to have an option to configure different values for TDLS setup and TDLS tear down operations. This change will enable firmware to have different values for setup and teardown operations. Change-Id: I300350c56d4ef23993953338529f29df2ea122a1 CRs-Fixed: 920835 --- core/hdd/inc/wlan_hdd_cfg.h | 20 ++++++++++-- core/hdd/inc/wlan_hdd_tdls.h | 2 ++ core/hdd/src/wlan_hdd_cfg.c | 7 +++++ core/hdd/src/wlan_hdd_tdls.c | 72 ++++++++------------------------------------ core/wma/inc/wma.h | 2 ++ core/wma/src/wma_features.c | 8 +++-- 6 files changed, 47 insertions(+), 64 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 56522889e4c4..90f64e819f54 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1538,22 +1538,35 @@ typedef enum { #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 (5000) +#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 (100) +#define CFG_TDLS_TX_PACKET_THRESHOLD_DEFAULT (10) #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 (2000) + + #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 (5) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT (1) #define CFG_TDLS_RSSI_TRIGGER_THRESHOLD "gTDLSRSSITriggerThreshold" #define CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN (-120) @@ -3087,6 +3100,7 @@ struct hdd_config { uint32_t fTDLSTxStatsPeriod; uint32_t fTDLSTxPacketThreshold; uint32_t fTDLSMaxDiscoveryAttempt; + uint32_t tdls_idle_timeout; uint32_t fTDLSIdlePacketThreshold; int32_t fTDLSRSSITriggerThreshold; int32_t fTDLSRSSITeardownThreshold; diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 33557fc20901..c1f06cec7460 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -394,6 +394,7 @@ typedef struct { * @puapsd_mask: puapsd mask * @puapsd_inactivity_time: puapsd inactivity time * @puapsd_rx_frame_threshold: puapsd rx frame threshold + * @teardown_notification_ms: tdls teardown notification interval */ typedef struct { uint32_t vdev_id; @@ -409,6 +410,7 @@ typedef struct { uint32_t puapsd_mask; uint32_t puapsd_inactivity_time; uint32_t puapsd_rx_frame_threshold; + uint32_t teardown_notification_ms; } tdlsInfo_t; int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter); diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index b0d7e88e7ae3..9b495dd7c7fb 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -2232,6 +2232,13 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MIN, CFG_TDLS_MAX_DISCOVERY_ATTEMPT_MAX), + REG_VARIABLE(CFG_TDLS_IDLE_TIMEOUT, WLAN_PARAM_Integer, + struct hdd_config, tdls_idle_timeout, + 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, struct hdd_config, fTDLSIdlePacketThreshold, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index aa0e442bdd5d..58f4660a5807 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -438,7 +438,7 @@ static void dump_tdls_state_param_setting(tdlsInfo_t *info) 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" + "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" ), info->vdev_id, info->tdls_state, @@ -452,7 +452,8 @@ static void dump_tdls_state_param_setting(tdlsInfo_t *info) info->peer_traffic_response_timeout, info->puapsd_mask, info->puapsd_inactivity_time, - info->puapsd_rx_frame_threshold); + info->puapsd_rx_frame_threshold, + info->teardown_notification_ms); } @@ -700,6 +701,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddCtx->config->fTDLSPuapsdInactivityTimer; tInfo->puapsd_rx_frame_threshold = pHddCtx->config->fTDLSRxFrameThreshold; + tInfo->teardown_notification_ms = + pHddCtx->config->tdls_idle_timeout; dump_tdls_state_param_setting(tInfo); @@ -799,6 +802,8 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) pHddCtx->config->fTDLSPuapsdInactivityTimer; tInfo->puapsd_rx_frame_threshold = pHddCtx->config->fTDLSRxFrameThreshold; + tInfo->teardown_notification_ms = + pHddCtx->config->tdls_idle_timeout; dump_tdls_state_param_setting(tInfo); @@ -1634,36 +1639,10 @@ int wlan_hdd_tdls_set_params(struct net_device *dev, pHddCtx->config->fTDLSPuapsdInactivityTimer; tdlsParams->puapsd_rx_frame_threshold = pHddCtx->config->fTDLSRxFrameThreshold; + tdlsParams->teardown_notification_ms = + pHddCtx->config->tdls_idle_timeout; - hddLog(LOG1, - "%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 ", - __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); + dump_tdls_state_param_setting(tdlsParams); cdf_ret_status = sme_update_fw_tdls_state(pHddCtx->hHal, tdlsParams, true); if (CDF_STATUS_SUCCESS != cdf_ret_status) { @@ -1768,35 +1747,10 @@ void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, hdd_ctx->config->fTDLSPuapsdInactivityTimer; tdls_param->puapsd_rx_frame_threshold = hdd_ctx->config->fTDLSRxFrameThreshold; + tdls_param->teardown_notification_ms = + hdd_ctx->config->tdls_idle_timeout; - hddLog(CDF_TRACE_LEVEL_DEBUG, - 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 "), - 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); + dump_tdls_state_param_setting(tdls_param); cdf_ret_status = sme_update_fw_tdls_state(hdd_ctx->hHal, tdls_param, diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 3028688cb682..afffb5e05dad 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1784,6 +1784,7 @@ typedef enum { * @puapsd_mask: uapsd mask * @puapsd_inactivity_time: uapsd inactivity time * @puapsd_rx_frame_threshold: uapsd rx frame threshold + * @teardown_notification_ms: tdls teardown notification interval */ typedef struct wma_tdls_params { uint32_t vdev_id; @@ -1799,6 +1800,7 @@ typedef struct wma_tdls_params { uint32_t puapsd_mask; uint32_t puapsd_inactivity_time; uint32_t puapsd_rx_frame_threshold; + uint32_t teardown_notification_ms; } t_wma_tdls_params; /** diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 32b3bc4f356e..7ed21d9d8a54 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -6509,6 +6509,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) 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; WMA_LOGD("%s: tdls_mode: %d, state: %d, " "notification_interval_ms: %d, " @@ -6521,7 +6523,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) "tdls_peer_traffic_response_timeout: %d, " "tdls_puapsd_mask: 0x%x, " "tdls_puapsd_inactivity_time: %d, " - "tdls_puapsd_rx_frame_threshold: %d ", + "tdls_puapsd_rx_frame_threshold: %d, " + "teardown_notification_ms: %d", __func__, tdls_mode, cmd->state, cmd->notification_interval_ms, cmd->tx_discovery_threshold, @@ -6533,7 +6536,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) cmd->tdls_peer_traffic_response_timeout_ms, cmd->tdls_puapsd_mask, cmd->tdls_puapsd_inactivity_time_ms, - cmd->tdls_puapsd_rx_frame_threshold); + cmd->tdls_puapsd_rx_frame_threshold, + cmd->teardown_notification_ms); if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len, WMI_TDLS_SET_STATE_CMDID)) { -- cgit v1.2.3 From 014b263faa7172707afe01c512ce9f0d8c4dcfe3 Mon Sep 17 00:00:00 2001 From: Kabilan Kannan Date: Mon, 23 Nov 2015 04:44:59 -0800 Subject: qcacld-3.0: Configure TDLS peer mac and kickout threshold to target qcacld-2.0 to qcacld-3.0 propagation. Add new TDLS mode for TDLS external control operation to achieve power save on the target. Firmware will use this mode to control timers precisely and save the power. Add configuration "gTDLSPeerKickoutThreshold" to fine tune TDLS peer sta kick out operation. Change-Id: Ie941f93b54983ca6323ef4384a66e0807a56a7b1 CRs-Fixed: 929749 --- core/hdd/inc/wlan_hdd_cfg.h | 15 +++++ core/hdd/inc/wlan_hdd_tdls.h | 10 ++++ core/hdd/src/wlan_hdd_cfg.c | 8 +++ core/hdd/src/wlan_hdd_tdls.c | 130 +++++++++++++++++++++++++++++++++--------- core/sme/inc/sme_api.h | 12 +++- core/sme/src/common/sme_api.c | 8 +++ core/wma/inc/wma.h | 8 ++- core/wma/inc/wma_types.h | 4 ++ core/wma/src/wma_features.c | 16 +++++- 9 files changed, 179 insertions(+), 32 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 90f64e819f54..ce3d8c4f10e9 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1654,6 +1654,20 @@ typedef enum { #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 /* Enable/Disable LPWR Image(cMEM uBSP) Transition */ @@ -3118,6 +3132,7 @@ struct hdd_config { uint8_t fTDLSPrefOffChanNum; uint8_t fTDLSPrefOffChanBandwidth; uint8_t enable_tdls_scan; + uint32_t tdls_peer_kickout_threshold; #endif #ifdef WLAN_SOFTAP_VSTA_FEATURE bool fEnableVSTASupport; diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index c1f06cec7460..801857c32176 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -134,12 +134,15 @@ typedef struct { * @eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY: suppress implicit trigger, * but respond to the peer * @eTDLS_SUPPORT_ENABLED: implicit trigger + * @eTDLS_SUPPORT_EXTERNAL_CONTROL: External control means implicit + * trigger but only to a peer mac configured by user space. */ typedef enum { eTDLS_SUPPORT_NOT_ENABLED = 0, eTDLS_SUPPORT_DISABLED, eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, eTDLS_SUPPORT_ENABLED, + eTDLS_SUPPORT_EXTERNAL_CONTROL, } eTDLSSupportMode; /** @@ -395,6 +398,8 @@ typedef struct { * @puapsd_inactivity_time: puapsd inactivity time * @puapsd_rx_frame_threshold: puapsd rx frame threshold * @teardown_notification_ms: tdls teardown notification interval + * @tdls_peer_kickout_threshold: tdls packets threshold + * for peer kickout operation */ typedef struct { uint32_t vdev_id; @@ -411,6 +416,7 @@ typedef struct { uint32_t puapsd_inactivity_time; uint32_t 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); @@ -525,6 +531,10 @@ int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, int wlan_hdd_tdls_set_force_peer(hdd_adapter_t *pAdapter, const uint8_t *mac, bool forcePeer); +int wlan_hdd_tdls_update_peer_mac(hdd_adapter_t *adapter, + const uint8_t *mac, + uint32_t peer_state); + int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, const uint8_t *peer); int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 9b495dd7c7fb..7113499ec329 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -2351,6 +2351,14 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, + struct hdd_config, 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 diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 58f4660a5807..3295fb793a8f 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -438,7 +438,7 @@ static void dump_tdls_state_param_setting(tdlsInfo_t *info) 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" + "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" ), info->vdev_id, info->tdls_state, @@ -453,7 +453,8 @@ static void dump_tdls_state_param_setting(tdlsInfo_t *info) info->puapsd_mask, info->puapsd_inactivity_time, info->puapsd_rx_frame_threshold, - info->teardown_notification_ms); + info->teardown_notification_ms, + info->tdls_peer_kickout_threshold); } @@ -639,6 +640,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddCtx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; hddLog(CDF_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__); + } else if (true == pHddCtx->config->fTDLSExternalControl) { + pHddCtx->tdls_mode = eTDLS_SUPPORT_EXTERNAL_CONTROL; } else { pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED; } @@ -703,7 +706,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddCtx->config->fTDLSRxFrameThreshold; tInfo->teardown_notification_ms = pHddCtx->config->tdls_idle_timeout; - + tInfo->tdls_peer_kickout_threshold = + pHddCtx->config->tdls_peer_kickout_threshold; dump_tdls_state_param_setting(tInfo); cdf_ret_status = sme_update_fw_tdls_state(pHddCtx->hHal, tInfo, true); @@ -804,7 +808,8 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) pHddCtx->config->fTDLSRxFrameThreshold; tInfo->teardown_notification_ms = pHddCtx->config->tdls_idle_timeout; - + tInfo->tdls_peer_kickout_threshold = + pHddCtx->config->tdls_peer_kickout_threshold; dump_tdls_state_param_setting(tInfo); cdf_ret_status = @@ -1356,7 +1361,8 @@ int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter, hddTdlsPeer_t *curr_peer; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode) + if (eTDLS_SUPPORT_ENABLED != pHddCtx->tdls_mode && + eTDLS_SUPPORT_EXTERNAL_CONTROL != pHddCtx->tdls_mode) return -EINVAL; curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac); @@ -1537,11 +1543,11 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, pAdapter = pAdapterNode->pAdapter; pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); if (NULL != pHddTdlsCtx) { - if (eTDLS_SUPPORT_ENABLED == tdls_mode) + 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)) + (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); } status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); @@ -1592,7 +1598,8 @@ int wlan_hdd_tdls_set_params(struct net_device *dev, } /* copy the configuration only when given tdls mode is implicit trigger enable */ - if (eTDLS_SUPPORT_ENABLED == req_tdls_mode) { + if (eTDLS_SUPPORT_ENABLED == req_tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == req_tdls_mode) { memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t)); } @@ -1641,6 +1648,8 @@ int wlan_hdd_tdls_set_params(struct net_device *dev, pHddCtx->config->fTDLSRxFrameThreshold; tdlsParams->teardown_notification_ms = pHddCtx->config->tdls_idle_timeout; + tdlsParams->tdls_peer_kickout_threshold = + pHddCtx->config->tdls_peer_kickout_threshold; dump_tdls_state_param_setting(tdlsParams); @@ -1695,15 +1704,14 @@ void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, if (tdls_prohibited) { hdd_ctx->tdls_mode = eTDLS_SUPPORT_NOT_ENABLED; } else { - if (false == hdd_ctx->config->fEnableTDLSImplicitTrigger) { - hdd_ctx->tdls_mode = - eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; - } else { + if (false == hdd_ctx->config->fEnableTDLSImplicitTrigger) + hdd_ctx->tdls_mode = eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY; + else if (true == hdd_ctx->config->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 = cdf_mem_malloc(sizeof(*tdls_param)); if (!tdls_param) { hddLog(CDF_TRACE_LEVEL_ERROR, @@ -1749,6 +1757,8 @@ void wlan_hdd_update_tdls_info(hdd_adapter_t *adapter, bool tdls_prohibited, hdd_ctx->config->fTDLSRxFrameThreshold; tdls_param->teardown_notification_ms = hdd_ctx->config->tdls_idle_timeout; + tdls_param->tdls_peer_kickout_threshold = + hdd_ctx->config->tdls_peer_kickout_threshold; dump_tdls_state_param_setting(tdls_param); @@ -1818,6 +1828,38 @@ int wlan_hdd_tdls_set_extctrl_param(hdd_adapter_t *pAdapter, const uint8_t *mac, return 0; } +/** + * wlan_hdd_tdls_update_peer_mac() - Update the peer mac information to firmware + * @adapter: 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 *adapter, const uint8_t *mac, + uint32_t peer_state) +{ + tSmeTdlsPeerStateParams sme_tdls_peer_state_params = {0}; + CDF_STATUS status = CDF_STATUS_E_FAILURE; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + sme_tdls_peer_state_params.vdevId = adapter->sessionId; + cdf_mem_copy(&sme_tdls_peer_state_params.peerMacAddr, mac, + sizeof(sme_tdls_peer_state_params.peerMacAddr)); + sme_tdls_peer_state_params.peerState = peer_state; + status = sme_update_tdls_peer_state(hdd_ctx->hHal, + &sme_tdls_peer_state_params); + if (CDF_STATUS_SUCCESS != status) { + hddLog(LOGE, FL("sme_UpdateTdlsPeerState failed for "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac)); + return -EPERM; + } + return 0; +} + /** * wlan_hdd_tdls_set_force_peer() - set/clear isForcedPeer flag on a peer * @pAdapter: HDD adapter @@ -2124,13 +2166,13 @@ void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter) FL("update %d"), pHddTdlsCtx->threshold_config.tx_period_t); - if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode) { + 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); - + wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); } + mutex_unlock(&pHddCtx->tdls_lock); } @@ -2418,6 +2460,15 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work) 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; } } @@ -2648,6 +2699,7 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, } /* 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 operatoin */ wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, false); @@ -2774,6 +2826,7 @@ void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter) /* 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) { hddLog(LOG1, ("%s: revert tdls mode %d"), __func__, @@ -3978,6 +4031,15 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, "%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; + } if (0 != wlan_hdd_tdls_set_extctrl_param(pAdapter, peer, chan, max_latency, op_class, min_bandwidth)) { @@ -4032,6 +4094,15 @@ int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, "%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; + } if (0 != wlan_hdd_set_callback(pTdlsPeer, NULL)) { CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "%s TDLS set callback Failed", __func__); @@ -4547,8 +4618,9 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *adapter) int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel) { if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && - (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || - eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { if (offchannel < CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN || offchannel > CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) { hddLog(LOGE, FL("Invalid tdls off channel %u"), @@ -4579,8 +4651,9 @@ int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel) int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset) { if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && - (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || - eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXTERNAL_CONTROL == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { hdd_ctx->tdls_channel_offset = 0; switch (offchanoffset) { @@ -4650,13 +4723,14 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode) } if ((true == hdd_ctx->config->fEnableTDLSOffChannel) && (eTDLS_SUPPORT_ENABLED == hdd_ctx->tdls_mode || - eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { - conn_peer = wlan_hdd_tdls_find_first_connected_peer(adapter); - if (NULL == conn_peer) { + eTDLS_SUPPORT_EXTERNAL_CONTROL == hdd_ctx->tdls_mode || + eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == hdd_ctx->tdls_mode)) { + conn_peer = wlan_hdd_tdls_find_first_connected_peer(adapter); + if (NULL == conn_peer) { hddLog(LOGP, FL("No TDLS Connected Peer")); - return -EPERM; - } + return -EPERM; + } } else { hddLog(LOGP, FL("TDLS Connection not supported")); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index b4af548b7f9d..e82c1515cec8 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -156,10 +156,20 @@ typedef struct _smeTdlsPeerCapParams { uint8_t opClassForPrefOffChan; } tSmeTdlsPeerCapParams; +/** + * eSmeTdlsPeerState - tdls peer state + * @eSME_TDLS_PEER_STATE_PEERING: tdls connection in progress + * @eSME_TDLS_PEER_STATE_CONNECTED: tdls peer is connected + * @eSME_TDLS_PEER_STATE_TEARDOWN: tdls peer is tear down + * @eSME_TDLS_PEER_ADD_MAC_ADDR: add peer mac into connection table + * @eSME_TDLS_PEER_REMOVE_MAC_ADDR: remove peer mac from connection table + */ typedef enum { eSME_TDLS_PEER_STATE_PEERING, eSME_TDLS_PEER_STATE_CONNECTED, - eSME_TDLS_PEER_STATE_TEARDOWN + eSME_TDLS_PEER_STATE_TEARDOWN, + eSME_TDLS_PEER_ADD_MAC_ADDR, + eSME_TDLS_PEER_REMOVE_MAC_ADDR, } eSmeTdlsPeerState; typedef struct _smeTdlsPeerStateParams { diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 948f8bb74e71..1f511656b5cb 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -10020,6 +10020,14 @@ CDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal, WMA_TDLS_PEER_STATE_TEARDOWN; break; + case eSME_TDLS_PEER_ADD_MAC_ADDR: + pTdlsPeerStateParams->peerState = WMA_TDLS_PEER_ADD_MAC_ADDR; + break; + + case eSME_TDLS_PEER_REMOVE_MAC_ADDR: + pTdlsPeerStateParams->peerState = WMA_TDLS_PEER_REMOVE_MAC_ADDR; + break; + default: CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, FL("invalid peer state param (%d)"), diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index afffb5e05dad..9a3cea4b1908 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -408,18 +408,21 @@ typedef enum { #ifdef FEATURE_WLAN_TDLS /** - * enum t_wma_tdls_mode: TDLS mode + * enum t_wma_tdls_mode - TDLS mode * @WMA_TDLS_SUPPORT_NOT_ENABLED: tdls is disable * @WMA_TDLS_SUPPORT_DISABLED: suppress implicit trigger and not respond to peer * @WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY: suppress implicit trigger, * but respond to the peer * @WMA_TDLS_SUPPORT_ENABLED: implicit trigger + * @WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL: External control means + * implicit trigger but only to a peer mac configured by user space. */ typedef enum { WMA_TDLS_SUPPORT_NOT_ENABLED = 0, WMA_TDLS_SUPPORT_DISABLED, WMA_TDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY, WMA_TDLS_SUPPORT_ENABLED, + WMA_TDLS_SUPPORT_ACTIVE_EXTERNAL_CONTROL, } t_wma_tdls_mode; /** @@ -1785,6 +1788,8 @@ typedef enum { * @puapsd_inactivity_time: uapsd inactivity time * @puapsd_rx_frame_threshold: uapsd rx frame threshold * @teardown_notification_ms: tdls teardown notification interval + * @tdls_peer_kickout_threshold: tdls packet threshold for + * peer kickout operation */ typedef struct wma_tdls_params { uint32_t vdev_id; @@ -1801,6 +1806,7 @@ typedef struct wma_tdls_params { uint32_t puapsd_inactivity_time; uint32_t puapsd_rx_frame_threshold; uint32_t teardown_notification_ms; + uint32_t tdls_peer_kickout_threshold; } t_wma_tdls_params; /** diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 17caf8f1de75..5c5c9747ff70 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -617,11 +617,15 @@ struct ar6k_testmode_cmd_data { * @WMA_TDLS_PEER_STATE_PEERING: peer is making connection * @WMA_TDLS_PEER_STATE_CONNECTED: peer is connected * @WMA_TDLS_PEER_STATE_TEARDOWN: peer is teardown + * @WMA_TDLS_PEER_ADD_MAC_ADDR: add peer into connection table + * @WMA_TDLS_PEER_REMOVE_MAC_ADDR: remove peer from connection table */ typedef enum { WMA_TDLS_PEER_STATE_PEERING, WMA_TDLS_PEER_STATE_CONNECTED, WMA_TDLS_PEER_STATE_TEARDOWN, + WMA_TDLS_PEER_ADD_MAC_ADDR, + WMA_TDLS_PEER_REMOVE_MAC_ADDR, } WMA_TdlsPeerState; /** diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 7ed21d9d8a54..acebf9b3ae3f 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -6492,6 +6492,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) 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; } @@ -6511,6 +6513,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) 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, " @@ -6524,7 +6528,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) "tdls_puapsd_mask: 0x%x, " "tdls_puapsd_inactivity_time: %d, " "tdls_puapsd_rx_frame_threshold: %d, " - "teardown_notification_ms: %d", + "teardown_notification_ms: %d, " + "tdls_peer_kickout_threshold: %d", __func__, tdls_mode, cmd->state, cmd->notification_interval_ms, cmd->tx_discovery_threshold, @@ -6537,7 +6542,8 @@ int wma_update_fw_tdls_state(WMA_HANDLE handle, void *pwmaTdlsparams) cmd->tdls_puapsd_mask, cmd->tdls_puapsd_inactivity_time_ms, cmd->tdls_puapsd_rx_frame_threshold, - cmd->teardown_notification_ms); + 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)) { @@ -6621,6 +6627,12 @@ int wma_update_tdls_peer_state(WMA_HANDLE handle, case WMA_TDLS_PEER_STATE_TEARDOWN: cmd->peer_state = WMI_TDLS_PEER_STATE_TEARDOWN; break; + case WMA_TDLS_PEER_ADD_MAC_ADDR: + cmd->peer_state = WMI_TDLS_PEER_ADD_MAC_ADDR; + break; + case WMA_TDLS_PEER_REMOVE_MAC_ADDR: + cmd->peer_state = WMI_TDLS_PEER_REMOVE_MAC_ADDR; + break; } WMA_LOGD("%s: vdev_id: %d, peerStateParams->peerMacAddr: %pM, " -- cgit v1.2.3 From 02be99a6c5768fa82800cfe84893e958ba4f9551 Mon Sep 17 00:00:00 2001 From: Kabilan Kannan Date: Sun, 29 Nov 2015 16:04:05 -0800 Subject: qcacld-3.0: Change TDLS default teardown parameters qcacld-2.0 to qcacld-3.0 propagation. Current TDLS default teardown interval does not work in all the scenarios. Hence, change the default teadown interval to 5 seconds and default TDLS idle packet threshold to 3 to support all TDLS use cases. Change-Id: Idf8b4cd02963d24350a1322ac4c7465fbfc7204f CRs-Fixed: 936003 --- core/hdd/inc/wlan_hdd_cfg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index ce3d8c4f10e9..2d4deeda24c7 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1560,13 +1560,13 @@ typedef enum { #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 (2000) +#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 (1) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT (3) #define CFG_TDLS_RSSI_TRIGGER_THRESHOLD "gTDLSRSSITriggerThreshold" #define CFG_TDLS_RSSI_TRIGGER_THRESHOLD_MIN (-120) -- cgit v1.2.3 From a46e863ff5b520da796966558f3db663faf71b0a Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Mon, 23 Nov 2015 18:54:58 -0800 Subject: qcacld-3.0: Add configuration option for mpdu density qcacld-2.0 to qcacld-3.0 propagation Add configuration option for mpdu density through INI. Update the default value of mpdu density from 0 to 7. Change-Id: Ib97869d4aec160065c945cd62876d6fd191d63a5 CRs-Fixed: 941182 --- core/hdd/inc/wlan_hdd_cfg.h | 16 ++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 19 +++++++++++++++++++ core/mac/inc/wni_cfg.h | 2 +- core/mac/src/pe/lim/lim_api.c | 16 +++++++++------- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 2d4deeda24c7..3d5efe59eeab 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -138,6 +138,21 @@ #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" @@ -3384,6 +3399,7 @@ struct hdd_config { int8_t early_stop_scan_min_threshold; int8_t early_stop_scan_max_threshold; int8_t first_scan_bucket_threshold; + uint8_t ht_mpdu_density; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 7113499ec329..5192d0b5a493 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -500,6 +500,13 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_MAX_RX_AMPDU_FACTOR_MIN, CFG_MAX_RX_AMPDU_FACTOR_MAX), + REG_VARIABLE(CFG_HT_MPDU_DENSITY_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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, struct hdd_config, TxRate, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, @@ -5182,6 +5189,10 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hddLog(LOGE, "Name = [%s] Value = [%d]", CFG_FIRST_SCAN_BUCKET_THRESHOLD_NAME, pHddCtx->config->first_scan_bucket_threshold); + hddLog(LOGE, "Name = [%s] Value = [%u]", + CFG_HT_MPDU_DENSITY_NAME, + pHddCtx->config->ht_mpdu_density); + } @@ -5609,6 +5620,14 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx) "Could not pass on WNI_CFG_HT_AMPDU_PARAMS_MAX_RX_AMPDU_FACTOR to CFG"); } + if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_MPDU_DENSITY, + pConfig->ht_mpdu_density) == + CDF_STATUS_E_FAILURE) { + fStatus = false; + hddLog(LOGE, + "Could not pass on WNI_CFG_MPDU_DENSITY to CFG"); + } + if (sme_cfg_set_int (pHddCtx->hHal, WNI_CFG_SHORT_PREAMBLE, pConfig->fIsShortPreamble) == CDF_STATUS_E_FAILURE) { diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 53a1c8b77f4c..adc9e6513d56 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -1158,7 +1158,7 @@ enum { #define WNI_CFG_MPDU_DENSITY_STAMIN 0 #define WNI_CFG_MPDU_DENSITY_STAMAX 7 -#define WNI_CFG_MPDU_DENSITY_STADEF 0 +#define WNI_CFG_MPDU_DENSITY_STADEF 7 #define WNI_CFG_NUM_BUFF_ADVERT_STAMIN 0 #define WNI_CFG_NUM_BUFF_ADVERT_STAMAX 128 diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 2ed29da641de..bb825e71cc70 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -449,22 +449,24 @@ static tSirRetStatus __lim_init_config(tpAniSirGlobal pMac) if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) { - PELOGE(lim_log - (pMac, LOGE, - FL("could not retrieve HT AMPDU Param CFG")); - ) + lim_log(pMac, LOGE, FL("could not retrieve HT AMPDU Param")); return eSIR_FAILURE; } if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) { - PELOGE(lim_log - (pMac, LOGE, FL("could not retrieve AMPDU Factor CFG")); - ) + lim_log(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG")); return eSIR_FAILURE; } + if (wlan_cfg_get_int(pMac, WNI_CFG_MPDU_DENSITY, &val3) != + eSIR_SUCCESS) { + lim_log(pMac, LOGE, FL("could not retrieve MPDU Density CFG")); + return eSIR_FAILURE; + } + val16 = (uint16_t) val1; pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16; pAmpduParamInfo->maxRxAMPDUFactor = (uint8_t) val2; + pAmpduParamInfo->mpduDensity = (uint8_t)val3; if (cfg_set_int (pMac, WNI_CFG_HT_AMPDU_PARAMS, *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS) { -- cgit v1.2.3 From 763e040a5a1127294fdea4da7c40c19d599b1851 Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Mon, 26 Oct 2015 18:58:00 -0700 Subject: qcacld-3.0: BT AMP Cleanup in CSR Remove unused BT AMP code from CSR module Change-Id: I12ee3940ed8b9b4f50faffbed4ad949730cb1297 CRs-Fixed: 926965 --- core/sme/inc/csr_api.h | 34 ---- core/sme/inc/csr_support.h | 1 - core/sme/src/csr/csr_api_roam.c | 380 +++++++++++--------------------------- core/sme/src/csr/csr_api_scan.c | 16 +- core/sme/src/csr/csr_inside_api.h | 1 - core/sme/src/csr/csr_util.c | 16 -- 6 files changed, 104 insertions(+), 344 deletions(-) diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index a4194e8c96ef..bf2162d5a098 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -166,8 +166,6 @@ typedef enum { eCSR_BSS_TYPE_INFRA_AP, /* SoftAP AP */ eCSR_BSS_TYPE_IBSS, /* IBSS network we'll NOT start */ eCSR_BSS_TYPE_START_IBSS, /* IBSS network we'll start if no partners */ - 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; @@ -475,8 +473,6 @@ typedef enum { eCSR_ROAM_GEN_INFO, eCSR_ROAM_SET_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, @@ -588,20 +584,6 @@ typedef enum { #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 */ @@ -896,12 +878,6 @@ typedef struct tagCsrRoamModifyProfileFields { } 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 bit mask of all the needed phy mode defined in eCsrPhyMode */ @@ -1603,20 +1579,10 @@ typedef CDF_STATUS (*csr_roamSessionCloseCallback)(void *pContext); (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) #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)) #define CSR_IS_CLOSE_SESSION_COMMAND(pCommand) \ ((pCommand)->command == eSmeCommandDelStaSession) diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h index c484e6ec67b0..7614b1eae1b8 100644 --- a/core/sme/inc/csr_support.h +++ b/core/sme/inc/csr_support.h @@ -311,7 +311,6 @@ bool csr_is_security_match(tHalHandle hHal, tCsrAuthList *authType, eCsrEncryptionType *negotiatedMCCipher); bool csr_is_bss_type_match(eCsrRoamBssType bssType1, eCsrRoamBssType bssType2); bool csr_is_bss_type_ibss(eCsrRoamBssType bssType); -bool csr_is_bss_type_wds(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 diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 8c6f830ab4bc..f22b16d51cfe 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -4152,8 +4152,7 @@ CDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal pMac, uint32_t sessionId, pBssConfig->uPowerLimit); /* CB */ - if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_WDS_AP(pProfile) - || CSR_IS_IBSS(pProfile)) { + if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_IBSS(pProfile)) { channel = pProfile->operationChannel; } else { if (pBssDesc) { @@ -4214,7 +4213,6 @@ CDF_STATUS csr_roam_stop_network(tpAniSirGlobal pMac, uint32_t sessionId, pSession->bssParams.cbMode = pBssConfig->cbMode; /* For IBSS, we need to prepare some more information */ if (csr_is_bss_type_ibss(pProfile->BSSType) || - CSR_IS_WDS(pProfile) || CSR_IS_INFRA_AP(pProfile)) csr_roam_prepare_bss_params(pMac, sessionId, pProfile, pBssDesc, pBssConfig, pIes); @@ -4249,7 +4247,7 @@ CDF_STATUS csr_roam_stop_network(tpAniSirGlobal pMac, uint32_t sessionId, status = csr_roam_set_bss_config_cfg(pMac, sessionId, pProfile, pBssDesc, pBssConfig, pIes, false); - } else if (pBssDesc || CSR_IS_WDS_AP(pProfile) || + } else if (pBssDesc || CSR_IS_INFRA_AP(pProfile)) { /* * Neither in IBSS nor in Infra. We can go ahead and set @@ -4326,10 +4324,6 @@ eCsrJoinState csr_roam_join(tpAniSirGlobal pMac, uint32_t sessionId, return eCsrStopRoaming; } - if (CSR_IS_WDS_STA(pProfile) && - !CDF_IS_STATUS_SUCCESS(csr_roam_start_wds(pMac, sessionId, - pProfile, pBssDesc))) - return eCsrStopRoaming; if (!pIesLocal && !CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(pMac, pBssDesc, &pIesLocal))) { @@ -4560,7 +4554,6 @@ static void csr_roam_join_handle_profile(tpAniSirGlobal mac_ctx, /* * 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(profile)) { if (roam_info_ptr && session->bRefAssocStartCnt) { @@ -4685,8 +4678,7 @@ static void csr_roam_join_handle_profile(tpAniSirGlobal mac_ctx, *roam_state = eCsrStopRoaming; } return; - } else if ((CSR_IS_WDS_AP(profile)) || - (CSR_IS_INFRA_AP(profile))) { + } else if (CSR_IS_INFRA_AP(profile)) { /* Attempt to start this WDS... */ csr_roam_assign_default_param(mac_ctx, cmd); /* For AP WDS, we dont have any BSSDescription */ @@ -5772,16 +5764,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, #endif csr_roam_completion(mac_ctx, session_id, NULL, cmd, eCSR_ROAM_RESULT_FAILURE, false); -#ifdef FEATURE_WLAN_BTAMP_UT_RF - /* - * For WDS STA. To fix the issue where the WDS AP side may - * be too busy by BT activity and not able to receive - * WLAN traffic. Retry the join - */ - if (CSR_IS_WDS_STA(profile)) - csr_roam_start_join_retry_timer(mac_ctx, session_id, - CSR_JOIN_RETRY_TIMEOUT_PERIOD); -#endif break; case eCsrHddIssuedReassocToSameAP: case eCsrSmeIssuedReassocToSameAP: @@ -5937,119 +5919,90 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED; else session->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED; - if (!CSR_IS_WDS_STA(profile)) { - csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, + csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_JOINED, session_id); - bss_desc = &start_bss_rsp->bssDescription; - if (!CDF_IS_STATUS_SUCCESS - (csr_get_parsed_bss_description_ies(mac_ctx, bss_desc, - &ies_ptr))) { - sms_log(mac_ctx, LOGW, FL("cannot parse IBSS IEs")); - roam_info.pBssDesc = bss_desc; - csr_roam_call_callback(mac_ctx, session_id, &roam_info, - cmd->u.roamCmd.roamId, eCSR_ROAM_IBSS_IND, - eCSR_ROAM_RESULT_IBSS_START_FAILED); - return; - } - if (!CSR_IS_INFRA_AP(profile)) { - scan_res = - csr_scan_append_bss_description(mac_ctx, - bss_desc, ies_ptr, false, - session_id); - } - csr_roam_save_connected_bss_desc(mac_ctx, session_id, bss_desc); - csr_roam_free_connect_profile(mac_ctx, - &session->connectedProfile); - csr_roam_free_connected_info(mac_ctx, - &session->connectedInfo); - if (bss_desc) { - csr_roam_save_connected_infomation(mac_ctx, session_id, - profile, bss_desc, ies_ptr); - cdf_mem_copy(&roam_info.bssid, &bss_desc->bssId, - sizeof(struct cdf_mac_addr)); - } - /* We are done with the IEs so free it */ - cdf_mem_free(ies_ptr); + bss_desc = &start_bss_rsp->bssDescription; + if (!CDF_IS_STATUS_SUCCESS + (csr_get_parsed_bss_description_ies(mac_ctx, bss_desc, + &ies_ptr))) { + sms_log(mac_ctx, LOGW, FL("cannot parse IBSS IEs")); + roam_info.pBssDesc = bss_desc; + csr_roam_call_callback(mac_ctx, session_id, &roam_info, + cmd->u.roamCmd.roamId, eCSR_ROAM_IBSS_IND, + eCSR_ROAM_RESULT_IBSS_START_FAILED); + return; + } + if (!CSR_IS_INFRA_AP(profile)) { + scan_res = + csr_scan_append_bss_description(mac_ctx, + bss_desc, ies_ptr, false, + session_id); + } + csr_roam_save_connected_bss_desc(mac_ctx, session_id, bss_desc); + csr_roam_free_connect_profile(mac_ctx, + &session->connectedProfile); + csr_roam_free_connected_info(mac_ctx, + &session->connectedInfo); + if (bss_desc) { + csr_roam_save_connected_infomation(mac_ctx, session_id, + profile, bss_desc, ies_ptr); + cdf_mem_copy(&roam_info.bssid, &bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + } + /* We are done with the IEs so free it */ + cdf_mem_free(ies_ptr); #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR - WLAN_HOST_DIAG_LOG_ALLOC(ibss_log, - host_log_ibss_pkt_type, LOG_WLAN_IBSS_C); - if (ibss_log) { - if (CSR_INVALID_SCANRESULT_HANDLE == - cmd->u.roamCmd.hBSSList) { - /* - * We start the IBSS (didn't find any - * matched IBSS out there) - */ - ibss_log->eventId = - WLAN_IBSS_EVENT_START_IBSS_RSP; - } else { - ibss_log->eventId = - WLAN_IBSS_EVENT_JOIN_IBSS_RSP; - } - if (bss_desc) { - cdf_mem_copy(ibss_log->bssid, - bss_desc->bssId, 6); - ibss_log->operatingChannel = - bss_desc->channelId; - } - if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int( - mac_ctx, - WNI_CFG_BEACON_INTERVAL, - &bi))) - /* U8 is not enough for BI */ - ibss_log->beaconInterval = (uint8_t) bi; - WLAN_HOST_DIAG_LOG_REPORT(ibss_log); - } -#endif - /* - * 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(profile->negotiatedUCEncryptionType) - && session->pCurRoamProfile - && !CSR_IS_INFRA_AP(session->pCurRoamProfile)) { + WLAN_HOST_DIAG_LOG_ALLOC(ibss_log, + host_log_ibss_pkt_type, LOG_WLAN_IBSS_C); + if (ibss_log) { + if (CSR_INVALID_SCANRESULT_HANDLE == + cmd->u.roamCmd.hBSSList) { /* - * 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. + * We start the IBSS (didn't find any + * matched IBSS out there) */ - if (!CSR_IS_IBSS(session->pCurRoamProfile)) { - /* NO keys. these key parameters don't matter */ - csr_roam_issue_set_context_req(mac_ctx, - session_id, - profile->negotiatedMCEncryptionType, - bss_desc, &bcast_mac, false, - false, eSIR_TX_RX, 0, 0, NULL, 0); - } - + ibss_log->eventId = + WLAN_IBSS_EVENT_START_IBSS_RSP; + } else { + ibss_log->eventId = + WLAN_IBSS_EVENT_JOIN_IBSS_RSP; } - } else { + if (bss_desc) { + cdf_mem_copy(ibss_log->bssid, + bss_desc->bssId, 6); + ibss_log->operatingChannel = + bss_desc->channelId; + } + if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int( + mac_ctx, + WNI_CFG_BEACON_INTERVAL, + &bi))) + /* U8 is not enough for BI */ + ibss_log->beaconInterval = (uint8_t) bi; + WLAN_HOST_DIAG_LOG_REPORT(ibss_log); + } +#endif + /* + * 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(profile->negotiatedUCEncryptionType) + && session->pCurRoamProfile + && !CSR_IS_INFRA_AP(session->pCurRoamProfile)) { /* - * Keep the state to eCSR_ROAMING_STATE_JOINING. - * Need to send join_req. + * 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 (cmd->u.roamCmd.pRoamBssEntry) { - scan_res = GET_BASE_ADDR(cmd->u.roamCmd. - pRoamBssEntry, tCsrScanResult, Link); - if (scan_res) { - bss_desc = &scan_res->Result.BssDescriptor; - ies_ptr = (tDot11fBeaconIEs *) - (scan_res->Result.pvIes); - /* Set the roaming substate to join attempt */ - csr_roam_substate_change(mac_ctx, - eCSR_ROAM_SUBSTATE_JOIN_REQ, - session_id); - status = csr_send_join_req_msg(mac_ctx, - session_id, bss_desc, - profile, ies_ptr, - eWNI_SME_JOIN_REQ); - } - } else { - sms_log(mac_ctx, LOGE, - "StartBSS for WDS station with no BssDesc"); - CDF_ASSERT(0); + if (!CSR_IS_IBSS(session->pCurRoamProfile)) { + /* NO keys. these key parameters don't matter */ + csr_roam_issue_set_context_req(mac_ctx, + session_id, + profile->negotiatedMCEncryptionType, + bss_desc, &bcast_mac, false, + false, eSIR_TX_RX, 0, 0, NULL, 0); } } /* @@ -6061,10 +6014,6 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, if (!CSR_IS_JOIN_TO_IBSS(profile)) { roam_status = eCSR_ROAM_IBSS_IND; roam_result = eCSR_ROAM_RESULT_IBSS_STARTED; - if (CSR_IS_WDS(profile)) { - roam_status = eCSR_ROAM_WDS_IND; - roam_result = eCSR_ROAM_RESULT_WDS_STARTED; - } if (CSR_IS_INFRA_AP(profile)) { roam_status = eCSR_ROAM_INFRA_IND; roam_result = eCSR_ROAM_RESULT_INFRA_STARTED; @@ -6099,16 +6048,6 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, roam_status, roam_result); } - - if (CSR_IS_WDS_STA(profile)) { - /* need to send stop BSS because we fail to send join_req */ - csr_roam_issue_disassociate_cmd(mac_ctx, session_id, - eCSR_DISCONNECT_REASON_UNSPECIFIED); - csr_roam_call_callback(mac_ctx, session_id, &roam_info, - cmd->u.roamCmd.roamId, - eCSR_ROAM_WDS_IND, - eCSR_ROAM_RESULT_WDS_STOPPED); - } } /** @@ -6595,10 +6534,6 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, #endif roam_status = eCSR_ROAM_IBSS_IND; roam_result = eCSR_ROAM_RESULT_IBSS_STARTED; - if (CSR_IS_WDS(profile)) { - roam_status = eCSR_ROAM_WDS_IND; - roam_result = eCSR_ROAM_RESULT_WDS_STARTED; - } if (CSR_IS_INFRA_AP(profile)) { roam_status = eCSR_ROAM_INFRA_IND; roam_result = eCSR_ROAM_RESULT_INFRA_START_FAILED; @@ -6681,24 +6616,14 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, eCSR_ROAM_RESULT_ASSOCIATED, true); break; case eCsrReassocFailure: + /* + * Currently Reassoc failure is handled through eCsrJoinFailure + * Need to revisit for eCsrReassocFailure handling + */ #ifndef WLAN_MDM_CODE_REDUCTION_OPT sme_qos_csr_event_ind(mac_ctx, (uint8_t) session_id, SME_QOS_CSR_REASSOC_FAILURE, NULL); #endif - case eCsrJoinWdsFailure: - sms_log(mac_ctx, LOGW, FL("failed to join WDS")); - csr_free_connect_bss_desc(mac_ctx, session_id); - csr_roam_free_connect_profile(mac_ctx, - &session->connectedProfile); - csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); - cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); - roam_info.pBssDesc = cmd->u.roamCmd.pLastRoamBss; - roam_info.statusCode = session->joinFailStatusCode.statusCode; - roam_info.reasonCode = session->joinFailStatusCode.reasonCode; - csr_roam_call_callback(mac_ctx, session_id, &roam_info, - cmd->u.roamCmd.roamId, eCSR_ROAM_WDS_IND, - eCSR_ROAM_RESULT_WDS_NOT_ASSOCIATED); - /* Need to issue stop_bss */ break; case eCsrJoinFailure: case eCsrNothingToJoin: @@ -7269,8 +7194,7 @@ CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, pScanFilter->bWPSAssociation = 0; pScanFilter->bOSENAssociation = 0; } - if ((pProfile && CSR_IS_WDS_AP(pProfile)) || (pProfile - && CSR_IS_INFRA_AP(pProfile))) { + if (pProfile && CSR_IS_INFRA_AP(pProfile)) { /* This can be started right away */ status = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL, eCsrHddIssued, roamId, false, false); @@ -7605,26 +7529,6 @@ CDF_STATUS csr_roam_process_disassoc_deauth(tpAniSirGlobal pMac, tSmeCmd *pComma eCSR_ROAM_SUBSTATE_DEAUTH_REQ); } fComplete = (!CDF_IS_STATUS_SUCCESS(status)); - } else if (csr_is_conn_state_wds(pMac, sessionId)) { - if (CSR_IS_WDS_AP - (&pMac->roam.roamSession[sessionId].connectedProfile)) { - status = - csr_roam_issue_stop_bss(pMac, sessionId, - eCSR_ROAM_SUBSTATE_STOP_BSS_REQ); - fComplete = (!CDF_IS_STATUS_SUCCESS(status)); - } - /* This has to be WDS station */ - else if (csr_is_conn_state_connected_wds(pMac, sessionId)) { - /* This has to be WDS station */ - pCommand->u.roamCmd.fStopWds = true; - if (fDisassoc) { - status = - csr_roam_issue_disassociate(pMac, sessionId, - eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, - fMICFailure); - fComplete = (!CDF_IS_STATUS_SUCCESS(status)); - } - } } else { /* we got a dis-assoc request while not connected to any peer */ /* just complete the command */ @@ -7791,7 +7695,6 @@ CDF_STATUS csr_roam_disconnect_internal(tpAniSirGlobal pMac, uint32_t sessionId, /* Only issue disconnect when necessary */ if (csr_is_conn_state_connected(pMac, sessionId) || csr_is_bss_type_ibss(pSession->connectedProfile.BSSType) - || csr_is_bss_type_wds(pSession->connectedProfile.BSSType) || csr_is_roam_command_waiting_for_session(pMac, sessionId)) { sms_log(pMac, LOG2, FL("called")); status = csr_roam_issue_disassociate_cmd(pMac, sessionId, @@ -8074,17 +7977,7 @@ static void csr_roam_join_rsp_processor(tpAniSirGlobal pMac, is_dis_pending = is_disconnect_pending(pMac, session_ptr->sessionId); if (pCommand && (session_ptr->join_bssid_count < CSR_MAX_BSSID_COUNT) && !is_dis_pending) { - if (CSR_IS_WDS_STA(&pCommand->u.roamCmd.roamProfile)) { - pCommand->u.roamCmd.fStopWds = true; - session_ptr->connectedProfile.BSSType = - eCSR_BSS_TYPE_WDS_STA; - csr_roam_reissue_roam_command(pMac); - } else if (CSR_IS_WDS(&pCommand->u.roamCmd.roamProfile)) { - session_ptr->join_bssid_count = 0; - csr_roam_complete(pMac, eCsrNothingToJoin, NULL); - } else { - csr_roam(pMac, pCommand); - } + csr_roam(pMac, pCommand); } else { /* **************************************************** * When the upper layers issue a connect command, there @@ -8199,20 +8092,11 @@ void csr_roam_reissue_roam_command(tpAniSirGlobal pMac) 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; - csr_roam_call_callback(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; - csr_roam_call_callback(pMac, sessionId, &roamInfo, - pCommand->u.roamCmd.roamId, - eCSR_ROAM_INFRA_IND, - eCSR_ROAM_RESULT_INFRA_DISASSOCIATED); - } + pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED; + csr_roam_call_callback(pMac, sessionId, &roamInfo, + pCommand->u.roamCmd.roamId, + eCSR_ROAM_INFRA_IND, + eCSR_ROAM_RESULT_INFRA_DISASSOCIATED); if (!CDF_IS_STATUS_SUCCESS(csr_roam_issue_stop_bss(pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ))) { @@ -8467,7 +8351,6 @@ csr_roaming_state_config_cnf_processor(tpAniSirGlobal mac_ctx, bss_desc = &scan_result->Result.BssDescriptor; } if (csr_is_bss_type_ibss(cmd->u.roamCmd.roamProfile.BSSType) - || CSR_IS_WDS(&cmd->u.roamCmd.roamProfile) || CSR_IS_INFRA_AP(&cmd->u.roamCmd.roamProfile)) { if (!CDF_IS_STATUS_SUCCESS(csr_roam_issue_start_bss(mac_ctx, session_id, &session->bssParams, @@ -9223,12 +9106,6 @@ void csr_roam_joined_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf) eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); } - if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) { - cdf_sleep(100); - pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; /* Sta */ - status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); /* Sta */ - } - } break; default: @@ -9669,15 +9546,7 @@ csr_roam_prepare_filter_from_profile(tpAniSirGlobal mac_ctx, } if (profile->SSIDs.numOfSSIDs) { - if (!CSR_IS_WDS_STA(profile)) { - scan_fltr->SSIDs.numOfSSIDs = profile->SSIDs.numOfSSIDs; - } else { - /* - * For WDS station we always use idx 1 for self SSID. - * Index 0 for peer's SSID that we want to join - */ - scan_fltr->SSIDs.numOfSSIDs = 1; - } + scan_fltr->SSIDs.numOfSSIDs = profile->SSIDs.numOfSSIDs; CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, FL("No of Allowed List:%d"), roam_params->num_ssid_allowed_list); @@ -10083,10 +9952,6 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) cdf_mem_copy(&roam_info_ptr->chan_info, &pAssocInd->chan_info, sizeof(tSirSmeChanInfo)); - if (CSR_IS_WDS_AP(roam_info_ptr->u.pConnectedProfile)) - status = csr_roam_call_callback(mac_ctx, sessionId, - roam_info_ptr, 0, eCSR_ROAM_WDS_IND, - eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile)) { if (session->pCurRoamProfile && CSR_IS_ENC_TYPE_STATIC( @@ -10115,10 +9980,7 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) * send a message to CSR itself just to avoid the EAPOL frames going * OTA before association response */ - if (CSR_IS_WDS_AP(roam_info_ptr->u.pConnectedProfile)) { - status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac_ctx, - pAssocInd, status, sessionId); - } else if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile) + if (CSR_IS_INFRA_AP(roam_info_ptr->u.pConnectedProfile) && (roam_info_ptr->statusCode != eSIR_SME_ASSOC_REFUSED)) { roam_info_ptr->fReassocReq = pAssocInd->reassocReq; status = csr_send_assoc_ind_to_upper_layer_cnf_msg(mac_ctx, @@ -11668,15 +11530,6 @@ void csr_roam_process_wm_status_change_command(tpAniSirGlobal pMac, 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 (!CDF_IS_STATUS_SUCCESS - (csr_roam_issue_stop_bss_cmd(pMac, pCommand->sessionId, true))) { - /* This is not good */ - sms_log(pMac, LOGE, - FL(" failed to issue stopBSS command")); - } - } /* Lost Link just triggers a roaming sequence. We can complte the Lost Link */ /* command here since there is nothing else to do. */ csr_roam_wm_status_change_complete(pMac); @@ -11854,7 +11707,7 @@ csr_roam_get_phy_mode_band_for_bss(tpAniSirGlobal mac_ctx, * If the global setting for dot11Mode is set to auto/abg, we overwrite * the setting in the profile. */ - if (((!CSR_IS_INFRA_AP(profile) && !CSR_IS_WDS(profile)) + if ((!CSR_IS_INFRA_AP(profile) && ((eCSR_CFG_DOT11_MODE_AUTO == curr_mode) || (eCSR_CFG_DOT11_MODE_ABG == curr_mode))) || (eCSR_CFG_DOT11_MODE_AUTO == cfg_dot11_mode) @@ -12741,37 +12594,21 @@ static void csr_roam_prepare_bss_params(tpAniSirGlobal pMac, uint32_t sessionId, if (pBssDesc) { csr_roam_get_bss_start_parms_from_bss_desc(pMac, pBssDesc, pIes, &pSession->bssParams); - /* Since csr_roam_get_bss_start_parms_from_bss_desc 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)) { - cdf_mem_copy(&pSession->bssParams.bssid, - &pSession->selfMacAddr, - sizeof(struct cdf_mac_addr)); - } } else { csr_roam_get_bss_start_parms(pMac, pProfile, &pSession->bssParams); /* Use the first SSID */ - if (pProfile->SSIDs.numOfSSIDs) { + if (pProfile->SSIDs.numOfSSIDs) cdf_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)) { - cdf_mem_copy(&pSession->bssParams.bssid, - &pSession->selfMacAddr, - sizeof(struct cdf_mac_addr)); - } - /* Use the first BSSID */ - else if (pProfile->BSSIDs.numOfBSSIDs) { + if (pProfile->BSSIDs.numOfBSSIDs) + /* Use the first BSSID */ cdf_mem_copy(&pSession->bssParams.bssid, pProfile->BSSIDs.bssid, sizeof(struct cdf_mac_addr)); - } else { + else cdf_mem_set(&pSession->bssParams.bssid, sizeof(struct cdf_mac_addr), 0); - } } Channel = pSession->bssParams.operationChn; /* Set operating channel in pProfile which will be used */ @@ -14165,8 +14002,7 @@ CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, pMsg->sessionId = sessionId; pMsg->transactionId = 0; if ((pSession->pCurRoamProfile != NULL) - && ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) - || (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))) { + && (CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) { cdf_mem_copy(&pMsg->bssId, &pSession->selfMacAddr, sizeof(tSirMacAddr)); @@ -14372,8 +14208,7 @@ CDF_STATUS csr_send_mb_deauth_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, pMsg->transactionId = 0; if ((pSession->pCurRoamProfile != NULL) - && ((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) - || (CSR_IS_WDS_AP(pSession->pCurRoamProfile)))) { + && (CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) { cdf_mem_copy(&pMsg->bssId, &pSession->selfMacAddr, sizeof(tSirMacAddr)); @@ -14792,18 +14627,9 @@ CDF_STATUS csr_send_mb_stop_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId) pMsg->length = sizeof(tSirSmeStopBssReq); pMsg->transactionId = 0; pMsg->reasonCode = 0; - /* - * if BSSType is WDS sta, use selfmacAddr as bssid, - * else use bssid in connectedProfile - */ - if (CSR_IS_CONN_WDS_STA(&pSession->connectedProfile)) - cdf_mem_copy(&pMsg->bssId, - &pSession->selfMacAddr.bytes, - sizeof(tSirMacAddr)); - else - cdf_mem_copy(&pMsg->bssId, - &pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->bssId, + &pSession->connectedProfile.bssid.bytes, + sizeof(tSirMacAddr)); return cds_send_mb_message_to_mac(pMsg); } diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 1c3669341d2e..2ca632d2da50 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2466,14 +2466,6 @@ CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF); } - if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) { - cdf_sleep(100); - pMac->roam.roamSession[sessionId].connectState = - eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED; - status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0, - eCSR_ROAM_WDS_IND, - eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND); - } return status; } @@ -4945,9 +4937,7 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, * 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) + && (eCSR_SCAN_P2P_DISCOVERY != pScanReq->requestType) && (false == pMac->scan.fEnableBypass11d)) { scanType = pMac->scan.curScanType; if (eSIR_PASSIVE_SCAN == pMac->scan.curScanType) { @@ -6004,10 +5994,6 @@ CDF_STATUS csr_scan_for_ssid(tpAniSirGlobal mac_ctx, uint32_t session_id, sms_log(mac_ctx, LOG2, FL("called")); - /* For WDS, we use the index 0. There must be at least one in there */ - if (CSR_IS_WDS_STA(profile) && num_ssid) - num_ssid = 1; - if (!(mac_ctx->scan.fScanEnable) && (num_ssid != 1)) { sms_log(mac_ctx, LOGE, FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"), diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 3896db080f46..3b97ebd26de3 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -137,7 +137,6 @@ typedef enum { eCsrStartBssFailure, eCsrSilentlyStopRoaming, eCsrSilentlyStopRoamingSaveState, - eCsrJoinWdsFailure, eCsrJoinFailureDueToConcurrency, } eCsrRoamCompleteResult; diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index a6796d9adc92..d45482d357be 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -4371,12 +4371,6 @@ bool csr_is_bss_type_ibss(eCsrRoamBssType bssType) || eCSR_BSS_TYPE_IBSS == bssType); } -bool csr_is_bss_type_wds(eCsrRoamBssType bssType) -{ - return (bool) - (eCSR_BSS_TYPE_WDS_STA == bssType - || eCSR_BSS_TYPE_WDS_AP == bssType); -} bool csr_is_bss_type_caps_match(eCsrRoamBssType bssType, tSirBssDescription *pSirBssDesc) @@ -4389,10 +4383,8 @@ bool csr_is_bss_type_caps_match(eCsrRoamBssType bssType, break; case eCSR_BSS_TYPE_INFRASTRUCTURE: - case eCSR_BSS_TYPE_WDS_STA: if (!csr_is_infra_bss_desc(pSirBssDesc)) fMatch = false; - break; case eCSR_BSS_TYPE_IBSS: @@ -4401,8 +4393,6 @@ bool csr_is_bss_type_caps_match(eCsrRoamBssType bssType, fMatch = false; break; - - case eCSR_BSS_TYPE_WDS_AP: /* For WDS AP, no need to match anything */ default: fMatch = false; break; @@ -5317,12 +5307,6 @@ tSirBssType csr_translate_bsstype_to_mac_type(eCsrRoamBssType csrtype) 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; -- cgit v1.2.3 From 914142d054005ad7fed22ceb0540f59aabca2069 Mon Sep 17 00:00:00 2001 From: "Masti, Narayanraddi" Date: Mon, 2 Nov 2015 11:42:28 +0530 Subject: qcacld-3.0: Fix SAP to not send Assoc Rsp for duplicate Assoc Req qcacld-2.0 to qcacld-3.0 propagation Fix soft AP to not send Assoc response for Assoc req which is unprotected and initiated by an injector rather than a testbed station. If STAUT sends duplicate Assoc request, Assoc response should be sent only in case of non-PMF connection. Change-Id: I6fb4c139af333c937e767cb111df4d1d69bddbd9 CRs-Fixed: 902969 --- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 8e23a4e9d21f..cda12aa0ff11 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -288,8 +288,9 @@ lim_process_assoc_req_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, MAC_ADDRESS_STR), psessionEntry->peSessionId, subType, GET_LIM_SYSTEM_ROLE(psessionEntry), MAC_ADDR_ARRAY(pHdr->sa)); - } else { - /* + } 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. */ -- cgit v1.2.3 From 5dd1a97b8147fe3b72d4efafc8b3f9c3f316c6e5 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Mon, 2 Nov 2015 17:01:51 -0800 Subject: qcacld-3.0: Clear txSTBC capab if number of tx streams is less than 2 Currently tx STBC param sent to FW is taken from peer's response frame, which is wrong if current hardware does not support 2x2 for given channel width. Update the driver to check number of tx stream for current vdev and clear txSTBC if needed. Change-Id: If05e5de72ba5af95b343817d811db0f413493ee1 CRs-Fixed: 941217 --- core/wma/src/wma_mgmt.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 89a9e728cb55..2287edb20722 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1110,7 +1110,18 @@ int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, WMITLV_GET_STRUCT_TLVLEN(wmi_vht_rate_set)); cmd->peer_nss = peer_nss; - + /* + * Because of DBS a vdev may come up in any of the two MACs with + * different capabilities. STBC capab should be fetched for given + * hard_mode->MAC_id combo. It is planned that firmware should provide + * these dev capabilities. But for now number of tx streams can be used + * to identify if Tx STBC needs to be disabled. + */ + if (intr->tx_streams < 2) { + cmd->peer_vht_caps &= ~(1 << SIR_MAC_VHT_CAP_TXSTBC); + WMA_LOGD("Num tx_streams: %d, Disabled txSTBC", + intr->tx_streams); + } WMA_LOGD("peer_nss %d peer_ht_rates.num_rates %d ", cmd->peer_nss, peer_ht_rates.num_rates); -- cgit v1.2.3 From 671895081f26d98cacd0346be76f974a64654e34 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 7 Dec 2015 13:48:50 -0800 Subject: qcacld-3.0: Remove obsolete lim_cleanup_lmm() Remove obsolete lim_cleanup_lmm(). Change-Id: I981c80bcd2f8b2a6755977423df80660036e9bb8 CRs-Fixed: 898864 --- core/mac/src/pe/lim/lim_api.c | 1 - core/mac/src/pe/lim/lim_types.h | 3 --- core/mac/src/pe/lim/lim_utils.c | 25 ------------------------- 3 files changed, 29 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index bb825e71cc70..130d3f648737 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -670,7 +670,6 @@ void lim_cleanup(tpAniSirGlobal pMac) } lim_cleanup_mlm(pMac); - lim_cleanup_lmm(pMac); /* free up preAuth table */ if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL) { diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index e03973065135..fab829f3f43b 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -423,9 +423,6 @@ void lim_init_mlm(tpAniSirGlobal); /* Function to cleanup MLM state machine */ void lim_cleanup_mlm(tpAniSirGlobal); -/* Function to cleanup LMM state machine */ -void lim_cleanup_lmm(tpAniSirGlobal); - /* Management frame handling functions */ void lim_process_beacon_frame(tpAniSirGlobal, uint8_t *, tpPESession); void lim_process_beacon_frame_no_session(tpAniSirGlobal, uint8_t *); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 28f4a84b0e55..6b6b95c14d91 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -753,31 +753,6 @@ void lim_cleanup_mlm(tpAniSirGlobal mac_ctx) } /*** end lim_cleanup_mlm() ***/ -/** - * lim_cleanup_lmm() - * - ***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 lim_cleanup_lmm(tpAniSirGlobal pMac) -{ -} /*** end lim_cleanup_lmm() ***/ - /** * lim_is_addr_bc() * -- cgit v1.2.3 From a248d0d7a26191229ed5158f4e29cbc09563d68a Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 8 Dec 2015 15:18:26 -0800 Subject: qcacld-3.0: Remove obsolete macros and functions Remove obsolete macros and functions. Change-Id: I18e3ba1ec3a38a0f1dfa2de70955f0af02bef37f CRs-Fixed: 898864 --- core/hdd/inc/wlan_hdd_host_offload.h | 6 +++--- core/hdd/inc/wlan_hdd_p2p.h | 11 ----------- core/hdd/inc/wlan_hdd_power.h | 12 ------------ core/hdd/inc/wlan_hdd_tdls.h | 14 -------------- core/hdd/inc/wlan_hdd_tx_rx.h | 17 ----------------- core/hdd/src/wlan_hdd_cfg80211.c | 2 -- core/hdd/src/wlan_hdd_power.c | 3 ++- core/hdd/src/wlan_hdd_wmm.c | 4 ---- core/mac/inc/sir_api.h | 9 +++------ core/mac/src/pe/lim/lim_utils.c | 4 ---- core/sme/inc/csr_internal.h | 7 ------- core/sme/inc/csr_support.h | 4 ---- core/sme/inc/sme_api.h | 2 -- core/sme/src/common/sme_api.c | 2 -- core/sme/src/csr/csr_util.c | 21 --------------------- core/sme/src/oem_data/oem_data_api.c | 8 +++----- 16 files changed, 11 insertions(+), 115 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_host_offload.h b/core/hdd/inc/wlan_hdd_host_offload.h index 515a8285510a..e0b4b4e99cb3 100644 --- a/core/hdd/inc/wlan_hdd_host_offload.h +++ b/core/hdd/inc/wlan_hdd_host_offload.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -51,8 +51,8 @@ typedef struct { uint8_t offloadType; uint8_t enableOrDisable; union { - uint8_t hostIpv4Addr[4]; - uint8_t hostIpv6Addr[16]; + uint8_t hostIpv4Addr[SIR_IPV4_ADDR_LEN]; + uint8_t hostIpv6Addr[SIR_MAC_IPV6_ADDR_LEN]; } params; struct cdf_mac_addr bssId; } tHostOffloadRequest, *tpHostOffloadRequest; diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index b9ef3445f627..baf2e4bcbbfb 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -38,7 +38,6 @@ #define WAIT_CANCEL_REM_CHAN 1000 #define WAIT_REM_CHAN_READY 1000 #define WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX 3000 -#define ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX 20 #define COMPLETE_EVENT_PROPOGATE_TIME 10 #ifdef QCA_WIFI_3_0_EMU @@ -61,19 +60,9 @@ #define P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT 5 #endif -#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 #define MAX_ROC_REQ_QUEUE_ENTRY 10 -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) diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index c6157f037516..d32a2345f37c 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -39,18 +39,6 @@ #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 /** * enum pkt_filter_protocol_layer - packet filter protocol layer diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 801857c32176..6c0e41d09272 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -34,20 +34,6 @@ #ifdef FEATURE_WLAN_TDLS -#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. diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index b4b29cca5adf..fc80851a1430 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -42,25 +42,10 @@ #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 @@ -68,8 +53,6 @@ #define SME_QOS_UAPSD_CFG_VI_CHANGED_MASK 0xF4 #define SME_QOS_UAPSD_CFG_VO_CHANGED_MASK 0xF8 -#define HDD_ETH_HEADER_LEN 14 - int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); void hdd_tx_timeout(struct net_device *dev); CDF_STATUS hdd_init_tx_rx(hdd_adapter_t *pAdapter); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 75944d45d1b7..5c3b659ab8a9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -89,8 +89,6 @@ #define g_mode_rates_size (12) #define a_mode_rates_size (8) -#define FREQ_BASE_80211G (2407) -#define FREQ_BAND_DIFF_80211G (5) #define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \ ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields))) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index df5620b51252..74ab785c50f9 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -388,7 +388,8 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable) offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; cdf_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr, - &pAdapter->macAddressCurrent.bytes, SIR_MAC_ADDR_LEN); + &pAdapter->macAddressCurrent.bytes, + CDF_MAC_ADDR_SIZE); /* set number of ns offload address count */ offLoadRequest.num_ns_offload_count = count; /* Configure the Firmware with this */ diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index 9b93e2711fa1..582b2dfd5713 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -81,10 +81,6 @@ #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 uint8_t hdd_wmm_up_to_ac_map[] = { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 6753bf860b9e..e075068b0864 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -71,7 +71,6 @@ #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 uint8_t tSirIpv4Addr[SIR_IPV4_ADDR_LEN]; @@ -2549,7 +2548,7 @@ typedef struct sSirUpdateAPWPARSNIEsReq { #ifdef WLAN_NS_OFFLOAD typedef struct sSirNsOffloadReq { - uint8_t srcIPv6Addr[16]; + uint8_t srcIPv6Addr[SIR_MAC_IPV6_ADDR_LEN]; uint8_t selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; uint8_t targetIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; tSirMacAddr selfMacAddr; @@ -2564,8 +2563,8 @@ typedef struct sSirHostOffloadReq { uint8_t enableOrDisable; uint32_t num_ns_offload_count; union { - uint8_t hostIpv4Addr[4]; - uint8_t hostIpv6Addr[16]; + uint8_t hostIpv4Addr[SIR_IPV4_ADDR_LEN]; + uint8_t hostIpv6Addr[SIR_MAC_IPV6_ADDR_LEN]; } params; #ifdef WLAN_NS_OFFLOAD tSirNsOffloadReq nsOffloadInfo; @@ -2976,8 +2975,6 @@ typedef struct sSirRoamOffloadScanRsp { /*--------------------------------------------------------------------------- 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 diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 6b6b95c14d91..4952804d9d2a 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -64,10 +64,6 @@ #endif #define ASCII_SPACE_CHARACTER 0x20 -#define SUCCESS 1 - -#define MAX_BA_WINDOW_SIZE_FOR_CISCO 25 - /** ------------------------------------------------------------- \fn lim_delete_dialogue_token_list \brief deletes the complete lim dialogue token linked list. diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index aa8eba8c7185..55408dfa445f 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -51,11 +51,6 @@ /* 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 @@ -1243,8 +1238,6 @@ bool csr_is_concurrent_infra_connected(tpAniSirGlobal pMac); bool csr_is_concurrent_session_running(tpAniSirGlobal pMac); bool csr_is_infra_ap_started(tpAniSirGlobal pMac); bool csr_is_ibss_started(tpAniSirGlobal pMac); -bool csr_is_btamp_started(tpAniSirGlobal pMac); -bool csr_is_btamp(tpAniSirGlobal pMac, uint32_t sessionId); bool csr_is_valid_mc_concurrent_session(tpAniSirGlobal pMac, uint32_t sessionId, tSirBssDescription *pBssDesc); bool csr_is_conn_state_connected_infra_ap(tpAniSirGlobal pMac, diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h index 7614b1eae1b8..f62c5a2a85fc 100644 --- a/core/sme/inc/csr_support.h +++ b/core/sme/inc/csr_support.h @@ -224,10 +224,6 @@ typedef struct tagRoamingTimerInfo { ((pIes)->WMMParams.qosInfo & SME_QOS_AP_SUPPORTS_APSD)) || \ ((pIes)->WMMInfoAp.present && (pIes)->WMMInfoAp.uapsd)) -/* This macro returns the total len needed of Tlv with with len bytes of data */ -#define GET_TLV_MSG_LEN(len) \ - GET_ROUND_UP((sizeof(tCsrCfgMsgTlvHdr) + (len)), sizeof(uint32_t)) - bool csr_get_bss_id_bss_desc(tHalHandle hHal, tSirBssDescription *pSirBssDesc, struct cdf_mac_addr *pBssId); bool csr_is_bss_id_equal(tHalHandle hHal, tSirBssDescription *pSirBssDesc1, diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index e82c1515cec8..91f6526aedf0 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -71,8 +71,6 @@ #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); \ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 1f511656b5cb..d53f36ab5a4f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -63,8 +63,6 @@ extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb); #define LOG_SIZE 256 -#define READ_MEMORY_DUMP_CMD 9 -#define TL_INIT_STATE 0 static tSelfRecoveryStats g_self_recovery_stats; /* TxMB Functions */ diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index d45482d357be..a116307655d0 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -893,22 +893,6 @@ bool csr_is_ibss_started(tpAniSirGlobal pMac) return fRc; } -bool csr_is_btamp_started(tpAniSirGlobal pMac) -{ - uint32_t i; - bool fRc = false; - - for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { - if (CSR_IS_SESSION_VALID(pMac, i) - && csr_is_conn_state_connected_wds(pMac, i)) { - fRc = true; - break; - } - } - - return fRc; -} - bool csr_is_concurrent_session_running(tpAniSirGlobal pMac) { uint32_t sessionId, noOfCocurrentSession = 0; @@ -954,11 +938,6 @@ bool csr_is_infra_ap_started(tpAniSirGlobal pMac) } -bool csr_is_btamp(tpAniSirGlobal pMac, uint32_t sessionId) -{ - return csr_is_conn_state_connected_wds(pMac, sessionId); -} - bool csr_is_conn_state_disconnected(tpAniSirGlobal pMac, uint32_t sessionId) { return eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED == diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c index 385b77d4bc32..8fa6b8999aa7 100644 --- a/core/sme/src/oem_data/oem_data_api.c +++ b/core/sme/src/oem_data/oem_data_api.c @@ -369,12 +369,10 @@ CDF_STATUS oem_data_is_oem_data_req_allowed(tHalHandle 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 (csr_is_conn_state_ibss(pMac, sessionId) - || csr_is_btamp(pMac, sessionId)) { - /* co-exist with IBSS or BT-AMP mode is not supported */ + /* co-exist with IBSS mode is not supported */ + if (csr_is_conn_state_ibss(pMac, sessionId)) { sms_log(pMac, LOGW, - "OEM DATA REQ is not allowed due to IBSS|BTAMP exist in session %d", + "OEM DATA REQ is not allowed due to IBSS exist in session %d", sessionId); status = CDF_STATUS_CSR_WRONG_STATE; break; -- cgit v1.2.3 From b2ba7eb31aee8de882daccd36ffc45a95ef3952b Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 9 Dec 2015 15:58:16 -0800 Subject: qcacld-3.0: Remove #ifndef block of FEATURE_WLAN_ESE_UPLOAD At present and going forward ESE and ESE_UPLOAD will be the de-facto approach of supporting ESE. There is no support for #ifndef FEATURE_WLAN_ESE_UPLOAD block of code. Hence clean up this code. Change-Id: I1e1307ec3430353496b1cf7aaa2eb5291ca1d5b2 CRs-Fixed: 949634 --- core/mac/src/include/sir_params.h | 5 ++--- core/mac/src/pe/lim/lim_assoc_utils.c | 2 -- core/mac/src/pe/lim/lim_process_action_frame.c | 4 ---- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 2 -- core/mac/src/pe/lim/lim_process_message_queue.c | 7 ------- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 -- core/mac/src/pe/lim/lim_timer_utils.h | 3 --- core/mac/src/pe/lim/lim_trace.c | 3 --- core/mac/src/sys/legacy/src/utils/src/mac_trace.c | 3 --- core/sme/src/csr/csr_api_roam.c | 12 ------------ core/wma/src/wma_features.c | 6 ------ 11 files changed, 2 insertions(+), 47 deletions(-) diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 78513a3ac805..c5b6d7c56ed7 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -680,9 +680,8 @@ typedef struct sSirMbMsgP2p { #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 + +/* currently unused (SIR_LIM_TIMEOUT_MSG_START + 0x25) */ #define SIR_LIM_DISASSOC_ACK_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x26) #define SIR_LIM_DEAUTH_ACK_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x27) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index acb078cd5de0..79f8a1f489a1 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -663,8 +663,6 @@ lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, #ifdef FEATURE_WLAN_ESE #ifdef FEATURE_WLAN_ESE_UPLOAD lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); -#else - lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER); #endif /* FEATURE_WLAN_ESE_UPLOAD */ #endif diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index dd041c448135..2ef83fd10038 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -822,8 +822,6 @@ static void __lim_process_add_ts_rsp(tpAniSirGlobal mac_ctx, lim_send_sme_tsm_ie_ind(mac_ctx, session, addts.tsmIE.tsid, addts.tsmIE.state, addts.tsmIE.msmt_interval); -#else - limActivateTSMStatsTimer(mac_ctx, session); #endif /* FEATURE_WLAN_ESE_UPLOAD */ } #endif @@ -1099,8 +1097,6 @@ static void __lim_process_del_ts_req(tpAniSirGlobal mac_ctx, #ifdef FEATURE_WLAN_ESE #ifdef FEATURE_WLAN_ESE_UPLOAD lim_send_sme_tsm_ie_ind(mac_ctx, session, 0, 0, 0); -#else - lim_deactivate_and_change_timer(mac_ctx, eLIM_TSM_TIMER); #endif /* FEATURE_WLAN_ESE_UPLOAD */ #endif } diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index c11cecc56d39..a73fa87a22fd 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -501,8 +501,6 @@ static void lim_update_ese_tsm(tpAniSirGlobal mac_ctx, session_entry, assoc_rsp->tsmIE.tsid, assoc_rsp->tsmIE.state, assoc_rsp->tsmIE.msmt_interval); -#else - limActivateTSMStatsTimer(mac_ctx, session_entry); #endif if (tsm_ctx->tsmInfo.state) tsm_ctx->tsmMetrics.RoamingCount++; diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index bacb031ed16c..ac63aee78c87 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1506,17 +1506,10 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) lim_process_sme_req_messages(mac_ctx, msg); break; #ifdef FEATURE_WLAN_ESE - case SIR_LIM_ESE_TSM_TIMEOUT: -#ifndef FEATURE_WLAN_ESE_UPLOAD - limProcessTsmTimeoutHandler(mac_ctx, msg); -#endif /* FEATURE_WLAN_ESE_UPLOAD */ - break; case WMA_TSM_STATS_RSP: #ifdef FEATURE_WLAN_ESE_UPLOAD lim_send_sme_pe_ese_tsm_rsp(mac_ctx, (tAniGetTsmStatsRsp *) msg->bodyptr); -#else - limProcessHalEseTsmRsp(mac_ctx, msg); #endif /* FEATURE_WLAN_ESE_UPLOAD */ break; #endif diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 3846b8bba891..81939b572ccb 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3981,8 +3981,6 @@ static void __lim_process_sme_delts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) #ifdef FEATURE_WLAN_ESE #ifdef FEATURE_WLAN_ESE_UPLOAD lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); -#else - lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER); #endif /* FEATURE_WLAN_ESE_UPLOAD */ #endif diff --git a/core/mac/src/pe/lim/lim_timer_utils.h b/core/mac/src/pe/lim/lim_timer_utils.h index b133d712f9e0..33b94d5505ee 100644 --- a/core/mac/src/pe/lim/lim_timer_utils.h +++ b/core/mac/src/pe/lim/lim_timer_utils.h @@ -65,9 +65,6 @@ enum { #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, diff --git a/core/mac/src/pe/lim/lim_trace.c b/core/mac/src/pe/lim/lim_trace.c index d82e022021c2..35f23a80ae1a 100644 --- a/core/mac/src/pe/lim/lim_trace.c +++ b/core/mac/src/pe/lim/lim_trace.c @@ -76,9 +76,6 @@ static uint8_t *__lim_trace_get_timer_string(uint16_t timerId) #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); diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 7d0d9ac102f3..63f13c8fe787 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -663,9 +663,6 @@ uint8_t *mac_trace_get_lim_msg_string(uint16_t lim_msg) 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); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f22b16d51cfe..fbfa066e3e5b 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10801,8 +10801,6 @@ csr_roam_chk_lnk_set_ctx_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) && session->connectedProfile.isESEAssoc) { #ifdef FEATURE_WLAN_ESE_UPLOAD csr_send_ese_adjacent_ap_rep_ind(mac_ctx, session); -#else - csr_ese_send_adjacent_ap_rep_msg(mac_ctx, session); #endif session->isPrevApInfoValid = false; } @@ -13565,16 +13563,6 @@ CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, cdf_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; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index acebf9b3ae3f..529ee0de6724 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4469,8 +4469,6 @@ CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, #ifdef FEATURE_WLAN_ESE_UPLOAD tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg; tpAniGetTsmStatsRsp pTsmRspParams = NULL; -#else - tpTSMStats pStats = (tpTSMStats) pTsmStatsMsg; #endif /* FEATURE_WLAN_ESE_UPLOAD */ int tid = pStats->tid; /* @@ -4506,8 +4504,6 @@ CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, pTsmRspParams->rc = eSIR_FAILURE; pTsmRspParams->tsmStatsReq = pStats; pTsmMetric = &pTsmRspParams->tsmMetrics; -#else - pTsmMetric = (tpAniTrafStrmMetrics)&(pStats->tsmMetrics); #endif /* FEATURE_WLAN_ESE_UPLOAD */ /* populate pTsmMetric */ pTsmMetric->UplinkPktQueueDly = queue_delay_microsec; @@ -4527,8 +4523,6 @@ CDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, /* post this message to LIM/PE */ #ifdef FEATURE_WLAN_ESE_UPLOAD wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0); -#else - wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmStatsMsg, 0); #endif /* FEATURE_WLAN_ESE_UPLOAD */ return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From b051973c794294641038e17c1017b20f54789b1a Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 11:37:34 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in roam_offload_synch_ind Replace tSirMacAddr with cdf_mac_addr in roam_offload_synch_ind. Change-Id: I953b089391f00ff2108e1f311a33d50aca724409 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_api.c | 2 +- core/sme/inc/csr_internal.h | 2 +- core/sme/src/csr/csr_api_roam.c | 4 ++-- core/wma/src/wma_scan_roam.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e075068b0864..7861f194066e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3939,7 +3939,7 @@ typedef struct sSirSmeRoamOffloadSynchInd { uint16_t reassocRespLength; uint8_t isBeacon; uint8_t roamedVdevId; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; int8_t txMgmtPower; uint32_t authStatus; uint8_t rssi; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 130d3f648737..2a2134ad58fd 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1977,7 +1977,7 @@ void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) roam_sync_ind_ptr->authStatus, roam_sync_ind_ptr->roamedVdevId); CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, - roam_sync_ind_ptr->bssId, 6); + roam_sync_ind_ptr->bssid.bytes, CDF_MAC_ADDR_SIZE); session_ptr = pe_find_session_by_bss_idx(pMac, roam_sync_ind_ptr->roamedVdevId); if (session_ptr == NULL) { diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 55408dfa445f..830ff6b67a15 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -856,7 +856,7 @@ typedef struct tagCsrRoamOffloadSynchStruct { uint8_t nss; /* no of spatial streams */ uint16_t chainMask; /* chainmask */ uint16_t smpsMode; /* smps.mode */ - tSirMacAddr bssid; /* MAC address of roamed AP */ + struct cdf_mac_addr bssid; /* MAC address of roamed AP */ bool bRoamSynchInProgress; /* a roam offload synch */ tCsrRoamOffloadAuthStatus authStatus; /* auth status */ uint8_t kck[SIR_KCK_KEY_LEN]; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index fbfa066e3e5b..252ba49fcd59 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -18325,8 +18325,8 @@ void csr_process_roam_offload_synch_ind(tHalHandle hHal, roam_synch_ind_ptr->roamReason; session_ptr->roamOffloadSynchParams.roamedVdevId = roam_synch_ind_ptr->roamedVdevId; - cdf_mem_copy(session_ptr->roamOffloadSynchParams.bssid, - roam_synch_ind_ptr->bssId, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&session_ptr->roamOffloadSynchParams.bssid, + &roam_synch_ind_ptr->bssid); session_ptr->roamOffloadSynchParams.txMgmtPower = roam_synch_ind_ptr->txMgmtPower; session_ptr->roamOffloadSynchParams.authStatus = diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 0156f9ac7f31..56318d6e8e6a 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -2785,7 +2785,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, roam_synch_ind_ptr->rssi = synch_event->rssi; roam_synch_ind_ptr->isBeacon = synch_event->is_beacon; WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, - roam_synch_ind_ptr->bssId); + roam_synch_ind_ptr->bssid.bytes); roam_synch_ind_ptr->beaconProbeRespOffset = sizeof(roam_offload_synch_ind); bcn_probersp_ptr = -- cgit v1.2.3 From bb59cdd6bca3bc16c40741d5f4994e1345e08ca9 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 11:50:16 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in struct roam_ext_params Replace tSirMacAddr with cdf_mac_addr in struct roam_ext_params Change-Id: I54abd74a93abdfee4a8eb413de78b939a07b97e7 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_cfg80211.c | 16 ++++++++-------- core/mac/inc/sir_api.h | 4 ++-- core/sme/src/common/sme_api.c | 7 +++---- core/sme/src/csr/csr_api_roam.c | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5c3b659ab8a9..fcb331a9c22b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -2367,11 +2367,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, hddLog(LOGE, FL("attr mac address failed")); goto fail; } - nla_memcpy(roam_params.bssid_favored[i], + nla_memcpy(roam_params.bssid_favored[i].bytes, tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID], - sizeof(tSirMacAddr)); - hddLog(CDF_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR, - MAC_ADDR_ARRAY(roam_params.bssid_favored[i])); + CDF_MAC_ADDR_SIZE); + hdd_debug(MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes)); /* 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")); @@ -2412,12 +2412,12 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, hddLog(LOGE, FL("attr blacklist addr failed")); goto fail; } - nla_memcpy(roam_params.bssid_avoid_list[i], + nla_memcpy(roam_params.bssid_avoid_list[i].bytes, tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID], - sizeof(tSirMacAddr)); - hddLog(CDF_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR, + CDF_MAC_ADDR_SIZE); + hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY( - roam_params.bssid_avoid_list[i])); + roam_params.bssid_avoid_list[i].bytes)); i++; } sme_update_roam_params(pHddCtx->hHal, session_id, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 7861f194066e..c96ca50d252e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2880,8 +2880,8 @@ struct roam_ext_params { 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]; + struct cdf_mac_addr bssid_avoid_list[MAX_BSSID_AVOID_LIST]; + struct cdf_mac_addr bssid_favored[MAX_BSSID_FAVORED]; uint8_t bssid_favored_factor[MAX_BSSID_FAVORED]; int raise_rssi_thresh_5g; int drop_rssi_thresh_5g; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index d53f36ab5a4f..382f93decaa8 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1509,13 +1509,12 @@ CDF_STATUS sme_update_roam_params(tHalHandle hal, break; case REASON_ROAM_SET_BLACKLIST_BSSID: cdf_mem_set(&roam_params_dst->bssid_avoid_list, 0, - sizeof(tSirMacAddr) * MAX_BSSID_AVOID_LIST); + CDF_MAC_ADDR_SIZE * MAX_BSSID_AVOID_LIST); roam_params_dst->num_bssid_avoid_list = roam_params_src.num_bssid_avoid_list; for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) { - cdf_mem_copy(&roam_params_dst->bssid_avoid_list[i], - &roam_params_src.bssid_avoid_list[i], - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roam_params_dst->bssid_avoid_list[i], + &roam_params_src.bssid_avoid_list[i]); } break; case REASON_ROAM_GOOD_RSSI_CHANGED: diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 252ba49fcd59..72d99e285b6e 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17035,7 +17035,7 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, "Blacklist Bssid: ("MAC_ADDRESS_STR")", - MAC_ADDR_ARRAY(roam_params_dst->bssid_avoid_list[i])); + MAC_ADDR_ARRAY(roam_params_dst->bssid_avoid_list[i].bytes)); } for (i = 0; i < roam_params_dst->num_ssid_allowed_list; i++) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, @@ -17046,7 +17046,7 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, for (i = 0; i < roam_params_dst->num_bssid_favored; i++) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, "Preferred Bssid: ("MAC_ADDRESS_STR") score: %d", - MAC_ADDR_ARRAY(roam_params_dst->bssid_favored[i]), + MAC_ADDR_ARRAY(roam_params_dst->bssid_favored[i].bytes), roam_params_dst->bssid_favored_factor[i]); } -- cgit v1.2.3 From b0a524b4eab45d595cade6afb06c0b72ef78a496 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 12:11:13 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirAppTypeParams Replace tSirMacAddr with cdf_mac_addr in tSirAppTypeParams Change-Id: I4629ab11d8014eae6ba27b24362b9253be1606b7 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_ioctl.c | 14 ++++++-------- core/mac/inc/sir_api.h | 4 ++-- core/wma/src/wma_features.c | 8 ++++---- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index c593a6a00d1a..462ffd679dc0 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1723,7 +1723,7 @@ static int hdd_set_app_type1_parser(hdd_adapter_t *adapter, tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); char id[20], password[20]; tSirAppType1Params params; - int rc, i; + int rc; rc = wlan_hdd_validate_context(hdd_ctx); if (0 != rc) { @@ -1739,9 +1739,7 @@ static int hdd_set_app_type1_parser(hdd_adapter_t *adapter, memset(¶ms, 0, sizeof(tSirAppType1Params)); params.vdev_id = adapter->sessionId; - for (i = 0; i < ETHER_ADDR_LEN; i++) - params.wakee_mac_addr[i] = - adapter->macAddressCurrent.bytes[i]; + cdf_copy_macaddr(¶ms.wakee_mac_addr, &adapter->macAddressCurrent); params.id_length = strlen(id); cdf_mem_copy(params.identification_id, id, params.id_length); @@ -1750,7 +1748,7 @@ static int hdd_set_app_type1_parser(hdd_adapter_t *adapter, CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: %d %pM %.8s %u %.16s %u", - __func__, params.vdev_id, params.wakee_mac_addr, + __func__, params.vdev_id, params.wakee_mac_addr.bytes, params.identification_id, params.id_length, params.password, params.pass_length); @@ -1782,7 +1780,7 @@ static int hdd_set_app_type2_parser(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter); char mac_addr[20], rc4_key[20]; - unsigned int gateway_mac[6], i; + unsigned int gateway_mac[CDF_MAC_ADDR_SIZE]; tSirAppType2Params params; int ret; @@ -1831,8 +1829,8 @@ static int hdd_set_app_type2_parser(hdd_adapter_t *adapter, return -EINVAL; } - for (i = 0; i < ETHER_ADDR_LEN; i++) - params.gateway_mac[i] = (uint8_t) gateway_mac[i]; + cdf_mem_copy(¶ms.gateway_mac.bytes, (uint8_t *) &gateway_mac, + CDF_MAC_ADDR_SIZE); params.rc4_key_len = strlen(rc4_key); cdf_mem_copy(params.rc4_key, rc4_key, params.rc4_key_len); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c96ca50d252e..a710e37a462a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2650,7 +2650,7 @@ typedef struct { typedef struct { uint8_t vdev_id; - tSirMacAddr wakee_mac_addr; + struct cdf_mac_addr wakee_mac_addr; uint8_t identification_id[8]; uint8_t password[16]; uint32_t id_length; @@ -2679,7 +2679,7 @@ typedef struct { uint32_t keepalive_max; /* Maximum ping interval */ uint32_t keepalive_inc; /* Increment of ping interval */ - tSirMacAddr gateway_mac; + struct cdf_mac_addr gateway_mac; uint32_t tcp_tx_timeout_val; uint32_t tcp_rx_timeout_val; } tSirAppType2Params, *tpSirAppType2Params; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 529ee0de6724..e5a5216ad6b7 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5413,7 +5413,7 @@ int wma_set_app_type1_params_in_fw(tp_wma_handle wma, (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, + WMI_CHAR_ARRAY_TO_MAC_ADDR(appType1Params->wakee_mac_addr.bytes, &cmd->wakee_mac); cdf_mem_copy(cmd->ident, appType1Params->identification_id, 8); cmd->ident_len = appType1Params->id_length; @@ -5423,7 +5423,7 @@ int wma_set_app_type1_params_in_fw(tp_wma_handle wma, 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, + __func__, cmd->vdev_id, appType1Params->wakee_mac_addr.bytes, cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len); ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, @@ -5486,7 +5486,7 @@ int wma_set_app_type2_params_in_fw(tp_wma_handle wma, cmd->keepalive_max = appType2Params->keepalive_max; cmd->keepalive_inc = appType2Params->keepalive_inc; - WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac, + WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes, &cmd->gateway_mac); cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val; cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val; @@ -5498,7 +5498,7 @@ int wma_set_app_type2_params_in_fw(tp_wma_handle wma, "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, + __func__, cmd->vdev_id, appType2Params->gateway_mac.bytes, 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, -- cgit v1.2.3 From 28d44ef4e4db297e404383de968a00cddcecbc82 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 12:28:25 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirKeepAliveReq Replace tSirMacAddr with cdf_mac_addr in tSirKeepAliveReq. Change-Id: Id7184f0acfba870c2f17b9d2dd76015687eb06b2 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_wext.c | 6 ++---- core/mac/inc/sir_api.h | 4 ++-- core/sme/src/common/sme_api.c | 3 +-- core/wma/src/wma_mgmt.c | 3 ++- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 3b50abf90b2f..42b9950331cc 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -8585,10 +8585,8 @@ static int __iw_set_keepalive_params(struct net_device *dev, request->destIpv4Addr[0], request->destIpv4Addr[1], request->destIpv4Addr[2], request->destIpv4Addr[3]); - hdd_info("Dest MAC address: %d:%d:%d:%d:%d:%d", - request->destMacAddr[0], request->destMacAddr[1], - request->destMacAddr[2], request->destMacAddr[3], - request->destMacAddr[4], request->destMacAddr[5]); + hdd_info("Dest MAC address: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(request->dest_macaddr.bytes)); break; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a710e37a462a..e873d6de9e92 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2582,8 +2582,8 @@ typedef struct sSirKeepAliveReq { uint32_t timePeriod; tSirIpv4Addr hostIpv4Addr; tSirIpv4Addr destIpv4Addr; - tSirMacAddr destMacAddr; - tSirMacAddr bssId; + struct cdf_mac_addr dest_macaddr; + struct cdf_mac_addr bssid; uint8_t sessionId; } tSirKeepAliveReq, *tpSirKeepAliveReq; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 382f93decaa8..5618a8fdd746 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -6013,8 +6013,7 @@ CDF_STATUS sme_set_keep_alive(tHalHandle hHal, uint8_t session_id, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(request->bssId, pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&request->bssid, &pSession->connectedProfile.bssid); cdf_mem_copy(request_buf, request, sizeof(tSirKeepAliveReq)); CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_LOW, diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 2287edb20722..1171b7ad2dd3 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -2622,7 +2622,8 @@ void wma_set_keepalive_req(tp_wma_handle wma, keepalive->packetType, keepalive->timePeriod, keepalive->hostIpv4Addr, - keepalive->destIpv4Addr, keepalive->destMacAddr); + keepalive->destIpv4Addr, + keepalive->dest_macaddr.bytes); cdf_mem_free(keepalive); } -- cgit v1.2.3 From 1c15c847bf225235e06fc0d69cf504a3b4982d8c Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 12:39:12 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirHostOffloadReq Replace tSirMacAddr with cdf_mac_addr in tSirHostOffloadReq. Change-Id: I94c7eace8e49f6e5a83e3d58d7ee3250c8100c0f CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/sme/src/common/sme_power_save.c | 6 ++---- core/wma/src/wma_features.c | 7 +++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e873d6de9e92..b40ec87debee 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2569,7 +2569,7 @@ typedef struct sSirHostOffloadReq { #ifdef WLAN_NS_OFFLOAD tSirNsOffloadReq nsOffloadInfo; #endif /* WLAN_NS_OFFLOAD */ - tSirMacAddr bssId; + struct cdf_mac_addr bssid; } tSirHostOffloadReq, *tpSirHostOffloadReq; /* Packet Types. */ diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c index be463897a2f8..b12bd4d004e3 100644 --- a/core/sme/src/common/sme_power_save.c +++ b/core/sme/src/common/sme_power_save.c @@ -990,8 +990,7 @@ CDF_STATUS sme_set_ps_host_offload(tHalHandle hal_ctx, return CDF_STATUS_E_NOMEM; } - cdf_mem_copy(request->bssId, session->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&request->bssid, &session->connectedProfile.bssid); cdf_mem_copy(request_buf, request, sizeof(tSirHostOffloadReq)); @@ -1033,8 +1032,7 @@ CDF_STATUS sme_set_ps_ns_offload(tHalHandle hal_ctx, return CDF_STATUS_E_FAILURE; } - cdf_mem_copy(request->bssId, session->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&request->bssid, &session->connectedProfile.bssid); request_buf = cdf_mem_malloc(sizeof(*request_buf)); if (NULL == request_buf) { diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index e5a5216ad6b7..739cd6eae973 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -4910,15 +4910,15 @@ CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, uint32_t count = 0, num_ns_ext_tuples = 0; /* Get the vdev id */ - if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssId, &vdev_id)) { + if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssid.bytes, + &vdev_id)) { WMA_LOGE("vdev handle is invalid for %pM", - pHostOffloadParams->bssId); + pHostOffloadParams->bssid.bytes); cdf_mem_free(pHostOffloadParams); return CDF_STATUS_E_INVAL; } if (!wma->interfaces[vdev_id].vdev_up) { - WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id); cdf_mem_free(pHostOffloadParams); return CDF_STATUS_E_FAILURE; @@ -4927,7 +4927,6 @@ CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, 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); -- cgit v1.2.3 From d11d8121cd52b992e3f9dfaa18a1fb721f8d51d4 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 14:09:39 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirUpdateAPWPARSNIEsReq Replace tSirMacAddr with cdf_mac_addr in tSirUpdateAPWPARSNIEsReq. Change-Id: I4ea2e5fb65157a1760e81dcf3bbaad0821ce71e0 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/sme/src/csr/csr_api_roam.c | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b40ec87debee..c79d58a3ae15 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2512,7 +2512,7 @@ typedef struct sSirUpdateAPWPARSNIEsReq { uint16_t messageType; /* eWNI_SME_SET_APWPARSNIEs_REQ */ uint16_t length; uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint8_t sessionId; /* Session ID */ tSirRSNie APWPARSNIEs; } tSirUpdateAPWPARSNIEsReq, *tpSirUpdateAPWPARSNIEsReq; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 81939b572ccb..d4b569c59f3d 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4244,7 +4244,7 @@ static void __lim_process_sme_set_wparsni_es(tpAniSirGlobal pMac, uint32_t *pMsg sizeof(struct sSirUpdateAPWPARSNIEsReq)); psessionEntry = pe_find_session_by_bssid(pMac, - pUpdateAPWPARSNIEsReq->bssId, + pUpdateAPWPARSNIEsReq->bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGW, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 72d99e285b6e..40d1f3c4fcfc 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17604,8 +17604,7 @@ CDF_STATUS csr_roam_update_wparsni_es(tpAniSirGlobal pMac, uint32_t sessionId, cdf_mem_set(pMsg, sizeof(tSirUpdateAPWPARSNIEsReq), 0); pMsg->messageType = eWNI_SME_SET_APWPARSNIEs_REQ; pMsg->transactionId = 0; - cdf_mem_copy(pMsg->bssId, &pSession->selfMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssid, &pSession->selfMacAddr); pMsg->sessionId = sessionId; cdf_mem_copy(&pMsg->APWPARSNIEs, pAPSirRSNie, sizeof(tSirRSNie)); -- cgit v1.2.3 From f51a2ff5d3d5eb110c91593f781f6efa668b1e14 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 14:18:13 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeProbeReqInd Replace tSirMacAddr with cdf_mac_addr in tSirSmeProbeReqInd. Change-Id: Ic9004fa301d196e684b1534a225a878f0df562a3 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_probe_req_frame.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c79d58a3ae15..e95c15112183 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2504,7 +2504,7 @@ typedef struct sSirSmeProbeReqInd { uint16_t messageType; /* eWNI_SME_WPS_PBC_PROBE_REQ_IND */ uint16_t length; uint8_t sessionId; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; tSirWPSPBCProbeReq WPSPBCProbeReq; } tSirSmeProbeReqInd, *tpSirSmeProbeReqInd; diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index 1ed186ec59c5..5c192f314914 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -664,8 +664,8 @@ lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, pSirSmeProbeReqInd->length = sizeof(tSirSmeProbeReq); pSirSmeProbeReqInd->sessionId = psessionEntry->smeSessionId; - cdf_mem_copy(pSirSmeProbeReqInd->bssId, psessionEntry->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeProbeReqInd->bssid.bytes, psessionEntry->bssId, + CDF_MAC_ADDR_SIZE); cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peerMacAddr, peerMacAddr, sizeof(tSirMacAddr)); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 40d1f3c4fcfc..237c3c660941 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10336,7 +10336,7 @@ csr_roam_chk_lnk_pbs_probe_req_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) sms_log(mac_ctx, LOG1, FL("WPS PBC Probe request Indication from SME")); status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *)pProbeReqInd->bssId, &sessionId); + &pProbeReqInd->bssid, &sessionId); if (CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_set(&roam_info, sizeof(tCsrRoamInfo), 0); roam_info.u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq; -- cgit v1.2.3 From 7c5fe34474fc7e73afd092e9383416bec00c917f Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 14:30:37 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirWPSPBCProbeReq Replace tSirMacAddr with cdf_mac_addr in tSirWPSPBCProbeReq. Change-Id: I7f465505aceaf420172635b9b21e57fc1e1d51ae CRs-Fixed: 898864 --- core/hdd/inc/qc_sap_ioctl.h | 2 +- core/hdd/src/wlan_hdd_hostapd.c | 18 ++++++++---------- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_probe_req_frame.c | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h index 6983a7a96ff1..d5b8259a7335 100644 --- a/core/hdd/inc/qc_sap_ioctl.h +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -109,7 +109,7 @@ struct sQcSapreq_wscie { * Retrieve the WPS PBC Probe Request IEs. */ typedef struct sQcSapreq_WPSPBCProbeReqIES { - uint8_t macaddr[QCSAP_ADDR_LEN]; + struct cdf_mac_addr macaddr; uint16_t probeReqIELen; uint8_t probeReqIE[512]; } sQcSapreq_WPSPBCProbeReqIES_t; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 357c6be68f7e..dd641595a16c 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1487,13 +1487,12 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, WPSPBCProbeReq.probeReqIE, pHddApCtx->WPSPBCProbeReq.probeReqIELen); - cdf_mem_copy(pHddApCtx->WPSPBCProbeReq.peerMacAddr, - pSapEvent->sapevt.sapPBCProbeReqEvent. - WPSPBCProbeReq.peerMacAddr, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pHddApCtx->WPSPBCProbeReq.peer_macaddr, + &pSapEvent->sapevt.sapPBCProbeReqEvent. + WPSPBCProbeReq.peer_macaddr); hddLog(LOG1, "WPS PBC probe req " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHddApCtx->WPSPBCProbeReq. - peerMacAddr)); + peer_macaddr.bytes)); memset(&wreq, 0, sizeof(wreq)); wreq.data.length = strlen(message); /* This is length of message */ wireless_send_event(dev, IWEVCUSTOM, &wreq, @@ -3766,9 +3765,8 @@ int __iw_get_wpspbc_probe_req_ies(struct net_device *dev, cdf_mem_copy(&WPSPBCProbeReqIEs.probeReqIE, pHddApCtx->WPSPBCProbeReq.probeReqIE, WPSPBCProbeReqIEs.probeReqIELen); - cdf_mem_copy(&WPSPBCProbeReqIEs.macaddr, - pHddApCtx->WPSPBCProbeReq.peerMacAddr, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&WPSPBCProbeReqIEs.macaddr, + &pHddApCtx->WPSPBCProbeReq.peer_macaddr); if (copy_to_user(wrqu->data.pointer, (void *)&WPSPBCProbeReqIEs, sizeof(WPSPBCProbeReqIEs))) { @@ -3776,8 +3774,8 @@ int __iw_get_wpspbc_probe_req_ies(struct net_device *dev, return -EFAULT; } wrqu->data.length = 12 + WPSPBCProbeReqIEs.probeReqIELen; - hddLog(LOG1, FL("Macaddress : " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(WPSPBCProbeReqIEs.macaddr)); + hdd_info("Macaddress : " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(WPSPBCProbeReqIEs.macaddr.bytes)); up(&pHddApCtx->semWpsPBCOverlapInd); EXIT(); return 0; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e95c15112183..900018849fdf 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2494,7 +2494,7 @@ typedef struct sSirSmeGetWPSPBCSessionsReq { } tSirSmeGetWPSPBCSessionsReq, *tpSirSmeGetWPSPBCSessionsReq; typedef struct sSirWPSPBCProbeReq { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint16_t probeReqIELen; uint8_t probeReqIE[512]; } tSirWPSPBCProbeReq, *tpSirWPSPBCProbeReq; diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index 5c192f314914..56b604ebaf83 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -666,8 +666,8 @@ lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, cdf_mem_copy(pSirSmeProbeReqInd->bssid.bytes, psessionEntry->bssId, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peerMacAddr, - peerMacAddr, sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peer_macaddr.bytes, + peerMacAddr, CDF_MAC_ADDR_SIZE); MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIELen = -- cgit v1.2.3 From e84e213cfcbdd9db144238aecbc34fcf13fd3db9 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 15:21:41 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeGetWPSPBCSessionsReq Replace tSirMacAddr with cdf_mac_addr in tSirSmeGetWPSPBCSessionsReq. Change-Id: I675907f2408b74e580fb9c5364e4ad1030e79736 CRs-Fixed: 898864 --- core/cdf/inc/cdf_util.h | 2 +- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_process_probe_req_frame.c | 23 ++++++++++++++-------- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 8 +++----- core/mac/src/pe/lim/lim_types.h | 5 +++-- core/sme/src/csr/csr_api_roam.c | 14 ++++++------- core/sme/src/csr/csr_inside_api.h | 6 ++++-- 7 files changed, 34 insertions(+), 28 deletions(-) diff --git a/core/cdf/inc/cdf_util.h b/core/cdf/inc/cdf_util.h index 7d9e16a60c03..537b1fd41b3a 100644 --- a/core/cdf/inc/cdf_util.h +++ b/core/cdf/inc/cdf_util.h @@ -140,7 +140,7 @@ CDF_INLINE_FN bool cdf_is_macaddr_equal(struct cdf_mac_addr *pMacAddr1, * * * Return: true if the MacAddress is all Zeros - * flase if the MacAddress is not all Zeros. + * false if the MacAddress is not all Zeros. * */ CDF_INLINE_FN bool cdf_is_macaddr_zero(struct cdf_mac_addr *pMacAddr) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 900018849fdf..b626ec077b0e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2488,9 +2488,9 @@ typedef struct sSirSmeGetWPSPBCSessionsReq { uint16_t length; void *pUsrContext; void *pSapEventCallback; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ /* MAC Address of STA in WPS Session to be removed */ - tSirMacAddr pRemoveMac; + struct cdf_mac_addr remove_mac; } tSirSmeGetWPSPBCSessionsReq, *tpSirSmeGetWPSPBCSessionsReq; typedef struct sSirWPSPBCProbeReq { diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index 56b604ebaf83..a9214728071f 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -145,26 +145,33 @@ static void lim_remove_timeout_pbc_sessions(tpAniSirGlobal pMac, } } -void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac, - tpPESession psessionEntry) +/** + * lim_remove_pbc_sessions() - Remove PBC sessions + * @mac: Pointer to Global MAC structure + * @remove_mac: MAC Address of STA in WPS Session to be removed + * @session_entry: session entry + * + * Return: none + */ +void lim_remove_pbc_sessions(tpAniSirGlobal mac, struct cdf_mac_addr remove_mac, + tpPESession session_entry) { tSirWPSPBCSession *pbc, *prev = NULL; - prev = pbc = psessionEntry->pAPWPSPBCSession; + prev = pbc = session_entry->pAPWPSPBCSession; while (pbc) { if (cdf_mem_compare((uint8_t *) pbc->addr, - (uint8_t *) pRemoveMac, - sizeof(tSirMacAddr))) { + (uint8_t *) remove_mac.bytes, + CDF_MAC_ADDR_SIZE)) { prev->next = pbc->next; - if (pbc == psessionEntry->pAPWPSPBCSession) - psessionEntry->pAPWPSPBCSession = pbc->next; + if (pbc == session_entry->pAPWPSPBCSession) + session_entry->pAPWPSPBCSession = pbc->next; cdf_mem_free(pbc); return; } prev = pbc; pbc = pbc->next; } - } /** diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index d4b569c59f3d..1c330e236b47 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3251,7 +3251,6 @@ void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, tSap_Event sap_event; tpWLAN_SAPEventCB sap_event_cb = NULL; uint8_t session_id = CSR_SESSION_ID_INVALID; - tSirMacAddr zero_mac = { 0, 0, 0, 0, 0, 0 }; tSap_GetWPSPBCSessionEvent *sap_get_wpspbc_event; if (msg_buf == NULL) { @@ -3269,7 +3268,7 @@ void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, * Find PE session Entry */ session_entry = pe_find_session_by_bssid(mac_ctx, - get_wps_pbc_sessions_req.bssId, &session_id); + get_wps_pbc_sessions_req.bssid.bytes, &session_id); if (session_entry == NULL) { lim_log(mac_ctx, LOGE, FL("session does not exist for given bssId")); @@ -3289,8 +3288,7 @@ void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, sap_event.sapHddEventCode = eSAP_GET_WPSPBC_SESSION_EVENT; sap_get_wpspbc_event->module = CDF_MODULE_ID_PE; - if (cdf_mem_compare(zero_mac, get_wps_pbc_sessions_req.pRemoveMac, - sizeof(tSirMacAddr))) { + if (cdf_is_macaddr_zero(&get_wps_pbc_sessions_req.remove_mac)) { lim_get_wpspbc_sessions(mac_ctx, sap_get_wpspbc_event->addr.bytes, sap_get_wpspbc_event->UUID_E, @@ -3298,7 +3296,7 @@ void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, session_entry); } else { lim_remove_pbc_sessions(mac_ctx, - get_wps_pbc_sessions_req.pRemoveMac, + get_wps_pbc_sessions_req.remove_mac, session_entry); /* don't have to inform the HDD/Host */ return; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index fab829f3f43b..d4b76258dd5d 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -816,8 +816,9 @@ void lim_get_wpspbc_sessions(tpAniSirGlobal pMac, uint8_t *addr, uint8_t *uuid_e eWPSPBCOverlap *overlap, tpPESession psessionEntry); void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry); void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry); -void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac, - tpPESession psessionEntry); +void lim_remove_pbc_sessions(tpAniSirGlobal pMac, + struct cdf_mac_addr pRemoveMac, + tpPESession psessionEntry); #define LIM_WPS_OVERLAP_TIMER_MS 10000 void diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 237c3c660941..28062cb770d8 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3183,9 +3183,8 @@ csr_roam_get_wps_session_overlap(tpAniSirGlobal pMac, uint32_t sessionId, "CSR getting WPS Session Overlap for Bssid = " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssId.bytes)); - status = - csr_send_mb_get_wpspbc_sessions(pMac, sessionId, bssId.bytes, pUsrContext, - pfnSapEventCallback, pRemoveMac); + status = csr_send_mb_get_wpspbc_sessions(pMac, sessionId, bssId, + pUsrContext, pfnSapEventCallback, pRemoveMac); return status; } @@ -14056,9 +14055,9 @@ csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, CDF_STATUS csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, uint32_t sessionId, - tSirMacAddr bssId, void *pUsrContext, + struct cdf_mac_addr bssid, void *pUsrContext, void *pfnSapEventCallback, - struct cdf_mac_addr pRemoveMac) + struct cdf_mac_addr remove_mac) { CDF_STATUS status = CDF_STATUS_SUCCESS; tSirSmeGetWPSPBCSessionsReq *pMsg; @@ -14076,9 +14075,8 @@ csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, uint32_t sessionId, cdf_mem_copy(pMsg->pUsrContext, pUsrContext, sizeof(void *)); cdf_mem_copy(pMsg->pSapEventCallback, pfnSapEventCallback, sizeof(void *)); - cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); - cdf_mem_copy(pMsg->pRemoveMac, pRemoveMac.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->bssid, &bssid); + cdf_copy_macaddr(&pMsg->remove_mac, &remove_mac); pMsg->length = sizeof(struct sSirSmeGetWPSPBCSessionsReq); status = cds_send_mb_message_to_mac(pMsg); } while (0); diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 3b97ebd26de3..8121ca0042d4 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -992,8 +992,10 @@ CDF_STATUS csr_roam_get_wps_session_overlap(tpAniSirGlobal pMac, uint32_t sessio void *pfnSapEventCallback, struct cdf_mac_addr pRemoveMac); -CDF_STATUS csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, uint32_t sessionId, - tSirMacAddr bssId, void *pUsrContext, +CDF_STATUS csr_send_mb_get_wpspbc_sessions(tpAniSirGlobal pMac, + uint32_t sessionId, + struct cdf_mac_addr bssId, + void *pUsrContext, void *pfnSapEventCallback, struct cdf_mac_addr pRemoveMac); -- cgit v1.2.3 From 8c976417a5d0289694c5cc88da4eb1a393b99792 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 15:39:54 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirWPSPBCSession Replace tSirMacAddr with cdf_mac_addr in tSirWPSPBCSession. Change-Id: I46c321c74cfae794c3a77be2cba198baa5aba12f CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_probe_req_frame.c | 25 ++++++++++------------ core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/mac/src/pe/lim/lim_types.h | 5 +++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b626ec077b0e..3d04d1fc2910 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2478,7 +2478,7 @@ typedef struct sSirSetHT2040Mode { typedef struct sSirWPSPBCSession { struct sSirWPSPBCSession *next; - tSirMacAddr addr; + struct cdf_mac_addr addr; uint8_t uuid_e[SIR_WPS_UUID_LEN]; uint32_t timestamp; } tSirWPSPBCSession; diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c index a9214728071f..6e45cd54057b 100644 --- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c @@ -61,7 +61,7 @@ lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, /** * lim_get_wpspbc_sessions() - to get wps pbs sessions * @mac_ctx: Pointer to Global MAC structure - * @addr: A pointer to probe request source MAC addresss + * @addr: probe request source MAC addresss * @uuid_e: A pointer to UUIDE element of WPS IE in WPS PBC probe request * @session: A pointer to station PE session * @@ -71,7 +71,7 @@ lim_send_sme_probe_req_ind(tpAniSirGlobal pMac, * @return None */ -void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, +void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, struct cdf_mac_addr addr, uint8_t *uuid_e, eWPSPBCOverlap *overlap, tpPESession session) { @@ -81,7 +81,7 @@ void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, cur_time = (uint32_t) (cdf_mc_timer_get_system_ticks() / CDF_TICKS_PER_SECOND); - cdf_mem_set((uint8_t *) addr, sizeof(tSirMacAddr), 0); + cdf_zero_macaddr(&addr); cdf_mem_set((uint8_t *) uuid_e, SIR_WPS_UUID_LEN, 0); for (pbc = session->pAPWPSPBCSession; pbc; pbc = pbc->next) { if (cur_time > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) @@ -89,8 +89,7 @@ void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, count++; if (count > 1) break; - cdf_mem_copy((uint8_t *) addr, (uint8_t *) pbc->addr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&addr, &pbc->addr); cdf_mem_copy((uint8_t *) uuid_e, (uint8_t *) pbc->uuid_e, SIR_WPS_UUID_LEN); } @@ -105,8 +104,8 @@ void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr, *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S; lim_log(mac_ctx, LOGE, FL("overlap = %d"), *overlap); - sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, addr, - sizeof(tSirMacAddr)); + sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, addr.bytes, + CDF_MAC_ADDR_SIZE); sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, uuid_e, SIR_WPS_UUID_LEN); return; @@ -160,9 +159,7 @@ void lim_remove_pbc_sessions(tpAniSirGlobal mac, struct cdf_mac_addr remove_mac, prev = pbc = session_entry->pAPWPSPBCSession; while (pbc) { - if (cdf_mem_compare((uint8_t *) pbc->addr, - (uint8_t *) remove_mac.bytes, - CDF_MAC_ADDR_SIZE)) { + if (cdf_is_macaddr_equal(&pbc->addr, &remove_mac)) { prev->next = pbc->next; if (pbc == session_entry->pAPWPSPBCSession) session_entry->pAPWPSPBCSession = pbc->next; @@ -224,8 +221,8 @@ static void lim_update_pbc_session_entry(tpAniSirGlobal pMac, while (pbc) { if (cdf_mem_compare - ((uint8_t *) pbc->addr, (uint8_t *) addr, - sizeof(tSirMacAddr)) + ((uint8_t *) pbc->addr.bytes, (uint8_t *) addr, + CDF_MAC_ADDR_SIZE) && cdf_mem_compare((uint8_t *) pbc->uuid_e, (uint8_t *) uuid_e, SIR_WPS_UUID_LEN)) { if (prev) @@ -246,8 +243,8 @@ static void lim_update_pbc_session_entry(tpAniSirGlobal pMac, ) return; } - cdf_mem_copy((uint8_t *) pbc->addr, (uint8_t *) addr, - sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pbc->addr.bytes, (uint8_t *) addr, + CDF_MAC_ADDR_SIZE); if (uuid_e) cdf_mem_copy((uint8_t *) pbc->uuid_e, diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 1c330e236b47..b3933f9fb7a3 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3290,7 +3290,7 @@ void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, if (cdf_is_macaddr_zero(&get_wps_pbc_sessions_req.remove_mac)) { lim_get_wpspbc_sessions(mac_ctx, - sap_get_wpspbc_event->addr.bytes, + sap_get_wpspbc_event->addr, sap_get_wpspbc_event->UUID_E, &sap_get_wpspbc_event->wpsPBCOverlap, session_entry); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index d4b76258dd5d..55f02fa66f22 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -812,8 +812,9 @@ void lim_send_vdev_restart(tpAniSirGlobal pMac, tpPESession psessionEntry, uint8_t sessionId); -void lim_get_wpspbc_sessions(tpAniSirGlobal pMac, uint8_t *addr, uint8_t *uuid_e, - eWPSPBCOverlap *overlap, tpPESession psessionEntry); +void lim_get_wpspbc_sessions(tpAniSirGlobal pMac, struct cdf_mac_addr addr, + uint8_t *uuid_e, eWPSPBCOverlap *overlap, + tpPESession psessionEntry); void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry); void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry); void lim_remove_pbc_sessions(tpAniSirGlobal pMac, -- cgit v1.2.3 From e0012150d2ff05f7d8b393f8527c45b1a4ea0128 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Mon, 14 Dec 2015 20:31:26 -0800 Subject: Release 5.0.0.150 Release 5.0.0.150 Change-Id: Ic243af4c7c3bd1061c2b5427ecab48da45b718b8 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 84ac7fee464b..7852513950e3 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 149 +#define QWLAN_VERSION_BUILD 150 -#define QWLAN_VERSIONSTR "5.0.0.149" +#define QWLAN_VERSIONSTR "5.0.0.150" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 8c0f3422a788a62c699c89017b5e0d748951996b Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Mon, 9 Nov 2015 18:41:20 -0800 Subject: qcacld-3.0: Interfacing files for LFR Subnet Detection support Add interfacing files and configuration options to enable LFR subnet detection feature support. Change-Id: I46756dfb2dd8071fd2bb762038414709e6212c1c CRs-fixed: 876335 --- Kbuild | 11 +++++++++++ Kconfig | 4 ++++ core/cdf/inc/cdf_types.h | 1 + core/mac/inc/sir_api.h | 27 +++++++++++++++++++++++++++ core/mac/src/include/sir_params.h | 2 +- core/sme/inc/sme_api.h | 5 +++++ core/wma/inc/wma.h | 11 +++++++++++ core/wma/inc/wma_types.h | 1 + 8 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Kbuild b/Kbuild index 23c60360a9e3..8e0256309419 100644 --- a/Kbuild +++ b/Kbuild @@ -130,6 +130,9 @@ ifeq ($(KERNEL_BUILD), 0) CONFIG_WLAN_LRO := n endif endif + + # Flag to enable LFR Subnet Detection + CONFIG_LFR_SUBNET_DETECTION := y endif ifneq ($(CONFIG_MOBILE_ROUTER), y) @@ -338,6 +341,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_memdump.o endif +ifeq ($(CONFIG_LFR_SUBNET_DETECTION), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_subnet_detect.o +endif + ########### HOST DIAG LOG ########### HOST_DIAG_LOG_DIR := core/utils/host_diag_log @@ -1317,6 +1324,10 @@ ifeq ($(CONFIG_STATICALLY_ADD_11P_CHANNELS),y) CDEFINES += -DFEATURE_STATICALLY_ADD_11P_CHANNELS endif +ifeq ($(CONFIG_LFR_SUBNET_DETECTION), y) +CDEFINES += -DFEATURE_LFR_SUBNET_DETECTION +endif + KBUILD_CPPFLAGS += $(CDEFINES) # Currently, for versions of gcc which support it, the kernel Makefile diff --git a/Kconfig b/Kconfig index 9cf8e1d9d01e..940ae4dcf1fd 100644 --- a/Kconfig +++ b/Kconfig @@ -107,4 +107,8 @@ config WLAN_FEATURE_RX_WAKELOCK bool "Enable RX wake lock feature" default n +config FEATURE_LFR_SUBNET_DETECTION + bool "Enable LFR Subnet Change Detection" + default n + endif # QCA_CLD_WLAN diff --git a/core/cdf/inc/cdf_types.h b/core/cdf/inc/cdf_types.h index 27151417bd03..5c987af344ca 100644 --- a/core/cdf/inc/cdf_types.h +++ b/core/cdf/inc/cdf_types.h @@ -353,6 +353,7 @@ struct cdf_mac_addr { #define CDF_MAC_ADDR_ZERO_INITIALIZER { { 0, 0, 0, 0, 0, 0 } } #define CDF_IPV4_ADDR_SIZE (4) +#define CDF_IPV6_ADDR_SIZE (16) /** * struct cdf_tso_frag_t - fragments of a single TCP segment diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3d04d1fc2910..a627a09d4785 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5395,6 +5395,33 @@ enum powersave_mode { PS_QPOWER_DEEPSLEEP = 4, PS_DUTY_CYCLING_QPOWER = 5 }; +#ifdef FEATURE_LFR_SUBNET_DETECTION +/** + * struct gateway_param_update_req - gateway parameter update request + * @request_id: request id + * @session_id: session id + * @max_retries: Max ARP/NS retry attempts + * @timeout: Retry interval + * @ipv4_addr_type: on ipv4 network + * @ipv6_addr_type: on ipv6 network + * @gw_mac_addr: gateway mac addr + * @ipv4_addr: ipv4 addr + * @ipv6_addr: ipv6 addr + */ +struct gateway_param_update_req { + uint32_t request_id; + uint32_t session_id; + uint32_t max_retries; + uint32_t timeout; + uint32_t ipv4_addr_type; + uint32_t ipv6_addr_type; + struct cdf_mac_addr gw_mac_addr; + uint8_t ipv4_addr[CDF_IPV4_ADDR_SIZE]; + uint8_t ipv6_addr[CDF_IPV6_ADDR_SIZE]; +}; +#else +struct gateway_param_update_req; +#endif /* FEATURE_LFR_SUBNET_DETECTION */ /** * struct sir_sme_ext_change_chan_req - channel change request diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index c5b6d7c56ed7..22aabae93a5b 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -579,7 +579,7 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_EXIT_PS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 236) #define SIR_HAL_ENABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237) #define SIR_HAL_DISABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238) - +#define SIR_HAL_GATEWAY_PARAM_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239) #define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313) #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) diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 91f6526aedf0..93e307fbcaa5 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1075,4 +1075,9 @@ sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset, } #endif +#ifdef FEATURE_LFR_SUBNET_DETECTION +CDF_STATUS sme_gateway_param_update(tHalHandle hHal, + struct gateway_param_update_req *request); +#endif + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 9a3cea4b1908..95a1ad5b40e6 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2008,6 +2008,17 @@ int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params, void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region); uint32_t wma_get_vht_ch_width(void); +#ifdef FEATURE_LFR_SUBNET_DETECTION +CDF_STATUS wma_set_gateway_params(tp_wma_handle wma, + struct gateway_param_update_req *req); +#else +static inline CDF_STATUS wma_set_gateway_params(tp_wma_handle wma, + struct gateway_param_update_req *req) +{ + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_LFR_SUBNET_DETECTION */ + #if defined(FEATURE_LRO) CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle, struct wma_lro_config_cmd_t *wma_lro_cmd); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 5c5c9747ff70..6676a08a1aef 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -447,6 +447,7 @@ #define WMA_SET_IE_INFO SIR_HAL_SET_IE_INFO #define WMA_LRO_CONFIG_CMD SIR_HAL_LRO_CONFIG_CMD +#define WMA_GW_PARAM_UPDATE_REQ SIR_HAL_GATEWAY_PARAM_UPDATE_REQ /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 -- cgit v1.2.3 From 4a9c884d7b368c3c0bc588d411ae2a4828b00fb7 Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Mon, 9 Nov 2015 18:56:53 -0800 Subject: qcacld-3.0: Add an INI item to configure LFR subnet detection Add an INI item to configure LFR subnet detection feature. LFR subnet detection is enabled by default. Change-Id: Ifb4bba60dfcd0347137f4a690db50b0c453d1ae8 CRs-Fixed: 876335 --- core/hdd/inc/wlan_hdd_cfg.h | 18 ++++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 3d5efe59eeab..e6a7d36ec954 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2818,6 +2818,21 @@ enum dot11p_mode { #define CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX (-30) #define CFG_FIRST_SCAN_BUCKET_THRESHOLD_DEFAULT (-30) +#ifdef FEATURE_LFR_SUBNET_DETECTION +/* + * Enable IP subnet detection during legacy fast roming version 3. + * Legacy fast roaming could roam across IP subnets without host + * processors' knowledge. This feature enables firmware to wake up + * the host processor if it successfully determines change in the IP subnet. + * Change in IP subnet could potentially cause disruption in IP connnectivity + * if IP address is not refreshed. + */ +#define CFG_ENABLE_LFR_SUBNET_DETECTION "gLFRSubnetDetectionEnable" +#define CFG_ENABLE_LFR_SUBNET_MIN (0) +#define CFG_ENABLE_LFR_SUBNET_MAX (1) +#define CFG_ENABLE_LFR_SUBNET_DEFAULT (1) +#endif /* FEATURE_LFR_SUBNET_DETECTION */ + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3400,6 +3415,9 @@ struct hdd_config { int8_t early_stop_scan_max_threshold; int8_t first_scan_bucket_threshold; uint8_t ht_mpdu_density; +#ifdef FEATURE_LFR_SUBNET_DETECTION + bool enable_lfr_subnet_detection; +#endif }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 5192d0b5a493..b15405ef331c 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3640,6 +3640,14 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_FIRST_SCAN_BUCKET_THRESHOLD_MIN, CFG_FIRST_SCAN_BUCKET_THRESHOLD_MAX), +#ifdef FEATURE_LFR_SUBNET_DETECTION + REG_VARIABLE(CFG_ENABLE_LFR_SUBNET_DETECTION, WLAN_PARAM_Integer, + struct hdd_config, enable_lfr_subnet_detection, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LFR_SUBNET_DEFAULT, + CFG_ENABLE_LFR_SUBNET_MIN, + CFG_ENABLE_LFR_SUBNET_MAX), +#endif }; @@ -5193,6 +5201,12 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CFG_HT_MPDU_DENSITY_NAME, pHddCtx->config->ht_mpdu_density); + +#ifdef FEATURE_LFR_SUBNET_DETECTION + hddLog(LOGE, "Name = [%s] Value = [%d]", + CFG_ENABLE_LFR_SUBNET_DETECTION, + pHddCtx->config->enable_lfr_subnet_detection); +#endif } -- cgit v1.2.3 From 7bdae9f214858d18407a3bb640ebe7181d9d34ed Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Mon, 9 Nov 2015 19:03:46 -0800 Subject: qcacld-3.0: Add LFR Subnet Detection support Add LFR subnet detection support to protocol stack and device access layers. In LFR3, the device may perform multiple roams (may be across multiple IP subnets) without the knowledge of wlan host. The LFR subnet detection feature enables the device to regain IP connectivity if the firmware has roamed across the subnets which otherwise is not possible without disconnect and reconnect. Change-Id: I60959af8b6ed330313a7f08f8aa1edfb63938bb8 CRs-Fixed: 876335 --- core/sme/src/common/sme_api.c | 41 +++++++++++++++++++++++++++++ core/wma/src/wma_main.c | 5 ++++ core/wma/src/wma_scan_roam.c | 61 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 5618a8fdd746..2cf8fbb92381 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14703,6 +14703,47 @@ CDF_STATUS sme_soc_set_dual_mac_config(tHalHandle hal, return CDF_STATUS_SUCCESS; } +#ifdef FEATURE_LFR_SUBNET_DETECTION +/** + * sme_gateway_param_update() - to update gateway parameters with WMA + * @Hal: hal handle + * @gw_params: request parameters from HDD + * + * Return: CDF_STATUS + * + * This routine will update gateway parameters to WMA + */ +CDF_STATUS sme_gateway_param_update(tHalHandle Hal, + struct gateway_param_update_req *gw_params) +{ + CDF_STATUS cdf_status; + cds_msg_t cds_message; + struct gateway_param_update_req *request_buf; + + request_buf = cdf_mem_malloc(sizeof(*request_buf)); + if (NULL == request_buf) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to allocate memory for gw param update request")); + return CDF_STATUS_E_NOMEM; + } + + *request_buf = *gw_params; + + cds_message.type = WMA_GW_PARAM_UPDATE_REQ; + cds_message.reserved = 0; + cds_message.bodyptr = request_buf; + cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("Not able to post WMA_GW_PARAM_UPDATE_REQ message to HAL")); + cdf_mem_free(request_buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_LFR_SUBNET_DETECTION */ + /** * sme_set_peer_authorized() - call peer authorized callback * @peer_addr: peer mac address diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 9ecbdecc7637..b185e7e25070 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5280,6 +5280,11 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct wma_lro_config_cmd_t *)msg->bodyptr); cdf_mem_free(msg->bodyptr); break; + case WMA_GW_PARAM_UPDATE_REQ: + wma_set_gateway_params(wma_handle, + (struct gateway_param_update_req *)msg->bodyptr); + cdf_mem_free(msg->bodyptr); + break; default: WMA_LOGD("unknow msg type %x", msg->type); /* Do Nothing? MSG Body should be freed at here */ diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 56318d6e8e6a..f170cca1c1a4 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -6969,3 +6969,64 @@ CDF_STATUS wma_get_scan_id(uint32_t *scan_id) return CDF_STATUS_SUCCESS; } +#ifdef FEATURE_LFR_SUBNET_DETECTION +/** + * wma_set_gateway_params() - set gateway parameters + * @wma: WMA handle + * @req: gateway parameter update request structure + * + * This function reads the incoming @req and fill in the destination + * WMI structure and sends down the gateway configs down to the firmware + * + * Return: CDF_STATUS + */ +CDF_STATUS wma_set_gateway_params(tp_wma_handle wma, + struct gateway_param_update_req *req) +{ + wmi_roam_subnet_change_config_fixed_param *cmd; + wmi_buf_t buf; + int ret; + int len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc failed", __func__); + return CDF_STATUS_E_NOMEM; + } + + cmd = (wmi_roam_subnet_change_config_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_roam_subnet_change_config_fixed_param)); + + cmd->vdev_id = req->session_id; + cdf_mem_copy(&cmd->inet_gw_ip_v4_addr, req->ipv4_addr, + CDF_IPV4_ADDR_SIZE); + cdf_mem_copy(&cmd->inet_gw_ip_v6_addr, req->ipv6_addr, + CDF_IPV6_ADDR_SIZE); + WMI_CHAR_ARRAY_TO_MAC_ADDR(req->gw_mac_addr.bytes, + &cmd->inet_gw_mac_addr); + cmd->max_retries = req->max_retries; + cmd->timeout = req->timeout; + cmd->num_skip_subnet_change_detection_bssid_list = 0; + cmd->flag = 0; + if (req->ipv4_addr_type) + WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(cmd->flag); + + if (req->ipv6_addr_type) + WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(cmd->flag); + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID); + if (ret != EOK) { + WMA_LOGE("Failed to send gw config parameter to fw, ret: %d", + ret); + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; + } + + return CDF_STATUS_SUCCESS; +} +#endif /* FEATURE_LFR_SUBNET_DETECTION */ + -- cgit v1.2.3 From 47f7a469248e742bc3f359a486a8b9dbb1358042 Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Mon, 9 Nov 2015 19:11:43 -0800 Subject: qcacld-3.0: Add handler for gateway parameter update request Add handler for gateway parameter request vendor command. The request is issued to update the gateway parameters to be used during subnet detection post roaming. Change-Id: I848f24b36a1d65a0e8bb8465b2b6f2016cb2224c CRs-Fixed: 876335 --- core/hdd/src/wlan_hdd_cfg80211.c | 18 ++++ core/hdd/src/wlan_hdd_cfg80211.h | 23 ++++ core/hdd/src/wlan_hdd_subnet_detect.c | 195 ++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_subnet_detect.h | 44 ++++++++ 4 files changed, 280 insertions(+) create mode 100644 core/hdd/src/wlan_hdd_subnet_detect.c create mode 100644 core/hdd/src/wlan_hdd_subnet_detect.h diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index fcb331a9c22b..9f431ae95cd1 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -87,6 +87,8 @@ #include "wlan_hdd_ocb.h" +#include "wlan_hdd_subnet_detect.h" + #define g_mode_rates_size (12) #define a_mode_rates_size (8) #define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \ @@ -1064,6 +1066,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT }, +#ifdef FEATURE_LFR_SUBNET_DETECTION + [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG + }, +#endif /*FEATURE_LFR_SUBNET_DETECTION */ }; /** @@ -4982,6 +4990,16 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_set_ota_test }, +#ifdef FEATURE_LFR_SUBNET_DETECTION + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_gateway_params + }, +#endif /* FEATURE_LFR_SUBNET_DETECTION */ }; /* diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 34275409f0bd..34134d3b9ff4 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -249,6 +249,7 @@ typedef enum { * @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete * @QCA_NL80211_VENDOR_SUBCMD_OTA_TEST: enable OTA test + * @QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG: set gateway parameters */ enum qca_nl80211_vendor_subcmds { @@ -350,6 +351,8 @@ enum qca_nl80211_vendor_subcmds { /* subcommand to get link properties */ QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101, + /* LFR Subnet Detection */ + QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102, /* DBS subcommands */ QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103, @@ -420,6 +423,8 @@ enum qca_nl80211_vendor_subcmds { * @QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX: vendor scan index * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX: * vendor scan complete event index + * @QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX: + * update gateway parameters index */ enum qca_nl80211_vendor_subcmds_index { @@ -488,6 +493,7 @@ enum qca_nl80211_vendor_subcmds_index { QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX, QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX, QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX, + QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX, }; /** @@ -2165,6 +2171,23 @@ enum qca_vendor_attr_probable_oper_channel { QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST - 1 }; +/** + * enum qca_wlan_vendor_attr_gw_param_config - gateway param config + * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_INVALID: Invalid + * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR: gateway mac addr + * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR: ipv4 addr + * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR: ipv6 addr + */ +enum qca_wlan_vendor_attr_gw_param_config { + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR, + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR, + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR, + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_AFTER_LAST - 1, +}; + /** * enum drv_dbs_capability - DBS capability * @DRV_DBS_CAPABILITY_DISABLED: DBS disabled diff --git a/core/hdd/src/wlan_hdd_subnet_detect.c b/core/hdd/src/wlan_hdd_subnet_detect.c new file mode 100644 index 000000000000..44d69b5c24b3 --- /dev/null +++ b/core/hdd/src/wlan_hdd_subnet_detect.c @@ -0,0 +1,195 @@ +/* + * 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. + */ + +/** + * DOC: wlan_hdd_subnet_detect.c + * + * WLAN Host Device Driver subnet detect API implementation + */ + +#include +#include +#include +#include +#include +#include "sme_api.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_subnet_detect.h" + +/* + * define short names for the global vendor params + * used by __wlan_hdd_cfg80211_set_gateway_params() + */ +#define PARAM_MAC_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR +#define PARAM_IPV4_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR +#define PARAM_IPV6_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR + +static const struct nla_policy + policy[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1] = { + [PARAM_MAC_ADDR] = { + .type = NLA_BINARY, + .len = CDF_MAC_ADDR_SIZE + }, + [PARAM_IPV4_ADDR] = { + .type = NLA_BINARY, + .len = CDF_IPV4_ADDR_SIZE + }, + [PARAM_IPV6_ADDR] = { + .type = NLA_BINARY, + .len = CDF_IPV6_ADDR_SIZE + } +}; + +/** + * __wlan_hdd_cfg80211_set_gateway_params() - set gateway params + * @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_set_gateway_params(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[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1]; + struct gateway_param_update_req req = { 0 }; + int ret; + CDF_STATUS status; + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + /* user may have disabled the feature in INI */ + if (!hdd_ctx->config->enable_lfr_subnet_detection) { + hdd_info("LFR Subnet Detection disabled in INI"); + return -ENOTSUPP; + } + + /* The gateway parameters are only valid in the STA persona + * and only in the connected state. + */ + if (WLAN_HDD_INFRA_STATION != adapter->device_mode) { + hdd_err("Received GW param update for non-STA mode adapter"); + return -ENOTSUPP; + } + + if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { + hdd_err("Received GW param update in disconnected state!"); + return -ENOTSUPP; + } + + /* Extract NL parameters + * mac_addr: 6 bytes + * ipv4 addr: 4 bytes + * ipv6 addr: 16 bytes + */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX, + data, data_len, policy)) { + hdd_err("Invalid ATTR list"); + return -EINVAL; + } + + if (!tb[PARAM_MAC_ADDR]) { + hdd_err("request mac addr failed"); + return -EINVAL; + } + nla_memcpy(req.gw_mac_addr.bytes, tb[PARAM_MAC_ADDR], + CDF_MAC_ADDR_SIZE); + + /* req ipv4_addr_type and ipv6_addr_type are initially false due + * to zeroing the struct + */ + if (tb[PARAM_IPV4_ADDR]) { + nla_memcpy(req.ipv4_addr, tb[PARAM_IPV4_ADDR], + CDF_IPV4_ADDR_SIZE); + req.ipv4_addr_type = true; + } + + if (tb[PARAM_IPV6_ADDR]) { + nla_memcpy(&req.ipv6_addr, tb[PARAM_IPV6_ADDR], + CDF_IPV6_ADDR_SIZE); + req.ipv6_addr_type = true; + } + + if (!req.ipv4_addr_type && !req.ipv6_addr_type) { + hdd_err("invalid ipv4 or ipv6 gateway address"); + return -EINVAL; + } + + req.max_retries = 3; + req.timeout = 100; /* in milliseconds */ + req.session_id = adapter->sessionId; + + hdd_info("**** Gateway Parameters: ****"); + hdd_info("session id: %d", req.session_id); + hdd_info("ipv4 addr type: %d", req.ipv4_addr_type); + hdd_info("ipv6 addr type: %d", req.ipv6_addr_type); + hdd_info("gw mac addr: %pM", req.gw_mac_addr.bytes); + hdd_info("ipv4 addr: %pI4", req.ipv4_addr); + hdd_info("ipv6 addr: %pI6c", req.ipv6_addr); + + status = sme_gateway_param_update(hdd_ctx->hHal, &req); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("sme_gateway_param_update failed(err=%d)", status); + ret = -EINVAL; + } + + EXIT(); + return ret; +} + +/** + * wlan_hdd_cfg80211_set_gateway_params() - set gateway parameters + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * The API is invoked by the user space to set the gateway parameters + * such as mac address and the IP address which is used for detecting + * the IP subnet change + * + * Return: 0 on success; errno on failure + */ +int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + + ret = __wlan_hdd_cfg80211_set_gateway_params( + wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + return ret; +} +#undef PARAM_MAC_ADDR +#undef PARAM_IPV4_ADDR +#undef PARAM_IPV6_ADDR diff --git a/core/hdd/src/wlan_hdd_subnet_detect.h b/core/hdd/src/wlan_hdd_subnet_detect.h new file mode 100644 index 000000000000..ffab910884cb --- /dev/null +++ b/core/hdd/src/wlan_hdd_subnet_detect.h @@ -0,0 +1,44 @@ +/* + * 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 __WLAN_HDD_SUBNET_DETECT_H +#define __WLAN_HDD_SUBNET_DETECT_H + +/** + * DOC: wlan_hdd_subnet_detect.h + * + * WLAN Host Device Driver subnet detect API specification + */ + +#ifdef FEATURE_LFR_SUBNET_DETECTION +struct wiphy; +struct wireless_dev; + +int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len); +#endif /* FEATURE_LFR_SUBNET_DETECTION */ +#endif /* __WLAN_HDD_SUBNET_DETECT_H */ -- cgit v1.2.3 From b0286c02e68bba6f527f6e3820bd1f554972677f Mon Sep 17 00:00:00 2001 From: Ravi Joshi Date: Fri, 13 Nov 2015 11:30:43 -0800 Subject: qcacld-3.0: Add support to indicate subnet change status to user space LFR3 to indicate the change in IP subnet to user space (supplicant). This enables the DHCP refresh in case of IP subnet change during roaming. Change-Id: I9842a28461346fe97ab39f5a11ae504f2e32fa16 CRs-Fixed: 876335 --- core/hdd/src/wlan_hdd_cfg80211.c | 20 +++++++++++++++++++- core/hdd/src/wlan_hdd_cfg80211.h | 2 ++ core/sme/inc/csr_api.h | 1 + core/sme/inc/csr_internal.h | 7 +++++++ core/sme/src/csr/csr_api_roam.c | 3 +++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9f431ae95cd1..13c76610e60c 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3012,7 +3012,7 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, ETH_ALEN + req_rsn_len + rsp_rsn_len + sizeof(uint8_t) + SIR_REPLAY_CTR_LEN + SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN + - (7 * NLMSG_HDRLEN), + sizeof(uint8_t) + (8 * NLMSG_HDRLEN), QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX, GFP_KERNEL); @@ -3057,6 +3057,24 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, } } + hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"), + roam_info_ptr->subnet_change_status); + + /* + * Add subnet change status if subnet has changed + * 0 = unchanged + * 1 = changed + * 2 = unknown + */ + if (roam_info_ptr->subnet_change_status) { + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS, + roam_info_ptr->subnet_change_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + goto nla_put_failure; + } + } + cfg80211_vendor_event(skb, GFP_KERNEL); return 0; diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 34134d3b9ff4..f86e36b96b65 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -1554,6 +1554,7 @@ enum qca_wlan_vendor_attr_set_no_dfs_flag { * @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 + * @QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS: subnet change status */ enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, @@ -1564,6 +1565,7 @@ enum qca_wlan_vendor_attr_roam_auth { 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_SUBNET_STATUS, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1 diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index bf2162d5a098..0ba6b035acf7 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1351,6 +1351,7 @@ typedef struct tagCsrRoamInfo { uint8_t kck[SIR_KCK_KEY_LEN]; uint8_t kek[SIR_KEK_KEY_LEN]; uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; + uint8_t subnet_change_status; #endif tSirSmeChanInfo chan_info; uint8_t target_channel; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 830ff6b67a15..0dc1db38f7a8 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -1202,6 +1202,13 @@ typedef struct tagCsrRoamStruct { (eCsrLostLink2 == (pCommand)->u.roamCmd.roamReason) || \ (eCsrLostLink3 == (pCommand)->u.roamCmd.roamReason)) +#ifdef FEATURE_LFR_SUBNET_DETECTION +/* bit-4 and bit-5 indicate the subnet status */ +#define CSR_GET_SUBNET_STATUS(roam_reason) (((roam_reason) & 0x30) >> 4) +#else +#define CSR_GET_SUBNET_STATUS(roam_reason) (0) +#endif + CDF_STATUS csr_get_channel_and_power_list(tpAniSirGlobal pMac); CDF_STATUS csrScanFilter11dResult(tpAniSirGlobal pMac); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 28062cb770d8..5ac222dabd40 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6440,6 +6440,9 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, FL ("LFR3: Copy KCK, KEK and Replay Ctr")); } + + roam_info.subnet_change_status = + CSR_GET_SUBNET_STATUS(roam_offload_params->roamReason); #endif csr_roam_call_callback(mac_ctx, session_id, &roam_info, cmd->u.roamCmd.roamId, -- cgit v1.2.3 From d768f502fbcb7fb4713eac6641c60ee656aa1830 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Tue, 3 Nov 2015 14:08:09 -0800 Subject: qcacld-3.0: Fix issue in Tx LDPC enable/disable using INI qcacld-2.0 to qcacld-3.0 propagation. FW checks the peer Rx LDPC capability in ht and vht capabilities to do Tx LPDC. But host sets the Tx LPDC flag in peer_flags. To disable Tx LDPC reset the Rx LDPC capability in peer ht and vht caps based on Tx LPDC configuration in INI. Change-Id: I211fd73fd70a35faaf4cfc2c5dc8d842c7ff1e5a CRs-Fixed: 894306 --- core/mac/src/pe/lim/lim_assoc_utils.c | 54 +++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 79f8a1f489a1..b21a708b76fa 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -2484,8 +2484,17 @@ lim_add_sta(tpAniSirGlobal mac_ctx, add_sta_params->htLdpcCapable = 0; add_sta_params->vhtLdpcCapable = 0; } else { - add_sta_params->htLdpcCapable = sta_ds->htLdpcCapable; - add_sta_params->vhtLdpcCapable = sta_ds->vhtLdpcCapable; + if (session_entry->txLdpcIniFeatureEnabled & 0x1) + add_sta_params->htLdpcCapable = + sta_ds->htLdpcCapable; + else + add_sta_params->htLdpcCapable = 0; + + if (session_entry->txLdpcIniFeatureEnabled & 0x2) + add_sta_params->vhtLdpcCapable = + sta_ds->vhtLdpcCapable; + else + add_sta_params->vhtLdpcCapable = 0; } } else if (STA_ENTRY_SELF == sta_ds->staType) { /* For Self STA get the LDPC capability from config.ini */ @@ -2625,6 +2634,12 @@ lim_add_sta(tpAniSirGlobal mac_ctx, add_sta_params->htLdpcCapable, add_sta_params->vhtLdpcCapable, add_sta_params->p2pCapableSta); + if (!add_sta_params->htLdpcCapable) + add_sta_params->ht_caps &= ~(1 << SIR_MAC_HT_CAP_ADVCODING_S); + if (!add_sta_params->vhtLdpcCapable) + add_sta_params->vht_caps &= + ~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP); + /* * we need to defer the message until we get the * response back from HAL. @@ -4134,8 +4149,12 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, pAddBssParams->staContext.htLdpcCapable = 0; pAddBssParams->staContext.vhtLdpcCapable = 0; } else { - pAddBssParams->staContext.htLdpcCapable = - (uint8_t) pAssocRsp->HTCaps.advCodingCap; + if (psessionEntry->txLdpcIniFeatureEnabled & 0x1) + pAddBssParams->staContext.htLdpcCapable = + (uint8_t) pAssocRsp->HTCaps.advCodingCap; + else + pAddBssParams->staContext.htLdpcCapable = 0; + if (pAssocRsp->VHTCaps.present) vht_caps = &pAssocRsp->VHTCaps; else if (pAssocRsp->vendor2_ie.VHTCaps.present) { @@ -4143,9 +4162,12 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, lim_log(pMac, LOG1, FL( "VHT Caps is in vendor Specfic IE")); } - if (vht_caps != NULL) + if (vht_caps != NULL && + (psessionEntry->txLdpcIniFeatureEnabled & 0x2)) pAddBssParams->staContext.vhtLdpcCapable = (uint8_t) vht_caps->ldpcCodingCap; + else + pAddBssParams->staContext.vhtLdpcCapable = 0; } if (pBeaconStruct->HTInfo.present) @@ -4253,6 +4275,13 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, (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); + lim_log(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d " "p2pCapableSta: %d"), pAddBssParams->staContext.wmmEnabled, @@ -4658,9 +4687,13 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update pAddBssParams->staContext.htLdpcCapable = 0; pAddBssParams->staContext.vhtLdpcCapable = 0; } else { - pAddBssParams->staContext.htLdpcCapable = - (uint8_t) pBeaconStruct->HTCaps. - advCodingCap; + if (psessionEntry->txLdpcIniFeatureEnabled & 0x1) + pAddBssParams->staContext.htLdpcCapable = + (uint8_t) pBeaconStruct->HTCaps. + advCodingCap; + else + pAddBssParams->staContext.htLdpcCapable = 0; + if (pBeaconStruct->VHTCaps.present) vht_caps = &pBeaconStruct->VHTCaps; else if (pBeaconStruct->vendor2_ie.VHTCaps.present) { @@ -4669,9 +4702,12 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update lim_log(pMac, LOG1, FL( "VHT Caps are in vendor Specfic IE")); } - if (vht_caps != NULL) + if (vht_caps != NULL && + (psessionEntry->txLdpcIniFeatureEnabled & 0x2)) pAddBssParams->staContext.vhtLdpcCapable = (uint8_t) vht_caps->ldpcCodingCap; + else + pAddBssParams->staContext.vhtLdpcCapable = 0; } if (pBeaconStruct->HTInfo.present) -- cgit v1.2.3 From 7edb88b4c962104675b8764eaae11ace4f9c345e Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Thu, 10 Dec 2015 17:21:29 -0800 Subject: qcacld-3.0: Move module init related implementation together Move module init/exit related implementation together and at the end of the file. Change-Id: I17a02e4fdddc17fc3a725c29e89a52f5bd9d49b9 CRs-fixed: 950170 --- core/hdd/src/wlan_hdd_main.c | 1022 +++++++++++++++++++++--------------------- 1 file changed, 511 insertions(+), 511 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 3edc5ad318c5..866b08e4359c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5555,465 +5555,131 @@ success: return 0; } -/* - * 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 durint driver load for reducing interrupt latency. +/** + * hdd_softap_sta_deauth() - handle deauth req from HDD + * @adapter: Pointer to the HDD + * @enable: bool value + * + * This to take counter measure to handle deauth req from HDD + * + * Return: None */ - -#ifdef CONFIG_CNSS -static inline void hdd_request_pm_qos(int val) +CDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter, + struct tagCsrDelStaParams *pDelStaParams) { - cnss_request_pm_qos(val); -} +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; +#endif + CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; -static inline void hdd_remove_pm_qos(void) -{ - cnss_remove_pm_qos(); -} + ENTER(); + + hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); + + /* Ignore request to deauth bcmc station */ + if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) + return cdf_status; + +#ifdef WLAN_FEATURE_MBSSID + cdf_status = + wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + pDelStaParams); #else -static inline void hdd_request_pm_qos(int val) -{ -} + cdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams); +#endif -static inline void hdd_remove_pm_qos(void) -{ + EXIT(); + return cdf_status; } -#endif /** - * hdd_driver_init() - Core Driver Init Function + * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD + * @adapter: Pointer to the HDD * - * This is the driver entry point - called in different timeline depending - * on whether the driver is statically or dynamically linked + * This to take counter measure to handle deauth req from HDD * - * Return: 0 for success, non zero for failure + * Return: None */ -static int hdd_driver_init(void) +void hdd_softap_sta_disassoc(hdd_adapter_t *adapter, + uint8_t *pDestMacAddress) { - CDF_STATUS status; - v_CONTEXT_t p_cds_context = NULL; - int ret_status = 0; - unsigned long rc; - -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - wlan_logging_sock_init_svc(); +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; #endif ENTER(); - cdf_wake_lock_init(&wlan_wake_lock, "wlan"); - hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); - /* - * The Krait is going to Idle/Stand Alone Power Save - * more aggressively which is resulting in the longer driver load time. - * The Fix is to not allow Krait to enter Idle Power Save during driver - * load. - */ - hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); - cds_ssr_protect_init(); - - pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME, - QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); - - do { - cdf_mc_timer_manager_init(); - cdf_mem_init(); - /* Allocate CDS global context */ - status = cds_alloc_global_context(&p_cds_context); - - if (!CDF_IS_STATUS_SUCCESS(status)) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("Failed to preOpen CDS")); - ret_status = -1; - break; - } - - hdd_trace_init(); + hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); -#ifndef MODULE - /* - * For statically linked driver, call hdd_set_conparam to update - * curr_con_mode - */ - hdd_set_conparam((uint32_t) con_mode); -#endif + /* Ignore request to disassoc bcmc station */ + if (pDestMacAddress[0] & 0x1) + return; -#ifdef QCA_WIFI_3_0_ADRASTEA -#define HDD_WLAN_START_WAIT_TIME (3600 * 1000) +#ifdef WLAN_FEATURE_MBSSID + wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + pDestMacAddress); #else -#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) + wlansap_disassoc_sta(p_cds_context, pDestMacAddress); #endif +} - init_completion(&wlan_start_comp); - ret_status = wlan_hdd_register_driver(); - if (!ret_status) { - rc = wait_for_completion_timeout( - &wlan_start_comp, - msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); - if (!rc) { - hddLog(LOGP, - FL("timed-out waiting for wlan_hdd_register_driver")); - ret_status = -1; - } else - ret_status = 0; - } - - hdd_remove_pm_qos(); - hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); - - if (ret_status) { - hddLog(LOGP, FL("WLAN Driver Initialization failed")); - wlan_hdd_unregister_driver(); - cds_free_global_context(&p_cds_context); - ret_status = -ENODEV; - break; - } else { - pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); - memdump_init(); - return 0; - } +void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter, + bool enable) +{ +#ifndef WLAN_FEATURE_MBSSID + v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; +#endif - } while (0); + ENTER(); - if (0 != ret_status) { - cdf_mc_timer_exit(); - cdf_mem_exit(); - cdf_wake_lock_destroy(&wlan_wake_lock); + hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"), + (WLAN_HDD_GET_CTX(adapter))->pcds_context); -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - wlan_logging_sock_deinit_svc(); +#ifdef WLAN_FEATURE_MBSSID + wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter), + (bool) enable); +#else + wlansap_set_counter_measure(p_cds_context, (bool) enable); #endif - memdump_deinit(); - pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); - } else { - pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); - } - - EXIT(); - - return ret_status; } /** - * hdd_module_init() - Init Function + * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected + * @hdd_ctx: HDD Context * - * This is the driver entry point (invoked when module is loaded using insmod) + * API to find if there is any STA or P2P-Client is connected * - * Return: 0 for success, non zero for failure + * Return: true if connected; false otherwise */ -#ifdef MODULE -static int __init hdd_module_init(void) -{ - return hdd_driver_init(); -} -#else /* #ifdef MODULE */ -static int __init hdd_module_init(void) +CDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx) { - /* Driver initialization is delayed to fwpath_changed_handler */ - return 0; + return sme_is_sta_p2p_client_connected(hdd_ctx->hHal); } -#endif /* #ifdef MODULE */ -/** - * hdd_driver_exit() - Exit function - * - * This is the driver exit point (invoked when module is unloaded using rmmod - * or con_mode was changed by userspace) - * - * Return: None - */ -static void hdd_driver_exit(void) +#ifdef WLAN_FEATURE_LPSS +int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data, + hdd_adapter_t *adapter, + hdd_station_ctx_t *pHddStaCtx, + uint8_t is_on, uint8_t is_connected) { hdd_context_t *hdd_ctx = NULL; - int retry = 0; - - pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, - QWLAN_VERSIONSTR); - - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (!hdd_ctx) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("module exit called before probe")); - } else { - /* Check IPA HW Pipe shutdown */ - hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); -#ifdef QCA_PKT_PROTO_TRACE - cds_pkt_proto_trace_close(); -#endif /* QCA_PKT_PROTO_TRACE */ - while (hdd_ctx->isLogpInProgress || - cds_is_logp_in_progress()) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL( - "SSR in Progress; block rmmod for 1 second!!!" - )); - msleep(1000); + uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN; - if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("SSR never completed, fatal error")); - CDF_BUG(0); - } + if (!data) { + hddLog(LOGE, FL("invalid data pointer")); + return -EINVAL; + } + if (!adapter) { + if (is_on) { + /* no active interface */ + data->lpss_support = 0; + data->is_on = is_on; + return 0; } - - rtnl_lock(); - hdd_ctx->isUnloadInProgress = true; - cds_set_load_unload_in_progress(true); - rtnl_unlock(); - } - - cds_wait_for_work_thread_completion(__func__); - memdump_deinit(); - - wlan_hdd_unregister_driver(); - return; -} - -/** - * hdd_module_exit() - Exit function - * - * This is the driver exit point (invoked when module is unloaded using rmmod) - * - * 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 */ -/** - * kickstart_driver() - driver entry point - * - * This is the driver entry point - * - delayed driver initialization when driver is statically linked - * - invoked when module parameter fwpath is modified from userspace to signal - * initializing the WLAN driver or when con_mode is modified from userspace - * to signal a switch in operating mode - * - * Return: 0 for success, non zero for failure - */ -static int kickstart_driver(void) -{ - int ret_status; - - 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; -} - -/** - * 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(); - return ret; -} - -#if !defined(QCA_WIFI_FTM) -/** - * con_mode_handler() - handls module param con_mode change - * - * Handler function for module param con_mode when it is changed by userspace - * Dynamically linked - do nothing - * Statically linked - exit and init driver, as in rmmod and insmod - * - * 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(); - return ret; -} -#endif -#endif /* #ifdef MODULE */ - -/** - * hdd_get_conparam() - driver exit point - * - * This is the driver exit point (invoked when module is unloaded using rmmod) - * - * Return: tCDF_CON_MODE - */ -tCDF_CON_MODE hdd_get_conparam(void) -{ -#ifdef MODULE - return (tCDF_CON_MODE) con_mode; -#else - return (tCDF_CON_MODE) curr_con_mode; -#endif -} - -void hdd_set_conparam(uint32_t newParam) -{ - con_mode = newParam; -#ifndef MODULE - curr_con_mode = con_mode; -#endif -} - -/** - * hdd_softap_sta_deauth() - handle deauth req from HDD - * @adapter: Pointer to the HDD - * @enable: bool value - * - * This to take counter measure to handle deauth req from HDD - * - * Return: None - */ -CDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter, - struct tagCsrDelStaParams *pDelStaParams) -{ -#ifndef WLAN_FEATURE_MBSSID - v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; -#endif - CDF_STATUS cdf_status = CDF_STATUS_E_FAULT; - - ENTER(); - - hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"), - (WLAN_HDD_GET_CTX(adapter))->pcds_context); - - /* Ignore request to deauth bcmc station */ - if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) - return cdf_status; - -#ifdef WLAN_FEATURE_MBSSID - cdf_status = - wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), - pDelStaParams); -#else - cdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams); -#endif - - EXIT(); - return cdf_status; -} - -/** - * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD - * @adapter: Pointer to the HDD - * - * This to take counter measure to handle deauth req from HDD - * - * Return: None - */ -void hdd_softap_sta_disassoc(hdd_adapter_t *adapter, - uint8_t *pDestMacAddress) -{ -#ifndef WLAN_FEATURE_MBSSID - v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; -#endif - - ENTER(); - - hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"), - (WLAN_HDD_GET_CTX(adapter))->pcds_context); - - /* Ignore request to disassoc bcmc station */ - if (pDestMacAddress[0] & 0x1) - return; - -#ifdef WLAN_FEATURE_MBSSID - wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), - pDestMacAddress); -#else - wlansap_disassoc_sta(p_cds_context, pDestMacAddress); -#endif -} - -void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter, - bool enable) -{ -#ifndef WLAN_FEATURE_MBSSID - v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context; -#endif - - ENTER(); - - hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"), - (WLAN_HDD_GET_CTX(adapter))->pcds_context); - -#ifdef WLAN_FEATURE_MBSSID - wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter), - (bool) enable); -#else - wlansap_set_counter_measure(p_cds_context, (bool) enable); -#endif -} - -/** - * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected - * @hdd_ctx: HDD Context - * - * API to find if there is any STA or P2P-Client is connected - * - * Return: true if connected; false otherwise - */ -CDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx) -{ - return sme_is_sta_p2p_client_connected(hdd_ctx->hHal); -} - -#ifdef WLAN_FEATURE_LPSS -int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data, - hdd_adapter_t *adapter, - hdd_station_ctx_t *pHddStaCtx, - uint8_t is_on, uint8_t is_connected) -{ - hdd_context_t *hdd_ctx = NULL; - uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN; - - if (!data) { - hddLog(LOGE, FL("invalid data pointer")); - return -EINVAL; - } - if (!adapter) { - if (is_on) { - /* no active interface */ - data->lpss_support = 0; - data->is_on = is_on; - return 0; - } - hddLog(LOGE, FL("invalid adapter pointer")); - return -EINVAL; + hddLog(LOGE, FL("invalid adapter pointer")); + return -EINVAL; } hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -6645,141 +6311,475 @@ void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Stop Success")); } else { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("Can't stop ap because its not started")); + hddLog(CDF_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: None + */ +void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) +{ + hdd_ap_ctx_t *hdd_ap_ctx; + hdd_hostapd_state_t *hostapd_state; + CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx; + tsap_Config_t *sap_config; + + if (NULL == ap_adapter) { + hddLog(CDF_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); + sap_config = &ap_adapter->sessionCtx.ap.sapConfig; + + if (0 != wlan_hdd_validate_context(hdd_ctx)) { + hddLog(CDF_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + 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_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); + goto end; + } + + if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb, + &hdd_ap_ctx->sapConfig, + ap_adapter->dev) + != CDF_STATUS_SUCCESS) + goto end; + + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, + FL("Waiting for SAP to start")); + cdf_status = cdf_wait_single_event(&hostapd_state->cdf_event, + BSS_WAIT_TIMEOUT); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hddLog(CDF_TRACE_LEVEL_ERROR, FL("SAP Start failed")); + goto end; + } + hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success")); + set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); + cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, + ap_adapter->sessionId); + hostapd_state->bCommit = true; + +end: + mutex_unlock(&hdd_ctx->sap_lock); + return; +} +#endif + +/** + * hdd_wlan_get_wake_lock_ptr(): get HDD's wake lock pointer + * + * This function returns the wake lock pointer to the caller + * + * Return: cdf_wake_lock_t + */ +cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void) +{ + return &wlan_wake_lock; +} + +/** + * 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; +} + +#ifdef QCA_CONFIG_SMP +/** + * wlan_hdd_get_cpu() - get cpu_index + * + * Return: cpu_index + */ +int wlan_hdd_get_cpu(void) +{ + 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; +} + +/* + * 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 durint driver load for reducing interrupt latency. + */ + +#ifdef CONFIG_CNSS +static inline void hdd_request_pm_qos(int val) +{ + cnss_request_pm_qos(val); +} + +static inline void hdd_remove_pm_qos(void) +{ + cnss_remove_pm_qos(); +} +#else +static inline void hdd_request_pm_qos(int val) +{ +} + +static inline void hdd_remove_pm_qos(void) +{ +} +#endif + +/** + * hdd_driver_init() - Core Driver Init Function + * + * This is the driver entry point - called in different timeline depending + * on whether the driver is statically or dynamically linked + * + * Return: 0 for success, non zero for failure + */ +static int hdd_driver_init(void) +{ + CDF_STATUS status; + v_CONTEXT_t p_cds_context = NULL; + int ret_status = 0; + unsigned long rc; + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_init_svc(); +#endif + + ENTER(); + + cdf_wake_lock_init(&wlan_wake_lock, "wlan"); + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + /* + * The Krait is going to Idle/Stand Alone Power Save + * more aggressively which is resulting in the longer driver load time. + * The Fix is to not allow Krait to enter Idle Power Save during driver + * load. + */ + hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); + cds_ssr_protect_init(); + + pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + + do { + cdf_mc_timer_manager_init(); + cdf_mem_init(); + /* Allocate CDS global context */ + status = cds_alloc_global_context(&p_cds_context); + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("Failed to preOpen CDS")); + ret_status = -1; + break; + } + + hdd_trace_init(); + +#ifndef MODULE + /* + * For statically linked driver, call hdd_set_conparam to update + * curr_con_mode + */ + hdd_set_conparam((uint32_t) con_mode); +#endif + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define HDD_WLAN_START_WAIT_TIME (3600 * 1000) +#else +#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) +#endif + + init_completion(&wlan_start_comp); + ret_status = wlan_hdd_register_driver(); + if (!ret_status) { + rc = wait_for_completion_timeout( + &wlan_start_comp, + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); + if (!rc) { + hddLog(LOGP, + FL("timed-out waiting for wlan_hdd_register_driver")); + ret_status = -1; + } else + ret_status = 0; + } + + hdd_remove_pm_qos(); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + + if (ret_status) { + hddLog(LOGP, FL("WLAN Driver Initialization failed")); + wlan_hdd_unregister_driver(); + cds_free_global_context(&p_cds_context); + ret_status = -ENODEV; + break; + } else { + pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); + memdump_init(); + return 0; + } + + } while (0); + + if (0 != ret_status) { + cdf_mc_timer_exit(); + cdf_mem_exit(); + cdf_wake_lock_destroy(&wlan_wake_lock); + +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif + memdump_deinit(); + pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); + } else { + pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); } - mutex_unlock(&hdd_ctx->sap_lock); - return; + + EXIT(); + + return ret_status; } /** - * wlan_hdd_start_sap() - this function starts bss of SAP. - * @ap_adapter: SAP adapter + * hdd_module_init() - Init Function * - * This function will process the starting of sap adapter. + * This is the driver entry point (invoked when module is loaded using insmod) + * + * 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 */ + +/** + * hdd_driver_exit() - Exit function + * + * This is the driver exit point (invoked when module is unloaded using rmmod + * or con_mode was changed by userspace) * * Return: None */ -void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) +static void hdd_driver_exit(void) { - hdd_ap_ctx_t *hdd_ap_ctx; - hdd_hostapd_state_t *hostapd_state; - CDF_STATUS cdf_status; - hdd_context_t *hdd_ctx; - tsap_Config_t *sap_config; + hdd_context_t *hdd_ctx = NULL; + int retry = 0; - if (NULL == ap_adapter) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("ap_adapter is NULL here")); - return; - } + pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR); - 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); - sap_config = &ap_adapter->sessionCtx.ap.sapConfig; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("module exit called before probe")); + } else { + /* Check IPA HW Pipe shutdown */ + hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); +#ifdef QCA_PKT_PROTO_TRACE + cds_pkt_proto_trace_close(); +#endif /* QCA_PKT_PROTO_TRACE */ + while (hdd_ctx->isLogpInProgress || + cds_is_logp_in_progress()) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL( + "SSR in Progress; block rmmod for 1 second!!!" + )); + msleep(1000); - if (0 != wlan_hdd_validate_context(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("HDD context is not valid")); - return; - } - mutex_lock(&hdd_ctx->sap_lock); - if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) - goto end; + if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { + hddLog(CDF_TRACE_LEVEL_FATAL, + FL("SSR never completed, fatal error")); + CDF_BUG(0); + } + } - if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) { - hddLog(LOGE, FL("SAP Not able to set AP IEs")); - wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); - goto end; + rtnl_lock(); + hdd_ctx->isUnloadInProgress = true; + cds_set_load_unload_in_progress(true); + rtnl_unlock(); } - if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb, - &hdd_ap_ctx->sapConfig, - ap_adapter->dev) - != CDF_STATUS_SUCCESS) - goto end; - - hddLog(CDF_TRACE_LEVEL_INFO_HIGH, - FL("Waiting for SAP to start")); - cdf_status = cdf_wait_single_event(&hostapd_state->cdf_event, - BSS_WAIT_TIMEOUT); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("SAP Start failed")); - goto end; - } - hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success")); - set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, - ap_adapter->sessionId); - hostapd_state->bCommit = true; + cds_wait_for_work_thread_completion(__func__); + memdump_deinit(); -end: - mutex_unlock(&hdd_ctx->sap_lock); + wlan_hdd_unregister_driver(); return; } -#endif /** - * hdd_wlan_get_wake_lock_ptr(): get HDD's wake lock pointer + * hdd_module_exit() - Exit function * - * This function returns the wake lock pointer to the caller + * This is the driver exit point (invoked when module is unloaded using rmmod) * - * Return: cdf_wake_lock_t + * Return: None */ -cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void) +static void __exit hdd_module_exit(void) { - return &wlan_wake_lock; + 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 */ /** - * 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 + * kickstart_driver() - driver entry point * - * This function is called to get the firmware build version stored - * as part of the HDD context + * This is the driver entry point + * - delayed driver initialization when driver is statically linked + * - invoked when module parameter fwpath is modified from userspace to signal + * initializing the WLAN driver or when con_mode is modified from userspace + * to signal a switch in operating mode * - * Return: None + * Return: 0 for success, non zero for failure */ -void hdd_get_fw_version(hdd_context_t *hdd_ctx, - uint32_t *major_spid, uint32_t *minor_spid, - uint32_t *siid, uint32_t *crmid) +static int kickstart_driver(void) { - *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; + int ret_status; + + 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; } -#ifdef QCA_CONFIG_SMP /** - * wlan_hdd_get_cpu() - get cpu_index + * fwpath_changed_handler() - Handler Function * - * Return: cpu_index + * Handle changes to the fwpath parameter + * + * Return: 0 for success, non zero for failure */ -int wlan_hdd_get_cpu(void) +static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) { - int cpu_index = get_cpu(); - put_cpu(); - return cpu_index; + int ret; + + ret = param_set_copystring(kmessage, kp); + if (0 == ret) + ret = kickstart_driver(); + return ret; +} + +#if !defined(QCA_WIFI_FTM) +/** + * con_mode_handler() - handls module param con_mode change + * + * Handler function for module param con_mode when it is changed by userspace + * Dynamically linked - do nothing + * Statically linked - exit and init driver, as in rmmod and insmod + * + * 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(); + return ret; } #endif +#endif /* #ifdef MODULE */ /** - * hdd_get_fwpath() - get framework path + * hdd_get_conparam() - driver exit point * - * This function is used to get the string written by - * userspace to start the wlan driver + * This is the driver exit point (invoked when module is unloaded using rmmod) * - * Return: string + * Return: tCDF_CON_MODE */ -const char *hdd_get_fwpath(void) +tCDF_CON_MODE hdd_get_conparam(void) { - return fwpath.string; +#ifdef MODULE + return (tCDF_CON_MODE) con_mode; +#else + return (tCDF_CON_MODE) curr_con_mode; +#endif +} + +void hdd_set_conparam(uint32_t newParam) +{ + con_mode = newParam; +#ifndef MODULE + curr_con_mode = con_mode; +#endif } -- cgit v1.2.3 From 2de24ecc525bea5f95f50de8ef0bd23f421afaea Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Thu, 10 Dec 2015 17:34:24 -0800 Subject: qcacld-3.0: hdd: Fix conditional compilation for FTM For statically linked driver, con_mode is used for moving from machine mode to FTM mode but it has conditional compilation issues. Fix the conditional compilation to properly compile when FTM feature is enabled. Along with it, unify the usage of con_mode such that curr_con_mode is the variable which holds the connection mode passed as part of module parameter as well as set by the driver. Change-Id: I7d6a5c9b82d1dbb727208caca78089d6be357e71 CRs-fixed: 950170 --- core/hdd/inc/wlan_hdd_main.h | 2 +- core/hdd/src/wlan_hdd_main.c | 49 +++++++++----------------------------------- 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 48a27c97e7ea..5d3ec985c4ea 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1385,7 +1385,7 @@ uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *pHddCtx); void wlan_hdd_release_intf_addr(hdd_context_t *pHddCtx, uint8_t *releaseAddr); uint8_t hdd_get_operating_channel(hdd_context_t *pHddCtx, device_mode_t mode); -void hdd_set_conparam(uint32_t newParam); +void hdd_set_conparam(uint32_t con_param); tCDF_CON_MODE hdd_get_conparam(void); void hdd_abort_mac_scan(hdd_context_t *pHddCtx, uint8_t sessionId, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 866b08e4359c..85565d601690 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -348,17 +348,9 @@ struct notifier_block hdd_netdev_notifier = { /* 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 userspace 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 userspace. So curr_con_mode records the current con_mode - * for exit when con_mode becomes the next mode for init - */ + +/* Variable to hold connection mode including module parameter con_mode */ static int curr_con_mode; -#endif /* wlan_hdd_find_opclass() - Find operating class for a channel * @hal: handler to HAL @@ -6526,13 +6518,7 @@ static int hdd_driver_init(void) hdd_trace_init(); -#ifndef MODULE - /* - * For statically linked driver, call hdd_set_conparam to update - * curr_con_mode - */ hdd_set_conparam((uint32_t) con_mode); -#endif #ifdef QCA_WIFI_3_0_ADRASTEA #define HDD_WLAN_START_WAIT_TIME (3600 * 1000) @@ -6681,13 +6667,6 @@ 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 */ /** * kickstart_driver() - driver entry point @@ -6736,9 +6715,9 @@ static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) return ret; } -#if !defined(QCA_WIFI_FTM) +#ifdef QCA_WIFI_FTM /** - * con_mode_handler() - handls module param con_mode change + * con_mode_handler() - Handles module param con_mode change * * Handler function for module param con_mode when it is changed by userspace * Dynamically linked - do nothing @@ -6755,7 +6734,7 @@ static int con_mode_handler(const char *kmessage, struct kernel_param *kp) ret = kickstart_driver(); return ret; } -#endif +#endif /* QCA_WIFI_FTM */ #endif /* #ifdef MODULE */ /** @@ -6767,22 +6746,14 @@ static int con_mode_handler(const char *kmessage, struct kernel_param *kp) */ tCDF_CON_MODE hdd_get_conparam(void) { -#ifdef MODULE - return (tCDF_CON_MODE) con_mode; -#else return (tCDF_CON_MODE) curr_con_mode; -#endif } -void hdd_set_conparam(uint32_t newParam) +void hdd_set_conparam(uint32_t con_param) { - con_mode = newParam; -#ifndef MODULE - curr_con_mode = con_mode; -#endif + curr_con_mode = con_param; } - /* Register the module init/exit functions */ module_init(hdd_module_init); module_exit(hdd_module_exit); @@ -6791,11 +6762,11 @@ 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 +#if !defined(MODULE) && defined(QCA_WIFI_FTM) module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#else +module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); #endif module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath, -- cgit v1.2.3 From 6b581cb470f5485ca4ba3d18325a591a60d25157 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Mon, 30 Nov 2015 14:28:52 -0800 Subject: qcacld-3.0: Clean-up module init and exit In module init, bunch of initializations are done which are not required till probe call back gets called. Also in module exit, some clean-up done which should wait till remove call back gets called. Move the initialization done in module init to probe call back and clean-up done in module exit to remove call back. Change-Id: Id4a0cb21300de1ceab8ed043638b735f31d516d4 CRs-fixed: 950170 --- core/cds/inc/cds_api.h | 5 +- core/cds/src/cds_api.c | 63 +++----- core/hdd/inc/wlan_hdd_main.h | 4 +- core/hdd/src/wlan_hdd_driver_ops.c | 227 +++++++++++++++++++--------- core/hdd/src/wlan_hdd_main.c | 286 +++++++++++++----------------------- core/utils/epping/src/epping_main.c | 1 + 6 files changed, 294 insertions(+), 292 deletions(-) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index cb30c6eb0e2b..9e7fd5a6721f 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -55,9 +55,8 @@ */ #define CDS_WMA_TIMEOUT (15000) -CDF_STATUS cds_alloc_global_context(v_CONTEXT_t *p_cds_context); - -CDF_STATUS cds_free_global_context(v_CONTEXT_t *p_cds_context); +v_CONTEXT_t cds_init(void); +void cds_deinit(void); CDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context); diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 1fcdf449d19c..179ad463a7de 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -80,70 +80,51 @@ static uint8_t cds_multicast_logging; void cds_sys_probe_thread_cback(void *pUserData); /** - * cds_alloc_global_context() - allocate CDS global context - * @p_cds_context: A pointer to where to store the CDS Context + * cds_init() - Initialize CDS * - * cds_alloc_global_context() function allocates the CDS global Context, - * but does not initialize all the members. This overal initialization will - * happen at cds_open(). + * This function allocates the resource required for CDS, but does not + * initialize all the members. This overall initialization will happen at + * cds_open(). * - * Return: CDF status + * Return: Global context on success and NULL on failure. */ -CDF_STATUS cds_alloc_global_context(v_CONTEXT_t *p_cds_context) +v_CONTEXT_t cds_init(void) { - if (p_cds_context == NULL) - return CDF_STATUS_E_FAILURE; + cdf_mc_timer_manager_init(); + cdf_mem_init(); - /* allocate the CDS Context */ - *p_cds_context = NULL; gp_cds_context = &g_cds_context; - cdf_mem_zero(gp_cds_context, sizeof(cds_context_type)); - *p_cds_context = gp_cds_context; - gp_cds_context->cdf_ctx = &g_cdf_ctx; cdf_mem_zero(&g_cdf_ctx, sizeof(g_cdf_ctx)); - /* initialize the spinlock */ cdf_trace_spin_lock_init(); - /* it is the right time to initialize MTRACE structures */ + #if defined(TRACE_RECORD) cdf_trace_init(); #endif - cdf_dp_trace_init(); - return CDF_STATUS_SUCCESS; -} /* cds_alloc_global_context() */ + + cds_ssr_protect_init(); + + return gp_cds_context; +} /** - * cds_free_global_context() - free CDS global context - * @p_cds_context: A pointer to where the CDS Context was stored - * - * cds_free_global_context() function frees the CDS Context. + * cds_deinit() - Deinitialize CDS * - * Return: CDF status + * This function frees the CDS resources */ -CDF_STATUS cds_free_global_context(v_CONTEXT_t *p_cds_context) +void cds_deinit(void) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, - "%s: De-allocating the CDS Context", __func__); - - if ((p_cds_context == NULL) || (*p_cds_context == NULL)) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: vOS Context is Null", __func__); - return CDF_STATUS_E_FAILURE; - } + if (gp_cds_context == NULL) + return; - if (gp_cds_context != *p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: Context mismatch", __func__); - return CDF_STATUS_E_FAILURE; - } gp_cds_context->cdf_ctx = NULL; - *p_cds_context = gp_cds_context = NULL; + gp_cds_context = NULL; - return CDF_STATUS_SUCCESS; -} /* cds_free_global_context() */ + return; +} #ifdef WLAN_FEATURE_NAN /** diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 5d3ec985c4ea..58b4ad69214c 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1425,6 +1425,9 @@ static inline void hdd_stop_bus_bw_computer_timer(hdd_adapter_t *pAdapter) } #endif +int hdd_init(void); +void hdd_deinit(void); + int hdd_wlan_startup(struct device *dev, void *hif_sc); void __hdd_wlan_exit(void); int hdd_wlan_notify_modem_power_state(int state); @@ -1517,7 +1520,6 @@ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter); 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 -cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void); #ifdef QCA_CONFIG_SMP int wlan_hdd_get_cpu(void); diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 1460850dc538..82c91482dc1f 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -47,6 +47,7 @@ #include "wma_api.h" #include "wlan_hdd_napi.h" #include "cds_concurrency.h" +#include "qwlan_version.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -72,6 +73,112 @@ #define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ icnss_unregister_driver(wlan_drv_ops) #endif /* HIF_PCI */ +#define DISABLE_KRAIT_IDLE_PS_VAL 200 + +/* + * 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 durint driver load for reducing interrupt latency. + */ +#ifdef CONFIG_CNSS +static inline void hdd_request_pm_qos(int val) +{ + cnss_request_pm_qos(val); +} + +static inline void hdd_remove_pm_qos(void) +{ + cnss_remove_pm_qos(); +} +#else +static inline void hdd_request_pm_qos(int val) +{ +} + +static inline void hdd_remove_pm_qos(void) +{ +} +#endif + +/** + * hdd_hif_open() - HIF open helper + * @dev: wlan device structure + * @bdev: bus device structure + * @bid: bus identifier for shared busses + * @bus_type: underlying bus type + * @reinit: true if we are reinitializing the driver during recovery phase + * + * This function brings-up HIF layer during load/recovery phase. + * + * Return: 0 on success and errno on failure. + */ +static int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, + enum ath_hal_bus_type bus_type, bool reinit) +{ + CDF_STATUS status; + int ret = 0; + void *hif_ctx; + + status = hif_open(); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("hif_open error = %d", status); + return cdf_status_to_os_return(status); + } + + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + + ret = hdd_napi_create(); + if (hdd_napi_enabled(HDD_NAPI_ANY)) { + hdd_info("hdd_napi_create returned: %d", status); + if (ret <= 0) { + hdd_err("NAPI creation error, rc: 0x%x, reinit = %d", + status, reinit); + ret = -EFAULT; + goto err_hif_close; + } + } + + status = hif_enable(hif_ctx, dev, bdev, bid, bus_type, + (reinit == true) ? HIF_ENABLE_TYPE_REINIT : + HIF_ENABLE_TYPE_PROBE); + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("hif_enable error = %d, reinit = %d", + status, reinit); + ret = cdf_status_to_os_return(status); + goto err_napi_destroy; + } + + return 0; + +err_napi_destroy: + hdd_napi_destroy(true); + +err_hif_close: + hif_close(hif_ctx); + + return ret; + +} + +/** + * hdd_hif_close() - HIF close helper + * @hif_ctx: HIF context + * + * Helper function to close HIF + */ +static void hdd_hif_close(void *hif_ctx) +{ + if (hif_ctx == NULL) + return; + + hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); + + hdd_napi_destroy(true); + + hif_close(hif_ctx); +} /** * wlan_hdd_probe() - handles probe request @@ -91,69 +198,68 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, { void *hif_ctx; CDF_STATUS status; - int ret; + int ret = 0; + + pr_info("%s: %sprobing driver v%s\n", WLAN_MODULE_NAME, + reinit ? "re-" : "", QWLAN_VERSIONSTR); + + hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + + /* + * The Krait is going to Idle/Stand Alone Power Save + * more aggressively which is resulting in the longer driver load time. + * The Fix is to not allow Krait to enter Idle Power Save during driver + * load. + */ + hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); + + if (!reinit) { + ret = hdd_init(); + + if (ret) + goto out; + } if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { status = epping_open(); if (status != CDF_STATUS_SUCCESS) - return status; + goto err_hdd_deinit; } - status = hif_open(); - if (status != CDF_STATUS_SUCCESS) { - hddLog(LOGE, FL("hif_open error = %d"), status); - return -EFAULT; - } - hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); - if (reinit) - hdd_napi_destroy(true); - status = hdd_napi_create(); - if (hdd_napi_enabled(HDD_NAPI_ANY)) { - hdd_info("hdd_napi_create returned: %d\n", status); - if (status <= 0) { - hdd_err("NAPI creation error, rc: 0x%x, reinit = %d", - status, reinit); - ret = -EFAULT; - goto end; - } - } + ret = hdd_hif_open(dev, bdev, bid, bus_type, reinit); - status = hif_enable(hif_ctx, dev, bdev, bid, - bus_type, (reinit == true) ? - HIF_ENABLE_TYPE_REINIT : HIF_ENABLE_TYPE_PROBE); - if (status != CDF_STATUS_SUCCESS) { - hdd_err("hif_enable error = %d, reinit = %d", - status, reinit); - ret = -EIO; - goto end; - } + if (ret) + goto err_epping_close; + + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); if (reinit) ret = hdd_wlan_re_init(hif_ctx); else ret = hdd_wlan_startup(dev, hif_ctx); -end: - if (ret) { - if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { - hif_pktlogmod_exit(hif_ctx); - epping_disable(); - htc_destroy(cds_get_context(CDF_MODULE_ID_HTC)); - hif_disable(hif_ctx, (reinit == true) ? - HIF_ENABLE_TYPE_REINIT : HIF_ENABLE_TYPE_PROBE); - cds_free_context(NULL, CDF_MODULE_ID_HTC, NULL); - epping_close(); - } else { - hif_pktlogmod_exit(hif_ctx); - __hdd_wlan_exit(); - hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); - } - hif_close(hif_ctx); - } + if (ret) + goto err_hif_close; + if (reinit) cds_set_logp_in_progress(false); + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + hdd_remove_pm_qos(); + + return 0; + +err_hif_close: + hdd_hif_close(hif_ctx); +err_epping_close: + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + epping_close(); +err_hdd_deinit: + hdd_deinit(); +out: + hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + hdd_remove_pm_qos(); return ret; } @@ -168,38 +274,26 @@ end: static void wlan_hdd_remove(void) { void *hif_ctx; - v_CONTEXT_t p_cds_context = NULL; - /* Get the global cds context */ - p_cds_context = cds_get_global_context(); + pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR); hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + hif_pktlogmod_exit(hif_ctx); + if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { - hif_pktlogmod_exit(hif_ctx); epping_disable(); - htc_destroy(cds_get_context(CDF_MODULE_ID_HTC)); - hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); - cds_free_context(NULL, CDF_MODULE_ID_HTC, NULL); epping_close(); } else { - hif_pktlogmod_exit(hif_ctx); __hdd_wlan_exit(); - hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE); } - hdd_napi_destroy(true); - hif_close(hif_ctx); - - cds_free_global_context(&p_cds_context); + hdd_hif_close(hif_ctx); -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - wlan_logging_sock_deinit_svc(); -#endif - - cdf_wake_lock_destroy(hdd_wlan_get_wake_lock_ptr()); + hdd_deinit(); - pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME); + pr_info("%s: Driver Removed\n", WLAN_MODULE_NAME); } /** @@ -235,8 +329,7 @@ static void wlan_hdd_shutdown(void) hdd_wlan_shutdown(); } - hif_disable(hif_ctx, HIF_DISABLE_TYPE_SHUTDOWN); - hif_close(hif_ctx); + hdd_hif_close(hif_ctx); } /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 85565d601690..6ee550e36e1c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -123,7 +123,6 @@ extern int hdd_hostapd_stop(struct net_device *dev); #define MEMORY_DEBUG_STR "" #endif -#define DISABLE_KRAIT_IDLE_PS_VAL 1 /* the Android framework expects this param even though we don't use it */ #define BUF_LEN 20 static char fwpath_buffer[BUF_LEN]; @@ -3610,10 +3609,18 @@ void __hdd_wlan_exit(void) cds_set_load_unload_in_progress(true); + /* Check IPA HW Pipe shutdown */ + hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); + #ifdef WLAN_FEATURE_LPSS wlan_hdd_send_status_pkg(NULL, NULL, 0, 0); #endif + memdump_deinit(); + +#ifdef QCA_PKT_PROTO_TRACE + cds_pkt_proto_trace_close(); +#endif /* Do all the cleanup before deregistering the driver */ hdd_wlan_exit(hdd_ctx); EXIT(); @@ -5449,9 +5456,13 @@ ftm_processing: } hif_enable_power_gating(hif_sc); + + memdump_init(); + hdd_ctx->isLoadInProgress = false; cds_set_load_unload_in_progress(false); complete(&wlan_start_comp); + goto success; err_nl_srv: @@ -6378,18 +6389,6 @@ end: } #endif -/** - * hdd_wlan_get_wake_lock_ptr(): get HDD's wake lock pointer - * - * This function returns the wake lock pointer to the caller - * - * Return: cdf_wake_lock_t - */ -cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void) -{ - return &wlan_wake_lock; -} - /** * hdd_get_fw_version() - Get FW version * @hdd_ctx: pointer to HDD context. @@ -6440,85 +6439,52 @@ const char *hdd_get_fwpath(void) return fwpath.string; } -/* - * 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 durint driver load for reducing interrupt latency. - */ - -#ifdef CONFIG_CNSS -static inline void hdd_request_pm_qos(int val) -{ - cnss_request_pm_qos(val); -} - -static inline void hdd_remove_pm_qos(void) -{ - cnss_remove_pm_qos(); -} -#else -static inline void hdd_request_pm_qos(int val) -{ -} - -static inline void hdd_remove_pm_qos(void) -{ -} -#endif - /** - * hdd_driver_init() - Core Driver Init Function + * hdd_init() - Initialize Driver * - * This is the driver entry point - called in different timeline depending - * on whether the driver is statically or dynamically linked + * This function initilizes CDS global context with the help of cds_init. This + * has to be the first function called after probe to get a valid global + * context. * - * Return: 0 for success, non zero for failure + * Return: 0 for success, errno on failure */ -static int hdd_driver_init(void) +int hdd_init(void) { - CDF_STATUS status; v_CONTEXT_t p_cds_context = NULL; - int ret_status = 0; - unsigned long rc; + int ret = 0; #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE wlan_logging_sock_init_svc(); #endif + p_cds_context = cds_init(); - ENTER(); - - cdf_wake_lock_init(&wlan_wake_lock, "wlan"); - hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); - /* - * The Krait is going to Idle/Stand Alone Power Save - * more aggressively which is resulting in the longer driver load time. - * The Fix is to not allow Krait to enter Idle Power Save during driver - * load. - */ - hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); - cds_ssr_protect_init(); - - pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME, - QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + if (p_cds_context == NULL) { + hdd_alert("Failed to allocate CDS context"); + ret = -ENOMEM; + goto err_out; + } - do { - cdf_mc_timer_manager_init(); - cdf_mem_init(); - /* Allocate CDS global context */ - status = cds_alloc_global_context(&p_cds_context); + hdd_trace_init(); - if (!CDF_IS_STATUS_SUCCESS(status)) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("Failed to preOpen CDS")); - ret_status = -1; - break; - } +err_out: + return ret; +} - hdd_trace_init(); +/** + * hdd_deinit() - Deinitialize Driver + * + * This function frees CDS global context with the help of cds_deinit. This + * has to be the last function call in remove callback to free the global + * context. + */ +void hdd_deinit(void) +{ + cds_deinit(); - hdd_set_conparam((uint32_t) con_mode); +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + wlan_logging_sock_deinit_svc(); +#endif +} #ifdef QCA_WIFI_3_0_ADRASTEA #define HDD_WLAN_START_WAIT_TIME (3600 * 1000) @@ -6526,54 +6492,64 @@ static int hdd_driver_init(void) #define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) #endif - init_completion(&wlan_start_comp); - ret_status = wlan_hdd_register_driver(); - if (!ret_status) { - rc = wait_for_completion_timeout( - &wlan_start_comp, - msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); - if (!rc) { - hddLog(LOGP, - FL("timed-out waiting for wlan_hdd_register_driver")); - ret_status = -1; - } else - ret_status = 0; - } +/** + * __hdd_module_init - Module init helper + * + * Module init helper function used by both module and static driver. + * + * Return: 0 for success, errno on failure + */ +static int __hdd_module_init(void) +{ + int ret = 0; + unsigned long rc; - hdd_remove_pm_qos(); - hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); + pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); - if (ret_status) { - hddLog(LOGP, FL("WLAN Driver Initialization failed")); - wlan_hdd_unregister_driver(); - cds_free_global_context(&p_cds_context); - ret_status = -ENODEV; - break; - } else { - pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); - memdump_init(); - return 0; - } + cdf_wake_lock_init(&wlan_wake_lock, "wlan"); - } while (0); + hdd_set_conparam((uint32_t) con_mode); - if (0 != ret_status) { - cdf_mc_timer_exit(); - cdf_mem_exit(); - cdf_wake_lock_destroy(&wlan_wake_lock); + init_completion(&wlan_start_comp); -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - wlan_logging_sock_deinit_svc(); -#endif - memdump_deinit(); + ret = wlan_hdd_register_driver(); + if (ret) { pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); - } else { - pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); + goto out; } - EXIT(); + rc = wait_for_completion_timeout(&wlan_start_comp, + msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); + + if (!rc) { + hdd_alert("Timed-out waiting for wlan_hdd_register_driver"); + goto out; + } + + pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); + + return 0; +out: + cdf_wake_lock_destroy(&wlan_wake_lock); + return ret; +} - return ret_status; +/** + * __hdd_module_exit - Module exit helper + * + * Module exit helper function used by both module and static driver. + */ +static void __hdd_module_exit(void) +{ + pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME, + QWLAN_VERSIONSTR); + + wlan_hdd_unregister_driver(); + + cdf_wake_lock_destroy(&wlan_wake_lock); + + return; } /** @@ -6586,7 +6562,7 @@ static int hdd_driver_init(void) #ifdef MODULE static int __init hdd_module_init(void) { - return hdd_driver_init(); + return __hdd_module_init(); } #else /* #ifdef MODULE */ static int __init hdd_module_init(void) @@ -6596,60 +6572,6 @@ static int __init hdd_module_init(void) } #endif /* #ifdef MODULE */ -/** - * hdd_driver_exit() - Exit function - * - * This is the driver exit point (invoked when module is unloaded using rmmod - * or con_mode was changed by userspace) - * - * Return: None - */ -static void hdd_driver_exit(void) -{ - hdd_context_t *hdd_ctx = NULL; - int retry = 0; - - pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, - QWLAN_VERSIONSTR); - - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (!hdd_ctx) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("module exit called before probe")); - } else { - /* Check IPA HW Pipe shutdown */ - hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); -#ifdef QCA_PKT_PROTO_TRACE - cds_pkt_proto_trace_close(); -#endif /* QCA_PKT_PROTO_TRACE */ - while (hdd_ctx->isLogpInProgress || - cds_is_logp_in_progress()) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL( - "SSR in Progress; block rmmod for 1 second!!!" - )); - msleep(1000); - - if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("SSR never completed, fatal error")); - CDF_BUG(0); - } - } - - rtnl_lock(); - hdd_ctx->isUnloadInProgress = true; - cds_set_load_unload_in_progress(true); - rtnl_unlock(); - } - - cds_wait_for_work_thread_completion(__func__); - memdump_deinit(); - - wlan_hdd_unregister_driver(); - return; -} - /** * hdd_module_exit() - Exit function * @@ -6659,7 +6581,7 @@ static void hdd_driver_exit(void) */ static void __exit hdd_module_exit(void) { - hdd_driver_exit(); + __hdd_module_exit(); } #ifdef MODULE @@ -6668,6 +6590,7 @@ static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) return param_set_copystring(kmessage, kp); } #else /* #ifdef MODULE */ + /** * kickstart_driver() - driver entry point * @@ -6681,21 +6604,24 @@ static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) */ static int kickstart_driver(void) { - int ret_status; + int ret = 0; if (!wlan_hdd_inited) { - ret_status = hdd_driver_init(); - wlan_hdd_inited = ret_status ? 0 : 1; - return ret_status; + ret = __hdd_module_init(); + wlan_hdd_inited = ret ? 0 : 1; + + return ret; } - hdd_driver_exit(); + __hdd_module_exit(); msleep(200); - ret_status = hdd_driver_init(); - wlan_hdd_inited = ret_status ? 0 : 1; - return ret_status; + ret = __hdd_module_init(); + + wlan_hdd_inited = ret ? 0 : 1; + + return ret; } /** diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c index c222c557d938..a625c0b109b5 100644 --- a/core/utils/epping/src/epping_main.c +++ b/core/utils/epping/src/epping_main.c @@ -128,6 +128,7 @@ void epping_disable(void) hif_reset_soc(cds_get_context(CDF_MODULE_ID_HIF)); htc_stop(cds_get_context(CDF_MODULE_ID_HTC)); epping_cookie_cleanup(pEpping_ctx); + htc_destroy(cds_get_context(CDF_MODULE_ID_HTC)); } /** -- cgit v1.2.3 From 699ae7795815385575694aaf627781b5c96e581a Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Tue, 15 Dec 2015 13:27:26 -0800 Subject: qcacld-3.0: Do not wait for probe in module_init Module_init waits for probe to complete after registering the driver. But this is unnecessary and module load is intended for loading the module but probe would be called when hardware is ready. Remove the wait during module_init. Change-Id: Ic2fe7efa78a1527acf1fd5b7689d70f6d450ccd3 CRs-fixed: 950170 --- core/hdd/src/wlan_hdd_main.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6ee550e36e1c..64f6a934669f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -174,7 +174,6 @@ static const struct wiphy_wowlan_support wowlan_support_reg_init = { struct sock *cesium_nl_srv_sock; -struct completion wlan_start_comp; #ifdef FEATURE_WLAN_AUTO_SHUTDOWN void wlan_hdd_auto_shutdown_cb(void); #endif @@ -5079,7 +5078,6 @@ ftm_processing: cds_set_load_unload_in_progress(false); hdd_ctx->isLoadInProgress = false; hddLog(LOGE, FL("FTM driver loaded")); - complete(&wlan_start_comp); return CDF_STATUS_SUCCESS; } #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) @@ -5461,7 +5459,6 @@ ftm_processing: hdd_ctx->isLoadInProgress = false; cds_set_load_unload_in_progress(false); - complete(&wlan_start_comp); goto success; @@ -6502,7 +6499,6 @@ void hdd_deinit(void) static int __hdd_module_init(void) { int ret = 0; - unsigned long rc; pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); @@ -6511,22 +6507,12 @@ static int __hdd_module_init(void) hdd_set_conparam((uint32_t) con_mode); - init_completion(&wlan_start_comp); - ret = wlan_hdd_register_driver(); if (ret) { pr_err("%s: driver load failure\n", WLAN_MODULE_NAME); goto out; } - rc = wait_for_completion_timeout(&wlan_start_comp, - msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME)); - - if (!rc) { - hdd_alert("Timed-out waiting for wlan_hdd_register_driver"); - goto out; - } - pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); return 0; -- cgit v1.2.3 From 1c3971a9b45a57dbeb21a3a326c1c81bb7367ad6 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Fri, 11 Dec 2015 15:36:14 -0800 Subject: qcacld-3.0: hdd: Remove unused SSR code Remove unused SSR code which were used for legacy chipsets. Change-Id: I3ae3f330a573383890d6e13dd626813f32fc0d51 CRs-fixed: 951587 --- core/hdd/inc/wlan_hdd_main.h | 8 -------- core/hdd/src/wlan_hdd_main.c | 43 ------------------------------------------- 2 files changed, 51 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 58b4ad69214c..6fefaaf4928f 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -623,12 +623,6 @@ typedef struct hdd_cfg80211_state_s { 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; @@ -1397,8 +1391,6 @@ 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(uint32_t timeout, uint32_t reason); -bool hdd_is_ssr_required(void); -void hdd_set_ssr_required(e_hdd_ssr_required value); void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy); CDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *pAdapter); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 64f6a934669f..eab8bdb240ba 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -146,8 +146,6 @@ static int wlan_hdd_inited; DEFINE_SPINLOCK(hdd_context_lock); static cdf_wake_lock_t wlan_wake_lock; -/* set when SSR is needed after unload */ -static e_hdd_ssr_required is_ssr_required = HDD_SSR_NOT_REQUIRED; #define WOW_MAX_FILTER_LISTS 1 #define WOW_MAX_FILTERS_PER_LIST 4 @@ -3051,20 +3049,6 @@ CDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) return CDF_STATUS_SUCCESS; } -bool hdd_is_ssr_required(void) -{ - return is_ssr_required == 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 == is_ssr_required) - return; - - is_ssr_required = value; -} - CDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx, hdd_adapter_list_node_t **padapterNode) { @@ -3569,19 +3553,6 @@ free_hdd_ctx: 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(false); } void __hdd_wlan_exit(void) @@ -5534,20 +5505,6 @@ err_free_hdd_context: /* kfree(wdev) ; */ CDF_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(false); - return -EIO; success: -- cgit v1.2.3 From f462a55a94901261d55cb5611d0b8a295aaf1232 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Tue, 8 Dec 2015 10:22:42 -0800 Subject: qcacld-3.0: send CLIENT_CONNECT message to IPA after enable WDI pipes qcacld-2.0 to qcacld-3.0 propagation Since CLIENT_CONNECT message is sent to IPA before enabling WDI pipes, CLIENT_CONNECT message count could be more than CLIENT_DISCONNECT count, and this could cause an abnormal behavior in the IPACM. Change-Id: I03d30c7f82aadf83979084b7e65b8ed14565588d CRs-fixed: 941894 --- core/hdd/src/wlan_hdd_ipa.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index ba20b1f4d07b..cfdffe8889d5 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -3795,6 +3795,24 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, cdf_mutex_release(&hdd_ipa->event_lock); return 0; } + + /* Enable IPA UC Data PIPEs when first STA connected */ + if ((0 == hdd_ipa->sap_num_connected_sta) && + (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) || + !hdd_ipa->sta_connected)) { + ret = hdd_ipa_uc_handle_first_con(hdd_ipa); + if (ret) { + cdf_mutex_release(&hdd_ipa->event_lock); + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: handle 1st con ret %d", + adapter->dev->name, ret); + return ret; + } + } + + hdd_ipa->sap_num_connected_sta++; + hdd_ipa->pending_cons_req = false; + cdf_mutex_release(&hdd_ipa->event_lock); meta.msg_type = type; @@ -3830,27 +3848,6 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, return ret; } hdd_ipa->stats.num_send_msg++; - - cdf_mutex_acquire(&hdd_ipa->event_lock); - /* Enable IPA UC Data PIPEs when first STA connected */ - if ((0 == hdd_ipa->sap_num_connected_sta) - && (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) - || !hdd_ipa->sta_connected)) { - ret = hdd_ipa_uc_handle_first_con(hdd_ipa); - if (ret) { - cdf_mutex_release(&hdd_ipa->event_lock); - HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, - "%s: handle 1st con ret %d", - adapter->dev->name, ret); - return ret; - } - } - - hdd_ipa->sap_num_connected_sta++; - hdd_ipa->pending_cons_req = false; - - cdf_mutex_release(&hdd_ipa->event_lock); - return ret; case WLAN_CLIENT_DISCONNECT: -- cgit v1.2.3 From c89c19130940e083d9539da378db7f0efa3299c8 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Wed, 2 Dec 2015 14:50:13 -0800 Subject: qcacld-3.0: Send IPA CONS RM grant notification when loading is completed qcacld-2.0 to qcacld-3.0 propagation When IPA requests WLAN CONS resource while IPA resource loading is in progress, resource will not be granted even after the loading is completed. This will eventually result IPA uC timeout. Change-Id: Iae8373c43709cbbccef790973642f5992ddcd359 CRs-Fixed: 943635 --- core/hdd/src/wlan_hdd_ipa.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index cfdffe8889d5..2f4e006b0701 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1377,6 +1377,10 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) { hdd_ipa->resource_loading = false; 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); } cdf_mutex_release(&hdd_ipa->ipa_lock); } -- cgit v1.2.3 From c9b52a5e7de7c11e9db048ffd20cc4abbaabab47 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Wed, 2 Dec 2015 15:05:01 -0800 Subject: qcacld-3.0: Fix incorrect completion of pending IPA RM CONS request qcacld-2.0 to qcacld-3.0 propagation Fix incorrect completion of pending CONS RM request/release notification, which is sent when receiving PROD RM notification from IPA. Also cleanup pending CONS request flag when IPA resource loading/unloading is compelted. Change-Id: Ie37b7d21e1ad016dbaf9aa0f89c97402911b4a02 CRs-Fixed: 943635 --- core/hdd/src/wlan_hdd_ipa.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 2f4e006b0701..42883c18264f 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1237,21 +1237,11 @@ hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event) hdd_ipa_uc_enable_pipes(hdd_ipa); } cdf_mutex_release(&hdd_ipa->ipa_lock); - if (hdd_ipa->pending_cons_req) { - ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED, - IPA_RM_RESOURCE_WLAN_CONS); - } - hdd_ipa->pending_cons_req = false; break; case IPA_RM_RESOURCE_RELEASED: /* Differed RM Released */ hdd_ipa->resource_unloading = false; - if (hdd_ipa->pending_cons_req) { - ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED, - IPA_RM_RESOURCE_WLAN_CONS); - } - hdd_ipa->pending_cons_req = false; break; default: @@ -1381,6 +1371,7 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) ipa_rm_notify_completion( IPA_RM_RESOURCE_GRANTED, IPA_RM_RESOURCE_WLAN_CONS); + hdd_ipa->pending_cons_req = false; } cdf_mutex_release(&hdd_ipa->ipa_lock); } @@ -1391,16 +1382,14 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) 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->hdd_ctx)) && - (!ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD))) { - /* Sync return success from IPA - * Enable/resume all the PIPEs */ - hdd_ipa->resource_unloading = false; - hdd_ipa_uc_proc_pending_event(hdd_ipa); - } else { - hdd_ipa->resource_unloading = false; - hdd_ipa_uc_proc_pending_event(hdd_ipa); - } + if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) + ipa_rm_release_resource( + IPA_RM_RESOURCE_WLAN_PROD); + /* Sync return success from IPA + * Enable/resume all the PIPEs */ + hdd_ipa->resource_unloading = false; + hdd_ipa_uc_proc_pending_event(hdd_ipa); + hdd_ipa->pending_cons_req = false; } cdf_mutex_release(&hdd_ipa->ipa_lock); } -- cgit v1.2.3 From 901e33ffc8f42d82831009e31adb09b1b3025948 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Thu, 8 Oct 2015 11:55:32 -0700 Subject: qcacld-3.0: Remove the obsolete LINUX VERSION checks We already know kernel version is more than equal to 3.10. So remove static checks for any previous kernel. Change-Id: I4e17614fae47782a02dd528c7b4adf3d2802ec69 CRs-Fixed: 920681 --- core/cds/src/cds_sched.c | 4 - core/hdd/inc/wlan_hdd_p2p.h | 51 +--- core/hdd/inc/wlan_hdd_power.h | 4 - core/hdd/inc/wlan_hdd_tdls.h | 9 - core/hdd/src/wlan_hdd_assoc.c | 8 +- core/hdd/src/wlan_hdd_cfg80211.c | 70 +----- core/hdd/src/wlan_hdd_cfg80211.h | 8 - core/hdd/src/wlan_hdd_hostapd.c | 317 +------------------------ core/hdd/src/wlan_hdd_hostapd.h | 16 -- core/hdd/src/wlan_hdd_ioctl.c | 8 +- core/hdd/src/wlan_hdd_main.c | 6 - core/hdd/src/wlan_hdd_memdump.c | 10 - core/hdd/src/wlan_hdd_p2p.c | 243 +------------------ core/hdd/src/wlan_hdd_power.c | 12 - core/hdd/src/wlan_hdd_scan.c | 18 -- core/hdd/src/wlan_hdd_scan.h | 3 - core/hdd/src/wlan_hdd_tdls.c | 25 -- core/hif/src/ath_procfs.c | 5 - core/hif/src/pcie/if_pci.c | 4 +- core/utils/logging/src/wlan_logging_sock_svc.c | 4 - core/utils/nlink/src/wlan_nlink_srv.c | 19 -- core/utils/pktlog/linux_ac.c | 148 +----------- 22 files changed, 17 insertions(+), 975 deletions(-) diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 82dfbbc64ce2..ada5e8858729 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -342,10 +342,6 @@ static int cds_mc_thread(void *Arg) } 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 */ diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index baf2e4bcbbfb..ce1670bfd1c4 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -92,31 +92,16 @@ typedef struct p2p_app_setP2pPs { } p2p_app_setP2pPs_t; int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif struct ieee80211_channel *chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - 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)) 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)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif u64 cookie); int hdd_set_p2p_ps(struct net_device *dev, void *msgData); @@ -136,54 +121,22 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 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)) +#else 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)) - 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)) 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)) 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); diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index d32a2345f37c..df3a0d0ba3e8 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -155,14 +155,10 @@ void hdd_ipv6_notifier_work_queue(struct work_struct *work); #endif int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) struct wireless_dev *wdev, -#endif int *dbm); int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) struct wireless_dev *wdev, -#endif enum nl80211_tx_power_setting type, int dbm); int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 6c0e41d09272..6fb191c84c20 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -101,9 +101,6 @@ typedef struct { */ typedef struct { struct wiphy *wiphy; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - struct net_device *dev; -#endif struct cfg80211_scan_request *scan_request; int magic; int attempt; @@ -486,15 +483,9 @@ hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - 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)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request); void wlan_hdd_tdls_scan_done_callback(hdd_adapter_t *pAdapter); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 0c87577ea7fd..a4afd07c8be6 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2073,9 +2073,7 @@ defined(FEATURE_WLAN_LFR) } if (!hddDisconInProgress) { cfg80211_put_bss( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) pHddCtx->wiphy, -#endif bss); /* @@ -2426,9 +2424,7 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, GFP_KERNEL); #endif cfg80211_put_bss( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) pHddCtx->wiphy, -#endif bss); } @@ -2589,9 +2585,7 @@ static CDF_STATUS roam_ibss_connect_handler(hdd_adapter_t *pAdapter, return CDF_STATUS_E_FAILURE; } cfg80211_put_bss( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) WLAN_HDD_GET_CTX(pAdapter)->wiphy, -#endif bss); return CDF_STATUS_SUCCESS; @@ -4086,7 +4080,7 @@ defined(FEATURE_WLAN_LFR)) hdd_send_ft_event(pAdapter); break; #endif -#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#ifdef FEATURE_WLAN_LFR case eCSR_ROAM_PMK_NOTIFY: if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType || eCSR_AUTH_TYPE_RSN_8021X_SHA256 == diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 13c76610e60c..22646780c844 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -363,7 +363,6 @@ static const struct ieee80211_txrx_stypes }, }; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) /* Interface limits and combinations registered by the driver */ /* STA ( + STA ) combination */ @@ -577,7 +576,6 @@ static struct ieee80211_iface_combination .beacon_int_infra_match = true, }, }; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */ static struct cfg80211_ops wlan_hdd_cfg80211_ops; @@ -1107,9 +1105,7 @@ static int __is_driver_dfs_capable(struct wiphy *wiphy, return -EPERM; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0)) dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD); -#endif temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) + NLMSG_HDRLEN); @@ -5130,15 +5126,14 @@ int wlan_hdd_cfg80211_init(struct device *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)) wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; + wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; #else wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; + wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE; #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL @@ -5147,13 +5142,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, #endif | WIPHY_FLAG_OFFCHAN_TX; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) - 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)) wiphy->wowlan = &wowlan_support_cfg80211_init; #else @@ -5221,7 +5209,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, | BIT(NL80211_IFTYPE_AP); if (pCfg->advertiseConcurrentOperation) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) if (pCfg->enableMCC) { int i; for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination); @@ -5234,7 +5221,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, 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 capabilitied based @@ -5309,11 +5295,9 @@ int wlan_hdd_cfg80211_init(struct device *dev, ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events); } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0)) if (pCfg->enableDFSMasterCap) { wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD; } -#endif wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers; @@ -7371,9 +7355,7 @@ int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, hdd_info("NULL returned by cfg80211_inform_bss_frame"); } else { cfg80211_put_bss( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) wiphy, -#endif bss_status); } } else { @@ -7400,7 +7382,7 @@ int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, return 0; } -#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#ifdef FEATURE_WLAN_LFR /** * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate * @pAdapter: Pointer to adapter @@ -9160,11 +9142,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, return status; if (NULL != -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) params->chandef.chan) -#else - params->channel) -#endif { uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; @@ -9173,16 +9151,10 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, /* Get channel number */ channelNum = ieee80211_frequency_to_channel( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) params-> chandef. chan-> center_freq); -#else - params-> - channel-> - center_freq); -#endif if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST, validChan, &numChans)) { @@ -9604,7 +9576,6 @@ static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy, return ret; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) /** * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params * @wiphy: Pointer to wiphy @@ -9620,21 +9591,6 @@ static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, ENTER(); return 0; } -#else -/** - * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params - * @wiphy: Pointer to wiphy - * @params: Pointer to tx queue parameters - * - * Return: 0 - */ -static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, - struct ieee80211_txq_params *params) -{ - ENTER(); - return 0; -} -#endif /* LINUX_VERSION_CODE */ /** * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params @@ -9644,7 +9600,6 @@ static int __wlan_hdd_set_txq_params(struct wiphy *wiphy, * * 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) @@ -9657,19 +9612,6 @@ static int wlan_hdd_set_txq_params(struct wiphy *wiphy, return ret; } -#else -static int wlan_hdd_set_txq_params(struct wiphy *wiphy, - struct ieee80211_txq_params *params) -{ - int ret; - - cds_ssr_protect(__func__); - ret = __wlan_hdd_set_txq_params(wiphy, params); - cds_ssr_unprotect(__func__); - - return ret; -} -#endif /* LINUX_VERSION_CODE */ /** * __wlan_hdd_cfg80211_del_station() - delete station v2 @@ -11114,15 +11056,9 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .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)) - .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, diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index f86e36b96b65..06718f634fdc 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2250,9 +2250,6 @@ void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index, 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)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request); int wlan_hdd_cfg80211_init(struct device *dev, @@ -2265,13 +2262,8 @@ 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)) void hdd_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); -#else -int hdd_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request); -#endif extern void hdd_conn_set_connection_state(hdd_adapter_t *pAdapter, eConnectionState connState); diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index dd641595a16c..a7113f54c552 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1309,9 +1309,7 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, (const u8 *)&pSapEvent->sapevt. sapStationAssocReassocCompleteEvent.ies[0]; staInfo.assoc_req_ies_len = iesLen; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 31)) staInfo.filled |= STATION_INFO_ASSOC_REQ_IES; -#endif cfg80211_new_sta(dev, (const u8 *)&pSapEvent->sapevt. sapStationAssocReassocCompleteEvent. @@ -6384,10 +6382,6 @@ static int wlan_hdd_set_channel(struct wiphy *wiphy, smeConfig.csrConfig. channelBondingMode5GHz = eCSR_INI_SINGLE_CHANNEL_CENTERED; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - sap_config->ch_width_orig = - eHT_CHANNEL_WIDTH_20MHZ; -#endif sap_config->sec_ch = 0; break; @@ -6637,19 +6631,6 @@ static void wlan_hdd_add_extra_ie(hdd_adapter_t *pHostapdAdapter, return; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -/** - * wlan_hdd_cfg80211_alloc_new_beacon() - alloc beacon in ap mode - * @pAdapter: Pointer to hostapd adapter - * @ppBeacon: Pointer to pointer to beacon data - * @params: Pointer to beacon parameters - * - * Return: 0 for success non-zero for failure - */ -int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, - beacon_data_t **ppBeacon, - struct beacon_parameters *params) -#else /** * wlan_hdd_cfg80211_alloc_new_beacon() - alloc beacon in ap mode * @pAdapter: Pointer to hostapd adapter @@ -6663,7 +6644,6 @@ 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; @@ -6727,17 +6707,10 @@ int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, FL("Mem allocation for beacon failed")); return -ENOMEM; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) - 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 | * ----------------------------------------------- @@ -7223,17 +7196,6 @@ setup_acs_overrides: return 0; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -/** - * wlan_hdd_cfg80211_start_bss() - start bss - * @pHostapdAdapter: Pointer to hostapd adapter - * @params: Pointer to start bss beacon parameters - * - * Return: 0 for success non-zero for failure - */ -static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, - struct beacon_parameters *params) -#else /** * wlan_hdd_cfg80211_start_bss() - start bss * @pHostapdAdapter: Pointer to hostapd adapter @@ -7248,7 +7210,6 @@ 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; @@ -7507,33 +7468,6 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->SSIDinfo.ssidHidden = false; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) - if (params->ssid != NULL) { - cdf_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) { cdf_mem_copy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len); pConfig->SSIDinfo.ssid.length = ssid_len; @@ -7557,7 +7491,6 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, break; } } -#endif cdf_mem_copy(pConfig->self_macaddr.bytes, pHostapdAdapter->macAddressCurrent.bytes, @@ -7653,16 +7586,6 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, sme_config.csrConfig.WMMSupportMode = eCsrRoamWmmNoQos; sme_update_config(pHddCtx->hHal, &sme_config); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - /* 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_80P80) { if (pHddCtx->isVHT80Allowed == false) pConfig->ch_width_orig = CH_WIDTH_40MHZ; @@ -7827,209 +7750,6 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return 0; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -/** - * __wlan_hdd_cfg80211_add_beacon() - add beacon in soft ap mode - * @wiphy: Pointer to wiphy structure - * @dev: Pointer to net_device structure - * @params: Pointer to add beacon parameters - * - * Return: 0 for success non-zero for failure - */ -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(); - - if (CDF_FTM_MODE == hdd_get_conparam()) { - hddLog(LOGE, FL("Command not allowed in FTM mode")); - return -EINVAL; - } - - MTRACE(cdf_trace(CDF_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 (!cds_allow_concurrency(pHddCtx, - cds_convert_device_mode_to_hdd_type( - pAdapter->device_mode), 0, HDD_20_MHZ)) { - hddLog(LOGE, - FL("This concurrency combination is not allowed")); - 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(LOGW, - FL("already beacon info added to session(%d)"), - pAdapter->sessionId); - return -EALREADY; - } - - status = - wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, - &new, params); - if (status != CDF_STATUS_SUCCESS) { - hddLog(LOGE, - 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 - */ -int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params) -{ - int ret; - - cds_ssr_protect(__func__); - ret = __wlan_hdd_cfg80211_add_beacon(wiphy, dev, params); - cds_ssr_unprotect(__func__); - - return ret; -} - -/** - * __wlan_hdd_cfg80211_set_beacon() - set beacon in soft ap mode - * @wiphy: Pointer to wiphy structure - * @dev: Pointer to net_device structure - * @params: Pointer to set beacon parameters - * - * Return: 0 for success non-zero for failure - */ -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(); - - if (CDF_FTM_MODE == hdd_get_conparam()) { - hddLog(LOGE, FL("Command not allowed in FTM mode")); - return -EINVAL; - } - - MTRACE(cdf_trace(CDF_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 ((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 != CDF_STATUS_SUCCESS) { - hddLog(LOGE, - 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 - */ -int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params) -{ - int ret; - - cds_ssr_protect(__func__); - ret = __wlan_hdd_cfg80211_set_beacon(wiphy, dev, params); - cds_ssr_unprotect(__func__); - - return ret; -} - -#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -/** - * __wlan_hdd_cfg80211_del_beacon() - stop soft ap - * @wiphy: Pointer to wiphy structure - * @dev: Pointer to net_device structure - * - * Return: 0 for success non-zero for failure - */ -static int __wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, - struct net_device *dev) -#else /** * __wlan_hdd_cfg80211_stop_ap() - stop soft ap * @wiphy: Pointer to wiphy structure @@ -8039,7 +7759,6 @@ static int __wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, */ 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; @@ -8209,7 +7928,6 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, return ret; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) /** * wlan_hdd_get_channel_bw() - get channel bandwidth * @width: input channel width in nl80211_chan_width value @@ -8245,28 +7963,7 @@ static enum hw_mode_bandwidth wlan_hdd_get_channel_bw( return ch_bw; } -#endif - -#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 - */ -int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, - struct net_device *dev) -{ - int ret; - - cds_ssr_protect(__func__); - ret = __wlan_hdd_cfg80211_del_beacon(wiphy, dev); - cds_ssr_unprotect(__func__); - return ret; -} -#else /** * wlan_hdd_cfg80211_stop_ap() - stop sap * @wiphy: Pointer to wiphy @@ -8285,9 +7982,7 @@ int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, return ret; } -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) /** * __wlan_hdd_cfg80211_start_ap() - start soft ap mode * @wiphy: Pointer to wiphy structure @@ -8331,14 +8026,10 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, hdd_device_mode_to_string(pAdapter->device_mode), pAdapter->device_mode); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) channel_width = wlan_hdd_get_channel_bw(params->chandef.width); channel = ieee80211_frequency_to_channel( params->chandef.chan->center_freq); -#else - channel_width = HW_MODE_20_MHZ; - channel = 0; -#endif + /* check if concurrency is allowed */ if (!cds_allow_concurrency(pHddCtx, cds_convert_device_mode_to_hdd_type( @@ -8374,9 +8065,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, || (pAdapter->device_mode == WLAN_HDD_P2P_GO) ) { beacon_data_t *old, *new; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) enum nl80211_channel_type channel_type; -#endif old = pAdapter->sessionCtx.ap.beacon; @@ -8419,10 +8108,8 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, pAdapter->sessionCtx.ap.sapConfig.authType = eSAP_AUTO_SWITCH; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) pAdapter->sessionCtx.ap.sapConfig.ch_width_orig = params->chandef.width; -#endif status = wlan_hdd_cfg80211_start_bss(pAdapter, ¶ms->beacon, @@ -8539,5 +8226,3 @@ int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, return ret; } - -#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) */ diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h index f4f72c82d658..f57cb1c4b677 100644 --- a/core/hdd/src/wlan_hdd_hostapd.h +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -99,29 +99,13 @@ CDF_STATUS hdd_set_sap_ht2040_mode(hdd_adapter_t *pHostapdAdapter, uint8_t channel_type); #endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params); - -int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params); -#endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) -int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy, - struct net_device *dev); -#else int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)) int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *params); -#endif int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 462ffd679dc0..b08bd02030f5 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -836,15 +836,9 @@ hdd_sendactionframe(hdd_adapter_t *adapter, const uint8_t *bssid, ret = wlan_hdd_mgmt_tx(NULL, &adapter->wdev, ¶ms, &cookie); #else ret = wlan_hdd_mgmt_tx(NULL, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) &(adapter->wdev), -#else - adapter->dev, -#endif &chan, 0, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - NL80211_CHAN_HT20, 1, -#endif + dwell_time, frame, frame_len, 1, 1, &cookie); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index eab8bdb240ba..75c0dbe049c8 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1731,11 +1731,7 @@ static struct net_device_ops wlan_drv_ops = { .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)) .ndo_set_rx_mode = hdd_set_multicast_list, -#else - .ndo_set_multicast_list = hdd_set_multicast_list, -#endif /* LINUX_VERSION_CODE */ #endif }; @@ -2254,10 +2250,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, if (WLAN_HDD_P2P_CLIENT == session_type) adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) else if (WLAN_HDD_P2P_DEVICE == session_type) adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; -#endif else adapter->wdev.iftype = NL80211_IFTYPE_STATION; diff --git a/core/hdd/src/wlan_hdd_memdump.c b/core/hdd/src/wlan_hdd_memdump.c index d1ad781ed929..21f398e52ce5 100644 --- a/core/hdd/src/wlan_hdd_memdump.c +++ b/core/hdd/src/wlan_hdd_memdump.c @@ -368,7 +368,6 @@ static struct proc_dir_entry *proc_file, *proc_dir; * * 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; @@ -376,15 +375,6 @@ static void *memdump_get_file_data(struct file *file) 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 diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index f41d4d97fdd9..be647ad8272e 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -211,19 +211,11 @@ CDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx, __func__); } cfg80211_remain_on_channel_expired( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) pRemainChanCtx->dev-> ieee80211_ptr, -#else - pRemainChanCtx->dev, -#endif pRemainChanCtx-> cookie, &pRemainChanCtx->chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - pRemainChanCtx-> - chan_type, -#endif GFP_KERNEL); pAdapter->last_roc_ts = cdf_mc_timer_get_system_time(); } @@ -827,10 +819,6 @@ void wlan_hdd_roc_request_dequeue(struct work_struct *work) 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)) - enum nl80211_channel_type - channel_type, -#endif unsigned int duration, u64 *cookie, rem_on_channel_request_type_t @@ -850,15 +838,9 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, 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)) - 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 pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(pHddCtx); if (0 != ret) @@ -879,9 +861,6 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, cdf_mem_zero(pRemainChanCtx, sizeof(*pRemainChanCtx)); cdf_mem_copy(&pRemainChanCtx->chan, chan, sizeof(struct ieee80211_channel)); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - pRemainChanCtx->chan_type = channel_type; -#endif pRemainChanCtx->duration = duration; pRemainChanCtx->dev = dev; *cookie = (uintptr_t) pRemainChanCtx; @@ -955,21 +934,11 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, } int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif struct ieee80211_channel *chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - enum nl80211_channel_type - channel_type, -#endif unsigned int duration, u64 *cookie) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct net_device *dev = wdev->netdev; -#endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *hdd_ctx; int ret; @@ -989,10 +958,8 @@ int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, MTRACE(cdf_trace(CDF_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)) - channel_type, -#endif duration, cookie, REMAIN_ON_CHANNEL_REQUEST); EXIT(); @@ -1000,30 +967,16 @@ int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, } int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif struct ieee80211_channel *chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - enum nl80211_channel_type channel_type, -#endif unsigned int duration, u64 *cookie) { int ret; cds_ssr_protect(__func__); ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) wdev, -#else - dev, -#endif chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - channel_type, -#endif duration, cookie); cds_ssr_unprotect(__func__); @@ -1073,19 +1026,11 @@ void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, if (REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { cfg80211_ready_on_channel( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) pAdapter->dev-> ieee80211_ptr, -#else - pAdapter->dev, -#endif (uintptr_t) pRemainChanCtx, &pRemainChanCtx->chan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - pRemainChanCtx-> - chan_type, -#endif pRemainChanCtx-> duration, GFP_KERNEL); } else if (OFF_CHANNEL_ACTION_TX == @@ -1109,7 +1054,7 @@ void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, 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)) +#else cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, pRemainChanCtx->action_pkt_buff.freq, 0, @@ -1117,21 +1062,6 @@ void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, 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 */ cdf_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr); @@ -1149,16 +1079,10 @@ void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter, } int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif u64 cookie) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 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; @@ -1294,56 +1218,27 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, } int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) struct wireless_dev *wdev, -#else - struct net_device *dev, -#endif u64 cookie) { int ret; cds_ssr_protect(__func__); ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) wdev, -#else - dev, -#endif cookie); cds_ssr_unprotect(__func__); return ret; } -#if (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)) - 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)) 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; @@ -1413,9 +1308,7 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, } #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) noack = dont_wait_for_ack; -#endif /* If the wait is coming as 0 with off channel set */ /* then set the wait to 200 ms */ @@ -1582,9 +1475,6 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 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)) - channel_type, -#endif wait, cookie, req_type); if (0 != status) { @@ -1713,11 +1603,7 @@ err: err_rem_channel: *cookie = (uintptr_t) cfgState; cfg80211_mgmt_tx_status( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) pAdapter->dev->ieee80211_ptr, -#else - pAdapter->dev, -#endif *cookie, buf, len, false, GFP_KERNEL); EXIT(); return 0; @@ -1726,29 +1612,12 @@ err_rem_channel: #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 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)) +#else 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)) - 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; @@ -1760,43 +1629,23 @@ int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, params->wait, params->buf, params->len, params->no_cck, params->dont_wait_for_ack, cookie); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +#else ret = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) - 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 */ cds_ssr_unprotect(__func__); return ret; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { 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)) int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { @@ -1808,19 +1657,6 @@ int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, return ret; } -#else -int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, - struct net_device *dev, u64 cookie) -{ - int ret; - - cds_ssr_protect(__func__); - ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie); - cds_ssr_unprotect(__func__); - - return ret; -} -#endif void hdd_send_action_cnf(hdd_adapter_t *pAdapter, bool actionSendSuccess) { @@ -1842,11 +1678,7 @@ void hdd_send_action_cnf(hdd_adapter_t *pAdapter, bool actionSendSuccess) * data while sending tx ack status. * */ cfg80211_mgmt_tx_status( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) pAdapter->dev->ieee80211_ptr, -#else - pAdapter->dev, -#endif cfgState->action_cookie, cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL); @@ -2104,24 +1936,11 @@ static uint8_t wlan_hdd_get_session_type(enum nl80211_iftype type) return sessionType; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) 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; @@ -2202,14 +2021,9 @@ struct net_device *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOSPC); } EXIT(); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) return pAdapter->dev->ieee80211_ptr; -#else - return pAdapter->dev; -#endif } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, const char *name, enum nl80211_iftype type, @@ -2223,43 +2037,10 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy, cds_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; - - cds_ssr_protect(__func__); - wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); - cds_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; - cds_ssr_protect(__func__); - ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params); - cds_ssr_unprotect(__func__); - return ndev; -} -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 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)) struct net_device *dev = wdev->netdev; -#endif hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy); hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); int status; @@ -2291,20 +2072,12 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) return 0; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 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; cds_ssr_protect(__func__); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) ret = __wlan_hdd_del_virtual_intf(wiphy, wdev); -#else - ret = __wlan_hdd_del_virtual_intf(wiphy, dev); -#endif cds_ssr_unprotect(__func__); return ret; @@ -2614,14 +2387,8 @@ void hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, 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, + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames, nFrameLength, GFP_ATOMIC); #endif /* LINUX_VERSION_CODE */ } diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 74ab785c50f9..479fbb6db690 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -2176,9 +2176,7 @@ int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, * Return: 0 for success, non-zero for failure */ static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) struct wireless_dev *wdev, -#endif enum nl80211_tx_power_setting type, int dbm) { @@ -2249,18 +2247,14 @@ static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, * Return: 0 for success, non-zero for failure */ int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) struct wireless_dev *wdev, -#endif enum nl80211_tx_power_setting type, int dbm) { int ret; cds_ssr_protect(__func__); ret = __wlan_hdd_cfg80211_set_txpower(wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) wdev, -#endif type, dbm); cds_ssr_unprotect(__func__); @@ -2276,9 +2270,7 @@ int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, * Return: 0 for success, non-zero for failure */ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) struct wireless_dev *wdev, -#endif int *dbm) { @@ -2328,18 +2320,14 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, * Return: 0 for success, error number on failure. */ 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; cds_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); cds_ssr_unprotect(__func__); diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 99b6db2b1411..0a13bf602b96 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1223,15 +1223,10 @@ static void wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work) * Return: 0 for success, non zero for failure */ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request, uint8_t source) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 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); @@ -1328,9 +1323,6 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, * (return -EBUSY) */ status = wlan_hdd_tdls_scan_callback(pAdapter, wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - dev, -#endif request); if (status <= 0) { if (!status) @@ -1598,17 +1590,11 @@ free_mem: * Return: 0 for success, non zero for failure */ int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request) { int ret; cds_ssr_protect(__func__); ret = __wlan_hdd_cfg80211_scan(wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - dev, -#endif request, NL_SCAN); cds_ssr_unprotect(__func__); return ret; @@ -2199,12 +2185,8 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, /*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) pPnoRequest->aNetworks[i].rssiThreshold = request->match_sets[i].rssi_thold; -#else - pPnoRequest->aNetworks[i].rssiThreshold = 0; /* Default value */ -#endif } for (i = 0; i < request->n_ssids; i++) { diff --git a/core/hdd/src/wlan_hdd_scan.h b/core/hdd/src/wlan_hdd_scan.h index 06ef03b3789c..05bc2754c354 100644 --- a/core/hdd/src/wlan_hdd_scan.h +++ b/core/hdd/src/wlan_hdd_scan.h @@ -51,9 +51,6 @@ int iw_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request); #ifdef FEATURE_WLAN_SCAN_PNO diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 3295fb793a8f..903fbfff4a73 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -419,9 +419,6 @@ static void wlan_hdd_tdls_schedule_scan(struct work_struct *work) scan_ctx->attempt++; wlan_hdd_cfg80211_scan(scan_ctx->wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - scan_ctx->dev, -#endif scan_ctx->scan_request); } @@ -2559,9 +2556,6 @@ void wlan_hdd_tdls_pre_setup(struct work_struct *work) */ int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request) { tdls_scan_context_t *scan_ctx; @@ -2574,9 +2568,6 @@ int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, scan_ctx = &pHddCtx->tdls_scan_ctxt; scan_ctx->wiphy = wiphy; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - scan_ctx->dev = dev; -#endif scan_ctx->scan_request = request; EXIT(); @@ -2595,18 +2586,11 @@ int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx, */ static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx, struct wiphy *wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - 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)) - 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; } @@ -2625,9 +2609,6 @@ static void wlan_hdd_tdls_scan_init_work(hdd_context_t *pHddCtx, * 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)) - struct net_device *dev, -#endif struct cfg80211_scan_request *request) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); @@ -2682,9 +2663,6 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, pHddCtx->tdls_scan_ctxt.attempt, delay); wlan_hdd_tdls_scan_init_work(pHddCtx, wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - dev, -#endif request, msecs_to_jiffies(delay)); /* scan should not continue */ @@ -2784,9 +2762,6 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, wlan_hdd_tdls_connected_peers(pAdapter), delay); wlan_hdd_tdls_scan_init_work(pHddCtx, wiphy, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) - dev, -#endif request, msecs_to_jiffies(delay)); /* scan should not continue */ diff --git a/core/hif/src/ath_procfs.c b/core/hif/src/ath_procfs.c index 941d2e598981..2b25e3ea7598 100644 --- a/core/hif/src/ath_procfs.c +++ b/core/hif/src/ath_procfs.c @@ -56,12 +56,7 @@ static void *get_hif_hdl_from_file(struct file *file) { struct ol_softc *scn; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) scn = (struct ol_softc *)PDE_DATA(file_inode(file)); -#else - scn = (struct ol_softc *)( - PDE(file->f_path.dentry->d_inode)->data); -#endif return (void *)scn; } diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 91cff6a8835f..b58f84d1d438 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -928,14 +928,12 @@ int hif_enable_pci(struct hif_pci_softc *sc, /* 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 (!defined(__LINUX_ARM_ARCH__)) if (pci_assign_resource(pdev, BAR_NUM)) { HIF_ERROR("%s: pci_assign_resource error", __func__); return -EIO; } #endif - if (pci_enable_device(pdev)) { HIF_ERROR("%s: pci_enable_device error", __func__); diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index 507b5847e939..60cbfb3b1bb6 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -528,10 +528,6 @@ static int wlan_logging_thread(void *Arg) 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, diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c index 8cd8c45a39c2..c9f78f6fa4e5 100644 --- a/core/utils/nlink/src/wlan_nlink_srv.c +++ b/core/utils/nlink/src/wlan_nlink_srv.c @@ -60,24 +60,13 @@ static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh); 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)); @@ -151,11 +140,7 @@ 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) @@ -181,11 +166,7 @@ int nl_srv_bcast(struct sk_buff *skb) 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) diff --git a/core/utils/pktlog/linux_ac.c b/core/utils/pktlog/linux_ac.c index 3b5dc1b943fc..8ef8e0f1a2a9 100644 --- a/core/utils/pktlog/linux_ac.c +++ b/core/utils/pktlog/linux_ac.c @@ -152,11 +152,7 @@ int pktlog_alloc_buf(struct ol_softc *scn) 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); } @@ -188,11 +184,7 @@ void pktlog_release_buf(struct ol_softc *scn) 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); } @@ -321,12 +313,6 @@ static int pktlog_sysctl_register(struct ol_softc *scn) 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 @@ -334,50 +320,44 @@ static int pktlog_sysctl_register(struct ol_softc *scn) * /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; @@ -385,7 +365,6 @@ static int pktlog_sysctl_register(struct ol_softc *scn) 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; @@ -393,14 +372,12 @@ static int pktlog_sysctl_register(struct ol_softc *scn) 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; @@ -411,13 +388,9 @@ static int pktlog_sysctl_register(struct ol_softc *scn) /* 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; @@ -468,7 +441,6 @@ static int pktlog_attach(struct ol_softc *scn) 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); @@ -478,22 +450,6 @@ static int pktlog_attach(struct ol_softc *scn) __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; @@ -867,14 +823,8 @@ pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) 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) @@ -985,51 +935,6 @@ rd_done: #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) { @@ -1041,7 +946,6 @@ 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; @@ -1056,62 +960,16 @@ int pktlog_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 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 */ -- cgit v1.2.3 From a5cea29bd15d6807fc99e939184d1c3421662189 Mon Sep 17 00:00:00 2001 From: Pradeep Reddy POTTETI Date: Wed, 4 Nov 2015 14:40:51 +0530 Subject: qcacld-3.0: Send TDLS setup request and response with VI tid qcacld-2.0 to qcacld-3.0 propagation. Send tdls mgmt frames with VI tid to give more priority to tdls mgmt frames. CRs-Fixed: 873749 Change-Id: I9196680f09678185c1010b472851c1aca00b1635 --- core/mac/src/pe/lim/lim_process_tdls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index b440f1684a2b..9686b4b7e318 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -1056,7 +1056,7 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, LINK_IDEN_ADDR_OFFSET (tdlsSetupReq), TDLS_LINK_AP, - TDLS_INITIATOR, TID_AC_BK, + TDLS_INITIATOR, TID_AC_VI, psessionEntry); lim_log(pMac, LOGW, @@ -1106,7 +1106,7 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - TID_AC_BK, + TID_AC_VI, lim_tx_complete, pFrame, lim_mgmt_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, @@ -1538,7 +1538,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, header_offset = lim_prepare_tdls_frame_header(pMac, pFrame, LINK_IDEN_ADDR_OFFSET (tdlsSetupRsp), TDLS_LINK_AP, - TDLS_RESPONDER, TID_AC_BK, + TDLS_RESPONDER, TID_AC_VI, psessionEntry); lim_log(pMac, LOG1, @@ -1586,7 +1586,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - TID_AC_BK, + TID_AC_VI, lim_tx_complete, pFrame, lim_mgmt_tx_complete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, -- cgit v1.2.3 From ea6109d49e4754ddf01e18731722ddff6d96c81c Mon Sep 17 00:00:00 2001 From: Pradeep Reddy POTTETI Date: Wed, 4 Nov 2015 15:01:46 +0530 Subject: qcacld-3.0: Enable WMM if HT capabilities are present in beacon qcacld-2.0 to qcacld-3.0 propagation. WMM should be enabled if HT caps are present even if WMM ie is not present in beacons/probe response frames. In few places it is not taken care. This commit will address the issue. CRs-fixed: 873761 Change-Id: I985b7721fc28c9b7d087123c6cff9d76f93696d5 --- core/mac/src/pe/lim/lim_prop_exts_utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index c45da30c1b61..f05f00c15904 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -103,7 +103,8 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, if (sir_parse_beacon_ie(mac_ctx, beacon_struct, p_ie, (uint32_t) ie_len) == eSIR_SUCCESS) { if (beacon_struct->wmeInfoPresent - || beacon_struct->wmeEdcaPresent) + || beacon_struct->wmeEdcaPresent + || beacon_struct->HTCaps.present) LIM_BSS_CAPS_SET(WME, *qos_cap); if (LIM_BSS_CAPS_GET(WME, *qos_cap) && beacon_struct->wsmCapablePresent) -- cgit v1.2.3 From 8a13e5ca400eababe451af18adca9380dc13c96f Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 29 Oct 2015 16:12:09 -0700 Subject: qcacld-3.0: Initialize irq_lock and connection_status_lock Uninitialize spinlock caused crash on mdm platform. Change-Id: I0d86999d70e35c69775e698e69a8388de24d6fb3 CRs-Fixed: 951563 --- core/hdd/src/wlan_hdd_main.c | 1 + core/hif/src/pcie/if_pci.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 75c0dbe049c8..e5e869948502 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4749,6 +4749,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) init_completion(&hdd_ctx->ready_to_suspend); spin_lock_init(&hdd_ctx->schedScan_lock); + spin_lock_init(&hdd_ctx->connection_status_lock); cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock); cdf_list_init(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index b58f84d1d438..23a50c9f11b4 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -882,6 +882,8 @@ CDF_STATUS hif_bus_open(struct ol_softc *ol_sc, enum ath_hal_bus_type bus_type) sc->ol_sc = ol_sc; ol_sc->bus_type = bus_type; + cdf_spinlock_init(&ol_sc->irq_lock); + return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From e8f53a6daf4ab6cccdf6ad450758356636d235d2 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Sun, 6 Dec 2015 20:29:12 -0800 Subject: qcacld-3.0: Support atomic sub in cdf qcacld-2.0 to qcacld-3.0 propagation support atomic_sub in cdf Change-Id: Ie03c786f96533063b429fa3ea011e6e05c9504e2 CRs-Fixed: 938145 --- core/cdf/inc/cdf_atomic.h | 12 ++++++++++++ core/cdf/src/i_cdf_atomic.h | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/cdf/inc/cdf_atomic.h b/core/cdf/inc/cdf_atomic.h index 230d4eda3057..a30d52bccae7 100644 --- a/core/cdf/inc/cdf_atomic.h +++ b/core/cdf/inc/cdf_atomic.h @@ -101,6 +101,18 @@ static inline void cdf_atomic_add(int i, cdf_atomic_t *v) __cdf_atomic_add(i, v); } +/** + * cdf_atomic_sub() - Subtract a value from an atomic variable. + * @i: the amount by which to decrease the atomic counter + * @v: a pointer to an opaque atomic variable + * + * Return: none + */ +static inline void cdf_atomic_sub(int i, cdf_atomic_t *v) +{ + __cdf_atomic_sub(i, v); +} + /** * cdf_atomic_dec_and_test() - decrement an atomic variable and check if the * new value is zero diff --git a/core/cdf/src/i_cdf_atomic.h b/core/cdf/src/i_cdf_atomic.h index f74b7dfd47c7..7c08eb982a78 100644 --- a/core/cdf/src/i_cdf_atomic.h +++ b/core/cdf/src/i_cdf_atomic.h @@ -60,6 +60,18 @@ static inline void __cdf_atomic_add(int i, __cdf_atomic_t *v) atomic_add(i, v); } +/** + * cdf_atomic_sub() - Subtract a value from an atomic variable + * @i: the amount by which to decrease the atomic counter + * @v: a pointer to an opaque atomic variable + * + * Return: none + */ +static inline void __cdf_atomic_sub(int i, __cdf_atomic_t *v) +{ + atomic_sub(i, v); +} + static inline uint32_t __cdf_atomic_dec_and_test(__cdf_atomic_t *v) { return atomic_dec_and_test(v); -- cgit v1.2.3 From 68e837ee9ca8014ef9623b61507c7a0f0f91e88c Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Fri, 4 Dec 2015 12:57:24 -0800 Subject: qcacld-3.0: Record ce descriptor events qcacld-2.0 to qcacld-3.0 propagation Record when descriptors are posted to or completed by the copy engine in SLUB_DEBUG builds. Change-Id: I78ee028a7a61ffd253092cbb530ce9ec2e5022d3 CRs-Fixed: 938120 --- core/hif/src/ce/ce_internal.h | 32 ++++++++++++ core/hif/src/ce/ce_main.c | 3 ++ core/hif/src/ce/ce_service.c | 116 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index fb600808909c..0592d2018ba5 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -275,6 +275,38 @@ struct CE_dest_desc { #define CE_SENDLIST_ITEMS_MAX 12 +/** + * union ce_desc - unified data type for ce descriptors + * + * Both src and destination descriptors follow the same format. + * They use different data structures for different access symantics. + * Here we provice a unifying data type. + */ +union ce_desc { + struct CE_src_desc src_desc; + struct CE_dest_desc dest_desc; +}; + +/** + * enum hif_ce_event_type - HIF copy engine event type + * @HIF_RX_DESC_POST: event recorded before updating write index of RX ring. + * @HIF_RX_DESC_COMPLETION: event recorded before updating sw index of RX ring. + * @HIF_TX_GATHER_DESC_POST: post gather desc. (no write index update) + * @HIF_TX_DESC_POST: event recorded before updating write index of TX ring. + * @HIF_TX_DESC_COMPLETION: event recorded before updating sw index of TX ring. + */ +enum hif_ce_event_type { + HIF_RX_DESC_POST, + HIF_RX_DESC_COMPLETION, + HIF_TX_GATHER_DESC_POST, + HIF_TX_DESC_POST, + HIF_TX_DESC_COMPLETION, +}; + +void ce_init_ce_desc_event_log(int ce_id, int size); +void hif_record_ce_desc_event(int ce_id, enum hif_ce_event_type type, + union ce_desc *descriptor, void *memory, int index); + enum ce_sendlist_type_e { CE_SIMPLE_BUFFER_TYPE, /* TBDXXX: CE_RX_DESC_LIST, */ diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 0d2e40e3e0c1..1d8003ccbf52 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -166,6 +166,9 @@ struct CE_handle *ce_init(struct ol_softc *scn, else CE_state->src_sz_max = attr->src_sz_max; + ce_init_ce_desc_event_log(CE_id, + attr->src_nentries + attr->dest_nentries); + /* source ring setup */ nentries = attr->src_nentries; if (nentries) { diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index f5e07c9164c8..6f48a2b96d9b 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -78,6 +78,99 @@ static int war1_allow_sleep; /* io32 write workaround */ static int hif_ce_war1; +#ifdef CONFIG_SLUB_DEBUG_ON + +/** + * struct hif_ce_event - structure for detailing a ce event + * @type: what the event was + * @time: when it happened + * @descriptor: descriptor enqueued or dequeued + * @memory: virtual address that was used + * @index: location of the descriptor in the ce ring; + */ +struct hif_ce_desc_event { + uint16_t index; + enum hif_ce_event_type type; + uint64_t time; + union ce_desc descriptor; + void *memory; +}; + +/* max history to record per copy engine */ +#define HIF_CE_HISTORY_MAX 512 +cdf_atomic_t hif_ce_desc_history_index[CE_COUNT_MAX]; +struct hif_ce_desc_event hif_ce_desc_history[CE_COUNT_MAX][HIF_CE_HISTORY_MAX]; + +/** + * get_next_record_index() - get the next record index + * @table_index: atomic index variable to increment + * @array_size: array size of the circular buffer + * + * Increment the atomic index and reserve the value. + * Takes care of buffer wrap. + * Guaranteed to be thread safe as long as fewer than array_size contexts + * try to access the array. If there are more than array_size contexts + * trying to access the array, full locking of the recording process would + * be needed to have sane logging. + */ +static int get_next_record_index(cdf_atomic_t *table_index, int array_size) +{ + int record_index = cdf_atomic_inc_return(table_index); + if (record_index == array_size) + cdf_atomic_sub(array_size, table_index); + + while (record_index >= array_size) + record_index -= array_size; + return record_index; +} + +/** + * hif_record_ce_desc_event() - record ce descriptor events + * @ce_id: which ce is the event occuring on + * @type: what happened + * @descriptor: pointer to the descriptor posted/completed + * @memory: virtual address of buffer related to the descriptor + * @index: index that the descriptor was/will be at. + */ +void hif_record_ce_desc_event(int ce_id, enum hif_ce_event_type type, + union ce_desc *descriptor, void *memory, int index) +{ + int record_index = get_next_record_index( + &hif_ce_desc_history_index[ce_id], HIF_CE_HISTORY_MAX); + + struct hif_ce_desc_event *event = + &hif_ce_desc_history[ce_id][record_index]; + event->type = type; + event->time = cds_get_monotonic_boottime(); + event->descriptor = *descriptor; + event->memory = memory; + event->index = index; +} + +/** + * ce_init_ce_desc_event_log() - initialize the ce event log + * @ce_id: copy engine id for which we are initializing the log + * @size: size of array to dedicate + * + * Currently the passed size is ignored in favor of a precompiled value. + */ +void ce_init_ce_desc_event_log(int ce_id, int size) +{ + cdf_atomic_init(&hif_ce_desc_history_index[ce_id]); +} +#else +void hif_record_ce_desc_event( + int ce_id, enum hif_ce_event_type type, + union ce_desc *descriptor, void *memory, + int index) +{ +} + +static inline void ce_init_ce_desc_event_log(int ce_id, int size) +{ +} +#endif + /* * Support for Copy Engine hardware, which is mainly used for * communication between Host and Target over a PCIe interconnect. @@ -194,6 +287,7 @@ ce_send_nolock(struct CE_handle *copyeng, return status; } { + enum hif_ce_event_type event_type = HIF_TX_GATHER_DESC_POST; struct CE_src_desc *src_ring_base = (struct CE_src_desc *)src_ring->base_addr_owner_space; struct CE_src_desc *shadow_base = @@ -237,10 +331,18 @@ ce_send_nolock(struct CE_handle *copyeng, /* WORKAROUND */ if (!shadow_src_desc->gather) { + event_type = HIF_TX_DESC_POST; war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index); } + /* src_ring->write index hasn't been updated event though + * the register has allready been written to. + */ + hif_record_ce_desc_event(CE_state->id, event_type, + (union ce_desc *) shadow_src_desc, per_transfer_context, + src_ring->write_index); + src_ring->write_index = write_index; status = CDF_STATUS_SUCCESS; } @@ -574,6 +676,10 @@ ce_recv_buf_enqueue(struct CE_handle *copyeng, dest_ring->per_transfer_context[write_index] = per_recv_context; + hif_record_ce_desc_event(CE_state->id, HIF_RX_DESC_POST, + (union ce_desc *) dest_desc, per_recv_context, + write_index); + /* Update Destination Ring Write Index */ write_index = CE_RING_IDX_INCR(nentries_mask, write_index); CE_DEST_RING_WRITE_IDX_SET(scn, ctrl_addr, write_index); @@ -764,6 +870,11 @@ ce_completed_recv_next_nolock(struct CE_state *CE_state, goto done; } + hif_record_ce_desc_event(CE_state->id, HIF_RX_DESC_COMPLETION, + (union ce_desc *) dest_desc, + dest_ring->per_transfer_context[sw_index], + sw_index); + dest_desc->nbytes = 0; /* Return data from completed destination descriptor */ @@ -925,6 +1036,11 @@ ce_completed_send_next_nolock(struct CE_state *CE_state, struct CE_src_desc *src_desc = CE_SRC_RING_TO_DESC(src_ring_base, sw_index); #endif + hif_record_ce_desc_event(CE_state->id, HIF_TX_DESC_COMPLETION, + (union ce_desc *) shadow_src_desc, + src_ring->per_transfer_context[sw_index], + sw_index); + /* Return data from completed source descriptor */ *bufferp = HIF_CE_DESC_ADDR_TO_DMA(shadow_src_desc); *nbytesp = shadow_src_desc->nbytes; -- cgit v1.2.3 From 4275ba2b4f0f4954925242ea02c8304569a26974 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Sun, 6 Dec 2015 21:02:11 -0800 Subject: qcacld-3.0: Record CE interrupt and tasklet entry/exit Record CE interrupt in CE event history since the interrupts may come separately for the different interrupts. Change-Id: I269a103054d3ab2015d67370c43f4af598871b8d CRs-Fixed: 951569 --- core/hif/src/ce/ce_internal.h | 8 ++++++++ core/hif/src/ce/ce_service.c | 6 +++++- core/hif/src/ce/ce_tasklet.c | 9 +++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index 0592d2018ba5..d95f27cd3e4f 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -294,6 +294,10 @@ union ce_desc { * @HIF_TX_GATHER_DESC_POST: post gather desc. (no write index update) * @HIF_TX_DESC_POST: event recorded before updating write index of TX ring. * @HIF_TX_DESC_COMPLETION: event recorded before updating sw index of TX ring. + * @HIF_IRQ_EVENT: event recorded in the irq before scheduling the bh + * @HIF_CE_TASKLET_ENTRY: records the start of the ce_tasklet + * @HIF_CE_TASKLET_RESCHEDULE: records the rescheduling of the wlan_tasklet + * @HIF_CE_TASKLET_EXIT: records the exit of the wlan tasklet without reschedule */ enum hif_ce_event_type { HIF_RX_DESC_POST, @@ -301,6 +305,10 @@ enum hif_ce_event_type { HIF_TX_GATHER_DESC_POST, HIF_TX_DESC_POST, HIF_TX_DESC_COMPLETION, + HIF_IRQ_EVENT, + HIF_CE_TASKLET_ENTRY, + HIF_CE_TASKLET_RESCHEDULE, + HIF_CE_TASKLET_EXIT, }; void ce_init_ce_desc_event_log(int ce_id, int size); diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 6f48a2b96d9b..5f474ccaeebf 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -101,6 +101,7 @@ struct hif_ce_desc_event { cdf_atomic_t hif_ce_desc_history_index[CE_COUNT_MAX]; struct hif_ce_desc_event hif_ce_desc_history[CE_COUNT_MAX][HIF_CE_HISTORY_MAX]; + /** * get_next_record_index() - get the next record index * @table_index: atomic index variable to increment @@ -142,7 +143,10 @@ void hif_record_ce_desc_event(int ce_id, enum hif_ce_event_type type, &hif_ce_desc_history[ce_id][record_index]; event->type = type; event->time = cds_get_monotonic_boottime(); - event->descriptor = *descriptor; + if (descriptor != NULL) + event->descriptor = *descriptor; + else + memset(&event->descriptor, 0, sizeof(union ce_desc)); event->memory = memory; event->index = index; } diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c index 2ca61ca34a2e..a2edeba26563 100644 --- a/core/hif/src/ce/ce_tasklet.c +++ b/core/hif/src/ce/ce_tasklet.c @@ -203,6 +203,9 @@ static void ce_tasklet(unsigned long data) struct ol_softc *scn = hif_ce_state->scn; struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id]; + hif_record_ce_desc_event(tasklet_entry->ce_id, HIF_CE_TASKLET_ENTRY, + NULL, NULL, 0); + if (cdf_atomic_read(&scn->link_suspended)) { HIF_ERROR("%s: ce %d tasklet fired after link suspend.", __func__, tasklet_entry->ce_id); @@ -221,6 +224,8 @@ static void ce_tasklet(unsigned long data) * Enable the interrupt only when there is no pending frames in * any of the Copy Engine pipes. */ + hif_record_ce_desc_event(tasklet_entry->ce_id, + HIF_CE_TASKLET_RESCHEDULE, NULL, NULL, 0); ce_schedule_tasklet(tasklet_entry); return; } @@ -228,6 +233,9 @@ static void ce_tasklet(unsigned long data) if (scn->target_status != OL_TRGET_STATUS_RESET) ce_irq_enable(scn, tasklet_entry->ce_id); + hif_record_ce_desc_event(tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT, + NULL, NULL, 0); + cdf_atomic_dec(&scn->active_tasklet_cnt); } /** @@ -301,6 +309,7 @@ static irqreturn_t ce_irq_handler(int irq, void *context) ce_irq_disable(scn, ce_id); ce_irq_status(scn, ce_id, &host_status); cdf_atomic_inc(&scn->active_tasklet_cnt); + hif_record_ce_desc_event(ce_id, HIF_IRQ_EVENT, NULL, NULL, 0); if (hif_napi_enabled(scn, ce_id)) hif_napi_schedule(scn, ce_id); else -- cgit v1.2.3 From 91fd4a7d5dd3b3a1d777d79461266685b9cf1c08 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 23 Nov 2015 11:56:36 -0800 Subject: qcacld-3.0: Process WOW wake up event in the tasklet context This is a qcacld-2.0 to qcacld-3.0 propagation. Currently WOW wake up event is processed in work thread which may be delayed to schedule. Directly complete the event in tasklet in order to proceed it in time. Also make sure the WOW wake up event handler is in atomic context. Change-Id: Ie6015d39321c7759b35f05acc7833ef8974c0157 CRs-Fixed: 900629 --- core/cds/inc/cds_sched.h | 1 + core/cds/src/cds_sched.c | 16 ++++++++++ core/hdd/src/wlan_hdd_ext_scan.c | 65 ++++++++++++++++++++++++++++------------ 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index c9acbdce02e7..2571378ffac2 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -445,6 +445,7 @@ void cds_ssr_protect_init(void); void cds_ssr_protect(const char *caller_func); void cds_ssr_unprotect(const char *caller_func); bool cds_is_ssr_ready(const char *caller_func); +int cds_get_gfp_flags(void); #define cds_wait_for_work_thread_completion(func) cds_is_ssr_ready(func) diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index ada5e8858729..c3726de00052 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -1264,3 +1264,19 @@ bool cds_is_ssr_ready(const char *caller_func) return true; } + +/** + * cds_get_gfp_flags(): get GFP flags + * + * Based on the scheduled context, return GFP flags + * Return: gfp flags + */ +int cds_get_gfp_flags(void) +{ + int flags = GFP_KERNEL; + + if (in_interrupt() || in_atomic() || irqs_disabled()) + flags = GFP_ATOMIC; + + return flags; +} diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index 4071f771848c..4247636a0121 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -501,6 +501,9 @@ fail: * @ctx: Pointer to hdd context * @pData: Pointer to ext scan result event * + * This callback execute in atomic context and must not invoke any + * blocking calls. + * * Return: none */ static void @@ -510,6 +513,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, hdd_context_t *pHddCtx = ctx; struct sk_buff *skb = NULL; uint32_t i, index; + int flags = cds_get_gfp_flags(); ENTER(); @@ -529,7 +533,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, pHddCtx->wiphy, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, - index, GFP_KERNEL); + index, flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -618,7 +622,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx, goto fail; } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); EXIT(); return; @@ -633,6 +637,9 @@ fail: * @ctx: Pointer to hdd context * @pData: Pointer to signif wifi change event * + * This callback execute in atomic context and must not invoke any + * blocking calls. + * * Return: none */ static void @@ -645,6 +652,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( tSirWifiSignificantChange *ap_info; int32_t *rssi; uint32_t i, j; + int flags = cds_get_gfp_flags(); ENTER(); @@ -660,7 +668,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -738,7 +746,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind( goto fail; } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); return; fail: @@ -752,6 +760,9 @@ fail: * @ctx: Pointer to hdd context * @pData: Pointer to full scan result event * + * This callback execute in atomic context and must not invoke any + * blocking calls. + * * Return: none */ static void @@ -764,6 +775,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, #ifdef CONFIG_CNSS struct timespec ts; #endif + int flags = cds_get_gfp_flags(); ENTER(); @@ -784,7 +796,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -867,7 +879,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, goto nla_put_failure; } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); EXIT(); return; @@ -881,6 +893,9 @@ nla_put_failure: * @ctx: Pointer to hdd context * @pData: Pointer to scan results available indication param * + * This callback execute in atomic context and must not invoke any + * blocking calls. + * * Return: none */ static void @@ -890,6 +905,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event( { hdd_context_t *pHddCtx = (hdd_context_t *) ctx; struct sk_buff *skb = NULL; + int flags = cds_get_gfp_flags(); ENTER(); @@ -905,7 +921,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event( NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -924,7 +940,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event( goto nla_put_failure; } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); EXIT(); return; @@ -938,6 +954,9 @@ nla_put_failure: * @ctx: Pointer to hdd context * @pData: Pointer to scan event indication param * + * This callback execute in atomic context and must not invoke any + * blocking calls. + * * Return: none */ static void @@ -947,6 +966,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, { hdd_context_t *pHddCtx = (hdd_context_t *) ctx; struct sk_buff *skb = NULL; + int flags = cds_get_gfp_flags(); ENTER(); @@ -962,7 +982,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -983,7 +1003,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, goto nla_put_failure; } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); EXIT(); return; @@ -999,6 +1019,8 @@ nla_put_failure: * * 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 */ @@ -1009,6 +1031,7 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx, hdd_context_t *pHddCtx = (hdd_context_t *)ctx; struct sk_buff *skb = NULL; uint32_t len, i; + int flags = cds_get_gfp_flags(); ENTER(); @@ -1037,7 +1060,7 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -1095,7 +1118,7 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx, nla_nest_end(skb, nla_aps); } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); return; fail: @@ -1110,6 +1133,8 @@ fail: * * 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 */ @@ -1120,8 +1145,8 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx, 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; + struct nlattr *nla_aps, *nla_bss; + int flags = cds_get_gfp_flags(); ENTER(); @@ -1142,7 +1167,7 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX, - GFP_KERNEL); + flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -1225,7 +1250,7 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx, } nla_nest_end(skb, nla_aps); - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); return; fail: @@ -1242,6 +1267,8 @@ fail: * 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 */ @@ -1252,6 +1279,7 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, hdd_context_t *hdd_ctx = ctx; struct sk_buff *skb; uint32_t i, index; + int flags = cds_get_gfp_flags(); ENTER(); @@ -1273,8 +1301,7 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL, EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, - index, - GFP_KERNEL); + index, flags); if (!skb) { hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); @@ -1367,7 +1394,7 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, } } - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, flags); return; fail: -- cgit v1.2.3 From 1ed08cb3affcadfc6503ee8d805e1c65d0d7abf0 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Mon, 7 Dec 2015 17:26:14 -0800 Subject: qcacld-3.0: Clean up inappropriate HDD API in CDS Clean up the hddLog API and CDF_MODULE_ID_HDD with CDS_TRACE misused in CDS module. Change-Id: I786fa1ba216b42a6218f7eadba60ee7e5e82ebe5 CRs-fixed: 948327 --- core/cds/src/cds_api.c | 32 ++++++++++++++++---------------- core/cds/src/cds_sched.c | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 179ad463a7de..573dd9bac357 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -40,7 +40,6 @@ #include "sme_api.h" #include "mac_init_api.h" #include "wlan_qct_sys.h" -#include "wlan_hdd_misc.h" #include "i_cds_packet.h" #include "cds_reg_service.h" #include "wma_types.h" @@ -1579,7 +1578,8 @@ CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type, *type = WMI_VDEV_TYPE_OCB; break; default: - hddLog(CDF_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "Invalid device mode %d", mode); status = CDF_STATUS_E_INVAL; break; } @@ -1707,7 +1707,7 @@ void cds_set_wakelock_logging(bool value) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "cds context is Invald"); return; } @@ -1728,7 +1728,7 @@ bool cds_is_wakelock_enabled(void) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "cds context is Invald"); return false; } @@ -1752,7 +1752,7 @@ void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invald", __func__); return; } @@ -1805,7 +1805,7 @@ enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invald", __func__); return WLAN_LOG_LEVEL_OFF; } @@ -1867,7 +1867,7 @@ void cds_init_log_completion(void) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return; } @@ -1896,7 +1896,7 @@ void cds_deinit_log_completion(void) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return; } @@ -1923,7 +1923,7 @@ CDF_STATUS cds_set_log_completion(uint32_t is_fatal, p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return CDF_STATUS_E_FAILURE; } @@ -1955,7 +1955,7 @@ void cds_get_log_completion(uint32_t *is_fatal, p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return; } @@ -1981,7 +1981,7 @@ bool cds_is_log_report_in_progress(void) p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return true; } @@ -2011,13 +2011,13 @@ CDF_STATUS cds_flush_logs(uint32_t is_fatal, p_cds_context = cds_get_global_context(); if (!p_cds_context) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: cds context is Invalid", __func__); return CDF_STATUS_E_FAILURE; } if (cds_is_log_report_in_progress() == true) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", __func__, is_fatal, indicator, reason_code); return CDF_STATUS_E_FAILURE; @@ -2025,18 +2025,18 @@ CDF_STATUS cds_flush_logs(uint32_t is_fatal, status = cds_set_log_completion(is_fatal, indicator, reason_code); if (CDF_STATUS_SUCCESS != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Failed to set log trigger params", __func__); return CDF_STATUS_E_FAILURE; } - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", __func__, is_fatal, indicator, reason_code); ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext); if (0 != ret) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Failed to send flush FW log", __func__); cds_init_log_completion(); return CDF_STATUS_E_FAILURE; diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index c3726de00052..e67485031f78 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -353,15 +353,15 @@ static int cds_mc_thread(void *Arg) /* Get the Global CDS Context */ p_cds_context = cds_get_global_context(); if (!p_cds_context) { - hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Global CDS context is Null", - __func__); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: Global CDS context is Null", __func__); return 0; } pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); if (!pHddCtx) { - hddLog(CDF_TRACE_LEVEL_FATAL, "%s: HDD context is Null", - __func__); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "%s: HDD context is Null", __func__); return 0; } @@ -1143,7 +1143,7 @@ static void cds_print_external_threads(void) while (i < MAX_SSR_PROTECT_LOG) { if (!ssr_protect_log[i].free) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "PID %d is stuck at %s", ssr_protect_log[i].pid, ssr_protect_log[i].func); } @@ -1186,7 +1186,7 @@ void cds_ssr_protect(const char *caller_func) spin_unlock_irqrestore(&ssr_protect_lock, irq_flags); if (!status) - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "Could not track PID %d call %s: log is full", current->pid, caller_func); } @@ -1225,7 +1225,7 @@ void cds_ssr_unprotect(const char *caller_func) spin_unlock_irqrestore(&ssr_protect_lock, irq_flags); if (!status) - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "Untracked call %s", caller_func); } @@ -1259,7 +1259,7 @@ bool cds_is_ssr_ready(const char *caller_func) return false; } - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "Allowing SSR for %s", caller_func); return true; -- cgit v1.2.3 From 7d21f88ad1d594ed4556ba06851eb7f01845b186 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Wed, 4 Nov 2015 17:29:00 -0800 Subject: qcacld-3.0: Fix the incorrect mcs rate index conversion qcacld-2.0 to qcacld-3.0 propagation Driver would get the tx rate info from firmware and converts it to mcs index or legacy rate for userspace. The problem here is when firmware creates a valid ratesets, it includes all the subset of lower grade rates. e.g - VHT80 would include VHT80/VHT40/VHT20, VHT40 include VHT40/HT20 - HT40 would include HT40/HT20 - NSS2 would include NSS2 and NSS1 So that firmware would not only use one rateset, but would use all other valid rates, the fix is to go through all other possibilities to make sure the rate look up can find the correct mcs index. Change-Id: I5df9059b73954951c4adec56002a3eba80915752 CRs-fixed: 936078 --- core/hdd/src/wlan_hdd_stats.c | 20 ++- core/wma/inc/wma_internal.h | 26 ++-- core/wma/src/wma_utils.c | 294 +++++++++++++++++++++--------------------- 3 files changed, 175 insertions(+), 165 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 1f6030c81859..8f50005d8a96 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1779,13 +1779,12 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, pAdapter->hdd_stats.ClassA_stat.mcs_index = 0; } } -#ifdef LINKSPEED_DEBUG_ENABLED - pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n", - 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); -#endif /* LINKSPEED_DEBUG_ENABLED */ + + hdd_info("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 */ @@ -2118,6 +2117,13 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, #endif /* LINKSPEED_DEBUG_ENABLED */ } } + + if (rate_flags & eHAL_TX_RATE_LEGACY) + hdd_info("Reporting legacy rate %d", sinfo->txrate.legacy); + else + hdd_info("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; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d204979b4e0c..0fd93a395ec5 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -111,27 +111,29 @@ /** * struct index_data_rate_type - non vht data rate type - * @beacon_rate_index: Beacon rate index - * @supported_rate: Supported rate table + * @mcs_index: mcs rate index + * @ht20_rate: HT20 supported rate table + * @ht40_rate: HT40 supported rate table */ struct index_data_rate_type { - uint8_t beacon_rate_index; - uint16_t supported_rate[4]; + uint8_t mcs_index; + uint16_t ht20_rate[2]; + uint16_t ht40_rate[2]; }; #ifdef WLAN_FEATURE_11AC /** * struct index_vht_data_rate_type - vht data rate type - * @beacon_rate_index: Beacon rate index - * @supported_VHT80_rate: VHT80 rate - * @supported_VHT40_rate: VHT40 rate - * @supported_VHT20_rate: VHT20 rate + * @mcs_index: mcs rate index + * @ht20_rate: VHT20 supported rate table + * @ht40_rate: VHT40 supported rate table + * @ht80_rate: VHT80 supported rate table */ struct index_vht_data_rate_type { - uint8_t beacon_rate_index; - uint16_t supported_VHT80_rate[2]; - uint16_t supported_VHT40_rate[2]; - uint16_t supported_VHT20_rate[2]; + uint8_t mcs_index; + uint16_t ht20_rate[2]; + uint16_t ht40_rate[2]; + uint16_t ht80_rate[2]; }; #endif diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index cb1cc1ef84c3..bb027532b8d7 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -74,61 +74,61 @@ /* 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} } +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 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} } +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 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} } +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 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} } +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 /* WLAN_FEATURE_11AC */ @@ -159,6 +159,45 @@ void wma_swap_bytes(void *pv, uint32_t n) #define SWAPME(x, len) wma_swap_bytes(&x, len); #endif /* BIG_ENDIAN_HOST */ +/** + * wma_mcs_rate_match() - find the match mcs rate + * @match_rate: the rate to look up + * @is_sgi: return if the SGI rate is found + * @nss: the nss in use + * @nss1_rate: the nss1 rate + * @nss1_srate: the nss1 SGI rate + * @nss2_rate: the nss2 rate + * @nss2_srate: the nss2 SGI rate + * + * This is a helper function to find the match of the tx_rate + * in terms of the nss1/nss2 rate with non-SGI/SGI. + * + * Return: the found rate or 0 otherwise + */ +static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi, + uint8_t nss, uint16_t nss1_rate, + uint16_t nss1_srate, + uint16_t nss2_rate, + uint16_t nss2_srate) +{ + WMA_LOGD("%s match_rate: %d, %d %d %d %d", + __func__, match_rate, nss1_rate, nss1_srate, nss2_rate, + nss2_srate); + + if (match_rate == nss1_rate) { + return nss1_rate; + } else if (match_rate == nss1_srate) { + *is_sgi = true; + return nss1_srate; + } else if (nss == 2 && match_rate == nss2_rate) + return nss2_rate; + else if (nss == 2 && match_rate == nss2_srate) { + *is_sgi = true; + return nss2_srate; + } else + return 0; +} + /** * wma_get_mcs_idx() - get mcs index * @maxRate: max rate @@ -171,130 +210,93 @@ void wma_swap_bytes(void *pv, uint32_t n) static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags, uint8_t nss, uint8_t *mcsRateFlag) { - uint8_t rateFlag = 0, curIdx = 0; - uint16_t curRate; - bool found = false; -#ifdef WLAN_FEATURE_11AC - struct index_vht_data_rate_type *supported_vht_mcs_rate; -#endif /* WLAN_FEATURE_11AC */ - struct index_data_rate_type *supported_mcs_rate; + uint8_t index = 0; + uint16_t match_rate; + bool is_sgi = false; - WMA_LOGD("%s rate:%d rate_flgs:%d", __func__, maxRate, rate_flags); -#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); -#endif /* WLAN_FEATURE_11AC */ - supported_mcs_rate = (struct index_data_rate_type *) - ((nss == 1) ? &supported_mcs_rate_nss1 : &supported_mcs_rate_nss2); + WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d", + __func__, maxRate, rate_flags, nss); *mcsRateFlag = rate_flags; *mcsRateFlag &= ~eHAL_TX_RATE_SGI; #ifdef WLAN_FEATURE_11AC - if (rate_flags & - (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_VHT80)) { - + for (index = 0; index < MAX_VHT_MCS_IDX; index++) { if (rate_flags & eHAL_TX_RATE_VHT80) { - for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { - rateFlag = 0; - if (curIdx >= 7) { - if (rate_flags & eHAL_TX_RATE_SGI) - rateFlag |= 0x1; - } - - curRate = supported_vht_mcs_rate[curIdx].supported_VHT80_rate[rateFlag]; - if (curRate == maxRate) { - found = true; - break; - } - } + /* check for vht80 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss, + vht_mcs_nss1[index].ht80_rate[0], + vht_mcs_nss1[index].ht80_rate[1], + vht_mcs_nss2[index].ht80_rate[0], + vht_mcs_nss2[index].ht80_rate[1]); + if (match_rate) + goto rate_found; } - - if ((found == false) && - ((rate_flags & eHAL_TX_RATE_VHT80) || - (rate_flags & eHAL_TX_RATE_VHT40))) { - for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { - rateFlag = 0; - if (curIdx >= 7) { - if (rate_flags & eHAL_TX_RATE_SGI) - rateFlag |= 0x1; - } - - curRate = supported_vht_mcs_rate[curIdx].supported_VHT40_rate[rateFlag]; - if (curRate == maxRate) { - found = true; - *mcsRateFlag &= ~eHAL_TX_RATE_VHT80; - break; - } + if ((rate_flags & eHAL_TX_RATE_VHT40) | + (rate_flags & eHAL_TX_RATE_VHT80)) { + /* check for vht40 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss, + vht_mcs_nss1[index].ht40_rate[0], + vht_mcs_nss1[index].ht40_rate[1], + vht_mcs_nss2[index].ht40_rate[0], + vht_mcs_nss2[index].ht40_rate[1]); + if (match_rate) { + *mcsRateFlag &= ~eHAL_TX_RATE_VHT80; + goto rate_found; } } - - if ((found == false) && - ((rate_flags & eHAL_TX_RATE_VHT80) || - (rate_flags & eHAL_TX_RATE_VHT40) || - (rate_flags & eHAL_TX_RATE_VHT20))) { - for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) { - rateFlag = 0; - if (curIdx >= 7) { - if (rate_flags & eHAL_TX_RATE_SGI) - rateFlag |= 0x1; - } - - curRate = supported_vht_mcs_rate[curIdx].supported_VHT20_rate[rateFlag]; - if (curRate == maxRate) { - found = true; - *mcsRateFlag &= - ~(eHAL_TX_RATE_VHT80 | - eHAL_TX_RATE_VHT40); - break; - } + if ((rate_flags & eHAL_TX_RATE_VHT20) | + (rate_flags & eHAL_TX_RATE_VHT40) | + (rate_flags & eHAL_TX_RATE_VHT80)) { + /* check for vht20 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss, + vht_mcs_nss1[index].ht20_rate[0], + vht_mcs_nss1[index].ht20_rate[1], + vht_mcs_nss2[index].ht20_rate[0], + vht_mcs_nss2[index].ht20_rate[1]); + if (match_rate) { + *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 | + eHAL_TX_RATE_VHT40); + goto rate_found; } } } #endif /* WLAN_FEATURE_11AC */ - if ((found == false) && - (rate_flags & (eHAL_TX_RATE_HT40 | eHAL_TX_RATE_HT20))) { + for (index = 0; index < MAX_HT_MCS_IDX; index++) { if (rate_flags & eHAL_TX_RATE_HT40) { - rateFlag = 0x1; - - for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) { - if (curIdx == 7) { - if (rate_flags & eHAL_TX_RATE_SGI) - rateFlag |= 0x2; - } - - curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag]; - if (curRate == maxRate) { - found = true; - *mcsRateFlag = eHAL_TX_RATE_HT40; - break; - } + /* check for ht40 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss, + mcs_nss1[index].ht40_rate[0], + mcs_nss1[index].ht40_rate[1], + mcs_nss2[index].ht40_rate[0], + mcs_nss2[index].ht40_rate[1]); + if (match_rate) { + *mcsRateFlag = eHAL_TX_RATE_HT40; + goto rate_found; } } - - if (found == false) { - rateFlag = 0; - for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) { - if (curIdx == 7) { - if (rate_flags & eHAL_TX_RATE_SGI) - rateFlag |= 0x2; - } - - curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag]; - if (curRate == maxRate) { - found = true; - *mcsRateFlag = eHAL_TX_RATE_HT20; - break; - } + if (rate_flags & eHAL_TX_RATE_HT20) { + /* check for ht20 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss, + mcs_nss1[index].ht20_rate[0], + mcs_nss1[index].ht20_rate[1], + mcs_nss2[index].ht20_rate[0], + mcs_nss2[index].ht20_rate[1]); + if (match_rate) { + *mcsRateFlag = eHAL_TX_RATE_HT20; + goto rate_found; } } } - /*SGI rates are used by firmware only for MCS >= 7 */ - if (found && (curIdx >= 7)) +rate_found: + /* set SGI flag only if this is SGI rate */ + if (match_rate && is_sgi == true) *mcsRateFlag |= eHAL_TX_RATE_SGI; - return found ? curIdx : INVALID_MCS_IDX; + WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d", + __func__, match_rate, index, *mcsRateFlag, is_sgi); + + return match_rate ? index : INVALID_MCS_IDX; } /** -- cgit v1.2.3 From 966b57bcce01e18bb333b0f44381f7eb9dffa7cc Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Tue, 23 Jun 2015 17:14:08 +0530 Subject: qcacld-3.0: Don't process TX frame in unauthenticated state qcacld-2.0 to qcacld-3.0 propagation Process TX frame only when STA state is in Connected state otherwise drop the frame. Change-Id: Id384bb4a11bc2783b8017a8b4fac67ba4f708cb5 CRs-Fixed: 778274 --- core/hdd/src/wlan_hdd_tx_rx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index f5e9c32584ca..42a5c2c04844 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -347,6 +347,16 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } else { + if (eConnectionState_Associated != + pHddStaCtx->conn_info.connState) { + CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_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]; } -- cgit v1.2.3 From da81f966826d01631f2ebef717c2e3603a57db38 Mon Sep 17 00:00:00 2001 From: Samuel Ahn Date: Mon, 5 Oct 2015 13:38:39 +0530 Subject: qcacld-3.0: Fix transmitting in OCB mode qcacld-2.0 to qcacld-3.0 propagation When transmitting a packet in OCB mode, the station does not need to be associated to an access point. CRs-Fixed: 863620 Change-Id: I71b7ad6afa10321a7c7cde597a727bed7454f644 --- core/hdd/src/wlan_hdd_tx_rx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 42a5c2c04844..e6abd5346252 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -347,8 +347,9 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } else { - if (eConnectionState_Associated != - pHddStaCtx->conn_info.connState) { + if (WLAN_HDD_OCB != pAdapter->device_mode && + eConnectionState_Associated != + pHddStaCtx->conn_info.connState) { CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_INFO, FL("Tx frame in not associated state in %d context"), pAdapter->device_mode); -- cgit v1.2.3 From bb8583d4ceef28c9b593ee237a100c020ef851ff Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Wed, 9 Dec 2015 13:26:44 -0800 Subject: qcacld-3.0: Prepare HDD for unified logging Currently the HDD code uses a variety of logging APIs. In qcacld-3.0 HDD should converge on a unified set of logging APIs. Due to the large number of changes required, this will have to be done in a phased approach, with conversions occurring one source file at a time. One potential problem that could occur, in the absence of any protection, is that once a particular source file has been converted to the unified set of logging APIs, someone could introduce new code, either as a new feature or as a change propagation from qcacld-2.0, which re-introduces invocations of legacy logging APIs. In order to help prevent this, add conditional compilation to the hddLog() API so that it will not be available to source files which have been converted to the unified set of logging APIs. This will cause a compilation error if hddLog() is called from source files which have been converted. Once all of the source files have been converted, the hddLog() macro itself can be removed from the source code. Change-Id: I5debb0eb9cd89c08fdfcc4fc117776160ed34501 CRs-Fixed: 949529 --- core/hdd/inc/wlan_hdd_main.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 6fefaaf4928f..7a311c2515ef 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -156,8 +156,9 @@ #define WLAN_CHIP_VERSION "WCNSS" +#ifndef HDD_DISALLOW_LEGACY_HDDLOG #define hddLog(level, args ...) CDF_TRACE(CDF_MODULE_ID_HDD, level, ## args) - +#endif #define hdd_log(level, args...) CDF_TRACE(CDF_MODULE_ID_HDD, level, ## args) #define hdd_logfl(level, format, args...) hdd_log(level, FL(format), ## args) -- cgit v1.2.3 From aa9459f319ce36eee12218bc8e4f28d88fe4d90b Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Tue, 15 Dec 2015 15:03:23 -0800 Subject: qcacld-3.0: Fix MDM compilation errors Fix compilation errors in MDM features and when compiled against MDM kernel Change-Id: Iee8fb5f88bfff22117e087f8879d4caf50a945c1 CRs-fixed: 952116 --- core/cds/src/cds_reg_service.c | 5 +++++ core/hdd/src/wlan_hdd_cfg80211.c | 16 ++++++++-------- core/hdd/src/wlan_hdd_ipa.c | 16 ++++++++-------- core/sap/src/sap_module.c | 2 +- core/sme/src/csr/csr_util.c | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index f439c5971efc..19109abf86ce 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -49,6 +49,11 @@ #define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR #endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) +#define IEEE80211_CHAN_NO_20MHZ (1<<11) +#define IEEE80211_CHAN_NO_10MHZ (1<<12) +#endif + static v_REGDOMAIN_t temp_reg_domain = REGDOMAIN_COUNT; /* true if init happens thru init time driver hint */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 22646780c844..5b117225fd47 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -615,14 +615,6 @@ static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = { }; #endif -#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 - /** * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported * @flags: Pointer to the flags to Add channel switch flag. @@ -644,6 +636,14 @@ static inline void hdd_add_channel_switch_support(uint32_t *flags) } #endif +#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 diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 42883c18264f..0e2bd0e51964 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1403,19 +1403,19 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) "CE RING BASE: 0x%llx\n" "CE RING SIZE: %d\n" "CE REG ADDR : 0x%llx", - hdd_ipa->ce_sr_base_paddr, + (unsigned long long)hdd_ipa->ce_sr_base_paddr, hdd_ipa->ce_sr_ring_size, - hdd_ipa->ce_reg_paddr); + (unsigned long long)hdd_ipa->ce_reg_paddr); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST TX ====\n" "COMP RING BASE: 0x%llx\n" "COMP RING SIZE: %d\n" "NUM ALLOC BUF: %d\n" "COMP RING DBELL : 0x%llx", - hdd_ipa->tx_comp_ring_base_paddr, + (unsigned long long)hdd_ipa->tx_comp_ring_base_paddr, hdd_ipa->tx_comp_ring_size, hdd_ipa->tx_num_alloc_buffer, - hdd_ipa->tx_comp_doorbell_paddr); + (unsigned long long)hdd_ipa->tx_comp_doorbell_paddr); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST RX ====\n" "IND RING BASE: 0x%llx\n" @@ -1425,13 +1425,13 @@ static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt) "NUM EXCP PKT : %llu\n" "NUM TX BCMC : %llu\n" "NUM TX BCMC ERR : %llu", - hdd_ipa->rx_rdy_ring_base_paddr, + (unsigned long long)hdd_ipa->rx_rdy_ring_base_paddr, hdd_ipa->rx_rdy_ring_size, - hdd_ipa->rx_ready_doorbell_paddr, - hdd_ipa->rx_proc_done_idx_paddr, + (unsigned long long)hdd_ipa->rx_ready_doorbell_paddr, + (unsigned long long)hdd_ipa->rx_proc_done_idx_paddr, hdd_ipa->stats.num_rx_excep, hdd_ipa->stats.num_tx_bcmc, - hdd_ipa->stats.num_tx_bcmc_err); + (unsigned long long)hdd_ipa->stats.num_tx_bcmc_err); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, "==== IPA_UC WLAN_HOST CONTROL ====\n" "SAP NUM STAs: %d\n" diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index f1b02349696a..fb84e6634b4b 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -612,7 +612,7 @@ static bool wlan_sap_validate_channel_switch(tHalHandle hal, uint16_t sap_ch, ptSapContext sap_context) { return sme_validate_sap_channel_switch( - hHal, + hal, sap_ch, sap_context->csr_roamProfile.phyMode, sap_context->cc_switch_mode, diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index a116307655d0..743f3cc01a93 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -704,7 +704,7 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, CDF_SAP_MODE)) && (session->connectState != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { - if (pSession->ch_switch_in_progress) + if (session->ch_switch_in_progress) continue; csr_handle_conc_chnl_overlap_for_sap_go(mac_ctx, -- cgit v1.2.3 From d2f458f35c59b0475a588f2e8d9fc5780ec03d02 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 18 Nov 2015 16:27:37 -0800 Subject: qcacld-3.0: Add IPA UC WDI 1.0 backward compatibility Update qcacld-3.0 for IPA UC WDI 1.0 backward compatibility for Rome WIFI device. Change-Id: I33084efd6dd3434d1f6baec49de43fab75c63e7f CRs-fixed: 952114 --- Kbuild | 4 ++ core/dp/htt/htt_h2t.c | 95 +++++++++++++++++++++++++ core/dp/htt/htt_rx.c | 154 ++++++++++++++++++++++++++-------------- core/dp/htt/htt_tx.c | 190 ++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 340 insertions(+), 103 deletions(-) diff --git a/Kbuild b/Kbuild index 8e0256309419..5e35ebc01f50 100644 --- a/Kbuild +++ b/Kbuild @@ -914,6 +914,10 @@ CDEFINES += -DADRASTEA_SHADOW_REGISTERS CDEFINES += -DADRASTEA_RRI_ON_DDR endif +ifneq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS) $(CONFIG_CNSS_ADRASTEA))) +CDEFINES += -DQCA_WIFI_2_0 +endif + ifeq ($(CONFIG_WLAN_FASTPATH), y) CDEFINES += -DWLAN_FEATURE_FASTPATH endif diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index ca5f7353cb24..59b0f06efa6c 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -648,6 +648,100 @@ htt_h2t_aggr_cfg_msg(struct htt_pdev_t *pdev, * Return: 0 success * A_NO_MEMORY No memory fail */ +#ifdef QCA_WIFI_2_0 +/* Rome Support only WDI 1.0 */ +int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) +{ + struct htt_htc_pkt *pkt; + cdf_nbuf_t msg; + uint32_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 */ + + /* reserve room for HTC header */ + msg = cdf_nbuf_alloc(pdev->osdev, HTT_MSG_BUF_SIZE(HTT_WDI_IPA_CFG_SZ), + 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 */ + cdf_nbuf_put_tail(msg, HTT_WDI_IPA_CFG_SZ); + + /* fill in the message contents */ + msg_word = (uint32_t *) cdf_nbuf_data(msg); + + /* rewind beyond alignment pad to get to the HTC header reserved area */ + cdf_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, + cdf_nbuf_data(msg), + cdf_nbuf_len(msg), + pdev->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + htc_send_pkt(pdev->htc_pdev, &pkt->htc_pkt); + + return A_OK; +} +#else int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; @@ -791,6 +885,7 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) return A_OK; } +#endif /** * htt_h2t_ipa_uc_set_active() - Propagate WDI path enable/disable to firmware diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 80a1b8c915d8..2eb0d68cfaca 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -2288,150 +2288,202 @@ fail1: } #ifdef IPA_OFFLOAD +#ifdef QCA_WIFI_3_0 /** - * htt_rx_ipa_uc_attach() - attach htt ipa uc rx resource + * htt_rx_ipa_uc_alloc_wdi2_rsc() - Allocate WDI2.0 resources * @pdev: htt context - * @rx_ind_ring_size: rx ring size + * @rx_ind_ring_elements: rx ring elements * * Return: 0 success */ -int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, +int htt_rx_ipa_uc_alloc_wdi2_rsc(struct htt_pdev_t *pdev, unsigned int rx_ind_ring_elements) { - pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr = + /* Allocate RX2 indication ring */ + /* RX2 IND ring element + * 4bytes: pointer + * 2bytes: VDEV ID + * 2bytes: length */ + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr = cdf_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, + &pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx_ind_ring_base), + rx2_ind_ring_base), memctx)); - if (!pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { + if (!pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { cdf_print("%s: RX IND RING alloc fail", __func__); return -ENOBUFS; } /* RX indication ring size, by bytes */ - pdev->ipa_uc_rx_rsc.rx_ind_ring_size = + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size = rx_ind_ring_elements * sizeof(struct ipa_uc_rx_ring_elem_t); - cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr, - pdev->ipa_uc_rx_rsc.rx_ind_ring_size); + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size); /* Allocate RX process done index */ - pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr = + pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr = cdf_os_mem_alloc_consistent( pdev->osdev, 4, - &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, + &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, cdf_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) { + if (!pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { cdf_print("%s: RX PROC DONE IND alloc fail", __func__); cdf_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, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx_ind_ring_base), + rx2_ind_ring_base), memctx)); return -ENOBUFS; } - cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr, 4); + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr, 4); + return 0; +} +#else +int htt_rx_ipa_uc_alloc_wdi2_rsc(struct htt_pdev_t *pdev, + unsigned int rx_ind_ring_elements) +{ + return 0; +} +#endif - pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr = +/** + * htt_rx_ipa_uc_attach() - attach htt ipa uc rx resource + * @pdev: htt context + * @rx_ind_ring_size: rx ring size + * + * Return: 0 success + */ +int htt_rx_ipa_uc_attach(struct htt_pdev_t *pdev, + unsigned int rx_ind_ring_elements) +{ + int ret = 0; + /* 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 = cdf_os_mem_alloc_consistent( pdev->osdev, rx_ind_ring_elements * - sizeof(cdf_dma_addr_t), - &pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + sizeof(struct ipa_uc_rx_ring_elem_t), + &pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx2_ind_ring_base), + rx_ind_ring_base), memctx)); - if (!pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { + if (!pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { cdf_print("%s: RX IND RING alloc fail", __func__); return -ENOBUFS; } /* RX indication ring size, by bytes */ - pdev->ipa_uc_rx_rsc.rx2_ind_ring_size = - rx_ind_ring_elements * sizeof(cdf_dma_addr_t); - cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_size); + pdev->ipa_uc_rx_rsc.rx_ind_ring_size = + rx_ind_ring_elements * sizeof(struct ipa_uc_rx_ring_elem_t); + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx_ind_ring_size); /* Allocate RX process done index */ - pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr = + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr = cdf_os_mem_alloc_consistent( pdev->osdev, 4, - &pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, + &pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. rx_ipa_prc_done_idx), memctx)); - if (!pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { + if (!pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr) { cdf_print("%s: RX PROC DONE IND alloc fail", __func__); cdf_os_mem_free_consistent( pdev->osdev, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + 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, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx2_ind_ring_base), + rx_ind_ring_base), memctx)); return -ENOBUFS; } - cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr, 4); - return 0; + cdf_mem_zero(pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr, 4); + + ret = htt_rx_ipa_uc_alloc_wdi2_rsc(pdev, rx_ind_ring_elements); + return ret; } -int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) +#ifdef QCA_WIFI_3_0 +/** + * htt_rx_ipa_uc_free_wdi2_rsc() - Free WDI2.0 resources + * @pdev: htt context + * + * Return: None + */ +void htt_rx_ipa_uc_free_wdi2_rsc(struct htt_pdev_t *pdev) { - if (pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { + if (pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { cdf_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, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, + pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx_ind_ring_base), + rx2_ind_ring_base), memctx)); } - if (pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr) { + if (pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { cdf_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, + pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. rx_ipa_prc_done_idx), memctx)); } - if (pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr) { +} +#else +void htt_rx_ipa_uc_free_wdi2_rsc(struct htt_pdev_t *pdev) +{ + return; +} +#endif + +int htt_rx_ipa_uc_detach(struct htt_pdev_t *pdev) +{ + if (pdev->ipa_uc_rx_rsc.rx_ind_ring_base.vaddr) { cdf_os_mem_free_consistent( pdev->osdev, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_size, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.vaddr, - pdev->ipa_uc_rx_rsc.rx2_ind_ring_base.paddr, + 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, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. - rx2_ind_ring_base), + rx_ind_ring_base), memctx)); } - if (pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.vaddr) { + if (pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.vaddr) { cdf_os_mem_free_consistent( pdev->osdev, 4, pdev->ipa_uc_rx_rsc. rx_ipa_prc_done_idx.vaddr, - pdev->ipa_uc_rx_rsc.rx2_ipa_prc_done_idx.paddr, + pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr, cdf_get_dma_mem_context((&pdev->ipa_uc_rx_rsc. rx2_ipa_prc_done_idx), memctx)); } + + htt_rx_ipa_uc_free_wdi2_rsc(pdev); return 0; } #endif /* IPA_OFFLOAD */ diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index 57cd62a8c6dc..96135a48ad44 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -833,17 +833,19 @@ void htt_tx_desc_display(void *tx_desc) #endif #ifdef IPA_OFFLOAD +#ifdef QCA_WIFI_2_0 /** - * htt_tx_ipa_uc_attach() - attach htt ipa uc tx resource + * htt_tx_ipa_uc_wdi_tx_buf_alloc() - Alloc WDI TX buffers * @pdev: htt context - * @uc_tx_buf_sz: single tx buffer size - * @uc_tx_buf_cnt: total tx buffer count - * @uc_tx_partition_base: tx buffer partition start + * @uc_tx_buf_sz: TX buffer size + * @uc_tx_buf_cnt: TX Buffer count + * @uc_tx_partition_base: IPA UC TX partition base value + * + * Allocate WDI TX buffers. Also note Rome supports only WDI 1.0. * * Return: 0 success - * ENOBUFS No memory fail */ -int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, +int htt_tx_ipa_uc_wdi_tx_buf_alloc(struct htt_pdev_t *pdev, unsigned int uc_tx_buf_sz, unsigned int uc_tx_buf_cnt, unsigned int uc_tx_partition_base) @@ -853,52 +855,68 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, cdf_dma_addr_t buffer_paddr; uint32_t *header_ptr; uint32_t *ring_vaddr; - int return_code = 0; - unsigned int tx_comp_ring_size; +#define IPA_UC_TX_BUF_FRAG_DESC_OFFSET 16 +#define IPA_UC_TX_BUF_FRAG_HDR_OFFSET 32 - /* Allocate CE Write Index WORD */ - pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr = - cdf_os_mem_alloc_consistent( - pdev->osdev, - 4, - &pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, - cdf_get_dma_mem_context( - (&pdev->ipa_uc_tx_rsc.tx_ce_idx), - memctx)); - if (!pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { - cdf_print("%s: CE Write Index WORD alloc fail", __func__); - return -ENOBUFS; - } + 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 = cdf_nbuf_alloc(pdev->osdev, + uc_tx_buf_sz, 0, 4, false); + if (!buffer_vaddr) { + cdf_print("%s: TX BUF alloc fail, loop index: %d", + __func__, tx_buffer_count); + return tx_buffer_count; + } - /* Allocate TX COMP Ring */ - tx_comp_ring_size = uc_tx_buf_cnt * sizeof(cdf_nbuf_t); - pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr = - cdf_os_mem_alloc_consistent( - pdev->osdev, - tx_comp_ring_size, - &pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, - cdf_get_dma_mem_context((&pdev->ipa_uc_tx_rsc. - tx_comp_base), - memctx)); - if (!pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { - cdf_print("%s: TX COMP ring alloc fail", __func__); - return_code = -ENOBUFS; - goto free_tx_ce_idx; - } + /* Init buffer */ + cdf_mem_zero(cdf_nbuf_data(buffer_vaddr), uc_tx_buf_sz); + header_ptr = (uint32_t *) cdf_nbuf_data(buffer_vaddr); - cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, tx_comp_ring_size); + /* HTT control header */ + *header_ptr = HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT; + header_ptr++; - /* Allocate TX BUF vAddress Storage */ - pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg = - (cdf_nbuf_t *) cdf_mem_malloc(uc_tx_buf_cnt * - sizeof(cdf_nbuf_t)); - if (!pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg) { - cdf_print("%s: TX BUF POOL vaddr storage alloc fail", __func__); - return_code = -ENOBUFS; - goto free_tx_comp_base; + /* PKT ID */ + *header_ptr |= ((uint16_t) uc_tx_partition_base + + tx_buffer_count) << 16; + + cdf_nbuf_map(pdev->osdev, buffer_vaddr, CDF_DMA_BIDIRECTIONAL); + buffer_paddr = cdf_nbuf_get_frag_paddr_lo(buffer_vaddr, 0); + header_ptr++; + *header_ptr = (uint32_t) (buffer_paddr + + IPA_UC_TX_BUF_FRAG_DESC_OFFSET); + header_ptr++; + *header_ptr = 0xFFFFFFFF; + + /* FRAG Header */ + header_ptr++; + *header_ptr = buffer_paddr + IPA_UC_TX_BUF_FRAG_HDR_OFFSET; + + *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++; } - cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg, - uc_tx_buf_cnt * sizeof(cdf_nbuf_t)); + return tx_buffer_count; +} +#else +int htt_tx_ipa_uc_wdi_tx_buf_alloc(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; + cdf_nbuf_t buffer_vaddr; + uint32_t buffer_paddr; + uint32_t *header_ptr; + uint32_t *ring_vaddr; +#define IPA_UC_TX_BUF_FRAG_DESC_OFFSET 20 +#define IPA_UC_TX_BUF_FRAG_HDR_OFFSET 64 +#define IPA_UC_TX_BUF_TSO_HDR_SIZE 6 ring_vaddr = pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr; /* Allocate TX buffers as many as possible */ @@ -909,7 +927,7 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, if (!buffer_vaddr) { cdf_print("%s: TX BUF alloc fail, loop index: %d", __func__, tx_buffer_count); - return 0; + return tx_buffer_count; } /* Init buffer */ @@ -930,7 +948,8 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, /* Frag Desc Pointer */ /* 64bits descriptor, Low 32bits */ - *header_ptr = (uint32_t) (buffer_paddr + 20); + *header_ptr = (uint32_t) (buffer_paddr + + IPA_UC_TX_BUF_FRAG_DESC_OFFSET); header_ptr++; /* 64bits descriptor, high 32bits */ @@ -943,8 +962,8 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, /* FRAG Header */ /* 6 words TSO header */ - header_ptr += 6; - *header_ptr = buffer_paddr + 64; + header_ptr += IPA_UC_TX_BUF_TSO_HDR_SIZE; + *header_ptr = buffer_paddr + IPA_UC_TX_BUF_FRAG_HDR_OFFSET; *ring_vaddr = buffer_paddr; pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg[tx_buffer_count] = @@ -953,8 +972,75 @@ int htt_tx_ipa_uc_attach(struct htt_pdev_t *pdev, ring_vaddr += 2; } + return tx_buffer_count; +} +#endif + +/** + * htt_tx_ipa_uc_attach() - attach htt ipa uc tx resource + * @pdev: htt context + * @uc_tx_buf_sz: single tx buffer size + * @uc_tx_buf_cnt: total tx buffer count + * @uc_tx_partition_base: tx buffer partition start + * + * Return: 0 success + * ENOBUFS No memory fail + */ +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 return_code = 0; + unsigned int tx_comp_ring_size; + + /* Allocate CE Write Index WORD */ + pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + 4, + &pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr, + cdf_get_dma_mem_context( + (&pdev->ipa_uc_tx_rsc.tx_ce_idx), + memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_ce_idx.vaddr) { + cdf_print("%s: CE Write Index WORD alloc fail", __func__); + return -ENOBUFS; + } + + /* Allocate TX COMP Ring */ + tx_comp_ring_size = uc_tx_buf_cnt * sizeof(cdf_nbuf_t); + pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr = + cdf_os_mem_alloc_consistent( + pdev->osdev, + tx_comp_ring_size, + &pdev->ipa_uc_tx_rsc.tx_comp_base.paddr, + cdf_get_dma_mem_context((&pdev->ipa_uc_tx_rsc. + tx_comp_base), + memctx)); + if (!pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr) { + cdf_print("%s: TX COMP ring alloc fail", __func__); + return_code = -ENOBUFS; + goto free_tx_ce_idx; + } + + cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_comp_base.vaddr, tx_comp_ring_size); + + /* Allocate TX BUF vAddress Storage */ + pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg = + (cdf_nbuf_t *) cdf_mem_malloc(uc_tx_buf_cnt * + sizeof(cdf_nbuf_t)); + if (!pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg) { + cdf_print("%s: TX BUF POOL vaddr storage alloc fail", __func__); + return_code = -ENOBUFS; + goto free_tx_comp_base; + } + cdf_mem_zero(pdev->ipa_uc_tx_rsc.tx_buf_pool_vaddr_strg, + uc_tx_buf_cnt * sizeof(cdf_nbuf_t)); + + pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = htt_tx_ipa_uc_wdi_tx_buf_alloc( + pdev, uc_tx_buf_sz, uc_tx_buf_cnt, uc_tx_partition_base); - pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; return 0; -- cgit v1.2.3 From aab2b6f3f226eed30708bb5e20fd8c6e5a300a0f Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Wed, 9 Dec 2015 19:01:06 -0800 Subject: qcacld-3.0: Fix the crash in wlan re-initialization Perform cfg download before the SME config update since the SME config update operation accesses the cfg database. Change-Id: Ic2d5b6d192ed164b20011b3eeaea6126951b87e8 CRs-Fixed: 948896 --- core/hdd/src/wlan_hdd_power.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 479fbb6db690..2c00f1fceedf 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1463,18 +1463,21 @@ CDF_STATUS hdd_wlan_re_init(void *hif_sc) goto err_cds_close; } - /* Set the SME configuration parameters. */ - cdf_status = hdd_set_sme_config(pHddCtx); - if (CDF_STATUS_SUCCESS != cdf_status) { - hddLog(CDF_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", - __func__); + cdf_status = cds_pre_enable(pHddCtx->pcds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + hdd_alert("cds_pre_enable failed"); goto err_cds_close; } - cdf_status = cds_pre_enable(pHddCtx->pcds_context); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { - hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_pre_enable failed", - __func__); + /* + * Note that the cds_pre_enable() 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. + * Set the SME configuration parameters. + */ + cdf_status = hdd_set_sme_config(pHddCtx); + if (CDF_STATUS_SUCCESS != cdf_status) { + hdd_alert("Failed hdd_set_sme_config"); goto err_cds_close; } -- cgit v1.2.3 From 8cb3c6214bd0e1defe5968dc5669b7702ca9f58e Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Tue, 15 Dec 2015 16:51:18 -0800 Subject: qcacld-3.0: Fix the Rx data rate issue in 11b mode Check for VHT caps in vendor specific IE only if the dot11mode is set to 11ac or auto, so that the vht caps are included in association reuest frame only if the dot11 mode is 11ac. Change-Id: If72117e5a46a754ae602dabd596a2ad8aac33d2e CRs-Fixed: 952134 --- core/mac/src/pe/lim/lim_assoc_utils.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index b21a708b76fa..c981c28b1d50 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -3382,6 +3382,7 @@ lim_check_and_announce_join_success(tpAniSirGlobal mac_ctx, uint32_t *noa2_duration_from_beacon = NULL; uint32_t noa; uint32_t total_num_noa_desc = 0; + uint32_t selfStaDot11Mode = 0; cdf_mem_copy(current_ssid.ssId, session_entry->ssId.ssId, session_entry->ssId.length); @@ -3494,7 +3495,10 @@ lim_check_and_announce_join_success(tpAniSirGlobal mac_ctx, lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, (uint32_t *) &mlm_join_cnf); - if (beacon_probe_rsp->vendor2_ie.VHTCaps.present) { + wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); + + if ((IS_DOT11_MODE_VHT(selfStaDot11Mode)) && + beacon_probe_rsp->vendor2_ie.VHTCaps.present) { session_entry->is_vendor_specific_vhtcaps = true; session_entry->vendor_specific_vht_ie_type = beacon_probe_rsp->vendor2_ie.type; -- cgit v1.2.3 From bf650e252354f349f4ed83c5311255abf479b269 Mon Sep 17 00:00:00 2001 From: Orhan K AKYILDIZ Date: Thu, 17 Dec 2015 11:38:12 -0800 Subject: qcacld-3.0: Enable single-queu NAPI Enable single queue NAPI by default on HTT rx path only. As multi-queue NAPI is being delayed per dependencies, we would like to enable multi-queue NAPI by default tgo give it a soak time. Preliminary results show equivalent results with non-NAPI case. This update does not disable rx-thread or change RPS settings. Eventually with multi-queue NAPI, rx-threads are expected to be removed and RPS will be re-evaluated (it is expectyed that there would be no need for it). Change-Id: Id11e459ea2c0d47428ce7fbcaf628b16d015d70d CRs-Fixed: 953232 --- config/WCNSS_qcom_cfg.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index c652d36db4d0..61f498bed89e 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -464,7 +464,7 @@ isP2pDeviceAddrAdministrated=0 gEnableRxThread=1 #Enable NAPI -gEnableNAPI=0 +gEnableNAPI=1 # Set Thermal Power limit TxPower2g=10 -- cgit v1.2.3 From e58ba6b4ebd5ed9881bc52736cedad89f824f7ed Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Tue, 1 Dec 2015 19:51:36 +0530 Subject: qcacld-3.0: while processing rx mgmt frame get vdev using bssid During processing of rx mgmt frame, host try to get the vdev using destination address but for BC frame it can't find the vdev and iface too, so desired functionality will not work. As a part of this fix, host is getting vdev using bssid. Change-Id: I52884faffc8c5fc8c2f9dcb4308e6f0739f80fe7 CRs-Fixed: 945583 --- core/wma/src/wma_mgmt.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 1171b7ad2dd3..bad92a00f21c 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -2952,7 +2952,7 @@ wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh, return true; } - vdev = wma_find_vdev_by_addr(cds_ctx, wh->i_addr2, &vdev_id); + vdev = wma_find_vdev_by_bssid(cds_ctx, wh->i_addr3, &vdev_id); if (!vdev) { WMA_LOGE("%s: Failed to find vdev", __func__); return true; @@ -3108,7 +3108,7 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) { cds_pkt_return_packet(rx_pkt); return -EINVAL; - } + } } else { WMA_LOGE("Rx unprotected unicast mgmt frame"); rx_pkt->pkt_meta.dpuFeedback = @@ -3134,7 +3134,7 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL; wmi_mgmt_rx_hdr *hdr = NULL; struct wma_txrx_node *iface = NULL; - uint8_t vdev_id; + uint8_t vdev_id = WMA_INVALID_VDEV_ID; cds_pkt_t *rx_pkt; cdf_nbuf_t wbuf; struct ieee80211_frame *wh; @@ -3254,22 +3254,25 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, mgt_type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK; mgt_subtype = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - iface = wma_find_vdev_by_addr(wma_handle, wh->i_addr3, &vdev_id); - rx_pkt->pkt_meta.sessionId = vdev_id; - #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)) { - if (iface && iface->rmfEnabled) { - status = wma_process_rmf_frame(wma_handle, - iface, wh, rx_pkt, wbuf); - if (status != 0) - return status; + if (wma_find_vdev_by_bssid( + wma_handle, wh->i_addr3, &vdev_id)) { + iface = &(wma_handle->interfaces[vdev_id]); + if (iface->rmfEnabled) { + status = wma_process_rmf_frame(wma_handle, + iface, wh, rx_pkt, wbuf); + if (status != 0) + return status; + } } } #endif /* WLAN_FEATURE_11W */ + rx_pkt->pkt_meta.sessionId = + (vdev_id == WMA_INVALID_VDEV_ID ? 0 : vdev_id); wma_handle->mgmt_rx(wma_handle, rx_pkt); return 0; } -- cgit v1.2.3 From 957f4bdb8484549cbec1a1b91d8bc327f9927283 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 16 Dec 2015 21:27:38 -0800 Subject: Release 5.0.0.151 Release 5.0.0.151 Change-Id: Icc3cf83583f5131f01f9ef7a0265409af71c06d0 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 7852513950e3..48950fd0a75c 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 150 +#define QWLAN_VERSION_BUILD 151 -#define QWLAN_VERSIONSTR "5.0.0.150" +#define QWLAN_VERSIONSTR "5.0.0.151" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 04b215801228eaf5ec6c710106f81a8cb7ad01a5 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Mon, 21 Dec 2015 21:42:42 -0800 Subject: Release 5.0.0.152 Release 5.0.0.152 Change-Id: I5fbaf62af2831499f39274f3ffdad0979b467d68 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 48950fd0a75c..3ee60f0324b9 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 151 +#define QWLAN_VERSION_BUILD 152 -#define QWLAN_VERSIONSTR "5.0.0.151" +#define QWLAN_VERSIONSTR "5.0.0.152" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 200b6e60485a2c18d5652ba4eee26d1436c5de56 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Mon, 26 Oct 2015 20:52:51 -0700 Subject: qcacld-3.0: add support for IBSS+STA concurrency Make necessary changes to support IBSS+STA concurrency for SCC and 2G+5G MCC. Don't support intraband MCC due to known limitation for this specific concurrency. Change-Id: I325b5f51abeee3da0a75f90723c8b882f71dbef2 CRs-Fixed: 953788 --- core/cds/src/cds_concurrency.c | 24 ++++++++++++++++++------ core/hdd/src/wlan_hdd_assoc.c | 13 ++++++++++--- core/hdd/src/wlan_hdd_cfg80211.c | 5 +++-- core/sme/src/csr/csr_api_roam.c | 1 + core/sme/src/csr/csr_util.c | 4 +++- core/wma/src/wma_dev_if.c | 16 +++++++--------- 6 files changed, 42 insertions(+), 21 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index afd6f9160d9e..48694243c276 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -1817,10 +1817,10 @@ next_action_two_connection_table[CDS_MAX_ONE_CONNECTION_MODE][CDS_MAX_BAND] = { [CDS_SAP_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, [CDS_SAP_5_1x1] = {CDS_DBS, CDS_NOP}, [CDS_SAP_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, - [CDS_IBSS_24_1x1] = {CDS_NOP, CDS_NOP}, - [CDS_IBSS_24_2x2] = {CDS_NOP, CDS_NOP}, - [CDS_IBSS_5_1x1] = {CDS_NOP, CDS_NOP}, - [CDS_IBSS_5_2x2] = {CDS_NOP, CDS_NOP}, + [CDS_IBSS_24_1x1] = {CDS_NOP, CDS_DBS}, + [CDS_IBSS_24_2x2] = {CDS_NOP, CDS_DBS_DOWNGRADE}, + [CDS_IBSS_5_1x1] = {CDS_DBS, CDS_NOP}, + [CDS_IBSS_5_2x2] = {CDS_DBS_DOWNGRADE, CDS_NOP}, }; /** @@ -3351,11 +3351,17 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) void cds_incr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, uint8_t session_id) { + /* + * Need to aquire mutex as entire functionality in this function + * is in critical section + */ + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: case CDF_P2P_GO_MODE: case CDF_SAP_MODE: + case CDF_IBSS_MODE: hdd_ctx->no_of_active_sessions[mode]++; break; default: @@ -3368,7 +3374,6 @@ void cds_incr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, * Let us set the PCL to the FW before updating the connection * info structure about the new connection. */ - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); if (mode == CDF_STA_MODE) { /* Set PCL of STA to the FW */ cds_soc_set_pcl(hdd_ctx, mode); @@ -3503,7 +3508,6 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, { CDF_STATUS cdf_status; - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); cds_decr_active_session(hdd_ctx, mode, session_id); /* * After the removal of this connection, we need to check if @@ -3519,6 +3523,7 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, * given to the FW. After setting the PCL, we need to restore * the entry that we have saved before. */ + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); cds_set_pcl_for_existing_combo(hdd_ctx, CDS_STA_MODE); /* do we need to change the HW mode */ if (cds_need_opportunistic_upgrade(hdd_ctx)) { @@ -3552,11 +3557,17 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, void cds_decr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, uint8_t session_id) { + /* + * Need to aquire mutex as entire functionality in this function + * is in critical section + */ + cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: case CDF_P2P_GO_MODE: case CDF_SAP_MODE: + case CDF_IBSS_MODE: if (hdd_ctx->no_of_active_sessions[mode]) hdd_ctx->no_of_active_sessions[mode]--; break; @@ -3566,6 +3577,7 @@ void cds_decr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, cds_info("No.# of active sessions for mode %d = %d", mode, hdd_ctx->no_of_active_sessions[mode]); cds_decr_connection_count(hdd_ctx, session_id); + cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); } /** diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index a4afd07c8be6..a23efed55b9d 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -814,8 +814,8 @@ static void hdd_send_association_event(struct net_device *dev, #endif } else if (eConnectionState_IbssConnected == /* IBss Associated */ pHddStaCtx->conn_info.connState) { - cds_incr_active_session(pHddCtx, pAdapter->device_mode, - pAdapter->sessionId); + cds_update_connection_info(pHddCtx, + pAdapter->sessionId); memcpy(wrqu.ap_addr.sa_data, pHddStaCtx->conn_info.bssId.bytes, ETH_ALEN); pr_info("wlan: new IBSS connection to " MAC_ADDRESS_STR "\n", @@ -2427,7 +2427,14 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, pHddCtx->wiphy, bss); } - + if (eCSR_ROAM_RESULT_IBSS_STARTED == roamResult) { + cds_incr_active_session(pHddCtx, pAdapter->device_mode, + pAdapter->sessionId); + } else if (eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS == roamResult || + eCSR_ROAM_RESULT_IBSS_COALESCED == roamResult) { + cds_update_connection_info(pHddCtx, + pAdapter->sessionId); + } break; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5b117225fd47..b904e4ddc6a8 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -510,7 +510,7 @@ static struct ieee80211_iface_combination /* ADHOC */ { .limits = wlan_hdd_adhoc_iface_limit, - .num_different_channels = 1, + .num_different_channels = 2, .max_interfaces = 2, .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit), }, @@ -5857,7 +5857,8 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) || - (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)) { + (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) || + (pAdapter->device_mode == WLAN_HDD_IBSS)) { hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 5ac222dabd40..60a45ad85bb4 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -5811,6 +5811,7 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, csr_roam_call_callback(mac_ctx, session_id, NULL, cmd->u.roamCmd.roamId, eCSR_ROAM_IBSS_LEAVE, eCSR_ROAM_RESULT_IBSS_STOP); + session->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; break; case eCsrForcedDisassocMICFailure: csr_roam_state_change(mac_ctx, eCSR_ROAMING_STATE_IDLE, diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 743f3cc01a93..a21cad315d38 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1905,7 +1905,8 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, } break; case CDF_IBSS_MODE: - if ((bss_persona == CDF_IBSS_MODE) && (connect_state != + if ((bss_persona == CDF_IBSS_MODE) && + (connect_state == eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED)) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, @@ -2231,6 +2232,7 @@ CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channel break; case CDF_SAP_MODE: + case CDF_IBSS_MODE: break; case CDF_P2P_GO_MODE: diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 2fa2461ac8ab..6876ffa240b3 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -2924,8 +2924,13 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) tSetBssKeyParams key_info; struct sir_hw_mode_params hw_mode = {0}; - WMA_LOGD("%s: add_bss->sessionId = %d", __func__, add_bss->sessionId); - vdev_id = add_bss->sessionId; + vdev = wma_find_vdev_by_addr(wma, add_bss->selfMacAddr, &vdev_id); + if (!vdev) { + WMA_LOGE("%s: vdev not found for vdev id %d.", + __func__, vdev_id); + goto send_fail_resp; + } + WMA_LOGD("%s: add_bss->sessionId = %d", __func__, vdev_id); pdev = cds_get_context(CDF_MODULE_ID_TXRX); if (NULL == pdev) { @@ -2934,13 +2939,6 @@ static void wma_add_bss_ibss_mode(tp_wma_handle wma, tpAddBssParams add_bss) } 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)) { -- cgit v1.2.3 From 9cf62384ba68edf3d896c5aa223192b1c5faa4b1 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Sun, 15 Nov 2015 23:41:56 -0800 Subject: qcacld-3.0: Add support for IBSS+SAP Provide necessary code changes to support IBSS+SAP concurrency for emulation platform only. Change-Id: I76dc023bd48ee79ba706f5a7009b1d8462c6b712 CRs-Fixed: 953796 --- core/cds/src/cds_concurrency.c | 16 +++++++++++++++- core/hdd/src/wlan_hdd_cfg80211.c | 15 +++++++++++++++ core/sme/src/csr/csr_util.c | 10 ++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 48694243c276..fe41bb41c7e7 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -4660,11 +4660,25 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, cds_err("No IBSS, we have concurrent connections already"); goto done; } +#ifndef QCA_WIFI_3_0_EMU if (CDS_STA_MODE != conc_connection_list[0].mode) { /* err msg */ - cds_err("No IBSS, we have a non STA connection"); + cds_err("No IBSS, we've a non-STA connection"); + goto done; + } +#else + if (CDS_STA_MODE != conc_connection_list[0].mode && + CDS_SAP_MODE != conc_connection_list[0].mode) { + /* err msg */ + cds_err("No IBSS, we've a non-STA/SAP conn"); goto done; } +#endif + /* + * This logic protects STA and IBSS to come up on same + * band. If requirement changes then this condition + * needs to be removed + */ if (channel && (conc_connection_list[0].chan != channel) && CDS_IS_SAME_BAND_CHANNELS( diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b904e4ddc6a8..f2cbcda32a63 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -374,6 +374,7 @@ static const struct ieee80211_iface_limit }, }; +#ifndef QCA_WIFI_3_0_EMU /* ADHOC (IBSS) limit */ static const struct ieee80211_iface_limit wlan_hdd_adhoc_iface_limit[] = { @@ -386,6 +387,20 @@ static const struct ieee80211_iface_limit .types = BIT(NL80211_IFTYPE_ADHOC), }, }; +#else +/* ADHOC (IBSS) limit */ +static const struct ieee80211_iface_limit + wlan_hdd_adhoc_iface_limit[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC), + }, +}; +#endif /* AP ( + AP ) combination */ static const struct ieee80211_iface_limit diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index a21cad315d38..8c9c1d869cec 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1877,10 +1877,13 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, #endif if ((bss_persona == CDF_IBSS_MODE) && (connect_state != temp)) { + /* allow IBSS+SAP for Emulation only */ +#ifndef QCA_WIFI_3_0_EMU CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - FL("Can't start GO")); + FL("Can't start SAP")); return CDF_STATUS_E_FAILURE; +#endif } break; @@ -1916,10 +1919,13 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, (bss_persona == CDF_SAP_MODE)) && (connect_state != eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + /* allow IBSS+SAP for Emulation only */ +#ifndef QCA_WIFI_3_0_EMU CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - FL("Can't start GO")); + FL("Can't start GO/SAP")); return CDF_STATUS_E_FAILURE; +#endif } break; case CDF_P2P_CLIENT_MODE: -- cgit v1.2.3 From d9fdf894a910d4baaba41d0516875e946eee9bb5 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Tue, 17 Nov 2015 17:42:59 -0800 Subject: qcacld-3.0: dump IBSS concurrency information Dump IBSS related concurrency information Change-Id: Id69bfa3681f38f9af376590f6bcc668f146ed9e8 CRs-fixed: 941652 --- core/cds/src/cds_concurrency.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index fe41bb41c7e7..6d24eb1b84c5 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2879,6 +2879,11 @@ static void cds_dump_legacy_concurrency(hdd_context_t *hdd_ctx, { const char *cc_mode = "Standalone"; + if ((sta_channel == 0) && (ap_channel == 0) && (p2p_channel == 0)) { + cds_err("IBSS standalone"); + hdd_ctx->mcc_mode = 0; + return; + } if (sta_channel > 0) { if (ap_channel > 0) { if (p2p_channel > 0) { @@ -3027,7 +3032,6 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) } break; case WLAN_HDD_IBSS: - return; /* skip printing station message below */ default: break; } -- cgit v1.2.3 From 031007422b8529fb8ee72e18e9355f14c9d39e2f Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Mon, 21 Dec 2015 12:17:16 -0800 Subject: qcacld-3.0: Do not allow STA scan on IBSS channel's band As per the requirement when IBSS connection co-exist with STA connection and scan request is coming from STA adapter, don't include those channels which fall in same band as IBSS channel's band. Change-Id: Ifb42ea6b463bd5020bf544eee504b9c3ceefcfc2 CRs-Fixed: 953788 --- core/cds/inc/cds_concurrency.h | 1 + core/cds/src/cds_concurrency.c | 41 +++++++++++++++ core/sme/src/csr/csr_api_scan.c | 114 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 261b97460d3d..bb799cb35c6a 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -688,6 +688,7 @@ CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, CDF_STATUS cds_current_connections_update(uint32_t session_id, uint8_t channel, enum cds_conn_update_reason); +bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel); #ifdef MPC_UT_FRAMEWORK CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 6d24eb1b84c5..2f97b411858d 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3245,6 +3245,7 @@ void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) case CDF_P2P_CLIENT_MODE: case CDF_P2P_GO_MODE: case CDF_SAP_MODE: + case CDF_IBSS_MODE: hdd_ctx->concurrency_mode |= (1 << mode); hdd_ctx->no_of_open_sessions[mode]++; break; @@ -4557,6 +4558,41 @@ bool cds_allow_new_home_channel(hdd_context_t *hdd_ctx, return status; } +/** + * cds_is_ibss_conn_exist() - to check if IBSS connection already present + * @hdd_ctx: pointer to hdd context + * @ibss_channel: pointer to ibss channel which needs to be filled + * + * this routine will check if IBSS connection already exist or no. If it + * exist then this routine will return true and fill the ibss_channel value. + * + * Return: true if ibss connection exist else false + */ +bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel) +{ + uint32_t count = 0, index = 0; + uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + bool status = false; + if ((NULL == hdd_ctx) || (NULL == ibss_channel)) { + cds_err("Null pointer error"); + return false; + } + count = cds_mode_specific_connection_count(hdd_ctx, + CDS_IBSS_MODE, list); + if (count == 0) { + /* No IBSS connection */ + status = false; + } else if (count == 1) { + *ibss_channel = conc_connection_list[list[index]].chan; + status = true; + } else { + *ibss_channel = conc_connection_list[list[index]].chan; + cds_notice("Multiple IBSS connections, picking first one"); + status = true; + } + return status; +} + /** * cds_allow_concurrency() - Check for allowed concurrency * combination @@ -4723,6 +4759,11 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, cds_err("No IBSS + STA SCC/MCC, IBSS is on DFS channel"); goto done; } + /* + * This logic protects STA and IBSS to come up on same + * band. If requirement changes then this condition + * needs to be removed + */ if ((conc_connection_list[0].chan != channel) && CDS_IS_SAME_BAND_CHANNELS( conc_connection_list[0].chan, channel)) { diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 2ca632d2da50..921288b9604b 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -5273,6 +5273,99 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, dst_req->ChannelInfo.numOfChannels = new_index; } +/** + * csr_scan_filter_ibss_chnl_band() - filter all channels which matches IBSS + * channel's band + * @mac_ctx: pointer to mac context + * @ibss_channel: Given IBSS channel + * @dst_req: destination scan request + * + * when ever IBSS connection already exist, STA should not scan the channels + * which fall under same band as IBSS channel's band. this routine will filter + * out those channels + * + * Return: true if success otherwise false for any failure + */ +static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, + uint8_t ibss_channel, tCsrScanRequest *dst_req) { + uint8_t valid_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + uint8_t filtered_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + uint32_t filter_chnl_len = 0, i = 0; + uint32_t valid_chnl_len = WNI_CFG_VALID_CHANNEL_LIST_LEN; + + if (ibss_channel == 0) { + sms_log(mac_ctx, LOG1, + FL("Nothing to filter as no IBSS session")); + return true; + } + + if (!dst_req) { + sms_log(mac_ctx, LOGE, + FL("No valid scan requests")); + return false; + } + /* + * In case of concurrent IBSS session exist, scan only + * those channels which are not in IBSS channel's band. + * In case if no-concurrent IBSS session exist then scan + * full band + */ + if ((dst_req->ChannelInfo.numOfChannels == 0)) { + csr_get_cfg_valid_channels(mac_ctx, valid_chnl_list, + &valid_chnl_len); + } else { + valid_chnl_len = (WNI_CFG_VALID_CHANNEL_LIST_LEN > + dst_req->ChannelInfo.numOfChannels) ? + dst_req->ChannelInfo.numOfChannels : + WNI_CFG_VALID_CHANNEL_LIST_LEN; + cdf_mem_copy(valid_chnl_list, dst_req->ChannelInfo.ChannelList, + valid_chnl_len); + } + for (i = 0; i < valid_chnl_len; i++) { + /* + * Don't allow DSRC channel when IBSS concurrent connection + * is up + */ + if (valid_chnl_list[i] >= MIN_11P_CHANNEL) + continue; + if (CDS_IS_CHANNEL_5GHZ(ibss_channel) && + CDS_IS_CHANNEL_24GHZ(valid_chnl_list[i])) { + filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[i]; + filter_chnl_len++; + } else if (CDS_IS_CHANNEL_24GHZ(ibss_channel) && + CDS_IS_CHANNEL_5GHZ(valid_chnl_list[i])) { + filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[i]; + filter_chnl_len++; + } + } + if (filter_chnl_len == 0) { + sms_log(mac_ctx, LOGE, + FL("there no channels to scan due to IBSS session")); + return false; + } + + if (dst_req->ChannelInfo.ChannelList) { + cdf_mem_free(dst_req->ChannelInfo.ChannelList); + dst_req->ChannelInfo.ChannelList = NULL; + dst_req->ChannelInfo.numOfChannels = 0; + } + + dst_req->ChannelInfo.ChannelList = + cdf_mem_malloc(filter_chnl_len * + sizeof(*dst_req->ChannelInfo.ChannelList)); + dst_req->ChannelInfo.numOfChannels = filter_chnl_len; + if (NULL == dst_req->ChannelInfo.ChannelList) { + sms_log(mac_ctx, LOGE, + FL("Memory allocation failed")); + return false; + } + cdf_mem_copy(dst_req->ChannelInfo.ChannelList, filtered_chnl_list, + filter_chnl_len); + return true; +} + /** * csr_scan_copy_request() - Function to copy scan request * @mac_ctx : pointer to Global Mac Structure @@ -5292,6 +5385,7 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, uint32_t index = 0; uint32_t new_index = 0; CHANNEL_STATE channel_state; + uint8_t ibss_channel = 0; bool skip_dfs_chnl = mac_ctx->roam.configParam.initial_scan_no_dfs_chnl || !mac_ctx->scan.fEnableDFSChnlScan; @@ -5389,6 +5483,26 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, new_index; } } /* Allocate memory for Channel List */ + + /* + * If IBSS concurrent connection exist, and if the scan + * request comes from STA adapter then we need to filter + * out IBSS channel's band otherwise it will cause issue + * in IBSS+STA concurrency + */ + if (true == cds_is_ibss_conn_exist(mac_ctx->hHdd, &ibss_channel)) { + sms_log(mac_ctx, LOG1, + FL("Conc IBSS exist, channel list will be modified")); + } + + if ((ibss_channel > 0) && + (false == csr_scan_filter_ibss_chnl_band(mac_ctx, + ibss_channel, dst_req))) { + sms_log(mac_ctx, LOGE, + FL("Can't filter channels due to IBSS")); + goto complete; + } + if (src_req->SSIDs.numOfSSIDs == 0) { dst_req->SSIDs.numOfSSIDs = 0; dst_req->SSIDs.SSIDList = NULL; -- cgit v1.2.3 From 98894948100b57fb82223a7742ea6d4d0c2e35be Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Wed, 9 Dec 2015 19:59:52 -0800 Subject: qcacld-3.0: Don't remove p2p device adapter when SAP comes up With current code, as soon as change interface command comes to convert interface type to AP, it removes p2p device adapter which is not required. In new platform, various concurrencies are supported which includes SAP+GO, SAP+STA+GO, and so on. To make these concurrencies work properly, no longer remove the p2p device adapter when SAP comes up. Change-Id: Icb1729f25e0604e0c342a136d9b4cf332e50d7c8 CRs-Fixed: 953788 --- core/hdd/src/wlan_hdd_cfg80211.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index f2cbcda32a63..583dcc840948 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5915,33 +5915,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, 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, - true); - hdd_deinit_adapter(pHddCtx, - pP2pAdapter, true); - hdd_close_adapter(pHddCtx, - pP2pAdapter, - true); - } - } hdd_stop_adapter(pHddCtx, pAdapter, true); /* De-init the adapter */ -- cgit v1.2.3 From d32d7007fcdce4cc3992824773aa27fefa6f1821 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Fri, 18 Dec 2015 11:44:56 +0530 Subject: qcacld-3.0: Wait for MC thread clean-up during IBSS leave Ensure that wait for MC thread clean-up happens as part of IBSS leave so that by the time upper stack calls the change interface, we are all set to proceed further. CRs-Fixed: 949956 Change-Id: Ib0ee79fe38cbf3c462bd8157c4e014c086f5c29f --- core/hdd/src/wlan_hdd_cfg80211.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 583dcc840948..aa2004dc00ee 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -9320,6 +9320,7 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); int status; CDF_STATUS hal_status; + unsigned long rc; ENTER(); @@ -9364,6 +9365,18 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, hal_status); return -EAGAIN; } + + /* wait for mc thread to cleanup and then return to upper stack + * so by the time upper layer calls the change interface, we are + * all set to proceed further + */ + rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!rc) { + hdd_err("Failed to disconnect, timed out"); + return -ETIMEDOUT; + } + EXIT(); return 0; } -- cgit v1.2.3 From faa640a6aee1cbd7bf9d241d5ee63b510d5fce50 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Fri, 18 Dec 2015 12:07:22 +0530 Subject: qcacld-3.0: Remove usage of fixed broadcast sta id for IBSS Remove the usage of fixed broadcast sta id of 1 for IBSS. Fixed broadcast std id of 1 was getting used for IBSS since no concurrency was supported for IBSS earlier and sta id 1 was always used as broadcast sta id. Now with concurrency being allowed with IBSS, this fixed broadcast sta id cannot be used. Make the broadcast sta id dynamic. Change-Id: I79222e276fbdd41a8938a3a26e58af9335f17ade CRs-Fixed: 953523 --- core/hdd/inc/wlan_hdd_assoc.h | 4 ---- core/hdd/inc/wlan_hdd_main.h | 2 ++ core/hdd/src/wlan_hdd_assoc.c | 19 ++++++++++--------- core/hdd/src/wlan_hdd_tx_rx.c | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index 190e756a7cb8..b9a95785e119 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -51,10 +51,6 @@ /* 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 - /* Type Declarations */ /** * typedef eConnectionState - Connection states diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 7a311c2515ef..ec3e66d064d2 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -657,6 +657,8 @@ struct hdd_station_ctx { /* STA ctx debug variables */ int staDebugState; + + uint8_t broadcast_ibss_staid; }; #define BSS_STOP 0 diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index a23efed55b9d..4912c80661fe 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1093,12 +1093,11 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, #endif if (eCSR_ROAM_IBSS_LEAVE == roamStatus) { uint8_t i; - sta_id = IBSS_BROADCAST_STAID; + sta_id = pHddStaCtx->broadcast_ibss_staid; vstatus = hdd_roam_deregister_sta(pAdapter, sta_id); if (!CDF_IS_STATUS_SUCCESS(vstatus)) { - hddLog(LOGE, - FL("hdd_roam_deregister_sta() failed for staID %d Status=%d [0x%x]"), - sta_id, status, status); + hdd_err("hdd_roam_deregister_sta() failed for staID %d Status=%d [0x%x]", + sta_id, status, status); status = CDF_STATUS_E_FAILURE; } pHddCtx->sta_to_adapter[sta_id] = NULL; @@ -2346,6 +2345,8 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, { hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx; + hdd_station_ctx_t *hdd_sta_ctx = + WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); struct cdf_mac_addr broadcastMacAddr = CDF_MAC_ADDR_BROADCAST_INITIALIZER; @@ -2365,10 +2366,13 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, /* notify wmm */ hdd_wmm_connect(pAdapter, pRoamInfo, eCSR_BSS_TYPE_IBSS); - pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = + + hdd_sta_ctx->broadcast_ibss_staid = pRoamInfo->staId; + + pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; hdd_roam_register_sta(pAdapter, pRoamInfo, - IBSS_BROADCAST_STAID, + pRoamInfo->staId, &broadcastMacAddr, pRoamInfo->pBssDesc); @@ -2705,9 +2709,6 @@ roam_roam_connect_status_update_handler(hdd_adapter_t *pAdapter, pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; - pHddCtx->sta_to_adapter[IBSS_BROADCAST_STAID] = - pAdapter; - /* Register the Station with TL for the new peer. */ cdf_status = hdd_roam_register_sta(pAdapter, pRoamInfo, diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index e6abd5346252..c7ed41ddae87 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -333,7 +333,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if ((STAId == HDD_WLAN_INVALID_STA_ID) && (cdf_is_macaddr_broadcast(pDestMacAddress) || cdf_is_macaddr_group(pDestMacAddress))) { - STAId = IBSS_BROADCAST_STAID; + STAId = pHddStaCtx->broadcast_ibss_staid; CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_INFO_LOW, "%s: BC/MC packet", __func__); -- cgit v1.2.3 From b9a4c16a238effe8816544e71869db8e048c7ac7 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 7 Dec 2015 13:36:10 -0800 Subject: qcacld-3.0: Remove OEM DATA request callback support qcacld-2.0 to qcacld-3.0 propagation. The SME OEM DATA request API supports a callback function pointer, however this callback functionality is obsolete. Therefore remove this functionality. Change-Id: Id06910841ad625412ba1f3222407e471f4d7edd7 CRs-Fixed: 911404 --- core/hdd/src/wlan_hdd_oemdata.c | 49 +----------------------------------- core/sme/inc/oem_data_api.h | 4 +-- core/sme/inc/oem_data_internal.h | 2 -- core/sme/inc/sme_api.h | 4 +-- core/sme/src/common/sme_api.c | 10 +++----- core/sme/src/oem_data/oem_data_api.c | 10 +------- 6 files changed, 7 insertions(+), 72 deletions(-) diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c index 63ae62ef9a27..5d76e0bbb635 100644 --- a/core/hdd/src/wlan_hdd_oemdata.c +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -47,52 +47,6 @@ static struct hdd_context_s *p_hdd_ctx; -/** - * hdd_oem_data_req_callback() - OEM Data request callback handler - * @hHal: MAC handle - * @pContext: User context. For this callback the net device was registered - * @oemDataReqID: The ID of the request - * @oemDataReqStatus: Status of the request - * - * This function reports the results of the request to user space - * - * Return: CDF_STATUS enumeration - */ -static CDF_STATUS hdd_oem_data_req_callback(tHalHandle hHal, - void *pContext, - uint32_t oemDataReqID, - eOemDataReqStatus oemDataReqStatus) -{ - CDF_STATUS status = CDF_STATUS_SUCCESS; - struct net_device *dev = (struct net_device *)pContext; - union iwreq_data wrqu; - char buffer[IW_CUSTOM_MAX + 1]; - - memset(&wrqu, '\0', sizeof(wrqu)); - memset(buffer, '\0', sizeof(buffer)); - - if (oemDataReqStatus == eOEM_DATA_REQ_FAILURE) { - snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-FAILED"); - hddLog(LOGW, "%s: oem data req %d failed", __func__, - oemDataReqID); - } else if (oemDataReqStatus == eOEM_DATA_REQ_INVALID_MODE) { - snprintf(buffer, IW_CUSTOM_MAX, - "QCOM: OEM-DATA-REQ-INVALID-MODE"); - hddLog(LOGW, - "%s: oem data req %d failed because the driver is in invalid mode (IBSS|AP)", - __func__, oemDataReqID); - } else { - snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-SUCCESS"); - } - - wrqu.data.pointer = buffer; - wrqu.data.length = strlen(buffer); - - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buffer); - - return status; -} - /** * iw_get_oem_data_cap() - Get OEM Data Capabilities * @dev: net device upon which the request was received @@ -428,8 +382,7 @@ static CDF_STATUS oem_process_data_req_msg(int oemDataLen, char *oemData) status = sme_oem_data_req(p_hdd_ctx->hHal, pAdapter->sessionId, &oemDataReqConfig, - &oemDataReqID, - &hdd_oem_data_req_callback, pAdapter->dev); + &oemDataReqID); return status; } diff --git a/core/sme/inc/oem_data_api.h b/core/sme/inc/oem_data_api.h index c7ec08c3b4f0..09630aedc744 100644 --- a/core/sme/inc/oem_data_api.h +++ b/core/sme/inc/oem_data_api.h @@ -76,9 +76,7 @@ typedef CDF_STATUS (*oem_data_oem_data_reqCompleteCallback)(tHalHandle, void *p2, uint32_t oemDataReqID, eOemDataReqStatus status); CDF_STATUS oem_data_oem_data_req(tHalHandle, uint8_t, tOemDataReqConfig *, - uint32_t *pOemDataReqID, - oem_data_oem_data_reqCompleteCallback callback, - void *pContext); + uint32_t *pOemDataReqID); CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *); CDF_STATUS oem_data_is_oem_data_req_allowed(tHalHandle hHal); typedef void (*sme_send_oem_data_rsp_msg)(int length, uint8_t *oem_data_rsp); diff --git a/core/sme/inc/oem_data_internal.h b/core/sme/inc/oem_data_internal.h index bf6a63460c77..0fa8857a2671 100644 --- a/core/sme/inc/oem_data_internal.h +++ b/core/sme/inc/oem_data_internal.h @@ -59,8 +59,6 @@ typedef struct tagOemDataStruct { typedef struct tagOemDataCmd { uint32_t oemDataReqID; - oem_data_oem_data_reqCompleteCallback callback; - void *pContext; tOemDataReq oemDataReq; } tOemDataCmd; #endif /* __OEM_DATA_INTERNAL_H__ */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 93e307fbcaa5..7882951a772c 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -475,9 +475,7 @@ CDF_STATUS sme_scan_get_bkid_candidate_list(tHalHandle hHal, uint32_t sessionId, CDF_STATUS sme_oem_data_req(tHalHandle hHal, uint8_t sessionId, tOemDataReqConfig *, - uint32_t *pOemDataReqID, - oem_data_oem_data_reqCompleteCallback callback, - void *pContext); + uint32_t *pOemDataReqID); #endif /*FEATURE_OEM_DATA_SUPPORT */ CDF_STATUS sme_roam_update_apwpsie(tHalHandle, uint8_t sessionId, tSirAPWPSIEs * pAPWPSIES); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 2cf8fbb92381..bca29ecb6c8e 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -5600,16 +5600,12 @@ CDF_STATUS sme_scan_get_bkid_candidate_list(tHalHandle hHal, uint32_t sessionId, \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 - \param callback - a callback function that is called upon finish - \param pContext - a pointer passed in for the callback \return CDF_STATUS ---------------------------------------------------------------------------*/ CDF_STATUS sme_oem_data_req(tHalHandle hHal, uint8_t sessionId, tOemDataReqConfig *pOemDataReqConfig, - uint32_t *pOemDataReqID, - oem_data_oem_data_reqCompleteCallback callback, - void *pContext) + uint32_t *pOemDataReqID) { CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -5629,8 +5625,8 @@ CDF_STATUS sme_oem_data_req(tHalHandle hHal, status = oem_data_oem_data_req(hHal, sessionId, - pOemDataReqConfig, pOemDataReqID, - callback, pContext); + pOemDataReqConfig, + pOemDataReqID); /* release the lock for the sme object */ sme_release_global_lock(&pMac->sme); diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c index 8fa6b8999aa7..89eda604f90c 100644 --- a/core/sme/src/oem_data/oem_data_api.c +++ b/core/sme/src/oem_data/oem_data_api.c @@ -124,16 +124,12 @@ void oem_data_release_oem_data_req_command(tpAniSirGlobal pMac, \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 - \param callback - a callback function that is called upon finish - \param pContext - a pointer passed in for the callback \return CDF_STATUS -------------------------------------------------------------------------------*/ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, uint8_t sessionId, tOemDataReqConfig *oemDataReqConfig, - uint32_t *pOemDataReqID, - oem_data_oem_data_reqCompleteCallback callback, - void *pContext) + uint32_t *pOemDataReqID) { CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -146,8 +142,6 @@ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, } pMac->oemData.oemDataReqConfig.sessionId = sessionId; - pMac->oemData.callback = callback; - pMac->oemData.pContext = pContext; pMac->oemData.oemDataReqID = *(pOemDataReqID); cdf_mem_copy((void *)(pMac->oemData.oemDataReqConfig. @@ -162,8 +156,6 @@ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, /* fill up the command before posting it. */ if (pOemDataCmd) { pOemDataCmd->command = eSmeCommandOemDataReq; - pOemDataCmd->u.oemDataCmd.callback = callback; - pOemDataCmd->u.oemDataCmd.pContext = pContext; pOemDataCmd->u.oemDataCmd.oemDataReqID = pMac->oemData.oemDataReqID; -- cgit v1.2.3 From b0435d7b879d9dd56fd1635bfcbde57a16076616 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 10 Dec 2015 12:29:44 -0800 Subject: qcacld-3.0: Relocate init of tx_action_cnf_event HDD has a completion variable which is used to synchronize the sending of an action frame with the send confirmation. Proper use of a completion variable requires a specific sequence of steps: - Initialize the completion variable - Perform the activity that has asynchronous processing - Wait on the completion variable Currently HDD does not correctly follow this model for sending action frames; it incorrectly initializes the completion variable after it has invoked the UMAC function which sends the frame. This creates a race condition whereby the TX could complete and set the completion variable before the completion variable is initialized, and then when the completion variable is initialized the fact that the activity has already completed will be lost. In order to prevent this race condition and conform to the sequence of steps required for proper completion variable usage, relocate the initialization of tx_action_cnf_event. Change-Id: Ibc54b8dd62c3a828d1a43922d89e7970af325f6e CRs-Fixed: 950132 --- core/hdd/src/wlan_hdd_main.c | 1 - core/hdd/src/wlan_hdd_p2p.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index e5e869948502..5d2bc52c46a6 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2057,7 +2057,6 @@ void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) if (NULL != cfgState->buf) { unsigned long rc; - INIT_COMPLETION(adapter->tx_action_cnf_event); rc = wait_for_completion_timeout( &adapter->tx_action_cnf_event, msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT)); diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index be647ad8272e..9018af87ba96 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -1544,6 +1544,8 @@ send_frame: current_freq = 0; } + INIT_COMPLETION(pAdapter->tx_action_cnf_event); + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) -- cgit v1.2.3 From b7ab97b169b5de962fb61bbf0fc7c4a283123752 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 17 Dec 2015 15:17:02 -0800 Subject: qcacld-3.0: Relocate key adapter fields This is a qcacld-2.0 to qcacld-3.0 propagation. A crash was observed internally where wlan_hdd_ipv6_changed() was accessing unmapped memory. This function has logic which looks at key fields in the netdev's private data area to make sure the netdev belongs to this driver before it further utilizes the netdev. The problem with this logic is when it is invoked with non-wlan netdevs, if those netdevs were created with small private data areas, then the offsets at which the key fields would exist in the wlan netdev may fall outside the memory mapped for those other netdevs. In order to avoid accessing unmapped memory in those cases, relocate the key wlan netdev fields to the beginning of the wlan adapter structure. Change-Id: Idb830fd18e5724a684505c9d110f6f1de5622eac CRs-Fixed: 946373 --- core/hdd/inc/wlan_hdd_main.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ec3e66d064d2..dd1e6c67de68 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -810,13 +810,20 @@ struct hdd_netif_queue_history { struct hdd_adapter_s { - void *pHddCtx; + /* 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 + */ + uint32_t magic; - device_mode_t device_mode; + 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 @@ -936,8 +943,6 @@ struct hdd_adapter_s { #endif uint8_t addr_filter_pattern; - /* Magic cookie for adapter sanity verification */ - uint32_t magic; bool higherDtimTransition; bool survey_idx; -- cgit v1.2.3 From ec4bf277c7fb199c5acb8d8ee8791a7a51d099b2 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Tue, 3 Nov 2015 14:17:26 -0800 Subject: qcacld-3.0: do not process HT IE change if RoC is in progress qcacld-2.0 to qcacld-3.0 propagation. Ignore HT IE change if RoC is in progress because as part of HT IE change we will try to change the channel parameters which use the same callback as RoC. So if we try to change the channel parameters if RoC is in progress we will overwrite the callback causing problems in the upper layers which are expecting a notification. Change-Id: I6bace6dd2bd40728ece94e3efe59f3e7038a4e6a CRs-Fixed: 710027 --- core/mac/src/pe/lim/lim_utils.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 4952804d9d2a..f11b3873c2a9 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -4918,6 +4918,20 @@ void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac, 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) { + lim_log(pMac, LOGE, FL("RoC is in progress")); + return; + } + if (psessionEntry->htSecondaryChannelOffset != (uint8_t) pHTInfo->secondaryChannelOffset || psessionEntry->htRecommendedTxWidthSet != -- cgit v1.2.3 From 04b1a36cf78fbf7da8317e37ed0926b42ac5e277 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Mon, 26 Oct 2015 18:30:53 -0700 Subject: qcacld-3.0: Check tdls off-channel passed is not a DFS channel qcacld-2.0 to qcacld-3.0 propagation Add check to validate if non-DFS channel is passed as TDLS off channel via driver command and INI config. Change-Id: I6696c47d438bdcc1b8733241e60ca5c52fb1022f CRs-Fixed: 915972 --- core/hdd/src/wlan_hdd_ioctl.c | 6 ++++++ core/hdd/src/wlan_hdd_tdls.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index b08bd02030f5..6fc55c587922 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5300,6 +5300,12 @@ static int drv_cmd_tdls_off_channel(hdd_adapter_t *adapter, if (ret != 1) return -EINVAL; + if (CDS_IS_DFS_CH(set_value)) { + hdd_err("DFS channel %d is passed for hdd_set_tdls_offchannel", + set_value); + return -EINVAL; + } + hddLog(LOG1, FL("Tdls offchannel num: %d"), set_value); ret = hdd_set_tdls_offchannel(hdd_ctx, set_value); diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 903fbfff4a73..3fd99256c057 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -4015,6 +4015,14 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter, MAC_ADDR_ARRAY(peer)); return -EINVAL; } + + /* validate if off channel is DFS channel */ + if (CDS_IS_DFS_CH(chan)) { + hdd_err("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)) { @@ -4265,6 +4273,16 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, pTdlsPeer-> op_class_for_pref_off_chan; + if (CDS_IS_DFS_CH(smeTdlsPeerStateParams. + peerCap.prefOffChanNum)) { + hdd_err("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; + } + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: Peer " MAC_ADDRESS_STR -- cgit v1.2.3 From 24e4dc9eaae23539b530954ffcf0990eec7d8f6c Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Tue, 3 Nov 2015 14:58:26 -0800 Subject: qcacld-3.0: Log the rssi info from FW in sta kick out event qcacld-2.0 to qcacld-3.0 propagation. Log the RSSI info of the disconnect if the STA disconnection is due to STA kick out event from FW. Change-Id: I0fad3f8d0e7990f4211b7840bed7605a4b97f3cb CRs-Fixed: 874197 --- core/hdd/src/wlan_hdd_assoc.c | 8 ++++++-- core/mac/inc/sir_api.h | 1 + core/mac/src/include/dph_global.h | 2 ++ core/mac/src/pe/lim/lim_link_monitoring_algo.c | 1 + core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 3 +++ core/sme/src/csr/csr_api_roam.c | 1 + core/wma/inc/wma_if.h | 2 ++ core/wma/src/wma_mgmt.c | 1 + 8 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 4912c80661fe..a7fc30d4beaf 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1046,15 +1046,19 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, * To avoid wpa_supplicant sending "HANGED" CMD * to ICS UI. */ - if (eCSR_ROAM_LOSTLINK == roamStatus) + if (eCSR_ROAM_LOSTLINK == roamStatus) { + if (pRoamInfo->reasonCode == + eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON) + pr_info("wlan: disconnected due to poor signal, rssi is %d dB\n", pRoamInfo->rxRssi); cfg80211_disconnected(dev, pRoamInfo-> reasonCode, NULL, 0, GFP_KERNEL); - else + } else { cfg80211_disconnected(dev, WLAN_REASON_UNSPECIFIED, NULL, 0, GFP_KERNEL); + } hdd_info("sent disconnected event to nl80211, rssi: %d", pAdapter->rssi); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a627a09d4785..d73049243280 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1398,6 +1398,7 @@ typedef struct sSirSmeDeauthInd { uint16_t staId; uint32_t reasonCode; + int8_t rssi; } tSirSmeDeauthInd, *tpSirSmeDeauthInd; /* / Definition for stop BSS request message */ diff --git a/core/mac/src/include/dph_global.h b/core/mac/src/include/dph_global.h index abeacf4f521c..30a8e2903b07 100644 --- a/core/mac/src/include/dph_global.h +++ b/core/mac/src/include/dph_global.h @@ -240,6 +240,8 @@ typedef struct sDphHashNode { uint8_t is_disassoc_deauth_in_progress; uint8_t nss; + int8_t del_sta_ctx_rssi; + /* * When a station with already an existing dph entry tries to * associate again, the old dph entry will be zeroed out except diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c index c4626c66c037..c61e18930916 100644 --- a/core/mac/src/pe/lim/lim_link_monitoring_algo.c +++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c @@ -92,6 +92,7 @@ static void lim_delete_sta_util(tpAniSirGlobal mac_ctx, tpDeleteStaContext msg, cdf_mem_free(msg); return; } + stads->del_sta_ctx_rssi = msg->rssi; /* check and see if same staId. This is to avoid the scenario * where we're trying to delete a staId we just added. diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index c7d1517d2523..326dfc7576a0 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1125,6 +1125,9 @@ lim_send_sme_deauth_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, pSirSmeDeauthInd->reasonCode = pStaDs->mlmStaContext.disassocReason; pSirSmeDeauthInd->staId = pStaDs->staIndex; + if (eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON == + pStaDs->mlmStaContext.disassocReason) + pSirSmeDeauthInd->rssi = pStaDs->del_sta_ctx_rssi; mmhMsg.type = eWNI_SME_DEAUTH_IND; mmhMsg.bodyptr = pSirSmeDeauthInd; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 60a45ad85bb4..7c1c12de50b4 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -11336,6 +11336,7 @@ CDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, sizeof(tSirMacAddr)); roamInfo.staId = (uint8_t) pDeauthIndMsg->staId; roamInfo.reasonCode = pDeauthIndMsg->reasonCode; + roamInfo.rxRssi = pDeauthIndMsg->rssi; } sms_log(pMac, LOGW, FL("roamInfo.staId (%d)"), roamInfo.staId); diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 52e313908ff6..f5875316f781 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -592,6 +592,7 @@ typedef enum eSmpsModeValue { * @bssId: mac address * @addr2: mac address * @reasonCode: reason code + * @rssi: rssi value during disconnection */ typedef struct { uint16_t assocId; @@ -599,6 +600,7 @@ typedef struct { tSirMacAddr bssId; tSirMacAddr addr2; uint16_t reasonCode; + int8_t rssi; } tDeleteStaContext, *tpDeleteStaContext; /** diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index bad92a00f21c..52719d97b35b 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -440,6 +440,7 @@ int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) cdf_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); -- cgit v1.2.3 From 62bd6b89ab066b7574c04b3aef79287b87693938 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 8 Dec 2015 14:43:13 -0800 Subject: qcacld-3.0: Initialize PMF timer in create session Initialize PMF comeback timer in PE create session. Currenlty PMF comeback timer is initialized in join request and destroyed in delete session. In offload cases, PE session is created without join request resulting in destruction of timer which was not initialized. Add timer initialization in pe_create_session. Change-Id: I3dba6713b2bf64cc69f0f2d8322293ff763c0989 CRs-Fixed: 948924 --- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 20 ++------------------ core/mac/src/pe/lim/lim_session.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index b3933f9fb7a3..ee010b6a4170 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1829,26 +1829,10 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) /* Record if management frames need to be protected */ #ifdef WLAN_FEATURE_11W - if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) { - CDF_STATUS cdf_status; + if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) session->limRmfEnabled = 1; - session->pmfComebackTimerInfo.pMac = mac_ctx; - session->pmfComebackTimerInfo.sessionID = - session_id; - cdf_status = cdf_mc_timer_init( - &session->pmfComebackTimer, - CDF_TIMER_TYPE_SW, - lim_pmf_comeback_timer_callback, - (void *)&session->pmfComebackTimerInfo); - if (CDF_STATUS_SUCCESS != cdf_status) { - lim_log(mac_ctx, LOGP, - FL("cannot init pmf comeback timer.")); - ret_code = eSIR_LOGP_EXCEPTION; - goto end; - } - } else { + else session->limRmfEnabled = 0; - } #endif #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index d6914543e697..55a126a180dd 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -384,6 +384,15 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, FL("cannot create or start protectionFieldsResetTimer\n")); } + + session_ptr->pmfComebackTimerInfo.pMac = pMac; + session_ptr->pmfComebackTimerInfo.sessionID = *sessionId; + status = cdf_mc_timer_init(&session_ptr->pmfComebackTimer, + CDF_TIMER_TYPE_SW, lim_pmf_comeback_timer_callback, + (void *)&session_ptr->pmfComebackTimerInfo); + if (!CDF_IS_STATUS_SUCCESS(status)) + lim_log(pMac, LOGE, FL("cannot init pmf comeback timer.")); + return &pMac->lim.gpSession[i]; } @@ -665,9 +674,10 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) session->addIeParams.probeRespBCNDataLen = 0; } #ifdef WLAN_FEATURE_11W - /* if PMF connection */ - if (session->limRmfEnabled) - cdf_mc_timer_destroy(&session->pmfComebackTimer); + if (CDF_TIMER_STATE_RUNNING == + cdf_mc_timer_get_current_state(&session->pmfComebackTimer)) + cdf_mc_timer_stop(&session->pmfComebackTimer); + cdf_mc_timer_destroy(&session->pmfComebackTimer); #endif session->valid = false; -- cgit v1.2.3 From b2225b1611736687bca3b83ca650dc9102ab79b9 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Tue, 15 Dec 2015 17:51:19 -0800 Subject: qcacld-3.0: Check for session validity in pe_delete_session Check if PE session passed to pe_delete_session is valid before proceeding with the deletion. Change-Id: Icfe54e8bc286f14ea757b0619c067cc74ce87492 CRs-Fixed: 948924 --- core/mac/src/pe/lim/lim_session.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 55a126a180dd..5e7f1cf6e665 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -536,6 +536,12 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) uint16_t n; TX_TIMER *timer_ptr; + if (!session || (session && !session->valid)) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, + FL("session is not valid")); + return; + } + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, FL("Trying to delete PE session %d Opmode %d BssIdx %d BSSID: "MAC_ADDRESS_STR), session->peSessionId, session->operMode, -- cgit v1.2.3 From 52249826fc81b341830db1dc94ddb2db3df2c10a Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Wed, 12 Aug 2015 12:43:18 -0700 Subject: qcacld-3.0: Error handling in Roaming code #2 Qcacld-2.0 to qcacld-3.0 propagation. This fix contains the following changes 1. Ensure rx mgmt packet is freed in all cases. 2. Fail preauth if the pre-auth response timer failed to start. 3. Correct some logging and remove unnecessary code. Change-Id: Icd3a12ba8878de5bad7ff1125ba8be123dfae4eb CRs-Fixed: 808756 --- core/mac/src/pe/lim/lim_ft.c | 35 ++++++++---------- core/mac/src/pe/lim/lim_process_message_queue.c | 42 ++++++++++------------ core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 10 ------ core/mac/src/pe/lim/lim_process_sme_req_messages.c | 13 ++++--- 4 files changed, 38 insertions(+), 62 deletions(-) diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index c96327c12d67..92769e8bb12d 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -370,35 +370,28 @@ void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status, psessionEntry->ftPEContext.pFTPreAuthReq) { /* Only 11r assoc has FT IEs */ if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies == NULL) { - PELOGE(lim_log(pMac, LOGE, - "%s: FTIEs for Auth Req Seq 1 is absent", - __func__); - ) + lim_log(pMac, LOGE, + FL("FTIEs for Auth Req Seq 1 is absent")); goto preauth_fail; } } if (status != CDF_STATUS_SUCCESS) { - PELOGE(lim_log(pMac, LOGE, - "%s: Change channel not successful for FT pre-auth", - __func__); - ) + lim_log(pMac, LOGE, + FL(" Change channel not successful for FT pre-auth")); 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(lim_log - (pMac, LOGE, FL("psessionEntry is not in STA mode")); - ) + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); #endif return; } #if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG2(lim_log(pMac, LOG2, "Entered wait auth2 state for FT" - " (old session %p)", psessionEntry); - ) + lim_log(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 @@ -423,15 +416,15 @@ void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status, if (TX_SUCCESS != tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) { #if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOGE(lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed"));) + lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed")); #endif + goto preauth_fail; } - MTRACE(mac_trace - (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, - eLIM_FT_PREAUTH_RSP_TIMER)); + MTRACE(mac_trace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_FT_PREAUTH_RSP_TIMER)); #if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started"));) + lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started")); #endif #ifdef FEATURE_WLAN_DIAG_SUPPORT lim_diag_event_report(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, @@ -439,8 +432,8 @@ void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status, #endif lim_send_auth_mgmt_frame(pMac, &authFrame, - psessionEntry->ftPEContext.pFTPreAuthReq-> - preAuthbssId, LIM_NO_WEP_IN_FC, psessionEntry); + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + LIM_NO_WEP_IN_FC, psessionEntry); return; diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index ac63aee78c87..928e5d7d5329 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -804,8 +804,7 @@ lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg if (fc.subType == SIR_MAC_MGMT_AUTH) { #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG lim_log(pMac, LOG1, - FL - ("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), + FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), fc.protVer, fc.type, fc.subType, WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); lim_print_mac_addr(pMac, pHdr->bssId, LOG1); @@ -813,31 +812,28 @@ lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg if (lim_process_auth_frame_no_session (pMac, pRxPacketInfo, limMsg->bodyptr) == eSIR_SUCCESS) { - lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, - pRxPacketInfo, limMsg->bodyptr); - return; + goto end; } } #endif + /* Public action frame can be received from non-assoc stations*/ 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 = - pe_find_session_by_peer_sta(pMac, pHdr->sa, - &sessionId)) == NULL) { - lim_log(pMac, LOG1, - FL - ("session does not exist for given bssId")); - lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, - pRxPacketInfo, limMsg->bodyptr); - return; - } else - lim_log(pMac, LOG1, - "SessionId:%d Session Exist for given Bssid", + && (fc.subType != SIR_MAC_MGMT_ACTION)) { + + psessionEntry = pe_find_session_by_peer_sta(pMac, + pHdr->sa, &sessionId); + if (psessionEntry == NULL) { + lim_log(pMac, LOG3, + FL("session does not exist for bssId")); + lim_print_mac_addr(pMac, pHdr->sa, LOG3); + goto end; + } else { + lim_log(pMac, LOG3, + "SessionId:%d exists 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 */ @@ -850,9 +846,7 @@ lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg /* Check if frame is registered by HDD */ if (lim_check_mgmt_registered_frames(pMac, pRxPacketInfo, psessionEntry)) { lim_log(pMac, LOG1, FL("Received frame is passed to SME")); - lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, - limMsg->bodyptr); - return; + goto end; } if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { /* Received Frame with non-zero Protocol Version */ @@ -864,7 +858,7 @@ lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg #ifdef WLAN_DEBUG pMac->lim.numProtErr++; #endif - return; + goto end; } /* Chance of crashing : to be done BT-AMP ........happens when broadcast probe req is received */ diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 8693bd801f20..c1761c855218 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1874,7 +1874,6 @@ static void lim_process_mlm_disassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) { tLimMlmDisassocReq *mlm_disassoc_req; - tpPESession session; if (msg_buf == NULL) { lim_log(mac_ctx, LOGE, @@ -1888,15 +1887,6 @@ lim_process_mlm_disassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) mlm_disassoc_req->sessionId, MAC_ADDR_ARRAY(mlm_disassoc_req->peerMacAddr)); - session = pe_find_session_by_session_id(mac_ctx, - mlm_disassoc_req->sessionId); - if (NULL == session) { - lim_log(mac_ctx, LOGE, - FL("session does not exist for given sessionId %d"), - mlm_disassoc_req->sessionId); - return; - } - lim_process_mlm_disassoc_req_ntf(mac_ctx, CDF_STATUS_SUCCESS, (uint32_t *) msg_buf); } diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index ee010b6a4170..934531e06572 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2476,6 +2476,9 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu switch (psessionEntry->limSmeState) { case eLIM_SME_ASSOCIATED_STATE: case eLIM_SME_LINK_EST_STATE: + lim_log(pMac, LOG1, + FL("Rcvd SME_DISASSOC_REQ in limSmeState: %d "), + psessionEntry->limSmeState); psessionEntry->limPrevSmeState = psessionEntry->limSmeState; psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE; @@ -2483,13 +2486,9 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu /* Delete all TDLS peers connected before leaving BSS */ lim_delete_tdls_peers(pMac, psessionEntry); #endif - MTRACE(mac_trace - (pMac, TRACE_CODE_SME_STATE, - psessionEntry->peSessionId, - psessionEntry->limSmeState)); - lim_log(pMac, LOG1, - FL("Rcvd SME_DISASSOC_REQ while in limSmeState: %d "), - psessionEntry->limSmeState); + MTRACE(mac_trace(pMac, TRACE_CODE_SME_STATE, + psessionEntry->peSessionId, + psessionEntry->limSmeState)); break; case eLIM_SME_WT_DEAUTH_STATE: -- cgit v1.2.3 From 1ae65638227a7a3101de4811f337b67868fca408 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:45:35 +0530 Subject: qcacld-3.0: Do not send DEL BSS to FW if ADD BSS fails qcacld-2.0 to qcacld-3.0 propagation Even though ADD_BSS fails the driver tries to send DEL BSS to firmware which will crash upon receiving DEL BSS. To avoid this crash do not send DEL BSS to Firmware if ADD BSS fails and just do cleanup. Change-Id: Ieabf241c8277ae76bb5f491f9d8a2b783d8ea47e CRs-Fixed: 929249 --- core/mac/src/pe/include/lim_session.h | 1 + core/mac/src/pe/lim/lim_assoc_utils.c | 17 ++++++++++------- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 5d27af28a009..4b0ebe7c459f 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -483,6 +483,7 @@ typedef struct sPESession /* Added to Support BT-AMP */ /* flag to indicate country code in beacon */ uint8_t country_info_present; uint8_t nss; + bool add_bss_failed; } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index c981c28b1d50..3cd37489f05a 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -671,13 +671,16 @@ lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, /* increment a debug count */ pMac->lim.gLimNumRxCleanup++; #endif - - if (psessionEntry->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) { - retCode = - lim_del_bss(pMac, pStaDs, psessionEntry->bssIdx, - psessionEntry); - } else - retCode = lim_del_sta(pMac, pStaDs, true, psessionEntry); + /* 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 = + lim_del_bss(pMac, pStaDs, psessionEntry->bssIdx, + psessionEntry); + } else + retCode = lim_del_sta(pMac, + pStaDs, true, psessionEntry); + } return retCode; diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 0fe37fe6da02..a4afe4c5f3d6 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1546,12 +1546,19 @@ lim_handle_sme_join_result(tpAniSirGlobal mac_ctx, * to SME */ lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + /* Cleanup if add bss failed */ + if (session_entry->add_bss_failed) { + dph_delete_hash_entry(mac_ctx, + sta_ds->staAddr, sta_ds->assocId, + &session_entry->dph.dphHashTable); + goto error; + } cdf_mem_free(session_entry->pLimJoinReq); session_entry->pLimJoinReq = NULL; return; } } - +error: cdf_mem_free(session_entry->pLimJoinReq); session_entry->pLimJoinReq = NULL; /* Delete teh session if JOIN failure occurred. */ @@ -1624,9 +1631,17 @@ lim_handle_sme_reaasoc_result(tpAniSirGlobal pMac, tSirResultCodes resultCode, pStaDs->mlmStaContext.resultCode = resultCode; pStaDs->mlmStaContext.protStatusCode = protStatusCode; lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); + /* Cleanup if add bss failed */ + if (psessionEntry->add_bss_failed) { + dph_delete_hash_entry(pMac, + pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); + goto error; + } return; } } +error: /* Delete teh session if REASSOC failure occurred. */ if (resultCode != eSIR_SME_SUCCESS) { if (NULL != psessionEntry) { @@ -3056,6 +3071,7 @@ lim_process_sta_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx, else mlm_assoc_cnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; + session_entry->add_bss_failed = true; } if (mlm_assoc_cnf.resultCode != eSIR_SME_SUCCESS) { -- cgit v1.2.3 From 109daae06e85debd3dc478b467351313e08ae36e Mon Sep 17 00:00:00 2001 From: Sushant Kaushik Date: Wed, 2 Dec 2015 16:57:47 +0530 Subject: qcacld-3.0: Set peer staId for management frame. qcacld-2.0 to qcacld-3.0 propagation Currently for sta mode while sending management frames such as auth, assoc, reasssoc,deauth, diassoc driver sends selfStaId. This results in frames going on the air with the self data rate and not the data rate supported by peer. As a part of fix, make sure that the peerStaId is used for sending above management frames. Change-Id: Ia368ff13aed1002600f5fb3ad55c3d20106d586a CRs-Fixed: 826260 --- core/mac/src/pe/lim/lim_send_management_frames.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 80bd967983ad..50884de03e6f 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1930,7 +1930,8 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, ) tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; - if (pe_session->pePersona == CDF_P2P_CLIENT_MODE) + if (pe_session->pePersona == CDF_P2P_CLIENT_MODE || + pe_session->pePersona == CDF_STA_MODE) tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK; #ifdef FEATURE_WLAN_DIAG_SUPPORT @@ -2710,9 +2711,9 @@ lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; } - if (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) { + if (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE || + psessionEntry->pePersona == CDF_STA_MODE) txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; - } #ifdef FEATURE_WLAN_DIAG_SUPPORT lim_diag_event_report(pMac, WLAN_PE_DIAG_REASSOC_START_EVENT, @@ -3015,10 +3016,10 @@ lim_send_auth_mgmt_frame(tpAniSirGlobal mac_ctx, tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; - if (session->pePersona == CDF_P2P_CLIENT_MODE) + if (session->pePersona == CDF_P2P_CLIENT_MODE || + session->pePersona == CDF_STA_MODE) tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK; - MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, session->peSessionId, mac_hdr->fc.subType)); /* Queue Authentication frame in high priority WQ */ @@ -3345,10 +3346,7 @@ lim_send_disassoc_mgmt_frame(tpAniSirGlobal pMac, txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; } - if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || - (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { - txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; - } + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; if (waitForAck) { MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, @@ -3525,10 +3523,7 @@ lim_send_deauth_mgmt_frame(tpAniSirGlobal pMac, txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; } - if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || - (psessionEntry->pePersona == CDF_P2P_GO_MODE)) { - txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; - } + txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK; #ifdef FEATURE_WLAN_TDLS pStaDs = dph_lookup_hash_entry(pMac, peer, &aid, -- cgit v1.2.3 From c13be71c78f0240a30df9d0d811c3912466e9b2f Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Wed, 16 Dec 2015 13:06:22 +0530 Subject: qcacld-3.0: Changes in Protocol Stack logs from numerical values to string qcacld-2.0 to qcacld-3.0 propagation As a part of logging enhancement,to make logs more interactive, changed pmcstate,scanType etc from numerical values to human readable string in Protocol stack. Change-Id: I589088c2c5fd0afa106a1d0773a2ff525b0dd083 CRs-Fixed: 638916 --- core/mac/inc/sir_api.h | 3 ++ core/mac/src/pe/lim/lim_process_beacon_frame.c | 4 +-- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 3 +- core/mac/src/pe/lim/lim_sme_req_utils.c | 3 +- core/mac/src/pe/lim/lim_utils.c | 37 ++++++++++++++++++++++ core/sme/inc/sme_api.h | 1 + core/sme/src/csr/csr_api_roam.c | 6 ++-- core/sme/src/csr/csr_api_scan.c | 24 +++++++++----- core/sme/src/csr/csr_util.c | 21 ++++++++++++ 9 files changed, 88 insertions(+), 14 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d73049243280..001844f6067e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -309,6 +309,9 @@ typedef enum eStaRateMode { #define IERATE_RATE_MASK 0x7f #define IERATE_IS_BASICRATE(x) ((x) & IERATE_BASICRATE_MASK) +const char *lim_bss_type_to_string(const uint16_t bss_type); +const char *lim_scan_type_to_string(const uint8_t scan_type); + typedef struct sSirSupportedRates { /* * For Self STA Entry: this represents Self Mode. diff --git a/core/mac/src/pe/lim/lim_process_beacon_frame.c b/core/mac/src/pe/lim/lim_process_beacon_frame.c index 3a72a69ba418..18c05fd653f4 100644 --- a/core/mac/src/pe/lim/lim_process_beacon_frame.c +++ b/core/mac/src/pe/lim/lim_process_beacon_frame.c @@ -238,9 +238,9 @@ lim_process_beacon_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo) cdf_mem_free(pBeacon); } /* end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) */ else { - lim_log(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d"), + lim_log(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %s (%d)"), + lim_mlm_state_str(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState); - lim_print_mlm_state(pMac, LOG1, pMac->lim.gLimMlmState); #ifdef WLAN_DEBUG pMac->lim.gLimUnexpBcnCnt++; #endif diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 934531e06572..70ceb3dfba6b 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1396,11 +1396,12 @@ static void __lim_process_sme_scan_req(tpAniSirGlobal mac_ctx, scan_req = (tpSirSmeScanReq) msg_buf; lim_log(mac_ctx, LOG1, - FL("SME SCAN REQ id %d numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d rsp %d"), + FL("SME SCAN REQ id %d numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %s (%d) rsp %d"), scan_req->scan_id, scan_req->channelList.numChannels, scan_req->minChannelTime, scan_req->maxChannelTime, scan_req->uIEFieldLen, scan_req->returnAfterFirstMatch, scan_req->returnFreshResults, scan_req->returnUniqueResults, + lim_scan_type_to_string(scan_req->scanType), scan_req->scanType, mac_ctx->lim.gLimRspReqd ? 1 : 0); /* * Since scan req always requires a response, we will overwrite response diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c index f0f660fdfd11..7e06f75d72cf 100644 --- a/core/mac/src/pe/lim/lim_sme_req_utils.c +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -388,7 +388,8 @@ lim_is_sme_start_bss_req_valid(tpAniSirGlobal mac_ctx, tSirMacRateSet *opr_rates = &start_bss_req->operationalRateSet; PELOG1(lim_log(mac_ctx, LOG1, - FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), + FL("Parsed START_BSS_REQ fields are bssType=%s (%d), channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), + lim_bss_type_to_string(start_bss_req->bssType), start_bss_req->bssType, start_bss_req->channelId, start_bss_req->ssId.length, start_bss_req->rsnIE.length, start_bss_req->nwType, opr_rates->numRates);) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index f11b3873c2a9..f49407430ec7 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7158,3 +7158,40 @@ lim_get_80Mhz_center_channel(uint8_t primary_channel) return INVALID_CHANNEL_ID; } + +/** + * lim_scan_type_to_string(): converts scan type enum to string. + * @scan_type: enum value of scan_type. + * + * Return: Printable string for scan_type + */ +const char *lim_scan_type_to_string(const uint8_t scan_type) +{ + switch (scan_type) { + CASE_RETURN_STRING(eSIR_PASSIVE_SCAN); + CASE_RETURN_STRING(eSIR_ACTIVE_SCAN); + CASE_RETURN_STRING(eSIR_BEACON_TABLE); + default: + return "Unknown scan_type"; + } +} + +/** + * lim_bss_type_to_string(): converts bss type enum to string. + * @bss_type: enum value of bss_type. + * + * Return: Printable string for bss_type + */ +const char *lim_bss_type_to_string(const uint16_t bss_type) +{ + switch (bss_type) { + 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 bss_type"; + } +} diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 7882951a772c..748652169697 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -819,6 +819,7 @@ CDF_STATUS sme_modify_add_ie(tHalHandle hHal, CDF_STATUS sme_update_add_ie(tHalHandle hHal, tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType); CDF_STATUS sme_update_connect_debug(tHalHandle hHal, uint32_t set_value); +const char *sme_request_type_to_string(const uint8_t request_type); CDF_STATUS sme_ap_disable_intra_bss_fwd(tHalHandle hHal, uint8_t sessionId, bool disablefwd); uint32_t sme_get_channel_bonding_mode5_g(tHalHandle hHal); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7c1c12de50b4..aa08d033a091 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7143,7 +7143,8 @@ CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, /* Initialize the count before proceeding with the Join requests */ pSession->join_bssid_count = 0; sms_log(pMac, LOG1, - FL("called BSSType = %d authtype = %d encryType = %d"), + FL("called BSSType = %s (%d) authtype = %d encryType = %d"), + lim_bss_type_to_string(pProfile->BSSType), pProfile->BSSType, pProfile->AuthType.authType[0], pProfile->EncryptionType.encryptionType[0]); csr_roam_cancel_roaming(pMac, sessionId); @@ -7325,7 +7326,8 @@ csr_roam_reassoc(tpAniSirGlobal mac_ctx, uint32_t session_id, return CDF_STATUS_E_FAILURE; } sms_log(mac_ctx, LOG1, - FL("called BSSType = %d authtype = %d encryType = %d"), + FL("called BSSType = %s (%d) authtype = %d encryType = %d"), + lim_bss_type_to_string(profile->BSSType), profile->BSSType, profile->AuthType.authType[0], profile->EncryptionType.encryptionType[0]); csr_roam_cancel_roaming(mac_ctx, session_id); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 921288b9604b..16ebbc7227ac 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -4861,11 +4861,15 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, pScanReqParam->fUniqueResult, pScanReqParam->freshScan, pScanReqParam->hiddenSsid); sms_log(pMac, LOG1, - FL("scanType = %u BSSType = %u numOfSSIDs = %d" - " numOfChannels = %d requestType = %d p2pSearch = %d\n"), - pScanReq->scanType, pScanReq->BSSType, + FL("scanType = %s (%u) BSSType = %s (%u) numOfSSIDs = %d" + " numOfChannels = %d requestType = %s (%d) p2pSearch = %d\n"), + lim_scan_type_to_string(pScanReq->scanType), + pScanReq->scanType, + lim_bss_type_to_string(pScanReq->BSSType), + pScanReq->BSSType, pScanReq->SSIDs.numOfSSIDs, pScanReq->ChannelInfo.numOfChannels, + sme_request_type_to_string(pScanReq->requestType), pScanReq->requestType, pScanReq->p2pSearch); return CDF_STATUS_E_NOMEM; } @@ -5006,10 +5010,12 @@ CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, send_scan_req: sms_log(pMac, LOG1, - FL("scanId %d domainIdCurrent %d scanType %d bssType %d requestType %d numChannels %d"), - pMsg->scan_id, pMac->scan.domainIdCurrent, pMsg->scanType, - pMsg->bssType, pScanReq->requestType, - pMsg->channelList.numChannels); + FL("scanId %d domainIdCurrent %d scanType %s (%d) bssType %s (%d) requestType %s (%d) numChannels %d"), + pMsg->scan_id, pMac->scan.domainIdCurrent, + lim_scan_type_to_string(pMsg->scanType), pMsg->scanType, + lim_bss_type_to_string(pMsg->bssType), pMsg->bssType, + sme_request_type_to_string(pScanReq->requestType), + pScanReq->requestType, pMsg->channelList.numChannels); for (i = 0; i < pMsg->channelList.numChannels; i++) { sms_log(pMac, LOG1, FL("channelNumber[%d]= %d"), i, @@ -5256,7 +5262,9 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, ) { #ifdef FEATURE_WLAN_LFR sms_log(mac_ctx, LOG2, - FL(" reqType=%d, numOfChannels=%d, ignoring DFS channel %d"), + FL(" reqType= %s (%d), numOfChannels=%d, ignoring DFS channel %d"), + sme_request_type_to_string( + src_req->requestType), src_req->requestType, src_req->ChannelInfo.numOfChannels, src_req->ChannelInfo.ChannelList diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 8c9c1d869cec..189e3b27705b 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -5561,6 +5561,27 @@ bool csr_is_channel_present_in_list(uint8_t *pChannelList, return false; } +/** + * sme_request_type_to_string(): converts scan request enum to string. + * @request_type: scan request type enum. + * + * Return: Printable string for request_type + */ +const char *sme_request_type_to_string(const uint8_t request_type) +{ + switch (request_type) { + CASE_RETURN_STRING(eCSR_SCAN_REQUEST_11D_SCAN); + CASE_RETURN_STRING(eCSR_SCAN_REQUEST_FULL_SCAN); + CASE_RETURN_STRING(eCSR_SCAN_IDLE_MODE_SCAN); + CASE_RETURN_STRING(eCSR_SCAN_HO_PROBE_SCAN); + CASE_RETURN_STRING(eCSR_SCAN_P2P_DISCOVERY); + CASE_RETURN_STRING(eCSR_SCAN_SOFTAP_CHANNEL_RANGE); + CASE_RETURN_STRING(eCSR_SCAN_P2P_FIND_PEER); + default: + return "Unknown Scan Request Type"; + } +} + CDF_STATUS csr_add_to_channel_list_front(uint8_t *pChannelList, int numChannels, uint8_t channel) { -- cgit v1.2.3 From c1e4966db6c4bffac4c4249aa9e7381e119652a8 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Tue, 22 Dec 2015 12:50:15 +0530 Subject: qcacld-3.0: Add missing MTRACE log in HDD qcacld-2.0 to qcacld-3.0 propagation Currently, MTRACE logs are not captured for the events posted from SME to HDD. So, add missing MTRACE log in hdd_smeRoamCallback() and also add missing eRoamCmdStatus enums in get_eRoamCmdStatus_str(). Change-Id: I26ef8c651b7b873939341b643056ff977a40ea19 CRs-Fixed: 855875 --- core/hdd/inc/wlan_hdd_trace.h | 3 ++- core/hdd/src/wlan_hdd_assoc.c | 4 ++++ core/hdd/src/wlan_hdd_trace.c | 12 +++++++---- core/sme/src/csr/csr_util.c | 48 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_trace.h b/core/hdd/inc/wlan_hdd_trace.h index 12e25d5b1a46..0703b2e8847e 100644 --- a/core/hdd/inc/wlan_hdd_trace.h +++ b/core/hdd/inc/wlan_hdd_trace.h @@ -108,7 +108,8 @@ ENUM(TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN) \ ENUM(TRACE_CODE_HDD_CFG80211_SET_MAC_ACL) \ ENUM(TRACE_CODE_HDD_CFG80211_TESTMODE) \ - ENUM(TRACE_CODE_HDD_CFG80211_DUMP_SURVEY) + ENUM(TRACE_CODE_HDD_CFG80211_DUMP_SURVEY) \ + ENUM(TRACE_CODE_HDD_RX_SME_MSG) enum { #undef ENUM diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index a7fc30d4beaf..e69f3c725c31 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -36,6 +36,7 @@ #include #include "dot11f.h" #include "wlan_hdd_power.h" +#include "wlan_hdd_trace.h" #include #include #include @@ -3852,6 +3853,9 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + MTRACE(cdf_trace(CDF_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); diff --git a/core/hdd/src/wlan_hdd_trace.c b/core/hdd/src/wlan_hdd_trace.c index f89bfb04ceb9..a5cec605bd16 100644 --- a/core/hdd/src/wlan_hdd_trace.c +++ b/core/hdd/src/wlan_hdd_trace.c @@ -50,10 +50,14 @@ static void hdd_trace_dump(void *mac, tp_cdf_trace_record record, uint16_t index) { - hddLog(LOG1, "%04d %012llu S%d %-14s %-30s(0x%x)", - index, record->time, record->session, - "HDD Event:", hdd_trace_event_string(record->code), - record->data); + if (TRACE_CODE_HDD_RX_SME_MSG == record->code) + hddLog(LOGE, "%04d %012llu S%d %-14s %-30s(0x%x) ", + index, record->time, record->session, "RX SME MSG:", + get_e_roam_cmd_status_str(record->data), record->data); + else + hddLog(LOGE, "%04d %012llu S%d %-14s %-30s(0x%x) ", + index, record->time, record->session, "HDD Event:", + hdd_trace_event_string(record->code), record->data); } /** diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 189e3b27705b..88ecfcbcd21f 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -179,14 +179,62 @@ const char *get_e_roam_cmd_status_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_ASSOCIATION_FAILURE); 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_IBSS_LEAVE); + CASE_RETURN_STR(eCSR_ROAM_INFRA_IND); + CASE_RETURN_STR(eCSR_ROAM_WPS_PBC_PROBE_REQ_IND); +#ifdef WLAN_FEATURE_VOWIFI_11R + CASE_RETURN_STR(eCSR_ROAM_FT_RESPONSE); +#endif + CASE_RETURN_STR(eCSR_ROAM_FT_START); + CASE_RETURN_STR(eCSR_ROAM_INDICATE_MGMT_FRAME); + CASE_RETURN_STR(eCSR_ROAM_REMAIN_CHAN_READY); + CASE_RETURN_STR(eCSR_ROAM_SEND_ACTION_CNF); + CASE_RETURN_STR(eCSR_ROAM_SESSION_OPENED); + CASE_RETURN_STR(eCSR_ROAM_FT_REASSOC_FAILED); +#ifdef FEATURE_WLAN_LFR + CASE_RETURN_STR(eCSR_ROAM_PMK_NOTIFY); +#endif +#ifdef FEATURE_WLAN_LFR_METRICS + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_INIT_NOTIFY); + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_STATUS_SUCCESS); + CASE_RETURN_STR(eCSR_ROAM_PREAUTH_STATUS_FAILURE); + CASE_RETURN_STR(eCSR_ROAM_HANDOVER_SUCCESS); +#endif +#ifdef FEATURE_WLAN_TDLS + CASE_RETURN_STR(eCSR_ROAM_TDLS_STATUS_UPDATE); + CASE_RETURN_STR(eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND); +#endif + CASE_RETURN_STR(eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS); + CASE_RETURN_STR(eCSR_ROAM_SEND_P2P_STOP_BSS); +#ifdef WLAN_FEATURE_11W + CASE_RETURN_STR(eCSR_ROAM_UNPROT_MGMT_FRAME_IND); +#endif +#ifdef WLAN_FEATURE_RMC + CASE_RETURN_STR(eCSR_ROAM_IBSS_PEER_INFO_COMPLETE); +#endif +#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"; } -- cgit v1.2.3 From 6798e7829f339f579a9e989ea8c3445ab69f997b Mon Sep 17 00:00:00 2001 From: Ganesh Kondabattini Date: Fri, 11 Dec 2015 19:58:35 +0530 Subject: qcacld-3.0: Transmit tdls mgmt frames only for STA in authenticated state qcacld-2.0 to qcacld-3.0 propagation Before transmitting the tdls mgmt frames the STA should be connected to AP and it should be in authenticated state. Change-Id: Id79d4e6ad55a6b80e2fac2369f48bedf6551bcd6 CRs-Fixed: 893784 --- core/hdd/src/wlan_hdd_tdls.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 3fd99256c057..368fa31e3d19 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -3654,6 +3654,7 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_station_ctx_t *hdd_sta_ctx; u8 peerMac[CDF_MAC_ADDR_SIZE]; CDF_STATUS status; int max_sta_failed = 0; @@ -3690,6 +3691,21 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, return -ENOTSUPP; } + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* + * STA should be connected and authenticated before sending + * any TDLS frames + */ + if ((eConnectionState_Associated != + hdd_sta_ctx->conn_info.connState) || + (false == hdd_sta_ctx->conn_info.uIsAuthenticated)) { + hdd_err("STA is not connected or not authenticated. connState %u, uIsAuthenticated %u", + hdd_sta_ctx->conn_info.connState, + hdd_sta_ctx->conn_info.uIsAuthenticated); + return -EAGAIN; + } + /* If any concurrency is detected */ if (((1 << CDF_STA_MODE) != pHddCtx->concurrency_mode) || (pHddCtx->no_of_active_sessions[CDF_STA_MODE] > 1)) { @@ -3835,6 +3851,18 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, return -EINVAL; } + if ((SIR_MAC_TDLS_DIS_REQ == action_code) || + (SIR_MAC_TDLS_DIS_RSP == action_code)) { + /* for DIS_REQ/DIS_RSP, supplicant does not consider the return + * status. So no need to wait for tdls_mgmt_comp to + * send ack status. + */ + hdd_info("tx done for frm %u", action_code); + return 0; + } + hdd_info("Wait for tdls_mgmt_comp. Timeout %u ms", + WAIT_TIME_TDLS_MGMT); + rc = wait_for_completion_timeout(&pAdapter->tdls_mgmt_comp, msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); @@ -3859,6 +3887,8 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, pAdapter->mgmtTxCompletionStatus = false; return -EINVAL; } + hdd_info("Mgmt Tx Completion status %ld TxCompletion %u", + rc, pAdapter->mgmtTxCompletionStatus); if (max_sta_failed) { return max_sta_failed; -- cgit v1.2.3 From 2ad401a79d247aaab28d044f3b83d2dacdbf3e77 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Wed, 2 Dec 2015 18:13:22 +0530 Subject: qcacld-3.0: Make data length as zero whenever we free the data qcacld-2.0 to qcacld-3.0 propagation In limSendSmeJoinReassocRsp API, assoc req, assoc rsp, ricData, tspecIes are sent to SME layer if corresponding pointer in psessionEntry is not NULL. There is bug here where the pointer is NULL but the length is non zero. Because of this data is copied at incorrect offset and data at SME layer is not at right offset leading to corrupted IE in next re-assoc request. Fix this by making length as zero whenever we free the data. Change-Id: I4ba4ff49e56bc2f2758d869eae8ff9370b0c0489 CRs-Fixed: 932712 --- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 3 ++ core/mac/src/pe/lim/lim_process_beacon_frame.c | 1 + core/mac/src/pe/lim/lim_process_probe_rsp_frame.c | 1 + core/mac/src/pe/lim/lim_send_management_frames.c | 1 + core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 39 +++++++++++++++-------- core/mac/src/pe/lim/lim_session.c | 3 ++ 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index a73fa87a22fd..be37a64b9232 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -381,6 +381,7 @@ static void lim_update_ric_data(tpAniSirGlobal mac_ctx, if (session_entry->ricData != NULL) { cdf_mem_free(session_entry->ricData); session_entry->ricData = NULL; + session_entry->RICDataLen = 0; } if (assoc_rsp->ricPresent) { session_entry->RICDataLen = @@ -429,6 +430,7 @@ static void lim_update_ese_tspec(tpAniSirGlobal mac_ctx, if (session_entry->tspecIes != NULL) { cdf_mem_free(session_entry->tspecIes); session_entry->tspecIes = NULL; + session_entry->tspecLen = 0; } if (assoc_rsp->tspecPresent) { lim_log(mac_ctx, LOG1, FL("Tspec EID present in assoc rsp")); @@ -745,6 +747,7 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, "and setting NULL")); cdf_mem_free(session_entry->assocRsp); session_entry->assocRsp = NULL; + session_entry->assocRspLen = 0; } session_entry->assocRsp = cdf_mem_malloc(frame_len); diff --git a/core/mac/src/pe/lim/lim_process_beacon_frame.c b/core/mac/src/pe/lim/lim_process_beacon_frame.c index 18c05fd653f4..6d8075149a71 100644 --- a/core/mac/src/pe/lim/lim_process_beacon_frame.c +++ b/core/mac/src/pe/lim/lim_process_beacon_frame.c @@ -150,6 +150,7 @@ lim_process_beacon_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, if (session->beacon != NULL) { cdf_mem_free(session->beacon); session->beacon = NULL; + session->bcnLen = 0; } session->bcnLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); session->beacon = cdf_mem_malloc(session->bcnLen); diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c index 0096b48cab36..1cfd74340774 100644 --- a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c @@ -161,6 +161,7 @@ lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info, if (session_entry->beacon != NULL) { cdf_mem_free(session_entry->beacon); session_entry->beacon = NULL; + session_entry->bcnLen = 0; } session_entry->bcnLen = WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info); diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 50884de03e6f..e33d95bf894a 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -2358,6 +2358,7 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, if (NULL != pe_session->assocReq) { cdf_mem_free(pe_session->assocReq); pe_session->assocReq = NULL; + pe_session->assocReqLen = 0; } if (ft_ies_length) { pe_session->assocReq = cdf_mem_malloc(ft_ies_length); diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 326dfc7576a0..470f11958ec1 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -271,48 +271,53 @@ static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, sme_join_rsp->beaconLength); cdf_mem_free(session_entry->beacon); session_entry->beacon = NULL; + session_entry->bcnLen = 0; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG lim_log(mac_ctx, LOG1, FL("Beacon=%d"), - session_entry->bcnLen); + sme_join_rsp->beaconLength); #endif } if (session_entry->assocReq != NULL) { sme_join_rsp->assocReqLength = session_entry->assocReqLen; cdf_mem_copy(sme_join_rsp->frames + - session_entry->bcnLen, session_entry->assocReq, + sme_join_rsp->beaconLength, + session_entry->assocReq, sme_join_rsp->assocReqLength); cdf_mem_free(session_entry->assocReq); session_entry->assocReq = NULL; + session_entry->assocReqLen = 0; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG lim_log(mac_ctx, LOG1, FL("AssocReq=%d"), - session_entry->assocReqLen); + sme_join_rsp->assocReqLength); #endif } if (session_entry->assocRsp != NULL) { sme_join_rsp->assocRspLength = session_entry->assocRspLen; cdf_mem_copy(sme_join_rsp->frames + - session_entry->bcnLen + - session_entry->assocReqLen, + sme_join_rsp->beaconLength + + sme_join_rsp->assocReqLength, session_entry->assocRsp, sme_join_rsp->assocRspLength); cdf_mem_free(session_entry->assocRsp); session_entry->assocRsp = NULL; + session_entry->assocRspLen = 0; } #ifdef WLAN_FEATURE_VOWIFI_11R if (session_entry->ricData != NULL) { sme_join_rsp->parsedRicRspLen = session_entry->RICDataLen; cdf_mem_copy(sme_join_rsp->frames + - session_entry->bcnLen + - session_entry->assocReqLen + - session_entry->assocRspLen, + sme_join_rsp->beaconLength + + sme_join_rsp->assocReqLength + + sme_join_rsp->assocRspLength, session_entry->ricData, sme_join_rsp->parsedRicRspLen); cdf_mem_free(session_entry->ricData); session_entry->ricData = NULL; + session_entry->RICDataLen = 0; lim_log(mac_ctx, LOG1, FL("RicLength=%d"), sme_join_rsp->parsedRicRspLen); } @@ -322,22 +327,23 @@ static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, sme_join_rsp->tspecIeLen = session_entry->tspecLen; cdf_mem_copy(sme_join_rsp->frames + - session_entry->bcnLen + - session_entry->assocReqLen + - session_entry->assocRspLen + - session_entry->RICDataLen, + sme_join_rsp->beaconLength + + sme_join_rsp->assocReqLength + + sme_join_rsp->assocRspLength + + sme_join_rsp->parsedRicRspLen, session_entry->tspecIes, sme_join_rsp->tspecIeLen); cdf_mem_free(session_entry->tspecIes); session_entry->tspecIes = NULL; + session_entry->tspecLen = 0; lim_log(mac_ctx, LOG1, FL("ESE-TspecLen=%d"), - session_entry->tspecLen); + sme_join_rsp->tspecIeLen); } #endif sme_join_rsp->aid = session_entry->limAID; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG lim_log(mac_ctx, LOG1, FL("AssocRsp=%d"), - session_entry->assocRspLen); + sme_join_rsp->assocRspLength); #endif sme_join_rsp->vht_channel_width = session_entry->ch_width; @@ -367,25 +373,30 @@ static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, if (session_entry->beacon != NULL) { cdf_mem_free(session_entry->beacon); session_entry->beacon = NULL; + session_entry->bcnLen = 0; } if (session_entry->assocReq != NULL) { cdf_mem_free(session_entry->assocReq); session_entry->assocReq = NULL; + session_entry->assocReqLen = 0; } if (session_entry->assocRsp != NULL) { cdf_mem_free(session_entry->assocRsp); session_entry->assocRsp = NULL; + session_entry->assocRspLen = 0; } #ifdef WLAN_FEATURE_VOWIFI_11R if (session_entry->ricData != NULL) { cdf_mem_free(session_entry->ricData); session_entry->ricData = NULL; + session_entry->RICDataLen = 0; } #endif #ifdef FEATURE_WLAN_ESE if (session_entry->tspecIes != NULL) { cdf_mem_free(session_entry->tspecIes); session_entry->tspecIes = NULL; + session_entry->tspecLen = 0; } #endif } diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 5e7f1cf6e665..2c245e94de8d 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -601,16 +601,19 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) if (session->beacon != NULL) { cdf_mem_free(session->beacon); session->beacon = NULL; + session->bcnLen = 0; } if (session->assocReq != NULL) { cdf_mem_free(session->assocReq); session->assocReq = NULL; + session->assocReqLen = 0; } if (session->assocRsp != NULL) { cdf_mem_free(session->assocRsp); session->assocRsp = NULL; + session->assocRspLen = 0; } if (session->parsedAssocReq != NULL) { -- cgit v1.2.3 From 2b0c3e2ced6b2bfb240a0d9d357c20e209c76bd9 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Fri, 18 Dec 2015 11:23:44 +0530 Subject: qcacld-3.0: If RSN IE is present ignore WPA IE to get cbmode qcacld-2.0 to qcacld-3.0 propagation if AP has RSN IE and supports AES, driver goes on to check WPA IE and if it contains only TKIP in unicast cipher, it sets cbmode to 0 (20Mhz). Added a check to ignore the WPA IE if RSN IE is present and take decision on cbmode with respect to RSN IE only. Change-Id: I4eaf8a2d6a9f3a43e74e606045af995fbaa800ad CRs-Fixed: 739345 --- core/sme/src/csr/csr_api_roam.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index aa08d033a091..7c58fde0ba36 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -11934,12 +11934,13 @@ static ePhyChanBondState csr_get_cb_mode_from_ies(tpAniSirGlobal pMac, 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 WPA1 and TKIP is the only one cipher suite - * in Unicast. + /* In Case only WPA1 is supported and TKIP is + * the only one cipher suite in Unicast. */ - || (pIes->WPA.present && (pIes->WPA.unicast_cipher_count == 1) - && !memcmp(&(pIes->WPA.unicast_ciphers[0][0]), - "\x00\x50\xf2\x02", 4))) { + || (!pIes->RSN.present && (pIes->WPA.present && + (pIes->WPA.unicast_cipher_count == 1) && + !memcmp(&(pIes->WPA.unicast_ciphers[0][0]), + "\x00\x50\xf2\x02", 4)))) { sms_log(pMac, LOGW, " No channel bonding in TKIP mode "); return PHY_SINGLE_CHANNEL_CENTERED; -- cgit v1.2.3 From 0b4f0c6c162a87ffa2cd0e5180a2b0c76926c2f2 Mon Sep 17 00:00:00 2001 From: Ganesh Kondabattini Date: Mon, 30 Nov 2015 11:55:40 +0530 Subject: qcacld-3.0: set TX_USAGE flag for bss key in AP mode. qcacld-2.0 to qcacld-3.0 propagation Set TX_USAGE flag for default key (BSS key) when using WEP40 or WEP140 encryption in AP mode. Change-Id: Icb4411410d84b05a47f193ffbd632445f736246e CRs-Fixed: 940725 --- core/wma/src/wma_mgmt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 52719d97b35b..fd887da84239 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1459,8 +1459,14 @@ static wmi_buf_t wma_setup_install_key_cmd(tp_wma_handle wma_handle, case eSIR_ED_WEP104: cmd->key_cipher = WMI_CIPHER_WEP; if (key_params->unicast && - cmd->key_ix == key_params->def_key_idx) + cmd->key_ix == key_params->def_key_idx) { + WMA_LOGD("STA Mode: cmd->key_flags |= TX_USAGE"); cmd->key_flags |= TX_USAGE; + } else if ((mode == wlan_op_mode_ap) && + (cmd->key_ix == key_params->def_key_idx)) { + WMA_LOGD("AP Mode: cmd->key_flags |= TX_USAGE"); + cmd->key_flags |= TX_USAGE; + } break; case eSIR_ED_TKIP: cmd->key_txmic_len = WMA_TXMIC_LEN; -- cgit v1.2.3 From 12650916478b166532570aa701186e538264bd55 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 16 Dec 2015 14:28:48 +0530 Subject: qcacld-3.0: Delete preauth session in case of deauth from host qcacld-2.0 to qcacld-3.0 propagation The preauth session is not deleted if the deauth is from host (eCsrForcedDeauth). Adds the check to delete the preauth session and stop the preAuthReassocIntvlTimer timer, in case of deauth from host. Change-Id: I181344b0f3a41ff5c3a77f30b4c8cf80557c23b5 CRs-fixed: 649521 --- core/mac/src/pe/lim/lim_send_management_frames.c | 38 ++++++++++++++++++++++++ core/sme/src/csr/csr_api_roam.c | 34 +++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index e33d95bf894a..62f452b6e97a 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -3076,6 +3076,44 @@ CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac) /* / Receive path cleanup with dummy packet */ lim_ft_cleanup_pre_auth_info(pMac, psessionEntry); lim_cleanup_rx_path(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(lim_log(pMac, LOGE, + FL("FT Preauth Session (%p,%d) Cleanup Deauth reason %d Trigger = %d"), + psessionEntry, psessionEntry->peSessionId, + pMlmDeauthReq->reasonCode, + pMlmDeauthReq->deauthTrigger);); + lim_ft_cleanup(pMac, psessionEntry); + } else { + PELOGE(lim_log(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 */ cdf_mem_free(pMlmDeauthReq); pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7c58fde0ba36..44908ed713a6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7524,6 +7524,40 @@ CDF_STATUS csr_roam_process_disassoc_deauth(tpAniSirGlobal pMac, tSmeCmd *pComma 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 (csr_roam_is11r_assoc(pMac, sessionId) && + (csr_neighbor_roam_state_preauth_done(pMac, + sessionId))) { + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + pMac, sessionId); + } +#endif +#ifdef FEATURE_WLAN_ESE + if (csr_roam_is_ese_assoc(pMac, sessionId) && + (csr_neighbor_roam_state_preauth_done(pMac, + sessionId))) { + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + pMac, sessionId); + } +#endif +#ifdef FEATURE_WLAN_LFR + if (csr_roam_is_fast_roam_enabled(pMac, sessionId) && + (csr_neighbor_roam_state_preauth_done(pMac, + sessionId))) { + csr_neighbor_roam_tranistion_preauth_done_to_disconnected( + pMac, sessionId); + } +#endif + } if (fDisassoc) { status = csr_roam_issue_disassociate(pMac, sessionId, -- cgit v1.2.3 From ec647396357b71d2ccf8b5a7f433f069ed69afed Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Wed, 28 Oct 2015 23:58:24 -0700 Subject: qcacld-3.0: Remove #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING from HDD The condition #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING is used to include some of the roaming code. It has been defined for all the recent driver builds. Roaming code underneath is permanent part of the driver. Remove #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING compiler flag from HDD so that the code will always be compiled in. CRs-Fixed: 936683 Change-Id: I777d48f26aea36383747281bd4fef2eadc7beefb --- core/hdd/inc/wlan_hdd_cfg.h | 4 ---- core/hdd/src/wlan_hdd_cfg.c | 10 ---------- core/hdd/src/wlan_hdd_ioctl.c | 2 -- core/sme/inc/csr_api.h | 2 -- 4 files changed, 18 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index e6a7d36ec954..a34ef7ae9fe3 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -884,7 +884,6 @@ typedef enum { #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) @@ -964,7 +963,6 @@ typedef enum { #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) @@ -2907,7 +2905,6 @@ struct hdd_config { bool fFTResourceReqSupported; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING uint16_t nNeighborScanPeriod; uint8_t nNeighborLookupRssiThreshold; uint8_t delay_before_vdev_stop; @@ -2926,7 +2923,6 @@ struct hdd_config { uint32_t nhi_rssi_scan_rssi_delta; uint32_t nhi_rssi_scan_delay; int32_t nhi_rssi_scan_rssi_ub; -#endif /* Additional Handoff params */ uint32_t nRoamingTime; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index b15405ef331c..42c8002becfa 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -149,7 +149,6 @@ cb_notify_set_fw_rssi_monitoring(hdd_context_t *pHddCtx, unsigned long notifyId) fEnableFwRssiMonitoring); } -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING static void cb_notify_set_opportunistic_scan_threshold_diff(hdd_context_t *pHddCtx, unsigned long notifyId) { @@ -275,8 +274,6 @@ cb_notify_set_dfs_scan_mode(hdd_context_t *pHddCtx, unsigned long notifyId) pHddCtx->config->allowDFSChannelRoam); } -#endif - static void cb_notify_set_enable_ssr(hdd_context_t *pHddCtx, unsigned long notifyId) { @@ -1350,7 +1347,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_FT_RESOURCE_REQ_MAX), #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING REG_DYNAMIC_VARIABLE(CFG_NEIGHBOR_SCAN_TIMER_PERIOD_NAME, WLAN_PARAM_Integer, struct hdd_config, nNeighborScanPeriod, @@ -1539,8 +1535,6 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, struct hdd_config, burstSizeDefinition, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -4755,7 +4749,6 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) pHddCtx->config->fFTResourceReqSupported); #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborLookupRssiThreshold] Value = [%u] ", pHddCtx->config->nNeighborLookupRssiThreshold); @@ -4810,7 +4803,6 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [nhi_rssi_scan_rssi_ub] Value = [%u] ", pHddCtx->config->nhi_rssi_scan_rssi_ub); -#endif CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [burstSizeDefinition] Value = [0x%x] ", pHddCtx->config->burstSizeDefinition); @@ -6525,7 +6517,6 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) /* Disable roaming in concurrency if roam scan offload is disabled */ smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = 0; } -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING smeConfig->csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold; smeConfig->csrConfig.neighborRoamConfig.delay_before_vdev_stop = @@ -6566,7 +6557,6 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) 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; diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 6fc55c587922..2a768974774d 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -5969,7 +5969,6 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = { {"SET_AP_WPS_P2P_IE", drv_cmd_dummy}, {"BTCOEXSCAN", drv_cmd_dummy}, {"RXFILTER", drv_cmd_dummy}, -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING {"SETROAMTRIGGER", drv_cmd_set_roam_trigger}, {"GETROAMTRIGGER", drv_cmd_get_roam_trigger}, {"SETROAMSCANPERIOD", drv_cmd_set_roam_scan_period}, @@ -5980,7 +5979,6 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = { {"SETROAMMODE", drv_cmd_set_roam_mode}, {"GETROAMMODE", drv_cmd_get_roam_mode}, #endif -#endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) {"SETROAMDELTA", drv_cmd_set_roam_delta}, {"GETROAMDELTA", drv_cmd_get_roam_delta}, diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 0ba6b035acf7..b74e411153f9 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -814,7 +814,6 @@ typedef enum { eCSR_HDD } eCsrStatsRequesterType; -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING /** * enum csr_hi_rssi_scan_id - Parameter ids for hi rssi scan feature * @@ -829,7 +828,6 @@ enum csr_hi_rssi_scan_id { eCSR_HI_RSSI_SCAN_DELAY_ID, eCSR_HI_RSSI_SCAN_RSSI_UB_ID }; -#endif typedef struct tagPmkidCandidateInfo { struct cdf_mac_addr BSSID; -- cgit v1.2.3 From b45399a48b5ccab044ae67b3b592bcb1be175c58 Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Sat, 7 Nov 2015 00:23:22 -0800 Subject: qcacld-3.0: Remove #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING from SME The condition #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING is used to include some of the roaming code. It has been defined for all the recent driver builds. Roaming code underneath is permanent part of the driver. Remove #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING compiler flag from SME and CSR so that the code will always be compiled in. CRs-Fixed: 936683 Change-Id: I63a43b7cfd9360341d4ac4126cbf9fc8ac89071a --- core/sme/inc/csr_api.h | 4 -- core/sme/inc/csr_internal.h | 8 ---- core/sme/inc/csr_neighbor_roam.h | 2 - core/sme/inc/sme_api.h | 2 - core/sme/src/common/sme_api.c | 2 - core/sme/src/common/sme_ft_api.c | 2 - core/sme/src/csr/csr_api_roam.c | 89 ++++++++++-------------------------- core/sme/src/csr/csr_neighbor_roam.c | 6 +-- 8 files changed, 27 insertions(+), 88 deletions(-) diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index b74e411153f9..e7df8894e350 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1035,7 +1035,6 @@ typedef struct tagCsr11rConfigParams { } tCsr11rConfigParams; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING typedef struct tagCsrNeighborRoamConfigParams { uint32_t nNeighborScanTimerPeriod; @@ -1057,7 +1056,6 @@ typedef struct tagCsrNeighborRoamConfigParams { uint32_t nhi_rssi_scan_delay; int32_t nhi_rssi_scan_rssi_ub; } tCsrNeighborRoamConfigParams; -#endif typedef struct tagCsrConfigParam { uint32_t FragmentationThreshold; @@ -1158,9 +1156,7 @@ typedef struct tagCsrConfigParam { uint8_t RoamRssiDiff; bool 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 diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 0dc1db38f7a8..76288c29bae6 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -40,9 +40,7 @@ #include "csr_support.h" #include "cds_reg_service.h" -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING #include "csr_neighbor_roam.h" -#endif #include "sir_types.h" @@ -464,7 +462,6 @@ typedef struct tagCsr11rConfig { } tCsr11rConfig; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING typedef struct tagCsrNeighborRoamConfig { uint32_t nNeighborScanTimerPeriod; uint8_t nNeighborLookupRssiThreshold; @@ -485,7 +482,6 @@ typedef struct tagCsrNeighborRoamConfig { uint32_t nhi_rssi_scan_delay; int32_t nhi_rssi_scan_rssi_ub; } tCsrNeighborRoamConfig; -#endif typedef struct tagCsrConfig { uint32_t agingCount; @@ -591,9 +587,7 @@ typedef struct tagCsrConfig { uint16_t nRoamScanHomeAwayTime; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING tCsrNeighborRoamConfig neighborRoamConfig; -#endif /* * Instead of Reassoc, send ADDTS/DELTS even when ACM is off for @@ -1022,9 +1016,7 @@ typedef struct tagCsrRoamStruct { tCsrTimerInfo WaitForKeyTimerInfo; tCsrRoamSession *roamSession; uint32_t transactionId; /* Current transaction ID for internal use. */ -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING tCsrNeighborRoamControlInfo neighborRoamInfo[CSR_ROAM_SESSION_MAX]; -#endif #ifdef FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; #endif diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 6bf27d01a963..10dfaa05d915 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -35,7 +35,6 @@ #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 @@ -307,5 +306,4 @@ CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, CDF_STATUS csr_neighbor_roam_offload_update_preauth_list(tpAniSirGlobal pMac, roam_offload_synch_ind *roam_synch_ind_ptr, uint8_t sessionId); #endif -#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ #endif /* CSR_NEIGHBOR_ROAM_H */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 748652169697..f99f70b83eee 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -615,7 +615,6 @@ CDF_STATUS sme_update_is_ese_feature_enabled(tHalHandle hHal, uint8_t sessionId, #endif /* FEATURE_WLAN_ESE */ CDF_STATUS sme_update_config_fw_rssi_monitoring(tHalHandle hHal, bool fEnableFwRssiMonitoring); -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING CDF_STATUS sme_set_roam_rescan_rssi_diff(tHalHandle hHal, uint8_t sessionId, const uint8_t nRoamRescanRssiDiff); @@ -665,7 +664,6 @@ uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal); CDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal, uint8_t sessionId, const uint8_t nRoamBeaconRssiWeight); uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal); -#endif #if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ defined(FEATURE_WLAN_LFR) uint8_t sme_get_roam_rssi_diff(tHalHandle hHal); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index bca29ecb6c8e..e8fe27604ef3 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -8610,7 +8610,6 @@ CDF_STATUS sme_update_config_fw_rssi_monitoring(tHalHandle hHal, return cdf_ret_status; } -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING /* --------------------------------------------------------------------------- \fn sme_set_roam_opportunistic_scan_threshold_diff \brief Update Opportunistic Scan threshold diff @@ -9424,7 +9423,6 @@ uint16_t sme_get_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId) neighborScanPeriod; } -#endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) diff --git a/core/sme/src/common/sme_ft_api.c b/core/sme/src/common/sme_ft_api.c index b48e13f10cb3..8f141861a33c 100644 --- a/core/sme/src/common/sme_ft_api.c +++ b/core/sme/src/common/sme_ft_api.c @@ -561,14 +561,12 @@ void sme_get_rici_es(tHalHandle hHal, uint32_t sessionId, uint8_t *ric_ies, *------------------------------------------------------------------------*/ void sme_preauth_reassoc_intvl_timer_callback(void *context) { -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING tFTRoamCallbackUsrCtx *pUsrCtx = (tFTRoamCallbackUsrCtx *) context; if (pUsrCtx) { csr_neighbor_roam_request_handoff(pUsrCtx->pMac, pUsrCtx->sessionId); } -#endif return; } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 44908ed713a6..a8f575486a73 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -47,9 +47,7 @@ #include "csr_internal.h" #include "cds_reg_service.h" #include "mac_trace.h" -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING #include "csr_neighbor_roam.h" -#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ #include "cds_regdomain_common.h" #include "cds_utils.h" #include "sir_types.h" @@ -712,10 +710,8 @@ CDF_STATUS csr_start(tpAniSirGlobal pMac) pMac->roam.sPendingCommands = 0; csr_scan_enable(pMac); -#if defined WLAN_FEATURE_NEIGHBOR_ROAMING for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) status = csr_neighbor_roam_init(pMac, i); -#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ pMac->roam.tlStatsReqInfo.numClient = 0; pMac->roam.tlStatsReqInfo.periodicity = 0; pMac->roam.tlStatsReqInfo.timerRunning = false; @@ -747,10 +743,8 @@ CDF_STATUS csr_stop(tpAniSirGlobal pMac, tHalStopType stopType) pMac->scan.fRestartIdleScan = false; csr_ll_purge(&pMac->roam.roamCmdPendingList, true); -#if defined WLAN_FEATURE_NEIGHBOR_ROAMING for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) csr_neighbor_roam_close(pMac, sessionId); -#endif for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) if (CSR_IS_SESSION_VALID(pMac, sessionId)) csr_scan_flush_result(pMac); @@ -1272,7 +1266,6 @@ static void init_config_param(tpAniSirGlobal pMac) #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; @@ -1296,7 +1289,6 @@ static void init_config_param(tpAniSirGlobal pMac) 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; @@ -1888,7 +1880,6 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pMac->roam.configParam.isEseIniFeatureEnabled = pParam->isEseIniFeatureEnabled; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING cdf_mem_copy(&pMac->roam.configParam.neighborRoamConfig, &pParam->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams)); @@ -1944,7 +1935,6 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, sms_log(pMac, LOG1, "nRoamBeaconRssiWeight = %d", pMac->roam.configParam.neighborRoamConfig. nRoamBeaconRssiWeight); -#endif pMac->roam.configParam.addTSWhenACMIsOff = pParam->addTSWhenACMIsOff; pMac->scan.fValidateList = pParam->fValidateList; @@ -2087,11 +2077,9 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->fEnableMCCMode = cfg_params->fenableMCCMode; pParam->fAllowMCCGODiffBI = cfg_params->fAllowMCCGODiffBI; pParam->scanCfgAgingTime = pMac->scan.scanResultCfgAgingTime; -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING cdf_mem_copy(&pParam->neighborRoamConfig, &cfg_params->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams)); -#endif #ifdef WLAN_FEATURE_11AC pParam->nVhtChannelWidth = cfg_params->nVhtChannelWidth; pParam->enableTxBF = cfg_params->txBFEnable; @@ -2124,7 +2112,6 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) #ifdef FEATURE_WLAN_ESE pParam->isEseIniFeatureEnabled = cfg_params->isEseIniFeatureEnabled; #endif -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING cdf_mem_copy(&pParam->neighborRoamConfig, &cfg_params->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams)); @@ -2138,7 +2125,6 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) cfg_params->neighborRoamConfig. neighborScanChanList.channelList[i]); } -#endif #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH pParam->cc_switch_mode = cfg_params->cc_switch_mode; @@ -2908,11 +2894,7 @@ CDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId, /* Returns whether handoff is currently in progress or not */ bool csr_roam_is_handoff_in_progress(tpAniSirGlobal pMac, uint8_t sessionId) { -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING return csr_neighbor_roam_is_handoff_in_progress(pMac, sessionId); -#else - return false; -#endif } CDF_STATUS csr_roam_issue_disassociate(tpAniSirGlobal pMac, uint32_t sessionId, @@ -5451,22 +5433,14 @@ static CDF_STATUS csr_roam_save_security_rsp_ie(tpAniSirGlobal pMac, /* Returns whether the current association is a 11r assoc or not */ bool csr_roam_is11r_assoc(tpAniSirGlobal pMac, uint8_t sessionId) { -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING return csr_neighbor_roam_is11r_assoc(pMac, sessionId); -#else - return false; -#endif } #endif #ifdef FEATURE_WLAN_ESE /* Returns whether the current association is a ESE assoc or not */ bool csr_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId) { -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING return csr_neighbor_roam_is_ese_assoc(pMac, sessionId); -#else - return false; -#endif } #endif #ifdef FEATURE_WLAN_LFR @@ -5720,7 +5694,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, &session->joinFailStatusCode.bssId, sizeof(struct cdf_mac_addr)); -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING /* * If Join fails while Handoff is in progress, indicate * disassociated event to supplicant to reconnect @@ -5729,7 +5702,6 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, csr_neighbor_roam_indicate_connect(mac_ctx, (uint8_t)session_id, CDF_STATUS_E_FAILURE); } -#endif if (session->bRefAssocStartCnt > 0) { session->bRefAssocStartCnt--; if (eCsrJoinFailureDueToConcurrency == res) @@ -7997,7 +7969,6 @@ static void csr_roam_join_rsp_processor(tpAniSirGlobal pMac, sms_log(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 (csr_roam_is_handoff_in_progress(pMac, pSmeJoinRsp->sessionId)) { csr_roam_call_callback(pMac, pSmeJoinRsp->sessionId, NULL, @@ -8008,7 +7979,6 @@ static void csr_roam_join_rsp_processor(tpAniSirGlobal pMac, pSmeJoinRsp->sessionId, CDF_STATUS_E_FAILURE); } -#endif /* * if userspace has issued disconnection, * driver should not continue connecting @@ -8523,18 +8493,17 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, FL("CSR SmeReassocReq Successful")); result = eCsrReassocSuccess; - /* Defeaturize this part later if needed */ -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING - /* Since the neighbor roam algorithm uses reassoc req for handoff instead of join, - * we need the response contents while processing the result in csr_roam_process_results() */ + /* + * Since the neighbor roam algorithm uses reassoc req for + * handoff instead of join, we need the response contents while + * processing the result in csr_roam_process_results() + */ if (csr_roam_is_handoff_in_progress(pMac, pSmeJoinRsp->sessionId)) { /* Need to dig more on indicating events to SME QoS module */ sme_qos_csr_event_ind(pMac, pSmeJoinRsp->sessionId, SME_QOS_CSR_HANDOFF_COMPLETE, NULL); csr_roam_complete(pMac, result, pSmeJoinRsp); - } else -#endif - { + } else { csr_roam_complete(pMac, result, NULL); } } @@ -8758,13 +8727,11 @@ csr_check_profile_in_scan_cache(tpAniSirGlobal mac_ctx, void csr_roam_roaming_state_disassoc_rsp_processor(tpAniSirGlobal pMac, tSirSmeDisassocRsp *pSmeRsp) { -#if defined WLAN_FEATURE_NEIGHBOR_ROAMING tScanResultHandle hBSSList; tCsrRoamInfo roamInfo; tCsrScanResultFilter *pScanFilter = NULL; uint32_t roamId = 0; tCsrRoamProfile *pCurRoamProfile = NULL; -#endif CDF_STATUS status; uint32_t sessionId; tCsrRoamSession *pSession; @@ -8806,7 +8773,6 @@ void csr_roam_roaming_state_disassoc_rsp_processor(tpAniSirGlobal pMac, FL("CSR SmeDisassocReq due to HO on session %d"), sessionId); pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING /* * First ensure if the roam profile is in the scan cache. * If not, post a reassoc failure and disconnect. @@ -8866,9 +8832,8 @@ void csr_roam_roaming_state_disassoc_rsp_processor(tpAniSirGlobal pMac, } POST_ROAM_FAILURE: - csr_post_roam_failure(pMac, sessionId, &roamInfo, + csr_post_roam_failure(pMac, sessionId, &roamInfo, pScanFilter, pCurRoamProfile); -#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 */ @@ -15231,32 +15196,32 @@ static uint32_t csr_find_ibss_session(tpAniSirGlobal pMac) static void csr_roam_link_up(tpAniSirGlobal pMac, struct cdf_mac_addr bssid) { - /* Update the current BSS info in ho control block based on connected - profile info from pmac global structure */ + uint32_t sessionId = 0; + + /* + * Update the current BSS info in ho control block based on connected + * profile info from pmac global structure + */ sms_log(pMac, LOGW, " csr_roam_link_up: WLAN link UP with AP= " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid.bytes)); - /* Check for user misconfig of RSSI trigger threshold */ + /* 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; + 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 */ + /* 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 - { - uint32_t sessionId = 0; - /* Indicate the neighbor roal algorithm about the connect indication */ - csr_roam_get_session_id_from_bssid(pMac, &bssid, - &sessionId); - csr_neighbor_roam_indicate_connect(pMac, sessionId, - CDF_STATUS_SUCCESS); - } -#endif + /* Indicate the neighbor roal algorithm about the connect indication */ + csr_roam_get_session_id_from_bssid(pMac, &bssid, + &sessionId); + csr_neighbor_roam_indicate_connect(pMac, sessionId, + CDF_STATUS_SUCCESS); } static void csr_roam_link_down(tpAniSirGlobal pMac, uint32_t sessionId) @@ -15290,10 +15255,8 @@ static void csr_roam_link_down(tpAniSirGlobal pMac, uint32_t sessionId) /* deregister the clients requesting stats from PE/TL & also stop the corresponding timers */ csr_roam_dereg_statistics_req(pMac); pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND; -#if defined WLAN_FEATURE_NEIGHBOR_ROAMING /* Indicate the neighbor roal algorithm about the disconnect indication */ csr_neighbor_roam_indicate_disconnect(pMac, sessionId); -#endif /* Remove this code once SLM_Sessionization is supported */ /* BMPS_WORKAROUND_NOT_NEEDED */ @@ -17744,10 +17707,9 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, sms_log(pMac, LOGE, FL("pSession is NULL")); return; } -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING - status = - csr_neighbor_roam_preauth_rsp_handler(pMac, pFTPreAuthRsp->smeSessionId, - pFTPreAuthRsp->status); + status = csr_neighbor_roam_preauth_rsp_handler(pMac, + pFTPreAuthRsp->smeSessionId, + pFTPreAuthRsp->status); if (status != CDF_STATUS_SUCCESS) { /* * Bail out if pre-auth was not even processed. @@ -17757,7 +17719,6 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, status, sessionId); return; } -#endif /* The below function calls/timers should be invoked only if the pre-auth is successful */ if (CDF_STATUS_SUCCESS != (CDF_STATUS) pFTPreAuthRsp->status) diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 31cae0c215ba..b015bb855a46 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -34,7 +34,6 @@ transitions and Legacy roaming for Android platform. ========================================================================== */ -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING #include "wma_types.h" #include "cds_mq.h" #include "csr_inside_api.h" @@ -1121,7 +1120,7 @@ DEQ_PREAUTH: csr_dequeue_roam_command(mac_ctx, eCsrPerformPreauth); return preauth_processed; } -#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ +#endif /* WLAN_FEATURE_VOWIFI_11R */ #ifdef WLAN_FEATURE_ROAM_OFFLOAD /** @@ -3046,7 +3045,7 @@ bool csr_neighbor_roam_is_handoff_in_progress(tpAniSirGlobal pMac, uint8_t sessi return false; } -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(WLAN_FEATURE_NEIGHBOR_ROAMING) +#if defined(WLAN_FEATURE_VOWIFI_11R) /* --------------------------------------------------------------------------- \fn csr_neighbor_roam_is11r_assoc @@ -3553,4 +3552,3 @@ CDF_STATUS csr_neighbor_roam_start_lfr_scan(tpAniSirGlobal pMac, uint8_t session return CDF_STATUS_SUCCESS; } -#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ -- cgit v1.2.3 From efcc4aa288525cee6a3e574dd473d05cf370f852 Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Sun, 8 Nov 2015 01:16:43 -0800 Subject: qcacld-3.0: Remove #ifdef FEATURE_WLAN_LFR from SME The condition #ifdef WLAN_FEATURE_LFR is used to include some of the roaming code. It has been defined for all the recent driver builds. Roaming code underneath is permanent part of the driver. Remove #ifdef FEATURE_WLAN_LFR compiler flag from SME so that the code will always be compiled in. CRs-Fixed: 936683 Change-Id: I86b9e3dee6b92c89a54de6df769800c31fc3ad17 --- core/sme/inc/csr_api.h | 10 ------ core/sme/inc/csr_internal.h | 15 -------- core/sme/inc/csr_neighbor_roam.h | 4 --- core/sme/inc/sme_api.h | 13 ------- core/sme/inc/sme_inside.h | 3 -- core/sme/src/common/sme_api.c | 10 ------ core/sme/src/csr/csr_api_roam.c | 67 +++++++----------------------------- core/sme/src/csr/csr_api_scan.c | 14 -------- core/sme/src/csr/csr_inside_api.h | 4 --- core/sme/src/csr/csr_neighbor_roam.c | 31 +---------------- core/sme/src/csr/csr_util.c | 7 +--- core/sme/src/qos/sme_qos.c | 4 --- 12 files changed, 15 insertions(+), 167 deletions(-) diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index e7df8894e350..954458eb4c52 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -486,9 +486,7 @@ typedef enum { /* this mean error happens before assoc_start/roam_start is called. */ eCSR_ROAM_SESSION_OPENED, eCSR_ROAM_FT_REASSOC_FAILED, -#ifdef FEATURE_WLAN_LFR eCSR_ROAM_PMK_NOTIFY, -#endif /* * Following 4 enums are used by FEATURE_WLAN_LFR_METRICS * but they are needed for compilation even when @@ -1146,16 +1144,11 @@ typedef struct tagCsrConfigParam { #ifdef FEATURE_WLAN_ESE uint8_t isEseIniFeatureEnabled; #endif -#ifdef FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; uint8_t MAWCEnabled; -#endif -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) uint8_t isFastTransitionEnabled; uint8_t RoamRssiDiff; bool isWESModeEnabled; -#endif tCsrNeighborRoamConfigParams neighborRoamConfig; /* * Instead of Reassoc, send ADDTS/DELTS even when ACM is off for that AC @@ -1204,8 +1197,6 @@ typedef struct tagCsrConfigParam { * To enable/disable scanning only 2.4Ghz channels on first scan */ bool fFirstScanOnly2GChnl; -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) bool nRoamPrefer5GHz; bool nRoamIntraBand; uint8_t nProbes; @@ -1213,7 +1204,6 @@ typedef struct tagCsrConfigParam { bool isRoamOffloadScanEnabled; bool bFastRoamInConIniFeatureEnabled; -#endif uint8_t scanCfgAgingTime; uint8_t enableTxLdpc; uint8_t isAmsduSupportInAMPDU; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 76288c29bae6..7ccddc2541d3 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -77,8 +77,6 @@ (((pMac)->roam.configParam.roam_params.is_5g_pref_enabled) ? \ true : 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) ? true : false) \ @@ -87,7 +85,6 @@ ( \ (((pMac)->roam.configParam.nRoamIntraBand) ? true : false) \ ) -#endif #define CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac) \ ( \ (((pMac)->roam.configParam.bFastRoamInConIniFeatureEnabled) ? \ @@ -566,17 +563,13 @@ typedef struct tagCsrConfig { #ifdef WLAN_FEATURE_VOWIFI_11R tCsr11rConfig csr11rConfig; #endif -#ifdef FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; uint8_t MAWCEnabled; uint8_t isRoamOffloadScanEnabled; bool bFastRoamInConIniFeatureEnabled; -#endif #ifdef FEATURE_WLAN_ESE uint8_t isEseIniFeatureEnabled; #endif -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) \ - || defined(FEATURE_WLAN_LFR) uint8_t isFastTransitionEnabled; uint8_t RoamRssiDiff; bool nRoamPrefer5GHz; @@ -585,7 +578,6 @@ typedef struct tagCsrConfig { bool nRoamScanControl; uint8_t nProbes; uint16_t nRoamScanHomeAwayTime; -#endif tCsrNeighborRoamConfig neighborRoamConfig; @@ -1017,17 +1009,12 @@ typedef struct tagCsrRoamStruct { tCsrRoamSession *roamSession; uint32_t transactionId; /* Current transaction ID for internal use. */ tCsrNeighborRoamControlInfo neighborRoamInfo[CSR_ROAM_SESSION_MAX]; -#ifdef FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; -#endif #ifdef FEATURE_WLAN_ESE uint8_t isEseIniFeatureEnabled; #endif -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) \ - || defined(FEATURE_WLAN_LFR) uint8_t RoamRssiDiff; bool isWESModeEnabled; -#endif uint32_t deauthRspStatus; #ifdef WLAN_FEATURE_ROAM_OFFLOAD uint8_t *pReassocResp; /* reassociation response from new AP */ @@ -1326,7 +1313,6 @@ bool csr_neighbor_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId); /* Remove this code once SLM_Sessionization is supported */ void csr_disconnect_all_active_sessions(tpAniSirGlobal pMac); -#ifdef FEATURE_WLAN_LFR /* Returns whether "Legacy Fast Roaming" is enabled...or not */ bool csr_roam_is_fast_roam_enabled(tpAniSirGlobal pMac, uint32_t sessionId); bool csr_roam_is_roam_offload_scan_enabled(tpAniSirGlobal pMac); @@ -1339,7 +1325,6 @@ CDF_STATUS csr_roam_offload_scan_rsp_hdlr(tpAniSirGlobal pMac, CDF_STATUS csr_handoff_request(tpAniSirGlobal pMac, uint8_t sessionId, tCsrHandoffRequest *pHandoffInfo); bool csr_roam_is_sta_mode(tpAniSirGlobal pMac, uint32_t sessionId); -#endif /* Post Channel Change Indication */ CDF_STATUS csr_roam_channel_change_req(tpAniSirGlobal pMac, diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 10dfaa05d915..64ca970571bb 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -126,7 +126,6 @@ typedef struct sCsr11rAssocNeighborInfo { } tCsr11rAssocNeighborInfo, *tpCsr11rAssocNeighborInfo; #endif /* WLAN_FEATURE_VOWIFI_11R */ -#ifdef FEATURE_WLAN_LFR typedef enum { eFirstEmptyScan = 1, eSecondEmptyScan, @@ -140,7 +139,6 @@ typedef enum { DEFAULT_SCAN = 0, SPLIT_SCAN_OCCUPIED_LIST = 1, } eNeighborRoamScanMode; -#endif /* Complete control information for neighbor roam algorithm */ typedef struct sCsrNeighborRoamControlInfo { @@ -164,7 +162,6 @@ typedef struct sCsrNeighborRoamControlInfo { bool isVOAdmitted; uint16_t MinQBssLoadRequired; #endif -#ifdef FEATURE_WLAN_LFR /* * Previous connected profile. * If the new profile does not match previous we re-initialize @@ -175,7 +172,6 @@ typedef struct sCsrNeighborRoamControlInfo { uint8_t uOsRequestedHandoff; /* handoff related info came with upper layer's req for reassoc */ tCsrHandoffRequest handoffReqInfo; -#endif uint8_t currentRoamBmissFirstBcnt; uint8_t currentRoamBmissFinalBcnt; uint8_t currentRoamBeaconRssiWeight; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index f99f70b83eee..ba46b3a0e49a 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -93,19 +93,14 @@ typedef struct _smeConfigParams { #if defined WLAN_FEATURE_VOWIFI struct rrm_config_param rrmConfig; #endif -#if defined FEATURE_WLAN_LFR uint8_t isFastRoamIniFeatureEnabled; uint8_t MAWCEnabled; -#endif #if defined FEATURE_WLAN_ESE uint8_t isEseIniFeatureEnabled; #endif -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) uint8_t isFastTransitionEnabled; uint8_t RoamRssiDiff; bool isWESModeEnabled; -#endif uint8_t isAmsduSupportInAMPDU; bool pnoOffload; uint8_t fEnableDebugLog; @@ -572,8 +567,6 @@ CDF_STATUS sme_set_tm_level(tHalHandle hHal, uint16_t newTMLevel, void sme_feature_caps_exchange(tHalHandle hHal); void sme_disable_feature_capablity(uint8_t feature_index); void sme_reset_power_values_for5_g(tHalHandle hHal); -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) CDF_STATUS sme_update_roam_prefer5_g_hz(tHalHandle hHal, bool nRoamPrefer5GHz); CDF_STATUS sme_set_roam_intra_band(tHalHandle hHal, const bool nRoamIntraBand); CDF_STATUS sme_update_roam_scan_n_probes(tHalHandle hHal, uint8_t sessionId, @@ -594,9 +587,7 @@ CDF_STATUS sme_update_wes_mode(tHalHandle hHal, bool isWESModeEnabled, uint8_t sessionId); CDF_STATUS sme_set_roam_scan_control(tHalHandle hHal, uint8_t sessionId, bool roamScanControl); -#endif /* (WLAN_FEATURE_VOWIFI_11R)||(FEATURE_WLAN_ESE)||(FEATURE_WLAN_LFR) */ -#ifdef FEATURE_WLAN_LFR CDF_STATUS sme_update_is_fast_roam_ini_feature_enabled(tHalHandle hHal, uint8_t sessionId, const bool @@ -608,7 +599,6 @@ CDF_STATUS sme_start_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason); CDF_STATUS sme_update_enable_fast_roam_in_concurrency(tHalHandle hHal, bool bFastRoamInConIniFeatureEnabled); -#endif /* FEATURE_WLAN_LFR */ #ifdef FEATURE_WLAN_ESE CDF_STATUS sme_update_is_ese_feature_enabled(tHalHandle hHal, uint8_t sessionId, const bool isEseIniFeatureEnabled); @@ -664,8 +654,6 @@ uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal); CDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal, uint8_t sessionId, const uint8_t nRoamBeaconRssiWeight); uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal); -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) uint8_t sme_get_roam_rssi_diff(tHalHandle hHal); CDF_STATUS sme_change_roam_scan_channel_list(tHalHandle hHal, uint8_t sessionId, uint8_t *pChannelList, @@ -683,7 +671,6 @@ bool sme_get_wes_mode(tHalHandle hHal); bool sme_get_roam_scan_control(tHalHandle hHal); bool sme_get_is_lfr_feature_enabled(tHalHandle hHal); bool sme_get_is_ft_feature_enabled(tHalHandle hHal); -#endif CDF_STATUS sme_update_roam_scan_offload_enabled(tHalHandle hHal, bool nRoamScanOffloadEnabled); uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue); diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index 4994c30a34bb..ed5f1a8ec59d 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -264,8 +264,6 @@ CDF_STATUS tdls_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, void *pMsgBuf); #endif /* FEATURE_WLAN_TDLS */ -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ - defined(FEATURE_WLAN_LFR) CDF_STATUS csr_flush_cfg_bg_scan_roam_channel_list(tpAniSirGlobal pMac, uint8_t sessionId); CDF_STATUS csr_create_bg_scan_roam_channel_list(tpAniSirGlobal pMac, @@ -273,7 +271,6 @@ CDF_STATUS csr_create_bg_scan_roam_channel_list(tpAniSirGlobal pMac, const uint8_t numChannels); CDF_STATUS csr_update_bg_scan_config_ini_channel_list(tpAniSirGlobal pMac, uint8_t sessionId, eCsrBand eBand); -#endif #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) CDF_STATUS csr_create_roam_scan_channel_list(tpAniSirGlobal pMac, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index e8fe27604ef3..527ad3ca8ec0 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -8011,7 +8011,6 @@ void sme_reset_power_values_for5_g(tHalHandle hHal) csr_apply_power2_current(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_update_roam_prefer5_g_hz \brief enable/disable Roam prefer 5G runtime option @@ -8380,9 +8379,7 @@ CDF_STATUS sme_set_roam_scan_control(tHalHandle hHal, uint8_t sessionId, } return status; } -#endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_ESE) || (FEATURE_WLAN_LFR) */ -#ifdef FEATURE_WLAN_LFR /*-------------------------------------------------------------------------- \brief sme_update_is_fast_roam_ini_feature_enabled() - enable/disable LFR support at runtime @@ -8532,7 +8529,6 @@ CDF_STATUS sme_update_enable_fast_roam_in_concurrency(tHalHandle hHal, return status; } -#endif /* FEATURE_WLAN_LFR */ #ifdef FEATURE_WLAN_ESE /*-------------------------------------------------------------------------- @@ -9424,7 +9420,6 @@ uint16_t sme_get_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId) } -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) /*-------------------------------------------------------------------------- \brief sme_get_roam_rssi_diff() - get Roam rssi diff @@ -9670,7 +9665,6 @@ bool sme_get_roam_scan_control(tHalHandle hHal) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); return pMac->roam.configParam.nRoamScanControl; } -#endif /*-------------------------------------------------------------------------- \brief sme_get_is_lfr_feature_enabled() - get LFR feature enabled or not @@ -9682,12 +9676,8 @@ bool sme_get_roam_scan_control(tHalHandle hHal) --------------------------------------------------------------------------*/ bool sme_get_is_lfr_feature_enabled(tHalHandle hHal) { -#ifdef FEATURE_WLAN_LFR tpAniSirGlobal pMac = PMAC_STRUCT(hHal); return pMac->roam.configParam.isFastRoamIniFeatureEnabled; -#else - return false; -#endif } /*-------------------------------------------------------------------------- diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a8f575486a73..041862f4b93e 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1336,7 +1336,6 @@ CDF_STATUS csr_flush_roam_scan_roam_channel_list(tpAniSirGlobal pMac, } #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 */ @@ -1390,7 +1389,6 @@ CDF_STATUS csr_create_bg_scan_roam_channel_list(tpAniSirGlobal pMac, return status; } -#endif #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) /* @@ -1853,7 +1851,6 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, 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; @@ -1865,16 +1862,13 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pMac->roam.configParam.nProbes = pParam->nProbes; pMac->roam.configParam.nRoamScanHomeAwayTime = pParam->nRoamScanHomeAwayTime; -#endif pMac->roam.configParam.isRoamOffloadScanEnabled = pParam->isRoamOffloadScanEnabled; pMac->roam.configParam.bFastRoamInConIniFeatureEnabled = pParam->bFastRoamInConIniFeatureEnabled; -#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 = @@ -2093,7 +2087,6 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) cdf_mem_copy(&cfg_params->csr11rConfig, &pParam->csr11rConfig, sizeof(tCsr11rConfigParams)); #endif -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) pParam->isFastTransitionEnabled = cfg_params->isFastTransitionEnabled; pParam->RoamRssiDiff = cfg_params->RoamRssiDiff; pParam->nRoamPrefer5GHz = cfg_params->nRoamPrefer5GHz; @@ -2101,14 +2094,11 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->isWESModeEnabled = cfg_params->isWESModeEnabled; pParam->nProbes = cfg_params->nProbes; pParam->nRoamScanHomeAwayTime = cfg_params->nRoamScanHomeAwayTime; -#endif pParam->isRoamOffloadScanEnabled = cfg_params->isRoamOffloadScanEnabled; pParam->bFastRoamInConIniFeatureEnabled = cfg_params->bFastRoamInConIniFeatureEnabled; -#ifdef FEATURE_WLAN_LFR pParam->isFastRoamIniFeatureEnabled = cfg_params->isFastRoamIniFeatureEnabled; -#endif #ifdef FEATURE_WLAN_ESE pParam->isEseIniFeatureEnabled = cfg_params->isEseIniFeatureEnabled; #endif @@ -5443,7 +5433,6 @@ bool csr_roam_is_ese_assoc(tpAniSirGlobal pMac, uint8_t sessionId) return csr_neighbor_roam_is_ese_assoc(pMac, sessionId); } #endif -#ifdef FEATURE_WLAN_LFR /* Returns whether "Legacy Fast Roaming" is currently enabled...or not */ bool csr_roam_is_fast_roam_enabled(tpAniSirGlobal pMac, uint32_t sessionId) { @@ -5488,7 +5477,6 @@ bool csr_roam_is_roam_offload_scan_enabled(tpAniSirGlobal pMac) { return pMac->roam.configParam.isRoamOffloadScanEnabled; } -#endif #if defined(FEATURE_WLAN_ESE) bool csr_roam_is_ese_ini_feature_enabled(tpAniSirGlobal pMac) @@ -8449,19 +8437,16 @@ csr_roaming_state_config_cnf_processor(tpAniSirGlobal mac_ctx, session_id); } else #endif -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_handoff_in_progress(mac_ctx, session_id) && csr_roam_is_fast_roam_enabled(mac_ctx, session_id)) { /* Now serialize the reassoc command. */ status = csr_roam_issue_reassociate_cmd(mac_ctx, session_id); - } else -#endif - { - /* - * else we are not connected and attempting to Join. Issue the - * Join request. - */ + } else { + /* + * else we are not connected and attempting to Join. + * Issue the Join request. + */ status = csr_roam_issue_join(mac_ctx, session_id, bss_desc, (tDot11fBeaconIEs *) @@ -8514,8 +8499,6 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, "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 == @@ -8544,7 +8527,6 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, 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. */ @@ -10045,12 +10027,10 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) csr_neighbor_roam_tranistion_preauth_done_to_disconnected( mac_ctx, sessionId); #endif -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionId) && (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) csr_neighbor_roam_tranistion_preauth_done_to_disconnected( mac_ctx, sessionId); -#endif session = CSR_GET_SESSION(mac_ctx, sessionId); if (!session) { sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); @@ -10131,12 +10111,10 @@ csr_roam_chk_lnk_deauth_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) csr_neighbor_roam_tranistion_preauth_done_to_disconnected( mac_ctx, sessionId); #endif -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_fast_roam_enabled(mac_ctx, sessionId) && (csr_neighbor_roam_state_preauth_done(mac_ctx, sessionId))) csr_neighbor_roam_tranistion_preauth_done_to_disconnected( mac_ctx, sessionId); -#endif session = CSR_GET_SESSION(mac_ctx, sessionId); if (!session) { sms_log(mac_ctx, LOGE, FL("session %d not found"), sessionId); @@ -11115,7 +11093,6 @@ void csr_roam_wait_for_key_time_out_handler(void *pv) curSubState[pInfo->sessionId])); if (CSR_IS_WAIT_FOR_KEY(pMac, pInfo->sessionId)) { -#ifdef FEATURE_WLAN_LFR if (csr_neighbor_roam_is_handoff_in_progress(pMac, pInfo->sessionId)) { /* * Enable heartbeat timer when hand-off is in progress @@ -11128,7 +11105,6 @@ void csr_roam_wait_for_key_time_out_handler(void *pv) cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->roam.configParam.HeartbeatThresh24); } -#endif sms_log(pMac, LOGE, " SME pre-auth state timeout. "); /* Change the substate so command queue is unblocked. */ @@ -11160,23 +11136,19 @@ CDF_STATUS csr_roam_start_wait_for_key_timer(tpAniSirGlobal pMac, uint32_t inter tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[pMac->roam.WaitForKeyTimerInfo. sessionId]; -#ifdef FEATURE_WLAN_LFR if (csr_neighbor_roam_is_handoff_in_progress(pMac, - pMac->roam.WaitForKeyTimerInfo. - sessionId)) { + pMac->roam.WaitForKeyTimerInfo. + sessionId)) { /* Disable heartbeat timer when hand-off is in progress */ sms_log(pMac, LOG2, FL("disabling HB timer in state=%s sub-state=%s"), - mac_trace_get_neighbour_roam_state(pNeighborRoamInfo-> - neighborRoamState), - mac_trace_getcsr_roam_sub_state(pMac->roam. - curSubState[pMac->roam. - WaitForKeyTimerInfo. - sessionId] - )); + mac_trace_get_neighbour_roam_state( + pNeighborRoamInfo->neighborRoamState), + mac_trace_getcsr_roam_sub_state( + pMac->roam.curSubState[pMac->roam. + WaitForKeyTimerInfo.sessionId])); cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0); } -#endif sms_log(pMac, LOG1, " csrScanStartWaitForKeyTimer"); status = cdf_mc_timer_start(&pMac->roam.hTimerWaitForKey, interval / CDF_MC_TIMER_TO_MS_UNIT); @@ -11198,7 +11170,6 @@ CDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac) curSubState[pMac->roam. WaitForKeyTimerInfo. sessionId])); -#ifdef FEATURE_WLAN_LFR if (csr_neighbor_roam_is_handoff_in_progress(pMac, pMac->roam.WaitForKeyTimerInfo. sessionId)) { @@ -11212,7 +11183,6 @@ CDF_STATUS csr_roam_stop_wait_for_key_timer(tpAniSirGlobal pMac) cfg_set_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->roam.configParam.HeartbeatThresh24); } -#endif return cdf_mc_timer_stop(&pMac->roam.hTimerWaitForKey); } @@ -13764,23 +13734,16 @@ CDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, } } #endif /* FEATURE_WLAN_ESE */ -#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) if (ese_config -#ifdef FEATURE_WLAN_LFR - || csr_roam_is_fast_roam_enabled(pMac, sessionId) -#endif - ) { + || csr_roam_is_fast_roam_enabled(pMac, sessionId)) { csr_join_req->isFastTransitionEnabled = true; } else { csr_join_req->isFastTransitionEnabled = false; } -#endif -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) csr_join_req->isFastRoamIniFeatureEnabled = true; else csr_join_req->isFastRoamIniFeatureEnabled = false; -#endif csr_join_req->txLdpcIniFeatureEnabled = (uint8_t) pMac->roam.configParam.txLdpcEnable; @@ -17696,9 +17659,7 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); CDF_STATUS status = CDF_STATUS_SUCCESS; -#if defined(FEATURE_WLAN_LFR) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD) tCsrRoamInfo roamInfo; -#endif eCsrAuthType conn_Auth_type; uint32_t sessionId = pFTPreAuthRsp->smeSessionId; tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); @@ -17772,7 +17733,6 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, } #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 (csr_roam_is_fast_roam_enabled(pMac, pFTPreAuthRsp->smeSessionId)) { @@ -17783,7 +17743,6 @@ void csr_roam_ft_pre_auth_rsp_processor(tHalHandle hHal, csr_roam_call_callback(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 */ diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 16ebbc7227ac..66f4609fc5f4 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1467,13 +1467,11 @@ static uint32_t csr_get_bss_cap_value(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIes) { uint32_t 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) && CDS_IS_CHANNEL_5GHZ(pBssDesc->channelId)) { ret += CSR_BSS_CAP_VALUE_5GHZ; } } -#endif /* * if strict select 5GHz is non-zero then ignore the capability checking */ @@ -1579,7 +1577,6 @@ static bool csr_is_better_bss(tpAniSirGlobal mac_ctx, return ret; } -#ifdef FEATURE_WLAN_LFR /* Add the channel to the occupiedChannels array */ static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac, tCsrScanResult *pResult, @@ -1611,17 +1608,14 @@ static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac, CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN; } } -#endif /* Put the BSS into the scan result list */ /* pIes can not be NULL */ static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult, tDot11fBeaconIEs *pIes, uint32_t sessionId) { -#ifdef FEATURE_WLAN_LFR tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; -#endif struct cdf_mac_addr bssid; uint8_t channel_id = pResult->Result.BssDescriptor.channelId; @@ -1635,7 +1629,6 @@ static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult, &pResult->Result.BssDescriptor, pIes); csr_ll_insert_tail(&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 @@ -1644,7 +1637,6 @@ static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult, csr_scan_add_to_occupied_channels(pMac, pResult, sessionId, &pMac->scan.occupiedChannels[sessionId], pIes); } -#endif } static void @@ -5260,7 +5252,6 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, ChannelList [index]))) ) { -#ifdef FEATURE_WLAN_LFR sms_log(mac_ctx, LOG2, FL(" reqType= %s (%d), numOfChannels=%d, ignoring DFS channel %d"), sme_request_type_to_string( @@ -5269,7 +5260,6 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, src_req->ChannelInfo.numOfChannels, src_req->ChannelInfo.ChannelList [index]); -#endif continue; } @@ -5663,9 +5653,7 @@ static void csr_sta_ap_conc_timer_handler(void *pv) if ((num_chn > numchan_combinedconc) && ((csr_is_sta_session_connected(mac_ctx) && -#ifdef FEATURE_WLAN_LFR (csr_is_concurrent_infra_connected(mac_ctx)) && -#endif (scan_cmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) || (csr_is_p2p_session_connected(mac_ctx)))) { cdf_mem_set(&scan_req, sizeof(tCsrScanRequest), 0); @@ -6953,7 +6941,6 @@ CDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac, } #endif /* FEATURE_WLAN_SCAN_PNO */ -#ifdef FEATURE_WLAN_LFR void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId) { tListElem *pEntry = NULL; @@ -7006,7 +6993,6 @@ void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId) } /* while */ csr_ll_unlock(&pMac->scan.scanResultList); } -#endif CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac, uint32_t sessionId, diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 8121ca0042d4..d3785659569d 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -88,9 +88,7 @@ #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_ROAMING_DFS_CHANNEL_DISABLED (0) @@ -1027,7 +1025,6 @@ CDF_STATUS csr_roam_enqueue_preauth(tpAniSirGlobal pMac, uint32_t sessionId, tpSirBssDescription pBssDescription, eCsrRoamReason reason, bool fImmediate); CDF_STATUS csr_dequeue_roam_command(tpAniSirGlobal pMac, eCsrRoamReason reason); -#ifdef FEATURE_WLAN_LFR void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId); bool csr_neighbor_roam_is_new_connected_profile(tpAniSirGlobal pMac, uint8_t sessionId); @@ -1035,7 +1032,6 @@ bool csr_neighbor_roam_connected_profile_match(tpAniSirGlobal pMac, uint8_t sessionId, tCsrScanResult *pResult, tDot11fBeaconIEs *pIes); -#endif CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac, uint32_t sessionId, diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index b015bb855a46..195c82a8db38 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -645,11 +645,9 @@ static void csr_neighbor_roam_reset_preauth_control_info(tpAniSirGlobal pMac, tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) pNeighborRoamInfo->is11rAssoc = false; /* Purge pre-auth fail list */ csr_neighbor_roam_purge_preauth_failed_list(pMac); -#endif pNeighborRoamInfo->FTRoamInfo.preauthRspPending = false; pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; @@ -1473,7 +1471,6 @@ csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx, "SKIP-currently associated AP"); continue; } -#ifdef FEATURE_WLAN_LFR /* * In case of reassoc requested by upper layer, look * for exact match of bssid & channel. csr cache might @@ -1490,7 +1487,6 @@ csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx, "SKIP-not a candidate AP for OS requested roam"); continue; } -#endif #ifdef WLAN_FEATURE_VOWIFI_11R if ((n_roam_info->is11rAssoc) && @@ -1537,7 +1533,6 @@ csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx, } #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, @@ -1550,7 +1545,6 @@ csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx, FL("BSSID present in pre-auth fail list.. Ignoring")); continue; } -#endif /* FEATURE_WLAN_LFR */ /* check the age of the AP */ age_ticks = (uint32_t) cdf_mc_timer_get_system_ticks() - @@ -2012,7 +2006,6 @@ CDF_STATUS csr_neighbor_roam_create_chan_list_from_neighbor_report(tpAniSirGloba } #endif /* WLAN_FEATURE_VOWIFI_11R */ -#ifdef FEATURE_WLAN_LFR /** * csr_neighbor_roam_is_ssid_and_security_match() - to match ssid/security * @pMac: Pointer to mac context @@ -2210,7 +2203,6 @@ csr_neighbor_roam_prepare_non_occupied_channel_list(tpAniSirGlobal pMac, *pOutputNumOfChannels = outputNumOfChannels; return CDF_STATUS_SUCCESS; } -#endif /* FEATURE_WLAN_LFR */ /** * csr_roam_reset_roam_params - API to reset the roaming parameters @@ -2255,10 +2247,8 @@ CDF_STATUS csr_neighbor_roam_indicate_disconnect(tpAniSirGlobal pMac, { tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId]; -#ifdef FEATURE_WLAN_LFR tCsrRoamConnectedProfile *pPrevProfile = &pNeighborRoamInfo->prevConnProfile; -#endif tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); tCsrRoamSession *roam_session = NULL; @@ -2271,14 +2261,12 @@ CDF_STATUS csr_neighbor_roam_indicate_disconnect(tpAniSirGlobal pMac, MAC_ADDRESS_STR), sessionId, pNeighborRoamInfo->neighborRoamState, MAC_ADDR_ARRAY(pSession->connectedProfile.bssid.bytes)); -#ifdef FEATURE_WLAN_LFR /* * Free the current previous profile and move * the current profile to prev profile. */ csr_roam_free_connect_profile(pMac, pPrevProfile); csr_roam_copy_connect_profile(pMac, sessionId, pPrevProfile); -#endif /* * clear the roaming parameters that are per connection. * For a new connection, they have to be programmed again. @@ -2402,11 +2390,8 @@ static void csr_neighbor_roam_info_ctx_init( &pMac->roam.neighborRoamInfo[session_id]; tCsrRoamSession *session = &pMac->roam.roamSession[session_id]; -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) int init_ft_flag = false; -#endif -#ifdef FEATURE_WLAN_LFR /* * Initialize the occupied list ONLY if we are * transitioning from INIT state to CONNECTED state. @@ -2414,7 +2399,6 @@ static void csr_neighbor_roam_info_ctx_init( if (eCSR_NEIGHBOR_ROAM_STATE_INIT == ngbr_roam_info->neighborRoamState) csr_init_occupied_channels_list(pMac, session_id); -#endif CSR_NEIGHBOR_ROAM_STATE_TRANSITION (pMac, eCSR_NEIGHBOR_ROAM_STATE_CONNECTED, session_id); @@ -2435,13 +2419,11 @@ static void csr_neighbor_roam_info_ctx_init( ngbr_roam_info->currentRoamBeaconRssiWeight = ngbr_roam_info->cfgParams.nRoamBeaconRssiWeight; -#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 */ csr_neighbor_roam_free_roamable_bss_list(pMac, &ngbr_roam_info->FTRoamInfo.preAuthDoneList); -#endif #ifdef WLAN_FEATURE_VOWIFI_11R /* Based on the auth scheme tell if we are 11r */ @@ -2469,12 +2451,9 @@ static void csr_neighbor_roam_info_ctx_init( FL("isESEAssoc is = %d ft = %d"), ngbr_roam_info->isESEAssoc, init_ft_flag); #endif -#ifdef FEATURE_WLAN_LFR /* If "Legacy Fast Roaming" is enabled */ if (csr_roam_is_fast_roam_enabled(pMac, session_id)) init_ft_flag = true; -#endif -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) if (init_ft_flag == false) return; /* Initialize all the data structures needed for the 11r FT Preauth */ @@ -2511,7 +2490,6 @@ static void csr_neighbor_roam_info_ctx_init( ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); } -#endif } /** @@ -2811,10 +2789,8 @@ CDF_STATUS csr_neighbor_roam_init(tpAniSirGlobal pMac, uint8_t sessionId) pNeighborRoamInfo->cfgParams.nRoamBmissFinalBcnt; pNeighborRoamInfo->currentRoamBeaconRssiWeight = pNeighborRoamInfo->cfgParams.nRoamBeaconRssiWeight; -#ifdef FEATURE_WLAN_LFR cdf_mem_set(&pNeighborRoamInfo->prevConnProfile, sizeof(tCsrRoamConnectedProfile), 0); -#endif status = csr_ll_open(pMac->hHdd, &pNeighborRoamInfo->roamableAPList); if (CDF_STATUS_SUCCESS != status) { @@ -2905,9 +2881,7 @@ void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId) /* Free the profile.. */ csr_release_profile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile); -#ifdef FEATURE_WLAN_LFR csr_roam_free_connect_profile(pMac, &pNeighborRoamInfo->prevConnProfile); -#endif #ifdef WLAN_FEATURE_VOWIFI_11R pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; @@ -3115,7 +3089,6 @@ bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac, preAuthDoneList)); } else #endif -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_fast_roam_enabled(pMac, session_id)) { /* Always the BSS info in the head is the handoff candidate */ bss_node = @@ -3126,9 +3099,7 @@ bool csr_neighbor_roam_get_handoff_ap_info(tpAniSirGlobal pMac, FL("Number of Handoff candidates = %d"), csr_ll_count( &ngbr_roam_info->FTRoamInfo.preAuthDoneList)); - } else -#endif - { + } else { bss_node = csr_neighbor_roam_next_roamable_ap(pMac, &ngbr_roam_info->roamableAPList, diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 88ecfcbcd21f..8b32fe94bd1d 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -3748,16 +3748,13 @@ uint8_t csr_retrieve_rsn_ie(tHalHandle hHal, uint32_t sessionId, do { if (!csr_is_profile_rsn(pProfile)) break; -#ifdef FEATURE_WLAN_LFR if (csr_roam_is_fast_roam_enabled(pMac, sessionId)) { /* If "Legacy Fast Roaming" is enabled ALWAYS rebuild the RSN IE from */ /* scratch. So it contains the current PMK-IDs */ cbRsnIe = csr_construct_rsn_ie(pMac, sessionId, pProfile, pSirBssDesc, pIes, pRsnIe); - } else -#endif - if (pProfile->nRSNReqIELength && pProfile->pRSNReqIE) { + } else if (pProfile->nRSNReqIELength && pProfile->pRSNReqIE) { /* If you have one started away, re-use it. */ if (SIR_MAC_WPA_IE_MAX_LENGTH >= pProfile->nRSNReqIELength) { @@ -5589,7 +5586,6 @@ void csr_disconnect_all_active_sessions(tpAniSirGlobal pMac) } } -#ifdef FEATURE_WLAN_LFR bool csr_is_channel_present_in_list(uint8_t *pChannelList, int numChannels, uint8_t channel) { @@ -5649,7 +5645,6 @@ CDF_STATUS csr_add_to_channel_list_front(uint8_t *pChannelList, return CDF_STATUS_SUCCESS; } -#endif #ifdef FEATURE_WLAN_DIAG_SUPPORT /** * csr_diag_event_report() - send PE diag event diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 8d127fe29302..1595a08cce62 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -987,13 +987,11 @@ CDF_STATUS sme_qos_csr_event_ind(tpAniSirGlobal pMac, sme_qos_process_preauth_success_ind(pMac, sessionId, pEvent_info); break; -#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) case SME_QOS_CSR_SET_KEY_SUCCESS_IND: status = sme_qos_process_set_key_success_ind(pMac, sessionId, pEvent_info); break; -#endif #endif default: /* Err msg */ @@ -2879,7 +2877,6 @@ sme_QosStatusType sme_qos_setup(tpAniSirGlobal pMac, 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 @@ -2894,7 +2891,6 @@ CDF_STATUS sme_qos_process_set_key_success_ind(tpAniSirGlobal pMac, (void)sme_qos_process_buffered_cmd(sessionId); return CDF_STATUS_SUCCESS; } -#endif #ifdef FEATURE_WLAN_ESE /** -- cgit v1.2.3 From f66f128fe12b05f50af4c985671119592f456e61 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Wed, 2 Dec 2015 16:45:09 -0800 Subject: qcacld-3.0: Add Enhanced Green AP interfaces and event handler qcacld-2.0 to qcacld-3.0 propagation The firmware reports the Enhanced Green AP (EGAP) service (EGAP_SERVICE) feature flag to indicate the support of EGAP feature. The EGAP is to offload the legacy Green AP feature to firmware in order to aggressively enable the Green AP other than wait for host control latency. Add the knob to hold the EGAP infomation when firmware support it, also populate the information up to hdd target config. And then add a SME interface to allow hdd layer to configure the EGAP configuration. Change-Id: I9be927369e7cf07731f8e9ba49d65224e05c340b CRs-fixed: 929063 --- core/hdd/src/wlan_hdd_green_ap.c | 18 ++++++ core/hdd/src/wlan_hdd_green_ap.h | 4 ++ core/hdd/src/wlan_hdd_main.c | 5 +- core/mac/inc/sir_api.h | 16 +++++ core/mac/src/include/sir_params.h | 2 + core/sme/inc/sme_api.h | 14 +++++ core/sme/src/common/sme_api.c | 42 ++++++++++++++ core/wma/inc/wma.h | 4 ++ core/wma/inc/wma_api.h | 16 +++++ core/wma/inc/wma_tgt_cfg.h | 4 ++ core/wma/inc/wma_types.h | 5 +- core/wma/src/wma_features.c | 119 ++++++++++++++++++++++++++++++++++++++ core/wma/src/wma_main.c | 8 +++ 13 files changed, 254 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_green_ap.c b/core/hdd/src/wlan_hdd_green_ap.c index 9cc9117dac6b..cfdaf06a062b 100644 --- a/core/hdd/src/wlan_hdd_green_ap.c +++ b/core/hdd/src/wlan_hdd_green_ap.c @@ -80,6 +80,7 @@ enum hdd_green_ap_event { * @ps_state: Current state * @ps_event: Event to trigger when timer expires * @ps_timer: Event timer + * @egap_support: Enhanced Green AP support flag */ struct hdd_green_ap_ctx { uint8_t ps_enable; @@ -91,6 +92,8 @@ struct hdd_green_ap_ctx { enum hdd_green_ap_event ps_event; cdf_mc_timer_t ps_timer; + + bool egap_support; }; /** @@ -449,3 +452,18 @@ void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx) { hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_DEL_STA_EVENT); } + +/** + * hdd_wlan_set_egap_support() - helper function to set egap support flag + * @hdd_ctx: pointer to hdd context + * @param: pointer to target configuration + * + * Return: None + */ +void hdd_wlan_set_egap_support(hdd_context_t *hdd_ctx, void *param) +{ + struct wma_tgt_cfg *cfg = (struct wma_tgt_cfg *) param; + + if (hdd_ctx && cfg) + hdd_ctx->green_ap_ctx->egap_support = cfg->egap_support; +} diff --git a/core/hdd/src/wlan_hdd_green_ap.h b/core/hdd/src/wlan_hdd_green_ap.h index 8844d71d870b..a688ba0222b4 100644 --- a/core/hdd/src/wlan_hdd_green_ap.h +++ b/core/hdd/src/wlan_hdd_green_ap.h @@ -43,6 +43,7 @@ void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx); void hdd_wlan_green_ap_stop_bss(struct hdd_context_s *hdd_ctx); void hdd_wlan_green_ap_add_sta(struct hdd_context_s *hdd_ctx); void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx); +void hdd_wlan_set_egap_support(struct hdd_context_s *hdd_ctx, void *param); #else static inline void hdd_wlan_green_ap_init(struct hdd_context_s *hdd_ctx) {} static inline void hdd_wlan_green_ap_deinit(struct hdd_context_s *hdd_ctx) {} @@ -50,5 +51,8 @@ static inline void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) {} static inline void hdd_wlan_green_ap_stop_bss(struct hdd_context_s *hdd_ctx) {} static inline void hdd_wlan_green_ap_add_sta(struct hdd_context_s *hdd_ctx) {} static inline void hdd_wlan_green_ap_del_sta(struct hdd_context_s *hdd_ctx) {} +static inline void hdd_wlan_set_egap_support(struct hdd_context_s *hdd_ctx, + void *param) {} + #endif /* FEATURE_GREEN_AP */ #endif /* __WLAN_HDD_GREEN_AP_H */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 5d2bc52c46a6..2b3fccef9b94 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1213,6 +1213,8 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_ctx->lpss_support = cfg->lpss_support; #endif + hdd_wlan_set_egap_support(hdd_ctx, cfg); + hdd_ctx->ap_arpns_support = cfg->ap_arpns_support; hdd_update_tgt_services(hdd_ctx, &cfg->services); @@ -4880,6 +4882,8 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) cds_set_connection_in_progress(hdd_ctx, false); + hdd_wlan_green_ap_init(hdd_ctx); + status = cds_open(&p_cds_context, 0); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed")); @@ -5296,7 +5300,6 @@ ftm_processing: hddLog(LOGE, FL("Failed to init ACS Skip timer")); #endif - hdd_wlan_green_ap_init(hdd_ctx); wlan_hdd_nan_init(hdd_ctx); status = cds_init_policy_mgr(hdd_ctx); if (!CDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 001844f6067e..d0c794834bf3 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5451,4 +5451,20 @@ struct sir_sme_ext_cng_chan_ind { uint8_t new_channel; }; +/** + * struct egap_params - the enhanced green ap params + * @vdev_id: vdev id + * @enable: enable or disable the enhance green ap in firmware + * @inactivity_time: inactivity timeout value + * @wait_time: wait timeout value + * @flags: feature flag in bitmask + * + */ +struct egap_conf_params { + uint32_t vdev_id; + bool enable; + uint32_t inactivity_time; + uint32_t wait_time; + uint32_t flags; +}; #endif /* __SIR_API_H */ diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 22aabae93a5b..64d4d624ecc1 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -605,6 +605,8 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_LRO_CONFIG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 335) +#define SIR_HAL_SET_EGAP_CONF_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 336) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index ba46b3a0e49a..9e8c40e1d845 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1064,4 +1064,18 @@ CDF_STATUS sme_gateway_param_update(tHalHandle hHal, struct gateway_param_update_req *request); #endif +#ifdef FEATURE_GREEN_AP +CDF_STATUS sme_send_egap_conf_params(uint32_t enable, + uint32_t inactivity_time, + uint32_t wait_time, + uint32_t flags); +#else +static inline CDF_STATUS sme_send_egap_conf_params(uint32_t enable, + uint32_t inactivity_time, + uint32_t wait_time, + uint32_t flags) +{ + return CDF_STATUS_E_NOSUPPORT; +} +#endif #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 527ad3ca8ec0..fa82c159f195 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14949,3 +14949,45 @@ void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset, } } #endif + +#ifdef FEATURE_GREEN_AP +/** + * sme_send_egap_conf_params() - set the enhanced green ap configuration params + * @enable: enable/disable the enhanced green ap feature + * @inactivity_time: inactivity timeout value + * @wait_time: wait timeout value + * @flag: feature flag in bitmasp + * + * Return: Return CDF_STATUS, otherwise appropriate failure code + */ +CDF_STATUS sme_send_egap_conf_params(uint32_t enable, uint32_t inactivity_time, + uint32_t wait_time, uint32_t flags) +{ + cds_msg_t message; + CDF_STATUS status; + struct egap_conf_params *egap_params; + + egap_params = cdf_mem_malloc(sizeof(*egap_params)); + if (NULL == egap_params) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: fail to alloc egap_params", __func__); + return CDF_STATUS_E_NOMEM; + } + + egap_params->enable = enable; + egap_params->inactivity_time = inactivity_time; + egap_params->wait_time = wait_time; + egap_params->flags = flags; + + message.type = WMA_SET_EGAP_CONF_PARAMS; + message.bodyptr = egap_params; + status = cds_mq_post_message(CDF_MODULE_ID_WMA, &message); + if (!CDF_IS_STATUS_SUCCESS(status)) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Not able to post msg to WMA!", __func__); + + cdf_mem_free(egap_params); + } + return status; +} +#endif diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 95a1ad5b40e6..3906d6d74312 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1083,6 +1083,7 @@ struct wmi_init_cmd { * @final_abi_vers: The final ABI version to be used for communicating * @target_fw_version: Target f/w build version * @lpss_support: LPSS feature is supported in target or not + * @egap_support: Enhanced Green AP support flag * @wmi_ready: wmi status flag * @wlan_init_status: wlan init status * @cdf_dev: cdf device @@ -1211,6 +1212,9 @@ typedef struct { uint8_t lpss_support; #endif uint8_t ap_arpns_support; +#ifdef FEATURE_GREEN_AP + bool egap_support; +#endif bool wmi_ready; uint32_t wlan_init_status; cdf_device_t cdf_dev; diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 0e9b5f5bc559..5990477e7ee9 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -219,4 +219,20 @@ struct wma_lro_config_cmd_t { int wma_lro_init(struct wma_lro_config_cmd_t *lro_config); #endif bool wma_is_scan_simultaneous_capable(void); + +#ifdef FEATURE_GREEN_AP +void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle); +void wma_register_egap_event_handle(WMA_HANDLE handle); +CDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle, + struct egap_conf_params *egap_params); +#else +static inline void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, + WMA_HANDLE handle) {} +static inline void wma_register_egap_event_handle(WMA_HANDLE handle) {} +static inline CDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle, + struct egap_conf_params *egap_params) +{ + return CDF_STATUS_E_NOSUPPORT; +} +#endif #endif diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index 5efa9545d822..73a739be0ef9 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -147,6 +147,7 @@ struct wma_dfs_radar_ind { * @vht_cap: struct wma_tgt_vht_cap * @max_intf_count: max interface count * @lpss_support: lpass support + * @egap_support: enhanced green ap support */ struct wma_tgt_cfg { uint32_t target_fw_version; @@ -164,5 +165,8 @@ struct wma_tgt_cfg { uint8_t lpss_support; #endif uint8_t ap_arpns_support; +#ifdef FEATURE_GREEN_AP + bool egap_support; +#endif }; #endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 6676a08a1aef..0f244989b1c7 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -444,10 +444,11 @@ #define WMA_DCC_GET_STATS_CMD SIR_HAL_DCC_GET_STATS_CMD #define WMA_DCC_CLEAR_STATS_CMD SIR_HAL_DCC_CLEAR_STATS_CMD #define WMA_DCC_UPDATE_NDL_CMD SIR_HAL_DCC_UPDATE_NDL_CMD -#define WMA_SET_IE_INFO SIR_HAL_SET_IE_INFO +#define WMA_SET_IE_INFO SIR_HAL_SET_IE_INFO -#define WMA_LRO_CONFIG_CMD SIR_HAL_LRO_CONFIG_CMD +#define WMA_LRO_CONFIG_CMD SIR_HAL_LRO_CONFIG_CMD #define WMA_GW_PARAM_UPDATE_REQ SIR_HAL_GATEWAY_PARAM_UPDATE_REQ +#define WMA_SET_EGAP_CONF_PARAMS SIR_HAL_SET_EGAP_CONF_PARAMS /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 739cd6eae973..1163ccab0b88 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -979,6 +979,125 @@ CDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed) #ifdef FEATURE_GREEN_AP +/** + * wma_egap_info_status_event() - egap info status event + * @handle: pointer to wma handler + * @event: pointer to event + * @len: len of the event + * + * Return: 0 for success, otherwise appropriate error code + */ +static int wma_egap_info_status_event(void *handle, u_int8_t *event, + uint32_t len) +{ + WMI_TX_PAUSE_EVENTID_param_tlvs *param_buf; + wmi_ap_ps_egap_info_event_fixed_param *egap_info_event; + wmi_ap_ps_egap_info_chainmask_list *chainmask_event; + u_int8_t *buf_ptr; + + param_buf = (WMI_TX_PAUSE_EVENTID_param_tlvs *)event; + if (!param_buf) { + WMA_LOGE("Invalid EGAP Info status event buffer"); + return -EINVAL; + } + + egap_info_event = (wmi_ap_ps_egap_info_event_fixed_param *) + param_buf->fixed_param; + buf_ptr = (uint8_t *)egap_info_event; + buf_ptr += sizeof(wmi_ap_ps_egap_info_event_fixed_param); + chainmask_event = (wmi_ap_ps_egap_info_chainmask_list *)buf_ptr; + + WMA_LOGI("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d", + chainmask_event->mac_id, + egap_info_event->status, + chainmask_event->tx_chainmask, + chainmask_event->rx_chainmask); + return 0; +} + +/** + * wma_send_egap_conf_params() - send wmi cmd of egap configuration params + * @wma_handle: wma handler + * @egap_params: pointer to egap_params + * + * Return: 0 for success, otherwise appropriate error code + */ +CDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle, + struct egap_conf_params *egap_params) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + wmi_ap_ps_egap_param_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 ap_ps_egap cmd"); + return CDF_STATUS_E_NOMEM; + } + cmd = (wmi_ap_ps_egap_param_cmd_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ap_ps_egap_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ap_ps_egap_param_cmd_fixed_param)); + + cmd->enable = egap_params->enable; + cmd->inactivity_time = egap_params->inactivity_time; + cmd->wait_time = egap_params->wait_time; + cmd->flags = egap_params->flags; + err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + sizeof(*cmd), WMI_AP_PS_EGAP_PARAM_CMDID); + if (err) { + WMA_LOGE("Failed to send ap_ps_egap cmd"); + wmi_buf_free(buf); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; +} + +/** + * wma_setup_egap_support() - setup the EGAP support flag + * @tgt_cfg: pointer to hdd target configuration + * @egap_support: EGAP support flag + * + * Return: None + */ +void wma_setup_egap_support(struct wma_tgt_cfg *tgt_cfg, WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + + if (tgt_cfg && wma_handle) + tgt_cfg->egap_support = wma_handle->egap_support; +} + +/** + * wma_register_egap_event_handle() - register the EGAP event handle + * @wma_handle: wma handler + * + * Return: None + */ +void wma_register_egap_event_handle(WMA_HANDLE handle) +{ + tp_wma_handle wma_handle = (tp_wma_handle) handle; + int status; + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_EGAP)) { + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_AP_PS_EGAP_INFO_EVENTID, + wma_egap_info_status_event); + if (status) { + WMA_LOGE("Failed to register Enhance Green AP event"); + wma_handle->egap_support = false; + } else { + WMA_LOGI("Set the Enhance Green AP event handler"); + wma_handle->egap_support = true; + } + } else + wma_handle->egap_support = false; +} + /** * wmi_unified_pdev_green_ap_ps_enable_cmd() - enable green ap powersave command * @wmi_handle: wmi handle diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index b185e7e25070..59253b83a016 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3459,6 +3459,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) tgt_cfg.lpss_support = wma_handle->lpss_support; #endif /* WLAN_FEATURE_LPSS */ tgt_cfg.ap_arpns_support = wma_handle->ap_arpns_support; + wma_setup_egap_support(&tgt_cfg, wma_handle); wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg); } @@ -3894,6 +3895,9 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) return; } + /* register the Enhanced Green AP event handler */ + wma_register_egap_event_handle(wma_handle); + /* Initialize the log supported event handler */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_DIAG_EVENT_LOG_SUPPORTED_EVENTID, @@ -5283,6 +5287,10 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) case WMA_GW_PARAM_UPDATE_REQ: wma_set_gateway_params(wma_handle, (struct gateway_param_update_req *)msg->bodyptr); + break; + case WMA_SET_EGAP_CONF_PARAMS: + wma_send_egap_conf_params(wma_handle, + (struct egap_conf_params *)msg->bodyptr); cdf_mem_free(msg->bodyptr); break; default: -- cgit v1.2.3 From 09c45a93c9c70fd80ab6289aef72920051697af6 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Mon, 9 Nov 2015 16:03:53 -0800 Subject: qcacld-3.0: hdd: Add EGAP interface and ini configuration qcacld-2.0 to qcacld-3.0 propagation This change introduces 4 ini parameters to configure to firmware - gEenableEGAP: forcely overwrite firmware feature capb - gEGAPInactTime: inactivity timeout value - gEGAPWaitTime: wait timeout value before enter EGAP mode - gEGAPFeatures: the feature flag firmware would support WMI_AP_PS_EGAP_F_ENABLE_PHYERR_DETECTION 0x1 WMI_AP_PS_EGAP_F_ENABLE_PWRSAVE_BY_PS_STATE 0x2 WMI_AP_PS_EGAP_F_ENABLE_PWRSAVE_BY_INACTIVITY 0x4 Integrate the hdd_wlan_kick_green_ap to execute the Green AP and EGAP features, depending on the ini and also the tgt_cfg capability flag, Change-Id: Ic5db3990aa0a028ed700f6e2f60a11e75c0f1ed1 CRs-fixed: 929063 --- core/hdd/inc/wlan_hdd_cfg.h | 27 +++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 36 ++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_green_ap.c | 26 ++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index a34ef7ae9fe3..d37bdcdeb80d 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1259,6 +1259,29 @@ typedef enum { #define CFG_ENABLE_GREEN_AP_FEATURE_MIN (0) #define CFG_ENABLE_GREEN_AP_FEATURE_MAX (1) #define CFG_ENABLE_GREEN_AP_FEATURE_DEFAULT (1) + +/* Enhanced Green AP (EGAP) flags/params */ +#define CFG_ENABLE_EGAP_ENABLE_FEATURE "gEnableEGAP" +#define CFG_ENABLE_EGAP_ENABLE_FEATURE_MIN (0) +#define CFG_ENABLE_EGAP_ENABLE_FEATURE_MAX (1) +#define CFG_ENABLE_EGAP_ENABLE_FEATURE_DEFAULT (0) + +#define CFG_ENABLE_EGAP_INACT_TIME_FEATURE "gEGAPInactTime" +#define CFG_ENABLE_EGAP_INACT_TIME_FEATURE_MIN (0) +#define CFG_ENABLE_EGAP_INACT_TIME_FEATURE_MAX (5000) +#define CFG_ENABLE_EGAP_INACT_TIME_FEATURE_DEFAULT (1000) + +#define CFG_ENABLE_EGAP_WAIT_TIME_FEATURE "gEGAPWaitTime" +#define CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_MIN (0) +#define CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_MAX (5000) +#define CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_DEFAULT (100) + +#define CFG_ENABLE_EGAP_FLAGS_FEATURE "gEGAPFeatures" +#define CFG_ENABLE_EGAP_FLAGS_FEATURE_MIN (0) +#define CFG_ENABLE_EGAP_FLAGS_FEATURE_MAX (15) +#define CFG_ENABLE_EGAP_FLAGS_FEATURE_DEFAULT (7) +/* end Enhanced Green AP flags/params */ + #endif #ifdef FEATURE_WLAN_FORCE_SAP_SCC @@ -3302,6 +3325,10 @@ struct hdd_config { #ifdef FEATURE_GREEN_AP bool enableGreenAP; + bool enable_egap; + uint32_t egap_feature_flag; + uint32_t egap_inact_time; + uint32_t egap_wait_time; #endif uint8_t force_sap_acs; uint8_t force_sap_acs_st_ch; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 42c8002becfa..b5451f3fa17c 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3109,6 +3109,30 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ENABLE_GREEN_AP_FEATURE_DEFAULT, CFG_ENABLE_GREEN_AP_FEATURE_MIN, CFG_ENABLE_GREEN_AP_FEATURE_MAX), + REG_VARIABLE(CFG_ENABLE_EGAP_ENABLE_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, enable_egap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_EGAP_ENABLE_FEATURE_DEFAULT, + CFG_ENABLE_EGAP_ENABLE_FEATURE_MIN, + CFG_ENABLE_EGAP_ENABLE_FEATURE_MAX), + REG_VARIABLE(CFG_ENABLE_EGAP_INACT_TIME_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, egap_inact_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_EGAP_INACT_TIME_FEATURE_DEFAULT, + CFG_ENABLE_EGAP_INACT_TIME_FEATURE_MIN, + CFG_ENABLE_EGAP_INACT_TIME_FEATURE_MAX), + REG_VARIABLE(CFG_ENABLE_EGAP_WAIT_TIME_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, egap_wait_time, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_DEFAULT, + CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_MIN, + CFG_ENABLE_EGAP_WAIT_TIME_FEATURE_MAX), + REG_VARIABLE(CFG_ENABLE_EGAP_FLAGS_FEATURE, WLAN_PARAM_Integer, + struct hdd_config, egap_feature_flag, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_EGAP_FLAGS_FEATURE_DEFAULT, + CFG_ENABLE_EGAP_FLAGS_FEATURE_MIN, + CFG_ENABLE_EGAP_FLAGS_FEATURE_MAX), #endif REG_VARIABLE(CFG_IGNORE_CAC_NAME, WLAN_PARAM_Integer, @@ -5032,6 +5056,18 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableGreenAp] Value = [%u] ", pHddCtx->config->enableGreenAP); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEenableEGAP] Value = [%u] ", + pHddCtx->config->enable_egap); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEGAPInactTime] Value = [%u] ", + pHddCtx->config->egap_inact_time); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEGAPWaitTime] Value = [%u] ", + pHddCtx->config->egap_wait_time); + CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, + "Name = [gEGAPFeatures] Value = [%u] ", + pHddCtx->config->egap_feature_flag); #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, diff --git a/core/hdd/src/wlan_hdd_green_ap.c b/core/hdd/src/wlan_hdd_green_ap.c index cfdaf06a062b..ac61e1898893 100644 --- a/core/hdd/src/wlan_hdd_green_ap.c +++ b/core/hdd/src/wlan_hdd_green_ap.c @@ -409,6 +409,30 @@ void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) { struct hdd_config *cfg = hdd_ctx->config; + /* check if the firmware and ini are both enabled the egap, + * and also the feature_flag enable, then we enable the egap + */ + if (hdd_ctx->green_ap_ctx->egap_support && cfg->enable_egap && + cfg->egap_feature_flag) { + hddLog(LOG1, + FL("Set EGAP - enabled: %d, flag: %x, inact_time: %d, wait_time: %d"), + cfg->enable_egap, + cfg->egap_feature_flag, + cfg->egap_inact_time, + cfg->egap_wait_time); + if (!sme_send_egap_conf_params(cfg->enable_egap, + cfg->egap_inact_time, + cfg->egap_wait_time, + cfg->egap_feature_flag)) { + /* EGAP is enabled, disable host GAP */ + hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT); + goto exit; + } + /* fall through, if send_egap_conf_params() failed, + * then check host GAP and enable it accordingly + */ + } + if (!(CDF_STA_MASK & hdd_ctx->concurrency_mode) && cfg->enable2x2 && cfg->enableGreenAP) { hdd_wlan_green_ap_mc(hdd_ctx, GREEN_AP_PS_START_EVENT); @@ -418,6 +442,8 @@ void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) CDF_STA_MASK & hdd_ctx->concurrency_mode, cfg->enable2x2, cfg->enableGreenAP); } +exit: + return; } /** -- cgit v1.2.3 From f40f47c932a5e70dee61ce675fba2588c097c974 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Thu, 3 Dec 2015 17:56:41 -0800 Subject: qcacld-3.0: CL 1424628 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Update for green AP feature related WMI TLVs and debug log ids Change-Id: I1e7463ee201572ec6bd4cdcb681524fa1c68c82a CRs-fixed: 865207 --- target/inc/dbglog_id.h | 13 +++++++++++++ target/inc/wmi_tlv_defs.h | 1 + target/inc/wmi_unified.h | 3 +++ target/inc/wmi_version.h | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/target/inc/dbglog_id.h b/target/inc/dbglog_id.h index 79b56fec795a..171701a02348 100644 --- a/target/inc/dbglog_id.h +++ b/target/inc/dbglog_id.h @@ -624,6 +624,19 @@ extern "C" { #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 diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 04fb12fe0a17..6acbf5e9e2ee 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -603,6 +603,7 @@ typedef enum { 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_ID; /* diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index d7e689ddbf44..926f107576c6 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -5077,6 +5077,9 @@ typedef enum { * 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; diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 87ad33b1f415..25a8f5b0488f 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 182 +#define __WMI_REVISION_ 183 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From b42d7d297d931ec1b7b40e1f1b65d723190dac3c Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Fri, 4 Dec 2015 13:47:58 -0800 Subject: qcacld-3.0: CL 1426046 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation WMI event update for SMPS complete Change-Id: Ifb8583d96bc634c5570b538aac2cc93de9f9efcd CRs-fixed: 865207 --- target/inc/wmi_tlv_defs.h | 8 +++++++- target/inc/wmi_unified.h | 19 +++++++++++++++++++ target/inc/wmi_version.h | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 6acbf5e9e2ee..a5ceb36a3edf 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -604,6 +604,7 @@ typedef enum { 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; /* @@ -961,7 +962,8 @@ typedef enum { 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_PDEV_UTF_SCPC_EVENTID) \ + OP(WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID) /* TLV definitions of WMI commands */ @@ -3022,6 +3024,10 @@ WMITLV_CREATE_PARAM_STRUC(WMI_PACKET_FILTER_ENABLE_CMDID); 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 } diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 926f107576c6..3d2fb50d69b4 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -1144,6 +1144,11 @@ typedef enum { /* 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 = @@ -12332,6 +12337,20 @@ typedef struct { A_UINT32 status; } wmi_transfer_data_to_flash_complete_event_fixed_param; +/* + * This structure is used to report SMPS force mode set complete to host. + */ +typedef struct { + /* TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_complete_event_fixed_param + */ + A_UINT32 tlv_header; + /* 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; + /* * This structure is used to report SCPC calibrated data to host. */ diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 25a8f5b0488f..47cdc8d9eb2c 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 183 +#define __WMI_REVISION_ 184 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 3ef9f3fce6fa3f717e1a337880946f11d47d547e Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 9 Dec 2015 12:23:08 -0800 Subject: qcacld-3.0: CL 1427469 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation WMI event update to add dd_profile field to RC_TX_RATE_SCHEDULE and WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT Change-Id: Ic9ba6dd82b2c6ea3d8894665270838a93a702f38 CRs-fixed: 865207 --- target/inc/wlan_defs.h | 1 + target/inc/wmi_unified.h | 3 ++- target/inc/wmi_version.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/target/inc/wlan_defs.h b/target/inc/wlan_defs.h index 3588a3008ba2..e9948d08dadb 100644 --- a/target/inc/wlan_defs.h +++ b/target/inc/wlan_defs.h @@ -333,6 +333,7 @@ typedef struct { A_RATE probe_rix; A_UINT8 num_valid_rates; A_UINT8 rtscts_tpc; + A_UINT8 dd_profile; } RC_TX_RATE_SCHEDULE; #else diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 3d2fb50d69b4..61d6939ed40a 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -2288,7 +2288,8 @@ enum wmi_scan_event_type { 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_RESTARTED = 0x80, /* scan restarted */ + WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT = 0x100, WMI_SCAN_EVENT_MAX = 0x8000 }; diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 47cdc8d9eb2c..1a2386c3b750 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 184 +#define __WMI_REVISION_ 185 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 7167413bb0008e3627e8d6f3d92b84f525d37b1a Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 9 Dec 2015 12:35:24 -0800 Subject: qcacld-3.0: CL 1427715 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation WMI changes to add reassoc_req_frame in wmi_roam_synch_event add WMI_INIT flag for special WOW platform that no need pcie reset Change-Id: Ica7653166239e5590d1daa62ec46971d8c905915 CRs-fixed: 865207 --- target/inc/wmi_tlv_defs.h | 3 ++- target/inc/wmi_unified.h | 24 ++++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index a5ceb36a3edf..3172cc0eb96c 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -2567,7 +2567,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_EVENTID); 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_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, status, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, reassoc_req_frame, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_ROAM_SYNCH_EVENTID); /* WOW Wakeup Host Event */ diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 61d6939ed40a..b3ef0396240d 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -1985,8 +1985,29 @@ typedef struct { * @brief num_ocb_schedules - The supported number of OCB schedule segments */ A_UINT32 num_ocb_schedules; + /** + * @brief specific configuration from host, such as per platform configuration + */ + #define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_S 0 + #define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_M 0x1 + A_UINT32 flag1; } wmi_resource_config; +#define WMI_RSRC_CFG_FLAG_SET(word32, flag, value) \ + do { \ + (word32) &= ~WMI_RSRC_CFG_FLAG_ ## flag ## _M; \ + (word32) |= ((value) << WMI_RSRC_CFG_FLAG_ ## flag ## _S) & \ + WMI_RSRC_CFG_FLAG_ ## flag ## _M; \ + } while (0) +#define WMI_RSRC_CFG_FLAG_GET(word32, flag) \ + (((word32) & WMI_RSRC_CFG_FLAG_ ## flag ## _M) >> \ + WMI_RSRC_CFG_FLAG_ ## flag ## _S) + +#define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), WOW_IGN_PCIE_RST, (value)) +#define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), WOW_IGN_PCIE_RST) + typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param */ @@ -9689,6 +9710,8 @@ typedef struct { A_UINT32 bcn_probe_rsp_len; /** the length of reassoc rsp */ A_UINT32 reassoc_rsp_len; + /** the length of reassoc req */ + A_UINT32 reassoc_req_len; /** * TLV (tag length value ) parameters follows roam_synch_event * The TLV's are: @@ -9698,6 +9721,7 @@ typedef struct { * wmi_key_material key; * A_UINT32 status; subnet changed status not being used * currently. will pass the information using roam_status. + * A_UINT8 reassoc_req_frame[]; length identified by reassoc_req_len **/ } wmi_roam_synch_event_fixed_param; diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 1a2386c3b750..68f1b40a3b64 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 185 +#define __WMI_REVISION_ 187 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 74ab29827c4cb9c55762fb67cdd18fa23788bb9b Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Fri, 14 Aug 2015 16:54:08 -0700 Subject: qcacld-3.0: Post message to SME upon DelBSS/DelSta failure qcacld-2.0 to qcacld-3.0 propagation. This fix ensures that a response message is sent back to SME if a DelBSS/DelSta failure is returned by firmware, without which SME command can get stuck. Change-Id: I42425809ef93d447af0b34aee05e601e30a18ccc CRs-Fixed: 810491 --- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 71 +++++++++++----------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index a4afe4c5f3d6..4f5c5d6148f2 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -2181,46 +2181,43 @@ void lim_process_sta_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, lim_log(pMac, LOGE, FL("Encountered NULL Pointer")); goto end; } - if (CDF_STATUS_SUCCESS == pDelStaParams->status) { - pStaDs = - dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, - &psessionEntry->dph.dphHashTable); - if (pStaDs == NULL) { - /* TODO: any response to be sent out here ? */ - lim_log(pMac, LOGE, FL("DPH Entry for STA %X missing."), + lim_log(pMac, LOG1, FL("Del STA RSP received. Status:%d AssocID:%d"), + pDelStaParams->status, pDelStaParams->assocId); + + if (CDF_STATUS_SUCCESS != pDelStaParams->status) + lim_log(pMac, LOGE, FL( + "Del STA failed! Status:%d, proceeding with Del BSS"), + pDelStaParams->status); + + pStaDs = dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) { + lim_log(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) { - /* TODO: any response to be sent out here ? */ - lim_log(pMac, LOGE, - FL - ("Received unexpected WMA_DELETE_STA_RSP in state %s"), - lim_mlm_state_str(psessionEntry->limMlmState)); - statusCode = eSIR_SME_REFUSED; - goto end; - } - PELOG1(lim_log - (pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId); - lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1); - ) - lim_log(pMac, LOGW, - FL("DEL_STA_RSP received for assocID: %X"), - pDelStaParams->assocId); - /* we must complete all cleanup related to delSta before calling limDelBSS. */ - if (0 != limMsgQ->bodyptr) { - cdf_mem_free(pDelStaParams); - limMsgQ->bodyptr = NULL; - } - statusCode = - (tSirResultCodes) lim_del_bss(pMac, pStaDs, 0, psessionEntry); - return; - } else { - lim_log(pMac, LOGE, FL("DEL_STA failed for sta Id %d"), - pDelStaParams->staIdx); statusCode = eSIR_SME_REFUSED; + goto end; + } + if (eLIM_MLM_WT_DEL_STA_RSP_STATE != psessionEntry->limMlmState) { + lim_log(pMac, LOGE, FL( + "Received unexpected WDA_DELETE_STA_RSP in state %s"), + lim_mlm_state_str(psessionEntry->limMlmState)); + statusCode = eSIR_SME_REFUSED; + goto end; + } + lim_log(pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId); + lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1); + /* + * we must complete all cleanup related to delSta before + * calling limDelBSS. + */ + if (0 != limMsgQ->bodyptr) { + cdf_mem_free(pDelStaParams); + limMsgQ->bodyptr = NULL; } + /* Proceed to do DelBSS even if DelSta resulted in failure */ + statusCode = (tSirResultCodes)lim_del_bss(pMac, pStaDs, 0, + psessionEntry); + return; end: if (0 != limMsgQ->bodyptr) { cdf_mem_free(pDelStaParams); -- cgit v1.2.3 From 5cc292bf4cd7220f25c53a9fd5e8a9dd039c6674 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 22 Dec 2015 11:33:14 -0800 Subject: qcacld-3.0: Make ce_init_ce_desc_event_log not static Fix a compilation error for perfbuild. Change-Id: I26950eddb8c0f0835cf1faf145f7997a601f2339 CRs-Fixed: 955059 --- core/hif/src/ce/ce_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 5f474ccaeebf..8e31cd507bab 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -170,7 +170,7 @@ void hif_record_ce_desc_event( { } -static inline void ce_init_ce_desc_event_log(int ce_id, int size) +inline void ce_init_ce_desc_event_log(int ce_id, int size) { } #endif -- cgit v1.2.3 From a575ec2fa4828136b22e68f6257c86a4ae53ba04 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 14 Dec 2015 16:35:15 -0800 Subject: qcacld-3.0: Record polled completion processing Since the wmi tx copy engine's completions can be processed in both its tasklet context and through ce_per_engine_servicereap on a polled basis, we wish to be able to distinguish the when each is used. Change-Id: I5892eeeab4e1c7e4c35b958d98db7ad0293ec24f CRs-Fixed: 951569 --- core/hif/src/ce/ce_internal.h | 4 ++++ core/hif/src/ce/ce_service.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/hif/src/ce/ce_internal.h b/core/hif/src/ce/ce_internal.h index d95f27cd3e4f..b4272c56a41a 100644 --- a/core/hif/src/ce/ce_internal.h +++ b/core/hif/src/ce/ce_internal.h @@ -298,6 +298,8 @@ union ce_desc { * @HIF_CE_TASKLET_ENTRY: records the start of the ce_tasklet * @HIF_CE_TASKLET_RESCHEDULE: records the rescheduling of the wlan_tasklet * @HIF_CE_TASKLET_EXIT: records the exit of the wlan tasklet without reschedule + * @HIF_CE_REAP_ENTRY: records when we process completion outside of a bh + * @HIF_CE_REAP_EXIT: records when we process completion outside of a bh */ enum hif_ce_event_type { HIF_RX_DESC_POST, @@ -309,6 +311,8 @@ enum hif_ce_event_type { HIF_CE_TASKLET_ENTRY, HIF_CE_TASKLET_RESCHEDULE, HIF_CE_TASKLET_EXIT, + HIF_CE_REAP_ENTRY, + HIF_CE_REAP_EXIT, }; void ce_init_ce_desc_event_log(int ce_id, int size); diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 8e31cd507bab..0d97b4949943 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -1181,7 +1181,7 @@ ce_completed_send_next(struct CE_handle *copyeng, * within it . */ -void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) +void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int ce_id) { void *CE_context; void *transfer_context; @@ -1190,9 +1190,11 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) unsigned int id; unsigned int sw_idx, hw_idx; uint32_t toeplitz_hash_result; - struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; + struct CE_state *CE_state = scn->ce_id_to_state[ce_id]; A_TARGET_ACCESS_BEGIN(scn); + hif_record_ce_desc_event(ce_id, HIF_CE_REAP_ENTRY, + NULL, NULL, 0); /* Since this function is called from both user context and * tasklet context the spinlock has to lock the bottom halves. @@ -1220,7 +1222,7 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) &nbytes, &id, &sw_idx, &hw_idx, &toeplitz_hash_result) == CDF_STATUS_SUCCESS) { - if (CE_id != CE_HTT_H2T_MSG) { + if (ce_id != CE_HTT_H2T_MSG) { cdf_spin_unlock_bh( &CE_state->ce_index_lock); CE_state->send_cb( @@ -1247,6 +1249,9 @@ void ce_per_engine_servicereap(struct ol_softc *scn, unsigned int CE_id) } cdf_spin_unlock_bh(&CE_state->ce_index_lock); + + hif_record_ce_desc_event(ce_id, HIF_CE_REAP_EXIT, + NULL, NULL, 0); A_TARGET_ACCESS_END(scn); } -- cgit v1.2.3 From 6666df7fab58aab559c0c653530c329b8f248c16 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 30 Nov 2015 16:48:35 -0800 Subject: qcacld-3.0: completion_freeq_lock needs initialization Initialization of completion_freeq_lock was removed as part of removing the completion thread. The lock still protects the variable num_sends_allowed for copy engines used for sending. Change-Id: Ia52d2c1b839d2ccfedbd175f1b8f60f953d08203 CRs-Fixed: 951563 --- core/hif/src/ce/ce_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 1d8003ccbf52..9ade278246fd 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -844,7 +844,11 @@ int hif_completion_thread_startup(struct HIF_CE_state *hif_state) hif_pci_ce_recv_data, pipe_info, attr.flags & CE_ATTR_DISABLE_INTR); } + + if (attr.src_nentries) + cdf_spinlock_init(&pipe_info->completion_freeq_lock); } + A_TARGET_ACCESS_UNLIKELY(scn); return 0; } -- cgit v1.2.3 From 6f8f7e6397b5ffcfa9b32ed88479af36072b9f3b Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 8 Dec 2015 13:48:02 -0800 Subject: qcacld-3.0: Recheck firmware indicator register after enabling interrupts qcacld-2.0 to qcacld-3.0 propagation We suspect that the firmware indicator interrupt is being dropped when the firmware indicator interrupt is disabled. Check the firmware indicator after reenabling the firmware indicator interrupt. Change-Id: I600bd9dfae99ab96dfaf7e3448cef9128f8b7357 CRs-Fixed: 925315 --- core/hif/src/pcie/hif_io32_pci.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hif/src/pcie/hif_io32_pci.h b/core/hif/src/pcie/hif_io32_pci.h index 3ffa30da0325..597508f6b0e8 100644 --- a/core/hif/src/pcie/hif_io32_pci.h +++ b/core/hif/src/pcie/hif_io32_pci.h @@ -243,6 +243,9 @@ extern void hif_target_write_checked(struct ol_softc *scn, uint32_t offset, #endif #endif /* CONFIG_ATH_PCIE_MAX_PERF */ + +irqreturn_t hif_fw_interrupt_handler(int irq, void *arg); + /** * ce_irq_enable() - ce_irq_enable * @scn: ol_softc @@ -276,6 +279,9 @@ static inline void ce_irq_enable(struct ol_softc *scn, int ce_id) if (scn->hif_init_done == true) A_TARGET_ACCESS_END(scn); cdf_spin_unlock_irqrestore(&scn->irq_lock); + + /* check for missed firmware crash */ + hif_fw_interrupt_handler(0, scn); } /** * ce_irq_disable() - ce_irq_disable -- cgit v1.2.3 From b13bf0365cd94de2a3769b2ed553364b97526940 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Mon, 14 Dec 2015 17:59:16 -0800 Subject: qcacld-3.0: Move 5GHz channels ahead of 2 GHz for Early Stop In case prefer 5 GHz preference is set, move the 5GHz channels ahead of 2GHz channels in channel list as used in Early Stop Roaming Scan feature. This ensures that while roaming, when these features are enabled DUT will scan 5 GHz channels first and roam if a candidate AP is found. Change-Id: I96d997560a3eca5fd378aa3ed78c5766d097cafd CRs-Fixed: 951959 --- core/sme/inc/csr_internal.h | 4 ++ core/sme/src/csr/csr_api_roam.c | 87 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 7ccddc2541d3..d18fc3d8d994 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -68,6 +68,10 @@ #define CSR_IS_SESSION_ANY(sessionId) (sessionId == SME_SESSION_ID_ANY) #define CSR_MAX_NUM_COUNTRY_CODE 100 +#define CSR_IS_DFS_CH_ROAM_ALLOWED(mac_ctx) \ + ( \ + (((mac_ctx)->roam.configParam.allowDFSChannelRoam) ? true : false) \ + ) #define CSR_IS_SELECT_5GHZ_MARGIN(pMac) \ ( \ (((pMac)->roam.configParam.nSelect5GHzMargin) ? true : false) \ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 041862f4b93e..0c96ec5aeef4 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -476,8 +476,84 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * CDF_ASSERT(0); return 0; } + +/** + * csr_roam_arrange_ch_list() - Updates the channel list modified with greedy + * order for 5 Ghz preference and DFS channels. + * @mac_ctx: pointer to mac context. + * @chan_list: channel list updated with greedy channel order. + * @num_channel: Number of channels in list + * + * To allow Early Stop Roaming Scan feature to co-exist with 5G preference, + * this function moves 5G channels ahead of 2G channels. This function can + * also move 2G channels, ahead of DFS channel or vice versa. Order is + * maintained among same category channels + * + * Return: None + */ +void csr_roam_arrange_ch_list(tpAniSirGlobal mac_ctx, + tSirUpdateChanParam *chan_list, uint8_t num_channel) +{ + bool prefer_5g = CSR_IS_ROAM_PREFER_5GHZ(mac_ctx); + bool prefer_dfs = CSR_IS_DFS_CH_ROAM_ALLOWED(mac_ctx); + int i, j = 0; + tSirUpdateChanParam *tmp_list = NULL; + + if (!prefer_5g) + return; + + tmp_list = (tSirUpdateChanParam *) + cdf_mem_malloc(sizeof(tSirUpdateChanParam) * num_channel); + if (tmp_list == NULL) { + sms_log(mac_ctx, LOGE, FL("Memory allocation failed")); + return; + } + + /* Fist copy Non-DFS 5g channels */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_5GHZ(chan_list[i].chanId) && + !CDS_IS_DFS_CH(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], + &chan_list[i], sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + if (prefer_dfs) { + /* next copy DFS channels (remaining channels in 5G) */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_5GHZ(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + } else { + /* next copy 2G channels */ + for (i = 0; i < num_channel; i++) { + if (CDS_IS_CHANNEL_24GHZ(chan_list[i].chanId)) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + } + /* copy rest of the channels in same order to tmp list */ + for (i = 0; i < num_channel; i++) { + if (chan_list[i].chanId != INVALID_CHANNEL_ID) { + cdf_mem_copy(&tmp_list[j++], &chan_list[i], + sizeof(tSirUpdateChanParam)); + chan_list[i].chanId = INVALID_CHANNEL_ID; + } + } + /* copy tmp list to original channel list buffer */ + cdf_mem_copy(chan_list, tmp_list, + sizeof(tSirUpdateChanParam) * num_channel); + cdf_mem_free(tmp_list); +} + /** * csr_roam_sort_channel_for_early_stop() - Sort the channels + * @mac_ctx: mac global context * @chan_list: Original channel list from the upper layers * @num_channel: Number of original channels * @@ -495,8 +571,8 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * * * Return: None */ -void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list, - uint8_t num_channel) +void csr_roam_sort_channel_for_early_stop(tpAniSirGlobal mac_ctx, + tSirUpdateChanList *chan_list, uint8_t num_channel) { tSirUpdateChanList *chan_list_greedy, *chan_list_non_greedy; uint8_t i, j; @@ -587,6 +663,9 @@ void csr_roam_sort_channel_for_early_stop(tSirUpdateChanList *chan_list, cdf_mem_copy(&chan_list->chanParam[i], &chan_list_non_greedy->chanParam[j], num_non_greedy_chan * sizeof(tSirUpdateChanParam)); + + /* Update channel list for 5g preference and allow DFS roam */ + csr_roam_arrange_ch_list(mac_ctx, chan_list->chanParam, num_channel); scan_list_sort_error: cdf_mem_free(chan_list_greedy); cdf_mem_free(chan_list_non_greedy); @@ -673,7 +752,8 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) } } if (pMac->roam.configParam.early_stop_scan_enable) - csr_roam_sort_channel_for_early_stop(pChanList, num_channel); + csr_roam_sort_channel_for_early_stop(pMac, pChanList, + num_channel); else CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, FL("Early Stop Scan Feature not supported")); @@ -726,7 +806,6 @@ CDF_STATUS csr_start(tpAniSirGlobal pMac) CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, "Scan offload is enabled, update default chan list"); status = csr_update_channel_list(pMac); - } while (0); return status; } -- cgit v1.2.3 From f2a13f96c88dde59195d300cce53a5eb059ed426 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 22 Dec 2015 17:18:56 -0800 Subject: qcacld-3.0: Fix rrm capability update from config ini file Get rrm capab from mac_ctx in function sme_get_config_param(). This ensures that subsequent calls to this function will correctly update rrm config. Change-Id: Iddaae66b94ccaa127f08fd0a897bc986a959a0eb CRs-Fixed: 955114 --- core/sme/src/common/sme_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index fa82c159f195..a6c41260ecc6 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -4339,6 +4339,9 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) pMac->roam.configParam.early_stop_scan_min_threshold; pParam->early_stop_scan_max_threshold = pMac->roam.configParam.early_stop_scan_max_threshold; + cdf_mem_copy(&pParam->rrmConfig, + &pMac->rrm.rrmSmeContext.rrmConfig, + sizeof(pMac->rrm.rrmSmeContext.rrmConfig)); sme_release_global_lock(&pMac->sme); } -- cgit v1.2.3 From 83622ef789a274595f414d5994e2c6f31ebc2d5e Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Wed, 25 Nov 2015 16:27:41 -0800 Subject: qcacld-3.0: For LFR 3, save reassoc frame sent OTA by firmware In LFR3 reassoc frame is sent by firmware and host or supplicant is not aware of its content. Because of this supplicant does not have complete information to perform EAP exchange with authenticator if fresh EAP exchange is requested. To fix this: 1) Take the reassoc req frame passed by firmware and save that to pe session This frame will then be passed to supplicant through usual path. 2) In case of FT connection, do not pass key replay counter attribute to supplicant. Change-Id: I51dd8004c910b45c7f25e9cd140448e592b096b3 CRs-Fixed: 943711 --- core/hdd/src/wlan_hdd_assoc.c | 26 +++++++++++++++++++++++++- core/hdd/src/wlan_hdd_cfg80211.c | 33 +++++++++++++++++++++++---------- core/mac/inc/sir_api.h | 2 ++ core/mac/src/pe/lim/lim_api.c | 25 +++++++++++++++++++++++++ core/wma/src/wma_scan_roam.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 102 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index e69f3c725c31..2c09426a1b48 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1368,6 +1368,7 @@ static void hdd_send_re_assoc_event(struct net_device *dev, unsigned int len = 0; u8 *pFTAssocRsp = NULL; uint8_t *rspRsnIe = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); + uint8_t *assoc_req_ies = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); uint32_t rspRsnLength = 0; struct ieee80211_channel *chan; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); @@ -1383,6 +1384,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev, return; } + if (!assoc_req_ies) { + hdd_err("Unable to allocate Assoc Req IE"); + return; + } if (pCsrRoamInfo == NULL) { hddLog(LOGE, FL("Invalid CSR roam info")); goto done; @@ -1462,14 +1467,24 @@ static void hdd_send_re_assoc_event(struct net_device *dev, final_req_ie, (ssid_ie_len + reqRsnLength), rspRsnIe, rspRsnLength, GFP_KERNEL); + cdf_mem_copy(assoc_req_ies, + (u8 *)pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength, + pCsrRoamInfo->nAssocReqLength); + + hdd_notice("ReAssoc Req IE dump"); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_DEBUG, + assoc_req_ies, pCsrRoamInfo->nAssocReqLength); + wlan_hdd_send_roam_auth_event(pHddCtx, pCsrRoamInfo->bssid.bytes, - reqRsnIe, reqRsnLength, rspRsnIe, rspRsnLength, + assoc_req_ies, pCsrRoamInfo->nAssocReqLength, + rspRsnIe, rspRsnLength, pCsrRoamInfo); done: sme_roam_free_connect_profile(hal_handle, &roam_profile); if (final_req_ie) kfree(final_req_ie); kfree(rspRsnIe); + kfree(assoc_req_ies); } /** @@ -1967,6 +1982,15 @@ defined(FEATURE_WLAN_LFR) "assocReqlen %d assocRsplen %d", assocReqlen, assocRsplen); + + hdd_notice( + "Reassoc Req IE dump"); + CDF_TRACE_HEX_DUMP( + CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_DEBUG, + pFTAssocReq, + assocReqlen); + cfg80211_roamed(dev, chan, pRoamInfo-> bssid.bytes, diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index aa2004dc00ee..8d830a3cbc0d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3047,16 +3047,29 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, if (roam_info_ptr->synchAuthStatus == CSR_ROAM_AUTH_STATUS_AUTHENTICATED) { hddLog(CDF_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(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) { + hdd_err("nla put fail"); + goto nla_put_failure; + } + /* if FT connection: dont send ROAM_AUTH_KEY_REPLAY_CTR */ + if (roam_info_ptr->u.pConnectedProfile->AuthType != + eCSR_AUTH_TYPE_FT_RSN && + roam_info_ptr->u.pConnectedProfile->AuthType != + eCSR_AUTH_TYPE_FT_RSN_PSK && + nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, + SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr)) { + hdd_err("non FT connection."); + hdd_err("failed to send replay counter."); + goto nla_put_failure; + } + if (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)) { + hdd_err("nla put fail"); goto nla_put_failure; } } else { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d0c794834bf3..d41818245bca 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3941,6 +3941,8 @@ typedef struct sSirSmeRoamOffloadSynchInd { uint16_t beaconProbeRespLength; uint16_t reassocRespOffset; uint16_t reassocRespLength; + uint16_t reassoc_req_offset; + uint16_t reassoc_req_length; uint8_t isBeacon; uint8_t roamedVdevId; struct cdf_mac_addr bssid; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 2a2134ad58fd..af61ed339e0e 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2036,6 +2036,31 @@ void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) /* Prepare the session right now with as much as possible */ lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr); + + if (ft_session_ptr->assocReqLen) { + /* + * For LFR3 the Assoc Request frame was sent by firmware, hence + * pe session struct does not have corresponding IEs. Firmware + * sends whole ASSOC req frame upto host in Roam Sync Event. + * Copy this frame pe session's buffer, so that it can follow + * LFR2 code path to send them to supplicant. + */ + ft_session_ptr->assocReqLen = + roam_sync_ind_ptr->reassoc_req_length + - SIR_MAC_HDR_LEN_3A - SIR_MAC_REASSOC_SSID_OFFSET; + ft_session_ptr->assocReq = + cdf_mem_malloc(ft_session_ptr->assocReqLen); + if (NULL == ft_session_ptr->assocReq) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3: Failed to alloc memory for Assoc Req"); + return; + } + cdf_mem_copy(ft_session_ptr->assocReq, + (uint8_t *)roam_sync_ind_ptr + + roam_sync_ind_ptr->reassoc_req_offset + + SIR_MAC_HDR_LEN_3A + SIR_MAC_REASSOC_SSID_OFFSET, + ft_session_ptr->assocReqLen); + } lim_ft_prepare_add_bss_req(pMac, false, ft_session_ptr, bss_desc_ptr); mmh_msg.type = roam_sync_ind_ptr->messageType; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index f170cca1c1a4..d4bb3367ecf2 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -2728,6 +2728,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, wmi_roam_synch_event_fixed_param *synch_event = NULL; uint8_t *bcn_probersp_ptr = NULL; uint8_t *reassoc_rsp_ptr = NULL; + uint8_t *reassoc_req_ptr = NULL; tp_wma_handle wma = (tp_wma_handle) handle; wmi_channel *chan = NULL; wmi_key_material *key = NULL; @@ -2759,7 +2760,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, } wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true; len = sizeof(roam_offload_synch_ind) + - synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len; + synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len + + synch_event->reassoc_req_len; roam_synch_ind_ptr = (roam_offload_synch_ind *) cdf_mem_malloc(len); if (!roam_synch_ind_ptr) { @@ -2786,6 +2788,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, roam_synch_ind_ptr->isBeacon = synch_event->is_beacon; WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, roam_synch_ind_ptr->bssid.bytes); + /* Beacon/Probe Rsp data */ roam_synch_ind_ptr->beaconProbeRespOffset = sizeof(roam_offload_synch_ind); bcn_probersp_ptr = @@ -2795,6 +2798,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, synch_event->bcn_probe_rsp_len; cdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, roam_synch_ind_ptr->beaconProbeRespLength); + + /* ReAssoc Rsp data */ roam_synch_ind_ptr->reassocRespOffset = sizeof(roam_offload_synch_ind) + roam_synch_ind_ptr->beaconProbeRespLength; @@ -2804,18 +2809,37 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, cdf_mem_copy(reassoc_rsp_ptr, param_buf->reassoc_rsp_frame, roam_synch_ind_ptr->reassocRespLength); + + /* ReAssoc Req data */ + roam_synch_ind_ptr->reassoc_req_offset = + sizeof(roam_offload_synch_ind) + + roam_synch_ind_ptr->beaconProbeRespLength + + roam_synch_ind_ptr->reassocRespLength; + roam_synch_ind_ptr->reassoc_req_length = synch_event->reassoc_req_len; + reassoc_req_ptr = (uint8_t *) roam_synch_ind_ptr + + roam_synch_ind_ptr->reassoc_req_offset; + cdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame, + roam_synch_ind_ptr->reassoc_req_length); + chan = (wmi_channel *) param_buf->chan; roam_synch_ind_ptr->chan_freq = chan->mhz; key = (wmi_key_material *) param_buf->key; if (key != NULL) { - CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, - key->replay_counter, SIR_REPLAY_CTR_LEN); cdf_mem_copy(roam_synch_ind_ptr->kck, key->kck, SIR_KCK_KEY_LEN); cdf_mem_copy(roam_synch_ind_ptr->kek, key->kek, SIR_KEK_KEY_LEN); cdf_mem_copy(roam_synch_ind_ptr->replay_ctr, key->replay_counter, SIR_REPLAY_CTR_LEN); + WMA_LOGD("%s: KCK dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->kck, SIR_KCK_KEY_LEN); + WMA_LOGD("%s: KEK dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->kek, SIR_KEK_KEY_LEN); + WMA_LOGD("%s: Key Replay Counter dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->replay_counter, SIR_REPLAY_CTR_LEN); } wma_send_msg(wma, WMA_ROAM_OFFLOAD_SYNCH_IND, (void *) roam_synch_ind_ptr, 0); -- cgit v1.2.3 From 44748d460e112bb68099d3273dc0ace3fa986943 Mon Sep 17 00:00:00 2001 From: Yuanyuan Liu Date: Wed, 2 Dec 2015 10:39:51 -0800 Subject: qcacld-3.0: Add support of setting FW debug mode FW needs the debug mode from WLAN INI file. After parsing INI file, WLAN driver passes the mode value to platform driver, which uses QMI message to exchange information with FW. Change-Id: Ifd01b18bcfafad2344196d80ab17c605cca35972 CRs-Fixed: 942237 --- core/hdd/src/wlan_hdd_main.c | 3 +++ core/hif/inc/platform_icnss.h | 37 ++++++++++++++++++++++++++++++++++++ core/hif/src/icnss_stub/icnss_stub.c | 27 ++++++++++++++++++++++++++ core/hif/src/icnss_stub/icnss_stub.h | 1 + 4 files changed, 68 insertions(+) create mode 100644 core/hif/inc/platform_icnss.h diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2b3fccef9b94..7d757071630f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -104,6 +104,7 @@ extern int hdd_hostapd_stop(struct net_device *dev); #include "wma.h" #include "cds_concurrency.h" #include "wlan_hdd_green_ap.h" +#include "platform_icnss.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -4788,6 +4789,8 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto err_config; } + icnss_set_fw_debug_mode(hdd_ctx->config->enablefwlog); + hdd_ctx->current_intf_count = 0; hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX; diff --git a/core/hif/inc/platform_icnss.h b/core/hif/inc/platform_icnss.h new file mode 100644 index 000000000000..40c22b6c265a --- /dev/null +++ b/core/hif/inc/platform_icnss.h @@ -0,0 +1,37 @@ +/* + * 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 _PLATFORM_ICNSS_H_ +#define _PLATFORM_ICNSS_H_ + +#ifdef HIF_PCI +#include "icnss_stub.h" +#else +#include +#endif + +#endif diff --git a/core/hif/src/icnss_stub/icnss_stub.c b/core/hif/src/icnss_stub/icnss_stub.c index 484d1e2cb738..aa958ec335d6 100644 --- a/core/hif/src/icnss_stub/icnss_stub.c +++ b/core/hif/src/icnss_stub/icnss_stub.c @@ -93,6 +93,17 @@ int icnss_wlan_disable(enum icnss_driver_mode mode) return 0; } +/** + * icnss_set_fw_debug_mode() - icnss_set_fw_debug_mode + * @mode: fw debug mode, 0 for QXDM, 1 for WMI + * + * Return: int + */ +int icnss_set_fw_debug_mode(bool mode) +{ + return 0; +} + #else /** @@ -167,6 +178,22 @@ int icnss_wlan_disable(enum icnss_driver_mode con_mode) cnss_wlan_disable(mode); return 0; } + +/** + * icnss_set_fw_debug_mode() - call the platform driver to set fw + * debug mode + * @mode: fw debug mode, 0 for QXDM, 1 for WMI + * + * This function passes the fw debug mode to platform driver. + * cnss_set_fw_debug_mode has been hacked to do a qmi handshake with fw. + * This is not needed for rome. + * + * Return: int + */ +int icnss_set_fw_debug_mode(bool mode) +{ + return cnss_set_fw_debug_mode(mode); +} #endif /** diff --git a/core/hif/src/icnss_stub/icnss_stub.h b/core/hif/src/icnss_stub/icnss_stub.h index bce229a2dbdf..33a83acaab00 100644 --- a/core/hif/src/icnss_stub/icnss_stub.h +++ b/core/hif/src/icnss_stub/icnss_stub.h @@ -121,6 +121,7 @@ struct icnss_soc_info { int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config, enum icnss_driver_mode mode, const char *host_version); int icnss_wlan_disable(enum icnss_driver_mode mode); +int icnss_set_fw_debug_mode(bool mode); int icnss_ce_request_irq(int ce_id, irqreturn_t (*handler)(int ce_id, void *arg), unsigned long flags, const char *name, void *context); -- cgit v1.2.3 From 28556aa279c8bacff08097beb6c70091f4b745d6 Mon Sep 17 00:00:00 2001 From: Sushant Kaushik Date: Wed, 22 Jul 2015 12:22:20 +0530 Subject: qcacld-3.0: Fix static analysis error in limProcessTdls.c qcacld-2.0 to qcacld-3.0 propagation Currently while populating 11a and 11b rates, there is no bound check for rateset array. This can result in buffer overflow. As a part of fix add bound check to avoid any buffer overflow for the rateset. CRs-fixed: 798054 Change-Id: Ib42f5de642ad54d5c2a1ccdab37d88928b98af01 --- core/mac/src/pe/lim/lim_process_tdls.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 9686b4b7e318..0b49077eea2c 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2159,15 +2159,13 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads, (temp_rate_set.rate[j] & 0x7F)) continue; -#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC - if ((b_rateindex > HAL_NUM_11B_RATES) || - (a_rateindex > HAL_NUM_11A_RATES)) { + if ((b_rateindex > SIR_NUM_11B_RATES) || + (a_rateindex > SIR_NUM_11A_RATES)) { lim_log(mac_ctx, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)"), b_rateindex, a_rateindex); return eSIR_FAILURE; } -#endif if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) { is_a_rate = 1; if (a_rateindex < SIR_NUM_11A_RATES) -- cgit v1.2.3 From 2a542e63faf394a1045ac2d337317ef229e7f1f2 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 15:49:31 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSetHT2040Mode Replace tSirMacAddr with cdf_mac_addr in tSirSetHT2040Mode. Change-Id: I802cd0353e6a6408f911ccf26a80b938be8a6e48 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d41818245bca..e284ecefec2a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2473,7 +2473,7 @@ typedef struct sSirSetHT2040Mode { uint16_t length; uint8_t cbMode; bool obssEnabled; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; uint8_t sessionId; /* Session ID */ } tSirSetHT2040Mode, *tpSirSetHT2040Mode; #endif diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 70ceb3dfba6b..98da86c48ea7 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4341,12 +4341,12 @@ static void __lim_process_sme_set_ht2040_mode(tpAniSirGlobal pMac, pSetHT2040Mode = (tpSirSetHT2040Mode) pMsgBuf; psessionEntry = pe_find_session_by_bssid(pMac, - pSetHT2040Mode->bssId, + pSetHT2040Mode->bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOG1, FL("Session does not exist for given BSSID ")); - lim_print_mac_addr(pMac, pSetHT2040Mode->bssId, LOG1); + lim_print_mac_addr(pMac, pSetHT2040Mode->bssid.bytes, LOG1); return; } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 0c96ec5aeef4..afdd9c4e8857 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14206,12 +14206,10 @@ CDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId, pMsg->messageType = eWNI_SME_SET_HT_2040_MODE; pMsg->length = len; - /* bssId */ - cdf_mem_copy((tSirMacAddr *) pMsg->bssId, - &pSession->selfMacAddr, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssid, &pSession->selfMacAddr); sms_log(pMac, LOG1, FL("CSR Attempting to set HT20/40 mode for Bssid= " - MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssId)); + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssid.bytes)); pMsg->sessionId = sessionId; sms_log(pMac, LOG1, FL(" session %d HT20/40 mode %d"), sessionId, cbMode); -- cgit v1.2.3 From 2087d8cb3e2adaffb4df910d0ea8f6c4bdc8ab6f Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 15:54:33 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirChangeBIParams Replace tSirMacAddr with cdf_mac_addr in tSirChangeBIParams. Change-Id: I21823288cb43379625ec892967eab432c89510cc CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/sme/src/csr/csr_api_roam.c | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e284ecefec2a..fdf0b749fcde 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2463,7 +2463,7 @@ typedef struct sSirChangeBIParams { uint16_t messageType; uint16_t length; uint16_t beaconInterval; /* Beacon Interval */ - tSirMacAddr bssId; + struct cdf_mac_addr bssid; uint8_t sessionId; /* Session ID */ } tSirChangeBIParams, *tpSirChangeBIParams; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 98da86c48ea7..ad1cea7239c9 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4276,7 +4276,7 @@ static void __lim_process_sme_change_bi(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pChangeBIParams = (tpSirChangeBIParams) pMsgBuf; psessionEntry = pe_find_session_by_bssid(pMac, - pChangeBIParams->bssId, + pChangeBIParams->bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index afdd9c4e8857..ceca2cdcdd11 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14162,12 +14162,10 @@ CDF_STATUS csr_send_chng_mcc_beacon_interval(tpAniSirGlobal pMac, uint32_t sessi pMsg->messageType = eWNI_SME_CHNG_MCC_BEACON_INTERVAL; pMsg->length = len; - /* bssId */ - cdf_mem_copy((tSirMacAddr *) pMsg->bssId, - &pSession->selfMacAddr, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssid, &pSession->selfMacAddr); sms_log(pMac, LOG1, FL("CSR Attempting to change BI for Bssid= " - MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssId)); + MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pMsg->bssid.bytes)); pMsg->sessionId = sessionId; sms_log(pMac, LOG1, FL(" session %d BeaconInterval %d"), sessionId, -- cgit v1.2.3 From c250b07891b4ca0c2aa04cc23aa1916eb7b1f8b0 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 25 Nov 2015 12:18:44 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirUpdateAPWPSIEsReq Replace tSirMacAddr with cdf_mac_addr in tSirUpdateAPWPSIEsReq. Change-Id: Ia6d8ea2523257caac541c84d10b7e6a81afc606b CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/sme/src/csr/csr_api_roam.c | 29 ++++++++++------------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index fdf0b749fcde..9e1501fc4ba8 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2446,7 +2446,7 @@ typedef struct sSirUpdateAPWPSIEsReq { uint16_t messageType; /* eWNI_SME_UPDATE_APWPSIE_REQ */ uint16_t length; uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint8_t sessionId; /* Session ID */ tSirAPWPSIEs APWPSIEs; } tSirUpdateAPWPSIEsReq, *tpSirUpdateAPWPSIEsReq; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index ad1cea7239c9..8e15c31d45a3 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4106,7 +4106,7 @@ __lim_process_sme_update_apwpsi_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf) sizeof(struct sSirUpdateAPWPSIEsReq)); psessionEntry = pe_find_session_by_bssid(pMac, - pUpdateAPWPSIEsReq->bssId, + pUpdateAPWPSIEsReq->bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGW, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index ceca2cdcdd11..d6e8468150d8 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17603,26 +17603,23 @@ CDF_STATUS csr_roam_update_apwpsie(tpAniSirGlobal pMac, uint32_t sessionId, tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); if (NULL == pSession) { sms_log(pMac, LOGE, - FL(" Session does not exist for session id %d"), + FL("Session does not exist for session id %d"), sessionId); return CDF_STATUS_E_FAILURE; } - do { - pMsg = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); - if (NULL == pMsg) - return CDF_STATUS_E_NOMEM; - cdf_mem_set(pMsg, sizeof(tSirUpdateAPWPSIEsReq), 0); - pMsg->messageType = eWNI_SME_UPDATE_APWPSIE_REQ; - pMsg->transactionId = 0; - cdf_mem_copy(pMsg->bssId, &pSession->selfMacAddr, - sizeof(tSirMacAddr)); - pMsg->sessionId = sessionId; - cdf_mem_copy(&pMsg->APWPSIEs, pAPWPSIES, - sizeof(tSirAPWPSIEs)); - pMsg->length = sizeof(struct sSirUpdateAPWPSIEsReq); - status = cds_send_mb_message_to_mac(pMsg); - } while (0); + pMsg = cdf_mem_malloc(sizeof(*pMsg)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + pMsg->messageType = eWNI_SME_UPDATE_APWPSIE_REQ; + pMsg->transactionId = 0; + cdf_copy_macaddr(&pMsg->bssid, &pSession->selfMacAddr); + pMsg->sessionId = sessionId; + cdf_mem_copy(&pMsg->APWPSIEs, pAPWPSIES, sizeof(tSirAPWPSIEs)); + pMsg->length = sizeof(*pMsg); + status = cds_send_mb_message_to_mac(pMsg); + return status; } -- cgit v1.2.3 From 4c9722cde076a00ed4721fb23535dfef1b918efd Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 25 Nov 2015 12:31:44 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in WowlEnterParams Replace tSirMacAddr with cdf_mac_addr in WowlEnterParams. Change-Id: Ifc2edce83693fb01ef4ea642727902d493347225 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_wowl.c | 6 +++--- core/mac/inc/sir_api.h | 6 +++--- core/sme/src/common/sme_power_save.c | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/hdd/src/wlan_hdd_wowl.c b/core/hdd/src/wlan_hdd_wowl.c index 1c2ff5789ae7..2901e1c2d207 100644 --- a/core/hdd/src/wlan_hdd_wowl.c +++ b/core/hdd/src/wlan_hdd_wowl.c @@ -522,8 +522,8 @@ bool hdd_enter_wowl(hdd_adapter_t *pAdapter, bool enable_mp, bool enable_pbm) wowParams.ucMagicPktEnable = enable_mp; wowParams.sessionId = pAdapter->sessionId; if (enable_mp) { - cdf_copy_macaddr((struct cdf_mac_addr *) &(wowParams.magicPtrn), - &(pAdapter->macAddressCurrent)); + cdf_copy_macaddr(&wowParams.magic_ptrn, + &pAdapter->macAddressCurrent); } #ifdef WLAN_WAKEUP_EVENTS wowParams.ucWoWEAPIDRequestEnable = true; @@ -533,7 +533,7 @@ bool hdd_enter_wowl(hdd_adapter_t *pAdapter, bool enable_mp, bool enable_pbm) wowParams.ucWoWBSSConnLoss = true; #endif /* WLAN_WAKEUP_EVENTS */ - /* Request to put Libra into WoWL */ + /* Request to put FW into WoWL */ cdf_ret_status = sme_enter_wowl(hHal, hdd_wowl_callback, pAdapter, #ifdef WLAN_WAKEUP_EVENTS hdd_wowl_wake_indication_callback, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 9e1501fc4ba8..5c6454451080 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2189,7 +2189,7 @@ typedef struct sSirSmeWowlEnterParams { uint8_t ucMagicPktEnable; /* Magic pattern */ - tSirMacAddr magicPtrn; + struct cdf_mac_addr magic_ptrn; /* Enables/disables packet pattern filtering */ uint8_t ucPatternFilteringEnable; @@ -2222,7 +2222,7 @@ typedef struct sSirSmeWowlEnterParams { uint8_t ucWoWBSSConnLoss; #endif /* WLAN_WAKEUP_EVENTS */ - tSirMacAddr bssId; + struct cdf_mac_addr bssid; } tSirSmeWowlEnterParams, *tpSirSmeWowlEnterParams; /* PE<->HAL: Enter WOWLAN parameters */ @@ -2233,7 +2233,7 @@ typedef struct sSirHalWowlEnterParams { uint8_t ucMagicPktEnable; /* Magic pattern */ - tSirMacAddr magicPtrn; + struct cdf_mac_addr magic_ptrn; /* Enables/disables packet pattern filtering in firmware. Enabling this flag enables broadcast pattern matching diff --git a/core/sme/src/common/sme_power_save.c b/core/sme/src/common/sme_power_save.c index b12bd4d004e3..8158218a0750 100644 --- a/core/sme/src/common/sme_power_save.c +++ b/core/sme/src/common/sme_power_save.c @@ -248,7 +248,7 @@ CDF_STATUS sme_ps_enter_wowl_req_params(tpAniSirGlobal mac_ctx, hal_wowl_params = cdf_mem_malloc(sizeof(*hal_wowl_params)); if (NULL == hal_wowl_params) { sms_log(mac_ctx, LOGP, - FL("Fail to allocate memory for Enter Wowl Request ")); + FL("Fail to allocate memory for Enter Wowl Request")); return CDF_STATUS_E_NOMEM; } cdf_mem_set((uint8_t *) hal_wowl_params, sizeof(*hal_wowl_params), 0); @@ -257,9 +257,8 @@ CDF_STATUS sme_ps_enter_wowl_req_params(tpAniSirGlobal mac_ctx, hal_wowl_params->ucMagicPktEnable = sme_wowl_params->ucMagicPktEnable; hal_wowl_params->ucPatternFilteringEnable = sme_wowl_params->ucPatternFilteringEnable; - cdf_mem_copy((uint8_t *) hal_wowl_params->magicPtrn, - (uint8_t *) sme_wowl_params->magicPtrn, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&hal_wowl_params->magic_ptrn, + &sme_wowl_params->magic_ptrn); #ifdef WLAN_WAKEUP_EVENTS hal_wowl_params->ucWoWEAPIDRequestEnable = -- cgit v1.2.3 From 05123e50519747d9f689ae539372c2509e7b2d5c Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 25 Nov 2015 12:42:32 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSmeCsaOffloadInd Replace tSirMacAddr with cdf_mac_addr in tSmeCsaOffloadInd. Change-Id: Iaf4357b2da216d9f11ca35331d45bff5193a2ee9 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 6 +++--- core/sme/src/csr/csr_api_scan.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 5c6454451080..6e0656add819 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2144,7 +2144,7 @@ typedef struct sSmeMaxAssocInd { typedef struct sSmeCsaOffloadInd { uint16_t mesgType; /* eWNI_SME_CSA_OFFLOAD_EVENT */ uint16_t mesgLen; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ } tSmeCsaOffloadInd, *tpSmeCsaOffloadInd; /* WOW related structures */ diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 470f11958ec1..ec18e49165a5 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2212,13 +2212,13 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) cdf_mem_set(csa_offload_ind, sizeof(tSmeCsaOffloadInd), 0); csa_offload_ind->mesgType = eWNI_SME_CSA_OFFLOAD_EVENT; csa_offload_ind->mesgLen = sizeof(tSmeCsaOffloadInd); - cdf_mem_copy(csa_offload_ind->bssId, session_entry->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(csa_offload_ind->bssid.bytes, session_entry->bssId, + CDF_MAC_ADDR_SIZE); mmh_msg.type = eWNI_SME_CSA_OFFLOAD_EVENT; mmh_msg.bodyptr = csa_offload_ind; mmh_msg.bodyval = 0; lim_log(mac_ctx, LOG1, - FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME. ")); + FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME.")); MTRACE(mac_trace_msg_tx (mac_ctx, session_entry->peSessionId, mmh_msg.type)); #ifdef FEATURE_WLAN_DIAG_SUPPORT diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 66f4609fc5f4..93866115f04a 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2162,13 +2162,13 @@ void csr_scan_flush_bss_entry(tpAniSirGlobal pMac, while (pEntry != NULL) { pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link); if (cdf_mem_compare(pBssDesc->Result.BssDescriptor.bssId, - pCsaOffloadInd->bssId, sizeof(tSirMacAddr))) { + pCsaOffloadInd->bssid.bytes, CDF_MAC_ADDR_SIZE)) { pFreeElem = pEntry; pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK); csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK); csr_free_scan_result_entry(pMac, pBssDesc); sms_log(pMac, LOG1, FL("Removed BSS entry:%pM"), - pCsaOffloadInd->bssId); + pCsaOffloadInd->bssid.bytes); continue; } -- cgit v1.2.3 From 430bfc3cab8ac7bf8cc5925065250771f698b7f2 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 25 Nov 2015 15:46:41 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSmeMaxAssocInd Replace tSirMacAddr with cdf_mac_addr in sSmeMaxAssocInd and tSirSmeGetAssocSTAsReq. Change-Id: Ie36a22b5ee5c823833981b51ef91525f6c6af692 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 4 +- core/sme/src/csr/csr_api_roam.c | 47 ++++++++++------------ core/sme/src/csr/csr_inside_api.h | 2 +- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 6e0656add819..b6b78404b3b0 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2125,7 +2125,7 @@ typedef struct sLimScanChnInfo { typedef struct sSirSmeGetAssocSTAsReq { uint16_t messageType; /* eWNI_SME_GET_ASSOC_STAS_REQ */ uint16_t length; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint16_t modId; void *pUsrContext; void *pSapEventCallback; @@ -2138,7 +2138,7 @@ typedef struct sSmeMaxAssocInd { uint16_t mesgLen; uint8_t sessionId; /* the new peer that got rejected max assoc limit reached */ - tSirMacAddr peerMac; + struct cdf_mac_addr peer_mac; } tSmeMaxAssocInd, *tpSmeMaxAssocInd; typedef struct sSmeCsaOffloadInd { diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 8e15c31d45a3..32aab52b1184 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3145,7 +3145,7 @@ void lim_process_sme_get_assoc_sta_info(tpAniSirGlobal mac_ctx, * Find PE session Entry */ session_entry = pe_find_session_by_bssid(mac_ctx, - get_assoc_stas_req.bssId, + get_assoc_stas_req.bssid.bytes, &session_id); if (session_entry == NULL) { lim_log(mac_ctx, LOGE, diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index ec18e49165a5..68e11a6c8528 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2305,8 +2305,8 @@ void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMa return; } cdf_mem_set((void *)pSmeMaxAssocInd, sizeof(tSmeMaxAssocInd), 0); - cdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peerMac, - (uint8_t *) peerMacAddr, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peer_mac.bytes, + (uint8_t *) peerMacAddr, CDF_MAC_ADDR_SIZE); pSmeMaxAssocInd->mesgType = eWNI_SME_MAX_ASSOC_EXCEEDED; pSmeMaxAssocInd->mesgLen = sizeof(tSmeMaxAssocInd); pSmeMaxAssocInd->sessionId = smesessionId; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index d6e8468150d8..7b69b208195b 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3201,7 +3201,7 @@ csr_roam_get_associated_stas(tpAniSirGlobal pMac, uint32_t sessionId, MAC_ADDR_ARRAY(bssId.bytes)); status = csr_send_mb_get_associated_stas_req_msg(pMac, sessionId, modId, - bssId.bytes, + bssId, pUsrContext, pfnSapEventCallback, pAssocStasBuf); @@ -10888,8 +10888,7 @@ csr_roam_chk_lnk_max_assoc_exceeded(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) FL("max assoc have been reached, new peer cannot be accepted")); sessionId = pSmeMaxAssocInd->sessionId; roam_info.sessionId = sessionId; - cdf_mem_copy(&roam_info.peerMac, pSmeMaxAssocInd->peerMac, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info.peerMac, &pSmeMaxAssocInd->peer_mac); csr_roam_call_callback(mac_ctx, sessionId, &roam_info, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED); @@ -14072,33 +14071,29 @@ CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, CDF_STATUS csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, - CDF_MODULE_ID modId, tSirMacAddr bssId, - void *pUsrContext, void *pfnSapEventCallback, + CDF_MODULE_ID modId, + struct cdf_mac_addr bssid, + void *pUsrContext, + void *pfnSapEventCallback, uint8_t *pAssocStasBuf) { CDF_STATUS status = CDF_STATUS_SUCCESS; tSirSmeGetAssocSTAsReq *pMsg; - do { - pMsg = cdf_mem_malloc(sizeof(tSirSmeGetAssocSTAsReq)); - if (NULL == pMsg) - status = CDF_STATUS_E_NOMEM; - else - status = CDF_STATUS_SUCCESS; - if (!CDF_IS_STATUS_SUCCESS(status)) - break; - cdf_mem_set(pMsg, sizeof(tSirSmeGetAssocSTAsReq), 0); - pMsg->messageType = eWNI_SME_GET_ASSOC_STAS_REQ; - cdf_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr)); - pMsg->modId = modId; - cdf_mem_copy(pMsg->pUsrContext, - pUsrContext, sizeof(void *)); - cdf_mem_copy(pMsg->pSapEventCallback, - pfnSapEventCallback, sizeof(void *)); - cdf_mem_copy(pMsg->pAssocStasArray, - pAssocStasBuf, sizeof(void *)); - pMsg->length = sizeof(struct sSirSmeGetAssocSTAsReq); - status = cds_send_mb_message_to_mac(pMsg); - } while (0); + + pMsg = cdf_mem_malloc(sizeof(*pMsg)); + if (NULL == pMsg) + return CDF_STATUS_E_NOMEM; + + pMsg->messageType = eWNI_SME_GET_ASSOC_STAS_REQ; + cdf_copy_macaddr(&pMsg->bssid, &bssid); + pMsg->modId = modId; + cdf_mem_copy(pMsg->pUsrContext, pUsrContext, sizeof(void *)); + cdf_mem_copy(pMsg->pSapEventCallback, + pfnSapEventCallback, sizeof(void *)); + cdf_mem_copy(pMsg->pAssocStasArray, pAssocStasBuf, sizeof(void *)); + pMsg->length = sizeof(*pMsg); + status = cds_send_mb_message_to_mac(pMsg); + return status; } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index d3785659569d..88c284ba7f24 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -971,7 +971,7 @@ CDF_STATUS csr_roam_get_associated_stas(tpAniSirGlobal pMac, uint32_t sessionId, CDF_STATUS csr_send_mb_get_associated_stas_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, CDF_MODULE_ID modId, - tSirMacAddr bssId, + struct cdf_mac_addr bssId, void *pUsrContext, void *pfnSapEventCallback, uint8_t *pAssocStasBuf); -- cgit v1.2.3 From 531a667f6c5a0bf84f8b56eb894dbbaba12ded57 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 25 Nov 2015 16:54:41 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSmeIbssPeerInd Replace tSirMacAddr with cdf_mac_addr in tSmeIbssPeerInd and tSirIbssPeerInactivityInd. Change-Id: Ie83aa414e312431aeb7f730a3f8027ea960acc36 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 +-- core/mac/src/pe/lim/lim_ibss_peer_mgmt.c | 3 +-- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 4 +-- core/sme/src/csr/csr_api_roam.c | 30 +++++++++++------------ core/utils/host_diag_log/inc/host_diag_core_log.h | 4 +-- core/wma/src/wma_mgmt.c | 2 +- 6 files changed, 22 insertions(+), 25 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b6b78404b3b0..9eb12a0dbb15 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2080,7 +2080,7 @@ typedef struct sSmeIbssPeerInd { uint16_t mesgLen; uint8_t sessionId; - tSirMacAddr peerAddr; + struct cdf_mac_addr peer_addr; uint16_t staId; /* @@ -2099,7 +2099,7 @@ typedef struct sSmeIbssPeerInd { typedef struct sSirIbssPeerInactivityInd { uint8_t bssIdx; uint8_t staIdx; - tSirMacAddr peerAddr; + struct cdf_mac_addr peer_addr; } tSirIbssPeerInactivityInd, *tpSirIbssPeerInactivityInd; typedef struct sLimScanChn { diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c index b2c974cad41a..e12252b16e08 100644 --- a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c @@ -1784,8 +1784,7 @@ __lim_ibss_peer_inactivity_handler(tpAniSirGlobal pMac, /* delete the peer for which heartbeat is observed */ __lim_ibss_search_and_delete_peer(pMac, psessionEntry, - peerInactivityInd->peerAddr); - + peerInactivityInd->peer_addr.bytes); } /** ------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 68e11a6c8528..75d1d50ea1c9 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1988,8 +1988,8 @@ lim_send_sme_ibss_peer_ind(tpAniSirGlobal pMac, cdf_mem_set((void *)pNewPeerInd, (sizeof(tSmeIbssPeerInd) + beaconLen), 0); - cdf_mem_copy((uint8_t *) pNewPeerInd->peerAddr, - peerMacAddr, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) pNewPeerInd->peer_addr.bytes, + peerMacAddr, CDF_MAC_ADDR_SIZE); pNewPeerInd->staId = staIndex; pNewPeerInd->ucastSig = ucastIdx; pNewPeerInd->bcastSig = bcastIdx; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7b69b208195b..230ad1b927a5 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6007,8 +6007,8 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, WLAN_IBSS_EVENT_JOIN_IBSS_RSP; } if (bss_desc) { - cdf_mem_copy(ibss_log->bssid, - bss_desc->bssId, 6); + cdf_mem_copy(ibss_log->bssid.bytes, + bss_desc->bssId, CDF_MAC_ADDR_SIZE); ibss_log->operatingChannel = bss_desc->channelId; } @@ -9061,8 +9061,7 @@ void csr_roaming_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf) roamInfo.staId = (uint8_t) pIbssPeerInd->staId; roamInfo.ucastSig = (uint8_t) pIbssPeerInd->ucastSig; roamInfo.bcastSig = (uint8_t) pIbssPeerInd->bcastSig; - cdf_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roamInfo.peerMac, &pIbssPeerInd->peer_addr); csr_roam_call_callback(pMac, pSmeRsp->sessionId, &roamInfo, 0, eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); @@ -10420,8 +10419,7 @@ csr_roam_diag_joined_new_bss(tpAniSirGlobal mac_ctx, return; pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING; if (pNewBss) { - cdf_mem_copy(pIbssLog->bssid, pNewBss->bssId.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pIbssLog->bssid, &pNewBss->bssId); if (pNewBss->ssId.length) cdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId, pNewBss->ssId.length); @@ -10610,7 +10608,8 @@ csr_roam_chk_lnk_ibss_new_peer_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) LOG_WLAN_IBSS_C); if (pIbssLog) { pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_JOIN; - cdf_mem_copy(pIbssLog->peerMacAddr, &pIbssPeerInd->peerAddr, 6); + cdf_copy_macaddr(&pIbssLog->peer_macaddr, + &pIbssPeerInd->peer_addr); WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); } #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ @@ -10632,8 +10631,7 @@ csr_roam_chk_lnk_ibss_new_peer_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) sms_log(mac_ctx, LOGW, FL("CSR: connected BSS is empty")); goto callback_and_free; } - cdf_mem_copy(&roam_info.peerMac, pIbssPeerInd->peerAddr, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info.peerMac, &pIbssPeerInd->peer_addr); cdf_mem_copy(&roam_info.bssid, session->pConnectBssDesc->bssId, sizeof(struct cdf_mac_addr)); if (pIbssPeerInd->mesgLen > sizeof(tSmeIbssPeerInd)) { @@ -10676,7 +10674,8 @@ csr_roam_chk_lnk_ibss_new_peer_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) /* NO keys. these key parameters don't matter */ csr_roam_issue_set_context_req(mac_ctx, sessionId, session->connectedProfile.EncryptionType, - session->pConnectBssDesc, &(pIbssPeerInd->peerAddr), + session->pConnectBssDesc, + &pIbssPeerInd->peer_addr.bytes, false, true, eSIR_TX_RX, 0, 0, NULL, 0); } @@ -10718,8 +10717,8 @@ csr_roam_chk_lnk_ibss_peer_departed_ind(tpAniSirGlobal mac_ctx, if (pIbssLog) { pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_LEAVE; if (pIbssPeerInd) { - cdf_mem_copy(pIbssLog->peerMacAddr, - &pIbssPeerInd->peerAddr, 6); + cdf_copy_macaddr(&pIbssLog->peer_macaddr, + &pIbssPeerInd->peer_addr); } WLAN_HOST_DIAG_LOG_REPORT(pIbssLog); } @@ -10729,8 +10728,7 @@ csr_roam_chk_lnk_ibss_peer_departed_ind(tpAniSirGlobal mac_ctx, roam_info.staId = (uint8_t) pIbssPeerInd->staId; roam_info.ucastSig = (uint8_t) pIbssPeerInd->ucastSig; roam_info.bcastSig = (uint8_t) pIbssPeerInd->bcastSig; - cdf_mem_copy(&roam_info.peerMac, pIbssPeerInd->peerAddr, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info.peerMac, &pIbssPeerInd->peer_addr); csr_roam_call_callback(mac_ctx, sessionId, &roam_info, 0, eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED); @@ -12547,8 +12545,8 @@ CDF_STATUS csr_roam_issue_start_bss(tpAniSirGlobal pMac, uint32_t sessionId, if (pBssDesc) { pIbssLog->eventId = WLAN_IBSS_EVENT_JOIN_IBSS_REQ; - cdf_mem_copy(pIbssLog->bssid, pBssDesc->bssId, - 6); + cdf_mem_copy(pIbssLog->bssid.bytes, + pBssDesc->bssId, CDF_MAC_ADDR_SIZE); } else { pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_REQ; diff --git a/core/utils/host_diag_log/inc/host_diag_core_log.h b/core/utils/host_diag_log/inc/host_diag_core_log.h index d17ad46dec5e..a5090113cbf0 100644 --- a/core/utils/host_diag_log/inc/host_diag_core_log.h +++ b/core/utils/host_diag_log/inc/host_diag_core_log.h @@ -98,8 +98,8 @@ typedef struct { log_hdr_type hdr; uint8_t eventId; uint8_t channelSetting; - uint8_t bssid[HOST_LOG_MAX_BSSID_SIZE]; - uint8_t peerMacAddr[HOST_LOG_MAX_BSSID_SIZE]; + struct cdf_mac_addr bssid; + struct cdf_mac_addr peer_macaddr; uint8_t ssid[HOST_LOG_MAX_SSID_SIZE]; uint8_t operatingChannel; uint8_t beaconInterval; diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index fd887da84239..84ffc0eb64ac 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -341,7 +341,7 @@ int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) } p_inactivity->staIdx = peer_id; - cdf_mem_copy(p_inactivity->peerAddr, macaddr, + cdf_mem_copy(p_inactivity->peer_addr.bytes, macaddr, IEEE80211_ADDR_LEN); wma_send_msg(wma, WMA_IBSS_PEER_INACTIVITY_IND, (void *)p_inactivity, 0); -- cgit v1.2.3 From 1e054ed6f1d7efd9855cf8201b04f167fc64ad28 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 3 Dec 2015 19:06:15 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirAggrQosReq Replace tSirMacAddr with cdf_mac_addr in struct sSirAggrQosReq. Change-Id: I1f58cf95eb3028ef763cd624fa05dcdc288d820e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_ft.c | 6 +++--- core/sme/src/qos/sme_qos.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 9eb12a0dbb15..c385c10ce89b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2048,7 +2048,7 @@ typedef struct sSirAggrQosReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint32_t timeout; /* in ms */ uint8_t rspReqd; tSirAggrQosReqInfo aggrInfo; diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index 92769e8bb12d..c7d7f6ab53a7 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -1850,8 +1850,8 @@ tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf return eSIR_MEM_ALLOC_FAILED; } - psessionEntry = - pe_find_session_by_bssid(pMac, aggrQosReq->bssId, &sessionId); + psessionEntry = pe_find_session_by_bssid(pMac, aggrQosReq->bssid.bytes, + &sessionId); if (psessionEntry == NULL) { PELOGE(lim_log @@ -1874,7 +1874,7 @@ tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf return eSIR_FAILURE; } - pSta = dph_lookup_hash_entry(pMac, aggrQosReq->bssId, &aid, + pSta = dph_lookup_hash_entry(pMac, aggrQosReq->bssid.bytes, &aid, &psessionEntry->dph.dphHashTable); if (pSta == NULL) { PELOGE(lim_log(pMac, LOGE, diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 1595a08cce62..52e64bf3edc1 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -3472,7 +3472,7 @@ CDF_STATUS sme_qos_ft_aggr_qos_req(tpAniSirGlobal mac_ctx, uint8_t session_id) aggr_req->sessionId = session_id; aggr_req->timeout = 0; aggr_req->rspReqd = true; - cdf_mem_copy(&aggr_req->bssId[0], + cdf_mem_copy(&aggr_req->bssid.bytes[0], &session->assocInfo.pBssDesc->bssId[0], sizeof(struct cdf_mac_addr)); -- cgit v1.2.3 From 0fcbab2fe4fb3b454a1cdaac090d63597f8effe1 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 3 Dec 2015 19:18:11 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirDelts Req/Rsp Replace tSirMacAddr with cdf_mac_addr in struct sSirDelts Req/Rsp. Change-Id: I66f2b191b1eb823d395f70fc2c66697b377c7482 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +++--- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 3 +-- core/mac/src/pe/lim/lim_utils.c | 2 +- core/sme/src/qos/sme_qos.c | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c385c10ce89b..8f5f48fd1cb4 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1996,9 +1996,9 @@ typedef struct sSirDeltsReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint16_t aid; /* use 0 if macAddr is being specified */ - tSirMacAddr macAddr; /* only on AP to specify the STA */ + struct cdf_mac_addr macaddr; /* only on AP to specify the STA */ uint8_t rspReqd; tSirDeltsReqInfo req; } tSirDeltsReq, *tpSirDeltsReq; @@ -2010,7 +2010,7 @@ typedef struct sSirDeltsRsp { uint16_t transactionId; /* sme transaction Id - for BT-AMP Support */ uint32_t rc; uint16_t aid; /* use 0 if macAddr is being specified */ - tSirMacAddr macAddr; /* only on AP to specify the STA */ + struct cdf_mac_addr macaddr; /* only on AP to specify the STA */ tSirDeltsReqInfo rsp; } tSirDeltsRsp, *tpSirDeltsRsp; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 32aab52b1184..7a4bcfe03240 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3881,7 +3881,7 @@ static void __lim_process_sme_delts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) &smetransactionId); psessionEntry = pe_find_session_by_bssid(pMac, - pDeltsReq->bssId, + pDeltsReq->bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, "Session Does not exist for given bssId"); diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 75d1d50ea1c9..1af8bad7d681 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1783,8 +1783,7 @@ lim_send_sme_delts_rsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, uint32_t status if (psessionEntry != NULL) { rsp->aid = delts->aid; - cdf_mem_copy((uint8_t *) &rsp->macAddr[0], - (uint8_t *) &delts->macAddr[0], 6); + cdf_copy_macaddr(&rsp->macaddr, &delts->macaddr); cdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) &delts->req, sizeof(tSirDeltsReqInfo)); } diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index f49407430ec7..db4b2df2648d 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -5209,7 +5209,7 @@ lim_validate_delts_req(tpAniSirGlobal mac_ctx, tpSirDeltsReq delts_req, &psession_entry->dph.dphHashTable); else sta = dph_lookup_hash_entry(mac_ctx, - delts_req->macAddr, + delts_req->macaddr.bytes, &associd, &psession_entry->dph. dphHashTable); diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 52e64bf3edc1..a171e1f5f9b6 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -4075,7 +4075,7 @@ CDF_STATUS sme_qos_del_ts_req(tpAniSirGlobal pMac, cdf_mem_free(pMsg); return CDF_STATUS_E_FAILURE; } - cdf_mem_copy(&pMsg->bssId[0], + cdf_mem_copy(&pMsg->bssid.bytes[0], &pSession->assocInfo.pBssDesc->bssId[0], sizeof(struct cdf_mac_addr)); -- cgit v1.2.3 From 24dab280116d4fda90a0a6c7a15cb8219193fb55 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 4 Dec 2015 10:54:07 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirAddtsReq Replace tSirMacAddr with cdf_mac_addr in struct sSirAddtsReq. Change-Id: I9a9f4cfc2185859c30d56ec4bc98891c9895531d CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 5 ++--- core/sme/src/qos/sme_qos.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 8f5f48fd1cb4..cf32b59141cf 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1976,7 +1976,7 @@ typedef struct sSirAddtsReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ uint32_t timeout; /* in ms */ uint8_t rspReqd; tSirAddtsReqInfo req; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 7a4bcfe03240..f1d42dcb5daf 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3713,9 +3713,8 @@ static void __lim_process_sme_addts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pSirAddts = (tpSirAddtsReq) pMsgBuf; - psessionEntry = pe_find_session_by_bssid(pMac, - pSirAddts->bssId, - &sessionId); + psessionEntry = pe_find_session_by_bssid(pMac, pSirAddts->bssid.bytes, + &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, "Session Does not exist for given bssId"); return; diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index a171e1f5f9b6..8372a1fa20d3 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -3965,7 +3965,7 @@ CDF_STATUS sme_qos_add_ts_req(tpAniSirGlobal pMac, cdf_mem_free(pMsg); return CDF_STATUS_E_FAILURE; } - cdf_mem_copy(&pMsg->bssId[0], + cdf_mem_copy(&pMsg->bssid.bytes[0], &pSession->assocInfo.pBssDesc->bssId[0], sizeof(struct cdf_mac_addr)); CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_HIGH, -- cgit v1.2.3 From e3b61cc4b7deaf73a148997cf68ede41db533d6a Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 4 Dec 2015 11:00:49 -0800 Subject: qcacld-3.0: Remove obsolete struct sAniGetStatsReq Remove obsolete struct sAniGetStatsReq. Change-Id: I8478e8d94f00b63ff2926ec4ea4e3dd7f271de13 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index cf32b59141cf..b505277d5ad6 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1584,24 +1584,6 @@ typedef struct sAniRxCtrs { uint32_t aesDecryptErrUcast; } tAniRxCtrs, *tpAniRxCtrs; -/* 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 */ - uint16_t msgType; /* message type is same as the request type */ - uint16_t msgLen; /* length of the entire request */ - uint8_t sessionId; /* Session ID */ - uint16_t transactionId; - tSirMacAddr bssId; /* BSSID */ - /* only used for clear stats and per sta stats clear */ - tAniStatSubTypes stat; /* Clears the stats of the described types. */ - uint32_t staId; /* Per STA stats request must contain valid */ - /* values */ - tSirMacAddr macAddr; -} tAniGetStatsReq, *tpAniGetStatsReq; - /* *************************************************************** */ /*******************PE Statistics*************************/ -- cgit v1.2.3 From fbdb24390872ec1456ff04351664d3819ede3f2d Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 4 Dec 2015 13:43:16 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirSmeSetContext Req/Rsp Replace tSirMacAddr with cdf_mac_addr in struct sSirSmeSetContext Req/Rsp. Change-Id: If4f75c162dbb4156d462a927033f94b9170a518f CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +-- core/mac/src/pe/lim/lim_ft.c | 6 +-- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 25 ++++++----- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 14 +++---- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 13 +++--- core/mac/src/pe/lim/lim_security_utils.c | 15 +++---- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 9 +--- core/mac/src/pe/lim/lim_send_sme_rsp_messages.h | 2 +- core/mac/src/pe/lim/lim_types.h | 2 +- core/sme/inc/csr_internal.h | 2 +- core/sme/src/csr/csr_api_roam.c | 48 +++++++++++----------- core/wma/inc/wma_if.h | 4 +- core/wma/src/wma_dev_if.c | 2 +- core/wma/src/wma_mgmt.c | 14 ++++--- 14 files changed, 77 insertions(+), 85 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b505277d5ad6..8ad8c1f61da6 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1467,8 +1467,8 @@ typedef struct sSirSmeSetContextReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr peerMacAddr; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr peer_macaddr; + struct cdf_mac_addr bssid; /* BSSID */ tSirKeyMaterial keyMaterial; } tSirSmeSetContextReq, *tpSirSmeSetContextReq; @@ -1480,7 +1480,7 @@ typedef struct sSirSmeSetContextRsp { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ tSirResultCodes statusCode; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; } tSirSmeSetContextRsp, *tpSirSmeSetContextRsp; /* / Statistic definitions */ diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index c7d7f6ab53a7..09575f762364 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -1635,8 +1635,8 @@ bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) extSetStaKeyParam; cdf_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq)); - cdf_mem_copy(pMlmSetKeysReq->peerMacAddr, pKeyInfo->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMlmSetKeysReq->peer_macaddr.bytes, + pKeyInfo->bssId, CDF_MAC_ADDR_SIZE); pMlmSetKeysReq->sessionId = psessionEntry->peSessionId; pMlmSetKeysReq->smesessionId = psessionEntry->smeSessionId; pMlmSetKeysReq->edType = pKeyInfo->keyMaterial.edType; @@ -1687,7 +1687,7 @@ bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) MAC_ADDR_ARRAY(pKeyInfo->bssId)); ) - sir_copy_mac_addr(pAddBssParams->extSetStaKeyParam.peerMacAddr, + sir_copy_mac_addr(pAddBssParams->extSetStaKeyParam.peer_macaddr.bytes, pKeyInfo->bssId); pAddBssParams->extSetStaKeyParam.sendRsp = false; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index c1761c855218..11561472d032 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -2209,7 +2209,7 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) uint16_t aid; uint16_t sta_idx = 0; uint32_t default_key_id = 0; - tSirMacAddr curr_bssid; + struct cdf_mac_addr curr_bssid; tpDphHashNode sta_ds; tLimMlmSetKeysReq *mlm_set_keys_req; tLimMlmSetKeysCnf mlm_set_keys_cnf; @@ -2236,8 +2236,8 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "), mlm_set_keys_req->aid, mlm_set_keys_req->edType, mlm_set_keys_req->numKeys); - lim_print_mac_addr(mac_ctx, mlm_set_keys_req->peerMacAddr, LOGW); - sir_copy_mac_addr(curr_bssid, session->bssId); + lim_print_mac_addr(mac_ctx, mlm_set_keys_req->peer_macaddr.bytes, LOGW); + cdf_mem_copy(curr_bssid.bytes, session->bssId, CDF_MAC_ADDR_SIZE); switch (GET_LIM_SYSTEM_ROLE(session)) { case eLIM_STA_ROLE: @@ -2247,13 +2247,15 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) * check if TDLS is enabled. */ #ifndef FEATURE_WLAN_TDLS - if ((!lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) && - (!cdf_mem_compare(mlm_set_keys_req->peerMacAddr, - curr_bssid, sizeof(tSirMacAddr)))) { + if ((!cdf_is_macaddr_broadcast( + &mlm_set_keys_req->peer_macaddr)) && + (!cdf_is_macaddr_equal(&mlm_set_keys_req->peer_macaddr, + &curr_bssid))) { lim_log(mac_ctx, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID" MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_set_keys_req-> + peer_macaddr.bytes)); /* * Prepare and Send LIM_MLM_SETKEYS_CNF with error code */ @@ -2280,7 +2282,7 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) * mlm_set_keys_req->key.unicast = 0 -> Multicast/broadcast * mlm_set_keys_req->key.unicast - 1 -> Unicast keys are being set */ - if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) { + if (cdf_is_macaddr_broadcast(&mlm_set_keys_req->peer_macaddr)) { lim_log(mac_ctx, LOG1, FL("Trying to set Group Keys...%d "), mlm_set_keys_req->sessionId); /* @@ -2304,7 +2306,7 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) * peer entity for which keys need to be set. */ sta_ds = dph_lookup_hash_entry(mac_ctx, - mlm_set_keys_req->peerMacAddr, &aid, + mlm_set_keys_req->peer_macaddr.bytes, &aid, &session->dph.dphHashTable); if ((sta_ds == NULL) || ((sta_ds->mlmStaContext.mlmState != @@ -2317,7 +2319,8 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) lim_log(mac_ctx, LOG1, FL("Invalid MLM_SETKEYS_REQ, Addr = " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_set_keys_req-> + peer_macaddr.bytes)); /* Prepare and Send LIM_MLM_SETKEYS_CNF */ mlm_set_keys_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; @@ -2352,7 +2355,7 @@ lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) FL("Trying to set keys for STA Index [%d], using default_key_id [%d]"), sta_idx, default_key_id); - if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) { + if (cdf_is_macaddr_broadcast(&mlm_set_keys_req->peer_macaddr)) { session->limPrevMlmState = session->limMlmState; session->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE; MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 4f5c5d6148f2..af40676794fd 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1482,14 +1482,14 @@ void lim_process_mlm_set_keys_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) { sta_ds = dph_lookup_hash_entry(pMac, - pMlmSetKeysCnf->peerMacAddr, + pMlmSetKeysCnf->peer_macaddr.bytes, &aid, &psessionEntry->dph.dphHashTable); if (sta_ds != NULL) sta_ds->is_key_installed = 1; } } lim_send_sme_set_context_rsp(pMac, - pMlmSetKeysCnf->peerMacAddr, + pMlmSetKeysCnf->peer_macaddr, 1, (tSirResultCodes) pMlmSetKeysCnf->resultCode, psessionEntry, psessionEntry->smeSessionId, @@ -3270,9 +3270,8 @@ void lim_process_mlm_set_sta_key_rsp(tpAniSirGlobal mac_ctx, (tpLimMlmSetKeysReq) mac_ctx->lim.gpLimMlmSetKeysReq; /* Prepare and Send LIM_MLM_SETKEYS_CNF */ if (NULL != lpLimMlmSetKeysReq) { - cdf_mem_copy((uint8_t *) &mlm_set_key_cnf.peerMacAddr, - (uint8_t *) lpLimMlmSetKeysReq->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlm_set_key_cnf.peer_macaddr, + &lpLimMlmSetKeysReq->peer_macaddr); /* * Free the buffer cached for the global * mac_ctx->lim.gpLimMlmSetKeysReq @@ -3359,9 +3358,8 @@ void lim_process_mlm_set_bss_key_rsp(tpAniSirGlobal mac_ctx, /* Prepare and Send LIM_MLM_SETKEYS_CNF */ if (NULL != set_key_req) { - cdf_mem_copy((uint8_t *) &set_key_cnf.peerMacAddr, - (uint8_t *) set_key_req->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&set_key_cnf.peer_macaddr, + &set_key_req->peer_macaddr); /* * Free the buffer cached for the * global mac_ctx->lim.gpLimMlmSetKeysReq diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index f1d42dcb5daf..d9858920dc14 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3003,19 +3003,19 @@ __lim_process_sme_set_context_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) "numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), set_context_req->keyMaterial.numKeys); lim_send_sme_set_context_rsp(mac_ctx, - set_context_req->peerMacAddr, 1, + set_context_req->peer_macaddr, 1, eSIR_SME_INVALID_PARAMETERS, NULL, sme_session_id, sme_transaction_id); goto end; } session_entry = pe_find_session_by_bssid(mac_ctx, - set_context_req->bssId, &session_id); + set_context_req->bssid.bytes, &session_id); if (session_entry == NULL) { lim_log(mac_ctx, LOGW, FL("Session does not exist for given BSSID")); lim_send_sme_set_context_rsp(mac_ctx, - set_context_req->peerMacAddr, 1, + set_context_req->peer_macaddr, 1, eSIR_SME_INVALID_PARAMETERS, NULL, sme_session_id, sme_transaction_id); goto end; @@ -3048,9 +3048,8 @@ __lim_process_sme_set_context_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) "no.of keys exceeded max num of default keys limit")); goto end; } - cdf_mem_copy((uint8_t *) &mlm_set_key_req->peerMacAddr, - (uint8_t *) &set_context_req->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlm_set_key_req->peer_macaddr, + &set_context_req->peer_macaddr); cdf_mem_copy((uint8_t *) &mlm_set_key_req->key, (uint8_t *) &set_context_req->keyMaterial.key, @@ -3098,7 +3097,7 @@ __lim_process_sme_set_context_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState); lim_send_sme_set_context_rsp(mac_ctx, - set_context_req->peerMacAddr, 1, + set_context_req->peer_macaddr, 1, eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, session_entry, sme_session_id, sme_transaction_id); diff --git a/core/mac/src/pe/lim/lim_security_utils.c b/core/mac/src/pe/lim/lim_security_utils.c index ae0a42224d06..40d51323688b 100644 --- a/core/mac/src/pe/lim/lim_security_utils.c +++ b/core/mac/src/pe/lim/lim_security_utils.c @@ -775,15 +775,10 @@ void lim_post_sme_set_keys_cnf(tpAniSirGlobal pMac, tLimMlmSetKeysCnf *mlmSetKeysCnf) { /* Prepare and Send LIM_MLM_SETKEYS_CNF */ - cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr, - (uint8_t *) pMlmSetKeysReq->peerMacAddr, - sizeof(tSirMacAddr)); - - cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr, - (uint8_t *) pMlmSetKeysReq->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlmSetKeysCnf->peer_macaddr, + &pMlmSetKeysReq->peer_macaddr); - /* / Free up buffer allocated for mlmSetKeysReq */ + /* Free up buffer allocated for mlmSetKeysReq */ cdf_mem_free(pMlmSetKeysReq); pMac->lim.gpLimMlmSetKeysReq = NULL; @@ -969,8 +964,8 @@ void lim_send_set_sta_key_req(tpAniSirGlobal pMac, pSetStaKeyParams->defWEPIdx = defWEPIdx; pSetStaKeyParams->smesessionId = pMlmSetKeysReq->smesessionId; - cdf_mem_copy(pSetStaKeyParams->peerMacAddr, - pMlmSetKeysReq->peerMacAddr, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pSetStaKeyParams->peer_macaddr, + &pMlmSetKeysReq->peer_macaddr); if (sendRsp == true) { /** Store the Previous MlmState*/ diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 1af8bad7d681..1eab1eccb9a1 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1568,13 +1568,11 @@ lim_send_sme_wm_status_change_ntf(tpAniSirGlobal mac_ctx, */ void lim_send_sme_set_context_rsp(tpAniSirGlobal pMac, - tSirMacAddr peerMacAddr, uint16_t aid, + struct cdf_mac_addr peer_macaddr, uint16_t aid, tSirResultCodes resultCode, tpPESession psessionEntry, uint8_t smesessionId, uint16_t smetransactionId) { - - uint8_t *pBuf; tSirMsgQ mmhMsg; tSirSmeSetContextRsp *pSirSmeSetContextRsp; @@ -1592,10 +1590,7 @@ lim_send_sme_set_context_rsp(tpAniSirGlobal pMac, pSirSmeSetContextRsp->length = sizeof(tSirSmeSetContextRsp); pSirSmeSetContextRsp->statusCode = resultCode; - pBuf = pSirSmeSetContextRsp->peerMacAddr; - - cdf_mem_copy(pBuf, (uint8_t *) peerMacAddr, sizeof(tSirMacAddr)); - pBuf += sizeof(tSirMacAddr); + cdf_copy_macaddr(&pSirSmeSetContextRsp->peer_macaddr, &peer_macaddr); /* Update SME session and transaction Id */ pSirSmeSetContextRsp->sessionId = smesessionId; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h index 260b128e9b47..e4ec6ea2a793 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h @@ -67,7 +67,7 @@ void lim_send_sme_deauth_ind(tpAniSirGlobal, tpDphHashNode, tpPESession psessionEntry); void lim_send_sme_wm_status_change_ntf(tpAniSirGlobal, tSirSmeStatusChangeCode, uint32_t *, uint16_t, uint8_t); -void lim_send_sme_set_context_rsp(tpAniSirGlobal, tSirMacAddr, uint16_t, +void lim_send_sme_set_context_rsp(tpAniSirGlobal, struct cdf_mac_addr, uint16_t, tSirResultCodes, tpPESession, uint8_t, uint16_t); void lim_send_sme_neighbor_bss_ind(tpAniSirGlobal, tLimScanResultNode *); void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 55f02fa66f22..d10bcccb88d2 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -371,7 +371,7 @@ typedef struct sLimMlmPurgeStaInd { } tLimMlmPurgeStaInd, *tpLimMlmPurgeStaInd; typedef struct sLimMlmSetKeysCnf { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint16_t resultCode; uint16_t aid; uint8_t sessionId; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index d18fc3d8d994..89abb9d49482 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -409,7 +409,7 @@ typedef struct tagSetKeyCmd { eCsrEncryptionType encType; eCsrAuthType authType; tAniKeyDirection keyDirection; /* Tx, Rx or Tx-and-Rx */ - tSirMacAddr peerMac; /* Peer's MAC address. ALL 1's for group key */ + struct cdf_mac_addr peermac; /* Peer's MAC address. ALL 1's for group key */ uint8_t paeRole; /* 0 for supplicant */ uint8_t keyId; /* Kye index */ uint8_t keyLength; /* Number of bytes containing the key in pKey */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 230ad1b927a5..b9a5e0d94ea9 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -213,7 +213,8 @@ static CDF_STATUS csr_roam_free_connected_info(tpAniSirGlobal pMac, tCsrRoamConnectedInfo * pConnectedInfo); CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, - tSirMacAddr peerMacAddr, uint8_t numKeys, + struct cdf_mac_addr peer_macaddr, + uint8_t numKeys, tAniEdType edType, bool fUnicast, tAniKeyDirection aniKeyDirection, uint8_t keyId, uint8_t keyLength, @@ -9423,8 +9424,8 @@ static CDF_STATUS csr_roam_issue_set_key_command(tpAniSirGlobal pMac, pCommand->u.setKeyCmd.roamId = roamId; pCommand->u.setKeyCmd.encType = pSetKey->encType; pCommand->u.setKeyCmd.keyDirection = pSetKey->keyDirection; - cdf_mem_copy(&pCommand->u.setKeyCmd.peerMac, &pSetKey->peerMac, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&pCommand->u.setKeyCmd.peermac, + &pSetKey->peerMac); /* 0 for supplicant */ pCommand->u.setKeyCmd.paeRole = pSetKey->paeRole; pCommand->u.setKeyCmd.keyId = pSetKey->keyId; @@ -9463,7 +9464,7 @@ CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, tSmeCmd *pComma tAniEdType edType = csr_translate_encrypt_type_to_ed_type(pCommand->u.setKeyCmd.encType); bool fUnicast = - (pCommand->u.setKeyCmd.peerMac[0] == 0xFF) ? false : true; + (pCommand->u.setKeyCmd.peermac.bytes[0] == 0xFF) ? false : true; uint32_t sessionId = pCommand->sessionId; #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); @@ -9478,7 +9479,7 @@ CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, tSmeCmd *pComma if (eSIR_ED_NONE != edType) { cdf_mem_set(&setKeyEvent, sizeof(host_event_wlan_security_payload_type), 0); - if (*((uint8_t *) &pCommand->u.setKeyCmd.peerMac) & 0x01) { + if (cdf_is_macaddr_group(&pCommand->u.setKeyCmd.peermac)) { setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_REQ; setKeyEvent.encryptionModeMulticast = (uint8_t) diag_enc_type_from_csr_type(pCommand->u. @@ -9520,8 +9521,9 @@ CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, tSmeCmd *pComma #endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */ if (csr_is_set_key_allowed(pMac, sessionId)) { status = csr_send_mb_set_context_req_msg(pMac, sessionId, - (uint8_t *) &pCommand->u. - setKeyCmd.peerMac, numKeys, + pCommand->u. + setKeyCmd.peermac, + numKeys, edType, fUnicast, pCommand->u.setKeyCmd. keyDirection, @@ -9546,8 +9548,8 @@ CDF_STATUS csr_roam_process_set_key_command(tpAniSirGlobal pMac, tSmeCmd *pComma eCSR_ROAM_RESULT_FAILURE); #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR if (eSIR_ED_NONE != edType) { - if (*((uint8_t *) &pCommand->u.setKeyCmd.peerMac) & - 0x01) { + if (cdf_is_macaddr_group( + &pCommand->u.setKeyCmd.peermac)) { setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP; } else { @@ -10748,7 +10750,7 @@ csr_roam_diag_set_ctx_rsp(tpAniSirGlobal mac_ctx, return; cdf_mem_set(&setKeyEvent, sizeof(host_event_wlan_security_payload_type), 0); - if (pRsp->peerMacAddr[0] & 0x01) + if (cdf_is_macaddr_group(&pRsp->peer_macaddr)) setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_GTK_RSP; else setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_PTK_RSP; @@ -10781,7 +10783,6 @@ csr_roam_chk_lnk_set_ctx_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) eCsrRoamResult result = eCSR_ROAM_RESULT_NONE; tSirSmeSetContextRsp *pRsp = (tSirSmeSetContextRsp *) msg_ptr; tListElem *entry; - tSirMacAddr Broadcastaddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; cdf_mem_set(&roam_info, sizeof(roam_info), 0); entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, @@ -10818,14 +10819,12 @@ csr_roam_chk_lnk_set_ctx_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) session->connectedProfile.bssid); } if (eSIR_SME_SUCCESS == pRsp->statusCode) { - cdf_mem_copy(&roam_info.peerMac, &pRsp->peerMacAddr, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info.peerMac, &pRsp->peer_macaddr); /* 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 (cdf_mem_compare(&Broadcastaddr, pRsp->peerMacAddr, - sizeof(tSirMacAddr))) { + if (cdf_is_macaddr_broadcast(&pRsp->peer_macaddr)) { tpSirSetActiveModeSetBncFilterReq pMsg; pMsg = cdf_mem_malloc( sizeof(tSirSetActiveModeSetBncFilterReq)); @@ -10841,9 +10840,10 @@ csr_roam_chk_lnk_set_ctx_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) } else { result = eCSR_ROAM_RESULT_FAILURE; sms_log(mac_ctx, LOGE, - FL("CSR: setkey command failed(%d) PeerMac " + FL("CSR: setkey command failed(err=%d) PeerMac " MAC_ADDRESS_STR), - pRsp->statusCode, MAC_ADDR_ARRAY(pRsp->peerMacAddr)); + pRsp->statusCode, + MAC_ADDR_ARRAY(pRsp->peer_macaddr.bytes)); } csr_roam_call_callback(mac_ctx, sessionId, &roam_info, cmd->u.setKeyCmd.roamId, @@ -14445,8 +14445,10 @@ CDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac, return CDF_STATUS_SUCCESS; } -CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, - tSirMacAddr peerMacAddr, uint8_t numKeys, +CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, + uint32_t sessionId, + struct cdf_mac_addr peer_macaddr, + uint8_t numKeys, tAniEdType edType, bool fUnicast, tAniKeyDirection aniKeyDirection, uint8_t keyId, uint8_t keyLength, @@ -14477,11 +14479,9 @@ CDF_STATUS csr_send_mb_set_context_req_msg(tpAniSirGlobal pMac, uint32_t session pMsg->length = msgLen; pMsg->sessionId = (uint8_t) sessionId; pMsg->transactionId = 0; - cdf_mem_copy(pMsg->peerMacAddr, peerMacAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(pMsg->bssId, - pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->peer_macaddr, &peer_macaddr); + cdf_copy_macaddr(&pMsg->bssid, + &pSession->connectedProfile.bssid); /** * Set the pMsg->keyMaterial.length field diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index f5875316f781..3428297832b1 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -373,7 +373,7 @@ typedef struct { tSirKeys key[SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS]; uint8_t singleTidRc; uint8_t smesessionId; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; CDF_STATUS status; uint8_t sessionId; uint8_t sendRsp; @@ -390,7 +390,7 @@ typedef struct { * @key: key data */ typedef struct sLimMlmSetKeysReq { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint8_t sessionId; /* Added For BT-AMP Support */ uint8_t smesessionId; /* Added for drivers based on wmi interface */ uint16_t aid; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 6876ffa240b3..27993c16f62d 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1190,7 +1190,7 @@ CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, peer_addr); cdf_mem_set(&key_info, sizeof(key_info), 0); key_info.smesessionId = vdev_id; - cdf_mem_copy(key_info.peerMacAddr, peer_addr, + cdf_mem_copy(key_info.peer_macaddr.bytes, peer_addr, IEEE80211_ADDR_LEN); key_info.sendRsp = false; diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 84ffc0eb64ac..2373f92a8a13 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1808,7 +1808,7 @@ void wma_adjust_ibss_heart_beat_timer(tp_wma_handle wma, */ static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, tpSetBssKeyParams key_info, - uint8_t *peerMacAddr) + struct cdf_mac_addr peer_macaddr) { struct wma_set_key_params key_params; wmi_buf_t buf; @@ -1818,7 +1818,6 @@ static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, 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__); @@ -1833,7 +1832,8 @@ static void wma_set_ibsskey_helper(tp_wma_handle wma_handle, key_params.unicast = false; ASSERT(wlan_op_mode_ibss == txrx_vdev->opmode); - cdf_mem_copy(key_params.peer_mac, peerMacAddr, IEEE80211_ADDR_LEN); + cdf_mem_copy(key_params.peer_mac, peer_macaddr.bytes, + IEEE80211_ADDR_LEN); if (key_info->numKeys == 0 && (key_info->encType == eSIR_ED_WEP40 || @@ -1913,7 +1913,8 @@ void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) goto out; } - peer = ol_txrx_find_peer_by_addr(txrx_pdev, key_info->peerMacAddr, + peer = ol_txrx_find_peer_by_addr(txrx_pdev, + key_info->peer_macaddr.bytes, &peer_id); if (!peer) { WMA_LOGE("%s:Invalid peer for key setting", __func__); @@ -1954,7 +1955,8 @@ void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) key_params.unicast = true; key_params.def_key_idx = key_info->defWEPIdx; cdf_mem_copy((void *)key_params.peer_mac, - (const void *)key_info->peerMacAddr, IEEE80211_ADDR_LEN); + (const void *)key_info->peer_macaddr.bytes, + IEEE80211_ADDR_LEN); for (i = 0; i < num_keys; i++) { if (key_params.key_type != eSIR_ED_NONE && !key_info->key[i].keyLength) @@ -2004,7 +2006,7 @@ void wma_set_stakey(tp_wma_handle wma_handle, tpSetStaKeyParams key_info) */ if (wlan_op_mode_ibss == txrx_vdev->opmode) { wma_set_ibsskey_helper(wma_handle, &wma_handle->ibsskey_info, - key_info->peerMacAddr); + key_info->peer_macaddr); } /* TODO: Should we wait till we get HTT_T2H_MSG_TYPE_SEC_IND? */ -- cgit v1.2.3 From 033aaebf0508c6b550c4a20b275b776730a15ff9 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Fri, 4 Dec 2015 13:53:58 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in sSirFTUpdateKeyInfo Replace tSirMacAddr with cdf_mac_addr in struct sSirFTUpdateKeyInfo. Change-Id: I427217dfb4f08dde6bef874de6d68ca5281502e0 CRs-Fixed: 898864 --- core/mac/src/pe/include/lim_ft_defs.h | 2 +- core/mac/src/pe/lim/lim_ft.c | 16 ++++++++-------- core/sme/src/common/sme_ft_api.c | 5 ++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core/mac/src/pe/include/lim_ft_defs.h b/core/mac/src/pe/include/lim_ft_defs.h index da4f11f7a27c..34c0ba68570f 100644 --- a/core/mac/src/pe/include/lim_ft_defs.h +++ b/core/mac/src/pe/include/lim_ft_defs.h @@ -89,7 +89,7 @@ typedef struct sSirFTUpdateKeyInfo { uint16_t messageType; uint16_t length; uint32_t smeSessionId; - tSirMacAddr bssId; + struct cdf_mac_addr bssid; tSirKeyMaterial keyMaterial; } tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo; diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index 09575f762364..ffab46808c22 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -1608,13 +1608,14 @@ bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pKeyInfo = (tSirFTUpdateKeyInfo *) pMsgBuf; - psessionEntry = pe_find_session_by_bssid(pMac, pKeyInfo->bssId, &sessionId); + psessionEntry = pe_find_session_by_bssid(pMac, pKeyInfo->bssid.bytes, + &sessionId); if (NULL == psessionEntry) { PELOGE(lim_log(pMac, LOGE, "%s: Unable to find session for the following bssid", __func__); ) - lim_print_mac_addr(pMac, pKeyInfo->bssId, LOGE); + lim_print_mac_addr(pMac, pKeyInfo->bssid.bytes, LOGE); return false; } @@ -1635,8 +1636,8 @@ bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) extSetStaKeyParam; cdf_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq)); - cdf_mem_copy(pMlmSetKeysReq->peer_macaddr.bytes, - pKeyInfo->bssId, CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMlmSetKeysReq->peer_macaddr, + &pKeyInfo->bssid); pMlmSetKeysReq->sessionId = psessionEntry->peSessionId; pMlmSetKeysReq->smesessionId = psessionEntry->smeSessionId; pMlmSetKeysReq->edType = pKeyInfo->keyMaterial.edType; @@ -1684,11 +1685,10 @@ bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf) PELOG1(lim_log(pMac, LOG1, FL("BSSID = " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pKeyInfo->bssId)); - ) + MAC_ADDR_ARRAY(pKeyInfo->bssid.bytes));) - sir_copy_mac_addr(pAddBssParams->extSetStaKeyParam.peer_macaddr.bytes, - pKeyInfo->bssId); + cdf_copy_macaddr(&pAddBssParams->extSetStaKeyParam.peer_macaddr, + &pKeyInfo->bssid); pAddBssParams->extSetStaKeyParam.sendRsp = false; diff --git a/core/sme/src/common/sme_ft_api.c b/core/sme/src/common/sme_ft_api.c index 8f141861a33c..ee6e374c4dd7 100644 --- a/core/sme/src/common/sme_ft_api.c +++ b/core/sme/src/common/sme_ft_api.c @@ -351,11 +351,10 @@ CDF_STATUS sme_ft_send_update_key_ind(tHalHandle hal, uint32_t session_id, } } - cdf_mem_copy(&msg->bssId[0], - &ftkey_info->peerMac.bytes[0], CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&msg->bssid, &ftkey_info->peerMac); msg->smeSessionId = session_id; sms_log(mac_ctx, LOG1, "BSSID = " MAC_ADDRESS_STR, - MAC_ADDR_ARRAY(msg->bssId)); + MAC_ADDR_ARRAY(msg->bssid.bytes)); status = cds_send_mb_message_to_mac(msg); return status; -- cgit v1.2.3 From 3bd1aff8fb76a22832679c1214448195705f2077 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 23 Dec 2015 15:40:13 -0800 Subject: Release 5.0.0.153 Release 5.0.0.153 Change-Id: I30b27c1d77de35cacb94e0b1ac3f384e87dd7ece CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 3ee60f0324b9..1dc8a2a9308e 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 152 +#define QWLAN_VERSION_BUILD 153 -#define QWLAN_VERSIONSTR "5.0.0.152" +#define QWLAN_VERSIONSTR "5.0.0.153" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 96c736af6d225e509870c9086f5790de808ccc89 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:14:00 +0530 Subject: qcacld-3.0: Abort preauth if disconnect is received for the current AP qcacld-2.0 to qcacld-3.0 propagation If preauth is in progress with too many APs in the roamable AP list and at the same time disconnect is received from supplicant as part of unload, the deauth req will be queued in sme pending list till csr completes the preauth process. Now as part of unload, driver may purge the sme pending command list and with it the disconnect command may also get removed if preauth takes too much time. This will lead to DEL BSS missing before HAL STOP and thus crash. To avoid this abort the preauth process once disconnect is received. Change-Id: I1c35f0c7e38295cfadafdad69f0b9a99ba61404c CRs-Fixed: 942579 --- core/sme/src/csr/csr_api_roam.c | 2 +- core/sme/src/csr/csr_inside_api.h | 2 ++ core/sme/src/csr/csr_neighbor_roam.c | 9 ++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b9a5e0d94ea9..6d65e8136297 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -7955,7 +7955,7 @@ CDF_STATUS csr_roam_save_connected_infomation(tpAniSirGlobal pMac, } -static bool is_disconnect_pending(tpAniSirGlobal pmac, +bool is_disconnect_pending(tpAniSirGlobal pmac, uint8_t sessionid) { tListElem *entry = NULL; diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 88c284ba7f24..3a7b54c8f974 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1065,6 +1065,8 @@ csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle, tSirBssDescription *bss_descr); void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand, eCsrScanStatus scanStatus); +bool is_disconnect_pending(tpAniSirGlobal mac_ctx, + uint8_t sessionid); void csr_scan_active_list_timeout_handle(void *userData); CDF_STATUS csr_prepare_disconnect_command(tpAniSirGlobal mac, uint32_t session_id, tSmeCmd **sme_cmd); diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 195c82a8db38..a66bfaadf971 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -1039,6 +1039,7 @@ CDF_STATUS csr_neighbor_roam_preauth_rsp_handler(tpAniSirGlobal mac_ctx, } else { tpCsrNeighborRoamBSSInfo neighbor_bss_node = NULL; tListElem *entry; + bool is_dis_pending = false; sms_log(mac_ctx, LOGE, FL("Preauth failed retry number %d, status = 0x%x"), @@ -1092,11 +1093,17 @@ CDF_STATUS csr_neighbor_roam_preauth_rsp_handler(tpAniSirGlobal mac_ctx, mac_ctx, neighbor_bss_node); } NEXT_PREAUTH: + is_dis_pending = is_disconnect_pending(mac_ctx, session_id); + if (is_dis_pending) { + sms_log(mac_ctx, LOGE, + FL("Disconnect in progress, Abort preauth")); + goto ABORT_PREAUTH; + } /* Issue preauth request for the same/next entry */ if (CDF_STATUS_SUCCESS == csr_neighbor_roam_issue_preauth_req( mac_ctx, session_id)) goto DEQ_PREAUTH; - +ABORT_PREAUTH: if (csr_roam_is_roam_offload_scan_enabled(mac_ctx)) { if (neighbor_roam_info->uOsRequestedHandoff) { neighbor_roam_info->uOsRequestedHandoff = 0; -- cgit v1.2.3 From e2a14d2f251668db4edd0066a3a16fb7e1c495b3 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 3 Dec 2015 16:06:59 +0530 Subject: qcacld-3.0: Add extended rates in Assoc req if AP has it qcacld-2.0 to qcacld-3.0 propagation Extended Supported Rates are filled in Assoc req based on the dot11mode and in Case dot11mode is 11A it's not filled. Some AP have Basic rate in Extended Rate set in 11A mode. Thus AP reject the association as Driver does not sent the extended rate set in 11A mode. Removed the dot11mode dependency for Extended Supported Rates. With this change if AP have Extended Supported Rates driver will add the Extended Supported Rates IE in Assoc req. Change-Id: Ibd1c98a7cfae46988ff4434579edde7d4222841d CRs-Fixed: 903270 --- core/sme/src/csr/csr_api_roam.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 6d65e8136297..eb325093529b 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3841,18 +3841,12 @@ static CDF_STATUS csr_get_rate_set(tpAniSirGlobal pMac, } } } - 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 - ) && pIes->ExtSuppRates.present) { - /* - * If there are extended rates in the beacon, - * we will reflect those extended rates that we support in our - * extended operational rate - */ + /* + * If there are Extended Rates in the beacon, we will reflect the + * extended rates that we support in our Extended Operational Rate + * set. + */ + if (pIes->ExtSuppRates.present) { pDstRate = pExRateSet->rate; for (i = 0; i < pIes->ExtSuppRates.num_rates; i++) { if (csr_rates_is_dot11_rate_supported(pMac, -- cgit v1.2.3 From 85d9c2e097002dbdcd349c3e3cfc3f5d18133eeb Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Fri, 11 Dec 2015 10:22:00 +0530 Subject: qcacld 3.0: Fix return type of few "cdf_atomic" APIs Propagation from qcacld 2.0 to qcacld 3.0 The atomic variables are of integer type but "cdf_atomic_read", "cdf_atomic_dec_and_test" and "cdf_atomic_inc_return" APIs have return type of unsigned int. Because of this, these APIs return positive value even when it is negative. This fix change the return value of "cdf_atomic_read", "cdf_atomic_dec_and_test" and "cdf_atomic_inc_return" APIs from unsigned int to int so that negative value remains negative. Change-Id: I9c4077547e1e1370bbb401af77b248944cdf25fa CRs-Fixed: 902636 --- core/cdf/inc/cdf_atomic.h | 6 +++--- core/cdf/src/i_cdf_atomic.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/cdf/inc/cdf_atomic.h b/core/cdf/inc/cdf_atomic.h index a30d52bccae7..4ae5dc5b9ab7 100644 --- a/core/cdf/inc/cdf_atomic.h +++ b/core/cdf/inc/cdf_atomic.h @@ -62,7 +62,7 @@ static inline void cdf_atomic_init(cdf_atomic_t *v) * * Return: The current value of the variable */ -static inline uint32_t cdf_atomic_read(cdf_atomic_t *v) +static inline int32_t cdf_atomic_read(cdf_atomic_t *v) { return __cdf_atomic_read(v); } @@ -122,7 +122,7 @@ static inline void cdf_atomic_sub(int i, cdf_atomic_t *v) * true (non-zero) if the new value is zero, * or false (0) if the new value is non-zero */ -static inline uint32_t cdf_atomic_dec_and_test(cdf_atomic_t *v) +static inline int32_t cdf_atomic_dec_and_test(cdf_atomic_t *v) { return __cdf_atomic_dec_and_test(v); } @@ -144,7 +144,7 @@ static inline void cdf_atomic_set(cdf_atomic_t *v, int i) * * Return: The current value of the variable */ -static inline uint32_t cdf_atomic_inc_return(cdf_atomic_t *v) +static inline int32_t cdf_atomic_inc_return(cdf_atomic_t *v) { return __cdf_atomic_inc_return(v); } diff --git a/core/cdf/src/i_cdf_atomic.h b/core/cdf/src/i_cdf_atomic.h index 7c08eb982a78..178c3275b490 100644 --- a/core/cdf/src/i_cdf_atomic.h +++ b/core/cdf/src/i_cdf_atomic.h @@ -40,7 +40,7 @@ static inline CDF_STATUS __cdf_atomic_init(__cdf_atomic_t *v) return CDF_STATUS_SUCCESS; } -static inline uint32_t __cdf_atomic_read(__cdf_atomic_t *v) +static inline int32_t __cdf_atomic_read(__cdf_atomic_t *v) { return atomic_read(v); } @@ -72,7 +72,7 @@ static inline void __cdf_atomic_sub(int i, __cdf_atomic_t *v) atomic_sub(i, v); } -static inline uint32_t __cdf_atomic_dec_and_test(__cdf_atomic_t *v) +static inline int32_t __cdf_atomic_dec_and_test(__cdf_atomic_t *v) { return atomic_dec_and_test(v); } @@ -82,7 +82,7 @@ static inline void __cdf_atomic_set(__cdf_atomic_t *v, int i) atomic_set(v, i); } -static inline uint32_t __cdf_atomic_inc_return(__cdf_atomic_t *v) +static inline int32_t __cdf_atomic_inc_return(__cdf_atomic_t *v) { return atomic_inc_return(v); } -- cgit v1.2.3 From 15df0cf75edd970bd0b399a1354a69fc8aaa0f0f Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Fri, 11 Dec 2015 10:35:10 +0530 Subject: qcacld-3.0: Avoid double free of vdev Propagation from qcacld 2.0 to qcacld 3.0 Due to a race condition, vdev is getting deleted in ol_txrx_vdev_detach and after that in ol_txrx_peer_unref_delete, as vdev->delete.pending is not equal to 0 as it is some garbage value, vdev is getting deleted again causing crash. This fix release the lock after checking vdev->delete.pending so that before vdev gets deleted in ol_txrx_vdev_detach, this check has been made and as vdev->delete.pending is 0, it will not delete the vdev in ol_txrx_peer_unref_delete and so vdev will be deleted only once. Change-Id: I4a7362b0e226c66ccb7c72243276d77e8df60b20 CRs-Fixed: 949397 --- core/dp/txrx/ol_txrx.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index fa9f7d8fd369..df24d693c900 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1642,11 +1642,6 @@ void ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) /* check whether the parent vdev has no peers left */ if (TAILQ_EMPTY(&vdev->peer_list)) { - /* - * Now that there are no references to the peer, we can - * release the peer reference lock. - */ - cdf_spin_unlock_bh(&pdev->peer_ref_mutex); /* * Check if the parent vdev was waiting for its peers * to be deleted, in order for it to be deleted too. @@ -1657,6 +1652,12 @@ void ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) void *vdev_delete_context = vdev->delete.context; + /* + * Now that there are no references to the peer, + * we can release the peer reference lock. + */ + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s: deleting vdev object %p " "(%02x:%02x:%02x:%02x:%02x:%02x)" @@ -1672,9 +1673,12 @@ void ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) cdf_mem_free(vdev); if (vdev_delete_cb) vdev_delete_cb(vdev_delete_context); + } else { + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); } - } else + } else { cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + } /* * 'array' is allocated in addba handler and is supposed to be -- cgit v1.2.3 From 5dabfc7759cebb6ddc7f6e11f7738d336de2ee45 Mon Sep 17 00:00:00 2001 From: DARAM SUDHA Date: Sat, 16 May 2015 08:11:57 +0530 Subject: qcacld-3.0: Fix datapath defects detected by Static code analyser qcacld-2.0 to qcacld-3.0 propagation Line 118: CID 50610 (#3 of 3): Out-of-bounds access (OVERRUN) Line 200: CID 50680 (#1 of 1): Out-of-bounds read (OVERRUN) Line 367: CID 50732 (#1 of 1): Out-of-bounds write (OVERRUN) add TID validation check in RX_IND to avoid tid >19 scenario. Change-Id: I32a3339902e231a8193fb8ee984ef029e24bc7e5 CRs-Fixed: 836067 --- core/dp/htt/htt_t2h.c | 5 +++++ core/dp/htt/htt_tx.c | 3 +-- core/dp/txrx/ol_cfg.c | 18 +++++++++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 3ef8cdd8c6f7..b4de1723a8f5 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -475,6 +475,11 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) 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) { + cdf_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)); diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index 96135a48ad44..f733fc64bc9f 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -252,8 +252,6 @@ static inline void htt_tx_desc_get_size(struct htt_pdev_t *pdev) + (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev) + 1) * 8 /* 2x uint32_t */ + 4; /* uint32_t fragmentation list terminator */ - if (pdev->tx_descs.size < sizeof(uint32_t *)) - pdev->tx_descs.size = sizeof(uint32_t *); } /** @@ -320,6 +318,7 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems) uint16_t num_page, num_desc_per_page; htt_tx_desc_get_size(pdev); + /* * Make sure tx_descs.size is a multiple of 4-bytes. * It should be, but round up just to be sure. diff --git a/core/dp/txrx/ol_cfg.c b/core/dp/txrx/ol_cfg.c index 2e6a8e767fc6..c921e2dddaf9 100644 --- a/core/dp/txrx/ol_cfg.c +++ b/core/dp/txrx/ol_cfg.c @@ -56,6 +56,20 @@ void ol_tx_set_flow_control_parameters(struct txrx_pdev_cfg_t *cfg_ctx, } #endif +#if CFG_TGT_DEFAULT_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK +static inline +uint8_t ol_defrag_timeout_check(void) +{ + return 1; +} +#else +static inline +uint8_t ol_defrag_timeout_check(void) +{ + return 0; +} +#endif + /* FIX THIS - * For now, all these configuration parameters are hardcoded. * Many of these should actually be determined dynamically instead. @@ -79,9 +93,7 @@ ol_pdev_handle ol_pdev_cfg_attach(cdf_device_t osdev, cfg_ctx->tx_download_size = 16; /* 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; -#endif + cfg_ctx->defrag_timeout_check = ol_defrag_timeout_check(); cfg_ctx->max_peer_id = 511; cfg_ctx->max_vdev = CFG_TGT_NUM_VDEV; cfg_ctx->pn_rx_fwd_check = 1; -- cgit v1.2.3 From 0b9e7a92947b3892cf4a0ed8ac75b416a0af417c Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 23 Dec 2015 12:35:12 -0800 Subject: qcacld-3.0: CL 1430888 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Update common WMI commands to merge firmware init of MCL and WIN SWOL update Change-Id: I732a70be17d451654f3fbbe6db84f62de6438862 CRs-fixed: 865207 --- target/inc/wlan_defs.h | 10 +++- target/inc/wmi_services.h | 10 +++- target/inc/wmi_unified.h | 123 ++++++++++++++++++++++++++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/target/inc/wlan_defs.h b/target/inc/wlan_defs.h index e9948d08dadb..8369bfb93930 100644 --- a/target/inc/wlan_defs.h +++ b/target/inc/wlan_defs.h @@ -192,6 +192,9 @@ enum { REGDMN_MODE_11AC_VHT40_2G = 0x000400000, /* 2Ghz, VHT40 */ REGDMN_MODE_11AC_VHT80_2G = 0x000800000, /* 2Ghz, VHT80 */ REGDMN_MODE_11AC_VHT160 = 0x001000000, /* 5Ghz, VHT160 */ + REGDMN_MODE_11AC_VHT40_2GPLUS = 0x002000000, /* 2Ghz, VHT40+ */ + REGDMN_MODE_11AC_VHT40_2GMINUS = 0x004000000, /* 2Ghz, VHT40- */ + REGDMN_MODE_11AC_VHT80_80 = 0x008000000, /* 5GHz, VHT80+80 */ }; #define REGDMN_MODE_ALL (0xFFFFFFFF) /* REGDMN_MODE_ALL is defined out of the enum @@ -408,8 +411,11 @@ typedef struct { A_UINT32 size; } wlan_host_memory_chunk; -#define NUM_UNITS_IS_NUM_VDEVS 0x1 -#define NUM_UNITS_IS_NUM_PEERS 0x2 +#define NUM_UNITS_IS_NUM_VDEVS 0x1 +#define NUM_UNITS_IS_NUM_PEERS 0x2 +#define NUM_UNITS_IS_NUM_ACTIVE_PEERS 0x4 +/* request host to allocate memory contiguously */ +#define REQ_TO_HOST_FOR_CONT_MEMORY 0x8 /** * structure used by FW for requesting host memory diff --git a/target/inc/wmi_services.h b/target/inc/wmi_services.h index 6a447e17212b..898bdaf7d39a 100644 --- a/target/inc/wmi_services.h +++ b/target/inc/wmi_services.h @@ -89,7 +89,7 @@ typedef enum { WMI_SERVICE_BATCH_SCAN, /*Service to support batch scan */ WMI_SERVICE_QPOWER, /* QPower service */ WMI_SERVICE_PLMREQ, - WMI_SERVICE_THERMAL_MGMT, + WMI_SERVICE_THERMAL_MGMT, /* thermal throttling support */ 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 */ @@ -131,6 +131,14 @@ typedef enum { WMI_SERVICE_STA_PMF_OFFLOAD, /* FW supports unified D0 and D3 wow */ WMI_SERVICE_UNIFIED_WOW_CAPABILITY, + WMI_SERVICE_ENHANCED_PROXY_STA, /* Enhanced ProxySTA mode support */ + WMI_SERVICE_ATF, /* Air Time Fairness support */ + WMI_SERVICE_COEX_GPIO, /* BTCOEX GPIO support */ + WMI_SERVICE_AUX_SPECTRAL_INTF, /* Aux Radio enhancement support for ignoring spectral scan intf from main radios */ + WMI_SERVICE_AUX_CHAN_LOAD_INTF, /* Aux Radio enhancement support for ignoring chan load intf from main radios*/ + WMI_SERVICE_BSS_CHANNEL_INFO_64, /* BSS channel info (freq, noise floor, 64-bit counters) event support */ + WMI_SERVICE_ENTERPRISE_MESH, /* Enterprise MESH Service Support */ + WMI_SERVICE_RESTRT_CHNL_SUPPORT, /* Restricted Channel Support */ WMI_MAX_SERVICE = 128 /* max service */ } WMI_SERVICE; diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index b3ef0396240d..59a1d798cf69 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -1990,7 +1990,59 @@ typedef struct { */ #define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_S 0 #define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_M 0x1 + + #define WMI_RSRC_CFG_FLAG_LTEU_SUPPORT_S 1 + #define WMI_RSRC_CFG_FLAG_LTEU_SUPPORT_M 0x2 + + #define WMI_RSRC_CFG_FLAG_COEX_GPIO_SUPPORT_S 2 + #define WMI_RSRC_CFG_FLAG_COEX_GPIO_SUPPORT_M 0x4 + + #define WMI_RSRC_CFG_FLAG_AUX_RADIO_SPECTRAL_INTF_S 3 + #define WMI_RSRC_CFG_FLAG_AUX_RADIO_SPECTRAL_INTF_M 0x8 + + #define WMI_RSRC_CFG_FLAG_AUX_RADIO_CHAN_LOAD_INTF_S 4 + #define WMI_RSRC_CFG_FLAG_AUX_RADIO_CHAN_LOAD_INTF_M 0x10 + + #define WMI_RSRC_CFG_FLAG_BSS_CHANNEL_INFO_64_S 5 + #define WMI_RSRC_CFG_FLAG_BSS_CHANNEL_INFO_64_M 0x20 + + #define WMI_RSRC_CFG_FLAG_ATF_CONFIG_ENABLE_S 6 + #define WMI_RSRC_CFG_FLAG_ATF_CONFIG_ENABLE_M 0x40 + + #define WMI_RSRC_CFG_FLAG_IPHR_PAD_CONFIG_ENABLE_S 7 + #define WMI_RSRC_CFG_FLAG_IPHR_PAD_CONFIG_ENABLE_M 0x80 + + #define WMI_RSRC_CFG_FLAG_QWRAP_MODE_ENABLE_S 8 + #define WMI_RSRC_CFG_FLAG_QWRAP_MODE_ENABLE_M 0x100 + A_UINT32 flag1; + + /** @brief smart_ant_cap - Smart Antenna capabilities information + * @details + * 1 - Smart antenna is enabled. + * 0 - Smart antenna is disabled. + * In future this can contain smart antenna specifc capabilities. + */ + A_UINT32 smart_ant_cap; + + /** + * User can configure the buffers allocated for each AC (BE, BK, VI, VO) + * during init + */ + A_UINT32 BK_Minfree; + A_UINT32 BE_Minfree; + A_UINT32 VI_Minfree; + A_UINT32 VO_Minfree; + + /** + * @brief alloc_frag_desc_for_data_pkt . Controls data packet fragment + * descriptor memory allocation. + * 1 - Allocate fragment descriptor memory for data packet in firmware. + * If host wants to transmit data packet at its desired rate, + * this field must be set. + * 0 - Don't allocate fragment descriptor for data packet. + */ + A_UINT32 alloc_frag_desc_for_data_pkt; } wmi_resource_config; #define WMI_RSRC_CFG_FLAG_SET(word32, flag, value) \ @@ -2008,6 +2060,46 @@ typedef struct { #define WMI_RSRC_CFG_FLAG_WOW_IGN_PCIE_RST_GET(word32) \ WMI_RSRC_CFG_FLAG_GET((word32), WOW_IGN_PCIE_RST) +#define WMI_RSRC_CFG_FLAG_LTEU_SUPPORT_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), LTEU_SUPPORT, (value)) +#define WMI_RSRC_CFG_FLAG_LTEU_SUPPORT_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), LTEU_SUPPORT) + +#define WMI_RSRC_CFG_FLAG_COEX_GPIO_SUPPORT_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), COEX_GPIO_SUPPORT, (value)) +#define WMI_RSRC_CFG_FLAG_COEX_GPIO_SUPPORT_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), COEX_GPIO_SUPPORT) + +#define WMI_RSRC_CFG_FLAG_AUX_RADIO_SPECTRAL_INTF_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), AUX_RADIO_SPECTRAL_INTF, (value)) +#define WMI_RSRC_CFG_FLAG_AUX_RADIO_SPECTRAL_INTF_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), AUX_RADIO_SPECTRAL_INTF) + +#define WMI_RSRC_CFG_FLAG_AUX_RADIO_CHAN_LOAD_INTF_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), AUX_RADIO_CHAN_LOAD_INTF, (value)) +#define WMI_RSRC_CFG_FLAG_AUX_RADIO_CHAN_LOAD_INTF_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), AUX_RADIO_CHAN_LOAD_INTF) + +#define WMI_RSRC_CFG_FLAG_BSS_CHANNEL_INFO_64_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), BSS_CHANNEL_INFO_64, (value)) +#define WMI_RSRC_CFG_FLAG_BSS_CHANNEL_INFO_64_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), BSS_CHANNEL_INFO_64) + +#define WMI_RSRC_CFG_FLAG_ATF_CONFIG_ENABLE_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), ATF_CONFIG_ENABLE, (value)) +#define WMI_RSRC_CFG_FLAG_ATF_CONFIG_ENABLE_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), ATF_CONFIG_ENABLE) + +#define WMI_RSRC_CFG_FLAG_IPHR_PAD_CONFIG_ENABLE_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), IPHR_PAD_CONFIG_ENABLE, (value)) +#define WMI_RSRC_CFG_FLAG_IPHR_PAD_CONFIG_ENABLE_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), IPHR_PAD_CONFIG_ENABLE) + +#define WMI_RSRC_CFG_FLAG_QWRAP_MODE_ENABLE_SET(word32, value) \ + WMI_RSRC_CFG_FLAG_SET((word32), QWRAP_MODE_ENABLE, (value)) +#define WMI_RSRC_CFG_FLAG_QWRAP_MODE_ENABLE_GET(word32) \ + WMI_RSRC_CFG_FLAG_GET((word32), QWRAP_MODE_ENABLE) + typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_init_cmd_fixed_param */ @@ -7206,6 +7298,7 @@ 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_TYPE_APP_PULSETEST, EXTWOW_DISABLED = 255, } EXTWOW_TYPE; @@ -7214,8 +7307,13 @@ typedef struct { A_UINT32 vdev_id; A_UINT32 type; A_UINT32 wakeup_pin_num; + A_UINT32 swol_pulsetest_type; + A_UINT32 swol_pulsetest_application; } wmi_extwow_enable_cmd_fixed_param; +#define SWOL_INDOOR_MAC_ADDRESS_INDEX_MAX 8 +#define SWOL_INDOOR_KEY_LEN 16 + 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; @@ -7224,6 +7322,31 @@ typedef struct { A_UINT8 passwd[16]; A_UINT32 ident_len; A_UINT32 passwd_len; + + /* indoor check parameters */ + /* key for mac addresses specified in swol_indoor_key_mac + * Big-endian hosts need to byte-swap the bytes within each 4-byte + * segment of this array, so the bytes will return to their original + * order when the entire WMI message contents are byte-swapped to + * convert from big-endian to little-endian format. + */ + A_UINT8 swol_indoor_key[SWOL_INDOOR_MAC_ADDRESS_INDEX_MAX][SWOL_INDOOR_KEY_LEN]; + /* key length for specified mac address index + * Big-endian hosts need to byte-swap the bytes within each 4-byte + * segment of this array, so the bytes will return to their original + * order when the entire WMI message contents are byte-swapped to + * convert from big-endian to little-endian format. + */ + A_UINT8 swol_indoor_key_len[SWOL_INDOOR_MAC_ADDRESS_INDEX_MAX]; + /* mac address array allowed to wakeup host*/ + wmi_mac_addr swol_indoor_key_mac[SWOL_INDOOR_MAC_ADDRESS_INDEX_MAX]; + /* app mask for the mac addresses specified in swol_indoor_key_mac */ + A_UINT32 swol_indoor_app_mask[SWOL_INDOOR_MAC_ADDRESS_INDEX_MAX]; + A_UINT32 swol_indoor_waker_check; /* whether to do indoor waker check */ + A_UINT32 swol_indoor_pw_check; /* whether to check password */ + A_UINT32 swol_indoor_pattern; /* wakeup pattern */ + A_UINT32 swol_indoor_exception; /* wakeup when exception happens */ + A_UINT32 swol_indoor_exception_app; } wmi_extwow_set_app_type1_params_cmd_fixed_param; typedef struct { diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 68f1b40a3b64..f063ff5a1ffa 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 187 +#define __WMI_REVISION_ 189 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 032eb4869ca070293341312a60ea88f2e4585e31 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 23 Dec 2015 13:53:34 -0800 Subject: qcacld-3.0: CL 1431762 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Update to add WMI interface for Berkeley packet filter feature. Change-Id: Ib531691c227a4b9e4c4087f6eaf08796677c93c1 CRs-fixed: 865207 --- core/wmi/wmi_unified.c | 5 ++++ target/inc/wmi_services.h | 1 + target/inc/wmi_tlv_defs.h | 47 ++++++++++++++++++++++++++++++++++++-- target/inc/wmi_unified.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 5 files changed, 110 insertions(+), 3 deletions(-) diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index d1980c73f567..5048b457ae98 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -743,6 +743,11 @@ static uint8_t *get_wmi_cmd_string(WMI_CMD_ID wmi_command) 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); + CASE_RETURN_STRING(WMI_BPF_GET_CAPABILITY_CMDID); + CASE_RETURN_STRING(WMI_BPF_GET_VDEV_STATS_CMDID); + CASE_RETURN_STRING(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID); + CASE_RETURN_STRING(WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID); + } return "Invalid WMI cmd"; } diff --git a/target/inc/wmi_services.h b/target/inc/wmi_services.h index 898bdaf7d39a..c654dffcf93f 100644 --- a/target/inc/wmi_services.h +++ b/target/inc/wmi_services.h @@ -139,6 +139,7 @@ typedef enum { WMI_SERVICE_BSS_CHANNEL_INFO_64, /* BSS channel info (freq, noise floor, 64-bit counters) event support */ WMI_SERVICE_ENTERPRISE_MESH, /* Enterprise MESH Service Support */ WMI_SERVICE_RESTRT_CHNL_SUPPORT, /* Restricted Channel Support */ + WMI_SERVICE_BPF_OFFLOAD, /* FW supports bpf offload */ WMI_MAX_SERVICE = 128 /* max service */ } WMI_SERVICE; diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 3172cc0eb96c..dcda8409f33f 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -605,6 +605,12 @@ typedef enum { 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_STRUC_wmi_bpf_get_capability_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_bpf_capability_info_evt_fixed_param, + WMITLV_TAG_STRUC_wmi_bpf_get_vdev_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_bpf_vdev_stats_info_evt_fixed_param, + WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_bpf_del_vdev_instructions_cmd_fixed_param, } WMITLV_TAG_ID; /* @@ -844,7 +850,12 @@ typedef enum { 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) + OP(WMI_OEM_REQUEST_CMDID) \ + OP(WMI_BPF_GET_CAPABILITY_CMDID) \ + OP(WMI_BPF_GET_VDEV_STATS_CMDID) \ + OP(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID) \ + OP(WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID) + /* * IMPORTANT: Please add _ALL_ WMI Events Here. * Otherwise, these WMI TLV Functions will be process them. @@ -963,7 +974,9 @@ typedef enum { 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) + OP(WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID) \ + OP(WMI_BPF_CAPABILIY_INFO_EVENTID) \ + OP(WMI_BPF_VDEV_STATS_INFO_EVENTID) /* TLV definitions of WMI commands */ @@ -2227,6 +2240,26 @@ WMITLV_CREATE_PARAM_STRUC(WMI_NLO_CONFIGURE_MAWC_CMDID); 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); +/* bpf offload capability get cmd */ +#define WMITLV_TABLE_WMI_BPF_GET_CAPABILITY_CMDID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param, wmi_bpf_get_capability_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_GET_CAPABILITY_CMDID); + +/* bpf offload get vdev status cmd */ +#define WMITLV_TABLE_WMI_BPF_GET_VDEV_STATS_CMDID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_get_vdev_stats_cmd_fixed_param, wmi_bpf_get_vdev_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_GET_VDEV_STATS_CMDID); + +/* bpf offload set vdev instructions cmd */ +#define WMITLV_TABLE_WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, wmi_bpf_set_vdev_instructions_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID); + +/* bpf offload delete vdev instructions cmd */ +#define WMITLV_TABLE_WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_del_vdev_instructions_cmd_fixed_param, wmi_bpf_del_vdev_instructions_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_DEL_VDEV_INSTRUCTIONS_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) @@ -3030,6 +3063,16 @@ WMITLV_CREATE_PARAM_STRUC(WMI_MAWC_ENABLE_SENSOR_EVENTID); 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); +/* bpf offload capability info event */ +#define WMITLV_TABLE_WMI_BPF_CAPABILIY_INFO_EVENTID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_capability_info_evt_fixed_param, wmi_bpf_capability_info_evt_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_CAPABILIY_INFO_EVENTID); + +/* bpf offload vdev status info event */ +#define WMITLV_TABLE_WMI_BPF_VDEV_STATS_INFO_EVENTID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_vdev_stats_info_evt_fixed_param, wmi_bpf_vdev_stats_info_evt_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_BPF_VDEV_STATS_INFO_EVENTID); + #ifdef __cplusplus } #endif diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 59a1d798cf69..80fdf0538b52 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -231,6 +231,7 @@ typedef enum { WMI_GRP_PKT_FILTER, WMI_GRP_MAWC, WMI_GRP_PMF_OFFLOAD, + WMI_GRP_BPF_OFFLOAD, /* Berkeley Packet Filter */ } WMI_GRP_ID; #define WMI_CMD_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) @@ -869,6 +870,11 @@ typedef enum { WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_PMF_OFFLOAD), + /** WMI commands related to pkt filter (BPF) offload */ + WMI_BPF_GET_CAPABILITY_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_BPF_OFFLOAD), + WMI_BPF_GET_VDEV_STATS_CMDID, + WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID, + WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID, } WMI_CMD_ID; typedef enum { @@ -1201,6 +1207,10 @@ typedef enum { /** Motion Aided WiFi Connectivity (MAWC) events */ WMI_MAWC_ENABLE_SENSOR_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MAWC), + /** pkt filter (BPF) offload relevant events */ + WMI_BPF_CAPABILIY_INFO_EVENTID = + WMI_EVT_GRP_START_ID(WMI_GRP_BPF_OFFLOAD), + WMI_BPF_VDEV_STATS_INFO_EVENTID, } WMI_EVT_ID; /* defines for OEM message sub-types */ @@ -6968,6 +6978,7 @@ typedef enum wake_reason_e { WOW_REASON_REASSOC_REQ_RECV, WOW_REASON_REASSOC_RES_RECV, WOW_REASON_ACTION_FRAME_RECV, + WOW_REASON_BPF_ALLOW, WOW_REASON_DEBUG_TEST = 0xFF, } WOW_WAKE_REASON_TYPE; @@ -12519,6 +12530,53 @@ typedef struct { */ } wmi_scpc_event_fixed_param; +/* bpf interface structure */ +typedef struct wmi_bpf_get_capability_cmd_s { + A_UINT32 tlv_header; + A_UINT32 reserved; /* reserved for future use - must be filled with 0x0 */ +} wmi_bpf_get_capability_cmd_fixed_param; + +typedef struct wmi_bpf_capability_info_evt_s { + A_UINT32 tlv_header; + A_UINT32 bpf_version; /* fw's implement version */ + A_UINT32 max_bpf_filters; /* max filters that fw supports */ + A_UINT32 max_bytes_for_bpf_inst; /* the maximum bytes that can be used as bpf instructions */ +} wmi_bpf_capability_info_evt_fixed_param; + +/* bit 0 of flags: report counters */ +#define WMI_BPF_GET_VDEV_STATS_FLAG_CTR_S 0 +#define WMI_BPF_GET_VDEV_STATS_FLAG_CTR_M 0x1 +typedef struct wmi_bpf_get_vdev_stats_cmd_s { + A_UINT32 tlv_header; + A_UINT32 flags; + A_UINT32 vdev_id; +} wmi_bpf_get_vdev_stats_cmd_fixed_param; + +typedef struct wmi_bpf_vdev_stats_info_evt_s { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 num_filters; + A_UINT32 num_checked_pkts; + A_UINT32 num_dropped_pkts; + } wmi_bpf_vdev_stats_info_evt_fixed_param; + +typedef struct wmi_bpf_set_vdev_instructions_cmd_s { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 filter_id; + A_UINT32 bpf_version; /* host bpf version */ + A_UINT32 total_length; + A_UINT32 current_offset; + A_UINT32 current_length; +} wmi_bpf_set_vdev_instructions_cmd_fixed_param; + +#define BPF_FILTER_ID_ALL 0xFFFFFFFF +typedef struct wmi_bpf_del_vdev_instructions_cmd_s { + A_UINT32 tlv_header; + A_UINT32 vdev_id; + A_UINT32 filter_id; /* BPF_FILTER_ID_ALL means delete all */ +} wmi_bpf_del_vdev_instructions_cmd_fixed_param; + /* ADD NEW DEFS HERE */ /***************************************************************************** diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index f063ff5a1ffa..c36a6d2e16c9 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 189 +#define __WMI_REVISION_ 190 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 0aac2f1594d534215579ca227cba7f9f7fdc43f2 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 23 Dec 2015 14:18:36 -0800 Subject: qcacld-3.0: CL 1432708 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Update SET BPF Instructions WMI TLV with missing item. Change-Id: I691f55bb27a66e9833e87bd4c6221c505eba6454 CRs-fixed: 865207 --- target/inc/wmi_tlv_defs.h | 3 ++- target/inc/wmi_unified.h | 8 ++++++-- target/inc/wmi_version.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index dcda8409f33f..533476121de8 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -2252,7 +2252,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_BPF_GET_VDEV_STATS_CMDID); /* bpf offload set vdev instructions cmd */ #define WMITLV_TABLE_WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID(id, op, buf, len) \ - WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, wmi_bpf_set_vdev_instructions_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, wmi_bpf_set_vdev_instructions_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, buf_inst, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID); /* bpf offload delete vdev instructions cmd */ diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 80fdf0538b52..007fd5ddfcdd 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -782,8 +782,8 @@ typedef enum { /*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, + WMI_OEM_REQ_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_OEM), + WMI_OEM_REQUEST_CMDID, /* UNUSED */ /** Nan Request */ WMI_NAN_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_NAN), @@ -12568,6 +12568,10 @@ typedef struct wmi_bpf_set_vdev_instructions_cmd_s { A_UINT32 total_length; A_UINT32 current_offset; A_UINT32 current_length; + /* + * The TLV follows: + * A_UINT8 buf_inst[]; //Variable length buffer for the instuctions + */ } wmi_bpf_set_vdev_instructions_cmd_fixed_param; #define BPF_FILTER_ID_ALL 0xFFFFFFFF diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index c36a6d2e16c9..7de4596c671e 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 190 +#define __WMI_REVISION_ 191 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 7b962531ffb5cb06b2e74355c6196e43700c406b Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Fri, 2 Oct 2015 17:17:03 -0700 Subject: qcacld-3.0: Clean up usage of con_mode Separate con_mode from adapter mode definition and clean up usage of con_mode. CRs-fixed: 917959 Change-Id: Ia058826cdb873558ab8703fcd4f80d37d3f782df --- core/bmi/src/ol_fw.c | 8 +- core/cdf/inc/cdf_types.h | 25 +- core/cds/inc/cds_api.h | 2 +- core/cds/inc/cds_concurrency.h | 17 +- core/cds/src/cds_api.c | 2 +- core/cds/src/cds_concurrency.c | 47 ++- core/hdd/inc/wlan_hdd_main.h | 17 +- core/hdd/src/wlan_hdd_cfg.c | 4 +- core/hdd/src/wlan_hdd_cfg80211.c | 80 ++-- core/hdd/src/wlan_hdd_driver_ops.c | 2 +- core/hdd/src/wlan_hdd_ext_scan.c | 28 +- core/hdd/src/wlan_hdd_hostapd.c | 6 +- core/hdd/src/wlan_hdd_ioctl.c | 4 +- core/hdd/src/wlan_hdd_main.c | 51 ++- core/hdd/src/wlan_hdd_memdump.c | 4 +- core/hdd/src/wlan_hdd_nan.c | 2 +- core/hdd/src/wlan_hdd_p2p.c | 10 +- core/hdd/src/wlan_hdd_power.c | 10 +- core/hdd/src/wlan_hdd_scan.c | 6 +- core/hdd/src/wlan_hdd_stats.c | 12 +- core/hdd/src/wlan_hdd_tdls.c | 10 +- core/hdd/src/wlan_hdd_tx_rx.c | 2 +- core/hif/src/ce/ce_main.c | 12 +- core/hif/src/hif_main.c | 13 +- core/hif/src/pcie/if_pci_internal.h | 2 +- core/mac/inc/sir_api.h | 6 +- core/mac/src/pe/include/lim_session.h | 2 +- core/mac/src/pe/lim/lim_api.c | 2 +- core/sap/inc/sap_api.h | 4 +- core/sap/src/sap_module.c | 709 +++++++++++++++----------------- core/sme/inc/csr_api.h | 4 +- core/sme/inc/csr_internal.h | 6 +- core/sme/inc/csr_support.h | 4 +- core/sme/inc/sme_api.h | 5 +- core/sme/inc/sme_internal.h | 2 +- core/sme/src/common/sme_api.c | 7 +- core/sme/src/csr/csr_api_roam.c | 12 +- core/sme/src/csr/csr_api_scan.c | 3 - core/sme/src/csr/csr_util.c | 38 +- core/utils/epping/inc/epping_internal.h | 4 +- core/utils/epping/src/epping_txrx.c | 2 +- core/wma/inc/wma_if.h | 4 +- core/wma/src/wma_main.c | 14 +- core/wma/src/wma_mgmt.c | 2 +- core/wma/src/wma_utils.c | 2 +- 45 files changed, 599 insertions(+), 609 deletions(-) diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c index 1607010d7dad..e01af6fe85e1 100644 --- a/core/bmi/src/ol_fw.c +++ b/core/bmi/src/ol_fw.c @@ -81,7 +81,7 @@ static int ol_check_fw_hash(const u8 *data, u32 fw_size, ATH_BIN_FILE file) break; case ATH_FIRMWARE_FILE: #ifdef QCA_WIFI_FTM - if (cds_get_conparam() == CDF_FTM_MODE) { + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) { hash = fw_hash.utf; break; } @@ -173,7 +173,7 @@ static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, break; } #ifdef QCA_WIFI_FTM - if (cds_get_conparam() == CDF_FTM_MODE) { + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) { #if defined(CONFIG_CNSS) filename = scn->fw_files.utf_file; #else @@ -201,7 +201,7 @@ static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, return 0; case ATH_BOARD_DATA_FILE: #ifdef QCA_WIFI_FTM - if (cds_get_conparam() == CDF_FTM_MODE) { + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) { #if defined(CONFIG_CNSS) filename = scn->fw_files.utf_board_data; #else @@ -225,7 +225,7 @@ static int __ol_transfer_bin_file(struct ol_softc *scn, ATH_BIN_FILE file, #endif break; case ATH_SETUP_FILE: - if (cds_get_conparam() != CDF_FTM_MODE && + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE && !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { #ifdef CONFIG_CNSS BMI_INFO("%s: no Setup file defined", __func__); diff --git a/core/cdf/inc/cdf_types.h b/core/cdf/inc/cdf_types.h index 5c987af344ca..cef5fe4e5a59 100644 --- a/core/cdf/inc/cdf_types.h +++ b/core/cdf/inc/cdf_types.h @@ -266,7 +266,7 @@ typedef enum { #define cdf_snprint __cdf_snprint /** - * typedef enum tCDF_CON_MODE - Concurrency role. + * enum tCDF_ADAPTER_MODE - adapter role. * * @CDF_STA_MODE: STA mode * @CDF_SAP_MODE: SAP mode @@ -282,18 +282,35 @@ typedef enum { * These are generic IDs that identify the various roles * in the software system */ -typedef enum { +enum tCDF_ADAPTER_MODE { CDF_STA_MODE = 0, CDF_SAP_MODE = 1, CDF_P2P_CLIENT_MODE, CDF_P2P_GO_MODE, - CDF_FTM_MODE = 5, + CDF_FTM_MODE, CDF_IBSS_MODE, CDF_P2P_DEVICE_MODE, CDF_EPPING_MODE, CDF_OCB_MODE, CDF_MAX_NO_OF_MODE -} tCDF_CON_MODE; +}; + +/** + * enum tCDF_GLOBAL_CON_MODE - global config mode when + * driver is loaded. + * + * @CDF_GLOBAL_MISSION_MODE: mission mode (STA, SAP...) + * @CDF_GLOBAL_FTM_MODE: FTM mode + * @CDF_GLOBAL_EPPING_MODE: EPPING mode + * @CDF_GLOBAL_MAX_MODE: Max place holder + */ +enum tCDF_GLOBAL_CON_MODE { + CDF_GLOBAL_MISSION_MODE, + CDF_GLOBAL_FTM_MODE = 5, + CDF_GLOBAL_EPPING_MODE = 8, + CDF_GLOBAL_MAX_MODE +}; + #ifdef WLAN_OPEN_P2P_INTERFACE /* This should match with WLAN_MAX_INTERFACES */ diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 9e7fd5a6721f..d3d327e76d77 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -90,7 +90,7 @@ CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID, void *pModuleContext); -CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type, +CDF_STATUS cds_get_vdev_types(enum tCDF_ADAPTER_MODE mode, uint32_t *type, uint32_t *subType); void cds_flush_work(void *work); diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index bb799cb35c6a..85af14772adb 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -465,9 +465,10 @@ struct cds_conc_connection_info { bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx); void cds_dump_concurrency_info(hdd_context_t *pHddCtx); -void cds_set_concurrency_mode(hdd_context_t *pHddCtx, tCDF_CON_MODE mode); +void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, + enum tCDF_ADAPTER_MODE mode); void cds_clear_concurrency_mode(hdd_context_t *pHddCtx, - tCDF_CON_MODE mode); + enum tCDF_ADAPTER_MODE mode); uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); /** * cds_is_sta_connection_pending() - This function will check if sta connection @@ -659,12 +660,14 @@ static inline void cds_check_and_restart_sap_with_non_dfs_acs( } #endif /* FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE */ -void cds_incr_active_session(hdd_context_t *pHddCtx, tCDF_CON_MODE mode, +void cds_incr_active_session(hdd_context_t *pHddCtx, + enum tCDF_ADAPTER_MODE mode, uint8_t sessionId); -void cds_decr_active_session(hdd_context_t *pHddCtx, tCDF_CON_MODE mode, +void cds_decr_active_session(hdd_context_t *pHddCtx, + enum tCDF_ADAPTER_MODE mode, uint8_t sessionId); void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, - tCDF_CON_MODE mode, + enum tCDF_ADAPTER_MODE mode, uint8_t session_id); CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx); CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, @@ -769,11 +772,11 @@ void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, uint32_t scan_config, uint32_t fw_mode_config); bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, - tCDF_CON_MODE *old_mode, enum cds_con_mode *new_mode); + enum tCDF_ADAPTER_MODE *old_mode, enum cds_con_mode *new_mode); CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint8_t *channel); -tCDF_CON_MODE cds_get_conparam(void); +enum tCDF_GLOBAL_CON_MODE cds_get_conparam(void); bool cds_concurrent_open_sessions_running(void); bool cds_max_concurrent_connections_reached(void); void cds_clear_concurrent_session_count(void); diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 573dd9bac357..03baf5089277 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1548,7 +1548,7 @@ CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context) * * Return: WMI vdev type */ -CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type, +CDF_STATUS cds_get_vdev_types(enum tCDF_ADAPTER_MODE mode, uint32_t *type, uint32_t *sub_type) { CDF_STATUS status = CDF_STATUS_SUCCESS; diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 2f97b411858d..ffb9a05ded2d 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3232,13 +3232,14 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) /** * cds_set_concurrency_mode() - To set concurrency mode * @hdd_ctx: HDD context - * @mode: Concurrency mode + * @mode: adapter mode * * This routine is called to set the concurrency mode * * Return: NONE */ -void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) +void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, + enum tCDF_ADAPTER_MODE mode) { switch (mode) { case CDF_STA_MODE: @@ -3260,14 +3261,14 @@ void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) /** * cds_clear_concurrency_mode() - To clear concurrency mode * @hdd_ctx: HDD context - * @mode: Concurrency mode + * @mode: adapter mode * * This routine is called to clear the concurrency mode * * Return: NONE */ void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, - tCDF_CON_MODE mode) + enum tCDF_ADAPTER_MODE mode) { switch (mode) { case CDF_STA_MODE: @@ -3289,7 +3290,7 @@ void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, /** * cds_soc_set_pcl() - Sets PCL to FW * @hdd_ctx: HDD context - * @mode: Connection mode + * @mode: adapter mode * * Fetches the PCL and sends the PCL to SME * module which in turn will send the WMI @@ -3297,7 +3298,7 @@ void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, * * Return: None */ -static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) +static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, enum tCDF_ADAPTER_MODE mode) { CDF_STATUS status; enum cds_con_mode con_mode; @@ -3344,7 +3345,7 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) /** * cds_incr_active_session() - increments the number of active sessions * @hdd_ctx: HDD Context - * @mode: Device mode + * @mode: Adapter mode * @session_id: session ID for the connection session * * This function increments the number of active sessions maintained per device @@ -3353,8 +3354,9 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode) * * Return: None */ -void cds_incr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, - uint8_t session_id) +void cds_incr_active_session(hdd_context_t *hdd_ctx, + enum tCDF_ADAPTER_MODE mode, + uint8_t session_id) { /* * Need to aquire mutex as entire functionality in this function @@ -3460,7 +3462,7 @@ static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, enum cds_con_mode mode) { struct cds_conc_connection_info info; - tCDF_CON_MODE pcl_mode; + enum tCDF_ADAPTER_MODE pcl_mode; switch (mode) { case CDS_STA_MODE: @@ -3499,7 +3501,7 @@ static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, /** * cds_decr_session_set_pcl() - Decrement session count and set PCL * @hdd_ctx: HDD context - * @mode: Connection mode + * @mode: Adapter mode * @session_id: Session id * * Decrements the active session count and sets the PCL if a STA connection @@ -3508,7 +3510,7 @@ static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, * Return: None */ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, - tCDF_CON_MODE mode, + enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { CDF_STATUS cdf_status; @@ -3549,8 +3551,8 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, /** * cds_decr_active_session() - decrements the number of active sessions - * @hdd_ctx: HDD Context - * @mode: Device mode + * @hdd_ctx: HDD Context + * @mode: Adapter mode * @session_id: session ID for the connection session * * This function decrements the number of active sessions maintained per device @@ -3559,7 +3561,8 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_decr_active_session(hdd_context_t *hdd_ctx, tCDF_CON_MODE mode, +void cds_decr_active_session(hdd_context_t *hdd_ctx, + enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { /* @@ -4306,7 +4309,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, /** * cds_map_concurrency_mode() - to map concurrency mode between sme and hdd * @hdd_ctx: hdd context - * @old_mode: sme provided concurrency mode + * @old_mode: sme provided adapter mode * @new_mode: hdd provided concurrency mode * * This routine will map concurrency mode between sme and hdd @@ -4314,7 +4317,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, * Return: true or false */ bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, - tCDF_CON_MODE *old_mode, enum cds_con_mode *new_mode) + enum tCDF_ADAPTER_MODE *old_mode, enum cds_con_mode *new_mode) { bool status = true; @@ -5719,7 +5722,7 @@ static int __cds_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { cds_err("Command not allowed in FTM mode"); return -EPERM; } @@ -6773,7 +6776,7 @@ CDF_STATUS cds_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter) cds_info("UPDATE Beacon Params"); - if (CDF_SAP_MODE == cds_get_conparam()) { + if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) { hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); if (NULL == hHal) { cds_err("Hal ctx is null"); @@ -7277,11 +7280,11 @@ enum cds_con_mode cds_convert_device_mode_to_hdd_type( * Return the connection mode parameter set by insmod or set during statically * linked driver * - * Return: tCDF_CON_MODE + * Return: enum tCDF_GLOBAL_CON_MODE */ -tCDF_CON_MODE cds_get_conparam(void) +enum tCDF_GLOBAL_CON_MODE cds_get_conparam(void) { - tCDF_CON_MODE con_mode; + enum tCDF_GLOBAL_CON_MODE con_mode; con_mode = hdd_get_conparam(); return con_mode; } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index dd1e6c67de68..e464b9c059b9 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -530,14 +530,23 @@ typedef struct beacon_data_s { int dtim_period; } beacon_data_t; -/* MAINTAIN 1 - 1 CORRESPONDENCE WITH tCDF_CON_MODE */ +/** + * enum device_mode: Maintain one to one correspondence with tCDF_ADAPTER_MODE + * @WLAN_HDD_INFRA_STATION: station mode + * @WLAN_HDD_SOFTAP: sap mode + * @WLAN_HDD_P2P_CLIENT: p2p client mode + * @WLAN_HDD_P2P_GO: p2p go mode + * @WLAN_HDD_FTM: ftm mode + * @WLAN_HDD_IBSS: ibss mode + * @WLAN_HDD_P2P_DEVICE: p2p device mode + * @WLAN_HDD_OCB: ocb mode + */ typedef enum device_mode { WLAN_HDD_INFRA_STATION, WLAN_HDD_SOFTAP, WLAN_HDD_P2P_CLIENT, WLAN_HDD_P2P_GO, - /* Mode 5 is reserved for FTM */ - WLAN_HDD_FTM = 5, + WLAN_HDD_FTM, WLAN_HDD_IBSS, WLAN_HDD_P2P_DEVICE, WLAN_HDD_OCB @@ -1388,7 +1397,7 @@ void wlan_hdd_release_intf_addr(hdd_context_t *pHddCtx, uint8_t *releaseAddr); uint8_t hdd_get_operating_channel(hdd_context_t *pHddCtx, device_mode_t mode); void hdd_set_conparam(uint32_t con_param); -tCDF_CON_MODE hdd_get_conparam(void); +enum tCDF_GLOBAL_CON_MODE hdd_get_conparam(void); void hdd_abort_mac_scan(hdd_context_t *pHddCtx, uint8_t sessionId, eCsrAbortReason reason); diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index b5451f3fa17c..33a41f009a13 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -6516,9 +6516,7 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) smeConfig->csrConfig.fFirstScanOnly2GChnl = pConfig->enableFirstScan2GOnly; - /* FIXME 11d config is hardcoded */ - if (CDF_SAP_MODE != hdd_get_conparam()) - smeConfig->csrConfig.Csr11dinfo.Channels.numChannels = 0; + smeConfig->csrConfig.Csr11dinfo.Channels.numChannels = 0; hdd_set_power_save_offload_config(pHddCtx); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 8d830a3cbc0d..cd1a4864978a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -680,7 +680,7 @@ static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy, struct sk_buff *skb; uint32_t set = 0; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1115,7 +1115,7 @@ static int __is_driver_dfs_capable(struct wiphy *wiphy, if (ret_val) return ret_val; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1422,7 +1422,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED }, */ - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1811,7 +1811,7 @@ __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1952,7 +1952,7 @@ __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2077,7 +2077,7 @@ __wlan_hdd_cfg80211_get_features(struct wiphy *wiphy, if (ret_val) return ret_val; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2196,7 +2196,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, uint32_t buf_len = 0; int ret; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2726,7 +2726,7 @@ static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy, hdd_context_t *hdd_ctx_ptr; int status; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2815,7 +2815,7 @@ __wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy, int status; struct sk_buff *reply_skb = NULL; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2912,7 +2912,7 @@ __wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, uint32_t features; struct sk_buff *reply_skb = NULL; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3146,7 +3146,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, u32 guard_time; CDF_STATUS status; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3265,7 +3265,7 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1]; struct sir_wifi_start_log start_log; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3389,7 +3389,7 @@ static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy, struct nlattr *tb [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1]; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3783,7 +3783,7 @@ __wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4336,7 +4336,7 @@ static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4519,7 +4519,7 @@ static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy, CDF_STATUS status; uint32_t current_roam_state; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -5208,7 +5208,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, #endif /*FEATURE_WLAN_SCAN_PNO */ #if defined QCA_WIFI_FTM - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { #endif /* even with WIPHY_FLAG_CUSTOM_REGULATORY, @@ -5313,7 +5313,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION; - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands); wiphy->vendor_commands = hdd_wiphy_vendor_commands; @@ -5698,7 +5698,7 @@ static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -5790,9 +5790,6 @@ static int wlan_hdd_change_iface_to_sta_mode(struct net_device *ndev, WLAN_HDD_INFRA_STATION : WLAN_HDD_P2P_CLIENT; } - /* set con_mode to STA only when no SAP concurrency mode */ - if (!(cds_get_concurrency_mode() & (CDF_SAP_MASK | CDF_P2P_GO_MASK))) - hdd_set_conparam(0); memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx)); hdd_set_station_ops(pAdapter->dev); status = hdd_init_station_mode(pAdapter); @@ -5850,7 +5847,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -5969,7 +5966,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, ("Error initializing the ap mode")); return -EINVAL; } - hdd_set_conparam(1); hdd_register_tx_flow_control(pAdapter, hdd_softap_tx_resume_timer_expired_handler, @@ -6140,7 +6136,7 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -6423,7 +6419,7 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -6757,7 +6753,7 @@ static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -6909,7 +6905,7 @@ static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -8630,7 +8626,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -8891,7 +8887,7 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9126,7 +9122,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9337,7 +9333,7 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9434,7 +9430,7 @@ static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9650,7 +9646,7 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9870,7 +9866,7 @@ static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -9950,7 +9946,7 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10031,7 +10027,7 @@ static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10111,7 +10107,7 @@ static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10183,7 +10179,7 @@ __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, if (status) return status; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10316,7 +10312,7 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10428,7 +10424,7 @@ static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -10820,7 +10816,7 @@ __wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy, tSmeConfigParams sme_config; bool cbModeChange; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 82c91482dc1f..8a45f4fe1e90 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -316,7 +316,7 @@ static void wlan_hdd_shutdown(void) /* this is for cases, where shutdown invoked from CNSS */ cds_set_logp_in_progress(true); - if (cds_get_conparam() != CDF_FTM_MODE && + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE && !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) hif_pktlogmod_exit(hif_ctx); diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index 4247636a0121..f33a6e20eab6 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -1718,7 +1718,7 @@ static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1852,7 +1852,7 @@ static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2000,7 +2000,7 @@ __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2197,7 +2197,7 @@ __wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -2479,7 +2479,7 @@ __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3144,7 +3144,7 @@ __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3354,7 +3354,7 @@ __wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3481,7 +3481,7 @@ __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3606,7 +3606,7 @@ __wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3822,7 +3822,7 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, if (ret_val) return ret_val; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4028,7 +4028,7 @@ static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, if (ret) return ret; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4144,7 +4144,7 @@ static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, if (ret) return ret; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4270,7 +4270,7 @@ __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -4490,7 +4490,7 @@ __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index a7113f54c552..02a6492e42a0 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -7774,7 +7774,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -8003,7 +8003,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -8161,7 +8161,7 @@ static int __wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 2a768974774d..0efca0fbb13b 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -6137,7 +6137,7 @@ static int hdd_driver_command(hdd_adapter_t *adapter, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -6275,7 +6275,7 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } #if defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR) - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { if (SIOCIOCTLTX99 == cmd) { ret = wlan_hdd_qcmbr_unified_ioctl(adapter, ifr); goto exit; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 7d757071630f..6f58aac08b41 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1619,7 +1619,7 @@ static void __hdd_set_multicast_list(struct net_device *dev) static const uint8_t ipv6_router_solicitation[] = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; - if (CDF_FTM_MODE == hdd_get_conparam()) + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) return; ENTER(); @@ -2117,12 +2117,6 @@ void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, hdd_unregister_hostapd(adapter, rtnl_held); - /* set con_mode to STA only when no SAP concurrency mode */ - if (! - (cds_get_concurrency_mode() & - (CDF_SAP_MASK | CDF_P2P_GO_MASK))) - hdd_set_conparam(0); - break; } @@ -2343,8 +2337,6 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH); - hdd_set_conparam(1); - break; } case WLAN_HDD_FTM: @@ -2431,7 +2423,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, cds_check_and_restart_sap_with_non_dfs_acs(hdd_ctx); } - if ((cds_get_conparam() != CDF_FTM_MODE) + if ((cds_get_conparam() != CDF_GLOBAL_FTM_MODE) && (!hdd_ctx->config->enable2x2)) { #define HDD_DTIM_1CHAIN_RX_ID 0x5 #define HDD_SMPS_PARAM_VALUE_S 29 @@ -2477,7 +2469,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, #undef HDD_SMPS_PARAM_VALUE_S } - if (CDF_FTM_MODE != cds_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE != cds_get_conparam()) { ret = wma_cli_set_command(adapter->sessionId, WMI_PDEV_PARAM_HYST_EN, hdd_ctx->config->enableMemDeepSleep, @@ -2494,7 +2486,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, #ifdef CONFIG_FW_LOGS_BASED_ON_INI /* Enable FW logs based on INI configuration */ - if ((CDF_FTM_MODE != cds_get_conparam()) && + if ((CDF_GLOBAL_FTM_MODE != cds_get_conparam()) && (hdd_ctx->config->enablefwlog)) { uint8_t count = 0; uint32_t value = 0; @@ -3389,7 +3381,7 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) hdd_unregister_wext_all_adapters(hdd_ctx); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(CDF_TRACE_LEVEL_INFO, FL("FTM MODE")); #if defined(QCA_WIFI_FTM) if (hdd_ftm_stop(hdd_ctx)) { @@ -4877,7 +4869,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_cfg_print(hdd_ctx); - if (CDF_FTM_MODE == hdd_get_conparam()) + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) goto ftm_processing; hdd_ctx->isLogpInProgress = false; @@ -5028,7 +5020,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) #endif /* QCA_PKT_PROTO_TRACE */ ftm_processing: - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { if (CDF_STATUS_SUCCESS != wlan_hdd_ftm_open(hdd_ctx)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("wlan_hdd_ftm_open Failed")); @@ -5250,13 +5242,11 @@ ftm_processing: if (cds_is_multicast_logging()) wlan_logging_set_log_level(); - if (CDF_SAP_MODE != hdd_get_conparam()) { - /* - * Action frame registered in one adapter which will - * applicable to all interfaces - */ - wlan_hdd_cfg80211_register_frames(adapter); - } + /* + * Action frame registered in one adapter which will + * applicable to all interfaces + */ + wlan_hdd_cfg80211_register_frames(adapter); mutex_init(&hdd_ctx->sap_lock); @@ -5485,7 +5475,7 @@ err_cds_close: err_cds_open: - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { #if defined(QCA_WIFI_FTM) err_free_ftm_open: wlan_hdd_ftm_close(hdd_ctx); @@ -5876,7 +5866,7 @@ void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter, int ret = 0; struct wlan_status_data data; - if (CDF_FTM_MODE == hdd_get_conparam()) + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) return; memset(&data, 0, sizeof(struct wlan_status_data)); @@ -5908,7 +5898,7 @@ void wlan_hdd_send_version_pkg(uint32_t fw_version, return; #endif - if (CDF_FTM_MODE == hdd_get_conparam()) + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) return; memset(&data, 0, sizeof(struct wlan_version_data)); @@ -6297,6 +6287,11 @@ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) return; } + if (WLAN_HDD_SOFTAP != ap_adapter->device_mode) { + hdd_err("SoftAp role has not been enabled"); + 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); @@ -6611,11 +6606,11 @@ static int con_mode_handler(const char *kmessage, struct kernel_param *kp) * * This is the driver exit point (invoked when module is unloaded using rmmod) * - * Return: tCDF_CON_MODE + * Return: enum tCDF_GLOBAL_CON_MODE */ -tCDF_CON_MODE hdd_get_conparam(void) +enum tCDF_GLOBAL_CON_MODE hdd_get_conparam(void) { - return (tCDF_CON_MODE) curr_con_mode; + return (enum tCDF_GLOBAL_CON_MODE) curr_con_mode; } void hdd_set_conparam(uint32_t con_param) diff --git a/core/hdd/src/wlan_hdd_memdump.c b/core/hdd/src/wlan_hdd_memdump.c index 21f398e52ce5..9013e81a77ed 100644 --- a/core/hdd/src/wlan_hdd_memdump.c +++ b/core/hdd/src/wlan_hdd_memdump.c @@ -548,7 +548,7 @@ int memdump_init(void) return -EINVAL; } - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Not initializing memdump in FTM mode")); return -EINVAL; } @@ -602,7 +602,7 @@ void memdump_deinit(void) return; } - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Not deinitializing memdump in FTM mode")); return; } diff --git a/core/hdd/src/wlan_hdd_nan.c b/core/hdd/src/wlan_hdd_nan.c index 4fff12bd158d..eb06a16aa8ff 100644 --- a/core/hdd/src/wlan_hdd_nan.c +++ b/core/hdd/src/wlan_hdd_nan.c @@ -65,7 +65,7 @@ static int __wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy, if (ret_val) return ret_val; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 9018af87ba96..f8d7acb00578 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -950,7 +950,7 @@ int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy, if (0 != ret) return ret; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -1094,7 +1094,7 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -1255,7 +1255,7 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -1952,7 +1952,7 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return ERR_PTR(-EINVAL); } @@ -2048,7 +2048,7 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) int status; ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 2c00f1fceedf..0acc47bd1735 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1742,7 +1742,7 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -1878,7 +1878,7 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2098,7 +2098,7 @@ static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2191,7 +2191,7 @@ static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2283,7 +2283,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 0a13bf602b96..46c0cfc55550 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1241,7 +1241,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2027,7 +2027,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2302,7 +2302,7 @@ static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 8f50005d8a96..3617d1b2769f 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1144,7 +1144,7 @@ __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1270,7 +1270,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1401,7 +1401,7 @@ __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1546,7 +1546,7 @@ static int __wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, if (ret_val) return ret_val; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -1723,7 +1723,7 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -2230,7 +2230,7 @@ static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 368fa31e3d19..10b3a86cff79 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -3049,7 +3049,7 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3228,7 +3228,7 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3347,7 +3347,7 @@ static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + 1]; CDF_STATUS status; - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); return -EPERM; } @@ -3668,7 +3668,7 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, #endif #endif - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } @@ -4148,7 +4148,7 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, ENTER(); - if (CDF_FTM_MODE == hdd_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hddLog(LOGE, FL("Command not allowed in FTM mode")); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index c7ed41ddae87..7479870fd3b4 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -305,7 +305,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif /* QCA_PKT_PROTO_TRACE */ #ifdef QCA_WIFI_FTM - if (hdd_get_conparam() == CDF_FTM_MODE) { + if (hdd_get_conparam() == CDF_GLOBAL_FTM_MODE) { kfree_skb(skb); return NETDEV_TX_OK; } diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 9ade278246fd..80379cff2ab8 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1806,17 +1806,13 @@ static int hif_wlan_enable(void) cfg.num_shadow_reg_cfg = shadow_cfg_sz / sizeof(struct shadow_reg_cfg); cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *) target_shadow_reg_cfg; - switch (con_mode) { - case CDF_FTM_MODE: + if (CDF_GLOBAL_FTM_MODE == con_mode) mode = ICNSS_FTM; - break; - case CDF_EPPING_MODE: + else if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) mode = ICNSS_EPPING; - break; - default: + else mode = ICNSS_MISSION; - break; - } + return icnss_wlan_enable(&cfg, mode, QWLAN_VERSIONSTR); } diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 100805f9100b..90544f309e29 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -652,7 +652,7 @@ void hif_pktlogmod_exit(void *hif_ctx) { struct ol_softc *scn = hif_ctx; - if (scn && cds_get_conparam() != CDF_FTM_MODE && + if (scn && cds_get_conparam() != CDF_GLOBAL_FTM_MODE && !WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && scn->pkt_log_init) { pktlogmod_exit(scn); scn->pkt_log_init = false; @@ -684,17 +684,12 @@ void hif_wlan_disable(void) enum icnss_driver_mode mode; uint32_t con_mode = cds_get_conparam(); - switch (con_mode) { - case CDF_FTM_MODE: + if (CDF_GLOBAL_FTM_MODE == con_mode) mode = ICNSS_FTM; - break; - case CDF_EPPING_MODE: + else if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) mode = ICNSS_EPPING; - break; - default: + else mode = ICNSS_MISSION; - break; - } icnss_wlan_disable(mode); } diff --git a/core/hif/src/pcie/if_pci_internal.h b/core/hif/src/pcie/if_pci_internal.h index e5f28d2b2774..5ea8e31481fb 100644 --- a/core/hif/src/pcie/if_pci_internal.h +++ b/core/hif/src/pcie/if_pci_internal.h @@ -97,7 +97,7 @@ { \ ol_txrx_pdev_handle pdev_txrx_handle; \ pdev_txrx_handle = cds_get_context(CDF_MODULE_ID_TXRX); \ - if (cds_get_conparam() != CDF_FTM_MODE && \ + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE && \ !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { \ ol_pl_sethandle(&pdev_txrx_handle->pl_dev, ol_sc); \ if (pktlogmod_init(ol_sc)) \ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 8ad8c1f61da6..219c5ecabfaf 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -586,7 +586,7 @@ typedef struct sSirSmeStartBssReq { uint32_t dtimPeriod; uint8_t wps_state; uint8_t isCoalesingInIBSSAllowed; /* Coalesing on/off knob */ - tCDF_CON_MODE bssPersona; + enum tCDF_ADAPTER_MODE bssPersona; uint8_t txLdpcIniFeatureEnabled; @@ -914,7 +914,7 @@ typedef struct sSirSmeJoinReq { #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH uint8_t cc_switch_mode; #endif - tCDF_CON_MODE staPersona; /* Persona */ + enum tCDF_ADAPTER_MODE staPersona; /* Persona */ ePhyChanBondState cbMode; /* Pass CB mode value in Join. */ /*This contains the UAPSD Flag for all 4 AC @@ -3695,7 +3695,7 @@ typedef struct { typedef struct sSirRateUpdateInd { uint8_t nss; /* 0: 1x1, 1: 2x2 */ struct cdf_mac_addr bssid; - tCDF_CON_MODE dev_mode; + enum tCDF_ADAPTER_MODE dev_mode; int32_t bcastDataRate; /* bcast rate unit Mbpsx10, -1:not used */ /* * 0 implies RA, positive value implies fixed rate, -1 implies ignore diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 4b0ebe7c459f..14cee56b5a70 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -276,7 +276,7 @@ typedef struct sPESession /* Added to Support BT-AMP */ uint32_t lim11hEnable; tPowerdBm maxTxPower; /* MIN (Regulatory and local power constraint) */ - tCDF_CON_MODE pePersona; + enum tCDF_ADAPTER_MODE pePersona; #if defined WLAN_FEATURE_VOWIFI tPowerdBm txMgmtPower; #endif diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index af61ed339e0e..bd221069ef15 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -655,7 +655,7 @@ void lim_cleanup(tpAniSirGlobal pMac) struct mgmt_frm_reg_info *pLimMgmtRegistration = NULL; - if (CDF_FTM_MODE != cds_get_conparam()) { + if (CDF_GLOBAL_FTM_MODE != cds_get_conparam()) { cdf_mutex_acquire(&pMac->lim.lim_frame_register_lock); while (cdf_list_remove_front( &pMac->lim.gLimMgmtFrameRegistratinQueue, diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 50a42391ee24..75f92b5454d7 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -539,7 +539,7 @@ typedef struct sap_Config { uint32_t ap_table_max_size; uint32_t ap_table_expiration_time; uint32_t ht_op_mode_fixed; - tCDF_CON_MODE persona; /* Tells us which persona its GO or AP for now */ + enum tCDF_ADAPTER_MODE persona; /* Tells us which persona, GO or AP */ uint8_t disableDFSChSwitch; bool enOverLapCh; #ifdef WLAN_FEATURE_11W @@ -671,7 +671,7 @@ typedef struct sSapDfsInfo { typedef struct tagSapCtxList { uint8_t sessionID; void *pSapContext; - tCDF_CON_MODE sapPersona; + enum tCDF_ADAPTER_MODE sapPersona; } tSapCtxList, tpSapCtxList; typedef struct tagSapStruct { diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index fb84e6634b4b..83658309b097 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -526,9 +526,7 @@ wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig, */ psap_ctx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; - /* - * Save a copy to SAP context - */ + /* Save a copy to SAP context */ cdf_mem_copy(psap_ctx->csr_roamProfile.BSSIDs.bssid, pconfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); cdf_mem_copy(psap_ctx->self_mac_addr, @@ -540,11 +538,11 @@ wlansap_set_scan_acs_channel_params(tsap_Config_t *pconfig, "%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 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_get_concurrent_operation_channel(h_hal)) && pconfig->ieee80211d) { /* Setting the region/country information */ @@ -660,106 +658,102 @@ CDF_STATUS wlansap_start_bss(void *pCtx, /* pwextCtx */ Sanity check Extract SAP control block ------------------------------------------------------------------------*/ - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); + pSapCtx = CDS_GET_SAP_CB(pCtx); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "wlansap_start_bss: sapContext=%p", pSapCtx); + + if (NULL == pSapCtx) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, - "wlansap_start_bss: sapContext=%p", pSapCtx); + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + pSapCtx->sapsMachine = eSAP_DISCONNECTED; - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - pSapCtx->sapsMachine = eSAP_DISCONNECTED; - - /* Channel selection is auto or configured */ - pSapCtx->channel = pConfig->channel; - pSapCtx->ch_params.ch_width = pConfig->ch_params.ch_width; - pSapCtx->ch_params.center_freq_seg0 = - pConfig->ch_params.center_freq_seg0; - pSapCtx->ch_params.center_freq_seg1 = - pConfig->ch_params.center_freq_seg1; - pSapCtx->ch_params.sec_ch_offset = - pConfig->ch_params.sec_ch_offset; - pSapCtx->ch_width_orig = pConfig->ch_width_orig; + /* Channel selection is auto or configured */ + pSapCtx->channel = pConfig->channel; + pSapCtx->ch_params.ch_width = pConfig->ch_params.ch_width; + pSapCtx->ch_params.center_freq_seg0 = + pConfig->ch_params.center_freq_seg0; + pSapCtx->ch_params.center_freq_seg1 = + pConfig->ch_params.center_freq_seg1; + pSapCtx->ch_params.sec_ch_offset = + pConfig->ch_params.sec_ch_offset; + pSapCtx->ch_width_orig = pConfig->ch_width_orig; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH - pSapCtx->cc_switch_mode = pConfig->cc_switch_mode; + pSapCtx->cc_switch_mode = pConfig->cc_switch_mode; #endif - pSapCtx->pUsrContext = pUsrContext; - pSapCtx->enableOverLapCh = pConfig->enOverLapCh; - pSapCtx->acs_cfg = &pConfig->acs_cfg; - /* Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD */ - pSapCtx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; - cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, - pSapCtx->self_mac_addr, sizeof(struct cdf_mac_addr)); - - /* Save a copy to SAP context */ - cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, - pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(pSapCtx->self_mac_addr, - pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); - - /* copy the configuration items to csrProfile */ - sapconvert_to_csr_profile(pConfig, eCSR_BSS_TYPE_INFRA_AP, - &pSapCtx->csr_roamProfile); - hHal = (tHalHandle) CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: Invalid MAC context from p_cds_gctx", - __func__); - return CDF_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_get_concurrent_operation_channel(hHal)) && - pConfig->ieee80211d) { - /* Setting the region/country information */ - sme_set_reg_info(hHal, pConfig->countryCode); - sme_apply_channel_power_info_to_fw(hHal); - } - } - - pmac = PMAC_STRUCT(hHal); - if (NULL == pmac) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: Invalid MAC context from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; + pSapCtx->pUsrContext = pUsrContext; + pSapCtx->enableOverLapCh = pConfig->enOverLapCh; + pSapCtx->acs_cfg = &pConfig->acs_cfg; + /* Set the BSSID to your "self MAC Addr" read the mac address + from Configuation ITEM received from HDD */ + pSapCtx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; + cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, + pSapCtx->self_mac_addr, sizeof(struct cdf_mac_addr)); + + /* Save a copy to SAP context */ + cdf_mem_copy(pSapCtx->csr_roamProfile.BSSIDs.bssid, + pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(pSapCtx->self_mac_addr, + pConfig->self_macaddr.bytes, CDF_MAC_ADDR_SIZE); + + /* copy the configuration items to csrProfile */ + sapconvert_to_csr_profile(pConfig, eCSR_BSS_TYPE_INFRA_AP, + &pSapCtx->csr_roamProfile); + hHal = (tHalHandle) CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from p_cds_gctx", + __func__); + return CDF_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_get_concurrent_operation_channel(hHal)) && + pConfig->ieee80211d) { + /* Setting the region/country information */ + sme_set_reg_info(hHal, pConfig->countryCode); + sme_apply_channel_power_info_to_fw(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; - cdf_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, - sizeof(pConfig->accept_mac)); - pSapCtx->nAcceptMac = pConfig->num_accept_mac; - sap_sort_mac_list(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); - cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, - sizeof(pConfig->deny_mac)); - pSapCtx->nDenyMac = pConfig->num_deny_mac; - sap_sort_mac_list(pSapCtx->denyMacList, pSapCtx->nDenyMac); - /* Fill in the event structure for FSM */ - sapEvent.event = eSAP_HDD_START_INFRA_BSS; - sapEvent.params = 0; /* pSapPhysLinkCreate */ + pmac = PMAC_STRUCT(hHal); + if (NULL == pmac) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid MAC context from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + /* + * 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; + cdf_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sap_sort_mac_list(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sap_sort_mac_list(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; + /* Store the HDD callback in SAP context */ + pSapCtx->pfnSapEventCallback = pSapEventCallback; - /* Handle event */ - cdf_status = sap_fsm(pSapCtx, &sapEvent); - } else { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "SoftAp role has not been enabled"); - } + /* Handle event */ + cdf_status = sap_fsm(pSapCtx, &sapEvent); return cdf_status; } /* wlansap_start_bss */ @@ -787,36 +781,30 @@ CDF_STATUS wlansap_set_mac_acl(void *pCtx, /* pwextCtx */ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_set_mac_acl"); - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - /* Copy MAC filtering settings to sap context */ - pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; - - if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) { - cdf_mem_copy(pSapCtx->acceptMacList, - pConfig->accept_mac, - sizeof(pConfig->accept_mac)); - pSapCtx->nAcceptMac = pConfig->num_accept_mac; - sap_sort_mac_list(pSapCtx->acceptMacList, - pSapCtx->nAcceptMac); - } else if (eSAP_ACCEPT_UNLESS_DENIED == - pSapCtx->eSapMacAddrAclMode) { - cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, - sizeof(pConfig->deny_mac)); - pSapCtx->nDenyMac = pConfig->num_deny_mac; - sap_sort_mac_list(pSapCtx->denyMacList, pSapCtx->nDenyMac); - } - } else { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s : SoftAp role has not been enabled", __func__); + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pCtx", + __func__); return CDF_STATUS_E_FAULT; } + /* Copy MAC filtering settings to sap context */ + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + + if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) { + cdf_mem_copy(pSapCtx->acceptMacList, + pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sap_sort_mac_list(pSapCtx->acceptMacList, + pSapCtx->nAcceptMac); + } else if (eSAP_ACCEPT_UNLESS_DENIED == + pSapCtx->eSapMacAddrAclMode) { + cdf_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sap_sort_mac_list(pSapCtx->denyMacList, pSapCtx->nDenyMac); + } return cdf_status; } /* wlansap_set_mac_acl */ @@ -1727,31 +1715,27 @@ CDF_STATUS wlansap_set_key_sta(void *pCtx, tCsrRoamSetKey *pSetKeyInfo) CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; uint32_t roamId = 0xFF; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid HAL pointer from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; - } - cdf_ret_status = - sme_roam_set_key(hHal, pSapCtx->sessionId, pSetKeyInfo, - &roamId); + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } + cdf_ret_status = + sme_roam_set_key(hHal, pSapCtx->sessionId, pSetKeyInfo, + &roamId); - if (cdf_ret_status == CDF_STATUS_SUCCESS) { - cdf_status = CDF_STATUS_SUCCESS; - } else { - cdf_status = CDF_STATUS_E_FAULT; - } - } else + if (cdf_ret_status == CDF_STATUS_SUCCESS) + cdf_status = CDF_STATUS_SUCCESS; + else cdf_status = CDF_STATUS_E_FAULT; return cdf_status; @@ -1775,15 +1759,6 @@ wlan_sap_getstation_ie_information CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; ptSapContext sap_ctx = NULL; uint32_t ie_len = 0; - tCDF_CON_MODE mode; - - mode = cds_get_conparam(); - if (CDF_SAP_MODE != mode) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%d: called in wrong mode ", - mode); - return CDF_STATUS_E_FAULT; - } sap_ctx = CDS_GET_SAP_CB(ctx); if (NULL == sap_ctx) { @@ -1831,44 +1806,41 @@ CDF_STATUS wlansap_set_wps_ie(void *pCtx, tSap_WPSIE *pSap_WPSIe) CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "%s, %d", __func__, __LINE__); - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid HAL pointer from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; - } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } - if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { - if (pSap_WPSIe->sapWPSIECode == eSAP_WPS_BEACON_IE) { - cdf_mem_copy(&pSapCtx->APWPSIEs.SirWPSBeaconIE, - &pSap_WPSIe->sapwpsie. - sapWPSBeaconIE, - sizeof(tSap_WPSBeaconIE)); - } else if (pSap_WPSIe->sapWPSIECode == - eSAP_WPS_PROBE_RSP_IE) { - cdf_mem_copy(&pSapCtx->APWPSIEs. - SirWPSProbeRspIE, - &pSap_WPSIe->sapwpsie. - sapWPSProbeRspIE, - sizeof(tSap_WPSProbeRspIE)); - } else { - sap_release_global_lock(pSapCtx); - return CDF_STATUS_E_FAULT; - } + if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { + if (pSap_WPSIe->sapWPSIECode == eSAP_WPS_BEACON_IE) { + cdf_mem_copy(&pSapCtx->APWPSIEs.SirWPSBeaconIE, + &pSap_WPSIe->sapwpsie. + sapWPSBeaconIE, + sizeof(tSap_WPSBeaconIE)); + } else if (pSap_WPSIe->sapWPSIECode == + eSAP_WPS_PROBE_RSP_IE) { + cdf_mem_copy(&pSapCtx->APWPSIEs. + SirWPSProbeRspIE, + &pSap_WPSIe->sapwpsie. + sapWPSProbeRspIE, + sizeof(tSap_WPSProbeRspIE)); + } else { sap_release_global_lock(pSapCtx); - return CDF_STATUS_SUCCESS; - } else return CDF_STATUS_E_FAULT; + } + sap_release_global_lock(pSapCtx); + return CDF_STATUS_SUCCESS; } else return CDF_STATUS_E_FAULT; } @@ -1894,34 +1866,30 @@ CDF_STATUS wlansap_update_wps_ie(void *pCtx) CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s, %d", __func__, __LINE__); - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid HAL pointer from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = - sme_roam_update_apwpsie(hHal, pSapCtx->sessionId, - &pSapCtx->APWPSIEs); + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } - if (cdf_ret_status == CDF_STATUS_SUCCESS) { - cdf_status = CDF_STATUS_SUCCESS; - } else { - cdf_status = CDF_STATUS_E_FAULT; - } + cdf_ret_status = + sme_roam_update_apwpsie(hHal, pSapCtx->sessionId, + &pSapCtx->APWPSIEs); - } + if (cdf_ret_status == CDF_STATUS_SUCCESS) + cdf_status = CDF_STATUS_SUCCESS; + else + cdf_status = CDF_STATUS_E_FAULT; return cdf_status; } @@ -1947,37 +1915,33 @@ CDF_STATUS wlansap_get_wps_state(void *pCtx, bool *bWPSState) CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "%s, %d", __func__, __LINE__); - if (CDF_SAP_MODE == cds_get_conparam()) { - - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid HAL pointer from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; - } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } - if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { - if (pSapCtx->APWPSIEs.SirWPSProbeRspIE. - FieldPresent & - SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) - *bWPSState = true; - else - *bWPSState = false; + if (sap_acquire_global_lock(pSapCtx) == CDF_STATUS_SUCCESS) { + if (pSapCtx->APWPSIEs.SirWPSProbeRspIE. + FieldPresent & + SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) + *bWPSState = true; + else + *bWPSState = false; - sap_release_global_lock(pSapCtx); + sap_release_global_lock(pSapCtx); - return CDF_STATUS_SUCCESS; - } else - return CDF_STATUS_E_FAULT; + return CDF_STATUS_SUCCESS; } else return CDF_STATUS_E_FAULT; @@ -2025,37 +1989,34 @@ CDF_STATUS wlansap_set_wparsn_ies CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; void *hHal = NULL; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if (NULL == hHal) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid HAL pointer from p_cds_gctx", - __func__); - return CDF_STATUS_E_FAULT; - } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if (NULL == hHal) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid HAL pointer from p_cds_gctx", + __func__); + return CDF_STATUS_E_FAULT; + } - pSapCtx->APWPARSNIEs.length = (uint16_t) WPARSNIEsLen; - cdf_mem_copy(pSapCtx->APWPARSNIEs.rsnIEdata, pWPARSNIEs, - WPARSNIEsLen); + pSapCtx->APWPARSNIEs.length = (uint16_t) WPARSNIEsLen; + cdf_mem_copy(pSapCtx->APWPARSNIEs.rsnIEdata, pWPARSNIEs, + WPARSNIEsLen); - cdf_ret_status = - sme_roam_update_apwparsni_es(hHal, pSapCtx->sessionId, - &pSapCtx->APWPARSNIEs); + cdf_ret_status = + sme_roam_update_apwparsni_es(hHal, pSapCtx->sessionId, + &pSapCtx->APWPARSNIEs); - if (cdf_ret_status == CDF_STATUS_SUCCESS) { - return CDF_STATUS_SUCCESS; - } else { - return CDF_STATUS_E_FAULT; - } - } + if (cdf_ret_status == CDF_STATUS_SUCCESS) + return CDF_STATUS_SUCCESS; + else + return CDF_STATUS_E_FAULT; return CDF_STATUS_E_FAULT; } @@ -2080,29 +2041,27 @@ CDF_STATUS wlansap_send_action(void *pCtx, const uint8_t *pBuf, void *hHal = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", - __func__, hHal, pSapCtx->isSapSessionOpen); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = - sme_send_action(hHal, pSapCtx->sessionId, pBuf, len, 0, - 0, channel_freq); + cdf_ret_status = + sme_send_action(hHal, pSapCtx->sessionId, pBuf, len, 0, + 0, channel_freq); - if (CDF_STATUS_SUCCESS == cdf_ret_status) { - return CDF_STATUS_SUCCESS; - } + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -2136,29 +2095,27 @@ CDF_STATUS wlansap_remain_on_channel(void *pCtx, void *hHal = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", - __func__, hHal, pSapCtx->isSapSessionOpen); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = sme_remain_on_channel(hHal, pSapCtx->sessionId, - channel, duration, callback, pContext, - true, scan_id); + cdf_ret_status = sme_remain_on_channel(hHal, pSapCtx->sessionId, + channel, duration, callback, pContext, + true, scan_id); - if (CDF_STATUS_SUCCESS == cdf_ret_status) { - return CDF_STATUS_SUCCESS; - } + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -2185,30 +2142,28 @@ CDF_STATUS wlansap_cancel_remain_on_channel(void *pCtx, void *hHal = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if ((NULL == hHal) || - (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", - __func__, hHal, pSapCtx->isSapSessionOpen); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || + (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = - sme_cancel_remain_on_channel(hHal, pSapCtx->sessionId, - scan_id); + cdf_ret_status = + sme_cancel_remain_on_channel(hHal, pSapCtx->sessionId, + scan_id); - if (CDF_STATUS_SUCCESS == cdf_ret_status) { - return CDF_STATUS_SUCCESS; - } + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -2238,29 +2193,27 @@ CDF_STATUS wlansap_register_mgmt_frame void *hHal = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", - __func__, hHal, pSapCtx->isSapSessionOpen); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = sme_register_mgmt_frame(hHal, pSapCtx->sessionId, - frameType, matchData, - matchLen); + cdf_ret_status = sme_register_mgmt_frame(hHal, pSapCtx->sessionId, + frameType, matchData, + matchLen); - if (CDF_STATUS_SUCCESS == cdf_ret_status) { - return CDF_STATUS_SUCCESS; - } + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -2290,29 +2243,27 @@ CDF_STATUS wlansap_de_register_mgmt_frame void *hHal = NULL; CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - if (CDF_SAP_MODE == cds_get_conparam()) { - pSapCtx = CDS_GET_SAP_CB(pCtx); - if (NULL == pSapCtx) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: Invalid SAP pointer from pCtx", - __func__); - return CDF_STATUS_E_FAULT; - } - hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); - if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", - __func__, hHal, pSapCtx->isSapSessionOpen); - return CDF_STATUS_E_FAULT; - } + pSapCtx = CDS_GET_SAP_CB(pCtx); + if (NULL == pSapCtx) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pCtx", + __func__); + return CDF_STATUS_E_FAULT; + } + hHal = CDS_GET_HAL_CB(pSapCtx->p_cds_gctx); + if ((NULL == hHal) || (eSAP_TRUE != pSapCtx->isSapSessionOpen)) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: HAL pointer (%p) NULL OR SME session is not open (%d)", + __func__, hHal, pSapCtx->isSapSessionOpen); + return CDF_STATUS_E_FAULT; + } - cdf_ret_status = - sme_deregister_mgmt_frame(hHal, pSapCtx->sessionId, frameType, - matchData, matchLen); + cdf_ret_status = + sme_deregister_mgmt_frame(hHal, pSapCtx->sessionId, frameType, + matchData, matchLen); - if (CDF_STATUS_SUCCESS == cdf_ret_status) { - return CDF_STATUS_SUCCESS; - } + if (CDF_STATUS_SUCCESS == cdf_ret_status) { + return CDF_STATUS_SUCCESS; } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 954458eb4c52..af46ebc441da 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -408,7 +408,7 @@ typedef struct tagCsrScanResultFilter { */ uint8_t scan_filter_for_roam; struct sCsrChannel_ pcl_channels; - tCDF_CON_MODE csrPersona; + enum tCDF_ADAPTER_MODE csrPersona; } tCsrScanResultFilter; typedef struct sCsrChnPower_ { @@ -951,7 +951,7 @@ typedef struct tagCsrRoamProfile { #ifdef WLAN_FEATURE_VOWIFI_11R tCsrMobilityDomainInfo MDID; #endif - tCDF_CON_MODE csrPersona; + enum tCDF_ADAPTER_MODE csrPersona; uint8_t disableDFSChSwitch; /* addIe params */ tSirAddIeParams addIeParams; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 89abb9d49482..bc82612bcdfd 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -346,7 +346,7 @@ typedef struct tagCsrRoamStartBssParams { uint8_t ApUapsdEnable; uint8_t ssidHidden; uint8_t wps_state; - tCDF_CON_MODE bssPersona; + enum tCDF_ADAPTER_MODE bssPersona; uint16_t nRSNIELength; /* If 0, pRSNIE is ignored. */ uint8_t *pRSNIE; /* If not null, it has IE byte stream for RSN */ /* Flag used to indicate update beaconInterval */ @@ -429,7 +429,7 @@ typedef struct tagWmStatusChangeCmd { typedef struct tagAddStaForSessionCmd { /* Session self mac addr */ tSirMacAddr selfMacAddr; - tCDF_CON_MODE currDeviceMode; + enum tCDF_ADAPTER_MODE currDeviceMode; uint32_t type; uint32_t subType; uint8_t sessionId; @@ -1405,4 +1405,6 @@ CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal pMac, bool csr_wait_for_connection_update(tpAniSirGlobal mac, bool do_release_reacquire_lock); +enum tCDF_ADAPTER_MODE csr_get_session_persona(tpAniSirGlobal pmac, + uint32_t session_id); #endif diff --git a/core/sme/inc/csr_support.h b/core/sme/inc/csr_support.h index f62c5a2a85fc..58d62f90d14a 100644 --- a/core/sme/inc/csr_support.h +++ b/core/sme/inc/csr_support.h @@ -356,11 +356,11 @@ CDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId, uint32_t *pRoamId, bool fForce); CDF_STATUS csr_isconcurrentsession_valid(tpAniSirGlobal pMac, - uint32_t cursessionId, tCDF_CON_MODE currBssPersona); + uint32_t cursessionId, enum tCDF_ADAPTER_MODE currBssPersona); /* BeaconInterval validation for MCC support */ CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channelId, uint16_t *beaconInterval, uint32_t cursessionId, - tCDF_CON_MODE currBssPersona); + enum tCDF_ADAPTER_MODE currBssPersona); #ifdef WLAN_FEATURE_VOWIFI_11R bool csr_is_profile11r(tCsrRoamProfile *pProfile); bool csr_is_auth_type11r(eCsrAuthType AuthType, uint8_t mdiePresent); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9e8c40e1d845..a00d847576b8 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -233,7 +233,8 @@ CDF_STATUS sme_open_session(tHalHandle hHal, csr_roam_completeCallback callback, void *pContext, uint8_t *pSelfMacAddr, uint8_t *pbSessionId, uint32_t type, uint32_t subType); -void sme_set_curr_device_mode(tHalHandle hHal, tCDF_CON_MODE currDeviceMode); +void sme_set_curr_device_mode(tHalHandle hHal, + enum tCDF_ADAPTER_MODE currDeviceMode); CDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId, csr_roamSessionCloseCallback callback, void *pContext); @@ -558,7 +559,7 @@ CDF_STATUS sme_set_max_tx_power(tHalHandle hHal, struct cdf_mac_addr pBssid, CDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t db); CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, struct cdf_mac_addr bssid, - tCDF_CON_MODE dev_mode, int power); + enum tCDF_ADAPTER_MODE dev_mode, int power); CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr); CDF_STATUS sme_hide_ssid(tHalHandle hHal, uint8_t sessionId, uint8_t ssidHidden); diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index eb1915f10fb8..9c0437b7f4e4 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -148,7 +148,7 @@ typedef struct tagSmeStruct { tDblLinkList smeCmdActiveList; tDblLinkList smeCmdPendingList; tDblLinkList smeCmdFreeList; /* preallocated roam cmd list */ - tCDF_CON_MODE currDeviceMode; + enum tCDF_ADAPTER_MODE currDeviceMode; #ifdef FEATURE_WLAN_LPHB void (*pLphbIndCb)(void *pHddCtx, tSirLPHBInd *indParam); #endif /* FEATURE_WLAN_LPHB */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a6c41260ecc6..5178a8de8521 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -7822,8 +7822,8 @@ CDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr) \- return CDF_STATUS ---------------------------------------------------------------------------*/ CDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId, - struct cdf_mac_addr pBSSId, - tCDF_CON_MODE dev_mode, int dBm) + struct cdf_mac_addr pBSSId, + enum tCDF_ADAPTER_MODE dev_mode, int dBm) { cds_msg_t msg; tpMaxTxPowerParams pTxParams = NULL; @@ -10428,7 +10428,8 @@ ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value) \param currDeviceMode - Current operating device mode. --------------------------------------------------------------------------*/ -void sme_set_curr_device_mode(tHalHandle hHal, tCDF_CON_MODE currDeviceMode) +void sme_set_curr_device_mode(tHalHandle hHal, + enum tCDF_ADAPTER_MODE currDeviceMode) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); pMac->sme.currDeviceMode = currDeviceMode; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index eb325093529b..f22cf8dac2a1 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -263,7 +263,8 @@ void csr_roam_remove_entry_from_pe_stats_req_list(tpAniSirGlobal pMac, tListElem *csr_roam_find_in_pe_stats_req_list(tpAniSirGlobal pMac, uint32_t statsMask); CDF_STATUS csr_roam_dereg_statistics_req(tpAniSirGlobal pMac); static uint32_t csr_find_ibss_session(tpAniSirGlobal pMac); -static uint32_t csr_find_session_by_type(tpAniSirGlobal, tCDF_CON_MODE); +static uint32_t csr_find_session_by_type(tpAniSirGlobal, + enum tCDF_ADAPTER_MODE); 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 CDF_STATUS csr_roam_start_wds(tpAniSirGlobal pMac, uint32_t sessionId, @@ -4162,8 +4163,11 @@ CDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal pMac, uint32_t sessionId, /* 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 (csr_learn_11dcountry_information(pMac, pBssDesc, pIes, true)) { - csr_apply_country_information(pMac); + if ((CDF_SAP_MODE != + csr_get_session_persona(pMac, sessionId)) && + csr_learn_11dcountry_information( + pMac, pBssDesc, pIes, true)) { + csr_apply_country_information(pMac); } if ((csr_is11d_supported(pMac)) && pIes) { if (!pIes->Country.present) { @@ -18545,7 +18549,7 @@ void csr_init_operating_classes(tHalHandle hHal) * Return: session id for give session type. **/ static uint32_t -csr_find_session_by_type(tpAniSirGlobal mac_ctx, tCDF_CON_MODE type) +csr_find_session_by_type(tpAniSirGlobal mac_ctx, enum tCDF_ADAPTER_MODE type) { uint32_t i, session_id = CSR_SESSION_ID_INVALID; tCsrRoamSession *session_ptr; diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 93866115f04a..95da9e7dd1b9 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -3559,9 +3559,6 @@ bool csr_learn_11dcountry_information(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIesLocal = pIes; bool useVoting = false; - if (CDF_SAP_MODE == cds_get_conparam()) - return CDF_STATUS_SUCCESS; - if ((NULL == pSirBssDesc) && (NULL == pIes)) useVoting = true; diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 8b32fe94bd1d..527c4d4090f7 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -451,7 +451,7 @@ uint8_t csr_get_concurrent_operation_channel(tpAniSirGlobal mac_ctx) { tCsrRoamSession *session = NULL; uint8_t i = 0; - tCDF_CON_MODE persona; + enum tCDF_ADAPTER_MODE persona; for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { if (!CSR_IS_SESSION_VALID(mac_ctx, i)) @@ -855,7 +855,7 @@ bool csr_is_p2p_session_connected(tpAniSirGlobal pMac) { uint32_t i; tCsrRoamSession *pSession = NULL; - tCDF_CON_MODE persona; + enum tCDF_ADAPTER_MODE persona; for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { if (CSR_IS_SESSION_VALID(pMac, i) @@ -1888,10 +1888,10 @@ bool csr_is_profile_rsn(tCsrRoamProfile *pProfile) */ CDF_STATUS csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, - tCDF_CON_MODE cur_bss_persona) + enum tCDF_ADAPTER_MODE cur_bss_persona) { uint32_t sessionid = 0; - tCDF_CON_MODE bss_persona; + enum tCDF_ADAPTER_MODE bss_persona; eCsrConnectState connect_state, temp; tCsrRoamSession *roam_session; @@ -2096,10 +2096,11 @@ uint16_t csr_calculate_mcc_beacon_interval(tpAniSirGlobal pMac, uint16_t sta_bi, return go_fbi; } -CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, uint8_t channelId, - uint16_t *beaconInterval, - uint32_t cursessionId, - tCDF_CON_MODE currBssPersona) +CDF_STATUS csr_validate_mcc_beacon_interval(tpAniSirGlobal pMac, + uint8_t channelId, + uint16_t *beaconInterval, + uint32_t cursessionId, + enum tCDF_ADAPTER_MODE currBssPersona) { uint32_t sessionId = 0; uint16_t new_beaconInterval = 0; @@ -5717,3 +5718,24 @@ bool csr_wait_for_connection_update(tpAniSirGlobal mac, return true; } + +/** + * csr_get_session_persona() - get persona of a session + * @pmac: pointer to global MAC context + * @session_id: session id + * + * This function is to return the persona of a session + * + * Reture: enum tCDF_ADAPTER_MODE persona + */ +enum tCDF_ADAPTER_MODE csr_get_session_persona(tpAniSirGlobal pmac, + uint32_t session_id) +{ + tCsrRoamSession *session = NULL; + + session = CSR_GET_SESSION(pmac, session_id); + if (NULL == session || NULL == session->pCurRoamProfile) + return CDF_MAX_NO_OF_MODE; + + return session->pCurRoamProfile->csrPersona; +} diff --git a/core/utils/epping/inc/epping_internal.h b/core/utils/epping/inc/epping_internal.h index ee32b4c7d4aa..ab68c2b18b49 100644 --- a/core/utils/epping/inc/epping_internal.h +++ b/core/utils/epping/inc/epping_internal.h @@ -135,7 +135,7 @@ typedef enum { typedef struct epping_adapter_s { epping_context_t *pEpping_ctx; - tCDF_CON_MODE device_mode; + enum tCDF_ADAPTER_MODE device_mode; /** Handle to the network device */ struct net_device *dev; struct cdf_mac_addr macAddressCurrent; @@ -183,7 +183,7 @@ void epping_refill(void *ctx, HTC_ENDPOINT_ID Endpoint); /* epping_txrx signatures */ epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx, tSirMacAddr macAddr, - tCDF_CON_MODE device_mode); + enum tCDF_ADAPTER_MODE device_mode); void epping_destroy_adapter(epping_adapter_t *pAdapter); int epping_connect_service(epping_context_t *pEpping_ctx); #ifdef HIF_PCI diff --git a/core/utils/epping/src/epping_txrx.c b/core/utils/epping/src/epping_txrx.c index 240d43aede81..6cb31924671a 100644 --- a/core/utils/epping/src/epping_txrx.c +++ b/core/utils/epping/src/epping_txrx.c @@ -342,7 +342,7 @@ static struct net_device_ops epping_drv_ops = { epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx, tSirMacAddr macAddr, - tCDF_CON_MODE device_mode) + enum tCDF_ADAPTER_MODE device_mode) { struct net_device *dev; epping_adapter_t *pAdapter; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 3428297832b1..482b800b298f 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1161,7 +1161,7 @@ typedef struct sMaxTxPowerParams { * power == tx power used for management frames. */ tPowerdBm power; - tCDF_CON_MODE dev_mode; + enum tCDF_ADAPTER_MODE dev_mode; } tMaxTxPowerParams, *tpMaxTxPowerParams; /** @@ -1185,7 +1185,7 @@ typedef struct sMaxTxPowerPerBandParams { */ struct add_sta_self_params { tSirMacAddr self_mac_addr; - tCDF_CON_MODE curr_device_mode; + enum tCDF_ADAPTER_MODE curr_device_mode; uint32_t type; uint32_t sub_type; uint8_t session_id; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 59253b83a016..07263102f653 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1558,7 +1558,7 @@ CDF_STATUS wma_open(void *cds_context, cdf_mem_zero(wma_handle, sizeof(t_wma_handle)); - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { #ifdef FEATURE_WLAN_SCAN_PNO cdf_wake_lock_init(&wma_handle->pno_wake_lock, "wlan_pno_wl"); #endif /* FEATURE_WLAN_SCAN_PNO */ @@ -1645,7 +1645,7 @@ CDF_STATUS wma_open(void *cds_context, goto err_wmi_handle; } #if defined(QCA_WIFI_FTM) - if (cds_get_conparam() == CDF_FTM_MODE) + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) wma_utf_attach(wma_handle); #endif /* QCA_WIFI_FTM */ @@ -1951,7 +1951,7 @@ err_wmi_handle: err_wma_handle: - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { #ifdef FEATURE_WLAN_SCAN_PNO cdf_wake_lock_destroy(&wma_handle->pno_wake_lock); #endif /* FEATURE_WLAN_SCAN_PNO */ @@ -2676,7 +2676,7 @@ CDF_STATUS wma_start(void *cds_ctx) * Tx mgmt attach requires TXRX context which is not created * in FTM mode. So skip the TX mgmt attach. */ - if (cds_get_conparam() == CDF_FTM_MODE) + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) goto end; #endif /* QCA_WIFI_FTM */ @@ -2779,7 +2779,7 @@ CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) * Tx mgmt detach requires TXRX context which is not created * in FTM mode. So skip the TX mgmt detach. */ - if (cds_get_conparam() == CDF_FTM_MODE) { + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) { cdf_status = CDF_STATUS_SUCCESS; goto end; } @@ -3044,7 +3044,7 @@ CDF_STATUS wma_close(void *cds_ctx) wma_handle->saved_wmi_init_cmd.buf = NULL; } - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { #ifdef FEATURE_WLAN_SCAN_PNO cdf_wake_lock_destroy(&wma_handle->pno_wake_lock); #endif /* FEATURE_WLAN_SCAN_PNO */ @@ -3083,7 +3083,7 @@ CDF_STATUS wma_close(void *cds_ctx) #if defined(QCA_WIFI_FTM) /* Detach UTF and unregister the handler */ - if (cds_get_conparam() == CDF_FTM_MODE) + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) wma_utf_detach(wma_handle); #endif /* QCA_WIFI_FTM */ diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 2373f92a8a13..9d4d402c4df4 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3297,7 +3297,7 @@ CDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx) tp_wma_handle wma_handle; #ifdef QCA_WIFI_FTM - if (cds_get_conparam() == CDF_FTM_MODE) + if (cds_get_conparam() == CDF_GLOBAL_FTM_MODE) return CDF_STATUS_SUCCESS; #endif diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index bb027532b8d7..5ab134190a24 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -2550,7 +2550,7 @@ wma_process_ftm_command(tp_wma_handle wma_handle, if (!msg_buffer) return CDF_STATUS_E_INVAL; - if (cds_get_conparam() != CDF_FTM_MODE) { + if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE) { WMA_LOGE("FTM command issued in non-FTM mode"); cdf_mem_free(msg_buffer->data); cdf_mem_free(msg_buffer); -- cgit v1.2.3 From 67bc5525855c1041d1666d9572246919fe2b64ab Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Fri, 16 Oct 2015 16:02:26 -0700 Subject: qcacld-3.0: Vendor command to scale TX power This is for FR23278: Runtime configuration of softAP Tx power. The value that send by the vendor command will set the power levels as below: 0 --- no scaling, 100% 1 --- 50% of max power 2 --- 25% of max power 3 --- 12% of max power 4 --- minimum power Another vendor command is to decrease the power by actual db value. CRs-fixed: 941772 Change-Id: I61d48299b4af361c214e2ab8bb1fa848161431de --- core/hdd/src/wlan_hdd_cfg80211.c | 173 +++++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 39 +++++++++ core/wma/inc/wma_api.h | 2 + core/wma/src/wma_power.c | 59 +++++++++++++ 4 files changed, 273 insertions(+) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index cd1a4864978a..493b6e867bff 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -138,6 +138,8 @@ #define HDD_CHANNEL_14 14 +#define MAX_TXPOWER_SCALE 4 + static const u32 hdd_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -4604,6 +4606,161 @@ static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy, return ret; } +/** + * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling + * @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_txpower_scale(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 = NULL; + int ret = 0; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1]; + uint8_t scale_value; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX, + data, data_len, NULL)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) { + hdd_err("attr tx power scale failed"); + return -EINVAL; + } + + scale_value = nla_get_u8(tb + [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]); + + if (scale_value > MAX_TXPOWER_SCALE) { + hdd_err("Invalid tx power scale level"); + return -EINVAL; + } + + ret = wma_set_tx_power_scale(adapter->sessionId, scale_value); + + if (ret != 0) { + hdd_err("Set tx power scale failed"); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_txpower_scale () - txpower scaling + * @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_txpower_scale(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling + * @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_txpower_scale_decr_db(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 = NULL; + int ret = 0; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1]; + uint8_t scale_value; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX, + data, data_len, NULL)) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) { + hdd_err("attr tx power decrease db value failed"); + return -EINVAL; + } + + scale_value = nla_get_u8(tb + [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]); + + ret = wma_set_tx_power_scale_decr_db(adapter->sessionId, scale_value); + + if (ret != 0) { + hdd_err("Set tx power decrease db failed"); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling + * @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_txpower_scale_decr_db(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret = 0; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev, + data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -5042,6 +5199,22 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { .doit = wlan_hdd_cfg80211_set_gateway_params }, #endif /* FEATURE_LFR_SUBNET_DETECTION */ + { + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_txpower_scale + }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_txpower_scale_decr_db + }, }; /* diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 06718f634fdc..0f24a05691bd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -250,6 +250,8 @@ typedef enum { * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete * @QCA_NL80211_VENDOR_SUBCMD_OTA_TEST: enable OTA test * @QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG: set gateway parameters + * @QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE: set tx power by percentage + * @QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB: reduce tx power by DB */ enum qca_nl80211_vendor_subcmds { @@ -364,6 +366,10 @@ enum qca_nl80211_vendor_subcmds { /* OTA test subcommand */ QCA_NL80211_VENDOR_SUBCMD_OTA_TEST = 108, + /* Tx power scaling subcommands */ + QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE = 109, + /* Tx power scaling in db subcommands */ + QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB = 115, }; @@ -2219,6 +2225,39 @@ enum qca_vendor_attr_ota_test { QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST - 1 }; +/** enum qca_vendor_attr_txpower_scale - vendor sub commands index + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_INVALID: invalid value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE: scaling value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST: last value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX: max value + */ +enum qca_vendor_attr_txpower_scale { + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_INVALID, + /* 8-bit unsigned value to indicate the scaling of tx power */ + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX = + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST - 1 +}; + +/** + * enum qca_vendor_attr_txpower_scale_decr_db - vendor sub commands index + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_INVALID: invalid value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB: scaling value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_AFTER_LAST: last value + * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX: max value + */ +enum qca_vendor_attr_txpower_scale_decr_db { + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_INVALID, + /* 8-bit unsigned value to indicate the scaling of tx power */ + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX = + QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_AFTER_LAST - 1 +}; + struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 5990477e7ee9..f04500e45ee2 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -235,4 +235,6 @@ static inline CDF_STATUS wma_send_egap_conf_params(WMA_HANDLE handle, return CDF_STATUS_E_NOSUPPORT; } #endif +CDF_STATUS wma_set_tx_power_scale(uint8_t vdev_id, int value); +CDF_STATUS wma_set_tx_power_scale_decr_db(uint8_t vdev_id, int value); #endif diff --git a/core/wma/src/wma_power.c b/core/wma/src/wma_power.c index 72d77b800d97..3793675ca3c4 100644 --- a/core/wma/src/wma_power.c +++ b/core/wma/src/wma_power.c @@ -2252,3 +2252,62 @@ void wma_set_resume_dtim(tp_wma_handle wma) } } +/** + * wma_set_tx_power_scale() - set tx power scale + * @vdev_id: vdev id + * @value: value + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_set_tx_power_scale(uint8_t vdev_id, int value) +{ + int ret = CDF_STATUS_SUCCESS; + tp_wma_handle wma_handle = + (tp_wma_handle)cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == wma_handle) { + WMA_LOGE("%s: wma_handle is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (!(wma_handle->interfaces[vdev_id].vdev_up)) { + WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id); + return CDF_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TXPOWER_SCALE, value); + if (ret != 0) + WMA_LOGE("Set tx power scale failed"); + + return ret; +} + +/** + * wma_set_tx_power_scale_decr_db() - decrease power by DB value + * @vdev_id: vdev id + * @value: value + * + * Return: CDF_STATUS_SUCCESS for success or error code. + */ +CDF_STATUS wma_set_tx_power_scale_decr_db(uint8_t vdev_id, int value) +{ + int ret = CDF_STATUS_SUCCESS; + tp_wma_handle wma_handle = + (tp_wma_handle)cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == wma_handle) { + WMA_LOGE("%s: wma_handle is NULL", __func__); + return CDF_STATUS_E_FAILURE; + } + + if (!(wma_handle->interfaces[vdev_id].vdev_up)) { + WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id); + return CDF_STATUS_E_FAILURE; + } + + ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, vdev_id, + WMI_VDEV_PARAM_TXPOWER_SCALE_DECR_DB, value); + if (ret != 0) + WMA_LOGE("Decrease tx power value failed"); + + return ret; +} -- cgit v1.2.3 From b5bc04a6e80e96a5f821cb1100a3e560c7950681 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Tue, 29 Dec 2015 17:05:52 -0800 Subject: Release 5.0.0.154 Release 5.0.0.154 Change-Id: I90325f3ebc5cbbc70c3d4fc24060f6acc94e2beb CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 1dc8a2a9308e..b2f1445f0799 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 153 +#define QWLAN_VERSION_BUILD 154 -#define QWLAN_VERSIONSTR "5.0.0.153" +#define QWLAN_VERSIONSTR "5.0.0.154" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From dbf709a2e9d3bc0381a808e40a64febea4ee1282 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Thu, 17 Dec 2015 12:22:02 -0800 Subject: qcacld-3.0: fix regression for STA PNO WoW qcacld-2.0 to qcacld-3.0 propagation This is to fix the regression in the case of suspend request. Below patch overkills the case for PNO and extscan in progress. Commit Subject: "Fix the PNO WoW is not configured in concurrency case" change id: I97084cfde73025f0d09b60616959c9530ba82c80 The combined condition check should be maintained to check the case for PNO or extscan in progress, otherwise the WoW would be enabled in the case PNO in progress is not enabled, and end up not setting PNO patterns and failed to reconnect after resume. Change-Id: Icc5f19d07abea9fb25479452ce1c467d7811317c CRs-fixed: 953257 --- core/wma/src/wma_features.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 1163ccab0b88..a35a58490061 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3965,7 +3965,7 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable); } - if (!enable_wow) { + 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"); cdf_mem_free(info); goto send_ready_to_suspend; -- cgit v1.2.3 From d6c020bb965b418acc6fa75628ed9c6b2a97f279 Mon Sep 17 00:00:00 2001 From: Orhan K AKYILDIZ Date: Wed, 30 Dec 2015 12:35:44 -0800 Subject: qcacld-3.0: fix softlock-up caused by co-existence of NAPI and rx-thread. If rxthread is on, NAPI will call the kernel-thread context API (instead of softirq context) API to transfer the packet to the stack. Eventually, this part will be re-considered when multi-queue NAPI gets in, which will eliminate the rx-thread. Change-Id: Ib3d4d1450fb36f5c1e710802ceaab5d015e20c7d CRs-Fixed: 957299 --- core/hdd/src/wlan_hdd_softap_tx_rx.c | 4 ++-- core/hdd/src/wlan_hdd_tx_rx.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index f50b582a6499..03e4392123b9 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -581,7 +581,7 @@ CDF_STATUS hdd_softap_rx_packet_cbk(void *cds_context, */ cdf_net_buf_debug_release_skb(rxBuf); - if (hdd_napi_enabled(HDD_NAPI_ANY)) + if (hdd_napi_enabled(HDD_NAPI_ANY) && !pHddCtx->config->enableRxThread) rxstat = netif_receive_skb(skb); else rxstat = netif_rx_ni(skb); diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 7479870fd3b4..2d8b0de8ca95 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -744,7 +744,8 @@ CDF_STATUS hdd_rx_packet_cbk(void *cds_context, cdf_nbuf_t rxBuf, uint8_t staId) if (HDD_LRO_NO_RX == hdd_lro_rx(pHddCtx, pAdapter, skb)) { - if (hdd_napi_enabled(HDD_NAPI_ANY)) + if (hdd_napi_enabled(HDD_NAPI_ANY) && + !pHddCtx->config->enableRxThread) rxstat = netif_receive_skb(skb); else rxstat = netif_rx_ni(skb); -- cgit v1.2.3 From 25aac8b878e686dff633af420500cad83433f910 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Mon, 28 Dec 2015 17:14:36 -0800 Subject: qcacld-3.0: cleanup cds_concurrency files Remove hdd context from argument list of all the cds concurrency APIs. Change-Id: Ic9f94ab2e0f975a745776675c254ecbd5ba6b203 CRs-fixed: 956394 --- core/cds/inc/cds_concurrency.h | 234 +++-------- core/cds/src/cds_concurrency.c | 839 ++++++++++++++++++++++++--------------- core/hdd/src/wlan_hdd_assoc.c | 29 +- core/hdd/src/wlan_hdd_cfg80211.c | 26 +- core/hdd/src/wlan_hdd_conc_ut.c | 36 +- core/hdd/src/wlan_hdd_hostapd.c | 32 +- core/hdd/src/wlan_hdd_ioctl.c | 4 +- core/hdd/src/wlan_hdd_main.c | 26 +- core/hdd/src/wlan_hdd_p2p.c | 5 +- core/hdd/src/wlan_hdd_scan.c | 4 +- core/hdd/src/wlan_hdd_wext.c | 22 +- core/sme/src/csr/csr_api_scan.c | 8 +- 12 files changed, 669 insertions(+), 596 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 85af14772adb..eead3b645b0b 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -463,139 +463,30 @@ struct cds_conc_connection_info { bool in_use; }; -bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx); -void cds_dump_concurrency_info(hdd_context_t *pHddCtx); -void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode); -void cds_clear_concurrency_mode(hdd_context_t *pHddCtx, - enum tCDF_ADAPTER_MODE mode); -uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); -/** - * cds_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 -cds_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; -} - -/** - * cds_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 -cds_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); -} - -/** - * cds_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 -cds_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; -} - -/** - * cds_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 -cds_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); -} - -/** - * cds_set_connection_in_progress() - to set the connection in progress flag - * @hdd_ctx: pointer to hdd context - * @value: value to set - * - * This function will set the passed value to connection in progress flag. - * If value is previously being set to true then no need to set it again. - * - * Return: true if value is being set correctly and false otherwise. - */ -static inline bool -cds_set_connection_in_progress(hdd_context_t *hdd_ctx, - bool value) -{ - bool status = true; - spin_lock(&hdd_ctx->connection_status_lock); - /* - * if the value is set to true previously and if someone is - * trying to make it true again then it could be some race - * condition being triggered. Avoid this situation by returning - * false - */ - if (hdd_ctx->connection_in_progress && value) - status = false; - else - hdd_ctx->connection_in_progress = value; - spin_unlock(&hdd_ctx->connection_status_lock); - return status; -} - - +bool cds_is_connection_in_progress(void); +void cds_dump_concurrency_info(void); +void cds_set_concurrency_mode(enum tCDF_ADAPTER_MODE mode); +void cds_clear_concurrency_mode(enum tCDF_ADAPTER_MODE mode); +uint32_t cds_get_connection_count(void); +bool cds_is_sta_connection_pending(void); +void cds_change_sta_conn_pending_status(bool value); +void cds_change_sap_restart_required_status(bool value); +bool cds_set_connection_in_progress(bool value); int cds_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); uint32_t cds_get_concurrency_mode(void); -CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, - eCsrRoamResult roam_result, +CDF_STATUS cds_check_and_restart_sap(eCsrRoamResult roam_result, hdd_station_ctx_t *hdd_sta_ctx); -void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, - hdd_adapter_t *adapter, +void cds_handle_conc_rule1(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile); #ifdef FEATURE_WLAN_CH_AVOID -bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, - hdd_adapter_t *adapter, +bool cds_handle_conc_rule2(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint32_t *roam_id); #else -static inline bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, - hdd_adapter_t *adapter, +static inline bool cds_handle_conc_rule2(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint32_t *roam_id) { @@ -608,10 +499,9 @@ bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel); CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); #ifdef FEATURE_WLAN_FORCE_SAP_SCC -void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result); +void cds_force_sap_on_scc(eCsrRoamResult roam_result); #else -static inline void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, - eCsrRoamResult roam_result) +static inline void cds_force_sap_on_scc(eCsrRoamResult roam_result) { } @@ -619,19 +509,17 @@ static inline void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH void cds_check_concurrent_intf_and_restart_sap( - hdd_context_t *hdd_ctx, hdd_station_ctx_t *hdd_sta_ctx, hdd_adapter_t *adapter); #else static inline void cds_check_concurrent_intf_and_restart_sap( - hdd_context_t *hdd_ctx, hdd_station_ctx_t *hdd_sta_ctx, hdd_adapter_t *adapter) { } #endif /* FEATURE_WLAN_MCC_TO_SCC_SWITCH */ -uint8_t cds_is_mcc_in_24G(hdd_context_t *hdd_ctx); +uint8_t cds_is_mcc_in_24G(void); int32_t cds_set_mas(hdd_adapter_t *adapter, uint8_t mas_value); int cds_set_mcc_p2p_quota(hdd_adapter_t *hostapd_adapter, uint32_t set_value); @@ -652,61 +540,47 @@ static inline void cds_restart_sap(hdd_adapter_t *ap_adapter) */ #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE -void cds_check_and_restart_sap_with_non_dfs_acs(hdd_context_t *hdd_ctx); +void cds_check_and_restart_sap_with_non_dfs_acs(void); #else -static inline void cds_check_and_restart_sap_with_non_dfs_acs( - hdd_context_t *hdd_ctx) +static inline void cds_check_and_restart_sap_with_non_dfs_acs(void) { } #endif /* FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE */ -void cds_incr_active_session(hdd_context_t *pHddCtx, - enum tCDF_ADAPTER_MODE mode, +void cds_incr_active_session(enum tCDF_ADAPTER_MODE mode, uint8_t sessionId); -void cds_decr_active_session(hdd_context_t *pHddCtx, - enum tCDF_ADAPTER_MODE mode, +void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, uint8_t sessionId); -void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode, +void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, uint8_t session_id); -CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx); -CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, +CDF_STATUS cds_init_policy_mgr(void); +CDF_STATUS cds_get_pcl(enum cds_con_mode mode, uint8_t *pcl_Channels, uint32_t *len); -bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, +bool cds_allow_concurrency(enum cds_con_mode mode, uint8_t channel, enum hw_mode_bandwidth bw); -enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( - hdd_context_t *hdd_ctx); -enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( - hdd_context_t *hdd_ctx); -enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( - hdd_context_t *hdd_ctx); -CDF_STATUS cds_mode_switch_dbs_to_mcc(hdd_context_t *hdd_ctx); -CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx); -CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, - uint32_t vdev_id); -CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, - uint32_t vdev_id); -CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, - uint32_t vdev_id); +enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index(void); +enum cds_one_connection_mode cds_get_second_connection_pcl_table_index(void); +enum cds_two_connection_mode cds_get_third_connection_pcl_table_index(void); +CDF_STATUS cds_incr_connection_count(uint32_t vdev_id); +CDF_STATUS cds_update_connection_info(uint32_t vdev_id); +CDF_STATUS cds_decr_connection_count(uint32_t vdev_id); CDF_STATUS cds_current_connections_update(uint32_t session_id, uint8_t channel, enum cds_conn_update_reason); -bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel); +bool cds_is_ibss_conn_exist(uint8_t *ibss_channel); #ifdef MPC_UT_FRAMEWORK -CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, +CDF_STATUS cds_incr_connection_count_utfw( uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id); -CDF_STATUS cds_update_connection_info_utfw(hdd_context_t *hdd_ctx, +CDF_STATUS cds_update_connection_info_utfw( uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id); -CDF_STATUS cds_decr_connection_count_utfw(hdd_context_t *hdd_ctx, +CDF_STATUS cds_decr_connection_count_utfw( uint32_t del_all, uint32_t vdev_id); -struct cds_conc_connection_info *cds_get_conn_info(hdd_context_t *hdd_ctx, - uint32_t *len); -enum cds_pcl_type get_pcl_from_first_conn_table( - enum cds_con_mode type, +struct cds_conc_connection_info *cds_get_conn_info(uint32_t *len); +enum cds_pcl_type get_pcl_from_first_conn_table(enum cds_con_mode type, enum cds_conc_priority_mode sys_pref); enum cds_pcl_type get_pcl_from_second_conn_table( enum cds_one_connection_mode idx, enum cds_con_mode type, @@ -715,39 +589,33 @@ enum cds_pcl_type get_pcl_from_third_conn_table( enum cds_two_connection_mode idx, enum cds_con_mode type, enum cds_conc_priority_mode sys_pref, uint8_t dbs_capable); #else -static inline CDF_STATUS cds_incr_connection_count_utfw( - hdd_context_t *hdd_ctx, uint32_t vdev_id, +static inline CDF_STATUS cds_incr_connection_count_utfw(uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { return CDF_STATUS_SUCCESS; } -static inline CDF_STATUS cds_update_connection_info_utfw( - hdd_context_t *hdd_ctx, uint32_t vdev_id, +static inline CDF_STATUS cds_update_connection_info_utfw(uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { return CDF_STATUS_SUCCESS; } -static inline CDF_STATUS cds_decr_connection_count_utfw( - hdd_context_t *hdd_ctx, - uint32_t del_all, uint32_t vdev_id) +static inline CDF_STATUS cds_decr_connection_count_utfw(uint32_t del_all, + uint32_t vdev_id) { return CDF_STATUS_SUCCESS; } -static inline struct cds_conc_connection_info *cds_get_conn_info( - hdd_context_t *hdd_ctx, uint32_t *len) +static inline struct cds_conc_connection_info *cds_get_conn_info(uint32_t *len) { return NULL; } #endif enum cds_con_mode cds_convert_device_mode_to_hdd_type( device_mode_t device_mode); -uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx); -CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, - uint32_t session_id, +CDF_STATUS cds_soc_set_hw_mode(uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, @@ -755,24 +623,20 @@ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, enum hw_mode_dbs_capab dbs, enum hw_mode_agile_dfs_capab dfs, enum cds_conn_update_reason reason); -enum cds_conc_next_action cds_need_opportunistic_upgrade( - hdd_context_t *hdd_ctx); -CDF_STATUS cds_next_actions( - hdd_context_t *hdd_ctx, uint32_t session_id, +enum cds_conc_next_action cds_need_opportunistic_upgrade(void); +CDF_STATUS cds_next_actions(uint32_t session_id, enum cds_conc_next_action action, enum cds_conn_update_reason reason); -void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, - uint8_t dbs_val, +void cds_set_dual_mac_scan_config(uint8_t dbs_val, uint8_t dbs_plus_agile_scan_val, uint8_t single_mac_scan_with_dbs_val); -void cds_set_dual_mac_fw_mode_config(hdd_context_t *hdd_ctx, - uint8_t dbs, +void cds_set_dual_mac_fw_mode_config(uint8_t dbs, uint8_t dfs); void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, uint32_t scan_config, uint32_t fw_mode_config); -bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE *old_mode, enum cds_con_mode *new_mode); +bool cds_map_concurrency_mode(enum tCDF_ADAPTER_MODE *old_mode, + enum cds_con_mode *new_mode); CDF_STATUS cds_get_channel_from_scan_result(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint8_t *channel); diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index ffb9a05ded2d..db5eb6cf8ee7 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1908,6 +1908,139 @@ next_action_three_connection_table[CDS_MAX_TWO_CONNECTION_MODE] }; +/** + * cds_is_sta_connection_pending() - This function will check if sta connection + * is pending or not. + * + * This function will return the status of flag is_sta_connection_pending + * + * Return: true or false + */ +bool cds_is_sta_connection_pending(void) +{ + bool status; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + + 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; +} + +/** + * cds_change_sta_conn_pending_status() - This function will change the value + * of is_sta_connection_pending + * @value: value to set + * + * This function will change the value of is_sta_connection_pending + * + * Return: none + */ +void cds_change_sta_conn_pending_status(bool value) +{ + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + + spin_lock(&hdd_ctx->sta_update_info_lock); + hdd_ctx->is_sta_connection_pending = value; + spin_unlock(&hdd_ctx->sta_update_info_lock); +} + +/** + * cds_is_sap_restart_required() - This function will check if sap restart + * is pending or not. + * + * This function will return the status of flag is_sap_restart_required. + * + * Return: true or false + */ +static bool cds_is_sap_restart_required(void) +{ + bool status; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + + 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; +} + +/** + * cds_change_sap_restart_required_status() - This function will change the + * value of is_sap_restart_required + * @value: value to set + * + * This function will change the value of is_sap_restart_required + * + * Return: none + */ +void cds_change_sap_restart_required_status(bool value) +{ + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + + spin_lock(&hdd_ctx->sap_update_info_lock); + hdd_ctx->is_sap_restart_required = value; + spin_unlock(&hdd_ctx->sap_update_info_lock); +} + +/** + * cds_set_connection_in_progress() - to set the connection in progress flag + * @value: value to set + * + * This function will set the passed value to connection in progress flag. + * If value is previously being set to true then no need to set it again. + * + * Return: true if value is being set correctly and false otherwise. + */ +bool cds_set_connection_in_progress(bool value) +{ + bool status = true; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + + spin_lock(&hdd_ctx->connection_status_lock); + /* + * if the value is set to true previously and if someone is + * trying to make it true again then it could be some race + * condition being triggered. Avoid this situation by returning + * false + */ + if (hdd_ctx->connection_in_progress && value) + status = false; + else + hdd_ctx->connection_in_progress = value; + spin_unlock(&hdd_ctx->connection_status_lock); + return status; +} + /** * cds_update_conc_list() - Update the concurrent connection list * @conn_index: Connection index @@ -1954,7 +2087,6 @@ static void cds_update_conc_list(uint32_t conn_index, /** * cds_mode_specific_connection_count() - provides the * count of connections of specific mode - * @hdd_ctx: HDD Context * @mode: type of connection * @list: To provide the indices on conc_connection_list * (optional) @@ -1963,9 +2095,8 @@ static void cds_update_conc_list(uint32_t conn_index, * * Return: connection count of specific type */ -static uint32_t cds_mode_specific_connection_count(hdd_context_t *hdd_ctx, - enum cds_con_mode mode, - uint32_t *list) +static uint32_t cds_mode_specific_connection_count(enum cds_con_mode mode, + uint32_t *list) { uint32_t conn_index = 0, count = 0; for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; @@ -1982,7 +2113,6 @@ static uint32_t cds_mode_specific_connection_count(hdd_context_t *hdd_ctx, /** * cds_store_and_del_conn_info() - Store and del a connection info - * @hdd_ctx: HDD context * @mode: Mode whose entry has to be deleted * @info: Struture pointer where the connection info will be saved * @@ -1992,9 +2122,8 @@ static uint32_t cds_mode_specific_connection_count(hdd_context_t *hdd_ctx, * * Return: None */ -static void cds_store_and_del_conn_info(hdd_context_t *hdd_ctx, - enum cds_con_mode mode, - struct cds_conc_connection_info *info) +static void cds_store_and_del_conn_info(enum cds_con_mode mode, + struct cds_conc_connection_info *info) { uint32_t conn_index = 0; bool found = false; @@ -2016,7 +2145,7 @@ static void cds_store_and_del_conn_info(hdd_context_t *hdd_ctx, *info = conc_connection_list[conn_index]; /* Deleting the STA entry */ - cds_decr_connection_count(hdd_ctx, info->vdev_id); + cds_decr_connection_count(info->vdev_id); cds_info("Stored %d (%d), deleted STA entry with vdev id %d, index %d", info->vdev_id, info->mode, info->vdev_id, conn_index); @@ -2026,7 +2155,6 @@ static void cds_store_and_del_conn_info(hdd_context_t *hdd_ctx, /** * cds_restore_deleted_conn_info() - Restore connection info - * @hdd_ctx: HDD context * @info: Saved connection info that is to be restored * * Restores the connection info of STA that was saved before @@ -2034,12 +2162,12 @@ static void cds_store_and_del_conn_info(hdd_context_t *hdd_ctx, * * Return: None */ -static void cds_restore_deleted_conn_info(hdd_context_t *hdd_ctx, +static void cds_restore_deleted_conn_info( struct cds_conc_connection_info *info) { uint32_t conn_index; - conn_index = cds_get_connection_count(hdd_ctx); + conn_index = cds_get_connection_count(); if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { cds_err("Failed to restore the deleted information %d/%d", conn_index, MAX_NUMBER_OF_CONC_CONNECTIONS); @@ -2131,7 +2259,6 @@ void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, /** * cds_set_dual_mac_scan_config() - Set the dual MAC scan config - * @hdd_ctx: HDD context * @dbs_val: Value of DBS bit * @dbs_plus_agile_scan_val: Value of DBS plus agile scan bit * @single_mac_scan_with_dbs_val: Value of Single MAC scan with DBS @@ -2141,14 +2268,15 @@ void cds_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, * * Return: None */ -void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, - uint8_t dbs_val, +void cds_set_dual_mac_scan_config(uint8_t dbs_val, uint8_t dbs_plus_agile_scan_val, uint8_t single_mac_scan_with_dbs_val) { struct sir_dual_mac_config cfg; CDF_STATUS status; + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { cds_err("HDD context is NULL"); return; @@ -2193,7 +2321,6 @@ void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, /** * cds_set_dual_mac_fw_mode_config() - Set the dual mac FW mode config - * @hdd_ctx: HDD context * @dbs: DBS bit * @dfs: Agile DFS bit * @@ -2202,13 +2329,14 @@ void cds_set_dual_mac_scan_config(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_set_dual_mac_fw_mode_config(hdd_context_t *hdd_ctx, - uint8_t dbs, +void cds_set_dual_mac_fw_mode_config(uint8_t dbs, uint8_t dfs) { struct sir_dual_mac_config cfg; CDF_STATUS status; + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { cds_err("HDD context is NULL"); return; @@ -2369,7 +2497,6 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, /** * cds_soc_set_hw_mode() - Set HW mode command to SME - * @hdd_ctx: HDD context * @session_id: Session ID * @mac0_ss: MAC0 spatial stream configuration * @mac0_bw: MAC0 bandwidth configuration @@ -2397,8 +2524,7 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, * * Return: Success if the message made it down to the next layer */ -CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, - uint32_t session_id, +CDF_STATUS cds_soc_set_hw_mode(uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, @@ -2410,7 +2536,9 @@ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, int8_t hw_mode_index; struct sir_hw_mode msg; CDF_STATUS status; + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { cds_err("Invalid HDD context"); return CDF_STATUS_E_FAILURE; @@ -2448,7 +2576,7 @@ CDF_STATUS cds_soc_set_hw_mode(hdd_context_t *hdd_ctx, * * Return: true if connection is in progress else false */ -bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx) +bool cds_is_connection_in_progress(void) { hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; hdd_station_ctx_t *hdd_sta_ctx = NULL; @@ -2456,6 +2584,13 @@ bool cds_is_connection_in_progress(hdd_context_t *hdd_ctx) CDF_STATUS status = 0; uint8_t sta_id = 0; uint8_t *sta_mac = NULL; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } if (true == hdd_ctx->btCoexModeSet) { cds_info("BTCoex Mode operation in progress"); @@ -2538,7 +2673,6 @@ end: /** * cds_dump_current_concurrency_one_connection() - To dump the * current concurrency info with one connection - * @hdd_ctx: HDD context * @cc_mode: connection string * @length: Maximum size of the string * @@ -2546,8 +2680,8 @@ end: * * Return: length of the string */ -static uint32_t cds_dump_current_concurrency_one_connection( - hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +static uint32_t cds_dump_current_concurrency_one_connection(char *cc_mode, + uint32_t length) { uint32_t count = 0; @@ -2583,7 +2717,6 @@ static uint32_t cds_dump_current_concurrency_one_connection( /** * cds_dump_current_concurrency_two_connection() - To dump the * current concurrency info with two connections - * @hdd_ctx: HDD context * @cc_mode: connection string * @length: Maximum size of the string * @@ -2591,39 +2724,39 @@ static uint32_t cds_dump_current_concurrency_one_connection( * * Return: length of the string */ -static uint32_t cds_dump_current_concurrency_two_connection( - hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +static uint32_t cds_dump_current_concurrency_two_connection(char *cc_mode, + uint32_t length) { uint32_t count = 0; switch (conc_connection_list[1].mode) { case CDS_STA_MODE: count = cds_dump_current_concurrency_one_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+STA", length); break; case CDS_SAP_MODE: count = cds_dump_current_concurrency_one_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+SAP", length); break; case CDS_P2P_CLIENT_MODE: count = cds_dump_current_concurrency_one_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+P2P CLI", length); break; case CDS_P2P_GO_MODE: count = cds_dump_current_concurrency_one_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+P2P GO", length); break; case CDS_IBSS_MODE: count = cds_dump_current_concurrency_one_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+IBSS", length); break; @@ -2638,7 +2771,6 @@ static uint32_t cds_dump_current_concurrency_two_connection( /** * cds_dump_current_concurrency_three_connection() - To dump the * current concurrency info with three connections - * @hdd_ctx: HDD context * @cc_mode: connection string * @length: Maximum size of the string * @@ -2646,39 +2778,39 @@ static uint32_t cds_dump_current_concurrency_two_connection( * * Return: length of the string */ -static uint32_t cds_dump_current_concurrency_three_connection( - hdd_context_t *hdd_ctx, char *cc_mode, uint32_t length) +static uint32_t cds_dump_current_concurrency_three_connection(char *cc_mode, + uint32_t length) { uint32_t count = 0; switch (conc_connection_list[2].mode) { case CDS_STA_MODE: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+STA", length); break; case CDS_SAP_MODE: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+SAP", length); break; case CDS_P2P_CLIENT_MODE: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+P2P CLI", length); break; case CDS_P2P_GO_MODE: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+P2P GO", length); break; case CDS_IBSS_MODE: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, length); + cc_mode, length); count += strlcat(cc_mode, "+IBSS", length); break; @@ -2749,29 +2881,28 @@ static void cds_dump_dbs_concurrency(char *cc_mode, uint32_t length) /** * cds_dump_current_concurrency() - To dump the current * concurrency combination - * @hdd_ctx: HDD context * * This routine is called to dump the concurrency info * * Return: None */ -static void cds_dump_current_concurrency(hdd_context_t *hdd_ctx) +static void cds_dump_current_concurrency(void) { uint32_t num_connections = 0; char cc_mode[CDS_MAX_CON_STRING_LEN] = {0}; uint32_t count = 0; - num_connections = cds_get_connection_count(hdd_ctx); + num_connections = cds_get_connection_count(); switch (num_connections) { case 1: - cds_dump_current_concurrency_one_connection(hdd_ctx, cc_mode, + cds_dump_current_concurrency_one_connection(cc_mode, sizeof(cc_mode)); cds_err("%s Standalone", cc_mode); break; case 2: count = cds_dump_current_concurrency_two_connection( - hdd_ctx, cc_mode, sizeof(cc_mode)); + cc_mode, sizeof(cc_mode)); if (conc_connection_list[0].chan == conc_connection_list[1].chan) { strlcat(cc_mode, " SCC", sizeof(cc_mode)); @@ -2784,7 +2915,7 @@ static void cds_dump_current_concurrency(hdd_context_t *hdd_ctx) break; case 3: count = cds_dump_current_concurrency_three_connection( - hdd_ctx, cc_mode, sizeof(cc_mode)); + cc_mode, sizeof(cc_mode)); if ((conc_connection_list[0].chan == conc_connection_list[1].chan) && (conc_connection_list[0].chan == @@ -2815,18 +2946,17 @@ static void cds_dump_current_concurrency(hdd_context_t *hdd_ctx) /** * cds_current_concurrency_is_scc() - To check the current * concurrency combination if it is doing SCC - * @hdd_ctx: HDD context * * This routine is called to check if it is doing SCC * * Return: True - SCC, False - Otherwise */ -static bool cds_current_concurrency_is_scc(hdd_context_t *hdd_ctx) +static bool cds_current_concurrency_is_scc(void) { uint32_t num_connections = 0; bool is_scc = false; - num_connections = cds_get_connection_count(hdd_ctx); + num_connections = cds_get_connection_count(); switch (num_connections) { case 1: @@ -2859,7 +2989,6 @@ static bool cds_current_concurrency_is_scc(hdd_context_t *hdd_ctx) /** * cds_dump_legacy_concurrency() - To dump the current * concurrency combination - * @hdd_ctx: HDD context * @sta_channel: Channel STA connection has come up * @ap_channel: Channel SAP connection has come up * @p2p_channel: Channel P2P connection has come up @@ -2872,12 +3001,19 @@ static bool cds_current_concurrency_is_scc(hdd_context_t *hdd_ctx) * * Return: None */ -static void cds_dump_legacy_concurrency(hdd_context_t *hdd_ctx, +static void cds_dump_legacy_concurrency( uint8_t sta_channel, uint8_t ap_channel, uint8_t p2p_channel, struct cdf_mac_addr sta_bssid, struct cdf_mac_addr p2p_bssid, struct cdf_mac_addr ap_bssid, const char *p2p_mode) { const char *cc_mode = "Standalone"; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } if ((sta_channel == 0) && (ap_channel == 0) && (p2p_channel == 0)) { cds_err("IBSS standalone"); @@ -2941,13 +3077,12 @@ static void cds_dump_legacy_concurrency(hdd_context_t *hdd_ctx, /** * cds_dump_concurrency_info() - To dump concurrency info - * @hdd_ctx: HDD context * * This routine is called to dump the concurrency info * * Return: None */ -void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) +void cds_dump_concurrency_info(void) { hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; CDF_STATUS status; @@ -2960,7 +3095,7 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) struct cdf_mac_addr apBssid = CDF_MAC_ADDR_ZERO_INITIALIZER; uint8_t staChannel = 0, p2pChannel = 0, apChannel = 0; const char *p2pMode = "DEV"; - + hdd_context_t *hdd_ctx; #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL uint8_t targetChannel = 0; uint8_t preAdapterChannel = 0; @@ -2971,6 +3106,12 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) hdd_adapter_t *adapter5 = NULL; #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + status = hdd_get_front_adapter(hdd_ctx, &adapterNode); while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) { adapter = adapterNode->pAdapter; @@ -3217,13 +3358,13 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) adapterNode = pNext; } if (hdd_ctx->config->policy_manager_enabled) { - cds_dump_current_concurrency(hdd_ctx); - hdd_ctx->mcc_mode = !cds_current_concurrency_is_scc(hdd_ctx); + cds_dump_current_concurrency(); + hdd_ctx->mcc_mode = !cds_current_concurrency_is_scc(); } else { /* hdd_ctx->mcc_mode gets updated inside below function, which * gets used by IPA */ - cds_dump_legacy_concurrency(hdd_ctx, + cds_dump_legacy_concurrency( staChannel, apChannel, p2pChannel, staBssid, p2pBssid, apBssid, p2pMode); } @@ -3231,16 +3372,22 @@ void cds_dump_concurrency_info(hdd_context_t *hdd_ctx) /** * cds_set_concurrency_mode() - To set concurrency mode - * @hdd_ctx: HDD context * @mode: adapter mode * * This routine is called to set the concurrency mode * * Return: NONE */ -void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode) +void cds_set_concurrency_mode(enum tCDF_ADAPTER_MODE mode) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: @@ -3260,16 +3407,22 @@ void cds_set_concurrency_mode(hdd_context_t *hdd_ctx, /** * cds_clear_concurrency_mode() - To clear concurrency mode - * @hdd_ctx: HDD context * @mode: adapter mode * * This routine is called to clear the concurrency mode * * Return: NONE */ -void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode) +void cds_clear_concurrency_mode(enum tCDF_ADAPTER_MODE mode) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: @@ -3289,7 +3442,6 @@ void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, /** * cds_soc_set_pcl() - Sets PCL to FW - * @hdd_ctx: HDD context * @mode: adapter mode * * Fetches the PCL and sends the PCL to SME @@ -3298,11 +3450,18 @@ void cds_clear_concurrency_mode(hdd_context_t *hdd_ctx, * * Return: None */ -static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, enum tCDF_ADAPTER_MODE mode) +static void cds_soc_set_pcl(enum tCDF_ADAPTER_MODE mode) { CDF_STATUS status; enum cds_con_mode con_mode; struct sir_pcl_list pcl; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } pcl.pcl_len = 0; switch (mode) { @@ -3328,7 +3487,7 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, enum tCDF_ADAPTER_MODE mode) cds_debug("get pcl to set it to the FW"); - status = cds_get_pcl(hdd_ctx, con_mode, + status = cds_get_pcl(con_mode, pcl.pcl_list, &pcl.pcl_len); if (status != CDF_STATUS_SUCCESS) { cds_err("Unable to set PCL to FW, Get PCL failed"); @@ -3344,7 +3503,6 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, enum tCDF_ADAPTER_MODE mode) /** * cds_incr_active_session() - increments the number of active sessions - * @hdd_ctx: HDD Context * @mode: Adapter mode * @session_id: session ID for the connection session * @@ -3354,10 +3512,17 @@ static void cds_soc_set_pcl(hdd_context_t *hdd_ctx, enum tCDF_ADAPTER_MODE mode) * * Return: None */ -void cds_incr_active_session(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode, - uint8_t session_id) +void cds_incr_active_session(enum tCDF_ADAPTER_MODE mode, + uint8_t session_id) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + /* * Need to aquire mutex as entire functionality in this function * is in critical section @@ -3383,25 +3548,23 @@ void cds_incr_active_session(hdd_context_t *hdd_ctx, */ if (mode == CDF_STA_MODE) { /* Set PCL of STA to the FW */ - cds_soc_set_pcl(hdd_ctx, mode); + cds_soc_set_pcl(mode); cds_info("Set PCL of STA to FW"); } - cds_incr_connection_count(hdd_ctx, session_id); + cds_incr_connection_count(session_id); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); } /** * cds_need_opportunistic_upgrade() - Tells us if we really * need an upgrade to 2x2 - * @hdd_ctx: HDD context * * This function returns if updrade to 2x2 is needed * * Return: CDS_NOP = upgrade is not needed, otherwise upgrade is * needed */ -enum cds_conc_next_action cds_need_opportunistic_upgrade( - hdd_context_t *hdd_ctx) +enum cds_conc_next_action cds_need_opportunistic_upgrade(void) { uint32_t conn_index; enum cds_conc_next_action upgrade = CDS_NOP; @@ -3451,15 +3614,13 @@ done: /** * cds_set_pcl_for_existing_combo() - Set PCL for existing connection - * @hdd_ctx: HDD context * @mode: Connection mode of type 'cds_con_mode' * * Set the PCL for an existing connection * * Return: None */ -static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, - enum cds_con_mode mode) +static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) { struct cds_conc_connection_info info; enum tCDF_ADAPTER_MODE pcl_mode; @@ -3486,21 +3647,19 @@ static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, }; if (cds_mode_specific_connection_count( - hdd_ctx, mode, NULL) > 0) { + mode, NULL) > 0) { /* Check, store and temp delete the mode's parameter */ - cds_store_and_del_conn_info(hdd_ctx, mode, - &info); + cds_store_and_del_conn_info(mode, &info); /* Set the PCL to the FW since connection got updated */ - cds_soc_set_pcl(hdd_ctx, pcl_mode); + cds_soc_set_pcl(pcl_mode); cds_info("Set PCL to FW for mode:%d", mode); /* Restore the connection info */ - cds_restore_deleted_conn_info(hdd_ctx, &info); + cds_restore_deleted_conn_info(&info); } } /** * cds_decr_session_set_pcl() - Decrement session count and set PCL - * @hdd_ctx: HDD context * @mode: Adapter mode * @session_id: Session id * @@ -3509,13 +3668,19 @@ static void cds_set_pcl_for_existing_combo(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode, +void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { CDF_STATUS cdf_status; + hdd_context_t *hdd_ctx; - cds_decr_active_session(hdd_ctx, mode, session_id); + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + + cds_decr_active_session(mode, session_id); /* * After the removal of this connection, we need to check if * a STA connection still exists. The reason for this is that @@ -3531,9 +3696,9 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, * the entry that we have saved before. */ cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); - cds_set_pcl_for_existing_combo(hdd_ctx, CDS_STA_MODE); + cds_set_pcl_for_existing_combo(CDS_STA_MODE); /* do we need to change the HW mode */ - if (cds_need_opportunistic_upgrade(hdd_ctx)) { + if (cds_need_opportunistic_upgrade()) { /* let's start the timer */ cdf_mc_timer_stop(&hdd_ctx->dbs_opportunistic_timer); cdf_status = cdf_mc_timer_start( @@ -3551,7 +3716,6 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, /** * cds_decr_active_session() - decrements the number of active sessions - * @hdd_ctx: HDD Context * @mode: Adapter mode * @session_id: session ID for the connection session * @@ -3561,10 +3725,17 @@ void cds_decr_session_set_pcl(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_decr_active_session(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE mode, +void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + /* * Need to aquire mutex as entire functionality in this function * is in critical section @@ -3584,7 +3755,7 @@ void cds_decr_active_session(hdd_context_t *hdd_ctx, } cds_info("No.# of active sessions for mode %d = %d", mode, hdd_ctx->no_of_active_sessions[mode]); - cds_decr_connection_count(hdd_ctx, session_id); + cds_decr_connection_count(session_id); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); } @@ -3609,14 +3780,14 @@ void cds_dbs_opportunistic_timer_handler(void *data) cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); /* if we still need it */ - action = cds_need_opportunistic_upgrade(hdd_ctx); + action = cds_need_opportunistic_upgrade(); if (action) { /* lets call for action */ /* session id is being used only * in hidden ssid case for now. * So, session id 0 is ok here. */ - cds_next_actions(hdd_ctx, 0, action, + cds_next_actions(0, action, CDS_UPDATE_REASON_OPPORTUNISTIC); } cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -3626,15 +3797,21 @@ void cds_dbs_opportunistic_timer_handler(void *data) /** * cds_init_policy_mgr() - Initialize the policy manager * related data structures - * @hdd_ctx: HDD Context * * Initialize the policy manager related data structures * * Return: Success if the policy manager is initialized completely */ -CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) +CDF_STATUS cds_init_policy_mgr(void) { CDF_STATUS status; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return CDF_STATUS_E_FAILURE; + } cds_debug("Initializing the policy manager"); @@ -3671,7 +3848,6 @@ CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) /** * cds_get_connection_for_vdev_id() - provides the * perticular connection with the requested vdev id - * @hdd_ctx: HDD Context * @vdev_id: vdev id of the connection * * This function provides the specific connection with the @@ -3679,8 +3855,7 @@ CDF_STATUS cds_init_policy_mgr(hdd_context_t *hdd_ctx) * * Return: index in the connection table */ -uint32_t cds_get_connection_for_vdev_id(hdd_context_t *hdd_ctx, - uint32_t vdev_id) +uint32_t cds_get_connection_for_vdev_id(uint32_t vdev_id) { uint32_t conn_index = 0; for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; @@ -3697,14 +3872,13 @@ uint32_t cds_get_connection_for_vdev_id(hdd_context_t *hdd_ctx, /** * cds_get_connection_count() - provides the count of * current connections - * @hdd_ctx: HDD Context * * * This function provides the count of current connections * * Return: connection count */ -uint32_t cds_get_connection_count(hdd_context_t *hdd_ctx) +uint32_t cds_get_connection_count(void) { uint32_t conn_index, count = 0; for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; @@ -3769,7 +3943,7 @@ enum cds_con_mode cds_get_mode(uint8_t type, uint8_t subtype) /** * cds_incr_connection_count() - adds the new connection to * the current connections list - * @hdd_ctx: HDD Context + * @vdev_id: vdev id * * * This function adds the new connection to the current @@ -3777,14 +3951,20 @@ enum cds_con_mode cds_get_mode(uint8_t type, uint8_t subtype) * * Return: CDF_STATUS */ -CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, - uint32_t vdev_id) +CDF_STATUS cds_incr_connection_count(uint32_t vdev_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index; struct wma_txrx_node *wma_conn_table_entry; + hdd_context_t *hdd_ctx; - conn_index = cds_get_connection_count(hdd_ctx); + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } + + conn_index = cds_get_connection_count(); if (hdd_ctx->config->gMaxConcurrentActiveSessions < conn_index) { /* err msg */ cds_err("exceeded max connection limit %d", @@ -3823,7 +4003,7 @@ CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, /** * cds_update_connection_info() - updates the existing * connection in the current connections list - * @hdd_ctx: HDD Context + * @vdev_id: vdev id * * * This function adds the new connection to the current @@ -3831,13 +4011,19 @@ CDF_STATUS cds_incr_connection_count(hdd_context_t *hdd_ctx, * * Return: CDF_STATUS */ -CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, - uint32_t vdev_id) +CDF_STATUS cds_update_connection_info(uint32_t vdev_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0; bool found = false; struct wma_txrx_node *wma_conn_table_entry; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { @@ -3882,7 +4068,6 @@ CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, /** * cds_decr_connection_count() - remove the old connection * from the current connections list - * @hdd_ctx: HDD Context * @vdev_id: vdev id of the old connection * * @@ -3891,8 +4076,7 @@ CDF_STATUS cds_update_connection_info(hdd_context_t *hdd_ctx, * * Return: CDF_STATUS */ -CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, - uint32_t vdev_id) +CDF_STATUS cds_decr_connection_count(uint32_t vdev_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0, next_conn_index = 0; @@ -3945,7 +4129,6 @@ CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, /** * cds_get_connection_channels() - provides the channel(s) * on which current connection(s) is - * @hdd_ctx: HDD Context * @channels: the channel(s) on which current connection(s) is * @len: Number of channels * @order: no order OR 2.4 Ghz channel followed by 5 Ghz @@ -3957,19 +4140,12 @@ CDF_STATUS cds_decr_connection_count(hdd_context_t *hdd_ctx, * * Return: CDF_STATUS */ -CDF_STATUS cds_get_connection_channels(hdd_context_t *hdd_ctx, - uint8_t *channels, uint32_t *len, uint8_t order) +CDF_STATUS cds_get_connection_channels(uint8_t *channels, + uint32_t *len, uint8_t order) { CDF_STATUS status = CDF_STATUS_SUCCESS; uint32_t conn_index = 0, num_channels = 0; - if (NULL == hdd_ctx) { - /* err msg*/ - cds_err("hdd_ctx is NULL"); - status = CDF_STATUS_E_FAILURE; - return status; - } - if ((NULL == channels) || (NULL == len)) { /* err msg*/ cds_err("channels or len is NULL"); @@ -4031,7 +4207,6 @@ CDF_STATUS cds_get_connection_channels(hdd_context_t *hdd_ctx, /** * cds_update_with_safe_channel_list() - provides the safe * channel list - * @hdd_ctx: HDD Context * @pcl_channels: channel list * @len: length of the list * @@ -4041,8 +4216,7 @@ CDF_STATUS cds_get_connection_channels(hdd_context_t *hdd_ctx, * Return: None */ #ifdef CONFIG_CNSS -void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, - uint8_t *pcl_channels, uint32_t *len) +void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) { uint16_t unsafe_channel_list[MAX_NUM_CHAN]; uint8_t current_channel_list[MAX_NUM_CHAN]; @@ -4090,8 +4264,7 @@ void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, return; } #else -void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, - uint8_t *pcl_channels, uint32_t *len) +void cds_update_with_safe_channel_list(uint8_t *pcl_channels, uint32_t *len) { return; } @@ -4110,8 +4283,7 @@ void cds_update_with_safe_channel_list(hdd_context_t *hdd_ctx, * * Return: Channel List */ -CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, - enum cds_pcl_type pcl, +CDF_STATUS cds_get_channel_list(enum cds_pcl_type pcl, uint8_t *pcl_channels, uint32_t *len) { CDF_STATUS status = CDF_STATUS_E_FAILURE; @@ -4120,10 +4292,11 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, uint8_t channel_list[MAX_NUM_CHAN] = {0}; uint8_t channel_list_24[MAX_NUM_CHAN] = {0}; uint8_t channel_list_5[MAX_NUM_CHAN] = {0}; + hdd_context_t *hdd_ctx; - if (NULL == hdd_ctx) { - /* err msg*/ - cds_err("hdd_ctx is NULL"); + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); return status; } @@ -4186,7 +4359,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, break; case CDS_SCC_CH: case CDS_MCC_CH: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 0); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4194,7 +4367,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, break; case CDS_SCC_CH_24G: case CDS_MCC_CH_24G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 0); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4205,7 +4378,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, break; case CDS_SCC_CH_5G: case CDS_MCC_CH_5G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 0); cdf_mem_copy(pcl_channels, channel_list, num_channels); @@ -4220,7 +4393,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, cdf_mem_copy(pcl_channels, channel_list_24, chan_index_24); *len = chan_index_24; - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 0); cdf_mem_copy(&pcl_channels[chan_index_24], channel_list, num_channels); @@ -4232,7 +4405,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, cdf_mem_copy(pcl_channels, channel_list_5, chan_index_5); *len = chan_index_5; - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 0); cdf_mem_copy(&pcl_channels[chan_index_5], channel_list, num_channels); @@ -4240,7 +4413,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_24_SCC_ON_5: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 1); cdf_mem_copy(pcl_channels, channel_list, num_channels); @@ -4248,14 +4421,14 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_5_SCC_ON_24: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 2); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_24_SCC_ON_5_24G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 1); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4265,7 +4438,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_24_SCC_ON_5_5G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 1); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4275,7 +4448,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_5_SCC_ON_24_24G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 2); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4285,7 +4458,7 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, status = CDF_STATUS_SUCCESS; break; case CDS_SCC_ON_5_SCC_ON_24_5G: - cds_get_connection_channels(hdd_ctx, + cds_get_connection_channels( channel_list, &num_channels, 2); cdf_mem_copy(pcl_channels, channel_list, num_channels); *len = num_channels; @@ -4301,14 +4474,13 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, } /* check the channel avoidance list */ - cds_update_with_safe_channel_list(hdd_ctx, pcl_channels, len); + cds_update_with_safe_channel_list(pcl_channels, len); return status; } /** * cds_map_concurrency_mode() - to map concurrency mode between sme and hdd - * @hdd_ctx: hdd context * @old_mode: sme provided adapter mode * @new_mode: hdd provided concurrency mode * @@ -4316,16 +4488,11 @@ CDF_STATUS cds_get_channel_list(hdd_context_t *hdd_ctx, * * Return: true or false */ -bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, - enum tCDF_ADAPTER_MODE *old_mode, enum cds_con_mode *new_mode) +bool cds_map_concurrency_mode(enum tCDF_ADAPTER_MODE *old_mode, + enum cds_con_mode *new_mode) { bool status = true; - if (!hdd_ctx) { - cds_err("HDD context is NULL"); - return false; - } - switch (*old_mode) { case CDF_STA_MODE: @@ -4354,7 +4521,6 @@ bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, /** * cds_get_pcl() - provides the preferred channel list for * new connection - * @hdd_ctx: HDD Context * @mode: Device mode * @pcl_channels: PCL channels * @len: lenght of the PCL @@ -4366,7 +4532,7 @@ bool cds_map_concurrency_mode(hdd_context_t *hdd_ctx, * * Return: CDF_STATUS */ -CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, +CDF_STATUS cds_get_pcl(enum cds_con_mode mode, uint8_t *pcl_channels, uint32_t *len) { CDF_STATUS status = CDF_STATUS_E_FAILURE; @@ -4376,8 +4542,16 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, enum cds_two_connection_mode third_index = 0; enum cds_pcl_type pcl = CDS_NONE; enum cds_conc_priority_mode conc_system_pref = 0; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } + /* find the current connection state from conc_connection_list*/ - num_connections = cds_get_connection_count(hdd_ctx); + num_connections = cds_get_connection_count(); cds_debug("connections:%d pref:%d requested mode:%d", num_connections, hdd_ctx->config->conc_system_pref, mode); @@ -4401,12 +4575,12 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, switch (num_connections) { case 0: first_index = - cds_get_first_connection_pcl_table_index(hdd_ctx); + cds_get_first_connection_pcl_table_index(); pcl = first_connection_pcl_table[mode][first_index]; break; case 1: second_index = - cds_get_second_connection_pcl_table_index(hdd_ctx); + cds_get_second_connection_pcl_table_index(); if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { /* err msg */ cds_err("couldn't find index for 2nd connection pcl table"); @@ -4423,7 +4597,7 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, break; case 2: third_index = - cds_get_third_connection_pcl_table_index(hdd_ctx); + cds_get_third_connection_pcl_table_index(); if (CDS_MAX_TWO_CONNECTION_MODE == third_index) { /* err msg */ cds_err("couldn't find index for 3rd connection pcl table"); @@ -4451,7 +4625,7 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, /* once the PCL enum is obtained find out the exact channel list with * help from sme_get_cfg_valid_channels */ - status = cds_get_channel_list(hdd_ctx, pcl, pcl_channels, len); + status = cds_get_channel_list(pcl, pcl_channels, len); if (status == CDF_STATUS_SUCCESS) { uint32_t i; cds_debug("pcl len:%d", *len); @@ -4465,7 +4639,6 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, /** * cds_disallow_mcc() - Check for mcc * - * @hdd_ctx: HDD Context * @channel: channel on which new connection is coming up * * When a new connection is about to come up check if current @@ -4474,7 +4647,7 @@ CDF_STATUS cds_get_pcl(hdd_context_t *hdd_ctx, enum cds_con_mode mode, * * Return: True/False */ -bool cds_disallow_mcc(hdd_context_t *hdd_ctx, uint8_t channel) +bool cds_disallow_mcc(uint8_t channel) { uint32_t index = 0; bool match = false; @@ -4500,8 +4673,6 @@ bool cds_disallow_mcc(hdd_context_t *hdd_ctx, uint8_t channel) /** * cds_allow_new_home_channel() - Check for allowed number of * home channels - * - * @hdd_ctx: HDD Context * @channel: channel on which new connection is coming up * @num_connections: number of current connections * @@ -4511,8 +4682,7 @@ bool cds_disallow_mcc(hdd_context_t *hdd_ctx, uint8_t channel) * * Return: True/False */ -bool cds_allow_new_home_channel(hdd_context_t *hdd_ctx, - uint8_t channel, uint32_t num_connections) +bool cds_allow_new_home_channel(uint8_t channel, uint32_t num_connections) { bool status = true; @@ -4571,17 +4741,16 @@ bool cds_allow_new_home_channel(hdd_context_t *hdd_ctx, * * Return: true if ibss connection exist else false */ -bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel) +bool cds_is_ibss_conn_exist(uint8_t *ibss_channel) { uint32_t count = 0, index = 0; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; bool status = false; - if ((NULL == hdd_ctx) || (NULL == ibss_channel)) { + if (NULL == ibss_channel) { cds_err("Null pointer error"); return false; } - count = cds_mode_specific_connection_count(hdd_ctx, - CDS_IBSS_MODE, list); + count = cds_mode_specific_connection_count(CDS_IBSS_MODE, list); if (count == 0) { /* No IBSS connection */ status = false; @@ -4599,8 +4768,6 @@ bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel) /** * cds_allow_concurrency() - Check for allowed concurrency * combination - * - * @hdd_ctx: HDD Context * @mode: new connection mode * @channel: channel on which new connection is coming up * @bw: Bandwidth requested by the connection (optional) @@ -4611,16 +4778,23 @@ bool cds_is_ibss_conn_exist(hdd_context_t *hdd_ctx, uint8_t *ibss_channel) * * Return: True/False */ -bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, +bool cds_allow_concurrency(enum cds_con_mode mode, uint8_t channel, enum hw_mode_bandwidth bw) { uint32_t num_connections = 0, count = 0, index = 0; bool status = false, match = false; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); /* find the current connection state from conc_connection_list*/ - num_connections = cds_get_connection_count(hdd_ctx); + num_connections = cds_get_connection_count(); if (cds_max_concurrent_connections_reached()) { cds_err("Reached max concurrent connections: %d", @@ -4630,14 +4804,14 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, if (channel) { /* don't allow 3rd home channel on same MAC */ - if (!cds_allow_new_home_channel(hdd_ctx, channel, + if (!cds_allow_new_home_channel(channel, num_connections)) goto done; /* don't allow MCC if SAP/GO on DFS channel or about to come up * on DFS channel */ - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_P2P_GO_MODE, list); while (index < count) { if ((CDS_IS_DFS_CH( @@ -4653,7 +4827,7 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, } index = 0; - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_SAP_MODE, list); while (index < count) { if ((CDS_IS_DFS_CH( @@ -4671,7 +4845,7 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, index = 0; if ((CDS_P2P_GO_MODE == mode) || (CDS_SAP_MODE == mode)) { if (CDS_IS_DFS_CH(channel)) - match = cds_disallow_mcc(hdd_ctx, channel); + match = cds_disallow_mcc(channel); } if (true == match) { cds_err("No MCC, SAP/GO about to come up on DFS channel"); @@ -4681,10 +4855,10 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, /* don't allow IBSS + STA MCC */ /* don't allow IBSS + STA SCC if IBSS is on DFS channel */ - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_STA_MODE, list); if ((CDS_IBSS_MODE == mode) && - (cds_mode_specific_connection_count(hdd_ctx, + (cds_mode_specific_connection_count( CDS_IBSS_MODE, list)) && count) { /* err msg */ cds_err("No 2nd IBSS, we already have STA + IBSS"); @@ -4736,10 +4910,10 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, goto done; } } - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_STA_MODE, list); if ((CDS_STA_MODE == mode) && - (cds_mode_specific_connection_count(hdd_ctx, + (cds_mode_specific_connection_count( CDS_IBSS_MODE, list)) && count) { /* err msg */ cds_err("No 2nd STA, we already have STA + IBSS"); @@ -4747,7 +4921,7 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, } if ((CDS_STA_MODE == mode) && - (cds_mode_specific_connection_count(hdd_ctx, + (cds_mode_specific_connection_count( CDS_IBSS_MODE, list))) { if (wma_is_hw_dbs_capable() == true) { if (num_connections > 1) { @@ -4792,7 +4966,7 @@ bool cds_allow_concurrency(hdd_context_t *hdd_ctx, enum cds_con_mode mode, /* don't allow two P2P GO on same band */ if (channel && (mode == CDS_P2P_GO_MODE) && num_connections) { index = 0; - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_P2P_GO_MODE, list); while (index < count) { if (CDS_IS_SAME_BAND_CHANNELS(channel, @@ -4815,16 +4989,22 @@ done: * cds_get_first_connection_pcl_table_index() - provides the * row index to firstConnectionPclTable to get to the correct * pcl - * @hdd_ctx: HDD Context * * This function provides the row index to * firstConnectionPclTable. The index is the preference config. * * Return: table index */ -enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( - hdd_context_t *hdd_ctx) +enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index(void) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return CDS_THROUGHPUT; + } + if (hdd_ctx->config->conc_system_pref >= CDS_MAX_CONC_PRIORITY_MODE) return CDS_THROUGHPUT; return hdd_ctx->config->conc_system_pref; @@ -4834,7 +5014,6 @@ enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( * cds_get_second_connection_pcl_table_index() - provides the * row index to secondConnectionPclTable to get to the correct * pcl - * @hdd_ctx: HDD Context * * This function provides the row index to * secondConnectionPclTable. The index is derived based on @@ -4843,8 +5022,7 @@ enum cds_conc_priority_mode cds_get_first_connection_pcl_table_index( * * Return: table index */ -enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( - hdd_context_t *hdd_ctx) +enum cds_one_connection_mode cds_get_second_connection_pcl_table_index(void) { enum cds_one_connection_mode index = CDS_MAX_ONE_CONNECTION_MODE; @@ -4921,7 +5099,6 @@ enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( * cds_get_third_connection_pcl_table_index() - provides the * row index to thirdConnectionPclTable to get to the correct * pcl - * @hdd_ctx: HDD Context * * This function provides the row index to * thirdConnectionPclTable. The index is derived based on @@ -4930,8 +5107,7 @@ enum cds_one_connection_mode cds_get_second_connection_pcl_table_index( * * Return: table index */ -enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( - hdd_context_t *hdd_ctx) +enum cds_two_connection_mode cds_get_third_connection_pcl_table_index(void) { enum cds_one_connection_mode index = CDS_MAX_TWO_CONNECTION_MODE; @@ -5264,40 +5440,6 @@ enum cds_two_connection_mode cds_get_third_connection_pcl_table_index( return index; } -/** - * cds_mode_switch_dbs_to_mcc() - initiates a mode switch - * from DBS to MCC - * @hdd_ctx: HDD Context - * - * This function initiates a mode switch from DBS to MCC if any - * change in concurrency scenario or some other external entity - * (looking for range, thermal mitigation etc.) made an explicit - * request. Notifies FW as well - * - * Return: CDF_STATUS enum - */ -CDF_STATUS cds_mode_switch_dbs_to_mcc(hdd_context_t *hdd_ctx) -{ - return CDF_STATUS_SUCCESS; -} - -/** - * cds_mode_switch_mcc_to_dbs() - initiates a mode switch - * from MCC to DBS - * @hdd_ctx: HDD Context - * - * This function initiates a mode switch from MCC to DBS if any - * change in concurrency scenario or some other external entity - * (powersave, thermal mitigation etc.) made an explicit - * request. Notifies FW as well - * - * Return: CDF_STATUS enum - */ -CDF_STATUS cds_mode_switch_mcc_to_dbs(hdd_context_t *hdd_ctx) -{ - return CDF_STATUS_SUCCESS; -} - /** * cds_current_connections_update() - initiates actions * needed on current connections once channel has been decided @@ -5340,7 +5482,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, band = CDS_BAND_5; cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); - num_connections = cds_get_connection_count(hdd_ctx); + num_connections = cds_get_connection_count(); cds_debug("num_connections=%d channel=%d", num_connections, channel); @@ -5358,7 +5500,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, break; case 1: second_index = - cds_get_second_connection_pcl_table_index(hdd_ctx); + cds_get_second_connection_pcl_table_index(); if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { /* err msg */ cds_err("couldn't find index for 2nd connection next action table"); @@ -5369,7 +5511,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, break; case 2: third_index = - cds_get_third_connection_pcl_table_index(hdd_ctx); + cds_get_third_connection_pcl_table_index(); if (CDS_MAX_TWO_CONNECTION_MODE == third_index) { /* err msg */ cds_err("couldn't find index for 3rd connection next action table"); @@ -5385,7 +5527,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, } if (CDS_NOP != next_action) - status = cds_next_actions(hdd_ctx, session_id, + status = cds_next_actions(session_id, next_action, reason); else status = CDF_STATUS_E_NOSUPPORT; @@ -5403,7 +5545,6 @@ done: * cds_wait_for_nss_update() - finds out if we need to wait * for all nss update to finish before requesting for HW mode * update - * @hdd_ctx: HDD Context * @action: next action to happen at policy mgr after * beacon update * @@ -5414,7 +5555,7 @@ done: * Return: boolean. True = wait for nss update, False = go ahead * with HW mode update */ -bool cds_wait_for_nss_update(hdd_context_t *hdd_ctx, uint8_t action) +bool cds_wait_for_nss_update(uint8_t action) { uint32_t conn_index = 0; bool wait = false; @@ -5487,7 +5628,7 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * Check if we are ok to request for HW mode change now */ cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); - conn_index = cds_get_connection_for_vdev_id(hdd_ctx, vdev_id); + conn_index = cds_get_connection_for_vdev_id(vdev_id); if (MAX_NUMBER_OF_CONC_CONNECTIONS == conn_index) { cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); cds_err("connection not found for vdev %d", vdev_id); @@ -5497,19 +5638,19 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, case CDS_DBS: conc_connection_list[conn_index].tx_spatial_stream = 1; conc_connection_list[conn_index].rx_spatial_stream = 1; - wait = cds_wait_for_nss_update(hdd_ctx, next_action); + wait = cds_wait_for_nss_update(next_action); break; case CDS_MCC: conc_connection_list[conn_index].tx_spatial_stream = 2; conc_connection_list[conn_index].rx_spatial_stream = 2; - wait = cds_wait_for_nss_update(hdd_ctx, next_action); + wait = cds_wait_for_nss_update(next_action); break; default: cds_err("unexpected action %d", next_action); break; } if (!wait) - cds_next_actions(hdd_ctx, vdev_id, + cds_next_actions(vdev_id, next_action, CDS_UPDATE_REASON_NSS_UPDATE); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -5520,7 +5661,6 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * cds_complete_action() - initiates actions needed on * current connections once channel has been decided for the new * connection - * @hdd_ctx: HDD Context * @new_nss: the new nss value * @next_action: next action to happen at policy mgr after * beacon update @@ -5533,8 +5673,7 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, * * Return: CDF_STATUS enum */ -CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, - uint8_t new_nss, uint8_t next_action, +CDF_STATUS cds_complete_action(uint8_t new_nss, uint8_t next_action, enum cds_conn_update_reason reason, uint32_t session_id) { @@ -5542,6 +5681,13 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, uint32_t index = 0, count = 0; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; uint32_t conn_index = 0; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } if (wma_is_hw_dbs_capable() == false) { cds_err("driver isn't dbs capable, no further action needed"); @@ -5553,10 +5699,10 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * protection. So, not taking any lock inside cds_complete_action() * during conc_connection_list access. */ - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_P2P_GO_MODE, list); while (index < count) { - conn_index = cds_get_connection_for_vdev_id(hdd_ctx, + conn_index = cds_get_connection_for_vdev_id( conc_connection_list[list[index]].vdev_id); if (MAX_NUMBER_OF_CONC_CONNECTIONS == conn_index) { cds_err("connection not found for vdev %d", @@ -5579,7 +5725,7 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, } index = 0; - count = cds_mode_specific_connection_count(hdd_ctx, + count = cds_mode_specific_connection_count( CDS_SAP_MODE, list); while (index < count) { if (1 == conc_connection_list[list[index]].original_nss) { @@ -5596,7 +5742,7 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, index++; } if (!CDF_IS_STATUS_SUCCESS(status)) - status = cds_next_actions(hdd_ctx, session_id, + status = cds_next_actions(session_id, next_action, reason); return status; @@ -5606,7 +5752,6 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * cds_next_actions() - initiates actions needed on current * connections once channel has been decided for the new * connection - * @hdd_ctx: HDD Context * @session_id: Session id * @action: action to be executed * @reason: Reason for connection update @@ -5617,8 +5762,7 @@ CDF_STATUS cds_complete_action(hdd_context_t *hdd_ctx, * * Return: CDF_STATUS enum */ -CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, - uint32_t session_id, +CDF_STATUS cds_next_actions(uint32_t session_id, enum cds_conc_next_action action, enum cds_conn_update_reason reason) { @@ -5657,11 +5801,11 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * update the beacon template & notify FW. Once FW confirms * beacon updated, send down the HW mode change req */ - status = cds_complete_action(hdd_ctx, 1, CDS_DBS, reason, + status = cds_complete_action(1, CDS_DBS, reason, session_id); break; case CDS_DBS: - status = cds_soc_set_hw_mode(hdd_ctx, session_id, + status = cds_soc_set_hw_mode(session_id, HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, @@ -5675,11 +5819,11 @@ CDF_STATUS cds_next_actions(hdd_context_t *hdd_ctx, * intially. If yes, update the beacon template & notify FW. * Once FW confirms beacon updated, send the HW mode change req */ - status = cds_complete_action(hdd_ctx, 0, CDS_MCC, reason, + status = cds_complete_action(0, CDS_MCC, reason, session_id); break; case CDS_MCC: - status = cds_soc_set_hw_mode(hdd_ctx, session_id, + status = cds_soc_set_hw_mode(session_id, HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, @@ -5855,13 +5999,12 @@ static void cds_sap_restart_handle(struct work_struct *work) } wlan_hdd_start_sap(sap_adapter); - cds_change_sap_restart_required_status(hdd_ctx, false); + cds_change_sap_restart_required_status(false); cds_ssr_unprotect(__func__); } /** * cds_check_and_restart_sap() - Check and restart sap if required - * @hdd_ctx: pointer to HDD context * @roam_result: Roam result * @hdd_sta_ctx: HDD station context * @@ -5869,16 +6012,22 @@ static void cds_sap_restart_handle(struct work_struct *work) * * Return: CDF_STATUS */ -CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, - eCsrRoamResult roam_result, +CDF_STATUS cds_check_and_restart_sap(eCsrRoamResult roam_result, hdd_station_ctx_t *hdd_sta_ctx) { hdd_adapter_t *sap_adapter = NULL; hdd_ap_ctx_t *hdd_ap_ctx = NULL; uint8_t default_sap_channel = 6; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return CDF_STATUS_E_FAILURE; + } if (!(hdd_ctx->config->conc_custom_rule1 && - (true == cds_is_sap_restart_required(hdd_ctx)))) + (true == cds_is_sap_restart_required()))) return CDF_STATUS_SUCCESS; sap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); @@ -5938,7 +6087,6 @@ CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, /** * cds_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. * @@ -5948,16 +6096,22 @@ CDF_STATUS cds_check_and_restart_sap(hdd_context_t *hdd_ctx, * * Return: true or false based on function's overall success. */ -static bool cds_sta_sap_concur_handle(hdd_context_t *hdd_ctx, - hdd_adapter_t *sta_adapter, +static bool cds_sta_sap_concur_handle(hdd_adapter_t *sta_adapter, tCsrRoamProfile *roam_profile) { - hdd_adapter_t *ap_adapter = hdd_get_adapter(hdd_ctx, - WLAN_HDD_SOFTAP); + hdd_adapter_t *ap_adapter; bool are_cc_channels_same = false; tScanResultHandle scan_cache = NULL; CDF_STATUS status; + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return are_cc_channels_same; + } + + ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP); if ((ap_adapter != NULL) && test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { status = @@ -5985,7 +6139,7 @@ static bool cds_sta_sap_concur_handle(hdd_context_t *hdd_ctx, if (false == are_cc_channels_same) { cds_info("Stop AP due to mismatch with STA channel"); wlan_hdd_stop_sap(ap_adapter); - cds_change_sap_restart_required_status(hdd_ctx, true); + cds_change_sap_restart_required_status(true); return false; } else { cds_info("sap channels are same"); @@ -5998,7 +6152,6 @@ static bool cds_sta_sap_concur_handle(hdd_context_t *hdd_ctx, /** * cds_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. @@ -6010,20 +6163,25 @@ static bool cds_sta_sap_concur_handle(hdd_context_t *hdd_ctx, * * Return: true or false based on function's overall success. */ -static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, - hdd_adapter_t *sta_adapter, +static bool cds_sta_p2pgo_concur_handle(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); + hdd_adapter_t *p2pgo_adapter; bool are_cc_channels_same = false; tScanResultHandle scan_cache = NULL; uint32_t p2pgo_channel_num, freq; tHddAvoidFreqList hdd_avoid_freq_list; CDF_STATUS status; bool ret; + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return are_cc_channels_same; + } + p2pgo_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_P2P_GO); if ((p2pgo_adapter != NULL) && test_bit(SOFTAP_BSS_STARTED, &p2pgo_adapter->event_flags)) { status = @@ -6039,7 +6197,7 @@ static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, * channel is different or STA channel is zero. */ if (false == are_cc_channels_same) { - if (true == cds_is_sta_connection_pending(hdd_ctx)) { + if (true == cds_is_sta_connection_pending()) { MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_CLEAR_JOIN_REQ, sta_adapter->sessionId, *roam_id)); @@ -6050,8 +6208,7 @@ static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, cds_err("sme_clear_joinreq_param failed"); /* Not returning */ } - cds_change_sta_conn_pending_status(hdd_ctx, - false); + cds_change_sta_conn_pending_status(false); cds_info("===>Clear pending join req"); } MTRACE(cdf_trace(CDF_MODULE_ID_HDD, @@ -6068,7 +6225,7 @@ static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, cds_err("sme_store_joinreq_param failed"); /* Not returning */ } - cds_change_sta_conn_pending_status(hdd_ctx, true); + cds_change_sta_conn_pending_status(true); /* * fill frequency avoidance event and send it up, so * p2pgo stop event should get trigger from upper layer @@ -6113,7 +6270,6 @@ static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, /** * cds_handle_conc_rule1() - Check if concurrency rule1 is enabled - * @hdd_ctx: HDD context * @adapter: HDD adpater * @roam_profile: Profile for connection * @@ -6123,11 +6279,17 @@ static bool cds_sta_p2pgo_concur_handle(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, - hdd_adapter_t *adapter, +void cds_handle_conc_rule1(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile) { bool ret; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } /* * Custom concurrency rule1: As per this rule if station is @@ -6137,7 +6299,7 @@ void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, */ if (hdd_ctx->config->conc_custom_rule1 && (WLAN_HDD_INFRA_STATION == adapter->device_mode)) { - ret = cds_sta_sap_concur_handle(hdd_ctx, adapter, + ret = cds_sta_sap_concur_handle(adapter, roam_profile); if (true != ret) { cds_err("cds_sta_sap_concur_handle failed"); @@ -6149,7 +6311,6 @@ void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, #ifdef FEATURE_WLAN_CH_AVOID /** * cds_handle_conc_rule2() - Check if concurrency rule2 is enabled - * @hdd_ctx: HDD context * @adapter: HDD adpater * @roam_profile: Profile for connection * @@ -6159,11 +6320,18 @@ void cds_handle_conc_rule1(hdd_context_t *hdd_ctx, * * Return: None */ -bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, - hdd_adapter_t *adapter, +bool cds_handle_conc_rule2(hdd_adapter_t *adapter, tCsrRoamProfile *roam_profile, uint32_t *roam_id) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } + /* * Custom concurrency rule2: As per this rule if station is * trying to connect to some AP in 5Ghz and P2PGO is already in @@ -6171,7 +6339,7 @@ bool cds_handle_conc_rule2(hdd_context_t *hdd_ctx, */ if (hdd_ctx->config->conc_custom_rule2 && (WLAN_HDD_INFRA_STATION == adapter->device_mode)) { - if (false == cds_sta_p2pgo_concur_handle(hdd_ctx, + if (false == cds_sta_p2pgo_concur_handle( adapter, roam_profile, roam_id)) { cds_err("P2PGO-STA chnl diff, cache join req"); return false; @@ -6246,7 +6414,7 @@ uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, } /* Take care of 160MHz and 80+80Mhz later */ - ret = cds_allow_concurrency(hdd_ctx, + ret = cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( adapter->device_mode), channel, HW_MODE_20_MHZ); @@ -6267,8 +6435,7 @@ uint8_t cds_search_and_check_for_session_conc(uint8_t session_id, * * True if the concurrency is allowed, false otherwise */ -bool cds_check_for_session_conc(uint8_t session_id, - uint8_t channel) +bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel) { hdd_context_t *hdd_ctx; hdd_adapter_t *adapter; @@ -6292,7 +6459,7 @@ bool cds_check_for_session_conc(uint8_t session_id, } /* Take care of 160MHz and 80+80Mhz later */ - ret = cds_allow_concurrency(hdd_ctx, + ret = cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( adapter->device_mode), channel, HW_MODE_20_MHZ); @@ -6314,8 +6481,7 @@ bool cds_check_for_session_conc(uint8_t session_id, * * Return: CDF_STATUS */ -CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, - uint8_t channel) +CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, uint8_t channel) { CDF_STATUS status; @@ -6344,15 +6510,20 @@ CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, * cds_restart_softap() - restart SAP on STA channel to support * STA + SAP concurrency. * - * @hdd_ctx: pointer to hdd context * @pHostapdAdapter: pointer to hdd adapter * * Return: None */ -void cds_restart_softap(hdd_context_t *hdd_ctx, - hdd_adapter_t *pHostapdAdapter) +void cds_restart_softap(hdd_adapter_t *pHostapdAdapter) { tHddAvoidFreqList hdd_avoid_freq_list; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } /* generate vendor specific event */ cdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); @@ -6368,7 +6539,6 @@ void cds_restart_softap(hdd_context_t *hdd_ctx, /** * cds_force_sap_on_scc() - Force SAP on SCC - * @hdd_ctx: Pointer to HDD context * @roam_result: Roam result * * Restarts SAP on SCC if its operating channel is different from that of the @@ -6376,9 +6546,16 @@ void cds_restart_softap(hdd_context_t *hdd_ctx, * * Return: None */ -void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result) +void cds_force_sap_on_scc(eCsrRoamResult roam_result) { hdd_adapter_t *hostapd_adapter; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } if (!(eCSR_ROAM_RESULT_ASSOCIATED == roam_result && hdd_ctx->config->SapSccChanAvoidance)) { @@ -6395,7 +6572,7 @@ void cds_force_sap_on_scc(hdd_context_t *hdd_ctx, eCsrRoamResult roam_result) cds_err("Restart SAP: SAP channel-%d, STA channel-%d", hostapd_adapter->sessionCtx.ap.operatingChannel, pRoamInfo->pBssDesc->channelId); - cds_restart_softap(hdd_ctx, hostapd_adapter); + cds_restart_softap(hostapd_adapter); } } } @@ -6459,15 +6636,22 @@ static void cds_check_sta_ap_concurrent_ch_intf(void *data) } /** * cds_check_concurrent_intf_and_restart_sap() - Check concurrent change intf - * @hdd_ctx: Pointer to HDD context * @hdd_sta_ctx: Pointer to HDD STA context * * Checks the concurrent change interface and restarts SAP * Return: None */ -void cds_check_concurrent_intf_and_restart_sap(hdd_context_t *hdd_ctx, - hdd_station_ctx_t *hdd_sta_ctx, hdd_adapter_t *adapter) +void cds_check_concurrent_intf_and_restart_sap(hdd_station_ctx_t *hdd_sta_ctx, + hdd_adapter_t *adapter) { + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } + if ((hdd_ctx->config->WlanMccToSccSwitchMode != CDF_MCC_TO_SCC_SWITCH_DISABLE) && ((0 == hdd_ctx->config->conc_custom_rule1) && @@ -6488,7 +6672,6 @@ void cds_check_concurrent_intf_and_restart_sap(hdd_context_t *hdd_ctx, /** * cds_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. @@ -6496,7 +6679,7 @@ void cds_check_concurrent_intf_and_restart_sap(hdd_context_t *hdd_ctx, * Return: Non zero value if MCC is detected in 2.4GHz band * */ -uint8_t cds_is_mcc_in_24G(hdd_context_t *hdd_ctx) +uint8_t cds_is_mcc_in_24G(void) { CDF_STATUS status; hdd_adapter_t *hdd_adapter = NULL; @@ -6507,6 +6690,13 @@ uint8_t cds_is_mcc_in_24G(hdd_context_t *hdd_ctx) uint8_t ch1 = 0, ch2 = 0; uint8_t channel = 0; hdd_hostapd_state_t *hostapd_state; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return 1; + } status = hdd_get_front_adapter(hdd_ctx, &adapter_node); @@ -7025,7 +7215,7 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) } } clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_decr_session_set_pcl(hdd_ctx, + cds_decr_session_set_pcl( ap_adapter->device_mode, ap_adapter->sessionId); cds_err("SAP Stop Success"); @@ -7060,7 +7250,7 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) } cds_err("SAP Start Success"); set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, + cds_incr_active_session(ap_adapter->device_mode, ap_adapter->sessionId); hostapd_state->bCommit = true; } @@ -7073,15 +7263,21 @@ end: #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE /** * cds_check_and_restart_sap_with_non_dfs_acs() - Restart SAP with non dfs acs - * @hdd_ctx: HDD context * * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported * * Return: None */ -void cds_check_and_restart_sap_with_non_dfs_acs(hdd_context_t *hdd_ctx) +void cds_check_and_restart_sap_with_non_dfs_acs(void) { hdd_adapter_t *ap_adapter; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return; + } if (cds_get_concurrency_mode() != (CDF_STA_MASK | CDF_SAP_MASK)) { cds_info("Concurrency mode is not SAP"); @@ -7106,13 +7302,20 @@ void cds_check_and_restart_sap_with_non_dfs_acs(hdd_context_t *hdd_ctx) } #endif #ifdef MPC_UT_FRAMEWORK -CDF_STATUS cds_update_connection_info_utfw(hdd_context_t *hdd_ctx, +CDF_STATUS cds_update_connection_info_utfw( uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0, found = 0; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { @@ -7141,16 +7344,23 @@ CDF_STATUS cds_update_connection_info_utfw(hdd_context_t *hdd_ctx, return CDF_STATUS_SUCCESS; } -CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, +CDF_STATUS cds_incr_connection_count_utfw( uint32_t vdev_id, uint32_t tx_streams, uint32_t rx_streams, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); - conn_index = cds_get_connection_count(hdd_ctx); + conn_index = cds_get_connection_count(); if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { /* err msg */ cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); @@ -7169,28 +7379,34 @@ CDF_STATUS cds_incr_connection_count_utfw(hdd_context_t *hdd_ctx, return CDF_STATUS_SUCCESS; } -CDF_STATUS cds_decr_connection_count_utfw(hdd_context_t *hdd_ctx, - uint32_t del_all, uint32_t vdev_id) +CDF_STATUS cds_decr_connection_count_utfw(uint32_t del_all, + uint32_t vdev_id) { CDF_STATUS status; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return CDF_STATUS_E_FAILURE; + } if (del_all) { - status = cds_init_policy_mgr(hdd_ctx); + status = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(status)) { cds_err("Policy manager initialization failed"); return CDF_STATUS_E_FAILURE; } } else { cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); - cds_decr_connection_count(hdd_ctx, vdev_id); + cds_decr_connection_count(vdev_id); cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); } return CDF_STATUS_SUCCESS; } -struct cds_conc_connection_info *cds_get_conn_info(hdd_context_t *hdd_ctx, - uint32_t *len) +struct cds_conc_connection_info *cds_get_conn_info(uint32_t *len) { struct cds_conc_connection_info *conn_ptr = &conc_connection_list[0]; *len = MAX_NUMBER_OF_CONC_CONNECTIONS; @@ -7198,8 +7414,7 @@ struct cds_conc_connection_info *cds_get_conn_info(hdd_context_t *hdd_ctx, return conn_ptr; } -enum cds_pcl_type get_pcl_from_first_conn_table( - enum cds_con_mode type, +enum cds_pcl_type get_pcl_from_first_conn_table(enum cds_con_mode type, enum cds_conc_priority_mode sys_pref) { if ((sys_pref >= CDS_MAX_CONC_PRIORITY_MODE) || diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 2c09426a1b48..e01b5bf61b7d 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -730,7 +730,7 @@ static void hdd_send_association_event(struct net_device *dev, return; } - cds_incr_active_session(pHddCtx, pAdapter->device_mode, + cds_incr_active_session(pAdapter->device_mode, pAdapter->sessionId); memcpy(wrqu.ap_addr.sa_data, pCsrRoamInfo->pBssDesc->bssId, sizeof(pCsrRoamInfo->pBssDesc->bssId)); @@ -815,8 +815,7 @@ static void hdd_send_association_event(struct net_device *dev, #endif } else if (eConnectionState_IbssConnected == /* IBss Associated */ pHddStaCtx->conn_info.connState) { - cds_update_connection_info(pHddCtx, - pAdapter->sessionId); + cds_update_connection_info(pAdapter->sessionId); memcpy(wrqu.ap_addr.sa_data, pHddStaCtx->conn_info.bssId.bytes, ETH_ALEN); pr_info("wlan: new IBSS connection to " MAC_ADDRESS_STR "\n", @@ -826,7 +825,7 @@ static void hdd_send_association_event(struct net_device *dev, pr_info("wlan: disconnected\n"); memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); cds_decr_session_set_pcl( - pHddCtx, pAdapter->device_mode, + pAdapter->device_mode, pAdapter->sessionId); #if defined(FEATURE_WLAN_LFR) wlan_hdd_enable_roaming(pAdapter); @@ -872,7 +871,7 @@ static void hdd_send_association_event(struct net_device *dev, hdd_stop_bus_bw_compute_timer(pAdapter); #endif } - cds_dump_concurrency_info(pHddCtx); + cds_dump_concurrency_info(); /* Send SCC/MCC Switching event to IPA */ hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); @@ -1419,7 +1418,7 @@ static void hdd_send_re_assoc_event(struct net_device *dev, * successful reassoc decrement the active session count here. */ cds_decr_session_set_pcl( - pHddCtx, pAdapter->device_mode, + pAdapter->device_mode, pAdapter->sessionId); /* Send the Assoc Resp, the supplicant needs this for initial Auth */ @@ -1772,7 +1771,7 @@ defined(WLAN_FEATURE_VOWIFI_11R) /* Indicate 'connect' status to user space */ hdd_send_association_event(dev, pRoamInfo); - if (cds_is_mcc_in_24G(pHddCtx)) { + if (cds_is_mcc_in_24G()) { if (pHddCtx->miracast_value) cds_set_mas(pAdapter, pHddCtx->miracast_value); } @@ -1849,7 +1848,7 @@ defined(FEATURE_WLAN_LFR) wlan_hdd_auto_shutdown_enable(pHddCtx, false); #endif - cds_check_concurrent_intf_and_restart_sap(pHddCtx, + cds_check_concurrent_intf_and_restart_sap( pHddStaCtx, pAdapter); @@ -1967,8 +1966,7 @@ defined(FEATURE_WLAN_LFR) * count here. */ cds_decr_session_set_pcl - (pHddCtx, - pAdapter->device_mode, + (pAdapter->device_mode, pAdapter->sessionId); hddLog(LOG1, FL("ft_carrier_on is %d, sending roamed indication"), @@ -2335,11 +2333,11 @@ defined(FEATURE_WLAN_LFR) WLAN_CONTROL_PATH); } - if (CDF_STATUS_SUCCESS != cds_check_and_restart_sap(pHddCtx, + if (CDF_STATUS_SUCCESS != cds_check_and_restart_sap( roamResult, pHddStaCtx)) return CDF_STATUS_E_FAILURE; - cds_force_sap_on_scc(pHddCtx, roamResult); + cds_force_sap_on_scc(roamResult); return CDF_STATUS_SUCCESS; } @@ -2461,12 +2459,11 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, bss); } if (eCSR_ROAM_RESULT_IBSS_STARTED == roamResult) { - cds_incr_active_session(pHddCtx, pAdapter->device_mode, + cds_incr_active_session(pAdapter->device_mode, pAdapter->sessionId); } else if (eCSR_ROAM_RESULT_IBSS_JOIN_SUCCESS == roamResult || eCSR_ROAM_RESULT_IBSS_COALESCED == roamResult) { - cds_update_connection_info(pHddCtx, - pAdapter->sessionId); + cds_update_connection_info(pAdapter->sessionId); } break; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 493b6e867bff..99de1e345b87 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1537,7 +1537,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, hdd_debug("get pcl for DO_ACS vendor command"); /* consult policy manager to get PCL */ - status = cds_get_pcl(hdd_ctx, CDS_SAP_MODE, + status = cds_get_pcl(CDS_SAP_MODE, sap_config->acs_cfg.pcl_channels, &sap_config->acs_cfg.pcl_ch_count); if (CDF_STATUS_SUCCESS != status) @@ -4113,7 +4113,7 @@ static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy, hdd_debug("Userspace requested pref freq list"); - status = cds_get_pcl(hdd_ctx, intf_mode, pcl, &pcl_len); + status = cds_get_pcl(intf_mode, pcl, &pcl_len); if (status != CDF_STATUS_SUCCESS) { hdd_err("Get pcl failed"); return -EINVAL; @@ -4237,7 +4237,7 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy, [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ])); /* check pcl table */ - if (!cds_allow_concurrency(hdd_ctx, intf_mode, + if (!cds_allow_concurrency(intf_mode, channel_hint, HW_MODE_20_MHZ)) { hdd_err("Set channel hint failed due to concurrency check"); return -EINVAL; @@ -6037,7 +6037,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, hddLog(CDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"), pAdapter->device_mode, type); - if (!cds_allow_concurrency(pHddCtx, + if (!cds_allow_concurrency( wlan_hdd_convert_nl_iftype_to_hdd_type(type), 0, HW_MODE_20_MHZ)) { hddLog(CDF_TRACE_LEVEL_DEBUG, @@ -6049,7 +6049,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, wdev = ndev->ieee80211_ptr; /* Reset the current device mode bit mask */ - cds_clear_concurrency_mode(pHddCtx, pAdapter->device_mode); + cds_clear_concurrency_mode(pAdapter->device_mode); hdd_tdls_notify_mode_change(pAdapter, pHddCtx); @@ -6231,7 +6231,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, done: /* Set bitmask based on updated value */ - cds_set_concurrency_mode(pHddCtx, pAdapter->device_mode); + cds_set_concurrency_mode(pAdapter->device_mode); #ifdef WLAN_FEATURE_LPSS wlan_hdd_send_all_scan_intf_info(pHddCtx); @@ -7955,7 +7955,7 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, } if (pHddCtx->config->policy_manager_enabled && - (true == cds_is_connection_in_progress(pHddCtx))) { + (true == cds_is_connection_in_progress())) { hdd_err("Connection refused: conn in progress"); return -EINVAL; } @@ -7994,9 +7994,9 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, * check for other concurrency rules. */ if (!pHddCtx->config->policy_manager_enabled) { - cds_handle_conc_rule1(pHddCtx, pAdapter, + cds_handle_conc_rule1(pAdapter, pRoamProfile); - if (true != cds_handle_conc_rule2(pHddCtx, + if (true != cds_handle_conc_rule2( pAdapter, pRoamProfile, &roamId)) return 0; } @@ -8829,7 +8829,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, if (0 != status) return status; if (req->channel) { - if (!cds_allow_concurrency(pHddCtx, + if (!cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( pAdapter->device_mode), req->channel->hw_value, HW_MODE_20_MHZ)) { @@ -8837,7 +8837,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, return -ECONNREFUSED; } } else { - if (!cds_allow_concurrency(pHddCtx, + if (!cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( pAdapter->device_mode), 0, HW_MODE_20_MHZ)) { hdd_err("This concurrency combination is not allowed"); @@ -9345,7 +9345,7 @@ static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy, } } - if (!cds_allow_concurrency(pHddCtx, CDS_IBSS_MODE, channelNum, + if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) { hdd_err("This concurrency combination is not allowed"); return -ECONNREFUSED; diff --git a/core/hdd/src/wlan_hdd_conc_ut.c b/core/hdd/src/wlan_hdd_conc_ut.c index 8ed71dd2338f..56470105971e 100644 --- a/core/hdd/src/wlan_hdd_conc_ut.c +++ b/core/hdd/src/wlan_hdd_conc_ut.c @@ -1,5 +1,5 @@ /* - * Copyright (c)2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -633,7 +633,7 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) CDF_STATUS ret; /* flush the entire table first */ - ret = cds_init_policy_mgr(hdd_ctx); + ret = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; @@ -641,7 +641,7 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) for (sub_type = 0; sub_type < CDS_MAX_NUM_OF_MODE; sub_type++) { /* validate one connection is created or no */ - if (cds_get_connection_count(hdd_ctx) != 0) { + if (cds_get_connection_count() != 0) { hddLog(LOGE, FL("Test failed - No. of connection is not 0")); return; @@ -651,7 +651,7 @@ void wlan_hdd_one_connection_scenario(hdd_context_t *hdd_ctx) pcl_type = get_pcl_from_first_conn_table(sub_type, system_pref); /* check PCL value for second connection is correct or no */ - cds_get_pcl(hdd_ctx, sub_type, pcl, &pcl_len); + cds_get_pcl(sub_type, pcl, &pcl_len); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, 0, 0, reason, sizeof(reason)); @@ -688,7 +688,7 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, type = wlan_hdd_valid_type_of_persona(sub_type); /* flush the entire table first */ - ret = cds_init_policy_mgr(hdd_ctx); + ret = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; @@ -697,11 +697,11 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, /* sub_type mapping between HDD and WMA are different */ wlan_hdd_map_subtypes_hdd_wma(&dummy_type, &sub_type); /* add first connection as STA */ - cds_incr_connection_count_utfw(hdd_ctx, vdevid, tx_stream, + cds_incr_connection_count_utfw(vdevid, tx_stream, rx_stream, chain_mask, type, dummy_type, channel_id, mac_id); /* validate one connection is created or no */ - if (cds_get_connection_count(hdd_ctx) != 1) { + if (cds_get_connection_count() != 1) { hddLog(LOGE, FL("Test failed - No. of connection is not 1")); return; @@ -710,8 +710,7 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, while (next_sub_type < CDS_MAX_NUM_OF_MODE) { /* get the PCL value & check the channels accordingly */ second_index = - cds_get_second_connection_pcl_table_index( - hdd_ctx); + cds_get_second_connection_pcl_table_index(); if (CDS_MAX_ONE_CONNECTION_MODE == second_index) { /* not valid combination*/ hddLog(LOGE, FL("couldn't find index for 2nd connection pcl table")); @@ -724,7 +723,7 @@ void wlan_hdd_two_connections_scenario(hdd_context_t *hdd_ctx, next_sub_type, system_pref, wma_is_hw_dbs_capable()); /* check PCL for second connection is correct or no */ - cds_get_pcl(hdd_ctx, next_sub_type, pcl, &pcl_len); + cds_get_pcl(next_sub_type, pcl, &pcl_len); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, channel_id, 0, reason, sizeof(reason)); @@ -787,7 +786,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, type_1 = wlan_hdd_valid_type_of_persona(sub_type_1); /* flush the entire table first */ - ret = cds_init_policy_mgr(hdd_ctx); + ret = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(ret)) { hdd_err("Policy manager initialization failed"); return; @@ -796,11 +795,11 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, /* sub_type mapping between HDD and WMA are different */ wlan_hdd_map_subtypes_hdd_wma(&dummy_type_1, &sub_type_1); /* add first connection as STA */ - cds_incr_connection_count_utfw(hdd_ctx, vdevid_1, + cds_incr_connection_count_utfw(vdevid_1, tx_stream_1, rx_stream_1, chain_mask_1, type_1, dummy_type_1, channel_id_1, mac_id_1); /* validate one connection is created or no */ - if (cds_get_connection_count(hdd_ctx) != 1) { + if (cds_get_connection_count() != 1) { hddLog(LOGE, FL("Test fail - No. of connection not 1")); return; @@ -812,11 +811,11 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, /* sub_type mapping between HDD and WMA are different */ wlan_hdd_map_subtypes_hdd_wma(&dummy_type_2, &sub_type_2); - cds_incr_connection_count_utfw(hdd_ctx, vdevid_2, + cds_incr_connection_count_utfw(vdevid_2, tx_stream_2, rx_stream_2, chain_mask_2, type_2, dummy_type_2, channel_id_2, mac_id_2); /* validate two connections are created or no */ - if (cds_get_connection_count(hdd_ctx) != 2) { + if (cds_get_connection_count() != 2) { hddLog(LOGE, FL("Test fail - No. connection not 2")); return; @@ -824,8 +823,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, next_sub_type = CDS_STA_MODE; while (next_sub_type < CDS_MAX_NUM_OF_MODE) { third_index = - cds_get_third_connection_pcl_table_index( - hdd_ctx); + cds_get_third_connection_pcl_table_index(); if (CDS_MAX_TWO_CONNECTION_MODE == third_index) { /* not valid combination */ @@ -839,7 +837,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, third_index, next_sub_type, system_pref, wma_is_hw_dbs_capable()); - cds_get_pcl(hdd_ctx, next_sub_type, + cds_get_pcl(next_sub_type, pcl, &pcl_len); status = wlan_hdd_validate_pcl(hdd_ctx, pcl_type, pcl, pcl_len, @@ -858,7 +856,7 @@ void wlan_hdd_three_connections_scenario(hdd_context_t *hdd_ctx, next_sub_type++; } /* remove entry to make a room for next iteration */ - cds_decr_connection_count(hdd_ctx, vdevid_2); + cds_decr_connection_count(vdevid_2); } next_sub_type = CDS_STA_MODE; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 02a6492e42a0..cecbbb0ee9c3 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -556,7 +556,7 @@ static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter, hddLog(LOGE, FL("Deleting SAP/P2P link!!!!!!")); clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); - cds_decr_session_set_pcl(pHddCtx, + cds_decr_session_set_pcl( pHostapdAdapter->device_mode, pHostapdAdapter->sessionId); } @@ -589,7 +589,7 @@ static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, } hal_handle = WLAN_HDD_GET_HAL_CTX(sta_adapter); - if (true == cds_is_sta_connection_pending(hdd_ctx)) { + if (true == cds_is_sta_connection_pending()) { MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_ISSUE_JOIN_REQ, sta_adapter->sessionId, roam_id)); @@ -601,7 +601,7 @@ static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, hdd_conn_set_connection_state(sta_adapter, eConnectionState_NotConnected); } - cds_change_sta_conn_pending_status(hdd_ctx, false); + cds_change_sta_conn_pending_status(false); } } @@ -999,7 +999,7 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, wrqu.data.length = strlen(startBssEvent); we_event = IWEVCUSTOM; we_custom_event_generic = we_custom_start_event; - cds_dump_concurrency_info(pHddCtx); + cds_dump_concurrency_info(); /* Send SCC/MCC Switching event to IPA */ hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); break; /* Event will be sent after Switch-Case stmt */ @@ -1792,7 +1792,7 @@ stopbss: we_custom_event_generic = we_custom_event; wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic); - cds_dump_concurrency_info(pHddCtx); + cds_dump_concurrency_info(); /* Send SCC/MCC Switching event to IPA */ hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); } @@ -4976,7 +4976,7 @@ __iw_softap_stopbss(struct net_device *dev, } } clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); - cds_decr_session_set_pcl(hdd_ctx, + cds_decr_session_set_pcl( pHostapdAdapter->device_mode, pHostapdAdapter->sessionId); } @@ -7237,7 +7237,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, uint16_t prev_rsn_length = 0; ENTER(); - if (cds_is_connection_in_progress(pHddCtx)) { + if (cds_is_connection_in_progress()) { hdd_err("Can't start BSS: connection is in progress"); return -EINVAL; } @@ -7661,7 +7661,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return 0; } - if (!cds_allow_concurrency(pHddCtx, + if (!cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( pHostapdAdapter->device_mode), pConfig->channel, HW_MODE_20_MHZ)) { @@ -7670,7 +7670,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return -EINVAL; } - if (!cds_set_connection_in_progress(pHddCtx, true)) { + if (!cds_set_connection_in_progress(true)) { hdd_err("Can't start BSS: set connnection in progress failed"); return -EINVAL; } @@ -7693,7 +7693,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pHostapdAdapter->dev); if (!CDF_IS_STATUS_SUCCESS(status)) { wlansap_reset_sap_config_add_ie(pConfig, eUPDATE_IE_ALL); - cds_set_connection_in_progress(pHddCtx, false); + cds_set_connection_in_progress(false); hddLog(LOGE, FL("SAP Start Bss fail")); return -EINVAL; } @@ -7708,7 +7708,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(LOGE, FL("ERROR: HDD cdf wait for single_event failed!!")); - cds_set_connection_in_progress(pHddCtx, false); + cds_set_connection_in_progress(false); sme_get_command_q_status(hHal); #ifdef WLAN_FEATURE_MBSSID wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter)); @@ -7722,7 +7722,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); /* Initialize WMM configuation */ hdd_wmm_init(pHostapdAdapter); - cds_incr_active_session(pHddCtx, pHostapdAdapter->device_mode, + cds_incr_active_session(pHostapdAdapter->device_mode, pHostapdAdapter->sessionId); #ifdef DHCP_SERVER_OFFLOAD if (iniConfig->enableDHCPServerOffload) @@ -7743,7 +7743,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } #endif - cds_set_connection_in_progress(pHddCtx, false); + cds_set_connection_in_progress(false); pHostapdState->bCommit = true; EXIT(); @@ -7883,7 +7883,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, } clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags); /*BSS stopped, clear the active sessions for this device mode*/ - cds_decr_session_set_pcl(pHddCtx, + cds_decr_session_set_pcl( pAdapter->device_mode, pAdapter->sessionId); pAdapter->sessionCtx.ap.beacon = NULL; @@ -8031,7 +8031,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, params->chandef.chan->center_freq); /* check if concurrency is allowed */ - if (!cds_allow_concurrency(pHddCtx, + if (!cds_allow_concurrency( cds_convert_device_mode_to_hdd_type( pAdapter->device_mode), channel, diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 0efca0fbb13b..c2c9938e37b4 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -4661,7 +4661,7 @@ static int drv_cmd_miracast(hdd_adapter_t *adapter, return -EBUSY; } - if (cds_is_mcc_in_24G(pHddCtx)) + if (cds_is_mcc_in_24G()) return cds_set_mas(adapter, filterType); exit: diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6f58aac08b41..91372fd1fc8b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2405,7 +2405,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, } if (CDF_STATUS_SUCCESS == status) { - cds_set_concurrency_mode(hdd_ctx, session_type); + cds_set_concurrency_mode(session_type); /* Initialize the WoWL service */ if (!hdd_init_wowl(adapter)) { @@ -2420,7 +2420,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, hddLog(CDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"), hdd_ctx->current_intf_count); - cds_check_and_restart_sap_with_non_dfs_acs(hdd_ctx); + cds_check_and_restart_sap_with_non_dfs_acs(); } if ((cds_get_conparam() != CDF_GLOBAL_FTM_MODE) @@ -2588,7 +2588,7 @@ CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, } adapterNode = pCurrent; if (CDF_STATUS_SUCCESS == status) { - cds_clear_concurrency_mode(hdd_ctx, adapter->device_mode); + cds_clear_concurrency_mode(adapter->device_mode); hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held); hdd_remove_adapter(hdd_ctx, adapterNode); @@ -2787,7 +2787,7 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, cds_flush_work(&hdd_ctx->sap_start_work); hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("Canceled the pending SAP restart work")); - cds_change_sap_restart_required_status(hdd_ctx, false); + cds_change_sap_restart_required_status(false); } /* Any softap specific cleanup here... */ if (adapter->device_mode == WLAN_HDD_P2P_GO) @@ -2798,14 +2798,14 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, mutex_lock(&hdd_ctx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { CDF_STATUS status; - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); /* Stop Bss. */ #ifdef WLAN_FEATURE_MBSSID status = wlansap_stop_bss( WLAN_HDD_GET_SAP_CTX_PTR(adapter)); #else - status = wlansap_stop_bss(hdd_ctx->pcds_context); + status = wlansap_stop_bss( + (WLAN_HDD_GET_CTX(adapter))->pcds_context); #endif if (CDF_IS_STATUS_SUCCESS(status)) { @@ -2829,7 +2829,7 @@ CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, hddLog(LOGE, FL("failure in wlansap_stop_bss")); } clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); - cds_decr_session_set_pcl(hdd_ctx, + cds_decr_session_set_pcl( adapter->device_mode, adapter->sessionId); @@ -2920,7 +2920,7 @@ CDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) adapter->sessionCtx.station.hdd_ReassocScenario = false; hdd_deinit_tx_rx(adapter); - cds_decr_session_set_pcl(hdd_ctx, + cds_decr_session_set_pcl( adapter->device_mode, adapter->sessionId); if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { @@ -4875,7 +4875,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_ctx->isLogpInProgress = false; cds_set_logp_in_progress(false); - cds_set_connection_in_progress(hdd_ctx, false); + cds_set_connection_in_progress(false); hdd_wlan_green_ap_init(hdd_ctx); @@ -5294,7 +5294,7 @@ ftm_processing: #endif wlan_hdd_nan_init(hdd_ctx); - status = cds_init_policy_mgr(hdd_ctx); + status = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(status)) { hdd_err("Policy manager initialization failed"); goto err_nl_srv; @@ -6252,7 +6252,7 @@ void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) } } clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_decr_session_set_pcl(hdd_ctx, + cds_decr_session_set_pcl( ap_adapter->device_mode, ap_adapter->sessionId); hddLog(CDF_TRACE_LEVEL_INFO_HIGH, @@ -6328,7 +6328,7 @@ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) } hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success")); set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_incr_active_session(hdd_ctx, ap_adapter->device_mode, + cds_incr_active_session(ap_adapter->device_mode, ap_adapter->sessionId); hostapd_state->bCommit = true; diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index f8d7acb00578..8d35b4cf29c9 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -845,8 +845,7 @@ static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy, ret = wlan_hdd_validate_context(pHddCtx); if (0 != ret) return ret; - if (cds_is_connection_in_progress( - (hdd_context_t *) pAdapter->pHddCtx)) { + if (cds_is_connection_in_progress()) { hddLog(LOGE, FL("Connection is in progress")); isBusy = true; } diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 46c0cfc55550..99880912236d 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1337,7 +1337,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, #endif /* Check if scan is allowed at this point of time */ - if (cds_is_connection_in_progress(pHddCtx)) { + if (cds_is_connection_in_progress()) { hddLog(LOGE, FL("Scan not allowed")); return -EBUSY; } diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 42b9950331cc..e6935bafb2b9 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -6875,7 +6875,7 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, return -EPERM; } hdd_debug("%d %d %d", value[1], value[2], value[3]); - cds_set_dual_mac_scan_config(hdd_ctx, + cds_set_dual_mac_scan_config( value[1], value[2], value[3]); break; @@ -7693,7 +7693,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, { hddLog(LOGE, FL(" is called\n")); - cds_incr_connection_count_utfw(hdd_ctx, apps_args[0], + cds_incr_connection_count_utfw(apps_args[0], apps_args[1], apps_args[2], apps_args[3], apps_args[4], apps_args[5], apps_args[6], apps_args[7]); @@ -7704,7 +7704,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, { hddLog(LOGE, FL(" is called\n")); - cds_decr_connection_count_utfw(hdd_ctx, apps_args[0], + cds_decr_connection_count_utfw(apps_args[0], apps_args[1]); } break; @@ -7713,7 +7713,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, { hddLog(LOGE, FL(" is called\n")); - cds_update_connection_info_utfw(hdd_ctx, apps_args[0], + cds_update_connection_info_utfw(apps_args[0], apps_args[1], apps_args[2], apps_args[3], apps_args[4], apps_args[5], apps_args[6], apps_args[7]); @@ -7745,7 +7745,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, hddLog(LOGE, FL(" is called\n")); - cds_get_pcl(hdd_ctx, apps_args[0], + cds_get_pcl(apps_args[0], pcl, &pcl_len); pr_info("PCL list for role[%d] is {", apps_args[0]); for (i = 0 ; i < pcl_len; i++) @@ -7761,7 +7761,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, hddLog(LOGE, FL(" is called\n")); - conn_info = cds_get_conn_info(hdd_ctx, &len); + conn_info = cds_get_conn_info(&len); pr_info("+-----------------------------+\n"); for (i = 0; i < len; i++) { pr_info("|table_index[%d]\t\t|\n", i); @@ -7787,7 +7787,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, if (apps_args[0] == 0) { hddLog(LOGE, FL("set hw mode for single mac\n")); - cds_soc_set_hw_mode(hdd_ctx, + cds_soc_set_hw_mode( pAdapter->sessionId, HW_MODE_SS_2x2, HW_MODE_80_MHZ, @@ -7798,7 +7798,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, } else if (apps_args[0] == 1) { hddLog(LOGE, FL("set hw mode for dual mac\n")); - cds_soc_set_hw_mode(hdd_ctx, + cds_soc_set_hw_mode( pAdapter->sessionId, HW_MODE_SS_1x1, HW_MODE_80_MHZ, @@ -7826,7 +7826,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, bool allow; hddLog(LOGE, FL(" is called\n")); - allow = cds_allow_concurrency(hdd_ctx, + allow = cds_allow_concurrency( apps_args[0], apps_args[1], apps_args[2]); pr_info("allow %d {0 = don't allow, 1 = allow}", allow); } @@ -9513,7 +9513,7 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, return -EPERM; } hdd_debug("%d %d", value[1], value[2]); - cds_set_dual_mac_fw_mode_config(hdd_ctx, + cds_set_dual_mac_fw_mode_config( value[1], value[2]); break; case WE_DUMP_DP_TRACE_LEVEL: diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 95da9e7dd1b9..a11a1062dea8 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1990,9 +1990,9 @@ csr_parse_scan_results(tpAniSirGlobal pMac, csr_ll_lock(&pMac->scan.scanResultList); if (pFilter) { - if (cds_map_concurrency_mode(pMac->hHdd, + if (cds_map_concurrency_mode( &pFilter->csrPersona, &new_mode)) { - status = cds_get_pcl(pMac->hHdd, new_mode, + status = cds_get_pcl(new_mode, &pFilter->pcl_channels.channelList[0], &len); pFilter->pcl_channels.numChannels = (uint8_t)len; } @@ -5485,7 +5485,7 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, * out IBSS channel's band otherwise it will cause issue * in IBSS+STA concurrency */ - if (true == cds_is_ibss_conn_exist(mac_ctx->hHdd, &ibss_channel)) { + if (true == cds_is_ibss_conn_exist(&ibss_channel)) { sms_log(mac_ctx, LOG1, FL("Conc IBSS exist, channel list will be modified")); } -- cgit v1.2.3 From 31f0317102a0f47a7477bfbdd4694ec9b3be2d09 Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Wed, 5 Aug 2015 15:16:35 -0700 Subject: qcacld-3.0: Optionally report raw rssi value to supplicant qcacld-2.0 to qcacld-3.0 propagation Add raw rssi in the beacon header from WMI to beacon descriptor. Pass it up to SME and report it to supplicant through a call to wlan_hdd_cfg80211_inform_bss_frame(). It can be enabled as a .ini configuration parameter "gInformBssRssiRaw". Default is 1, it will report raw rssi by default. Roaming decisions are based on rssi field of beacon descriptor, its interpretation and usage are unchanged. CRs-Fixed: 815344 Change-Id: I6dacdc0b333c093d16a74f8cf36471dfc183ce56 --- core/cds/src/i_cds_packet.h | 24 +++++++++++++++++- core/hdd/inc/wlan_hdd_cfg.h | 11 ++++++++- core/hdd/src/wlan_hdd_cfg.c | 7 ++++++ core/hdd/src/wlan_hdd_cfg80211.c | 11 ++++++++- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_action_frame.c | 4 +-- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 2 +- core/mac/src/pe/lim/lim_process_auth_frame.c | 4 +-- core/mac/src/pe/lim/lim_process_message_queue.c | 4 +-- core/mac/src/pe/lim/lim_process_probe_rsp_frame.c | 5 ++-- core/mac/src/pe/lim/lim_scan_result_utils.c | 7 +++++- core/mac/src/pe/rrm/rrm_api.c | 2 +- core/sme/src/csr/csr_api_scan.c | 30 ++++++++++++++--------- core/wma/inc/wma_types.h | 11 ++++++--- core/wma/src/wma_mgmt.c | 22 ++++++++++++++--- 15 files changed, 113 insertions(+), 33 deletions(-) diff --git a/core/cds/src/i_cds_packet.h b/core/cds/src/i_cds_packet.h index 23858fedd2bc..0a0e3a69f757 100644 --- a/core/cds/src/i_cds_packet.h +++ b/core/cds/src/i_cds_packet.h @@ -42,8 +42,29 @@ Include Files ------------------------------------------------------------------------*/ #include "cdf_types.h" -/* +/** * Rx Packet Struct + * Buffer for the packet received from WMA has pointers to 802.11 + * frame fields and additional information based on the type of frame. + * @channel: Channel number + * @snr: Signal to noise ratio + * @rssi: Received signal strength indicator, 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. + * @timestamp: System timestamp when frame was received. Set to jiffies. + * @mpdu_hdr_ptr: Pointer to beginning of 802.11 MPDU + * @mpdu_data_ptr: Pointer to beginning of payload + * @mpdu_len: Length of 802.11 MPDU + * @mpdu_hdr_len: Length of 802.11 MPDU header + * @mpdu_data_len: Length of 802.11 MPDU payload + * @offloadScanLearn: Bit set to 1 for beacons received during roaming scan + * @roamCandidateInd: Bit set to 1 when roaming candidate is found by fw + * @scan: Bit set to 1 if packet received during scanning + * @scan_src: Source of scan + * @dpuFeedback: DPU feedback for frame + * @sessionId: PE session + * @tsf_delta: Delta between tsf in frame and local value of tsf + * @rssi_raw: rssi based on actual noise floor in hardware. */ typedef struct { uint8_t channel; @@ -62,6 +83,7 @@ typedef struct { uint8_t dpuFeedback; uint8_t sessionId; uint32_t tsf_delta; + uint32_t rssi_raw; } t_packetmeta, *tp_packetmeta; /* implementation specific cds packet type */ diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index d37bdcdeb80d..92c51b7abbec 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2853,6 +2853,14 @@ enum dot11p_mode { #define CFG_ENABLE_LFR_SUBNET_MAX (1) #define CFG_ENABLE_LFR_SUBNET_DEFAULT (1) #endif /* FEATURE_LFR_SUBNET_DETECTION */ +/* 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) /*--------------------------------------------------------------------------- Type declarations @@ -3441,6 +3449,7 @@ struct hdd_config { #ifdef FEATURE_LFR_SUBNET_DETECTION bool enable_lfr_subnet_detection; #endif + uint8_t inform_bss_rssi_raw; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) @@ -3530,7 +3539,7 @@ typedef enum { 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 */ + WLAN_PARAMETER_TYPE RegType; /* variable type in hdd_config struct */ 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 */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 33a41f009a13..3cb0e6b82c48 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3666,6 +3666,13 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ENABLE_LFR_SUBNET_MIN, CFG_ENABLE_LFR_SUBNET_MAX), #endif + + REG_VARIABLE(CFG_INFORM_BSS_RSSI_RAW_NAME, WLAN_PARAM_Integer, + struct hdd_config, 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), }; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 99de1e345b87..ac59b0b6890e 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7307,6 +7307,7 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, #ifdef CONFIG_CNSS struct timespec ts; #endif + struct hdd_config *cfg_param; ENTER(); @@ -7315,6 +7316,7 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, if (0 != status) return NULL; + cfg_param = pHddCtx->config; mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL); if (!mgmt) { hddLog(LOGE, FL("memory allocation failed")); @@ -7408,8 +7410,15 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, 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 = (CDF_MIN((bss_desc->rssi + bss_desc->sinr), 0)) * 100; + rssi = CDF_MIN(rssi, 0) * 100; hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"), MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 219c5ecabfaf..2577959cc4af 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -625,8 +625,8 @@ typedef struct sSirBssDescription { uint16_t beaconInterval; uint16_t capabilityInfo; tSirNwType nwType; /* Indicates 11a/b/g */ - uint8_t reserved_padding0; int8_t rssi; + int8_t rssi_raw; int8_t sinr; /* channelId what peer sent in beacon/probersp. */ uint8_t channelId; diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 2ef83fd10038..277234c5421e 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1895,7 +1895,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, case SIR_MAC_WNM_BSS_TM_RESPONSE: case SIR_MAC_WNM_NOTIF_REQUEST: case SIR_MAC_WNM_NOTIF_RESPONSE: - rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); /* Forward to the SME to HDD to wpa_supplicant */ lim_send_sme_mgmt_frame_ind(mac_ctx, @@ -2056,7 +2056,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); - rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, ("Public Action TDLS Discovery RSP ..")); lim_send_sme_mgmt_frame_ind(mac_ctx, diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index be37a64b9232..8e0ed5a1ab33 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -611,7 +611,7 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, "and mlmstate: %d RSSI %d from " MAC_ADDRESS_STR), subtype, session_entry->peSessionId, GET_LIM_SYSTEM_ROLE(session_entry), session_entry->limMlmState, - (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(rx_pkt_info)), + (uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info)), MAC_ADDR_ARRAY(hdr->sa)); beacon = cdf_mem_malloc(sizeof(tSchBeaconStruct)); diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index 9871cff47c9b..526b5f4763d9 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -190,7 +190,7 @@ lim_process_auth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, "Frame Received: BSSID: " MAC_ADDRESS_STR " (RSSI %d)"), psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->bssId), - (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo))); + (uint) abs((int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo))); pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -1775,7 +1775,7 @@ tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *pB lim_log(pMac, LOG1, FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), MAC_ADDR_ARRAY(pHdr->bssId), - (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pBd))); + (uint) abs((int8_t) WMA_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 diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 928e5d7d5329..ca614fe4ea37 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -352,7 +352,7 @@ __lim_pno_match_fwd_bcn_probepsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, result->ap[i].capability = lim_get_u16((uint8_t *) &frame->capabilityInfo); result->ap[i].channel = WMA_GET_RX_CH(rx_pkt_info); - result->ap[i].rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + result->ap[i].rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); result->ap[i].rtt = 0; result->ap[i].rtt_sd = 0; result->ap[i].ieLength = ie_len; @@ -403,7 +403,7 @@ __lim_ext_scan_forward_bcn_probe_rsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, result->ap.capability = lim_get_u16((uint8_t *) &frame->capabilityInfo); result->ap.channel = WMA_GET_RX_CH(rx_pkt_info); - result->ap.rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info); + result->ap.rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); result->ap.rtt = 0; result->ap.rtt_sd = 0; result->ap.ieLength = ie_len; diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c index 1cfd74340774..16b960cf5e8d 100644 --- a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c @@ -129,7 +129,7 @@ lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info, FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), MAC_ADDR_ARRAY(header->bssId), - (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_Packet_info))); + (uint) abs((int8_t)WMA_GET_RX_RSSI_NORMALIZED(rx_Packet_info))); /* Get pointer to Probe Response frame body */ body = WMA_GET_RX_MPDU_DATA(rx_Packet_info); /* Enforce Mandatory IEs */ @@ -349,7 +349,8 @@ lim_process_probe_rsp_frame_no_session(tpAniSirGlobal mac_ctx, FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), MAC_ADDR_ARRAY(header->bssId), - (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_packet_info))); + (uint) abs((int8_t)WMA_GET_RX_RSSI_NORMALIZED( + rx_packet_info))); /* * Get pointer to Probe Response frame body */ diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.c b/core/mac/src/pe/lim/lim_scan_result_utils.c index 387152e92fee..85d60932d66a 100644 --- a/core/mac/src/pe/lim/lim_scan_result_utils.c +++ b/core/mac/src/pe/lim/lim_scan_result_utils.c @@ -177,10 +177,15 @@ lim_collect_bss_description(tpAniSirGlobal pMac, sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, (uint8_t *) pRxPacketInfo, 36); - pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo); + pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo); + pBssDescr->rssi_raw = (int8_t) WMA_GET_RX_RSSI_RAW(pRxPacketInfo); /* SINR no longer reported by HW */ pBssDescr->sinr = 0; + lim_log(pMac, LOG3, + FL(MAC_ADDRESS_STR " rssi: normalized = %d, absolute = %d"), + MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->rssi, + pBssDescr->rssi_raw); pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks(); pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo); diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index 38f748a0d478..1104a938f528 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -306,7 +306,7 @@ rrm_process_link_measurement_request(tpAniSirGlobal pMac, LinkReport.dialogToken = pLinkReq->DialogToken.token; LinkReport.rxAntenna = 0; LinkReport.txAntenna = 0; - currentRSSI = WMA_GET_RX_RSSI_DB(pRxPacketInfo); + currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo); lim_log(pMac, LOG1, "Received Link report frame with %d", currentRSSI); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index a11a1062dea8..b775de7e74a8 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2506,7 +2506,6 @@ bool csr_remove_dup_bss_description(tpAniSirGlobal pMac, tListElem *pEntry; tCsrScanResult *scan_entry; bool fRC = false; - int8_t scan_entry_rssi = 0; /* * Walk through all the chained BssDescriptions. If we find a chained @@ -2526,17 +2525,24 @@ bool csr_remove_dup_bss_description(tpAniSirGlobal pMac, if (csr_is_duplicate_bss_description(pMac, &scan_entry->Result.BssDescriptor, bss_dscp, pIes, fForced)) { - /* - * Following is mathematically a = (aX + b(100-X))/100 - * where: - * a = bss_dscp->rssi, b = scan_entry_rssi - * and X = CSR_SCAN_RESULT_RSSI_WEIGHT - */ - scan_entry_rssi = scan_entry->Result.BssDescriptor.rssi; - bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi * - CSR_SCAN_RESULT_RSSI_WEIGHT) + - ((int32_t) scan_entry_rssi * - (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100); + int32_t rssi_new, rssi_old; + + rssi_new = (int32_t) bss_dscp->rssi; + rssi_old = (int32_t) scan_entry-> + Result.BssDescriptor.rssi; + rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + + rssi_old * + (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; + bss_dscp->rssi = (int8_t) rssi_new; + + rssi_new = (int32_t) bss_dscp->rssi_raw; + rssi_old = (int32_t) scan_entry-> + Result.BssDescriptor.rssi_raw; + rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + + rssi_old * + (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; + bss_dscp->rssi_raw = (int8_t) rssi_new; + /* Remove the old entry from the list */ if (csr_ll_remove_entry (&pMac->scan.scanResultList, pEntry, diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 0f244989b1c7..d769a78555b6 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -123,9 +123,14 @@ #define WMA_GET_RX_RFBAND(pRxMeta) 0 -#define WMA_MAX_TXPOWER_INVALID 127 -#define WMA_GET_RX_RSSI_DB(pRxMeta) \ - (((t_packetmeta *)pRxMeta)->rssi) +#define WMA_MAX_TXPOWER_INVALID 127 +/* rssi value normalized to noise floor of -96 dBm */ +#define WMA_GET_RX_RSSI_NORMALIZED(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->rssi) + +/* raw rssi based on actual noise floor in hardware */ +#define WMA_GET_RX_RSSI_RAW(pRxMeta) \ + (((t_packetmeta *)pRxMeta)->rssi_raw) /* WMA Messages */ #define WMA_MSG_TYPES_BEGIN SIR_HAL_MSG_TYPES_BEGIN diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 9d4d402c4df4..9e46b64d23f7 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3191,10 +3191,21 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, */ rx_pkt->pkt_meta.channel = hdr->channel; rx_pkt->pkt_meta.scan_src = hdr->flags; - /*Get the absolute rssi value from the current rssi value - *the sinr value is hardcoded into 0 in the core stack*/ - rx_pkt->pkt_meta.rssi = hdr->snr + WMA_TGT_NOISE_FLOOR_DBM; + + /* + * Get the rssi value from the current snr value + * using standard noise floor of -96. + */ + rx_pkt->pkt_meta.rssi = hdr->snr + WMA_NOISE_FLOOR_DBM_DEFAULT; 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. @@ -3253,6 +3264,11 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, cdf_mem_copy(wh, param_tlvs->bufp, hdr->buf_len); #endif + WMA_LOGD( + FL("BSSID: "MAC_ADDRESS_STR" snr = %d, rssi = %d, rssi_raw = %d"), + MAC_ADDR_ARRAY(wh->i_addr3), + hdr->snr, rx_pkt->pkt_meta.rssi, + rx_pkt->pkt_meta.rssi_raw); if (!wma_handle->mgmt_rx) { WMA_LOGE("Not registered for Mgmt rx, dropping the frame"); cds_pkt_return_packet(rx_pkt); -- cgit v1.2.3 From a56eeac9d40b92d44f7a26782adc6a37729dafd6 Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Thu, 6 Aug 2015 14:16:53 -0700 Subject: qcacld-3.0: Fix issue about signal jump rssi_raw should not be updated when the channel in probe response does not match the channel in BD. Added rx_channel field to beacon descriptor passed from LIM to CSR. Channel check is performed in csr_remove_dup_bss_description() before computing new averaged rssi. CRs-Fixed: 873549 Change-Id: Iefacbf73f880e9d0c957ad83839dd2203fdf862d --- core/mac/inc/sir_api.h | 3 ++- core/mac/src/pe/lim/lim_scan_result_utils.c | 2 ++ core/sme/src/csr/csr_api_scan.c | 41 +++++++++++++++++------------ 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 2577959cc4af..162cebc9c294 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -655,7 +655,8 @@ typedef struct sSirBssDescription { /* whether it is from a probe rsp */ uint8_t fProbeRsp; - uint8_t reservedPadding1; + /* Actual channel the beacon/probe response was received on */ + uint8_t rx_channel; uint8_t reservedPadding2; uint8_t reservedPadding3; uint32_t WscIeLen; diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.c b/core/mac/src/pe/lim/lim_scan_result_utils.c index 85d60932d66a..a26a289531c5 100644 --- a/core/mac/src/pe/lim/lim_scan_result_utils.c +++ b/core/mac/src/pe/lim/lim_scan_result_utils.c @@ -165,6 +165,8 @@ lim_collect_bss_description(tpAniSirGlobal pMac, } pBssDescr->channelIdSelf = pBssDescr->channelId; + pBssDescr->rx_channel = rxChannel; + /* set the network type in bss description */ channelNum = pBssDescr->channelId; pBssDescr->nwType = diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index b775de7e74a8..fde1c3038bb1 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2525,23 +2525,30 @@ bool csr_remove_dup_bss_description(tpAniSirGlobal pMac, if (csr_is_duplicate_bss_description(pMac, &scan_entry->Result.BssDescriptor, bss_dscp, pIes, fForced)) { - int32_t rssi_new, rssi_old; - - rssi_new = (int32_t) bss_dscp->rssi; - rssi_old = (int32_t) scan_entry-> - Result.BssDescriptor.rssi; - rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + - rssi_old * - (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; - bss_dscp->rssi = (int8_t) rssi_new; - - rssi_new = (int32_t) bss_dscp->rssi_raw; - rssi_old = (int32_t) scan_entry-> - Result.BssDescriptor.rssi_raw; - rssi_new = ((rssi_new * CSR_SCAN_RESULT_RSSI_WEIGHT) + - rssi_old * - (100 - CSR_SCAN_RESULT_RSSI_WEIGHT)) / 100; - bss_dscp->rssi_raw = (int8_t) rssi_new; + if (bss_dscp->rx_channel == bss_dscp->channelId) { + /* + * Update rssi values only if beacon is + * received on the same channel that was + * sent on. + */ + int32_t rssi_new, rssi_old; + const int32_t weight = + CSR_SCAN_RESULT_RSSI_WEIGHT; + + rssi_new = (int32_t) bss_dscp->rssi; + rssi_old = (int32_t) scan_entry-> + Result.BssDescriptor.rssi; + rssi_new = ((rssi_new * weight) + + rssi_old * (100 - weight)) / 100; + bss_dscp->rssi = (int8_t) rssi_new; + + rssi_new = (int32_t) bss_dscp->rssi_raw; + rssi_old = (int32_t) scan_entry-> + Result.BssDescriptor.rssi_raw; + rssi_new = ((rssi_new * weight) + + rssi_old * (100 - weight)) / 100; + bss_dscp->rssi_raw = (int8_t) rssi_new; + } /* Remove the old entry from the list */ if (csr_ll_remove_entry -- cgit v1.2.3 From 1a934bdc7a396b60dea8cfc208756d4f0b79e8e6 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Wed, 23 Dec 2015 20:36:11 +0530 Subject: qcacld-3.0: Do not allocate mgmt descriptors Do not allocate txrx descriptors for management if management over WMI is enabled. Change-Id: Iafb231bebe83b658940119ed13a41d64a10d4eb0 CRs-Fixed: 955450 --- core/dp/txrx/ol_txrx.c | 8 +++++--- core/dp/txrx/ol_txrx_flow_control.c | 6 ++++++ core/wma/src/wma_main.c | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index df24d693c900..05e4d0a3e060 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -313,9 +313,11 @@ void ol_tx_set_desc_global_pool_size(uint32_t num_msdu_desc) cdf_print("%s: pdev is NULL\n", __func__); return; } - pdev->num_msdu_desc = num_msdu_desc + TX_FLOW_MGMT_POOL_SIZE; - TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global pool size: %d = %d + %d\n", - pdev->num_msdu_desc, num_msdu_desc, TX_FLOW_MGMT_POOL_SIZE); + pdev->num_msdu_desc = num_msdu_desc; + if (!ol_tx_get_is_mgmt_over_wmi_enabled()) + pdev->num_msdu_desc += TX_FLOW_MGMT_POOL_SIZE; + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global pool size: %d\n", + pdev->num_msdu_desc); return; } diff --git a/core/dp/txrx/ol_txrx_flow_control.c b/core/dp/txrx/ol_txrx_flow_control.c index 21d49908053f..77fd41ee1ed4 100644 --- a/core/dp/txrx/ol_txrx_flow_control.c +++ b/core/dp/txrx/ol_txrx_flow_control.c @@ -430,6 +430,9 @@ int ol_tx_delete_flow_pool(struct ol_tx_flow_pool_t *pool) cdf_spin_unlock_bh(&pool->flow_pool_lock); pdev->tx_desc.num_invalid_bin++; + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid pool created %d\n", + __func__, pdev->tx_desc.num_invalid_bin); if (pdev->tx_desc.num_invalid_bin > MAX_INVALID_BIN) ASSERT(0); @@ -477,6 +480,9 @@ int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool) cdf_spin_unlock_bh(&pool->flow_pool_lock); pdev->tx_desc.num_invalid_bin--; + TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, + "%s: invalid pool deleted %d\n", + __func__, pdev->tx_desc.num_invalid_bin); return ol_tx_delete_flow_pool(pool); } diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 07263102f653..f493262c8c0a 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3771,7 +3771,6 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) wma_handle->num_rf_chains = ev->num_rf_chains; wma_handle->target_fw_version = ev->fw_build_vers; - ol_tx_set_desc_global_pool_size(ev->num_msdu_desc); wma_handle->new_hw_mode_index = ev->default_dbs_hw_mode_index; WMA_LOGD("%s: Firmware default hw mode index : %d", @@ -3805,6 +3804,7 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) ol_tx_set_is_mgmt_over_wmi_enabled( WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, WMI_SERVICE_MGMT_TX_WMI)); + ol_tx_set_desc_global_pool_size(ev->num_msdu_desc); /* SWBA event handler for beacon transmission */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, -- cgit v1.2.3 From 8773696a276824f3cf1b6180c7e8de6c496ca4d8 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Tue, 29 Dec 2015 08:43:28 -0800 Subject: qcacld-3.0: Use assoc req len from roam sync msg in if condition Use assoc req from roam_sync_ind_ptr instead of ft_session_ptr in condition statement. assoc req from ft_session_ptr is not populated yet and hence will be 0 when the condition is invoked. This will cause if block to never execute. Change-Id: I9cd758674d13603087de013a0aea751032bc8603 CRs-Fixed: 957591 --- core/mac/src/pe/lim/lim_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index bd221069ef15..f516859e0955 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2037,7 +2037,7 @@ void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) /* Prepare the session right now with as much as possible */ lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr); - if (ft_session_ptr->assocReqLen) { + if (roam_sync_ind_ptr->reassoc_req_length) { /* * For LFR3 the Assoc Request frame was sent by firmware, hence * pe session struct does not have corresponding IEs. Firmware -- cgit v1.2.3 From 7b36dbfc440a9f9c3bea12027bd5814eccbac721 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Tue, 5 Jan 2016 11:30:07 -0800 Subject: Release 5.0.0.155 Release 5.0.0.155 Change-Id: I1ca017dec644ec2d352a3576e28a28302e412b30 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index b2f1445f0799..b6f86a1c5bcd 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 154 +#define QWLAN_VERSION_BUILD 155 -#define QWLAN_VERSIONSTR "5.0.0.154" +#define QWLAN_VERSIONSTR "5.0.0.155" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 2b72327980a1a39cc63015ceab5afec63bd21a06 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Fri, 20 Nov 2015 13:35:05 -0800 Subject: qcacld-3.0: Add event handler for oem data response Add event handler for oem data response event from FW. Add new boolean member to differentiate the response generated internally and one coming from the FW. Change-Id: Ia906c5dcbb7e560fd78ccd96fc47c7801b33aa6a CRs-Fixed: 942261 --- core/mac/inc/sir_api.h | 3 +- core/mac/src/pe/include/lim_global.h | 3 +- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 4 +- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 4 +- core/sme/src/oem_data/oem_data_api.c | 30 +++++------ core/wma/inc/wma_if.h | 3 +- core/wma/inc/wma_internal.h | 5 +- core/wma/src/wma_features.c | 60 ++++++++++++++++++++-- core/wma/src/wma_main.c | 6 ++- 9 files changed, 90 insertions(+), 28 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 162cebc9c294..e5dde5720b44 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -881,6 +881,7 @@ typedef struct sSirOemDataReq { typedef struct sSirOemDataRsp { uint16_t messageType; uint16_t length; + bool target_rsp; uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; } tSirOemDataRsp, *tpSirOemDataRsp; diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index c40bb1cef5dd..b5825b4f6203 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -311,6 +311,7 @@ typedef struct sLimMlmOemDataReq { } tLimMlmOemDataReq, *tpLimMlmOemDataReq; typedef struct sLimMlmOemDataRsp { + bool target_rsp; uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; } tLimMlmOemDataRsp, *tpLimMlmOemDataRsp; #endif diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 11561472d032..2de1a1db93ad 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -421,6 +421,7 @@ error: ("memory allocation for mlm_oem_data_rsp")); return; } + mlm_oem_data_rsp->target_rsp = false; if (NULL != mac_ctx->lim.gpLimMlmOemDataReq) { cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq); @@ -822,6 +823,7 @@ static void lim_process_mlm_oem_data_req(tpAniSirGlobal mac_ctx, /* Return Meas confirm with INVALID_PARAMETERS */ mlm_oem_data_rsp = cdf_mem_malloc(sizeof(tLimMlmOemDataRsp)); if (mlm_oem_data_rsp != NULL) { + mlm_oem_data_rsp->target_rsp = false; lim_post_sme_message(mac_ctx, LIM_MLM_OEM_DATA_CNF, (uint32_t *) mlm_oem_data_rsp); cdf_mem_free(mlm_oem_data_rsp); diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 1eab1eccb9a1..ff4848c2dd44 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -844,7 +844,7 @@ void lim_send_sme_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *pMsgBuf, pSirSmeOemDataRsp->length = msgLength; pSirSmeOemDataRsp->messageType = eWNI_SME_OEM_DATA_RSP; #endif - + pSirSmeOemDataRsp->target_rsp = pMlmOemDataRsp->target_rsp; cdf_mem_copy(pSirSmeOemDataRsp->oemDataRsp, pMlmOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c index 89eda604f90c..a666991cba05 100644 --- a/core/sme/src/oem_data/oem_data_api.c +++ b/core/sme/src/oem_data/oem_data_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -290,7 +290,6 @@ CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *pMsg) tListElem *pEntry = NULL; tSmeCmd *pCommand = NULL; tSirOemDataRsp *pOemDataRsp = NULL; - uint32_t *msgSubType; pMac = PMAC_STRUCT(hHal); @@ -326,21 +325,18 @@ CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *pMsg) pOemDataRsp = (tSirOemDataRsp *) pMsg; - /* check if message is to be forwarded to oem application or not */ - msgSubType = (uint32_t *) (&pOemDataRsp->oemDataRsp[0]); - if (*msgSubType != OEM_MESSAGE_SUBTYPE_INTERNAL) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, - "%s: calling send_oem_data_rsp_msg, msgSubType(0x%x)", - __func__, *msgSubType); - if (pMac->oemData.oem_data_rsp_callback != NULL) { - pMac->oemData.oem_data_rsp_callback( - sizeof(tOemDataRsp), - &pOemDataRsp->oemDataRsp[0]); - } - } else - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, - "%s: received internal oem data resp, msgSubType (0x%x)", - __func__, *msgSubType); + /* Send to upper layer only if rsp is from target */ + if (pOemDataRsp->target_rsp) { + sms_log(pMac, LOG1, + FL("received target oem data resp")); + if (pMac->oemData.oem_data_rsp_callback != NULL) + pMac->oemData.oem_data_rsp_callback( + sizeof(tOemDataRsp), + &pOemDataRsp->oemDataRsp[0]); + } else { + sms_log(pMac, LOG1, + FL("received internal oem data resp")); + } } while (0); return status; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 482b800b298f..42bd8844dfe8 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -688,6 +688,7 @@ typedef struct { * @oemDataRsp: OEM Data response */ typedef struct { + bool target_rsp; uint8_t oemDataRsp[OEM_DATA_RSP_SIZE]; } tStartOemDataRsp, *tpStartOemDataRsp; #endif /* FEATURE_OEM_DATA_SUPPORT */ diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 0fd93a395ec5..59751de4214b 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -910,6 +910,9 @@ int wma_oem_measurement_report_event_callback(void *handle, uint8_t *datap, int wma_oem_error_report_event_callback(void *handle, uint8_t *datap, uint32_t len); + +int wma_oem_data_response_handler(void *handle, uint8_t *datap, + uint32_t len); #endif void wma_register_dfs_event_handler(tp_wma_handle wma_handle); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index a35a58490061..735c36c0199b 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1699,6 +1699,7 @@ int wma_oem_capability_event_callback(void *handle, } cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + pStartOemDataRsp->target_rsp = true; msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); *msg_subtype = WMI_OEM_CAPABILITY_RSP; cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); @@ -1760,6 +1761,7 @@ int wma_oem_measurement_report_event_callback(void *handle, } cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + pStartOemDataRsp->target_rsp = true; msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); *msg_subtype = WMI_OEM_MEASUREMENT_RSP; cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); @@ -1820,6 +1822,7 @@ int wma_oem_error_report_event_callback(void *handle, } cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); + pStartOemDataRsp->target_rsp = true; msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); *msg_subtype = WMI_OEM_ERROR_REPORT_RSP; cdf_mem_copy(&pStartOemDataRsp->oemDataRsp[4], data, datalen); @@ -1831,6 +1834,59 @@ int wma_oem_error_report_event_callback(void *handle, return 0; } +/** + * wma_oem_data_response_handler() - OEM data response event handler + * @handle: wma handle + * @datap: data ptr + * @len: data length + * + * Return: 0 for success or error code + */ +int wma_oem_data_response_handler(void *handle, + uint8_t *datap, uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf; + uint8_t *data; + uint32_t datalen; + tStartOemDataRsp *oem_data_rsp; + + param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap; + if (!param_buf) { + WMA_LOGE(FL("Received NULL buf ptr from FW")); + return -ENOMEM; + } + + data = param_buf->data; + datalen = param_buf->num_data; + + if (!data) { + WMA_LOGE(FL("Received NULL data from FW")); + return -EINVAL; + } + + if (datalen > OEM_DATA_RSP_SIZE) { + WMA_LOGE(FL("Received data len %d exceeds max value %d"), + datalen, OEM_DATA_RSP_SIZE); + return -EINVAL; + } + + oem_data_rsp = cdf_mem_malloc(sizeof(*oem_data_rsp)); + if (!oem_data_rsp) { + WMA_LOGE(FL("Failed to alloc oem_data_rsp")); + return -ENOMEM; + } + + cdf_mem_zero(oem_data_rsp, sizeof(tStartOemDataRsp)); + oem_data_rsp->target_rsp = true; + cdf_mem_copy(&oem_data_rsp->oemDataRsp[0], data, datalen); + + WMA_LOGI(FL("Sending WMA_START_OEM_DATA_RSP, data len %d"), datalen); + + wma_send_msg(wma, WMA_START_OEM_DATA_RSP, (void *)oem_data_rsp, 0); + return 0; +} + /** * wma_start_oem_data_req() - start OEM data request to target * @wma_handle: wma handle @@ -1844,7 +1900,6 @@ void wma_start_oem_data_req(tp_wma_handle wma_handle, wmi_buf_t buf; uint8_t *cmd; int ret = 0; - uint32_t *msg_subtype; tStartOemDataRsp *pStartOemDataRsp; WMA_LOGD("%s: Send OEM Data Request to target", __func__); @@ -1903,8 +1958,7 @@ out: return; } cdf_mem_zero(pStartOemDataRsp, sizeof(tStartOemDataRsp)); - msg_subtype = (uint32_t *) (&pStartOemDataRsp->oemDataRsp[0]); - *msg_subtype = WMI_OEM_INTERNAL_RSP; + pStartOemDataRsp->target_rsp = false; WMA_LOGI("%s: Sending WMA_START_OEM_DATA_RSP to clear up PE/SME pending cmd", __func__); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index f493262c8c0a..ab6e66417626 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1817,6 +1817,10 @@ CDF_STATUS wma_open(void *cds_context, wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_OEM_ERROR_REPORT_EVENTID, wma_oem_error_report_event_callback); + + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OEM_RESPONSE_EVENTID, + wma_oem_data_response_handler); #endif /* FEATURE_OEM_DATA_SUPPORT */ /* * Register appropriate DFS phyerr event handler for -- cgit v1.2.3 From 0a7b79ae3f2bb2c250c5ec16831dccce06eaf5d2 Mon Sep 17 00:00:00 2001 From: Krishna Kumaar Natarajan Date: Fri, 20 Nov 2015 13:40:24 -0800 Subject: qcacld-3.0: Add data length in oem data request msg Add data length information in oem data request messages. Change-Id: Ibc132d31dd4345c4168dad23b4acf699f2a8c8e6 CRs-Fixed: 942260 --- core/hdd/src/wlan_hdd_oemdata.c | 15 +++- core/mac/inc/sir_api.h | 3 +- core/mac/src/pe/include/lim_global.h | 3 +- core/mac/src/pe/lim/lim_api.c | 7 ++ core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 38 +++++++--- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 17 +++-- core/sme/inc/oem_data_api.h | 5 +- core/sme/src/oem_data/oem_data_api.c | 83 +++++++++++++++++----- core/wma/inc/wma_if.h | 3 +- core/wma/src/wma_features.c | 31 ++++---- 10 files changed, 151 insertions(+), 54 deletions(-) diff --git a/core/hdd/src/wlan_hdd_oemdata.c b/core/hdd/src/wlan_hdd_oemdata.c index 5d76e0bbb635..e23412ac0dff 100644 --- a/core/hdd/src/wlan_hdd_oemdata.c +++ b/core/hdd/src/wlan_hdd_oemdata.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -374,7 +374,14 @@ static CDF_STATUS oem_process_data_req_msg(int oemDataLen, char *oemData) cdf_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig)); - cdf_mem_copy((&oemDataReqConfig)->oemDataReq, oemData, oemDataLen); + oemDataReqConfig.data = cdf_mem_malloc(oemDataLen); + if (!oemDataReqConfig.data) { + hddLog(LOGE, FL("malloc failed for data req buffer")); + return CDF_STATUS_E_NOMEM; + } + + oemDataReqConfig.data_len = oemDataLen; + cdf_mem_copy(oemDataReqConfig.data, oemData, oemDataLen); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO, "%s: calling sme_oem_data_req", __func__); @@ -383,6 +390,10 @@ static CDF_STATUS oem_process_data_req_msg(int oemDataLen, char *oemData) pAdapter->sessionId, &oemDataReqConfig, &oemDataReqID); + + cdf_mem_free(oemDataReqConfig.data); + oemDataReqConfig.data = NULL; + return status; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e5dde5720b44..77ed19180ed0 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -875,7 +875,8 @@ typedef struct sSirOemDataReq { uint16_t messageType; /* eWNI_SME_OEM_DATA_REQ */ uint16_t messageLen; struct cdf_mac_addr selfMacAddr; - uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tSirOemDataReq, *tpSirOemDataReq; typedef struct sSirOemDataRsp { diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index b5825b4f6203..07bd3bcc9224 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -307,7 +307,8 @@ struct tLimScanResultNode { /* OEM Data related structure definitions */ typedef struct sLimMlmOemDataReq { struct cdf_mac_addr selfMacAddr; - uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tLimMlmOemDataReq, *tpLimMlmOemDataReq; typedef struct sLimMlmOemDataRsp { diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index f516859e0955..c7bf4239c2af 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -260,6 +260,8 @@ static void __lim_init_vars(tpAniSirGlobal pMac) pMac->lim.gScanInPowersave = 0; pMac->lim.probeCounter = 0; pMac->lim.maxProbe = 0; + + pMac->lim.gpLimMlmOemDataReq = NULL; } static void __lim_init_assoc_vars(tpAniSirGlobal pMac) @@ -818,6 +820,11 @@ tSirRetStatus pe_close(tpAniSirGlobal pMac) pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; if (pMac->lim.gpLimMlmOemDataReq) { + if (pMac->lim.gpLimMlmOemDataReq->data) { + cdf_mem_free( + pMac->lim.gpLimMlmOemDataReq->data); + pMac->lim.gpLimMlmOemDataReq->data = NULL; + } cdf_mem_free(pMac->lim.gpLimMlmOemDataReq); pMac->lim.gpLimMlmOemDataReq = NULL; } diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 2de1a1db93ad..dc89b0918ad2 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -367,31 +367,36 @@ void lim_send_hal_oem_data_req(tpAniSirGlobal mac_ctx) tpStartOemDataReq start_oem_data_req = NULL; tSirRetStatus rc = eSIR_SUCCESS; tpLimMlmOemDataRsp mlm_oem_data_rsp; - uint32_t reqlen = 0; if (NULL == mac_ctx->lim.gpLimMlmOemDataReq) { lim_log(mac_ctx, LOGE, FL("Null pointer")); goto error; } - reqlen = sizeof(tStartOemDataReq); - - start_oem_data_req = cdf_mem_malloc(reqlen); + start_oem_data_req = cdf_mem_malloc(sizeof(*start_oem_data_req)); if (NULL == start_oem_data_req) { lim_log(mac_ctx, LOGE, FL ("Could not allocate memory for start_oem_data_req")); goto error; } - cdf_mem_set((uint8_t *) (start_oem_data_req), reqlen, 0); + start_oem_data_req->data = + cdf_mem_malloc(mac_ctx->lim.gpLimMlmOemDataReq->data_len); + if (!start_oem_data_req->data) { + lim_log(mac_ctx, LOGE, FL("memory allocation failed")); + cdf_mem_free(start_oem_data_req); + goto error; + } /* Now copy over the information to the OEM DATA REQ to HAL */ cdf_copy_macaddr(&start_oem_data_req->selfMacAddr, &mac_ctx->lim.gpLimMlmOemDataReq->selfMacAddr); - cdf_mem_copy(start_oem_data_req->oemDataReq, - mac_ctx->lim.gpLimMlmOemDataReq->oemDataReq, - OEM_DATA_REQ_SIZE); + start_oem_data_req->data_len = + mac_ctx->lim.gpLimMlmOemDataReq->data_len; + cdf_mem_copy(start_oem_data_req->data, + mac_ctx->lim.gpLimMlmOemDataReq->data, + mac_ctx->lim.gpLimMlmOemDataReq->data_len); /* Create the message to be passed to HAL */ msg.type = WMA_START_OEM_DATA_REQ; @@ -406,6 +411,7 @@ void lim_send_hal_oem_data_req(tpAniSirGlobal mac_ctx) return; SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + cdf_mem_free(start_oem_data_req->data); cdf_mem_free(start_oem_data_req); lim_log(mac_ctx, LOGE, FL("OEM_DATA: posting WMA_START_OEM_DATA_REQ to HAL failed")); @@ -424,6 +430,11 @@ error: mlm_oem_data_rsp->target_rsp = false; if (NULL != mac_ctx->lim.gpLimMlmOemDataReq) { + if (NULL != mac_ctx->lim.gpLimMlmOemDataReq->data) { + cdf_mem_free( + mac_ctx->lim.gpLimMlmOemDataReq->data); + mac_ctx->lim.gpLimMlmOemDataReq->data = NULL; + } cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq); mac_ctx->lim.gpLimMlmOemDataReq = NULL; } @@ -789,6 +800,7 @@ static void lim_process_mlm_oem_data_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) { tLimMlmOemDataRsp *mlm_oem_data_rsp; + tLimMlmOemDataReq *data_req = (tLimMlmOemDataReq *) msg_buf; if (((mac_ctx->lim.gLimMlmState == eLIM_MLM_IDLE_STATE) || (mac_ctx->lim.gLimMlmState == eLIM_MLM_JOINED_STATE) || @@ -801,11 +813,19 @@ static void lim_process_mlm_oem_data_req(tpAniSirGlobal mac_ctx, * second OEM data request */ if (mac_ctx->lim.gpLimMlmOemDataReq) { + if (mac_ctx->lim.gpLimMlmOemDataReq->data) { + cdf_mem_free( + mac_ctx->lim.gpLimMlmOemDataReq->data); + mac_ctx->lim.gpLimMlmOemDataReq->data = + NULL; + } cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq); mac_ctx->lim.gpLimMlmOemDataReq = NULL; } - mac_ctx->lim.gpLimMlmOemDataReq = (tLimMlmOemDataReq *) msg_buf; + mac_ctx->lim.gpLimMlmOemDataReq = data_req; + mac_ctx->lim.gpLimMlmOemDataReq->data = + data_req->data; mac_ctx->lim.gLimPrevMlmState = mac_ctx->lim.gLimMlmState; lim_log(mac_ctx, LOG2, FL("Calling lim_send_hal_oem_data_req")); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index d9858920dc14..c3f4705917f9 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1495,19 +1495,24 @@ static void __lim_process_sme_oem_data_req(tpAniSirGlobal pMac, uint32_t *pMsgBu pOemDataReq = (tpSirOemDataReq) pMsgBuf; /* post the lim mlm message now */ - pMlmOemDataReq = cdf_mem_malloc(sizeof(tLimMlmOemDataReq)); + pMlmOemDataReq = cdf_mem_malloc(sizeof(*pMlmOemDataReq)); if (NULL == pMlmOemDataReq) { lim_log(pMac, LOGP, FL("AllocateMemory failed for mlmOemDataReq")); return; } - /* Initialize this buffer */ - cdf_mem_set(pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0); + pMlmOemDataReq->data = cdf_mem_malloc(pOemDataReq->data_len); + if (!pMlmOemDataReq->data) { + lim_log(pMac, LOGP, FL("memory allocation failed")); + cdf_mem_free(pMlmOemDataReq); + return; + } cdf_copy_macaddr(&pMlmOemDataReq->selfMacAddr, &pOemDataReq->selfMacAddr); - cdf_mem_copy(pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq, - OEM_DATA_REQ_SIZE); + pMlmOemDataReq->data_len = pOemDataReq->data_len; + cdf_mem_copy(pMlmOemDataReq->data, pOemDataReq->data, + pOemDataReq->data_len); /* Issue LIM_MLM_OEM_DATA_REQ to MLM */ lim_post_mlm_message(pMac, LIM_MLM_OEM_DATA_REQ, diff --git a/core/sme/inc/oem_data_api.h b/core/sme/inc/oem_data_api.h index 09630aedc744..f60c9a44ed60 100644 --- a/core/sme/inc/oem_data_api.h +++ b/core/sme/inc/oem_data_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -53,7 +53,8 @@ /* Structure for defining req sent to the PE */ typedef struct tagOemDataReq { uint8_t sessionId; - uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tOemDataReq, tOemDataReqConfig; typedef struct tagOemDataRsp { diff --git a/core/sme/src/oem_data/oem_data_api.c b/core/sme/src/oem_data/oem_data_api.c index a666991cba05..2678d0af6b25 100644 --- a/core/sme/src/oem_data/oem_data_api.c +++ b/core/sme/src/oem_data/oem_data_api.c @@ -89,6 +89,7 @@ CDF_STATUS oem_data_oem_data_req_close(tHalHandle hHal) /* initialize all the variables to null */ cdf_mem_set(&(pMac->oemData), sizeof(tOemDataStruct), 0); + } while (0); return CDF_STATUS_SUCCESS; @@ -108,8 +109,13 @@ void oem_data_release_oem_data_req_command(tpAniSirGlobal pMac, /* First take this command out of the active list */ if (csr_ll_remove_entry (&pMac->sme.smeCmdActiveList, &pOemDataCmd->Link, LL_ACCESS_LOCK)) { - cdf_mem_set(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd), - 0); + if (pOemDataCmd->u.oemDataCmd.oemDataReq.data) { + cdf_mem_free( + pOemDataCmd->u.oemDataCmd.oemDataReq.data); + pOemDataCmd->u.oemDataCmd.oemDataReq.data = + NULL; + } + cdf_mem_zero(&(pOemDataCmd->u.oemDataCmd), sizeof(tOemDataCmd)); /* Now put this command back on the avilable command list */ sme_release_command(pMac, pOemDataCmd); @@ -134,6 +140,7 @@ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, CDF_STATUS status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tSmeCmd *pOemDataCmd = NULL; + tOemDataReq *cmd_req, *mac_req; do { if (!CSR_IS_SESSION_VALID(pMac, sessionId)) { @@ -144,10 +151,25 @@ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, pMac->oemData.oemDataReqConfig.sessionId = sessionId; pMac->oemData.oemDataReqID = *(pOemDataReqID); - cdf_mem_copy((void *)(pMac->oemData.oemDataReqConfig. - oemDataReq), - (void *)(oemDataReqConfig->oemDataReq), - OEM_DATA_REQ_SIZE); + pMac->oemData.oemDataReqConfig.data_len = + oemDataReqConfig->data_len; + + if (pMac->oemData.oemDataReqConfig.data) { + cdf_mem_free(pMac->oemData.oemDataReqConfig.data); + pMac->oemData.oemDataReqConfig.data = NULL; + } + + pMac->oemData.oemDataReqConfig.data = + cdf_mem_malloc(pMac->oemData.oemDataReqConfig.data_len); + if (!pMac->oemData.oemDataReqConfig.data) { + sms_log(pMac, LOGE, FL("memory alloc failed")); + status = CDF_STATUS_E_NOMEM; + break; + } + + cdf_mem_copy((void *)(pMac->oemData.oemDataReqConfig.data), + (void *)(oemDataReqConfig->data), + oemDataReqConfig->data_len); pMac->oemData.oemDataReqActive = false; @@ -159,13 +181,23 @@ CDF_STATUS oem_data_oem_data_req(tHalHandle hHal, pOemDataCmd->u.oemDataCmd.oemDataReqID = pMac->oemData.oemDataReqID; + + cmd_req = &(pOemDataCmd->u.oemDataCmd.oemDataReq); + mac_req = &(pMac->oemData.oemDataReqConfig); /* set the oem data request */ - pOemDataCmd->u.oemDataCmd.oemDataReq.sessionId = - pMac->oemData.oemDataReqConfig.sessionId; - cdf_mem_copy((void *)(pOemDataCmd->u.oemDataCmd. - oemDataReq.oemDataReq), - (void *)(pMac->oemData.oemDataReqConfig. - oemDataReq), OEM_DATA_REQ_SIZE); + cmd_req->sessionId = mac_req->sessionId; + cmd_req->data_len = mac_req->data_len; + cmd_req->data = cdf_mem_malloc(cmd_req->data_len); + + if (!cmd_req->data) { + sms_log(pMac, LOGE, FL("memory alloc failed")); + status = CDF_STATUS_E_NOMEM; + break; + } + + cdf_mem_copy((void *)(cmd_req->data), + (void *)(mac_req->data), + cmd_req->data_len); } else { status = CDF_STATUS_E_FAILURE; break; @@ -199,25 +231,36 @@ CDF_STATUS oem_data_send_mb_oem_data_req(tpAniSirGlobal pMac, { CDF_STATUS status = CDF_STATUS_SUCCESS; tSirOemDataReq *pMsg; - uint16_t msgLen; tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, pOemDataReq->sessionId); + uint16_t msgLen; sms_log(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); - msgLen = (uint16_t) (sizeof(tSirOemDataReq)); + if (!pOemDataReq) { + sms_log(pMac, LOGE, FL("oem data req is NULL")); + return CDF_STATUS_E_INVAL; + } - pMsg = cdf_mem_malloc(msgLen); + pMsg = cdf_mem_malloc(sizeof(*pMsg)); if (NULL == pMsg) { sms_log(pMac, LOGP, FL("cdf_mem_malloc failed")); return CDF_STATUS_E_NOMEM; } - cdf_mem_set(pMsg, msgLen, 0); + pMsg->data = cdf_mem_malloc(pOemDataReq->data_len); + if (!pMsg->data) { + sms_log(pMac, LOGP, FL("cdf_mem_malloc failed")); + cdf_mem_free(pMsg); + return CDF_STATUS_E_NOMEM; + } + + msgLen = (uint16_t) (sizeof(*pMsg) + pOemDataReq->data_len); pMsg->messageType = eWNI_SME_OEM_DATA_REQ; pMsg->messageLen = msgLen; cdf_copy_macaddr(&pMsg->selfMacAddr, &pSession->selfMacAddr); - cdf_mem_copy(pMsg->oemDataReq, pOemDataReq->oemDataReq, - OEM_DATA_REQ_SIZE); + pMsg->data_len = pOemDataReq->data_len; + cdf_mem_copy(pMsg->data, pOemDataReq->data, + pOemDataReq->data_len); sms_log(pMac, LOGW, "OEM_DATA: sending message to pe%s", __func__); status = cds_send_mb_message_to_mac(pMsg); @@ -290,6 +333,7 @@ CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *pMsg) tListElem *pEntry = NULL; tSmeCmd *pCommand = NULL; tSirOemDataRsp *pOemDataRsp = NULL; + tOemDataReq *req; pMac = PMAC_STRUCT(hHal); @@ -318,6 +362,9 @@ CDF_STATUS sme_handle_oem_data_rsp(tHalHandle hHal, uint8_t *pMsg) &pCommand->Link, LL_ACCESS_LOCK)) { cdf_mem_set(&(pCommand->u.oemDataCmd), sizeof(tOemDataCmd), 0); + req = + &(pCommand->u.oemDataCmd.oemDataReq); + cdf_mem_free(req->data); sme_release_command(pMac, pCommand); } } diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 42bd8844dfe8..5bfa717f2f40 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -680,7 +680,8 @@ typedef struct { typedef struct { struct cdf_mac_addr selfMacAddr; CDF_STATUS status; - uint8_t oemDataReq[OEM_DATA_REQ_SIZE]; + uint8_t data_len; + uint8_t *data; } tStartOemDataReq, *tpStartOemDataReq; /** diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 735c36c0199b..d68d2e2f7bf4 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1902,48 +1902,51 @@ void wma_start_oem_data_req(tp_wma_handle wma_handle, int ret = 0; tStartOemDataRsp *pStartOemDataRsp; - WMA_LOGD("%s: Send OEM Data Request to target", __func__); + WMA_LOGD(FL("Send OEM Data Request to target")); - if (!startOemDataReq) { - WMA_LOGE("%s: startOemDataReq is null", __func__); + if (!startOemDataReq && !startOemDataReq->data) { + WMA_LOGE(FL("startOemDataReq is null")); goto out; } if (!wma_handle || !wma_handle->wmi_handle) { - WMA_LOGE("%s: WMA is closed, can not send Oem data request cmd", - __func__); + WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd")); return; } buf = wmi_buf_alloc(wma_handle->wmi_handle, - (OEM_DATA_REQ_SIZE + WMI_TLV_HDR_SIZE)); + (startOemDataReq->data_len + WMI_TLV_HDR_SIZE)); if (!buf) { - WMA_LOGE("%s:wmi_buf_alloc failed", __func__); + WMA_LOGE(FL("wmi_buf_alloc failed")); goto out; } cmd = (uint8_t *) wmi_buf_data(buf); - WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, OEM_DATA_REQ_SIZE); + WMITLV_SET_HDR(cmd, WMITLV_TAG_ARRAY_BYTE, startOemDataReq->data_len); cmd += WMI_TLV_HDR_SIZE; - cdf_mem_copy(cmd, &startOemDataReq->oemDataReq[0], OEM_DATA_REQ_SIZE); + cdf_mem_copy(cmd, startOemDataReq->data, + startOemDataReq->data_len); - WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)", - __func__, OEM_DATA_REQ_SIZE); + WMA_LOGI(FL("Sending OEM Data Request to target, data len %d"), + startOemDataReq->data_len); ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, - (OEM_DATA_REQ_SIZE + + (startOemDataReq->data_len + WMI_TLV_HDR_SIZE), WMI_OEM_REQ_CMDID); if (ret != EOK) { - WMA_LOGE("%s:wmi cmd send failed", __func__); + WMA_LOGE(FL(":wmi cmd send failed")); cdf_nbuf_free(buf); } out: /* free oem data req buffer received from UMAC */ - if (startOemDataReq) + if (startOemDataReq) { + if (startOemDataReq->data) + cdf_mem_free(startOemDataReq->data); cdf_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 -- cgit v1.2.3 From ccf6c22d7050cac862520e540e7c6fa5bed21c55 Mon Sep 17 00:00:00 2001 From: Yuanyuan Liu Date: Mon, 14 Dec 2015 15:44:20 -0800 Subject: qcacld-3.0: Add cdf_mem_exit cdf_mc_timer_exit when wlan exits cdf_mem_exit cdf_mc_timer_exit are missing from hdd_driver_exit. Add them back so that wlan driver exits properly. Change-Id: I571f65118a1755d2f43c29e8320563a43b49e713 CRs-Fixed: 951519 --- core/cds/src/cds_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 03baf5089277..bb17c18153ea 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -122,6 +122,9 @@ void cds_deinit(void) gp_cds_context->cdf_ctx = NULL; gp_cds_context = NULL; + cdf_mc_timer_exit(); + cdf_mem_exit(); + return; } -- cgit v1.2.3 From aa9042d2422fc542300006f088ebc53ff6859302 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Tue, 22 Dec 2015 17:32:59 -0800 Subject: qcacld-3.0: hdd: Clean-up FTM initialization FTM initialization has conditional compilation within the function. Clean-up and create separate functions to initialize and remove FTM during driver probe and remove. Change-Id: I04890f49447c22b6d7dd93baf0a266ea9f5a4ca7 CRs-fixed: 957630 --- core/hdd/src/wlan_hdd_main.c | 144 ++++++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 51 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 91372fd1fc8b..abeb133321fa 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3357,6 +3357,85 @@ static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) } #endif +#ifdef QCA_WIFI_FTM +/** + * hdd_disable_ftm() - Disable FTM mode + * @hdd_ctx: HDD context + * + * Helper function to disable FTM mode. + * + * Return: None. + */ +static void hdd_disable_ftm(hdd_context_t *hdd_ctx) +{ + hdd_notice("Disabling FTM mode"); + + if (hdd_ftm_stop(hdd_ctx)) { + hdd_alert("hdd_ftm_stop Failed!"); + CDF_ASSERT(0); + } + + hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED; + + wlan_hdd_ftm_close(hdd_ctx); + + return; +} + +/** + * hdd_enable_ftm() - Enable FTM mode + * @hdd_ctx: HDD context + * + * Helper function to enable FTM mode. + * + * Return: 0 on success and errno on failure. + */ +int hdd_enable_ftm(hdd_context_t *hdd_ctx) +{ + int ret; + + ret = wlan_hdd_ftm_open(hdd_ctx); + if (ret) { + hdd_alert("wlan_hdd_ftm_open Failed: %d", ret); + goto err_out; + } + + ret = hdd_ftm_start(hdd_ctx); + + if (ret) { + hdd_alert("hdd_ftm_start Failed: %d", ret); + goto err_ftm_close; + } + + ret = wiphy_register(hdd_ctx->wiphy); + if (ret) { + hdd_alert("wiphy register failed: %d", ret); + goto err_ftm_stop; + } + + hdd_err("FTM driver loaded"); + + return 0; + +err_ftm_stop: + hdd_ftm_stop(hdd_ctx); +err_ftm_close: + wlan_hdd_ftm_close(hdd_ctx); +err_out: + return ret; + +} +#else +int hdd_enable_ftm(hdd_context_t *hdd_ctx) +{ + hdd_err("Driver built without FTM feature enabled!"); + + return -ENOTSUPP; +} + +static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { } +#endif + /** * hdd_wlan_exit() - HDD WLAN exit function * @hdd_ctx: Pointer to the HDD Context @@ -3382,17 +3461,9 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) hdd_unregister_wext_all_adapters(hdd_ctx); if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - hddLog(CDF_TRACE_LEVEL_INFO, FL("FTM MODE")); -#if defined(QCA_WIFI_FTM) - if (hdd_ftm_stop(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("hdd_ftm_stop Failed")); - CDF_ASSERT(0); - } - hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED; -#endif - wlan_hdd_ftm_close(hdd_ctx); - hddLog(CDF_TRACE_LEVEL_FATAL, FL("FTM driver unloaded")); + hdd_disable_ftm(hdd_ctx); + + hdd_alert("FTM driver unloaded"); goto free_hdd_ctx; } @@ -4869,8 +4940,14 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_cfg_print(hdd_ctx); - if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) - goto ftm_processing; + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + ret = hdd_enable_ftm(hdd_ctx); + + if (ret) + goto err_config; + + goto success; + } hdd_ctx->isLogpInProgress = false; cds_set_logp_in_progress(false); @@ -4882,7 +4959,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) status = cds_open(&p_cds_context, 0); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed")); - goto err_cds_open; + goto err_config; } wlan_hdd_update_wiphy(wiphy, hdd_ctx->config); @@ -5019,31 +5096,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) cds_pkt_proto_trace_init(); #endif /* QCA_PKT_PROTO_TRACE */ -ftm_processing: - if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { - if (CDF_STATUS_SUCCESS != wlan_hdd_ftm_open(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("wlan_hdd_ftm_open Failed")); - goto err_config; - } -#if defined(QCA_WIFI_FTM) - if (hdd_ftm_start(hdd_ctx)) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("hdd_ftm_start Failed")); - 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; - } - - cds_set_load_unload_in_progress(false); - hdd_ctx->isLoadInProgress = false; - hddLog(LOGE, FL("FTM driver loaded")); - return CDF_STATUS_SUCCESS; - } #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) rtnl_lock(); rtnl_lock_enable = true; @@ -5418,9 +5470,6 @@ ftm_processing: memdump_init(); - hdd_ctx->isLoadInProgress = false; - cds_set_load_unload_in_progress(false); - goto success; err_nl_srv: @@ -5473,15 +5522,6 @@ err_cds_close: } cds_close(p_cds_context); -err_cds_open: - - if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { -#if defined(QCA_WIFI_FTM) -err_free_ftm_open: - wlan_hdd_ftm_close(hdd_ctx); -#endif - } - err_config: kfree(hdd_ctx->config); hdd_ctx->config = NULL; @@ -5498,6 +5538,8 @@ err_free_hdd_context: return -EIO; success: + hdd_ctx->isLoadInProgress = false; + cds_set_load_unload_in_progress(false); EXIT(); return 0; } -- cgit v1.2.3 From dfcae6ba35a02348afb3265fc9cff52b8fa93063 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Fri, 4 Dec 2015 11:56:47 -0800 Subject: qcacld-3.0: Maintain driver state in CDS Driver state of loading, unloading, logp are maintained in multiple modules like HDD, CDS. Change to maintain the driver state in CDS and provide CDS APIs to find out the state of the driver so that any of the module can query it. Also rename the logp to recovery in progress for clarity purpose. Change-Id: I8e1864e1bc7f3b1dd6f4eb804ce2578c6695967d CRs-fixed: 958659 --- config/WCNSS_qcom_cfg.ini | 2 - core/bmi/src/ol_fw.c | 8 +- core/cds/inc/cds_api.h | 137 ++++++++++++++++++++++++++++++++--- core/cds/inc/cds_sched.h | 6 +- core/cds/src/cds_api.c | 114 +++++++++-------------------- core/cds/src/cds_reg_service.c | 6 +- core/dp/txrx/ol_rx.c | 4 +- core/hdd/inc/wlan_hdd_cfg.h | 8 +- core/hdd/inc/wlan_hdd_main.h | 8 +- core/hdd/src/wlan_hdd_assoc.c | 6 +- core/hdd/src/wlan_hdd_cfg.c | 9 +-- core/hdd/src/wlan_hdd_driver_ops.c | 41 +++++++++-- core/hdd/src/wlan_hdd_hostapd.c | 8 +- core/hdd/src/wlan_hdd_ioctl.c | 6 +- core/hdd/src/wlan_hdd_ipa.c | 6 +- core/hdd/src/wlan_hdd_main.c | 33 +++------ core/hdd/src/wlan_hdd_p2p.c | 6 +- core/hdd/src/wlan_hdd_power.c | 18 ++--- core/hdd/src/wlan_hdd_scan.c | 14 ++-- core/hdd/src/wlan_hdd_softap_tx_rx.c | 15 ++-- core/hdd/src/wlan_hdd_stats.c | 4 +- core/hdd/src/wlan_hdd_tdls.c | 17 ++--- core/hdd/src/wlan_hdd_tx_rx.c | 4 +- core/hdd/src/wlan_hdd_wext.c | 18 ++--- core/hif/src/ce/ce_main.c | 4 +- core/hif/src/pcie/if_pci.c | 4 +- core/mac/src/pe/lim/lim_utils.c | 4 +- core/wma/src/wma_features.c | 10 +-- core/wma/src/wma_main.c | 2 +- 29 files changed, 292 insertions(+), 230 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 61f498bed89e..8a5646885a79 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -311,8 +311,6 @@ gEnableDFSChnlScan=1 gAllowDFSChannelRoam=1 gVhtChannelWidth=2 -gEnableLogp=1 - # Enable Automatic Tx Power control diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c index e01af6fe85e1..e73d5c8a65b8 100644 --- a/core/bmi/src/ol_fw.c +++ b/core/bmi/src/ol_fw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -618,8 +618,8 @@ void ol_target_failure(void *instance, CDF_STATUS status) } scn->target_status = OL_TRGET_STATUS_RESET; - if (cds_is_logp_in_progress()) { - BMI_ERR("%s: LOGP is in progress, ignore!\n", __func__); + if (cds_is_driver_recovering()) { + BMI_ERR("%s: Recovery in progress, ignore!\n", __func__); return; } @@ -628,7 +628,7 @@ void ol_target_failure(void *instance, CDF_STATUS status) __func__); return; } - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); #ifdef CONFIG_CNSS ret = hif_check_fw_reg(scn); diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index d3d327e76d77..4e954b9dabd9 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -55,6 +55,133 @@ */ #define CDS_WMA_TIMEOUT (15000) +/** + * enum cds_driver_state - Driver state + * @CDS_DRIVER_STATE_UNINITIALIZED: Driver is in uninitialized state. + * CDS_DRIVER_STATE_LOADED: Driver is loaded and functional. + * CDS_DRIVER_STATE_LOADING: Driver probe is in progress. + * CDS_DRIVER_STATE_UNLOADING: Driver remove is in progress. + * CDS_DRIVER_STATE_RECOVERING: Recovery in progress. + */ +enum cds_driver_state { + CDS_DRIVER_STATE_UNINITIALIZED = 0, + CDS_DRIVER_STATE_LOADED = BIT(0), + CDS_DRIVER_STATE_LOADING = BIT(1), + CDS_DRIVER_STATE_UNLOADING = BIT(2), + CDS_DRIVER_STATE_RECOVERING = BIT(3), +}; + +#define __CDS_IS_DRIVER_STATE(_state, _mask) (((_state) & (_mask)) == (_mask)) + +void cds_set_driver_state(enum cds_driver_state); +void cds_clear_driver_state(enum cds_driver_state); +enum cds_driver_state cds_get_driver_state(void); + +/** + * cds_is_driver_loading() - Is driver load in progress + * + * Return: true if driver is loading and false otherwise. + */ +static inline bool cds_is_driver_loading(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_LOADING); +} + +/** + * cds_is_driver_unloading() - Is driver unload in progress + * + * Return: true if driver is unloading and false otherwise. + */ +static inline bool cds_is_driver_unloading(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_UNLOADING); +} + +/** + * cds_is_driver_recovering() - Is recovery in progress + * + * Return: true if recovery in progress and false otherwise. + */ +static inline bool cds_is_driver_recovering(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_RECOVERING); +} + +/** + * cds_is_load_unload_in_progress() - Is driver load/unload in progress + * + * Return: true if driver is loading or unloading and false otherwise. + */ +static inline bool cds_is_load_unload_in_progress(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_LOADING | + CDS_DRIVER_STATE_UNLOADING); +} + +/** + * cds_set_recovery_in_progress() - Set recovery in progress + * @value: value to set + * + * Return: none + */ +static inline void cds_set_recovery_in_progress(uint8_t value) +{ + if (value) + cds_set_driver_state(CDS_DRIVER_STATE_RECOVERING); + else + cds_clear_driver_state(CDS_DRIVER_STATE_RECOVERING); +} + +/** + * cds_set_load_in_progress() - Set load in progress + * @value: value to set + * + * Return: none + */ +static inline void cds_set_load_in_progress(uint8_t value) +{ + if (value) + cds_set_driver_state(CDS_DRIVER_STATE_LOADING); + else + cds_clear_driver_state(CDS_DRIVER_STATE_LOADING); +} + +/** + * cds_set_driver_loaded() - Set load completed + * @value: value to set + * + * Return: none + */ +static inline void cds_set_driver_loaded(uint8_t value) +{ + if (value) + cds_set_driver_state(CDS_DRIVER_STATE_LOADED); + else + cds_clear_driver_state(CDS_DRIVER_STATE_LOADED); +} + +/** + * cds_set_unload_in_progress() - Set unload in progress + * @value: value to set + * + * Return: none + */ +static inline void cds_set_unload_in_progress(uint8_t value) +{ + if (value) + cds_set_driver_state(CDS_DRIVER_STATE_UNLOADING); + else + cds_clear_driver_state(CDS_DRIVER_STATE_UNLOADING); +} + v_CONTEXT_t cds_init(void); void cds_deinit(void); @@ -76,14 +203,6 @@ void *cds_get_context(CDF_MODULE_ID moduleId); v_CONTEXT_t cds_get_global_context(void); -uint8_t cds_is_logp_in_progress(void); -void cds_set_logp_in_progress(uint8_t value); - -uint8_t cds_is_load_unload_in_progress(void); -uint8_t cds_is_unload_in_progress(void); - -void cds_set_load_unload_in_progress(uint8_t value); - CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, void **ppModuleContext, uint32_t size); diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 2571378ffac2..d58c3c21c168 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -257,7 +257,7 @@ typedef struct _cds_context_type { cdf_event_t ProbeEvent; - volatile uint8_t isLogpInProgress; + uint32_t driver_state; cdf_event_t wmaCompleteEvent; @@ -281,8 +281,6 @@ typedef struct _cds_context_type { /* Configuration handle used to get system configuration */ void *cfg_ctx; - volatile uint8_t isLoadUnloadInProgress; - bool is_wakelock_log_enabled; uint32_t wakelock_log_level; uint32_t connectivity_log_level; diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index bb17c18153ea..4f2477dedbe4 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -122,6 +122,8 @@ void cds_deinit(void) gp_cds_context->cdf_ctx = NULL; gp_cds_context = NULL; + cdf_mem_zero(&g_cds_context, sizeof(g_cds_context)); + cdf_mc_timer_exit(); cdf_mem_exit(); @@ -966,113 +968,67 @@ v_CONTEXT_t cds_get_global_context(void) } /* cds_get_global_context() */ /** - * cds_is_logp_in_progress() - check if ssr/self recovery is going on + * cds_get_driver_state() - Get current driver state * - * Return: true if ssr/self recvoery is going on else false - */ -uint8_t cds_is_logp_in_progress(void) -{ - if (gp_cds_context == NULL) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: global cds context is NULL", __func__); - return 1; - } - - return gp_cds_context->isLogpInProgress; -} - -/** - * cds_set_logp_in_progress() - set ssr/self recovery in progress - * @value: value to set + * This API returns current driver state stored in global context. * - * Return: none + * Return: Driver state enum */ -void cds_set_logp_in_progress(uint8_t value) +enum cds_driver_state cds_get_driver_state(void) { - hdd_context_t *pHddCtx = NULL; - if (gp_cds_context == NULL) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: global cds context is NULL", __func__); - return; - } - gp_cds_context->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 = cds_get_context(CDF_MODULE_ID_HDD); - if (!pHddCtx) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return; + return CDS_DRIVER_STATE_UNINITIALIZED; } - pHddCtx->isLogpInProgress = value; -} -/** - * cds_is_load_unload_in_progress() - check if driver load/unload in progress - * - * Return: true if load/unload is going on else false - */ -uint8_t cds_is_load_unload_in_progress(void) -{ - if (gp_cds_context == NULL) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: global cds context is NULL", __func__); - return 0; - } - - return gp_cds_context->isLoadUnloadInProgress; + return gp_cds_context->driver_state; } /** - * cds_is_unload_in_progress() - check if driver unload in - * progress + * cds_set_driver_state() - Set current driver state + * @state: Driver state to be set to. + * + * This API sets driver state to state. This API only sets the state and doesn't + * clear states, please make sure to use cds_clear_driver_state to clear any + * state if required. * - * Return: true if unload is going on else false + * Return: None */ -uint8_t cds_is_unload_in_progress(void) +void cds_set_driver_state(enum cds_driver_state state) { - hdd_context_t *hdd_ctx = NULL; if (gp_cds_context == NULL) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: global cds context is NULL", __func__); - return 0; - } - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + "%s: global cds context is NULL: %x", __func__, + state); - if (hdd_ctx == NULL) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: HDD context is NULL", __func__); - return 0; + return; } - return hdd_ctx->isUnloadInProgress; + gp_cds_context->driver_state |= state; } /** - * cds_set_load_unload_in_progress() - set load/unload in progress - * @value: value to set + * cds_clear_driver_state() - Clear current driver state + * @state: Driver state to be cleared. * - * Return: none + * This API clears driver state. This API only clears the state, please make + * sure to use cds_set_driver_state to set any new states. + * + * Return: None */ -void cds_set_load_unload_in_progress(uint8_t value) +void cds_clear_driver_state(enum cds_driver_state state) { if (gp_cds_context == NULL) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "%s: global cds context is NULL", __func__); + "%s: global cds context is NULL: %x", __func__, + state); + return; } - gp_cds_context->isLoadUnloadInProgress = value; -#ifdef CONFIG_CNSS - if (value) - cnss_set_driver_status(CNSS_LOAD_UNLOAD); - else - cnss_set_driver_status(CNSS_INITIALIZED); -#endif + gp_cds_context->driver_state &= ~state; } /** @@ -1663,12 +1619,12 @@ void cds_trigger_recovery(void) CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "CRASH_INJECT command is timed out!"); #ifdef CONFIG_CNSS - if (cds_is_logp_in_progress()) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "LOGP is in progress, ignore!"); + "Recovery is in progress, ignore!"); return; } - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); cnss_schedule_recovery_work(); #endif diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index 19109abf86ce..016d5860b1bd 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -896,7 +896,7 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, wiphy = hdd_ctx->wiphy; - if (cds_is_logp_in_progress()) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "SSR in progress, return"); *reg_domain_ptr = temp_reg_domain; @@ -1243,7 +1243,7 @@ void __hdd_reg_notifier(struct wiphy *wiphy, return; } - if (hdd_ctx->isUnloadInProgress || hdd_ctx->isLogpInProgress) { + if (cds_is_driver_unloading() || cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "%s: Unloading or SSR in Progress, Ignore!!!", __func__); diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index 7d007aaab897..19db13998ccc 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -98,7 +98,7 @@ void ol_rx_trigger_restore(htt_pdev_handle htt_pdev, cdf_nbuf_t head_msdu, } if (!htt_pdev->rx_ring.htt_rx_restore) { - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); htt_pdev->rx_ring.htt_rx_restore = 1; schedule_work(&ol_rx_restore_work); } diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 92c51b7abbec..242eb793e20b 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -847,11 +847,6 @@ typedef enum { #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) - #if defined WLAN_FEATURE_VOWIFI_11R #define CFG_FT_RESOURCE_REQ_NAME "gFTResourceReqSupported" #define CFG_FT_RESOURCE_REQ_MIN (0) @@ -2880,7 +2875,6 @@ struct hdd_config { bool fSupplicantCountryCodeHasPriority; uint32_t HeartbeatThresh24; char PowerUsageControl[4]; - bool fIsLogpEnabled; bool fIsImpsEnabled; bool is_ps_enabled; uint32_t nBmpsModListenInterval; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index e464b9c059b9..cb7693f1cc3d 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1138,12 +1138,6 @@ struct hdd_context_s { bool is_ol_rx_thread_suspended; #endif - volatile bool isLogpInProgress; - - bool isLoadInProgress; - - bool isUnloadInProgress; - /* Track whether Mcast/Bcast Filter is enabled. */ bool hdd_mcastbcast_filter_set; diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index e01b5bf61b7d..81bb20992072 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -878,8 +878,7 @@ static void hdd_send_association_event(struct net_device *dev, 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)) { + if (cds_is_load_unload_in_progress()) { wireless_send_event(dev, we_event, &wrqu, msg); #ifdef FEATURE_WLAN_ESE if (eConnectionState_Associated == @@ -1068,8 +1067,7 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, * before the driver so not sending the status of the * connection to supplicant. */ - if ((pHddCtx->isLoadInProgress != true) && - (pHddCtx->isUnloadInProgress != true)) { + if (cds_is_load_unload_in_progress()) { #ifdef WLAN_FEATURE_P2P_DEBUG if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { if (global_p2p_connection_status == diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 3cb0e6b82c48..7c516c1bea5d 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -427,13 +427,6 @@ REG_TABLE_ENTRY g_registry_table[] = { VAR_FLAGS_OPTIONAL, (void *)CFG_POWER_USAGE_DEFAULT), - REG_VARIABLE(CFG_ENABLE_LOGP_NAME, WLAN_PARAM_Integer, - struct hdd_config, 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, struct hdd_config, fIsImpsEnabled, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 8a45f4fe1e90..9f0d6d99b513 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -73,7 +73,7 @@ #define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ icnss_unregister_driver(wlan_drv_ops) #endif /* HIF_PCI */ -#define DISABLE_KRAIT_IDLE_PS_VAL 200 +#define DISABLE_KRAIT_IDLE_PS_VAL 1 /* * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at @@ -213,11 +213,14 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, */ hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL); - if (!reinit) { + if (reinit) { + cds_set_recovery_in_progress(true); + } else { ret = hdd_init(); if (ret) goto out; + cds_set_load_in_progress(true); } if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { @@ -242,8 +245,12 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, goto err_hif_close; - if (reinit) - cds_set_logp_in_progress(false); + if (reinit) { + cds_set_recovery_in_progress(false); + } else { + cds_set_load_in_progress(false); + cds_set_driver_loaded(true); + } hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); hdd_remove_pm_qos(); @@ -256,6 +263,7 @@ err_epping_close: if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) epping_close(); err_hdd_deinit: + cds_set_load_in_progress(false); hdd_deinit(); out: hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT); @@ -263,6 +271,16 @@ out: return ret; } +#ifdef CONFIG_CNSS +static inline void hdd_cnss_driver_unloading(void) +{ + cnss_set_driver_status(CNSS_LOAD_UNLOAD); +} +#else +static inline void hdd_cnss_driver_unloading(void) { } +#endif + + /** * wlan_hdd_remove() - wlan_hdd_remove * @@ -278,6 +296,17 @@ static void wlan_hdd_remove(void) pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); + /* Wait for recovery to complete */ + while (cds_is_driver_recovering()) { + hdd_alert("Recovery in progress; wait here!!!"); + msleep(1000); + } + + cds_set_driver_loaded(false); + cds_set_unload_in_progress(true); + + hdd_cnss_driver_unloading(); + hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); hif_pktlogmod_exit(hif_ctx); @@ -314,7 +343,7 @@ static void wlan_hdd_shutdown(void) return; } /* this is for cases, where shutdown invoked from CNSS */ - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); if (cds_get_conparam() != CDF_GLOBAL_FTM_MODE && !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index cecbbb0ee9c3..5361c76ac12d 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -222,12 +222,12 @@ static int __hdd_hostapd_open(struct net_device *dev) MTRACE(cdf_trace(CDF_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")); + if (cds_is_load_unload_in_progress()) { + hdd_err("Driver load/unload in progress, ignore, state: 0x%x", + cds_get_driver_state()); goto done; } + /* Enable all Tx queues */ hddLog(LOG1, FL("Enabling queues")); wlan_hdd_netif_queue_control(pAdapter, diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index c2c9938e37b4..68005f54ec51 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -2112,15 +2112,15 @@ static void hdd_get_link_status_cb(uint8_t status, void *context) static int wlan_hdd_get_link_status(hdd_adapter_t *adapter) { - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); struct statsContext context; CDF_STATUS hstatus; unsigned long rc; - if (hdd_ctx->isLogpInProgress) { - hddLog(LOGW, FL("LOGP in Progress. Ignore!!!")); + if (cds_is_driver_recovering()) { + hdd_warn("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return 0; } diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 0e2bd0e51964..98c95f656ef3 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2454,7 +2454,7 @@ static void hdd_ipa_send_skb_to_network(cdf_nbuf_t skb, return; } - if (hdd_ipa->hdd_ctx->isUnloadInProgress) { + if (cds_is_driver_unloading()) { HDD_IPA_INCREASE_INTERNAL_DROP_COUNT(hdd_ipa); cdf_nbuf_free(skb); return; @@ -3745,7 +3745,7 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, if ((!hdd_ipa->num_iface) && (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe)) { - if (hdd_ipa->hdd_ctx->isUnloadInProgress) { + if (cds_is_driver_unloading()) { /* * We disable WDI pipes directly here since * IPA_OPCODE_TX/RX_SUSPEND message will not be diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index abeb133321fa..b2b86a758f58 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -265,7 +265,7 @@ static int __hdd_netdev_notifier_call(struct notifier_block *nb, CDF_ASSERT(0); return NOTIFY_DONE; } - if (hdd_ctx->isLogpInProgress) + if (cds_is_driver_recovering()) return NOTIFY_DONE; hddLog(CDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"), @@ -417,13 +417,15 @@ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx) return -ENODEV; } - if (hdd_ctx->isLogpInProgress) { - hddLog(LOGE, FL("LOGP in Progress. Ignore!!!")); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return -EAGAIN; } - if ((hdd_ctx->isLoadInProgress) || (hdd_ctx->isUnloadInProgress)) { - hddLog(LOGE, FL("Unloading/Loading in Progress. Ignore!!!")); + if (cds_is_load_unload_in_progress()) { + hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x", + cds_get_driver_state()); return -EAGAIN; } return 0; @@ -1189,7 +1191,7 @@ void hdd_update_tgt_cfg(void *context, void *param) FL("ini BandCapability not supported by the target")); } - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { hdd_ctx->reg.reg_domain = cfg->reg_domain; hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext; } @@ -3627,17 +3629,6 @@ void __hdd_wlan_exit(void) return; } - /* module exit should never proceed if SSR is not completed */ - while (hdd_ctx->isLogpInProgress) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("SSR in Progress; block rmmod for 1 second!!!")); - msleep(1000); - } - - hdd_ctx->isUnloadInProgress = true; - - cds_set_load_unload_in_progress(true); - /* Check IPA HW Pipe shutdown */ hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); @@ -4786,12 +4777,9 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) cdf_mem_zero(hdd_ctx, sizeof(hdd_context_t)); hdd_ctx->wiphy = wiphy; - hdd_ctx->isLoadInProgress = true; hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; cds_set_wakelock_logging(false); - cds_set_load_unload_in_progress(true); - /* Get cds context here bcoz cds_open requires it */ p_cds_context = cds_get_global_context(); @@ -4949,8 +4937,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto success; } - hdd_ctx->isLogpInProgress = false; - cds_set_logp_in_progress(false); + cds_set_recovery_in_progress(false); cds_set_connection_in_progress(false); @@ -5538,8 +5525,6 @@ err_free_hdd_context: return -EIO; success: - hdd_ctx->isLoadInProgress = false; - cds_set_load_unload_in_progress(false); EXIT(); return 0; } diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index 8d35b4cf29c9..f22f95e95e10 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -1166,9 +1166,9 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, "%s: timeout waiting for remain on channel ready indication", __func__); - if (pHddCtx->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: LOGP in Progress. Ignore!!!", __func__); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return -EAGAIN; } } diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 0acc47bd1735..79054dc479e2 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1115,9 +1115,9 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), return; } - if (pHddCtx->isLogpInProgress) { - hddLog(CDF_TRACE_LEVEL_ERROR, - "%s: Ignore suspend wlan, LOGP in progress!", __func__); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore suspend!!!", + cds_get_driver_state()); return; } @@ -1171,9 +1171,9 @@ static void hdd_resume_wlan(void) return; } - if (pHddCtx->isLogpInProgress) { - hddLog(CDF_TRACE_LEVEL_INFO, - "%s: Ignore resume wlan, LOGP in progress!", __func__); + if (cds_is_driver_recovering()) { + hdd_warn("Recovery in Progress. State: 0x%x Ignore resume!!!", + cds_get_driver_state()); return; } @@ -1305,8 +1305,7 @@ CDF_STATUS hdd_wlan_shutdown(void) return CDF_STATUS_E_FAILURE; } - pHddCtx->isLogpInProgress = true; - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); cds_clear_concurrent_session_count(); @@ -1656,7 +1655,6 @@ err_re_init: return -EPERM; success: - pHddCtx->isLogpInProgress = false; return CDF_STATUS_SUCCESS; } diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 99880912236d..1162fa3e9a54 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -2314,8 +2314,8 @@ static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, return -ENODEV; } - /* The return 0 is intentional when isLogpInProgress and - * isLoadUnloadInProgress. We did observe a crash due to a return of + /* The return 0 is intentional when Recovery and Load/Unload in + * progress. 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 @@ -2323,13 +2323,15 @@ static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, * clean up of the second interface will have the dev pointer corresponding * to the first one leading to a crash. */ - if (pHddCtx->isLogpInProgress) { - hddLog(LOGE, FL("LOGP in Progress. Ignore!!!")); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return ret; } - if ((pHddCtx->isLoadInProgress) || (pHddCtx->isUnloadInProgress)) { - hddLog(LOGE, FL("Unloading/Loading in Progress. Ignore!!!")); + if (cds_is_load_unload_in_progress()) { + hdd_err("Unload/Load in Progress, state: 0x%x. Ignore!!!", + cds_get_driver_state()); return ret; } diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index 03e4392123b9..d6b98e132bcc 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -168,7 +168,6 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) sme_ac_enum_type ac = SME_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); struct cdf_mac_addr *pDestMacAddress; uint8_t STAId; uint8_t proto_type = 0; @@ -181,9 +180,9 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * context may not be reinitialized at this time which may * lead to a crash. */ - if (pHddCtx->isLogpInProgress) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_INFO_HIGH, - "%s: LOGP in Progress. Ignore!!!", __func__); + "%s: Recovery in Progress. Ignore!!!", __func__); goto drop_pkt; } @@ -368,9 +367,9 @@ static void __hdd_softap_tx_timeout(struct net_device *dev) * recovery here */ hdd_ctx = WLAN_HDD_GET_CTX(adapter); - if (hdd_ctx->isLogpInProgress) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, - "%s: LOGP in Progress. Ignore!!!", __func__); + "%s: Recovery in Progress. Ignore!!!", __func__); return; } } @@ -810,10 +809,10 @@ CDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter) /* bss deregister is not allowed during wlan driver loading or * unloading */ - if ((pHddCtx->isLoadInProgress) || (pHddCtx->isUnloadInProgress)) { + if (cds_is_load_unload_in_progress()) { CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, - "%s:Loading_unloading in Progress. Ignore!!!", - __func__); + "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!", + __func__, cds_get_driver_state()); return CDF_STATUS_E_PERM; } diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 3617d1b2769f..660ec09266b9 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1753,7 +1753,7 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, #ifdef WLAN_FEATURE_LPSS if (!pAdapter->rssi_send) { pAdapter->rssi_send = true; - if (pHddCtx->isUnloadInProgress != true) + if (cds_is_driver_unloading()) wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1); } #endif diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 10b3a86cff79..48d0e19aa8ac 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -771,7 +771,7 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) /* No need to post message during driver unlaod because MC thread is already shutdown */ - if (!pHddCtx->isUnloadInProgress) { + if (!cds_is_driver_unloading()) { tInfo = cdf_mem_malloc(sizeof(tdlsInfo_t)); if (NULL != tInfo) { tInfo->vdev_id = pAdapter->sessionId; @@ -3871,16 +3871,15 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, "%s: Mgmt Tx Completion timed out TxCompletion %u", __func__, pAdapter->mgmtTxCompletionStatus); - if (pHddCtx->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: LOGP in Progress. Ignore!!!", __func__); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return -EAGAIN; } - if (pHddCtx->isUnloadInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s: Unloading/Loading in Progress. Ignore!!!", - __func__); + if (cds_is_driver_unloading()) { + hdd_err("Unload in progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return -EAGAIN; } diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 2d8b0de8ca95..2f3e4fe90d05 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -312,9 +312,9 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled; - if (cds_is_logp_in_progress()) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_HDD_DATA, CDF_TRACE_LEVEL_WARN, - "LOPG in progress, dropping the packet"); + "Recovery in progress, dropping the packet"); ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; kfree_skb(skb); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index e6935bafb2b9..29e5d087263b 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1109,9 +1109,9 @@ CDF_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, int8_t *rssi_value) "%s: Invalid context, pAdapter", __func__); return CDF_STATUS_E_FAULT; } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); /* return a cached value */ *rssi_value = pAdapter->rssi; return CDF_STATUS_SUCCESS; @@ -2248,9 +2248,9 @@ static int __iw_get_bitrate(struct net_device *dev, if (0 != ret) return ret; - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); + if (cds_is_driver_recovering()) { + hdd_alert("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return status; } @@ -3352,9 +3352,9 @@ CDF_STATUS wlan_hdd_get_class_astats(hdd_adapter_t *pAdapter) hddLog(CDF_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); return CDF_STATUS_E_FAULT; } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); + if (cds_is_driver_recovering()) { + hdd_err("Recovery in Progress. State: 0x%x Ignore!!!", + cds_get_driver_state()); return CDF_STATUS_SUCCESS; } diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 80379cff2ab8..bac788852f45 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1494,7 +1494,7 @@ static void hif_sleep_entry(void *arg) if (scn->recovery) return; - if (cds_is_unload_in_progress()) + if (cds_is_driver_unloading()) return; cdf_spin_lock_irqsave(&hif_state->keep_awake_lock); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 23a50c9f11b4..6c7a5622c4f0 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1824,7 +1824,7 @@ hif_target_sleep_state_adjust(struct ol_softc *scn, if (!sc->ol_sc->enable_self_recovery) CDF_BUG(0); scn->recovery = true; - cds_set_logp_in_progress(true); + cds_set_recovery_in_progress(true); cnss_wlan_pci_link_down(); return -EACCES; } diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index db4b2df2648d..00d416928ff0 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -734,7 +734,7 @@ void lim_cleanup_mlm(tpAniSirGlobal mac_ctx) * each STA associated per BSSId and deactivate/delete * the pmfSaQueryTimer for it */ - if (cds_is_logp_in_progress()) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, FL("SSR is detected, proceed to clean up pmfSaQueryTimer")); for (bss_entry = 0; bss_entry < mac_ctx->lim.maxBssId; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index d68d2e2f7bf4..00259865229c 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3573,7 +3573,7 @@ CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle) WMA_LOGE("Credits:%d; Pending_Cmds: %d", wmi_get_host_credits(wma->wmi_handle), wmi_get_pending_cmds(wma->wmi_handle)); - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { #ifdef CONFIG_CNSS if (pMac->sme.enableSelfRecovery) { cds_trigger_recovery(); @@ -3605,7 +3605,7 @@ CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle) "cannot resume back", __func__, host_credits, wmi_pending_cmds); htc_dump_counter_info(wma->htc_handle); - if (!cds_is_logp_in_progress()) + if (!cds_is_driver_recovering()) CDF_BUG(0); else WMA_LOGE("%s: SSR in progress, ignore no credit issue", @@ -4131,7 +4131,7 @@ static CDF_STATUS wma_send_host_wakeup_ind_to_fw(tp_wma_handle wma) WMA_LOGP("%s: Pending commands %d credits %d", __func__, wmi_get_pending_cmds(wma->wmi_handle), wmi_get_host_credits(wma->wmi_handle)); - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { #ifdef CONFIG_CNSS if (pMac->sme.enableSelfRecovery) { cds_trigger_recovery(); @@ -6285,7 +6285,7 @@ int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) WMA_LOGE("Failed to get ACK from firmware for pdev suspend"); wmi_set_target_suspend(wma_handle->wmi_handle, false); #ifdef CONFIG_CNSS - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { if (pmac->sme.enableSelfRecovery) { cds_trigger_recovery(); } else { @@ -6382,7 +6382,7 @@ int wma_resume_target(WMA_HANDLE handle) WMA_LOGP("%s: Pending commands %d credits %d", __func__, wmi_get_pending_cmds(wma->wmi_handle), wmi_get_host_credits(wma->wmi_handle)); - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { #ifdef CONFIG_CNSS if (pMac->sme.enableSelfRecovery) { cds_trigger_recovery(); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index ab6e66417626..26b633515483 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2802,7 +2802,7 @@ CDF_STATUS wma_stop(void *cds_ctx, uint8_t reason) } /* There's no need suspend target which is already down during SSR. */ - if (!cds_is_logp_in_progress()) { + if (!cds_is_driver_recovering()) { #ifdef HIF_USB /* Suspend the target and enable interrupt */ if (wma_suspend_target(wma_handle, 0)) -- cgit v1.2.3 From d78d30cb273fa481e567970ce9d4a481c19e4ba5 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Mon, 4 Jan 2016 16:48:19 -0800 Subject: qcacld-3.0: call IPA cleanup when cds_enable failed qcacld-2.0 to qcacld-3.0 propagation When CDS enable fails after IPA init, IPA cleanup is missed. This will cause a system crash later as IPA resource is not properly teared down. Change-Id: I563e92e4ed5319b6489dcc8cffb6a802d54e8549 CRs-fixed: 949015 --- core/hdd/src/wlan_hdd_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index b2b86a758f58..cd4e695f1d18 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5068,7 +5068,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) status = cds_enable(hdd_ctx->pcds_context); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_enable failed")); - goto err_wiphy_unregister; + goto err_ipa_cleanup; } hdd_init_channel_avoidance(hdd_ctx); @@ -5497,6 +5497,9 @@ err_close_adapter: err_cds_disable: cds_disable(p_cds_context); +err_ipa_cleanup: + hdd_ipa_cleanup(hdd_ctx); + err_wiphy_unregister: wiphy_unregister(wiphy); -- cgit v1.2.3 From 58f72939dd7464735d8709291f9d8146d53b19c6 Mon Sep 17 00:00:00 2001 From: Yun Park Date: Mon, 4 Jan 2016 17:00:01 -0800 Subject: qcacld-3.0: Remove code to clean pending_cons_req from WLAN_CLIENT_CONNECT qcacld-2.0 to qcacld-3.0 propagation There is a race condition between TX_RESUME opcode, where checks pending_cons_req before sending WLAN_CONS grant notification to IPA, and WLAN_CLIENT_CONNECT event where clearing the pending_cons_req. We don't need to clear pending_cons_req from WLAN_CLIENT_CONNECT event, which is actually cleared by TX_RESUME opcode. Change-Id: Icc5d05bc77800251b031efd0c07b0feaa2ae921d CRs-Fixed: 952171 --- core/hdd/src/wlan_hdd_ipa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 98c95f656ef3..38ac21d3bfea 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -3804,7 +3804,6 @@ int hdd_ipa_wlan_evt(hdd_adapter_t *adapter, uint8_t sta_id, } hdd_ipa->sap_num_connected_sta++; - hdd_ipa->pending_cons_req = false; cdf_mutex_release(&hdd_ipa->event_lock); -- cgit v1.2.3 From 25420011d5153d430dc538420a4b07c485d24b62 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Wed, 23 Dec 2015 14:35:54 -0800 Subject: qcacld-3.0: CL 1434462 update fw common interface files qcacld-2.0 to qcacld-3.0 propagation Add WMI changes to send FW response for Peer, Vdev delete command Change-Id: Icbcf0b68e9ac64252a7206c9f5ea81da6e457457 CRs-fixed: 865207 --- target/inc/wmi_services.h | 1 + target/inc/wmi_tlv_defs.h | 22 +++++++++++++++++++--- target/inc/wmi_unified.h | 21 +++++++++++++++++++++ target/inc/wmi_version.h | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/target/inc/wmi_services.h b/target/inc/wmi_services.h index c654dffcf93f..8b1268c6ac2f 100644 --- a/target/inc/wmi_services.h +++ b/target/inc/wmi_services.h @@ -140,6 +140,7 @@ typedef enum { WMI_SERVICE_ENTERPRISE_MESH, /* Enterprise MESH Service Support */ WMI_SERVICE_RESTRT_CHNL_SUPPORT, /* Restricted Channel Support */ WMI_SERVICE_BPF_OFFLOAD, /* FW supports bpf offload */ + WMI_SERVICE_SYNC_DELETE_CMDS, /* FW sends response event for Peer, Vdev delete commands */ WMI_MAX_SERVICE = 128 /* max service */ } WMI_SERVICE; diff --git a/target/inc/wmi_tlv_defs.h b/target/inc/wmi_tlv_defs.h index 533476121de8..d7645fa8cacf 100644 --- a/target/inc/wmi_tlv_defs.h +++ b/target/inc/wmi_tlv_defs.h @@ -611,6 +611,9 @@ typedef enum { WMITLV_TAG_STRUC_wmi_bpf_vdev_stats_info_evt_fixed_param, WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, WMITLV_TAG_STRUC_wmi_bpf_del_vdev_instructions_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_vdev_delete_resp_event_fixed_param, + WMITLV_TAG_STRUC_wmi_peer_delete_resp_event_fixed_param, + } WMITLV_TAG_ID; /* @@ -976,7 +979,10 @@ typedef enum { OP(WMI_PDEV_UTF_SCPC_EVENTID) \ OP(WMI_STA_SMPS_FORCE_MODE_COMPLETE_EVENTID) \ OP(WMI_BPF_CAPABILIY_INFO_EVENTID) \ - OP(WMI_BPF_VDEV_STATS_INFO_EVENTID) + OP(WMI_BPF_VDEV_STATS_INFO_EVENTID) \ + OP(WMI_VDEV_DELETE_RESP_EVENTID) \ + OP(WMI_PEER_DELETE_RESP_EVENTID) + /* TLV definitions of WMI commands */ @@ -2545,6 +2551,11 @@ WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_START_RESP_EVENTID); 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 delete response Event */ +#define WMITLV_TABLE_WMI_VDEV_DELETE_RESP_EVENTID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_vdev_delete_resp_event_fixed_param, wmi_vdev_delete_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_DELETE_RESP_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) @@ -2945,10 +2956,15 @@ WMITLV_CREATE_PARAM_STRUC(WMI_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID); 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) +#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 delete response Event */ +#define WMITLV_TABLE_WMI_PEER_DELETE_RESP_EVENTID(id, op, buf, len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_peer_delete_resp_event_fixed_param, wmi_peer_delete_resp_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_PEER_DELETE_RESP_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) diff --git a/target/inc/wmi_unified.h b/target/inc/wmi_unified.h index 007fd5ddfcdd..869c68f11113 100644 --- a/target/inc/wmi_unified.h +++ b/target/inc/wmi_unified.h @@ -934,6 +934,10 @@ typedef enum { /* Return the TSF timestamp of specified vdev */ WMI_VDEV_TSF_REPORT_EVENTID, + + /* FW response to Host for vdev delete cmdid */ + WMI_VDEV_DELETE_RESP_EVENTID, + /* peer specific events */ /** FW reauet to kick out the station for reasons like inactivity,lack of response ..etc */ WMI_PEER_STA_KICKOUT_EVENTID = @@ -959,6 +963,9 @@ typedef enum { */ WMI_PEER_ASSOC_CONF_EVENTID, + /* FW response to Host for peer delete cmdid */ + WMI_PEER_DELETE_RESP_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), @@ -4739,6 +4746,12 @@ typedef struct { A_UINT32 vdev_id; } wmi_vdev_stopped_event_fixed_param; +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_delete_resp_event_fixed_param */ + /** unique id identifying the VDEV, generated by the caller */ + A_UINT32 vdev_id; +} wmi_vdev_delete_resp_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 */ @@ -9907,6 +9920,14 @@ typedef struct { */ } wmi_stats_ext_event_fixed_param; +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_peer_delete_resp_event_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_resp_event_fixed_param; + typedef struct { /* TLV tag and len; tag equals WMITLV_TAG_STRUC_ wmi_peer_state_event_fixed_param */ A_UINT32 tlv_header; diff --git a/target/inc/wmi_version.h b/target/inc/wmi_version.h index 7de4596c671e..875992f38794 100644 --- a/target/inc/wmi_version.h +++ b/target/inc/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility */ -#define __WMI_REVISION_ 191 +#define __WMI_REVISION_ 192 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work -- cgit v1.2.3 From 8da8e600067db33eb80f9dd048ff9b05c7c5161f Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Thu, 7 Jan 2016 18:00:16 -0800 Subject: qcacld-3.0: Configure FW WMI logging for adrastea and rome In adrastea multithreaded firmware WMI logging infrastructure is not yet ready. Disable WMI FW logging for adrastea and enable it for ROME based targets. Change-Id: I64c858681f57a2a013fd23bcd9204f59ff638102 CRs-Fixed: 959416 --- config/WCNSS_qcom_cfg.ini | 3 --- core/hdd/inc/wlan_hdd_cfg.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 8a5646885a79..8de3a16d4241 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -418,9 +418,6 @@ gEnablePowerSaveOffload=2 #Enable firmware uart print gEnablefwprint=0 -#Enable firmware log -gEnablefwlog=1 - #IPA config gIPAConfig=0 gIPADescSize=800 diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 242eb793e20b..beb482abdf5e 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1945,7 +1945,11 @@ typedef enum { #define CFG_ENABLE_FW_LOG_NAME "gEnablefwlog" #define CFG_ENABLE_FW_LOG_DISABLE (0) #define CFG_ENABLE_FW_LOG_ENABLE (1) +#ifdef QCA_WIFI_3_0_ADRASTEA #define CFG_ENABLE_FW_LOG_DEFAULT (CFG_ENABLE_FW_LOG_DISABLE) +#else +#define CFG_ENABLE_FW_LOG_DEFAULT (CFG_ENABLE_FW_LOG_ENABLE) +#endif /* * Enable/Disable SSR for USB -- cgit v1.2.3 From 1c66dfac6535a15812a3a7af406aca8637a8e3fd Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Thu, 7 Jan 2016 15:21:29 -0800 Subject: Release 5.0.0.156 Release 5.0.0.156 Change-Id: Ia96b37945abda73a18cb4a1c4df0939d1e23a099 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index b6f86a1c5bcd..1868305a54c7 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 155 +#define QWLAN_VERSION_BUILD 156 -#define QWLAN_VERSIONSTR "5.0.0.155" +#define QWLAN_VERSIONSTR "5.0.0.156" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 2c9cb348907e2ab2d57d53947f9b953404b75bd9 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 11 Jan 2016 15:24:59 -0800 Subject: qcacld-3.0: Convert wlan_hdd_nan.c to unified logging Currently the HDD code uses a variety of logging APIs. In qcacld-3.0 HDD should converge on a unified set of logging APIs. Update wlan_hdd_nan.c to use the unified set of APIs. Change-Id: I4dcc61656f1cd45d3a2c9d63441c27a733385328 CRs-Fixed: 937673 --- core/hdd/src/wlan_hdd_nan.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/core/hdd/src/wlan_hdd_nan.c b/core/hdd/src/wlan_hdd_nan.c index eb06a16aa8ff..7e1e8c613152 100644 --- a/core/hdd/src/wlan_hdd_nan.c +++ b/core/hdd/src/wlan_hdd_nan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -25,6 +25,9 @@ * WLAN Host Device Driver NAN API implementation */ +/* denote that this file does not allow legacy hddLog */ +#define HDD_DISALLOW_LEGACY_HDDLOG 1 + #include #include #include @@ -131,15 +134,13 @@ static void wlan_hdd_cfg80211_nan_callback(void *ctx, tSirNanEvent *msg) int status; if (NULL == msg) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("msg received here is null")); + hdd_err("msg received here is null"); return; } status = wlan_hdd_validate_context(hdd_ctx); if (0 != status) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("HDD context is not valid")); + hdd_err("HDD context is not valid"); return; } @@ -151,14 +152,12 @@ static void wlan_hdd_cfg80211_nan_callback(void *ctx, tSirNanEvent *msg) GFP_KERNEL); if (!vendor_event) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("cfg80211_vendor_event_alloc failed")); + hdd_err("cfg80211_vendor_event_alloc failed"); return; } if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NAN, msg->event_data_len, msg->event_data)) { - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR, - FL("QCA_WLAN_VENDOR_ATTR_NAN put fail")); + hdd_err("QCA_WLAN_VENDOR_ATTR_NAN put fail"); kfree_skb(vendor_event); return; } -- cgit v1.2.3 From 842318192c99071e298249c363b24516bb935e79 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Wed, 6 Jan 2016 16:02:31 -0800 Subject: qcacld-3.0: Fix incorrect logging in hdd_send_re_assoc_event() Change "qcacld-3.0: Roaming enhancement to allow multiple ssid" (Change-Id If4953e64f9e0485edec85167a7bc1dd6ca7c2047) added some incorrect logging to function hdd_send_re_assoc_event(). The intent was to perform a hex dump of the buf_ssid_ie and final_req_ie buffers, but in reality the code actually uses these buffers as logging format strings. Fix this by invoking the correct API to perform a hex dump. Change-Id: Id861ececd119ea7247ce24c7c8ea9173f13703d3 CRs-Fixed: 958752 --- core/hdd/src/wlan_hdd_assoc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 81bb20992072..e9242d384b5a 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1445,8 +1445,9 @@ static void hdd_send_re_assoc_event(struct net_device *dev, cdf_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:")); - hddLog(CDF_TRACE_LEVEL_DEBUG, buf_ssid_ie, ssid_ie_len); + hdd_notice("SSIDIE:"); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_HDD, CDF_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; @@ -1457,9 +1458,9 @@ static void hdd_send_re_assoc_event(struct net_device *dev, cdf_mem_copy(rspRsnIe, pFTAssocRsp, len); cdf_mem_zero(final_req_ie + (ssid_ie_len + reqRsnLength), IW_GENERIC_IE_MAX - (ssid_ie_len + reqRsnLength)); - hddLog(LOG2, FL("Req RSN IE:")); - hddLog(CDF_TRACE_LEVEL_DEBUG, final_req_ie, - (ssid_ie_len + reqRsnLength)); + hdd_notice("Req RSN IE:"); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_HDD, CDF_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); -- cgit v1.2.3 From 016329735ffd2bf4b61d2df1cf342088bf62282d Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Fri, 8 Jan 2016 15:42:27 -0800 Subject: qcacld-3.0: Convert wlan_hdd_lro.c to unified logging Currently the HDD code uses a variety of logging APIs. In qcacld-3.0 HDD should converge on a unified set of logging APIs. Update wlan_hdd_lro.c to use the unified set of APIs. Change-Id: I72bf2b55390e1c72706077d22f61e59d17d14f13 CRs-Fixed: 937662 --- core/hdd/src/wlan_hdd_lro.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c index a84e839b6967..5ff2b9deeddb 100644 --- a/core/hdd/src/wlan_hdd_lro.c +++ b/core/hdd/src/wlan_hdd_lro.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -30,6 +30,9 @@ * WLAN HDD LRO interface implementation */ +/* denote that this file does not allow legacy hddLog */ +#define HDD_DISALLOW_LEGACY_HDDLOG 1 + #include #include #include @@ -458,7 +461,7 @@ int hdd_lro_init(hdd_context_t *hdd_ctx) struct wma_lro_config_cmd_t lro_config; if (!hdd_ctx->config->lro_enable) { - hdd_err(FL("LRO Disabled")); + hdd_err("LRO Disabled"); return 0; } -- cgit v1.2.3 From 03059dca6c440b2a33fb43d480a8e4e0825d0625 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 7 Jan 2016 18:31:35 -0800 Subject: qcacld-3.0: Convert wlan_hdd_driver_ops.c to unified logging Currently the HDD code uses a variety of logging APIs. In qcacld-3.0 HDD should converge on a unified set of logging APIs. Update wlan_hdd_driver_ops.c to use the unified set of APIs. Change-Id: I5620e91797412c0dbf32c1071b3eefd54f54aca7 CRs-Fixed: 937590 --- core/hdd/src/wlan_hdd_driver_ops.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 9f0d6d99b513..2308a0d6edaf 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -25,6 +25,9 @@ * to the Linux Foundation. */ +/* denote that this file does not allow legacy hddLog */ +#define HDD_DISALLOW_LEGACY_HDDLOG 1 + #include #include #ifdef HIF_PCI @@ -338,8 +341,7 @@ static void wlan_hdd_shutdown(void) void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); if (cds_is_load_unload_in_progress()) { - hddLog(LOGE, - FL("Load/unload in progress, ignore SSR shutdown")); + hdd_err("Load/unload in progress, ignore SSR shutdown"); return; } /* this is for cases, where shutdown invoked from CNSS */ @@ -350,8 +352,7 @@ static void wlan_hdd_shutdown(void) hif_pktlogmod_exit(hif_ctx); if (!cds_is_ssr_ready(__func__)) - hddLog(LOGE, - FL("Host is not ready for SSR, attempting anyway")); + hdd_err("Host is not ready for SSR, attempting anyway"); if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { hif_disable_isr(hif_ctx); @@ -390,7 +391,7 @@ void wlan_hdd_notify_handler(int state) int ret = 0; ret = hdd_wlan_notify_modem_power_state(state); if (ret < 0) - hddLog(LOGE, FL("Fail to send notify")); + hdd_err("Fail to send notify"); } } @@ -486,7 +487,7 @@ static int __wlan_hdd_bus_resume(void) int status = wlan_hdd_validate_context(hdd_ctx); if (0 != status) { - hddLog(LOGE, FL("HDD context is not valid")); + hdd_err("HDD context is not valid"); return status; } -- cgit v1.2.3 From 27bb52f2bf62bd4725c84292cb6dccc55220dfdb Mon Sep 17 00:00:00 2001 From: kaliu Date: Wed, 30 Dec 2015 17:27:58 +0530 Subject: qcacld-3.0: eSmeCommandDelStaSession stuck in smeCmdActiveList qcacld-2.0 to qcacld-3.0 propagation. 1.Use iw tool to let dut connect to remote ap, dut is working on wlan0. 2.At same time, use hostapd to start sap also on interface wlan0. In item1, before connect to ap, dut will do an internal scan to search ap, if scan result matched configured ap profile, dut trys to connect to ap. In item2, when starting sap, found it's sta mode it will try to disconnect dut with remote ap and close sta session. #1 If ap start action happened in item1's scan period, trying disconnecting won't take effect as currently sta has not yet connected with remote ap. So after item1's scan finished, dut continues to do connection. #2 During closing sta session, sme issued eSmeCommandDelStaSession, as currently sta is doing connection, so session is in started status, this cause closure failed, so there is no chance to remove cmd in smeCmdActiveList. While cmd pending in smeCmdActiveList for 120s, driver issued crash. The solution is in item1 after scan complete to check whether it's needed to start following connection. If stop action has been issued during scan period, then don't do the connection. Change-Id: If632e21cb13277fba371ff1bf8df97febf856d09 CRs-Fixed: 923375 --- core/sme/inc/csr_api.h | 4 +++- core/sme/src/csr/csr_api_roam.c | 4 +++- core/sme/src/csr/csr_api_scan.c | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index af46ebc441da..08e3b15f3e37 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -662,6 +662,8 @@ typedef enum { eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED, /* Participating in a Infra network and connected to a peer */ eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED, + /* Disconnecting with AP or stop connecting process */ + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING, } eCsrConnectState; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f22cf8dac2a1..b7a9aefb3711 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -7777,6 +7777,8 @@ CDF_STATUS csr_roam_disconnect_internal(tpAniSirGlobal pMac, uint32_t sessionId, status = csr_roam_issue_disassociate_cmd(pMac, sessionId, reason); } else { + pMac->roam.roamSession[sessionId].connectState = + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING; csr_scan_abort_scan_for_ssid(pMac, sessionId); status = CDF_STATUS_CMD_NOT_QUEUED; sms_log(pMac, LOG1, diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index fde1c3038bb1..7a6e1155eab8 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1181,6 +1181,13 @@ CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac, status = csr_scan_get_result(pMac, pScanFilter, &hBSSList); if (!CDF_IS_STATUS_SUCCESS(status)) break; + if (pMac->roam.roamSession[sessionId].connectState == + eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING) { + sms_log(pMac, LOGE, + FL("upper layer issued disconnetion")); + status = CDF_STATUS_E_FAILURE; + break; + } status = csr_roam_issue_connect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued, pCommand->u.scanCmd.roamId, -- cgit v1.2.3 From df962438e5e6f4f2f780bf5018aba5464cc9310d Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 30 Dec 2015 17:24:02 +0530 Subject: qcacld-3.0: Send management frame indication directly to HDD from PE qcacld-2.0 to qcacld-3.0 propagation. If MC thread stall while waiting on any event, In case of WPS, probe requests may get accumulated in PE message queue. Now every time MC thread process a probe request, eWNI_SME_MGMT_FRM_IND msg is posted in SME message queue. But unless PE queue is fully processed SME queue won't be processed. This will gradually use all vos message wrapper. To avoid this register a callback to send management frame indication directly to HDD from PE which avoids posting message to SME queue. Change-Id: Ib83700825112cc52dade594909bfa8993909ac29 CRs-Fixed: 944961 --- core/hdd/inc/wlan_hdd_main.h | 3 + core/hdd/inc/wlan_hdd_p2p.h | 4 +- core/hdd/src/wlan_hdd_assoc.c | 8 -- core/hdd/src/wlan_hdd_cfg80211.c | 3 + core/hdd/src/wlan_hdd_hostapd.c | 11 --- core/hdd/src/wlan_hdd_main.c | 90 ++++++++++++++++++++++ core/hdd/src/wlan_hdd_p2p.c | 2 +- core/mac/inc/ani_global.h | 4 +- core/mac/inc/sir_api.h | 18 ++++- core/mac/inc/wni_api.h | 4 +- core/mac/src/pe/lim/lim_p2p.c | 17 ++-- core/mac/src/pe/lim/lim_process_message_queue.c | 3 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 31 ++++++++ core/mac/src/sys/legacy/src/utils/src/mac_trace.c | 4 +- core/sap/inc/sap_api.h | 5 +- core/sap/src/sap_api_link_cntl.c | 7 +- core/sap/src/sap_fsm.c | 14 +--- core/sme/inc/csr_api.h | 1 - core/sme/inc/sme_api.h | 5 +- core/sme/src/common/sme_api.c | 55 ++++++++++--- core/sme/src/csr/csr_util.c | 3 +- core/sme/src/p2p/p2p_api.c | 42 +--------- 22 files changed, 214 insertions(+), 120 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index cb7693f1cc3d..33776454ae7a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1542,6 +1542,9 @@ void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *pHddCtx); void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx); void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx); const char *hdd_get_fwpath(void); +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); uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset); diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index ce1670bfd1c4..cfd9aaf686d1 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -108,7 +108,7 @@ int hdd_set_p2p_ps(struct net_device *dev, void *msgData); int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command); int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command); -void hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, +void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, uint32_t nFrameLength, uint8_t *pbFrames, uint8_t frameType, uint32_t rxChan, int8_t rxRssi); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index e9242d384b5a..12addc14c9b7 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -4168,14 +4168,6 @@ defined(FEATURE_WLAN_LFR)) } break; #endif - - case eCSR_ROAM_INDICATE_MGMT_FRAME: - hdd_indicate_mgmt_frame(pAdapter, - pRoamInfo->nFrameLength, - pRoamInfo->pbFrames, - pRoamInfo->frameType, - pRoamInfo->rxChan, pRoamInfo->rxRssi); - break; case eCSR_ROAM_REMAIN_CHAN_READY: hdd_remain_chan_ready_handler(pAdapter, pRoamInfo->roc_scan_id); break; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index ac59b0b6890e..e80b293541fa 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5576,6 +5576,9 @@ void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter) ENTER(); + /* Register frame indication call back */ + sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame); + /* 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 */ diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 5361c76ac12d..c5ee4d860821 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1519,17 +1519,6 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, cdf_mem_free(pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas); /* Release caller allocated memory here */ pSapEvent->sapevt.sapAssocStaListEvent.pAssocStas = NULL; return CDF_STATUS_SUCCESS; - case eSAP_INDICATE_MGMT_FRAME: - hdd_indicate_mgmt_frame(pHostapdAdapter, - pSapEvent->sapevt.sapManagementFrameInfo. - nFrameLength, - pSapEvent->sapevt.sapManagementFrameInfo. - pbFrames, - pSapEvent->sapevt.sapManagementFrameInfo. - frameType, - pSapEvent->sapevt.sapManagementFrameInfo. - rxChan, 0); - return CDF_STATUS_SUCCESS; case eSAP_REMAIN_CHAN_READY: hdd_remain_chan_ready_handler(pHostapdAdapter, pSapEvent->sapevt.sap_roc_ind.scan_id); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index cd4e695f1d18..31d5a88cd335 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3159,6 +3159,43 @@ hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx, return NULL; } +/** + * hdd_get_adapter_by_sme_session_id() - Return adapter with + * the sessionid + * @hdd_ctx: hdd context. + * @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; + CDF_STATUS cdf_status; + + + cdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + + while ((NULL != adapter_node) && + (CDF_STATUS_SUCCESS == cdf_status)) { + adapter = adapter_node->pAdapter; + + if (adapter && + adapter->sessionId == sme_session_id) + return adapter; + + cdf_status = + hdd_get_next_adapter(hdd_ctx, + adapter_node, &next); + adapter_node = next; + } + return NULL; +} + hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode) { hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; @@ -4450,6 +4487,59 @@ static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, } return 0; } +/** + * 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 = NULL; + hdd_adapter_t *adapter = NULL; + void *cds_context = NULL; + int i; + + /* Get the global VOSS context.*/ + cds_context = cds_get_global_context(); + if (!cds_context) { + hddLog(LOGE, FL("Global VOS context is Null")); + return; + } + /* Get the HDD context.*/ + hdd_ctx = + (hdd_context_t *)cds_get_context(CDF_MODULE_ID_HDD); + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return; + + if (SME_SESSION_ID_ANY == frame_ind->sessionId) { + for (i = 0; i < CSR_ROAM_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; +} /** * hdd_ch_avoid_cb() - Avoid notified channels from FW handler diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index f22f95e95e10..6bbf1c625c2d 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -2084,7 +2084,7 @@ int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) return ret; } -void hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, +void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, uint32_t nFrameLength, uint8_t *pbFrames, uint8_t frameType, uint32_t rxChan, int8_t rxRssi) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index d89063e831b6..c90e433e131d 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1041,7 +1041,7 @@ typedef struct sAniSirGlobal { bool enable_dot11p; uint32_t dual_mac_feature_disable; - + sir_mgmt_frame_ind_callback mgmt_frame_ind_cb; bool first_scan_done; int8_t first_scan_bucket_threshold; } tAniSirGlobal; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 77ed19180ed0..041a17b1aabe 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2577,8 +2577,7 @@ typedef struct sSirKeepAliveReq { } tSirKeepAliveReq, *tpSirKeepAliveReq; typedef struct sSirSmeMgmtFrameInd { - uint16_t mesgType; - uint16_t mesgLen; + uint16_t frame_len; uint32_t rxChan; uint8_t sessionId; uint8_t frameType; @@ -2586,6 +2585,21 @@ typedef struct sSirSmeMgmtFrameInd { uint8_t 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; +}; + #ifdef WLAN_FEATURE_11W typedef struct sSirSmeUnprotMgmtFrameInd { uint8_t sessionId; diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index ca7bf580ecf1..12b874d5f02b 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -104,7 +104,6 @@ enum eWniMsgTypes { eWNI_SME_CHNG_MCC_BEACON_INTERVAL, eWNI_SME_REMAIN_ON_CHANNEL_REQ, eWNI_SME_REMAIN_ON_CHN_RSP, - eWNI_SME_MGMT_FRM_IND, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eWNI_SME_SEND_ACTION_FRAME_IND, eWNI_SME_ACTION_FRAME_SEND_CNF, @@ -249,6 +248,7 @@ enum eWniMsgTypes { eWNI_SME_SET_IE_REQ, eWNI_SME_EXT_CHANGE_CHANNEL, eWNI_SME_EXT_CHANGE_CHANNEL_IND, + eWNI_SME_REGISTER_MGMT_FRAME_CB, eWNI_SME_MSG_TYPES_END }; diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c index 08ed8fce3ce3..8a776b99a540 100644 --- a/core/mac/src/pe/lim/lim_p2p.c +++ b/core/mac/src/pe/lim/lim_p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014,2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -380,7 +380,6 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, uint16_t sessionId, uint32_t rxChannel, tpPESession psessionEntry, int8_t rxRssi) { - tSirMsgQ mmhMsg; tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL; uint16_t length; @@ -394,8 +393,7 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, } cdf_mem_set((void *)pSirSmeMgmtFrame, length, 0); - pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND; - pSirSmeMgmtFrame->mesgLen = length; + pSirSmeMgmtFrame->frame_len = frameLen; pSirSmeMgmtFrame->sessionId = sessionId; pSirSmeMgmtFrame->frameType = frameType; pSirSmeMgmtFrame->rxRssi = rxRssi; @@ -404,11 +402,12 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType, cdf_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen); cdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); - mmhMsg.type = eWNI_SME_MGMT_FRM_IND; - mmhMsg.bodyptr = pSirSmeMgmtFrame; - mmhMsg.bodyval = 0; - - lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); + if (pMac->mgmt_frame_ind_cb) + pMac->mgmt_frame_ind_cb(pSirSmeMgmtFrame); + else + lim_log(pMac, LOGW, + FL("Management indication callback not registered!!")); + cdf_mem_free(pSirSmeMgmtFrame); return; } diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index ca614fe4ea37..d6e314e7d962 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1354,6 +1354,7 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) #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_REGISTER_MGMT_FRAME_CB: case eWNI_SME_EXT_CHANGE_CHANNEL: /* These messages are from HDD.No need to respond to HDD */ lim_process_normal_hdd_msg(mac_ctx, msg, false); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index c3f4705917f9..03121a6019fe 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -4732,6 +4732,34 @@ __lim_process_sme_reset_ap_caps_change(tpAniSirGlobal pMac, uint32_t *pMsgBuf) return; } +/** + * lim_register_mgmt_frame_ind_cb() - Save the Management frame + * indication callback in PE. + * @mac_ptr: 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) { + lim_log(mac_ctx, LOGE, FL("msg_buf is null")); + return; + } + if (sme_req->callback) + mac_ctx->mgmt_frame_ind_cb = + (sir_mgmt_frame_ind_callback)sme_req->callback; + else + lim_log(mac_ctx, LOGE, FL("sme_req->callback is null")); +} + /** * lim_process_sme_req_messages() * @@ -4968,6 +4996,9 @@ bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_SET_IE_REQ: lim_process_set_ie_req(pMac, pMsgBuf); break; + case eWNI_SME_REGISTER_MGMT_FRAME_CB: + lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf); + break; case eWNI_SME_EXT_CHANGE_CHANNEL: lim_process_ext_change_channel(pMac, pMsgBuf); break; diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 63f13c8fe787..10b000bb9227 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -283,7 +283,6 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) 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_RSP); - CASE_RETURN_STRING(eWNI_SME_MGMT_FRM_IND); CASE_RETURN_STRING(eWNI_SME_REMAIN_ON_CHN_RDY_IND); CASE_RETURN_STRING(eWNI_SME_SEND_ACTION_FRAME_IND); CASE_RETURN_STRING(eWNI_SME_ACTION_FRAME_SEND_CNF); @@ -334,6 +333,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) CASE_RETURN_STRING(eWNI_SME_SET_HW_MODE_REQ); CASE_RETURN_STRING(eWNI_SME_SET_HW_MODE_RESP); CASE_RETURN_STRING(eWNI_SME_HW_MODE_TRANS_IND); + CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB); default: return (uint8_t *) "UNKNOWN"; break; diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 75f92b5454d7..40f3b2d3073a 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -158,7 +158,6 @@ typedef enum { eSAP_GET_WPSPBC_SESSION_EVENT, /* Event send on WPS PBC probe request is received */ eSAP_WPS_PBC_PROBE_REQ_EVENT, - eSAP_INDICATE_MGMT_FRAME, eSAP_REMAIN_CHAN_READY, eSAP_SEND_ACTION_CNF, eSAP_DISCONNECT_ALL_P2P_CLIENT, @@ -448,8 +447,6 @@ typedef struct sap_Event_s { tSap_GetWPSPBCSessionEvent sapGetWPSPBCSessionEvent; /*eSAP_WPS_PBC_PROBE_REQ_EVENT */ tSap_WPSPBCProbeReqEvent sapPBCProbeReqEvent; - /*eSAP_INDICATE_MGMT_FRAME */ - tSap_ManagementFrameInfo sapManagementFrameInfo; /* eSAP_SEND_ACTION_CNF */ tSap_SendActionCnf sapActionCnf; /* eSAP_UNKNOWN_STA_JOIN */ diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index 381f444d640b..0474e2120f14 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -888,11 +888,6 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, FL("CSR roam_status = eCSR_ROAM_WPS_PBC_PROBE_REQ_IND (%d)\n"), roam_status); break; - case eCSR_ROAM_INDICATE_MGMT_FRAME: - sap_signal_hdd_event(sap_ctx, csr_roam_info, - eSAP_INDICATE_MGMT_FRAME, - (void *) eSAP_STATUS_SUCCESS); - break; case eCSR_ROAM_REMAIN_CHAN_READY: /* roamId contains scan identifier */ sap_ctx->roc_ind_scan_id = csr_roam_info->roc_scan_id; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index b14deb41f103..8335de53ab5f 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -818,7 +818,6 @@ static uint8_t *sap_hdd_event_to_string(eSapHddEvent event) CASE_RETURN_STRING(eSAP_ASSOC_STA_CALLBACK_EVENT); CASE_RETURN_STRING(eSAP_GET_WPSPBC_SESSION_EVENT); CASE_RETURN_STRING(eSAP_WPS_PBC_PROBE_REQ_EVENT); - CASE_RETURN_STRING(eSAP_INDICATE_MGMT_FRAME); CASE_RETURN_STRING(eSAP_REMAIN_CHAN_READY); CASE_RETURN_STRING(eSAP_SEND_ACTION_CNF); CASE_RETURN_STRING(eSAP_DISCONNECT_ALL_P2P_CLIENT); @@ -2516,7 +2515,6 @@ CDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx, tSap_StationDisassocCompleteEvent *disassoc_comp; tSap_StationSetKeyCompleteEvent *key_complete; tSap_StationMICFailureEvent *mic_failure; - tSap_ManagementFrameInfo *mgmt_frame; /* Format the Start BSS Complete event to return... */ if (NULL == sap_ctx->pfnSapEventCallback) { @@ -2732,16 +2730,6 @@ CDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx, sizeof(tSirWPSPBCProbeReq)); break; - case eSAP_INDICATE_MGMT_FRAME: - sap_ap_event.sapHddEventCode = eSAP_INDICATE_MGMT_FRAME; - mgmt_frame = &sap_ap_event.sapevt.sapManagementFrameInfo; - - mgmt_frame->nFrameLength = csr_roaminfo->nFrameLength; - mgmt_frame->pbFrames = csr_roaminfo->pbFrames; - mgmt_frame->frameType = csr_roaminfo->frameType; - mgmt_frame->rxChan = csr_roaminfo->rxChan; - break; - case eSAP_REMAIN_CHAN_READY: sap_ap_event.sapHddEventCode = eSAP_REMAIN_CHAN_READY; sap_ap_event.sapevt.sap_roc_ind.scan_id = diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 08e3b15f3e37..0b16d7b54787 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -480,7 +480,6 @@ typedef enum { eCSR_ROAM_FT_RESPONSE, #endif eCSR_ROAM_FT_START, - eCSR_ROAM_INDICATE_MGMT_FRAME, eCSR_ROAM_REMAIN_CHAN_READY, eCSR_ROAM_SEND_ACTION_CNF, /* this mean error happens before assoc_start/roam_start is called. */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index a00d847576b8..9ef7599b29ed 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -973,6 +973,9 @@ CDF_STATUS sme_set_rssi_monitoring(tHalHandle hal, CDF_STATUS sme_set_rssi_threshold_breached_cb(tHalHandle hal, void (*cb)(void *, struct rssi_breach_event *)); +CDF_STATUS sme_register_mgmt_frame_ind_callback(tHalHandle hal, + sir_mgmt_frame_ind_callback callback); + CDF_STATUS sme_update_nss(tHalHandle h_hal, uint8_t nss); bool sme_is_any_session_in_connected_state(tHalHandle h_hal); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 5178a8de8521..92bbe82a8a8d 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -74,8 +74,6 @@ extern void qos_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand); extern CDF_STATUS p2p_process_remain_on_channel_cmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn); extern CDF_STATUS sme_remain_on_chn_rsp(tpAniSirGlobal pMac, uint8_t *pMsg); -extern CDF_STATUS sme_mgmt_frm_ind(tHalHandle hHal, - tpSirSmeMgmtFrameInd pSmeMgmtFrm); extern CDF_STATUS sme_remain_on_chn_ready(tHalHandle hHal, uint8_t *pMsg); extern CDF_STATUS sme_send_action_cnf(tHalHandle hHal, uint8_t *pMsg); @@ -2350,15 +2348,6 @@ CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) pMsg->type); } break; - case eWNI_SME_MGMT_FRM_IND: - if (pMsg->bodyptr) { - sme_mgmt_frm_ind(pMac, pMsg->bodyptr); - cdf_mem_free(pMsg->bodyptr); - } else { - sms_log(pMac, LOGE, FL("Empty message for %d"), - pMsg->type); - } - break; case eWNI_SME_ACTION_FRAME_SEND_CNF: if (pMsg->bodyptr) { status = sme_send_action_cnf(pMac, pMsg->bodyptr); @@ -6128,6 +6117,48 @@ CDF_STATUS sme_get_operation_channel(tHalHandle hHal, uint32_t *pChannel, return CDF_STATUS_E_FAILURE; } /* sme_get_operation_channel ends here */ +/** + * 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. + */ +CDF_STATUS 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; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + sms_log(mac_ctx, LOG1, FL(": ENTER")); + + if (CDF_STATUS_SUCCESS == + sme_acquire_global_lock(&mac_ctx->sme)) { + msg = cdf_mem_malloc(sizeof(*msg)); + if (NULL == msg) { + sms_log(mac_ctx, LOGE, + FL("Not able to allocate memory for eWNI_SME_REGISTER_MGMT_FRAME_CB")); + sme_release_global_lock(&mac_ctx->sme); + return CDF_STATUS_E_NOMEM; + } + cdf_mem_set(msg, sizeof(*msg), 0); + msg->message_type = eWNI_SME_REGISTER_MGMT_FRAME_CB; + msg->length = sizeof(*msg); + + msg->callback = callback; + status = cds_send_mb_message_to_mac(msg); + sme_release_global_lock(&mac_ctx->sme); + return status; + } + return CDF_STATUS_E_FAILURE; +} + /* --------------------------------------------------------------------------- \fn sme_RegisterMgtFrame diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 527c4d4090f7..e78d8b518ddc 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -203,7 +203,6 @@ const char *get_e_roam_cmd_status_str(eRoamCmdStatus val) CASE_RETURN_STR(eCSR_ROAM_FT_RESPONSE); #endif CASE_RETURN_STR(eCSR_ROAM_FT_START); - CASE_RETURN_STR(eCSR_ROAM_INDICATE_MGMT_FRAME); CASE_RETURN_STR(eCSR_ROAM_REMAIN_CHAN_READY); CASE_RETURN_STR(eCSR_ROAM_SEND_ACTION_CNF); CASE_RETURN_STR(eCSR_ROAM_SESSION_OPENED); diff --git a/core/sme/src/p2p/p2p_api.c b/core/sme/src/p2p/p2p_api.c index 36c17d435651..118f78ad3159 100644 --- a/core/sme/src/p2p/p2p_api.c +++ b/core/sme/src/p2p/p2p_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -139,46 +139,6 @@ CDF_STATUS sme_remain_on_chn_rsp(tpAniSirGlobal pMac, uint8_t *pMsg) return status; } -/*------------------------------------------------------------------ - * - * Handle the Mgmt frm ind from LIM and forward to HDD. - * - *------------------------------------------------------------------*/ - -CDF_STATUS sme_mgmt_frm_ind(tHalHandle hHal, tpSirSmeMgmtFrameInd pSmeMgmtFrm) -{ - tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - CDF_STATUS status = CDF_STATUS_SUCCESS; - tCsrRoamInfo pRoamInfo = { 0 }; - uint8_t i = 0; - uint32_t SessionId = pSmeMgmtFrm->sessionId; - - pRoamInfo.nFrameLength = - pSmeMgmtFrm->mesgLen - sizeof(tSirSmeMgmtFrameInd); - pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; - pRoamInfo.frameType = pSmeMgmtFrm->frameType; - pRoamInfo.rxChan = pSmeMgmtFrm->rxChan; - pRoamInfo.rxRssi = pSmeMgmtFrm->rxRssi; - if (CSR_IS_SESSION_ANY(SessionId)) { - for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { - if (CSR_IS_SESSION_VALID(pMac, i)) { - SessionId = i; - break; - } - } - } - - if (i == CSR_ROAM_SESSION_MAX) { - sms_log(pMac, LOGE, FL("No valid sessions found.")); - return CDF_STATUS_E_FAILURE; - } - /* forward the mgmt frame to HDD */ - csr_roam_call_callback(pMac, SessionId, &pRoamInfo, 0, - eCSR_ROAM_INDICATE_MGMT_FRAME, 0); - - return status; -} - /*------------------------------------------------------------------ * * Handle the remain on channel ready indication from PE -- cgit v1.2.3 From c830f14aa2efb39953209cb8e6341af765ca8a3e Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 7 Jan 2016 18:07:06 +0530 Subject: qcacld-3.0: Abort previous connect if fresh connect is received qcacld-2.0 to qcacld-3.0 propagation If connect is received with previous connect in progress, driver doesn't abort the previous connect and process the new connect. In csr if new connect is for same profile, sme directly indicate connection success to hdd and thus hdd increment the active session count twice for both connect. Now if one more connect is received it will try to disconnect the previous connection and decrements the active session count. So the count is 1 though no session is active. Eventually if same scenario happens again the active session count will become 2 with no active session. As max active session limit is 2, no more connect is accepted. To avoid this, if fresh connect is received and previous connect is in progress abort the previous connect. CRs-Fixed: 958963 Change-Id: I1544bc6e7894ffeda1956a19a553b6fe4e35f988 --- core/hdd/src/wlan_hdd_cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e80b293541fa..20f73e649a5a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8747,8 +8747,9 @@ static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter) hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType); if ((eMib_dot11DesiredBssType_independent == connectedBssType) || - (eConnectionState_Associated == pHddStaCtx->conn_info.connState) || - (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) { + (eConnectionState_Associated == pHddStaCtx->conn_info.connState) || + (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) || + (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) { hdd_conn_set_connection_state(pAdapter, eConnectionState_Disconnecting); /* Issue disconnect to CSR */ -- cgit v1.2.3 From 8a32473952e684f624b4e1622b38429354e07c92 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Wed, 30 Dec 2015 17:31:21 +0530 Subject: qcacld-3.0: Remove roam cmd from sme active list in case of failure qcacld-2.0 to qcacld-3.0 propagation -In case CSR is already connected and it receives connect with the same profile, csr will silently return and try to send the connect success to HDD. But if roamInfo staId is 0 this roam command is not removed from sme active list and leads to active list timeout. This back to back connect to CSR can happen if HDD and CSR go out of sync and is taken care already. -Also if disconnect is received in case scan for ssid is in progress it will be dropped and roam session state is set to disconnecting. But this roam session state is not reset for the fresh connection and thus if next connect also issue scan for ssid the connect command will be dropped assuming disconnect is in progress. This change removes roam cmd from sme active list in case of above failure and resets roam session state for fresh connections. Also does some cleanup in HDD disconnect command. Change-Id: I222626f1da6bdad83a5264668dde9aafd3dda149 CRs-Fixed: 953196 --- core/hdd/src/wlan_hdd_cfg80211.c | 8 ++++++-- core/sme/src/csr/csr_api_roam.c | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 20f73e649a5a..14588985eff6 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8949,10 +8949,15 @@ int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) status = sme_roam_disconnect(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 (CDF_STATUS_CMD_NOT_QUEUED == status) { hddLog(LOG1, FL("status = %d, already disconnected"), (int)status); - goto disconnected; } else if (0 != status) { hddLog(LOGE, FL("csr_roam_disconnect failure, returned %d"), @@ -9130,7 +9135,6 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy, hddLog(LOG1, FL("convert to internal reason %d to reasonCode %d"), reason, reasonCode); - pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; pScanInfo = &pAdapter->scan_info; if (pScanInfo->mScanPending) { hddLog(LOG1, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b7a9aefb3711..b5af6635e9bc 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6644,10 +6644,9 @@ static bool csr_roam_process_results(tpAniSirGlobal mac_ctx, tSmeCmd *cmd, roam_info.pbFrames = session->connectedInfo.pbFrames; roam_info.staId = session->connectedInfo.staId; roam_info.u.pConnectedProfile = &session->connectedProfile; - if (0 == roam_info.staId) { + if (0 == roam_info.staId) CDF_ASSERT(0); - return false; - } + session->bRefAssocStartCnt--; csr_roam_call_callback(mac_ctx, session_id, &roam_info, cmd->u.roamCmd.roamId, @@ -7196,6 +7195,19 @@ CDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId, &pSession->connectedProfile.SSID, &pProfile->SSIDs)) csr_roam_issue_disassociate_cmd(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; #ifdef FEATURE_WLAN_BTAMP_UT_RF pSession->maxRetryCount = CSR_JOIN_MAX_RETRY_COUNT; #endif -- cgit v1.2.3 From 926baab580a8f29187b7dd15c37df97abd6e0459 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Wed, 6 Jan 2016 18:11:55 -0800 Subject: qcacld-3.0: Fix compilation issues on MSM8998 RUMI platform Fix compilation issues on MSM8998 RUMI platform caused by CONFIG_CNSS not being defined and un-initialized local variable usage. Change-Id: Iaf8bec493a42ec9fd09e1b2b6aa085be8de4bc8a CRs-Fixed: 959249 --- core/cdf/src/cdf_memory.c | 6 ++---- core/hdd/src/wlan_hdd_ipa.c | 48 +++++++++++++++++++++++++++++++++++++++++++-- core/htc/htc_send.c | 4 ++-- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c index 197de54069dc..f32c56620f7f 100644 --- a/core/cdf/src/cdf_memory.c +++ b/core/cdf/src/cdf_memory.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -338,9 +338,6 @@ void cdf_mem_free(void *ptr) void *cdf_mem_malloc(size_t size) { int flags = GFP_KERNEL; -#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC - void *pmem; -#endif void *memPtr = NULL; unsigned long time_before_kzalloc; @@ -353,6 +350,7 @@ void *cdf_mem_malloc(size_t size) #if defined(CONFIG_CNSS) && defined(CONFIG_WCNSS_MEM_PRE_ALLOC) if (size > WCNSS_PRE_ALLOC_GET_THRESHOLD) { + void *pmem; pmem = wcnss_prealloc_get(size); if (NULL != pmem) { memset(pmem, 0, size); diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 38ac21d3bfea..5d6cb265c65c 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1725,6 +1725,28 @@ end: cdf_mem_free(op_msg); } +/** + * hdd_ipa_init_uc_op_work - init ipa uc op work + * @work: struct work_struct + * @work_handler: work_handler + * + * Return: none + */ +#ifdef CONFIG_CNSS +static void hdd_ipa_init_uc_op_work(struct work_struct *work, + work_func_t work_handler) +{ + cnss_init_work(work, work_handler); +} +#else +static void hdd_ipa_init_uc_op_work(struct work_struct *work, + work_func_t work_handler) +{ + INIT_WORK(work, work_handler); +} +#endif + + /** * hdd_ipa_uc_ol_init() - Initialize IPA uC offload * @hdd_ctx: Global HDD context @@ -1828,7 +1850,7 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) 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_init_uc_op_work(&ipa_ctxt->uc_op_work[i].work, hdd_ipa_uc_fw_op_event_handler); ipa_ctxt->uc_op_work[i].msg = NULL; } @@ -2305,6 +2327,27 @@ int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets, return 0; } +/** + * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work + * @work: struct work_struct + * @work_handler: work_handler + * + * Return: none + */ +#ifdef CONFIG_CNSS +static void hdd_ipa_init_uc_rm_work(struct work_struct *work, + work_func_t work_handler) +{ + cnss_init_work(work, work_handler); +} +#else +static void hdd_ipa_init_uc_rm_work(struct work_struct *work, + work_func_t work_handler) +{ + INIT_WORK(work, work_handler); +} +#endif + /** * hdd_ipa_setup_rm() - Setup IPA resource management * @hdd_ipa: Global HDD IPA context @@ -2319,7 +2362,8 @@ static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa) if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx)) return 0; - cnss_init_work(&hdd_ipa->uc_rm_work.work, hdd_ipa_uc_rm_notify_defer); + hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work, + hdd_ipa_uc_rm_notify_defer); memset(&create_params, 0, sizeof(create_params)); create_params.name = IPA_RM_RESOURCE_WLAN_PROD; create_params.reg_params.user_data = hdd_ipa; diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index cb3c57d642f8..2f2925cf624f 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1313,7 +1313,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, HTC_ENDPOINT *pEndpoint; HTC_FRAME_HDR *pHtcHdr; HTC_PACKET_QUEUE sendQueue; - cdf_nbuf_t netbuf; + cdf_nbuf_t netbuf = NULL; int tx_resources; A_STATUS status = A_OK; uint32_t data_attr = 0; -- cgit v1.2.3 From 67e0fcac5e2343a08deae4042f985348eeff63ad Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Wed, 13 Jan 2016 18:32:40 -0800 Subject: qcacld-3.0: Enable 11 AC TX compact feature for adrastea Enable 11 AC TX compact feature for adrastea core to achieve better TX throughput numbers Change-Id: I4e66328e01a348ccf0e5519a62181e2aeeaa40fe CRs-Fixed: 962336 --- Kbuild | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Kbuild b/Kbuild index 5e35ebc01f50..09dc487eb170 100644 --- a/Kbuild +++ b/Kbuild @@ -1282,6 +1282,11 @@ ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) CDEFINES += -DCONFIG_ATH_PROCFS_DIAG_SUPPORT endif +# Enable 11AC TX compact feature for adrastea +ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) +CDEFINES += -DATH_11AC_TXCOMPACT +endif + # NOTE: CONFIG_64BIT_PADDR requires CONFIG_HELIUMPLUS ifeq (y,$(filter y,$(CONFIG_CNSS_EOS) $(CONFIG_ICNSS))) CONFIG_HELIUMPLUS := y -- cgit v1.2.3 From 040ffc4704f6826642fb97f8c062aa588ff767b2 Mon Sep 17 00:00:00 2001 From: Hanumantha Reddy Pothula Date: Tue, 12 Jan 2016 11:16:06 +0530 Subject: qcacld-3.0: Process SIR_LIM_ADDTS_RSP_TIMEOUT command in defer state qcacld-2.0 to qcacld-3.0 propagation If ADDTS response timer is fired because of not receiving ADDTS RSP within time then this timer handler posts SIR_LIM_ADDTS_RSP_TIMEOUT command to LIM. But if deferring is enabled(say due to processing any action frame) then SIR_LIM_ADDTS_RSP_TIMEOUT command will be added to defer queue and as gLimAddtsSent is set to TRUE, including this command all other defer commands will never be processed. This may lead to active command timeout. Hence process SIR_LIM_ADDTS_RSP_TIMEOUT command in defer state. Change-Id: I48f09a7fd560702ac7701e0a1a41c77ad94626d4 CRs-Fixed: 919490 --- core/mac/src/pe/lim/lim_process_message_queue.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index d6e314e7d962..aa73bca79dfa 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -288,6 +288,19 @@ uint8_t static def_msg_decision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) (limMsg->type != WMA_START_OEM_DATA_RSP) && #endif (limMsg->type != WMA_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 -- cgit v1.2.3 From 1d1d3eb7806d88c839f0bc918a36c82b3570b4c4 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 11:26:40 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirTdlsSendMgmtReq Replace tSirMacAddr with struct cdf_mac_addr in tSirTdlsSendMgmtReq. Change-Id: I0f545721d184c17b2d150df5435d51cd6ca7bf9e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +-- core/mac/src/pe/lim/lim_process_tdls.c | 88 ++++++++++++++++++---------------- core/mac/src/pe/lim/lim_types.h | 5 -- core/sme/src/csr/csr_tdls_process.c | 8 ++-- 4 files changed, 54 insertions(+), 53 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 041a17b1aabe..940c27285e34 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3338,9 +3338,9 @@ typedef struct sSirTdlsSendMgmtReq { uint8_t responder; uint32_t peerCapability; /* For multi-session, for PE to locate peSession ID */ - tSirMacAddr bssid; - tSirMacAddr peerMac; - /* Variable lenght. Dont add any field after this. */ + struct cdf_mac_addr bssid; + struct cdf_mac_addr peer_mac; + /* Variable length. Dont add any field after this. */ uint8_t addIe[1]; } tSirTdlsSendMgmtReq, *tpSirSmeTdlsSendMgmtReq; diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 0b49077eea2c..7cb5eb1d8bb2 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -92,7 +92,7 @@ static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac, tSirTdlsAddStaReq * pAddStaReq, tpPESession psessionEntry); void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry, tDot11fIELinkIdentifier *linkIden, - tSirMacAddr peerMac, uint8_t reqType); + struct cdf_mac_addr peer_mac, uint8_t reqType); void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac, tpPESession psessionEntry, tDot11fIEExtCap *extCapability); @@ -343,8 +343,10 @@ CDF_STATUS lim_mgmt_tx_complete(tpAniSirGlobal pMac, uint32_t txCompleteSuccess) * 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 lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, - uint8_t dialog, tpPESession psessionEntry) +tSirRetStatus lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, + struct cdf_mac_addr peer_mac, + uint8_t dialog, + tpPESession psessionEntry) { tDot11fTDLSDisReq tdlsDisReq; uint32_t status = 0; @@ -504,7 +506,7 @@ tSirRetStatus lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, tSirMacAddr peer_ FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), SIR_MAC_TDLS_DIS_REQ, lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_REQ), - MAC_ADDR_ARRAY(peer_mac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, @@ -591,9 +593,11 @@ static void populate_dot11f_tdls_ht_vht_cap(tpAniSirGlobal pMac, */ static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, uint8_t dialog, + struct cdf_mac_addr peer_mac, + uint8_t dialog, tpPESession psessionEntry, - uint8_t *addIe, uint16_t addIeLen) + uint8_t *addIe, + uint16_t addIeLen) { tDot11fTDLSDisRsp tdlsDisRsp; uint16_t caps = 0; @@ -633,7 +637,7 @@ static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, populate_dot11f_link_iden(pMac, psessionEntry, &tdlsDisRsp.LinkIdentifier, - peerMac, TDLS_RESPONDER); + peer_mac, TDLS_RESPONDER); if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { @@ -735,7 +739,7 @@ static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, /* Make public Action Frame */ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, - SIR_MAC_MGMT_ACTION, peerMac, + SIR_MAC_MGMT_ACTION, peer_mac.bytes, psessionEntry->selfMacAddr); { @@ -775,7 +779,7 @@ static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, FL("[TDLS] action %d (%s) -DIRECT-> OTA peer="MAC_ADDRESS_STR), SIR_MAC_TDLS_DIS_RSP, lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_RSP), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; /* @@ -810,7 +814,8 @@ static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac, * lim_send_tdls_setup_rsp_frame to populate the AID if device is 11ac capable. */ static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mode, - tSirMacAddr peerMac, tDot11fIEAID *Aid, + struct cdf_mac_addr peerMac, + tDot11fIEAID *Aid, tpPESession psessionEntry) { if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) && @@ -823,7 +828,7 @@ static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mo tpDphHashNode pStaDs; pStaDs = - dph_lookup_hash_entry(pMac, peerMac, &aid, + dph_lookup_hash_entry(pMac, peerMac.bytes, &aid, &psessionEntry->dph. dphHashTable); if (NULL != pStaDs) { @@ -834,7 +839,7 @@ static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mo lim_log(pMac, LOGE, FL("pStaDs is NULL for " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peerMac.bytes)); } } } else { @@ -848,9 +853,11 @@ static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mo */ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, uint8_t dialog, + struct cdf_mac_addr peer_mac, + uint8_t dialog, tpPESession psessionEntry, - uint8_t *addIe, uint16_t addIeLen) + uint8_t *addIe, + uint16_t addIeLen) { tDot11fTDLSSetupReq tdlsSetupReq; uint16_t caps = 0; @@ -882,7 +889,7 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, tdlsSetupReq.DialogToken.token = dialog; populate_dot11f_link_iden(pMac, psessionEntry, - &tdlsSetupReq.LinkIdentifier, peerMac, + &tdlsSetupReq.LinkIdentifier, peer_mac, TDLS_INITIATOR); if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { @@ -975,7 +982,7 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, &tdlsSetupReq.VHTCaps, psessionEntry); /* Populate AID */ - populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac, + populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peer_mac, &tdlsSetupReq.AID, psessionEntry); /* Populate TDLS offchannel param only if offchannel is enabled @@ -1099,7 +1106,7 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), SIR_MAC_TDLS_SETUP_REQ, lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_REQ), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1128,7 +1135,8 @@ tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac, */ tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, uint16_t reason, + struct cdf_mac_addr peer_mac, + uint16_t reason, uint8_t responder, tpPESession psessionEntry, uint8_t *addIe, uint16_t addIeLen) @@ -1162,7 +1170,7 @@ tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, teardown.Reason.code = reason; populate_dot11f_link_iden(pMac, psessionEntry, &teardown.LinkIdentifier, - peerMac, + peer_mac, (responder == true) ? TDLS_RESPONDER : TDLS_INITIATOR); @@ -1300,7 +1308,7 @@ tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, lim_trace_tdls_action_string(SIR_MAC_TDLS_TEARDOWN), ((reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? "AP" : "DIRECT"), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1321,14 +1329,13 @@ tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, } return eSIR_SUCCESS; - } /* * Send Setup RSP frame on AP link. */ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, + struct cdf_mac_addr peer_mac, uint8_t dialog, tpPESession psessionEntry, etdlsLinkSetupStatus setupStatus, @@ -1373,7 +1380,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, tdlsSetupRsp.DialogToken.token = dialog; populate_dot11f_link_iden(pMac, psessionEntry, - &tdlsSetupRsp.LinkIdentifier, peerMac, + &tdlsSetupRsp.LinkIdentifier, peer_mac, TDLS_RESPONDER); if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) { @@ -1456,7 +1463,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, &tdlsSetupRsp.VHTCaps, psessionEntry); /* Populate AID */ - populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac, + populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peer_mac, &tdlsSetupRsp.AID, psessionEntry); /* Populate TDLS offchannel param only if offchannel is enabled @@ -1579,7 +1586,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), SIR_MAC_TDLS_SETUP_RSP, lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_RSP), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1600,7 +1607,6 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, } return eSIR_SUCCESS; - } /* @@ -1608,7 +1614,7 @@ static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac, */ tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, + struct cdf_mac_addr peer_mac, uint8_t dialog, uint32_t peerCapability, tpPESession psessionEntry, @@ -1644,7 +1650,7 @@ tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac, tdlsSetupCnf.DialogToken.token = dialog; populate_dot11f_link_iden(pMac, psessionEntry, - &tdlsSetupCnf.LinkIdentifier, peerMac, + &tdlsSetupCnf.LinkIdentifier, peer_mac, TDLS_INITIATOR); /* * TODO: we need to see if we have to support conditions where we have @@ -1800,7 +1806,7 @@ tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac, FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR), SIR_MAC_TDLS_SETUP_CNF, lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_CNF), - MAC_ADDR_ARRAY(peerMac)); + MAC_ADDR_ARRAY(peer_mac.bytes)); pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -2662,7 +2668,7 @@ void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac, void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry, tDot11fIELinkIdentifier *linkIden, - tSirMacAddr peerMac, uint8_t reqType) + struct cdf_mac_addr peer_mac, uint8_t reqType) { uint8_t *initStaAddr = NULL; uint8_t *respStaAddr = NULL; @@ -2672,13 +2678,13 @@ void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry, : ((respStaAddr = linkIden->InitStaAddr), (initStaAddr = linkIden->RespStaAddr)); cdf_mem_copy((uint8_t *) linkIden->bssid, - (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); + (uint8_t *) psessionEntry->bssId, CDF_MAC_ADDR_SIZE); cdf_mem_copy((uint8_t *) initStaAddr, - psessionEntry->selfMacAddr, sizeof(tSirMacAddr)); + psessionEntry->selfMacAddr, CDF_MAC_ADDR_SIZE); - cdf_mem_copy((uint8_t *) respStaAddr, (uint8_t *) peerMac, - sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) respStaAddr, (uint8_t *) peer_mac.bytes, + CDF_MAC_ADDR_SIZE); linkIden->present = 1; return; @@ -2738,7 +2744,7 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, lim_log(mac_ctx, LOG1, FL("Send Mgmt Recieved")); session_entry = pe_find_session_by_bssid(mac_ctx, - send_req->bssid, &session_id); + send_req->bssid.bytes, &session_id); if (NULL == session_entry) { lim_log(mac_ctx, LOGE, FL("PE Session does not exist for given sme session_id %d"), @@ -2770,14 +2776,14 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, case SIR_MAC_TDLS_DIS_REQ: lim_log(mac_ctx, LOG1, FL("Transmit Discovery Request Frame")); /* format TDLS discovery request frame and transmit it */ - lim_send_tdls_dis_req_frame(mac_ctx, send_req->peerMac, + lim_send_tdls_dis_req_frame(mac_ctx, send_req->peer_mac, send_req->dialog, session_entry); result_code = eSIR_SME_SUCCESS; break; case SIR_MAC_TDLS_DIS_RSP: lim_log(mac_ctx, LOG1, FL("Transmit Discovery Response Frame")); /* Send a response mgmt action frame */ - lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peerMac, + lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peer_mac, send_req->dialog, session_entry, &send_req->addIe[0], (send_req->length - sizeof(tSirTdlsSendMgmtReq))); result_code = eSIR_SME_SUCCESS; @@ -2785,7 +2791,7 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, case SIR_MAC_TDLS_SETUP_REQ: lim_log(mac_ctx, LOG1, FL("Transmit Setup Request Frame")); lim_send_tdls_link_setup_req_frame(mac_ctx, - send_req->peerMac, send_req->dialog, session_entry, + send_req->peer_mac, send_req->dialog, session_entry, &send_req->addIe[0], (send_req->length - sizeof(tSirTdlsSendMgmtReq))); result_code = eSIR_SME_SUCCESS; @@ -2793,7 +2799,7 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, case SIR_MAC_TDLS_SETUP_RSP: lim_log(mac_ctx, LOG1, FL("Transmit Setup Response Frame")); lim_send_tdls_setup_rsp_frame(mac_ctx, - send_req->peerMac, send_req->dialog, session_entry, + send_req->peer_mac, send_req->dialog, session_entry, send_req->statusCode, &send_req->addIe[0], (send_req->length - sizeof(tSirTdlsSendMgmtReq))); result_code = eSIR_SME_SUCCESS; @@ -2801,7 +2807,7 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, case SIR_MAC_TDLS_SETUP_CNF: lim_log(mac_ctx, LOG1, FL("Transmit Setup Confirm Frame")); lim_send_tdls_link_setup_cnf_frame(mac_ctx, - send_req->peerMac, send_req->dialog, + send_req->peer_mac, send_req->dialog, send_req->peerCapability, session_entry, &send_req->addIe[0], (send_req->length - sizeof(tSirTdlsSendMgmtReq))); @@ -2810,7 +2816,7 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, case SIR_MAC_TDLS_TEARDOWN: lim_log(mac_ctx, LOG1, FL("Transmit Teardown Frame")); lim_send_tdls_teardown_frame(mac_ctx, - send_req->peerMac, send_req->statusCode, + send_req->peer_mac, send_req->statusCode, send_req->responder, session_entry, &send_req->addIe[0], (send_req->length - sizeof(tSirTdlsSendMgmtReq))); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index d10bcccb88d2..99ff48599312 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -539,11 +539,6 @@ void lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac, tpPESession psessionEn tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, tpPESession session_entry); CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession); -tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac, - tSirMacAddr peerMac, uint16_t reason, - uint8_t responder, - tpPESession psessionEntry, - uint8_t *addIe, uint16_t addIeLen); #else static inline tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, tpPESession session_entry) diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index 802f7cb6e00e..e800fad1c037 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -411,11 +411,11 @@ CDF_STATUS csr_tdls_process_send_mgmt(tpAniSirGlobal pMac, tSmeCmd *cmd) tdlsSendMgmtReq->responder = tdlsSendMgmtCmdInfo->responder; tdlsSendMgmtReq->peerCapability = tdlsSendMgmtCmdInfo->peerCapability; - cdf_mem_copy(tdlsSendMgmtReq->bssid, - pSession->pConnectBssDesc->bssId, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsSendMgmtReq->bssid.bytes, + pSession->pConnectBssDesc->bssId, CDF_MAC_ADDR_SIZE); - cdf_mem_copy(tdlsSendMgmtReq->peerMac, - tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr)); + cdf_mem_copy(tdlsSendMgmtReq->peer_mac.bytes, + tdlsSendMgmtCmdInfo->peerMac, CDF_MAC_ADDR_SIZE); if (tdlsSendMgmtCmdInfo->len && tdlsSendMgmtCmdInfo->buf) { cdf_mem_copy(tdlsSendMgmtReq->addIe, tdlsSendMgmtCmdInfo->buf, -- cgit v1.2.3 From c6c40bade2742aec8b496f9819a16593fbb378e7 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 24 Nov 2015 12:48:46 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirNsOffloadReq Replace tSirMacAddr with cdf_mac_addr in tSirNsOffloadReq. Change-Id: Ic53f963b3df46d67bf5f202ac6aaf7c49ab858a9 CRs-Fixed: 898864 --- core/hdd/src/wlan_hdd_power.c | 5 ++--- core/mac/inc/sir_api.h | 2 +- core/wma/src/wma_features.c | 7 ++++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 79054dc479e2..cf4944e93824 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -387,9 +387,8 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable) } offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; - cdf_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr, - &pAdapter->macAddressCurrent.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&offLoadRequest.nsOffloadInfo.self_macaddr, + &pAdapter->macAddressCurrent); /* set number of ns offload address count */ offLoadRequest.num_ns_offload_count = count; /* Configure the Firmware with this */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 940c27285e34..149f36116f4a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2540,7 +2540,7 @@ typedef struct sSirNsOffloadReq { uint8_t srcIPv6Addr[SIR_MAC_IPV6_ADDR_LEN]; uint8_t selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; uint8_t targetIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN]; - tSirMacAddr selfMacAddr; + struct cdf_mac_addr self_macaddr; uint8_t srcIPv6AddrValid; uint8_t targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; uint8_t slotIdx; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 00259865229c..42f86d0a21ec 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5185,8 +5185,8 @@ CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, * local MAC address rather than the tuple */ WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams-> - nsOffloadInfo.selfMacAddr, - &ns_tuple->target_mac); + nsOffloadInfo.self_macaddr.bytes, + &ns_tuple->target_mac); #endif /* WLAN_NS_OFFLOAD */ if ((ns_tuple->target_mac.mac_addr31to0 != 0) || (ns_tuple->target_mac.mac_addr47to32 != 0)) { @@ -5250,7 +5250,8 @@ CDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, /* 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, + WMI_CHAR_ARRAY_TO_MAC_ADDR( + pHostOffloadParams->nsOffloadInfo.self_macaddr.bytes, &ns_tuple->target_mac); #endif if ((ns_tuple->target_mac.mac_addr31to0 != 0) || -- cgit v1.2.3 From 8371edfe04132c8775da2e2af01bf855b92d5709 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Fri, 8 Jan 2016 09:57:17 -0800 Subject: qcacld-3.0: clean up hddLog API in wlan_hdd_green_ap.c Clean up wlan_hdd_green_ap.c to use the unified hdd logging APIs. Change-Id: If444137793895dea9b0e0ed894f238ac00363f2d CRs-fixed: 959696 --- core/hdd/src/wlan_hdd_green_ap.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/core/hdd/src/wlan_hdd_green_ap.c b/core/hdd/src/wlan_hdd_green_ap.c index ac61e1898893..fed68aa1ae29 100644 --- a/core/hdd/src/wlan_hdd_green_ap.c +++ b/core/hdd/src/wlan_hdd_green_ap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -414,12 +414,9 @@ void hdd_wlan_green_ap_start_bss(struct hdd_context_s *hdd_ctx) */ if (hdd_ctx->green_ap_ctx->egap_support && cfg->enable_egap && cfg->egap_feature_flag) { - hddLog(LOG1, - FL("Set EGAP - enabled: %d, flag: %x, inact_time: %d, wait_time: %d"), - cfg->enable_egap, - cfg->egap_feature_flag, - cfg->egap_inact_time, - cfg->egap_wait_time); + hdd_notice("Set EGAP - enabled: %d, flag: %x, inact_time: %d, wait_time: %d", + cfg->enable_egap, cfg->egap_feature_flag, + cfg->egap_inact_time, cfg->egap_wait_time); if (!sme_send_egap_conf_params(cfg->enable_egap, cfg->egap_inact_time, cfg->egap_wait_time, -- cgit v1.2.3 From 896ca1dea9ea701f0e4063dc64c8c65c80bc028f Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Thu, 7 Jan 2016 15:07:12 -0800 Subject: qcacld-3.0: cleanup cds_concurrency files Code cleanup & update of correct copyright information. Change-Id: Icee77761cf00cee3b633bd260d5af38286a4f22c CRs-fixed: 956394 --- core/cds/inc/cds_concurrency.h | 2 +- core/cds/src/cds_concurrency.c | 14 +++++--------- core/hdd/src/wlan_hdd_assoc.c | 7 ++----- core/hdd/src/wlan_hdd_cfg80211.c | 3 +-- core/hdd/src/wlan_hdd_hostapd.c | 9 +++------ core/hdd/src/wlan_hdd_main.c | 6 ++---- core/hdd/src/wlan_hdd_wext.c | 7 ++----- 7 files changed, 16 insertions(+), 32 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index eead3b645b0b..f7e37d5e8afc 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index db5eb6cf8ee7..4a67e941fa58 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2329,8 +2329,7 @@ void cds_set_dual_mac_scan_config(uint8_t dbs_val, * * Return: None */ -void cds_set_dual_mac_fw_mode_config(uint8_t dbs, - uint8_t dfs) +void cds_set_dual_mac_fw_mode_config(uint8_t dbs, uint8_t dfs) { struct sir_dual_mac_config cfg; CDF_STATUS status; @@ -3646,8 +3645,7 @@ static void cds_set_pcl_for_existing_combo(enum cds_con_mode mode) return; }; - if (cds_mode_specific_connection_count( - mode, NULL) > 0) { + if (cds_mode_specific_connection_count(mode, NULL) > 0) { /* Check, store and temp delete the mode's parameter */ cds_store_and_del_conn_info(mode, &info); /* Set the PCL to the FW since connection got updated */ @@ -4910,8 +4908,7 @@ bool cds_allow_concurrency(enum cds_con_mode mode, goto done; } } - count = cds_mode_specific_connection_count( - CDS_STA_MODE, list); + count = cds_mode_specific_connection_count(CDS_STA_MODE, list); if ((CDS_STA_MODE == mode) && (cds_mode_specific_connection_count( CDS_IBSS_MODE, list)) && count) { @@ -4921,8 +4918,7 @@ bool cds_allow_concurrency(enum cds_con_mode mode, } if ((CDS_STA_MODE == mode) && - (cds_mode_specific_connection_count( - CDS_IBSS_MODE, list))) { + (cds_mode_specific_connection_count(CDS_IBSS_MODE, list))) { if (wma_is_hw_dbs_capable() == true) { if (num_connections > 1) { /* err msg */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 12addc14c9b7..6d124107945e 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1415,9 +1415,7 @@ static void hdd_send_re_assoc_event(struct net_device *dev, * active session count should still be the same and hence upon * successful reassoc decrement the active session count here. */ - cds_decr_session_set_pcl( - pAdapter->device_mode, - pAdapter->sessionId); + cds_decr_session_set_pcl(pAdapter->device_mode, pAdapter->sessionId); /* Send the Assoc Resp, the supplicant needs this for initial Auth */ len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; @@ -1847,8 +1845,7 @@ defined(FEATURE_WLAN_LFR) wlan_hdd_auto_shutdown_enable(pHddCtx, false); #endif - cds_check_concurrent_intf_and_restart_sap( - pHddStaCtx, + cds_check_concurrent_intf_and_restart_sap(pHddStaCtx, pAdapter); #ifdef FEATURE_WLAN_TDLS diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 14588985eff6..a6737ff9d503 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8006,8 +8006,7 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, * check for other concurrency rules. */ if (!pHddCtx->config->policy_manager_enabled) { - cds_handle_conc_rule1(pAdapter, - pRoamProfile); + cds_handle_conc_rule1(pAdapter, pRoamProfile); if (true != cds_handle_conc_rule2( pAdapter, pRoamProfile, &roamId)) return 0; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index c5ee4d860821..ba98484d1f91 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -556,8 +556,7 @@ static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter, hddLog(LOGE, FL("Deleting SAP/P2P link!!!!!!")); clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); - cds_decr_session_set_pcl( - pHostapdAdapter->device_mode, + cds_decr_session_set_pcl(pHostapdAdapter->device_mode, pHostapdAdapter->sessionId); } EXIT(); @@ -4965,8 +4964,7 @@ __iw_softap_stopbss(struct net_device *dev, } } clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); - cds_decr_session_set_pcl( - pHostapdAdapter->device_mode, + cds_decr_session_set_pcl(pHostapdAdapter->device_mode, pHostapdAdapter->sessionId); } EXIT(); @@ -7872,8 +7870,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, } clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags); /*BSS stopped, clear the active sessions for this device mode*/ - cds_decr_session_set_pcl( - pAdapter->device_mode, + cds_decr_session_set_pcl(pAdapter->device_mode, pAdapter->sessionId); pAdapter->sessionCtx.ap.beacon = NULL; kfree(old); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 31d5a88cd335..3906b8a6a677 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2922,8 +2922,7 @@ CDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) adapter->sessionCtx.station.hdd_ReassocScenario = false; hdd_deinit_tx_rx(adapter); - cds_decr_session_set_pcl( - adapter->device_mode, + cds_decr_session_set_pcl(adapter->device_mode, adapter->sessionId); if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { hdd_wmm_adapter_close(adapter); @@ -6372,8 +6371,7 @@ void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) } } clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_decr_session_set_pcl( - ap_adapter->device_mode, + cds_decr_session_set_pcl(ap_adapter->device_mode, ap_adapter->sessionId); hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Stop Success")); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 29e5d087263b..73be0e6db036 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -6875,9 +6875,7 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, return -EPERM; } hdd_debug("%d %d %d", value[1], value[2], value[3]); - cds_set_dual_mac_scan_config( - value[1], value[2], - value[3]); + cds_set_dual_mac_scan_config(value[1], value[2], value[3]); break; default: hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); @@ -9513,8 +9511,7 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, return -EPERM; } hdd_debug("%d %d", value[1], value[2]); - cds_set_dual_mac_fw_mode_config( - value[1], value[2]); + cds_set_dual_mac_fw_mode_config(value[1], value[2]); break; case WE_DUMP_DP_TRACE_LEVEL: hdd_info("WE_DUMP_DP_TRACE_LEVEL: %d %d", -- cgit v1.2.3 From 58e12dc35ab0016bb78010a5532c38d24d4d56f4 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Mon, 12 Oct 2015 14:51:56 -0700 Subject: qcacld-3.0: Add config for the MCC restriction on Adrastea emulation On M2M emulation platform we have a fixed mapping between macs, hence vdev transition & MCC support is not possible on this platform. But MPR platform doesn't have these limitations. This config allows at runtime enable/disable vdev transition & MCC support depending on the platform it is running on. Change-Id: I17a92dce695ee30f7994f040d4bc612a38680f3e CRs-fixed: 922181 --- core/cds/src/cds_concurrency.c | 30 +++++++++++++++++++++++++----- core/hdd/inc/wlan_hdd_cfg.h | 17 +++++++++++++++++ core/hdd/src/wlan_hdd_cfg.c | 10 ++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 4a67e941fa58..b29c4918196e 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -3568,7 +3568,15 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) uint32_t conn_index; enum cds_conc_next_action upgrade = CDS_NOP; uint8_t mac = 0; +#ifdef QCA_WIFI_3_0_EMU + hdd_context_t *hdd_ctx; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return upgrade; + } +#endif if (wma_is_hw_dbs_capable() == false) { cds_err("driver isn't dbs capable, no further action needed"); return upgrade; @@ -3590,8 +3598,9 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) } } #ifdef QCA_WIFI_3_0_EMU - /* For emulation only: if we have a connection on 2.4, stay in DBS */ - if (CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) + /* For M2M emulation only: if we have a connection on 2.4, stay in DBS */ + if (hdd_ctx->config->enable_m2m_limitation && + CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) goto done; #endif /* Let's request for single MAC mode */ @@ -4683,6 +4692,15 @@ bool cds_disallow_mcc(uint8_t channel) bool cds_allow_new_home_channel(uint8_t channel, uint32_t num_connections) { bool status = true; +#ifdef QCA_WIFI_3_0_EMU + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return false; + } +#endif if ((num_connections == 2) && (conc_connection_list[0].chan != conc_connection_list[1].chan) @@ -4712,7 +4730,8 @@ bool cds_allow_new_home_channel(uint8_t channel, uint32_t num_connections) #ifndef QCA_WIFI_3_0_EMU } #else - } else if ((num_connections == 1) && + } else if (hdd_ctx->config->enable_m2m_limitation && + (num_connections == 1) && (conc_connection_list[0].chan != channel)) { if (((CDS_IS_CHANNEL_24GHZ(channel)) && (CDS_IS_CHANNEL_24GHZ @@ -5487,10 +5506,11 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, case 0: next_action = CDS_NOP; #ifdef QCA_WIFI_3_0_EMU - /* For emulation only: if it is a connection on 2.4, + /* For M2M emulation only: if it is a connection on 2.4, * request DBS */ - if (CDS_IS_CHANNEL_24GHZ(channel)) + if (hdd_ctx->config->enable_m2m_limitation && + CDS_IS_CHANNEL_24GHZ(channel)) next_action = CDS_DBS; #endif break; diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index beb482abdf5e..33c79eb54bdc 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -2861,6 +2861,20 @@ enum dot11p_mode { #define CFG_INFORM_BSS_RSSI_RAW_MAX (1) #define CFG_INFORM_BSS_RSSI_RAW_DEFAULT (1) +#ifdef QCA_WIFI_3_0_EMU +/* + * On M2M emulation platform we have a fixed mapping between macs, hence + * vdev transition & MCC support is not possible on this platform. But MPR + * platform doesn't have these limitations. This config allows at runtime + * enable/disable vdev transition & MCC support depending on the platform + * it is running on + */ +#define CFG_ENABLE_M2M_LIMITATION "gEnableM2MLimitation" +#define CFG_ENABLE_M2M_LIMITATION_MIN (0) +#define CFG_ENABLE_M2M_LIMITATION_MAX (1) +#define CFG_ENABLE_M2M_LIMITATION_DEFAULT (1) +#endif /* QCA_WIFI_3_0_EMU */ + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3448,6 +3462,9 @@ struct hdd_config { bool enable_lfr_subnet_detection; #endif uint8_t inform_bss_rssi_raw; +#ifdef QCA_WIFI_3_0_EMU + bool enable_m2m_limitation; +#endif }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 7c516c1bea5d..c60eb9b5a38e 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3666,6 +3666,16 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_INFORM_BSS_RSSI_RAW_DEFAULT, CFG_INFORM_BSS_RSSI_RAW_MIN, CFG_INFORM_BSS_RSSI_RAW_MAX), + +#ifdef QCA_WIFI_3_0_EMU + REG_VARIABLE(CFG_ENABLE_M2M_LIMITATION, WLAN_PARAM_Integer, + struct hdd_config, enable_m2m_limitation, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LFR_SUBNET_DEFAULT, + CFG_ENABLE_LFR_SUBNET_MIN, + CFG_ENABLE_LFR_SUBNET_MAX), +#endif + }; -- cgit v1.2.3 From 9c6b4e19085459fa4a3656e367da008e95f58c79 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 6 Oct 2015 12:01:08 -0700 Subject: qcacld-3.0: Define wma_is_vdev_in_beaconning_mode Define wma_is_vdev_in_beaconning_mode to remove in function ifdefs. Remove conditional compilation arround wma_is_vdev_in_ibss_mode calls. Change-Id: I4b047d05088b5cbe51fa49818634fdd3a78e6b68 CRs-Fixed: 935297 --- core/wma/inc/wma_internal.h | 30 +++++++++++++++++++++ core/wma/src/wma_dev_if.c | 65 ++++++++++++++++++++++++++------------------- core/wma/src/wma_features.c | 12 ++------- core/wma/src/wma_mgmt.c | 4 +-- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 59751de4214b..ab9ebf89722b 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -463,8 +463,38 @@ bool wma_is_vdev_in_ap_mode(tp_wma_handle wma, uint8_t vdev_id); #ifdef QCA_IBSS_SUPPORT bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, uint8_t vdev_id); +#else +/** + * wma_is_vdev_in_ibss_mode(): dummy function + * @wma: wma handle + * @vdev_id: vdev id + * + * Return false since no vdev can be in ibss mode without ibss support + */ +static inline +bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, uint8_t vdev_id); +{ + return false; +} #endif +/** + * wma_is_vdev_in_beaconning_mode() - check if vdev is in a beaconning mode + * @wma: wma handle + * @vdev_id: vdev id + * + * Helper function to know whether given vdev id + * is in a beaconning mode or not. + * + * Return: True if vdev needs to beacon. + */ +static inline +bool wma_is_vdev_in_beaconning_mode(tp_wma_handle wma, uint8_t vdev_id) +{ + return wma_is_vdev_in_ap_mode(wma, vdev_id) || + wma_is_vdev_in_ibss_mode(wma, vdev_id); +} + /** * wma_find_bssid_by_vdev_id() - Get the BSS ID corresponding to the vdev ID * @wma - wma handle diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 27993c16f62d..0fd66336c6ee 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -153,7 +153,6 @@ bool wma_is_vdev_in_ibss_mode(tp_wma_handle wma, uint8_t vdev_id) } #endif /* QCA_IBSS_SUPPORT */ - /** * wma_find_vdev_by_bssid() - Get the corresponding vdev_id from BSSID * @wma - wma handle @@ -1078,13 +1077,11 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid, 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 /* QCA_IBSS_SUPPORT */ wmi_unified_peer_delete_send(wma->wmi_handle, peer_addr, vdev_id); #undef PEER_ALL_TID_BITMASK @@ -1179,7 +1176,6 @@ CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, 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) && !cdf_mem_compare(peer_addr, vdev->mac_addr.raw, @@ -1196,7 +1192,6 @@ CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, wma_set_stakey(wma, &key_info); } -#endif /* QCA_IBSS_SUPPORT */ return CDF_STATUS_SUCCESS; err: @@ -1289,7 +1284,22 @@ static void wma_delete_all_ibss_peers(tp_wma_handle wma, A_UINT32 vdev_id) wma_remove_peer(wma, wma->interfaces[vdev_id].bssid, vdev_id, peer, false); } - +#else +/** + * wma_delete_all_ibss_peers(): dummy function for when ibss is not supported + * @wma: wma handle + * @vdev_id: vdev id + * + * This function send peer delete command to fw for all + * peers in peer_list and remove ref count for peer id + * peer will actually remove from list after receving + * unmap event from firmware. + * + * Return: none + */ +static void wma_delete_all_ibss_peers(tp_wma_handle wma, A_UINT32 vdev_id) +{ +} #endif /* QCA_IBSS_SUPPORT */ /** @@ -1405,6 +1415,20 @@ static void wma_recreate_ibss_vdev_and_bss_peer(tp_wma_handle wma, WMA_LOGA("IBSS BSS peer created with mac %pM", vdev->mac_addr.raw); } +#else +/** + * wma_recreate_ibss_vdev_and_bss_peer() - dummy function + * @wma: wma handle + * @vdev_id: vdev id + * + * Dummy for when IBSS not supported + * + * Return: none + */ +static void wma_recreate_ibss_vdev_and_bss_peer(tp_wma_handle wma, + uint8_t vdev_id) +{ +} #endif /* QCA_IBSS_SUPPORT */ /** @@ -1568,11 +1592,9 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, 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 /* QCA_IBSS_SUPPORT */ { if (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id)) { wma_delete_all_ap_remote_peers(wma, @@ -1619,12 +1641,12 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, cdf_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 /* QCA_IBSS_SUPPORT */ + /* 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 @@ -2472,11 +2494,9 @@ void wma_vdev_resp_timer(void *data) cdf_mc_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 /* QCA_IBSS_SUPPORT */ { if (wma_is_vdev_in_ap_mode(wma, tgt_req->vdev_id)) { wma_delete_all_ap_remote_peers(wma, @@ -2522,12 +2542,12 @@ void wma_vdev_resp_timer(void *data) cdf_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 /* QCA_IBSS_SUPPORT */ + params->status = CDF_STATUS_E_TIMEOUT; WMA_LOGA("%s: WMA_DELETE_BSS_REQ timedout", __func__); wma_send_msg(wma, WMA_DELETE_BSS_RSP, (void *)params, 0); @@ -4221,19 +4241,16 @@ void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) if (wma_is_vdev_in_ap_mode(wma, add_sta->smesessionId)) 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; -#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 + /* IBSS should share the same code as AP mode */ + case BSS_OPERATIONAL_MODE_IBSS: case BSS_OPERATIONAL_MODE_AP: hif_vote_link_up(); wma_add_sta_req_ap_mode(wma, add_sta); @@ -4263,21 +4280,17 @@ void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) if (wma_is_vdev_in_ap_mode(wma, smesession_id)) 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; 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: hif_vote_link_down(); wma_delete_sta_req_ap_mode(wma, del_sta); @@ -4353,15 +4366,13 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) 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); + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id); if (!peer) { WMA_LOGP("%s: Failed to find peer %pM", __func__, diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 42f86d0a21ec..ed5459412242 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3391,12 +3391,7 @@ void wma_register_wow_default_patterns(WMA_HANDLE handle, uint8_t vdev_id) iface = &wma->interfaces[vdev_id]; if (iface->ptrn_match_enable) { - if (wma_is_vdev_in_ap_mode(wma, vdev_id) -#ifdef QCA_IBSS_SUPPORT - || - wma_is_vdev_in_ibss_mode(wma, vdev_id) -#endif - ) { + if (wma_is_vdev_in_beaconning_mode(wma, vdev_id)) { /* Configure SAP/GO/IBSS mode default wow patterns */ WMA_LOGI("Config SAP specific default wow patterns vdev_id %d", vdev_id); @@ -3985,10 +3980,7 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) * 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 /* QCA_IBSS_SUPPORT */ + if ((wma_is_vdev_in_beaconning_mode(wma, i) ) && wma->interfaces[i].vdev_up && WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) { diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 9e46b64d23f7..215b450ba824 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -954,9 +954,7 @@ int32_t wmi_unified_send_peer_assoc(tp_wma_handle wma, * 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 /* QCA_IBSS_SUPPORT */ #ifdef FEATURE_WLAN_TDLS || (STA_ENTRY_TDLS_PEER == params->staType) #endif /* FEATURE_WLAN_TDLS */ -- cgit v1.2.3 From 06bc4f52fc42a924ddab4fecd8afcb0a60934de7 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 16 Dec 2015 18:43:34 -0800 Subject: qcacld-3.0: Remove IHELIUM_BU flag This flag supports depricated emulation hardware. Remove conditionally compiled code and dummy functions that become unused as a result. Change-Id: Ie21df7e39b196109acfb6b41afc6b8c22fecb822 CRs-Fixed: 958120 --- core/bmi/src/bmi.c | 4 +-- core/bmi/src/bmi_2.c | 2 +- core/bmi/src/i_bmi.h | 6 ++-- core/hif/src/adrastea_reg_def.h | 4 --- core/hif/src/ce/ce_main.c | 14 +-------- core/hif/src/hif_main.c | 13 --------- core/hif/src/hif_main.h | 8 +----- core/hif/src/pcie/if_pci.c | 63 ++--------------------------------------- 8 files changed, 11 insertions(+), 103 deletions(-) diff --git a/core/bmi/src/bmi.c b/core/bmi/src/bmi.c index 7104619faffe..ddeab53c0197 100644 --- a/core/bmi/src/bmi.c +++ b/core/bmi/src/bmi.c @@ -112,7 +112,7 @@ CDF_STATUS bmi_done(struct ol_softc *scn) CDF_STATUS status = CDF_STATUS_SUCCESS; hif_claim_device(scn, scn); - if (IHELIUM_NO_BMI) + if (NO_BMI) return status; status = bmi_done_local(scn); @@ -175,7 +175,7 @@ CDF_STATUS bmi_download_firmware(struct ol_softc *scn) uint32_t address; int32_t ret; - if (IHELIUM_NO_BMI) + if (NO_BMI) return CDF_STATUS_SUCCESS; /* no BMI for Q6 bring up */ if (!scn) { diff --git a/core/bmi/src/bmi_2.c b/core/bmi/src/bmi_2.c index cd8ce45bcf26..b04f4cbfc159 100644 --- a/core/bmi/src/bmi_2.c +++ b/core/bmi/src/bmi_2.c @@ -429,7 +429,7 @@ CDF_STATUS bmi_firmware_download(struct ol_softc *scn) { CDF_STATUS status; - if (IHELIUM_NO_BMI) + if (NO_BMI) return CDF_STATUS_SUCCESS; status = bmi_init(scn); diff --git a/core/bmi/src/i_bmi.h b/core/bmi/src/i_bmi.h index 9df099d02669..a176b4c4ddd2 100644 --- a/core/bmi/src/i_bmi.h +++ b/core/bmi/src/i_bmi.h @@ -118,10 +118,10 @@ typedef enum _ATH_BIN_FILE { ATH_SETUP_FILE, } ATH_BIN_FILE; -#if defined(QCA_WIFI_3_0_IHELIUM) || defined(QCA_WIFI_3_0_ADRASTEA) -#define IHELIUM_NO_BMI 1 +#if defined(QCA_WIFI_3_0_ADRASTEA) +#define NO_BMI 1 #else -#define IHELIUM_NO_BMI 0 +#define NO_BMI 0 #endif CDF_STATUS bmi_execute(uint32_t address, uint32_t *param, diff --git a/core/hif/src/adrastea_reg_def.h b/core/hif/src/adrastea_reg_def.h index c7fa92c47a48..c51733aae3be 100644 --- a/core/hif/src/adrastea_reg_def.h +++ b/core/hif/src/adrastea_reg_def.h @@ -1812,11 +1812,7 @@ #define ADRASTEA_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA 0x08 #define ADRASTEA_A_SOC_PCIE_PCIE_SCRATCH_2 0x0013005C -#ifdef QCA_WIFI_3_0_IHELIUM -#define ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK 0xff -#else #define ADRASTEA_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK 0x0 -#endif /* QCA_WIFI_3_0_IHELIUM */ /* end: Q6 iHelium emulation registers */ struct targetdef_s adrastea_targetdef = { diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index bac788852f45..a6eed4e8a3fa 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1550,7 +1550,7 @@ int hif_set_hia(struct ol_softc *scn) HIF_TRACE("%s: E", __func__); - if (IHELIUM_BU || ADRASTEA_BU) + if (ADRASTEA_BU) return CDF_STATUS_SUCCESS; #ifdef QCA_WIFI_3_0 @@ -1816,13 +1816,6 @@ static int hif_wlan_enable(void) return icnss_wlan_enable(&cfg, mode, QWLAN_VERSIONSTR); } -#if ((!defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA)) || defined(CONFIG_ICNSS)) -static inline void cnss_pcie_notify_q6(void) -{ - return; -} -#endif - /* * Called from PCI layer whenever a new PCI device is probed. * Initializes per-device HIF state and notifies the main @@ -1861,11 +1854,6 @@ int hif_config_ce(hif_handle_t hif_hdl) HIF_ERROR("%s: hif_wlan_enable error = %d", __func__, ret); return CDF_STATUS_NOT_INITIALIZED; } - if (IHELIUM_BU) { - cnss_pcie_notify_q6(); - HIF_TRACE("%s: cnss_pcie_notify_q6 done, notice_send= %d", - __func__, scn->notice_send); - } scn->notice_send = true; diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 90544f309e29..0c324346651e 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -664,13 +664,6 @@ void hif_pktlogmod_exit(void *hif_ctx) } #endif -#if ((!defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA)) || defined(CONFIG_ICNSS)) -static inline void cnss_pcie_notify_q6(void) -{ - return; -} -#endif - /** * hif_wlan_disable(): call the platform driver to disable wlan * @@ -713,12 +706,6 @@ void hif_disable(void *hif_ctx, enum hif_disable_type type) if (scn->aps_osdev.bdev) hif_disable_bus(scn->aps_osdev.bdev); - if (IHELIUM_BU) { - cnss_pcie_notify_q6(); - HIF_TRACE("%s: cnss_pcie_notify_q6 done, notice_send= %d", - __func__, scn->notice_send); - } - hif_wlan_disable(); scn->notice_send = false; diff --git a/core/hif/src/hif_main.h b/core/hif/src/hif_main.h index 5a9c81ca1afa..812b7637671e 100644 --- a/core/hif/src/hif_main.h +++ b/core/hif/src/hif_main.h @@ -73,12 +73,6 @@ bool hif_target_forced_awake(struct ol_softc *scn); #define MAX_NUM_OF_RECEIVES 1000 #endif /* SLUB_DEBUG_ON / FEATURE_NAPI */ -#ifdef QCA_WIFI_3_0_IHELIUM -#define IHELIUM_BU 1 -#else -#define IHELIUM_BU 0 -#endif - #ifdef QCA_WIFI_3_0_ADRASTEA #define ADRASTEA_BU 1 #else @@ -101,7 +95,7 @@ bool hif_target_forced_awake(struct ol_softc *scn); #define AR6320_FW_3_2 (0x32) #define ADRASTEA_DEVICE_ID (0xabcd) #define ADRASTEA_DEVICE_ID_P2_E12 (0x7021) -#if (defined(QVIT) || defined (QCA_WIFI_3_0_IHELIUM)) +#if (defined(QVIT)) #define QCA6180_DEVICE_ID (0xabcd) #else #define QCA6180_DEVICE_ID (0x041) diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 6c7a5622c4f0..21cec32177a0 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -100,64 +100,19 @@ struct ce_irq_reg_table { uint32_t irq_status; }; -#if !defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA) +#if !defined(QCA_WIFI_3_0_ADRASTEA) static inline void cnss_intr_notify_q6(void) { } #endif -#if !defined(QCA_WIFI_3_0_IHELIUM) && !defined(QCA_WIFI_3_0_ADRASTEA) +#if !defined(QCA_WIFI_3_0_ADRASTEA) static inline void *cnss_get_target_smem(void) { return NULL; } #endif -void hif_pci_route_target_interrupt(struct hif_pci_softc *sc) -{ - uint32_t target_cause0, target_cause1, target_cause2; - uint32_t *target_smem; - struct ol_softc *scn = sc->ol_sc; - - target_smem = (uint32_t *)cnss_get_target_smem(); - if (!target_smem) - return; - - /* disable interrupts */ - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_0_ADDRESS, 0); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_1_ADDRESS, 0); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_2_ADDRESS, 0); - /* read cause */ - target_cause0 = hif_read32_mb(sc->mem + - A_SOC_CORE_SCRATCH_3_ADDRESS); - target_cause1 = hif_read32_mb(sc->mem + - A_SOC_CORE_SCRATCH_4_ADDRESS); - target_cause2 = hif_read32_mb(sc->mem + - A_SOC_CORE_SCRATCH_5_ADDRESS); - /* clear cause registers */ - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_3_ADDRESS, 0xffffffff); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_4_ADDRESS, 0xffffffff); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_5_ADDRESS, 0xffffffff); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_3_ADDRESS, 0); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_4_ADDRESS, 0); - hif_write32_mb(sc->mem + - A_SOC_CORE_SCRATCH_5_ADDRESS, 0); - /* copy cause value to Q6 */ - *target_smem = target_cause0; - *(target_smem + 1) = target_cause1; - *(target_smem + 2) = target_cause2; - if (scn->notice_send) - cnss_intr_notify_q6(); -} - #ifndef QCA_WIFI_3_0_ADRASTEA static inline void hif_pci_route_adrastea_interrupt(struct hif_pci_softc *sc) { @@ -220,18 +175,6 @@ static irqreturn_t hif_pci_interrupt_handler(int irq, void *arg) hif_write32_mb(sc->mem + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), 0); - if (IHELIUM_BU) { - if (!hif_read32_mb(sc->mem + PCIE_INTR_CAUSE_ADDRESS)) { - hif_pci_route_target_interrupt(sc); - - hif_write32_mb(sc->mem + - (SOC_CORE_BASE_ADDRESS | - PCIE_INTR_ENABLE_ADDRESS), - HOST_GROUP0_MASK); - - return IRQ_HANDLED; - } - } hif_write32_mb(sc->mem + (SOC_CORE_BASE_ADDRESS | PCIE_INTR_CLR_ADDRESS), @@ -850,7 +793,7 @@ static void wlan_tasklet(unsigned long data) if (cdf_atomic_read(&scn->link_suspended)) goto end; - if (!IHELIUM_BU && !ADRASTEA_BU) { + if (!ADRASTEA_BU) { (irqreturn_t) hif_fw_interrupt_handler(sc->irq_event, scn); if (sc->ol_sc->target_status == OL_TRGET_STATUS_RESET) goto end; -- cgit v1.2.3 From 49794a3d07d00b2e88fa36132a6cf785b6b4cb0f Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 21 Dec 2015 12:14:56 -0800 Subject: qcacld-3.0: Fix firmware assert completion handling Hif needs to guarantee that it frees the buffers that it doesn't pass to upper layers. Change-Id: I816d0a1b19a5a0c00e9669c18dfdf427c102c911 CRs-Fixed: 958124 --- core/hif/src/ce/ce_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index a6eed4e8a3fa..aaf42961bd2b 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -694,9 +694,9 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context, if (transfer_context != CE_SENDLIST_ITEM_CTXT) { if (hif_state->scn->target_status == OL_TRGET_STATUS_RESET) - return; - - msg_callbacks->txCompletionHandler( + cdf_nbuf_free(transfer_context); + else + msg_callbacks->txCompletionHandler( msg_callbacks->Context, transfer_context, transfer_id, toeplitz_hash_result); @@ -762,9 +762,9 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, atomic_inc(&pipe_info->recv_bufs_needed); hif_post_recv_buffers_for_pipe(pipe_info); if (hif_state->scn->target_status == OL_TRGET_STATUS_RESET) - return; - - hif_ce_do_recv(msg_callbacks, transfer_context, + cdf_nbuf_free(transfer_context); + else + hif_ce_do_recv(msg_callbacks, transfer_context, nbytes, pipe_info); /* Set up force_break flag if num of receices reaches -- cgit v1.2.3 From 565aa509fd2d8592f767d09fbe82b2b129a85048 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 20 Oct 2015 16:03:06 -0700 Subject: qcacld-3.0: Rename cdf_sched_work to cdf_schedule_work The api is clearer without the abreviation. The api is cleaner without an unused cdf_handle. Also remove unnecessary cdf_schedule_work api. cdf_create_work is also cleaner without cdf_handle. Change-Id: Id8c32596a92184d6768e2bc3210c308b44da2a57 CRs-Fixed: 935297 --- core/cdf/inc/cdf_defer.h | 25 +++++-------------------- core/cdf/src/i_cdf_defer.h | 13 +++---------- core/cds/src/cds_concurrency.c | 5 ++--- core/wma/src/wma_data.c | 12 +++++------- 4 files changed, 15 insertions(+), 40 deletions(-) diff --git a/core/cdf/inc/cdf_defer.h b/core/cdf/inc/cdf_defer.h index fa527f3b3dbc..829f350f6023 100644 --- a/core/cdf/inc/cdf_defer.h +++ b/core/cdf/inc/cdf_defer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -96,7 +96,6 @@ static inline void cdf_destroy_bh(cdf_handle_t hdl, cdf_bh_t *bh) /** * cdf_create_work() - create a work/task queue, This runs in non-interrupt * context, so can be preempted by H/W & S/W intr - * @hdl: OS handle * @work: Work instance * @func: Deferred function to run at bottom half non-interrupt * context @@ -105,34 +104,20 @@ static inline void cdf_destroy_bh(cdf_handle_t hdl, cdf_bh_t *bh) * Return: None */ static inline void -cdf_create_work(cdf_handle_t hdl, cdf_work_t *work, +cdf_create_work(cdf_work_t *work, cdf_defer_fn_t func, void *arg) { - __cdf_init_work(hdl, work, func, arg); + __cdf_init_work(work, func, arg); } /** * cdf_sched_work() - schedule a deferred task on non-interrupt context - * @hdl: OS handle - * @work: Work instance - * - * Return: None - */ -static inline void cdf_sched_work(cdf_handle_t hdl, cdf_work_t *work) -{ - __cdf_sched_work(hdl, work); -} - -/** - * cdf_destroy_work() - destroy the deferred task (synchronous) - * @hdl: OS handle * @work: Work instance * * Return: None */ -static inline void cdf_destroy_work(cdf_handle_t hdl, cdf_work_t *work) +static inline void cdf_schedule_work(cdf_work_t *work) { - __cdf_disable_work(hdl, work); + __cdf_schedule_work(work); } - #endif /*__CDF_DEFER_H*/ diff --git a/core/cdf/src/i_cdf_defer.h b/core/cdf/src/i_cdf_defer.h index fc9bd7796eae..a21b618f5434 100644 --- a/core/cdf/src/i_cdf_defer.h +++ b/core/cdf/src/i_cdf_defer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -52,8 +52,7 @@ typedef struct { extern void __cdf_defer_func(struct work_struct *work); static inline CDF_STATUS -__cdf_init_work(cdf_handle_t hdl, - __cdf_work_t *work, cdf_defer_fn_t func, void *arg) +__cdf_init_work(__cdf_work_t *work, cdf_defer_fn_t func, void *arg) { /*Initilize func and argument in work struct */ work->fn = func; @@ -66,18 +65,12 @@ __cdf_init_work(cdf_handle_t hdl, return CDF_STATUS_SUCCESS; } -static inline CDF_STATUS __cdf_sched_work(cdf_handle_t hdl, __cdf_work_t *work) +static inline CDF_STATUS __cdf_schedule_work(__cdf_work_t *work) { schedule_work(&work->work); return CDF_STATUS_SUCCESS; } -static inline CDF_STATUS -__cdf_disable_work(cdf_handle_t hdl, __cdf_work_t *work) -{ - return CDF_STATUS_SUCCESS; -} - static inline CDF_STATUS __cdf_init_bh(cdf_handle_t hdl, struct tasklet_struct *bh, cdf_defer_fn_t func, void *arg) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index b29c4918196e..8f9dfb072398 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -6595,7 +6595,6 @@ void cds_force_sap_on_scc(eCsrRoamResult roam_result) #endif /* FEATURE_WLAN_FORCE_SAP_SCC */ #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH - /** * cds_check_sta_ap_concurrent_ch_intf() - Restart SAP in STA-AP case * @data: Pointer to STA adapter @@ -6677,10 +6676,10 @@ void cds_check_concurrent_intf_and_restart_sap(hdd_station_ctx_t *hdd_sta_ctx, operationChannel) #endif ) { - cdf_create_work(0, &hdd_ctx->sta_ap_intf_check_work, + cdf_create_work(&hdd_ctx->sta_ap_intf_check_work, cds_check_sta_ap_concurrent_ch_intf, (void *)adapter); - cdf_sched_work(0, &hdd_ctx->sta_ap_intf_check_work); + cdf_schedule_work(&hdd_ctx->sta_ap_intf_check_work); cds_info("Checking for Concurrent Change interference"); } } diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 286df551ed02..2c2a41c4b843 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -888,11 +888,10 @@ wma_data_tx_ack_comp_hdlr(void *wma_context, cdf_nbuf_t netbuf, int32_t status) ack_work->sub_type = 0; ack_work->status = status; - cdf_create_work(0, &ack_work->ack_cmp_work, + cdf_create_work(&ack_work->ack_cmp_work, wma_data_tx_ack_work_handler, ack_work); - /* Schedule the Work */ - cdf_sched_work(0, &ack_work->ack_cmp_work); + cdf_schedule_work(&ack_work->ack_cmp_work); } } @@ -1564,12 +1563,11 @@ wma_mgmt_tx_ack_comp_hdlr(void *wma_context, cdf_nbuf_t netbuf, int32_t status) ack_work->sub_type = pFc->subType; ack_work->status = status; - cdf_create_work(0, &ack_work->ack_cmp_work, + cdf_create_work(&ack_work->ack_cmp_work, wma_mgmt_tx_ack_work_handler, ack_work); - /* Schedule the Work */ - cdf_sched_work(0, &ack_work->ack_cmp_work); + cdf_schedule_work(&ack_work->ack_cmp_work); } } } -- cgit v1.2.3 From 29573d960dc01d332b9743546428cacb91f510f7 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 20 Oct 2015 17:49:44 -0700 Subject: qcacld-3.0: Replace EndPoint with endpoint This change also changes EndPointStats to endpoint_stats. Change-Id: I88509901b0d15a59f35633dccbe7ca0b5f7b3b76 CRs-Fixed: 935297 --- core/hif/src/ce/ce_main.c | 2 +- core/htc/htc.c | 14 +++++++------- core/htc/htc_internal.h | 8 ++++---- core/htc/htc_recv.c | 6 +++--- core/htc/htc_send.c | 26 +++++++++++++------------- core/htc/htc_services.c | 2 +- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index aaf42961bd2b..216ea979a094 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -1168,7 +1168,7 @@ void hif_send_buffer_cleanup_on_pipe(struct HIF_CE_pipe_info *pipe_info) * 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 + * by checking whether it's the endpoint * which they are queued in. */ if (id == hif_state->scn->htc_endpoint) diff --git a/core/htc/htc.c b/core/htc/htc.c index a22244f0f21a..2d7521094825 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -257,7 +257,7 @@ HTC_HANDLE htc_create(void *ol_sc, HTC_INIT_INFO *pInfo, cdf_device_t osdev) target->hif_dev = ol_sc; /* Get HIF default pipe for HTC message exchange */ - pEndpoint = &target->EndPoint[ENDPOINT_0]; + pEndpoint = &target->endpoint[ENDPOINT_0]; hif_post_init(target->hif_dev, target, &htcCallbacks); hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID, @@ -516,7 +516,7 @@ static void reset_endpoint_states(HTC_TARGET *target) int i; for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; pEndpoint->ServiceID = 0; pEndpoint->MaxMsgLength = 0; pEndpoint->MaxTxQueueDepth = 0; @@ -616,7 +616,7 @@ void htc_flush_surprise_remove(HTC_HANDLE HTCHandle) /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; htc_flush_rx_hold_queue(target, pEndpoint); htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); } @@ -652,7 +652,7 @@ void htc_stop(HTC_HANDLE HTCHandle) /* cleanup endpoints */ for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; htc_flush_rx_hold_queue(target, pEndpoint); htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); if (pEndpoint->ul_is_polled) { @@ -691,7 +691,7 @@ void htc_dump_credit_states(HTC_HANDLE HTCHandle) int i; for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; if (0 == pEndpoint->ServiceID) { continue; } @@ -749,13 +749,13 @@ A_BOOL htc_get_endpoint_statistics(HTC_HANDLE HTCHandle, if (sample) { A_ASSERT(pStats != NULL); /* return the stats to the caller */ - A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, + A_MEMCPY(pStats, &target->endpoint[Endpoint].endpoint_stats, sizeof(HTC_ENDPOINT_STATS)); } if (clearStats) { /* reset stats */ - A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, + A_MEMZERO(&target->endpoint[Endpoint].endpoint_stats, sizeof(HTC_ENDPOINT_STATS)); } diff --git a/core/htc/htc_internal.h b/core/htc/htc_internal.h index b7a526ec6464..db2fc4818c14 100644 --- a/core/htc/htc_internal.h +++ b/core/htc/htc_internal.h @@ -123,15 +123,15 @@ typedef struct _HTC_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 */ + HTC_ENDPOINT_STATS endpoint_stats; /* 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); +#define INC_HTC_EP_STAT(p, stat, count) ((p)->endpoint_stats.stat += (count)) #else -#define INC_HTC_EP_STAT(p,stat,count) +#define INC_HTC_EP_STAT(p, stat, count) #endif typedef struct { @@ -150,7 +150,7 @@ enum ol_ath_htc_pkt_ecodes { /* our HTC target state */ typedef struct _HTC_TARGET { struct ol_softc *hif_dev; - HTC_ENDPOINT EndPoint[ENDPOINT_MAX]; + HTC_ENDPOINT endpoint[ENDPOINT_MAX]; cdf_spinlock_t HTCLock; cdf_spinlock_t HTCRxLock; cdf_spinlock_t HTCTxLock; diff --git a/core/htc/htc_recv.c b/core/htc/htc_recv.c index ad0644ce69ab..79bf6c6847d0 100644 --- a/core/htc/htc_recv.c +++ b/core/htc/htc_recv.c @@ -168,7 +168,7 @@ void htc_disable_recv(HTC_HANDLE HTCHandle) int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; + HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint]; return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue); } @@ -315,7 +315,7 @@ CDF_STATUS htc_rx_completion_handler(void *Context, cdf_nbuf_t netbuf, break; } - pEndpoint = &target->EndPoint[htc_ep_id]; + pEndpoint = &target->endpoint[htc_ep_id]; /* * If this endpoint that received a message from the target has @@ -531,7 +531,7 @@ A_STATUS htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE_DEPTH(pPktQueue), pFirstPacket->BufferLength)); - pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; + pEndpoint = &target->endpoint[pFirstPacket->Endpoint]; LOCK_HTC_RX(target); diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index 2f2925cf624f..1af9e935c83c 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -121,7 +121,7 @@ void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle, int *credits *credits = 0; LOCK_HTC_TX(target); for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { *credits = pEndpoint->TxCredits; break; @@ -185,7 +185,7 @@ static void do_send_completion(HTC_ENDPOINT *pEndpoint, static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket) { - HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint]; + HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint]; HTC_PACKET_QUEUE container; restore_tx_packet(target, pPacket); @@ -1034,7 +1034,7 @@ static A_UINT16 htc_send_pkts_sched_check(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID } for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) { - pEndpoint = &target->EndPoint[eid]; + pEndpoint = &target->endpoint[eid]; pTxQueue = &pEndpoint->TxQueue; if (HTC_QUEUE_EMPTY(pTxQueue)) { @@ -1068,7 +1068,7 @@ static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target, HTC_PACKET *pPacket; int goodPkts; - pEndpoint = &target->EndPoint[eid]; + pEndpoint = &target->endpoint[eid]; pTxQueue = &pEndpoint->TxQueue; LOCK_HTC_TX(target); @@ -1133,7 +1133,7 @@ A_STATUS htc_send_pkts_multiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueu } AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); - pEndpoint = &target->EndPoint[pPacket->Endpoint]; + pEndpoint = &target->endpoint[pPacket->Endpoint]; if (!pEndpoint->ServiceID) { AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s ServiceID is invalid\n", @@ -1246,7 +1246,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, cdf_nbuf_t netbuf, int Epid, int tx_resources; uint32_t data_attr = 0; - pEndpoint = &target->EndPoint[Epid]; + pEndpoint = &target->endpoint[Epid]; tx_resources = hif_get_free_queue_number(target->hif_dev, pEndpoint->UL_PipeID); @@ -1320,7 +1320,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, if (pPacket) { AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); - pEndpoint = &target->EndPoint[pPacket->Endpoint]; + pEndpoint = &target->endpoint[pPacket->Endpoint]; /* add HTC_FRAME_HDR in the initial fragment */ netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); @@ -1372,7 +1372,7 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, #endif } else { LOCK_HTC_TX(target); - pEndpoint = &target->EndPoint[1]; + pEndpoint = &target->endpoint[1]; } /* increment tx processing count on entry */ @@ -1597,7 +1597,7 @@ CDF_STATUS htc_tx_completion_handler(void *Context, A_UINT16 resourcesMax; #endif - pEndpoint = &target->EndPoint[EpID]; + pEndpoint = &target->endpoint[EpID]; target->TX_comp_cnt++; do { @@ -1647,7 +1647,7 @@ void htc_tx_resource_avail_handler(void *context, A_UINT8 pipeID) HTC_ENDPOINT *pEndpoint = NULL; for (i = 0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; + pEndpoint = &target->endpoint[i]; if (pEndpoint->ServiceID != 0) { if (pEndpoint->UL_PipeID == pipeID) { break; @@ -1693,7 +1693,7 @@ void htc_flush_endpoint(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]; + HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint]; if (pEndpoint->ServiceID == 0) { AR_DEBUG_ASSERT(false); @@ -1743,7 +1743,7 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS); - pEndpoint = &target->EndPoint[rpt_ep_id]; + pEndpoint = &target->endpoint[rpt_ep_id]; #if DEBUG_CREDIT if (ep_debug_mask & (1 << pEndpoint->Id)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, @@ -1787,7 +1787,7 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, target->avail_tx_credits += rpt_credits; for (epid_idx = 0; epid_idx < DATA_EP_SIZE; epid_idx++) { - pEndpoint = &target->EndPoint[eid[epid_idx]]; + pEndpoint = &target->endpoint[eid[epid_idx]]; if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { break; } diff --git a/core/htc/htc_services.c b/core/htc/htc_services.c index 40067f733649..6d5d30868a46 100644 --- a/core/htc/htc_services.c +++ b/core/htc/htc_services.c @@ -267,7 +267,7 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, break; } - pEndpoint = &target->EndPoint[assignedEndpoint]; + pEndpoint = &target->endpoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; if (pEndpoint->ServiceID != 0) { /* endpoint already in use! */ -- cgit v1.2.3 From 4f2f4597228f1bc539ce3dbc4fddb43dc9ae07f3 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 20 Oct 2015 18:00:29 -0700 Subject: qcacld-3.0: Replace ServiceID with service_id Removes cammel case. Change-Id: I8107c9fa783bdec41468191315c901018f6fd05f CRs-Fixed: 935297 --- core/dp/htt/htt.c | 2 +- core/htc/htc.c | 40 ++++++++++++++++++------------------- core/htc/htc_api.h | 4 ++-- core/htc/htc_internal.h | 12 +++++++---- core/htc/htc_send.c | 16 +++++++-------- core/htc/htc_services.c | 31 ++++++++++++++-------------- core/utils/epping/src/epping_txrx.c | 4 ++-- core/wmi/wmi_unified.c | 2 +- target/inc/htc.h | 6 ++++-- 9 files changed, 62 insertions(+), 55 deletions(-) diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index 3c4d6fd74774..4bc45c879a65 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -424,7 +424,7 @@ int htt_htc_attach(struct htt_pdev_t *pdev) #endif /* connect to control service */ - connect.ServiceID = HTT_DATA_MSG_SVC; + connect.service_id = HTT_DATA_MSG_SVC; status = htc_connect_service(pdev->htc_pdev, &connect, &response); diff --git a/core/htc/htc.c b/core/htc/htc.c index 2d7521094825..8e45efcd1721 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -333,7 +333,7 @@ A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) */ status = A_OK; pEntry++; - pEntry->ServiceID = WMI_CONTROL_SVC; + pEntry->service_id = WMI_CONTROL_SVC; pEntry->CreditAllocation = credits; if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { @@ -360,23 +360,23 @@ A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) * BE and BK services to stress the bus so that the total credits * are equally distributed to BE and BK services. */ - pEntry->ServiceID = WMI_DATA_BE_SVC; + pEntry->service_id = WMI_DATA_BE_SVC; pEntry->CreditAllocation = (credits >> 1); pEntry++; - pEntry->ServiceID = WMI_DATA_BK_SVC; + pEntry->service_id = WMI_DATA_BK_SVC; pEntry->CreditAllocation = (credits >> 1); } if (A_SUCCESS(status)) { int i; for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { - if (target->ServiceTxAllocTable[i].ServiceID != 0) { + if (target->ServiceTxAllocTable[i].service_id != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, - ("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n", + ("HTC Service Index : %d TX : 0x%2.2X : alloc:%d\n", i, target->ServiceTxAllocTable[i]. - ServiceID, + service_id, target->ServiceTxAllocTable[i]. CreditAllocation)); } @@ -386,13 +386,13 @@ A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) return status; } -A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID) +A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 service_id) { A_UINT8 allocation = 0; int i; for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { - if (target->ServiceTxAllocTable[i].ServiceID == ServiceID) { + if (target->ServiceTxAllocTable[i].service_id == service_id) { allocation = target->ServiceTxAllocTable[i].CreditAllocation; } @@ -400,8 +400,8 @@ A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID) if (0 == allocation) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, - ("HTC Service TX : 0x%2.2X : allocation is zero! \n", - ServiceID)); + ("HTC Service TX : 0x%2.2X : allocation is zero!\n", + service_id)); } return allocation; @@ -490,7 +490,7 @@ A_STATUS htc_wait_target(HTC_HANDLE HTCHandle) connect.EpCallbacks.EpTxComplete = htc_control_tx_complete; connect.EpCallbacks.EpRecv = htc_control_rx_complete; connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS; - connect.ServiceID = HTC_CTRL_RSVD_SVC; + connect.service_id = HTC_CTRL_RSVD_SVC; /* connect fake service */ status = htc_connect_service((HTC_HANDLE) target, @@ -517,7 +517,7 @@ static void reset_endpoint_states(HTC_TARGET *target) for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->endpoint[i]; - pEndpoint->ServiceID = 0; + pEndpoint->service_id = 0; pEndpoint->MaxMsgLength = 0; pEndpoint->MaxTxQueueDepth = 0; pEndpoint->Id = i; @@ -692,23 +692,23 @@ void htc_dump_credit_states(HTC_HANDLE HTCHandle) for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->endpoint[i]; - if (0 == pEndpoint->ServiceID) { + if (0 == pEndpoint->service_id) continue; - } + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, - ("--- EP : %d ServiceID: 0x%X --------------\n", - pEndpoint->Id, pEndpoint->ServiceID)); + ("--- EP : %d service_id: 0x%X --------------\n", + pEndpoint->Id, pEndpoint->service_id)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, - (" TxCredits : %d \n", + (" TxCredits : %d\n", pEndpoint->TxCredits)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, - (" TxCreditSize : %d \n", + (" TxCreditSize : %d\n", pEndpoint->TxCreditSize)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, - (" TxCreditsPerMaxMsg : %d \n", + (" TxCreditsPerMaxMsg : %d\n", pEndpoint->TxCreditsPerMaxMsg)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, - (" TxQueueDepth : %d \n", + (" TxQueueDepth : %d\n", HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); diff --git a/core/htc/htc_api.h b/core/htc/htc_api.h index 75c83d7d8414..7ae13b453955 100644 --- a/core/htc/htc_api.h +++ b/core/htc/htc_api.h @@ -163,7 +163,7 @@ typedef struct _HTC_EP_CALLBACKS { /* service connection information */ typedef struct _HTC_SERVICE_CONNECT_REQ { - HTC_SERVICE_ID ServiceID; /* service ID to connect to */ + HTC_SERVICE_ID service_id; /* 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 */ @@ -189,7 +189,7 @@ typedef struct _HTC_SERVICE_CONNECT_RESP { 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_SERVICE_ID service_id; /* 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 */ diff --git a/core/htc/htc_internal.h b/core/htc/htc_internal.h index db2fc4818c14..8785993893b6 100644 --- a/core/htc/htc_internal.h +++ b/core/htc/htc_internal.h @@ -96,8 +96,12 @@ typedef struct { 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 */ + + /* service ID this endpoint is bound to + * non-zero value means this endpoint is in use + */ + HTC_SERVICE_ID service_id; + 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 @@ -135,7 +139,7 @@ typedef struct _HTC_ENDPOINT { #endif typedef struct { - A_UINT16 ServiceID; + A_UINT16 service_id; A_UINT8 CreditAllocation; } HTC_SERVICE_TX_CREDIT_ALLOCATION; @@ -233,7 +237,7 @@ void htc_recv_init(HTC_TARGET *target); A_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target); void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket); HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target); -A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID); +A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 service_id); void htc_tx_resource_avail_handler(void *context, A_UINT8 pipeID); void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket); void htc_process_credit_rpt(HTC_TARGET *target, diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index 1af9e935c83c..bb5c34368a00 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -122,7 +122,7 @@ void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle, int *credits LOCK_HTC_TX(target); for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->endpoint[i]; - if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + if (pEndpoint->service_id == WMI_CONTROL_SVC) { *credits = pEndpoint->TxCredits; break; } @@ -689,7 +689,7 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, /* tell the target we need credits ASAP! */ sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; - if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + if (pEndpoint->service_id == WMI_CONTROL_SVC) { LOCK_HTC_CREDIT(target); htc_credit_record(HTC_REQUEST_CREDIT, pEndpoint->TxCredits, @@ -1135,8 +1135,8 @@ A_STATUS htc_send_pkts_multiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueu 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", + if (!pEndpoint->service_id) { + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n", __func__)); return A_EINVAL; } @@ -1648,7 +1648,7 @@ void htc_tx_resource_avail_handler(void *context, A_UINT8 pipeID) for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->endpoint[i]; - if (pEndpoint->ServiceID != 0) { + if (pEndpoint->service_id != 0) { if (pEndpoint->UL_PipeID == pipeID) { break; } @@ -1695,7 +1695,7 @@ void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint]; - if (pEndpoint->ServiceID == 0) { + if (pEndpoint->service_id == 0) { AR_DEBUG_ASSERT(false); /* not in use.. */ return; @@ -1809,7 +1809,7 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, #else pEndpoint->TxCredits += rpt_credits; - if (pEndpoint->ServiceID == WMI_CONTROL_SVC) { + if (pEndpoint->service_id == WMI_CONTROL_SVC) { LOCK_HTC_CREDIT(target); htc_credit_record(HTC_PROCESS_CREDIT_REPORT, pEndpoint->TxCredits, @@ -1824,7 +1824,7 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, #ifdef ATH_11AC_TXCOMPACT htc_try_send(target, pEndpoint, NULL); #else - if (pEndpoint->ServiceID == HTT_DATA_MSG_SVC) { + if (pEndpoint->service_id == HTT_DATA_MSG_SVC) { htc_send_data_pkt(target, NULL, 0); } else { htc_try_send(target, pEndpoint, NULL); diff --git a/core/htc/htc_services.c b/core/htc/htc_services.c index 6d5d30868a46..0e6ce13a6c90 100644 --- a/core/htc/htc_services.c +++ b/core/htc/htc_services.c @@ -57,14 +57,14 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, A_UINT8 rsp_msg_status, rsp_msg_end_id, rsp_msg_serv_meta_len; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, - ("+htc_connect_service, target:%p SvcID:0x%X \n", target, - pConnectReq->ServiceID)); + ("+htc_connect_service, target:%p SvcID:0x%X\n", target, + pConnectReq->service_id)); do { - AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); + AR_DEBUG_ASSERT(pConnectReq->service_id != 0); - if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { + if (HTC_CTRL_RSVD_SVC == pConnectReq->service_id) { /* special case for pseudo control service */ assignedEndpoint = ENDPOINT_0; maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; @@ -72,13 +72,13 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, } else { - txAlloc = - htc_get_credit_allocation(target, - pConnectReq->ServiceID); + txAlloc = htc_get_credit_allocation(target, + pConnectReq->service_id); + if (!txAlloc) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Service %d does not allocate target credits!\n", - pConnectReq->ServiceID)); + pConnectReq->service_id)); } /* allocate a packet to send to the target */ @@ -117,7 +117,7 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, 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); + SERVICE_ID, pConnectReq->service_id); HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, CONNECTIONFLAGS, conn_flags); @@ -133,7 +133,7 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, #else /* Only enable credit for WMI service */ if (!htc_credit_flow - && pConnectReq->ServiceID != WMI_CONTROL_SVC) { + && pConnectReq->service_id != WMI_CONTROL_SVC) { disableCreditFlowCtrl = true; } #endif @@ -269,7 +269,7 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, pEndpoint = &target->endpoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; - if (pEndpoint->ServiceID != 0) { + if (pEndpoint->service_id != 0) { /* endpoint already in use! */ AR_DEBUG_ASSERT(false); break; @@ -280,7 +280,8 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, pConnectResp->MaxMsgLength = maxMsgSize; /* setup the endpoint */ - pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ + /* service_id marks the endpoint in use */ + pEndpoint->service_id = pConnectReq->service_id; pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; pEndpoint->MaxMsgLength = maxMsgSize; pEndpoint->TxCredits = txAlloc; @@ -300,7 +301,7 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; status = hif_map_service_to_pipe(target->hif_dev, - pEndpoint->ServiceID, + pEndpoint->service_id, &pEndpoint->UL_PipeID, &pEndpoint->DL_PipeID, &pEndpoint->ul_is_polled, @@ -321,14 +322,14 @@ A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, 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->service_id, 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, + pEndpoint->service_id, assignedEndpoint)); } diff --git a/core/utils/epping/src/epping_txrx.c b/core/utils/epping/src/epping_txrx.c index 6cb31924671a..f3a3101eefcc 100644 --- a/core/utils/epping/src/epping_txrx.c +++ b/core/utils/epping/src/epping_txrx.c @@ -415,7 +415,7 @@ int epping_connect_service(epping_context_t *pEpping_ctx) #endif /* connect to service */ - connect.ServiceID = WMI_DATA_BE_SVC; + connect.service_id = WMI_DATA_BE_SVC; status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); if (status != EOK) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, @@ -429,7 +429,7 @@ int epping_connect_service(epping_context_t *pEpping_ctx) pEpping_ctx->EppingEndpoint[0] = response.Endpoint; #if defined(HIF_PCI) || defined(HIF_USB) - connect.ServiceID = WMI_DATA_BK_SVC; + connect.service_id = WMI_DATA_BK_SVC; status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); if (status != EOK) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 5048b457ae98..78bc9f345961 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -1300,7 +1300,7 @@ wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle, wmi_htc_tx_complete /* ar6000_tx_queue_full */; /* connect to control service */ - connect.ServiceID = WMI_CONTROL_SVC; + connect.service_id = WMI_CONTROL_SVC; if ((status = htc_connect_service(htc_handle, &connect, &response)) != EOK) { diff --git a/target/inc/htc.h b/target/inc/htc.h index 19239abdf34f..9b081bfd4753 100644 --- a/target/inc/htc.h +++ b/target/inc/htc.h @@ -196,7 +196,8 @@ typedef PREPACK struct { /* connect service * direction : host-to-target */ typedef PREPACK struct { - A_UINT32 MessageID : 16, ServiceID : 16; /* service ID of the service to connect to */ + /* service ID of the service to connect to */ + A_UINT32 MessageID:16, service_id:16; A_UINT32 ConnectionFlags : 16, /* connection flags */ #define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when @@ -238,7 +239,8 @@ typedef PREPACK struct { /* connect response * direction : target-to-host */ typedef PREPACK struct { - A_UINT32 MessageID : 16, ServiceID : 16; /* service ID that the connection request was made */ + /* service ID that the connection request was made */ + A_UINT32 MessageID:16, service_id:16; A_UINT32 Status : 8, /* service connection status */ EndpointID : 8, /* assigned endpoint ID */ MaxMsgSize : 16; /* maximum expected message size on this endpoint */ -- cgit v1.2.3 From af206a788c18fce90182e3e668a053e253c0d1bb Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 15 Dec 2015 20:15:41 -0800 Subject: qcacld-3.0: Revert merge conflicts in wma_suspend_req wma_suspend_req is rewritten in changes I020fc8864dbf7378805361d54dc6cff60b2652e5 and I95876979652ab16976f23561038c877cee4c930a Revert "qcacld-3.0: Fix the PNO WoW is not configured in concurrency case" This reverts commit 3bf7846a5ee12e0641f90b9ff05a80a068cde777. Revert "qcacld-3.0: Cleanup WOW_NLO_SCAN_COMPLETE_EVENT" This reverts commit 8098644b8cbf89f23442c5bef02f186460cd9f8f. Revert "qcacld-3.0: Find extscan_in_progress irrespective of connected or pno" This reverts commit 7bb7f564b75965bfbf09fef6b5406aaa19c245a7. Change-Id: If0953ad7ca8d7224c87f026e77d1a3f256c4f124 CRs-Fixed: 935297 --- core/wma/src/wma_features.c | 78 +++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index ed5459412242..36e7b8da25cf 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -102,6 +102,10 @@ static const uint8_t arp_mask[] = {0xff, 0xff}; static const uint8_t ns_ptrn[] = {0x86, 0xDD}; static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; +static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, + uint32_t vdev_id, + uint32_t bitmap, + bool enable); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN /** @@ -2846,11 +2850,20 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD); node = &wma->interfaces[wake_info->vdev_id]; if (node) { + CDF_STATUS ret = CDF_STATUS_SUCCESS; WMA_LOGD("NLO match happened"); node->nlo_match_evt_received = true; cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, WIFI_POWER_EVENT_WAKELOCK_PNO); + /* Configure pno scan complete wakeup */ + ret = wma_add_wow_wakeup_event(wma, wake_info->vdev_id, + (1 << WOW_NLO_SCAN_COMPLETE_EVENT), + true); + if (ret != CDF_STATUS_SUCCESS) + WMA_LOGE("Failed to configure pno scan complete wakeup"); + else + WMA_LOGD("PNO scan complete wakeup is enabled in fw"); } break; @@ -3887,33 +3900,6 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) return CDF_STATUS_SUCCESS; } -#ifdef FEATURE_WLAN_EXTSCAN -/** - * wma_is_extscan_in_progress(): check if extscan is in progress - * @wma: wma handle - * - * Return: true is extscan in progress, false otherwise. - */ -static bool wma_is_extscan_in_progress(tp_wma_handle wma) -{ - int i; - - for (i = 0; i < wma->max_bssid; i++) { - if (wma->interfaces[i].extscan_in_progress) { - WMA_LOGD("Extscan is in progress, enabling wow"); - return true; - } - } - - return false; -} -#else -static bool wma_is_extscan_in_progress(tp_wma_handle wma) -{ - return false; -} -#endif - /** * wma_suspend_req() - Handles suspend indication request received from umac. * @wma: wma handle @@ -3924,10 +3910,9 @@ static bool wma_is_extscan_in_progress(tp_wma_handle wma) CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) { struct wma_txrx_node *iface; - bool pno_in_progress = false; - uint8_t i, vdev_id = 0; - bool extscan_in_progress = false, pno_matched = false; - bool enable_wow = false; + bool connected = false, pno_in_progress = false; + uint8_t i; + bool extscan_in_progress = false; wma->no_of_suspend_ind++; @@ -3986,40 +3971,42 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) WMI_SERVICE_BEACON_OFFLOAD)) { WMA_LOGD("vdev %d is in beaconning mode, enabling wow", i); - enable_wow = true; + goto enable_wow; } } for (i = 0; i < wma->max_bssid; i++) { - if (wma->interfaces[i].conn_state) - enable_wow = true; + if (wma->interfaces[i].conn_state) { + connected = true; + break; + } #ifdef FEATURE_WLAN_SCAN_PNO if (wma->interfaces[i].pno_in_progress) { WMA_LOGD("PNO is in progress, enabling wow"); - enable_wow = true; pno_in_progress = true; - vdev_id = i; - if (wma->interfaces[i].nlo_match_evt_received) - pno_matched = true; break; } #endif /* FEATURE_WLAN_SCAN_PNO */ +#ifdef FEATURE_WLAN_EXTSCAN + if (wma->interfaces[i].extscan_in_progress) { + WMA_LOGD("Extscan is in progress, enabling wow"); + extscan_in_progress = true; + break; + } +#endif } - extscan_in_progress = wma_is_extscan_in_progress(wma); - if (extscan_in_progress) - enable_wow = true; - 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) { + if (!connected && !pno_in_progress && !extscan_in_progress) { WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); cdf_mem_free(info); goto send_ready_to_suspend; } +enable_wow: WMA_LOGE("WOW Suspend"); /* @@ -4041,11 +4028,6 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) } #endif /* FEATURE_WLAN_LPHB */ - if (pno_matched) - wma_enable_disable_wakeup_event(wma, vdev_id, - (1 << WOW_NLO_SCAN_COMPLETE_EVENT), - pno_matched); - wma->wow.wow_enable = true; wma->wow.wow_enable_cmd_sent = false; -- cgit v1.2.3 From 11667807b96dab5eef91c64ed01cf34716e25150 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Kalikot Veetil Date: Mon, 2 Nov 2015 15:35:10 -0800 Subject: qcacld-3.0: Add backward compatibiilty to older FW If DBS hwmode is not available from FW, return accrodingly in wma_get_hw_mode_from_idx. Change-Id: I603edd8a49bfd584300dcfc21c2b3c8c4c3c1892 CRs-Fixed: 934012 --- core/wma/src/wma_utils.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 5ab134190a24..c7b0a621fd6e 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -2797,6 +2797,11 @@ CDF_STATUS wma_get_hw_mode_from_idx(uint32_t idx, return CDF_STATUS_E_FAILURE; } + if (!wma->num_dbs_hw_modes) { + WMA_LOGE("%s: No dbs hw modes available", __func__); + return CDF_STATUS_E_FAILURE; + } + param = wma->hw_mode.hw_mode_list[idx]; hw_mode->mac0_tx_ss = WMI_DBS_HW_MODE_MAC0_TX_STREAMS_GET(param); -- cgit v1.2.3 From 234d3528b26b8d316552bdf0b9425ac26db64ebb Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Fri, 8 Jan 2016 11:58:15 -0800 Subject: qcacld-3.0: Use CDF APIs for spin lock sched_scan_lock and connection_status_lock's are using spin lock APIs directly from kernel. Change to use CDF APIs for spin lock. Change-Id: I0f56624df34682150b402fc36b9dfdba36a598f3 CRs-fixed: 959287 --- core/cds/src/cds_concurrency.c | 4 ++-- core/hdd/inc/wlan_hdd_main.h | 4 ++-- core/hdd/src/wlan_hdd_main.c | 4 ++-- core/hdd/src/wlan_hdd_power.c | 6 +++--- core/hdd/src/wlan_hdd_scan.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 8f9dfb072398..9242863e829c 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2026,7 +2026,7 @@ bool cds_set_connection_in_progress(bool value) return false; } - spin_lock(&hdd_ctx->connection_status_lock); + cdf_spin_lock(&hdd_ctx->connection_status_lock); /* * if the value is set to true previously and if someone is * trying to make it true again then it could be some race @@ -2037,7 +2037,7 @@ bool cds_set_connection_in_progress(bool value) status = false; else hdd_ctx->connection_in_progress = value; - spin_unlock(&hdd_ctx->connection_status_lock); + cdf_spin_unlock(&hdd_ctx->connection_status_lock); return status; } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 33776454ae7a..969c2f0aa64c 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1208,7 +1208,7 @@ struct hdd_context_s { /* Use below lock to protect access to isSchedScanUpdatePending * since it will be accessed in two different contexts. */ - spinlock_t schedScan_lock; + cdf_spinlock_t sched_scan_lock; /* Flag keeps track of wiphy suspend/resume */ bool isWiphySuspended; @@ -1325,7 +1325,7 @@ struct hdd_context_s { cdf_mc_timer_t dbs_opportunistic_timer; bool connection_in_progress; - spinlock_t connection_status_lock; + cdf_spinlock_t connection_status_lock; cdf_mutex_t hdd_conc_list_lock; uint16_t hdd_txrx_hist_idx; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 3906b8a6a677..98c560fc010c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4890,8 +4890,8 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) init_completion(&hdd_ctx->mc_sus_event_var); init_completion(&hdd_ctx->ready_to_suspend); - spin_lock_init(&hdd_ctx->schedScan_lock); - spin_lock_init(&hdd_ctx->connection_status_lock); + cdf_spinlock_init(&hdd_ctx->sched_scan_lock); + cdf_spinlock_init(&hdd_ctx->connection_status_lock); cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock); cdf_list_init(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index cf4944e93824..b7475f6f76a9 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1768,16 +1768,16 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_RESUME_WLAN, NO_SESSION, pHddCtx->isWiphySuspended)); - spin_lock(&pHddCtx->schedScan_lock); + cdf_spin_lock(&pHddCtx->sched_scan_lock); pHddCtx->isWiphySuspended = false; if (true != pHddCtx->isSchedScanUpdatePending) { - spin_unlock(&pHddCtx->schedScan_lock); + cdf_spin_unlock(&pHddCtx->sched_scan_lock); hddLog(LOG1, FL("Return resume is not due to PNO indication")); return 0; } /* Reset flag to avoid updatating cfg80211 data old results again */ pHddCtx->isSchedScanUpdatePending = false; - spin_unlock(&pHddCtx->schedScan_lock); + cdf_spin_unlock(&pHddCtx->sched_scan_lock); status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 1162fa3e9a54..46804353b39b 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1951,15 +1951,15 @@ hdd_sched_scan_callback(void *callbackContext, return; } - spin_lock(&pHddCtx->schedScan_lock); + cdf_spin_lock(&pHddCtx->sched_scan_lock); if (true == pHddCtx->isWiphySuspended) { pHddCtx->isSchedScanUpdatePending = true; - spin_unlock(&pHddCtx->schedScan_lock); + cdf_spin_unlock(&pHddCtx->sched_scan_lock); hddLog(LOG1, FL("Update cfg80211 scan database after it resume")); return; } - spin_unlock(&pHddCtx->schedScan_lock); + cdf_spin_unlock(&pHddCtx->sched_scan_lock); ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter, 0); -- cgit v1.2.3 From 5b2fe2d54d21e95f98847ef736ba6ce4b065dd7f Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 18 Dec 2015 15:54:59 +0530 Subject: qcacld-3.0: Fix build failure in cds module pRoamInfo is not initialized in cds_force_sap_on_scc function. This is resulting in build failure when FEATURE_WLAN_FORCE_SAP_SCC flag is enabled. Modify cds_force_sap_on_scc function to fix the same. CRs-Fixed: 953618 Change-Id: I136d33f108dab19c236c7bf1aadf7608c0673baf --- core/cds/inc/cds_concurrency.h | 6 ++++-- core/cds/src/cds_concurrency.c | 8 +++++--- core/hdd/src/wlan_hdd_assoc.c | 8 +++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index f7e37d5e8afc..c5c30e2389fd 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -499,9 +499,11 @@ bool cds_check_for_session_conc(uint8_t session_id, uint8_t channel); CDF_STATUS cds_handle_conc_multiport(uint8_t session_id, uint8_t channel); #ifdef FEATURE_WLAN_FORCE_SAP_SCC -void cds_force_sap_on_scc(eCsrRoamResult roam_result); +void cds_force_sap_on_scc(eCsrRoamResult roam_result, + uint8_t channel_id); #else -static inline void cds_force_sap_on_scc(eCsrRoamResult roam_result) +static inline void cds_force_sap_on_scc(eCsrRoamResult roam_result, + uint8_t channel_id) { } diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 9242863e829c..f7bf7f0e64cf 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -6556,13 +6556,15 @@ void cds_restart_softap(hdd_adapter_t *pHostapdAdapter) /** * cds_force_sap_on_scc() - Force SAP on SCC * @roam_result: Roam result + * @channel_id: STA channel id * * Restarts SAP on SCC if its operating channel is different from that of the * STA-AP interface * * Return: None */ -void cds_force_sap_on_scc(eCsrRoamResult roam_result) +void cds_force_sap_on_scc(eCsrRoamResult roam_result, + uint8_t channel_id) { hdd_adapter_t *hostapd_adapter; hdd_context_t *hdd_ctx; @@ -6584,10 +6586,10 @@ void cds_force_sap_on_scc(eCsrRoamResult roam_result) * from AP channel. */ if (hostapd_adapter->sessionCtx.ap.operatingChannel != - pRoamInfo->pBssDesc->channelId) { + channel_id) { cds_err("Restart SAP: SAP channel-%d, STA channel-%d", hostapd_adapter->sessionCtx.ap.operatingChannel, - pRoamInfo->pBssDesc->channelId); + channel_id); cds_restart_softap(hostapd_adapter); } } diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 6d124107945e..d9808e883fcb 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -2333,7 +2333,13 @@ defined(FEATURE_WLAN_LFR) roamResult, pHddStaCtx)) return CDF_STATUS_E_FAILURE; - cds_force_sap_on_scc(roamResult); + if (NULL != pRoamInfo && NULL != pRoamInfo->pBssDesc) { + cds_force_sap_on_scc(roamResult, + pRoamInfo->pBssDesc->channelId); + } else { + hdd_err("pRoamInfo profile is not set properly"); + return CDF_STATUS_E_FAILURE; + } return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From f83551419ef46540ba3c3ab4a131e87b7823a0c4 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 15 Dec 2015 17:15:45 -0800 Subject: qcacld-3.0: Save call stack for each memory allocation in SLUB builds qcacld-2.0 to qcacld-3.0 propagation Currently only one level of information (file name and line number of the caller who wants to allocate memory) is saved when each memory is allocated. This may not be able to provide enough information for some cases that multiple levels of callers are the same. Hence save call stack as well for each memory allocation in SLUB builds for debug purpose. Change-Id: I245d53ec3805217ca34d7c1f5e31b84cac73e395 CRs-fixed: 930557 --- core/cdf/src/cdf_memory.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/core/cdf/src/cdf_memory.c b/core/cdf/src/cdf_memory.c index f32c56620f7f..874f5fb7a8fe 100644 --- a/core/cdf/src/cdf_memory.c +++ b/core/cdf/src/cdf_memory.c @@ -48,6 +48,7 @@ #ifdef MEMORY_DEBUG #include +#include cdf_list_t cdf_mem_list; cdf_spinlock_t cdf_mem_list_lock; @@ -57,11 +58,17 @@ static uint8_t WLAN_MEM_HEADER[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, static uint8_t WLAN_MEM_TAIL[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 }; +#define CDF_MEM_MAX_STACK_TRACE 16 + struct s_cdf_mem_struct { cdf_list_node_t pNode; char *fileName; unsigned int lineNum; unsigned int size; +#ifdef WLAN_OPEN_SOURCE + unsigned long stack_trace[CDF_MEM_MAX_STACK_TRACE]; + struct stack_trace trace; +#endif uint8_t header[8]; }; #endif @@ -75,6 +82,51 @@ struct s_cdf_mem_struct { /* External Function implementation */ #ifdef MEMORY_DEBUG +#ifdef WLAN_OPEN_SOURCE +/** + * cdf_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 cdf_mem_save_stack_trace(struct s_cdf_mem_struct *mem_struct) +{ + struct stack_trace *trace = &mem_struct->trace; + + trace->nr_entries = 0; + trace->max_entries = CDF_MEM_MAX_STACK_TRACE; + trace->entries = mem_struct->stack_trace; + trace->skip = 2; + + save_stack_trace(trace); +} + +/** + * cdf_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 cdf_mem_print_stack_trace(struct s_cdf_mem_struct + *mem_struct) +{ + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL, + "Call stack for the source of leaked memory:"); + + print_stack_trace(&mem_struct->trace, 1); +} +#else +static inline void cdf_mem_save_stack_trace(struct s_cdf_mem_struct *mem_struct) +{ + +} +static inline void cdf_mem_print_stack_trace(struct s_cdf_mem_struct + *mem_struct) +{ + +} +#endif /** * cdf_mem_init() - initialize cdf memory debug functionality @@ -144,6 +196,7 @@ void cdf_mem_clean(void) mleak_cnt = 0; } mleak_cnt++; + cdf_mem_print_stack_trace(memStruct); kfree((void *)memStruct); } } while (cdf_status == CDF_STATUS_SUCCESS); @@ -240,6 +293,7 @@ void *cdf_mem_malloc_debug(size_t size, char *fileName, uint32_t lineNum) memStruct->fileName = fileName; memStruct->lineNum = lineNum; memStruct->size = size; + cdf_mem_save_stack_trace(memStruct); cdf_mem_copy(&memStruct->header[0], &WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER)); -- cgit v1.2.3 From 24cc9e05c834c8602ae7bb8788e253cc2c396149 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 12 Jan 2016 18:43:54 -0800 Subject: qcacld-3.0: Fix potential memory leaks in SSR qcacld-2.0 to qcacld-3.0 propagation During SSR, since VDEV detach won't happen, some contexts saved in VDEV may not get a chance to be freed. Add change to check these contexts in SSR shutdown routine to make sure they are freed. Change-Id: I36d12b3bb524ca107ece2441c1dc1d80293cb31b CRs-fixed: 957587 --- core/wma/src/wma_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 26b633515483..95cc3aa87e29 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2951,6 +2951,17 @@ CDF_STATUS wma_wmi_service_close(void *cds_ctx) cdf_mem_free(wma_handle->interfaces[i].handle); wma_handle->interfaces[i].handle = NULL; } + + if (wma_handle->interfaces[i].addBssStaContext) { + cdf_mem_free(wma_handle-> + interfaces[i].addBssStaContext); + wma_handle->interfaces[i].addBssStaContext = NULL; + } + + if (wma_handle->interfaces[i].del_staself_req) { + cdf_mem_free(wma_handle->interfaces[i].del_staself_req); + wma_handle->interfaces[i].del_staself_req = NULL; + } } cdf_mem_free(wma_handle->interfaces); -- cgit v1.2.3 From 663679ed08ff63fc27f608e68844c0a84f78a675 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Thu, 14 Jan 2016 13:38:00 -0800 Subject: Release 5.0.0.157 Release 5.0.0.157 Change-Id: If54fac1194de693983bf4f0744fb11dfffdeb7ba CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 1868305a54c7..3108f2203ad8 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 156 +#define QWLAN_VERSION_BUILD 157 -#define QWLAN_VERSIONSTR "5.0.0.156" +#define QWLAN_VERSIONSTR "5.0.0.157" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From dad871f574d740094710e6778cde48a8cd7acc24 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Thu, 24 Dec 2015 18:14:02 -0800 Subject: qcacld-3.0: Optimize LFR3 roam synch propagation The current roam sync propagation for LFR3.0 in the host driver is based on queuing and message processing mechanism. This can lead to many unknown sequence of operations as there might be other messages sitting in the queue which may interrupt with this operation. Hence, it would be good to introduce a callback mechanism which take care of running the code to execution completely in case of roam synch propagation. It also improves to reduce the roam delay by 50 percent as compared to the existing mechanism. CRs-Fixed: 962290 Change-Id: I4af569b1e3020a64beb606e8bbffd7613775138f --- core/hdd/inc/wlan_hdd_assoc.h | 11 +- core/hdd/src/wlan_hdd_assoc.c | 38 +- core/mac/inc/sir_api.h | 8 + core/mac/inc/wni_api.h | 1 - core/mac/src/pe/include/lim_api.h | 13 +- core/mac/src/pe/lim/lim_api.c | 304 +++++++----- core/mac/src/pe/lim/lim_assoc_utils.c | 11 +- core/mac/src/pe/lim/lim_assoc_utils.h | 7 +- core/mac/src/pe/lim/lim_ft.c | 30 +- core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c | 15 +- core/mac/src/pe/lim/lim_process_message_queue.c | 7 - core/mac/src/pe/lim/lim_process_sme_req_messages.c | 6 +- core/mac/src/pe/lim/lim_process_tdls.c | 4 +- core/mac/src/sys/legacy/src/utils/src/mac_trace.c | 4 - core/sme/inc/csr_api.h | 8 + core/sme/inc/csr_internal.h | 10 +- core/sme/inc/csr_neighbor_roam.h | 7 +- core/sme/src/common/sme_api.c | 6 +- core/sme/src/csr/csr_api_roam.c | 523 +++++++++++++-------- core/sme/src/csr/csr_api_scan.c | 5 +- core/sme/src/csr/csr_neighbor_roam.c | 18 +- core/sme/src/qos/sme_qos.c | 26 +- core/wma/inc/wma.h | 8 +- core/wma/inc/wma_internal.h | 14 +- core/wma/inc/wma_types.h | 11 +- core/wma/src/wma_data.c | 9 +- core/wma/src/wma_dev_if.c | 45 +- core/wma/src/wma_main.c | 5 - core/wma/src/wma_mgmt.c | 31 ++ core/wma/src/wma_scan_roam.c | 270 +++++++---- 30 files changed, 917 insertions(+), 538 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index b9a95785e119..3549c7b2d5e1 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -252,4 +252,13 @@ CDF_STATUS hdd_change_peer_state(hdd_adapter_t *pAdapter, uint8_t sta_id, enum ol_txrx_peer_state sta_state, bool roam_synch_in_progress); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +bool hdd_is_roam_sync_in_progress(tCsrRoamInfo *roaminfo); +#else +static inline bool hdd_is_roam_sync_in_progress(tCsrRoamInfo *roaminfo) +{ + return false; +} +#endif + #endif diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index d9808e883fcb..cdd34a79f3a7 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -730,8 +730,9 @@ static void hdd_send_association_event(struct net_device *dev, return; } - cds_incr_active_session(pAdapter->device_mode, - pAdapter->sessionId); + if (!hdd_is_roam_sync_in_progress(pCsrRoamInfo)) + cds_incr_active_session(pAdapter->device_mode, + pAdapter->sessionId); memcpy(wrqu.ap_addr.sa_data, pCsrRoamInfo->pBssDesc->bssId, sizeof(pCsrRoamInfo->pBssDesc->bssId)); @@ -1415,7 +1416,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev, * active session count should still be the same and hence upon * successful reassoc decrement the active session count here. */ - cds_decr_session_set_pcl(pAdapter->device_mode, pAdapter->sessionId); + if (!hdd_is_roam_sync_in_progress(pCsrRoamInfo)) + cds_decr_session_set_pcl( + pAdapter->device_mode, + pAdapter->sessionId); /* Send the Assoc Resp, the supplicant needs this for initial Auth */ len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; @@ -1485,18 +1489,17 @@ done: /** * hdd_is_roam_sync_in_progress()- Check if roam offloaded + * @roaminfo - Roaming Information * * 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) +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; + if (roaminfo) + return roaminfo->roamSynchInProgress; + else + return false; } #endif @@ -1724,13 +1727,6 @@ defined(WLAN_FEATURE_VOWIFI_11R) return CDF_STATUS_E_FAILURE; } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (pRoamInfo && pRoamInfo->roamSynchInProgress) { - /* change logging before release */ - hddLog(LOG3, "LFR3:hdd_association_completion_handler"); - } -#endif - /* HDD has initiated disconnect, do not send connect result indication * to kernel as it will be handled by __cfg80211_disconnect. */ @@ -1961,9 +1957,11 @@ defined(FEATURE_WLAN_LFR) * decrement the active session * count here. */ - cds_decr_session_set_pcl - (pAdapter->device_mode, - pAdapter->sessionId); + if (!hdd_is_roam_sync_in_progress + (pRoamInfo)) + cds_decr_session_set_pcl + (pAdapter->device_mode, + pAdapter->sessionId); hddLog(LOG1, FL("ft_carrier_on is %d, sending roamed indication"), ft_carrier_on); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 149f36116f4a..bd2853f875ff 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -162,6 +162,9 @@ typedef enum { #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) + +#define ROAM_SYNCH_PROPAGATION 1 +#define ROAMING_TX_QUEUE_DISABLE 2 #endif /** @@ -423,6 +426,8 @@ typedef struct sSirSmeReadyReq { uint16_t length; uint16_t transactionId; void *add_bssdescr_cb; + void *csr_roam_synch_cb; + void *pe_roam_synch_cb; } tSirSmeReadyReq, *tpSirSmeReadyReq; /** @@ -3953,6 +3958,9 @@ typedef struct sSirSmeRoamOffloadSynchInd { uint8_t kck[SIR_KCK_KEY_LEN]; uint8_t kek[SIR_KEK_KEY_LEN]; uint8_t replay_ctr[SIR_REPLAY_CTR_LEN]; + void *add_bss_params; + tpSirSmeJoinRsp join_rsp; + uint16_t aid; tpSirBssDescription bss_desc_ptr; } roam_offload_synch_ind; diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 12b874d5f02b..64235814b2e9 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -213,7 +213,6 @@ enum eWniMsgTypes { 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 diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index 99e2fc7376cc..bf612454958f 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -169,7 +169,9 @@ bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info); #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD -void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg); +CDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, + struct sSirSmeRoamOffloadSynchInd *roam_sync_ind_ptr, + tpSirBssDescription bss_desc_ptr); #endif #define limGetQosMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limQosEnabled) #define limGetWmeMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWmeEnabled) @@ -246,6 +248,13 @@ void lim_process_abort_scan_ind(tpAniSirGlobal pMac, uint8_t sessionId, uint32_t scan_id); void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal, uint32_t, uint32_t *); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +void lim_fill_join_rsp_ht_caps(tpPESession session, tpSirSmeJoinRsp rsp); +#else +static inline void lim_fill_join_rsp_ht_caps(tpPESession session, + tpSirSmeJoinRsp rsp) +{} +#endif /************************************************************/ #endif /* __LIM_API_H */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index c7bf4239c2af..14fcfb71cc21 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1076,10 +1076,11 @@ CDF_STATUS pe_handle_mgmt_frame(void *p_cds_gctx, void *cds_buff) /** * pe_register_wma_handle() - register management frame handler to WMA * @pMac: mac global ctx + * @ready_req: Ready request parameters * * Return: None */ -void pe_register_wma_handle(tpAniSirGlobal pMac) +void pe_register_wma_handle(tpAniSirGlobal pMac, tSirSmeReadyReq *ready_req) { void *p_cds_gctx; CDF_STATUS retStatus; @@ -1092,6 +1093,12 @@ void pe_register_wma_handle(tpAniSirGlobal pMac) lim_log(pMac, LOGP, FL("Registering the PE Handle with WMA has failed")); + retStatus = wma_register_roaming_callbacks(p_cds_gctx, + ready_req->csr_roam_synch_cb, + ready_req->pe_roam_synch_cb); + if (retStatus != CDF_STATUS_SUCCESS) + lim_log(pMac, LOGP, + FL("Registering roaming callbacks with WMA failed")); } /** @@ -1791,15 +1798,54 @@ void lim_ps_offload_handle_missed_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg return; } +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH +/** + * lim_fill_join_rsp_ht_caps() - Fill the HT caps in join response + * @session: PE Session + * @join_rsp: Join response buffer to be filled up. + * + * Return: None + */ +void lim_fill_join_rsp_ht_caps(tpPESession session, tpSirSmeJoinRsp join_rsp) +{ + tSirSmeHTProfile *ht_profile; + if (session == NULL) { + lim_log(mac_ctx, LOGE, FL("Invalid Session")); + return; + } + if (join_rsp == NULL) { + lim_log(mac_ctx, LOGE, FL("Invalid Join Response")); + return; + } + if (session->cc_switch_mode != + CDF_MCC_TO_SCC_SWITCH_DISABLE) { + ht_profile = &join_rsp->HTProfile; + ht_profile->htSupportedChannelWidthSet = + session->htSupportedChannelWidthSet; + ht_profile->htRecommendedTxWidthSet = + session->htRecommendedTxWidthSet; + ht_profile->htSecondaryChannelOffset = + session->htSecondaryChannelOffset; + ht_profile->dot11mode = session->dot11mode; + ht_profile->htCapability = session->htCapability; + } + ht_profile->vhtCapability = session->vhtCapability; + ht_profile->vhtTxChannelWidthSet = + session->vhtTxChannelWidthSet; + ht_profile->apCenterChan = session->ch_center_freq_seg0; + ht_profile->apChanWidth = session->ch_width; +} +#endif + #ifdef WLAN_FEATURE_ROAM_OFFLOAD CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac, - roam_offload_synch_ind *roam_offload_synch_ind_ptr) + roam_offload_synch_ind *roam_offload_synch_ind_ptr, + tpSirBssDescription bss_desc_ptr) { uint32_t ie_len = 0; tpSirProbeRespBeacon parsed_frm_ptr; tpSirMacMgmtHdr mac_hdr; uint8_t *bcn_proberesp_ptr; - tSirBssDescription *bss_desc_ptr = NULL; bcn_proberesp_ptr = (uint8_t *)roam_offload_synch_ind_ptr + roam_offload_synch_ind_ptr->beaconProbeRespOffset; @@ -1821,7 +1867,7 @@ CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac, } CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, - "LFR3: Beacon/Prb Rsp:"); + "LFR3:Beacon/Prb Rsp:%d", roam_offload_synch_ind_ptr->isBeacon); CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO, bcn_proberesp_ptr, roam_offload_synch_ind_ptr->beaconProbeRespLength); if (roam_offload_synch_ind_ptr->isBeacon) { @@ -1856,20 +1902,6 @@ CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac, ie_len = roam_offload_synch_ind_ptr->beaconProbeRespLength - (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); } - /* - * Memory allocated below is freed up in csrProcessRoamOffloadSynchInd - */ - roam_offload_synch_ind_ptr->bss_desc_ptr = - cdf_mem_malloc(sizeof (tSirBssDescription) + ie_len); - bss_desc_ptr = roam_offload_synch_ind_ptr->bss_desc_ptr; - if (NULL == bss_desc_ptr) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3:Failed to allocate memory"); - CDF_ASSERT(bss_desc_ptr != NULL); - return CDF_STATUS_E_NOMEM; - } - cdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription)); - /* * Length of BSS desription is without length of * length itself and length of pointer @@ -1955,129 +1987,159 @@ CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac, cdf_mem_free(parsed_frm_ptr); return CDF_STATUS_SUCCESS; } - -/**----------------------------------------------------------------- - * brief lim_roam_offload_synch_ind() - Handles Roam Synch Indication - * param pMac - global mac structure - * return - none - *----------------------------------------------------------------- - **/ -void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) +/** + * pe_roam_synch_callback() - PE level callback for roam synch propagation + * @mac_ctx: MAC Context + * @roam_sync_ind_ptr: Roam synch indication buffer pointer + * @bss_desc: BSS Descriptor pointer + * + * This is a PE level callback called from WMA to complete the roam synch + * propagation at PE level and also fill the BSS descriptor which will be + * helpful further to complete the roam synch propagation. + * + * Return: Success or Failure status + */ +CDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, + roam_offload_synch_ind *roam_sync_ind_ptr, + tpSirBssDescription bss_desc) { tpPESession session_ptr; tpPESession ft_session_ptr; uint8_t session_id; - tSirMsgQ mmh_msg; - tSirBssDescription *bss_desc_ptr = NULL; - roam_offload_synch_ind *roam_sync_ind_ptr = - (roam_offload_synch_ind *)pMsg->bodyptr; + tpDphHashNode curr_sta_ds; + uint16_t aid; + tpAddBssParams add_bss_params; + uint8_t local_nss; + CDF_STATUS status = CDF_STATUS_E_FAILURE; if (!roam_sync_ind_ptr) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3:%s:roam_sync_ind_ptr is NULL", __func__); - return; + lim_log(mac_ctx, LOGE, FL("LFR3:roam_sync_ind_ptr is NULL")); + return status; } - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3: Received WMA_ROAM_OFFLOAD_SYNCH_IND"); - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, - "LFR3:%s:authStatus=%d, vdevId=%d", __func__, - roam_sync_ind_ptr->authStatus, - roam_sync_ind_ptr->roamedVdevId); - CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, - roam_sync_ind_ptr->bssid.bytes, CDF_MAC_ADDR_SIZE); - session_ptr = pe_find_session_by_bss_idx(pMac, - roam_sync_ind_ptr->roamedVdevId); + lim_log(mac_ctx, LOGE, FL("LFR3:Received WMA_ROAM_OFFLOAD_SYNCH_IND")); + lim_log(mac_ctx, CDF_TRACE_LEVEL_DEBUG, FL("LFR3:auth=%d, vdevId=%d"), + roam_sync_ind_ptr->authStatus, roam_sync_ind_ptr->roamedVdevId); + lim_print_mac_addr(mac_ctx, roam_sync_ind_ptr->bssid.bytes, + CDF_TRACE_LEVEL_DEBUG); + session_ptr = pe_find_session_by_sme_session_id(mac_ctx, + roam_sync_ind_ptr->roamedVdevId); if (session_ptr == NULL) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "%s: LFR3:Unable to find session", __func__); - return; + lim_log(mac_ctx, LOGE, FL("LFR3:Unable to find session")); + return status; } - /* Nothing to be done if the session is not in STA mode */ if (!LIM_IS_STA_ROLE(session_ptr)) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "session is not in STA mode"); - return; + lim_log(mac_ctx, LOGE, FL("LFR3:session is not in STA mode")); + return status; } - if (!CDF_IS_STATUS_SUCCESS(lim_roam_fill_bss_descr(pMac, - roam_sync_ind_ptr))) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3:%s:Failed to fill Bss Descr", __func__); - return; + status = lim_roam_fill_bss_descr(mac_ctx, roam_sync_ind_ptr, bss_desc); + if (!CDF_IS_STATUS_SUCCESS(status)) { + lim_log(mac_ctx, LOGE, FL("LFR3:Failed to fill Bss Descr")); + return status; } - bss_desc_ptr = roam_sync_ind_ptr->bss_desc_ptr; - ft_session_ptr = pe_create_session(pMac, bss_desc_ptr->bssId, - &session_id, pMac->lim.maxStation, - eSIR_INFRASTRUCTURE_MODE); + status = CDF_STATUS_E_FAILURE; + ft_session_ptr = pe_create_session(mac_ctx, bss_desc->bssId, + &session_id, mac_ctx->lim.maxStation, + eSIR_INFRASTRUCTURE_MODE); if (ft_session_ptr == NULL) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3: Session Can't be created for new AP during Roam Synch"); - lim_print_mac_addr(pMac, bss_desc_ptr->bssId, LOGE); - return; + lim_log(mac_ctx, LOGE, FL("LFR3:Cannot create PE Session")); + lim_print_mac_addr(mac_ctx, bss_desc->bssId, LOGE); + return status; } ft_session_ptr->peSessionId = session_id; sir_copy_mac_addr(ft_session_ptr->selfMacAddr, session_ptr->selfMacAddr); - sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc_ptr->bssId); + sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc->bssId); ft_session_ptr->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 - **/ + session_ptr->bRoamSynchInProgress = true; ft_session_ptr->bRoamSynchInProgress = true; - - if (ft_session_ptr->bssType == eSIR_INFRASTRUCTURE_MODE) { - ft_session_ptr->limSystemRole = eLIM_STA_ROLE; - } else { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3:Invalid bss type"); - return; + ft_session_ptr->limSystemRole = eLIM_STA_ROLE; + sir_copy_mac_addr(session_ptr->limReAssocbssId, bss_desc->bssId); + ft_session_ptr->csaOffloadEnable = session_ptr->csaOffloadEnable; + + lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr, session_ptr); + lim_ft_prepare_add_bss_req(mac_ctx, false, ft_session_ptr, bss_desc); + roam_sync_ind_ptr->add_bss_params = + (tpAddBssParams) ft_session_ptr->ftPEContext.pAddBssReq; + add_bss_params = ft_session_ptr->ftPEContext.pAddBssReq; + lim_delete_tdls_peers(mac_ctx, session_ptr); + curr_sta_ds = dph_lookup_hash_entry(mac_ctx, session_ptr->bssId, + &aid, &session_ptr->dph.dphHashTable); + local_nss = curr_sta_ds->nss; + session_ptr->limSmeState = eLIM_SME_IDLE_STATE; + lim_cleanup_rx_path(mac_ctx, curr_sta_ds, session_ptr); + lim_delete_dph_hash_entry(mac_ctx, curr_sta_ds->staAddr, + aid, session_ptr); + pe_delete_session(mac_ctx, session_ptr); + session_ptr = NULL; + ft_session_ptr->nss = local_nss; + curr_sta_ds = dph_add_hash_entry(mac_ctx, + roam_sync_ind_ptr->bssid.bytes, DPH_STA_HASH_INDEX_PEER, + &ft_session_ptr->dph.dphHashTable); + if (curr_sta_ds == NULL) { + lim_log(mac_ctx, LOGE, FL("LFR3:failed to add hash entry for")); + lim_print_mac_addr(mac_ctx, + add_bss_params->staContext.staMac, LOGE); + ft_session_ptr->bRoamSynchInProgress = false; + return status; } - ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState; - ft_session_ptr->limSmeState = eLIM_SME_WT_REASSOC_STATE; - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, - "LFR3:%s:created session (%p) with id = %d", - __func__, ft_session_ptr, ft_session_ptr->peSessionId); - /* Update the ReAssoc BSSID of the current session */ - sir_copy_mac_addr(session_ptr->limReAssocbssId, bss_desc_ptr->bssId); - lim_print_mac_addr(pMac, session_ptr->limReAssocbssId, LOG2); - - /* Prepare the session right now with as much as possible */ - lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr); - - if (roam_sync_ind_ptr->reassoc_req_length) { - /* - * For LFR3 the Assoc Request frame was sent by firmware, hence - * pe session struct does not have corresponding IEs. Firmware - * sends whole ASSOC req frame upto host in Roam Sync Event. - * Copy this frame pe session's buffer, so that it can follow - * LFR2 code path to send them to supplicant. - */ - ft_session_ptr->assocReqLen = - roam_sync_ind_ptr->reassoc_req_length - - SIR_MAC_HDR_LEN_3A - SIR_MAC_REASSOC_SSID_OFFSET; - ft_session_ptr->assocReq = - cdf_mem_malloc(ft_session_ptr->assocReqLen); - if (NULL == ft_session_ptr->assocReq) { - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, - "LFR3: Failed to alloc memory for Assoc Req"); - return; - } - cdf_mem_copy(ft_session_ptr->assocReq, - (uint8_t *)roam_sync_ind_ptr + - roam_sync_ind_ptr->reassoc_req_offset + - SIR_MAC_HDR_LEN_3A + SIR_MAC_REASSOC_SSID_OFFSET, - ft_session_ptr->assocReqLen); - } - lim_ft_prepare_add_bss_req(pMac, false, ft_session_ptr, bss_desc_ptr); - mmh_msg.type = - roam_sync_ind_ptr->messageType; - /* eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */ - mmh_msg.bodyptr = roam_sync_ind_ptr; - mmh_msg.bodyval = 0; + ft_session_ptr->bssIdx = (uint8_t) add_bss_params->bssIdx; + + curr_sta_ds->bssId = add_bss_params->bssIdx; + curr_sta_ds->staIndex = + add_bss_params->staContext.staIdx; + curr_sta_ds->ucUcastSig = + add_bss_params->staContext.ucUcastSig; + curr_sta_ds->ucBcastSig = + add_bss_params->staContext.ucBcastSig; + rrm_cache_mgmt_tx_power(mac_ctx, + add_bss_params->txMgmtPower, ft_session_ptr); + mac_ctx->roam.reassocRespLen = roam_sync_ind_ptr->reassocRespLength; + mac_ctx->roam.pReassocResp = + cdf_mem_malloc(mac_ctx->roam.reassocRespLen); + if (NULL == mac_ctx->roam.pReassocResp) { + lim_log(mac_ctx, LOGE, FL("LFR3:assoc resp mem alloc failed")); + ft_session_ptr->bRoamSynchInProgress = false; + return CDF_STATUS_E_NOMEM; + } + cdf_mem_copy(mac_ctx->roam.pReassocResp, + (uint8_t *)roam_sync_ind_ptr + + roam_sync_ind_ptr->reassocRespOffset, + mac_ctx->roam.reassocRespLen); - CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG, - "LFR3:%s:sending eWNI_SME_ROAM_OFFLOAD_SYNCH_IND", __func__); - lim_sys_process_mmh_msg_api(pMac, &mmh_msg, ePROT); + lim_log(mac_ctx, LOG1, FL("LFR3:the reassoc resp frame data:")); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + mac_ctx->roam.pReassocResp, + mac_ctx->roam.reassocRespLen); + ft_session_ptr->bRoamSynchInProgress = true; + lim_process_assoc_rsp_frame(mac_ctx, mac_ctx->roam.pReassocResp, + LIM_REASSOC, ft_session_ptr); + roam_sync_ind_ptr->aid = ft_session_ptr->limAID; + curr_sta_ds->mlmStaContext.mlmState = + eLIM_MLM_LINK_ESTABLISHED_STATE; + curr_sta_ds->nss = local_nss; + ft_session_ptr->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + lim_init_tdls_data(mac_ctx, ft_session_ptr); + roam_sync_ind_ptr->join_rsp->vht_channel_width = + ft_session_ptr->ch_width; + roam_sync_ind_ptr->join_rsp->staId = curr_sta_ds->staIndex; + roam_sync_ind_ptr->join_rsp->ucastSig = curr_sta_ds->ucUcastSig; + roam_sync_ind_ptr->join_rsp->bcastSig = curr_sta_ds->ucBcastSig; + roam_sync_ind_ptr->join_rsp->timingMeasCap = curr_sta_ds->timingMeasCap; + roam_sync_ind_ptr->join_rsp->nss = curr_sta_ds->nss; + roam_sync_ind_ptr->join_rsp->max_rate_flags = + lim_get_max_rate_flags(mac_ctx, curr_sta_ds); + roam_sync_ind_ptr->join_rsp->tdls_prohibited = + ft_session_ptr->tdls_prohibited; + roam_sync_ind_ptr->join_rsp->tdls_chan_swit_prohibited = + ft_session_ptr->tdls_chan_swit_prohibited; + roam_sync_ind_ptr->join_rsp->aid = ft_session_ptr->limAID; + lim_fill_join_rsp_ht_caps(ft_session_ptr, roam_sync_ind_ptr->join_rsp); + ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState; + ft_session_ptr->limSmeState = eLIM_SME_LINK_EST_STATE; + ft_session_ptr->bRoamSynchInProgress = false; + if (mac_ctx->roam.pReassocResp) + cdf_mem_free(mac_ctx->roam.pReassocResp); + mac_ctx->roam.pReassocResp = NULL; + return CDF_STATUS_SUCCESS; } #endif diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 3cd37489f05a..3c47c79b0cd9 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -646,6 +646,10 @@ lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, * releases those BDs */ pStaDs->valid = 0; + lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); + /* Any roaming related changes should be above this line */ + if (psessionEntry->bRoamSynchInProgress) + return eSIR_SUCCESS; pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; if (LIM_IS_STA_ROLE(psessionEntry) || @@ -660,11 +664,6 @@ lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, pMac->lim.gLastBeaconDtimCount = 0; pMac->lim.gLastBeaconDtimPeriod = 0; -#ifdef FEATURE_WLAN_ESE -#ifdef FEATURE_WLAN_ESE_UPLOAD - lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0); -#endif /* FEATURE_WLAN_ESE_UPLOAD */ -#endif } #ifdef WLAN_DEBUG diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h index b9efbff3c842..f869ad3b7fa9 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.h +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -207,6 +207,11 @@ void lim_send_sme_unprotected_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameT #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) void lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, tpPESession psessionEntry, uint8_t tid, uint8_t state, uint16_t measInterval); +#else +static inline void lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, + tpPESession psessionEntry, uint8_t tid, + uint8_t state, uint16_t measInterval) +{} #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ #endif /* __LIM_ASSOC_UTILS_H */ diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index ffab46808c22..72784141a56a 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -813,11 +813,14 @@ tSirRetStatus lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac, pAddBssParams->sessionId = pftSessionEntry->peSessionId; /* Set a new state for MLME */ - - pftSessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE; - MTRACE(mac_trace - (pMac, TRACE_CODE_MLM_STATE, pftSessionEntry->peSessionId, - eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE)); + if (!pftSessionEntry->bRoamSynchInProgress) { + pftSessionEntry->limMlmState = + eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE; + MTRACE(mac_trace + (pMac, TRACE_CODE_MLM_STATE, + pftSessionEntry->peSessionId, + eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE)); + } pAddBssParams->halPersona = (uint8_t) pftSessionEntry->pePersona; pftSessionEntry->ftPEContext.pAddBssReq = pAddBssParams; @@ -1040,13 +1043,14 @@ void lim_fill_ft_session(tpAniSirGlobal pMac, regMax, localPowerConstraint, pMac->roam.configParam.nTxPowerCap, pftSessionEntry->maxTxPower); #endif - - pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; - pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; - MTRACE(mac_trace - (pMac, TRACE_CODE_SME_STATE, pftSessionEntry->peSessionId, - pftSessionEntry->limSmeState)); - + if (!psessionEntry->bRoamSynchInProgress) { + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + MTRACE(mac_trace(pMac, + TRACE_CODE_SME_STATE, + pftSessionEntry->peSessionId, + pftSessionEntry->limSmeState)); + } pftSessionEntry->encryptType = psessionEntry->encryptType; #ifdef WLAN_FEATURE_11W pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled; diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 8e0ed5a1ab33..336460fb8233 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -646,6 +646,7 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, if (((subtype == LIM_ASSOC) && (session_entry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) || ((subtype == LIM_REASSOC) && + !session_entry->bRoamSynchInProgress && ((session_entry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) && (session_entry->limMlmState != @@ -917,7 +918,8 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, #endif if (!((session_entry->bssType == eSIR_BTAMP_STA_MODE) || ((session_entry->bssType == eSIR_BTAMP_AP_MODE) && - LIM_IS_BT_AMP_STA_ROLE(session_entry)))) { + LIM_IS_BT_AMP_STA_ROLE(session_entry)) || + session_entry->bRoamSynchInProgress)) { if (lim_set_link_state (mac_ctx, eSIR_LINK_POSTASSOC_STATE, session_entry->bssId, @@ -972,8 +974,9 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, goto assocReject; } #if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) - if (session_entry->limMlmState == - eLIM_MLM_WT_FT_REASSOC_RSP_STATE) { + if ((session_entry->limMlmState == + eLIM_MLM_WT_FT_REASSOC_RSP_STATE) || + session_entry->bRoamSynchInProgress) { #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG lim_log(mac_ctx, LOG1, FL("Sending self sta")); #endif @@ -992,11 +995,11 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx, lim_send_edca_params(mac_ctx, session_entry->gLimEdcaParamsActive, sta_ds->bssId); + lim_add_ft_sta_self(mac_ctx, (assoc_rsp->aid & 0x3FFF), + session_entry); #ifdef WLAN_FEATURE_ROAM_OFFLOAD } #endif - lim_add_ft_sta_self(mac_ctx, (assoc_rsp->aid & 0x3FFF), - session_entry); cdf_mem_free(beacon); return; } diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index aa73bca79dfa..bb731323dbdf 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1503,13 +1503,6 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) cdf_mem_free(msg->bodyptr); msg->bodyptr = NULL; break; -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - case WMA_ROAM_OFFLOAD_SYNCH_IND: - lim_roam_offload_synch_ind(mac_ctx, msg); - /* bodyPtr is freed after handling - * eWNI_SME_ROAM_OFFLOAD_SYNCH_IND in sme_ProcessMsg */ - break; -#endif case SIR_LIM_ADDTS_RSP_TIMEOUT: lim_process_sme_req_messages(mac_ctx, msg); break; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 03121a6019fe..da1d9b60001c 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -113,7 +113,8 @@ static void lim_process_modify_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg); static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg); -extern void pe_register_wma_handle(tpAniSirGlobal pMac); +extern void pe_register_wma_handle(tpAniSirGlobal pMac, + tSirSmeReadyReq *ready_req); static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t *msg); @@ -483,7 +484,8 @@ static bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal pMac, uint32_t *pMsgB msg.bodyval = 0; if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { - pe_register_wma_handle(pMac); + ready_req->pe_roam_synch_cb = pe_roam_synch_callback; + pe_register_wma_handle(pMac, ready_req); pMac->lim.add_bssdescr_callback = ready_req->add_bssdescr_cb; } PELOGW(lim_log(pMac, LOGW, FL("sending WMA_SYS_READY_IND msg to HAL"));) diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 7cb5eb1d8bb2..bbabde1c834f 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3272,6 +3272,8 @@ tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx, CLEAR_BIT(session_entry->peerAIDBitmap[i], aid); } } + if (session_entry->bRoamSynchInProgress) + return eSIR_SUCCESS; lim_send_sme_tdls_delete_all_peer_ind(mac_ctx, session_entry); return eSIR_SUCCESS; diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index 10b000bb9227..2c5e1026ed79 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -327,9 +327,6 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg) 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_SET_HW_MODE_REQ); CASE_RETURN_STRING(eWNI_SME_SET_HW_MODE_RESP); CASE_RETURN_STRING(eWNI_SME_HW_MODE_TRANS_IND); @@ -506,7 +503,6 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) CASE_RETURN_STRING(WMA_SET_THERMAL_LEVEL); CASE_RETURN_STRING(WMA_SET_SAP_INTRABSS_DIS); #ifdef WLAN_FEATURE_ROAM_OFFLOAD - CASE_RETURN_STRING(WMA_ROAM_OFFLOAD_SYNCH_CNF); CASE_RETURN_STRING(WMA_ROAM_OFFLOAD_SYNCH_FAIL); #endif CASE_RETURN_STRING(SIR_HAL_SET_BASE_MACADDR_IND); diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 0b16d7b54787..1bb5b5c0b9eb 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1607,4 +1607,12 @@ CDF_STATUS csr_roam_issue_ft_roam_offload_synch(tHalHandle hHal, uint32_t sessionId, tSirBssDescription *pBssDescription); #endif typedef void (*tCsrLinkStatusCallback)(uint8_t status, void *pContext); +#ifdef FEATURE_WLAN_TDLS +void csr_roam_fill_tdls_info(tCsrRoamInfo *roam_info, tpSirSmeJoinRsp join_rsp); +#else +static inline void csr_roam_fill_tdls_info(tCsrRoamInfo *roam_info, + tpSirSmeJoinRsp join_rsp) +{} +#endif + #endif diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index bc82612bcdfd..1140a54ed4dd 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -847,7 +847,6 @@ typedef struct tagCsrRoamOffloadSynchStruct { uint16_t chainMask; /* chainmask */ uint16_t smpsMode; /* smps.mode */ struct cdf_mac_addr bssid; /* MAC address of roamed AP */ - bool bRoamSynchInProgress; /* a roam offload synch */ tCsrRoamOffloadAuthStatus authStatus; /* auth status */ uint8_t kck[SIR_KCK_KEY_LEN]; uint8_t kek[SIR_KEK_KEY_LEN]; @@ -968,6 +967,7 @@ typedef struct tagCsrRoamSession { uint8_t psk_pmk[SIR_ROAM_SCAN_PSK_SIZE]; size_t pmk_len; uint8_t RoamKeyMgmtOffloadEnabled; + roam_offload_synch_ind *roam_synch_data; #endif #if defined WLAN_FEATURE_VOWIFI_11R tftSMEContext ftSmeContext; @@ -976,6 +976,7 @@ typedef struct tagCsrRoamSession { uint8_t join_bssid_count; struct csr_roam_stored_profile stored_roam_profile; bool ch_switch_in_progress; + bool roam_synch_in_progress; } tCsrRoamSession; typedef struct tagCsrRoamStruct { @@ -1359,10 +1360,9 @@ static inline void csr_roaming_report_diag_event(tpAniSirGlobal mac_ctx, {} #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD -void csr_process_roam_offload_synch_ind(tHalHandle hHal, - roam_offload_synch_ind * roam_synch_ind_ptr); CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac, - roam_offload_synch_ind *roam_synch_ind_ptr); + roam_offload_synch_ind *roam_synch_ind_ptr, + tpSirBssDescription bss_desc_ptr); void csr_process_ho_fail_ind(tpAniSirGlobal pMac, void *pMsgBuf); #endif bool csr_store_joinreq_param(tpAniSirGlobal mac_ctx, diff --git a/core/sme/inc/csr_neighbor_roam.h b/core/sme/inc/csr_neighbor_roam.h index 64ca970571bb..1b888b6a2a78 100644 --- a/core/sme/inc/csr_neighbor_roam.h +++ b/core/sme/inc/csr_neighbor_roam.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -297,9 +297,10 @@ CDF_STATUS csr_roam_read_tsf(tpAniSirGlobal pMac, uint8_t *pTimestamp, const uint8_t sessionId); #endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ #ifdef WLAN_FEATURE_ROAM_OFFLOAD -CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, - uint8_t sessionId); CDF_STATUS csr_neighbor_roam_offload_update_preauth_list(tpAniSirGlobal pMac, roam_offload_synch_ind *roam_synch_ind_ptr, uint8_t sessionId); +void csr_roam_synch_callback(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr, uint8_t reason); #endif #endif /* CSR_NEIGHBOR_ROAM_H */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 92bbe82a8a8d..a1d4a534a384 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1694,6 +1694,7 @@ CDF_STATUS sme_hdd_ready_ind(tHalHandle hHal) Msg.messageType = eWNI_SME_SYS_READY_IND; Msg.length = sizeof(tSirSmeReadyReq); Msg.add_bssdescr_cb = csr_scan_process_single_bssdescr; + Msg.csr_roam_synch_cb = csr_roam_synch_callback; if (eSIR_FAILURE != u_mac_post_ctrl_msg(hHal, (tSirMbMsg *) &Msg)) { @@ -2242,11 +2243,6 @@ CDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) } switch (pMsg->type) { #ifdef WLAN_FEATURE_ROAM_OFFLOAD - case eWNI_SME_ROAM_OFFLOAD_SYNCH_IND: - csr_process_roam_offload_synch_ind(pMac, - (roam_offload_synch_ind *) pMsg->bodyptr); - cdf_mem_free(pMsg->bodyptr); - break; case eWNI_SME_HO_FAIL_IND: CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, FL("LFR3: Rcvd eWNI_SME_HO_FAIL_IND")); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b5af6635e9bc..813c2c7a9036 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -4106,7 +4106,7 @@ void csr_roam_ccm_cfg_set_callback(tpAniSirGlobal pMac, int32_t result) sessionId = pCommand->sessionId; #ifdef WLAN_FEATURE_ROAM_OFFLOAD pSession = &pMac->roam.roamSession[sessionId]; - if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { + if (pSession->roam_synch_in_progress) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, "LFR3:csr_roam_cfg_set_callback"); } @@ -4160,6 +4160,8 @@ CDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal pMac, uint32_t sessionId, tSirRetStatus status; uint32_t cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; uint8_t channel = 0; + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + /* 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) { @@ -4223,12 +4225,15 @@ CDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal pMac, uint32_t sessionId, } else { csr_set_cfg_rate_set_from_profile(pMac, pProfile); } + status = cfg_set_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, + pBssConfig->uJoinTimeOut); + /* Any roaming related changes should be above this line */ + if (pSession && pSession->roam_synch_in_progress) + return CDF_STATUS_SUCCESS; /* Make this the last CFG to set. The callback will trigger a join_req */ /* Join time out */ csr_roam_substate_change(pMac, eCSR_ROAM_SUBSTATE_CONFIG, sessionId); - status = cfg_set_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, - pBssConfig->uJoinTimeOut); csr_roam_ccm_cfg_set_callback(pMac, status); return CDF_STATUS_SUCCESS; } @@ -5458,12 +5463,6 @@ static CDF_STATUS csr_roam_save_security_rsp_ie(tpAniSirGlobal pMac, sms_log(pMac, LOGE, FL("session %d not found"), sessionId); return CDF_STATUS_E_FAILURE; } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, - FL("LFR3:csr_roam_save_security_rsp_ie")); - } -#endif if ((eCSR_AUTH_TYPE_WPA == authType) || (eCSR_AUTH_TYPE_WPA_PSK == authType) || @@ -5605,43 +5604,6 @@ eCsrPhyMode csr_roamdot11mode_to_phymode(uint8_t dot11mode) #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD -CDF_STATUS csr_roam_offload_send_synch_cnf(tpAniSirGlobal pMac, uint8_t sessionId) -{ - tpSirSmeRoamOffloadSynchCnf pRoamOffloadSynchCnf; - cds_msg_t msg; - tCsrRoamSession *pSession = &pMac->roam.roamSession[sessionId]; - pRoamOffloadSynchCnf = - cdf_mem_malloc(sizeof(tSirSmeRoamOffloadSynchCnf)); - if (NULL == pRoamOffloadSynchCnf) { - CDF_TRACE(CDF_MODULE_ID_SME, - CDF_TRACE_LEVEL_ERROR, - "%s: not able to allocate memory for roam" - "offload synch confirmation data", __func__); - pSession->roamOffloadSynchParams.bRoamSynchInProgress = - false; - return CDF_STATUS_E_NOMEM; - } - pRoamOffloadSynchCnf->sessionId = sessionId; - msg.type = WMA_ROAM_OFFLOAD_SYNCH_CNF; - msg.reserved = 0; - msg.bodyptr = pRoamOffloadSynchCnf; - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "LFR3: Posting WMA_ROAM_OFFLOAD_SYNCH_CNF"); - if (!CDF_IS_STATUS_SUCCESS - (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, - "%s: Not able to post WMA_ROAM_OFFLOAD_SYNCH_CNF message to WMA", - __func__); - cdf_mem_free(pRoamOffloadSynchCnf); - pSession->roamOffloadSynchParams.bRoamSynchInProgress = - false; - return CDF_STATUS_E_FAILURE; - } - csr_roaming_report_diag_event(pMac, NULL, eCSR_REASON_ROAM_SYNCH_CNF); - pSession->roamOffloadSynchParams.bRoamSynchInProgress = false; - return CDF_STATUS_SUCCESS; -} - void csr_roam_synch_clean_up (tpAniSirGlobal mac, uint8_t session_id) { cds_msg_t msg; @@ -5651,7 +5613,7 @@ void csr_roam_synch_clean_up (tpAniSirGlobal mac, uint8_t session_id) /* Clean up the roam synch in progress for LFR3 */ CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "%s: Roam Synch Failed, Clean Up", __func__); - session->roamOffloadSynchParams.bRoamSynchInProgress = false; + session->roam_synch_in_progress = false; roam_offload_failed = cdf_mem_malloc( sizeof(struct roam_offload_synch_fail)); @@ -6254,7 +6216,7 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, eSIR_TX_RX, 0, 0, NULL, 0); } else { #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (roam_offload_params->bRoamSynchInProgress + if (session->roam_synch_in_progress && (roam_offload_params->authStatus == CSR_ROAM_AUTH_STATUS_AUTHENTICATED)) { CDF_TRACE(CDF_MODULE_ID_SME, @@ -6316,7 +6278,7 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, assoc_info.pProfile = profile; if (context) { #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (roam_offload_params->bRoamSynchInProgress) + if (session->roam_synch_in_progress) CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, FL("LFR3:Clear Connected info")); @@ -6461,7 +6423,7 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, mac_ctx->roam.configParam.doBMPSWorkaround = 1; } #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (roam_offload_params->bRoamSynchInProgress) { + if (session->roam_synch_in_progress) { roam_info.roamSynchInProgress = 1; roam_info.synchAuthStatus = roam_offload_params->authStatus; @@ -6487,17 +6449,6 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, cmd->u.roamCmd.roamId, eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (roam_offload_params->bRoamSynchInProgress - && (roam_offload_params->authStatus - == CSR_ROAM_AUTH_STATUS_CONNECTED)) { - CDF_TRACE(CDF_MODULE_ID_SME, - CDF_TRACE_LEVEL_DEBUG, - FL("LFR3:Send Synch Cnf for Auth status connected")); - csr_roam_offload_send_synch_cnf(mac_ctx, - session_id); - } -#endif } csr_roam_completion(mac_ctx, session_id, NULL, cmd, @@ -6516,7 +6467,7 @@ static void csr_roam_process_join_res(tpAniSirGlobal mac_ctx, */ if (!CSR_IS_WAIT_FOR_KEY(mac_ctx, session_id)) { #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (roam_offload_params->bRoamSynchInProgress) { + if (session->roam_synch_in_progress) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, FL @@ -7837,60 +7788,57 @@ CDF_STATUS csr_roam_save_connected_infomation(tpAniSirGlobal pMac, return CDF_STATUS_E_FAILURE; } pConnectProfile = &pSession->connectedProfile; -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (pSession->roamOffloadSynchParams.bRoamSynchInProgress) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, - FL("csr_roam_save_connected_infomation")); - } -#endif if (pConnectProfile->pAddIEAssoc) { cdf_mem_free(pConnectProfile->pAddIEAssoc); pConnectProfile->pAddIEAssoc = NULL; } - cdf_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; + if (!pSession->roam_synch_in_progress) { + cdf_mem_set(&pSession->connectedProfile, + sizeof(tCsrRoamConnectedProfile), 0); + pConnectProfile->AuthType = pProfile->negotiatedAuthType; + pConnectProfile->AuthInfo = pProfile->AuthType; + pConnectProfile->CBMode = pProfile->CBMode; + 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; + cdf_mem_copy(&pConnectProfile->Keys, &pProfile->Keys, + sizeof(tCsrKeys)); + if (pProfile->nAddIEAssocLength) { + pConnectProfile->pAddIEAssoc = + cdf_mem_malloc(pProfile->nAddIEAssocLength); + if (NULL == pConnectProfile->pAddIEAssoc) + status = CDF_STATUS_E_NOMEM; + else + status = CDF_STATUS_SUCCESS; + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(pMac, LOGE, + FL("Failed to allocate memory for IE")); + return CDF_STATUS_E_FAILURE; + } + pConnectProfile->nAddIEAssocLength = + pProfile->nAddIEAssocLength; + cdf_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 */ pConnectProfile->operationChannel = pSirBssDesc->channelId; pConnectProfile->beaconInterval = pSirBssDesc->beaconInterval; if (!pConnectProfile->beaconInterval) { sms_log(pMac, LOGW, FL("ERROR: Beacon interval is ZERO")); } - cdf_mem_copy(&pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys)); - /* saving the addional IE`s like Hot spot indication element and extended capabilities */ - if (pProfile->nAddIEAssocLength) { - pConnectProfile->pAddIEAssoc = - cdf_mem_malloc(pProfile->nAddIEAssocLength); - if (NULL == pConnectProfile->pAddIEAssoc) - status = CDF_STATUS_E_NOMEM; - else - status = CDF_STATUS_SUCCESS; - if (!CDF_IS_STATUS_SUCCESS(status)) { - sms_log(pMac, LOGE, - FL - ("Failed to allocate memory for additional IEs")); - return CDF_STATUS_E_FAILURE; - } - pConnectProfile->nAddIEAssocLength = - pProfile->nAddIEAssocLength; - cdf_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 */ csr_get_bss_id_bss_desc(pMac, pSirBssDesc, &pConnectProfile->bssid); #ifdef WLAN_FEATURE_VOWIFI_11R if (pSirBssDesc->mdiePresent) { @@ -16977,7 +16925,7 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, return CDF_STATUS_E_FAILURE; } #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (session->roamOffloadSynchParams.bRoamSynchInProgress + if (session->roam_synch_in_progress && (ROAM_SCAN_OFFLOAD_STOP == command)) { /* * When roam synch is in progress for propagation, there is no @@ -18327,91 +18275,6 @@ void csr_roaming_report_diag_event(tpAniSirGlobal mac_ctx, #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD -/*---------------------------------------------------------------------------- -* fn csr_process_roam_offload_synch_ind -* brief This will process the roam synch indication received from -* lower layers.This function also calls another API to -* parse the beacon IE and fill the appropriate fields -* param pMac - pMac global structure -* param pMsgBuf - Message buffer received from lower layers -* --------------------------------------------------------------------------*/ -void csr_process_roam_offload_synch_ind(tHalHandle hHal, - roam_offload_synch_ind *roam_synch_ind_ptr) -{ - tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - tCsrRoamSession *session_ptr = NULL; - uint8_t session_id = roam_synch_ind_ptr->roamedVdevId; - session_ptr = CSR_GET_SESSION(pMac, roam_synch_ind_ptr->roamedVdevId); - if (!session_ptr) { - sms_log(pMac, LOGE, FL("LFR3: session %d not found "), - roam_synch_ind_ptr->roamedVdevId); - goto err_synch_rsp; - } - if (!CDF_IS_STATUS_SUCCESS(csr_scan_save_roam_offload_ap_to_scan_cache( - pMac, roam_synch_ind_ptr))) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "fail to save roam offload AP to scan cache"); - goto err_synch_rsp; - } - - csr_roaming_report_diag_event(pMac, roam_synch_ind_ptr, - eCSR_REASON_ROAM_SYNCH_IND); - session_ptr->roamOffloadSynchParams.rssi = roam_synch_ind_ptr->rssi; - session_ptr->roamOffloadSynchParams.roamReason = - roam_synch_ind_ptr->roamReason; - session_ptr->roamOffloadSynchParams.roamedVdevId = - roam_synch_ind_ptr->roamedVdevId; - cdf_copy_macaddr(&session_ptr->roamOffloadSynchParams.bssid, - &roam_synch_ind_ptr->bssid); - session_ptr->roamOffloadSynchParams.txMgmtPower = - roam_synch_ind_ptr->txMgmtPower; - session_ptr->roamOffloadSynchParams.authStatus = - roam_synch_ind_ptr->authStatus; - session_ptr->roamOffloadSynchParams.bRoamSynchInProgress = true; - /*Save the BSS descriptor for later use*/ - session_ptr->roamOffloadSynchParams.bss_desc_ptr = - roam_synch_ind_ptr->bss_desc_ptr; - pMac->roam.reassocRespLen = roam_synch_ind_ptr->reassocRespLength; - pMac->roam.pReassocResp = - cdf_mem_malloc(pMac->roam.reassocRespLen); - if (NULL == pMac->roam.pReassocResp) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - "Memory allocation for reassoc response failed"); - goto err_synch_rsp; - } - cdf_mem_copy(pMac->roam.pReassocResp, - (uint8_t *)roam_synch_ind_ptr + - roam_synch_ind_ptr->reassocRespOffset, - pMac->roam.reassocRespLen); - - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, - "LFR3:%s: the reassoc resp frame data:", __func__); - CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, - pMac->roam.pReassocResp, pMac->roam.reassocRespLen); - - cdf_mem_copy(session_ptr->roamOffloadSynchParams.kck, - roam_synch_ind_ptr->kck, SIR_KCK_KEY_LEN); - cdf_mem_copy(session_ptr->roamOffloadSynchParams.kek, - roam_synch_ind_ptr->kek, SIR_KEK_KEY_LEN); - cdf_mem_copy(session_ptr->roamOffloadSynchParams.replay_ctr, - roam_synch_ind_ptr->replay_ctr, SIR_REPLAY_CTR_LEN); - if (CDF_STATUS_SUCCESS != csr_neighbor_roam_offload_update_preauth_list( - pMac, roam_synch_ind_ptr, session_id)) { - /** - *Bail out if Roam Offload Synch Response was not even handled. - **/ - sms_log(pMac, LOGE, FL("Roam Offload Synch Response " - "was not processed")); - goto err_synch_rsp; - } - - csr_neighbor_roam_request_handoff(pMac, session_id); - -err_synch_rsp: - cdf_mem_free(roam_synch_ind_ptr->bss_desc_ptr); - roam_synch_ind_ptr->bss_desc_ptr = NULL; -} - /*---------------------------------------------------------------------------- * fn csr_process_ho_fail_ind * brief This function will process the Hand Off Failure indication @@ -19025,3 +18888,277 @@ fail: msg_return.bodyval = 0; sys_process_mmh_msg(mac, &msg_return); } +#ifdef FEATURE_WLAN_TDLS +/** + * csr_roam_fill_tdls_info() - Fill TDLS information + * @roam_info: Roaming information buffer + * @join_rsp: Join response which has TDLS info + * + * Return: None + */ +void csr_roam_fill_tdls_info(tCsrRoamInfo *roam_info, tpSirSmeJoinRsp join_rsp) +{ + roam_info->tdls_prohibited = join_rsp->tdls_prohibited; + roam_info->tdls_chan_swit_prohibited = + join_rsp->tdls_chan_swit_prohibited; +} +#endif + +/** + * csr_roam_synch_callback() - SME level callback for roam synch propagation + * @mac_ctx: MAC Context + * @roam_synch_data: Roam synch data buffer pointer + * @bss_desc: BSS descriptor pointer + * @reason: Reason for calling the callback + * + * This callback is registered with WMA and used after roaming happens in + * firmware and the call to this routine completes the roam synch + * propagation at both CSR and HDD levels. The HDD level propagation + * is achieved through the already defined callback for assoc completion + * handler. + * + * Return: None. + */ +void csr_roam_synch_callback(tpAniSirGlobal mac_ctx, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc, uint8_t reason) +{ + uint8_t session_id = roam_synch_data->roamedVdevId; + tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id); + tDot11fBeaconIEs *ies_local = NULL; + struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; + tCsrRoamInfo *roam_info; + tCsrRoamConnectedProfile *conn_profile = NULL; + sme_QosAssocInfo assoc_info; + struct cdf_mac_addr bcast_mac = CDF_MAC_ADDR_BROADCAST_INITIALIZER; + tpAddBssParams add_bss_params; + CDF_STATUS status = CDF_STATUS_SUCCESS; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (!CDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, FL("LFR3: Locking failed, bailing out")); + return; + } + if (!session) { + sms_log(mac_ctx, LOGE, FL("LFR3: Session not found")); + sme_release_global_lock(&mac_ctx->sme); + return; + } + session->roam_synch_in_progress = true; + if (reason == ROAMING_TX_QUEUE_DISABLE) { + csr_roam_call_callback(mac_ctx, session_id, NULL, 0, + eCSR_ROAM_FT_START, eSIR_SME_SUCCESS); + sme_release_global_lock(&mac_ctx->sme); + return; + } + session->roam_synch_data = roam_synch_data; + if (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(mac_ctx, + bss_desc, &ies_local))) { + sms_log(mac_ctx, LOGE, FL("LFR3: fail to parse IEs")); + session->roam_synch_in_progress = false; + sme_release_global_lock(&mac_ctx->sme); + return; + } + conn_profile = &session->connectedProfile; + csr_roam_stop_network(mac_ctx, session_id, + session->pCurRoamProfile, + bss_desc, + ies_local); + ps_global_info->remain_in_power_active_till_dhcp = false; + session->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + roam_info = cdf_mem_malloc(sizeof(tCsrRoamInfo)); + if (NULL == roam_info) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("LFR3: Mem Alloc failed for roam info")); + session->roam_synch_in_progress = false; + sme_release_global_lock(&mac_ctx->sme); + return; + } + csr_scan_save_roam_offload_ap_to_scan_cache(mac_ctx, roam_synch_data, + bss_desc); + cdf_mem_zero(roam_info, sizeof(tCsrRoamInfo)); + roam_info->sessionId = session_id; + csr_roam_call_callback(mac_ctx, roam_synch_data->roamedVdevId, + roam_info, 0, eCSR_ROAM_TDLS_STATUS_UPDATE, + eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND); + cdf_mem_copy(&roam_info->bssid.bytes, &bss_desc->bssId, + sizeof(struct cdf_mac_addr)); + csr_roam_save_connected_infomation(mac_ctx, session_id, + session->pCurRoamProfile, + bss_desc, + ies_local); + csr_roam_save_security_rsp_ie(mac_ctx, session_id, + session->pCurRoamProfile->negotiatedAuthType, + bss_desc, ies_local); + roam_info->isESEAssoc = conn_profile->isESEAssoc; + if (CSR_IS_ENC_TYPE_STATIC + (session->pCurRoamProfile->negotiatedUCEncryptionType) && + !session->pCurRoamProfile->bWPSAssociation) { + if (!CDF_IS_STATUS_SUCCESS( + csr_roam_issue_set_context_req(mac_ctx, + session_id, + session->pCurRoamProfile->negotiatedUCEncryptionType, + bss_desc, + &(bss_desc->bssId), + false, true, + eSIR_TX_RX, 0, 0, NULL, 0))) { + /* NO keys. these key parameters don't matter */ + sms_log(mac_ctx, LOGE, + FL("Set context for unicast fail")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, session_id); + } + csr_roam_issue_set_context_req(mac_ctx, session_id, + session->pCurRoamProfile->negotiatedMCEncryptionType, + bss_desc, + &bcast_mac.bytes, false, false, + eSIR_TX_RX, 0, 0, NULL, 0); + } + if ((roam_synch_data->authStatus + == CSR_ROAM_AUTH_STATUS_AUTHENTICATED)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Don't start waitforkey timer")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, session_id); + } else { + roam_info->fAuthRequired = true; + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, + session_id); + + ps_global_info->remain_in_power_active_till_dhcp = true; + mac_ctx->roam.WaitForKeyTimerInfo.sessionId = session_id; + if (!CDF_IS_STATUS_SUCCESS(csr_roam_start_wait_for_key_timer( + mac_ctx, CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD)) + ) { + sms_log(mac_ctx, LOGE, FL + ("Failed wait for key timer start")); + csr_roam_substate_change(mac_ctx, + eCSR_ROAM_SUBSTATE_NONE, + session_id); + } + } + roam_info->nBeaconLength = 0; + roam_info->nAssocReqLength = roam_synch_data->reassoc_req_length - + SIR_MAC_HDR_LEN_3A - SIR_MAC_REASSOC_SSID_OFFSET; + roam_info->nAssocRspLength = roam_synch_data->reassocRespLength - + SIR_MAC_HDR_LEN_3A; + roam_info->pbFrames = cdf_mem_malloc(roam_info->nBeaconLength + + roam_info->nAssocReqLength + roam_info->nAssocRspLength); + if (NULL == roam_info->pbFrames) { + sms_log(mac_ctx, LOGE, FL("no memory available")); + session->roam_synch_in_progress = false; + if (roam_info) + cdf_mem_free(roam_info); + sme_release_global_lock(&mac_ctx->sme); + return; + } + cdf_mem_zero(roam_info->pbFrames, roam_info->nBeaconLength + + roam_info->nAssocReqLength + roam_info->nAssocRspLength); + cdf_mem_copy(roam_info->pbFrames, + (uint8_t *)roam_synch_data + + roam_synch_data->reassoc_req_offset + + SIR_MAC_HDR_LEN_3A + SIR_MAC_REASSOC_SSID_OFFSET, + roam_info->nAssocReqLength); + cdf_mem_copy(roam_info->pbFrames + roam_info->nAssocReqLength, + (uint8_t *)roam_synch_data + + roam_synch_data->reassocRespOffset + + SIR_MAC_HDR_LEN_3A, + roam_info->nAssocRspLength); + + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL("LFR3:Clear Connected info")); + csr_roam_free_connected_info(mac_ctx, + &session->connectedInfo); + conn_profile->vht_channel_width = + roam_synch_data->join_rsp->vht_channel_width; + add_bss_params = (tpAddBssParams)roam_synch_data->add_bss_params; + session->connectedInfo.staId = add_bss_params->staContext.staIdx; + roam_info->staId = session->connectedInfo.staId; + roam_info->ucastSig = + (uint8_t) roam_synch_data->join_rsp->ucastSig; + roam_info->bcastSig = + (uint8_t) roam_synch_data->join_rsp->bcastSig; + roam_info->timingMeasCap = + roam_synch_data->join_rsp->timingMeasCap; + roam_info->chan_info.nss = roam_synch_data->join_rsp->nss; + roam_info->chan_info.rate_flags = + roam_synch_data->join_rsp->max_rate_flags; + csr_roam_fill_tdls_info(roam_info, roam_synch_data->join_rsp); + sms_log(mac_ctx, LOG1, + FL("tdls:prohibit: %d, chan_swit_prohibit: %d"), + roam_info->tdls_prohibited, + roam_info->tdls_chan_swit_prohibited); +#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH + src_profile = &roam_synch_data->join_rsp->HTProfile; + dst_profile = &conn_profile->HTProfile; + if (mac_ctx->roam.configParam.cc_switch_mode + != CDF_MCC_TO_SCC_SWITCH_DISABLE) + csr_roam_copy_ht_profile(dst_profile, + src_profile); +#endif + assoc_info.pBssDesc = bss_desc; + roam_info->statusCode = eSIR_SME_SUCCESS; + roam_info->reasonCode = eSIR_SME_SUCCESS; + assoc_info.pProfile = session->pCurRoamProfile; + mac_ctx->roam.roamSession[session_id].connectState = + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + sme_qos_csr_event_ind(mac_ctx, session_id, + SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL); + sme_qos_csr_event_ind(mac_ctx, session_id, + SME_QOS_CSR_REASSOC_REQ, NULL); + sme_qos_csr_event_ind(mac_ctx, session_id, + SME_QOS_CSR_HANDOFF_COMPLETE, NULL); + mac_ctx->roam.roamSession[session_id].connectState = + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + sme_qos_csr_event_ind(mac_ctx, session_id, + SME_QOS_CSR_REASSOC_COMPLETE, &assoc_info); + roam_info->pBssDesc = bss_desc; + conn_profile->acm_mask = sme_qos_get_acm_mask(mac_ctx, + bss_desc, NULL); + if (conn_profile->modifyProfileFields.uapsd_mask) { + sms_log(mac_ctx, LOGE, + " uapsd_mask (0x%X) set, request UAPSD now", + conn_profile->modifyProfileFields.uapsd_mask); + sme_ps_start_uapsd(mac_ctx, session_id, + NULL, NULL); + } + conn_profile->dot11Mode = session->bssParams.uCfgDot11Mode; + roam_info->u.pConnectedProfile = conn_profile; + + if (!IS_FEATURE_SUPPORTED_BY_FW + (SLM_SESSIONIZATION) && + (csr_is_concurrent_session_running(mac_ctx))) { + mac_ctx->roam.configParam.doBMPSWorkaround = 1; + } + roam_info->roamSynchInProgress = true; + roam_info->synchAuthStatus = roam_synch_data->authStatus; + cdf_mem_copy(roam_info->kck, roam_synch_data->kck, SIR_KCK_KEY_LEN); + cdf_mem_copy(roam_info->kek, roam_synch_data->kek, SIR_KEK_KEY_LEN); + cdf_mem_copy(roam_info->replay_ctr, roam_synch_data->replay_ctr, + SIR_REPLAY_CTR_LEN); + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, + FL("LFR3: Copy KCK, KEK and Replay Ctr")); + roam_info->subnet_change_status = + CSR_GET_SUBNET_STATUS(roam_synch_data->roamReason); + csr_roam_call_callback(mac_ctx, session_id, roam_info, 0, + eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); + csr_reset_pmkid_candidate_list(mac_ctx, session_id); +#ifdef FEATURE_WLAN_WAPI + csr_reset_bkid_candidate_list(mac_ctx, session_id); +#endif + if (!CSR_IS_WAIT_FOR_KEY(mac_ctx, session_id)) { + CDF_TRACE(CDF_MODULE_ID_SME, + CDF_TRACE_LEVEL_DEBUG, + FL + ("NO CSR_IS_WAIT_FOR_KEY -> csr_roam_link_up")); + csr_roam_link_up(mac_ctx, conn_profile->bssid); + } + session->fRoaming = false; + session->roam_synch_in_progress = false; + cdf_mem_free(roam_info->pbFrames); + cdf_mem_free(roam_info); + sme_release_global_lock(&mac_ctx->sme); +} diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 7a6e1155eab8..20293af2a9f0 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -7102,7 +7102,8 @@ void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1, */ #ifdef WLAN_FEATURE_ROAM_OFFLOAD CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac, - roam_offload_synch_ind *roam_sync_ind_ptr) + roam_offload_synch_ind *roam_sync_ind_ptr, + tpSirBssDescription bss_desc_ptr) { uint32_t length = 0; bool dup_bss; @@ -7123,7 +7124,7 @@ CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac, cdf_mem_zero(scan_res_ptr, sizeof(tCsrScanResult) + length); cdf_mem_copy(&scan_res_ptr->Result.BssDescriptor, - roam_sync_ind_ptr->bss_desc_ptr, + bss_desc_ptr, (sizeof(tSirBssDescription) + length)); ies_local_ptr = (tDot11fBeaconIEs *)(scan_res_ptr->Result.pvIes); if (!ies_local_ptr && diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index a66bfaadf971..40f282787327 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2480,7 +2480,7 @@ static void csr_neighbor_roam_info_ctx_init( } ngbr_roam_info->uOsRequestedHandoff = 0; #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (session->roamOffloadSynchParams.bRoamSynchInProgress) { + if (session->roam_synch_in_progress) { if (pMac->roam.pReassocResp != NULL) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, @@ -2488,9 +2488,6 @@ static void csr_neighbor_roam_info_ctx_init( cdf_mem_free(pMac->roam.pReassocResp); pMac->roam.pReassocResp = NULL; } - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, - "LFR3:Send SynchCnf auth, authenticated"); - csr_roam_offload_send_synch_cnf(pMac, session_id); } else #endif csr_roam_offload_scan(pMac, session_id, @@ -2554,9 +2551,9 @@ CDF_STATUS csr_neighbor_roam_indicate_connect( return CDF_STATUS_SUCCESS; } #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (session->roamOffloadSynchParams.bRoamSynchInProgress && + if (session->roam_synch_in_progress && (eSIR_ROAM_AUTH_STATUS_AUTHENTICATED == - session->roamOffloadSynchParams.authStatus)) { + session->roam_synch_data->authStatus)) { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG, "LFR3:csr_neighbor_roam_indicate_connect"); msg = cdf_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq)); @@ -2572,10 +2569,15 @@ CDF_STATUS csr_neighbor_roam_indicate_connect( cdf_copy_macaddr(&roamInfo.peerMac, &session->connectedProfile.bssid); roamInfo.roamSynchInProgress = - session->roamOffloadSynchParams.bRoamSynchInProgress; + session->roam_synch_in_progress; csr_roam_call_callback(pMac, session_id, &roamInfo, 0, eCSR_ROAM_SET_KEY_COMPLETE, eCSR_ROAM_RESULT_AUTHENTICATED); + csr_neighbor_roam_reset_init_state_control_info(pMac, + session_id); + csr_neighbor_roam_info_ctx_init(pMac, session_id); + + return status; } #endif diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 8372a1fa20d3..ac80f810a083 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3822,20 +3822,20 @@ CDF_STATUS sme_qos_process_ft_reassoc_rsp_ev(tpAniSirGlobal mac_ctx, csr_conn_info->nAssocRspLength)); #ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (!csr_session->roamOffloadSynchParams.bRoamSynchInProgress) { + if (!csr_session->roam_synch_in_progress) { #endif - for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { - ac_info = &qos_session->ac_info[ac]; - sme_qos_find_matching_tspec(mac_ctx, sessionid, ac, - ac_info, ric_data_desc, &ric_rsplen); - } + for (ac = SME_QOS_EDCA_AC_BE; ac < SME_QOS_EDCA_AC_MAX; ac++) { + ac_info = &qos_session->ac_info[ac]; + sme_qos_find_matching_tspec(mac_ctx, sessionid, ac, + ac_info, ric_data_desc, &ric_rsplen); + } - if (ric_rsplen) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - FL("RIC Response still follows despite traversing " - "through all ACs. Remaining len = %d"), ric_rsplen); - CDF_ASSERT(0); - } + if (ric_rsplen) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + FL("RIC Resp still follows . Rem len = %d"), + ric_rsplen); + CDF_ASSERT(0); + } #ifdef WLAN_FEATURE_ROAM_OFFLOAD } else { CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 3906d6d74312..b9ea71fac370 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1367,6 +1367,12 @@ typedef struct { * the serialized MC thread context with a timer. */ cdf_mc_timer_t service_ready_ext_timer; + void (*csr_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr, uint8_t reason); + CDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr); } t_wma_handle, *tp_wma_handle; /** diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index ab9ebf89722b..9a2cad03eed9 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -415,8 +415,18 @@ int wma_nlo_scan_cmp_evt_handler(void *handle, uint8_t *event, uint32_t len); #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD -void wma_process_roam_synch_complete(WMA_HANDLE handle, - tSirSmeRoamOffloadSynchCnf *synchcnf); +void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id); +static inline bool wma_is_roam_synch_in_progress(tp_wma_handle wma, + uint8_t vdev_id) +{ + return wma->interfaces[vdev_id].roam_synch_in_progress; +} +#else +static inline bool wma_is_roam_synch_in_progress(tp_wma_handle wma, + uint8_t vdev_id) +{ + return false; +} #endif /* diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index d769a78555b6..0a6428a6e36c 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -285,7 +285,6 @@ #define WMA_ROAM_SCAN_OFFLOAD_REQ SIR_HAL_ROAM_SCAN_OFFLOAD_REQ #ifdef WLAN_FEATURE_ROAM_OFFLOAD -#define WMA_ROAM_OFFLOAD_SYNCH_CNF SIR_HAL_ROAM_OFFLOAD_SYNCH_CNF #define WMA_ROAM_OFFLOAD_SYNCH_IND SIR_HAL_ROAM_OFFLOAD_SYNCH_IND #define WMA_ROAM_OFFLOAD_SYNCH_FAIL SIR_HAL_ROAM_OFFLOAD_SYNCH_FAIL #endif @@ -685,6 +684,12 @@ CDF_STATUS wma_register_mgmt_frm_client(void *p_cds_gctx, wma_mgmt_frame_rx_callback mgmt_rx_cb); CDF_STATUS wma_de_register_mgmt_frm_client(void *p_cds_gctx); - +CDF_STATUS wma_register_roaming_callbacks(void *cds_ctx, + void (*csr_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr, uint8_t reason), + CDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr)); #endif diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 2c2a41c4b843..e93e49979d86 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -1319,16 +1319,15 @@ void wma_set_linkstate(tp_wma_handle wma, tpLinkStateParams params) } if (params->state == eSIR_LINK_PREASSOC_STATE) { -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (wma->interfaces[vdev_id].roam_synch_in_progress) { + if (wma_is_roam_synch_in_progress(wma, vdev_id)) roam_synch_in_progress = true; - } -#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ status = wma_create_peer(wma, pdev, vdev, params->bssid, WMI_PEER_TYPE_DEFAULT, vdev_id, roam_synch_in_progress); if (status != CDF_STATUS_SUCCESS) - params->status = false; + WMA_LOGE("%s: Unable to create peer", __func__); + if (roam_synch_in_progress) + return; } else { WMA_LOGD("%s, vdev_id: %d, pausing tx_ll_queue for VDEV_STOP", __func__, vdev_id); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 0fd66336c6ee..8d906c2f51a4 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1068,10 +1068,8 @@ void wma_remove_peer(tp_wma_handle wma, uint8_t *bssid, wma->interfaces[vdev_id].peer_count--; WMA_LOGE("%s: Removed peer with peer_addr %pM vdevid %d peer_count %d", __func__, bssid, vdev_id, wma->interfaces[vdev_id].peer_count); -#ifdef WLAN_FEATURE_ROAM_OFFLOAD if (roam_synch_in_progress) return; -#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ /* 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, @@ -1158,15 +1156,13 @@ CDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, WMA_LOGE("%s : Unable to attach peer %pM", __func__, peer_addr); goto err; } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD if (roam_synch_in_progress) { - WMA_LOGE("%s: Created peer with peer_addr %pM vdev_id %d," + WMA_LOGE("%s: LFR3: Created peer with peer_addr %pM vdev_id %d," "peer_count - %d", __func__, peer_addr, vdev_id, wma->interfaces[vdev_id].peer_count); return CDF_STATUS_SUCCESS; } -#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 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__); @@ -3222,13 +3218,14 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss) add_bss->bssId); goto send_fail_resp; } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (iface->roam_synch_in_progress) { + if (wma_is_roam_synch_in_progress(wma, vdev_id)) { add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); - goto send_bss_resp; + WMA_LOGD("LFR3:%s: bssid %pM staIdx %d", + __func__, add_bss->bssId, + add_bss->staContext.staIdx); + return; } -#endif msg = wma_fill_vdev_req(wma, vdev_id, WMA_ADD_BSS_REQ, WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, @@ -3900,7 +3897,6 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) status = CDF_STATUS_E_FAILURE; goto out; } - if (peer != NULL && peer->state == ol_txrx_peer_state_disc) { /* * This is the case for reassociation. @@ -3921,8 +3917,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) ol_txrx_peer_state_conn); } -#ifdef WLAN_FEATURE_ROAM_OFFLOAD - if (iface->roam_synch_in_progress) { + if (wma_is_roam_synch_in_progress(wma, params->smesessionId)) { /* iface->nss = params->nss; */ /*In LFR2.0, the following operations are performed as * part of wmi_unified_send_peer_assoc. As we are @@ -3933,9 +3928,11 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) cdf_atomic_set(&iface->bss_status, WMA_BSS_STATUS_STARTED); iface->aid = params->assocId; - goto out; + WMA_LOGE("LFR3:statype %d vdev %d aid %d bssid %pM", + params->staType, params->smesessionId, + params->assocId, params->bssId); + return; } -#endif wmi_unified_send_txbf(wma, params); if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, @@ -4199,20 +4196,13 @@ static void wma_delete_sta_req_sta_mode(tp_wma_handle wma, 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 + if (wma_is_roam_synch_in_progress(wma, params->smesessionId)) + return; #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) { @@ -4288,6 +4278,8 @@ void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta) switch (oper_mode) { case BSS_OPERATIONAL_MODE_STA: wma_delete_sta_req_sta_mode(wma, del_sta); + if (wma_is_roam_synch_in_progress(wma, smesession_id)) + return; break; case BSS_OPERATIONAL_MODE_IBSS: /* IBSS shares AP code */ @@ -4405,15 +4397,13 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) 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) { + if (wma_is_roam_synch_in_progress(wma, params->smesessionId)) { roam_synch_in_progress = true; WMA_LOGD("LFR3:%s: Setting vdev_up to FALSE for session %d", __func__, params->smesessionId); wma->interfaces[params->smesessionId].vdev_up = false; goto detach_peer; } -#endif msg = wma_fill_vdev_req(wma, params->smesessionId, WMA_DELETE_BSS_REQ, WMA_TARGET_REQ_TYPE_VDEV_STOP, params, WMA_VDEV_STOP_REQUEST_TIMEOUT); @@ -4463,6 +4453,9 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) detach_peer: wma_remove_peer(wma, params->bssid, params->smesessionId, peer, roam_synch_in_progress); + if (wma_is_roam_synch_in_progress(wma, params->smesessionId)) + return; + out: params->status = status; wma_send_msg(wma, WMA_DELETE_BSS_RSP, (void *)params, 0); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 95cc3aa87e29..718c66dc9bb6 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5140,11 +5140,6 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) cdf_mem_free(msg->bodyptr); break; #ifdef WLAN_FEATURE_ROAM_OFFLOAD - case WMA_ROAM_OFFLOAD_SYNCH_CNF: - wma_process_roam_synch_complete(wma_handle, - (tSirSmeRoamOffloadSynchCnf *)msg->bodyptr); - cdf_mem_free(msg->bodyptr); - break; case WMA_ROAM_OFFLOAD_SYNCH_FAIL: wma_process_roam_synch_fail(wma_handle, (struct roam_offload_synch_fail *)msg->bodyptr); diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 215b450ba824..6827e25ce207 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3330,6 +3330,37 @@ CDF_STATUS wma_de_register_mgmt_frm_client(void *cds_ctx) return CDF_STATUS_SUCCESS; } +/** + * wma_register_roaming_callbacks() - Register roaming callbacks + * @cds_ctx: CDS Context + * @csr_roam_synch_cb: CSR roam synch callback routine pointer + * @pe_roam_synch_cb: PE roam synch callback routine pointer + * + * Register the SME and PE callback routines with WMA for + * handling roaming + * + * Return: Success or Failure Status + */ +CDF_STATUS wma_register_roaming_callbacks(void *cds_ctx, + void (*csr_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr, uint8_t reason), + CDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac, + roam_offload_synch_ind *roam_synch_data, + tpSirBssDescription bss_desc_ptr)) +{ + + tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA); + + if (!wma) { + WMA_LOGE("%s: Failed to get WMA context", __func__); + return CDF_STATUS_E_FAILURE; + } + wma->csr_roam_synch_cb = csr_roam_synch_cb; + wma->pe_roam_synch_cb = pe_roam_synch_cb; + WMA_LOGD("Registered roam synch callbacks with WMA successfully"); + return CDF_STATUS_SUCCESS; +} /** * wma_register_mgmt_frm_client() - register management frame callback * @cds_ctx: cds context diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index d4bb3367ecf2..83c6eaa275ac 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2713,74 +2713,30 @@ void wma_process_roam_synch_fail(WMA_HANDLE handle, } /** - * wma_roam_synch_event_handler() - roam synch event handler - * @handle: wma handle - * @event: event data - * @len: length of data + * wma_fill_roam_synch_buffer() - Fill the the roam sync buffer + * @wma: Global WMA Handle + * @roam_synch_ind_ptr: Buffer to be filled + * @param_buf: Source buffer * - * This function is roam synch event handler. It sends roam - * indication for upper layer. + * Firmware sends all the required information required for roam + * synch propagation as TLV's and stored in param_buf. These + * parameters are parsed and filled into the roam synch indication + * buffer which will be used at different layers for propagation. + * + * Return: None */ -int wma_roam_synch_event_handler(void *handle, uint8_t *event, - uint32_t len) +void wma_fill_roam_synch_buffer(tp_wma_handle wma, + roam_offload_synch_ind *roam_synch_ind_ptr, + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf) { - WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; - wmi_roam_synch_event_fixed_param *synch_event = NULL; - uint8_t *bcn_probersp_ptr = NULL; - uint8_t *reassoc_rsp_ptr = NULL; - uint8_t *reassoc_req_ptr = NULL; - tp_wma_handle wma = (tp_wma_handle) handle; - wmi_channel *chan = NULL; - wmi_key_material *key = NULL; - int size = 0; - roam_offload_synch_ind *roam_synch_ind_ptr; - - 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; - } + wmi_roam_synch_event_fixed_param *synch_event; + uint8_t *bcn_probersp_ptr; + uint8_t *reassoc_rsp_ptr; + uint8_t *reassoc_req_ptr; + wmi_channel *chan; + wmi_key_material *key; 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) { - WMA_LOGE("%s: Ignoring RSI since one is already in progress", - __func__); - return -EINVAL; - } - wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true; - len = sizeof(roam_offload_synch_ind) + - synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len + - synch_event->reassoc_req_len; - roam_synch_ind_ptr = - (roam_offload_synch_ind *) cdf_mem_malloc(len); - if (!roam_synch_ind_ptr) { - 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 abort_scan; - WMA_LOGD("LFR3: Aborting Scan with scan_id=%d\n", - wma->interfaces[synch_event->vdev_id].scan_info.scan_id); - abort_scan.SessionId = synch_event->vdev_id; - wma_stop_scan(wma, &abort_scan); - } - - roam_synch_ind_ptr->messageType = eWNI_SME_ROAM_OFFLOAD_SYNCH_IND; - roam_synch_ind_ptr->length = size; roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id; roam_synch_ind_ptr->authStatus = synch_event->auth_status; roam_synch_ind_ptr->roamReason = synch_event->roam_reason; @@ -2788,17 +2744,17 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, roam_synch_ind_ptr->isBeacon = synch_event->is_beacon; WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, roam_synch_ind_ptr->bssid.bytes); + wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context, + roam_synch_ind_ptr, NULL, ROAMING_TX_QUEUE_DISABLE); /* Beacon/Probe Rsp data */ roam_synch_ind_ptr->beaconProbeRespOffset = sizeof(roam_offload_synch_ind); - bcn_probersp_ptr = - (uint8_t *) roam_synch_ind_ptr + + bcn_probersp_ptr = (uint8_t *) roam_synch_ind_ptr + roam_synch_ind_ptr->beaconProbeRespOffset; roam_synch_ind_ptr->beaconProbeRespLength = synch_event->bcn_probe_rsp_len; cdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, roam_synch_ind_ptr->beaconProbeRespLength); - /* ReAssoc Rsp data */ roam_synch_ind_ptr->reassocRespOffset = sizeof(roam_offload_synch_ind) + @@ -2841,8 +2797,169 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, key->replay_counter, SIR_REPLAY_CTR_LEN); } - wma_send_msg(wma, WMA_ROAM_OFFLOAD_SYNCH_IND, - (void *) roam_synch_ind_ptr, 0); +} + +/** + * wma_roam_update_vdev() - Update the STA and BSS + * @wma: Global WMA Handle + * @roam_synch_ind_ptr: Information needed for roam sync propagation + * + * This function will perform all the vdev related operations with + * respect to the self sta and the peer after roaming and completes + * the roam synch propagation with respect to WMA layer. + * + * Return: None + */ +void wma_roam_update_vdev(tp_wma_handle wma, + roam_offload_synch_ind *roam_synch_ind_ptr) +{ + tDeleteBssParams *del_bss_params; + tDeleteStaParams *del_sta_params; + tLinkStateParams *set_link_params; + tAddStaParams *add_sta_params; + uint8_t vdev_id; + + del_bss_params = cdf_mem_malloc(sizeof(*del_bss_params)); + del_sta_params = cdf_mem_malloc(sizeof(*del_sta_params)); + set_link_params = cdf_mem_malloc(sizeof(*set_link_params)); + add_sta_params = cdf_mem_malloc(sizeof(*add_sta_params)); + if (!del_bss_params || !del_sta_params || + !set_link_params || !add_sta_params) { + WMA_LOGE("%s: failed to allocate memory", __func__); + return; + } + vdev_id = roam_synch_ind_ptr->roamedVdevId; + cdf_mem_zero(del_bss_params, sizeof(*del_bss_params)); + cdf_mem_zero(del_sta_params, sizeof(*del_sta_params)); + cdf_mem_zero(set_link_params, sizeof(*set_link_params)); + cdf_mem_zero(add_sta_params, sizeof(*add_sta_params)); + + del_bss_params->smesessionId = vdev_id; + del_sta_params->smesessionId = vdev_id; + cdf_mem_copy(del_bss_params->bssid, wma->interfaces[vdev_id].bssid, + IEEE80211_ADDR_LEN); + set_link_params->state = eSIR_LINK_PREASSOC_STATE; + cdf_mem_copy(set_link_params->selfMacAddr, wma->myaddr, + IEEE80211_ADDR_LEN); + cdf_mem_copy(set_link_params->bssid, roam_synch_ind_ptr->bssid.bytes, + IEEE80211_ADDR_LEN); + add_sta_params->staType = STA_ENTRY_SELF; + add_sta_params->smesessionId = vdev_id; + cdf_mem_copy(&add_sta_params->bssId, &roam_synch_ind_ptr->bssid.bytes, + IEEE80211_ADDR_LEN); + add_sta_params->staIdx = STA_INVALID_IDX; + add_sta_params->assocId = roam_synch_ind_ptr->aid; + + wma_delete_sta(wma, del_sta_params); + wma_delete_bss(wma, del_bss_params); + wma_set_linkstate(wma, set_link_params); + wma_add_bss(wma, (tpAddBssParams)roam_synch_ind_ptr->add_bss_params); + wma_add_sta(wma, add_sta_params); + wma->interfaces[vdev_id].vdev_up = true; + cdf_mem_copy(wma->interfaces[vdev_id].bssid, + roam_synch_ind_ptr->bssid.bytes, IEEE80211_ADDR_LEN); + cdf_mem_free(del_bss_params); + cdf_mem_free(del_sta_params); + cdf_mem_free(set_link_params); + cdf_mem_free(add_sta_params); +} + +/** + * wma_roam_synch_event_handler() - roam synch event handler + * @handle: wma handle + * @event: event data + * @len: length of data + * + * This function is roam synch event handler. It sends roam + * indication for upper layer. + * + * Return: Success or Failure status + */ +int wma_roam_synch_event_handler(void *handle, uint8_t *event, + uint32_t len) +{ + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; + wmi_roam_synch_event_fixed_param *synch_event = NULL; + tp_wma_handle wma = (tp_wma_handle) handle; + roam_offload_synch_ind *roam_synch_ind_ptr; + tpSirBssDescription bss_desc_ptr = NULL; + uint16_t ie_len = 0; + int status = -EINVAL; + + WMA_LOGD("LFR3:%s", __func__); + if (!event) { + WMA_LOGE("%s: event param null", __func__); + return status; + } + + param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *) event; + if (!param_buf) { + WMA_LOGE("%s: received null buf from target", __func__); + return status; + } + + synch_event = param_buf->fixed_param; + if (!synch_event) { + WMA_LOGE("%s: received null event data from target", __func__); + return status; + } + + if (wma_is_roam_synch_in_progress(wma, synch_event->vdev_id)) { + WMA_LOGE("%s: Ignoring RSI since one is already in progress", + __func__); + return status; + } + + wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true; + len = sizeof(roam_offload_synch_ind) + + synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len + + synch_event->reassoc_req_len; + roam_synch_ind_ptr = + (roam_offload_synch_ind *) cdf_mem_malloc(len); + if (!roam_synch_ind_ptr) { + WMA_LOGE("%s: failed to allocate memory for roam_synch_event", + __func__); + CDF_ASSERT(roam_synch_ind_ptr != NULL); + return -ENOMEM; + } + cdf_mem_zero(roam_synch_ind_ptr, len); + wma_fill_roam_synch_buffer(wma, roam_synch_ind_ptr, param_buf); + + /* 24 byte MAC header and 12 byte to ssid IE */ + if (roam_synch_ind_ptr->beaconProbeRespLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) { + ie_len = roam_synch_ind_ptr->beaconProbeRespLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } else { + WMA_LOGE("LFR3: Invalid Beacon Length"); + goto cleanup_label; + } + bss_desc_ptr = cdf_mem_malloc(sizeof(tSirBssDescription) + ie_len); + roam_synch_ind_ptr->join_rsp = cdf_mem_malloc(sizeof(tSirSmeJoinRsp)); + if ((NULL == roam_synch_ind_ptr->join_rsp) || (NULL == bss_desc_ptr)) { + WMA_LOGE("LFR3: mem alloc failed!"); + CDF_ASSERT(bss_desc_ptr != NULL); + CDF_ASSERT(roam_synch_ind_ptr->join_rsp != NULL); + status = -ENOMEM; + goto cleanup_label; + } + cdf_mem_zero(roam_synch_ind_ptr->join_rsp, sizeof(tSirSmeJoinRsp)); + cdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription) + ie_len); + wma->pe_roam_synch_cb((tpAniSirGlobal)wma->mac_context, + roam_synch_ind_ptr, bss_desc_ptr); + wma_roam_update_vdev(wma, roam_synch_ind_ptr); + wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context, + roam_synch_ind_ptr, bss_desc_ptr, ROAM_SYNCH_PROPAGATION); + wma_process_roam_synch_complete(wma, synch_event->vdev_id); +cleanup_label: + if (roam_synch_ind_ptr->join_rsp) + cdf_mem_free(roam_synch_ind_ptr->join_rsp); + if (roam_synch_ind_ptr) + cdf_mem_free(roam_synch_ind_ptr); + if (bss_desc_ptr) + cdf_mem_free(bss_desc_ptr); + wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = false; + return 0; } @@ -3267,15 +3384,13 @@ static void wma_roam_ho_fail_handler(tp_wma_handle wma, uint32_t vdev_id) * * Return: none */ -void wma_process_roam_synch_complete(WMA_HANDLE handle, - tSirSmeRoamOffloadSynchCnf *synchcnf) +void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id) { tp_wma_handle wma_handle = (tp_wma_handle) handle; wmi_roam_synch_complete_fixed_param *cmd; wmi_buf_t wmi_buf; uint8_t *buf_ptr; uint16_t len; - bool roam_synch_in_progress; len = sizeof(wmi_roam_synch_complete_fixed_param); if (!wma_handle || !wma_handle->wmi_handle) { @@ -3283,15 +3398,6 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, __func__); return; } - roam_synch_in_progress = - wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress; - if (roam_synch_in_progress == false) { - WMA_LOGE("%s: Dont send roam synch complete", __func__); - return; - } else { - wma_handle->interfaces[synchcnf->sessionId].roam_synch_in_progress = - false; - } wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); if (!wmi_buf) { WMA_LOGE("%s: wmi_buf_alloc failed", __func__); @@ -3303,7 +3409,7 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param, WMITLV_GET_STRUCT_TLVLEN (wmi_roam_synch_complete_fixed_param)); - cmd->vdev_id = synchcnf->sessionId; + cmd->vdev_id = vdev_id; 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", -- cgit v1.2.3 From 02216642cebc6dd31882e738d7de6f8fd6025751 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Thu, 7 Jan 2016 02:18:39 -0800 Subject: qcacld-3.0: Remove the cb_mode usage in channel bonding Remove the CB mode usage in channel bonding since the center center frequency is calculated using channel width and channel number. Change-Id: Ie9685a833750bf3b69cce40c5d9587fb9b232047 CRs-Fixed: 962174 --- core/cds/inc/cds_regdomain.h | 2 + core/cds/src/cds_reg_service.c | 24 ++++ core/mac/inc/sir_api.h | 36 +++++- core/mac/src/include/sir_params.h | 2 +- core/mac/src/pe/include/lim_global.h | 1 + core/mac/src/pe/lim/lim_process_sme_req_messages.c | 95 +++------------ core/mac/src/pe/lim/lim_send_management_frames.c | 135 --------------------- core/mac/src/pe/lim/lim_send_messages.h | 7 -- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 92 +++++++------- core/mac/src/pe/lim/lim_types.h | 8 -- core/mac/src/pe/lim/lim_utils.c | 6 +- core/mac/src/pe/lim/lim_utils.h | 53 -------- core/sap/inc/sap_api.h | 7 +- core/sap/src/sap_fsm.c | 127 ++++++------------- core/sap/src/sap_module.c | 76 ++---------- core/sme/inc/csr_api.h | 17 --- core/sme/inc/csr_internal.h | 5 +- core/sme/inc/sme_api.h | 5 +- core/sme/src/common/sme_api.c | 57 +++++---- core/sme/src/csr/csr_api_roam.c | 31 +++-- core/wma/src/wma_dev_if.c | 26 ---- 21 files changed, 230 insertions(+), 582 deletions(-) diff --git a/core/cds/inc/cds_regdomain.h b/core/cds/inc/cds_regdomain.h index 262677f201a1..28a22904024b 100644 --- a/core/cds/inc/cds_regdomain.h +++ b/core/cds/inc/cds_regdomain.h @@ -1094,5 +1094,7 @@ int32_t cds_get_country_from_alpha2(uint8_t *alpha2); void cds_fill_send_ctl_info_to_fw(struct regulatory *reg, uint32_t modesAvail, uint32_t modeSelect); void cds_set_wma_dfs_region(struct regulatory *reg); +void cds_set_ch_params(uint8_t ch, uint32_t phy_mode, + chan_params_t *ch_params); #endif /* REGULATORY_H */ diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index 016d5860b1bd..0e0b10ee5c4c 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -1458,3 +1458,27 @@ CDF_STATUS cds_set_reg_domain(void *client_ctxt, v_REGDOMAIN_t reg_domain) return CDF_STATUS_SUCCESS; } + +/** + * cds_set_ch_params() - set channel parameters + * @ch: channel + * @phy_mode: physical mode + * @ch_param: channel parameters will be returned + * + * Return: None + */ +void cds_set_ch_params(uint8_t ch, uint32_t phy_mode, + chan_params_t *ch_params) +{ + tHalHandle *hal_ctx = cds_get_context(CDF_MODULE_ID_PE); + if (!hal_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + ("Invalid hal_ctx pointer")); + return; + } + /* + * TODO: remove SME call and move the SME set channel + * param functionality to CDS. + */ + sme_set_ch_params(hal_ctx, phy_mode, ch, 0, ch_params); +} diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index bd2853f875ff..cdc23d7dd2eb 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -287,6 +287,36 @@ struct rrm_config_param { uint8_t max_randn_interval; uint8_t rm_capability[RMENABLEDCAP_MAX_LEN]; }; +/** + * typedef ch_width - channel width + * @CH_WIDTH_20MHZ: channel width 20 MHz + * @CH_WIDTH_40MHZ: channel width 40 MHz + * @CH_WIDTH_80MHZ: channel width 80MHz + * @CH_WIDTH_160MHZ: channel width 160 MHz + * @CH_WIDTH_80P80MHZ: channel width 160MHz(80+80) + */ +typedef enum ch_width { + CH_WIDTH_20MHZ = 0, + CH_WIDTH_40MHZ = 1, + CH_WIDTH_80MHZ = 2, + CH_WIDTH_160MHZ = 3, + CH_WIDTH_80P80MHZ = 4 +} phy_ch_width; + +/** + * struct ch_params_s + * + * @ch_width: channel width + * @sec_ch_offset: secondary channel offset + * @center_freq_seg0: center freq for segment 0 + * @center_freq_seg1: center freq for segment 1 + */ +typedef struct ch_params_s { + enum ch_width ch_width; + uint8_t sec_ch_offset; + uint8_t center_freq_seg0; + uint8_t center_freq_seg1; +} chan_params_t; /* each station added has a rate mode which specifies the sta attributes */ typedef enum eStaRateMode { @@ -3790,8 +3820,8 @@ typedef struct sSirChanChangeRequest { uint16_t messageType; uint16_t messageLen; uint8_t targetChannel; - uint8_t cbMode; - uint8_t channel_width; + uint8_t sec_ch_offset; + phy_ch_width ch_width; uint8_t center_freq_seg_0; uint8_t center_freq_seg_1; uint8_t bssid[CDF_MAC_ADDR_SIZE]; @@ -3872,7 +3902,7 @@ typedef struct sSirDfsCsaIeRequest { uint8_t targetChannel; uint8_t csaIeRequired; uint8_t bssid[CDF_MAC_ADDR_SIZE]; - uint8_t ch_bandwidth; + struct ch_params_s ch_params; } tSirDfsCsaIeRequest, *tpSirDfsCsaIeRequest; /* Indication from lower layer indicating the completion of first beacon send diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 64d4d624ecc1..6a4a485a195e 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -71,7 +71,7 @@ typedef enum { PHY_CHANNEL_BONDING_STATE_MAX = 11 } ePhyChanBondState; -#define MAX_BONDED_CHANNELS 4 +#define MAX_BONDED_CHANNELS 8 typedef enum { MCC = 0, diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index 07bd3bcc9224..a7747a1e67f6 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -512,6 +512,7 @@ typedef struct sLimChannelSwitchInfo { uint8_t primaryChannel; uint8_t ch_center_freq_seg0; uint8_t ch_center_freq_seg1; + uint8_t sec_ch_offset; phy_ch_width ch_width; int8_t switchCount; uint32_t switchTimeoutValue; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index da1d9b60001c..9544e1aea5e1 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -498,60 +498,6 @@ static bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal pMac, uint32_t *pMsgB return false; } -#ifdef WLAN_FEATURE_11AC - -uint32_t lim_get_center_channel(tpAniSirGlobal pMac, uint8_t primarychanNum, - ePhyChanBondState secondaryChanOffset, - uint8_t 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 - /** *lim_configure_ap_start_bss_session() - Configure the AP Start BSS in session. *@mac_ctx: Pointer to Global MAC structure @@ -5136,17 +5082,17 @@ static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx, "switch old chnl %d to new chnl %d, ch_bw %d"), session_entry->currentOperChannel, ch_change_req->targetChannel, - ch_change_req->channel_width); + ch_change_req->ch_width); /* Store the New Channel Params in session_entry */ - session_entry->ch_width = ch_change_req->channel_width; + session_entry->ch_width = ch_change_req->ch_width; session_entry->ch_center_freq_seg0 = ch_change_req->center_freq_seg_0; session_entry->ch_center_freq_seg1 = ch_change_req->center_freq_seg_1; - session_entry->htSecondaryChannelOffset = ch_change_req->cbMode; + session_entry->htSecondaryChannelOffset = ch_change_req->sec_ch_offset; session_entry->htSupportedChannelWidthSet = - (ch_change_req->channel_width ? 1 : 0); + (ch_change_req->ch_width ? 1 : 0); session_entry->htRecommendedTxWidthSet = session_entry->htSupportedChannelWidthSet; session_entry->currentOperChannel = @@ -5548,7 +5494,6 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, { tpSirDfsCsaIeRequest dfs_csa_ie_req; tpPESession session_entry = NULL; - uint32_t ch_width = 0; uint8_t session_id; tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch; @@ -5581,7 +5526,7 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, session_entry->dfsIncludeChanSwIe = true; session_entry->gLimChannelSwitch.switchCount = LIM_MAX_CSA_IE_UPDATES; session_entry->gLimChannelSwitch.ch_width = - dfs_csa_ie_req->ch_bandwidth; + dfs_csa_ie_req->ch_params.ch_width; if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) session_entry->gLimChannelSwitch.switchMode = 1; @@ -5592,16 +5537,10 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, if (true != session_entry->vhtCapability) goto skip_vht; - if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == - session_entry->vhtTxChannelWidthSet) - ch_width = eHT_CHANNEL_WIDTH_80MHZ; - else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == - session_entry->vhtTxChannelWidthSet) - ch_width = session_entry->htSupportedChannelWidthSet; /* Now encode the Wider Ch BW element depending on the ch width */ wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch; - switch (ch_width) { - case eHT_CHANNEL_WIDTH_20MHZ: + switch (dfs_csa_ie_req->ch_params.ch_width) { + case CH_WIDTH_20MHZ: /* * Wide channel BW sublement in channel wrapper element is not * required in case of 20 Mhz operation. Currently It is set @@ -5611,21 +5550,26 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; break; - case eHT_CHANNEL_WIDTH_40MHZ: - session_entry->dfsIncludeChanWrapperIe = true; + case CH_WIDTH_40MHZ: + session_entry->dfsIncludeChanWrapperIe = false; wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; break; - case eHT_CHANNEL_WIDTH_80MHZ: + case CH_WIDTH_80MHZ: session_entry->dfsIncludeChanWrapperIe = true; wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; break; - case eHT_CHANNEL_WIDTH_160MHZ: + case CH_WIDTH_160MHZ: session_entry->dfsIncludeChanWrapperIe = true; wider_bw_ch_switch->newChanWidth = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; break; + case CH_WIDTH_80P80MHZ: + session_entry->dfsIncludeChanWrapperIe = true; + wider_bw_ch_switch->newChanWidth = + WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; + break; default: session_entry->dfsIncludeChanWrapperIe = false; /* @@ -5637,16 +5581,15 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, } /* Fetch the center channel based on the channel width */ wider_bw_ch_switch->newCenterChanFreq0 = - lim_get_center_channel(mac_ctx, dfs_csa_ie_req->targetChannel, - session_entry->htSecondaryChannelOffset, - wider_bw_ch_switch->newChanWidth); + dfs_csa_ie_req->ch_params.center_freq_seg0; /* * 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. */ - wider_bw_ch_switch->newCenterChanFreq1 = 0; + wider_bw_ch_switch->newCenterChanFreq1 = + dfs_csa_ie_req->ch_params.center_freq_seg1; skip_vht: /* Send CSA IE request from here */ if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 62f452b6e97a..f99affbba849 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -4259,7 +4259,6 @@ lim_send_extended_chan_switch_action_frame(tpAniSirGlobal mac_ctx, return eSIR_SUCCESS; } /* End lim_send_extended_chan_switch_action_frame */ -#ifdef WLAN_FEATURE_11AC tSirRetStatus lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, tSirMacAddr peer, @@ -4369,140 +4368,6 @@ lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, 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 -lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac, - tSirMacAddr peer, - uint8_t nChanWidth, - uint8_t nNewChannel, - uint8_t ncbMode, tpPESession psessionEntry) -{ - tDot11fChannelSwitch frm; - uint8_t *pFrame; - tpSirMacMgmtHdr pMacHdr; - uint32_t nBytes, nPayload, nStatus; /* , nCfg; */ - void *pPacket; - CDF_STATUS cdf_status; - uint8_t txFlag = 0; - - uint8_t smeSessionId = 0; - - if (psessionEntry == NULL) { - PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));) - return eSIR_FAILURE; - } - smeSessionId = psessionEntry->smeSessionId; - - cdf_mem_set((uint8_t *) &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 = - lim_get_htcb_state(ncbMode); - frm.sec_chan_offset_ele.present = 1; - frm.WiderBWChanSwitchAnn.newChanWidth = nChanWidth; - frm.WiderBWChanSwitchAnn.newCenterChanFreq0 = - lim_get_center_channel(pMac, nNewChannel, ncbMode, nChanWidth); - frm.WiderBWChanSwitchAnn.newCenterChanFreq1 = 0; - frm.ChanSwitchAnn.present = 1; - frm.WiderBWChanSwitchAnn.present = 1; - - nStatus = dot11f_get_packed_channel_switch_size(pMac, &frm, &nPayload); - if (DOT11F_FAILED(nStatus)) { - lim_log(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)) { - lim_log(pMac, LOGW, FL("There were warnings while calculating " - "the packed size for a Channel Switch (0x" - "%08x)."), nStatus); - } - - nBytes = nPayload + sizeof(tSirMacMgmtHdr); - - cdf_status = - cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame, - (void **)&pPacket); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { - lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report."), nBytes); - return eSIR_FAILURE; - } - /* Paranoia: */ - cdf_mem_set(pFrame, nBytes, 0); - - /* Next, we fill out the buffer descriptor: */ - lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME, - SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr); - pMacHdr = (tpSirMacMgmtHdr) pFrame; - cdf_mem_copy((uint8_t *) pMacHdr->bssId, - (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr)); - nStatus = dot11f_pack_channel_switch(pMac, &frm, pFrame + - sizeof(tSirMacMgmtHdr), - nPayload, &nPayload); - if (DOT11F_FAILED(nStatus)) { - lim_log(pMac, LOGE, - FL("Failed to pack a Channel Switch (0x%08x)."), - nStatus); - cds_packet_free((void *)pPacket); - return eSIR_FAILURE; /* allocated! */ - } else if (DOT11F_WARNED(nStatus)) { - lim_log(pMac, LOGW, FL("There were warnings while packing a C" - "hannel Switch (0x%08x)."), nStatus); - } - - if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel)) - || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) || - (psessionEntry->pePersona == CDF_P2P_GO_MODE) - ) { - txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; - } - - MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT, - psessionEntry->peSessionId, pMacHdr->fc.subType)); - cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes, - TXRX_FRM_802_11_MGMT, - ANI_TXDIR_TODS, - 7, lim_tx_complete, pFrame, txFlag, - smeSessionId, 0); - MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE, - psessionEntry->peSessionId, cdf_status)); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { - lim_log(pMac, LOGE, - FL("Failed to send a Channel Switch (%X)!"), - cdf_status); - /* Pkt will be freed up by the callback */ - return eSIR_FAILURE; - } - - return eSIR_SUCCESS; - -} /* End lim_send_vht_channel_switch_mgmt_frame. */ - -#endif - #if defined WLAN_FEATURE_VOWIFI /** diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h index d884de757253..95161fbab130 100644 --- a/core/mac/src/pe/lim/lim_send_messages.h +++ b/core/mac/src/pe/lim/lim_send_messages.h @@ -49,7 +49,6 @@ tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, tpUpdateBeaconParams pUpdatedBcnParams, tpPESession psessionEntry); /* tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, tpUpdateBeaconParams pUpdatedBcnParams); */ -#ifdef WLAN_FEATURE_11AC tSirRetStatus lim_send_mode_update(tpAniSirGlobal pMac, tUpdateVHTOpMode *tempParam, tpPESession psessionEntry); @@ -57,11 +56,6 @@ tSirRetStatus lim_send_rx_nss_update(tpAniSirGlobal pMac, tUpdateRxNss *tempParam, tpPESession psessionEntry); -uint32_t lim_get_center_channel(tpAniSirGlobal pMac, - uint8_t primarychanNum, - ePhyChanBondState secondaryChanOffset, - uint8_t chanWidth); - tSirRetStatus lim_set_membership(tpAniSirGlobal pMac, tUpdateMembership *pTempParam, tpPESession psessionEntry); @@ -69,7 +63,6 @@ tSirRetStatus lim_set_membership(tpAniSirGlobal pMac, tSirRetStatus lim_set_user_pos(tpAniSirGlobal pMac, tUpdateUserPos *pTempParam, tpPESession psessionEntry); -#endif #if defined WLAN_FEATURE_VOWIFI tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, uint8_t chnlNumber, diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index ff4848c2dd44..ec9f22e98332 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2021,9 +2021,10 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) uint8_t session_id; uint16_t aid = 0; uint16_t chan_space = 0; - int cb_mode = 0; + chan_params_t ch_params; tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL; + tLimChannelSwitchInfo *lim_ch_switch = NULL; if (!csa_params) { lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL")); @@ -2055,6 +2056,7 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) */ lim_delete_tdls_peers(mac_ctx, session_entry); + lim_ch_switch = &session_entry->gLimChannelSwitch; session_entry->gLimChannelSwitch.switchMode = csa_params->switchmode; /* timer already started by firmware, switch immediately */ @@ -2064,7 +2066,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) session_entry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ; - + lim_ch_switch->sec_ch_offset = + session_entry->htSecondaryChannelOffset; session_entry->gLimChannelSwitch.ch_center_freq_seg0 = 0; session_entry->gLimChannelSwitch.ch_center_freq_seg1 = 0; chnl_switch_info = @@ -2102,20 +2105,17 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) } else { chnl_switch_info->newChanWidth = CH_WIDTH_20MHZ; - session_entry->gLimChannelSwitch.state = + lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; } - cb_mode = lim_select_cb_mode_for_sta( - session_entry, - csa_params->channel, - chan_space); - + ch_params.ch_width = + chnl_switch_info->newChanWidth; + cds_set_ch_params(csa_params->channel, + eCSR_DOT11_MODE_11ac, + &ch_params); chnl_switch_info->newCenterChanFreq0 = - lim_get_center_channel(mac_ctx, - csa_params->channel, - cb_mode, - chnl_switch_info->newChanWidth); + ch_params.center_freq_seg0; /* * This is not applicable for 20/40/80 MHz. * Only used when we support 80+80 MHz operation. @@ -2123,7 +2123,10 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) * center channel frequency index of 80 MHz * channel offrequency segment 1. */ - chnl_switch_info->newCenterChanFreq1 = 0; + chnl_switch_info->newCenterChanFreq1 = + ch_params.center_freq_seg1; + lim_ch_switch->sec_ch_offset = + ch_params.sec_ch_offset; } session_entry->gLimChannelSwitch.ch_center_freq_seg0 = @@ -2141,56 +2144,47 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) mac_ctx->scan.countryCodeCurrent, csa_params->channel, csa_params->new_op_class); - session_entry->gLimChannelSwitch.state = + lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; if (chan_space == 40) { - session_entry-> - gLimChannelSwitch.ch_width = + lim_ch_switch->ch_width = CH_WIDTH_40MHZ; chnl_switch_info->newChanWidth = CH_WIDTH_40MHZ; - cb_mode = lim_select_cb_mode_for_sta( - session_entry, - csa_params->channel, - chan_space); - if (cb_mode == - PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { - session_entry-> - gLimChannelSwitch. - ch_center_freq_seg0 = - csa_params->channel + 2; - } else if (cb_mode == - PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) { - session_entry-> - gLimChannelSwitch. - ch_center_freq_seg0 = - csa_params->channel - 2; - } - + ch_params.ch_width = + chnl_switch_info->newChanWidth; + cds_set_ch_params(csa_params->channel, + eCSR_DOT11_MODE_11n, + &ch_params); + lim_ch_switch->ch_center_freq_seg0 = + ch_params.center_freq_seg0; + lim_ch_switch->sec_ch_offset = + ch_params.sec_ch_offset; } else { - session_entry-> - gLimChannelSwitch.ch_width = + lim_ch_switch->ch_width = CH_WIDTH_20MHZ; chnl_switch_info->newChanWidth = CH_WIDTH_40MHZ; - session_entry->gLimChannelSwitch.state = + lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; + lim_ch_switch->sec_ch_offset = + PHY_SINGLE_CHANNEL_CENTERED; } - - - } - - if (csa_params->sec_chan_offset) { - session_entry->gLimChannelSwitch.ch_width = + } else { + lim_ch_switch->ch_width = CH_WIDTH_40MHZ; - session_entry->gLimChannelSwitch.state = + lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; - } else { - session_entry->htSupportedChannelWidthSet = - WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - session_entry->htRecommendedTxWidthSet = - session_entry->htSupportedChannelWidthSet; + ch_params.ch_width = CH_WIDTH_40MHZ; + cds_set_ch_params(csa_params->channel, + eCSR_DOT11_MODE_11n, + &ch_params); + lim_ch_switch->ch_center_freq_seg0 = + ch_params.center_freq_seg0; + lim_ch_switch->sec_ch_offset = + ch_params.sec_ch_offset; } + } lim_log(mac_ctx, LOG1, FL("new ch width = %d"), session_entry->gLimChannelSwitch.ch_width); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 99ff48599312..c4b575058c79 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -497,17 +497,9 @@ 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 lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac, tSirMacAddr peer, uint8_t nMode, tpPESession psessionEntry); -tSirRetStatus lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac, - tSirMacAddr peer, - uint8_t nChanWidth, - uint8_t nNewChannel, - uint8_t ncbMode, - tpPESession psessionEntry); -#endif #if defined WLAN_FEATURE_VOWIFI tSirRetStatus lim_send_neighbor_report_request_frame(tpAniSirGlobal, diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 00d416928ff0..0b90d19ad229 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -2810,11 +2810,13 @@ void lim_switch_primary_secondary_channel(tpAniSirGlobal pMac, psessionEntry->currentOperChannel, newChannel); psessionEntry->currentOperChannel = newChannel; } - if (psessionEntry->htSecondaryChannelOffset != subband) { + if (psessionEntry->htSecondaryChannelOffset != + psessionEntry->gLimChannelSwitch.sec_ch_offset) { lim_log(pMac, LOGW, FL("switch old sec chnl %d --> new sec chnl %d "), psessionEntry->htSecondaryChannelOffset, subband); - psessionEntry->htSecondaryChannelOffset = subband; + psessionEntry->htSecondaryChannelOffset = + psessionEntry->gLimChannelSwitch.sec_ch_offset; if (psessionEntry->htSecondaryChannelOffset == PHY_SINGLE_CHANNEL_CENTERED) { psessionEntry->htSupportedChannelWidthSet = diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 42a5eab8e451..cd9d6a1a1bf3 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -294,59 +294,6 @@ is_entering_mimo_ps(tSirMacHTMIMOPowerSaveState curState, return false; } -/** - * lim_select_cb_mode_for_sta() - return cb_mode based on current session - * @session_entry: Session entry - * @channel: channel - * @chan_bw: channel bandwidth - * - * Given a value of channel and bandwidth this API will return the value of - * cb_mode on basis of channel, bandwidth ht/vht capabilities - * - * Return: cb_mode - * - */ - -static inline int lim_select_cb_mode_for_sta(tpPESession session_entry, - uint8_t channel, uint8_t chan_bw) -{ - if (session_entry->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 (session_entry->htSupportedChannelWidthSet) { - 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; -} - - static inline int lim_select_cb_mode(tDphHashNode *pStaDs, tpPESession psessionEntry, uint8_t channel, uint8_t chan_bw) diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 40f3b2d3073a..ffe912c33b2b 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -625,10 +625,9 @@ typedef struct sSapDfsInfo { * New channel width and new channel bonding mode * will only be updated via channel fallback mechanism */ - uint8_t orig_cbMode; - uint8_t orig_chanWidth; - uint8_t new_chanWidth; - uint8_t new_cbMode; + phy_ch_width orig_chanWidth; + phy_ch_width new_chanWidth; + chan_params_t new_ch_params; /* * INI param to enable/disable SAP W53 diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 8335de53ab5f..771fc58cf699 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -878,23 +878,19 @@ static inline void sap_event_init(ptWLAN_SAPEvent sapEvent) #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION /* - * This function gives the leakage matrix for given NOL channel and cbMode + * sap_find_target_channel_in_channel_matrix() - finds the leakage matrix + * @sapContext: Pointer to vos global context structure + * @ch_width: target channel width + * @NOL_channel: the NOL channel whose leakage matrix is required + * @pTarget_chnl_mtrx: pointer to target channel matrix returned. * - * 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. + * This function gives the leakage matrix for given NOL channel and ch_width * - * RETURN VALUE - * BOOLEAN - * TRUE: leakage matrix was found - * FALSE: leakage matrix was not found + * Return: TRUE or FALSE */ bool sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, - ePhyChanBondState cbMode, + phy_ch_width ch_width, uint8_t NOL_channel, tSapTxLeakInfo **pTarget_chnl_mtrx) { @@ -903,28 +899,22 @@ sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, uint32_t nchan_matrix; int i = 0; - switch (cbMode) { - case PHY_SINGLE_CHANNEL_CENTERED: + switch (ch_width) { + case CH_WIDTH_20MHZ: /* HT20 */ pchan_matrix = ht20_chan; nchan_matrix = CDF_ARRAY_SIZE(ht20_chan); break; - case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: - case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + case CH_WIDTH_40MHZ: /* HT40 */ pchan_matrix = ht40_chan; nchan_matrix = CDF_ARRAY_SIZE(ht40_chan); 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: + case CH_WIDTH_80MHZ: /* HT80 */ pchan_matrix = ht80_chan; nchan_matrix = CDF_ARRAY_SIZE(ht80_chan); break; -#endif default: /* handle exception and fall back to HT20 table */ pchan_matrix = ht20_chan; @@ -951,7 +941,7 @@ sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, /** * sap_mark_channels_leaking_into_nol() - to mark channel leaking in to nol * @sap_ctx: pointer to SAP context - * @cb_mode: channel bonding mode + * @ch_width: channel width * @nol: nol info * @temp_ch_lst_sz: the target channel list * @temp_ch_lst: the target channel list @@ -965,7 +955,7 @@ sap_find_target_channel_in_channel_matrix(ptSapContext sapContext, CDF_STATUS sap_mark_channels_leaking_into_nol(ptSapContext sap_ctx, - ePhyChanBondState cb_mode, + phy_ch_width ch_width, tSapDfsNolInfo *nol, uint8_t temp_ch_lst_sz, uint8_t *temp_ch_lst) @@ -990,7 +980,7 @@ sap_mark_channels_leaking_into_nol(ptSapContext sap_ctx, FL("sapdfs: processing NOL channel: %d"), dfs_nol_channel); if (false == sap_find_target_channel_in_channel_matrix( - sap_ctx, cb_mode, dfs_nol_channel, + sap_ctx, ch_width, dfs_nol_channel, &target_chan_matrix)) { /* * should never happen, we should always find a table @@ -1066,9 +1056,9 @@ static void sap_set_bitmap(chan_bonding_bitmap *pBitmap, uint8_t channel) } /** - * sap_populate_available_channels - To populate available channel + * sap_populate_available_channels() - To populate available channel * @bitmap: bitmap to populate - * @current_cbmode: cb mode to check for channel availability + * @ch_width: channel width * @avail_chnl: available channel list to populate * * This function reads the bitmap and populates available channel @@ -1079,20 +1069,16 @@ static void sap_set_bitmap(chan_bonding_bitmap *pBitmap, uint8_t channel) * Return: number of channels found */ static uint8_t sap_populate_available_channels(chan_bonding_bitmap *bitmap, - ePhyChanBondState current_cbmode, + phy_ch_width ch_width, uint8_t *avail_chnl) { uint8_t i = 0; uint8_t chnl_count = 0; uint8_t start_channel = 0; - switch (current_cbmode) { -#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: + switch (ch_width) { + /* VHT80 */ + case CH_WIDTH_80MHZ: for (i = 0; i < MAX_80MHZ_BANDS; i++) { start_channel = bitmap->chanBondingSet[i].startChannel; if (bitmap->chanBondingSet[i].channelMap == @@ -1104,10 +1090,8 @@ static uint8_t sap_populate_available_channels(chan_bonding_bitmap *bitmap, } } break; -#endif /* HT40 */ - case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: - case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: + case CH_WIDTH_40MHZ: for (i = 0; i < MAX_80MHZ_BANDS; i++) { start_channel = bitmap->chanBondingSet[i].startChannel; if ((bitmap->chanBondingSet[i].channelMap & @@ -1262,8 +1246,7 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) uint8_t channelID; tHalHandle hHal = CDS_GET_HAL_CB(sapContext->p_cds_gctx); tpAniSirGlobal pMac; - uint32_t chanWidth; - ePhyChanBondState cbModeCurrent; + phy_ch_width ch_width; uint8_t *tmp_ch_lst = NULL; uint8_t dfs_region; @@ -1280,19 +1263,6 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) 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 = - (sapContext->ch_width_orig > CH_WIDTH_20MHZ ? 1 : 0); - 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 @@ -1301,9 +1271,9 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) if (pMac->sap.SapDfsInfo.orig_chanWidth == 0) { pMac->sap.SapDfsInfo.orig_chanWidth = sapContext->ch_width_orig; - chanWidth = pMac->sap.SapDfsInfo.orig_chanWidth; + ch_width = pMac->sap.SapDfsInfo.orig_chanWidth; } else { - chanWidth = pMac->sap.SapDfsInfo.orig_chanWidth; + ch_width = pMac->sap.SapDfsInfo.orig_chanWidth; } if (sap_get5_g_hz_channel_list(sapContext)) { @@ -1471,7 +1441,7 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) ); if (CDF_STATUS_SUCCESS != sap_mark_channels_leaking_into_nol(sapContext, - cbModeCurrent, + ch_width, nol, valid_chnl_count, tmp_ch_lst)) { @@ -1505,8 +1475,7 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) * for 20MHz, directly create available * channel list */ - if (cbModeCurrent == - PHY_SINGLE_CHANNEL_CENTERED) { + if (ch_width == CH_WIDTH_20MHZ) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_DEBUG, FL @@ -1529,18 +1498,17 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) * if 40 MHz or 80 MHz, populate available * channel list from bitmap */ - if (cbModeCurrent != PHY_SINGLE_CHANNEL_CENTERED) { + if (ch_width != CH_WIDTH_20MHZ) { available_ch_cnt = sap_populate_available_channels(&channelBitmap, - cbModeCurrent, + ch_width, availableChannels); /* * if no valid channel bonding found, * fallback to lower bandwidth */ if (available_ch_cnt == 0) { - if (cbModeCurrent >= - PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED) { + if (ch_width == CH_WIDTH_80MHZ) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, FL @@ -1549,22 +1517,12 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) CDF_TRACE_LEVEL_WARN, FL ("sapdfs:Changing chanWidth from [%d] to [%d]"), - chanWidth, + ch_width, CH_WIDTH_40MHZ); - CDF_TRACE(CDF_MODULE_ID_SAP, - CDF_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 = CH_WIDTH_40MHZ; + ch_width = CH_WIDTH_40MHZ; /* continue to start of do loop */ continue; - } else if (cbModeCurrent >= - PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { + } else if (ch_width == CH_WIDTH_40MHZ) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN, FL @@ -1573,17 +1531,9 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) CDF_TRACE_LEVEL_WARN, FL ("sapdfs:Changing chanWidth from [%d] to [%d]"), - chanWidth, + ch_width, CH_WIDTH_20MHZ); - CDF_TRACE(CDF_MODULE_ID_SAP, - CDF_TRACE_LEVEL_WARN, - FL - ("sapdfs:Changing CB mode from [%d] to [%d]"), - cbModeCurrent, - PHY_SINGLE_CHANNEL_CENTERED); - cbModeCurrent = - PHY_SINGLE_CHANNEL_CENTERED; - chanWidth = CH_WIDTH_20MHZ; + ch_width = CH_WIDTH_20MHZ; /* continue to start of do loop */ continue; } @@ -1629,12 +1579,7 @@ static uint8_t sap_random_channel_sel(ptSapContext sapContext) target_channel = avail_dfs_chan_list[i]; } - pMac->sap.SapDfsInfo.new_chanWidth = chanWidth; - pMac->sap.SapDfsInfo.new_cbMode = cbModeCurrent; - CDF_TRACE(CDF_MODULE_ID_SAP, - CDF_TRACE_LEVEL_INFO_LOW, - FL("sapdfs: New CB mode = %d"), - pMac->sap.SapDfsInfo.new_cbMode); + pMac->sap.SapDfsInfo.new_chanWidth = ch_width; CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, FL("sapdfs: New Channel width = %d"), diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 83658309b097..40fcc28bd150 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1425,7 +1425,6 @@ static CDF_STATUS wlansap_update_csa_channel_params(ptSapContext sap_context, { void *hal; tpAniSirGlobal mac_ctx; - tSmeConfigParams *sme_config; uint8_t bw; hal = CDS_GET_HAL_CB(sap_context->p_cds_gctx); @@ -1437,23 +1436,12 @@ static CDF_STATUS wlansap_update_csa_channel_params(ptSapContext sap_context, mac_ctx = PMAC_STRUCT(hal); - sme_config = cdf_mem_malloc(sizeof(*sme_config)); - if (!sme_config) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - FL("memory allocation failed for sme_config")); - return CDF_STATUS_E_NOMEM; - } - - sme_get_config_param(mac_ctx, sme_config); if (channel <= RF_CHAN_14) { /* * 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. */ - sme_config->csrConfig.channelBondingMode24GHz = - eCSR_INI_SINGLE_CHANNEL_CENTERED; - mac_ctx->sap.SapDfsInfo.new_cbMode = 0; mac_ctx->sap.SapDfsInfo.new_chanWidth = 0; } else { @@ -1475,37 +1463,23 @@ static CDF_STATUS wlansap_update_csa_channel_params(ptSapContext sap_context, continue; if (bw == BW80) { - wlansap_update_bw80_cbmode(channel, sme_config); - mac_ctx->sap.SapDfsInfo.new_cbMode = - sme_config->csrConfig.channelBondingMode5GHz; mac_ctx->sap.SapDfsInfo.new_chanWidth = CH_WIDTH_80MHZ; } else if (bw == BW40_HIGH_PRIMARY) { mac_ctx->sap.SapDfsInfo.new_chanWidth = CH_WIDTH_40MHZ; - sme_config->csrConfig.channelBondingMode5GHz = - mac_ctx->sap.SapDfsInfo.new_cbMode = - eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY; } else if (bw == BW40_LOW_PRIMARY) { mac_ctx->sap.SapDfsInfo.new_chanWidth = CH_WIDTH_40MHZ; - sme_config->csrConfig.channelBondingMode5GHz = - mac_ctx->sap.SapDfsInfo.new_cbMode = - eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY; } else { mac_ctx->sap.SapDfsInfo.new_chanWidth = CH_WIDTH_20MHZ; - sme_config->csrConfig.channelBondingMode5GHz = - mac_ctx->sap.SapDfsInfo.new_cbMode = - eCSR_INI_SINGLE_CHANNEL_CENTERED; } break; } } - sme_update_config(mac_ctx, sme_config); - cdf_mem_free(sme_config); return CDF_STATUS_SUCCESS; } @@ -1599,6 +1573,13 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) * to sap context. */ pMac->sap.SapDfsInfo.target_channel = targetChannel; + pMac->sap.SapDfsInfo.new_ch_params.ch_width = + pMac->sap.SapDfsInfo.new_chanWidth; + sme_set_ch_params(hHal, + sapContext->csr_roamProfile.phyMode, + targetChannel, + 0, + &pMac->sap.SapDfsInfo.new_ch_params); /* * Set the CSA IE required flag. */ @@ -2307,8 +2288,6 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel) void *hHal = NULL; tpAniSirGlobal mac_ctx = NULL; eCsrPhyMode phy_mode; - uint32_t cb_mode; - uint32_t vht_channel_width; chan_params_t ch_params; sapContext = (ptSapContext) pSapCtx; @@ -2332,18 +2311,16 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel) * because we've implemented channel width fallback mechanism for DFS * which will result in channel width changing dynamically. */ - cb_mode = mac_ctx->sap.SapDfsInfo.new_cbMode; - vht_channel_width = mac_ctx->sap.SapDfsInfo.new_chanWidth; - ch_params.ch_width = vht_channel_width; + ch_params.ch_width = mac_ctx->sap.SapDfsInfo.new_chanWidth; sme_set_ch_params(hHal, phy_mode, target_channel, 0, &ch_params); - sapContext->ch_params.ch_width = vht_channel_width; + sapContext->ch_params.ch_width = ch_params.ch_width; /* Update the channel as this will be used to * send event to supplicant */ sapContext->channel = target_channel; - sapContext->csr_roamProfile.ch_params.ch_width = vht_channel_width; + sapContext->csr_roamProfile.ch_params.ch_width = ch_params.ch_width; cdf_ret_status = sme_roam_channel_change_req(hHal, sapContext->bssid, - cb_mode, &sapContext->csr_roamProfile); + &ch_params, &sapContext->csr_roamProfile); if (cdf_ret_status == CDF_STATUS_SUCCESS) { sap_signal_hdd_event(sapContext, NULL, @@ -2446,8 +2423,6 @@ CDF_STATUS wlansap_dfs_send_csa_ie_request(void *pSapCtx) CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; void *hHal = NULL; tpAniSirGlobal pMac = NULL; - uint32_t cbmode, vht_ch_width; - uint8_t ch_bandwidth; sapContext = (ptSapContext) pSapCtx; if (NULL == sapContext) { @@ -2464,38 +2439,11 @@ CDF_STATUS wlansap_dfs_send_csa_ie_request(void *pSapCtx) } pMac = PMAC_STRUCT(hHal); - /* - * We are getting channel bonding mode from sapDfsInfor structure - * because we've implemented channel width fallback mechanism for DFS - * which will result in channel width changing dynamically. - */ - vht_ch_width = pMac->sap.SapDfsInfo.new_chanWidth; - cbmode = pMac->sap.SapDfsInfo.new_cbMode; - - 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; - } - cdf_ret_status = sme_roam_csa_ie_request(hHal, sapContext->bssid, pMac->sap.SapDfsInfo.target_channel, pMac->sap.SapDfsInfo.csaIERequired, - ch_bandwidth); + &pMac->sap.SapDfsInfo.new_ch_params); if (cdf_ret_status == CDF_STATUS_SUCCESS) { return CDF_STATUS_SUCCESS; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 1bb5b5c0b9eb..82d3cfcb4ad1 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -40,21 +40,6 @@ #define CSR_INVALID_SCANRESULT_HANDLE (NULL) -typedef enum { - CH_WIDTH_20MHZ = 0, - CH_WIDTH_40MHZ = 1, - CH_WIDTH_80MHZ = 2, - CH_WIDTH_160MHZ = 3, - CH_WIDTH_80P80MHZ = 4 -} phy_ch_width; - -typedef struct ch_params_s { - phy_ch_width ch_width; - uint8_t sec_ch_offset; - uint8_t center_freq_seg0; - uint8_t center_freq_seg1; -} chan_params_t; - typedef enum { /* never used */ eCSR_AUTH_TYPE_NONE, @@ -145,10 +130,8 @@ typedef enum { 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 diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 1140a54ed4dd..a7e5d4d6f9b1 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -1333,7 +1333,7 @@ bool csr_roam_is_sta_mode(tpAniSirGlobal pMac, uint32_t sessionId); /* Post Channel Change Indication */ CDF_STATUS csr_roam_channel_change_req(tpAniSirGlobal pMac, - struct cdf_mac_addr bssid, uint8_t cb_mode, + struct cdf_mac_addr bssid, chan_params_t *ch_params, tCsrRoamProfile *profile); /* Post Beacon Tx Start Indication */ @@ -1342,7 +1342,8 @@ CDF_STATUS csr_roam_start_beacon_req(tpAniSirGlobal pMac, CDF_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal pMac, struct cdf_mac_addr bssid, - uint8_t targetChannel, uint8_t csaIeReqd, uint8_t ch_bandwidth); + uint8_t targetChannel, uint8_t csaIeReqd, + chan_params_t *ch_params); CDF_STATUS csr_roam_modify_add_ies(tpAniSirGlobal pMac, tSirModifyIE *pModifyIE, eUpdateIEsType updateType); diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9ef7599b29ed..413a80152896 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -786,12 +786,13 @@ CDF_STATUS sme_set_auto_shutdown_cb(tHalHandle hHal, void (*pCallbackfn)(void)); CDF_STATUS sme_set_auto_shutdown_timer(tHalHandle hHal, uint32_t timer_value); #endif CDF_STATUS sme_roam_channel_change_req(tHalHandle hHal, - struct cdf_mac_addr bssid, uint32_t cb_mode, + struct cdf_mac_addr bssid, chan_params_t *ch_params, tCsrRoamProfile *profile); CDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, struct cdf_mac_addr bssid, uint8_t dfsCacWaitStatus); CDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct cdf_mac_addr bssid, - uint8_t targetChannel, uint8_t csaIeReqd, uint8_t ch_bandwidth); + uint8_t targetChannel, uint8_t csaIeReqd, + chan_params_t *ch_params); CDF_STATUS sme_init_thermal_info(tHalHandle hHal, tSmeThermalParams thermalParam); CDF_STATUS sme_set_thermal_level(tHalHandle hHal, uint8_t level); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a1d4a534a384..1d45f67c78c8 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -11995,32 +11995,28 @@ CDF_STATUS sme_set_mas(uint32_t val) return CDF_STATUS_SUCCESS; } -/* ------------------------------------------------------------------------- - \fn sme_roam_channel_change_req - \brief API to Indicate Channel change to new target channel - \param hHal - The handle returned by mac_open - \param targetChannel - New Channel to move the SAP to. - \return CDF_STATUS - ---------------------------------------------------------------------------*/ +/** + * sme_roam_channel_change_req() - Channel change to new target channel + * @hHal: handle returned by mac_open + * @bssid: mac address of BSS + * @ch_params: target channel information + * @profile: CSR profile + * + * API to Indicate Channel change to new target channel + * + * Return: CDF_STATUS + */ CDF_STATUS sme_roam_channel_change_req(tHalHandle hHal, - struct cdf_mac_addr bssid, uint32_t cb_mode, tCsrRoamProfile *profile) + struct cdf_mac_addr bssid, chan_params_t *ch_params, + tCsrRoamProfile *profile) { CDF_STATUS status = CDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - uint8_t ch_mode; - - ch_mode = (profile->ChannelInfo.ChannelList[0] <= - CSR_MAX_2_4_GHZ_SUPPORTED_CHANNELS) ? - pMac->roam.configParam.channelBondingMode24GHz : - pMac->roam.configParam.channelBondingMode5GHz; status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { - CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO_MED, - FL("sapdfs: requested cbmode=[%d] & new negotiated cbmode[%d]"), - cb_mode, ch_mode); - status = csr_roam_channel_change_req(pMac, bssid, ch_mode, + status = csr_roam_channel_change_req(pMac, bssid, ch_params, profile); sme_release_global_lock(&pMac->sme); } @@ -12109,25 +12105,26 @@ CDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, struct cdf_mac_addr bssid, return status; } -/* ------------------------------------------------------------------------- - \fn sme_roam_csa_ie_request - \brief API to request CSA IE transmission from PE - \param hHal - The handle returned by mac_open - \param pDfsCsaReq - CSA IE request - \param bssid - SAP bssid - \param ch_bandwidth - Channel offset - \return CDF_STATUS - ---------------------------------------------------------------------------*/ +/** + * sme_roam_csa_ie_request() - request CSA IE transmission from PE + * @hHal: handle returned by mac_open + * @bssid: SAP bssid + * @targetChannel: target channel information + * @csaIeReqd: CSA IE Request + * @ch_params: channel information + * + * Return: CDF_STATUS + */ CDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct cdf_mac_addr bssid, uint8_t targetChannel, uint8_t csaIeReqd, - uint8_t ch_bandwidth) + chan_params_t *ch_params) { CDF_STATUS status = CDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { - status = csr_roam_send_chan_sw_ie_request(pMac, bssid, targetChannel, - csaIeReqd, ch_bandwidth); + status = csr_roam_send_chan_sw_ie_request(pMac, bssid, + targetChannel, csaIeReqd, ch_params); sme_release_global_lock(&pMac->sme); } return status; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 813c2c7a9036..08f422d9db55 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17964,14 +17964,21 @@ CDF_STATUS csr_roam_read_tsf(tpAniSirGlobal pMac, uint8_t *pTimestamp, } #endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ -/* - * Post Channel Change Request to LIM +/** + * csr_roam_channel_change_req() - Post channel change request to LIM + * @pMac: mac context + * @bssid: SAP bssid + * @ch_params: channel information + * @profile: CSR profile + * * This API is primarily used to post * Channel Change Req for SAP + * + * Return: CDF_STATUS */ -CDF_STATUS -csr_roam_channel_change_req(tpAniSirGlobal pMac, struct cdf_mac_addr bssid, - uint8_t cbMode, tCsrRoamProfile *profile) +CDF_STATUS csr_roam_channel_change_req(tpAniSirGlobal pMac, + struct cdf_mac_addr bssid, + chan_params_t *ch_params, tCsrRoamProfile *profile) { CDF_STATUS status = CDF_STATUS_SUCCESS; tSirChanChangeRequest *pMsg; @@ -17988,12 +17995,12 @@ csr_roam_channel_change_req(tpAniSirGlobal pMac, struct cdf_mac_addr bssid, pMsg->messageType = eWNI_SME_CHANNEL_CHANGE_REQ; pMsg->messageLen = sizeof(tSirChanChangeRequest); pMsg->targetChannel = profile->ChannelInfo.ChannelList[0]; - pMsg->cbMode = cbMode; - pMsg->channel_width = profile->ch_params.ch_width; + pMsg->sec_ch_offset = ch_params->sec_ch_offset; + pMsg->ch_width = profile->ch_params.ch_width; pMsg->dot11mode = csr_translate_to_wni_cfg_dot11_mode(pMac, pMac->roam.configParam.uCfgDot11Mode); - pMsg->center_freq_seg_0 = pMsg->targetChannel; - pMsg->center_freq_seg_1 = 0; + pMsg->center_freq_seg_0 = ch_params->center_freq_seg0; + pMsg->center_freq_seg_1 = ch_params->center_freq_seg1; cdf_mem_copy(pMsg->bssid, bssid.bytes, CDF_MAC_ADDR_SIZE); cdf_mem_copy(&pMsg->operational_rateset, ¶m.operationalRateSet, sizeof(pMsg->operational_rateset)); @@ -18194,7 +18201,7 @@ CDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t channel, * @bssid: BSSID * @target_channel: Channel on which to send the IE * @csa_ie_reqd: Include/Exclude CSA IE. - * @ch_bandwidth: Channel offset + * @ch_params: operating Channel related information * * This function sends request to transmit channel switch announcement * IE to lower layers @@ -18204,7 +18211,7 @@ CDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t channel, CDF_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx, struct cdf_mac_addr bssid, uint8_t target_channel, - uint8_t csa_ie_reqd, uint8_t ch_bandwidth) + uint8_t csa_ie_reqd, chan_params_t *ch_params) { CDF_STATUS status = CDF_STATUS_SUCCESS; tSirDfsCsaIeRequest *msg; @@ -18221,7 +18228,7 @@ csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx, msg->targetChannel = target_channel; msg->csaIeRequired = csa_ie_reqd; cdf_mem_copy(msg->bssid, bssid.bytes, CDF_MAC_ADDR_SIZE); - msg->ch_bandwidth = ch_bandwidth; + cdf_mem_copy(&msg->ch_params, ch_params, sizeof(chan_params_t)); status = cds_send_mb_message_to_mac(msg); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 8d906c2f51a4..4aac03ff2f7f 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1921,32 +1921,6 @@ end: return txrx_vdev_handle; } -/** - * wma_get_center_channel() - get center channel - * @chan: channel number - * @chan_offset: channel offset - * - * Return: center channel - */ -uint8_t wma_get_center_channel(uint8_t chan, uint8_t chan_offset) -{ - uint8_t 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; -} - /** * wma_vdev_start() - send vdev start request to fw * @wma: wma handle -- cgit v1.2.3 From 28c9b2ab7104264497431387fea1434a488b5060 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Mon, 11 Jan 2016 19:28:52 +0530 Subject: qcacld-3.0: Fix invalid operating class calculation during channel switch Fix invalid operating class calculation while sending out channel switch frames. The operating class is getting wrongly calculated using the channel width instead of the channel offset. Fix this by calculating and passing the channel offset parameter instead of the channel width to the necessary function to ensure that the operating class gets calculated correctly. CRs-Fixed: 955414 Change-Id: I011db65e57c477e381fd471a4a930a02e2a7ee21 --- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 9544e1aea5e1..fd9616a791b1 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -5496,6 +5496,7 @@ static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx, tpPESession session_entry = NULL; uint8_t session_id; tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch; + offset_t ch_offset; if (msg_buf == NULL) { lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); @@ -5604,13 +5605,23 @@ skip_vht: * the template update */ lim_send_beacon_ind(mac_ctx, session_entry); - lim_log(mac_ctx, LOG1, FL("Updated CSA IE, IE COUNT = %d"), - session_entry->gLimChannelSwitch.switchCount); + + if (dfs_csa_ie_req->ch_params.ch_width == CH_WIDTH_80MHZ) + ch_offset = BW80; + else + ch_offset = dfs_csa_ie_req->ch_params.sec_ch_offset; + + lim_log(mac_ctx, LOG1, FL("IE count:%d chan:%d width:%d wrapper:%d ch_offset:%d"), + session_entry->gLimChannelSwitch.switchCount, + session_entry->gLimChannelSwitch.primaryChannel, + session_entry->gLimChannelSwitch.ch_width, + session_entry->dfsIncludeChanWrapperIe, + ch_offset); + /* Send ECSA Action frame after updating the beacon */ send_extended_chan_switch_action_frame(mac_ctx, session_entry->gLimChannelSwitch.primaryChannel, - session_entry->gLimChannelSwitch.ch_width, - session_entry); + ch_offset, session_entry); session_entry->gLimChannelSwitch.switchCount--; } -- cgit v1.2.3 From c6419ecac54e4919bee1ab9ade8a7236cb663352 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Tue, 12 Jan 2016 18:37:43 +0530 Subject: qcacld-3.0: Accommodate channel bandwidth as input during channel switch Add support to include channel bandwidth as one of the inputs to decide the channel switch parameters. Currently only the target channel is used as the input to decide the channel switch parameters. With this fix, user specified channel bandwidth is also taken into consideration. Change-Id: Ic49b24edde6cabc52aa2b38110763da82da6790d CRs-Fixed: 955368 --- core/hdd/inc/wlan_hdd_main.h | 2 +- core/hdd/src/wlan_hdd_cfg80211.c | 5 ++- core/hdd/src/wlan_hdd_hostapd.c | 18 +++++++---- core/hdd/src/wlan_hdd_hostapd.h | 5 +-- core/hdd/src/wlan_hdd_main.c | 33 +++++++++++++++++++ core/mac/inc/sir_api.h | 3 +- core/sap/inc/sap_api.h | 2 +- core/sap/src/sap_module.c | 70 +++++++++++++++++++++++++--------------- 8 files changed, 100 insertions(+), 38 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 969c2f0aa64c..3845c5ef12c7 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1545,7 +1545,7 @@ const char *hdd_get_fwpath(void); 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); - +phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width); uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index a6737ff9d503..d25e9ff99d6f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -11115,6 +11115,7 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, uint8_t channel; uint16_t freq; int ret; + phy_ch_width ch_width; hddLog(LOG1, FL("Set Freq %d"), csa_params->chandef.chan->center_freq); @@ -11132,7 +11133,9 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy, freq = csa_params->chandef.chan->center_freq; channel = cds_freq_to_chan(freq); - ret = hdd_softap_set_channel_change(dev, channel); + ch_width = hdd_map_nl_chan_width(csa_params->chandef.width); + + ret = hdd_softap_set_channel_change(dev, channel, ch_width); return ret; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index ba98484d1f91..6da5ebba25a9 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1701,7 +1701,8 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, 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)) + pSapEvent->sapevt.sap_chan_cng_ind.new_chan, + CH_WIDTH_MAX)) return CDF_STATUS_E_FAILURE; else return CDF_STATUS_SUCCESS; @@ -1893,10 +1894,13 @@ int hdd_softap_unpack_ie(tHalHandle halHandle, * * @dev: pointer to the net device. * @target_channel: target channel number. + * @target_bw: Target bandwidth to move. + * If no bandwidth is specified, the value is CH_WIDTH_MAX * * Return: 0 for success, non zero for failure */ -int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) +int hdd_softap_set_channel_change(struct net_device *dev, int target_channel, + phy_ch_width target_bw) { CDF_STATUS status; int ret = 0; @@ -1960,12 +1964,13 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel) p_cds_context, #endif (uint32_t) - target_channel); + target_channel, + target_bw); if (CDF_STATUS_SUCCESS != status) { hddLog(LOGE, - FL("SAP set channel failed for channel = %d"), - target_channel); + FL("SAP set channel failed for channel = %d, bw:%d"), + target_channel, target_bw); /* * If channel change command fails then clear the * radar found flag and also restart the netif @@ -2287,7 +2292,8 @@ static __iw_softap_setparam(struct net_device *dev, hddLog(LOG1, "SET Channel Change to new channel= %d", set_value); - ret = hdd_softap_set_channel_change(dev, set_value); + ret = hdd_softap_set_channel_change(dev, set_value, + CH_WIDTH_MAX); } else { hddLog(LOGE, FL("Channel Change Failed, Device in test mode")); diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h index f57cb1c4b677..46dc54ebc8f9 100644 --- a/core/hdd/src/wlan_hdd_hostapd.h +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -58,7 +58,8 @@ eCsrAuthType hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]); int hdd_softap_set_channel_change(struct net_device *dev, - int target_channel); + int target_channel, + phy_ch_width target_bw); eCsrEncryptionType hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 98c560fc010c..fd30caf42c52 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -349,6 +349,39 @@ static int con_mode; /* Variable to hold connection mode including module parameter con_mode */ static int curr_con_mode; +/** + * hdd_map_nl_chan_width() - Map NL channel width to internal representation + * @ch_width: NL channel width + * + * Converts the NL channel width to the driver's internal representation + * + * Return: Converted channel width. In case of non matching NL channel width, + * CH_WIDTH_MAX will be returned. + */ +phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width) +{ + switch (ch_width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + return CH_WIDTH_20MHZ; + case NL80211_CHAN_WIDTH_40: + return CH_WIDTH_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + return CH_WIDTH_80MHZ; + case NL80211_CHAN_WIDTH_80P80: + return CH_WIDTH_80P80MHZ; + case NL80211_CHAN_WIDTH_160: + return CH_WIDTH_160MHZ; + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: + default: + hdd_err("Invalid channel width %d, setting to default", + ch_width); + return CH_WIDTH_MAX; + } +} + /* wlan_hdd_find_opclass() - Find operating class for a channel * @hal: handler to HAL * @channel: channel id diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index cdc23d7dd2eb..e69dbf26b9d9 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -300,7 +300,8 @@ typedef enum ch_width { CH_WIDTH_40MHZ = 1, CH_WIDTH_80MHZ = 2, CH_WIDTH_160MHZ = 3, - CH_WIDTH_80P80MHZ = 4 + CH_WIDTH_80P80MHZ = 4, + CH_WIDTH_MAX } phy_ch_width; /** diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index ffe912c33b2b..165efe61c290 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -841,7 +841,7 @@ CDF_STATUS wlansap_disassoc_sta(void *p_cds_gctx, CDF_STATUS wlansap_deauth_sta(void *p_cds_gctx, struct tagCsrDelStaParams *pDelStaParams); CDF_STATUS wlansap_set_channel_change_with_csa(void *p_cds_gctx, - uint32_t targetChannel); + uint32_t targetChannel, phy_ch_width target_bw); CDF_STATUS wlansap_set_key_sta(void *p_cds_gctx, tCsrRoamSetKey *pSetKeyInfo); CDF_STATUS wlansap_get_assoc_stations(void *p_cds_gctx, diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 40fcc28bd150..2bbeccc2e7bb 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1483,32 +1483,20 @@ static CDF_STATUS wlansap_update_csa_channel_params(ptSapContext sap_context, return CDF_STATUS_SUCCESS; } -/*========================================================================== - FUNCTION wlansap_set_channel_change_with_csa - - 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 - p_cds_gctx : Pointer to cds global context structure - targetChannel : New target channel to change to. - - RETURN VALUE - The CDF_STATUS code associated with performing the operation - - CDF_STATUS_SUCCESS: Success - - SIDE EFFECTS - ============================================================================*/ +/** + * wlansap_set_channel_change_with_csa() - Set channel change with CSA + * @p_cds_gctx: Pointer to cds global context structure + * @targetChannel: Target channel + * @target_bw: Target bandwidth + * + * This api function does a channel change to the target channel specified. + * CSA IE is included in the beacons before doing a channel change. + * + * Return: CDF_STATUS + */ CDF_STATUS -wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) +wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel, + phy_ch_width target_bw) { ptSapContext sapContext = NULL; @@ -1575,11 +1563,41 @@ wlansap_set_channel_change_with_csa(void *p_cds_gctx, uint32_t targetChannel) pMac->sap.SapDfsInfo.target_channel = targetChannel; pMac->sap.SapDfsInfo.new_ch_params.ch_width = pMac->sap.SapDfsInfo.new_chanWidth; + + /* By this time, the best bandwidth is calculated for + * the given target channel. Now, if there was a + * request from user to move to a selected bandwidth, + * we can see if it can be honored. + * + * Ex1: BW80 was selected for the target channel and + * user wants BW40, it can be allowed + * Ex2: BW40 was selected for the target channel and + * user wants BW80, it cannot be allowed for the given + * target channel. + * + * So, the MIN of the selected channel bandwidth and + * user input is used for the bandwidth + */ + if (target_bw != CH_WIDTH_MAX) { + CDF_TRACE(CDF_MODULE_ID_SAP, + CDF_TRACE_LEVEL_INFO, + "%s: target bw:%d new width:%d", + __func__, target_bw, + pMac->sap.SapDfsInfo. + new_ch_params.ch_width); + pMac->sap.SapDfsInfo.new_ch_params.ch_width = + pMac->sap.SapDfsInfo.new_chanWidth = + CDF_MIN(pMac->sap.SapDfsInfo. + new_ch_params.ch_width, + target_bw); + } + sme_set_ch_params(hHal, sapContext->csr_roamProfile.phyMode, targetChannel, 0, &pMac->sap.SapDfsInfo.new_ch_params); + /* * Set the CSA IE required flag. */ -- cgit v1.2.3 From 84a65326a6cd842f534641f329e3e23a5f802c0f Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Tue, 12 Jan 2016 19:42:20 +0530 Subject: qcacld-3.0: Add new IOCTL to change SAP/P2P-GO's operating channel Add new IOCTL 'CHANNEL_SWITCH' which is used to move the operating channel of SAP/P2P-GO. This IOCTL is supported only for SAP/P2P-GO and not for STA/P2P-GC. E.g., format to issue command through wpa_supplicant: DRIVER CHANNEL_SWITCH - is channel number to move (1 for ch1, 149 for ch149 etc.) - is bandwidth to move (20 for BW 20, 40 for BW 40 etc.) Change-Id: Ie65f2ceb9ece04053ab32ee60f83fd09cd232f77 CRs-Fixed: 955368 --- core/hdd/inc/wlan_hdd_main.h | 3 + core/hdd/src/wlan_hdd_hostapd.c | 7 +++ core/hdd/src/wlan_hdd_ioctl.c | 119 ++++++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_main.c | 71 ++++++++++++++++++++++++ 4 files changed, 200 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3845c5ef12c7..4cc4eeb424db 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1341,6 +1341,9 @@ struct hdd_context_s { /*--------------------------------------------------------------------------- Function declarations and documentation -------------------------------------------------------------------------*/ +int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter, + uint32_t chan_number, + phy_ch_width chan_bw); #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH void wlan_hdd_check_sta_ap_concurrent_ch_intf(void *sta_pAdapter); #endif diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 6da5ebba25a9..e7a70a974b4e 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1921,6 +1921,13 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel, return ret; } + ret = hdd_validate_channel_and_bandwidth(pHostapdAdapter, + target_channel, target_bw); + if (ret) { + hdd_err("Invalid CH and BW combo"); + return ret; + } + sta_adapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); /* * conc_custom_rule1: diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 68005f54ec51..be6ea8f17071 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -34,6 +34,7 @@ #include "wlan_hdd_power.h" #include "wlan_hdd_driver_ops.h" #include "cds_concurrency.h" +#include "wlan_hdd_hostapd.h" #include "wlan_hdd_p2p.h" #include @@ -5954,6 +5955,123 @@ static int drv_cmd_set_fcc_channel(hdd_adapter_t *adapter, return ret; } +/** + * hdd_parse_set_channel_switch_command() - Parse and validate CHANNEL_SWITCH + * command + * @value: Pointer to the command + * @chan_number: Pointer to the channel number + * @chan_bw: Pointer to the channel bandwidth + * + * Parses and provides the channel number and channel width from the input + * command which is expected to be of the format: CHANNEL_SWITCH + * is channel number to move (where 1 = channel 1, 149 = channel 149, ...) + * is bandwidth to move (where 20 = BW 20, 40 = BW 40, 80 = BW 80) + * + * Return: 0 for success, non-zero for failure + */ +static int hdd_parse_set_channel_switch_command(uint8_t *value, + uint32_t *chan_number, + uint32_t *chan_bw) +{ + const uint8_t *in_ptr = value; + int ret; + + in_ptr = strnchr(value, strlen(value), SPACE_ASCII_VALUE); + + /* no argument after the command */ + if (NULL == in_ptr) { + hdd_err("No argument after the command"); + return -EINVAL; + } + + /* no space after the command */ + if (SPACE_ASCII_VALUE != *in_ptr) { + hdd_err("No space after the command "); + return -EINVAL; + } + + /* remove empty spaces and move the next argument */ + while ((SPACE_ASCII_VALUE == *in_ptr) && ('\0' != *in_ptr)) + in_ptr++; + + /* no argument followed by spaces */ + if ('\0' == *in_ptr) { + hdd_err("No argument followed by spaces"); + return -EINVAL; + } + + /* get the two arguments: channel number and bandwidth */ + ret = sscanf(in_ptr, "%u %u", chan_number, chan_bw); + if (ret != 2) { + hdd_err("Arguments retrieval from cmd string failed"); + return -EINVAL; + } + + return 0; +} + +/** + * drv_cmd_set_channel_switch() - Switch SAP/P2P-GO operating channel + * @adapter: HDD adapter + * @hdd_ctx: HDD context + * @command: Pointer to the input command CHANNEL_SWITCH + * @command_len: Command len + * @priv_data: Private data + * + * Handles private IOCTL CHANNEL_SWITCH command to switch the operating channel + * of SAP/P2P-GO + * + * Return: 0 for success, non-zero for failure + */ +static int drv_cmd_set_channel_switch(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, + uint8_t *command, + uint8_t command_len, + hdd_priv_data_t *priv_data) +{ + struct net_device *dev = adapter->dev; + int status; + uint32_t chan_number = 0, chan_bw = 0; + uint8_t *value = command; + phy_ch_width width; + + if ((adapter->device_mode != WLAN_HDD_P2P_GO) && + (adapter->device_mode != WLAN_HDD_SOFTAP)) { + hdd_err("IOCTL CHANNEL_SWITCH not supported for mode %d", + adapter->device_mode); + return -EINVAL; + } + + status = hdd_parse_set_channel_switch_command(value, + &chan_number, &chan_bw); + if (status) { + hdd_err("Invalid CHANNEL_SWITCH command"); + return status; + } + + if ((chan_bw != 20) && (chan_bw != 40) && (chan_bw != 80)) { + hdd_err("BW %d is not allowed for CHANNEL_SWITCH", chan_bw); + return -EINVAL; + } + + if (chan_bw == 80) + width = CH_WIDTH_80MHZ; + else if (chan_bw == 40) + width = CH_WIDTH_40MHZ; + else + width = CH_WIDTH_20MHZ; + + hdd_info("CH:%d BW:%d", chan_number, chan_bw); + + status = hdd_softap_set_channel_change(dev, chan_number, width); + if (status) { + hdd_err("Set channel change fail"); + return status; + } + + return 0; +} + /* * The following table contains all supported WLAN HDD * IOCTL driver commands and the handler for each of them. @@ -6066,6 +6184,7 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = { {"RXFILTER-REMOVE", drv_cmd_rx_filter_remove}, {"RXFILTER-ADD", drv_cmd_rx_filter_add}, {"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel}, + {"CHANNEL_SWITCH", drv_cmd_set_channel_switch}, }; /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fd30caf42c52..7b7f78ce82fc 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -232,6 +232,77 @@ const char *hdd_device_mode_to_string(uint8_t device_mode) } } +/** + * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo + * @adapter: HDD adapter + * @chan_number: Channel number + * @chan_bw: Bandwidth + * + * Checks if the given bandwidth is valid for the given channel number. + * + * Return: 0 for success, non-zero for failure + */ +int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter, + uint32_t chan_number, + phy_ch_width chan_bw) +{ + uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i; + bool found = false; + tHalHandle hal; + + hal = WLAN_HDD_GET_HAL_CTX(adapter); + if (!hal) { + hdd_err("Invalid HAL context"); + return -EINVAL; + } + + if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) { + hdd_err("No valid channel list"); + return -EOPNOTSUPP; + } + + for (i = 0; i < len; i++) { + if (chan[i] == chan_number) { + found = true; + break; + } + } + + if (found == false) { + hdd_err("Channel not in driver's valid channel list"); + return -EOPNOTSUPP; + } + + if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) && + (!CDS_IS_CHANNEL_5GHZ(chan_number))) { + hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number); + return -EINVAL; + } + + if (CDS_IS_CHANNEL_24GHZ(chan_number)) { + if (chan_bw == CH_WIDTH_80MHZ) { + hdd_err("BW80 not possible in 2.4GHz band"); + return -EINVAL; + } + if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) && + (chan_bw != CH_WIDTH_MAX)) { + hdd_err("Only BW20 possible on channel 14"); + return -EINVAL; + } + } + + if (CDS_IS_CHANNEL_5GHZ(chan_number)) { + if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) && + (chan_bw != CH_WIDTH_MAX)) { + hdd_err("Only BW20 possible on channel 165"); + return -EINVAL; + } + } + + return 0; +} + static int __hdd_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *data) { -- cgit v1.2.3 From 182b6acddabbc4b7e07e9999e3097910e30d3cde Mon Sep 17 00:00:00 2001 From: Chouhan Lokesh Date: Sat, 16 Jan 2016 16:44:38 +0530 Subject: qcacld-3.0: Prefer ini params logging preference over code preference qcacld-2.0 to qcacld-3.0 propogation Previously trace logging levels are set from cfg.ini for different modules which again over written by code. Ultimately code logging preference was taking place. After changes if the log level for any module is set to DEFAULT(0xffff) then only code logging preference will be used else cfg.ini logging will be preferred. CRs-Fixed: 875973 Change-Id: Ia3df86908cec1d5c487d614a418721c0cd98fc52 --- core/hdd/src/wlan_hdd_main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 7b7f78ce82fc..a8ac0d81d4b6 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5081,7 +5081,16 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0; } - /* Update CDF trace levels based upon the cfg.ini */ + + /* + * Update CDF trace levels based upon the code + */ + if (hdd_ctx->config->multicast_host_fw_msgs) + wlan_logging_set_log_level(); + + /* + * Update CDF trace levels based upon the cfg.ini + */ hdd_cdf_trace_enable(CDF_MODULE_ID_WMI, hdd_ctx->config->cdf_trace_enable_wdi); hdd_cdf_trace_enable(CDF_MODULE_ID_HDD, @@ -5471,8 +5480,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) } } #endif - if (cds_is_multicast_logging()) - wlan_logging_set_log_level(); /* * Action frame registered in one adapter which will -- cgit v1.2.3 From dc3231b00d083a439281c4bf8629acd9f7f6bf12 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Sat, 16 Jan 2016 17:04:32 +0530 Subject: qcacld-3.0: Avoid all module logging onto kmsg during driver load This is qcacld-2.0 to qcacld-3.0 propagation Avoid logging of all module logs into kmsg during the driver load phase. All module log level is set much before setting of the flag that indicates whether multicast logging is enabled or not. Because of this all module log levels are getting printed for a brief duration in kmsg during driver load. Fix the same by setting the multicast flag appropriately so that when multicast logging is enabled, all the logs are multicast to user space and only the error and fatal messages continue to get logged in the kmsg. CRs-Fixed: 958705 Change-Id: I260e38ef64f704dfd9ca1ca4dc68c56428526559 --- core/hdd/src/wlan_hdd_main.c | 46 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index a8ac0d81d4b6..448718855925 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4921,6 +4921,34 @@ static CDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx) return CDF_STATUS_SUCCESS; } +#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->config->wlanLoggingEnable) { + if (wlan_logging_sock_activate_svc( + hdd_ctx->config->wlanLoggingFEToConsole, + hdd_ctx->config->wlanLoggingNumBuf)) { + hdd_err("wlan_logging_sock_activate_svc failed"); + return -EINVAL; + } + } + return 0; +} +#else +static inline int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) +{ + return 0; +} +#endif + /** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device @@ -5082,10 +5110,15 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0; } + cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs); + + if (wlan_hdd_logging_sock_activate_svc(hdd_ctx) < 0) + goto err_config; + /* * Update CDF trace levels based upon the code */ - if (hdd_ctx->config->multicast_host_fw_msgs) + if (cds_is_multicast_logging()) wlan_logging_set_log_level(); /* @@ -5469,17 +5502,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) FL("cnss_diag_activate_service failed")); goto err_nl_srv; } -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - if (hdd_ctx->config->wlanLoggingEnable) { - if (wlan_logging_sock_activate_svc - (hdd_ctx->config->wlanLoggingFEToConsole, - hdd_ctx->config->wlanLoggingNumBuf)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("wlan_logging_sock_activate_svc failed")); - goto err_nl_srv; - } - } -#endif /* * Action frame registered in one adapter which will -- cgit v1.2.3 From 191131eeba0c9af9a7252c9b5f8ff11c30a516f1 Mon Sep 17 00:00:00 2001 From: "Chandrasekaran, Manishekar" Date: Sat, 16 Jan 2016 17:28:11 +0530 Subject: qcacld-3.0: Deactivate and clean up logging thread on driver load failure This is qcacld-2.0 to qcacld-3.0 propagation Deactivate and clean up the logging thread during driver load failure and ensure that logging thread is not enabled for FTM mode CRs-Fixed: 961865 Change-Id: I53f85a30f52fc5715705624bf515ab5e4666db8e --- core/hdd/src/wlan_hdd_main.c | 109 ++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 448718855925..a22b44b88e1b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3578,6 +3578,54 @@ int hdd_enable_ftm(hdd_context_t *hdd_ctx) static inline void hdd_disable_ftm(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->config->wlanLoggingEnable) { + if (wlan_logging_sock_activate_svc( + hdd_ctx->config->wlanLoggingFEToConsole, + hdd_ctx->config->wlanLoggingNumBuf)) { + hdd_err("wlan_logging_sock_activate_svc failed"); + 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->config->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 + /** * hdd_wlan_exit() - HDD WLAN exit function * @hdd_ctx: Pointer to the HDD Context @@ -3591,7 +3639,6 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context; CDF_STATUS cdf_status; struct wiphy *wiphy = hdd_ctx->wiphy; - struct hdd_config *pConfig = hdd_ctx->config; ENTER(); @@ -3718,11 +3765,9 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) hdd_wlan_green_ap_deinit(hdd_ctx); -#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE - if (pConfig && pConfig->wlanLoggingEnable) { - wlan_logging_sock_deactivate_svc(); - } -#endif + if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) + wlan_hdd_logging_sock_deactivate_svc(hdd_ctx); + #ifdef WLAN_KD_READY_NOTIFIER cnss_diag_notify_wlan_close(); ptt_sock_deactivate_svc(); @@ -4921,34 +4966,6 @@ static CDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx) return CDF_STATUS_SUCCESS; } -#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->config->wlanLoggingEnable) { - if (wlan_logging_sock_activate_svc( - hdd_ctx->config->wlanLoggingFEToConsole, - hdd_ctx->config->wlanLoggingNumBuf)) { - hdd_err("wlan_logging_sock_activate_svc failed"); - return -EINVAL; - } - } - return 0; -} -#else -static inline int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) -{ - return 0; -} -#endif - /** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device @@ -5110,16 +5127,21 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0; } - cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs); + if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) { + cds_set_multicast_logging( + hdd_ctx->config->multicast_host_fw_msgs); - if (wlan_hdd_logging_sock_activate_svc(hdd_ctx) < 0) - goto err_config; + if (wlan_hdd_logging_sock_activate_svc(hdd_ctx) < 0) + goto err_config; - /* - * Update CDF trace levels based upon the code - */ - if (cds_is_multicast_logging()) - wlan_logging_set_log_level(); + /* + * Update CDF trace levels based upon the code. The multicast + * levels of the code need not be set when the logger thread + * is not enabled. + */ + if (cds_is_multicast_logging()) + wlan_logging_set_log_level(); + } /* * Update CDF trace levels based upon the cfg.ini @@ -5734,6 +5756,9 @@ err_cds_close: } cds_close(p_cds_context); + if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) + wlan_hdd_logging_sock_deactivate_svc(hdd_ctx); + err_config: kfree(hdd_ctx->config); hdd_ctx->config = NULL; -- cgit v1.2.3 From 8077fae3065458d65d729bd6d0dd953ea72594a6 Mon Sep 17 00:00:00 2001 From: Ryan Hsu Date: Tue, 5 Jan 2016 11:18:24 -0800 Subject: qcacld-3.0: clean up the WLAN_FEATURE_MBSSID flag (phase 1) WLAN_FEATURE_MBSSID flag is originally added to support MBSSID, specifically for the MOBILE ROUTER build, and is now enabled for all builds, there is no longer needed to have a separate feature flag, so that removing it. This commit cleans up the following modules - cds/mac/sap/sme. Change-Id: I79ad9767b7945af0c567b6294ac07e7697898e9e CRs-fixed: 958154 --- core/cds/inc/cds_concurrency.h | 9 ---- core/cds/inc/cds_sched.h | 7 +-- core/cds/src/cds_api.c | 27 +---------- core/cds/src/cds_concurrency.c | 37 ++++----------- core/mac/src/pe/sch/sch_beacon_process.c | 31 +----------- core/sap/inc/sap_api.h | 15 +----- core/sap/src/sap_ch_select.c | 19 ++------ core/sap/src/sap_fsm.c | 9 ++-- core/sap/src/sap_internal.h | 11 ++--- core/sap/src/sap_module.c | 81 +++++--------------------------- core/sme/src/common/sme_api.c | 46 ------------------ core/sme/src/csr/csr_util.c | 32 +++---------- 12 files changed, 44 insertions(+), 280 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index c5c30e2389fd..4e48d9f431d6 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -648,16 +648,7 @@ bool cds_max_concurrent_connections_reached(void); void cds_clear_concurrent_session_count(void); bool cds_is_multiple_active_sta_sessions(void); bool cds_is_sta_active_connection_exists(void); - -#ifdef WLAN_FEATURE_MBSSID bool cds_concurrent_beaconing_sessions_running(void); -#else -static inline bool cds_concurrent_beaconing_sessions_running(void) -{ - return true; -} -#endif - CDF_STATUS cdf_wait_for_connection_update(void); CDF_STATUS cdf_reset_connection_update(void); CDF_STATUS cdf_set_connection_update(void); diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index d58c3c21c168..cafff80dd699 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -250,11 +250,6 @@ typedef struct _cds_context_type { /* MAC Module Context */ void *pMACContext; -#ifndef WLAN_FEATURE_MBSSID - /* SAP Context */ - void *pSAPContext; -#endif - cdf_event_t ProbeEvent; uint32_t driver_state; diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 4f2477dedbe4..dc2ffef7d5d0 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -863,14 +863,6 @@ void *cds_get_context(CDF_MODULE_ID moduleId) } switch (moduleId) { -#ifndef WLAN_FEATURE_MBSSID - case CDF_MODULE_ID_SAP: - { - pModContext = gp_cds_context->pSAPContext; - break; - } -#endif - case CDF_MODULE_ID_HDD: { pModContext = gp_cds_context->pHDDContext; @@ -1064,15 +1056,6 @@ CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, } switch (moduleID) { - -#ifndef WLAN_FEATURE_MBSSID - case CDF_MODULE_ID_SAP: - { - pGpModContext = &(gp_cds_context->pSAPContext); - break; - } -#endif - case CDF_MODULE_ID_WMA: { pGpModContext = &(gp_cds_context->pWMAContext); @@ -1160,14 +1143,6 @@ CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID, } switch (moduleID) { -#ifndef WLAN_FEATURE_MBSSID - case CDF_MODULE_ID_SAP: - { - pGpModContext = &(gp_cds_context->pSAPContext); - break; - } -#endif - case CDF_MODULE_ID_WMA: { pGpModContext = &(gp_cds_context->pWMAContext); diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index f7bf7f0e64cf..a832dbb67452 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -6633,11 +6633,8 @@ static void cds_check_sta_ap_concurrent_ch_intf(void *data) if (hal_handle == NULL) return; -#ifdef WLAN_FEATURE_MBSSID intf_ch = wlansap_check_cc_intf(hdd_ap_ctx->sapContext); -#else - intf_ch = wlansap_check_cc_intf(hdd_ctx->pcds_context); -#endif + if (intf_ch == 0) return; @@ -7177,9 +7174,7 @@ void cds_set_mcc_latency(hdd_adapter_t *adapter, int set_value) #if defined(FEATURE_WLAN_MCC_TO_SCC_SWITCH) || \ defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) /** - * cds_restart_sap() - This function is used to restart SAP in - * driver internally - * + * cds_restart_sap() - to restart SAP in driver internally * @ap_adapter: Pointer to SAP hdd_adapter_t structure * * Return: None @@ -7194,9 +7189,11 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) struct tagCsrDelStaParams delStaParams; #endif tsap_Config_t *sap_config; + void *sap_ctx; hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); - sap_config = &ap_adapter->sessionCtx.ap.sapConfig; + sap_config = &hdd_ap_ctx.sapConfig; + sap_ctx = hdd_ap_ctx->sapContext; mutex_lock(&hdd_ctx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { @@ -7214,13 +7211,7 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) hdd_cleanup_actionframe(hdd_ctx, ap_adapter); hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); cdf_event_reset(&hostapd_state->cdf_stop_bss_event); - if (CDF_STATUS_SUCCESS == wlansap_stop_bss( -#ifdef WLAN_FEATURE_MBSSID - hdd_ap_ctx->sapContext -#else - hdd_ctx->pcds_context -#endif - )) { + if (CDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) { cdf_status = cdf_wait_single_event(&hostapd_state-> cdf_stop_bss_event, @@ -7243,16 +7234,9 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) goto end; } - if (wlansap_start_bss( -#ifdef WLAN_FEATURE_MBSSID - hdd_ap_ctx->sapContext, -#else - hdd_ctx->pcds_context, -#endif - hdd_hostapd_sap_event_cb, - &hdd_ap_ctx->sapConfig, - ap_adapter->dev) != - CDF_STATUS_SUCCESS) { + if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb, + sap_config, + ap_adapter->dev) != CDF_STATUS_SUCCESS) { cds_err("SAP Start Bss fail"); goto end; } @@ -7544,7 +7528,6 @@ bool cds_concurrent_open_sessions_running(void) return j > 1; } -#ifdef WLAN_FEATURE_MBSSID /** * cds_concurrent_beaconing_sessions_running() - Checks for concurrent beaconing * entities @@ -7567,7 +7550,7 @@ bool cds_concurrent_beaconing_sessions_running(void) } return i > 1; } -#endif + /** * cds_max_concurrent_connections_reached() - Check if max conccurrency is diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index 059a58712a36..489d75808d6b 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -848,11 +848,10 @@ static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, /** * sch_beacon_process() - process the beacon frame - * * @mac_ctx: mac global context * @rx_pkt_info: pointer to buffer descriptor * - * @return None + * Return: None */ void sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, @@ -861,9 +860,7 @@ sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, static tSchBeaconStruct bcn; tUpdateBeaconParams bcn_prm; tpPESession ap_session = NULL; -#ifdef WLAN_FEATURE_MBSSID uint8_t i; -#endif cdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams)); bcn_prm.paramChangeBitmap = 0; @@ -889,7 +886,6 @@ sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, * 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 < mac_ctx->lim.maxBssId; i++) { ap_session = pe_find_session_by_session_id(mac_ctx, i); if (!((ap_session != NULL) && @@ -918,30 +914,7 @@ sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); } } -#else - ap_session = lim_is_ap_session_active(mac_ctx); - if ((ap_session != NULL) - && (!(WMA_GET_OFFLOADSCANLEARN(rx_pkt_info)))) { - bcn_prm.bssIdx = ap_session->bssIdx; - if (ap_session->gLimProtectionControl != - WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) - ap_beacon_process(mac_ctx, rx_pkt_info, &bcn, - &bcn_prm, ap_session); - if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) - && bcn_prm.paramChangeBitmap) { - /* Update the bcn and apply the new settings to HAL */ - sch_set_fixed_beacon_fields(mac_ctx, ap_session); - PELOG1(sch_log(mac_ctx, LOG1, - FL("Beacon for PE session[%d] got changed."), - ap_session->peSessionId);) - PELOG1(sch_log(mac_ctx, LOG1, - FL("sending beacon param change bitmap: 0x%x "), - bcn_prm.paramChangeBitmap);) - lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); - } - } -#endif /* * Now process the beacon in the context of the BSS which is * transmitting the beacons, if one is found diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 165efe61c290..1109ca023c59 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -69,11 +69,7 @@ extern "C" { #define MAX_TEXT_SIZE 32 #define MAX_CHANNEL_LIST_LEN 256 -#ifdef WLAN_FEATURE_MBSSID #define CDF_MAX_NO_OF_SAP_MODE 2 /* max # of SAP */ -#else -#define CDF_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 */ #define SAP_ACS_WEIGHT_MAX (4444) @@ -803,23 +799,14 @@ typedef struct { bool isSafe; } sapSafeChannelType; #endif /* FEATURE_WLAN_CH_AVOID */ -#ifdef WLAN_FEATURE_MBSSID void sap_cleanup_channel_list(void *sapContext); -#else -void sap_cleanup_channel_list(void); -#endif void sapCleanupAllChannelList(void); CDF_STATUS wlansap_set_wps_ie(void *p_cds_gctx, tSap_WPSIE *pWPSIe); CDF_STATUS wlansap_update_wps_ie(void *p_cds_gctx); CDF_STATUS wlansap_stop_Wps(void *p_cds_gctx); CDF_STATUS wlansap_get_wps_state(void *p_cds_gctx, bool *pbWPSState); -#ifdef WLAN_FEATURE_MBSSID -void * -#else -CDF_STATUS -#endif -wlansap_open(void *p_cds_gctx); +void *wlansap_open(void *p_cds_gctx); CDF_STATUS wlansap_start(void *p_cds_gctx); CDF_STATUS wlansap_stop(void *p_cds_gctx); CDF_STATUS wlansap_close(void *p_cds_gctx); diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index 9e7aabc01787..b22f6cffdb96 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -434,8 +434,7 @@ void sap_update_unsafe_channel_list(ptSapContext pSapCtx) } /* Try to find unsafe channel */ -#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || \ - defined(WLAN_FEATURE_MBSSID) +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { if (pSapCtx->dfs_ch_disable == true) { if (CDS_IS_DFS_CH(safe_channels[i].channelNumber)) { @@ -501,16 +500,8 @@ void sap_update_unsafe_channel_list(ptSapContext pSapCtx) NULL ============================================================================*/ -void sap_cleanup_channel_list( -#ifdef WLAN_FEATURE_MBSSID - void *p_cds_gctx -#else - void -#endif - ) { -#ifndef WLAN_FEATURE_MBSSID - void *p_cds_gctx = cds_get_global_context(); -#endif +void sap_cleanup_channel_list(void *p_cds_gctx) +{ ptSapContext pSapCtx; CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, @@ -647,7 +638,7 @@ bool sap_chan_sel_init(tHalHandle halHandle, pChans = pMac->scan.base_channels.channelList; -#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || defined(WLAN_FEATURE_MBSSID) +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) if (pSapCtx->dfs_ch_disable == true) include_dfs_ch = false; #endif diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 771fc58cf699..b66bf04e6ee1 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -1981,11 +1981,11 @@ CDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, FL("invalid h_hal")); return CDF_STATUS_E_FAULT; } -#ifdef WLAN_FEATURE_MBSSID + if (cds_concurrent_beaconing_sessions_running()) { con_ch = sme_get_concurrent_operation_channel(h_hal); - +#ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE if (con_ch && sap_context->channel == AUTO_CHANNEL_SELECT) { sap_context->dfs_ch_disable = true; } else if (con_ch && sap_context->channel != con_ch && @@ -1994,6 +1994,7 @@ CDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, FL("MCC DFS not supported in AP_AP Mode")); return CDF_STATUS_E_ABORTED; } +#endif #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH if (sap_context->cc_switch_mode != CDF_MCC_TO_SCC_SWITCH_DISABLE) { @@ -2011,7 +2012,6 @@ CDF_STATUS sap_goto_channel_sel(ptSapContext sap_context, } #endif } -#endif if (cds_get_concurrency_mode() == (CDF_STA_MASK | CDF_SAP_MASK)) { #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE @@ -3251,7 +3251,6 @@ static CDF_STATUS sap_fsm_state_ch_select(ptSapContext sap_ctx, eCSR_DOT11_MODE_11g_ONLY)) sap_ctx->csr_roamProfile.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 @@ -3265,7 +3264,7 @@ static CDF_STATUS sap_fsm_state_ch_select(ptSapContext sap_ctx, if (con_ch && CDS_IS_DFS_CH(con_ch)) sap_ctx->channel = con_ch; } -#endif + /* * Transition from eSAP_CH_SELECT to eSAP_STARTING * (both without substates) diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index a94c251c581b..1e88ffccf549 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -58,13 +58,9 @@ extern "C" { #define SAP_DEBUG /* Used to enable or disable security on the BT-AMP link */ #define WLANSAP_SECURITY_ENABLED_STATE true -#ifdef WLAN_FEATURE_MBSSID + /* When MBSSID feature is enabled, SAP context is directly passed to SAP APIs */ #define CDS_GET_SAP_CB(ctx) (ptSapContext)(ctx) -#else -/* How do I get SAP context from cds context? */ -#define CDS_GET_SAP_CB(ctx) cds_get_context(CDF_MODULE_ID_SAP) -#endif #define CDS_GET_HAL_CB(ctx) cds_get_context(CDF_MODULE_ID_PE) /* MAC Address length */ @@ -239,8 +235,7 @@ typedef struct sSapContext { uint8_t cc_switch_mode; #endif -#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || \ - defined(WLAN_FEATURE_MBSSID) +#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) bool dfs_ch_disable; #endif bool isCacEndNotified; diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 2bbeccc2e7bb..581db3d8bdc2 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -99,54 +99,22 @@ ptSapContext gp_sap_ctx; * all its internal resources and will wait for the call to start to * register with the other modules. * - * Return: The result code associated with performing the operation - * - * #ifdef WLAN_FEATURE_MBSSID - * void *: Pointer to the SAP context - * #else - * CDF_STATUS_E_FAULT: Pointer to SAP cb is NULL ; - * access would cause a page fault - * CDF_STATUS_SUCCESS: Success - * #endif + * Return: Pointer to the SAP context */ -#ifdef WLAN_FEATURE_MBSSID -void * -#else -CDF_STATUS -#endif -wlansap_open(void *p_cds_gctx) { +void *wlansap_open(void *p_cds_gctx) +{ ptSapContext pSapCtx = NULL; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -#ifdef WLAN_FEATURE_MBSSID - /* amically allocate the sapContext */ + /* dynamically allocate the sapContext */ pSapCtx = (ptSapContext) cdf_mem_malloc(sizeof(tSapContext)); -#else - if (NULL == p_cds_gctx) { - CDF_ASSERT(p_cds_gctx); - return CDF_STATUS_E_NOMEM; - } - /*------------------------------------------------------------------------ - Allocate (and sanity check?!) SAP control block - ------------------------------------------------------------------------*/ - cds_alloc_context(p_cds_gctx, CDF_MODULE_ID_SAP, (void **)&pSapCtx, - sizeof(tSapContext)); -#endif if (NULL == pSapCtx) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s: Invalid SAP pointer from p_cds_gctx", __func__); -#ifdef WLAN_FEATURE_MBSSID return NULL; -#else - return CDF_STATUS_E_FAULT; -#endif } - - /*------------------------------------------------------------------------ - Clean up SAP control block, initialize all values - ------------------------------------------------------------------------*/ + /* Clean up SAP control block, initialize all values */ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_open"); wlansap_clean_cb(pSapCtx, 0); /*do not empty */ @@ -157,15 +125,7 @@ wlansap_open(void *p_cds_gctx) { /* Store a pointer to the SAP context provided by CDS */ gp_sap_ctx = pSapCtx; - /*------------------------------------------------------------------------ - Allocate internal resources - ------------------------------------------------------------------------*/ - -#ifdef WLAN_FEATURE_MBSSID return pSapCtx; -#else - return CDF_STATUS_SUCCESS; -#endif } /* wlansap_open */ /** @@ -253,10 +213,7 @@ CDF_STATUS wlansap_stop(void *pCtx) { ptSapContext pSapCtx = NULL; - /*------------------------------------------------------------------------ - Sanity check - Extract SAP control block - ------------------------------------------------------------------------*/ + /* Sanity check - Extract SAP control block */ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_stop invoked successfully "); @@ -274,9 +231,6 @@ CDF_STATUS wlansap_stop(void *pCtx) "wlansap_stop failed destroy lock"); return CDF_STATUS_E_FAULT; } - /*------------------------------------------------------------------------ - Stop SAP (de-register RSN handler!?) - ------------------------------------------------------------------------*/ return CDF_STATUS_SUCCESS; } @@ -299,12 +253,7 @@ CDF_STATUS wlansap_close(void *pCtx) { ptSapContext pSapCtx = NULL; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - - /*------------------------------------------------------------------------ - Sanity check - Extract SAP control block - ------------------------------------------------------------------------*/ + /* Sanity check - Extract SAP control block */ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_close invoked"); @@ -315,22 +264,14 @@ CDF_STATUS wlansap_close(void *pCtx) return CDF_STATUS_E_FAULT; } - /*------------------------------------------------------------------------ - Cleanup SAP control block. - ------------------------------------------------------------------------*/ + /* Cleanup SAP control block */ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "wlansap_close"); - wlansap_clean_cb(pSapCtx, - true); /* empty queues/lists/pkts if any */ -#ifdef WLAN_FEATURE_MBSSID + /* empty queues/lists/pkts if any */ + wlansap_clean_cb(pSapCtx, true); + cdf_mem_free(pSapCtx); -#else - /*------------------------------------------------------------------------ - Free SAP context from CDS global - ------------------------------------------------------------------------*/ - cds_free_context(pCtx, CDF_MODULE_ID_SAP, pSapCtx); -#endif return CDF_STATUS_SUCCESS; } /* wlansap_close */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 1d45f67c78c8..8fd48ac788e0 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1045,9 +1045,6 @@ CDF_STATUS sme_open(tHalHandle hHal) { CDF_STATUS status = CDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifndef WLAN_FEATURE_MBSSID - void *p_cds_gctx = cds_get_global_context(); -#endif pMac->sme.state = SME_STATE_STOP; pMac->sme.currDeviceMode = CDF_STA_MODE; @@ -1092,18 +1089,6 @@ CDF_STATUS sme_open(tHalHandle hHal) status = init_sme_cmd_list(pMac); if (!CDF_IS_STATUS_SUCCESS(status)) return status; -#ifndef WLAN_FEATURE_MBSSID - if (NULL == p_cds_gctx) { - sms_log(pMac, LOGE, FL("p_cds_gctx is NULL")); - return CDF_STATUS_E_FAILURE; - } - status = wlansap_open(p_cds_gctx); - if (!CDF_IS_STATUS_SUCCESS(status)) { - sms_log(pMac, LOGE, FL("wlansap_open failed, status=%d"), - status); - return status; - } -#endif #if defined WLAN_FEATURE_VOWIFI status = rrm_open(pMac); @@ -1754,17 +1739,6 @@ CDF_STATUS sme_start(tHalHandle hHal) status); break; } - -#ifndef WLAN_FEATURE_MBSSID - status = wlansap_start(cds_get_global_context()); - if (!CDF_IS_STATUS_SUCCESS(status)) { - sms_log(pMac, LOGE, - "wlansap_start failed during smeStart with status=%d", - status); - break; - } -#endif - pMac->sme.state = SME_STATE_START; } while (0); @@ -2870,16 +2844,6 @@ CDF_STATUS sme_stop(tHalHandle hHal, tHalStopType stopType) CDF_STATUS fail_status = CDF_STATUS_SUCCESS; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifndef WLAN_FEATURE_MBSSID - status = wlansap_stop(cds_get_global_context()); - if (!CDF_IS_STATUS_SUCCESS(status)) { - sms_log(pMac, LOGE, - "wlansap_stop failed during smeStop with status=%d", - status); - fail_status = status; - } -#endif - p2p_stop(hHal); status = csr_stop(pMac, stopType); @@ -2936,16 +2900,6 @@ CDF_STATUS sme_close(tHalHandle hHal) status); fail_status = status; } -#ifndef WLAN_FEATURE_MBSSID - status = wlansap_close(cds_get_global_context()); - if (!CDF_IS_STATUS_SUCCESS(status)) { - sms_log(pMac, LOGE, - "WLANSAP_close failed during sme close with status=%d", - status); - fail_status = status; - } -#endif - #ifndef WLAN_MDM_CODE_REDUCTION_OPT status = sme_qos_close(pMac); if (!CDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index e78d8b518ddc..41ede0889193 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -1912,40 +1912,20 @@ csr_isconcurrentsession_valid(tpAniSirGlobal mac_ctx, uint32_t cur_sessionid, case CDF_SAP_MODE: temp = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; -#ifndef WLAN_FEATURE_MBSSID - if ((bss_persona == CDF_SAP_MODE) && - (connect_state != - eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { + if ((bss_persona == CDF_IBSS_MODE) + && (connect_state != temp)) { + /* allow IBSS+SAP for Emulation only */ +#ifndef QCA_WIFI_3_0_EMU CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, - FL("sap mode already exist")); + FL("Can't start SAP")); return CDF_STATUS_E_FAILURE; - } else -#endif - if ((bss_persona == CDF_IBSS_MODE) - && (connect_state != temp)) { - /* allow IBSS+SAP for Emulation only */ -#ifndef QCA_WIFI_3_0_EMU - CDF_TRACE(CDF_MODULE_ID_SME, - CDF_TRACE_LEVEL_ERROR, - FL("Can't start SAP")); - return CDF_STATUS_E_FAILURE; #endif - } + } break; case CDF_P2P_GO_MODE: temp = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED; -#ifndef WLAN_FEATURE_MBSSID - if ((bss_persona == CDF_P2P_GO_MODE) && - (connect_state != - eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED)) { - CDF_TRACE(CDF_MODULE_ID_SME, - CDF_TRACE_LEVEL_ERROR, - FL("GO mode already exists")); - return CDF_STATUS_E_FAILURE; - } -#endif if ((bss_persona == CDF_IBSS_MODE) && (connect_state != temp)) { CDF_TRACE(CDF_MODULE_ID_SME, -- cgit v1.2.3 From edd6bc625ff1db1452a255a9d613720c622b0d46 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Wed, 6 Jan 2016 16:46:37 -0800 Subject: qcacld-3.0: Fix checkpatch error in wlan_qct_sys.c This patch is to fix the check-patch errors in wlan_qct_sys.c CRs-Fixed: 824222 Change-Id: I99f5c2daad9d14fcc6a7ab24dee95810829eeaf4 --- core/mac/src/sys/common/src/wlan_qct_sys.c | 293 ++++++++++++++--------------- 1 file changed, 145 insertions(+), 148 deletions(-) diff --git a/core/mac/src/sys/common/src/wlan_qct_sys.c b/core/mac/src/sys/common/src/wlan_qct_sys.c index c2c39d1d97ca..212af83a949a 100644 --- a/core/mac/src/sys/common/src/wlan_qct_sys.c +++ b/core/mac/src/sys/common/src/wlan_qct_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -36,7 +36,8 @@ #include "sme_api.h" #include "mac_init_api.h" -/* Cookie for SYS messages. Note that anyone posting a SYS 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 */ @@ -44,27 +45,50 @@ /* SYS stop timeout 30 seconds */ #define SYS_STOP_TIMEOUT (30000) - static cdf_event_t g_stop_evt; +/** + * sys_build_message_header() - to build the sys message header + * @sysMsgId: message id + * @pMsg: pointer to message context + * + * This API is used to build the sys message header. + * + * Return: CDF_STATUS + */ CDF_STATUS sys_build_message_header(SYS_MSG_ID sysMsgId, cds_msg_t *pMsg) { pMsg->type = sysMsgId; pMsg->reserved = SYS_MSG_COOKIE; - return (CDF_STATUS_SUCCESS); + return CDF_STATUS_SUCCESS; } -void sys_stop_complete_cb(void *pUserData) { +/** + * sys_stop_complete_cb() - a callback when system stop completes + * @pUserData: pointer to user provided data context + * + * this callback is used once system stop is completed. + * + * Return: none + */ +void sys_stop_complete_cb(void *pUserData) +{ cdf_event_t *pStopEvt = (cdf_event_t *) pUserData; - CDF_STATUS cdf_status; -/*-------------------------------------------------------------------------*/ + CDF_STATUS cdf_status = cdf_event_set(pStopEvt); - cdf_status = cdf_event_set(pStopEvt); CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); -} /* cds_sys_stop_complete_cback() */ +} +/** + * sys_stop() - To post stop message to system module + * @p_cds_context: pointer to cds context + * + * This API is used post a stop message to system module + * + * Return: CDF_STATUS + */ CDF_STATUS sys_stop(v_CONTEXT_t p_cds_context) { CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; @@ -73,23 +97,20 @@ CDF_STATUS sys_stop(v_CONTEXT_t p_cds_context) /* Initialize the stop event */ cdf_status = cdf_event_init(&g_stop_evt); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) return cdf_status; - } /* post a message to SYS module in MC to stop SME and MAC */ sys_build_message_header(SYS_MSG_ID_MC_STOP, &sysMsg); /* Save the user callback and user data */ - /* finished. */ sysMsg.callback = sys_stop_complete_cb; sysMsg.bodyptr = (void *)&g_stop_evt; /* post the message.. */ cdf_status = cds_mq_post_message(CDS_MQ_ID_SYS, &sysMsg); - if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) cdf_status = CDF_STATUS_E_BADMSG; - } cdf_status = cdf_wait_single_event(&g_stop_evt, SYS_STOP_TIMEOUT); CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); @@ -97,22 +118,34 @@ CDF_STATUS sys_stop(v_CONTEXT_t p_cds_context) cdf_status = cdf_event_destroy(&g_stop_evt); CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); - return (cdf_status); + return cdf_status; } +/** + * sys_mc_process_msg() - to process system mc thread messages + * @p_cds_context: pointer to cds context + * @pMsg: message pointer + * + * This API is used to process the message + * + * Return: CDF_STATUS + */ CDF_STATUS sys_mc_process_msg(v_CONTEXT_t p_cds_context, cds_msg_t *pMsg) { CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; + cdf_mc_timer_callback_t timerCB; + tpAniSirGlobal mac_ctx; void *hHal; if (NULL == pMsg) { - CDF_ASSERT(0); CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, "%s: NULL pointer to cds_msg_t", __func__); + CDF_ASSERT(0); return CDF_STATUS_E_INVAL; } - /* All 'new' SYS messages are identified by a cookie in the reserved + /* + * 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 @@ -122,241 +155,208 @@ CDF_STATUS sys_mc_process_msg(v_CONTEXT_t p_cds_context, cds_msg_t *pMsg) /* 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 CDF_ASSERT*/ - CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - " Received SYS_MSG_ID_MC_START message msgType= %d [0x%08x]", - pMsg->type, pMsg->type); + /* + * Handling for this message is not needed now so adding + * debug print and CDF_ASSERT + */ + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Rx SYS_MSG_ID_MC_START msgType= %d [0x%08x]", + pMsg->type, pMsg->type); CDF_ASSERT(0); break; - } case SYS_MSG_ID_MC_STOP: - { - CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_INFO, - "Processing SYS MC STOP"); + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, + "Processing SYS MC STOP"); /* get the HAL context... */ hHal = cds_get_context(CDF_MODULE_ID_PE); if (NULL == hHal) { CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - "%s: Invalid hHal", __func__); + CDF_TRACE_LEVEL_ERROR, + "%s: Invalid hHal", __func__); } else { - cdf_status = - sme_stop(hHal, - HAL_STOP_TYPE_SYS_DEEP_SLEEP); - CDF_ASSERT(CDF_IS_STATUS_SUCCESS - (cdf_status)); - - cdf_status = - mac_stop(hHal, - HAL_STOP_TYPE_SYS_DEEP_SLEEP); - CDF_ASSERT(CDF_IS_STATUS_SUCCESS - (cdf_status)); + cdf_status = sme_stop(hHal, + HAL_STOP_TYPE_SYS_DEEP_SLEEP); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); + cdf_status = mac_stop(hHal, + HAL_STOP_TYPE_SYS_DEEP_SLEEP); + CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status)); - ((sysResponseCback) pMsg-> - callback)((void *)pMsg->bodyptr); + ((sysResponseCback) pMsg->callback)( + (void *)pMsg->bodyptr); cdf_status = CDF_STATUS_SUCCESS; } break; - } - /* Process MC thread probe. Just callback to the */ - /* function that is in the message. */ case SYS_MSG_ID_MC_THR_PROBE: - { - CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - " Received SYS_MSG_ID_MC_THR_PROBE message msgType = %d [0x%08x]", - pMsg->type, pMsg->type); + /* + * Process MC thread probe. Just callback to the + * function that is in the message. + */ + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Rx SYS_MSG_ID_MC_THR_PROBE msgType=%d[0x%08x]", + pMsg->type, pMsg->type); break; - } case SYS_MSG_ID_MC_TIMER: - { - cdf_mc_timer_callback_t timerCB = - pMsg->callback; - - if (NULL != timerCB) { + timerCB = pMsg->callback; + if (NULL != timerCB) timerCB(pMsg->bodyptr); - } break; - } + case SYS_MSG_ID_FTM_RSP: - { - tpAniSirGlobal mac_ctx = NULL; hHal = cds_get_context(CDF_MODULE_ID_PE); if (NULL == hHal) { CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - FL("Invalid hal")); + CDF_TRACE_LEVEL_ERROR, + FL("Invalid hal")); cdf_mem_free(pMsg->bodyptr); break; } mac_ctx = PMAC_STRUCT(hHal); if (NULL == mac_ctx) { CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - FL("Invalid mac context")); + CDF_TRACE_LEVEL_ERROR, + FL("Invalid mac context")); cdf_mem_free(pMsg->bodyptr); break; } if (NULL == mac_ctx->ftm_msg_processor_callback) { CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - FL("callback pointer is NULL")); + CDF_TRACE_LEVEL_ERROR, + FL("callback pointer is NULL")); cdf_mem_free(pMsg->bodyptr); break; } mac_ctx->ftm_msg_processor_callback( - (void *)pMsg->bodyptr); + (void *)pMsg->bodyptr); cdf_mem_free(pMsg->bodyptr); break; - } default: - { - CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - "Unknown message type in sys_mc_process_msg() msgType= %d [0x%08x]", - pMsg->type, pMsg->type); + CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, + "Unknown message type 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: - { - CDF_ASSERT(0); - - CDF_TRACE(CDF_MODULE_ID_SYS, - CDF_TRACE_LEVEL_ERROR, - "Received SYS message cookie with unidentified " - "MC message type= %d [0x%08X]", - pMsg->type, pMsg->type); - cdf_status = CDF_STATUS_E_BADMSG; - if (pMsg->bodyptr) - cdf_mem_free(pMsg->bodyptr); - break; } - } /* end switch on pMsg->type */ - } /* end else */ + } else { + CDF_TRACE(CDF_MODULE_ID_SYS, + CDF_TRACE_LEVEL_ERROR, + "Rx SYS unknown MC msgtype= %d [0x%08X]", + pMsg->type, pMsg->type); + CDF_ASSERT(0); + cdf_status = CDF_STATUS_E_BADMSG; + if (pMsg->bodyptr) + cdf_mem_free(pMsg->bodyptr); + } return (cdf_status); } - -void sys_process_mmh_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) { +/** + * sys_process_mmh_msg() - this api to process mmh message + * @pMac: pointer to mac context + * @pMsg: pointer to message + * + * This API is used to process mmh message + * + * Return: none + */ +void sys_process_mmh_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg) +{ CDS_MQ_ID targetMQ = CDS_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 - */ + /* + * The body of this pMsg is a tSirMbMsg + * Contrary to previous generation, we cannot free it here! + * It is up to the callee to free it + */ if (NULL == pMsg) { CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, - "NULL Message Pointer"); + "NULL Message Pointer"); CDF_ASSERT(0); return; } switch (pMsg->type) { /* - ** Following messages are routed to SYS - */ + * Following messages are routed to SYS + */ case WNI_CFG_DNLD_REQ: case WNI_CFG_DNLD_CNF: - { /* Forward this message to the SYS module */ targetMQ = CDS_MQ_ID_SYS; - CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, - "Handling for the Message ID %d is removed in SYS\r\n", - pMsg->type); - + "Handling for the Message ID %d is removed in SYS", + pMsg->type); CDF_ASSERT(0); break; - } - /* - ** Following messages are routed to HAL - */ + /* + * Following messages are routed to HAL + */ case WNI_CFG_DNLD_RSP: - { /* Forward this message to the HAL module */ targetMQ = CDS_MQ_ID_WMA; - CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, - "Handling for the Message ID %d is removed as there is no HAL \r\n", - pMsg->type); + "Handling for the Message ID %d is removed as no HAL", + pMsg->type); CDF_ASSERT(0); break; - } 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 = CDS_MQ_ID_PE; break; - } case WNI_CFG_GET_RSP: case WNI_CFG_SET_CNF: - { /* Forward this message to the SME module */ targetMQ = CDS_MQ_ID_SME; break; - } default: - { - if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) - && (pMsg->type <= eWNI_SME_MSG_TYPES_END)) { + && (pMsg->type <= eWNI_SME_MSG_TYPES_END)) { targetMQ = CDS_MQ_ID_SME; break; } CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_ERROR, - "Message of ID %d is not yet handled by SYS\r\n", - pMsg->type); - + "Message of ID %d is not yet handled by SYS", + pMsg->type); CDF_ASSERT(0); } - } - /* - ** Post now the message to the appropriate module for handling - */ - if (CDF_STATUS_SUCCESS != - cds_mq_post_message(targetMQ, (cds_msg_t *) pMsg)) { - /* Caller doesn't allocate memory for the pMsg. It allocate memory for bodyptr */ - /* free the mem and return */ - if (pMsg->bodyptr) { + * Post now the message to the appropriate module for handling + */ + if (CDF_STATUS_SUCCESS != cds_mq_post_message(targetMQ, + (cds_msg_t *) pMsg)) { + /* + * Caller doesn't allocate memory for the pMsg. + * It allocate memory for bodyptr free the mem and return + */ + if (pMsg->bodyptr) cdf_mem_free(pMsg->bodyptr); - } } -} /* sys_process_mmh_msg() */ +} +/** + * wlan_sys_probe() - API to post MC thread probe + * + * This API will be used send probe message + * + * Return: none + */ void wlan_sys_probe(void) { cds_msg_t cds_message; @@ -364,8 +364,5 @@ void wlan_sys_probe(void) cds_message.reserved = SYS_MSG_COOKIE; cds_message.type = SYS_MSG_ID_MC_THR_PROBE; cds_message.bodyptr = NULL; - cds_mq_post_message(CDS_MQ_ID_SYS, &cds_message); - - return; } -- cgit v1.2.3 From 6d761723d7fcddacd2caf4f9f4c0adf87bacca98 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Fri, 12 Jun 2015 15:12:19 -0700 Subject: qcacld-3.0: Send the correct supported channel width in Assoc Resp qcacld-2.0 to qcacld-3.0 propagation Currently, if SAP supports 40Mhz, then it sends the supported channel width as 40Mhz irrespective whether STA supports or not. Changes done to check the STA capability for supported channel width and send it accordingly in Assoc Resp Change-Id: I58ca44b6998d4712521a10285b9fd2a3f825d2ed CRs-Fixed: 728676 Signed-off-by: Krunal Soni --- core/mac/src/pe/lim/lim_send_management_frames.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index f99affbba849..f2aaf946d4b7 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1202,6 +1202,18 @@ lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, FL("Populate HT IEs in Assoc Response")); populate_dot11f_ht_caps(mac_ctx, pe_session, &frm.HTCaps); + /* + * Check the STA capability and + * update the HTCaps accordingly + */ + frm.HTCaps.supportedChannelWidthSet = ( + sta->htSupportedChannelWidthSet < + pe_session->htSupportedChannelWidthSet) ? + sta->htSupportedChannelWidthSet : + pe_session->htSupportedChannelWidthSet; + if (!frm.HTCaps.supportedChannelWidthSet) + frm.HTCaps.shortGI40MHz = 0; + populate_dot11f_ht_info(mac_ctx, &frm.HTInfo, pe_session); } -- cgit v1.2.3 From d51b14c377d343dd0d5847f97b74610f3d7ccec9 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Thu, 14 Jan 2016 13:00:44 -0800 Subject: qcacld-3.0: Merge two sme & csr config structure in to one SME holds config item in tCsrConfigParams structure as well as some of the same items in tSmeConfigParams which makes tCsrConfigParams super set of tSmeConfigParams. There are high chances if somebody misses copying item from tSmeConfigParams to tCsrConfigParams and that will result in config item not being set correctly. In order to make it clean and easy, merge both config structure in one. Change-Id: I8c93d9fae0986cb90b4ed4c4712b1e2b023b4be3 CRs-Fixed: 963752 --- core/hdd/src/wlan_hdd_cfg.c | 43 ++++++++++--------- core/sme/inc/csr_api.h | 14 +++++++ core/sme/inc/sme_api.h | 37 +---------------- core/sme/src/common/sme_api.c | 91 ++++++----------------------------------- core/sme/src/csr/csr_api_roam.c | 63 ++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 134 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index c60eb9b5a38e..378d9fe96296 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -5543,10 +5543,11 @@ static void hdd_set_fine_time_meas_cap(hdd_context_t *hdd_ctx, /* Make sure only supported capabilities are enabled in INI */ capability &= CFG_FINE_TIME_MEAS_CAPABILITY_MAX; - sme_config->fine_time_meas_cap = capability; + sme_config->csrConfig.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); + config->fine_time_meas_cap, + sme_config->csrConfig.fine_time_meas_cap); return; } @@ -6369,14 +6370,15 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx) void hdd_set_pno_channel_prediction_config( tpSmeConfigParams sme_config, hdd_context_t *hdd_ctx) { - sme_config->dual_mac_feature_disable = + sme_config->csrConfig.dual_mac_feature_disable = hdd_ctx->config->dual_mac_feature_disable; - sme_config->pno_channel_prediction = + sme_config->csrConfig.pno_channel_prediction = hdd_ctx->config->pno_channel_prediction; - sme_config->top_k_num_of_channels = + sme_config->csrConfig.top_k_num_of_channels = hdd_ctx->config->top_k_num_of_channels; - sme_config->stationary_thresh = hdd_ctx->config->stationary_thresh; - sme_config->channel_prediction_full_scan = + sme_config->csrConfig.stationary_thresh = + hdd_ctx->config->stationary_thresh; + sme_config->csrConfig.channel_prediction_full_scan = hdd_ctx->config->channel_prediction_full_scan; } #endif @@ -6635,17 +6637,18 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) #ifdef FEATURE_WLAN_SCAN_PNO /* Update PNO offoad status */ - smeConfig->pnoOffload = pHddCtx->config->PnoOffload; + smeConfig->csrConfig.pnoOffload = pHddCtx->config->PnoOffload; #endif /* Update maximum interfaces information */ - smeConfig->max_intf_count = pHddCtx->max_intf_count; + smeConfig->csrConfig.max_intf_count = pHddCtx->max_intf_count; - smeConfig->fEnableDebugLog = pHddCtx->config->gEnableDebugLog; + smeConfig->csrConfig.fEnableDebugLog = pHddCtx->config->gEnableDebugLog; - smeConfig->enable5gEBT = pHddCtx->config->enable5gEBT; + smeConfig->csrConfig.enable5gEBT = pHddCtx->config->enable5gEBT; - smeConfig->enableSelfRecovery = pHddCtx->config->enableSelfRecovery; + smeConfig->csrConfig.enableSelfRecovery = + pHddCtx->config->enableSelfRecovery; #ifdef WLAN_FEATURE_ROAM_OFFLOAD smeConfig->csrConfig.isRoamOffloadEnabled = pHddCtx->config->isRoamOffloadEnabled; @@ -6657,25 +6660,25 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) smeConfig->csrConfig.is_sta_connection_in_5gz_enabled = pHddCtx->config->is_sta_connection_in_5gz_enabled; - smeConfig->f_sta_miracast_mcc_rest_time_val = + smeConfig->csrConfig.f_sta_miracast_mcc_rest_time_val = pHddCtx->config->sta_miracast_mcc_rest_time_val; #ifdef FEATURE_AP_MCC_CH_AVOIDANCE - smeConfig->sap_channel_avoidance = + smeConfig->csrConfig.sap_channel_avoidance = pHddCtx->config->sap_channel_avoidance; #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ - smeConfig->f_prefer_non_dfs_on_radar = + smeConfig->csrConfig.f_prefer_non_dfs_on_radar = pHddCtx->config->prefer_non_dfs_on_radar; - smeConfig->is_ps_enabled = pHddCtx->config->is_ps_enabled; + smeConfig->csrConfig.is_ps_enabled = pHddCtx->config->is_ps_enabled; hdd_set_fine_time_meas_cap(pHddCtx, smeConfig); cds_set_multicast_logging(pHddCtx->config->multicast_host_fw_msgs); smeConfig->csrConfig.sendDeauthBeforeCon = pConfig->sendDeauthBeforeCon; - smeConfig->policy_manager_enabled = + smeConfig->csrConfig.policy_manager_enabled = pHddCtx->config->policy_manager_enabled; smeConfig->csrConfig.max_scan_count = pHddCtx->config->max_scan_count; @@ -6685,11 +6688,11 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) (pHddCtx->config->dot11p_mode != WLAN_HDD_11P_DISABLED); hdd_set_pno_channel_prediction_config(smeConfig, pHddCtx); - smeConfig->early_stop_scan_enable = + smeConfig->csrConfig.early_stop_scan_enable = pHddCtx->config->early_stop_scan_enable; - smeConfig->early_stop_scan_min_threshold = + smeConfig->csrConfig.early_stop_scan_min_threshold = pHddCtx->config->early_stop_scan_min_threshold; - smeConfig->early_stop_scan_max_threshold = + smeConfig->csrConfig.early_stop_scan_max_threshold = pHddCtx->config->early_stop_scan_max_threshold; smeConfig->csrConfig.first_scan_bucket_threshold = pHddCtx->config->first_scan_bucket_threshold; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 82d3cfcb4ad1..a34856598ef2 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1219,6 +1219,20 @@ typedef struct tagCsrConfigParam { int8_t early_stop_scan_min_threshold; int8_t early_stop_scan_max_threshold; int8_t first_scan_bucket_threshold; + bool pnoOffload; + uint8_t fEnableDebugLog; + uint8_t max_intf_count; + bool enable5gEBT; + bool 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; + bool is_ps_enabled; + bool policy_manager_enabled; + uint32_t fine_time_meas_cap; + uint32_t dual_mac_feature_disable; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 413a80152896..9348ff9d80e2 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -93,39 +93,6 @@ typedef struct _smeConfigParams { #if defined WLAN_FEATURE_VOWIFI struct rrm_config_param rrmConfig; #endif - uint8_t isFastRoamIniFeatureEnabled; - uint8_t MAWCEnabled; -#if defined FEATURE_WLAN_ESE - uint8_t isEseIniFeatureEnabled; -#endif - uint8_t isFastTransitionEnabled; - uint8_t RoamRssiDiff; - bool isWESModeEnabled; - uint8_t isAmsduSupportInAMPDU; - bool pnoOffload; - uint8_t fEnableDebugLog; - uint8_t max_intf_count; - bool enable5gEBT; - bool 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; - bool is_ps_enabled; - bool policy_manager_enabled; - uint32_t fine_time_meas_cap; - uint32_t dual_mac_feature_disable; -#ifdef FEATURE_WLAN_SCAN_PNO - bool pno_channel_prediction; - uint8_t top_k_num_of_channels; - uint8_t stationary_thresh; - uint32_t channel_prediction_full_scan; -#endif - bool early_stop_scan_enable; - int8_t early_stop_scan_min_threshold; - int8_t early_stop_scan_max_threshold; - int8_t first_scan_bucket_threshold; } tSmeConfigParams, *tpSmeConfigParams; #ifdef FEATURE_WLAN_TDLS @@ -242,11 +209,11 @@ CDF_STATUS sme_update_roam_params(tHalHandle hHal, uint8_t session_id, struct roam_ext_params roam_params_src, int update_param); #ifdef FEATURE_WLAN_SCAN_PNO void sme_update_roam_pno_channel_prediction_config( - tHalHandle hal, tpSmeConfigParams sme_config, + tHalHandle hal, tCsrConfigParam * csr_config, uint8_t copy_from_to); #else static inline void sme_update_roam_pno_channel_prediction_config( - tHalHandle hal, tpSmeConfigParams sme_config, + tHalHandle hal, tCsrConfigParam *csr_config, uint8_t copy_from_to) {} #endif diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 8fd48ac788e0..333c31420458 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1384,47 +1384,6 @@ CDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, "Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CFG"); } - pMac->isCoalesingInIBSSAllowed = - pSmeConfigParams->csrConfig.isCoalesingInIBSSAllowed; - - /* 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->sme.ps_global_info.ps_enabled = - pSmeConfigParams->is_ps_enabled; - - pMac->policy_manager_enabled = pSmeConfigParams->policy_manager_enabled; - pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap; - pMac->dual_mac_feature_disable = - pSmeConfigParams->dual_mac_feature_disable; - sme_update_roam_pno_channel_prediction_config(pMac, pSmeConfigParams, - SME_CONFIG_TO_ROAM_CONFIG); - pMac->roam.configParam.early_stop_scan_enable = - pSmeConfigParams->early_stop_scan_enable; - pMac->roam.configParam.early_stop_scan_min_threshold = - pSmeConfigParams->early_stop_scan_min_threshold; - pMac->roam.configParam.early_stop_scan_max_threshold = - pSmeConfigParams->early_stop_scan_max_threshold; - return status; } @@ -4252,35 +4211,9 @@ CDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) sme_release_global_lock(&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->max_intf_count = pMac->sme.max_intf_count; - pParam->enableSelfRecovery = pMac->sme.enableSelfRecovery; - pParam->pnoOffload = pMac->pnoOffload; - pParam->f_prefer_non_dfs_on_radar = - pMac->f_prefer_non_dfs_on_radar; - pParam->policy_manager_enabled = pMac->policy_manager_enabled; - pParam->fine_time_meas_cap = pMac->fine_time_meas_cap; - pParam->dual_mac_feature_disable = - pMac->dual_mac_feature_disable; - pParam->is_ps_enabled = pMac->sme.ps_global_info.ps_enabled; - pParam->pnoOffload = pMac->pnoOffload; - pParam->fEnableDebugLog = pMac->fEnableDebugLog; - pParam->enable5gEBT = pMac->enable5gEBT; - pParam->f_sta_miracast_mcc_rest_time_val = - pMac->f_sta_miracast_mcc_rest_time_val; - sme_update_roam_pno_channel_prediction_config(pMac, pParam, - ROAM_CONFIG_TO_SME_CONFIG); - pParam->early_stop_scan_enable = - pMac->roam.configParam.early_stop_scan_enable; - pParam->early_stop_scan_min_threshold = - pMac->roam.configParam.early_stop_scan_min_threshold; - pParam->early_stop_scan_max_threshold = - pMac->roam.configParam.early_stop_scan_max_threshold; cdf_mem_copy(&pParam->rrmConfig, - &pMac->rrm.rrmSmeContext.rrmConfig, - sizeof(pMac->rrm.rrmSmeContext.rrmConfig)); + &pMac->rrm.rrmSmeContext.rrmConfig, + sizeof(pMac->rrm.rrmSmeContext.rrmConfig)); sme_release_global_lock(&pMac->sme); } @@ -6849,7 +6782,7 @@ uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch, #ifdef FEATURE_WLAN_SCAN_PNO /** * sme_update_roam_pno_channel_prediction_config() - Update PNO config - * @sme_config: config from SME context + * @csr_config: config from SME context * @hal: Global Hal handle * @copy_from_to: Used to specify the source and destination * @@ -6859,27 +6792,27 @@ uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch, * Return: None */ void sme_update_roam_pno_channel_prediction_config( - tHalHandle hal, tpSmeConfigParams sme_config, + tHalHandle hal, tCsrConfigParam *csr_config, uint8_t copy_from_to) { tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); if (copy_from_to == SME_CONFIG_TO_ROAM_CONFIG) { mac_ctx->roam.configParam.pno_channel_prediction = - sme_config->pno_channel_prediction; + csr_config->pno_channel_prediction; mac_ctx->roam.configParam.top_k_num_of_channels = - sme_config->top_k_num_of_channels; + csr_config->top_k_num_of_channels; mac_ctx->roam.configParam.stationary_thresh = - sme_config->stationary_thresh; + csr_config->stationary_thresh; mac_ctx->roam.configParam.channel_prediction_full_scan = - sme_config->channel_prediction_full_scan; + csr_config->channel_prediction_full_scan; } else if (copy_from_to == ROAM_CONFIG_TO_SME_CONFIG) { - sme_config->pno_channel_prediction = + csr_config->pno_channel_prediction = mac_ctx->roam.configParam.pno_channel_prediction; - sme_config->top_k_num_of_channels = + csr_config->top_k_num_of_channels = mac_ctx->roam.configParam.top_k_num_of_channels; - sme_config->stationary_thresh = + csr_config->stationary_thresh = mac_ctx->roam.configParam.stationary_thresh; - sme_config->channel_prediction_full_scan = + csr_config->channel_prediction_full_scan = mac_ctx->roam.configParam.channel_prediction_full_scan; } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 08f422d9db55..a605be0f71b3 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2079,7 +2079,45 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->early_stop_scan_min_threshold; pMac->roam.configParam.early_stop_scan_max_threshold = pParam->early_stop_scan_max_threshold; + pMac->isCoalesingInIBSSAllowed = + pParam->isCoalesingInIBSSAllowed; + + /* update p2p offload status */ + pMac->pnoOffload = pParam->pnoOffload; + + pMac->fEnableDebugLog = pParam->fEnableDebugLog; + + /* update interface configuration */ + pMac->sme.max_intf_count = pParam->max_intf_count; + + pMac->enable5gEBT = pParam->enable5gEBT; + pMac->sme.enableSelfRecovery = pParam->enableSelfRecovery; + + pMac->f_sta_miracast_mcc_rest_time_val = + pParam->f_sta_miracast_mcc_rest_time_val; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + pMac->sap.sap_channel_avoidance = + pParam->sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + + pMac->f_prefer_non_dfs_on_radar = + pParam->f_prefer_non_dfs_on_radar; + pMac->sme.ps_global_info.ps_enabled = + pParam->is_ps_enabled; + + pMac->policy_manager_enabled = pParam->policy_manager_enabled; + pMac->fine_time_meas_cap = pParam->fine_time_meas_cap; + pMac->dual_mac_feature_disable = + pParam->dual_mac_feature_disable; + sme_update_roam_pno_channel_prediction_config(pMac, pParam, + SME_CONFIG_TO_ROAM_CONFIG); + pMac->roam.configParam.early_stop_scan_enable = + pParam->early_stop_scan_enable; + pMac->roam.configParam.early_stop_scan_min_threshold = + pParam->early_stop_scan_min_threshold; + pMac->roam.configParam.early_stop_scan_max_threshold = + pParam->early_stop_scan_max_threshold; } return status; @@ -2222,6 +2260,31 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->max_scan_count = pMac->scan.max_scan_count; pParam->first_scan_bucket_threshold = pMac->first_scan_bucket_threshold; +#ifdef FEATURE_AP_MCC_CH_AVOIDANCE + pParam->sap_channel_avoidance = pMac->sap.sap_channel_avoidance; +#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ + pParam->max_intf_count = pMac->sme.max_intf_count; + pParam->enableSelfRecovery = pMac->sme.enableSelfRecovery; + pParam->pnoOffload = pMac->pnoOffload; + pParam->f_prefer_non_dfs_on_radar = + pMac->f_prefer_non_dfs_on_radar; + pParam->policy_manager_enabled = pMac->policy_manager_enabled; + pParam->fine_time_meas_cap = pMac->fine_time_meas_cap; + pParam->dual_mac_feature_disable = + pMac->dual_mac_feature_disable; + pParam->is_ps_enabled = pMac->sme.ps_global_info.ps_enabled; + pParam->fEnableDebugLog = pMac->fEnableDebugLog; + pParam->enable5gEBT = pMac->enable5gEBT; + pParam->f_sta_miracast_mcc_rest_time_val = + pMac->f_sta_miracast_mcc_rest_time_val; + sme_update_roam_pno_channel_prediction_config(pMac, pParam, + ROAM_CONFIG_TO_SME_CONFIG); + pParam->early_stop_scan_enable = + pMac->roam.configParam.early_stop_scan_enable; + pParam->early_stop_scan_min_threshold = + pMac->roam.configParam.early_stop_scan_min_threshold; + pParam->early_stop_scan_max_threshold = + pMac->roam.configParam.early_stop_scan_max_threshold; return CDF_STATUS_SUCCESS; } -- cgit v1.2.3 From 162f56579e8628364282d6e5fa73fb34108d4032 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 5 Oct 2015 18:43:07 -0700 Subject: qcacld-3.0: Send one suspend indication message to wma Send one suspend indication message to wma after configuring all the offloads. Reduce context switches and complexity. Change-Id: I020fc8864dbf7378805361d54dc6cff60b2652e5 CRs-Fixed: 935297 --- core/hdd/src/wlan_hdd_power.c | 129 ++++++++++----------- core/mac/inc/sir_api.h | 6 - core/sme/inc/sme_api.h | 2 +- core/sme/src/common/sme_api.c | 4 +- core/wma/inc/wma.h | 1 - core/wma/inc/wma_internal.h | 3 +- core/wma/src/wma_features.c | 262 ++++++++++++++++++++++++++---------------- core/wma/src/wma_main.c | 4 +- 8 files changed, 230 insertions(+), 181 deletions(-) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index b7475f6f76a9..9c993e308a14 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -511,16 +511,19 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) hdd_conf_gtk_offload(pAdapter, fenable); - /* Configure ARP/NS offload during cfg80211 suspend/resume only - * if active mode offload is disabled + /* Configure ARP/NS offload during cfg80211 suspend/resume and + * Enable MC address filtering during cfg80211 suspend + * only if active mode offload is disabled */ if (!pHddCtx->config->active_mode_offload) { + hdd_info("configuring unconfigured active mode offloads"); hdd_conf_arp_offload(pAdapter, fenable); + wlan_hdd_set_mc_addr_list(pAdapter, fenable); + if (pHddCtx->config->fhostNSOffload) hdd_conf_ns_offload(pAdapter, fenable); } EXIT(); - EXIT(); return; } #endif @@ -966,6 +969,23 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) } #endif +/** + * hdd_update_mcastbcast_filter(): cache multi and broadcast filter for suspend + * @hdd_ctx: hdd context + * + * Cache the configured filter to be used in suspend resume. + */ +static void hdd_update_mcastbcast_filter(hdd_context_t *hdd_ctx) +{ + if (false == hdd_ctx->sus_res_mcastbcast_filter_valid) { + hdd_ctx->sus_res_mcastbcast_filter = + hdd_ctx->configuredMcastBcastFilter; + hdd_ctx->sus_res_mcastbcast_filter_valid = true; + hdd_info("configuredMCastBcastFilter saved = %d", + hdd_ctx->configuredMcastBcastFilter); + } +} + /** * hdd_conf_suspend_ind() - Send Suspend notification * @pHddCtx: HDD Global context @@ -975,69 +995,26 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) * * Return: None. */ -static void hdd_conf_suspend_ind(hdd_context_t *pHddCtx, - hdd_adapter_t *pAdapter, +static void hdd_send_suspend_ind(hdd_context_t *pHddCtx, + uint32_t conn_state_mask, void (*callback)(void *callbackContext, bool suspended), void *callbackContext) { CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - tpSirWlanSuspendParam wlanSuspendParam = - cdf_mem_malloc(sizeof(tSirWlanSuspendParam)); - - if (false == pHddCtx->sus_res_mcastbcast_filter_valid) { - pHddCtx->sus_res_mcastbcast_filter = - pHddCtx->configuredMcastBcastFilter; - pHddCtx->sus_res_mcastbcast_filter_valid = true; - hddLog(CDF_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); - hddLog(CDF_TRACE_LEVEL_INFO, - "configuredMCastBcastFilter saved = %d", - pHddCtx->configuredMcastBcastFilter); - - } - - if (NULL == wlanSuspendParam) { - hddLog(CDF_TRACE_LEVEL_FATAL, - "%s: cdf_mem_alloc failed ", __func__); - return; - } - - hddLog(CDF_TRACE_LEVEL_INFO, - "%s: send wlan suspend indication", __func__); - - /* Configure supported OffLoads */ - hdd_conf_hostoffload(pAdapter, true); - wlanSuspendParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - /* Enable MC address filtering during cfg80211 suspend if active mode - * mode offload is disabled in INI - */ - if (!pHddCtx->config->active_mode_offload) { - hdd_info("enable mc address filtering"); - wlan_hdd_set_mc_addr_list(pAdapter, true); - } + hdd_info("%s: send wlan suspend indication", __func__); - 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; cdf_ret_status = - sme_configure_suspend_ind(pHddCtx->hHal, wlanSuspendParam, + sme_configure_suspend_ind(pHddCtx->hHal, conn_state_mask, callback, callbackContext); + if (CDF_STATUS_SUCCESS == cdf_ret_status) { pHddCtx->hdd_mcastbcast_filter_set = true; } else { hddLog(CDF_TRACE_LEVEL_ERROR, FL("sme_configure_suspend_ind returned failure %d"), cdf_ret_status); - - cdf_mem_free(wlanSuspendParam); } } @@ -1077,14 +1054,27 @@ static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); hddLog(CDF_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", pHddCtx->configuredMcastBcastFilter); +} - /* Disable MC address filtering during cfg80211 suspend if active mode - * mode offload is disabled in INI - */ - if (!pHddCtx->config->active_mode_offload) { - hdd_info("disable mc address filtering"); - wlan_hdd_set_mc_addr_list(pAdapter, false); - } +/** + * hdd_update_conn_state_mask(): record info needed by wma_suspend_req + * @adapter: adapter to get info from + * @conn_state_mask: mask of connection info + * + * currently only need to send connection info. + */ +static void +hdd_update_conn_state_mask(hdd_adapter_t *adapter, uint32_t *conn_state_mask) +{ + + eConnectionState connState; + hdd_station_ctx_t *sta_ctx; + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + connState = sta_ctx->conn_info.connState; + + if (connState == eConnectionState_Associated || + connState == eConnectionState_IbssConnected) + *conn_state_mask |= (1 << adapter->sessionId); } /** @@ -1103,9 +1093,9 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), CDF_STATUS status; hdd_adapter_t *pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + uint32_t conn_state_mask = 0; - hddLog(CDF_TRACE_LEVEL_INFO, "%s: WLAN being suspended by OS", - __func__); + hdd_info("%s: WLAN being suspended by OS", __func__); pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); if (!pHddCtx) { @@ -1120,6 +1110,8 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), return; } + hdd_update_mcastbcast_filter(pHddCtx); + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) { pAdapter = pAdapterNode->pAdapter; @@ -1129,20 +1121,19 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, WLAN_CONTROL_PATH); - /* Send suspend notification down to firmware. - * - * N.B.: Keep this suspend indication at the end - * (before processing next adaptor). This indication - * is considered as trigger point to start WOW (if wow - * is enabled). - */ - hdd_conf_suspend_ind(pHddCtx, pAdapter, callback, - callbackContext); + /* Configure supported OffLoads */ + hdd_conf_hostoffload(pAdapter, true); + + hdd_update_conn_state_mask(pAdapter, &conn_state_mask); status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; } + hdd_send_suspend_ind(pHddCtx, conn_state_mask, callback, + callbackContext); + pHddCtx->hdd_wlan_suspended = true; return; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e69dbf26b9d9..5de6302bd66d 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2663,12 +2663,6 @@ typedef struct sSirNoAParam { uint8_t psSelection; } tSirNoAParam, *tpSirNoAParam; -typedef struct sSirWlanSuspendParam { - uint8_t configuredMcstBcstFilterSetting; - uint8_t sessionId; - uint8_t connectedState; -} tSirWlanSuspendParam, *tpSirWlanSuspendParam; - typedef struct sSirWlanResumeParam { uint8_t configuredMcstBcstFilterSetting; } tSirWlanResumeParam, *tpSirWlanResumeParam; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9348ff9d80e2..7cc219d01cb3 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -461,7 +461,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, tpSirWlanSetRxpFilters wlanRxpFilterParam); CDF_STATUS sme_ConfigureAppsCpuWakeupState(tHalHandle hHal, bool isAppsAwake); CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, - tpSirWlanSuspendParam wlanSuspendParam, + uint32_t conn_state_mask, csr_readyToSuspendCallback, void *callbackContext); CDF_STATUS sme_configure_resume_req(tHalHandle hHal, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 333c31420458..b61de7734763 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -6448,7 +6448,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, --------------------------------------------------------------------------- */ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, - tpSirWlanSuspendParam wlanSuspendParam, + uint32_t conn_state_mask, csr_readyToSuspendCallback callback, void *callback_context) { @@ -6467,7 +6467,7 @@ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { /* serialize the req through MC thread */ - cds_message.bodyptr = wlanSuspendParam; + cds_message.bodyval = conn_state_mask; cds_message.type = WMA_WLAN_SUSPEND_IND; cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index b9ea71fac370..03486b165a37 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -736,7 +736,6 @@ struct wma_wow { bool deauth_enable; bool disassoc_enable; bool bmiss_enable; - bool gtk_pdev_enable; bool gtk_err_enable[WMA_MAX_SUPPORTED_BSS]; #ifdef FEATURE_WLAN_LPHB /* currently supports only vdev 0. diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 9a2cad03eed9..8ef008c7956b 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -993,7 +993,8 @@ CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info); CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info); -CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info); +CDF_STATUS wma_suspend_req(tp_wma_handle wma); +void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask); void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 36e7b8da25cf..07f511af6554 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3901,122 +3901,172 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) } /** - * wma_suspend_req() - Handles suspend indication request received from umac. + * wma_update_conn_state(): synchronize wma & hdd * @wma: wma handle - * @info: suspend params + * @conn_state: boolean array to populate + * @len: validation parameter * - * Return: CDF status + * populate interfaces conn_state with true if the interface + * is a connected client and wow will configure a pattern. */ -CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) +void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask) { - struct wma_txrx_node *iface; - bool connected = false, pno_in_progress = false; - uint8_t i; - bool extscan_in_progress = false; - - wma->no_of_suspend_ind++; - - if (info->sessionId > wma->max_bssid) { - WMA_LOGE("Invalid vdev id (%d)", info->sessionId); - cdf_mem_free(info); - return CDF_STATUS_E_INVAL; - } - - iface = &wma->interfaces[info->sessionId]; - if (!iface) { - WMA_LOGD("vdev %d node is not found", info->sessionId); - cdf_mem_free(info); - return CDF_STATUS_SUCCESS; + int i; + for (i = 0; i < wma->max_bssid; i++) { + if (conn_mask & (1 << i)) + wma->interfaces[i].conn_state = true; + else + wma->interfaces[i].conn_state = false; } - if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) { - cdf_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; - } + if (wma->wow.magic_ptrn_enable) + return; - return CDF_STATUS_SUCCESS; + for (i = 0; i < wma->max_bssid; i++) { + if (!wma->interfaces[i].ptrn_match_enable) + wma->interfaces[i].conn_state = false; } +} - 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)) { - cdf_mem_free(info); - return CDF_STATUS_SUCCESS; +/** + * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up + * @wma: wma handle + * + * Return TRUE if beaconning vdev is up + */ +static inline +bool wma_is_beaconning_vdev_up(tp_wma_handle wma) +{ + int i; + for (i = 0; i < wma->max_bssid; i++) { + if (wma_is_vdev_in_beaconning_mode(wma, i) + && wma->interfaces[i].vdev_up) + return true; } + return false; +} - wma->no_of_suspend_ind = 0; - wma->wow.gtk_pdev_enable = 0; - /* - * 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_beaconning_mode(wma, i) - ) && 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); - goto enable_wow; - } +/** + * wma_support_wow_for_beaconing: wow query for beaconning + * @wma: wma handle + * + * Need to configure wow to enable beaconning offload when + * a beaconing vdev is up and beaonning offload is configured. + * + * Return: true if we need to enable wow for beaconning offload + */ +static inline +bool wma_support_wow_for_beaconing(tp_wma_handle wma) +{ + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BEACON_OFFLOAD)) { + if (wma_is_beaconning_vdev_up(wma)) + return true; } - for (i = 0; i < wma->max_bssid; i++) { - if (wma->interfaces[i].conn_state) { - connected = true; - break; - } + return false; +} + #ifdef FEATURE_WLAN_SCAN_PNO - if (wma->interfaces[i].pno_in_progress) { - WMA_LOGD("PNO is in progress, enabling wow"); - pno_in_progress = true; - break; - } -#endif /* FEATURE_WLAN_SCAN_PNO */ +/** + * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: TRUE/FALSE + */ +static inline +bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return wma->interfaces[vdev_id].pno_in_progress; +} +#else +/** + * wma_is_pnoscan_in_progress(): dummy + * + * Return: False since no pnoscan can be in progress + * when feature flag is not defined. + */ +bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return FALSE; +} +#endif + #ifdef FEATURE_WLAN_EXTSCAN - if (wma->interfaces[i].extscan_in_progress) { - WMA_LOGD("Extscan is in progress, enabling wow"); - extscan_in_progress = true; - break; - } +static inline +/** + * wma_is_extscan_in_progress(): check if an extscan is in progress + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: TRUE/FALSvE + */ +bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return wma->interfaces[vdev_id].extscan_in_progress; +} +#else +/** + * wma_is_extscan_in_progress(): dummy + * + * Return: False since no extscan can be in progress + * when feature flag is not defined. + */ +bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return false; +} #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); + +/** + * wma_is_wow_applicable(): should enable wow + * @wma: wma handle + * + * 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 ? + * + * Return: true if wma needs to configure wow. + */ +bool wma_is_wow_applicable(tp_wma_handle wma) +{ + int vdev_id; + if (wma_support_wow_for_beaconing(wma)) { + WMA_LOGD("vdev is in beaconning mode, enabling wow"); + return true; } - if (!connected && !pno_in_progress && !extscan_in_progress) { - WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); - cdf_mem_free(info); - goto send_ready_to_suspend; + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + if (wma->interfaces[vdev_id].conn_state) { + WMA_LOGD("STA is connected, enabling wow"); + return true; + } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) { + WMA_LOGD("PNO is in progress, enabling wow"); + return true; + } else if (wma_is_extscan_in_progress(wma, vdev_id)) { + WMA_LOGD("EXT is in progress, enabling wow"); + return true; + } } -enable_wow: - WMA_LOGE("WOW Suspend"); + WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); + return true; +} - /* - * 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_apply_lphb(): apply cached LPHB settings + * @wma: wma handle + * + * LPHB cache, if any item was enabled, should be + * applied. + */ +static inline +void wma_apply_lphb(tp_wma_handle wma) +{ + int i; WMA_LOGD("%s: checking LPHB cache", __func__); for (i = 0; i < 2; i++) { if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) { @@ -4026,14 +4076,28 @@ enable_wow: false); } } +} +#else +void wma_apply_lphb(tp_wma_handle wma) {} #endif /* FEATURE_WLAN_LPHB */ - wma->wow.wow_enable = true; - wma->wow.wow_enable_cmd_sent = false; +/** + * wma_suspend_req() - Handles suspend indication request received from umac. + * @wma: wma handle + * @info: suspend params + * + * Return: CDF status + */ +CDF_STATUS wma_suspend_req(tp_wma_handle wma) +{ + if (wma_is_wow_applicable(wma)) { + WMA_LOGE("WOW Suspend"); + wma_apply_lphb(wma); - cdf_mem_free(info); + wma->wow.wow_enable = true; + wma->wow.wow_enable_cmd_sent = false; + } -send_ready_to_suspend: /* Set the Suspend DTIM Parameters */ wma_set_suspend_dtim(wma); wma_send_status_to_suspend_ind(wma, true); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 718c66dc9bb6..935db34862a6 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -4875,8 +4875,8 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); break; case WMA_WLAN_SUSPEND_IND: - wma_suspend_req(wma_handle, - (tpSirWlanSuspendParam) msg->bodyptr); + wma_update_conn_state(wma_handle, msg->bodyval); + wma_suspend_req(wma_handle); break; case WMA_8023_MULTICAST_LIST_REQ: wma_process_mcbc_set_filter_req(wma_handle, -- cgit v1.2.3 From 8e1d8a6c8922eb5fe91f207b1cb03d782acaf122 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 16 Dec 2015 11:28:51 -0800 Subject: qcacld-3.0: Add dynamic wake event configuration Want to dynamically enable and disable wakeup for pno scan. Change-Id: I95876979652ab16976f23561038c877cee4c930a CRs-Fixed: 935297 --- core/wma/src/wma_features.c | 80 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 07f511af6554..541b7eb3dc49 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -102,10 +102,6 @@ static const uint8_t arp_mask[] = {0xff, 0xff}; static const uint8_t ns_ptrn[] = {0x86, 0xDD}; static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; -static CDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, - uint32_t vdev_id, - uint32_t bitmap, - bool enable); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN /** @@ -2850,20 +2846,11 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, wma_wow_wake_up_stats(wma, NULL, 0, WOW_REASON_NLOD); node = &wma->interfaces[wake_info->vdev_id]; if (node) { - CDF_STATUS ret = CDF_STATUS_SUCCESS; WMA_LOGD("NLO match happened"); node->nlo_match_evt_received = true; cdf_wake_lock_timeout_acquire(&wma->pno_wake_lock, WMA_PNO_MATCH_WAKE_LOCK_TIMEOUT, WIFI_POWER_EVENT_WAKELOCK_PNO); - /* Configure pno scan complete wakeup */ - ret = wma_add_wow_wakeup_event(wma, wake_info->vdev_id, - (1 << WOW_NLO_SCAN_COMPLETE_EVENT), - true); - if (ret != CDF_STATUS_SUCCESS) - WMA_LOGE("Failed to configure pno scan complete wakeup"); - else - WMA_LOGD("PNO scan complete wakeup is enabled in fw"); } break; @@ -3979,17 +3966,44 @@ bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) { return wma->interfaces[vdev_id].pno_in_progress; } + +/** + * wma_is_pnoscan_match_found(): check if a scan match was found + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: TRUE/FALSE + */ +static inline +bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id) +{ + return wma->interfaces[vdev_id].nlo_match_evt_received; +} #else /** * wma_is_pnoscan_in_progress(): dummy * - * Return: False since no pnoscan can be in progress + * Return: False since no pnoscan cannot be in progress * when feature flag is not defined. */ bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) { return FALSE; } + +/** + * wma_is_pnoscan_match_found(): dummy + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: False since no pnoscan cannot occur + * when feature flag is not defined. + */ +static inline +bool wma_is_pnoscan_match_found(tp_wma_handle wma, int vdev_id) +{ + return FALSE; +} #endif #ifdef FEATURE_WLAN_EXTSCAN @@ -4055,6 +4069,42 @@ bool wma_is_wow_applicable(tp_wma_handle wma) return true; } +/** + * wma_configure_dynamic_wake_events(): configure dyanmic wake events + * @wma: wma handle + * + * Some wake events need to be enabled dynamically. Controll those here. + * + * Return: none + */ +void wma_configure_dynamic_wake_events(tp_wma_handle wma) +{ + int vdev_id; + int enable_mask; + int disable_mask; + + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + enable_mask = 0; + disable_mask = 0; + + if (wma_is_pnoscan_in_progress(wma, vdev_id)) { + if (wma_is_pnoscan_match_found(wma, vdev_id)) + enable_mask |= + (1 << WOW_NLO_SCAN_COMPLETE_EVENT); + else + disable_mask |= + (1 << WOW_NLO_SCAN_COMPLETE_EVENT); + } + + if (enable_mask != 0) + wma_enable_disable_wakeup_event(wma, vdev_id, + enable_mask, true); + if (disable_mask != 0) + wma_enable_disable_wakeup_event(wma, vdev_id, + disable_mask, false); + } +} + #ifdef FEATURE_WLAN_LPHB /** * wma_apply_lphb(): apply cached LPHB settings @@ -4094,6 +4144,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma) WMA_LOGE("WOW Suspend"); wma_apply_lphb(wma); + wma_configure_dynamic_wake_events(wma); + wma->wow.wow_enable = true; wma->wow.wow_enable_cmd_sent = false; } -- cgit v1.2.3 From 47e387baf71dc643605e9a204dddcb558da85c67 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 20 Oct 2015 17:04:42 -0700 Subject: qcacld-3.0: Implement htc runtime suspend/resume Provide the apis to suspend & resume the htc layer for runtime suspend. Change-Id: Ia4c4f00fa62b250c5097e6bc14137b0114c5c90f CRs-Fixed: 935300 --- core/dp/htt/htt.c | 4 +++- core/dp/htt/htt_internal.h | 3 ++- core/dp/htt/htt_tx.c | 20 +++++++++++++++- core/htc/htc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++-- core/htc/htc_api.h | 8 ++++++- core/htc/htc_internal.h | 5 +++- core/htc/htc_send.c | 29 +++++++++++++++++++++++ 7 files changed, 121 insertions(+), 7 deletions(-) diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index 4bc45c879a65..686882b6aead 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -43,6 +43,7 @@ #include #include +#include #include "hif.h" #define HTT_HTC_PKT_POOL_INIT_SIZE 100 /* enough for a large A-MPDU */ @@ -405,6 +406,7 @@ int htt_htc_attach(struct htt_pdev_t *pdev) connect.EpCallbacks.EpTxComplete = htt_h2t_send_complete; connect.EpCallbacks.EpTxCompleteMultiple = NULL; connect.EpCallbacks.EpRecv = htt_t2h_msg_handler; + connect.EpCallbacks.ep_resume_tx_queue = htt_tx_resume_handler; /* rx buffers currently are provided by HIF, not by EpRecvRefill */ connect.EpCallbacks.EpRecvRefill = NULL; diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index 5ab0b1a680b0..28b1e08b3da6 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -413,6 +413,7 @@ static inline void htt_print_rx_desc(struct htt_host_rx_desc_base *rx_desc) #endif +void htt_tx_resume_handler(void *); #ifdef ATH_11AC_TXCOMPACT #define HTT_TX_SCHED htt_tx_sched #else diff --git a/core/dp/htt/htt_tx.c b/core/dp/htt/htt_tx.c index f733fc64bc9f..1aa28f9ce202 100644 --- a/core/dp/htt/htt_tx.c +++ b/core/dp/htt/htt_tx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -625,6 +625,24 @@ int htt_tx_send_std(htt_pdev_handle pdev, cdf_nbuf_t msdu, uint16_t msdu_id) } +#ifdef FEATURE_RUNTIME_PM +/** + * htt_tx_resume_handler() - resume callback for the htt endpoint + * @context: a pointer to the htt context + * + * runs htt_tx_sched. + */ +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 + cdf_nbuf_t htt_tx_send_batch(htt_pdev_handle pdev, cdf_nbuf_t head_msdu, int num_msdus) { diff --git a/core/htc/htc.c b/core/htc/htc.c index 8e45efcd1721..d065193da3b7 100644 --- a/core/htc/htc.c +++ b/core/htc/htc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -34,6 +34,7 @@ #include "epping_main.h" #include "hif_io32.h" #include "cds_concurrency.h" +#include #ifdef DEBUG static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = { @@ -214,6 +215,7 @@ HTC_HANDLE htc_create(void *ol_sc, HTC_INIT_INFO *pInfo, cdf_device_t osdev) A_MEMZERO(target, sizeof(HTC_TARGET)); + htc_runtime_pm_init(target); cdf_spinlock_init(&target->HTCLock); cdf_spinlock_init(&target->HTCRxLock); cdf_spinlock_init(&target->HTCTxLock); @@ -681,7 +683,60 @@ void htc_stop(HTC_HANDLE HTCHandle) reset_endpoint_states(target); - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n")); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n")); +} + +/** + * htc_runtime_pm_init(): runtime pm related intialization + * + * need to initialize a work item. + */ +void htc_runtime_pm_init(HTC_TARGET *target) +{ + cdf_create_work(&target->queue_kicker, htc_kick_queues, target); +} + +/** + * htc_runtime_suspend(): ensure htc is ready to suspend + * + * htc is ready to suspend if there are no pending pactets + * in the txrx queues. + * + * Return: 0 on success or -EBUSY if there are queued packets. + */ +int htc_runtime_suspend(void) +{ + ol_txrx_pdev_handle txrx_pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + if (txrx_pdev == NULL) { + HTC_ERROR("%s: txrx context null", __func__); + return CDF_STATUS_E_FAULT; + } + + if (ol_txrx_get_tx_pending(txrx_pdev)) + return -EBUSY; + else + return 0; +} + +/** + * htc_runtime_resume(): resume htc + * + * The htc message queue needs to be kicked off after + * a runtime resume. Otherwise messages would get stuck. + * + * Return: 0 for success; + */ +int htc_runtime_resume(void) +{ + HTC_HANDLE htc_ctx = cds_get_context(CDF_MODULE_ID_HTC); + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_ctx); + + if (target == NULL) + return 0; + + cdf_schedule_work(&target->queue_kicker); + return 0; } void htc_dump_credit_states(HTC_HANDLE HTCHandle) diff --git a/core/htc/htc_api.h b/core/htc/htc_api.h index 7ae13b453955..94b38296a5c3 100644 --- a/core/htc/htc_api.h +++ b/core/htc/htc_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -66,6 +66,9 @@ struct ol_ath_htc_stats { 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 @@ -151,6 +154,7 @@ typedef struct _HTC_EP_CALLBACKS { indications (EpTxComplete must be NULL) */ HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple recv packet indications (EpRecv must be NULL) */ + HTC_EP_RESUME_TX_QUEUE ep_resume_tx_queue; 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 */ @@ -694,6 +698,8 @@ void htc_dump_counter_info(HTC_HANDLE HTCHandle); void *htc_get_targetdef(HTC_HANDLE htc_handle); void htc_set_target_to_sleep(void *context); void htc_cancel_deferred_target_sleep(void *context); +int htc_runtime_suspend(void); +int htc_runtime_resume(void); /* Disable ASPM : Disable PCIe low power */ void htc_disable_aspm(void); diff --git a/core/htc/htc_internal.h b/core/htc/htc_internal.h index 8785993893b6..5b98d1368aae 100644 --- a/core/htc/htc_internal.h +++ b/core/htc/htc_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -184,6 +184,7 @@ typedef struct _HTC_TARGET { A_UINT32 ce_send_cnt; A_UINT32 TX_comp_cnt; A_UINT8 MaxMsgsPerHTCBundle; + cdf_work_t queue_kicker; } HTC_TARGET; #define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1) @@ -245,6 +246,8 @@ void htc_process_credit_rpt(HTC_TARGET *target, int NumEntries, HTC_ENDPOINT_ID FromEndpoint); void htc_fw_event_handler(void *context, CDF_STATUS status); void htc_send_complete_check_cleanup(void *context); +void htc_runtime_pm_init(HTC_TARGET *target); +void htc_kick_queues(void *context); void htc_credit_record(htc_credit_exchange_type type, uint32_t tx_credit, uint32_t htc_tx_queue_depth); diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index bb5c34368a00..99c626b192d3 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -1669,6 +1669,35 @@ void htc_tx_resource_avail_handler(void *context, A_UINT8 pipeID) htc_try_send(target, pEndpoint, NULL); } +/** + * htc_kick_queues(): resumes tx transactions of suspended endpoints + * @context: pointer to the htc target context + * + * Iterates throught the enpoints and provides a context to empty queues + * int the hif layer when they are stalled due to runtime suspend. + * + * Return: none + */ +void htc_kick_queues(void *context) +{ + int i; + HTC_TARGET *target = (HTC_TARGET *)context; + HTC_ENDPOINT *endpoint = NULL; + + for (i = 0; i < ENDPOINT_MAX; i++) { + endpoint = &target->endpoint[i]; + + if (endpoint->service_id == 0) + continue; + + if (endpoint->EpCallBacks.ep_resume_tx_queue) + endpoint->EpCallBacks.ep_resume_tx_queue( + endpoint->EpCallBacks.pContext); + + htc_try_send(target, endpoint, NULL); + } +} + /* flush endpoint TX queue */ void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag) -- cgit v1.2.3 From 62aa58dc7ae14301b4f3c491e216e4c78d6de530 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 2 Nov 2015 21:14:55 -0800 Subject: qcacld-3.0: Add runtime pm initialization Add runtime pm initialization, including the creation of a debugfs entry. Change-Id: Ib057feaf36a04bb525a731e236187c134449c5f2 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 1 + core/hif/inc/hif.h | 1 + core/hif/src/pcie/if_pci.c | 325 +++++++++++++++++++++++++++++++++++++ core/hif/src/pcie/if_pci.h | 63 ++++++- 4 files changed, 389 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 2308a0d6edaf..39cd2111e883 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -247,6 +247,7 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, if (ret) goto err_hif_close; + hif_enable_power_management(hif_ctx); if (reinit) { cds_set_recovery_in_progress(false); diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index cc7a66fd7fad..b1ff3d930269 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -642,6 +642,7 @@ CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, void *bdev, enum hif_enable_type type); void hif_disable(void *hif_ctx, enum hif_disable_type type); void hif_enable_power_gating(void *hif_ctx); +void hif_enable_power_management(void *hif_ctx); int hif_bus_resume(void); int hif_bus_suspend(void); void hif_vote_link_down(void); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 21cec32177a0..15e8ccb94c3e 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -43,6 +43,8 @@ #include "bmi_msg.h" /* TARGET_TYPE_ */ #include "regtable.h" #include "ol_fw.h" +#include +#include #include #include "cds_api.h" #include "cdf_status.h" @@ -804,6 +806,326 @@ end: cdf_atomic_dec(&scn->active_tasklet_cnt); } +#ifdef FEATURE_RUNTIME_PM +#define HIF_PCI_RUNTIME_PM_STATS(_s, _sc, _name) \ + seq_printf(_s, "%30s: %u\n", #_name, _sc->pm_stats._name) + +/** + * hif_pci_runtime_pm_warn() - Runtime PM Debugging API + * @sc: hif_pci_softc context + * @msg: log message + * + * log runtime pm stats when something seems off. + * + * Return: void + */ +void hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *msg) +{ + struct hif_pm_runtime_lock *ctx; + + HIF_ERROR("%s: usage_count: %d, pm_state: %d, prevent_suspend_cnt: %d", + msg, atomic_read(&sc->dev->power.usage_count), + atomic_read(&sc->pm_state), + sc->prevent_suspend_cnt); + + HIF_ERROR("runtime_status: %d, runtime_error: %d, disable_depth: %d autosuspend_delay: %d", + sc->dev->power.runtime_status, + sc->dev->power.runtime_error, + sc->dev->power.disable_depth, + sc->dev->power.autosuspend_delay); + + HIF_ERROR("runtime_get: %u, runtime_put: %u, request_resume: %u", + sc->pm_stats.runtime_get, sc->pm_stats.runtime_put, + sc->pm_stats.request_resume); + + HIF_ERROR("allow_suspend: %u, prevent_suspend: %u", + sc->pm_stats.allow_suspend, + sc->pm_stats.prevent_suspend); + + HIF_ERROR("prevent_suspend_timeout: %u, allow_suspend_timeout: %u", + sc->pm_stats.prevent_suspend_timeout, + sc->pm_stats.allow_suspend_timeout); + + HIF_ERROR("Suspended: %u, resumed: %u count", + sc->pm_stats.suspended, + sc->pm_stats.resumed); + + HIF_ERROR("suspend_err: %u, runtime_get_err: %u", + sc->pm_stats.suspend_err, + sc->pm_stats.runtime_get_err); + + HIF_ERROR("Active Wakeup Sources preventing Runtime Suspend: "); + + list_for_each_entry(ctx, &sc->prevent_suspend_list, list) { + HIF_ERROR("source %s; timeout %d ms", ctx->name, ctx->timeout); + } + + WARN_ON(1); +} + +/** + * hif_pci_pm_runtime_debugfs_show(): show debug stats for runtimepm + * @s: file to print to + * @data: unused + * + * debugging tool added to the debug fs for displaying runtimepm stats + * + * Return: 0 + */ +static int hif_pci_pm_runtime_debugfs_show(struct seq_file *s, void *data) +{ + struct hif_pci_softc *sc = s->private; + static const char * const 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_lock *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_RUNTIME_PM_STATS(s, sc, suspended); + HIF_PCI_RUNTIME_PM_STATS(s, sc, suspend_err); + HIF_PCI_RUNTIME_PM_STATS(s, sc, resumed); + HIF_PCI_RUNTIME_PM_STATS(s, sc, runtime_get); + HIF_PCI_RUNTIME_PM_STATS(s, sc, runtime_put); + HIF_PCI_RUNTIME_PM_STATS(s, sc, request_resume); + HIF_PCI_RUNTIME_PM_STATS(s, sc, prevent_suspend); + HIF_PCI_RUNTIME_PM_STATS(s, sc, allow_suspend); + HIF_PCI_RUNTIME_PM_STATS(s, sc, prevent_suspend_timeout); + HIF_PCI_RUNTIME_PM_STATS(s, sc, allow_suspend_timeout); + HIF_PCI_RUNTIME_PM_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_RUNTIME_PM_STATS + +/** + * hif_pci_autopm_open() - open a debug fs file to access the runtime pm stats + * @inode + * @file + * + * Return: linux error code of single_open. + */ +static int hif_pci_runtime_pm_open(struct inode *inode, struct file *file) +{ + return single_open(file, hif_pci_pm_runtime_debugfs_show, + inode->i_private); +} + +#ifdef WLAN_OPEN_SOURCE +static const struct file_operations hif_pci_runtime_pm_fops = { + .owner = THIS_MODULE, + .open = hif_pci_runtime_pm_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +/** + * hif_runtime_pm_debugfs_create() - creates runtimepm debugfs entry + * @sc: pci context + * + * creates a debugfs entry to debug the runtime pm feature. + */ +static void hif_runtime_pm_debugfs_create(struct hif_pci_softc *sc) +{ + sc->pm_dentry = debugfs_create_file("cnss_runtime_pm", + S_IRUSR, NULL, sc, + &hif_pci_runtime_pm_fops); +} +/** + * hif_runtime_pm_debugfs_remove() - removes runtimepm debugfs entry + * @sc: pci context + * + * removes the debugfs entry to debug the runtime pm feature. + */ +static void hif_runtime_pm_debugfs_remove(struct hif_pci_softc *sc) +{ + debugfs_remove(sc->pm_dentry); +} +#else +static inline void hif_runtime_pm_debugfs_create(struct hif_pci_softc *sc) +{ +} +static inline void hif_runtime_pm_debugfs_remove(struct hif_pci_softc *sc) +{ +} +#endif + +/** + * hif_pm_runtime_lock_timeout_fn() - callback the runtime lock timeout + * @data: calback data that is the pci context + * + * if runtime locks are aquired with a timeout, this function releases + * the locks when the latest runtime lock expires. + * + * dummy implementation until lock acquisition is implemented. + */ +void hif_pm_runtime_lock_timeout_fn(unsigned long data) {} + +/** + * hif_pm_runtime_start(): start the runtime pm + * @sc: pci context + * + * After this call, runtime pm will be active. + */ +static void hif_pm_runtime_start(struct hif_pci_softc *sc) +{ + struct ol_softc *ol_sc; + + ol_sc = sc->ol_sc; + + if (!ol_sc->enable_runtime_pm) { + HIF_INFO("%s: RUNTIME PM is disabled in ini\n", __func__); + return; + } + + if (cds_get_conparam() == CDF_FTM_MODE || + WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + HIF_INFO("%s: RUNTIME PM is disabled for FTM/EPPING mode\n", + __func__); + return; + } + + setup_timer(&sc->runtime_timer, hif_pm_runtime_lock_timeout_fn, + (unsigned long)sc); + + HIF_INFO("%s: Enabling RUNTIME PM, Delay: %d ms", __func__, + ol_sc->runtime_pm_delay); + + cnss_runtime_init(sc->dev, ol_sc->runtime_pm_delay); + cdf_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_ON); + hif_runtime_pm_debugfs_create(sc); +} + +/** + * hif_pm_runtime_stop(): stop runtime pm + * @sc: pci context + * + * Turns off runtime pm and frees corresponding resources + * that were acquired by hif_runtime_pm_start(). + */ +static void hif_pm_runtime_stop(struct hif_pci_softc *sc) +{ + struct ol_softc *ol_sc = sc->ol_sc; + + if (!ol_sc->enable_runtime_pm) + return; + + if (cds_get_conparam() == CDF_FTM_MODE || + WLAN_IS_EPPING_ENABLED(cds_get_conparam())) + return; + + cnss_runtime_exit(sc->dev); + cnss_pm_runtime_request(sc->dev, CNSS_PM_RUNTIME_RESUME); + + cdf_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_NONE); + + hif_runtime_pm_debugfs_remove(sc); + del_timer_sync(&sc->runtime_timer); + /* doesn't wait for penting trafic unlike cld-2.0 */ +} + +/** + * hif_pm_runtime_open(): initialize runtime pm + * @sc: pci data structure + * + * Early initialization + */ +static void hif_pm_runtime_open(struct hif_pci_softc *sc) +{ + spin_lock_init(&sc->runtime_lock); + + cdf_atomic_init(&sc->pm_state); + cdf_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_NONE); + INIT_LIST_HEAD(&sc->prevent_suspend_list); +} + +/** + * hif_pm_runtime_close(): close runtime pm + * @sc: pci bus handle + * + * ensure runtime_pm is stopped before closing the driver + */ +static void hif_pm_runtime_close(struct hif_pci_softc *sc) +{ + if (cdf_atomic_read(&sc->pm_state) == HIF_PM_RUNTIME_STATE_NONE) + return; + else + hif_pm_runtime_stop(sc); +} + + +#else + +static void hif_pm_runtime_close(struct hif_pci_softc *sc) {} +static void hif_pm_runtime_open(struct hif_pci_softc *sc) {} +static void hif_pm_runtime_start(struct hif_pci_softc *sc) {} +#endif + +/** + * hif_enable_power_management(): enable power management + * @hif_ctx: hif context + * + * Currently only does runtime pm. Eventually this function could + * consolidate other power state features such as only letting + * the soc sleep after the driver finishes loading and re-enabling + * aspm (hif_enable_power_gating). + */ +void hif_enable_power_management(void *hif_ctx) +{ + struct hif_pci_softc *pci_ctx; + + if (hif_ctx == NULL) { + HIF_ERROR("%s, hif_ctx null", __func__); + return; + } + + pci_ctx = ((struct ol_softc *)hif_ctx)->hif_sc; + + hif_pm_runtime_start(pci_ctx); +} + #define ATH_PCI_PROBE_RETRY_MAX 3 /** * hif_bus_open(): hif_bus_open @@ -824,6 +1146,7 @@ CDF_STATUS hif_bus_open(struct ol_softc *ol_sc, enum ath_hal_bus_type bus_type) ol_sc->hif_sc = (void *)sc; sc->ol_sc = ol_sc; ol_sc->bus_type = bus_type; + hif_pm_runtime_open(sc); cdf_spinlock_init(&ol_sc->irq_lock); @@ -846,6 +1169,8 @@ void hif_bus_close(struct ol_softc *ol_sc) sc = ol_sc->hif_sc; if (sc == NULL) return; + + hif_pm_runtime_close(sc); cdf_mem_free(sc); ol_sc->hif_sc = NULL; } diff --git a/core/hif/src/pcie/if_pci.h b/core/hif/src/pcie/if_pci.h index b2f5bd6c20a2..d49c53e671d4 100644 --- a/core/hif/src/pcie/if_pci.h +++ b/core/hif/src/pcie/if_pci.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -50,6 +50,54 @@ struct hif_tasklet_entry { uint8_t id; /* 0 - 9: maps to CE, 10: fw */ void *hif_handler; /* struct hif_pci_softc */ }; + +/** + * enum hif_pm_runtime_state - Driver States for Runtime Power Management + * HIF_PM_RUNTIME_STATE_NONE: runtime pm is off + * HIF_PM_RUNTIME_STATE_ON: runtime pm is active and link is active + * HIF_PM_RUNTIME_STATE_INPROGRESS: a runtime suspend or resume is in progress + * HIF_PM_RUNTIME_STATE_SUSPENDED: the driver is runtime suspended + */ +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, +}; + +#ifdef FEATURE_RUNTIME_PM + +/** + * struct hif_pm_runtime_lock - data structure for preventing runtime suspend + * @list - global list of runtime locks + * @active - true if this lock is preventing suspend + * @name - character string for tracking this lock + */ +struct hif_pm_runtime_lock { + struct list_head list; + bool active; + uint32_t timeout; + const char *name; +}; + +/* 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 */ @@ -69,6 +117,19 @@ struct hif_pci_softc { cdf_dma_addr_t soc_pcie_bar0; struct hif_tasklet_entry tasklet_entries[HIF_MAX_TASKLET_NUM]; bool pci_enabled; +#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; + spinlock_t 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 }; bool hif_pci_targ_is_present(struct ol_softc *scn, void *__iomem *mem); -- cgit v1.2.3 From f2ff37a509c64c0fbe8cdf584f33e88a67c9d364 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 3 Nov 2015 11:33:36 -0800 Subject: qcacld-3.0: Provide setters for pm_state to upper layer Runtime pm opperations will be initiated in hdd, so hdd needs an api to updated the runtime_pm state. Change-Id: I783fc136777a56d8ea23f8b11617ebe92641221a CRs-Fixed: 935300 --- core/hif/inc/hif.h | 3 +++ core/hif/src/pcie/if_pci.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ core/hif/src/snoc/if_snoc.c | 29 ++++++++++++++++++++++- 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index b1ff3d930269..c49e14b102b2 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -648,6 +648,9 @@ int hif_bus_suspend(void); void hif_vote_link_down(void); void hif_vote_link_up(void); bool hif_can_suspend_link(void); +void hif_runtime_pm_set_state_inprogress(void); +void hif_runtime_pm_set_state_on(void); +void hif_runtime_pm_set_state_suspended(void); int dump_ce_register(struct ol_softc *scn); int ol_copy_ramdump(struct ol_softc *scn); void hif_pktlogmod_exit(void *hif_ctx); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 15e8ccb94c3e..71d0291aa1c1 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1832,6 +1832,64 @@ int hif_bus_resume(void) return hif_bus_resume_link_up(); } +#ifdef FEATURE_RUNTIME_PM +/** + * __hif_runtime_pm_set_state(): utility function + * @state: state to set + * + * indexes into the runtime pm state and sets it. + */ +static void __hif_runtime_pm_set_state(enum hif_pm_runtime_state state) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + struct hif_pci_softc *sc; + + if (NULL == scn) { + HIF_ERROR("%s: HIF_CTX not initialized", + __func__); + return; + } + + sc = scn->hif_sc; + cdf_atomic_set(&sc->pm_state, state); + +} +#else +static void __hif_runtime_pm_set_state(enum hif_pm_runtime_state state) +{ +} +#endif + +/** + * hif_runtime_pm_set_state_inprogress(): adjust runtime pm state + * + * Notify hif that a runtime pm opperation has started + */ +void hif_runtime_pm_set_state_inprogress(void) +{ + __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_INPROGRESS); +} + +/** + * hif_runtime_pm_set_state_on(): adjust runtime pm state + * + * Notify hif that a the runtime pm state should be on + */ +void hif_runtime_pm_set_state_on(void) +{ + __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_ON); +} + +/** + * hif_runtime_pm_set_state_suspended(): adjust runtime pm state + * + * Notify hif that a runtime suspend attempt has been completed successfully + */ +void hif_runtime_pm_set_state_suspended(void) +{ + __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_SUSPENDED); +} + void hif_disable_isr(void *ol_sc) { struct ol_softc *scn = (struct ol_softc *)ol_sc; diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index f9fa886ce12a..c5f248d8f847 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -114,6 +114,33 @@ void dump_ce_debug_register(struct ol_softc *scn) return; } +/** + * hif_runtime_pm_set_state_inprogress() - dummy function + * + * currently runtime pm only supported in pci + */ +void hif_runtime_pm_set_state_inprogress(void) +{ +} + +/** + * hif_runtime_pm_set_state_on() - dummy function + * + * currently runtime pm only supported in pci + */ +void hif_runtime_pm_set_state_on(void) +{ +} + +/** + * hif_runtime_pm_set_state_suspended() - dummy function + * + * currently runtime pm only supported in pci + */ +void hif_runtime_pm_set_state_on(void) +{ +} + /** * hif_bus_suspend() - suspend the bus * -- cgit v1.2.3 From 9078a159f16dd8757d5c4f0f9d39cb8a66918280 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 2 Nov 2015 16:15:02 -0800 Subject: qcacld-3.0: Add hif apis to prevent allow runtime pm Support pm_runtime put/get/prevent/allow apis in hif layer. Change-Id: I66be45de4177eeff3678b9ebd874c9bbde3cad22 CRs-Fixed: 935300 --- core/hif/inc/hif.h | 41 ++++ core/hif/src/pcie/if_pci.c | 468 ++++++++++++++++++++++++++++++++++++++++++++- core/hif/src/pcie/if_pci.h | 55 ++++++ 3 files changed, 554 insertions(+), 10 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index c49e14b102b2..de926ef998b1 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -642,6 +642,47 @@ CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, void *bdev, enum hif_enable_type type); void hif_disable(void *hif_ctx, enum hif_disable_type type); void hif_enable_power_gating(void *hif_ctx); + +#ifdef FEATURE_RUNTIME_PM +struct hif_pm_runtime_lock; +int hif_pm_runtime_get(void *hif_ctx); +int hif_pm_runtime_put(void *hif_ctx); +struct hif_pm_runtime_lock *hif_runtime_lock_init(const char *name); +void hif_runtime_lock_deinit(struct hif_pm_runtime_lock *lock); +int hif_pm_runtime_prevent_suspend(void *ol_sc, + struct hif_pm_runtime_lock *lock); +int hif_pm_runtime_allow_suspend(void *ol_sc, + struct hif_pm_runtime_lock *lock); +int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, + struct hif_pm_runtime_lock *lock, unsigned int delay); +#else +struct hif_pm_runtime_lock { + const char *name; +}; +static inline int hif_pm_runtime_get(void *hif_ctx) +{ return 0; } +static inline int hif_pm_runtime_put(void *hif_ctx) +{ return 0; } +static inline struct hif_pm_runtime_lock *hif_runtime_lock_init( + const char *name) +{ return NULL; } +static inline void hif_runtime_lock_deinit(struct hif_pm_runtime_lock *lock) +{} + +static inline int hif_pm_runtime_prevent_suspend(void *ol_sc, + struct hif_pm_runtime_lock *lock) +{ return 0; } +static inline int hif_pm_runtime_allow_suspend(void *ol_sc, + struct hif_pm_runtime_lock *lock) +{ return 0; } +static inline int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, + struct hif_pm_runtime_lock *lock, unsigned int delay) +{ return 0; } +#endif + +void hif_runtime_pm_set_state_inprogress(void); +void hif_runtime_pm_set_state_on(void); + void hif_enable_power_management(void *hif_ctx); int hif_bus_resume(void); int hif_bus_suspend(void); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 71d0291aa1c1..09e06f15fa30 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -992,16 +992,7 @@ static inline void hif_runtime_pm_debugfs_remove(struct hif_pci_softc *sc) } #endif -/** - * hif_pm_runtime_lock_timeout_fn() - callback the runtime lock timeout - * @data: calback data that is the pci context - * - * if runtime locks are aquired with a timeout, this function releases - * the locks when the latest runtime lock expires. - * - * dummy implementation until lock acquisition is implemented. - */ -void hif_pm_runtime_lock_timeout_fn(unsigned long data) {} +static void hif_pm_runtime_lock_timeout_fn(unsigned long data); /** * hif_pm_runtime_start(): start the runtime pm @@ -2564,3 +2555,460 @@ int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, return hif_get_device_type(id->device, revision_id, hif_type, target_type); } + +#ifdef FEATURE_RUNTIME_PM +/** + * hif_pm_runtime_get() - do a get opperation on the device + * + * A get opperation will prevent a runtime suspend untill a + * corresponding put is done. This api should be used when sending + * data. + * + * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED, + * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!! + * + * return: success if the bus is up and a get has been issued + * otherwise an error code. + */ +int hif_pm_runtime_get(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + struct hif_pci_softc *sc; + int ret; + int pm_state; + + if (NULL == scn) { + HIF_ERROR("%s: Could not do runtime get, scn is null", + __func__); + return -EFAULT; + } + sc = scn->hif_sc; + + pm_state = cdf_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_ctx); + + if (ret && ret != -EINPROGRESS) { + sc->pm_stats.runtime_get_err++; + HIF_ERROR("%s: Runtime Get PM Error in pm_state:%d ret: %d", + __func__, cdf_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; +} + +/** + * hif_pm_runtime_put() - do a put opperation on the device + * + * A put opperation will allow a runtime suspend after a corresponding + * get was done. This api should be used when sending data. + * + * This api will return a failure if runtime pm is stopped + * This api will return failure if it would decrement the usage count below 0. + * + * return: CDF_STATUS_SUCCESS if the put is performed + */ +int hif_pm_runtime_put(void *hif_ctx) +{ + struct ol_softc *scn = (struct ol_softc *)hif_ctx; + struct hif_pci_softc *sc; + int pm_state, usage_count; + unsigned long flags; + char *error = NULL; + + if (NULL == scn) { + HIF_ERROR("%s: Could not do runtime put, scn is null", + __func__); + return -EFAULT; + } + sc = scn->hif_sc; + + usage_count = atomic_read(&sc->dev->power.usage_count); + + if (usage_count == 1) { + pm_state = cdf_atomic_read(&sc->pm_state); + + if (pm_state == HIF_PM_RUNTIME_STATE_NONE) + error = "Ignoring unexpected put when runtime pm is disabled"; + + } else if (usage_count == 0) { + error = "PUT Without a Get Operation"; + } + + if (error) { + spin_lock_irqsave(&sc->runtime_lock, flags); + hif_pci_runtime_pm_warn(sc, error); + spin_unlock_irqrestore(&sc->runtime_lock, flags); + return -EINVAL; + } + + sc->pm_stats.runtime_put++; + + hif_pm_runtime_mark_last_busy(sc->dev); + hif_pm_runtime_put_auto(sc->dev); + + return 0; +} + + +/** + * __hif_pm_runtime_prevent_suspend() - prevent runtime suspend for a protocol reason + * @hif_sc: pci context + * @lock: runtime_pm lock being acquired + * + * Return 0 if successful. + */ +static int __hif_pm_runtime_prevent_suspend(struct hif_pci_softc + *hif_sc, struct hif_pm_runtime_lock *lock) +{ + 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 (lock->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++; + + lock->active = true; + + list_add_tail(&lock->list, &hif_sc->prevent_suspend_list); + + hif_sc->pm_stats.prevent_suspend++; + + HIF_ERROR("%s: in pm_state:%d ret: %d", __func__, + cdf_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_lock *lock) +{ + int ret = 0; + int usage_count; + + if (hif_sc->prevent_suspend_cnt == 0) + return ret; + + if (!lock->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 ((cdf_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(&lock->list); + + hif_sc->prevent_suspend_cnt--; + + lock->active = false; + lock->timeout = 0; + + hif_pm_runtime_mark_last_busy(hif_sc->dev); + ret = hif_pm_runtime_put_auto(hif_sc->dev); + + HIF_ERROR("%s: in pm_state:%d ret: %d", __func__, + cdf_atomic_read(&hif_sc->pm_state), ret); + + hif_sc->pm_stats.allow_suspend++; + return ret; +} + +/** + * hif_pm_runtime_lock_timeout_fn() - callback the runtime lock timeout + * @data: calback data that is the pci context + * + * if runtime locks are aquired with a timeout, this function releases + * the locks when the last runtime lock expires. + * + * dummy implementation until lock acquisition is implemented. + */ +static void hif_pm_runtime_lock_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_lock *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, + struct hif_pm_runtime_lock *data) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + struct hif_pm_runtime_lock *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, struct hif_pm_runtime_lock *data) +{ + struct ol_softc *sc = (struct ol_softc *)ol_sc; + struct hif_pci_softc *hif_sc = sc->hif_sc; + struct hif_pm_runtime_lock *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 + * @lock: which lock is being acquired + * @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, + struct hif_pm_runtime_lock *lock, 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_lock *context = lock; + + if (cds_is_load_unload_in_progress()) { + HIF_ERROR("%s: Load/unload in progress, ignore!", + __func__); + return -EINVAL; + } + + if (cds_is_logp_in_progress()) { + HIF_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); + + HIF_ERROR("%s: pm_state: %d delay: %dms ret: %d\n", __func__, + cdf_atomic_read(&hif_sc->pm_state), delay, ret); + + return ret; +} + +/** + * hif_runtime_lock_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 * + */ +struct hif_pm_runtime_lock *hif_runtime_lock_init(const char *name) +{ + struct hif_pm_runtime_lock *context; + + context = cdf_mem_malloc(sizeof(*context)); + if (!context) { + HIF_ERROR("%s: No memory for Runtime PM wakelock context\n", + __func__); + return NULL; + } + + context->name = name ? name : "Default"; + return context; +} + +/** + * hif_runtime_lock_deinit() - This API frees the runtime pm ctx + * @data: Runtime PM context + * + * Return: void + */ +void hif_runtime_lock_deinit(struct hif_pm_runtime_lock *data) +{ + unsigned long flags; + struct hif_pm_runtime_lock *context = data; + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + 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); + + cdf_mem_free(context); +} + +#endif /* FEATURE_RUNTIME_PM */ diff --git a/core/hif/src/pcie/if_pci.h b/core/hif/src/pcie/if_pci.h index d49c53e671d4..b0d465149367 100644 --- a/core/hif/src/pcie/if_pci.h +++ b/core/hif/src/pcie/if_pci.h @@ -173,4 +173,59 @@ void hif_pci_cancel_deferred_target_sleep(struct ol_softc *scn); #endif #define HIF_CE_DRAIN_WAIT_CNT 20 + + +#ifdef FEATURE_RUNTIME_PM +#include + +#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 */ +#endif /* FEATURE_RUNTIME_PM */ #endif /* __ATH_PCI_H__ */ -- cgit v1.2.3 From d2d9bd96b7c538d71c9eb7b42b6f5dd7c8847727 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 2 Nov 2015 14:29:35 -0800 Subject: qcacld-3.0: Provide cdf apis for runtime suspend Provide apis to allow and prevent runtime suspend. Change-Id: I7604659d257823f436ff370715f421d58ce25d3a CRs-Fixed: 935300 --- core/cdf/inc/cdf_lock.h | 12 +++- core/cdf/src/cdf_lock.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 2 deletions(-) diff --git a/core/cdf/inc/cdf_lock.h b/core/cdf/inc/cdf_lock.h index 82fd160959c3..83a5c4164e01 100644 --- a/core/cdf/inc/cdf_lock.h +++ b/core/cdf/inc/cdf_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -262,6 +262,16 @@ CDF_STATUS cdf_wake_lock_release(cdf_wake_lock_t *pLock, uint32_t reason); */ CDF_STATUS cdf_wake_lock_destroy(cdf_wake_lock_t *pLock); +struct hif_pm_runtime_lock; +typedef struct hif_pm_runtime_lock *cdf_runtime_lock_t; + +CDF_STATUS cdf_runtime_pm_get(void); +CDF_STATUS cdf_runtime_pm_put(void); +CDF_STATUS cdf_runtime_pm_prevent_suspend(cdf_runtime_lock_t lock); +CDF_STATUS cdf_runtime_pm_allow_suspend(cdf_runtime_lock_t lock); +cdf_runtime_lock_t cdf_runtime_lock_init(const char *name); +void cdf_runtime_lock_deinit(cdf_runtime_lock_t lock); + /** * cdf_spinlock_acquire() - acquires a spin lock * @lock: Spin lock to acquire diff --git a/core/cdf/src/cdf_lock.c b/core/cdf/src/cdf_lock.c index 283cd510cd05..b57363327a92 100644 --- a/core/cdf/src/cdf_lock.c +++ b/core/cdf/src/cdf_lock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -46,6 +46,7 @@ #include "i_host_diag_core_event.h" #include "cds_api.h" #include "ani_global.h" +#include "hif.h" /* Preprocessor Definitions and Constants */ #define LINUX_LOCK_COOKIE 0x12345678 @@ -489,3 +490,158 @@ CDF_STATUS cdf_wake_lock_destroy(cdf_wake_lock_t *pLock) #endif return CDF_STATUS_SUCCESS; } + +/** + * cdf_runtime_pm_get() - do a get opperation on the device + * + * A get opperation will prevent a runtime suspend untill a + * corresponding put is done. This api should be used when sending + * data. + * + * CONTRARY TO THE REGULAR RUNTIME PM, WHEN THE BUS IS SUSPENDED, + * THIS API WILL ONLY REQUEST THE RESUME AND NOT TO A GET!!! + * + * return: success if the bus is up and a get has been issued + * otherwise an error code. + */ +CDF_STATUS cdf_runtime_pm_get(void) +{ + void *ol_sc; + int ret; + + ol_sc = cds_get_context(CDF_MODULE_ID_HIF); + + if (ol_sc == NULL) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return CDF_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_get(ol_sc); + + if (ret) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_runtime_pm_put() - do a put opperation on the device + * + * A put opperation will allow a runtime suspend after a corresponding + * get was done. This api should be used when sending data. + * + * This api will return a failure if the hif module hasn't been initialized + * + * return: CDF_STATUS_SUCCESS if the put is performed + */ +CDF_STATUS cdf_runtime_pm_put(void) +{ + void *ol_sc; + int ret; + + ol_sc = cds_get_context(CDF_MODULE_ID_HIF); + + if (ol_sc == NULL) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return CDF_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_put(ol_sc); + + if (ret) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend + * @lock: an opaque context for tracking + * + * The lock can only be acquired once per lock context and is tracked. + * + * return: CDF_STATUS_SUCCESS or failure code. + */ +CDF_STATUS cdf_runtime_pm_prevent_suspend(cdf_runtime_lock_t lock) +{ + void *ol_sc; + int ret; + + ol_sc = cds_get_context(CDF_MODULE_ID_HIF); + + if (ol_sc == NULL) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return CDF_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_prevent_suspend(ol_sc, lock); + + if (ret) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_runtime_pm_prevent_suspend() - prevent a runtime bus suspend + * @lock: an opaque context for tracking + * + * The lock can only be acquired once per lock context and is tracked. + * + * return: CDF_STATUS_SUCCESS or failure code. + */ +CDF_STATUS cdf_runtime_pm_allow_suspend(cdf_runtime_lock_t lock) +{ + void *ol_sc; + int ret; + + ol_sc = cds_get_context(CDF_MODULE_ID_HIF); + + if (ol_sc == NULL) { + CDF_ASSERT(0); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: HIF context is null!", __func__); + return CDF_STATUS_E_INVAL; + } + + ret = hif_pm_runtime_allow_suspend(ol_sc, lock); + + if (ret) + return CDF_STATUS_E_FAILURE; + + return CDF_STATUS_SUCCESS; +} + +/** + * cdf_runtime_lock_init() - initialize runtime lock + * @name: name of the runtime lock + * + * Initialize a runtime pm lock. This lock can be used + * to prevent the runtime pm system from putting the bus + * to sleep. + * + * Return: runtime_pm_lock_t + */ +cdf_runtime_lock_t cdf_runtime_lock_init(const char *name) +{ + return hif_runtime_lock_init(name); +} + +/** + * cdf_runtime_lock_deinit() - deinitialize runtime pm lock + * @lock: the lock to deinitialize + * + * Ensures the lock is released. Frees the runtime lock. + * + * Return: void + */ +void cdf_runtime_lock_deinit(cdf_runtime_lock_t lock) +{ + hif_runtime_lock_deinit(lock); +} -- cgit v1.2.3 From dbfb7ad84d1c70aee7cd3af20144981240184740 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:45:19 -0800 Subject: qcacld-3.0: Introduce cdf_suspend_type Introduce an enum for use by multiple layers to suspend slightly differently when doing a runtime suspend versus a system suspend. Change-Id: I753bbe909e53558fe592defdca021331ec6feb88 CRs-Fixed: 935300 --- core/cdf/inc/cdf_types.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/cdf/inc/cdf_types.h b/core/cdf/inc/cdf_types.h index cef5fe4e5a59..cdc16edb8125 100644 --- a/core/cdf/inc/cdf_types.h +++ b/core/cdf/inc/cdf_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -508,4 +508,14 @@ struct cdf_tso_info_t { */ #define CDF_CE_TX_PKT_OFFSET_BIT_M 0x0fff0000 +/** + * enum cdf_suspend_type - type of suspend + * CDF_SYSTEM_SUSPEND: System suspend triggered wlan suspend + * CDF_RUNTIME_SUSPEND: Runtime pm inactivity timer triggered wlan suspend + */ +enum cdf_suspend_type { + CDF_SYSTEM_SUSPEND, + CDF_RUNTIME_SUSPEND +}; + #endif /* if !defined __CDF_TYPES_H */ -- cgit v1.2.3 From 1688fba972be071f03a2dc5d108e42f0478d4b7e Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:47:27 -0800 Subject: qcacld-3.0: Provide hif runtime suspend resume apis hif runtime suspend resume is identical to a regular bus suspend resume, but provide a different api just in case this changes. Change-Id: If069df7733d6a1ebe38d356ac5bdd4e2a250118b CRs-Fixed: 935300 --- core/hif/inc/hif.h | 2 ++ core/hif/src/pcie/if_pci.c | 28 +++++++++++++++++++++++++--- core/hif/src/snoc/if_snoc.c | 20 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index de926ef998b1..40950c31f031 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -684,6 +684,8 @@ void hif_runtime_pm_set_state_inprogress(void); void hif_runtime_pm_set_state_on(void); void hif_enable_power_management(void *hif_ctx); +int hif_runtime_suspend(void); +int hif_runtime_resume(void); int hif_bus_resume(void); int hif_bus_suspend(void); void hif_vote_link_down(void); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 09e06f15fa30..a70811e7e052 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1797,9 +1797,10 @@ static int hif_bus_resume_link_down(void) /** * hif_bus_suspend(): prepare hif for suspend + * * chose suspend type based on link suspend voting. * - * Return: linux status + * Return: 0 for success and non-zero error code for failure */ int hif_bus_suspend(void) { @@ -1810,10 +1811,11 @@ int hif_bus_suspend(void) } /** - * hif_bus_suspend(): prepare hif for suspend + * hif_bus_resume(): prepare hif for resume + * * chose suspend type based on link suspend voting. * - * Return: linux status + * Return: 0 for success and non-zero error code for failure */ int hif_bus_resume(void) { @@ -1881,6 +1883,26 @@ void hif_runtime_pm_set_state_suspended(void) __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_SUSPENDED); } +/** + * hif_runtime_suspend() - do the bus suspend part of a runtime suspend + * + * Return: 0 for success and non-zero error code for failure + */ +int hif_runtime_suspend(void) +{ + return hif_bus_suspend(); +} + +/** + * hif_runtime_resume() - do the bus resume part of a runtime resume + * + * Return: 0 for success and non-zero error code for failure + */ +int hif_runtime_resume(void) +{ + return hif_bus_resume(); +} + void hif_disable_isr(void *ol_sc) { struct ol_softc *scn = (struct ol_softc *)ol_sc; diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index c5f248d8f847..c9dfa8c96d20 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -141,6 +141,15 @@ void hif_runtime_pm_set_state_on(void) { } +/** + * hif_runtime_pm_set_state_suspended() - dummy function + * + * currently runtime pm only supported in pci + */ +void hif_runtime_pm_set_state_suspended(void) +{ +} + /** * hif_bus_suspend() - suspend the bus * @@ -167,6 +176,17 @@ int hif_bus_resume(void) return 0; } +static int hif_runtime_suspend(void) +{ + return hif_bus_suspend(); +} + +static int hif_runtime_resume(void) +{ + return hif_bus_resume(); +} + + /** * hif_enable_power_gating(): enable HW power gating * -- cgit v1.2.3 From 0c83a5b04c5c79f7006ec30268551b3058a5ac3c Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:52:05 -0800 Subject: qcacld-3.0: Provide wma runtime suspend resume apis wma has to do some extra steps that were part of 802.11 suspend for runtime suspend. Change-Id: I91fbdcacd6c557f30e0d4f422324f2db67cb96dc CRs-Fixed: 935300 --- core/mac/src/include/sir_params.h | 6 +- core/wma/inc/wma.h | 1 + core/wma/inc/wma_api.h | 6 +- core/wma/inc/wma_internal.h | 6 +- core/wma/inc/wma_types.h | 3 + core/wma/src/wma_features.c | 216 +++++++++++++++++++++++++++++++++----- core/wma/src/wma_main.c | 22 +++- 7 files changed, 228 insertions(+), 32 deletions(-) diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 6a4a485a195e..ff6f339154e8 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -580,6 +580,10 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_ENABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237) #define SIR_HAL_DISABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238) #define SIR_HAL_GATEWAY_PARAM_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239) + +#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) + #define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313) #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) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 03486b165a37..bf14268e7abf 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1197,6 +1197,7 @@ typedef struct { cdf_event_t wma_ready_event; cdf_event_t wma_resume_event; cdf_event_t target_suspend; + cdf_event_t runtime_suspend; cdf_event_t recovery_event; uint16_t max_station; uint16_t max_bssid; diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index f04500e45ee2..a0d73deec6a7 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -117,6 +117,8 @@ CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx, uint8_t *pVersion, uint32_t versionBufferSize); +int wma_runtime_suspend(void); +int wma_runtime_resume(void); int wma_bus_suspend(void); int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); void wma_target_suspend_acknowledge(void *context); @@ -124,7 +126,7 @@ int wma_bus_resume(void); int wma_resume_target(WMA_HANDLE handle); CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle); -int wma_is_wow_mode_selected(WMA_HANDLE handle); +bool wma_is_wow_mode_selected(WMA_HANDLE handle); CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle); bool wma_check_scan_in_progress(WMA_HANDLE handle); diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 8ef008c7956b..ea192525f642 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -981,7 +981,7 @@ static inline int wma_get_wow_bus_suspend(tp_wma_handle wma) return cdf_atomic_read(&wma->is_wow_bus_suspended); } -CDF_STATUS wma_resume_req(tp_wma_handle wma); +CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type); CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, struct wow_add_pattern *ptrn); @@ -993,7 +993,9 @@ CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info); CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info); -CDF_STATUS wma_suspend_req(tp_wma_handle wma); +CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type); +void wma_calculate_and_update_conn_state(tp_wma_handle wma); +void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask); void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask); void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 0a6428a6e36c..9460d5f0fcc4 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -262,6 +262,9 @@ #define WMA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ #define WMA_MSG_TYPES_END SIR_HAL_MSG_TYPES_END +#define WMA_RUNTIME_PM_SUSPEND_IND SIR_HAL_RUNTIME_PM_SUSPEND_IND +#define WMA_RUNTIME_PM_RESUME_IND SIR_HAL_RUNTIME_PM_RESUME_IND + #ifdef WLAN_FEATURE_VOWIFI_11R #define WMA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ #define WMA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 541b7eb3dc49..c97fccc7dcd1 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3632,17 +3632,20 @@ error: /** * wma_resume_req() - clear configured wow patterns in fw * @wma: wma handle + * @type: type of suspend * * Return: CDF status */ -CDF_STATUS wma_resume_req(tp_wma_handle wma) +CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type) { - wma->no_of_resume_ind++; + if (type == CDF_SYSTEM_SUSPEND) { + wma->no_of_resume_ind++; - if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) - return CDF_STATUS_SUCCESS; + if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) + return CDF_STATUS_SUCCESS; - wma->no_of_resume_ind = 0; + wma->no_of_resume_ind = 0; + } /* Reset the DTIM Parameters */ wma_set_resume_dtim(wma); @@ -3887,6 +3890,23 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) return CDF_STATUS_SUCCESS; } +/** + * wma_calculate_and_update_conn_state(): calculate each interfaces conn state + * @wma: validated wma handle + * + * Identifies any vdev that is up and not in ap mode as connected. + * stores this in the interfaces conn_state varible. + */ +void wma_calculate_and_update_conn_state(tp_wma_handle wma) +{ + int i; + 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)); + } +} + /** * wma_update_conn_state(): synchronize wma & hdd * @wma: wma handle @@ -4131,14 +4151,26 @@ void wma_apply_lphb(tp_wma_handle wma) void wma_apply_lphb(tp_wma_handle wma) {} #endif /* FEATURE_WLAN_LPHB */ +static void wma_notify_suspend_req_procesed(tp_wma_handle wma, + enum cdf_suspend_type type) +{ + if (type == CDF_SYSTEM_SUSPEND) + wma_send_status_to_suspend_ind(wma, true); + else if (type == CDF_RUNTIME_SUSPEND) + cdf_event_set(&wma->runtime_suspend); +} + /** * wma_suspend_req() - Handles suspend indication request received from umac. * @wma: wma handle - * @info: suspend params + * @type: type of suspend + * + * The type controlls how we notify the indicator that the indication has + * been processed * * Return: CDF status */ -CDF_STATUS wma_suspend_req(tp_wma_handle wma) +CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type) { if (wma_is_wow_applicable(wma)) { WMA_LOGE("WOW Suspend"); @@ -4152,7 +4184,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma) /* Set the Suspend DTIM Parameters */ wma_set_suspend_dtim(wma); - wma_send_status_to_suspend_ind(wma, true); + + wma_notify_suspend_req_procesed(wma, type); /* to handle race between hif_pci_suspend and * unpause/pause tx handler @@ -4333,7 +4366,7 @@ bool static wma_is_nan_enabled(tp_wma_handle wma) * * Return: true is wow mode is needed else false */ -int wma_is_wow_mode_selected(WMA_HANDLE handle) +bool wma_is_wow_mode_selected(WMA_HANDLE handle) { tp_wma_handle wma = (tp_wma_handle) handle; @@ -6256,13 +6289,69 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, } /** - * wma_bus_suspend() - handles bus suspend request from hdd + * wma_post_runtime_resume_msg() - post the resume request + * @handle: validated wma handle * - * Calls the appropriate handler based on configuration and event + * request the MC thread unpaus the vdev and set resume dtim + * + * Return: cdf status of the mq post + */ +static CDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle) +{ + cds_msg_t resume_msg; + + resume_msg.bodyptr = NULL; + resume_msg.type = WMA_RUNTIME_PM_RESUME_IND; + return cds_mq_post_message(CDF_MODULE_ID_WMA, &resume_msg); +} + +/** + * wma_post_runtime_suspend_msg() - post the suspend request + * @handle: validated wma handle + * + * Requests for offloads to be configured for runtime suspend + * on the MC thread + * + * Return CDF_STATUS_E_AGAIN in case of timeout or CDF_STATUS_SUCCESS + */ +static CDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle) +{ + cds_msg_t cds_msg; + CDF_STATUS cdf_status; + tp_wma_handle wma = (tp_wma_handle) handle; + + cdf_event_reset(&wma->runtime_suspend); + + cds_msg.bodyptr = NULL; + cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND; + cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_msg); + + if (cdf_status != CDF_STATUS_SUCCESS) + goto failure; + + if (cdf_wait_single_event(&wma->runtime_suspend, + WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) != + CDF_STATUS_SUCCESS) { + WMA_LOGE("Failed to get runtime suspend event"); + goto failure; + } + + return CDF_STATUS_SUCCESS; + +failure: + return CDF_STATUS_E_AGAIN; +} + +/** + * __wma_bus_suspend(): handles bus suspend for wma + * @type: is this suspend part of runtime suspend or system suspend? + * + * Bails if a scan is in progress. + * Calls the appropriate handlers based on configuration and event. * * Return: 0 for success or error code */ -int wma_bus_suspend(void) +static int __wma_bus_suspend(enum cdf_suspend_type type) { WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); if (NULL == handle) { @@ -6270,20 +6359,104 @@ int wma_bus_suspend(void) return -EFAULT; } - WMA_LOGE("%s: wow mode selected %d", __func__, - wma_is_wow_mode_selected(handle)); - if (wma_check_scan_in_progress(handle)) { WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__); return -EBUSY; } - if (wma_is_wow_mode_selected(handle)) - return cdf_status_to_os_return(wma_enable_wow_in_fw(handle)); + if (type == CDF_RUNTIME_SUSPEND) { + CDF_STATUS status = wma_post_runtime_suspend_msg(handle); + if (status) + return cdf_status_to_os_return(status); + } + + if (type == CDF_SYSTEM_SUSPEND) + WMA_LOGE("%s: wow mode selected %d", __func__, + wma_is_wow_mode_selected(handle)); + + if (wma_is_wow_mode_selected(handle)) { + CDF_STATUS status = wma_enable_wow_in_fw(handle); + return cdf_status_to_os_return(status); + } return wma_suspend_target(handle, 0); } +/** + * wma_runtime_suspend() - handles runtime suspend request from hdd + * + * Calls the appropriate handler based on configuration and event. + * Last busy marking should prevent race conditions between processing + * of asyncronous fw events and the running of runtime suspend. + * (eg. last busy marking should guarantee that any auth requests have + * been processed) + * Events comming from the host are not protected, but aren't expected + * to be an issue. + * + * Return: 0 for success or error code + */ +int wma_runtime_suspend(void) +{ + return __wma_bus_suspend(CDF_RUNTIME_SUSPEND); +} + +/** + * wma_bus_suspend() - handles bus suspend request from hdd + * + * Calls the appropriate handler based on configuration and event + * + * Return: 0 for success or error code + */ +int wma_bus_suspend(void) +{ + + return __wma_bus_suspend(CDF_RUNTIME_SUSPEND); +} + +/** + * __wma_bus_resume() - bus resume for wma + * + * does the part of the bus resume common to bus and system suspend + * + * Return: os error code. + */ +int __wma_bus_resume(WMA_HANDLE handle) +{ + bool wow_mode = wma_is_wow_mode_selected(handle); + CDF_STATUS status; + + WMA_LOGE("%s: wow mode %d", __func__, wow_mode); + + if (!wow_mode) + return wma_resume_target(handle); + + status = wma_disable_wow_in_fw(handle); + return cdf_status_to_os_return(status); +} + +/** + * wma_runtime_resume() - do the runtime resume operation for wma + * + * Return: os error code. + */ +int wma_runtime_resume(void) +{ + int ret; + CDF_STATUS status; + WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); + if (NULL == handle) { + WMA_LOGE("%s: wma context is NULL", __func__); + return -EFAULT; + } + + ret = __wma_bus_resume(handle); + if (ret) + return ret; + + status = wma_post_runtime_resume_msg(handle); + return cdf_status_to_os_return(status); +} + /** * wma_bus_resume() - handles bus resume request from hdd * @handle: valid wma handle @@ -6295,19 +6468,12 @@ int wma_bus_suspend(void) int wma_bus_resume(void) { WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); - int wow_mode; if (NULL == handle) { WMA_LOGE("%s: wma context is NULL", __func__); return -EFAULT; } - wow_mode = wma_is_wow_mode_selected(handle); - WMA_LOGE("%s: wow mode %d", __func__, wow_mode); - - if (!wow_mode) - return wma_resume_target(handle); - - return cdf_status_to_os_return(wma_disable_wow_in_fw(handle)); + return __wma_bus_resume(handle); } /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 935db34862a6..815fbd9c964c 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1766,6 +1766,13 @@ CDF_STATUS wma_open(void *cds_context, goto err_event_init; } + cdf_status = cdf_event_init(&wma_handle->runtime_suspend); + if (cdf_status != CDF_STATUS_SUCCESS) { + WMA_LOGP("%s: runtime_suspend event initialization failed", + __func__); + goto err_event_init; + } + cdf_status = cdf_event_init(&wma_handle->recovery_event); if (cdf_status != CDF_STATUS_SUCCESS) { WMA_LOGP("%s: recovery event initialization failed", __func__); @@ -3083,6 +3090,7 @@ CDF_STATUS wma_close(void *cds_ctx) cdf_event_destroy(&wma_handle->target_suspend); cdf_event_destroy(&wma_handle->wma_resume_event); + cdf_event_destroy(&wma_handle->runtime_suspend); cdf_event_destroy(&wma_handle->recovery_event); wma_cleanup_vdev_resp(wma_handle); wma_cleanup_hold_req(wma_handle); @@ -4874,9 +4882,19 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) case WMA_WOWL_EXIT_REQ: wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); break; + + case WMA_RUNTIME_PM_SUSPEND_IND: + wma_calculate_and_update_conn_state(wma_handle); + wma_suspend_req(wma_handle, CDF_RUNTIME_SUSPEND); + break; + + case WMA_RUNTIME_PM_RESUME_IND: + wma_resume_req(wma_handle, CDF_RUNTIME_SUSPEND); + break; + case WMA_WLAN_SUSPEND_IND: wma_update_conn_state(wma_handle, msg->bodyval); - wma_suspend_req(wma_handle); + wma_suspend_req(wma_handle, CDF_SYSTEM_SUSPEND); break; case WMA_8023_MULTICAST_LIST_REQ: wma_process_mcbc_set_filter_req(wma_handle, @@ -5015,7 +5033,7 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) cdf_mem_free(msg->bodyptr); break; case WMA_WLAN_RESUME_REQ: - wma_resume_req(wma_handle); + wma_resume_req(wma_handle, CDF_SYSTEM_SUSPEND); break; #ifdef WLAN_FEATURE_STATS_EXT -- cgit v1.2.3 From 466cb5b6195ad715df3d7cec4a732faa37a1b575 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:49:12 -0800 Subject: qcacld-3.0: Coordinate runtime suspend from hdd HDD interfaces with the platform driver. Runtime suspend is a callback registered with the platform driver. Coordinate runtime suspend from hdd since it is both the logical entry point and knows what other layers need to participate in a runtime suspend. Change-Id: I80b71e504d0cd31bd5a8e47895db7e0bd233f6c3 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 153 +++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 39cd2111e883..dc9d1ea26a27 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -43,6 +43,7 @@ #include "cds_sched.h" #include "osdep.h" #include "hif.h" +#include "htc.h" #include "epping_main.h" #include "wlan_hdd_main.h" #include "wlan_hdd_power.h" @@ -524,6 +525,120 @@ static int wlan_hdd_bus_resume(void) return ret; } +#ifdef FEATURE_RUNTIME_PM + +/** + * __wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend + * + * Each layer is responsible for its own suspend actions. wma_runtime_suspend + * takes care of the parts of the 802.11 suspend that we want to do for runtime + * suspend. + * + * Return: 0 or errno + */ +static int __wlan_hdd_runtime_suspend(void) +{ + void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + int status = wlan_hdd_validate_context(hdd_ctx); + + if (0 != status) + return status; + + if (!hif_can_suspend_link()) { + hdd_err("Runtime PM not supported for link up suspend"); + return -EINVAL; + } + + hif_runtime_pm_set_state_inprogress(); + status = htc_runtime_suspend(); + if (status) + goto set_state; + + status = wma_runtime_suspend(); + if (status) + goto resume_htc; + + status = hif_runtime_suspend(); + if (status) + goto resume_wma; + + status = cnss_auto_suspend(); + if (status) + goto resume_hif; + + hif_runtime_pm_set_state_suspended(); + return status; + +resume_hif: + CDF_BUG(!hif_runtime_resume()); +resume_wma: + CDF_BUG(!wma_runtime_resume()); +resume_htc: + CDF_BUG(!htc_runtime_resume()); +set_state: + hif_runtime_pm_set_state_on(); + return status; +} + + +/** + * wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend + * + * This function is called by the platform driver to suspend the + * wlan bus separately from system suspend + * + * Return: 0 or errno + */ +static int wlan_hdd_runtime_suspend(void) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_runtime_suspend(); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend + * + * Sets the runtime pm state and coordinates resume between hif wma and + * ol_txrx. + * + * Return: success since failure is a bug + */ +static int __wlan_hdd_runtime_resume(void) +{ + hif_runtime_pm_set_state_inprogress(); + CDF_BUG(!cnss_auto_resume()); + CDF_BUG(!hif_runtime_resume()); + CDF_BUG(!wma_runtime_resume()); + CDF_BUG(!htc_runtime_resume()); + hif_runtime_pm_set_state_on(); + return 0; +} + +/** + * wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend + * + * This function is called by the platform driver to resume the + * wlan bus separately from system suspend + * + * Return: success since failure is a bug + */ +static int wlan_hdd_runtime_resume(void) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_runtime_resume(); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + #ifdef HIF_PCI /** * wlan_hdd_pci_probe() - probe callback for pci platform driver @@ -618,6 +733,32 @@ static int wlan_hdd_pci_resume(struct pci_dev *pdev) { return wlan_hdd_bus_resume(); } + +#ifdef FEATURE_RUNTIME_PM +/** + * wlan_hdd_pci_runtime_suspend() - wlan_hdd_pci_suspend + * @pdev: pdev + * @state: state + * + * Return: success or errno + */ +static int wlan_hdd_pci_runtime_suspend(struct pci_dev *pdev) +{ + return wlan_hdd_runtime_suspend(); +} + +/** + * wlan_hdd_pci_runtime_resume() - runtime resume callback to register with pci + * @pdev: pci device id + * + * Return: success or errno + */ +static int wlan_hdd_pci_runtime_resume(struct pci_dev *pdev) +{ + return wlan_hdd_runtime_resume(); +} +#endif + #else /** * wlan_hdd_snoc_probe() - wlan_hdd_snoc_probe @@ -709,6 +850,14 @@ static struct pci_device_id wlan_hdd_pci_id_table[] = { }; #ifdef CONFIG_CNSS + +#ifdef FEATURE_RUNTIME_PM +struct cnss_wlan_runtime_ops runtime_pm_ops = { + .runtime_suspend = wlan_hdd_pci_runtime_suspend, + .runtime_resume = wlan_hdd_pci_runtime_resume, +}; +#endif + struct cnss_wlan_driver wlan_drv_ops = { .name = "wlan_hdd_pci", .id_table = wlan_hdd_pci_id_table, @@ -722,6 +871,9 @@ struct cnss_wlan_driver wlan_drv_ops = { .suspend = wlan_hdd_pci_suspend, .resume = wlan_hdd_pci_resume, #endif /* ATH_BUS_PM */ +#ifdef FEATURE_RUNTIME_PM + .runtime_ops = &runtime_pm_ops, +#endif }; #else MODULE_DEVICE_TABLE(pci, wlan_hdd_pci_id_table); @@ -734,6 +886,7 @@ struct pci_driver wlan_drv_ops = { .suspend = wlan_hdd_pci_suspend, .resume = wlan_hdd_pci_resume, #endif /* ATH_BUS_PM */ + }; #endif /* CONFIG_CNSS */ #else -- cgit v1.2.3 From c5141b0f983911c2fcb870a2ab68c4a9750af1b7 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 18 Nov 2015 02:36:30 -0800 Subject: qcacld-3.0: Runtime PM handling for htc messages Check runtime pm status while sending messages. Update runtime pm when sending messages to hif. Update runtime pm when messages are tx completed. Change-Id: I27840f57ff87d6d27b1e3611e7fe1f2cd933ddd0 CRs-Fixed: 935300 --- core/dp/txrx/ol_tx_send.c | 3 +- core/htc/htc_packet.h | 19 +++++-- core/htc/htc_send.c | 132 ++++++++++++++++++++++++++++++++++++++++---- core/wma/src/wma_features.c | 5 ++ core/wmi/wmi_unified.c | 61 +++++++++++++++++++- core/wmi/wmi_unified_api.h | 21 ++++++- core/wmi/wmi_unified_priv.h | 7 ++- 7 files changed, 226 insertions(+), 22 deletions(-) diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index f6dc650cb837..bc762694cecf 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -504,6 +504,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, tx_desc->status = status; netbuf = tx_desc->netbuf; + cdf_runtime_pm_put(); cdf_nbuf_trace_update(netbuf, trace_str); /* Per SDU update of byte count */ byte_cnt += cdf_nbuf_len(netbuf); diff --git a/core/htc/htc_packet.h b/core/htc/htc_packet.h index 34707e5c6e8a..ea0d75f0cafb 100644 --- a/core/htc/htc_packet.h +++ b/core/htc/htc_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -61,10 +61,19 @@ typedef struct _HTC_TX_PACKET_INFO { 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 */ +/** + * HTC_TX_PACKET_TAG_XXX - #defines for tagging packets for special handling + * HTC_TX_PACKET_TAG_ALL: zero is reserved and used to flush ALL packets + * HTC_TX_PACKET_TAG_INTERNAL: internal tags start here + * HTC_TX_PACKET_TAG_USER_DEFINED: user-defined tags start here + * HTC_TX_PACKET_TAG_BUNDLED: indicate this is a bundled tx packet + * HTC_TX_PACKET_TAG_AUTO_PM: indicate a power management wmi command + */ +#define HTC_TX_PACKET_TAG_ALL 0 +#define HTC_TX_PACKET_TAG_INTERNAL 1 +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) +#define HTC_TX_PACKET_TAG_BUNDLED (HTC_TX_PACKET_TAG_USER_DEFINED + 1) +#define HTC_TX_PACKET_TAG_AUTO_PM (HTC_TX_PACKET_TAG_USER_DEFINED + 2) #define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0) diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index 99c626b192d3..3b3d3c7265f9 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -597,6 +597,60 @@ static A_STATUS htc_issue_packets(HTC_TARGET *target, return status; } +#ifdef FEATURE_RUNTIME_PM +/** + * extract_htc_pm_packtes(): move pm packets from endpoint into queue + * @endpoint: which enpoint to extract packets from + * @queue: a queue to store extracted packets in. + * + * remove pm packets from the endpoint's tx queue. + * queue them into a queue + */ +static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{ + HTC_PACKET *packet; + + /* only WMI endpoint has power management packets */ + if (endpoint->service_id != WMI_CONTROL_SVC) + return; + + ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet, + HTC_PACKET, ListLink) { + if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) { + HTC_PACKET_REMOVE(&endpoint->TxQueue, packet); + HTC_PACKET_ENQUEUE(queue, packet); + } + } ITERATE_END +} + +/** + * queue_htc_pm_packets(): queue pm packets with priority + * @endpoint: enpoint to queue packets to + * @queue: queue of pm packets to enque + * + * suspend resume packets get special treatment & priority. + * need to queue them at the front of the queue. + */ +static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{ + if (endpoint->service_id != WMI_CONTROL_SVC) + return; + + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue); +} +#else +static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{} + +static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{} +#endif + + /* get HTC send packets from the TX queue on an endpoint, based on available credits */ void get_htc_send_packets_credit_based(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, @@ -607,24 +661,43 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, A_UINT8 sendFlags; HTC_PACKET *pPacket; unsigned int transferLength; + HTC_PACKET_QUEUE *tx_queue; + HTC_PACKET_QUEUE pm_queue; + bool do_pm_get = false; /****** NOTE : the TX lock is held when this function is called *****************/ - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+get_htc_send_packets_credit_based \n")); + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+get_htc_send_packets_credit_based\n")); + + INIT_HTC_PACKET_QUEUE(&pm_queue); + extract_htc_pm_packets(pEndpoint, &pm_queue); + if (HTC_QUEUE_EMPTY(&pm_queue)) { + tx_queue = &pEndpoint->TxQueue; + do_pm_get = true; + } else { + tx_queue = &pm_queue; + } /* loop until we can grab as many packets out of the queue as we can */ while (true) { + if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) { + /* bus suspended, runtime resume issued */ + CDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); + break; + } sendFlags = 0; /* get packet at head, but don't remove it */ - pPacket = htc_get_pkt_at_head(&pEndpoint->TxQueue); + pPacket = htc_get_pkt_at_head(tx_queue); if (pPacket == NULL) { + if (do_pm_get) + 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(&pEndpoint->TxQueue))); + HTC_PACKET_QUEUE_DEPTH(tx_queue))); transferLength = pPacket->ActualLength + HTC_HDR_LENGTH; @@ -676,6 +749,8 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, pEndpoint->TxCredits, creditsRequired)); #endif + if (do_pm_get) + hif_pm_runtime_put(target->hif_dev); break; } @@ -694,8 +769,7 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, htc_credit_record(HTC_REQUEST_CREDIT, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH - (&pEndpoint-> - TxQueue)); + (tx_queue)); UNLOCK_HTC_CREDIT(target); } @@ -710,7 +784,7 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, } /* now we can fully dequeue */ - pPacket = htc_packet_dequeue(&pEndpoint->TxQueue); + pPacket = htc_packet_dequeue(tx_queue); if (pPacket) { /* save the number of credits this packet consumed */ pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired; @@ -722,7 +796,11 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target, } } - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets_credit_based \n")); + if (!HTC_QUEUE_EMPTY(&pm_queue)) + queue_htc_pm_packets(pEndpoint, &pm_queue); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("-get_htc_send_packets_credit_based\n")); } @@ -732,23 +810,43 @@ void get_htc_send_packets(HTC_TARGET *target, { HTC_PACKET *pPacket; + HTC_PACKET_QUEUE *tx_queue; + HTC_PACKET_QUEUE pm_queue; + bool do_pm_get; /****** NOTE : the TX lock is held when this function is called *****************/ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+get_htc_send_packets %d resources\n", Resources)); + INIT_HTC_PACKET_QUEUE(&pm_queue); + extract_htc_pm_packets(pEndpoint, &pm_queue); + if (HTC_QUEUE_EMPTY(&pm_queue)) { + tx_queue = &pEndpoint->TxQueue; + do_pm_get = true; + } else { + tx_queue = &pm_queue; + } + /* loop until we can grab as many packets out of the queue as we can */ while (Resources > 0) { int num_frags; - pPacket = htc_packet_dequeue(&pEndpoint->TxQueue); + if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) { + /* bus suspended, runtime resume issued */ + CDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); + break; + } + + pPacket = htc_packet_dequeue(tx_queue); if (pPacket == NULL) { + if (do_pm_get) + 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(&pEndpoint->TxQueue))); + HTC_PACKET_QUEUE_DEPTH(tx_queue))); /* For non-credit path the sequence number is already embedded * in the constructed HTC header */ @@ -779,7 +877,10 @@ void get_htc_send_packets(HTC_TARGET *target, Resources -= num_frags; } - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets \n")); + if (!HTC_QUEUE_EMPTY(&pm_queue)) + queue_htc_pm_packets(pEndpoint, &pm_queue); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n")); } @@ -991,9 +1092,14 @@ static HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target, /* send what we can */ result = htc_issue_packets(target, pEndpoint, &sendQueue); if (result) { + int i; AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue", result)); + + for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--) + hif_pm_runtime_put(target->hif_dev); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, &sendQueue); LOCK_HTC_TX(target); @@ -1264,6 +1370,9 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, cdf_nbuf_t netbuf, int Epid, } } + if (hif_pm_runtime_get(target->hif_dev)) + return A_ERROR; + pHtcHdr = (HTC_FRAME_HDR *) cdf_nbuf_get_frag_vaddr(netbuf, 0); AR_DEBUG_ASSERT(pHtcHdr); @@ -1609,6 +1718,9 @@ CDF_STATUS htc_tx_completion_handler(void *Context, netbuf = NULL; break; } + 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 = diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index c97fccc7dcd1..5bd515e647fe 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3654,6 +3654,8 @@ CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type) /* unpause the vdev if left paused and hif_pci_suspend fails */ wma_unpause_vdev(wma); + wmi_set_runtime_pm_inprogress(wma->wmi_handle, false); + return CDF_STATUS_SUCCESS; } @@ -4172,6 +4174,9 @@ static void wma_notify_suspend_req_procesed(tp_wma_handle wma, */ CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type) { + if (type == CDF_RUNTIME_SUSPEND) + wmi_set_runtime_pm_inprogress(wma->wmi_handle, true); + if (wma_is_wow_applicable(wma)) { WMA_LOGE("WOW Suspend"); wma_apply_lphb(wma); diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 78bc9f345961..2270e602f3d4 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -766,6 +766,30 @@ static inline void wma_log_cmd_id(WMI_CMD_ID cmd_id) } #endif +/** + * wmi_is_runtime_pm_cmd() - check if a cmd is part of the suspend resume sequence + * @cmd: command to check + * + * Return: true if the command is part of the suspend resume sequence. + */ +bool wmi_is_runtime_pm_cmd(WMI_CMD_ID cmd_id) +{ + 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: + case WMI_D0_WOW_ENABLE_DISABLE_CMDID: + return true; + + default: + return false; + } +} + /* WMI command API */ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, WMI_CMD_ID cmd_id) @@ -773,8 +797,12 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, HTC_PACKET *pkt; A_STATUS status; struct ol_softc *scn; + uint16_t htc_tag = 0; - if (cdf_atomic_read(&wmi_handle->is_target_suspended) && + if (wmi_get_runtime_pm_inprogress(wmi_handle)) { + if (wmi_is_runtime_pm_cmd(cmd_id)) + htc_tag = HTC_TX_PACKET_TAG_AUTO_PM; + } else if (cdf_atomic_read(&wmi_handle->is_target_suspended) && ((WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) && (WMI_PDEV_RESUME_CMDID != cmd_id))) { pr_err("%s: Target is suspended could not send WMI command\n", @@ -830,7 +858,7 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, NULL, cdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR), /* htt_host_data_dl_len(buf)+20 */ - wmi_handle->wmi_endpoint_id, 0 /*htc_tag */ ); + wmi_handle->wmi_endpoint_id, htc_tag); SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf); @@ -1160,6 +1188,21 @@ void wmi_rx_event_work(struct work_struct *work) /* WMI Initialization functions */ +#ifdef FEATURE_RUNTIME_PM +/** + * wmi_runtime_pm_init() - initialize runtime pm wmi variables + * @wmi_handle: wmi context + */ +void wmi_runtime_pm_init(struct wmi_unified *wmi_handle) +{ + cdf_atomic_init(&wmi_handle->runtime_pm_inprogress); +} +#else +void wmi_runtime_pm_init(struct wmi_unified *wmi_handle) +{ +} +#endif + void *wmi_unified_attach(ol_scn_t scn_handle, wma_process_fw_event_handler_cbk func) { @@ -1176,6 +1219,7 @@ void *wmi_unified_attach(ol_scn_t scn_handle, wmi_handle->scn_handle = scn_handle; cdf_atomic_init(&wmi_handle->pending_cmds); cdf_atomic_init(&wmi_handle->is_target_suspended); + wmi_runtime_pm_init(wmi_handle); cdf_spinlock_init(&wmi_handle->eventq_lock); cdf_nbuf_queue_init(&wmi_handle->event_queue); #ifdef CONFIG_CNSS @@ -1335,3 +1379,14 @@ void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val) cdf_atomic_set(&wmi_handle->is_target_suspended, val); } +#ifdef FEATURE_RUNTIME_PM +void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val) +{ + cdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val); +} + +inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) +{ + return cdf_atomic_read(&wmi_handle->runtime_pm_inprogress); +} +#endif diff --git a/core/wmi/wmi_unified_api.h b/core/wmi/wmi_unified_api.h index bcac971aa79e..f96c128aa19d 100644 --- a/core/wmi/wmi_unified_api.h +++ b/core/wmi/wmi_unified_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -150,7 +150,24 @@ 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_target_suspend(wmi_unified_t wmi_handle, bool val); + +#ifdef FEATURE_RUNTIME_PM +void +wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, 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, bool val) +{ + return; +} +static inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle) +{ + return false; +} +#endif + /** * WMA Callback to process fw event. diff --git a/core/wmi/wmi_unified_priv.h b/core/wmi/wmi_unified_priv.h index f0f87028530b..293480dba42c 100644 --- a/core/wmi/wmi_unified_priv.h +++ b/core/wmi/wmi_unified_priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -89,6 +89,11 @@ struct wmi_unified { #endif /*WMI_INTERFACE_EVENT_LOGGING */ cdf_atomic_t is_target_suspended; + +#ifdef FEATURE_RUNTIME_PM + cdf_atomic_t runtime_pm_inprogress; +#endif + int (*wma_process_fw_event_handler_cbk)(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf); }; -- cgit v1.2.3 From 1dd227691f0e8fbe1805c59705200de47ff64361 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 11:35:49 -0800 Subject: qcacld-3.0: Runtime puts for HTT messages HTT messages do not have a tx complete and should have their runtime puts done when the firmware response come. Tag messages without responses so that the put can be done after issuing the message. Also do runtime put in error case. Change-Id: I7253ace95ca6bb4fa17bc6d82ec52fc598d17712 CRs-Fixed: 935300 --- core/dp/htt/htt_h2t.c | 16 ++++++++++------ core/dp/htt/htt_t2h.c | 4 ++++ core/htc/htc_packet.h | 4 ++++ core/htc/htc_send.c | 7 +++++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index 59b0f06efa6c..cbfa4a7523d0 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -417,7 +417,7 @@ A_STATUS htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) cdf_nbuf_data(msg), cdf_nbuf_len(msg), pdev->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -439,6 +439,7 @@ htt_h2t_dbg_stats_get(struct htt_pdev_t *pdev, struct htt_htc_pkt *pkt; cdf_nbuf_t msg; uint32_t *msg_word; + uint16_t htc_tag = 1; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) @@ -452,6 +453,9 @@ htt_h2t_dbg_stats_get(struct htt_pdev_t *pdev, return -EINVAL; /* 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) */ @@ -503,7 +507,7 @@ htt_h2t_dbg_stats_get(struct htt_pdev_t *pdev, cdf_nbuf_data(msg), cdf_nbuf_len(msg), pdev->htc_endpoint, - 1); /* tag - not relevant here */ + htc_tag); /* tag - not relevant here */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -559,7 +563,7 @@ A_STATUS htt_h2t_sync_msg(struct htt_pdev_t *pdev, uint8_t sync_cnt) cdf_nbuf_data(msg), cdf_nbuf_len(msg), pdev->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -626,7 +630,7 @@ htt_h2t_aggr_cfg_msg(struct htt_pdev_t *pdev, cdf_nbuf_data(msg), cdf_nbuf_len(msg), pdev->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -733,7 +737,7 @@ int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) cdf_nbuf_data(msg), cdf_nbuf_len(msg), pdev->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index b4de1723a8f5..639c34506c8a 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -141,6 +141,7 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) switch (msg_type) { case HTT_T2H_MSG_TYPE_VERSION_CONF: { + cdf_runtime_pm_put(); pdev->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); pdev->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); cdf_print @@ -287,6 +288,7 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) ol_tx_single_completion_handler(pdev->txrx_pdev, compl_msg->status, compl_msg->desc_id); + cdf_runtime_pm_put(); HTT_TX_SCHED(pdev); } else { cdf_print("Ignoring HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND indication\n"); @@ -302,6 +304,7 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) cookie |= ((uint64_t) (*(msg_word + 2))) << 32; stats_info_list = (uint8_t *) (msg_word + 3); + cdf_runtime_pm_put(); ol_txrx_fw_stats_handler(pdev->txrx_pdev, cookie, stats_info_list); break; @@ -357,6 +360,7 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg) uint8_t *op_msg_buffer; uint8_t *msg_start_ptr; + cdf_runtime_pm_put(); msg_start_ptr = (uint8_t *) msg_word; op_code = HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word); diff --git a/core/htc/htc_packet.h b/core/htc/htc_packet.h index ea0d75f0cafb..ca3698f019b7 100644 --- a/core/htc/htc_packet.h +++ b/core/htc/htc_packet.h @@ -75,6 +75,10 @@ typedef struct _HTC_TX_PACKET_INFO { #define HTC_TX_PACKET_TAG_BUNDLED (HTC_TX_PACKET_TAG_USER_DEFINED + 1) #define HTC_TX_PACKET_TAG_AUTO_PM (HTC_TX_PACKET_TAG_USER_DEFINED + 2) +/* Tag packet for runtime put after sending */ +#define HTC_TX_PACKET_TAG_RUNTIME_PUT (HTC_TX_PACKET_TAG_USER_DEFINED + 3) + + #define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0) typedef struct _HTC_RX_PACKET_INFO { diff --git a/core/htc/htc_send.c b/core/htc/htc_send.c index 3b3d3c7265f9..26821fd542a4 100644 --- a/core/htc/htc_send.c +++ b/core/htc/htc_send.c @@ -577,6 +577,13 @@ static A_STATUS htc_issue_packets(HTC_TARGET *target, break; } + /* + * For HTT messages without a response from fw, + * do the runtime put here. + * otherwise runtime put will be done when the fw response comes + */ + if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) + hif_pm_runtime_put(target->hif_dev); } if (cdf_unlikely(A_FAILED(status))) { #if defined(HIF_USB) -- cgit v1.2.3 From 692cc05e93cf1823122dfa7267faae60f23804d7 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 18:42:47 -0800 Subject: qcacld-3.0: Log runtime suspend resume occurances Keep track of how many times supesend resume succeeds and fails also mark last busy on a failed runtime suspend or a successful runtime resume. Change-Id: I04df805429e3a9ce91bc3d7f27bfd598396257c9 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 8 ++++- core/hif/inc/hif.h | 7 +++++ core/hif/src/pcie/if_pci.c | 61 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index dc9d1ea26a27..ada556907c78 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -541,11 +541,14 @@ static int __wlan_hdd_runtime_suspend(void) void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); int status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) + if (0 != status) { + hif_log_runtime_suspend_failure(); return status; + } if (!hif_can_suspend_link()) { hdd_err("Runtime PM not supported for link up suspend"); + hif_log_runtime_suspend_failure(); return -EINVAL; } @@ -567,6 +570,7 @@ static int __wlan_hdd_runtime_suspend(void) goto resume_hif; hif_runtime_pm_set_state_suspended(); + hif_log_runtime_suspend_success(); return status; resume_hif: @@ -576,6 +580,7 @@ resume_wma: resume_htc: CDF_BUG(!htc_runtime_resume()); set_state: + hif_log_runtime_suspend_failure(); hif_runtime_pm_set_state_on(); return status; } @@ -615,6 +620,7 @@ static int __wlan_hdd_runtime_resume(void) CDF_BUG(!hif_runtime_resume()); CDF_BUG(!wma_runtime_resume()); CDF_BUG(!htc_runtime_resume()); + hif_log_runtime_resume_success(); hif_runtime_pm_set_state_on(); return 0; } diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 40950c31f031..ec210a91237c 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -694,6 +694,13 @@ bool hif_can_suspend_link(void); void hif_runtime_pm_set_state_inprogress(void); void hif_runtime_pm_set_state_on(void); void hif_runtime_pm_set_state_suspended(void); + +#ifdef FEATURE_RUNTIME_PM +void hif_log_runtime_suspend_success(void); +void hif_log_runtime_suspend_failure(void); +void hif_log_runtime_resume_success(void); +#endif + int dump_ce_register(struct ol_softc *scn); int ol_copy_ramdump(struct ol_softc *scn); void hif_pktlogmod_exit(void *hif_ctx); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index a70811e7e052..af05003a8025 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1883,6 +1883,67 @@ void hif_runtime_pm_set_state_suspended(void) __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_SUSPENDED); } + +#ifdef FEATURE_RUNTIME_PM +static inline struct hif_pci_softc *get_sc(void) +{ + struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); + + if (NULL == scn) { + HIF_ERROR("%s: Could not disable ASPM scn is null", + __func__); + return NULL; + } + + return scn->hif_sc; +} + +/** + * hif_log_runtime_suspend_success() - log a successful runtime suspend + */ +void hif_log_runtime_suspend_success(void) +{ + struct hif_pci_softc *sc = get_sc(); + if (sc == NULL) + return; + + sc->pm_stats.suspended++; + sc->pm_stats.suspend_jiffies = jiffies; +} + +/** + * hif_log_runtime_suspend_failure() - log a failed runtime suspend + * + * log a failed runtime suspend + * mark last busy to prevent immediate runtime suspend + */ +void hif_log_runtime_suspend_failure(void) +{ + struct hif_pci_softc *sc = get_sc(); + if (sc == NULL) + return; + + sc->pm_stats.suspend_err++; + hif_pm_runtime_mark_last_busy(sc->dev); +} + +/** + * hif_log_runtime_resume_success() - log a successful runtime resume + * + * log a successfull runtime resume + * mark last busy to prevent immediate runtime suspend + */ +void hif_log_runtime_resume_success(void) +{ + struct hif_pci_softc *sc = get_sc(); + if (sc == NULL) + return; + + sc->pm_stats.resumed++; + hif_pm_runtime_mark_last_busy(sc->dev); +} +#endif + /** * hif_runtime_suspend() - do the bus suspend part of a runtime suspend * -- cgit v1.2.3 From cceec341a3e7197f2e0f499c7d9cc9464f4ee3cf Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 11 Nov 2015 11:37:20 -0800 Subject: qcacld-3.0: Prevent runtime suspend when linkdown not allowed Runtime suspend does not save power in d0 mode. Change-Id: I6bc83923a6384c3275b95bd0ffbb4404d9a3f86d CRs-Fixed: 935300 --- core/hif/src/hif_main.c | 6 +++--- core/hif/src/hif_main.h | 4 ++-- core/hif/src/pcie/if_pci.c | 29 ++++++++++++++++++++++++++++- core/hif/src/pcie/if_pci.h | 1 + core/hif/src/snoc/if_snoc.c | 2 +- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 0c324346651e..e76c64c9a590 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -292,7 +292,7 @@ void hif_vote_link_down(void) scn->linkstate_vote--; if (scn->linkstate_vote == 0) - hif_bus_prevent_linkdown(false); + hif_bus_prevent_linkdown(scn, false); } /** @@ -313,7 +313,7 @@ void hif_vote_link_up(void) scn->linkstate_vote++; if (scn->linkstate_vote == 1) - hif_bus_prevent_linkdown(true); + hif_bus_prevent_linkdown(scn, true); } /** diff --git a/core/hif/src/hif_main.h b/core/hif/src/hif_main.h index 812b7637671e..9544ef823dae 100644 --- a/core/hif/src/hif_main.h +++ b/core/hif/src/hif_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -131,6 +131,6 @@ CDF_STATUS hif_bus_open(struct ol_softc *ol_sc, CDF_STATUS hif_enable_bus(struct ol_softc *ol_sc, struct device *dev, void *bdev, const hif_bus_id *bid, enum hif_enable_type type); void hif_disable_bus(void *bdev); -void hif_bus_prevent_linkdown(bool flag); +void hif_bus_prevent_linkdown(struct ol_softc *scn, bool flag); #endif /* __HIF_MAIN_H__ */ diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index af05003a8025..8971bb3a883c 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1068,6 +1068,8 @@ static void hif_pm_runtime_open(struct hif_pci_softc *sc) spin_lock_init(&sc->runtime_lock); cdf_atomic_init(&sc->pm_state); + sc->prevent_linkdown_lock = + hif_runtime_lock_init("linkdown suspend disabled"); cdf_atomic_set(&sc->pm_state, HIF_PM_RUNTIME_STATE_NONE); INIT_LIST_HEAD(&sc->prevent_suspend_list); } @@ -1621,6 +1623,30 @@ void hif_disable_bus(void *bdev) #define OL_ATH_PCI_PM_CONTROL 0x44 #ifdef CONFIG_CNSS + +#ifdef RUNTIME_PM +/** + * hif_runtime_prevent_linkdown() - prevent or allow a runtime pm from occuring + * @scn: hif context + * @flag: prevent linkdown if true otherwise allow + * + * this api should only be called as part of bus prevent linkdown + */ +static void hif_runtime_prevent_linkdown(struct ol_softc *scn, bool flag) +{ + struct hif_pci_softc *sc = scn->hif_sc; + + if (flag) + hif_pm_runtime_prevent_suspend(scn, sc->prevent_linkdown_lock); + else + hif_pm_runtime_allow_suspend(scn, sc->prevent_linkdown_lock); +} +#else +static void hif_runtime_prevent_linkdown(struct ol_softc *scn, bool flag) +{ +} +#endif + /** * hif_bus_prevent_linkdown(): allow or permit linkdown * @flag: true prevents linkdown, false allows @@ -1630,10 +1656,11 @@ void hif_disable_bus(void *bdev) * * Return: n/a */ -void hif_bus_prevent_linkdown(bool flag) +void hif_bus_prevent_linkdown(struct ol_softc *scn, bool flag) { HIF_ERROR("wlan: %s pcie power collapse", (flag ? "disable" : "enable")); + hif_runtime_prevent_linkdown(scn, flag); cnss_wlan_pm_control(flag); } #endif diff --git a/core/hif/src/pcie/if_pci.h b/core/hif/src/pcie/if_pci.h index b0d465149367..3c275ebf326f 100644 --- a/core/hif/src/pcie/if_pci.h +++ b/core/hif/src/pcie/if_pci.h @@ -126,6 +126,7 @@ struct hif_pci_softc { struct timer_list runtime_timer; struct list_head prevent_suspend_list; unsigned long runtime_timer_expires; + struct hif_pm_runtime_lock *prevent_linkdown_lock; #ifdef WLAN_OPEN_SOURCE struct dentry *pm_dentry; #endif diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index c9dfa8c96d20..f84b772b0d4d 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -47,7 +47,7 @@ * This is duplicated here because CONFIG_CNSS can be defined * even though it is not used for the snoc bus. */ -void hif_bus_prevent_linkdown(bool flag) +void hif_bus_prevent_linkdown(struct ol_softc *scn, bool flag) { HIF_ERROR("wlan: %s pcie power collapse ignored", (flag ? "disable" : "enable")); -- cgit v1.2.3 From 226a3b1bfee356aaa361d3cadd8c7d2abdbd1c24 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 12 Nov 2015 18:00:21 -0800 Subject: qcacld-3.0: Mark last busy in recieve for runtime pm Scan was not going through. Change-Id: I37d02a88e29da9c4fa756cc46fc812f10c58fe00 CRs-Fixed: 935300 --- core/hif/src/ce/ce_main.c | 1 + core/hif/src/pcie/if_pci.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 216ea979a094..31a64f5cbdac 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -755,6 +755,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, &hif_state->msg_callbacks_current; do { + hif_pm_runtime_mark_last_busy(scn->hif_sc->dev); cdf_nbuf_unmap_single(scn->cdf_dev, (cdf_nbuf_t) transfer_context, CDF_DMA_FROM_DEVICE); diff --git a/core/hif/src/pcie/if_pci.h b/core/hif/src/pcie/if_pci.h index 3c275ebf326f..806f91aadb8a 100644 --- a/core/hif/src/pcie/if_pci.h +++ b/core/hif/src/pcie/if_pci.h @@ -228,5 +228,7 @@ 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 +static inline void hif_pm_runtime_mark_last_busy(struct device *dev) { } #endif /* FEATURE_RUNTIME_PM */ #endif /* __ATH_PCI_H__ */ -- cgit v1.2.3 From 53b34c47142c4f7e3980b7618cefde60bf93d04b Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 18 Nov 2015 15:51:32 -0800 Subject: qcacld-3.0: Fix rmmod for runtime pm Runtime PM should be turned off before the driver is unloaded. Change-Id: I8746e92931375893708556e77a3d93bfd6266668 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 1 + core/hif/inc/hif.h | 1 + core/hif/src/pcie/if_pci.c | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index ada556907c78..77ebe6a6122a 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -314,6 +314,7 @@ static void wlan_hdd_remove(void) hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); + hif_disable_power_management(hif_ctx); hif_pktlogmod_exit(hif_ctx); if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index ec210a91237c..3ccf9d2f4a9f 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -684,6 +684,7 @@ void hif_runtime_pm_set_state_inprogress(void); void hif_runtime_pm_set_state_on(void); void hif_enable_power_management(void *hif_ctx); +void hif_disable_power_management(void *hif_ctx); int hif_runtime_suspend(void); int hif_runtime_resume(void); int hif_bus_resume(void); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 8971bb3a883c..7b90546f4c4c 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1094,6 +1094,7 @@ static void hif_pm_runtime_close(struct hif_pci_softc *sc) static void hif_pm_runtime_close(struct hif_pci_softc *sc) {} static void hif_pm_runtime_open(struct hif_pci_softc *sc) {} static void hif_pm_runtime_start(struct hif_pci_softc *sc) {} +static void hif_pm_runtime_stop(struct hif_pci_softc *sc) {} #endif /** @@ -1119,6 +1120,28 @@ void hif_enable_power_management(void *hif_ctx) hif_pm_runtime_start(pci_ctx); } +/** + * hif_disable_power_management(): disable power management + * @hif_ctx: hif context + * + * Currently disables runtime pm. Should be updated to behave + * if runtime pm is not started. Should be updated to take care + * of aspm and soc sleep for driver load. + */ +void hif_disable_power_management(void *hif_ctx) +{ + struct hif_pci_softc *pci_ctx; + + if (hif_ctx == NULL) { + HIF_ERROR("%s, hif_ctx null", __func__); + return; + } + + pci_ctx = ((struct ol_softc *)hif_ctx)->hif_sc; + + hif_pm_runtime_stop(pci_ctx); +} + #define ATH_PCI_PROBE_RETRY_MAX 3 /** * hif_bus_open(): hif_bus_open -- cgit v1.2.3 From f460785909c94e399c4f7e6f79737ff197e8ffa0 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Thu, 17 Dec 2015 17:14:40 -0800 Subject: qcacld-3.0: Instrument fastpath for runtime_pm Fastpath needs gets and puts to work with runtime_pm enabled. Change-Id: I2248d1e77c842ab12fcc10e3f29fa3ef4dd76052 CRs-Fixed: 935300 --- core/hif/inc/hif.h | 5 ++++ core/hif/src/ce/ce_main.c | 1 + core/hif/src/ce/ce_service.c | 14 ++++++++--- core/hif/src/pcie/if_pci.c | 58 +++++++++++++++++++++++++++++++++++++++++++- core/hif/src/snoc/if_snoc.c | 1 - 5 files changed, 73 insertions(+), 6 deletions(-) diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 3ccf9d2f4a9f..2deb9c831901 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -646,6 +646,7 @@ void hif_enable_power_gating(void *hif_ctx); #ifdef FEATURE_RUNTIME_PM struct hif_pm_runtime_lock; int hif_pm_runtime_get(void *hif_ctx); +void hif_pm_runtime_get_noresume(void *hif_ctx); int hif_pm_runtime_put(void *hif_ctx); struct hif_pm_runtime_lock *hif_runtime_lock_init(const char *name); void hif_runtime_lock_deinit(struct hif_pm_runtime_lock *lock); @@ -659,6 +660,10 @@ int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, struct hif_pm_runtime_lock { const char *name; }; + +static inline void hif_pm_runtime_get_noresume(void *hif_ctx) +{} + static inline int hif_pm_runtime_get(void *hif_ctx) { return 0; } static inline int hif_pm_runtime_put(void *hif_ctx) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 31a64f5cbdac..0b7d9d000e37 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -779,6 +779,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, } while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context, &CE_data, &nbytes, &transfer_id, &flags) == CDF_STATUS_SUCCESS); + } /* TBDXXX: Set CE High Watermark; invoke txResourceAvailHandler in response */ diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 0d97b4949943..0437f2d43b71 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -548,6 +548,7 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, struct CE_src_desc *shadow_src_desc = CE_SRC_RING_TO_DESC(shadow_base, write_index); + hif_pm_runtime_get_noresume(scn); msdu = msdus[i]; /* @@ -619,10 +620,15 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, /* Write the final index to h/w one-shot */ if (i) { src_ring->write_index = write_index; - /* Don't call WAR_XXX from here - * Just call XXX instead, that has the reqd. intel - */ - war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index); + + if (hif_pm_runtime_get(scn) == 0) { + /* Don't call WAR_XXX from here + * Just call XXX instead, that has the reqd. intel + */ + war_ce_src_ring_write_idx_set(scn, ctrl_addr, + write_index); + hif_pm_runtime_put(scn); + } } cdf_spin_unlock_bh(&ce_state->ce_index_lock); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 7b90546f4c4c..1425d2c1b617 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -2004,6 +2004,41 @@ int hif_runtime_suspend(void) return hif_bus_suspend(); } +#ifdef WLAN_FEATURE_FASTPATH +/** + * hif_fastpath_resume() - resume fastpath for runtimepm + * + * ensure that the fastpath write index register is up to date + * since runtime pm may cause ce_send_fast to skip the register + * write. + */ +static void hif_fastpath_resume(void) +{ + struct ol_softc *scn = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + struct CE_state *ce_state; + + if (!scn) + return; + + if (scn->fastpath_mode_on) { + if (Q_TARGET_ACCESS_BEGIN(scn)) { + ce_state = scn->ce_id_to_state[CE_HTT_H2T_MSG]; + cdf_spin_lock_bh(&ce_state->ce_index_lock); + + /*war_ce_src_ring_write_idx_set */ + CE_SRC_RING_WRITE_IDX_SET(scn, ce_state->ctrl_addr, + ce_state->src_ring->write_index); + cdf_spin_unlock_bh(&ce_state->ce_index_lock); + Q_TARGET_ACCESS_END(scn); + } + } +} +#else +static void hif_fastpath_resume(void) {} +#endif + + /** * hif_runtime_resume() - do the bus resume part of a runtime resume * @@ -2011,7 +2046,11 @@ int hif_runtime_suspend(void) */ int hif_runtime_resume(void) { - return hif_bus_resume(); + int status = hif_bus_resume(); + + hif_fastpath_resume(); + + return status; } void hif_disable_isr(void *ol_sc) @@ -2690,6 +2729,23 @@ int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, } #ifdef FEATURE_RUNTIME_PM + +void hif_pm_runtime_get_noresume(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + struct hif_pci_softc *sc; + + if (NULL == scn) + return; + + sc = scn->hif_sc; + if (NULL == sc) + return; + + sc->pm_stats.runtime_get++; + pm_runtime_get_noresume(sc->dev); +} + /** * hif_pm_runtime_get() - do a get opperation on the device * diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index f84b772b0d4d..52bebcd3ec2a 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -186,7 +186,6 @@ static int hif_runtime_resume(void) return hif_bus_resume(); } - /** * hif_enable_power_gating(): enable HW power gating * -- cgit v1.2.3 From 78467a8d6a2865152692e110b6824e0895756020 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 5 Jan 2016 20:08:56 -0800 Subject: qcacld-3.0: Move runtime pm bookkeeping out of hdd Move state machine and stat logging for runtime pm feature out of hdd. Change-Id: I2699905d9c238a1402eac11c1107b44bb9e617e4 CRs-Fixed: 935300 --- core/hdd/src/wlan_hdd_driver_ops.c | 31 +++++------- core/hif/inc/hif.h | 24 +++++----- core/hif/src/pcie/if_pci.c | 98 ++++++++++++++++++++++++++++++++------ core/hif/src/snoc/if_snoc.c | 46 ------------------ 4 files changed, 106 insertions(+), 93 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 77ebe6a6122a..65462ac3ed10 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -527,7 +527,6 @@ static int wlan_hdd_bus_resume(void) } #ifdef FEATURE_RUNTIME_PM - /** * __wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend * @@ -542,21 +541,16 @@ static int __wlan_hdd_runtime_suspend(void) void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); int status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) { - hif_log_runtime_suspend_failure(); - return status; - } + if (0 != status) + goto process_failure; - if (!hif_can_suspend_link()) { - hdd_err("Runtime PM not supported for link up suspend"); - hif_log_runtime_suspend_failure(); - return -EINVAL; - } + status = hif_pre_runtime_suspend(); + if (status) + goto process_failure; - hif_runtime_pm_set_state_inprogress(); status = htc_runtime_suspend(); if (status) - goto set_state; + goto process_failure; status = wma_runtime_suspend(); if (status) @@ -570,8 +564,7 @@ static int __wlan_hdd_runtime_suspend(void) if (status) goto resume_hif; - hif_runtime_pm_set_state_suspended(); - hif_log_runtime_suspend_success(); + hif_process_runtime_suspend_success(); return status; resume_hif: @@ -580,9 +573,8 @@ resume_wma: CDF_BUG(!wma_runtime_resume()); resume_htc: CDF_BUG(!htc_runtime_resume()); -set_state: - hif_log_runtime_suspend_failure(); - hif_runtime_pm_set_state_on(); +process_failure: + hif_process_runtime_suspend_failure(); return status; } @@ -616,13 +608,12 @@ static int wlan_hdd_runtime_suspend(void) */ static int __wlan_hdd_runtime_resume(void) { - hif_runtime_pm_set_state_inprogress(); + hif_pre_runtime_resume(); CDF_BUG(!cnss_auto_resume()); CDF_BUG(!hif_runtime_resume()); CDF_BUG(!wma_runtime_resume()); CDF_BUG(!htc_runtime_resume()); - hif_log_runtime_resume_success(); - hif_runtime_pm_set_state_on(); + hif_process_runtime_resume_success(); return 0; } diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 2deb9c831901..0adc66dafbad 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -685,26 +685,24 @@ static inline int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, { return 0; } #endif -void hif_runtime_pm_set_state_inprogress(void); -void hif_runtime_pm_set_state_on(void); - void hif_enable_power_management(void *hif_ctx); void hif_disable_power_management(void *hif_ctx); -int hif_runtime_suspend(void); -int hif_runtime_resume(void); -int hif_bus_resume(void); -int hif_bus_suspend(void); + void hif_vote_link_down(void); void hif_vote_link_up(void); bool hif_can_suspend_link(void); -void hif_runtime_pm_set_state_inprogress(void); -void hif_runtime_pm_set_state_on(void); -void hif_runtime_pm_set_state_suspended(void); + +int hif_bus_resume(void); +int hif_bus_suspend(void); #ifdef FEATURE_RUNTIME_PM -void hif_log_runtime_suspend_success(void); -void hif_log_runtime_suspend_failure(void); -void hif_log_runtime_resume_success(void); +int hif_pre_runtime_suspend(void); +void hif_pre_runtime_resume(void); +int hif_runtime_suspend(void); +int hif_runtime_resume(void); +void hif_process_runtime_suspend_success(void); +void hif_process_runtime_suspend_failure(void); +void hif_process_runtime_resume_success(void); #endif int dump_ce_register(struct ol_softc *scn); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 1425d2c1b617..1e8e0cd257ef 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -1896,19 +1896,16 @@ static void __hif_runtime_pm_set_state(enum hif_pm_runtime_state state) sc = scn->hif_sc; cdf_atomic_set(&sc->pm_state, state); -} -#else -static void __hif_runtime_pm_set_state(enum hif_pm_runtime_state state) -{ } #endif +#ifdef FEATURE_RUNTIME_PM /** * hif_runtime_pm_set_state_inprogress(): adjust runtime pm state * * Notify hif that a runtime pm opperation has started */ -void hif_runtime_pm_set_state_inprogress(void) +static void hif_runtime_pm_set_state_inprogress(void) { __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_INPROGRESS); } @@ -1918,7 +1915,7 @@ void hif_runtime_pm_set_state_inprogress(void) * * Notify hif that a the runtime pm state should be on */ -void hif_runtime_pm_set_state_on(void) +static void hif_runtime_pm_set_state_on(void) { __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_ON); } @@ -1928,13 +1925,11 @@ void hif_runtime_pm_set_state_on(void) * * Notify hif that a runtime suspend attempt has been completed successfully */ -void hif_runtime_pm_set_state_suspended(void) +static void hif_runtime_pm_set_state_suspended(void) { __hif_runtime_pm_set_state(HIF_PM_RUNTIME_STATE_SUSPENDED); } - -#ifdef FEATURE_RUNTIME_PM static inline struct hif_pci_softc *get_sc(void) { struct ol_softc *scn = cds_get_context(CDF_MODULE_ID_HIF); @@ -1951,7 +1946,7 @@ static inline struct hif_pci_softc *get_sc(void) /** * hif_log_runtime_suspend_success() - log a successful runtime suspend */ -void hif_log_runtime_suspend_success(void) +static void hif_log_runtime_suspend_success(void) { struct hif_pci_softc *sc = get_sc(); if (sc == NULL) @@ -1967,14 +1962,13 @@ void hif_log_runtime_suspend_success(void) * log a failed runtime suspend * mark last busy to prevent immediate runtime suspend */ -void hif_log_runtime_suspend_failure(void) +static void hif_log_runtime_suspend_failure(void) { struct hif_pci_softc *sc = get_sc(); if (sc == NULL) return; sc->pm_stats.suspend_err++; - hif_pm_runtime_mark_last_busy(sc->dev); } /** @@ -1983,14 +1977,90 @@ void hif_log_runtime_suspend_failure(void) * log a successfull runtime resume * mark last busy to prevent immediate runtime suspend */ -void hif_log_runtime_resume_success(void) +static void hif_log_runtime_resume_success(void) { struct hif_pci_softc *sc = get_sc(); if (sc == NULL) return; sc->pm_stats.resumed++; - hif_pm_runtime_mark_last_busy(sc->dev); +} + +/** + * hif_process_runtime_suspend_failure() - bookkeeping of suspend failure + * + * Record the failure. + * mark last busy to delay a retry. + * adjust the runtime_pm state. + */ +void hif_process_runtime_suspend_failure(void) +{ + struct hif_pci_softc *sc = get_sc(); + + hif_log_runtime_suspend_failure(); + if (sc != NULL) + hif_pm_runtime_mark_last_busy(sc->dev); + hif_runtime_pm_set_state_on(); +} + +/** + * hif_pre_runtime_suspend() - bookkeeping before beginning runtime suspend + * + * Makes sure that the pci link will be taken down by the suspend opperation. + * If the hif layer is configured to leave the bus on, runtime suspend will + * not save any power. + * + * Set the runtime suspend state to in progress. + * + * return -EINVAL if the bus won't go down. otherwise return 0 + */ +int hif_pre_runtime_suspend(void) +{ + if (!hif_can_suspend_link()) { + HIF_ERROR("Runtime PM not supported for link up suspend"); + return -EINVAL; + } + + hif_runtime_pm_set_state_inprogress(); + return 0; +} + +/** + * hif_process_runtime_suspend_success() - bookkeeping of suspend success + * + * Record the success. + * adjust the runtime_pm state + */ +void hif_process_runtime_suspend_success(void) +{ + hif_runtime_pm_set_state_suspended(); + hif_log_runtime_suspend_success(); +} + +/** + * hif_pre_runtime_resume() - bookkeeping before beginning runtime resume + * + * update the runtime pm state. + */ +void hif_pre_runtime_resume(void) +{ + hif_runtime_pm_set_state_inprogress(); +} + +/** + * hif_process_runtime_resume_success() - bookkeeping after a runtime resume + * + * record the success. + * adjust the runtime_pm state + */ +void hif_process_runtime_resume_success(void) +{ + struct hif_pci_softc *sc = get_sc(); + + hif_log_runtime_resume_success(); + if (sc != NULL) + hif_pm_runtime_mark_last_busy(sc->dev); + hif_runtime_pm_set_state_on(); } #endif diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index 52bebcd3ec2a..c71bd5f16354 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -114,42 +114,6 @@ void dump_ce_debug_register(struct ol_softc *scn) return; } -/** - * hif_runtime_pm_set_state_inprogress() - dummy function - * - * currently runtime pm only supported in pci - */ -void hif_runtime_pm_set_state_inprogress(void) -{ -} - -/** - * hif_runtime_pm_set_state_on() - dummy function - * - * currently runtime pm only supported in pci - */ -void hif_runtime_pm_set_state_on(void) -{ -} - -/** - * hif_runtime_pm_set_state_suspended() - dummy function - * - * currently runtime pm only supported in pci - */ -void hif_runtime_pm_set_state_on(void) -{ -} - -/** - * hif_runtime_pm_set_state_suspended() - dummy function - * - * currently runtime pm only supported in pci - */ -void hif_runtime_pm_set_state_suspended(void) -{ -} - /** * hif_bus_suspend() - suspend the bus * @@ -176,16 +140,6 @@ int hif_bus_resume(void) return 0; } -static int hif_runtime_suspend(void) -{ - return hif_bus_suspend(); -} - -static int hif_runtime_resume(void) -{ - return hif_bus_resume(); -} - /** * hif_enable_power_gating(): enable HW power gating * -- cgit v1.2.3 From 3a28a11ccd66d9de13b40b2b8f67de5e5873911a Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 14 Jan 2016 17:08:26 -0800 Subject: qcacld-3.0: Remove obsolete and duplicate macros Remove obsolete and duplicate macros. Change-Id: I19010da3b40af1e65ec9a9a5e1fc01ecac56b0df CRs-Fixed: 898864 --- core/hdd/inc/wlan_hdd_wext.h | 8 +----- core/hdd/src/wlan_hdd_assoc.c | 2 +- core/hdd/src/wlan_hdd_cfg80211.c | 4 +-- core/mac/inc/sir_api.h | 2 +- core/mac/inc/sir_mac_prot_def.h | 36 ++----------------------- core/mac/src/pe/include/lim_api.h | 2 -- core/mac/src/pe/include/lim_ft_defs.h | 3 +-- core/mac/src/pe/include/lim_global.h | 6 ----- core/mac/src/pe/include/lim_session.h | 7 ++--- core/mac/src/pe/lim/lim_ibss_peer_mgmt.h | 4 +-- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 3 --- 11 files changed, 13 insertions(+), 64 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 0636c3262fe4..428e4f76160c 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -143,12 +143,6 @@ typedef enum { /** 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 diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index cdd34a79f3a7..15b7f8bc53ef 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -4449,7 +4449,7 @@ static int32_t hdd_process_genie(hdd_adapter_t *pAdapter, * in the bssid. */ cdf_mem_copy(PMKIDCache[i].BSSID.bytes, - bssid, ETHER_ADDR_LEN); + bssid, CDF_MAC_ADDR_SIZE); cdf_mem_copy(PMKIDCache[i].PMKID, dot11RSNIE.pmkid[i], CSR_RSN_PMKID_SIZE); } diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index d25e9ff99d6f..09ba705be76c 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -9871,7 +9871,7 @@ int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, mac, pAdapter->aStaInfo[i]. macAddrSTA.bytes, - ETHER_ADDR_LEN); + CDF_MAC_ADDR_SIZE); if (hdd_ipa_uc_is_enabled(pHddCtx)) { hdd_ipa_wlan_evt(pAdapter, pAdapter-> @@ -10161,7 +10161,7 @@ static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); - cdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, ETHER_ADDR_LEN); + cdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, CDF_MAC_ADDR_SIZE); cdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE); /* Add to the PMKSA ID Cache in CSR */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 5de6302bd66d..68bc6ff9c0ef 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -49,7 +49,7 @@ #define SIR_MAX_SUPPORTED_CHANNEL_LIST 96 #define SIR_MDIE_ELEMENT_ID 54 -#define SIR_MDIE_SIZE 3 +#define SIR_MDIE_SIZE 3 /* MD ID(2 bytes), Capability(1 byte) */ /* Increase dwell time for P2P search in ms */ #define P2P_SEARCH_DWELL_TIME_INCREASE 20 diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index bf90279c001f..d6494dacec6e 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -493,39 +493,7 @@ #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(uint8_t) + 2 * sizeof(uint16_t) + sizeof(uint32_t) +\ - 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) (((uint8_t) x) | 2) -#define SIR_MAC_SET_MEAS_REQ_REQUEST(x) (((uint8_t) x) | 4) -#define SIR_MAC_SET_MEAS_REQ_REPORT(x) (((uint8_t) x) | 8) - -#define SIR_MAC_SET_MEAS_REPORT_LATE(x) (((uint8_t) x) | 1) -#define SIR_MAC_SET_MEAS_REPORT_INCAPABLE(x) (((uint8_t) x) | 2) -#define SIR_MAC_SET_MEAS_REPORT_REFUSE(x) (((uint8_t) 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 */ diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index bf612454958f..d1d52cf2ad81 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -81,8 +81,6 @@ #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 { diff --git a/core/mac/src/pe/include/lim_ft_defs.h b/core/mac/src/pe/include/lim_ft_defs.h index 34c0ba68570f..599da6fa34df 100644 --- a/core/mac/src/pe/include/lim_ft_defs.h +++ b/core/mac/src/pe/include/lim_ft_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -41,7 +41,6 @@ /*-------------------------------------------------------------------------- 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 */ /*-------------------------------------------------------------------------- diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index a7747a1e67f6..3969a17599ca 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -51,9 +51,6 @@ #include "dot11f.h" #include "wma_if.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 @@ -74,9 +71,6 @@ ((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 */ diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 14cee56b5a70..16ebd4dd5bf5 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -65,7 +65,8 @@ typedef struct tagComebackTimerInfo { /*-------------------------------------------------------------------------- Preprocessor definitions and constants ------------------------------------------------------------------------*/ -#define NUM_WEP_KEYS 4 +/* Maximum Number of WEP KEYS */ +#define MAX_WEP_KEYS 4 /* Maximum allowable size of a beacon frame */ #define SCH_MAX_BEACON_SIZE 512 @@ -251,7 +252,7 @@ typedef struct sPESession /* Added to Support BT-AMP */ uint8_t privacy; tAniAuthType authType; - tSirKeyMaterial WEPKeyMaterial[NUM_WEP_KEYS]; + tSirKeyMaterial WEPKeyMaterial[MAX_WEP_KEYS]; tDot11fIERSN gStartBssRSNIe; tDot11fIEWPA gStartBssWPAIe; diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h index 0c97919c3d9f..9051fa2ddde9 100644 --- a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h +++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -39,8 +39,6 @@ #include "sir_common.h" #include "lim_utils.h" -#define IBSS_STATIONS_USED_DURING_INIT 4 /* (broadcast + self + p2p + softap) */ - void lim_ibss_init(tpAniSirGlobal); void lim_ibss_delete(tpAniSirGlobal, tpPESession psessionEntry); tSirRetStatus lim_ibss_coalesce(tpAniSirGlobal, tpSirMacMgmtHdr, diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index ec9f22e98332..491f97931308 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -698,9 +698,6 @@ lim_send_sme_start_bss_rsp(tpAniSirGlobal pMac, lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT); } /*** end lim_send_sme_start_bss_rsp() ***/ -#define LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED 20 -#define LIM_SIZE_OF_EACH_BSS 400 /* this is a rough estimate */ - /** * lim_send_sme_scan_rsp() - Send scan response to SME * @pMac: Pointer to Global MAC structure -- cgit v1.2.3 From 1d4ce0f30dd818969bd66c002a4a670da0c75028 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Thu, 14 Jan 2016 17:35:25 -0800 Subject: qcacld-3.0: Fix mangled function lim_cmp_s_sid() Fix mangled API lim_cmp_s_sid() to lim_cmp_ssid() which were introduced while converting the names programmatically. Change-Id: I3a6d4b8678fc815fb8c8787bd080c9188ef98f67 CRs-Fixed: 882962 --- core/mac/src/pe/lim/lim_api.c | 4 +-- core/mac/src/pe/lim/lim_assoc_utils.c | 36 ++++++----------------- core/mac/src/pe/lim/lim_assoc_utils.h | 2 +- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 2 +- 4 files changed, 13 insertions(+), 31 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 14fcfb71cc21..2584645074bf 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1417,7 +1417,7 @@ lim_handle_ibss_coalescing(tpAniSirGlobal pMac, 4. Encyption type in the beacon does not match with self station */ if ((!pBeacon->capabilityInfo.ibss) || - (lim_cmp_s_sid(pMac, &pBeacon->ssId, psessionEntry) != true) || + (lim_cmp_ssid(&pBeacon->ssId, psessionEntry) != true) || (psessionEntry->currentOperChannel != pBeacon->channelNumber)) retCode = eSIR_LIM_IGNORE_BEACON; else if (lim_ibss_enc_type_matched(pBeacon, psessionEntry) != eSIR_TRUE) { @@ -1553,7 +1553,7 @@ lim_detect_change_in_ap_capabilities(tpAniSirGlobal pMac, psessionEntry); if ((false == psessionEntry->limSentCapsChangeNtf) && (((!lim_is_null_ssid(&pBeacon->ssId)) && - (false == lim_cmp_s_sid(pMac, &pBeacon->ssId, psessionEntry))) || + (false == lim_cmp_ssid(&pBeacon->ssId, psessionEntry))) || ((SIR_MAC_GET_ESS(apNewCaps.capabilityInfo) != SIR_MAC_GET_ESS(psessionEntry->limCurrentBssCaps)) || (SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) != diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 3c47c79b0cd9..cb797399aa0a 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -85,38 +85,20 @@ lim_fill_supported_rates_info(tpAniSirGlobal pMac, } /** - * lim_cmp_s_sid() + * lim_cmp_ssid() - utility function to compare SSIDs + * @rx_ssid: Received SSID + * @session_entry: Session entry * - ***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 + * to determine whether received SSID is same as SSID in use. * - * @param *prxSSid - pointer to SSID structure - * - * @return status - true for SSID match else false. + * Return: true if SSID matched, false otherwise. */ - -uint8_t -lim_cmp_s_sid(tpAniSirGlobal pMac, tSirMacSSid *prxSSid, - tpPESession psessionEntry) +bool lim_cmp_ssid(tSirMacSSid *rx_ssid, tpPESession session_entry) { - - if (cdf_mem_compare - ((uint8_t *) prxSSid, (uint8_t *) &psessionEntry->ssId, - (uint8_t) (psessionEntry->ssId.length + 1))) - return true; - else - return false; - -} /****** end lim_cmp_s_sid() ******/ + return cdf_mem_compare(rx_ssid, &session_entry->ssId, + session_entry->ssId.length); +} /** * lim_compare_capabilities() diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h index f869ad3b7fa9..c0fc5a9e32a7 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.h +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -45,7 +45,7 @@ #include "lim_types.h" -uint8_t lim_cmp_s_sid(tpAniSirGlobal, tSirMacSSid *, tpPESession); +bool lim_cmp_ssid(tSirMacSSid *, tpPESession); uint8_t lim_compare_capabilities(tpAniSirGlobal, tSirAssocReq *, tSirMacCapabilityInfo *, tpPESession); diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index cda12aa0ff11..e7418bd49ef1 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -418,7 +418,7 @@ lim_process_assoc_req_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, updateContext = false; - if (lim_cmp_s_sid(pMac, &pAssocReq->ssId, psessionEntry) == false) { + if (lim_cmp_ssid(&pAssocReq->ssId, psessionEntry) == false) { lim_log(pMac, LOGE, FL("Received %s Req with unmatched ssid ( Received" " SSID: %.*s current SSID: %.*s ) from " -- cgit v1.2.3 From ac69ec2378d5e64802796ad94cea090b566aef93 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 30 Dec 2015 17:39:50 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeSwitchChannelInd Replace tSirMacAddr with cdf_mac_addr in tSirSmeSwitchChannelInd. Change-Id: Ide9e600c1c4b105740bd16a13366e1e2f5f9fda6 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_utils.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 68bc6ff9c0ef..431a71ec7e3a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1469,7 +1469,7 @@ typedef struct sSirSmeSwitchChannelInd { uint16_t length; uint8_t sessionId; uint16_t newChannelId; - tSirMacAddr bssId; /* BSSID */ + struct cdf_mac_addr bssid; /* BSSID */ } tSirSmeSwitchChannelInd, *tpSirSmeSwitchChannelInd; /* / Definition for Neighbor BSS indication */ diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 0b90d19ad229..41801aa1bbf0 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -2683,8 +2683,8 @@ void lim_switch_channel_cback(tpAniSirGlobal pMac, CDF_STATUS status, pSirSmeSwitchChInd->newChannelId = psessionEntry->gLimChannelSwitch.primaryChannel; pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId; - cdf_mem_copy(pSirSmeSwitchChInd->bssId, psessionEntry->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeSwitchChInd->bssid.bytes, psessionEntry->bssId, + CDF_MAC_ADDR_SIZE); mmhMsg.bodyptr = pSirSmeSwitchChInd; mmhMsg.bodyval = 0; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a605be0f71b3..7fa928825265 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10268,7 +10268,7 @@ csr_roam_chk_lnk_swt_ch_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) * statusCode. */ status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *) pSwitchChnInd->bssId, &sessionId); + &pSwitchChnInd->bssid, &sessionId); if (CDF_IS_STATUS_SUCCESS(status)) { session = CSR_GET_SESSION(mac_ctx, sessionId); if (!session) { -- cgit v1.2.3 From af677fc818df2b8e0cc389688c1d8ca0315f62ba Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 4 Jan 2016 14:32:25 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeStopBssReq Replace tSirMacAddr with cdf_mac_addr in tSirSmeStopBssReq. Change-Id: Ie758460224c632a8192f8dfbe14cbb508636ff25 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/sme/src/csr/csr_api_roam.c | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 431a71ec7e3a..473492070ab1 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1450,7 +1450,7 @@ typedef struct sSirSmeStopBssReq { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* tranSaction ID for cmd */ tSirResultCodes reasonCode; - tSirMacAddr bssId; /* Self BSSID */ + struct cdf_mac_addr bssid; /* Self BSSID */ } tSirSmeStopBssReq, *tpSirSmeStopBssReq; /* / Definition for stop BSS response message */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index fd9616a791b1..cecad6397b22 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -3332,7 +3332,7 @@ __lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf) } psessionEntry = pe_find_session_by_bssid(pMac, - stopBssReq.bssId, + stopBssReq.bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGW, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7fa928825265..677e8decf539 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14674,9 +14674,7 @@ CDF_STATUS csr_send_mb_stop_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId) pMsg->length = sizeof(tSirSmeStopBssReq); pMsg->transactionId = 0; pMsg->reasonCode = 0; - cdf_mem_copy(&pMsg->bssId, - &pSession->connectedProfile.bssid.bytes, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMsg->bssid, &pSession->connectedProfile.bssid); return cds_send_mb_message_to_mac(pMsg); } -- cgit v1.2.3 From 3daefc9a3053f81c807485af40e1e6b2386e64cd Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 4 Jan 2016 15:51:05 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthInd Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthInd. Change-Id: Ic8203cb89b970d5efb4c99e5e570af95ac9f802e CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 12 +++++----- core/sme/src/csr/csr_api_roam.c | 29 +++++++++++-------------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 473492070ab1..a1328bda376e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1435,8 +1435,8 @@ typedef struct sSirSmeDeauthInd { uint8_t sessionId; /* Added for BT-AMP */ uint16_t transactionId; /* Added for BT-AMP */ tSirResultCodes statusCode; - tSirMacAddr bssId; /* AP BSSID */ - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; /* AP BSSID */ + struct cdf_mac_addr peer_macaddr; uint16_t staId; uint32_t reasonCode; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 491f97931308..54580f82e21b 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1125,11 +1125,11 @@ lim_send_sme_deauth_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, (tSirResultCodes) pStaDs->mlmStaContext.disassocReason; } /* BSSID */ - cdf_mem_copy(pSirSmeDeauthInd->bssId, psessionEntry->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeDeauthInd->bssid.bytes, psessionEntry->bssId, + CDF_MAC_ADDR_SIZE); /* peerMacAddr */ - cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, pStaDs->staAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, pStaDs->staAddr, + CDF_MAC_ADDR_SIZE); pSirSmeDeauthInd->reasonCode = pStaDs->mlmStaContext.disassocReason; pSirSmeDeauthInd->staId = pStaDs->staIndex; @@ -1451,8 +1451,8 @@ lim_send_sme_deauth_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, pBuf += sizeof(tSirMacAddr); /* peerMacAddr */ - cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, peerMacAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, peerMacAddr, + CDF_MAC_ADDR_SIZE); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 677e8decf539..7b5769bff1ec 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10193,8 +10193,8 @@ csr_roam_chk_lnk_deauth_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) sms_log(mac_ctx, LOG1, FL("DEAUTHENTICATION Indication from MAC")); pDeauthInd = (tpSirSmeDeauthInd) msg_ptr; status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *) pDeauthInd-> - bssId, &sessionId); + &pDeauthInd->bssid, + &sessionId); if (!CDF_IS_STATUS_SUCCESS(status)) return; /* If we are in neighbor preauth done state then on receiving @@ -10240,12 +10240,10 @@ csr_roam_chk_lnk_deauth_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) roam_info_ptr->reasonCode = pDeauthInd->reasonCode; roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; roam_info_ptr->staId = (uint8_t) pDeauthInd->staId; - cdf_mem_copy(roam_info_ptr->peerMac.bytes, - pDeauthInd->peerMacAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(&roam_info_ptr->bssid.bytes, - pDeauthInd->bssId, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info_ptr->peerMac, + &pDeauthInd->peer_macaddr); + cdf_copy_macaddr(&roam_info_ptr->bssid, + &pDeauthInd->bssid); status = csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, eCSR_ROAM_INFRA_IND, @@ -11401,14 +11399,13 @@ CDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, roamInfo.reasonCode = pDisassocIndMsg->reasonCode; } else if (eWNI_SME_DEAUTH_IND == type) { /* staMacAddr */ - cdf_mem_copy(roamInfo.peerMac.bytes, - pDeauthIndMsg->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, + &pDeauthIndMsg->peer_macaddr); roamInfo.staId = (uint8_t) pDeauthIndMsg->staId; roamInfo.reasonCode = pDeauthIndMsg->reasonCode; roamInfo.rxRssi = pDeauthIndMsg->rssi; } - sms_log(pMac, LOGW, FL("roamInfo.staId (%d)"), roamInfo.staId); + sms_log(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 @@ -14329,15 +14326,15 @@ CDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, pMsg->messageType = eWNI_SME_DEAUTH_CNF; pMsg->statusCode = eSIR_SME_SUCCESS; pMsg->length = sizeof(tSirSmeDeauthCnf); - cdf_mem_copy(pMsg->bssId, pDeauthInd->bssId, - sizeof(pMsg->bssId)); + cdf_mem_copy(pMsg->bssId, pDeauthInd->bssid.bytes, + CDF_MAC_ADDR_SIZE); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); break; } - cdf_mem_copy(pMsg->peerMacAddr, pDeauthInd->peerMacAddr, - sizeof(pMsg->peerMacAddr)); + cdf_mem_copy(pMsg->peerMacAddr, pDeauthInd->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); -- cgit v1.2.3 From cd88e7602a222fee18132160c6c0cbd290997c08 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 4 Jan 2016 16:17:15 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthRsp Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthRsp. Change-Id: I383f867f8847f66bc6f6e99ee2a56b4bc89ebe5b CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 4 ++-- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 2 +- core/sme/src/csr/csr_api_roam.c | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a1328bda376e..8fe896135244 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1425,7 +1425,7 @@ typedef struct sSirSmeDeauthRsp { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ tSirResultCodes statusCode; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; } tSirSmeDeauthRsp, *tpSirSmeDeauthRsp; /* / Definition for Deauthetication indication from peer */ diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index dc89b0918ad2..949b44ced937 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -2010,9 +2010,9 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, mlm_deauth_req->sessionId; sme_deauth_rsp->transactionId = 0; - cdf_mem_copy(sme_deauth_rsp->peerMacAddr, + cdf_mem_copy(sme_deauth_rsp->peer_macaddr.bytes, mlm_deauth_req->peerMacAddr, - sizeof(tSirMacAddr)); + CDF_MAC_ADDR_SIZE); msg_buf = (uint32_t *)sme_deauth_rsp; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 54580f82e21b..96af67bf1b87 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1401,7 +1401,7 @@ lim_send_sme_deauth_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, pSirSmeDeauthRsp->sessionId = smesessionId; pSirSmeDeauthRsp->transactionId = smetransactionId; - pBuf = (uint8_t *) pSirSmeDeauthRsp->peerMacAddr; + pBuf = (uint8_t *) pSirSmeDeauthRsp->peer_macaddr.bytes; cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7b5769bff1ec..8415a89fc485 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10302,9 +10302,8 @@ csr_roam_chk_lnk_deauth_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) if (CSR_IS_INFRA_AP(&session->connectedProfile)) { roam_info_ptr = &roam_info; roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; - cdf_mem_copy(roam_info_ptr->peerMac.bytes, - pDeauthRsp->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roam_info_ptr->peerMac, + &pDeauthRsp->peer_macaddr); roam_info_ptr->reasonCode = eCSR_ROAM_RESULT_FORCED; roam_info_ptr->statusCode = pDeauthRsp->statusCode; status = csr_roam_call_callback(mac_ctx, sessionId, -- cgit v1.2.3 From e6a851ebdf73fcd88e4da0ba212bd253cfe719a0 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 4 Jan 2016 18:49:40 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthRsp Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthRsp. Change-Id: I7036160f39ff69be5f937a71769e057d8906f2d3 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 +- core/mac/src/pe/lim/lim_assoc_utils.c | 54 ++++++++----------- core/mac/src/pe/lim/lim_assoc_utils.h | 2 +- core/mac/src/pe/lim/lim_process_auth_frame.c | 17 +++--- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 60 ++++++++++++---------- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 2 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 17 +++--- core/mac/src/pe/lim/lim_send_management_frames.c | 11 ++-- core/mac/src/pe/lim/lim_sme_req_utils.c | 6 +-- core/mac/src/pe/lim/lim_types.h | 4 +- core/sme/src/csr/csr_api_roam.c | 13 ++--- 11 files changed, 89 insertions(+), 101 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 8fe896135244..ccbbb8a7c822 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1413,8 +1413,8 @@ typedef struct sSirSmeDeauthReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; /* AP BSSID */ - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; /* AP BSSID */ + struct cdf_mac_addr peer_macaddr; uint16_t reasonCode; } tSirSmeDeauthReq, *tpSirSmeDeauthReq; diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index cb797399aa0a..008b8c4c860e 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -668,45 +668,32 @@ lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs, } /*** end lim_cleanup_rx_path() ***/ /** - * lim_send_del_sta_cnf() + * lim_send_del_sta_cnf() - Send Del sta confirmation + * @pMac: Pointer to Global MAC structure + * @sta_dsaddr: sta ds address + * @staDsAssocId: sta ds association id + * @mlmStaContext: MLM station context + * @statusCode: Status code + * @psessionEntry: Session entry * - ***FUNCTION: - * This function is called to send appropriate CNF message to SME - * - ***LOGIC: + * This function is called to send appropriate CNF message to SME. * - * - ***ASSUMPTIONS: - * NA - * - ***NOTE: - * NA - * - * @param pMac Pointer to Global MAC structure - * @param tpAniSirGlobal pMac, - * @param tSirMacAddr staDsAddr, - * @param uint16_t staDsAssocId, - * @param tLimMlmStaContext mlmStaContext, - * @param tSirResultCodes statusCode - * - * @return None + * Return: None */ - void -lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, +lim_send_del_sta_cnf(tpAniSirGlobal pMac, struct cdf_mac_addr sta_dsaddr, uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext, tSirResultCodes statusCode, tpPESession psessionEntry) { - tLimMlmDisassocCnf mlmDisassocCnf; tLimMlmDeauthCnf mlmDeauthCnf; tLimMlmPurgeStaInd mlmPurgeStaInd; - lim_log(pMac, LOG1, FL("Sessionid: %d staDsAssocId: %d Trigger: %d" - "statusCode: %d staDsAddr: " MAC_ADDRESS_STR), + lim_log(pMac, LOG1, + FL("Sessionid: %d staDsAssocId: %d Trigger: %d statusCode: %d sta_dsaddr: "MAC_ADDRESS_STR), psessionEntry->peSessionId, staDsAssocId, mlmStaContext.cleanupTrigger, statusCode, - MAC_ADDR_ARRAY(staDsAddr)); + MAC_ADDR_ARRAY(sta_dsaddr.bytes)); if (LIM_IS_STA_ROLE(psessionEntry) || LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { @@ -748,7 +735,7 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, mlmStaContext.cleanupTrigger); cdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr, - (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + (uint8_t *) sta_dsaddr.bytes, CDF_MAC_ADDR_SIZE); mlmDisassocCnf.resultCode = statusCode; mlmDisassocCnf.disassocTrigger = mlmStaContext.cleanupTrigger; /* Update PE session Id */ @@ -768,8 +755,7 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, lim_log(pMac, LOGW, FL("Lim Posting DEAUTH_CNF to Sme. Trigger: %d"), mlmStaContext.cleanupTrigger); - cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr, - (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlmDeauthCnf.peer_macaddr, &sta_dsaddr); mlmDeauthCnf.resultCode = statusCode; mlmDeauthCnf.deauthTrigger = mlmStaContext.cleanupTrigger; /* PE session Id */ @@ -789,7 +775,7 @@ lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, FL("Lim Posting PURGE_STA_IND to Sme. Trigger: %d"), mlmStaContext.cleanupTrigger); cdf_mem_copy((uint8_t *) &mlmPurgeStaInd.peerMacAddr, - (uint8_t *) staDsAddr, sizeof(tSirMacAddr)); + (uint8_t *) sta_dsaddr.bytes, CDF_MAC_ADDR_SIZE); mlmPurgeStaInd.reasonCode = (uint8_t) mlmStaContext.disassocReason; mlmPurgeStaInd.aid = staDsAssocId; @@ -4857,7 +4843,7 @@ lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry) { uint16_t staDsAssocId = 0; - tSirMacAddr staDsAddr; + struct cdf_mac_addr sta_dsaddr; tLimMlmStaContext mlmStaContext; if (pStaDs == NULL) { @@ -4865,8 +4851,8 @@ lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, return; } staDsAssocId = pStaDs->assocId; - cdf_mem_copy((uint8_t *) staDsAddr, - pStaDs->staAddr, sizeof(tSirMacAddr)); + cdf_mem_copy((uint8_t *) sta_dsaddr.bytes, + pStaDs->staAddr, CDF_MAC_ADDR_SIZE); mlmStaContext = pStaDs->mlmStaContext; if (LIM_IS_AP_ROLE(psessionEntry) || @@ -4883,7 +4869,7 @@ lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs, psessionEntry->peSessionId, psessionEntry->limMlmState)); } - lim_send_del_sta_cnf(pMac, staDsAddr, staDsAssocId, mlmStaContext, + lim_send_del_sta_cnf(pMac, sta_dsaddr, staDsAssocId, mlmStaContext, statusCode, psessionEntry); } diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h index c0fc5a9e32a7..8a846119a284 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.h +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -134,7 +134,7 @@ void lim_post_reassoc_failure(tpAniSirGlobal, tSirResultCodes, uint16_t, tpPESession); bool lim_is_reassoc_in_progress(tpAniSirGlobal, tpPESession); void -lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr, +lim_send_del_sta_cnf(tpAniSirGlobal pMac, struct cdf_mac_addr sta_dsaddr, uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext, tSirResultCodes statusCode, tpPESession psessionEntry); diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index 526b5f4763d9..e292e2c0dfcb 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -527,15 +527,14 @@ lim_process_auth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, && (cdf_mem_compare ((uint8_t *) pHdr->sa, - (uint8_t *) &pMlmDeauthReq->peerMacAddr, - sizeof(tSirMacAddr)))) { + (uint8_t *) &pMlmDeauthReq->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE))) { PELOGE(lim_log - (pMac, LOGE, - FL("TODO:Ack for deauth frame " - "is pending Issue delsta for " - MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pMlmDeauthReq-> - peerMacAddr)); + (pMac, LOGE, + FL("TODO:Ack for deauth frame is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDeauthReq-> + peer_macaddr.bytes)); ) lim_process_deauth_ack_timeout(pMac); isConnected = eSIR_FALSE; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 949b44ced937..5f0f4ab5f1ba 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1798,8 +1798,8 @@ bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal mac_ctx, (uint8_t *) &disassoc_req->peerMacAddr, sizeof(tSirMacAddr)))) || (deauth_req && (cdf_mem_compare((uint8_t *) sta_mac, - (uint8_t *) &deauth_req->peerMacAddr, - sizeof(tSirMacAddr))))) { + (uint8_t *) &deauth_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE)))) { PELOG1(lim_log(mac_ctx, LOG1, FL("Disassoc/Deauth ack pending"));) return true; @@ -1848,8 +1848,8 @@ void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal mac_ctx, mlm_deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; if (mlm_deauth_req && (cdf_mem_compare((uint8_t *) sta_mac, - (uint8_t *) &mlm_deauth_req->peerMacAddr, - sizeof(tSirMacAddr)))) { + (uint8_t *) &mlm_deauth_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE))) { if (clean_rx_path) { lim_process_deauth_ack_timeout(mac_ctx); } else { @@ -1957,7 +1957,7 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, mlm_deauth_req->sessionId, GET_LIM_SYSTEM_ROLE(session), session->limMlmState, - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_deauth_req->peer_macaddr.bytes)); sir_copy_mac_addr(curr_bssId, session->bssId); switch (GET_LIM_SYSTEM_ROLE(session)) { @@ -1974,14 +1974,14 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, case eLIM_MLM_AUTHENTICATED_STATE: case eLIM_MLM_WT_ASSOC_RSP_STATE: case eLIM_MLM_LINK_ESTABLISHED_STATE: - if (!cdf_mem_compare(mlm_deauth_req->peerMacAddr, - curr_bssId, sizeof(tSirMacAddr))) { + if (!cdf_mem_compare(mlm_deauth_req->peer_macaddr.bytes, + curr_bssId, CDF_MAC_ADDR_SIZE)) { lim_log(mac_ctx, LOGE, FL("received MLM_DEAUTH_REQ with invalid BSS id " "Peer MAC: "MAC_ADDRESS_STR " CFG BSSID Addr : "MAC_ADDRESS_STR), MAC_ADDR_ARRAY( - mlm_deauth_req->peerMacAddr), + mlm_deauth_req->peer_macaddr.bytes), MAC_ADDR_ARRAY(curr_bssId)); /* * Deauthentication response to host triggered @@ -1998,7 +1998,8 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, lim_log(mac_ctx, LOG1, FL("send deauth rsp with ret code %d for" MAC_ADDRESS_STR), eSIR_SME_DEAUTH_STATUS, - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY( + mlm_deauth_req->peer_macaddr.bytes)); sme_deauth_rsp->messageType = eWNI_SME_DEAUTH_RSP; @@ -2011,8 +2012,8 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, sme_deauth_rsp->transactionId = 0; cdf_mem_copy(sme_deauth_rsp->peer_macaddr.bytes, - mlm_deauth_req->peerMacAddr, - CDF_MAC_ADDR_SIZE); + mlm_deauth_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE); msg_buf = (uint32_t *)sme_deauth_rsp; @@ -2027,9 +2028,9 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, eLIM_MLM_WT_ASSOC_RSP_STATE)) { /* Send deauth frame to peer entity */ lim_send_deauth_mgmt_frame(mac_ctx, - mlm_deauth_req->reasonCode, - mlm_deauth_req->peerMacAddr, - session, false); + mlm_deauth_req->reasonCode, + mlm_deauth_req->peer_macaddr.bytes, + session, false); /* Prepare and Send LIM_MLM_DEAUTH_CNF */ mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; session->limMlmState = eLIM_MLM_IDLE_STATE; @@ -2044,7 +2045,8 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, FL("received MLM_DEAUTH_REQ with in state %d for peer " MAC_ADDRESS_STR), session->limMlmState, - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY( + mlm_deauth_req->peer_macaddr.bytes)); lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState); /* Prepare and Send LIM_MLM_DEAUTH_CNF */ @@ -2077,13 +2079,14 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, * Check if there exists a context for the peer entity * to be deauthenticated with. */ - sta_ds = dph_lookup_hash_entry(mac_ctx, mlm_deauth_req->peerMacAddr, + sta_ds = dph_lookup_hash_entry(mac_ctx, + mlm_deauth_req->peer_macaddr.bytes, &aid, &session->dph.dphHashTable); if (sta_ds == NULL) { /* Check if there exists pre-auth context for this STA */ auth_node = lim_search_pre_auth_list(mac_ctx, - mlm_deauth_req->peerMacAddr); + mlm_deauth_req->peer_macaddr.bytes); if (auth_node == NULL) { /* * Received DEAUTH REQ for a STA that is neither @@ -2095,19 +2098,20 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, "does not have context, Addr=" MAC_ADDRESS_STR), session->limMlmState, - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY( + mlm_deauth_req->peer_macaddr.bytes)); mlm_deauth_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED; } else { mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; /* Delete STA from pre-auth STA list */ lim_delete_pre_auth_node(mac_ctx, - mlm_deauth_req->peerMacAddr); + mlm_deauth_req->peer_macaddr.bytes); /* Send Deauthentication frame to peer entity */ lim_send_deauth_mgmt_frame(mac_ctx, - mlm_deauth_req->reasonCode, - mlm_deauth_req->peerMacAddr, - session, false); + mlm_deauth_req->reasonCode, + mlm_deauth_req->peer_macaddr.bytes, + session, false); } goto end; } else if ((sta_ds->mlmStaContext.mlmState != @@ -2120,7 +2124,7 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, */ lim_log(mac_ctx, LOGW, FL("Invalid MLM_DEAUTH_REQ, Addr="MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_deauth_req->peer_macaddr.bytes)); /* Prepare and Send LIM_MLM_DEAUTH_CNF */ mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; @@ -2141,12 +2145,12 @@ lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx, sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; /* Send Deauthentication frame to peer entity */ lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode, - mlm_deauth_req->peerMacAddr, session, true); + mlm_deauth_req->peer_macaddr.bytes, + session, true); return; end: - cdf_mem_copy((uint8_t *) &mlm_deauth_cnf.peerMacAddr, - (uint8_t *) mlm_deauth_req->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlm_deauth_cnf.peer_macaddr, + &mlm_deauth_req->peer_macaddr); mlm_deauth_cnf.deauthTrigger = mlm_deauth_req->deauthTrigger; mlm_deauth_cnf.aid = mlm_deauth_req->aid; mlm_deauth_cnf.sessionId = mlm_deauth_req->sessionId; @@ -2200,7 +2204,7 @@ lim_process_mlm_deauth_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) FL("Process Deauth Req on sessionID %d from: " MAC_ADDRESS_STR), mlm_deauth_req->sessionId, - MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_deauth_req->peer_macaddr.bytes)); session = pe_find_session_by_session_id(mac_ctx, mlm_deauth_req->sessionId); diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index af40676794fd..c64ef91effb6 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1328,7 +1328,7 @@ void lim_process_mlm_deauth_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) pMac->lim.gLimRspReqd = false; } /* On STA or on BASIC AP, send SME_DEAUTH_RSP to host */ - lim_send_sme_deauth_ntf(pMac, pMlmDeauthCnf->peerMacAddr, + lim_send_sme_deauth_ntf(pMac, pMlmDeauthCnf->peer_macaddr.bytes, resultCode, pMlmDeauthCnf->deauthTrigger, aid, psessionEntry->smeSessionId, diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index cecad6397b22..d99a213a3d71 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2729,8 +2729,9 @@ static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx, * We need to get a session first but we don't even know * if the message is correct. */ - session_entry = pe_find_session_by_bssid(mac_ctx, sme_deauth_req.bssId, - &session_id); + session_entry = pe_find_session_by_bssid(mac_ctx, + sme_deauth_req.bssid.bytes, + &session_id); if (session_entry == NULL) { lim_log(mac_ctx, LOGE, FL("session does not exist for given bssId")); @@ -2754,7 +2755,7 @@ static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx, MAC_ADDRESS_STR), sme_session_id, GET_LIM_SYSTEM_ROLE(session_entry), sme_deauth_req.reasonCode, session_entry->limSmeState, - MAC_ADDR_ARRAY(sme_deauth_req.peerMacAddr)); + MAC_ADDR_ARRAY(sme_deauth_req.peer_macaddr.bytes)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, session_entry, 0, sme_deauth_req.reasonCode); @@ -2885,9 +2886,8 @@ static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx, return; } - cdf_mem_copy((uint8_t *) &mlm_deauth_req->peerMacAddr, - (uint8_t *) &sme_deauth_req.peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlm_deauth_req->peer_macaddr, + &sme_deauth_req.peer_macaddr); mlm_deauth_req->reasonCode = reason_code; mlm_deauth_req->deauthTrigger = deauth_trigger; @@ -2900,8 +2900,9 @@ static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx, return; send_deauth: - lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peerMacAddr, ret_code, - deauth_trigger, 1, sme_session_id, sme_transaction_id); + lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peer_macaddr.bytes, + ret_code, deauth_trigger, 1, + sme_session_id, sme_transaction_id); } /** diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index f2aaf946d4b7..a8df2cca966d 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -3078,7 +3078,9 @@ CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac) } pStaDs = - dph_lookup_hash_entry(pMac, pMlmDeauthReq->peerMacAddr, &aid, + dph_lookup_hash_entry(pMac, + pMlmDeauthReq->peer_macaddr.bytes, + &aid, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; @@ -3132,9 +3134,8 @@ CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac) } return CDF_STATUS_SUCCESS; end: - cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr, - (uint8_t *) pMlmDeauthReq->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&mlmDeauthCnf.peer_macaddr, + &pMlmDeauthReq->peer_macaddr); mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger; mlmDeauthCnf.aid = pMlmDeauthReq->aid; mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId; diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c index 7e06f75d72cf..fe3e2f035603 100644 --- a/core/mac/src/pe/lim/lim_sme_req_utils.c +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -648,8 +648,8 @@ uint8_t lim_is_sme_deauth_req_valid(tpAniSirGlobal pMac, tpSirSmeDeauthReq pDeauthReq, tpPESession psessionEntry) { - if (lim_is_group_addr(pDeauthReq->peerMacAddr) && - !lim_is_addr_bc(pDeauthReq->peerMacAddr)) + if (cdf_is_macaddr_group(&pDeauthReq->peer_macaddr) && + !cdf_is_macaddr_broadcast(&pDeauthReq->peer_macaddr)) return false; return true; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index c4b575058c79..176a1113f5d6 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -309,7 +309,7 @@ typedef struct sLimMlmAuthCnf { } tLimMlmAuthCnf, *tpLimMlmAuthCnf; typedef struct sLimMlmDeauthReq { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint16_t reasonCode; uint16_t deauthTrigger; uint16_t aid; @@ -318,7 +318,7 @@ typedef struct sLimMlmDeauthReq { } tLimMlmDeauthReq, *tpLimMlmDeauthReq; typedef struct sLimMlmDeauthCnf { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; tSirResultCodes resultCode; uint16_t deauthTrigger; uint16_t aid; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 8415a89fc485..4f0f729bd61c 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14252,19 +14252,16 @@ CDF_STATUS csr_send_mb_deauth_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, if ((pSession->pCurRoamProfile != NULL) && (CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) { - cdf_mem_copy(&pMsg->bssId, + cdf_mem_copy(&pMsg->bssid, &pSession->selfMacAddr, - sizeof(tSirMacAddr)); + CDF_MAC_ADDR_SIZE); } else { - cdf_mem_copy(&pMsg->bssId, - bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->bssid, + bssId, CDF_MAC_ADDR_SIZE); } /* Set the peer MAC address before sending the message to LIM */ - cdf_mem_copy(&pMsg->peerMacAddr, - bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, CDF_MAC_ADDR_SIZE); pMsg->reasonCode = reasonCode; return cds_send_mb_message_to_mac(pMsg); -- cgit v1.2.3 From c5409f98847957c3d787246a53d737ee63450f01 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Mon, 4 Jan 2016 21:47:19 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthCnf Replace tSirMacAddr with cdf_mac_addr in tSirSmeDeauthCnf. Change-Id: I16b399bcb76a6dd3fcc35c52e5822e988d4e5001 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 11 +++++------ core/mac/src/pe/lim/lim_sme_req_utils.c | 2 +- core/sme/src/csr/csr_api_roam.c | 16 ++++++++-------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index ccbbb8a7c822..71124f09658c 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1402,8 +1402,8 @@ typedef struct sSirSmeDisassocCnf { uint16_t messageType; /* eWNI_SME_DISASSOC_CNF */ uint16_t length; tSirResultCodes statusCode; - tSirMacAddr bssId; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; + struct cdf_mac_addr peer_macaddr; } tSirSmeDisassocCnf, *tpSirSmeDisassocCnf, tSirSmeDeauthCnf, *tpSirSmeDeauthCnf; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index d99a213a3d71..26a93d27b0f1 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2603,7 +2603,7 @@ static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBu sizeof(struct sSirSmeDisassocCnf)); psessionEntry = pe_find_session_by_bssid(pMac, - smeDisassocCnf.bssId, + smeDisassocCnf.bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, @@ -2661,13 +2661,13 @@ static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBu (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE) || LIM_IS_AP_ROLE(psessionEntry)) { pStaDs = dph_lookup_hash_entry(pMac, - smeDisassocCnf.peerMacAddr, &aid, + smeDisassocCnf.peer_macaddr.bytes, &aid, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { lim_log(pMac, LOGE, FL("DISASSOC_CNF for a STA with no context, addr= " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr)); + MAC_ADDR_ARRAY(smeDisassocCnf.peer_macaddr.bytes)); return; } @@ -2677,7 +2677,7 @@ static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBu eLIM_MLM_WT_DEL_STA_RSP_STATE)) { lim_log(pMac, LOGE, FL("No need of cleanup for addr:" MAC_ADDRESS_STR "as MLM state is %d"), - MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr), + MAC_ADDR_ARRAY(smeDisassocCnf.peer_macaddr.bytes), pStaDs->mlmStaContext.mlmState); return; } @@ -2689,8 +2689,7 @@ static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBu lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); lim_clean_up_disassoc_deauth_req(pMac, - (char *)&smeDisassocCnf.peerMacAddr, - 0); + (char *)&smeDisassocCnf.peer_macaddr, 0); } return; diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c index fe3e2f035603..fd82e7cbd62d 100644 --- a/core/mac/src/pe/lim/lim_sme_req_utils.c +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -618,7 +618,7 @@ lim_is_sme_disassoc_cnf_valid(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tpPESession psessionEntry) { - if (lim_is_group_addr(pDisassocCnf->peerMacAddr)) + if (cdf_is_macaddr_group(&pDisassocCnf->peer_macaddr)) return false; return true; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 4f0f729bd61c..a0bcbaab378b 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14284,16 +14284,17 @@ CDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac, pMsg->messageType = eWNI_SME_DISASSOC_CNF; pMsg->statusCode = eSIR_SME_SUCCESS; pMsg->length = sizeof(tSirSmeDisassocCnf); - cdf_mem_copy(pMsg->peerMacAddr, pDisassocInd->peerMacAddr, - sizeof(pMsg->peerMacAddr)); + cdf_mem_copy(pMsg->peer_macaddr.bytes, + pDisassocInd->peerMacAddr, + CDF_MAC_ADDR_SIZE); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); break; } - cdf_mem_copy(pMsg->bssId, pDisassocInd->bssId, - sizeof(pMsg->peerMacAddr)); + cdf_mem_copy(pMsg->bssid.bytes, pDisassocInd->bssId, + CDF_MAC_ADDR_SIZE); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); @@ -14322,15 +14323,14 @@ CDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac, pMsg->messageType = eWNI_SME_DEAUTH_CNF; pMsg->statusCode = eSIR_SME_SUCCESS; pMsg->length = sizeof(tSirSmeDeauthCnf); - cdf_mem_copy(pMsg->bssId, pDeauthInd->bssid.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->bssid, &pDeauthInd->bssid); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); break; } - cdf_mem_copy(pMsg->peerMacAddr, pDeauthInd->peer_macaddr.bytes, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->peer_macaddr, + &pDeauthInd->peer_macaddr); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); -- cgit v1.2.3 From 70a196142e70f9cf3a805d3954a58b653d3d7929 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 5 Jan 2016 17:07:53 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocInd Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocInd. Change-Id: Icdf3420c24762f919df73d57dffdf1b51151a0e8 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 +-- core/mac/src/pe/lim/lim_send_sme_rsp_messages.c | 8 +++--- core/sme/src/csr/csr_api_roam.c | 34 +++++++++++-------------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 71124f09658c..facb9d0eba1d 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1389,8 +1389,8 @@ typedef struct sSirSmeDisassocInd { uint8_t sessionId; /* Session Identifier */ uint16_t transactionId; /* Transaction Identifier with PE */ tSirResultCodes statusCode; - tSirMacAddr bssId; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; + struct cdf_mac_addr peer_macaddr; tAniStaStatStruct perStaStats; /* STA stats */ uint16_t staId; uint32_t reasonCode; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 96af67bf1b87..b1c3d36db155 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -1063,11 +1063,11 @@ lim_send_sme_disassoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, pSirSmeDisassocInd->statusCode = pStaDs->mlmStaContext.disassocReason; pSirSmeDisassocInd->reasonCode = pStaDs->mlmStaContext.disassocReason; - cdf_mem_copy(pSirSmeDisassocInd->bssId, psessionEntry->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeDisassocInd->bssid.bytes, psessionEntry->bssId, + CDF_MAC_ADDR_SIZE); - cdf_mem_copy(pSirSmeDisassocInd->peerMacAddr, pStaDs->staAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes, pStaDs->staAddr, + CDF_MAC_ADDR_SIZE); pSirSmeDisassocInd->staId = pStaDs->staIndex; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a0bcbaab378b..b103e1cfd0c6 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10096,10 +10096,11 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) pDisassocInd = (tSirSmeDisassocInd *) msg_ptr; cdf_mem_set(&roam_info, sizeof(roam_info), 0); status = csr_roam_get_session_id_from_bssid(mac_ctx, - (struct cdf_mac_addr *) pDisassocInd->bssId, &sessionId); + &pDisassocInd->bssid, &sessionId); if (!CDF_IS_STATUS_SUCCESS(status)) { sms_log(mac_ctx, LOGE, FL("Session Id not found for BSSID " - MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pDisassocInd->bssId)); + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDisassocInd->bssid.bytes)); return; } @@ -10109,7 +10110,7 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) sms_log(mac_ctx, LOGE, FL("DISASSOCIATION from peer =" MAC_ADDRESS_STR " " " reason = %d status = %d "), - MAC_ADDR_ARRAY(pDisassocInd->peerMacAddr), + MAC_ADDR_ARRAY(pDisassocInd->peer_macaddr.bytes), pDisassocInd->reasonCode, pDisassocInd->statusCode); /* @@ -10154,12 +10155,10 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) roam_info_ptr->reasonCode = pDisassocInd->reasonCode; roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; roam_info_ptr->staId = (uint8_t) pDisassocInd->staId; - cdf_mem_copy(roam_info_ptr->peerMac.bytes, - pDisassocInd->peerMacAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(&roam_info_ptr->bssid.bytes, - pDisassocInd->bssId, - sizeof(struct cdf_mac_addr)); + cdf_copy_macaddr(&roam_info_ptr->peerMac, + &pDisassocInd->peer_macaddr); + cdf_copy_macaddr(&roam_info_ptr->bssid, + &pDisassocInd->bssid); status = csr_roam_call_callback(mac_ctx, sessionId, roam_info_ptr, 0, eCSR_ROAM_INFRA_IND, @@ -10172,8 +10171,8 @@ csr_roam_chk_lnk_disassoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) cmd.sessionId = (uint8_t) sessionId; cmd.u.roamCmd.roamReason = eCsrForcedDeauthSta; cdf_mem_copy(cmd.u.roamCmd.peerMac, - pDisassocInd->peerMacAddr, - sizeof(tSirMacAddr)); + pDisassocInd->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE); csr_roam_remove_duplicate_command(mac_ctx, sessionId, &cmd, eCsrForcedDeauthSta); } @@ -11391,9 +11390,8 @@ CDF_STATUS csr_roam_lost_link(tpAniSirGlobal pMac, uint32_t sessionId, roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode; if (eWNI_SME_DISASSOC_IND == type) { /* staMacAddr */ - cdf_mem_copy(roamInfo.peerMac.bytes, - pDisassocIndMsg->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roamInfo.peerMac, + &pDisassocIndMsg->peer_macaddr); roamInfo.staId = (uint8_t) pDisassocIndMsg->staId; roamInfo.reasonCode = pDisassocIndMsg->reasonCode; } else if (eWNI_SME_DEAUTH_IND == type) { @@ -14284,17 +14282,15 @@ CDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac, pMsg->messageType = eWNI_SME_DISASSOC_CNF; pMsg->statusCode = eSIR_SME_SUCCESS; pMsg->length = sizeof(tSirSmeDisassocCnf); - cdf_mem_copy(pMsg->peer_macaddr.bytes, - pDisassocInd->peerMacAddr, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->peer_macaddr, + &pDisassocInd->peer_macaddr); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); break; } - cdf_mem_copy(pMsg->bssid.bytes, pDisassocInd->bssId, - CDF_MAC_ADDR_SIZE); + cdf_copy_macaddr(&pMsg->bssid, &pDisassocInd->bssid); status = CDF_STATUS_SUCCESS; if (!CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_free(pMsg); -- cgit v1.2.3 From f06a5cf8c8deb9e483dc1ec508b331d8cd9f20e1 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 5 Jan 2016 19:41:27 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocRsp Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocRsp. Change-Id: Ia196615e99506b4fa80a7d611cdefd2e7d2150fa CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 2 +- core/mac/src/pe/lim/lim_process_auth_frame.c | 18 +++++----- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 41 +++++++++++----------- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 2 +- core/mac/src/pe/lim/lim_send_management_frames.c | 6 ++-- core/mac/src/pe/lim/lim_types.h | 4 +-- core/sme/src/csr/csr_api_roam.c | 7 ++-- 7 files changed, 39 insertions(+), 41 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index facb9d0eba1d..8fb581b9dc67 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1377,7 +1377,7 @@ typedef struct sSirSmeDisassocRsp { uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ tSirResultCodes statusCode; - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; tAniStaStatStruct perStaStats; /* STA stats */ uint16_t staId; } cdf_packed tSirSmeDisassocRsp, *tpSirSmeDisassocRsp; diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c index e292e2c0dfcb..36bed2d9d142 100644 --- a/core/mac/src/pe/lim/lim_process_auth_frame.c +++ b/core/mac/src/pe/lim/lim_process_auth_frame.c @@ -507,17 +507,15 @@ lim_process_auth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, if (pMlmDisassocReq && (cdf_mem_compare - ((uint8_t *) pHdr->sa, - (uint8_t *) &pMlmDisassocReq->peerMacAddr, - sizeof(tSirMacAddr)))) { + ((uint8_t *) pHdr->sa, + &pMlmDisassocReq->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE))) { PELOGE(lim_log - (pMac, LOGE, - FL("TODO:Ack for disassoc " - "frame is pending Issue delsta for " - MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(pMlmDisassocReq-> - peerMacAddr)); - ) + (pMac, LOGE, + FL("TODO:Ack for disassoc frame is pending Issue delsta for " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pMlmDisassocReq-> + peer_macaddr.bytes));) lim_process_disassoc_ack_timeout(pMac); isConnected = eSIR_FALSE; } diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 5f0f4ab5f1ba..4d16c164c892 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1584,7 +1584,7 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, CDF_STATUS suspend_status, uint32_t *msg) { uint16_t aid; - tSirMacAddr curr_bssid; + struct cdf_mac_addr curr_bssid; tpDphHashNode stads; tLimMlmDisassocReq *mlm_disassocreq; tLimMlmDisassocCnf mlm_disassoccnf; @@ -1614,19 +1614,19 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, "mlmstate %d from: " MAC_ADDRESS_STR), mlm_disassocreq->sessionId, GET_LIM_SYSTEM_ROLE(session), session->limMlmState, - MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_disassocreq->peer_macaddr.bytes)); - sir_copy_mac_addr(curr_bssid, session->bssId); + cdf_mem_copy(curr_bssid.bytes, session->bssId, CDF_MAC_ADDR_SIZE); switch (GET_LIM_SYSTEM_ROLE(session)) { case eLIM_STA_ROLE: case eLIM_BT_AMP_STA_ROLE: - if (!cdf_mem_compare(mlm_disassocreq->peerMacAddr, - curr_bssid, sizeof(tSirMacAddr))) { + if (!cdf_is_macaddr_equal(&mlm_disassocreq->peer_macaddr, + &curr_bssid)) { lim_log(mac_ctx, LOGW, FL("received MLM_DISASSOC_REQ with invalid BSS id")); lim_print_mac_addr(mac_ctx, - mlm_disassocreq->peerMacAddr, LOGW); + mlm_disassocreq->peer_macaddr.bytes, LOGW); /* * Disassociation response due to host triggered @@ -1643,7 +1643,8 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, lim_log(mac_ctx, LOG1, FL("send disassoc rsp with ret code %d for" MAC_ADDRESS_STR), eSIR_SME_DEAUTH_STATUS, - MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + MAC_ADDR_ARRAY( + mlm_disassocreq->peer_macaddr.bytes)); sme_disassoc_rsp->messageType = eWNI_SME_DISASSOC_RSP; sme_disassoc_rsp->length = sizeof(tSirSmeDisassocRsp); @@ -1652,9 +1653,8 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, sme_disassoc_rsp->transactionId = 0; sme_disassoc_rsp->statusCode = eSIR_SME_DEAUTH_STATUS; - cdf_mem_copy(sme_disassoc_rsp->peerMacAddr, - mlm_disassocreq->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&sme_disassoc_rsp->peer_macaddr, + &mlm_disassocreq->peer_macaddr); msg = (uint32_t *)sme_disassoc_rsp; lim_send_sme_disassoc_deauth_ntf(mac_ctx, @@ -1683,7 +1683,8 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, * Check if there exists a context for the peer entity * to be disassociated with. */ - stads = dph_lookup_hash_entry(mac_ctx, mlm_disassocreq->peerMacAddr, + stads = dph_lookup_hash_entry(mac_ctx, + mlm_disassocreq->peer_macaddr.bytes, &aid, &session->dph.dphHashTable); if (stads) mlm_state = stads->mlmStaContext.mlmState; @@ -1699,7 +1700,7 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, */ lim_log(mac_ctx, LOGW, FL("Invalid MLM_DISASSOC_REQ, Addr= " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_disassocreq->peer_macaddr.bytes)); if (stads != NULL) lim_log(mac_ctx, LOGE, FL("Sta MlmState : %d"), stads->mlmStaContext.mlmState); @@ -1735,7 +1736,7 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, lim_send_disassoc_mgmt_frame(mac_ctx, mlm_disassocreq->reasonCode, - mlm_disassocreq->peerMacAddr, session, true); + mlm_disassocreq->peer_macaddr.bytes, session, true); /* * Abort Tx so that data frames won't be sent to the AP * after sending Disassoc. @@ -1760,8 +1761,8 @@ lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx, end: cdf_mem_copy((uint8_t *) &mlm_disassoccnf.peerMacAddr, - (uint8_t *) mlm_disassocreq->peerMacAddr, - sizeof(tSirMacAddr)); + (uint8_t *) mlm_disassocreq->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE); mlm_disassoccnf.aid = mlm_disassocreq->aid; mlm_disassoccnf.disassocTrigger = mlm_disassocreq->disassocTrigger; @@ -1795,8 +1796,8 @@ bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal mac_ctx, disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; if ((disassoc_req && (cdf_mem_compare((uint8_t *) sta_mac, - (uint8_t *) &disassoc_req->peerMacAddr, - sizeof(tSirMacAddr)))) || + (uint8_t *) &disassoc_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE))) || (deauth_req && (cdf_mem_compare((uint8_t *) sta_mac, (uint8_t *) &deauth_req->peer_macaddr.bytes, CDF_MAC_ADDR_SIZE)))) { @@ -1829,8 +1830,8 @@ void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal mac_ctx, mlm_disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; if (mlm_disassoc_req && (cdf_mem_compare((uint8_t *) sta_mac, - (uint8_t *) &mlm_disassoc_req->peerMacAddr, - sizeof(tSirMacAddr)))) { + (uint8_t *) &mlm_disassoc_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE))) { if (clean_rx_path) { lim_process_disassoc_ack_timeout(mac_ctx); } else { @@ -1907,7 +1908,7 @@ lim_process_mlm_disassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) lim_log(mac_ctx, LOG1, FL("Process disassoc req, sessionID %d from: "MAC_ADDRESS_STR), mlm_disassoc_req->sessionId, - MAC_ADDR_ARRAY(mlm_disassoc_req->peerMacAddr)); + MAC_ADDR_ARRAY(mlm_disassoc_req->peer_macaddr.bytes)); lim_process_mlm_disassoc_req_ntf(mac_ctx, CDF_STATUS_SUCCESS, (uint32_t *) msg_buf); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 26a93d27b0f1..d087d9d9136c 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2549,7 +2549,7 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu return; } - cdf_mem_copy((uint8_t *) &pMlmDisassocReq->peerMacAddr, + cdf_mem_copy((uint8_t *) &pMlmDisassocReq->peer_macaddr, (uint8_t *) &smeDisassocReq.peerMacAddr, sizeof(tSirMacAddr)); diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index a8df2cca966d..a4ae823af135 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -3186,7 +3186,7 @@ CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx) } sta_ds = dph_lookup_hash_entry(mac_ctx, - disassoc_req->peerMacAddr, &aid, + disassoc_req->peer_macaddr.bytes, &aid, &pe_session->dph.dphHashTable); if (sta_ds == NULL) { lim_log(mac_ctx, LOGE, FL("StaDs Null")); @@ -3250,8 +3250,8 @@ CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx) } end: cdf_mem_copy((uint8_t *) &disassoc_cnf.peerMacAddr, - (uint8_t *) disassoc_req->peerMacAddr, - sizeof(tSirMacAddr)); + (uint8_t *) disassoc_req->peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE); disassoc_cnf.aid = disassoc_req->aid; disassoc_cnf.disassocTrigger = disassoc_req->disassocTrigger; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 176a1113f5d6..a51c3d5f0ca5 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -333,7 +333,7 @@ typedef struct sLimMlmDeauthInd { } tLimMlmDeauthInd, *tpLimMlmDeauthInd; typedef struct sLimMlmDisassocReq { - tSirMacAddr peerMacAddr; + struct cdf_mac_addr peer_macaddr; uint16_t reasonCode; uint16_t disassocTrigger; uint16_t aid; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index b103e1cfd0c6..150f3c5e4329 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -10335,9 +10335,8 @@ csr_roam_chk_lnk_disassoc_rsp(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) if (CSR_IS_INFRA_AP(&session->connectedProfile)) { roam_info_ptr = &roam_info; roam_info_ptr->u.pConnectedProfile = &session->connectedProfile; - cdf_mem_copy(roam_info_ptr->peerMac.bytes, - pDisassocRsp->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&roam_info_ptr->peerMac, + &pDisassocRsp->peer_macaddr); roam_info_ptr->reasonCode = eCSR_ROAM_RESULT_FORCED; roam_info_ptr->statusCode = pDisassocRsp->statusCode; status = csr_roam_call_callback(mac_ctx, sessionId, @@ -17885,7 +17884,7 @@ static void csr_ser_des_unpack_diassoc_rsp(uint8_t *pBuf, tSirSmeDisassocRsp *pR pBuf += 2; cdf_get_u32(pBuf, (uint32_t *) &pRsp->statusCode); pBuf += 4; - cdf_mem_copy(pRsp->peerMacAddr, pBuf, 6); + cdf_mem_copy(pRsp->peer_macaddr.bytes, pBuf, CDF_MAC_ADDR_SIZE); } } -- cgit v1.2.3 From 7907a2402fff250bf373674dd1675a7c7628bac0 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 5 Jan 2016 22:43:30 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocReq Replace tSirMacAddr with cdf_mac_addr in tSirSmeDisassocReq. Change-Id: I9d0b77e0ce624c48ca0fea2774c0f63285793cee CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 4 ++-- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 22 +++++++++++----------- core/mac/src/pe/lim/lim_sme_req_utils.c | 4 ++-- core/sme/src/csr/csr_api_roam.c | 18 ++++++++---------- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 8fb581b9dc67..d5d450c1ce1b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1241,8 +1241,8 @@ typedef struct sSirSmeDisassocReq { uint16_t length; uint8_t sessionId; /* Session ID */ uint16_t transactionId; /* Transaction ID for cmd */ - tSirMacAddr bssId; /* Peer BSSID */ - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; /* Peer BSSID */ + struct cdf_mac_addr peer_macaddr; uint16_t reasonCode; /* 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 */ diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index d087d9d9136c..b3ddfcd1e752 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -2396,13 +2396,13 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu } psessionEntry = pe_find_session_by_bssid(pMac, - smeDisassocReq.bssId, + smeDisassocReq.bssid.bytes, &sessionId); if (psessionEntry == NULL) { lim_log(pMac, LOGE, FL("session does not exist for given bssId " MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(smeDisassocReq.bssId)); + MAC_ADDR_ARRAY(smeDisassocReq.bssid.bytes)); retCode = eSIR_SME_INVALID_PARAMETERS; disassocTrigger = eLIM_HOST_DISASSOC; goto sendDisassoc; @@ -2412,7 +2412,7 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu MAC_ADDRESS_STR), smesessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), smeDisassocReq.reasonCode, pMac->lim.gLimSmeState, - MAC_ADDR_ARRAY(smeDisassocReq.peerMacAddr)); + MAC_ADDR_ARRAY(smeDisassocReq.peer_macaddr.bytes)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, psessionEntry, @@ -2549,9 +2549,8 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu return; } - cdf_mem_copy((uint8_t *) &pMlmDisassocReq->peer_macaddr, - (uint8_t *) &smeDisassocReq.peerMacAddr, - sizeof(tSirMacAddr)); + cdf_copy_macaddr(&pMlmDisassocReq->peer_macaddr, + &smeDisassocReq.peer_macaddr); pMlmDisassocReq->reasonCode = reasonCode; pMlmDisassocReq->disassocTrigger = disassocTrigger; @@ -2565,16 +2564,17 @@ static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBu sendDisassoc: if (psessionEntry) - lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr, + lim_send_sme_disassoc_ntf(pMac, + smeDisassocReq.peer_macaddr.bytes, retCode, disassocTrigger, 1, smesessionId, smetransactionId, psessionEntry); else - lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr, - retCode, - disassocTrigger, - 1, smesessionId, smetransactionId, NULL); + lim_send_sme_disassoc_ntf(pMac, + smeDisassocReq.peer_macaddr.bytes, + retCode, disassocTrigger, 1, + smesessionId, smetransactionId, NULL); } /*** end __lim_process_sme_disassoc_req() ***/ diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c index fd82e7cbd62d..9f3825150ee5 100644 --- a/core/mac/src/pe/lim/lim_sme_req_utils.c +++ b/core/mac/src/pe/lim/lim_sme_req_utils.c @@ -585,8 +585,8 @@ lim_is_sme_disassoc_req_valid(tpAniSirGlobal pMac, tpSirSmeDisassocReq pDisassocReq, tpPESession psessionEntry) { - if (lim_is_group_addr(pDisassocReq->peerMacAddr) && - !lim_is_addr_bc(pDisassocReq->peerMacAddr)) + if (cdf_is_macaddr_group(&pDisassocReq->peer_macaddr) && + !cdf_is_macaddr_broadcast(&pDisassocReq->peer_macaddr)) return false; return true; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 150f3c5e4329..c11ced3ae4b5 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14052,19 +14052,17 @@ CDF_STATUS csr_send_mb_disassoc_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, pMsg->transactionId = 0; if ((pSession->pCurRoamProfile != NULL) && (CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) { - cdf_mem_copy(&pMsg->bssId, + cdf_mem_copy(&pMsg->bssid.bytes, &pSession->selfMacAddr, - sizeof(tSirMacAddr)); - cdf_mem_copy(&pMsg->peerMacAddr, + CDF_MAC_ADDR_SIZE); + cdf_mem_copy(&pMsg->peer_macaddr.bytes, bssId, - sizeof(tSirMacAddr)); + CDF_MAC_ADDR_SIZE); } else { - cdf_mem_copy(&pMsg->bssId, - bssId, - sizeof(tSirMacAddr)); - cdf_mem_copy(&pMsg->peerMacAddr, - bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(&pMsg->bssid.bytes, + bssId, CDF_MAC_ADDR_SIZE); + cdf_mem_copy(&pMsg->peer_macaddr.bytes, + bssId, CDF_MAC_ADDR_SIZE); } pMsg->reasonCode = reasonCode; /* -- cgit v1.2.3 From 2bac5d24b1315a33b4e5b165a9a2d9f9a7ae78cb Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 5 Jan 2016 23:04:28 -0800 Subject: qcacld-3.0: Replace tSirMacAddr with cdf_mac_addr in tSirSmeAssocCnf Replace tSirMacAddr with cdf_mac_addr in tSirSmeAssocCnf. Change-Id: I0b267ad09aac1f44079477cfde8d13265c1f2264 CRs-Fixed: 898864 --- core/mac/inc/sir_api.h | 6 +++--- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 16 ++++++++-------- core/sme/src/csr/csr_api_roam.c | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d5d450c1ce1b..7118f800ed97 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1150,10 +1150,10 @@ typedef struct sSirSmeAssocCnf { uint16_t messageType; /* eWNI_SME_ASSOC_CNF */ uint16_t length; tSirResultCodes statusCode; - tSirMacAddr bssId; /* Self BSSID */ - tSirMacAddr peerMacAddr; + struct cdf_mac_addr bssid; /* Self BSSID */ + struct cdf_mac_addr peer_macaddr; uint16_t aid; - tSirMacAddr alternateBssId; + struct cdf_mac_addr alternate_bssid; uint8_t alternateChannelId; } tSirSmeAssocCnf, *tpSirSmeAssocCnf; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index b3ddfcd1e752..e11f9ac36e3f 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -358,7 +358,7 @@ __lim_fresh_scan_reqd(tpAniSirGlobal mac_ctx, uint8_t return_fresh_results) static inline uint8_t __lim_is_sme_assoc_cnf_valid(tpSirSmeAssocCnf pAssocCnf) { - if (lim_is_group_addr(pAssocCnf->peerMacAddr)) + if (cdf_is_macaddr_group(&pAssocCnf->peer_macaddr)) return false; else return true; @@ -3526,7 +3526,7 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, goto end; } - session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssId, + session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssid.bytes, &session_id); if (session_entry == NULL) { lim_log(mac_ctx, LOGE, @@ -3551,13 +3551,13 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, lim_log(mac_ctx, LOGE, FL( "Rcvd invalid msg %X due to no STA ctx, aid %d, peer "), msg_type, assoc_cnf.aid); - lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + lim_print_mac_addr(mac_ctx, assoc_cnf.peer_macaddr.bytes, LOG1); /* * send a DISASSOC_IND message to WSM to make sure * the state in WSM and LIM is the same */ - lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peerMacAddr, + lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peer_macaddr.bytes, eSIR_SME_STA_NOT_ASSOCIATED, eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid, session_entry->smeSessionId, @@ -3566,12 +3566,12 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, goto end; } if (!cdf_mem_compare((uint8_t *)sta_ds->staAddr, - (uint8_t *) assoc_cnf.peerMacAddr, - sizeof(tSirMacAddr))) { + (uint8_t *) assoc_cnf.peer_macaddr.bytes, + CDF_MAC_ADDR_SIZE)) { lim_log(mac_ctx, LOG1, FL( "peerMacAddr mismatched for aid %d, peer "), assoc_cnf.aid); - lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + lim_print_mac_addr(mac_ctx, assoc_cnf.peer_macaddr.bytes, LOG1); goto end; } @@ -3584,7 +3584,7 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type, "not in MLM_WT_ASSOC_CNF_STATE, for aid %d, peer" "StaD mlmState : %d"), assoc_cnf.aid, sta_ds->mlmStaContext.mlmState); - lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1); + lim_print_mac_addr(mac_ctx, assoc_cnf.peer_macaddr.bytes, LOG1); goto end; } /* diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index c11ced3ae4b5..af8d356d8415 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -14355,16 +14355,16 @@ CDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocIn else pMsg->statusCode = eSIR_SME_ASSOC_REFUSED; /* bssId */ - cdf_mem_copy(pMsg->bssId, pAssocInd->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->bssid.bytes, pAssocInd->bssId, + CDF_MAC_ADDR_SIZE); /* peerMacAddr */ - cdf_mem_copy(pMsg->peerMacAddr, pAssocInd->peerMacAddr, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->peer_macaddr.bytes, pAssocInd->peerMacAddr, + CDF_MAC_ADDR_SIZE); /* aid */ pMsg->aid = pAssocInd->aid; /* alternateBssId */ - cdf_mem_copy(pMsg->alternateBssId, pAssocInd->bssId, - sizeof(tSirMacAddr)); + cdf_mem_copy(pMsg->alternate_bssid.bytes, pAssocInd->bssId, + CDF_MAC_ADDR_SIZE); /* alternateChannelId */ pMsg->alternateChannelId = 11; /* pMsg is freed by cds_send_mb_message_to_mac in anycase*/ -- cgit v1.2.3 From 666bbb33749e62a4d21ca1a8075f49b74f771b0b Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Tue, 13 Oct 2015 17:14:08 -0700 Subject: qcacld-3.0 : Remove the local regdomain mapping Remove the local country to regdomain mapping in the driver. Return a fixed regdomain index 0 to the caller. Also update copyright for cds_regdomain.h for 2015. Change-Id: I33e0a861b0a3bd95b20becb2d765b8300688ec4c CRs-Fixed: 856727 --- core/cds/inc/cds_reg_service.h | 49 +++--- core/cds/inc/cds_regdomain.h | 20 +-- core/cds/src/cds_reg_service.c | 341 ++++++----------------------------------- core/mac/inc/sir_api.h | 2 - core/sap/src/sap_internal.h | 2 +- core/sme/inc/sme_api.h | 4 +- core/sme/src/common/sme_api.c | 112 ++------------ 7 files changed, 94 insertions(+), 436 deletions(-) diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h index 02a6965c5c4c..d69c877d1a21 100644 --- a/core/cds/inc/cds_reg_service.h +++ b/core/cds/inc/cds_reg_service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -206,10 +206,6 @@ typedef struct { tPowerdBm pwrLimit; } sRegulatoryChannel; -typedef struct { - sRegulatoryChannel channels[NUM_RF_CHANNELS]; -} sRegulatoryDomain; - typedef struct { uint16_t targetFreq; uint16_t channelNum; @@ -220,6 +216,27 @@ typedef struct { tPowerdBm pwr; } tChannelListWithPower; +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 def_country[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; +}; + typedef enum { COUNTRY_INIT, COUNTRY_IE, @@ -255,11 +272,6 @@ enum channel_width { */ typedef uint8_t country_code_t[CDS_COUNTRY_CODE_LEN + 1]; -typedef struct { - sRegulatoryDomain regDomains[REGDOMAIN_COUNT]; - country_code_t default_country; -} t_reg_table; - CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *pRegDomain, const country_code_t countryCode, @@ -278,6 +290,15 @@ CDF_STATUS cds_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); CHANNEL_STATE cds_get_channel_state(uint32_t rfChannel); +CDF_STATUS cds_regulatory_init(void); +CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region); +CDF_STATUS cds_set_dfs_region(uint8_t dfs_region); +bool cds_is_dsrc_channel(uint16_t); +CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, + enum channel_width ch_width); +enum channel_width cds_get_max_channel_bw(uint32_t chan_num); + + #define CDS_IS_DFS_CH(channel) (cds_get_channel_state((channel)) == \ CHANNEL_STATE_DFS) @@ -299,12 +320,4 @@ CHANNEL_STATE cds_get_channel_state(uint32_t rfChannel); (ch1 && ch2 && \ (CDS_IS_CHANNEL_5GHZ(ch1) == CDS_IS_CHANNEL_5GHZ(ch2))) -CDF_STATUS cds_regulatory_init(void); -CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region); -CDF_STATUS cds_set_dfs_region(uint8_t dfs_region); -bool cds_is_dsrc_channel(uint16_t); -CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, - enum channel_width ch_width); -enum channel_width cds_get_max_channel_bw(uint32_t chan_num); - #endif /* __CDS_REG_SERVICE_H */ diff --git a/core/cds/inc/cds_regdomain.h b/core/cds/inc/cds_regdomain.h index 28a22904024b..7f40344e46ae 100644 --- a/core/cds/inc/cds_regdomain.h +++ b/core/cds/inc/cds_regdomain.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -301,24 +301,6 @@ typedef struct { uint8_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 */ diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index 0e0b10ee5c4c..ddbec514f1fe 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -49,20 +49,13 @@ #define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR #endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) -#define IEEE80211_CHAN_NO_20MHZ (1<<11) -#define IEEE80211_CHAN_NO_10MHZ (1<<12) -#endif - -static v_REGDOMAIN_t temp_reg_domain = REGDOMAIN_COUNT; - /* true if init happens thru init time driver hint */ static bool init_by_driver = false; /* true if init happens thru init time callback from regulatory core. this should be set to true during driver reload */ static bool init_by_reg_core = false; -#define REG_WAIT_TIME 50 +#define REG_WAIT_TIME 50 #define REG_RULE_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) @@ -70,7 +63,7 @@ static bool init_by_reg_core = false; 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) + 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) @@ -138,161 +131,6 @@ static const struct ieee80211_regdomain cds_world_regdom_67_68_6A_6C = { } }; -typedef struct { - uint8_t regDomain; - country_code_t countryCode; -} CountryInfo_t; - -typedef struct { - uint16_t countryCount; - CountryInfo_t countryInfo[MAX_COUNTRY_COUNT]; -} CountryInfoTable_t; - -static CountryInfoTable_t country_info_table = { - /* 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 */ - } -}; - const tRfChannelProps rf_channels[NUM_RF_CHANNELS] = { {2412, 1}, {2417, 2}, @@ -390,14 +228,10 @@ const tRfChannelProps rf_channels[NUM_RF_CHANNELS] = { {5755, 151}, {5775, 155}, {5795, 159}, - {5815, 163, }, + {5815, 163}, }; -static t_reg_table reg_table; - -const sRegulatoryChannel *reg_channels = - reg_table.regDomains[0].channels; - +sRegulatoryChannel reg_channels[NUM_RF_CHANNELS]; /** * cds_is_wwr_sku() - is regdomain world sku @@ -616,17 +450,25 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * */ CDF_STATUS cds_read_default_country(country_code_t default_country) { - CDF_STATUS status = CDF_STATUS_SUCCESS; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + if (!hdd_ctx) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "invalid hdd_ctx pointer"); + return CDF_STATUS_E_FAULT; + } memcpy(default_country, - reg_table.default_country, + hdd_ctx->reg.def_country, sizeof(country_code_t)); - pr_info("DefaultCountry is %c%c\n", - default_country[0], - default_country[1]); + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, + "default country is %c%c\n", + default_country[0], + default_country[1]); - return status; + return CDF_STATUS_SUCCESS; } /** @@ -791,31 +633,31 @@ static int cds_bw20_ch_index_to_bw40_ch_index(int k) */ CDF_STATUS cds_set_dfs_region(uint8_t dfs_region) { - hdd_context_t *hdd_ctx_ptr = NULL; + hdd_context_t *hdd_ctx; - hdd_ctx_ptr = cds_get_context(CDF_MODULE_ID_HDD); + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL == hdd_ctx_ptr) + if (NULL == hdd_ctx) return CDF_STATUS_E_EXISTS; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) - hdd_ctx_ptr->reg.dfs_region = dfs_region; + hdd_ctx->reg.dfs_region = dfs_region; #else /* remap the ctl code to dfs region code */ - switch (hdd_ctx_ptr->reg.ctl_5g) { + switch (hdd_ctx->reg.ctl_5g) { case FCC: - hdd_ctx_ptr->reg.dfs_region = DFS_FCC_DOMAIN; + hdd_ctx->reg.dfs_region = DFS_FCC_DOMAIN; break; case ETSI: - hdd_ctx_ptr->reg.dfs_region = DFS_ETSI_DOMAIN; + hdd_ctx->reg.dfs_region = DFS_ETSI_DOMAIN; break; case MKK: - hdd_ctx_ptr->reg.dfs_region = DFS_MKK4_DOMAIN; + hdd_ctx->reg.dfs_region = DFS_MKK4_DOMAIN; break; default: /* set default dfs_region to FCC */ - hdd_ctx_ptr->reg.dfs_region = DFS_FCC_DOMAIN; + hdd_ctx->reg.dfs_region = DFS_FCC_DOMAIN; break; } #endif @@ -831,14 +673,14 @@ CDF_STATUS cds_set_dfs_region(uint8_t dfs_region) */ CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region) { - hdd_context_t *hdd_ctx_ptr = NULL; + hdd_context_t *hdd_ctx; - hdd_ctx_ptr = cds_get_context(CDF_MODULE_ID_HDD); + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (NULL == hdd_ctx_ptr) + if (NULL == hdd_ctx) return CDF_STATUS_E_EXISTS; - *dfs_region = hdd_ctx_ptr->reg.dfs_region; + *dfs_region = hdd_ctx->reg.dfs_region; return CDF_STATUS_SUCCESS; } @@ -856,10 +698,8 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, country_code, v_CountryInfoSource_t source) { - v_CONTEXT_t cds_context = NULL; hdd_context_t *hdd_ctx = NULL; struct wiphy *wiphy = NULL; - int i; if (NULL == reg_domain_ptr) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, @@ -867,7 +707,10 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, return CDF_STATUS_E_FAULT; } - *reg_domain_ptr = REGDOMAIN_COUNT; + *reg_domain_ptr = 0; + + if (COUNTRY_QUERY == source) + return CDF_STATUS_SUCCESS; if (NULL == country_code) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, @@ -875,18 +718,13 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, return CDF_STATUS_E_FAULT; } - if (0 == country_info_table.countryCount) { + if (cds_is_driver_recovering()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - ("Reg domain table is empty")); - return CDF_STATUS_E_EMPTY; + "SSR in progress, return"); + return CDF_STATUS_SUCCESS; } - cds_context = cds_get_global_context(); - - if (NULL != cds_context) - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - else - return CDF_STATUS_E_EXISTS; + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (NULL == hdd_ctx) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, @@ -896,37 +734,6 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, wiphy = hdd_ctx->wiphy; - if (cds_is_driver_recovering()) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - "SSR in progress, return"); - *reg_domain_ptr = temp_reg_domain; - return CDF_STATUS_SUCCESS; - } - - temp_reg_domain = REGDOMAIN_COUNT; - for (i = 0; i < country_info_table.countryCount && - REGDOMAIN_COUNT == temp_reg_domain; i++) { - if (memcmp(country_code, - country_info_table.countryInfo[i].countryCode, - CDS_COUNTRY_CODE_LEN) == 0) { - - temp_reg_domain = - country_info_table.countryInfo[i].regDomain; - break; - } - } - - if (REGDOMAIN_COUNT == temp_reg_domain) { - CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - ("Country does not map to any Regulatory domain")); - temp_reg_domain = REGDOMAIN_WORLD; - } - - if (COUNTRY_QUERY == source) { - *reg_domain_ptr = temp_reg_domain; - return CDF_STATUS_SUCCESS; - } - if ((COUNTRY_INIT == source) && (false == init_by_reg_core)) { init_by_driver = true; if (('0' != country_code[0]) || ('0' != country_code[1])) { @@ -940,7 +747,6 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, NL80211_USER_REG_HINT_USER); } - *reg_domain_ptr = temp_reg_domain; return CDF_STATUS_SUCCESS; } @@ -981,7 +787,8 @@ bool cds_is_dsrc_channel(uint16_t center_freq) * Return: int */ static int cds_process_regulatory_data(struct wiphy *wiphy, - uint8_t band_capability, bool reset) + uint8_t band_capability, + bool reset) { int i, j, m; int k = 0, n = 0; @@ -1028,13 +835,8 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, n = cds_bw20_ch_index_to_bw40_ch_index(k); chan = &(wiphy->bands[i]->channels[j]); - temp_chan_k = - &(reg_table.regDomains[temp_reg_domain]. - channels[k]); - - temp_chan_n = - &(reg_table.regDomains[temp_reg_domain]. - channels[n]); + temp_chan_k = &(reg_channels[k]); + temp_chan_n = &(reg_channels[n]); if ((!reset) && #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) @@ -1173,8 +975,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, if (0 == (hdd_ctx->reg.eeprom_rd_ext & (1 << WHAL_REG_EXT_FCC_CH_144))) { - temp_chan = &(reg_table.regDomains[temp_reg_domain]. - channels[RF_CHAN_144]); + temp_chan = &(reg_channels[RF_CHAN_144]); temp_chan->enabled = CHANNEL_STATE_DISABLE; } @@ -1225,8 +1026,6 @@ void __hdd_reg_notifier(struct wiphy *wiphy, { hdd_context_t *hdd_ctx = wiphy_priv(wiphy); eCsrBand band_capability = eCSR_BAND_ALL; - country_code_t country_code; - int i; bool vht80_allowed; bool reset = false; @@ -1288,9 +1087,9 @@ void __hdd_reg_notifier(struct wiphy *wiphy, #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) + if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) #endif - reset = true; + reset = true; } else if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) hdd_ctx->reg.cc_src = COUNTRY_CODE_SET_BY_DRIVER; else { @@ -1305,31 +1104,11 @@ void __hdd_reg_notifier(struct wiphy *wiphy, #endif } - /* first lookup the country in the local database */ - country_code[0] = request->alpha2[0]; - country_code[1] = request->alpha2[1]; - hdd_ctx->reg.alpha2[0] = request->alpha2[0]; hdd_ctx->reg.alpha2[1] = request->alpha2[1]; cds_update_regulatory_info(hdd_ctx); - temp_reg_domain = REGDOMAIN_COUNT; - for (i = 0; i < country_info_table.countryCount && - REGDOMAIN_COUNT == temp_reg_domain; i++) { - if (memcmp(country_code, - country_info_table.countryInfo[i].countryCode, - CDS_COUNTRY_CODE_LEN) == 0) { - - temp_reg_domain = - country_info_table.countryInfo[i].regDomain; - break; - } - } - - if (REGDOMAIN_COUNT == temp_reg_domain) - temp_reg_domain = REGDOMAIN_WORLD; - vht80_allowed = hdd_ctx->isVHT80Allowed; if (cds_process_regulatory_data(wiphy, band_capability, reset) == 0) { @@ -1342,16 +1121,8 @@ void __hdd_reg_notifier(struct wiphy *wiphy, if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) complete(&hdd_ctx->reg_init); - if (request->alpha2[0] == '0' - && request->alpha2[1] == '0') { - sme_generic_change_country_code(hdd_ctx->hHal, - country_code, - REGDOMAIN_COUNT); - } else { - sme_generic_change_country_code(hdd_ctx->hHal, - country_code, - temp_reg_domain); - } + sme_generic_change_country_code(hdd_ctx->hHal, + hdd_ctx->reg.alpha2); cds_fill_and_send_ctl_to_fw(&hdd_ctx->reg); @@ -1386,21 +1157,15 @@ void hdd_reg_notifier(struct wiphy *wiphy, */ CDF_STATUS cds_regulatory_init(void) { - v_CONTEXT_t cds_context = NULL; hdd_context_t *hdd_ctx = NULL; struct wiphy *wiphy = NULL; int ret_val = 0; struct regulatory *reg_info; - cds_context = cds_get_global_context(); - - if (!cds_context) - return CDF_STATUS_E_FAULT; - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, - ("Invalid pHddCtx pointer")); + "invalid hdd_ctx pointer"); return CDF_STATUS_E_FAULT; } @@ -1410,8 +1175,6 @@ CDF_STATUS cds_regulatory_init(void) cds_regulatory_wiphy_init(hdd_ctx, reg_info, wiphy); - temp_reg_domain = REGDOMAIN_WORLD; - if (cds_process_regulatory_data(wiphy, hdd_ctx->config-> nBandCapability, true) != 0) { @@ -1428,8 +1191,8 @@ CDF_STATUS cds_regulatory_init(void) return ret_val; } - reg_table.default_country[0] = reg_info->alpha2[0]; - reg_table.default_country[1] = reg_info->alpha2[1]; + hdd_ctx->reg.def_country[0] = reg_info->alpha2[0]; + hdd_ctx->reg.def_country[1] = reg_info->alpha2[1]; init_completion(&hdd_ctx->reg_init); @@ -1454,8 +1217,6 @@ CDF_STATUS cds_set_reg_domain(void *client_ctxt, v_REGDOMAIN_t reg_domain) return CDF_STATUS_E_INVAL; } - reg_channels = reg_table.regDomains[reg_domain].channels; - return CDF_STATUS_SUCCESS; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 7118f800ed97..93c71024a27e 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -1823,11 +1823,9 @@ struct ani_roc_req { /* generic country code change request MSG structure */ typedef struct sAniGenericChangeCountryCodeReq { - /* Common for all types are requests */ uint16_t msgType; /* message type is same as the request type */ uint16_t msgLen; /* length of the entire request */ uint8_t countryCode[WNI_CFG_COUNTRY_CODE_LEN]; /* 3 char country code */ - uint16_t domain_index; } tAniGenericChangeCountryCodeReq, *tpAniGenericChangeCountryCodeReq; /** diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 1e88ffccf549..3ba7b0a410d1 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -76,7 +76,7 @@ extern "C" { #define SAP_CHAN_PREFERRED_INDOOR 1 #define SAP_CHAN_PREFERRED_OUTDOOR 2 -extern const sRegulatoryChannel *reg_channels; +extern const sRegulatoryChannel reg_channels[NUM_RF_CHANNELS]; /*---------------------------------------------------------------------------- * Typedefs diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 7cc219d01cb3..7b69bbeaf287 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -404,9 +404,7 @@ CDF_STATUS sme_change_country_code(tHalHandle hHal, tAniBool countryFromUserSpace, tAniBool sendRegHint); CDF_STATUS sme_generic_change_country_code(tHalHandle hHal, - uint8_t *pCountry, - v_REGDOMAIN_t reg_domain); - + uint8_t *pCountry); CDF_STATUS sme_dhcp_start_ind(tHalHandle hHal, uint8_t device_mode, uint8_t *macAddr, uint8_t sessionId); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index b61de7734763..41d15b960acc 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -5042,8 +5042,7 @@ CDF_STATUS sme_change_country_code(tHalHandle hHal, -----------------------------------------------------------------------------*/ CDF_STATUS sme_generic_change_country_code(tHalHandle hHal, - uint8_t *pCountry, - v_REGDOMAIN_t reg_domain) + uint8_t *pCountry) { CDF_STATUS status = CDF_STATUS_E_FAILURE; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -5072,8 +5071,7 @@ CDF_STATUS sme_generic_change_country_code(tHalHandle hHal, pMsg->msgLen = (uint16_t) sizeof(tAniGenericChangeCountryCodeReq); cdf_mem_copy(pMsg->countryCode, pCountry, 2); - pMsg->domain_index = reg_domain; - pMsg->countryCode[2] = ' '; /* For ASCII space */ + pMsg->countryCode[2] = ' '; msg.type = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE; msg.bodyptr = pMsg; @@ -7051,7 +7049,7 @@ CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf) } /** - * sme_handle_change_country_code_by_user() - handles country ch req + * sme_handle_generic_change_country_code() - handles country ch req * @mac_ctx: mac global context * @msg: request msg packet * @@ -7063,17 +7061,18 @@ CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf) * Return: status of operation */ CDF_STATUS -sme_handle_change_country_code_by_user(tpAniSirGlobal mac_ctx, - tAniGenericChangeCountryCodeReq *msg) +sme_handle_generic_change_country_code(tpAniSirGlobal mac_ctx, + void *pMsgBuf) { CDF_STATUS status = CDF_STATUS_SUCCESS; - v_REGDOMAIN_t reg_domain_id; + v_REGDOMAIN_t reg_domain_id = 0; bool is_11d_country = false; bool supplicant_priority = mac_ctx->roam.configParam.fSupplicantCountryCodeHasPriority; + tAniGenericChangeCountryCodeReq *msg = pMsgBuf; sms_log(mac_ctx, LOG1, FL(" called")); - reg_domain_id = (v_REGDOMAIN_t) msg->domain_index; + if (memcmp(msg->countryCode, mac_ctx->scan.countryCode11d, CDS_COUNTRY_CODE_LEN) == 0) { is_11d_country = true; @@ -7106,6 +7105,7 @@ sme_handle_change_country_code_by_user(tpAniSirGlobal mac_ctx, return CDF_STATUS_E_FAILURE; } + /* if Supplicant country code has priority, disable 11d */ if (!is_11d_country && supplicant_priority) mac_ctx->roam.configParam.Is11dSupportEnabled = false; @@ -7162,64 +7162,6 @@ sme_handle_change_country_code_by_user(tpAniSirGlobal mac_ctx, return CDF_STATUS_SUCCESS; } -/* --------------------------------------------------------------------------- - - \fn sme_handle_change_country_code_by_core - - \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 mac_open. - \param pMsg - Carrying new CC set in kernel - - \return CDF_STATUS - - -------------------------------------------------------------------------------*/ -CDF_STATUS sme_handle_change_country_code_by_core(tpAniSirGlobal pMac, - tAniGenericChangeCountryCodeReq * - pMsg) -{ - CDF_STATUS status; - - sms_log(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])) { - sms_log(pMac, LOGW, - FL - ("Setting countryCode11d & countryCodeCurrent to world CC")); - cdf_mem_copy(pMac->scan.countryCode11d, pMsg->countryCode, - WNI_CFG_COUNTRY_CODE_LEN); - cdf_mem_copy(pMac->scan.countryCodeCurrent, pMsg->countryCode, - WNI_CFG_COUNTRY_CODE_LEN); - } - - status = wma_set_reg_domain(pMac, REGDOMAIN_WORLD); - - if (status != CDF_STATUS_SUCCESS) { - sms_log(pMac, LOGE, FL(" fail to set regId")); - return status; - } else { - status = csr_get_channel_and_power_list(pMac); - if (status != CDF_STATUS_SUCCESS) { - sms_log(pMac, LOGE, FL(" fail to get Channels ")); - } else { - csr_apply_channel_and_power_list(pMac); - } - } - /* Country code Changed, Purge Only scan result - * which does not have channel number belong to 11d - * channel list - */ - csr_scan_filter_results(pMac); - sms_log(pMac, LOG1, FL(" returned")); - return CDF_STATUS_SUCCESS; -} - static bool sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch) { @@ -7273,42 +7215,6 @@ void sme_disconnect_connected_sessions(tpAniSirGlobal mac_ctx) } } -/* --------------------------------------------------------------------------- - - \fn sme_handle_generic_change_country_code - - \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 mac_open. - \param pMsgBuf - message buffer - - \return CDF_STATUS - - -------------------------------------------------------------------------------*/ -CDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac, - void *pMsgBuf) -{ - tAniGenericChangeCountryCodeReq *pMsg; - v_REGDOMAIN_t reg_domain_id; - - sms_log(pMac, LOG1, FL(" called")); - pMsg = (tAniGenericChangeCountryCodeReq *) pMsgBuf; - reg_domain_id = (v_REGDOMAIN_t) pMsg->domain_index; - - if (REGDOMAIN_COUNT == reg_domain_id) { - sme_handle_change_country_code_by_core(pMac, pMsg); - } else { - sme_handle_change_country_code_by_user(pMac, pMsg); - } - sms_log(pMac, LOG1, FL(" returned")); - return CDF_STATUS_SUCCESS; -} - #ifdef WLAN_FEATURE_PACKET_FILTERING CDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId, tpSirRcvFltMcAddrList pMulticastAddrs) -- cgit v1.2.3 From e10e82a3250dfba2617a45a9bc6e727764453197 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Wed, 14 Oct 2015 16:28:11 -0700 Subject: qcacld-3.0: Change regulatory data structures style Change regulatory data structures and APIs to linux style. Change the references to the data structures accordingly. Leave data structures that would be deleted in subsequent iterations as is. Change-Id: I68dcd3485d3fb3d98f648b5844508356c3f3c29d CRs-Fixed: 856727 --- core/cds/inc/cds_reg_service.h | 109 +++++++++++++++++++------------------- core/cds/src/cds_reg_service.c | 49 ++++++++--------- core/hdd/src/wlan_hdd_cfg80211.c | 18 +++---- core/hdd/src/wlan_hdd_hostapd.c | 6 +-- core/hdd/src/wlan_hdd_main.c | 14 ++--- core/sap/inc/sap_api.h | 3 +- core/sap/src/sap_fsm.c | 28 +++++----- core/sap/src/sap_internal.h | 2 - core/sme/src/csr/csr_api_roam.c | 2 +- core/sme/src/csr/csr_api_scan.c | 15 +++--- core/sme/src/csr/csr_inside_api.h | 4 +- core/sme/src/csr/csr_util.c | 6 +-- 12 files changed, 122 insertions(+), 134 deletions(-) diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h index d69c877d1a21..43f0a8a21df5 100644 --- a/core/cds/inc/cds_reg_service.h +++ b/core/cds/inc/cds_reg_service.h @@ -41,6 +41,36 @@ #define CDS_COUNTRY_CODE_LEN 2 #define CDS_MAC_ADDRESS_LEN 6 +#define CDS_CHANNEL_STATE(enum) reg_channels[enum].enabled +#define CDS_CHANNEL_NUM(enum) chan_mapping[enum].chan_num +#define CDS_CHANNEL_FREQ(enum) chan_mapping[enum].center_freq +#define CDS_IS_DFS_CH(chan_num) (cds_get_channel_state((chan_num)) == \ + CHANNEL_STATE_DFS) + +#define CDS_IS_PASSIVE_OR_DISABLE_CH(chan_num) \ + (cds_get_channel_state(chan_num) != CHANNEL_STATE_ENABLE) + +#define CDS_MIN_24GHZ_CHANNEL_NUMBER \ + chan_mapping[MIN_24GHZ_CHANNEL].chan_num +#define CDS_MAX_24GHZ_CHANNEL_NUMBER \ + chan_mapping[MAX_24GHZ_CHANNEL].chan_num +#define CDS_MIN_5GHZ_CHANNEL_NUMBER chan_mapping[MIN_5GHZ_CHANNEL].chan_num +#define CDS_MAX_5GHZ_CHANNEL_NUMBER chan_mapping[MAX_5GHZ_CHANNEL].chan_num + +#define CDS_IS_CHANNEL_5GHZ(chan_num) \ + ((chan_num >= CDS_MIN_5GHZ_CHANNEL_NUMBER) && \ + (chan_num <= CDS_MAX_5GHZ_CHANNEL_NUMBER)) + +#define CDS_IS_CHANNEL_24GHZ(chan_num) \ + ((chan_num >= CDS_MIN_24GHZ_CHANNEL_NUMBER) && \ + (chan_num <= CDS_MAX_24GHZ_CHANNEL_NUMBER)) + +#define CDS_IS_SAME_BAND_CHANNELS(ch1, ch2) \ + (ch1 && ch2 && \ + (CDS_IS_CHANNEL_5GHZ(ch1) == CDS_IS_CHANNEL_5GHZ(ch2))) + +#define CDS_MIN_11P_CHANNEL chan_mapping[MIN_59GHZ_CHANNEL].chan_num + typedef enum { REGDOMAIN_FCC, REGDOMAIN_ETSI, @@ -50,7 +80,6 @@ typedef enum { } v_REGDOMAIN_t; typedef enum { - /* 2.4GHz Band */ RF_CHAN_1 = 0, RF_CHAN_2, RF_CHAN_3, @@ -66,7 +95,6 @@ typedef enum { RF_CHAN_13, RF_CHAN_14, - /* 4.9GHz Band */ RF_CHAN_240, RF_CHAN_244, RF_CHAN_248, @@ -75,7 +103,6 @@ typedef enum { RF_CHAN_212, RF_CHAN_216, - /* 5GHz Low & Mid U-NII Band */ RF_CHAN_36, RF_CHAN_40, RF_CHAN_44, @@ -85,7 +112,6 @@ typedef enum { RF_CHAN_60, RF_CHAN_64, - /* 5GHz Mid Band - ETSI & FCC */ RF_CHAN_100, RF_CHAN_104, RF_CHAN_108, @@ -97,17 +123,14 @@ typedef enum { RF_CHAN_132, RF_CHAN_136, RF_CHAN_140, - RF_CHAN_144, - /* 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, @@ -134,19 +157,19 @@ typedef enum { RF_CHAN_BOND_9, RF_CHAN_BOND_10, RF_CHAN_BOND_11, - RF_CHAN_BOND_242, /* 4.9GHz Band */ + RF_CHAN_BOND_242, 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_38, 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_102, RF_CHAN_BOND_106, RF_CHAN_BOND_110, RF_CHAN_BOND_114, @@ -156,21 +179,19 @@ typedef enum { RF_CHAN_BOND_130, RF_CHAN_BOND_134, RF_CHAN_BOND_138, - RF_CHAN_BOND_142, - - RF_CHAN_BOND_151, /* 5GHz High U-NII Band */ + RF_CHAN_BOND_151, 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, - NUM_24GHZ_CHANNELS = (MAX_2_4GHZ_CHANNEL - MIN_2_4GHZ_CHANNEL + 1), + MIN_24GHZ_CHANNEL = RF_CHAN_1, + MAX_24GHZ_CHANNEL = RF_CHAN_14, + NUM_24GHZ_CHANNELS = (MAX_24GHZ_CHANNEL - MIN_24GHZ_CHANNEL + 1), - MIN_5GHZ_CHANNEL = RF_CHAN_240, + MIN_5GHZ_CHANNEL = RF_CHAN_36, MAX_5GHZ_CHANNEL = RF_CHAN_184, NUM_5GHZ_CHANNELS = (MAX_5GHZ_CHANNEL - MIN_5GHZ_CHANNEL + 1), @@ -184,8 +205,8 @@ typedef enum { NUM_40MHZ_RF_CHANNELS = (MAX_40MHZ_RF_CHANNEL - MIN_40MHZ_RF_CHANNEL + 1), - MIN_5_9GHZ_CHANNEL = RF_CHAN_170, - MAX_5_9GHZ_CHANNEL = RF_CHAN_184, + MIN_59GHZ_CHANNEL = RF_CHAN_170, + MAX_59GHZ_CHANNEL = RF_CHAN_184, INVALID_RF_CHANNEL = 0xBAD, RF_CHANNEL_INVALID_MAX_FIELD = 0x7FFFFFFF @@ -200,16 +221,16 @@ typedef enum { typedef int8_t tPowerdBm; -typedef struct { +struct regulatory_channel { uint32_t enabled:4; uint32_t flags:28; - tPowerdBm pwrLimit; -} sRegulatoryChannel; + tPowerdBm pwr_limit; +}; -typedef struct { - uint16_t targetFreq; - uint16_t channelNum; -} tRfChannelProps; +struct chan_map { + uint16_t center_freq; + uint16_t chan_num; +}; typedef struct { uint8_t chanId; @@ -272,6 +293,8 @@ enum channel_width { */ typedef uint8_t country_code_t[CDS_COUNTRY_CODE_LEN + 1]; +extern struct regulatory_channel reg_channels[NUM_RF_CHANNELS]; +extern const struct chan_map chan_mapping[NUM_RF_CHANNELS]; CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *pRegDomain, const country_code_t countryCode, @@ -280,44 +303,22 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *pRegDomain, CDF_STATUS cds_read_default_country(country_code_t default_country); CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower - *pChannels20MHz, - uint8_t *pNum20MHzChannelsFound, + *base_channels, + uint8_t *num_base_channels, tChannelListWithPower *pChannels40MHz, - uint8_t *pNum40MHzChannelsFound); + uint8_t *); -CDF_STATUS cds_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId); +CDF_STATUS cds_set_reg_domain(void *client_ctxt, v_REGDOMAIN_t reg_domain); -CHANNEL_STATE cds_get_channel_state(uint32_t rfChannel); +CHANNEL_STATE cds_get_channel_state(uint32_t chan_num); CDF_STATUS cds_regulatory_init(void); CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region); CDF_STATUS cds_set_dfs_region(uint8_t dfs_region); bool cds_is_dsrc_channel(uint16_t); CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, - enum channel_width ch_width); + enum channel_width chan_width); enum channel_width cds_get_max_channel_bw(uint32_t chan_num); - -#define CDS_IS_DFS_CH(channel) (cds_get_channel_state((channel)) == \ - CHANNEL_STATE_DFS) - -#define CDS_IS_PASSIVE_OR_DISABLE_CH(channel) \ - (cds_get_channel_state((channel)) != CHANNEL_STATE_ENABLE) - -#define CDS_MAX_24GHz_CHANNEL_NUMBER \ - (rf_channels[MAX_2_4GHZ_CHANNEL].channelNum) -#define CDS_MIN_5GHz_CHANNEL_NUMBER (rf_channels[RF_CHAN_36].channelNum) -#define CDS_MAX_5GHz_CHANNEL_NUMBER (rf_channels[MAX_5GHZ_CHANNEL].channelNum) - -#define CDS_IS_CHANNEL_5GHZ(chnNum) \ - (((chnNum) >= CDS_MIN_5GHz_CHANNEL_NUMBER) && ((chnNum) <= CDS_MAX_5GHz_CHANNEL_NUMBER)) - -#define CDS_IS_CHANNEL_24GHZ(chnNum) \ - (((chnNum) > 0) && ((chnNum) <= CDS_MAX_24GHz_CHANNEL_NUMBER)) - -#define CDS_IS_SAME_BAND_CHANNELS(ch1, ch2) \ - (ch1 && ch2 && \ - (CDS_IS_CHANNEL_5GHZ(ch1) == CDS_IS_CHANNEL_5GHZ(ch2))) - #endif /* __CDS_REG_SERVICE_H */ diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index ddbec514f1fe..c4945722a6b9 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -42,21 +42,13 @@ #define WORLD_SKU_MASK 0x00F0 #define WORLD_SKU_PREFIX 0x0060 -#define MAX_COUNTRY_COUNT 300 +#define REG_WAIT_TIME 50 #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 -/* true if init happens thru init time driver hint */ -static bool init_by_driver = false; -/* true if init happens thru init time callback from regulatory core. - this should be set to true during driver reload */ -static bool init_by_reg_core = false; - -#define REG_WAIT_TIME 50 - #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, \ @@ -131,7 +123,7 @@ static const struct ieee80211_regdomain cds_world_regdom_67_68_6A_6C = { } }; -const tRfChannelProps rf_channels[NUM_RF_CHANNELS] = { +const struct chan_map chan_mapping[NUM_RF_CHANNELS] = { {2412, 1}, {2417, 2}, {2422, 3}, @@ -231,7 +223,10 @@ const tRfChannelProps rf_channels[NUM_RF_CHANNELS] = { {5815, 163}, }; -sRegulatoryChannel reg_channels[NUM_RF_CHANNELS]; +static bool init_by_driver; +static bool init_by_reg_core; + +struct regulatory_channel reg_channels[NUM_RF_CHANNELS]; /** * cds_is_wwr_sku() - is regdomain world sku @@ -400,17 +395,17 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * for (i = 0; i <= RF_CHAN_14; i++) { if (reg_channels[i].enabled) { base_channels[count].chanId = - rf_channels[i].channelNum; + chan_mapping[i].chan_num; base_channels[count++].pwr = - reg_channels[i].pwrLimit; + reg_channels[i].pwr_limit; } } for (i = RF_CHAN_36; i <= RF_CHAN_184; i++) { if (reg_channels[i].enabled) { base_channels[count].chanId = - rf_channels[i].channelNum; + chan_mapping[i].chan_num; base_channels[count++].pwr = - reg_channels[i].pwrLimit; + reg_channels[i].pwr_limit; } } *num_base_channels = count; @@ -422,18 +417,18 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * for (i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++) { if (reg_channels[i].enabled) { channels_40mhz[count].chanId = - rf_channels[i].channelNum; + chan_mapping[i].chan_num; channels_40mhz[count++].pwr = - reg_channels[i].pwrLimit; + reg_channels[i].pwr_limit; } } for (i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++) { if (reg_channels[i].enabled) { channels_40mhz[count].chanId = - rf_channels[i].channelNum; + chan_mapping[i].chan_num; channels_40mhz[count++].pwr = - reg_channels[i].pwrLimit; + reg_channels[i].pwr_limit; } } *num_40mhz_channels = count; @@ -482,7 +477,7 @@ static eRfChannels cds_get_channel_enum(uint32_t chan_num) uint32_t loop; for (loop = 0; loop <= RF_CHAN_184; loop++) - if (rf_channels[loop].channelNum == chan_num) + if (chan_mapping[loop].chan_num == chan_num) return loop; CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, @@ -494,7 +489,7 @@ static eRfChannels cds_get_channel_enum(uint32_t chan_num) /** * cds_get_channel_state() - get the channel state - * @channel_num: channel number + * @chan_num: channel number * * Return: CHANNEL_STATE */ @@ -795,9 +790,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, hdd_context_t *hdd_ctx; const struct ieee80211_reg_rule *reg_rule; struct ieee80211_channel *chan; - sRegulatoryChannel *temp_chan_k; - sRegulatoryChannel *temp_chan_n; - sRegulatoryChannel *temp_chan; + struct regulatory_channel *temp_chan_k, *temp_chan_n, *temp_chan; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (NULL == hdd_ctx) { @@ -927,7 +920,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, IEEE80211_CHAN_PASSIVE_SCAN; #endif temp_chan_k->enabled = CHANNEL_STATE_DFS; - temp_chan_k->pwrLimit = + temp_chan_k->pwr_limit = chan->max_power; temp_chan_k->flags = chan->flags; @@ -940,7 +933,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, } else { temp_chan_n->enabled = CHANNEL_STATE_DFS; - temp_chan_n->pwrLimit = + temp_chan_n->pwr_limit = chan->max_power-3; } temp_chan_n->flags = chan->flags; @@ -950,7 +943,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, hdd_ctx->isVHT80Allowed = 1; } else { temp_chan_k->enabled = CHANNEL_STATE_ENABLE; - temp_chan_k->pwrLimit = chan->max_power; + temp_chan_k->pwr_limit = chan->max_power; temp_chan_k->flags = chan->flags; if (n != -1) { if ((chan->flags & @@ -961,7 +954,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, } else { temp_chan_n->enabled = CHANNEL_STATE_ENABLE; - temp_chan_n->pwrLimit = + temp_chan_n->pwr_limit = chan->max_power - 3; } temp_chan_n->flags = chan->flags; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 09ba705be76c..138b634affc5 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1275,20 +1275,20 @@ static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_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 = rf_channels[RF_CHAN_1].channelNum; - sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_14].channelNum; + sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1); + sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_14); } 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 = rf_channels[RF_CHAN_1].channelNum; - sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_13].channelNum; + sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1); + sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_13); } 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 = rf_channels[RF_CHAN_36].channelNum; - sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_165].channelNum; + sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_36); + sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165); } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) { sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg; - sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_1].channelNum; - sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_165].channelNum; + sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1); + sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165); } if (ht_enabled) @@ -5772,7 +5772,7 @@ CDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter, if (hdd_pConfig_ini->sapAllowAllChannel) { /* Validate the channel */ for (count = RF_CHAN_1; count <= RF_CHAN_165; count++) { - if (channel == rf_channels[count].channelNum) { + if (channel == CDS_CHANNEL_NUM(count)) { fValidChannel = true; break; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index e7a70a974b4e..0e69738968e5 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -3629,10 +3629,10 @@ static int __iw_softap_get_channel_list(struct net_device *dev, curBand, bandStartChannel, bandEndChannel); for (i = bandStartChannel; i <= bandEndChannel; i++) { - if ((CHANNEL_STATE_ENABLE == reg_channels[i].enabled) || - (CHANNEL_STATE_DFS == reg_channels[i].enabled)) { + if ((CHANNEL_STATE_ENABLE == CDS_CHANNEL_STATE(i)) || + (CHANNEL_STATE_DFS == CDS_CHANNEL_STATE(i))) { channel_list->channels[num_channels] = - rf_channels[i].channelNum; + CDS_CHANNEL_NUM(i); num_channels++; } } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index a22b44b88e1b..6a4e405da5a3 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4603,7 +4603,7 @@ static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, is_unsafe = 0; for (channel_loop = 0; channel_loop < unsafe_channel_count; channel_loop++) { - if (rf_channels[i].channelNum == + if (CDS_CHANNEL_NUM(i) == hdd_ctxt->unsafe_channel_list[channel_loop]) { is_unsafe = 1; break; @@ -4611,7 +4611,7 @@ static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt, } if (!is_unsafe) { safe_channels[safe_channel_count] = - rf_channels[i].channelNum; + CDS_CHANNEL_NUM(i); hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("safe channel %d"), safe_channels[safe_channel_count]); @@ -4773,7 +4773,7 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <= MAX_20MHZ_RF_CHANNEL; channel_loop++) { - if (rf_channels[channel_loop].targetFreq >= + if (CDS_CHANNEL_FREQ(channel_loop) >= ch_avoid_indi->avoid_freq_range[ range_loop].start_freq) { start_channel_idx = channel_loop; @@ -4782,11 +4782,11 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) } for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <= MAX_20MHZ_RF_CHANNEL; channel_loop++) { - if (rf_channels[channel_loop].targetFreq >= + if (CDS_CHANNEL_FREQ(channel_loop) >= ch_avoid_indi->avoid_freq_range[ range_loop].end_freq) { end_channel_idx = channel_loop; - if (rf_channels[channel_loop].targetFreq > + if (CDS_CHANNEL_FREQ(channel_loop) > ch_avoid_indi->avoid_freq_range[ range_loop].end_freq) end_channel_idx--; @@ -4801,8 +4801,8 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) for (channel_loop = start_channel_idx; channel_loop <= end_channel_idx; channel_loop++) { hdd_ctxt->unsafe_channel_list[ - hdd_ctxt->unsafe_channel_count++] = - rf_channels[channel_loop].channelNum; + hdd_ctxt->unsafe_channel_count++] = + CDS_CHANNEL_FREQ(channel_loop); if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) { hddLog(LOGW, FL("LTECoex unsafe ch list full")); diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 1109ca023c59..0da62d0f9c05 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -790,8 +790,7 @@ typedef struct sap_SoftapStats_s { uint32_t pktCounterRssi[MAX_NUM_RSSI]; #endif } tSap_SoftapStats, *tpSap_SoftapStats; -/* Channel/Frequency table */ -extern const tRfChannelProps rf_channels[NUM_RF_CHANNELS]; + #ifdef FEATURE_WLAN_CH_AVOID /* Store channel safety information */ typedef struct { diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index b66bf04e6ee1..377cd0861431 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -4184,8 +4184,8 @@ static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, for (loop_count = band_start_ch; loop_count <= band_end_ch; loop_count++) { /* go to next channel if rf_channel is out of range */ - if ((start_ch_num > rf_channels[loop_count].channelNum) || - (end_ch_num < rf_channels[loop_count].channelNum)) + if ((start_ch_num > CDS_CHANNEL_NUM(loop_count)) || + (end_ch_num < CDS_CHANNEL_NUM(loop_count))) continue; /* * go to next channel if none of these condition pass @@ -4193,22 +4193,22 @@ static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, * - DFS scan disable but chan in CHANNEL_STATE_ENABLE */ if (!(((eSAP_TRUE == mac_ctx->scan.fEnableDFSChnlScan) && - (reg_channels[loop_count].enabled)) || + CDS_CHANNEL_STATE(loop_count)) || ((eSAP_FALSE == mac_ctx->scan.fEnableDFSChnlScan) && (CHANNEL_STATE_ENABLE == - reg_channels[loop_count].enabled)))) + CDS_CHANNEL_STATE(loop_count))))) continue; #ifdef FEATURE_WLAN_CH_AVOID for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) { if ((safe_channels[i].channelNumber == - rf_channels[loop_count].channelNum)) { + CDS_CHANNEL_NUM(loop_count))) { /* Check if channel is safe */ if (true == safe_channels[i].isSafe) { #endif #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE uint8_t ch; - ch = rf_channels[loop_count].channelNum; + ch = CDS_CHANNEL_NUM(loop_count); if ((sap_ctx->acs_cfg->skip_scan_status == eSAP_DO_PAR_ACS_SCAN)) { if ((ch >= sap_ctx->acs_cfg->skip_scan_range1_stch && @@ -4216,7 +4216,7 @@ static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, (ch >= sap_ctx->acs_cfg->skip_scan_range2_stch && ch <= sap_ctx->acs_cfg->skip_scan_range2_endch)) { list[ch_count] = - rf_channels[loop_count].channelNum; + CDS_CHANNEL_NUM(loop_count); ch_count++; CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, @@ -4230,7 +4230,7 @@ static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, } } else { list[ch_count] = - rf_channels[loop_count].channelNum; + CDS_CHANNEL_NUM(loop_count); ch_count++; CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, @@ -4238,7 +4238,7 @@ static CDF_STATUS sap_get_channel_list(ptSapContext sap_ctx, ch_count, ch); } #else - list[ch_count] = rf_channels[loop_count].channelNum; + list[ch_count] = CDS_CHANNEL_NUM(loop_count); ch_count++; #endif #ifdef FEATURE_WLAN_CH_AVOID @@ -4306,10 +4306,10 @@ static CDF_STATUS sap_get5_g_hz_channel_list(ptSapContext sapContext) } for (i = RF_CHAN_36; i <= RF_CHAN_165; i++) { - if (reg_channels[i].enabled == CHANNEL_STATE_ENABLE || - reg_channels[i].enabled == CHANNEL_STATE_DFS) { + if (CDS_CHANNEL_STATE(i) == CHANNEL_STATE_ENABLE || + CDS_CHANNEL_STATE(i) == CHANNEL_STATE_DFS) { sapContext->SapAllChnlList.channelList[count].channel = - rf_channels[i].channelNum; + CDS_CHANNEL_NUM(i); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, "%s[%d] CHANNEL = %d", __func__, __LINE__, sapContext->SapAllChnlList.channelList[count]. @@ -4601,12 +4601,12 @@ CDF_STATUS sap_init_dfs_channel_nol_list(ptSapContext sapContext) } for (i = RF_CHAN_36; i <= RF_CHAN_165; i++) { - if (reg_channels[i].enabled == CHANNEL_STATE_DFS) { + if (CDS_CHANNEL_STATE(i) == CHANNEL_STATE_DFS) { /* if dfs nol is not found, initialize it */ if (!bFound) { pMac->sap.SapDfsInfo.sapDfsChannelNolList[count] .dfs_channel_number = - rf_channels[i].channelNum; + CDS_CHANNEL_NUM(i); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_LOW, diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h index 3ba7b0a410d1..1abf9c8e3216 100644 --- a/core/sap/src/sap_internal.h +++ b/core/sap/src/sap_internal.h @@ -76,8 +76,6 @@ extern "C" { #define SAP_CHAN_PREFERRED_INDOOR 1 #define SAP_CHAN_PREFERRED_OUTDOOR 2 -extern const sRegulatoryChannel reg_channels[NUM_RF_CHANNELS]; - /*---------------------------------------------------------------------------- * Typedefs * -------------------------------------------------------------------------*/ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index af8d356d8415..e3189eae4f33 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -706,7 +706,7 @@ CDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac) for (i = 0; i < pScan->base_channels.numChannels; i++) { /* Scan is not performed on DSRC channels*/ - if (pScan->base_channels.channelList[i] >= MIN_11P_CHANNEL) + if (pScan->base_channels.channelList[i] >= CDS_MIN_11P_CHANNEL) continue; if (pScan->fcc_constraint) { if (pScan->base_channels.channelList[i] == 12) diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 20293af2a9f0..c6e446bcdb80 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -3058,13 +3058,13 @@ CDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac, if ((CDS_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) && ((pChannelSet->firstChannel + (pChannelSet->numChannels - 1)) <= - CDS_MAX_24GHz_CHANNEL_NUMBER)) { + CDS_MAX_24GHZ_CHANNEL_NUMBER)) { pChannelSet->interChannelOffset = 1; f2GHzInfoFound = true; } else if ((CDS_IS_CHANNEL_5GHZ(pChannelSet->firstChannel)) && ((pChannelSet->firstChannel + ((pChannelSet->numChannels - 1) * 4)) <= - CDS_MAX_5GHz_CHANNEL_NUMBER)) { + CDS_MAX_5GHZ_CHANNEL_NUMBER)) { pChannelSet->interChannelOffset = 4; f2GHzInfoFound = false; } else { @@ -5184,7 +5184,7 @@ csr_issue_user_scan(tpAniSirGlobal mac_ctx, tSmeCmd *cmd) j = 0; for (i = 0; i < len; i++) { new_ch_info.ChannelList[j++] = ch_lst[i]; - if (CDS_MAX_24GHz_CHANNEL_NUMBER >= ch_lst[i]) + if (CDS_MAX_24GHZ_CHANNEL_NUMBER >= ch_lst[i]) new_ch_info.ChannelList[j++] = ch_lst[i]; } if (NULL != @@ -5256,7 +5256,8 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, * that is the only way to find p2p peers. * This can happen only if band is set to 5Ghz mode. */ - if (src_req->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL && + if (src_req->ChannelInfo.ChannelList[index] < + CDS_MIN_11P_CHANNEL && ((csr_roam_is_valid_channel(mac_ctx, src_req->ChannelInfo.ChannelList[index])) || ((eCSR_SCAN_P2P_DISCOVERY == src_req->requestType) && @@ -5341,7 +5342,7 @@ static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, * Don't allow DSRC channel when IBSS concurrent connection * is up */ - if (valid_chnl_list[i] >= MIN_11P_CHANNEL) + if (valid_chnl_list[i] >= CDS_MIN_11P_CHANNEL) continue; if (CDS_IS_CHANNEL_5GHZ(ibss_channel) && CDS_IS_CHANNEL_24GHZ(valid_chnl_list[i])) { @@ -5455,7 +5456,7 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, ChannelInfo. ChannelList[index]); if (src_req->ChannelInfo.ChannelList[index] < - MIN_11P_CHANNEL && + CDS_MIN_11P_CHANNEL && ((CHANNEL_STATE_ENABLE == channel_state) || ((CHANNEL_STATE_DFS == channel_state) && @@ -5486,7 +5487,7 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, for (index = 0; index < src_req->ChannelInfo. numOfChannels; index++) { if (src_req->ChannelInfo.ChannelList[index] < - MIN_11P_CHANNEL) { + CDS_MIN_11P_CHANNEL) { dst_req->ChannelInfo. ChannelList[new_index] = src_req->ChannelInfo. diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 3a7b54c8f974..7e2a489def6d 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -104,7 +104,6 @@ #define CSR_MAX_BSSID_COUNT ((CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE/4000) * 3) #define CSR_CUSTOM_CONC_GO_BI 100 -#define MIN_11P_CHANNEL (rf_channels[MIN_5_9GHZ_CHANNEL].channelNum) typedef enum { eCsrNextScanNothing, @@ -196,7 +195,6 @@ typedef struct { (eCsrForcedDisassocMICFailure == \ (pCommand)->u.roamCmd.roamReason))) -extern const tRfChannelProps rf_channels[NUM_RF_CHANNELS]; eCsrRoamState csr_roam_state_change(tpAniSirGlobal pMac, eCsrRoamState NewRoamState, uint8_t sessionId); CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac, void *pMsgBuf); diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 41ede0889193..95faef7eccf1 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -97,7 +97,6 @@ uint8_t csr_wapi_oui[][CSR_WAPI_OUI_SIZE] = { uint8_t csr_wme_info_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; uint8_t csr_wme_parm_oui[CSR_WME_OUI_SIZE] = { 0x00, 0x50, 0xf2, 0x02 }; - /* ////////////////////////////////////////////////////////////////////// */ /** @@ -5535,9 +5534,8 @@ uint16_t sme_chn_to_freq(uint8_t chanNum) int i; for (i = 0; i < NUM_RF_CHANNELS; i++) { - if (rf_channels[i].channelNum == chanNum) { - return rf_channels[i].targetFreq; - } + if (CDS_CHANNEL_NUM(i) == chanNum) + return CDS_CHANNEL_FREQ(i); } return 0; -- cgit v1.2.3 From 6b176d20a9d54fc2112943c138ca3ba8366a5226 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Mon, 2 Nov 2015 15:08:59 -0800 Subject: qcacld-3.0: Remove FEATURE_STATICALLY_ADD_11P_CHANNELS FEATURE_STATICALLY_ADD_11P_CHANNELS was a temporary solution for builds that were not defining DSRC channels in db.txt. That restriction no more holds true. Also correct the list of DSRC channels in function cds_is_dsrc_channel. Change-Id: I1146ec9702a8eec801b635a276e981962dd42817 CRs-Fixed: 856727 --- Kbuild | 8 --- core/cds/src/cds_reg_service.c | 28 ++-------- core/hdd/src/wlan_hdd_cfg80211.c | 2 - core/hdd/src/wlan_hdd_ocb.c | 112 +-------------------------------------- 4 files changed, 5 insertions(+), 145 deletions(-) diff --git a/Kbuild b/Kbuild index 09dc487eb170..8b88845e2b44 100644 --- a/Kbuild +++ b/Kbuild @@ -253,10 +253,6 @@ CONFIG_FEATURE_SECURE_FIRMWARE := 0 #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 @@ -1329,10 +1325,6 @@ ifeq ($(CONFIG_WLAN_FEATURE_MEMDUMP),y) CDEFINES += -DWLAN_FEATURE_MEMDUMP endif -ifeq ($(CONFIG_STATICALLY_ADD_11P_CHANNELS),y) -CDEFINES += -DFEATURE_STATICALLY_ADD_11P_CHANNELS -endif - ifeq ($(CONFIG_LFR_SUBNET_DETECTION), y) CDEFINES += -DFEATURE_LFR_SUBNET_DETECTION endif diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index c4945722a6b9..5bb313942cd0 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -754,26 +754,13 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, */ bool cds_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: + if (center_freq >= 5852 && + center_freq <= 5920) return 1; - } + return 0; } -#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS -#define DEFAULT_11P_POWER (30) -#endif - /** * cds_process_regulatory_data() - process regulatory data * @wiphy: wiphy @@ -886,15 +873,6 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, } } -#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS - if (is_dsrc_channel(chan->center_freq)) { - temp_chan_k->enabled = - CHANNEL_STATE_ENABLE; - temp_chan_k->pwrLimit = - DEFAULT_11P_POWER; - temp_chan_k->flags = chan->flags; - } else -#endif if (chan->flags & IEEE80211_CHAN_DISABLED) { temp_chan_k->enabled = CHANNEL_STATE_DISABLE; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 138b634affc5..4346765d9976 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -217,7 +217,6 @@ static struct ieee80211_channel hdd_channels_5_ghz[] = { 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), @@ -233,7 +232,6 @@ static struct ieee80211_channel hdd_channels_5_ghz[] = { HDD5GHZCHAN(5910, 182, 0), HDD5GHZCHAN(5915, 183, 0), HDD5GHZCHAN(5920, 184, 0), -#endif }; static struct ieee80211_rate g_mode_rates[] = { diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index 881859a074b8..f8df3fbfcd35 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -121,113 +121,6 @@ static int dot11p_validate_qos_params(struct sir_qos_params qos_params[]) return 0; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)) || \ - defined(FEATURE_STATICALLY_ADD_11P_CHANNELS) -/* - * 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) -#endif - -#ifdef FEATURE_STATICALLY_ADD_11P_CHANNELS - -#define DOT11P_TX_PWR_MAX 30 -#define DOT11P_TX_ANTENNA_MAX 6 -#define NUM_DOT11P_CHANNELS 10 -/** - * 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 @@ -304,8 +197,7 @@ static int dot11p_validate_channel(struct wiphy *wiphy, } } - return dot11p_validate_channel_static_channels(wiphy, channel_freq, - bandwidth, tx_power, reg_power, antenna_max); + return -EINVAL; } /** -- cgit v1.2.3 From 21767015e82394dae08074ab63105873781d5d46 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Wed, 16 Dec 2015 11:57:57 -0800 Subject: qcacld-3.0: Remove the 4.9 GHZ channels Remove the 4.9 GHZ channels from the driver stack. 4.9 GHZ channels are not being used for any country, so remove them. Change-Id: I135f997bb4c8ad7a536596b4e89eb037f41e0c73 CRs-Fixed: 856727 --- core/cds/inc/cds_reg_service.h | 13 ------------- core/cds/src/cds_reg_service.c | 16 ---------------- core/hdd/src/wlan_hdd_cfg80211.c | 7 ------- core/sap/src/sap_ch_select.c | 14 -------------- 4 files changed, 50 deletions(-) diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h index 43f0a8a21df5..3803e5747317 100644 --- a/core/cds/inc/cds_reg_service.h +++ b/core/cds/inc/cds_reg_service.h @@ -95,14 +95,6 @@ typedef enum { RF_CHAN_13, RF_CHAN_14, - RF_CHAN_240, - RF_CHAN_244, - RF_CHAN_248, - RF_CHAN_252, - RF_CHAN_208, - RF_CHAN_212, - RF_CHAN_216, - RF_CHAN_36, RF_CHAN_40, RF_CHAN_44, @@ -157,11 +149,6 @@ typedef enum { RF_CHAN_BOND_9, RF_CHAN_BOND_10, RF_CHAN_BOND_11, - RF_CHAN_BOND_242, - RF_CHAN_BOND_246, - RF_CHAN_BOND_250, - RF_CHAN_BOND_210, - RF_CHAN_BOND_214, RF_CHAN_BOND_38, RF_CHAN_BOND_42, RF_CHAN_BOND_46, diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index 5bb313942cd0..c1f0213ede23 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -138,13 +138,6 @@ const struct chan_map chan_mapping[NUM_RF_CHANNELS] = { {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}, @@ -194,11 +187,6 @@ const struct chan_map chan_mapping[NUM_RF_CHANNELS] = { {2452, 9}, {2457, 10}, {2462, 11}, - {4930, 242}, - {4950, 246}, - {4970, 250}, - {5050, 210}, - {5070, 214}, {5190, 38}, {5210, 42}, {5230, 46}, @@ -597,10 +585,6 @@ static int cds_bw20_ch_index_to_bw40_ch_index(int k) 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) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 4346765d9976..1806541bbc05 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -185,13 +185,6 @@ static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = { }; 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), diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index b22f6cffdb96..9e09a08b7436 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -114,20 +114,6 @@ sapSafeChannelType safe_channels[NUM_20MHZ_RF_CHANNELS] = { , /* RF_CHAN_13, */ {14, true} , /* RF_CHAN_14, */ - {240, true} - , /* RF_CHAN_240, */ - {244, true} - , /* RF_CHAN_244, */ - {248, true} - , /* RF_CHAN_248, */ - {252, true} - , /* RF_CHAN_252, */ - {208, true} - , /* RF_CHAN_208, */ - {212, true} - , /* RF_CHAN_212, */ - {216, true} - , /* RF_CHAN_216, */ {36, true} , /* RF_CHAN_36, */ {40, true} -- cgit v1.2.3 From 69581755634a44404680241fdd4b623f5fa4f09a Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Thu, 15 Oct 2015 15:07:29 -0700 Subject: qcacld-3.0: More regulatory cleanups Remove typedef tPowerdBm. Rename and use linux style for channel enum, channel state, channel power and country source data structures. Change-Id: Iebc59e6f001ccdb403c7445f4cea02c6a8141366 CRs-Fixed: 856727 --- core/cds/inc/cds_reg_service.h | 147 +++++++++++++-------- core/cds/src/cds_reg_service.c | 130 +++++++++--------- core/hdd/src/wlan_hdd_cfg80211.c | 2 +- core/hdd/src/wlan_hdd_main.c | 2 +- core/mac/inc/sir_api.h | 2 +- core/mac/src/cfg/cfg_api.c | 26 ++-- core/mac/src/include/cfg_api.h | 6 +- core/mac/src/pe/include/lim_session.h | 5 +- core/mac/src/pe/include/rrm_api.h | 12 +- core/mac/src/pe/include/rrm_global.h | 4 +- core/mac/src/pe/lim/lim_assoc_utils.c | 4 +- core/mac/src/pe/lim/lim_ft.c | 4 +- core/mac/src/pe/lim/lim_process_mlm_req_messages.c | 4 +- core/mac/src/pe/lim/lim_process_sme_req_messages.c | 10 +- core/mac/src/pe/lim/lim_prop_exts_utils.c | 4 +- core/mac/src/pe/lim/lim_prop_exts_utils.h | 4 +- core/mac/src/pe/lim/lim_send_messages.c | 4 +- core/mac/src/pe/lim/lim_send_messages.h | 4 +- core/mac/src/pe/lim/lim_types.h | 2 +- core/mac/src/pe/lim/lim_utils.c | 4 +- core/mac/src/pe/lim/lim_utils.h | 6 +- core/mac/src/pe/rrm/rrm_api.c | 17 ++- core/mac/src/pe/sch/sch_beacon_process.c | 6 +- core/sap/src/sap_ch_select.c | 2 +- core/sme/inc/csr_internal.h | 4 +- core/sme/inc/sme_api.h | 2 +- core/sme/src/common/sme_api.c | 19 +-- core/sme/src/csr/csr_api_roam.c | 21 +-- core/sme/src/csr/csr_api_scan.c | 35 ++--- core/sme/src/csr/csr_inside_api.h | 4 +- core/sme/src/csr/csr_util.c | 13 +- core/wma/inc/wma.h | 4 +- core/wma/inc/wma_if.h | 16 +-- core/wma/src/wma_dev_if.c | 6 +- core/wma/src/wma_power.c | 4 +- 35 files changed, 286 insertions(+), 253 deletions(-) diff --git a/core/cds/inc/cds_reg_service.h b/core/cds/inc/cds_reg_service.h index 3803e5747317..5bc32ea79c55 100644 --- a/core/cds/inc/cds_reg_service.h +++ b/core/cds/inc/cds_reg_service.h @@ -39,23 +39,21 @@ #include "cdf_status.h" #define CDS_COUNTRY_CODE_LEN 2 -#define CDS_MAC_ADDRESS_LEN 6 +#define CDS_MAC_ADDRESS_LEN 6 -#define CDS_CHANNEL_STATE(enum) reg_channels[enum].enabled -#define CDS_CHANNEL_NUM(enum) chan_mapping[enum].chan_num -#define CDS_CHANNEL_FREQ(enum) chan_mapping[enum].center_freq +#define CDS_CHANNEL_STATE(chan_enum) reg_channels[chan_enum].state +#define CDS_CHANNEL_NUM(chan_enum) chan_mapping[chan_enum].chan_num +#define CDS_CHANNEL_FREQ(chan_enum) chan_mapping[chan_enum].center_freq #define CDS_IS_DFS_CH(chan_num) (cds_get_channel_state((chan_num)) == \ CHANNEL_STATE_DFS) #define CDS_IS_PASSIVE_OR_DISABLE_CH(chan_num) \ (cds_get_channel_state(chan_num) != CHANNEL_STATE_ENABLE) -#define CDS_MIN_24GHZ_CHANNEL_NUMBER \ - chan_mapping[MIN_24GHZ_CHANNEL].chan_num -#define CDS_MAX_24GHZ_CHANNEL_NUMBER \ - chan_mapping[MAX_24GHZ_CHANNEL].chan_num -#define CDS_MIN_5GHZ_CHANNEL_NUMBER chan_mapping[MIN_5GHZ_CHANNEL].chan_num -#define CDS_MAX_5GHZ_CHANNEL_NUMBER chan_mapping[MAX_5GHZ_CHANNEL].chan_num +#define CDS_MIN_24GHZ_CHANNEL_NUMBER chan_mapping[MIN_24GHZ_CHANNEL].chan_num +#define CDS_MAX_24GHZ_CHANNEL_NUMBER chan_mapping[MAX_24GHZ_CHANNEL].chan_num +#define CDS_MIN_5GHZ_CHANNEL_NUMBER chan_mapping[MIN_5GHZ_CHANNEL].chan_num +#define CDS_MAX_5GHZ_CHANNEL_NUMBER chan_mapping[MAX_5GHZ_CHANNEL].chan_num #define CDS_IS_CHANNEL_5GHZ(chan_num) \ ((chan_num >= CDS_MIN_5GHZ_CHANNEL_NUMBER) && \ @@ -65,9 +63,9 @@ ((chan_num >= CDS_MIN_24GHZ_CHANNEL_NUMBER) && \ (chan_num <= CDS_MAX_24GHZ_CHANNEL_NUMBER)) -#define CDS_IS_SAME_BAND_CHANNELS(ch1, ch2) \ - (ch1 && ch2 && \ - (CDS_IS_CHANNEL_5GHZ(ch1) == CDS_IS_CHANNEL_5GHZ(ch2))) +#define CDS_IS_SAME_BAND_CHANNELS(chan_num1, chan_num2) \ + (chan_num1 && chan_num2 && \ + (CDS_IS_CHANNEL_5GHZ(chan_num1) == CDS_IS_CHANNEL_5GHZ(chan_num2))) #define CDS_MIN_11P_CHANNEL chan_mapping[MIN_59GHZ_CHANNEL].chan_num @@ -79,7 +77,7 @@ typedef enum { REGDOMAIN_COUNT } v_REGDOMAIN_t; -typedef enum { +enum channel_enum { RF_CHAN_1 = 0, RF_CHAN_2, RF_CHAN_3, @@ -197,62 +195,104 @@ typedef enum { INVALID_RF_CHANNEL = 0xBAD, RF_CHANNEL_INVALID_MAX_FIELD = 0x7FFFFFFF -} eRfChannels; +}; -typedef enum { +/** + * enum channel_state: channel state + * + * @CHANNEL_STATE_DISABLE: channel disabled + * @CHANNEL_STATE_ENABLE: tx/rx enabled + * @CHANNEL_STATE_DFS: rx enabled, tx DFS + * @CHANNEL_STATE_INVALID: not a valid channel + */ +enum channel_state { CHANNEL_STATE_DISABLE, CHANNEL_STATE_ENABLE, CHANNEL_STATE_DFS, CHANNEL_STATE_INVALID -} CHANNEL_STATE; - -typedef int8_t tPowerdBm; +}; +/** + * struct regulatory_channel: regulatory channel + * + * @state: channel state + * @flags: channel flags + * @pwr_limit: channel tx power limit + */ struct regulatory_channel { - uint32_t enabled:4; + uint32_t state:4; uint32_t flags:28; - tPowerdBm pwr_limit; + int8_t pwr_limit; }; +/** + * struct chan_map: channel mapping + * + * @center_freq: channel center freq + * @chan_num: channel number + */ struct chan_map { uint16_t center_freq; uint16_t chan_num; }; -typedef struct { - uint8_t chanId; - tPowerdBm pwr; -} tChannelListWithPower; - -typedef enum { - COUNTRY_CODE_SET_BY_CORE, - COUNTRY_CODE_SET_BY_DRIVER, - COUNTRY_CODE_SET_BY_USER -} COUNTRY_CODE_SOURCE; +/** + * struct channel_power: channel power + * + * @chan_num: channel number + * @power: tx power + */ +struct channel_power { + uint8_t chan_num; + int8_t power; +}; +/** + * enum country_src: country source + * + * @SOURCE_QUERY: source query + * @SOURCE_CORE: source regulatory core + * @SOURCE_DRIVER: source driver + * @SOURCE_USERSPACE: source userspace + * @SOURCE_11D: source 11D + */ +enum country_src { + SOURCE_QUERY, + SOURCE_CORE, + SOURCE_DRIVER, + SOURCE_USERSPACE, + SOURCE_11D +}; +/** + * struct regulatory: regulatory information + * + * @reg_domain: regulatory domain pair + * @eeprom_rd_ext: eeprom value + * @country_code: current country in integer + * @alpha2: current alpha2 + * @def_country: default country alpha2 + * @def_region: DFS region + * @ctl_2g: 2G CTL value + * @ctl_5g: 5G CTL value + * @reg_pair: pointer to regulatory pair + * @cc_src: country code src + * @reg_flags: kernel regulatory flags + */ struct regulatory { uint32_t reg_domain; uint32_t eeprom_rd_ext; uint16_t country_code; - uint8_t alpha2[3]; - uint8_t def_country[3]; + uint8_t alpha2[CDS_COUNTRY_CODE_LEN + 1]; + uint8_t def_country[CDS_COUNTRY_CODE_LEN + 1]; uint8_t dfs_region; uint8_t ctl_2g; uint8_t ctl_5g; const void *regpair; - COUNTRY_CODE_SOURCE cc_src; + enum country_src cc_src; uint32_t reg_flags; }; -typedef enum { - COUNTRY_INIT, - COUNTRY_IE, - COUNTRY_USER, - COUNTRY_QUERY, - COUNTRY_MAX = COUNTRY_QUERY -} v_CountryInfoSource_t; - /** * enum chan_width: channel width * @@ -274,37 +314,32 @@ enum channel_width { CHAN_WIDTH_160MHZ }; -/** - * @country_code_t : typedef for country code. One extra - * char for holding null character - */ -typedef uint8_t country_code_t[CDS_COUNTRY_CODE_LEN + 1]; extern struct regulatory_channel reg_channels[NUM_RF_CHANNELS]; extern const struct chan_map chan_mapping[NUM_RF_CHANNELS]; CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *pRegDomain, - const country_code_t countryCode, - v_CountryInfoSource_t source); + const uint8_t *country_alpha2, + enum country_src source); -CDF_STATUS cds_read_default_country(country_code_t default_country); +CDF_STATUS cds_read_default_country(uint8_t *default_country); -CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower +CDF_STATUS cds_get_channel_list_with_power(struct channel_power *base_channels, uint8_t *num_base_channels, - tChannelListWithPower - *pChannels40MHz, - uint8_t *); + struct channel_power + *channel_40mhz, + uint8_t *num_channels_40mhz); CDF_STATUS cds_set_reg_domain(void *client_ctxt, v_REGDOMAIN_t reg_domain); -CHANNEL_STATE cds_get_channel_state(uint32_t chan_num); +enum channel_state cds_get_channel_state(uint32_t chan_num); CDF_STATUS cds_regulatory_init(void); CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region); CDF_STATUS cds_set_dfs_region(uint8_t dfs_region); bool cds_is_dsrc_channel(uint16_t); -CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, +enum channel_state cds_get_bonded_channel_state(uint32_t chan_num, enum channel_width chan_width); enum channel_width cds_get_max_channel_bw(uint32_t chan_num); diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index c1f0213ede23..b4aa41aa7b24 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -211,33 +211,24 @@ const struct chan_map chan_mapping[NUM_RF_CHANNELS] = { {5815, 163}, }; +struct regulatory_channel reg_channels[NUM_RF_CHANNELS]; static bool init_by_driver; static bool init_by_reg_core; -struct regulatory_channel reg_channels[NUM_RF_CHANNELS]; - -/** - * cds_is_wwr_sku() - is regdomain world sku - * @regd: integer regulatory domain - * - * Return: bool - */ -static inline bool cds_is_wwr_sku(u16 regd) -{ - return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && - (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || - (regd == WORLD)); -} - /** * cds_is_world_regdomain() - whether world regdomain * @regd: integer regulatory domain * * Return: bool */ -bool cds_is_world_regdomain(uint32_t regd) +bool cds_is_world_regdomain(uint32_t reg_domain) { - return cds_is_wwr_sku(regd & ~WORLDWIDE_ROAMING_FLAG); + uint32_t temp_regd = reg_domain & ~WORLDWIDE_ROAMING_FLAG; + + return ((temp_regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && + (((temp_regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || + (temp_regd == WORLD)); + } @@ -368,11 +359,11 @@ static void cds_update_regulatory_info(hdd_context_t *hdd_ctx) * * Return: CDF_STATUS_SUCCESS */ -CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * - base_channels, +CDF_STATUS cds_get_channel_list_with_power(struct channel_power + *base_channels, uint8_t *num_base_channels, - tChannelListWithPower * - channels_40mhz, + struct channel_power + *channels_40mhz, uint8_t *num_40mhz_channels) { CDF_STATUS status = CDF_STATUS_SUCCESS; @@ -381,18 +372,18 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * if (base_channels && num_base_channels) { count = 0; for (i = 0; i <= RF_CHAN_14; i++) { - if (reg_channels[i].enabled) { - base_channels[count].chanId = + if (reg_channels[i].state) { + base_channels[count].chan_num = chan_mapping[i].chan_num; - base_channels[count++].pwr = + base_channels[count++].power = reg_channels[i].pwr_limit; } } for (i = RF_CHAN_36; i <= RF_CHAN_184; i++) { - if (reg_channels[i].enabled) { - base_channels[count].chanId = + if (reg_channels[i].state) { + base_channels[count].chan_num = chan_mapping[i].chan_num; - base_channels[count++].pwr = + base_channels[count++].power = reg_channels[i].pwr_limit; } } @@ -403,19 +394,19 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * count = 0; for (i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++) { - if (reg_channels[i].enabled) { - channels_40mhz[count].chanId = + if (reg_channels[i].state) { + channels_40mhz[count].chan_num = chan_mapping[i].chan_num; - channels_40mhz[count++].pwr = + channels_40mhz[count++].power = reg_channels[i].pwr_limit; } } for (i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++) { - if (reg_channels[i].enabled) { - channels_40mhz[count].chanId = + if (reg_channels[i].state) { + channels_40mhz[count].chan_num = chan_mapping[i].chan_num; - channels_40mhz[count++].pwr = + channels_40mhz[count++].power = reg_channels[i].pwr_limit; } } @@ -431,7 +422,7 @@ CDF_STATUS cds_get_channel_list_with_power(tChannelListWithPower * * * Return: CDF_STATUS */ -CDF_STATUS cds_read_default_country(country_code_t default_country) +CDF_STATUS cds_read_default_country(uint8_t *default_country) { hdd_context_t *hdd_ctx; @@ -444,7 +435,7 @@ CDF_STATUS cds_read_default_country(country_code_t default_country) memcpy(default_country, hdd_ctx->reg.def_country, - sizeof(country_code_t)); + CDS_COUNTRY_CODE_LEN + 1); CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "default country is %c%c\n", @@ -460,7 +451,7 @@ CDF_STATUS cds_read_default_country(country_code_t default_country) * * Return: enum for the channel */ -static eRfChannels cds_get_channel_enum(uint32_t chan_num) +static enum channel_enum cds_get_channel_enum(uint32_t chan_num) { uint32_t loop; @@ -479,17 +470,17 @@ static eRfChannels cds_get_channel_enum(uint32_t chan_num) * cds_get_channel_state() - get the channel state * @chan_num: channel number * - * Return: CHANNEL_STATE + * Return: channel state */ -CHANNEL_STATE cds_get_channel_state(uint32_t chan_num) +enum channel_state cds_get_channel_state(uint32_t chan_num) { - eRfChannels chan_enum; + enum channel_enum chan_enum; chan_enum = cds_get_channel_enum(chan_num); if (INVALID_RF_CHANNEL == chan_enum) return CHANNEL_STATE_INVALID; else - return reg_channels[chan_enum].enabled; + return reg_channels[chan_enum].state; } @@ -497,19 +488,19 @@ CHANNEL_STATE cds_get_channel_state(uint32_t chan_num) * cds_get_bonded_channel_state() - get the bonded channel state * @channel_num: channel number * - * Return: CHANNEL_STATE + * Return: channel state */ -CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, +enum channel_state cds_get_bonded_channel_state(uint32_t chan_num, enum channel_width ch_width) { - eRfChannels chan_enum; + enum channel_enum chan_enum; bool bw_enabled = false; chan_enum = cds_get_channel_enum(chan_num); if (INVALID_RF_CHANNEL == chan_enum) return CHANNEL_STATE_INVALID; - if (reg_channels[chan_enum].enabled) { + if (reg_channels[chan_enum].state) { if (CHAN_WIDTH_5MHZ == ch_width) bw_enabled = 1; else if (CHAN_WIDTH_10MHZ == ch_width) @@ -530,7 +521,7 @@ CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, } if (bw_enabled) - return reg_channels[chan_enum].enabled; + return reg_channels[chan_enum].state; else return CHANNEL_STATE_DISABLE; } @@ -543,13 +534,13 @@ CHANNEL_STATE cds_get_bonded_channel_state(uint32_t chan_num, */ enum channel_width cds_get_max_channel_bw(uint32_t chan_num) { - eRfChannels chan_enum; + enum channel_enum chan_enum; enum channel_width chan_bw = CHAN_WIDTH_0MHZ; chan_enum = cds_get_channel_enum(chan_num); if ((INVALID_RF_CHANNEL != chan_enum) && - (CHANNEL_STATE_DISABLE != reg_channels[chan_enum].enabled)) { + (CHANNEL_STATE_DISABLE != reg_channels[chan_enum].state)) { if (!(reg_channels[chan_enum].flags & IEEE80211_CHAN_NO_160MHZ)) @@ -673,9 +664,8 @@ CDF_STATUS cds_get_dfs_region(uint8_t *dfs_region) * CDF_STATUS_E_EMPTY country table empty */ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, - const country_code_t - country_code, - v_CountryInfoSource_t source) + const uint8_t *country_alpha2, + enum country_src source) { hdd_context_t *hdd_ctx = NULL; struct wiphy *wiphy = NULL; @@ -688,10 +678,10 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, *reg_domain_ptr = 0; - if (COUNTRY_QUERY == source) + if (SOURCE_QUERY == source) return CDF_STATUS_SUCCESS; - if (NULL == country_code) { + if (NULL == country_alpha2) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, ("Country code array is NULL")); return CDF_STATUS_E_FAULT; @@ -713,16 +703,16 @@ CDF_STATUS cds_get_reg_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, wiphy = hdd_ctx->wiphy; - if ((COUNTRY_INIT == source) && (false == init_by_reg_core)) { + if ((SOURCE_DRIVER == source) && (false == init_by_reg_core)) { init_by_driver = true; - if (('0' != country_code[0]) || ('0' != country_code[1])) { + if (('0' != country_alpha2[0]) || ('0' != country_alpha2[1])) { INIT_COMPLETION(hdd_ctx->reg_init); - regulatory_hint(wiphy, country_code); + regulatory_hint(wiphy, country_alpha2); wait_for_completion_timeout(&hdd_ctx->reg_init, msecs_to_jiffies(REG_WAIT_TIME)); } - } else if (COUNTRY_IE == source || COUNTRY_USER == source) { - regulatory_hint_user(country_code, + } else if (SOURCE_11D == source || SOURCE_USERSPACE == source) { + regulatory_hint_user(country_alpha2, NL80211_USER_REG_HINT_USER); } @@ -858,11 +848,11 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, } if (chan->flags & IEEE80211_CHAN_DISABLED) { - temp_chan_k->enabled = + temp_chan_k->state = CHANNEL_STATE_DISABLE; temp_chan_k->flags = chan->flags; if (n != -1) { - temp_chan_n->enabled = + temp_chan_n->state = CHANNEL_STATE_DISABLE; temp_chan_n->flags = chan->flags; } @@ -881,7 +871,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, chan->flags |= IEEE80211_CHAN_PASSIVE_SCAN; #endif - temp_chan_k->enabled = CHANNEL_STATE_DFS; + temp_chan_k->state = CHANNEL_STATE_DFS; temp_chan_k->pwr_limit = chan->max_power; temp_chan_k->flags = chan->flags; @@ -890,10 +880,10 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) { - temp_chan_n->enabled = + temp_chan_n->state = CHANNEL_STATE_DISABLE; } else { - temp_chan_n->enabled = + temp_chan_n->state = CHANNEL_STATE_DFS; temp_chan_n->pwr_limit = chan->max_power-3; @@ -904,17 +894,17 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, IEEE80211_CHAN_NO_80MHZ) == 0) hdd_ctx->isVHT80Allowed = 1; } else { - temp_chan_k->enabled = CHANNEL_STATE_ENABLE; + temp_chan_k->state = CHANNEL_STATE_ENABLE; temp_chan_k->pwr_limit = chan->max_power; temp_chan_k->flags = chan->flags; if (n != -1) { if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) { - temp_chan_n->enabled = + temp_chan_n->state = CHANNEL_STATE_DISABLE; } else { - temp_chan_n->enabled = + temp_chan_n->state = CHANNEL_STATE_ENABLE; temp_chan_n->pwr_limit = chan->max_power - 3; @@ -931,7 +921,7 @@ static int cds_process_regulatory_data(struct wiphy *wiphy, if (0 == (hdd_ctx->reg.eeprom_rd_ext & (1 << WHAL_REG_EXT_FCC_CH_144))) { temp_chan = &(reg_channels[RF_CHAN_144]); - temp_chan->enabled = + temp_chan->state = CHANNEL_STATE_DISABLE; } @@ -1038,7 +1028,7 @@ void __hdd_reg_notifier(struct wiphy *wiphy, } if (NL80211_REGDOM_SET_BY_CORE == request->initiator) { - hdd_ctx->reg.cc_src = COUNTRY_CODE_SET_BY_CORE; + hdd_ctx->reg.cc_src = SOURCE_CORE; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(WITH_BACKPORTS) if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) #else @@ -1046,9 +1036,9 @@ void __hdd_reg_notifier(struct wiphy *wiphy, #endif reset = true; } else if (NL80211_REGDOM_SET_BY_DRIVER == request->initiator) - hdd_ctx->reg.cc_src = COUNTRY_CODE_SET_BY_DRIVER; + hdd_ctx->reg.cc_src = SOURCE_DRIVER; else { - hdd_ctx->reg.cc_src = COUNTRY_CODE_SET_BY_USER; + hdd_ctx->reg.cc_src = SOURCE_USERSPACE; #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) && !defined(WITH_BACKPORTS) if ((request->alpha2[0] == '0') && (request->alpha2[1] == '0') && @@ -1138,7 +1128,7 @@ CDF_STATUS cds_regulatory_init(void) return CDF_STATUS_E_FAULT; } - reg_info->cc_src = COUNTRY_CODE_SET_BY_DRIVER; + reg_info->cc_src = SOURCE_DRIVER; ret_val = cds_fill_some_regulatory_info(reg_info); if (ret_val) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 1806541bbc05..686e16e2e448 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5242,7 +5242,7 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) { int i, j; - CHANNEL_STATE channelEnabledState; + enum channel_state channelEnabledState; ENTER(); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6a4e405da5a3..7be37c17fd84 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4706,7 +4706,7 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) hdd_context_t *hdd_ctxt; tSirChAvoidIndType *ch_avoid_indi; uint8_t range_loop; - eRfChannels channel_loop, start_channel_idx = INVALID_RF_CHANNEL, + enum channel_enum channel_loop, start_channel_idx = INVALID_RF_CHANNEL, end_channel_idx = INVALID_RF_CHANNEL; uint16_t start_channel; uint16_t end_channel; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 93c71024a27e..a077817867f4 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2042,7 +2042,7 @@ typedef struct sSirPlmReq { uint16_t measDuration; /* in TU's,STA goes off-ch */ /* no of times the STA should cycle through PLM ch list */ uint8_t burstLen; - tPowerdBm desiredTxPwr; /* desired tx power */ + int8_t desiredTxPwr; /* desired tx power */ struct cdf_mac_addr mac_addr; /* MC dest addr */ /* no of channels */ uint8_t plmNumCh; diff --git a/core/mac/src/cfg/cfg_api.c b/core/mac/src/cfg/cfg_api.c index 6e3d63e8f343..e5578431e907 100644 --- a/core/mac/src/cfg/cfg_api.c +++ b/core/mac/src/cfg/cfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -572,19 +572,22 @@ tSirRetStatus wlan_cfg_get_str_len(tpAniSirGlobal pMac, uint16_t cfgId, } /*** end wlan_cfg_get_str_len() ***/ -/*------------------------------------------------------------- - \fn cfg_get_dot11d_transmit_power - \brief This function returns the regulatory max transmit power - \param pMac - \return tPowerdBm - Power - \-------------------------------------------------------------*/ -static tPowerdBm +/** + * cfg_get_dot11d_transmit_power() - regulatory max transmit power + * @pMac: pointer to mac data + * @cfgId: configuration ID + * @cfgLength: configuration length + * @channel: channel number + * + * Return: int8_t - power + */ +static int8_t cfg_get_dot11d_transmit_power(tpAniSirGlobal pMac, uint16_t cfgId, uint32_t cfgLength, uint8_t channel) { uint8_t *pCountryInfo = NULL; uint8_t count = 0; - tPowerdBm maxTxPwr = WMA_MAX_TXPOWER_INVALID; + int8_t maxTxPwr = WMA_MAX_TXPOWER_INVALID; /* At least one element is present */ if (cfgLength < sizeof(tSirMacChanInfo)) { @@ -644,11 +647,12 @@ error: \param channel \param rfBand -----------------------------------------------------------------------*/ -tPowerdBm cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, uint8_t channel) +int8_t cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, + uint8_t channel) { uint32_t cfgLength = 0; uint16_t cfgId = 0; - tPowerdBm maxTxPwr; + int8_t maxTxPwr; eRfBandMode rfBand = eRF_BAND_UNKNOWN; if ((channel >= SIR_11A_CHANNEL_BEGIN) && diff --git a/core/mac/src/include/cfg_api.h b/core/mac/src/include/cfg_api.h index e165d5a3622d..b6ed90796e01 100644 --- a/core/mac/src/include/cfg_api.h +++ b/core/mac/src/include/cfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012,2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -101,8 +101,8 @@ tSirRetStatus wlan_cfg_get_str_max_len(tpAniSirGlobal, uint16_t, uint32_t *); tSirRetStatus wlan_cfg_get_str_len(tpAniSirGlobal, uint16_t, uint32_t *); /* / Get the regulatory tx power on given channel */ -tPowerdBm cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, - uint8_t channel); +int8_t cfg_get_regulatory_max_transmit_power(tpAniSirGlobal pMac, + uint8_t channel); /* / Dump CFG data to memory */ void cfgDump(uint32_t *); diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 16ebd4dd5bf5..4a5b5752a791 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -276,10 +276,11 @@ typedef struct sPESession /* Added to Support BT-AMP */ #endif uint32_t lim11hEnable; - tPowerdBm maxTxPower; /* MIN (Regulatory and local power constraint) */ + int8_t maxTxPower; /* MIN (Regulatory and local power constraint) */ enum tCDF_ADAPTER_MODE pePersona; + #if defined WLAN_FEATURE_VOWIFI - tPowerdBm txMgmtPower; + int8_t txMgmtPower; #endif #ifdef WLAN_FEATURE_VOWIFI_11R diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h index 849fa5c17919..998364e121de 100644 --- a/core/mac/src/pe/include/rrm_api.h +++ b/core/mac/src/pe/include/rrm_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -45,8 +45,8 @@ #define RRM_BCN_RPT_NO_BSS_INFO 0 #define RRM_BCN_RPT_MIN_RPT 1 -uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, tPowerdBm regMax, - tPowerdBm apTxPower); +uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, int8_t regMax, + int8_t apTxPower); extern tSirRetStatus rrm_initialize(tpAniSirGlobal pMac); @@ -75,14 +75,14 @@ extern tSirRetStatus rrm_process_neighbor_report_response(tpAniSirGlobal pMac, extern void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg); extern tSirRetStatus rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, - tPowerdBm txPower, + int8_t txPower, tpPESession pSessionEntry); -extern tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, +extern int8_t rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry); extern void rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, - tPowerdBm txPower, tpPESession pSessionEntry); + int8_t txPower, tpPESession pSessionEntry); extern tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry); diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h index a1db83544444..6d829fffa999 100644 --- a/core/mac/src/pe/include/rrm_global.h +++ b/core/mac/src/pe/include/rrm_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -214,7 +214,7 @@ typedef struct sRrmPEContext { * gets it from bss decsription. */ tRRMCaps rrmEnabledCaps; - tPowerdBm txMgmtPower; + int8_t txMgmtPower; /* Dialog token for the request initiated from station. */ uint8_t DialogToken; tpRRMReq pCurrentReq; diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 008b8c4c860e..cd2b14c8cb0c 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -5012,7 +5012,7 @@ tSirRetStatus lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac, tSirAssocReq *assoc, tpPESession psessionEntry) { - tPowerdBm localMaxTxPower; + int8_t localMaxTxPower; uint32_t localPwrConstraint; localMaxTxPower = @@ -5026,7 +5026,7 @@ tSirRetStatus lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac, FL("Unable to get Local Power Constraint from cfg")); return eSIR_FAILURE; } - localMaxTxPower -= (tPowerdBm) localPwrConstraint; + localMaxTxPower -= (int8_t) localPwrConstraint; /** * The min Tx Power of the associating station should not be greater than (regulatory diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index 72784141a56a..e37f09d58e80 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -844,8 +844,8 @@ void lim_fill_ft_session(tpAniSirGlobal pMac, tpPESession pftSessionEntry, tpPESession psessionEntry) { uint8_t currentBssUapsd; - tPowerdBm localPowerConstraint; - tPowerdBm regMax; + int8_t localPowerConstraint; + int8_t regMax; tSchBeaconStruct *pBeaconStruct; uint32_t selfDot11Mode; ePhyChanBondState cbEnabledMode; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 4d16c164c892..21b1bb2ca939 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -2899,7 +2899,7 @@ void lim_complete_mlm_scan(tpAniSirGlobal mac_ctx, tSirResultCodes ret_code) */ void lim_set_channel(tpAniSirGlobal mac_ctx, uint8_t channel, uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, - phy_ch_width ch_width, tPowerdBm max_tx_power, + phy_ch_width ch_width, int8_t max_tx_power, uint8_t pe_session_id) { #if !defined WLAN_FEATURE_VOWIFI @@ -2927,7 +2927,7 @@ void lim_set_channel(tpAniSirGlobal mac_ctx, uint8_t channel, /* Send WMA_CHNL_SWITCH_IND to HAL */ lim_send_switch_chnl_params(mac_ctx, channel, ch_center_freq_seg0, ch_center_freq_seg1, ch_width, - (tPowerdBm) localPwrConstraint, + (int8_t)localPwrConstraint, pe_session_id, false); #endif } diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index e11f9ac36e3f..47caaf885c71 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1516,7 +1516,7 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) tpPESession session = NULL; uint8_t sme_session_id; uint16_t sme_transaction_id; - tPowerdBm local_power_constraint = 0, reg_max = 0; + int8_t local_power_constraint = 0, reg_max = 0; uint16_t ie_len; uint8_t *vendor_ie; tSirBssDescription bss_desc; @@ -2030,7 +2030,7 @@ end: } #if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI -uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower, +uint8_t lim_get_max_tx_power(int8_t regMax, int8_t apTxPower, uint8_t iniTxPower) { uint8_t maxTxPower = 0; @@ -2071,7 +2071,7 @@ static void __lim_process_sme_reassoc_req(tpAniSirGlobal mac_ctx, uint8_t session_id; uint8_t sme_session_id; uint16_t transaction_id; - tPowerdBm local_pwr_constraint = 0, reg_max = 0; + int8_t local_pwr_constraint = 0, reg_max = 0; uint32_t tele_bcn_en = 0; uint16_t size; @@ -4437,7 +4437,7 @@ void __lim_process_report_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg) * @return None */ tSirRetStatus -lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, +lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, int8_t txPower, tpPESession pSessionEntry) { tpMaxTxPowerParams pMaxTxParams = NULL; @@ -5038,7 +5038,7 @@ static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx, tpSirChanChangeRequest ch_change_req; tpPESession session_entry; uint8_t session_id; /* PE session_id */ - tPowerdBm max_tx_pwr; + int8_t max_tx_pwr; uint32_t val = 0; if (msg_buf == NULL) { diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index f05f00c15904..2ec7b318a14e 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -77,7 +77,7 @@ void lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, uint16_t ie_len, uint8_t *qos_cap, uint16_t *prop_cap, uint8_t *uapsd, - tPowerdBm *local_constraint, tpPESession session) + int8_t *local_constraint, tpPESession session) { tSirProbeRespBeacon *beacon_struct; #if !defined WLAN_FEATURE_VOWIFI diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.h b/core/mac/src/pe/lim/lim_prop_exts_utils.h index a648a78ddbfd..6c0fd89b1886 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.h +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -54,7 +54,7 @@ uint32_t limComputeAvg(tpAniSirGlobal, uint32_t, uint32_t); /* / Function to extract AP's HCF capability from IE fields */ void lim_extract_ap_capability(tpAniSirGlobal, uint8_t *, uint16_t, uint8_t *, - uint16_t *, uint8_t *, tPowerdBm *, tpPESession); + uint16_t *, uint8_t *, int8_t *, tpPESession); tStaRateMode lim_get_sta_peer_type(tpAniSirGlobal, tpDphHashNode, tpPESession); #ifdef WLAN_FEATURE_11AC diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c index 3e6f53b6ad76..264cf02c800f 100644 --- a/core/mac/src/pe/lim/lim_send_messages.c +++ b/core/mac/src/pe/lim/lim_send_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -220,7 +220,7 @@ tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, phy_ch_width ch_width, - tPowerdBm maxTxPower, + int8_t maxTxPower, uint8_t peSessionId, uint8_t is_restart) #endif diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h index 95161fbab130..e8b4665a2962 100644 --- a/core/mac/src/pe/lim/lim_send_messages.h +++ b/core/mac/src/pe/lim/lim_send_messages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -69,7 +69,7 @@ tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, phy_ch_width ch_width, - tPowerdBm maxTxPower, + int8_t maxTxPower, uint8_t peSessionId, uint8_t is_restart); #else diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index a51c3d5f0ca5..514b70cdee9a 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -558,7 +558,7 @@ uint32_t lim_defer_msg(tpAniSirGlobal, tSirMsgQ *); /* / Function that Switches the Channel and sets the CB Mode */ void lim_set_channel(tpAniSirGlobal pMac, uint8_t channel, uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1, - phy_ch_width ch_width, tPowerdBm maxTxPower, + phy_ch_width ch_width, int8_t maxTxPower, uint8_t peSessionId); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 41801aa1bbf0..98cb55117ff7 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -2738,7 +2738,7 @@ void lim_switch_primary_channel(tpAniSirGlobal pMac, uint8_t newChannel, return; } lim_send_switch_chnl_params(pMac, newChannel, 0, 0, CH_WIDTH_20MHZ, - (tPowerdBm) localPwrConstraint, + localPwrConstraint, psessionEntry->peSessionId, false); #endif return; @@ -4975,7 +4975,7 @@ void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac, lim_send_switch_chnl_params(pMac, (uint8_t) pHTInfo->primaryChannel, center_freq, 0, psessionEntry->htRecommendedTxWidthSet, - (tPowerdBm) localPwrConstraint, + (int8_t)localPwrConstraint, psessionEntry->peSessionId, true); #endif diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index cd9d6a1a1bf3..36fc97bc1825 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -95,9 +95,9 @@ void lim_print_msg_name(tpAniSirGlobal pMac, uint16_t logLevel, uint32_t msgType #if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI extern tSirRetStatus lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, - tPowerdBm txPower, + int8_t txPower, tpPESession pSessionEntry); -extern uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower, +extern uint8_t lim_get_max_tx_power(int8_t regMax, int8_t apTxPower, uint8_t iniTxPower); #endif uint8_t lim_is_addr_bc(tSirMacAddr); diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index 1104a938f528..b4f499bc0edf 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -55,7 +55,7 @@ uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, - tPowerdBm regMax, tPowerdBm apTxPower) + int8_t regMax, int8_t apTxPower) { uint8_t maxTxPower = 0; uint8_t txPower = CDF_MIN(regMax, (apTxPower)); @@ -88,7 +88,7 @@ rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, * @return None */ void -rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, tPowerdBm txPower, +rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, int8_t txPower, tpPESession pSessionEntry) { lim_log(pMac, LOG3, "Cache Mgmt Tx Power = %d", txPower); @@ -115,7 +115,7 @@ rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, tPowerdBm txPower, * @param pSessionEntry session entry. * @return txPower */ -tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry) +int8_t rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry) { lim_log(pMac, LOG3, "RrmGetMgmtTxPower called"); @@ -145,7 +145,7 @@ tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry) * @return None */ tSirRetStatus -rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower, +rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, int8_t txPower, tpPESession pSessionEntry) { tpMaxTxPowerParams pMaxTxParams; @@ -288,8 +288,7 @@ rrm_process_link_measurement_request(tpAniSirGlobal pMac, if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) && (eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac, - (tPowerdBm) (LinkReport. - txPower), + LinkReport.txPower, pSessionEntry))) { PELOGW(lim_log (pMac, LOGW, @@ -299,8 +298,8 @@ rrm_process_link_measurement_request(tpAniSirGlobal pMac, pSessionEntry->maxTxPower, LinkReport.txPower, pLinkReq->MaxTxPower.maxTxPower); ) - pSessionEntry->maxTxPower = - (tPowerdBm) (LinkReport.txPower); + pSessionEntry->maxTxPower = + LinkReport.txPower; } LinkReport.dialogToken = pLinkReq->DialogToken.token; diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index 489d75808d6b..ca769bfc5764 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -716,7 +716,7 @@ static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, tpPESession session) { - tPowerdBm localRRMConstraint = 0; + int8_t localRRMConstraint = 0; uint8_t bssIdx = 0; tUpdateBeaconParams beaconParams; uint8_t sendProbeReq = false; @@ -724,7 +724,7 @@ static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info); #endif #if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI - tPowerdBm regMax = 0, maxTxPower = 0; + int8_t regMax = 0, maxTxPower = 0; #endif cdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); beaconParams.paramChangeBitmap = 0; @@ -792,7 +792,7 @@ static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx, #if defined FEATURE_WLAN_ESE if (session->isESEconnection) { - tPowerdBm localESEConstraint = 0; + int8_t localESEConstraint = 0; if (bcn->eseTxPwr.present) { localESEConstraint = bcn->eseTxPwr.power_limit; maxTxPower = lim_get_max_tx_power(maxTxPower, diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index 9e09a08b7436..4ed3b3636314 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -2016,7 +2016,7 @@ uint8_t sap_select_channel(tHalHandle halHandle, ptSapContext pSapCtx, if ((safe_channels[i].channelNumber >= startChannelNum) && (safe_channels[i].channelNumber <= endChannelNum)) { - CHANNEL_STATE channel_type = + enum channel_state channel_type = cds_get_channel_state(safe_channels[i]. channelNumber); diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index a7e5d4d6f9b1..c0a7a506f578 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -692,8 +692,8 @@ typedef struct tagCsrScanStruct { uint8_t scanResultCfgAgingTime; tSirScanType curScanType; tCsrChannel channels11d; - tChannelListWithPower defaultPowerTable[WNI_CFG_VALID_CHANNEL_LIST_LEN]; - tChannelListWithPower + struct channel_power defaultPowerTable[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + struct channel_power defaultPowerTable40MHz[WNI_CFG_VALID_CHANNEL_LIST_LEN]; uint32_t numChannelsDefault; tCsrChannel base_channels; /* The channel base to work on */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 7b69bbeaf287..df5dc9e4dced 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -192,7 +192,7 @@ typedef enum { ------------------------------------------------------------------------*/ CDF_STATUS sme_open(tHalHandle hHal); CDF_STATUS sme_init_chan_list(tHalHandle hal, uint8_t *alpha2, - COUNTRY_CODE_SOURCE cc_src); + enum country_src cc_src); CDF_STATUS sme_close(tHalHandle hHal); CDF_STATUS sme_start(tHalHandle hHal); CDF_STATUS sme_stop(tHalHandle hHal, tHalStopType stopType); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 41d15b960acc..06163a8fa913 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1106,11 +1106,11 @@ CDF_STATUS sme_open(tHalHandle hHal) * sme_init_chan_list, triggers channel setup based on country code. */ CDF_STATUS sme_init_chan_list(tHalHandle hal, uint8_t *alpha2, - COUNTRY_CODE_SOURCE cc_src) + enum country_src cc_src) { tpAniSirGlobal pmac = PMAC_STRUCT(hal); - if ((cc_src == COUNTRY_CODE_SET_BY_USER) && + if ((cc_src == SOURCE_USERSPACE) && (pmac->roam.configParam.fSupplicantCountryCodeHasPriority)) { pmac->roam.configParam.Is11dSupportEnabled = false; } @@ -6945,7 +6945,7 @@ CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf) tAniChangeCountryCodeReq *pMsg; v_REGDOMAIN_t domainIdIoctl; CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; - static country_code_t default_country; + static uint8_t default_country[CDS_COUNTRY_CODE_LEN + 1]; pMsg = (tAniChangeCountryCodeReq *) pMsgBuf; /* @@ -7008,7 +7008,8 @@ CDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf) status = csr_get_regulatory_domain_for_country(pMac, pMac->scan.countryCodeCurrent, (v_REGDOMAIN_t *) & - domainIdIoctl, COUNTRY_QUERY); + domainIdIoctl, + SOURCE_QUERY); if (status != CDF_STATUS_SUCCESS) { sms_log(pMac, LOGE, FL(" fail to get regId %d"), domainIdIoctl); return status; @@ -7096,12 +7097,12 @@ sme_handle_generic_change_country_code(tpAniSirGlobal mac_ctx, && (mac_ctx->scan.countryCode11d[1] == 0)) status = csr_get_regulatory_domain_for_country(mac_ctx, "00", (v_REGDOMAIN_t *) ®_domain_id, - COUNTRY_IE); + SOURCE_11D); else status = csr_get_regulatory_domain_for_country(mac_ctx, mac_ctx->scan.countryCode11d, (v_REGDOMAIN_t *) ®_domain_id, - COUNTRY_IE); + SOURCE_11D); return CDF_STATUS_E_FAILURE; } @@ -11535,12 +11536,12 @@ CDF_STATUS sme_get_reg_info(tHalHandle hHal, uint8_t chanId, return status; for (i = 0; i < WNI_CFG_VALID_CHANNEL_LIST_LEN; i++) { - if (pMac->scan.defaultPowerTable[i].chanId == chanId) { + if (pMac->scan.defaultPowerTable[i].chan_num == chanId) { SME_SET_CHANNEL_REG_POWER(*regInfo1, - pMac->scan.defaultPowerTable[i].pwr); + pMac->scan.defaultPowerTable[i].power); SME_SET_CHANNEL_MAX_TX_POWER(*regInfo2, - pMac->scan.defaultPowerTable[i].pwr); + pMac->scan.defaultPowerTable[i].power); found = true; break; } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index e3189eae4f33..922b80743fe7 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -341,7 +341,7 @@ CDF_STATUS csr_init_chan_list(tpAniSirGlobal mac, uint8_t *alpha2) { CDF_STATUS status; v_REGDOMAIN_t reg_id; - v_CountryInfoSource_t source = COUNTRY_INIT; + enum country_src source = SOURCE_DRIVER; mac->scan.countryCodeDefault[0] = alpha2[0]; mac->scan.countryCodeDefault[1] = alpha2[1]; @@ -388,7 +388,7 @@ CDF_STATUS csr_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode) cntryCodeLength = WNI_CFG_COUNTRY_CODE_LEN; status = csr_get_regulatory_domain_for_country(pMac, apCntryCode, ®Id, - COUNTRY_USER); + SOURCE_USERSPACE); if (status != CDF_STATUS_SUCCESS) { sms_log(pMac, LOGE, FL(" fail to get regId for country Code %.2s"), @@ -436,7 +436,7 @@ CDF_STATUS csr_set_channels(tHalHandle hHal, tCsrConfigParam *pParam) pMac->scan.base_channels.channelList[index]; pParam->Csr11dinfo.ChnPower[index].numChannels = 1; pParam->Csr11dinfo.ChnPower[index].maxtxPower = - pMac->scan.defaultPowerTable[index].pwr; + pMac->scan.defaultPowerTable[index].power; } pParam->Csr11dinfo.Channels.numChannels = pMac->scan.base_channels.numChannels; @@ -462,7 +462,7 @@ CDF_STATUS csr_close(tpAniSirGlobal pMac) return status; } -static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * +static int8_t csr_find_channel_pwr(struct channel_power * pdefaultPowerTable, uint8_t ChannelNum) { @@ -470,8 +470,8 @@ static tPowerdBm csr_find_channel_pwr(tChannelListWithPower * /* 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; + if (pdefaultPowerTable[i].chan_num == ChannelNum) + return pdefaultPowerTable[i].power; } /* could not find the channel list in default list */ /* this should not have occured */ @@ -2521,7 +2521,7 @@ CDF_STATUS csr_get_channel_and_power_list(tpAniSirGlobal pMac) /* structure -- this will be used as the scan list */ for (Index = 0; Index < num20MHzChannelsFound; Index++) { pMac->scan.base_channels.channelList[Index] = - pMac->scan.defaultPowerTable[Index].chanId; + pMac->scan.defaultPowerTable[Index].chan_num; } pMac->scan.base_channels.numChannels = num20MHzChannelsFound; @@ -2530,7 +2530,8 @@ CDF_STATUS csr_get_channel_and_power_list(tpAniSirGlobal pMac) } for (Index = 0; Index < num40MHzChannelsFound; Index++) { pMac->scan.base40MHzChannels.channelList[Index] = - pMac->scan.defaultPowerTable40MHz[Index].chanId; + pMac->scan.defaultPowerTable40MHz[Index]. + chan_num; } pMac->scan.base40MHzChannels.numChannels = num40MHzChannelsFound; @@ -11868,11 +11869,11 @@ CDF_STATUS csr_get_cfg_valid_channels(tpAniSirGlobal pMac, uint8_t *pChannels, return CDF_STATUS_SUCCESS; } -tPowerdBm csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel) +int8_t csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel) { uint32_t cfgLength = 0; uint16_t cfgId = 0; - tPowerdBm maxTxPwr = 0; + int8_t maxTxPwr = 0; uint8_t *pCountryInfo = NULL; CDF_STATUS status; uint8_t count = 0; diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index c6e446bcdb80..5c44c089c6fa 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -3204,7 +3204,7 @@ static void csr_diag_reset_country_information(tpAniSirGlobal pMac) Index < pMac->scan.base_channels.numChannels; Index++) { p11dLog->TxPwr[Index] = CDF_MIN( - pMac->scan.defaultPowerTable[Index].pwr, + pMac->scan.defaultPowerTable[Index].power, pMac->roam.configParam.nTxPowerCap); } } @@ -3271,7 +3271,7 @@ void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode) if (!CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(pMac, pCountryCode, NULL, - COUNTRY_QUERY))) { + SOURCE_QUERY))) { pCountryCode[0] = '0'; pCountryCode[1] = '0'; } @@ -3367,8 +3367,8 @@ CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry) if (pCountry) { status = csr_get_regulatory_domain_for_country(pMac, pCountry, - &domainId, - COUNTRY_USER); + &domainId, + SOURCE_USERSPACE); if (CDF_IS_STATUS_SUCCESS(status)) { cdf_mem_copy(pMac->scan.countryCodeCurrent, pCountry, @@ -3384,7 +3384,7 @@ CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry) /* Upon return, *pNumChn has the number of channels assigned. */ void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list, uint32_t *num_ch, - tChannelListWithPower *chn_pwr_info) + struct channel_power *chn_pwr_info) { tListElem *entry; uint32_t chn_idx = 0, idx; @@ -3396,10 +3396,10 @@ void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list, ch_set = GET_BASE_ADDR(entry, tCsrChannelPowerInfo, link); for (idx = 0; (idx < ch_set->numChannels) && (chn_idx < *num_ch); idx++) { - chn_pwr_info[chn_idx].chanId = + chn_pwr_info[chn_idx].chan_num = (uint8_t) (ch_set->firstChannel + (idx * ch_set->interChannelOffset)); - chn_pwr_info[chn_idx++].pwr = ch_set->txPower; + chn_pwr_info[chn_idx++].power = ch_set->txPower; } entry = csr_ll_next(list, entry, LL_ACCESS_LOCK); } @@ -3412,7 +3412,7 @@ void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list, void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx) { host_log_802_11d_pkt_type *p11dLog; - tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + struct channel_power chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN]; uint32_t nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp; WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type, @@ -3442,9 +3442,9 @@ void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx) nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN; nChnInfo++) { if (p11dLog->Channels[nTmp] == - chnPwrInfo[nChnInfo].chanId) { + chnPwrInfo[nChnInfo].chan_num) { p11dLog->TxPwr[nTmp] = - chnPwrInfo[nChnInfo].pwr; + chnPwrInfo[nChnInfo].power; break; } } @@ -3476,7 +3476,7 @@ void csr_apply_country_information(tpAniSirGlobal pMac) || 0 == pMac->scan.channelOf11dInfo) return; status = csr_get_regulatory_domain_for_country(pMac, - pMac->scan.countryCode11d, &domainId, COUNTRY_QUERY); + pMac->scan.countryCode11d, &domainId, SOURCE_QUERY); if (!CDF_IS_STATUS_SUCCESS(status)) return; /* Check whether we need to enforce default domain */ @@ -3522,7 +3522,7 @@ void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f) WNI_CFG_VALID_CHANNEL_LIST_LEN, 0); ch_info_start = chan_info; for (idx = 0; idx < max_ch_idx; idx++) { - ch = pMac->scan.defaultPowerTable[idx].chanId; + ch = pMac->scan.defaultPowerTable[idx].chan_num; tmp_bool = (fill_5f && CDS_IS_CHANNEL_5GHZ(ch)) || (!fill_5f && CDS_IS_CHANNEL_24GHZ(ch)); if (!tmp_bool) @@ -3534,10 +3534,10 @@ void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f) } chan_info->firstChanNum = - pMac->scan.defaultPowerTable[idx].chanId; + pMac->scan.defaultPowerTable[idx].chan_num; chan_info->numChannels = 1; chan_info->maxTxPower = - CDF_MIN(pMac->scan.defaultPowerTable[idx].pwr, + CDF_MIN(pMac->scan.defaultPowerTable[idx].power, pMac->roam.configParam.nTxPowerCap); chan_info++; count++; @@ -3598,7 +3598,7 @@ bool csr_learn_11dcountry_information(tpAniSirGlobal pMac, goto free_ie; status = csr_get_regulatory_domain_for_country(pMac, pIesLocal->Country.country, &domainId, - COUNTRY_QUERY); + SOURCE_QUERY); if (CDF_IS_STATUS_SUCCESS(status) && (domainId == REGDOMAIN_WORLD)) goto free_ie; @@ -3610,7 +3610,7 @@ bool csr_learn_11dcountry_information(tpAniSirGlobal pMac, pCountryCodeSelected = pMac->scan.countryCodeElected; status = csr_get_regulatory_domain_for_country(pMac, - pCountryCodeSelected, &domainId, COUNTRY_IE); + pCountryCodeSelected, &domainId, SOURCE_11D); if (status != CDF_STATUS_SUCCESS) { sms_log(pMac, LOGE, FL("fail to get regId %d"), domainId); fRet = false; @@ -5400,8 +5400,9 @@ CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx, uint32_t len = sizeof(mac_ctx->roam.validChannelList); uint32_t index = 0; uint32_t new_index = 0; - CHANNEL_STATE channel_state; + enum channel_state channel_state; uint8_t ibss_channel = 0; + bool skip_dfs_chnl = mac_ctx->roam.configParam.initial_scan_no_dfs_chnl || !mac_ctx->scan.fEnableDFSChnlScan; diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 7e2a489def6d..ab0f12719bca 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -396,7 +396,7 @@ CDF_STATUS csr_get_cfg_valid_channels(tpAniSirGlobal pMac, uint8_t *pChannels, uint32_t *pNumChan); void csr_roam_ccm_cfg_set_callback(tpAniSirGlobal pMac, int32_t result); -tPowerdBm csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel); +int8_t csr_get_cfg_max_tx_power(tpAniSirGlobal pMac, uint8_t channel); /* To free the last roaming profile */ void csr_free_roam_profile(tpAniSirGlobal pMac, uint32_t sessionId); @@ -584,7 +584,7 @@ CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry); CDF_STATUS csr_get_regulatory_domain_for_country(tpAniSirGlobal pMac, uint8_t *pCountry, v_REGDOMAIN_t *pDomainId, - v_CountryInfoSource_t source); + enum country_src source); /* some support functions */ bool csr_is11d_supported(tpAniSirGlobal pMac); diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 95faef7eccf1..dfecf1bc92e3 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -5285,7 +5285,7 @@ tSirResultCodes csr_get_de_auth_rsp_status_code(tSirSmeDeauthRsp *pSmeRsp) tSirScanType csr_get_scan_type(tpAniSirGlobal pMac, uint8_t chnId) { tSirScanType scanType = eSIR_PASSIVE_SCAN; - CHANNEL_STATE channelEnabledType; + enum channel_state channelEnabledType; channelEnabledType = cds_get_channel_state(chnId); if (CHANNEL_STATE_ENABLE == channelEnabledType) { @@ -5395,13 +5395,14 @@ eCsrCfgDot11Mode csr_get_cfg_dot11_mode_from_csr_phy_mode(tCsrRoamProfile *pProf return cfgDot11Mode; } -CDF_STATUS csr_get_regulatory_domain_for_country - (tpAniSirGlobal pMac, - uint8_t *pCountry, - v_REGDOMAIN_t *pDomainId, v_CountryInfoSource_t source) { +CDF_STATUS csr_get_regulatory_domain_for_country(tpAniSirGlobal pMac, + uint8_t *pCountry, + v_REGDOMAIN_t *pDomainId, + enum country_src source) +{ CDF_STATUS status = CDF_STATUS_E_INVAL; CDF_STATUS cdf_status; - country_code_t countryCode; + uint8_t countryCode[CDS_COUNTRY_CODE_LEN + 1]; v_REGDOMAIN_t domainId; if (pCountry) { diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index bf14268e7abf..626df86d8ae4 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -903,8 +903,8 @@ struct wma_txrx_node { uint8_t nss; bool is_channel_switch; uint16_t pause_bitmap; - tPowerdBm tx_power; - tPowerdBm max_tx_power; + int8_t tx_power; + int8_t max_tx_power; uint32_t nwType; #if defined WLAN_FEATURE_VOWIFI_11R void *staKeyParams; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 5bfa717f2f40..3c1728b8c60f 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -317,7 +317,7 @@ typedef struct { uint16_t ht_caps; uint32_t vht_caps; tSirNwType nwType; - tPowerdBm maxTxPower; + int8_t maxTxPower; uint8_t atimIePresent; uint32_t peerAtimWindowLength; uint8_t nonRoamReassoc; @@ -487,8 +487,8 @@ typedef struct { uint8_t respReqd; uint8_t sessionId; #if defined WLAN_FEATURE_VOWIFI - tPowerdBm txMgmtPower; - tPowerdBm maxTxPower; + int8_t txMgmtPower; + int8_t maxTxPower; #endif /* WLAN_FEATURE_VOWIFI */ #if defined WLAN_FEATURE_VOWIFI_11R @@ -615,7 +615,7 @@ typedef struct { CDF_STATUS status; #if defined WLAN_FEATURE_VOWIFI uint32_t startTSF[2]; - tPowerdBm txMgmtPower; + int8_t txMgmtPower; #endif /* WLAN_FEATURE_VOWIFI */ } tStartScanParams, *tpStartScanParams; @@ -900,8 +900,8 @@ typedef struct { #endif /* WLAN_FEATURE_VOWIFI */ uint8_t peSessionId; #if defined WLAN_FEATURE_VOWIFI - tPowerdBm txMgmtPower; - tPowerdBm maxTxPower; + int8_t txMgmtPower; + int8_t maxTxPower; #endif /* WLAN_FEATURE_VOWIFI */ tSirMacAddr selfStaMacAddr; /* the request has power constraints, this should be applied only to @@ -1162,7 +1162,7 @@ typedef struct sMaxTxPowerParams { * In response, * power == tx power used for management frames. */ - tPowerdBm power; + int8_t power; enum tCDF_ADAPTER_MODE dev_mode; } tMaxTxPowerParams, *tpMaxTxPowerParams; @@ -1173,7 +1173,7 @@ typedef struct sMaxTxPowerParams { */ typedef struct sMaxTxPowerPerBandParams { eCsrBand bandInfo; - tPowerdBm power; + int8_t power; } tMaxTxPowerPerBandParams, *tpMaxTxPowerPerBandParams; /** diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 4aac03ff2f7f..fb57c04b6505 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -2704,7 +2704,7 @@ static void wma_vdev_set_bss_params(tp_wma_handle wma, int vdev_id, tSirMacBeaconInterval beaconInterval, uint8_t dtimPeriod, uint8_t shortSlotTimeSupported, - uint8_t llbCoexist, tPowerdBm maxTxPower) + uint8_t llbCoexist, int8_t maxTxPower) { int ret; uint32_t slot_time; @@ -2773,7 +2773,7 @@ static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) struct wma_target_req *msg; uint8_t vdev_id, peer_id; CDF_STATUS status; - tPowerdBm maxTxPower; + int8_t maxTxPower; #ifdef WLAN_FEATURE_11W int ret = 0; #endif /* WLAN_FEATURE_11W */ @@ -3831,7 +3831,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) CDF_STATUS status = CDF_STATUS_SUCCESS; ol_txrx_peer_handle peer; struct wma_txrx_node *iface; - tPowerdBm maxTxPower; + int8_t maxTxPower; int ret = 0; struct wma_target_req *msg; bool peer_assoc_cnf = false; diff --git a/core/wma/src/wma_power.c b/core/wma/src/wma_power.c index 3793675ca3c4..b8f855a53cfd 100644 --- a/core/wma/src/wma_power.c +++ b/core/wma/src/wma_power.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -490,7 +490,7 @@ void wma_set_max_tx_power(WMA_HANDLE handle, uint8_t vdev_id; int ret = -1; void *pdev; - tPowerdBm prev_max_power; + int8_t prev_max_power; pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId.bytes, &vdev_id); -- cgit v1.2.3 From 71b3d7242ccba4a62db3fcc1c473425fcbe3c469 Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Tue, 19 Jan 2016 11:39:54 -0800 Subject: Release 5.0.0.158 Release 5.0.0.158 Change-Id: I4682e3242ba368aa7bd5907811f0365c6b135953 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 3108f2203ad8..840f8fa6be8b 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 157 +#define QWLAN_VERSION_BUILD 158 -#define QWLAN_VERSIONSTR "5.0.0.157" +#define QWLAN_VERSIONSTR "5.0.0.158" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From 2d305045a2fdf4448b9301b3384fcc454f5cb2dc Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Thu, 3 Dec 2015 15:06:15 -0800 Subject: qcacld-3.0: hdd: Refactor wlan_startup (phase 1) In HDD, hdd_wlan_startup which is called by probe is beast of a function to maintain. Over time it has grown to such an extent that it is almost 800 lines of code with in a single function. Divide the beast into logical smaller functions. This is the first phase of changes to add a separate function to allocate and initialize HDD context. Change-Id: I35b6c95c1b09f853e83752123c44e8d21c8af50a CRs-fixed: 959287 --- core/cdf/src/cdf_mc_timer.c | 3 +- core/cds/inc/cds_api.h | 2 +- core/cds/src/cds_api.c | 9 +- core/cds/src/cds_packet.c | 9 +- core/hdd/inc/wlan_hdd_tdls.h | 3 + core/hdd/src/wlan_hdd_cfg80211.c | 29 +-- core/hdd/src/wlan_hdd_cfg80211.h | 2 +- core/hdd/src/wlan_hdd_main.c | 449 ++++++++++++++++++++------------------- core/hdd/src/wlan_hdd_power.c | 2 +- core/hdd/src/wlan_hdd_tdls.c | 15 ++ 10 files changed, 276 insertions(+), 247 deletions(-) diff --git a/core/cdf/src/cdf_mc_timer.c b/core/cdf/src/cdf_mc_timer.c index 0edc8f3d54d1..896e75fa8ab5 100644 --- a/core/cdf/src/cdf_mc_timer.c +++ b/core/cdf/src/cdf_mc_timer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -247,7 +247,6 @@ static void cdf_timer_clean(void); */ void cdf_mc_timer_manager_init(void) { - /* Initalizing the list with maximum size of 60000 */ cdf_list_init(&cdf_timer_list, 1000); cdf_spinlock_init(&cdf_timer_list_lock); return; diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 4e954b9dabd9..059a0d1dea98 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -187,7 +187,7 @@ void cds_deinit(void); CDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context); -CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize); +CDF_STATUS cds_open(void); CDF_STATUS cds_enable(v_CONTEXT_t cds_context); diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index dc2ffef7d5d0..5c36ef3944f5 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -152,8 +152,6 @@ static void cds_set_nan_enable(tMacOpenParameters *param, /** * cds_open() - open the CDS Module - * @p_cds_context: A pointer to where the CDS Context was stored - * @hddContextSize: Size of the HDD context to allocate. * * cds_open() function opens the CDS Scheduler * Upon successful initialization: @@ -166,7 +164,7 @@ static void cds_set_nan_enable(tMacOpenParameters *param, * * Return: CDF status */ -CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize) +CDF_STATUS cds_open(void) { CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; int iter = 0; @@ -447,8 +445,6 @@ CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize) CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS successfully Opened", __func__); - *p_cds_context = gp_cds_context; - return CDF_STATUS_SUCCESS; err_sme_close: @@ -836,6 +832,9 @@ CDF_STATUS cds_close(v_CONTEXT_t cds_context) } cds_deinit_log_completion(); + + gp_cds_context->pHDDContext = NULL; + return CDF_STATUS_SUCCESS; } diff --git a/core/cds/src/cds_packet.c b/core/cds/src/cds_packet.c index 70e5fc10732a..3f0ce95ae657 100644 --- a/core/cds/src/cds_packet.c +++ b/core/cds/src/cds_packet.c @@ -259,12 +259,9 @@ void cds_pkt_proto_trace_init(void) /* Init spin lock to protect global memory */ cdf_spinlock_init(&trace_buffer_lock); trace_buffer_order = 0; - trace_buffer = - cdf_mem_malloc(CDS_PKT_TRAC_MAX_TRACE_BUF * - sizeof(cds_pkt_proto_trace_t)); - cdf_mem_zero((void *)trace_buffer, - CDS_PKT_TRAC_MAX_TRACE_BUF * - sizeof(cds_pkt_proto_trace_t)); + + trace_buffer = cdf_mem_malloc(CDS_PKT_TRAC_MAX_TRACE_BUF * + sizeof(cds_pkt_proto_trace_t)); /* Register callback function to NBUF * Lower layer event also will be reported to here */ diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 6fb191c84c20..db275de7c946 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -607,6 +607,7 @@ int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel); int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset); int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode); int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val); +void hdd_tdls_pre_init(hdd_context_t *hdd_ctx); #else static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, @@ -620,6 +621,8 @@ wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) static inline void wlan_hdd_tdls_exit(hdd_adapter_t *adapter) { } + +static inline void hdd_tdls_pre_init(hdd_context_t *hdd_ctx) { } #endif /* End of FEATURE_WLAN_TDLS */ #endif /* __HDD_TDLS_H */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 686e16e2e448..aa226e1cbd41 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5208,30 +5208,33 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { }, }; -/* - * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc - * This function is called by hdd_wlan_startup() - * during initialization. - * This function is used to allocate wiphy structure. +/** + * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context + * @priv_size: Size of the hdd context. + * + * Allocate wiphy context and hdd context. + * + * Return: hdd context on success and NULL on failure. */ -struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) +hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size) { struct wiphy *wiphy; + hdd_context_t *hdd_ctx; + 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(CDF_TRACE_LEVEL_ERROR, "%s: wiphy init failed", - __func__); + hdd_err("wiphy init failed!\n"); return NULL; } - return wiphy; + hdd_ctx = wiphy_priv(wiphy); + + hdd_ctx->wiphy = wiphy; + + return hdd_ctx; } /* diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 0f24a05691bd..b306fd45e746 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2286,7 +2286,7 @@ void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index, const uint8_t *mac_addr, const uint8_t *key, int key_Len); #endif -struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size); +hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size); int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 7be37c17fd84..fb009dfa7abe 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3580,25 +3580,28 @@ static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { } #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE /** - * wlan_hdd_logging_sock_activate_svc() - Activate logging + * 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) +static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) { - if (hdd_ctx->config->wlanLoggingEnable) { - if (wlan_logging_sock_activate_svc( - hdd_ctx->config->wlanLoggingFEToConsole, - hdd_ctx->config->wlanLoggingNumBuf)) { - hdd_err("wlan_logging_sock_activate_svc failed"); - return -EINVAL; - } - } - return 0; + int ret; + struct hdd_config *config = hdd_ctx->config; + + if (!config->wlanLoggingEnable) + return 0; + + ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole, + config->wlanLoggingNumBuf); + if (ret) + hdd_err("wlan_logging_sock_activate_svc failed: %d", ret); + return ret; } + /** * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging * @hdd_ctx: HDD context @@ -3607,7 +3610,7 @@ static int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) * * Return: 0 on deactivating the logging service */ -static int wlan_hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) +static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) { if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable) return wlan_logging_sock_deactivate_svc(); @@ -3615,17 +3618,36 @@ static int wlan_hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) return 0; } #else -static inline int wlan_hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) +static inline int 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) +static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) { return 0; } #endif +/** + * hdd_free_context - Free HDD context + * @hdd_ctx: HDD context to be freed. + * + * Free config and HDD context. + * + * Return: None + */ +static void hdd_free_context(hdd_context_t *hdd_ctx) +{ + if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) + hdd_logging_sock_deactivate_svc(hdd_ctx); + + cdf_mem_free(hdd_ctx->config); + hdd_ctx->config = NULL; + + wiphy_free(hdd_ctx->wiphy); +} + /** * hdd_wlan_exit() - HDD WLAN exit function * @hdd_ctx: Pointer to the HDD Context @@ -3765,9 +3787,6 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) hdd_wlan_green_ap_deinit(hdd_ctx); - if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) - wlan_hdd_logging_sock_deactivate_svc(hdd_ctx); - #ifdef WLAN_KD_READY_NOTIFIER cnss_diag_notify_wlan_close(); ptt_sock_deactivate_svc(); @@ -3791,14 +3810,9 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) free_hdd_ctx: - /* Free up dynamically allocated members inside HDD Adapter */ - if (hdd_ctx->config) { - kfree(hdd_ctx->config); - hdd_ctx->config = NULL; - } - wiphy_unregister(wiphy); - wiphy_free(wiphy); + + hdd_free_context(hdd_ctx); } void __hdd_wlan_exit(void) @@ -4967,229 +4981,252 @@ static CDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx) } /** - * hdd_wlan_startup() - HDD init function + * hdd_override_ini_config - Override INI config + * @hdd_ctx: HDD context + * + * Override INI config based on module parameter. + * + * Return: None + */ +static void hdd_override_ini_config(hdd_context_t *hdd_ctx) +{ + + if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) { + hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan; + hdd_notice("Module enable_dfs_chan_scan set to %d", + enable_dfs_chan_scan); + } + if (0 == enable_11d || 1 == enable_11d) { + hdd_ctx->config->Is11dSupportEnabled = enable_11d; + hdd_notice("Module enable_11d set to %d", enable_11d); + } +} + +/** + * hdd_set_trace_level_for_each - Set trace level for each INI config + * @hdd_ctx - HDD context + * + * Set trace level for each module based on INI config. + * + * Return: None + */ +static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx) +{ + hdd_cdf_trace_enable(CDF_MODULE_ID_WMI, + hdd_ctx->config->cdf_trace_enable_wdi); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD, + hdd_ctx->config->cdf_trace_enable_hdd); + hdd_cdf_trace_enable(CDF_MODULE_ID_SME, + hdd_ctx->config->cdf_trace_enable_sme); + hdd_cdf_trace_enable(CDF_MODULE_ID_PE, + hdd_ctx->config->cdf_trace_enable_pe); + hdd_cdf_trace_enable(CDF_MODULE_ID_WMA, + hdd_ctx->config->cdf_trace_enable_wma); + hdd_cdf_trace_enable(CDF_MODULE_ID_SYS, + hdd_ctx->config->cdf_trace_enable_sys); + hdd_cdf_trace_enable(CDF_MODULE_ID_CDF, + hdd_ctx->config->cdf_trace_enable_cdf); + hdd_cdf_trace_enable(CDF_MODULE_ID_SAP, + hdd_ctx->config->cdf_trace_enable_sap); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SOFTAP, + hdd_ctx->config->cdf_trace_enable_hdd_sap); + hdd_cdf_trace_enable(CDF_MODULE_ID_BMI, + hdd_ctx->config->cdf_trace_enable_bmi); + hdd_cdf_trace_enable(CDF_MODULE_ID_CFG, + hdd_ctx->config->cdf_trace_enable_cfg); + hdd_cdf_trace_enable(CDF_MODULE_ID_EPPING, + hdd_ctx->config->cdf_trace_enable_epping); + hdd_cdf_trace_enable(CDF_MODULE_ID_CDF_DEVICE, + hdd_ctx->config->cdf_trace_enable_cdf_devices); + hdd_cdf_trace_enable(CDF_MODULE_ID_TXRX, + hdd_ctx->config->cfd_trace_enable_txrx); + hdd_cdf_trace_enable(CDF_MODULE_ID_HTC, + hdd_ctx->config->cdf_trace_enable_htc); + hdd_cdf_trace_enable(CDF_MODULE_ID_HIF, + hdd_ctx->config->cdf_trace_enable_hif); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SAP_DATA, + hdd_ctx->config->cdf_trace_enable_hdd_sap_data); + hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_DATA, + hdd_ctx->config->cdf_trace_enable_hdd_data); + + hdd_cfg_print(hdd_ctx); +} + +/** + * hdd_init_context - Alloc and initialize HDD context * @dev: Pointer to the underlying device + * @hif_sc: HIF context * - * This is the driver startup code executed once a WLAN device has been detected + * Allocate and initialize HDD context. HDD context is allocated as part of + * wiphy allocation and then context is initialized. * - * Return: 0 for success, < 0 for failure + * Return: HDD context on success and ERR_PTR on failure */ -int hdd_wlan_startup(struct device *dev, void *hif_sc) +hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc) { CDF_STATUS status; - hdd_adapter_t *adapter = NULL; -#ifdef WLAN_OPEN_P2P_INTERFACE - hdd_adapter_t *pP2adapter = NULL; -#endif - hdd_context_t *hdd_ctx = NULL; - v_CONTEXT_t p_cds_context = NULL; - int ret; - int i; - struct wiphy *wiphy; - unsigned long rc; - tSmeThermalParams thermalParam; - tSirTxPowerLimit *hddtxlimit; - uint8_t rtnl_lock_enable; - uint8_t reg_netdev_notifier_done = false; - hdd_adapter_t *dot11_adapter = NULL; + int ret = 0; + hdd_context_t *hdd_ctx; + v_CONTEXT_t p_cds_context; ENTER(); - if (WLAN_IS_EPPING_ENABLED(con_mode)) { - ret = epping_enable(dev); - EXIT(); - return ret; + p_cds_context = cds_get_global_context(); + if (p_cds_context == NULL) { + hdd_alert("Failed to get CDS global context"); + ret = -EINVAL; + goto err_out; } - /* cfg80211: wiphy allocation */ - wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)); + hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)); - if (wiphy == NULL) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("cfg80211 init failed")); - return -EIO; + if (hdd_ctx == NULL) { + ret = -ENOMEM; + goto err_out; } - hdd_ctx = wiphy_priv(wiphy); - - /* Initialize the adapter context to zeros. */ - cdf_mem_zero(hdd_ctx, sizeof(hdd_context_t)); - - hdd_ctx->wiphy = wiphy; - hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; - cds_set_wakelock_logging(false); - - /* Get cds context here bcoz cds_open requires it */ - p_cds_context = cds_get_global_context(); + hdd_ctx->pcds_context = p_cds_context; - if (p_cds_context == NULL) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("Failed cds_get_global_context")); + hdd_ctx->config = cdf_mem_malloc(sizeof(struct hdd_config)); + if (hdd_ctx->config == NULL) { + hdd_alert("Failed to alloc memory for HDD config!"); + ret = -ENOMEM; goto err_free_hdd_context; } - /* Save the Global CDS context in adapter context for future. */ - hdd_ctx->pcds_context = p_cds_context; - /* Save the adapter context in global context for future. */ + /* Read and parse the qcom_cfg.ini file */ + status = hdd_parse_config_ini(hdd_ctx); + if (CDF_STATUS_SUCCESS != status) { + hdd_alert("Error (status: %d) parsing INI file: %s", status, + WLAN_INI_FILE); + ret = -EINVAL; + goto err_free_config; + } + ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx; hdd_ctx->parent_dev = dev; + hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + hdd_init_ll_stats_ctx(); init_completion(&hdd_ctx->mc_sus_event_var); init_completion(&hdd_ctx->ready_to_suspend); - cdf_spinlock_init(&hdd_ctx->sched_scan_lock); cdf_spinlock_init(&hdd_ctx->connection_status_lock); + cdf_spinlock_init(&hdd_ctx->sched_scan_lock); cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock); cdf_list_init(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); wlan_hdd_cfg80211_extscan_init(hdd_ctx); -#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(&hdd_ctx->tdls_lock); -#endif + hdd_tdls_pre_init(hdd_ctx); mutex_init(&hdd_ctx->dfs_lock); - /* store target type and target version info in hdd ctx */ - hdd_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type; - hdd_init_offloaded_packets_ctx(hdd_ctx); - /* Load all config first as TL config is needed during cds_open */ - hdd_ctx->config = - (struct hdd_config *) kmalloc(sizeof(struct hdd_config), GFP_KERNEL); - if (hdd_ctx->config == NULL) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("Failed kmalloc struct hdd_config")); - goto err_config; - } - cdf_mem_zero(hdd_ctx->config, sizeof(struct hdd_config)); + hdd_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type; - /* Read and parse the qcom_cfg.ini file */ - status = hdd_parse_config_ini(hdd_ctx); - if (CDF_STATUS_SUCCESS != status) { - hddLog(CDF_TRACE_LEVEL_FATAL, FL("error parsing %s"), - WLAN_INI_FILE); - goto err_config; - } + hdd_init_offloaded_packets_ctx(hdd_ctx); icnss_set_fw_debug_mode(hdd_ctx->config->enablefwlog); - hdd_ctx->current_intf_count = 0; hdd_ctx->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 - */ hdd_ctx->configuredMcastBcastFilter = hdd_ctx->config->mcastBcastFilterSetting; - hddLog(CDF_TRACE_LEVEL_INFO, - FL("Setting configuredMcastBcastFilter: %d"), - hdd_ctx->config->mcastBcastFilterSetting); - if (false == hdd_is_5g_supported(hdd_ctx)) { - /* 5Ghz is not supported. */ - if (1 != hdd_ctx->config->nBandCapability) { - hddLog(CDF_TRACE_LEVEL_INFO, - FL( - "Setting hdd_ctx->config->nBandCapability = 1" - )); - hdd_ctx->config->nBandCapability = 1; - } - } + hdd_notice("Setting configuredMcastBcastFilter: %d", + hdd_ctx->config->mcastBcastFilterSetting); - /* - * cfg80211: Initialization ... - */ - if (0 < wlan_hdd_cfg80211_init(dev, wiphy, hdd_ctx->config)) { - hddLog(LOGE, - FL("wlan_hdd_cfg80211_init return failure")); - goto err_config; + hdd_override_ini_config(hdd_ctx); + + ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config); + + if (ret) { + hdd_err("CFG80211 wiphy init failed: %d", ret); + goto err_free_config; } hdd_enable_fastpath(hdd_ctx->config, hif_sc); - /* - * Initialize struct for saving f/w log setting will be used - * after ssr - */ + + /* Uses to enabled logging after SSR */ hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enablefwlog; - hdd_ctx->fw_log_settings.dl_type = 0; - hdd_ctx->fw_log_settings.dl_report = 0; - hdd_ctx->fw_log_settings.dl_loglevel = 0; - hdd_ctx->fw_log_settings.index = 0; - for (i = 0; i < MAX_MOD_LOGLEVEL; i++) { - hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0; - } - if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) { - cds_set_multicast_logging( - hdd_ctx->config->multicast_host_fw_msgs); + if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) + goto skip_multicast_logging; - if (wlan_hdd_logging_sock_activate_svc(hdd_ctx) < 0) - goto err_config; + cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs); - /* - * Update CDF trace levels based upon the code. The multicast - * levels of the code need not be set when the logger thread - * is not enabled. - */ - if (cds_is_multicast_logging()) - wlan_logging_set_log_level(); - } + ret = hdd_logging_sock_activate_svc(hdd_ctx); + if (ret) + goto err_free_config; /* - * Update CDF trace levels based upon the cfg.ini + * Update CDF trace levels based upon the code. The multicast + * levels of the code need not be set when the logger thread + * is not enabled. */ - hdd_cdf_trace_enable(CDF_MODULE_ID_WMI, - hdd_ctx->config->cdf_trace_enable_wdi); - hdd_cdf_trace_enable(CDF_MODULE_ID_HDD, - hdd_ctx->config->cdf_trace_enable_hdd); - hdd_cdf_trace_enable(CDF_MODULE_ID_SME, - hdd_ctx->config->cdf_trace_enable_sme); - hdd_cdf_trace_enable(CDF_MODULE_ID_PE, - hdd_ctx->config->cdf_trace_enable_pe); - hdd_cdf_trace_enable(CDF_MODULE_ID_WMA, - hdd_ctx->config->cdf_trace_enable_wma); - hdd_cdf_trace_enable(CDF_MODULE_ID_SYS, - hdd_ctx->config->cdf_trace_enable_sys); - hdd_cdf_trace_enable(CDF_MODULE_ID_CDF, - hdd_ctx->config->cdf_trace_enable_cdf); - hdd_cdf_trace_enable(CDF_MODULE_ID_SAP, - hdd_ctx->config->cdf_trace_enable_sap); - hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SOFTAP, - hdd_ctx->config->cdf_trace_enable_hdd_sap); - hdd_cdf_trace_enable(CDF_MODULE_ID_BMI, - hdd_ctx->config->cdf_trace_enable_bmi); - hdd_cdf_trace_enable(CDF_MODULE_ID_CFG, - hdd_ctx->config->cdf_trace_enable_cfg); - hdd_cdf_trace_enable(CDF_MODULE_ID_EPPING, - hdd_ctx->config->cdf_trace_enable_epping); - hdd_cdf_trace_enable(CDF_MODULE_ID_CDF_DEVICE, - hdd_ctx->config->cdf_trace_enable_cdf_devices); - hdd_cdf_trace_enable(CDF_MODULE_ID_TXRX, - hdd_ctx->config->cfd_trace_enable_txrx); - hdd_cdf_trace_enable(CDF_MODULE_ID_HTC, - hdd_ctx->config->cdf_trace_enable_htc); - hdd_cdf_trace_enable(CDF_MODULE_ID_HIF, - hdd_ctx->config->cdf_trace_enable_hif); - hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SAP_DATA, - hdd_ctx->config->cdf_trace_enable_hdd_sap_data); - hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_DATA, - hdd_ctx->config->cdf_trace_enable_hdd_data); + if (cds_is_multicast_logging()) + wlan_logging_set_log_level(); - hdd_cfg_print(hdd_ctx); +skip_multicast_logging: + hdd_set_trace_level_for_each(hdd_ctx); + + return hdd_ctx; + +err_free_config: + cdf_mem_free(hdd_ctx->config); + +err_free_hdd_context: + wiphy_free(hdd_ctx->wiphy); + +err_out: + return ERR_PTR(ret); +} + +/** + * hdd_wlan_startup() - HDD init function + * @dev: Pointer to the underlying device + * + * This is the driver startup code executed once a WLAN device has been detected + * + * Return: 0 for success, < 0 for failure + */ +int hdd_wlan_startup(struct device *dev, void *hif_sc) +{ + CDF_STATUS status; + hdd_adapter_t *adapter = NULL; +#ifdef WLAN_OPEN_P2P_INTERFACE + hdd_adapter_t *pP2adapter = NULL; +#endif + hdd_context_t *hdd_ctx = NULL; + int ret; + unsigned long rc; + tSmeThermalParams thermalParam; + tSirTxPowerLimit *hddtxlimit; + uint8_t rtnl_lock_enable; + uint8_t reg_netdev_notifier_done = false; + hdd_adapter_t *dot11_adapter = NULL; + + ENTER(); + + if (WLAN_IS_EPPING_ENABLED(con_mode)) { + ret = epping_enable(dev); + EXIT(); + return ret; + } + + hdd_ctx = hdd_init_context(dev, hif_sc); + + if (IS_ERR(hdd_ctx)) + return PTR_ERR(hdd_ctx); if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { ret = hdd_enable_ftm(hdd_ctx); if (ret) - goto err_config; + goto err_hdd_free_context; goto success; } @@ -5200,13 +5237,13 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_wlan_green_ap_init(hdd_ctx); - status = cds_open(&p_cds_context, 0); + status = cds_open(); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed")); - goto err_config; + goto err_hdd_free_context; } - wlan_hdd_update_wiphy(wiphy, hdd_ctx->config); + wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config); hdd_ctx->hHal = cds_get_context(CDF_MODULE_ID_SME); @@ -5240,18 +5277,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) */ hdd_set_dot11p_config(hdd_ctx); - if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) { - hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan; - hddLog(CDF_TRACE_LEVEL_INFO, - FL("module enable_dfs_chan_scan set to %d"), - enable_dfs_chan_scan); - } - if (0 == enable_11d || 1 == enable_11d) { - hdd_ctx->config->Is11dSupportEnabled = enable_11d; - hddLog(CDF_TRACE_LEVEL_INFO, FL("module enable_11d set to %d"), - enable_11d); - } - /* * Note that the cds_pre_enable() sequence triggers the cfg download. * The cfg download must occur before we update the SME config @@ -5739,37 +5764,25 @@ err_close_adapter: hdd_close_all_adapters(hdd_ctx); err_cds_disable: - cds_disable(p_cds_context); + cds_disable(hdd_ctx->pcds_context); err_ipa_cleanup: hdd_ipa_cleanup(hdd_ctx); err_wiphy_unregister: - wiphy_unregister(wiphy); + wiphy_unregister(hdd_ctx->wiphy); err_cds_close: - status = cds_sched_close(p_cds_context); + status = cds_sched_close(hdd_ctx->pcds_context); if (!CDF_IS_STATUS_SUCCESS(status)) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("Failed to close CDS Scheduler")); CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status)); } - cds_close(p_cds_context); - - if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam()) - wlan_hdd_logging_sock_deactivate_svc(hdd_ctx); - -err_config: - kfree(hdd_ctx->config); - hdd_ctx->config = NULL; - -err_free_hdd_context: - /* wiphy_free() will free the HDD context so remove global reference */ - if (p_cds_context) - ((cds_context_type *) (p_cds_context))->pHDDContext = NULL; + cds_close(hdd_ctx->pcds_context); - wiphy_free(wiphy); - /* kfree(wdev) ; */ +err_hdd_free_context: + hdd_free_context(hdd_ctx); CDF_BUG(1); return -EIO; diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 9c993e308a14..5e53aec21ab7 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1438,7 +1438,7 @@ CDF_STATUS hdd_wlan_re_init(void *hif_sc) hdd_set_conparam(0); /* Re-open CDS, it is a re-open b'se control transport was never closed. */ - cdf_status = cds_open(&p_cds_context, 0); + cdf_status = cds_open(); if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { hddLog(CDF_TRACE_LEVEL_FATAL, "%s: cds_open failed", __func__); goto err_re_init; diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 48d0e19aa8ac..d7e1cacc64bf 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -507,6 +507,21 @@ static void wlan_hdd_tdls_del_non_forced_peers(tdlsCtx_t *hdd_tdls_ctx) } } +/** + * hdd_tdls_pre_init - TDLS pre init + * @hdd_ctx: HDD context + * + * 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. + * + * Return: None + */ +void hdd_tdls_pre_init(hdd_context_t *hdd_ctx) +{ + mutex_init(&hdd_ctx->tdls_lock); +} + /** * wlan_hdd_tdls_init() - tdls initializaiton * @pAdapter: hdd adapter -- cgit v1.2.3 From 59b4c87e27f019d9f2ac7a19e7cb5c1b7c41d3b5 Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Fri, 8 Jan 2016 16:46:21 -0800 Subject: qcacld-3.0: hdd: Refactor wlan_startup (phase 2) In HDD, hdd_wlan_startup which is called by probe is beast of a function to maintain. Over time it has grown to such an extent that it is almost 800 lines of code with in a single function. Divide the beast into logical smaller functions. Make separate function to open the interfaces at probe time. Change-Id: Ia0044f5b0d0f009950d62556e09928ac578a1d4b CRs-fixed: 959287 --- core/hdd/inc/wlan_hdd_main.h | 6 +- core/hdd/src/wlan_hdd_ftm.c | 4 +- core/hdd/src/wlan_hdd_main.c | 320 +++++++++++++++++++++++++------------------ 3 files changed, 190 insertions(+), 140 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 4cc4eeb424db..e72ae1de1fa1 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1371,10 +1371,10 @@ CDF_STATUS hdd_add_adapter_front(hdd_context_t *pHddCtx, hdd_adapter_t *hdd_open_adapter(hdd_context_t *pHddCtx, uint8_t session_type, const char *name, tSirMacAddr macAddr, - uint8_t rtnl_held); + bool rtnl_held); CDF_STATUS hdd_close_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, - uint8_t rtnl_held); -CDF_STATUS hdd_close_all_adapters(hdd_context_t *pHddCtx); + bool rtnl_held); +CDF_STATUS hdd_close_all_adapters(hdd_context_t *pHddCtx, bool rtnl_held); CDF_STATUS hdd_stop_all_adapters(hdd_context_t *pHddCtx); CDF_STATUS hdd_reset_all_adapters(hdd_context_t *pHddCtx); CDF_STATUS hdd_start_all_adapters(hdd_context_t *pHddCtx); diff --git a/core/hdd/src/wlan_hdd_ftm.c b/core/hdd/src/wlan_hdd_ftm.c index bf285c00975d..87785387357d 100644 --- a/core/hdd/src/wlan_hdd_ftm.c +++ b/core/hdd/src/wlan_hdd_ftm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -659,7 +659,7 @@ int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx) wlan_ftm_stop(hdd_ctx); } - hdd_close_all_adapters(hdd_ctx); + hdd_close_all_adapters(hdd_ctx, false); cdf_status = cds_sched_close(cds_context); if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fb009dfa7abe..9fc7254ec6e4 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1939,14 +1939,14 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, } CDF_STATUS hdd_register_interface(hdd_adapter_t *adapter, - uint8_t rtnl_lock_held) + bool rtnl_held) { struct net_device *pWlanDev = adapter->dev; /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */ /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */ /* CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; */ - if (rtnl_lock_held) { + if (rtnl_held) { if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) { if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) { hddLog(CDF_TRACE_LEVEL_ERROR, @@ -2234,7 +2234,7 @@ void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, } void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, - uint8_t rtnl_held) + bool rtnl_held) { struct net_device *pWlanDev = NULL; @@ -2291,7 +2291,7 @@ CDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx, } hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, const char *iface_name, tSirMacAddr macAddr, - uint8_t rtnl_held) + bool rtnl_held) { hdd_adapter_t *adapter = NULL; hdd_adapter_list_node_t *pHddAdapterNode = NULL; @@ -2673,7 +2673,7 @@ err_free_netdev: } CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, - uint8_t rtnl_held) + bool rtnl_held) { hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext; CDF_STATUS status; @@ -2711,7 +2711,16 @@ CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, return CDF_STATUS_E_FAILURE; } -CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx) +/** + * hdd_close_all_adapters - Close all open adapters + * @hdd_ctx: Hdd context + * rtnl_held: True if RTNL lock held + * + * Close all open adapters. + * + * Return: CDF status code + */ +CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held) { hdd_adapter_list_node_t *pHddAdapterNode; CDF_STATUS status; @@ -2722,7 +2731,7 @@ CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx) status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode); if (pHddAdapterNode && CDF_STATUS_SUCCESS == status) { hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter, - false); + rtnl_held); cdf_mem_free(pHddAdapterNode); } } while (NULL != pHddAdapterNode && CDF_STATUS_E_EMPTY != status); @@ -3793,7 +3802,7 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) #endif /* WLAN_KD_READY_NOTIFIER */ nl_srv_exit(); - hdd_close_all_adapters(hdd_ctx); + hdd_close_all_adapters(hdd_ctx, false); hdd_ipa_cleanup(hdd_ctx); @@ -5185,6 +5194,152 @@ err_out: return ERR_PTR(ret); } +#ifdef WLAN_OPEN_P2P_INTERFACE +/** + * hdd_open_p2p_interface - Open P2P interface + * @hdd_ctx: HDD context + * @rtnl_held: True if RTNL lock held + * + * Open P2P interface during probe. This function called to open the P2P + * interface at probe along with STA interface. + * + * Return: 0 on success and errno on failure + */ +static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held) +{ + hdd_adapter_t *adapter; + uint8_t *p2p_dev_addr; + + if (hdd_ctx->config->isP2pDeviceAddrAdministrated && + !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) { + cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes, + hdd_ctx->config->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. + */ + hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02; + } else { + p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx); + if (p2p_dev_addr == NULL) { + hdd_alert("Failed to allocate mac_address for p2p_device"); + return -ENOSPC; + } + + cdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr, + CDF_MAC_ADDR_SIZE); + } + + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d", + &hdd_ctx->p2pDeviceAddress.bytes[0], + rtnl_held); + + if (NULL == adapter) { + hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface"); + return -ENOSPC; + } + + return 0; +} +#else +static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx, + bool rtnl_held) +{ + return 0; +} +#endif + +/** + * hdd_open_interfaces - Open all required interfaces + * hdd_ctx: HDD context + * rtnl_held: True if RTNL lock is held + * + * Open all the interfaces like STA, P2P and OCB based on the configuration. + * + * Return: Primary adapter on success and PTR_ERR on failure + */ +static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx, + bool rtnl_held) +{ + hdd_adapter_t *adapter = NULL; + hdd_adapter_t *adapter_11p = NULL; + int ret; + + /* Create only 802.11p interface */ + if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) { + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_held); + + if (adapter == NULL) + return ERR_PTR(-ENOSPC); + + return adapter; + } + + adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_held); + + if (adapter == NULL) + return ERR_PTR(-ENOSPC); + + ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held); + if (ret) + goto err_close_adapter; + + /* Open 802.11p Interface */ + if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { + adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, + "wlanocb%d", + wlan_hdd_get_intf_addr(hdd_ctx), + rtnl_held); + if (adapter_11p == NULL) { + hdd_err("Failed to open 802.11p interface"); + goto err_close_adapter; + } + } + + return adapter; + +err_close_adapter: + hdd_close_all_adapters(hdd_ctx, rtnl_held); + return ERR_PTR(ret); +} + +#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) +/** + * hdd_hold_rtnl_lock - Hold RTNL lock + * + * Hold RTNL lock + * + * Return: True if held and false otherwise + */ +static inline bool hdd_hold_rtnl_lock(void) +{ + rtnl_lock(); + return true; +} + +/** + * hdd_release_rtnl_lock - Release RTNL lock + * + * Release RTNL lock + * + * Return: None + */ +static inline void hdd_release_rtnl_lock(void) +{ + rtnl_unlock(); +} +#else +static inline bool hdd_hold_rtnl_lock(void) { return false; } +static inline void hdd_release_rtnl_lock(void) { } +#endif + /** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device @@ -5197,17 +5352,12 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) { CDF_STATUS status; hdd_adapter_t *adapter = NULL; -#ifdef WLAN_OPEN_P2P_INTERFACE - hdd_adapter_t *pP2adapter = NULL; -#endif hdd_context_t *hdd_ctx = NULL; int ret; unsigned long rc; tSmeThermalParams thermalParam; tSirTxPowerLimit *hddtxlimit; - uint8_t rtnl_lock_enable; - uint8_t reg_netdev_notifier_done = false; - hdd_adapter_t *dot11_adapter = NULL; + bool rtnl_held; ENTER(); @@ -5365,87 +5515,13 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) cds_pkt_proto_trace_init(); #endif /* QCA_PKT_PROTO_TRACE */ -#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) - rtnl_lock(); - rtnl_lock_enable = true; -#else - rtnl_lock_enable = false; -#endif - - if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) - /* Create only 802.11p interface */ - adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d", - wlan_hdd_get_intf_addr(hdd_ctx), - rtnl_lock_enable); - else - adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, - "wlan%d", - wlan_hdd_get_intf_addr(hdd_ctx), - rtnl_lock_enable); - -#ifdef WLAN_OPEN_P2P_INTERFACE - /* Open P2P device interface */ - if (adapter != NULL) { - if (hdd_ctx->config->isP2pDeviceAddrAdministrated && - !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) { - cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes, - hdd_ctx->config->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. - */ - hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02; - } else { - uint8_t *p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx); - if (p2p_dev_addr != NULL) { - cdf_mem_copy(&hdd_ctx->p2pDeviceAddress. - bytes[0], p2p_dev_addr, - CDF_MAC_ADDR_SIZE); - } else { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL( - "Failed to allocate mac_address for p2p_device" - )); - goto err_close_adapter; - } - } - - pP2adapter = - hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d", - &hdd_ctx->p2pDeviceAddress.bytes[0], - rtnl_lock_enable); - - if (NULL == pP2adapter) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL( - "Failed to do hdd_open_adapter for P2P Device Interface" - )); - goto err_close_adapter; - } - } -#endif + rtnl_held = hdd_hold_rtnl_lock(); - if (adapter == NULL) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("hdd_open_adapter failed")); - goto err_close_adapter; - } + adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); - /* Open 802.11p Interface */ - if (adapter != NULL) { - if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { - dot11_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, - "wlanocb%d", - wlan_hdd_get_intf_addr(hdd_ctx), - rtnl_lock_enable); - if (dot11_adapter == NULL) { - hddLog(LOGE, - FL("failed to open 802.11p Interface")); - goto err_close_adapter; - } - } + if (IS_ERR(adapter)) { + ret = PTR_ERR(adapter); + goto err_cds_disable; } /* @@ -5505,21 +5581,11 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) /* FW capabilities received, Set the Dot11 mode */ sme_setdef_dot11mode(hdd_ctx->hHal); -#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(CDF_TRACE_LEVEL_ERROR, - FL("register_netdevice_notifier failed")); - goto err_free_power_on_lock; - } - reg_netdev_notifier_done = true; -#endif /* Initialize the nlink service */ if (nl_srv_init() != 0) { hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed")); - goto err_reg_netdev; + goto err_close_adapter; } #ifdef WLAN_KD_READY_NOTIFIER hdd_ctx->kd_nl_init = 1; @@ -5558,19 +5624,15 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) mutex_init(&hdd_ctx->sap_lock); -#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) - if (rtnl_lock_enable == true) { - rtnl_lock_enable = false; - rtnl_unlock(); - } + hdd_release_rtnl_lock(); + rtnl_held = false; + ret = register_netdevice_notifier(&hdd_netdev_notifier); if (ret < 0) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("register_netdevice_notifier failed")); + hdd_err("register_netdevice_notifier failed: %d", ret); goto err_nl_srv; } - reg_netdev_notifier_done = true; -#endif + #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK /* Initialize the wake lcok */ cdf_wake_lock_init(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock"); @@ -5605,7 +5667,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) status = cds_init_policy_mgr(); if (!CDF_IS_STATUS_SUCCESS(status)) { hdd_err("Policy manager initialization failed"); - goto err_nl_srv; + goto err_unreg_netdev_notifier; } /* Thermal Mitigation */ @@ -5648,7 +5710,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) if (!hddtxlimit) { hddLog(CDF_TRACE_LEVEL_ERROR, FL("Memory allocation for TxPowerLimit failed!")); - goto err_nl_srv; + goto err_unreg_netdev_notifier; } hddtxlimit->txPower2g = hdd_ctx->config->TxPower2g; hddtxlimit->txPower5g = hdd_ctx->config->TxPower5g; @@ -5718,7 +5780,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx); if (status != CDF_STATUS_SUCCESS) { hdd_err("Failed to disable dual mac features"); - goto err_nl_srv; + goto err_unreg_netdev_notifier; } } @@ -5728,6 +5790,9 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto success; +err_unreg_netdev_notifier: + unregister_netdevice_notifier(&hdd_netdev_notifier); + err_nl_srv: #ifdef WLAN_KD_READY_NOTIFIER cnss_diag_notify_wlan_close(); @@ -5740,28 +5805,13 @@ err_nl_srv: hdd_err("Failed to destroy hdd_conc_list_lock"); /* Proceed and complete the clean up */ } -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 + hdd_debugfs_exit(hdd_ctx); 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(hdd_ctx); + hdd_release_rtnl_lock(); + + hdd_close_all_adapters(hdd_ctx, false); err_cds_disable: cds_disable(hdd_ctx->pcds_context); -- cgit v1.2.3 From 1540102eccd9cca3c0880baa8af8009f8de5eead Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Sat, 9 Jan 2016 13:15:21 -0800 Subject: qcacld-3.0: hdd: Refactor wlan_startup (phase 3) In HDD, hdd_wlan_startup which is called by probe is beast of a function to maintain. Over time it has grown to such an extent that it is almost 800 lines of code with in a single function. Divide the beast into logical smaller functions. Create separate functions to update country code from module parameter and initialize thermal mitigations settings in SME. Change-Id: I84cf611347a5abadc16eeb46fed90934913e09ed CRs-fixed: 959287 --- core/hdd/src/wlan_hdd_main.c | 166 +++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 61 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 9fc7254ec6e4..b29165008606 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4572,7 +4572,7 @@ static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, #if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) /** * hdd_set_thermal_level_cb() - set thermal level callback function - * @hdd_ctxt: hdd context pointer + * @context: hdd context pointer * @level: thermal level * * Change IPA data path to SW path when the thermal throttle level greater @@ -4580,8 +4580,10 @@ static void hdd_enable_fastpath(struct hdd_config *hdd_cfg, * * Return: none */ -static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, u_int8_t level) +static void hdd_set_thermal_level_cb(void *context, u_int8_t level) { + hdd_context_t *hdd_ctx = context; + /* Change IPA to SW path when throttle level greater than 0 */ if (level > THROTTLE_LEVEL_0) hdd_ipa_send_mcc_scc_msg(hdd_ctx, true); @@ -4950,7 +4952,7 @@ static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) { } -static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, u_int8_t level) +static void hdd_set_thermal_level_cb(void *context, u_int8_t level) { } #endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */ @@ -5310,6 +5312,98 @@ err_close_adapter: return ERR_PTR(ret); } +/** + * hdd_update_country_code - Update country code + * @hdd_ctx: HDD context + * @adapter: Primary adapter context + * + * Update country code based on module parameter country_code at SME and wait + * for the settings to take effect. + * + * Return: 0 on success and errno on failure + */ +static int hdd_update_country_code(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + CDF_STATUS status; + int ret = 0; + unsigned long rc; + + if (country_code == NULL) + return 0; + + INIT_COMPLETION(adapter->change_country_code); + + status = sme_change_country_code(hdd_ctx->hHal, + wlan_hdd_change_country_code_callback, + country_code, adapter, + hdd_ctx->pcds_context, eSIR_TRUE, + eSIR_TRUE); + + + if (!CDF_IS_STATUS_SUCCESS(status)) { + hdd_err("SME Change Country code from module param fail ret=%d", + ret); + return -EINVAL; + } + + rc = wait_for_completion_timeout(&adapter->change_country_code, + msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); + if (!rc) { + hdd_err("SME while setting country code timed out"); + ret = -ETIMEDOUT; + } + + return ret; +} + +/** + * hdd_init_thermal_info - Initialize thermal level + * @hdd_ctx: HDD context + * + * Initialize thermal level at SME layer and set the thermal level callback + * which would be called when a configured thermal threshold is hit. + * + * Return: 0 on success and errno on failure + */ +static int hdd_init_thermal_info(hdd_context_t *hdd_ctx) +{ + tSmeThermalParams thermal_param; + CDF_STATUS status; + + thermal_param.smeThermalMgmtEnabled = + hdd_ctx->config->thermalMitigationEnable; + thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod; + + thermal_param.smeThermalLevels[0].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel0; + thermal_param.smeThermalLevels[0].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel0; + thermal_param.smeThermalLevels[1].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel1; + thermal_param.smeThermalLevels[1].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel1; + thermal_param.smeThermalLevels[2].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel2; + thermal_param.smeThermalLevels[2].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel2; + thermal_param.smeThermalLevels[3].smeMinTempThreshold = + hdd_ctx->config->thermalTempMinLevel3; + thermal_param.smeThermalLevels[3].smeMaxTempThreshold = + hdd_ctx->config->thermalTempMaxLevel3; + + status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param); + + if (!CDF_IS_STATUS_SUCCESS(status)) + return cdf_status_to_os_return(status); + + sme_add_set_thermal_level_callback(hdd_ctx->hHal, + hdd_set_thermal_level_cb); + + return 0; + +} + #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) /** * hdd_hold_rtnl_lock - Hold RTNL lock @@ -5354,8 +5448,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_adapter_t *adapter = NULL; hdd_context_t *hdd_ctx = NULL; int ret; - unsigned long rc; - tSmeThermalParams thermalParam; tSirTxPowerLimit *hddtxlimit; bool rtnl_held; @@ -5538,33 +5630,10 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) /* pass target_fw_version to HIF layer */ hif_set_fw_info(hif_sc, hdd_ctx->target_fw_version); - if (country_code) { - CDF_STATUS ret; - - INIT_COMPLETION(adapter->change_country_code); + ret = hdd_update_country_code(hdd_ctx, adapter); - ret = sme_change_country_code(hdd_ctx->hHal, - wlan_hdd_change_country_code_callback, - country_code, adapter, - hdd_ctx->pcds_context, eSIR_TRUE, - eSIR_TRUE); - if (CDF_STATUS_SUCCESS == ret) { - rc = wait_for_completion_timeout( - &adapter->change_country_code, - msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); - if (!rc) { - hddLog(LOGE, - FL("SME while setting country code timed out")); - } - } else { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL( - "SME Change Country code from module param fail ret=%d" - ), - ret); - ret = -EINVAL; - } - } + if (ret) + goto err_cds_disable; sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done); @@ -5670,41 +5739,16 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto err_unreg_netdev_notifier; } - /* Thermal Mitigation */ - thermalParam.smeThermalMgmtEnabled = - hdd_ctx->config->thermalMitigationEnable; - thermalParam.smeThrottlePeriod = hdd_ctx->config->throttlePeriod; + ret = hdd_init_thermal_info(hdd_ctx); - thermalParam.smeThermalLevels[0].smeMinTempThreshold = - hdd_ctx->config->thermalTempMinLevel0; - thermalParam.smeThermalLevels[0].smeMaxTempThreshold = - hdd_ctx->config->thermalTempMaxLevel0; - thermalParam.smeThermalLevels[1].smeMinTempThreshold = - hdd_ctx->config->thermalTempMinLevel1; - thermalParam.smeThermalLevels[1].smeMaxTempThreshold = - hdd_ctx->config->thermalTempMaxLevel1; - thermalParam.smeThermalLevels[2].smeMinTempThreshold = - hdd_ctx->config->thermalTempMinLevel2; - thermalParam.smeThermalLevels[2].smeMaxTempThreshold = - hdd_ctx->config->thermalTempMaxLevel2; - thermalParam.smeThermalLevels[3].smeMinTempThreshold = - hdd_ctx->config->thermalTempMinLevel3; - thermalParam.smeThermalLevels[3].smeMaxTempThreshold = - hdd_ctx->config->thermalTempMaxLevel3; + if (ret) { + hdd_err("Error while initializing thermal information"); + goto err_unreg_netdev_notifier; + } if (0 != hdd_lro_init(hdd_ctx)) hdd_err("Unable to initialize LRO in fw"); - if (CDF_STATUS_SUCCESS != - sme_init_thermal_info(hdd_ctx->hHal, thermalParam)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("Error while initializing thermal information")); - } - - /* Plug in set thermal level callback */ - sme_add_set_thermal_level_callback(hdd_ctx->hHal, - (sme_set_thermal_level_callback)hdd_set_thermal_level_cb); - /* SAR power limit */ hddtxlimit = cdf_mem_malloc(sizeof(tSirTxPowerLimit)); if (!hddtxlimit) { -- cgit v1.2.3 From 9229132f4bba19c73a1e788f420294372c7e511c Mon Sep 17 00:00:00 2001 From: Prashanth Bhatta Date: Mon, 11 Jan 2016 18:30:08 -0800 Subject: qcacld-3.0: hdd: Refactor wlan_startup (phase 4) In HDD, hdd_wlan_startup which is called by probe is beast of a function to maintain. Over time it has grown to such an extent that it is almost 800 lines of code with in a single function. Divide the beast into logical smaller functions. Fix style issues like conditional compilation with in the function and other minor ones. Change-Id: Iec2dc3aac934bbb90b87d4e8581e877e5b0a561c CRs-fixed: 959287 --- core/cds/inc/cds_packet.h | 5 +- core/hdd/inc/wlan_hdd_main.h | 21 ------ core/hdd/inc/wlan_hdd_oemdata.h | 15 ++-- core/hdd/src/wlan_hdd_main.c | 130 ++++++++++++++------------------- core/hdd/src/wlan_hdd_stats.c | 4 +- core/hdd/src/wlan_hdd_stats.h | 23 ++++++ core/sme/inc/sme_api.h | 12 +++ core/sme/src/common/sme_api.c | 23 +++--- core/utils/fwlog/dbglog_host.c | 9 +-- core/utils/ptt/inc/wlan_ptt_sock_svc.h | 12 ++- 10 files changed, 132 insertions(+), 122 deletions(-) diff --git a/core/cds/inc/cds_packet.h b/core/cds/inc/cds_packet.h index f3a87d3e645c..1fb7de36ab25 100644 --- a/core/cds/inc/cds_packet.h +++ b/core/cds/inc/cds_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -109,6 +109,9 @@ void cds_pkt_proto_trace_init(void); ---------------------------------------------------------------------------*/ void cds_pkt_proto_trace_close(void); +#else +static inline void cds_pkt_proto_trace_init(void) { } +static inline void cds_pkt_proto_trace_close(void) {} #endif /* QCA_PKT_PROTO_TRACE */ /** diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index e72ae1de1fa1..da650869192a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1147,10 +1147,6 @@ struct hdd_context_s { /* Lock to avoid race condition during start/stop bss */ struct mutex sap_lock; -#ifdef WLAN_KD_READY_NOTIFIER - bool kd_nl_init; -#endif /* WLAN_KD_READY_NOTIFIER */ - #ifdef FEATURE_OEM_DATA_SUPPORT /* OEM App registered or not */ bool oem_app_registered; @@ -1462,23 +1458,6 @@ bool hdd_is_5g_supported(hdd_context_t *pHddCtx); int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter); -#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); -static inline bool hdd_link_layer_stats_supported(void) -{ - return true; -} -#else -static inline bool hdd_link_layer_stats_supported(void) -{ - return false; -} -#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); diff --git a/core/hdd/inc/wlan_hdd_oemdata.h b/core/hdd/inc/wlan_hdd_oemdata.h index 9107dc315afe..82ea3e18263c 100644 --- a/core/hdd/inc/wlan_hdd_oemdata.h +++ b/core/hdd/inc/wlan_hdd_oemdata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -25,8 +25,6 @@ * to the Linux Foundation. */ -#ifdef FEATURE_OEM_DATA_SUPPORT - /** * DOC: wlan_hdd_oemdata.h * @@ -36,6 +34,8 @@ #ifndef __WLAN_HDD_OEM_DATA_H__ #define __WLAN_HDD_OEM_DATA_H__ +#ifdef FEATURE_OEM_DATA_SUPPORT + #ifndef OEM_DATA_REQ_SIZE #define OEM_DATA_REQ_SIZE 280 #endif @@ -166,7 +166,10 @@ int iw_get_oem_data_cap(struct net_device *dev, struct iw_request_info *info, int oem_activate_service(struct hdd_context_s *hdd_ctx); void hdd_send_oem_data_rsp_msg(int length, uint8_t *oemDataRsp); - -#endif /* __WLAN_HDD_OEM_DATA_H__ */ - +#else +static inline int oem_activate_service(struct hdd_context_s *hdd_ctx) +{ + return 0; +} #endif /* FEATURE_OEM_DATA_SUPPORT */ +#endif /* __WLAN_HDD_OEM_DATA_H__ */ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index b29165008606..06e03bb59c5f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5448,8 +5448,9 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_adapter_t *adapter = NULL; hdd_context_t *hdd_ctx = NULL; int ret; - tSirTxPowerLimit *hddtxlimit; + tSirTxPowerLimit hddtxlimit; bool rtnl_held; + tSirRetStatus hal_status; ENTER(); @@ -5473,10 +5474,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto success; } - cds_set_recovery_in_progress(false); - - cds_set_connection_in_progress(false); - hdd_wlan_green_ap_init(hdd_ctx); status = cds_open(); @@ -5559,27 +5556,19 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) FL("can't update mac config, using MAC from ini file")); } - { - CDF_STATUS cdf_ret_status; - /* - * 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. - */ - cdf_ret_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, - (uint8_t *) &hdd_ctx->config-> - intfMacAddr[0], - sizeof(hdd_ctx->config-> - intfMacAddr[0])); + /* + * 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. + */ + hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, + hdd_ctx->config->intfMacAddr[0].bytes, + sizeof(hdd_ctx->config->intfMacAddr[0])); - if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL( - "Failed to set MAC Address. HALStatus is %08d [x%08x]" - ), - cdf_ret_status, cdf_ret_status); - goto err_wiphy_unregister; - } + if (!IS_SIR_STATUS_SUCCESS(hal_status)) { + hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]", + hal_status, hal_status); + ret = -EINVAL; + goto err_wiphy_unregister; } if (hdd_ipa_init(hdd_ctx) == CDF_STATUS_E_FAILURE) @@ -5603,9 +5592,8 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) FL("hdd_post_cds_enable_config failed")); goto err_cds_disable; } -#ifdef QCA_PKT_PROTO_TRACE + cds_pkt_proto_trace_init(); -#endif /* QCA_PKT_PROTO_TRACE */ rtnl_held = hdd_hold_rtnl_lock(); @@ -5637,16 +5625,13 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done); -#ifdef FEATURE_OEM_DATA_SUPPORT sme_register_oem_data_rsp_callback(hdd_ctx->hHal, hdd_send_oem_data_rsp_msg); -#endif - /* Open debugfs interface */ - if (CDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("hdd_debugfs_init failed!")); - } + status = hdd_debugfs_init(adapter); + + if (CDF_IS_STATUS_SUCCESS(status)) + hdd_err("hdd_debugfs_init failed: %d!", status); /* FW capabilities received, Set the Dot11 mode */ sme_setdef_dot11mode(hdd_ctx->hHal); @@ -5656,32 +5641,22 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed")); goto err_close_adapter; } -#ifdef WLAN_KD_READY_NOTIFIER - hdd_ctx->kd_nl_init = 1; -#endif /* WLAN_KD_READY_NOTIFIER */ -#ifdef FEATURE_OEM_DATA_SUPPORT - /* Initialize the OEM service */ - if (oem_activate_service(hdd_ctx) != 0) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("oem_activate_service failed")); + ret = oem_activate_service(hdd_ctx); + if (ret) { + hdd_alert("oem_activate_service failed: %d", ret); goto err_nl_srv; } -#endif -#ifdef PTT_SOCK_SVC_ENABLE - /* Initialize the PTT service */ - if (ptt_sock_activate_svc() != 0) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("ptt_sock_activate_svc failed")); + ret = ptt_sock_activate_svc(); + if (ret) { + hdd_alert("ptt_sock_activate_svc failed: %d", ret); goto err_nl_srv; } -#endif - /* Initialize the CNSS-DIAG service */ - if (cnss_diag_activate_service() < 0) { - hddLog(CDF_TRACE_LEVEL_FATAL, - FL("cnss_diag_activate_service failed")); + ret = cnss_diag_activate_service(); + if (ret) { + hdd_alert("cnss_diag_activate_service failed: %d", ret); goto err_nl_srv; } @@ -5749,19 +5724,11 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) if (0 != hdd_lro_init(hdd_ctx)) hdd_err("Unable to initialize LRO in fw"); - /* SAR power limit */ - hddtxlimit = cdf_mem_malloc(sizeof(tSirTxPowerLimit)); - if (!hddtxlimit) { - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("Memory allocation for TxPowerLimit failed!")); - goto err_unreg_netdev_notifier; - } - hddtxlimit->txPower2g = hdd_ctx->config->TxPower2g; - hddtxlimit->txPower5g = hdd_ctx->config->TxPower5g; - - if (CDF_STATUS_SUCCESS != sme_txpower_limit(hdd_ctx->hHal, hddtxlimit)) - hddLog(CDF_TRACE_LEVEL_ERROR, - FL("Error setting txlimit in sme")); + hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g; + hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g; + status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit); + if (CDF_IS_STATUS_SUCCESS(status)) + hdd_err("Error setting txlimit in sme: %d", status); #ifdef MSM_PLATFORM spin_lock_init(&hdd_ctx->bus_bw_lock); @@ -5770,25 +5737,20 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_bus_bw_compute_cbk, (void *)hdd_ctx); #endif -#ifdef WLAN_FEATURE_STATS_EXT wlan_hdd_cfg80211_stats_ext_init(hdd_ctx); -#endif -#ifdef FEATURE_WLAN_EXTSCAN + sme_ext_scan_register_callback(hdd_ctx->hHal, wlan_hdd_cfg80211_extscan_callback); -#endif /* FEATURE_WLAN_EXTSCAN */ + sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal, hdd_rssi_threshold_breached); -#ifdef WLAN_FEATURE_LINK_LAYER_STATS - wlan_hdd_cfg80211_link_layer_stats_init(hdd_ctx); -#endif -#ifdef WLAN_FEATURE_LPSS + hdd_cfg80211_link_layer_stats_init(hdd_ctx); + wlan_hdd_send_all_scan_intf_info(hdd_ctx); wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version, hdd_ctx->target_hw_version, hdd_ctx->target_hw_name); -#endif cdf_spinlock_init(&hdd_ctx->hdd_roc_req_q_lock); cdf_list_init((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY); @@ -6328,6 +6290,24 @@ void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx) if (!scan_intf_found) wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0); } +#else +static inline void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter, + hdd_station_ctx_t *pHddStaCtx, + uint8_t is_on, uint8_t is_connected) +{ + return; +} + +static inline void wlan_hdd_send_version_pkg(uint32_t fw_version, uint32_t + chip_id, const char *chip_name) +{ + return; +} + +static inline void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx) +{ + return; +} #endif #ifdef FEATURE_WLAN_AUTO_SHUTDOWN diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 660ec09266b9..025c1ca8258e 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1100,12 +1100,12 @@ static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, } /** - * wlan_hdd_cfg80211_link_layer_stats_init() - initialize link layer stats + * hdd_cfg80211_link_layer_stats_init() - Initialize link layer stats * @pHddCtx: Pointer to hdd context * * Return: None */ -void wlan_hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx) +void hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx) { sme_set_link_layer_stats_ind_cb(pHddCtx->hHal, wlan_hdd_cfg80211_link_layer_stats_callback); diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index ae5e84d0a215..b30b587be819 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -90,6 +90,8 @@ struct index_data_rate_type { */ #define LL_STATS_EVENT_BUF_SIZE 4096 +void hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx); + /** * wlan_hdd_cfg80211_ll_stats_set() - set link layer stats * @wiphy: Pointer to wiphy @@ -134,12 +136,29 @@ int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy, int data_len); void hdd_init_ll_stats_ctx(void); + +static inline bool hdd_link_layer_stats_supported(void) +{ + return true; +} + #else + +static inline void hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx) +{ + return; +} + static inline void hdd_init_ll_stats_ctx(void) { return; } +static inline bool hdd_link_layer_stats_supported(void) +{ + return false; +} + #endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */ #ifdef WLAN_FEATURE_STATS_EXT @@ -156,6 +175,10 @@ int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx); +#else +static inline void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx) {} #endif /* End of WLAN_FEATURE_STATS_EXT */ /** diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index df5dc9e4dced..c1698cf5e592 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -357,6 +357,12 @@ extern CDF_STATUS sme_register11d_scan_done_callback(tHalHandle hHal, #ifdef FEATURE_OEM_DATA_SUPPORT extern CDF_STATUS sme_register_oem_data_rsp_callback(tHalHandle h_hal, sme_send_oem_data_rsp_msg callback); +#else +static inline CDF_STATUS sme_register_oem_data_rsp_callback(tHalHandle h_hal, + sme_send_oem_data_rsp_msg callback) +{ + return CDF_STATUS_SUCCESS; +} #endif extern CDF_STATUS sme_wow_add_pattern(tHalHandle hHal, @@ -832,6 +838,12 @@ sme_set_ssid_hotlist(tHalHandle hal, CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, void (*pExtScanIndCb)(void *, const uint16_t, void *)); +#else +static inline CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, + void (*pExtScanIndCb)(void *, const uint16_t, void *)) +{ + return CDF_STATUS_SUCCESS; +} #endif /* FEATURE_WLAN_EXTSCAN */ CDF_STATUS sme_abort_roam_scan(tHalHandle hHal, uint8_t sessionId); #ifdef WLAN_FEATURE_LINK_LAYER_STATS diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 06163a8fa913..0a316bfb5b77 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -12047,12 +12047,23 @@ CDF_STATUS sme_txpower_limit(tHalHandle hHal, tSirTxPowerLimit *psmetx) CDF_STATUS cdf_status = CDF_STATUS_SUCCESS; cds_msg_t cds_message; tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tSirTxPowerLimit *tx_power_limit; + + tx_power_limit = cdf_mem_malloc(sizeof(*tx_power_limit)); + if (!tx_power_limit) { + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR, + "%s: Memory allocation for TxPowerLimit failed!", + __func__); + return CDF_STATUS_E_FAILURE; + } + + *tx_power_limit = *psmetx; status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { cds_message.type = WMA_TX_POWER_LIMIT; cds_message.reserved = 0; - cds_message.bodyptr = psmetx; + cds_message.bodyptr = tx_power_limit; cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { @@ -12060,7 +12071,7 @@ CDF_STATUS sme_txpower_limit(tHalHandle hHal, tSirTxPowerLimit *psmetx) "%s: not able to post WMA_TX_POWER_LIMIT", __func__); status = CDF_STATUS_E_FAILURE; - cdf_mem_free(psmetx); + cdf_mem_free(tx_power_limit); } sme_release_global_lock(&pMac->sme); } @@ -13079,14 +13090,6 @@ CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, } return status; } - -#else -CDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal, - void (*pExtScanIndCb)(void *, const uint16_t, void *)) -{ - return CDF_STATUS_SUCCESS; -} - #endif /* FEATURE_WLAN_EXTSCAN */ #ifdef WLAN_FEATURE_LINK_LAYER_STATS diff --git a/core/utils/fwlog/dbglog_host.c b/core/utils/fwlog/dbglog_host.c index 242c68545625..a2eaf57fca29 100644 --- a/core/utils/fwlog/dbglog_host.c +++ b/core/utils/fwlog/dbglog_host.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -57,7 +57,6 @@ 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; @@ -4264,12 +4263,11 @@ int cnss_diag_activate_service() /* 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) { + if (ret) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("CNSS-DIAG Registeration failed \n")); + ("CNSS-DIAG Registration failed")); return ret; } - kd_nl_init = true; return 0; } @@ -4459,6 +4457,5 @@ int dbglog_deinit(wmi_unified_t wmi_handle) if (res != 0) return res; - kd_nl_init = false; return res; } diff --git a/core/utils/ptt/inc/wlan_ptt_sock_svc.h b/core/utils/ptt/inc/wlan_ptt_sock_svc.h index 7e17dd8329ec..121fcbac7579 100644 --- a/core/utils/ptt/inc/wlan_ptt_sock_svc.h +++ b/core/utils/ptt/inc/wlan_ptt_sock_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -92,9 +92,19 @@ * Length : 4 bytes [LEN_PAYLOAD] * Payload : LEN_PAYLOAD bytes */ +#ifdef PTT_SOCK_SVC_ENABLE int ptt_sock_activate_svc(void); void ptt_sock_deactivate_svc(void); int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid); +#else +static inline int ptt_sock_activate_svc(void) { return 0; } +static inline void ptt_sock_deactivate_svc(void) { return; } +static inline int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, + int src_mod, int pid) +{ + return 0; +} +#endif /* * Format of message exchanged between the PTT Socket App in userspace and the -- cgit v1.2.3 From 09b5e5528b5407f45f3b7b81953b7deb14770c39 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Wed, 13 Jan 2016 15:59:52 -0800 Subject: qcacld-3.0: Fix all comments given as part of IBSS+STA code changes Fix all the comments given during code review of IBSS+STA changes. Change-Id: If675f55b612f9412c803fc3587a352c9967d1fbe CRs-Fixed: 963738 --- core/cds/inc/cds_concurrency.h | 1 + core/cds/inc/cds_sched.h | 1 + core/cds/src/cds_concurrency.c | 200 +++++++++++++++++++++++++++++----------- core/hdd/inc/wlan_hdd_main.h | 1 - core/hdd/src/wlan_hdd_main.c | 10 +- core/hdd/src/wlan_hdd_power.c | 5 +- core/sme/src/csr/csr_api_scan.c | 7 +- 7 files changed, 157 insertions(+), 68 deletions(-) diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 4e48d9f431d6..7ac1a0736f98 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -556,6 +556,7 @@ void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, uint8_t session_id); CDF_STATUS cds_init_policy_mgr(void); +CDF_STATUS cds_deinit_policy_mgr(void); CDF_STATUS cds_get_pcl(enum cds_con_mode mode, uint8_t *pcl_Channels, uint32_t *len); bool cds_allow_concurrency(enum cds_con_mode mode, diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index cafff80dd699..9d77986c3789 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -285,6 +285,7 @@ typedef struct _cds_context_type { struct cds_log_complete log_complete; cdf_spinlock_t bug_report_lock; cdf_event_t connection_update_done_evt; + cdf_mutex_t cdf_conc_list_lock; } cds_context_type, *p_cds_contextType; diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index a832dbb67452..39b2f0a1cb30 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -2195,15 +2195,15 @@ static void cds_update_hw_mode_conn_info(uint32_t num_vdev_mac_entries, struct sir_hw_mode_params hw_mode) { uint32_t i, conn_index, found; - hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (0 != wlan_hdd_validate_context(hdd_ctx)) { - cds_err("Invalid HDD Context"); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); for (i = 0; i < num_vdev_mac_entries; i++) { conn_index = 0; found = 0; @@ -2236,7 +2236,7 @@ static void cds_update_hw_mode_conn_info(uint32_t num_vdev_mac_entries, conc_connection_list[conn_index].rx_spatial_stream); } } - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); } /** @@ -3515,6 +3515,7 @@ void cds_incr_active_session(enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -3522,11 +3523,17 @@ void cds_incr_active_session(enum tCDF_ADAPTER_MODE mode, return; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + /* * Need to aquire mutex as entire functionality in this function * is in critical section */ - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: @@ -3551,7 +3558,7 @@ void cds_incr_active_session(enum tCDF_ADAPTER_MODE mode, cds_info("Set PCL of STA to FW"); } cds_incr_connection_count(session_id); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); } /** @@ -3680,6 +3687,7 @@ void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, { CDF_STATUS cdf_status; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -3687,6 +3695,12 @@ void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, return; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + cds_decr_active_session(mode, session_id); /* * After the removal of this connection, we need to check if @@ -3702,7 +3716,7 @@ void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, * given to the FW. After setting the PCL, we need to restore * the entry that we have saved before. */ - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); cds_set_pcl_for_existing_combo(CDS_STA_MODE); /* do we need to change the HW mode */ if (cds_need_opportunistic_upgrade()) { @@ -3715,7 +3729,7 @@ void cds_decr_session_set_pcl(enum tCDF_ADAPTER_MODE mode, if (!CDF_IS_STATUS_SUCCESS(cdf_status)) cds_err("Failed to start dbs opportunistic timer"); } - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return; } @@ -3736,6 +3750,7 @@ void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, uint8_t session_id) { hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -3743,11 +3758,17 @@ void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, return; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + /* * Need to aquire mutex as entire functionality in this function * is in critical section */ - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); switch (mode) { case CDF_STA_MODE: case CDF_P2P_CLIENT_MODE: @@ -3763,7 +3784,7 @@ void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, cds_info("No.# of active sessions for mode %d = %d", mode, hdd_ctx->no_of_active_sessions[mode]); cds_decr_connection_count(session_id); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); } /** @@ -3777,15 +3798,16 @@ void cds_decr_active_session(enum tCDF_ADAPTER_MODE mode, */ void cds_dbs_opportunistic_timer_handler(void *data) { - hdd_context_t *hdd_ctx = (hdd_context_t *) data; enum cds_conc_next_action action = CDS_NOP; + cds_context_type *cds_ctx; - if (NULL == hdd_ctx) { - cds_err("hdd_ctx is NULL"); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); /* if we still need it */ action = cds_need_opportunistic_upgrade(); if (action) { @@ -3797,8 +3819,33 @@ void cds_dbs_opportunistic_timer_handler(void *data) cds_next_actions(0, action, CDS_UPDATE_REASON_OPPORTUNISTIC); } - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); + +} + +/** + * cds_deinit_policy_mgr() - Deinitialize the policy manager + * related data structures + * + * Deinitialize the policy manager related data structures + * + * Return: Success if the policy manager is deinitialized completely + */ +CDF_STATUS cds_deinit_policy_mgr(void) +{ + cds_context_type *cds_ctx; + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return CDF_STATUS_E_FAILURE; + } + if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy( + &cds_ctx->cdf_conc_list_lock))) { + cds_err("Failed to destroy cdf_conc_list_lock"); + return CDF_STATUS_E_FAILURE; + } + return CDF_STATUS_SUCCESS; } /** @@ -3813,6 +3860,7 @@ CDF_STATUS cds_init_policy_mgr(void) { CDF_STATUS status; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -3820,14 +3868,20 @@ CDF_STATUS cds_init_policy_mgr(void) return CDF_STATUS_E_FAILURE; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return CDF_STATUS_E_FAILURE; + } + cds_debug("Initializing the policy manager"); /* init conc_connection_list */ cdf_mem_zero(conc_connection_list, sizeof(conc_connection_list)); if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init( - &hdd_ctx->hdd_conc_list_lock))) { - cds_err("Failed to init hdd_conc_list_lock"); + &cds_ctx->cdf_conc_list_lock))) { + cds_err("Failed to init cdf_conc_list_lock"); /* Lets us not proceed further */ return CDF_STATUS_E_FAILURE; } @@ -3964,6 +4018,7 @@ CDF_STATUS cds_incr_connection_count(uint32_t vdev_id) uint32_t conn_index; struct wma_txrx_node *wma_conn_table_entry; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -3971,6 +4026,12 @@ CDF_STATUS cds_incr_connection_count(uint32_t vdev_id) return status; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return status; + } + conn_index = cds_get_connection_count(); if (hdd_ctx->config->gMaxConcurrentActiveSessions < conn_index) { /* err msg */ @@ -4024,15 +4085,15 @@ CDF_STATUS cds_update_connection_info(uint32_t vdev_id) uint32_t conn_index = 0; bool found = false; struct wma_txrx_node *wma_conn_table_entry; - hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (!hdd_ctx) { - cds_err("HDD context is NULL"); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return status; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (vdev_id == conc_connection_list[conn_index].vdev_id) { /* debug msg */ @@ -4043,7 +4104,7 @@ CDF_STATUS cds_update_connection_info(uint32_t vdev_id) } if (!found) { /* err msg */ - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); cds_err("can't find vdev_id %d in conc_connection_list", vdev_id); return status; @@ -4053,7 +4114,7 @@ CDF_STATUS cds_update_connection_info(uint32_t vdev_id) if (NULL == wma_conn_table_entry) { /* err msg*/ - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); cds_err("can't find vdev_id %d in WMA table", vdev_id); return status; } @@ -4068,7 +4129,7 @@ CDF_STATUS cds_update_connection_info(uint32_t vdev_id) wma_conn_table_entry->tx_streams, wma_conn_table_entry->rx_streams, wma_conn_table_entry->nss, vdev_id, true); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return CDF_STATUS_SUCCESS; } @@ -4763,6 +4824,7 @@ bool cds_is_ibss_conn_exist(uint8_t *ibss_channel) uint32_t count = 0, index = 0; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; bool status = false; + if (NULL == ibss_channel) { cds_err("Null pointer error"); return false; @@ -4802,6 +4864,7 @@ bool cds_allow_concurrency(enum cds_con_mode mode, bool status = false, match = false; uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS]; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -4809,7 +4872,13 @@ bool cds_allow_concurrency(enum cds_con_mode mode, return status; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return status; + } + + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); /* find the current connection state from conc_connection_list*/ num_connections = cds_get_connection_count(); @@ -4996,7 +5065,7 @@ bool cds_allow_concurrency(enum cds_con_mode mode, status = true; done: - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return status; } @@ -5478,9 +5547,16 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, enum cds_one_connection_mode second_index = 0; enum cds_two_connection_mode third_index = 0; enum cds_band band; + cds_context_type *cds_ctx; hdd_context_t *hdd_ctx; CDF_STATUS status = CDF_STATUS_E_FAILURE; + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return status; + } + hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { cds_err("Invalid HDD context"); @@ -5496,7 +5572,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, else band = CDS_BAND_5; - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); num_connections = cds_get_connection_count(); cds_debug("num_connections=%d channel=%d", @@ -5553,7 +5629,7 @@ CDF_STATUS cds_current_connections_update(uint32_t session_id, reason, session_id); done: - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return status; } @@ -5627,7 +5703,7 @@ bool cds_wait_for_nss_update(uint8_t action) void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, uint8_t next_action) { - hdd_context_t *hdd_ctx = (hdd_context_t *)context; + cds_context_type *cds_ctx; uint32_t conn_index = 0; bool wait = true; @@ -5635,18 +5711,20 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, cds_err("nss update failed for vdev %d", vdev_id); return; } - if (NULL == hdd_ctx) { - cds_err("NULL hdd_ctx"); + + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return; } - /** + /* * Check if we are ok to request for HW mode change now */ - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); conn_index = cds_get_connection_for_vdev_id(vdev_id); if (MAX_NUMBER_OF_CONC_CONNECTIONS == conn_index) { - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); cds_err("connection not found for vdev %d", vdev_id); return; } @@ -5669,7 +5747,7 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, cds_next_actions(vdev_id, next_action, CDS_UPDATE_REASON_NSS_UPDATE); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return; } @@ -7273,6 +7351,7 @@ void cds_check_and_restart_sap_with_non_dfs_acs(void) { hdd_adapter_t *ap_adapter; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -7280,6 +7359,12 @@ void cds_check_and_restart_sap_with_non_dfs_acs(void) return; } + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + if (cds_get_concurrency_mode() != (CDF_STA_MASK | CDF_SAP_MASK)) { cds_info("Concurrency mode is not SAP"); return; @@ -7310,15 +7395,15 @@ CDF_STATUS cds_update_connection_info_utfw( { CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0, found = 0; - hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (!hdd_ctx) { - cds_err("HDD context is NULL"); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return status; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { if (vdev_id == conc_connection_list[conn_index].vdev_id) { /* debug msg */ @@ -7329,7 +7414,7 @@ CDF_STATUS cds_update_connection_info_utfw( } if (!found) { /* err msg */ - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); cds_err("can't find vdev_id %d in conc_connection_list", vdev_id); return status; @@ -7340,7 +7425,7 @@ CDF_STATUS cds_update_connection_info_utfw( cds_get_mode(type, sub_type), channelid, mac_id, chain_mask, tx_streams, rx_streams, 0, vdev_id, true); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return CDF_STATUS_SUCCESS; } @@ -7353,6 +7438,7 @@ CDF_STATUS cds_incr_connection_count_utfw( CDF_STATUS status = CDF_STATUS_E_FAILURE; uint32_t conn_index = 0; hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); if (!hdd_ctx) { @@ -7360,11 +7446,17 @@ CDF_STATUS cds_incr_connection_count_utfw( return status; } - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return status; + } + + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); conn_index = cds_get_connection_count(); if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { /* err msg */ - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); cds_err("exceeded max connection limit %d", MAX_NUMBER_OF_CONC_CONNECTIONS); return status; @@ -7375,7 +7467,7 @@ CDF_STATUS cds_incr_connection_count_utfw( cds_get_mode(type, sub_type), channelid, mac_id, chain_mask, tx_streams, rx_streams, 0, vdev_id, true); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); return CDF_STATUS_SUCCESS; } @@ -7384,11 +7476,11 @@ CDF_STATUS cds_decr_connection_count_utfw(uint32_t del_all, uint32_t vdev_id) { CDF_STATUS status; - hdd_context_t *hdd_ctx; + cds_context_type *cds_ctx; - hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); - if (!hdd_ctx) { - cds_err("HDD context is NULL"); + cds_ctx = cds_get_context(CDF_MODULE_ID_CDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); return CDF_STATUS_E_FAILURE; } @@ -7399,9 +7491,9 @@ CDF_STATUS cds_decr_connection_count_utfw(uint32_t del_all, return CDF_STATUS_E_FAILURE; } } else { - cdf_mutex_acquire(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_acquire(&cds_ctx->cdf_conc_list_lock); cds_decr_connection_count(vdev_id); - cdf_mutex_release(&hdd_ctx->hdd_conc_list_lock); + cdf_mutex_release(&cds_ctx->cdf_conc_list_lock); } return CDF_STATUS_SUCCESS; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index da650869192a..d24ab8553121 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1322,7 +1322,6 @@ struct hdd_context_s { cdf_mc_timer_t dbs_opportunistic_timer; bool connection_in_progress; cdf_spinlock_t connection_status_lock; - cdf_mutex_t hdd_conc_list_lock; uint16_t hdd_txrx_hist_idx; struct hdd_tx_rx_histogram hdd_txrx_hist[NUM_TX_RX_HISTOGRAM]; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 06e03bb59c5f..315170ef9103 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3811,9 +3811,8 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) cdf_list_destroy(&hdd_ctx->hdd_roc_req_q); cdf_list_destroy(&hdd_ctx->hdd_scan_req_q); - if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy( - &hdd_ctx->hdd_conc_list_lock))) { - hdd_err("Failed to destroy hdd_conc_list_lock"); + if (!CDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { + hdd_err("Failed to deinit policy manager"); /* Proceed and complete the clean up */ } @@ -5806,9 +5805,8 @@ err_nl_srv: #endif /* WLAN_KD_READY_NOTIFIER */ nl_srv_exit(); - if (!CDF_IS_STATUS_SUCCESS - (cdf_mutex_destroy(&hdd_ctx->hdd_conc_list_lock))) { - hdd_err("Failed to destroy hdd_conc_list_lock"); + if (!CDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { + hdd_err("Failed to deinit policy manager"); /* Proceed and complete the clean up */ } diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 5e53aec21ab7..0af3ff235a09 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1631,9 +1631,8 @@ err_cds_close: wiphy_unregister(pHddCtx->wiphy); wiphy_free(pHddCtx->wiphy); - if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy( - &pHddCtx->hdd_conc_list_lock))) { - hdd_err("Failed to destroy hdd_conc_list_lock"); + if (!CDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { + hdd_err("Failed to deinit policy manager"); /* Proceed and complete the clean up */ } } diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 5c44c089c6fa..2486d9eb8753 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -5305,7 +5305,6 @@ static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx, static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, uint8_t ibss_channel, tCsrScanRequest *dst_req) { uint8_t valid_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; - uint8_t filtered_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; uint32_t filter_chnl_len = 0, i = 0; uint32_t valid_chnl_len = WNI_CFG_VALID_CHANNEL_LIST_LEN; @@ -5346,12 +5345,12 @@ static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, continue; if (CDS_IS_CHANNEL_5GHZ(ibss_channel) && CDS_IS_CHANNEL_24GHZ(valid_chnl_list[i])) { - filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[filter_chnl_len] = valid_chnl_list[i]; filter_chnl_len++; } else if (CDS_IS_CHANNEL_24GHZ(ibss_channel) && CDS_IS_CHANNEL_5GHZ(valid_chnl_list[i])) { - filtered_chnl_list[filter_chnl_len] = + valid_chnl_list[filter_chnl_len] = valid_chnl_list[i]; filter_chnl_len++; } @@ -5377,7 +5376,7 @@ static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx, FL("Memory allocation failed")); return false; } - cdf_mem_copy(dst_req->ChannelInfo.ChannelList, filtered_chnl_list, + cdf_mem_copy(dst_req->ChannelInfo.ChannelList, valid_chnl_list, filter_chnl_len); return true; } -- cgit v1.2.3 From 2f58cf8ec81bc622e78ca7003b1f78121c5911ac Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Mon, 14 Dec 2015 16:37:38 -0800 Subject: qcacld-3.0: SAP DFS-3 Feature support Changes needed in protocol stack related to DFS-3 feature. Change-Id: Iec8e4e336039f5b643b9d10ee6737203222683cf CRs-Fixed: 964262 --- core/wma/inc/wma_dfs_interface.h | 7 ++++++ core/wma/src/wma_features.c | 54 +++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 63d069bea3cf..5783ed454642 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -71,6 +71,10 @@ #define IEEE80211_CHAN_VHT40MINUS 0x00400000 /* VHT 80 channel */ #define IEEE80211_CHAN_VHT80 0x00800000 +/* VHT 80+80 Channel */ +#define IEEE80211_CHAN_VHT80P80 0x01000000 +/* VHT 160 Channel */ +#define IEEE80211_CHAN_VHT160 0x02000000 /* token for ``any channel'' */ #define DFS_IEEE80211_CHAN_ANY (-1) @@ -116,9 +120,11 @@ */ struct dfs_ieee80211_channel { uint32_t ic_freq; + uint32_t ic_freq_ext; uint32_t ic_flags; uint8_t ic_flagext; uint8_t ic_ieee; + uint8_t ic_ieee_ext; int8_t ic_maxregpower; int8_t ic_maxpower; int8_t ic_minpower; @@ -127,6 +133,7 @@ struct dfs_ieee80211_channel { uint32_t ic_vhtop_ch_freq_seg1; uint32_t ic_vhtop_ch_freq_seg2; int ic_pri_freq_center_freq_mhz_separation; + bool ic_80p80_both_dfs; }; /** diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 5bd515e647fe..8c733ee6853b 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -7388,6 +7388,8 @@ struct dfs_ieee80211_channel *wma_dfs_configure_channel( struct wma_vdev_start_req *req) { + uint8_t ext_channel; + if (dfs_ic == NULL) { WMA_LOGE("%s: DFS ic is Invalid", __func__); return NULL; @@ -7420,23 +7422,57 @@ struct dfs_ieee80211_channel *wma_dfs_configure_channel( (dfs_ic->ic_curchan->ic_ieee <= WMA_11A_CHANNEL_END)) { dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_5GHZ; } - if (CH_WIDTH_80MHZ == req->chan_width) { - dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80; - } - if (CH_WIDTH_40MHZ == req->chan_width) { + + switch (req->chan_width) { + case CH_WIDTH_20MHZ: + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? IEEE80211_CHAN_VHT20 : + IEEE80211_CHAN_HT20); + break; + case CH_WIDTH_40MHZ: if (req->chan < req->ch_center_freq_seg0) - dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ? + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? IEEE80211_CHAN_VHT40PLUS : IEEE80211_CHAN_HT40PLUS); else - dfs_ic->ic_curchan->ic_flags |= (req->vht_capable ? + dfs_ic->ic_curchan->ic_flags |= + (req->vht_capable ? IEEE80211_CHAN_VHT40MINUS : IEEE80211_CHAN_HT40MINUS); - } else if (CH_WIDTH_20MHZ == req->chan_width) { + break; + case CH_WIDTH_80MHZ: + dfs_ic->ic_curchan->ic_flags |= IEEE80211_CHAN_VHT80; + break; + case CH_WIDTH_80P80MHZ: + ext_channel = cds_freq_to_chan(chan->band_center_freq2); + dfs_ic->ic_curchan->ic_flags |= + IEEE80211_CHAN_VHT80P80; + dfs_ic->ic_curchan->ic_freq_ext = + chan->band_center_freq2; + dfs_ic->ic_curchan->ic_ieee_ext = ext_channel; + + /* verify both the 80MHz are DFS bands or not */ + if ((CHANNEL_STATE_DFS == + cds_get_bonded_channel_state(req->chan , + CH_WIDTH_80MHZ)) && + (CHANNEL_STATE_DFS == + cds_get_bonded_channel_state( + ext_channel - 6 , + CH_WIDTH_80MHZ))) + dfs_ic->ic_curchan->ic_80p80_both_dfs = true; + break; + case CH_WIDTH_160MHZ: dfs_ic->ic_curchan->ic_flags |= - (req->vht_capable ? IEEE80211_CHAN_VHT20 : - IEEE80211_CHAN_HT20); + IEEE80211_CHAN_VHT160; + break; + default: + WMA_LOGE( + "%s: Recieved a wrong channel width %d", + __func__, req->chan_width); + break; } + dfs_ic->ic_curchan->ic_flagext |= IEEE80211_CHAN_DFS; if (req->oper_mode == BSS_OPERATIONAL_MODE_AP) { -- cgit v1.2.3 From 07e5e15ad25cfa218cfcdc625cfc03469d3c9595 Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Tue, 19 Jan 2016 18:24:35 -0800 Subject: qcacld-3.0: Fix scan request memory leak scan complete callback function is not freeing scan request memory after scan completion. Free the scan request memory after scan completion. Change-Id: I2636e3b4576d2c86d88dc3e7684a196ed1838297 CRs-Fixed: 964244 --- core/hdd/src/wlan_hdd_scan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 46804353b39b..0b5ec7c2e520 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1014,6 +1014,7 @@ static void hdd_vendor_scan_callback(hdd_adapter_t *adapter, if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { hdd_err("Invalid adapter magic"); + cdf_mem_free(req); return; } skb = cfg80211_vendor_event_alloc(hddctx->wiphy, NULL, @@ -1023,6 +1024,7 @@ static void hdd_vendor_scan_callback(hdd_adapter_t *adapter, if (!skb) { hdd_err("skb alloc failed"); + cdf_mem_free(req); return; } @@ -1067,10 +1069,12 @@ static void hdd_vendor_scan_callback(hdd_adapter_t *adapter, goto nla_put_failure; cfg80211_vendor_event(skb, GFP_KERNEL); + cdf_mem_free(req); return; nla_put_failure: kfree_skb(skb); + cdf_mem_free(req); return; } -- cgit v1.2.3 From 048e1fe407a0cbbeedf4e545891ab3b1393dd979 Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Wed, 20 Jan 2016 12:23:55 -0800 Subject: qcacld-3.0: Fix memory leak in scan Free the scan request parameters after scan request is posted to scan queue. Change-Id: I370249f9ef6b4180a106acb5e6929351ad4a0467 CRs-Fixed: 964341 --- core/sme/src/common/sme_api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0a316bfb5b77..0305d0506a10 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -1733,6 +1733,7 @@ static CDF_STATUS sme_handle_scan_req(tpAniSirGlobal mac_ctx, FL("scan request failed. session_id %d"), session_id); } csr_scan_free_request(mac_ctx, scan_msg->scan_param); + cdf_mem_free(scan_msg->scan_param); return status; } @@ -2989,6 +2990,7 @@ CDF_STATUS sme_scan_request(tHalHandle hal, uint8_t session_id, sms_log(mac_ctx, LOGE, " sme_scan_req failed to post msg"); csr_scan_free_request(mac_ctx, scan_msg->scan_param); + cdf_mem_free(scan_msg->scan_param); cdf_mem_free(scan_msg); status = CDF_STATUS_E_FAILURE; } -- cgit v1.2.3 From 826461a5376b0e2c62dd4ee09b15419d27a48c7f Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 19 Jan 2016 12:42:19 -0800 Subject: qcacld-3.0: Add kernel doc for wlan_hdd_cfg80211_change_iface Add kernel doc for wlan_hdd_cfg80211_change_iface function. Change-Id: I1616b60ba805a055b5b15fbc0bb1aa65ee7b56a3 CRs-Fixed: 964145 --- core/hdd/src/wlan_hdd_cfg80211.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index aa226e1cbd41..154f905c9ea3 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5994,9 +5994,15 @@ void *wlan_hdd_change_country_code_cb(void *pAdapter) return NULL; } -/* - * FUNCTION: __wlan_hdd_cfg80211_change_iface - * This function is used to set the interface type (INFRASTRUCTURE/ADHOC) +/** + * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op + * @wiphy: Pointer to the wiphy structure + * @ndev: Pointer to the net device + * @type: Interface type + * @flags: Flags for change interface + * @params: Pointer to change interface parameters + * + * Return: 0 for success, error number on failure. */ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, @@ -6238,9 +6244,15 @@ done: return 0; } -/* - * FUNCTION: wlan_hdd_cfg80211_change_iface - * wrapper function to protect the actual implementation from SSR. +/** + * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op + * @wiphy: Pointer to the wiphy structure + * @ndev: Pointer to the net device + * @type: Interface type + * @flags: Flags for change interface + * @params: Pointer to change interface parameters + * + * Return: 0 for success, error number on failure. */ static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, -- cgit v1.2.3 From 0e3b224a3195c9e7f38bf03d89e55e1c4778ee59 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 19 Jan 2016 12:56:04 -0800 Subject: qcacld-3.0: Add CDS SSR ready check for driver unload Driver unload is not waiting for external threads to exit before starting clean up process. Add CDS SSR ready check for driver unload such that driver unload waits for all external threads to exit before cleaning up driver data structures. Change-Id: Ic5ac1b770dea8e470ed8dcce50a4f66451f918f1 CRs-Fixed: 964151 --- core/cds/inc/cds_sched.h | 4 +--- core/cds/src/cds_sched.c | 10 +++++----- core/hdd/src/wlan_hdd_driver_ops.c | 5 ++++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 9d77986c3789..3ccf3cb8c6c3 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -438,9 +438,7 @@ void cdf_timer_module_init(void); void cds_ssr_protect_init(void); void cds_ssr_protect(const char *caller_func); void cds_ssr_unprotect(const char *caller_func); -bool cds_is_ssr_ready(const char *caller_func); +bool cds_wait_for_external_threads_completion(const char *caller_func); int cds_get_gfp_flags(void); -#define cds_wait_for_work_thread_completion(func) cds_is_ssr_ready(func) - #endif /* #if !defined __CDS_SCHED_H */ diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index e67485031f78..077bfc346896 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1230,14 +1230,14 @@ void cds_ssr_unprotect(const char *caller_func) } /** - * cds_is_ssr_ready() - check if the calling execution can proceed with ssr - * + * cds_wait_for_external_threads_completion() - wait for external threads + * completion before proceeding further * @caller_func: name of calling function. * * Return: true if there is no active entry points in driver * false if there is at least one active entry in driver */ -bool cds_is_ssr_ready(const char *caller_func) +bool cds_wait_for_external_threads_completion(const char *caller_func) { int count = MAX_SSR_WAIT_ITERATIONS; @@ -1260,7 +1260,7 @@ bool cds_is_ssr_ready(const char *caller_func) } CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, - "Allowing SSR for %s", caller_func); + "Allowing SSR/Driver unload for %s", caller_func); return true; } diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 65462ac3ed10..c366b909185f 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -310,6 +310,9 @@ static void wlan_hdd_remove(void) cds_set_driver_loaded(false); cds_set_unload_in_progress(true); + if (!cds_wait_for_external_threads_completion(__func__)) + hdd_err("External threads are still active attempting driver unload anyway"); + hdd_cnss_driver_unloading(); hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); @@ -354,7 +357,7 @@ static void wlan_hdd_shutdown(void) !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) hif_pktlogmod_exit(hif_ctx); - if (!cds_is_ssr_ready(__func__)) + if (!cds_wait_for_external_threads_completion(__func__)) hdd_err("Host is not ready for SSR, attempting anyway"); if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { -- cgit v1.2.3 From e04c726b30c5efe88aeeb8b42a7617cf039b797f Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 19 Jan 2016 15:05:09 -0800 Subject: qcacld-3.0: Fix cds_is_load_unload_in_progress API cds_is_load_unload_in_progress is checking for both driver load AND unload states. This is leading to all external threads still enter in driver when driver has already started unload clean up process. Fix this API to check either load OR unload in progress driver states. Change-Id: I4cd446393346bc5c085bc9a92ee68f46f1ec5097 CRs-Fixed: 964211 --- core/cds/inc/cds_api.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 059a0d1dea98..588f0e2c176b 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -116,14 +116,14 @@ static inline bool cds_is_driver_recovering(void) /** * cds_is_load_unload_in_progress() - Is driver load/unload in progress * - * Return: true if driver is loading or unloading and false otherwise. + * Return: true if driver is loading OR unloading and false otherwise. */ static inline bool cds_is_load_unload_in_progress(void) { enum cds_driver_state state = cds_get_driver_state(); - return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_LOADING | - CDS_DRIVER_STATE_UNLOADING); + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_LOADING) || + __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_UNLOADING); } /** -- cgit v1.2.3 From e3b4b4b480c95c1cd2e15f33a3e2d524ceb6d56b Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 19 Jan 2016 15:23:52 -0800 Subject: qcacld-3.0: Rename API cds_is_load_unload_in_progress Rename API cds_is_load_unload_in_progress() to cds_is_load_or_unload_in_progress() for clarity purpose. Change-Id: I209c661ccee760f822d5df53577d822f3c741b37 CRs-Fixed: 964217 --- core/bmi/src/ol_fw.c | 2 +- core/cds/inc/cds_api.h | 4 ++-- core/cds/src/cds_sched.c | 2 +- core/hdd/src/wlan_hdd_assoc.c | 4 ++-- core/hdd/src/wlan_hdd_driver_ops.c | 2 +- core/hdd/src/wlan_hdd_hostapd.c | 2 +- core/hdd/src/wlan_hdd_main.c | 2 +- core/hdd/src/wlan_hdd_scan.c | 2 +- core/hdd/src/wlan_hdd_softap_tx_rx.c | 2 +- core/hdd/src/wlan_hdd_tdls.c | 2 +- core/hif/src/hif_main.c | 2 +- core/utils/host_diag_log/src/host_diag_log.c | 4 ++-- core/wma/src/wma_data.c | 4 ++-- core/wma/src/wma_mgmt.c | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c index e73d5c8a65b8..ddb08fefce72 100644 --- a/core/bmi/src/ol_fw.c +++ b/core/bmi/src/ol_fw.c @@ -623,7 +623,7 @@ void ol_target_failure(void *instance, CDF_STATUS status) return; } - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { BMI_ERR("%s: Loading/Unloading is in progress, ignore!", __func__); return; diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 588f0e2c176b..c88218f8f766 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -114,11 +114,11 @@ static inline bool cds_is_driver_recovering(void) } /** - * cds_is_load_unload_in_progress() - Is driver load/unload in progress + * cds_is_load_or_unload_in_progress() - Is driver load OR unload in progress * * Return: true if driver is loading OR unloading and false otherwise. */ -static inline bool cds_is_load_unload_in_progress(void) +static inline bool cds_is_load_or_unload_in_progress(void) { enum cds_driver_state state = cds_get_driver_state(); diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index 077bfc346896..a30b031b12cd 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -120,7 +120,7 @@ cds_cpu_hotplug_notify(struct notifier_block *block, if ((NULL == pSchedContext) || (NULL == pSchedContext->ol_rx_thread)) return NOTIFY_OK; - if (cds_is_load_unload_in_progress()) + if (cds_is_load_or_unload_in_progress()) return NOTIFY_OK; num_cpus = num_possible_cpus(); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 15b7f8bc53ef..06c8c16cc711 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -879,7 +879,7 @@ static void hdd_send_association_event(struct net_device *dev, msg = NULL; /*During the WLAN uninitialization,supplicant is stopped before the driver so not sending the status of the connection to supplicant */ - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { wireless_send_event(dev, we_event, &wrqu, msg); #ifdef FEATURE_WLAN_ESE if (eConnectionState_Associated == @@ -1068,7 +1068,7 @@ static CDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter, * before the driver so not sending the status of the * connection to supplicant. */ - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { #ifdef WLAN_FEATURE_P2P_DEBUG if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) { if (global_p2p_connection_status == diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index c366b909185f..cb4603a76a42 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -346,7 +346,7 @@ static void wlan_hdd_shutdown(void) { void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF); - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { hdd_err("Load/unload in progress, ignore SSR shutdown"); return; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 0e69738968e5..b43b4ecf2fc6 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -222,7 +222,7 @@ static int __hdd_hostapd_open(struct net_device *dev) MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_HOSTAPD_OPEN_REQUEST, NO_SESSION, 0)); - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { hdd_err("Driver load/unload in progress, ignore, state: 0x%x", cds_get_driver_state()); goto done; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 315170ef9103..0278c1dea824 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -527,7 +527,7 @@ int wlan_hdd_validate_context(hdd_context_t *hdd_ctx) return -EAGAIN; } - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x", cds_get_driver_state()); return -EAGAIN; diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 0b5ec7c2e520..1a708a60b881 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -2333,7 +2333,7 @@ static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, return ret; } - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { hdd_err("Unload/Load in Progress, state: 0x%x. Ignore!!!", cds_get_driver_state()); return ret; diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index d6b98e132bcc..698308566ae1 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -809,7 +809,7 @@ CDF_STATUS hdd_softap_stop_bss(hdd_adapter_t *pAdapter) /* bss deregister is not allowed during wlan driver loading or * unloading */ - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { CDF_TRACE(CDF_MODULE_ID_HDD_SAP_DATA, CDF_TRACE_LEVEL_ERROR, "%s: Loading_unloading in Progress, state: 0x%x. Ignore!!!", __func__, cds_get_driver_state()); diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index d7e1cacc64bf..8e48da640e69 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -2842,7 +2842,7 @@ void wlan_hdd_tdls_timer_restart(hdd_adapter_t *pAdapter, hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); /* Check whether driver load unload is in progress */ - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { hddLog(LOGE, FL("Driver load/unload is in progress.")); return; } diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index e76c64c9a590..5ee1727197f1 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -764,7 +764,7 @@ void hif_crash_shutdown(void *hif_ctx) return; } - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__); return; } diff --git a/core/utils/host_diag_log/src/host_diag_log.c b/core/utils/host_diag_log/src/host_diag_log.c index 4fd357eb1547..168ccd7decda 100644 --- a/core/utils/host_diag_log/src/host_diag_log.c +++ b/core/utils/host_diag_log/src/host_diag_log.c @@ -116,7 +116,7 @@ void host_diag_log_submit(void *plog_hdr_ptr) uint16_t data_len; uint16_t total_len; - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Unloading/Loading in Progress. Ignore!!!", __func__); @@ -213,7 +213,7 @@ void host_diag_event_report_payload(uint16_t event_Id, uint16_t length, event_report_t *pEvent_report; uint16_t total_len; - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO, "%s: Unloading/Loading in Progress. Ignore!!!", __func__); diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index e93e49979d86..91bb65d4b57c 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -806,7 +806,7 @@ static void wma_data_tx_ack_work_handler(void *ack_work) tp_wma_handle wma_handle; pWMAAckFnTxComp ack_cb; - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { WMA_LOGE("%s: Driver load/unload in progress", __func__); return; } @@ -1480,7 +1480,7 @@ static void wma_mgmt_tx_ack_work_handler(void *ack_work) tp_wma_handle wma_handle; pWMAAckFnTxComp ack_cb; - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { WMA_LOGE("%s: Driver load/unload in progress", __func__); return; } diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 6827e25ce207..d9da1626706c 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -3176,7 +3176,7 @@ static int wma_mgmt_rx_process(void *handle, uint8_t *data, return -ENOMEM; } - if (cds_is_load_unload_in_progress()) { + if (cds_is_load_or_unload_in_progress()) { WMA_LOGE("Load/Unload in progress"); return -EINVAL; } -- cgit v1.2.3 From 8f9e6e392c4fda36c309f5fb877a8c122d07768d Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Wed, 6 Jan 2016 18:32:14 -0800 Subject: qcacld-3.0: Fix memory leak in hdd_send_re_assoc_event In case kmalloc fail goto end of function and properly free other possible allocated memory buffers. Change-Id: I41d7577471b475b0a2a0daa83c6ffc845314ceb4 CRs-Fixed: 958755 --- core/hdd/src/wlan_hdd_assoc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 06c8c16cc711..2f1d820c2116 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1379,12 +1379,12 @@ static void hdd_send_re_assoc_event(struct net_device *dev, if (!rspRsnIe) { hddLog(LOGE, FL("Unable to allocate RSN IE")); - return; + goto done; } if (!assoc_req_ies) { hdd_err("Unable to allocate Assoc Req IE"); - return; + goto done; } if (pCsrRoamInfo == NULL) { hddLog(LOGE, FL("Invalid CSR roam info")); -- cgit v1.2.3 From a20cd9f91d43add22607aa0ae000ac6c36322378 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Wed, 26 Aug 2015 12:13:18 -0700 Subject: qcacld-3.0: Fix definition of tx_timer_create macro Add new argument for mac_ctx in definition of tx_timer_create macro so that its caller can use any local variable name for mac context. Currently pMac is hardcoded as first param in definition of the macro which prohibits caller of that function from using any other name. Change-Id: Id901424ba16846eab62c00a80d48a5c85c73bea6 CRs-Fixed: 824222 --- core/mac/src/pe/lim/lim_assoc_utils.c | 8 ++-- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 2 +- core/mac/src/pe/lim/lim_timer_utils.c | 50 +++++++++++----------- .../src/sys/legacy/src/platform/inc/sys_wrapper.h | 4 +- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index cd2b14c8cb0c..9637e85a07d6 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -4932,10 +4932,10 @@ void lim_init_pre_auth_timer_table(tpAniSirGlobal pMac, cfgValue = SYS_MS_TO_TICKS(cfgValue); for (authNodeIdx = 0; authNodeIdx < pPreAuthTimerTable->numEntry; authNodeIdx++, pAuthNode++) { - if (tx_timer_create - (&pAuthNode->timer, "AUTH RESPONSE TIMEOUT", - lim_auth_response_timer_handler, authNodeIdx, cfgValue, 0, - TX_NO_ACTIVATE) != TX_SUCCESS) { + if (tx_timer_create(pMac, &pAuthNode->timer, + "AUTH RESPONSE TIMEOUT", + lim_auth_response_timer_handler, authNodeIdx, + cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { /* Cannot create timer. Log error. */ lim_log(pMac, LOGP, FL("Cannot create Auth Rsp timer of Index :%d."), diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index e7418bd49ef1..aa7cf8db3487 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1461,7 +1461,7 @@ sendIndToSme: if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN > retryInterval) { retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF; } - if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer", + if (tx_timer_create(pMac, &pStaDs->pmfSaQueryTimer, "PMF SA Query timer", lim_pmf_sa_query_timer_handler, timerId.value, SYS_MS_TO_TICKS((retryInterval * 1024) / 1000), 0, TX_NO_ACTIVATE) != TX_SUCCESS) { diff --git a/core/mac/src/pe/lim/lim_timer_utils.c b/core/mac/src/pe/lim/lim_timer_utils.c index f68f7b08bbf6..26838581309b 100644 --- a/core/mac/src/pe/lim/lim_timer_utils.c +++ b/core/mac/src/pe/lim/lim_timer_utils.c @@ -60,7 +60,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) { uint32_t cfgValue; /* Create Channel Switch Timer */ - if (tx_timer_create(&pMac->lim.limTimers.gLimChannelSwitchTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimChannelSwitchTimer, "CHANNEL SWITCH TIMER", lim_channel_switch_timer_handler, 0, LIM_CHANNEL_SWITCH_TIMER_TICKS, @@ -72,7 +72,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) * 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, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimQuietTimer, "QUIET TIMER", lim_quiet_timer_handler, SIR_LIM_QUIET_TIMEOUT, LIM_QUIET_TIMER_TICKS, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -84,7 +84,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) * timer, gLimQuietBssTimer, trigger and put the STA to sleep for the * specified gLimQuietDuration */ - if (tx_timer_create(&pMac->lim.limTimers.gLimQuietBssTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimQuietBssTimer, "QUIET BSS TIMER", lim_quiet_bss_timer_handler, SIR_LIM_QUIET_BSS_TIMEOUT, LIM_QUIET_BSS_TIMER_TICK, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -98,7 +98,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) 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, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimJoinFailureTimer, "JOIN FAILURE TIMEOUT", lim_timer_handler, SIR_LIM_JOIN_FAIL_TIMEOUT, cfgValue, 0, @@ -110,7 +110,8 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) return false; } /* Send unicast probe req frame every 200 ms */ - if (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, + if (tx_timer_create(pMac, + &pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, "Periodic Join Probe Request Timer", lim_timer_handler, SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT, @@ -128,7 +129,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(cfgValue); /* Create Association failure timer and activate it later */ - if (tx_timer_create(&pMac->lim.limTimers.gLimAssocFailureTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimAssocFailureTimer, "ASSOC FAILURE TIMEOUT", lim_assoc_failure_timer_handler, LIM_ASSOC, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -143,8 +144,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(cfgValue); /* Create Association failure timer and activate it later */ - if (tx_timer_create - (&pMac->lim.limTimers.gLimReassocFailureTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimReassocFailureTimer, "REASSOC FAILURE TIMEOUT", lim_assoc_failure_timer_handler, LIM_REASSOC, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { lim_log(pMac, LOGP, @@ -160,7 +160,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(cfgValue); /* Create Addts response timer and activate it later */ - if (tx_timer_create(&pMac->lim.limTimers.gLimAddtsRspTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimAddtsRspTimer, "ADDTS RSP TIMEOUT", lim_addts_response_timer_handler, SIR_LIM_ADDTS_RSP_TIMEOUT, @@ -177,7 +177,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(cfgValue); /* Create Auth failure timer and activate it later */ - if (tx_timer_create(&pMac->lim.limTimers.gLimAuthFailureTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimAuthFailureTimer, "AUTH FAILURE TIMEOUT", lim_timer_handler, SIR_LIM_AUTH_FAIL_TIMEOUT, @@ -193,7 +193,7 @@ lim_create_non_ap_timers(tpAniSirGlobal pMac) /* Change timer to reactivate it in future */ cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimProbeAfterHBTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimProbeAfterHBTimer, "Probe after Heartbeat TIMEOUT", lim_timer_handler, SIR_LIM_PROBE_HB_FAILURE_TIMEOUT, @@ -238,10 +238,11 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue1 = cfgValue / 2; /* Create periodic probe request timer and activate them later */ if (cfgValue1 >= 1 - && (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, - "Periodic Probe Request Timer", lim_timer_handler, - SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT, cfgValue1, 0, - TX_NO_ACTIVATE) != TX_SUCCESS)) { + && (tx_timer_create(pMac, + &pMac->lim.limTimers.gLimPeriodicProbeReqTimer, + "Periodic Probe Request Timer", lim_timer_handler, + SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT, cfgValue1, 0, + TX_NO_ACTIVATE) != TX_SUCCESS)) { lim_log(pMac, LOGP, FL("could not create periodic probe timer")); goto err_timer; @@ -262,7 +263,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(LIM_HASH_MISS_TIMER_MS); - if (tx_timer_create( + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer, "Disassoc throttle TIMEOUT", lim_send_disassoc_frame_threshold_handler, @@ -282,7 +283,8 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue = SYS_MS_TO_TICKS(cfgValue); for (i = 0; i < (pMac->lim.maxStation + 1); i++) { - if (tx_timer_create(&pMac->lim.limTimers.gpLimCnfWaitTimer[i], + if (tx_timer_create(pMac, + &pMac->lim.limTimers.gpLimCnfWaitTimer[i], "CNF_MISS_TIMEOUT", lim_cnf_wait_tmer_handler, (uint32_t) i, cfgValue, @@ -315,7 +317,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) FL("could not retrieve OLBD detect timeout value")); cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimUpdateOlbcCacheTimer, "OLBC UPDATE CACHE TIMEOUT", lim_update_olbc_cache_timer_handler, SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT, cfgValue, @@ -330,7 +332,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) */ cfgValue = 1000; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimFTPreAuthRspTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimFTPreAuthRspTimer, "FT PREAUTH RSP TIMEOUT", lim_timer_handler, SIR_LIM_FT_PREAUTH_RSP_TIMEOUT, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -340,7 +342,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) #endif cfgValue = 1000; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimRemainOnChannelTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimRemainOnChannelTimer, "FT PREAUTH RSP TIMEOUT", lim_timer_handler, SIR_LIM_REMAIN_CHN_TIMEOUT, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -350,7 +352,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue = 1000; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimDisassocAckTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimDisassocAckTimer, "DISASSOC ACK TIMEOUT", lim_timer_handler, SIR_LIM_DISASSOC_ACK_TIMEOUT, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -360,7 +362,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue = 1000; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create(&pMac->lim.limTimers.gLimDeauthAckTimer, + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimDeauthAckTimer, "DISASSOC ACK TIMEOUT", lim_timer_handler, SIR_LIM_DEAUTH_ACK_TIMEOUT, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { @@ -375,7 +377,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) */ cfgValue = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create( + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer, "Single Shot NOA Insert timeout", lim_timer_handler, SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT, cfgValue, 0, @@ -387,7 +389,7 @@ uint32_t lim_create_timers(tpAniSirGlobal pMac) cfgValue = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT; cfgValue = SYS_MS_TO_TICKS(cfgValue); - if (tx_timer_create( + if (tx_timer_create(pMac, &pMac->lim.limTimers.gLimActiveToPassiveChannelTimer, "ACTIVE TO PASSIVE CHANNEL", lim_timer_handler, SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, cfgValue, 0, diff --git a/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h b/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h index 6aeb635cd0a0..8a4a2c010186 100644 --- a/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h +++ b/core/mac/src/sys/legacy/src/platform/inc/sys_wrapper.h @@ -89,9 +89,9 @@ extern "C" { #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((void *)pMac, a, b, c, d, e, f, g, __FILE__, __LINE__) +#define tx_timer_create(a, b, c, d, e, f, g, h) tx_timer_create_intern_debug((void *)a, b, c, d, e, f, g, h, __FILE__, __LINE__) #else -#define tx_timer_create(a, b, c, d, e, f, g) tx_timer_create_intern((void *)pMac, a, b, c, d, e, f, g) +#define tx_timer_create(a, b, c, d, e, f, g, h) tx_timer_create_intern((void *)a, b, c, d, e, f, g, h) #endif /*--------------------------------------------------------------------*/ -- cgit v1.2.3 From 01c7dd9c4ee1e8bab5c798e45d197c34c64f5666 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Wed, 6 Jan 2016 18:35:53 -0800 Subject: qcacld-3.0: Remove unnecessary lock from sme_roam_free_connect_profile Remove unnecessary acquiring of SME lock in sme_roam_free_connect_profile since this function does not access any SME structures. Change-Id: I0ddafc4276ef5028b48fda0ae3ea4e6a0c23245e CRs-Fixed: 958839 --- core/hdd/src/wlan_hdd_assoc.c | 2 +- core/hdd/src/wlan_hdd_cfg80211.c | 2 +- core/sme/inc/sme_api.h | 3 +-- core/sme/src/common/sme_api.c | 31 ++++++++++--------------------- core/sme/src/csr/csr_api_roam.c | 34 ++++++++++++---------------------- core/sme/src/csr/csr_inside_api.h | 9 +-------- core/sme/src/csr/csr_neighbor_roam.c | 4 ++-- 7 files changed, 28 insertions(+), 57 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 2f1d820c2116..bb81a878d4b0 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1480,7 +1480,7 @@ static void hdd_send_re_assoc_event(struct net_device *dev, rspRsnIe, rspRsnLength, pCsrRoamInfo); done: - sme_roam_free_connect_profile(hal_handle, &roam_profile); + sme_roam_free_connect_profile(&roam_profile); if (final_req_ie) kfree(final_req_ie); kfree(rspRsnIe); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 154f905c9ea3..102c44790c9f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7470,7 +7470,7 @@ struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter, hddLog(LOG1, FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL")); - sme_roam_free_connect_profile(hHal, &roamProfile); + sme_roam_free_connect_profile(&roamProfile); } else { hddLog(LOGE, FL("roamProfile.pBssDesc is NULL")); } diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index c1698cf5e592..49850aae7cb2 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -293,8 +293,7 @@ CDF_STATUS sme_roam_get_connect_state(tHalHandle hHal, uint8_t sessionId, eCsrConnectState *pState); CDF_STATUS sme_roam_get_connect_profile(tHalHandle hHal, uint8_t sessionId, tCsrRoamConnectedProfile *pProfile); -CDF_STATUS sme_roam_free_connect_profile(tHalHandle hHal, - tCsrRoamConnectedProfile *pProfile); +void sme_roam_free_connect_profile(tCsrRoamConnectedProfile *profile); CDF_STATUS sme_roam_set_pmkid_cache(tHalHandle hHal, uint8_t sessionId, tPmkidCacheInfo *pPMKIDCache, uint32_t numItems, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0305d0506a10..e2607e99d0c8 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -3931,31 +3931,20 @@ CDF_STATUS sme_roam_get_connect_profile(tHalHandle hHal, uint8_t sessionId, return status; } -/* --------------------------------------------------------------------------- - \fn sme_roam_free_connect_profile - \brief a wrapper function to request CSR to free and reinitialize the - profile returned previously by csr_roam_get_connect_profile. - This is a synchronous call. - \param pProfile - pointer to a caller allocated structure - tCsrRoamConnectedProfile - \return CDF_STATUS. - ---------------------------------------------------------------------------*/ -CDF_STATUS sme_roam_free_connect_profile(tHalHandle hHal, - tCsrRoamConnectedProfile *pProfile) +/** + * sme_roam_free_connect_profile - a wrapper function to request CSR to free and + * reinitialize the profile returned previously by csr_roam_get_connect_profile. + * + * @profile - pointer to a caller allocated structure tCsrRoamConnectedProfile + * + * Return: none + */ +void sme_roam_free_connect_profile(tCsrRoamConnectedProfile *profile) { - CDF_STATUS status = CDF_STATUS_E_FAILURE; - tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - MTRACE(cdf_trace(CDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE, NO_SESSION, 0)); - status = sme_acquire_global_lock(&pMac->sme); - if (CDF_IS_STATUS_SUCCESS(status)) { - status = csr_roam_free_connect_profile(pMac, pProfile); - sme_release_global_lock(&pMac->sme); - } - - return status; + csr_roam_free_connect_profile(profile); } /* --------------------------------------------------------------------------- diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 922b80743fe7..9b1e60cf17f9 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1075,21 +1075,14 @@ CDF_STATUS csr_roam_get_connect_profile(tpAniSirGlobal pMac, uint32_t sessionId, return status; } -CDF_STATUS csr_roam_free_connect_profile(tpAniSirGlobal pMac, - tCsrRoamConnectedProfile *pProfile) +void csr_roam_free_connect_profile(tCsrRoamConnectedProfile *profile) { - CDF_STATUS status = CDF_STATUS_SUCCESS; - - if (pProfile->pBssDesc) { - cdf_mem_free(pProfile->pBssDesc); - } - if (pProfile->pAddIEAssoc) { - cdf_mem_free(pProfile->pAddIEAssoc); - } - cdf_mem_set(pProfile, sizeof(tCsrRoamConnectedProfile), 0); - - pProfile->AuthType = eCSR_AUTH_TYPE_UNKNOWN; - return status; + if (profile->pBssDesc) + cdf_mem_free(profile->pBssDesc); + if (profile->pAddIEAssoc) + cdf_mem_free(profile->pAddIEAssoc); + cdf_mem_set(profile, sizeof(tCsrRoamConnectedProfile), 0); + profile->AuthType = eCSR_AUTH_TYPE_UNKNOWN; } static CDF_STATUS csr_roam_free_connected_info(tpAniSirGlobal pMac, @@ -5759,8 +5752,7 @@ static void csr_roam_process_results_default(tpAniSirGlobal mac_ctx, * to send down stop BSS later */ csr_free_connect_bss_desc(mac_ctx, session_id); - csr_roam_free_connect_profile(mac_ctx, - &session->connectedProfile); + csr_roam_free_connect_profile(&session->connectedProfile); csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); csr_set_default_dot11_mode(mac_ctx); } @@ -6003,10 +5995,8 @@ static void csr_roam_process_start_bss_success(tpAniSirGlobal mac_ctx, session_id); } csr_roam_save_connected_bss_desc(mac_ctx, session_id, bss_desc); - csr_roam_free_connect_profile(mac_ctx, - &session->connectedProfile); - csr_roam_free_connected_info(mac_ctx, - &session->connectedInfo); + csr_roam_free_connect_profile(&session->connectedProfile); + csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); if (bss_desc) { csr_roam_save_connected_infomation(mac_ctx, session_id, profile, bss_desc, ies_ptr); @@ -15091,7 +15081,7 @@ void csr_cleanup_session(tpAniSirGlobal pMac, uint32_t sessionId) sme_ft_close(pMac, sessionId); #endif csr_free_connect_bss_desc(pMac, sessionId); - csr_roam_free_connect_profile(pMac, &pSession->connectedProfile); + csr_roam_free_connect_profile(&pSession->connectedProfile); csr_roam_free_connected_info(pMac, &pSession->connectedInfo); cdf_mc_timer_destroy(&pSession->hTimerRoaming); #ifdef FEATURE_WLAN_BTAMP_UT_RF @@ -15151,7 +15141,7 @@ static void csr_init_session(tpAniSirGlobal pMac, uint32_t sessionId) pSession->pContext = NULL; pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; csr_free_roam_profile(pMac, sessionId); - csr_roam_free_connect_profile(pMac, &pSession->connectedProfile); + csr_roam_free_connect_profile(&pSession->connectedProfile); csr_roam_free_connected_info(pMac, &pSession->connectedInfo); csr_free_connect_bss_desc(pMac, sessionId); csr_scan_enable(pMac); diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index ab0f12719bca..99414ad2330a 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -836,14 +836,7 @@ CDF_STATUS csr_roam_get_connect_profile(tpAniSirGlobal pMac, uint32_t sessionId, CDF_STATUS csr_roam_get_connect_state(tpAniSirGlobal pMac, uint32_t sessionId, eCsrConnectState *pState); -/* --------------------------------------------------------------------------- - \fn csr_roam_free_connect_profile - \brief To free and reinitialize the profile return previous by csr_roam_get_connect_profile. - \param pProfile - pointer to a caller allocated structure tCsrRoamConnectedProfile - \return CDF_STATUS. - -------------------------------------------------------------------------------*/ -CDF_STATUS csr_roam_free_connect_profile(tpAniSirGlobal pMac, - tCsrRoamConnectedProfile *pProfile); +void csr_roam_free_connect_profile(tCsrRoamConnectedProfile *profile); /* --------------------------------------------------------------------------- \fn csr_apply_channel_and_power_list diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 40f282787327..2e8198225330 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -2272,7 +2272,7 @@ CDF_STATUS csr_neighbor_roam_indicate_disconnect(tpAniSirGlobal pMac, * Free the current previous profile and move * the current profile to prev profile. */ - csr_roam_free_connect_profile(pMac, pPrevProfile); + csr_roam_free_connect_profile(pPrevProfile); csr_roam_copy_connect_profile(pMac, sessionId, pPrevProfile); /* * clear the roaming parameters that are per connection. @@ -2890,7 +2890,7 @@ void csr_neighbor_roam_close(tpAniSirGlobal pMac, uint8_t sessionId) /* Free the profile.. */ csr_release_profile(pMac, &pNeighborRoamInfo->csrNeighborRoamProfile); - csr_roam_free_connect_profile(pMac, &pNeighborRoamInfo->prevConnProfile); + csr_roam_free_connect_profile(&pNeighborRoamInfo->prevConnProfile); #ifdef WLAN_FEATURE_VOWIFI_11R pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; pNeighborRoamInfo->FTRoamInfo.numBssFromNeighborReport = 0; -- cgit v1.2.3 From dc2b5f5e8dabfe148c72275c670b2c5a79b62b0f Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 21 Jan 2016 10:00:16 +0530 Subject: qcacld-3.0: Use appropriate API to get total free descriptors Use appropriate API to get total free descriptors for all flow pool. CRs-Fixed: 964984 Change-Id: I1ac40b2ce55743a65c6c487fd4055fe34ab61d2d --- core/dp/txrx/ol_txrx.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 05e4d0a3e060..8193e12f0b80 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -332,6 +332,32 @@ uint32_t ol_tx_get_desc_global_pool_size(struct ol_txrx_pdev_t *pdev) { return pdev->num_msdu_desc; } + +/** + * ol_tx_get_total_free_desc() - get total free descriptors + * @pdev: pdev handle + * + * Return: total free descriptors + */ +static inline +uint32_t ol_tx_get_total_free_desc(struct ol_txrx_pdev_t *pdev) +{ + struct ol_tx_flow_pool_t *pool = NULL; + uint32_t free_desc; + + free_desc = pdev->tx_desc.num_free; + cdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock); + TAILQ_FOREACH(pool, &pdev->tx_desc.flow_pool_list, + flow_pool_list_elem) { + cdf_spin_lock_bh(&pool->flow_pool_lock); + free_desc += pool->avail_desc; + cdf_spin_unlock_bh(&pool->flow_pool_lock); + } + cdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock); + + return free_desc; +} + #else /** * ol_tx_get_desc_global_pool_size() - get global pool size @@ -344,6 +370,19 @@ uint32_t ol_tx_get_desc_global_pool_size(struct ol_txrx_pdev_t *pdev) { return ol_cfg_target_tx_credit(pdev->ctrl_pdev); } + +/** + * ol_tx_get_total_free_desc() - get total free descriptors + * @pdev: pdev handle + * + * Return: total free descriptors + */ +static inline +uint32_t ol_tx_get_total_free_desc(struct ol_txrx_pdev_t *pdev) +{ + return pdev->tx_desc.num_free; +} + #endif /** @@ -1859,7 +1898,7 @@ int ol_txrx_get_tx_pending(ol_txrx_pdev_handle pdev_handle) total = ol_tx_get_desc_global_pool_size(pdev); - return total - pdev->tx_desc.num_free; + return total - ol_tx_get_total_free_desc(pdev); } void ol_txrx_discard_tx_pending(ol_txrx_pdev_handle pdev_handle) -- cgit v1.2.3 From e8825e9bace76dfc281c8227d278f31ae8bc6628 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Thu, 21 Jan 2016 18:58:06 +0530 Subject: qcacld-3.0: Fix memory leak in case of fw reset stats command Fix memory leak in case of txrx_fw_st_rst command where we are not expecting any response from firmware. CRs-Fixed: 964465 Change-Id: Iad91cb5557ef167d126ef68e07f02445ad7a0b97 --- core/dp/ol/inc/ol_txrx_dbg.h | 7 ++++--- core/dp/txrx/ol_txrx.c | 6 +++++- core/wma/src/wma_utils.c | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/dp/ol/inc/ol_txrx_dbg.h b/core/dp/ol/inc/ol_txrx_dbg.h index 035010936527..138e1ed0df21 100644 --- a/core/dp/ol/inc/ol_txrx_dbg.h +++ b/core/dp/ol/inc/ol_txrx_dbg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -82,7 +82,7 @@ struct ol_txrx_stats_req { #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_fw_stats_get(vdev, req, response_expected) 0 #define ol_txrx_aggr_cfg(vdev, max_subfrms_ampdu, max_subfrms_amsdu) 0 #else /*---------------------------------------------------------------------*/ @@ -95,7 +95,8 @@ void ol_txrx_fw_stats_cfg(ol_txrx_vdev_handle vdev, uint8_t cfg_stats_type, uint32_t cfg_val); int ol_txrx_fw_stats_get(ol_txrx_vdev_handle vdev, - struct ol_txrx_stats_req *req); + struct ol_txrx_stats_req *req, + bool response_expected); int ol_txrx_aggr_cfg(ol_txrx_vdev_handle vdev, int max_subfrms_ampdu, int max_subfrms_amsdu); diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 8193e12f0b80..2a75a527609d 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1965,7 +1965,8 @@ ol_txrx_fw_stats_cfg(ol_txrx_vdev_handle vdev, } A_STATUS -ol_txrx_fw_stats_get(ol_txrx_vdev_handle vdev, struct ol_txrx_stats_req *req) +ol_txrx_fw_stats_get(ol_txrx_vdev_handle vdev, struct ol_txrx_stats_req *req, + bool response_expected) { struct ol_txrx_pdev_t *pdev = vdev->pdev; uint64_t cookie; @@ -2006,6 +2007,9 @@ ol_txrx_fw_stats_get(ol_txrx_vdev_handle vdev, struct ol_txrx_stats_req *req) while (cdf_semaphore_acquire(pdev->osdev, req->wait.sem_ptr)) ; + if (response_expected == false) + cdf_mem_free(non_volatile_req); + return A_OK; } #endif diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index c7b0a621fd6e..1f91443b9164 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1834,7 +1834,7 @@ int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle, } cdf_mem_zero(&req, sizeof(req)); req.stats_type_reset_mask = value; - ol_txrx_fw_stats_get(vdev, &req); + ol_txrx_fw_stats_get(vdev, &req, false); return 0; } @@ -1947,7 +1947,7 @@ int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle, } req.stats_type_upload_mask = l_up_mask; - ol_txrx_fw_stats_get(vdev, &req); + ol_txrx_fw_stats_get(vdev, &req, true); return 0; } -- cgit v1.2.3 From 945c02a9d617f77acd4a49f2a3c710b78775bd61 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Mon, 11 Jan 2016 19:31:38 -0800 Subject: qcacld-3.0: Set the IMPS enable/disable based on INI Send IMPS disable cmd to FW if IMPS is disabled in INI. Change-Id: Ib5e663d1966ab059b69aa0b7a3bc92a99dd6368a CRs-Fixed: 962402 --- core/hdd/src/wlan_hdd_cfg.c | 14 ++++---------- core/hdd/src/wlan_hdd_main.c | 5 ++++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 378d9fe96296..551f12e261ae 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -5507,20 +5507,14 @@ eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode(eHddDot11Mode dot11Mode) */ CDF_STATUS hdd_set_idle_ps_config(hdd_context_t *pHddCtx, uint32_t val) { - struct hdd_config *pConfig = pHddCtx->config; CDF_STATUS status = CDF_STATUS_SUCCESS; hddLog(LOG1, "hdd_set_idle_ps_config: Enter Val %d", val); - if (pConfig->fIsImpsEnabled) { - status = sme_set_idle_powersave_config(pHddCtx->pcds_context, - pHddCtx->hHal, val); - if (CDF_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"); - } + status = sme_set_idle_powersave_config(pHddCtx->pcds_context, + pHddCtx->hHal, val); + if (CDF_STATUS_SUCCESS != status) + hddLog(LOGE, "Fail to Set Idle PS Config val %d", val); return status; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0278c1dea824..6e8f8bb2428a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5685,7 +5685,10 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_hostapd_channel_wakelock_init(hdd_ctx); - hdd_set_idle_ps_config(hdd_ctx, true); + if (hdd_ctx->config->fIsImpsEnabled) + hdd_set_idle_ps_config(hdd_ctx, true); + else + hdd_set_idle_ps_config(hdd_ctx, false); #ifdef FEATURE_WLAN_AUTO_SHUTDOWN if (hdd_ctx->config->WlanAutoShutdown != 0) if (sme_set_auto_shutdown_cb -- cgit v1.2.3 From 381c39f7c498631f6f2d158ea27ecd86628335c8 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Wed, 16 Dec 2015 16:03:16 -0800 Subject: qcacld-3.0: Enable Tx beamformee in SAP mode Currently Tx beamformee feature is enabled only in STA mode. Add knob to enable or disable the Tx beamformee feature in SAP mode Change-Id: I6ea218b3bff6c973688aad716a3f1a3c8acc469b CRs-Fixed: 963034 --- config/WCNSS_qcom_cfg.ini | 3 +++ core/hdd/inc/wlan_hdd_cfg.h | 10 ++++++++++ core/hdd/src/wlan_hdd_cfg.c | 9 +++++++++ core/mac/inc/sir_api.h | 2 ++ core/mac/src/pe/include/lim_session.h | 1 + core/mac/src/pe/lim/lim_process_sme_req_messages.c | 19 +++++++------------ core/mac/src/sys/legacy/src/utils/src/parser_api.c | 14 +++++++++----- core/sme/inc/csr_api.h | 1 + core/sme/inc/csr_internal.h | 1 + core/sme/src/csr/csr_api_roam.c | 8 ++++++++ 10 files changed, 51 insertions(+), 17 deletions(-) diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 8de3a16d4241..cab58d6c3c77 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -367,6 +367,9 @@ gEnableRXLDPC=1 #Enable/Disable Tx beamforming gTxBFEnable=1 +#Enable/Disable Tx beamformee in SAP mode +gEnableTxBFeeSAP=1 + # Enable Tx beamforming in VHT20MHz # Valid values are 0,1. If commented out, the default value is 0. # 0=disable, 1=enable diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 33c79eb54bdc..c626a29dcb02 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1739,6 +1739,15 @@ typedef enum { #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) +/* + * Enable / Disable Tx beamformee in SAP mode + * Default: Disable + */ +#define CFG_VHT_ENABLE_TXBF_SAP_MODE "gEnableTxBFeeSAP" +#define CFG_VHT_ENABLE_TXBF_SAP_MODE_MIN (0) +#define CFG_VHT_ENABLE_TXBF_SAP_MODE_MAX (1) +#define CFG_VHT_ENABLE_TXBF_SAP_MODE_DEFAULT (0) + #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) @@ -3154,6 +3163,7 @@ struct hdd_config { uint8_t vhtRxMCS; uint8_t vhtTxMCS; bool enableTxBF; + bool enable_txbf_sap_mode; uint8_t txBFCsnValue; bool enable_su_tx_bformer; uint8_t vhtRxMCS2x2; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 551f12e261ae..b8b2adf98e26 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -2427,6 +2427,13 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MIN, CFG_VHT_SU_BEAMFORMEE_CAP_FEATURE_MAX), + REG_VARIABLE(CFG_VHT_ENABLE_TXBF_SAP_MODE, WLAN_PARAM_Integer, + struct hdd_config, enable_txbf_sap_mode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_VHT_ENABLE_TXBF_SAP_MODE_DEFAULT, + CFG_VHT_ENABLE_TXBF_SAP_MODE_MIN, + CFG_VHT_ENABLE_TXBF_SAP_MODE_MAX), + REG_VARIABLE(CFG_VHT_ENABLE_TXBF_IN_20MHZ, WLAN_PARAM_Integer, struct hdd_config, enableTxBFin20MHz, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -6485,6 +6492,8 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) #ifdef WLAN_FEATURE_11AC smeConfig->csrConfig.nVhtChannelWidth = pConfig->vhtChannelWidth; smeConfig->csrConfig.enableTxBF = pConfig->enableTxBF; + smeConfig->csrConfig.enable_txbf_sap_mode = + pConfig->enable_txbf_sap_mode; smeConfig->csrConfig.txBFCsnValue = pConfig->txBFCsnValue; smeConfig->csrConfig.enable2x2 = pConfig->enable2x2; smeConfig->csrConfig.enableVhtFor24GHz = pConfig->enableVhtFor24GHzBand; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index a077817867f4..51f2e11ad537 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -610,6 +610,8 @@ typedef struct sSirSmeStartBssReq { uint8_t center_freq_seg0; uint8_t center_freq_seg1; uint8_t sec_ch_offset; + bool txbf_ini_enabled; + uint8_t txbf_csn_val; uint8_t privacy; uint8_t apUapsdEnable; diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 4a5b5752a791..e5847c000262 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -330,6 +330,7 @@ typedef struct sPESession /* Added to Support BT-AMP */ phy_ch_width ch_width; uint8_t ch_center_freq_seg1; uint8_t txBFIniFeatureEnabled; + uint8_t txbf_csn_value; uint8_t txMuBformee; uint8_t enableVhtpAid; uint8_t enableVhtGid; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 47caaf885c71..3d806079fb1d 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -718,7 +718,6 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) session->vhtCapability); session->txLdpcIniFeatureEnabled = sme_start_bss_req->txLdpcIniFeatureEnabled; - if (mac_ctx->roam.configParam.enable2x2) session->nss = 2; else @@ -741,6 +740,12 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) case eSIR_INFRA_AP_MODE: lim_configure_ap_start_bss_session(mac_ctx, session, sme_start_bss_req); + if (session->pePersona == CDF_SAP_MODE) { + session->txBFIniFeatureEnabled = + sme_start_bss_req->txbf_ini_enabled; + session->txbf_csn_value = + sme_start_bss_req->txbf_csn_val; + } break; case eSIR_IBSS_MODE: session->limSystemRole = eLIM_STA_IN_IBSS_ROLE; @@ -1740,17 +1745,7 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED, "%s: txBFCsnValue=%d", __func__, sme_join_req->txBFCsnValue); - if (cfg_set_int(mac_ctx, - WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, - sme_join_req->txBFCsnValue) != eSIR_SUCCESS) { - /* - * Set Failed for CFG - * CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED - */ - lim_log(mac_ctx, LOGP, FL("Set Fail CFG")); - ret_code = eSIR_LOGP_EXCEPTION; - goto end; - } + session->txbf_csn_value = sme_join_req->txBFCsnValue; } #endif diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index f7cfb78f38bb..2d443af9042f 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1002,6 +1002,8 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac, CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, nCfgValue); pDot11f->muBeamformeeCap = (nCfgValue & 0x0001); + pDot11f->csnofBeamformerAntSup = + psessionEntry->txbf_csn_value; } else { pDot11f->muBeamformeeCap = 0; } @@ -1037,11 +1039,13 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac, 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_CSN_BEAMFORMEE_ANT_SUPPORTED, - nCfgValue); - pDot11f->csnofBeamformerAntSup = (nCfgValue & 0x0007); nCfgValue = 0; CFG_GET_INT(nStatus, pMac, WNI_CFG_VHT_NUM_SOUNDING_DIMENSIONS, diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index a34856598ef2..fd4621a8bc57 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1166,6 +1166,7 @@ typedef struct tagCsrConfigParam { #ifdef WLAN_FEATURE_11AC uint32_t nVhtChannelWidth; uint8_t enableTxBF; + uint8_t enable_txbf_sap_mode; uint8_t txBFCsnValue; uint8_t enable2x2; bool enableVhtFor24GHz; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index c0a7a506f578..e2bbd48eb53a 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -601,6 +601,7 @@ typedef struct tagCsrConfig { #ifdef WLAN_FEATURE_11AC uint32_t nVhtChannelWidth; uint8_t txBFEnable; + uint8_t enable_txbf_sap_mode; uint8_t txBFCsnValue; uint8_t enable2x2; bool enableVhtFor24GHz; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 9b1e60cf17f9..ebbfe474c24c 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2026,6 +2026,8 @@ CDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pMac->roam.configParam.nVhtChannelWidth = pParam->nVhtChannelWidth; pMac->roam.configParam.txBFEnable = pParam->enableTxBF; + pMac->roam.configParam.enable_txbf_sap_mode = + pParam->enable_txbf_sap_mode; pMac->roam.configParam.txBFCsnValue = pParam->txBFCsnValue; pMac->roam.configParam.enable2x2 = pParam->enable2x2; pMac->roam.configParam.enableVhtFor24GHz = @@ -2189,6 +2191,8 @@ CDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) #ifdef WLAN_FEATURE_11AC pParam->nVhtChannelWidth = cfg_params->nVhtChannelWidth; pParam->enableTxBF = cfg_params->txBFEnable; + pParam->enable_txbf_sap_mode = + cfg_params->enable_txbf_sap_mode; pParam->txBFCsnValue = cfg_params->txBFCsnValue; pParam->enableMuBformee = cfg_params->txMuBformee; pParam->enableVhtFor24GHz = cfg_params->enableVhtFor24GHz; @@ -14600,6 +14604,10 @@ CDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId pMsg->isCoalesingInIBSSAllowed = pMac->isCoalesingInIBSSAllowed; pMsg->bssPersona = pParam->bssPersona; pMsg->txLdpcIniFeatureEnabled = pMac->roam.configParam.txLdpcEnable; + pMsg->txbf_ini_enabled = + (uint8_t)pMac->roam.configParam.txBFEnable && + (uint8_t)pMac->roam.configParam.enable_txbf_sap_mode; + pMsg->txbf_csn_val = (uint8_t)pMac->roam.configParam.txBFCsnValue; #ifdef WLAN_FEATURE_11W pMsg->pmfCapable = pParam->mfpCapable; pMsg->pmfRequired = pParam->mfpRequired; -- cgit v1.2.3 From ef86da0a957bd276ea2fcf2fc5ad39e15c7bd019 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 18 Jan 2016 13:46:36 -0800 Subject: qcacld-3.0: Remove epping context from cds cds_get_context was not supporting epping. Allow epping to manage its own global context since it is a top level module. Change-Id: Ic5faf885c83109162be141788a5f8871a4e35cef CRs-Fixed: 967244 --- core/cds/inc/cds_sched.h | 1 - core/cds/src/cds_api.c | 11 +-------- core/utils/epping/inc/epping_internal.h | 4 +-- core/utils/epping/src/epping_main.c | 44 ++++++++++++++++----------------- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 3ccf3cb8c6c3..3d8d367d3d5e 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -263,7 +263,6 @@ typedef struct _cds_context_type { void *htc_ctx; - void *epping_ctx; /* * cdf_ctx will be used by cdf * while allocating dma memory diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 5c36ef3944f5..448aee02073d 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1068,10 +1068,6 @@ CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID, } case CDF_MODULE_ID_EPPING: - { - pGpModContext = &(gp_cds_context->epping_ctx); - break; - } case CDF_MODULE_ID_SME: case CDF_MODULE_ID_PE: case CDF_MODULE_ID_HDD: @@ -1154,18 +1150,13 @@ CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID, break; } - case CDF_MODULE_ID_EPPING: - { - pGpModContext = &(gp_cds_context->epping_ctx); - break; - } - case CDF_MODULE_ID_TXRX: { pGpModContext = &(gp_cds_context->pdev_txrx_ctx); break; } + case CDF_MODULE_ID_EPPING: case CDF_MODULE_ID_HDD: case CDF_MODULE_ID_SME: case CDF_MODULE_ID_PE: diff --git a/core/utils/epping/inc/epping_internal.h b/core/utils/epping/inc/epping_internal.h index ab68c2b18b49..0ea5d526558c 100644 --- a/core/utils/epping/inc/epping_internal.h +++ b/core/utils/epping/inc/epping_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -104,7 +104,7 @@ typedef struct { } epping_poll_t; #endif -typedef struct epping_context_s { +typedef struct epping_context { int32_t con_mode; char *pwlan_module_name; uint32_t target_type; diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c index a625c0b109b5..2fa63759009c 100644 --- a/core/utils/epping/src/epping_main.c +++ b/core/utils/epping/src/epping_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -73,6 +73,8 @@ #define WLAN_WAIT_TIME_WLANSTART 2000 #endif +static struct epping_context *g_epping_ctx; + /** * epping_open(): End point ping driver open Function * @@ -83,22 +85,17 @@ */ int epping_open(void) { - epping_context_t *pEpping_ctx; - v_CONTEXT_t cds_context; - CDF_STATUS status = CDF_STATUS_SUCCESS; - EPPING_LOG(CDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__); - cds_context = cds_get_global_context(); - status = cds_alloc_context(cds_context, CDF_MODULE_ID_EPPING, - (void **)&pEpping_ctx, - sizeof(*pEpping_ctx)); - if (status != CDF_STATUS_SUCCESS) { - EPPING_LOG(CDF_TRACE_LEVEL_ERROR, "%s: cannot alloc epping context", __func__); + g_epping_ctx = cdf_mem_malloc(sizeof(*g_epping_ctx)); + + if (g_epping_ctx == NULL) { + EPPING_LOG(CDF_TRACE_LEVEL_ERROR, + "%s: cannot alloc epping context", __func__); return -ENOMEM; } - pEpping_ctx->con_mode = cds_get_conparam(); + g_epping_ctx->con_mode = cds_get_conparam(); return 0; } @@ -114,7 +111,7 @@ void epping_disable(void) { epping_context_t *pEpping_ctx; - pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + pEpping_ctx = g_epping_ctx; if (pEpping_ctx == NULL) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, "%s: error: pEpping_ctx = NULL", __func__); @@ -140,30 +137,31 @@ void epping_disable(void) */ void epping_close(void) { - epping_context_t *pEpping_ctx; + epping_context_t *to_free; - pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); - if (pEpping_ctx == NULL) { + + if (g_epping_ctx == NULL) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, - "%s: error: pEpping_ctx = NULL", __func__); + "%s: error: g_epping_ctx = NULL", __func__); return; } - cds_free_context(NULL, CDF_MODULE_ID_EPPING, - cds_get_context(CDF_MODULE_ID_EPPING)); + + to_free = g_epping_ctx; + g_epping_ctx = NULL; + cdf_mem_free(to_free); } static void epping_target_suspend_acknowledge(void *context) { - epping_context_t *pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); int wow_nack = *((int *)context); - if (NULL == pEpping_ctx) { + if (NULL == g_epping_ctx) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, "%s: epping_ctx is NULL", __func__); return; } /* EPPING_TODO: do we need wow_nack? */ - pEpping_ctx->wow_nack = wow_nack; + g_epping_ctx->wow_nack = wow_nack; } /** @@ -195,7 +193,7 @@ int epping_enable(struct device *parent_dev) return ret; } - pEpping_ctx = cds_get_context(CDF_MODULE_ID_EPPING); + pEpping_ctx = g_epping_ctx; if (pEpping_ctx == NULL) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, "%s: Failed to get pEpping_ctx", __func__); -- cgit v1.2.3 From ebc68145ac84407604ad2021202858947513b2ab Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 18 Jan 2016 15:38:27 -0800 Subject: qcacld-3.0: Remove hif_claim_device hif_claim_device does not serve a purpose in copy engine. The usage and implementation of hif_claim_device need to be reexamined for sdio and usb. It should not store the device in a ce specific data structure. Change-Id: I0847e152ae3a1ca57d5c6937d6929918063cc362 CRs-Fixed: 967244 --- core/bmi/src/bmi.c | 3 +-- core/hif/inc/hif.h | 10 +--------- core/hif/src/ce/ce_main.c | 14 -------------- core/hif/src/ce/ce_main.h | 4 +--- core/utils/epping/src/epping_main.c | 2 -- 5 files changed, 3 insertions(+), 30 deletions(-) diff --git a/core/bmi/src/bmi.c b/core/bmi/src/bmi.c index ddeab53c0197..6753f01b1bf2 100644 --- a/core/bmi/src/bmi.c +++ b/core/bmi/src/bmi.c @@ -1,5 +1,5 @@ /* - * copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -110,7 +110,6 @@ void bmi_cleanup(struct ol_softc *scn) CDF_STATUS bmi_done(struct ol_softc *scn) { CDF_STATUS status = CDF_STATUS_SUCCESS; - hif_claim_device(scn, scn); if (NO_BMI) return status; diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 0adc66dafbad..3f66a7b64705 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -394,14 +394,6 @@ typedef struct osdrv_callbacks { */ int hif_init(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 hif_claim_device(struct ol_softc *scn, void *claimedContext); -/* release the claimed device */ -void hif_release_device(struct ol_softc *scn); - /* This API detaches the HTC layer from the HIF device */ void hif_detach_htc(struct ol_softc *scn); diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 0b7d9d000e37..af6233c19f31 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -872,20 +872,6 @@ static void hif_msg_callbacks_install(struct ol_softc *scn) sizeof(hif_state->msg_callbacks_pending)); } -void hif_claim_device(struct ol_softc *scn, void *claimedContext) -{ - struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; - - hif_state->claimedContext = claimedContext; -} - -void hif_release_device(struct ol_softc *scn) -{ - struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl; - - hif_state->claimedContext = NULL; -} - void hif_get_default_pipe(struct ol_softc *scn, uint8_t *ULPipe, uint8_t *DLPipe) { diff --git a/core/hif/src/ce/ce_main.h b/core/hif/src/ce/ce_main.h index 1e82e58d045f..8806bd31367d 100644 --- a/core/hif/src/ce/ce_main.h +++ b/core/hif/src/ce/ce_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -123,8 +123,6 @@ struct HIF_CE_state { /* current msg callbacks in use */ struct hif_msg_callbacks msg_callbacks_current; - void *claimedContext; - /* Target address used to signal a pending firmware event */ uint32_t fw_indicator_address; diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c index 2fa63759009c..cfbf04cf1c1e 100644 --- a/core/utils/epping/src/epping_main.c +++ b/core/utils/epping/src/epping_main.c @@ -251,8 +251,6 @@ int epping_enable(struct device *parent_dev) } scn->htc_handle = pEpping_ctx->HTCHandle; - hif_claim_device(scn->hif_hdl, scn); - if (bmi_done(scn)) { EPPING_LOG(CDF_TRACE_LEVEL_FATAL, "%s: Failed to complete BMI phase", __func__); -- cgit v1.2.3 From 3cfe68601a773ab6450bfe70704ab58718f4fd18 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Fri, 8 Jan 2016 10:33:55 -0800 Subject: qcacld-3.0: move hif_bus_open to hif_open Can consolidate these allocations. Change-Id: I8af6fa459db62c99bf93ecdbd1dcd94bbee580a8 CRs-Fixed: 967256 --- core/hdd/src/wlan_hdd_driver_ops.c | 2 +- core/hif/inc/hif.h | 2 +- core/hif/src/hif_main.c | 19 +++++++++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index cb4603a76a42..0627f9e7ae50 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -125,7 +125,7 @@ static int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid, int ret = 0; void *hif_ctx; - status = hif_open(); + status = hif_open(bus_type); if (!CDF_IS_STATUS_SUCCESS(status)) { hdd_err("hif_open error = %d", status); return cdf_status_to_os_return(status); diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 3f66a7b64705..08885739dd3d 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -627,7 +627,7 @@ void hif_disable_isr(void *scn); void hif_reset_soc(void *scn); void hif_disable_aspm(void); void hif_save_htc_htt_config_endpoint(int htc_endpoint); -CDF_STATUS hif_open(void); +CDF_STATUS hif_open(enum ath_hal_bus_type bus_type); void hif_close(void *hif_ctx); CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, void *bdev, const hif_bus_id *bid, enum ath_hal_bus_type bus_type, diff --git a/core/hif/src/hif_main.c b/core/hif/src/hif_main.c index 5ee1727197f1..ef1aca1939f0 100644 --- a/core/hif/src/hif_main.c +++ b/core/hif/src/hif_main.c @@ -511,7 +511,7 @@ void hif_set_fw_info(void *scn, uint32_t target_fw_version) * * Return: scn */ -CDF_STATUS hif_open(void) +CDF_STATUS hif_open(enum ath_hal_bus_type bus_type) { struct ol_softc *scn; v_CONTEXT_t cds_context; @@ -536,6 +536,14 @@ CDF_STATUS hif_open(void) cdf_atomic_init(&scn->tasklet_from_intr); init_waitqueue_head(&scn->aps_osdev.event_queue); scn->linkstate_vote = 0; + + status = hif_bus_open(scn, bus_type); + if (status != CDF_STATUS_SUCCESS) { + HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d", + __func__, status, bus_type); + cds_free_context(cds_context, CDF_MODULE_ID_HIF, scn); + } + return status; } @@ -592,16 +600,8 @@ CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, return CDF_STATUS_E_NULL_VALUE; } - status = hif_bus_open(scn, bus_type); - if (status != CDF_STATUS_SUCCESS) { - HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d", - __func__, status, bus_type); - return status; - } - status = hif_enable_bus(scn, dev, bdev, bid, type); if (status != CDF_STATUS_SUCCESS) { - hif_bus_close(scn); HIF_ERROR("%s: hif_enable_bus error = %d", __func__, status); return status; @@ -613,7 +613,6 @@ CDF_STATUS hif_enable(void *hif_ctx, struct device *dev, if (hif_config_ce(scn)) { HIF_ERROR("%s: Target probe failed.", __func__); hif_disable_bus(scn->aps_osdev.bdev); - hif_bus_close(scn); status = CDF_STATUS_E_FAILURE; return status; } -- cgit v1.2.3 From 3e502cb8f8832fa5d9eb3c8b1735595ed7106a4b Mon Sep 17 00:00:00 2001 From: Liangwei Dong Date: Thu, 5 Nov 2015 21:50:25 -0500 Subject: qcacld-3.0: correct phy_mode in hdd_chan_change_notify qcacld-2.0 to qcacld-3.0 propagation The sap Context related phyMode should be used instead of the phyMode in hal. Otherwise, the incorrect channel width will be reported to supplicant. Change-Id: Ic0ce7861a786de5aef8b43c6aa0fde9f600b08b2 CRs-Fixed: 909668 --- core/hdd/src/wlan_hdd_hostapd.c | 20 +++++++++++++++++++- core/sap/inc/sap_api.h | 1 + core/sap/src/sap_module.c | 23 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index b43b4ecf2fc6..9ddd3fd6d48a 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -604,6 +604,21 @@ static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter, } } +#ifdef WLAN_FEATURE_MBSSID +static eCsrPhyMode +hdd_sap_get_phymode(hdd_adapter_t *hostapd_adapter) +{ + return wlansap_get_phymode(WLAN_HDD_GET_SAP_CTX_PTR(hostapd_adapter)); +} +#else +static eCsrPhyMode +hdd_sap_get_phymode(hdd_adapter_t *hostapd_adapter) +{ + return wlansap_get_phymode( + (WLAN_HDD_GET_CTX(hostapd_adapter))->pcds_context); +} +#endif + /** * hdd_chan_change_notify() - Function to notify hostapd about channel change * @hostapd_adapter hostapd adapter @@ -641,7 +656,7 @@ CDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, return CDF_STATUS_E_FAILURE; } - phy_mode = sme_get_phy_mode(hal); + phy_mode = hdd_sap_get_phymode(hostapd_adapter); if (oper_chan <= 14) cb_mode = sme_get_cb_phy_state_from_cb_ini_value( @@ -669,6 +684,9 @@ CDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, break; } + hdd_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); diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 0da62d0f9c05..e77d058822ea 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -906,6 +906,7 @@ CDF_STATUS wlansap_acs_chselect(void *pvos_gctx, tpWLAN_SAPEventCB pacs_event_callback, tsap_Config_t *pconfig, void *pusr_context); +eCsrPhyMode wlansap_get_phymode(void *pctx); #ifdef __cplusplus } #endif diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 581db3d8bdc2..63b9981bf27f 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -3299,3 +3299,26 @@ void wlan_sap_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; } +/** +* 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(void *pctx) +{ + ptSapContext sap_context = NULL; + + sap_context = CDS_GET_SAP_CB(pctx); + if (NULL == sap_context) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: Invalid SAP pointer from pctx", __func__); + return eCSR_DOT11_MODE_AUTO; + } + return sap_context->csr_roamProfile.phyMode; +} -- cgit v1.2.3 From 30de2f1e488e5467e938f427c9b647c542469d18 Mon Sep 17 00:00:00 2001 From: Rakesh Sunki Date: Thu, 10 Dec 2015 15:11:19 -0800 Subject: qcacld-3.0: SAP DFS-3 Feature support in WMA Adding support for parsing the WMI_PHYERR_EVENTID for DFS-3 in WMA event handler. Configure the hw board id to DFS module fetched from the wmi service ready event. Change-Id: I003fab790c7f46b54e5d41bcf1bbfa16f0cdc722 CRs-Fixed: 964262 --- core/wma/inc/wma_dfs_interface.h | 17 +++++++++++++ core/wma/inc/wma_internal.h | 11 +++++++-- core/wma/src/wma_features.c | 52 ++++++++++++++++++++++++++++++++++++---- core/wma/src/wma_main.c | 1 + 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 5783ed454642..27fa5b4fe31a 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -103,6 +103,9 @@ /* In case of VHT160, we can have 8 20Mhz channels */ #define IEE80211_MAX_20M_SUB_CH 8 +#define WMA_DFS2_PHYERROR_CODE 0x5 +#define WMA_DFS2_FALSE_RADAR_EXT 0x24 + /** * struct dfs_ieee80211_channel - channel info * @ic_freq: frequency in MHz @@ -168,6 +171,19 @@ struct ieee80211_dfs_state { uint8_t enable : 1, cac_timer_running : 1, ignore_dfs : 1, ignore_cac : 1; }; +/** + * enum DFS_HWBD_ID - Board ID to differentiate between DFS-2 and DFS-3 + * @DFS_HWBD_NONE: No hw board information/currently used for adreastea FPGA + * @DFS_HWBD_QCA6174: Rome(AR6320) + * @DFS_HWBD_QCA2582: Killer 1525 + */ +typedef enum { + DFS_HWBD_NONE = 0, + DFS_HWBD_QCA6174 = 1, + DFS_HWBD_QCA2582 = 2, +} DFS_HWBD_ID; + + /** * struct ieee80211com - per device structure * @ic_opmode: operation mode @@ -239,6 +255,7 @@ typedef struct ieee80211com { int32_t dfs_pri_multiplier; cdf_spinlock_t chan_lock; bool disable_phy_err_processing; + DFS_HWBD_ID dfs_hw_bd_id; } IEEE80211COM, *PIEEE80211COM; /** diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index ea192525f642..bf8b1dfafb84 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -77,8 +77,15 @@ #define MKK 0x40 #define ETSI 0x30 -/* Maximum Buffer length allowed for DFS phyerrors */ -#define DFS_MAX_BUF_LENGHT 4096 +/* Maximum Buffer length allowed for DFS-2 phyerrors */ +#define DFS_MAX_BUF_LENGTH 4096 + +/* + * Maximum Buffer length allowed for DFS-3 phyerrors + * When 160MHz is supported the Max length of phyerrors + * is larger than the legacy phyerrors. + */ +#define DFS3_MAX_BUF_LENGTH 4436 #define WMI_DEFAULT_NOISE_FLOOR_DBM (-96) diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 8c733ee6853b..689851376a1d 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -2181,10 +2181,12 @@ static int wma_unified_phyerr_rx_event_handler(void *handle, cdf_size_t n; A_UINT64 tsf64 = 0; int phy_err_code = 0; + A_UINT32 phy_err_mask = 0; int error = 0; tpAniSirGlobal mac_ctx = (tpAniSirGlobal)cds_get_context(CDF_MODULE_ID_PE); bool enable_log = false; + int max_dfs_buf_length = 0; if (NULL == mac_ctx) { WMA_LOGE("%s: mac_ctx is NULL", __func__); @@ -2211,10 +2213,19 @@ static int wma_unified_phyerr_rx_event_handler(void *handle, __func__, sizeof(*pe_hdr), datalen); return 0; } - if (pe_hdr->buf_len > DFS_MAX_BUF_LENGHT) { + /* + * The max buffer lenght is larger for DFS-3 than DFS-2. + * So, accordingly use the correct max buffer size. + */ + if (wma->hw_bd_id != WMI_HWBD_QCA6174) + max_dfs_buf_length = DFS3_MAX_BUF_LENGTH; + else + max_dfs_buf_length = DFS_MAX_BUF_LENGTH; + + if (pe_hdr->buf_len > max_dfs_buf_length) { WMA_LOGE("%s: Received Invalid Phyerror event buffer length = %d" "Maximum allowed buf length = %d", __func__, - pe_hdr->buf_len, DFS_MAX_BUF_LENGHT); + pe_hdr->buf_len, max_dfs_buf_length); return 0; } @@ -2227,6 +2238,21 @@ static int wma_unified_phyerr_rx_event_handler(void *handle, tsf64 = pe_hdr->tsf_l32; tsf64 |= (((uint64_t) pe_hdr->tsf_u32) << 32); + /* + * Check the HW board ID to figure out + * if DFS-3 is supported. In DFS-3 + * phyerror mask indicates the type of + * phyerror, whereas in DFS-2 phyerrorcode + * indicates the type of phyerror. If the + * board is NOT WMI_HWBD_QCA6174, for now + * assume that it supports DFS-3. + */ + if (wma->hw_bd_id != WMI_HWBD_QCA6174) { + phy_err_mask = pe_hdr->rsPhyErrMask0; + WMA_LOGD("%s: DFS-3 phyerror mask = 0x%x", + __func__, phy_err_mask); + } + /* * Loop over the bufp, extracting out phyerrors * wmi_unified_comb_phyerr_rx_event.bufp is a char pointer, @@ -2271,14 +2297,30 @@ static int wma_unified_phyerr_rx_event_handler(void *handle, error = 1; break; } - phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr); + /* + * If the board id is WMI_HWBD_QCA6174 + * then it supports only DFS-2. So, fetch + * phyerror code in order to know the type + * of phyerror. + */ + if (wma->hw_bd_id == WMI_HWBD_QCA6174) { + phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr); + WMA_LOGD("%s: DFS-2 phyerror code = 0x%x", + __func__, phy_err_code); + } /* - * If the phyerror category matches, + * phy_err_code is set for DFS-2 and phy_err_mask + * is set for DFS-3. Checking both to support + * compatability for older platforms. + * If the phyerror or phyerrmask 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 (((phy_err_mask & WMI_PHY_ERROR_MASK0_RADAR) || + (phy_err_mask & WMI_PHY_ERROR_MASK0_FALSE_RADAR_EXT)) || + (phy_err_code == WMA_DFS2_PHYERROR_CODE || + phy_err_code == WMA_DFS2_FALSE_RADAR_EXT)) { if (ev->hdr.buf_len > 0) { /* Calling in to the DFS module to process the phyerr */ dfs_process_phyerr(ic, &ev->bufp[0], diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 815fbd9c964c..5ca415c0ccf0 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3815,6 +3815,7 @@ void wma_rx_service_ready_event(WMA_HANDLE handle, void *cmd_param_info) sizeof(wma_handle->hw_bd_info)); WMA_LOGE("%s: Board version is unknown!", __func__); } + wma_handle->dfs_ic->dfs_hw_bd_id = wma_handle->hw_bd_id; /* TODO: Recheck below line to dump service ready event */ /* dbg_print_wmi_service_11ac(ev); */ -- cgit v1.2.3 From 2782fb52023f63b08a750ba4a5681737fb3cc153 Mon Sep 17 00:00:00 2001 From: Rakesh Sunki Date: Mon, 14 Dec 2015 15:09:40 -0800 Subject: qcacld-3.0: SAP DFS-3 Feature support in DFS layer Introduce DFS-3 support changes in DFS layer. Add support for per segment based queuing, processing and pattern matching of the radar events in 80+80 channel width mode, when both segments are dfs. Also, add support for parsing the new DFS-3 radar summary report and extract the segment ID on which a phyerror is seen. Report the segment ID on which the radar has been detected to the WMA layer to add only radar detected 80MHz segment channels to be added to NOL in 80+80 MHz channel width mode. Change-Id: Ib9ed2122844cef5fde2b632accc8c798e86bf7a3 CRs-Fixed: 964262 --- core/sap/dfs/inc/dfs.h | 37 +++- core/sap/dfs/src/dfs.c | 70 ++++++- core/sap/dfs/src/dfs_bindetects.c | 35 +++- core/sap/dfs/src/dfs_fcc_bin5.c | 26 ++- core/sap/dfs/src/dfs_init.c | 131 ++++++++++--- core/sap/dfs/src/dfs_phyerr_tlv.c | 293 +++++++++++++++++++++++++----- core/sap/dfs/src/dfs_phyerr_tlv.h | 38 ++++ core/sap/dfs/src/dfs_process_phyerr.c | 9 + core/sap/dfs/src/dfs_process_radarevent.c | 152 +++++++++++----- core/sap/dfs/src/dfs_staggered.c | 8 +- core/wma/inc/wma_dfs_interface.h | 9 + 11 files changed, 650 insertions(+), 158 deletions(-) diff --git a/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h index 64bc046fa04f..f3bdff8e7efb 100644 --- a/core/sap/dfs/inc/dfs.h +++ b/core/sap/dfs/inc/dfs.h @@ -98,6 +98,9 @@ #define DFS_STATUS_SUCCESS 0 #define DFS_STATUS_FAIL 1 +#define DFS_80P80_SEG0 0 +#define DFS_80P80_SEG1 1 + /* * Constants to use for chirping detection. * @@ -115,6 +118,8 @@ #define MAX_BIN5_DUR 145 #define MAX_BIN5_DUR_MICROSEC 105 +#define DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER 1000000 + #define DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a, b)) <= margin) #define DFS_MAX_STAGGERED_BURSTS 3 @@ -280,6 +285,7 @@ struct dfs_event { uint32_t re_freq_lo; /* Lower bounds of frequency, KHz */ uint32_t re_freq_hi; /* Upper bounds of frequency, KHz */ int sidx; /* Pulse Index as in radar summary report */ + int radar_80p80_segid; /* 80p80 segment ID as in radar sum report */ STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */ } cdf_packed; #ifdef WIN32 @@ -355,6 +361,8 @@ struct dfs_delayline { struct dfs_filter { /* Delay line of pulses for this filter */ struct dfs_delayline rf_dl; + /* Delay line of pulses for this filter in 80p80 */ + struct dfs_delayline rf_dl_ext_seg; /* Number of pulses in the filter */ uint32_t rf_numpulses; /* min pri to be considered for this filter */ @@ -475,6 +483,7 @@ struct dfs_info { uint64_t dfs_bin5_chirp_ts; uint8_t dfs_last_bin5_dur; + uint8_t dfs_last_bin5_dur_ext_seg; } cdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_info) @@ -574,6 +583,8 @@ struct ath_dfs { struct dfs_info dfs_rinfo; /* State vars for radar processing */ struct dfs_bin5radars *dfs_b5radars; /* array of bin5 radar events */ + /* array of bin5 radar events on extension segment in 80p80 */ + struct dfs_bin5radars *dfs_b5radars_ext_seg; 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 */ @@ -583,6 +594,7 @@ struct ath_dfs { struct ath_dfs_phyerr_param dfs_defaultparams; struct dfs_stats ath_dfs_stats; /* DFS related stats */ struct dfs_pulseline *pulses; /* pulse history */ + struct dfs_pulseline *pulses_ext_seg; /* pulse history ext 80p80 seg */ struct dfs_event *events; /* Events structure */ uint32_t ath_radar_tasksched:1, /* radar task is scheduled */ @@ -630,6 +642,8 @@ struct ath_dfs { * channel switch is disabled. */ int8_t disable_dfs_ch_switch; + uint32_t test_ts; /* to capture timestamps on primary segment */ + uint32_t test_ts_ext_seg; /* to capture timestamps on ext segment */ }; /* This should match the table from if_ath.c */ @@ -718,6 +732,11 @@ struct dfs_phy_err { uint8_t rssi; /* pulse RSSI */ uint8_t dur; /* pulse duration, raw (not uS) */ int sidx; /* Pulse Index as in radar summary report */ + /* + * Indicates segment ID on which the phyerror is received + * when SAP is operating in 80p80 channel width. + */ + int radar_80p80_segid; }; /* Attach, detach, handle ioctl prototypes */ @@ -746,14 +765,14 @@ 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, uint64_t thists); -int dfs_bin5_check(struct ath_dfs *dfs); +int dfs_bin5_check(struct ath_dfs *dfs, int seg_id); int dfs_check_chirping(struct ath_dfs *dfs, void *buf, uint16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc); uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur); + uint8_t old_dur, int seg_id); uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur); + uint8_t old_dur, int seg_id); int dfs_get_random_bin5_dur(struct ath_dfs *dfs, uint64_t tstamp); /* Debug prototypes */ @@ -773,26 +792,26 @@ struct dfs_state *dfs_getchanstate(struct ath_dfs *dfs, uint8_t *index, 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_alldelaylines(struct ath_dfs *dfs, int seg_id); 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, uint32_t deltaT, uint64_t this_ts); + struct dfs_event *re, uint32_t deltaT, uint64_t this_ts, + int seg_id); int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t dur, int ext_chan_flag); + uint32_t dur, int ext_chan_flag, int seg_id); int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t dur, int ext_chan_flag); + uint32_t deltaT, uint32_t dur, int ext_chan_flag, int seg_id); int dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_delayline *dl, uint32_t score, uint32_t refpri, uint32_t refdur, int ext_chan_flag, int fundamentalpri); int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t width); + uint32_t deltaT, uint32_t width, int seg_id); /* False detection reduction */ int dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, int is_fixed_pattern); diff --git a/core/sap/dfs/src/dfs.c b/core/sap/dfs/src/dfs.c index 2d0a81a3c55d..22ba6f405b0a 100644 --- a/core/sap/dfs/src/dfs.c +++ b/core/sap/dfs/src/dfs.c @@ -300,6 +300,28 @@ int dfs_attach(struct ieee80211com *ic) return 1; } + /* + * If the chip supports DFS-3 then allocate + * memory for pulses for extension segment. + */ + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->pulses_ext_seg = (struct dfs_pulseline *) + os_malloc(NULL, + sizeof(struct dfs_pulseline), + GFP_ATOMIC); + if (dfs->pulses_ext_seg == NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + OS_FREE(dfs); + ic->ic_dfs = NULL; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: pulse buffer allocation failed", + __func__, __LINE__); + return 1; + } + dfs->pulses_ext_seg->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + } + dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; /* Allocate memory for radar filters */ @@ -351,6 +373,10 @@ int dfs_attach(struct ieee80211com *ic) 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 (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->dfs_rinfo.dfs_last_bin5_dur_ext_seg = MAX_BIN5_DUR; + dfs->dfs_b5radars_ext_seg = NULL; + } /* * If dfs_init_radar_filters() fails, we can abort here and @@ -388,6 +414,11 @@ bad1: OS_FREE(dfs->pulses); dfs->pulses = NULL; } + if (dfs->pulses_ext_seg && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->pulses_ext_seg); + dfs->pulses_ext_seg = NULL; + } if (dfs->events) { OS_FREE(dfs->events); dfs->events = NULL; @@ -446,9 +477,12 @@ void dfs_detach(struct ieee80211com *ic) } #endif #endif + /* Return radar events to free q */ dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); /* Free up pulse log */ if (dfs->pulses != NULL) { @@ -456,6 +490,12 @@ void dfs_detach(struct ieee80211com *ic) dfs->pulses = NULL; } + if (dfs->pulses_ext_seg != NULL && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->pulses_ext_seg); + dfs->pulses_ext_seg = NULL; + } + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { if (dfs->dfs_radarf[n] != NULL) { OS_FREE(dfs->dfs_radarf[n]); @@ -481,6 +521,11 @@ void dfs_detach(struct ieee80211com *ic) OS_FREE(dfs->dfs_b5radars); dfs->dfs_b5radars = NULL; } + if (dfs->dfs_b5radars_ext_seg != NULL && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->dfs_b5radars_ext_seg); + dfs->dfs_b5radars_ext_seg = NULL; + } /* Commenting out since all the ar functions are obsolete and * the function definition has been removed as part of dfs_ar.c @@ -582,7 +627,14 @@ int dfs_radar_enable(struct ieee80211com *ic, if (is_ext_ch) { ext_ch = ieee80211_get_extchan(ic); } - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + /* + * Extension segment delaylines will be + * enabled only when SAP operates in 80p80 + * and both the channels are DFS. + */ + if (chan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); rs_pri = dfs_getchanstate(dfs, &index_pri, 0); if (ext_ch) { @@ -594,9 +646,17 @@ int dfs_radar_enable(struct ieee80211com *ic, OS_MEMSET(&pe, '\0', sizeof(pe)); - if (index_pri != dfs->dfs_curchan_radindex) - dfs_reset_alldelaylines(dfs); - + if (index_pri != dfs->dfs_curchan_radindex) { + dfs_reset_alldelaylines(dfs, + DFS_80P80_SEG0); + /* + * Reset only when ext segment is + * present + */ + if (chan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, + DFS_80P80_SEG1); + } dfs->dfs_curchan_radindex = (int16_t) index_pri; dfs->dfs_pri_multiplier_ini = radar_info->dfs_pri_multiplier; diff --git a/core/sap/dfs/src/dfs_bindetects.c b/core/sap/dfs/src/dfs_bindetects.c index 7c48309942ca..dc3acf6dabd6 100644 --- a/core/sap/dfs/src/dfs_bindetects.c +++ b/core/sap/dfs/src/dfs_bindetects.c @@ -59,14 +59,19 @@ int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t dur, int ext_chan_flag) + uint32_t dur, int ext_chan_flag, int seg_id) { - struct dfs_pulseline *pl = dfs->pulses; + struct dfs_pulseline *pl; int i, n, refpri, primargin, numpulses = 0; uint64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end; uint32_t index, next_index, deltadur; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; + else + pl = dfs->pulses; + /* For fixed pattern types, rf->rf_patterntype=1 */ primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype == 1)); @@ -151,12 +156,15 @@ dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, void dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, - uint32_t deltaT, uint64_t this_ts) + uint32_t deltaT, uint64_t this_ts, int seg_id) { uint32_t index, n, window; struct dfs_delayline *dl; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + 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) */ @@ -197,7 +205,7 @@ dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, - uint32_t width, int ext_chan_flag) + uint32_t width, int ext_chan_flag, int seg_id) { uint32_t refpri, refdur, searchpri, deltapri, deltapri_2, deltapri_3, averagerefpri; @@ -208,7 +216,11 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, int numpulses = 0; int lowprichk = 3, pri_match = 0; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + dl = &rf->rf_dl; + if (dl->dl_numelems < (rf->rf_threshold - 1)) { return 0; } @@ -226,7 +238,8 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, if (rf->rf_patterntype == 1) { found = - dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag); + dfs_bin_fixedpattern_check(dfs, rf, width, + ext_chan_flag, seg_id); if (found) { dl->dl_numelems = 0; } @@ -330,7 +343,13 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, "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); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_print_delayline(dfs, + (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg); + else + dfs_print_delayline(dfs, &rf->rf_dl); + dfs_print_filter(dfs, rf); } return found; diff --git a/core/sap/dfs/src/dfs_fcc_bin5.c b/core/sap/dfs/src/dfs_fcc_bin5.c index d6f62542c0ce..027e3211866e 100644 --- a/core/sap/dfs/src/dfs_fcc_bin5.c +++ b/core/sap/dfs/src/dfs_fcc_bin5.c @@ -176,7 +176,7 @@ int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, * properly, then signify that a bin5 radar was found */ -int dfs_bin5_check(struct ath_dfs *dfs) +int dfs_bin5_check(struct ath_dfs *dfs, int seg_id) { struct dfs_bin5radars *br; int index[DFS_MAX_B5_SIZE]; @@ -191,7 +191,11 @@ int dfs_bin5_check(struct ath_dfs *dfs) return 1; } for (n = 0; n < dfs->dfs_rinfo.rn_numbin5radars; n++) { - br = &(dfs->dfs_b5radars[n]); + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + br = (seg_id == 0) ? &(dfs->dfs_b5radars[n]) : + &(dfs->dfs_b5radars_ext_seg[n]); + else + br = &(dfs->dfs_b5radars[n]); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "Num elems = %d\n", br->br_numelems); @@ -806,9 +810,18 @@ dfs_check_chirping(struct ath_dfs *dfs, void *buf, uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur) + uint8_t old_dur, int seg_id) { + u_int8_t dfs_last_bin5_dur; + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_last_bin5_dur = (seg_id == 0) ? + dfs->dfs_rinfo.dfs_last_bin5_dur : + dfs->dfs_rinfo.dfs_last_bin5_dur_ext_seg; + else + dfs_last_bin5_dur = dfs->dfs_rinfo.dfs_last_bin5_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 @@ -821,7 +834,7 @@ dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, 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); + dfs_last_bin5_dur, old_dur); } /* * Check if this is the 2nd or 3rd pulse in the same burst, @@ -836,10 +849,9 @@ dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, 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); + __func__, dfs_last_bin5_dur, old_dur); - return (dfs->dfs_rinfo.dfs_last_bin5_dur); + return dfs_last_bin5_dur; } /* * This pulse does not belong to this burst, return unchanged diff --git a/core/sap/dfs/src/dfs_init.c b/core/sap/dfs/src/dfs_init.c index ca259c4af8ea..7ab7df12a9cb 100644 --- a/core/sap/dfs/src/dfs_init.c +++ b/core/sap/dfs/src/dfs_init.c @@ -66,7 +66,7 @@ extern int domainoverride; * (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) +void dfs_reset_alldelaylines(struct ath_dfs *dfs, int seg_id) { struct dfs_filtertype *ft = NULL; struct dfs_filter *rf; @@ -79,7 +79,11 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) "%s[%d]: sc_dfs is NULL", __func__, __LINE__); return; } - pl = dfs->pulses; + + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; + else + pl = dfs->pulses; if (pl == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -87,13 +91,24 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) return; } - if (dfs->dfs_b5radars == NULL) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s[%d]: pl==NULL, b5radars=%p", __func__, __LINE__, - dfs->dfs_b5radars); - return; + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + if (((seg_id == 0) ? + dfs->dfs_b5radars : dfs->dfs_b5radars_ext_seg) == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: pl==NULL, b5radars=%p\n", + __func__, + (seg_id == 0) ? dfs->dfs_b5radars : + dfs->dfs_b5radars_ext_seg); + return; + } + } else { + if (dfs->dfs_b5radars == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_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; @@ -104,7 +119,13 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) if (NULL != ft) { for (j = 0; j < ft->ft_numfilters; j++) { rf = &(ft->ft_filters[j]); - dl = &(rf->rf_dl); + if (dfs->ic->dfs_hw_bd_id != + DFS_HWBD_QCA6174) + dl = (seg_id == 0) ? + &(rf->rf_dl) : + &(rf->rf_dl_ext_seg); + else + dl = &(rf->rf_dl); if (dl != NULL) { OS_MEMZERO(dl, sizeof(struct @@ -118,12 +139,34 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) } } 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; + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + if (seg_id == DFS_80P80_SEG0) { + 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; + } else { + OS_MEMZERO( + &(dfs->dfs_b5radars_ext_seg[i].br_elems[0]), + sizeof(struct dfs_bin5elem)* + DFS_MAX_B5_SIZE); + dfs->dfs_b5radars_ext_seg[i].br_firstelem = 0; + dfs->dfs_b5radars_ext_seg[i].br_numelems = 0; + dfs->dfs_b5radars_ext_seg[i].br_lastelem = + (0xFFFFFFFF)&DFS_MAX_B5_MASK; + } + + } else { + 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; + } } } @@ -137,16 +180,6 @@ void dfs_reset_delayline(struct dfs_delayline *dl) 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; @@ -183,6 +216,8 @@ int dfs_init_radar_filters(struct ieee80211com *ic, struct dfs_bin5pulse *b5pulses = NULL; int32_t min_rssithresh = DFS_MAX_RSSI_VALUE; uint32_t max_pulsedur = 0; + uint32_t b5_rssithresh; + uint32_t b5_maxdur; if (dfs == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -299,6 +334,10 @@ int dfs_init_radar_filters(struct ieee80211com *ic, } rf = &(ft->ft_filters[ft->ft_numfilters++]); dfs_reset_delayline(&rf->rf_dl); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_delayline(&rf->rf_dl_ext_seg); + numpulses = dfs_radars[p].rp_numpulses; rf->rf_numpulses = numpulses; @@ -359,9 +398,24 @@ int dfs_init_radar_filters(struct ieee80211com *ic, __func__); goto bad4; } + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->dfs_b5radars_ext_seg = + (struct dfs_bin5radars *)os_malloc(NULL, numb5radars * + sizeof(struct dfs_bin5radars), + GFP_KERNEL); + if (dfs->dfs_b5radars_ext_seg == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s:Fail allocate memory for ext bin5 radars", + __func__); + goto bad4; + } + } + for (n = 0; n < numb5radars; n++) { dfs->dfs_b5radars[n].br_pulse = b5pulses[n]; - dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; + dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= + DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER; if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh) min_rssithresh = @@ -369,7 +423,30 @@ int dfs_init_radar_filters(struct ieee80211com *ic, 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); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + for (n = 0; n < numb5radars; n++) { + dfs->dfs_b5radars_ext_seg[n].br_pulse = b5pulses[n]; + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_timewindow *= + DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER; + b5_rssithresh = + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_rssithresh; + if (b5_rssithresh < min_rssithresh) + min_rssithresh = b5_rssithresh; + + b5_maxdur = + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_maxdur; + if (b5_maxdur > max_pulsedur) + max_pulsedur = b5_maxdur; + + } + } + + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + dfs_reset_radarq(dfs); dfs->dfs_curchan_radindex = -1; dfs->dfs_extchan_radindex = -1; diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c index 89a6c0b471b4..aaf568636282 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.c +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -35,6 +35,16 @@ #include "dfs_phyerr.h" #include "dfs_phyerr_tlv.h" +/** + * enum RADAR_SUMMARY_VERSION - Radar summary report version + * @DFS_RADAR_SUMMARY_REPORT_VERSION_2: DFS-2 radar summary report + * @DFS_RADAR_SUMMARY_REPORT_VERSION_3: DFS-3 radar summary report + */ +typedef enum { +DFS_RADAR_SUMMARY_REPORT_VERSION_2 = 1, +DFS_RADAR_SUMMARY_REPORT_VERSION_3 = 2, +} RADAR_SUMMARY_VERSION; + /* * Parsed radar status */ @@ -48,6 +58,28 @@ struct rx_radar_status { int delta_diff; int sidx; int freq_offset; /* in KHz */ + int agc_total_gain; + int agc_mb_gain; + /*Parsed only for DFS-3*/ + int radar_subchan_mask; + RADAR_SUMMARY_VERSION rsu_version; + /* + * The parameters below are present only in + * DFS-3 radar summary report and need to be + * parsed only for DFS-3. + */ + /* DFS-3 Only */ + int pulse_height; + /* DFS-3 Only */ + int triggering_agc_event; + /* DFS-3 Only */ + int pulse_rssi; + /* DFS-3 Only */ + int radar_fft_pri80_inband_power; + /* DFS-3 Only */ + int radar_fft_ext80_inband_power; + /* DFS-3 Only */ + int radar_80p80_segid; }; struct rx_search_fft_report { @@ -106,9 +138,22 @@ radar_summary_print(struct ath_dfs *dfs, struct rx_radar_status *rsu, bool enable_log) { + int is_chip_oversampling; + if (!enable_log) return; + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "\n ############ Radar Summary ############\n"); @@ -152,7 +197,7 @@ radar_summary_print(struct ath_dfs *dfs, "%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)); + is_chip_oversampling); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "\n ###################################\n"); @@ -168,50 +213,165 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_radar_status *rsu) { uint32_t rs[2]; + uint32_t dfs3_rs[5]; int freq_centre, freq; + int is_chip_oversampling; - /* 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)); + /* + * Drop out if we have < 2 DWORDs available for DFS-2 + * and drop out if we have < 5 DWORDS available for DFS-3 + */ + if ((dfs->ic->dfs_hw_bd_id == DFS_HWBD_QCA6174) && + (len < sizeof(rs))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: DFS-2 radar summary len = (%zu) wrong, expected = (%zu)", + __func__, len, sizeof(rs)); + } else if ((dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) && + (len < sizeof(dfs3_rs))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: DFS-3 radar summary len = (%zu) wrong, expected = (%zu)", + __func__, len, sizeof(dfs3_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. + * If the length of TLV is equal to + * DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH + * then it means the radar summary report + * has 5 DWORDS and we need to parse the + * report accordingly. + * Else if the length is equal to + * DFS2_RADAR_PULSE_SUMMARY_TLV_LENGTH then + * it the radar summary report will have only + * two DWORDS so we parse for only two DWORDS. */ - OS_MEMCPY(rs, buf, sizeof(rs)); + if (len == DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH) { + /* + * 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(dfs3_rs, buf, sizeof(dfs3_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)); + /* + * Oversampling is only needed to be + * turned on for older chips that support + * DFS-2. It needs to be turned off for chips + * that support DFS-3. + */ + is_chip_oversampling = 0; - /* 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); + /* + * populate the version of the radar summary report + * based on the TLV length to differentiate between + * DFS-2 and DFS-3 radar summary report. + */ + rsu->rsu_version = DFS_RADAR_SUMMARY_REPORT_VERSION_3; + + /* Populate the fields from the summary report */ + rsu->tsf_offset = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_TSF_OFFSET); + rsu->pulse_duration = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_DUR); + rsu->is_chirp = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_IS_CHIRP); + rsu->sidx = sign_extend_32(MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_SIDX), 10); + rsu->freq_offset = calc_freq_offset(rsu->sidx, + is_chip_oversampling); + /* These are only relevant if the pulse is a chirp */ + rsu->delta_peak = sign_extend_32( + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_PEAK), + 6); + rsu->delta_diff = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_DIFF); + /* For false detection Debug */ + rsu->agc_total_gain = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_AGC_TOTAL_GAIN); + rsu->agc_mb_gain = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_AGC_MB_GAIN); + /* + * radar_subchan_mask will be used in the future to identify the + * sub channel that encoutered radar pulses and block those + * channels in NOL accordingly. + */ + rsu->radar_subchan_mask = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_SUBCHAN_MASK); + + rsu->pulse_height = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_3], + RADAR_REPORT_PULSE_HEIGHT); + rsu->triggering_agc_event = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_4], + RADAR_REPORT_TRIGGERING_AGC_EVENT); + rsu->pulse_rssi = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_4], + RADAR_REPORT_PULSE_RSSI); + rsu->radar_fft_pri80_inband_power = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_FFT_PRI80_INBAND_POWER); + rsu->radar_fft_ext80_inband_power = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_FFT_EXT80_INBAND_POWER); + rsu->radar_80p80_segid = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_80P80_SEGID); + } else { + /* + * 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); + */ + + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); + /* + * populate the version of the radar summary report + * based on the TLV length to differentiate between + * DFS-2 and DFS-3 radar summary report. + */ + rsu->rsu_version = DFS_RADAR_SUMMARY_REPORT_VERSION_2; + + /* 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, is_chip_oversampling); + + /* 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); + + /* For false detection Debug */ + rsu->agc_total_gain = + MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_AGC_TOTAL_GAIN); + rsu->agc_mb_gain = + MS(rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_AGC_MB_GAIN); + + } /* WAR for FCC Type 4 */ /* @@ -441,19 +601,21 @@ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) cdf_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! + * calculate the channel center frequency for + * 160MHz and 80p80 MHz including the legacy + * channel widths. */ - if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { + if (IEEE80211_IS_CHAN_11AC_VHT160(dfs->ic->ic_curchan)) { + chan_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(dfs->ic->ic_curchan)) { + if (rs->radar_80p80_segid == DFS_80P80_SEG0) + chan_centre = + dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + else + chan_centre = + dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg2; + } else 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 */ @@ -505,6 +667,18 @@ tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, { int chan_width; int chan_centre; + int is_chip_oversampling; + + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); /* Fetch the channel centre frequency in MHz */ chan_centre = tlv_calc_freq_info(dfs, rs); @@ -517,7 +691,7 @@ tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, * XXX this needs to take into account the core clock speed * XXX for half/quarter rate mode. */ - if (PERE_IS_OVERSAMPLING(dfs)) + if (is_chip_oversampling) chan_width = (44000 * 2 / 128); else chan_width = (40000 * 2 / 128); @@ -559,13 +733,25 @@ tlv_calc_event_freq_chirp(struct ath_dfs *dfs, struct rx_radar_status *rs, int32_t total_bw; int32_t chan_centre; int32_t freq_1, freq_2; + int is_chip_oversampling; + + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); /* * KHz isn't enough resolution here! * So treat it as deci-hertz (10Hz) and convert back to KHz * later. */ - if (PERE_IS_OVERSAMPLING(dfs)) + if (is_chip_oversampling) bin_resolution = (44000 * 100) / 128; else bin_resolution = (40000 * 100) / 128; @@ -691,6 +877,13 @@ dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, uint16_t datalen, e->is_ext = 0; e->is_dc = 0; e->is_early = 0; + + /* + * Copy the segment ID from the radar summary report + * only when radar summary report version is DFS-3. + */ + if (rs.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) + e->radar_80p80_segid = rs.radar_80p80_segid; /* * XXX TODO: add a "chirp detection enabled" capability or config * bit somewhere, in case for some reason the hardware chirp diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.h b/core/sap/dfs/src/dfs_phyerr_tlv.h index d65375267cfd..61da81c3ad09 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.h +++ b/core/sap/dfs/src/dfs_phyerr_tlv.h @@ -66,6 +66,13 @@ #define TAG_ID_SEARCH_FFT_REPORT 0xFB #define TAG_ID_RADAR_PULSE_SUMMARY 0xF8 + +/* DFS-2 Radar pulse summary Length */ +#define DFS2_RADAR_PULSE_SUMMARY_TLV_LENGTH 8 + +/* DFS-3 Radar pulse summary length */ +#define DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH 20 + /* * Radar pulse summary * @@ -110,6 +117,37 @@ #define RADAR_REPORT_PULSE_DUR 0x000000FF #define RADAR_REPORT_PULSE_DUR_S 0 +/* + * These are the new TLV's in the DFS-3 + * radar summary report. Three new DWORDS + * have been added to radar summary report + * as part of DFS-3 as defined below. + */ + +#define RADAR_REPORT_PULSE_REG_3 0x02 + +#define RADAR_REPORT_PULSE_HEIGHT 0x000003FF +#define RADAR_REPORT_PULSE_HEIGHT_S 0 + +#define RADAR_REPORT_PULSE_REG_4 0x03 + +#define RADAR_REPORT_TRIGGERING_AGC_EVENT 0xC0000000 +#define RADAR_REPORT_TRIGGERING_AGC_EVENT_S 30 + +#define RADAR_REPORT_PULSE_RSSI 0X3FFC0000 +#define RADAR_REPORT_PULSE_RSSI_S 18 + +#define RADAR_REPORT_PULSE_REG_5 0x04 + +#define RADAR_REPORT_FFT_PRI80_INBAND_POWER 0x1FFF8000 +#define RADAR_REPORT_FFT_PRI80_INBAND_POWER_S 15 + +#define RADAR_REPORT_FFT_EXT80_INBAND_POWER 0x00007FFE +#define RADAR_REPORT_FFT_EXT80_INBAND_POWER_S 1 + +#define RADAR_REPORT_80P80_SEGID 0x00000001 +#define RADAR_REPORT_80P80_SEGID_S 0 + #define SEARCH_FFT_REPORT_REG_1 0x00 #define SEARCH_FFT_REPORT_TOTAL_GAIN_DB 0xFF800000 diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 38a49deb3766..0a806b4db8c4 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -737,6 +737,15 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, event->re_chanindex = dfs->dfs_curchan_radindex; event->re_flags = 0; event->sidx = e.sidx; + /* + * Copy the segment ID of the phyerror + * from the radar summary report only + * if SAP is operating in 80p80 mode + * and both primary and extension segments + * are DFS. + */ + if (chan->ic_80p80_both_dfs) + event->radar_80p80_segid = e.radar_80p80_segid; /* * Handle chirp flags. diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index c5a586c10341..3c05d322707a 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -127,27 +127,31 @@ int dfs_process_radarevent(struct ath_dfs *dfs, uint64_t deltafull_ts = 0, this_ts, deltaT; struct dfs_ieee80211_channel *thischan; struct dfs_pulseline *pl; - static uint32_t test_ts = 0; static uint32_t diff_ts = 0; int ext_chan_event_flag = 0; #if 0 int pri_multiplier = 2; #endif int i; + int seg_id = DFS_80P80_SEG0; + struct dfs_delayline *dl; if (dfs == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s[%d]: dfs is NULL", __func__, __LINE__); return 0; } - pl = dfs->pulses; cdf_spin_lock_bh(&dfs->ic->chan_lock); if (!(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { cdf_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); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + return 0; } @@ -218,6 +222,12 @@ int dfs_process_radarevent(struct ath_dfs *dfs, } events_processed++; re = *event; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + seg_id = re.radar_80p80_segid; + else + seg_id = DFS_80P80_SEG0; + + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; OS_MEMZERO(event, sizeof(struct dfs_event)); ATH_DFSEVENTQ_LOCK(dfs); @@ -375,8 +385,13 @@ int dfs_process_radarevent(struct ath_dfs *dfs, 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 = (uint32_t) this_ts - test_ts; - test_ts = (uint32_t) this_ts; + if (seg_id == 0) { + diff_ts = (uint32_t) this_ts - dfs->test_ts; + dfs->test_ts = (uint32_t) this_ts; + } else { + diff_ts = (u_int32_t)this_ts - dfs->test_ts_ext_seg; + dfs->test_ts_ext_seg = (u_int32_t)this_ts; + } DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu", (uint32_t) this_ts, re.re_dur, re.re_rssi, diff_ts, @@ -402,7 +417,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, * harsh environments, but helps with false detects. */ if (diff_ts < 100) { - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, seg_id); dfs_reset_radarq(dfs); } found = 0; @@ -512,23 +527,36 @@ int dfs_process_radarevent(struct ath_dfs *dfs, p++) { struct dfs_bin5radars *br; - br = &(dfs->dfs_b5radars[p]); + br = (seg_id == 0) ? + &(dfs->dfs_b5radars[p]) : + &(dfs->dfs_b5radars_ext_seg[p]); + if (dfs_bin5_check_pulse(dfs, &re, br)) { - /* This is a valid Bin5 pulse, check if it belongs to a burst */ + /* + * 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; + dfs_retain_bin5_burst_pattern(dfs, + diff_ts, re.re_dur, seg_id); + /* + * Remember our computed duration for + * the next pulse in the burst + * (if needed) + */ + if (seg_id == 0) + dfs->dfs_rinfo. + dfs_last_bin5_dur = + re.re_dur; + else + dfs->dfs_rinfo. + dfs_last_bin5_dur_ext_seg = + re.re_dur; if (dfs_bin5_addpulse (dfs, br, &re, this_ts)) { - found |= dfs_bin5_check(dfs); + found |= dfs_bin5_check(dfs, + seg_id); } } else { DFS_DPRINTK(dfs, @@ -607,19 +635,18 @@ int dfs_process_radarevent(struct ath_dfs *dfs, for (p = 0, found = 0; (p < ft->ft_numfilters) && (!found); p++) { rf = &(ft->ft_filters[p]); + dl = (seg_id == 0) ? &rf->rf_dl : + &rf->rf_dl_ext_seg; 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; + (this_ts < dl->dl_last_ts) ? + (int64_t) + ((DFS_TSF_WRAP - + dl->dl_last_ts) + + this_ts + 1) : + this_ts - dl->dl_last_ts; if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { @@ -663,8 +690,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, long)deltaT, rf->rf_minpri); /* But update the last time stamp */ - rf->rf_dl.dl_last_ts = - this_ts; + dl->dl_last_ts = + this_ts; continue; } } else { @@ -702,13 +729,13 @@ int dfs_process_radarevent(struct ath_dfs *dfs, long)deltaT, rf->rf_minpri); /* But update the last time stamp */ - rf->rf_dl.dl_last_ts = - this_ts; + dl->dl_last_ts = + this_ts; continue; } } dfs_add_pulse(dfs, rf, &re, deltaT, - this_ts); + this_ts, seg_id); /* If this is an extension channel event, flag it for false alarm reduction */ if (re.re_chanindex == @@ -717,25 +744,23 @@ int dfs_process_radarevent(struct ath_dfs *dfs, } if (rf->rf_patterntype == 2) { found = - dfs_staggered_check(dfs, rf, - (uint32_t) - deltaT, - re. - re_dur); + dfs_staggered_check(dfs, + rf, + (uint32_t)deltaT, + re.re_dur, seg_id); } else { found = dfs_bin_check(dfs, rf, - (uint32_t) - deltaT, - re.re_dur, - ext_chan_event_flag); + (uint32_t)deltaT, + re.re_dur, + ext_chan_event_flag, + seg_id); } if (dfs-> dfs_debug_mask & ATH_DEBUG_DFS2) { - dfs_print_delayline(dfs, - &rf->rf_dl); + dfs_print_delayline(dfs, dl); } - rf->rf_dl.dl_last_ts = this_ts; + dl->dl_last_ts = this_ts; } } ft->ft_last_ts = this_ts; @@ -746,9 +771,10 @@ int dfs_process_radarevent(struct ath_dfs *dfs, ft->ft_mindur, rf != NULL ? rf->rf_pulseid : -1); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, - "%s[%d]:### Found on channel minDur = %d,filterId = %d ###", + "%s[%d]:### Found on channel minDur = %d,filterId = %d seg_id = %d ###", __func__,__LINE__,ft->ft_mindur, - rf != NULL ? rf->rf_pulseid : -1); + rf != NULL ? rf->rf_pulseid : -1, + seg_id); } tabledepth++; } @@ -761,10 +787,21 @@ dfsfound: /* Collect stats */ dfs->ath_dfs_stats.num_radar_detects++; thischan = &rs->rs_chan; + + /* + * Since we support 80p80 mode, indicate the + * segment on which the radar has been detected. + * only if both segments are dfs in 80p80 mode + * and the radar is found on ext the segment + * ic_radar_found_segid is to 1, in all other + * cases it is set to 0. + */ + dfs->ic->ic_curchan->ic_radar_found_segid = seg_id; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s[%d]: ### RADAR FOUND ON CHANNEL %d (%d MHz) ###", - __func__, __LINE__, thischan->ic_ieee, - thischan->ic_freq); + "%s[%d]:### RADAR FOUND ON CHANNEL %d (%d MHz),seg_id=%d ###", + __func__, __LINE__, thischan->ic_ieee, + thischan->ic_freq, seg_id); DFS_PRINTK("Radar found on channel %d (%d MHz)", thischan->ic_ieee, thischan->ic_freq); @@ -775,7 +812,22 @@ dfsfound: ath_hal_setrxfilter(ah, rfilt); #endif dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); + + /* + * For now reset both segments + * until we have changes for us + * to do sub-channel marking which + * enables SAP to continue to use the 80 + * segment where radar was not detected + * and as a result CAC can be avoided on + * that segment. Currently we do not support + * sub-channel marking. + */ + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + /* XXX Should we really enable again? Maybe not... */ /* No reason to re-enable so far - Ajay*/ #if 0 diff --git a/core/sap/dfs/src/dfs_staggered.c b/core/sap/dfs/src/dfs_staggered.c index 71c04b573b0a..cf00e741d1ad 100644 --- a/core/sap/dfs/src/dfs_staggered.c +++ b/core/sap/dfs/src/dfs_staggered.c @@ -96,7 +96,7 @@ static int is_unique_pri(uint32_t highestpri, uint32_t midpri, } int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t width) + uint32_t deltaT, uint32_t width, int seg_id) { uint32_t refpri, refdur, searchpri = 0, deltapri; /* , averagerefpri; */ uint32_t n, i, primargin, durmargin; @@ -112,7 +112,11 @@ int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t midscore = 0, midscoreindex = 0, midpri = 0; uint32_t highestscore = 0, highestscoreindex = 0, highestpri = 0; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + 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", diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 27fa5b4fe31a..39f031740270 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -91,6 +91,12 @@ #define IEEE80211_IS_CHAN_11AC_VHT80(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == \ IEEE80211_CHAN_11AC_VHT80) +#define IEEE80211_IS_CHAN_11AC_VHT80P80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT80P80) == \ + IEEE80211_CHAN_VHT80P80) +#define IEEE80211_IS_CHAN_11AC_VHT160(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT160) == \ + IEEE80211_CHAN_VHT160) #define CHANNEL_108G \ (IEEE80211_CHAN_2GHZ|IEEE80211_CHAN_OFDM|IEEE80211_CHAN_TURBO) @@ -120,6 +126,8 @@ * @ic_vhtop_ch_freq_seg1: channel center frequency * @ic_vhtop_ch_freq_seg2: Channel Center frequency applicable * @ic_pri_freq_center_freq_mhz_separation: separation b/w pri and center freq + * @ic_80p80_both_dfs: Flag indicating if both 80p80 segments are dfs + * @ic_radar_found_segid: Indicates seg ID on which radar is found in 80p80 mode */ struct dfs_ieee80211_channel { uint32_t ic_freq; @@ -137,6 +145,7 @@ struct dfs_ieee80211_channel { uint32_t ic_vhtop_ch_freq_seg2; int ic_pri_freq_center_freq_mhz_separation; bool ic_80p80_both_dfs; + int ic_radar_found_segid; }; /** -- cgit v1.2.3 From 9947e0ad5d00d6e53c56bf18f4aa5f4475bbd98c Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 28 Dec 2015 23:07:54 +0530 Subject: qcacld-3.0: Fix IPA-uc callback in NON-SMP system IPA callbacks need to be processed in tasklet context in NON-SMP configuration as rx thread is not used in NON-SMP context. Hence Process IPA uc response in tasklet context for NON-SMP configuration. CRs-Fixed: 960302 Change-Id: I98d69dbdc1083f43035fe264bbee668e5efd5eee --- core/dp/txrx/ol_txrx.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 2a75a527609d..f1aa269bccee 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2777,16 +2777,20 @@ void ol_txrx_ipa_uc_fw_op_event_handler(void *context, if (cdf_unlikely(!pdev)) { CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, "%s: Invalid context", __func__); + cdf_mem_free(rxpkt); return; } - if (pdev->ipa_uc_op_cb) + if (pdev->ipa_uc_op_cb) { pdev->ipa_uc_op_cb(rxpkt, pdev->osif_dev); - else + } else { CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, "%s: ipa_uc_op_cb NULL", __func__); + cdf_mem_free(rxpkt); + } } +#ifdef QCA_CONFIG_SMP /** * ol_txrx_ipa_uc_op_response() - Handle OP command response from firmware * @pdev: handle to the HTT instance @@ -2815,6 +2819,20 @@ void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, uint8_t *op_msg) pkt->staId = 0; cds_indicate_rxpkt(sched_ctx, pkt); } +#else +void ol_txrx_ipa_uc_op_response(ol_txrx_pdev_handle pdev, + uint8_t *op_msg) +{ + if (pdev->ipa_uc_op_cb) { + pdev->ipa_uc_op_cb(op_msg, pdev->osif_dev); + } else { + CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR, + "%s: IPA callback function is not registered", __func__); + cdf_mem_free(op_msg); + return; + } +} +#endif /** * ol_txrx_ipa_uc_register_op_cb() - Register OP handler function -- cgit v1.2.3 From f051ee490b0419ae81884b31041d4fe48423bf75 Mon Sep 17 00:00:00 2001 From: Dhanashri Atre Date: Tue, 15 Dec 2015 18:07:10 -0800 Subject: qcacld-3.0: Fix fw statistics parsing on the host For iHelium, the flag AR900B is defined in the firmware however it is not defined on the host. This is causing a mismatch in the statistics structure between the host and the firmware. Temporarily enable this flag on the host. Eventually, this flag will be replaced by a iHelium specific flag on both the host and the firmware CRs-Fixed: 964909 Change-Id: I1a13db22448a099ea51602108eb5626e878e2c2e --- Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/Kbuild b/Kbuild index 8b88845e2b44..3bfa2604faf8 100644 --- a/Kbuild +++ b/Kbuild @@ -1292,6 +1292,7 @@ CONFIG_FEATURE_TSO_DEBUG := y ifeq ($(CONFIG_HELIUMPLUS),y) CDEFINES += -DHELIUMPLUS_PADDR64 CDEFINES += -DHELIUMPLUS +CDEFINES += -DAR900B ifeq ($(CONFIG_64BIT_PADDR),y) CDEFINES += -DHTT_PADDR64 endif -- cgit v1.2.3 From 99722fb229c2f469ccb81f11c24df52675c73840 Mon Sep 17 00:00:00 2001 From: "Gupta, Kapil" Date: Wed, 13 Jan 2016 19:34:02 +0530 Subject: qcacld-3.0: Remove RRM ie in Assoc Req based on AP capability RRM ie should not be present in association req if AP doesn't support 11k. As a part of fix add the check to append RMM ie only if AP support 11k. Change-Id: I4e521dbdbdd5b083360405f26913278788c86555 CRs-Fixed: 961737 --- core/mac/src/pe/lim/lim_send_management_frames.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index a4ae823af135..13f117e5680d 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1725,7 +1725,8 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, pe_session); #if defined WLAN_FEATURE_VOWIFI - if (mac_ctx->rrm.rrmPEContext.rrmEnable) + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap, pe_session); #endif @@ -2103,7 +2104,8 @@ lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, pe_session); #if defined WLAN_FEATURE_VOWIFI - if (mac_ctx->rrm.rrmPEContext.rrmEnable) + if (mac_ctx->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) populate_dot11f_rrm_ie(mac_ctx, &frm.RRMEnabledCap, pe_session); #endif @@ -2574,7 +2576,8 @@ lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, &frm.ExtSuppRates, psessionEntry); #if defined WLAN_FEATURE_VOWIFI - if (pMac->rrm.rrmPEContext.rrmEnable) + if (pMac->rrm.rrmPEContext.rrmEnable && + SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) populate_dot11f_rrm_ie(pMac, &frm.RRMEnabledCap, psessionEntry); #endif /* The join request *should* contain zero or one of the WPA and RSN */ -- cgit v1.2.3 From c49931aaf505ca406e832be0954b4fc9e62c4ec2 Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Thu, 29 Oct 2015 15:11:06 -0700 Subject: qcacld-3.0: Remove #ifdef FEATURE_WLAN_LFR from HDD The condition #ifdef WLAN_FEATURE_LFR is used to include some of the roaming code. It has been defined for all the recent driver builds. Roaming code underneath is permanent part of the driver. Remove #ifdef FEATURE_WLAN_LFR compiler flag from HDD so that the code will always be compiled in. CRs-Fixed: 936683 Change-Id: If5010bc1470a35b2f1516a5c5d10461352fd87fc --- core/hdd/inc/wlan_hdd_cfg.h | 13 ---- core/hdd/inc/wlan_hdd_main.h | 4 -- core/hdd/src/wlan_hdd_assoc.c | 134 ++++++++++----------------------------- core/hdd/src/wlan_hdd_cfg.c | 22 ------- core/hdd/src/wlan_hdd_cfg80211.c | 15 +---- core/hdd/src/wlan_hdd_cfg80211.h | 4 +- core/hdd/src/wlan_hdd_ioctl.c | 19 ------ core/hdd/src/wlan_hdd_main.c | 7 -- 8 files changed, 37 insertions(+), 181 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index c626a29dcb02..10b5077bbe84 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -245,7 +245,6 @@ typedef enum { #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) @@ -259,7 +258,6 @@ typedef enum { #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 @@ -633,7 +631,6 @@ typedef enum { #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) @@ -643,9 +640,7 @@ typedef enum { #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. */ @@ -685,8 +680,6 @@ typedef enum { #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) @@ -3027,19 +3020,15 @@ struct hdd_config { uint32_t InfraUapsdBeSuspIntv; uint32_t InfraUapsdBkSrvIntv; uint32_t InfraUapsdBkSuspIntv; -#ifdef FEATURE_WLAN_LFR bool isFastRoamIniFeatureEnabled; bool MAWCEnabled; -#endif #ifdef FEATURE_WLAN_ESE uint32_t InfraInactivityInterval; bool isEseIniFeatureEnabled; #endif -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) bool isFastTransitionEnabled; uint8_t RoamRssiDiff; bool isWESModeEnabled; -#endif #ifdef FEATURE_WLAN_OKC bool isOkcIniFeatureEnabled; #endif @@ -3148,12 +3137,10 @@ struct hdd_config { int32_t linkSpeedRssiHigh; int32_t linkSpeedRssiMid; int32_t linkSpeedRssiLow; -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) bool nRoamPrefer5GHz; bool nRoamIntraBand; uint8_t nProbes; uint16_t nRoamScanHomeAwayTime; -#endif uint8_t enableMCC; uint8_t allowMCCGODiffBI; bool isP2pDeviceAddrAdministrated; diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index d24ab8553121..1e0e388c8087 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -646,9 +646,7 @@ struct hdd_station_ctx { 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; @@ -1483,10 +1481,8 @@ static inline bool hdd_is_memdump_supported(void) void hdd_update_macaddr(struct hdd_config *config, struct cdf_mac_addr hw_macaddr); -#if defined(FEATURE_WLAN_LFR) void wlan_hdd_disable_roaming(hdd_adapter_t *pAdapter); void wlan_hdd_enable_roaming(hdd_adapter_t *pAdapter); -#endif CDF_STATUS hdd_post_cds_enable_config(hdd_context_t *pHddCtx); diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index bb81a878d4b0..f21d96d2690e 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -828,9 +828,7 @@ static void hdd_send_association_event(struct net_device *dev, cds_decr_session_set_pcl( pAdapter->device_mode, pAdapter->sessionId); -#if defined(FEATURE_WLAN_LFR) wlan_hdd_enable_roaming(pAdapter); -#endif #ifdef FEATURE_WLAN_AUTO_SHUTDOWN wlan_hdd_auto_shutdown_enable(pHddCtx, true); @@ -1715,10 +1713,7 @@ static CDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter, CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE; uint8_t reqRsnIe[DOT11F_IE_RSN_MAX_LEN]; uint32_t 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 bool hddDisconInProgress = false; unsigned long rc; @@ -1781,49 +1776,38 @@ defined(WLAN_FEATURE_VOWIFI_11R) * 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; + /* + * 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 */ - wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_CARRIER_ON, - WLAN_CONTROL_PATH); + /* Switch on the Carrier to activate the device */ + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_CARRIER_ON, + WLAN_CONTROL_PATH); - /* - * 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(LOGW, FL("Warning:ASSOC_LINKUP_TIMEOUT")); + /* + * 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) + hdd_warn("Warning:ASSOC_LINKUP_TIMEOUT"); - /* - * 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 + /* + * Disable Linkup Event Servicing - no more service + * required from the net device notifier call. + */ + pAdapter->isLinkUpSvcNeeded = false; + } else { + pHddStaCtx->ft_carrier_on = false; + ft_carrier_on = true; + } if ((WLAN_MAX_STA_COUNT + 3) > pRoamInfo->staId) pHddCtx->sta_to_adapter[pRoamInfo->staId] = pAdapter; else @@ -2059,17 +2043,13 @@ defined(FEATURE_WLAN_LFR) &rspRsnLength, rspRsnIe); if (!hddDisconInProgress) { -#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) if (ft_carrier_on) hdd_send_re_assoc_event(dev, pAdapter, pRoamInfo, reqRsnIe, reqRsnLength); - else -#endif /* FEATURE_WLAN_ESE */ - - { + else { hddLog(LOG1, FL("sending connect indication to nl80211:for bssid " MAC_ADDRESS_STR @@ -3883,8 +3863,6 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, 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 @@ -3925,72 +3903,32 @@ defined(FEATURE_WLAN_LFR) * doing disassoc at this time. This saves 30-60 msec * after reassoc. */ - { hddLog(LOG1, FL("Disabling queues")); - wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, - WLAN_CONTROL_PATH); - status = - hdd_roam_deregister_sta(pAdapter, - pHddStaCtx->conn_info. - staId[0]); - if (!CDF_IS_STATUS_SUCCESS(status)) { - hddLog(LOGW, - FL - ("hdd_roam_deregister_sta() failed to for staID %d. Status=%d [0x%x]"), - pHddStaCtx->conn_info.staId[0], - status, status); + wlan_hdd_netif_queue_control(pAdapter, + WLAN_NETIF_TX_DISABLE, + WLAN_CONTROL_PATH); + status = hdd_roam_deregister_sta(pAdapter, + pHddStaCtx->conn_info.staId[0]); + if (!CDF_IS_STATUS_SUCCESS(status)) cdf_ret_status = CDF_STATUS_E_FAILURE; - } - } pHddStaCtx->ft_carrier_on = true; pHddStaCtx->hdd_ReassocScenario = 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 */ - { - 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")); wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, WLAN_CONTROL_PATH); -#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \ -defined(FEATURE_WLAN_LFR) if (pHddStaCtx->ft_carrier_on == false) { -#endif wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_CARRIER_OFF, WLAN_CONTROL_PATH); -#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_roam_deregister_sta(pAdapter, - pHddStaCtx->conn_info. - staId[0]); - if (!CDF_IS_STATUS_SUCCESS(status)) { - hddLog(LOGW, - FL - ("hdd_roam_deregister_sta() failed to for staID %d. Status=%d [0x%x]"), - pHddStaCtx->conn_info.staId[0], - status, status); - cdf_ret_status = CDF_STATUS_E_FAILURE; } -#endif - } break; case eCSR_ROAM_LOSTLINK: if (roamResult == eCSR_ROAM_RESULT_LOSTLINK) { @@ -4117,7 +4055,6 @@ defined(FEATURE_WLAN_LFR)) hdd_send_ft_event(pAdapter); break; #endif -#ifdef FEATURE_WLAN_LFR case eCSR_ROAM_PMK_NOTIFY: if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType || eCSR_AUTH_TYPE_RSN_8021X_SHA256 == @@ -4128,7 +4065,6 @@ defined(FEATURE_WLAN_LFR)) pAdapter, pRoamInfo, 1, false); } break; -#endif #ifdef FEATURE_WLAN_LFR_METRICS case eCSR_ROAM_PREAUTH_INIT_NOTIFY: diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index b8b2adf98e26..31810db07d27 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -45,7 +45,6 @@ #include #include -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) static void cb_notify_set_roam_prefer5_g_hz(hdd_context_t *pHddCtx, unsigned long notifyId) { @@ -95,7 +94,6 @@ cb_notify_set_roam_scan_home_away_time(hdd_context_t *pHddCtx, unsigned long not pHddCtx->config->nRoamScanHomeAwayTime, true); } -#endif #ifdef FEATURE_WLAN_OKC static void @@ -106,7 +104,6 @@ cb_notify_set_okc_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyId } #endif -#ifdef FEATURE_WLAN_LFR static void notify_is_fast_roam_ini_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyId) @@ -126,7 +123,6 @@ notify_is_mawc_ini_feature_enabled(hdd_context_t *pHddCtx, unsigned long notifyI sme_update_is_mawc_ini_feature_enabled(pHddCtx->hHal, pHddCtx->config->MAWCEnabled); } -#endif #ifdef FEATURE_WLAN_ESE static void @@ -1018,7 +1014,6 @@ REG_TABLE_ENTRY g_registry_table[] = { cb_notify_set_ese_feature_enabled, 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, struct hdd_config, isFastRoamIniFeatureEnabled, @@ -1040,9 +1035,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_LFR_MAWC_FEATURE_ENABLED_MAX, notify_is_mawc_ini_feature_enabled, 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, @@ -1073,7 +1065,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ENABLE_WES_MODE_NAME_MIN, CFG_ENABLE_WES_MODE_NAME_MAX, cb_notify_set_wes_mode, 0), -#endif #ifdef FEATURE_WLAN_OKC REG_DYNAMIC_VARIABLE(CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, struct hdd_config, isOkcIniFeatureEnabled, @@ -1920,7 +1911,6 @@ REG_TABLE_ENTRY g_registry_table[] = { 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, struct hdd_config, nRoamPrefer5GHz, VAR_FLAGS_OPTIONAL | @@ -1957,8 +1947,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX, cb_notify_set_roam_scan_home_away_time, 0), -#endif - REG_VARIABLE(CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, WLAN_PARAM_Integer, struct hdd_config, isP2pDeviceAddrAdministrated, @@ -4646,22 +4634,18 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) "Name = [gTxPowerCap] Value = [%u] dBm ", pHddCtx->config->nTxPowerCap); #endif -#ifdef FEATURE_WLAN_LFR CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [FastRoamEnabled] Value = [%u] ", pHddCtx->config->isFastRoamIniFeatureEnabled); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [MAWCEnabled] Value = [%u] ", pHddCtx->config->MAWCEnabled); -#endif -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [RoamRssiDiff] Value = [%u] ", pHddCtx->config->RoamRssiDiff); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [isWESModeEnabled] Value = [%u] ", pHddCtx->config->isWESModeEnabled); -#endif #ifdef FEATURE_WLAN_OKC CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [OkcEnabled] Value = [%u] ", @@ -6520,14 +6504,12 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) 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; @@ -6539,11 +6521,9 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) 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; @@ -6551,12 +6531,10 @@ CDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) 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.isWESModeEnabled = pConfig->isWESModeEnabled; -#endif smeConfig->csrConfig.isRoamOffloadScanEnabled = pConfig->isRoamOffloadScanEnabled; smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 102c44790c9f..efed484d0e90 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5346,18 +5346,13 @@ int wlan_hdd_cfg80211_init(struct device *dev, 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 + if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled #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; @@ -7571,7 +7566,6 @@ int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, return 0; } -#ifdef FEATURE_WLAN_LFR /** * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate * @pAdapter: Pointer to adapter @@ -7609,7 +7603,6 @@ int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter, #endif /* FEATURE_WLAN_OKC */ return 0; } -#endif /* FEATURE_WLAN_LFR */ #ifdef FEATURE_WLAN_LFR_METRICS /** @@ -8862,9 +8855,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, return -ECONNREFUSED; } } -#if defined(FEATURE_WLAN_LFR) wlan_hdd_disable_roaming(pAdapter); -#endif /*Try disconnecting if already in connected state */ status = wlan_hdd_try_disconnect(pAdapter); @@ -10119,7 +10110,6 @@ static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, return ret; } -#ifdef FEATURE_WLAN_LFR /** * __wlan_hdd_cfg80211_set_pmksa() - set pmksa * @wiphy: Pointer to wiphy @@ -10347,7 +10337,6 @@ static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, return ret; } -#endif #if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) /** @@ -11291,11 +11280,9 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .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 diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index b306fd45e746..c830c06aa0ed 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2261,11 +2261,9 @@ enum qca_vendor_attr_txpower_scale_decr_db { 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 CDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter, diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index be6ea8f17071..a81b3d6676da 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -261,7 +261,6 @@ CDF_STATUS hdd_get_tsm_stats(hdd_adapter_t *adapter, } #endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) static void hdd_get_band_helper(hdd_context_t *hdd_ctx, int *pBand) { eCsrBand band = -1; @@ -521,9 +520,6 @@ static int hdd_parse_reassoc_command_v1_data(const uint8_t *pValue, return 0; } -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ - -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) /** * hdd_reassoc() - perform a userspace-directed reassoc * @adapter: Adapter upon which the command was received @@ -696,9 +692,6 @@ static int hdd_parse_reassoc(hdd_adapter_t *adapter, const char *command) return ret; } -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ - -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) /** * hdd_sendactionframe() - send a userspace-supplied action frame * @adapter: Adapter upon which the command was received @@ -974,9 +967,6 @@ hdd_parse_sendactionframe(hdd_adapter_t *adapter, const char *command) return ret; } -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */ - -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) /** * hdd_parse_channellist() - HDD Parse channel list * @pValue: Pointer to input channel list @@ -1272,7 +1262,6 @@ hdd_parse_set_roam_scan_channels(hdd_adapter_t *adapter, const char *command) return ret; } -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) /** @@ -6093,15 +6082,10 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = { {"GETROAMSCANPERIOD", drv_cmd_get_roam_scan_period}, {"SETROAMSCANREFRESHPERIOD", drv_cmd_set_roam_scan_refresh_period}, {"GETROAMSCANREFRESHPERIOD", drv_cmd_get_roam_scan_refresh_period}, -#ifdef FEATURE_WLAN_LFR {"SETROAMMODE", drv_cmd_set_roam_mode}, {"GETROAMMODE", drv_cmd_get_roam_mode}, -#endif -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) {"SETROAMDELTA", drv_cmd_set_roam_delta}, {"GETROAMDELTA", drv_cmd_get_roam_delta}, -#endif -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) {"GETBAND", drv_cmd_get_band}, {"SETROAMSCANCHANNELS", drv_cmd_set_roam_scan_channels}, {"GETROAMSCANCHANNELS", drv_cmd_get_roam_scan_channels}, @@ -6129,10 +6113,7 @@ static const hdd_drv_cmd_t hdd_drv_cmds[] = { {"GETOPPORTUNISTICRSSIDIFF", drv_cmd_get_opportunistic_rssi_diff}, {"SETROAMRESCANRSSIDIFF", drv_cmd_set_roam_rescan_rssi_diff}, {"GETROAMRESCANRSSIDIFF", drv_cmd_get_roam_rescan_rssi_diff}, -#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */ -#ifdef FEATURE_WLAN_LFR {"SETFASTROAM", drv_cmd_set_fast_roam}, -#endif #ifdef WLAN_FEATURE_VOWIFI_11R {"SETFASTTRANSITION", drv_cmd_set_fast_transition}, {"FASTREASSOC", drv_cmd_fast_reassoc}, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6e8f8bb2428a..53f052808af3 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -723,10 +723,6 @@ CDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter) return CDF_STATUS_SUCCESS; } -#if defined(WLAN_FEATURE_VOWIFI_11R) ||\ - defined(FEATURE_WLAN_ESE) ||\ - defined(FEATURE_WLAN_LFR) - #define INTF_MACADDR_MASK 0x7 /** @@ -1390,7 +1386,6 @@ bool hdd_dfs_indicate_radar(void *context, void *param) return true; } -#endif /** * hdd_is_valid_mac_address() - validate MAC address @@ -6032,7 +6027,6 @@ int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data, } #endif -#if defined(FEATURE_WLAN_LFR) /** * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one * @adapter: HDD adapter pointer @@ -6138,7 +6132,6 @@ void wlan_hdd_enable_roaming(hdd_adapter_t *adapter) } } } -#endif void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len) { -- cgit v1.2.3 From f6479c5709903b5959c6d19aefa3f640a81e9010 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 19 Jan 2016 14:12:00 +0530 Subject: qcacld-3.0: Move sta state to not connected after try disconnect qcacld-2.0 to qcacld-3.0 propagation If a connect is received with previous connect already in progress, sta connect state is moved from connecting to disconnecting and disconnect is initiated to stop the previous connect. If previous is present in sme/roam pending queue the disconnect will abort the previous connect by removing the cmd from pending queue. In this case the connect state is not moved back to not connected from disconecting. Thus the current connect command fails and all new connect command will fail as the connect state will always be in disconnecting state. To avoid this, move the connect state to not connected, once try disconnect is issued internally. Change-Id: Ia563f85df84cb9dbb3d3a82bc97127d39e7b1421 CRs-Fixed: 961559 --- core/hdd/src/wlan_hdd_cfg80211.c | 64 ++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index efed484d0e90..4f1c1be971c1 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8739,6 +8739,7 @@ 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); @@ -8752,36 +8753,48 @@ static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter) eConnectionState_Disconnecting); /* Issue disconnect to CSR */ INIT_COMPLETION(pAdapter->disconnect_comp_var); - if (CDF_STATUS_SUCCESS == - sme_roam_disconnect(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("Sme disconnect event timed out session Id %d staDebugState %d"), - pAdapter->sessionId, - pHddStaCtx->staDebugState); - return -EALREADY; - } + + status = sme_roam_disconnect(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 (CDF_STATUS_CMD_NOT_QUEUED == status) { + hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect"); + } else if (0 != status) { + hdd_err("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 && (CDF_STATUS_CMD_NOT_QUEUED != status)) { + hdd_err("Sme disconnect event timed out session Id %d staDebugState %d", + pAdapter->sessionId, pHddStaCtx->staDebugState); + result = -ETIMEDOUT; } } else if (eConnectionState_Disconnecting == - pHddStaCtx->conn_info.connState) { + pHddStaCtx->conn_info.connState) { rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies - (WLAN_WAIT_TIME_DISCONNECT)); + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); if (!rc) { - hddLog(LOGE, - FL("Disconnect event timed out session Id %d staDebugState %d"), + hdd_err("Disconnect event timed out session Id %d staDebugState %d", pAdapter->sessionId, pHddStaCtx->staDebugState); - return -EALREADY; + result = -ETIMEDOUT; } } - - return 0; +disconnected: + hdd_info("Set HDD connState to eConnectionState_NotConnected"); + hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected); + return result; } /** @@ -8952,8 +8965,7 @@ int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) * race conditions leading to SME and HDD out of sync. */ if (CDF_STATUS_CMD_NOT_QUEUED == status) { - hddLog(LOG1, FL("status = %d, already disconnected"), - (int)status); + hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect"); } else if (0 != status) { hddLog(LOGE, FL("csr_roam_disconnect failure, returned %d"), @@ -8966,7 +8978,7 @@ int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason) msecs_to_jiffies (WLAN_WAIT_TIME_DISCONNECT)); - if (!rc) { + if (!rc && (CDF_STATUS_CMD_NOT_QUEUED != status)) { hddLog(LOGE, FL("Failed to disconnect, timed out")); result = -ETIMEDOUT; -- cgit v1.2.3 From d7ff6aef93fe3e7f9865058a96f5867f3420f58a Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Fri, 22 Jan 2016 10:56:07 +0800 Subject: qcacld-3.0: Update channel width and center freq qcacld-2.0 to qcacld-3.0 propagation "cfg80211_chandef_create" doesn't support channel width "HT80". If create chandef by it, channel width set to HT40 when working on SAP VHT80 mode. Which cause a mismatch between supplicant and host driver. Update channel width and center freq for VHT80 mode Change-Id: I9c5734fca4bcc02436aea8684ca9d0b968eb1dee CRs-Fixed: 944618 --- core/hdd/src/wlan_hdd_hostapd.c | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 9ddd3fd6d48a..97a3142d0fc8 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -619,6 +619,77 @@ hdd_sap_get_phymode(hdd_adapter_t *hostapd_adapter) } #endif +/** + * hdd_update_chandef() - Function to update channel width and center freq + * @hostapd_adapter: hostapd adapter + * @chandef: cfg80211 chan def + * @cb_mode: chan offset + * + * This function will be called to update channel width and center freq + * + * Return: None + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) || defined(WITH_BACKPORTS) +static inline void +hdd_update_chandef(hdd_adapter_t *hostapd_adapter, + struct cfg80211_chan_def *chandef, + ePhyChanBondState cb_mode) +{ + uint16_t ch_width; + hdd_ap_ctx_t *phdd_ap_ctx; + uint8_t center_chan, chan; + + phdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter); + ch_width = phdd_ap_ctx->sapConfig.acs_cfg.ch_width; + + switch (ch_width) { + case eHT_CHANNEL_WIDTH_20MHZ: + case eHT_CHANNEL_WIDTH_40MHZ: + hdd_info("ch_width %d, won't update", ch_width); + break; + case eHT_CHANNEL_WIDTH_80MHZ: + chan = cds_freq_to_chan(chandef->chan->center_freq); + chandef->width = NL80211_CHAN_WIDTH_80; + + switch (cb_mode) { + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: + center_chan = chan + 2; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: + center_chan = chan + 6; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: + center_chan = chan - 2; + break; + case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: + center_chan = chan - 6; + break; + default: + center_chan = chan; + break; + } + + chandef->center_freq1 = cds_chan_to_freq(center_chan); + break; + case eHT_CHANNEL_WIDTH_160MHZ: + default: + /* Todo, please add related codes if support 160MHZ or others */ + hdd_err("unsupport ch_width %d", ch_width); + break; + } + +} +#else +static inline void +hdd_update_chandef(hdd_adapter_t *hostapd_adapter, + struct cfg80211_chan_def *chandef, + ePhyChanBondState cb_mode) +{ +} +#endif + /** * hdd_chan_change_notify() - Function to notify hostapd about channel change * @hostapd_adapter hostapd adapter @@ -689,6 +760,10 @@ CDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, cfg80211_chandef_create(&chandef, chan, channel_type); + if ((phy_mode == eCSR_DOT11_MODE_11ac) || + (phy_mode == eCSR_DOT11_MODE_11ac_ONLY)) + hdd_update_chandef(hostapd_adapter, &chandef, cb_mode); + cfg80211_ch_switch_notify(dev, &chandef); return CDF_STATUS_SUCCESS; -- cgit v1.2.3 From 9f79df4afdcc688412582fafb9ddcefdaaa527c2 Mon Sep 17 00:00:00 2001 From: Komal Seelam Date: Tue, 15 Dec 2015 11:05:18 +0530 Subject: qcacld-3.0: Fix Compilation error on WLAN_FEATURE_11W disabled eCSR_AUTH_TYPE_RSN_8021X_SHA256 is defined only when 11W feature is enabled. The code is using the identifier eCSR_AUTH_TYPE_RSN_8021X_SHA256 without conditional compilation. Access eCSR_AUTH_TYPE_RSN_8021X_SHA256 under 11W feature flag. Change-Id: I5e1e513c12cf526045991749a487ac89d1773659 CRs-Fixed: 947938 --- core/hdd/src/wlan_hdd_assoc.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index f21d96d2690e..7e211981946f 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3820,6 +3820,27 @@ hdd_indicate_ese_bcn_report_ind(const hdd_adapter_t *pAdapter, #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +/** + * hdd_is_8021x_sha256_auth_type() - check authentication type to 8021x_sha256 + * @pHddStaCtx: Station Context + * + * API to check if the connection authentication type is 8021x_sha256. + * + * Return: bool + */ +#ifdef WLAN_FEATURE_11W +static inline bool hdd_is_8021x_sha256_auth_type(hdd_station_ctx_t *pHddStaCtx) +{ + return eCSR_AUTH_TYPE_RSN_8021X_SHA256 == + pHddStaCtx->conn_info.authType; +} +#else +static inline bool hdd_is_8021x_sha256_auth_type(hdd_station_ctx_t *pHddStaCtx) +{ + return false; +} +#endif + /** * hdd_sme_roam_callback() - hdd sme roam callback * @pContext: pointer to adapter context @@ -4056,9 +4077,8 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, break; #endif case eCSR_ROAM_PMK_NOTIFY: - if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType || - eCSR_AUTH_TYPE_RSN_8021X_SHA256 == - pHddStaCtx->conn_info.authType) { + if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType + || hdd_is_8021x_sha256_auth_type(pHddStaCtx)) { /* notify the supplicant of a new candidate */ cdf_ret_status = wlan_hdd_cfg80211_pmksa_candidate_notify( -- cgit v1.2.3 From 32a4e14a7636eb19bb973a23fbdf4642a5be307c Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Wed, 27 Jan 2016 11:05:20 -0800 Subject: Release 5.0.0.159 Release 5.0.0.159 Change-Id: I3f104ce7093b6ba6d9a9bb166c519de998a8ac43 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 840f8fa6be8b..a1b577bb4c7a 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 158 +#define QWLAN_VERSION_BUILD 159 -#define QWLAN_VERSIONSTR "5.0.0.158" +#define QWLAN_VERSIONSTR "5.0.0.159" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3 From a7512da0885dbf2a1f9a4c042d65629c0d975b74 Mon Sep 17 00:00:00 2001 From: Sandeep Puligilla Date: Tue, 5 Jan 2016 12:18:02 -0800 Subject: qcacld-3.0: Add wma handler for vdev delete and peer delete responses - Add handler for the vdev delete and peer delete response at WMA. - As part of timeout handler, assert if the response is not received in 3 seconds. Change-Id: I7b20254013266414174f686e1f3918822adc65d8 CRs-fixed: 960173 --- .../utils/host_diag_log/inc/host_diag_core_event.h | 4 +- core/wma/inc/wma.h | 10 + core/wma/inc/wma_if.h | 10 + core/wma/inc/wma_internal.h | 6 + core/wma/src/wma_dev_if.c | 455 ++++++++++++++++++--- core/wma/src/wma_main.c | 16 +- 6 files changed, 431 insertions(+), 70 deletions(-) diff --git a/core/utils/host_diag_log/inc/host_diag_core_event.h b/core/utils/host_diag_log/inc/host_diag_core_event.h index 7962dda35245..623db35d7e3d 100644 --- a/core/utils/host_diag_log/inc/host_diag_core_event.h +++ b/core/utils/host_diag_log/inc/host_diag_core_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -332,6 +332,7 @@ enum wifi_connectivity_events { * @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_WMI_CMD_RSP: Firmware response * @WIFI_POWER_EVENT_WAKELOCK_MISC: Miscellaneous wakelocks * * Indicates the reason for which the wakelock was taken/released @@ -353,6 +354,7 @@ enum wake_lock_reason { WIFI_POWER_EVENT_WAKELOCK_PNO, WIFI_POWER_EVENT_WAKELOCK_DEL_STA, WIFI_POWER_EVENT_WAKELOCK_DFS, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP, WIFI_POWER_EVENT_WAKELOCK_MISC, }; diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 626df86d8ae4..f3b3b882b895 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -243,6 +243,11 @@ #define WMA_PEER_ASSOC_CNF_START 0x01 #define WMA_PEER_ASSOC_TIMEOUT (3000) /* 3 seconds */ +#define WMA_DELETE_STA_RSP_START 0x02 +#define WMA_DELETE_STA_TIMEOUT (6000) /* 6 seconds */ + +#define WMA_DEL_P2P_SELF_STA_RSP_START 0x03 + #define WMA_VDEV_START_REQUEST_TIMEOUT (3000) /* 3 seconds */ #define WMA_VDEV_STOP_REQUEST_TIMEOUT (3000) /* 3 seconds */ @@ -300,6 +305,7 @@ #define WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION (5 * 1000) /* in msec */ #endif #define WMA_BMISS_EVENT_WAKE_LOCK_DURATION (4 * 1000) /* in msec */ +#define WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION (3 * 1000) /* in msec */ #define WMA_TXMIC_LEN 8 #define WMA_RXMIC_LEN 8 @@ -1188,6 +1194,8 @@ struct wmi_init_cmd { * handle of other modules. * @saved_wmi_init_cmd: Saved WMI INIT command * @service_ready_ext_evt: Wait event for service ready ext + * @wmi_cmd_rsp_wake_lock: wmi command response wake lock + * @wmi_cmd_rsp_runtime_lock: wmi command response bus lock */ typedef struct { void *wmi_handle; @@ -1373,6 +1381,8 @@ typedef struct { CDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac, roam_offload_synch_ind *roam_synch_data, tpSirBssDescription bss_desc_ptr); + cdf_wake_lock_t wmi_cmd_rsp_wake_lock; + cdf_runtime_lock_t wmi_cmd_rsp_runtime_lock; } t_wma_handle, *tp_wma_handle; /** diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 3c1728b8c60f..1dab6fab4b65 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -1287,6 +1287,16 @@ struct del_sta_self_params { uint32_t status; }; +/** + * struct del_sta_self_rsp_params - Del Sta Self response params + * @self_sta_param: sta params + * @generate_rsp: generate response to upper layers + */ +struct del_sta_self_rsp_params { + struct del_sta_self_params *self_sta_param; + uint8_t generate_rsp; +}; + /** * struct tP2pPsParams - P2P powersave related params * @opp_ps: opportunistic power save diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index bf8b1dfafb84..d2788103f868 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1169,5 +1169,11 @@ CDF_STATUS wma_process_set_ie_info(tp_wma_handle wma, struct vdev_ie_info *ie_info); int wma_peer_assoc_conf_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +int wma_vdev_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); +int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len); +void wma_remove_req(tp_wma_handle wma, uint8_t vdev_id, + uint8_t type); #endif diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index fb57c04b6505..d5d0abf2344c 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -297,6 +297,9 @@ static int wma_unified_vdev_delete_send(wmi_unified_t wmi_handle, uint8_t if_id) * @vdev_id: vdev id * @type: request type * + * Find target request for given vdev id & type of request. + * Remove that request from active list. + * * Return: return target request if found or NULL. */ static struct wma_target_req *wma_find_req(tp_wma_handle wma, @@ -349,6 +352,68 @@ static struct wma_target_req *wma_find_req(tp_wma_handle wma, return req_msg; } +/** + * wma_find_remove_req_msgtype() - find and remove request for vdev id + * @wma: wma handle + * @vdev_id: vdev id + * @msg_type: message request type + * + * Find target request for given vdev id & sub type of request. + * Remove the same from active list. + * + * Return: Success if request found, failure other wise + */ +static struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma, + uint8_t vdev_id, uint32_t msg_type) +{ + struct wma_target_req *req_msg = NULL; + bool found = false; + cdf_list_node_t *node1 = NULL, *node2 = NULL; + CDF_STATUS status; + + cdf_spin_lock_bh(&wma->wma_hold_req_q_lock); + if (CDF_STATUS_SUCCESS != cdf_list_peek_front(&wma->wma_hold_req_queue, + &node2)) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGE(FL("unable to get msg node from request queue")); + return NULL; + } + + do { + node1 = node2; + req_msg = cdf_container_of(node1, struct wma_target_req, node); + if (req_msg->vdev_id != vdev_id) + continue; + if (req_msg->msg_type != msg_type) + continue; + + found = true; + status = cdf_list_remove_node(&wma->wma_hold_req_queue, node1); + if (CDF_STATUS_SUCCESS != status) { + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + WMA_LOGD(FL("Failed to remove request. vdev_id %d type %d"), + vdev_id, msg_type); + return NULL; + } + break; + } while (CDF_STATUS_SUCCESS == + cdf_list_peek_next(&wma->wma_hold_req_queue, node1, + &node2)); + + cdf_spin_unlock_bh(&wma->wma_hold_req_q_lock); + if (!found) { + WMA_LOGE(FL("target request not found for vdev_id %d type %d"), + vdev_id, msg_type); + return NULL; + } + + WMA_LOGD(FL("target request found for vdev id: %d type %d"), + vdev_id, msg_type); + + return req_msg; +} + + /** * wma_find_vdev_req() - find target request for vdev id * @wma: wma handle @@ -428,21 +493,24 @@ void wma_vdev_detach_callback(void *ctx) return; } param = (struct del_sta_self_params *) iface->del_staself_req; - WMA_LOGD("%s: sending eWNI_SME_DEL_STA_SELF_RSP for vdev %d", + WMA_LOGE("%s: sending eWNI_SME_DEL_STA_SELF_RSP for vdev %d", __func__, param->session_id); - - req_msg = wma_find_vdev_req(wma, param->session_id, - WMA_TARGET_REQ_TYPE_VDEV_DEL); - if (req_msg) { - WMA_LOGD("%s: Found vdev request for vdev id %d", - __func__, param->session_id); - cdf_mc_timer_stop(&req_msg->event_timeout); - cdf_mc_timer_destroy(&req_msg->event_timeout); - cdf_mem_free(req_msg); + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + req_msg = wma_find_vdev_req(wma, param->session_id, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (req_msg) { + WMA_LOGD("%s: Found vdev request for vdev id %d", + __func__, param->session_id); + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + } } if (iface->addBssStaContext) cdf_mem_free(iface->addBssStaContext); + #if defined WLAN_FEATURE_VOWIFI_11R if (iface->staKeyParams) cdf_mem_free(iface->staKeyParams); @@ -460,93 +528,127 @@ void wma_vdev_detach_callback(void *ctx) } } + /** - * wma_vdev_detach() - send vdev delete command to fw - * @wma_handle: wma handle - * @pdel_sta_self_req_param: del sta params - * @generateRsp: generate Response flag + * wma_self_peer_remove() - Self peer remove handler + * @wma: wma handle + * @del_sta_self_req_param: vdev id + * @generate_vdev_rsp: request type * - * Return: CDF status + * Return: success if peer delete command sent to firmware, else failure. */ -CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, - struct del_sta_self_params *pdel_sta_self_req_param, - uint8_t generateRsp) + +static CDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle, + struct del_sta_self_params *del_sta_self_req_param, + uint8_t generate_vdev_rsp) { - CDF_STATUS status = CDF_STATUS_SUCCESS; ol_txrx_peer_handle peer; ol_txrx_pdev_handle pdev; uint8_t peer_id; - uint8_t vdev_id = pdel_sta_self_req_param->session_id; - struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; - struct wma_target_req *msg; - cds_msg_t sme_msg = { 0 }; - - if ((iface->type == WMI_VDEV_TYPE_AP) && - (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + uint8_t vdev_id = del_sta_self_req_param->session_id; + struct wma_target_req *msg = NULL; + struct del_sta_self_rsp_params *sta_self_wmi_rsp; - WMA_LOGA("P2P Device: removing self peer %pM", - pdel_sta_self_req_param->self_mac_addr); + WMA_LOGE("P2P Device: removing self peer %pM", + del_sta_self_req_param->self_mac_addr); - pdev = cds_get_context(CDF_MODULE_ID_TXRX); - - if (NULL == pdev) { - WMA_LOGE("%s: Failed to get pdev", __func__); + pdev = cds_get_context(CDF_MODULE_ID_TXRX); + if (NULL == pdev) { + WMA_LOGE("%s: Failed to get pdev", __func__); return CDF_STATUS_E_FAULT; - } - - peer = ol_txrx_find_peer_by_addr(pdev, - pdel_sta_self_req_param->self_mac_addr, - &peer_id); - if (!peer) { - WMA_LOGE("%s Failed to find peer %pM", __func__, - pdel_sta_self_req_param->self_mac_addr); - } - wma_remove_peer(wma_handle, - pdel_sta_self_req_param->self_mac_addr, - vdev_id, peer, false); - } - if (cdf_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; } - if (!iface->handle) { - WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", - vdev_id); - cdf_mem_free(pdel_sta_self_req_param); - pdel_sta_self_req_param = NULL; - return status; + peer = ol_txrx_find_peer_by_addr(pdev, + del_sta_self_req_param->self_mac_addr, + &peer_id); + if (!peer) { + WMA_LOGE("%s Failed to find peer %pM", __func__, + del_sta_self_req_param->self_mac_addr); + return CDF_STATUS_SUCCESS; } + wma_remove_peer(wma_handle, + del_sta_self_req_param->self_mac_addr, + vdev_id, peer, false); + + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + sta_self_wmi_rsp = + cdf_mem_malloc(sizeof(struct del_sta_self_rsp_params)); + if (sta_self_wmi_rsp == NULL) { + WMA_LOGP(FL("Failed to allocate memory")); + return CDF_STATUS_E_NOMEM; + } + sta_self_wmi_rsp->self_sta_param = del_sta_self_req_param; + sta_self_wmi_rsp->generate_rsp = generate_vdev_rsp; + msg = wma_fill_hold_req(wma_handle, vdev_id, + WMA_DELETE_STA_REQ, + WMA_DEL_P2P_SELF_STA_RSP_START, + sta_self_wmi_rsp, + WMA_DELETE_STA_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to allocate request for vdev_id %d"), + vdev_id); + wma_remove_req(wma_handle, vdev_id, + WMA_DEL_P2P_SELF_STA_RSP_START); + return CDF_STATUS_E_FAILURE; + } + } + return CDF_STATUS_SUCCESS; +} +static CDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *del_sta_self_req_param, + uint8_t generate_rsp) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t vdev_id = del_sta_self_req_param->session_id; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + struct wma_target_req *msg = NULL; + cds_msg_t sme_msg = { 0 }; - /* 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."); + WMA_LOGE("Unable to remove an interface"); status = CDF_STATUS_E_FAILURE; goto out; } - WMA_LOGD("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); - if (!generateRsp) { + WMA_LOGE("vdev_id:%hu vdev_hdl:%p", vdev_id, iface->handle); + if (!generate_rsp) { WMA_LOGE("Call txrx detach w/o callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); goto out; } - iface->del_staself_req = pdel_sta_self_req_param; + iface->del_staself_req = del_sta_self_req_param; msg = wma_fill_vdev_req(wma_handle, vdev_id, WMA_DEL_STA_SELF_REQ, - WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 2000); + WMA_TARGET_REQ_TYPE_VDEV_DEL, iface, 6000); if (!msg) { WMA_LOGE("%s: Failed to fill vdev request for vdev_id %d", __func__, vdev_id); status = CDF_STATUS_E_NOMEM; goto out; } + + /* Acquire wake lock only when you expect a response from firmware */ + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + cdf_wake_lock_timeout_acquire( + &wma_handle->wmi_cmd_rsp_wake_lock, + WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_prevent_suspend( + wma_handle->wmi_cmd_rsp_runtime_lock); + } WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id); ol_txrx_vdev_detach(iface->handle, NULL, NULL); - wma_vdev_detach_callback(iface); + + /* + * send the response immediately if WMI_SERVICE_SYNC_DELETE_CMDS + * service is not supported by firmware + */ + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) + wma_vdev_detach_callback(iface); return status; out: if (iface->addBssStaContext) @@ -556,20 +658,67 @@ out: cdf_mem_free(iface->staKeyParams); #endif /* WLAN_FEATURE_VOWIFI_11R */ cdf_mem_zero(iface, sizeof(*iface)); - pdel_sta_self_req_param->status = status; - if (generateRsp) { + del_sta_self_req_param->status = status; + if (generate_rsp) { sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; - sme_msg.bodyptr = pdel_sta_self_req_param; + sme_msg.bodyptr = del_sta_self_req_param; sme_msg.bodyval = 0; status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg); if (!CDF_IS_STATUS_SUCCESS(status)) { - WMA_LOGE("Failed to post eWNI_SME_ADD_STA_SELF_RSP"); - cdf_mem_free(pdel_sta_self_req_param); + WMA_LOGE("Failed to post eWNI_SME_DEL_STA_SELF_RSP"); + cdf_mem_free(del_sta_self_req_param); } } return status; } +/** + * wma_vdev_detach() - send vdev delete command to fw + * @wma_handle: wma handle + * @pdel_sta_self_req_param: del sta params + * @generateRsp: generate Response flag + * + * Return: CDF status + */ +CDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, + struct del_sta_self_params *pdel_sta_self_req_param, + uint8_t generateRsp) +{ + CDF_STATUS status = CDF_STATUS_SUCCESS; + uint8_t vdev_id = pdel_sta_self_req_param->session_id; + struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + + if (cdf_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; + } + + if (!iface->handle) { + WMA_LOGE("handle of vdev_id %d is NULL vdev is already freed", + vdev_id); + cdf_mem_free(pdel_sta_self_req_param); + pdel_sta_self_req_param = NULL; + return status; + } + + /* P2P Device */ + if ((iface->type == WMI_VDEV_TYPE_AP) && + (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + wma_self_peer_remove(wma_handle, pdel_sta_self_req_param, + generateRsp); + if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) + status = wma_handle_vdev_detach(wma_handle, + pdel_sta_self_req_param, generateRsp); + } else { /* other than P2P */ + status = wma_handle_vdev_detach(wma_handle, + pdel_sta_self_req_param, generateRsp); + } + + return status; +} /** * wmi_unified_peer_delete_send() - send PEER delete command to fw @@ -2275,6 +2424,123 @@ free_req_msg: return status; } +/** + * wma_vdev_delete_handler() - vdev delete response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_vdev_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf; + wmi_vdev_delete_cmd_fixed_param *event; + struct wma_target_req *req_msg; + int status = 0; + + param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + event = (wmi_vdev_delete_cmd_fixed_param *)param_buf->fixed_param; + if (!event) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + WMA_LOGE("%s Vdev delete resp vdev id %d", __func__, event->vdev_id); + req_msg = wma_find_vdev_req(wma, event->vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_DEL); + if (!req_msg) { + WMA_LOGD(FL("Vdev delete resp is not handled! vdev id %d"), + event->vdev_id); + return -EINVAL; + } + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock); + /* Send response to upper layers */ + wma_vdev_detach_callback(req_msg->user_data); + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + cdf_mem_free(req_msg); + + return status; +} + +/** + * wma_peer_delete_handler() - peer delete response handler + * @handle: wma handle + * @cmd_param_info: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + WMI_PEER_DELETE_RESP_EVENTID_param_tlvs *param_buf; + wmi_peer_delete_cmd_fixed_param *event; + struct wma_target_req *req_msg; + tDeleteStaParams *del_sta; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + int status = 0; + + param_buf = (WMI_PEER_DELETE_RESP_EVENTID_param_tlvs *)cmd_param_info; + if (!param_buf) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + event = (wmi_peer_delete_cmd_fixed_param *)param_buf->fixed_param; + if (!event) { + WMA_LOGE("Invalid vdev delete event buffer"); + return -EINVAL; + } + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->peer_macaddr, macaddr); + WMA_LOGE(FL("Peer Delete Response, vdev %d Peer %pM"), + event->vdev_id, macaddr); + req_msg = wma_find_remove_req_msgtype(wma, event->vdev_id, + WMA_DELETE_STA_REQ); + if (!req_msg) { + WMA_LOGD("Peer Delete response is not handled"); + return -EINVAL; + } + + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock); + /* Cleanup timeout handler */ + cdf_mc_timer_stop(&req_msg->event_timeout); + cdf_mc_timer_destroy(&req_msg->event_timeout); + + if (req_msg->type == WMA_DELETE_STA_RSP_START) { + del_sta = req_msg->user_data; + if (del_sta->respReqd) { + WMA_LOGD(FL("Sending peer del rsp to umac")); + wma_send_msg(wma, WMA_DELETE_STA_RSP, + (void *)del_sta, CDF_STATUS_SUCCESS); + } + } else if (req_msg->type == WMA_DEL_P2P_SELF_STA_RSP_START) { + struct del_sta_self_rsp_params *data; + data = (struct del_sta_self_rsp_params *)req_msg->user_data; + WMA_LOGD(FL("Calling vdev detach handler")); + wma_handle_vdev_detach(wma, data->self_sta_param, + data->generate_rsp); + cdf_mem_free(data); + } + cdf_mem_free(req_msg); + return status; +} + + /** * wma_hold_req_timer() - wma hold request timeout function * @data: target request params @@ -2310,6 +2576,24 @@ void wma_hold_req_timer(void *data) WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"), params->staMac, params->status); wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)params, 0); + } else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) && + (tgt_req->type == WMA_DELETE_STA_RSP_START)) { + tpDeleteStaParams params = + (tpDeleteStaParams) tgt_req->user_data; + params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGE(FL("WMA_DEL_STA_REQ timed out")); + WMA_LOGP(FL("Sending del sta rsp to umac (mac:%pM, status:%d)"), + params->staMac, params->status); + /* + * Assert in development build only. + * Send response in production builds. + */ + CDF_ASSERT(0); + wma_send_msg(wma, WMA_DELETE_STA_RSP, (void *)params, 0); + } else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) && + (tgt_req->type == WMA_DEL_P2P_SELF_STA_RSP_START)) { + WMA_LOGA(FL("wma delete sta p2p request timed out")); + CDF_ASSERT(0); } free_tgt_req: cdf_mc_timer_destroy(&tgt_req->event_timeout); @@ -2342,6 +2626,7 @@ struct wma_target_req *wma_fill_hold_req(tp_wma_handle wma, } WMA_LOGE(FL("vdev_id %d msg %d type %d"), vdev_id, msg_type, type); + req->vdev_id = vdev_id; req->msg_type = msg_type; req->type = type; @@ -2532,7 +2817,15 @@ void wma_vdev_resp_timer(void *data) struct del_sta_self_params *params = (struct del_sta_self_params *) iface->del_staself_req; + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + cdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_allow_suspend( + wma->wmi_cmd_rsp_runtime_lock); + } params->status = CDF_STATUS_E_TIMEOUT; + WMA_LOGA("%s: WMA_DEL_STA_SELF_REQ timedout", __func__); sme_msg.type = eWNI_SME_DEL_STA_SELF_RSP; sme_msg.bodyptr = iface->del_staself_req; @@ -4056,6 +4349,7 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, { ol_txrx_pdev_handle pdev; struct ol_txrx_peer_t *peer; + struct wma_target_req *msg; pdev = cds_get_context(CDF_MODULE_ID_TXRX); @@ -4077,6 +4371,31 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma, false); del_sta->status = CDF_STATUS_SUCCESS; + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_SYNC_DELETE_CMDS)) { + msg = wma_fill_hold_req(wma, del_sta->smesessionId, + WMA_DELETE_STA_REQ, + WMA_DELETE_STA_RSP_START, del_sta, + WMA_DELETE_STA_TIMEOUT); + if (!msg) { + WMA_LOGP(FL("Failed to allocate request. vdev_id %d"), + del_sta->smesessionId); + wma_remove_req(wma, del_sta->smesessionId, + WMA_DELETE_STA_RSP_START); + del_sta->status = CDF_STATUS_E_NOMEM; + goto send_del_rsp; + } + /* + * Acquire wake lock and bus lock till + * firmware sends the response + */ + cdf_wake_lock_timeout_acquire(&wma->wmi_cmd_rsp_wake_lock, + WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + cdf_runtime_pm_prevent_suspend(wma->wmi_cmd_rsp_runtime_lock); + return; + } + send_del_rsp: if (del_sta->respReqd) { WMA_LOGD("%s: Sending del rsp to umac (status: %d)", diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 5ca415c0ccf0..a83f89558d03 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1937,14 +1937,26 @@ CDF_STATUS wma_open(void *cds_context, WMI_RSSI_BREACH_EVENTID, wma_rssi_breached_event_handler); + cdf_wake_lock_init(&wma_handle->wmi_cmd_rsp_wake_lock, + "wlan_fw_rsp_wakelock"); + wma_handle->wmi_cmd_rsp_runtime_lock = + cdf_runtime_lock_init("wlan_fw_rsp_runtime_lock"); + /* Register peer assoc conf event handler */ wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_PEER_ASSOC_CONF_EVENTID, wma_peer_assoc_conf_handler); - + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_DELETE_RESP_EVENTID, + wma_vdev_delete_handler); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PEER_DELETE_RESP_EVENTID, + wma_peer_delete_handler); return CDF_STATUS_SUCCESS; err_dbglog_init: + cdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); + cdf_runtime_lock_deinit(wma_handle->wmi_cmd_rsp_runtime_lock); cdf_spinlock_destroy(&wma_handle->vdev_respq_lock); cdf_spinlock_destroy(&wma_handle->wma_hold_req_q_lock); err_event_init: @@ -3094,6 +3106,8 @@ CDF_STATUS wma_close(void *cds_ctx) cdf_event_destroy(&wma_handle->recovery_event); wma_cleanup_vdev_resp(wma_handle); wma_cleanup_hold_req(wma_handle); + cdf_wake_lock_destroy(&wma_handle->wmi_cmd_rsp_wake_lock); + cdf_runtime_lock_deinit(wma_handle->wmi_cmd_rsp_runtime_lock); for (idx = 0; idx < wma_handle->num_mem_chunks; ++idx) { cdf_os_mem_free_consistent(wma_handle->cdf_dev, wma_handle->mem_chunks[idx].len, -- cgit v1.2.3 From 0219ae607ac51d3009808a4709cc5c07140586ac Mon Sep 17 00:00:00 2001 From: Satish Singh Date: Sat, 30 Jan 2016 00:19:00 -0800 Subject: Release 5.0.0.160 Release 5.0.0.160 Change-Id: Ie65b9fdb1412a6d205e4b96d9c60d7847b7a2485 CRs-Fixed: 688141 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index a1b577bb4c7a..916c01e6be27 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -42,8 +42,8 @@ #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 159 +#define QWLAN_VERSION_BUILD 160 -#define QWLAN_VERSIONSTR "5.0.0.159" +#define QWLAN_VERSIONSTR "5.0.0.160" #endif /* QWLAN_VERSION_H */ -- cgit v1.2.3